[PATCH 20/20] drm/amd/display: 3.2.285
From: Aric Cyr This version brings along following fixes: - Read default boot options - Find max flickerless instant vtotal delta - Refactor dcn401_update_clocks - Reduce I2C speed to 95kHz in DCN401 - Allow higher DSC slice support for small timings on dcn401 - Don't offload flip if not only address update - Check UHBR13.5 cap when determining max link cap - Enable SYMCLK gating in DCCG - Expand to higher link rates - Add left edge pixel for YCbCr422/420 + ODM pipe split - Add resource interfaces for get ODM slice rect - Add COEF filter types for DCN401 - Refactor DCN401 DCCG into component directory - Fix 3dlut size for Fastloading on DCN401 - Fix write to non-existent reg on DCN401 - Remove USBC check for DCN32 - Remove unused code for some dc files - Disable AC/DC codepath when unnecessary - Create dcn401_clk_mgr struct Acked-by: Alex Hung Signed-off-by: Aric Cyr --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index d550b6f97039..a7ba80c84128 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -55,7 +55,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.284" +#define DC_VER "3.2.285" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- 2.34.1
[PATCH 19/20] drm/amd/display: Read default boot options
From: Duncan Ma [WHY] DPIA boot option is set by VBIOS. It gets overwritten when driver loads DMU. [HOW] Read PreOS boot options and determine if dpia is enabled. Reviewed-by: Ovidiu Bunea Acked-by: Alex Hung Signed-off-by: Duncan Ma --- drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c index 70e63aeb8f89..7f53074f4e48 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_dcn35.c @@ -410,10 +410,13 @@ union dmub_fw_boot_options dmub_dcn35_get_fw_boot_option(struct dmub_srv *dmub) void dmub_dcn35_enable_dmub_boot_options(struct dmub_srv *dmub, const struct dmub_srv_hw_params *params) { union dmub_fw_boot_options boot_options = {0}; + union dmub_fw_boot_options cur_boot_options = {0}; + + cur_boot_options = dmub_dcn35_get_fw_boot_option(dmub); boot_options.bits.z10_disable = params->disable_z10; boot_options.bits.dpia_supported = params->dpia_supported; - boot_options.bits.enable_dpia = params->disable_dpia == true ? 0:1; + boot_options.bits.enable_dpia = cur_boot_options.bits.enable_dpia && !params->disable_dpia; boot_options.bits.usb4_cm_version = params->usb4_cm_version; boot_options.bits.dpia_hpd_int_enable_supported = params->dpia_hpd_int_enable_supported; boot_options.bits.power_optimization = params->power_optimization; -- 2.34.1
[PATCH 18/20] drm/amd/display: Find max flickerless instant vtotal delta
From: Ethan Bitnun [WHAT & HOW] - Populate dml 2 callback with get_max_flickerless_instant_vtotal_increase - Use long long when necessary to prevent overflow - Add asic specific default values, currently disabled by default for every asic - Use the pre-existing debug option to protect the call to get_max_flickerless_instant_vtotal_increase Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Ethan Bitnun --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 3 + .../gpu/drm/amd/display/dc/core/dc_stream.c | 64 +-- .../gpu/drm/amd/display/dc/dc_stream_priv.h | 14 .../display/dc/dcn32/dcn32_resource_helpers.c | 2 +- .../drm/amd/display/dc/dml2/dml2_wrapper.h| 3 + 5 files changed, 79 insertions(+), 7 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 8a5cc8b80217..70c39eef99e5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -43,6 +43,8 @@ #include "link.h" #include "clk_mgr.h" #include "dc_state_priv.h" +#include "dc_stream_priv.h" + #include "virtual/virtual_link_hwss.h" #include "link/hwss/link_hwss_dio.h" #include "link/hwss/link_hwss_dpia.h" @@ -5195,6 +5197,7 @@ void resource_init_common_dml2_callbacks(struct dc *dc, struct dml2_configuratio dml2_options->callbacks.get_dpp_pipes_for_plane = _get_dpp_pipes_for_plane; dml2_options->callbacks.get_stream_status = _state_get_stream_status; dml2_options->callbacks.get_stream_from_id = _state_get_stream_from_id; + dml2_options->callbacks.get_max_flickerless_instant_vtotal_increase = _stream_get_max_flickerless_instant_vtotal_increase; dml2_options->svp_pstate.callbacks.dc = dc; dml2_options->svp_pstate.callbacks.add_phantom_plane = _state_add_phantom_plane; diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index b5a89b587d86..de48084eac25 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -833,7 +833,7 @@ static int dc_stream_get_brightness_millinits_linear_interpolation (struct dc_st int index2, int refresh_hz) { - int slope = 0; + long long slope = 0; if (stream->lumin_data.refresh_rate_hz[index2] != stream->lumin_data.refresh_rate_hz[index1]) { slope = (stream->lumin_data.luminance_millinits[index2] - stream->lumin_data.luminance_millinits[index1]) / (stream->lumin_data.refresh_rate_hz[index2] - stream->lumin_data.refresh_rate_hz[index1]); @@ -852,7 +852,7 @@ static int dc_stream_get_refresh_hz_linear_interpolation (struct dc_stream_state int index2, int brightness_millinits) { - int slope = 1; + long long slope = 1; if (stream->lumin_data.refresh_rate_hz[index2] != stream->lumin_data.refresh_rate_hz[index1]) { slope = (stream->lumin_data.luminance_millinits[index2] - stream->lumin_data.luminance_millinits[index1]) / (stream->lumin_data.refresh_rate_hz[index2] - stream->lumin_data.refresh_rate_hz[index1]); @@ -860,7 +860,7 @@ static int dc_stream_get_refresh_hz_linear_interpolation (struct dc_stream_state int y_intercept = stream->lumin_data.luminance_millinits[index2] - slope * stream->lumin_data.refresh_rate_hz[index2]; - return ((brightness_millinits - y_intercept) / slope); + return ((int)div64_s64((brightness_millinits - y_intercept), slope)); } /* @@ -884,8 +884,9 @@ static int dc_stream_get_brightness_millinits_from_refresh (struct dc_stream_sta } /* - * Finds the lowest refresh rate that can be achieved - * from starting_refresh_hz while staying within flicker criteria + * Finds the lowest/highest refresh rate (depending on search_for_max_increase) + * that can be achieved from starting_refresh_hz while staying + * within flicker criteria */ static int dc_stream_calculate_flickerless_refresh_rate(struct dc_stream_state *stream, int current_brightness, @@ -942,7 +943,7 @@ static int dc_stream_calculate_flickerless_refresh_rate(struct dc_stream_state * } if (search_for_max_increase) - return stream->lumin_data.refresh_rate_hz[LUMINANCE_DATA_TABLE_SIZE - 1]; + return (int)div64_s64((long long)stream->timing.pix_clk_100hz*100, stream->timing.v_total*stream->timing.h_total);
[PATCH 17/20] drm/amd/display: Refactor dcn401_update_clocks
From: Dillon Varone [WHY & HOW] Refactor complex code into manageable functions. This also cleans up some updating logics. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Dillon Varone --- .../amd/display/dc/clk_mgr/dcn401/dalsmc.h| 8 +- .../dc/clk_mgr/dcn401/dcn401_clk_mgr.c| 523 +- .../dc/clk_mgr/dcn401/dcn401_clk_mgr.h| 94 .../clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c | 80 ++- .../clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h | 10 + .../gpu/drm/amd/display/dc/core/dc_resource.c | 3 +- drivers/gpu/drm/amd/display/dc/dc.h | 3 + .../gpu/drm/amd/display/include/dal_asic_id.h | 3 + 8 files changed, 718 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dalsmc.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dalsmc.h index 0d2584437934..5653c7991c62 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dalsmc.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dalsmc.h @@ -36,7 +36,13 @@ #define DALSMC_MSG_SetFclkSwitchAllow 0x11 #define DALSMC_MSG_SetCabForUclkPstate0x12 #define DALSMC_MSG_SetWorstCaseUclkLatency0x13 -#define DALSMC_Message_Count 0x14 +#define DALSMC_MSG_DcnExitReset 0x14 +#define DALSMC_MSG_ReturnHardMinStatus0x15 +#define DALSMC_MSG_SetAlwaysWaitDmcubResp 0x16 +#define DALSMC_MSG_IndicateDrrStatus 0x17 // PMFW 15811 +#define DALSMC_MSG_ActiveUclkFclk 0x18 +#define DALSMC_MSG_IdleUclkFclk 0x19 +#define DALSMC_Message_Count 0x1A typedef enum { FCLK_SWITCH_DISALLOW, diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c index bd74ff47fb37..d2abc00a60c5 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c @@ -67,6 +67,9 @@ static const struct clk_mgr_mask clk_mgr_mask_dcn401 = { CLK_COMMON_MASK_SH_LIST_DCN401(_MASK) }; +#define TO_DCN401_CLK_MGR(clk_mgr)\ + container_of(clk_mgr, struct dcn401_clk_mgr, base) + static bool dcn401_is_ppclk_dpm_enabled(struct clk_mgr_internal *clk_mgr, PPCLK_e clk) { bool ppclk_dpm_enabled = false; @@ -112,6 +115,30 @@ static bool dcn401_is_ppclk_dpm_enabled(struct clk_mgr_internal *clk_mgr, PPCLK_ return ppclk_dpm_enabled; } +static bool dcn401_is_ppclk_idle_dpm_enabled(struct clk_mgr_internal *clk_mgr, PPCLK_e clk) +{ + bool ppclk_idle_dpm_enabled = false; + + switch (clk) { + case PPCLK_UCLK: + case PPCLK_FCLK: + if (ASICREV_IS_GC_12_0_0_A0(clk_mgr->base.ctx->asic_id.hw_internal_rev) && + clk_mgr->smu_ver >= 0x681800) { + ppclk_idle_dpm_enabled = true; + } else if (ASICREV_IS_GC_12_0_1_A0(clk_mgr->base.ctx->asic_id.hw_internal_rev) && + clk_mgr->smu_ver >= 0x661300) { + ppclk_idle_dpm_enabled = true; + } + break; + default: + ppclk_idle_dpm_enabled = false; + } + + ppclk_idle_dpm_enabled &= clk_mgr->smu_present; + + return ppclk_idle_dpm_enabled; +} + /* Query SMU for all clock states for a particular clock */ static void dcn401_init_single_clock(struct clk_mgr_internal *clk_mgr, PPCLK_e clk, unsigned int *entry_0, unsigned int *num_levels) @@ -470,7 +497,7 @@ static void dcn401_update_clocks_update_dentist( } -static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base, +static void dcn401_update_clocks_legacy(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool safe_to_lower) { @@ -512,7 +539,7 @@ static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base, if (clk_mgr->smu_present) { if (enter_display_off == safe_to_lower) - dcn30_smu_set_num_of_displays(clk_mgr, display_count); + dcn401_smu_set_num_of_displays(clk_mgr, display_count); clk_mgr_base->clks.fclk_prev_p_state_change_support = clk_mgr_base->clks.fclk_p_state_change_support; @@ -542,7 +569,7 @@ static void dcn401_update_clocks(struct clk_mgr *clk_mgr_base, if (should_set_clock(safe_to_lower, new_clocks->dcfclk_deep_sleep_khz, clk_mgr_base->clks.dcfclk_deep_sleep_khz)) { clk_mgr_base->clks.dcfclk_deep_sleep_khz = new_clocks->dcfclk_deep_sleep_khz; if (dcn401_is_ppclk_dpm_enabled(clk_mgr, PPCLK_DCFCLK)) - dcn30_smu_set_min_deep_sleep_dcef_clk(clk_mgr, khz_to_mhz_ceil(clk_mgr_base->clks.dcfclk_deep_sleep_khz)); +
[PATCH 16/20] drm/amd/display: Reduce I2C speed to 95kHz in DCN401
From: Chris Park [WHY] HW for DCN401 is presented with a small I2C speed fluctuation that exceeds the hard cap limitation of 100kHz occasionally. This violates compliance requirement and will result in failure in compliance. [HOW] After various measurements and traceback to previous generation HW, DCN IP, SI and SW driver agrees that we can reduce I2C speed to 95kHz to address the I2C spped fluctuation in DCN401. Reviewed-by: Dillon Varone Acked-by: Alex Hung Signed-off-by: Chris Park --- .../gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c index 75e2c62ae792..a55421363772 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c @@ -1772,8 +1772,8 @@ static bool dcn401_resource_construct( pool->base.pipe_count = num_pipes; pool->base.mpcc_count = num_pipes; dc->caps.max_downscale_ratio = 600; - dc->caps.i2c_speed_in_khz = 100; - dc->caps.i2c_speed_in_khz_hdcp = 100; /*1.4 w/a applied by default*/ + dc->caps.i2c_speed_in_khz = 95; + dc->caps.i2c_speed_in_khz_hdcp = 95; /*1.4 w/a applied by default*/ /* TODO: Bring max cursor size back to 256 after subvp cursor corruption is fixed*/ dc->caps.max_cursor_size = 64; dc->caps.cursor_not_scaled = true; -- 2.34.1
[PATCH 15/20] drm/amd/display: Allow higher DSC slice support for small timings on dcn401
From: Wenjing Liu [WHY] DML2.1 has added the support to determine ODM combine based on DSC slice count limitation. This support would allow us to support DSC slice higher than 4 on small timings. The change will allow higher DSC slice support independent from pixel clock in use. [HOW] Add a DCN401 get_enc_caps function to allow the support for DSC slice count higher than 4. Reviewed-by: Dillon Varone Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- .../amd/display/dc/dsc/dcn401/dcn401_dsc.c| 412 ++ 1 file changed, 39 insertions(+), 373 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c index 845686d57919..52f23bb554af 100644 --- a/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dsc/dcn401/dcn401_dsc.c @@ -9,6 +9,9 @@ #include "dsc/dscc_types.h" #include "dsc/rc_calc.h" +#define MAX_THROUGHPUT_PER_DSC_100HZ 2000 +#define MAX_DSC_UNIT_COMBINE 4 + static void dsc_write_to_registers(struct display_stream_compressor *dsc, const struct dsc_reg_values *reg_vals); /* Object I/F functions */ @@ -22,9 +25,10 @@ static void dsc401_enable(struct display_stream_compressor *dsc, int opp_pipe); static void dsc401_disable(struct display_stream_compressor *dsc); static void dsc401_disconnect(struct display_stream_compressor *dsc); static void dsc401_wait_disconnect_pending_clear(struct display_stream_compressor *dsc); +static void dsc401_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz); const struct dsc_funcs dcn401_dsc_funcs = { - .dsc_get_enc_caps = dsc2_get_enc_caps, + .dsc_get_enc_caps = dsc401_get_enc_caps, .dsc_read_state = dsc401_read_state, .dsc_validate_stream = dsc401_validate_stream, .dsc_set_config = dsc401_set_config, @@ -48,9 +52,6 @@ const struct dsc_funcs dcn401_dsc_funcs = { #define DC_LOGGER \ dsc->ctx->logger -#define DCN401_MAX_PIXEL_CLOCK_Mhz 1188 -#define DCN401_MAX_DISPLAY_CLOCK_Mhz1200 - enum dsc_bits_per_comp { DSC_BPC_8 = 8, DSC_BPC_10 = 10, @@ -78,50 +79,40 @@ void dsc401_construct(struct dcn401_dsc *dsc, dsc->max_image_width = 5184; } -/* This returns the capabilities for a single DSC encoder engine. Number of slices and total throughput - * can be doubled, tripled etc. by using additional DSC engines. - */ -//static void dsc401_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz) -//{ -// dsc_enc_caps->dsc_version = 0x21; /* v1.2 - DP spec defined it in reverse order and we kept it */ -// -// /*dsc_enc_caps->slice_caps.bits.NUM_SLICES_1 = 1; -// dsc_enc_caps->slice_caps.bits.NUM_SLICES_2 = 1; -// dsc_enc_caps->slice_caps.bits.NUM_SLICES_3 = 1; -// dsc_enc_caps->slice_caps.bits.NUM_SLICES_4 = 1; -// -// dsc_enc_caps->lb_bit_depth = 13; -// dsc_enc_caps->is_block_pred_supported = true; -// -// dsc_enc_caps->color_formats.bits.RGB = 1; -// dsc_enc_caps->color_formats.bits.YCBCR_444 = 1; -// dsc_enc_caps->color_formats.bits.YCBCR_SIMPLE_422 = 1; -// dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_422 = 0; -// dsc_enc_caps->color_formats.bits.YCBCR_NATIVE_420 = 1; -// -// dsc_enc_caps->color_depth.bits.COLOR_DEPTH_8_BPC = 1; -// dsc_enc_caps->color_depth.bits.COLOR_DEPTH_10_BPC = 1; -// dsc_enc_caps->color_depth.bits.COLOR_DEPTH_12_BPC = 1; -// -// /* Maximum total throughput with all the slices combined. This is different from how DP spec specifies it. -// * Our decoder's total throughput in Pix/s is equal to DISPCLK. This is then shared between slices. -// * The value below is the absolute maximum value. The actual throughput may be lower, but it'll always -// * be sufficient to process the input pixel rate fed into a single DSC engine. -// */ -// /*dsc_enc_caps->max_total_throughput_mps = DCN401_MAX_DISPLAY_CLOCK_Mhz; -// -// /* For pixel clock bigger than a single-pipe limit we'll need two engines, which then doubles our -// * throughput and number of slices, but also introduces a lower limit of 2 slices -// */ -// /*if (pixel_clock_100Hz >= DCN401_MAX_PIXEL_CLOCK_Mhz*1) { -// dsc_enc_caps->slice_caps.bits.NUM_SLICES_1 = 0; -// dsc_enc_caps->slice_caps.bits.NUM_SLICES_8 = 1; -// dsc_enc_caps->max_total_throughput_mps = DCN401_MAX_DISPLAY_CLOCK_Mhz * 2; -// } -// -// dsc_enc_caps->max_slice_width = 5184; /* (including 64 overlap pixels for eDP MSO mode) */ -// /*dsc_enc_caps->bpp_increment_div = 16; /* 1/16th of a bit */ -//} +static void dsc401_get_enc_caps(struct dsc_enc_caps *dsc_enc_caps, int pixel_clock_100Hz) +{ + int min_dsc_unit_required = (pixel_clock_100Hz + MAX_THROUGHPUT_PER_DSC_100HZ - 1) / MAX_THROUGHPUT_PER_
[PATCH 14/20] drm/amd/display: Don't offload flip if not only address update
From: Alvin Lee [WHAT & HOW] Fast updates can consist of some stream updates as well (i.e., out_csc). In these cases we should not offload the flip to FW as we can only offload address only updates to FW. Reviewed-by: Chris Park Acked-by: Alex Hung Signed-off-by: Alvin Lee --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 0f20a3d96d93..0208b28517ac 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3664,6 +3664,10 @@ static void commit_planes_for_stream_fast(struct dc *dc, break; } } + if (stream_update) { + /* more than address update, need to acquire FAMS2 lock */ + should_offload_fams2_flip = false; + } } dc_exit_ips_for_hw_access(dc); -- 2.34.1
[PATCH 13/20] drm/amd/display: Check UHBR13.5 cap when determining max link cap
From: George Shen [WHY] UHBR13.5 support is optional, even if UHBR20 is supported by the device. If source supports max UHBR13.5 while sink, cable and LTTPR support UHBR20 but not UHBR13.5, UHBR10 should be used as the max link cap. Reviewed-by: Wenjing Liu Acked-by: Alex Hung Signed-off-by: George Shen --- .../dc/link/protocols/link_dp_capability.c| 22 +++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index 8f57b344f09e..766116ec627d 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -2062,7 +2062,7 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) enum dc_link_rate lttpr_max_link_rate; enum dc_link_rate cable_max_link_rate; struct link_encoder *link_enc = NULL; - + bool is_uhbr13_5_supported = true; link_enc = link_enc_cfg_get_link_enc(link); ASSERT(link_enc); @@ -2083,6 +2083,9 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) max_link_cap.link_spread = link->reported_link_cap.link_spread; + if (!link->dpcd_caps.dp_128b_132b_supported_link_rates.bits.UHBR13_5) + is_uhbr13_5_supported = false; + /* Lower link settings based on cable attributes * Cable ID is a DP2 feature to identify max certified link rate that * a cable can carry. The cable identification method requires both @@ -2101,9 +2104,13 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) cable_max_link_rate = get_cable_max_link_rate(link); if (!link->dc->debug.ignore_cable_id && - cable_max_link_rate != LINK_RATE_UNKNOWN && - cable_max_link_rate < max_link_cap.link_rate) - max_link_cap.link_rate = cable_max_link_rate; + cable_max_link_rate != LINK_RATE_UNKNOWN) { + if (cable_max_link_rate < max_link_cap.link_rate) + max_link_cap.link_rate = cable_max_link_rate; + + if (!link->dpcd_caps.cable_id.bits.UHBR13_5_CAPABILITY) + is_uhbr13_5_supported = false; + } /* account for lttpr repeaters cap * notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3). @@ -2116,12 +2123,19 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link) if (lttpr_max_link_rate < max_link_cap.link_rate) max_link_cap.link_rate = lttpr_max_link_rate; + if (!link->dpcd_caps.lttpr_caps.supported_128b_132b_rates.bits.UHBR13_5) + is_uhbr13_5_supported = false; + DC_LOG_HW_LINK_TRAINING("%s\n Training with LTTPR, max_lane count %d max_link rate %d \n", __func__, max_link_cap.lane_count, max_link_cap.link_rate); } + if (max_link_cap.link_rate == LINK_RATE_UHBR13_5 && + !is_uhbr13_5_supported) + max_link_cap.link_rate = LINK_RATE_UHBR10; + if (link_dp_get_encoding_format(_link_cap) == DP_128b_132b_ENCODING && link->dc->debug.disable_uhbr) max_link_cap.link_rate = LINK_RATE_HIGH3; -- 2.34.1
[PATCH 12/20] drm/amd/display: Enable SYMCLK gating in DCCG
From: Daniel Miess [WHY & HOW] Enable root clock optimization for SYMCLK and only disable it when it's actively used. Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Daniel Miess --- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/dc/dccg/dcn35/dcn35_dccg.c| 102 ++ .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 45 +++- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 2 + .../amd/display/dc/hwss/dcn35/dcn35_init.c| 1 + .../amd/display/dc/hwss/dcn351/dcn351_init.c | 1 + .../display/dc/hwss/hw_sequencer_private.h| 4 + drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 7 ++ 8 files changed, 115 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 2fce8c0303fa..eef2f357fe14 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -726,6 +726,7 @@ enum pg_hw_pipe_resources { PG_DPSTREAM, PG_HDMISTREAM, PG_PHYSYMCLK, + PG_SYMCLK, PG_HW_PIPE_RESOURCES_NUM_ELEMENT }; diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c index 1fc3aa2b507b..d3b27920e294 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c @@ -655,9 +655,61 @@ static void dccg35_disable_symclk32_se( } } +static void dccg35_set_symclk_root_clock_gating(struct dccg *dccg, uint32_t stream_enc_inst, + uint32_t link_enc_inst, bool enable) +{ + struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg); + + switch (stream_enc_inst) { + case 0: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 1: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 2: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 3: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 4: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_FE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + } + + switch (link_enc_inst) { + case 0: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKA_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 1: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKB_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 2: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKC_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 3: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKD_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + case 4: + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, SYMCLKE_ROOT_GATE_DISABLE, enable ? 1 : 0); + break; + } +} + void dccg35_init(struct dccg *dccg) { - int otg_inst; + int otg_inst, phy_inst; /* Set HPO stream encoder to use refclk to avoid case where PHY is * disabled and SYMCLK32 for HPO SE is sourced from PHYD32CLK which * will cause DCN to hang. @@ -671,10 +723,9 @@ void dccg35_init(struct dccg *dccg) dccg31_set_symclk32_le_root_clock_gating(dccg, otg_inst, false); } -// if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk32_se) -// for (otg_inst = 0; otg_inst < 4; otg_inst++) -// dccg35_disable_symclk_se(dccg, otg_inst, otg_inst); - + if (dccg->ctx->dc->debug.root_clock_optimization.bits.symclk_fe) + for (phy_inst = 0; phy_inst < 5; phy_inst++) +
[PATCH 11/20] drm/amd/display: Expand to higher link rates
From: Sung Joon Kim [WHY & HOW] To support higher link rates that sink allows, we need to make sure driver is ready and perform correct link-training sequence. Reviewed-by: Wenjing Liu Acked-by: Alex Hung Signed-off-by: Sung Joon Kim --- .../gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index 107b2cec572d..8f57b344f09e 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -209,6 +209,9 @@ static enum dc_link_rate linkRateInKHzToLinkRateMultiplier(uint32_t link_rate_in case 810: link_rate = LINK_RATE_HIGH3;// Rate_9 (HBR3)- 8.10 Gbps/Lane break; + case 1000: + link_rate = LINK_RATE_UHBR10; // UHBR10 - 10.0 Gbps/Lane + break; default: link_rate = LINK_RATE_UNKNOWN; break; -- 2.34.1
[PATCH 10/20] drm/amd/display: Add left edge pixel for YCbCr422/420 + ODM pipe split
From: Wenjing Liu [WHY] Currently 3-tap chroma subsampling is used for YCbCr422/420. When ODM pipesplit is used, pixels on the left edge of ODM slices need one extra pixel from the right edge of the previous slice to calculate the correct chroma value. Without this change, the chroma value is slightly different than expected. This is usually imperceptible visually, but it impacts test pattern CRCs for compliance test automation. [HOW] Update logic to use the register for adding extra left edge pixel for YCbCr422/420 ODM cases. Reviewed-by: George Shen Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 9 ++- .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.c | 25 +-- .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.h | 4 +- .../drm/amd/display/dc/dcn201/dcn201_opp.c| 1 + .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 67 +-- .../amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 4 +- .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 8 ++- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 4 +- .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 48 - drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 7 +- .../amd/display/dc/inc/hw/timing_generator.h | 2 +- .../amd/display/dc/optc/dcn20/dcn20_optc.c| 6 +- .../amd/display/dc/optc/dcn20/dcn20_optc.h| 2 +- .../amd/display/dc/optc/dcn30/dcn30_optc.c| 6 +- .../amd/display/dc/optc/dcn30/dcn30_optc.h| 2 +- .../amd/display/dc/optc/dcn31/dcn31_optc.c| 8 +-- .../amd/display/dc/optc/dcn314/dcn314_optc.c | 7 +- .../amd/display/dc/optc/dcn32/dcn32_optc.c| 7 +- .../amd/display/dc/optc/dcn35/dcn35_optc.c| 7 +- .../amd/display/dc/optc/dcn401/dcn401_optc.c | 22 ++ 20 files changed, 140 insertions(+), 106 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 fd03d7129ffa..fd624b1fee25 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2110,12 +2110,19 @@ struct rect resource_get_odm_slice_src_rect(struct pipe_ctx *pipe_ctx) struct rect odm_slice_dst; struct rect odm_slice_src; struct pipe_ctx *opp_head = resource_get_opp_head(pipe_ctx); + struct output_pixel_processor *opp = opp_head->stream_res.opp; uint32_t left_edge_extra_pixel_count; odm_slice_dst = resource_get_odm_slice_dst_rect(opp_head); odm_slice_src = odm_slice_dst; - left_edge_extra_pixel_count = 0; + if (opp->funcs->opp_get_left_edge_extra_pixel_count) + left_edge_extra_pixel_count = + opp->funcs->opp_get_left_edge_extra_pixel_count( + opp, pipe_ctx->stream->timing.pixel_encoding, + resource_is_pipe_type(opp_head, OTG_MASTER)); + else + left_edge_extra_pixel_count = 0; odm_slice_src.x -= left_edge_extra_pixel_count; odm_slice_src.width += left_edge_extra_pixel_count; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c index fbf1b6370eb2..f5fe0cac7cb0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c @@ -23,6 +23,7 @@ * */ +#include "core_types.h" #include "dm_services.h" #include "dcn20_opp.h" #include "reg_helper.h" @@ -350,19 +351,32 @@ bool opp2_dpg_is_pending(struct output_pixel_processor *opp) return (dpg_en == 1 && double_buffer_pending == 1); } -void opp2_program_left_edge_extra_pixel ( +void opp2_program_left_edge_extra_pixel( struct output_pixel_processor *opp, - bool count) + enum dc_pixel_encoding pixel_encoding, + bool is_primary) { struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp); + uint32_t count = opp2_get_left_edge_extra_pixel_count(opp, pixel_encoding, is_primary); - /* Specifies the number of extra left edge pixels that are supplied to + /* +* Specifies the number of extra left edge pixels that are supplied to * the 422 horizontal chroma sub-sample filter. -* Note that when left edge pixel is not "0", fmt pixel encoding can be in either 420 or 422 mode -* */ +*/ REG_UPDATE(FMT_422_CONTROL, FMT_LEFT_EDGE_EXTRA_PIXEL_COUNT, count); } +uint32_t opp2_get_left_edge_extra_pixel_count(struct output_pixel_processor *opp, + enum dc_pixel_encoding pixel_encoding, bool is_primary) +{ + if ((pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) && + !opp->ctx->dc->debug.force_chroma_subsampling_1tap &&a
[PATCH 09/20] drm/amd/display: Add resource interfaces for get ODM slice rect
From: Wenjing Liu [WHY] We need an unified location to perform ODM slice rect calculation. [HOW] Add three interfaces for ODM slice rect/width calucaltion in resource.h Reviewed-by: George Shen Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 137 ++ drivers/gpu/drm/amd/display/dc/inc/resource.h | 10 ++ 2 files changed, 83 insertions(+), 64 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 532882ee7b2b..fd03d7129ffa 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -816,37 +816,6 @@ static struct rect shift_rec(const struct rect *rec_in, int x, int y) return rec_out; } -static struct rect calculate_odm_slice_in_timing_active(struct pipe_ctx *pipe_ctx) -{ - const struct dc_stream_state *stream = pipe_ctx->stream; - int odm_slice_count = resource_get_odm_slice_count(pipe_ctx); - int odm_slice_idx = resource_get_odm_slice_index(pipe_ctx); - bool is_last_odm_slice = (odm_slice_idx + 1) == odm_slice_count; - int h_active = stream->timing.h_addressable + - stream->timing.h_border_left + - stream->timing.h_border_right; - int odm_slice_width = h_active / odm_slice_count; - struct rect odm_rec; - bool is_two_pixels_per_container = - pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(>timing); - - if ((odm_slice_width % 2) && is_two_pixels_per_container) - odm_slice_width++; - - odm_rec.x = odm_slice_width * odm_slice_idx; - odm_rec.width = is_last_odm_slice ? - /* last slice width is the reminder of h_active */ - h_active - odm_slice_width * (odm_slice_count - 1) : - /* odm slice width is the floor of h_active / count */ - odm_slice_width; - odm_rec.y = 0; - odm_rec.height = stream->timing.v_addressable + - stream->timing.v_border_bottom + - stream->timing.v_border_top; - - return odm_rec; -} - static struct rect calculate_plane_rec_in_timing_active( struct pipe_ctx *pipe_ctx, const struct rect *rec_in) @@ -1134,7 +1103,7 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx) */ struct rect plane_clip; struct rect mpc_slice_of_plane_clip; - struct rect odm_slice; + struct rect odm_slice_src; struct rect overlapping_area; plane_clip = calculate_plane_rec_in_timing_active(pipe_ctx, @@ -1144,16 +1113,16 @@ static void calculate_recout(struct pipe_ctx *pipe_ctx) _ctx->stream->dst); mpc_slice_of_plane_clip = calculate_mpc_slice_in_timing_active( pipe_ctx, _clip); - odm_slice = calculate_odm_slice_in_timing_active(pipe_ctx); - overlapping_area = intersect_rec(_slice_of_plane_clip, _slice); + odm_slice_src = resource_get_odm_slice_src_rect(pipe_ctx); + overlapping_area = intersect_rec(_slice_of_plane_clip, _slice_src); if (overlapping_area.height > 0 && overlapping_area.width > 0) { /* shift the overlapping area so it is with respect to current -* ODM slice's position +* ODM slice source's position */ pipe_ctx->plane_res.scl_data.recout = shift_rec( _area, - -odm_slice.x, -odm_slice.y); + -odm_slice_src.x, -odm_slice_src.y); adjust_recout_for_visual_confirm( _ctx->plane_res.scl_data.recout, pipe_ctx); @@ -1290,13 +1259,13 @@ static void calculate_inits_and_viewports(struct pipe_ctx *pipe_ctx) struct rect recout_clip_in_active_timing; struct rect recout_clip_in_recout_dst; struct rect overlap_in_active_timing; - struct rect odm_slice = calculate_odm_slice_in_timing_active(pipe_ctx); + struct rect odm_slice_src = resource_get_odm_slice_src_rect(pipe_ctx); int vpc_div = (data->format == PIXEL_FORMAT_420BPP8 || data->format == PIXEL_FORMAT_420BPP10) ? 2 : 1; bool orthogonal_rotation, flip_vert_scan_dir, flip_horz_scan_dir; recout_clip_in_active_timing = shift_rec( - >recout, odm_slice.x, odm_slice.y); + >recout, odm_slice_src.x, odm_slice_src.y); recout_dst_in_active_timing = calculate_plane_rec_in_timing_active( pipe_ctx, _state->dst_rect); overlap_in_active_
[PATCH 08/20] drm/amd/display: Add COEF filter types for DCN401
From: Samson Tam Add VERTICAL_BLUR_SCALE & HORIZONTAL_BLUR_SCALE types. Reviewed-by: Jun Lei Acked-by: Alex Hung Signed-off-by: Samson Tam --- drivers/gpu/drm/amd/display/dc/dpp/dcn401/dcn401_dpp_dscl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 696ccf96b847..d9a08cd160b3 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 @@ -56,7 +56,9 @@ enum dcn401_coef_filter_type_sel { SCL_COEF_CHROMA_VERT_FILTER = 2, SCL_COEF_CHROMA_HORZ_FILTER = 3, SCL_COEF_ALPHA_VERT_FILTER = 4, - SCL_COEF_ALPHA_HORZ_FILTER = 5 + SCL_COEF_ALPHA_HORZ_FILTER = 5, + SCL_COEF_VERTICAL_BLUR_SCALE = SCL_COEF_ALPHA_VERT_FILTER, + SCL_COEF_HORIZONTAL_BLUR_SCALE = SCL_COEF_ALPHA_HORZ_FILTER }; enum dscl_autocal_mode { -- 2.34.1
[PATCH 07/20] drm/amd/display: Refactor DCN401 DCCG into component directory
From: Revalla Hari Krishna [WHY] Clean up the code that requires dccg to be in its own component. [HOW] Move all files under newly created dccg dir and fix the makefiles. Acked-by: Alex Hung Reviewed-by: Rodrigo Siqueira Signed-off-by: Revalla Hari Krishna --- drivers/gpu/drm/amd/display/dc/dccg/Makefile | 7 ++- .../gpu/drm/amd/display/dc/{ => dccg}/dcn401/dcn401_dccg.c | 0 .../gpu/drm/amd/display/dc/{ => dccg}/dcn401/dcn401_dccg.h | 0 drivers/gpu/drm/amd/display/dc/dcn401/Makefile | 1 - 4 files changed, 6 insertions(+), 2 deletions(-) rename drivers/gpu/drm/amd/display/dc/{ => dccg}/dcn401/dcn401_dccg.c (100%) rename drivers/gpu/drm/amd/display/dc/{ => dccg}/dcn401/dcn401_dccg.h (100%) diff --git a/drivers/gpu/drm/amd/display/dc/dccg/Makefile b/drivers/gpu/drm/amd/display/dc/dccg/Makefile index bfdce98768f1..1d5cf0f8e79d 100644 --- a/drivers/gpu/drm/amd/display/dc/dccg/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dccg/Makefile @@ -95,4 +95,9 @@ AMD_DAL_DCCG_DCN35 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn35/,$(DCCG_DCN35)) AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN35) ### -endif \ No newline at end of file +DCCG_DCN401 = dcn401_dccg.o + +AMD_DAL_DCCG_DCN401 = $(addprefix $(AMDDALPATH)/dc/dccg/dcn401/,$(DCCG_DCN401)) + +AMD_DISPLAY_FILES += $(AMD_DAL_DCCG_DCN401) +endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c similarity index 100% rename from drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dccg.c rename to drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.c diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dccg.h b/drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h similarity index 100% rename from drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dccg.h rename to drivers/gpu/drm/amd/display/dc/dccg/dcn401/dcn401_dccg.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/Makefile b/drivers/gpu/drm/amd/display/dc/dcn401/Makefile index 2e15e639194d..73544559f41f 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn401/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn401/Makefile @@ -6,7 +6,6 @@ DCN401 += dcn401_dio_link_encoder.o DCN401 += dcn401_dio_stream_encoder.o DCN401 += dcn401_hubp.o DCN401 += dcn401_mpc.o -DCN401 += dcn401_dccg.o DCN401 += dcn401_hubbub.o AMD_DAL_DCN401 = $(addprefix $(AMDDALPATH)/dc/dcn401/,$(DCN401)) -- 2.34.1
[PATCH 06/20] drm/amd/display: Fix 3dlut size for Fastloading on DCN401
From: Adam Nelson [WHY] After a non-3dlut test the MPCC_MCM_3DLUT_MODE::MPCC_MCM_3DLUT_SIZE is incorrect. [HOW] Add register write to make valid. Acked-by: Alex Hung Reviewed-by: Rodrigo Siqueira Signed-off-by: Adam Nelson --- drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.c| 8 drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.h| 5 + drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 3 +++ drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 1 + 4 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.c index d6c99c6c2b35..37ab5a4eefc7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.c @@ -297,6 +297,13 @@ void mpc401_program_lut_read_write_control(struct mpc *mpc, const enum MCM_LUT_I } } +void mpc401_program_3dlut_size(struct mpc *mpc, bool is_17x17x17, int mpcc_id) +{ + struct dcn401_mpc *mpc401 = TO_DCN401_MPC(mpc); + + REG_UPDATE(MPCC_MCM_3DLUT_MODE[mpcc_id], MPCC_MCM_3DLUT_SIZE, is_17x17x17 ? 0 : 1); +} + static void program_gamut_remap( struct mpc *mpc, unsigned int mpcc_id, @@ -615,6 +622,7 @@ static const struct mpc_funcs dcn401_mpc_funcs = { .populate_lut = mpc401_populate_lut, .program_lut_read_write_control = mpc401_program_lut_read_write_control, .program_lut_mode = mpc401_program_lut_mode, + .program_3dlut_size = mpc401_program_3dlut_size, }; diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.h index a8ef67695757..af44054c2477 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_mpc.h @@ -221,6 +221,11 @@ void mpc401_program_lut_read_write_control( bool lut_bank_a, int mpcc_id); +void mpc401_program_3dlut_size( + struct mpc *mpc, + bool is_17x17x17, + int mpcc_id); + void mpc401_set_gamut_remap( struct mpc *mpc, int mpcc_id, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 3b74c4a9c2a8..5b87186598e6 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -478,6 +478,7 @@ void dcn401_populate_mcm_luts(struct dc *dc, enum MCM_LUT_XABLE shaper_xable = MCM_LUT_DISABLE; enum MCM_LUT_XABLE lut3d_xable = MCM_LUT_DISABLE; enum MCM_LUT_XABLE lut1d_xable = MCM_LUT_DISABLE; + bool is_17x17x17 = true; dcn401_get_mcm_lut_xable_from_pipe_ctx(dc, pipe_ctx, _xable, _xable, _xable); @@ -543,6 +544,8 @@ void dcn401_populate_mcm_luts(struct dc *dc, mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, mpcc_id); if (mpc->funcs->program_lut_mode) mpc->funcs->program_lut_mode(mpc, MCM_LUT_3DLUT, lut3d_xable, lut_bank_a, mpcc_id); + if (mpc->funcs->program_3dlut_size) + mpc->funcs->program_3dlut_size(mpc, is_17x17x17, mpcc_id); if (hubp->funcs->hubp_program_3dlut_fl_addr) hubp->funcs->hubp_program_3dlut_fl_addr(hubp, mcm_luts.lut3d_data.gpu_mem_params.addr); switch (mcm_luts.lut3d_data.gpu_mem_params.layout) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h index dd786600668f..34cf8efc5cb9 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h @@ -576,6 +576,7 @@ struct mpc_funcs { void (*program_lut_read_write_control)(struct mpc *mpc, const enum MCM_LUT_ID id, bool lut_bank_a, int mpcc_id); void (*program_lut_mode)(struct mpc *mpc, const enum MCM_LUT_ID id, const enum MCM_LUT_XABLE xable, bool lut_bank_a, int mpcc_id); + void (*program_3dlut_size)(struct mpc *mpc, bool is_17x17x17, int mpcc_id); }; #endif -- 2.34.1
[PATCH 05/20] drm/amd/display: Fix write to non-existent reg on DCN401
From: Ilya Bakoulin DP_DSC_CNTL no longer exists on DCN401. Acked-by: Alex Hung Reviewed-by: Rodrigo Siqueira Signed-off-by: Ilya Bakoulin --- .../dc/dcn401/dcn401_dio_stream_encoder.c | 20 +++ 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.c index 1c55ccede09b..090288305609 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn401/dcn401_dio_stream_encoder.c @@ -372,21 +372,6 @@ static void enc401_stream_encoder_dp_unblank( link->dc->link_srv->dp_trace_source_sequence(link, DPCD_SOURCE_SEQ_AFTER_ENABLE_DP_VID_STREAM); } -/* Set DSC-related configuration. - * dsc_mode: 0 disables DSC, other values enable DSC in specified format - * sc_bytes_per_pixel: DP_DSC_BYTES_PER_PIXEL removed in DCN3x - * dsc_slice_width: DP_DSC_SLICE_WIDTH removed in DCN3x - */ -static void enc401_dp_set_dsc_config(struct stream_encoder *enc, - enum optc_dsc_mode dsc_mode, - uint32_t dsc_bytes_per_pixel, - uint32_t dsc_slice_width) -{ - struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); - - REG_UPDATE(DP_DSC_CNTL, DP_DSC_MODE, dsc_mode == OPTC_DSC_DISABLED ? 0 : 1); -} - /* this function read dsc related register fields to be logged later in dcn10_log_hw_state * into a dcn_dsc_state struct. */ @@ -395,7 +380,8 @@ static void enc401_read_state(struct stream_encoder *enc, struct enc_state *s) struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); //if dsc is enabled, continue to read - REG_GET(DP_DSC_CNTL, DP_DSC_MODE, >dsc_mode); + REG_GET(DP_PIXEL_FORMAT, PIXEL_ENCODING_TYPE, >dsc_mode); + if (s->dsc_mode) { REG_GET(DP_GSP11_CNTL, DP_SEC_GSP11_LINE_NUM, >sec_gsp_pps_line_num); @@ -770,7 +756,7 @@ static const struct stream_encoder_funcs dcn401_str_enc_funcs = { .dp_get_pixel_format = enc1_stream_encoder_dp_get_pixel_format, .enc_read_state = enc401_read_state, - .dp_set_dsc_config = enc401_dp_set_dsc_config, + .dp_set_dsc_config = NULL, .dp_set_dsc_pps_info_packet = enc3_dp_set_dsc_pps_info_packet, .set_dynamic_metadata = enc401_set_dynamic_metadata, .hdmi_reset_stream_attribute = enc1_reset_hdmi_stream_attribute, -- 2.34.1
[PATCH 04/20] drm/amd/display: Remove USBC check for DCN32
From: Rodrigo Siqueira The CONNECTOR_ID_USBC check was removed to fix a regression, but it was re-introduced by accident. This commit drops the USBC that causes the regressions. Acked-by: Alex Hung Signed-off-by: Rodrigo Siqueira --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c index d9ff95cd2dbd..06907e8a4eda 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dio_link_encoder.c @@ -252,9 +252,6 @@ void dcn32_link_encoder_construct( enc10->base.features = *enc_features; - if (enc10->base.connector.id == CONNECTOR_ID_USBC) - enc10->base.features.flags.bits.DP_IS_USB_C = 1; - enc10->base.transmitter = init_data->transmitter; /* set the flag to indicate whether driver poll the I2C data pin -- 2.34.1
[PATCH 03/20] drm/amd/display: Remove unused code for some dc files
From: Rodrigo Siqueira Cleanup unused code in DC. Acked-by: Alex Hung Signed-off-by: Rodrigo Siqueira --- drivers/gpu/drm/amd/display/dc/core/dc.c | 9 - drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 3 --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h | 4 3 files changed, 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d19c67205de6..0f20a3d96d93 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3614,9 +3614,6 @@ static void commit_plane_for_stream_offload_fams2_flip(struct dc *dc, for (i = 0; i < surface_count; i++) { struct dc_plane_state *plane_state = srf_updates[i].surface; - /* set offload flag so driver does not program address */ - plane_state->address.offload_flip = true; - for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = >res_ctx.pipe_ctx[j]; @@ -3638,12 +3635,6 @@ static void commit_plane_for_stream_offload_fams2_flip(struct dc *dc, stream, srf_updates, surface_count); - - /* reset offload flip flag */ - for (i = 0; i < surface_count; i++) { - struct dc_plane_state *plane_state = srf_updates[i].surface; - plane_state->address.offload_flip = false; - } } static void commit_planes_for_stream_fast(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index 226285037b2b..959ae0df1e56 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -125,9 +125,6 @@ struct dc_plane_address { union large_integer page_table_base; uint8_t vmid; - /* dc should use hw flip queue rather than directly programming the surface address. -* Value is determined on each flip. */ - bool offload_flip; }; struct dc_size { diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h index 54f889cfd911..ce93003dae01 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h @@ -1091,10 +1091,6 @@ void mpc3_power_on_ogam_lut( void mpc3_init_mpcc(struct mpcc *mpcc, int mpcc_inst); -void mpc3_mpc_init_single_inst( - struct mpc *mpc, - unsigned int mpcc_id); - enum dc_lut_mode mpc3_get_ogam_current( struct mpc *mpc, int mpcc_id); -- 2.34.1
[PATCH 02/20] drm/amd/display: Disable AC/DC codepath when unnecessary
From: Joshua Aberback [WHY] If there are no DC clock limits present, or if the DC limits are the same as the AC limits, we can disable the AC/DC codepath as there won't be any validation differences between the two modes. [HOW] When all DC power mode clock limits are the same as the max clock values, there won't be any difference between AC mode and DC mode. Zero out DC limits that equal max and provide a new cap to indicate the presence of any non-zero DC mode limit. In summary: - zero out DC limits that are the same as max clock value - new dc cap to indicate the presence of DC mode limits - set limits present if any clock has distinct AC and DC values from SMU Acked-by: Alex Hung Reviewed-by: Rodrigo Siqueira Signed-off-by: Joshua Aberback --- .../dc/clk_mgr/dcn401/dcn401_clk_mgr.c| 28 ++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 12 +++- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c index 1cf750cfed66..bd74ff47fb37 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c @@ -180,7 +180,6 @@ static void dcn401_build_wm_range_table(struct clk_mgr *clk_mgr) void dcn401_init_clocks(struct clk_mgr *clk_mgr_base) { struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base); - unsigned int num_levels; struct clk_limit_num_entries *num_entries_per_clk = _mgr_base->bw_params->clk_table.num_entries_per_clk; unsigned int i; @@ -208,34 +207,43 @@ void dcn401_init_clocks(struct clk_mgr *clk_mgr_base) _mgr_base->bw_params->clk_table.entries[0].dcfclk_mhz, _entries_per_clk->num_dcfclk_levels); clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DCFCLK); + if (num_entries_per_clk->num_dcfclk_levels && clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_dcfclk_levels - 1].dcfclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.dcfclk_mhz = 0; /* SOCCLK */ dcn401_init_single_clock(clk_mgr, PPCLK_SOCCLK, _mgr_base->bw_params->clk_table.entries[0].socclk_mhz, _entries_per_clk->num_socclk_levels); clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_SOCCLK); + if (num_entries_per_clk->num_socclk_levels && clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_socclk_levels - 1].socclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.socclk_mhz = 0; /* DTBCLK */ if (!clk_mgr->base.ctx->dc->debug.disable_dtb_ref_clk_switch) { dcn401_init_single_clock(clk_mgr, PPCLK_DTBCLK, _mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz, _entries_per_clk->num_dtbclk_levels); - clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz = - dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DTBCLK); + clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DTBCLK); + if (num_entries_per_clk->num_dtbclk_levels && clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_dtbclk_levels - 1].dtbclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.dtbclk_mhz = 0; } /* DISPCLK */ dcn401_init_single_clock(clk_mgr, PPCLK_DISPCLK, _mgr_base->bw_params->clk_table.entries[0].dispclk_mhz, _entries_per_clk->num_dispclk_levels); - num_levels = num_entries_per_clk->num_dispclk_levels; clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DISPCLK); + if (num_entries_per_clk->num_dispclk_levels && clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz == + clk_mgr_base->bw_params->clk_table.entries[num_entries_per_clk->num_dispclk_levels - 1].dispclk_mhz) + clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = 0; /* DPPCLK */ dcn401_init_single_clock(clk_mgr, PPC
[PATCH 01/20] drm/amd/display: Create dcn401_clk_mgr struct
From: Dillon Varone Create dcn401 specific structure to encapsulate version specific variables. Acked-by: Alex Hung Reviewed-by: Rodrigo Siqueira Signed-off-by: Dillon Varone --- .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 3 +-- .../dc/clk_mgr/dcn401/dcn401_clk_mgr.c| 23 --- .../dc/clk_mgr/dcn401/dcn401_clk_mgr.h| 10 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c index 5f67d159e1e2..f770828df149 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c @@ -367,14 +367,13 @@ struct clk_mgr *dc_clk_mgr_create(struct dc_context *ctx, struct pp_smu_funcs *p break; case AMDGPU_FAMILY_GC_12_0_0: { - struct clk_mgr_internal *clk_mgr = kzalloc(sizeof(*clk_mgr), GFP_KERNEL); + struct clk_mgr_internal *clk_mgr = dcn401_clk_mgr_construct(ctx, dccg); if (clk_mgr == NULL) { BREAK_TO_DEBUGGER(); return NULL; } - dcn401_clk_mgr_construct(ctx, clk_mgr, pp_smu, dccg); return _mgr->base; } break; diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c index 7db7446ad91f..1cf750cfed66 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.c @@ -935,14 +935,18 @@ static struct clk_mgr_funcs dcn401_funcs = { .is_smu_present = dcn401_is_smu_present, }; -void dcn401_clk_mgr_construct( +struct clk_mgr_internal *dcn401_clk_mgr_construct( struct dc_context *ctx, - struct clk_mgr_internal *clk_mgr, - struct pp_smu_funcs *pp_smu, struct dccg *dccg) { struct clk_log_info log_info = {0}; + struct dcn401_clk_mgr *clk_mgr401 = kzalloc(sizeof(struct dcn401_clk_mgr), GFP_KERNEL); + struct clk_mgr_internal *clk_mgr; + + if (!clk_mgr401) + return NULL; + clk_mgr = _mgr401->base; clk_mgr->base.ctx = ctx; clk_mgr->base.funcs = _funcs; clk_mgr->regs = _mgr_regs_dcn401; @@ -987,11 +991,24 @@ void dcn401_clk_mgr_construct( clk_mgr->smu_present = false; clk_mgr->base.bw_params = kzalloc(sizeof(*clk_mgr->base.bw_params), GFP_KERNEL); + if (!clk_mgr->base.bw_params) { + BREAK_TO_DEBUGGER(); + kfree(clk_mgr); + return NULL; + } /* need physical address of table to give to PMFW */ clk_mgr->wm_range_table = dm_helpers_allocate_gpu_mem(clk_mgr->base.ctx, DC_MEM_ALLOC_TYPE_GART, sizeof(WatermarksExternal_t), _mgr->wm_range_table_addr); + if (!clk_mgr->wm_range_table) { + BREAK_TO_DEBUGGER(); + kfree(clk_mgr->base.bw_params); + return NULL; + } + + return _mgr401->base; + } void dcn401_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h index 496540ec1950..dad203de0dd4 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn401/dcn401_clk_mgr.h @@ -5,11 +5,13 @@ #ifndef __DCN401_CLK_MGR_H_ #define __DCN401_CLK_MGR_H_ +struct dcn401_clk_mgr { + struct clk_mgr_internal base; +}; + void dcn401_init_clocks(struct clk_mgr *clk_mgr_base); -void dcn401_clk_mgr_construct(struct dc_context *ctx, - struct clk_mgr_internal *clk_mgr, - struct pp_smu_funcs *pp_smu, +struct clk_mgr_internal *dcn401_clk_mgr_construct(struct dc_context *ctx, struct dccg *dccg); void dcn401_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, @@ -17,6 +19,4 @@ void dcn401_update_clocks_update_dpp_dto(struct clk_mgr_internal *clk_mgr, void dcn401_clk_mgr_destroy(struct clk_mgr_internal *clk_mgr); - - #endif /* __DCN401_CLK_MGR_H_ */ -- 2.34.1
[PATCH 00/20] DC Patches May 08, 2024
This DC patchset brings improvements in multiple areas. In summary, we have: * Fixes on DCN401, 3dlut and I2C * Improvements on AC/DC, link rates, DSC and ODM slice rect and pipe * Refactoring on code styles and unused code Cc: Daniel Wheeler Adam Nelson (1): drm/amd/display: Fix 3dlut size for Fastloading on DCN401 Alvin Lee (1): drm/amd/display: Don't offload flip if not only address update Aric Cyr (1): drm/amd/display: 3.2.285 Chris Park (1): drm/amd/display: Reduce I2C speed to 95kHz in DCN401 Daniel Miess (1): drm/amd/display: Enable SYMCLK gating in DCCG Dillon Varone (2): drm/amd/display: Create dcn401_clk_mgr struct drm/amd/display: Refactor dcn401_update_clocks Duncan Ma (1): drm/amd/display: Read default boot options Ethan Bitnun (1): drm/amd/display: Find max flickerless instant vtotal delta George Shen (1): drm/amd/display: Check UHBR13.5 cap when determining max link cap Ilya Bakoulin (1): drm/amd/display: Fix write to non-existent reg on DCN401 Joshua Aberback (1): drm/amd/display: Disable AC/DC codepath when unnecessary Revalla Hari Krishna (1): drm/amd/display: Refactor DCN401 DCCG into component directory Rodrigo Siqueira (2): drm/amd/display: Remove unused code for some dc files drm/amd/display: Remove USBC check for DCN32 Samson Tam (1): drm/amd/display: Add COEF filter types for DCN401 Sung Joon Kim (1): drm/amd/display: Expand to higher link rates Wenjing Liu (3): drm/amd/display: Add resource interfaces for get ODM slice rect drm/amd/display: Add left edge pixel for YCbCr422/420 + ODM pipe split drm/amd/display: Allow higher DSC slice support for small timings on dcn401 .../gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c | 3 +- .../amd/display/dc/clk_mgr/dcn401/dalsmc.h| 8 +- .../dc/clk_mgr/dcn401/dcn401_clk_mgr.c| 574 +- .../dc/clk_mgr/dcn401/dcn401_clk_mgr.h| 104 +++- .../clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.c | 80 ++- .../clk_mgr/dcn401/dcn401_clk_mgr_smu_msg.h | 10 + drivers/gpu/drm/amd/display/dc/core/dc.c | 13 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 150 +++-- .../gpu/drm/amd/display/dc/core/dc_stream.c | 64 +- drivers/gpu/drm/amd/display/dc/dc.h | 7 +- drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 3 - .../gpu/drm/amd/display/dc/dc_stream_priv.h | 14 + drivers/gpu/drm/amd/display/dc/dccg/Makefile | 7 +- .../amd/display/dc/dccg/dcn35/dcn35_dccg.c| 102 ++-- .../dc/{ => dccg}/dcn401/dcn401_dccg.c| 0 .../dc/{ => dccg}/dcn401/dcn401_dccg.h| 0 .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.c | 25 +- .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.h | 4 +- .../drm/amd/display/dc/dcn201/dcn201_opp.c| 1 + .../gpu/drm/amd/display/dc/dcn30/dcn30_mpc.h | 4 - .../display/dc/dcn32/dcn32_dio_link_encoder.c | 3 - .../display/dc/dcn32/dcn32_resource_helpers.c | 2 +- .../gpu/drm/amd/display/dc/dcn401/Makefile| 1 - .../dc/dcn401/dcn401_dio_stream_encoder.c | 20 +- .../drm/amd/display/dc/dcn401/dcn401_mpc.c| 8 + .../drm/amd/display/dc/dcn401/dcn401_mpc.h| 5 + .../drm/amd/display/dc/dml2/dml2_wrapper.h| 3 + .../display/dc/dpp/dcn401/dcn401_dpp_dscl.c | 4 +- .../amd/display/dc/dsc/dcn401/dcn401_dsc.c| 412 ++--- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 67 +- .../amd/display/dc/hwss/dcn314/dcn314_hwseq.c | 4 +- .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 8 +- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 49 +- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 2 + .../amd/display/dc/hwss/dcn35/dcn35_init.c| 1 + .../amd/display/dc/hwss/dcn351/dcn351_init.c | 1 + .../amd/display/dc/hwss/dcn401/dcn401_hwseq.c | 63 +- .../display/dc/hwss/hw_sequencer_private.h| 4 + drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h | 7 + drivers/gpu/drm/amd/display/dc/inc/hw/mpc.h | 1 + drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 7 +- .../amd/display/dc/inc/hw/timing_generator.h | 2 +- drivers/gpu/drm/amd/display/dc/inc/resource.h | 10 + .../dc/link/protocols/link_dp_capability.c| 25 +- .../amd/display/dc/optc/dcn20/dcn20_optc.c| 6 +- .../amd/display/dc/optc/dcn20/dcn20_optc.h| 2 +- .../amd/display/dc/optc/dcn30/dcn30_optc.c| 6 +- .../amd/display/dc/optc/dcn30/dcn30_optc.h| 2 +- .../amd/display/dc/optc/dcn31/dcn31_optc.c| 8 +- .../amd/display/dc/optc/dcn314/dcn314_optc.c | 7 +- .../amd/display/dc/optc/dcn32/dcn32_optc.c| 7 +- .../amd/display/dc/optc/dcn35/dcn35_optc.c| 7 +- .../amd/display/dc/optc/dcn401/dcn401_optc.c | 22 +- .../dc/resource/dcn401/dcn401_resource.c | 4 +- .../gpu/drm/amd/display/dmub/src/dmub_dcn35.c | 5 +- .../gpu/drm/amd/display/include/dal_asic_id.h | 3 + 56 files changed, 1293 insertions(+), 668 deletions(-) rename drivers/gpu/drm/amd/display/dc/{ => dccg}/dcn401/dcn401_dccg.c (100%) rename
[PATCH 30/34] drm/amd/display: Backup and restore only on full updates
From: Alvin Lee [WHY & HOW] Since the backup and restore for plane and stream states has a significant amount of data to copy, we will change the backup and restore sequence to only take place during full updates. We will also move the scratch memory to struct dc instead of dc_state to avoid needing to allocate large amounts of memory every time we create a new DC state. Reviewed-by: Wenjing Liu Acked-by: Alex Hung Signed-off-by: Alvin Lee --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 +- .../gpu/drm/amd/display/dc/core/dc_state.c| 1 - drivers/gpu/drm/amd/display/dc/dc.h | 164 ++ .../gpu/drm/amd/display/dc/inc/core_types.h | 22 --- 4 files changed, 100 insertions(+), 97 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d8967087335e..2105e4ba3384 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3162,9 +3162,10 @@ static bool update_planes_and_stream_state(struct dc *dc, } context = dc->current_state; - backup_planes_and_stream_state(>current_state->scratch, stream); update_type = dc_check_update_surfaces_for_stream( dc, srf_updates, surface_count, stream_update, stream_status); + if (update_type == UPDATE_TYPE_FULL) + backup_planes_and_stream_state(>scratch.current_state, stream); /* update current stream with the new updates */ copy_stream_update_to_stream(dc, context, stream, stream_update); @@ -3267,7 +3268,8 @@ static bool update_planes_and_stream_state(struct dc *dc, *new_context = context; *new_update_type = update_type; - backup_planes_and_stream_state(>scratch, stream); + if (update_type == UPDATE_TYPE_FULL) + backup_planes_and_stream_state(>scratch.new_state, stream); return true; @@ -4321,7 +4323,7 @@ static bool commit_minimal_transition_based_on_current_context(struct dc *dc, * This restores back the original stream and plane states associated * with the current state. */ - restore_planes_and_stream_state(>current_state->scratch, stream); + restore_planes_and_stream_state(>scratch.current_state, stream); intermediate_context = create_minimal_transition_state(dc, dc->current_state, ); if (intermediate_context) { @@ -4348,7 +4350,7 @@ static bool commit_minimal_transition_based_on_current_context(struct dc *dc, * Restore stream and plane states back to the values associated with * new context. */ - restore_planes_and_stream_state(_context->scratch, stream); + restore_planes_and_stream_state(>scratch.new_state, stream); return success; } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c index 5cc7f8da209c..cce4e1c465b6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c @@ -310,7 +310,6 @@ void dc_state_destruct(struct dc_state *state) memset(state->dc_dmub_cmd, 0, sizeof(state->dc_dmub_cmd)); state->dmub_cmd_count = 0; memset(>perf_params, 0, sizeof(state->perf_params)); - memset(>scratch, 0, sizeof(state->scratch)); } void dc_state_retain(struct dc_state *state) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 09c6a393642a..9629bd9252b4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -1004,76 +1004,6 @@ struct dc_current_properties { unsigned int cursor_size_limit; }; -struct dc { - struct dc_debug_options debug; - struct dc_versions versions; - struct dc_caps caps; - struct dc_cap_funcs cap_funcs; - struct dc_config config; - struct dc_bounding_box_overrides bb_overrides; - struct dc_bug_wa work_arounds; - struct dc_context *ctx; - struct dc_phy_addr_space_config vm_pa_config; - - uint8_t link_count; - struct dc_link *links[MAX_PIPES * 2]; - struct link_service *link_srv; - - struct dc_state *current_state; - struct resource_pool *res_pool; - - struct clk_mgr *clk_mgr; - - /* Display Engine Clock levels */ - struct dm_pp_clock_levels sclk_lvls; - - /* Inputs into BW and WM calculations. */ - struct bw_calcs_dceip *bw_dceip; - struct bw_calcs_vbios *bw_vbios; - struct dcn_soc_bounding_box *dcn_soc; - struct dcn_ip_params *dcn_ip; - struct display_mode_lib dml; - - /* HW functions */ - struct hw_sequencer_funcs hwss; - struct dce_hwseq *hwseq; - - /* Require to optimize clocks and bandwidth for added/removed planes */ - bool optimized_required; - bool w
[PATCH 34/34] drm/amd/display: 3.2.275
From: Aric Cyr - Support long vblank feature - Add monitor patch for specific eDP - Init DPPCLK from SMU on dcn32 - Update odm when ODM combine is changed on an otg master pipe with no plane - Fix idle check for shared firmware state - Add guards for idle on reg read/write - Guard cursor idle reallow by DC debug option - Add debug counters to IPS exit prints - Add left edge pixel for YCbCr422/420 + ODM pipe split - Amend coasting vtotal for replay low hz - Refactor DPP into a component directory - Set the power_down_on_boot function pointer to null - Implement update_planes_and_stream_v3 sequence - Lock all enabled otg pipes even with no planes - Implement wait_for_odm_update_pending_complete - Add a dc_state NULL check in dc_state_release - Backup and restore only on full updates - Update DMUB flags and definitions - Return the correct HDCP error code - Add comments to v_total calculation and drop legacy TODO Acked-by: Alex Hung Signed-off-by: Aric Cyr --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9629bd9252b4..e17ddda8ec38 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -51,7 +51,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.274" +#define DC_VER "3.2.275" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- 2.34.1
[PATCH 33/34] drm/amd/display: Add comments to v_total calculation and drop legacy TODO
From: Rodrigo Siqueira [WHY & HOW] This commit just adds some simple comments to help understand the calculation of V total duration for Freesync. Also, remove a legacy TODO comment from link service type. Acked-by: Alex Hung Signed-off-by: Rodrigo Siqueira --- drivers/gpu/drm/amd/display/include/link_service_types.h | 1 - drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h index 92dbff22a7c6..1867aac57cf2 100644 --- a/drivers/gpu/drm/amd/display/include/link_service_types.h +++ b/drivers/gpu/drm/amd/display/include/link_service_types.h @@ -73,7 +73,6 @@ struct link_training_settings { enum dc_pre_emphasis *pre_emphasis; enum dc_post_cursor2 *post_cursor2; bool should_set_fec_ready; - /* TODO - factor lane_settings out because it changes during LT */ union dc_dp_ffe_preset *ffe_preset; uint16_t cr_pattern_time; diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index fbaa6effd0e3..b19ef58d1555 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -158,13 +158,13 @@ static unsigned int calc_v_total_from_duration( if (duration_in_us > vrr->max_duration_in_us) duration_in_us = vrr->max_duration_in_us; - if (dc_is_hdmi_signal(stream->signal)) { + if (dc_is_hdmi_signal(stream->signal)) { // change for HDMI to comply with spec uint32_t h_total_up_scaled; h_total_up_scaled = stream->timing.h_total * 1; v_total = div_u64((unsigned long long)duration_in_us * stream->timing.pix_clk_100hz + (h_total_up_scaled - 1), - h_total_up_scaled); + h_total_up_scaled); //ceiling for MMax and MMin for MVRR } else { v_total = div64_u64(div64_u64(((unsigned long long)( duration_in_us) * (stream->timing.pix_clk_100hz / 10)), -- 2.34.1
[PATCH 32/34] drm/amd/display: Return the correct HDCP error code
From: Rodrigo Siqueira [WHY & HOW] If the display is null when creating an HDCP session, return a proper error code. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Acked-by: Alex Hung Signed-off-by: Rodrigo Siqueira --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c index 8c137d7c032e..7c9805705fd3 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp_psp.c @@ -513,6 +513,9 @@ enum mod_hdcp_status mod_hdcp_hdcp2_create_session(struct mod_hdcp *hdcp) hdcp_cmd = (struct ta_hdcp_shared_memory *)psp->hdcp_context.context.mem_context.shared_buf; memset(hdcp_cmd, 0, sizeof(struct ta_hdcp_shared_memory)); + if (!display) + return MOD_HDCP_STATUS_DISPLAY_NOT_FOUND; + hdcp_cmd->in_msg.hdcp2_create_session_v2.display_handle = display->index; if (hdcp->connection.link.adjust.hdcp2.force_type == MOD_HDCP_FORCE_TYPE_0) -- 2.34.1
[PATCH 31/34] drm/amd/display: Update DMUB flags and definitions
From: Anthony Koo [WHAT] - Update replay residency tracing design to support more types including tracking PHY and ALPM residency types - Add commands for Replay frame update count profiling - Enhance HWFQ with additional flags to allow for more optimized IPS low power state residencies - Add new flag to indicate if a new frame update needed for ABM to ramp up into steady state Acked-by: Alex Hung Signed-off-by: Anthony Koo --- .../gpu/drm/amd/display/dc/dce/dmub_replay.c | 2 +- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 40 +-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c index b010814706fe..4f559a025cf0 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_replay.c @@ -244,7 +244,7 @@ static void dmub_replay_residency(struct dmub_replay *dmub, uint8_t panel_inst, uint16_t param = (uint16_t)(panel_inst << 8); if (is_alpm) - param |= REPLAY_RESIDENCY_MODE_ALPM; + param |= REPLAY_RESIDENCY_FIELD_MODE_ALPM; if (is_start) param |= REPLAY_RESIDENCY_ENABLE; diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 4a650ac571d7..b81cd2649db3 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -194,6 +194,11 @@ union abm_flags { * of user backlight level. */ unsigned int abm_gradual_bl_change : 1; + + /** +* @abm_new_frame: Indicates if a new frame update needed for ABM to ramp up into steady +*/ + unsigned int abm_new_frame : 1; } bitfields; unsigned int u32All; @@ -2937,18 +2942,47 @@ struct dmub_rb_cmd_psr_set_power_opt { struct dmub_cmd_psr_set_power_opt_data psr_set_power_opt_data; }; +/** + * Definition of Replay Residency GPINT command. + * Bit[0] - Residency mode for Revision 0 + * Bit[1] - Enable/Disable state + * Bit[2-3] - Revision number + * Bit[4-7] - Residency mode for Revision 1 + * Bit[8] - Panel instance + * Bit[9-15] - Reserved + */ + +enum pr_residency_mode { + PR_RESIDENCY_MODE_PHY = 0x0, + PR_RESIDENCY_MODE_ALPM, + PR_RESIDENCY_MODE_IPS2, + PR_RESIDENCY_MODE_FRAME_CNT, +}; + #define REPLAY_RESIDENCY_MODE_SHIFT(0) #define REPLAY_RESIDENCY_ENABLE_SHIFT (1) +#define REPLAY_RESIDENCY_REVISION_SHIFT(2) +#define REPLAY_RESIDENCY_MODE2_SHIFT (4) #define REPLAY_RESIDENCY_MODE_MASK (0x1 << REPLAY_RESIDENCY_MODE_SHIFT) -# define REPLAY_RESIDENCY_MODE_PHY (0x0 << REPLAY_RESIDENCY_MODE_SHIFT) -# define REPLAY_RESIDENCY_MODE_ALPM(0x1 << REPLAY_RESIDENCY_MODE_SHIFT) -# define REPLAY_RESIDENCY_MODE_IPS 0x10 +# define REPLAY_RESIDENCY_FIELD_MODE_PHY (0x0 << REPLAY_RESIDENCY_MODE_SHIFT) +# define REPLAY_RESIDENCY_FIELD_MODE_ALPM (0x1 << REPLAY_RESIDENCY_MODE_SHIFT) + +#define REPLAY_RESIDENCY_MODE2_MASK(0xF << REPLAY_RESIDENCY_MODE2_SHIFT) +# define REPLAY_RESIDENCY_FIELD_MODE2_IPS (0x1 << REPLAY_RESIDENCY_MODE2_SHIFT) +# define REPLAY_RESIDENCY_FIELD_MODE2_FRAME_CNT(0x2 << REPLAY_RESIDENCY_MODE2_SHIFT) #define REPLAY_RESIDENCY_ENABLE_MASK (0x1 << REPLAY_RESIDENCY_ENABLE_SHIFT) # define REPLAY_RESIDENCY_DISABLE (0x0 << REPLAY_RESIDENCY_ENABLE_SHIFT) # define REPLAY_RESIDENCY_ENABLE (0x1 << REPLAY_RESIDENCY_ENABLE_SHIFT) +#define REPLAY_RESIDENCY_REVISION_MASK (0x3 << REPLAY_RESIDENCY_REVISION_SHIFT) +# define REPLAY_RESIDENCY_REVISION_0 (0x0 << REPLAY_RESIDENCY_REVISION_SHIFT) +# define REPLAY_RESIDENCY_REVISION_1 (0x1 << REPLAY_RESIDENCY_REVISION_SHIFT) + +/** + * Definition of a replay_state. + */ enum replay_state { REPLAY_STATE_0 = 0x0, REPLAY_STATE_1 = 0x10, -- 2.34.1
[PATCH 29/34] drm/amd/display: Add a dc_state NULL check in dc_state_release
From: Allen Pan [How] Check wheather state is NULL before releasing it. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Allen Pan --- drivers/gpu/drm/amd/display/dc/core/dc_state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c index 180ac47868c2..5cc7f8da209c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c @@ -334,7 +334,8 @@ static void dc_state_free(struct kref *kref) void dc_state_release(struct dc_state *state) { - kref_put(>refcount, dc_state_free); + if (state != NULL) + kref_put(>refcount, dc_state_free); } /* * dc_state_add_stream() - Add a new dc_stream_state to a dc_state. -- 2.34.1
[PATCH 28/34] drm/amd/display: Implement wait_for_odm_update_pending_complete
From: Wenjing Liu [WHY] Odm update is doubled buffered. We need to wait for ODM update to be completed before optimizing bandwidth or programming new udpates. [HOW] implement wait_for_odm_update_pending_complete function to wait for: 1. odm configuration update is no longer pending in timing generator. 2. no pending dpg pattern update for each active OPP. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- drivers/gpu/drm/amd/display/dc/core/dc.c | 56 ++- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 1 + .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.c | 14 + .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.h | 2 + .../drm/amd/display/dc/dcn201/dcn201_opp.c| 1 + .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 4 +- drivers/gpu/drm/amd/display/dc/inc/hw/opp.h | 3 + .../amd/display/dc/inc/hw/timing_generator.h | 1 + .../amd/display/dc/optc/dcn10/dcn10_optc.h| 3 +- .../amd/display/dc/optc/dcn32/dcn32_optc.c| 8 +++ .../amd/display/dc/optc/dcn32/dcn32_optc.h| 1 + 11 files changed, 90 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index e87aad983b40..d8967087335e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1335,6 +1335,54 @@ static void disable_vbios_mode_if_required( } } +/** + * wait_for_blank_complete - wait for all active OPPs to finish pending blank + * pattern updates + * + * @dc: [in] dc reference + * @context: [in] hardware context in use + */ +static void wait_for_blank_complete(struct dc *dc, + struct dc_state *context) +{ + struct pipe_ctx *opp_head; + struct dce_hwseq *hws = dc->hwseq; + int i; + + if (!hws->funcs.wait_for_blank_complete) + return; + + for (i = 0; i < MAX_PIPES; i++) { + opp_head = >res_ctx.pipe_ctx[i]; + + if (!resource_is_pipe_type(opp_head, OPP_HEAD) || + dc_state_get_pipe_subvp_type(context, opp_head) == SUBVP_PHANTOM) + continue; + + hws->funcs.wait_for_blank_complete(opp_head->stream_res.opp); + } +} + +static void wait_for_odm_update_pending_complete(struct dc *dc, struct dc_state *context) +{ + struct pipe_ctx *otg_master; + struct timing_generator *tg; + int i; + + for (i = 0; i < MAX_PIPES; i++) { + otg_master = >res_ctx.pipe_ctx[i]; + if (!resource_is_pipe_type(otg_master, OTG_MASTER) || + dc_state_get_pipe_subvp_type(context, otg_master) == SUBVP_PHANTOM) + continue; + tg = otg_master->stream_res.tg; + if (tg->funcs->wait_odm_doublebuffer_pending_clear) + tg->funcs->wait_odm_doublebuffer_pending_clear(tg); + } + + /* ODM update may require to reprogram blank pattern for each OPP */ + wait_for_blank_complete(dc, context); +} + static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context) { int i; @@ -2026,6 +2074,11 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c context->stream_count == 0) { /* Must wait for no flips to be pending before doing optimize bw */ wait_for_no_pipes_pending(dc, context); + /* +* optimized dispclk depends on ODM setup. Need to wait for ODM +* update pending complete before optimizing bandwidth. +*/ + wait_for_odm_update_pending_complete(dc, context); /* pplib is notified if disp_num changed */ dc->hwss.optimize_bandwidth(dc, context); /* Need to do otg sync again as otg could be out of sync due to otg @@ -3591,7 +3644,7 @@ static void commit_planes_for_stream_fast(struct dc *dc, top_pipe_to_program->stream->update_flags.raw = 0; } -static void wait_for_outstanding_hw_updates(struct dc *dc, const struct dc_state *dc_context) +static void wait_for_outstanding_hw_updates(struct dc *dc, struct dc_state *dc_context) { /* * This function calls HWSS to wait for any potentially double buffered @@ -3629,6 +3682,7 @@ static void wait_for_outstanding_hw_updates(struct dc *dc, const struct dc_state } } } + wait_for_odm_update_pending_complete(dc, dc_context); } static void commit_planes_for_stream(struct dc *dc, diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c index 48a40dcc7050..5838a11efd00 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/
[PATCH 27/34] drm/amd/display: Lock all enabled otg pipes even with no planes
From: Wenjing Liu [WHY] On DCN32 we support dynamic ODM even when OTG is blanked. When ODM configuration is dynamically changed and the OTG is on blank pattern, we will need to reprogram OPP's test pattern based on new ODM configuration. Therefore we need to lock the OTG pipe to avoid temporary corruption when we are reprogramming OPP blank patterns. [HOW] Add a new interdependent update lock implementation to lock all enabled OTG pipes even when there is no plane on the OTG for DCN32. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 23 +++ .../amd/display/dc/hwss/dcn32/dcn32_hwseq.h | 2 ++ .../amd/display/dc/hwss/dcn32/dcn32_init.c| 2 +- 3 files changed, 26 insertions(+), 1 deletion(-) 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 b890db0bfc46..c0b526cf1786 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 @@ -1785,3 +1785,26 @@ void dcn32_prepare_bandwidth(struct dc *dc, context->bw_ctx.bw.dcn.clk.p_state_change_support = p_state_change_support; } } + +void dcn32_interdependent_update_lock(struct dc *dc, + struct dc_state *context, bool lock) +{ + unsigned int i; + struct pipe_ctx *pipe; + struct timing_generator *tg; + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = >res_ctx.pipe_ctx[i]; + tg = pipe->stream_res.tg; + + if (!resource_is_pipe_type(pipe, OTG_MASTER) || + !tg->funcs->is_tg_enabled(tg) || + dc_state_get_pipe_subvp_type(context, pipe) == SUBVP_PHANTOM) + continue; + + if (lock) + dc->hwss.pipe_control_lock(dc, pipe, true); + else + dc->hwss.pipe_control_lock(dc, pipe, false); + } +} diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h index 069e20bc87c0..f55c11fc56ec 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.h @@ -129,4 +129,6 @@ bool dcn32_is_pipe_topology_transition_seamless(struct dc *dc, void dcn32_prepare_bandwidth(struct dc *dc, struct dc_state *context); +void dcn32_interdependent_update_lock(struct dc *dc, + struct dc_state *context, bool lock); #endif /* __DC_HWSS_DCN32_H__ */ diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c index 2b073123d3ed..67d661dbd5b7 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_init.c @@ -58,7 +58,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = { .disable_plane = dcn20_disable_plane, .disable_pixel_data = dcn20_disable_pixel_data, .pipe_control_lock = dcn20_pipe_control_lock, - .interdependent_update_lock = dcn10_lock_all_pipes, + .interdependent_update_lock = dcn32_interdependent_update_lock, .cursor_lock = dcn10_cursor_lock, .prepare_bandwidth = dcn32_prepare_bandwidth, .optimize_bandwidth = dcn20_optimize_bandwidth, -- 2.34.1
[PATCH 26/34] drm/amd/display: Implement update_planes_and_stream_v3 sequence
From: Wenjing Liu [WHY & HOW] Update planes and stream version 3 separates FULL and FAST updates to their own sequences. It aims to clean up frequent checks for update type resulting unnecessary branching in logic flow. It also adds a new commit minimal transition sequence, which detects the need for minimal transition based on the actual comparison of current and new states instead of "predicting" it based on per feature software policy, i.e. could_mpcc_tree_change_for_active_pipes. The new commit minimal transition sequence is made universal to any power saving features that would use extra free pipes such as Dynamic ODM/MPC Combine, MPO or SubVp. Therefore there is no longer a need to specially handle compatibility problems with transitions among those features as they are now transparent to the new sequence. Reviewed-by: Wenjing Liu Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- drivers/gpu/drm/amd/display/dc/core/dc.c | 700 +++ 1 file changed, 469 insertions(+), 231 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ed6579633a58..e87aad983b40 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2065,7 +2065,7 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c return result; } -static bool commit_minimal_transition_state_legacy(struct dc *dc, +static bool commit_minimal_transition_state(struct dc *dc, struct dc_state *transition_base_context); /** @@ -2131,7 +2131,7 @@ enum dc_status dc_commit_streams(struct dc *dc, } if (handle_exit_odm2to1) - res = commit_minimal_transition_state_legacy(dc, dc->current_state); + res = commit_minimal_transition_state(dc, dc->current_state); context = dc_state_create_current_copy(dc); if (!context) @@ -3029,6 +3029,63 @@ static void restore_planes_and_stream_state( *stream->out_transfer_func = scratch->out_transfer_func; } +/** + * update_seamless_boot_flags() - Helper function for updating seamless boot flags + * + * @dc: Current DC state + * @context: New DC state to be programmed + * @surface_count: Number of surfaces that have an updated + * @stream: Corresponding stream to be updated in the current flip + * + * Updating seamless boot flags do not need to be part of the commit sequence. This + * helper function will update the seamless boot flags on each flip (if required) + * outside of the HW commit sequence (fast or slow). + * + * Return: void + */ +static void update_seamless_boot_flags(struct dc *dc, + struct dc_state *context, + int surface_count, + struct dc_stream_state *stream) +{ + if (get_seamless_boot_stream_count(context) > 0 && surface_count > 0) { + /* Optimize seamless boot flag keeps clocks and watermarks high until +* first flip. After first flip, optimization is required to lower +* bandwidth. Important to note that it is expected UEFI will +* only light up a single display on POST, therefore we only expect +* one stream with seamless boot flag set. +*/ + if (stream->apply_seamless_boot_optimization) { + stream->apply_seamless_boot_optimization = false; + + if (get_seamless_boot_stream_count(context) == 0) + dc->optimized_required = true; + } + } +} + +/** + * update_planes_and_stream_state() - The function takes planes and stream + * updates as inputs and determines the appropriate update type. If update type + * is FULL, the function allocates a new context, populates and validates it. + * Otherwise, it updates current dc context. The function will return both + * new_context and new_update_type back to the caller. The function also backs + * up both current and new contexts into corresponding dc state scratch memory. + * TODO: The function does too many things, and even conditionally allocates dc + * context memory implicitly. We should consider to break it down. + * + * @dc: Current DC state + * @srf_updates: an array of surface updates + * @surface_count: surface update count + * @stream: Corresponding stream to be updated + * @stream_update: stream update + * @new_update_type: [out] determined update type by the function + * @new_context: [out] new context allocated and validated if update type is + * FULL, reference to current context if update type is less than FULL. + * + * Return: true if a valid update is populated into new_context, false + * otherwise. + */ static bool update_planes_and_stream_state(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream
[PATCH 25/34] drm/amd/display: Set the power_down_on_boot function pointer to null
From: Muhammad Ahmed [WHY] Blackscreen hang @ PC EF25 when trying to wake up from S0i3. DCN gets powered off due to dc_power_down_on_boot() being called after timeout. [HOW] Setting the power_down_on_boot function pointer to null since we don't expect the function to be called for APU. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Nicholas Kazlauskas Acked-by: Alex Hung Signed-off-by: Muhammad Ahmed --- drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c index dce620d359a6..d4e0abbef28e 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_init.c @@ -39,7 +39,7 @@ static const struct hw_sequencer_funcs dcn35_funcs = { .program_gamut_remap = dcn30_program_gamut_remap, .init_hw = dcn35_init_hw, - .power_down_on_boot = dcn35_power_down_on_boot, + .power_down_on_boot = NULL, .apply_ctx_to_hw = dce110_apply_ctx_to_hw, .apply_ctx_for_surface = NULL, .program_front_end_for_ctx = dcn20_program_front_end_for_ctx, -- 2.34.1
[PATCH 24/34] drm/amd/display: Refactor DPP into a component directory
From: Revalla Hari Krishna [WHY & HOW] Move all dpp files to a new dpp directory. Reviewed-by: Martin Leung Acked-by: Alex Hung Signed-off-by: Revalla Hari Krishna --- drivers/gpu/drm/amd/display/Makefile | 1 + drivers/gpu/drm/amd/display/dc/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 4 +- .../amd/display/dc/dcn10/dcn10_cm_common.c| 2 +- drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn201/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/dcn30/Makefile | 2 - .../amd/display/dc/dcn30/dcn30_cm_common.c| 2 +- drivers/gpu/drm/amd/display/dc/dcn32/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn35/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dpp/Makefile | 77 +++ .../amd/display/dc/dpp/dcn10/CMakeLists.txt | 6 ++ .../display/dc/{ => dpp}/dcn10/dcn10_dpp.c| 2 +- .../display/dc/{ => dpp}/dcn10/dcn10_dpp.h| 0 .../display/dc/{ => dpp}/dcn10/dcn10_dpp_cm.c | 4 +- .../dc/{ => dpp}/dcn10/dcn10_dpp_dscl.c | 2 +- .../amd/display/dc/dpp/dcn20/CMakeLists.txt | 5 ++ .../display/dc/{ => dpp}/dcn20/dcn20_dpp.c| 2 +- .../display/dc/{ => dpp}/dcn20/dcn20_dpp.h| 0 .../display/dc/{ => dpp}/dcn20/dcn20_dpp_cm.c | 2 +- .../amd/display/dc/dpp/dcn201/CMakeLists.txt | 4 + .../display/dc/{ => dpp}/dcn201/dcn201_dpp.c | 2 +- .../display/dc/{ => dpp}/dcn201/dcn201_dpp.h | 0 .../amd/display/dc/dpp/dcn30/CMakeLists.txt | 5 ++ .../display/dc/{ => dpp}/dcn30/dcn30_dpp.c| 4 +- .../display/dc/{ => dpp}/dcn30/dcn30_dpp.h| 0 .../display/dc/{ => dpp}/dcn30/dcn30_dpp_cm.c | 4 +- .../amd/display/dc/dpp/dcn32/CMakeLists.txt | 4 + .../display/dc/{ => dpp}/dcn32/dcn32_dpp.c| 2 +- .../display/dc/{ => dpp}/dcn32/dcn32_dpp.h| 0 .../amd/display/dc/dpp/dcn35/CMakeLists.txt | 4 + .../display/dc/{ => dpp}/dcn35/dcn35_dpp.c| 2 +- .../display/dc/{ => dpp}/dcn35/dcn35_dpp.h| 0 33 files changed, 128 insertions(+), 24 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn10/CMakeLists.txt rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn10/dcn10_dpp.c (99%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn10/dcn10_dpp.h (100%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn10/dcn10_dpp_cm.c (99%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn10/dcn10_dpp_dscl.c (99%) create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn20/CMakeLists.txt rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn20/dcn20_dpp.c (99%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn20/dcn20_dpp.h (100%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn20/dcn20_dpp_cm.c (99%) create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn201/CMakeLists.txt rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn201/dcn201_dpp.c (99%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn201/dcn201_dpp.h (100%) create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn30/CMakeLists.txt rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn30/dcn30_dpp.c (99%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn30/dcn30_dpp.h (100%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn30/dcn30_dpp_cm.c (99%) create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn32/CMakeLists.txt rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn32/dcn32_dpp.c (99%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn32/dcn32_dpp.h (100%) create mode 100644 drivers/gpu/drm/amd/display/dc/dpp/dcn35/CMakeLists.txt rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn35/dcn35_dpp.c (98%) rename drivers/gpu/drm/amd/display/dc/{ => dpp}/dcn35/dcn35_dpp.h (100%) diff --git a/drivers/gpu/drm/amd/display/Makefile b/drivers/gpu/drm/amd/display/Makefile index 92a5c5efcf92..9a5bcafbf730 100644 --- a/drivers/gpu/drm/amd/display/Makefile +++ b/drivers/gpu/drm/amd/display/Makefile @@ -33,6 +33,7 @@ subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/hwss subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/resource subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dsc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/optc +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dpp subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/color diff --git a/drivers/gpu/drm/amd/display/dc/Makefile b/drivers/gpu/drm/amd/display/dc/Makefile index 7991ae468f75..4e9fb1742877 100644 --- a/drivers/gpu/drm/amd/display/dc/Makefile +++ b/drivers/gpu/drm/amd/display/dc/Makefile @@ -22,7 +22,7 @@ # # Makefile for Display Core (dc) component. -DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtual dsc resource optc +DC_LIBS = basics bios dml clk_mgr dce gpio hwss irq link virtua
[PATCH 23/34] drm/amd/display: Amend coasting vtotal for replay low hz
From: ChunTao Tso [WHY] The original coasting vtotal is 2 bytes, and it need to be amended to 4 bytes because low hz case. [HOW] Amend coasting vtotal from 2 bytes to 4 bytes. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: ChunTao Tso --- drivers/gpu/drm/amd/display/dc/dc_types.h | 4 ++-- drivers/gpu/drm/amd/display/dc/inc/link.h | 4 ++-- .../display/dc/link/protocols/link_edp_panel_control.c| 4 ++-- .../display/dc/link/protocols/link_edp_panel_control.h| 4 ++-- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 8 drivers/gpu/drm/amd/display/modules/power/power_helpers.c | 2 +- drivers/gpu/drm/amd/display/modules/power/power_helpers.h | 2 +- 7 files changed, 18 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index 9900dda2eef5..be2ac5c442a4 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -1085,9 +1085,9 @@ struct replay_settings { /* SMU optimization is enabled */ bool replay_smu_opt_enable; /* Current Coasting vtotal */ - uint16_t coasting_vtotal; + uint32_t coasting_vtotal; /* Coasting vtotal table */ - uint16_t coasting_vtotal_table[PR_COASTING_TYPE_NUM]; + uint32_t coasting_vtotal_table[PR_COASTING_TYPE_NUM]; /* Maximum link off frame count */ enum replay_link_off_frame_count_level link_off_frame_count_level; /* Replay pseudo vtotal for abm + ips on full screen video which can improve ips residency */ diff --git a/drivers/gpu/drm/amd/display/dc/inc/link.h b/drivers/gpu/drm/amd/display/dc/inc/link.h index 26fe81f213da..bf29fc58ea6a 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/link.h +++ b/drivers/gpu/drm/amd/display/dc/inc/link.h @@ -285,12 +285,12 @@ struct link_service { enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_data); bool (*edp_set_coasting_vtotal)( - struct dc_link *link, uint16_t coasting_vtotal); + struct dc_link *link, uint32_t coasting_vtotal); bool (*edp_replay_residency)(const struct dc_link *link, unsigned int *residency, const bool is_start, const bool is_alpm); bool (*edp_set_replay_power_opt_and_coasting_vtotal)(struct dc_link *link, - const unsigned int *power_opts, uint16_t coasting_vtotal); + const unsigned int *power_opts, uint32_t coasting_vtotal); bool (*edp_wait_for_t12)(struct dc_link *link); bool (*edp_is_ilr_optimization_required)(struct dc_link *link, diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c index acfbbc638cc6..3baa2bdd6dd6 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c @@ -1034,7 +1034,7 @@ bool edp_send_replay_cmd(struct dc_link *link, return true; } -bool edp_set_coasting_vtotal(struct dc_link *link, uint16_t coasting_vtotal) +bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal) { struct dc *dc = link->ctx->dc; struct dmub_replay *replay = dc->res_pool->replay; @@ -1073,7 +1073,7 @@ bool edp_replay_residency(const struct dc_link *link, } bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link, - const unsigned int *power_opts, uint16_t coasting_vtotal) + const unsigned int *power_opts, uint32_t coasting_vtotal) { struct dc *dc = link->ctx->dc; struct dmub_replay *replay = dc->res_pool->replay; diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h index 34e521af7bb4..a158c6234d42 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.h @@ -59,12 +59,12 @@ bool edp_setup_replay(struct dc_link *link, bool edp_send_replay_cmd(struct dc_link *link, enum replay_FW_Message_type msg, union dmub_replay_cmd_set *cmd_data); -bool edp_set_coasting_vtotal(struct dc_link *link, uint16_t coasting_vtotal); +bool edp_set_coasting_vtotal(struct dc_link *link, uint32_t coasting_vtotal); bool edp_replay_residency(const struct dc_link *link, unsigned int *residency, const bool is_start, const bool is_alpm); bool edp_get_replay_state(const struct dc_link *link, uint64_t *state); bool edp_set_replay_power_opt_and_coasting_vtotal(struct dc_link *link, - const
[PATCH 22/34] drm/amd/display: Add left edge pixel for YCbCr422/420 + ODM pipe split
From: George Shen [WHY] Currently 3-tap chroma subsampling is used for YCbCr422/420. When ODM pipesplit is used, pixels on the left edge of ODM slices need one extra pixel from the right edge of the previous slice to calculate the correct chroma value. Without this change, the chroma value is slightly different than expected. This is usually imperceptible visually, but it impacts test pattern CRCs for compliance test automation. [HOW] Update logic to use the register for adding extra left edge pixel for YCbCr422/420 ODM cases. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: George Shen --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++ .../gpu/drm/amd/display/dc/core/dc_resource.c | 37 +++ .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 10 + .../gpu/drm/amd/display/dc/inc/core_types.h | 2 + drivers/gpu/drm/amd/display/dc/inc/resource.h | 4 ++ 5 files changed, 57 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index acd8f1257ade..ed6579633a58 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3147,6 +3147,10 @@ static bool update_planes_and_stream_state(struct dc *dc, if (otg_master && otg_master->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) resource_build_test_pattern_params(>res_ctx, otg_master); + + if (otg_master && (otg_master->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422 || + otg_master->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)) + resource_build_subsampling_params(>res_ctx, otg_master); } } 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 1b7765bc5e5e..96ea283bd169 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -822,6 +822,16 @@ static struct rect calculate_odm_slice_in_timing_active(struct pipe_ctx *pipe_ct stream->timing.v_border_bottom + stream->timing.v_border_top; + /* Recout for ODM slices after the first slice need one extra left edge pixel +* for 3-tap chroma subsampling. +*/ + if (odm_slice_idx > 0 && + (pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422 || + pipe_ctx->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)) { + odm_rec.x -= 1; + odm_rec.width += 1; + } + return odm_rec; } @@ -1438,6 +1448,7 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx, enum controller_dp_test_pattern controller_test_pattern; enum controller_dp_color_space controller_color_space; enum dc_color_depth color_depth = otg_master->stream->timing.display_color_depth; + enum dc_pixel_encoding pixel_encoding = otg_master->stream->timing.pixel_encoding; int h_active = otg_master->stream->timing.h_addressable + otg_master->stream->timing.h_border_left + otg_master->stream->timing.h_border_right; @@ -1469,10 +1480,36 @@ void resource_build_test_pattern_params(struct resource_context *res_ctx, else params->width = last_odm_slice_width; + /* Extra left edge pixel is required for 3-tap chroma subsampling. */ + if (i != 0 && (pixel_encoding == PIXEL_ENCODING_YCBCR422 || + pixel_encoding == PIXEL_ENCODING_YCBCR420)) { + params->offset -= 1; + params->width += 1; + } + offset += odm_slice_width; } } +void resource_build_subsampling_params(struct resource_context *res_ctx, + struct pipe_ctx *otg_master) +{ + struct pipe_ctx *opp_heads[MAX_PIPES]; + int odm_cnt = 1; + int i; + + odm_cnt = resource_get_opp_heads_for_otg_master(otg_master, res_ctx, opp_heads); + + /* For ODM slices after the first slice, extra left edge pixel is required +* for 3-tap chroma subsampling. +*/ + if (otg_master->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422 || + otg_master->stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) { + for (i = 0; i < odm_cnt; i++) + opp_heads[i]->stream_res.left_edge_extra_pixel = (i == 0) ? false : true; + } +} + bool resource_build_scaling_params(struct pipe_ctx *pipe_ct
[PATCH 21/34] drm/amd/display: Add debug counters to IPS exit prints
From: Nicholas Kazlauskas [WHY] To have a log of the entry/exit counters in case the system hangs to measure stability. [HOW] Read them from firmware state and pass them to the prints. Reviewed-by: Duncan Ma Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 18 +++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 938e8cb2fec1..765a459d54eb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -1279,6 +1279,7 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) static void dc_dmub_srv_exit_low_power_state(const struct dc *dc) { struct dc_dmub_srv *dc_dmub_srv; + uint32_t rcg_exit_count, ips1_exit_count, ips2_exit_count; if (dc->debug.dmcub_emulation) return; @@ -1295,15 +1296,22 @@ static void dc_dmub_srv_exit_low_power_state(const struct dc *dc) _dmub_srv->dmub->shared_state[DMUB_SHARED_SHARE_FEATURE__IPS_DRIVER].data.ips_driver; union dmub_shared_state_ips_driver_signals prev_driver_signals = ips_driver->signals; + rcg_exit_count = ips_fw->rcg_exit_count; + ips1_exit_count = ips_fw->ips1_exit_count; + ips2_exit_count = ips_fw->ips2_exit_count; + ips_driver->signals.all = 0; DC_LOG_IPS( - "%s check (allow_ips1=%d allow_ips2=%d) (ips1_commit=%d ips2_commit=%d)", + "%s (allow ips1=%d ips2=%d) (commit ips1=%d ips2=%d) (count rcg=%d ips1=%d ips2=%d)", __func__, ips_driver->signals.bits.allow_ips1, ips_driver->signals.bits.allow_ips2, ips_fw->signals.bits.ips1_commit, - ips_fw->signals.bits.ips2_commit); + ips_fw->signals.bits.ips2_commit, + ips_fw->rcg_entry_count, + ips_fw->ips1_entry_count, + ips_fw->ips2_entry_count); /* Note: register access has technically not resumed for DCN here, but we * need to be message PMFW through our standard register interface. @@ -1387,7 +1395,11 @@ static void dc_dmub_srv_exit_low_power_state(const struct dc *dc) if (!dc_dmub_srv_is_hw_pwr_up(dc->ctx->dmub_srv, true)) ASSERT(0); - DC_LOG_IPS("%s exited", __func__); + DC_LOG_IPS("%s exit (count rcg=%d ips1=%d ips2=%d)", + __func__, + rcg_exit_count, + ips1_exit_count, + ips2_exit_count); } void dc_dmub_srv_set_power_state(struct dc_dmub_srv *dc_dmub_srv, enum dc_acpi_cm_power_state powerState) -- 2.34.1
[PATCH 20/34] drm/amd/display: Guard cursor idle reallow by DC debug option
From: Nicholas Kazlauskas [WHY] To control whether idle optimizations reallowed after the first cursor update. [HOW] Add checks to the conditions. Reviewed-by: Duncan Ma Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 51a970fcb5d0..212e057ed9b0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -319,7 +319,7 @@ bool dc_stream_set_cursor_attributes( program_cursor_attributes(dc, stream, attributes); /* re-enable idle optimizations if necessary */ - if (reset_idle_optimizations) + if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle) dc_allow_idle_optimizations(dc, true); return true; @@ -394,7 +394,7 @@ bool dc_stream_set_cursor_position( program_cursor_position(dc, stream, position); /* re-enable idle optimizations if necessary */ - if (reset_idle_optimizations) + if (reset_idle_optimizations && !dc->debug.disable_dmub_reallow_idle) dc_allow_idle_optimizations(dc, true); return true; -- 2.34.1
[PATCH 19/34] drm/amd/display: Add guards for idle on reg read/write
From: Nicholas Kazlauskas [WHY] If DCN is in idle then we should not be accessing DCN registers or it can lead to hangs. [HOW] Log the error and return 0 or drop the write if it's in idle. This is skipped in the exit sequence itself since the boolean flips before it starts. It also does not cover accesses from external clients outside of DM/DC like firmware or the kernel mode driver. Reviewed-by: Duncan Ma Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 9 + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index b168dfc79381..938e8cb2fec1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -1270,6 +1270,10 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) /* NOTE: This does not use the "wake" interface since this is part of the wake path. */ /* We also do not perform a wait since DMCUB could enter idle after the notification. */ dm_execute_dmub_cmd(dc->ctx, , allow_idle ? DM_DMUB_WAIT_TYPE_NO_WAIT : DM_DMUB_WAIT_TYPE_WAIT); + + /* Register access should stop at this point. */ + if (allow_idle) + dc_dmub_srv->needs_idle_wake = true; } static void dc_dmub_srv_exit_low_power_state(const struct dc *dc) @@ -1301,6 +1305,11 @@ static void dc_dmub_srv_exit_low_power_state(const struct dc *dc) ips_fw->signals.bits.ips1_commit, ips_fw->signals.bits.ips2_commit); + /* Note: register access has technically not resumed for DCN here, but we +* need to be message PMFW through our standard register interface. +*/ + dc_dmub_srv->needs_idle_wake = false; + if (prev_driver_signals.bits.allow_ips2) { DC_LOG_IPS( "wait IPS2 eval (ips1_commit=%d ips2_commit=%d)", diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h index 952bfb368886..60c93e9e3533 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h @@ -52,6 +52,7 @@ struct dc_dmub_srv { void *dm; bool idle_allowed; + bool needs_idle_wake; }; void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv); -- 2.34.1
[PATCH 18/34] drm/amd/display: Fix idle check for shared firmware state
From: Nicholas Kazlauskas [WHY] We still had an instance of get_idle_state checking the PMFW scratch register instead of the actual idle allow signal. [HOW] Replace it with the SW state check for whether we had allowed idle through notify_idle. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Duncan Ma Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/dc/core/dc.c | 12 +++- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index daf6c7fe0906..acd8f1257ade 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -4884,22 +4884,16 @@ void dc_exit_ips_for_hw_access_internal(struct dc *dc, const char *caller_name) bool dc_dmub_is_ips_idle_state(struct dc *dc) { - uint32_t idle_state = 0; - if (dc->debug.disable_idle_power_optimizations) return false; if (!dc->caps.ips_support || (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL)) return false; - if (dc->hwss.get_idle_state) - idle_state = dc->hwss.get_idle_state(dc); - - if (!(idle_state & DMUB_IPS1_ALLOW_MASK) || - !(idle_state & DMUB_IPS2_ALLOW_MASK)) - return true; + if (!dc->ctx->dmub_srv) + return false; - return false; + return dc->ctx->dmub_srv->idle_allowed; } /* set min and max memory clock to lowest and highest DPM level, respectively */ -- 2.34.1
[PATCH 17/34] drm/amd/display: Update odm when ODM combine is changed on an otg master pipe with no plane
From: Wenjing Liu [WHY] When committing an update with ODM combine change when the plane is removing or already removed, we fail to detect odm change in pipe update flags. This has caused mismatch between new dc state and the actual hardware state, because we missed odm programming. [HOW] - Detect odm change even for otg master pipe without a plane. - Update odm config before calling program pipes for pipe with planes. The commit also updates blank pattern programming when odm is changed without plane. This is because number of OPP is changed when ODM combine is changed. Blank pattern is per OPP so we will need to reprogram OPP based on the new pipe topology. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Dillon Varone Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- .../amd/display/dc/hwss/dcn20/dcn20_hwseq.c | 41 ++- .../amd/display/dc/hwss/dcn32/dcn32_hwseq.c | 7 2 files changed, 28 insertions(+), 20 deletions(-) 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 c55d5155ecb9..40098d9f70cb 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 @@ -1498,6 +1498,11 @@ static void dcn20_detect_pipe_changes(struct dc_state *old_state, return; } + if (resource_is_pipe_type(new_pipe, OTG_MASTER) && + resource_is_odm_topology_changed(new_pipe, old_pipe)) + /* Detect odm changes */ + new_pipe->update_flags.bits.odm = 1; + /* Exit on unchanged, unused pipe */ if (!old_pipe->plane_state && !new_pipe->plane_state) return; @@ -1551,10 +1556,6 @@ static void dcn20_detect_pipe_changes(struct dc_state *old_state, /* Detect top pipe only changes */ if (resource_is_pipe_type(new_pipe, OTG_MASTER)) { - /* Detect odm changes */ - if (resource_is_odm_topology_changed(new_pipe, old_pipe)) - new_pipe->update_flags.bits.odm = 1; - /* Detect global sync changes */ if (old_pipe->pipe_dlg_param.vready_offset != new_pipe->pipe_dlg_param.vready_offset || old_pipe->pipe_dlg_param.vstartup_start != new_pipe->pipe_dlg_param.vstartup_start @@ -1999,19 +2000,20 @@ void dcn20_program_front_end_for_ctx( DC_LOGGER_INIT(dc->ctx->logger); unsigned int prev_hubp_count = 0; unsigned int hubp_count = 0; + struct pipe_ctx *pipe; if (resource_is_pipe_topology_changed(dc->current_state, context)) resource_log_pipe_topology_update(dc, context); if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) { for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe_ctx = >res_ctx.pipe_ctx[i]; + pipe = >res_ctx.pipe_ctx[i]; - if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->plane_state) { - ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); + if (!pipe->top_pipe && !pipe->prev_odm_pipe && pipe->plane_state) { + ASSERT(!pipe->plane_state->triplebuffer_flips); /*turn off triple buffer for full update*/ dc->hwss.program_triplebuffer( - dc, pipe_ctx, pipe_ctx->plane_state->triplebuffer_flips); + dc, pipe, pipe->plane_state->triplebuffer_flips); } } } @@ -2085,12 +2087,22 @@ void dcn20_program_front_end_for_ctx( DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx); } + /* update ODM for blanked OTG master pipes */ + for (i = 0; i < dc->res_pool->pipe_count; i++) { + pipe = >res_ctx.pipe_ctx[i]; + if (resource_is_pipe_type(pipe, OTG_MASTER) && + !resource_is_pipe_type(pipe, DPP_PIPE) && + pipe->update_flags.bits.odm && + hws->funcs.update_odm) + hws->funcs.update_odm(dc, context, pipe); + } + /* * Program all updated pipes, order matters for mpcc setup. Start with * top pipe and program all pipes that follow in order */ for (i = 0; i < dc->res_pool->pipe_count; i++) { - struct pipe_ctx *pipe = &g
[PATCH 16/34] drm/amd/display: Init DPPCLK from SMU on dcn32
From: Dillon Varone [WHY & HOW] DPPCLK ranges should be obtained from the SMU when available. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Chaitanya Dhere Acked-by: Alex Hung Signed-off-by: Dillon Varone --- .../display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 14 ++ .../drm/amd/display/dc/dml2/dml2_wrapper.c| 28 +-- .../drm/amd/display/dc/dml2/dml2_wrapper.h| 3 ++ .../dc/resource/dcn32/dcn32_resource.c| 2 ++ .../dc/resource/dcn321/dcn321_resource.c | 2 ++ 5 files changed, 41 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index 668f05c8654e..bec252e1dd27 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -216,6 +216,16 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) if (clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz > 1950) clk_mgr_base->bw_params->dc_mode_limit.dispclk_mhz = 1950; + /* DPPCLK */ + dcn32_init_single_clock(clk_mgr, PPCLK_DPPCLK, + _mgr_base->bw_params->clk_table.entries[0].dppclk_mhz, + _entries_per_clk->num_dppclk_levels); + num_levels = num_entries_per_clk->num_dppclk_levels; + clk_mgr_base->bw_params->dc_mode_limit.dppclk_mhz = dcn30_smu_get_dc_mode_max_dpm_freq(clk_mgr, PPCLK_DPPCLK); + //HW recommends limit of 1950 MHz in display clock for all DCN3.2.x + if (clk_mgr_base->bw_params->dc_mode_limit.dppclk_mhz > 1950) + clk_mgr_base->bw_params->dc_mode_limit.dppclk_mhz = 1950; + if (num_entries_per_clk->num_dcfclk_levels && num_entries_per_clk->num_dtbclk_levels && num_entries_per_clk->num_dispclk_levels) @@ -240,6 +250,10 @@ void dcn32_init_clocks(struct clk_mgr *clk_mgr_base) = khz_to_mhz_ceil(clk_mgr_base->ctx->dc->debug.min_dpp_clk_khz); } + for (i = 0; i < num_levels; i++) + if (clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz > 1950) + clk_mgr_base->bw_params->clk_table.entries[i].dppclk_mhz = 1950; + /* Get UCLK, update bounding box */ clk_mgr_base->funcs->get_memclk_states_from_smu(clk_mgr_base); diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c index 2a58a7687bdb..72cca367062e 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.c @@ -703,13 +703,8 @@ static inline struct dml2_context *dml2_allocate_memory(void) return (struct dml2_context *) kzalloc(sizeof(struct dml2_context), GFP_KERNEL); } -bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2) +static void dml2_init(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2) { - // Allocate Mode Lib Ctx - *dml2 = dml2_allocate_memory(); - - if (!(*dml2)) - return false; // Store config options (*dml2)->config = *config; @@ -737,9 +732,18 @@ bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options initialize_dml2_soc_bbox(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc); initialize_dml2_soc_states(*dml2, in_dc, &(*dml2)->v20.dml_core_ctx.soc, &(*dml2)->v20.dml_core_ctx.states); +} + +bool dml2_create(const struct dc *in_dc, const struct dml2_configuration_options *config, struct dml2_context **dml2) +{ + // Allocate Mode Lib Ctx + *dml2 = dml2_allocate_memory(); + + if (!(*dml2)) + return false; + + dml2_init(in_dc, config, dml2); - /*Initialize DML20 instance which calls dml2_core_create, and core_dcn3_populate_informative*/ - //dml2_initialize_instance(&(*dml_ctx)->v20.dml_init); return true; } @@ -779,3 +783,11 @@ bool dml2_create_copy(struct dml2_context **dst_dml2, return true; } + +void dml2_reinit(const struct dc *in_dc, +const struct dml2_configuration_options *config, +struct dml2_context **dml2) +{ + + dml2_init(in_dc, config, dml2); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h index ee0eb184eb6d..cc662d682fd4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_wrapper.h @@ -214,6 +214,9 @@ void dml2_copy(struct dml2_context *dst_dml2, struct dm
[PATCH 15/34] drm/amd/display: Add monitor patch for specific eDP
From: Ryan Lin [WHY] Some eDP panels' ext caps don't write initial values. The value of dpcd_addr (0x317) can be random and the backlight control interface will be incorrect. [HOW] Add new panel patches to remove sink ext caps. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org # 6.5.x Cc: Tsung-hua Lin Cc: Chris Chi Reviewed-by: Wayne Lin Acked-by: Alex Hung Signed-off-by: Ryan Lin --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 85b7f58a7f35..c27063305a13 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -67,6 +67,8 @@ static void apply_edid_quirks(struct edid *edid, struct dc_edid_caps *edid_caps) /* Workaround for some monitors that do not clear DPCD 0x317 if FreeSync is unsupported */ case drm_edid_encode_panel_id('A', 'U', 'O', 0xA7AB): case drm_edid_encode_panel_id('A', 'U', 'O', 0xE69B): + case drm_edid_encode_panel_id('B', 'O', 'E', 0x092A): + case drm_edid_encode_panel_id('L', 'G', 'D', 0x06D1): DRM_DEBUG_DRIVER("Clearing DPCD 0x317 on monitor with panel id %X\n", panel_id); edid_caps->panel_patch.remove_sink_ext_caps = true; break; @@ -120,6 +122,8 @@ enum dc_edid_status dm_helpers_parse_edid_caps( edid_caps->edid_hdmi = connector->display_info.is_hdmi; + apply_edid_quirks(edid_buf, edid_caps); + sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, ); if (sad_count <= 0) return result; @@ -146,8 +150,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps( else edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION; - apply_edid_quirks(edid_buf, edid_caps); - kfree(sads); kfree(sadb); -- 2.34.1
[PATCH 14/34] drm/amd/display: Support long vblank feature
From: Robin Chen [WHY] We want to support low hz case, but the original vtotal/vtotal_min/vtotal_max can't support more than 0x7FFF. [HOW] We use the 2 HW reg to contorl long vblank case. 1. OTG_V_COUNT_STOP_CONTROL -> vcount_stop 2. OTG_V_COUNT_STOP_CONTROL2 -> vcount_stop_timer vcount_stop define from which line we stop using vcount and start using vcount2. vcount_stop_timer define how long we use vcount2. Ex: Vtotal = 7 OTG_V_COUNT_STOP_CONTROL = 4 OTG_V_COUNT_STOP_CONTROL2 = 5 time: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 vcount : 0, 1, 2, 3, - - - - - 4, 5, 6 vcount2 : 0, 1, 2, 3, 4, Reviewed-by: Jun Lei Acked-by: Alex Hung Signed-off-by: ChunTao Tso Signed-off-by: Robin Chen --- drivers/gpu/drm/amd/display/dc/core/dc.c | 33 drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 + .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 28 +++ .../amd/display/dc/hwss/dcn35/dcn35_hwseq.h | 3 + .../amd/display/dc/hwss/dcn35/dcn35_init.c| 3 +- .../drm/amd/display/dc/hwss/hw_sequencer.h| 1 + .../amd/display/dc/inc/hw/timing_generator.h | 7 + .../amd/display/dc/optc/dcn10/dcn10_optc.h| 6 +- .../amd/display/dc/optc/dcn35/dcn35_optc.c| 165 +- .../amd/display/dc/optc/dcn35/dcn35_optc.h| 6 +- .../dc/resource/dcn35/dcn35_resource.h| 2 + .../amd/display/modules/freesync/freesync.c | 2 + 12 files changed, 253 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 501e0298623a..daf6c7fe0906 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -386,6 +386,30 @@ static void dc_perf_trace_destroy(struct dc_perf_trace **perf_trace) *perf_trace = NULL; } +static bool set_long_vtotal(struct dc *dc, struct dc_stream_state *stream, struct dc_crtc_timing_adjust *adjust) +{ + if (!dc || !stream || !adjust) + return false; + + if (!dc->current_state) + return false; + + int i; + + for (i = 0; i < MAX_PIPES; i++) { + struct pipe_ctx *pipe = >current_state->res_ctx.pipe_ctx[i]; + + if (pipe->stream == stream && pipe->stream_res.tg) { + if (dc->hwss.set_long_vtotal) + dc->hwss.set_long_vtotal(, 1, adjust->v_total_min, adjust->v_total_max); + + return true; + } + } + + return false; +} + /** * dc_stream_adjust_vmin_vmax - look up pipe context & update parts of DRR * @dc: dc reference @@ -420,6 +444,15 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, stream->adjust.v_total_mid = adjust->v_total_mid; stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; stream->adjust.v_total_min = adjust->v_total_min; + stream->adjust.allow_otg_v_count_halt = adjust->allow_otg_v_count_halt; + + if (dc->caps.max_v_total != 0 && + (adjust->v_total_max > dc->caps.max_v_total || adjust->v_total_min > dc->caps.max_v_total)) { + if (adjust->allow_otg_v_count_halt) + return set_long_vtotal(dc, stream, adjust); + else + return false; + } for (i = 0; i < MAX_PIPES; i++) { struct pipe_ctx *pipe = >current_state->res_ctx.pipe_ctx[i]; diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h index aae2f3a2660d..465e15f57f93 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h @@ -974,6 +974,7 @@ struct dc_crtc_timing_adjust { uint32_t v_total_max; uint32_t v_total_mid; uint32_t v_total_mid_frame_num; + uint32_t allow_otg_v_count_halt; }; diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 4b92df23ff0d..2e8ec58a16eb 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -1394,3 +1394,31 @@ void dcn35_set_static_screen_control(struct pipe_ctx **pipe_ctx, set_static_screen_control(pipe_ctx[i]->stream_res.tg, triggers, params->num_frames); } + +void dcn35_set_long_vblank(struct pipe_ctx **pipe_ctx, + int num_pipes, uint32_t v_total_min, uint32_t v_total_max) +{ + int i = 0; + struct long_vtotal_params params = {0}; + + params.vertical_total_max = v_total_max; + params.vertical_total_min = v_total_min; + + for (i = 0; i < num_pipes; i++) { + if (!pipe_ctx[i]) + continue; + +
[PATCH 13/34] drm/amd/display: 3.2.274
From: Aric Cyr - Change default size for dummy plane in DML2 - Enable DML2 debug flags - Add some forward declarations - Add DML2 folder to include path - Set DCN351 BB and IP the same as DCN35 - Override min required DCFCLK in dml1_validate - Fix function banner for amdgpu_dm_psr_disable_all() - Allow dirty rects to be sent to dmub when abm is active - Add debug key to allow disabling dtbclk - Add debug prints for IPS testing - Exit idle optimizations before HDCP execution - Add entry and exit counters Acked-by: Alex Hung Signed-off-by: Aric Cyr --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c9485a7744d7..09c6a393642a 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -51,7 +51,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.273" +#define DC_VER "3.2.274" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- 2.34.1
[PATCH 12/34] drm/amd/display: Add entry and exit counters
From: Anthony Koo [WHY & HOW] Add new counters in the shared IPS firmware state. Acked-by: Alex Hung Signed-off-by: Anthony Koo --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index a529e369b2ac..02ad641bd8df 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -724,7 +724,13 @@ union dmub_shared_state_ips_driver_signals { */ struct dmub_shared_state_ips_fw { union dmub_shared_state_ips_fw_signals signals; /**< 4 bytes, IPS signal bits */ - uint32_t reserved[61]; /**< Reversed, to be updated when adding new fields. */ + uint32_t rcg_entry_count; /**< Entry counter for RCG */ + uint32_t rcg_exit_count; /**< Exit counter for RCG */ + uint32_t ips1_entry_count; /**< Entry counter for IPS1 */ + uint32_t ips1_exit_count; /**< Exit counter for IPS1 */ + uint32_t ips2_entry_count; /**< Entry counter for IPS2 */ + uint32_t ips2_exit_count; /**< Exit counter for IPS2 */ + uint32_t reserved[55]; /**< Reversed, to be updated when adding new fields. */ }; /* 248-bytes, fixed */ /** -- 2.34.1
[PATCH 11/34] drm/amd/display: Exit idle optimizations before HDCP execution
From: Nicholas Kazlauskas [WHY] PSP can access DCN registers during command submission and we need to ensure that DCN is not in PG before doing so. [HOW] Add a callback to DM to lock and notify DC for idle optimization exit. It can't be DC directly because of a potential race condition with the link protection thread and the rest of DM operation. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c| 10 ++ drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h | 8 2 files changed, 18 insertions(+) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index 5e01c6e24cbc..9a5a1726acaf 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -88,6 +88,14 @@ static uint8_t is_cp_desired_hdcp2(struct mod_hdcp *hdcp) !hdcp->connection.is_hdcp2_revoked; } +static void exit_idle_optimizations(struct mod_hdcp *hdcp) +{ + struct mod_hdcp_dm *dm = >config.dm; + + if (dm->funcs.exit_idle_optimizations) + dm->funcs.exit_idle_optimizations(dm->handle); +} + static enum mod_hdcp_status execution(struct mod_hdcp *hdcp, struct mod_hdcp_event_context *event_ctx, union mod_hdcp_transition_input *input) @@ -543,6 +551,8 @@ enum mod_hdcp_status mod_hdcp_process_event(struct mod_hdcp *hdcp, memset(_ctx, 0, sizeof(struct mod_hdcp_event_context)); event_ctx.event = event; + exit_idle_optimizations(hdcp); + /* execute and transition */ exec_status = execution(hdcp, _ctx, >auth.trans_input); trans_status = transition( diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h index a4d344a4db9e..cdb17b093f2b 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h @@ -156,6 +156,13 @@ struct mod_hdcp_ddc { } funcs; }; +struct mod_hdcp_dm { + void *handle; + struct { + void (*exit_idle_optimizations)(void *handle); + } funcs; +}; + struct mod_hdcp_psp { void *handle; void *funcs; @@ -272,6 +279,7 @@ struct mod_hdcp_display_query { struct mod_hdcp_config { struct mod_hdcp_psp psp; struct mod_hdcp_ddc ddc; + struct mod_hdcp_dm dm; uint8_t index; }; -- 2.34.1
[PATCH 10/34] drm/amd/display: Add debug prints for IPS testing
From: Nicholas Kazlauskas [WHY] To log commit states and when we transition in/out of allow and idle states and the caller. [HOW] Add a new logging helper and wrap idle optimization calls to receive the caller. Reviewed-by: Duncan Ma Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/dc/core/dc.c | 10 ++- drivers/gpu/drm/amd/display/dc/dc.h | 7 +- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 73 +++ .../drm/amd/display/include/logger_types.h| 1 + 4 files changed, 86 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 613d09c42f3b..501e0298623a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -4820,11 +4820,15 @@ bool dc_set_replay_allow_active(struct dc *dc, bool active) return true; } -void dc_allow_idle_optimizations(struct dc *dc, bool allow) +void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, char const *caller_name) { if (dc->debug.disable_idle_power_optimizations) return; + if (allow != dc->idle_optimizations_allowed) + DC_LOG_IPS("%s: allow_idle old=%d new=%d (caller=%s)\n", __func__, + dc->idle_optimizations_allowed, allow, caller_name); + if (dc->caps.ips_support && (dc->config.disable_ips == DMUB_IPS_DISABLE_ALL)) return; @@ -4839,10 +4843,10 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow) dc->idle_optimizations_allowed = allow; } -void dc_exit_ips_for_hw_access(struct dc *dc) +void dc_exit_ips_for_hw_access_internal(struct dc *dc, const char *caller_name) { if (dc->caps.ips_support) - dc_allow_idle_optimizations(dc, false); + dc_allow_idle_optimizations_internal(dc, false, caller_name); } bool dc_dmub_is_ips_idle_state(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c1d8288a08b3..c9485a7744d7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -2339,8 +2339,11 @@ void dc_get_clock(struct dc *dc, enum dc_clock_type clock_type, struct dc_clock_ bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_state *plane, struct dc_cursor_attributes *cursor_attr); -void dc_allow_idle_optimizations(struct dc *dc, bool allow); -void dc_exit_ips_for_hw_access(struct dc *dc); +#define dc_allow_idle_optimizations(dc, allow) dc_allow_idle_optimizations_internal(dc, allow, __func__) +#define dc_exit_ips_for_hw_access(dc) dc_exit_ips_for_hw_access_internal(dc, __func__) + +void dc_allow_idle_optimizations_internal(struct dc *dc, bool allow, const char *caller_name); +void dc_exit_ips_for_hw_access_internal(struct dc *dc, const char *caller_name); bool dc_dmub_is_ips_idle_state(struct dc *dc); /* set min and max memory clock to lowest and highest DPM level, respectively */ diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 6083b1dcf050..b168dfc79381 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -910,6 +910,8 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv) return; } + DC_LOG_ERROR("%s: DMCUB error - collecting diagnostic data\n", __func__); + if (!dc_dmub_srv_get_diagnostic_data(dc_dmub_srv, _data)) { DC_LOG_ERROR("%s: dc_dmub_srv_get_diagnostic_data failed.", __func__); return; @@ -1201,6 +1203,7 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait) static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) { + volatile const struct dmub_shared_state_ips_fw *ips_fw; struct dc_dmub_srv *dc_dmub_srv; union dmub_rb_cmd cmd = {0}; @@ -1211,6 +1214,7 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) return; dc_dmub_srv = dc->ctx->dmub_srv; + ips_fw = _dmub_srv->dmub->shared_state[DMUB_SHARED_SHARE_FEATURE__IPS_FW].data.ips_fw; memset(, 0, sizeof(cmd)); cmd.idle_opt_notify_idle.header.type = DMUB_CMD__IDLE_OPT; @@ -1226,6 +1230,12 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle) _dmub_srv->dmub->shared_state[DMUB_SHARED_SHARE_FEATURE__IPS_DRIVER].data.ips_driver; union dmub_shared_state_ips_driver_signals new_signals; + DC_LOG_IPS( + "%s wait idle (ips1_commit=%d ips2_commit=%d)", + __func__, + ips
[PATCH 09/34] drm/amd/display: Add debug key to allow disabling dtbclk
From: Muhammad Ahmed [HOW] Add debug key to allow disabling dtbclk Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Muhammad Ahmed --- drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 3 ++- drivers/gpu/drm/amd/display/dc/dc.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index c378b879c76d..c6030bed95a0 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -244,7 +244,8 @@ void dcn35_update_clocks(struct clk_mgr *clk_mgr_base, } if (clk_mgr_base->clks.dtbclk_en && !new_clocks->dtbclk_en) { - dcn35_smu_set_dtbclk(clk_mgr, false); + if (clk_mgr->base.ctx->dc->config.allow_0_dtb_clk) + dcn35_smu_set_dtbclk(clk_mgr, false); clk_mgr_base->clks.dtbclk_en = new_clocks->dtbclk_en; } /* check that we're not already in lower */ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index ee8453bf958f..c1d8288a08b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -435,6 +435,7 @@ struct dc_config { unsigned int disable_ips; unsigned int disable_ips_in_vpb; bool usb4_bw_alloc_support; + bool allow_0_dtb_clk; }; enum visual_confirm { -- 2.34.1
[PATCH 08/34] drm/amd/display: Allow dirty rects to be sent to dmub when abm is active
From: Josip Pavic [WHY] It's beneficial for ABM to know when new frame data are available. [HOW] Add new condition to allow dirty rects to be sent to DMUB when ABM is active. ABM will use this as a signal that a new frame has arrived. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Anthony Koo Acked-by: Alex Hung Signed-off-by: Josip Pavic --- drivers/gpu/drm/amd/display/dc/core/dc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 5211c1c0f3c0..613d09c42f3b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3270,6 +3270,9 @@ static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_s if (stream->link->replay_settings.config.replay_supported) return true; + if (stream->ctx->dce_version >= DCN_VERSION_3_5 && stream->abm_level) + return true; + return false; } -- 2.34.1
[PATCH 07/34] drm/amd/display: Fix function banner for amdgpu_dm_psr_disable_all()
From: Roman Li [WHY] Incorrect function name in function banner. [HOW] Correct name and brief description. Reviewed-by: Hersen Wu Reviewed-by: Aurabindo Pillai Acked-by: Alex Hung Signed-off-by: Roman Li --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c index 1f08c6564c3b..a48a79e84e82 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c @@ -210,7 +210,7 @@ bool amdgpu_dm_psr_disable(struct dc_stream_state *stream) } /* - * amdgpu_dm_psr_disable() - disable psr f/w + * amdgpu_dm_psr_disable_all() - disable psr f/w for all streams * if psr is enabled on any stream * * Return: true if success -- 2.34.1
[PATCH 06/34] drm/amd/display: Override min required DCFCLK in dml1_validate
From: Sohaib Nadeem [WHY]: Increasing min DCFCLK addresses underflow issues that occur when phantom pipe is turned on for some Sub-Viewport configs [HOW]: dcn32_override_min_req_dcfclk is added to override DCFCLK value in dml1_validate when subviewport is being used. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Sohaib Nadeem --- .../gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c | 6 ++ .../gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c | 1 + .../gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h | 3 +++ 3 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c index 87760600e154..f98def6c8c2d 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c @@ -782,3 +782,9 @@ void dcn32_update_dml_pipes_odm_policy_based_on_context(struct dc *dc, struct dc pipe_cnt++; } } + +void dcn32_override_min_req_dcfclk(struct dc *dc, struct dc_state *context) +{ + if (dcn32_subvp_in_use(dc, context) && context->bw_ctx.bw.dcn.clk.dcfclk_khz <= MIN_SUBVP_DCFCLK_KHZ) + context->bw_ctx.bw.dcn.clk.dcfclk_khz = MIN_SUBVP_DCFCLK_KHZ; +} diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c index 3f3951f3ba98..f844f57ecc49 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -1771,6 +1771,7 @@ static bool dml1_validate(struct dc *dc, struct dc_state *context, bool fast_val dc->res_pool->funcs->calculate_wm_and_dlg(dc, context, pipes, pipe_cnt, vlevel); dcn32_override_min_req_memclk(dc, context); + dcn32_override_min_req_dcfclk(dc, context); BW_VAL_TRACE_END_WATERMARKS(); diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h index 0c87b0fabba7..2258c5c7212d 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.h @@ -42,6 +42,7 @@ #define SUBVP_ACTIVE_MARGIN_LIST_LEN 2 #define DCN3_2_MAX_SUBVP_PIXEL_RATE_MHZ 1800 #define DCN3_2_VMIN_DISPCLK_HZ 71700 +#define MIN_SUBVP_DCFCLK_KHZ 40 #define TO_DCN32_RES_POOL(pool)\ container_of(pool, struct dcn32_resource_pool, base) @@ -181,6 +182,8 @@ bool dcn32_subvp_vblank_admissable(struct dc *dc, struct dc_state *context, int void dcn32_update_dml_pipes_odm_policy_based_on_context(struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes); +void dcn32_override_min_req_dcfclk(struct dc *dc, struct dc_state *context); + /* definitions for run time init of reg offsets */ /* CLK SRC */ -- 2.34.1
[PATCH 05/34] drm/amd/display: Set DCN351 BB and IP the same as DCN35
From: Xi Liu [WHY & HOW] DCN351 and DCN35 should use the same bounding box and IP settings. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Jun Lei Acked-by: Alex Hung Signed-off-by: Xi Liu --- .../gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c | 6 +- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index 17a58f41fc6a..a20f28a5d2e7 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -228,17 +228,13 @@ void dml2_init_socbb_params(struct dml2_context *dml2, const struct dc *in_dc, s break; case dml_project_dcn35: + case dml_project_dcn351: out->num_chans = 4; out->round_trip_ping_latency_dcfclk_cycles = 106; out->smn_latency_us = 2; out->dispclk_dppclk_vco_speed_mhz = 3600; break; - case dml_project_dcn351: - out->num_chans = 16; - out->round_trip_ping_latency_dcfclk_cycles = 1100; - out->smn_latency_us = 2; - break; } /* ---Overrides if available--- */ if (dml2->config.bbox_overrides.dram_num_chan) -- 2.34.1
[PATCH 04/34] drm/amd/display: Add DML2 folder to include path
From: Aurabindo Pillai Add DML2 compilation rule in the Makefile. Reviewed-by: Chaitanya Dhere Acked-by: Alex Hung Signed-off-by: Aurabindo Pillai --- drivers/gpu/drm/amd/display/dc/dml2/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/Makefile b/drivers/gpu/drm/amd/display/dc/dml2/Makefile index acff3449b8d7..1c9498a72520 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml2/Makefile @@ -67,6 +67,7 @@ frame_warn_flag := -Wframe-larger-than=2048 endif endif +subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/dml2 CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_core.o := $(dml2_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml2/display_mode_util.o := $(dml2_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml2/dml2_wrapper.o := $(dml2_ccflags) -- 2.34.1
[PATCH 03/34] drm/amd/display: Add some forward declarations
From: Aurabindo Pillai [WHAT] Add DML2 pipe and config struct forward declaration as a preparation for DML2. Reviewed-by: Chaitanya Dhere Acked-by: Alex Hung Signed-off-by: Aurabindo Pillai --- drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h index 2f91244a7b01..1538b708d8be 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.h @@ -30,6 +30,8 @@ #include "dml2_dc_types.h" struct dml2_context; +struct dml2_dml_to_dc_pipe_mapping; +struct dml_display_cfg_st; /* * dml2_map_dc_pipes - Creates a pipe linkage in dc_state based on current display config. -- 2.34.1
[PATCH 02/34] drm/amd/display: Enable DML2 debug flags
From: Aurabindo Pillai [WHY & HOW] Enable DML2 related debug config options in DM for testing purposes. Reviewed-by: Chaitanya Dhere Acked-by: Alex Hung Signed-off-by: Aurabindo Pillai --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 32efce81a5a7..e12f56ca3b6a 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1766,6 +1766,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) if (amdgpu_dc_debug_mask & DC_FORCE_SUBVP_MCLK_SWITCH) adev->dm.dc->debug.force_subvp_mclk_switch = true; + if (amdgpu_dc_debug_mask & DC_ENABLE_DML2) + adev->dm.dc->debug.using_dml2 = true; + adev->dm.dc->debug.visual_confirm = amdgpu_dc_visual_confirm; /* TODO: Remove after DP2 receiver gets proper support of Cable ID feature */ -- 2.34.1
[PATCH 01/34] drm/amd/display: Change default size for dummy plane in DML2
From: Swapnil Patel [WHY & HOW] Currently, to map dc states into dml_display_cfg, We create a dummy plane if the stream doesn't have any planes attached to it. This dummy plane uses max addersable width height. This results in certain mode validations failing when they shouldn't. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Chaitanya Dhere Acked-by: Alex Hung Signed-off-by: Swapnil Patel --- .../display/dc/dml2/dml2_translation_helper.c | 18 +++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c index 1ba6933d2b36..17a58f41fc6a 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_translation_helper.c @@ -824,13 +824,25 @@ static struct scaler_data get_scaler_data_for_plane(const struct dc_plane_state static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned int location, const struct dc_stream_state *in) { + dml_uint_t width, height; + + if (in->timing.h_addressable > 3840) + width = 3840; + else + width = in->timing.h_addressable; // 4K max + + if (in->timing.v_addressable > 2160) + height = 2160; + else + height = in->timing.v_addressable; // 4K max + out->CursorBPP[location] = dml_cur_32bit; out->CursorWidth[location] = 256; out->GPUVMMinPageSizeKBytes[location] = 256; - out->ViewportWidth[location] = in->timing.h_addressable; - out->ViewportHeight[location] = in->timing.v_addressable; + out->ViewportWidth[location] = width; + out->ViewportHeight[location] = height; out->ViewportStationary[location] = false; out->ViewportWidthChroma[location] = 0; out->ViewportHeightChroma[location] = 0; @@ -849,7 +861,7 @@ static void populate_dummy_dml_plane_cfg(struct dml_plane_cfg_st *out, unsigned out->HTapsChroma[location] = 0; out->VTapsChroma[location] = 0; out->SourceScan[location] = dml_rotation_0; - out->ScalerRecoutWidth[location] = in->timing.h_addressable; + out->ScalerRecoutWidth[location] = width; out->LBBitPerPixel[location] = 57; -- 2.34.1
[PATCH 00/34] DC Patches Feb 28, 2020
This DC patchset brings improvements in multiple areas. In summary, we highlight: * Fixes on HDCP, eDP and FW idle check. * Enhancement in debug messages * Improvement on updates sequences * DPP refactoring to a new directory * Enhancements in DMUB Cc: Daniel Wheeler Allen Pan (1): drm/amd/display: Add a dc_state NULL check in dc_state_release Alvin Lee (1): drm/amd/display: Backup and restore only on full updates Anthony Koo (2): drm/amd/display: Add entry and exit counters drm/amd/display: Update DMUB flags and definitions Aric Cyr (2): drm/amd/display: 3.2.274 drm/amd/display: 3.2.275 Aurabindo Pillai (3): drm/amd/display: Enable DML2 debug flags drm/amd/display: Add some forward declarations drm/amd/display: Add DML2 folder to include path ChunTao Tso (1): drm/amd/display: Amend coasting vtotal for replay low hz Dillon Varone (1): drm/amd/display: Init DPPCLK from SMU on dcn32 George Shen (1): drm/amd/display: Add left edge pixel for YCbCr422/420 + ODM pipe split Josip Pavic (1): drm/amd/display: Allow dirty rects to be sent to dmub when abm is active Muhammad Ahmed (2): drm/amd/display: Add debug key to allow disabling dtbclk drm/amd/display: Set the power_down_on_boot function pointer to null Nicholas Kazlauskas (6): drm/amd/display: Add debug prints for IPS testing drm/amd/display: Exit idle optimizations before HDCP execution drm/amd/display: Fix idle check for shared firmware state drm/amd/display: Add guards for idle on reg read/write drm/amd/display: Guard cursor idle reallow by DC debug option drm/amd/display: Add debug counters to IPS exit prints Revalla Hari Krishna (1): drm/amd/display: Refactor DPP into a component directory Robin Chen (1): drm/amd/display: Support long vblank feature Rodrigo Siqueira (2): drm/amd/display: Return the correct HDCP error code drm/amd/display: Add comments to v_total calculation and drop legacy TODO Roman Li (1): drm/amd/display: Fix function banner for amdgpu_dm_psr_disable_all() Ryan Lin (1): drm/amd/display: Add monitor patch for specific eDP Sohaib Nadeem (1): drm/amd/display: Override min required DCFCLK in dml1_validate Swapnil Patel (1): drm/amd/display: Change default size for dummy plane in DML2 Wenjing Liu (4): drm/amd/display: Update odm when ODM combine is changed on an otg master pipe with no plane drm/amd/display: Implement update_planes_and_stream_v3 sequence drm/amd/display: Lock all enabled otg pipes even with no planes drm/amd/display: Implement wait_for_odm_update_pending_complete Xi Liu (1): drm/amd/display: Set DCN351 BB and IP the same as DCN35 drivers/gpu/drm/amd/display/Makefile | 1 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 + .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 6 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_psr.c | 2 +- drivers/gpu/drm/amd/display/dc/Makefile | 2 +- .../display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 14 + .../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 3 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 824 -- .../gpu/drm/amd/display/dc/core/dc_resource.c | 37 + .../gpu/drm/amd/display/dc/core/dc_state.c| 4 +- .../gpu/drm/amd/display/dc/core/dc_stream.c | 4 +- drivers/gpu/drm/amd/display/dc/dc.h | 174 ++-- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 94 ++ drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h | 1 + drivers/gpu/drm/amd/display/dc/dc_hw_types.h | 1 + drivers/gpu/drm/amd/display/dc/dc_types.h | 4 +- .../gpu/drm/amd/display/dc/dce/dmub_replay.c | 2 +- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 4 +- .../amd/display/dc/dcn10/dcn10_cm_common.c| 2 +- .../gpu/drm/amd/display/dc/dcn10/dcn10_opp.c | 1 + drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.c | 14 + .../gpu/drm/amd/display/dc/dcn20/dcn20_opp.h | 2 + .../gpu/drm/amd/display/dc/dcn201/Makefile| 2 +- .../drm/amd/display/dc/dcn201/dcn201_opp.c| 1 + drivers/gpu/drm/amd/display/dc/dcn30/Makefile | 2 - .../amd/display/dc/dcn30/dcn30_cm_common.c| 2 +- drivers/gpu/drm/amd/display/dc/dcn32/Makefile | 2 +- .../display/dc/dcn32/dcn32_resource_helpers.c | 6 + drivers/gpu/drm/amd/display/dc/dcn35/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dml2/Makefile | 1 + .../display/dc/dml2/dml2_dc_resource_mgmt.h | 2 + .../display/dc/dml2/dml2_translation_helper.c | 24 +- .../drm/amd/display/dc/dml2/dml2_wrapper.c| 28 +- .../drm/amd/display/dc/dml2/dml2_wrapper.h| 3 + drivers/gpu/drm/amd/display/dc/dpp/Makefile | 77 ++ .../amd/display/dc/dpp/dcn10/CMakeLists.txt | 6 + .../display/dc/{ => dpp}/dcn10/dcn10_dpp.c| 2 +- .../display/dc/{ => dpp}/dcn10/dcn10_dpp.h| 0 .../display/dc/{ => dpp}/dcn10/dcn10_dpp_cm.c | 4 +- .../dc/{ => dpp}/dcn10/dcn10_dpp_dscl.c | 2 +-
Re: [RFC PATCH 2/2] drm/amd/display: switch amdgpu_dm_connector to use struct drm_edid
On 2024-01-26 09:28, Melissa Wen wrote: Replace raw edid handling (struct edid) with the opaque EDID type (struct drm_edid) on amdgpu_dm_connector for consistency. It may also prevent mismatch of approaches in different parts of the driver code. Working in progress. There are a couple of cast warnings and it was only tested with IGT. Signed-off-by: Melissa Wen --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 63 ++- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 4 +- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 9 +-- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 23 +++ 4 files changed, 51 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 68e71e2ea472..741081d73bb3 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3277,12 +3277,12 @@ void amdgpu_dm_update_connector_after_detect( >dm_dp_aux.aux); } } else { - aconnector->edid = - (struct edid *)sink->dc_edid.raw_edid; + const struct edid *edid = (const struct edid *)sink->dc_edid.raw_edid; + aconnector->edid = drm_edid_alloc(edid, (edid->extensions + 1) * EDID_LENGTH); if (aconnector->dc_link->aux_mode) drm_dp_cec_set_edid(>dm_dp_aux.aux, - aconnector->edid); + drm_edid_raw(aconnector->edid)); } if (!aconnector->timing_requested) { @@ -3293,13 +3293,13 @@ void amdgpu_dm_update_connector_after_detect( "failed to create aconnector->requested_timing\n"); } - drm_connector_update_edid_property(connector, aconnector->edid); + drm_edid_connector_update(connector, aconnector->edid); amdgpu_dm_update_freesync_caps(connector, aconnector->edid); update_connector_ext_caps(aconnector); } else { drm_dp_cec_unset_edid(>dm_dp_aux.aux); amdgpu_dm_update_freesync_caps(connector, NULL); - drm_connector_update_edid_property(connector, NULL); + drm_edid_connector_update(connector, NULL); aconnector->num_modes = 0; dc_sink_release(aconnector->dc_sink); aconnector->dc_sink = NULL; @@ -6564,7 +6564,6 @@ static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector) struct dc_link *dc_link = aconnector->dc_link; struct dc_sink *dc_em_sink = aconnector->dc_em_sink; const struct drm_edid *drm_edid; - const struct edid *edid; /* * Note: drm_get_edid gets edid in the following order: @@ -6578,11 +6577,12 @@ static void amdgpu_dm_connector_funcs_force(struct drm_connector *connector) DRM_ERROR("No EDID found on connector: %s.\n", connector->name); return; } - edid = drm_edid_raw(drm_edid); - aconnector->edid = edid; - + aconnector->edid = drm_edid; + drm_edid_connector_update(connector, drm_edid); /* Update emulated (virtual) sink's EDID */ if (dc_em_sink && dc_link) { + const struct edid *edid = drm_edid_raw(drm_edid); + memset(_em_sink->edid_caps, 0, sizeof(struct dc_edid_caps)); memmove(dc_em_sink->dc_edid.raw_edid, (uint8_t *)edid, (edid->extensions + 1) * EDID_LENGTH); dm_helpers_parse_edid_caps( @@ -6633,13 +6633,13 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector) return; } - edid = drm_edid_raw(drm_edid); - - if (drm_detect_hdmi_monitor(edid)) + if (connector->display_info.is_hdmi) init_params.sink_signal = SIGNAL_TYPE_HDMI_TYPE_A; - aconnector->edid = edid; + aconnector->edid = drm_edid; + drm_edid_connector_update(connector, drm_edid); + edid = drm_edid_raw(drm_edid); aconnector->dc_em_sink = dc_link_add_remote_sink( aconnector->dc_link, (uint8_t *)edid, @@ -7322,16 +7322,16 @@ static void amdgpu_set_panel_orientation(struct drm_connector *connector) } static void amdgpu_dm_connector_ddc_get_modes(struct drm_connector *connector, - struct edid *edid) + const struct drm_edid *drm_edid) { struct amdgpu_dm_connector *amdgpu_dm_connector = to_amdgpu_dm_connector(connector); - if (edid) { + if (drm_edid) { /* empty probed_modes */ INIT_LIST_HEAD(>probed_modes);
Re: [PATCH] drm/amd/display: Drop 'acrtc' and add 'new_crtc_state' NULL check for writeback requests.
Thanks for catching this. Reviewed-by: Alex Hung On 2024-01-13 02:11, Srinivasan Shanmugam wrote: Return value of 'to_amdgpu_crtc' which is container_of(...) can't be null, so it's null check 'acrtc' is dropped. Fixing the below: drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:9302 amdgpu_dm_atomic_commit_tail() error: we previously assumed 'acrtc' could be null (see line 9299) Add 'new_crtc_state'NULL check for function 'drm_atomic_get_new_crtc_state' that retrieves the new state for a CRTC, while enabling writeback requests. Cc: sta...@vger.kernel.org Cc: Alex Hung Cc: Aurabindo Pillai Cc: Rodrigo Siqueira Cc: Hamza Mahfooz Signed-off-by: Srinivasan Shanmugam --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 95ff3800fc87..8eb381d5f6b8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -9294,10 +9294,10 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) if (!new_con_state->writeback_job) continue; - new_crtc_state = NULL; + new_crtc_state = drm_atomic_get_new_crtc_state(state, >base); - if (acrtc) - new_crtc_state = drm_atomic_get_new_crtc_state(state, >base); + if (!new_crtc_state) + continue; if (acrtc->wb_enabled) continue;
[PATCH 19/19] drm/amd/display: 3.2.267
From: Martin Leung - Align the returned error code with legacy DP - Allow Z8 for multiplane configurations on DCN35 - Set default Z8 minimum residency for DCN35 - Rework DC Z10 restore - Enable Panel Replay for static screen use case - Add DP audio BW validation - Fix dml2 assigned pipe search - Ensure populate uclk in bb construction - Update P010 scaling cap - Reenable windowed mpo odm support - Fix DML2 watermark calculation - Clear OPTC mem select on disable - Floor to mhz when requesting dpp disp clock changes to SMU - Port DENTIST hang and TDR fixes to OTG disable W/A - Add logging resource checks - Add Replay IPS register for DMUB command table - Init link enc resources in dc_state only if res_pool presents - Allow IPS2 during Replay Acked-by: Alex Hung Signed-off-by: Martin Leung --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c9317ea0258e..1d052742d4c7 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -51,7 +51,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.266" +#define DC_VER "3.2.267" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- 2.34.1
[PATCH 18/19] drm/amd/display: Align the returned error code with legacy DP
From: Wayne Lin [Why] For usb4 connector, AUX transaction is handled by dmub utilizing a differnt code path comparing to legacy DP connector. If the usb4 DP connector is disconnected, AUX access will report EBUSY and cause igt@kms_dp_aux_dev fail. [How] Align the error code with the one reported by legacy DP as EIO. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Acked-by: Alex Hung Signed-off-by: Wayne Lin --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index d3966ce3dc91..e3915c4f8566 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -978,6 +978,11 @@ int dm_helper_dmub_aux_transfer_sync( struct aux_payload *payload, enum aux_return_code_type *operation_result) { + if (!link->hpd_status) { + *operation_result = AUX_RET_ERROR_HPD_DISCON; + return -1; + } + return amdgpu_dm_process_dmub_aux_transfer_sync(ctx, link->link_index, payload, operation_result); } -- 2.34.1
[PATCH 17/19] drm/amd/display: Allow Z8 for multiplane configurations on DCN35
From: Nicholas Kazlauskas [Why] Power improvement over DCN314, but also addresses a functional issue where plane_state remains uncleared on pipes that aren't actually active. [How] Update the check to allow for zero streams to be treated as z8 allow. Update the check to remove plane count on the active stream case. Z8 will still be blocked based on stutter duration, which is likely to be the case for most multi plane configurations. Reviewed-by: Gabe Teeger Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c index 475c4ec43c01..a85693caebd5 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn35/dcn35_fpu.c @@ -583,9 +583,9 @@ void dcn35_decide_zstate_support(struct dc *dc, struct dc_state *context) plane_count++; } - if (plane_count == 0) { + if (context->stream_count == 0 || plane_count == 0) { support = DCN_ZSTATE_SUPPORT_ALLOW; - } else if (plane_count == 1 && context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { + } else if (context->stream_count == 1 && context->streams[0]->signal == SIGNAL_TYPE_EDP) { struct dc_link *link = context->streams[0]->sink->link; bool is_pwrseq0 = link && link->link_index == 0; bool is_psr1 = link && link->psr_settings.psr_version == DC_PSR_VERSION_1 && !link->panel_config.psr.disable_psr; -- 2.34.1
[PATCH 16/19] drm/amd/display: Set default Z8 minimum residency for DCN35
From: Nicholas Kazlauskas [Why & How] Match DCN314's policy. Reviewed-by: Gabe Teeger Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 7d8e957d6a19..5f7cf01abef9 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -764,6 +764,7 @@ static const struct dc_debug_options debug_defaults_drv = { }, .seamless_boot_odm_combine = DML_FAIL_SOURCE_PIXEL_FORMAT, .enable_z9_disable_interface = true, /* Allow support for the PMFW interface for disable Z9*/ + .minimum_z8_residency_time = 2100, .using_dml2 = true, .support_eDP1_5 = true, .enable_hpo_pg_support = false, -- 2.34.1
[PATCH 15/19] drm/amd/display: Rework DC Z10 restore
From: Nicholas Kazlauskas [Why] The call currently does two things: 1. Exits DMCUB from idle optimization if it was in 2. Checks DMCUB scratch register to determine if we need to call DMCUB to do deferred HW restore and then sends the command if it's ready for it. By doing (1) we prevent driver idle from being renotified in the cases where driver had previously allowed DC level idle optimizations via dc_allow_idle_optimizations since it thinks: allow == dc->idle_optimizations_allowed ...and that the operation is a no-op. We want driver idle to be resent at the next opprotunity to do so for video playback cases. [How] Migrate all usecases of dc_z10_restore to only perform (2). Add extra calls to dc_allow_idle_optimizations to handle (1) and also keep SW state matching with when we requested enter/exit of DMCUB idle optimizations. Ensure cursor idle optimizations false always get called when IPS is supported. Further rework/redesign is needed to decide whether we need a separate level of DM allow vs DC allow and when to attempt re-entry. Reviewed-by: Yihan Zhu Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/dc/core/dc.c | 11 ++- drivers/gpu/drm/amd/display/dc/core/dc_stream.c | 9 + .../gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 2 -- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index aa7c02ba948e..af83ec23f3a0 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1836,8 +1836,8 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c struct dc_state *old_state; bool subvp_prev_use = false; - dc_z10_restore(dc); dc_allow_idle_optimizations(dc, false); + dc_z10_restore(dc); for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *old_pipe = >current_state->res_ctx.pipe_ctx[i]; @@ -3376,6 +3376,9 @@ static void commit_planes_for_stream_fast(struct dc *dc, int i, j; struct pipe_ctx *top_pipe_to_program = NULL; struct dc_stream_status *stream_status = NULL; + if (dc->caps.ips_support) + dc_allow_idle_optimizations(dc, false); + dc_z10_restore(dc); top_pipe_to_program = resource_get_otg_master_for_stream( @@ -3503,6 +3506,9 @@ static void commit_planes_for_stream(struct dc *dc, // dc->current_state anymore, so we have to cache it before we apply // the new SubVP context subvp_prev_use = false; + if (dc->caps.ips_support) + dc_allow_idle_optimizations(dc, false); + dc_z10_restore(dc); if (update_type == UPDATE_TYPE_FULL) wait_for_outstanding_hw_updates(dc, context); @@ -4686,6 +4692,9 @@ void dc_set_power_state( case DC_ACPI_CM_POWER_STATE_D0: dc_state_construct(dc, dc->current_state); + if (dc->caps.ips_support) + dc_allow_idle_optimizations(dc, false); + dc_z10_restore(dc); dc->hwss.init_hw(dc); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c index 54670e0b1518..23f4f3c070cb 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c @@ -309,7 +309,6 @@ bool dc_stream_set_cursor_attributes( stream->cursor_attributes = *attributes; - dc_z10_restore(dc); /* disable idle optimizations while updating cursor */ if (dc->idle_optimizations_allowed) { dc_allow_idle_optimizations(dc, false); @@ -381,12 +380,14 @@ bool dc_stream_set_cursor_position( } dc = stream->ctx->dc; - dc_z10_restore(dc); /* disable idle optimizations if enabling cursor */ - if (dc->idle_optimizations_allowed && (!stream->cursor_position.enable || dc->debug.exit_idle_opt_for_cursor_updates) - && position->enable) { + if (dc->idle_optimizations_allowed && + (!stream->cursor_position.enable || dc->debug.exit_idle_opt_for_cursor_updates || +dc->caps.ips_support) && + position->enable) { dc_allow_idle_optimizations(dc, false); + dc_z10_restore(dc); reset_idle_optimizations = true; } diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 8b6c49622f3b..da4f98de9b82 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -708,8 +708
[PATCH 14/19] drm/amd/display: Enable Panel Replay for static screen use case
From: Tom Chung [Why] Enable the Panel Replay if eDP panel and ASIC support. (prioritize Panel Replay over PSR) [How] - Setup the Panel Replay config during the device init (prioritize Panel Replay over PSR). - Separate the Replay init function into two functions amdgpu_dm_link_setup_replay() and amdgpu_dm_set_replay_caps() to fix the issue in the earlier commit that cause PSR and Replay enabled at the same time. Reviewed-by: Sun peng Li Acked-by: Alex Hung Signed-off-by: Tom Chung --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 42 ++- .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c| 59 +++-- .../amd/display/amdgpu_dm/amdgpu_dm_replay.c | 119 ++ .../amd/display/amdgpu_dm/amdgpu_dm_replay.h | 4 +- 4 files changed, 156 insertions(+), 68 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 95ff3800fc87..f9e41006ac87 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -67,6 +67,7 @@ #include "amdgpu_dm_debugfs.h" #endif #include "amdgpu_dm_psr.h" +#include "amdgpu_dm_replay.h" #include "ivsrcid/ivsrcid_vislands30.h" @@ -4393,6 +4394,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) enum dc_connection_type new_connection_type = dc_connection_none; const struct dc_plane_cap *plane; bool psr_feature_enabled = false; + bool replay_feature_enabled = false; int max_overlay = dm->dc->caps.max_slave_planes; dm->display_indexes_num = dm->dc->caps.max_streams; @@ -4504,6 +4506,23 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) } } + /* Determine whether to enable Replay support by default. */ + if (!(amdgpu_dc_debug_mask & DC_DISABLE_REPLAY)) { + switch (amdgpu_ip_version(adev, DCE_HWIP, 0)) { + case IP_VERSION(3, 1, 4): + case IP_VERSION(3, 1, 5): + case IP_VERSION(3, 1, 6): + case IP_VERSION(3, 2, 0): + case IP_VERSION(3, 2, 1): + case IP_VERSION(3, 5, 0): + replay_feature_enabled = true; + break; + default: + replay_feature_enabled = amdgpu_dc_feature_mask & DC_REPLAY_MASK; + break; + } + } + /* loops over all connectors on the board */ for (i = 0; i < link_cnt; i++) { struct dc_link *link = NULL; @@ -4572,6 +4591,11 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev) amdgpu_dm_update_connector_after_detect(aconnector); setup_backlight_device(dm, aconnector); + /* Disable PSR if Replay can be enabled */ + if (replay_feature_enabled) + if (amdgpu_dm_set_replay_caps(link, aconnector)) + psr_feature_enabled = false; + if (psr_feature_enabled) amdgpu_dm_set_psr_caps(link); @@ -8521,10 +8545,17 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, dm_update_pflip_irq_state(drm_to_adev(dev), acrtc_attach); - if ((acrtc_state->update_type > UPDATE_TYPE_FAST) && - acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && - !acrtc_state->stream->link->psr_settings.psr_feature_enabled) - amdgpu_dm_link_setup_psr(acrtc_state->stream); + if (acrtc_state->update_type > UPDATE_TYPE_FAST) { + if (acrtc_state->stream->link->replay_settings.config.replay_supported && + !acrtc_state->stream->link->replay_settings.replay_feature_enabled) { + struct amdgpu_dm_connector *aconn = + (struct amdgpu_dm_connector *)acrtc_state->stream->dm_stream_context; + amdgpu_dm_link_setup_replay(acrtc_state->stream->link, aconn); + } else if (acrtc_state->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED && + !acrtc_state->stream->link->psr_settings.psr_feature_enabled) { + amdgpu_dm_link_setup_psr(acrtc_state->stream); + } + }
[PATCH 13/19] drm/amd/display: Add DP audio BW validation
From: George Shen [Why] Timings with small HBlank (such as CVT RBv2) can result in insufficient HBlank bandwidth for audio SDP transmission when DSC is active. This will cause some higher bandwidth audio modes to fail. The combination of CVT RBv2 timings + DSC can commonly be encountered in MST scenarios. [How] Add DP audio bandwidth validation for 8b/10b MST and 128b/132b SST/MST cases and filter out modes that cannot be supported with the current timing config. Reviewed-by: Wenjing Liu Acked-by: Alex Hung Signed-off-by: George Shen --- .../gpu/drm/amd/display/dc/dce/dce_audio.c| 288 +- .../gpu/drm/amd/display/dc/dce/dce_audio.h| 3 +- .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 56 +++- drivers/gpu/drm/amd/display/dc/inc/hw/audio.h | 3 +- .../gpu/drm/amd/display/include/audio_types.h | 15 + 5 files changed, 349 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c index f0458b8f00af..07b507150c51 100644 --- a/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c +++ b/drivers/gpu/drm/amd/display/dc/dce/dce_audio.c @@ -239,27 +239,289 @@ static void check_audio_bandwidth_hdmi( } } } +static struct fixed31_32 get_link_symbol_clk_freq_mhz(enum dc_link_rate link_rate) +{ + switch (link_rate) { + case LINK_RATE_LOW: + return dc_fixpt_from_int(162); /* 162 MHz */ + case LINK_RATE_HIGH: + return dc_fixpt_from_int(270); /* 270 MHz */ + case LINK_RATE_HIGH2: + return dc_fixpt_from_int(540); /* 540 MHz */ + case LINK_RATE_HIGH3: + return dc_fixpt_from_int(810); /* 810 MHz */ + case LINK_RATE_UHBR10: + return dc_fixpt_from_fraction(3125, 10); /* 312.5 MHz */ + case LINK_RATE_UHBR13_5: + return dc_fixpt_from_fraction(421875, 1000); /* 421.875 MHz */ + case LINK_RATE_UHBR20: + return dc_fixpt_from_int(625); /* 625 MHz */ + default: + /* Unexpected case, this requires debug if encountered. */ + ASSERT(0); + return dc_fixpt_from_int(0); + } +} + +struct dp_audio_layout_config { + uint8_t layouts_per_sample_denom; + uint8_t symbols_per_layout; + uint8_t max_layouts_per_audio_sdp; +}; + +static void get_audio_layout_config( + uint32_t channel_count, + enum dp_link_encoding encoding, + struct dp_audio_layout_config *output) +{ + /* Assuming L-PCM audio. Current implementation uses max 1 layout per SDP, +* with each layout being the same size (8ch layout). +*/ + if (encoding == DP_8b_10b_ENCODING) { + if (channel_count == 2) { + output->layouts_per_sample_denom = 4; + output->symbols_per_layout = 40; + output->max_layouts_per_audio_sdp = 1; + } else if (channel_count == 8) { + output->layouts_per_sample_denom = 1; + output->symbols_per_layout = 40; + output->max_layouts_per_audio_sdp = 1; + } + } else if (encoding == DP_128b_132b_ENCODING) { + if (channel_count == 2) { + output->layouts_per_sample_denom = 4; + output->symbols_per_layout = 10; + output->max_layouts_per_audio_sdp = 1; + } else if (channel_count == 8) { + output->layouts_per_sample_denom = 1; + output->symbols_per_layout = 10; + output->max_layouts_per_audio_sdp = 1; + } + } +} -/*For DP SST, calculate if specified sample rates can fit into a given timing */ -static void check_audio_bandwidth_dpsst( +static uint32_t get_av_stream_map_lane_count( + enum dp_link_encoding encoding, + enum dc_lane_count lane_count, + bool is_mst) +{ + uint32_t av_stream_map_lane_count = 0; + + if (encoding == DP_8b_10b_ENCODING) { + if (!is_mst) + av_stream_map_lane_count = lane_count; + else + av_stream_map_lane_count = 4; + } else if (encoding == DP_128b_132b_ENCODING) { + av_stream_map_lane_count = 4; + } + + ASSERT(av_stream_map_lane_count != 0); + + return av_stream_map_lane_count; +} + +static uint32_t get_audio_sdp_overhead( + enum dp_link_encoding encoding, + enum dc_lane_count lane_count, + bool is_mst) +{ + uint32_t audio_sdp_overhead = 0; + + if (encoding == DP_8b_10b_ENCODING) { + if (is_mst) + audio_sdp_overhead = 16; /* 4 * 2 + 8 */ + else + audio_sdp_overhead = lane_count * 2 + 8; + } else i
[PATCH 12/19] drm/amd/display: Fix dml2 assigned pipe search
From: Dmytro Laktyushkin [Why & How] DML2 currently finds assigned pipes in array order rather than the existing linked list order. This results in rearranging pipe order on flip and more importantly otg inst and pipe idx mismatch. This change preserves the order of existing pipes and guarantees the head pipe will have matching otg inst and pipe idx. Reviewed-by: Gabe Teeger Acked-by: Alex Hung Signed-off-by: Dmytro Laktyushkin --- .../display/dc/dml2/dml2_dc_resource_mgmt.c | 36 ++- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c index 0baf39d64a2d..a0ce681b26c6 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c @@ -141,14 +141,28 @@ static unsigned int find_pipes_assigned_to_plane(struct dml2_context *ctx, { int i; unsigned int num_found = 0; - unsigned int plane_id_assigned_to_pipe; + unsigned int plane_id_assigned_to_pipe = -1; for (i = 0; i < ctx->config.dcn_pipe_count; i++) { - if (state->res_ctx.pipe_ctx[i].plane_state && get_plane_id(ctx, state, state->res_ctx.pipe_ctx[i].plane_state, - state->res_ctx.pipe_ctx[i].stream->stream_id, - ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[state->res_ctx.pipe_ctx[i].pipe_idx], _id_assigned_to_pipe)) { - if (plane_id_assigned_to_pipe == plane_id) - pipes[num_found++] = i; + struct pipe_ctx *pipe = >res_ctx.pipe_ctx[i]; + + if (!pipe->stream) + continue; + + get_plane_id(ctx, state, pipe->plane_state, pipe->stream->stream_id, + ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[pipe->pipe_idx], + _id_assigned_to_pipe); + if (pipe->plane_state && plane_id_assigned_to_pipe == plane_id && !pipe->top_pipe && !pipe->prev_odm_pipe) { + while (pipe) { + struct pipe_ctx *mpo_pipe = pipe; + + while (mpo_pipe) { + pipes[num_found++] = mpo_pipe->pipe_idx; + mpo_pipe = mpo_pipe->bottom_pipe; + } + pipe = pipe->next_odm_pipe; + } + break; } } @@ -566,8 +580,14 @@ static unsigned int find_pipes_assigned_to_stream(struct dml2_context *ctx, stru unsigned int num_found = 0; for (i = 0; i < ctx->config.dcn_pipe_count; i++) { - if (state->res_ctx.pipe_ctx[i].stream && state->res_ctx.pipe_ctx[i].stream->stream_id == stream_id) { - pipes[num_found++] = i; + struct pipe_ctx *pipe = >res_ctx.pipe_ctx[i]; + + if (pipe->stream && pipe->stream->stream_id == stream_id && !pipe->top_pipe && !pipe->prev_odm_pipe) { + while (pipe) { + pipes[num_found++] = pipe->pipe_idx; + pipe = pipe->next_odm_pipe; + } + break; } } -- 2.34.1
[PATCH 11/19] drm/amd/display: Ensure populate uclk in bb construction
From: Alvin Lee [Description] - For some SKUs, the optimal DCFCLK for each UCLK is less than the smallest DCFCLK STA target due to low memory bandwidth. There is an assumption that the DCFCLK STA targets will always be less than one of the optimal DCFCLK values, but this is not true for SKUs that have low memory bandwidth. In this case we need to populate the optimal UCLK for each DCFCLK STA targets as the max UCLK freq. - Also fix a bug in DML where start_state is not assigned and used correctly. Reviewed-by: Samson Tam Reviewed-by: Chaitanya Dhere Acked-by: Alex Hung Signed-off-by: Alvin Lee --- .../display/dc/dml/dcn30/display_mode_vba_30.c | 16 .../drm/amd/display/dc/dml/dcn303/dcn303_fpu.c | 11 +++ .../display/dc/resource/dcn30/dcn30_resource.c | 11 +++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index 63c48c29ba49..e7f4a2d491cc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -4273,7 +4273,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l //Calculate Swath, DET Configuration, DCFCLKDeepSleep // - for (i = 0; i < mode_lib->soc.num_states; ++i) { + for (i = start_state; i < mode_lib->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { for (k = 0; k < v->NumberOfActivePlanes; ++k) { v->RequiredDPPCLKThisState[k] = v->RequiredDPPCLK[i][j][k]; @@ -4576,7 +4576,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l //Calculate Return BW - for (i = 0; i < mode_lib->soc.num_states; ++i) { + for (i = start_state; i < mode_lib->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) { if (v->BlendingAndTiming[k] == k) { @@ -4635,7 +4635,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l v->UrgentOutOfOrderReturnPerChannelVMDataOnly); v->FinalDRAMClockChangeLatency = (v->DRAMClockChangeLatencyOverride > 0 ? v->DRAMClockChangeLatencyOverride : v->DRAMClockChangeLatency); - for (i = 0; i < mode_lib->soc.num_states; ++i) { + for (i = start_state; i < mode_lib->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { v->DCFCLKState[i][j] = v->DCFCLKPerState[i]; } @@ -4646,7 +4646,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l if (v->ClampMinDCFCLK) { /* Clamp calculated values to actual minimum */ - for (i = 0; i < mode_lib->soc.num_states; ++i) { + for (i = start_state; i < mode_lib->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { if (v->DCFCLKState[i][j] < mode_lib->soc.min_dcfclk) { v->DCFCLKState[i][j] = mode_lib->soc.min_dcfclk; @@ -4656,7 +4656,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } } - for (i = 0; i < mode_lib->soc.num_states; ++i) { + for (i = start_state; i < mode_lib->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { v->IdealSDPPortBandwidthPerState[i][j] = dml_min3( v->ReturnBusWidth * v->DCFCLKState[i][j], @@ -4674,7 +4674,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l //Re-ordering Buffer Support Check - for (i = 0; i < mode_lib->soc.num_states; ++i) { + for (i = start_state; i < mode_lib->soc.num_states; ++i) { for (j = 0; j <= 1; ++j) { if ((v->ROBBufferSizeInKByte - v->PixelChunkSizeInKByte) * 1024 / v->ReturnBWPerState[i][j] > (v->RoundTripPingLatencyCycles + 32) / v->DCFCLKState[i][j] + ReorderingBytes / v->ReturnBWPerState[i][j]) { @@ -4692,7 +4692,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l MaxTotalVActiveRDBandwidth = MaxTotalVActiveRDBandwidth + v->ReadBandwidthLuma[k] + v->ReadBandwidthChroma[k]; } - for (i = 0; i < mode_lib->soc.num_states; ++i) { + for (i = start_state; i < mode_
[PATCH 10/19] drm/amd/display: Update P010 scaling cap
From: Charlene Liu [Why] Keep the same as previous APU and also insert clock dump Reviewed-by: Ovidiu Bunea Acked-by: Alex Hung Signed-off-by: Charlene Liu --- .../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 25 +-- .../dc/resource/dcn35/dcn35_resource.c| 2 +- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 9c660d1facc7..0e5a3184f01c 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -384,19 +384,6 @@ static void dcn35_enable_pme_wa(struct clk_mgr *clk_mgr_base) dcn35_smu_enable_pme_wa(clk_mgr); } -void dcn35_init_clocks(struct clk_mgr *clk_mgr) -{ - uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz; - - memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks)); - - // Assumption is that boot state always supports pstate - clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk - clk_mgr->clks.p_state_change_support = true; - clk_mgr->clks.prev_p_state_change_support = true; - clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN; - clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN; -} bool dcn35_are_clock_states_equal(struct dc_clocks *a, struct dc_clocks *b) @@ -421,7 +408,19 @@ static void dcn35_dump_clk_registers(struct clk_state_registers_and_bypass *regs struct clk_mgr_dcn35 *clk_mgr) { } +void dcn35_init_clocks(struct clk_mgr *clk_mgr) +{ + uint32_t ref_dtbclk = clk_mgr->clks.ref_dtbclk_khz; + memset(&(clk_mgr->clks), 0, sizeof(struct dc_clocks)); + + // Assumption is that boot state always supports pstate + clk_mgr->clks.ref_dtbclk_khz = ref_dtbclk; // restore ref_dtbclk + clk_mgr->clks.p_state_change_support = true; + clk_mgr->clks.prev_p_state_change_support = true; + clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN; + clk_mgr->clks.zstate_support = DCN_ZSTATE_SUPPORT_UNKNOWN; +} static struct clk_bw_params dcn35_bw_params = { .vram_type = Ddr4MemType, .num_channels = 1, diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c index 761ec9891875..7d8e957d6a19 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c @@ -701,7 +701,7 @@ static const struct dc_plane_cap plane_cap = { // 6:1 downscaling ratio: 1000/6 = 166.666 .max_downscale_factor = { - .argb = 167, + .argb = 250, .nv12 = 167, .fp16 = 167 }, -- 2.34.1
[PATCH 09/19] drm/amd/display: Reenable windowed mpo odm support
From: Wenjing Liu [Why] The feature was disabled due to regression found during testing. Now that all the pending issues are addressed, we are reenabling the power saving feature again. The feature optimizes dispclk level when user is using MPO capable broswers or watching MPO capable videos in windowed mode. The feature achieves power optimization by utilizing free pipes to process incoming pixels in parallel. So it reduces max dispclk requirements for each pipe. Previously ODM power optimization will be disabled when MPO plane is present due to technical challeges. This is mainly because ODM divides pixel workload with respect to stream but MPO plane position and size are arbitrary with respect to stream. The pixel processing workload of an MPO plane is not guaranteed to be evenly distributed across DCN pipes. For example if a plane is moved inside single ODM slice, all the processing for the plane is distributed to the pipe in the current ODM slice, while the other ODM slices don't need to process this plane. If the plane is then moved to the middle crosing two ODM slices, each ODM slice gets half of the workload. This is especially difficult when the plane itself has a large source rect which can't be processed by single DCN pipe. In this case we can't enable ODM power optimization when the plane is only within one ODM slice. [How] To overcome the challeges, new pipe resource management is in place to make sure a plane is validated with ODM power optimization support if it can be validated regardless of its position and the same pipe topology can be used regardless of the plane's position. When the plane is moved outside current ODM slice, we will set recout to 0 so the pipe can be idling without the need to update pipe topology. When the user resizes a plane, it may result in downscaling ratio changes. When the downscaling ratio is above single pipe's threshold, we will seamlessly exit ODM power optimization and applies MPC combine to support the plane. when downscaling ratio becomes smaller, we will seamlessly enter ODM power optimization again. All these pipe transitions happen automatically and quietly when the conditions are met without any visual impacts to the user. Reviewed-by: Martin Leung Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c | 1 + drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c index c4d71e7f18af..5c24a769ce60 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c @@ -2104,6 +2104,7 @@ static bool dcn32_resource_construct( dc->config.use_pipe_ctx_sync_logic = true; dc->config.dc_mode_clk_limit_support = true; + dc->config.enable_windowed_mpo_odm = true; /* read VBIOS LTTPR caps */ { if (ctx->dc_bios->funcs->get_lttpr_caps) { diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c index 74412e5f03fe..b356fed1726d 100644 --- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c @@ -1760,6 +1760,7 @@ static bool dcn321_resource_construct( dc->caps.color.mpc.ocsc = 1; dc->config.dc_mode_clk_limit_support = true; + dc->config.enable_windowed_mpo_odm = true; /* read VBIOS LTTPR caps */ { if (ctx->dc_bios->funcs->get_lttpr_caps) { -- 2.34.1
[PATCH 08/19] drm/amd/display: Fix DML2 watermark calculation
From: Ovidiu Bunea [Why] core_mode_programming in DML2 should output watermark calculations to locals, but it incorrectly uses mode_lib [How] update code to match HW DML2 Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Ovidiu Bunea --- .../drm/amd/display/dc/dml2/display_mode_core.c| 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c index a6b938a12de1..9be5ebf3a8c0 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c @@ -9446,13 +9446,13 @@ void dml_core_mode_programming(struct display_mode_lib_st *mode_lib, const struc CalculateWatermarks_params->CompressedBufferSizeInkByte = locals->CompressedBufferSizeInkByte; // Output - CalculateWatermarks_params->Watermark = >dummy_watermark; // Watermarks *Watermark - CalculateWatermarks_params->DRAMClockChangeSupport = _lib->ms.support.DRAMClockChangeSupport[0]; - CalculateWatermarks_params->MaxActiveDRAMClockChangeLatencySupported = >dummy_single_array[0][0]; // dml_float_t *MaxActiveDRAMClockChangeLatencySupported[] - CalculateWatermarks_params->SubViewportLinesNeededInMALL = _lib->ms.SubViewportLinesNeededInMALL[j]; // dml_uint_t SubViewportLinesNeededInMALL[] - CalculateWatermarks_params->FCLKChangeSupport = _lib->ms.support.FCLKChangeSupport[0]; - CalculateWatermarks_params->MaxActiveFCLKChangeLatencySupported = >dummy_single[0]; // dml_float_t *MaxActiveFCLKChangeLatencySupported - CalculateWatermarks_params->USRRetrainingSupport = _lib->ms.support.USRRetrainingSupport[0]; + CalculateWatermarks_params->Watermark = >Watermark; // Watermarks *Watermark + CalculateWatermarks_params->DRAMClockChangeSupport = >DRAMClockChangeSupport; + CalculateWatermarks_params->MaxActiveDRAMClockChangeLatencySupported = locals->MaxActiveDRAMClockChangeLatencySupported; // dml_float_t *MaxActiveDRAMClockChangeLatencySupported[] + CalculateWatermarks_params->SubViewportLinesNeededInMALL = locals->SubViewportLinesNeededInMALL; // dml_uint_t SubViewportLinesNeededInMALL[] + CalculateWatermarks_params->FCLKChangeSupport = >FCLKChangeSupport; + CalculateWatermarks_params->MaxActiveFCLKChangeLatencySupported = >MaxActiveFCLKChangeLatencySupported; // dml_float_t *MaxActiveFCLKChangeLatencySupported + CalculateWatermarks_params->USRRetrainingSupport = >USRRetrainingSupport; CalculateWatermarksMALLUseAndDRAMSpeedChangeSupport( _lib->scratch, -- 2.34.1
[PATCH 07/19] drm/amd/display: Clear OPTC mem select on disable
From: Ilya Bakoulin [Why] Not clearing the memory select bits prior to OPTC disable can cause DSC corruption issues when attempting to reuse a memory instance for another OPTC that enables ODM. [How] Clear the memory select bits prior to disabling an OPTC. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Ilya Bakoulin --- drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c | 3 +++ drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c index 1788eb29474b..823493543325 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c @@ -173,6 +173,9 @@ static bool optc32_disable_crtc(struct timing_generator *optc) OPTC_SEG3_SRC_SEL, 0xf, OPTC_NUM_OF_INPUT_SEGMENT, 0); + REG_UPDATE(OPTC_MEMORY_CONFIG, + OPTC_MEM_SEL, 0); + /* disable otg request until end of the first line * in the vertical blank region */ diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c index 3d6c1b2c2b4d..5b1547508850 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c @@ -145,6 +145,9 @@ static bool optc35_disable_crtc(struct timing_generator *optc) OPTC_SEG3_SRC_SEL, 0xf, OPTC_NUM_OF_INPUT_SEGMENT, 0); + REG_UPDATE(OPTC_MEMORY_CONFIG, + OPTC_MEM_SEL, 0); + /* disable otg request until end of the first line * in the vertical blank region */ -- 2.34.1
[PATCH 06/19] drm/amd/display: Floor to mhz when requesting dpp disp clock changes to SMU
From: Wenjing Liu [Why] SMU uses discrete dpp and disp clock levels. When we submit SMU request for clock changes in Mhz we need to floor the requested value from Khz so SMU will choose the next higher clock level in Khz to set. If we ceil to Mhz, SMU will have to choose the next higher clock level after the ceil, which could result in unnecessarily jumpping to the next level. For example, we request 1911,111Khz which is exactly one of the SMU preset level. If we pass 1912Mhz, SMU will choose 2150,000 khz. If we pass 1911Mhz, SMU will choose 1911,111kHz, which is the expected value. Reviewed-by: Alvin Lee Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- .../display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 40 +-- .../amd/display/dc/inc/hw/clk_mgr_internal.h | 5 +++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c index aadd07bc68c5..8fa0aae941c3 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c @@ -387,7 +387,15 @@ static void dcn32_update_clocks_update_dentist( uint32_t temp_dispclk_khz = (DENTIST_DIVIDER_RANGE_SCALE_FACTOR * clk_mgr->base.dentist_vco_freq_khz) / temp_disp_divider; if (clk_mgr->smu_present) - dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(temp_dispclk_khz)); + /* +* SMU uses discrete dispclk presets. We applied +* the same formula to increase our dppclk_khz +* to the next matching discrete value. By +* contract, we should use the preset dispclk +* floored in Mhz to describe the intended clock. +*/ + dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, + khz_to_mhz_floor(temp_dispclk_khz)); if (dc->debug.override_dispclk_programming) { REG_GET(DENTIST_DISPCLK_CNTL, @@ -426,7 +434,15 @@ static void dcn32_update_clocks_update_dentist( /* do requested DISPCLK updates*/ if (clk_mgr->smu_present) - dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, khz_to_mhz_ceil(clk_mgr->base.clks.dispclk_khz)); + /* +* SMU uses discrete dispclk presets. We applied +* the same formula to increase our dppclk_khz +* to the next matching discrete value. By +* contract, we should use the preset dispclk +* floored in Mhz to describe the intended clock. +*/ + dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DISPCLK, + khz_to_mhz_floor(clk_mgr->base.clks.dispclk_khz)); if (dc->debug.override_dispclk_programming) { REG_GET(DENTIST_DISPCLK_CNTL, @@ -734,7 +750,15 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, clk_mgr_base->clks.dppclk_khz = new_clocks->dppclk_khz; if (clk_mgr->smu_present && !dpp_clock_lowered) - dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz)); + /* +* SMU uses discrete dppclk presets. We applied +* the same formula to increase our dppclk_khz +* to the next matching discrete value. By +* contract, we should use the preset dppclk +* floored in Mhz to describe the intended clock. +*/ + dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, + khz_to_mhz_floor(clk_mgr_base->clks.dppclk_khz)); update_dppclk = true; } @@ -765,7 +789,15 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base, dcn32_update_clocks_update_dpp_dto(clk_mgr, context, safe_to_lower); dcn32_update_clocks_update_dentist(clk_mgr, context); if (clk_mgr->smu_present) - dcn32_smu_set_hard_min_by_freq(clk_mgr, PPCLK_DPPCLK, khz_to_mhz_ceil(clk_mgr_base->clks.dppclk_khz)); + /* +* SMU uses discrete dppclk presets. We applied +* the same formula to increase our dppclk_khz +* to the next matching discrete value. By +* contract, we should use the preset dppclk +
[PATCH 05/19] drm/amd/display: Port DENTIST hang and TDR fixes to OTG disable W/A
From: Nicholas Kazlauskas [Why] We can experience DENTIST hangs during optimize_bandwidth or TDRs if FIFO is toggled and hangs. [How] Port the DCN35 fixes to DCN314. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- .../dc/clk_mgr/dcn314/dcn314_clk_mgr.c| 21 --- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c index 878c0e7b78ab..a84f1e376dee 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_clk_mgr.c @@ -145,30 +145,27 @@ static int dcn314_get_active_display_cnt_wa( return display_count; } -static void dcn314_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, bool disable) +static void dcn314_disable_otg_wa(struct clk_mgr *clk_mgr_base, struct dc_state *context, + bool safe_to_lower, bool disable) { struct dc *dc = clk_mgr_base->ctx->dc; int i; for (i = 0; i < dc->res_pool->pipe_count; ++i) { - struct pipe_ctx *pipe = >current_state->res_ctx.pipe_ctx[i]; + struct pipe_ctx *pipe = safe_to_lower + ? >res_ctx.pipe_ctx[i] + : >current_state->res_ctx.pipe_ctx[i]; if (pipe->top_pipe || pipe->prev_odm_pipe) continue; if (pipe->stream && (pipe->stream->dpms_off || dc_is_virtual_signal(pipe->stream->signal))) { - struct stream_encoder *stream_enc = pipe->stream_res.stream_enc; - if (disable) { - if (stream_enc && stream_enc->funcs->disable_fifo) - pipe->stream_res.stream_enc->funcs->disable_fifo(stream_enc); + if (pipe->stream_res.tg && pipe->stream_res.tg->funcs->immediate_disable_crtc) + pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); - pipe->stream_res.tg->funcs->immediate_disable_crtc(pipe->stream_res.tg); reset_sync_context_for_pipe(dc, context, i); } else { pipe->stream_res.tg->funcs->enable_crtc(pipe->stream_res.tg); - - if (stream_enc && stream_enc->funcs->enable_fifo) - pipe->stream_res.stream_enc->funcs->enable_fifo(stream_enc); } } } @@ -297,11 +294,11 @@ void dcn314_update_clocks(struct clk_mgr *clk_mgr_base, } if (should_set_clock(safe_to_lower, new_clocks->dispclk_khz, clk_mgr_base->clks.dispclk_khz)) { - dcn314_disable_otg_wa(clk_mgr_base, context, true); + dcn314_disable_otg_wa(clk_mgr_base, context, safe_to_lower, true); clk_mgr_base->clks.dispclk_khz = new_clocks->dispclk_khz; dcn314_smu_set_dispclk(clk_mgr, clk_mgr_base->clks.dispclk_khz); - dcn314_disable_otg_wa(clk_mgr_base, context, false); + dcn314_disable_otg_wa(clk_mgr_base, context, safe_to_lower, false); update_dispclk = true; } -- 2.34.1
[PATCH 04/19] drm/amd/display: Add logging resource checks
From: Charlene Liu [Why] When mapping resources, resources could be unavailable. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Sung joon Kim Acked-by: Alex Hung Signed-off-by: Charlene Liu --- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 +++- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 4 drivers/gpu/drm/amd/display/dc/core/dc_state.c| 5 +++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 69e726630241..aa7c02ba948e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3522,7 +3522,7 @@ static void commit_planes_for_stream(struct dc *dc, top_pipe_to_program = resource_get_otg_master_for_stream( >res_ctx, stream); - + ASSERT(top_pipe_to_program != NULL); for (i = 0; i < dc->res_pool->pipe_count; i++) { struct pipe_ctx *old_pipe = >current_state->res_ctx.pipe_ctx[i]; @@ -4345,6 +4345,8 @@ static bool should_commit_minimal_transition_for_windowed_mpo_odm(struct dc *dc, cur_pipe = resource_get_otg_master_for_stream(>current_state->res_ctx, stream); new_pipe = resource_get_otg_master_for_stream(>res_ctx, stream); + if (!cur_pipe || !new_pipe) + return false; cur_is_odm_in_use = resource_get_odm_slice_count(cur_pipe) > 1; new_is_odm_in_use = resource_get_odm_slice_count(new_pipe) > 1; if (cur_is_odm_in_use == new_is_odm_in_use) 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 f2abc1096ffb..9fbdb09697fd 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2194,6 +2194,10 @@ void resource_log_pipe_topology_update(struct dc *dc, struct dc_state *state) for (stream_idx = 0; stream_idx < state->stream_count; stream_idx++) { otg_master = resource_get_otg_master_for_stream( >res_ctx, state->streams[stream_idx]); + if (!otg_master || otg_master->stream_res.tg == NULL) { + DC_LOG_DC("topology update: otg_master NULL stream_idx %d!\n", stream_idx); + return; + } slice_count = resource_get_opp_heads_for_otg_master(otg_master, >res_ctx, opp_heads); for (slice_idx = 0; slice_idx < slice_count; slice_idx++) { diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c index 56feee0ff01b..88c6436b28b6 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c @@ -434,8 +434,9 @@ bool dc_state_add_plane( otg_master_pipe = resource_get_otg_master_for_stream( >res_ctx, stream); - added = resource_append_dpp_pipes_for_plane_composition(state, - dc->current_state, pool, otg_master_pipe, plane_state); + if (otg_master_pipe) + added = resource_append_dpp_pipes_for_plane_composition(state, + dc->current_state, pool, otg_master_pipe, plane_state); if (added) { stream_status->plane_states[stream_status->plane_count] = -- 2.34.1
[PATCH 03/19] drm/amd/display: Add Replay IPS register for DMUB command table
From: Alvin Lee - Introduce a new Replay mode for DMUB version 0.0.199.0 Reviewed-by: Martin Leung Acked-by: Alex Hung Signed-off-by: Alvin Lee --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index c64b6c848ef7..bcd3c361cca5 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -2832,6 +2832,7 @@ struct dmub_rb_cmd_psr_set_power_opt { #define REPLAY_RESIDENCY_MODE_MASK (0x1 << REPLAY_RESIDENCY_MODE_SHIFT) # define REPLAY_RESIDENCY_MODE_PHY (0x0 << REPLAY_RESIDENCY_MODE_SHIFT) # define REPLAY_RESIDENCY_MODE_ALPM(0x1 << REPLAY_RESIDENCY_MODE_SHIFT) +# define REPLAY_RESIDENCY_MODE_IPS 0x10 #define REPLAY_RESIDENCY_ENABLE_MASK (0x1 << REPLAY_RESIDENCY_ENABLE_SHIFT) # define REPLAY_RESIDENCY_DISABLE (0x0 << REPLAY_RESIDENCY_ENABLE_SHIFT) -- 2.34.1
[PATCH 02/19] drm/amd/display: Init link enc resources in dc_state only if res_pool presents
From: Dillon Varone [Why & How] res_pool is not initialized in all situations such as virtual environments, and therefore link encoder resources should not be initialized if res_pool is NULL. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Martin Leung Acked-by: Alex Hung Signed-off-by: Dillon Varone --- drivers/gpu/drm/amd/display/dc/core/dc_state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_state.c b/drivers/gpu/drm/amd/display/dc/core/dc_state.c index 460a8010c79f..56feee0ff01b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_state.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_state.c @@ -267,7 +267,8 @@ void dc_state_construct(struct dc *dc, struct dc_state *state) state->clk_mgr = dc->clk_mgr; /* Initialise DIG link encoder resource tracking variables. */ - link_enc_cfg_init(dc, state); + if (dc->res_pool) + link_enc_cfg_init(dc, state); } void dc_state_destruct(struct dc_state *state) -- 2.34.1
[PATCH 01/19] drm/amd/display: Allow IPS2 during Replay
From: Nicholas Kazlauskas [Why & How] Add regkey to block video playback in IPS2 by default Allow idle optimizations in the same spot we allow Replay for video playback usecases. Avoid sending it when there's an external display connected by modifying the allow idle checks to check for active non-eDP screens. Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 9 - 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 111c6f51f0ae..95ff3800fc87 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -1716,6 +1716,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev) init_data.flags.disable_ips = DMUB_IPS_DISABLE_ALL; + init_data.flags.disable_ips_in_vpb = 1; + /* Enable DWB for tested platforms only */ if (amdgpu_ip_version(adev, DCE_HWIP, 0) >= IP_VERSION(3, 0, 0)) init_data.num_virtual_links = 1; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 5d7aa882416b..c9317ea0258e 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -434,6 +434,7 @@ struct dc_config { bool EnableMinDispClkODM; bool enable_auto_dpm_test_logs; unsigned int disable_ips; + unsigned int disable_ips_in_vpb; }; enum visual_confirm { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index 9c806385ecbd..8b6c49622f3b 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -680,7 +680,7 @@ void dcn35_power_down_on_boot(struct dc *dc) bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable) { struct dc_link *edp_links[MAX_NUM_EDP]; - int edp_num; + int i, edp_num; if (dc->debug.dmcub_emulation) return true; @@ -688,6 +688,13 @@ bool dcn35_apply_idle_power_optimizations(struct dc *dc, bool enable) dc_get_edp_links(dc, edp_links, _num); if (edp_num == 0 || edp_num > 1) return false; + + for (i = 0; i < dc->current_state->stream_count; ++i) { + struct dc_stream_state *stream = dc->current_state->streams[i]; + + if (!stream->dpms_off && !dc_is_embedded_signal(stream->signal)) + return false; + } } // TODO: review other cases when idle optimization is allowed -- 2.34.1
[PATCH 00/19] DC Patches January 10, 2024
This DC patchset brings improvements in multiple areas. In summary, we highlight: * Fixes on DCN35 and DML2. * Enhancements in DMUB. * Improvements on IPS, DP and MPO and others. Cc: Daniel Wheeler Alvin Lee (2): drm/amd/display: Add Replay IPS register for DMUB command table drm/amd/display: Ensure populate uclk in bb construction Charlene Liu (2): drm/amd/display: Add logging resource checks drm/amd/display: Update P010 scaling cap Dillon Varone (1): drm/amd/display: Init link enc resources in dc_state only if res_pool presents Dmytro Laktyushkin (1): drm/amd/display: Fix dml2 assigned pipe search George Shen (1): drm/amd/display: Add DP audio BW validation Ilya Bakoulin (1): drm/amd/display: Clear OPTC mem select on disable Martin Leung (1): drm/amd/display: 3.2.267 Nicholas Kazlauskas (5): drm/amd/display: Allow IPS2 during Replay drm/amd/display: Port DENTIST hang and TDR fixes to OTG disable W/A drm/amd/display: Rework DC Z10 restore drm/amd/display: Set default Z8 minimum residency for DCN35 drm/amd/display: Allow Z8 for multiplane configurations on DCN35 Ovidiu Bunea (1): drm/amd/display: Fix DML2 watermark calculation Tom Chung (1): drm/amd/display: Enable Panel Replay for static screen use case Wayne Lin (1): drm/amd/display: Align the returned error code with legacy DP Wenjing Liu (2): drm/amd/display: Floor to mhz when requesting dpp disp clock changes to SMU drm/amd/display: Reenable windowed mpo odm support .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 44 ++- .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c| 59 +++- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 5 + .../amd/display/amdgpu_dm/amdgpu_dm_replay.c | 119 +--- .../amd/display/amdgpu_dm/amdgpu_dm_replay.h | 4 +- .../dc/clk_mgr/dcn314/dcn314_clk_mgr.c| 21 +- .../display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c | 40 ++- .../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 25 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 15 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 4 + .../gpu/drm/amd/display/dc/core/dc_state.c| 8 +- .../gpu/drm/amd/display/dc/core/dc_stream.c | 9 +- drivers/gpu/drm/amd/display/dc/dc.h | 3 +- .../gpu/drm/amd/display/dc/dce/dce_audio.c| 288 +- .../gpu/drm/amd/display/dc/dce/dce_audio.h| 3 +- .../dc/dml/dcn30/display_mode_vba_30.c| 16 +- .../amd/display/dc/dml/dcn303/dcn303_fpu.c| 11 + .../drm/amd/display/dc/dml/dcn35/dcn35_fpu.c | 4 +- .../amd/display/dc/dml2/display_mode_core.c | 14 +- .../display/dc/dml2/dml2_dc_resource_mgmt.c | 36 ++- .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 56 +++- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 11 +- drivers/gpu/drm/amd/display/dc/inc/hw/audio.h | 3 +- .../amd/display/dc/inc/hw/clk_mgr_internal.h | 5 + .../amd/display/dc/optc/dcn32/dcn32_optc.c| 3 + .../amd/display/dc/optc/dcn35/dcn35_optc.c| 3 + .../dc/resource/dcn30/dcn30_resource.c| 11 + .../dc/resource/dcn32/dcn32_resource.c| 1 + .../dc/resource/dcn321/dcn321_resource.c | 1 + .../dc/resource/dcn35/dcn35_resource.c| 3 +- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 1 + .../gpu/drm/amd/display/include/audio_types.h | 15 + 32 files changed, 689 insertions(+), 152 deletions(-) -- 2.34.1
Re: [PATCH] drm/amd/display: Fix memory leak in dm_set_writeback()
Thanks for catching this. Reviewed-by: Alex Hung On 2023-12-08 02:58, Harshit Mogalapalli wrote: 'wb_info' needs to be freed on error paths or it would leak the memory. Smatch pointed this out. Fixes: c81e13b929df ("drm/amd/display: Hande writeback request from userspace") Signed-off-by: Harshit Mogalapalli --- This is based on static analysis and only compile tested --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index afdcc43ea06c..333995f70239 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8871,12 +8871,14 @@ static void dm_set_writeback(struct amdgpu_display_manager *dm, acrtc = to_amdgpu_crtc(wb_conn->encoder.crtc); if (!acrtc) { DRM_ERROR("no amdgpu_crtc found\n"); + kfree(wb_info); return; } afb = to_amdgpu_framebuffer(new_con_state->writeback_job->fb); if (!afb) { DRM_ERROR("No amdgpu_framebuffer found\n"); + kfree(wb_info); return; }
[PATCH 20/20] drm/amd/display: Promote DC to 3.2.260
From: Aric Cyr - Add missing chips for HDCP - Add new command to disable replay timing resync - Fix encoder disable logic - Enable DSC Flag in MST Mode Validation - Change the DMCUB mailbox memory location from FB to inbox - Add disable timeout option - Negate IPS allow and commit bits - Enable DCN clock gating for DCN35 - Prefer currently used OTG master when acquiring free pipe - Try to acquire a free OTG master not used in cur ctx first - Clear dpcd_sink_ext_caps if not set - Enable fast plane updates on DCN3.2 and above - Add null checks for 8K60 lightup - Refactor resource into component directory - Fix DSC not Enabled on Direct MST Sink - Guard against invalid RPTR/WPTR being set - Enable CM low mem power optimization - Fix a debugfs null pointer error Acked-by: Alex Hung Signed-off-by: Aric Cyr --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 18ab453bfdb1..e6f109bbf468 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -49,7 +49,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.259" +#define DC_VER "3.2.260" #define MAX_SURFACES 3 #define MAX_PLANES 6 -- 2.42.0
[PATCH 19/20] drm/amd/display: Add missing chips for HDCP
From: Rodrigo Siqueira [WHAT] Add missing HDCP ID in the message id enum. Acked-by: Alex Hung Signed-off-by: Rodrigo Siqueira --- drivers/gpu/drm/amd/display/include/hdcp_msg_types.h | 5 + 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h b/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h index 42229b4effdc..eced9ad91f1d 100644 --- a/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h +++ b/drivers/gpu/drm/amd/display/include/hdcp_msg_types.h @@ -69,6 +69,11 @@ enum hdcp_message_id { HDCP_MESSAGE_ID_READ_RXSTATUS, HDCP_MESSAGE_ID_WRITE_CONTENT_STREAM_TYPE, + /* PS175 chip */ + + HDCP_MESSAGE_ID_WRITE_PS175_CMD, + HDCP_MESSAGE_ID_READ_PS175_RSP, + HDCP_MESSAGE_ID_MAX }; -- 2.42.0
[PATCH 18/20] drm/amd/display: Add new command to disable replay timing resync
From: Anthony Koo [WHY & HOW] Add new command to disable replay timing resync Acked-by: Alex Hung Signed-off-by: Anthony Koo --- .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 41 +++ 1 file changed, 41 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index ed4379c04715..97faa9cfb6f7 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -2840,6 +2840,10 @@ enum dmub_cmd_replay_type { * Set power opt and coasting vtotal. */ DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL = 4, + /** +* Set disabled iiming sync. +*/ + DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED = 5, }; /** @@ -3002,6 +3006,27 @@ struct dmub_cmd_replay_set_power_opt_data { uint32_t power_opt; }; +/** + * Data passed from driver to FW in a DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED command. + */ +struct dmub_cmd_replay_set_timing_sync_data { + /** +* Panel Instance. +* Panel isntance to identify which replay_state to use +* Currently the support is only for 0 or 1 +*/ + uint8_t panel_inst; + + /** +* Explicit padding to 4 byte boundary. +*/ + uint8_t pad[3]; + /** +* REPLAY set_timing_sync +*/ + bool timing_sync_supported; +}; + /** * Definition of a DMUB_CMD__SET_REPLAY_POWER_OPT command. */ @@ -3068,6 +3093,20 @@ struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal { struct dmub_cmd_replay_set_coasting_vtotal_data replay_set_coasting_vtotal_data; }; +/** + * Definition of a DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED command. + */ +struct dmub_rb_cmd_replay_set_timing_sync { + /** +* Command header. +*/ + struct dmub_cmd_header header; + /** +* Definition of DMUB_CMD__REPLAY_SET_TIMING_SYNC_SUPPORTED command. +*/ + struct dmub_cmd_replay_set_timing_sync_data replay_set_timing_sync_data; +}; + /** * Set of HW components that can be locked. * @@ -4201,6 +4240,8 @@ union dmub_rb_cmd { * Definition of a DMUB_CMD__REPLAY_SET_POWER_OPT_AND_COASTING_VTOTAL command. */ struct dmub_rb_cmd_replay_set_power_opt_and_coasting_vtotal replay_set_power_opt_and_coasting_vtotal; + + struct dmub_rb_cmd_replay_set_timing_sync replay_set_timing_sync; }; /** -- 2.42.0
[PATCH 17/20] drm/amd/display: Send PQ bit in AMD VSIF
From: Krunoslav Kovac [WHY & HOW] PB9 bit 5 was added to signal PQ EOTF in AMD vendor specific infoframe. This change sets it when appropriate. Reviewed-by: Aric Cyr Acked-by: Alex Hung Signed-off-by: Krunoslav Kovac --- drivers/gpu/drm/amd/display/modules/freesync/freesync.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c index ccecddafeb05..47296d155c3a 100644 --- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c +++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c @@ -693,10 +693,12 @@ static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf, if (app_tf != TRANSFER_FUNC_UNKNOWN) { infopacket->valid = true; - if (app_tf != TRANSFER_FUNC_PQ2084) { + if (app_tf == TRANSFER_FUNC_PQ2084) + infopacket->sb[9] |= 0x20; // PB9 = [Bit 5 = PQ EOTF Active] + else { infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active] if (app_tf == TRANSFER_FUNC_GAMMA_22) - infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active] + infopacket->sb[9] |= 0x04; // PB9 = [Bit 2 = Gamma 2.2 EOTF Active] } } } -- 2.42.0
[PATCH 16/20] drm/amd/display: Fix encoder disable logic
From: Nicholas Susanto [WHY] DENTIST hangs when OTG is off and encoder is on. We were not disabling the encoder properly when switching from extended mode to external monitor only. [HOW] Disable the encoder using an existing enable/disable fifo helper instead of enc35_stream_encoder_enable. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Nicholas Kazlauskas Acked-by: Alex Hung Signed-off-by: Nicholas Susanto --- .../amd/display/dc/dcn35/dcn35_dio_stream_encoder.c| 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c index 001f9eb66920..62a8f0b56006 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dio_stream_encoder.c @@ -261,12 +261,6 @@ static void enc35_stream_encoder_enable( /* invalid mode ! */ ASSERT_CRITICAL(false); } - - REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 1); - REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 1); - } else { - REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 0); - REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 0); } } @@ -436,6 +430,8 @@ static void enc35_disable_fifo(struct stream_encoder *enc) struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, 0); + REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 0); + REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 0); } static void enc35_enable_fifo(struct stream_encoder *enc) @@ -443,6 +439,8 @@ static void enc35_enable_fifo(struct stream_encoder *enc) struct dcn10_stream_encoder *enc1 = DCN10STRENC_FROM_STRENC(enc); REG_UPDATE(DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, 0x7); + REG_UPDATE(DIG_FE_CLK_CNTL, DIG_FE_CLK_EN, 1); + REG_UPDATE(DIG_FE_EN_CNTL, DIG_FE_ENABLE, 1); enc35_reset_fifo(enc, true); enc35_reset_fifo(enc, false); -- 2.42.0
[PATCH 15/20] drm/amd/display: Enable DSC Flag in MST Mode Validation
From: Fangzhi Zuo [WHY & HOW] When dsc is possible, MST mode validation includes: 1. if maximum dsc compression cannot fit into end to end bw, mode pruned 2. if native bw cannot fit into end to end bw, try to enabled dsc to see whether a feasible dsc config can be found 3. if native bw can fit into end to end bw, mode supported Reviewed-by: Wayne Lin Acked-by: Alex Hung Signed-off-by: Fangzhi Zuo --- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 44 +++ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index ec87e31c6fe8..8d7d4024f285 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -1602,9 +1602,8 @@ enum dc_status dm_dp_mst_is_port_support_mode( struct dc_link_settings cur_link_settings; unsigned int end_to_end_bw_in_kbps = 0; unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0; - unsigned int max_compressed_bw_in_kbps = 0; struct dc_dsc_bw_range bw_range = {0}; - uint16_t full_pbn = aconnector->mst_output_port->full_pbn; + struct dc_dsc_config_options dsc_options = {0}; /* * Consider the case with the depth of the mst topology tree is equal or less than 2 @@ -1620,30 +1619,39 @@ enum dc_status dm_dp_mst_is_port_support_mode( (aconnector->mst_output_port->passthrough_aux || aconnector->dsc_aux == >mst_output_port->aux)) { cur_link_settings = stream->link->verified_link_cap; + upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, _link_settings); + down_link_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn); - upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, - _link_settings); - down_link_bw_in_kbps = kbps_from_pbn(full_pbn); - - /* pick the bottleneck */ - end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps, - down_link_bw_in_kbps); - - /* -* use the maximum dsc compression bandwidth as the required -* bandwidth for the mode -*/ - max_compressed_bw_in_kbps = bw_range.min_kbps; + /* pick the end to end bw bottleneck */ + end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps, down_link_bw_in_kbps); - if (end_to_end_bw_in_kbps < max_compressed_bw_in_kbps) { - DRM_DEBUG_DRIVER("Mode does not fit into DSC pass-through bandwidth validation\n"); + if (end_to_end_bw_in_kbps < bw_range.min_kbps) { + DRM_DEBUG_DRIVER("maximum dsc compression cannot fit into end-to-end bandwidth\n"); return DC_FAIL_BANDWIDTH_VALIDATE; } + + if (end_to_end_bw_in_kbps < bw_range.stream_kbps) { + dc_dsc_get_default_config_option(stream->link->dc, _options); + dsc_options.max_target_bpp_limit_override_x16 = aconnector->base.display_info.max_dsc_bpp * 16; + if (dc_dsc_compute_config(stream->sink->ctx->dc->res_pool->dscs[0], + >sink->dsc_caps.dsc_dec_caps, + _options, + end_to_end_bw_in_kbps, + >timing, + dc_link_get_highest_encoding_format(stream->link), + >timing.dsc_cfg)) { + stream->timing.flags.DSC = 1; + DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc and dsc config found\n"); + } else { + DRM_DEBUG_DRIVER("end-to-end bandwidth require dsc but dsc config not found\n"); + return DC_FAIL_BANDWIDTH_VALIDATE; + } + } } else { /* check if mode could be supported within full_pbn */ bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3; pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false); - if (pbn > full_pbn) + if (pbn > aconnector->mst_output_port->full_pbn) return DC_FAIL_BANDWIDTH_VALIDATE; } -- 2.42.0
[PATCH 14/20] drm/amd/display: Change the DMCUB mailbox memory location from FB to inbox
From: Lewis Huang [WHY] Flush command sent to DMCUB spends more time for execution on a dGPU than on an APU. This causes cursor lag when using high refresh rate mouses. [HOW] 1. Change the DMCUB mailbox memory location from FB to inbox. 2. Only change windows memory to inbox. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Nicholas Kazlauskas Acked-by: Alex Hung Signed-off-by: Lewis Huang --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 13 drivers/gpu/drm/amd/display/dmub/dmub_srv.h | 22 - .../gpu/drm/amd/display/dmub/src/dmub_srv.c | 32 ++- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8ebdbfbbb691..6199440a9da8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2078,7 +2078,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) struct dmub_srv_create_params create_params; struct dmub_srv_region_params region_params; struct dmub_srv_region_info region_info; - struct dmub_srv_fb_params fb_params; + struct dmub_srv_memory_params memory_params; struct dmub_srv_fb_info *fb_info; struct dmub_srv *dmub_srv; const struct dmcub_firmware_header_v1_0 *hdr; @@ -2181,6 +2181,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) adev->dm.dmub_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes) + PSP_HEADER_BYTES; + region_params.is_mailbox_in_inbox = false; status = dmub_srv_calc_region_info(dmub_srv, _params, _info); @@ -2204,10 +2205,10 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) return r; /* Rebase the regions on the framebuffer address. */ - memset(_params, 0, sizeof(fb_params)); - fb_params.cpu_addr = adev->dm.dmub_bo_cpu_addr; - fb_params.gpu_addr = adev->dm.dmub_bo_gpu_addr; - fb_params.region_info = _info; + memset(_params, 0, sizeof(memory_params)); + memory_params.cpu_fb_addr = adev->dm.dmub_bo_cpu_addr; + memory_params.gpu_fb_addr = adev->dm.dmub_bo_gpu_addr; + memory_params.region_info = _info; adev->dm.dmub_fb_info = kzalloc(sizeof(*adev->dm.dmub_fb_info), GFP_KERNEL); @@ -2219,7 +2220,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev) return -ENOMEM; } - status = dmub_srv_calc_fb_info(dmub_srv, _params, fb_info); + status = dmub_srv_calc_mem_info(dmub_srv, _params, fb_info); if (status != DMUB_STATUS_OK) { DRM_ERROR("Error calculating DMUB FB info: %d\n", status); return -EINVAL; diff --git a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h index 9665ada0f894..df63aa8f01e9 100644 --- a/drivers/gpu/drm/amd/display/dmub/dmub_srv.h +++ b/drivers/gpu/drm/amd/display/dmub/dmub_srv.h @@ -195,6 +195,7 @@ struct dmub_srv_region_params { uint32_t vbios_size; const uint8_t *fw_inst_const; const uint8_t *fw_bss_data; + bool is_mailbox_in_inbox; }; /** @@ -214,20 +215,25 @@ struct dmub_srv_region_params { */ struct dmub_srv_region_info { uint32_t fb_size; + uint32_t inbox_size; uint8_t num_regions; struct dmub_region regions[DMUB_WINDOW_TOTAL]; }; /** - * struct dmub_srv_fb_params - parameters used for driver fb setup + * struct dmub_srv_memory_params - parameters used for driver fb setup * @region_info: region info calculated by dmub service - * @cpu_addr: base cpu address for the framebuffer - * @gpu_addr: base gpu virtual address for the framebuffer + * @cpu_fb_addr: base cpu address for the framebuffer + * @cpu_inbox_addr: base cpu address for the gart + * @gpu_fb_addr: base gpu virtual address for the framebuffer + * @gpu_inbox_addr: base gpu virtual address for the gart */ -struct dmub_srv_fb_params { +struct dmub_srv_memory_params { const struct dmub_srv_region_info *region_info; - void *cpu_addr; - uint64_t gpu_addr; + void *cpu_fb_addr; + void *cpu_inbox_addr; + uint64_t gpu_fb_addr; + uint64_t gpu_inbox_addr; }; /** @@ -563,8 +569,8 @@ dmub_srv_calc_region_info(struct dmub_srv *dmub, * DMUB_STATUS_OK - success * DMUB_STATUS_INVALID - unspecified error */ -enum dmub_status dmub_srv_calc_fb_info(struct dmub_srv *dmub, - const struct dmub_srv_fb_params *params, +enum dmub_status dmub_srv_calc_mem_info(struct dmub_srv *dmub, + const struct dmub_srv_memory_params *params, struct dmub_srv_fb_info *out); /** diff --git a
[PATCH 13/20] drm/amd/display: Add disable timeout option
From: Duncan Ma [WHY] Driver continues running whenever there is is timeout from smu or dmcub. It is difficult to track failure state when dcn, dc or dmcub changes on root failure. [HOW] Add disable_timeout option to halt driver whenever there is a failure in response. Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Duncan Ma --- .../amd/display/dc/clk_mgr/dcn35/dcn35_smu.c | 3 ++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 29 +++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c index b6b8c3ca1572..af0a0f292595 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_smu.c @@ -116,6 +116,9 @@ static uint32_t dcn35_smu_wait_for_response(struct clk_mgr_internal *clk_mgr, un msleep(delay_us/1000); else if (delay_us > 0) udelay(delay_us); + + if (clk_mgr->base.ctx->dc->debug.disable_timeout) + max_retries++; } while (max_retries--); return res_val; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index c5e7da302acb..18ab453bfdb1 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -978,6 +978,7 @@ struct dc_debug_options { bool psp_disabled_wa; unsigned int ips2_eval_delay_us; unsigned int ips2_entry_delay_us; + bool disable_timeout; }; struct gpu_info_soc_bounding_box_v1_0; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index 0e07699c1e83..53400cc05b5b 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -241,7 +241,12 @@ bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int coun // Wait for DMUB to process command if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) { - status = dmub_srv_wait_for_idle(dmub, 10); + if (dc_dmub_srv->ctx->dc->debug.disable_timeout) { + do { + status = dmub_srv_wait_for_idle(dmub, 10); + } while (status != DMUB_STATUS_OK); + } else + status = dmub_srv_wait_for_idle(dmub, 10); if (status != DMUB_STATUS_OK) { DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status); @@ -1147,10 +1152,16 @@ bool dc_dmub_srv_is_hw_pwr_up(struct dc_dmub_srv *dc_dmub_srv, bool wait) return true; if (wait) { - status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 50); - if (status != DMUB_STATUS_OK) { - DC_ERROR("Error querying DMUB hw power up status: error=%d\n", status); - return false; + if (dc_dmub_srv->ctx->dc->debug.disable_timeout) { + do { + status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 50); + } while (status != DMUB_STATUS_OK); + } else { + status = dmub_srv_wait_for_hw_pwr_up(dc_dmub_srv->dmub, 50); + if (status != DMUB_STATUS_OK) { + DC_ERROR("Error querying DMUB hw power up status: error=%d\n", status); + return false; + } } } else return dmub_srv_is_hw_pwr_up(dc_dmub_srv->dmub); @@ -1187,7 +1198,7 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) const uint32_t max_num_polls = 1; uint32_t allow_state = 0; uint32_t commit_state = 0; - uint32_t i; + int i; if (dc->debug.dmcub_emulation) return; @@ -1220,6 +1231,9 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) break; udelay(1); + + if (dc->debug.disable_timeout) + i--; } ASSERT(i < max_num_polls); @@ -1242,6 +1256,9 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) break; udelay(1); + + if (dc->debug.disable_timeout) + i--; } ASSERT(i < max_num_polls); } -- 2.42.0
[PATCH 12/20] drm/amd/display: Negate IPS allow and commit bits
From: Duncan Ma [WHY] On s0i3, IPS mask isn't saved and restored. It is reset to zero on exit. If it is cleared unexpectedly, driver will proceed operations while DCN is in IPS2 and cause a hang. [HOW] Negate the bit logic. Default value of zero indicates it is still in IPS2. Driver must poll for the bit to assert. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Duncan Ma --- .../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 18 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 4 ++-- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 10 +- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c index 0fa4fcd00de2..507a7cf56711 100644 --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c @@ -820,22 +820,22 @@ static void dcn35_set_idle_state(struct clk_mgr *clk_mgr_base, bool allow_idle) if (dc->config.disable_ips == DMUB_IPS_ENABLE || dc->config.disable_ips == DMUB_IPS_DISABLE_DYNAMIC) { - val |= DMUB_IPS1_ALLOW_MASK; - val |= DMUB_IPS2_ALLOW_MASK; - } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS1) { val = val & ~DMUB_IPS1_ALLOW_MASK; val = val & ~DMUB_IPS2_ALLOW_MASK; - } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2) { - val |= DMUB_IPS1_ALLOW_MASK; - val = val & ~DMUB_IPS2_ALLOW_MASK; - } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2_Z10) { + } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS1) { val |= DMUB_IPS1_ALLOW_MASK; val |= DMUB_IPS2_ALLOW_MASK; + } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2) { + val = val & ~DMUB_IPS1_ALLOW_MASK; + val |= DMUB_IPS2_ALLOW_MASK; + } else if (dc->config.disable_ips == DMUB_IPS_DISABLE_IPS2_Z10) { + val = val & ~DMUB_IPS1_ALLOW_MASK; + val = val & ~DMUB_IPS2_ALLOW_MASK; } if (!allow_idle) { - val = val & ~DMUB_IPS1_ALLOW_MASK; - val = val & ~DMUB_IPS2_ALLOW_MASK; + val |= DMUB_IPS1_ALLOW_MASK; + val |= DMUB_IPS2_ALLOW_MASK; } dcn35_smu_write_ips_scratch(clk_mgr, val); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index d8f434738212..76b47f178127 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -4934,8 +4934,8 @@ bool dc_dmub_is_ips_idle_state(struct dc *dc) if (dc->hwss.get_idle_state) idle_state = dc->hwss.get_idle_state(dc); - if ((idle_state & DMUB_IPS1_ALLOW_MASK) || - (idle_state & DMUB_IPS2_ALLOW_MASK)) + if (!(idle_state & DMUB_IPS1_ALLOW_MASK) || + !(idle_state & DMUB_IPS2_ALLOW_MASK)) return true; return false; diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c index e4c007203318..0e07699c1e83 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c @@ -1202,11 +1202,11 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) allow_state = dc->hwss.get_idle_state(dc); dc->hwss.set_idle_state(dc, false); - if (allow_state & DMUB_IPS2_ALLOW_MASK) { + if (!(allow_state & DMUB_IPS2_ALLOW_MASK)) { // Wait for evaluation time udelay(dc->debug.ips2_eval_delay_us); commit_state = dc->hwss.get_idle_state(dc); - if (commit_state & DMUB_IPS2_COMMIT_MASK) { + if (!(commit_state & DMUB_IPS2_COMMIT_MASK)) { // Tell PMFW to exit low power state dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr); @@ -1216,7 +1216,7 @@ void dc_dmub_srv_exit_low_power_state(const struct dc *dc) for (i = 0; i < max_num_polls; ++i) { commit_state = dc->hwss.get_idle_state(dc); - if (!(commit_state & DMUB_IPS2_COMMIT_MASK)) + if (commit_state & DMUB_IPS2_COMMIT_MASK) break; udelay(1); @@ -1235,10 +1235,10 @@ void dc_dmub_srv_exit_low_power_state(const struct dc
[PATCH 10/20] drm/amd/display: Prefer currently used OTG master when acquiring free pipe
From: Wenjing Liu [WHY & HOW] When acquiring an OTG master pipe we should prefer currently enabled OTG master pipes first. If there are no free pipes used as current OTG master pipe then we will try to acquire a currently unused free pipe as new OTG master instead of tearing down current secondary pipes from ODM or MPC combine. Reviewed-by: Alvin Lee Reviewed-by: Dillon Varone Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- .../gpu/drm/amd/display/dc/core/dc_resource.c | 37 ++- drivers/gpu/drm/amd/display/dc/inc/resource.h | 12 ++ 2 files changed, 48 insertions(+), 1 deletion(-) 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 49f8c90f0d2b..42a927710743 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -1764,6 +1764,29 @@ int recource_find_free_pipe_not_used_in_cur_res_ctx( return free_pipe_idx; } +int recource_find_free_pipe_used_as_otg_master_in_cur_res_ctx( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool) +{ + int free_pipe_idx = FREE_PIPE_INDEX_NOT_FOUND; + const struct pipe_ctx *new_pipe, *cur_pipe; + int i; + + for (i = 0; i < pool->pipe_count; i++) { + cur_pipe = _res_ctx->pipe_ctx[i]; + new_pipe = _res_ctx->pipe_ctx[i]; + + if (resource_is_pipe_type(cur_pipe, OTG_MASTER) && + resource_is_pipe_type(new_pipe, FREE_PIPE)) { + free_pipe_idx = i; + break; + } + } + + return free_pipe_idx; +} + int resource_find_free_pipe_used_as_cur_sec_dpp_in_mpcc_combine( const struct resource_context *cur_res_ctx, struct resource_context *new_res_ctx, @@ -3600,8 +3623,20 @@ static bool acquire_otg_master_pipe_for_stream( int pipe_idx; struct pipe_ctx *pipe_ctx = NULL; - pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( + /* +* Upper level code is responsible to optimize unnecessary addition and +* removal for unchanged streams. So unchanged stream will keep the same +* OTG master instance allocated. When current stream is removed and a +* new stream is added, we want to reuse the OTG instance made available +* by the removed stream first. If not found, we try to avoid of using +* any free pipes already used in current context as this could tear +* down exiting ODM/MPC/MPO configuration unnecessarily. +*/ + pipe_idx = recource_find_free_pipe_used_as_otg_master_in_cur_res_ctx( _ctx->res_ctx, _ctx->res_ctx, pool); + if (pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( + _ctx->res_ctx, _ctx->res_ctx, pool); if (pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) pipe_idx = resource_find_any_free_pipe(_ctx->res_ctx, pool); if (pipe_idx != FREE_PIPE_INDEX_NOT_FOUND) { diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h index 06ca8bfb91e7..0458d2d749f4 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/resource.h +++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h @@ -500,6 +500,18 @@ int recource_find_free_pipe_not_used_in_cur_res_ctx( struct resource_context *new_res_ctx, const struct resource_pool *pool); +/* + * Look for a free pipe in new resource context that is used in current resource + * context as an OTG master pipe. + * + * return - FREE_PIPE_INDEX_NOT_FOUND if free pipe is not found, otherwise + * pipe idx of the free pipe + */ +int recource_find_free_pipe_used_as_otg_master_in_cur_res_ctx( + const struct resource_context *cur_res_ctx, + struct resource_context *new_res_ctx, + const struct resource_pool *pool); + /* * Look for a free pipe in new resource context that is used as a secondary DPP * pipe in any MPCC combine in current resource context. -- 2.42.0
[PATCH 11/20] drm/amd/display: Enable DCN clock gating for DCN35
From: Daniel Miess [WHY & HOW] Enable DCN clock gating for DCN35. Disable DTBCLK gate before link training and re-enable afterwards Reviewed-by: Nicholas Kazlauskas Acked-by: Alex Hung Signed-off-by: Daniel Miess --- .../gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h | 6 ++- .../gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c | 30 + .../gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h | 7 +++- .../drm/amd/display/dc/dcn35/dcn35_pg_cntl.c | 10 + .../drm/amd/display/dc/dcn35/dcn35_pg_cntl.h | 1 - .../drm/amd/display/dc/hwss/dce/dce_hwseq.h | 15 ++- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 42 +-- .../gpu/drm/amd/display/dc/inc/hw/pg_cntl.h | 2 - .../dc/resource/dcn35/dcn35_resource.c| 16 ++- .../dc/resource/dcn35/dcn35_resource.h| 1 + .../include/asic_reg/dcn/dcn_3_5_0_sh_mask.h | 8 11 files changed, 108 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h index ab6d09c6fe34..76da59d8caaf 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h @@ -291,7 +291,11 @@ type SYMCLKB_FE_SRC_SEL;\ type SYMCLKC_FE_SRC_SEL;\ type SYMCLKD_FE_SRC_SEL;\ - type SYMCLKE_FE_SRC_SEL; + type SYMCLKE_FE_SRC_SEL;\ + type DTBCLK_P0_GATE_DISABLE;\ + type DTBCLK_P1_GATE_DISABLE;\ + type DTBCLK_P2_GATE_DISABLE;\ + type DTBCLK_P3_GATE_DISABLE;\ struct dccg_shift { DCCG_REG_FIELD_LIST(uint8_t) diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c index 479f3683c0b7..142efd390d86 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c @@ -256,6 +256,21 @@ static void dccg35_set_dtbclk_dto( if (params->ref_dtbclk_khz && req_dtbclk_khz) { uint32_t modulo, phase; + switch (params->otg_inst) { + case 0: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 1); + break; + case 1: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 1); + break; + case 2: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 1); + break; + case 3: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 1); + break; + } + // phase / modulo = dtbclk / dtbclk ref modulo = params->ref_dtbclk_khz * 1000; phase = req_dtbclk_khz * 1000; @@ -280,6 +295,21 @@ static void dccg35_set_dtbclk_dto( REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst], PIPE_DTO_SRC_SEL[params->otg_inst], 2); } else { + switch (params->otg_inst) { + case 0: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, 0); + break; + case 1: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, 0); + break; + case 2: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P2_GATE_DISABLE, 0); + break; + case 3: + REG_UPDATE(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P3_GATE_DISABLE, 0); + break; + } + REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst], DTBCLK_DTO_ENABLE[params->otg_inst], 0, PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1); diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h index 423feb4c2f3f..bde48bee0119 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h @@ -34,6 +34,7 @@ #define DCCG_REG_LIST_DCN35() \ DCCG_REG_LIST_DCN314(),\ SR(DPPCLK_CTRL),\ + SR(DCCG_GATE_DISABLE_CNTL5),\ SR(DCCG_GATE_DISABLE_CNTL6),\ SR(DCCG_GLOBAL_FGCG_REP_CNTL),\ SR(SYMCLKA_CLOCK_ENABLE),\ @@ -174,7 +175,11 @@ DCCG_SF(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, mask_sh),\ DCCG_SF(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, mask_sh),\ DCCG_SF(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, mask_sh),\ - DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh) + DCCG_SF(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P0_GATE_DISABLE, mask_sh),\ + DCCG_SF(DCCG_GATE_DISABLE_CNTL5, DTBCLK_P1_GATE_DISABLE, mask_sh)
[PATCH 09/20] drm/amd/display: Try to acquire a free OTG master not used in cur ctx first
From: Wenjing Liu [WHY & HOW] The current otg master pipe allocation logic is not optimized based current resource context. We should try to acquire a free OTG master not used in cur cts first to avoid unnecessary pipe switch from current state. Acked-by: Alex Hung Signed-off-by: Wenjing Liu --- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 8 ++-- 1 file changed, 6 insertions(+), 2 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 6159d819c5c5..49f8c90f0d2b 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -3586,6 +3586,7 @@ static void mark_seamless_boot_stream( * ||___|___|_| */ static bool acquire_otg_master_pipe_for_stream( + const struct dc_state *cur_ctx, struct dc_state *new_ctx, const struct resource_pool *pool, struct dc_stream_state *stream) @@ -3599,7 +3600,10 @@ static bool acquire_otg_master_pipe_for_stream( int pipe_idx; struct pipe_ctx *pipe_ctx = NULL; - pipe_idx = resource_find_any_free_pipe(_ctx->res_ctx, pool); + pipe_idx = recource_find_free_pipe_not_used_in_cur_res_ctx( + _ctx->res_ctx, _ctx->res_ctx, pool); + if (pipe_idx == FREE_PIPE_INDEX_NOT_FOUND) + pipe_idx = resource_find_any_free_pipe(_ctx->res_ctx, pool); if (pipe_idx != FREE_PIPE_INDEX_NOT_FOUND) { pipe_ctx = _ctx->res_ctx.pipe_ctx[pipe_idx]; memset(pipe_ctx, 0, sizeof(*pipe_ctx)); @@ -3659,7 +3663,7 @@ enum dc_status resource_map_pool_resources( if (!acquired) /* acquire new resources */ - acquired = acquire_otg_master_pipe_for_stream( + acquired = acquire_otg_master_pipe_for_stream(dc->current_state, context, pool, stream); pipe_ctx = resource_get_otg_master_for_stream(>res_ctx, stream); -- 2.42.0
[PATCH 08/20] drm/amd/display: Clear dpcd_sink_ext_caps if not set
From: Paul Hsieh [WHY] Some eDP panels' ext caps don't set initial values and the value of dpcd_addr (0x317) is random. It means that sometimes the eDP can be OLED, miniLED and etc, and cause incorrect backlight control interface. [HOW] Add remove_sink_ext_caps to remove sink ext caps (HDR, OLED and etc) Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Anthony Koo Acked-by: Alex Hung Signed-off-by: Paul Hsieh --- drivers/gpu/drm/amd/display/dc/dc_types.h| 1 + drivers/gpu/drm/amd/display/dc/link/link_detection.c | 3 +++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h index cea666ea66c6..fcb825e4f1bb 100644 --- a/drivers/gpu/drm/amd/display/dc/dc_types.h +++ b/drivers/gpu/drm/amd/display/dc/dc_types.h @@ -177,6 +177,7 @@ struct dc_panel_patch { unsigned int disable_fams; unsigned int skip_avmute; unsigned int mst_start_top_delay; + unsigned int remove_sink_ext_caps; }; struct dc_edid_caps { diff --git a/drivers/gpu/drm/amd/display/dc/link/link_detection.c b/drivers/gpu/drm/amd/display/dc/link/link_detection.c index d6f0f857c05a..f2fe523f914f 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_detection.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_detection.c @@ -1088,6 +1088,9 @@ static bool detect_link_and_local_sink(struct dc_link *link, if (sink->edid_caps.panel_patch.skip_scdc_overwrite) link->ctx->dc->debug.hdmi20_disable = true; + if (sink->edid_caps.panel_patch.remove_sink_ext_caps) + link->dpcd_sink_ext_caps.raw = 0; + if (dc_is_hdmi_signal(link->connector_signal)) read_scdc_caps(link->ddc, link->local_sink); -- 2.42.0
[PATCH 07/20] drm/amd/display: Enable fast plane updates on DCN3.2 and above
From: Tianci Yin [WHY] When cursor moves across screen boarder, lag cursor observed, since subvp settings need to sync up with vblank that causes cursor updates being delayed. [HOW] Enable fast plane updates on DCN3.2 to fix it. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Aurabindo Pillai Acked-by: Alex Hung Signed-off-by: Tianci Yin --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index adbeb2c897b5..8ebdbfbbb691 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -9585,14 +9585,14 @@ static bool should_reset_plane(struct drm_atomic_state *state, struct drm_plane *other; struct drm_plane_state *old_other_state, *new_other_state; struct drm_crtc_state *new_crtc_state; + struct amdgpu_device *adev = drm_to_adev(plane->dev); int i; /* -* TODO: Remove this hack once the checks below are sufficient -* enough to determine when we need to reset all the planes on -* the stream. +* TODO: Remove this hack for all asics once it proves that the +* fast updates works fine on DCN3.2+. */ - if (state->allow_modeset) + if (adev->ip_versions[DCE_HWIP][0] < IP_VERSION(3, 2, 0) && state->allow_modeset) return true; /* Exit early if we know that we're adding or removing the plane. */ -- 2.42.0
[PATCH 06/20] drm/amd/display: Add null checks for 8K60 lightup
From: Muhammad Ahmed [WHY & HOW] Add some null checks to fix an issue where 8k60 tiled display fails to light up. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Charlene Liu Acked-by: Alex Hung Signed-off-by: Muhammad Ahmed --- drivers/gpu/drm/amd/display/dc/core/dc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc_resource.c | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 7b9bf5cb4529..d8f434738212 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -3178,7 +3178,7 @@ static bool update_planes_and_stream_state(struct dc *dc, struct pipe_ctx *otg_master = resource_get_otg_master_for_stream(>res_ctx, context->streams[i]); - if (otg_master->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) + if (otg_master && otg_master->stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) resource_build_test_pattern_params(>res_ctx, otg_master); } } 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 06fc4c5a3b69..6159d819c5c5 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -5190,6 +5190,9 @@ bool dc_resource_acquire_secondary_pipe_for_mpc_odm_legacy( sec_next = sec_pipe->next_odm_pipe; sec_prev = sec_pipe->prev_odm_pipe; + if (pri_pipe == NULL) + return false; + *sec_pipe = *pri_pipe; sec_pipe->top_pipe = sec_top; -- 2.42.0
[PATCH 05/20] drm/amd/display: Refactor resource into component directory
From: Mounika Adhuri [WHY] Move all resource files to unique folder resource. [HOW] Created resource folder in dc, moved the dcnxx_resource.c and dcnxx_resource.h files into corresponding new folders inside the resource and made appropriate changes for compilation in Makefiles. Reviewed-by: Martin Leung Acked-by: Alex Hung Signed-off-by: Mounika Adhuri --- drivers/gpu/drm/amd/display/Makefile | 1 + .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 2 +- drivers/gpu/drm/amd/display/dc/Makefile | 5 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 4 +- .../gpu/drm/amd/display/dc/dce100/Makefile| 46 .../gpu/drm/amd/display/dc/dce110/Makefile| 4 +- .../gpu/drm/amd/display/dc/dce112/Makefile| 3 +- .../gpu/drm/amd/display/dc/dce120/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 3 +- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn201/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/dcn21/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn30/Makefile | 1 - .../gpu/drm/amd/display/dc/dcn301/Makefile| 2 +- .../gpu/drm/amd/display/dc/dcn302/Makefile| 2 +- .../gpu/drm/amd/display/dc/dcn303/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn314/Makefile| 2 +- .../gpu/drm/amd/display/dc/dcn315/Makefile| 30 --- .../gpu/drm/amd/display/dc/dcn316/Makefile| 30 --- drivers/gpu/drm/amd/display/dc/dcn32/Makefile | 2 +- .../display/dc/dcn32/dcn32_resource_helpers.c | 2 +- .../gpu/drm/amd/display/dc/dcn321/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/dcn35/Makefile | 2 +- .../drm/amd/display/dc/dml/calcs/dcn_calcs.c | 2 +- .../gpu/drm/amd/display/dc/resource/Makefile | 199 ++ .../{ => resource}/dce100/dce100_resource.c | 0 .../{ => resource}/dce100/dce100_resource.h | 0 .../{ => resource}/dce110/dce110_resource.c | 0 .../{ => resource}/dce110/dce110_resource.h | 0 .../{ => resource}/dce112/dce112_resource.c | 0 .../{ => resource}/dce112/dce112_resource.h | 0 .../{ => resource}/dce120/dce120_resource.c | 2 +- .../{ => resource}/dce120/dce120_resource.h | 0 .../display/dc/resource/dce80/CMakeLists.txt | 4 + .../dc/{ => resource}/dce80/dce80_resource.c | 0 .../dc/{ => resource}/dce80/dce80_resource.h | 0 .../dc/{ => resource}/dcn10/dcn10_resource.c | 25 ++- .../dc/{ => resource}/dcn10/dcn10_resource.h | 0 .../dc/{ => resource}/dcn20/dcn20_resource.c | 24 +-- .../dc/{ => resource}/dcn20/dcn20_resource.h | 0 .../{ => resource}/dcn201/dcn201_resource.c | 14 +- .../{ => resource}/dcn201/dcn201_resource.h | 0 .../dc/{ => resource}/dcn21/dcn21_resource.c | 6 +- .../dc/{ => resource}/dcn21/dcn21_resource.h | 0 .../dc/{ => resource}/dcn30/dcn30_resource.c | 2 +- .../dc/{ => resource}/dcn30/dcn30_resource.h | 0 .../{ => resource}/dcn301/dcn301_resource.c | 4 +- .../{ => resource}/dcn301/dcn301_resource.h | 0 .../{ => resource}/dcn302/dcn302_resource.c | 4 +- .../{ => resource}/dcn302/dcn302_resource.h | 0 .../{ => resource}/dcn303/dcn303_resource.c | 4 +- .../{ => resource}/dcn303/dcn303_resource.h | 0 .../dc/{ => resource}/dcn31/dcn31_resource.c | 2 +- .../dc/{ => resource}/dcn31/dcn31_resource.h | 0 .../{ => resource}/dcn314/dcn314_resource.c | 0 .../{ => resource}/dcn314/dcn314_resource.h | 0 .../{ => resource}/dcn315/dcn315_resource.c | 0 .../{ => resource}/dcn315/dcn315_resource.h | 0 .../{ => resource}/dcn316/dcn316_resource.c | 0 .../{ => resource}/dcn316/dcn316_resource.h | 0 .../dc/{ => resource}/dcn32/dcn32_resource.c | 4 +- .../dc/{ => resource}/dcn32/dcn32_resource.h | 0 .../{ => resource}/dcn321/dcn321_resource.c | 2 +- .../{ => resource}/dcn321/dcn321_resource.h | 0 .../dc/{ => resource}/dcn35/dcn35_resource.c | 2 +- .../dc/{ => resource}/dcn35/dcn35_resource.h | 0 68 files changed, 276 insertions(+), 181 deletions(-) delete mode 100644 drivers/gpu/drm/amd/display/dc/dce100/Makefile delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn315/Makefile delete mode 100644 drivers/gpu/drm/amd/display/dc/dcn316/Makefile create mode 100644 drivers/gpu/drm/amd/display/dc/resource/Makefile rename drivers/gpu/drm/amd/display/dc/{ => resource}/dce100/dce100_resource.c (100%) rename drivers/gpu/drm/amd/display/dc/{ => resource}/dce100/dce100_resource.h (100%) rename drivers/gpu/drm/amd/display/dc/{ => resource}/dce110/dce110_resource.c (100%) rename drivers/gpu/drm/amd/display/dc/{ => resource}/dce110/dce110_resource.h (100%) rename drivers/gpu/drm/amd/display/dc/{ => resource}/dce112/dce112_resource.
[PATCH 04/20] drm/amd/display: Fix DSC not Enabled on Direct MST Sink
From: Fangzhi Zuo [WHY & HOW] For the scenario when a dsc capable MST sink device is directly connected, it needs to use max dsc compression as the link bw constraint. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Roman Li Acked-by: Alex Hung Signed-off-by: Fangzhi Zuo --- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 29 +-- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index d3b13d362eda..11da0eebee6c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -1604,31 +1604,31 @@ enum dc_status dm_dp_mst_is_port_support_mode( unsigned int upper_link_bw_in_kbps = 0, down_link_bw_in_kbps = 0; unsigned int max_compressed_bw_in_kbps = 0; struct dc_dsc_bw_range bw_range = {0}; - struct drm_dp_mst_topology_mgr *mst_mgr; + uint16_t full_pbn = aconnector->mst_output_port->full_pbn; /* -* check if the mode could be supported if DSC pass-through is supported -* AND check if there enough bandwidth available to support the mode -* with DSC enabled. +* Consider the case with the depth of the mst topology tree is equal or less than 2 +* A. When dsc bitstream can be transmitted along the entire path +*1. dsc is possible between source and branch/leaf device (common dsc params is possible), AND +*2. dsc passthrough supported at MST branch, or +*3. dsc decoding supported at leaf MST device +*Use maximum dsc compression as bw constraint +* B. When dsc bitstream cannot be transmitted along the entire path +*Use native bw as bw constraint */ if (is_dsc_common_config_possible(stream, _range) && - aconnector->mst_output_port->passthrough_aux) { - mst_mgr = aconnector->mst_output_port->mgr; - mutex_lock(_mgr->lock); - + (aconnector->mst_output_port->passthrough_aux || + aconnector->dsc_aux == >mst_output_port->aux)) { cur_link_settings = stream->link->verified_link_cap; upper_link_bw_in_kbps = dc_link_bandwidth_kbps(aconnector->dc_link, - _link_settings - ); - down_link_bw_in_kbps = kbps_from_pbn(aconnector->mst_output_port->full_pbn); + _link_settings); + down_link_bw_in_kbps = kbps_from_pbn(full_pbn); /* pick the bottleneck */ end_to_end_bw_in_kbps = min(upper_link_bw_in_kbps, down_link_bw_in_kbps); - mutex_unlock(_mgr->lock); - /* * use the maximum dsc compression bandwidth as the required * bandwidth for the mode @@ -1643,8 +1643,7 @@ enum dc_status dm_dp_mst_is_port_support_mode( /* check if mode could be supported within full_pbn */ bpp = convert_dc_color_depth_into_bpc(stream->timing.display_color_depth) * 3; pbn = drm_dp_calc_pbn_mode(stream->timing.pix_clk_100hz / 10, bpp, false); - - if (pbn > aconnector->mst_output_port->full_pbn) + if (pbn > full_pbn) return DC_FAIL_BANDWIDTH_VALIDATE; } -- 2.42.0
[PATCH 03/20] drm/amd/display: Guard against invalid RPTR/WPTR being set
From: Nicholas Kazlauskas [WHY] HW can return invalid values on register read, guard against these being set and causing us to access memory out of range and page fault. [HOW] Guard at sync_inbox1 and guard at pushing commands. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Hansen Dsouza Acked-by: Alex Hung Signed-off-by: Nicholas Kazlauskas --- .../gpu/drm/amd/display/dmub/src/dmub_srv.c| 18 +++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c index e43e8d4bfe37..5d36f3e5dc2b 100644 --- a/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c +++ b/drivers/gpu/drm/amd/display/dmub/src/dmub_srv.c @@ -707,9 +707,16 @@ enum dmub_status dmub_srv_sync_inbox1(struct dmub_srv *dmub) return DMUB_STATUS_INVALID; if (dmub->hw_funcs.get_inbox1_rptr && dmub->hw_funcs.get_inbox1_wptr) { - dmub->inbox1_rb.rptr = dmub->hw_funcs.get_inbox1_rptr(dmub); - dmub->inbox1_rb.wrpt = dmub->hw_funcs.get_inbox1_wptr(dmub); - dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt; + uint32_t rptr = dmub->hw_funcs.get_inbox1_rptr(dmub); + uint32_t wptr = dmub->hw_funcs.get_inbox1_wptr(dmub); + + if (rptr > dmub->inbox1_rb.capacity || wptr > dmub->inbox1_rb.capacity) { + return DMUB_STATUS_HW_FAILURE; + } else { + dmub->inbox1_rb.rptr = rptr; + dmub->inbox1_rb.wrpt = wptr; + dmub->inbox1_last_wptr = dmub->inbox1_rb.wrpt; + } } return DMUB_STATUS_OK; @@ -743,6 +750,11 @@ enum dmub_status dmub_srv_cmd_queue(struct dmub_srv *dmub, if (!dmub->hw_init) return DMUB_STATUS_INVALID; + if (dmub->inbox1_rb.rptr > dmub->inbox1_rb.capacity || + dmub->inbox1_rb.wrpt > dmub->inbox1_rb.capacity) { + return DMUB_STATUS_HW_FAILURE; + } + if (dmub_rb_push_front(>inbox1_rb, cmd)) return DMUB_STATUS_OK; -- 2.42.0
[PATCH 02/20] drm/amd/display: Enable CM low mem power optimization
From: Yihan Zhu [WHY & HOW] MPC MCM low mem power optimization still causes color distortion on first SCE enablement, only forces light sleep for it. DPP low memory power optimization still needs this bit to save power. Reviewed-by: Nicholas Kazlauskas Acked-by: Alex Hung Signed-off-by: Yihan Zhu --- drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c| 13 - .../gpu/drm/amd/display/dc/dcn35/dcn35_resource.c | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c index 994b21ed272f..1a2adb354718 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c @@ -71,21 +71,24 @@ void mpc32_power_on_blnd_lut( { struct dcn30_mpc *mpc30 = TO_DCN30_MPC(mpc); +/* if (mpc->ctx->dc->debug.enable_mem_low_power.bits.cm) { if (power_on) { REG_UPDATE(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_FORCE, 0); REG_WAIT(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], MPCC_MCM_1DLUT_MEM_PWR_STATE, 0, 1, 5); } else if (!mpc->ctx->dc->debug.disable_mem_low_power) { - ASSERT(false); - /* TODO: change to mpc -* dpp_base->ctx->dc->optimized_required = true; -* dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true; -*/ + //TODO: change to mpc + dpp_base->ctx->dc->optimized_required = true; + dpp_base->deferred_reg_writes.bits.disable_blnd_lut = true; } } else { REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0, MPCC_MCM_1DLUT_MEM_PWR_FORCE, power_on == true ? 0 : 1); } +*/ + + REG_SET(MPCC_MCM_MEM_PWR_CTRL[mpcc_id], 0, + MPCC_MCM_1DLUT_MEM_PWR_FORCE, power_on == true ? 0 : 1); } static enum dc_lut_mode mpc32_get_post1dlut_current(struct mpc *mpc, uint32_t mpcc_id) diff --git a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c index c7e011d26d41..7a3faf2b1f06 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn35/dcn35_resource.c @@ -724,7 +724,7 @@ static const struct dc_debug_options debug_defaults_drv = { .i2c = true, .dmcu = false, // This is previously known to cause hang on S3 cycles if enabled .dscl = true, - .cm = false, + .cm = true, .mpc = true, .optc = true, .vpg = true, -- 2.42.0
[PATCH 01/20] drm/amd/display: Fix a debugfs null pointer error
From: Aurabindo Pillai [WHY & HOW] Check whether get_subvp_en() callback exists before calling it. Cc: Mario Limonciello Cc: Alex Deucher Cc: sta...@vger.kernel.org Reviewed-by: Alex Hung Acked-by: Alex Hung Signed-off-by: Aurabindo Pillai --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c index 13a177d34376..45c972f2630d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c @@ -3647,12 +3647,16 @@ static int capabilities_show(struct seq_file *m, void *unused) bool mall_supported = dc->caps.mall_size_total; bool subvp_supported = dc->caps.subvp_fw_processing_delay_us; unsigned int mall_in_use = false; - unsigned int subvp_in_use = dc->cap_funcs.get_subvp_en(dc, dc->current_state); + unsigned int subvp_in_use = false; + struct hubbub *hubbub = dc->res_pool->hubbub; if (hubbub->funcs->get_mall_en) hubbub->funcs->get_mall_en(hubbub, _in_use); + if (dc->cap_funcs.get_subvp_en) + subvp_in_use = dc->cap_funcs.get_subvp_en(dc, dc->current_state); + seq_printf(m, "mall supported: %s, enabled: %s\n", mall_supported ? "yes" : "no", mall_in_use ? "yes" : "no"); seq_printf(m, "sub-viewport supported: %s, enabled: %s\n", -- 2.42.0
[PATCH 00/20] DC Patches Nov 08, 2023
This DC patchset brings improvements in multiple areas. In summary, we highlight: * Add missing chips for HDCP * Add new command to disable replay timing resync * Fix encoder disable logic * Enable DSC Flag in MST Mode Validation * Change the DMCUB mailbox memory location from FB to inbox * Add disable timeout option * Negate IPS allow and commit bits * Enable DCN clock gating for DCN35 * Prefer currently used OTG master when acquiring free pipe * Try to acquire a free OTG master not used in cur ctx first * Clear dpcd_sink_ext_caps if not set * Enable fast plane updates on DCN3.2 and above * Add null checks for 8K60 lightup * Refactor resource into component directory * Fix DSC not Enabled on Direct MST Sink * Guard against invalid RPTR/WPTR being set * Enable CM low mem power optimization * Fix a debugfs null pointer error Cc: Daniel Wheeler Anthony Koo (1): drm/amd/display: Add new command to disable replay timing resync Aric Cyr (1): drm/amd/display: Promote DC to 3.2.260 Aurabindo Pillai (1): drm/amd/display: Fix a debugfs null pointer error Daniel Miess (1): drm/amd/display: Enable DCN clock gating for DCN35 Duncan Ma (2): drm/amd/display: Negate IPS allow and commit bits drm/amd/display: Add disable timeout option Fangzhi Zuo (2): drm/amd/display: Fix DSC not Enabled on Direct MST Sink drm/amd/display: Enable DSC Flag in MST Mode Validation Krunoslav Kovac (1): drm/amd/display: Send PQ bit in AMD VSIF Lewis Huang (1): drm/amd/display: Change the DMCUB mailbox memory location from FB to inbox Mounika Adhuri (1): drm/amd/display: Refactor resource into component directory Muhammad Ahmed (1): drm/amd/display: Add null checks for 8K60 lightup Nicholas Kazlauskas (1): drm/amd/display: Guard against invalid RPTR/WPTR being set Nicholas Susanto (1): drm/amd/display: Fix encoder disable logic Paul Hsieh (1): drm/amd/display: Clear dpcd_sink_ext_caps if not set Rodrigo Siqueira (1): drm/amd/display: Add missing chips for HDCP Tianci Yin (1): drm/amd/display: Enable fast plane updates on DCN3.2 and above Wenjing Liu (2): drm/amd/display: Try to acquire a free OTG master not used in cur ctx first drm/amd/display: Prefer currently used OTG master when acquiring free pipe Yihan Zhu (1): drm/amd/display: Enable CM low mem power optimization drivers/gpu/drm/amd/display/Makefile | 1 + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 21 +- .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 6 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 63 +++--- drivers/gpu/drm/amd/display/dc/Makefile | 5 +- .../display/dc/clk_mgr/dcn35/dcn35_clk_mgr.c | 18 +- .../amd/display/dc/clk_mgr/dcn35/dcn35_smu.c | 3 + drivers/gpu/drm/amd/display/dc/core/dc.c | 6 +- .../gpu/drm/amd/display/dc/core/dc_resource.c | 50 - drivers/gpu/drm/amd/display/dc/dc.h | 3 +- drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 39 +++- drivers/gpu/drm/amd/display/dc/dc_types.h | 1 + .../gpu/drm/amd/display/dc/dce100/Makefile| 46 .../gpu/drm/amd/display/dc/dce110/Makefile| 4 +- .../gpu/drm/amd/display/dc/dce112/Makefile| 3 +- .../gpu/drm/amd/display/dc/dce120/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/dce80/Makefile | 3 +- drivers/gpu/drm/amd/display/dc/dcn10/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn20/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn20/dcn20_dccg.h | 6 +- .../gpu/drm/amd/display/dc/dcn201/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/dcn21/Makefile | 2 +- drivers/gpu/drm/amd/display/dc/dcn30/Makefile | 1 - .../gpu/drm/amd/display/dc/dcn301/Makefile| 2 +- .../gpu/drm/amd/display/dc/dcn302/Makefile| 2 +- .../gpu/drm/amd/display/dc/dcn303/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn314/Makefile| 2 +- .../gpu/drm/amd/display/dc/dcn315/Makefile| 30 --- .../gpu/drm/amd/display/dc/dcn316/Makefile| 30 --- drivers/gpu/drm/amd/display/dc/dcn32/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c | 13 +- .../display/dc/dcn32/dcn32_resource_helpers.c | 2 +- .../gpu/drm/amd/display/dc/dcn321/Makefile| 2 +- drivers/gpu/drm/amd/display/dc/dcn35/Makefile | 2 +- .../gpu/drm/amd/display/dc/dcn35/dcn35_dccg.c | 30 +++ .../gpu/drm/amd/display/dc/dcn35/dcn35_dccg.h | 7 +- .../dc/dcn35/dcn35_dio_stream_encoder.c | 10 +- .../drm/amd/display/dc/dcn35/dcn35_pg_cntl.c | 10 +- .../drm/amd/display/dc/dcn35/dcn35_pg_cntl.h | 1 - .../drm/amd/display/dc/dml/calcs/dcn_calcs.c | 2 +- .../drm/amd/display/dc/hwss/dce/dce_hwseq.h | 15 +- .../amd/display/dc/hwss/dcn35/dcn35_hwseq.c | 42 ++-- .../gpu/drm/amd/display/dc/inc/hw/pg_cntl.h | 2 - drivers/gpu/drm/amd/display/dc/inc/resource.h | 12 ++ .../drm/amd/display/dc/link/link_detection.c | 3 + .../gpu/drm/amd/display/dc/resource/Makefile | 199