aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3765-drm-amd-display-Set-disp-clk-in-a-safe-way-to-avoid-.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3765-drm-amd-display-Set-disp-clk-in-a-safe-way-to-avoid-.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3765-drm-amd-display-Set-disp-clk-in-a-safe-way-to-avoid-.patch287
1 files changed, 287 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3765-drm-amd-display-Set-disp-clk-in-a-safe-way-to-avoid-.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3765-drm-amd-display-Set-disp-clk-in-a-safe-way-to-avoid-.patch
new file mode 100644
index 00000000..03d4b5d6
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/3765-drm-amd-display-Set-disp-clk-in-a-safe-way-to-avoid-.patch
@@ -0,0 +1,287 @@
+From e586a4a7b3c1977300c2711acb0806fcb2afd1d7 Mon Sep 17 00:00:00 2001
+From: Yongqiang Sun <yongqiang.sun@amd.com>
+Date: Wed, 28 Feb 2018 17:14:50 -0500
+Subject: [PATCH 3765/4131] drm/amd/display: Set disp clk in a safe way to
+ avoid over high dpp clk.
+
+Increase clock, if current dpp div is 0 and request dpp div is 1, request clk is
+higher than maximum dpp clk as per dpm table.
+ set dispclk to the value of maximum supported dpp clk
+ set div to 1
+ set dispclk to request value.
+Decrease clock, currrent dpp div is 1 and request dpp div is 0, current clk is
+higher than maximum dpp clk as per dpm table.
+ set dispclk to the value of maximum supported dpp clk
+ set div to 0
+ set dispclk to request value.
+
+Signed-off-by: Yongqiang Sun <yongqiang.sun@amd.com>
+Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
+Reviewed-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Acked-by: Harry Wentland <harry.wentland@amd.com>
+---
+ drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c | 19 +++
+ drivers/gpu/drm/amd/display/dc/dc.h | 1 +
+ drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c | 2 -
+ .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 142 +++++++++++++++++----
+ 4 files changed, 139 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
+index 8020bc7..8bab3fe 100644
+--- a/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
++++ b/drivers/gpu/drm/amd/display/dc/calcs/dcn_calcs.c
+@@ -1000,6 +1000,25 @@ bool dcn_validate_bandwidth(
+
+ context->bw.dcn.calc_clk.max_dppclk_khz = context->bw.dcn.calc_clk.dispclk_khz / v->dispclk_dppclk_ratio;
+
++ switch (v->voltage_level) {
++ case 0:
++ context->bw.dcn.calc_clk.max_supported_dppclk_khz =
++ (int)(dc->dcn_soc->max_dppclk_vmin0p65 * 1000);
++ break;
++ case 1:
++ context->bw.dcn.calc_clk.max_supported_dppclk_khz =
++ (int)(dc->dcn_soc->max_dppclk_vmid0p72 * 1000);
++ break;
++ case 2:
++ context->bw.dcn.calc_clk.max_supported_dppclk_khz =
++ (int)(dc->dcn_soc->max_dppclk_vnom0p8 * 1000);
++ break;
++ default:
++ context->bw.dcn.calc_clk.max_supported_dppclk_khz =
++ (int)(dc->dcn_soc->max_dppclk_vmax0p9 * 1000);
++ break;
++ }
++
+ for (i = 0, input_idx = 0; i < pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
+index db91a6b..ff4b181 100644
+--- a/drivers/gpu/drm/amd/display/dc/dc.h
++++ b/drivers/gpu/drm/amd/display/dc/dc.h
+@@ -187,6 +187,7 @@ enum wm_report_mode {
+ struct dc_clocks {
+ int dispclk_khz;
+ int max_dppclk_khz;
++ int max_supported_dppclk_khz;
+ int dcfclk_khz;
+ int socclk_khz;
+ int dcfclk_deep_sleep_khz;
+diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
+index 78e6beb..76fc903 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
++++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
+@@ -623,7 +623,6 @@ static bool dce_apply_clock_voltage_request(
+ }
+ }
+ if (send_request) {
+-#if defined(CONFIG_DRM_AMD_DC_DCN1_0)
+ if (clk->ctx->dce_version >= DCN_VERSION_1_0) {
+ struct dc *core_dc = clk->ctx->dc;
+ /*use dcfclk request voltage*/
+@@ -631,7 +630,6 @@ static bool dce_apply_clock_voltage_request(
+ clock_voltage_req.clocks_in_khz =
+ dcn_find_dcfclk_suits_all(core_dc, &clk->cur_clocks_value);
+ }
+-#endif
+ dm_pp_apply_clock_for_voltage_request(
+ clk->ctx, &clock_voltage_req);
+ }
+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 50088b6..9f9b910 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
+@@ -1699,16 +1699,22 @@ static void update_dchubp_dpp(
+ union plane_size size = plane_state->plane_size;
+
+ /* depends on DML calculation, DPP clock value may change dynamically */
++ /* If request max dpp clk is lower than current dispclk, no need to
++ * divided by 2
++ */
+ if (plane_state->update_flags.bits.full_update) {
++ bool should_divided_by_2 = context->bw.dcn.calc_clk.max_dppclk_khz <=
++ context->bw.dcn.cur_clk.dispclk_khz / 2;
++
+ dpp->funcs->dpp_dppclk_control(
+ dpp,
+- context->bw.dcn.calc_clk.max_dppclk_khz <
+- context->bw.dcn.calc_clk.dispclk_khz,
++ should_divided_by_2,
+ true);
+
+ dc->current_state->bw.dcn.cur_clk.max_dppclk_khz =
+- context->bw.dcn.calc_clk.max_dppclk_khz;
+- context->bw.dcn.cur_clk.max_dppclk_khz = context->bw.dcn.calc_clk.max_dppclk_khz;
++ should_divided_by_2 ?
++ context->bw.dcn.cur_clk.dispclk_khz / 2 :
++ context->bw.dcn.cur_clk.dispclk_khz;
+ }
+
+ /* TODO: Need input parameter to tell current DCHUB pipe tie to which OTG
+@@ -2117,6 +2123,96 @@ static inline bool should_set_clock(bool decrease_allowed, int calc_clk, int cur
+ return ((decrease_allowed && calc_clk < cur_clk) || calc_clk > cur_clk);
+ }
+
++static int determine_dppclk_threshold(struct dc *dc, struct dc_state *context)
++{
++ bool request_dpp_div = context->bw.dcn.calc_clk.dispclk_khz >
++ context->bw.dcn.calc_clk.max_dppclk_khz;
++ bool dispclk_increase = context->bw.dcn.calc_clk.dispclk_khz >
++ context->bw.dcn.cur_clk.dispclk_khz;
++ int disp_clk_threshold = context->bw.dcn.calc_clk.max_supported_dppclk_khz;
++ bool cur_dpp_div = context->bw.dcn.cur_clk.dispclk_khz >
++ context->bw.dcn.cur_clk.max_dppclk_khz;
++
++ /* increase clock, looking for div is 0 for current, request div is 1*/
++ if (dispclk_increase) {
++ /* already divided by 2, no need to reach target clk with 2 steps*/
++ if (cur_dpp_div)
++ return context->bw.dcn.calc_clk.dispclk_khz;
++
++ /* request disp clk is lower than maximum supported dpp clk,
++ * no need to reach target clk with two steps.
++ */
++ if (context->bw.dcn.calc_clk.dispclk_khz <= disp_clk_threshold)
++ return context->bw.dcn.calc_clk.dispclk_khz;
++
++ /* target dpp clk not request divided by 2, still within threshold */
++ if (!request_dpp_div)
++ return context->bw.dcn.calc_clk.dispclk_khz;
++
++ } else {
++ /* decrease clock, looking for current dppclk divided by 2,
++ * request dppclk not divided by 2.
++ */
++
++ /* current dpp clk not divided by 2, no need to ramp*/
++ if (!cur_dpp_div)
++ return context->bw.dcn.calc_clk.dispclk_khz;
++
++ /* current disp clk is lower than current maximum dpp clk,
++ * no need to ramp
++ */
++ if (context->bw.dcn.cur_clk.dispclk_khz <= disp_clk_threshold)
++ return context->bw.dcn.calc_clk.dispclk_khz;
++
++ /* request dpp clk need to be divided by 2 */
++ if (request_dpp_div)
++ return context->bw.dcn.calc_clk.dispclk_khz;
++ }
++
++ return disp_clk_threshold;
++}
++
++static void ramp_up_dispclk_with_dpp(struct dc *dc, struct dc_state *context)
++{
++ int i;
++ bool request_dpp_div = context->bw.dcn.calc_clk.dispclk_khz >
++ context->bw.dcn.calc_clk.max_dppclk_khz;
++
++ int dispclk_to_dpp_threshold = determine_dppclk_threshold(dc, context);
++
++ /* set disp clk to dpp clk threshold */
++ dc->res_pool->display_clock->funcs->set_clock(
++ dc->res_pool->display_clock,
++ dispclk_to_dpp_threshold);
++
++ /* update request dpp clk division option */
++ for (i = 0; i < dc->res_pool->pipe_count; i++) {
++ struct pipe_ctx *pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
++
++ if (!pipe_ctx->plane_state)
++ continue;
++
++ pipe_ctx->plane_res.dpp->funcs->dpp_dppclk_control(
++ pipe_ctx->plane_res.dpp,
++ request_dpp_div,
++ true);
++ }
++
++ /* If target clk not same as dppclk threshold, set to target clock */
++ if (dispclk_to_dpp_threshold != context->bw.dcn.calc_clk.dispclk_khz) {
++ dc->res_pool->display_clock->funcs->set_clock(
++ dc->res_pool->display_clock,
++ context->bw.dcn.calc_clk.dispclk_khz);
++ }
++
++ context->bw.dcn.cur_clk.dispclk_khz =
++ context->bw.dcn.calc_clk.dispclk_khz;
++ context->bw.dcn.cur_clk.max_dppclk_khz =
++ context->bw.dcn.calc_clk.max_dppclk_khz;
++ context->bw.dcn.cur_clk.max_supported_dppclk_khz =
++ context->bw.dcn.calc_clk.max_supported_dppclk_khz;
++}
++
+ static void dcn10_set_bandwidth(
+ struct dc *dc,
+ struct dc_state *context,
+@@ -2136,17 +2232,6 @@ static void dcn10_set_bandwidth(
+
+ if (should_set_clock(
+ decrease_allowed,
+- context->bw.dcn.calc_clk.dispclk_khz,
+- dc->current_state->bw.dcn.cur_clk.dispclk_khz)) {
+- dc->res_pool->display_clock->funcs->set_clock(
+- dc->res_pool->display_clock,
+- context->bw.dcn.calc_clk.dispclk_khz);
+- context->bw.dcn.cur_clk.dispclk_khz =
+- context->bw.dcn.calc_clk.dispclk_khz;
+- }
+-
+- if (should_set_clock(
+- decrease_allowed,
+ context->bw.dcn.calc_clk.dcfclk_khz,
+ dc->current_state->bw.dcn.cur_clk.dcfclk_khz)) {
+ context->bw.dcn.cur_clk.dcfclk_khz =
+@@ -2157,6 +2242,14 @@ static void dcn10_set_bandwidth(
+
+ if (should_set_clock(
+ decrease_allowed,
++ context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz,
++ dc->current_state->bw.dcn.cur_clk.dcfclk_deep_sleep_khz)) {
++ context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz =
++ context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
++ }
++
++ if (should_set_clock(
++ decrease_allowed,
+ context->bw.dcn.calc_clk.fclk_khz,
+ dc->current_state->bw.dcn.cur_clk.fclk_khz)) {
+ context->bw.dcn.cur_clk.fclk_khz =
+@@ -2164,14 +2257,6 @@ static void dcn10_set_bandwidth(
+ smu_req.hard_min_fclk_khz = context->bw.dcn.calc_clk.fclk_khz;
+ }
+
+- if (should_set_clock(
+- decrease_allowed,
+- context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz,
+- dc->current_state->bw.dcn.cur_clk.dcfclk_deep_sleep_khz)) {
+- context->bw.dcn.cur_clk.dcfclk_deep_sleep_khz =
+- context->bw.dcn.calc_clk.dcfclk_deep_sleep_khz;
+- }
+-
+ smu_req.display_count = context->stream_count;
+
+ if (pp_smu->set_display_requirement)
+@@ -2179,6 +2264,17 @@ static void dcn10_set_bandwidth(
+
+ *smu_req_cur = smu_req;
+
++ /* make sure dcf clk is before dpp clk to
++ * make sure we have enough voltage to run dpp clk
++ */
++ if (should_set_clock(
++ decrease_allowed,
++ context->bw.dcn.calc_clk.dispclk_khz,
++ dc->current_state->bw.dcn.cur_clk.dispclk_khz)) {
++
++ ramp_up_dispclk_with_dpp(dc, context);
++ }
++
+ /* Decrease in freq is increase in period so opposite comparison for dram_ccm */
+ if ((decrease_allowed && context->bw.dcn.calc_clk.dram_ccm_us
+ > dc->current_state->bw.dcn.cur_clk.dram_ccm_us) ||
+--
+2.7.4
+