diff options
author | Quinn Jensen <quinn.jensen@freescale.com> | 2007-10-24 21:25:50 -0600 |
---|---|---|
committer | Quinn Jensen <quinn.jensen@freescale.com> | 2007-10-24 21:25:50 -0600 |
commit | d1ac43b861f163ae029de46059972802586ecb68 (patch) | |
tree | 79b780b813e4dfcbaa6f48987d2698120ad2e972 | |
parent | 911eb62722a75d3e133c54aaa02d0700f5f924db (diff) |
CR ENGR00013463 IPU: wait for SDC flips to finish on disable
Patch for CR ENGR00013463 IPU: wait for SDC flips to finish on disable.
This patch makes sure SDC buffer flips complete before disabling the
channel. Applies to linux 2.6.22 kernel on MX platforms.
http://www.bitshrine.org/gpp/linux-2.6.22-mx-CR-ENGR00013463-IPU-wait-for-SDC-flips-to-.patch
-rw-r--r-- | drivers/mxc/ipu/ipu_common.c | 60 | ||||
-rw-r--r-- | drivers/video/mxc/mxcfb.c | 1 |
2 files changed, 33 insertions, 28 deletions
diff --git a/drivers/mxc/ipu/ipu_common.c b/drivers/mxc/ipu/ipu_common.c index 6abe712c5ba3..8de829573540 100644 --- a/drivers/mxc/ipu/ipu_common.c +++ b/drivers/mxc/ipu/ipu_common.c @@ -1121,6 +1121,9 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop) uint32_t in_dma; uint32_t out_dma; uint32_t chan_mask = 0; + uint32_t timeout; + uint32_t eof_intr; + uint32_t enabled; /* Get input and output dma channels */ out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER); @@ -1134,7 +1137,7 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop) chan_mask |= 1UL << sec_dma; if (wait_for_stop && channel != MEM_SDC_FG && channel != MEM_SDC_BG) { - uint32_t timeout = 40; + timeout = 40; while ((__raw_readl(IDMAC_CHA_BUSY) & chan_mask) || (_ipu_channel_status(channel) == TASK_STAT_ACTIVE)) { timeout--; @@ -1155,37 +1158,38 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop) dev_dbg(g_ipu_dev, "timeout = %d * 10ms\n", 40 - timeout); } /* SDC BG and FG must be disabled before DMA is disabled */ - if (channel == MEM_SDC_BG) { - uint32_t timeout = 5; - spin_lock_irqsave(&ipu_lock, lock_flags); - ipu_clear_irq(IPU_IRQ_SDC_BG_EOF); - if (_ipu_sdc_bg_uninit() && wait_for_stop) { - spin_unlock_irqrestore(&ipu_lock, lock_flags); - - while (!ipu_get_irq_status(IPU_IRQ_SDC_BG_EOF)) { - msleep(5); - timeout--; - if (timeout == 0) - break; - } - } else { - spin_unlock_irqrestore(&ipu_lock, lock_flags); + if ((channel == MEM_SDC_BG) || (channel == MEM_SDC_FG)) { + + if (channel == MEM_SDC_BG) + eof_intr = IPU_IRQ_SDC_BG_EOF; + else + eof_intr = IPU_IRQ_SDC_FG_EOF; + + /* Wait for any buffer flips to finsh */ + timeout = 4; + while (timeout && + ((__raw_readl(IPU_CHA_BUF0_RDY) & chan_mask) || + (__raw_readl(IPU_CHA_BUF1_RDY) & chan_mask))) { + msleep(10); + timeout--; } - } else if (channel == MEM_SDC_FG) { - uint32_t timeout = 5; + spin_lock_irqsave(&ipu_lock, lock_flags); - ipu_clear_irq(IPU_IRQ_SDC_FG_EOF); - if (_ipu_sdc_fg_uninit() && wait_for_stop) { - spin_unlock_irqrestore(&ipu_lock, lock_flags); + ipu_clear_irq(eof_intr); + if (channel == MEM_SDC_BG) + enabled = _ipu_sdc_bg_uninit(); + else + enabled = _ipu_sdc_fg_uninit(); + spin_unlock_irqrestore(&ipu_lock, lock_flags); - while (!ipu_get_irq_status(IPU_IRQ_SDC_FG_EOF)) { - msleep(5); - timeout--; - if (timeout == 0) - break; - } + if (enabled && wait_for_stop) { + timeout = 5; } else { - spin_unlock_irqrestore(&ipu_lock, lock_flags); + timeout = 0; + } + while (timeout && !ipu_get_irq_status(eof_intr)) { + msleep(5); + timeout--; } } diff --git a/drivers/video/mxc/mxcfb.c b/drivers/video/mxc/mxcfb.c index 1a473b739424..0622974a92ec 100644 --- a/drivers/video/mxc/mxcfb.c +++ b/drivers/video/mxc/mxcfb.c @@ -179,6 +179,7 @@ static int mxcfb_set_par(struct fb_info *fbi) ipu_disable_irq(mxc_fbi->ipu_ch_irq); ipu_disable_channel(mxc_fbi->ipu_ch, true); + ipu_uninit_channel(mxc_fbi->ipu_ch); ipu_clear_irq(mxc_fbi->ipu_ch_irq); mxcfb_set_fix(fbi); |