Эх сурвалжийг харах

disp: msm: sde: wait for lp2 and pm_suspend frame trigger

PM_SUSPEND API adds extra pm_runtime refcount and calls
the device driver for pm_suspend. At this point display
device may not be in power collapse state. This patch
makes sure that crtc_commit thread is idle and triggers
power collapse also.

Change-Id: Ia21d6a6b6fd32caeb9d16fa5cf998b91ef990e01
Signed-off-by: Dhaval Patel <[email protected]>
Dhaval Patel 5 жил өмнө
parent
commit
96d5b9646d

+ 7 - 0
msm/sde/sde_encoder_phys_cmd.c

@@ -1406,6 +1406,13 @@ static int sde_encoder_phys_cmd_wait_for_tx_complete(
 
 	cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
 
+	if (!atomic_read(&phys_enc->pending_kickoff_cnt)) {
+		SDE_EVT32(DRMID(phys_enc->parent),
+			phys_enc->intf_idx - INTF_0,
+			phys_enc->enable_state);
+		return 0;
+	}
+
 	rc = _sde_encoder_phys_cmd_wait_for_idle(phys_enc);
 	if (rc) {
 		SDE_EVT32(DRMID(phys_enc->parent),

+ 43 - 18
msm/sde/sde_kms.c

@@ -2587,6 +2587,45 @@ end:
 	drm_modeset_acquire_fini(&ctx);
 }
 
+static void _sde_kms_pm_suspend_idle_helper(struct sde_kms *sde_kms,
+	struct device *dev)
+{
+	int i, ret;
+	struct drm_device *ddev = dev_get_drvdata(dev);
+	struct drm_connector *conn;
+	struct drm_connector_list_iter conn_iter;
+	struct msm_drm_private *priv = sde_kms->dev->dev_private;
+
+	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(
+				"[conn: %d] wait for commit done returned %d\n",
+				conn->base.id, ret);
+		else if (!ret)
+			sde_encoder_idle_request(conn->encoder);
+	}
+	drm_connector_list_iter_end(&conn_iter);
+
+	for (i = 0; i < priv->num_crtcs; i++) {
+		if (priv->disp_thread[i].thread)
+			kthread_flush_worker(
+				&priv->disp_thread[i].worker);
+		if (priv->event_thread[i].thread)
+			kthread_flush_worker(
+				&priv->event_thread[i].worker);
+	}
+	kthread_flush_worker(&priv->pp_event_worker);
+}
+
 static int sde_kms_pm_suspend(struct device *dev)
 {
 	struct drm_device *ddev;
@@ -2607,6 +2646,7 @@ static int sde_kms_pm_suspend(struct device *dev)
 
 	sde_kms = to_sde_kms(ddev_to_msm_kms(ddev));
 	SDE_EVT32(0);
+	pm_runtime_put_noidle(dev);
 
 	/* disable hot-plug polling */
 	drm_kms_helper_poll_disable(ddev);
@@ -2689,6 +2729,7 @@ retry:
 	if (num_crtcs == 0) {
 		DRM_DEBUG("all crtcs are already in the off state\n");
 		sde_kms->suspend_block = true;
+		_sde_kms_pm_suspend_idle_helper(sde_kms, dev);
 		goto unlock;
 	}
 
@@ -2700,25 +2741,8 @@ retry:
 	}
 
 	sde_kms->suspend_block = true;
+	_sde_kms_pm_suspend_idle_helper(sde_kms, dev);
 
-	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 (state) {
 		drm_atomic_state_put(state);
@@ -2731,6 +2755,7 @@ unlock:
 	}
 	drm_modeset_drop_locks(&ctx);
 	drm_modeset_acquire_fini(&ctx);
+	pm_runtime_get_noresume(dev);
 
 	return ret;
 }