[PATCH 3/3] drm/amdgpu/display: add MALL support
Bas Nieuwenhuizen
bas at basnieuwenhuizen.nl
Mon Oct 26 15:51:06 UTC 2020
On Tue, Oct 20, 2020 at 10:26 PM Alex Deucher <alexdeucher at gmail.com> wrote:
>
> From: Bhawanpreet Lakha <Bhawanpreet.Lakha at amd.com>
>
> Enable Memory Access at Last Level (MALL) feature for display.
>
> Signed-off-by: Bhawanpreet Lakha <Bhawanpreet.Lakha at amd.com>
> Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
> ---
> .../drm/amd/display/dc/clk_mgr/dcn30/dalsmc.h | 1 +
> .../display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c | 10 +++
> .../dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c | 9 +++
> .../dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h | 2 +
> .../drm/amd/display/dc/dcn30/dcn30_hwseq.c | 65 +++++++++++++++++++
> .../drm/amd/display/dc/dcn30/dcn30_resource.c | 2 +-
> .../gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 20 ++++++
> 7 files changed, 108 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dalsmc.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dalsmc.h
> index 5ed03287aaaf..fa09c594fd36 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dalsmc.h
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dalsmc.h
> @@ -53,6 +53,7 @@
> #define DALSMC_MSG_GetDcModeMaxDpmFreq 0xC
> #define DALSMC_MSG_SetMinDeepSleepDcefclk 0xD
> #define DALSMC_MSG_NumOfDisplays 0xE
> +#define DALSMC_MSG_SetDisplayRefreshFromMall 0xF
> #define DALSMC_MSG_SetExternalClientDfCstateAllow 0x10
> #define DALSMC_MSG_BacoAudioD3PME 0x11
> #define DALSMC_Message_Count 0x12
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
> index b0e9b0509568..7bad73b2d146 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr.c
> @@ -145,6 +145,16 @@ static void dcn3_build_wm_range_table(struct clk_mgr_internal *clk_mgr)
> clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz;
> clk_mgr->base.bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF;
>
> + /* Set D - MALL - SR enter and exit times adjusted for MALL */
> +// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].valid = true;
> +// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = pstate_latency_us;
> +// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = 2;
> +// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = 4;
> +// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL;
> +// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = 0;
> +// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF;
> +// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz;
> +// clk_mgr->base.bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF;
> }
>
> void dcn3_init_clocks(struct clk_mgr *clk_mgr_base)
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c
> index 7ee3ec5a8af8..8ecc708bcd9e 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.c
> @@ -297,6 +297,15 @@ void dcn30_smu_set_num_of_displays(struct clk_mgr_internal *clk_mgr, uint32_t nu
> DALSMC_MSG_NumOfDisplays, num_displays, NULL);
> }
>
> +void dcn30_smu_set_display_refresh_from_mall(struct clk_mgr_internal *clk_mgr, bool enable, uint8_t cache_timer_delay, uint8_t cache_timer_scale)
> +{
> + /* bits 8:7 for cache timer scale, bits 6:1 for cache timer delay, bit 0 = 1 for enable, = 0 for disable */
> + uint32_t param = (cache_timer_scale << 7) | (cache_timer_delay << 1) | (enable ? 1 : 0);
> +
> + dcn30_smu_send_msg_with_param(clk_mgr,
> + DALSMC_MSG_SetDisplayRefreshFromMall, param, NULL);
> +}
> +
> void dcn30_smu_set_external_client_df_cstate_allow(struct clk_mgr_internal *clk_mgr, bool enable)
> {
> smu_print("SMU Set external client df cstate allow: enable = %d\n", enable);
> diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h
> index 236f20ec90d4..dd2640a3ce5d 100644
> --- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h
> +++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_clk_mgr_smu_msg.h
> @@ -70,6 +70,7 @@ typedef enum {
> typedef enum {
> WATERMARKS_CLOCK_RANGE = 0,
> WATERMARKS_DUMMY_PSTATE,
> + WATERMARKS_MALL,
> WATERMARKS_COUNT,
> } WATERMARKS_FLAGS_e;
>
> @@ -102,6 +103,7 @@ unsigned int dcn30_smu_get_dpm_freq_by_index(struct clk_mgr_internal *clk_mgr, P
> unsigned int dcn30_smu_get_dc_mode_max_dpm_freq(struct clk_mgr_internal *clk_mgr, PPCLK_e clk);
> void dcn30_smu_set_min_deep_sleep_dcef_clk(struct clk_mgr_internal *clk_mgr, uint32_t freq_mhz);
> void dcn30_smu_set_num_of_displays(struct clk_mgr_internal *clk_mgr, uint32_t num_displays);
> +void dcn30_smu_set_display_refresh_from_mall(struct clk_mgr_internal *clk_mgr, bool enable, uint8_t cache_timer_delay, uint8_t cache_timer_scale);
> void dcn30_smu_set_external_client_df_cstate_allow(struct clk_mgr_internal *clk_mgr, bool enable);
> void dcn30_smu_set_pme_workaround(struct clk_mgr_internal *clk_mgr);
>
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
> index 8eb8e13e1130..a06f6d19e38e 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c
> @@ -696,6 +696,10 @@ void dcn30_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
>
> bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
> {
> + union dmub_rb_cmd cmd;
> + unsigned int surface_size, refresh_hz, denom;
> + uint32_t tmr_delay = 0, tmr_scale = 0;
> +
> if (!dc->ctx->dmub_srv)
> return false;
>
> @@ -710,12 +714,73 @@ bool dcn30_apply_idle_power_optimizations(struct dc *dc, bool enable)
> /* Fail eligibility on a visible stream */
> break;
> }
> +
> + // TODO: remove hard code size
> + if (surface_size < 128 * 1024 * 1024) {
I think surface_size is uninitialized here?
> + refresh_hz = (unsigned long long) dc->current_state->streams[0]->timing.pix_clk_100hz * 100LL /
> + (dc->current_state->streams[0]->timing.v_total * dc->current_state->streams[0]->timing.h_total);
> +
> + /*
> + * Delay_Us = 65.28 * (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
> + * Delay_Us / 65.28 = (64 + MallFrameCacheTmrDly) * 2^MallFrameCacheTmrScale
> + * (Delay_Us / 65.28) / 2^MallFrameCacheTmrScale = 64 + MallFrameCacheTmrDly
> + * MallFrameCacheTmrDly = ((Delay_Us / 65.28) / 2^MallFrameCacheTmrScale) - 64
> + * = (1000000 / refresh) / 65.28 / 2^MallFrameCacheTmrScale - 64
> + * = 1000000 / (refresh * 65.28 * 2^MallFrameCacheTmrScale) - 64
> + * = (1000000 * 100) / (refresh * 6528 * 2^MallFrameCacheTmrScale) - 64
> + *
> + * need to round up the result of the division before the subtraction
> + */
> + denom = refresh_hz * 6528;
> + tmr_delay = (100000000LL + denom - 1) / denom - 64LL;
> +
> + /* scale should be increased until it fits into 6 bits */
> + while (tmr_delay & ~0x3F) {
> + tmr_scale++;
> +
> + if (tmr_scale > 3) {
> + /* The delay exceeds the range of the hystersis timer */
> + ASSERT(false);
> + return false;
> + }
> +
> + denom *= 2;
> + tmr_delay = (100000000LL + denom - 1) / denom - 64LL;
> + }
> +
> + /* Enable MALL */
> + memset(&cmd, 0, sizeof(cmd));
> + cmd.mall.header.type = DMUB_CMD__MALL;
> + cmd.mall.header.sub_type =
> + DMUB_CMD__MALL_ACTION_ALLOW;
> + cmd.mall.header.payload_bytes =
> + sizeof(cmd.mall) -
> + sizeof(cmd.mall.header);
> + cmd.mall.tmr_delay = tmr_delay;
> + cmd.mall.tmr_scale = tmr_scale;
> +
> + dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
> + dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
> +
> + return true;
> + }
> }
>
> /* No applicable optimizations */
> return false;
> }
>
> + /* Disable MALL */
> + memset(&cmd, 0, sizeof(cmd));
> + cmd.mall.header.type = DMUB_CMD__MALL;
> + cmd.mall.header.sub_type = DMUB_CMD__MALL_ACTION_DISALLOW;
> + cmd.mall.header.payload_bytes =
> + sizeof(cmd.mall) - sizeof(cmd.mall.header);
> +
> + dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
> + dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
> + dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
> +
> return true;
> }
>
> diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
> index 783a1d7ae7d3..b132bb7f6704 100644
> --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
> +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
> @@ -2247,7 +2247,7 @@ void dcn30_calculate_wm_and_dlg(
> /* Set D:
> * DCFCLK: Min Required
> * FCLK(proportional to UCLK): 1GHz or Max
> - * sr_enter_exit = 4, sr_exit = 2us
> + * MALL stutter, sr_enter_exit = 4, sr_exit = 2us
> */
> /*
> if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].valid) {
> 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 26a4c6caf606..6e5be1fdb4bb 100644
> --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
> +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
> @@ -298,6 +298,7 @@ enum dmub_cmd_type {
> DMUB_CMD__REG_REG_WAIT = 4,
> DMUB_CMD__PLAT_54186_WA = 5,
> DMUB_CMD__PSR = 64,
> + DMUB_CMD__MALL = 65,
> DMUB_CMD__ABM = 66,
> DMUB_CMD__HW_LOCK = 69,
> DMUB_CMD__DP_AUX_ACCESS = 70,
> @@ -425,6 +426,18 @@ struct dmub_rb_cmd_PLAT_54186_wa {
> struct dmub_cmd_PLAT_54186_wa flip;
> };
>
> +struct dmub_rb_cmd_mall {
> + struct dmub_cmd_header header;
> + union dmub_addr cursor_copy_src;
> + union dmub_addr cursor_copy_dst;
> + uint32_t tmr_delay;
> + uint32_t tmr_scale;
> + uint16_t cursor_width;
> + uint16_t cursor_pitch;
> + uint16_t cursor_height;
> + uint8_t cursor_bpp;
> +};
> +
> struct dmub_cmd_digx_encoder_control_data {
> union dig_encoder_control_parameters_v1_5 dig;
> };
> @@ -556,6 +569,12 @@ enum psr_version {
> PSR_VERSION_UNSUPPORTED = 0xFFFFFFFF,
> };
>
> +enum dmub_cmd_mall_type {
> + DMUB_CMD__MALL_ACTION_ALLOW = 0,
> + DMUB_CMD__MALL_ACTION_DISALLOW = 1,
> + DMUB_CMD__MALL_ACTION_COPY_CURSOR = 2,
> +};
> +
> struct dmub_cmd_psr_copy_settings_data {
> union dmub_psr_debug_flags debug;
> uint16_t psr_level;
> @@ -761,6 +780,7 @@ union dmub_rb_cmd {
> struct dmub_rb_cmd_psr_enable psr_enable;
> struct dmub_rb_cmd_psr_set_level psr_set_level;
> struct dmub_rb_cmd_PLAT_54186_wa PLAT_54186_wa;
> + struct dmub_rb_cmd_mall mall;
> struct dmub_rb_cmd_abm_set_pipe abm_set_pipe;
> struct dmub_rb_cmd_abm_set_backlight abm_set_backlight;
> struct dmub_rb_cmd_abm_set_level abm_set_level;
> --
> 2.25.4
>
> _______________________________________________
> amd-gfx mailing list
> amd-gfx at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/amd-gfx
More information about the amd-gfx
mailing list