Commit dee13f12 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'omapdrm-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux into drm-next

omapdrm patches for 3.14

* tag 'omapdrm-3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux:
  drm/omap: Enable DT support for DMM
  drm/omap: fix: change dev_unload order
  drm/omap: fix: disable encoder before destroying it
  drm/omap: fix: disconnect devices when omapdrm module is removed
  drm/omap: fix: Defer probe if an omapdss device requests for it at connect
  drm/omap: fix (un)registering irqs inside an irq handler

Conflicts:
	drivers/gpu/drm/omapdrm/omap_drv.c
parents 5a0abe30 3d232346
...@@ -411,7 +411,7 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) ...@@ -411,7 +411,7 @@ static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
struct drm_crtc *crtc = &omap_crtc->base; struct drm_crtc *crtc = &omap_crtc->base;
DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus); DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
/* avoid getting in a flood, unregister the irq until next vblank */ /* avoid getting in a flood, unregister the irq until next vblank */
omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); __omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
} }
static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus) 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,13 +421,13 @@ static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
struct drm_crtc *crtc = &omap_crtc->base; struct drm_crtc *crtc = &omap_crtc->base;
if (!omap_crtc->error_irq.registered) if (!omap_crtc->error_irq.registered)
omap_irq_register(crtc->dev, &omap_crtc->error_irq); __omap_irq_register(crtc->dev, &omap_crtc->error_irq);
if (!dispc_mgr_go_busy(omap_crtc->channel)) { if (!dispc_mgr_go_busy(omap_crtc->channel)) {
struct omap_drm_private *priv = struct omap_drm_private *priv =
crtc->dev->dev_private; crtc->dev->dev_private;
DBG("%s: apply done", omap_crtc->name); DBG("%s: apply done", omap_crtc->name);
omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq); __omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
queue_work(priv->wq, &omap_crtc->apply_work); queue_work(priv->wq, &omap_crtc->apply_work);
} }
} }
...@@ -623,6 +623,11 @@ void omap_crtc_pre_init(void) ...@@ -623,6 +623,11 @@ void omap_crtc_pre_init(void)
dss_install_mgr_ops(&mgr_ops); dss_install_mgr_ops(&mgr_ops);
} }
void omap_crtc_pre_uninit(void)
{
dss_uninstall_mgr_ops();
}
/* initialize crtc */ /* initialize crtc */
struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_crtc *omap_crtc_init(struct drm_device *dev,
struct drm_plane *plane, enum omap_channel channel, int id) struct drm_plane *plane, enum omap_channel channel, int id)
......
...@@ -969,12 +969,21 @@ static const struct dev_pm_ops omap_dmm_pm_ops = { ...@@ -969,12 +969,21 @@ static const struct dev_pm_ops omap_dmm_pm_ops = {
}; };
#endif #endif
#if defined(CONFIG_OF)
static const struct of_device_id dmm_of_match[] = {
{ .compatible = "ti,omap4-dmm", },
{ .compatible = "ti,omap5-dmm", },
{},
};
#endif
struct platform_driver omap_dmm_driver = { struct platform_driver omap_dmm_driver = {
.probe = omap_dmm_probe, .probe = omap_dmm_probe,
.remove = omap_dmm_remove, .remove = omap_dmm_remove,
.driver = { .driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = DMM_DRIVER_NAME, .name = DMM_DRIVER_NAME,
.of_match_table = of_match_ptr(dmm_of_match),
#ifdef CONFIG_PM #ifdef CONFIG_PM
.pm = &omap_dmm_pm_ops, .pm = &omap_dmm_pm_ops,
#endif #endif
......
...@@ -86,6 +86,47 @@ static bool channel_used(struct drm_device *dev, enum omap_channel channel) ...@@ -86,6 +86,47 @@ static bool channel_used(struct drm_device *dev, enum omap_channel channel)
return false; 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) static int omap_modeset_init(struct drm_device *dev)
{ {
...@@ -95,9 +136,6 @@ 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_mgrs = dss_feat_get_num_mgrs();
int num_crtcs; int num_crtcs;
int i, id = 0; int i, id = 0;
int r;
omap_crtc_pre_init();
drm_mode_config_init(dev); drm_mode_config_init(dev);
...@@ -119,26 +157,8 @@ static int omap_modeset_init(struct drm_device *dev) ...@@ -119,26 +157,8 @@ static int omap_modeset_init(struct drm_device *dev)
enum omap_channel channel; enum omap_channel channel;
struct omap_overlay_manager *mgr; struct omap_overlay_manager *mgr;
if (!dssdev->driver) { if (!omapdss_device_is_connected(dssdev))
dev_warn(dev->dev, "%s has no driver.. skipping it\n",
dssdev->name);
continue; 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);
continue;
}
encoder = omap_encoder_init(dev, dssdev); encoder = omap_encoder_init(dev, dssdev);
...@@ -497,16 +517,16 @@ static int dev_unload(struct drm_device *dev) ...@@ -497,16 +517,16 @@ static int dev_unload(struct drm_device *dev)
DBG("unload: dev=%p", dev); DBG("unload: dev=%p", dev);
drm_kms_helper_poll_fini(dev); drm_kms_helper_poll_fini(dev);
drm_vblank_cleanup(dev);
omap_drm_irq_uninstall(dev);
omap_fbdev_free(dev); omap_fbdev_free(dev);
omap_modeset_free(dev); omap_modeset_free(dev);
omap_gem_deinit(dev); omap_gem_deinit(dev);
flush_workqueue(priv->wq);
destroy_workqueue(priv->wq); destroy_workqueue(priv->wq);
drm_vblank_cleanup(dev);
omap_drm_irq_uninstall(dev);
kfree(dev->dev_private); kfree(dev->dev_private);
dev->dev_private = NULL; dev->dev_private = NULL;
...@@ -655,9 +675,19 @@ static void pdev_shutdown(struct platform_device *device) ...@@ -655,9 +675,19 @@ static void pdev_shutdown(struct platform_device *device)
static int pdev_probe(struct platform_device *device) static int pdev_probe(struct platform_device *device)
{ {
int r;
if (omapdss_is_initialized() == false) if (omapdss_is_initialized() == false)
return -EPROBE_DEFER; return -EPROBE_DEFER;
omap_crtc_pre_init();
r = omap_connect_dssdevs();
if (r) {
omap_crtc_pre_uninit();
return r;
}
DBG("%s", device->name); DBG("%s", device->name);
return drm_platform_init(&omap_drm_driver, device); return drm_platform_init(&omap_drm_driver, device);
} }
...@@ -666,8 +696,10 @@ static int pdev_remove(struct platform_device *device) ...@@ -666,8 +696,10 @@ static int pdev_remove(struct platform_device *device)
{ {
DBG(""); DBG("");
drm_put_dev(platform_get_drvdata(device)); omap_disconnect_dssdevs();
omap_crtc_pre_uninit();
drm_put_dev(platform_get_drvdata(device));
return 0; return 0;
} }
......
...@@ -145,6 +145,8 @@ irqreturn_t omap_irq_handler(int irq, void *arg); ...@@ -145,6 +145,8 @@ irqreturn_t omap_irq_handler(int irq, void *arg);
void omap_irq_preinstall(struct drm_device *dev); void omap_irq_preinstall(struct drm_device *dev);
int omap_irq_postinstall(struct drm_device *dev); int omap_irq_postinstall(struct drm_device *dev);
void omap_irq_uninstall(struct drm_device *dev); void omap_irq_uninstall(struct drm_device *dev);
void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
int omap_drm_irq_uninstall(struct drm_device *dev); int omap_drm_irq_uninstall(struct drm_device *dev);
...@@ -158,6 +160,7 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); ...@@ -158,6 +160,7 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
int omap_crtc_apply(struct drm_crtc *crtc, int omap_crtc_apply(struct drm_crtc *crtc,
struct omap_drm_apply *apply); struct omap_drm_apply *apply);
void omap_crtc_pre_init(void); void omap_crtc_pre_init(void);
void omap_crtc_pre_uninit(void);
struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_crtc *omap_crtc_init(struct drm_device *dev,
struct drm_plane *plane, enum omap_channel channel, int id); struct drm_plane *plane, enum omap_channel channel, int id);
......
...@@ -51,6 +51,9 @@ struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder) ...@@ -51,6 +51,9 @@ struct omap_dss_device *omap_encoder_get_dssdev(struct drm_encoder *encoder)
static void omap_encoder_destroy(struct drm_encoder *encoder) static void omap_encoder_destroy(struct drm_encoder *encoder)
{ {
struct omap_encoder *omap_encoder = to_omap_encoder(encoder); struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
omap_encoder_set_enabled(encoder, false);
drm_encoder_cleanup(encoder); drm_encoder_cleanup(encoder);
kfree(omap_encoder); kfree(omap_encoder);
} }
......
...@@ -45,12 +45,11 @@ static void omap_irq_update(struct drm_device *dev) ...@@ -45,12 +45,11 @@ static void omap_irq_update(struct drm_device *dev)
dispc_read_irqenable(); /* flush posted write */ dispc_read_irqenable(); /* flush posted write */
} }
void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) void __omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
{ {
struct omap_drm_private *priv = dev->dev_private; struct omap_drm_private *priv = dev->dev_private;
unsigned long flags; unsigned long flags;
dispc_runtime_get();
spin_lock_irqsave(&list_lock, flags); spin_lock_irqsave(&list_lock, flags);
if (!WARN_ON(irq->registered)) { if (!WARN_ON(irq->registered)) {
...@@ -60,14 +59,21 @@ void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) ...@@ -60,14 +59,21 @@ void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
} }
spin_unlock_irqrestore(&list_lock, flags); spin_unlock_irqrestore(&list_lock, flags);
}
void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
{
dispc_runtime_get();
__omap_irq_register(dev, irq);
dispc_runtime_put(); dispc_runtime_put();
} }
void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) void __omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
{ {
unsigned long flags; unsigned long flags;
dispc_runtime_get();
spin_lock_irqsave(&list_lock, flags); spin_lock_irqsave(&list_lock, flags);
if (!WARN_ON(!irq->registered)) { if (!WARN_ON(!irq->registered)) {
...@@ -77,6 +83,14 @@ void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) ...@@ -77,6 +83,14 @@ void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
} }
spin_unlock_irqrestore(&list_lock, flags); spin_unlock_irqrestore(&list_lock, flags);
}
void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
{
dispc_runtime_get();
__omap_irq_unregister(dev, irq);
dispc_runtime_put(); dispc_runtime_put();
} }
......
...@@ -3691,7 +3691,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev) ...@@ -3691,7 +3691,6 @@ static int __init omap_dispchw_probe(struct platform_device *pdev)
} }
pm_runtime_enable(&pdev->dev); pm_runtime_enable(&pdev->dev);
pm_runtime_irq_safe(&pdev->dev);
r = dispc_runtime_get(); r = dispc_runtime_get();
if (r) if (r)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment