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 */
10static 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
69struct 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
86static 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(vb: &buf->vb.vb2_buf, plane_no: 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, fourcc: 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
182static 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, fourcc: 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, bit: 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(x: dev, MASK_27);
213
214 return 0;
215}
216
217static 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, fourcc: 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(x: dev, MASK_27);
245
246 /* shut down all used video dma transfers */
247 saa7146_write(dev, MC1, dmas);
248
249 spin_unlock_irqrestore(lock: &dev->slock, flags);
250
251 saa7146_res_free(dev, bits: resource);
252}
253
254static 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
267static 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
275int 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(q: &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(q: &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
326static 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(id: vv->standard->id,
336 frameperiod: &parm->parm.capture.timeperframe);
337 return 0;
338}
339
340static 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
349static 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
358static 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, fourcc: 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
420static 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(q: &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
448static 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
457static 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(q: &vv->video_dmaq.q) || vb2_is_busy(q: &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
495const 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
515const 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
537static 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(timer: &vv->video_dmaq.timeout, expires: jiffies+BUFFER_TIMEOUT);
546 return 0;
547}
548
549static void release_all_pagetables(struct saa7146_dev *dev, struct saa7146_buf *buf)
550{
551 saa7146_pgtable_free(pci: dev->pci, pt: &buf->pt[0]);
552 saa7146_pgtable_free(pci: dev->pci, pt: &buf->pt[1]);
553 saa7146_pgtable_free(pci: dev->pci, pt: &buf->pt[2]);
554}
555
556static 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
571static 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(q: 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, q: &dev->vv_data->video_dmaq, buf);
582 spin_unlock_irqrestore(lock: &dev->slock, flags);
583}
584
585static 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(q: 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, fourcc: vv->video_fmt.pixelformat);
597
598 if (IS_PLANAR(sfmt->trans)) {
599 saa7146_pgtable_alloc(pci: dev->pci, pt: &buf->pt[0]);
600 saa7146_pgtable_alloc(pci: dev->pci, pt: &buf->pt[1]);
601 saa7146_pgtable_alloc(pci: dev->pci, pt: &buf->pt[2]);
602 } else {
603 saa7146_pgtable_alloc(pci: dev->pci, pt: &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
612static 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(q: vq);
616 struct saa7146_vv *vv = dev->vv_data;
617 unsigned int size = vv->video_fmt.sizeimage;
618
619 if (vb2_plane_size(vb, plane_no: 0) < size)
620 return -EINVAL;
621 vb2_set_plane_payload(vb, plane_no: 0, size);
622 return 0;
623}
624
625static 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(q: vq);
631
632 release_all_pagetables(dev, buf);
633}
634
635static 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(vb: &buf->vb.vb2_buf, state);
645 }
646 while (!list_empty(head: &dq->queue)) {
647 buf = list_entry(dq->queue.next, struct saa7146_buf, list);
648 list_del(entry: &buf->list);
649 vb2_buffer_done(vb: &buf->vb.vb2_buf, state);
650 }
651}
652
653static 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(q: &dev->vv_data->video_dmaq.q))
659 dev->vv_data->seqnr = 0;
660 ret = video_begin(dev);
661 if (ret)
662 return_buffers(q, state: VB2_BUF_STATE_QUEUED);
663 return ret;
664}
665
666static 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(timer: &dq->timeout);
672 video_end(dev);
673 return_buffers(q, state: VB2_BUF_STATE_ERROR);
674}
675
676const 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
691static void video_init(struct saa7146_dev *dev, struct saa7146_vv *vv)
692{
693 INIT_LIST_HEAD(list: &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
706static 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(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, state: VB2_BUF_STATE_DONE);
717 saa7146_buffer_next(dev,q,vbi: 0);
718
719 spin_unlock(lock: &dev->slock);
720}
721
722const struct saa7146_use_ops saa7146_video_uops = {
723 .init = video_init,
724 .irq_done = video_irq_done,
725};
726

source code of linux/drivers/media/common/saa7146/saa7146_video.c