brcm2708: update linux 4.4 patches to latest version
[openwrt/openwrt.git] / target / linux / brcm2708 / patches-4.4 / 0282-drm-vc4-Add-support-for-YUV-planes.patch
1 From 64f2da0496d51f7260e18aeed6e72ed09fec7b00 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] 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