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	sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci));
447	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
448			    V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
449			    V4L2_CAP_DEVICE_CAPS;
450	cap->capabilities |= dev->ext_vv_data->capabilities;
451	return 0;
452}
453
454static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
455{
456	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
457	struct saa7146_vv *vv = dev->vv_data;
458
459	*fb = vv->ov_fb;
460	fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
461	fb->flags = V4L2_FBUF_FLAG_PRIMARY;
462	return 0;
463}
464
465static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
466{
467	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
468	struct saa7146_vv *vv = dev->vv_data;
469	struct saa7146_format *fmt;
470
471	DEB_EE("VIDIOC_S_FBUF\n");
472
473	if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
474		return -EPERM;
475
476	/* check args */
477	fmt = saa7146_format_by_fourcc(dev, fb->fmt.pixelformat);
478	if (NULL == fmt)
479		return -EINVAL;
480
481	/* planar formats are not allowed for overlay video, clipping and video dma would clash */
482	if (fmt->flags & FORMAT_IS_PLANAR)
483		DEB_S("planar pixelformat '%4.4s' not allowed for overlay\n",
484		      (char *)&fmt->pixelformat);
485
486	/* check if overlay is running */
487	if (IS_OVERLAY_ACTIVE(fh) != 0) {
488		if (vv->video_fh != fh) {
489			DEB_D("refusing to change framebuffer information while overlay is active in another open\n");
490			return -EBUSY;
491		}
492	}
493
494	/* ok, accept it */
495	vv->ov_fb = *fb;
496	vv->ov_fmt = fmt;
497
498	if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) {
499		vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8;
500		DEB_D("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline);
501	}
502	return 0;
503}
504
505static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
506{
507	if (f->index >= ARRAY_SIZE(formats))
508		return -EINVAL;
509	f->pixelformat = formats[f->index].pixelformat;
510	return 0;
511}
512
513int saa7146_s_ctrl(struct v4l2_ctrl *ctrl)
514{
515	struct saa7146_dev *dev = container_of(ctrl->handler,
516				struct saa7146_dev, ctrl_handler);
517	struct saa7146_vv *vv = dev->vv_data;
518	u32 val;
519
520	switch (ctrl->id) {
521	case V4L2_CID_BRIGHTNESS:
522		val = saa7146_read(dev, BCS_CTRL);
523		val &= 0x00ffffff;
524		val |= (ctrl->val << 24);
525		saa7146_write(dev, BCS_CTRL, val);
526		saa7146_write(dev, MC2, MASK_22 | MASK_06);
527		break;
528
529	case V4L2_CID_CONTRAST:
530		val = saa7146_read(dev, BCS_CTRL);
531		val &= 0xff00ffff;
532		val |= (ctrl->val << 16);
533		saa7146_write(dev, BCS_CTRL, val);
534		saa7146_write(dev, MC2, MASK_22 | MASK_06);
535		break;
536
537	case V4L2_CID_SATURATION:
538		val = saa7146_read(dev, BCS_CTRL);
539		val &= 0xffffff00;
540		val |= (ctrl->val << 0);
541		saa7146_write(dev, BCS_CTRL, val);
542		saa7146_write(dev, MC2, MASK_22 | MASK_06);
543		break;
544
545	case V4L2_CID_HFLIP:
546		/* fixme: we can support changing VFLIP and HFLIP here... */
547		if ((vv->video_status & STATUS_CAPTURE))
548			return -EBUSY;
549		vv->hflip = ctrl->val;
550		break;
551
552	case V4L2_CID_VFLIP:
553		if ((vv->video_status & STATUS_CAPTURE))
554			return -EBUSY;
555		vv->vflip = ctrl->val;
556		break;
557
558	default:
559		return -EINVAL;
560	}
561
562	if ((vv->video_status & STATUS_OVERLAY) != 0) { /* CHECK: && (vv->video_fh == fh)) */
563		struct saa7146_fh *fh = vv->video_fh;
564
565		saa7146_stop_preview(fh);
566		saa7146_start_preview(fh);
567	}
568	return 0;
569}
570
571static int vidioc_g_parm(struct file *file, void *fh,
572		struct v4l2_streamparm *parm)
573{
574	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
575	struct saa7146_vv *vv = dev->vv_data;
576
577	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
578		return -EINVAL;
579	parm->parm.capture.readbuffers = 1;
580	v4l2_video_std_frame_period(vv->standard->id,
581				    &parm->parm.capture.timeperframe);
582	return 0;
583}
584
585static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
586{
587	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
588	struct saa7146_vv *vv = dev->vv_data;
589
590	f->fmt.pix = vv->video_fmt;
591	return 0;
592}
593
594static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
595{
596	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
597	struct saa7146_vv *vv = dev->vv_data;
598
599	f->fmt.win = vv->ov.win;
600	return 0;
601}
602
603static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)
604{
605	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
606	struct saa7146_vv *vv = dev->vv_data;
607
608	f->fmt.vbi = vv->vbi_fmt;
609	return 0;
610}
611
612static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
613{
614	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
615	struct saa7146_vv *vv = dev->vv_data;
616	struct saa7146_format *fmt;
617	enum v4l2_field field;
618	int maxw, maxh;
619	int calc_bpl;
620
621	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
622
623	fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
624	if (NULL == fmt)
625		return -EINVAL;
626
627	field = f->fmt.pix.field;
628	maxw  = vv->standard->h_max_out;
629	maxh  = vv->standard->v_max_out;
630
631	if (V4L2_FIELD_ANY == field) {
632		field = (f->fmt.pix.height > maxh / 2)
633			? V4L2_FIELD_INTERLACED
634			: V4L2_FIELD_BOTTOM;
635	}
636	switch (field) {
637	case V4L2_FIELD_ALTERNATE:
638		vv->last_field = V4L2_FIELD_TOP;
639		maxh = maxh / 2;
640		break;
641	case V4L2_FIELD_TOP:
642	case V4L2_FIELD_BOTTOM:
643		vv->last_field = V4L2_FIELD_INTERLACED;
644		maxh = maxh / 2;
645		break;
646	case V4L2_FIELD_INTERLACED:
647		vv->last_field = V4L2_FIELD_INTERLACED;
648		break;
649	default:
650		DEB_D("no known field mode '%d'\n", field);
651		return -EINVAL;
652	}
653
654	f->fmt.pix.field = field;
655	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
656	if (f->fmt.pix.width > maxw)
657		f->fmt.pix.width = maxw;
658	if (f->fmt.pix.height > maxh)
659		f->fmt.pix.height = maxh;
660
661	calc_bpl = (f->fmt.pix.width * fmt->depth) / 8;
662
663	if (f->fmt.pix.bytesperline < calc_bpl)
664		f->fmt.pix.bytesperline = calc_bpl;
665
666	if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */
667		f->fmt.pix.bytesperline = calc_bpl;
668
669	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
670	DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",
671	      f->fmt.pix.width, f->fmt.pix.height,
672	      f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
673
674	return 0;
675}
676
677
678static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
679{
680	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
681	struct saa7146_vv *vv = dev->vv_data;
682	struct v4l2_window *win = &f->fmt.win;
683	enum v4l2_field field;
684	int maxw, maxh;
685
686	DEB_EE("dev:%p\n", dev);
687
688	if (NULL == vv->ov_fb.base) {
689		DEB_D("no fb base set\n");
690		return -EINVAL;
691	}
692	if (NULL == vv->ov_fmt) {
693		DEB_D("no fb fmt set\n");
694		return -EINVAL;
695	}
696	if (win->w.width < 48 || win->w.height < 32) {
697		DEB_D("min width/height. (%d,%d)\n",
698		      win->w.width, win->w.height);
699		return -EINVAL;
700	}
701	if (win->clipcount > 16) {
702		DEB_D("clipcount too big\n");
703		return -EINVAL;
704	}
705
706	field = win->field;
707	maxw  = vv->standard->h_max_out;
708	maxh  = vv->standard->v_max_out;
709
710	if (V4L2_FIELD_ANY == field) {
711		field = (win->w.height > maxh / 2)
712			? V4L2_FIELD_INTERLACED
713			: V4L2_FIELD_TOP;
714		}
715	switch (field) {
716	case V4L2_FIELD_TOP:
717	case V4L2_FIELD_BOTTOM:
718	case V4L2_FIELD_ALTERNATE:
719		maxh = maxh / 2;
720		break;
721	case V4L2_FIELD_INTERLACED:
722		break;
723	default:
724		DEB_D("no known field mode '%d'\n", field);
725		return -EINVAL;
726	}
727
728	win->field = field;
729	if (win->w.width > maxw)
730		win->w.width = maxw;
731	if (win->w.height > maxh)
732		win->w.height = maxh;
733
734	return 0;
735}
736
737static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f)
738{
739	struct saa7146_fh *fh = __fh;
740	struct saa7146_dev *dev = fh->dev;
741	struct saa7146_vv *vv = dev->vv_data;
742	int err;
743
744	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
745	if (IS_CAPTURE_ACTIVE(fh) != 0) {
746		DEB_EE("streaming capture is active\n");
747		return -EBUSY;
748	}
749	err = vidioc_try_fmt_vid_cap(file, fh, f);
750	if (0 != err)
751		return err;
752	vv->video_fmt = f->fmt.pix;
753	DEB_EE("set to pixelformat '%4.4s'\n",
754	       (char *)&vv->video_fmt.pixelformat);
755	return 0;
756}
757
758static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f)
759{
760	struct saa7146_fh *fh = __fh;
761	struct saa7146_dev *dev = fh->dev;
762	struct saa7146_vv *vv = dev->vv_data;
763	int err;
764
765	DEB_EE("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh);
766	err = vidioc_try_fmt_vid_overlay(file, fh, f);
767	if (0 != err)
768		return err;
769	vv->ov.win    = f->fmt.win;
770	vv->ov.nclips = f->fmt.win.clipcount;
771	if (vv->ov.nclips > 16)
772		vv->ov.nclips = 16;
773	if (copy_from_user(vv->ov.clips, f->fmt.win.clips,
774				sizeof(struct v4l2_clip) * vv->ov.nclips)) {
775		return -EFAULT;
776	}
777
778	/* vv->ov.fh is used to indicate that we have valid overlay information, too */
779	vv->ov.fh = fh;
780
781	/* check if our current overlay is active */
782	if (IS_OVERLAY_ACTIVE(fh) != 0) {
783		saa7146_stop_preview(fh);
784		saa7146_start_preview(fh);
785	}
786	return 0;
787}
788
789static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
790{
791	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
792	struct saa7146_vv *vv = dev->vv_data;
793
794	*norm = vv->standard->id;
795	return 0;
796}
797
798	/* the saa7146 supfhrts (used in conjunction with the saa7111a for example)
799	   PAL / NTSC / SECAM. if your hardware does not (or does more)
800	   -- override this function in your extension */
801/*
802	case VIDIOC_ENUMSTD:
803	{
804		struct v4l2_standard *e = arg;
805		if (e->index < 0 )
806			return -EINVAL;
807		if( e->index < dev->ext_vv_data->num_stds ) {
808			DEB_EE("VIDIOC_ENUMSTD: index:%d\n", e->index);
809			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
810			return 0;
811		}
812		return -EINVAL;
813	}
814	*/
815
816static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
817{
818	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
819	struct saa7146_vv *vv = dev->vv_data;
820	int found = 0;
821	int err, i;
822
823	DEB_EE("VIDIOC_S_STD\n");
824
825	if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
826		DEB_D("cannot change video standard while streaming capture is active\n");
827		return -EBUSY;
828	}
829
830	if ((vv->video_status & STATUS_OVERLAY) != 0) {
831		vv->ov_suspend = vv->video_fh;
832		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
833		if (0 != err) {
834			DEB_D("suspending video failed. aborting\n");
835			return err;
836		}
837	}
838
839	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
840		if (id & dev->ext_vv_data->stds[i].id)
841			break;
842	if (i != dev->ext_vv_data->num_stds) {
843		vv->standard = &dev->ext_vv_data->stds[i];
844		if (NULL != dev->ext_vv_data->std_callback)
845			dev->ext_vv_data->std_callback(dev, vv->standard);
846		found = 1;
847	}
848
849	if (vv->ov_suspend != NULL) {
850		saa7146_start_preview(vv->ov_suspend);
851		vv->ov_suspend = NULL;
852	}
853
854	if (!found) {
855		DEB_EE("VIDIOC_S_STD: standard not found\n");
856		return -EINVAL;
857	}
858
859	DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name);
860	return 0;
861}
862
863static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
864{
865	int err;
866
867	DEB_D("VIDIOC_OVERLAY on:%d\n", on);
868	if (on)
869		err = saa7146_start_preview(fh);
870	else
871		err = saa7146_stop_preview(fh);
872	return err;
873}
874
875static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b)
876{
877	struct saa7146_fh *fh = __fh;
878
879	if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
880		return videobuf_reqbufs(&fh->video_q, b);
881	if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE)
882		return videobuf_reqbufs(&fh->vbi_q, b);
883	return -EINVAL;
884}
885
886static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
887{
888	struct saa7146_fh *fh = __fh;
889
890	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
891		return videobuf_querybuf(&fh->video_q, buf);
892	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
893		return videobuf_querybuf(&fh->vbi_q, buf);
894	return -EINVAL;
895}
896
897static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
898{
899	struct saa7146_fh *fh = __fh;
900
901	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
902		return videobuf_qbuf(&fh->video_q, buf);
903	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
904		return videobuf_qbuf(&fh->vbi_q, buf);
905	return -EINVAL;
906}
907
908static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
909{
910	struct saa7146_fh *fh = __fh;
911
912	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
913		return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK);
914	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
915		return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK);
916	return -EINVAL;
917}
918
919static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
920{
921	struct saa7146_fh *fh = __fh;
922	int err;
923
924	DEB_D("VIDIOC_STREAMON, type:%d\n", type);
925
926	err = video_begin(fh);
927	if (err)
928		return err;
929	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
930		return videobuf_streamon(&fh->video_q);
931	if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
932		return videobuf_streamon(&fh->vbi_q);
933	return -EINVAL;
934}
935
936static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
937{
938	struct saa7146_fh *fh = __fh;
939	struct saa7146_dev *dev = fh->dev;
940	struct saa7146_vv *vv = dev->vv_data;
941	int err;
942
943	DEB_D("VIDIOC_STREAMOFF, type:%d\n", type);
944
945	/* ugly: we need to copy some checks from video_end(),
946	   because videobuf_streamoff() relies on the capture running.
947	   check and fix this */
948	if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
949		DEB_S("not capturing\n");
950		return 0;
951	}
952
953	if (vv->video_fh != fh) {
954		DEB_S("capturing, but in another open\n");
955		return -EBUSY;
956	}
957
958	err = -EINVAL;
959	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
960		err = videobuf_streamoff(&fh->video_q);
961	else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
962		err = videobuf_streamoff(&fh->vbi_q);
963	if (0 != err) {
964		DEB_D("warning: videobuf_streamoff() failed\n");
965		video_end(fh, file);
966	} else {
967		err = video_end(fh, file);
968	}
969	return err;
970}
971
972const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
973	.vidioc_querycap             = vidioc_querycap,
974	.vidioc_enum_fmt_vid_cap     = vidioc_enum_fmt_vid_cap,
975	.vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap,
976	.vidioc_g_fmt_vid_cap        = vidioc_g_fmt_vid_cap,
977	.vidioc_try_fmt_vid_cap      = vidioc_try_fmt_vid_cap,
978	.vidioc_s_fmt_vid_cap        = vidioc_s_fmt_vid_cap,
979	.vidioc_g_fmt_vid_overlay    = vidioc_g_fmt_vid_overlay,
980	.vidioc_try_fmt_vid_overlay  = vidioc_try_fmt_vid_overlay,
981	.vidioc_s_fmt_vid_overlay    = vidioc_s_fmt_vid_overlay,
982
983	.vidioc_overlay		     = vidioc_overlay,
984	.vidioc_g_fbuf		     = vidioc_g_fbuf,
985	.vidioc_s_fbuf		     = vidioc_s_fbuf,
986	.vidioc_reqbufs              = vidioc_reqbufs,
987	.vidioc_querybuf             = vidioc_querybuf,
988	.vidioc_qbuf                 = vidioc_qbuf,
989	.vidioc_dqbuf                = vidioc_dqbuf,
990	.vidioc_g_std                = vidioc_g_std,
991	.vidioc_s_std                = vidioc_s_std,
992	.vidioc_streamon             = vidioc_streamon,
993	.vidioc_streamoff            = vidioc_streamoff,
994	.vidioc_g_parm		     = vidioc_g_parm,
995	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
996	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
997};
998
999const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
1000	.vidioc_querycap             = vidioc_querycap,
1001	.vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
1002
1003	.vidioc_reqbufs              = vidioc_reqbufs,
1004	.vidioc_querybuf             = vidioc_querybuf,
1005	.vidioc_qbuf                 = vidioc_qbuf,
1006	.vidioc_dqbuf                = vidioc_dqbuf,
1007	.vidioc_g_std                = vidioc_g_std,
1008	.vidioc_s_std                = vidioc_s_std,
1009	.vidioc_streamon             = vidioc_streamon,
1010	.vidioc_streamoff            = vidioc_streamoff,
1011	.vidioc_g_parm		     = vidioc_g_parm,
1012	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
1013	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
1014};
1015
1016/*********************************************************************************/
1017/* buffer handling functions                                                  */
1018
1019static int buffer_activate (struct saa7146_dev *dev,
1020		     struct saa7146_buf *buf,
1021		     struct saa7146_buf *next)
1022{
1023	struct saa7146_vv *vv = dev->vv_data;
1024
1025	buf->vb.state = VIDEOBUF_ACTIVE;
1026	saa7146_set_capture(dev,buf,next);
1027
1028	mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
1029	return 0;
1030}
1031
1032static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf)
1033{
1034	saa7146_pgtable_free(dev->pci, &buf->pt[0]);
1035	saa7146_pgtable_free(dev->pci, &buf->pt[1]);
1036	saa7146_pgtable_free(dev->pci, &buf->pt[2]);
1037}
1038
1039static int buffer_prepare(struct videobuf_queue *q,
1040			  struct videobuf_buffer *vb, enum v4l2_field field)
1041{
1042	struct file *file = q->priv_data;
1043	struct saa7146_fh *fh = file->private_data;
1044	struct saa7146_dev *dev = fh->dev;
1045	struct saa7146_vv *vv = dev->vv_data;
1046	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1047	int size,err = 0;
1048
1049	DEB_CAP("vbuf:%p\n", vb);
1050
1051	/* sanity checks */
1052	if (vv->video_fmt.width  < 48 ||
1053	    vv->video_fmt.height < 32 ||
1054	    vv->video_fmt.width  > vv->standard->h_max_out ||
1055	    vv->video_fmt.height > vv->standard->v_max_out) {
1056		DEB_D("w (%d) / h (%d) out of bounds\n",
1057		      vv->video_fmt.width, vv->video_fmt.height);
1058		return -EINVAL;
1059	}
1060
1061	size = vv->video_fmt.sizeimage;
1062	if (0 != buf->vb.baddr && buf->vb.bsize < size) {
1063		DEB_D("size mismatch\n");
1064		return -EINVAL;
1065	}
1066
1067	DEB_CAP("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
1068		vv->video_fmt.width, vv->video_fmt.height,
1069		size, v4l2_field_names[vv->video_fmt.field]);
1070	if (buf->vb.width  != vv->video_fmt.width  ||
1071	    buf->vb.bytesperline != vv->video_fmt.bytesperline ||
1072	    buf->vb.height != vv->video_fmt.height ||
1073	    buf->vb.size   != size ||
1074	    buf->vb.field  != field      ||
1075	    buf->vb.field  != vv->video_fmt.field  ||
1076	    buf->fmt       != &vv->video_fmt) {
1077		saa7146_dma_free(dev,q,buf);
1078	}
1079
1080	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
1081		struct saa7146_format *sfmt;
1082
1083		buf->vb.bytesperline  = vv->video_fmt.bytesperline;
1084		buf->vb.width  = vv->video_fmt.width;
1085		buf->vb.height = vv->video_fmt.height;
1086		buf->vb.size   = size;
1087		buf->vb.field  = field;
1088		buf->fmt       = &vv->video_fmt;
1089		buf->vb.field  = vv->video_fmt.field;
1090
1091		sfmt = saa7146_format_by_fourcc(dev,buf->fmt->pixelformat);
1092
1093		release_all_pagetables(dev, buf);
1094		if( 0 != IS_PLANAR(sfmt->trans)) {
1095			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
1096			saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
1097			saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
1098		} else {
1099			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
1100		}
1101
1102		err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
1103		if (err)
1104			goto oops;
1105		err = saa7146_pgtable_build(dev,buf);
1106		if (err)
1107			goto oops;
1108	}
1109	buf->vb.state = VIDEOBUF_PREPARED;
1110	buf->activate = buffer_activate;
1111
1112	return 0;
1113
1114 oops:
1115	DEB_D("error out\n");
1116	saa7146_dma_free(dev,q,buf);
1117
1118	return err;
1119}
1120
1121static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1122{
1123	struct file *file = q->priv_data;
1124	struct saa7146_fh *fh = file->private_data;
1125	struct saa7146_vv *vv = fh->dev->vv_data;
1126
1127	if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)
1128		*count = MAX_SAA7146_CAPTURE_BUFFERS;
1129
1130	*size = vv->video_fmt.sizeimage;
1131
1132	/* check if we exceed the "max_memory" parameter */
1133	if( (*count * *size) > (max_memory*1048576) ) {
1134		*count = (max_memory*1048576) / *size;
1135	}
1136
1137	DEB_CAP("%d buffers, %d bytes each\n", *count, *size);
1138
1139	return 0;
1140}
1141
1142static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1143{
1144	struct file *file = q->priv_data;
1145	struct saa7146_fh *fh = file->private_data;
1146	struct saa7146_dev *dev = fh->dev;
1147	struct saa7146_vv *vv = dev->vv_data;
1148	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1149
1150	DEB_CAP("vbuf:%p\n", vb);
1151	saa7146_buffer_queue(fh->dev, &vv->video_dmaq, buf);
1152}
1153
1154static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1155{
1156	struct file *file = q->priv_data;
1157	struct saa7146_fh *fh = file->private_data;
1158	struct saa7146_dev *dev = fh->dev;
1159	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1160
1161	DEB_CAP("vbuf:%p\n", vb);
1162
1163	saa7146_dma_free(dev,q,buf);
1164
1165	release_all_pagetables(dev, buf);
1166}
1167
1168static const struct videobuf_queue_ops video_qops = {
1169	.buf_setup    = buffer_setup,
1170	.buf_prepare  = buffer_prepare,
1171	.buf_queue    = buffer_queue,
1172	.buf_release  = buffer_release,
1173};
1174
1175/********************************************************************************/
1176/* file operations */
1177
1178static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
1179{
1180	INIT_LIST_HEAD(&vv->video_dmaq.queue);
1181
1182	timer_setup(&vv->video_dmaq.timeout, saa7146_buffer_timeout, 0);
1183	vv->video_dmaq.dev              = dev;
1184
1185	/* set some default values */
1186	vv->standard = &dev->ext_vv_data->stds[0];
1187
1188	/* FIXME: what's this? */
1189	vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
1190	vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
1191}
1192
1193
1194static int video_open(struct saa7146_dev *dev, struct file *file)
1195{
1196	struct saa7146_fh *fh = file->private_data;
1197
1198	videobuf_queue_sg_init(&fh->video_q, &video_qops,
1199			    &dev->pci->dev, &dev->slock,
1200			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
1201			    V4L2_FIELD_INTERLACED,
1202			    sizeof(struct saa7146_buf),
1203			    file, &dev->v4l2_lock);
1204
1205	return 0;
1206}
1207
1208
1209static void video_close(struct saa7146_dev *dev, struct file *file)
1210{
1211	struct saa7146_fh *fh = file->private_data;
1212	struct saa7146_vv *vv = dev->vv_data;
1213	struct videobuf_queue *q = &fh->video_q;
1214
1215	if (IS_CAPTURE_ACTIVE(fh) != 0)
1216		video_end(fh, file);
1217	else if (IS_OVERLAY_ACTIVE(fh) != 0)
1218		saa7146_stop_preview(fh);
1219
1220	videobuf_stop(q);
1221	/* hmm, why is this function declared void? */
1222}
1223
1224
1225static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
1226{
1227	struct saa7146_vv *vv = dev->vv_data;
1228	struct saa7146_dmaqueue *q = &vv->video_dmaq;
1229
1230	spin_lock(&dev->slock);
1231	DEB_CAP("called\n");
1232
1233	/* only finish the buffer if we have one... */
1234	if( NULL != q->curr ) {
1235		saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);
1236	}
1237	saa7146_buffer_next(dev,q,0);
1238
1239	spin_unlock(&dev->slock);
1240}
1241
1242static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1243{
1244	struct saa7146_fh *fh = file->private_data;
1245	struct saa7146_dev *dev = fh->dev;
1246	struct saa7146_vv *vv = dev->vv_data;
1247	ssize_t ret = 0;
1248
1249	DEB_EE("called\n");
1250
1251	if ((vv->video_status & STATUS_CAPTURE) != 0) {
1252		/* fixme: should we allow read() captures while streaming capture? */
1253		if (vv->video_fh == fh) {
1254			DEB_S("already capturing\n");
1255			return -EBUSY;
1256		}
1257		DEB_S("already capturing in another open\n");
1258		return -EBUSY;
1259	}
1260
1261	ret = video_begin(fh);
1262	if( 0 != ret) {
1263		goto out;
1264	}
1265
1266	ret = videobuf_read_one(&fh->video_q , data, count, ppos,
1267				file->f_flags & O_NONBLOCK);
1268	if (ret != 0) {
1269		video_end(fh, file);
1270	} else {
1271		ret = video_end(fh, file);
1272	}
1273out:
1274	/* restart overlay if it was active before */
1275	if (vv->ov_suspend != NULL) {
1276		saa7146_start_preview(vv->ov_suspend);
1277		vv->ov_suspend = NULL;
1278	}
1279
1280	return ret;
1281}
1282
1283const struct saa7146_use_ops saa7146_video_uops = {
1284	.init = video_init,
1285	.open = video_open,
1286	.release = video_close,
1287	.irq_done = video_irq_done,
1288	.read = video_read,
1289};
1290