aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0240-drm-amd-display-bandwidth-update-fix.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0240-drm-amd-display-bandwidth-update-fix.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0240-drm-amd-display-bandwidth-update-fix.patch689
1 files changed, 689 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0240-drm-amd-display-bandwidth-update-fix.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0240-drm-amd-display-bandwidth-update-fix.patch
new file mode 100644
index 00000000..6bed1de3
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/0240-drm-amd-display-bandwidth-update-fix.patch
@@ -0,0 +1,689 @@
+From 966eb4bca77011c7275fb5ac76085e6d645c67ad Mon Sep 17 00:00:00 2001
+From: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Date: Wed, 22 Feb 2017 17:52:22 -0500
+Subject: [PATCH 0240/4131] drm/amd/display: bandwidth update fix
+
+Signed-off-by: Dmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
+Acked-by: Harry Wentland <Harry.Wentland@amd.com>
+Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+---
+ drivers/gpu/drm/amd/display/dc/core/dc.c | 173 +------------
+ .../amd/display/dc/dce100/dce100_hw_sequencer.c | 15 +-
+ .../amd/display/dc/dce110/dce110_hw_sequencer.c | 279 ++++++++++++---------
+ .../drm/amd/display/dc/dce80/dce80_hw_sequencer.c | 16 +-
+ drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 9 +-
+ 5 files changed, 179 insertions(+), 313 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
+index da0f720..0ec2c4f 100644
+--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
++++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
+@@ -795,159 +795,6 @@ static bool streams_changed(
+ return false;
+ }
+
+-static void fill_display_configs(
+- const struct validate_context *context,
+- struct dm_pp_display_configuration *pp_display_cfg)
+-{
+- int j;
+- int num_cfgs = 0;
+-
+- for (j = 0; j < context->stream_count; j++) {
+- int k;
+-
+- const struct core_stream *stream = context->streams[j];
+- struct dm_pp_single_disp_config *cfg =
+- &pp_display_cfg->disp_configs[num_cfgs];
+- const struct pipe_ctx *pipe_ctx = NULL;
+-
+- for (k = 0; k < MAX_PIPES; k++)
+- if (stream == context->res_ctx.pipe_ctx[k].stream) {
+- pipe_ctx = &context->res_ctx.pipe_ctx[k];
+- break;
+- }
+-
+- ASSERT(pipe_ctx != NULL);
+-
+- num_cfgs++;
+- cfg->signal = pipe_ctx->stream->signal;
+- cfg->pipe_idx = pipe_ctx->pipe_idx;
+- cfg->src_height = stream->public.src.height;
+- cfg->src_width = stream->public.src.width;
+- cfg->ddi_channel_mapping =
+- stream->sink->link->ddi_channel_mapping.raw;
+- cfg->transmitter =
+- stream->sink->link->link_enc->transmitter;
+- cfg->link_settings.lane_count =
+- stream->sink->link->public.cur_link_settings.lane_count;
+- cfg->link_settings.link_rate =
+- stream->sink->link->public.cur_link_settings.link_rate;
+- cfg->link_settings.link_spread =
+- stream->sink->link->public.cur_link_settings.link_spread;
+- cfg->sym_clock = stream->phy_pix_clk;
+- /* Round v_refresh*/
+- cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000;
+- cfg->v_refresh /= stream->public.timing.h_total;
+- cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2)
+- / stream->public.timing.v_total;
+- }
+-
+- pp_display_cfg->display_count = num_cfgs;
+-}
+-
+-static uint32_t get_min_vblank_time_us(const struct validate_context *context)
+-{
+- uint8_t j;
+- uint32_t min_vertical_blank_time = -1;
+-
+- for (j = 0; j < context->stream_count; j++) {
+- const struct dc_stream *stream = &context->streams[j]->public;
+- uint32_t vertical_blank_in_pixels = 0;
+- uint32_t vertical_blank_time = 0;
+-
+- vertical_blank_in_pixels = stream->timing.h_total *
+- (stream->timing.v_total
+- - stream->timing.v_addressable);
+-
+- vertical_blank_time = vertical_blank_in_pixels
+- * 1000 / stream->timing.pix_clk_khz;
+-
+- if (min_vertical_blank_time > vertical_blank_time)
+- min_vertical_blank_time = vertical_blank_time;
+- }
+-
+- return min_vertical_blank_time;
+-}
+-
+-static int determine_sclk_from_bounding_box(
+- const struct core_dc *dc,
+- int required_sclk)
+-{
+- int i;
+-
+- /*
+- * Some asics do not give us sclk levels, so we just report the actual
+- * required sclk
+- */
+- if (dc->sclk_lvls.num_levels == 0)
+- return required_sclk;
+-
+- for (i = 0; i < dc->sclk_lvls.num_levels; i++) {
+- if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk)
+- return dc->sclk_lvls.clocks_in_khz[i];
+- }
+- /*
+- * even maximum level could not satisfy requirement, this
+- * is unexpected at this stage, should have been caught at
+- * validation time
+- */
+- ASSERT(0);
+- return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1];
+-}
+-
+-void pplib_apply_display_requirements(
+- struct core_dc *dc,
+- const struct validate_context *context,
+- struct dm_pp_display_configuration *pp_display_cfg)
+-{
+- pp_display_cfg->all_displays_in_sync =
+- context->bw_results.all_displays_in_sync;
+- pp_display_cfg->nb_pstate_switch_disable =
+- context->bw_results.nbp_state_change_enable == false;
+- pp_display_cfg->cpu_cc6_disable =
+- context->bw_results.cpuc_state_change_enable == false;
+- pp_display_cfg->cpu_pstate_disable =
+- context->bw_results.cpup_state_change_enable == false;
+- pp_display_cfg->cpu_pstate_separation_time =
+- context->bw_results.blackout_recovery_time_us;
+-
+- pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk
+- / MEMORY_TYPE_MULTIPLIER;
+-
+- pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box(
+- dc,
+- context->bw_results.required_sclk);
+-
+- pp_display_cfg->min_engine_clock_deep_sleep_khz
+- = context->bw_results.required_sclk_deep_sleep;
+-
+- pp_display_cfg->avail_mclk_switch_time_us =
+- get_min_vblank_time_us(context);
+- /* TODO: dce11.2*/
+- pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0;
+-
+- pp_display_cfg->disp_clk_khz = context->dispclk_khz;
+-
+- fill_display_configs(context, pp_display_cfg);
+-
+- /* TODO: is this still applicable?*/
+- if (pp_display_cfg->display_count == 1) {
+- const struct dc_crtc_timing *timing =
+- &context->streams[0]->public.timing;
+-
+- pp_display_cfg->crtc_index =
+- pp_display_cfg->disp_configs[0].pipe_idx;
+- pp_display_cfg->line_time_in_us = timing->h_total * 1000
+- / timing->pix_clk_khz;
+- }
+-
+- if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
+- struct dm_pp_display_configuration)) != 0)
+- dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
+-
+- dc->prev_display_config = *pp_display_cfg;
+-
+-}
+-
+ bool dc_commit_streams(
+ struct dc *dc,
+ const struct dc_stream *streams[],
+@@ -1036,9 +883,6 @@ bool dc_commit_streams(
+ context->streams[i]->public.timing.pix_clk_khz);
+ }
+
+- pplib_apply_display_requirements(core_dc,
+- context, &context->pp_display_cfg);
+-
+ resource_validate_ctx_destruct(core_dc->current_context);
+
+ if (core_dc->temp_flip_context != core_dc->current_context) {
+@@ -1065,7 +909,6 @@ bool dc_pre_update_surfaces_to_stream(
+ {
+ int i, j;
+ struct core_dc *core_dc = DC_TO_CORE(dc);
+- int prev_disp_clk = core_dc->current_context->dispclk_khz;
+ struct dc_stream_status *stream_status = NULL;
+ struct validate_context *context;
+ bool ret = true;
+@@ -1150,16 +993,7 @@ bool dc_pre_update_surfaces_to_stream(
+ goto unexpected_fail;
+ }
+
+- if (!IS_FPGA_MAXIMUS_DC(core_dc->ctx->dce_environment)
+- && prev_disp_clk < context->dispclk_khz) {
+- pplib_apply_display_requirements(core_dc, context,
+- &context->pp_display_cfg);
+- context->res_ctx.pool->display_clock->funcs->set_clock(
+- context->res_ctx.pool->display_clock,
+- context->dispclk_khz * 115 / 100);
+- core_dc->current_context->bw_results.dispclk_khz = context->dispclk_khz;
+- core_dc->current_context->dispclk_khz = context->dispclk_khz;
+- }
++ core_dc->hwss.set_bandwidth(core_dc, context, false);
+
+ for (i = 0; i < new_surface_count; i++)
+ for (j = 0; j < context->res_ctx.pool->pipe_count; j++) {
+@@ -1206,10 +1040,7 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
+ return false;
+ }
+
+- core_dc->hwss.set_bandwidth(core_dc);
+-
+- /*TODO: dce specific*/
+- pplib_apply_display_requirements(core_dc, context, &context->pp_display_cfg);
++ core_dc->hwss.set_bandwidth(core_dc, context, true);
+
+ resource_validate_ctx_destruct(core_dc->current_context);
+ core_dc->current_context = context;
+diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c
+index e2fe024..bd8e19f 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_hw_sequencer.c
+@@ -104,22 +104,18 @@ static bool dce100_enable_display_power_gating(
+ return false;
+ }
+
+-static void set_display_mark_for_pipe_if_needed(struct core_dc *dc,
+- struct pipe_ctx *pipe_ctx,
+- struct validate_context *context)
+-{
+- /* Do nothing until we have proper bandwitdth calcs */
+-}
+-
+ static void set_displaymarks(
+ const struct core_dc *dc, struct validate_context *context)
+ {
+ /* Do nothing until we have proper bandwitdth calcs */
+ }
+
+-static void set_bandwidth(struct core_dc *dc)
++static void set_bandwidth(
++ struct core_dc *dc,
++ struct validate_context *context,
++ bool decrease_allowed)
+ {
+- /* Do nothing until we have proper bandwitdth calcs */
++ dc->hwss.set_displaymarks(dc, context);
+ }
+
+
+@@ -132,7 +128,6 @@ bool dce100_hw_sequencer_construct(struct core_dc *dc)
+ /* TODO: dce80 is empty implementation at the moment*/
+ dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating;
+ dc->hwss.set_displaymarks = set_displaymarks;
+- dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed;
+ dc->hwss.set_bandwidth = set_bandwidth;
+
+ return true;
+diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+index 2d2daa6..d9dcb37 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+@@ -1209,93 +1209,6 @@ static uint32_t compute_pstate_blackout_duration(
+ return total_dest_line_time_ns;
+ }
+
+-/* get the index of the pipe_ctx if there were no gaps in the pipe_ctx array*/
+-int get_bw_result_idx(
+- struct resource_context *res_ctx,
+- int pipe_idx)
+-{
+- int i, collapsed_idx;
+-
+- if (res_ctx->pipe_ctx[pipe_idx].top_pipe)
+- return 3;
+-
+- collapsed_idx = 0;
+- for (i = 0; i < pipe_idx; i++) {
+- if (res_ctx->pipe_ctx[i].stream)
+- collapsed_idx++;
+- }
+-
+- return collapsed_idx;
+-}
+-
+-static bool is_watermark_set_a_greater(
+- const struct bw_watermarks *set_a,
+- const struct bw_watermarks *set_b)
+-{
+- if (set_a->a_mark > set_b->a_mark
+- || set_a->b_mark > set_b->b_mark
+- || set_a->c_mark > set_b->c_mark
+- || set_a->d_mark > set_b->d_mark)
+- return true;
+- return false;
+-}
+-
+-static bool did_watermarks_increase(
+- struct pipe_ctx *pipe_ctx,
+- struct validate_context *context,
+- struct validate_context *old_context)
+-{
+- int collapsed_pipe_idx = get_bw_result_idx(&context->res_ctx,
+- pipe_ctx->pipe_idx);
+- int old_collapsed_pipe_idx = get_bw_result_idx(&old_context->res_ctx,
+- pipe_ctx->pipe_idx);
+- struct pipe_ctx *old_pipe_ctx = &old_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx];
+-
+- if (!old_pipe_ctx->stream)
+- return true;
+-
+- if (is_watermark_set_a_greater(
+- &context->bw_results.nbp_state_change_wm_ns[collapsed_pipe_idx],
+- &old_context->bw_results.nbp_state_change_wm_ns[old_collapsed_pipe_idx]))
+- return true;
+- if (is_watermark_set_a_greater(
+- &context->bw_results.stutter_exit_wm_ns[collapsed_pipe_idx],
+- &old_context->bw_results.stutter_exit_wm_ns[old_collapsed_pipe_idx]))
+- return true;
+- if (is_watermark_set_a_greater(
+- &context->bw_results.urgent_wm_ns[collapsed_pipe_idx],
+- &old_context->bw_results.urgent_wm_ns[old_collapsed_pipe_idx]))
+- return true;
+-
+- return false;
+-}
+-
+-static void program_wm_for_pipe(struct core_dc *dc,
+- struct pipe_ctx *pipe_ctx,
+- struct validate_context *context)
+-{
+- int total_dest_line_time_ns = compute_pstate_blackout_duration(
+- dc->bw_vbios.blackout_duration,
+- pipe_ctx->stream);
+- int bw_result_idx = get_bw_result_idx(&context->res_ctx,
+- pipe_ctx->pipe_idx);
+-
+- pipe_ctx->mi->funcs->mem_input_program_display_marks(
+- pipe_ctx->mi,
+- context->bw_results.nbp_state_change_wm_ns[bw_result_idx],
+- context->bw_results.stutter_exit_wm_ns[bw_result_idx],
+- context->bw_results.urgent_wm_ns[bw_result_idx],
+- total_dest_line_time_ns);
+-
+- if (pipe_ctx->top_pipe)
+- pipe_ctx->mi->funcs->mem_input_program_chroma_display_marks(
+- pipe_ctx->mi,
+- context->bw_results.nbp_state_change_wm_ns[bw_result_idx + 1],
+- context->bw_results.stutter_exit_wm_ns[bw_result_idx + 1],
+- context->bw_results.urgent_wm_ns[bw_result_idx + 1],
+- total_dest_line_time_ns);
+-}
+-
+ void dce110_set_displaymarks(
+ const struct core_dc *dc,
+ struct validate_context *context)
+@@ -1589,7 +1502,7 @@ static void reset_hw_ctx_wrap(
+ }
+ }
+
+-/*TODO: const validate_context*/
++
+ enum dc_status dce110_apply_ctx_to_hw(
+ struct core_dc *dc,
+ struct validate_context *context)
+@@ -1768,7 +1681,7 @@ enum dc_status dce110_apply_ctx_to_hw(
+ return status;
+ }
+
+- dc->hwss.set_displaymarks(dc, context);
++ dc->hwss.set_bandwidth(dc, context, true);
+
+ /* to save power */
+ apply_min_clocks(dc, context, &clocks_state, false);
+@@ -1777,6 +1690,7 @@ enum dc_status dce110_apply_ctx_to_hw(
+
+ switch_dp_clock_sources(dc, &context->res_ctx);
+
++
+ return DC_OK;
+ }
+
+@@ -2135,7 +2049,6 @@ static void init_hw(struct core_dc *dc)
+ }
+ }
+
+-/* TODO: move this to apply_ctx_tohw some how?*/
+ static void dce110_power_on_pipe_if_needed(
+ struct core_dc *dc,
+ struct pipe_ctx *pipe_ctx,
+@@ -2180,31 +2093,175 @@ static void dce110_power_on_pipe_if_needed(
+ }
+ }
+
+-static void dce110_increase_watermarks_for_pipe(
+- struct core_dc *dc,
+- struct pipe_ctx *pipe_ctx,
+- struct validate_context *context)
++static void fill_display_configs(
++ const struct validate_context *context,
++ struct dm_pp_display_configuration *pp_display_cfg)
++{
++ int j;
++ int num_cfgs = 0;
++
++ for (j = 0; j < context->stream_count; j++) {
++ int k;
++
++ const struct core_stream *stream = context->streams[j];
++ struct dm_pp_single_disp_config *cfg =
++ &pp_display_cfg->disp_configs[num_cfgs];
++ const struct pipe_ctx *pipe_ctx = NULL;
++
++ for (k = 0; k < MAX_PIPES; k++)
++ if (stream == context->res_ctx.pipe_ctx[k].stream) {
++ pipe_ctx = &context->res_ctx.pipe_ctx[k];
++ break;
++ }
++
++ ASSERT(pipe_ctx != NULL);
++
++ num_cfgs++;
++ cfg->signal = pipe_ctx->stream->signal;
++ cfg->pipe_idx = pipe_ctx->pipe_idx;
++ cfg->src_height = stream->public.src.height;
++ cfg->src_width = stream->public.src.width;
++ cfg->ddi_channel_mapping =
++ stream->sink->link->ddi_channel_mapping.raw;
++ cfg->transmitter =
++ stream->sink->link->link_enc->transmitter;
++ cfg->link_settings.lane_count =
++ stream->sink->link->public.cur_link_settings.lane_count;
++ cfg->link_settings.link_rate =
++ stream->sink->link->public.cur_link_settings.link_rate;
++ cfg->link_settings.link_spread =
++ stream->sink->link->public.cur_link_settings.link_spread;
++ cfg->sym_clock = stream->phy_pix_clk;
++ /* Round v_refresh*/
++ cfg->v_refresh = stream->public.timing.pix_clk_khz * 1000;
++ cfg->v_refresh /= stream->public.timing.h_total;
++ cfg->v_refresh = (cfg->v_refresh + stream->public.timing.v_total / 2)
++ / stream->public.timing.v_total;
++ }
++
++ pp_display_cfg->display_count = num_cfgs;
++}
++
++static uint32_t get_min_vblank_time_us(const struct validate_context *context)
+ {
+- if (did_watermarks_increase(pipe_ctx, context, dc->current_context))
+- program_wm_for_pipe(dc, pipe_ctx, context);
++ uint8_t j;
++ uint32_t min_vertical_blank_time = -1;
++
++ for (j = 0; j < context->stream_count; j++) {
++ const struct dc_stream *stream = &context->streams[j]->public;
++ uint32_t vertical_blank_in_pixels = 0;
++ uint32_t vertical_blank_time = 0;
++
++ vertical_blank_in_pixels = stream->timing.h_total *
++ (stream->timing.v_total
++ - stream->timing.v_addressable);
++
++ vertical_blank_time = vertical_blank_in_pixels
++ * 1000 / stream->timing.pix_clk_khz;
++
++ if (min_vertical_blank_time > vertical_blank_time)
++ min_vertical_blank_time = vertical_blank_time;
++ }
++
++ return min_vertical_blank_time;
+ }
+
+-static void dce110_set_bandwidth(struct core_dc *dc)
++static int determine_sclk_from_bounding_box(
++ const struct core_dc *dc,
++ int required_sclk)
+ {
+ int i;
+
+- for (i = 0; i < dc->current_context->res_ctx.pool->pipe_count; i++) {
+- struct pipe_ctx *pipe_ctx = &dc->current_context->res_ctx.pipe_ctx[i];
++ /*
++ * Some asics do not give us sclk levels, so we just report the actual
++ * required sclk
++ */
++ if (dc->sclk_lvls.num_levels == 0)
++ return required_sclk;
+
+- if (!pipe_ctx->stream)
+- continue;
++ for (i = 0; i < dc->sclk_lvls.num_levels; i++) {
++ if (dc->sclk_lvls.clocks_in_khz[i] >= required_sclk)
++ return dc->sclk_lvls.clocks_in_khz[i];
++ }
++ /*
++ * even maximum level could not satisfy requirement, this
++ * is unexpected at this stage, should have been caught at
++ * validation time
++ */
++ ASSERT(0);
++ return dc->sclk_lvls.clocks_in_khz[dc->sclk_lvls.num_levels - 1];
++}
++
++static void pplib_apply_display_requirements(
++ struct core_dc *dc,
++ struct validate_context *context)
++{
++ struct dm_pp_display_configuration *pp_display_cfg = &context->pp_display_cfg;
++
++ pp_display_cfg->all_displays_in_sync =
++ context->bw_results.all_displays_in_sync;
++ pp_display_cfg->nb_pstate_switch_disable =
++ context->bw_results.nbp_state_change_enable == false;
++ pp_display_cfg->cpu_cc6_disable =
++ context->bw_results.cpuc_state_change_enable == false;
++ pp_display_cfg->cpu_pstate_disable =
++ context->bw_results.cpup_state_change_enable == false;
++ pp_display_cfg->cpu_pstate_separation_time =
++ context->bw_results.blackout_recovery_time_us;
++
++ pp_display_cfg->min_memory_clock_khz = context->bw_results.required_yclk
++ / MEMORY_TYPE_MULTIPLIER;
++
++ pp_display_cfg->min_engine_clock_khz = determine_sclk_from_bounding_box(
++ dc,
++ context->bw_results.required_sclk);
++
++ pp_display_cfg->min_engine_clock_deep_sleep_khz
++ = context->bw_results.required_sclk_deep_sleep;
++
++ pp_display_cfg->avail_mclk_switch_time_us =
++ get_min_vblank_time_us(context);
++ /* TODO: dce11.2*/
++ pp_display_cfg->avail_mclk_switch_time_in_disp_active_us = 0;
+
+- program_wm_for_pipe(dc, pipe_ctx, dc->current_context);
++ pp_display_cfg->disp_clk_khz = context->dispclk_khz;
++
++ fill_display_configs(context, pp_display_cfg);
++
++ /* TODO: is this still applicable?*/
++ if (pp_display_cfg->display_count == 1) {
++ const struct dc_crtc_timing *timing =
++ &context->streams[0]->public.timing;
++
++ pp_display_cfg->crtc_index =
++ pp_display_cfg->disp_configs[0].pipe_idx;
++ pp_display_cfg->line_time_in_us = timing->h_total * 1000
++ / timing->pix_clk_khz;
++ }
++
++ if (memcmp(&dc->prev_display_config, pp_display_cfg, sizeof(
++ struct dm_pp_display_configuration)) != 0)
++ dm_pp_apply_display_requirements(dc->ctx, pp_display_cfg);
++
++ dc->prev_display_config = *pp_display_cfg;
++}
++
++static void dce110_set_bandwidth(
++ struct core_dc *dc,
++ struct validate_context *context,
++ bool decrease_allowed)
++{
++ dc->hwss.set_displaymarks(dc, context);
++
++ if (decrease_allowed || context->dispclk_khz > dc->current_context->dispclk_khz) {
++ context->res_ctx.pool->display_clock->funcs->set_clock(
++ context->res_ctx.pool->display_clock,
++ context->dispclk_khz * 115 / 100);
++ dc->current_context->bw_results.dispclk_khz = context->dispclk_khz;
++ dc->current_context->dispclk_khz = context->dispclk_khz;
+ }
+
+- dc->current_context->res_ctx.pool->display_clock->funcs->set_clock(
+- dc->current_context->res_ctx.pool->display_clock,
+- dc->current_context->dispclk_khz * 115 / 100);
++ pplib_apply_display_requirements(dc, context);
+ }
+
+ static void dce110_program_front_end_for_pipe(
+@@ -2335,15 +2392,6 @@ static void dce110_program_front_end_for_pipe(
+ pipe_ctx->scl_data.recout.y);
+ }
+
+-static void dce110_prepare_pipe_for_context(
+- struct core_dc *dc,
+- struct pipe_ctx *pipe_ctx,
+- struct validate_context *context)
+-{
+- dce110_power_on_pipe_if_needed(dc, pipe_ctx, context);
+- dc->hwss.increase_watermarks_for_pipe(dc, pipe_ctx, context);
+-}
+-
+ static void dce110_apply_ctx_for_surface(
+ struct core_dc *dc,
+ struct core_surface *surface,
+@@ -2388,7 +2436,7 @@ static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe)
+ static const struct hw_sequencer_funcs dce110_funcs = {
+ .init_hw = init_hw,
+ .apply_ctx_to_hw = dce110_apply_ctx_to_hw,
+- .prepare_pipe_for_context = dce110_prepare_pipe_for_context,
++ .prepare_pipe_for_context = dce110_power_on_pipe_if_needed,
+ .apply_ctx_for_surface = dce110_apply_ctx_for_surface,
+ .set_plane_config = set_plane_config,
+ .update_plane_addr = update_plane_addr,
+@@ -2407,7 +2455,6 @@ static const struct hw_sequencer_funcs dce110_funcs = {
+ .power_down_front_end = dce110_power_down_fe,
+ .pipe_control_lock = dce_pipe_control_lock,
+ .set_displaymarks = dce110_set_displaymarks,
+- .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe,
+ .set_bandwidth = dce110_set_bandwidth,
+ .set_drr = set_drr,
+ .set_static_screen_control = set_static_screen_control,
+diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c
+index c7a2b76..85a54d9 100644
+--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c
++++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_hw_sequencer.c
+@@ -106,23 +106,18 @@ static bool dce80_enable_display_power_gating(
+ return false;
+ }
+
+-
+-static void set_display_mark_for_pipe_if_needed(struct core_dc *dc,
+- struct pipe_ctx *pipe_ctx,
+- struct validate_context *context)
+-{
+- /* Do nothing until we have proper bandwitdth calcs */
+-}
+-
+ static void set_displaymarks(
+ const struct core_dc *dc, struct validate_context *context)
+ {
+ /* Do nothing until we have proper bandwitdth calcs */
+ }
+
+-static void set_bandwidth(struct core_dc *dc)
++static void set_bandwidth(
++ struct core_dc *dc,
++ struct validate_context *context,
++ bool decrease_allowed)
+ {
+- /* Do nothing until we have proper bandwitdth calcs */
++ dc->hwss.set_displaymarks(dc, context);
+ }
+
+
+@@ -133,7 +128,6 @@ bool dce80_hw_sequencer_construct(struct core_dc *dc)
+ dc->hwss.enable_display_power_gating = dce80_enable_display_power_gating;
+ dc->hwss.pipe_control_lock = dce_pipe_control_lock;
+ dc->hwss.set_displaymarks = set_displaymarks;
+- dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed;
+ dc->hwss.set_bandwidth = set_bandwidth;
+
+ return true;
+diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+index 758a568..7b780c6 100644
+--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
++++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+@@ -124,11 +124,10 @@ struct hw_sequencer_funcs {
+ const struct core_dc *dc,
+ struct validate_context *context);
+
+- void (*increase_watermarks_for_pipe)(struct core_dc *dc,
+- struct pipe_ctx *pipe_ctx,
+- struct validate_context *context);
+-
+- void (*set_bandwidth)(struct core_dc *dc);
++ void (*set_bandwidth)(
++ struct core_dc *dc,
++ struct validate_context *context,
++ bool decrease_allowed);
+
+ void (*set_drr)(struct pipe_ctx **pipe_ctx, int num_pipes,
+ int vmin, int vmax);
+--
+2.7.4
+