|
@@ -1209,93 +1209,6 @@ static uint32_t compute_pstate_blackout_duration(
|
|
return total_dest_line_time_ns;
|
|
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(
|
|
void dce110_set_displaymarks(
|
|
const struct core_dc *dc,
|
|
const struct core_dc *dc,
|
|
struct validate_context *context)
|
|
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(
|
|
enum dc_status dce110_apply_ctx_to_hw(
|
|
struct core_dc *dc,
|
|
struct core_dc *dc,
|
|
struct validate_context *context)
|
|
struct validate_context *context)
|
|
@@ -1768,7 +1681,7 @@ enum dc_status dce110_apply_ctx_to_hw(
|
|
return status;
|
|
return status;
|
|
}
|
|
}
|
|
|
|
|
|
- dc->hwss.set_displaymarks(dc, context);
|
|
|
|
|
|
+ dc->hwss.set_bandwidth(dc, context, true);
|
|
|
|
|
|
/* to save power */
|
|
/* to save power */
|
|
apply_min_clocks(dc, context, &clocks_state, false);
|
|
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);
|
|
switch_dp_clock_sources(dc, &context->res_ctx);
|
|
|
|
|
|
|
|
+
|
|
return DC_OK;
|
|
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(
|
|
static void dce110_power_on_pipe_if_needed(
|
|
struct core_dc *dc,
|
|
struct core_dc *dc,
|
|
struct pipe_ctx *pipe_ctx,
|
|
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;
|
|
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(
|
|
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);
|
|
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(
|
|
static void dce110_apply_ctx_for_surface(
|
|
struct core_dc *dc,
|
|
struct core_dc *dc,
|
|
struct core_surface *surface,
|
|
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 = {
|
|
static const struct hw_sequencer_funcs dce110_funcs = {
|
|
.init_hw = init_hw,
|
|
.init_hw = init_hw,
|
|
.apply_ctx_to_hw = dce110_apply_ctx_to_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,
|
|
.apply_ctx_for_surface = dce110_apply_ctx_for_surface,
|
|
.set_plane_config = set_plane_config,
|
|
.set_plane_config = set_plane_config,
|
|
.update_plane_addr = update_plane_addr,
|
|
.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,
|
|
.power_down_front_end = dce110_power_down_fe,
|
|
.pipe_control_lock = dce_pipe_control_lock,
|
|
.pipe_control_lock = dce_pipe_control_lock,
|
|
.set_displaymarks = dce110_set_displaymarks,
|
|
.set_displaymarks = dce110_set_displaymarks,
|
|
- .increase_watermarks_for_pipe = dce110_increase_watermarks_for_pipe,
|
|
|
|
.set_bandwidth = dce110_set_bandwidth,
|
|
.set_bandwidth = dce110_set_bandwidth,
|
|
.set_drr = set_drr,
|
|
.set_drr = set_drr,
|
|
.set_static_screen_control = set_static_screen_control,
|
|
.set_static_screen_control = set_static_screen_control,
|