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