diff options
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.patch | 231 |
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 + |