]> git.hungrycats.org Git - linux/commitdiff
[PATCH] video capture updates for saa7146 core
authorMichael Hunold <hunold@linuxtv.org>
Wed, 8 Oct 2003 01:46:54 +0000 (18:46 -0700)
committerLinus Torvalds <torvalds@home.osdl.org>
Wed, 8 Oct 2003 01:46:54 +0000 (18:46 -0700)
 - some Kconfig simplifications
 - FIELD_ALTERNATE capture was broken, add a "wait for vbi" command
   before actually waiting for the field change
 - improvements regarding streaming capture to gfx card memory.
 - captured frames could only be page aligned.  fixed.
 - fix pgtable_build_single, it should work for all kinds of buffers now
   (system memory (kernel/user) and gfx-memory)
 - Fix bytesperline-calculation for V4L2_FIELD_ALTERNATE vs.
   V4L2_FIELD_INTERLACED capture

drivers/media/common/Kconfig
drivers/media/common/saa7146_core.c
drivers/media/common/saa7146_fops.c
drivers/media/common/saa7146_hlp.c
drivers/media/common/saa7146_video.c

index 1a6b17203381d222bae8ac791bc7b11de279a2b6..211e74ee07d5fc98892efa7062cda36806929365 100644 (file)
@@ -1,11 +1,8 @@
 config VIDEO_SAA7146
-        tristate
-        default y if DVB_AV7110=y || DVB_BUDGET=y || DVB_BUDGET_AV=y || VIDEO_MXB=y || VIDEO_DPC=y || VIDEO_HEXIUM_ORION=y || VIDEO_HEXIUM_GEMINI=y
-        default m if DVB_AV7110=m || DVB_BUDGET=m || DVB_BUDGET_AV=m || VIDEO_MXB=m || VIDEO_DPC=m || VIDEO_HEXIUM_ORION=m || VIDEO_HEXIUM_GEMINI=m
+       def_tristate DVB_AV7110 || DVB_BUDGET || DVB_BUDGET_AV || \
+                    VIDEO_MXB || VIDEO_DPC || VIDEO_HEXIUM_ORION || \
+                    VIDEO_HEXIUM_GEMINI
         depends on VIDEO_DEV && PCI && I2C
-
 config VIDEO_VIDEOBUF
-        tristate
-        default y if VIDEO_SAA7134=y || VIDEO_BT848=y || VIDEO_SAA7146=y
-        default m if VIDEO_SAA7134=m || VIDEO_BT848=m || VIDEO_SAA7146=m
+       def_tristate VIDEO_SAA7134 || VIDEO_BT848 || VIDEO_SAA7146
         depends on VIDEO_DEV
index fff083393c70765776099b6061b1b29dd0df55bc..3d5d7a7588070407f8ec69706db5cc0c6e4290df 100644 (file)
@@ -139,34 +139,42 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
        return 0;
 }
 
-void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt, struct scatterlist *list, int length )
+void saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
+       struct scatterlist *list, int sglen  )
 {
        u32   *ptr, fill;
+       int nr_pages = 0;
        int   i,p;
 
-//fm   DEB_EE(("pci:%p, pt:%p, sl:%p, len:%d\n",pci,pt,list,length));
+       BUG_ON( 0 == sglen);
 
        /* if we have a user buffer, the first page may not be
           aligned to a page boundary. */
        pt->offset = list->offset;
 
        ptr = pt->cpu;
-       for (i = 0; i < length; i++, list++) {
+       for (i = 0; i < sglen; i++, list++) {
+/*
+               printk("i:%d, adr:0x%08x, len:%d, offset:%d\n", i,sg_dma_address(list), sg_dma_len(list), list->offset);
+*/
                for (p = 0; p * 4096 < list->length; p++, ptr++) {
-                       *ptr = sg_dma_address(list) - list->offset;
+                       *ptr = sg_dma_address(list) + p * 4096;
+                       nr_pages++;
                }
        }
 
 
        /* safety; fill the page table up with the last valid page */
        fill = *(ptr-1);
-       for(;i<1024;i++) {
+       for(i=nr_pages;i<1024;i++) {
                *ptr++ = fill;
        }
+
 /*
        ptr = pt->cpu;
-       for(j=0;j<60;j++) {
-               printk("ptr1 %d: 0x%08x\n",j,ptr[j]);
+       printk("offset: %d\n",pt->offset);
+       for(i=0;i<5;i++) {
+               printk("ptr1 %d: 0x%08x\n",i,ptr[i]);
        }
 */
 }
index b3423b7e6c4d9d40bdb318f4216b8c1f1f5133a0..f2a3234318288336e0a6d8a3c8d232597a064298 100644 (file)
@@ -304,6 +304,7 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
                        return videobuf_poll_stream(file, &fh->vbi_q, wait);
                q = &fh->vbi_q;
        } else {
+               DEB_D(("using video queue.\n"));
                q = &fh->video_q;
        }
 
@@ -311,14 +312,17 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
                buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
 
        if (!buf) {
+               DEB_D(("buf == NULL!\n"));
                return POLLERR;
        }
 
        poll_wait(file, &buf->done, wait);
        if (buf->state == STATE_DONE || buf->state == STATE_ERROR) {
+               DEB_D(("poll succeeded!\n"));
                return POLLIN|POLLRDNORM;
        }
 
+       DEB_D(("nothing to poll for, buf->state:%d\n",buf->state));
        return 0;
 }
 
index 55ca60ad421d443074a61efbc1e1eb217e20e519..0f41a4d8013fd085ba62e4a11ab63281462423e1 100644 (file)
@@ -742,6 +742,7 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
 
        int width = buf->fmt->width;
        int height = buf->fmt->height;
+       int bytesperline = buf->fmt->bytesperline;
        enum v4l2_field field = buf->fmt->field;
 
        int depth = sfmt->depth;
@@ -749,7 +750,11 @@ static int calculate_video_dma_grab_packed(struct saa7146_dev* dev, struct saa71
        DEB_CAP(("[size=%dx%d,fields=%s]\n",
                width,height,v4l2_field_names[field]));
 
+       if( bytesperline != 0) {
+               vdma1.pitch = bytesperline*2;
+       } else {
        vdma1.pitch             = (width*depth*2)/8;
+       }
        vdma1.num_line_byte     = ((vv->standard->v_field<<16) + vv->standard->h_pixels);
        vdma1.base_page         = buf->pt[0].dma | ME1;
        
@@ -799,6 +804,8 @@ static int calc_planar_422(struct saa7146_vv *vv, struct saa7146_buf *buf, struc
        vdma2->pitch    = width;
        vdma3->pitch    = width;
 
+       /* fixme: look at bytesperline! */
+
        if( 0 != vv->vflip ) {
                vdma2->prot_addr        = buf->pt[1].offset;
                vdma2->base_even        = ((vdma2->pitch/2)*height)+buf->pt[1].offset;
@@ -871,6 +878,8 @@ static int calculate_video_dma_grab_planar(struct saa7146_dev* dev, struct saa71
        DEB_CAP(("[size=%dx%d,fields=%s]\n",
                width,height,v4l2_field_names[field]));
 
+       /* fixme: look at bytesperline! */
+
        /* fixme: what happens for user space buffers here?. The offsets are
           most likely wrong, this version here only works for page-aligned
           buffers, modifications to the pagetable-functions are necessary...*/
@@ -997,8 +1006,10 @@ static void program_capture_engine(struct saa7146_dev *dev, int planar)
                WRITE_RPS0(CMD_PAUSE | o_wait);
        WRITE_RPS0(CMD_PAUSE | e_wait);
        } else if ( vv->last_field == V4L2_FIELD_TOP ) {
+               WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
        WRITE_RPS0(CMD_PAUSE | o_wait);
        } else if ( vv->last_field == V4L2_FIELD_BOTTOM ) {
+               WRITE_RPS0(CMD_PAUSE | (vv->current_hps_sync == SAA7146_HPS_SYNC_PORT_A ? MASK_10 : MASK_09));
                WRITE_RPS0(CMD_PAUSE | e_wait);
        }
 
@@ -1033,16 +1044,6 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struc
 
        DEB_CAP(("buf:%p, next:%p\n",buf,next));
 
-/*
-       printk("vdma%d.base_even:     0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
-       printk("vdma%d.base_odd:      0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
-       printk("vdma%d.prot_addr:     0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
-       printk("vdma%d.base_page:     0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
-       printk("vdma%d.pitch:         0x%08x\n", 1,saa7146_read(dev,PITCH1));
-       printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
-       printk("vdma%d => vptr      : 0x%08x\n", 1,saa7146_read(dev,PCI_VDP1));
-*/
-
        vdma1_prot_addr = saa7146_read(dev, PROT_ADDR1);
        if( 0 == vdma1_prot_addr ) {
                /* clear out beginning of streaming bit (rps register 0)*/
@@ -1069,6 +1070,16 @@ void saa7146_set_capture(struct saa7146_dev *dev, struct saa7146_buf *buf, struc
                program_capture_engine(dev,0);
        }
 
+/*
+       printk("vdma%d.base_even:     0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
+       printk("vdma%d.base_odd:      0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
+       printk("vdma%d.prot_addr:     0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
+       printk("vdma%d.base_page:     0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
+       printk("vdma%d.pitch:         0x%08x\n", 1,saa7146_read(dev,PITCH1));
+       printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
+       printk("vdma%d => vptr      : 0x%08x\n", 1,saa7146_read(dev,PCI_VDP1));
+*/
+
        /* write the address of the rps-program */
        saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
 
index f027f6ce20802c9d943e55b41ef99edd073d00fa..324fb64e1e845e42553d69292607282d4072f16f 100644 (file)
@@ -169,6 +169,7 @@ static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
                struct saa7146_format *fmt;
                enum v4l2_field field;
                int maxw, maxh;
+               int calc_bpl;
 
                DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n",dev,fh));
 
@@ -211,8 +212,18 @@ static int try_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
                        f->fmt.pix.width = maxw;
                if (f->fmt.pix.height > maxh)
                        f->fmt.pix.height = maxh;
-               f->fmt.pix.sizeimage =
-                       (f->fmt.pix.width * f->fmt.pix.height * fmt->depth)/8;
+
+               calc_bpl = (f->fmt.pix.width * fmt->depth)/8;
+
+               if (f->fmt.pix.bytesperline < calc_bpl)
+                       f->fmt.pix.bytesperline = calc_bpl;
+                       
+               if (f->fmt.pix.bytesperline > (2*PAGE_SIZE * fmt->depth)/8) /* arbitrary constraint */
+                       f->fmt.pix.bytesperline = calc_bpl;
+                       
+               f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
+               DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",f->fmt.pix.width,f->fmt.pix.height,f->fmt.pix.bytesperline,f->fmt.pix.sizeimage));
+
                return 0;
        }
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
@@ -359,41 +370,41 @@ static int s_fmt(struct saa7146_fh *fh, struct v4l2_format *f)
 
 static struct v4l2_queryctrl controls[] = {
        {
-               .id            = V4L2_CID_BRIGHTNESS,
-               .name          = "Brightness",
-               .minimum       = 0,
-               .maximum       = 255,
-               .step          = 1,
-               .default_value = 128,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
+               id:            V4L2_CID_BRIGHTNESS,
+               name:          "Brightness",
+               minimum:       0,
+               maximum:       255,
+               step:          1,
+               default_value: 128,
+               type:          V4L2_CTRL_TYPE_INTEGER,
        },{
-               .id            = V4L2_CID_CONTRAST,
-               .name          = "Contrast",
-               .minimum       = 0,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 64,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
+               id:            V4L2_CID_CONTRAST,
+               name:          "Contrast",
+               minimum:       0,
+               maximum:       127,
+               step:          1,
+               default_value: 64,
+               type:          V4L2_CTRL_TYPE_INTEGER,
        },{
-               .id            = V4L2_CID_SATURATION,
-               .name          = "Saturation",
-               .minimum       = 0,
-               .maximum       = 127,
-               .step          = 1,
-               .default_value = 64,
-               .type          = V4L2_CTRL_TYPE_INTEGER,
+               id:            V4L2_CID_SATURATION,
+               name:          "Saturation",
+               minimum:       0,
+               maximum:       127,
+               step:          1,
+               default_value: 64,
+               type:          V4L2_CTRL_TYPE_INTEGER,
        },{
-               .id            = V4L2_CID_VFLIP,
-               .name          = "Vertical flip",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               id:            V4L2_CID_VFLIP,
+               name:          "Vertical flip",
+               minimum:       0,
+               maximum:       1,
+               type:          V4L2_CTRL_TYPE_BOOLEAN,
        },{
-               .id            = V4L2_CID_HFLIP,
-               .name          = "Horizontal flip",
-               .minimum       = 0,
-               .maximum       = 1,
-               .type          = V4L2_CTRL_TYPE_BOOLEAN,
+               id:            V4L2_CID_HFLIP,
+               name:          "Horizontal flip",
+               minimum:       0,
+               maximum:       1,
+               type:          V4L2_CTRL_TYPE_BOOLEAN,
        },
 };
 static int NUM_CONTROLS = sizeof(controls)/sizeof(struct v4l2_queryctrl);
@@ -549,7 +560,7 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
        int length = buf->vb.dma.sglen;
        struct saa7146_format *sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
 
-       DEB_EE(("dev:%p, buf:%p\n",dev,buf));
+       DEB_EE(("dev:%p, buf:%p, sg_len:%d\n",dev,buf,length));
 
        if( 0 != IS_PLANAR(sfmt->trans)) {
                struct saa7146_pgtable *pt1 = &buf->pt[0];
@@ -729,6 +740,81 @@ static int video_end(struct saa7146_fh *fh)
        return 0;
 }
 
+/* capturing to framebuffer */
+
+int overlay_reqbufs(struct saa7146_dev *dev, struct v4l2_requestbuffers *req)
+{
+/*     struct saa7146_fh *fh = file->private_data;
+
+       if (req->count > VIDEO_MAX_FRAME)
+               req->count = VIDEO_MAX_FRAME;
+
+       *size = fh->video_fmt.sizeimage;
+
+*/
+       return 0;
+}
+int overlay_querybuf(struct saa7146_dev *dev, struct v4l2_buffer *buf)
+{
+       return 0;
+}
+int overlay_qbuf(struct saa7146_dev *dev, struct v4l2_buffer *b)
+{
+/*     if (b->index < 0 || b->index >= VIDEO_MAX_FRAME) {
+               DEB_D(("index %d out of bounds.\n",b->index));
+               goto -EINVAL;
+       }
+       
+       buf = q->bufs[b->index];
+       if (NULL == buf) {
+               printk("videobuf_qbuf: NULL == buf\n");
+               goto done;
+       }
+       if (0 == buf->baddr) {
+               printk("videobuf_qbuf: 0 == buf->baddr\n");
+               goto done;
+       }
+       if (buf->state == STATE_QUEUED ||
+           buf->state == STATE_ACTIVE) {
+               printk("videobuf_qbuf: already queued or activated.\n");
+               goto done;
+       }
+
+       field = videobuf_next_field(q);
+       retval = q->ops->buf_prepare(file,buf,field);
+       if (0 != retval) {
+               printk("videobuf_qbuf: buf_prepare() failed.\n");
+               goto done;
+       }
+       
+       list_add_tail(&buf->stream,&q->stream);
+       if (q->streaming) {
+               spin_lock_irqsave(q->irqlock,flags);
+               q->ops->buf_queue(file,buf);
+               spin_unlock_irqrestore(q->irqlock,flags);
+       }
+       retval = 0;
+       
+ done:
+       up(&q->lock);
+       return retval;
+*/
+       return 0;
+}
+int overlay_dqbuf(struct saa7146_dev *dev, struct v4l2_buffer *buf)
+{
+       return 0;
+}
+int overlay_streamon(struct saa7146_dev *dev)
+{
+       return 0;
+}
+int overlay_streamoff(struct saa7146_dev *dev)
+{
+       return 0;
+}
+
+
 /*
  * This function is _not_ called directly, but from
  * video_generic_ioctl (and maybe others).  userspace
@@ -794,7 +880,7 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
                
                 strcpy(cap->driver, "saa7146 v4l2");
                strlcpy(cap->card, dev->ext->name, sizeof(cap->card));
-               sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci));
+               sprintf(cap->bus_info,"PCI:%s",dev->pci->slot_name);
                cap->version = SAA7146_VERSION_CODE;
                cap->capabilities =
                        V4L2_CAP_VIDEO_CAPTURE |
@@ -884,8 +970,11 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
                        
                ctrl = ctrl_by_id(c->id);
                if( NULL == ctrl ) {
+                       return -EINVAL;
+/*
                        c->flags = V4L2_CTRL_FLAG_DISABLED;     
                        return 0;
+*/
                }
 
                DEB_EE(("VIDIOC_QUERYCTRL: id:%d\n",c->id));
@@ -1037,44 +1126,71 @@ int saa7146_video_do_ioctl(struct inode *inode, struct file *file, unsigned int
                return err;
        }
        case VIDIOC_REQBUFS: {
-               DEB_D(("VIDIOC_REQBUFS \n"));
-               return videobuf_reqbufs(file,q,arg);
+               struct v4l2_requestbuffers *req = arg;
+               DEB_D(("VIDIOC_REQBUFS, type:%d\n",req->type));
+/*
+               if( req->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
+                       return overlay_reqbufs(dev,req);
+               } 
+*/
+               return videobuf_reqbufs(file,q,req);
        }
        case VIDIOC_QUERYBUF: {
-               DEB_D(("VIDIOC_QUERYBUF \n"));
-               return videobuf_querybuf(q,arg);
+               struct v4l2_buffer *buf = arg;
+               DEB_D(("VIDIOC_QUERYBUF, type:%d, offset:%d\n",buf->type,buf->m.offset));
+/*             if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
+                       return overlay_querybuf(dev,buf);
+               } 
+ */            return videobuf_querybuf(q,buf);
        }
        case VIDIOC_QBUF: {
-               struct v4l2_buffer *b = arg;
+               struct v4l2_buffer *buf = arg;
                int ret = 0;
-               ret = videobuf_qbuf(file,q,b);
-               DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,b->index));
+/*             if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
+                       return overlay_qbuf(dev,buf);
+               } 
+ */            ret = videobuf_qbuf(file,q,buf);
+               DEB_D(("VIDIOC_QBUF: ret:%d, index:%d\n",ret,buf->index));
                return ret;
        }
        case VIDIOC_DQBUF: {
-               struct v4l2_buffer *b = arg;
+               struct v4l2_buffer *buf = arg;
                int ret = 0;
-               ret = videobuf_dqbuf(file,q,b);
-               DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,b->index));
+/*             if( buf->type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
+                       return overlay_dqbuf(dev,buf);
+               } 
+ */            ret = videobuf_dqbuf(file,q,buf);
+               DEB_D(("VIDIOC_DQBUF: ret:%d, index:%d\n",ret,buf->index));
                return ret;
        }
        case VIDIOC_STREAMON: {
-               DEB_D(("VIDIOC_STREAMON \n"));
+               int *type = arg;
+               DEB_D(("VIDIOC_STREAMON, type:%d\n",*type));
+
                if( 0 != ops->capture_begin ) {
                        if( 0 != (err = ops->capture_begin(fh))) {
                                return err;
                        }
                }
+/*             if( *type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
+                       err = overlay_streamon(dev);
+               } else { */
                err = videobuf_streamon(file,q);
+/*             } */
                return err;
        }
        case VIDIOC_STREAMOFF: {
-               DEB_D(("VIDIOC_STREAMOFF \n"));
+               int *type = arg;
+
+               DEB_D(("VIDIOC_STREAMOFF, type:%d\n",*type));
                if( 0 != ops->capture_end ) {
                        ops->capture_end(fh);
                }
-               err = videobuf_streamoff(file,q);
-               return 0;
+/*             if( *type == V4L2_BUF_TYPE_VIDEO_OVERLAY ) {
+                       return overlay_streamoff(dev);
+               } 
+ */            err = videobuf_streamoff(file,q);
+               return err;
        }
        case VIDIOCGMBUF:
        {
@@ -1135,6 +1251,8 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, enum v4
        struct saa7146_buf *buf = (struct saa7146_buf *)vb;
        int size,err = 0;
 
+       DEB_CAP(("vbuf:%p\n",vb));
+
        /* sanity checks */
        if (fh->video_fmt.width  < 64 ||
            fh->video_fmt.height < 64 ||
@@ -1153,6 +1271,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, enum v4
        DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
                fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
        if (buf->vb.width  != fh->video_fmt.width  ||
+           buf->vb.bytesperline != fh->video_fmt.bytesperline ||
            buf->vb.height != fh->video_fmt.height ||
            buf->vb.size   != size ||
            buf->vb.field  != field      ||
@@ -1164,6 +1283,7 @@ static int buffer_prepare(struct file *file, struct videobuf_buffer *vb, enum v4
        if (STATE_NEEDS_INIT == buf->vb.state) {
                struct saa7146_format *sfmt;
                
+               buf->vb.bytesperline  = fh->video_fmt.bytesperline;
                buf->vb.width  = fh->video_fmt.width;
                buf->vb.height = fh->video_fmt.height;
                buf->vb.size   = size;
@@ -1281,6 +1401,7 @@ static void video_open(struct saa7146_dev *dev, struct saa7146_fh *fh)
        fh->video_fmt.width = 384;
        fh->video_fmt.height = 288;
        fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
+       fh->video_fmt.bytesperline = 0;
        fh->video_fmt.field = V4L2_FIELD_ANY;
        sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
        fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;