aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Chen <b02280@freescale.com>2011-11-14 10:34:49 +0800
committerJason Chen <b02280@freescale.com>2011-11-16 16:32:05 +0800
commit6026a34078d0a5d29460850c5cadff6291f12b98 (patch)
treea466b17534019acddd703f1f0be32d4f7f19caac
parent912eb564ab1b233944d5a82256b99645d8cc9f43 (diff)
downloadlinux-linaro-6026a34078d0a5d29460850c5cadff6291f12b98.tar.gz
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 <b02280@freescale.com>
-rw-r--r--drivers/media/video/mxc/output/mxc_vout.c31
-rw-r--r--drivers/video/mxc/mxc_ipuv3_fb.c21
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);