Commit 57430404 authored by Su Sung Chung's avatar Su Sung Chung Committed by Alex Deucher

drm/amd/display: fix audio endpoint not getting disabled issue

[Why]
Disable_audio_stream gets enum option as a paramenter which will decide
if we free acquired resources or not. However checks for the option is
guarded by the other condition which check if audio stream is getting
diabled more than once. With both conditions combined, if we attempt to
disable audio stream twice in a row, first with keep and second with
free as an option, we will never free any resources, which will make
system think there is audio endpoint connected even after we plug out
the device

[How]
Get rid of option as parameter to disable_audio_stream and move the part
of the code that free acquired resources to outside where to keep or to
free resources is actually determined
Signed-off-by: default avatarSu Sung Chung <Su.Chung@amd.com>
Reviewed-by: default avatarJun Lei <Jun.Lei@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 67427d4f
...@@ -1918,7 +1918,11 @@ static void commit_planes_do_stream_update(struct dc *dc, ...@@ -1918,7 +1918,11 @@ static void commit_planes_do_stream_update(struct dc *dc,
dc->hwss.pipe_control_lock(dc, pipe_ctx, true); dc->hwss.pipe_control_lock(dc, pipe_ctx, true);
if (*stream_update->dpms_off) { if (*stream_update->dpms_off) {
core_link_disable_stream(pipe_ctx, KEEP_ACQUIRED_RESOURCE); core_link_disable_stream(pipe_ctx);
/* for dpms, keep acquired resources*/
if (pipe_ctx->stream_res.audio && !dc->debug.az_endpoint_mute_only)
pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
dc->hwss.optimize_bandwidth(dc, dc->current_state); dc->hwss.optimize_bandwidth(dc, dc->current_state);
} else { } else {
if (!dc->optimize_seamless_boot) if (!dc->optimize_seamless_boot)
......
...@@ -2804,7 +2804,7 @@ void core_link_enable_stream( ...@@ -2804,7 +2804,7 @@ void core_link_enable_stream(
#endif #endif
} }
void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) void core_link_disable_stream(struct pipe_ctx *pipe_ctx)
{ {
struct dc *core_dc = pipe_ctx->stream->ctx->dc; struct dc *core_dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream; struct dc_stream_state *stream = pipe_ctx->stream;
...@@ -2839,7 +2839,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option) ...@@ -2839,7 +2839,7 @@ void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option)
write_i2c_redriver_setting(pipe_ctx, false); write_i2c_redriver_setting(pipe_ctx, false);
} }
} }
core_dc->hwss.disable_stream(pipe_ctx, option); core_dc->hwss.disable_stream(pipe_ctx);
disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal); disable_link(pipe_ctx->stream->link, pipe_ctx->stream->signal);
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
......
...@@ -289,7 +289,9 @@ void dp_retrain_link_dp_test(struct dc_link *link, ...@@ -289,7 +289,9 @@ void dp_retrain_link_dp_test(struct dc_link *link,
dp_receiver_power_ctrl(link, false); dp_receiver_power_ctrl(link, false);
link->dc->hwss.disable_stream(&pipes[i], KEEP_ACQUIRED_RESOURCE); link->dc->hwss.disable_stream(&pipes[i]);
if ((&pipes[i])->stream_res.audio && !link->dc->debug.az_endpoint_mute_only)
(&pipes[i])->stream_res.audio->funcs->az_disable((&pipes[i])->stream_res.audio);
link->link_enc->funcs->disable_output( link->link_enc->funcs->disable_output(
link->link_enc, link->link_enc,
......
...@@ -981,7 +981,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) ...@@ -981,7 +981,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
} }
} }
void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
{ {
struct dc *dc; struct dc *dc;
struct pp_smu_funcs *pp_smu = NULL; struct pp_smu_funcs *pp_smu = NULL;
...@@ -1004,24 +1004,13 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) ...@@ -1004,24 +1004,13 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
if (dc->res_pool->pp_smu) if (dc->res_pool->pp_smu)
pp_smu = dc->res_pool->pp_smu; pp_smu = dc->res_pool->pp_smu;
if (option != KEEP_ACQUIRED_RESOURCE ||
!dc->debug.az_endpoint_mute_only)
/*only disalbe az_endpoint if power down or free*/
pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
if (dc_is_dp_signal(pipe_ctx->stream->signal)) if (dc_is_dp_signal(pipe_ctx->stream->signal))
pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable( pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc);
else else
pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable( pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc);
/*don't free audio if it is from retrain or internal disable stream*/
if (option == FREE_ACQUIRED_RESOURCE && dc->caps.dynamic_audio == true) {
/*we have to dynamic arbitrate the audio endpoints*/
/*we free the resource, need reset is_audio_acquired*/
update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
pipe_ctx->stream_res.audio = NULL;
}
if (clk_mgr->funcs->enable_pme_wa) if (clk_mgr->funcs->enable_pme_wa)
/*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
clk_mgr->funcs->enable_pme_wa(clk_mgr); clk_mgr->funcs->enable_pme_wa(clk_mgr);
...@@ -1034,7 +1023,7 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) ...@@ -1034,7 +1023,7 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
} }
} }
void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
{ {
struct dc_stream_state *stream = pipe_ctx->stream; struct dc_stream_state *stream = pipe_ctx->stream;
struct dc_link *link = stream->link; struct dc_link *link = stream->link;
...@@ -1051,7 +1040,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) ...@@ -1051,7 +1040,7 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option)
pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets(
pipe_ctx->stream_res.stream_enc); pipe_ctx->stream_res.stream_enc);
dc->hwss.disable_audio_stream(pipe_ctx, option); dc->hwss.disable_audio_stream(pipe_ctx);
link->link_enc->funcs->connect_dig_be_to_fe( link->link_enc->funcs->connect_dig_be_to_fe(
link->link_enc, link->link_enc,
...@@ -1914,8 +1903,25 @@ static void dce110_reset_hw_ctx_wrap( ...@@ -1914,8 +1903,25 @@ static void dce110_reset_hw_ctx_wrap(
/* Disable if new stream is null. O/w, if stream is /* Disable if new stream is null. O/w, if stream is
* disabled already, no need to disable again. * disabled already, no need to disable again.
*/ */
if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) if (!pipe_ctx->stream || !pipe_ctx->stream->dpms_off) {
core_link_disable_stream(pipe_ctx_old, FREE_ACQUIRED_RESOURCE); core_link_disable_stream(pipe_ctx_old);
/* free acquired resources*/
if (pipe_ctx_old->stream_res.audio) {
/*disable az_endpoint*/
pipe_ctx_old->stream_res.audio->funcs->
az_disable(pipe_ctx_old->stream_res.audio);
/*free audio*/
if (dc->caps.dynamic_audio == true) {
/*we have to dynamic arbitrate the audio endpoints*/
/*we free the resource, need reset is_audio_acquired*/
update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
pipe_ctx_old->stream_res.audio, false);
pipe_ctx_old->stream_res.audio = NULL;
}
}
}
pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true); pipe_ctx_old->stream_res.tg->funcs->set_blank(pipe_ctx_old->stream_res.tg, true);
if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) { if (!hwss_wait_for_blank_complete(pipe_ctx_old->stream_res.tg)) {
......
...@@ -42,7 +42,7 @@ enum dc_status dce110_apply_ctx_to_hw( ...@@ -42,7 +42,7 @@ enum dc_status dce110_apply_ctx_to_hw(
void dce110_enable_stream(struct pipe_ctx *pipe_ctx); void dce110_enable_stream(struct pipe_ctx *pipe_ctx);
void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option); void dce110_disable_stream(struct pipe_ctx *pipe_ctx);
void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link_settings *link_settings); struct dc_link_settings *link_settings);
...@@ -50,7 +50,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, ...@@ -50,7 +50,7 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
void dce110_blank_stream(struct pipe_ctx *pipe_ctx); void dce110_blank_stream(struct pipe_ctx *pipe_ctx);
void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx); void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx);
void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option); void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx);
void dce110_update_info_frame(struct pipe_ctx *pipe_ctx); void dce110_update_info_frame(struct pipe_ctx *pipe_ctx);
......
...@@ -828,11 +828,23 @@ static void dcn10_reset_back_end_for_pipe( ...@@ -828,11 +828,23 @@ static void dcn10_reset_back_end_for_pipe(
if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
/* DPMS may already disable */ /* DPMS may already disable */
if (!pipe_ctx->stream->dpms_off) if (!pipe_ctx->stream->dpms_off)
core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); core_link_disable_stream(pipe_ctx);
else if (pipe_ctx->stream_res.audio) { else if (pipe_ctx->stream_res.audio)
dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); dc->hwss.disable_audio_stream(pipe_ctx);
}
if (pipe_ctx->stream_res.audio) {
/*disable az_endpoint*/
pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
/*free audio*/
if (dc->caps.dynamic_audio == true) {
/*we have to dynamic arbitrate the audio endpoints*/
/*we free the resource, need reset is_audio_acquired*/
update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
pipe_ctx->stream_res.audio, false);
pipe_ctx->stream_res.audio = NULL;
}
}
} }
/* by upper caller loop, parent pipe: pipe0, will be reset last. /* by upper caller loop, parent pipe: pipe0, will be reset last.
......
...@@ -1461,9 +1461,9 @@ void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx) ...@@ -1461,9 +1461,9 @@ void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx)
hubp->funcs->dmdata_set_attributes(hubp, &attr); hubp->funcs->dmdata_set_attributes(hubp, &attr);
} }
void dcn20_disable_stream(struct pipe_ctx *pipe_ctx, int option) void dcn20_disable_stream(struct pipe_ctx *pipe_ctx)
{ {
dce110_disable_stream(pipe_ctx, option); dce110_disable_stream(pipe_ctx);
} }
static void dcn20_init_vm_ctx( static void dcn20_init_vm_ctx(
...@@ -1617,9 +1617,23 @@ static void dcn20_reset_back_end_for_pipe( ...@@ -1617,9 +1617,23 @@ static void dcn20_reset_back_end_for_pipe(
if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) { if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) {
/* DPMS may already disable */ /* DPMS may already disable */
if (!pipe_ctx->stream->dpms_off) if (!pipe_ctx->stream->dpms_off)
core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); core_link_disable_stream(pipe_ctx);
else if (pipe_ctx->stream_res.audio) { else if (pipe_ctx->stream_res.audio)
dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); dc->hwss.disable_audio_stream(pipe_ctx);
/* free acquired resources */
if (pipe_ctx->stream_res.audio) {
/*disable az_endpoint*/
pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio);
/*free audio*/
if (dc->caps.dynamic_audio == true) {
/*we have to dynamic arbitrate the audio endpoints*/
/*we free the resource, need reset is_audio_acquired*/
update_audio_usage(&dc->current_state->res_ctx, dc->res_pool,
pipe_ctx->stream_res.audio, false);
pipe_ctx->stream_res.audio = NULL;
}
} }
} }
#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
......
...@@ -75,7 +75,7 @@ bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx); ...@@ -75,7 +75,7 @@ bool dcn20_dmdata_status_done(struct pipe_ctx *pipe_ctx);
void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx); void dcn20_set_dmdata_attributes(struct pipe_ctx *pipe_ctx);
void dcn20_disable_stream(struct pipe_ctx *pipe_ctx, int option); void dcn20_disable_stream(struct pipe_ctx *pipe_ctx);
void dcn20_program_tripleBuffer( void dcn20_program_tripleBuffer(
const struct dc *dc, const struct dc *dc,
......
...@@ -63,11 +63,6 @@ struct link_init_data { ...@@ -63,11 +63,6 @@ struct link_init_data {
TODO: remove it when DC is complete. */ TODO: remove it when DC is complete. */
}; };
enum {
FREE_ACQUIRED_RESOURCE = 0,
KEEP_ACQUIRED_RESOURCE = 1,
};
struct dc_link *link_create(const struct link_init_data *init_params); struct dc_link *link_create(const struct link_init_data *init_params);
void link_destroy(struct dc_link **link); void link_destroy(struct dc_link **link);
...@@ -82,7 +77,7 @@ void core_link_enable_stream( ...@@ -82,7 +77,7 @@ void core_link_enable_stream(
struct dc_state *state, struct dc_state *state,
struct pipe_ctx *pipe_ctx); struct pipe_ctx *pipe_ctx);
void core_link_disable_stream(struct pipe_ctx *pipe_ctx, int option); void core_link_disable_stream(struct pipe_ctx *pipe_ctx);
void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); void core_link_set_avmute(struct pipe_ctx *pipe_ctx, bool enable);
/********** DAL Core*********************/ /********** DAL Core*********************/
......
...@@ -196,8 +196,7 @@ struct hw_sequencer_funcs { ...@@ -196,8 +196,7 @@ struct hw_sequencer_funcs {
void (*enable_stream)(struct pipe_ctx *pipe_ctx); void (*enable_stream)(struct pipe_ctx *pipe_ctx);
void (*disable_stream)(struct pipe_ctx *pipe_ctx, void (*disable_stream)(struct pipe_ctx *pipe_ctx);
int option);
void (*unblank_stream)(struct pipe_ctx *pipe_ctx, void (*unblank_stream)(struct pipe_ctx *pipe_ctx,
struct dc_link_settings *link_settings); struct dc_link_settings *link_settings);
...@@ -206,7 +205,7 @@ struct hw_sequencer_funcs { ...@@ -206,7 +205,7 @@ struct hw_sequencer_funcs {
void (*enable_audio_stream)(struct pipe_ctx *pipe_ctx); void (*enable_audio_stream)(struct pipe_ctx *pipe_ctx);
void (*disable_audio_stream)(struct pipe_ctx *pipe_ctx, int option); void (*disable_audio_stream)(struct pipe_ctx *pipe_ctx);
void (*pipe_control_lock)( void (*pipe_control_lock)(
struct dc *dc, struct dc *dc,
......
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