From: Sridevi Arvindekar <[email protected]> [Why] When a subsampled YUV surface is scaled in linear space, the chroma planes are interpolated before being upsampled to 4:4:4, producing incorrect chroma on the scaled output.
[How] Enable the CNVC chroma upsampler for these cases: - resource_is_upsp_required() selects the mode from the surface format - DPP programs the pre-CSC matrix - DCN60 programs the CNVC_UPSP coefficients - SPL and DSCL treat a pipe with upsp enabled as 4:4:4 RGB Reviewed-by: Alvin Lee <[email protected]> Signed-off-by: Sridevi Arvindekar <[email protected]> Signed-off-by: Ivan Lipski <[email protected]> --- drivers/gpu/drm/amd/display/dc/Makefile | 1 + .../drm/amd/display/dc/core/dc_hw_sequencer.c | 4 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 19 ----- .../amd/display/dc/core/dc_resource_helper.c | 46 +++++++++++ .../gpu/drm/amd/display/dc/dc_spl_translate.c | 22 ++++-- .../drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c | 4 +- .../drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h | 3 +- .../drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c | 4 +- .../amd/display/dc/dpp/dcn201/dcn201_dpp.c | 4 +- .../drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c | 76 ++++++++++++++++++- .../drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h | 9 ++- .../amd/display/dc/dpp/dcn401/dcn401_dpp.c | 4 +- .../amd/display/dc/dpp/dcn401/dcn401_dpp.h | 3 +- .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c | 8 +- .../drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c | 4 +- .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.c | 4 +- .../drm/amd/display/dc/dpp/dcn50/dcn50_dpp.h | 3 +- .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c | 38 ++++++++-- .../drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h | 15 ++-- .../amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c | 13 ++-- .../amd/display/dc/hwss/dcn10/dcn10_hwseq.c | 3 +- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 3 +- .../amd/display/dc/hwss/dcn50/dcn50_hwseq.c | 3 +- .../drm/amd/display/dc/hwss/hw_sequencer.h | 1 + drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h | 3 +- .../dc/resource/dcn60/dcn60_resource.h | 6 ++ 26 files changed, 237 insertions(+), 66 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/core/dc_resource_helper.c diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index f868999515dd..1cbf284bb2fd 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -75,6 +75,7 @@ FILES += core/dc_hw_sequencer.o FILES += core/dc_link_enc_cfg.o FILES += core/dc_link_exports.o FILES += core/dc_resource.o +FILES += core/dc_resource_helper.o FILES += core/dc_sink.o FILES += core/dc_stat.o FILES += core/dc_state.o diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c index 430dc7a220ef..f881a3be6f0a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c @@ -2964,7 +2964,8 @@ void hwss_setup_dpp(union block_sequence_params *params) EXPANSION_MODE_ZERO, p->input_csc_color_matrix, p->color_space, - NULL); + NULL, + p->upsp_mode); } } @@ -5722,6 +5723,7 @@ void hwss_add_dpp_setup_dpp(struct block_sequence_state *seq_state, p->format = plane_state->format; p->input_csc_color_matrix = plane_state->input_csc_color_matrix; p->color_space = plane_state->color_space; + p->upsp_mode = resource_is_upsp_required(plane_state->format, plane_state->scaling_linearity); (*seq_state->num_steps)++; } } 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 187486d978da..fa44c68b3340 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1557,25 +1557,6 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx, } } -enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format, - enum dc_scaling_linearity scaling_linearity) -{ - 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 (scaling_in_linear && is_422_format) - return UPSP_HORIZONTAL_UPSAMPLING_ONLY; - return UPSP_BYPASS; -} - bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx) { const struct dc_plane_state *plane_state = pipe_ctx->plane_state; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource_helper.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource_helper.c new file mode 100644 index 000000000000..55dfa465163f --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource_helper.c @@ -0,0 +1,46 @@ +/* + * Copyright 2026 Advanced Micro Devices, Inc. + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "dc_types.h" +#include "sspl/dc_spl_types.h" +#include "resource.h" + +enum upsp_mode resource_is_upsp_required(enum surface_pixel_format format, + enum dc_scaling_linearity scaling_linearity) +{ + 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 (scaling_in_linear && is_422_format) + return UPSP_HORIZONTAL_UPSAMPLING_ONLY; + return UPSP_BYPASS; +} diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c index 76c0d62031b6..00e121bb8ef7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c +++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c @@ -209,21 +209,27 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl } } // Translate linear light scaling preference - if (pipe_ctx->stream->ctx->dc->debug.force_lls > 0) + if (pipe_ctx->stream->ctx->dc->debug.force_lls > 0) { spl_in->lls_pref = pipe_ctx->stream->ctx->dc->debug.force_lls; - else + spl_in->upsp_mode = pipe_ctx->plane_res.scl_data.upsp; + } else { if ((plane_state->ctx->dce_version == DCN_VERSION_4_01) || (plane_state->ctx->dce_version == DCN_VERSION_4_2) || - (plane_state->ctx->dce_version == DCN_VERSION_4_2B)) + (plane_state->ctx->dce_version == DCN_VERSION_4_2B)) { spl_in->lls_pref = LLS_PREF_DONT_CARE; - else + spl_in->upsp_mode = UPSP_BYPASS; + } else { set_linear_light_scaling_preference(plane_state, spl_in); - /* Translate upsampling mode*/ - spl_in->upsp_mode = pipe_ctx->plane_res.scl_data.upsp; + /* Translate upsampling mode*/ + spl_in->upsp_mode = pipe_ctx->plane_res.scl_data.upsp; + } + } /* Translate chroma subsampling offset ( cositing ) */ - if (pipe_ctx->stream->ctx->dc->debug.force_cositing) + if (pipe_ctx->stream->ctx->dc->debug.force_cositing) { spl_in->basic_in.cositing = pipe_ctx->stream->ctx->dc->debug.force_cositing - 1; - else + if (spl_in->upsp_mode && spl_in->basic_in.cositing == CHROMA_COSITING_NONE) + spl_in->basic_in.cositing = CHROMA_COSITING_TOPLEFT; + } else spl_in->basic_in.cositing = plane_state->cositing; /* Translate transfer function */ spl_in->basic_in.tf_type = (enum spl_transfer_func_type) plane_state->in_transfer_func.type; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c index ef605e0a75e3..de420cdf1514 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.c @@ -286,9 +286,11 @@ void dpp1_cnv_setup ( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut) + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode) { (void)alpha_2bit_lut; + (void)upsp_mode; uint32_t pixel_format; uint32_t alpha_en; enum pixel_format_description fmt ; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h index 890d04b1ddaf..b04d5fa2cd32 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn10/dcn10_dpp.h @@ -1501,7 +1501,8 @@ void dpp1_cnv_setup ( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut); + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode); void dpp1_dppclk_control( struct dpp *dpp_base, diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c index 8d5000790904..0f3b1717563b 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn20/dcn20_dpp.c @@ -103,8 +103,10 @@ static void dpp2_cnv_setup ( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut) + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode) { + (void)upsp_mode; struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base); uint32_t pixel_format = 0; uint32_t alpha_en = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn201/dcn201_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn201/dcn201_dpp.c index d78ab3ffd95d..a2079db62f63 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn201/dcn201_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn201/dcn201_dpp.c @@ -47,8 +47,10 @@ static void dpp201_cnv_setup( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut) + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode) { + (void)upsp_mode; struct dcn201_dpp *dpp = TO_DCN201_DPP(dpp_base); uint32_t pixel_format = 0; uint32_t alpha_en = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c index 2ebc738c37f2..3db10019fa84 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.c @@ -100,6 +100,78 @@ void dpp30_read_reg_state(struct dpp *dpp_base, struct dcn_dpp_reg_state *dpp_re dpp_reg_state->mpc_size = REG_READ(MPC_SIZE); } +void dpp3_program_pre_csc( + struct dpp *dpp_base, + enum dc_color_space color_space, + enum dcn10_input_csc_select input_select, + const struct out_csc_color_matrix *tbl_entry) +{ + int i; + enum dcn10_input_csc_select select; + struct color_matrices_reg gam_regs; + struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); + int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix); + const uint16_t *regval = NULL; + uint32_t cur_select = 0; + + if (input_select == INPUT_CSC_SELECT_BYPASS) { + REG_SET(PRE_CSC_MODE, 0, PRE_CSC_MODE, 0); + return; + } + + if (tbl_entry == NULL) { + for (i = 0; i < arr_size; i++) + if (dpp_input_csc_matrix[i].color_space == color_space) { + regval = dpp_input_csc_matrix[i].regval; + break; + } + + if (regval == NULL) { + BREAK_TO_DEBUGGER(); + return; + } + } else { + regval = tbl_entry->regval; + } + + /* determine which CSC matrix (icsc or coma) we are using + * currently. select the alternate set to double buffer + * the CSC update so CSC is updated on frame boundary + */ + REG_GET(PRE_CSC_MODE, + PRE_CSC_MODE_CURRENT, &cur_select); + + if (cur_select != INPUT_CSC_SELECT_ICSC) + select = INPUT_CSC_SELECT_ICSC; + else + select = INPUT_CSC_SELECT_COMA; + + gam_regs.shifts.csc_c11 = dpp->tf_shift->PRE_CSC_C11; + gam_regs.masks.csc_c11 = dpp->tf_mask->PRE_CSC_C11; + gam_regs.shifts.csc_c12 = dpp->tf_shift->PRE_CSC_C12; + gam_regs.masks.csc_c12 = dpp->tf_mask->PRE_CSC_C12; + + if (select == INPUT_CSC_SELECT_ICSC) { + + gam_regs.csc_c11_c12 = REG(PRE_CSC_C11_C12); + gam_regs.csc_c33_c34 = REG(PRE_CSC_C33_C34); + + } else { + + gam_regs.csc_c11_c12 = REG(PRE_CSC_B_C11_C12); + gam_regs.csc_c33_c34 = REG(PRE_CSC_B_C33_C34); + + } + + cm_helper_program_color_matrices( + dpp->base.ctx, + regval, + &gam_regs); + + REG_SET(PRE_CSC_MODE, 0, + PRE_CSC_MODE, select); +} + /*program post scaler scs block in dpp CM*/ void dpp3_program_post_csc( struct dpp *dpp_base, @@ -223,8 +295,10 @@ void dpp3_cnv_setup ( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut) + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode) { + (void)upsp_mode; struct dcn3_dpp *dpp = TO_DCN30_DPP(dpp_base); uint32_t pixel_format = 0; uint32_t alpha_en = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h index f397e8222ac9..349a1b9ee916 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn30/dcn30_dpp.h @@ -629,7 +629,8 @@ void dpp3_cnv_setup( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut); + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode); void dpp3_program_CM_bias( struct dpp *dpp_base, @@ -650,6 +651,12 @@ void dpp3_set_cursor_attributes( struct dpp *dpp_base, struct dc_cursor_attributes *cursor_attributes); +void dpp3_program_pre_csc( + struct dpp *dpp_base, + enum dc_color_space color_space, + enum dcn10_input_csc_select input_select, + const struct out_csc_color_matrix *tbl_entry); + void dpp3_program_post_csc( struct dpp *dpp_base, enum dc_color_space color_space, diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c index 8e0fa7be34ee..7a3a7678c71a 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.c @@ -58,8 +58,10 @@ void dpp401_dpp_setup( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut) + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode) { + (void)upsp_mode; struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); uint32_t pixel_format = 0; uint32_t alpha_en = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h index e34d291de37b..f1530e8805cb 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp.h @@ -712,7 +712,8 @@ void dpp401_dpp_setup( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut); + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode); void dpp401_set_cursor_attributes( struct dpp *dpp_base, diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c index 81f287c89562..6e85890e44f7 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c @@ -478,8 +478,9 @@ enum lb_memory_config dpp401_dscl_find_lb_memory_config(struct dcn401_dpp *dpp, int ceil_vratio_c = dc_fixpt_ceil(scl_data->ratios.vert_c); if (dpp->base.ctx->dc->debug.use_max_lb) { - if (scl_data->format == PIXEL_FORMAT_420BPP8 + if ((scl_data->format == PIXEL_FORMAT_420BPP8 || scl_data->format == PIXEL_FORMAT_420BPP10) + && !scl_data->upsp) return LB_MEMORY_CONFIG_3; return LB_MEMORY_CONFIG_0; } @@ -498,8 +499,9 @@ enum lb_memory_config dpp401_dscl_find_lb_memory_config(struct dcn401_dpp *dpp, && dpp401_dscl_is_lb_conf_valid(ceil_vratio_c, num_part_c, vtaps_c)) return LB_MEMORY_CONFIG_2; - if (scl_data->format == PIXEL_FORMAT_420BPP8 - || scl_data->format == PIXEL_FORMAT_420BPP10) { + if ((scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) + && !scl_data->upsp) { dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_3, &num_part_y, &num_part_c); diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c index eed86f5ae731..2ce0694e3725 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn42/dcn42_dpp.c @@ -118,8 +118,10 @@ static void dpp42_dpp_setup( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut) + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode) { + (void)upsp_mode; struct dcn401_dpp *dpp = TO_DCN401_DPP(dpp_base); uint32_t pixel_format = 0; uint32_t alpha_en = 1; 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 38739ed048fa..5382fc656169 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 @@ -90,8 +90,10 @@ void dpp50_dpp_setup( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut) + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode) { + (void)upsp_mode; struct dcn50_dpp *dpp = TO_DCN50_DPP(dpp_base); uint32_t pixel_format = 0; uint32_t alpha_en = 1; 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 c81e910ae095..fb9ed75ae901 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 @@ -77,7 +77,8 @@ void dpp50_dpp_setup( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut); + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode); void dpp50_set_pregam_state( struct dpp *dpp_base, diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c index be2effb14fc3..4218863d2a04 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.c @@ -24,7 +24,8 @@ void dpp60_dpp_setup( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut) + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode) { struct dcn60_dpp *dpp = TO_DCN60_DPP(dpp_base); uint32_t pixel_format = 8; @@ -249,25 +250,47 @@ void dpp60_dpp_setup( PRE_REALPHA_EN, realpha_en, PRE_REALPHA_ABLND_EN, realpha_ablnd_en); - if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || - format >= SURFACE_PIXEL_FORMAT_SUBSAMPLE_END || - color_space != COLOR_SPACE_SRGB) { - /* If input adjustment exists, program the ICSC with those values. */ + // color matrix applied PreCSC for upsp mode + if (upsp_mode) { if (input_csc_color_matrix.enable_adjustment == true) { for (i = 0; i < 12; i++) tbl_entry.regval[i] = input_csc_color_matrix.matrix[i]; tbl_entry.color_space = input_color_space; + // Re-use post csc function to program pre csc as + // the programming is same for both if (dpp3_should_bypass_post_csc_for_colorspace(color_space)) select = INPUT_CSC_SELECT_BYPASS; else select = INPUT_CSC_SELECT_ICSC; - dpp3_program_post_csc(dpp_base, color_space, select, + dpp3_program_pre_csc(dpp_base, color_space, select, &tbl_entry); } else { - dpp3_program_post_csc(dpp_base, color_space, select, NULL); + dpp3_program_pre_csc(dpp_base, color_space, select, NULL); + } + } else { + if (format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || + format >= SURFACE_PIXEL_FORMAT_SUBSAMPLE_END || + color_space != COLOR_SPACE_SRGB) { + /* If input adjustment exists, program the ICSC with those values. */ + if (input_csc_color_matrix.enable_adjustment == true) { + for (i = 0; i < 12; i++) + tbl_entry.regval[i] = input_csc_color_matrix.matrix[i]; + + tbl_entry.color_space = input_color_space; + + if (dpp3_should_bypass_post_csc_for_colorspace(color_space)) + select = INPUT_CSC_SELECT_BYPASS; + else + select = INPUT_CSC_SELECT_ICSC; + + dpp3_program_post_csc(dpp_base, color_space, + select, &tbl_entry); + } else { + dpp3_program_post_csc(dpp_base, color_space, select, NULL); + } } } } @@ -317,6 +340,7 @@ static struct dpp_funcs dcn60_dpp_funcs = { .dpp_cm_hist_read = dpp42_dpp_cm_hist_read, .dpp_read_reg_state = dpp30_read_reg_state, .dpp_set_pregam_state = dpp50_set_pregam_state, + .dpp_program_upsp = dpp60_dscl_program_upsp }; static struct dpp_caps dcn60_dpp_cap = { diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h b/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h index 5d09fcd04553..f12a6061e5fb 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp.h @@ -448,12 +448,12 @@ #define DPP_REG_VARIABLE_LIST_DCN60 \ DPP_REG_VARIABLE_LIST_DCN50; \ uint32_t SCL_BLACK_COLOR; \ - uint32_t UPSP_MODE; \ - uint32_t UPSP_V_COEF_P0; \ - uint32_t UPSP_V_COEF_P1; \ - uint32_t UPSP_H_COEF_P0; \ - uint32_t UPSP_H_COEF_P1; \ - uint32_t UPSP_CLAMP + uint32_t CNVC_UPSP_MODE; \ + uint32_t CNVC_UPSP_V_COEF_P0; \ + uint32_t CNVC_UPSP_V_COEF_P1; \ + uint32_t CNVC_UPSP_H_COEF_P0; \ + uint32_t CNVC_UPSP_H_COEF_P1; \ + uint32_t CNVC_UPSP_CLAMP struct dcn60_dpp_registers { DPP_REG_VARIABLE_LIST_DCN60; @@ -490,7 +490,8 @@ void dpp60_dpp_setup( enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut); + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode); void dpp60_full_bypass(struct dpp *dpp_base); diff --git a/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c index 0898148ba704..f030b2a0a1f4 100644 --- a/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dpp/dcn60/dcn60_dpp_dscl.c @@ -187,6 +187,7 @@ void dpp60_dscl_set_scaler_manual_scale(struct dpp *dpp_base, v_num_taps_c = scl_data->dscl_prog_data.taps.v_taps_c; h_num_taps = scl_data->dscl_prog_data.taps.h_taps; h_num_taps_c = scl_data->dscl_prog_data.taps.h_taps_c; + ycbcr = ycbcr && !scl_data->dscl_prog_data.upsp_mode; } /* Unconditionally power on DSCL - can be in light sleep otherwise. */ @@ -280,7 +281,7 @@ void dpp60_dscl_program_upsp(struct dpp *dpp_base, { struct dcn60_dpp *dpp = TO_DCN60_DPP(dpp_base); - REG_SET_8(UPSP_MODE, 0, + REG_SET_8(CNVC_UPSP_MODE, 0, UPSP_MODE, dscl_prog_data->upsp_mode, UPSP_V_NUM_TAPS, dscl_prog_data->upsp_v_num_taps, UPSP_V_INIT_INT, dscl_prog_data->upsp_v_init_int, @@ -289,27 +290,27 @@ void dpp60_dscl_program_upsp(struct dpp *dpp_base, UPSP_H_INIT_INT, dscl_prog_data->upsp_h_init_int, UPSP_H_INIT_FRAC, dscl_prog_data->upsp_h_init_frac, UPSP_BOUNDARY_MODE, dscl_prog_data->upsp_boundary_mode); - REG_SET_4(UPSP_V_COEF_P0, 0, + REG_SET_4(CNVC_UPSP_V_COEF_P0, 0, UPSP_V_COEF_TAP0_P0, dscl_prog_data->upsp_v_coef_tap0_p0, UPSP_V_COEF_TAP1_P0, dscl_prog_data->upsp_v_coef_tap1_p0, UPSP_V_COEF_TAP2_P0, dscl_prog_data->upsp_v_coef_tap2_p0, UPSP_V_COEF_TAP3_P0, dscl_prog_data->upsp_v_coef_tap3_p0); - REG_SET_4(UPSP_V_COEF_P1, 0, + REG_SET_4(CNVC_UPSP_V_COEF_P1, 0, UPSP_V_COEF_TAP0_P1, dscl_prog_data->upsp_v_coef_tap0_p1, UPSP_V_COEF_TAP1_P1, dscl_prog_data->upsp_v_coef_tap1_p1, UPSP_V_COEF_TAP2_P1, dscl_prog_data->upsp_v_coef_tap2_p1, UPSP_V_COEF_TAP3_P1, dscl_prog_data->upsp_v_coef_tap3_p1); - REG_SET_4(UPSP_H_COEF_P0, 0, + REG_SET_4(CNVC_UPSP_H_COEF_P0, 0, UPSP_H_COEF_TAP0_P0, dscl_prog_data->upsp_h_coef_tap0_p0, UPSP_H_COEF_TAP1_P0, dscl_prog_data->upsp_h_coef_tap1_p0, UPSP_H_COEF_TAP2_P0, dscl_prog_data->upsp_h_coef_tap2_p0, UPSP_H_COEF_TAP3_P0, dscl_prog_data->upsp_h_coef_tap3_p0); - REG_SET_4(UPSP_H_COEF_P1, 0, + REG_SET_4(CNVC_UPSP_H_COEF_P1, 0, UPSP_H_COEF_TAP0_P1, dscl_prog_data->upsp_h_coef_tap0_p1, UPSP_H_COEF_TAP1_P1, dscl_prog_data->upsp_h_coef_tap1_p1, UPSP_H_COEF_TAP2_P1, dscl_prog_data->upsp_h_coef_tap2_p1, UPSP_H_COEF_TAP3_P1, dscl_prog_data->upsp_h_coef_tap3_p1); - REG_SET_2(UPSP_CLAMP, 0, + REG_SET_2(CNVC_UPSP_CLAMP, 0, UPSP_CLAMP_MAX, dscl_prog_data->upsp_clamp_max, UPSP_CLAMP_MIN, dscl_prog_data->upsp_clamp_min); } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c index c42e493720bc..2ab247d9748b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn10/dcn10_hwseq.c @@ -2943,7 +2943,8 @@ static void dcn10_update_dpp(struct dpp *dpp, struct dc_plane_state *plane_state EXPANSION_MODE_ZERO, plane_state->input_csc_color_matrix, plane_state->color_space, - NULL); + NULL, + 0); //set scale and bias registers build_prescale_params(&bns_params, plane_state); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c index 27b886e78998..6b8c5b1e436c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c @@ -1787,7 +1787,8 @@ void dcn20_update_dchubp_dpp( EXPANSION_MODE_ZERO, plane_state->input_csc_color_matrix, plane_state->color_space, - NULL); + NULL, + pipe_ctx->plane_res.scl_data.upsp); if (dpp->funcs->set_cursor_matrix) { dpp->funcs->set_cursor_matrix(dpp, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c index 7a82aaa6d1d6..151ec838f613 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn50/dcn50_hwseq.c @@ -153,7 +153,8 @@ void dcn50_update_dchubp_dpp( EXPANSION_MODE_ZERO, plane_state->input_csc_color_matrix, plane_state->color_space, - NULL); + NULL, + pipe_ctx->plane_res.scl_data.upsp); if (dpp->funcs->set_cursor_matrix) { dpp->funcs->set_cursor_matrix(dpp, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h index 7e7054608d74..7de59001453c 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h @@ -155,6 +155,7 @@ struct setup_dpp_params { enum surface_pixel_format format; struct dc_csc_transform input_csc_color_matrix; enum dc_color_space color_space; + enum upsp_mode upsp_mode; }; struct program_bias_and_scale_params { 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 71244d3b6c90..562176e8d7d1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h @@ -314,7 +314,8 @@ struct dpp_funcs { enum expansion_mode mode, struct dc_csc_transform input_csc_color_matrix, enum dc_color_space input_color_space, - struct cnv_alpha_2bit_lut *alpha_2bit_lut); + struct cnv_alpha_2bit_lut *alpha_2bit_lut, + enum upsp_mode upsp_mode); void (*dpp_full_bypass)(struct dpp *dpp_base); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.h index b1a802f9f4b4..34cfdc6eb8e5 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn60/dcn60_resource.h @@ -370,6 +370,12 @@ bool dcn50_program_mcache_pipe_config(struct dc_state *context, SRI_ARR(CM_TEST_DEBUG_DATA, CM, id), \ SRI_ARR(FORMAT_CONTROL, CNVC_CFG, id), \ SRI_ARR(CNVC_SURFACE_PIXEL_FORMAT, CNVC_CFG, id), \ + SRI_ARR(CNVC_UPSP_CLAMP, CNVC_CFG, id), \ + SRI_ARR(CNVC_UPSP_MODE, CNVC_CFG, id), \ + SRI_ARR(CNVC_UPSP_H_COEF_P0, CNVC_CFG, id), \ + SRI_ARR(CNVC_UPSP_H_COEF_P1, CNVC_CFG, id), \ + SRI_ARR(CNVC_UPSP_V_COEF_P0, CNVC_CFG, id), \ + SRI_ARR(CNVC_UPSP_V_COEF_P1, CNVC_CFG, id), \ SRI_ARR(CURSOR0_CONTROL, CM_CUR, id), \ SRI_ARR(CURSOR0_COLOR0, CM_CUR, id), \ SRI_ARR(CURSOR0_COLOR1, CM_CUR, id), \ -- 2.43.0
