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