diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2018-09-23 12:58:15 +0300 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2019-03-18 11:42:14 +0200 |
commit | 79107f274b2fc6bce13f687de33c8d0b70994558 (patch) | |
tree | c7aa23a717c4ecb622157370dffb4c9c40ff2951 /drivers/gpu/drm/omapdrm/omap_drv.c | |
parent | 163f7a3578eca8f9bc550e0161b7d9b79e24e056 (diff) | |
download | talos-op-linux-79107f274b2fc6bce13f687de33c8d0b70994558.tar.gz talos-op-linux-79107f274b2fc6bce13f687de33c8d0b70994558.zip |
drm/omap: Add support for drm_bridge
Hook up drm_bridge support in the omapdrm driver. Despite the recent
extensive preparation work, this is a rather intrusive change, as the
management of outputs needs to be adapted through the driver to handle
both omap_dss_device and drm_bridge.
Connector creation is skipped when using a drm_bridge, as the bridge
creates the connector internally. This creates issues with systems that
split connector operations (such as modes retrieval and hot-plug
detection) across different bridges. These systems can't be supported
using drm_bridge for now (their support through the omap_dss_device
infrastructure is not affected), this will be fixed in subsequent
changes.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 69 |
1 files changed, 51 insertions, 18 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 33f79c490011..f3a36f7b3c4d 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -140,9 +140,7 @@ static void omap_disconnect_pipelines(struct drm_device *ddev) omapdss_device_disconnect(NULL, pipe->output); omapdss_device_put(pipe->output); - omapdss_device_put(pipe->display); pipe->output = NULL; - pipe->display = NULL; } memset(&priv->channels, 0, sizeof(priv->channels)); @@ -169,7 +167,6 @@ static int omap_connect_pipelines(struct drm_device *ddev) pipe = &priv->pipes[priv->num_pipes++]; pipe->output = omapdss_device_get(output); - pipe->display = omapdss_display_get(output); if (priv->num_pipes == ARRAY_SIZE(priv->pipes)) { /* To balance the 'for_each_dss_output' loop */ @@ -207,6 +204,28 @@ static int omap_modeset_init_properties(struct drm_device *dev) return 0; } +static int omap_display_id(struct omap_dss_device *output) +{ + struct device_node *node = NULL; + + if (output->next) { + struct omap_dss_device *display; + + display = omapdss_display_get(output); + node = display->dev->of_node; + omapdss_device_put(display); + } else { + struct drm_bridge *bridge = output->bridge; + + while (bridge->next) + bridge = bridge->next; + + node = bridge->of_node; + } + + return node ? of_alias_get_id(node, "display") : -ENODEV; +} + static int omap_modeset_init(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; @@ -262,7 +281,10 @@ static int omap_modeset_init(struct drm_device *dev) priv->planes[priv->num_planes++] = plane; } - /* Create the encoders and get the pipelines aliases. */ + /* + * Create the encoders, attach the bridges and get the pipeline alias + * IDs. + */ for (i = 0; i < priv->num_pipes; i++) { struct omap_drm_pipeline *pipe = &priv->pipes[i]; int id; @@ -271,7 +293,14 @@ static int omap_modeset_init(struct drm_device *dev) if (!pipe->encoder) return -ENOMEM; - id = of_alias_get_id(pipe->display->dev->of_node, "display"); + if (pipe->output->bridge) { + ret = drm_bridge_attach(pipe->encoder, + pipe->output->bridge, NULL); + if (ret < 0) + return ret; + } + + id = omap_display_id(pipe->output); pipe->alias_id = id >= 0 ? id : i; } @@ -297,16 +326,16 @@ static int omap_modeset_init(struct drm_device *dev) for (i = 0; i < priv->num_pipes; i++) { struct omap_drm_pipeline *pipe = &priv->pipes[i]; struct drm_encoder *encoder = pipe->encoder; - struct drm_connector *connector; struct drm_crtc *crtc; - connector = omap_connector_init(dev, pipe->output, - pipe->display, encoder); - if (!connector) - return -ENOMEM; + if (!pipe->output->bridge) { + pipe->connector = omap_connector_init(dev, pipe->output, + encoder); + if (!pipe->connector) + return -ENOMEM; - drm_connector_attach_encoder(connector, encoder); - pipe->connector = connector; + drm_connector_attach_encoder(pipe->connector, encoder); + } crtc = omap_crtc_init(dev, pipe, priv->planes[i]); if (IS_ERR(crtc)) @@ -350,10 +379,12 @@ static int omap_modeset_init(struct drm_device *dev) static void omap_modeset_enable_external_hpd(struct drm_device *ddev) { struct omap_drm_private *priv = ddev->dev_private; - int i; + unsigned int i; - for (i = 0; i < priv->num_pipes; i++) - omap_connector_enable_hpd(priv->pipes[i].connector); + for (i = 0; i < priv->num_pipes; i++) { + if (priv->pipes[i].connector) + omap_connector_enable_hpd(priv->pipes[i].connector); + } } /* @@ -362,10 +393,12 @@ static void omap_modeset_enable_external_hpd(struct drm_device *ddev) static void omap_modeset_disable_external_hpd(struct drm_device *ddev) { struct omap_drm_private *priv = ddev->dev_private; - int i; + unsigned int i; - for (i = 0; i < priv->num_pipes; i++) - omap_connector_disable_hpd(priv->pipes[i].connector); + for (i = 0; i < priv->num_pipes; i++) { + if (priv->pipes[i].connector) + omap_connector_disable_hpd(priv->pipes[i].connector); + } } /* |