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 f2724713ddd08da4f3f929214877db36060e0fb7..6c04ad1b58598f0a6b1753e381aeca5aa2cfd6e6 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3771,7 +3771,8 @@ static void prepare_flip_isr(struct amdgpu_crtc *acrtc) */ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, - uint32_t target) + uint32_t target, + struct dc_state *state) { unsigned long flags; uint32_t target_vblank; @@ -3842,7 +3843,13 @@ static void amdgpu_dm_do_flip(struct drm_crtc *crtc, surface_updates->flip_addr = &addr; - dc_update_planes_and_stream(adev->dm.dc, surface_updates, 1, acrtc_state->stream, NULL); + dc_commit_updates_for_stream(adev->dm.dc, + surface_updates, + 1, + acrtc_state->stream, + NULL, + &surface_updates->surface, + state); DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", __func__, @@ -3868,6 +3875,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, struct drm_crtc_state *new_pcrtc_state = drm_atomic_get_new_crtc_state(state, pcrtc); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(new_pcrtc_state); + struct dm_atomic_state *dm_state = to_dm_atomic_state(state); int planes_count = 0; unsigned long flags; @@ -3925,7 +3933,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, amdgpu_dm_do_flip( crtc, fb, - drm_crtc_vblank_count(crtc) + *wait_for_vblank); + drm_crtc_vblank_count(crtc) + *wait_for_vblank, + dm_state->context); } } @@ -3945,7 +3954,8 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, if (false == dc_commit_planes_to_stream(dm->dc, plane_states_constructed, planes_count, - dc_stream_attach)) + dc_stream_attach, + dm_state->context)) dm_error("%s: Failed to attach plane!\n", __func__); } else { /*TODO BUG Here should go disable planes on CRTC. */ @@ -4165,7 +4175,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm->dc, status->plane_states, status->plane_count, - dm_new_crtc_state->stream)) + dm_new_crtc_state->stream, + dm_state->context)) dm_error("%s: Failed to update stream scaling!\n", __func__); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 47f16a4b9f27146cc43fe97681683a2e2a8f3bc5..1ec6df9870da1d12f26e3ef369e40fbfb294c88e 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -869,7 +869,8 @@ bool dc_commit_planes_to_stream( struct dc *dc, struct dc_plane_state **plane_states, uint8_t new_plane_count, - struct dc_stream_state *dc_stream) + struct dc_stream_state *dc_stream, + struct dc_state *state) { struct dc_surface_update updates[MAX_SURFACES]; struct dc_flip_addrs flip_addr[MAX_SURFACES]; @@ -920,11 +921,11 @@ bool dc_commit_planes_to_stream( updates[i].scaling_info = &scaling_info[i]; } - dc_update_planes_and_stream( + dc_commit_updates_for_stream( dc, updates, new_plane_count, - dc_stream, stream_update); + dc_stream, stream_update, plane_states, state); dc_post_update_surfaces_to_stream(dc); @@ -1150,192 +1151,20 @@ static struct dc_stream_status *stream_get_status( static const enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; -void dc_update_planes_and_stream(struct dc *dc, - struct dc_surface_update *srf_updates, int surface_count, + +static void commit_planes_for_stream(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_stream_update *stream_update, + enum surface_update_type update_type, + struct dc_state *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; - - stream_status = dc_stream_get_status(stream); - - ASSERT(stream_status); - if (!stream_status) - return; /* Cannot commit surface to stream that is not committed */ - -#ifdef ENABLE_FBC - if (srf_updates->flip_addr) { - if (srf_updates->flip_addr->address.grph.addr.low_part == 0) - ASSERT(0); - } -#endif - context = dc->current_state; - - /* update current stream with the new updates */ - if (stream_update) { - if ((stream_update->src.height != 0) && - (stream_update->src.width != 0)) - stream->src = stream_update->src; - - if ((stream_update->dst.height != 0) && - (stream_update->dst.width != 0)) - stream->dst = stream_update->dst; - - if (stream_update->out_transfer_func && - stream_update->out_transfer_func != - stream->out_transfer_func) { - if (stream->out_transfer_func != NULL) - dc_transfer_func_release(stream->out_transfer_func); - dc_transfer_func_retain(stream_update->out_transfer_func); - stream->out_transfer_func = - stream_update->out_transfer_func; - } - } - - /* do not perform surface update if surface has invalid dimensions - * (all zero) and no scaling_info is provided - */ - if (surface_count > 0 && - srf_updates->surface->src_rect.width == 0 && - srf_updates->surface->src_rect.height == 0 && - srf_updates->surface->dst_rect.width == 0 && - srf_updates->surface->dst_rect.height == 0 && - !srf_updates->scaling_info) { - ASSERT(false); - return; - } - - update_type = dc_check_update_surfaces_for_stream( - dc, srf_updates, surface_count, stream_update, stream_status); - - if (update_type >= update_surface_trace_level) - update_surface_trace(dc, srf_updates, surface_count); - - if (update_type >= UPDATE_TYPE_FULL) { - struct dc_plane_state *new_planes[MAX_SURFACES] = {0}; - - for (i = 0; i < surface_count; i++) - new_planes[i] = srf_updates[i].surface; - - /* initialize scratch memory for building context */ - context = dc_create_state(); - if (context == NULL) { - DC_ERROR("Failed to allocate new validate context!\n"); - return; - } - - dc_resource_state_copy_construct( - dc->current_state, context); - - /*remove old surfaces from context */ - if (!dc_rem_all_planes_for_stream(dc, stream, context)) { - - BREAK_TO_DEBUGGER(); - goto fail; - } - - /* add surface to context */ - if (!dc_add_all_planes_for_stream(dc, stream, new_planes, surface_count, context)) { - - BREAK_TO_DEBUGGER(); - goto fail; - } - } - - /* save update parameters into surface */ - for (i = 0; i < surface_count; i++) { - struct dc_plane_state *surface = srf_updates[i].surface; - - if (srf_updates[i].flip_addr) { - surface->address = srf_updates[i].flip_addr->address; - surface->flip_immediate = - srf_updates[i].flip_addr->flip_immediate; - } - - if (srf_updates[i].scaling_info) { - surface->scaling_quality = - srf_updates[i].scaling_info->scaling_quality; - surface->dst_rect = - srf_updates[i].scaling_info->dst_rect; - surface->src_rect = - srf_updates[i].scaling_info->src_rect; - surface->clip_rect = - srf_updates[i].scaling_info->clip_rect; - } - - if (srf_updates[i].plane_info) { - surface->color_space = - srf_updates[i].plane_info->color_space; - surface->format = - srf_updates[i].plane_info->format; - surface->plane_size = - srf_updates[i].plane_info->plane_size; - surface->rotation = - srf_updates[i].plane_info->rotation; - surface->horizontal_mirror = - srf_updates[i].plane_info->horizontal_mirror; - surface->stereo_format = - srf_updates[i].plane_info->stereo_format; - surface->tiling_info = - srf_updates[i].plane_info->tiling_info; - surface->visible = - srf_updates[i].plane_info->visible; - surface->per_pixel_alpha = - srf_updates[i].plane_info->per_pixel_alpha; - surface->dcc = - srf_updates[i].plane_info->dcc; - } - - if (update_type >= UPDATE_TYPE_MED) { - 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 != surface) - continue; - - resource_build_scaling_params(pipe_ctx); - } - } - - if (srf_updates[i].gamma && - srf_updates[i].gamma != surface->gamma_correction) { - if (surface->gamma_correction != NULL) - dc_gamma_release(&surface->gamma_correction); - - dc_gamma_retain(srf_updates[i].gamma); - surface->gamma_correction = srf_updates[i].gamma; - } - - if (srf_updates[i].in_transfer_func && - srf_updates[i].in_transfer_func != surface->in_transfer_func) { - if (surface->in_transfer_func != NULL) - dc_transfer_func_release( - surface-> - in_transfer_func); - - dc_transfer_func_retain( - srf_updates[i].in_transfer_func); - surface->in_transfer_func = - srf_updates[i].in_transfer_func; - } - - if (srf_updates[i].hdr_static_metadata) - surface->hdr_static_ctx = - *(srf_updates[i].hdr_static_metadata); - } if (update_type == UPDATE_TYPE_FULL) { - if (!dc->res_pool->funcs->validate_bandwidth(dc, context)) { - BREAK_TO_DEBUGGER(); - goto fail; - } else { - dc->hwss.set_bandwidth(dc, context, false); - context_clock_trace(dc, context); - } + dc->hwss.set_bandwidth(dc, context, false); + context_clock_trace(dc, context); } if (update_type > UPDATE_TYPE_FAST) { @@ -1459,27 +1288,60 @@ void dc_update_planes_and_stream(struct dc *dc, break; } } +} + +void dc_commit_updates_for_stream(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_plane_state **plane_states, + struct dc_state *state) +{ + const struct dc_stream_status *stream_status; + enum surface_update_type update_type; + struct dc_state *context; + int i; - if (dc->current_state != context) { + stream_status = dc_stream_get_status(stream); + context = dc->current_state; + + update_type = dc_check_update_surfaces_for_stream( + dc, srf_updates, surface_count, stream_update, stream_status); + + if (update_type >= update_surface_trace_level) + update_surface_trace(dc, srf_updates, surface_count); - /* Since memory free requires elevated IRQL, an interrupt - * request is generated by mem free. If this happens - * between freeing and reassigning the context, our vsync - * interrupt will call into dc and cause a memory - * corruption BSOD. Hence, we first reassign the context, - * then free the old context. - */ - struct dc_state *old = dc->current_state; + if (update_type >= UPDATE_TYPE_FULL) + dc_resource_state_copy_construct(state, context); - dc->current_state = context; - dc_release_state(old); + + for (i = 0; i < surface_count; i++) { + struct dc_plane_state *surface = srf_updates[i].surface; + + /* TODO: On flip we don't build the state, so it still has the + * old address. Which is why we are updating the address here + */ + if (srf_updates[i].flip_addr) + surface->address = srf_updates[i].flip_addr->address; } + + + commit_planes_for_stream( + dc, + srf_updates, + surface_count, + stream, + stream_update, + update_type, + context); + + dc_post_update_surfaces_to_stream(dc); + return; -fail: - dc_release_state(context); } uint8_t dc_get_current_stream_count(struct dc *dc) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 4ff543826476c469fb530cfe06fce08dd0636f7f..50440731f83c7976ee206504ed8192d7871a5fb9 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -449,23 +449,6 @@ struct dc_flip_addrs { /* TODO: add flip duration for FreeSync */ }; -/* - * Set up surface attributes and associate to a stream - * The surfaces parameter is an absolute set of all surface active for the stream. - * If no surfaces are provided, the stream will be blanked; no memory read. - * Any flip related attribute changes must be done through this interface. - * - * After this call: - * Surfaces attributes are programmed and configured to be composed into stream. - * This does not trigger a flip. No surface address is programmed. - */ - -bool dc_commit_planes_to_stream( - struct dc *dc, - struct dc_plane_state **plane_states, - uint8_t new_plane_count, - struct dc_stream_state *stream); - bool dc_post_update_surfaces_to_stream( struct dc *dc); @@ -571,9 +554,6 @@ bool dc_is_stream_unchanged( struct dc_stream_state *old_stream, struct dc_stream_state *stream); /* - * Setup stream attributes if no stream updates are provided - * there will be no impact on the stream parameters - * * Set up surface attributes and associate to a stream * The surfaces parameter is an absolute set of all surface active for the stream. * If no surfaces are provided, the stream will be blanked; no memory read. @@ -582,14 +562,22 @@ bool dc_is_stream_unchanged( * After this call: * Surfaces attributes are programmed and configured to be composed into stream. * This does not trigger a flip. No surface address is programmed. - * */ -void dc_update_planes_and_stream(struct dc *dc, - struct dc_surface_update *surface_updates, int surface_count, +bool dc_commit_planes_to_stream( + struct dc *dc, + struct dc_plane_state **plane_states, + uint8_t new_plane_count, struct dc_stream_state *dc_stream, - struct dc_stream_update *stream_update); + struct dc_state *state); +void dc_commit_updates_for_stream(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_plane_state **plane_states, + struct dc_state *state); /* * Log the current stream state. */