1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * (C) Copyright 2022 Rockchip Electronics Co., Ltd
4 */
5
6 #include <common.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <i2c.h>
10 #include <linux/iopoll.h>
11
12 #include "rk628.h"
13 #include "rk628_cru.h"
14 #include "rk628_post_process.h"
15
16 #define PQ_CSC_HUE_TABLE_NUM 256
17 #define PQ_CSC_MODE_COEF_COMMENT_LEN 32
18 #define PQ_CSC_SIMPLE_MAT_PARAM_FIX_BIT_WIDTH 10
19 #define PQ_CSC_SIMPLE_MAT_PARAM_FIX_NUM (1 << PQ_CSC_SIMPLE_MAT_PARAM_FIX_BIT_WIDTH)
20
21 #define PQ_CALC_ENHANCE_BIT 6
22 /* csc convert coef fixed-point num bit width */
23 #define PQ_CSC_PARAM_FIX_BIT_WIDTH 10
24 /* csc convert coef half fixed-point num bit width */
25 #define PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH (PQ_CSC_PARAM_FIX_BIT_WIDTH - 1)
26 /* csc convert coef fixed-point num */
27 #define PQ_CSC_PARAM_FIX_NUM (1 << PQ_CSC_PARAM_FIX_BIT_WIDTH)
28 #define PQ_CSC_PARAM_HALF_FIX_NUM (1 << PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH)
29 /* csc input param bit width */
30 #define PQ_CSC_IN_PARAM_NORM_BIT_WIDTH 9
31 /* csc input param normalization coef */
32 #define PQ_CSC_IN_PARAM_NORM_COEF (1 << PQ_CSC_IN_PARAM_NORM_BIT_WIDTH)
33
34 /* csc hue table range [0,255] */
35 #define PQ_CSC_HUE_TABLE_DIV_COEF 2
36 /* csc brightness offset */
37 #define PQ_CSC_BRIGHTNESS_OFFSET 256
38
39 /* dc coef base bit width */
40 #define PQ_CSC_DC_COEF_BASE_BIT_WIDTH 10
41 /* input dc coef offset for 10bit data */
42 #define PQ_CSC_DC_IN_OFFSET 64
43 /* input and output dc coef offset for 10bit data u,v */
44 #define PQ_CSC_DC_IN_OUT_DEFAULT 512
45 /* r,g,b color temp div coef, range [-128,128] for 10bit data */
46 #define PQ_CSC_TEMP_OFFSET_DIV_COEF 2
47
48 #define MAX(a, b) ((a) > (b) ? (a) : (b))
49 #define MIN(a, b) ((a) < (b) ? (a) : (b))
50 #define CLIP(x, min_v, max_v) MIN(MAX(x, min_v), max_v)
51
52 #define V4L2_COLORSPACE_BT709F 0xfe
53 #define V4L2_COLORSPACE_BT2020F 0xff
54
55 enum vop_csc_bit_depth {
56 CSC_10BIT_DEPTH,
57 CSC_13BIT_DEPTH,
58 };
59
60 enum rk_pq_csc_mode {
61 RK_PQ_CSC_YUV2RGB_601 = 0, /* YCbCr_601 LIMIT-> RGB FULL */
62 RK_PQ_CSC_YUV2RGB_709, /* YCbCr_709 LIMIT-> RGB FULL */
63 RK_PQ_CSC_RGB2YUV_601, /* RGB FULL->YCbCr_601 LIMIT */
64 RK_PQ_CSC_RGB2YUV_709, /* RGB FULL->YCbCr_709 LIMIT */
65 RK_PQ_CSC_YUV2YUV_709_601, /* YCbCr_709 LIMIT->YCbCr_601 LIMIT */
66 RK_PQ_CSC_YUV2YUV_601_709, /* YCbCr_601 LIMIT->YCbCr_709 LIMIT */
67 RK_PQ_CSC_YUV2YUV, /* YCbCr LIMIT->YCbCr LIMIT */
68 RK_PQ_CSC_YUV2RGB_601_FULL, /* YCbCr_601 FULL-> RGB FULL */
69 RK_PQ_CSC_YUV2RGB_709_FULL, /* YCbCr_709 FULL-> RGB FULL */
70 RK_PQ_CSC_RGB2YUV_601_FULL, /* RGB FULL->YCbCr_601 FULL */
71 RK_PQ_CSC_RGB2YUV_709_FULL, /* RGB FULL->YCbCr_709 FULL */
72 RK_PQ_CSC_YUV2YUV_709_601_FULL, /* YCbCr_709 FULL->YCbCr_601 FULL */
73 RK_PQ_CSC_YUV2YUV_601_709_FULL, /* YCbCr_601 FULL->YCbCr_709 FULL */
74 RK_PQ_CSC_YUV2YUV_FULL, /* YCbCr FULL->YCbCr FULL */
75 RK_PQ_CSC_YUV2YUV_LIMIT2FULL, /* YCbCr LIMIT->YCbCr FULL */
76 RK_PQ_CSC_YUV2YUV_601_709_LIMIT2FULL, /* YCbCr 601 LIMIT->YCbCr 709 FULL */
77 RK_PQ_CSC_YUV2YUV_709_601_LIMIT2FULL, /* YCbCr 709 LIMIT->YCbCr 601 FULL */
78 RK_PQ_CSC_YUV2YUV_FULL2LIMIT, /* YCbCr FULL->YCbCr LIMIT */
79 RK_PQ_CSC_YUV2YUV_601_709_FULL2LIMIT, /* YCbCr 601 FULL->YCbCr 709 LIMIT */
80 RK_PQ_CSC_YUV2YUV_709_601_FULL2LIMIT, /* YCbCr 709 FULL->YCbCr 601 LIMIT */
81 RK_PQ_CSC_YUV2RGBL_601, /* YCbCr_601 LIMIT-> RGB LIMIT */
82 RK_PQ_CSC_YUV2RGBL_709, /* YCbCr_709 LIMIT-> RGB LIMIT */
83 RK_PQ_CSC_RGBL2YUV_601, /* RGB LIMIT->YCbCr_601 LIMIT */
84 RK_PQ_CSC_RGBL2YUV_709, /* RGB LIMIT->YCbCr_709 LIMIT */
85 RK_PQ_CSC_YUV2RGBL_601_FULL, /* YCbCr_601 FULL-> RGB LIMIT */
86 RK_PQ_CSC_YUV2RGBL_709_FULL, /* YCbCr_709 FULL-> RGB LIMIT */
87 RK_PQ_CSC_RGBL2YUV_601_FULL, /* RGB LIMIT->YCbCr_601 FULL */
88 RK_PQ_CSC_RGBL2YUV_709_FULL, /* RGB LIMIT->YCbCr_709 FULL */
89 RK_PQ_CSC_RGB2RGBL, /* RGB FULL->RGB LIMIT */
90 RK_PQ_CSC_RGBL2RGB, /* RGB LIMIT->RGB FULL */
91 RK_PQ_CSC_RGBL2RGBL, /* RGB LIMIT->RGB LIMIT */
92 RK_PQ_CSC_RGB2RGB, /* RGB FULL->RGB FULL */
93 RK_PQ_CSC_YUV2RGB_2020, /* YUV 2020 FULL->RGB 2020 FULL */
94 RK_PQ_CSC_RGB2YUV2020_LIMIT2FULL, /* BT2020RGBLIMIT -> BT2020YUVFULL */
95 RK_PQ_CSC_RGB2YUV2020_LIMIT, /* BT2020RGBLIMIT -> BT2020YUVLIMIT */
96 RK_PQ_CSC_RGB2YUV2020_FULL2LIMIT, /* BT2020RGBFULL -> BT2020YUVLIMIT */
97 RK_PQ_CSC_RGB2YUV2020_FULL, /* BT2020RGBFULL -> BT2020YUVFULL */
98 };
99
100 enum color_space_type {
101 OPTM_CS_E_UNKNOWN = 0,
102 OPTM_CS_E_ITU_R_BT_709 = 1,
103 OPTM_CS_E_FCC = 4,
104 OPTM_CS_E_ITU_R_BT_470_2_BG = 5,
105 OPTM_CS_E_SMPTE_170_M = 6,
106 OPTM_CS_E_SMPTE_240_M = 7,
107 OPTM_CS_E_XV_YCC_709 = OPTM_CS_E_ITU_R_BT_709,
108 OPTM_CS_E_XV_YCC_601 = 8,
109 OPTM_CS_E_RGB = 9,
110 OPTM_CS_E_XV_YCC_2020 = 10,
111 OPTM_CS_E_RGB_2020 = 11,
112 };
113
114 struct rk_pq_csc_coef {
115 s32 csc_coef00;
116 s32 csc_coef01;
117 s32 csc_coef02;
118 s32 csc_coef10;
119 s32 csc_coef11;
120 s32 csc_coef12;
121 s32 csc_coef20;
122 s32 csc_coef21;
123 s32 csc_coef22;
124 };
125
126 struct rk_pq_csc_ventor {
127 s32 csc_offset0;
128 s32 csc_offset1;
129 s32 csc_offset2;
130 };
131
132 struct rk_pq_csc_dc_coef {
133 s32 csc_in_dc0;
134 s32 csc_in_dc1;
135 s32 csc_in_dc2;
136 s32 csc_out_dc0;
137 s32 csc_out_dc1;
138 s32 csc_out_dc2;
139 };
140
141 /* color space param */
142 struct rk_csc_colorspace_info {
143 enum color_space_type input_color_space;
144 enum color_space_type output_color_space;
145 bool in_full_range;
146 bool out_full_range;
147 };
148
149 struct rk_csc_mode_coef {
150 enum rk_pq_csc_mode csc_mode;
151 char c_csc_comment[PQ_CSC_MODE_COEF_COMMENT_LEN];
152 const struct rk_pq_csc_coef *pst_csc_coef;
153 const struct rk_pq_csc_dc_coef *pst_csc_dc_coef;
154 struct rk_csc_colorspace_info st_csc_color_info;
155 };
156
157 /*
158 *CSC matrix
159 */
160 /* xv_ycc BT.601 limit(i.e. SD) -> RGB full */
161 static const struct rk_pq_csc_coef rk_csc_table_xv_yccsdy_cb_cr_limit_to_rgb_full = {
162 1196, 0, 1639,
163 1196, -402, -835,
164 1196, 2072, 0
165 };
166
167 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_xv_yccsdy_cb_cr_limit_to_rgb_full = {
168 -64, -512, -512,
169 0, 0, 0
170 };
171
172 /* BT.709 limit(i.e. HD) -> RGB full */
173 static const struct rk_pq_csc_coef rk_csc_table_hdy_cb_cr_limit_to_rgb_full = {
174 1196, 0, 1841,
175 1196, -219, -547,
176 1196, 2169, 0
177 };
178
179 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_hdy_cb_cr_limit_to_rgb_full = {
180 -64, -512, -512,
181 0, 0, 0
182 };
183
184 /* RGB full-> YUV601 (i.e. SD) limit */
185 static const struct rk_pq_csc_coef rk_csc_table_rgb_to_xv_yccsdy_cb_cr = {
186 262, 515, 100,
187 -151, -297, 448,
188 448, -376, -73
189 };
190
191 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_rgb_to_xv_yccsdy_cb_cr = {
192 0, 0, 0,
193 64, 512, 512
194 };
195
196 /* RGB full-> YUV709 (i.e. SD) limit */
197 static const struct rk_pq_csc_coef rk_csc_table_rgb_to_hdy_cb_cr = {
198 186, 627, 63,
199 -103, -346, 448,
200 448, -407, -41
201 };
202
203 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_rgb_to_hdy_cb_cr = {
204 0, 0, 0,
205 64, 512, 512
206 };
207
208 /* BT.709 (i.e. HD) -> to xv_ycc BT.601 (i.e. SD) */
209 static const struct rk_pq_csc_coef rk_csc_table_hdy_cb_cr_to_xv_yccsdy_cb_cr = {
210 1024, 104, 201,
211 0, 1014, -113,
212 0, -74, 1007
213 };
214
215 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_hdy_cb_cr_to_xv_yccsdy_cb_cr = {
216 -64, -512, -512,
217 64, 512, 512
218 };
219
220 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsdy_cb_cr_full = {
221 0, -512, -512,
222 0, 512, 512
223 };
224
225 /* xv_ycc BT.601 (i.e. SD) -> to BT.709 (i.e. HD) */
226 static const struct rk_pq_csc_coef rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr = {
227 1024, -121, -218,
228 0, 1043, 117,
229 0, 77, 1050
230 };
231
232 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr = {
233 -64, -512, -512,
234 64, 512, 512
235 };
236
237 /* xv_ycc BT.601 full(i.e. SD) -> RGB full */
238 static const struct rk_pq_csc_coef rk_csc_table_xv_yccsdy_cb_cr_to_rgb_full = {
239 1024, 0, 1436,
240 1024, -352, -731,
241 1024, 1815, 0
242 };
243
244 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_xv_yccsdy_cb_cr_to_rgb_full = {
245 0, -512, -512,
246 0, 0, 0
247 };
248
249 /* BT.709 full(i.e. HD) -> RGB full */
250 static const struct rk_pq_csc_coef rk_csc_table_hdy_cb_cr_to_rgb_full = {
251 1024, 0, 1613,
252 1024, -192, -479,
253 1024, 1900, 0
254 };
255
256 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_hdy_cb_cr_to_rgb_full = {
257 0, -512, -512,
258 0, 0, 0
259 };
260
261 /* RGB full-> YUV601 full(i.e. SD) */
262 static const struct rk_pq_csc_coef rk_csc_table_rgb_to_xv_yccsdy_cb_cr_full = {
263 306, 601, 117,
264 -173, -339, 512,
265 512, -429, -83
266 };
267
268 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_rgb_to_xv_yccsdy_cb_cr_full = {
269 0, 0, 0,
270 0, 512, 512
271 };
272
273 /* RGB full-> YUV709 full (i.e. SD) */
274 static const struct rk_pq_csc_coef rk_csc_table_rgb_to_hdy_cb_cr_full = {
275 218, 732, 74,
276 -117, -395, 512,
277 512, -465, -47
278 };
279
280 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_rgb_to_hdy_cb_cr_full = {
281 0, 0, 0,
282 0, 512, 512
283 };
284
285 /* limit -> full */
286 static const struct rk_pq_csc_coef rk_csc_table_identity_y_cb_cr_limit_to_y_cb_cr_full = {
287 1196, 0, 0,
288 0, 1169, 0,
289 0, 0, 1169
290 };
291
292 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_y_cb_cr_limit_to_y_cb_cr_full = {
293 -64, -512, -512,
294 0, 512, 512
295 };
296
297 /* 601 limit -> 709 full */
298 static const struct rk_pq_csc_coef rk_csc_table_identity_601_limit_to_709_full = {
299 1196, -138, -249,
300 0, 1191, 134,
301 0, 88, 1199
302 };
303
304 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_601_limit_to_709_full = {
305 -64, -512, -512,
306 0, 512, 512
307 };
308
309 /* 709 limit -> 601 full */
310 static const struct rk_pq_csc_coef rk_csc_table_identity_709_limit_to_601_full = {
311 1196, 119, 229,
312 0, 1157, -129,
313 0, -85, 1150
314 };
315
316 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_709_limit_to_601_full = {
317 -64, -512, -512,
318 0, 512, 512
319 };
320
321 /* full -> limit */
322 static const struct rk_pq_csc_coef rk_csc_table_identity_y_cb_cr_full_to_y_cb_cr_limit = {
323 877, 0, 0,
324 0, 897, 0,
325 0, 0, 897
326 };
327
328 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_y_cb_cr_full_to_y_cb_cr_limit = {
329 0, -512, -512,
330 64, 512, 512
331 };
332
333 /* 601 full -> 709 limit */
334 static const struct rk_pq_csc_coef rk_csc_table_identity_y_cb_cr_601_full_to_y_cb_cr_709_limit = {
335 877, -106, -191,
336 0, 914, 103,
337 0, 67, 920
338 };
339
340 static const struct rk_pq_csc_dc_coef
341 rk_dc_csc_table_identity_y_cb_cr_601_full_to_y_cb_cr_709_limit = {
342 0, -512, -512,
343 64, 512, 512
344 };
345
346 /* 709 full -> 601 limit */
347 static const struct rk_pq_csc_coef rk_csc_table_identity_y_cb_cr_709_full_to_y_cb_cr_601_limit = {
348 877, 91, 176,
349 0, 888, -99,
350 0, -65, 882
351 };
352
353 static const struct rk_pq_csc_dc_coef
354 rk_dc_csc_table_identity_y_cb_cr_709_full_to_y_cb_cr_601_limit = {
355 0, -512, -512,
356 64, 512, 512
357 };
358
359 /* xv_ycc BT.601 limit(i.e. SD) -> RGB limit */
360 static const struct rk_pq_csc_coef rk_csc_table_xv_yccsdy_cb_cr_limit_to_rgb_limit = {
361 1024, 0, 1404,
362 1024, -344, -715,
363 1024, 1774, 0
364 };
365
366 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_xv_yccsdy_cb_cr_limit_to_rgb_limit = {
367 -64, -512, -512,
368 64, 64, 64
369 };
370
371 /* BT.709 limit(i.e. HD) -> RGB limit */
372 static const struct rk_pq_csc_coef rk_csc_table_hdy_cb_cr_limit_to_rgb_limit = {
373 1024, 0, 1577,
374 1024, -188, -469,
375 1024, 1858, 0
376 };
377
378 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_hdy_cb_cr_limit_to_rgb_limit = {
379 -64, -512, -512,
380 64, 64, 64
381 };
382
383 /* RGB limit-> YUV601 (i.e. SD) limit */
384 static const struct rk_pq_csc_coef rk_csc_table_rgb_limit_to_xv_yccsdy_cb_cr = {
385 306, 601, 117,
386 -177, -347, 524,
387 524, -439, -85
388 };
389
390 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_rgb_limit_to_xv_yccsdy_cb_cr = {
391 -64, -64, -64,
392 64, 512, 512
393 };
394
395 /* RGB limit -> YUV709 (i.e. SD) limit */
396 static const struct rk_pq_csc_coef rk_csc_table_rgb_limit_to_hdy_cb_cr = {
397 218, 732, 74,
398 -120, -404, 524,
399 524, -476, -48
400 };
401
402 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_rgb_limit_to_hdy_cb_cr = {
403 -64, -64, -64,
404 64, 512, 512
405 };
406
407 /* xv_ycc BT.601 full(i.e. SD) -> RGB limit */
408 static const struct rk_pq_csc_coef rk_csc_table_xv_yccsdy_cb_cr_to_rgb_limit = {
409 877, 0, 1229,
410 877, -302, -626,
411 877, 1554, 0
412 };
413
414 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_xv_yccsdy_cb_cr_to_rgb_limit = {
415 0, -512, -512,
416 64, 64, 64
417 };
418
419 /* BT.709 full(i.e. HD) -> RGB limit */
420 static const struct rk_pq_csc_coef rk_csc_table_hdy_cb_cr_to_rgb_limit = {
421 877, 0, 1381,
422 877, -164, -410,
423 877, 1627, 0
424 };
425
426 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_hdy_cb_cr_to_rgb_limit = {
427 0, -512, -512,
428 64, 64, 64
429 };
430
431 /* RGB limit-> YUV601 full(i.e. SD) */
432 static const struct rk_pq_csc_coef rk_csc_table_rgb_limit_to_xv_yccsdy_cb_cr_full = {
433 358, 702, 136,
434 -202, -396, 598,
435 598, -501, -97
436 };
437
438 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_rgb_limit_to_xv_yccsdy_cb_cr_full = {
439 -64, -64, -64,
440 0, 512, 512
441 };
442
443 /* RGB limit-> YUV709 full (i.e. SD) */
444 static const struct rk_pq_csc_coef rk_csc_table_rgb_limit_to_hdy_cb_cr_full = {
445 254, 855, 86,
446 -137, -461, 598,
447 598, -543, -55
448 };
449
450 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_rgb_limit_to_hdy_cb_cr_full = {
451 -64, -64, -64,
452 0, 512, 512
453 };
454
455 /* RGB full -> RGB limit */
456 static const struct rk_pq_csc_coef rk_csc_table_identity_rgb_to_rgb_limit = {
457 877, 0, 0,
458 0, 877, 0,
459 0, 0, 877
460 };
461
462 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_rgb_to_rgb_limit = {
463 0, 0, 0,
464 64, 64, 64
465 };
466
467 /* RGB limit -> RGB full */
468 static const struct rk_pq_csc_coef rk_csc_table_identity_rgb_limit_to_rgb = {
469 1196, 0, 0,
470 0, 1196, 0,
471 0, 0, 1196
472 };
473
474 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_rgb_limit_to_rgb = {
475 -64, -64, -64,
476 0, 0, 0
477 };
478
479 /* RGB limit/full -> RGB limit/full */
480 static const struct rk_pq_csc_coef rk_csc_table_identity_rgb_to_rgb = {
481 1024, 0, 0,
482 0, 1024, 0,
483 0, 0, 1024
484 };
485
486 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_rgb_to_rgb1 = {
487 -64, -64, -64,
488 64, 64, 64
489 };
490
491 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_rgb_to_rgb2 = {
492 0, 0, 0,
493 0, 0, 0
494 };
495
496 static const struct rk_pq_csc_coef rk_csc_table_identity_yuv_to_rgb_2020 = {
497 1024, 0, 1510,
498 1024, -169, -585,
499 1024, 1927, 0
500 };
501
502 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_yuv_to_rgb_2020 = {
503 0, -512, -512,
504 0, 0, 0
505 };
506
507 /* 2020 RGB LIMIT ->YUV LIMIT */
508 static const struct rk_pq_csc_coef rk_csc_table_identity_rgb_limit_to_yuv_limit_2020 = {
509 269, 694, 61,
510 -146, -377, 524,
511 524, -482, -42
512 };
513
514 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_rgb_limit_to_yuv_limit_2020 = {
515 -64, -64, -64,
516 64, 512, 512
517 };
518
519 /* 2020 RGB LIMIT ->YUV FULL */
520 static const struct rk_pq_csc_coef rk_csc_table_identity_rgb_limit_to_yuv_full_2020 = {
521 314, 811, 71,
522 -167, -431, 598,
523 598, -550, -48
524 };
525
526 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_rgb_limit_to_yuv_full_2020 = {
527 -64, -64, -64,
528 0, 512, 512
529 };
530
531 /* 2020 RGB FULL ->YUV LIMIT */
532 static const struct rk_pq_csc_coef rk_csc_table_identity_rgb_full_to_yuv_limit_2020 = {
533 230, 595, 52,
534 -125, -323, 448,
535 448, -412, -36
536 };
537
538 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_rgb_full_to_yuv_limit_2020 = {
539 0, 0, 0,
540 64, 512, 512
541 };
542
543 /* 2020 RGB FULL ->YUV FULL */
544 static const struct rk_pq_csc_coef rk_csc_table_identity_rgb_full_to_yuv_full_2020 = {
545 269, 694, 61,
546 -143, -369, 512,
547 512, -471, -41
548 };
549
550 static const struct rk_pq_csc_dc_coef rk_dc_csc_table_identity_rgb_full_to_yuv_full_2020 = {
551 0, 0, 0,
552 0, 512, 512
553 };
554
555 /* identity matrix */
556 static const struct rk_pq_csc_coef rk_csc_table_identity_y_cb_cr_to_y_cb_cr = {
557 1024, 0, 0,
558 0, 1024, 0,
559 0, 0, 1024
560 };
561
562 /*
563 *CSC Param Struct
564 */
565 static const struct rk_csc_mode_coef g_mode_csc_coef[] = {
566 {
567 RK_PQ_CSC_YUV2RGB_601, "YUV601 L->RGB F",
568 &rk_csc_table_xv_yccsdy_cb_cr_limit_to_rgb_full,
569 &rk_dc_csc_table_xv_yccsdy_cb_cr_limit_to_rgb_full,
570 {
571 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_RGB, false, true
572 }
573 },
574 {
575 RK_PQ_CSC_YUV2RGB_709, "YUV709 L->RGB F",
576 &rk_csc_table_hdy_cb_cr_limit_to_rgb_full,
577 &rk_dc_csc_table_hdy_cb_cr_limit_to_rgb_full,
578 {
579 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_RGB, false, true
580 }
581 },
582 {
583 RK_PQ_CSC_RGB2YUV_601, "RGB F->YUV601 L",
584 &rk_csc_table_rgb_to_xv_yccsdy_cb_cr,
585 &rk_dc_csc_table_rgb_to_xv_yccsdy_cb_cr,
586 {
587 OPTM_CS_E_RGB, OPTM_CS_E_XV_YCC_601, true, false
588 }
589 },
590 {
591 RK_PQ_CSC_RGB2YUV_709, "RGB F->YUV709 L",
592 &rk_csc_table_rgb_to_hdy_cb_cr,
593 &rk_dc_csc_table_rgb_to_hdy_cb_cr,
594 {
595 OPTM_CS_E_RGB, OPTM_CS_E_ITU_R_BT_709, true, false
596 }
597 },
598 {
599 RK_PQ_CSC_YUV2YUV_709_601, "YUV709 L->YUV601 L",
600 &rk_csc_table_hdy_cb_cr_to_xv_yccsdy_cb_cr,
601 &rk_dc_csc_table_hdy_cb_cr_to_xv_yccsdy_cb_cr,
602 {
603 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_XV_YCC_601, false, false
604 }
605 },
606 {
607 RK_PQ_CSC_YUV2YUV_601_709, "YUV601 L->YUV709 L",
608 &rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
609 &rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
610 {
611 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_ITU_R_BT_709, false, false
612 }
613 },
614 {
615 RK_PQ_CSC_YUV2YUV, "YUV L->YUV L",
616 &rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
617 &rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
618 {
619 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_ITU_R_BT_709, false, false
620 }
621 },
622 {
623 RK_PQ_CSC_YUV2RGB_601_FULL, "YUV601 F->RGB F",
624 &rk_csc_table_xv_yccsdy_cb_cr_to_rgb_full,
625 &rk_dc_csc_table_xv_yccsdy_cb_cr_to_rgb_full,
626 {
627 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_RGB, true, true
628 }
629 },
630 {
631 RK_PQ_CSC_YUV2RGB_709_FULL, "YUV709 F->RGB F",
632 &rk_csc_table_hdy_cb_cr_to_rgb_full,
633 &rk_dc_csc_table_hdy_cb_cr_to_rgb_full,
634 {
635 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_RGB, true, true
636 }
637 },
638 {
639 RK_PQ_CSC_RGB2YUV_601_FULL, "RGB F->YUV601 F",
640 &rk_csc_table_rgb_to_xv_yccsdy_cb_cr_full,
641 &rk_dc_csc_table_rgb_to_xv_yccsdy_cb_cr_full,
642 {
643 OPTM_CS_E_RGB, OPTM_CS_E_XV_YCC_601, true, true
644 }
645 },
646 {
647 RK_PQ_CSC_RGB2YUV_709_FULL, "RGB F->YUV709 F",
648 &rk_csc_table_rgb_to_hdy_cb_cr_full,
649 &rk_dc_csc_table_rgb_to_hdy_cb_cr_full,
650 {
651 OPTM_CS_E_RGB, OPTM_CS_E_ITU_R_BT_709, true, true
652 }
653 },
654 {
655 RK_PQ_CSC_YUV2YUV_709_601_FULL, "YUV709 F->YUV601 F",
656 &rk_csc_table_hdy_cb_cr_to_xv_yccsdy_cb_cr,
657 &rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsdy_cb_cr_full,
658 {
659 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_XV_YCC_601, true, true
660 }
661 },
662 {
663 RK_PQ_CSC_YUV2YUV_601_709_FULL, "YUV601 F->YUV709 F",
664 &rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
665 &rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsdy_cb_cr_full,
666 {
667 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_ITU_R_BT_709, true, true
668 }
669 },
670 {
671 RK_PQ_CSC_YUV2YUV_FULL, "YUV F->YUV F",
672 &rk_csc_table_identity_y_cb_cr_to_y_cb_cr,
673 &rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsdy_cb_cr_full,
674 {
675 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_ITU_R_BT_709, true, true
676 }
677 },
678 {
679 RK_PQ_CSC_YUV2YUV_LIMIT2FULL, "YUV L->YUV F",
680 &rk_csc_table_identity_y_cb_cr_limit_to_y_cb_cr_full,
681 &rk_dc_csc_table_identity_y_cb_cr_limit_to_y_cb_cr_full,
682 {
683 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_ITU_R_BT_709, false, true
684 }
685 },
686 {
687 RK_PQ_CSC_YUV2YUV_601_709_LIMIT2FULL, "YUV601 L->YUV709 F",
688 &rk_csc_table_identity_601_limit_to_709_full,
689 &rk_dc_csc_table_identity_601_limit_to_709_full,
690 {
691 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_ITU_R_BT_709, false, true
692 }
693 },
694 {
695 RK_PQ_CSC_YUV2YUV_709_601_LIMIT2FULL, "YUV709 L->YUV601 F",
696 &rk_csc_table_identity_709_limit_to_601_full,
697 &rk_dc_csc_table_identity_709_limit_to_601_full,
698 {
699 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_XV_YCC_601, false, true
700 }
701 },
702 {
703 RK_PQ_CSC_YUV2YUV_FULL2LIMIT, "YUV F->YUV L",
704 &rk_csc_table_identity_y_cb_cr_full_to_y_cb_cr_limit,
705 &rk_dc_csc_table_identity_y_cb_cr_full_to_y_cb_cr_limit,
706 {
707 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_ITU_R_BT_709, true, false
708 }
709 },
710 {
711 RK_PQ_CSC_YUV2YUV_601_709_FULL2LIMIT, "YUV601 F->YUV709 L",
712 &rk_csc_table_identity_y_cb_cr_601_full_to_y_cb_cr_709_limit,
713 &rk_dc_csc_table_identity_y_cb_cr_601_full_to_y_cb_cr_709_limit,
714 {
715 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_ITU_R_BT_709, true, false
716 }
717 },
718 {
719 RK_PQ_CSC_YUV2YUV_709_601_FULL2LIMIT, "YUV709 F->YUV601 L",
720 &rk_csc_table_identity_y_cb_cr_709_full_to_y_cb_cr_601_limit,
721 &rk_dc_csc_table_identity_y_cb_cr_709_full_to_y_cb_cr_601_limit,
722 {
723 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_XV_YCC_601, true, false
724 }
725 },
726 {
727 RK_PQ_CSC_YUV2RGBL_601, "YUV601 L->RGB L",
728 &rk_csc_table_xv_yccsdy_cb_cr_limit_to_rgb_limit,
729 &rk_dc_csc_table_xv_yccsdy_cb_cr_limit_to_rgb_limit,
730 {
731 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_RGB, false, false
732 }
733 },
734 {
735 RK_PQ_CSC_YUV2RGBL_709, "YUV709 L->RGB L",
736 &rk_csc_table_hdy_cb_cr_limit_to_rgb_limit,
737 &rk_dc_csc_table_hdy_cb_cr_limit_to_rgb_limit,
738 {
739 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_RGB, false, false
740 }
741 },
742 {
743 RK_PQ_CSC_RGBL2YUV_601, "RGB L->YUV601 L",
744 &rk_csc_table_rgb_limit_to_xv_yccsdy_cb_cr,
745 &rk_dc_csc_table_rgb_limit_to_xv_yccsdy_cb_cr,
746 {
747 OPTM_CS_E_RGB, OPTM_CS_E_XV_YCC_601, false, false
748 }
749 },
750 {
751 RK_PQ_CSC_RGBL2YUV_709, "RGB L->YUV709 L",
752 &rk_csc_table_rgb_limit_to_hdy_cb_cr,
753 &rk_dc_csc_table_rgb_limit_to_hdy_cb_cr,
754 {
755 OPTM_CS_E_RGB, OPTM_CS_E_ITU_R_BT_709, false, false
756 }
757 },
758 {
759 RK_PQ_CSC_YUV2RGBL_601_FULL, "YUV601 F->RGB L",
760 &rk_csc_table_xv_yccsdy_cb_cr_to_rgb_limit,
761 &rk_dc_csc_table_xv_yccsdy_cb_cr_to_rgb_limit,
762 {
763 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_RGB, true, false
764 }
765 },
766 {
767 RK_PQ_CSC_YUV2RGBL_709_FULL, "YUV709 F->RGB L",
768 &rk_csc_table_hdy_cb_cr_to_rgb_limit,
769 &rk_dc_csc_table_hdy_cb_cr_to_rgb_limit,
770 {
771 OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_RGB, true, false
772 }
773 },
774 {
775 RK_PQ_CSC_RGBL2YUV_601_FULL, "RGB L->YUV601 F",
776 &rk_csc_table_rgb_limit_to_xv_yccsdy_cb_cr_full,
777 &rk_dc_csc_table_rgb_limit_to_xv_yccsdy_cb_cr_full,
778 {
779 OPTM_CS_E_RGB, OPTM_CS_E_XV_YCC_601, false, true
780 }
781 },
782 {
783 RK_PQ_CSC_RGBL2YUV_709_FULL, "RGB L->YUV709 F",
784 &rk_csc_table_rgb_limit_to_hdy_cb_cr_full,
785 &rk_dc_csc_table_rgb_limit_to_hdy_cb_cr_full,
786 {
787 OPTM_CS_E_RGB, OPTM_CS_E_ITU_R_BT_709, false, true
788 }
789 },
790 {
791 RK_PQ_CSC_RGB2RGBL, "RGB F->RGB L",
792 &rk_csc_table_identity_rgb_to_rgb_limit,
793 &rk_dc_csc_table_identity_rgb_to_rgb_limit,
794 {
795 OPTM_CS_E_RGB, OPTM_CS_E_RGB, true, false
796 }
797 },
798 {
799 RK_PQ_CSC_RGBL2RGB, "RGB L->RGB F",
800 &rk_csc_table_identity_rgb_limit_to_rgb,
801 &rk_dc_csc_table_identity_rgb_limit_to_rgb,
802 {
803 OPTM_CS_E_RGB, OPTM_CS_E_RGB, false, true
804 }
805 },
806 {
807 RK_PQ_CSC_RGBL2RGBL, "RGB L->RGB L",
808 &rk_csc_table_identity_rgb_to_rgb,
809 &rk_dc_csc_table_identity_rgb_to_rgb1,
810 {
811 OPTM_CS_E_RGB, OPTM_CS_E_RGB, false, false
812 }
813 },
814 {
815 RK_PQ_CSC_RGB2RGB, "RGB F->RGB F",
816 &rk_csc_table_identity_rgb_to_rgb,
817 &rk_dc_csc_table_identity_rgb_to_rgb2,
818 {
819 OPTM_CS_E_RGB, OPTM_CS_E_RGB, true, true
820 }
821 },
822 {
823 RK_PQ_CSC_YUV2RGB_2020, "YUV2020 F->RGB2020 F",
824 &rk_csc_table_identity_yuv_to_rgb_2020,
825 &rk_dc_csc_table_identity_yuv_to_rgb_2020,
826 {
827 OPTM_CS_E_XV_YCC_2020, OPTM_CS_E_RGB_2020, true, true
828 }
829 },
830 {
831 RK_PQ_CSC_RGB2YUV2020_LIMIT2FULL, "RGB2020 L->YUV2020 F",
832 &rk_csc_table_identity_rgb_limit_to_yuv_full_2020,
833 &rk_dc_csc_table_identity_rgb_limit_to_yuv_full_2020,
834 {
835 OPTM_CS_E_RGB_2020, OPTM_CS_E_XV_YCC_2020, false, true
836 }
837 },
838 {
839 RK_PQ_CSC_RGB2YUV2020_LIMIT, "RGB2020 L->YUV2020 L",
840 &rk_csc_table_identity_rgb_limit_to_yuv_limit_2020,
841 &rk_dc_csc_table_identity_rgb_limit_to_yuv_limit_2020,
842 {
843 OPTM_CS_E_RGB_2020, OPTM_CS_E_XV_YCC_2020, false, false
844 }
845 },
846 {
847 RK_PQ_CSC_RGB2YUV2020_FULL2LIMIT, "RGB2020 F->YUV2020 L",
848 &rk_csc_table_identity_rgb_full_to_yuv_limit_2020,
849 &rk_dc_csc_table_identity_rgb_full_to_yuv_limit_2020,
850 {
851 OPTM_CS_E_RGB_2020, OPTM_CS_E_XV_YCC_2020, true, false
852 }
853 },
854 {
855 RK_PQ_CSC_RGB2YUV2020_FULL, "RGB2020 F->YUV2020 F",
856 &rk_csc_table_identity_rgb_full_to_yuv_full_2020,
857 &rk_dc_csc_table_identity_rgb_full_to_yuv_full_2020,
858 {
859 OPTM_CS_E_RGB_2020, OPTM_CS_E_XV_YCC_2020, true, true
860 }
861 },
862 {
863 RK_PQ_CSC_YUV2YUV, "YUV 601 L->YUV 601 L",
864 &rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
865 &rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
866 {
867 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_XV_YCC_601, false, false
868 }
869 },
870 {
871 RK_PQ_CSC_YUV2YUV_FULL, "YUV 601 F->YUV 601 F",
872 &rk_csc_table_identity_y_cb_cr_to_y_cb_cr,
873 &rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsdy_cb_cr_full,
874 {
875 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_XV_YCC_601, true, true
876 }
877 },
878 {
879 RK_PQ_CSC_YUV2YUV_LIMIT2FULL, "YUV 601 L->YUV 601 F",
880 &rk_csc_table_identity_y_cb_cr_limit_to_y_cb_cr_full,
881 &rk_dc_csc_table_identity_y_cb_cr_limit_to_y_cb_cr_full,
882 {
883 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_XV_YCC_601, false, true
884 }
885 },
886 {
887 RK_PQ_CSC_YUV2YUV_FULL2LIMIT, "YUV 601 F->YUV 601 L",
888 &rk_csc_table_identity_y_cb_cr_full_to_y_cb_cr_limit,
889 &rk_dc_csc_table_identity_y_cb_cr_full_to_y_cb_cr_limit,
890 {
891 OPTM_CS_E_XV_YCC_601, OPTM_CS_E_XV_YCC_601, true, false
892 }
893 },
894 {
895 RK_PQ_CSC_YUV2YUV, "YUV 2020 L->YUV 2020 L",
896 &rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
897 &rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
898 {
899 OPTM_CS_E_XV_YCC_2020, OPTM_CS_E_XV_YCC_2020, false, false
900 }
901 },
902 {
903 RK_PQ_CSC_YUV2YUV_FULL, "YUV 2020 F->YUV 2020 F",
904 &rk_csc_table_identity_y_cb_cr_to_y_cb_cr,
905 &rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsdy_cb_cr_full,
906 {
907 OPTM_CS_E_XV_YCC_2020, OPTM_CS_E_XV_YCC_2020, true, true
908 }
909 },
910 {
911 RK_PQ_CSC_YUV2YUV_LIMIT2FULL, "YUV 2020 L->YUV 2020 F",
912 &rk_csc_table_identity_y_cb_cr_limit_to_y_cb_cr_full,
913 &rk_dc_csc_table_identity_y_cb_cr_limit_to_y_cb_cr_full,
914 {
915 OPTM_CS_E_XV_YCC_2020, OPTM_CS_E_XV_YCC_2020, false, true
916 }
917 },
918 {
919 RK_PQ_CSC_YUV2YUV_FULL2LIMIT, "YUV 2020 F->YUV 2020 L",
920 &rk_csc_table_identity_y_cb_cr_full_to_y_cb_cr_limit,
921 &rk_dc_csc_table_identity_y_cb_cr_full_to_y_cb_cr_limit,
922 {
923 OPTM_CS_E_XV_YCC_2020, OPTM_CS_E_XV_YCC_2020, true, false
924 }
925 },
926 {
927 RK_PQ_CSC_RGB2RGBL, "RGB 2020 F->RGB 2020 L",
928 &rk_csc_table_identity_rgb_to_rgb_limit,
929 &rk_dc_csc_table_identity_rgb_to_rgb_limit,
930 {
931 OPTM_CS_E_RGB_2020, OPTM_CS_E_RGB_2020, true, false
932 }
933 },
934 {
935 RK_PQ_CSC_RGBL2RGB, "RGB 2020 L->RGB 2020 F",
936 &rk_csc_table_identity_rgb_limit_to_rgb,
937 &rk_dc_csc_table_identity_rgb_limit_to_rgb,
938 {
939 OPTM_CS_E_RGB_2020, OPTM_CS_E_RGB_2020, false, true
940 }
941 },
942 {
943 RK_PQ_CSC_RGBL2RGBL, "RGB 2020 L->RGB 2020 L",
944 &rk_csc_table_identity_rgb_to_rgb,
945 &rk_dc_csc_table_identity_rgb_to_rgb1,
946 {
947 OPTM_CS_E_RGB_2020, OPTM_CS_E_RGB_2020, false, false
948 }
949 },
950 {
951 RK_PQ_CSC_RGB2RGB, "RGB 2020 F->RGB 2020 F",
952 &rk_csc_table_identity_rgb_to_rgb,
953 &rk_dc_csc_table_identity_rgb_to_rgb2,
954 {
955 OPTM_CS_E_RGB_2020, OPTM_CS_E_RGB_2020, true, true
956 }
957 },
958 };
959
960 enum vop_csc_format {
961 CSC_BT601L,
962 CSC_BT709L,
963 CSC_BT601F,
964 CSC_BT2020,
965 CSC_BT709L_13BIT,
966 CSC_BT709F_13BIT,
967 CSC_BT2020L_13BIT,
968 CSC_BT2020F_13BIT,
969 };
970
971 enum vop_csc_mode {
972 CSC_RGB,
973 CSC_YUV,
974 };
975
976 struct csc_mapping {
977 enum vop_csc_format csc_format;
978 enum color_space_type rgb_color_space;
979 enum color_space_type yuv_color_space;
980 bool rgb_full_range;
981 bool yuv_full_range;
982 };
983
984 static const struct csc_mapping csc_mapping_table[] = {
985 {
986 CSC_BT601L,
987 OPTM_CS_E_RGB,
988 OPTM_CS_E_XV_YCC_601,
989 true,
990 false,
991 },
992 {
993 CSC_BT709L,
994 OPTM_CS_E_RGB,
995 OPTM_CS_E_XV_YCC_709,
996 true,
997 false,
998 },
999 {
1000 CSC_BT601F,
1001 OPTM_CS_E_RGB,
1002 OPTM_CS_E_XV_YCC_601,
1003 true,
1004 true,
1005 },
1006 {
1007 CSC_BT2020,
1008 OPTM_CS_E_RGB_2020,
1009 OPTM_CS_E_XV_YCC_2020,
1010 true,
1011 true,
1012 },
1013 {
1014 CSC_BT709L_13BIT,
1015 OPTM_CS_E_RGB,
1016 OPTM_CS_E_XV_YCC_709,
1017 true,
1018 false,
1019 },
1020 {
1021 CSC_BT709F_13BIT,
1022 OPTM_CS_E_RGB,
1023 OPTM_CS_E_XV_YCC_709,
1024 true,
1025 true,
1026 },
1027 {
1028 CSC_BT2020L_13BIT,
1029 OPTM_CS_E_RGB_2020,
1030 OPTM_CS_E_XV_YCC_2020,
1031 true,
1032 false,
1033 },
1034 {
1035 CSC_BT2020F_13BIT,
1036 OPTM_CS_E_RGB_2020,
1037 OPTM_CS_E_XV_YCC_2020,
1038 true,
1039 true,
1040 },
1041 };
1042
is_rgb_format(u64 format)1043 static bool is_rgb_format(u64 format)
1044 {
1045 switch (format) {
1046 case BUS_FMT_YUV420:
1047 case BUS_FMT_YUV422:
1048 case BUS_FMT_YUV444:
1049 return false;
1050 case BUS_FMT_RGB:
1051 default:
1052 return true;
1053 }
1054 }
1055
1056 struct post_csc_coef {
1057 s32 csc_coef00;
1058 s32 csc_coef01;
1059 s32 csc_coef02;
1060 s32 csc_coef10;
1061 s32 csc_coef11;
1062 s32 csc_coef12;
1063 s32 csc_coef20;
1064 s32 csc_coef21;
1065 s32 csc_coef22;
1066
1067 s32 csc_dc0;
1068 s32 csc_dc1;
1069 s32 csc_dc2;
1070
1071 u32 range_type;
1072 };
1073
csc_get_mode_index(int post_csc_mode,bool is_input_yuv,bool is_output_yuv)1074 static int csc_get_mode_index(int post_csc_mode, bool is_input_yuv, bool is_output_yuv)
1075 {
1076 const struct rk_csc_colorspace_info *colorspace_info;
1077 enum color_space_type input_color_space;
1078 enum color_space_type output_color_space;
1079 bool is_input_full_range;
1080 bool is_output_full_range;
1081 int i;
1082
1083 for (i = 0; i < ARRAY_SIZE(csc_mapping_table); i++) {
1084 if (post_csc_mode == csc_mapping_table[i].csc_format) {
1085 input_color_space = is_input_yuv ? csc_mapping_table[i].yuv_color_space :
1086 csc_mapping_table[i].rgb_color_space;
1087 is_input_full_range = is_input_yuv ? csc_mapping_table[i].yuv_full_range :
1088 csc_mapping_table[i].rgb_full_range;
1089 output_color_space = is_output_yuv ? csc_mapping_table[i].yuv_color_space :
1090 csc_mapping_table[i].rgb_color_space;
1091 is_output_full_range = is_output_yuv ? csc_mapping_table[i].yuv_full_range :
1092 csc_mapping_table[i].rgb_full_range;
1093 break;
1094 }
1095 }
1096 if (i >= ARRAY_SIZE(csc_mapping_table))
1097 return -EINVAL;
1098
1099 for (i = 0; i < ARRAY_SIZE(g_mode_csc_coef); i++) {
1100 colorspace_info = &g_mode_csc_coef[i].st_csc_color_info;
1101 if (colorspace_info->input_color_space == input_color_space &&
1102 colorspace_info->output_color_space == output_color_space &&
1103 colorspace_info->in_full_range == is_input_full_range &&
1104 colorspace_info->out_full_range == is_output_full_range)
1105 return i;
1106 }
1107
1108 return -EINVAL;
1109 }
1110
csc_matrix_ventor_multiply(struct rk_pq_csc_ventor * dst,const struct rk_pq_csc_coef * m0,const struct rk_pq_csc_ventor * v0)1111 static void csc_matrix_ventor_multiply(struct rk_pq_csc_ventor *dst,
1112 const struct rk_pq_csc_coef *m0,
1113 const struct rk_pq_csc_ventor *v0)
1114 {
1115 dst->csc_offset0 = m0->csc_coef00 * v0->csc_offset0 +
1116 m0->csc_coef01 * v0->csc_offset1 +
1117 m0->csc_coef02 * v0->csc_offset2;
1118
1119 dst->csc_offset1 = m0->csc_coef10 * v0->csc_offset0 +
1120 m0->csc_coef11 * v0->csc_offset1 +
1121 m0->csc_coef12 * v0->csc_offset2;
1122
1123 dst->csc_offset2 = m0->csc_coef20 * v0->csc_offset0 +
1124 m0->csc_coef21 * v0->csc_offset1 +
1125 m0->csc_coef22 * v0->csc_offset2;
1126 }
1127
pq_csc_simple_round(s32 x,s32 n)1128 static inline s32 pq_csc_simple_round(s32 x, s32 n)
1129 {
1130 s32 value = 0;
1131
1132 if (n == 0)
1133 return x;
1134
1135 value = (abs(x) + (1 << (n - 1))) >> (n);
1136 return (((x) >= 0) ? value : -value);
1137 }
1138
csc_calc_default_output_coef(const struct rk_csc_mode_coef * csc_mode_cfg,struct rk_pq_csc_coef * out_matrix,struct rk_pq_csc_ventor * out_dc)1139 static int csc_calc_default_output_coef(const struct rk_csc_mode_coef *csc_mode_cfg,
1140 struct rk_pq_csc_coef *out_matrix,
1141 struct rk_pq_csc_ventor *out_dc)
1142 {
1143 const struct rk_pq_csc_coef *csc_coef;
1144 const struct rk_pq_csc_dc_coef *csc_dc_coef;
1145 struct rk_pq_csc_ventor dc_in_ventor;
1146 struct rk_pq_csc_ventor dc_out_ventor;
1147 struct rk_pq_csc_ventor v;
1148
1149 csc_coef = csc_mode_cfg->pst_csc_coef;
1150 csc_dc_coef = csc_mode_cfg->pst_csc_dc_coef;
1151
1152 out_matrix->csc_coef00 = csc_coef->csc_coef00;
1153 out_matrix->csc_coef01 = csc_coef->csc_coef01;
1154 out_matrix->csc_coef02 = csc_coef->csc_coef02;
1155 out_matrix->csc_coef10 = csc_coef->csc_coef10;
1156 out_matrix->csc_coef11 = csc_coef->csc_coef11;
1157 out_matrix->csc_coef12 = csc_coef->csc_coef12;
1158 out_matrix->csc_coef20 = csc_coef->csc_coef20;
1159 out_matrix->csc_coef21 = csc_coef->csc_coef21;
1160 out_matrix->csc_coef22 = csc_coef->csc_coef22;
1161
1162 dc_in_ventor.csc_offset0 = csc_dc_coef->csc_in_dc0;
1163 dc_in_ventor.csc_offset1 = csc_dc_coef->csc_in_dc1;
1164 dc_in_ventor.csc_offset2 = csc_dc_coef->csc_in_dc2;
1165 dc_out_ventor.csc_offset0 = csc_dc_coef->csc_out_dc0;
1166 dc_out_ventor.csc_offset1 = csc_dc_coef->csc_out_dc1;
1167 dc_out_ventor.csc_offset2 = csc_dc_coef->csc_out_dc2;
1168
1169 csc_matrix_ventor_multiply(&v, csc_coef, &dc_in_ventor);
1170 out_dc->csc_offset0 = v.csc_offset0 + dc_out_ventor.csc_offset0 *
1171 PQ_CSC_SIMPLE_MAT_PARAM_FIX_NUM;
1172 out_dc->csc_offset1 = v.csc_offset1 + dc_out_ventor.csc_offset1 *
1173 PQ_CSC_SIMPLE_MAT_PARAM_FIX_NUM;
1174 out_dc->csc_offset2 = v.csc_offset2 + dc_out_ventor.csc_offset2 *
1175 PQ_CSC_SIMPLE_MAT_PARAM_FIX_NUM;
1176
1177 return 0;
1178 }
1179
vop2_convert_csc_mode(int csc_mode,int bit_depth)1180 static int vop2_convert_csc_mode(int csc_mode, int bit_depth)
1181 {
1182 switch (csc_mode) {
1183 case V4L2_COLORSPACE_SMPTE170M:
1184 case V4L2_COLORSPACE_470_SYSTEM_M:
1185 case V4L2_COLORSPACE_470_SYSTEM_BG:
1186 return CSC_BT601L;
1187 case V4L2_COLORSPACE_REC709:
1188 case V4L2_COLORSPACE_SMPTE240M:
1189 case V4L2_COLORSPACE_DEFAULT:
1190 if (bit_depth == CSC_13BIT_DEPTH)
1191 return CSC_BT709L_13BIT;
1192 else
1193 return CSC_BT709L;
1194 case V4L2_COLORSPACE_JPEG:
1195 return CSC_BT601F;
1196 case V4L2_COLORSPACE_BT2020:
1197 if (bit_depth == CSC_13BIT_DEPTH)
1198 return CSC_BT2020L_13BIT;
1199 else
1200 return CSC_BT2020;
1201 case V4L2_COLORSPACE_BT709F:
1202 if (bit_depth == CSC_10BIT_DEPTH)
1203 return CSC_BT601F;
1204 else
1205 return CSC_BT709F_13BIT;
1206 case V4L2_COLORSPACE_BT2020F:
1207 if (bit_depth == CSC_10BIT_DEPTH)
1208 return CSC_BT601F;
1209 else
1210 return CSC_BT2020F_13BIT;
1211 default:
1212 return CSC_BT709L;
1213 }
1214 }
1215
rockchip_calc_post_csc(struct post_csc_coef * csc_simple_coef,int csc_mode,bool is_input_yuv,bool is_output_yuv)1216 static int rockchip_calc_post_csc(struct post_csc_coef *csc_simple_coef,
1217 int csc_mode, bool is_input_yuv, bool is_output_yuv)
1218 {
1219 int ret = 0;
1220 struct rk_pq_csc_coef out_matrix;
1221 struct rk_pq_csc_ventor out_dc;
1222 const struct rk_csc_mode_coef *csc_mode_cfg;
1223 int bit_num = PQ_CSC_SIMPLE_MAT_PARAM_FIX_BIT_WIDTH;
1224
1225 ret = csc_get_mode_index(csc_mode, is_input_yuv, is_output_yuv);
1226 if (ret < 0)
1227 return ret;
1228
1229 csc_mode_cfg = &g_mode_csc_coef[ret];
1230
1231 ret = csc_calc_default_output_coef(csc_mode_cfg, &out_matrix, &out_dc);
1232
1233 csc_simple_coef->csc_coef00 = out_matrix.csc_coef00;
1234 csc_simple_coef->csc_coef01 = out_matrix.csc_coef01;
1235 csc_simple_coef->csc_coef02 = out_matrix.csc_coef02;
1236 csc_simple_coef->csc_coef10 = out_matrix.csc_coef10;
1237 csc_simple_coef->csc_coef11 = out_matrix.csc_coef11;
1238 csc_simple_coef->csc_coef12 = out_matrix.csc_coef12;
1239 csc_simple_coef->csc_coef20 = out_matrix.csc_coef20;
1240 csc_simple_coef->csc_coef21 = out_matrix.csc_coef21;
1241 csc_simple_coef->csc_coef22 = out_matrix.csc_coef22;
1242 csc_simple_coef->csc_dc0 = out_dc.csc_offset0;
1243 csc_simple_coef->csc_dc1 = out_dc.csc_offset1;
1244 csc_simple_coef->csc_dc2 = out_dc.csc_offset2;
1245
1246 csc_simple_coef->csc_dc0 = pq_csc_simple_round(csc_simple_coef->csc_dc0, bit_num);
1247 csc_simple_coef->csc_dc1 = pq_csc_simple_round(csc_simple_coef->csc_dc1, bit_num);
1248 csc_simple_coef->csc_dc2 = pq_csc_simple_round(csc_simple_coef->csc_dc2, bit_num);
1249 csc_simple_coef->range_type = csc_mode_cfg->st_csc_color_info.out_full_range;
1250
1251 return ret;
1252 }
1253
calc_dsp_frm_hst_vst(const struct drm_display_mode * src,const struct drm_display_mode * dst,u32 * dsp_frame_hst,u32 * dsp_frame_vst)1254 static void calc_dsp_frm_hst_vst(const struct drm_display_mode *src,
1255 const struct drm_display_mode *dst,
1256 u32 *dsp_frame_hst,
1257 u32 *dsp_frame_vst)
1258 {
1259 u32 bp_in, bp_out;
1260 u32 v_scale_ratio;
1261 u64 t_frm_st;
1262 u64 t_bp_in, t_bp_out, t_delta, tin;
1263 u32 src_pixclock, dst_pixclock;
1264 u32 dst_htotal, dst_hsync_len, dst_hback_porch;
1265 u32 dst_vsync_len, dst_vback_porch, dst_vactive;
1266 u32 src_htotal, src_hsync_len, src_hback_porch;
1267 u32 src_vtotal, src_vsync_len, src_vback_porch, src_vactive;
1268 u32 rem;
1269 u32 x;
1270
1271 src_pixclock = div_u64(1000000000llu, src->clock);
1272 dst_pixclock = div_u64(1000000000llu, dst->clock);
1273
1274 src_hsync_len = src->hsync_end - src->hsync_start;
1275 src_hback_porch = src->htotal - src->hsync_end;
1276 src_htotal = src->htotal;
1277 src_vsync_len = src->vsync_end - src->vsync_start;
1278 src_vback_porch = src->vtotal - src->vsync_end;
1279 src_vactive = src->vdisplay;
1280 src_vtotal = src->vtotal;
1281
1282 dst_hsync_len = dst->hsync_end - dst->hsync_start;
1283 dst_hback_porch = dst->htotal - dst->hsync_end;
1284 dst_htotal = dst->htotal;
1285 dst_vsync_len = dst->vsync_end - dst->vsync_start;
1286 dst_vback_porch = dst->vtotal - dst->vsync_end;
1287 dst_vactive = dst->vdisplay;
1288
1289 bp_in = (src_vback_porch + src_vsync_len) * src_htotal +
1290 src_hsync_len + src_hback_porch;
1291 bp_out = (dst_vback_porch + dst_vsync_len) * dst_htotal +
1292 dst_hsync_len + dst_hback_porch;
1293
1294 t_bp_in = bp_in * src_pixclock;
1295 t_bp_out = bp_out * dst_pixclock;
1296 tin = src_vtotal * src_htotal * src_pixclock;
1297
1298 v_scale_ratio = src_vactive / dst_vactive;
1299 x = 5;
1300 __retry:
1301 if (v_scale_ratio <= 2)
1302 t_delta = x * src_htotal * src_pixclock;
1303 else
1304 t_delta = 12 * src_htotal * src_pixclock;
1305
1306 if (t_bp_in + t_delta > t_bp_out)
1307 t_frm_st = (t_bp_in + t_delta - t_bp_out);
1308 else
1309 t_frm_st = tin - (t_bp_out - (t_bp_in + t_delta));
1310
1311 do_div(t_frm_st, src_pixclock);
1312 rem = do_div(t_frm_st, src_htotal);
1313 if ((t_frm_st < 2 || t_frm_st > 14) && x < 12) {
1314 x++;
1315 goto __retry;
1316 }
1317 if (t_frm_st < 2 || t_frm_st > 14)
1318 t_frm_st = 4;
1319
1320 *dsp_frame_hst = rem;
1321 *dsp_frame_vst = t_frm_st;
1322 }
1323
rk628_post_process_scaler_init(struct rk628 * rk628,struct drm_display_mode * src,const struct drm_display_mode * dst)1324 static void rk628_post_process_scaler_init(struct rk628 *rk628,
1325 struct drm_display_mode *src,
1326 const struct drm_display_mode *dst)
1327 {
1328 u32 dsp_frame_hst, dsp_frame_vst;
1329 u32 scl_hor_mode, scl_ver_mode;
1330 u32 scl_v_factor, scl_h_factor;
1331 u32 dsp_htotal, dsp_hs_end, dsp_hact_st, dsp_hact_end;
1332 u32 dsp_vtotal, dsp_vs_end, dsp_vact_st, dsp_vact_end;
1333 u32 dsp_hbor_end, dsp_hbor_st, dsp_vbor_end, dsp_vbor_st;
1334 u16 bor_right = 0, bor_left = 0, bor_up = 0, bor_down = 0;
1335 u8 hor_down_mode = 0, ver_down_mode = 0;
1336 u32 dst_hsync_len, dst_hback_porch, dst_hfront_porch, dst_hactive;
1337 u32 dst_vsync_len, dst_vback_porch, dst_vfront_porch, dst_vactive;
1338 u32 src_hactive;
1339 u32 src_vactive;
1340 int gvi_offset = 0;
1341
1342 if (rk628->version == RK628F_VERSION && rk628->gvi.division_mode)
1343 gvi_offset = 4;
1344
1345 src_hactive = src->hdisplay;
1346 src_vactive = src->vdisplay;
1347
1348 dst_hactive = dst->hdisplay;
1349 dst_hsync_len = dst->hsync_end - dst->hsync_start;
1350 dst_hback_porch = dst->htotal - dst->hsync_end;
1351 dst_hfront_porch = dst->hsync_start - dst->hdisplay;
1352 dst_vsync_len = dst->vsync_end - dst->vsync_start;
1353 dst_vback_porch = dst->vtotal - dst->vsync_end;
1354 dst_vfront_porch = dst->vsync_start - dst->vdisplay;
1355 dst_vactive = dst->vdisplay;
1356
1357 dsp_htotal = dst_hsync_len + dst_hback_porch +
1358 dst_hactive + dst_hfront_porch;
1359 dsp_vtotal = dst_vsync_len + dst_vback_porch +
1360 dst_vactive + dst_vfront_porch;
1361 dsp_hs_end = dst_hsync_len;
1362 dsp_vs_end = dst_vsync_len;
1363 dsp_hbor_end = dst_hsync_len + dst_hback_porch + dst_hactive - gvi_offset;
1364 dsp_hbor_st = dst_hsync_len + dst_hback_porch - gvi_offset;
1365 dsp_vbor_end = dst_vsync_len + dst_vback_porch + dst_vactive;
1366 dsp_vbor_st = dst_vsync_len + dst_vback_porch;
1367 dsp_hact_st = dsp_hbor_st + bor_left;
1368 dsp_hact_end = dsp_hbor_end - bor_right;
1369 dsp_vact_st = dsp_vbor_st + bor_up;
1370 dsp_vact_end = dsp_vbor_end - bor_down;
1371
1372 calc_dsp_frm_hst_vst(src, dst, &dsp_frame_hst, &dsp_frame_vst);
1373 printf("rk628 dsp_frame_vst:%d dsp_frame_hst:%d\n",
1374 dsp_frame_vst, dsp_frame_hst);
1375
1376 if (src_hactive > dst_hactive) {
1377 scl_hor_mode = 2;
1378
1379 if (hor_down_mode == 0) {
1380 if ((src_hactive - 1) / (dst_hactive - 1) > 2)
1381 scl_h_factor = ((src_hactive - 1) << 14) /
1382 (dst_hactive - 1);
1383 else
1384 scl_h_factor = ((src_hactive - 2) << 14) /
1385 (dst_hactive - 1);
1386 } else {
1387 scl_h_factor = (dst_hactive << 16) / (src_hactive - 1);
1388 }
1389
1390 } else if (src_hactive == dst_hactive) {
1391 scl_hor_mode = 0;
1392 scl_h_factor = 0;
1393 } else {
1394 scl_hor_mode = 1;
1395 scl_h_factor = ((src_hactive - 1) << 16) / (dst_hactive - 1);
1396 }
1397
1398 if (src_vactive > dst_vactive) {
1399 scl_ver_mode = 2;
1400
1401 if (ver_down_mode == 0) {
1402 if ((src_vactive - 1) / (dst_vactive - 1) > 2)
1403 scl_v_factor = ((src_vactive - 1) << 14) /
1404 (dst_vactive - 1);
1405 else
1406 scl_v_factor = ((src_vactive - 2) << 14) /
1407 (dst_vactive - 1);
1408 } else {
1409 scl_v_factor = (dst_vactive << 16) / (src_vactive - 1);
1410 }
1411
1412 } else if (src_vactive == dst_vactive) {
1413 scl_ver_mode = 0;
1414 scl_v_factor = 0;
1415 } else {
1416 scl_ver_mode = 1;
1417 scl_v_factor = ((src_vactive - 1) << 16) / (dst_vactive - 1);
1418 }
1419
1420 rk628_i2c_update_bits(rk628, GRF_RGB_DEC_CON0, SW_HRES_MASK,
1421 SW_HRES(src_hactive));
1422 rk628_i2c_write(rk628, GRF_SCALER_CON0, SCL_VER_DOWN_MODE(ver_down_mode) |
1423 SCL_HOR_DOWN_MODE(hor_down_mode) |
1424 SCL_VER_MODE(scl_ver_mode) |
1425 SCL_HOR_MODE(scl_hor_mode));
1426 rk628_i2c_write(rk628, GRF_SCALER_CON1, SCL_V_FACTOR(scl_v_factor) |
1427 SCL_H_FACTOR(scl_h_factor));
1428 rk628_i2c_write(rk628, GRF_SCALER_CON2, DSP_FRAME_VST(dsp_frame_vst) |
1429 DSP_FRAME_HST(dsp_frame_hst));
1430 rk628_i2c_write(rk628, GRF_SCALER_CON3, DSP_HS_END(dsp_hs_end) |
1431 DSP_HTOTAL(dsp_htotal));
1432 rk628_i2c_write(rk628, GRF_SCALER_CON4, DSP_HACT_END(dsp_hact_end) |
1433 DSP_HACT_ST(dsp_hact_st));
1434 rk628_i2c_write(rk628, GRF_SCALER_CON5, DSP_VS_END(dsp_vs_end) |
1435 DSP_VTOTAL(dsp_vtotal));
1436 rk628_i2c_write(rk628, GRF_SCALER_CON6, DSP_VACT_END(dsp_vact_end) |
1437 DSP_VACT_ST(dsp_vact_st));
1438 rk628_i2c_write(rk628, GRF_SCALER_CON7, DSP_HBOR_END(dsp_hbor_end) |
1439 DSP_HBOR_ST(dsp_hbor_st));
1440 rk628_i2c_write(rk628, GRF_SCALER_CON8, DSP_VBOR_END(dsp_vbor_end) |
1441 DSP_VBOR_ST(dsp_vbor_st));
1442 }
1443
rk628_post_process_init(struct rk628 * rk628)1444 void rk628_post_process_init(struct rk628 *rk628)
1445 {
1446 struct drm_display_mode *src = &rk628->src_mode;
1447 const struct drm_display_mode *dst = &rk628->dst_mode;
1448 u64 dst_rate, src_rate;
1449
1450 src_rate = src->clock * 1000;
1451 dst_rate = src_rate * dst->vtotal * dst->htotal;
1452 do_div(dst_rate, (src->vtotal * src->htotal));
1453 do_div(dst_rate, 1000);
1454 printf("rk628 src %dx%d clock:%d\n",
1455 src->hdisplay, src->vdisplay, src->clock);
1456
1457 printf("rk628 dst %dx%d clock:%llu\n",
1458 dst->hdisplay, dst->vdisplay, dst_rate);
1459
1460 rk628_cru_clk_set_rate(rk628, CGU_CLK_RX_READ, src->clock * 1000);
1461 rk628_cru_clk_set_rate(rk628, CGU_SCLK_VOP, dst_rate * 1000);
1462
1463 if (rk628_output_is_hdmi(rk628)) {
1464 rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_VSYNC_POL_MASK,
1465 SW_VSYNC_POL(rk628->sync_pol));
1466 rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0, SW_HSYNC_POL_MASK,
1467 SW_HSYNC_POL(rk628->sync_pol));
1468 } else {
1469 if (src->flags & DRM_MODE_FLAG_PVSYNC)
1470 rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0,
1471 SW_VSYNC_POL_MASK, SW_VSYNC_POL(1));
1472 if (src->flags & DRM_MODE_FLAG_PHSYNC)
1473 rk628_i2c_update_bits(rk628, GRF_SYSTEM_CON0,
1474 SW_HSYNC_POL_MASK,
1475 SW_HSYNC_POL(1));
1476 }
1477
1478 rk628_post_process_scaler_init(rk628, src, dst);
1479 }
1480
rk628_post_process_csc(struct rk628 * rk628)1481 static void rk628_post_process_csc(struct rk628 *rk628)
1482 {
1483 enum bus_format in_fmt, out_fmt;
1484 struct post_csc_coef csc_coef = {};
1485 bool is_input_yuv, is_output_yuv;
1486 u32 color_space = V4L2_COLORSPACE_DEFAULT;
1487 u32 csc_mode;
1488 u32 val;
1489 int range_type;
1490
1491 in_fmt = rk628_get_input_bus_format(rk628);
1492 out_fmt = rk628_get_output_bus_format(rk628);
1493
1494 if (in_fmt == out_fmt) {
1495 if (out_fmt == BUS_FMT_YUV422) {
1496 rk628_i2c_write(rk628, GRF_CSC_CTRL_CON,
1497 SW_YUV2VYU_SWP(1) |
1498 SW_R2Y_EN(0));
1499 return;
1500 }
1501 rk628_i2c_write(rk628, GRF_CSC_CTRL_CON, SW_R2Y_EN(0));
1502 rk628_i2c_write(rk628, GRF_CSC_CTRL_CON, SW_Y2R_EN(0));
1503 return;
1504 }
1505
1506 if (rk628->version == RK628D_VERSION) {
1507 if (in_fmt == BUS_FMT_RGB)
1508 rk628_i2c_write(rk628, GRF_CSC_CTRL_CON, SW_R2Y_EN(1));
1509 else if (out_fmt == BUS_FMT_RGB)
1510 rk628_i2c_write(rk628, GRF_CSC_CTRL_CON, SW_Y2R_EN(1));
1511 } else {
1512 csc_mode = vop2_convert_csc_mode(color_space, CSC_13BIT_DEPTH);
1513
1514 is_input_yuv = !is_rgb_format(in_fmt);
1515 is_output_yuv = !is_rgb_format(out_fmt);
1516 rockchip_calc_post_csc(&csc_coef, csc_mode, is_input_yuv, is_output_yuv);
1517
1518 val = ((csc_coef.csc_coef01 & 0xffff) << 16) | (csc_coef.csc_coef00 & 0xffff);
1519 rk628_i2c_write(rk628, GRF_CSC_MATRIX_COE01_COE00, val);
1520
1521 val = ((csc_coef.csc_coef10 & 0xffff) << 16) | (csc_coef.csc_coef02 & 0xffff);
1522 rk628_i2c_write(rk628, GRF_CSC_MATRIX_COE10_COE02, val);
1523
1524 val = ((csc_coef.csc_coef12 & 0xffff) << 16) | (csc_coef.csc_coef11 & 0xffff);
1525 rk628_i2c_write(rk628, GRF_CSC_MATRIX_COE12_COE11, val);
1526
1527 val = ((csc_coef.csc_coef21 & 0xffff) << 16) | (csc_coef.csc_coef20 & 0xffff);
1528 rk628_i2c_write(rk628, GRF_CSC_MATRIX_COE21_COE20, val);
1529
1530 rk628_i2c_write(rk628, GRF_CSC_MATRIX_COE22, csc_coef.csc_coef22);
1531
1532 rk628_i2c_write(rk628, GRF_CSC_MATRIX_OFFSET0, csc_coef.csc_dc0);
1533 rk628_i2c_write(rk628, GRF_CSC_MATRIX_OFFSET1, csc_coef.csc_dc1);
1534 rk628_i2c_write(rk628, GRF_CSC_MATRIX_OFFSET2, csc_coef.csc_dc2);
1535
1536 range_type = csc_coef.range_type ? 0 : 1;
1537 range_type <<= is_input_yuv ? 0 : 1;
1538 val = SW_Y2R_MODE(range_type) | SW_FROM_CSC_MATRIX_EN(1);
1539 rk628_i2c_write(rk628, GRF_CSC_CTRL_CON, val);
1540
1541 if (rk628_output_is_bt1120(rk628))
1542 rk628_i2c_write(rk628, GRF_CSC_CTRL_CON, SW_YUV2VYU_SWP(1));
1543 }
1544 }
1545
rk628_post_process_enable(struct rk628 * rk628)1546 void rk628_post_process_enable(struct rk628 *rk628)
1547 {
1548 #if 0
1549 /*
1550 * bt1120 needs to configure the timing register, but hdmitx will modify
1551 * the timing as needed, so the bt1120 enable process is moved here.
1552 */
1553 if (rk628_input_is_bt1120(rk628))
1554 rk628_bt1120_rx_enable(rk628);
1555 #endif
1556 rk628_post_process_csc(rk628);
1557 rk628_i2c_write(rk628, GRF_SCALER_CON0, SCL_EN(1));
1558 }
1559
rk628_post_process_disable(struct rk628 * rk628)1560 void rk628_post_process_disable(struct rk628 *rk628)
1561 {
1562 rk628_i2c_write(rk628, GRF_SCALER_CON0, SCL_EN(0));
1563 }
1564