From: Eric Yang <eric.ya...@amd.com>

[Why]
SMU does not keep the wm table across S3, S4, need to re-send
the table. Also defer sending the cable to after DCN bave initialized

[How]
Send table at end of init hw

Signed-off-by: Eric Yang <eric.ya...@amd.com>
Reviewed-by: Yongqiang Sun <yongqiang....@amd.com>
Acked-by: Leo Li <sunpeng...@amd.com>
---
 .../amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c | 149 +++++++++---------
 .../amd/display/dc/dcn10/dcn10_hw_sequencer.c |   4 +
 .../gpu/drm/amd/display/dc/inc/hw/clk_mgr.h   |   1 +
 3 files changed, 81 insertions(+), 73 deletions(-)

diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c 
b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
index e8b8ee4f1b1e..f64d221ad6f1 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
@@ -396,12 +396,87 @@ void rn_init_clocks(struct clk_mgr *clk_mgr)
        clk_mgr->clks.pwr_state = DCN_PWR_STATE_UNKNOWN;
 }
 
+void build_watermark_ranges(struct clk_bw_params *bw_params, struct 
pp_smu_wm_range_sets *ranges)
+{
+       int i, num_valid_sets;
+
+       num_valid_sets = 0;
+
+       for (i = 0; i < WM_SET_COUNT; i++) {
+               /* skip empty entries, the smu array has no holes*/
+               if (!bw_params->wm_table.entries[i].valid)
+                       continue;
+
+               ranges->reader_wm_sets[num_valid_sets].wm_inst = 
bw_params->wm_table.entries[i].wm_inst;
+               ranges->reader_wm_sets[num_valid_sets].wm_type = 
bw_params->wm_table.entries[i].wm_type;;
+               /* We will not select WM based on dcfclk, so leave it as 
unconstrained */
+               ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
+               ranges->reader_wm_sets[num_valid_sets].max_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
+               /* fclk wil be used to select WM*/
+
+               if (ranges->reader_wm_sets[num_valid_sets].wm_type == 
WM_TYPE_PSTATE_CHG) {
+                       if (i == 0)
+                               
ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = 0;
+                       else {
+                               /* add 1 to make it non-overlapping with next 
lvl */
+                               
ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = 
bw_params->clk_table.entries[i - 1].fclk_mhz + 1;
+                       }
+                       ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz 
= bw_params->clk_table.entries[i].fclk_mhz;
+
+               } else {
+                       /* unconstrained for memory retraining */
+                       ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz 
= PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
+                       ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz 
= PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
+
+                       /* Modify previous watermark range to cover up to max */
+                       ranges->reader_wm_sets[num_valid_sets - 
1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
+               }
+               num_valid_sets++;
+       }
+
+       ASSERT(num_valid_sets != 0); /* Must have at least one set of valid 
watermarks */
+       ranges->num_reader_wm_sets = num_valid_sets;
+
+       /* modify the min and max to make sure we cover the whole range*/
+       ranges->reader_wm_sets[0].min_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
+       ranges->reader_wm_sets[0].min_fill_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
+       ranges->reader_wm_sets[ranges->num_reader_wm_sets - 
1].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
+       ranges->reader_wm_sets[ranges->num_reader_wm_sets - 1].max_fill_clk_mhz 
= PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
+
+       /* This is for writeback only, does not matter currently as no 
writeback support*/
+       ranges->num_writer_wm_sets = 1;
+       ranges->writer_wm_sets[0].wm_inst = WM_A;
+       ranges->writer_wm_sets[0].min_fill_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
+       ranges->writer_wm_sets[0].max_fill_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
+       ranges->writer_wm_sets[0].min_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
+       ranges->writer_wm_sets[0].max_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
+
+}
+
+static void rn_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
+{
+       struct dc_debug_options *debug = &clk_mgr_base->ctx->dc->debug;
+       struct pp_smu_wm_range_sets ranges = {0};
+       struct clk_mgr_internal *clk_mgr = TO_CLK_MGR_INTERNAL(clk_mgr_base);
+       struct pp_smu_funcs *pp_smu = clk_mgr->pp_smu;
+
+       if (!debug->disable_pplib_wm_range) {
+               build_watermark_ranges(clk_mgr_base->bw_params, &ranges);
+
+               /* Notify PP Lib/SMU which Watermarks to use for which clock 
ranges */
+               if (pp_smu && pp_smu->rn_funcs.set_wm_ranges)
+                       
pp_smu->rn_funcs.set_wm_ranges(&pp_smu->rn_funcs.pp_smu, &ranges);
+       }
+
+}
+
 static struct clk_mgr_funcs dcn21_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .update_clocks = rn_update_clocks,
        .init_clocks = rn_init_clocks,
        .enable_pme_wa = rn_enable_pme_wa,
-       /* .dump_clk_registers = rn_dump_clk_registers */
+       /* .dump_clk_registers = rn_dump_clk_registers, */
+       .notify_wm_ranges = rn_notify_wm_ranges
 };
 
 struct clk_bw_params rn_bw_params = {
@@ -472,63 +547,6 @@ struct clk_bw_params rn_bw_params = {
        }
 };
 
-static void rn_build_watermark_ranges(struct clk_bw_params *bw_params, struct 
pp_smu_wm_range_sets *ranges)
-{
-       int i, num_valid_sets;
-
-       num_valid_sets = 0;
-
-       for (i = 0; i < WM_SET_COUNT; i++) {
-               /* skip empty entries, the smu array has no holes*/
-               if (!bw_params->wm_table.entries[i].valid)
-                       continue;
-
-               ranges->reader_wm_sets[num_valid_sets].wm_inst = 
bw_params->wm_table.entries[i].wm_inst;
-               ranges->reader_wm_sets[num_valid_sets].wm_type = 
bw_params->wm_table.entries[i].wm_type;;
-               /* We will not select WM based on dcfclk, so leave it as 
unconstrained */
-               ranges->reader_wm_sets[num_valid_sets].min_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
-               ranges->reader_wm_sets[num_valid_sets].max_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
-               /* fclk wil be used to select WM*/
-
-               if (ranges->reader_wm_sets[num_valid_sets].wm_type == 
WM_TYPE_PSTATE_CHG) {
-                       if (i == 0)
-                               
ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = 0;
-                       else {
-                               /* add 1 to make it non-overlapping with next 
lvl */
-                               
ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz = 
bw_params->clk_table.entries[i - 1].fclk_mhz + 1;
-                       }
-                       ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz 
= bw_params->clk_table.entries[i].fclk_mhz;
-
-               } else {
-                       /* unconstrained for memory retraining */
-                       ranges->reader_wm_sets[num_valid_sets].min_fill_clk_mhz 
= PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
-                       ranges->reader_wm_sets[num_valid_sets].max_fill_clk_mhz 
= PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
-
-                       /* Modify previous watermark range to cover up to max */
-                       ranges->reader_wm_sets[num_valid_sets - 
1].max_fill_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
-               }
-               num_valid_sets++;
-       }
-
-       ASSERT(num_valid_sets != 0); /* Must have at least one set of valid 
watermarks */
-       ranges->num_reader_wm_sets = num_valid_sets;
-
-       /* modify the min and max to make sure we cover the whole range*/
-       ranges->reader_wm_sets[0].min_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
-       ranges->reader_wm_sets[0].min_fill_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
-       ranges->reader_wm_sets[ranges->num_reader_wm_sets - 
1].max_drain_clk_mhz = PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
-       ranges->reader_wm_sets[ranges->num_reader_wm_sets - 1].max_fill_clk_mhz 
= PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
-
-       /* This is for writeback only, does not matter currently as no 
writeback support*/
-       ranges->num_writer_wm_sets = 1;
-       ranges->writer_wm_sets[0].wm_inst = WM_A;
-       ranges->writer_wm_sets[0].min_fill_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
-       ranges->writer_wm_sets[0].max_fill_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
-       ranges->writer_wm_sets[0].min_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MIN;
-       ranges->writer_wm_sets[0].max_drain_clk_mhz = 
PP_SMU_WM_SET_RANGE_CLK_UNCONSTRAINED_MAX;
-
-}
-
 static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, 
unsigned int voltage)
 {
        int i;
@@ -661,21 +679,6 @@ void rn_clk_mgr_construct(
                rn_clk_mgr_helper_populate_bw_params(clk_mgr->base.bw_params, 
&clock_table, &ctx->asic_id);
        }
 
-       /*
-        * Notify SMU which set of WM should be selected for different ranges 
of fclk
-        * On Renoir there is a maximumum of 4 DF pstates supported, could be 
less
-        * depending on DDR speed and fused maximum fclk.
-        */
-       if (!debug->disable_pplib_wm_range) {
-               struct pp_smu_wm_range_sets ranges = {0};
-
-               rn_build_watermark_ranges(clk_mgr->base.bw_params, &ranges);
-
-               /* Notify PP Lib/SMU which Watermarks to use for which clock 
ranges */
-               if (pp_smu && pp_smu->rn_funcs.set_wm_ranges)
-                       
pp_smu->rn_funcs.set_wm_ranges(&pp_smu->rn_funcs.pp_smu, &ranges);
-       }
-
        if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver >= 
0x00371500) {
                /* enable powerfeatures when displaycount goes to 0 */
                rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(clk_mgr, 
!debug->disable_48mhz_pwrdwn);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c 
b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index df1be8ada66d..eb91432621ab 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -1304,6 +1304,10 @@ static void dcn10_init_hw(struct dc *dc)
        }
 
        dc->hwss.enable_power_gating_plane(dc->hwseq, true);
+
+       if (dc->clk_mgr->funcs->notify_wm_ranges)
+               dc->clk_mgr->funcs->notify_wm_ranges(dc->clk_mgr);
+
 }
 
 static void dcn10_reset_hw_ctx_wrap(
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h 
b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
index da43523a7bfe..4e18e77dcf42 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
@@ -183,6 +183,7 @@ struct clk_mgr_funcs {
 
        bool (*are_clock_states_equal) (struct dc_clocks *a,
                        struct dc_clocks *b);
+       void (*notify_wm_ranges)(struct clk_mgr *clk_mgr);
 };
 
 struct clk_mgr {
-- 
2.23.0

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

Reply via email to