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