summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core')
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c478
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c305
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c55
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c38
4 files changed, 720 insertions, 156 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 52564b93f7eb..be72e03cdf92 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -515,8 +515,7 @@ dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv,
cmd.secure_display.roi_info.y_end = rect->y + rect->height;
}
- dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dmub_srv);
+ dm_execute_dmub_cmd(dmub_srv->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
}
static inline void
@@ -858,7 +857,6 @@ static bool dc_construct_ctx(struct dc *dc,
const struct dc_init_data *init_params)
{
struct dc_context *dc_ctx;
- enum dce_version dc_version = DCE_VERSION_UNKNOWN;
dc_ctx = kzalloc(sizeof(*dc_ctx), GFP_KERNEL);
if (!dc_ctx)
@@ -876,8 +874,7 @@ static bool dc_construct_ctx(struct dc *dc,
/* Create logger */
- dc_version = resource_parse_asic_id(init_params->asic_id);
- dc_ctx->dce_version = dc_version;
+ dc_ctx->dce_version = resource_parse_asic_id(init_params->asic_id);
dc_ctx->perf_trace = dc_perf_trace_create();
if (!dc_ctx->perf_trace) {
@@ -1120,6 +1117,33 @@ static void phantom_pipe_blank(
hws->funcs.wait_for_blank_complete(opp);
}
+static void dc_update_viusal_confirm_color(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
+{
+ if (dc->ctx->dce_version >= DCN_VERSION_1_0) {
+ memset(&pipe_ctx->visual_confirm_color, 0, sizeof(struct tg_color));
+
+ if (dc->debug.visual_confirm == VISUAL_CONFIRM_HDR)
+ get_hdr_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SURFACE)
+ get_surface_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SWIZZLE)
+ get_surface_tile_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else {
+ if (dc->ctx->dce_version < DCN_VERSION_2_0)
+ color_space_to_black_color(
+ dc, pipe_ctx->stream->output_color_space, &(pipe_ctx->visual_confirm_color));
+ }
+ if (dc->ctx->dce_version >= DCN_VERSION_2_0) {
+ if (dc->debug.visual_confirm == VISUAL_CONFIRM_MPCTREE)
+ get_mpctree_visual_confirm_color(pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP)
+ get_subvp_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ else if (dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH)
+ get_mclk_switch_visual_confirm_color(dc, context, pipe_ctx, &(pipe_ctx->visual_confirm_color));
+ }
+ }
+}
+
static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
{
int i, j;
@@ -1190,6 +1214,9 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
+ if (pipe->stream && pipe->plane_state)
+ dc_update_viusal_confirm_color(dc, context, pipe);
+
if (dc->hwss.apply_ctx_for_surface) {
apply_ctx_interdependent_lock(dc, dc->current_state, old_stream, true);
dc->hwss.apply_ctx_for_surface(dc, old_stream, 0, dangling_context);
@@ -1269,7 +1296,7 @@ static void disable_vbios_mode_if_required(
if (pix_clk_100hz != requested_pix_clk_100hz) {
dc->link_srv->set_dpms_off(pipe);
- pipe->stream->dpms_off = false;
+ pipe->stream->dpms_off = true;
}
}
}
@@ -1981,6 +2008,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
return result;
}
+static bool commit_minimal_transition_state(struct dc *dc,
+ struct dc_state *transition_base_context);
+
/**
* dc_commit_streams - Commit current stream state
*
@@ -2002,6 +2032,8 @@ enum dc_status dc_commit_streams(struct dc *dc,
struct dc_state *context;
enum dc_status res = DC_OK;
struct dc_validation_set set[MAX_STREAMS] = {0};
+ struct pipe_ctx *pipe;
+ bool handle_exit_odm2to1 = false;
if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW)
return res;
@@ -2026,6 +2058,22 @@ enum dc_status dc_commit_streams(struct dc *dc,
}
}
+ /* Check for case where we are going from odm 2:1 to max
+ * pipe scenario. For these cases, we will call
+ * commit_minimal_transition_state() to exit out of odm 2:1
+ * first before processing new streams
+ */
+ if (stream_count == dc->res_pool->pipe_count) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe->next_odm_pipe)
+ handle_exit_odm2to1 = true;
+ }
+ }
+
+ if (handle_exit_odm2to1)
+ res = commit_minimal_transition_state(dc, dc->current_state);
+
context = dc_create_state(dc);
if (!context)
goto context_alloc_fail;
@@ -2483,9 +2531,6 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
enum surface_update_type overall_type = UPDATE_TYPE_FAST;
union surface_update_flags *update_flags = &u->surface->update_flags;
- if (u->flip_addr)
- update_flags->bits.addr_update = 1;
-
if (!is_surface_in_context(context, u->surface) || u->surface->force_full_update) {
update_flags->raw = 0xFFFFFFFF;
return UPDATE_TYPE_FULL;
@@ -2544,15 +2589,19 @@ static enum surface_update_type det_surface_update(const struct dc *dc,
elevate_update_type(&overall_type, type);
}
- if (update_flags->bits.input_csc_change
- || update_flags->bits.coeff_reduction_change
- || update_flags->bits.lut_3d
- || update_flags->bits.gamma_change
- || update_flags->bits.gamut_remap_change) {
+ if (update_flags->bits.lut_3d) {
type = UPDATE_TYPE_FULL;
elevate_update_type(&overall_type, type);
}
+ if (dc->debug.enable_legacy_fast_update &&
+ (update_flags->bits.gamma_change ||
+ update_flags->bits.gamut_remap_change ||
+ update_flags->bits.input_csc_change ||
+ update_flags->bits.coeff_reduction_change)) {
+ type = UPDATE_TYPE_FULL;
+ elevate_update_type(&overall_type, type);
+ }
return overall_type;
}
@@ -2585,7 +2634,7 @@ static enum surface_update_type check_update_surfaces_for_stream(
stream_update->integer_scaling_update)
su_flags->bits.scaling = 1;
- if (stream_update->out_transfer_func)
+ if (dc->debug.enable_legacy_fast_update && stream_update->out_transfer_func)
su_flags->bits.out_tf = 1;
if (stream_update->abm_level)
@@ -2605,14 +2654,23 @@ static enum surface_update_type check_update_surfaces_for_stream(
if (stream_update->mst_bw_update)
su_flags->bits.mst_bw = 1;
- if (stream_update->crtc_timing_adjust && dc_extended_blank_supported(dc))
- su_flags->bits.crtc_timing_adjust = 1;
+
+ if (stream_update->stream && stream_update->stream->freesync_on_desktop &&
+ (stream_update->vrr_infopacket || stream_update->allow_freesync ||
+ stream_update->vrr_active_variable || stream_update->vrr_active_fixed))
+ su_flags->bits.fams_changed = 1;
if (su_flags->raw != 0)
overall_type = UPDATE_TYPE_FULL;
if (stream_update->output_csc_transform || stream_update->output_color_space)
su_flags->bits.out_csc = 1;
+
+ /* Output transfer function changes do not require bandwidth recalculation,
+ * so don't trigger a full update
+ */
+ if (!dc->debug.enable_legacy_fast_update && stream_update->out_transfer_func)
+ su_flags->bits.out_tf = 1;
}
for (i = 0 ; i < surface_count; i++) {
@@ -2965,6 +3023,9 @@ static void copy_stream_update_to_stream(struct dc *dc,
if (update->vrr_active_variable)
stream->vrr_active_variable = *update->vrr_active_variable;
+ if (update->vrr_active_fixed)
+ stream->vrr_active_fixed = *update->vrr_active_fixed;
+
if (update->crtc_timing_adjust)
stream->adjust = *update->crtc_timing_adjust;
@@ -3269,6 +3330,13 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc->hwss.prepare_bandwidth(dc, dc->current_state);
dc->link_srv->set_dpms_on(dc->current_state, pipe_ctx);
}
+ } else if (pipe_ctx->stream->link->wa_flags.blank_stream_on_ocs_change && stream_update->output_color_space
+ && !stream->dpms_off && dc_is_dp_signal(pipe_ctx->stream->signal)) {
+ /*
+ * Workaround for firmware issue in some receivers where they don't pick up
+ * correct output color space unless DP link is disabled/re-enabled
+ */
+ dc->link_srv->set_dpms_on(dc->current_state, pipe_ctx);
}
if (stream_update->abm_level && pipe_ctx->stream_res.abm) {
@@ -3309,7 +3377,6 @@ void dc_dmub_update_dirty_rect(struct dc *dc,
struct dc_state *context)
{
union dmub_rb_cmd cmd;
- struct dc_context *dc_ctx = dc->ctx;
struct dmub_cmd_update_dirty_rect_data *update_dirty_rect;
unsigned int i, j;
unsigned int panel_inst = 0;
@@ -3350,10 +3417,168 @@ void dc_dmub_update_dirty_rect(struct dc *dc,
update_dirty_rect->panel_inst = panel_inst;
update_dirty_rect->pipe_idx = j;
- dc_dmub_srv_cmd_queue(dc_ctx->dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dc_ctx->dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_NO_WAIT);
+ }
+ }
+}
+
+static void build_dmub_update_dirty_rect(
+ struct dc *dc,
+ int surface_count,
+ struct dc_stream_state *stream,
+ struct dc_surface_update *srf_updates,
+ struct dc_state *context,
+ struct dc_dmub_cmd dc_dmub_cmd[],
+ unsigned int *dmub_cmd_count)
+{
+ union dmub_rb_cmd cmd;
+ struct dmub_cmd_update_dirty_rect_data *update_dirty_rect;
+ unsigned int i, j;
+ unsigned int panel_inst = 0;
+
+ if (!dc_dmub_should_send_dirty_rect_cmd(dc, stream))
+ return;
+
+ if (!dc_get_edp_link_panel_inst(dc, stream->link, &panel_inst))
+ return;
+
+ memset(&cmd, 0x0, sizeof(cmd));
+ cmd.update_dirty_rect.header.type = DMUB_CMD__UPDATE_DIRTY_RECT;
+ cmd.update_dirty_rect.header.sub_type = 0;
+ cmd.update_dirty_rect.header.payload_bytes =
+ sizeof(cmd.update_dirty_rect) -
+ sizeof(cmd.update_dirty_rect.header);
+ update_dirty_rect = &cmd.update_dirty_rect.update_dirty_rect_data;
+ for (i = 0; i < surface_count; i++) {
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
+ const struct dc_flip_addrs *flip_addr = srf_updates[i].flip_addr;
+
+ if (!srf_updates[i].surface || !flip_addr)
+ continue;
+ /* Do not send in immediate flip mode */
+ if (srf_updates[i].surface->flip_immediate)
+ continue;
+ update_dirty_rect->cmd_version = DMUB_CMD_PSR_CONTROL_VERSION_1;
+ update_dirty_rect->dirty_rect_count = flip_addr->dirty_rect_count;
+ memcpy(update_dirty_rect->src_dirty_rects, flip_addr->dirty_rects,
+ sizeof(flip_addr->dirty_rects));
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+ if (pipe_ctx->stream != stream)
+ continue;
+ if (pipe_ctx->plane_state != plane_state)
+ continue;
+ update_dirty_rect->panel_inst = panel_inst;
+ update_dirty_rect->pipe_idx = j;
+ dc_dmub_cmd[*dmub_cmd_count].dmub_cmd = cmd;
+ dc_dmub_cmd[*dmub_cmd_count].wait_type = DM_DMUB_WAIT_TYPE_NO_WAIT;
+ (*dmub_cmd_count)++;
+ }
+ }
+}
+
+
+/**
+ * ************************************************************************************************
+ * build_dmub_cmd_list: Build an array of DMCUB commands to be sent to DMCUB
+ *
+ * @param [in]: dc: Current DC state
+ * @param [in]: srf_updates: Array of surface updates
+ * @param [in]: surface_count: Number of surfaces that have an updated
+ * @param [in]: stream: Correponding stream to be updated in the current flip
+ * @param [in]: context: New DC state to be programmed
+ *
+ * @param [out]: dc_dmub_cmd: Array of DMCUB commands to be sent to DMCUB
+ * @param [out]: dmub_cmd_count: Count indicating the number of DMCUB commands in dc_dmub_cmd array
+ *
+ * This function builds an array of DMCUB commands to be sent to DMCUB. This function is required
+ * to build an array of commands and have them sent while the OTG lock is acquired.
+ *
+ * @return: void
+ * ************************************************************************************************
+ */
+static void build_dmub_cmd_list(struct dc *dc,
+ struct dc_surface_update *srf_updates,
+ int surface_count,
+ struct dc_stream_state *stream,
+ struct dc_state *context,
+ struct dc_dmub_cmd dc_dmub_cmd[],
+ unsigned int *dmub_cmd_count)
+{
+ // Initialize cmd count to 0
+ *dmub_cmd_count = 0;
+ build_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, context, dc_dmub_cmd, dmub_cmd_count);
+}
+
+static void commit_planes_for_stream_fast(struct dc *dc,
+ struct dc_surface_update *srf_updates,
+ int surface_count,
+ struct dc_stream_state *stream,
+ struct dc_stream_update *stream_update,
+ enum surface_update_type update_type,
+ struct dc_state *context)
+{
+ int i, j;
+ struct pipe_ctx *top_pipe_to_program = NULL;
+ dc_z10_restore(dc);
+
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+ if (!pipe_ctx->top_pipe &&
+ !pipe_ctx->prev_odm_pipe &&
+ pipe_ctx->stream &&
+ pipe_ctx->stream == stream) {
+ top_pipe_to_program = pipe_ctx;
+ }
+ }
+
+ if (dc->debug.visual_confirm) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream && pipe->plane_state)
+ dc_update_viusal_confirm_color(dc, context, pipe);
+ }
+ }
+
+ for (i = 0; i < surface_count; i++) {
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
+ /*set logical flag for lock/unlock use*/
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+
+ if (!pipe_ctx->plane_state)
+ continue;
+ if (should_update_pipe_for_plane(context, pipe_ctx, plane_state))
+ continue;
+ pipe_ctx->plane_state->triplebuffer_flips = false;
+ if (update_type == UPDATE_TYPE_FAST &&
+ dc->hwss.program_triplebuffer &&
+ !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) {
+ /*triple buffer for VUpdate only*/
+ pipe_ctx->plane_state->triplebuffer_flips = true;
+ }
}
}
+
+ build_dmub_cmd_list(dc,
+ srf_updates,
+ surface_count,
+ stream,
+ context,
+ context->dc_dmub_cmd,
+ &(context->dmub_cmd_count));
+ hwss_build_fast_sequence(dc,
+ context->dc_dmub_cmd,
+ context->dmub_cmd_count,
+ context->block_sequence,
+ &(context->block_sequence_steps),
+ top_pipe_to_program);
+ hwss_execute_sequence(dc,
+ context->block_sequence,
+ context->block_sequence_steps);
}
static void commit_planes_for_stream(struct dc *dc,
@@ -3393,21 +3618,6 @@ static void commit_planes_for_stream(struct dc *dc,
}
}
- if (get_seamless_boot_stream_count(context) > 0 && surface_count > 0) {
- /* Optimize seamless boot flag keeps clocks and watermarks high until
- * first flip. After first flip, optimization is required to lower
- * bandwidth. Important to note that it is expected UEFI will
- * only light up a single display on POST, therefore we only expect
- * one stream with seamless boot flag set.
- */
- if (stream->apply_seamless_boot_optimization) {
- stream->apply_seamless_boot_optimization = false;
-
- if (get_seamless_boot_stream_count(context) == 0)
- dc->optimized_required = true;
- }
- }
-
if (update_type == UPDATE_TYPE_FULL) {
dc_allow_idle_optimizations(dc, false);
@@ -3449,6 +3659,14 @@ static void commit_planes_for_stream(struct dc *dc,
}
}
+ if (dc->debug.visual_confirm)
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream && pipe->plane_state)
+ dc_update_viusal_confirm_color(dc, context, pipe);
+ }
+
if (stream->test_pattern.type != DP_TEST_PATTERN_VIDEO_MODE) {
struct pipe_ctx *mpcc_pipe;
struct pipe_ctx *odm_pipe;
@@ -3532,43 +3750,40 @@ static void commit_planes_for_stream(struct dc *dc,
for (j = 0; j < dc->res_pool->pipe_count; j++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
- if (dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP &&
+ if ((dc->debug.visual_confirm == VISUAL_CONFIRM_SUBVP ||
+ dc->debug.visual_confirm == VISUAL_CONFIRM_MCLK_SWITCH) &&
pipe_ctx->stream && pipe_ctx->plane_state) {
- /* Only update visual confirm for SUBVP here.
+ /* Only update visual confirm for SUBVP and Mclk switching here.
* The bar appears on all pipes, so we need to update the bar on all displays,
* so the information doesn't get stale.
*/
- struct mpcc_blnd_cfg blnd_cfg = { 0 };
-
- dc->hwss.update_visual_confirm_color(dc, pipe_ctx, &blnd_cfg.black_color,
+ dc->hwss.update_visual_confirm_color(dc, pipe_ctx,
pipe_ctx->plane_res.hubp->inst);
}
}
}
- if (!IS_DIAG_DC(dc->ctx->dce_environment)) {
- for (i = 0; i < surface_count; i++) {
- struct dc_plane_state *plane_state = srf_updates[i].surface;
- /*set logical flag for lock/unlock use*/
- for (j = 0; j < dc->res_pool->pipe_count; j++) {
- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
- if (!pipe_ctx->plane_state)
- continue;
- if (should_update_pipe_for_plane(context, pipe_ctx, plane_state))
- continue;
- pipe_ctx->plane_state->triplebuffer_flips = false;
- if (update_type == UPDATE_TYPE_FAST &&
- dc->hwss.program_triplebuffer != NULL &&
- !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) {
- /*triple buffer for VUpdate only*/
- pipe_ctx->plane_state->triplebuffer_flips = true;
- }
- }
- if (update_type == UPDATE_TYPE_FULL) {
- /* force vsync flip when reconfiguring pipes to prevent underflow */
- plane_state->flip_immediate = false;
+ for (i = 0; i < surface_count; i++) {
+ struct dc_plane_state *plane_state = srf_updates[i].surface;
+ /*set logical flag for lock/unlock use*/
+ for (j = 0; j < dc->res_pool->pipe_count; j++) {
+ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j];
+ if (!pipe_ctx->plane_state)
+ continue;
+ if (should_update_pipe_for_plane(context, pipe_ctx, plane_state))
+ continue;
+ pipe_ctx->plane_state->triplebuffer_flips = false;
+ if (update_type == UPDATE_TYPE_FAST &&
+ dc->hwss.program_triplebuffer != NULL &&
+ !pipe_ctx->plane_state->flip_immediate && dc->debug.enable_tri_buf) {
+ /*triple buffer for VUpdate only*/
+ pipe_ctx->plane_state->triplebuffer_flips = true;
}
}
+ if (update_type == UPDATE_TYPE_FULL) {
+ /* force vsync flip when reconfiguring pipes to prevent underflow */
+ plane_state->flip_immediate = false;
+ }
}
// Update Type FULL, Surface updates
@@ -3872,6 +4087,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
unsigned int i, j;
unsigned int pipe_in_use = 0;
bool subvp_in_use = false;
+ bool odm_in_use = false;
if (!transition_context)
return false;
@@ -3900,6 +4116,18 @@ static bool commit_minimal_transition_state(struct dc *dc,
}
}
+ /* If ODM is enabled and we are adding or removing planes from any ODM
+ * pipe, we must use the minimal transition.
+ */
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream && pipe->next_odm_pipe) {
+ odm_in_use = true;
+ break;
+ }
+ }
+
/* When the OS add a new surface if we have been used all of pipes with odm combine
* and mpc split feature, it need use commit_minimal_transition_state to transition safely.
* After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need
@@ -3908,7 +4136,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
* Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially
* enter/exit MPO when DCN still have enough resources.
*/
- if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use) {
+ if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use && !odm_in_use) {
dc_release_state(transition_context);
return true;
}
@@ -3972,6 +4200,43 @@ static bool commit_minimal_transition_state(struct dc *dc,
return true;
}
+/**
+ * *******************************************************************************
+ * update_seamless_boot_flags: Helper function for updating seamless boot flags
+ *
+ * @param [in]: dc: Current DC state
+ * @param [in]: context: New DC state to be programmed
+ * @param [in]: surface_count: Number of surfaces that have an updated
+ * @param [in]: stream: Correponding stream to be updated in the current flip
+ *
+ * Updating seamless boot flags do not need to be part of the commit sequence. This
+ * helper function will update the seamless boot flags on each flip (if required)
+ * outside of the HW commit sequence (fast or slow).
+ *
+ * @return: void
+ * *******************************************************************************
+ */
+static void update_seamless_boot_flags(struct dc *dc,
+ struct dc_state *context,
+ int surface_count,
+ struct dc_stream_state *stream)
+{
+ if (get_seamless_boot_stream_count(context) > 0 && surface_count > 0) {
+ /* Optimize seamless boot flag keeps clocks and watermarks high until
+ * first flip. After first flip, optimization is required to lower
+ * bandwidth. Important to note that it is expected UEFI will
+ * only light up a single display on POST, therefore we only expect
+ * one stream with seamless boot flag set.
+ */
+ if (stream->apply_seamless_boot_optimization) {
+ stream->apply_seamless_boot_optimization = false;
+
+ if (get_seamless_boot_stream_count(context) == 0)
+ dc->optimized_required = true;
+ }
+ }
+}
+
bool dc_update_planes_and_stream(struct dc *dc,
struct dc_surface_update *srf_updates, int surface_count,
struct dc_stream_state *stream,
@@ -4038,14 +4303,25 @@ bool dc_update_planes_and_stream(struct dc *dc,
update_type = UPDATE_TYPE_FULL;
}
- commit_planes_for_stream(
- dc,
- srf_updates,
- surface_count,
- stream,
- stream_update,
- update_type,
- context);
+ update_seamless_boot_flags(dc, context, surface_count, stream);
+ if (!dc->debug.enable_legacy_fast_update && update_type == UPDATE_TYPE_FAST) {
+ commit_planes_for_stream_fast(dc,
+ srf_updates,
+ surface_count,
+ stream,
+ stream_update,
+ update_type,
+ context);
+ } else {
+ commit_planes_for_stream(
+ dc,
+ srf_updates,
+ surface_count,
+ stream,
+ stream_update,
+ update_type,
+ context);
+ }
if (dc->current_state != context) {
@@ -4170,7 +4446,17 @@ void dc_commit_updates_for_stream(struct dc *dc,
TRACE_DC_PIPE_STATE(pipe_ctx, i, MAX_PIPES);
- commit_planes_for_stream(
+ update_seamless_boot_flags(dc, context, surface_count, stream);
+ if (!dc->debug.enable_legacy_fast_update && update_type == UPDATE_TYPE_FAST) {
+ commit_planes_for_stream_fast(dc,
+ srf_updates,
+ surface_count,
+ stream,
+ stream_update,
+ update_type,
+ context);
+ } else {
+ commit_planes_for_stream(
dc,
srf_updates,
surface_count,
@@ -4178,6 +4464,7 @@ void dc_commit_updates_for_stream(struct dc *dc,
stream_update,
update_type,
context);
+ }
/*update current_State*/
if (dc->current_state != context) {
@@ -4264,9 +4551,6 @@ void dc_set_power_state(
dc_z10_restore(dc);
- if (dc->ctx->dmub_srv)
- dc_dmub_srv_wait_phy_init(dc->ctx->dmub_srv);
-
dc->hwss.init_hw(dc);
if (dc->hwss.init_sys_ctx != NULL &&
@@ -4606,7 +4890,6 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc,
{
uint8_t action;
union dmub_rb_cmd cmd = {0};
- struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
ASSERT(payload->length <= 16);
@@ -4654,9 +4937,7 @@ bool dc_process_dmub_aux_transfer_async(struct dc *dc,
);
}
- dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dmub_srv);
- dc_dmub_srv_wait_idle(dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
return true;
}
@@ -4700,7 +4981,6 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
struct dmub_notification *notify)
{
union dmub_rb_cmd cmd = {0};
- struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
bool is_cmd_complete = true;
/* prepare SET_CONFIG command */
@@ -4711,7 +4991,7 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
cmd.set_config_access.set_config_control.cmd_pkt.msg_type = payload->msg_type;
cmd.set_config_access.set_config_control.cmd_pkt.msg_data = payload->msg_data;
- if (!dc_dmub_srv_cmd_with_reply_data(dmub_srv, &cmd)) {
+ if (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
/* command is not processed by dmub */
notify->sc_status = SET_CONFIG_UNKNOWN_ERROR;
return is_cmd_complete;
@@ -4746,7 +5026,6 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
uint8_t *mst_slots_in_use)
{
union dmub_rb_cmd cmd = {0};
- struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
/* prepare MST_ALLOC_SLOTS command */
cmd.set_mst_alloc_slots.header.type = DMUB_CMD__DPIA;
@@ -4755,7 +5034,7 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
cmd.set_mst_alloc_slots.mst_slots_control.instance = dc->links[link_index]->ddc_hw_inst;
cmd.set_mst_alloc_slots.mst_slots_control.mst_alloc_slots = mst_alloc_slots;
- if (!dc_dmub_srv_cmd_with_reply_data(dmub_srv, &cmd))
+ if (!dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY))
/* command is not processed by dmub */
return DC_ERROR_UNEXPECTED;
@@ -4789,19 +5068,28 @@ void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
uint32_t hpd_int_enable)
{
union dmub_rb_cmd cmd = {0};
- struct dc_dmub_srv *dmub_srv = dc->ctx->dmub_srv;
cmd.dpia_hpd_int_enable.header.type = DMUB_CMD__DPIA_HPD_INT_ENABLE;
cmd.dpia_hpd_int_enable.enable = hpd_int_enable;
- dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
- dc_dmub_srv_cmd_execute(dmub_srv);
- dc_dmub_srv_wait_idle(dmub_srv);
+ dm_execute_dmub_cmd(dc->ctx, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
DC_LOG_DEBUG("%s: hpd_int_enable(%d)\n", __func__, hpd_int_enable);
}
/**
+ * dc_print_dmub_diagnostic_data - Print DMUB diagnostic data for debugging
+ *
+ * @dc: [in] dc structure
+ *
+ *
+ */
+void dc_print_dmub_diagnostic_data(const struct dc *dc)
+{
+ dc_dmub_srv_log_diagnostic_data(dc->ctx->dmub_srv);
+}
+
+/**
* dc_disable_accelerated_mode - disable accelerated mode
* @dc: dc structure
*/
@@ -4860,21 +5148,3 @@ void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bo
if (pipe->stream_res.abm && pipe->stream_res.abm->funcs->set_abm_pause)
pipe->stream_res.abm->funcs->set_abm_pause(pipe->stream_res.abm, !enable, i, pipe->stream_res.tg->inst);
}
-
-/**
- * dc_extended_blank_supported - Decide whether extended blank is supported
- *
- * @dc: [in] Current DC state
- *
- * Extended blank is a freesync optimization feature to be enabled in the
- * future. During the extra vblank period gained from freesync, we have the
- * ability to enter z9/z10.
- *
- * Return:
- * Indicate whether extended blank is supported (%true or %false)
- */
-bool dc_extended_blank_supported(struct dc *dc)
-{
- return dc->debug.extended_blank_optimization && !dc->debug.disable_z10
- && dc->caps.zstate_support && dc->caps.is_apu;
-}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 2acbf692193f..182c42c63bc5 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -27,6 +27,8 @@
#include "core_types.h"
#include "timing_generator.h"
#include "hw_sequencer.h"
+#include "hw_sequencer_private.h"
+#include "basics/dc_common.h"
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
@@ -421,6 +423,7 @@ void get_hdr_visual_confirm_color(
void get_subvp_visual_confirm_color(
struct dc *dc,
+ struct dc_state *context,
struct pipe_ctx *pipe_ctx,
struct tg_color *color)
{
@@ -428,15 +431,17 @@ void get_subvp_visual_confirm_color(
bool enable_subvp = false;
int i;
- if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx)
+ if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !context)
return;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
if (pipe->stream && pipe->stream->mall_stream_config.paired_stream &&
pipe->stream->mall_stream_config.type == SUBVP_MAIN) {
/* SubVP enable - red */
+ color->color_g_y = 0;
+ color->color_b_cb = 0;
color->color_r_cr = color_value;
enable_subvp = true;
@@ -448,12 +453,304 @@ void get_subvp_visual_confirm_color(
if (enable_subvp && pipe_ctx->stream->mall_stream_config.type == SUBVP_NONE) {
color->color_r_cr = 0;
- if (pipe_ctx->stream->ignore_msa_timing_param == 1)
+ if (pipe_ctx->stream->allow_freesync == 1) {
/* SubVP enable and DRR on - green */
+ color->color_b_cb = 0;
color->color_g_y = color_value;
- else
+ } else {
/* SubVP enable and No DRR - blue */
+ color->color_g_y = 0;
+ color->color_b_cb = color_value;
+ }
+ }
+}
+
+void hwss_build_fast_sequence(struct dc *dc,
+ struct dc_dmub_cmd *dc_dmub_cmd,
+ unsigned int dmub_cmd_count,
+ struct block_sequence block_sequence[],
+ int *num_steps,
+ struct pipe_ctx *pipe_ctx)
+{
+ struct dc_plane_state *plane = pipe_ctx->plane_state;
+ struct dc_stream_state *stream = pipe_ctx->stream;
+ struct dce_hwseq *hws = dc->hwseq;
+ struct pipe_ctx *current_pipe = NULL;
+ struct pipe_ctx *current_mpc_pipe = NULL;
+ unsigned int i = 0;
+
+ *num_steps = 0; // Initialize to 0
+
+ if (!plane || !stream)
+ return;
+
+ if (dc->hwss.subvp_pipe_control_lock_fast) {
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = true;
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
+ block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
+ (*num_steps)++;
+ }
+ if (dc->hwss.pipe_control_lock) {
+ block_sequence[*num_steps].params.pipe_control_lock_params.dc = dc;
+ block_sequence[*num_steps].params.pipe_control_lock_params.lock = true;
+ block_sequence[*num_steps].params.pipe_control_lock_params.pipe_ctx = pipe_ctx;
+ block_sequence[*num_steps].func = OPTC_PIPE_CONTROL_LOCK;
+ (*num_steps)++;
+ }
+
+ for (i = 0; i < dmub_cmd_count; i++) {
+ block_sequence[*num_steps].params.send_dmcub_cmd_params.ctx = dc->ctx;
+ block_sequence[*num_steps].params.send_dmcub_cmd_params.cmd = &(dc_dmub_cmd[i].dmub_cmd);
+ block_sequence[*num_steps].params.send_dmcub_cmd_params.wait_type = dc_dmub_cmd[i].wait_type;
+ block_sequence[*num_steps].func = DMUB_SEND_DMCUB_CMD;
+ (*num_steps)++;
+ }
+
+ current_pipe = pipe_ctx;
+ while (current_pipe) {
+ current_mpc_pipe = current_pipe;
+ while (current_mpc_pipe) {
+ if (dc->hwss.set_flip_control_gsl && current_mpc_pipe->plane_state && current_mpc_pipe->plane_state->update_flags.raw) {
+ block_sequence[*num_steps].params.set_flip_control_gsl_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].params.set_flip_control_gsl_params.flip_immediate = current_mpc_pipe->plane_state->flip_immediate;
+ block_sequence[*num_steps].func = HUBP_SET_FLIP_CONTROL_GSL;
+ (*num_steps)++;
+ }
+ if (dc->hwss.program_triplebuffer && dc->debug.enable_tri_buf && current_mpc_pipe->plane_state->update_flags.raw) {
+ block_sequence[*num_steps].params.program_triplebuffer_params.dc = dc;
+ block_sequence[*num_steps].params.program_triplebuffer_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].params.program_triplebuffer_params.enableTripleBuffer = current_mpc_pipe->plane_state->triplebuffer_flips;
+ block_sequence[*num_steps].func = HUBP_PROGRAM_TRIPLEBUFFER;
+ (*num_steps)++;
+ }
+ if (dc->hwss.update_plane_addr && current_mpc_pipe->plane_state->update_flags.bits.addr_update) {
+ block_sequence[*num_steps].params.update_plane_addr_params.dc = dc;
+ block_sequence[*num_steps].params.update_plane_addr_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = HUBP_UPDATE_PLANE_ADDR;
+ (*num_steps)++;
+ }
+
+ if (hws->funcs.set_input_transfer_func && current_mpc_pipe->plane_state->update_flags.bits.gamma_change) {
+ block_sequence[*num_steps].params.set_input_transfer_func_params.dc = dc;
+ block_sequence[*num_steps].params.set_input_transfer_func_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].params.set_input_transfer_func_params.plane_state = current_mpc_pipe->plane_state;
+ block_sequence[*num_steps].func = DPP_SET_INPUT_TRANSFER_FUNC;
+ (*num_steps)++;
+ }
+
+ if (dc->hwss.program_gamut_remap && current_mpc_pipe->plane_state->update_flags.bits.gamut_remap_change) {
+ block_sequence[*num_steps].params.program_gamut_remap_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = DPP_PROGRAM_GAMUT_REMAP;
+ (*num_steps)++;
+ }
+ if (current_mpc_pipe->plane_state->update_flags.bits.input_csc_change) {
+ block_sequence[*num_steps].params.setup_dpp_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = DPP_SETUP_DPP;
+ (*num_steps)++;
+ }
+ if (current_mpc_pipe->plane_state->update_flags.bits.coeff_reduction_change) {
+ block_sequence[*num_steps].params.program_bias_and_scale_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = DPP_PROGRAM_BIAS_AND_SCALE;
+ (*num_steps)++;
+ }
+ if (hws->funcs.set_output_transfer_func && current_mpc_pipe->stream->update_flags.bits.out_tf) {
+ block_sequence[*num_steps].params.set_output_transfer_func_params.dc = dc;
+ block_sequence[*num_steps].params.set_output_transfer_func_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].params.set_output_transfer_func_params.stream = current_mpc_pipe->stream;
+ block_sequence[*num_steps].func = DPP_SET_OUTPUT_TRANSFER_FUNC;
+ (*num_steps)++;
+ }
+
+ current_mpc_pipe = current_mpc_pipe->bottom_pipe;
+ }
+ current_pipe = current_pipe->next_odm_pipe;
+ }
+
+ if (dc->hwss.pipe_control_lock) {
+ block_sequence[*num_steps].params.pipe_control_lock_params.dc = dc;
+ block_sequence[*num_steps].params.pipe_control_lock_params.lock = false;
+ block_sequence[*num_steps].params.pipe_control_lock_params.pipe_ctx = pipe_ctx;
+ block_sequence[*num_steps].func = OPTC_PIPE_CONTROL_LOCK;
+ (*num_steps)++;
+ }
+ if (dc->hwss.subvp_pipe_control_lock_fast) {
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.dc = dc;
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.lock = false;
+ block_sequence[*num_steps].params.subvp_pipe_control_lock_fast_params.pipe_ctx = pipe_ctx;
+ block_sequence[*num_steps].func = DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST;
+ (*num_steps)++;
+ }
+
+ current_pipe = pipe_ctx;
+ while (current_pipe) {
+ current_mpc_pipe = current_pipe;
+
+ while (current_mpc_pipe) {
+ if (!current_mpc_pipe->bottom_pipe && !pipe_ctx->next_odm_pipe &&
+ current_mpc_pipe->stream && current_mpc_pipe->plane_state &&
+ current_mpc_pipe->plane_state->update_flags.bits.addr_update &&
+ !current_mpc_pipe->plane_state->skip_manual_trigger) {
+ block_sequence[*num_steps].params.program_manual_trigger_params.pipe_ctx = current_mpc_pipe;
+ block_sequence[*num_steps].func = OPTC_PROGRAM_MANUAL_TRIGGER;
+ (*num_steps)++;
+ }
+ current_mpc_pipe = current_mpc_pipe->bottom_pipe;
+ }
+ current_pipe = current_pipe->next_odm_pipe;
+ }
+}
+
+void hwss_execute_sequence(struct dc *dc,
+ struct block_sequence block_sequence[],
+ int num_steps)
+{
+ unsigned int i;
+ union block_sequence_params *params;
+ struct dce_hwseq *hws = dc->hwseq;
+
+ for (i = 0; i < num_steps; i++) {
+ params = &(block_sequence[i].params);
+ switch (block_sequence[i].func) {
+
+ case DMUB_SUBVP_PIPE_CONTROL_LOCK_FAST:
+ dc->hwss.subvp_pipe_control_lock_fast(params);
+ break;
+ case OPTC_PIPE_CONTROL_LOCK:
+ dc->hwss.pipe_control_lock(params->pipe_control_lock_params.dc,
+ params->pipe_control_lock_params.pipe_ctx,
+ params->pipe_control_lock_params.lock);
+ break;
+ case HUBP_SET_FLIP_CONTROL_GSL:
+ dc->hwss.set_flip_control_gsl(params->set_flip_control_gsl_params.pipe_ctx,
+ params->set_flip_control_gsl_params.flip_immediate);
+ break;
+ case HUBP_PROGRAM_TRIPLEBUFFER:
+ dc->hwss.program_triplebuffer(params->program_triplebuffer_params.dc,
+ params->program_triplebuffer_params.pipe_ctx,
+ params->program_triplebuffer_params.enableTripleBuffer);
+ break;
+ case HUBP_UPDATE_PLANE_ADDR:
+ dc->hwss.update_plane_addr(params->update_plane_addr_params.dc,
+ params->update_plane_addr_params.pipe_ctx);
+ break;
+ case DPP_SET_INPUT_TRANSFER_FUNC:
+ hws->funcs.set_input_transfer_func(params->set_input_transfer_func_params.dc,
+ params->set_input_transfer_func_params.pipe_ctx,
+ params->set_input_transfer_func_params.plane_state);
+ break;
+ case DPP_PROGRAM_GAMUT_REMAP:
+ dc->hwss.program_gamut_remap(params->program_gamut_remap_params.pipe_ctx);
+ break;
+ case DPP_SETUP_DPP:
+ hwss_setup_dpp(params);
+ break;
+ case DPP_PROGRAM_BIAS_AND_SCALE:
+ hwss_program_bias_and_scale(params);
+ break;
+ case OPTC_PROGRAM_MANUAL_TRIGGER:
+ hwss_program_manual_trigger(params);
+ break;
+ case DPP_SET_OUTPUT_TRANSFER_FUNC:
+ hws->funcs.set_output_transfer_func(params->set_output_transfer_func_params.dc,
+ params->set_output_transfer_func_params.pipe_ctx,
+ params->set_output_transfer_func_params.stream);
+ break;
+ case MPC_UPDATE_VISUAL_CONFIRM:
+ dc->hwss.update_visual_confirm_color(params->update_visual_confirm_params.dc,
+ params->update_visual_confirm_params.pipe_ctx,
+ params->update_visual_confirm_params.mpcc_id);
+ break;
+ case DMUB_SEND_DMCUB_CMD:
+ hwss_send_dmcub_cmd(params);
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+ }
+}
+
+void hwss_send_dmcub_cmd(union block_sequence_params *params)
+{
+ struct dc_context *ctx = params->send_dmcub_cmd_params.ctx;
+ union dmub_rb_cmd *cmd = params->send_dmcub_cmd_params.cmd;
+ enum dm_dmub_wait_type wait_type = params->send_dmcub_cmd_params.wait_type;
+
+ dm_execute_dmub_cmd(ctx, cmd, wait_type);
+}
+
+void hwss_program_manual_trigger(union block_sequence_params *params)
+{
+ struct pipe_ctx *pipe_ctx = params->program_manual_trigger_params.pipe_ctx;
+
+ if (pipe_ctx->stream_res.tg->funcs->program_manual_trigger)
+ pipe_ctx->stream_res.tg->funcs->program_manual_trigger(pipe_ctx->stream_res.tg);
+}
+
+void hwss_setup_dpp(union block_sequence_params *params)
+{
+ struct pipe_ctx *pipe_ctx = params->setup_dpp_params.pipe_ctx;
+ struct dpp *dpp = pipe_ctx->plane_res.dpp;
+ struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+
+ if (dpp && dpp->funcs->dpp_setup) {
+ // program the input csc
+ dpp->funcs->dpp_setup(dpp,
+ plane_state->format,
+ EXPANSION_MODE_ZERO,
+ plane_state->input_csc_color_matrix,
+ plane_state->color_space,
+ NULL);
+ }
+}
+
+void hwss_program_bias_and_scale(union block_sequence_params *params)
+{
+ struct pipe_ctx *pipe_ctx = params->program_bias_and_scale_params.pipe_ctx;
+ struct dpp *dpp = pipe_ctx->plane_res.dpp;
+ struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+ struct dc_bias_and_scale bns_params = {0};
+
+ //TODO :for CNVC set scale and bias registers if necessary
+ build_prescale_params(&bns_params, plane_state);
+ if (dpp->funcs->dpp_program_bias_and_scale)
+ dpp->funcs->dpp_program_bias_and_scale(dpp, &bns_params);
+}
+
+void get_mclk_switch_visual_confirm_color(
+ struct dc *dc,
+ struct dc_state *context,
+ struct pipe_ctx *pipe_ctx,
+ struct tg_color *color)
+{
+ uint32_t color_value = MAX_TG_COLOR_VALUE;
+ struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
+
+ if (!dc->ctx || !dc->ctx->dmub_srv || !pipe_ctx || !vba || !context)
+ return;
+
+ if (vba->DRAMClockChangeSupport[vba->VoltageLevel][vba->maxMpcComb] !=
+ dm_dram_clock_change_unsupported) {
+ /* MCLK switching is supported */
+ if (!pipe_ctx->has_vactive_margin) {
+ /* In Vblank - yellow */
+ color->color_r_cr = color_value;
+ color->color_g_y = color_value;
+
+ if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
+ /* FPO + Vblank - cyan */
+ color->color_r_cr = 0;
+ color->color_g_y = color_value;
+ color->color_b_cb = color_value;
+ }
+ } else {
+ /* In Vactive - pink */
+ color->color_r_cr = color_value;
color->color_b_cb = color_value;
+ }
+ /* SubVP */
+ get_subvp_visual_confirm_color(dc, context, pipe_ctx, color);
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 117d80cb36fb..2f3d9a698486 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -69,6 +69,7 @@
#include "../dcn32/dcn32_resource.h"
#include "../dcn321/dcn321_resource.h"
+
#define DC_LOGGER_INIT(logger)
enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id)
@@ -1446,6 +1447,26 @@ static int acquire_first_split_pipe(
split_pipe->stream = stream;
return i;
+ } else if (split_pipe->prev_odm_pipe &&
+ split_pipe->prev_odm_pipe->plane_state == split_pipe->plane_state) {
+ split_pipe->prev_odm_pipe->next_odm_pipe = split_pipe->next_odm_pipe;
+ if (split_pipe->next_odm_pipe)
+ split_pipe->next_odm_pipe->prev_odm_pipe = split_pipe->prev_odm_pipe;
+
+ if (split_pipe->prev_odm_pipe->plane_state)
+ resource_build_scaling_params(split_pipe->prev_odm_pipe);
+
+ memset(split_pipe, 0, sizeof(*split_pipe));
+ split_pipe->stream_res.tg = pool->timing_generators[i];
+ split_pipe->plane_res.hubp = pool->hubps[i];
+ split_pipe->plane_res.ipp = pool->ipps[i];
+ split_pipe->plane_res.dpp = pool->dpps[i];
+ split_pipe->stream_res.opp = pool->opps[i];
+ split_pipe->plane_res.mpcc_inst = pool->dpps[i]->inst;
+ split_pipe->pipe_idx = i;
+
+ split_pipe->stream = stream;
+ return i;
}
}
return -1;
@@ -1858,7 +1879,7 @@ bool dc_add_all_planes_for_stream(
return add_all_planes_for_stream(dc, stream, &set, 1, context);
}
-bool is_timing_changed(struct dc_stream_state *cur_stream,
+bool dc_is_timing_changed(struct dc_stream_state *cur_stream,
struct dc_stream_state *new_stream)
{
if (cur_stream == NULL)
@@ -1883,7 +1904,7 @@ static bool are_stream_backends_same(
if (stream_a == NULL || stream_b == NULL)
return false;
- if (is_timing_changed(stream_a, stream_b))
+ if (dc_is_timing_changed(stream_a, stream_b))
return false;
if (stream_a->signal != stream_b->signal)
@@ -3014,23 +3035,29 @@ static void set_avi_info_frame(
hdmi_info.bits.S0_S1 = scan_type;
/* C0, C1 : Colorimetry */
- if (color_space == COLOR_SPACE_YCBCR709 ||
- color_space == COLOR_SPACE_YCBCR709_LIMITED)
+ switch (color_space) {
+ case COLOR_SPACE_YCBCR709:
+ case COLOR_SPACE_YCBCR709_LIMITED:
hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
- else if (color_space == COLOR_SPACE_YCBCR601 ||
- color_space == COLOR_SPACE_YCBCR601_LIMITED)
+ break;
+ case COLOR_SPACE_YCBCR601:
+ case COLOR_SPACE_YCBCR601_LIMITED:
hdmi_info.bits.C0_C1 = COLORIMETRY_ITU601;
- else {
- hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
- }
- if (color_space == COLOR_SPACE_2020_RGB_FULLRANGE ||
- color_space == COLOR_SPACE_2020_RGB_LIMITEDRANGE ||
- color_space == COLOR_SPACE_2020_YCBCR) {
+ break;
+ case COLOR_SPACE_2020_RGB_FULLRANGE:
+ case COLOR_SPACE_2020_RGB_LIMITEDRANGE:
+ case COLOR_SPACE_2020_YCBCR:
hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_BT2020RGBYCBCR;
hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
- } else if (color_space == COLOR_SPACE_ADOBERGB) {
+ break;
+ case COLOR_SPACE_ADOBERGB:
hdmi_info.bits.EC0_EC2 = COLORIMETRYEX_ADOBERGB;
hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
+ break;
+ case COLOR_SPACE_SRGB:
+ default:
+ hdmi_info.bits.C0_C1 = COLORIMETRY_NO_DATA;
+ break;
}
if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR &&
@@ -3508,7 +3535,7 @@ bool pipe_need_reprogram(
if (pipe_ctx_old->stream_res.stream_enc != pipe_ctx->stream_res.stream_enc)
return true;
- if (is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
+ if (dc_is_timing_changed(pipe_ctx_old->stream, pipe_ctx->stream))
return true;
if (pipe_ctx_old->stream->dpms_off != pipe_ctx->stream->dpms_off)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
index 72b261ad9587..6e11d2b701f8 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -276,8 +276,8 @@ static void program_cursor_attributes(
}
dc->hwss.set_cursor_attribute(pipe_ctx);
-
- dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
+ if (dc->ctx->dmub_srv)
+ dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
if (dc->hwss.set_cursor_sdr_white_level)
dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
}
@@ -396,8 +396,8 @@ static void program_cursor_position(
}
dc->hwss.set_cursor_position(pipe_ctx);
-
- dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
+ if (dc->ctx->dmub_srv)
+ dc_send_update_cursor_info_to_dmu(pipe_ctx, i);
}
if (pipe_to_program)
@@ -490,25 +490,6 @@ bool dc_stream_add_writeback(struct dc *dc,
struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
dwb->otg_inst = stream_status->primary_otg_inst;
}
- if (IS_DIAG_DC(dc->ctx->dce_environment)) {
- if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
- dm_error("DC: update_bandwidth failed!\n");
- return false;
- }
-
- /* enable writeback */
- if (dc->hwss.enable_writeback) {
- struct dwbc *dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
-
- if (dwb->funcs->is_enabled(dwb)) {
- /* writeback pipe already enabled, only need to update */
- dc->hwss.update_writeback(dc, wb_info, dc->current_state);
- } else {
- /* Enable writeback pipe from scratch*/
- dc->hwss.enable_writeback(dc, wb_info, dc->current_state);
- }
- }
- }
return true;
}
@@ -553,17 +534,6 @@ bool dc_stream_remove_writeback(struct dc *dc,
}
stream->num_wb_info = j;
- if (IS_DIAG_DC(dc->ctx->dce_environment)) {
- /* recalculate and apply DML parameters */
- if (!dc->hwss.update_bandwidth(dc, dc->current_state)) {
- dm_error("DC: update_bandwidth failed!\n");
- return false;
- }
-
- /* disable writeback */
- if (dc->hwss.disable_writeback)
- dc->hwss.disable_writeback(dc, dwb_pipe_inst);
- }
return true;
}