From 222025e42d7f77133b8c3a2355d20a6004096c4b Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 11 Jan 2015 00:02:07 +0200 Subject: drm: omapdrm: Fix indentation of structure and array initializers Indenting by one tab is enough. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/omapdrm/omap_drv.c | 106 ++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 53 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 8241ed9b353c..642748cb7a4e 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -610,55 +610,55 @@ static const struct vm_operations_struct omap_gem_vm_ops = { }; static const struct file_operations omapdriver_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .unlocked_ioctl = drm_ioctl, - .release = drm_release, - .mmap = omap_gem_mmap, - .poll = drm_poll, - .read = drm_read, - .llseek = noop_llseek, + .owner = THIS_MODULE, + .open = drm_open, + .unlocked_ioctl = drm_ioctl, + .release = drm_release, + .mmap = omap_gem_mmap, + .poll = drm_poll, + .read = drm_read, + .llseek = noop_llseek, }; static struct drm_driver omap_drm_driver = { - .driver_features = - DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, - .load = dev_load, - .unload = dev_unload, - .open = dev_open, - .lastclose = dev_lastclose, - .preclose = dev_preclose, - .postclose = dev_postclose, - .set_busid = drm_platform_set_busid, - .get_vblank_counter = drm_vblank_count, - .enable_vblank = omap_irq_enable_vblank, - .disable_vblank = omap_irq_disable_vblank, - .irq_preinstall = omap_irq_preinstall, - .irq_postinstall = omap_irq_postinstall, - .irq_uninstall = omap_irq_uninstall, - .irq_handler = omap_irq_handler, + .driver_features = DRIVER_HAVE_IRQ | DRIVER_MODESET | DRIVER_GEM + | DRIVER_PRIME, + .load = dev_load, + .unload = dev_unload, + .open = dev_open, + .lastclose = dev_lastclose, + .preclose = dev_preclose, + .postclose = dev_postclose, + .set_busid = drm_platform_set_busid, + .get_vblank_counter = drm_vblank_count, + .enable_vblank = omap_irq_enable_vblank, + .disable_vblank = omap_irq_disable_vblank, + .irq_preinstall = omap_irq_preinstall, + .irq_postinstall = omap_irq_postinstall, + .irq_uninstall = omap_irq_uninstall, + .irq_handler = omap_irq_handler, #ifdef CONFIG_DEBUG_FS - .debugfs_init = omap_debugfs_init, - .debugfs_cleanup = omap_debugfs_cleanup, + .debugfs_init = omap_debugfs_init, + .debugfs_cleanup = omap_debugfs_cleanup, #endif - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .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_free_object = omap_gem_free_object, - .gem_vm_ops = &omap_gem_vm_ops, - .dumb_create = omap_gem_dumb_create, - .dumb_map_offset = omap_gem_dumb_map_offset, - .dumb_destroy = drm_gem_dumb_destroy, - .ioctls = ioctls, - .num_ioctls = DRM_OMAP_NUM_IOCTLS, - .fops = &omapdriver_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .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_free_object = omap_gem_free_object, + .gem_vm_ops = &omap_gem_vm_ops, + .dumb_create = omap_gem_dumb_create, + .dumb_map_offset = omap_gem_dumb_map_offset, + .dumb_destroy = drm_gem_dumb_destroy, + .ioctls = ioctls, + .num_ioctls = DRM_OMAP_NUM_IOCTLS, + .fops = &omapdriver_fops, + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + .patchlevel = DRIVER_PATCHLEVEL, }; static int pdev_suspend(struct platform_device *pDevice, pm_message_t state) @@ -716,17 +716,17 @@ static const struct dev_pm_ops omapdrm_pm_ops = { #endif static struct platform_driver pdev = { - .driver = { - .name = DRIVER_NAME, + .driver = { + .name = DRIVER_NAME, #ifdef CONFIG_PM - .pm = &omapdrm_pm_ops, + .pm = &omapdrm_pm_ops, #endif - }, - .probe = pdev_probe, - .remove = pdev_remove, - .suspend = pdev_suspend, - .resume = pdev_resume, - .shutdown = pdev_shutdown, + }, + .probe = pdev_probe, + .remove = pdev_remove, + .suspend = pdev_suspend, + .resume = pdev_resume, + .shutdown = pdev_shutdown, }; static int __init omap_drm_init(void) -- cgit From fb9a35f89fac2ca97597ce212439d2997f2caf7e Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 11 Jan 2015 16:30:44 +0200 Subject: drm: omapdrm: Refactor CRTC creation code Create a omap_modeset_create_crtc() function to avoid duplicating plane and CRTC creation code. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/omapdrm/omap_drv.c | 76 +++++++++++++++++++++--------------- drivers/gpu/drm/omapdrm/omap_plane.c | 2 +- 2 files changed, 45 insertions(+), 33 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 642748cb7a4e..021855605a1f 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -128,6 +128,29 @@ cleanup: return r; } +static int omap_modeset_create_crtc(struct drm_device *dev, int id, + enum omap_channel channel) +{ + struct omap_drm_private *priv = dev->dev_private; + struct drm_plane *plane; + struct drm_crtc *crtc; + + plane = omap_plane_init(dev, id, true); + if (IS_ERR(plane)) + return PTR_ERR(plane); + + crtc = omap_crtc_init(dev, plane, channel, id); + + BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); + priv->crtcs[id] = crtc; + priv->num_crtcs++; + + priv->planes[id] = plane; + priv->num_planes++; + + return 0; +} + static int omap_modeset_init(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; @@ -136,6 +159,7 @@ 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 ret; drm_mode_config_init(dev); @@ -209,18 +233,13 @@ static int omap_modeset_init(struct drm_device *dev) * allocated crtc, we create a new crtc for it */ if (!channel_used(dev, channel)) { - struct drm_plane *plane; - struct drm_crtc *crtc; - - plane = omap_plane_init(dev, id, true); - crtc = omap_crtc_init(dev, plane, channel, id); - - BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); - priv->crtcs[id] = crtc; - priv->num_crtcs++; - - priv->planes[id] = plane; - priv->num_planes++; + ret = omap_modeset_create_crtc(dev, id, channel); + if (ret < 0) { + dev_err(dev->dev, + "could not create CRTC (channel %u)\n", + channel); + return ret; + } id++; } @@ -234,26 +253,8 @@ static int omap_modeset_init(struct drm_device *dev) /* find a free manager for this crtc */ for (i = 0; i < num_mgrs; i++) { - if (!channel_used(dev, i)) { - struct drm_plane *plane; - struct drm_crtc *crtc; - - plane = omap_plane_init(dev, id, true); - crtc = omap_crtc_init(dev, plane, i, id); - - BUG_ON(priv->num_crtcs >= - ARRAY_SIZE(priv->crtcs)); - - priv->crtcs[id] = crtc; - priv->num_crtcs++; - - priv->planes[id] = plane; - priv->num_planes++; - + if (!channel_used(dev, i)) break; - } else { - continue; - } } if (i == num_mgrs) { @@ -261,13 +262,24 @@ static int omap_modeset_init(struct drm_device *dev) dev_err(dev->dev, "no managers left for crtc\n"); return -ENOMEM; } + + ret = omap_modeset_create_crtc(dev, id, i); + if (ret < 0) { + dev_err(dev->dev, + "could not create CRTC (channel %u)\n", i); + return ret; + } } /* * Create normal planes for the remaining overlays: */ for (; id < num_ovls; id++) { - struct drm_plane *plane = omap_plane_init(dev, id, false); + struct drm_plane *plane; + + plane = omap_plane_init(dev, id, false); + if (IS_ERR(plane)) + return PTR_ERR(plane); BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); priv->planes[priv->num_planes++] = plane; diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index a418fa7e5d0e..056ded8280f8 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -393,7 +393,7 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); if (!omap_plane) - return NULL; + return ERR_PTR(-ENOMEM); drm_flip_work_init(&omap_plane->unpin_work, "unpin", unpin_worker); -- cgit From ef6b0e0275387f79e6ad848d61dfcb1a4f962fc7 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 11 Jan 2015 00:11:18 +0200 Subject: drm: omapdrm: Switch to the universal plane API Remove the CRTC private planes by switching to the universal plane API. This results in a merge of the CRTC private plane created by the driver (omap_crtc->plane) and the CRTC primary plane created by the DRM core (crtc->primary). Reference counting of the framebuffers in the update plane operation is thus simplified as no reference needs to be stored in the private plane anymore. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/omapdrm/omap_crtc.c | 43 ++++++++++++++++++------------------ drivers/gpu/drm/omapdrm/omap_drv.c | 4 ++-- drivers/gpu/drm/omapdrm/omap_drv.h | 2 +- drivers/gpu/drm/omapdrm/omap_plane.c | 36 ++++++++++++++++++------------ 4 files changed, 46 insertions(+), 39 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index b9c3d8f830e8..7570db59a9ea 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -28,7 +28,6 @@ struct omap_crtc { struct drm_crtc base; - struct drm_plane *plane; const char *name; int pipe; @@ -217,10 +216,7 @@ static void omap_crtc_dpms(struct drm_crtc *crtc, int mode) omap_crtc->full_update = true; omap_crtc_apply(crtc, &omap_crtc->apply); - /* also enable our private plane: */ - WARN_ON(omap_plane_dpms(omap_crtc->plane, mode)); - - /* and any attached overlay planes: */ + /* Enable/disable all planes associated with the CRTC. */ for (i = 0; i < priv->num_planes; i++) { struct drm_plane *plane = priv->planes[i]; if (plane->crtc == crtc) @@ -258,7 +254,13 @@ static int omap_crtc_mode_set(struct drm_crtc *crtc, copy_timings_drm_to_omap(&omap_crtc->timings, mode); omap_crtc->full_update = true; - return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb, + /* + * The primary plane CRTC can be reset if the plane is disabled directly + * through the universal plane API. Set it again here. + */ + crtc->primary->crtc = crtc; + + return omap_plane_mode_set(crtc->primary, crtc, crtc->primary->fb, 0, 0, mode->hdisplay, mode->vdisplay, x << 16, y << 16, mode->hdisplay << 16, mode->vdisplay << 16, @@ -282,8 +284,7 @@ static void omap_crtc_commit(struct drm_crtc *crtc) static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) { - struct omap_crtc *omap_crtc = to_omap_crtc(crtc); - struct drm_plane *plane = omap_crtc->plane; + struct drm_plane *plane = crtc->primary; struct drm_display_mode *mode = &crtc->mode; return omap_plane_mode_set(plane, crtc, crtc->primary->fb, @@ -321,7 +322,7 @@ static void page_flip_worker(struct work_struct *work) struct drm_gem_object *bo; drm_modeset_lock(&crtc->mutex, NULL); - omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb, + omap_plane_mode_set(crtc->primary, crtc, crtc->primary->fb, 0, 0, mode->hdisplay, mode->vdisplay, crtc->x << 16, crtc->y << 16, mode->hdisplay << 16, mode->vdisplay << 16, @@ -385,7 +386,6 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, static int omap_crtc_set_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t val) { - struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct omap_drm_private *priv = crtc->dev->dev_private; if (property == priv->rotation_prop) { @@ -393,7 +393,7 @@ static int omap_crtc_set_property(struct drm_crtc *crtc, !!(val & ((1LL << DRM_ROTATE_90) | (1LL << DRM_ROTATE_270))); } - return omap_plane_set_property(omap_crtc->plane, property, val); + return omap_plane_set_property(crtc->primary, property, val); } static const struct drm_crtc_funcs omap_crtc_funcs = { @@ -681,12 +681,13 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_crtc *crtc = NULL; struct omap_crtc *omap_crtc; struct omap_overlay_manager_info *info; + int ret; DBG("%s", channel_names[channel]); omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); if (!omap_crtc) - goto fail; + return NULL; crtc = &omap_crtc->base; @@ -700,8 +701,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, omap_crtc->apply.post_apply = omap_crtc_post_apply; omap_crtc->channel = channel; - omap_crtc->plane = plane; - omap_crtc->plane->crtc = crtc; omap_crtc->name = channel_names[channel]; omap_crtc->pipe = id; @@ -723,18 +722,18 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; info->trans_enabled = false; - drm_crtc_init(dev, crtc, &omap_crtc_funcs); + ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, + &omap_crtc_funcs); + if (ret < 0) { + kfree(omap_crtc); + return NULL; + } + drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); - omap_plane_install_properties(omap_crtc->plane, &crtc->base); + omap_plane_install_properties(crtc->primary, &crtc->base); omap_crtcs[channel] = omap_crtc; return crtc; - -fail: - if (crtc) - omap_crtc_destroy(crtc); - - return NULL; } diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 021855605a1f..5eab83d7de15 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -135,7 +135,7 @@ static int omap_modeset_create_crtc(struct drm_device *dev, int id, struct drm_plane *plane; struct drm_crtc *crtc; - plane = omap_plane_init(dev, id, true); + plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_PRIMARY); if (IS_ERR(plane)) return PTR_ERR(plane); @@ -277,7 +277,7 @@ static int omap_modeset_init(struct drm_device *dev) for (; id < num_ovls; id++) { struct drm_plane *plane; - plane = omap_plane_init(dev, id, false); + plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_OVERLAY); if (IS_ERR(plane)) return PTR_ERR(plane); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 60e47b33c801..f38ffd14ff06 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -160,7 +160,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, void omap_crtc_flush(struct drm_crtc *crtc); struct drm_plane *omap_plane_init(struct drm_device *dev, - int plane_id, bool private_plane); + int id, enum drm_plane_type type); int omap_plane_dpms(struct drm_plane *plane, int mode); int omap_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index c17460336fcc..32df3e783128 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -220,14 +220,6 @@ int omap_plane_mode_set(struct drm_plane *plane, omap_plane->apply_done_cb.arg = arg; } - if (plane->fb) - drm_framebuffer_unreference(plane->fb); - - drm_framebuffer_reference(fb); - - plane->fb = fb; - plane->crtc = crtc; - return apply(plane); } @@ -249,6 +241,13 @@ static int omap_plane_update(struct drm_plane *plane, break; } + /* + * We don't need to take a reference to the framebuffer as the DRM core + * has already done so for the purpose of setting plane->fb. + */ + plane->fb = fb; + plane->crtc = crtc; + return omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h, @@ -377,14 +376,15 @@ static const uint32_t error_irqs[] = { /* initialize plane */ struct drm_plane *omap_plane_init(struct drm_device *dev, - int id, bool private_plane) + int id, enum drm_plane_type type) { struct omap_drm_private *priv = dev->dev_private; - struct drm_plane *plane = NULL; + struct drm_plane *plane; struct omap_plane *omap_plane; struct omap_overlay_info *info; + int ret; - DBG("%s: priv=%d", plane_names[id], private_plane); + DBG("%s: type=%d", plane_names[id], type); omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); if (!omap_plane) @@ -408,8 +408,11 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, omap_plane->error_irq.irq = omap_plane_error_irq; omap_irq_register(dev, &omap_plane->error_irq); - drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs, - omap_plane->formats, omap_plane->nformats, private_plane); + ret = drm_universal_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, + &omap_plane_funcs, omap_plane->formats, + omap_plane->nformats, type); + if (ret < 0) + goto error; omap_plane_install_properties(plane, &plane->base); @@ -427,10 +430,15 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, * TODO add ioctl to give userspace an API to change this.. this * will come in a subsequent patch. */ - if (private_plane) + if (type == DRM_PLANE_TYPE_PRIMARY) omap_plane->info.zorder = 0; else omap_plane->info.zorder = id; return plane; + +error: + omap_irq_unregister(plane->dev, &omap_plane->error_irq); + kfree(omap_plane); + return NULL; } -- cgit From 173372975457ca0fa0acddf60d087976bacb6ab3 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 3 Sep 2014 19:25:49 +0000 Subject: drm/omap: fix encoder-crtc mapping OMAP DSS hardware supports changing the output port to which an overlay manager's video stream goes. For example, DPI video stream can come from any of the four overlay managers on OMAP5. However, as it's difficult to manage the change in the driver, the omapdss driver does not support that at the moment, and has a hardcoded overlay manager per output. omapdrm, on the other hand, uses the hardware features to find out which overlay manager to use for an output, which causes problems. For example, on OMAP5, omapdrm tries to use DIGIT overlay manager for DPI output, instead of the LCD3 required by the omapdss driver. This patch changes the omapdrm to use the omapdss driver's hardcoded overlay managers, which fixes the issue. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_drv.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 5eab83d7de15..b71a443e671e 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -298,14 +298,13 @@ static int omap_modeset_init(struct drm_device *dev) for (id = 0; id < priv->num_crtcs; id++) { struct drm_crtc *crtc = priv->crtcs[id]; enum omap_channel crtc_channel; - enum omap_dss_output_id supported_outputs; crtc_channel = omap_crtc_channel(crtc); - supported_outputs = - dss_feat_get_supported_outputs(crtc_channel); - if (supported_outputs & output->id) + if (output->dispc_channel == crtc_channel) { encoder->possible_crtcs |= (1 << id); + break; + } } omap_dss_put_device(output); -- cgit From c7c1aecd8e490c3818eaaea33e3c0d372931350a Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 25 Sep 2014 19:24:26 +0000 Subject: drm/omap: fix operation without fbdev omapdrm should work fine even if fbdev is missing. The current driver crashes in that case, though, as it is missing checks for the fbdev. Add the checks so that we don't free fbdev or restore fbdev mode when there's no fbdev. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_drv.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index b71a443e671e..63c953971c11 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -530,7 +530,8 @@ static int dev_unload(struct drm_device *dev) drm_kms_helper_poll_fini(dev); - omap_fbdev_free(dev); + if (priv->fbdev) + omap_fbdev_free(dev); /* flush crtcs so the fbs get released */ for (i = 0; i < priv->num_crtcs; i++) @@ -599,9 +600,11 @@ static void dev_lastclose(struct drm_device *dev) } } - ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev); - if (ret) - DBG("failed to restore crtc mode"); + if (priv->fbdev) { + ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev); + if (ret) + DBG("failed to restore crtc mode"); + } } static void dev_preclose(struct drm_device *dev, struct drm_file *file) -- cgit From f5a1d3174f9e1d2d55bfd06626586963283e58be Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 14 Nov 2014 15:18:27 +0200 Subject: drm/omap: remove dummy PM functions omapdrm has dummy functions for platform_device's suspend/resume/shutdown. The functions don't do anything, and those platform device functions are deprecated, so remove them from omapdrm. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_drv.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 63c953971c11..8d8cf82ecdf7 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -675,23 +675,6 @@ static struct drm_driver omap_drm_driver = { .patchlevel = DRIVER_PATCHLEVEL, }; -static int pdev_suspend(struct platform_device *pDevice, pm_message_t state) -{ - DBG(""); - return 0; -} - -static int pdev_resume(struct platform_device *device) -{ - DBG(""); - return 0; -} - -static void pdev_shutdown(struct platform_device *device) -{ - DBG(""); -} - static int pdev_probe(struct platform_device *device) { int r; @@ -738,9 +721,6 @@ static struct platform_driver pdev = { }, .probe = pdev_probe, .remove = pdev_remove, - .suspend = pdev_suspend, - .resume = pdev_resume, - .shutdown = pdev_shutdown, }; static int __init omap_drm_init(void) -- cgit From ccd7b5ed7d1ed47ee5ea2f66325972811eb093bd Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 14 Nov 2014 15:18:28 +0200 Subject: drm/omap: stop connector polling during suspend When not using proper hotplug detection, DRM polls periodically the connectors to find out if a cable is connected. This polling can happen at any time, even very late in the suspend process. This causes a problem with omapdrm, when the poll happens during the suspend process after GPIOs have been disabled, leading to a crash in gpio_get(). This patch fixes the issue by adding suspend and resume hooks to omapdrm, in which we disable and enable, respectively, the polling. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_drv.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 8d8cf82ecdf7..c4c237317901 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -706,9 +706,28 @@ static int pdev_remove(struct platform_device *device) return 0; } +static int omap_drm_suspend(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + + drm_kms_helper_poll_disable(drm_dev); + + return 0; +} + +static int omap_drm_resume(struct device *dev) +{ + struct drm_device *drm_dev = dev_get_drvdata(dev); + + drm_kms_helper_poll_enable(drm_dev); + + return omap_gem_resume(dev); +} + #ifdef CONFIG_PM static const struct dev_pm_ops omapdrm_pm_ops = { - .resume = omap_gem_resume, + .suspend = omap_drm_suspend, + .resume = omap_drm_resume, }; #endif -- cgit From 76c4055f2c9a7ae556e96c1cadd82ee182b7d87e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 17 Dec 2014 14:34:22 +0200 Subject: drm/omap: fix race condition with dev->obj_list omap_gem_objects are added to dev->obj_list in omap_gem_new, and removed in omap_gem_free_object. Unfortunately there's no locking for dev->obj_list, which eventually leads to a crash: WARNING: CPU: 1 PID: 1123 at lib/list_debug.c:59 __list_del_entry+0xa4/0xe0() list_del corruption. prev->next should be e9281344, but was ea722b84 Add a spinlock to protect dev->obj_list. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_drv.c | 1 + drivers/gpu/drm/omapdrm/omap_drv.h | 3 +++ drivers/gpu/drm/omapdrm/omap_gem.c | 5 +++++ 3 files changed, 9 insertions(+) (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index c4c237317901..c6980985884b 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -491,6 +491,7 @@ static int dev_load(struct drm_device *dev, unsigned long flags) priv->wq = alloc_ordered_workqueue("omapdrm", 0); + spin_lock_init(&priv->list_lock); INIT_LIST_HEAD(&priv->obj_list); omap_gem_init(dev); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 57e11c1f589f..b31c79f15aed 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -105,6 +105,9 @@ struct omap_drm_private { struct workqueue_struct *wq; + /* lock for obj_list below */ + spinlock_t list_lock; + /* list of GEM objects: */ struct list_head obj_list; diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index d37ee756a0b1..e9718b99a8a9 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1273,13 +1273,16 @@ unlock: void omap_gem_free_object(struct drm_gem_object *obj) { struct drm_device *dev = obj->dev; + struct omap_drm_private *priv = dev->dev_private; struct omap_gem_object *omap_obj = to_omap_bo(obj); evict(obj); WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + spin_lock(&priv->list_lock); list_del(&omap_obj->mm_list); + spin_unlock(&priv->list_lock); drm_gem_free_mmap_offset(obj); @@ -1377,7 +1380,9 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev, if (!omap_obj) goto fail; + spin_lock(&priv->list_lock); list_add(&omap_obj->mm_list, &priv->obj_list); + spin_unlock(&priv->list_lock); obj = &omap_obj->base; -- cgit From 8450c8d071d858e8f95855a7b5897df3981e3d21 Mon Sep 17 00:00:00 2001 From: Grygorii Strashko Date: Thu, 26 Feb 2015 15:57:17 +0200 Subject: drm/omap: add hibernation callbacks Setting a dev_pm_ops suspend/resume pair but not a set of hibernation functions means those pm functions will not be called upon hibernation. Fix this by using SIMPLE_DEV_PM_OPS, which appropriately assigns the suspend and hibernation handlers and move omap_drm_suspend/omap_drm_resume under CONFIG_PM_SLEEP to avoid build warnings. Signed-off-by: Grygorii Strashko [tomi.valkeinen@ti.com: fix conflict, clean up description] Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_drv.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_drv.c') diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index c6980985884b..94920d47e3b6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -707,6 +707,7 @@ static int pdev_remove(struct platform_device *device) return 0; } +#ifdef CONFIG_PM_SLEEP static int omap_drm_suspend(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); @@ -724,20 +725,14 @@ static int omap_drm_resume(struct device *dev) return omap_gem_resume(dev); } - -#ifdef CONFIG_PM -static const struct dev_pm_ops omapdrm_pm_ops = { - .suspend = omap_drm_suspend, - .resume = omap_drm_resume, -}; #endif +static SIMPLE_DEV_PM_OPS(omapdrm_pm_ops, omap_drm_suspend, omap_drm_resume); + static struct platform_driver pdev = { .driver = { .name = DRIVER_NAME, -#ifdef CONFIG_PM .pm = &omapdrm_pm_ops, -#endif }, .probe = pdev_probe, .remove = pdev_remove, -- cgit