diff options
Diffstat (limited to 'drivers/mxc')
-rw-r--r-- | drivers/mxc/ipu3/ipu_common.c | 77 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_prv.h | 2 |
2 files changed, 57 insertions, 22 deletions
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c index c3b09da5b2f2..d837cf4140dd 100644 --- a/drivers/mxc/ipu3/ipu_common.c +++ b/drivers/mxc/ipu3/ipu_common.c @@ -504,6 +504,8 @@ int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params) if (g_channel_init_mask & (1L << IPU_CHAN_ID(channel))) { dev_err(g_ipu_dev, "Warning: channel already initialized %d\n", IPU_CHAN_ID(channel)); + ret = -EINVAL; + goto err; } ipu_conf = __raw_readl(IPU_CONF); @@ -743,7 +745,8 @@ int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params) break; default: dev_err(g_ipu_dev, "Missing channel initialization\n"); - break; + ret = -EINVAL; + goto err; } /* Enable IPU sub module */ @@ -769,9 +772,12 @@ void ipu_uninit_channel(ipu_channel_t channel) uint32_t in_dma, out_dma = 0; uint32_t ipu_conf; + spin_lock_irqsave(&ipu_lock, lock_flags); + if ((g_channel_init_mask & (1L << IPU_CHAN_ID(channel))) == 0) { dev_err(g_ipu_dev, "Channel already uninitialized %d\n", IPU_CHAN_ID(channel)); + spin_unlock_irqrestore(&ipu_lock, lock_flags); return; } @@ -785,11 +791,10 @@ void ipu_uninit_channel(ipu_channel_t channel) dev_err(g_ipu_dev, "Channel %d is not disabled, disable first\n", IPU_CHAN_ID(channel)); + spin_unlock_irqrestore(&ipu_lock, lock_flags); return; } - spin_lock_irqsave(&ipu_lock, lock_flags); - ipu_conf = __raw_readl(IPU_CONF); /* Reset the double buffer */ @@ -1894,6 +1899,34 @@ void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type, } EXPORT_SYMBOL(ipu_clear_buffer_ready); +void _ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type, + uint32_t bufNum) +{ + uint32_t dma_ch = channel_2_dma(channel, type); + + if (!idma_is_valid(dma_ch)) + return; + + __raw_writel(0xF0300000, IPU_GPR); /* write one to clear */ + if (bufNum == 0) { + if (idma_is_set(IPU_CHA_BUF0_RDY, dma_ch)) { + __raw_writel(idma_mask(dma_ch), + IPU_CHA_BUF0_RDY(dma_ch)); + } + } else if (bufNum == 1) { + if (idma_is_set(IPU_CHA_BUF1_RDY, dma_ch)) { + __raw_writel(idma_mask(dma_ch), + IPU_CHA_BUF1_RDY(dma_ch)); + } + } else { + if (idma_is_set(IPU_CHA_BUF2_RDY, dma_ch)) { + __raw_writel(idma_mask(dma_ch), + IPU_CHA_BUF2_RDY(dma_ch)); + } + } + __raw_writel(0x0, IPU_GPR); /* write one to set */ +} + static irqreturn_t disable_chan_irq_handler(int irq, void *dev_id) { struct completion *comp = dev_id; @@ -2063,29 +2096,29 @@ int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop) __raw_writel(idma_mask(thrd_dma), IPU_CHA_CUR_BUF(thrd_dma)); } - g_channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel)); - - spin_unlock_irqrestore(&ipu_lock, lock_flags); - /* Set channel buffers NOT to be ready */ if (idma_is_valid(in_dma)) { - ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 0); - ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 1); - ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 2); + _ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 0); + _ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 1); + _ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 2); } if (idma_is_valid(out_dma)) { - ipu_clear_buffer_ready(channel, IPU_OUTPUT_BUFFER, 0); - ipu_clear_buffer_ready(channel, IPU_OUTPUT_BUFFER, 1); + _ipu_clear_buffer_ready(channel, IPU_OUTPUT_BUFFER, 0); + _ipu_clear_buffer_ready(channel, IPU_OUTPUT_BUFFER, 1); } if (g_sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) { - ipu_clear_buffer_ready(channel, IPU_GRAPH_IN_BUFFER, 0); - ipu_clear_buffer_ready(channel, IPU_GRAPH_IN_BUFFER, 1); + _ipu_clear_buffer_ready(channel, IPU_GRAPH_IN_BUFFER, 0); + _ipu_clear_buffer_ready(channel, IPU_GRAPH_IN_BUFFER, 1); } if (g_thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) { - ipu_clear_buffer_ready(channel, IPU_ALPHA_IN_BUFFER, 0); - ipu_clear_buffer_ready(channel, IPU_ALPHA_IN_BUFFER, 1); + _ipu_clear_buffer_ready(channel, IPU_ALPHA_IN_BUFFER, 0); + _ipu_clear_buffer_ready(channel, IPU_ALPHA_IN_BUFFER, 1); } + g_channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel)); + + spin_unlock_irqrestore(&ipu_lock, lock_flags); + return 0; } EXPORT_SYMBOL(ipu_disable_channel); @@ -2464,14 +2497,14 @@ int32_t ipu_swap_channel(ipu_channel_t from_ch, ipu_channel_t to_ch) __raw_writel(tri_cur_buf_mask(from_dma), IPU_CHA_TRIPLE_CUR_BUF(from_dma)); + _ipu_clear_buffer_ready(from_ch, IPU_VIDEO_IN_BUFFER, 0); + _ipu_clear_buffer_ready(from_ch, IPU_VIDEO_IN_BUFFER, 1); + _ipu_clear_buffer_ready(from_ch, IPU_VIDEO_IN_BUFFER, 2); + g_channel_enable_mask &= ~(1L << IPU_CHAN_ID(from_ch)); spin_unlock_irqrestore(&ipu_lock, lock_flags); - ipu_clear_buffer_ready(from_ch, IPU_VIDEO_IN_BUFFER, 0); - ipu_clear_buffer_ready(from_ch, IPU_VIDEO_IN_BUFFER, 1); - ipu_clear_buffer_ready(from_ch, IPU_VIDEO_IN_BUFFER, 2); - return 0; } EXPORT_SYMBOL(ipu_swap_channel); @@ -2560,6 +2593,8 @@ EXPORT_SYMBOL(ipu_set_csc_coefficients); static int ipu_suspend(struct platform_device *pdev, pm_message_t state) { if (g_ipu_clk_enabled) { + uint32_t chan_should_disable, timeout = 1000, time = 0; + /* save and disable enabled channels*/ idma_enable_reg[0] = __raw_readl(IDMAC_CHA_EN(0)); idma_enable_reg[1] = __raw_readl(IDMAC_CHA_EN(32)); @@ -2567,8 +2602,6 @@ static int ipu_suspend(struct platform_device *pdev, pm_message_t state) || (__raw_readl(IDMAC_CHA_BUSY(32)) & idma_enable_reg[1])) { /* disable channel not busy already */ - uint32_t chan_should_disable, timeout = 1000, time = 0; - chan_should_disable = __raw_readl(IDMAC_CHA_BUSY(0)) ^ idma_enable_reg[0]; diff --git a/drivers/mxc/ipu3/ipu_prv.h b/drivers/mxc/ipu3/ipu_prv.h index ec27264c47e3..df55b1c8c1f7 100644 --- a/drivers/mxc/ipu3/ipu_prv.h +++ b/drivers/mxc/ipu3/ipu_prv.h @@ -99,5 +99,7 @@ void _ipu_csi_ccir_err_detection_disable(uint32_t csi); void _ipu_smfc_init(ipu_channel_t channel, uint32_t mipi_id, uint32_t csi); void _ipu_smfc_set_burst_size(ipu_channel_t channel, uint32_t bs); void _ipu_dp_set_csc_coefficients(ipu_channel_t channel, int32_t param[][3]); +void _ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type, + uint32_t bufNum); #endif /* __INCLUDE_IPU_PRV_H__ */ |