ENGR00120370 v4l2 output: fix display fail for blank fb during video play

1. Blank BG during video play on FG:
./mxc_v4l2_output.out -iw 320 -ih 240 -ow 1024 -oh 768 -d 3 qvga.yuv
echo 1 > /sys/class/graphics/fb0/blank
echo 0 > /sys/class/graphics/fb0/blank

2. The same input and output (ic_bypass):
./mxc_v4l2_output.out -iw 320 -ih 240 -ow 320 -oh 240 -d 3 qvga.yuv
echo 1 > /sys/class/graphics/fb0/blank
echo 0 > /sys/class/graphics/fb0/blank

Signed-off-by: Jason Chen <b02280@freescale.com>
This commit is contained in:
Jason Chen
2010-01-25 10:38:07 +08:00
committed by Matt Sealey
parent bd50dbbbaa
commit 6a73a12e8e
5 changed files with 107 additions and 52 deletions

View File

@@ -273,19 +273,22 @@ static void setup_next_buf_timer(vout_data *vout, int index)
"timer handler next schedule: %lu\n", timeout);
}
static void wait_for_disp_vsync(vout_data *vout)
static int wait_for_disp_vsync(vout_data *vout)
{
struct fb_info *fbi =
registered_fb[vout->output_fb_num[vout->cur_disp_output]];
mm_segment_t old_fs;
int ret = 0;
/* wait for display frame finish */
if (fbi->fbops->fb_ioctl) {
old_fs = get_fs();
set_fs(KERNEL_DS);
fbi->fbops->fb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC, (unsigned int)NULL);
ret = fbi->fbops->fb_ioctl(fbi, MXCFB_WAIT_FOR_VSYNC,
(unsigned int)NULL);
set_fs(old_fs);
}
return ret;
}
static void timer_work_func(struct work_struct *work)
@@ -323,7 +326,11 @@ static void timer_work_func(struct work_struct *work)
return;
}
wait_for_disp_vsync(vout);
if (wait_for_disp_vsync(vout) < 0) {
/* ic_bypass need clear display buffer ready for next update*/
ipu_clear_buffer_ready(vout->display_ch, IPU_INPUT_BUFFER,
!vout->next_done_ipu_buf);
}
spin_lock_irqsave(&g_lock, lock_flags);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -1188,6 +1188,23 @@ int32_t ipu_enable_channel(ipu_channel_t channel)
return 0;
}
/*!
* This function clear buffer ready for a logical channel.
*
* @param channel Input parameter for the logical channel ID.
*
* @param type Input parameter which buffer to clear.
*
* @param bufNum Input parameter for which buffer number clear
* ready state.
*
*/
void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type,
uint32_t bufNum)
{
/*TODO*/
}
/*!
* This function disables a logical channel.
*

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005-2009 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2005-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -1751,6 +1751,44 @@ int32_t ipu_enable_channel(ipu_channel_t channel)
}
EXPORT_SYMBOL(ipu_enable_channel);
/*!
* This function clear buffer ready for a logical channel.
*
* @param channel Input parameter for the logical channel ID.
*
* @param type Input parameter which buffer to clear.
*
* @param bufNum Input parameter for which buffer number clear
* ready state.
*
*/
void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type,
uint32_t bufNum)
{
unsigned long lock_flags;
uint32_t dma_ch = channel_2_dma(channel, type);
if (!idma_is_valid(dma_ch))
return;
spin_lock_irqsave(&ipu_lock, lock_flags);
__raw_writel(0xF0000000, 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 (idma_is_set(IPU_CHA_BUF1_RDY, dma_ch)) {
__raw_writel(idma_mask(dma_ch),
IPU_CHA_BUF1_RDY(dma_ch));
}
}
__raw_writel(0x0, IPU_GPR); /* write one to set */
spin_unlock_irqrestore(&ipu_lock, lock_flags);
}
static irqreturn_t disable_chan_irq_handler(int irq, void *dev_id)
{
struct completion *comp = dev_id;
@@ -1882,54 +1920,28 @@ 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));
}
/* Set channel buffers NOT to be ready */
__raw_writel(0xF0000000, IPU_GPR); /* write one to clear */
if (idma_is_valid(in_dma)) {
if (idma_is_set(IPU_CHA_BUF0_RDY, in_dma)) {
__raw_writel(idma_mask(in_dma),
IPU_CHA_BUF0_RDY(in_dma));
}
if (idma_is_set(IPU_CHA_BUF1_RDY, in_dma)) {
__raw_writel(idma_mask(in_dma),
IPU_CHA_BUF1_RDY(in_dma));
}
}
if (idma_is_valid(out_dma)) {
if (idma_is_set(IPU_CHA_BUF0_RDY, out_dma)) {
__raw_writel(idma_mask(out_dma),
IPU_CHA_BUF0_RDY(out_dma));
}
if (idma_is_set(IPU_CHA_BUF1_RDY, out_dma)) {
__raw_writel(idma_mask(out_dma),
IPU_CHA_BUF1_RDY(out_dma));
}
}
if (g_sec_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(sec_dma)) {
if (idma_is_set(IPU_CHA_BUF0_RDY, sec_dma)) {
__raw_writel(idma_mask(sec_dma),
IPU_CHA_BUF0_RDY(sec_dma));
}
if (idma_is_set(IPU_CHA_BUF1_RDY, sec_dma)) {
__raw_writel(idma_mask(sec_dma),
IPU_CHA_BUF1_RDY(sec_dma));
}
}
if (g_thrd_chan_en[IPU_CHAN_ID(channel)] && idma_is_valid(thrd_dma)) {
if (idma_is_set(IPU_CHA_BUF0_RDY, thrd_dma)) {
__raw_writel(idma_mask(thrd_dma),
IPU_CHA_BUF0_RDY(thrd_dma));
}
if (idma_is_set(IPU_CHA_BUF1_RDY, thrd_dma)) {
__raw_writel(idma_mask(thrd_dma),
IPU_CHA_BUF1_RDY(thrd_dma));
}
}
__raw_writel(0x0, IPU_GPR); /* write one to set */
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);
}
if (idma_is_valid(out_dma)) {
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);
}
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);
}
return 0;
}
EXPORT_SYMBOL(ipu_disable_channel);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2009 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved.
*/
/*
@@ -855,8 +855,25 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
}
case MXCFB_WAIT_FOR_VSYNC:
{
if (mxc_fbi->blank != FB_BLANK_UNBLANK)
if (mxc_fbi->ipu_ch == MEM_FG_SYNC) {
struct mxcfb_info *bg_mxcfbi = NULL;
int i;
for (i = 0; i < num_registered_fb; i++) {
bg_mxcfbi =
((struct mxcfb_info *)(registered_fb[i]->par));
if (bg_mxcfbi->ipu_ch == MEM_BG_SYNC)
break;
}
if (bg_mxcfbi->blank != FB_BLANK_UNBLANK) {
retval = -EINVAL;
break;
}
}
if (mxc_fbi->blank != FB_BLANK_UNBLANK) {
retval = -EINVAL;
break;
}
down(&mxc_fbi->flip_sem);
init_completion(&mxc_fbi->vsync_complete);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005-2009 Freescale Semiconductor, Inc.
* Copyright 2005-2010 Freescale Semiconductor, Inc.
*/
/*
@@ -895,6 +895,8 @@ int32_t ipu_link_channels(ipu_channel_t src_ch, ipu_channel_t dest_ch);
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);
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);