OSDN Git Service

drm/amd/display: Refactor audio programming
authorAnthony Koo <Anthony.Koo@amd.com>
Thu, 10 May 2018 18:21:47 +0000 (14:21 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 15 Jun 2018 17:20:26 +0000 (12:20 -0500)
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>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h

index 2fa5218..a9485c1 100644 (file)
@@ -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,
index c29052b..cae0054 100644 (file)
@@ -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,
@@ -1298,6 +1330,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);
 
@@ -1949,6 +2005,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,
@@ -2040,79 +2176,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 =
@@ -2131,31 +2196,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,
@@ -2968,6 +3008,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,
index 5d7e9f5..f48d5a6 100644 (file)
@@ -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);
index 52924ef..03eb736 100644 (file)
@@ -719,19 +719,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);
                }
 
        }
@@ -2778,6 +2766,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,
index 52db80f..a71770e 100644 (file)
@@ -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,