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