1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include <linux/kernel.h>
23#include <linux/slab.h>
24#include "pvrusb2-context.h"
25#include "pvrusb2-hdw.h"
26#include "pvrusb2.h"
27#include "pvrusb2-debug.h"
28#include "pvrusb2-v4l2.h"
29#include "pvrusb2-ioread.h"
30#include <linux/videodev2.h>
31#include <linux/module.h>
32#include <media/v4l2-dev.h>
33#include <media/v4l2-device.h>
34#include <media/v4l2-fh.h>
35#include <media/v4l2-common.h>
36#include <media/v4l2-ioctl.h>
37
38struct pvr2_v4l2_dev;
39struct pvr2_v4l2_fh;
40struct pvr2_v4l2;
41
42struct pvr2_v4l2_dev {
43 struct video_device devbase;
44 struct pvr2_v4l2 *v4lp;
45 struct pvr2_context_stream *stream;
46
47 enum pvr2_config config;
48 int v4l_type;
49 enum pvr2_v4l_type minor_type;
50};
51
52struct pvr2_v4l2_fh {
53 struct v4l2_fh fh;
54 struct pvr2_channel channel;
55 struct pvr2_v4l2_dev *pdi;
56 struct pvr2_ioread *rhp;
57 struct file *file;
58 wait_queue_head_t wait_data;
59 int fw_mode_flag;
60
61 unsigned char *input_map;
62 unsigned int input_cnt;
63};
64
65struct pvr2_v4l2 {
66 struct pvr2_channel channel;
67
68
69
70
71 struct pvr2_v4l2_dev *dev_video;
72 struct pvr2_v4l2_dev *dev_radio;
73};
74
75static int video_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
76module_param_array(video_nr, int, NULL, 0444);
77MODULE_PARM_DESC(video_nr, "Offset for device's video dev minor");
78static int radio_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
79module_param_array(radio_nr, int, NULL, 0444);
80MODULE_PARM_DESC(radio_nr, "Offset for device's radio dev minor");
81static int vbi_nr[PVR_NUM] = {[0 ... PVR_NUM-1] = -1};
82module_param_array(vbi_nr, int, NULL, 0444);
83MODULE_PARM_DESC(vbi_nr, "Offset for device's vbi dev minor");
84
85static struct v4l2_fmtdesc pvr_fmtdesc [] = {
86 {
87 .index = 0,
88 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
89 .flags = V4L2_FMT_FLAG_COMPRESSED,
90 .description = "MPEG1/2",
91
92
93 .pixelformat = 0,
94 }
95};
96
97#define PVR_FORMAT_PIX 0
98#define PVR_FORMAT_VBI 1
99
100static struct v4l2_format pvr_format [] = {
101 [PVR_FORMAT_PIX] = {
102 .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
103 .fmt = {
104 .pix = {
105 .width = 720,
106 .height = 576,
107
108
109 .pixelformat = 0,
110 .field = V4L2_FIELD_INTERLACED,
111 .bytesperline = 0,
112
113
114 .sizeimage = (32*1024),
115 .colorspace = 0,
116 .priv = 0
117 }
118 }
119 },
120 [PVR_FORMAT_VBI] = {
121 .type = V4L2_BUF_TYPE_VBI_CAPTURE,
122 .fmt = {
123 .vbi = {
124 .sampling_rate = 27000000,
125 .offset = 248,
126 .samples_per_line = 1443,
127 .sample_format = V4L2_PIX_FMT_GREY,
128 .start = { 0, 0 },
129 .count = { 0, 0 },
130 .flags = 0,
131 }
132 }
133 }
134};
135
136
137
138
139
140
141static int pvr2_querycap(struct file *file, void *priv, struct v4l2_capability *cap)
142{
143 struct pvr2_v4l2_fh *fh = file->private_data;
144 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
145
146 strlcpy(cap->driver, "pvrusb2", sizeof(cap->driver));
147 strlcpy(cap->bus_info, pvr2_hdw_get_bus_info(hdw),
148 sizeof(cap->bus_info));
149 strlcpy(cap->card, pvr2_hdw_get_desc(hdw), sizeof(cap->card));
150 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
151 V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
152 V4L2_CAP_READWRITE | V4L2_CAP_DEVICE_CAPS;
153 switch (fh->pdi->devbase.vfl_type) {
154 case VFL_TYPE_GRABBER:
155 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_AUDIO;
156 break;
157 case VFL_TYPE_RADIO:
158 cap->device_caps = V4L2_CAP_RADIO;
159 break;
160 }
161 cap->device_caps |= V4L2_CAP_TUNER | V4L2_CAP_READWRITE;
162 return 0;
163}
164
165static int pvr2_g_std(struct file *file, void *priv, v4l2_std_id *std)
166{
167 struct pvr2_v4l2_fh *fh = file->private_data;
168 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
169 int val = 0;
170 int ret;
171
172 ret = pvr2_ctrl_get_value(
173 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), &val);
174 *std = val;
175 return ret;
176}
177
178static int pvr2_s_std(struct file *file, void *priv, v4l2_std_id std)
179{
180 struct pvr2_v4l2_fh *fh = file->private_data;
181 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
182
183 return pvr2_ctrl_set_value(
184 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDCUR), std);
185}
186
187static int pvr2_querystd(struct file *file, void *priv, v4l2_std_id *std)
188{
189 struct pvr2_v4l2_fh *fh = file->private_data;
190 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
191 int val = 0;
192 int ret;
193
194 ret = pvr2_ctrl_get_value(
195 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_STDDETECT), &val);
196 *std = val;
197 return ret;
198}
199
200static int pvr2_enum_input(struct file *file, void *priv, struct v4l2_input *vi)
201{
202 struct pvr2_v4l2_fh *fh = file->private_data;
203 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
204 struct pvr2_ctrl *cptr;
205 struct v4l2_input tmp;
206 unsigned int cnt;
207 int val;
208
209 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
210
211 memset(&tmp, 0, sizeof(tmp));
212 tmp.index = vi->index;
213 if (vi->index >= fh->input_cnt)
214 return -EINVAL;
215 val = fh->input_map[vi->index];
216 switch (val) {
217 case PVR2_CVAL_INPUT_TV:
218 case PVR2_CVAL_INPUT_DTV:
219 case PVR2_CVAL_INPUT_RADIO:
220 tmp.type = V4L2_INPUT_TYPE_TUNER;
221 break;
222 case PVR2_CVAL_INPUT_SVIDEO:
223 case PVR2_CVAL_INPUT_COMPOSITE:
224 tmp.type = V4L2_INPUT_TYPE_CAMERA;
225 break;
226 default:
227 return -EINVAL;
228 }
229
230 cnt = 0;
231 pvr2_ctrl_get_valname(cptr, val,
232 tmp.name, sizeof(tmp.name) - 1, &cnt);
233 tmp.name[cnt] = 0;
234
235
236
237
238
239
240
241
242
243
244 *vi = tmp;
245 return 0;
246}
247
248static int pvr2_g_input(struct file *file, void *priv, unsigned int *i)
249{
250 struct pvr2_v4l2_fh *fh = file->private_data;
251 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
252 unsigned int idx;
253 struct pvr2_ctrl *cptr;
254 int val;
255 int ret;
256
257 cptr = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
258 val = 0;
259 ret = pvr2_ctrl_get_value(cptr, &val);
260 *i = 0;
261 for (idx = 0; idx < fh->input_cnt; idx++) {
262 if (fh->input_map[idx] == val) {
263 *i = idx;
264 break;
265 }
266 }
267 return ret;
268}
269
270static int pvr2_s_input(struct file *file, void *priv, unsigned int inp)
271{
272 struct pvr2_v4l2_fh *fh = file->private_data;
273 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
274
275 if (inp >= fh->input_cnt)
276 return -EINVAL;
277 return pvr2_ctrl_set_value(
278 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
279 fh->input_map[inp]);
280}
281
282static int pvr2_enumaudio(struct file *file, void *priv, struct v4l2_audio *vin)
283{
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299 if (vin->index > 0)
300 return -EINVAL;
301 strncpy(vin->name, "PVRUSB2 Audio", 14);
302 vin->capability = V4L2_AUDCAP_STEREO;
303 return 0;
304}
305
306static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
307{
308
309 vin->index = 0;
310 strncpy(vin->name, "PVRUSB2 Audio", 14);
311 vin->capability = V4L2_AUDCAP_STEREO;
312 return 0;
313}
314
315static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout)
316{
317 if (vout->index)
318 return -EINVAL;
319 return 0;
320}
321
322static int pvr2_g_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
323{
324 struct pvr2_v4l2_fh *fh = file->private_data;
325 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
326
327 if (vt->index != 0)
328 return -EINVAL;
329
330 pvr2_hdw_execute_tuner_poll(hdw);
331 return pvr2_hdw_get_tuner_status(hdw, vt);
332}
333
334static int pvr2_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
335{
336 struct pvr2_v4l2_fh *fh = file->private_data;
337 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
338
339 if (vt->index != 0)
340 return -EINVAL;
341
342 return pvr2_ctrl_set_value(
343 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_AUDIOMODE),
344 vt->audmode);
345}
346
347static int pvr2_s_frequency(struct file *file, void *priv, const struct v4l2_frequency *vf)
348{
349 struct pvr2_v4l2_fh *fh = file->private_data;
350 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
351 unsigned long fv;
352 struct v4l2_tuner vt;
353 int cur_input;
354 struct pvr2_ctrl *ctrlp;
355 int ret;
356
357 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
358 if (ret != 0)
359 return ret;
360 ctrlp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT);
361 ret = pvr2_ctrl_get_value(ctrlp, &cur_input);
362 if (ret != 0)
363 return ret;
364 if (vf->type == V4L2_TUNER_RADIO) {
365 if (cur_input != PVR2_CVAL_INPUT_RADIO)
366 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_RADIO);
367 } else {
368 if (cur_input == PVR2_CVAL_INPUT_RADIO)
369 pvr2_ctrl_set_value(ctrlp, PVR2_CVAL_INPUT_TV);
370 }
371 fv = vf->frequency;
372 if (vt.capability & V4L2_TUNER_CAP_LOW)
373 fv = (fv * 125) / 2;
374 else
375 fv = fv * 62500;
376 return pvr2_ctrl_set_value(
377 pvr2_hdw_get_ctrl_by_id(hdw,PVR2_CID_FREQUENCY),fv);
378}
379
380static int pvr2_g_frequency(struct file *file, void *priv, struct v4l2_frequency *vf)
381{
382 struct pvr2_v4l2_fh *fh = file->private_data;
383 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
384 int val = 0;
385 int cur_input;
386 struct v4l2_tuner vt;
387 int ret;
388
389 ret = pvr2_hdw_get_tuner_status(hdw, &vt);
390 if (ret != 0)
391 return ret;
392 ret = pvr2_ctrl_get_value(
393 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_FREQUENCY),
394 &val);
395 if (ret != 0)
396 return ret;
397 pvr2_ctrl_get_value(
398 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_INPUT),
399 &cur_input);
400 if (cur_input == PVR2_CVAL_INPUT_RADIO)
401 vf->type = V4L2_TUNER_RADIO;
402 else
403 vf->type = V4L2_TUNER_ANALOG_TV;
404 if (vt.capability & V4L2_TUNER_CAP_LOW)
405 val = (val * 2) / 125;
406 else
407 val /= 62500;
408 vf->frequency = val;
409 return 0;
410}
411
412static int pvr2_enum_fmt_vid_cap(struct file *file, void *priv, struct v4l2_fmtdesc *fd)
413{
414
415 if (fd->index != 0)
416 return -EINVAL;
417
418 memcpy(fd, pvr_fmtdesc, sizeof(struct v4l2_fmtdesc));
419 return 0;
420}
421
422static int pvr2_g_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
423{
424 struct pvr2_v4l2_fh *fh = file->private_data;
425 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
426 int val;
427
428 memcpy(vf, &pvr_format[PVR_FORMAT_PIX], sizeof(struct v4l2_format));
429 val = 0;
430 pvr2_ctrl_get_value(
431 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES),
432 &val);
433 vf->fmt.pix.width = val;
434 val = 0;
435 pvr2_ctrl_get_value(
436 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES),
437 &val);
438 vf->fmt.pix.height = val;
439 return 0;
440}
441
442static int pvr2_try_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
443{
444 struct pvr2_v4l2_fh *fh = file->private_data;
445 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
446 int lmin, lmax, ldef;
447 struct pvr2_ctrl *hcp, *vcp;
448 int h = vf->fmt.pix.height;
449 int w = vf->fmt.pix.width;
450
451 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
452 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
453
454 lmin = pvr2_ctrl_get_min(hcp);
455 lmax = pvr2_ctrl_get_max(hcp);
456 pvr2_ctrl_get_def(hcp, &ldef);
457 if (w == -1)
458 w = ldef;
459 else if (w < lmin)
460 w = lmin;
461 else if (w > lmax)
462 w = lmax;
463 lmin = pvr2_ctrl_get_min(vcp);
464 lmax = pvr2_ctrl_get_max(vcp);
465 pvr2_ctrl_get_def(vcp, &ldef);
466 if (h == -1)
467 h = ldef;
468 else if (h < lmin)
469 h = lmin;
470 else if (h > lmax)
471 h = lmax;
472
473 memcpy(vf, &pvr_format[PVR_FORMAT_PIX],
474 sizeof(struct v4l2_format));
475 vf->fmt.pix.width = w;
476 vf->fmt.pix.height = h;
477 return 0;
478}
479
480static int pvr2_s_fmt_vid_cap(struct file *file, void *priv, struct v4l2_format *vf)
481{
482 struct pvr2_v4l2_fh *fh = file->private_data;
483 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
484 struct pvr2_ctrl *hcp, *vcp;
485 int ret = pvr2_try_fmt_vid_cap(file, fh, vf);
486
487 if (ret)
488 return ret;
489 hcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_HRES);
490 vcp = pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_VRES);
491 pvr2_ctrl_set_value(hcp, vf->fmt.pix.width);
492 pvr2_ctrl_set_value(vcp, vf->fmt.pix.height);
493 return 0;
494}
495
496static int pvr2_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
497{
498 struct pvr2_v4l2_fh *fh = file->private_data;
499 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
500 struct pvr2_v4l2_dev *pdi = fh->pdi;
501 int ret;
502
503 if (!fh->pdi->stream) {
504
505
506
507 return -EPERM;
508 }
509 ret = pvr2_hdw_set_stream_type(hdw, pdi->config);
510 if (ret < 0)
511 return ret;
512 return pvr2_hdw_set_streaming(hdw, !0);
513}
514
515static int pvr2_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
516{
517 struct pvr2_v4l2_fh *fh = file->private_data;
518 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
519
520 if (!fh->pdi->stream) {
521
522
523
524 return -EPERM;
525 }
526 return pvr2_hdw_set_streaming(hdw, 0);
527}
528
529static int pvr2_queryctrl(struct file *file, void *priv,
530 struct v4l2_queryctrl *vc)
531{
532 struct pvr2_v4l2_fh *fh = file->private_data;
533 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
534 struct pvr2_ctrl *cptr;
535 int val;
536
537 if (vc->id & V4L2_CTRL_FLAG_NEXT_CTRL) {
538 cptr = pvr2_hdw_get_ctrl_nextv4l(
539 hdw, (vc->id & ~V4L2_CTRL_FLAG_NEXT_CTRL));
540 if (cptr)
541 vc->id = pvr2_ctrl_get_v4lid(cptr);
542 } else {
543 cptr = pvr2_hdw_get_ctrl_v4l(hdw, vc->id);
544 }
545 if (!cptr) {
546 pvr2_trace(PVR2_TRACE_V4LIOCTL,
547 "QUERYCTRL id=0x%x not implemented here",
548 vc->id);
549 return -EINVAL;
550 }
551
552 pvr2_trace(PVR2_TRACE_V4LIOCTL,
553 "QUERYCTRL id=0x%x mapping name=%s (%s)",
554 vc->id, pvr2_ctrl_get_name(cptr),
555 pvr2_ctrl_get_desc(cptr));
556 strlcpy(vc->name, pvr2_ctrl_get_desc(cptr), sizeof(vc->name));
557 vc->flags = pvr2_ctrl_get_v4lflags(cptr);
558 pvr2_ctrl_get_def(cptr, &val);
559 vc->default_value = val;
560 switch (pvr2_ctrl_get_type(cptr)) {
561 case pvr2_ctl_enum:
562 vc->type = V4L2_CTRL_TYPE_MENU;
563 vc->minimum = 0;
564 vc->maximum = pvr2_ctrl_get_cnt(cptr) - 1;
565 vc->step = 1;
566 break;
567 case pvr2_ctl_bool:
568 vc->type = V4L2_CTRL_TYPE_BOOLEAN;
569 vc->minimum = 0;
570 vc->maximum = 1;
571 vc->step = 1;
572 break;
573 case pvr2_ctl_int:
574 vc->type = V4L2_CTRL_TYPE_INTEGER;
575 vc->minimum = pvr2_ctrl_get_min(cptr);
576 vc->maximum = pvr2_ctrl_get_max(cptr);
577 vc->step = 1;
578 break;
579 default:
580 pvr2_trace(PVR2_TRACE_V4LIOCTL,
581 "QUERYCTRL id=0x%x name=%s not mappable",
582 vc->id, pvr2_ctrl_get_name(cptr));
583 return -EINVAL;
584 }
585 return 0;
586}
587
588static int pvr2_querymenu(struct file *file, void *priv, struct v4l2_querymenu *vm)
589{
590 struct pvr2_v4l2_fh *fh = file->private_data;
591 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
592 unsigned int cnt = 0;
593 int ret;
594
595 ret = pvr2_ctrl_get_valname(pvr2_hdw_get_ctrl_v4l(hdw, vm->id),
596 vm->index,
597 vm->name, sizeof(vm->name) - 1,
598 &cnt);
599 vm->name[cnt] = 0;
600 return ret;
601}
602
603static int pvr2_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
604{
605 struct pvr2_v4l2_fh *fh = file->private_data;
606 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
607 int val = 0;
608 int ret;
609
610 ret = pvr2_ctrl_get_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
611 &val);
612 vc->value = val;
613 return ret;
614}
615
616static int pvr2_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
617{
618 struct pvr2_v4l2_fh *fh = file->private_data;
619 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
620
621 return pvr2_ctrl_set_value(pvr2_hdw_get_ctrl_v4l(hdw, vc->id),
622 vc->value);
623}
624
625static int pvr2_g_ext_ctrls(struct file *file, void *priv,
626 struct v4l2_ext_controls *ctls)
627{
628 struct pvr2_v4l2_fh *fh = file->private_data;
629 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
630 struct v4l2_ext_control *ctrl;
631 struct pvr2_ctrl *cptr;
632 unsigned int idx;
633 int val;
634 int ret;
635
636 ret = 0;
637 for (idx = 0; idx < ctls->count; idx++) {
638 ctrl = ctls->controls + idx;
639 cptr = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
640 if (cptr) {
641 if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL)
642 pvr2_ctrl_get_def(cptr, &val);
643 else
644 ret = pvr2_ctrl_get_value(cptr, &val);
645 } else
646 ret = -EINVAL;
647
648 if (ret) {
649 ctls->error_idx = idx;
650 return ret;
651 }
652
653
654 ctrl->value64 = 0;
655 ctrl->value = val;
656 }
657 return 0;
658}
659
660static int pvr2_s_ext_ctrls(struct file *file, void *priv,
661 struct v4l2_ext_controls *ctls)
662{
663 struct pvr2_v4l2_fh *fh = file->private_data;
664 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
665 struct v4l2_ext_control *ctrl;
666 unsigned int idx;
667 int ret;
668
669
670 if (ctls->which == V4L2_CTRL_WHICH_DEF_VAL)
671 return -EINVAL;
672
673 ret = 0;
674 for (idx = 0; idx < ctls->count; idx++) {
675 ctrl = ctls->controls + idx;
676 ret = pvr2_ctrl_set_value(
677 pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id),
678 ctrl->value);
679 if (ret) {
680 ctls->error_idx = idx;
681 return ret;
682 }
683 }
684 return 0;
685}
686
687static int pvr2_try_ext_ctrls(struct file *file, void *priv,
688 struct v4l2_ext_controls *ctls)
689{
690 struct pvr2_v4l2_fh *fh = file->private_data;
691 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
692 struct v4l2_ext_control *ctrl;
693 struct pvr2_ctrl *pctl;
694 unsigned int idx;
695
696
697
698 for (idx = 0; idx < ctls->count; idx++) {
699 ctrl = ctls->controls + idx;
700 pctl = pvr2_hdw_get_ctrl_v4l(hdw, ctrl->id);
701 if (!pctl) {
702 ctls->error_idx = idx;
703 return -EINVAL;
704 }
705 }
706 return 0;
707}
708
709static int pvr2_cropcap(struct file *file, void *priv, struct v4l2_cropcap *cap)
710{
711 struct pvr2_v4l2_fh *fh = file->private_data;
712 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
713 int ret;
714
715 if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
716 return -EINVAL;
717 ret = pvr2_hdw_get_cropcap(hdw, cap);
718 cap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
719 return ret;
720}
721
722static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
723{
724 struct pvr2_v4l2_fh *fh = file->private_data;
725 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
726 int val = 0;
727 int ret;
728
729 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
730 return -EINVAL;
731 ret = pvr2_ctrl_get_value(
732 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL), &val);
733 if (ret != 0)
734 return -EINVAL;
735 crop->c.left = val;
736 ret = pvr2_ctrl_get_value(
737 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT), &val);
738 if (ret != 0)
739 return -EINVAL;
740 crop->c.top = val;
741 ret = pvr2_ctrl_get_value(
742 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW), &val);
743 if (ret != 0)
744 return -EINVAL;
745 crop->c.width = val;
746 ret = pvr2_ctrl_get_value(
747 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH), &val);
748 if (ret != 0)
749 return -EINVAL;
750 crop->c.height = val;
751 return 0;
752}
753
754static int pvr2_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop)
755{
756 struct pvr2_v4l2_fh *fh = file->private_data;
757 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
758 int ret;
759
760 if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
761 return -EINVAL;
762 ret = pvr2_ctrl_set_value(
763 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
764 crop->c.left);
765 if (ret != 0)
766 return -EINVAL;
767 ret = pvr2_ctrl_set_value(
768 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPT),
769 crop->c.top);
770 if (ret != 0)
771 return -EINVAL;
772 ret = pvr2_ctrl_set_value(
773 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPW),
774 crop->c.width);
775 if (ret != 0)
776 return -EINVAL;
777 ret = pvr2_ctrl_set_value(
778 pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPH),
779 crop->c.height);
780 if (ret != 0)
781 return -EINVAL;
782 return 0;
783}
784
785static int pvr2_log_status(struct file *file, void *priv)
786{
787 struct pvr2_v4l2_fh *fh = file->private_data;
788 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
789
790 pvr2_hdw_trigger_module_log(hdw);
791 return 0;
792}
793
794static const struct v4l2_ioctl_ops pvr2_ioctl_ops = {
795 .vidioc_querycap = pvr2_querycap,
796 .vidioc_s_audio = pvr2_s_audio,
797 .vidioc_g_audio = pvr2_g_audio,
798 .vidioc_enumaudio = pvr2_enumaudio,
799 .vidioc_enum_input = pvr2_enum_input,
800 .vidioc_cropcap = pvr2_cropcap,
801 .vidioc_s_crop = pvr2_s_crop,
802 .vidioc_g_crop = pvr2_g_crop,
803 .vidioc_g_input = pvr2_g_input,
804 .vidioc_s_input = pvr2_s_input,
805 .vidioc_g_frequency = pvr2_g_frequency,
806 .vidioc_s_frequency = pvr2_s_frequency,
807 .vidioc_s_tuner = pvr2_s_tuner,
808 .vidioc_g_tuner = pvr2_g_tuner,
809 .vidioc_g_std = pvr2_g_std,
810 .vidioc_s_std = pvr2_s_std,
811 .vidioc_querystd = pvr2_querystd,
812 .vidioc_log_status = pvr2_log_status,
813 .vidioc_enum_fmt_vid_cap = pvr2_enum_fmt_vid_cap,
814 .vidioc_g_fmt_vid_cap = pvr2_g_fmt_vid_cap,
815 .vidioc_s_fmt_vid_cap = pvr2_s_fmt_vid_cap,
816 .vidioc_try_fmt_vid_cap = pvr2_try_fmt_vid_cap,
817 .vidioc_streamon = pvr2_streamon,
818 .vidioc_streamoff = pvr2_streamoff,
819 .vidioc_queryctrl = pvr2_queryctrl,
820 .vidioc_querymenu = pvr2_querymenu,
821 .vidioc_g_ctrl = pvr2_g_ctrl,
822 .vidioc_s_ctrl = pvr2_s_ctrl,
823 .vidioc_g_ext_ctrls = pvr2_g_ext_ctrls,
824 .vidioc_s_ext_ctrls = pvr2_s_ext_ctrls,
825 .vidioc_try_ext_ctrls = pvr2_try_ext_ctrls,
826};
827
828static void pvr2_v4l2_dev_destroy(struct pvr2_v4l2_dev *dip)
829{
830 struct pvr2_hdw *hdw = dip->v4lp->channel.mc_head->hdw;
831 enum pvr2_config cfg = dip->config;
832 char msg[80];
833 unsigned int mcnt;
834
835
836
837
838 mcnt = scnprintf(msg, sizeof(msg) - 1,
839 "pvrusb2: unregistered device %s [%s]",
840 video_device_node_name(&dip->devbase),
841 pvr2_config_get_name(cfg));
842 msg[mcnt] = 0;
843
844 pvr2_hdw_v4l_store_minor_number(hdw,dip->minor_type,-1);
845
846
847 dip->v4lp = NULL;
848 dip->stream = NULL;
849
850
851
852 video_unregister_device(&dip->devbase);
853
854 printk(KERN_INFO "%s\n", msg);
855
856}
857
858
859static void pvr2_v4l2_dev_disassociate_parent(struct pvr2_v4l2_dev *dip)
860{
861 if (!dip) return;
862 if (!dip->devbase.v4l2_dev->dev) return;
863 dip->devbase.v4l2_dev->dev = NULL;
864 device_move(&dip->devbase.dev, NULL, DPM_ORDER_NONE);
865}
866
867
868static void pvr2_v4l2_destroy_no_lock(struct pvr2_v4l2 *vp)
869{
870 if (vp->dev_video) {
871 pvr2_v4l2_dev_destroy(vp->dev_video);
872 vp->dev_video = NULL;
873 }
874 if (vp->dev_radio) {
875 pvr2_v4l2_dev_destroy(vp->dev_radio);
876 vp->dev_radio = NULL;
877 }
878
879 pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr2_v4l2 id=%p",vp);
880 pvr2_channel_done(&vp->channel);
881 kfree(vp);
882}
883
884
885static void pvr2_video_device_release(struct video_device *vdev)
886{
887 struct pvr2_v4l2_dev *dev;
888 dev = container_of(vdev,struct pvr2_v4l2_dev,devbase);
889 kfree(dev);
890}
891
892
893static void pvr2_v4l2_internal_check(struct pvr2_channel *chp)
894{
895 struct pvr2_v4l2 *vp;
896 vp = container_of(chp,struct pvr2_v4l2,channel);
897 if (!vp->channel.mc_head->disconnect_flag) return;
898 pvr2_v4l2_dev_disassociate_parent(vp->dev_video);
899 pvr2_v4l2_dev_disassociate_parent(vp->dev_radio);
900 if (!list_empty(&vp->dev_video->devbase.fh_list) ||
901 !list_empty(&vp->dev_radio->devbase.fh_list))
902 return;
903 pvr2_v4l2_destroy_no_lock(vp);
904}
905
906
907static long pvr2_v4l2_ioctl(struct file *file,
908 unsigned int cmd, unsigned long arg)
909{
910
911 struct pvr2_v4l2_fh *fh = file->private_data;
912 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
913 long ret = -EINVAL;
914
915 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL)
916 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
917
918 if (!pvr2_hdw_dev_ok(hdw)) {
919 pvr2_trace(PVR2_TRACE_ERROR_LEGS,
920 "ioctl failed - bad or no context");
921 return -EFAULT;
922 }
923
924 ret = video_ioctl2(file, cmd, arg);
925
926 pvr2_hdw_commit_ctl(hdw);
927
928 if (ret < 0) {
929 if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
930 pvr2_trace(PVR2_TRACE_V4LIOCTL,
931 "pvr2_v4l2_do_ioctl failure, ret=%ld"
932 " command was:", ret);
933 v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
934 }
935 } else {
936 pvr2_trace(PVR2_TRACE_V4LIOCTL,
937 "pvr2_v4l2_do_ioctl complete, ret=%ld (0x%lx)",
938 ret, ret);
939 }
940 return ret;
941
942}
943
944
945static int pvr2_v4l2_release(struct file *file)
946{
947 struct pvr2_v4l2_fh *fhp = file->private_data;
948 struct pvr2_v4l2 *vp = fhp->pdi->v4lp;
949 struct pvr2_hdw *hdw = fhp->channel.mc_head->hdw;
950
951 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_release");
952
953 if (fhp->rhp) {
954 struct pvr2_stream *sp;
955 pvr2_hdw_set_streaming(hdw,0);
956 sp = pvr2_ioread_get_stream(fhp->rhp);
957 if (sp) pvr2_stream_set_callback(sp,NULL,NULL);
958 pvr2_ioread_destroy(fhp->rhp);
959 fhp->rhp = NULL;
960 }
961
962 v4l2_fh_del(&fhp->fh);
963 v4l2_fh_exit(&fhp->fh);
964 file->private_data = NULL;
965
966 pvr2_channel_done(&fhp->channel);
967 pvr2_trace(PVR2_TRACE_STRUCT,
968 "Destroying pvr_v4l2_fh id=%p",fhp);
969 if (fhp->input_map) {
970 kfree(fhp->input_map);
971 fhp->input_map = NULL;
972 }
973 kfree(fhp);
974 if (vp->channel.mc_head->disconnect_flag &&
975 list_empty(&vp->dev_video->devbase.fh_list) &&
976 list_empty(&vp->dev_radio->devbase.fh_list)) {
977 pvr2_v4l2_destroy_no_lock(vp);
978 }
979 return 0;
980}
981
982
983static int pvr2_v4l2_open(struct file *file)
984{
985 struct pvr2_v4l2_dev *dip;
986 struct pvr2_v4l2_fh *fhp;
987 struct pvr2_v4l2 *vp;
988 struct pvr2_hdw *hdw;
989 unsigned int input_mask = 0;
990 unsigned int input_cnt,idx;
991 int ret = 0;
992
993 dip = container_of(video_devdata(file),struct pvr2_v4l2_dev,devbase);
994
995 vp = dip->v4lp;
996 hdw = vp->channel.hdw;
997
998 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,"pvr2_v4l2_open");
999
1000 if (!pvr2_hdw_dev_ok(hdw)) {
1001 pvr2_trace(PVR2_TRACE_OPEN_CLOSE,
1002 "pvr2_v4l2_open: hardware not ready");
1003 return -EIO;
1004 }
1005
1006 fhp = kzalloc(sizeof(*fhp),GFP_KERNEL);
1007 if (!fhp) {
1008 return -ENOMEM;
1009 }
1010
1011 v4l2_fh_init(&fhp->fh, &dip->devbase);
1012 init_waitqueue_head(&fhp->wait_data);
1013 fhp->pdi = dip;
1014
1015 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_v4l2_fh id=%p",fhp);
1016 pvr2_channel_init(&fhp->channel,vp->channel.mc_head);
1017
1018 if (dip->v4l_type == VFL_TYPE_RADIO) {
1019
1020
1021 input_mask = (1 << PVR2_CVAL_INPUT_RADIO);
1022 } else {
1023
1024
1025 input_mask = ((1 << PVR2_CVAL_INPUT_RADIO) |
1026 (1 << PVR2_CVAL_INPUT_TV) |
1027 (1 << PVR2_CVAL_INPUT_COMPOSITE) |
1028 (1 << PVR2_CVAL_INPUT_SVIDEO));
1029 }
1030 ret = pvr2_channel_limit_inputs(&fhp->channel,input_mask);
1031 if (ret) {
1032 pvr2_channel_done(&fhp->channel);
1033 pvr2_trace(PVR2_TRACE_STRUCT,
1034 "Destroying pvr_v4l2_fh id=%p (input mask error)",
1035 fhp);
1036
1037 kfree(fhp);
1038 return ret;
1039 }
1040
1041 input_mask &= pvr2_hdw_get_input_available(hdw);
1042 input_cnt = 0;
1043 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1044 if (input_mask & (1 << idx)) input_cnt++;
1045 }
1046 fhp->input_cnt = input_cnt;
1047 fhp->input_map = kzalloc(input_cnt,GFP_KERNEL);
1048 if (!fhp->input_map) {
1049 pvr2_channel_done(&fhp->channel);
1050 pvr2_trace(PVR2_TRACE_STRUCT,
1051 "Destroying pvr_v4l2_fh id=%p (input map failure)",
1052 fhp);
1053 kfree(fhp);
1054 return -ENOMEM;
1055 }
1056 input_cnt = 0;
1057 for (idx = 0; idx < (sizeof(input_mask) << 3); idx++) {
1058 if (!(input_mask & (1 << idx))) continue;
1059 fhp->input_map[input_cnt++] = idx;
1060 }
1061
1062 fhp->file = file;
1063 file->private_data = fhp;
1064
1065 fhp->fw_mode_flag = pvr2_hdw_cpufw_get_enabled(hdw);
1066 v4l2_fh_add(&fhp->fh);
1067
1068 return 0;
1069}
1070
1071
1072static void pvr2_v4l2_notify(struct pvr2_v4l2_fh *fhp)
1073{
1074 wake_up(&fhp->wait_data);
1075}
1076
1077static int pvr2_v4l2_iosetup(struct pvr2_v4l2_fh *fh)
1078{
1079 int ret;
1080 struct pvr2_stream *sp;
1081 struct pvr2_hdw *hdw;
1082 if (fh->rhp) return 0;
1083
1084 if (!fh->pdi->stream) {
1085
1086
1087 return -EPERM;
1088 }
1089
1090
1091
1092 if ((ret = pvr2_channel_claim_stream(&fh->channel,
1093 fh->pdi->stream)) != 0) {
1094
1095 return ret;
1096 }
1097
1098 fh->rhp = pvr2_channel_create_mpeg_stream(fh->pdi->stream);
1099 if (!fh->rhp) {
1100 pvr2_channel_claim_stream(&fh->channel,NULL);
1101 return -ENOMEM;
1102 }
1103
1104 hdw = fh->channel.mc_head->hdw;
1105 sp = fh->pdi->stream->stream;
1106 pvr2_stream_set_callback(sp,(pvr2_stream_callback)pvr2_v4l2_notify,fh);
1107 pvr2_hdw_set_stream_type(hdw,fh->pdi->config);
1108 if ((ret = pvr2_hdw_set_streaming(hdw,!0)) < 0) return ret;
1109 return pvr2_ioread_set_enabled(fh->rhp,!0);
1110}
1111
1112
1113static ssize_t pvr2_v4l2_read(struct file *file,
1114 char __user *buff, size_t count, loff_t *ppos)
1115{
1116 struct pvr2_v4l2_fh *fh = file->private_data;
1117 int ret;
1118
1119 if (fh->fw_mode_flag) {
1120 struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
1121 char *tbuf;
1122 int c1,c2;
1123 int tcnt = 0;
1124 unsigned int offs = *ppos;
1125
1126 tbuf = kmalloc(PAGE_SIZE,GFP_KERNEL);
1127 if (!tbuf) return -ENOMEM;
1128
1129 while (count) {
1130 c1 = count;
1131 if (c1 > PAGE_SIZE) c1 = PAGE_SIZE;
1132 c2 = pvr2_hdw_cpufw_get(hdw,offs,tbuf,c1);
1133 if (c2 < 0) {
1134 tcnt = c2;
1135 break;
1136 }
1137 if (!c2) break;
1138 if (copy_to_user(buff,tbuf,c2)) {
1139 tcnt = -EFAULT;
1140 break;
1141 }
1142 offs += c2;
1143 tcnt += c2;
1144 buff += c2;
1145 count -= c2;
1146 *ppos += c2;
1147 }
1148 kfree(tbuf);
1149 return tcnt;
1150 }
1151
1152 if (!fh->rhp) {
1153 ret = pvr2_v4l2_iosetup(fh);
1154 if (ret) {
1155 return ret;
1156 }
1157 }
1158
1159 for (;;) {
1160 ret = pvr2_ioread_read(fh->rhp,buff,count);
1161 if (ret >= 0) break;
1162 if (ret != -EAGAIN) break;
1163 if (file->f_flags & O_NONBLOCK) break;
1164
1165 ret = wait_event_interruptible(
1166 fh->wait_data,
1167 pvr2_ioread_avail(fh->rhp) >= 0);
1168 if (ret < 0) break;
1169 }
1170
1171 return ret;
1172}
1173
1174
1175static unsigned int pvr2_v4l2_poll(struct file *file, poll_table *wait)
1176{
1177 unsigned int mask = 0;
1178 struct pvr2_v4l2_fh *fh = file->private_data;
1179 int ret;
1180
1181 if (fh->fw_mode_flag) {
1182 mask |= POLLIN | POLLRDNORM;
1183 return mask;
1184 }
1185
1186 if (!fh->rhp) {
1187 ret = pvr2_v4l2_iosetup(fh);
1188 if (ret) return POLLERR;
1189 }
1190
1191 poll_wait(file,&fh->wait_data,wait);
1192
1193 if (pvr2_ioread_avail(fh->rhp) >= 0) {
1194 mask |= POLLIN | POLLRDNORM;
1195 }
1196
1197 return mask;
1198}
1199
1200
1201static const struct v4l2_file_operations vdev_fops = {
1202 .owner = THIS_MODULE,
1203 .open = pvr2_v4l2_open,
1204 .release = pvr2_v4l2_release,
1205 .read = pvr2_v4l2_read,
1206 .unlocked_ioctl = pvr2_v4l2_ioctl,
1207 .poll = pvr2_v4l2_poll,
1208};
1209
1210
1211static struct video_device vdev_template = {
1212 .fops = &vdev_fops,
1213};
1214
1215
1216static void pvr2_v4l2_dev_init(struct pvr2_v4l2_dev *dip,
1217 struct pvr2_v4l2 *vp,
1218 int v4l_type)
1219{
1220 int mindevnum;
1221 int unit_number;
1222 struct pvr2_hdw *hdw;
1223 int *nr_ptr = NULL;
1224 dip->v4lp = vp;
1225
1226 hdw = vp->channel.mc_head->hdw;
1227 dip->v4l_type = v4l_type;
1228 switch (v4l_type) {
1229 case VFL_TYPE_GRABBER:
1230 dip->stream = &vp->channel.mc_head->video_stream;
1231 dip->config = pvr2_config_mpeg;
1232 dip->minor_type = pvr2_v4l_type_video;
1233 nr_ptr = video_nr;
1234 if (!dip->stream) {
1235 pr_err(KBUILD_MODNAME
1236 ": Failed to set up pvrusb2 v4l video dev"
1237 " due to missing stream instance\n");
1238 return;
1239 }
1240 break;
1241 case VFL_TYPE_VBI:
1242 dip->config = pvr2_config_vbi;
1243 dip->minor_type = pvr2_v4l_type_vbi;
1244 nr_ptr = vbi_nr;
1245 break;
1246 case VFL_TYPE_RADIO:
1247 dip->stream = &vp->channel.mc_head->video_stream;
1248 dip->config = pvr2_config_mpeg;
1249 dip->minor_type = pvr2_v4l_type_radio;
1250 nr_ptr = radio_nr;
1251 break;
1252 default:
1253
1254 pr_err(KBUILD_MODNAME ": Failed to set up pvrusb2 v4l dev"
1255 " due to unrecognized config\n");
1256 return;
1257 }
1258
1259 dip->devbase = vdev_template;
1260 dip->devbase.release = pvr2_video_device_release;
1261 dip->devbase.ioctl_ops = &pvr2_ioctl_ops;
1262 {
1263 int val;
1264 pvr2_ctrl_get_value(
1265 pvr2_hdw_get_ctrl_by_id(hdw,
1266 PVR2_CID_STDAVAIL), &val);
1267 dip->devbase.tvnorms = (v4l2_std_id)val;
1268 }
1269
1270 mindevnum = -1;
1271 unit_number = pvr2_hdw_get_unit_number(hdw);
1272 if (nr_ptr && (unit_number >= 0) && (unit_number < PVR_NUM)) {
1273 mindevnum = nr_ptr[unit_number];
1274 }
1275 pvr2_hdw_set_v4l2_dev(hdw, &dip->devbase);
1276 if ((video_register_device(&dip->devbase,
1277 dip->v4l_type, mindevnum) < 0) &&
1278 (video_register_device(&dip->devbase,
1279 dip->v4l_type, -1) < 0)) {
1280 pr_err(KBUILD_MODNAME
1281 ": Failed to register pvrusb2 v4l device\n");
1282 }
1283
1284 printk(KERN_INFO "pvrusb2: registered device %s [%s]\n",
1285 video_device_node_name(&dip->devbase),
1286 pvr2_config_get_name(dip->config));
1287
1288 pvr2_hdw_v4l_store_minor_number(hdw,
1289 dip->minor_type,dip->devbase.minor);
1290}
1291
1292
1293struct pvr2_v4l2 *pvr2_v4l2_create(struct pvr2_context *mnp)
1294{
1295 struct pvr2_v4l2 *vp;
1296
1297 vp = kzalloc(sizeof(*vp),GFP_KERNEL);
1298 if (!vp) return vp;
1299 pvr2_channel_init(&vp->channel,mnp);
1300 pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr2_v4l2 id=%p",vp);
1301
1302 vp->channel.check_func = pvr2_v4l2_internal_check;
1303
1304
1305 vp->dev_video = kzalloc(sizeof(*vp->dev_video),GFP_KERNEL);
1306 if (!vp->dev_video) goto fail;
1307 pvr2_v4l2_dev_init(vp->dev_video,vp,VFL_TYPE_GRABBER);
1308 if (pvr2_hdw_get_input_available(vp->channel.mc_head->hdw) &
1309 (1 << PVR2_CVAL_INPUT_RADIO)) {
1310 vp->dev_radio = kzalloc(sizeof(*vp->dev_radio),GFP_KERNEL);
1311 if (!vp->dev_radio) goto fail;
1312 pvr2_v4l2_dev_init(vp->dev_radio,vp,VFL_TYPE_RADIO);
1313 }
1314
1315 return vp;
1316 fail:
1317 pvr2_trace(PVR2_TRACE_STRUCT,"Failure creating pvr2_v4l2 id=%p",vp);
1318 pvr2_v4l2_destroy_no_lock(vp);
1319 return NULL;
1320}
1321