From: Alvin Lee <[email protected]> [Description] - UPSP should only be enabled when we want linear scaling for 420/422 - In DC for non-FP16 formats that are told to scale in non-linear, program bypass for PRE_GAM since these formats are already non-linear (i.e., YUV420, YUV422, RGB, etc.)
Reviewed-by: Aric Cyr <[email protected]> Reviewed-by: Taimur Hassan <[email protected]> Signed-off-by: Alvin Lee <[email protected]> Signed-off-by: Chenyu Chen <[email protected]> --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 18 ++++++++++++---- .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c | 20 +++++++++++++----- .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h | 3 ++- .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 21 ++++++++++++++++++- drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 3 ++- drivers/gpu/drm/amd/display/dc/inc/resource.h | 3 ++- 6 files changed, 55 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index f9b8e9474b4c..593c1fd537ae 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1557,11 +1557,21 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx, } } -enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format) +enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format, + enum dc_scaling_linearity scaling_linearity) { - if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN && format <= SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb) //420 Formats + bool scaling_in_linear = (scaling_linearity == DC_SCALING_LINEARITY_LINEAR); + bool is_420_format = (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN && + format <= SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb); + bool is_422_format = (format > SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb && + format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END); + + /* UPSP (chroma upsampling) is only needed when subsampled YUV is scaled in + * linear space. + */ + if (scaling_in_linear && is_420_format) return UPSP_HORIZONTAL_VERTICAL_UPSAMPLING; - if (format > SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb && format < SURFACE_PIXEL_FORMAT_SUBSAMPLE_END) //422 Formats + if (scaling_in_linear && is_422_format) return UPSP_HORIZONTAL_UPSAMPLING_ONLY; return UPSP_BYPASS; } @@ -1611,7 +1621,7 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) pipe_ctx->plane_res.scl_data.lb_params.depth = LB_PIXEL_DEPTH_30BPP; pipe_ctx->plane_res.scl_data.lb_params.alpha_en = plane_state->per_pixel_alpha; - pipe_ctx->plane_res.scl_data.upsp = resource_is_upsp_required(plane_state->format); + pipe_ctx->plane_res.scl_data.upsp = resource_is_upsp_required(plane_state->format, plane_state->scaling_linearity); // Convert pipe_ctx to respective input params for SPL translate_SPL_in_params_from_pipe_ctx(pipe_ctx, spl_in); diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c index 04cab7d3a5c2..38739ed048fa 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c @@ -25,17 +25,27 @@ void dpp50_set_pregam_state( struct dpp *dpp_base, enum dc_transfer_func_predefined tr, - enum dc_scaling_linearity scaling) + enum dc_scaling_linearity scaling, + bool source_is_linear) { struct dcn50_dpp *dpp = TO_DCN50_DPP(dpp_base); enum pregam_mode pre_degam_en = PREGAM_DEGAM; enum degam_lut degamma_lut_selection = 0; if (scaling == DC_SCALING_LINEARITY_SOURCE) { - //If scaling in non-linear, apply regamma - REG_SET_2(PRE_GAM, 0, - PRE_GAM_MODE, PREGAM_REGAM, - PRE_REGAM_SELECT, REGAM_20); + if (source_is_linear) { + //Linear source data (e.g. FP16) must be de-linearized + //(apply regamma) before scaling in source/non-linear space. + REG_SET_2(PRE_GAM, 0, + PRE_GAM_MODE, PREGAM_REGAM, + PRE_REGAM_SELECT, REGAM_20); + } else { + //Non-linear source data (e.g. YUV) is already in source + //space, so scale directly with no pregam conversion. + REG_SET_2(PRE_GAM, 0, + PRE_GAM_MODE, PREGAM_BYPASS, + PRE_DEGAM_SELECT, 0); + } } else { //If scaling in linear, apply degamma based on TF switch (tr) { diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h index 7f5d3fa6bbef..c81e910ae095 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h @@ -82,6 +82,7 @@ void dpp50_dpp_setup( void dpp50_set_pregam_state( struct dpp *dpp_base, enum dc_transfer_func_predefined tr, - enum dc_scaling_linearity scaling); + enum dc_scaling_linearity scaling, + bool source_is_linear); #endif /* __DCN50_DPP_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index 79be5c385280..430966af3808 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -528,6 +528,24 @@ bool dcn32_set_mcm_luts(struct dc *dc, struct dpp *dpp, struct hubp *hubp, return result; } +/* + * FP16 / 64bpp 16161616 surfaces store pixel data in linear light. These are + * the only source formats that must be de-linearized before scaling in + * source/non-linear space; every other format is already non-linear. + */ +static bool is_source_pixel_format_linear(enum surface_pixel_format format) +{ + switch (format) { + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616: + case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: + case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F: + return true; + default: + return false; + } +} + bool dcn32_set_input_transfer_func(struct set_input_transfer_func_params *params) { struct dce_hwseq *hws = params->dc->hwseq; @@ -547,7 +565,8 @@ bool dcn32_set_input_transfer_func(struct set_input_transfer_func_params *params tf = plane_state->in_transfer_func.tf; if (dpp->funcs->dpp_set_pregam_state) - dpp->funcs->dpp_set_pregam_state(dpp, tf, plane_state->scaling_linearity); + dpp->funcs->dpp_set_pregam_state(dpp, tf, plane_state->scaling_linearity, + is_source_pixel_format_linear(plane_state->format)); else dpp->funcs->dpp_set_pre_degam(dpp, tf); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h index b31b144d2e8f..930b5533256f 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -378,7 +378,8 @@ struct dpp_funcs { void (*dpp_set_pregam_state)( struct dpp *dpp_base, enum dc_transfer_func_predefined tr, - enum dc_scaling_linearity scaling); + enum dc_scaling_linearity scaling, + bool source_is_linear); void (*dpp_program_upsp)( struct dpp *dpp_base, const struct dscl_prog_data *dscl_prog_data); diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 8e21aaac06b3..9c6794f8dec0 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -123,7 +123,8 @@ void resource_build_test_pattern_params( struct resource_context *res_ctx, struct pipe_ctx *pipe_ctx); -enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format); +enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format, + enum dc_scaling_linearity scaling_linearity); bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx); -- 2.43.0
