drm/rockchip: fix some csc parameters error

1. Fix the csc matrix. For YUV709L to YUV709L, YUV601L to
YUV601L, YUV2020L to YUV2020L, The csc matrix should be
identity matrix. For YUV601L to YUV709L, modeify the csc
matrix.
2. optimize the final calculation result. Use the new r2y
and y2r matrix for csc yuv2yuv and rgb2rgb case. A simple
round is used for csc yuv2yuv and rgb2rgb case for a more
precise result.

Change-Id: I51f1b597c2aa3edcb66bc359df709b9b61a97b52
Signed-off-by: Zhang Yubing <yubing.zhang@rock-chips.com>
This commit is contained in:
Zhang Yubing
2024-08-16 16:52:48 +08:00
committed by Tao Huang
parent 0cb1f2340c
commit 9ce43aae96

View File

@@ -207,6 +207,13 @@ static const struct rk_pq_csc_dc_coef rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsd
/* xv_ycc BT.601 (i.e. SD) -> to BT.709 (i.e. HD) */
static const struct rk_pq_csc_coef rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr = {
1024, -118, -213,
0, 1043, 117,
0, 77, 1050
};
/* xv_ycc BT.601 full(i.e. SD) -> to BT.709 full(i.e. HD) */
static const struct rk_pq_csc_coef rk_csc_table_xv_yccsdy_cb_cr_full_to_hdy_cb_cr_full = {
1024, -121, -218,
0, 1043, 117,
0, 77, 1050
@@ -642,7 +649,7 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = {
},
{
RK_PQ_CSC_YUV2YUV, "YUV L->YUV L",
&rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
&rk_csc_table_identity_y_cb_cr_to_y_cb_cr,
&rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
{
OPTM_CS_E_ITU_R_BT_709, OPTM_CS_E_ITU_R_BT_709, false, false
@@ -690,7 +697,7 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = {
},
{
RK_PQ_CSC_YUV2YUV_601_709_FULL, "YUV601 F->YUV709 F",
&rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
&rk_csc_table_xv_yccsdy_cb_cr_full_to_hdy_cb_cr_full,
&rk_dc_csc_table_hdy_cb_cr_full_to_xv_yccsdy_cb_cr_full,
{
OPTM_CS_E_XV_YCC_601, OPTM_CS_E_ITU_R_BT_709, true, true
@@ -890,7 +897,7 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = {
},
{
RK_PQ_CSC_YUV2YUV, "YUV 601 L->YUV 601 L",
&rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
&rk_csc_table_identity_y_cb_cr_to_y_cb_cr,
&rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
{
OPTM_CS_E_XV_YCC_601, OPTM_CS_E_XV_YCC_601, false, false
@@ -922,7 +929,7 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = {
},
{
RK_PQ_CSC_YUV2YUV, "YUV 2020 L->YUV 2020 L",
&rk_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
&rk_csc_table_identity_y_cb_cr_to_y_cb_cr,
&rk_dc_csc_table_xv_yccsdy_cb_cr_to_hdy_cb_cr,
{
OPTM_CS_E_XV_YCC_2020, OPTM_CS_E_XV_YCC_2020, false, false
@@ -988,14 +995,26 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = {
static const struct rk_pq_csc_coef r2y_for_y2y = {
306, 601, 117,
-151, -296, 446,
630, -527, -102,
-173, -339, 512,
512, -429, -83,
};
static const struct rk_pq_csc_coef y2r_for_y2y = {
1024, -0, 1167,
1024, -404, -594,
1024, 2081, -1,
1024, -1, 1436,
1024, -353, -731,
1024, 1814, 1,
};
static const struct rk_pq_csc_coef r2y_for_r2r = {
1024, 0, 1612,
1024, -192, -480,
1024, 1900, -2,
};
static const struct rk_pq_csc_coef y2r_for_r2r = {
218, 732, 74,
-117, -395, 512,
512, -465, -47,
};
static const struct rk_pq_csc_coef rgb_input_swap_matrix = {
@@ -1124,7 +1143,7 @@ static void csc_matrix_ventor_multiply(struct rk_pq_csc_ventor *dst,
m0->csc_coef22 * v0->csc_offset2;
}
static void csc_matrix_element_left_shift(struct rk_pq_csc_coef *m, int n)
static void csc_matrix_element_right_shift(struct rk_pq_csc_coef *m, int n)
{
m->csc_coef00 = m->csc_coef00 >> n;
m->csc_coef01 = m->csc_coef01 >> n;
@@ -1137,6 +1156,30 @@ static void csc_matrix_element_left_shift(struct rk_pq_csc_coef *m, int n)
m->csc_coef22 = m->csc_coef22 >> n;
}
static inline s32 csc_simple_round(s32 x, s32 n)
{
s32 value = 0;
if (n == 0)
return x;
value = (abs(x) + (1 << (n - 1))) >> (n);
return (((x) >= 0) ? value : -value);
}
static void csc_matrix_element_right_shift_with_simple_round(struct rk_pq_csc_coef *m, int n)
{
m->csc_coef00 = csc_simple_round(m->csc_coef00, n);
m->csc_coef01 = csc_simple_round(m->csc_coef01, n);
m->csc_coef02 = csc_simple_round(m->csc_coef02, n);
m->csc_coef10 = csc_simple_round(m->csc_coef10, n);
m->csc_coef11 = csc_simple_round(m->csc_coef11, n);
m->csc_coef12 = csc_simple_round(m->csc_coef12, n);
m->csc_coef20 = csc_simple_round(m->csc_coef20, n);
m->csc_coef21 = csc_simple_round(m->csc_coef21, n);
m->csc_coef22 = csc_simple_round(m->csc_coef22, n);
}
static struct rk_pq_csc_coef create_rgb_gain_matrix(s32 r_gain, s32 g_gain, s32 b_gain)
{
struct rk_pq_csc_coef m;
@@ -1280,23 +1323,23 @@ static int csc_calc_adjust_output_coef(bool is_input_yuv, bool is_output_yuv,
csc_matrix_multiply(&temp0, csc_mode_cfg->pst_csc_coef, &hue_matrix);
/*
* The value bits width is 32 bit, so every time 2 matirx multifly,
* left shift is necessary to avoid overflow. For enhancing the
* right shift is necessary to avoid overflow. For enhancing the
* calculator precision, PQ_CALC_ENHANCE_BIT bits is reserved and
* left shift before get the final result.
* right shift before get the final result.
*/
csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH -
PQ_CALC_ENHANCE_BIT);
csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH -
PQ_CALC_ENHANCE_BIT);
csc_matrix_multiply(&temp1, &temp0, &saturation_matrix);
csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_multiply(&temp0, &temp1, r2y_matrix);
csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH);
csc_matrix_multiply(&temp1, &temp0, &gain_matrix);
csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_multiply(&temp0, &temp1, &contrast_matrix);
csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_multiply(out_matrix, &temp0, y2r_matrix);
csc_matrix_element_left_shift(out_matrix, PQ_CSC_PARAM_FIX_BIT_WIDTH +
PQ_CALC_ENHANCE_BIT);
csc_matrix_element_right_shift_with_simple_round(out_matrix,
PQ_CSC_PARAM_FIX_BIT_WIDTH + PQ_CALC_ENHANCE_BIT);
dc_in_ventor.csc_offset0 = dc_in_offset;
dc_in_ventor.csc_offset1 = -PQ_CSC_DC_IN_OUT_DEFAULT;
@@ -1311,15 +1354,15 @@ static int csc_calc_adjust_output_coef(bool is_input_yuv, bool is_output_yuv,
* hue_matrix * saturation_matrix
*/
csc_matrix_multiply(&temp0, csc_mode_cfg->pst_csc_coef, &hue_matrix);
csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH -
PQ_CALC_ENHANCE_BIT);
csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH -
PQ_CALC_ENHANCE_BIT);
csc_matrix_multiply(&temp1, &temp0, &saturation_matrix);
csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_multiply(&temp0, &contrast_matrix, &temp1);
csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_multiply(out_matrix, &gain_matrix, &temp0);
csc_matrix_element_left_shift(out_matrix, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH +
PQ_CALC_ENHANCE_BIT);
csc_matrix_element_right_shift(out_matrix, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH +
PQ_CALC_ENHANCE_BIT);
dc_in_ventor.csc_offset0 = dc_in_offset;
dc_in_ventor.csc_offset1 = -PQ_CSC_DC_IN_OUT_DEFAULT;
@@ -1334,15 +1377,15 @@ static int csc_calc_adjust_output_coef(bool is_input_yuv, bool is_output_yuv,
* gain_matrix * contrast_matrix
*/
csc_matrix_multiply(&temp0, csc_mode_cfg->pst_csc_coef, &gain_matrix);
csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH -
PQ_CALC_ENHANCE_BIT);
csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH -
PQ_CALC_ENHANCE_BIT);
csc_matrix_multiply(&temp1, &temp0, &contrast_matrix);
csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_multiply(&temp0, &saturation_matrix, &temp1);
csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_multiply(out_matrix, &hue_matrix, &temp0);
csc_matrix_element_left_shift(out_matrix, PQ_CSC_PARAM_FIX_BIT_WIDTH +
PQ_CALC_ENHANCE_BIT);
csc_matrix_element_right_shift(out_matrix, PQ_CSC_PARAM_FIX_BIT_WIDTH +
PQ_CALC_ENHANCE_BIT);
dc_in_ventor.csc_offset0 = dc_in_offset;
dc_in_ventor.csc_offset1 = dc_in_offset;
@@ -1356,35 +1399,21 @@ static int csc_calc_adjust_output_coef(bool is_input_yuv, bool is_output_yuv,
* so output = T * gain_matrix * contrast_matrix *
* N_y2r * hue_matrix * saturation_matrix * N_r2y
*/
if (!color_info->in_full_range && color_info->out_full_range) {
r2y_matrix = &rk_csc_table_rgb_limit_to_hdy_cb_cr;
y2r_matrix = &rk_csc_table_hdy_cb_cr_limit_to_rgb_full;
} else if (color_info->in_full_range && !color_info->out_full_range) {
r2y_matrix = &rk_csc_table_rgb_to_hdy_cb_cr;
y2r_matrix = &rk_csc_table_hdy_cb_cr_limit_to_rgb_limit;
} else if (color_info->in_full_range && color_info->out_full_range) {
r2y_matrix = &rk_csc_table_rgb_to_hdy_cb_cr_full;
y2r_matrix = &rk_csc_table_hdy_cb_cr_to_rgb_full;
} else {
r2y_matrix = &rk_csc_table_rgb_limit_to_hdy_cb_cr;
y2r_matrix = &rk_csc_table_hdy_cb_cr_limit_to_rgb_limit;
}
r2y_matrix = &r2y_for_r2r;
y2r_matrix = &y2r_for_r2r;
csc_matrix_multiply(&temp0, &contrast_matrix, y2r_matrix);
csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH -
PQ_CALC_ENHANCE_BIT);
csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH -
PQ_CALC_ENHANCE_BIT);
csc_matrix_multiply(&temp1, &gain_matrix, &temp0);
csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_multiply(&temp0, &temp1, &hue_matrix);
csc_matrix_element_left_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp0, PQ_CSC_PARAM_FIX_BIT_WIDTH);
csc_matrix_multiply(&temp1, &temp0, &saturation_matrix);
csc_matrix_element_left_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_element_right_shift(&temp1, PQ_CSC_PARAM_HALF_FIX_BIT_WIDTH);
csc_matrix_multiply(out_matrix, &temp1, r2y_matrix);
csc_matrix_element_left_shift(out_matrix, PQ_CSC_PARAM_FIX_BIT_WIDTH +
PQ_CALC_ENHANCE_BIT);
if (color_info->in_full_range && color_info->out_full_range)
out_matrix->csc_coef00 += 1;
csc_matrix_element_right_shift_with_simple_round(out_matrix,
PQ_CSC_PARAM_FIX_BIT_WIDTH + PQ_CALC_ENHANCE_BIT);
dc_in_ventor.csc_offset0 = dc_in_offset;
dc_in_ventor.csc_offset1 = dc_in_offset;
@@ -1522,9 +1551,9 @@ int rockchip_calc_post_csc(struct post_csc *csc_cfg, struct post_csc_coef *csc_s
rockchip_swap_color_channel(convert_mode->is_input_yuv, convert_mode->is_output_yuv,
csc_simple_coef, &out_matrix, &out_dc);
csc_simple_coef->csc_dc0 = pq_csc_simple_round(csc_simple_coef->csc_dc0, bit_num);
csc_simple_coef->csc_dc1 = pq_csc_simple_round(csc_simple_coef->csc_dc1, bit_num);
csc_simple_coef->csc_dc2 = pq_csc_simple_round(csc_simple_coef->csc_dc2, bit_num);
csc_simple_coef->csc_dc0 = csc_simple_round(csc_simple_coef->csc_dc0, bit_num);
csc_simple_coef->csc_dc1 = csc_simple_round(csc_simple_coef->csc_dc1, bit_num);
csc_simple_coef->csc_dc2 = csc_simple_round(csc_simple_coef->csc_dc2, bit_num);
csc_simple_coef->range_type = csc_mode_cfg->st_csc_color_info.out_full_range;
return ret;