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

Commit a34362a9 authored by Samantha Tran's avatar Samantha Tran
Browse files

disp: msm: sde: fix vsync wakeup time



Current wakeup time is surpassing next vsync and not being used.
This change will use mdp transfer time calculated by dsi to compute
line time in command mode. In video mode, fps will be used to compute
the line time. This line time will be used with current interface
line count to calculate time until the next vsync.

Change-Id: I0b6fc396711ade95ecf95755a907280309af223e
Signed-off-by: default avatarSamantha Tran <samtran@codeaurora.org>
parent 76f7b284
Loading
Loading
Loading
Loading
+25 −60
Original line number Diff line number Diff line
@@ -4314,61 +4314,14 @@ static void _sde_encoder_setup_dither(struct sde_encoder_phys *phys)
	}
}

static u32 _sde_encoder_calculate_linetime(struct sde_encoder_virt *sde_enc,
		struct drm_display_mode *mode)
{
	u64 pclk_rate;
	u32 pclk_period;
	u32 line_time;

	/*
	 * For linetime calculation, only operate on master encoder.
	 */
	if (!sde_enc->cur_master)
		return 0;

	if (!sde_enc->cur_master->ops.get_line_count) {
		SDE_ERROR("get_line_count function not defined\n");
		return 0;
	}

	pclk_rate = mode->clock; /* pixel clock in kHz */
	if (pclk_rate == 0) {
		SDE_ERROR("pclk is 0, cannot calculate line time\n");
		return 0;
	}

	pclk_period = DIV_ROUND_UP_ULL(1000000000ull, pclk_rate);
	if (pclk_period == 0) {
		SDE_ERROR("pclk period is 0\n");
		return 0;
	}

	/*
	 * Line time calculation based on Pixel clock and HTOTAL.
	 * Final unit is in ns.
	 */
	line_time = (pclk_period * mode->htotal) / 1000;
	if (line_time == 0) {
		SDE_ERROR("line time calculation is 0\n");
		return 0;
	}

	SDE_DEBUG_ENC(sde_enc,
			"clk_rate=%lldkHz, clk_period=%d, linetime=%dns\n",
			pclk_rate, pclk_period, line_time);

	return line_time;
}

static int _sde_encoder_wakeup_time(struct drm_encoder *drm_enc,
		ktime_t *wakeup_time)
{
	struct drm_display_mode *mode;
	struct sde_encoder_virt *sde_enc;
	u32 cur_line;
	u32 line_time;
	u32 vtotal, time_to_vsync;
	u32 cur_line, lines_left;
	u32 line_time, mdp_transfer_time_us;
	u32 vtotal, time_to_vsync_us, threshold_time_us = 0;
	ktime_t cur_time;

	sde_enc = to_sde_encoder_virt(drm_enc);
@@ -4378,31 +4331,43 @@ static int _sde_encoder_wakeup_time(struct drm_encoder *drm_enc,
	}

	mode = &sde_enc->cur_master->cached_mode;
	mdp_transfer_time_us = sde_enc->mode_info.mdp_transfer_time_us;

	vtotal = mode->vtotal;
	if (!mdp_transfer_time_us) {
		/* mdp_transfer_time set to 0 for video mode */
		line_time = (1000000 / sde_enc->mode_info.frame_rate) / vtotal;
	} else {
		line_time = mdp_transfer_time_us / vtotal;
		threshold_time_us = ((1000000 / sde_enc->mode_info.frame_rate)
						- mdp_transfer_time_us);
	}

	line_time = _sde_encoder_calculate_linetime(sde_enc, mode);
	if (!line_time)
	if (!sde_enc->cur_master->ops.get_line_count) {
		SDE_DEBUG_ENC(sde_enc, "can't get master line count\n");
		return -EINVAL;
	}

	cur_line = sde_enc->cur_master->ops.get_line_count(sde_enc->cur_master);

	vtotal = mode->vtotal;
	if (cur_line >= vtotal)
		time_to_vsync = line_time * vtotal;
	else
		time_to_vsync = line_time * (vtotal - cur_line);
	lines_left = (cur_line >= vtotal) ? vtotal : (vtotal - cur_line);

	time_to_vsync_us = line_time * lines_left;

	if (time_to_vsync == 0) {
	if (!time_to_vsync_us) {
		SDE_ERROR("time to vsync should not be zero, vtotal=%d\n",
				vtotal);
		return -EINVAL;
	}

	cur_time = ktime_get();
	*wakeup_time = ktime_add_ns(cur_time, time_to_vsync);
	*wakeup_time = ktime_add_us(cur_time, time_to_vsync_us);
	if (threshold_time_us)
		*wakeup_time = ktime_add_us(*wakeup_time, threshold_time_us);

	SDE_DEBUG_ENC(sde_enc,
			"cur_line=%u vtotal=%u time_to_vsync=%u, cur_time=%lld, wakeup_time=%lld\n",
			cur_line, vtotal, time_to_vsync,
			cur_line, vtotal, time_to_vsync_us,
			ktime_to_ms(cur_time),
			ktime_to_ms(*wakeup_time));
	return 0;