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