drm/amd/display: move wm ranges reporting to end of init hw
authorEric Yang <Eric.Yang2@amd.com>
Tue, 24 Sep 2019 16:02:38 +0000 (12:02 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 25 Oct 2019 20:50:09 +0000 (16:50 -0400)
[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.Yang2@amd.com>
Reviewed-by: Yongqiang Sun <yongqiang.sun@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h

index e8b8ee4f1b1ee5154ec9f11411766695d8fb05ec..f64d221ad6f19b651fddb1dd06e6fdd191d1cdaf 100644 (file)
@@ -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);
index df1be8ada66de0742b30a9f2b97d4ebcb3480ef1..eb91432621abe0f0d8cb91472011e005b4260264 100644 (file)
@@ -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(
index da43523a7bfe9e5a4ea67098911ea2a5fbe9cd85..4e18e77dcf422d0db1c76319595a897c300976fa 100644 (file)
@@ -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 {