saa7146_video.c revision 84a1d9c83e3e13991b958c897b6e9d6a5e4ce76d
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* 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 = 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 = 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 = 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 = 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		/* fixme: we can support changing VFLIP and HFLIP here... */
694		if (IS_CAPTURE_ACTIVE(fh) != 0) {
695			DEB_D(("V4L2_CID_HFLIP while active capture.\n"));
696			mutex_unlock(&dev->lock);
697			return -EBUSY;
698		}
699		vv->hflip = c->value;
700		break;
701	case V4L2_CID_VFLIP:
702		if (IS_CAPTURE_ACTIVE(fh) != 0) {
703			DEB_D(("V4L2_CID_VFLIP while active capture.\n"));
704			mutex_unlock(&dev->lock);
705			return -EBUSY;
706		}
707		vv->vflip = c->value;
708		break;
709	default:
710		mutex_unlock(&dev->lock);
711		return -EINVAL;
712	}
713	mutex_unlock(&dev->lock);
714
715	if (IS_OVERLAY_ACTIVE(fh) != 0) {
716		saa7146_stop_preview(fh);
717		saa7146_start_preview(fh);
718	}
719	return 0;
720}
721
722static int vidioc_g_parm(struct file *file, void *fh,
723		struct v4l2_streamparm *parm)
724{
725	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
726	struct saa7146_vv *vv = dev->vv_data;
727
728	parm->parm.capture.readbuffers = 1;
729	v4l2_video_std_frame_period(vv->standard->id,
730				    &parm->parm.capture.timeperframe);
731	return 0;
732}
733
734static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
735{
736	f->fmt.pix = ((struct saa7146_fh *)fh)->video_fmt;
737	return 0;
738}
739
740static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
741{
742	f->fmt.win = ((struct saa7146_fh *)fh)->ov.win;
743	return 0;
744}
745
746static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)
747{
748	f->fmt.vbi = ((struct saa7146_fh *)fh)->vbi_fmt;
749	return 0;
750}
751
752static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
753{
754	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
755	struct saa7146_vv *vv = dev->vv_data;
756	struct saa7146_format *fmt;
757	enum v4l2_field field;
758	int maxw, maxh;
759	int calc_bpl;
760
761	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
762
763	fmt = format_by_fourcc(dev, f->fmt.pix.pixelformat);
764	if (NULL == fmt)
765		return -EINVAL;
766
767	field = f->fmt.pix.field;
768	maxw  = vv->standard->h_max_out;
769	maxh  = vv->standard->v_max_out;
770
771	if (V4L2_FIELD_ANY == field) {
772		field = (f->fmt.pix.height > maxh / 2)
773			? V4L2_FIELD_INTERLACED
774			: V4L2_FIELD_BOTTOM;
775	}
776	switch (field) {
777	case V4L2_FIELD_ALTERNATE:
778		vv->last_field = V4L2_FIELD_TOP;
779		maxh = maxh / 2;
780		break;
781	case V4L2_FIELD_TOP:
782	case V4L2_FIELD_BOTTOM:
783		vv->last_field = V4L2_FIELD_INTERLACED;
784		maxh = maxh / 2;
785		break;
786	case V4L2_FIELD_INTERLACED:
787		vv->last_field = V4L2_FIELD_INTERLACED;
788		break;
789	default:
790		DEB_D(("no known field mode '%d'.\n", field));
791		return -EINVAL;
792	}
793
794	f->fmt.pix.field = field;
795	if (f->fmt.pix.width > maxw)
796		f->fmt.pix.width = maxw;
797	if (f->fmt.pix.height > maxh)
798		f->fmt.pix.height = maxh;
799
800	calc_bpl = (f->fmt.pix.width * fmt->depth) / 8;
801
802	if (f->fmt.pix.bytesperline < calc_bpl)
803		f->fmt.pix.bytesperline = calc_bpl;
804
805	if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */
806		f->fmt.pix.bytesperline = calc_bpl;
807
808	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
809	DEB_D(("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n", f->fmt.pix.width,
810			f->fmt.pix.height, f->fmt.pix.bytesperline, f->fmt.pix.sizeimage));
811
812	return 0;
813}
814
815
816static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh, struct v4l2_format *f)
817{
818	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
819	struct saa7146_vv *vv = dev->vv_data;
820	struct v4l2_window *win = &f->fmt.win;
821	enum v4l2_field field;
822	int maxw, maxh;
823
824	DEB_EE(("dev:%p\n", dev));
825
826	if (NULL == vv->ov_fb.base) {
827		DEB_D(("no fb base set.\n"));
828		return -EINVAL;
829	}
830	if (NULL == vv->ov_fmt) {
831		DEB_D(("no fb fmt set.\n"));
832		return -EINVAL;
833	}
834	if (win->w.width < 48 || win->w.height < 32) {
835		DEB_D(("min width/height. (%d,%d)\n", win->w.width, win->w.height));
836		return -EINVAL;
837	}
838	if (win->clipcount > 16) {
839		DEB_D(("clipcount too big.\n"));
840		return -EINVAL;
841	}
842
843	field = win->field;
844	maxw  = vv->standard->h_max_out;
845	maxh  = vv->standard->v_max_out;
846
847	if (V4L2_FIELD_ANY == field) {
848		field = (win->w.height > maxh / 2)
849			? V4L2_FIELD_INTERLACED
850			: V4L2_FIELD_TOP;
851		}
852	switch (field) {
853	case V4L2_FIELD_TOP:
854	case V4L2_FIELD_BOTTOM:
855	case V4L2_FIELD_ALTERNATE:
856		maxh = maxh / 2;
857		break;
858	case V4L2_FIELD_INTERLACED:
859		break;
860	default:
861		DEB_D(("no known field mode '%d'.\n", field));
862		return -EINVAL;
863	}
864
865	win->field = field;
866	if (win->w.width > maxw)
867		win->w.width = maxw;
868	if (win->w.height > maxh)
869		win->w.height = maxh;
870
871	return 0;
872}
873
874static int vidioc_s_fmt_vid_cap(struct file *file, void *__fh, struct v4l2_format *f)
875{
876	struct saa7146_fh *fh = __fh;
877	struct saa7146_dev *dev = fh->dev;
878	struct saa7146_vv *vv = dev->vv_data;
879	int err;
880
881	DEB_EE(("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh));
882	if (IS_CAPTURE_ACTIVE(fh) != 0) {
883		DEB_EE(("streaming capture is active\n"));
884		return -EBUSY;
885	}
886	err = vidioc_try_fmt_vid_cap(file, fh, f);
887	if (0 != err)
888		return err;
889	fh->video_fmt = f->fmt.pix;
890	DEB_EE(("set to pixelformat '%4.4s'\n", (char *)&fh->video_fmt.pixelformat));
891	return 0;
892}
893
894static int vidioc_s_fmt_vid_overlay(struct file *file, void *__fh, struct v4l2_format *f)
895{
896	struct saa7146_fh *fh = __fh;
897	struct saa7146_dev *dev = fh->dev;
898	struct saa7146_vv *vv = dev->vv_data;
899	int err;
900
901	DEB_EE(("V4L2_BUF_TYPE_VIDEO_OVERLAY: dev:%p, fh:%p\n", dev, fh));
902	err = vidioc_try_fmt_vid_overlay(file, fh, f);
903	if (0 != err)
904		return err;
905	mutex_lock(&dev->lock);
906	fh->ov.win    = f->fmt.win;
907	fh->ov.nclips = f->fmt.win.clipcount;
908	if (fh->ov.nclips > 16)
909		fh->ov.nclips = 16;
910	if (copy_from_user(fh->ov.clips, f->fmt.win.clips,
911				sizeof(struct v4l2_clip) * fh->ov.nclips)) {
912		mutex_unlock(&dev->lock);
913		return -EFAULT;
914	}
915
916	/* fh->ov.fh is used to indicate that we have valid overlay informations, too */
917	fh->ov.fh = fh;
918
919	mutex_unlock(&dev->lock);
920
921	/* check if our current overlay is active */
922	if (IS_OVERLAY_ACTIVE(fh) != 0) {
923		saa7146_stop_preview(fh);
924		saa7146_start_preview(fh);
925	}
926	return 0;
927}
928
929static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
930{
931	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
932	struct saa7146_vv *vv = dev->vv_data;
933
934	*norm = vv->standard->id;
935	return 0;
936}
937
938	/* the saa7146 supfhrts (used in conjunction with the saa7111a for example)
939	   PAL / NTSC / SECAM. if your hardware does not (or does more)
940	   -- override this function in your extension */
941/*
942	case VIDIOC_ENUMSTD:
943	{
944		struct v4l2_standard *e = arg;
945		if (e->index < 0 )
946			return -EINVAL;
947		if( e->index < dev->ext_vv_data->num_stds ) {
948			DEB_EE(("VIDIOC_ENUMSTD: index:%d\n",e->index));
949			v4l2_video_std_construct(e, dev->ext_vv_data->stds[e->index].id, dev->ext_vv_data->stds[e->index].name);
950			return 0;
951		}
952		return -EINVAL;
953	}
954	*/
955
956static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
957{
958	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
959	struct saa7146_vv *vv = dev->vv_data;
960	int found = 0;
961	int err, i;
962
963	DEB_EE(("VIDIOC_S_STD\n"));
964
965	if ((vv->video_status & STATUS_CAPTURE) == STATUS_CAPTURE) {
966		DEB_D(("cannot change video standard while streaming capture is active\n"));
967		return -EBUSY;
968	}
969
970	if ((vv->video_status & STATUS_OVERLAY) != 0) {
971		vv->ov_suspend = vv->video_fh;
972		err = saa7146_stop_preview(vv->video_fh); /* side effect: video_status is now 0, video_fh is NULL */
973		if (0 != err) {
974			DEB_D(("suspending video failed. aborting\n"));
975			return err;
976		}
977	}
978
979	mutex_lock(&dev->lock);
980
981	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
982		if (*id & dev->ext_vv_data->stds[i].id)
983			break;
984	if (i != dev->ext_vv_data->num_stds) {
985		vv->standard = &dev->ext_vv_data->stds[i];
986		if (NULL != dev->ext_vv_data->std_callback)
987			dev->ext_vv_data->std_callback(dev, vv->standard);
988		found = 1;
989	}
990
991	mutex_unlock(&dev->lock);
992
993	if (vv->ov_suspend != NULL) {
994		saa7146_start_preview(vv->ov_suspend);
995		vv->ov_suspend = NULL;
996	}
997
998	if (!found) {
999		DEB_EE(("VIDIOC_S_STD: standard not found.\n"));
1000		return -EINVAL;
1001	}
1002
1003	DEB_EE(("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name));
1004	return 0;
1005}
1006
1007static int vidioc_overlay(struct file *file, void *fh, unsigned int on)
1008{
1009	int err;
1010
1011	DEB_D(("VIDIOC_OVERLAY on:%d\n", on));
1012	if (on)
1013		err = saa7146_start_preview(fh);
1014	else
1015		err = saa7146_stop_preview(fh);
1016	return err;
1017}
1018
1019static int vidioc_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *b)
1020{
1021	struct saa7146_fh *fh = __fh;
1022
1023	if (b->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1024		return videobuf_reqbufs(&fh->video_q, b);
1025	if (b->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1026		return videobuf_reqbufs(&fh->vbi_q, b);
1027	return -EINVAL;
1028}
1029
1030static int vidioc_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
1031{
1032	struct saa7146_fh *fh = __fh;
1033
1034	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1035		return videobuf_querybuf(&fh->video_q, buf);
1036	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1037		return videobuf_querybuf(&fh->vbi_q, buf);
1038	return -EINVAL;
1039}
1040
1041static int vidioc_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
1042{
1043	struct saa7146_fh *fh = __fh;
1044
1045	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1046		return videobuf_qbuf(&fh->video_q, buf);
1047	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1048		return videobuf_qbuf(&fh->vbi_q, buf);
1049	return -EINVAL;
1050}
1051
1052static int vidioc_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
1053{
1054	struct saa7146_fh *fh = __fh;
1055
1056	if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1057		return videobuf_dqbuf(&fh->video_q, buf, file->f_flags & O_NONBLOCK);
1058	if (buf->type == V4L2_BUF_TYPE_VBI_CAPTURE)
1059		return videobuf_dqbuf(&fh->vbi_q, buf, file->f_flags & O_NONBLOCK);
1060	return -EINVAL;
1061}
1062
1063static int vidioc_streamon(struct file *file, void *__fh, enum v4l2_buf_type type)
1064{
1065	struct saa7146_fh *fh = __fh;
1066	int err;
1067
1068	DEB_D(("VIDIOC_STREAMON, type:%d\n", type));
1069
1070	err = video_begin(fh);
1071	if (err)
1072		return err;
1073	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1074		return videobuf_streamon(&fh->video_q);
1075	if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
1076		return videobuf_streamon(&fh->vbi_q);
1077	return -EINVAL;
1078}
1079
1080static int vidioc_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type)
1081{
1082	struct saa7146_fh *fh = __fh;
1083	struct saa7146_dev *dev = fh->dev;
1084	struct saa7146_vv *vv = dev->vv_data;
1085	int err;
1086
1087	DEB_D(("VIDIOC_STREAMOFF, type:%d\n", type));
1088
1089	/* ugly: we need to copy some checks from video_end(),
1090	   because videobuf_streamoff() relies on the capture running.
1091	   check and fix this */
1092	if ((vv->video_status & STATUS_CAPTURE) != STATUS_CAPTURE) {
1093		DEB_S(("not capturing.\n"));
1094		return 0;
1095	}
1096
1097	if (vv->video_fh != fh) {
1098		DEB_S(("capturing, but in another open.\n"));
1099		return -EBUSY;
1100	}
1101
1102	err = -EINVAL;
1103	if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
1104		err = videobuf_streamoff(&fh->video_q);
1105	else if (type == V4L2_BUF_TYPE_VBI_CAPTURE)
1106		err = videobuf_streamoff(&fh->vbi_q);
1107	if (0 != err) {
1108		DEB_D(("warning: videobuf_streamoff() failed.\n"));
1109		video_end(fh, file);
1110	} else {
1111		err = video_end(fh, file);
1112	}
1113	return err;
1114}
1115
1116static int vidioc_g_chip_ident(struct file *file, void *__fh,
1117		struct v4l2_dbg_chip_ident *chip)
1118{
1119	struct saa7146_fh *fh = __fh;
1120	struct saa7146_dev *dev = fh->dev;
1121
1122	chip->ident = V4L2_IDENT_NONE;
1123	chip->revision = 0;
1124	if (chip->match.type == V4L2_CHIP_MATCH_HOST && !chip->match.addr) {
1125		chip->ident = V4L2_IDENT_SAA7146;
1126		return 0;
1127	}
1128	return v4l2_device_call_until_err(&dev->v4l2_dev, 0,
1129			core, g_chip_ident, chip);
1130}
1131
1132#ifdef CONFIG_VIDEO_V4L1_COMPAT
1133static int vidiocgmbuf(struct file *file, void *__fh, struct video_mbuf *mbuf)
1134{
1135	struct saa7146_fh *fh = __fh;
1136	struct videobuf_queue *q = &fh->video_q;
1137	int err, i;
1138
1139	/* fixme: number of capture buffers and sizes for v4l apps */
1140	int gbuffers = 2;
1141	int gbufsize = 768 * 576 * 4;
1142
1143	DEB_D(("VIDIOCGMBUF \n"));
1144
1145	q = &fh->video_q;
1146	err = videobuf_mmap_setup(q, gbuffers, gbufsize,
1147			V4L2_MEMORY_MMAP);
1148	if (err < 0)
1149		return err;
1150
1151	gbuffers = err;
1152	memset(mbuf, 0, sizeof(*mbuf));
1153	mbuf->frames = gbuffers;
1154	mbuf->size   = gbuffers * gbufsize;
1155	for (i = 0; i < gbuffers; i++)
1156		mbuf->offsets[i] = i * gbufsize;
1157	return 0;
1158}
1159#endif
1160
1161const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
1162	.vidioc_querycap             = vidioc_querycap,
1163	.vidioc_enum_fmt_vid_cap     = vidioc_enum_fmt_vid_cap,
1164	.vidioc_enum_fmt_vid_overlay = vidioc_enum_fmt_vid_cap,
1165	.vidioc_g_fmt_vid_cap        = vidioc_g_fmt_vid_cap,
1166	.vidioc_try_fmt_vid_cap      = vidioc_try_fmt_vid_cap,
1167	.vidioc_s_fmt_vid_cap        = vidioc_s_fmt_vid_cap,
1168	.vidioc_g_fmt_vid_overlay    = vidioc_g_fmt_vid_overlay,
1169	.vidioc_try_fmt_vid_overlay  = vidioc_try_fmt_vid_overlay,
1170	.vidioc_s_fmt_vid_overlay    = vidioc_s_fmt_vid_overlay,
1171	.vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
1172	.vidioc_g_chip_ident         = vidioc_g_chip_ident,
1173
1174	.vidioc_overlay 	     = vidioc_overlay,
1175	.vidioc_g_fbuf  	     = vidioc_g_fbuf,
1176	.vidioc_s_fbuf  	     = vidioc_s_fbuf,
1177	.vidioc_reqbufs              = vidioc_reqbufs,
1178	.vidioc_querybuf             = vidioc_querybuf,
1179	.vidioc_qbuf                 = vidioc_qbuf,
1180	.vidioc_dqbuf                = vidioc_dqbuf,
1181	.vidioc_g_std                = vidioc_g_std,
1182	.vidioc_s_std                = vidioc_s_std,
1183	.vidioc_queryctrl            = vidioc_queryctrl,
1184	.vidioc_g_ctrl               = vidioc_g_ctrl,
1185	.vidioc_s_ctrl               = vidioc_s_ctrl,
1186	.vidioc_streamon             = vidioc_streamon,
1187	.vidioc_streamoff            = vidioc_streamoff,
1188	.vidioc_g_parm 		     = vidioc_g_parm,
1189#ifdef CONFIG_VIDEO_V4L1_COMPAT
1190	.vidiocgmbuf                 = vidiocgmbuf,
1191#endif
1192};
1193
1194/*********************************************************************************/
1195/* buffer handling functions                                                  */
1196
1197static int buffer_activate (struct saa7146_dev *dev,
1198		     struct saa7146_buf *buf,
1199		     struct saa7146_buf *next)
1200{
1201	struct saa7146_vv *vv = dev->vv_data;
1202
1203	buf->vb.state = VIDEOBUF_ACTIVE;
1204	saa7146_set_capture(dev,buf,next);
1205
1206	mod_timer(&vv->video_q.timeout, jiffies+BUFFER_TIMEOUT);
1207	return 0;
1208}
1209
1210static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf)
1211{
1212	saa7146_pgtable_free(dev->pci, &buf->pt[0]);
1213	saa7146_pgtable_free(dev->pci, &buf->pt[1]);
1214	saa7146_pgtable_free(dev->pci, &buf->pt[2]);
1215}
1216
1217static int buffer_prepare(struct videobuf_queue *q,
1218			  struct videobuf_buffer *vb, enum v4l2_field field)
1219{
1220	struct file *file = q->priv_data;
1221	struct saa7146_fh *fh = file->private_data;
1222	struct saa7146_dev *dev = fh->dev;
1223	struct saa7146_vv *vv = dev->vv_data;
1224	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1225	int size,err = 0;
1226
1227	DEB_CAP(("vbuf:%p\n",vb));
1228
1229	/* sanity checks */
1230	if (fh->video_fmt.width  < 48 ||
1231	    fh->video_fmt.height < 32 ||
1232	    fh->video_fmt.width  > vv->standard->h_max_out ||
1233	    fh->video_fmt.height > vv->standard->v_max_out) {
1234		DEB_D(("w (%d) / h (%d) out of bounds.\n",fh->video_fmt.width,fh->video_fmt.height));
1235		return -EINVAL;
1236	}
1237
1238	size = fh->video_fmt.sizeimage;
1239	if (0 != buf->vb.baddr && buf->vb.bsize < size) {
1240		DEB_D(("size mismatch.\n"));
1241		return -EINVAL;
1242	}
1243
1244	DEB_CAP(("buffer_prepare [size=%dx%d,bytes=%d,fields=%s]\n",
1245		fh->video_fmt.width,fh->video_fmt.height,size,v4l2_field_names[fh->video_fmt.field]));
1246	if (buf->vb.width  != fh->video_fmt.width  ||
1247	    buf->vb.bytesperline != fh->video_fmt.bytesperline ||
1248	    buf->vb.height != fh->video_fmt.height ||
1249	    buf->vb.size   != size ||
1250	    buf->vb.field  != field      ||
1251	    buf->vb.field  != fh->video_fmt.field  ||
1252	    buf->fmt       != &fh->video_fmt) {
1253		saa7146_dma_free(dev,q,buf);
1254	}
1255
1256	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
1257		struct saa7146_format *sfmt;
1258
1259		buf->vb.bytesperline  = fh->video_fmt.bytesperline;
1260		buf->vb.width  = fh->video_fmt.width;
1261		buf->vb.height = fh->video_fmt.height;
1262		buf->vb.size   = size;
1263		buf->vb.field  = field;
1264		buf->fmt       = &fh->video_fmt;
1265		buf->vb.field  = fh->video_fmt.field;
1266
1267		sfmt = format_by_fourcc(dev,buf->fmt->pixelformat);
1268
1269		release_all_pagetables(dev, buf);
1270		if( 0 != IS_PLANAR(sfmt->trans)) {
1271			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
1272			saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
1273			saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
1274		} else {
1275			saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
1276		}
1277
1278		err = videobuf_iolock(q,&buf->vb, &vv->ov_fb);
1279		if (err)
1280			goto oops;
1281		err = saa7146_pgtable_build(dev,buf);
1282		if (err)
1283			goto oops;
1284	}
1285	buf->vb.state = VIDEOBUF_PREPARED;
1286	buf->activate = buffer_activate;
1287
1288	return 0;
1289
1290 oops:
1291	DEB_D(("error out.\n"));
1292	saa7146_dma_free(dev,q,buf);
1293
1294	return err;
1295}
1296
1297static int buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
1298{
1299	struct file *file = q->priv_data;
1300	struct saa7146_fh *fh = file->private_data;
1301
1302	if (0 == *count || *count > MAX_SAA7146_CAPTURE_BUFFERS)
1303		*count = MAX_SAA7146_CAPTURE_BUFFERS;
1304
1305	*size = fh->video_fmt.sizeimage;
1306
1307	/* check if we exceed the "max_memory" parameter */
1308	if( (*count * *size) > (max_memory*1048576) ) {
1309		*count = (max_memory*1048576) / *size;
1310	}
1311
1312	DEB_CAP(("%d buffers, %d bytes each.\n",*count,*size));
1313
1314	return 0;
1315}
1316
1317static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
1318{
1319	struct file *file = q->priv_data;
1320	struct saa7146_fh *fh = file->private_data;
1321	struct saa7146_dev *dev = fh->dev;
1322	struct saa7146_vv *vv = dev->vv_data;
1323	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1324
1325	DEB_CAP(("vbuf:%p\n",vb));
1326	saa7146_buffer_queue(fh->dev,&vv->video_q,buf);
1327}
1328
1329static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
1330{
1331	struct file *file = q->priv_data;
1332	struct saa7146_fh *fh = file->private_data;
1333	struct saa7146_dev *dev = fh->dev;
1334	struct saa7146_buf *buf = (struct saa7146_buf *)vb;
1335
1336	DEB_CAP(("vbuf:%p\n",vb));
1337
1338	saa7146_dma_free(dev,q,buf);
1339
1340	release_all_pagetables(dev, buf);
1341}
1342
1343static struct videobuf_queue_ops video_qops = {
1344	.buf_setup    = buffer_setup,
1345	.buf_prepare  = buffer_prepare,
1346	.buf_queue    = buffer_queue,
1347	.buf_release  = buffer_release,
1348};
1349
1350/********************************************************************************/
1351/* file operations */
1352
1353static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
1354{
1355	INIT_LIST_HEAD(&vv->video_q.queue);
1356
1357	init_timer(&vv->video_q.timeout);
1358	vv->video_q.timeout.function = saa7146_buffer_timeout;
1359	vv->video_q.timeout.data     = (unsigned long)(&vv->video_q);
1360	vv->video_q.dev              = dev;
1361
1362	/* set some default values */
1363	vv->standard = &dev->ext_vv_data->stds[0];
1364
1365	/* FIXME: what's this? */
1366	vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
1367	vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
1368}
1369
1370
1371static int video_open(struct saa7146_dev *dev, struct file *file)
1372{
1373	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
1374	struct saa7146_format *sfmt;
1375
1376	fh->video_fmt.width = 384;
1377	fh->video_fmt.height = 288;
1378	fh->video_fmt.pixelformat = V4L2_PIX_FMT_BGR24;
1379	fh->video_fmt.bytesperline = 0;
1380	fh->video_fmt.field = V4L2_FIELD_ANY;
1381	sfmt = format_by_fourcc(dev,fh->video_fmt.pixelformat);
1382	fh->video_fmt.sizeimage = (fh->video_fmt.width * fh->video_fmt.height * sfmt->depth)/8;
1383
1384	videobuf_queue_sg_init(&fh->video_q, &video_qops,
1385			    &dev->pci->dev, &dev->slock,
1386			    V4L2_BUF_TYPE_VIDEO_CAPTURE,
1387			    V4L2_FIELD_INTERLACED,
1388			    sizeof(struct saa7146_buf),
1389			    file);
1390
1391	return 0;
1392}
1393
1394
1395static void video_close(struct saa7146_dev *dev, struct file *file)
1396{
1397	struct saa7146_fh *fh = (struct saa7146_fh *)file->private_data;
1398	struct saa7146_vv *vv = dev->vv_data;
1399	struct videobuf_queue *q = &fh->video_q;
1400	int err;
1401
1402	if (IS_CAPTURE_ACTIVE(fh) != 0) {
1403		err = video_end(fh, file);
1404	} else if (IS_OVERLAY_ACTIVE(fh) != 0) {
1405		err = saa7146_stop_preview(fh);
1406	}
1407
1408	videobuf_stop(q);
1409
1410	/* hmm, why is this function declared void? */
1411	/* return err */
1412}
1413
1414
1415static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
1416{
1417	struct saa7146_vv *vv = dev->vv_data;
1418	struct saa7146_dmaqueue *q = &vv->video_q;
1419
1420	spin_lock(&dev->slock);
1421	DEB_CAP(("called.\n"));
1422
1423	/* only finish the buffer if we have one... */
1424	if( NULL != q->curr ) {
1425		saa7146_buffer_finish(dev,q,VIDEOBUF_DONE);
1426	}
1427	saa7146_buffer_next(dev,q,0);
1428
1429	spin_unlock(&dev->slock);
1430}
1431
1432static ssize_t video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1433{
1434	struct saa7146_fh *fh = file->private_data;
1435	struct saa7146_dev *dev = fh->dev;
1436	struct saa7146_vv *vv = dev->vv_data;
1437	ssize_t ret = 0;
1438
1439	DEB_EE(("called.\n"));
1440
1441	if ((vv->video_status & STATUS_CAPTURE) != 0) {
1442		/* fixme: should we allow read() captures while streaming capture? */
1443		if (vv->video_fh == fh) {
1444			DEB_S(("already capturing.\n"));
1445			return -EBUSY;
1446		}
1447		DEB_S(("already capturing in another open.\n"));
1448		return -EBUSY;
1449	}
1450
1451	ret = video_begin(fh);
1452	if( 0 != ret) {
1453		goto out;
1454	}
1455
1456	ret = videobuf_read_one(&fh->video_q , data, count, ppos,
1457				file->f_flags & O_NONBLOCK);
1458	if (ret != 0) {
1459		video_end(fh, file);
1460	} else {
1461		ret = video_end(fh, file);
1462	}
1463out:
1464	/* restart overlay if it was active before */
1465	if (vv->ov_suspend != NULL) {
1466		saa7146_start_preview(vv->ov_suspend);
1467		vv->ov_suspend = NULL;
1468	}
1469
1470	return ret;
1471}
1472
1473struct saa7146_use_ops saa7146_video_uops = {
1474	.init = video_init,
1475	.open = video_open,
1476	.release = video_close,
1477	.irq_done = video_irq_done,
1478	.read = video_read,
1479};
1480