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

Commit 810ece19 authored by Yongqiang Sun's avatar Yongqiang Sun Committed by Alex Deucher
Browse files

drm/amd/display: Calc vline position in dc.



We need to calcualte vline position in DC for DCN.

Signed-off-by: default avatarYongqiang Sun <yongqiang.sun@amd.com>
Reviewed-by: default avatarTony Cheng <Tony.Cheng@amd.com>
Acked-by: default avatarBhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 3f01f098
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -1572,13 +1572,13 @@ static void commit_planes_do_stream_update(struct dc *dc,
					stream_update->adjust->v_total_min,
					stream_update->adjust->v_total_min,
					stream_update->adjust->v_total_max);
					stream_update->adjust->v_total_max);


			if (stream_update->vline0_config && pipe_ctx->stream_res.tg->funcs->program_vline_interrupt)
			if (stream_update->periodic_vsync_config && pipe_ctx->stream_res.tg->funcs->program_vline_interrupt)
				pipe_ctx->stream_res.tg->funcs->program_vline_interrupt(
				pipe_ctx->stream_res.tg->funcs->program_vline_interrupt(
					pipe_ctx->stream_res.tg, VLINE0, &stream->vline0_config);
					pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, VLINE0, &stream->periodic_vsync_config);


			if (stream_update->vline1_config && pipe_ctx->stream_res.tg->funcs->program_vline_interrupt)
			if (stream_update->enhanced_sync_config && pipe_ctx->stream_res.tg->funcs->program_vline_interrupt)
				pipe_ctx->stream_res.tg->funcs->program_vline_interrupt(
				pipe_ctx->stream_res.tg->funcs->program_vline_interrupt(
					pipe_ctx->stream_res.tg, VLINE1, &stream->vline1_config);
					pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing, VLINE1, &stream->enhanced_sync_config);


			if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
			if ((stream_update->hdr_static_metadata && !stream->use_dynamic_meta) ||
					stream_update->vrr_infopacket ||
					stream_update->vrr_infopacket ||
+8 −7
Original line number Original line Diff line number Diff line
@@ -51,11 +51,12 @@ struct freesync_context {
	bool dummy;
	bool dummy;
};
};


struct vline_config {
union vline_config {
	unsigned int start_line;
	unsigned int line_number;
	unsigned int end_line;
	unsigned long long delta_in_ns;
};
};



struct dc_stream_state {
struct dc_stream_state {
	// sink is deprecated, new code should not reference
	// sink is deprecated, new code should not reference
	// this pointer
	// this pointer
@@ -105,8 +106,8 @@ struct dc_stream_state {
	/* DMCU info */
	/* DMCU info */
	unsigned int abm_level;
	unsigned int abm_level;


	struct vline_config vline0_config;
	union vline_config periodic_vsync_config;
	struct vline_config vline1_config;
	union vline_config enhanced_sync_config;


	/* from core_stream struct */
	/* from core_stream struct */
	struct dc_context *ctx;
	struct dc_context *ctx;
@@ -155,8 +156,8 @@ struct dc_stream_update {
	struct dc_info_packet *hdr_static_metadata;
	struct dc_info_packet *hdr_static_metadata;
	unsigned int *abm_level;
	unsigned int *abm_level;


	struct vline_config *vline0_config;
	union vline_config *periodic_vsync_config;
	struct vline_config *vline1_config;
	union vline_config *enhanced_sync_config;


	struct dc_crtc_timing_adjust *adjust;
	struct dc_crtc_timing_adjust *adjust;
	struct dc_info_packet *vrr_infopacket;
	struct dc_info_packet *vrr_infopacket;
+76 −4
Original line number Original line Diff line number Diff line
@@ -92,22 +92,94 @@ static void optc1_disable_stereo(struct timing_generator *optc)
		OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0);
		OTG_3D_STRUCTURE_STEREO_SEL_OVR, 0);
}
}


static uint32_t get_start_vline(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing)
{
	struct dc_crtc_timing patched_crtc_timing;
	int vesa_sync_start;
	int asic_blank_end;
	int interlace_factor;
	int vertical_line_start;

	patched_crtc_timing = *dc_crtc_timing;
	optc1_apply_front_porch_workaround(optc, &patched_crtc_timing);

	vesa_sync_start = patched_crtc_timing.h_addressable +
			patched_crtc_timing.h_border_right +
			patched_crtc_timing.h_front_porch;

	asic_blank_end = patched_crtc_timing.h_total -
			vesa_sync_start -
			patched_crtc_timing.h_border_left;

	interlace_factor = patched_crtc_timing.flags.INTERLACE ? 2 : 1;

	vesa_sync_start = patched_crtc_timing.v_addressable +
			patched_crtc_timing.v_border_bottom +
			patched_crtc_timing.v_front_porch;

	asic_blank_end = (patched_crtc_timing.v_total -
			vesa_sync_start -
			patched_crtc_timing.v_border_top)
			* interlace_factor;

	vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1;
	if (vertical_line_start < 0) {
		ASSERT(0);
		vertical_line_start = 0;
	}

	return vertical_line_start;
}

static void calc_vline_position(
		struct timing_generator *optc,
		const struct dc_crtc_timing *dc_crtc_timing,
		unsigned long long vsync_delta,
		uint32_t *start_line,
		uint32_t *end_line)
{
	unsigned long long req_delta_tens_of_usec = div64_u64((vsync_delta + 9999), 10000);
	unsigned long long pix_clk_hundreds_khz = div64_u64((dc_crtc_timing->pix_clk_100hz + 999), 1000);
	uint32_t req_delta_lines = (uint32_t) div64_u64(
			(req_delta_tens_of_usec * pix_clk_hundreds_khz + dc_crtc_timing->h_total - 1),
								dc_crtc_timing->h_total);

	uint32_t vsync_line = get_start_vline(optc, dc_crtc_timing);

	if (req_delta_lines != 0)
			req_delta_lines--;

		if (req_delta_lines > vsync_line)
			*start_line = dc_crtc_timing->v_total - (req_delta_lines - vsync_line) - 1;
		else
			*start_line = vsync_line - req_delta_lines;

		*end_line = *start_line + 2;

		if (*end_line >= dc_crtc_timing->v_total)
			*end_line = 2;
}

void optc1_program_vline_interrupt(
void optc1_program_vline_interrupt(
		struct timing_generator *optc,
		struct timing_generator *optc,
		const struct dc_crtc_timing *dc_crtc_timing,
		enum vline_select vline,
		enum vline_select vline,
		const struct vline_config *vline_config)
		const union vline_config *vline_config)
{
{
	struct optc *optc1 = DCN10TG_FROM_TG(optc);
	struct optc *optc1 = DCN10TG_FROM_TG(optc);
	uint32_t start_line = 0;
	uint32_t end_line = 0;


	switch (vline) {
	switch (vline) {
	case VLINE0:
	case VLINE0:
		calc_vline_position(optc, dc_crtc_timing, vline_config->delta_in_ns, &start_line, &end_line);
		REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0,
		REG_SET_2(OTG_VERTICAL_INTERRUPT0_POSITION, 0,
				OTG_VERTICAL_INTERRUPT0_LINE_START, vline_config->start_line,
				OTG_VERTICAL_INTERRUPT0_LINE_START, start_line,
				OTG_VERTICAL_INTERRUPT0_LINE_END, vline_config->end_line);
				OTG_VERTICAL_INTERRUPT0_LINE_END, end_line);
		break;
		break;
	case VLINE1:
	case VLINE1:
		REG_SET(OTG_VERTICAL_INTERRUPT1_POSITION, 0,
		REG_SET(OTG_VERTICAL_INTERRUPT1_POSITION, 0,
					OTG_VERTICAL_INTERRUPT1_LINE_START, vline_config->start_line);
					OTG_VERTICAL_INTERRUPT1_LINE_START, vline_config->line_number);
		break;
		break;
	default:
	default:
		break;
		break;
+4 −2
Original line number Original line Diff line number Diff line
@@ -483,9 +483,11 @@ void optc1_program_timing(
	const struct dc_crtc_timing *dc_crtc_timing,
	const struct dc_crtc_timing *dc_crtc_timing,
	bool use_vbios);
	bool use_vbios);


void optc1_program_vline_interrupt(struct timing_generator *optc,
void optc1_program_vline_interrupt(
		struct timing_generator *optc,
		const struct dc_crtc_timing *dc_crtc_timing,
		enum vline_select vline,
		enum vline_select vline,
		const struct vline_config *vline_config);
		const union vline_config *vline_config);


void optc1_program_global_sync(
void optc1_program_global_sync(
		struct timing_generator *optc);
		struct timing_generator *optc);
+5 −3
Original line number Original line Diff line number Diff line
@@ -134,7 +134,7 @@ struct dc_crtc_timing;


struct drr_params;
struct drr_params;


struct vline_config;
union vline_config;




enum vline_select {
enum vline_select {
@@ -149,9 +149,11 @@ struct timing_generator_funcs {
	void (*program_timing)(struct timing_generator *tg,
	void (*program_timing)(struct timing_generator *tg,
							const struct dc_crtc_timing *timing,
							const struct dc_crtc_timing *timing,
							bool use_vbios);
							bool use_vbios);
	void (*program_vline_interrupt)(struct timing_generator *optc,
	void (*program_vline_interrupt)(
			struct timing_generator *optc,
			const struct dc_crtc_timing *dc_crtc_timing,
			enum vline_select vline,
			enum vline_select vline,
			const struct vline_config *vline_config);
			const union vline_config *vline_config);
	bool (*enable_crtc)(struct timing_generator *tg);
	bool (*enable_crtc)(struct timing_generator *tg);
	bool (*disable_crtc)(struct timing_generator *tg);
	bool (*disable_crtc)(struct timing_generator *tg);
	bool (*is_counter_moving)(struct timing_generator *tg);
	bool (*is_counter_moving)(struct timing_generator *tg);