summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <Ying.Liu@freescale.com>2012-10-10 15:13:30 +0800
committerLiu Ying <Ying.liu@freescale.com>2012-10-11 14:42:33 +0800
commitb0b1cfbdee2165f811f9dc680aae133a89c1f8e4 (patch)
tree2cd7457696aecf2d22d0899848ebdefbfa3afaec
parent020ad348c5c6ea039c68e2aa98f28a1e723130bb (diff)
ENGR00227681 IPUv3:Use spinlock to protect buf ready reg
There are several channels' buffer ready bits controlled by a single 32bit register-IPU_CHA_BUFx_RDY. These buffer ready can be write-one-to-set or write-one-to-clear, which is controlled by IPU_GPR register. v4l2 capture driver will touch the buffer ready registers in interrupt context, so, currently, ipu->mutex_lock is bypassed with the context. Then, a race condition is that v4l2 capture driver interrupt context tries to set a channel buffer ready, while, another context tries to disable another channel(clear buffer ready bit), which may cause v4l2 capture driver fails to set buffer ready(SMFC0_FRM_LOST error may happen). This patch uses ipu-> rdy_reg_spin_lock to protect buffer ready registers to fix the race condition issue and rename ipu->spin_lock to ipu-> int_reg_spin_lock. Signed-off-by: Liu Ying <Ying.Liu@freescale.com> (cherry picked from commit d3515529a4be205809356961e58afa660781547b)
-rw-r--r--drivers/mxc/ipu3/ipu_capture.c18
-rw-r--r--drivers/mxc/ipu3/ipu_common.c146
-rw-r--r--drivers/mxc/ipu3/ipu_disp.c34
-rw-r--r--drivers/mxc/ipu3/ipu_prv.h5
4 files changed, 101 insertions, 102 deletions
diff --git a/drivers/mxc/ipu3/ipu_capture.c b/drivers/mxc/ipu3/ipu_capture.c
index 029ab5e9dec7..dae3a7596bc9 100644
--- a/drivers/mxc/ipu3/ipu_capture.c
+++ b/drivers/mxc/ipu3/ipu_capture.c
@@ -125,7 +125,7 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
ipu_csi_write(ipu, csi, data, CSI_SENS_CONF);
@@ -171,7 +171,7 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
} else {
dev_err(ipu->dev, "Unsupported CCIR656 interlaced "
"video mode\n");
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
return -EINVAL;
}
@@ -197,7 +197,7 @@ ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
dev_dbg(ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE));
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
@@ -263,13 +263,13 @@ void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *hei
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
reg = ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE);
*width = (reg & 0xFFFF) + 1;
*height = (reg >> 16 & 0xFFFF) + 1;
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
}
@@ -287,11 +287,11 @@ void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t heigh
{
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
ipu_csi_write(ipu, csi, (width - 1) | (height - 1) << 16, CSI_ACT_FRM_SIZE);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
}
@@ -311,14 +311,14 @@ void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, ui
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
temp &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
temp |= ((top << CSI_VSC_SHIFT) | (left << CSI_HSC_SHIFT));
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
}
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index c8f2983a1bbf..877f2e5a2a9f 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -188,20 +188,6 @@ struct ipu_soc *ipu_get_soc(int id)
}
EXPORT_SYMBOL_GPL(ipu_get_soc);
-void _ipu_lock(struct ipu_soc *ipu)
-{
- /*TODO:remove in_irq() condition after v4l2 driver rewrite*/
- if (!in_irq() && !in_softirq())
- mutex_lock(&ipu->mutex_lock);
-}
-
-void _ipu_unlock(struct ipu_soc *ipu)
-{
- /*TODO:remove in_irq() condition after v4l2 driver rewrite*/
- if (!in_irq() && !in_softirq())
- mutex_unlock(&ipu->mutex_lock);
-}
-
void _ipu_get(struct ipu_soc *ipu)
{
int ret;
@@ -239,7 +225,8 @@ static int __devinit ipu_probe(struct platform_device *pdev)
ipu = &ipu_array[pdev->id];
memset(ipu, 0, sizeof(struct ipu_soc));
- spin_lock_init(&ipu->spin_lock);
+ spin_lock_init(&ipu->int_reg_spin_lock);
+ spin_lock_init(&ipu->rdy_reg_spin_lock);
mutex_init(&ipu->mutex_lock);
g_ipu_hw_rev = plat_data->rev;
@@ -496,7 +483,7 @@ int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
/* Re-enable error interrupts every time a channel is initialized */
ipu_cm_write(ipu, 0xFFFFFFFF, IPU_INT_CTRL(5));
@@ -786,7 +773,7 @@ int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel
ipu_cm_write(ipu, ipu_conf, IPU_CONF);
err:
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return ret;
}
EXPORT_SYMBOL(ipu_init_channel);
@@ -804,12 +791,12 @@ void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
uint32_t ipu_conf;
uint32_t dc_chan = 0;
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
if ((ipu->channel_init_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
dev_dbg(ipu->dev, "Channel already uninitialized %d\n",
IPU_CHAN_ID(channel));
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return;
}
@@ -823,7 +810,7 @@ void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
dev_err(ipu->dev,
"Channel %d is not disabled, disable first\n",
IPU_CHAN_ID(channel));
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return;
}
@@ -1008,7 +995,7 @@ void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel)
if (_ipu_is_primary_disp_chan(in_dma))
clk_disable(&ipu->pixel_clk[ipu->dc_di_assignment[dc_chan]]);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
@@ -1117,7 +1104,7 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
return -EINVAL;
}
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
/* Build parameter memory data for DMA channel */
_ipu_ch_param_init(ipu, dma_chan, pixel_fmt, width, height, stride, u, v, 0,
@@ -1289,7 +1276,7 @@ int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
}
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return 0;
}
@@ -1318,12 +1305,12 @@ int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
uint32_t reg;
int ret = 0;
uint32_t dma_chan = channel_2_dma(channel, type);
+ unsigned long lock_flags;
if (dma_chan == IDMA_CHAN_INVALID)
return -EINVAL;
- _ipu_lock(ipu);
-
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
if (bufNum == 0)
reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan));
else if (bufNum == 1)
@@ -1335,8 +1322,7 @@ int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
_ipu_ch_param_set_buffer(ipu, dma_chan, bufNum, phyaddr);
else
ret = -EACCES;
-
- _ipu_unlock(ipu);
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
return ret;
}
@@ -1368,7 +1354,7 @@ int32_t ipu_set_channel_bandmode(struct ipu_soc *ipu, ipu_channel_t channel,
if ((2 > band_height) || (8 < band_height))
return -EINVAL;
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
reg = ipu_idmac_read(ipu, IDMAC_BAND_EN(dma_chan));
reg |= 1 << (dma_chan % 32);
@@ -1377,7 +1363,7 @@ int32_t ipu_set_channel_bandmode(struct ipu_soc *ipu, ipu_channel_t channel,
_ipu_ch_param_set_bandmode(ipu, dma_chan, band_height);
dev_dbg(ipu->dev, "dma_chan:%d, band_height:%d.\n\n",
dma_chan, 1 << band_height);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return ret;
}
@@ -1429,12 +1415,12 @@ int32_t ipu_update_channel_offset(struct ipu_soc *ipu,
{
int ret = 0;
uint32_t dma_chan = channel_2_dma(channel, type);
+ unsigned long lock_flags;
if (dma_chan == IDMA_CHAN_INVALID)
return -EINVAL;
- _ipu_lock(ipu);
-
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
if ((ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan)) & idma_mask(dma_chan)) ||
(ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(dma_chan)) & idma_mask(dma_chan)) ||
((ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(dma_chan)) & idma_mask(dma_chan)) &&
@@ -1444,8 +1430,8 @@ int32_t ipu_update_channel_offset(struct ipu_soc *ipu,
else
_ipu_ch_offset_update(ipu, dma_chan, pixel_fmt, width, height, stride,
u, v, 0, vertical_offset, horizontal_offset);
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- _ipu_unlock(ipu);
return ret;
}
EXPORT_SYMBOL(ipu_update_channel_offset);
@@ -1468,12 +1454,13 @@ int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
ipu_buffer_t type, uint32_t bufNum)
{
uint32_t dma_chan = channel_2_dma(channel, type);
+ unsigned long lock_flags;
if (dma_chan == IDMA_CHAN_INVALID)
return -EINVAL;
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
/* Mark buffer to be ready. */
- _ipu_lock(ipu);
if (bufNum == 0)
ipu_cm_write(ipu, idma_mask(dma_chan),
IPU_CHA_BUF0_RDY(dma_chan));
@@ -1483,7 +1470,8 @@ int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
else
ipu_cm_write(ipu, idma_mask(dma_chan),
IPU_CHA_BUF2_RDY(dma_chan));
- _ipu_unlock(ipu);
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+
return 0;
}
EXPORT_SYMBOL(ipu_select_buffer);
@@ -1505,14 +1493,16 @@ int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum)
idma_mask(channel_2_dma(MEM_VDI_PRP_VF_MEM_P, IPU_INPUT_BUFFER))|
idma_mask(dma_chan)|
idma_mask(channel_2_dma(MEM_VDI_PRP_VF_MEM_N, IPU_INPUT_BUFFER));
+ unsigned long lock_flags;
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
/* Mark buffers to be ready. */
- _ipu_lock(ipu);
if (bufNum == 0)
ipu_cm_write(ipu, mask_bit, IPU_CHA_BUF0_RDY(dma_chan));
else
ipu_cm_write(ipu, mask_bit, IPU_CHA_BUF1_RDY(dma_chan));
- _ipu_unlock(ipu);
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
+
return 0;
}
EXPORT_SYMBOL(ipu_select_multi_vdi_buffer);
@@ -1550,7 +1540,7 @@ int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel
uint32_t fs_proc_flow3;
uint32_t fs_disp_flow1;
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
@@ -1748,7 +1738,7 @@ int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel
ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
err:
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return retval;
}
EXPORT_SYMBOL(ipu_link_channels);
@@ -1775,7 +1765,7 @@ int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_chann
uint32_t fs_proc_flow3;
uint32_t fs_disp_flow1;
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
fs_proc_flow1 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW1);
fs_proc_flow2 = ipu_cm_read(ipu, IPU_FS_PROC_FLOW2);
@@ -1884,7 +1874,7 @@ int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_chann
ipu_cm_write(ipu, fs_disp_flow1, IPU_FS_DISP_FLOW1);
err:
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return retval;
}
EXPORT_SYMBOL(ipu_unlink_channels);
@@ -1935,12 +1925,12 @@ int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel)
uint32_t sec_dma;
uint32_t thrd_dma;
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
if (ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) {
dev_err(ipu->dev, "Warning: channel already enabled %d\n",
IPU_CHAN_ID(channel));
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return -EACCES;
}
@@ -2023,7 +2013,7 @@ int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel)
ipu->channel_enable_mask |= 1L << IPU_CHAN_ID(channel);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return 0;
}
@@ -2046,16 +2036,19 @@ int32_t ipu_check_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_b
{
uint32_t dma_chan = channel_2_dma(channel, type);
uint32_t reg;
+ unsigned long lock_flags;
if (dma_chan == IDMA_CHAN_INVALID)
return -EINVAL;
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
if (bufNum == 0)
reg = ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(dma_chan));
else if (bufNum == 1)
reg = ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(dma_chan));
else
reg = ipu_cm_read(ipu, IPU_CHA_BUF2_RDY(dma_chan));
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
if (reg & idma_mask(dma_chan))
return 1;
@@ -2100,9 +2093,11 @@ void _ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buf
void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
uint32_t bufNum)
{
- _ipu_lock(ipu);
+ unsigned long lock_flags;
+
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
_ipu_clear_buffer_ready(ipu, channel, type, bufNum);
- _ipu_unlock(ipu);
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
}
EXPORT_SYMBOL(ipu_clear_buffer_ready);
@@ -2126,13 +2121,14 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
uint32_t sec_dma = NO_DMA;
uint32_t thrd_dma = NO_DMA;
uint16_t fg_pos_x, fg_pos_y;
+ unsigned long lock_flags;
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
if ((ipu->channel_enable_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
dev_dbg(ipu->dev, "Channel already disabled %d\n",
IPU_CHAN_ID(channel));
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return -EACCES;
}
@@ -2144,7 +2140,7 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
!idma_is_set(ipu, IDMAC_CHA_EN, in_dma))
&& (idma_is_valid(out_dma) &&
!idma_is_set(ipu, IDMAC_CHA_EN, out_dma))) {
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return -EINVAL;
}
@@ -2280,6 +2276,7 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
if (channel == MEM_FG_SYNC)
_ipu_disp_set_window_pos(ipu, channel, fg_pos_x, fg_pos_y);
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
/* Set channel buffers NOT to be ready */
if (idma_is_valid(in_dma)) {
_ipu_clear_buffer_ready(ipu, channel, IPU_VIDEO_IN_BUFFER, 0);
@@ -2298,10 +2295,11 @@ int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wai
_ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 0);
_ipu_clear_buffer_ready(ipu, channel, IPU_ALPHA_IN_BUFFER, 1);
}
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return 0;
}
@@ -2326,7 +2324,7 @@ int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi)
}
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
ipu->csi_use_count[csi]++;
if (ipu->csi_use_count[csi] == 1) {
@@ -2336,7 +2334,7 @@ int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi)
else
ipu_cm_write(ipu, reg | IPU_CONF_CSI1_EN, IPU_CONF);
}
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
return 0;
}
@@ -2360,7 +2358,7 @@ int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi)
return -EINVAL;
}
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
ipu->csi_use_count[csi]--;
if (ipu->csi_use_count[csi] == 0) {
reg = ipu_cm_read(ipu, IPU_CONF);
@@ -2369,7 +2367,7 @@ int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi)
else
ipu_cm_write(ipu, reg & ~IPU_CONF_CSI1_EN, IPU_CONF);
}
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
return 0;
}
@@ -2387,7 +2385,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *desc)
const int err_reg[] = { 5, 6, 9, 10, 0 };
const int int_reg[] = { 1, 2, 3, 4, 11, 12, 13, 14, 15, 0 };
- spin_lock(&ipu->spin_lock);
+ spin_lock(&ipu->int_reg_spin_lock);
for (i = 0;; i++) {
if (err_reg[i] == 0)
@@ -2431,7 +2429,7 @@ static irqreturn_t ipu_irq_handler(int irq, void *desc)
}
}
- spin_unlock(&ipu->spin_lock);
+ spin_unlock(&ipu->int_reg_spin_lock);
return result;
}
@@ -2451,13 +2449,13 @@ void ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq)
_ipu_get(ipu);
- spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
reg |= IPUIRQ_2_MASK(irq);
ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
_ipu_put(ipu);
}
@@ -2478,13 +2476,13 @@ void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq)
_ipu_get(ipu);
- spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
reg &= ~IPUIRQ_2_MASK(irq);
ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
_ipu_put(ipu);
}
@@ -2504,11 +2502,11 @@ void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq)
_ipu_get(ipu);
- spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
ipu_cm_write(ipu, IPUIRQ_2_MASK(irq), IPUIRQ_2_STATREG(irq));
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
_ipu_put(ipu);
}
@@ -2531,9 +2529,9 @@ bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq)
_ipu_get(ipu);
- spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
reg = ipu_cm_read(ipu, IPUIRQ_2_STATREG(irq));
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
_ipu_put(ipu);
@@ -2576,12 +2574,12 @@ int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
_ipu_get(ipu);
- spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
if (ipu->irq_list[irq].handler != NULL) {
dev_err(ipu->dev,
"handler already installed on irq %d\n", irq);
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
return -EINVAL;
}
@@ -2597,7 +2595,7 @@ int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
reg |= IPUIRQ_2_MASK(irq);
ipu_cm_write(ipu, reg, IPUIRQ_2_CTRLREG(irq));
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
_ipu_put(ipu);
@@ -2624,7 +2622,7 @@ void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id)
_ipu_get(ipu);
- spin_lock_irqsave(&ipu->spin_lock, lock_flags);
+ spin_lock_irqsave(&ipu->int_reg_spin_lock, lock_flags);
/* disable the interrupt */
reg = ipu_cm_read(ipu, IPUIRQ_2_CTRLREG(irq));
@@ -2633,7 +2631,7 @@ void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id)
if (ipu->irq_list[irq].dev_id == dev_id)
memset(&ipu->irq_list[irq], 0, sizeof(ipu->irq_list[irq]));
- spin_unlock_irqrestore(&ipu->spin_lock, lock_flags);
+ spin_unlock_irqrestore(&ipu->int_reg_spin_lock, lock_flags);
_ipu_put(ipu);
}
@@ -2715,9 +2713,9 @@ uint32_t ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel)
uint32_t dma_status;
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
dma_status = ipu_is_channel_busy(ipu, channel);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
dev_dbg(ipu->dev, "%s, dma_status:%d.\n", __func__, dma_status);
@@ -2729,11 +2727,11 @@ EXPORT_SYMBOL(ipu_channel_status);
int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel_t to_ch)
{
uint32_t reg;
-
+ unsigned long lock_flags;
int from_dma = channel_2_dma(from_ch, IPU_INPUT_BUFFER);
int to_dma = channel_2_dma(to_ch, IPU_INPUT_BUFFER);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
/* enable target channel */
reg = ipu_idmac_read(ipu, IDMAC_CHA_EN(to_dma));
@@ -2753,11 +2751,13 @@ int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel
ipu->channel_enable_mask &= ~(1L << IPU_CHAN_ID(from_ch));
+ spin_lock_irqsave(&ipu->rdy_reg_spin_lock, lock_flags);
_ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 0);
_ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 1);
_ipu_clear_buffer_ready(ipu, from_ch, IPU_VIDEO_IN_BUFFER, 2);
+ spin_unlock_irqrestore(&ipu->rdy_reg_spin_lock, lock_flags);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return 0;
}
diff --git a/drivers/mxc/ipu3/ipu_disp.c b/drivers/mxc/ipu3/ipu_disp.c
index 7a344319e28a..35b78199b0df 100644
--- a/drivers/mxc/ipu3/ipu_disp.c
+++ b/drivers/mxc/ipu3/ipu_disp.c
@@ -1298,7 +1298,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
/* Get integer portion of divider */
div = clk_get_rate(clk_get_parent(&ipu->pixel_clk[disp])) / rounded_pixel_clk;
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
_ipu_di_data_wave_config(ipu, disp, SYNC_WAVE, div - 1, div - 1);
_ipu_di_data_pin_config(ipu, disp, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
@@ -1306,7 +1306,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
map = _ipu_pixfmt_to_map(pixel_fmt);
if (map < 0) {
dev_dbg(ipu->dev, "IPU_DISP: No MAP\n");
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return -EINVAL;
}
@@ -1696,7 +1696,7 @@ int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp, uint32_t pixel_clk,
ipu_dc_write(ipu, width, DC_DISP_CONF2(DC_DISP_ID_SYNC(disp)));
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return 0;
}
@@ -1710,7 +1710,7 @@ void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp)
if ((disp != 0) || (disp != 1))
return;
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
di_gen = ipu_di_read(ipu, disp, DI_GENERAL);
di_gen |= 0x3ff | DI_GEN_POLARITY_DISP_CLK;
@@ -1720,7 +1720,7 @@ void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp)
reg |= 0x3ffffff;
ipu_di_write(ipu, disp, reg, DI_POL);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
}
EXPORT_SYMBOL(ipu_uninit_sync_panel);
@@ -1740,7 +1740,7 @@ int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle
if (map < 0)
return -EINVAL;
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
if (type == IPU_PANEL_SERIAL) {
ipu_di_write(ipu, disp, (div << 24) | ((sig.ifc_width - 1) << 4),
@@ -1769,7 +1769,7 @@ int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle
ipu_di_write(ipu, disp, ser_conf, DI_SER_CONF);
}
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
return 0;
}
EXPORT_SYMBOL(ipu_init_async_panel);
@@ -1813,7 +1813,7 @@ int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
if (bg_chan) {
reg = ipu_dp_read(ipu, DP_COM_CONF(flow));
@@ -1838,7 +1838,7 @@ int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel,
reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
@@ -1876,7 +1876,7 @@ int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel,
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
ipu->color_key_4rgb = true;
/* Transform color key from rgb to yuv if CSC is enabled */
@@ -1915,7 +1915,7 @@ int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel,
reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
@@ -1952,7 +1952,7 @@ int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
for (i = 0; i < 8; i++)
ipu_dp_write(ipu, (constk[2*i] & 0x1ff) | ((constk[2*i+1] & 0x1ff) << 16), DP_GAMMA_C(flow, i));
@@ -1973,7 +1973,7 @@ int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel
reg = ipu_cm_read(ipu, IPU_SRM_PRI2) | 0x8;
ipu_cm_write(ipu, reg, IPU_SRM_PRI2);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
@@ -2037,9 +2037,9 @@ int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
int ret;
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
ret = _ipu_disp_set_window_pos(ipu, channel, x_pos, y_pos);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
return ret;
}
@@ -2073,9 +2073,9 @@ int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
int ret;
_ipu_get(ipu);
- _ipu_lock(ipu);
+ mutex_lock(&ipu->mutex_lock);
ret = _ipu_disp_get_window_pos(ipu, channel, x_pos, y_pos);
- _ipu_unlock(ipu);
+ mutex_unlock(&ipu->mutex_lock);
_ipu_put(ipu);
return ret;
}
diff --git a/drivers/mxc/ipu3/ipu_prv.h b/drivers/mxc/ipu3/ipu_prv.h
index a81f47882981..a0d71dd5dad3 100644
--- a/drivers/mxc/ipu3/ipu_prv.h
+++ b/drivers/mxc/ipu3/ipu_prv.h
@@ -100,7 +100,8 @@ struct ipu_soc {
int csi_use_count[2];
struct mutex mutex_lock;
- spinlock_t spin_lock;
+ spinlock_t int_reg_spin_lock;
+ spinlock_t rdy_reg_spin_lock;
int dmfc_size_28;
int dmfc_size_29;
@@ -322,6 +323,4 @@ int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
int16_t *x_pos, int16_t *y_pos);
void _ipu_get(struct ipu_soc *ipu);
void _ipu_put(struct ipu_soc *ipu);
-void _ipu_lock(struct ipu_soc *ipu);
-void _ipu_unlock(struct ipu_soc *ipu);
#endif /* __INCLUDE_IPU_PRV_H__ */