aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c88
1 files changed, 61 insertions, 27 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index d2750f60f519..cdafd7ef1c32 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -12,6 +12,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_file.h>
@@ -134,9 +135,6 @@ static void omap_disconnect_pipelines(struct drm_device *ddev)
for (i = 0; i < priv->num_pipes; i++) {
struct omap_drm_pipeline *pipe = &priv->pipes[i];
- if (pipe->output->panel)
- drm_panel_detach(pipe->output->panel);
-
omapdss_device_disconnect(NULL, pipe->output);
omapdss_device_put(pipe->output);
@@ -209,11 +207,12 @@ static int omap_display_id(struct omap_dss_device *output)
struct device_node *node = NULL;
if (output->next) {
- struct omap_dss_device *display;
+ struct omap_dss_device *display = output;
+
+ while (display->next)
+ display = display->next;
- display = omapdss_display_get(output);
node = display->dev->of_node;
- omapdss_device_put(display);
} else if (output->bridge) {
struct drm_bridge *bridge = output->bridge;
@@ -221,8 +220,6 @@ static int omap_display_id(struct omap_dss_device *output)
bridge = drm_bridge_get_next_bridge(bridge);
node = bridge->of_node;
- } else if (output->panel) {
- node = output->panel->dev->of_node;
}
return node ? of_alias_get_id(node, "display") : -ENODEV;
@@ -297,9 +294,14 @@ static int omap_modeset_init(struct drm_device *dev)
if (pipe->output->bridge) {
ret = drm_bridge_attach(pipe->encoder,
- pipe->output->bridge, NULL);
- if (ret < 0)
+ pipe->output->bridge, NULL,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (ret < 0) {
+ dev_err(priv->dev,
+ "unable to attach bridge %pOF\n",
+ pipe->output->bridge->of_node);
return ret;
+ }
}
id = omap_display_id(pipe->output);
@@ -330,20 +332,28 @@ static int omap_modeset_init(struct drm_device *dev)
struct drm_encoder *encoder = pipe->encoder;
struct drm_crtc *crtc;
- if (!pipe->output->bridge) {
+ if (pipe->output->next) {
pipe->connector = omap_connector_init(dev, pipe->output,
encoder);
if (!pipe->connector)
return -ENOMEM;
+ } else {
+ pipe->connector = drm_bridge_connector_init(dev, encoder);
+ if (IS_ERR(pipe->connector)) {
+ dev_err(priv->dev,
+ "unable to create bridge connector for %s\n",
+ pipe->output->name);
+ return PTR_ERR(pipe->connector);
+ }
+ }
- drm_connector_attach_encoder(pipe->connector, encoder);
+ drm_connector_attach_encoder(pipe->connector, encoder);
- if (pipe->output->panel) {
- ret = drm_panel_attach(pipe->output->panel,
- pipe->connector);
- if (ret < 0)
- return ret;
- }
+ if (pipe->output->panel) {
+ ret = drm_panel_attach(pipe->output->panel,
+ pipe->connector);
+ if (ret < 0)
+ return ret;
}
crtc = omap_crtc_init(dev, pipe, priv->planes[i]);
@@ -382,6 +392,23 @@ static int omap_modeset_init(struct drm_device *dev)
return 0;
}
+static void omap_modeset_fini(struct drm_device *ddev)
+{
+ struct omap_drm_private *priv = ddev->dev_private;
+ unsigned int i;
+
+ omap_drm_irq_uninstall(ddev);
+
+ for (i = 0; i < priv->num_pipes; i++) {
+ struct omap_drm_pipeline *pipe = &priv->pipes[i];
+
+ if (pipe->output->panel)
+ drm_panel_detach(pipe->output->panel);
+ }
+
+ drm_mode_config_cleanup(ddev);
+}
+
/*
* Enable the HPD in external components if supported
*/
@@ -391,8 +418,13 @@ static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
unsigned int i;
for (i = 0; i < priv->num_pipes; i++) {
- if (priv->pipes[i].connector)
- omap_connector_enable_hpd(priv->pipes[i].connector);
+ struct drm_connector *connector = priv->pipes[i].connector;
+
+ if (!connector)
+ continue;
+
+ if (priv->pipes[i].output->bridge)
+ drm_bridge_connector_enable_hpd(connector);
}
}
@@ -405,8 +437,13 @@ static void omap_modeset_disable_external_hpd(struct drm_device *ddev)
unsigned int i;
for (i = 0; i < priv->num_pipes; i++) {
- if (priv->pipes[i].connector)
- omap_connector_disable_hpd(priv->pipes[i].connector);
+ struct drm_connector *connector = priv->pipes[i].connector;
+
+ if (!connector)
+ continue;
+
+ if (priv->pipes[i].output->bridge)
+ drm_bridge_connector_disable_hpd(connector);
}
}
@@ -629,8 +666,7 @@ err_cleanup_helpers:
omap_fbdev_fini(ddev);
err_cleanup_modeset:
- drm_mode_config_cleanup(ddev);
- omap_drm_irq_uninstall(ddev);
+ omap_modeset_fini(ddev);
err_gem_deinit:
omap_gem_deinit(ddev);
destroy_workqueue(priv->wq);
@@ -655,9 +691,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv)
drm_atomic_helper_shutdown(ddev);
- drm_mode_config_cleanup(ddev);
-
- omap_drm_irq_uninstall(ddev);
+ omap_modeset_fini(ddev);
omap_gem_deinit(ddev);
destroy_workqueue(priv->wq);