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

Commit 86fa8f9f authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "disp: msm: sde: fix vsync wakeup time"

parents a9fd1746 a34362a9
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;