3ead02cbbf97ecc2a33808455a6190bf1ba16ac6
[oweals/openwrt.git] /
1 From 2a98dc34696c6510a49a684eb56d3a9c2a150571 Mon Sep 17 00:00:00 2001
2 From: Boris Brezillon <boris.brezillon@bootlin.com>
3 Date: Fri, 3 Aug 2018 11:22:29 +0200
4 Subject: [PATCH] drm/vc4: Use drm_atomic_helper_check_plane_state() to
5  simplify the logic
6
7 drm_atomic_helper_check_plane_state() takes care of checking the
8 scaling capabilities and calculating the clipped X/Y offsets for us.
9
10 Rely on this function instead of open-coding the logic.
11
12 Incidentally, it seems to fix a problem we had with negative X/Y
13 positioning of YUV planes.
14
15 Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
16 Reviewed-by: Eric Anholt <eric@anholt.net>
17 Link: https://patchwork.freedesktop.org/patch/msgid/20180803092231.26446-3-boris.brezillon@bootlin.com
18 ---
19  drivers/gpu/drm/vc4/vc4_plane.c | 103 ++++++++++++++++----------------
20  1 file changed, 52 insertions(+), 51 deletions(-)
21
22 --- a/drivers/gpu/drm/vc4/vc4_plane.c
23 +++ b/drivers/gpu/drm/vc4/vc4_plane.c
24 @@ -313,31 +313,59 @@ static int vc4_plane_setup_clipping_and_
25         u32 subpixel_src_mask = (1 << 16) - 1;
26         u32 format = fb->format->format;
27         int num_planes = fb->format->num_planes;
28 -       u32 h_subsample = 1;
29 -       u32 v_subsample = 1;
30 -       int ret;
31 -       int i;
32 +       int min_scale = 1, max_scale = INT_MAX;
33 +       struct drm_crtc_state *crtc_state;
34 +       u32 h_subsample, v_subsample;
35 +       int i, ret;
36 +
37 +       crtc_state = drm_atomic_get_existing_crtc_state(state->state,
38 +                                                       state->crtc);
39 +       if (!crtc_state) {
40 +               DRM_DEBUG_KMS("Invalid crtc state\n");
41 +               return -EINVAL;
42 +       }
43 +
44 +       /* No configuring scaling on the cursor plane, since it gets
45 +        * non-vblank-synced updates, and scaling requires LBM changes which
46 +        * have to be vblank-synced.
47 +        */
48 +       if (plane->type == DRM_PLANE_TYPE_CURSOR) {
49 +               min_scale = DRM_PLANE_HELPER_NO_SCALING;
50 +               max_scale = DRM_PLANE_HELPER_NO_SCALING;
51 +       } else {
52 +               min_scale = 1;
53 +               max_scale = INT_MAX;
54 +       }
55 +
56 +       ret = drm_atomic_helper_check_plane_state(state, crtc_state,
57 +                                                 min_scale, max_scale,
58 +                                                 true, true);
59 +       if (ret)
60 +               return ret;
61 +
62 +       h_subsample = drm_format_horz_chroma_subsampling(format);
63 +       v_subsample = drm_format_vert_chroma_subsampling(format);
64  
65         for (i = 0; i < num_planes; i++)
66                 vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
67  
68         /* We don't support subpixel source positioning for scaling. */
69 -       if ((state->src_x & subpixel_src_mask) ||
70 -           (state->src_y & subpixel_src_mask) ||
71 -           (state->src_w & subpixel_src_mask) ||
72 -           (state->src_h & subpixel_src_mask)) {
73 +       if ((state->src.x1 & subpixel_src_mask) ||
74 +           (state->src.x2 & subpixel_src_mask) ||
75 +           (state->src.y1 & subpixel_src_mask) ||
76 +           (state->src.y2 & subpixel_src_mask)) {
77                 return -EINVAL;
78         }
79  
80 -       vc4_state->src_x = state->src_x >> 16;
81 -       vc4_state->src_y = state->src_y >> 16;
82 -       vc4_state->src_w[0] = state->src_w >> 16;
83 -       vc4_state->src_h[0] = state->src_h >> 16;
84 -
85 -       vc4_state->crtc_x = state->crtc_x;
86 -       vc4_state->crtc_y = state->crtc_y;
87 -       vc4_state->crtc_w = state->crtc_w;
88 -       vc4_state->crtc_h = state->crtc_h;
89 +       vc4_state->src_x = state->src.x1 >> 16;
90 +       vc4_state->src_y = state->src.y1 >> 16;
91 +       vc4_state->src_w[0] = (state->src.x2 - state->src.x1) >> 16;
92 +       vc4_state->src_h[0] = (state->src.y2 - state->src.y1) >> 16;
93 +
94 +       vc4_state->crtc_x = state->dst.x1;
95 +       vc4_state->crtc_y = state->dst.y1;
96 +       vc4_state->crtc_w = state->dst.x2 - state->dst.x1;
97 +       vc4_state->crtc_h = state->dst.y2 - state->dst.y1;
98  
99         ret = vc4_plane_margins_adj(state);
100         if (ret)
101 @@ -354,8 +382,6 @@ static int vc4_plane_setup_clipping_and_
102         if (num_planes > 1) {
103                 vc4_state->is_yuv = true;
104  
105 -               h_subsample = drm_format_horz_chroma_subsampling(format);
106 -               v_subsample = drm_format_vert_chroma_subsampling(format);
107                 vc4_state->src_w[1] = vc4_state->src_w[0] / h_subsample;
108                 vc4_state->src_h[1] = vc4_state->src_h[0] / v_subsample;
109  
110 @@ -380,39 +406,14 @@ static int vc4_plane_setup_clipping_and_
111                 vc4_state->y_scaling[1] = VC4_SCALING_NONE;
112         }
113  
114 -       /* No configuring scaling on the cursor plane, since it gets
115 -          non-vblank-synced updates, and scaling requires requires
116 -          LBM changes which have to be vblank-synced.
117 -        */
118 -       if (plane->type == DRM_PLANE_TYPE_CURSOR && !vc4_state->is_unity)
119 -               return -EINVAL;
120 -
121 -       /* Clamp the on-screen start x/y to 0.  The hardware doesn't
122 -        * support negative y, and negative x wastes bandwidth.
123 -        */
124 -       if (vc4_state->crtc_x < 0) {
125 -               for (i = 0; i < num_planes; i++) {
126 -                       u32 cpp = fb->format->cpp[i];
127 -                       u32 subs = ((i == 0) ? 1 : h_subsample);
128 -
129 -                       vc4_state->offsets[i] += (cpp *
130 -                                                 (-vc4_state->crtc_x) / subs);
131 -               }
132 -               vc4_state->src_w[0] += vc4_state->crtc_x;
133 -               vc4_state->src_w[1] += vc4_state->crtc_x / h_subsample;
134 -               vc4_state->crtc_x = 0;
135 -       }
136 -
137 -       if (vc4_state->crtc_y < 0) {
138 -               for (i = 0; i < num_planes; i++) {
139 -                       u32 subs = ((i == 0) ? 1 : v_subsample);
140 -
141 -                       vc4_state->offsets[i] += (fb->pitches[i] *
142 -                                                 (-vc4_state->crtc_y) / subs);
143 -               }
144 -               vc4_state->src_h[0] += vc4_state->crtc_y;
145 -               vc4_state->src_h[1] += vc4_state->crtc_y / v_subsample;
146 -               vc4_state->crtc_y = 0;
147 +       /* Adjust the base pointer to the first pixel to be scanned out. */
148 +       for (i = 0; i < num_planes; i++) {
149 +               vc4_state->offsets[i] += (vc4_state->src_y /
150 +                                         (i ? v_subsample : 1)) *
151 +                                        fb->pitches[i];
152 +               vc4_state->offsets[i] += (vc4_state->src_x /
153 +                                         (i ? h_subsample : 1)) *
154 +                                        fb->format->cpp[i];
155         }
156  
157         return 0;