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