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

Commit 934d3289 authored by Dhaval Patel's avatar Dhaval Patel Committed by Gerrit - the friendly Code Review server
Browse files

drm/msm/sde: move to idle state before doze_suspend



Wait for last frame transfer complete and move to
idle state before entering in doze_suspend state.
This avoid clocks left ON during this power state
transition.

Change-Id: Ic50ed8e1d4cc422b70b66174db138a137ec1ff15
Signed-off-by: default avatarDhaval Patel <pdhaval@codeaurora.org>
Signed-off-by: default avatarSteve Cohen <cohens@codeaurora.org>
parent 8bdbd0ab
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -2140,7 +2140,7 @@ static int sde_encoder_resource_control(struct drm_encoder *drm_enc,
		mutex_lock(&sde_enc->rc_lock);

		if (sde_enc->rc_state != SDE_ENC_RC_STATE_ON) {
			SDE_ERROR_ENC(sde_enc, "sw_event:%d, rc:%d !ON state\n",
			SDE_DEBUG_ENC(sde_enc, "sw_event:%d, rc:%d !ON state\n",
					sw_event, sde_enc->rc_state);
			SDE_EVT32(DRMID(drm_enc), sw_event, sde_enc->rc_state,
					SDE_EVTLOG_ERROR);
@@ -2768,18 +2768,35 @@ static void sde_encoder_frame_done_callback(
	}
}

int sde_encoder_idle_request(struct drm_encoder *drm_enc)
{
	struct sde_encoder_virt *sde_enc;

	if (!drm_enc) {
		SDE_ERROR("invalid drm encoder\n");
		return -EINVAL;
	}

	sde_enc = to_sde_encoder_virt(drm_enc);
	sde_encoder_resource_control(&sde_enc->base,
						SDE_ENC_RC_EVENT_ENTER_IDLE);

	return 0;
}

static void sde_encoder_off_work(struct kthread_work *work)
{
	struct sde_encoder_virt *sde_enc = container_of(work,
			struct sde_encoder_virt, delayed_off_work.work);
	struct drm_encoder *drm_enc;

	if (!sde_enc) {
		SDE_ERROR("invalid sde encoder\n");
		return;
	}
	drm_enc = &sde_enc->base;

	sde_encoder_resource_control(&sde_enc->base,
						SDE_ENC_RC_EVENT_ENTER_IDLE);
	sde_encoder_idle_request(drm_enc);
}

/**
+8 −0
Original line number Diff line number Diff line
@@ -155,6 +155,14 @@ void sde_encoder_kickoff(struct drm_encoder *encoder, bool is_error);
int sde_encoder_wait_for_event(struct drm_encoder *drm_encoder,
						enum msm_event_wait event);

/**
 * sde_encoder_idle_request - request for idle request to avoid 4 vsync cycle
 *                            to turn off the clocks.
 * @encoder:	encoder pointer
 * Returns: 0 on success, errorcode otherwise
 */
int sde_encoder_idle_request(struct drm_encoder *drm_enc);

/*
 * sde_encoder_get_intf_mode - get interface mode of the given encoder
 * @encoder: Pointer to drm encoder object
+20 −2
Original line number Diff line number Diff line
@@ -2052,7 +2052,8 @@ static int sde_kms_pm_suspend(struct device *dev)
	if (num_crtcs == 0) {
		DRM_DEBUG("all crtcs are already in the off state\n");
		drm_atomic_state_put(state);
		goto suspended;
		sde_kms->suspend_block = true;
		goto unlock;
	}

	/* commit the "disable all" state */
@@ -2063,9 +2064,26 @@ static int sde_kms_pm_suspend(struct device *dev)
		goto unlock;
	}

suspended:
	sde_kms->suspend_block = true;

	drm_connector_list_iter_begin(ddev, &conn_iter);
	drm_for_each_connector_iter(conn, &conn_iter) {
		uint64_t lp;

		lp = sde_connector_get_lp(conn);
		if (lp != SDE_MODE_DPMS_LP2)
			continue;

		ret = sde_encoder_wait_for_event(conn->encoder,
						MSM_ENC_TX_COMPLETE);
		if (ret && ret != -EWOULDBLOCK)
			SDE_ERROR(
				"[enc: %d] wait for commit done returned %d\n",
				conn->encoder->base.id, ret);
		else if (!ret)
			sde_encoder_idle_request(conn->encoder);
	}
	drm_connector_list_iter_end(&conn_iter);
unlock:
	if (ret == -EDEADLK) {
		drm_modeset_backoff(&ctx);