xref: /linux/drivers/media/common/saa7146/saa7146_video.c (revision fd7d598270724cc787982ea48bbe17ad383a8b7f)
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 
9 /* format descriptions for capture and preview */
10 static struct saa7146_format formats[] = {
11 	{
12 		.pixelformat	= V4L2_PIX_FMT_RGB332,
13 		.trans		= RGB08_COMPOSED,
14 		.depth		= 8,
15 		.flags		= 0,
16 	}, {
17 		.pixelformat	= V4L2_PIX_FMT_RGB565,
18 		.trans		= RGB16_COMPOSED,
19 		.depth		= 16,
20 		.flags		= 0,
21 	}, {
22 		.pixelformat	= V4L2_PIX_FMT_BGR24,
23 		.trans		= RGB24_COMPOSED,
24 		.depth		= 24,
25 		.flags		= 0,
26 	}, {
27 		.pixelformat	= V4L2_PIX_FMT_BGR32,
28 		.trans		= RGB32_COMPOSED,
29 		.depth		= 32,
30 		.flags		= 0,
31 	}, {
32 		.pixelformat	= V4L2_PIX_FMT_RGB32,
33 		.trans		= RGB32_COMPOSED,
34 		.depth		= 32,
35 		.flags		= 0,
36 		.swap		= 0x2,
37 	}, {
38 		.pixelformat	= V4L2_PIX_FMT_GREY,
39 		.trans		= Y8,
40 		.depth		= 8,
41 		.flags		= 0,
42 	}, {
43 		.pixelformat	= V4L2_PIX_FMT_YUV422P,
44 		.trans		= YUV422_DECOMPOSED,
45 		.depth		= 16,
46 		.flags		= FORMAT_IS_PLANAR,
47 	}, {
48 		.pixelformat	= V4L2_PIX_FMT_YVU420,
49 		.trans		= YUV420_DECOMPOSED,
50 		.depth		= 12,
51 		.flags		= FORMAT_BYTE_SWAP|FORMAT_IS_PLANAR,
52 	}, {
53 		.pixelformat	= V4L2_PIX_FMT_YUV420,
54 		.trans		= YUV420_DECOMPOSED,
55 		.depth		= 12,
56 		.flags		= FORMAT_IS_PLANAR,
57 	}, {
58 		.pixelformat	= V4L2_PIX_FMT_UYVY,
59 		.trans		= YUV422_COMPOSED,
60 		.depth		= 16,
61 		.flags		= 0,
62 	}
63 };
64 
65 /* unfortunately, the saa7146 contains a bug which prevents it from doing on-the-fly byte swaps.
66    due to this, it's impossible to provide additional *packed* formats, which are simply byte swapped
67    (like V4L2_PIX_FMT_YUYV) ... 8-( */
68 
69 struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc)
70 {
71 	int i;
72 
73 	for (i = 0; i < ARRAY_SIZE(formats); i++) {
74 		if (formats[i].pixelformat == fourcc) {
75 			return formats+i;
76 		}
77 	}
78 
79 	DEB_D("unknown pixelformat:'%4.4s'\n", (char *)&fourcc);
80 	return NULL;
81 }
82 
83 /********************************************************************************/
84 /* common pagetable functions */
85 
86 static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *buf)
87 {
88 	struct saa7146_vv *vv = dev->vv_data;
89 	struct pci_dev *pci = dev->pci;
90 	struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb.vb2_buf, 0);
91 	struct scatterlist *list = sgt->sgl;
92 	int length = sgt->nents;
93 	struct v4l2_pix_format *pix = &vv->video_fmt;
94 	struct saa7146_format *sfmt = saa7146_format_by_fourcc(dev, pix->pixelformat);
95 
96 	DEB_EE("dev:%p, buf:%p, sg_len:%d\n", dev, buf, length);
97 
98 	if( 0 != IS_PLANAR(sfmt->trans)) {
99 		struct saa7146_pgtable *pt1 = &buf->pt[0];
100 		struct saa7146_pgtable *pt2 = &buf->pt[1];
101 		struct saa7146_pgtable *pt3 = &buf->pt[2];
102 		struct sg_dma_page_iter dma_iter;
103 		__le32  *ptr1, *ptr2, *ptr3;
104 		__le32 fill;
105 
106 		int size = pix->width * pix->height;
107 		int i, m1, m2, m3, o1, o2;
108 
109 		switch( sfmt->depth ) {
110 			case 12: {
111 				/* create some offsets inside the page table */
112 				m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
113 				m2 = ((size + (size / 4) + PAGE_SIZE) / PAGE_SIZE) - 1;
114 				m3 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
115 				o1 = size % PAGE_SIZE;
116 				o2 = (size + (size / 4)) % PAGE_SIZE;
117 				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
118 					size, m1, m2, m3, o1, o2);
119 				break;
120 			}
121 			case 16: {
122 				/* create some offsets inside the page table */
123 				m1 = ((size + PAGE_SIZE) / PAGE_SIZE) - 1;
124 				m2 = ((size + (size / 2) + PAGE_SIZE) / PAGE_SIZE) - 1;
125 				m3 = ((2 * size + PAGE_SIZE) / PAGE_SIZE) - 1;
126 				o1 = size % PAGE_SIZE;
127 				o2 = (size + (size / 2)) % PAGE_SIZE;
128 				DEB_CAP("size:%d, m1:%d, m2:%d, m3:%d, o1:%d, o2:%d\n",
129 					size, m1, m2, m3, o1, o2);
130 				break;
131 			}
132 			default: {
133 				return -1;
134 			}
135 		}
136 
137 		ptr1 = pt1->cpu;
138 		ptr2 = pt2->cpu;
139 		ptr3 = pt3->cpu;
140 
141 		for_each_sg_dma_page(list, &dma_iter, length, 0)
142 			*ptr1++ = cpu_to_le32(sg_page_iter_dma_address(&dma_iter) - list->offset);
143 
144 		/* if we have a user buffer, the first page may not be
145 		   aligned to a page boundary. */
146 		pt1->offset = sgt->sgl->offset;
147 		pt2->offset = pt1->offset + o1;
148 		pt3->offset = pt1->offset + o2;
149 
150 		/* create video-dma2 page table */
151 		ptr1 = pt1->cpu;
152 		for (i = m1; i <= m2; i++, ptr2++)
153 			*ptr2 = ptr1[i];
154 		fill = *(ptr2 - 1);
155 		for (; i < 1024; i++, ptr2++)
156 			*ptr2 = fill;
157 		/* create video-dma3 page table */
158 		ptr1 = pt1->cpu;
159 		for (i = m2; i <= m3; i++, ptr3++)
160 			*ptr3 = ptr1[i];
161 		fill = *(ptr3 - 1);
162 		for (; i < 1024; i++, ptr3++)
163 			*ptr3 = fill;
164 		/* finally: finish up video-dma1 page table */
165 		ptr1 = pt1->cpu + m1;
166 		fill = pt1->cpu[m1];
167 		for (i = m1; i < 1024; i++, ptr1++)
168 			*ptr1 = fill;
169 	} else {
170 		struct saa7146_pgtable *pt = &buf->pt[0];
171 
172 		return saa7146_pgtable_build_single(pci, pt, list, length);
173 	}
174 
175 	return 0;
176 }
177 
178 
179 /********************************************************************************/
180 /* file operations */
181 
182 static int video_begin(struct saa7146_dev *dev)
183 {
184 	struct saa7146_vv *vv = dev->vv_data;
185 	struct saa7146_format *fmt = NULL;
186 	unsigned int resource;
187 	int ret = 0;
188 
189 	DEB_EE("dev:%p\n", dev);
190 
191 	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
192 	/* we need to have a valid format set here */
193 	if (!fmt)
194 		return -EINVAL;
195 
196 	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
197 		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
198 	} else {
199 		resource = RESOURCE_DMA1_HPS;
200 	}
201 
202 	ret = saa7146_res_get(dev, resource);
203 	if (0 == ret) {
204 		DEB_S("cannot get capture resource %d\n", resource);
205 		return -EBUSY;
206 	}
207 
208 	/* clear out beginning of streaming bit (rps register 0)*/
209 	saa7146_write(dev, MC2, MASK_27 );
210 
211 	/* enable rps0 irqs */
212 	SAA7146_IER_ENABLE(dev, MASK_27);
213 
214 	return 0;
215 }
216 
217 static void video_end(struct saa7146_dev *dev)
218 {
219 	struct saa7146_vv *vv = dev->vv_data;
220 	struct saa7146_format *fmt = NULL;
221 	unsigned long flags;
222 	unsigned int resource;
223 	u32 dmas = 0;
224 	DEB_EE("dev:%p\n", dev);
225 
226 	fmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
227 	/* we need to have a valid format set here */
228 	if (!fmt)
229 		return;
230 
231 	if (0 != (fmt->flags & FORMAT_IS_PLANAR)) {
232 		resource = RESOURCE_DMA1_HPS|RESOURCE_DMA2_CLP|RESOURCE_DMA3_BRS;
233 		dmas = MASK_22 | MASK_21 | MASK_20;
234 	} else {
235 		resource = RESOURCE_DMA1_HPS;
236 		dmas = MASK_22;
237 	}
238 	spin_lock_irqsave(&dev->slock,flags);
239 
240 	/* disable rps0  */
241 	saa7146_write(dev, MC1, MASK_28);
242 
243 	/* disable rps0 irqs */
244 	SAA7146_IER_DISABLE(dev, MASK_27);
245 
246 	/* shut down all used video dma transfers */
247 	saa7146_write(dev, MC1, dmas);
248 
249 	spin_unlock_irqrestore(&dev->slock, flags);
250 
251 	saa7146_res_free(dev, resource);
252 }
253 
254 static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
255 {
256 	struct saa7146_dev *dev = video_drvdata(file);
257 
258 	strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));
259 	strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
260 	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
261 			    V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
262 			    V4L2_CAP_DEVICE_CAPS;
263 	cap->capabilities |= dev->ext_vv_data->capabilities;
264 	return 0;
265 }
266 
267 static int vidioc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
268 {
269 	if (f->index >= ARRAY_SIZE(formats))
270 		return -EINVAL;
271 	f->pixelformat = formats[f->index].pixelformat;
272 	return 0;
273 }
274 
275 int saa7146_s_ctrl(struct v4l2_ctrl *ctrl)
276 {
277 	struct saa7146_dev *dev = container_of(ctrl->handler,
278 				struct saa7146_dev, ctrl_handler);
279 	struct saa7146_vv *vv = dev->vv_data;
280 	u32 val;
281 
282 	switch (ctrl->id) {
283 	case V4L2_CID_BRIGHTNESS:
284 		val = saa7146_read(dev, BCS_CTRL);
285 		val &= 0x00ffffff;
286 		val |= (ctrl->val << 24);
287 		saa7146_write(dev, BCS_CTRL, val);
288 		saa7146_write(dev, MC2, MASK_22 | MASK_06);
289 		break;
290 
291 	case V4L2_CID_CONTRAST:
292 		val = saa7146_read(dev, BCS_CTRL);
293 		val &= 0xff00ffff;
294 		val |= (ctrl->val << 16);
295 		saa7146_write(dev, BCS_CTRL, val);
296 		saa7146_write(dev, MC2, MASK_22 | MASK_06);
297 		break;
298 
299 	case V4L2_CID_SATURATION:
300 		val = saa7146_read(dev, BCS_CTRL);
301 		val &= 0xffffff00;
302 		val |= (ctrl->val << 0);
303 		saa7146_write(dev, BCS_CTRL, val);
304 		saa7146_write(dev, MC2, MASK_22 | MASK_06);
305 		break;
306 
307 	case V4L2_CID_HFLIP:
308 		/* fixme: we can support changing VFLIP and HFLIP here... */
309 		if (vb2_is_busy(&vv->video_dmaq.q))
310 			return -EBUSY;
311 		vv->hflip = ctrl->val;
312 		break;
313 
314 	case V4L2_CID_VFLIP:
315 		if (vb2_is_busy(&vv->video_dmaq.q))
316 			return -EBUSY;
317 		vv->vflip = ctrl->val;
318 		break;
319 
320 	default:
321 		return -EINVAL;
322 	}
323 	return 0;
324 }
325 
326 static int vidioc_g_parm(struct file *file, void *fh,
327 		struct v4l2_streamparm *parm)
328 {
329 	struct saa7146_dev *dev = video_drvdata(file);
330 	struct saa7146_vv *vv = dev->vv_data;
331 
332 	if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
333 		return -EINVAL;
334 	parm->parm.capture.readbuffers = 1;
335 	v4l2_video_std_frame_period(vv->standard->id,
336 				    &parm->parm.capture.timeperframe);
337 	return 0;
338 }
339 
340 static int vidioc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
341 {
342 	struct saa7146_dev *dev = video_drvdata(file);
343 	struct saa7146_vv *vv = dev->vv_data;
344 
345 	f->fmt.pix = vv->video_fmt;
346 	return 0;
347 }
348 
349 static int vidioc_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f)
350 {
351 	struct saa7146_dev *dev = video_drvdata(file);
352 	struct saa7146_vv *vv = dev->vv_data;
353 
354 	f->fmt.vbi = vv->vbi_fmt;
355 	return 0;
356 }
357 
358 static int vidioc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
359 {
360 	struct saa7146_dev *dev = video_drvdata(file);
361 	struct saa7146_vv *vv = dev->vv_data;
362 	struct saa7146_format *fmt;
363 	enum v4l2_field field;
364 	int maxw, maxh;
365 	int calc_bpl;
366 
367 	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p, fh:%p\n", dev, fh);
368 
369 	fmt = saa7146_format_by_fourcc(dev, f->fmt.pix.pixelformat);
370 	if (NULL == fmt)
371 		return -EINVAL;
372 
373 	field = f->fmt.pix.field;
374 	maxw  = vv->standard->h_max_out;
375 	maxh  = vv->standard->v_max_out;
376 
377 	if (V4L2_FIELD_ANY == field) {
378 		field = (f->fmt.pix.height > maxh / 2)
379 			? V4L2_FIELD_INTERLACED
380 			: V4L2_FIELD_BOTTOM;
381 	}
382 	switch (field) {
383 	case V4L2_FIELD_ALTERNATE:
384 	case V4L2_FIELD_TOP:
385 	case V4L2_FIELD_BOTTOM:
386 		maxh = maxh / 2;
387 		break;
388 	default:
389 		field = V4L2_FIELD_INTERLACED;
390 		break;
391 	}
392 
393 	f->fmt.pix.field = field;
394 	f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
395 	if (f->fmt.pix.width < 48)
396 		f->fmt.pix.width = 48;
397 	if (f->fmt.pix.height < 32)
398 		f->fmt.pix.height = 32;
399 	if (f->fmt.pix.width > maxw)
400 		f->fmt.pix.width = maxw;
401 	if (f->fmt.pix.height > maxh)
402 		f->fmt.pix.height = maxh;
403 
404 	calc_bpl = (f->fmt.pix.width * fmt->depth) / 8;
405 
406 	if (f->fmt.pix.bytesperline < calc_bpl)
407 		f->fmt.pix.bytesperline = calc_bpl;
408 
409 	if (f->fmt.pix.bytesperline > (2 * PAGE_SIZE * fmt->depth) / 8) /* arbitrary constraint */
410 		f->fmt.pix.bytesperline = calc_bpl;
411 
412 	f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * f->fmt.pix.height;
413 	DEB_D("w:%d, h:%d, bytesperline:%d, sizeimage:%d\n",
414 	      f->fmt.pix.width, f->fmt.pix.height,
415 	      f->fmt.pix.bytesperline, f->fmt.pix.sizeimage);
416 
417 	return 0;
418 }
419 
420 static int vidioc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
421 {
422 	struct saa7146_dev *dev = video_drvdata(file);
423 	struct saa7146_vv *vv = dev->vv_data;
424 	int err;
425 
426 	DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: dev:%p\n", dev);
427 	if (vb2_is_busy(&vv->video_dmaq.q)) {
428 		DEB_EE("streaming capture is active\n");
429 		return -EBUSY;
430 	}
431 	err = vidioc_try_fmt_vid_cap(file, fh, f);
432 	if (0 != err)
433 		return err;
434 	switch (f->fmt.pix.field) {
435 	case V4L2_FIELD_ALTERNATE:
436 		vv->last_field = V4L2_FIELD_TOP;
437 		break;
438 	default:
439 		vv->last_field = V4L2_FIELD_INTERLACED;
440 		break;
441 	}
442 	vv->video_fmt = f->fmt.pix;
443 	DEB_EE("set to pixelformat '%4.4s'\n",
444 	       (char *)&vv->video_fmt.pixelformat);
445 	return 0;
446 }
447 
448 static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
449 {
450 	struct saa7146_dev *dev = video_drvdata(file);
451 	struct saa7146_vv *vv = dev->vv_data;
452 
453 	*norm = vv->standard->id;
454 	return 0;
455 }
456 
457 static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
458 {
459 	struct saa7146_dev *dev = video_drvdata(file);
460 	struct saa7146_vv *vv = dev->vv_data;
461 	int found = 0;
462 	int i;
463 
464 	DEB_EE("VIDIOC_S_STD\n");
465 
466 	for (i = 0; i < dev->ext_vv_data->num_stds; i++)
467 		if (id & dev->ext_vv_data->stds[i].id)
468 			break;
469 
470 	if (i != dev->ext_vv_data->num_stds &&
471 	    vv->standard == &dev->ext_vv_data->stds[i])
472 		return 0;
473 
474 	if (vb2_is_busy(&vv->video_dmaq.q) || vb2_is_busy(&vv->vbi_dmaq.q)) {
475 		DEB_D("cannot change video standard while streaming capture is active\n");
476 		return -EBUSY;
477 	}
478 
479 	if (i != dev->ext_vv_data->num_stds) {
480 		vv->standard = &dev->ext_vv_data->stds[i];
481 		if (NULL != dev->ext_vv_data->std_callback)
482 			dev->ext_vv_data->std_callback(dev, vv->standard);
483 		found = 1;
484 	}
485 
486 	if (!found) {
487 		DEB_EE("VIDIOC_S_STD: standard not found\n");
488 		return -EINVAL;
489 	}
490 
491 	DEB_EE("VIDIOC_S_STD: set to standard to '%s'\n", vv->standard->name);
492 	return 0;
493 }
494 
495 const struct v4l2_ioctl_ops saa7146_video_ioctl_ops = {
496 	.vidioc_querycap             = vidioc_querycap,
497 	.vidioc_enum_fmt_vid_cap     = vidioc_enum_fmt_vid_cap,
498 	.vidioc_g_fmt_vid_cap        = vidioc_g_fmt_vid_cap,
499 	.vidioc_try_fmt_vid_cap      = vidioc_try_fmt_vid_cap,
500 	.vidioc_s_fmt_vid_cap        = vidioc_s_fmt_vid_cap,
501 	.vidioc_g_std                = vidioc_g_std,
502 	.vidioc_s_std                = vidioc_s_std,
503 	.vidioc_g_parm		     = vidioc_g_parm,
504 	.vidioc_reqbufs		     = vb2_ioctl_reqbufs,
505 	.vidioc_create_bufs	     = vb2_ioctl_create_bufs,
506 	.vidioc_querybuf	     = vb2_ioctl_querybuf,
507 	.vidioc_qbuf		     = vb2_ioctl_qbuf,
508 	.vidioc_dqbuf		     = vb2_ioctl_dqbuf,
509 	.vidioc_streamon	     = vb2_ioctl_streamon,
510 	.vidioc_streamoff	     = vb2_ioctl_streamoff,
511 	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
512 	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
513 };
514 
515 const struct v4l2_ioctl_ops saa7146_vbi_ioctl_ops = {
516 	.vidioc_querycap             = vidioc_querycap,
517 	.vidioc_g_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
518 	.vidioc_try_fmt_vbi_cap      = vidioc_g_fmt_vbi_cap,
519 	.vidioc_s_fmt_vbi_cap        = vidioc_g_fmt_vbi_cap,
520 	.vidioc_g_std                = vidioc_g_std,
521 	.vidioc_s_std                = vidioc_s_std,
522 	.vidioc_g_parm		     = vidioc_g_parm,
523 	.vidioc_reqbufs		     = vb2_ioctl_reqbufs,
524 	.vidioc_create_bufs	     = vb2_ioctl_create_bufs,
525 	.vidioc_querybuf	     = vb2_ioctl_querybuf,
526 	.vidioc_qbuf		     = vb2_ioctl_qbuf,
527 	.vidioc_dqbuf		     = vb2_ioctl_dqbuf,
528 	.vidioc_streamon	     = vb2_ioctl_streamon,
529 	.vidioc_streamoff	     = vb2_ioctl_streamoff,
530 	.vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
531 	.vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
532 };
533 
534 /*********************************************************************************/
535 /* buffer handling functions                                                  */
536 
537 static int buffer_activate (struct saa7146_dev *dev,
538 		     struct saa7146_buf *buf,
539 		     struct saa7146_buf *next)
540 {
541 	struct saa7146_vv *vv = dev->vv_data;
542 
543 	saa7146_set_capture(dev,buf,next);
544 
545 	mod_timer(&vv->video_dmaq.timeout, jiffies+BUFFER_TIMEOUT);
546 	return 0;
547 }
548 
549 static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf)
550 {
551 	saa7146_pgtable_free(dev->pci, &buf->pt[0]);
552 	saa7146_pgtable_free(dev->pci, &buf->pt[1]);
553 	saa7146_pgtable_free(dev->pci, &buf->pt[2]);
554 }
555 
556 static int queue_setup(struct vb2_queue *q,
557 		       unsigned int *num_buffers, unsigned int *num_planes,
558 		       unsigned int sizes[], struct device *alloc_devs[])
559 {
560 	struct saa7146_dev *dev = vb2_get_drv_priv(q);
561 	unsigned int size = dev->vv_data->video_fmt.sizeimage;
562 
563 	if (*num_planes)
564 		return sizes[0] < size ? -EINVAL : 0;
565 	*num_planes = 1;
566 	sizes[0] = size;
567 
568 	return 0;
569 }
570 
571 static void buf_queue(struct vb2_buffer *vb)
572 {
573 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
574 	struct vb2_queue *vq = vb->vb2_queue;
575 	struct saa7146_dev *dev = vb2_get_drv_priv(vq);
576 	struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
577 	unsigned long flags;
578 
579 	spin_lock_irqsave(&dev->slock, flags);
580 
581 	saa7146_buffer_queue(dev, &dev->vv_data->video_dmaq, buf);
582 	spin_unlock_irqrestore(&dev->slock, flags);
583 }
584 
585 static int buf_init(struct vb2_buffer *vb)
586 {
587 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
588 	struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
589 	struct vb2_queue *vq = vb->vb2_queue;
590 	struct saa7146_dev *dev = vb2_get_drv_priv(vq);
591 	struct saa7146_vv *vv = dev->vv_data;
592 	struct saa7146_format *sfmt;
593 	int ret;
594 
595 	buf->activate = buffer_activate;
596 	sfmt = saa7146_format_by_fourcc(dev, vv->video_fmt.pixelformat);
597 
598 	if (IS_PLANAR(sfmt->trans)) {
599 		saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
600 		saa7146_pgtable_alloc(dev->pci, &buf->pt[1]);
601 		saa7146_pgtable_alloc(dev->pci, &buf->pt[2]);
602 	} else {
603 		saa7146_pgtable_alloc(dev->pci, &buf->pt[0]);
604 	}
605 
606 	ret = saa7146_pgtable_build(dev, buf);
607 	if (ret)
608 		release_all_pagetables(dev, buf);
609 	return ret;
610 }
611 
612 static int buf_prepare(struct vb2_buffer *vb)
613 {
614 	struct vb2_queue *vq = vb->vb2_queue;
615 	struct saa7146_dev *dev = vb2_get_drv_priv(vq);
616 	struct saa7146_vv *vv = dev->vv_data;
617 	unsigned int size = vv->video_fmt.sizeimage;
618 
619 	if (vb2_plane_size(vb, 0) < size)
620 		return -EINVAL;
621 	vb2_set_plane_payload(vb, 0, size);
622 	return 0;
623 }
624 
625 static void buf_cleanup(struct vb2_buffer *vb)
626 {
627 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
628 	struct saa7146_buf *buf = container_of(vbuf, struct saa7146_buf, vb);
629 	struct vb2_queue *vq = vb->vb2_queue;
630 	struct saa7146_dev *dev = vb2_get_drv_priv(vq);
631 
632 	release_all_pagetables(dev, buf);
633 }
634 
635 static void return_buffers(struct vb2_queue *q, int state)
636 {
637 	struct saa7146_dev *dev = vb2_get_drv_priv(q);
638 	struct saa7146_dmaqueue *dq = &dev->vv_data->video_dmaq;
639 	struct saa7146_buf *buf;
640 
641 	if (dq->curr) {
642 		buf = dq->curr;
643 		dq->curr = NULL;
644 		vb2_buffer_done(&buf->vb.vb2_buf, state);
645 	}
646 	while (!list_empty(&dq->queue)) {
647 		buf = list_entry(dq->queue.next, struct saa7146_buf, list);
648 		list_del(&buf->list);
649 		vb2_buffer_done(&buf->vb.vb2_buf, state);
650 	}
651 }
652 
653 static int start_streaming(struct vb2_queue *q, unsigned int count)
654 {
655 	struct saa7146_dev *dev = vb2_get_drv_priv(q);
656 	int ret;
657 
658 	if (!vb2_is_streaming(&dev->vv_data->video_dmaq.q))
659 		dev->vv_data->seqnr = 0;
660 	ret = video_begin(dev);
661 	if (ret)
662 		return_buffers(q, VB2_BUF_STATE_QUEUED);
663 	return ret;
664 }
665 
666 static void stop_streaming(struct vb2_queue *q)
667 {
668 	struct saa7146_dev *dev = vb2_get_drv_priv(q);
669 	struct saa7146_dmaqueue *dq = &dev->vv_data->video_dmaq;
670 
671 	del_timer(&dq->timeout);
672 	video_end(dev);
673 	return_buffers(q, VB2_BUF_STATE_ERROR);
674 }
675 
676 const struct vb2_ops video_qops = {
677 	.queue_setup	= queue_setup,
678 	.buf_queue	= buf_queue,
679 	.buf_init	= buf_init,
680 	.buf_prepare	= buf_prepare,
681 	.buf_cleanup	= buf_cleanup,
682 	.start_streaming = start_streaming,
683 	.stop_streaming = stop_streaming,
684 	.wait_prepare	= vb2_ops_wait_prepare,
685 	.wait_finish	= vb2_ops_wait_finish,
686 };
687 
688 /********************************************************************************/
689 /* file operations */
690 
691 static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
692 {
693 	INIT_LIST_HEAD(&vv->video_dmaq.queue);
694 
695 	timer_setup(&vv->video_dmaq.timeout, saa7146_buffer_timeout, 0);
696 	vv->video_dmaq.dev              = dev;
697 
698 	/* set some default values */
699 	vv->standard = &dev->ext_vv_data->stds[0];
700 
701 	/* FIXME: what's this? */
702 	vv->current_hps_source = SAA7146_HPS_SOURCE_PORT_A;
703 	vv->current_hps_sync = SAA7146_HPS_SYNC_PORT_A;
704 }
705 
706 static void video_irq_done(struct saa7146_dev *dev, unsigned long st)
707 {
708 	struct saa7146_vv *vv = dev->vv_data;
709 	struct saa7146_dmaqueue *q = &vv->video_dmaq;
710 
711 	spin_lock(&dev->slock);
712 	DEB_CAP("called\n");
713 
714 	/* only finish the buffer if we have one... */
715 	if (q->curr)
716 		saa7146_buffer_finish(dev, q, VB2_BUF_STATE_DONE);
717 	saa7146_buffer_next(dev,q,0);
718 
719 	spin_unlock(&dev->slock);
720 }
721 
722 const struct saa7146_use_ops saa7146_video_uops = {
723 	.init = video_init,
724 	.irq_done = video_irq_done,
725 };
726