linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Archit Taneja <archit@ti.com>
To: dri-devel@lists.freedesktop.org, robdclark@gmail.com
Cc: linux-omap@vger.kernel.org, tomi.valkeinen@ti.com,
	Archit Taneja <archit@ti.com>
Subject: [PATCH v3 1/4] drm/omap: fix: Defer probe if an omapdss device requests for it at connect
Date: Thu, 2 Jan 2014 14:49:51 +0530	[thread overview]
Message-ID: <1388654394-5708-2-git-send-email-archit@ti.com> (raw)
In-Reply-To: <1388654394-5708-1-git-send-email-archit@ti.com>

With the omapdss device model changes. omapdrm is required to call dssdriver's
connect() op to register a panel. This is currently done in omap_modeset_init()

A call to connect() can fail if the omapdss panels or the encoders(HDMI/DPI)
they connect to have some resource(like regulators, I2C adapter) missing. If
this happens, the correct approach is to defer omapdrm's probe.

omapdrm currently ignores those panels which return a non zero value when
connected. This could result in omapdrm ignoring all panels on an omap board.

The right approach would be for omapdrm to request for probe deferral when a
panel's connect op returns -EPROBE_DEFER.

In order to do this, we need to call connect() much earlier during omapdrm's
probe to prevent too many things are already done by then. We now connect the
panels during pdev_probe(), before anything else is initialized, so that we
don't need to undo too many things if a defer was requested.

Now when we enter omap_modeset_init(), we have a set of panels that have been
connected. We now proceed with registering only those panels that are already
connected.

A special case has to be considered when no panels are available to connect when
omapdrm probes. In this case too, we defer probe and expect that a panel will be
available to connect the next time.

Checking whether the panel has a driver or whether it has get_timing/read_edid
ops in omap_modeset_init() are redundant with the new display model. These can
be removed since a dssdev device will always have a driver associated with it,
and all dssdev drivers have a get_timings op.

This will mainly fix cases when omapdrm is built-in the kernel, since that's
generally where resources like regulators or I2C are unavailable because of
probe order dependencies.

In particular this fixes boot with omapdrm built-in on an omap4 panda ES board.
The regulators used by HDMI(provided by I2C based TWL regulators) aren't
initialized because I2C isn't initialized, I2C isn't initialized as it's pins
are not configured because pinctrl is yet to probe.

Signed-off-by: Archit Taneja <archit@ti.com>
---
 drivers/gpu/drm/omapdrm/omap_crtc.c |  5 +++
 drivers/gpu/drm/omapdrm/omap_drv.c  | 70 +++++++++++++++++++++++++------------
 drivers/gpu/drm/omapdrm/omap_drv.h  |  1 +
 3 files changed, 54 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 0fd2eb1..9c01311 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -623,6 +623,11 @@ void omap_crtc_pre_init(void)
 	dss_install_mgr_ops(&mgr_ops);
 }
 
+void omap_crtc_pre_uninit(void)
+{
+	dss_uninstall_mgr_ops();
+}
+
 /* initialize crtc */
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, enum omap_channel channel, int id)
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index e7fa3cd..651f902 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -87,6 +87,43 @@ static bool channel_used(struct drm_device *dev, enum omap_channel channel)
 	return false;
 }
 
+static int omap_connect_dssdevs(void)
+{
+	int r;
+	struct omap_dss_device *dssdev = NULL;
+	bool no_displays = true;
+
+	for_each_dss_dev(dssdev) {
+		r = dssdev->driver->connect(dssdev);
+		if (r == -EPROBE_DEFER) {
+			omap_dss_put_device(dssdev);
+			goto cleanup;
+		} else if (r) {
+			dev_warn(dssdev->dev, "could not connect display: %s\n",
+				dssdev->name);
+		} else {
+			no_displays = false;
+		}
+	}
+
+	if (no_displays)
+		return -EPROBE_DEFER;
+
+	return 0;
+
+cleanup:
+	/*
+	 * if we are deferring probe, we disconnect the devices we previously
+	 * connected
+	 */
+	dssdev = NULL;
+
+	for_each_dss_dev(dssdev)
+		dssdev->driver->disconnect(dssdev);
+
+	return r;
+}
+
 static int omap_modeset_init(struct drm_device *dev)
 {
 	struct omap_drm_private *priv = dev->dev_private;
@@ -95,9 +132,6 @@ static int omap_modeset_init(struct drm_device *dev)
 	int num_mgrs = dss_feat_get_num_mgrs();
 	int num_crtcs;
 	int i, id = 0;
-	int r;
-
-	omap_crtc_pre_init();
 
 	drm_mode_config_init(dev);
 
@@ -119,26 +153,8 @@ static int omap_modeset_init(struct drm_device *dev)
 		enum omap_channel channel;
 		struct omap_overlay_manager *mgr;
 
-		if (!dssdev->driver) {
-			dev_warn(dev->dev, "%s has no driver.. skipping it\n",
-					dssdev->name);
-			continue;
-		}
-
-		if (!(dssdev->driver->get_timings ||
-					dssdev->driver->read_edid)) {
-			dev_warn(dev->dev, "%s driver does not support "
-				"get_timings or read_edid.. skipping it!\n",
-				dssdev->name);
-			continue;
-		}
-
-		r = dssdev->driver->connect(dssdev);
-		if (r) {
-			dev_err(dev->dev, "could not connect display: %s\n",
-					dssdev->name);
+		if (!omapdss_device_is_connected(dssdev))
 			continue;
-		}
 
 		encoder = omap_encoder_init(dev, dssdev);
 
@@ -655,9 +671,19 @@ static void pdev_shutdown(struct platform_device *device)
 
 static int pdev_probe(struct platform_device *device)
 {
+	int r;
+
 	if (omapdss_is_initialized() == false)
 		return -EPROBE_DEFER;
 
+	omap_crtc_pre_init();
+
+	r = omap_connect_dssdevs();
+	if (r) {
+		omap_crtc_pre_uninit();
+		return r;
+	}
+
 	DBG("%s", device->name);
 	return drm_platform_init(&omap_drm_driver, device);
 }
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h
index 0784769..f6c2236 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.h
+++ b/drivers/gpu/drm/omapdrm/omap_drv.h
@@ -158,6 +158,7 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
 int omap_crtc_apply(struct drm_crtc *crtc,
 		struct omap_drm_apply *apply);
 void omap_crtc_pre_init(void);
+void omap_crtc_pre_uninit(void);
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
 		struct drm_plane *plane, enum omap_channel channel, int id);
 
-- 
1.8.3.2


  reply	other threads:[~2014-01-02  9:20 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-01-02  9:19 [PATCH v3 0/4] drm/omap: fix issues in omap_drv probe/remove Archit Taneja
2014-01-02  9:19 ` Archit Taneja [this message]
2014-01-02  9:19 ` [PATCH v3 2/4] drm/omap: fix: disconnect devices when omapdrm module is removed Archit Taneja
2014-01-02  9:19 ` [PATCH v3 3/4] drm/omap: fix: disable encoder before destroying it Archit Taneja
2014-01-02  9:19 ` [PATCH v3 4/4] drm/omap: fix: change dev_unload order Archit Taneja
2014-01-08 13:22 ` [PATCH v3 0/4] drm/omap: fix issues in omap_drv probe/remove Tomi Valkeinen

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=1388654394-5708-2-git-send-email-archit@ti.com \
    --to=archit@ti.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-omap@vger.kernel.org \
    --cc=robdclark@gmail.com \
    --cc=tomi.valkeinen@ti.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).