aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2014-04-02 04:37:06 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2014-04-14 05:34:14 -0400
commit2ec8e3787ae6957f738bb133e755213b9d7c066e (patch)
tree47ec00c3ca196eeea817c8eab277f1952dbd973b /drivers/gpu
parentc9eaa447e77efe77b7fa4c953bd62de8297fd6c5 (diff)
drm/omap: fix output enable/disable sequence
At the moment it's quite easy to get the following errors when the HDMI output is enabled or disabled: [drm:omap_crtc_error_irq] *ERROR* tv: errors: 00008000 The reason for the errors is that the omapdrm driver doesn't properly handle the sync-lost irqs that happen when enabling the DIGIT crtc, which is used for HDMI and analog TV. The driver does disable the sync-lost irq properly, but it fails to wait until the output has been fully enabled (i.e. the first vsync), so the sync-lost errors are still seen occasionally. This patch makes the omapdrm act the same way as the omapfb does: - When enabling a display, we'll wait for the first vsync. - When disabling a display, we'll wait for framedone if available, or odd and even vsyncs. These changes make sure the output is fully enabled or disabled at the end of the function. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com> Reported-by: Sanjay Singh Rawat <sanjay.rawat@linaro.org> Reviewed-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_crtc.c46
1 files changed, 27 insertions, 19 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index 355157e4f78d..0acbe62901d9 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -528,38 +528,46 @@ static void set_enabled(struct drm_crtc *crtc, bool enable)
528 struct drm_device *dev = crtc->dev; 528 struct drm_device *dev = crtc->dev;
529 struct omap_crtc *omap_crtc = to_omap_crtc(crtc); 529 struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
530 enum omap_channel channel = omap_crtc->channel; 530 enum omap_channel channel = omap_crtc->channel;
531 struct omap_irq_wait *wait = NULL; 531 struct omap_irq_wait *wait;
532 u32 framedone_irq, vsync_irq;
533 int ret;
532 534
533 if (dispc_mgr_is_enabled(channel) == enable) 535 if (dispc_mgr_is_enabled(channel) == enable)
534 return; 536 return;
535 537
536 /* ignore sync-lost irqs during enable/disable */ 538 /*
539 * Digit output produces some sync lost interrupts during the first
540 * frame when enabling, so we need to ignore those.
541 */
537 omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); 542 omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
538 543
539 if (dispc_mgr_get_framedone_irq(channel)) { 544 framedone_irq = dispc_mgr_get_framedone_irq(channel);
540 if (!enable) { 545 vsync_irq = dispc_mgr_get_vsync_irq(channel);
541 wait = omap_irq_wait_init(dev, 546
542 dispc_mgr_get_framedone_irq(channel), 1); 547 if (enable) {
543 } 548 wait = omap_irq_wait_init(dev, vsync_irq, 1);
544 } else { 549 } else {
545 /* 550 /*
546 * When we disable digit output, we need to wait until fields 551 * When we disable the digit output, we need to wait for
547 * are done. Otherwise the DSS is still working, and turning 552 * FRAMEDONE to know that DISPC has finished with the output.
548 * off the clocks prevents DSS from going to OFF mode. And when 553 *
549 * enabling, we need to wait for the extra sync losts 554 * OMAP2/3 does not have FRAMEDONE irq for digit output, and in
555 * that case we need to use vsync interrupt, and wait for both
556 * even and odd frames.
550 */ 557 */
551 wait = omap_irq_wait_init(dev, 558
552 dispc_mgr_get_vsync_irq(channel), 2); 559 if (framedone_irq)
560 wait = omap_irq_wait_init(dev, framedone_irq, 1);
561 else
562 wait = omap_irq_wait_init(dev, vsync_irq, 2);
553 } 563 }
554 564
555 dispc_mgr_enable(channel, enable); 565 dispc_mgr_enable(channel, enable);
556 566
557 if (wait) { 567 ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
558 int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); 568 if (ret) {
559 if (ret) { 569 dev_err(dev->dev, "%s: timeout waiting for %s\n",
560 dev_err(dev->dev, "%s: timeout waiting for %s\n", 570 omap_crtc->name, enable ? "enable" : "disable");
561 omap_crtc->name, enable ? "enable" : "disable");
562 }
563 } 571 }
564 572
565 omap_irq_register(crtc->dev, &omap_crtc->error_irq); 573 omap_irq_register(crtc->dev, &omap_crtc->error_irq);