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