aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2012-10-10 05:48:31 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2012-10-18 06:11:13 -0400
commitb111224900ed743cc5a5f4feafdc910b9e8e736c (patch)
tree9c015352f19594800c0fabe1227f6cd39d7037c7 /drivers/video
parentcb699200af1626a4c718018f28b7737bf56496e5 (diff)
OMAPDSS: DISPC: cleanup lcd/digit enable/disable
We currently have a single function to enable and disable the manager output for LCD and DIGIT. The functions are a bit complex, as handling both enable and disable require some extra steps to ensure that the output is enabled or disabled properly without errors before exiting the function. The code can be made simpler to understand by splitting the functions into separate enable and disable functions. We'll also clean up the comments and some parameter names at the same time. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video')
-rw-r--r--drivers/video/omap2/dss/apply.c6
-rw-r--r--drivers/video/omap2/dss/dispc.c184
-rw-r--r--drivers/video/omap2/dss/dss.h3
3 files changed, 122 insertions, 71 deletions
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c
index 7cdc09641b1f..7a61a2f7765d 100644
--- a/drivers/video/omap2/dss/apply.c
+++ b/drivers/video/omap2/dss/apply.c
@@ -772,7 +772,7 @@ void dss_mgr_start_update(struct omap_overlay_manager *mgr)
772 if (!dss_data.irq_enabled && need_isr()) 772 if (!dss_data.irq_enabled && need_isr())
773 dss_register_vsync_isr(); 773 dss_register_vsync_isr();
774 774
775 dispc_mgr_enable(mgr->id, true); 775 dispc_mgr_enable(mgr->id);
776 776
777 mgr_clear_shadow_dirty(mgr); 777 mgr_clear_shadow_dirty(mgr);
778 778
@@ -1027,7 +1027,7 @@ int dss_mgr_enable(struct omap_overlay_manager *mgr)
1027 spin_unlock_irqrestore(&data_lock, flags); 1027 spin_unlock_irqrestore(&data_lock, flags);
1028 1028
1029 if (!mgr_manual_update(mgr)) 1029 if (!mgr_manual_update(mgr))
1030 dispc_mgr_enable(mgr->id, true); 1030 dispc_mgr_enable(mgr->id);
1031 1031
1032out: 1032out:
1033 mutex_unlock(&apply_lock); 1033 mutex_unlock(&apply_lock);
@@ -1052,7 +1052,7 @@ void dss_mgr_disable(struct omap_overlay_manager *mgr)
1052 goto out; 1052 goto out;
1053 1053
1054 if (!mgr_manual_update(mgr)) 1054 if (!mgr_manual_update(mgr))
1055 dispc_mgr_enable(mgr->id, false); 1055 dispc_mgr_disable(mgr->id);
1056 1056
1057 spin_lock_irqsave(&data_lock, flags); 1057 spin_lock_irqsave(&data_lock, flags);
1058 1058
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index c50270e0afb4..6dd9eb4a2c5b 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -2589,7 +2589,7 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable)
2589 return 0; 2589 return 0;
2590} 2590}
2591 2591
2592static void dispc_disable_isr(void *data, u32 mask) 2592static void dispc_mgr_disable_isr(void *data, u32 mask)
2593{ 2593{
2594 struct completion *compl = data; 2594 struct completion *compl = data;
2595 complete(compl); 2595 complete(compl);
@@ -2607,122 +2607,172 @@ bool dispc_mgr_is_enabled(enum omap_channel channel)
2607 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); 2607 return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE);
2608} 2608}
2609 2609
2610static void dispc_mgr_enable_lcd_out(enum omap_channel channel, bool enable) 2610static void dispc_mgr_enable_lcd_out(enum omap_channel channel)
2611{ 2611{
2612 struct completion frame_done_completion; 2612 _enable_mgr_out(channel, true);
2613 bool is_on; 2613}
2614
2615static void dispc_mgr_disable_lcd_out(enum omap_channel channel)
2616{
2617 DECLARE_COMPLETION_ONSTACK(framedone_compl);
2614 int r; 2618 int r;
2615 u32 irq; 2619 u32 irq;
2616 2620
2617 /* When we disable LCD output, we need to wait until frame is done. 2621 if (dispc_mgr_is_enabled(channel) == false)
2618 * Otherwise the DSS is still working, and turning off the clocks 2622 return;
2619 * prevents DSS from going to OFF mode */
2620 is_on = dispc_mgr_is_enabled(channel);
2621 2623
2622 irq = mgr_desc[channel].framedone_irq; 2624 /*
2625 * When we disable LCD output, we need to wait for FRAMEDONE to know
2626 * that DISPC has finished with the LCD output.
2627 */
2623 2628
2624 if (!enable && is_on) { 2629 irq = dispc_mgr_get_framedone_irq(channel);
2625 init_completion(&frame_done_completion);
2626 2630
2627 r = omap_dispc_register_isr(dispc_disable_isr, 2631 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
2628 &frame_done_completion, irq); 2632 irq);
2633 if (r)
2634 DSSERR("failed to register FRAMEDONE isr\n");
2629 2635
2630 if (r) 2636 _enable_mgr_out(channel, false);
2631 DSSERR("failed to register FRAMEDONE isr\n"); 2637
2638 /* if we couldn't register for framedone, just sleep and exit */
2639 if (r) {
2640 msleep(100);
2641 return;
2632 } 2642 }
2633 2643
2634 _enable_mgr_out(channel, enable); 2644 if (!wait_for_completion_timeout(&framedone_compl,
2645 msecs_to_jiffies(100)))
2646 DSSERR("timeout waiting for FRAME DONE\n");
2635 2647
2636 if (!enable && is_on) { 2648 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
2637 if (!wait_for_completion_timeout(&frame_done_completion, 2649 irq);
2638 msecs_to_jiffies(100))) 2650 if (r)
2639 DSSERR("timeout waiting for FRAME DONE\n"); 2651 DSSERR("failed to unregister FRAMEDONE isr\n");
2652}
2640 2653
2641 r = omap_dispc_unregister_isr(dispc_disable_isr, 2654static void dispc_digit_out_enable_isr(void *data, u32 mask)
2642 &frame_done_completion, irq); 2655{
2656 struct completion *compl = data;
2643 2657
2644 if (r) 2658 /* ignore any sync lost interrupts */
2645 DSSERR("failed to unregister FRAMEDONE isr\n"); 2659 if (mask & (DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD))
2660 complete(compl);
2661}
2662
2663static void dispc_mgr_enable_digit_out(void)
2664{
2665 DECLARE_COMPLETION_ONSTACK(vsync_compl);
2666 int r;
2667 u32 irq_mask;
2668
2669 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == true)
2670 return;
2671
2672 /*
2673 * Digit output produces some sync lost interrupts during the first
2674 * frame when enabling. Those need to be ignored, so we register for the
2675 * sync lost irq to prevent the error handler from triggering.
2676 */
2677
2678 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT) |
2679 dispc_mgr_get_sync_lost_irq(OMAP_DSS_CHANNEL_DIGIT);
2680
2681 r = omap_dispc_register_isr(dispc_digit_out_enable_isr, &vsync_compl,
2682 irq_mask);
2683 if (r) {
2684 DSSERR("failed to register %x isr\n", irq_mask);
2685 return;
2646 } 2686 }
2687
2688 _enable_mgr_out(OMAP_DSS_CHANNEL_DIGIT, true);
2689
2690 /* wait for the first evsync */
2691 if (!wait_for_completion_timeout(&vsync_compl, msecs_to_jiffies(100)))
2692 DSSERR("timeout waiting for digit out to start\n");
2693
2694 r = omap_dispc_unregister_isr(dispc_digit_out_enable_isr, &vsync_compl,
2695 irq_mask);
2696 if (r)
2697 DSSERR("failed to unregister %x isr\n", irq_mask);
2647} 2698}
2648 2699
2649static void dispc_mgr_enable_digit_out(bool enable) 2700static void dispc_mgr_disable_digit_out(void)
2650{ 2701{
2651 struct completion frame_done_completion; 2702 DECLARE_COMPLETION_ONSTACK(framedone_compl);
2652 enum dss_hdmi_venc_clk_source_select src; 2703 enum dss_hdmi_venc_clk_source_select src;
2653 int r, i; 2704 int r, i;
2654 u32 irq_mask; 2705 u32 irq_mask;
2655 int num_irqs; 2706 int num_irqs;
2656 2707
2657 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == enable) 2708 if (dispc_mgr_is_enabled(OMAP_DSS_CHANNEL_DIGIT) == false)
2658 return; 2709 return;
2659 2710
2660 src = dss_get_hdmi_venc_clk_source(); 2711 src = dss_get_hdmi_venc_clk_source();
2661 2712
2662 if (enable) { 2713 /*
2663 unsigned long flags; 2714 * When we disable the digit output, we need to wait for FRAMEDONE to
2664 /* When we enable digit output, we'll get an extra digit 2715 * know that DISPC has finished with the output. For analog tv out we'll
2665 * sync lost interrupt, that we need to ignore */ 2716 * use vsync, as omap2/3 don't have framedone for TV.
2666 spin_lock_irqsave(&dispc.irq_lock, flags); 2717 */
2667 dispc.irq_error_mask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
2668 _omap_dispc_set_irqs();
2669 spin_unlock_irqrestore(&dispc.irq_lock, flags);
2670 }
2671
2672 /* When we disable digit output, we need to wait until fields are done.
2673 * Otherwise the DSS is still working, and turning off the clocks
2674 * prevents DSS from going to OFF mode. And when enabling, we need to
2675 * wait for the extra sync losts */
2676 init_completion(&frame_done_completion);
2677 2718
2678 if (src == DSS_HDMI_M_PCLK && enable == false) { 2719 if (src == DSS_HDMI_M_PCLK) {
2679 irq_mask = DISPC_IRQ_FRAMEDONETV; 2720 irq_mask = DISPC_IRQ_FRAMEDONETV;
2680 num_irqs = 1; 2721 num_irqs = 1;
2681 } else { 2722 } else {
2682 irq_mask = DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD; 2723 irq_mask = dispc_mgr_get_vsync_irq(OMAP_DSS_CHANNEL_DIGIT);
2683 /* XXX I understand from TRM that we should only wait for the 2724 /*
2684 * current field to complete. But it seems we have to wait for 2725 * We need to wait for both even and odd vsyncs. Note that this
2685 * both fields */ 2726 * is not totally reliable, as we could get a vsync interrupt
2727 * before we disable the output, which leads to timeout in the
2728 * wait_for_completion.
2729 */
2686 num_irqs = 2; 2730 num_irqs = 2;
2687 } 2731 }
2688 2732
2689 r = omap_dispc_register_isr(dispc_disable_isr, &frame_done_completion, 2733 r = omap_dispc_register_isr(dispc_mgr_disable_isr, &framedone_compl,
2690 irq_mask); 2734 irq_mask);
2691 if (r) 2735 if (r)
2692 DSSERR("failed to register %x isr\n", irq_mask); 2736 DSSERR("failed to register %x isr\n", irq_mask);
2693 2737
2694 _enable_mgr_out(OMAP_DSS_CHANNEL_DIGIT, enable); 2738 _enable_mgr_out(OMAP_DSS_CHANNEL_DIGIT, false);
2739
2740 /* if we couldn't register the irq, just sleep and exit */
2741 if (r) {
2742 msleep(100);
2743 return;
2744 }
2695 2745
2696 for (i = 0; i < num_irqs; ++i) { 2746 for (i = 0; i < num_irqs; ++i) {
2697 if (!wait_for_completion_timeout(&frame_done_completion, 2747 if (!wait_for_completion_timeout(&framedone_compl,
2698 msecs_to_jiffies(100))) 2748 msecs_to_jiffies(100)))
2699 DSSERR("timeout waiting for digit out to %s\n", 2749 DSSERR("timeout waiting for digit out to stop\n");
2700 enable ? "start" : "stop");
2701 } 2750 }
2702 2751
2703 r = omap_dispc_unregister_isr(dispc_disable_isr, &frame_done_completion, 2752 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr, &framedone_compl,
2704 irq_mask); 2753 irq_mask);
2705 if (r) 2754 if (r)
2706 DSSERR("failed to unregister %x isr\n", irq_mask); 2755 DSSERR("failed to unregister %x isr\n", irq_mask);
2756}
2707 2757
2708 if (enable) { 2758void dispc_mgr_enable(enum omap_channel channel)
2709 unsigned long flags; 2759{
2710 spin_lock_irqsave(&dispc.irq_lock, flags); 2760 if (dss_mgr_is_lcd(channel))
2711 dispc.irq_error_mask |= DISPC_IRQ_SYNC_LOST_DIGIT; 2761 dispc_mgr_enable_lcd_out(channel);
2712 dispc_write_reg(DISPC_IRQSTATUS, DISPC_IRQ_SYNC_LOST_DIGIT); 2762 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
2713 _omap_dispc_set_irqs(); 2763 dispc_mgr_enable_digit_out();
2714 spin_unlock_irqrestore(&dispc.irq_lock, flags); 2764 else
2715 } 2765 WARN_ON(1);
2716} 2766}
2717 2767
2718void dispc_mgr_enable(enum omap_channel channel, bool enable) 2768void dispc_mgr_disable(enum omap_channel channel)
2719{ 2769{
2720 if (dss_mgr_is_lcd(channel)) 2770 if (dss_mgr_is_lcd(channel))
2721 dispc_mgr_enable_lcd_out(channel, enable); 2771 dispc_mgr_disable_lcd_out(channel);
2722 else if (channel == OMAP_DSS_CHANNEL_DIGIT) 2772 else if (channel == OMAP_DSS_CHANNEL_DIGIT)
2723 dispc_mgr_enable_digit_out(enable); 2773 dispc_mgr_disable_digit_out();
2724 else 2774 else
2725 BUG(); 2775 WARN_ON(1);
2726} 2776}
2727 2777
2728void dispc_wb_enable(bool enable) 2778void dispc_wb_enable(bool enable)
@@ -2739,7 +2789,7 @@ void dispc_wb_enable(bool enable)
2739 if (!enable && is_on) { 2789 if (!enable && is_on) {
2740 init_completion(&frame_done_completion); 2790 init_completion(&frame_done_completion);
2741 2791
2742 r = omap_dispc_register_isr(dispc_disable_isr, 2792 r = omap_dispc_register_isr(dispc_mgr_disable_isr,
2743 &frame_done_completion, irq); 2793 &frame_done_completion, irq);
2744 if (r) 2794 if (r)
2745 DSSERR("failed to register FRAMEDONEWB isr\n"); 2795 DSSERR("failed to register FRAMEDONEWB isr\n");
@@ -2752,7 +2802,7 @@ void dispc_wb_enable(bool enable)
2752 msecs_to_jiffies(100))) 2802 msecs_to_jiffies(100)))
2753 DSSERR("timeout waiting for FRAMEDONEWB\n"); 2803 DSSERR("timeout waiting for FRAMEDONEWB\n");
2754 2804
2755 r = omap_dispc_unregister_isr(dispc_disable_isr, 2805 r = omap_dispc_unregister_isr(dispc_mgr_disable_isr,
2756 &frame_done_completion, irq); 2806 &frame_done_completion, irq);
2757 if (r) 2807 if (r)
2758 DSSERR("failed to unregister FRAMEDONEWB isr\n"); 2808 DSSERR("failed to unregister FRAMEDONEWB isr\n");
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h
index bf9b7a4c5065..fb891656f1f8 100644
--- a/drivers/video/omap2/dss/dss.h
+++ b/drivers/video/omap2/dss/dss.h
@@ -438,7 +438,8 @@ u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel);
438bool dispc_mgr_go_busy(enum omap_channel channel); 438bool dispc_mgr_go_busy(enum omap_channel channel);
439void dispc_mgr_go(enum omap_channel channel); 439void dispc_mgr_go(enum omap_channel channel);
440bool dispc_mgr_is_enabled(enum omap_channel channel); 440bool dispc_mgr_is_enabled(enum omap_channel channel);
441void dispc_mgr_enable(enum omap_channel channel, bool enable); 441void dispc_mgr_enable(enum omap_channel channel);
442void dispc_mgr_disable(enum omap_channel channel);
442bool dispc_mgr_is_channel_enabled(enum omap_channel channel); 443bool dispc_mgr_is_channel_enabled(enum omap_channel channel);
443void dispc_mgr_set_lcd_config(enum omap_channel channel, 444void dispc_mgr_set_lcd_config(enum omap_channel channel,
444 const struct dss_lcd_mgr_config *config); 445 const struct dss_lcd_mgr_config *config);