xref: /rk3399_rockchip-uboot/drivers/video/drm/rk628/rk628_post_process.c (revision ab3bc87339b1566ceabcfb54995e11928492c356)
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