cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

saa7146_video.c (33909B)


      1#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      2
      3#include <media/drv-intf/saa7146_vv.h>
      4#include <media/v4l2-event.h>
      5#include <media/v4l2-ctrls.h>
      6#include <linux/module.h>
      7#include <linux/kernel.h>
      8
      9static int max_memory = 32;
     10
     11module_param(max_memory, int, 0644);
     12MODULE_PARM_DESC(max_memory, "maximum memory usage for capture buffers (default: 32Mb)");
     13
     14#define IS_CAPTURE_ACTIVE(fh) \
     15	(((vv->video_status & STATUS_CAPTURE) != 0) && (vv->video_fh == fh))
     16
     17#define IS_OVERLAY_ACTIVE(fh) \
     18	(((vv->video_status & STATUS_OVERLAY) != 0) && (vv->video_fh == fh))
     19
     20/* format descriptions for capture and preview */
     21static struct saa7146_format formats[] = {
     22	{
     23		.pixelformat	= V4L2_PIX_FMT_RGB332,
     24		.trans		= RGB08_COMPOSED,
     25		.depth		= 8,
     26		.flags		= 0,
     27	}, {
     28		.pixelformat	= V4L2_PIX_FMT_RGB565,
     29		.trans		= RGB16_COMPOSED,
     30		.depth		= 16,
     31		.flags		= 0,
     32	}, {
     33		.pixelformat	= V4L2_PIX_FMT_BGR24,
     34		.trans		= RGB24_COMPOSED,
     35		.depth		= 24,
     36		.flags		= 0,
     37	}, {
     38		.pixelformat	= V4L2_PIX_FMT_BGR32,
     39		.trans		= RGB32_COMPOSED,
     40		.depth		= 32,
     41		.flags		= 0,
     42	}, {
     43		.pixelformat	= V4L2_PIX_FMT_RGB32,
     44		.trans		= RGB32_COMPOSED,
     45		.depth		= 32,
     46		.flags		= 0,
     47		.swap		= 0x2,
     48	}, {
     49		.pixelformat	= V4L2_PIX_FMT_GREY,
     50		.trans		= Y8,
     51		.depth		= 8,
     52		.flags		= 0,
     53	}, {
     54		.pixelformat	= V4L2_PIX_FMT_YUV422P,
     55		.trans		= YUV422_DECOMPOSED,
     56		.depth		= 16,
     57		.flags		= FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
     58	}, {
     59		.pixelformat	= V4L2_PIX_FMT_YVU420,
     60		.trans		= YUV420_DECOMPOSED,
     61		.depth		= 12,
     62		.flags		= FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
     63	}, {
     64		.pixelformat	= V4L2_PIX_FMT_YUV420,
     65		.trans		= YUV420_DECOMPOSED,
     66		.depth		= 12,
     67		.flags		= FORMAT_IS_PLANAR,
     68	}, {
     69		.pixelformat	= V4L2_PIX_FMT_UYVY,
     70		.trans		= YUV422_COMPOSED,
     71		.depth		= 16,
     72		.flags		= 0,
     73	}
     74};
     75
     76/* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps.
     77   due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped
     78   (like V4L2_PIX_FMT_YUYV) ... 8-( */
     79
     80struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)
     81{
     82	int i;
     83
     84	for (i = 0; i < ARRAY_SIZE(formats); i++) {
     85		if (formats[i].pixelformat == fourcc) {
     86			return formats+i;
     87		}
     88	}
     89
     90	DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
     91	return NULL;
     92}
     93
     94static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f);
     95
     96int saa7146_start_preview(struct saa7146_fh *fh)
     97{
     98	struct saa7146_dev *dev = fh->dev;
     99	struct saa7146_vv *vv = dev->vv_data;
    100	struct v4l2_format fmt;
    101	int ret = 0, err = 0;
    102
    103	DEB_EE("dev:%p, fh:%p\n", dev, fh);
    104
    105	/* check if we have overlay information */
    106	if (vv->ov.fh == NULL) {
    107		DEB_D("no overlay data available. try S_FMT first.\n");
    108		return -EAGAIN;
    109	}
    110
    111	/* check if streaming capture is running */
    112	if (IS_CAPTURE_ACTIVE(fh) != 0) {
    113		DEB_D("streaming capture is active\n");
    114		return -EBUSY;
    115	}
    116
    117	/* check if overlay is running */
    118	if (IS_OVERLAY_ACTIVE(fh) != 0) {
    119		if (vv->video_fh == fh) {
    120			DEB_D("overlay is already active\n");
    121			return 0;
    122		}
    123		DEB_D("overlay is already active in another open\n");
    124		return -EBUSY;
    125	}
    126
    127	if (0 == saa7146_res_get(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP)) {
    128		DEB_D("cannot get necessary overlay resources\n");
    129		return -EBUSY;
    130	}
    131
    132	fmt.fmt.win = vv->ov.win;
    133	err = vidioc_try_fmt_vid_overlay(NULL, fh, &fmt);
    134	if (0 != err) {
    135		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
    136		return -EBUSY;
    137	}
    138	vv->ov.win = fmt.fmt.win;
    139
    140	DEB_D("%dx%d+%d+%d 0x%08x field=%s\n",
    141	      vv->ov.win.w.width, vv->ov.win.w.height,
    142	      vv->ov.win.w.left, vv->ov.win.w.top,
    143	      vv->ov_fmt->pixelformat, v4l2_field_names[vv->ov.win.field]);
    144
    145	if (0 != (ret = saa7146_enable_overlay(fh))) {
    146		DEB_D("enabling overlay failed: %d\n", ret);
    147		saa7146_res_free(vv->video_fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
    148		return ret;
    149	}
    150
    151	vv->video_status = STATUS_OVERLAY;
    152	vv->video_fh = fh;
    153
    154	return 0;
    155}
    156EXPORT_SYMBOL_GPL(saa7146_start_preview);
    157
    158int saa7146_stop_preview(struct saa7146_fh *fh)
    159{
    160	struct saa7146_dev *dev = fh->dev;
    161	struct saa7146_vv *vv = dev->vv_data;
    162
    163	DEB_EE("dev:%p, fh:%p\n", dev, fh);
    164
    165	/* check if streaming capture is running */
    166	if (IS_CAPTURE_ACTIVE(fh) != 0) {
    167		DEB_D("streaming capture is active\n");
    168		return -EBUSY;
    169	}
    170
    171	/* check if overlay is running at all */
    172	if ((vv->video_status & STATUS_OVERLAY) == 0) {
    173		DEB_D("no active overlay\n");
    174		return 0;
    175	}
    176
    177	if (vv->video_fh != fh) {
    178		DEB_D("overlay is active, but in another open\n");
    179		return -EBUSY;
    180	}
    181
    182	vv->video_status = 0;
    183	vv->video_fh = NULL;
    184
    185	saa7146_disable_overlay(fh);
    186
    187	saa7146_res_free(fh, RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP);
    188
    189	return 0;
    190}
    191EXPORT_SYMBOL_GPL(saa7146_stop_preview);
    192
    193/********************************************************************************/
    194/* common pagetable functions */
    195
    196static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
    197{
    198	struct pci_dev *pci = dev->pci;
    199	struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
    200	struct scatterlist *list = dma->sglist;
    201	int length = dma->sglen;
    202	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
    203
    204	DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
    205
    206	if( 0 != IS_PLANAR(sfmt->trans)) {
    207		struct saa7146_pgtable *pt1 = &buf->pt[0];
    208		struct saa7146_pgtable *pt2 = &buf->pt[1];
    209		struct saa7146_pgtable *pt3 = &buf->pt[2];
    210		__le32  *ptr1, *ptr2, *ptr3;
    211		__le32 fill;
    212
    213		int size = buf->fmt->width*buf->fmt->height;
    214		int i,p,m1,m2,m3,o1,o2;
    215
    216		switch( sfmt->depth ) {
    217			case 12: {
    218				/* create some offsets inside the page table */
    219				m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
    220				m2 = ((size+(size/4)+PAGE_SIZE)/PAGE_SIZE)-1;
    221				m3 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
    222				o1 = size%PAGE_SIZE;
    223				o2 = (size+(size/4))%PAGE_SIZE;
    224				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
    225					size, m1, m2, m3, o1, o2);
    226				break;
    227			}
    228			case 16: {
    229				/* create some offsets inside the page table */
    230				m1 = ((size+PAGE_SIZE)/PAGE_SIZE)-1;
    231				m2 = ((size+(size/2)+PAGE_SIZE)/PAGE_SIZE)-1;
    232				m3 = ((2*size+PAGE_SIZE)/PAGE_SIZE)-1;
    233				o1 = size%PAGE_SIZE;
    234				o2 = (size+(size/2))%PAGE_SIZE;
    235				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
    236					size, m1, m2, m3, o1, o2);
    237				break;
    238			}
    239			default: {
    240				return -1;
    241			}
    242		}
    243
    244		ptr1 = pt1->cpu;
    245		ptr2 = pt2->cpu;
    246		ptr3 = pt3->cpu;
    247
    248		/* walk all pages, copy all page addresses to ptr1 */
    249		for (i = 0; i < length; i++, list++) {
    250			for (p = 0; p * 4096 < sg_dma_len(list); p++, ptr1++)
    251				*ptr1 = cpu_to_le32(sg_dma_address(list) - list->offset);
    252		}
    253/*
    254		ptr1 = pt1->cpu;
    255		for(j=0;j<40;j++) {
    256			printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
    257		}
    258*/
    259
    260		/* if we have a user buffer, the first page may not be
    261		   aligned to a page boundary. */
    262		pt1->offset = dma->sglist->offset;
    263		pt2->offset = pt1->offset+o1;
    264		pt3->offset = pt1->offset+o2;
    265
    266		/* create video-dma2 page table */
    267		ptr1 = pt1->cpu;
    268		for(i = m1; i <= m2 ; i++, ptr2++) {
    269			*ptr2 = ptr1[i];
    270		}
    271		fill = *(ptr2-1);
    272		for(;i<1024;i++,ptr2++) {
    273			*ptr2 = fill;
    274		}
    275		/* create video-dma3 page table */
    276		ptr1 = pt1->cpu;
    277		for(i = m2; i <= m3; i++,ptr3++) {
    278			*ptr3 = ptr1[i];
    279		}
    280		fill = *(ptr3-1);
    281		for(;i<1024;i++,ptr3++) {
    282			*ptr3 = fill;
    283		}
    284		/* finally: finish up video-dma1 page table */
    285		ptr1 = pt1->cpu+m1;
    286		fill = pt1->cpu[m1];
    287		for(i=m1;i<1024;i++,ptr1++) {
    288			*ptr1 = fill;
    289		}
    290/*
    291		ptr1 = pt1->cpu;
    292		ptr2 = pt2->cpu;
    293		ptr3 = pt3->cpu;
    294		for(j=0;j<40;j++) {
    295			printk("ptr1 %d: 0x%08x\n",j,ptr1[j]);
    296		}
    297		for(j=0;j<40;j++) {
    298			printk("ptr2 %d: 0x%08x\n",j,ptr2[j]);
    299		}
    300		for(j=0;j<40;j++) {
    301			printk("ptr3 %d: 0x%08x\n",j,ptr3[j]);
    302		}
    303*/
    304	} else {
    305		struct saa7146_pgtable *pt = &buf->pt[0];
    306		return saa7146_pgtable_build_single(pci, pt, list, length);
    307	}
    308
    309	return 0;
    310}
    311
    312
    313/********************************************************************************/
    314/* file operations */
    315
    316static int video_begin(struct saa7146_fh *fh)
    317{
    318	struct saa7146_dev *dev = fh->dev;
    319	struct saa7146_vv *vv = dev->vv_data;
    320	struct saa7146_format *fmt = NULL;
    321	unsigned int resource;
    322	int ret = 0, err = 0;
    323
    324	DEB_EE("dev:%p, fh:%p\n", dev, fh);
    325
    326	if ((vv->video_status & STATUS_CAPTURE) != 0) {
    327		if (vv->video_fh == fh) {
    328			DEB_S("already capturing\n");
    329			return 0;
    330		}
    331		DEB_S("already capturing in another open\n");
    332		return -EBUSY;
    333	}
    334
    335	if ((vv->video_status & STATUS_OVERLAY) != 0) {
    336		DEB_S("warning: suspending overlay video for streaming capture\n");
    337		vv->ov_suspend = vv->video_fh;
    338		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
    339		if (0 != err) {
    340			DEB_D("suspending video failed. aborting\n");
    341			return err;
    342		}
    343	}
    344
    345	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
    346	/* we need to have a valid format set here */
    347	if (!fmt)
    348		return -EINVAL;
    349
    350	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
    351		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
    352	} else {
    353		resource = RESOURCE_DMA1_HPS;
    354	}
    355
    356	ret = saa7146_res_get(fh, resource);
    357	if (0 == ret) {
    358		DEB_S("cannot get capture resource %d\n", resource);
    359		if (vv->ov_suspend != NULL) {
    360			saa7146_start_preview(vv->ov_suspend);
    361			vv->ov_suspend = NULL;
    362		}
    363		return -EBUSY;
    364	}
    365
    366	/* clear out beginning of streaming bit (rps register 0)*/
    367	saa7146_write(dev, MC2, MASK_27 );
    368
    369	/* enable rps0 irqs */
    370	SAA7146_IER_ENABLE(dev, MASK_27);
    371
    372	vv->video_fh = fh;
    373	vv->video_status = STATUS_CAPTURE;
    374
    375	return 0;
    376}
    377
    378static int video_end(struct saa7146_fh *fh, struct file *file)
    379{
    380	struct saa7146_dev *dev = fh->dev;
    381	struct saa7146_vv *vv = dev->vv_data;
    382	struct saa7146_dmaqueue *q = &vv->video_dmaq;
    383	struct saa7146_format *fmt = NULL;
    384	unsigned long flags;
    385	unsigned int resource;
    386	u32 dmas = 0;
    387	DEB_EE("dev:%p, fh:%p\n", dev, fh);
    388
    389	if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
    390		DEB_S("not capturing\n");
    391		return 0;
    392	}
    393
    394	if (vv->video_fh != fh) {
    395		DEB_S("capturing, but in another open\n");
    396		return -EBUSY;
    397	}
    398
    399	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
    400	/* we need to have a valid format set here */
    401	if (!fmt)
    402		return -EINVAL;
    403
    404	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
    405		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
    406		dmas = MASK_22 | MASK_21 | MASK_20;
    407	} else {
    408		resource = RESOURCE_DMA1_HPS;
    409		dmas = MASK_22;
    410	}
    411	spin_lock_irqsave(&dev->slock,flags);
    412
    413	/* disable rps0  */
    414	saa7146_write(dev, MC1, MASK_28);
    415
    416	/* disable rps0 irqs */
    417	SAA7146_IER_DISABLE(dev, MASK_27);
    418
    419	/* shut down all used video dma transfers */
    420	saa7146_write(dev, MC1, dmas);
    421
    422	if (q->curr)
    423		saa7146_buffer_finish(dev, q, VIDEOBUF_DONE);
    424
    425	spin_unlock_irqrestore(&dev->slock, flags);
    426
    427	vv->video_fh = NULL;
    428	vv->video_status = 0;
    429
    430	saa7146_res_free(fh, resource);
    431
    432	if (vv->ov_suspend != NULL) {
    433		saa7146_start_preview(vv->ov_suspend);
    434		vv->ov_suspend = NULL;
    435	}
    436
    437	return 0;
    438}
    439
    440static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
    441{
    442	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    443
    444	strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));
    445	strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
    446	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
    447			    V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
    448			    V4L2_CAP_DEVICE_CAPS;
    449	cap->capabilities |= dev->ext_vv_data->capabilities;
    450	return 0;
    451}
    452
    453static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
    454{
    455	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    456	struct saa7146_vv *vv = dev->vv_data;
    457
    458	*fb = vv->ov_fb;
    459	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
    460	fb->flags = V4L2_FBUF_FLAG_PRIMARY;
    461	return 0;
    462}
    463
    464static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
    465{
    466	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    467	struct saa7146_vv *vv = dev->vv_data;
    468	struct saa7146_format *fmt;
    469
    470	DEB_EE("VIDIOC_S_FBUF\n");
    471
    472	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
    473		return -EPERM;
    474
    475	/* check args */
    476	fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);
    477	if (NULL == fmt)
    478		return -EINVAL;
    479
    480	/* planar formats are not allowed for overlay video, clipping and video dma would clash */
    481	if (fmt->flags & FORMAT_IS_PLANAR)
    482		DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n",
    483		      (char *)&fmt->pixelformat);
    484
    485	/* check if overlay is running */
    486	if (IS_OVERLAY_ACTIVE(fh) != 0) {
    487		if (vv->video_fh != fh) {
    488			DEB_D("refusing to change framebuffer information while overlay is active in another open\n");
    489			return -EBUSY;
    490		}
    491	}
    492
    493	/* ok, accept it */
    494	vv->ov_fb = *fb;
    495	vv->ov_fmt = fmt;
    496
    497	if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
    498		vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
    499		DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
    500	}
    501	return 0;
    502}
    503
    504static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
    505{
    506	if (f->index >= ARRAY_SIZE(formats))
    507		return -EINVAL;
    508	f->pixelformat = formats[f->index].pixelformat;
    509	return 0;
    510}
    511
    512int saa7146_s_ctrl(struct v4l2_ctrl *ctrl)
    513{
    514	struct saa7146_dev *dev = container_of(ctrl->handler,
    515				struct saa7146_dev, ctrl_handler);
    516	struct saa7146_vv *vv = dev->vv_data;
    517	u32 val;
    518
    519	switch (ctrl->id) {
    520	case V4L2_CID_BRIGHTNESS:
    521		val = saa7146_read(dev, BCS_CTRL);
    522		val &= 0x00ffffff;
    523		val |= (ctrl->val << 24);
    524		saa7146_write(dev, BCS_CTRL, val);
    525		saa7146_write(dev, MC2, MASK_22 | MASK_06);
    526		break;
    527
    528	case V4L2_CID_CONTRAST:
    529		val = saa7146_read(dev, BCS_CTRL);
    530		val &= 0xff00ffff;
    531		val |= (ctrl->val << 16);
    532		saa7146_write(dev, BCS_CTRL, val);
    533		saa7146_write(dev, MC2, MASK_22 | MASK_06);
    534		break;
    535
    536	case V4L2_CID_SATURATION:
    537		val = saa7146_read(dev, BCS_CTRL);
    538		val &= 0xffffff00;
    539		val |= (ctrl->val << 0);
    540		saa7146_write(dev, BCS_CTRL, val);
    541		saa7146_write(dev, MC2, MASK_22 | MASK_06);
    542		break;
    543
    544	case V4L2_CID_HFLIP:
    545		/* fixme: we can support changing VFLIP and HFLIP here... */
    546		if ((vv->video_status & STATUS_CAPTURE))
    547			return -EBUSY;
    548		vv->hflip = ctrl->val;
    549		break;
    550
    551	case V4L2_CID_VFLIP:
    552		if ((vv->video_status & STATUS_CAPTURE))
    553			return -EBUSY;
    554		vv->vflip = ctrl->val;
    555		break;
    556
    557	default:
    558		return -EINVAL;
    559	}
    560
    561	if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */
    562		struct saa7146_fh *fh = vv->video_fh;
    563
    564		saa7146_stop_preview(fh);
    565		saa7146_start_preview(fh);
    566	}
    567	return 0;
    568}
    569
    570static int vidioc_g_parm(struct file *file, void *fh,
    571		struct v4l2_streamparm *parm)
    572{
    573	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    574	struct saa7146_vv *vv = dev->vv_data;
    575
    576	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
    577		return -EINVAL;
    578	parm->parm.capture.readbuffers = 1;
    579	v4l2_video_std_frame_period(vv->standard->id,
    580				    &parm->parm.capture.timeperframe);
    581	return 0;
    582}
    583
    584static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
    585{
    586	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    587	struct saa7146_vv *vv = dev->vv_data;
    588
    589	f->fmt.pix = vv->video_fmt;
    590	return 0;
    591}
    592
    593static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
    594{
    595	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    596	struct saa7146_vv *vv = dev->vv_data;
    597
    598	f->fmt.win = vv->ov.win;
    599	return 0;
    600}
    601
    602static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)
    603{
    604	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    605	struct saa7146_vv *vv = dev->vv_data;
    606
    607	f->fmt.vbi = vv->vbi_fmt;
    608	return 0;
    609}
    610
    611static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
    612{
    613	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    614	struct saa7146_vv *vv = dev->vv_data;
    615	struct saa7146_format *fmt;
    616	enum v4l2_field field;
    617	int maxw, maxh;
    618	int calc_bpl;
    619
    620	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
    621
    622	fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
    623	if (NULL == fmt)
    624		return -EINVAL;
    625
    626	field = f->fmt.pix.field;
    627	maxw  = vv->standard->h_max_out;
    628	maxh  = vv->standard->v_max_out;
    629
    630	if (V4L2_FIELD_ANY == field) {
    631		field = (f->fmt.pix.height > maxh / 2)
    632			? V4L2_FIELD_INTERLACED
    633			: V4L2_FIELD_BOTTOM;
    634	}
    635	switch (field) {
    636	case V4L2_FIELD_ALTERNATE:
    637		vv->last_field = V4L2_FIELD_TOP;
    638		maxh = maxh / 2;
    639		break;
    640	case V4L2_FIELD_TOP:
    641	case V4L2_FIELD_BOTTOM:
    642		vv->last_field = V4L2_FIELD_INTERLACED;
    643		maxh = maxh / 2;
    644		break;
    645	case V4L2_FIELD_INTERLACED:
    646		vv->last_field = V4L2_FIELD_INTERLACED;
    647		break;
    648	default:
    649		DEB_D("no known field mode '%d'\n", field);
    650		return -EINVAL;
    651	}
    652
    653	f->fmt.pix.field = field;
    654	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
    655	if (f->fmt.pix.width > maxw)
    656		f->fmt.pix.width = maxw;
    657	if (f->fmt.pix.height > maxh)
    658		f->fmt.pix.height = maxh;
    659
    660	calc_bpl = (f->fmt.pix.width * fmt->depth) / 8;
    661
    662	if (f->fmt.pix.bytesperline < calc_bpl)
    663		f->fmt.pix.bytesperline = calc_bpl;
    664
    665	if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */
    666		f->fmt.pix.bytesperline = calc_bpl;
    667
    668	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
    669	DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",
    670	      f->fmt.pix.width, f->fmt.pix.height,
    671	      f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
    672
    673	return 0;
    674}
    675
    676
    677static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
    678{
    679	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    680	struct saa7146_vv *vv = dev->vv_data;
    681	struct v4l2_window *win = &f->fmt.win;
    682	enum v4l2_field field;
    683	int maxw, maxh;
    684
    685	DEB_EE("dev:%p\n", dev);
    686
    687	if (NULL == vv->ov_fb.base) {
    688		DEB_D("no fb base set\n");
    689		return -EINVAL;
    690	}
    691	if (NULL == vv->ov_fmt) {
    692		DEB_D("no fb fmt set\n");
    693		return -EINVAL;
    694	}
    695	if (win->w.width < 48 || win->w.height < 32) {
    696		DEB_D("min width/height. (%d,%d)\n",
    697		      win->w.width, win->w.height);
    698		return -EINVAL;
    699	}
    700	if (win->clipcount > 16) {
    701		DEB_D("clipcount too big\n");
    702		return -EINVAL;
    703	}
    704
    705	field = win->field;
    706	maxw  = vv->standard->h_max_out;
    707	maxh  = vv->standard->v_max_out;
    708
    709	if (V4L2_FIELD_ANY == field) {
    710		field = (win->w.height > maxh / 2)
    711			? V4L2_FIELD_INTERLACED
    712			: V4L2_FIELD_TOP;
    713		}
    714	switch (field) {
    715	case V4L2_FIELD_TOP:
    716	case V4L2_FIELD_BOTTOM:
    717	case V4L2_FIELD_ALTERNATE:
    718		maxh = maxh / 2;
    719		break;
    720	case V4L2_FIELD_INTERLACED:
    721		break;
    722	default:
    723		DEB_D("no known field mode '%d'\n", field);
    724		return -EINVAL;
    725	}
    726
    727	win->field = field;
    728	if (win->w.width > maxw)
    729		win->w.width = maxw;
    730	if (win->w.height > maxh)
    731		win->w.height = maxh;
    732
    733	return 0;
    734}
    735
    736static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f)
    737{
    738	struct saa7146_fh *fh = __fh;
    739	struct saa7146_dev *dev = fh->dev;
    740	struct saa7146_vv *vv = dev->vv_data;
    741	int err;
    742
    743	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
    744	if (IS_CAPTURE_ACTIVE(fh) != 0) {
    745		DEB_EE("streaming capture is active\n");
    746		return -EBUSY;
    747	}
    748	err = vidioc_try_fmt_vid_cap(file, fh, f);
    749	if (0 != err)
    750		return err;
    751	vv->video_fmt = f->fmt.pix;
    752	DEB_EE("set to pixelformat '%4.4s'\n",
    753	       (char *)&vv->video_fmt.pixelformat);
    754	return 0;
    755}
    756
    757static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f)
    758{
    759	struct saa7146_fh *fh = __fh;
    760	struct saa7146_dev *dev = fh->dev;
    761	struct saa7146_vv *vv = dev->vv_data;
    762	int err;
    763
    764	DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh);
    765	err = vidioc_try_fmt_vid_overlay(file, fh, f);
    766	if (0 != err)
    767		return err;
    768	vv->ov.win    = f->fmt.win;
    769	vv->ov.nclips = f->fmt.win.clipcount;
    770	if (vv->ov.nclips > 16)
    771		vv->ov.nclips = 16;
    772	memcpy(vv->ov.clips, f->fmt.win.clips,
    773	       sizeof(struct v4l2_clip) * vv->ov.nclips);
    774
    775	/* vv->ov.fh is used to indicate that we have valid overlay information, too */
    776	vv->ov.fh = fh;
    777
    778	/* check if our current overlay is active */
    779	if (IS_OVERLAY_ACTIVE(fh) != 0) {
    780		saa7146_stop_preview(fh);
    781		saa7146_start_preview(fh);
    782	}
    783	return 0;
    784}
    785
    786static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
    787{
    788	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    789	struct saa7146_vv *vv = dev->vv_data;
    790
    791	*norm = vv->standard->id;
    792	return 0;
    793}
    794
    795	/* the saa7146 supfhrts (used in conjunction with the saa7111a for example)
    796	   PAL / NTSC / SECAM. if your hardware does not (or does more)
    797	   -- override this function in your extension */
    798/*
    799	case VIDIOC_ENUMSTD:
    800	{
    801		struct v4l2_standard *e = arg;
    802		if (e->index < 0 )
    803			return -EINVAL;
    804		if( e->index < dev->ext_vv_data->num_stds ) {
    805			DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
    806			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
    807			return 0;
    808		}
    809		return -EINVAL;
    810	}
    811	*/
    812
    813static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
    814{
    815	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
    816	struct saa7146_vv *vv = dev->vv_data;
    817	int found = 0;
    818	int err, i;
    819
    820	DEB_EE("VIDIOC_S_STD\n");
    821
    822	if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
    823		DEB_D("cannot change video standard while streaming capture is active\n");
    824		return -EBUSY;
    825	}
    826
    827	if ((vv->video_status & STATUS_OVERLAY) != 0) {
    828		vv->ov_suspend = vv->video_fh;
    829		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
    830		if (0 != err) {
    831			DEB_D("suspending video failed. aborting\n");
    832			return err;
    833		}
    834	}
    835
    836	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
    837		if (id & dev->ext_vv_data->stds[i].id)
    838			break;
    839	if (i != dev->ext_vv_data->num_stds) {
    840		vv->standard = &dev->ext_vv_data->stds[i];
    841		if (NULL != dev->ext_vv_data->std_callback)
    842			dev->ext_vv_data->std_callback(dev, vv->standard);
    843		found = 1;
    844	}
    845
    846	if (vv->ov_suspend != NULL) {
    847		saa7146_start_preview(vv->ov_suspend);
    848		vv->ov_suspend = NULL;
    849	}
    850
    851	if (!found) {
    852		DEB_EE("VIDIOC_S_STD: standard not found\n");
    853		return -EINVAL;
    854	}
    855
    856	DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name);
    857	return 0;
    858}
    859
    860static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
    861{
    862	int err;
    863
    864	DEB_D("VIDIOC_OVERLAY on:%d\n", on);
    865	if (on)
    866		err = saa7146_start_preview(fh);
    867	else
    868		err = saa7146_stop_preview(fh);
    869	return err;
    870}
    871
    872static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b)
    873{
    874	struct saa7146_fh *fh = __fh;
    875
    876	if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
    877		return videobuf_reqbufs(&fh->video_q, b);
    878	if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE)
    879		return videobuf_reqbufs(&fh->vbi_q, b);
    880	return -EINVAL;
    881}
    882
    883static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
    884{
    885	struct saa7146_fh *fh = __fh;
    886
    887	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
    888		return videobuf_querybuf(&fh->video_q, buf);
    889	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
    890		return videobuf_querybuf(&fh->vbi_q, buf);
    891	return -EINVAL;
    892}
    893
    894static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
    895{
    896	struct saa7146_fh *fh = __fh;
    897
    898	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
    899		return videobuf_qbuf(&fh->video_q, buf);
    900	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
    901		return videobuf_qbuf(&fh->vbi_q, buf);
    902	return -EINVAL;
    903}
    904
    905static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
    906{
    907	struct saa7146_fh *fh = __fh;
    908
    909	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
    910		return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK);
    911	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
    912		return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK);
    913	return -EINVAL;
    914}
    915
    916static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
    917{
    918	struct saa7146_fh *fh = __fh;
    919	int err;
    920
    921	DEB_D("VIDIOC_STREAMON, type:%d\n", type);
    922
    923	err = video_begin(fh);
    924	if (err)
    925		return err;
    926	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
    927		return videobuf_streamon(&fh->video_q);
    928	if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
    929		return videobuf_streamon(&fh->vbi_q);
    930	return -EINVAL;
    931}
    932
    933static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
    934{
    935	struct saa7146_fh *fh = __fh;
    936	struct saa7146_dev *dev = fh->dev;
    937	struct saa7146_vv *vv = dev->vv_data;
    938	int err;
    939
    940	DEB_D("VIDIOC_STREAMOFF, type:%d\n", type);
    941
    942	/* ugly: we need to copy some checks from video_end(),
    943	   because videobuf_streamoff() relies on the capture running.
    944	   check and fix this */
    945	if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
    946		DEB_S("not capturing\n");
    947		return 0;
    948	}
    949
    950	if (vv->video_fh != fh) {
    951		DEB_S("capturing, but in another open\n");
    952		return -EBUSY;
    953	}
    954
    955	err = -EINVAL;
    956	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
    957		err = videobuf_streamoff(&fh->video_q);
    958	else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
    959		err = videobuf_streamoff(&fh->vbi_q);
    960	if (0 != err) {
    961		DEB_D("warning: videobuf_streamoff() failed\n");
    962		video_end(fh, file);
    963	} else {
    964		err = video_end(fh, file);
    965	}
    966	return err;
    967}
    968
    969const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
    970	.vidioc_querycap             = vidioc_querycap,
    971	.vidioc_enum_fmt_vid_cap     = vidioc_enum_fmt_vid_cap,
    972	.vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap,
    973	.vidioc_g_fmt_vid_cap        = vidioc_g_fmt_vid_cap,
    974	.vidioc_try_fmt_vid_cap      = vidioc_try_fmt_vid_cap,
    975	.vidioc_s_fmt_vid_cap        = vidioc_s_fmt_vid_cap,
    976	.vidioc_g_fmt_vid_overlay    = vidioc_g_fmt_vid_overlay,
    977	.vidioc_try_fmt_vid_overlay  = vidioc_try_fmt_vid_overlay,
    978	.vidioc_s_fmt_vid_overlay    = vidioc_s_fmt_vid_overlay,
    979
    980	.vidioc_overlay		     = vidioc_overlay,
    981	.vidioc_g_fbuf		     = vidioc_g_fbuf,
    982	.vidioc_s_fbuf		     = vidioc_s_fbuf,
    983	.vidioc_reqbufs              = vidioc_reqbufs,
    984	.vidioc_querybuf             = vidioc_querybuf,
    985	.vidioc_qbuf                 = vidioc_qbuf,
    986	.vidioc_dqbuf                = vidioc_dqbuf,
    987	.vidioc_g_std                = vidioc_g_std,
    988	.vidioc_s_std                = vidioc_s_std,
    989	.vidioc_streamon             = vidioc_streamon,
    990	.vidioc_streamoff            = vidioc_streamoff,
    991	.vidioc_g_parm		     = vidioc_g_parm,
    992	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
    993	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
    994};
    995
    996const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
    997	.vidioc_querycap             = vidioc_querycap,
    998	.vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
    999
   1000	.vidioc_reqbufs              = vidioc_reqbufs,
   1001	.vidioc_querybuf             = vidioc_querybuf,
   1002	.vidioc_qbuf                 = vidioc_qbuf,
   1003	.vidioc_dqbuf                = vidioc_dqbuf,
   1004	.vidioc_g_std                = vidioc_g_std,
   1005	.vidioc_s_std                = vidioc_s_std,
   1006	.vidioc_streamon             = vidioc_streamon,
   1007	.vidioc_streamoff            = vidioc_streamoff,
   1008	.vidioc_g_parm		     = vidioc_g_parm,
   1009	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
   1010	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
   1011};
   1012
   1013/*********************************************************************************/
   1014/* buffer handling functions                                                  */
   1015
   1016static int buffer_activate (struct saa7146_dev *dev,
   1017		     struct saa7146_buf *buf,
   1018		     struct saa7146_buf *next)
   1019{
   1020	struct saa7146_vv *vv = dev->vv_data;
   1021
   1022	buf->vb.state = VIDEOBUF_ACTIVE;
   1023	saa7146_set_capture(dev,buf,next);
   1024
   1025	mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
   1026	return 0;
   1027}
   1028
   1029static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf)
   1030{
   1031	saa7146_pgtable_free(dev->pci, &buf->pt[0]);
   1032	saa7146_pgtable_free(dev->pci, &buf->pt[1]);
   1033	saa7146_pgtable_free(dev->pci, &buf->pt[2]);
   1034}
   1035
   1036static int buffer_prepare(struct videobuf_queue *q,
   1037			  struct videobuf_buffer *vb, enum v4l2_field field)
   1038{
   1039	struct file *file = q->priv_data;
   1040	struct saa7146_fh *fh = file->private_data;
   1041	struct saa7146_dev *dev = fh->dev;
   1042	struct saa7146_vv *vv = dev->vv_data;
   1043	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
   1044	int size,err = 0;
   1045
   1046	DEB_CAP("vbuf:%p\n", vb);
   1047
   1048	/* sanity checks */
   1049	if (vv->video_fmt.width  < 48 ||
   1050	    vv->video_fmt.height < 32 ||
   1051	    vv->video_fmt.width  > vv->standard->h_max_out ||
   1052	    vv->video_fmt.height > vv->standard->v_max_out) {
   1053		DEB_D("w (%d) / h (%d) out of bounds\n",
   1054		      vv->video_fmt.width, vv->video_fmt.height);
   1055		return -EINVAL;
   1056	}
   1057
   1058	size = vv->video_fmt.sizeimage;
   1059	if (0 != buf->vb.baddr && buf->vb.bsize < size) {
   1060		DEB_D("size mismatch\n");
   1061		return -EINVAL;
   1062	}
   1063
   1064	DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
   1065		vv->video_fmt.width, vv->video_fmt.height,
   1066		size, v4l2_field_names[vv->video_fmt.field]);
   1067	if (buf->vb.width  != vv->video_fmt.width  ||
   1068	    buf->vb.bytesperline != vv->video_fmt.bytesperline ||
   1069	    buf->vb.height != vv->video_fmt.height ||
   1070	    buf->vb.size   != size ||
   1071	    buf->vb.field  != field      ||
   1072	    buf->vb.field  != vv->video_fmt.field  ||
   1073	    buf->fmt       != &vv->video_fmt) {
   1074		saa7146_dma_free(dev,q,buf);
   1075	}
   1076
   1077	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
   1078		struct saa7146_format *sfmt;
   1079
   1080		buf->vb.bytesperline  = vv->video_fmt.bytesperline;
   1081		buf->vb.width  = vv->video_fmt.width;
   1082		buf->vb.height = vv->video_fmt.height;
   1083		buf->vb.size   = size;
   1084		buf->vb.field  = field;
   1085		buf->fmt       = &vv->video_fmt;
   1086		buf->vb.field  = vv->video_fmt.field;
   1087
   1088		sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
   1089
   1090		release_all_pagetables(dev, buf);
   1091		if( 0 != IS_PLANAR(sfmt->trans)) {
   1092			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
   1093			saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
   1094			saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
   1095		} else {
   1096			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
   1097		}
   1098
   1099		err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
   1100		if (err)
   1101			goto oops;
   1102		err = saa7146_pgtable_build(dev,buf);
   1103		if (err)
   1104			goto oops;
   1105	}
   1106	buf->vb.state = VIDEOBUF_PREPARED;
   1107	buf->activate = buffer_activate;
   1108
   1109	return 0;
   1110
   1111 oops:
   1112	DEB_D("error out\n");
   1113	saa7146_dma_free(dev,q,buf);
   1114
   1115	return err;
   1116}
   1117
   1118static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
   1119{
   1120	struct file *file = q->priv_data;
   1121	struct saa7146_fh *fh = file->private_data;
   1122	struct saa7146_vv *vv = fh->dev->vv_data;
   1123
   1124	if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)
   1125		*count = MAX_SAA7146_CAPTURE_BUFFERS;
   1126
   1127	*size = vv->video_fmt.sizeimage;
   1128
   1129	/* check if we exceed the "max_memory" parameter */
   1130	if( (*count * *size) > (max_memory*1048576) ) {
   1131		*count = (max_memory*1048576) / *size;
   1132	}
   1133
   1134	DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
   1135
   1136	return 0;
   1137}
   1138
   1139static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
   1140{
   1141	struct file *file = q->priv_data;
   1142	struct saa7146_fh *fh = file->private_data;
   1143	struct saa7146_dev *dev = fh->dev;
   1144	struct saa7146_vv *vv = dev->vv_data;
   1145	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
   1146
   1147	DEB_CAP("vbuf:%p\n", vb);
   1148	saa7146_buffer_queue(fh->dev, &vv->video_dmaq, buf);
   1149}
   1150
   1151static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
   1152{
   1153	struct file *file = q->priv_data;
   1154	struct saa7146_fh *fh = file->private_data;
   1155	struct saa7146_dev *dev = fh->dev;
   1156	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
   1157
   1158	DEB_CAP("vbuf:%p\n", vb);
   1159
   1160	saa7146_dma_free(dev,q,buf);
   1161
   1162	release_all_pagetables(dev, buf);
   1163}
   1164
   1165static const struct videobuf_queue_ops video_qops = {
   1166	.buf_setup    = buffer_setup,
   1167	.buf_prepare  = buffer_prepare,
   1168	.buf_queue    = buffer_queue,
   1169	.buf_release  = buffer_release,
   1170};
   1171
   1172/********************************************************************************/
   1173/* file operations */
   1174
   1175static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
   1176{
   1177	INIT_LIST_HEAD(&vv->video_dmaq.queue);
   1178
   1179	timer_setup(&vv->video_dmaq.timeout, saa7146_buffer_timeout, 0);
   1180	vv->video_dmaq.dev              = dev;
   1181
   1182	/* set some default values */
   1183	vv->standard = &dev->ext_vv_data->stds[0];
   1184
   1185	/* FIXME: what's this? */
   1186	vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
   1187	vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
   1188}
   1189
   1190
   1191static int video_open(struct saa7146_dev *dev, struct file *file)
   1192{
   1193	struct saa7146_fh *fh = file->private_data;
   1194
   1195	videobuf_queue_sg_init(&fh->video_q, &video_qops,
   1196			    &dev->pci->dev, &dev->slock,
   1197			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
   1198			    V4L2_FIELD_INTERLACED,
   1199			    sizeof(struct saa7146_buf),
   1200			    file, &dev->v4l2_lock);
   1201
   1202	return 0;
   1203}
   1204
   1205
   1206static void video_close(struct saa7146_dev *dev, struct file *file)
   1207{
   1208	struct saa7146_fh *fh = file->private_data;
   1209	struct saa7146_vv *vv = dev->vv_data;
   1210	struct videobuf_queue *q = &fh->video_q;
   1211
   1212	if (IS_CAPTURE_ACTIVE(fh) != 0)
   1213		video_end(fh, file);
   1214	else if (IS_OVERLAY_ACTIVE(fh) != 0)
   1215		saa7146_stop_preview(fh);
   1216
   1217	videobuf_stop(q);
   1218	/* hmm, why is this function declared void? */
   1219}
   1220
   1221
   1222static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
   1223{
   1224	struct saa7146_vv *vv = dev->vv_data;
   1225	struct saa7146_dmaqueue *q = &vv->video_dmaq;
   1226
   1227	spin_lock(&dev->slock);
   1228	DEB_CAP("called\n");
   1229
   1230	/* only finish the buffer if we have one... */
   1231	if( NULL != q->curr ) {
   1232		saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);
   1233	}
   1234	saa7146_buffer_next(dev,q,0);
   1235
   1236	spin_unlock(&dev->slock);
   1237}
   1238
   1239static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
   1240{
   1241	struct saa7146_fh *fh = file->private_data;
   1242	struct saa7146_dev *dev = fh->dev;
   1243	struct saa7146_vv *vv = dev->vv_data;
   1244	ssize_t ret = 0;
   1245
   1246	DEB_EE("called\n");
   1247
   1248	if ((vv->video_status & STATUS_CAPTURE) != 0) {
   1249		/* fixme: should we allow read() captures while streaming capture? */
   1250		if (vv->video_fh == fh) {
   1251			DEB_S("already capturing\n");
   1252			return -EBUSY;
   1253		}
   1254		DEB_S("already capturing in another open\n");
   1255		return -EBUSY;
   1256	}
   1257
   1258	ret = video_begin(fh);
   1259	if( 0 != ret) {
   1260		goto out;
   1261	}
   1262
   1263	ret = videobuf_read_one(&fh->video_q , data, count, ppos,
   1264				file->f_flags & O_NONBLOCK);
   1265	if (ret != 0) {
   1266		video_end(fh, file);
   1267	} else {
   1268		ret = video_end(fh, file);
   1269	}
   1270out:
   1271	/* restart overlay if it was active before */
   1272	if (vv->ov_suspend != NULL) {
   1273		saa7146_start_preview(vv->ov_suspend);
   1274		vv->ov_suspend = NULL;
   1275	}
   1276
   1277	return ret;
   1278}
   1279
   1280const struct saa7146_use_ops saa7146_video_uops = {
   1281	.init = video_init,
   1282	.open = video_open,
   1283	.release = video_close,
   1284	.irq_done = video_irq_done,
   1285	.read = video_read,
   1286};