diff options
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.14.71/4542-drm-amd-display-Refactor-audio-programming.patch')
-rw-r--r-- | common/recipes-kernel/linux/linux-yocto-4.14.71/4542-drm-amd-display-Refactor-audio-programming.patch | 440 |
1 files changed, 440 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.14.71/4542-drm-amd-display-Refactor-audio-programming.patch b/common/recipes-kernel/linux/linux-yocto-4.14.71/4542-drm-amd-display-Refactor-audio-programming.patch new file mode 100644 index 00000000..10f7bdcc --- /dev/null +++ b/common/recipes-kernel/linux/linux-yocto-4.14.71/4542-drm-amd-display-Refactor-audio-programming.patch @@ -0,0 +1,440 @@ +From 5a2e7ffaa966e64a7c1c07813010ac71b992ee86 Mon Sep 17 00:00:00 2001 +From: Anthony Koo <Anthony.Koo@amd.com> +Date: Thu, 10 May 2018 14:21:47 -0400 +Subject: [PATCH 4542/5725] drm/amd/display: Refactor audio programming + +Signed-off-by: Anthony Koo <Anthony.Koo@amd.com> +Reviewed-by: Aric Cyr <Aric.Cyr@amd.com> +Acked-by: Harry Wentland <harry.wentland@amd.com> +--- + drivers/gpu/drm/amd/display/dc/core/dc_link.c | 24 +- + .../amd/display/dc/dce110/dce110_hw_sequencer.c | 256 ++++++++++++--------- + .../amd/display/dc/dce110/dce110_hw_sequencer.h | 4 + + .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 16 +- + drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h | 5 + + 5 files changed, 163 insertions(+), 142 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c +index 2fa5218..a9485c1 100644 +--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c ++++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c +@@ -1861,28 +1861,6 @@ static enum dc_status enable_link( + break; + } + +- if (pipe_ctx->stream_res.audio && status == DC_OK) { +- struct dc *core_dc = pipe_ctx->stream->ctx->dc; +- /* notify audio driver for audio modes of monitor */ +- struct pp_smu_funcs_rv *pp_smu = core_dc->res_pool->pp_smu; +- unsigned int i, num_audio = 1; +- for (i = 0; i < MAX_PIPES; i++) { +- /*current_state not updated yet*/ +- if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL) +- num_audio++; +- } +- +- pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); +- +- if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) +- /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ +- pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); +- /* un-mute audio */ +- /* TODO: audio should be per stream rather than per link */ +- pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( +- pipe_ctx->stream_res.stream_enc, false); +- } +- + return status; + } + +@@ -2415,6 +2393,8 @@ void core_link_enable_stream( + } + } + ++ core_dc->hwss.enable_audio_stream(pipe_ctx); ++ + /* turn off otg test pattern if enable */ + pipe_ctx->stream_res.tg->funcs->set_test_pattern(pipe_ctx->stream_res.tg, + CONTROLLER_DP_TEST_PATTERN_VIDEOMODE, +diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +index 6b22a53..0544568 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +@@ -972,19 +972,35 @@ void hwss_edp_backlight_control( + edp_receiver_ready_T9(link); + } + +-void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) ++void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx) + { +- struct dc_stream_state *stream = pipe_ctx->stream; +- struct dc_link *link = stream->sink->link; +- struct dc *dc = pipe_ctx->stream->ctx->dc; ++ struct dc *core_dc = pipe_ctx->stream->ctx->dc; ++ /* notify audio driver for audio modes of monitor */ ++ struct pp_smu_funcs_rv *pp_smu = core_dc->res_pool->pp_smu; ++ unsigned int i, num_audio = 1; + +- if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) +- pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( +- pipe_ctx->stream_res.stream_enc); ++ if (pipe_ctx->stream_res.audio) { ++ for (i = 0; i < MAX_PIPES; i++) { ++ /*current_state not updated yet*/ ++ if (core_dc->current_state->res_ctx.pipe_ctx[i].stream_res.audio != NULL) ++ num_audio++; ++ } + +- if (dc_is_dp_signal(pipe_ctx->stream->signal)) +- pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( +- pipe_ctx->stream_res.stream_enc); ++ pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio); ++ ++ if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL) ++ /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/ ++ pp_smu->set_pme_wa_enable(&pp_smu->pp_smu); ++ /* un-mute audio */ ++ /* TODO: audio should be per stream rather than per link */ ++ pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( ++ pipe_ctx->stream_res.stream_enc, false); ++ } ++} ++ ++void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option) ++{ ++ struct dc *dc = pipe_ctx->stream->ctx->dc; + + pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control( + pipe_ctx->stream_res.stream_enc, true); +@@ -1015,7 +1031,23 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) + * stream->stream_engine_id); + */ + } ++} + ++void dce110_disable_stream(struct pipe_ctx *pipe_ctx, int option) ++{ ++ struct dc_stream_state *stream = pipe_ctx->stream; ++ struct dc_link *link = stream->sink->link; ++ struct dc *dc = pipe_ctx->stream->ctx->dc; ++ ++ if (dc_is_hdmi_signal(pipe_ctx->stream->signal)) ++ pipe_ctx->stream_res.stream_enc->funcs->stop_hdmi_info_packets( ++ pipe_ctx->stream_res.stream_enc); ++ ++ if (dc_is_dp_signal(pipe_ctx->stream->signal)) ++ pipe_ctx->stream_res.stream_enc->funcs->stop_dp_info_packets( ++ pipe_ctx->stream_res.stream_enc); ++ ++ dc->hwss.disable_audio_stream(pipe_ctx, option); + + link->link_enc->funcs->connect_dig_be_to_fe( + link->link_enc, +@@ -1308,6 +1340,30 @@ static enum dc_status apply_single_controller_ctx_to_hw( + struct pipe_ctx *pipe_ctx_old = &dc->current_state->res_ctx. + pipe_ctx[pipe_ctx->pipe_idx]; + ++ if (pipe_ctx->stream_res.audio != NULL) { ++ struct audio_output audio_output; ++ ++ build_audio_output(context, pipe_ctx, &audio_output); ++ ++ if (dc_is_dp_signal(pipe_ctx->stream->signal)) ++ pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( ++ pipe_ctx->stream_res.stream_enc, ++ pipe_ctx->stream_res.audio->inst, ++ &pipe_ctx->stream->audio_info); ++ else ++ pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( ++ pipe_ctx->stream_res.stream_enc, ++ pipe_ctx->stream_res.audio->inst, ++ &pipe_ctx->stream->audio_info, ++ &audio_output.crtc_info); ++ ++ pipe_ctx->stream_res.audio->funcs->az_configure( ++ pipe_ctx->stream_res.audio, ++ pipe_ctx->stream->signal, ++ &audio_output.crtc_info, ++ &pipe_ctx->stream->audio_info); ++ } ++ + /* */ + dc->hwss.enable_stream_timing(pipe_ctx, context, dc); + +@@ -1966,6 +2022,86 @@ static void dce110_reset_hw_ctx_wrap( + } + } + ++static void dce110_setup_audio_dto( ++ struct dc *dc, ++ struct dc_state *context) ++{ ++ int i; ++ ++ /* program audio wall clock. use HDMI as clock source if HDMI ++ * audio active. Otherwise, use DP as clock source ++ * first, loop to find any HDMI audio, if not, loop find DP audio ++ */ ++ /* Setup audio rate clock source */ ++ /* Issue: ++ * Audio lag happened on DP monitor when unplug a HDMI monitor ++ * ++ * Cause: ++ * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL ++ * is set to either dto0 or dto1, audio should work fine. ++ * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, ++ * set to dto0 will cause audio lag. ++ * ++ * Solution: ++ * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, ++ * find first available pipe with audio, setup audio wall DTO per topology ++ * instead of per pipe. ++ */ ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; ++ ++ if (pipe_ctx->stream == NULL) ++ continue; ++ ++ if (pipe_ctx->top_pipe) ++ continue; ++ ++ if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) ++ continue; ++ ++ if (pipe_ctx->stream_res.audio != NULL) { ++ struct audio_output audio_output; ++ ++ build_audio_output(context, pipe_ctx, &audio_output); ++ ++ pipe_ctx->stream_res.audio->funcs->wall_dto_setup( ++ pipe_ctx->stream_res.audio, ++ pipe_ctx->stream->signal, ++ &audio_output.crtc_info, ++ &audio_output.pll_info); ++ break; ++ } ++ } ++ ++ /* no HDMI audio is found, try DP audio */ ++ if (i == dc->res_pool->pipe_count) { ++ for (i = 0; i < dc->res_pool->pipe_count; i++) { ++ struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; ++ ++ if (pipe_ctx->stream == NULL) ++ continue; ++ ++ if (pipe_ctx->top_pipe) ++ continue; ++ ++ if (!dc_is_dp_signal(pipe_ctx->stream->signal)) ++ continue; ++ ++ if (pipe_ctx->stream_res.audio != NULL) { ++ struct audio_output audio_output; ++ ++ build_audio_output(context, pipe_ctx, &audio_output); ++ ++ pipe_ctx->stream_res.audio->funcs->wall_dto_setup( ++ pipe_ctx->stream_res.audio, ++ pipe_ctx->stream->signal, ++ &audio_output.crtc_info, ++ &audio_output.pll_info); ++ break; ++ } ++ } ++ } ++} + + enum dc_status dce110_apply_ctx_to_hw( + struct dc *dc, +@@ -2057,79 +2193,8 @@ enum dc_status dce110_apply_ctx_to_hw( + dc->res_pool->display_clock, + context->bw.dce.dispclk_khz * 115 / 100); + } +- /* program audio wall clock. use HDMI as clock source if HDMI +- * audio active. Otherwise, use DP as clock source +- * first, loop to find any HDMI audio, if not, loop find DP audio +- */ +- /* Setup audio rate clock source */ +- /* Issue: +- * Audio lag happened on DP monitor when unplug a HDMI monitor +- * +- * Cause: +- * In case of DP and HDMI connected or HDMI only, DCCG_AUDIO_DTO_SEL +- * is set to either dto0 or dto1, audio should work fine. +- * In case of DP connected only, DCCG_AUDIO_DTO_SEL should be dto1, +- * set to dto0 will cause audio lag. +- * +- * Solution: +- * Not optimized audio wall dto setup. When mode set, iterate pipe_ctx, +- * find first available pipe with audio, setup audio wall DTO per topology +- * instead of per pipe. +- */ +- for (i = 0; i < dc->res_pool->pipe_count; i++) { +- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; +- +- if (pipe_ctx->stream == NULL) +- continue; +- +- if (pipe_ctx->top_pipe) +- continue; +- +- if (pipe_ctx->stream->signal != SIGNAL_TYPE_HDMI_TYPE_A) +- continue; +- +- if (pipe_ctx->stream_res.audio != NULL) { +- struct audio_output audio_output; +- +- build_audio_output(context, pipe_ctx, &audio_output); +- +- pipe_ctx->stream_res.audio->funcs->wall_dto_setup( +- pipe_ctx->stream_res.audio, +- pipe_ctx->stream->signal, +- &audio_output.crtc_info, +- &audio_output.pll_info); +- break; +- } +- } +- +- /* no HDMI audio is found, try DP audio */ +- if (i == dc->res_pool->pipe_count) { +- for (i = 0; i < dc->res_pool->pipe_count; i++) { +- struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; +- +- if (pipe_ctx->stream == NULL) +- continue; +- +- if (pipe_ctx->top_pipe) +- continue; +- +- if (!dc_is_dp_signal(pipe_ctx->stream->signal)) +- continue; +- +- if (pipe_ctx->stream_res.audio != NULL) { +- struct audio_output audio_output; +- +- build_audio_output(context, pipe_ctx, &audio_output); + +- pipe_ctx->stream_res.audio->funcs->wall_dto_setup( +- pipe_ctx->stream_res.audio, +- pipe_ctx->stream->signal, +- &audio_output.crtc_info, +- &audio_output.pll_info); +- break; +- } +- } +- } ++ dce110_setup_audio_dto(dc, context); + + for (i = 0; i < dc->res_pool->pipe_count; i++) { + struct pipe_ctx *pipe_ctx_old = +@@ -2148,31 +2213,6 @@ enum dc_status dce110_apply_ctx_to_hw( + if (pipe_ctx->top_pipe) + continue; + +- if (context->res_ctx.pipe_ctx[i].stream_res.audio != NULL) { +- +- struct audio_output audio_output; +- +- build_audio_output(context, pipe_ctx, &audio_output); +- +- if (dc_is_dp_signal(pipe_ctx->stream->signal)) +- pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup( +- pipe_ctx->stream_res.stream_enc, +- pipe_ctx->stream_res.audio->inst, +- &pipe_ctx->stream->audio_info); +- else +- pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup( +- pipe_ctx->stream_res.stream_enc, +- pipe_ctx->stream_res.audio->inst, +- &pipe_ctx->stream->audio_info, +- &audio_output.crtc_info); +- +- pipe_ctx->stream_res.audio->funcs->az_configure( +- pipe_ctx->stream_res.audio, +- pipe_ctx->stream->signal, +- &audio_output.crtc_info, +- &pipe_ctx->stream->audio_info); +- } +- + status = apply_single_controller_ctx_to_hw( + pipe_ctx, + context, +@@ -2985,6 +3025,8 @@ static const struct hw_sequencer_funcs dce110_funcs = { + .disable_stream = dce110_disable_stream, + .unblank_stream = dce110_unblank_stream, + .blank_stream = dce110_blank_stream, ++ .enable_audio_stream = dce110_enable_audio_stream, ++ .disable_audio_stream = dce110_disable_audio_stream, + .enable_display_pipe_clock_gating = enable_display_pipe_clock_gating, + .enable_display_power_gating = dce110_enable_display_power_gating, + .disable_plane = dce110_power_down_fe, +diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +index 5d7e9f5..f48d5a6 100644 +--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h +@@ -49,6 +49,10 @@ void dce110_unblank_stream(struct pipe_ctx *pipe_ctx, + struct dc_link_settings *link_settings); + + void dce110_blank_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_update_info_frame(struct pipe_ctx *pipe_ctx); + + void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable); +diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +index b7ff538..72d0b6f6 100644 +--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c ++++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +@@ -734,19 +734,7 @@ static void reset_back_end_for_pipe( + if (!pipe_ctx->stream->dpms_off) + core_link_disable_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + else if (pipe_ctx->stream_res.audio) { +- /* +- * if stream is already disabled outside of commit streams path, +- * audio disable was skipped. Need to do it here +- */ +- pipe_ctx->stream_res.audio->funcs->az_disable(pipe_ctx->stream_res.audio); +- +- if (dc->caps.dynamic_audio == true) { +- /*we have to dynamic arbitrate the audio endpoints*/ +- pipe_ctx->stream_res.audio = NULL; +- /*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); +- } +- ++ dc->hwss.disable_audio_stream(pipe_ctx, FREE_ACQUIRED_RESOURCE); + } + + } +@@ -2801,6 +2789,8 @@ static const struct hw_sequencer_funcs dcn10_funcs = { + .disable_stream = dce110_disable_stream, + .unblank_stream = dce110_unblank_stream, + .blank_stream = dce110_blank_stream, ++ .enable_audio_stream = dce110_enable_audio_stream, ++ .disable_audio_stream = dce110_disable_audio_stream, + .enable_display_power_gating = dcn10_dummy_display_power_gating, + .disable_plane = dcn10_disable_plane, + .blank_pixel_data = dcn10_blank_pixel_data, +diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +index 52db80f..a71770e 100644 +--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h ++++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h +@@ -154,6 +154,11 @@ struct hw_sequencer_funcs { + struct dc_link_settings *link_settings); + + void (*blank_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 (*pipe_control_lock)( + struct dc *dc, + struct pipe_ctx *pipe, +-- +2.7.4 + |