All of lore.kernel.org
 help / color / mirror / Atom feed
From: Inki Dae <inki.dae@samsung.com>
To: airlied@linux.ie, dri-devel@lists.freedesktop.org
Cc: kyungmin.park@samsung.com
Subject: [PATCH 05/10] drm/exynos: fixed duplicated mode setting.
Date: Mon, 20 Aug 2012 21:35:50 +0900	[thread overview]
Message-ID: <1345466155-9154-6-git-send-email-inki.dae@samsung.com> (raw)
In-Reply-To: <1345466155-9154-1-git-send-email-inki.dae@samsung.com>

this patch fixes that when drm_crtc_helper_set_mode() is called,
mode data for hardware overlay and conntroller are updated two times.
for example, 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().

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 |   41 ++++++++++++++++++++++++-
 drivers/gpu/drm/exynos/exynos_drm_connector.h |    2 +
 drivers/gpu/drm/exynos/exynos_drm_crtc.c      |    3 +-
 drivers/gpu/drm/exynos/exynos_drm_encoder.c   |   30 +++++++++++-------
 4 files changed, 62 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index d956819..1fadc22 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -40,6 +40,7 @@ struct exynos_drm_connector {
 	struct drm_connector	drm_connector;
 	uint32_t		encoder_id;
 	struct exynos_drm_manager *manager;
+	uint32_t		dpms;
 };
 
 /* convert exynos_video_timings to drm_display_mode */
@@ -226,6 +227,43 @@ static struct drm_connector_helper_funcs exynos_connector_helper_funcs = {
 	.best_encoder	= exynos_drm_best_encoder,
 };
 
+void exynos_drm_display_power(struct drm_connector *connector, int mode)
+{
+	struct drm_encoder *encoder = connector->encoder;
+	struct exynos_drm_connector *exynos_connector;
+	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
+	struct exynos_drm_display_ops *display_ops = manager->display_ops;
+
+	exynos_connector = to_exynos_connector(connector);
+
+	if (exynos_connector->dpms == mode) {
+		DRM_DEBUG_KMS("desired dpms mode is same as previous one.\n");
+		return;
+	}
+
+	if (display_ops && display_ops->power_on)
+		display_ops->power_on(manager->dev, mode);
+
+	exynos_connector->dpms = mode;
+}
+
+static void exynos_drm_connector_dpms(struct drm_connector *connector,
+					int mode)
+{
+	DRM_DEBUG_KMS("%s\n", __FILE__);
+
+	/*
+	 * in case that drm_crtc_helper_set_mode() is called,
+	 * encoder/crtc->funcs->dpms() will be just returned
+	 * because they already were DRM_MODE_DPMS_ON so only
+	 * exynos_drm_display_power() will be called.
+	 */
+	drm_helper_connector_dpms(connector, mode);
+
+	exynos_drm_display_power(connector, mode);
+
+}
+
 static int exynos_drm_connector_fill_modes(struct drm_connector *connector,
 				unsigned int max_width, unsigned int max_height)
 {
@@ -285,7 +323,7 @@ static void exynos_drm_connector_destroy(struct drm_connector *connector)
 }
 
 static struct drm_connector_funcs exynos_connector_funcs = {
-	.dpms		= drm_helper_connector_dpms,
+	.dpms		= exynos_drm_connector_dpms,
 	.fill_modes	= exynos_drm_connector_fill_modes,
 	.detect		= exynos_drm_connector_detect,
 	.destroy	= exynos_drm_connector_destroy,
@@ -334,6 +372,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->encoder = encoder;
 
 	err = drm_mode_connector_attach_encoder(connector, encoder);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.h b/drivers/gpu/drm/exynos/exynos_drm_connector.h
index 1c7b2b5..40a55c2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.h
@@ -31,4 +31,6 @@
 struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,
 						   struct drm_encoder *encoder);
 
+void exynos_drm_display_power(struct drm_connector *connector, int mode);
+
 #endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index abb1e2f..b612bf5 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -97,6 +97,7 @@ static void exynos_drm_crtc_commit(struct drm_crtc *crtc)
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
+	exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
 	exynos_plane_commit(exynos_crtc->plane);
 	exynos_plane_dpms(exynos_crtc->plane, DRM_MODE_DPMS_ON);
 }
@@ -126,8 +127,6 @@ exynos_drm_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
-	exynos_drm_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
-
 	/*
 	 * copy the mode data adjusted by mode_fixup() into crtc->mode
 	 * so that hardware can be seet to proper mode.
diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
index 2c037cd..08ba62f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c
@@ -31,6 +31,7 @@
 
 #include "exynos_drm_drv.h"
 #include "exynos_drm_encoder.h"
+#include "exynos_drm_connector.h"
 
 #define to_exynos_encoder(x)	container_of(x, struct exynos_drm_encoder,\
 				drm_encoder)
@@ -49,21 +50,17 @@ struct exynos_drm_encoder {
 	int dpms;
 };
 
-static void exynos_drm_display_power(struct drm_encoder *encoder, int mode)
+static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_connector *connector;
-	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder);
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		if (connector->encoder == encoder) {
-			struct exynos_drm_display_ops *display_ops =
-							manager->display_ops;
-
 			DRM_DEBUG_KMS("connector[%d] dpms[%d]\n",
 					connector->base.id, mode);
-			if (display_ops && display_ops->power_on)
-				display_ops->power_on(manager->dev, mode);
+
+			exynos_drm_display_power(connector, mode);
 		}
 	}
 }
@@ -88,13 +85,13 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)
 	case DRM_MODE_DPMS_ON:
 		if (manager_ops && manager_ops->apply)
 			manager_ops->apply(manager->dev);
-		exynos_drm_display_power(encoder, mode);
+		exynos_drm_connector_power(encoder, mode);
 		exynos_encoder->dpms = mode;
 		break;
 	case DRM_MODE_DPMS_STANDBY:
 	case DRM_MODE_DPMS_SUSPEND:
 	case DRM_MODE_DPMS_OFF:
-		exynos_drm_display_power(encoder, mode);
+		exynos_drm_connector_power(encoder, mode);
 		exynos_encoder->dpms = mode;
 		break;
 	default:
@@ -138,8 +135,6 @@ static void exynos_drm_encoder_mode_set(struct drm_encoder *encoder,
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
-	exynos_drm_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
-
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 		if (connector->encoder == encoder)
 			if (manager_ops && manager_ops->mode_set)
@@ -338,6 +333,19 @@ 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.
-- 
1.7.4.1

  parent reply	other threads:[~2012-08-20 12:35 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-20 12:35 [PATCH 00/10 v2] updated exynos-drm-fixes Inki Dae
2012-08-20 12:35 ` [PATCH 01/10] drm/exynos: added device object to subdrv's remove callback as argument Inki Dae
2012-08-20 12:35 ` [PATCH 02/10] drm/exynos: separated subdrv_probe function into two parts Inki Dae
2012-08-21  4:07   ` [PATCH v2] " Inki Dae
2012-08-20 12:35 ` [PATCH 03/10] drm/exynos: fixed page align bug Inki Dae
2012-08-20 12:35 ` [PATCH 04/10] drm/exynos: separeated fimd_power_on into some parts Inki Dae
2012-08-20 12:35 ` Inki Dae [this message]
2012-08-20 12:35 ` [PATCH 06/10] drm/exynos: add wait_for_vblank callback interface Inki Dae
2012-08-21  2:23   ` [PATCH v2] " Inki Dae
2012-08-20 12:35 ` [PATCH 07/10] drm/exynos: make sure that hardware overlay for fimd is disabled Inki Dae
2012-08-24  9:36   ` [PATCH v2] " Inki Dae
2012-08-20 12:35 ` [PATCH 08/10] drm/exynos: make sure that hardware overlay for hdmi " Inki Dae
2012-08-20 12:35 ` [PATCH 09/10] drm/exynos: check NV12M format specific to Exynos properly Inki Dae
2012-08-20 12:35 ` [PATCH 10/10] drm/exynos: update crtc to plane safely Inki Dae

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1345466155-9154-6-git-send-email-inki.dae@samsung.com \
    --to=inki.dae@samsung.com \
    --cc=airlied@linux.ie \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=kyungmin.park@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.