aboutsummaryrefslogtreecommitdiff
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.c121
1 files changed, 86 insertions, 35 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 2603d909f49..002b9721e85 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -86,6 +86,47 @@ static bool channel_used(struct drm_device *dev, enum omap_channel channel)
return false;
}
+static void omap_disconnect_dssdevs(void)
+{
+ struct omap_dss_device *dssdev = NULL;
+
+ for_each_dss_dev(dssdev)
+ dssdev->driver->disconnect(dssdev);
+}
+
+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
+ */
+ omap_disconnect_dssdevs();
+
+ return r;
+}
static int omap_modeset_init(struct drm_device *dev)
{
@@ -95,9 +136,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 +157,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);
@@ -493,20 +513,26 @@ static int dev_load(struct drm_device *dev, unsigned long flags)
static int dev_unload(struct drm_device *dev)
{
struct omap_drm_private *priv = dev->dev_private;
+ int i;
DBG("unload: dev=%p", dev);
drm_kms_helper_poll_fini(dev);
- drm_vblank_cleanup(dev);
- omap_drm_irq_uninstall(dev);
omap_fbdev_free(dev);
+
+ /* flush crtcs so the fbs get released */
+ for (i = 0; i < priv->num_crtcs; i++)
+ omap_crtc_flush(priv->crtcs[i]);
+
omap_modeset_free(dev);
omap_gem_deinit(dev);
- flush_workqueue(priv->wq);
destroy_workqueue(priv->wq);
+ drm_vblank_cleanup(dev);
+ omap_drm_irq_uninstall(dev);
+
kfree(dev->dev_private);
dev->dev_private = NULL;
@@ -562,9 +588,7 @@ static void dev_lastclose(struct drm_device *dev)
}
}
- drm_modeset_lock_all(dev);
- ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
- drm_modeset_unlock_all(dev);
+ ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
if (ret)
DBG("failed to restore crtc mode");
}
@@ -620,7 +644,6 @@ static struct drm_driver omap_drm_driver = {
.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
.gem_prime_export = omap_gem_prime_export,
.gem_prime_import = omap_gem_prime_import,
- .gem_init_object = omap_gem_init_object,
.gem_free_object = omap_gem_free_object,
.gem_vm_ops = &omap_gem_vm_ops,
.dumb_create = omap_gem_dumb_create,
@@ -656,9 +679,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);
}
@@ -666,9 +699,12 @@ static int pdev_probe(struct platform_device *device)
static int pdev_remove(struct platform_device *device)
{
DBG("");
- drm_platform_exit(&omap_drm_driver, device);
- platform_driver_unregister(&omap_dmm_driver);
+ drm_put_dev(platform_get_drvdata(device));
+
+ omap_disconnect_dssdevs();
+ omap_crtc_pre_uninit();
+
return 0;
}
@@ -695,18 +731,33 @@ static struct platform_driver pdev = {
static int __init omap_drm_init(void)
{
+ int r;
+
DBG("init");
- if (platform_driver_register(&omap_dmm_driver)) {
- /* we can continue on without DMM.. so not fatal */
- dev_err(NULL, "DMM registration failed\n");
+
+ r = platform_driver_register(&omap_dmm_driver);
+ if (r) {
+ pr_err("DMM driver registration failed\n");
+ return r;
+ }
+
+ r = platform_driver_register(&pdev);
+ if (r) {
+ pr_err("omapdrm driver registration failed\n");
+ platform_driver_unregister(&omap_dmm_driver);
+ return r;
}
- return platform_driver_register(&pdev);
+
+ return 0;
}
static void __exit omap_drm_fini(void)
{
DBG("fini");
+
platform_driver_unregister(&pdev);
+
+ platform_driver_unregister(&omap_dmm_driver);
}
/* need late_initcall() so we load after dss_driver's are loaded */