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