From 6026a34078d0a5d29460850c5cadff6291f12b98 Mon Sep 17 00:00:00 2001 From: Jason Chen Date: Mon, 14 Nov 2011 10:34:49 +0800 Subject: ENGR00161948 mxc v4l2 output: fix case of input crop with xoffset run test like: /unit_tests//mxc_v4l2_output.out -iw 1280 -ih 720 -cr 1024 700 40 0 -ow 1024 -oh 700 /unit_tests/720p.yuv Under IPU IC bypass mode, the output color is not correct. And sometimes come out tearing issue. Fix them by modify fb driver adding xpanstep support and set vb->state to DONE after it finish show. When previous videobuf finish show and next videobuf ready to show, set VIDEOBUF_DONE state to avoid tearing issue, which make sure showing buffer will not be dequeue to write new data. It also bring side-effect that the last buffer can not be dequeue correctly, app need take care about it. Signed-off-by: Jason Chen --- drivers/media/video/mxc/output/mxc_vout.c | 31 +++++++++++++++++++++++-------- drivers/video/mxc/mxc_ipuv3_fb.c | 21 ++++++++++----------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/drivers/media/video/mxc/output/mxc_vout.c b/drivers/media/video/mxc/output/mxc_vout.c index 81056b5b1db..37d61fe9265 100644 --- a/drivers/media/video/mxc/output/mxc_vout.c +++ b/drivers/media/video/mxc/output/mxc_vout.c @@ -74,6 +74,8 @@ struct mxc_vout_output { int ctrl_hflip; dma_addr_t disp_bufs[FB_BUFS]; + + struct videobuf_buffer *pre_vb; }; struct mxc_vout_dev { @@ -451,15 +453,26 @@ static void disp_work_func(struct work_struct *work) goto err; } - show_buf(vout, vout->frame_count % FB_BUFS); + if (show_buf(vout, vout->frame_count % FB_BUFS) < 0) + goto err; spin_lock_irqsave(q->irqlock, flags); list_del(&vb->queue); - vb->state = VIDEOBUF_DONE; + /* + * previous videobuf finish show, set VIDEOBUF_DONE state here + * to avoid tearing issue, which make sure showing buffer will + * not be dequeue to write new data. It also bring side-effect + * that the last buffer can not be dequeue correctly, app need + * take care about it. + */ + if (vout->pre_vb) { + vout->pre_vb->state = VIDEOBUF_DONE; + wake_up_interruptible(&vout->pre_vb->done); + } - wake_up_interruptible(&vb->done); + vout->pre_vb = vb; vout->frame_count++; @@ -627,10 +640,10 @@ static int mxc_vout_release(struct file *file) return 0; if (--vout->open_cnt == 0) { - destroy_workqueue(vout->v4l_wq); q = &vout->vbq; if (q->streaming) ret = mxc_vidioc_streamoff(file, vout, vout->type); + destroy_workqueue(vout->v4l_wq); } return ret; @@ -803,13 +816,13 @@ static int mxc_vout_try_format(struct mxc_vout_output *vout, struct v4l2_format rect = (struct v4l2_rect *)f->fmt.pix.priv; vout->task.input.crop.pos.x = rect->left; vout->task.input.crop.pos.y = rect->top; - vout->task.input.crop.w = rect->width; - vout->task.input.crop.h = rect->height; + vout->task.input.crop.w = rect->width - rect->width%8; + vout->task.input.crop.h = rect->height - rect->height%8; } else { vout->task.input.crop.pos.x = 0; vout->task.input.crop.pos.y = 0; - vout->task.input.crop.w = f->fmt.pix.width; - vout->task.input.crop.h = f->fmt.pix.height; + vout->task.input.crop.w = f->fmt.pix.width - f->fmt.pix.width%8; + vout->task.input.crop.h = f->fmt.pix.height - f->fmt.pix.height%8; } /* assume task.output already set by S_CROP */ @@ -1278,6 +1291,8 @@ static int mxc_vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i vout->start_jiffies = jiffies; + vout->pre_vb = NULL; + ret = videobuf_streamon(q); done: return ret; diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c index 0c7c83dbff4..b674caea465 100644 --- a/drivers/video/mxc/mxc_ipuv3_fb.c +++ b/drivers/video/mxc/mxc_ipuv3_fb.c @@ -170,7 +170,7 @@ static int mxcfb_set_fix(struct fb_info *info) fix->type = FB_TYPE_PACKED_PIXELS; fix->accel = FB_ACCEL_NONE; fix->visual = FB_VISUAL_TRUECOLOR; - fix->xpanstep = 0; + fix->xpanstep = 1; fix->ywrapstep = 1; fix->ypanstep = 1; @@ -1234,16 +1234,15 @@ mxcfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) } /* update u/v offset */ - if (info->var.xres_virtual > info->var.xres) - ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch, - IPU_INPUT_BUFFER, - bpp_to_pixfmt(info), - info->var.xres_virtual, - info->var.yres_virtual, - info->var.xres_virtual, - 0, 0, - var->yoffset, - var->xoffset); + ipu_update_channel_offset(mxc_fbi->ipu, mxc_fbi->ipu_ch, + IPU_INPUT_BUFFER, + bpp_to_pixfmt(info), + info->var.xres_virtual, + info->var.yres_virtual, + info->var.xres_virtual, + 0, 0, + var->yoffset, + var->xoffset); ipu_select_buffer(mxc_fbi->ipu, mxc_fbi->ipu_ch, IPU_INPUT_BUFFER, mxc_fbi->cur_ipu_buf); -- cgit v1.2.3