video: ipu_disp: wait for DP SF end irq when disabling sync BG flows
authorLiu Ying <Ying.Liu@freescale.com>
Fri, 28 Feb 2014 07:12:25 +0000 (15:12 +0800)
committerAnatolij Gustschin <agust@denx.de>
Mon, 11 Aug 2014 15:31:41 +0000 (17:31 +0200)
Instead of waiting for DC triple buffer to be cleared, this patch
changes to wait for a relevant DP sync flow end interrupt to come
when disabling sync BG flows.  In this way, we align the implement
to the freescale internal IPUv3 driver.  After applying this patch,
an uboot hang up issue at the arch_preboot_os() stage, where we
disable a relevant ipu display channel, is not observed any more on
some MX6DL platforms.

Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
drivers/video/ipu.h
drivers/video/ipu_disp.c
drivers/video/ipu_regs.h

index 3d2741f223eeffbf33deb8796bfd2ec162612991..091b58fb47bfccfa4bc30bfdd9e87006bbafa438 100644 (file)
@@ -175,6 +175,14 @@ typedef union {
        } mem_dp_fg_sync;
 } ipu_channel_params_t;
 
+/*
+ * Enumeration of IPU interrupts.
+ */
+enum ipu_irq_line {
+       IPU_IRQ_DP_SF_END = 448 + 3,
+       IPU_IRQ_DC_FC_1 = 448 + 9,
+};
+
 /*
  * Bitfield of Display Interface signal polarities.
  */
index cefd2dc14a2ebbcd9b6c91228da3fb361b8fc05d..bf39a517fa48b3f9973dda8963ba724b2c36c788 100644 (file)
@@ -666,13 +666,16 @@ void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap)
        uint32_t csc;
        uint32_t dc_chan = 0;
        int timeout = 50;
+       int irq = 0;
 
        dc_swap = swap;
 
        if (channel == MEM_DC_SYNC) {
                dc_chan = 1;
+               irq = IPU_IRQ_DC_FC_1;
        } else if (channel == MEM_BG_SYNC) {
                dc_chan = 5;
+               irq = IPU_IRQ_DP_SF_END;
        } else if (channel == MEM_FG_SYNC) {
                /* Disable FG channel */
                dc_chan = 5;
@@ -723,25 +726,11 @@ void ipu_dp_dc_disable(ipu_channel_t channel, unsigned char swap)
                reg ^= DC_WR_CH_CONF_PROG_DI_ID;
                __raw_writel(reg, DC_WR_CH_CONF(dc_chan));
        } else {
-               timeout = 50;
-
-               /* Wait for DC triple buffer to empty */
-               if (g_dc_di_assignment[dc_chan] == 0)
-                       while ((__raw_readl(DC_STAT) & 0x00000002)
-                               != 0x00000002) {
-                               udelay(2000);
-                               timeout -= 2;
-                               if (timeout <= 0)
-                                       break;
-                       }
-               else if (g_dc_di_assignment[dc_chan] == 1)
-                       while ((__raw_readl(DC_STAT) & 0x00000020)
-                               != 0x00000020) {
-                               udelay(2000);
-                               timeout -= 2;
-                               if (timeout <= 0)
-                                       break;
-                       }
+               /* Make sure that we leave at the irq starting edge */
+               __raw_writel(IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
+               do {
+                       reg = __raw_readl(IPUIRQ_2_STATREG(irq));
+               } while (!(reg & IPUIRQ_2_MASK(irq)));
 
                reg = __raw_readl(DC_WR_CH_CONF(dc_chan));
                reg &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
index 21e9c99e0e637b68e1c834e16189f7694d72b961..c2c134a7de0738beca41c7b871c0869d5f6fe031 100644 (file)
@@ -313,9 +313,12 @@ struct ipu_dmfc {
 
 #define IPU_STAT               ((struct ipu_stat *)(IPU_CTRL_BASE_ADDR + \
                                IPU_STAT_REG_BASE))
+#define IPU_INT_STAT(n)                (&IPU_STAT->int_stat[(n) - 1])
 #define IPU_CHA_CUR_BUF(ch)    (&IPU_STAT->cur_buf[ch / 32])
 #define IPU_CHA_BUF0_RDY(ch)   (&IPU_STAT->ch_buf0_rdy[ch / 32])
 #define IPU_CHA_BUF1_RDY(ch)   (&IPU_STAT->ch_buf1_rdy[ch / 32])
+#define IPUIRQ_2_STATREG(irq)  (IPU_INT_STAT(1) + ((irq) / 32))
+#define IPUIRQ_2_MASK(irq)     (1UL << ((irq) & 0x1F))
 
 #define IPU_INT_CTRL(n)                (&IPU_CM_REG->int_ctrl[(n) - 1])