]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00161948 mxc v4l2 output: fix case of input crop with xoffset
authorJason Chen <b02280@freescale.com>
Mon, 14 Nov 2011 02:34:49 +0000 (10:34 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:33:27 +0000 (08:33 +0200)
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>
drivers/media/video/mxc/output/mxc_vout.c
drivers/video/mxc/mxc_ipuv3_fb.c

index b5f93daca088087624d581cc4fedb3fb71059f05..fb82a6816e8366642e068bb43b5d9487e382ee2f 100644 (file)
@@ -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;
index 74e4077600b7b03ade0173b0ed987b32dc56aa21..e7ad13727de5f04137408f9e702470b5d7ea956f 100644 (file)
@@ -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);