Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a05873f authored by Anthony Koo's avatar Anthony Koo Committed by Alex Deucher
Browse files

drm/amd/display: Refactor audio programming

parent 4ea20907
Loading
Loading
Loading
Loading
+2 −22
Original line number Diff line number Diff line
@@ -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,
+149 −107
Original line number Diff line number Diff line
@@ -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,
+4 −0
Original line number Diff line number Diff line
@@ -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);
+3 −13
Original line number Diff line number Diff line
@@ -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,
+5 −0
Original line number Diff line number Diff line
@@ -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,