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