diff options
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/core/dc.c')
-rw-r--r-- | drivers/gpu/drm/amd/display/dc/core/dc.c | 200 |
1 files changed, 122 insertions, 78 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index fb22c3d70528..258ba5a872b1 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -401,6 +401,9 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, { int i; + if (memcmp(adjust, &stream->adjust, sizeof(struct dc_crtc_timing_adjust)) == 0) + return true; + stream->adjust.v_total_max = adjust->v_total_max; stream->adjust.v_total_mid = adjust->v_total_mid; stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; @@ -638,14 +641,17 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, /** * dc_stream_get_crc() - Get CRC values for the given stream. - * @dc: DC object + * + * @dc: DC object. * @stream: The DC stream state of the stream to get CRCs from. - * @r_cr: CRC value for the first of the 3 channels stored here. - * @g_y: CRC value for the second of the 3 channels stored here. - * @b_cb: CRC value for the third of the 3 channels stored here. + * @r_cr: CRC value for the red component. + * @g_y: CRC value for the green component. + * @b_cb: CRC value for the blue component. * * dc_stream_configure_crc needs to be called beforehand to enable CRCs. - * Return false if stream is not found, or if CRCs are not enabled. + * + * Return: + * false if stream is not found, or if CRCs are not enabled. */ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, uint32_t *r_cr, uint32_t *g_y, uint32_t *b_cb) @@ -1195,7 +1201,7 @@ static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context) int count = 0; struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i]; - if (!pipe->plane_state) + if (!pipe->plane_state || pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) continue; /* Timeout 100 ms */ @@ -1744,6 +1750,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c context->stream_count == 0) dc->hwss.prepare_bandwidth(dc, context); + if (dc->debug.enable_double_buffered_dsc_pg_support) + dc->hwss.update_dsc_pg(dc, context, false); + disable_dangling_plane(dc, context); /* re-program planes for existing stream, in case we need to * free up plane resource for later use @@ -1834,6 +1843,9 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c dc->hwss.optimize_bandwidth(dc, context); } + if (dc->debug.enable_double_buffered_dsc_pg_support) + dc->hwss.update_dsc_pg(dc, context, true); + if (dc->ctx->dce_version >= DCE_VERSION_MAX) TRACE_DCN_CLOCK_STATE(&context->bw_ctx.bw.dcn.clk); else @@ -1997,6 +2009,9 @@ void dc_post_update_surfaces_to_stream(struct dc *dc) dc->hwss.optimize_bandwidth(dc, context); + if (dc->debug.enable_double_buffered_dsc_pg_support) + dc->hwss.update_dsc_pg(dc, context, true); + dc->optimized_required = false; dc->wm_optimized_required = false; } @@ -2316,9 +2331,13 @@ static enum surface_update_type det_surface_update(const struct dc *dc, type = get_scaling_info_update_type(u); elevate_update_type(&overall_type, type); - if (u->flip_addr) + if (u->flip_addr) { update_flags->bits.addr_update = 1; - + if (u->flip_addr->address.tmz_surface != u->surface->address.tmz_surface) { + update_flags->bits.tmz_changed = 1; + elevate_update_type(&overall_type, UPDATE_TYPE_FULL); + } + } if (u->in_transfer_func) update_flags->bits.in_transfer_func_change = 1; @@ -2753,11 +2772,8 @@ static void copy_stream_update_to_stream(struct dc *dc, if (update->abm_level) stream->abm_level = *update->abm_level; - if (update->periodic_interrupt0) - stream->periodic_interrupt0 = *update->periodic_interrupt0; - - if (update->periodic_interrupt1) - stream->periodic_interrupt1 = *update->periodic_interrupt1; + if (update->periodic_interrupt) + stream->periodic_interrupt = *update->periodic_interrupt; if (update->gamut_remap) stream->gamut_remap_matrix = *update->gamut_remap; @@ -2842,16 +2858,6 @@ static void copy_stream_update_to_stream(struct dc *dc, } } -void dc_reset_state(struct dc *dc, struct dc_state *context) -{ - dc_resource_state_destruct(context); - - /* clear the structure, but don't reset the reference count */ - memset(context, 0, offsetof(struct dc_state, refcount)); - - init_state(dc, context); -} - static bool update_planes_and_stream_state(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, @@ -2987,13 +2993,8 @@ static void commit_planes_do_stream_update(struct dc *dc, if (!pipe_ctx->top_pipe && !pipe_ctx->prev_odm_pipe && pipe_ctx->stream == stream) { - if (stream_update->periodic_interrupt0 && - dc->hwss.setup_periodic_interrupt) - dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE0); - - if (stream_update->periodic_interrupt1 && - dc->hwss.setup_periodic_interrupt) - dc->hwss.setup_periodic_interrupt(dc, pipe_ctx, VLINE1); + if (stream_update->periodic_interrupt && dc->hwss.setup_periodic_interrupt) + dc->hwss.setup_periodic_interrupt(dc, pipe_ctx); if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) || stream_update->vrr_infopacket || @@ -3071,7 +3072,6 @@ static void commit_planes_do_stream_update(struct dc *dc, } else { if (get_seamless_boot_stream_count(context) == 0) dc->hwss.prepare_bandwidth(dc, dc->current_state); - core_link_enable_stream(dc->current_state, pipe_ctx); } } @@ -3099,11 +3099,9 @@ static void commit_planes_do_stream_update(struct dc *dc, static bool dc_dmub_should_send_dirty_rect_cmd(struct dc *dc, struct dc_stream_state *stream) { - if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1) - return true; - - if (stream->link->psr_settings.psr_version == DC_PSR_VERSION_1 && - dc->debug.enable_sw_cntl_psr) + if ((stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 + || stream->link->psr_settings.psr_version == DC_PSR_VERSION_1) + && stream->ctx->dce_version >= DCN_VERSION_3_1) return true; return false; @@ -3205,6 +3203,9 @@ static void commit_planes_for_stream(struct dc *dc, if (get_seamless_boot_stream_count(context) == 0) dc->hwss.prepare_bandwidth(dc, context); + if (dc->debug.enable_double_buffered_dsc_pg_support) + dc->hwss.update_dsc_pg(dc, context, false); + context_clock_trace(dc, context); } @@ -3319,10 +3320,6 @@ static void commit_planes_for_stream(struct dc *dc, if (dc->hwss.program_front_end_for_ctx) dc->hwss.program_front_end_for_ctx(dc, context); - if (update_type != UPDATE_TYPE_FAST) - if (dc->hwss.commit_subvp_config) - dc->hwss.commit_subvp_config(dc, context); - if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { dc->hwss.interdependent_update_lock(dc, context, false); } else { @@ -3330,16 +3327,15 @@ static void commit_planes_for_stream(struct dc *dc, } dc->hwss.post_unlock_program_front_end(dc, context); + if (update_type != UPDATE_TYPE_FAST) + if (dc->hwss.commit_subvp_config) + dc->hwss.commit_subvp_config(dc, context); + /* Since phantom pipe programming is moved to post_unlock_program_front_end, * move the SubVP lock to after the phantom pipes have been setup */ - if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { - if (dc->hwss.subvp_pipe_control_lock) - dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); - } else { - if (dc->hwss.subvp_pipe_control_lock) - dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); - } + if (dc->hwss.subvp_pipe_control_lock) + dc->hwss.subvp_pipe_control_lock(dc, context, false, should_lock_all_pipes, NULL, subvp_prev_use); return; } @@ -3463,10 +3459,6 @@ static void commit_planes_for_stream(struct dc *dc, } - if (update_type != UPDATE_TYPE_FAST) - if (dc->hwss.commit_subvp_config) - dc->hwss.commit_subvp_config(dc, context); - if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) { dc->hwss.interdependent_update_lock(dc, context, false); } else { @@ -3504,6 +3496,10 @@ static void commit_planes_for_stream(struct dc *dc, if (update_type != UPDATE_TYPE_FAST) dc->hwss.post_unlock_program_front_end(dc, context); + if (update_type != UPDATE_TYPE_FAST) + if (dc->hwss.commit_subvp_config) + dc->hwss.commit_subvp_config(dc, context); + /* Since phantom pipe programming is moved to post_unlock_program_front_end, * move the SubVP lock to after the phantom pipes have been setup */ @@ -3533,19 +3529,72 @@ static void commit_planes_for_stream(struct dc *dc, } } +/* Determines if the incoming context requires a applying transition state with unnecessary + * pipe splitting and ODM disabled, due to hardware limitations. In a case where + * the OPP associated with an MPCC might change due to plane additions, this function + * returns true. + */ +static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc, + struct dc_stream_state *stream, + int surface_count, + bool *is_plane_addition) +{ + + struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream); + bool force_minimal_pipe_splitting = false; + + *is_plane_addition = false; + + if (cur_stream_status && + dc->current_state->stream_count > 0 && + dc->debug.pipe_split_policy != MPC_SPLIT_AVOID) { + /* determine if minimal transition is required due to MPC*/ + if (surface_count > 0) { + if (cur_stream_status->plane_count > surface_count) { + force_minimal_pipe_splitting = true; + } else if (cur_stream_status->plane_count < surface_count) { + force_minimal_pipe_splitting = true; + *is_plane_addition = true; + } + } + } + + if (cur_stream_status && + dc->current_state->stream_count == 1 && + dc->debug.enable_single_display_2to1_odm_policy) { + /* determine if minimal transition is required due to dynamic ODM*/ + if (surface_count > 0) { + if (cur_stream_status->plane_count > 2 && cur_stream_status->plane_count > surface_count) { + force_minimal_pipe_splitting = true; + } else if (surface_count > 2 && cur_stream_status->plane_count < surface_count) { + force_minimal_pipe_splitting = true; + *is_plane_addition = true; + } + } + } + + return force_minimal_pipe_splitting; +} + static bool commit_minimal_transition_state(struct dc *dc, struct dc_state *transition_base_context) { struct dc_state *transition_context = dc_create_state(dc); - enum pipe_split_policy tmp_policy; + enum pipe_split_policy tmp_mpc_policy; + bool temp_dynamic_odm_policy; enum dc_status ret = DC_ERROR_UNEXPECTED; unsigned int i, j; if (!transition_context) return false; - tmp_policy = dc->debug.pipe_split_policy; - dc->debug.pipe_split_policy = MPC_SPLIT_AVOID; + if (!dc->config.is_vmin_only_asic) { + tmp_mpc_policy = dc->debug.pipe_split_policy; + dc->debug.pipe_split_policy = MPC_SPLIT_AVOID; + } + + temp_dynamic_odm_policy = dc->debug.enable_single_display_2to1_odm_policy; + dc->debug.enable_single_display_2to1_odm_policy = false; dc_resource_state_copy_construct(transition_base_context, transition_context); @@ -3567,19 +3616,22 @@ static bool commit_minimal_transition_state(struct dc *dc, ret = dc_commit_state_no_check(dc, transition_context); } - //always release as dc_commit_state_no_check retains in good case + /*always release as dc_commit_state_no_check retains in good case*/ dc_release_state(transition_context); - //restore previous pipe split policy - dc->debug.pipe_split_policy = tmp_policy; + /*restore previous pipe split and odm policy*/ + if (!dc->config.is_vmin_only_asic) + dc->debug.pipe_split_policy = tmp_mpc_policy; + + dc->debug.enable_single_display_2to1_odm_policy = temp_dynamic_odm_policy; if (ret != DC_OK) { - //this should never happen + /*this should never happen*/ BREAK_TO_DEBUGGER(); return false; } - //force full surface update + /*force full surface update*/ for (i = 0; i < dc->current_state->stream_count; i++) { for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) { dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF; @@ -3602,22 +3654,14 @@ bool dc_update_planes_and_stream(struct dc *dc, * cause underflow. Apply stream configuration with minimal pipe * split first to avoid unsupported transitions for active pipes. */ - bool force_minimal_pipe_splitting = false; - bool is_plane_addition = false; - - struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream); + bool force_minimal_pipe_splitting; + bool is_plane_addition; - if (cur_stream_status && - dc->current_state->stream_count > 0 && - dc->debug.pipe_split_policy != MPC_SPLIT_AVOID) { - /* determine if minimal transition is required */ - if (cur_stream_status->plane_count > surface_count) { - force_minimal_pipe_splitting = true; - } else if (cur_stream_status->plane_count < surface_count) { - force_minimal_pipe_splitting = true; - is_plane_addition = true; - } - } + force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes( + dc, + stream, + surface_count, + &is_plane_addition); /* on plane addition, minimal state is the current one */ if (force_minimal_pipe_splitting && is_plane_addition && @@ -3634,7 +3678,7 @@ bool dc_update_planes_and_stream(struct dc *dc, &context)) return false; - /* on plane addition, minimal state is the new one */ + /* on plane removal, minimal state is the new one */ if (force_minimal_pipe_splitting && !is_plane_addition) { if (!commit_minimal_transition_state(dc, context)) { dc_release_state(context); @@ -4021,7 +4065,7 @@ struct dc_sink *dc_link_add_remote_sink( * Treat device as no EDID device if EDID * parsing fails */ - if (edid_status != EDID_OK) { + if (edid_status != EDID_OK && edid_status != EDID_PARTIAL_VALID) { dc_sink->dc_edid.length = 0; dm_error("Bad EDID, status%d!\n", edid_status); } @@ -4276,8 +4320,8 @@ void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc) /* ***************************************************************************** * Function: dc_is_dmub_outbox_supported - - * - * @brief + * + * @brief * Checks whether DMUB FW supports outbox notifications, if supported * DM should register outbox interrupt prior to actually enabling interrupts * via dc_enable_dmub_outbox |