diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm')
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 11 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 84 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_encoder.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_irq.c | 22 |
6 files changed, 99 insertions, 33 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 0fd2eb139f6e..4313bb0a49a6 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c | |||
| @@ -411,7 +411,7 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | |||
| 411 | struct drm_crtc *crtc = &omap_crtc->base; | 411 | struct drm_crtc *crtc = &omap_crtc->base; |
| 412 | DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus); | 412 | DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus); |
| 413 | /* avoid getting in a flood, unregister the irq until next vblank */ | 413 | /* avoid getting in a flood, unregister the irq until next vblank */ |
| 414 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | 414 | __omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | 417 | static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus) |
| @@ -421,13 +421,13 @@ static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | |||
| 421 | struct drm_crtc *crtc = &omap_crtc->base; | 421 | struct drm_crtc *crtc = &omap_crtc->base; |
| 422 | 422 | ||
| 423 | if (!omap_crtc->error_irq.registered) | 423 | if (!omap_crtc->error_irq.registered) |
| 424 | omap_irq_register(crtc->dev, &omap_crtc->error_irq); | 424 | __omap_irq_register(crtc->dev, &omap_crtc->error_irq); |
| 425 | 425 | ||
| 426 | if (!dispc_mgr_go_busy(omap_crtc->channel)) { | 426 | if (!dispc_mgr_go_busy(omap_crtc->channel)) { |
| 427 | struct omap_drm_private *priv = | 427 | struct omap_drm_private *priv = |
| 428 | crtc->dev->dev_private; | 428 | crtc->dev->dev_private; |
| 429 | DBG("%s: apply done", omap_crtc->name); | 429 | DBG("%s: apply done", omap_crtc->name); |
| 430 | omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq); | 430 | __omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq); |
| 431 | queue_work(priv->wq, &omap_crtc->apply_work); | 431 | queue_work(priv->wq, &omap_crtc->apply_work); |
| 432 | } | 432 | } |
| 433 | } | 433 | } |
| @@ -623,6 +623,11 @@ void omap_crtc_pre_init(void) | |||
| 623 | dss_install_mgr_ops(&mgr_ops); | 623 | dss_install_mgr_ops(&mgr_ops); |
| 624 | } | 624 | } |
| 625 | 625 | ||
| 626 | void omap_crtc_pre_uninit(void) | ||
| 627 | { | ||
| 628 | dss_uninstall_mgr_ops(); | ||
| 629 | } | ||
| 630 | |||
| 626 | /* initialize crtc */ | 631 | /* initialize crtc */ |
| 627 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, | 632 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, |
| 628 | struct drm_plane *plane, enum omap_channel channel, int id) | 633 | struct drm_plane *plane, enum omap_channel channel, int id) |
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c index 701c4c10e08b..f926b4caf449 100644 --- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c +++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c | |||
| @@ -969,12 +969,21 @@ static const struct dev_pm_ops omap_dmm_pm_ops = { | |||
| 969 | }; | 969 | }; |
| 970 | #endif | 970 | #endif |
| 971 | 971 | ||
| 972 | #if defined(CONFIG_OF) | ||
| 973 | static const struct of_device_id dmm_of_match[] = { | ||
| 974 | { .compatible = "ti,omap4-dmm", }, | ||
| 975 | { .compatible = "ti,omap5-dmm", }, | ||
| 976 | {}, | ||
| 977 | }; | ||
| 978 | #endif | ||
| 979 | |||
| 972 | struct platform_driver omap_dmm_driver = { | 980 | struct platform_driver omap_dmm_driver = { |
| 973 | .probe = omap_dmm_probe, | 981 | .probe = omap_dmm_probe, |
| 974 | .remove = omap_dmm_remove, | 982 | .remove = omap_dmm_remove, |
| 975 | .driver = { | 983 | .driver = { |
| 976 | .owner = THIS_MODULE, | 984 | .owner = THIS_MODULE, |
| 977 | .name = DMM_DRIVER_NAME, | 985 | .name = DMM_DRIVER_NAME, |
| 986 | .of_match_table = of_match_ptr(dmm_of_match), | ||
| 978 | #ifdef CONFIG_PM | 987 | #ifdef CONFIG_PM |
| 979 | .pm = &omap_dmm_pm_ops, | 988 | .pm = &omap_dmm_pm_ops, |
| 980 | #endif | 989 | #endif |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 13f294aeaefd..bf39fcc49e0f 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) | |||
| 86 | 86 | ||
| 87 | return false; | 87 | return false; |
| 88 | } | 88 | } |
| 89 | static void omap_disconnect_dssdevs(void) | ||
| 90 | { | ||
| 91 | struct omap_dss_device *dssdev = NULL; | ||
| 92 | |||
| 93 | for_each_dss_dev(dssdev) | ||
| 94 | dssdev->driver->disconnect(dssdev); | ||
| 95 | } | ||
| 96 | |||
| 97 | static int omap_connect_dssdevs(void) | ||
| 98 | { | ||
| 99 | int r; | ||
| 100 | struct omap_dss_device *dssdev = NULL; | ||
| 101 | bool no_displays = true; | ||
| 102 | |||
| 103 | for_each_dss_dev(dssdev) { | ||
| 104 | r = dssdev->driver->connect(dssdev); | ||
| 105 | if (r == -EPROBE_DEFER) { | ||
| 106 | omap_dss_put_device(dssdev); | ||
| 107 | goto cleanup; | ||
| 108 | } else if (r) { | ||
| 109 | dev_warn(dssdev->dev, "could not connect display: %s\n", | ||
| 110 | dssdev->name); | ||
| 111 | } else { | ||
| 112 | no_displays = false; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 116 | if (no_displays) | ||
| 117 | return -EPROBE_DEFER; | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | |||
| 121 | cleanup: | ||
| 122 | /* | ||
| 123 | * if we are deferring probe, we disconnect the devices we previously | ||
| 124 | * connected | ||
| 125 | */ | ||
| 126 | omap_disconnect_dssdevs(); | ||
| 127 | |||
| 128 | return r; | ||
| 129 | } | ||
| 89 | 130 | ||
| 90 | static int omap_modeset_init(struct drm_device *dev) | 131 | static int omap_modeset_init(struct drm_device *dev) |
| 91 | { | 132 | { |
| @@ -95,9 +136,6 @@ static int omap_modeset_init(struct drm_device *dev) | |||
| 95 | int num_mgrs = dss_feat_get_num_mgrs(); | 136 | int num_mgrs = dss_feat_get_num_mgrs(); |
| 96 | int num_crtcs; | 137 | int num_crtcs; |
| 97 | int i, id = 0; | 138 | int i, id = 0; |
| 98 | int r; | ||
| 99 | |||
| 100 | omap_crtc_pre_init(); | ||
| 101 | 139 | ||
| 102 | drm_mode_config_init(dev); | 140 | drm_mode_config_init(dev); |
| 103 | 141 | ||
| @@ -119,26 +157,8 @@ static int omap_modeset_init(struct drm_device *dev) | |||
| 119 | enum omap_channel channel; | 157 | enum omap_channel channel; |
| 120 | struct omap_overlay_manager *mgr; | 158 | struct omap_overlay_manager *mgr; |
| 121 | 159 | ||
| 122 | if (!dssdev->driver) { | 160 | if (!omapdss_device_is_connected(dssdev)) |
| 123 | dev_warn(dev->dev, "%s has no driver.. skipping it\n", | ||
| 124 | dssdev->name); | ||
| 125 | continue; | 161 | continue; |
| 126 | } | ||
| 127 | |||
| 128 | if (!(dssdev->driver->get_timings || | ||
| 129 | dssdev->driver->read_edid)) { | ||
| 130 | dev_warn(dev->dev, "%s driver does not support " | ||
| 131 | "get_timings or read_edid.. skipping it!\n", | ||
| 132 | dssdev->name); | ||
| 133 | continue; | ||
| 134 | } | ||
| 135 | |||
| 136 | r = dssdev->driver->connect(dssdev); | ||
| 137 | if (r) { | ||
| 138 | dev_err(dev->dev, "could not connect display: %s\n", | ||
| 139 | dssdev->name); | ||
| 140 | continue; | ||
| 141 | } | ||
| 142 | 162 | ||
| 143 | encoder = omap_encoder_init(dev, dssdev); | 163 | encoder = omap_encoder_init(dev, dssdev); |
| 144 | 164 | ||
| @@ -497,16 +517,16 @@ static int dev_unload(struct drm_device *dev) | |||
| 497 | DBG("unload: dev=%p", dev); | 517 | DBG("unload: dev=%p", dev); |
| 498 | 518 | ||
| 499 | drm_kms_helper_poll_fini(dev); | 519 | drm_kms_helper_poll_fini(dev); |
| 500 | drm_vblank_cleanup(dev); | ||
| 501 | omap_drm_irq_uninstall(dev); | ||
| 502 | 520 | ||
| 503 | omap_fbdev_free(dev); | 521 | omap_fbdev_free(dev); |
| 504 | omap_modeset_free(dev); | 522 | omap_modeset_free(dev); |
| 505 | omap_gem_deinit(dev); | 523 | omap_gem_deinit(dev); |
| 506 | 524 | ||
| 507 | flush_workqueue(priv->wq); | ||
| 508 | destroy_workqueue(priv->wq); | 525 | destroy_workqueue(priv->wq); |
| 509 | 526 | ||
| 527 | drm_vblank_cleanup(dev); | ||
| 528 | omap_drm_irq_uninstall(dev); | ||
| 529 | |||
| 510 | kfree(dev->dev_private); | 530 | kfree(dev->dev_private); |
| 511 | dev->dev_private = NULL; | 531 | dev->dev_private = NULL; |
| 512 | 532 | ||
| @@ -655,9 +675,19 @@ static void pdev_shutdown(struct platform_device *device) | |||
| 655 | 675 | ||
| 656 | static int pdev_probe(struct platform_device *device) | 676 | static int pdev_probe(struct platform_device *device) |
| 657 | { | 677 | { |
| 678 | int r; | ||
| 679 | |||
| 658 | if (omapdss_is_initialized() == false) | 680 | if (omapdss_is_initialized() == false) |
| 659 | return -EPROBE_DEFER; | 681 | return -EPROBE_DEFER; |
| 660 | 682 | ||
| 683 | omap_crtc_pre_init(); | ||
| 684 | |||
| 685 | r = omap_connect_dssdevs(); | ||
| 686 | if (r) { | ||
| 687 | omap_crtc_pre_uninit(); | ||
| 688 | return r; | ||
| 689 | } | ||
| 690 | |||
| 661 | DBG("%s", device->name); | 691 | DBG("%s", device->name); |
| 662 | return drm_platform_init(&omap_drm_driver, device); | 692 | return drm_platform_init(&omap_drm_driver, device); |
| 663 | } | 693 | } |
| @@ -666,8 +696,10 @@ static int pdev_remove(struct platform_device *device) | |||
| 666 | { | 696 | { |
| 667 | DBG(""); | 697 | DBG(""); |
| 668 | 698 | ||
| 669 | drm_put_dev(platform_get_drvdata(device)); | 699 | omap_disconnect_dssdevs(); |
| 700 | omap_crtc_pre_uninit(); | ||
| 670 | 701 | ||
| 702 | drm_put_dev(platform_get_drvdata(device)); | ||
| 671 | return 0; | 703 | return 0; |
| 672 | } | 704 | } |
| 673 | 705 | ||
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index c88fea32dbf6..428b2981fd68 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
| @@ -145,6 +145,8 @@ irqreturn_t omap_irq_handler(int irq, void *arg); | |||
| 145 | void omap_irq_preinstall(struct drm_device *dev); | 145 | void omap_irq_preinstall(struct drm_device *dev); |
| 146 | int omap_irq_postinstall(struct drm_device *dev); | 146 | int omap_irq_postinstall(struct drm_device *dev); |
| 147 | void omap_irq_uninstall(struct drm_device *dev); | 147 | void omap_irq_uninstall(struct drm_device *dev); |
| 148 | void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); | ||
| 149 | void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); | ||
| 148 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); | 150 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); |
| 149 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); | 151 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); |
| 150 | int omap_drm_irq_uninstall(struct drm_device *dev); | 152 | int omap_drm_irq_uninstall(struct drm_device *dev); |
| @@ -158,6 +160,7 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); | |||
| 158 | int omap_crtc_apply(struct drm_crtc *crtc, | 160 | int omap_crtc_apply(struct drm_crtc *crtc, |
| 159 | struct omap_drm_apply *apply); | 161 | struct omap_drm_apply *apply); |
| 160 | void omap_crtc_pre_init(void); | 162 | void omap_crtc_pre_init(void); |
| 163 | void omap_crtc_pre_uninit(void); | ||
| 161 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, | 164 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, |
| 162 | struct drm_plane *plane, enum omap_channel channel, int id); | 165 | struct drm_plane *plane, enum omap_channel channel, int id); |
| 163 | 166 | ||
diff --git a/drivers/gpu/drm/omapdrm/omap_encoder.c b/drivers/gpu/drm/omapdrm/omap_encoder.c index 6a12e899235b..5290a88c681d 100644 --- a/drivers/gpu/drm/omapdrm/omap_encoder.c +++ b/drivers/gpu/drm/omapdrm/omap_encoder.c | |||
| @@ -51,6 +51,9 @@ struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder) | |||
| 51 | static void omap_encoder_destroy(struct drm_encoder *encoder) | 51 | static void omap_encoder_destroy(struct drm_encoder *encoder) |
| 52 | { | 52 | { |
| 53 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 53 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
| 54 | |||
| 55 | omap_encoder_set_enabled(encoder, false); | ||
| 56 | |||
| 54 | drm_encoder_cleanup(encoder); | 57 | drm_encoder_cleanup(encoder); |
| 55 | kfree(omap_encoder); | 58 | kfree(omap_encoder); |
| 56 | } | 59 | } |
diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c index 0e5336e5a791..f035d2bceae7 100644 --- a/drivers/gpu/drm/omapdrm/omap_irq.c +++ b/drivers/gpu/drm/omapdrm/omap_irq.c | |||
| @@ -45,12 +45,11 @@ static void omap_irq_update(struct drm_device *dev) | |||
| 45 | dispc_read_irqenable(); /* flush posted write */ | 45 | dispc_read_irqenable(); /* flush posted write */ |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) | 48 | void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) |
| 49 | { | 49 | { |
| 50 | struct omap_drm_private *priv = dev->dev_private; | 50 | struct omap_drm_private *priv = dev->dev_private; |
| 51 | unsigned long flags; | 51 | unsigned long flags; |
| 52 | 52 | ||
| 53 | dispc_runtime_get(); | ||
| 54 | spin_lock_irqsave(&list_lock, flags); | 53 | spin_lock_irqsave(&list_lock, flags); |
| 55 | 54 | ||
| 56 | if (!WARN_ON(irq->registered)) { | 55 | if (!WARN_ON(irq->registered)) { |
| @@ -60,14 +59,21 @@ void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) | |||
| 60 | } | 59 | } |
| 61 | 60 | ||
| 62 | spin_unlock_irqrestore(&list_lock, flags); | 61 | spin_unlock_irqrestore(&list_lock, flags); |
| 62 | } | ||
| 63 | |||
| 64 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) | ||
| 65 | { | ||
| 66 | dispc_runtime_get(); | ||
| 67 | |||
| 68 | __omap_irq_register(dev, irq); | ||
| 69 | |||
| 63 | dispc_runtime_put(); | 70 | dispc_runtime_put(); |
| 64 | } | 71 | } |
| 65 | 72 | ||
| 66 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) | 73 | void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) |
| 67 | { | 74 | { |
| 68 | unsigned long flags; | 75 | unsigned long flags; |
| 69 | 76 | ||
| 70 | dispc_runtime_get(); | ||
| 71 | spin_lock_irqsave(&list_lock, flags); | 77 | spin_lock_irqsave(&list_lock, flags); |
| 72 | 78 | ||
| 73 | if (!WARN_ON(!irq->registered)) { | 79 | if (!WARN_ON(!irq->registered)) { |
| @@ -77,6 +83,14 @@ void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) | |||
| 77 | } | 83 | } |
| 78 | 84 | ||
| 79 | spin_unlock_irqrestore(&list_lock, flags); | 85 | spin_unlock_irqrestore(&list_lock, flags); |
| 86 | } | ||
| 87 | |||
| 88 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) | ||
| 89 | { | ||
| 90 | dispc_runtime_get(); | ||
| 91 | |||
| 92 | __omap_irq_unregister(dev, irq); | ||
| 93 | |||
| 80 | dispc_runtime_put(); | 94 | dispc_runtime_put(); |
| 81 | } | 95 | } |
| 82 | 96 | ||
