Commit d62c3e7a73f87defb17651109a55d36adedadc6f

Authored by Dave Airlie

Merge tag 'omapdrm-fixes-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/…

…tomba/linux into drm-next

Fixes for omapdrm, some of which were already present in 3.14, and some which
appeared in 3.15-rc1:

- fixes for primary-plane handling which caused crashes
- fix all kinds of uninit issues which prevented from unloading the omapdrm
  module.
- fixes for HDMI enable/disable issues

* tag 'omapdrm-fixes-3.15' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux:
  drm/omap: fix the handling of fb ref counts
  drm/omap: protect omap_crtc's event with event_lock spinlock
  drm/omap: Use old_fb to synchronize between successive page flips
  drm/omap: Fix crash when using LCD3 overlay manager
  drm/omap: gem sync: wait on correct events
  drm/omap: Fix memory leak in omap_gem_op_async
  drm/omap: remove warn from debugfs
  drm/omap: remove extra plane->destroy from crtc destroy
  drm/omap: print warning when rotating non-TILER fb
  drm/omap: fix missing unref to fb's buf object
  drm/omap: fix plane rotation
  drm/omap: fix enabling/disabling of video pipeline
  drm/omap: fix missing disable for unused encoder
  drm/omap: fix race issue when unloading omapdrm
  drm/omap: fix DMM driver (un)registration
  drm/omap: fix uninit order in pdev_remove()
  drm/omap: fix output enable/disable sequence

Showing 7 changed files Side-by-side Diff

drivers/gpu/drm/omapdrm/omap_crtc.c
... ... @@ -33,6 +33,7 @@
33 33 int pipe;
34 34 enum omap_channel channel;
35 35 struct omap_overlay_manager_info info;
  36 + struct drm_encoder *current_encoder;
36 37  
37 38 /*
38 39 * Temporary: eventually this will go away, but it is needed
39 40  
40 41  
... ... @@ -120,13 +121,25 @@
120 121 {
121 122 }
122 123  
  124 +static void set_enabled(struct drm_crtc *crtc, bool enable);
  125 +
123 126 static int omap_crtc_enable(struct omap_overlay_manager *mgr)
124 127 {
  128 + struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
  129 +
  130 + dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info);
  131 + dispc_mgr_set_timings(omap_crtc->channel,
  132 + &omap_crtc->timings);
  133 + set_enabled(&omap_crtc->base, true);
  134 +
125 135 return 0;
126 136 }
127 137  
128 138 static void omap_crtc_disable(struct omap_overlay_manager *mgr)
129 139 {
  140 + struct omap_crtc *omap_crtc = omap_crtcs[mgr->id];
  141 +
  142 + set_enabled(&omap_crtc->base, false);
130 143 }
131 144  
132 145 static void omap_crtc_set_timings(struct omap_overlay_manager *mgr,
... ... @@ -184,7 +197,6 @@
184 197 WARN_ON(omap_crtc->apply_irq.registered);
185 198 omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
186 199  
187   - omap_crtc->plane->funcs->destroy(omap_crtc->plane);
188 200 drm_crtc_cleanup(crtc);
189 201  
190 202 kfree(omap_crtc);
191 203  
192 204  
193 205  
194 206  
... ... @@ -338,18 +350,24 @@
338 350 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
339 351 struct drm_plane *primary = crtc->primary;
340 352 struct drm_gem_object *bo;
  353 + unsigned long flags;
341 354  
342 355 DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1,
343 356 fb->base.id, event);
344 357  
  358 + spin_lock_irqsave(&dev->event_lock, flags);
  359 +
345 360 if (omap_crtc->old_fb) {
  361 + spin_unlock_irqrestore(&dev->event_lock, flags);
346 362 dev_err(dev->dev, "already a pending flip\n");
347 363 return -EINVAL;
348 364 }
349 365  
350 366 omap_crtc->event = event;
351   - primary->fb = fb;
  367 + omap_crtc->old_fb = primary->fb = fb;
352 368  
  369 + spin_unlock_irqrestore(&dev->event_lock, flags);
  370 +
353 371 /*
354 372 * Hold a reference temporarily until the crtc is updated
355 373 * and takes the reference to the bo. This avoids it
356 374  
357 375  
358 376  
359 377  
360 378  
... ... @@ -528,38 +546,46 @@
528 546 struct drm_device *dev = crtc->dev;
529 547 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
530 548 enum omap_channel channel = omap_crtc->channel;
531   - struct omap_irq_wait *wait = NULL;
  549 + struct omap_irq_wait *wait;
  550 + u32 framedone_irq, vsync_irq;
  551 + int ret;
532 552  
533 553 if (dispc_mgr_is_enabled(channel) == enable)
534 554 return;
535 555  
536   - /* ignore sync-lost irqs during enable/disable */
  556 + /*
  557 + * Digit output produces some sync lost interrupts during the first
  558 + * frame when enabling, so we need to ignore those.
  559 + */
537 560 omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
538 561  
539   - if (dispc_mgr_get_framedone_irq(channel)) {
540   - if (!enable) {
541   - wait = omap_irq_wait_init(dev,
542   - dispc_mgr_get_framedone_irq(channel), 1);
543   - }
  562 + framedone_irq = dispc_mgr_get_framedone_irq(channel);
  563 + vsync_irq = dispc_mgr_get_vsync_irq(channel);
  564 +
  565 + if (enable) {
  566 + wait = omap_irq_wait_init(dev, vsync_irq, 1);
544 567 } else {
545 568 /*
546   - * When we disable digit output, we need to wait until fields
547   - * are done. Otherwise the DSS is still working, and turning
548   - * off the clocks prevents DSS from going to OFF mode. And when
549   - * enabling, we need to wait for the extra sync losts
  569 + * When we disable the digit output, we need to wait for
  570 + * FRAMEDONE to know that DISPC has finished with the output.
  571 + *
  572 + * OMAP2/3 does not have FRAMEDONE irq for digit output, and in
  573 + * that case we need to use vsync interrupt, and wait for both
  574 + * even and odd frames.
550 575 */
551   - wait = omap_irq_wait_init(dev,
552   - dispc_mgr_get_vsync_irq(channel), 2);
  576 +
  577 + if (framedone_irq)
  578 + wait = omap_irq_wait_init(dev, framedone_irq, 1);
  579 + else
  580 + wait = omap_irq_wait_init(dev, vsync_irq, 2);
553 581 }
554 582  
555 583 dispc_mgr_enable(channel, enable);
556 584  
557   - if (wait) {
558   - int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
559   - if (ret) {
560   - dev_err(dev->dev, "%s: timeout waiting for %s\n",
561   - omap_crtc->name, enable ? "enable" : "disable");
562   - }
  585 + ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
  586 + if (ret) {
  587 + dev_err(dev->dev, "%s: timeout waiting for %s\n",
  588 + omap_crtc->name, enable ? "enable" : "disable");
563 589 }
564 590  
565 591 omap_irq_register(crtc->dev, &omap_crtc->error_irq);
566 592  
... ... @@ -586,8 +612,12 @@
586 612 }
587 613 }
588 614  
  615 + if (omap_crtc->current_encoder && encoder != omap_crtc->current_encoder)
  616 + omap_encoder_set_enabled(omap_crtc->current_encoder, false);
  617 +
  618 + omap_crtc->current_encoder = encoder;
  619 +
589 620 if (!omap_crtc->enabled) {
590   - set_enabled(&omap_crtc->base, false);
591 621 if (encoder)
592 622 omap_encoder_set_enabled(encoder, false);
593 623 } else {
594 624  
... ... @@ -596,13 +626,7 @@
596 626 omap_encoder_update(encoder, omap_crtc->mgr,
597 627 &omap_crtc->timings);
598 628 omap_encoder_set_enabled(encoder, true);
599   - omap_crtc->full_update = false;
600 629 }
601   -
602   - dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info);
603   - dispc_mgr_set_timings(omap_crtc->channel,
604   - &omap_crtc->timings);
605   - set_enabled(&omap_crtc->base, true);
606 630 }
607 631  
608 632 omap_crtc->full_update = false;
609 633  
... ... @@ -613,10 +637,30 @@
613 637 /* nothing needed for post-apply */
614 638 }
615 639  
  640 +void omap_crtc_flush(struct drm_crtc *crtc)
  641 +{
  642 + struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
  643 + int loops = 0;
  644 +
  645 + while (!list_empty(&omap_crtc->pending_applies) ||
  646 + !list_empty(&omap_crtc->queued_applies) ||
  647 + omap_crtc->event || omap_crtc->old_fb) {
  648 +
  649 + if (++loops > 10) {
  650 + dev_err(crtc->dev->dev,
  651 + "omap_crtc_flush() timeout\n");
  652 + break;
  653 + }
  654 +
  655 + schedule_timeout_uninterruptible(msecs_to_jiffies(20));
  656 + }
  657 +}
  658 +
616 659 static const char *channel_names[] = {
617 660 [OMAP_DSS_CHANNEL_LCD] = "lcd",
618 661 [OMAP_DSS_CHANNEL_DIGIT] = "tv",
619 662 [OMAP_DSS_CHANNEL_LCD2] = "lcd2",
  663 + [OMAP_DSS_CHANNEL_LCD3] = "lcd3",
620 664 };
621 665  
622 666 void omap_crtc_pre_init(void)
drivers/gpu/drm/omapdrm/omap_drv.c
... ... @@ -513,12 +513,18 @@
513 513 static int dev_unload(struct drm_device *dev)
514 514 {
515 515 struct omap_drm_private *priv = dev->dev_private;
  516 + int i;
516 517  
517 518 DBG("unload: dev=%p", dev);
518 519  
519 520 drm_kms_helper_poll_fini(dev);
520 521  
521 522 omap_fbdev_free(dev);
  523 +
  524 + /* flush crtcs so the fbs get released */
  525 + for (i = 0; i < priv->num_crtcs; i++)
  526 + omap_crtc_flush(priv->crtcs[i]);
  527 +
522 528 omap_modeset_free(dev);
523 529 omap_gem_deinit(dev);
524 530  
525 531  
... ... @@ -696,10 +702,11 @@
696 702 {
697 703 DBG("");
698 704  
  705 + drm_put_dev(platform_get_drvdata(device));
  706 +
699 707 omap_disconnect_dssdevs();
700 708 omap_crtc_pre_uninit();
701 709  
702   - drm_put_dev(platform_get_drvdata(device));
703 710 return 0;
704 711 }
705 712  
706 713  
707 714  
708 715  
709 716  
... ... @@ -726,18 +733,33 @@
726 733  
727 734 static int __init omap_drm_init(void)
728 735 {
  736 + int r;
  737 +
729 738 DBG("init");
730   - if (platform_driver_register(&omap_dmm_driver)) {
731   - /* we can continue on without DMM.. so not fatal */
732   - dev_err(NULL, "DMM registration failed\n");
  739 +
  740 + r = platform_driver_register(&omap_dmm_driver);
  741 + if (r) {
  742 + pr_err("DMM driver registration failed\n");
  743 + return r;
733 744 }
734   - return platform_driver_register(&pdev);
  745 +
  746 + r = platform_driver_register(&pdev);
  747 + if (r) {
  748 + pr_err("omapdrm driver registration failed\n");
  749 + platform_driver_unregister(&omap_dmm_driver);
  750 + return r;
  751 + }
  752 +
  753 + return 0;
735 754 }
736 755  
737 756 static void __exit omap_drm_fini(void)
738 757 {
739 758 DBG("fini");
  759 +
740 760 platform_driver_unregister(&pdev);
  761 +
  762 + platform_driver_unregister(&omap_dmm_driver);
741 763 }
742 764  
743 765 /* need late_initcall() so we load after dss_driver's are loaded */
drivers/gpu/drm/omapdrm/omap_drv.h
... ... @@ -163,6 +163,7 @@
163 163 void omap_crtc_pre_uninit(void);
164 164 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
165 165 struct drm_plane *plane, enum omap_channel channel, int id);
  166 +void omap_crtc_flush(struct drm_crtc *crtc);
166 167  
167 168 struct drm_plane *omap_plane_init(struct drm_device *dev,
168 169 int plane_id, bool private_plane);
drivers/gpu/drm/omapdrm/omap_fb.c
... ... @@ -218,6 +218,20 @@
218 218 info->rotation_type = OMAP_DSS_ROT_TILER;
219 219 info->screen_width = omap_gem_tiled_stride(plane->bo, orient);
220 220 } else {
  221 + switch (win->rotation & 0xf) {
  222 + case 0:
  223 + case BIT(DRM_ROTATE_0):
  224 + /* OK */
  225 + break;
  226 +
  227 + default:
  228 + dev_warn(fb->dev->dev,
  229 + "rotation '%d' ignored for non-tiled fb\n",
  230 + win->rotation);
  231 + win->rotation = 0;
  232 + break;
  233 + }
  234 +
221 235 info->paddr = get_linear_addr(plane, format, 0, x, y);
222 236 info->rotation_type = OMAP_DSS_ROT_DMA;
223 237 info->screen_width = plane->pitch;
drivers/gpu/drm/omapdrm/omap_fbdev.c
... ... @@ -371,6 +371,9 @@
371 371  
372 372 fbdev = to_omap_fbdev(priv->fbdev);
373 373  
  374 + /* release the ref taken in omap_fbdev_create() */
  375 + omap_gem_put_paddr(fbdev->bo);
  376 +
374 377 /* this will free the backing object */
375 378 if (fbdev->fb) {
376 379 drm_framebuffer_unregister_private(fbdev->fb);
drivers/gpu/drm/omapdrm/omap_gem.c
... ... @@ -980,12 +980,9 @@
980 980 #ifdef CONFIG_DEBUG_FS
981 981 void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
982 982 {
983   - struct drm_device *dev = obj->dev;
984 983 struct omap_gem_object *omap_obj = to_omap_bo(obj);
985 984 uint64_t off;
986 985  
987   - WARN_ON(!mutex_is_locked(&dev->struct_mutex));
988   -
989 986 off = drm_vma_node_start(&obj->vma_node);
990 987  
991 988 seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d",
992 989  
... ... @@ -1050,10 +1047,10 @@
1050 1047 {
1051 1048 struct omap_gem_object *omap_obj = waiter->omap_obj;
1052 1049 if ((waiter->op & OMAP_GEM_READ) &&
1053   - (omap_obj->sync->read_complete < waiter->read_target))
  1050 + (omap_obj->sync->write_complete < waiter->write_target))
1054 1051 return true;
1055 1052 if ((waiter->op & OMAP_GEM_WRITE) &&
1056   - (omap_obj->sync->write_complete < waiter->write_target))
  1053 + (omap_obj->sync->read_complete < waiter->read_target))
1057 1054 return true;
1058 1055 return false;
1059 1056 }
... ... @@ -1229,6 +1226,8 @@
1229 1226 }
1230 1227  
1231 1228 spin_unlock(&sync_lock);
  1229 +
  1230 + kfree(waiter);
1232 1231 }
1233 1232  
1234 1233 /* no waiting.. */
drivers/gpu/drm/omapdrm/omap_plane.c
... ... @@ -225,6 +225,11 @@
225 225 omap_plane->apply_done_cb.arg = arg;
226 226 }
227 227  
  228 + if (plane->fb)
  229 + drm_framebuffer_unreference(plane->fb);
  230 +
  231 + drm_framebuffer_reference(fb);
  232 +
228 233 plane->fb = fb;
229 234 plane->crtc = crtc;
230 235  
... ... @@ -241,10 +246,13 @@
241 246 struct omap_plane *omap_plane = to_omap_plane(plane);
242 247 omap_plane->enabled = true;
243 248  
244   - if (plane->fb)
245   - drm_framebuffer_unreference(plane->fb);
246   -
247   - drm_framebuffer_reference(fb);
  249 + /* omap_plane_mode_set() takes adjusted src */
  250 + switch (omap_plane->win.rotation & 0xf) {
  251 + case BIT(DRM_ROTATE_90):
  252 + case BIT(DRM_ROTATE_270):
  253 + swap(src_w, src_h);
  254 + break;
  255 + }
248 256  
249 257 return omap_plane_mode_set(plane, crtc, fb,
250 258 crtc_x, crtc_y, crtc_w, crtc_h,