summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJason Chen <b02280@freescale.com>2010-01-26 16:55:03 +0800
committerAlejandro Gonzalez <alex.gonzalez@digi.com>2010-05-24 11:50:04 +0200
commitc2601bc8c92c41d6e9395a47484e943b604d18f9 (patch)
treea6e0d27b84e2aeb67ed285625093beda34cef166 /drivers
parentab8c5a1a9a0d7c42e063762700f497a57300a93b (diff)
ENGR00120428 v4l2 output: jitter after blank/unblank fb
blank/unblank fb during v4l2 playback, unblank will cause current buffer of display channel to be 1. This patch make the sequence of select display buffer correct. Signed-off-by: Jason Chen <b02280@freescale.com> Signed-off-by: Alejandro Gonzalez <alex.gonzalez@digi.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/mxc/output/mxc_v4l2_output.c25
-rw-r--r--drivers/mxc/ipu/ipu_common.c15
-rw-r--r--drivers/mxc/ipu3/ipu_common.c17
3 files changed, 51 insertions, 6 deletions
diff --git a/drivers/media/video/mxc/output/mxc_v4l2_output.c b/drivers/media/video/mxc/output/mxc_v4l2_output.c
index 521275ce7635..47c4bd1e7769 100644
--- a/drivers/media/video/mxc/output/mxc_v4l2_output.c
+++ b/drivers/media/video/mxc/output/mxc_v4l2_output.c
@@ -246,6 +246,22 @@ static u32 bpp_to_fmt(struct fb_info *fbi)
return 0;
}
+/*
+ * we are using double buffer for video playback, ipu need make
+ * sure current buffer should not be the same buffer of next display
+ * one.
+ */
+static int select_display_buffer(vout_data *vout, int next_buf)
+{
+ int ret = 0;
+
+ if (ipu_get_cur_buffer_idx(vout->display_ch, IPU_INPUT_BUFFER)
+ != next_buf)
+ ret = ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER,
+ next_buf);
+ return ret;
+}
+
static void setup_next_buf_timer(vout_data *vout, int index)
{
unsigned long timeout;
@@ -347,8 +363,7 @@ static void timer_work_func(struct work_struct *work)
}
if (vout->ic_bypass)
- ret = ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER,
- vout->next_rdy_ipu_buf);
+ ret = select_display_buffer(vout, vout->next_rdy_ipu_buf);
else if (LOAD_3FIELDS(vout))
ret = ipu_select_multi_vdi_buffer(vout->next_rdy_ipu_buf);
else
@@ -580,8 +595,7 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id)
vout->next_done_ipu_buf = !vout->next_done_ipu_buf;
} else /* right stripe is done, run display refresh */
- ret = ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER,
- disp_buf_num);
+ select_display_buffer(vout, disp_buf_num);
vout->next_rdy_ipu_buf = !vout->next_rdy_ipu_buf;
@@ -609,8 +623,7 @@ static irqreturn_t mxc_v4l2out_work_irq_handler(int irq, void *dev_id)
vout->pp_split_buf_num = (vout->pp_split_buf_num + 1) & 3;
} else {
/* show to display */
- ret = ipu_select_buffer(vout->display_ch, IPU_INPUT_BUFFER,
- vout->next_done_ipu_buf);
+ select_display_buffer(vout, vout->next_done_ipu_buf);
ret += ipu_select_buffer(vout->display_input_ch, IPU_OUTPUT_BUFFER,
vout->next_done_ipu_buf);
}
diff --git a/drivers/mxc/ipu/ipu_common.c b/drivers/mxc/ipu/ipu_common.c
index 634dea6cd3a4..c748a3304967 100644
--- a/drivers/mxc/ipu/ipu_common.c
+++ b/drivers/mxc/ipu/ipu_common.c
@@ -1204,6 +1204,21 @@ void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type,
{
/*TODO*/
}
+EXPORT_SYMBOL(ipu_clear_buffer_ready);
+
+uint32_t ipu_get_cur_buffer_idx(ipu_channel_t channel, ipu_buffer_t type)
+{
+ uint32_t reg, dma_chan;
+
+ dma_chan = channel_2_dma(channel, type);
+
+ reg = __raw_readl(IPU_CHA_CUR_BUF);
+ if (reg & (1UL << dma_chan))
+ return 1;
+ else
+ return 0;
+}
+EXPORT_SYMBOL(ipu_get_cur_buffer_idx);
/*!
* This function disables a logical channel.
diff --git a/drivers/mxc/ipu3/ipu_common.c b/drivers/mxc/ipu3/ipu_common.c
index 5b51fe2942ed..f53a047a186a 100644
--- a/drivers/mxc/ipu3/ipu_common.c
+++ b/drivers/mxc/ipu3/ipu_common.c
@@ -1788,6 +1788,7 @@ void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type,
__raw_writel(0x0, IPU_GPR); /* write one to set */
spin_unlock_irqrestore(&ipu_lock, lock_flags);
}
+EXPORT_SYMBOL(ipu_clear_buffer_ready);
static irqreturn_t disable_chan_irq_handler(int irq, void *dev_id)
{
@@ -2162,6 +2163,22 @@ void ipu_free_irq(uint32_t irq, void *dev_id)
}
EXPORT_SYMBOL(ipu_free_irq);
+uint32_t ipu_get_cur_buffer_idx(ipu_channel_t channel, ipu_buffer_t type)
+{
+ uint32_t reg, dma_chan;
+
+ dma_chan = channel_2_dma(channel, type);
+ if (!idma_is_valid(dma_chan))
+ return -EINVAL;
+
+ reg = __raw_readl(IPU_CHA_CUR_BUF(dma_chan/32));
+ if (reg & idma_mask(dma_chan))
+ return 1;
+ else
+ return 0;
+}
+EXPORT_SYMBOL(ipu_get_cur_buffer_idx);
+
uint32_t _ipu_channel_status(ipu_channel_t channel)
{
uint32_t stat = 0;