linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] drm/msm/dsi: Add support for external bridge chips
@ 2015-06-26  7:45 Archit Taneja
  2015-06-26  7:45 ` [PATCH 1/5] drm/msm/dsi: Make TE gpio optional Archit Taneja
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Archit Taneja @ 2015-06-26  7:45 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

The dsi driver only connects to drm_panel devices right now. drm_bridge
based devices can be used to implement external encoder chips (like DSI to
HDMI, DSI to LVDS) etc.

Make changes such that the dsi driver works with drm_bridge devices. This
enables the driver to connect with the encoder chips mentioned above.

Archit Taneja (5):
  drm/msm/dsi: Make TE gpio optional
  drm/msm/dsi: Refer to connected device as 'device' instead of 'panel'
  drm/msm/dsi: Create a helper to check if there is a connected device
  drm/msm/dsi: Allow dsi to connect to an external bridge
  drm/msm/dsi: Modify dsi manager bridge ops to work with external
    bridges

 drivers/gpu/drm/msm/dsi/dsi.c         | 66 ++++++++++++++++++++++++++++++-----
 drivers/gpu/drm/msm/dsi/dsi.h         | 17 ++++++++-
 drivers/gpu/drm/msm/dsi/dsi_host.c    | 49 +++++++++++++++++---------
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 55 ++++++++++++++++++-----------
 4 files changed, 141 insertions(+), 46 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH 1/5] drm/msm/dsi: Make TE gpio optional
  2015-06-26  7:45 [PATCH 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
@ 2015-06-26  7:45 ` Archit Taneja
  2015-06-26  7:45 ` [PATCH 2/5] drm/msm/dsi: Refer to connected device as 'device' instead of 'panel' Archit Taneja
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-06-26  7:45 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

Platforms containing only DSI video mode devices don't need a TE gpio.
Make TE gpio optional.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 5b9077d..3785083f 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1364,7 +1364,8 @@ static int dsi_host_init_panel_gpios(struct msm_dsi_host *msm_host,
 		return PTR_ERR(msm_host->disp_en_gpio);
 	}
 
-	msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te", GPIOD_IN);
+	msm_host->te_gpio = devm_gpiod_get_optional(panel_device, "disp-te",
+								GPIOD_IN);
 	if (IS_ERR(msm_host->te_gpio)) {
 		DBG("cannot get disp-te-gpios %ld", PTR_ERR(msm_host->te_gpio));
 		return PTR_ERR(msm_host->te_gpio);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 2/5] drm/msm/dsi: Refer to connected device as 'device' instead of 'panel'
  2015-06-26  7:45 [PATCH 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
  2015-06-26  7:45 ` [PATCH 1/5] drm/msm/dsi: Make TE gpio optional Archit Taneja
@ 2015-06-26  7:45 ` Archit Taneja
  2015-06-26  7:45 ` [PATCH 3/5] drm/msm/dsi: Create a helper to check if there is a connected device Archit Taneja
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-06-26  7:45 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

We currently support only panels connected to dsi output. We're going to
also support external bridge chips now.

Change 'panel_node' to 'device_node' in the struct msm_dsi_host and
'panel_flags' to 'device_flags' in msm_dsi. This makes things sound a
bit more generic.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi.c         |  2 +-
 drivers/gpu/drm/msm/dsi/dsi.h         |  2 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c    | 31 +++++++++++++++++--------------
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  4 ++--
 4 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 1f2561e..9f5fe59 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -18,7 +18,7 @@ struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
 	if (!msm_dsi || !msm_dsi->panel)
 		return NULL;
 
-	return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ?
+	return (msm_dsi->device_flags & MIPI_DSI_MODE_VIDEO) ?
 		msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] :
 		msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID];
 }
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 5e29aad..2bf4859 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -59,7 +59,7 @@ struct msm_dsi {
 	struct mipi_dsi_host *host;
 	struct msm_dsi_phy *phy;
 	struct drm_panel *panel;
-	unsigned long panel_flags;
+	unsigned long device_flags;
 
 	struct device *phy_dev;
 	bool phy_enabled;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 3785083f..e5a44e7 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -213,8 +213,8 @@ struct msm_dsi_host {
 
 	struct drm_display_mode *mode;
 
-	/* Panel info */
-	struct device_node *panel_node;
+	/* connected device info */
+	struct device_node *device_node;
 	unsigned int channel;
 	unsigned int lanes;
 	enum mipi_dsi_pixel_format format;
@@ -1385,7 +1385,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
 	msm_host->format = dsi->format;
 	msm_host->mode_flags = dsi->mode_flags;
 
-	WARN_ON(dsi->dev.of_node != msm_host->panel_node);
+	WARN_ON(dsi->dev.of_node != msm_host->device_node);
 
 	/* Some gpios defined in panel DT need to be controlled by host */
 	ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev);
@@ -1404,7 +1404,7 @@ static int dsi_host_detach(struct mipi_dsi_host *host,
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 
-	msm_host->panel_node = NULL;
+	msm_host->device_node = NULL;
 
 	DBG("id=%d", msm_host->id);
 	if (msm_host->dev)
@@ -1439,7 +1439,7 @@ static int msm_dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
 	struct device_node *np = dev->of_node;
-	struct device_node *endpoint, *panel_node;
+	struct device_node *endpoint, *device_node;
 	int ret;
 
 	ret = of_property_read_u32(np, "qcom,dsi-host-index", &msm_host->id);
@@ -1451,7 +1451,7 @@ static int msm_dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 
 	/*
 	 * get the first endpoint node. in our case, dsi has one output port
-	 * to which the panel is connected.
+	 * to which the device is connected.
 	 */
 	endpoint = of_graph_get_next_endpoint(np, NULL);
 	if (IS_ERR(endpoint)) {
@@ -1459,18 +1459,21 @@ static int msm_dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 		return PTR_ERR(endpoint);
 	}
 
-	/* get panel node from the output port's endpoint data */
-	panel_node = of_graph_get_remote_port_parent(endpoint);
-	if (IS_ERR(panel_node)) {
+	/*
+	 * get connected device(panel/bridge) node from the output port's
+	 * endpoint data
+	 */
+	device_node = of_graph_get_remote_port_parent(endpoint);
+	if (IS_ERR(device_node)) {
 		dev_err(dev, "%s: no valid device\n", __func__);
 		of_node_put(endpoint);
-		return PTR_ERR(panel_node);
+		return PTR_ERR(device_node);
 	}
 
 	of_node_put(endpoint);
-	of_node_put(panel_node);
+	of_node_put(device_node);
 
-	msm_host->panel_node = panel_node;
+	msm_host->device_node = device_node;
 
 	return 0;
 }
@@ -1622,7 +1625,7 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer)
 		 * create framebuffer.
 		 */
 		if (check_defer) {
-			if (!of_drm_find_panel(msm_host->panel_node))
+			if (!of_drm_find_panel(msm_host->device_node))
 				return -EPROBE_DEFER;
 		}
 	}
@@ -2032,7 +2035,7 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 	struct drm_panel *panel;
 
-	panel = of_drm_find_panel(msm_host->panel_node);
+	panel = of_drm_find_panel(msm_host->device_node);
 	if (panel_flags)
 			*panel_flags = msm_host->mode_flags;
 
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index bd247b7..ec8db80 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -156,7 +156,7 @@ static enum drm_connector_status dsi_mgr_connector_detect(
 	DBG("id=%d", id);
 	if (!msm_dsi->panel) {
 		msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host,
-						&msm_dsi->panel_flags);
+						&msm_dsi->device_flags);
 
 		/* There is only 1 panel in the global panel list
 		 * for dual DSI mode. Therefore slave dsi should get
@@ -177,7 +177,7 @@ static enum drm_connector_status dsi_mgr_connector_detect(
 		 */
 		if (msm_dsi->panel && IS_DUAL_DSI() &&
 			other_dsi && other_dsi->panel) {
-			bool cmd_mode = !(msm_dsi->panel_flags &
+			bool cmd_mode = !(msm_dsi->device_flags &
 						MIPI_DSI_MODE_VIDEO);
 			struct drm_encoder *encoder = msm_dsi_get_encoder(
 					dsi_mgr_get_dsi(DSI_ENCODER_MASTER));
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 3/5] drm/msm/dsi: Create a helper to check if there is a connected device
  2015-06-26  7:45 [PATCH 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
  2015-06-26  7:45 ` [PATCH 1/5] drm/msm/dsi: Make TE gpio optional Archit Taneja
  2015-06-26  7:45 ` [PATCH 2/5] drm/msm/dsi: Refer to connected device as 'device' instead of 'panel' Archit Taneja
@ 2015-06-26  7:45 ` Archit Taneja
  2015-06-26  7:45 ` [PATCH 4/5] drm/msm/dsi: Allow dsi to connect to an external bridge Archit Taneja
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-06-26  7:45 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

Create a helper msm_dsi_device_connected() which checks whether we have a
device connected to the dsi host or not. This check gets messy when we
have support external bridges too. Having an inline function makes it
more legible.

For now, the check only consists of msm_dsi->panel being non-NULL. Later,
this will check if we have an external bridge or not.

This helper isn't used in dsi_connector related code as that's specific
to only when a drm_panel is connected.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi.c         | 2 +-
 drivers/gpu/drm/msm/dsi/dsi.h         | 5 +++++
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 6 ++++--
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 9f5fe59..e991270 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -15,7 +15,7 @@
 
 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
 {
-	if (!msm_dsi || !msm_dsi->panel)
+	if (!msm_dsi || !msm_dsi_device_connected(msm_dsi))
 		return NULL;
 
 	return (msm_dsi->device_flags & MIPI_DSI_MODE_VIDEO) ?
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 2bf4859..d36a449 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -84,6 +84,11 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 
 /* msm dsi */
+static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
+{
+	return msm_dsi->panel;
+}
+
 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi);
 
 /* dsi pll */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index ec8db80..c4c95c7 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -344,7 +344,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 	int ret;
 
 	DBG("id=%d", id);
-	if (!panel || (is_dual_dsi && (DSI_1 == id)))
+	if (!msm_dsi_device_connected(msm_dsi) ||
+			(is_dual_dsi && (DSI_1 == id)))
 		return;
 
 	ret = msm_dsi_host_power_on(host);
@@ -431,7 +432,8 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 
 	DBG("id=%d", id);
 
-	if (!panel || (is_dual_dsi && (DSI_1 == id)))
+	if (!msm_dsi_device_connected(msm_dsi) ||
+			(is_dual_dsi && (DSI_1 == id)))
 		return;
 
 	ret = drm_panel_disable(panel);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 4/5] drm/msm/dsi: Allow dsi to connect to an external bridge
  2015-06-26  7:45 [PATCH 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
                   ` (2 preceding siblings ...)
  2015-06-26  7:45 ` [PATCH 3/5] drm/msm/dsi: Create a helper to check if there is a connected device Archit Taneja
@ 2015-06-26  7:45 ` Archit Taneja
  2015-06-26  7:45 ` [PATCH 5/5] drm/msm/dsi: Modify dsi manager bridge ops to work with external bridges Archit Taneja
  2015-08-02 16:20 ` [PATCH v2 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
  5 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-06-26  7:45 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

There are platforms where the DSI output can be connected to another
encoder bridge chip (DSI to HDMI, DSI to LVDS etc).

Add support for external bridge support to the dsi driver. We assume that
the external bridge chip would be of the type drm_bridge. The dsi driver's
internal drm_bridge (msm_dsi->bridge) is linked to the external bridge's
drm_bridge struct.

In the case we're connected to an external bridge, we don't need to create
and manage a connector within our driver, it's the bridge driver's
responsibility to create one.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi.c         | 62 +++++++++++++++++++++++++++++++----
 drivers/gpu/drm/msm/dsi/dsi.h         | 12 ++++++-
 drivers/gpu/drm/msm/dsi/dsi_host.c    | 15 ++++++++-
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  2 +-
 4 files changed, 81 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index e991270..d91185d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -223,12 +223,59 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
 		msm_dsi->encoders[i] = encoders[i];
 	}
 
-	msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id);
-	if (IS_ERR(msm_dsi->connector)) {
-		ret = PTR_ERR(msm_dsi->connector);
-		dev_err(dev->dev, "failed to create dsi connector: %d\n", ret);
-		msm_dsi->connector = NULL;
-		goto fail;
+	/*
+	 * check if the dsi encoder output is connected to a panel or an
+	 * external bridge. We create a connector only if we're connected to a
+	 * drm_panel device. When we're connected to an external bridge, we
+	 * assume that the drm_bridge driver will create the connector itself.
+	 */
+	msm_dsi->external_bridge = msm_dsi_host_get_bridge(msm_dsi->host,
+					&msm_dsi->device_flags);
+
+	if (msm_dsi->external_bridge) {
+		struct drm_encoder *encoder = msm_dsi_get_encoder(msm_dsi);
+		struct drm_bridge *int_bridge, *ext_bridge;
+		struct drm_connector *connector;
+		struct list_head *connector_list;
+
+		int_bridge = msm_dsi->bridge;
+		ext_bridge = msm_dsi->external_bridge;
+
+		/* link the internal dsi bridge to the external bridge */
+		int_bridge->next = ext_bridge;
+		/* set the external bridge's encoder as dsi's encoder */
+		ext_bridge->encoder = encoder;
+
+		drm_bridge_attach(msm_dsi->dev, ext_bridge);
+
+		/*
+		 * we need the drm_connector created by the external bridge
+		 * driver (or someone else) to feed it to our driver's
+		 * priv->connector[] list
+		 */
+		connector_list = &dev->mode_config.connector_list;
+
+		list_for_each_entry(connector, connector_list, head) {
+			int i;
+
+			for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+				if (connector->encoder_ids[i] ==
+						encoder->base.id) {
+					msm_dsi->connector = connector;
+					break;
+				}
+			}
+		}
+	} else {
+		msm_dsi->connector =
+			msm_dsi_manager_connector_init(msm_dsi->id);
+		if (IS_ERR(msm_dsi->connector)) {
+			ret = PTR_ERR(msm_dsi->connector);
+			dev_err(dev->dev,
+				"failed to create dsi connector: %d\n", ret);
+			msm_dsi->connector = NULL;
+			goto fail;
+		}
 	}
 
 	priv->bridges[priv->num_bridges++]       = msm_dsi->bridge;
@@ -242,7 +289,8 @@ fail:
 			msm_dsi_manager_bridge_destroy(msm_dsi->bridge);
 			msm_dsi->bridge = NULL;
 		}
-		if (msm_dsi->connector) {
+		/* don't destroy connector if we didn't make it */
+		if (msm_dsi->connector && !msm_dsi->external_bridge) {
 			msm_dsi->connector->funcs->destroy(msm_dsi->connector);
 			msm_dsi->connector = NULL;
 		}
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index d36a449..d179ed9 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -53,12 +53,20 @@ struct msm_dsi {
 	struct drm_device *dev;
 	struct platform_device *pdev;
 
+	/* connector managed by us when we're connected to a drm_panel */
 	struct drm_connector *connector;
+	/* internal dsi bridge attached to MDP interface */
 	struct drm_bridge *bridge;
 
 	struct mipi_dsi_host *host;
 	struct msm_dsi_phy *phy;
+
+	/*
+	 * panel/external_bridge connected to dsi bridge output, only one of the
+	 * two can be valid at a time
+	 */
 	struct drm_panel *panel;
+	struct drm_bridge *external_bridge;
 	unsigned long device_flags;
 
 	struct device *phy_dev;
@@ -86,7 +94,7 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 /* msm dsi */
 static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
 {
-	return msm_dsi->panel;
+	return msm_dsi->panel || msm_dsi->external_bridge;
 }
 
 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi);
@@ -133,6 +141,8 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
 					struct drm_display_mode *mode);
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
 					unsigned long *panel_flags);
+struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host,
+					unsigned long *bridge_flags);
 int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);
 void msm_dsi_host_unregister(struct mipi_dsi_host *host);
 int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index e5a44e7..2031a31 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1626,7 +1626,8 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer)
 		 */
 		if (check_defer) {
 			if (!of_drm_find_panel(msm_host->device_node))
-				return -EPROBE_DEFER;
+				if (!of_drm_find_bridge(msm_host->device_node))
+					return -EPROBE_DEFER;
 		}
 	}
 
@@ -2042,3 +2043,15 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
 	return panel;
 }
 
+struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host,
+				unsigned long *bridge_flags)
+{
+	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+	struct drm_bridge *bridge;
+
+	bridge = of_drm_find_bridge(msm_host->device_node);
+	if (bridge_flags)
+		*bridge_flags = msm_host->mode_flags;
+
+	return bridge;
+}
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index c4c95c7..026e223 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -517,7 +517,7 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = {
 	.mode_set = dsi_mgr_bridge_mode_set,
 };
 
-/* initialize connector */
+/* initialize connector when we're connected to a drm_panel */
 struct drm_connector *msm_dsi_manager_connector_init(u8 id)
 {
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH 5/5] drm/msm/dsi: Modify dsi manager bridge ops to work with external bridges
  2015-06-26  7:45 [PATCH 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
                   ` (3 preceding siblings ...)
  2015-06-26  7:45 ` [PATCH 4/5] drm/msm/dsi: Allow dsi to connect to an external bridge Archit Taneja
@ 2015-06-26  7:45 ` Archit Taneja
  2015-08-02 16:20 ` [PATCH v2 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
  5 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-06-26  7:45 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-arm-msm

The dsi bridge ops call drm_panel functions to set up the connected
drm_panel. Add checks to make sure these aren't called when we're
connected to an external bridge.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 43 +++++++++++++++++++++++------------
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 026e223..b03c4ba 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -366,10 +366,13 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 	/* Always call panel functions once, because even for dual panels,
 	 * there is only one drm_panel instance.
 	 */
-	ret = drm_panel_prepare(panel);
-	if (ret) {
-		pr_err("%s: prepare panel %d failed, %d\n", __func__, id, ret);
-		goto panel_prep_fail;
+	if (panel) {
+		ret = drm_panel_prepare(panel);
+		if (ret) {
+			pr_err("%s: prepare panel %d failed, %d\n", __func__,
+								id, ret);
+			goto panel_prep_fail;
+		}
 	}
 
 	ret = msm_dsi_host_enable(host);
@@ -386,10 +389,13 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 		}
 	}
 
-	ret = drm_panel_enable(panel);
-	if (ret) {
-		pr_err("%s: enable panel %d failed, %d\n", __func__, id, ret);
-		goto panel_en_fail;
+	if (panel) {
+		ret = drm_panel_enable(panel);
+		if (ret) {
+			pr_err("%s: enable panel %d failed, %d\n", __func__, id,
+									ret);
+			goto panel_en_fail;
+		}
 	}
 
 	return;
@@ -400,7 +406,8 @@ panel_en_fail:
 host1_en_fail:
 	msm_dsi_host_disable(host);
 host_en_fail:
-	drm_panel_unprepare(panel);
+	if (panel)
+		drm_panel_unprepare(panel);
 panel_prep_fail:
 	if (is_dual_dsi && msm_dsi1)
 		msm_dsi_host_power_off(msm_dsi1->host);
@@ -436,9 +443,12 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 			(is_dual_dsi && (DSI_1 == id)))
 		return;
 
-	ret = drm_panel_disable(panel);
-	if (ret)
-		pr_err("%s: Panel %d OFF failed, %d\n", __func__, id, ret);
+	if (panel) {
+		ret = drm_panel_disable(panel);
+		if (ret)
+			pr_err("%s: Panel %d OFF failed, %d\n", __func__, id,
+									ret);
+	}
 
 	ret = msm_dsi_host_disable(host);
 	if (ret)
@@ -450,9 +460,12 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 			pr_err("%s: host1 disable failed, %d\n", __func__, ret);
 	}
 
-	ret = drm_panel_unprepare(panel);
-	if (ret)
-		pr_err("%s: Panel %d unprepare failed,%d\n", __func__, id, ret);
+	if (panel) {
+		ret = drm_panel_unprepare(panel);
+		if (ret)
+			pr_err("%s: Panel %d unprepare failed,%d\n", __func__,
+								id, ret);
+	}
 
 	ret = msm_dsi_host_power_off(host);
 	if (ret)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 0/5] drm/msm/dsi: Add support for external bridge chips
  2015-06-26  7:45 [PATCH 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
                   ` (4 preceding siblings ...)
  2015-06-26  7:45 ` [PATCH 5/5] drm/msm/dsi: Modify dsi manager bridge ops to work with external bridges Archit Taneja
@ 2015-08-02 16:20 ` Archit Taneja
  2015-08-02 16:20   ` [PATCH v2 1/5] drm/msm/dsi: Make TE gpio optional Archit Taneja
                     ` (4 more replies)
  5 siblings, 5 replies; 12+ messages in thread
From: Archit Taneja @ 2015-08-02 16:20 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

The dsi driver only connects to drm_panel devices right now. drm_bridge
based devices can be used to implement external encoder chips (like DSI to
HDMI, DSI to LVDS) etc.

Make changes such that the dsi driver works with drm_bridge devices. This
enables the driver to connect with the encoder chips mentioned above.

v2:
- Rebased over v3 of drm/msm: "Use device graph to parse connected panels"
- Some little tweaks

Archit Taneja (5):
  drm/msm/dsi: Make TE gpio optional
  drm/msm/dsi: Refer to connected device as 'device' instead of 'panel'
  drm/msm/dsi: Create a helper to check if there is a connected device
  drm/msm/dsi: Allow dsi to connect to an external bridge
  drm/msm/dsi: Modify dsi manager bridge ops to work with external
    bridges

 drivers/gpu/drm/msm/dsi/dsi.c         |  32 ++++++++---
 drivers/gpu/drm/msm/dsi/dsi.h         |  17 +++++-
 drivers/gpu/drm/msm/dsi/dsi_host.c    |  36 +++++++-----
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 102 +++++++++++++++++++++++++++-------
 4 files changed, 145 insertions(+), 42 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v2 1/5] drm/msm/dsi: Make TE gpio optional
  2015-08-02 16:20 ` [PATCH v2 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
@ 2015-08-02 16:20   ` Archit Taneja
  2015-08-02 16:20   ` [PATCH v2 2/5] drm/msm/dsi: Refer to connected device as 'device' instead of 'panel' Archit Taneja
                     ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-08-02 16:20 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

Platforms containing only DSI video mode devices don't need a TE gpio.
Make TE gpio optional.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 914559c..e3659dd 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1360,7 +1360,8 @@ static int dsi_host_init_panel_gpios(struct msm_dsi_host *msm_host,
 		return PTR_ERR(msm_host->disp_en_gpio);
 	}
 
-	msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te", GPIOD_IN);
+	msm_host->te_gpio = devm_gpiod_get_optional(panel_device, "disp-te",
+								GPIOD_IN);
 	if (IS_ERR(msm_host->te_gpio)) {
 		DBG("cannot get disp-te-gpios %ld", PTR_ERR(msm_host->te_gpio));
 		return PTR_ERR(msm_host->te_gpio);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 2/5] drm/msm/dsi: Refer to connected device as 'device' instead of 'panel'
  2015-08-02 16:20 ` [PATCH v2 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
  2015-08-02 16:20   ` [PATCH v2 1/5] drm/msm/dsi: Make TE gpio optional Archit Taneja
@ 2015-08-02 16:20   ` Archit Taneja
  2015-08-02 16:20   ` [PATCH v2 3/5] drm/msm/dsi: Create a helper to check if there is a connected device Archit Taneja
                     ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-08-02 16:20 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

We currently support only panels connected to dsi output. We're going to
also support external bridge chips now.

Change 'panel_node' to 'device_node' in the struct msm_dsi_host and
'panel_flags' to 'device_flags' in msm_dsi. This makes things sound a
bit more generic.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi.c         |  2 +-
 drivers/gpu/drm/msm/dsi/dsi.h         |  2 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c    | 24 ++++++++++++------------
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  4 ++--
 4 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 1f2561e..9f5fe59 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -18,7 +18,7 @@ struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
 	if (!msm_dsi || !msm_dsi->panel)
 		return NULL;
 
-	return (msm_dsi->panel_flags & MIPI_DSI_MODE_VIDEO) ?
+	return (msm_dsi->device_flags & MIPI_DSI_MODE_VIDEO) ?
 		msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID] :
 		msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID];
 }
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 92d697d..fe5204e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -71,7 +71,7 @@ struct msm_dsi {
 	struct mipi_dsi_host *host;
 	struct msm_dsi_phy *phy;
 	struct drm_panel *panel;
-	unsigned long panel_flags;
+	unsigned long device_flags;
 
 	struct device *phy_dev;
 	bool phy_enabled;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index e3659dd..06f2975 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -213,8 +213,8 @@ struct msm_dsi_host {
 
 	struct drm_display_mode *mode;
 
-	/* Panel info */
-	struct device_node *panel_node;
+	/* connected device info */
+	struct device_node *device_node;
 	unsigned int channel;
 	unsigned int lanes;
 	enum mipi_dsi_pixel_format format;
@@ -1381,7 +1381,7 @@ static int dsi_host_attach(struct mipi_dsi_host *host,
 	msm_host->format = dsi->format;
 	msm_host->mode_flags = dsi->mode_flags;
 
-	WARN_ON(dsi->dev.of_node != msm_host->panel_node);
+	WARN_ON(dsi->dev.of_node != msm_host->device_node);
 
 	/* Some gpios defined in panel DT need to be controlled by host */
 	ret = dsi_host_init_panel_gpios(msm_host, &dsi->dev);
@@ -1400,7 +1400,7 @@ static int dsi_host_detach(struct mipi_dsi_host *host,
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 
-	msm_host->panel_node = NULL;
+	msm_host->device_node = NULL;
 
 	DBG("id=%d", msm_host->id);
 	if (msm_host->dev)
@@ -1435,7 +1435,7 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
 	struct device_node *np = dev->of_node;
-	struct device_node *endpoint, *panel_node;
+	struct device_node *endpoint, *device_node;
 	int ret;
 
 	ret = of_property_read_u32(np, "qcom,dsi-host-index", &msm_host->id);
@@ -1458,17 +1458,17 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 	}
 
 	/* Get panel node from the output port's endpoint data */
-	panel_node = of_graph_get_remote_port_parent(endpoint);
-	if (!panel_node) {
+	device_node = of_graph_get_remote_port_parent(endpoint);
+	if (!device_node) {
 		dev_err(dev, "%s: no valid device\n", __func__);
 		of_node_put(endpoint);
 		return -ENODEV;
 	}
 
 	of_node_put(endpoint);
-	of_node_put(panel_node);
+	of_node_put(device_node);
 
-	msm_host->panel_node = panel_node;
+	msm_host->device_node = device_node;
 
 	return 0;
 }
@@ -1621,8 +1621,8 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer)
 		 * Don't try to defer if there is nothing connected to the dsi
 		 * output
 		 */
-		if (check_defer && msm_host->panel_node) {
-			if (!of_drm_find_panel(msm_host->panel_node))
+		if (check_defer && msm_host->device_node) {
+			if (!of_drm_find_panel(msm_host->device_node))
 				return -EPROBE_DEFER;
 		}
 	}
@@ -2032,7 +2032,7 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
 	struct drm_panel *panel;
 
-	panel = of_drm_find_panel(msm_host->panel_node);
+	panel = of_drm_find_panel(msm_host->device_node);
 	if (panel_flags)
 			*panel_flags = msm_host->mode_flags;
 
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 87ac661..925412e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -144,7 +144,7 @@ static enum drm_connector_status dsi_mgr_connector_detect(
 	DBG("id=%d", id);
 	if (!msm_dsi->panel) {
 		msm_dsi->panel = msm_dsi_host_get_panel(msm_dsi->host,
-						&msm_dsi->panel_flags);
+						&msm_dsi->device_flags);
 
 		/* There is only 1 panel in the global panel list
 		 * for dual panel mode. Therefore slave dsi should get
@@ -165,7 +165,7 @@ static enum drm_connector_status dsi_mgr_connector_detect(
 		 */
 		if (msm_dsi->panel && IS_DUAL_PANEL() &&
 			other_dsi && other_dsi->panel) {
-			bool cmd_mode = !(msm_dsi->panel_flags &
+			bool cmd_mode = !(msm_dsi->device_flags &
 						MIPI_DSI_MODE_VIDEO);
 			struct drm_encoder *encoder = msm_dsi_get_encoder(
 					dsi_mgr_get_dsi(DSI_ENCODER_MASTER));
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 3/5] drm/msm/dsi: Create a helper to check if there is a connected device
  2015-08-02 16:20 ` [PATCH v2 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
  2015-08-02 16:20   ` [PATCH v2 1/5] drm/msm/dsi: Make TE gpio optional Archit Taneja
  2015-08-02 16:20   ` [PATCH v2 2/5] drm/msm/dsi: Refer to connected device as 'device' instead of 'panel' Archit Taneja
@ 2015-08-02 16:20   ` Archit Taneja
  2015-08-02 16:20   ` [PATCH v2 4/5] drm/msm/dsi: Allow dsi to connect to an external bridge Archit Taneja
  2015-08-02 16:20   ` [PATCH v2 5/5] drm/msm/dsi: Modify dsi manager bridge ops to work with external bridges Archit Taneja
  4 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-08-02 16:20 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

Create a helper msm_dsi_device_connected() which checks whether we have a
device connected to the dsi host or not. This check gets messy when we
have support external bridges too. Having an inline function makes it
more legible.

For now, the check only consists of msm_dsi->panel being non-NULL. Later,
this will check if we have an external bridge or not.

This helper isn't used in dsi_connector related code as that's specific
to only when a drm_panel is connected.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi.c         | 2 +-
 drivers/gpu/drm/msm/dsi/dsi.h         | 5 +++++
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 6 ++++--
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 9f5fe59..e991270 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -15,7 +15,7 @@
 
 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
 {
-	if (!msm_dsi || !msm_dsi->panel)
+	if (!msm_dsi || !msm_dsi_device_connected(msm_dsi))
 		return NULL;
 
 	return (msm_dsi->device_flags & MIPI_DSI_MODE_VIDEO) ?
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index fe5204e..918b0c6 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -96,6 +96,11 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 
 /* msm dsi */
+static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
+{
+	return msm_dsi->panel;
+}
+
 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi);
 
 /* dsi pll */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 925412e..e252d9d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -332,7 +332,8 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 	int ret;
 
 	DBG("id=%d", id);
-	if (!panel || (is_dual_panel && (DSI_1 == id)))
+	if (!msm_dsi_device_connected(msm_dsi) ||
+			(is_dual_panel && (DSI_1 == id)))
 		return;
 
 	ret = msm_dsi_host_power_on(host);
@@ -419,7 +420,8 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 
 	DBG("id=%d", id);
 
-	if (!panel || (is_dual_panel && (DSI_1 == id)))
+	if (!msm_dsi_device_connected(msm_dsi) ||
+			(is_dual_panel && (DSI_1 == id)))
 		return;
 
 	ret = drm_panel_disable(panel);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 4/5] drm/msm/dsi: Allow dsi to connect to an external bridge
  2015-08-02 16:20 ` [PATCH v2 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
                     ` (2 preceding siblings ...)
  2015-08-02 16:20   ` [PATCH v2 3/5] drm/msm/dsi: Create a helper to check if there is a connected device Archit Taneja
@ 2015-08-02 16:20   ` Archit Taneja
  2015-08-02 16:20   ` [PATCH v2 5/5] drm/msm/dsi: Modify dsi manager bridge ops to work with external bridges Archit Taneja
  4 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-08-02 16:20 UTC (permalink / raw)
  To: dri-devel
  Cc: robdclark, linux-arm-msm, hali, wentaox, sviau, jilaiw, Archit Taneja

There are platforms where the DSI output can be connected to another
encoder bridge chip (DSI to HDMI, DSI to LVDS etc).

Add support for external bridge support to the dsi driver. We assume that
the external bridge chip would be of the type drm_bridge. The dsi driver's
internal drm_bridge (msm_dsi->bridge) is linked to the external bridge's
drm_bridge struct.

In the case we're connected to an external bridge, we don't need to create
and manage a connector within our driver, it's the bridge driver's
responsibility to create one.

v2:
- Move the external bridge attaching stuff to dsi manager to make things
  cleaner.
- Force the bridge to connect to a video mode encoder for now (the dsi
  mode flags may have not been populated by modeset_init)

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi.c         | 28 ++++++++++++++++----
 drivers/gpu/drm/msm/dsi/dsi.h         | 12 ++++++++-
 drivers/gpu/drm/msm/dsi/dsi_host.c    |  9 ++++++-
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 49 ++++++++++++++++++++++++++++++++++-
 4 files changed, 90 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index e991270..f036060 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -196,6 +196,7 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
 		struct drm_encoder *encoders[MSM_DSI_ENCODER_NUM])
 {
 	struct msm_drm_private *priv = dev->dev_private;
+	struct drm_bridge *ext_bridge;
 	int ret, i;
 
 	if (WARN_ON(!encoders[MSM_DSI_VIDEO_ENCODER_ID] ||
@@ -223,10 +224,25 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
 		msm_dsi->encoders[i] = encoders[i];
 	}
 
-	msm_dsi->connector = msm_dsi_manager_connector_init(msm_dsi->id);
+	/*
+	 * check if the dsi encoder output is connected to a panel or an
+	 * external bridge. We create a connector only if we're connected to a
+	 * drm_panel device. When we're connected to an external bridge, we
+	 * assume that the drm_bridge driver will create the connector itself.
+	 */
+	ext_bridge = msm_dsi_host_get_bridge(msm_dsi->host);
+
+	if (ext_bridge)
+		msm_dsi->connector =
+			msm_dsi_manager_ext_bridge_init(msm_dsi->id);
+	else
+		msm_dsi->connector =
+			msm_dsi_manager_connector_init(msm_dsi->id);
+
 	if (IS_ERR(msm_dsi->connector)) {
 		ret = PTR_ERR(msm_dsi->connector);
-		dev_err(dev->dev, "failed to create dsi connector: %d\n", ret);
+		dev_err(dev->dev,
+			"failed to create dsi connector: %d\n", ret);
 		msm_dsi->connector = NULL;
 		goto fail;
 	}
@@ -242,10 +258,12 @@ fail:
 			msm_dsi_manager_bridge_destroy(msm_dsi->bridge);
 			msm_dsi->bridge = NULL;
 		}
-		if (msm_dsi->connector) {
+
+		/* don't destroy connector if we didn't make it */
+		if (msm_dsi->connector && !msm_dsi->external_bridge)
 			msm_dsi->connector->funcs->destroy(msm_dsi->connector);
-			msm_dsi->connector = NULL;
-		}
+
+		msm_dsi->connector = NULL;
 	}
 
 	return ret;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 918b0c6..2a5e02c 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -65,12 +65,20 @@ struct msm_dsi {
 	struct drm_device *dev;
 	struct platform_device *pdev;
 
+	/* connector managed by us when we're connected to a drm_panel */
 	struct drm_connector *connector;
+	/* internal dsi bridge attached to MDP interface */
 	struct drm_bridge *bridge;
 
 	struct mipi_dsi_host *host;
 	struct msm_dsi_phy *phy;
+
+	/*
+	 * panel/external_bridge connected to dsi bridge output, only one of the
+	 * two can be valid at a time
+	 */
 	struct drm_panel *panel;
+	struct drm_bridge *external_bridge;
 	unsigned long device_flags;
 
 	struct device *phy_dev;
@@ -86,6 +94,7 @@ struct msm_dsi {
 struct drm_bridge *msm_dsi_manager_bridge_init(u8 id);
 void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge);
 struct drm_connector *msm_dsi_manager_connector_init(u8 id);
+struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id);
 int msm_dsi_manager_phy_enable(int id,
 		const unsigned long bit_rate, const unsigned long esc_rate,
 		u32 *clk_pre, u32 *clk_post);
@@ -98,7 +107,7 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 /* msm dsi */
 static inline bool msm_dsi_device_connected(struct msm_dsi *msm_dsi)
 {
-	return msm_dsi->panel;
+	return msm_dsi->panel || msm_dsi->external_bridge;
 }
 
 struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi);
@@ -145,6 +154,7 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
 					struct drm_display_mode *mode);
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
 					unsigned long *panel_flags);
+struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host);
 int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);
 void msm_dsi_host_unregister(struct mipi_dsi_host *host);
 int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 06f2975..8134a17 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1623,7 +1623,8 @@ int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer)
 		 */
 		if (check_defer && msm_host->device_node) {
 			if (!of_drm_find_panel(msm_host->device_node))
-				return -EPROBE_DEFER;
+				if (!of_drm_find_bridge(msm_host->device_node))
+					return -EPROBE_DEFER;
 		}
 	}
 
@@ -2039,3 +2040,9 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
 	return panel;
 }
 
+struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host)
+{
+	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+
+	return of_drm_find_bridge(msm_host->device_node);
+}
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index e252d9d..620aca0 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -505,7 +505,7 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = {
 	.mode_set = dsi_mgr_bridge_mode_set,
 };
 
-/* initialize connector */
+/* initialize connector when we're connected to a drm_panel */
 struct drm_connector *msm_dsi_manager_connector_init(u8 id)
 {
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
@@ -590,6 +590,53 @@ fail:
 	return ERR_PTR(ret);
 }
 
+struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id)
+{
+	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+	struct drm_device *dev = msm_dsi->dev;
+	struct drm_encoder *encoder;
+	struct drm_bridge *int_bridge, *ext_bridge;
+	struct drm_connector *connector;
+	struct list_head *connector_list;
+
+	int_bridge = msm_dsi->bridge;
+	ext_bridge = msm_dsi->external_bridge =
+			msm_dsi_host_get_bridge(msm_dsi->host);
+
+	/*
+	 * HACK: we may not know the external DSI bridge device's mode
+	 * flags here. We'll get to know them only when the device
+	 * attaches to the dsi host. For now, assume the bridge supports
+	 * DSI video mode
+	 */
+	encoder = msm_dsi->encoders[MSM_DSI_VIDEO_ENCODER_ID];
+
+	/* link the internal dsi bridge to the external bridge */
+	int_bridge->next = ext_bridge;
+	/* set the external bridge's encoder as dsi's encoder */
+	ext_bridge->encoder = encoder;
+
+	drm_bridge_attach(dev, ext_bridge);
+
+	/*
+	 * we need the drm_connector created by the external bridge
+	 * driver (or someone else) to feed it to our driver's
+	 * priv->connector[] list, mainly for msm_fbdev_init()
+	 */
+	connector_list = &dev->mode_config.connector_list;
+
+	list_for_each_entry(connector, connector_list, head) {
+		int i;
+
+		for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
+			if (connector->encoder_ids[i] == encoder->base.id)
+				return connector;
+		}
+	}
+
+	return ERR_PTR(-ENODEV);
+}
+
 void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge)
 {
 }
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v2 5/5] drm/msm/dsi: Modify dsi manager bridge ops to work with external bridges
  2015-08-02 16:20 ` [PATCH v2 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
                     ` (3 preceding siblings ...)
  2015-08-02 16:20   ` [PATCH v2 4/5] drm/msm/dsi: Allow dsi to connect to an external bridge Archit Taneja
@ 2015-08-02 16:20   ` Archit Taneja
  4 siblings, 0 replies; 12+ messages in thread
From: Archit Taneja @ 2015-08-02 16:20 UTC (permalink / raw)
  To: dri-devel; +Cc: linux-arm-msm

The dsi bridge ops call drm_panel functions to set up the connected
drm_panel. Add checks to make sure these aren't called when we're
connected to an external bridge.

Signed-off-by: Archit Taneja <architt@codeaurora.org>
---
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 43 +++++++++++++++++++++++------------
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 620aca0..3d4f977 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -354,10 +354,13 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 	/* Always call panel functions once, because even for dual panels,
 	 * there is only one drm_panel instance.
 	 */
-	ret = drm_panel_prepare(panel);
-	if (ret) {
-		pr_err("%s: prepare panel %d failed, %d\n", __func__, id, ret);
-		goto panel_prep_fail;
+	if (panel) {
+		ret = drm_panel_prepare(panel);
+		if (ret) {
+			pr_err("%s: prepare panel %d failed, %d\n", __func__,
+								id, ret);
+			goto panel_prep_fail;
+		}
 	}
 
 	ret = msm_dsi_host_enable(host);
@@ -374,10 +377,13 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge)
 		}
 	}
 
-	ret = drm_panel_enable(panel);
-	if (ret) {
-		pr_err("%s: enable panel %d failed, %d\n", __func__, id, ret);
-		goto panel_en_fail;
+	if (panel) {
+		ret = drm_panel_enable(panel);
+		if (ret) {
+			pr_err("%s: enable panel %d failed, %d\n", __func__, id,
+									ret);
+			goto panel_en_fail;
+		}
 	}
 
 	return;
@@ -388,7 +394,8 @@ panel_en_fail:
 host1_en_fail:
 	msm_dsi_host_disable(host);
 host_en_fail:
-	drm_panel_unprepare(panel);
+	if (panel)
+		drm_panel_unprepare(panel);
 panel_prep_fail:
 	if (is_dual_panel && msm_dsi1)
 		msm_dsi_host_power_off(msm_dsi1->host);
@@ -424,9 +431,12 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 			(is_dual_panel && (DSI_1 == id)))
 		return;
 
-	ret = drm_panel_disable(panel);
-	if (ret)
-		pr_err("%s: Panel %d OFF failed, %d\n", __func__, id, ret);
+	if (panel) {
+		ret = drm_panel_disable(panel);
+		if (ret)
+			pr_err("%s: Panel %d OFF failed, %d\n", __func__, id,
+									ret);
+	}
 
 	ret = msm_dsi_host_disable(host);
 	if (ret)
@@ -438,9 +448,12 @@ static void dsi_mgr_bridge_post_disable(struct drm_bridge *bridge)
 			pr_err("%s: host1 disable failed, %d\n", __func__, ret);
 	}
 
-	ret = drm_panel_unprepare(panel);
-	if (ret)
-		pr_err("%s: Panel %d unprepare failed,%d\n", __func__, id, ret);
+	if (panel) {
+		ret = drm_panel_unprepare(panel);
+		if (ret)
+			pr_err("%s: Panel %d unprepare failed,%d\n", __func__,
+								id, ret);
+	}
 
 	ret = msm_dsi_host_power_off(host);
 	if (ret)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply related	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2015-08-02 16:20 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-26  7:45 [PATCH 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
2015-06-26  7:45 ` [PATCH 1/5] drm/msm/dsi: Make TE gpio optional Archit Taneja
2015-06-26  7:45 ` [PATCH 2/5] drm/msm/dsi: Refer to connected device as 'device' instead of 'panel' Archit Taneja
2015-06-26  7:45 ` [PATCH 3/5] drm/msm/dsi: Create a helper to check if there is a connected device Archit Taneja
2015-06-26  7:45 ` [PATCH 4/5] drm/msm/dsi: Allow dsi to connect to an external bridge Archit Taneja
2015-06-26  7:45 ` [PATCH 5/5] drm/msm/dsi: Modify dsi manager bridge ops to work with external bridges Archit Taneja
2015-08-02 16:20 ` [PATCH v2 0/5] drm/msm/dsi: Add support for external bridge chips Archit Taneja
2015-08-02 16:20   ` [PATCH v2 1/5] drm/msm/dsi: Make TE gpio optional Archit Taneja
2015-08-02 16:20   ` [PATCH v2 2/5] drm/msm/dsi: Refer to connected device as 'device' instead of 'panel' Archit Taneja
2015-08-02 16:20   ` [PATCH v2 3/5] drm/msm/dsi: Create a helper to check if there is a connected device Archit Taneja
2015-08-02 16:20   ` [PATCH v2 4/5] drm/msm/dsi: Allow dsi to connect to an external bridge Archit Taneja
2015-08-02 16:20   ` [PATCH v2 5/5] drm/msm/dsi: Modify dsi manager bridge ops to work with external bridges Archit Taneja

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).