GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / media / common / saa7146 / saa7146_video.c
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 };