brcm2708: update linux 4.4 patches to latest version
[librecmc/librecmc.git] / target / linux / brcm2708 / patches-4.4 / 0286-drm-vc4-Add-support-for-YUV-planes.patch
1 From 59b40e05378ba51d3e5355f8860fca1341edf0c0 Mon Sep 17 00:00:00 2001
2 From: Eric Anholt <eric@anholt.net>
3 Date: Wed, 30 Dec 2015 12:25:44 -0800
4 Subject: [PATCH 286/304] drm/vc4: Add support for YUV planes.
5
6 This supports 420 and 422 subsampling with 2 or 3 planes, tested with
7 modetest.  It doesn't set up chroma subsampling position (which it
8 appears KMS doesn't deal with yet).
9
10 The LBM memory is overallocated in many cases, but apparently the docs
11 aren't quite correct and I'll probably need to look at the hardware
12 source to really figure it out.
13
14 Signed-off-by: Eric Anholt <eric@anholt.net>
15 (cherry picked from commit fc04023fafecf19ebd09278d8d67dc5ed1f68b46)
16 ---
17  drivers/gpu/drm/vc4/vc4_plane.c | 256 +++++++++++++++++++++++++++++++---------
18  drivers/gpu/drm/vc4/vc4_regs.h  |  56 ++++++++-
19  2 files changed, 253 insertions(+), 59 deletions(-)
20
21 --- a/drivers/gpu/drm/vc4/vc4_plane.c
22 +++ b/drivers/gpu/drm/vc4/vc4_plane.c
23 @@ -54,15 +54,19 @@ struct vc4_plane_state {
24         /* Clipped coordinates of the plane on the display. */
25         int crtc_x, crtc_y, crtc_w, crtc_h;
26         /* Clipped area being scanned from in the FB. */
27 -       u32 src_x, src_y, src_w, src_h;
28 +       u32 src_x, src_y;
29  
30 -       enum vc4_scaling_mode x_scaling, y_scaling;
31 +       u32 src_w[2], src_h[2];
32 +
33 +       /* Scaling selection for the RGB/Y plane and the Cb/Cr planes. */
34 +       enum vc4_scaling_mode x_scaling[2], y_scaling[2];
35         bool is_unity;
36 +       bool is_yuv;
37  
38         /* Offset to start scanning out from the start of the plane's
39          * BO.
40          */
41 -       u32 offset;
42 +       u32 offsets[3];
43  
44         /* Our allocation in LBM for temporary storage during scaling. */
45         struct drm_mm_node lbm;
46 @@ -79,6 +83,7 @@ static const struct hvs_format {
47         u32 hvs; /* HVS_FORMAT_* */
48         u32 pixel_order;
49         bool has_alpha;
50 +       bool flip_cbcr;
51  } hvs_formats[] = {
52         {
53                 .drm = DRM_FORMAT_XRGB8888, .hvs = HVS_PIXEL_FORMAT_RGBA8888,
54 @@ -104,6 +109,32 @@ static const struct hvs_format {
55                 .drm = DRM_FORMAT_XRGB1555, .hvs = HVS_PIXEL_FORMAT_RGBA5551,
56                 .pixel_order = HVS_PIXEL_ORDER_ABGR, .has_alpha = false,
57         },
58 +       {
59 +               .drm = DRM_FORMAT_YUV422,
60 +               .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
61 +       },
62 +       {
63 +               .drm = DRM_FORMAT_YVU422,
64 +               .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE,
65 +               .flip_cbcr = true,
66 +       },
67 +       {
68 +               .drm = DRM_FORMAT_YUV420,
69 +               .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
70 +       },
71 +       {
72 +               .drm = DRM_FORMAT_YVU420,
73 +               .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE,
74 +               .flip_cbcr = true,
75 +       },
76 +       {
77 +               .drm = DRM_FORMAT_NV12,
78 +               .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE,
79 +       },
80 +       {
81 +               .drm = DRM_FORMAT_NV16,
82 +               .hvs = HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE,
83 +       },
84  };
85  
86  static const struct hvs_format *vc4_get_hvs_format(u32 drm_format)
87 @@ -219,11 +250,11 @@ static void vc4_dlist_write(struct vc4_p
88   *
89   * This is a replication of a table from the spec.
90   */
91 -static u32 vc4_get_scl_field(struct drm_plane_state *state)
92 +static u32 vc4_get_scl_field(struct drm_plane_state *state, int plane)
93  {
94         struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
95  
96 -       switch (vc4_state->x_scaling << 2 | vc4_state->y_scaling) {
97 +       switch (vc4_state->x_scaling[plane] << 2 | vc4_state->y_scaling[plane]) {
98         case VC4_SCALING_PPF << 2 | VC4_SCALING_PPF:
99                 return SCALER_CTL0_SCL_H_PPF_V_PPF;
100         case VC4_SCALING_TPZ << 2 | VC4_SCALING_PPF:
101 @@ -254,9 +285,16 @@ static int vc4_plane_setup_clipping_and_
102         struct drm_plane *plane = state->plane;
103         struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
104         struct drm_framebuffer *fb = state->fb;
105 +       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
106         u32 subpixel_src_mask = (1 << 16) - 1;
107 +       u32 format = fb->pixel_format;
108 +       int num_planes = drm_format_num_planes(format);
109 +       u32 h_subsample = 1;
110 +       u32 v_subsample = 1;
111 +       int i;
112  
113 -       vc4_state->offset = fb->offsets[0];
114 +       for (i = 0; i < num_planes; i++)
115 +               vc4_state->offsets[i] = bo->paddr + fb->offsets[i];
116  
117         /* We don't support subpixel source positioning for scaling. */
118         if ((state->src_x & subpixel_src_mask) ||
119 @@ -268,20 +306,48 @@ static int vc4_plane_setup_clipping_and_
120  
121         vc4_state->src_x = state->src_x >> 16;
122         vc4_state->src_y = state->src_y >> 16;
123 -       vc4_state->src_w = state->src_w >> 16;
124 -       vc4_state->src_h = state->src_h >> 16;
125 +       vc4_state->src_w[0] = state->src_w >> 16;
126 +       vc4_state->src_h[0] = state->src_h >> 16;
127  
128         vc4_state->crtc_x = state->crtc_x;
129         vc4_state->crtc_y = state->crtc_y;
130         vc4_state->crtc_w = state->crtc_w;
131         vc4_state->crtc_h = state->crtc_h;
132  
133 -       vc4_state->x_scaling = vc4_get_scaling_mode(vc4_state->src_w,
134 -                                                   vc4_state->crtc_w);
135 -       vc4_state->y_scaling = vc4_get_scaling_mode(vc4_state->src_h,
136 -                                                   vc4_state->crtc_h);
137 -       vc4_state->is_unity = (vc4_state->x_scaling == VC4_SCALING_NONE &&
138 -                              vc4_state->y_scaling == VC4_SCALING_NONE);
139 +       vc4_state->x_scaling[0] = vc4_get_scaling_mode(vc4_state->src_w[0],
140 +                                                      vc4_state->crtc_w);
141 +       vc4_state->y_scaling[0] = vc4_get_scaling_mode(vc4_state->src_h[0],
142 +                                                      vc4_state->crtc_h);
143 +
144 +       if (num_planes > 1) {
145 +               vc4_state->is_yuv = true;
146 +
147 +               h_subsample = drm_format_horz_chroma_subsampling(format);
148 +               v_subsample = drm_format_vert_chroma_subsampling(format);
149 +               vc4_state->src_w[1] = vc4_state->src_w[0] / h_subsample;
150 +               vc4_state->src_h[1] = vc4_state->src_h[0] / v_subsample;
151 +
152 +               vc4_state->x_scaling[1] =
153 +                       vc4_get_scaling_mode(vc4_state->src_w[1],
154 +                                            vc4_state->crtc_w);
155 +               vc4_state->y_scaling[1] =
156 +                       vc4_get_scaling_mode(vc4_state->src_h[1],
157 +                                            vc4_state->crtc_h);
158 +
159 +               /* YUV conversion requires that scaling be enabled,
160 +                * even on a plane that's otherwise 1:1.  Choose TPZ
161 +                * for simplicity.
162 +                */
163 +               if (vc4_state->x_scaling[0] == VC4_SCALING_NONE)
164 +                       vc4_state->x_scaling[0] = VC4_SCALING_TPZ;
165 +               if (vc4_state->y_scaling[0] == VC4_SCALING_NONE)
166 +                       vc4_state->y_scaling[0] = VC4_SCALING_TPZ;
167 +       }
168 +
169 +       vc4_state->is_unity = (vc4_state->x_scaling[0] == VC4_SCALING_NONE &&
170 +                              vc4_state->y_scaling[0] == VC4_SCALING_NONE &&
171 +                              vc4_state->x_scaling[1] == VC4_SCALING_NONE &&
172 +                              vc4_state->y_scaling[1] == VC4_SCALING_NONE);
173  
174         /* No configuring scaling on the cursor plane, since it gets
175            non-vblank-synced updates, and scaling requires requires
176 @@ -294,16 +360,27 @@ static int vc4_plane_setup_clipping_and_
177          * support negative y, and negative x wastes bandwidth.
178          */
179         if (vc4_state->crtc_x < 0) {
180 -               vc4_state->offset += (drm_format_plane_cpp(fb->pixel_format,
181 -                                                          0) *
182 -                                     -vc4_state->crtc_x);
183 -               vc4_state->src_w += vc4_state->crtc_x;
184 +               for (i = 0; i < num_planes; i++) {
185 +                       u32 cpp = drm_format_plane_cpp(fb->pixel_format, i);
186 +                       u32 subs = ((i == 0) ? 1 : h_subsample);
187 +
188 +                       vc4_state->offsets[i] += (cpp *
189 +                                                 (-vc4_state->crtc_x) / subs);
190 +               }
191 +               vc4_state->src_w[0] += vc4_state->crtc_x;
192 +               vc4_state->src_w[1] += vc4_state->crtc_x / h_subsample;
193                 vc4_state->crtc_x = 0;
194         }
195  
196         if (vc4_state->crtc_y < 0) {
197 -               vc4_state->offset += fb->pitches[0] * -vc4_state->crtc_y;
198 -               vc4_state->src_h += vc4_state->crtc_y;
199 +               for (i = 0; i < num_planes; i++) {
200 +                       u32 subs = ((i == 0) ? 1 : v_subsample);
201 +
202 +                       vc4_state->offsets[i] += (fb->pitches[i] *
203 +                                                 (-vc4_state->crtc_y) / subs);
204 +               }
205 +               vc4_state->src_h[0] += vc4_state->crtc_y;
206 +               vc4_state->src_h[1] += vc4_state->crtc_y / v_subsample;
207                 vc4_state->crtc_y = 0;
208         }
209  
210 @@ -344,15 +421,23 @@ static u32 vc4_lbm_size(struct drm_plane
211         /* This is the worst case number.  One of the two sizes will
212          * be used depending on the scaling configuration.
213          */
214 -       u32 pix_per_line = max(vc4_state->src_w, (u32)vc4_state->crtc_w);
215 +       u32 pix_per_line = max(vc4_state->src_w[0], (u32)vc4_state->crtc_w);
216         u32 lbm;
217  
218 -       if (vc4_state->is_unity)
219 -               return 0;
220 -       else if (vc4_state->y_scaling == VC4_SCALING_TPZ)
221 -               lbm = pix_per_line * 8;
222 -       else {
223 -               /* In special cases, this multiplier might be 12. */
224 +       if (!vc4_state->is_yuv) {
225 +               if (vc4_state->is_unity)
226 +                       return 0;
227 +               else if (vc4_state->y_scaling[0] == VC4_SCALING_TPZ)
228 +                       lbm = pix_per_line * 8;
229 +               else {
230 +                       /* In special cases, this multiplier might be 12. */
231 +                       lbm = pix_per_line * 16;
232 +               }
233 +       } else {
234 +               /* There are cases for this going down to a multiplier
235 +                * of 2, but according to the firmware source, the
236 +                * table in the docs is somewhat wrong.
237 +                */
238                 lbm = pix_per_line * 16;
239         }
240  
241 @@ -361,33 +446,34 @@ static u32 vc4_lbm_size(struct drm_plane
242         return lbm;
243  }
244  
245 -static void vc4_write_scaling_parameters(struct drm_plane_state *state)
246 +static void vc4_write_scaling_parameters(struct drm_plane_state *state,
247 +                                        int channel)
248  {
249         struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
250  
251         /* Ch0 H-PPF Word 0: Scaling Parameters */
252 -       if (vc4_state->x_scaling == VC4_SCALING_PPF) {
253 +       if (vc4_state->x_scaling[channel] == VC4_SCALING_PPF) {
254                 vc4_write_ppf(vc4_state,
255 -                             vc4_state->src_w, vc4_state->crtc_w);
256 +                             vc4_state->src_w[channel], vc4_state->crtc_w);
257         }
258  
259         /* Ch0 V-PPF Words 0-1: Scaling Parameters, Context */
260 -       if (vc4_state->y_scaling == VC4_SCALING_PPF) {
261 +       if (vc4_state->y_scaling[channel] == VC4_SCALING_PPF) {
262                 vc4_write_ppf(vc4_state,
263 -                             vc4_state->src_h, vc4_state->crtc_h);
264 +                             vc4_state->src_h[channel], vc4_state->crtc_h);
265                 vc4_dlist_write(vc4_state, 0xc0c0c0c0);
266         }
267  
268         /* Ch0 H-TPZ Words 0-1: Scaling Parameters, Recip */
269 -       if (vc4_state->x_scaling == VC4_SCALING_TPZ) {
270 +       if (vc4_state->x_scaling[channel] == VC4_SCALING_TPZ) {
271                 vc4_write_tpz(vc4_state,
272 -                             vc4_state->src_w, vc4_state->crtc_w);
273 +                             vc4_state->src_w[channel], vc4_state->crtc_w);
274         }
275  
276         /* Ch0 V-TPZ Words 0-2: Scaling Parameters, Recip, Context */
277 -       if (vc4_state->y_scaling == VC4_SCALING_TPZ) {
278 +       if (vc4_state->y_scaling[channel] == VC4_SCALING_TPZ) {
279                 vc4_write_tpz(vc4_state,
280 -                             vc4_state->src_h, vc4_state->crtc_h);
281 +                             vc4_state->src_h[channel], vc4_state->crtc_h);
282                 vc4_dlist_write(vc4_state, 0xc0c0c0c0);
283         }
284  }
285 @@ -401,13 +487,13 @@ static int vc4_plane_mode_set(struct drm
286         struct vc4_dev *vc4 = to_vc4_dev(plane->dev);
287         struct vc4_plane_state *vc4_state = to_vc4_plane_state(state);
288         struct drm_framebuffer *fb = state->fb;
289 -       struct drm_gem_cma_object *bo = drm_fb_cma_get_gem_obj(fb, 0);
290         u32 ctl0_offset = vc4_state->dlist_count;
291         const struct hvs_format *format = vc4_get_hvs_format(fb->pixel_format);
292 -       u32 scl;
293 +       int num_planes = drm_format_num_planes(format->drm);
294 +       u32 scl0, scl1;
295         u32 lbm_size;
296         unsigned long irqflags;
297 -       int ret;
298 +       int ret, i;
299  
300         ret = vc4_plane_setup_clipping_and_scaling(state);
301         if (ret)
302 @@ -432,7 +518,19 @@ static int vc4_plane_mode_set(struct drm
303         if (ret)
304                 return ret;
305  
306 -       scl = vc4_get_scl_field(state);
307 +       /* SCL1 is used for Cb/Cr scaling of planar formats.  For RGB
308 +        * and 4:4:4, scl1 should be set to scl0 so both channels of
309 +        * the scaler do the same thing.  For YUV, the Y plane needs
310 +        * to be put in channel 1 and Cb/Cr in channel 0, so we swap
311 +        * the scl fields here.
312 +        */
313 +       if (num_planes == 1) {
314 +               scl0 = vc4_get_scl_field(state, 1);
315 +               scl1 = scl0;
316 +       } else {
317 +               scl0 = vc4_get_scl_field(state, 1);
318 +               scl1 = vc4_get_scl_field(state, 0);
319 +       }
320  
321         /* Control word */
322         vc4_dlist_write(vc4_state,
323 @@ -440,8 +538,8 @@ static int vc4_plane_mode_set(struct drm
324                         (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
325                         (format->hvs << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
326                         (vc4_state->is_unity ? SCALER_CTL0_UNITY : 0) |
327 -                       VC4_SET_FIELD(scl, SCALER_CTL0_SCL0) |
328 -                       VC4_SET_FIELD(scl, SCALER_CTL0_SCL1));
329 +                       VC4_SET_FIELD(scl0, SCALER_CTL0_SCL0) |
330 +                       VC4_SET_FIELD(scl1, SCALER_CTL0_SCL1));
331  
332         /* Position Word 0: Image Positions and Alpha Value */
333         vc4_state->pos0_offset = vc4_state->dlist_count;
334 @@ -466,35 +564,68 @@ static int vc4_plane_mode_set(struct drm
335                                       SCALER_POS2_ALPHA_MODE_PIPELINE :
336                                       SCALER_POS2_ALPHA_MODE_FIXED,
337                                       SCALER_POS2_ALPHA_MODE) |
338 -                       VC4_SET_FIELD(vc4_state->src_w, SCALER_POS2_WIDTH) |
339 -                       VC4_SET_FIELD(vc4_state->src_h, SCALER_POS2_HEIGHT));
340 +                       VC4_SET_FIELD(vc4_state->src_w[0], SCALER_POS2_WIDTH) |
341 +                       VC4_SET_FIELD(vc4_state->src_h[0], SCALER_POS2_HEIGHT));
342  
343         /* Position Word 3: Context.  Written by the HVS. */
344         vc4_dlist_write(vc4_state, 0xc0c0c0c0);
345  
346 -       /* Pointer Word 0: RGB / Y Pointer */
347 +
348 +       /* Pointer Word 0/1/2: RGB / Y / Cb / Cr Pointers
349 +        *
350 +        * The pointers may be any byte address.
351 +        */
352         vc4_state->ptr0_offset = vc4_state->dlist_count;
353 -       vc4_dlist_write(vc4_state, bo->paddr + vc4_state->offset);
354 +       if (!format->flip_cbcr) {
355 +               for (i = 0; i < num_planes; i++)
356 +                       vc4_dlist_write(vc4_state, vc4_state->offsets[i]);
357 +       } else {
358 +               WARN_ON_ONCE(num_planes != 3);
359 +               vc4_dlist_write(vc4_state, vc4_state->offsets[0]);
360 +               vc4_dlist_write(vc4_state, vc4_state->offsets[2]);
361 +               vc4_dlist_write(vc4_state, vc4_state->offsets[1]);
362 +       }
363  
364 -       /* Pointer Context Word 0: Written by the HVS */
365 -       vc4_dlist_write(vc4_state, 0xc0c0c0c0);
366 +       /* Pointer Context Word 0/1/2: Written by the HVS */
367 +       for (i = 0; i < num_planes; i++)
368 +               vc4_dlist_write(vc4_state, 0xc0c0c0c0);
369  
370 -       /* Pitch word 0: Pointer 0 Pitch */
371 -       vc4_dlist_write(vc4_state,
372 -                       VC4_SET_FIELD(fb->pitches[0], SCALER_SRC_PITCH));
373 +       /* Pitch word 0/1/2 */
374 +       for (i = 0; i < num_planes; i++) {
375 +               vc4_dlist_write(vc4_state,
376 +                               VC4_SET_FIELD(fb->pitches[i], SCALER_SRC_PITCH));
377 +       }
378 +
379 +       /* Colorspace conversion words */
380 +       if (vc4_state->is_yuv) {
381 +               vc4_dlist_write(vc4_state, SCALER_CSC0_ITR_R_601_5);
382 +               vc4_dlist_write(vc4_state, SCALER_CSC1_ITR_R_601_5);
383 +               vc4_dlist_write(vc4_state, SCALER_CSC2_ITR_R_601_5);
384 +       }
385  
386         if (!vc4_state->is_unity) {
387                 /* LBM Base Address. */
388 -               if (vc4_state->y_scaling != VC4_SCALING_NONE)
389 +               if (vc4_state->y_scaling[0] != VC4_SCALING_NONE ||
390 +                   vc4_state->y_scaling[1] != VC4_SCALING_NONE) {
391                         vc4_dlist_write(vc4_state, vc4_state->lbm.start);
392 +               }
393  
394 -               vc4_write_scaling_parameters(state);
395 +               if (num_planes > 1) {
396 +                       /* Emit Cb/Cr as channel 0 and Y as channel
397 +                        * 1. This matches how we set up scl0/scl1
398 +                        * above.
399 +                        */
400 +                       vc4_write_scaling_parameters(state, 1);
401 +               }
402 +               vc4_write_scaling_parameters(state, 0);
403  
404                 /* If any PPF setup was done, then all the kernel
405                  * pointers get uploaded.
406                  */
407 -               if (vc4_state->x_scaling == VC4_SCALING_PPF ||
408 -                   vc4_state->y_scaling == VC4_SCALING_PPF) {
409 +               if (vc4_state->x_scaling[0] == VC4_SCALING_PPF ||
410 +                   vc4_state->y_scaling[0] == VC4_SCALING_PPF ||
411 +                   vc4_state->x_scaling[1] == VC4_SCALING_PPF ||
412 +                   vc4_state->y_scaling[1] == VC4_SCALING_PPF) {
413                         u32 kernel = VC4_SET_FIELD(vc4->hvs->mitchell_netravali_filter.start,
414                                                    SCALER_PPF_KERNEL_OFFSET);
415  
416 @@ -698,6 +829,7 @@ struct drm_plane *vc4_plane_init(struct
417         struct drm_plane *plane = NULL;
418         struct vc4_plane *vc4_plane;
419         u32 formats[ARRAY_SIZE(hvs_formats)];
420 +       u32 num_formats = 0;
421         int ret = 0;
422         unsigned i;
423  
424 @@ -708,12 +840,20 @@ struct drm_plane *vc4_plane_init(struct
425                 goto fail;
426         }
427  
428 -       for (i = 0; i < ARRAY_SIZE(hvs_formats); i++)
429 -               formats[i] = hvs_formats[i].drm;
430 +       for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
431 +               /* Don't allow YUV in cursor planes, since that means
432 +                * tuning on the scaler, which we don't allow for the
433 +                * cursor.
434 +                */
435 +               if (type != DRM_PLANE_TYPE_CURSOR ||
436 +                   hvs_formats[i].hvs < HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE) {
437 +                       formats[num_formats++] = hvs_formats[i].drm;
438 +               }
439 +       }
440         plane = &vc4_plane->base;
441         ret = drm_universal_plane_init(dev, plane, 0xff,
442                                        &vc4_plane_funcs,
443 -                                      formats, ARRAY_SIZE(formats),
444 +                                      formats, num_formats,
445                                        type);
446  
447         drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
448 --- a/drivers/gpu/drm/vc4/vc4_regs.h
449 +++ b/drivers/gpu/drm/vc4/vc4_regs.h
450 @@ -503,7 +503,12 @@ enum hvs_pixel_format {
451         HVS_PIXEL_FORMAT_RGB888 = 5,
452         HVS_PIXEL_FORMAT_RGBA6666 = 6,
453         /* 32bpp */
454 -       HVS_PIXEL_FORMAT_RGBA8888 = 7
455 +       HVS_PIXEL_FORMAT_RGBA8888 = 7,
456 +
457 +       HVS_PIXEL_FORMAT_YCBCR_YUV420_3PLANE = 8,
458 +       HVS_PIXEL_FORMAT_YCBCR_YUV420_2PLANE = 9,
459 +       HVS_PIXEL_FORMAT_YCBCR_YUV422_3PLANE = 10,
460 +       HVS_PIXEL_FORMAT_YCBCR_YUV422_2PLANE = 11,
461  };
462  
463  /* Note: the LSB is the rightmost character shown.  Only valid for
464 @@ -585,6 +590,55 @@ enum hvs_pixel_format {
465  #define SCALER_POS2_WIDTH_MASK                 VC4_MASK(11, 0)
466  #define SCALER_POS2_WIDTH_SHIFT                        0
467  
468 +/* Color Space Conversion words.  Some values are S2.8 signed
469 + * integers, except that the 2 integer bits map as {0x0: 0, 0x1: 1,
470 + * 0x2: 2, 0x3: -1}
471 + */
472 +/* bottom 8 bits of S2.8 contribution of Cr to Blue */
473 +#define SCALER_CSC0_COEF_CR_BLU_MASK           VC4_MASK(31, 24)
474 +#define SCALER_CSC0_COEF_CR_BLU_SHIFT          24
475 +/* Signed offset to apply to Y before CSC. (Y' = Y + YY_OFS) */
476 +#define SCALER_CSC0_COEF_YY_OFS_MASK           VC4_MASK(23, 16)
477 +#define SCALER_CSC0_COEF_YY_OFS_SHIFT          16
478 +/* Signed offset to apply to CB before CSC (Cb' = Cb - 128 + CB_OFS). */
479 +#define SCALER_CSC0_COEF_CB_OFS_MASK           VC4_MASK(15, 8)
480 +#define SCALER_CSC0_COEF_CB_OFS_SHIFT          8
481 +/* Signed offset to apply to CB before CSC (Cr' = Cr - 128 + CR_OFS). */
482 +#define SCALER_CSC0_COEF_CR_OFS_MASK           VC4_MASK(7, 0)
483 +#define SCALER_CSC0_COEF_CR_OFS_SHIFT          0
484 +#define SCALER_CSC0_ITR_R_601_5                        0x00f00000
485 +#define SCALER_CSC0_ITR_R_709_3                        0x00f00000
486 +#define SCALER_CSC0_JPEG_JFIF                  0x00000000
487 +
488 +/* S2.8 contribution of Cb to Green */
489 +#define SCALER_CSC1_COEF_CB_GRN_MASK           VC4_MASK(31, 22)
490 +#define SCALER_CSC1_COEF_CB_GRN_SHIFT          22
491 +/* S2.8 contribution of Cr to Green */
492 +#define SCALER_CSC1_COEF_CR_GRN_MASK           VC4_MASK(21, 12)
493 +#define SCALER_CSC1_COEF_CR_GRN_SHIFT          12
494 +/* S2.8 contribution of Y to all of RGB */
495 +#define SCALER_CSC1_COEF_YY_ALL_MASK           VC4_MASK(11, 2)
496 +#define SCALER_CSC1_COEF_YY_ALL_SHIFT          2
497 +/* top 2 bits of S2.8 contribution of Cr to Blue */
498 +#define SCALER_CSC1_COEF_CR_BLU_MASK           VC4_MASK(1, 0)
499 +#define SCALER_CSC1_COEF_CR_BLU_SHIFT          0
500 +#define SCALER_CSC1_ITR_R_601_5                        0xe73304a8
501 +#define SCALER_CSC1_ITR_R_709_3                        0xf2b784a8
502 +#define SCALER_CSC1_JPEG_JFIF                  0xea34a400
503 +
504 +/* S2.8 contribution of Cb to Red */
505 +#define SCALER_CSC2_COEF_CB_RED_MASK           VC4_MASK(29, 20)
506 +#define SCALER_CSC2_COEF_CB_RED_SHIFT          20
507 +/* S2.8 contribution of Cr to Red */
508 +#define SCALER_CSC2_COEF_CR_RED_MASK           VC4_MASK(19, 10)
509 +#define SCALER_CSC2_COEF_CR_RED_SHIFT          10
510 +/* S2.8 contribution of Cb to Blue */
511 +#define SCALER_CSC2_COEF_CB_BLU_MASK           VC4_MASK(19, 10)
512 +#define SCALER_CSC2_COEF_CB_BLU_SHIFT          10
513 +#define SCALER_CSC2_ITR_R_601_5                        0x00066204
514 +#define SCALER_CSC2_ITR_R_709_3                        0x00072a1c
515 +#define SCALER_CSC2_JPEG_JFIF                  0x000599c5
516 +
517  #define SCALER_TPZ0_VERT_RECALC                        BIT(31)
518  #define SCALER_TPZ0_SCALE_MASK                 VC4_MASK(28, 8)
519  #define SCALER_TPZ0_SCALE_SHIFT                        8