Commit a9b1a4f6 authored by Nicholas Kazlauskas's avatar Nicholas Kazlauskas Committed by Alex Deucher

drm/amd/display: Add more checks for exiting idle in DC

[Why]
Any interface that touches registers needs to wake up the system.

[How]
Add a new interface dc_exit_ips_for_hw_access that wraps the check
for IPS support and insert it into the public DC interfaces that
touch registers.

We don't re-enter, since we expect that the enter/exit to have been done
on the DM side.

Cc: stable@vger.kernel.org # 6.1+
Reviewed-by: default avatarOvidiu Bunea <ovidiu.bunea@amd.com>
Acked-by: default avatarHamza Mahfooz <hamza.mahfooz@amd.com>
Signed-off-by: default avatarNicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent db839147
...@@ -417,6 +417,8 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc, ...@@ -417,6 +417,8 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
if (!memcmp(&stream->adjust, adjust, sizeof(*adjust))) if (!memcmp(&stream->adjust, adjust, sizeof(*adjust)))
return true; return true;
dc_exit_ips_for_hw_access(dc);
stream->adjust.v_total_max = adjust->v_total_max; stream->adjust.v_total_max = adjust->v_total_max;
stream->adjust.v_total_mid = adjust->v_total_mid; stream->adjust.v_total_mid = adjust->v_total_mid;
stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num; stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
...@@ -457,6 +459,8 @@ bool dc_stream_get_last_used_drr_vtotal(struct dc *dc, ...@@ -457,6 +459,8 @@ bool dc_stream_get_last_used_drr_vtotal(struct dc *dc,
int i = 0; int i = 0;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
...@@ -487,6 +491,8 @@ bool dc_stream_get_crtc_position(struct dc *dc, ...@@ -487,6 +491,8 @@ bool dc_stream_get_crtc_position(struct dc *dc,
bool ret = false; bool ret = false;
struct crtc_position position; struct crtc_position position;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe = struct pipe_ctx *pipe =
&dc->current_state->res_ctx.pipe_ctx[i]; &dc->current_state->res_ctx.pipe_ctx[i];
...@@ -606,6 +612,8 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream, ...@@ -606,6 +612,8 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
if (pipe == NULL) if (pipe == NULL)
return false; return false;
dc_exit_ips_for_hw_access(dc);
/* By default, capture the full frame */ /* By default, capture the full frame */
param.windowa_x_start = 0; param.windowa_x_start = 0;
param.windowa_y_start = 0; param.windowa_y_start = 0;
...@@ -665,6 +673,8 @@ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream, ...@@ -665,6 +673,8 @@ bool dc_stream_get_crc(struct dc *dc, struct dc_stream_state *stream,
struct pipe_ctx *pipe; struct pipe_ctx *pipe;
struct timing_generator *tg; struct timing_generator *tg;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
pipe = &dc->current_state->res_ctx.pipe_ctx[i]; pipe = &dc->current_state->res_ctx.pipe_ctx[i];
if (pipe->stream == stream) if (pipe->stream == stream)
...@@ -689,6 +699,8 @@ void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream, ...@@ -689,6 +699,8 @@ void dc_stream_set_dyn_expansion(struct dc *dc, struct dc_stream_state *stream,
int i; int i;
struct pipe_ctx *pipe_ctx; struct pipe_ctx *pipe_ctx;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
if (dc->current_state->res_ctx.pipe_ctx[i].stream if (dc->current_state->res_ctx.pipe_ctx[i].stream
== stream) { == stream) {
...@@ -724,6 +736,8 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream, ...@@ -724,6 +736,8 @@ void dc_stream_set_dither_option(struct dc_stream_state *stream,
if (option > DITHER_OPTION_MAX) if (option > DITHER_OPTION_MAX)
return; return;
dc_exit_ips_for_hw_access(stream->ctx->dc);
stream->dither_option = option; stream->dither_option = option;
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
...@@ -748,6 +762,8 @@ bool dc_stream_set_gamut_remap(struct dc *dc, const struct dc_stream_state *stre ...@@ -748,6 +762,8 @@ bool dc_stream_set_gamut_remap(struct dc *dc, const struct dc_stream_state *stre
bool ret = false; bool ret = false;
struct pipe_ctx *pipes; struct pipe_ctx *pipes;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) { if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream) {
pipes = &dc->current_state->res_ctx.pipe_ctx[i]; pipes = &dc->current_state->res_ctx.pipe_ctx[i];
...@@ -765,6 +781,8 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream) ...@@ -765,6 +781,8 @@ bool dc_stream_program_csc_matrix(struct dc *dc, struct dc_stream_state *stream)
bool ret = false; bool ret = false;
struct pipe_ctx *pipes; struct pipe_ctx *pipes;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
if (dc->current_state->res_ctx.pipe_ctx[i].stream if (dc->current_state->res_ctx.pipe_ctx[i].stream
== stream) { == stream) {
...@@ -791,6 +809,8 @@ void dc_stream_set_static_screen_params(struct dc *dc, ...@@ -791,6 +809,8 @@ void dc_stream_set_static_screen_params(struct dc *dc,
struct pipe_ctx *pipes_affected[MAX_PIPES]; struct pipe_ctx *pipes_affected[MAX_PIPES];
int num_pipes_affected = 0; int num_pipes_affected = 0;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < num_streams; i++) { for (i = 0; i < num_streams; i++) {
struct dc_stream_state *stream = streams[i]; struct dc_stream_state *stream = streams[i];
...@@ -1769,6 +1789,8 @@ void dc_enable_stereo( ...@@ -1769,6 +1789,8 @@ void dc_enable_stereo(
int i, j; int i, j;
struct pipe_ctx *pipe; struct pipe_ctx *pipe;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
if (context != NULL) { if (context != NULL) {
pipe = &context->res_ctx.pipe_ctx[i]; pipe = &context->res_ctx.pipe_ctx[i];
...@@ -1788,6 +1810,8 @@ void dc_enable_stereo( ...@@ -1788,6 +1810,8 @@ void dc_enable_stereo(
void dc_trigger_sync(struct dc *dc, struct dc_state *context) void dc_trigger_sync(struct dc *dc, struct dc_state *context)
{ {
if (context->stream_count > 1 && !dc->debug.disable_timing_sync) { if (context->stream_count > 1 && !dc->debug.disable_timing_sync) {
dc_exit_ips_for_hw_access(dc);
enable_timing_multisync(dc, context); enable_timing_multisync(dc, context);
program_timing_sync(dc, context); program_timing_sync(dc, context);
} }
...@@ -2044,6 +2068,8 @@ enum dc_status dc_commit_streams(struct dc *dc, ...@@ -2044,6 +2068,8 @@ enum dc_status dc_commit_streams(struct dc *dc,
if (!streams_changed(dc, streams, stream_count)) if (!streams_changed(dc, streams, stream_count))
return res; return res;
dc_exit_ips_for_hw_access(dc);
DC_LOG_DC("%s: %d streams\n", __func__, stream_count); DC_LOG_DC("%s: %d streams\n", __func__, stream_count);
for (i = 0; i < stream_count; i++) { for (i = 0; i < stream_count; i++) {
...@@ -3373,6 +3399,8 @@ static void commit_planes_for_stream_fast(struct dc *dc, ...@@ -3373,6 +3399,8 @@ static void commit_planes_for_stream_fast(struct dc *dc,
int i, j; int i, j;
struct pipe_ctx *top_pipe_to_program = NULL; struct pipe_ctx *top_pipe_to_program = NULL;
struct dc_stream_status *stream_status = NULL; struct dc_stream_status *stream_status = NULL;
dc_exit_ips_for_hw_access(dc);
dc_z10_restore(dc); dc_z10_restore(dc);
top_pipe_to_program = resource_get_otg_master_for_stream( top_pipe_to_program = resource_get_otg_master_for_stream(
...@@ -3527,6 +3555,8 @@ static void commit_planes_for_stream(struct dc *dc, ...@@ -3527,6 +3555,8 @@ static void commit_planes_for_stream(struct dc *dc,
// dc->current_state anymore, so we have to cache it before we apply // dc->current_state anymore, so we have to cache it before we apply
// the new SubVP context // the new SubVP context
subvp_prev_use = false; subvp_prev_use = false;
dc_exit_ips_for_hw_access(dc);
dc_z10_restore(dc); dc_z10_restore(dc);
if (update_type == UPDATE_TYPE_FULL) if (update_type == UPDATE_TYPE_FULL)
wait_for_outstanding_hw_updates(dc, context); wait_for_outstanding_hw_updates(dc, context);
...@@ -4409,6 +4439,8 @@ bool dc_update_planes_and_stream(struct dc *dc, ...@@ -4409,6 +4439,8 @@ bool dc_update_planes_and_stream(struct dc *dc,
bool is_plane_addition = 0; bool is_plane_addition = 0;
bool is_fast_update_only; bool is_fast_update_only;
dc_exit_ips_for_hw_access(dc);
populate_fast_updates(fast_update, srf_updates, surface_count, stream_update); populate_fast_updates(fast_update, srf_updates, surface_count, stream_update);
is_fast_update_only = fast_update_only(dc, fast_update, srf_updates, is_fast_update_only = fast_update_only(dc, fast_update, srf_updates,
surface_count, stream_update, stream); surface_count, stream_update, stream);
...@@ -4529,6 +4561,8 @@ void dc_commit_updates_for_stream(struct dc *dc, ...@@ -4529,6 +4561,8 @@ void dc_commit_updates_for_stream(struct dc *dc,
int i, j; int i, j;
struct dc_fast_update fast_update[MAX_SURFACES] = {0}; struct dc_fast_update fast_update[MAX_SURFACES] = {0};
dc_exit_ips_for_hw_access(dc);
populate_fast_updates(fast_update, srf_updates, surface_count, stream_update); populate_fast_updates(fast_update, srf_updates, surface_count, stream_update);
stream_status = dc_stream_get_status(stream); stream_status = dc_stream_get_status(stream);
context = dc->current_state; context = dc->current_state;
...@@ -4713,6 +4747,8 @@ void dc_set_power_state( ...@@ -4713,6 +4747,8 @@ void dc_set_power_state(
case DC_ACPI_CM_POWER_STATE_D0: case DC_ACPI_CM_POWER_STATE_D0:
dc_state_construct(dc, dc->current_state); dc_state_construct(dc, dc->current_state);
dc_exit_ips_for_hw_access(dc);
dc_z10_restore(dc); dc_z10_restore(dc);
dc->hwss.init_hw(dc); dc->hwss.init_hw(dc);
...@@ -4854,6 +4890,12 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow) ...@@ -4854,6 +4890,12 @@ void dc_allow_idle_optimizations(struct dc *dc, bool allow)
dc->idle_optimizations_allowed = allow; dc->idle_optimizations_allowed = allow;
} }
void dc_exit_ips_for_hw_access(struct dc *dc)
{
if (dc->caps.ips_support)
dc_allow_idle_optimizations(dc, false);
}
bool dc_dmub_is_ips_idle_state(struct dc *dc) bool dc_dmub_is_ips_idle_state(struct dc *dc)
{ {
uint32_t idle_state = 0; uint32_t idle_state = 0;
......
...@@ -423,6 +423,8 @@ bool dc_stream_add_writeback(struct dc *dc, ...@@ -423,6 +423,8 @@ bool dc_stream_add_writeback(struct dc *dc,
return false; return false;
} }
dc_exit_ips_for_hw_access(dc);
wb_info->dwb_params.out_transfer_func = stream->out_transfer_func; wb_info->dwb_params.out_transfer_func = stream->out_transfer_func;
dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst]; dwb = dc->res_pool->dwbc[wb_info->dwb_pipe_inst];
...@@ -493,6 +495,8 @@ bool dc_stream_fc_disable_writeback(struct dc *dc, ...@@ -493,6 +495,8 @@ bool dc_stream_fc_disable_writeback(struct dc *dc,
return false; return false;
} }
dc_exit_ips_for_hw_access(dc);
if (dwb->funcs->set_fc_enable) if (dwb->funcs->set_fc_enable)
dwb->funcs->set_fc_enable(dwb, DWB_FRAME_CAPTURE_DISABLE); dwb->funcs->set_fc_enable(dwb, DWB_FRAME_CAPTURE_DISABLE);
...@@ -542,6 +546,8 @@ bool dc_stream_remove_writeback(struct dc *dc, ...@@ -542,6 +546,8 @@ bool dc_stream_remove_writeback(struct dc *dc,
return false; return false;
} }
dc_exit_ips_for_hw_access(dc);
/* disable writeback */ /* disable writeback */
if (dc->hwss.disable_writeback) { if (dc->hwss.disable_writeback) {
struct dwbc *dwb = dc->res_pool->dwbc[dwb_pipe_inst]; struct dwbc *dwb = dc->res_pool->dwbc[dwb_pipe_inst];
...@@ -557,6 +563,8 @@ bool dc_stream_warmup_writeback(struct dc *dc, ...@@ -557,6 +563,8 @@ bool dc_stream_warmup_writeback(struct dc *dc,
int num_dwb, int num_dwb,
struct dc_writeback_info *wb_info) struct dc_writeback_info *wb_info)
{ {
dc_exit_ips_for_hw_access(dc);
if (dc->hwss.mmhubbub_warmup) if (dc->hwss.mmhubbub_warmup)
return dc->hwss.mmhubbub_warmup(dc, num_dwb, wb_info); return dc->hwss.mmhubbub_warmup(dc, num_dwb, wb_info);
else else
...@@ -569,6 +577,8 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream) ...@@ -569,6 +577,8 @@ uint32_t dc_stream_get_vblank_counter(const struct dc_stream_state *stream)
struct resource_context *res_ctx = struct resource_context *res_ctx =
&dc->current_state->res_ctx; &dc->current_state->res_ctx;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
...@@ -597,6 +607,8 @@ bool dc_stream_send_dp_sdp(const struct dc_stream_state *stream, ...@@ -597,6 +607,8 @@ bool dc_stream_send_dp_sdp(const struct dc_stream_state *stream,
dc = stream->ctx->dc; dc = stream->ctx->dc;
res_ctx = &dc->current_state->res_ctx; res_ctx = &dc->current_state->res_ctx;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &res_ctx->pipe_ctx[i];
...@@ -628,6 +640,8 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream, ...@@ -628,6 +640,8 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,
struct resource_context *res_ctx = struct resource_context *res_ctx =
&dc->current_state->res_ctx; &dc->current_state->res_ctx;
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < MAX_PIPES; i++) { for (i = 0; i < MAX_PIPES; i++) {
struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg; struct timing_generator *tg = res_ctx->pipe_ctx[i].stream_res.tg;
...@@ -664,6 +678,8 @@ bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream) ...@@ -664,6 +678,8 @@ bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream)
if (i == MAX_PIPES) if (i == MAX_PIPES)
return true; return true;
dc_exit_ips_for_hw_access(dc);
return dc->hwss.dmdata_status_done(pipe); return dc->hwss.dmdata_status_done(pipe);
} }
...@@ -698,6 +714,8 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc, ...@@ -698,6 +714,8 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc,
pipe_ctx->stream->dmdata_address = attr->address; pipe_ctx->stream->dmdata_address = attr->address;
dc_exit_ips_for_hw_access(dc);
dc->hwss.program_dmdata_engine(pipe_ctx); dc->hwss.program_dmdata_engine(pipe_ctx);
if (hubp->funcs->dmdata_set_attributes != NULL && if (hubp->funcs->dmdata_set_attributes != NULL &&
......
...@@ -161,6 +161,8 @@ const struct dc_plane_status *dc_plane_get_status( ...@@ -161,6 +161,8 @@ const struct dc_plane_status *dc_plane_get_status(
break; break;
} }
dc_exit_ips_for_hw_access(dc);
for (i = 0; i < dc->res_pool->pipe_count; i++) { for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = struct pipe_ctx *pipe_ctx =
&dc->current_state->res_ctx.pipe_ctx[i]; &dc->current_state->res_ctx.pipe_ctx[i];
......
...@@ -2325,6 +2325,7 @@ bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_ ...@@ -2325,6 +2325,7 @@ bool dc_is_plane_eligible_for_idle_optimizations(struct dc *dc, struct dc_plane_
struct dc_cursor_attributes *cursor_attr); struct dc_cursor_attributes *cursor_attr);
void dc_allow_idle_optimizations(struct dc *dc, bool allow); void dc_allow_idle_optimizations(struct dc *dc, bool allow);
void dc_exit_ips_for_hw_access(struct dc *dc);
bool dc_dmub_is_ips_idle_state(struct dc *dc); bool dc_dmub_is_ips_idle_state(struct dc *dc);
/* set min and max memory clock to lowest and highest DPM level, respectively */ /* set min and max memory clock to lowest and highest DPM level, respectively */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment