aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4254-drm-amd-display-move-wm-ranges-reporting-to-end-of-i.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4254-drm-amd-display-move-wm-ranges-reporting-to-end-of-i.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4254-drm-amd-display-move-wm-ranges-reporting-to-end-of-i.patch231
1 files changed, 231 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4254-drm-amd-display-move-wm-ranges-reporting-to-end-of-i.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4254-drm-amd-display-move-wm-ranges-reporting-to-end-of-i.patch
new file mode 100644
index 00000000..4bfe3379
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.19.8/4254-drm-amd-display-move-wm-ranges-reporting-to-end-of-i.patch
@@ -0,0 +1,231 @@
+From 9660422158b380fa32fd18ba9d56424ced83d18c Mon Sep 17 00:00:00 2001
+From: Eric Yang <Eric.Yang2@amd.com>
+Date: Tue, 24 Sep 2019 12:02:38 -0400
+Subject: [PATCH 4254/4736] drm/amd/display: move wm ranges reporting to end of
+ init hw
+
+[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>
+---
+ .../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 7c02f646feed..b61cc211e659 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
+@@ -1303,6 +1303,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.17.1
+