From: Bhawanpreet Lakha <bhawanpreet.la...@amd.com>

Enable Memory Access at Last Level (MALL) feature for display.

Signed-off-by: Bhawanpreet Lakha <bhawanpreet.la...@amd.com>
Signed-off-by: Alex Deucher <alexander.deuc...@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) {
+                               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@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to