From: Dillon Varone <[email protected]> [WHY&HOW] DC currently has fragmented definitions of update types. This changes consolidates them into a single interface, and adds expanded functionality to accommodate all use cases. - adds `dc_check_update_state_and_surfaces_for_stream` to determine update type including state, surface, and stream changes. - adds missing surface/stream update checks to `dc_check_update_surfaces_for_stream` - adds new update type `UPDATE_TYPE_ADDR_ONLY` to accomodate flows where further distinction from `UPDATE_TYPE_FAST` was needed - removes caller reliance on `enable_legacy_fast_update` to determine which commit function to use, instead embedding it in the update type
Reviewed-by: Nicholas Kazlauskas <[email protected]> Signed-off-by: Dillon Varone <[email protected]> Signed-off-by: Chuanyu Tseng <[email protected]> --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 6 +- .../amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 2 +- drivers/gpu/drm/amd/display/dc/core/dc.c | 472 ++++++++---------- drivers/gpu/drm/amd/display/dc/dc.h | 20 +- 4 files changed, 201 insertions(+), 299 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 344ff8cb42df..2b0648460097 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -9885,7 +9885,7 @@ static void amdgpu_dm_enable_self_refresh(struct amdgpu_crtc *acrtc_attach, } /* Decrement skip count when SR is enabled and we're doing fast updates. */ - if (acrtc_state->update_type == UPDATE_TYPE_FAST && + if (acrtc_state->update_type <= UPDATE_TYPE_FAST && (psr->psr_feature_enabled || pr->config.replay_supported)) { if (aconn->sr_skip_count > 0) aconn->sr_skip_count--; @@ -10093,7 +10093,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * fast updates. */ if (crtc->state->async_flip && - (acrtc_state->update_type != UPDATE_TYPE_FAST || + (acrtc_state->update_type > UPDATE_TYPE_FAST || get_mem_type(old_plane_state->fb) != get_mem_type(fb))) drm_warn_once(state->dev, "[PLANE:%d:%s] async flip with non-fast update\n", @@ -10101,7 +10101,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, bundle->flip_addrs[planes_count].flip_immediate = crtc->state->async_flip && - acrtc_state->update_type == UPDATE_TYPE_FAST && + acrtc_state->update_type <= UPDATE_TYPE_FAST && get_mem_type(old_plane_state->fb) == get_mem_type(fb); timestamp_ns = ktime_get_ns(); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index 39fcbc3e702d..50f2fb704539 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -685,7 +685,7 @@ static int amdgpu_dm_crtc_helper_atomic_check(struct drm_crtc *crtc, * pitch, the DCC state, rotation, etc. */ if (crtc_state->async_flip && - dm_crtc_state->update_type != UPDATE_TYPE_FAST) { + dm_crtc_state->update_type > UPDATE_TYPE_FAST) { drm_dbg_atomic(crtc->dev, "[CRTC:%d:%s] async flips are only supported for fast updates\n", crtc->base.id, crtc->name); diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index ef7108e94627..414c9a0e8922 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -2696,7 +2696,7 @@ static bool is_surface_in_context( static struct surface_update_descriptor get_plane_info_update_type(const struct dc_surface_update *u) { union surface_update_flags *update_flags = &u->surface->update_flags; - struct surface_update_descriptor update_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE }; + struct surface_update_descriptor update_type = { UPDATE_TYPE_ADDR_ONLY, LOCK_DESCRIPTOR_NONE }; if (!u->plane_info) return update_type; @@ -2804,7 +2804,7 @@ static struct surface_update_descriptor get_scaling_info_update_type( const struct dc_surface_update *u) { union surface_update_flags *update_flags = &u->surface->update_flags; - struct surface_update_descriptor update_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE }; + struct surface_update_descriptor update_type = { UPDATE_TYPE_ADDR_ONLY, LOCK_DESCRIPTOR_NONE }; if (!u->scaling_info) return update_type; @@ -2855,11 +2855,11 @@ static struct surface_update_descriptor get_scaling_info_update_type( return update_type; } -static struct surface_update_descriptor det_surface_update( +static struct surface_update_descriptor check_update_surface( const struct dc_check_config *check_config, struct dc_surface_update *u) { - struct surface_update_descriptor overall_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE }; + struct surface_update_descriptor overall_type = { UPDATE_TYPE_ADDR_ONLY, LOCK_DESCRIPTOR_NONE }; union surface_update_flags *update_flags = &u->surface->update_flags; if (u->surface->force_full_update) { @@ -2879,7 +2879,7 @@ static struct surface_update_descriptor det_surface_update( if (u->flip_addr) { update_flags->bits.addr_update = 1; - elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); + elevate_update_type(&overall_type, UPDATE_TYPE_ADDR_ONLY, LOCK_DESCRIPTOR_STREAM); if (u->flip_addr->address.tmz_surface != u->surface->address.tmz_surface) { update_flags->bits.tmz_changed = 1; @@ -2893,27 +2893,43 @@ static struct surface_update_descriptor det_surface_update( if (u->input_csc_color_matrix) { update_flags->bits.input_csc_change = 1; - elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); + elevate_update_type(&overall_type, + check_config->enable_legacy_fast_update ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST, + LOCK_DESCRIPTOR_STREAM); + } + + if (u->cursor_csc_color_matrix) { + elevate_update_type(&overall_type, + check_config->enable_legacy_fast_update ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST, + LOCK_DESCRIPTOR_STREAM); } if (u->coeff_reduction_factor) { update_flags->bits.coeff_reduction_change = 1; - elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); + elevate_update_type(&overall_type, + check_config->enable_legacy_fast_update ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST, + LOCK_DESCRIPTOR_STREAM); } if (u->gamut_remap_matrix) { update_flags->bits.gamut_remap_change = 1; - elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); + elevate_update_type(&overall_type, + check_config->enable_legacy_fast_update ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST, + LOCK_DESCRIPTOR_STREAM); } if (u->cm || (u->gamma && dce_use_lut(u->plane_info ? u->plane_info->format : u->surface->format))) { update_flags->bits.gamma_change = 1; - elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); + elevate_update_type(&overall_type, + check_config->enable_legacy_fast_update ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST, + LOCK_DESCRIPTOR_STREAM); } if (u->cm && (u->cm->flags.bits.lut3d_enable || u->surface->cm.flags.bits.lut3d_enable)) { update_flags->bits.lut_3d = 1; - elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); + elevate_update_type(&overall_type, + check_config->enable_legacy_fast_update ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST, + LOCK_DESCRIPTOR_STREAM); } if (u->cm && u->cm->flags.bits.lut3d_dma_enable != u->surface->cm.flags.bits.lut3d_dma_enable && @@ -2929,9 +2945,10 @@ static struct surface_update_descriptor det_surface_update( if (u->hdr_mult.value) if (u->hdr_mult.value != u->surface->hdr_mult.value) { - // TODO: Should be fast? update_flags->bits.hdr_mult = 1; - elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); + elevate_update_type(&overall_type, + check_config->enable_legacy_fast_update ? UPDATE_TYPE_MED : UPDATE_TYPE_FAST, + LOCK_DESCRIPTOR_STREAM); } if (u->sdr_white_level_nits) @@ -2985,7 +3002,7 @@ static struct surface_update_descriptor check_update_surfaces_for_stream( int surface_count, struct dc_stream_update *stream_update) { - struct surface_update_descriptor overall_type = { UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_NONE }; + struct surface_update_descriptor overall_type = { UPDATE_TYPE_ADDR_ONLY, LOCK_DESCRIPTOR_NONE }; /* When countdown finishes, promote this flip to full to trigger deferred final transition */ if (check_config->deferred_transition_state && !check_config->transition_countdown_to_steady_state) { @@ -3052,7 +3069,18 @@ static struct surface_update_descriptor check_update_surfaces_for_stream( if (su_flags->raw) elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); - // Non-global cases + /* Non-global cases */ + if (stream_update->hdr_static_metadata || + stream_update->vrr_infopacket || + stream_update->vsc_infopacket || + stream_update->vsp_infopacket || + stream_update->hfvsif_infopacket || + stream_update->adaptive_sync_infopacket || + stream_update->vtem_infopacket || + stream_update->avi_infopacket) { + elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); + } + if (stream_update->output_csc_transform) { su_flags->bits.out_csc = 1; elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); @@ -3062,11 +3090,32 @@ static struct surface_update_descriptor check_update_surfaces_for_stream( su_flags->bits.out_tf = 1; elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); } + + if (stream_update->periodic_interrupt) { + elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); + } + + if (stream_update->dither_option) { + elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); + } + + if (stream_update->cursor_position || stream_update->cursor_attributes) { + elevate_update_type(&overall_type, UPDATE_TYPE_MED, LOCK_DESCRIPTOR_STREAM); + } + + /* TODO - cleanup post blend CM */ + if (stream_update->func_shaper || stream_update->lut3d_func) { + elevate_update_type(&overall_type, UPDATE_TYPE_FAST, LOCK_DESCRIPTOR_STREAM); + } + + if (stream_update->pending_test_pattern) { + elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); + } } for (int i = 0 ; i < surface_count; i++) { struct surface_update_descriptor inner_type = - det_surface_update(check_config, &updates[i]); + check_update_surface(check_config, &updates[i]); elevate_update_type(&overall_type, inner_type.update_type, inner_type.lock_descriptor); } @@ -3093,6 +3142,81 @@ struct surface_update_descriptor dc_check_update_surfaces_for_stream( return check_update_surfaces_for_stream(check_config, updates, surface_count, stream_update); } +/* + * check_update_state_and_surfaces_for_stream() - Determine update type (fast, med, or full) + * + * This function performs checks on the DC global state, and is therefore not re-entrant. It + * should not be called from DM. + * + * See :c:type:`enum surface_update_type <surface_update_type>` for explanation of update types + */ +static struct surface_update_descriptor check_update_state_and_surfaces_for_stream( + const struct dc *dc, + const struct dc_check_config *check_config, + const struct dc_stream_state *stream, + const struct dc_surface_update *updates, + const int surface_count, + const struct dc_stream_update *stream_update) +{ + const struct dc_state *context = dc->current_state; + + struct surface_update_descriptor overall_type = { UPDATE_TYPE_ADDR_ONLY, LOCK_DESCRIPTOR_NONE}; + + if (updates) + for (int i = 0; i < surface_count; i++) + if (!is_surface_in_context(context, updates[i].surface)) + elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); + + if (stream) { + const struct dc_stream_status *stream_status = dc_stream_get_status_const(stream); + if (stream_status == NULL || stream_status->plane_count != surface_count) + elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); + } + if (dc->idle_optimizations_allowed) + elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); + + if (dc_can_clear_cursor_limit(dc)) + elevate_update_type(&overall_type, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); + + return overall_type; +} + +/* + * dc_check_update_state_and_surfaces_for_stream() - Determine update type (fast, med, or full) + * + * This function performs checks on the DC global state, stream and surface update, and is + * therefore not re-entrant. It should not be called from DM. + * + * See :c:type:`enum surface_update_type <surface_update_type>` for explanation of update types + */ +static struct surface_update_descriptor dc_check_update_state_and_surfaces_for_stream( + const struct dc *dc, + const struct dc_check_config *check_config, + struct dc_stream_state *stream, + struct dc_surface_update *updates, + int surface_count, + struct dc_stream_update *stream_update) +{ + /* check updates against the entire DC state (global) first */ + struct surface_update_descriptor overall_update_type = check_update_state_and_surfaces_for_stream( + dc, + check_config, + stream, + updates, + surface_count, + stream_update); + + /* check updates for stream and plane */ + struct surface_update_descriptor stream_update_type = dc_check_update_surfaces_for_stream( + check_config, + updates, + surface_count, + stream_update); + elevate_update_type(&overall_update_type, stream_update_type.update_type, stream_update_type.lock_descriptor); + + return overall_update_type; +} + static struct dc_stream_status *stream_get_status( struct dc_state *ctx, struct dc_stream_state *stream) @@ -3449,13 +3573,6 @@ static void update_seamless_boot_flags(struct dc *dc, } } -static bool full_update_required_weak( - const struct dc *dc, - const struct dc_surface_update *srf_updates, - int surface_count, - const struct dc_stream_update *stream_update, - const struct dc_stream_state *stream); - struct pipe_split_policy_backup { bool dynamic_odm_policy; bool subvp_policy; @@ -3525,12 +3642,11 @@ static bool update_planes_and_stream_state(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 *new_update_type, + struct surface_update_descriptor *update_descriptor, struct dc_state **new_context) { struct dc_state *context; int i, j; - enum surface_update_type update_type; const struct dc_stream_status *stream_status; struct dc_context *dc_ctx = dc->ctx; @@ -3544,17 +3660,20 @@ static bool update_planes_and_stream_state(struct dc *dc, } context = dc->current_state; - update_type = dc_check_update_surfaces_for_stream( - &dc->check_config, srf_updates, surface_count, stream_update).update_type; - if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream)) - update_type = UPDATE_TYPE_FULL; + *update_descriptor = dc_check_update_state_and_surfaces_for_stream( + dc, + &dc->check_config, + stream, + srf_updates, + surface_count, + stream_update); /* It is possible to receive a flip for one plane while there are multiple flip_immediate planes in the same stream. * E.g. Desktop and MPO plane are flip_immediate but only the MPO plane received a flip * Force the other flip_immediate planes to flip so GSL doesn't wait for a flip that won't come. */ force_immediate_gsl_plane_flip(dc, srf_updates, surface_count); - if (update_type == UPDATE_TYPE_FULL) + if (update_descriptor->update_type == UPDATE_TYPE_FULL) backup_planes_and_stream_state(&dc->scratch.current_state, stream); /* update current stream with the new updates */ @@ -3580,7 +3699,7 @@ static bool update_planes_and_stream_state(struct dc *dc, } } - if (update_type == UPDATE_TYPE_FULL) { + if (update_descriptor->update_type == UPDATE_TYPE_FULL) { if (stream_update) { uint32_t dsc_changed = stream_update->stream->update_flags.bits.dsc_changed; stream_update->stream->update_flags.raw = 0xFFFFFFFF; @@ -3590,13 +3709,13 @@ static bool update_planes_and_stream_state(struct dc *dc, srf_updates[i].surface->update_flags.raw = 0xFFFFFFFF; } - if (update_type >= update_surface_trace_level) + if (update_descriptor->update_type >= update_surface_trace_level) update_surface_trace(dc, srf_updates, surface_count); for (i = 0; i < surface_count; i++) copy_surface_update_to_plane(srf_updates[i].surface, &srf_updates[i]); - if (update_type >= UPDATE_TYPE_FULL) { + if (update_descriptor->update_type >= UPDATE_TYPE_FULL) { struct dc_plane_state *new_planes[MAX_SURFACES] = {0}; for (i = 0; i < surface_count; i++) @@ -3634,7 +3753,7 @@ static bool update_planes_and_stream_state(struct dc *dc, for (i = 0; i < surface_count; i++) { struct dc_plane_state *surface = srf_updates[i].surface; - if (update_type != UPDATE_TYPE_MED) + if (update_descriptor->update_type != UPDATE_TYPE_MED) continue; if (surface->update_flags.bits.position_change) { for (j = 0; j < dc->res_pool->pipe_count; j++) { @@ -3648,7 +3767,7 @@ static bool update_planes_and_stream_state(struct dc *dc, } } - if (update_type == UPDATE_TYPE_FULL) { + if (update_descriptor->update_type == UPDATE_TYPE_FULL) { struct pipe_split_policy_backup policy; bool minimize = false; @@ -3677,8 +3796,7 @@ static bool update_planes_and_stream_state(struct dc *dc, update_seamless_boot_flags(dc, context, surface_count, stream); *new_context = context; - *new_update_type = update_type; - if (update_type == UPDATE_TYPE_FULL) + if (update_descriptor->update_type == UPDATE_TYPE_FULL) backup_planes_and_stream_state(&dc->scratch.new_state, stream); return true; @@ -3758,7 +3876,7 @@ static void commit_planes_do_stream_update(struct dc *dc, program_cursor_position(dc, stream); /* Full fe update*/ - if (update_type == UPDATE_TYPE_FAST) + if (update_type <= UPDATE_TYPE_FAST) continue; if (stream_update->dsc_config) @@ -4067,7 +4185,7 @@ static void commit_planes_for_stream_fast(struct dc *dc, struct pipe_ctx *top_pipe_to_program = NULL; struct dc_stream_status *stream_status = NULL; bool should_offload_fams2_flip = false; - bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST); + bool should_lock_all_pipes = (update_type > UPDATE_TYPE_FAST); if (should_lock_all_pipes) determine_pipe_unlock_order(dc, context); @@ -4127,7 +4245,7 @@ static void commit_planes_for_stream_fast(struct dc *dc, continue; pipe_ctx->plane_state->triplebuffer_flips = false; - if (update_type == UPDATE_TYPE_FAST && + 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*/ @@ -4184,7 +4302,7 @@ static void commit_planes_for_stream(struct dc *dc, { int i, j; struct pipe_ctx *top_pipe_to_program = NULL; - bool should_lock_all_pipes = (update_type != UPDATE_TYPE_FAST); + bool should_lock_all_pipes = (update_type > UPDATE_TYPE_FAST); bool subvp_prev_use = false; bool subvp_curr_use = false; uint8_t current_stream_mask = 0; @@ -4201,7 +4319,7 @@ static void commit_planes_for_stream(struct dc *dc, if (update_type == UPDATE_TYPE_FULL && dc->optimized_required) hwss_process_outstanding_hw_updates(dc, dc->current_state); - if (update_type != UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming) + if (update_type > UPDATE_TYPE_FAST && dc->res_pool->funcs->prepare_mcache_programming) dc->res_pool->funcs->prepare_mcache_programming(dc, context); for (i = 0; i < dc->res_pool->pipe_count; i++) { @@ -4263,7 +4381,7 @@ static void commit_planes_for_stream(struct dc *dc, odm_pipe->ttu_regs.min_ttu_vblank = MAX_TTU; } - if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) + if ((update_type > UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) if (top_pipe_to_program && top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { if (should_use_dmub_inbox1_lock(dc, stream->link)) { @@ -4334,7 +4452,7 @@ 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 (update_type > UPDATE_TYPE_FAST) if (dc->hwss.commit_subvp_config) dc->hwss.commit_subvp_config(dc, context); @@ -4350,7 +4468,7 @@ static void commit_planes_for_stream(struct dc *dc, return; } - if (update_type != UPDATE_TYPE_FAST) { + if (update_type > UPDATE_TYPE_FAST) { for (j = 0; j < dc->res_pool->pipe_count; j++) { struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[j]; @@ -4378,7 +4496,7 @@ static void commit_planes_for_stream(struct dc *dc, 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 && + 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*/ @@ -4405,7 +4523,7 @@ static void commit_planes_for_stream(struct dc *dc, continue; /* Full fe update*/ - if (update_type == UPDATE_TYPE_FAST) + if (update_type <= UPDATE_TYPE_FAST) continue; stream_status = @@ -4424,7 +4542,7 @@ static void commit_planes_for_stream(struct dc *dc, continue; /* Full fe update*/ - if (update_type == UPDATE_TYPE_FAST) + if (update_type <= UPDATE_TYPE_FAST) continue; ASSERT(!pipe_ctx->plane_state->triplebuffer_flips); @@ -4435,7 +4553,7 @@ static void commit_planes_for_stream(struct dc *dc, } } - if (dc->hwss.program_front_end_for_ctx && update_type != UPDATE_TYPE_FAST) { + if (dc->hwss.program_front_end_for_ctx && update_type > UPDATE_TYPE_FAST) { dc->hwss.program_front_end_for_ctx(dc, context); //Pipe busy until some frame and line # @@ -4463,7 +4581,7 @@ static void commit_planes_for_stream(struct dc *dc, } // Update Type FAST, Surface updates - if (update_type == UPDATE_TYPE_FAST) { + if (update_type <= UPDATE_TYPE_FAST) { if (dc->hwss.set_flip_control_gsl) for (i = 0; i < surface_count; i++) { struct dc_plane_state *plane_state = srf_updates[i].surface; @@ -4520,7 +4638,7 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.pipe_control_lock(dc, top_pipe_to_program, false); } - if ((update_type != UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) + if ((update_type > UPDATE_TYPE_FAST) && stream->update_flags.bits.dsc_changed) if (top_pipe_to_program && top_pipe_to_program->stream_res.tg->funcs->lock_doublebuffer_enable) { top_pipe_to_program->stream_res.tg->funcs->wait_for_state( @@ -4553,13 +4671,13 @@ static void commit_planes_for_stream(struct dc *dc, /* If enabling subvp or transitioning from subvp->subvp, enable the * phantom streams before we program front end for the phantom pipes. */ - if (update_type != UPDATE_TYPE_FAST) { + if (update_type > UPDATE_TYPE_FAST) { if (dc->hwss.enable_phantom_streams) dc->hwss.enable_phantom_streams(dc, context); } } - if (update_type != UPDATE_TYPE_FAST) + if (update_type > UPDATE_TYPE_FAST) dc->hwss.post_unlock_program_front_end(dc, context); if (subvp_prev_use && !subvp_curr_use) { @@ -4572,7 +4690,7 @@ static void commit_planes_for_stream(struct dc *dc, dc->hwss.disable_phantom_streams(dc, context); } - if (update_type != UPDATE_TYPE_FAST) + 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, @@ -5044,191 +5162,12 @@ static bool commit_minimal_transition_state(struct dc *dc, return true; } -void populate_fast_updates(struct dc_fast_update *fast_update, - struct dc_surface_update *srf_updates, - int surface_count, - struct dc_stream_update *stream_update) -{ - int i = 0; - - if (stream_update) { - fast_update[0].out_transfer_func = stream_update->out_transfer_func; - fast_update[0].output_csc_transform = stream_update->output_csc_transform; - } else { - fast_update[0].out_transfer_func = NULL; - fast_update[0].output_csc_transform = NULL; - } - - for (i = 0; i < surface_count; i++) { - fast_update[i].flip_addr = srf_updates[i].flip_addr; - fast_update[i].gamma = srf_updates[i].gamma; - fast_update[i].gamut_remap_matrix = srf_updates[i].gamut_remap_matrix; - fast_update[i].input_csc_color_matrix = srf_updates[i].input_csc_color_matrix; - fast_update[i].coeff_reduction_factor = srf_updates[i].coeff_reduction_factor; - fast_update[i].cursor_csc_color_matrix = srf_updates[i].cursor_csc_color_matrix; - fast_update[i].cm_hist_control = srf_updates[i].cm_hist_control; - } -} - -static bool fast_updates_exist(const struct dc_fast_update *fast_update, int surface_count) -{ - int i; - - if (fast_update[0].out_transfer_func || - fast_update[0].output_csc_transform) - return true; - - for (i = 0; i < surface_count; i++) { - if (fast_update[i].flip_addr || - fast_update[i].gamma || - fast_update[i].gamut_remap_matrix || - fast_update[i].input_csc_color_matrix || - fast_update[i].cursor_csc_color_matrix || - fast_update[i].cm_hist_control || - fast_update[i].coeff_reduction_factor) - return true; - } - - return false; -} - -bool fast_nonaddr_updates_exist(struct dc_fast_update *fast_update, int surface_count) -{ - int i; - - if (fast_update[0].out_transfer_func || - fast_update[0].output_csc_transform) - return true; - - for (i = 0; i < surface_count; i++) { - if (fast_update[i].input_csc_color_matrix || - fast_update[i].gamma || - fast_update[i].gamut_remap_matrix || - fast_update[i].coeff_reduction_factor || - fast_update[i].cm_hist_control || - fast_update[i].cursor_csc_color_matrix) - return true; - } - - return false; -} - -static bool full_update_required_weak( - const struct dc *dc, - const struct dc_surface_update *srf_updates, - int surface_count, - const struct dc_stream_update *stream_update, - const struct dc_stream_state *stream) -{ - const struct dc_state *context = dc->current_state; - if (srf_updates) - for (int i = 0; i < surface_count; i++) - if (!is_surface_in_context(context, srf_updates[i].surface)) - return true; - - if (stream) { - const struct dc_stream_status *stream_status = dc_stream_get_status_const(stream); - if (stream_status == NULL || stream_status->plane_count != surface_count) - return true; - } - if (dc->idle_optimizations_allowed) - return true; - - if (dc_can_clear_cursor_limit(dc)) - return true; - - return false; -} - -static bool full_update_required( - const struct dc *dc, - const struct dc_surface_update *srf_updates, - int surface_count, - const struct dc_stream_update *stream_update, - const struct dc_stream_state *stream) -{ - const union dc_plane_cm_flags blend_only_flags = { - .bits = { - .blend_enable = 1, - } - }; - - if (full_update_required_weak(dc, srf_updates, surface_count, stream_update, stream)) - return true; - - for (int i = 0; i < surface_count; i++) { - if (srf_updates && - (srf_updates[i].plane_info || - srf_updates[i].scaling_info || - (srf_updates[i].hdr_mult.value && - srf_updates[i].hdr_mult.value != srf_updates->surface->hdr_mult.value) || - (srf_updates[i].sdr_white_level_nits && - srf_updates[i].sdr_white_level_nits != srf_updates->surface->sdr_white_level_nits) || - srf_updates[i].in_transfer_func || - srf_updates[i].surface->force_full_update || - (srf_updates[i].flip_addr && - srf_updates[i].flip_addr->address.tmz_surface != srf_updates[i].surface->address.tmz_surface) || - (srf_updates[i].cm && - ((srf_updates[i].cm->flags.all != blend_only_flags.all && srf_updates[i].cm->flags.all != 0) || - (srf_updates[i].surface->cm.flags.all != blend_only_flags.all && srf_updates[i].surface->cm.flags.all != 0))))) - return true; - } - - if (stream_update && - (((stream_update->src.height != 0 && stream_update->src.width != 0) || - (stream_update->dst.height != 0 && stream_update->dst.width != 0) || - stream_update->integer_scaling_update) || - stream_update->hdr_static_metadata || - stream_update->abm_level || - stream_update->periodic_interrupt || - stream_update->vrr_infopacket || - stream_update->vsc_infopacket || - stream_update->vsp_infopacket || - stream_update->hfvsif_infopacket || - stream_update->vtem_infopacket || - stream_update->adaptive_sync_infopacket || - stream_update->avi_infopacket || - stream_update->dpms_off || - stream_update->allow_freesync || - stream_update->vrr_active_variable || - stream_update->vrr_active_fixed || - stream_update->gamut_remap || - stream_update->output_color_space || - stream_update->dither_option || - stream_update->wb_update || - stream_update->dsc_config || - stream_update->mst_bw_update || - stream_update->func_shaper || - stream_update->lut3d_func || - stream_update->pending_test_pattern || - stream_update->crtc_timing_adjust || - stream_update->scaler_sharpener_update || - stream_update->hw_cursor_req)) - return true; - - return false; -} - -static bool fast_update_only( - const struct dc *dc, - const struct dc_fast_update *fast_update, - const struct dc_surface_update *srf_updates, - int surface_count, - const struct dc_stream_update *stream_update, - const struct dc_stream_state *stream) -{ - return fast_updates_exist(fast_update, surface_count) - && !full_update_required(dc, srf_updates, surface_count, stream_update, stream); -} - static bool update_planes_and_stream_v2(struct dc *dc, struct dc_surface_update *srf_updates, int surface_count, struct dc_stream_state *stream, struct dc_stream_update *stream_update) { struct dc_state *context; - enum surface_update_type update_type; - struct dc_fast_update fast_update[MAX_SURFACES] = {0}; /* In cases where MPO and split or ODM are used transitions can * cause underflow. Apply stream configuration with minimal pipe @@ -5236,11 +5175,9 @@ static bool update_planes_and_stream_v2(struct dc *dc, */ bool force_minimal_pipe_splitting = 0; bool is_plane_addition = 0; - bool is_fast_update_only; - populate_fast_updates(fast_update, srf_updates, surface_count, stream_update); - is_fast_update_only = fast_update_only(dc, fast_update, srf_updates, - surface_count, stream_update, stream); + struct surface_update_descriptor update_descriptor = {0}; + force_minimal_pipe_splitting = could_mpcc_tree_change_for_active_pipes( dc, stream, @@ -5259,7 +5196,7 @@ static bool update_planes_and_stream_v2(struct dc *dc, surface_count, stream, stream_update, - &update_type, + &update_descriptor, &context)) return false; @@ -5269,7 +5206,7 @@ static bool update_planes_and_stream_v2(struct dc *dc, dc_state_release(context); return false; } - update_type = UPDATE_TYPE_FULL; + elevate_update_type(&update_descriptor, UPDATE_TYPE_FULL, LOCK_DESCRIPTOR_GLOBAL); } if (dc->hwss.is_pipe_topology_transition_seamless && @@ -5278,13 +5215,13 @@ static bool update_planes_and_stream_v2(struct dc *dc, commit_minimal_transition_state_in_dc_update(dc, context, stream, srf_updates, surface_count); - if (is_fast_update_only && !dc->check_config.enable_legacy_fast_update) { + if (update_descriptor.update_type <= UPDATE_TYPE_FAST) { commit_planes_for_stream_fast(dc, srf_updates, surface_count, stream, stream_update, - update_type, + update_descriptor.update_type, context); } else { if (!stream_update && @@ -5300,7 +5237,7 @@ static bool update_planes_and_stream_v2(struct dc *dc, surface_count, stream, stream_update, - update_type, + update_descriptor.update_type, context); } if (dc->current_state != context) @@ -5314,14 +5251,8 @@ static void commit_planes_and_stream_update_on_current_context(struct dc *dc, struct dc_stream_update *stream_update, enum surface_update_type update_type) { - struct dc_fast_update fast_update[MAX_SURFACES] = {0}; - ASSERT(update_type < UPDATE_TYPE_FULL); - populate_fast_updates(fast_update, srf_updates, surface_count, - stream_update); - if (fast_update_only(dc, fast_update, srf_updates, surface_count, - stream_update, stream) && - !dc->check_config.enable_legacy_fast_update) + if (update_type <= UPDATE_TYPE_FAST) commit_planes_for_stream_fast(dc, srf_updates, surface_count, @@ -5412,7 +5343,7 @@ static bool update_planes_and_stream_v3(struct dc *dc, struct dc_stream_update *stream_update) { struct dc_state *new_context; - enum surface_update_type update_type; + struct surface_update_descriptor update_descriptor = {0}; /* * When this function returns true and new_context is not equal to @@ -5424,22 +5355,26 @@ static bool update_planes_and_stream_v3(struct dc *dc, * replaced by a newer context. Refer to the use of * swap_and_free_current_context below. */ - if (!update_planes_and_stream_state(dc, srf_updates, surface_count, - stream, stream_update, &update_type, + if (!update_planes_and_stream_state(dc, + srf_updates, + surface_count, + stream, + stream_update, + &update_descriptor, &new_context)) return false; if (new_context == dc->current_state) { commit_planes_and_stream_update_on_current_context(dc, srf_updates, surface_count, stream, - stream_update, update_type); + stream_update, update_descriptor.update_type); if (dc->check_config.transition_countdown_to_steady_state) dc->check_config.transition_countdown_to_steady_state--; } else { commit_planes_and_stream_update_with_new_context(dc, srf_updates, surface_count, stream, - stream_update, update_type, new_context); + stream_update, update_descriptor.update_type, new_context); } return true; @@ -7213,7 +7148,7 @@ struct dc_update_scratch_space { struct dc_stream_update *stream_update; bool update_v3; bool do_clear_update_flags; - enum surface_update_type update_type; + struct surface_update_descriptor update_descriptor; struct dc_state *new_context; enum update_v3_flow flow; struct dc_state *backup_context; @@ -7296,45 +7231,28 @@ static bool update_planes_and_stream_prepare_v3( ASSERT(scratch->flow == UPDATE_V3_FLOW_INVALID); dc_exit_ips_for_hw_access(scratch->dc); - /* HWSS path determination needs to be done prior to updating the surface and stream states. */ - struct dc_fast_update fast_update[MAX_SURFACES] = { 0 }; - - populate_fast_updates(fast_update, - scratch->surface_updates, - scratch->surface_count, - scratch->stream_update); - - const bool is_hwss_fast_path_only = - fast_update_only(scratch->dc, - fast_update, - scratch->surface_updates, - scratch->surface_count, - scratch->stream_update, - scratch->stream) && - !scratch->dc->check_config.enable_legacy_fast_update; - if (!update_planes_and_stream_state( scratch->dc, scratch->surface_updates, scratch->surface_count, scratch->stream, scratch->stream_update, - &scratch->update_type, + &scratch->update_descriptor, &scratch->new_context )) { return false; } if (scratch->new_context == scratch->dc->current_state) { - ASSERT(scratch->update_type < UPDATE_TYPE_FULL); + ASSERT(scratch->update_descriptor.update_type < UPDATE_TYPE_FULL); - scratch->flow = is_hwss_fast_path_only + scratch->flow = scratch->update_descriptor.update_type <= UPDATE_TYPE_FAST ? UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FAST : UPDATE_V3_FLOW_NO_NEW_CONTEXT_CONTEXT_FULL; return true; } - ASSERT(scratch->update_type >= UPDATE_TYPE_FULL); + ASSERT(scratch->update_descriptor.update_type >= UPDATE_TYPE_FULL); const bool seamless = scratch->dc->hwss.is_pipe_topology_transition_seamless( scratch->dc, @@ -7407,7 +7325,7 @@ static void update_planes_and_stream_execute_v3_commit( intermediate_update ? scratch->intermediate_count : scratch->surface_count, scratch->stream, use_stream_update ? scratch->stream_update : NULL, - intermediate_context ? UPDATE_TYPE_FULL : scratch->update_type, + intermediate_context ? UPDATE_TYPE_FULL : scratch->update_descriptor.update_type, // `dc->current_state` only used in `NO_NEW_CONTEXT`, where it is equal to `new_context` intermediate_context ? scratch->intermediate_context : scratch->new_context ); @@ -7425,7 +7343,7 @@ static void update_planes_and_stream_execute_v3( scratch->surface_count, scratch->stream, scratch->stream_update, - scratch->update_type, + scratch->update_descriptor.update_type, scratch->new_context ); break; diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4d15d97ed7f1..1dd0a2cf786c 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -467,6 +467,7 @@ struct dc_static_screen_params { */ enum surface_update_type { + UPDATE_TYPE_ADDR_ONLY, /* only surface address is being updated, no other programming needed */ UPDATE_TYPE_FAST, /* super fast, safe to execute in isr */ UPDATE_TYPE_MED, /* ISR safe, most of programming needed, no bw/clk change*/ UPDATE_TYPE_FULL, /* may need to shuffle resources */ @@ -1880,18 +1881,6 @@ struct dc_scaling_info { struct scaling_taps scaling_quality; }; -struct dc_fast_update { - const struct dc_flip_addrs *flip_addr; - const struct dc_gamma *gamma; - const struct colorspace_transform *gamut_remap_matrix; - const struct dc_csc_transform *input_csc_color_matrix; - const struct fixed31_32 *coeff_reduction_factor; - struct dc_transfer_func *out_transfer_func; - struct dc_csc_transform *output_csc_transform; - const struct dc_csc_transform *cursor_csc_color_matrix; - struct cm_hist_control *cm_hist_control; -}; - struct dc_surface_update { struct dc_plane_state *surface; @@ -2030,12 +2019,7 @@ bool dc_resource_is_dsc_encoding_supported(const struct dc *dc); void get_audio_check(struct audio_info *aud_modes, struct audio_check *aud_chk); -bool fast_nonaddr_updates_exist(struct dc_fast_update *fast_update, int surface_count); -void populate_fast_updates(struct dc_fast_update *fast_update, - struct dc_surface_update *srf_updates, - int surface_count, - struct dc_stream_update *stream_update); -/* + /* * Set up streams and links associated to drive sinks * The streams parameter is an absolute set of all active streams. * -- 2.43.0
