diff mbox

drm/exynos: fix display on issue

Message ID 1350554532-10514-1-git-send-email-inki.dae@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Inki Dae Oct. 18, 2012, 10:02 a.m. UTC
When crtc_funcs->dpms callback is called, exynos_crtc->dpms
and exynos_encoder->dpms are changed to new mode. But if user
requests dpms mode operation, OFF -> ON, when crtc's dpms callback
is called, exynos_encoder->dpms is also changed to ON. This
makes encoder's dpms callback call be ignored so display power
couldn't become on again.

This patch removes exynos_encoder->dpms changing and adds 'updated'
variable to exynos_drm_encoder structure to avoid duplicated overlay
updating.

Signed-off-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_connector.c |    1 +
 drivers/gpu/drm/exynos/exynos_drm_encoder.c   |   33 +++++++++++++------------
 2 files changed, 18 insertions(+), 16 deletions(-)
diff mbox

Patch

diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index 18c2718..0f68a28 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -374,6 +374,7 @@  struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 	exynos_connector->encoder_id = encoder->base.id;
 	exynos_connector->manager = manager;
 	exynos_connector->dpms = DRM_MODE_DPMS_OFF;
+	connector->dpms = DRM_MODE_DPMS_OFF;
 	connector->encoder = encoder;
 
 	err = drm_mode_connector_attach_encoder(connector, encoder);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index e51503f..241ad1e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -43,12 +43,14 @@ 
  * @manager: specific encoder has its own manager to control a hardware
  *	appropriately and we can access a hardware drawing on this manager.
  * @dpms: store the encoder dpms value.
+ * @updated: indicate whether overlay data updating is needed or not.
  */
 struct exynos_drm_encoder {
 	struct drm_crtc			*old_crtc;
 	struct drm_encoder		drm_encoder;
 	struct exynos_drm_manager	*manager;
-	int dpms;
+	int				dpms;
+	bool				updated;
 };
 
 static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
@@ -85,7 +87,9 @@  static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 	switch (mode) {
 	case DRM_MODE_DPMS_ON:
 		if (manager_ops && manager_ops->apply)
-			manager_ops->apply(manager->dev);
+			if (!exynos_encoder->updated)
+				manager_ops->apply(manager->dev);
+
 		exynos_drm_connector_power(encoder, mode);
 		exynos_encoder->dpms = mode;
 		break;
@@ -94,6 +98,7 @@  static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 	case DRM_MODE_DPMS_OFF:
 		exynos_drm_connector_power(encoder, mode);
 		exynos_encoder->dpms = mode;
+		exynos_encoder->updated = false;
 		break;
 	default:
 		DRM_ERROR("unspecified mode %d\n", mode);
@@ -205,13 +210,22 @@  static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)
 
 static void exynos_drm_encoder_commit(struct drm_encoder *encoder)
 {
-	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder);
+	struct exynos_drm_manager *manager = exynos_encoder->manager;
 	struct exynos_drm_manager_ops *manager_ops = manager->ops;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
 	if (manager_ops && manager_ops->commit)
 		manager_ops->commit(manager->dev);
+
+	/*
+	 * this will avoid one issue that overlay data is updated to
+	 * real hardware two times.
+	 * And this variable will be used to check if the data was
+	 * already updated or not by exynos_drm_encoder_dpms function.
+	 */
+	exynos_encoder->updated = true;
 }
 
 static void exynos_drm_encoder_disable(struct drm_encoder *encoder)
@@ -401,19 +415,6 @@  void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)
 		manager_ops->dpms(manager->dev, mode);
 
 	/*
-	 * set current mode to new one so that data aren't updated into
-	 * registers by drm_helper_connector_dpms two times.
-	 *
-	 * in case that drm_crtc_helper_set_mode() is called,
-	 * overlay_ops->commit() and manager_ops->commit() callbacks
-	 * can be called two times, first at drm_crtc_helper_set_mode()
-	 * and second at drm_helper_connector_dpms().
-	 * so with this setting, when drm_helper_connector_dpms() is called
-	 * encoder->funcs->dpms() will be ignored.
-	 */
-	exynos_encoder->dpms = mode;
-
-	/*
 	 * if this condition is ok then it means that the crtc is already
 	 * detached from encoder and last function for detaching is properly
 	 * done, so clear pipe from manager to prevent repeated call.