aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.14.71/4542-drm-amd-display-Refactor-audio-programming.patch
diff options
context:
space:
mode:
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.patch440
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
+