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