Commit f591344e authored by Julian Parkin's avatar Julian Parkin Committed by Alex Deucher
Browse files

drm/amd/display: Clean up dynamic metadata logic



 [Why]
Code to enable DCN20 dynamic metadata feature is duplicated in two places
and was added to DCE110 enable stream.

[How]
Create DCN20 specific enable stream function for clarity, and add a hardware
sequencer function to program dynamic metadata to avoid the duplicate
code.

Signed-off-by: default avatarJulian Parkin <julian.parkin@amd.com>
Reviewed-by: default avatarCharlene Liu <Charlene.Liu@amd.com>
Acked-by: default avatarLeo Li <sunpeng.li@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ce08aad3
Loading
Loading
Loading
Loading
+10 −17
Original line number Diff line number Diff line
@@ -566,6 +566,7 @@ bool dc_stream_get_scanoutpos(const struct dc_stream_state *stream,

	return ret;
}

#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
bool dc_stream_dmdata_status_done(struct dc *dc, struct dc_stream_state *stream)
{
@@ -597,6 +598,14 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc,
	struct hubp *hubp;
	int i;

	/* Dynamic metadata is only supported on HDMI or DP */
	if (!dc_is_hdmi_signal(stream->signal) && !dc_is_dp_signal(stream->signal))
		return false;

	/* Check hardware support */
	if (!dc->hwss.program_dmdata_engine)
		return false;

	for (i = 0; i < MAX_PIPES; i++) {
		pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
		if (pipe_ctx->stream == stream)
@@ -612,23 +621,7 @@ bool dc_stream_set_dynamic_metadata(struct dc *dc,

	pipe_ctx->stream->dmdata_address = attr->address;

	if (pipe_ctx->stream_res.stream_enc &&
			pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL) {
		if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
			/* if using dynamic meta, don't set up generic infopackets */
			pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
			pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata(
					pipe_ctx->stream_res.stream_enc,
					true, pipe_ctx->plane_res.hubp->inst,
					dc_is_dp_signal(pipe_ctx->stream->signal) ?
							dmdata_dp : dmdata_hdmi);
		} else
			pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata(
					pipe_ctx->stream_res.stream_enc,
					false, pipe_ctx->plane_res.hubp->inst,
					dc_is_dp_signal(pipe_ctx->stream->signal) ?
							dmdata_dp : dmdata_hdmi);
	}
	dc->hwss.program_dmdata_engine(pipe_ctx);

	if (hubp->funcs->dmdata_set_attributes != NULL &&
			pipe_ctx->stream->dmdata_address.quad_part != 0) {
+1 −23
Original line number Diff line number Diff line
@@ -667,29 +667,7 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
	link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
						    pipe_ctx->stream_res.stream_enc->id, true);

	/* update AVI info frame (HDMI, DP)*/
	/* TODO: FPGA may change to hwss.update_info_frame */

#if defined(CONFIG_DRM_AMD_DC_DCN2_0)
	if (pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata != NULL &&
			pipe_ctx->plane_res.hubp != NULL) {
		if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
			/* if using dynamic meta, don't set up generic infopackets */
			pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
			pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata(
					pipe_ctx->stream_res.stream_enc,
					true, pipe_ctx->plane_res.hubp->inst,
					dc_is_dp_signal(pipe_ctx->stream->signal) ?
							dmdata_dp : dmdata_hdmi);
		} else
			pipe_ctx->stream_res.stream_enc->funcs->set_dynamic_metadata(
					pipe_ctx->stream_res.stream_enc,
					false, pipe_ctx->plane_res.hubp->inst,
					dc_is_dp_signal(pipe_ctx->stream->signal) ?
							dmdata_dp : dmdata_hdmi);
	}
#endif
	dce110_update_info_frame(pipe_ctx);
	link->dc->hwss.update_info_frame(pipe_ctx);

	/* enable early control to avoid corruption on DP monitor*/
	active_total_with_borders =
+74 −0
Original line number Diff line number Diff line
@@ -2056,6 +2056,78 @@ static void dcn20_set_flip_control_gsl(

}

static void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
{
	enum dc_lane_count lane_count =
		pipe_ctx->stream->link->cur_link_settings.lane_count;

	struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
	struct dc_link *link = pipe_ctx->stream->link;

	uint32_t active_total_with_borders;
	uint32_t early_control = 0;
	struct timing_generator *tg = pipe_ctx->stream_res.tg;

	/* For MST, there are multiply stream go to only one link.
	 * connect DIG back_end to front_end while enable_stream and
	 * disconnect them during disable_stream
	 * BY this, it is logic clean to separate stream and link
	 */
	link->link_enc->funcs->connect_dig_be_to_fe(link->link_enc,
						    pipe_ctx->stream_res.stream_enc->id, true);

	if (link->dc->hwss.program_dmdata_engine)
		link->dc->hwss.program_dmdata_engine(pipe_ctx);

	link->dc->hwss.update_info_frame(pipe_ctx);

	/* enable early control to avoid corruption on DP monitor*/
	active_total_with_borders =
			timing->h_addressable
				+ timing->h_border_left
				+ timing->h_border_right;

	if (lane_count != 0)
		early_control = active_total_with_borders % lane_count;

	if (early_control == 0)
		early_control = lane_count;

	tg->funcs->set_early_control(tg, early_control);

	/* enable audio only within mode set */
	if (pipe_ctx->stream_res.audio != NULL) {
		if (dc_is_dp_signal(pipe_ctx->stream->signal))
			pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
	}
}

static void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
{
	struct dc_stream_state    *stream     = pipe_ctx->stream;
	struct hubp               *hubp       = pipe_ctx->plane_res.hubp;
	bool                       enable     = false;
	struct stream_encoder     *stream_enc = pipe_ctx->stream_res.stream_enc;
	enum dynamic_metadata_mode mode       = dc_is_dp_signal(stream->signal)
							? dmdata_dp
							: dmdata_hdmi;

	/* if using dynamic meta, don't set up generic infopackets */
	if (pipe_ctx->stream->dmdata_address.quad_part != 0) {
		pipe_ctx->stream_res.encoder_info_frame.hdrsmd.valid = false;
		enable = true;
	}

	if (!hubp)
		return;

	if (!stream_enc || !stream_enc->funcs->set_dynamic_metadata)
		return;

	stream_enc->funcs->set_dynamic_metadata(stream_enc, enable,
						hubp->inst, mode);
}

void dcn20_hw_sequencer_construct(struct dc *dc)
{
	dcn10_hw_sequencer_construct(dc);
@@ -2080,6 +2152,8 @@ void dcn20_hw_sequencer_construct(struct dc *dc)
	dc->hwss.update_odm = dcn20_update_odm;
	dc->hwss.blank_pixel_data = dcn20_blank_pixel_data;
	dc->hwss.dmdata_status_done = dcn20_dmdata_status_done;
	dc->hwss.program_dmdata_engine = dcn20_program_dmdata_engine;
	dc->hwss.enable_stream = dcn20_enable_stream;
	dc->hwss.disable_stream = dcn20_disable_stream;
	dc->hwss.init_sys_ctx = dcn20_init_sys_ctx;
	dc->hwss.init_vm_ctx = dcn20_init_vm_ctx;
+1 −0
Original line number Diff line number Diff line
@@ -231,6 +231,7 @@ struct hw_sequencer_funcs {
	bool (*update_bandwidth)(
			struct dc *dc,
			struct dc_state *context);
	void (*program_dmdata_engine)(struct pipe_ctx *pipe_ctx);
	bool (*dmdata_status_done)(struct pipe_ctx *pipe_ctx);
#endif