From 2e4cd35f068704b5c182d4fa4ef1efb942049074 Mon Sep 17 00:00:00 2001 From: Algea Cao Date: Tue, 11 Mar 2025 16:34:13 +0800 Subject: [PATCH] drm/rockchip: vop2: update color-encoding selection policy for post-csc When all layers are rgb, the post-csc input color encoding is fixed to rgb full, and the value of input_color_encoding has no actual utility. If there are any yuv planes, value of post-csc input_color_encoding selects the value of the yuv plane with the largest area. Change-Id: If624730e93a5ac03fc334890074883b9e6b828eb Signed-off-by: Algea Cao --- drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 3 +- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 37 +++++++++++++---- drivers/gpu/drm/rockchip/rockchip_post_csc.c | 43 ++++++++++++-------- 3 files changed, 57 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 2c7148002009..5f5ea7ccfcac 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -698,7 +698,8 @@ enum vop_hdr_format { }; struct post_csc_convert_mode { - enum drm_color_encoding color_encoding; + enum drm_color_encoding intput_color_encoding; + enum drm_color_encoding output_color_encoding; bool is_input_yuv; bool is_output_yuv; bool is_input_full_range; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index 2e733ebe4950..02f4cc262046 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -12844,23 +12844,33 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st struct rockchip_crtc_state *vcstate = to_rockchip_crtc_state(crtc->state); struct vop2 *vop2 = vp->vop2; struct drm_plane *plane; - struct drm_plane_state *pstate; + struct drm_plane_state *pstate, *pstate_max = NULL; + struct vop2_plane_state *vpstate; struct post_csc_coef csc_coef = {}; struct post_csc_convert_mode convert_mode = {}; + struct drm_rect *dest; bool acm_enable; bool post_r2y_en = false; bool post_csc_en = false; - bool has_yuv_plane = false; int range_type; + u64 max_yuv_plane = 0, plane_area; + enum drm_color_encoding max_yuv_plane_color_encoding = DRM_COLOR_YCBCR_BT601; drm_atomic_crtc_for_each_plane(plane, crtc) { struct vop2_win *win = to_vop2_win(plane); pstate = win->base.state; + vpstate = to_vop2_plane_state(pstate); + dest = &vpstate->dest; if (pstate->fb->format->is_yuv) { - has_yuv_plane = true; - break; + plane_area = drm_rect_width(dest) * drm_rect_height(dest); + /* find yuv plane with largest area */ + if (max_yuv_plane < plane_area) { + max_yuv_plane = plane_area; + max_yuv_plane_color_encoding = pstate->color_encoding; + pstate_max = pstate; + } } } @@ -12898,9 +12908,9 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st convert_mode.is_input_full_range = true; else if (vcstate->yuv_overlay) convert_mode.is_input_full_range = false; - else if (has_yuv_plane) + else if (pstate_max) convert_mode.is_input_full_range = - pstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; + pstate_max->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; else convert_mode.is_input_full_range = vcstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; @@ -12911,10 +12921,19 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st vcstate->post_csc_mode = vop2_convert_csc_mode(vcstate->color_encoding, vcstate->color_range, CSC_13BIT_DEPTH); if (post_csc_en) { - if (has_yuv_plane) - convert_mode.color_encoding = pstate->color_encoding; + convert_mode.output_color_encoding = vcstate->color_encoding; + /* + * When all layers are rgb, the post-csc input color encoding + * is fixed to rgb full, and the value of input_color_encoding + * has no actual utility. + * If there are any yuv planes, value of post-csc input_color_encoding + * selects the value of the yuv plane with the largest area. + */ + if (!pstate_max && !vcstate->yuv_overlay) + convert_mode.intput_color_encoding = vcstate->color_encoding; else - convert_mode.color_encoding = vcstate->color_encoding; + convert_mode.intput_color_encoding = max_yuv_plane_color_encoding; + rockchip_calc_post_csc(csc, &csc_coef, &convert_mode); VOP_MODULE_SET(vop2, vp, csc_coe00, csc_coef.csc_coef00); diff --git a/drivers/gpu/drm/rockchip/rockchip_post_csc.c b/drivers/gpu/drm/rockchip/rockchip_post_csc.c index 7a7838b27648..98efbbc70b4b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_post_csc.c +++ b/drivers/gpu/drm/rockchip/rockchip_post_csc.c @@ -1063,24 +1063,37 @@ enum color_space_type get_color_space_type(enum drm_color_encoding color_encodin return color_space_type; } -static int csc_get_mode_index(bool is_input_full_range, bool is_output_full_range, - bool is_input_yuv, bool is_output_yuv, - enum drm_color_encoding color_encoding) +static int csc_get_mode_index(struct post_csc_convert_mode *convert_mode) { const struct rk_csc_colorspace_info *colorspace_info; - int i; + int i, j; enum color_space_type input_color_space, output_color_space; + bool is_input_full_range = convert_mode->is_input_full_range; + bool is_output_full_range = convert_mode->is_output_full_range; + bool is_input_yuv = convert_mode->is_input_yuv; + bool is_output_yuv = convert_mode->is_output_yuv; - input_color_space = get_color_space_type(color_encoding, is_input_yuv); - output_color_space = get_color_space_type(color_encoding, is_output_yuv); + for (i = 0; i < 2; i++) { + input_color_space = get_color_space_type(convert_mode->intput_color_encoding, + is_input_yuv); + output_color_space = get_color_space_type(convert_mode->output_color_encoding, + is_output_yuv); - for (i = 0; i < ARRAY_SIZE(g_mode_csc_coef); i++) { - colorspace_info = &g_mode_csc_coef[i].st_csc_color_info; - if (colorspace_info->input_color_space == input_color_space && - colorspace_info->output_color_space == output_color_space && - colorspace_info->in_full_range == is_input_full_range && - colorspace_info->out_full_range == is_output_full_range) - return i; + for (j = 0; j < ARRAY_SIZE(g_mode_csc_coef); j++) { + colorspace_info = &g_mode_csc_coef[j].st_csc_color_info; + if (colorspace_info->input_color_space == input_color_space && + colorspace_info->output_color_space == output_color_space && + colorspace_info->in_full_range == is_input_full_range && + colorspace_info->out_full_range == is_output_full_range) + return j; + } + + /* + * If no csc matrix can be found for current input/output + * colorspace of post-csc, then csc matrix is found based + * on colorspace of post-csc output. + */ + convert_mode->intput_color_encoding = convert_mode->output_color_encoding; } return -EINVAL; @@ -1529,9 +1542,7 @@ int rockchip_calc_post_csc(struct post_csc *csc_cfg, struct post_csc_coef *csc_s const struct rk_csc_mode_coef *csc_mode_cfg; int bit_num = PQ_CSC_SIMPLE_MAT_PARAM_FIX_BIT_WIDTH; - ret = csc_get_mode_index(convert_mode->is_input_full_range, - convert_mode->is_output_full_range, convert_mode->is_input_yuv, - convert_mode->is_output_yuv, convert_mode->color_encoding); + ret = csc_get_mode_index(convert_mode); if (ret < 0) { DRM_ERROR("get csc index err:\n"); DRM_ERROR("input yuv %d full_range %d,output yuv %d full_range %d\n",