diff options
-rw-r--r-- | drivers/media/video/mxc/output/mxc_v4l2_output.c | 25 | ||||
-rw-r--r-- | drivers/mxc/ipu/ipu_common.c | 15 | ||||
-rw-r--r-- | drivers/mxc/ipu3/ipu_common.c | 17 | ||||
-rw-r--r-- | include/linux/ipu.h | 1 |
4 files changed, 52 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; diff --git a/include/linux/ipu.h b/include/linux/ipu.h index 499435a4a7ac..f2e6c3536d1c 100644 --- a/include/linux/ipu.h +++ b/include/linux/ipu.h @@ -897,6 +897,7 @@ int32_t ipu_unlink_channels(ipu_channel_t src_ch, ipu_channel_t dest_ch); int32_t ipu_is_channel_busy(ipu_channel_t channel); void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type, uint32_t bufNum); +uint32_t ipu_get_cur_buffer_idx(ipu_channel_t channel, ipu_buffer_t type); int32_t ipu_enable_channel(ipu_channel_t channel); int32_t ipu_disable_channel(ipu_channel_t channel, bool wait_for_stop); int32_t ipu_swap_channel(ipu_channel_t from_ch, ipu_channel_t to_ch); |