Subversion Repositories shark

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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