diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm')
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 100 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.c | 32 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_drv.h | 1 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_fb.c | 14 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_fbdev.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_gem.c | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/omapdrm/omap_plane.c | 16 |
7 files changed, 133 insertions, 42 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 355157e4f78d..e3c47a8005ff 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c | |||
| @@ -33,6 +33,7 @@ struct omap_crtc { | |||
| 33 | int pipe; | 33 | int pipe; |
| 34 | enum omap_channel channel; | 34 | enum omap_channel channel; |
| 35 | struct omap_overlay_manager_info info; | 35 | struct omap_overlay_manager_info info; |
| 36 | struct drm_encoder *current_encoder; | ||
| 36 | 37 | ||
| 37 | /* | 38 | /* |
| 38 | * Temporary: eventually this will go away, but it is needed | 39 | * Temporary: eventually this will go away, but it is needed |
| @@ -120,13 +121,25 @@ static void omap_crtc_start_update(struct omap_overlay_manager *mgr) | |||
| 120 | { | 121 | { |
| 121 | } | 122 | } |
| 122 | 123 | ||
| 124 | static void set_enabled(struct drm_crtc *crtc, bool enable); | ||
| 125 | |||
| 123 | static int omap_crtc_enable(struct omap_overlay_manager *mgr) | 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 | return 0; | 135 | return 0; |
| 126 | } | 136 | } |
| 127 | 137 | ||
| 128 | static void omap_crtc_disable(struct omap_overlay_manager *mgr) | 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 | static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, | 145 | static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, |
| @@ -184,7 +197,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) | |||
| 184 | WARN_ON(omap_crtc->apply_irq.registered); | 197 | WARN_ON(omap_crtc->apply_irq.registered); |
| 185 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | 198 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); |
| 186 | 199 | ||
| 187 | omap_crtc->plane->funcs->destroy(omap_crtc->plane); | ||
| 188 | drm_crtc_cleanup(crtc); | 200 | drm_crtc_cleanup(crtc); |
| 189 | 201 | ||
| 190 | kfree(omap_crtc); | 202 | kfree(omap_crtc); |
| @@ -338,17 +350,23 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, | |||
| 338 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 350 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| 339 | struct drm_plane *primary = crtc->primary; | 351 | struct drm_plane *primary = crtc->primary; |
| 340 | struct drm_gem_object *bo; | 352 | struct drm_gem_object *bo; |
| 353 | unsigned long flags; | ||
| 341 | 354 | ||
| 342 | DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1, | 355 | DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1, |
| 343 | fb->base.id, event); | 356 | fb->base.id, event); |
| 344 | 357 | ||
| 358 | spin_lock_irqsave(&dev->event_lock, flags); | ||
| 359 | |||
| 345 | if (omap_crtc->old_fb) { | 360 | if (omap_crtc->old_fb) { |
| 361 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
| 346 | dev_err(dev->dev, "already a pending flip\n"); | 362 | dev_err(dev->dev, "already a pending flip\n"); |
| 347 | return -EINVAL; | 363 | return -EINVAL; |
| 348 | } | 364 | } |
| 349 | 365 | ||
| 350 | omap_crtc->event = event; | 366 | omap_crtc->event = event; |
| 351 | primary->fb = fb; | 367 | omap_crtc->old_fb = primary->fb = fb; |
| 368 | |||
| 369 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
| 352 | 370 | ||
| 353 | /* | 371 | /* |
| 354 | * Hold a reference temporarily until the crtc is updated | 372 | * Hold a reference temporarily until the crtc is updated |
| @@ -528,38 +546,46 @@ static void set_enabled(struct drm_crtc *crtc, bool enable) | |||
| 528 | struct drm_device *dev = crtc->dev; | 546 | struct drm_device *dev = crtc->dev; |
| 529 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 547 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
| 530 | enum omap_channel channel = omap_crtc->channel; | 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 | if (dispc_mgr_is_enabled(channel) == enable) | 553 | if (dispc_mgr_is_enabled(channel) == enable) |
| 534 | return; | 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 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | 560 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); |
| 538 | 561 | ||
| 539 | if (dispc_mgr_get_framedone_irq(channel)) { | 562 | framedone_irq = dispc_mgr_get_framedone_irq(channel); |
| 540 | if (!enable) { | 563 | vsync_irq = dispc_mgr_get_vsync_irq(channel); |
| 541 | wait = omap_irq_wait_init(dev, | 564 | |
| 542 | dispc_mgr_get_framedone_irq(channel), 1); | 565 | if (enable) { |
| 543 | } | 566 | wait = omap_irq_wait_init(dev, vsync_irq, 1); |
| 544 | } else { | 567 | } else { |
| 545 | /* | 568 | /* |
| 546 | * When we disable digit output, we need to wait until fields | 569 | * When we disable the digit output, we need to wait for |
| 547 | * are done. Otherwise the DSS is still working, and turning | 570 | * FRAMEDONE to know that DISPC has finished with the output. |
| 548 | * off the clocks prevents DSS from going to OFF mode. And when | 571 | * |
| 549 | * enabling, we need to wait for the extra sync losts | 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, | 576 | |
| 552 | dispc_mgr_get_vsync_irq(channel), 2); | 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 | dispc_mgr_enable(channel, enable); | 583 | dispc_mgr_enable(channel, enable); |
| 556 | 584 | ||
| 557 | if (wait) { | 585 | ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); |
| 558 | int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); | 586 | if (ret) { |
| 559 | if (ret) { | 587 | dev_err(dev->dev, "%s: timeout waiting for %s\n", |
| 560 | dev_err(dev->dev, "%s: timeout waiting for %s\n", | 588 | omap_crtc->name, enable ? "enable" : "disable"); |
| 561 | omap_crtc->name, enable ? "enable" : "disable"); | ||
| 562 | } | ||
| 563 | } | 589 | } |
| 564 | 590 | ||
| 565 | omap_irq_register(crtc->dev, &omap_crtc->error_irq); | 591 | omap_irq_register(crtc->dev, &omap_crtc->error_irq); |
| @@ -586,8 +612,12 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) | |||
| 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 | if (!omap_crtc->enabled) { | 620 | if (!omap_crtc->enabled) { |
| 590 | set_enabled(&omap_crtc->base, false); | ||
| 591 | if (encoder) | 621 | if (encoder) |
| 592 | omap_encoder_set_enabled(encoder, false); | 622 | omap_encoder_set_enabled(encoder, false); |
| 593 | } else { | 623 | } else { |
| @@ -596,13 +626,7 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) | |||
| 596 | omap_encoder_update(encoder, omap_crtc->mgr, | 626 | omap_encoder_update(encoder, omap_crtc->mgr, |
| 597 | &omap_crtc->timings); | 627 | &omap_crtc->timings); |
| 598 | omap_encoder_set_enabled(encoder, true); | 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 | omap_crtc->full_update = false; | 632 | omap_crtc->full_update = false; |
| @@ -613,10 +637,30 @@ static void omap_crtc_post_apply(struct omap_drm_apply *apply) | |||
| 613 | /* nothing needed for post-apply */ | 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 | static const char *channel_names[] = { | 659 | static const char *channel_names[] = { |
| 617 | [OMAP_DSS_CHANNEL_LCD] = "lcd", | 660 | [OMAP_DSS_CHANNEL_LCD] = "lcd", |
| 618 | [OMAP_DSS_CHANNEL_DIGIT] = "tv", | 661 | [OMAP_DSS_CHANNEL_DIGIT] = "tv", |
| 619 | [OMAP_DSS_CHANNEL_LCD2] = "lcd2", | 662 | [OMAP_DSS_CHANNEL_LCD2] = "lcd2", |
| 663 | [OMAP_DSS_CHANNEL_LCD3] = "lcd3", | ||
| 620 | }; | 664 | }; |
| 621 | 665 | ||
| 622 | void omap_crtc_pre_init(void) | 666 | void omap_crtc_pre_init(void) |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index bf39fcc49e0f..c8270e4b26f3 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c | |||
| @@ -513,12 +513,18 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
| 513 | static int dev_unload(struct drm_device *dev) | 513 | static int dev_unload(struct drm_device *dev) |
| 514 | { | 514 | { |
| 515 | struct omap_drm_private *priv = dev->dev_private; | 515 | struct omap_drm_private *priv = dev->dev_private; |
| 516 | int i; | ||
| 516 | 517 | ||
| 517 | DBG("unload: dev=%p", dev); | 518 | DBG("unload: dev=%p", dev); |
| 518 | 519 | ||
| 519 | drm_kms_helper_poll_fini(dev); | 520 | drm_kms_helper_poll_fini(dev); |
| 520 | 521 | ||
| 521 | omap_fbdev_free(dev); | 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 | omap_modeset_free(dev); | 528 | omap_modeset_free(dev); |
| 523 | omap_gem_deinit(dev); | 529 | omap_gem_deinit(dev); |
| 524 | 530 | ||
| @@ -696,10 +702,11 @@ static int pdev_remove(struct platform_device *device) | |||
| 696 | { | 702 | { |
| 697 | DBG(""); | 703 | DBG(""); |
| 698 | 704 | ||
| 705 | drm_put_dev(platform_get_drvdata(device)); | ||
| 706 | |||
| 699 | omap_disconnect_dssdevs(); | 707 | omap_disconnect_dssdevs(); |
| 700 | omap_crtc_pre_uninit(); | 708 | omap_crtc_pre_uninit(); |
| 701 | 709 | ||
| 702 | drm_put_dev(platform_get_drvdata(device)); | ||
| 703 | return 0; | 710 | return 0; |
| 704 | } | 711 | } |
| 705 | 712 | ||
| @@ -726,18 +733,33 @@ static struct platform_driver pdev = { | |||
| 726 | 733 | ||
| 727 | static int __init omap_drm_init(void) | 734 | static int __init omap_drm_init(void) |
| 728 | { | 735 | { |
| 736 | int r; | ||
| 737 | |||
| 729 | DBG("init"); | 738 | DBG("init"); |
| 730 | if (platform_driver_register(&omap_dmm_driver)) { | 739 | |
| 731 | /* we can continue on without DMM.. so not fatal */ | 740 | r = platform_driver_register(&omap_dmm_driver); |
| 732 | dev_err(NULL, "DMM registration failed\n"); | 741 | if (r) { |
| 742 | pr_err("DMM driver registration failed\n"); | ||
| 743 | return r; | ||
| 744 | } | ||
| 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; | ||
| 733 | } | 751 | } |
| 734 | return platform_driver_register(&pdev); | 752 | |
| 753 | return 0; | ||
| 735 | } | 754 | } |
| 736 | 755 | ||
| 737 | static void __exit omap_drm_fini(void) | 756 | static void __exit omap_drm_fini(void) |
| 738 | { | 757 | { |
| 739 | DBG("fini"); | 758 | DBG("fini"); |
| 759 | |||
| 740 | platform_driver_unregister(&pdev); | 760 | platform_driver_unregister(&pdev); |
| 761 | |||
| 762 | platform_driver_unregister(&omap_dmm_driver); | ||
| 741 | } | 763 | } |
| 742 | 764 | ||
| 743 | /* need late_initcall() so we load after dss_driver's are loaded */ | 765 | /* need late_initcall() so we load after dss_driver's are loaded */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 428b2981fd68..284b80fc3c54 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h | |||
| @@ -163,6 +163,7 @@ void omap_crtc_pre_init(void); | |||
| 163 | void omap_crtc_pre_uninit(void); | 163 | void omap_crtc_pre_uninit(void); |
| 164 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, | 164 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, |
| 165 | struct drm_plane *plane, enum omap_channel channel, int id); | 165 | struct drm_plane *plane, enum omap_channel channel, int id); |
| 166 | void omap_crtc_flush(struct drm_crtc *crtc); | ||
| 166 | 167 | ||
| 167 | struct drm_plane *omap_plane_init(struct drm_device *dev, | 168 | struct drm_plane *omap_plane_init(struct drm_device *dev, |
| 168 | int plane_id, bool private_plane); | 169 | int plane_id, bool private_plane); |
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index d2b8c49bfb4a..8b019602ffe6 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c | |||
| @@ -218,6 +218,20 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, | |||
| 218 | info->rotation_type = OMAP_DSS_ROT_TILER; | 218 | info->rotation_type = OMAP_DSS_ROT_TILER; |
| 219 | info->screen_width = omap_gem_tiled_stride(plane->bo, orient); | 219 | info->screen_width = omap_gem_tiled_stride(plane->bo, orient); |
| 220 | } else { | 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 | info->paddr = get_linear_addr(plane, format, 0, x, y); | 235 | info->paddr = get_linear_addr(plane, format, 0, x, y); |
| 222 | info->rotation_type = OMAP_DSS_ROT_DMA; | 236 | info->rotation_type = OMAP_DSS_ROT_DMA; |
| 223 | info->screen_width = plane->pitch; | 237 | info->screen_width = plane->pitch; |
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 002988d09021..1388ca7f87e8 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c | |||
| @@ -371,6 +371,9 @@ void omap_fbdev_free(struct drm_device *dev) | |||
| 371 | 371 | ||
| 372 | fbdev = to_omap_fbdev(priv->fbdev); | 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 | /* this will free the backing object */ | 377 | /* this will free the backing object */ |
| 375 | if (fbdev->fb) { | 378 | if (fbdev->fb) { |
| 376 | drm_framebuffer_unregister_private(fbdev->fb); | 379 | drm_framebuffer_unregister_private(fbdev->fb); |
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index c8d972763889..95dbce286a41 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c | |||
| @@ -980,12 +980,9 @@ int omap_gem_resume(struct device *dev) | |||
| 980 | #ifdef CONFIG_DEBUG_FS | 980 | #ifdef CONFIG_DEBUG_FS |
| 981 | void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) | 981 | void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) |
| 982 | { | 982 | { |
| 983 | struct drm_device *dev = obj->dev; | ||
| 984 | struct omap_gem_object *omap_obj = to_omap_bo(obj); | 983 | struct omap_gem_object *omap_obj = to_omap_bo(obj); |
| 985 | uint64_t off; | 984 | uint64_t off; |
| 986 | 985 | ||
| 987 | WARN_ON(!mutex_is_locked(&dev->struct_mutex)); | ||
| 988 | |||
| 989 | off = drm_vma_node_start(&obj->vma_node); | 986 | off = drm_vma_node_start(&obj->vma_node); |
| 990 | 987 | ||
| 991 | seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d", | 988 | seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d", |
| @@ -1050,10 +1047,10 @@ static inline bool is_waiting(struct omap_gem_sync_waiter *waiter) | |||
| 1050 | { | 1047 | { |
| 1051 | struct omap_gem_object *omap_obj = waiter->omap_obj; | 1048 | struct omap_gem_object *omap_obj = waiter->omap_obj; |
| 1052 | if ((waiter->op & OMAP_GEM_READ) && | 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 | return true; | 1051 | return true; |
| 1055 | if ((waiter->op & OMAP_GEM_WRITE) && | 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 | return true; | 1054 | return true; |
| 1058 | return false; | 1055 | return false; |
| 1059 | } | 1056 | } |
| @@ -1229,6 +1226,8 @@ int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op, | |||
| 1229 | } | 1226 | } |
| 1230 | 1227 | ||
| 1231 | spin_unlock(&sync_lock); | 1228 | spin_unlock(&sync_lock); |
| 1229 | |||
| 1230 | kfree(waiter); | ||
| 1232 | } | 1231 | } |
| 1233 | 1232 | ||
| 1234 | /* no waiting.. */ | 1233 | /* no waiting.. */ |
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 046d5e660c04..3cf31ee59aac 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c | |||
| @@ -225,6 +225,11 @@ int omap_plane_mode_set(struct drm_plane *plane, | |||
| 225 | omap_plane->apply_done_cb.arg = arg; | 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 | plane->fb = fb; | 233 | plane->fb = fb; |
| 229 | plane->crtc = crtc; | 234 | plane->crtc = crtc; |
| 230 | 235 | ||
| @@ -241,10 +246,13 @@ static int omap_plane_update(struct drm_plane *plane, | |||
| 241 | struct omap_plane *omap_plane = to_omap_plane(plane); | 246 | struct omap_plane *omap_plane = to_omap_plane(plane); |
| 242 | omap_plane->enabled = true; | 247 | omap_plane->enabled = true; |
| 243 | 248 | ||
| 244 | if (plane->fb) | 249 | /* omap_plane_mode_set() takes adjusted src */ |
| 245 | drm_framebuffer_unreference(plane->fb); | 250 | switch (omap_plane->win.rotation & 0xf) { |
| 246 | 251 | case BIT(DRM_ROTATE_90): | |
| 247 | drm_framebuffer_reference(fb); | 252 | case BIT(DRM_ROTATE_270): |
| 253 | swap(src_w, src_h); | ||
| 254 | break; | ||
| 255 | } | ||
| 248 | 256 | ||
| 249 | return omap_plane_mode_set(plane, crtc, fb, | 257 | return omap_plane_mode_set(plane, crtc, fb, |
| 250 | crtc_x, crtc_y, crtc_w, crtc_h, | 258 | crtc_x, crtc_y, crtc_w, crtc_h, |
