diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h index 1233ace1bb38..f857f556d9c0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.h @@ -611,6 +611,14 @@ enum vop_hdr_format { HDR_FORMAT_MAX, }; +struct post_csc_convert_mode { + enum drm_color_encoding color_encoding; + bool is_input_yuv; + bool is_output_yuv; + bool is_input_full_range; + bool is_output_full_range; +}; + struct post_csc_coef { s32 csc_coef00; s32 csc_coef01; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c index e581794f72d7..b490a4c4f5f5 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c @@ -619,6 +619,12 @@ struct vop2_video_port { * */ bool skip_vsync; + /** + * @has_dci_enabled_win: Indicate dci enables on this vp. + * post csc input will be full range yuv. + * + */ + bool has_dci_enabled_win; /** * @bg_ovl_dly: The timing delay from background layer @@ -5300,6 +5306,13 @@ static int vop2_plane_atomic_check(struct drm_plane *plane, struct drm_atomic_st } vpstate->mst_end = rk_obj->dma_addr + rk_obj->size; + if (win->feature & WIN_FEATURE_DCI) { + if (vpstate->dci_data) + vp->has_dci_enabled_win = true; + else + vp->has_dci_enabled_win = false; + } + return 0; } @@ -10615,14 +10628,27 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st struct vop2_video_port *vp = to_vop2_video_port(crtc); 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 post_csc_coef csc_coef; + struct post_csc_convert_mode convert_mode; bool acm_enable; - bool is_input_yuv = false; - bool is_output_yuv = false; bool post_r2y_en = false; bool post_csc_en = false; + bool has_yuv_plane = false; int range_type; + drm_atomic_crtc_for_each_plane(plane, crtc) { + struct vop2_win *win = to_vop2_win(plane); + + pstate = win->base.state; + + if (pstate->fb->format->is_yuv) { + has_yuv_plane = true; + break; + } + } + if (!acm) acm_enable = false; else @@ -10648,16 +10674,31 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st post_csc_en = true; if (vcstate->yuv_overlay || post_r2y_en) - is_input_yuv = true; + convert_mode.is_input_yuv = true; if (is_yuv_output(vcstate->bus_format)) - is_output_yuv = true; + convert_mode.is_output_yuv = true; + + if (vp->has_dci_enabled_win) + convert_mode.is_input_full_range = true; + else if (has_yuv_plane) + convert_mode.is_input_full_range = + pstate->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; + + convert_mode.is_output_full_range = + vcstate->color_range == DRM_COLOR_YCBCR_FULL_RANGE ? 1 : 0; vcstate->post_csc_mode = vop2_convert_csc_mode(vcstate->color_encoding, vcstate->color_range, CSC_13BIT_DEPTH); if (post_csc_en) { - rockchip_calc_post_csc(csc, &csc_coef, vcstate->post_csc_mode, is_input_yuv, - is_output_yuv); + if (has_yuv_plane) + convert_mode.color_encoding = pstate->color_encoding; + else + convert_mode.color_encoding = vcstate->color_encoding; + rockchip_calc_post_csc(csc, &csc_coef, &convert_mode); VOP_MODULE_SET(vop2, vp, csc_coe00, csc_coef.csc_coef00); VOP_MODULE_SET(vop2, vp, csc_coe01, csc_coef.csc_coef01); @@ -10673,7 +10714,7 @@ static void vop3_post_csc_config(struct drm_crtc *crtc, struct post_acm *acm, st VOP_MODULE_SET(vop2, vp, csc_offset2, csc_coef.csc_dc2); range_type = csc_coef.range_type ? 0 : 1; - range_type <<= is_input_yuv ? 0 : 1; + range_type <<= convert_mode.is_input_yuv ? 0 : 1; VOP_MODULE_SET(vop2, vp, csc_mode, range_type); } diff --git a/drivers/gpu/drm/rockchip/rockchip_post_csc.c b/drivers/gpu/drm/rockchip/rockchip_post_csc.c index 4a583ba3bfdb..a57d562bf04f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_post_csc.c +++ b/drivers/gpu/drm/rockchip/rockchip_post_csc.c @@ -986,73 +986,6 @@ static const struct rk_csc_mode_coef g_mode_csc_coef[] = { }, }; -struct csc_mapping { - enum vop_csc_format csc_format; - enum color_space_type rgb_color_space; - enum color_space_type yuv_color_space; - bool rgb_full_range; - bool yuv_full_range; -}; - -static const struct csc_mapping csc_mapping_table[] = { - { - CSC_BT601L, - OPTM_CS_E_RGB, - OPTM_CS_E_XV_YCC_601, - true, - false, - }, - { - CSC_BT709L, - OPTM_CS_E_RGB, - OPTM_CS_E_XV_YCC_709, - true, - false, - }, - { - CSC_BT601F, - OPTM_CS_E_RGB, - OPTM_CS_E_XV_YCC_601, - true, - true, - }, - { - CSC_BT2020L, - OPTM_CS_E_RGB_2020, - OPTM_CS_E_XV_YCC_2020, - true, - true, - }, - { - CSC_BT709L_13BIT, - OPTM_CS_E_RGB, - OPTM_CS_E_XV_YCC_709, - true, - false, - }, - { - CSC_BT709F_13BIT, - OPTM_CS_E_RGB, - OPTM_CS_E_XV_YCC_709, - true, - true, - }, - { - CSC_BT2020L_13BIT, - OPTM_CS_E_RGB_2020, - OPTM_CS_E_XV_YCC_2020, - true, - false, - }, - { - CSC_BT2020F_13BIT, - OPTM_CS_E_RGB_2020, - OPTM_CS_E_XV_YCC_2020, - true, - true, - }, -}; - static const struct rk_pq_csc_coef r2y_for_y2y = { 306, 601, 117, -151, -296, 446, @@ -1077,30 +1010,50 @@ static const struct rk_pq_csc_coef yuv_output_swap_matrix = { 0, 1, 0, }; -static int csc_get_mode_index(int post_csc_mode, bool is_input_yuv, bool is_output_yuv) +static +enum color_space_type get_color_space_type(enum drm_color_encoding color_encoding, bool is_yuv) +{ + enum color_space_type color_space_type; + + switch (color_encoding) { + case DRM_COLOR_YCBCR_BT601: + if (is_yuv) + color_space_type = OPTM_CS_E_XV_YCC_601; + else + color_space_type = OPTM_CS_E_RGB; + break; + case DRM_COLOR_YCBCR_BT709: + if (is_yuv) + color_space_type = OPTM_CS_E_XV_YCC_709; + else + color_space_type = OPTM_CS_E_RGB; + break; + case DRM_COLOR_YCBCR_BT2020: + if (is_yuv) + color_space_type = OPTM_CS_E_XV_YCC_2020; + else + color_space_type = OPTM_CS_E_RGB_2020; + break; + default: + if (is_yuv) + color_space_type = OPTM_CS_E_XV_YCC_601; + else + color_space_type = OPTM_CS_E_RGB_2020; + } + + 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) { const struct rk_csc_colorspace_info *colorspace_info; - enum color_space_type input_color_space; - enum color_space_type output_color_space; - bool is_input_full_range; - bool is_output_full_range; int i; + enum color_space_type input_color_space, output_color_space; - for (i = 0; i < ARRAY_SIZE(csc_mapping_table); i++) { - if (post_csc_mode == csc_mapping_table[i].csc_format) { - input_color_space = is_input_yuv ? csc_mapping_table[i].yuv_color_space : - csc_mapping_table[i].rgb_color_space; - is_input_full_range = is_input_yuv ? csc_mapping_table[i].yuv_full_range : - csc_mapping_table[i].rgb_full_range; - output_color_space = is_output_yuv ? csc_mapping_table[i].yuv_color_space : - csc_mapping_table[i].rgb_color_space; - is_output_full_range = is_output_yuv ? csc_mapping_table[i].yuv_full_range : - csc_mapping_table[i].rgb_full_range; - break; - } - } - if (i >= ARRAY_SIZE(csc_mapping_table)) - return -EINVAL; + 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 < ARRAY_SIZE(g_mode_csc_coef); i++) { colorspace_info = &g_mode_csc_coef[i].st_csc_color_info; @@ -1539,7 +1492,7 @@ static void rockchip_swap_color_channel(bool is_input_yuv, bool is_output_yuv, } int rockchip_calc_post_csc(struct post_csc *csc_cfg, struct post_csc_coef *csc_simple_coef, - int csc_mode, bool is_input_yuv, bool is_output_yuv) + struct post_csc_convert_mode *convert_mode) { int ret = 0; struct rk_pq_csc_coef out_matrix; @@ -1547,22 +1500,27 @@ 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(csc_mode, is_input_yuv, is_output_yuv); + 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); if (ret < 0) { - DRM_ERROR("invalid csc_mode:%d\n", csc_mode); + DRM_ERROR("get csc index err:\n"); + DRM_ERROR("input yuv %d full_range %d,output yuv %d full_range %d\n", + convert_mode->is_input_yuv, convert_mode->is_input_full_range, + convert_mode->is_output_yuv, convert_mode->is_output_full_range); return ret; } csc_mode_cfg = &g_mode_csc_coef[ret]; - if (csc_cfg) - ret = csc_calc_adjust_output_coef(is_input_yuv, is_output_yuv, csc_cfg, + ret = csc_calc_adjust_output_coef(convert_mode->is_input_yuv, + convert_mode->is_output_yuv, csc_cfg, csc_mode_cfg, &out_matrix, &out_dc); else ret = csc_calc_default_output_coef(csc_mode_cfg, &out_matrix, &out_dc); - rockchip_swap_color_channel(is_input_yuv, is_output_yuv, csc_simple_coef, &out_matrix, - &out_dc); + 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); diff --git a/drivers/gpu/drm/rockchip/rockchip_post_csc.h b/drivers/gpu/drm/rockchip/rockchip_post_csc.h index 1215a5cd1c87..385eeca53aab 100644 --- a/drivers/gpu/drm/rockchip/rockchip_post_csc.h +++ b/drivers/gpu/drm/rockchip/rockchip_post_csc.h @@ -12,7 +12,7 @@ #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" -int rockchip_calc_post_csc(struct post_csc *csc, struct post_csc_coef *csc_coef, - int csc_mode, bool is_input_yuv, bool is_output_yuv); +int rockchip_calc_post_csc(struct post_csc *csc_cfg, struct post_csc_coef *csc_simple_coef, + struct post_csc_convert_mode *convert_mode); #endif