static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,enum v4l2_field field) { struct file *file = q->priv_data; struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; struct saa7146_buf *buf = (struct saa7146_buf *)vb; int err = 0; int lines, llength, size; lines = 16 * 2 ; /* 2 fields */ llength = vbi_pixel_to_capture; size = lines * llength; DEB_VBI("vb:%p\n", vb); if (0 != buf->vb.baddr && buf->vb.bsize < size) { DEB_VBI("size mismatch\n"); return -EINVAL; } if (buf->vb.size != size) saa7146_dma_free(dev,q,buf); if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); buf->vb.width = llength; buf->vb.height = lines; buf->vb.size = size; buf->vb.field = field; // FIXME: check this saa7146_pgtable_free(dev->pci, &buf->pt[2]); saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); err = videobuf_iolock(q,&buf->vb, NULL); if (err) goto oops; err = saa7146_pgtable_build_single(dev->pci, &buf->pt[2], dma->sglist, dma->sglen); if (0 != err) return err; } buf->vb.state = VIDEOBUF_PREPARED; buf->activate = buffer_activate; return 0; oops: DEB_VBI("error out\n"); saa7146_dma_free(dev,q,buf); return err; }
void *saa7146_vmalloc_build_pgtable(struct pci_dev *pci, long length, struct saa7146_pgtable *pt) { int pages = (length+PAGE_SIZE-1)/PAGE_SIZE; void *mem = vmalloc_32(length); int slen = 0; if (NULL == mem) goto err_null; if (!(pt->slist = vmalloc_to_sg(mem, pages))) goto err_free_mem; if (saa7146_pgtable_alloc(pci, pt)) goto err_free_slist; pt->nents = pages; slen = pci_map_sg(pci,pt->slist,pt->nents,PCI_DMA_FROMDEVICE); if (0 == slen) goto err_free_pgtable; if (0 != saa7146_pgtable_build_single(pci, pt, pt->slist, slen)) goto err_unmap_sg; return mem; err_unmap_sg: pci_unmap_sg(pci, pt->slist, pt->nents, PCI_DMA_FROMDEVICE); err_free_pgtable: saa7146_pgtable_free(pci, pt); err_free_slist: kfree(pt->slist); pt->slist = NULL; err_free_mem: vfree(mem); err_null: return NULL; }
static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, enum v4l2_field field) { struct file *file = q->priv_data; struct saa7146_fh *fh = file->private_data; struct saa7146_dev *dev = fh->dev; struct saa7146_vv *vv = dev->vv_data; 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 < 48 || fh->video_fmt.height < 32 || fh->video_fmt.width > vv->standard->h_max_out || fh->video_fmt.height > vv->standard->v_max_out) { DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height)); return -EINVAL; } size = fh->video_fmt.sizeimage; if (0 != buf->vb.baddr && buf->vb.bsize < size) { DEB_D(("size mismatch.\n")); return -EINVAL; } 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 || buf->vb.field != fh->video_fmt.field || buf->fmt != &fh->video_fmt) { saa7146_dma_free(dev,buf); } 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; buf->vb.field = field; buf->fmt = &fh->video_fmt; buf->vb.field = fh->video_fmt.field; sfmt = format_by_fourcc(dev,buf->fmt->pixelformat); if( 0 != IS_PLANAR(sfmt->trans)) { saa7146_pgtable_free(dev->pci, &buf->pt[0]); saa7146_pgtable_free(dev->pci, &buf->pt[1]); saa7146_pgtable_free(dev->pci, &buf->pt[2]); saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); saa7146_pgtable_alloc(dev->pci, &buf->pt[1]); saa7146_pgtable_alloc(dev->pci, &buf->pt[2]); } else { saa7146_pgtable_free(dev->pci, &buf->pt[0]); saa7146_pgtable_alloc(dev->pci, &buf->pt[0]); } err = videobuf_iolock(dev->pci,&buf->vb, &vv->ov_fb); if (err) goto oops; err = saa7146_pgtable_build(dev,buf); if (err) goto oops; } buf->vb.state = STATE_PREPARED; buf->activate = buffer_activate; return 0; oops: DEB_D(("error out.\n")); saa7146_dma_free(dev,buf); return err; }