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

Commit dcb1c4ae authored by Lloyd Atkinson's avatar Lloyd Atkinson Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/sde: toggle vblank using enable state in display thread



Add enabled flag to the CRTC to be able to track the enabled or
disabled status in the display thread instead of the atomic
state. The atomic state is swapped prior to the display thread
dispatch. This is before the display thread executes the enable
or disable operation, so the state is not properly reflected for
a running VSYNC work item.

Also, simplify the CRTC VBLANK function structure to use a
single common function call to update the CRTC's VBLANK
registration with the encoder to avoid extra refs and unrefs.

Change-Id: I9b473becec15427b03b5ebf0333e10e4911dfd9b
Signed-off-by: default avatarLloyd Atkinson <latkinso@codeaurora.org>
parent 607b49ce
Loading
Loading
Loading
Loading
+58 −43
Original line number Diff line number Diff line
@@ -2204,11 +2204,13 @@ void sde_crtc_commit_kickoff(struct drm_crtc *crtc)
}

/**
 * _sde_crtc_vblank_enable_nolock - update power resource and vblank request
 * _sde_crtc_vblank_enable_no_lock - update power resource and vblank request
 * @sde_crtc: Pointer to sde crtc structure
 * @enable: Whether to enable/disable vblanks
 *
 * @Return: error code
 */
static void _sde_crtc_vblank_enable_nolock(
static int _sde_crtc_vblank_enable_no_lock(
		struct sde_crtc *sde_crtc, bool enable)
{
	struct drm_device *dev;
@@ -2217,7 +2219,7 @@ static void _sde_crtc_vblank_enable_nolock(

	if (!sde_crtc) {
		SDE_ERROR("invalid crtc\n");
		return;
		return -EINVAL;
	}

	crtc = &sde_crtc->base;
@@ -2231,13 +2233,16 @@ static void _sde_crtc_vblank_enable_nolock(
		ret = _sde_crtc_power_enable(sde_crtc, true);
		mutex_lock(&sde_crtc->crtc_lock);
		if (ret)
			return;
			return ret;

		list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
			if (enc->crtc != crtc)
				continue;

			SDE_EVT32(DRMID(crtc), DRMID(enc), enable);
			SDE_EVT32(DRMID(&sde_crtc->base), DRMID(enc), enable,
					sde_crtc->enabled,
					sde_crtc->suspend,
					sde_crtc->vblank_requested);

			sde_encoder_register_vblank_callback(enc,
					sde_crtc_vblank_cb, (void *)crtc);
@@ -2247,7 +2252,10 @@ static void _sde_crtc_vblank_enable_nolock(
			if (enc->crtc != crtc)
				continue;

			SDE_EVT32(DRMID(crtc), DRMID(enc), enable);
			SDE_EVT32(DRMID(&sde_crtc->base), DRMID(enc), enable,
					sde_crtc->enabled,
					sde_crtc->suspend,
					sde_crtc->vblank_requested);

			sde_encoder_register_vblank_callback(enc, NULL, NULL);
		}
@@ -2257,6 +2265,8 @@ static void _sde_crtc_vblank_enable_nolock(
		_sde_crtc_power_enable(sde_crtc, false);
		mutex_lock(&sde_crtc->crtc_lock);
	}

	return 0;
}

/**
@@ -2271,6 +2281,7 @@ static void _sde_crtc_set_suspend(struct drm_crtc *crtc, bool enable)
	struct sde_kms *sde_kms;
	struct drm_event event;
	u32 power_on;
	int ret = 0;

	if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
		SDE_ERROR("invalid crtc\n");
@@ -2286,6 +2297,7 @@ static void _sde_crtc_set_suspend(struct drm_crtc *crtc, bool enable)
	sde_kms = to_sde_kms(priv->kms);

	SDE_DEBUG("crtc%d suspend = %d\n", crtc->base.id, enable);
	SDE_EVT32_VERBOSE(DRMID(crtc), enable);

	mutex_lock(&sde_crtc->crtc_lock);

@@ -2306,11 +2318,17 @@ static void _sde_crtc_set_suspend(struct drm_crtc *crtc, bool enable)
	 * If the vblank is enabled, release a power reference on suspend
	 * and take it back during resume (if it is still enabled).
	 */
	SDE_EVT32(DRMID(&sde_crtc->base), enable, sde_crtc->enabled,
			sde_crtc->suspend, sde_crtc->vblank_requested);
	if (sde_crtc->suspend == enable)
		SDE_DEBUG("crtc%d suspend already set to %d, ignoring update\n",
				crtc->base.id, enable);
	else if (sde_crtc->vblank_enable)
		_sde_crtc_vblank_enable_nolock(sde_crtc, !enable);
	else if (sde_crtc->enabled && sde_crtc->vblank_requested) {
		ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, !enable);
		if (ret)
			SDE_ERROR("%s vblank enable failed: %d\n",
					sde_crtc->name, ret);
	}

	sde_crtc->suspend = enable;
	msm_mode_object_event_notify(&crtc->base, crtc->dev, &event,
@@ -2400,23 +2418,6 @@ static void sde_crtc_reset(struct drm_crtc *crtc)
	crtc->state = &cstate->base;
}

static int _sde_crtc_vblank_no_lock(struct sde_crtc *sde_crtc, bool en)
{
	if (!sde_crtc) {
		SDE_ERROR("invalid crtc\n");
		return -EINVAL;
	}

	if (!sde_crtc->base.enabled || sde_crtc->suspend)
		SDE_EVT32(DRMID(&sde_crtc->base), sde_crtc->base.enabled, en,
				sde_crtc->vblank_enable, sde_crtc->suspend);
	else if (sde_crtc->vblank_enable != en)
		_sde_crtc_vblank_enable_nolock(sde_crtc, en);
	sde_crtc->vblank_enable = en;

	return 0;
}

static void sde_crtc_handle_power_event(u32 event_type, void *arg)
{
	struct drm_crtc *crtc = arg;
@@ -2498,7 +2499,7 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
		_sde_crtc_set_suspend(crtc, true);

	mutex_lock(&sde_crtc->crtc_lock);
	SDE_EVT32(DRMID(crtc));
	SDE_EVT32_VERBOSE(DRMID(crtc));

	/* wait for frame_event_done completion */
	if (_sde_crtc_wait_for_frame_done(crtc))
@@ -2506,13 +2507,16 @@ static void sde_crtc_disable(struct drm_crtc *crtc)
				crtc->base.id,
				atomic_read(&sde_crtc->frame_pending));

	if (sde_crtc->vblank_enable && !sde_crtc->suspend) {
		SDE_DEBUG("crtc%d vblank left enabled at disable time\n",
				crtc->base.id);
		SDE_EVT32(DRMID(crtc), sde_crtc->vblank_enable,
				SDE_EVTLOG_FUNC_CASE1);
		_sde_crtc_vblank_enable_nolock(sde_crtc, false);
	SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend,
			sde_crtc->vblank_requested);
	if (sde_crtc->enabled && !sde_crtc->suspend &&
			sde_crtc->vblank_requested) {
		ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, false);
		if (ret)
			SDE_ERROR("%s vblank enable failed: %d\n",
					sde_crtc->name, ret);
	}
	sde_crtc->enabled = false;

	if (atomic_read(&sde_crtc->frame_pending)) {
		SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->frame_pending),
@@ -2572,7 +2576,7 @@ static void sde_crtc_enable(struct drm_crtc *crtc)
	priv = crtc->dev->dev_private;

	SDE_DEBUG("crtc%d\n", crtc->base.id);
	SDE_EVT32(DRMID(crtc));
	SDE_EVT32_VERBOSE(DRMID(crtc));
	sde_crtc = to_sde_crtc(crtc);

	drm_for_each_encoder(encoder, crtc->dev) {
@@ -2583,13 +2587,16 @@ static void sde_crtc_enable(struct drm_crtc *crtc)
	}

	mutex_lock(&sde_crtc->crtc_lock);
	if (sde_crtc->vblank_enable) {
		/* honor user vblank request on crtc while it was disabled */
		SDE_DEBUG("%s vblank found enabled at crtc enable time\n",
				sde_crtc->name);
		SDE_EVT32(DRMID(crtc), sde_crtc->vblank_enable);
		_sde_crtc_vblank_enable_nolock(sde_crtc, true);
	SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend,
			sde_crtc->vblank_requested);
	if (!sde_crtc->enabled && !sde_crtc->suspend &&
			sde_crtc->vblank_requested) {
		ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, true);
		if (ret)
			SDE_ERROR("%s vblank enable failed: %d\n",
					sde_crtc->name, ret);
	}
	sde_crtc->enabled = true;
	mutex_unlock(&sde_crtc->crtc_lock);

	spin_lock_irqsave(&sde_crtc->spin_lock, flags);
@@ -3110,7 +3117,7 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
{
	struct sde_crtc *sde_crtc;
	int rc;
	int ret;

	if (!crtc) {
		SDE_ERROR("invalid crtc\n");
@@ -3119,10 +3126,18 @@ int sde_crtc_vblank(struct drm_crtc *crtc, bool en)
	sde_crtc = to_sde_crtc(crtc);

	mutex_lock(&sde_crtc->crtc_lock);
	rc = _sde_crtc_vblank_no_lock(sde_crtc, en);
	SDE_EVT32(DRMID(&sde_crtc->base), en, sde_crtc->enabled,
			sde_crtc->suspend, sde_crtc->vblank_requested);
	if (sde_crtc->enabled && !sde_crtc->suspend) {
		ret = _sde_crtc_vblank_enable_no_lock(sde_crtc, en);
		if (ret)
			SDE_ERROR("%s vblank enable failed: %d\n",
					sde_crtc->name, ret);
	}
	sde_crtc->vblank_requested = en;
	mutex_unlock(&sde_crtc->crtc_lock);

	return rc;
	return 0;
}

void sde_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file)
@@ -3588,7 +3603,7 @@ static int _sde_debugfs_status_show(struct seq_file *s, void *data)
		sde_crtc->vblank_cb_time = ktime_set(0, 0);
	}

	seq_printf(s, "vblank_enable:%d\n", sde_crtc->vblank_enable);
	seq_printf(s, "vblank_enable:%d\n", sde_crtc->vblank_requested);

	mutex_unlock(&sde_crtc->crtc_lock);

+6 −2
Original line number Diff line number Diff line
@@ -123,8 +123,11 @@ struct sde_crtc_event {
 * @vblank_cb_count : count of vblank callback since last reset
 * @play_count    : frame count between crtc enable and disable
 * @vblank_cb_time  : ktime at vblank count reset
 * @vblank_enable : whether the user has requested vblank events
 * @vblank_requested : whether the user has requested vblank events
 * @suspend         : whether or not a suspend operation is in progress
 * @enabled       : whether the SDE CRTC is currently enabled. updated in the
 *                  commit-thread, not state-swap time which is earlier, so
 *                  safe to make decisions on during VBLANK on/off work
 * @feature_list  : list of color processing features supported on a crtc
 * @active_list   : list of color processing features are active
 * @dirty_list    : list of color processing features are dirty
@@ -171,8 +174,9 @@ struct sde_crtc {
	u32 vblank_cb_count;
	u64 play_count;
	ktime_t vblank_cb_time;
	bool vblank_enable;
	bool vblank_requested;
	bool suspend;
	bool enabled;

	struct list_head feature_list;
	struct list_head active_list;