Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelv...
[pandora-kernel.git] / drivers / media / video / saa7164 / saa7164-vbi.c
1 /*
2  *  Driver for the NXP SAA7164 PCIe bridge
3  *
4  *  Copyright (c) 2010 Steven Toth <stoth@kernellabs.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #include "saa7164.h"
23
24 static struct saa7164_tvnorm saa7164_tvnorms[] = {
25         {
26                 .name      = "NTSC-M",
27                 .id        = V4L2_STD_NTSC_M,
28         }, {
29                 .name      = "NTSC-JP",
30                 .id        = V4L2_STD_NTSC_M_JP,
31         }
32 };
33
34 static const u32 saa7164_v4l2_ctrls[] = {
35         0
36 };
37
38 /* Take the encoder configuration from the port struct and
39  * flush it to the hardware.
40  */
41 static void saa7164_vbi_configure(struct saa7164_port *port)
42 {
43         struct saa7164_dev *dev = port->dev;
44         dprintk(DBGLVL_VBI, "%s()\n", __func__);
45
46         port->vbi_params.width = port->width;
47         port->vbi_params.height = port->height;
48         port->vbi_params.is_50hz =
49                 (port->encodernorm.id & V4L2_STD_625_50) != 0;
50
51         /* Set up the DIF (enable it) for analog mode by default */
52         saa7164_api_initialize_dif(port);
53
54 //      /* Configure the correct video standard */
55 //      saa7164_api_configure_dif(port, port->encodernorm.id);
56
57 //      /* Ensure the audio decoder is correct configured */
58 //      saa7164_api_set_audio_std(port);
59         dprintk(DBGLVL_VBI, "%s() ends\n", __func__);
60 }
61
62 static int saa7164_vbi_buffers_dealloc(struct saa7164_port *port)
63 {
64         struct list_head *c, *n, *p, *q, *l, *v;
65         struct saa7164_dev *dev = port->dev;
66         struct saa7164_buffer *buf;
67         struct saa7164_user_buffer *ubuf;
68
69         /* Remove any allocated buffers */
70         mutex_lock(&port->dmaqueue_lock);
71
72         dprintk(DBGLVL_VBI, "%s(port=%d) dmaqueue\n", __func__, port->nr);
73         list_for_each_safe(c, n, &port->dmaqueue.list) {
74                 buf = list_entry(c, struct saa7164_buffer, list);
75                 list_del(c);
76                 saa7164_buffer_dealloc(buf);
77         }
78
79         dprintk(DBGLVL_VBI, "%s(port=%d) used\n", __func__, port->nr);
80         list_for_each_safe(p, q, &port->list_buf_used.list) {
81                 ubuf = list_entry(p, struct saa7164_user_buffer, list);
82                 list_del(p);
83                 saa7164_buffer_dealloc_user(ubuf);
84         }
85
86         dprintk(DBGLVL_VBI, "%s(port=%d) free\n", __func__, port->nr);
87         list_for_each_safe(l, v, &port->list_buf_free.list) {
88                 ubuf = list_entry(l, struct saa7164_user_buffer, list);
89                 list_del(l);
90                 saa7164_buffer_dealloc_user(ubuf);
91         }
92
93         mutex_unlock(&port->dmaqueue_lock);
94         dprintk(DBGLVL_VBI, "%s(port=%d) done\n", __func__, port->nr);
95
96         return 0;
97 }
98
99 /* Dynamic buffer switch at vbi start time */
100 static int saa7164_vbi_buffers_alloc(struct saa7164_port *port)
101 {
102         struct saa7164_dev *dev = port->dev;
103         struct saa7164_buffer *buf;
104         struct saa7164_user_buffer *ubuf;
105         struct tmHWStreamParameters *params = &port->hw_streamingparams;
106         int result = -ENODEV, i;
107         int len = 0;
108
109         dprintk(DBGLVL_VBI, "%s()\n", __func__);
110
111         /* TODO: NTSC SPECIFIC */
112         /* Init and establish defaults */
113         params->samplesperline = 1440;
114         params->numberoflines = 12;
115         params->numberoflines = 18;
116         params->pitch = 1600;
117         params->pitch = 1440;
118         params->numpagetables = 2 +
119                 ((params->numberoflines * params->pitch) / PAGE_SIZE);
120         params->bitspersample = 8;
121         params->linethreshold = 0;
122         params->pagetablelistvirt = 0;
123         params->pagetablelistphys = 0;
124         params->numpagetableentries = port->hwcfg.buffercount;
125
126         /* Allocate the PCI resources, buffers (hard) */
127         for (i = 0; i < port->hwcfg.buffercount; i++) {
128                 buf = saa7164_buffer_alloc(port,
129                         params->numberoflines *
130                         params->pitch);
131
132                 if (!buf) {
133                         printk(KERN_ERR "%s() failed "
134                                "(errno = %d), unable to allocate buffer\n",
135                                 __func__, result);
136                         result = -ENOMEM;
137                         goto failed;
138                 } else {
139
140                         mutex_lock(&port->dmaqueue_lock);
141                         list_add_tail(&buf->list, &port->dmaqueue.list);
142                         mutex_unlock(&port->dmaqueue_lock);
143
144                 }
145         }
146
147         /* Allocate some kenrel kernel buffers for copying
148          * to userpsace.
149          */
150         len = params->numberoflines * params->pitch;
151
152         if (vbi_buffers < 16)
153                 vbi_buffers = 16;
154         if (vbi_buffers > 512)
155                 vbi_buffers = 512;
156
157         for (i = 0; i < vbi_buffers; i++) {
158
159                 ubuf = saa7164_buffer_alloc_user(dev, len);
160                 if (ubuf) {
161                         mutex_lock(&port->dmaqueue_lock);
162                         list_add_tail(&ubuf->list, &port->list_buf_free.list);
163                         mutex_unlock(&port->dmaqueue_lock);
164                 }
165
166         }
167
168         result = 0;
169
170 failed:
171         return result;
172 }
173
174
175 static int saa7164_vbi_initialize(struct saa7164_port *port)
176 {
177         saa7164_vbi_configure(port);
178         return 0;
179 }
180
181 /* -- V4L2 --------------------------------------------------------- */
182 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
183 {
184         struct saa7164_vbi_fh *fh = file->private_data;
185         struct saa7164_port *port = fh->port;
186         struct saa7164_dev *dev = port->dev;
187         unsigned int i;
188
189         dprintk(DBGLVL_VBI, "%s(id=0x%x)\n", __func__, (u32)*id);
190
191         for (i = 0; i < ARRAY_SIZE(saa7164_tvnorms); i++) {
192                 if (*id & saa7164_tvnorms[i].id)
193                         break;
194         }
195         if (i == ARRAY_SIZE(saa7164_tvnorms))
196                 return -EINVAL;
197
198         port->encodernorm = saa7164_tvnorms[i];
199
200         /* Update the audio decoder while is not running in
201          * auto detect mode.
202          */
203         saa7164_api_set_audio_std(port);
204
205         dprintk(DBGLVL_VBI, "%s(id=0x%x) OK\n", __func__, (u32)*id);
206
207         return 0;
208 }
209
210 static int vidioc_enum_input(struct file *file, void *priv,
211         struct v4l2_input *i)
212 {
213         int n;
214
215         char *inputs[] = { "tuner", "composite", "svideo", "aux",
216                 "composite 2", "svideo 2", "aux 2" };
217
218         if (i->index >= 7)
219                 return -EINVAL;
220
221         strcpy(i->name, inputs[i->index]);
222
223         if (i->index == 0)
224                 i->type = V4L2_INPUT_TYPE_TUNER;
225         else
226                 i->type  = V4L2_INPUT_TYPE_CAMERA;
227
228         for (n = 0; n < ARRAY_SIZE(saa7164_tvnorms); n++)
229                 i->std |= saa7164_tvnorms[n].id;
230
231         return 0;
232 }
233
234 static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
235 {
236         struct saa7164_vbi_fh *fh = file->private_data;
237         struct saa7164_port *port = fh->port;
238         struct saa7164_dev *dev = port->dev;
239
240         if (saa7164_api_get_videomux(port) != SAA_OK)
241                 return -EIO;
242
243         *i = (port->mux_input - 1);
244
245         dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, *i);
246
247         return 0;
248 }
249
250 static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
251 {
252         struct saa7164_vbi_fh *fh = file->private_data;
253         struct saa7164_port *port = fh->port;
254         struct saa7164_dev *dev = port->dev;
255
256         dprintk(DBGLVL_VBI, "%s() input=%d\n", __func__, i);
257
258         if (i >= 7)
259                 return -EINVAL;
260
261         port->mux_input = i + 1;
262
263         if (saa7164_api_set_videomux(port) != SAA_OK)
264                 return -EIO;
265
266         return 0;
267 }
268
269 static int vidioc_g_tuner(struct file *file, void *priv,
270         struct v4l2_tuner *t)
271 {
272         struct saa7164_vbi_fh *fh = file->private_data;
273         struct saa7164_port *port = fh->port;
274         struct saa7164_dev *dev = port->dev;
275
276         if (0 != t->index)
277                 return -EINVAL;
278
279         strcpy(t->name, "tuner");
280         t->type = V4L2_TUNER_ANALOG_TV;
281         t->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO;
282
283         dprintk(DBGLVL_VBI, "VIDIOC_G_TUNER: tuner type %d\n", t->type);
284
285         return 0;
286 }
287
288 static int vidioc_s_tuner(struct file *file, void *priv,
289         struct v4l2_tuner *t)
290 {
291         /* Update the A/V core */
292         return 0;
293 }
294
295 static int vidioc_g_frequency(struct file *file, void *priv,
296         struct v4l2_frequency *f)
297 {
298         struct saa7164_vbi_fh *fh = file->private_data;
299         struct saa7164_port *port = fh->port;
300
301         f->type = V4L2_TUNER_ANALOG_TV;
302         f->frequency = port->freq;
303
304         return 0;
305 }
306
307 static int vidioc_s_frequency(struct file *file, void *priv,
308         struct v4l2_frequency *f)
309 {
310         struct saa7164_vbi_fh *fh = file->private_data;
311         struct saa7164_port *port = fh->port;
312         struct saa7164_dev *dev = port->dev;
313         struct saa7164_port *tsport;
314         struct dvb_frontend *fe;
315
316         /* TODO: Pull this for the std */
317         struct analog_parameters params = {
318                 .mode      = V4L2_TUNER_ANALOG_TV,
319                 .audmode   = V4L2_TUNER_MODE_STEREO,
320                 .std       = port->encodernorm.id,
321                 .frequency = f->frequency
322         };
323
324         /* Stop the encoder */
325         dprintk(DBGLVL_VBI, "%s() frequency=%d tuner=%d\n", __func__,
326                 f->frequency, f->tuner);
327
328         if (f->tuner != 0)
329                 return -EINVAL;
330
331         if (f->type != V4L2_TUNER_ANALOG_TV)
332                 return -EINVAL;
333
334         port->freq = f->frequency;
335
336         /* Update the hardware */
337         if (port->nr == SAA7164_PORT_VBI1)
338                 tsport = &dev->ports[SAA7164_PORT_TS1];
339         else
340         if (port->nr == SAA7164_PORT_VBI2)
341                 tsport = &dev->ports[SAA7164_PORT_TS2];
342         else
343                 BUG();
344
345         fe = tsport->dvb.frontend;
346
347         if (fe && fe->ops.tuner_ops.set_analog_params)
348                 fe->ops.tuner_ops.set_analog_params(fe, &params);
349         else
350                 printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__);
351
352         saa7164_vbi_initialize(port);
353
354         return 0;
355 }
356
357 static int vidioc_g_ctrl(struct file *file, void *priv,
358         struct v4l2_control *ctl)
359 {
360         struct saa7164_vbi_fh *fh = file->private_data;
361         struct saa7164_port *port = fh->port;
362         struct saa7164_dev *dev = port->dev;
363
364         dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
365                 ctl->id, ctl->value);
366
367         switch (ctl->id) {
368         case V4L2_CID_BRIGHTNESS:
369                 ctl->value = port->ctl_brightness;
370                 break;
371         case V4L2_CID_CONTRAST:
372                 ctl->value = port->ctl_contrast;
373                 break;
374         case V4L2_CID_SATURATION:
375                 ctl->value = port->ctl_saturation;
376                 break;
377         case V4L2_CID_HUE:
378                 ctl->value = port->ctl_hue;
379                 break;
380         case V4L2_CID_SHARPNESS:
381                 ctl->value = port->ctl_sharpness;
382                 break;
383         case V4L2_CID_AUDIO_VOLUME:
384                 ctl->value = port->ctl_volume;
385                 break;
386         default:
387                 return -EINVAL;
388         }
389
390         return 0;
391 }
392
393 static int vidioc_s_ctrl(struct file *file, void *priv,
394         struct v4l2_control *ctl)
395 {
396         struct saa7164_vbi_fh *fh = file->private_data;
397         struct saa7164_port *port = fh->port;
398         struct saa7164_dev *dev = port->dev;
399         int ret = 0;
400
401         dprintk(DBGLVL_VBI, "%s(id=%d, value=%d)\n", __func__,
402                 ctl->id, ctl->value);
403
404         switch (ctl->id) {
405         case V4L2_CID_BRIGHTNESS:
406                 if ((ctl->value >= 0) && (ctl->value <= 255)) {
407                         port->ctl_brightness = ctl->value;
408                         saa7164_api_set_usercontrol(port,
409                                 PU_BRIGHTNESS_CONTROL);
410                 } else
411                         ret = -EINVAL;
412                 break;
413         case V4L2_CID_CONTRAST:
414                 if ((ctl->value >= 0) && (ctl->value <= 255)) {
415                         port->ctl_contrast = ctl->value;
416                         saa7164_api_set_usercontrol(port, PU_CONTRAST_CONTROL);
417                 } else
418                         ret = -EINVAL;
419                 break;
420         case V4L2_CID_SATURATION:
421                 if ((ctl->value >= 0) && (ctl->value <= 255)) {
422                         port->ctl_saturation = ctl->value;
423                         saa7164_api_set_usercontrol(port,
424                                 PU_SATURATION_CONTROL);
425                 } else
426                         ret = -EINVAL;
427                 break;
428         case V4L2_CID_HUE:
429                 if ((ctl->value >= 0) && (ctl->value <= 255)) {
430                         port->ctl_hue = ctl->value;
431                         saa7164_api_set_usercontrol(port, PU_HUE_CONTROL);
432                 } else
433                         ret = -EINVAL;
434                 break;
435         case V4L2_CID_SHARPNESS:
436                 if ((ctl->value >= 0) && (ctl->value <= 255)) {
437                         port->ctl_sharpness = ctl->value;
438                         saa7164_api_set_usercontrol(port, PU_SHARPNESS_CONTROL);
439                 } else
440                         ret = -EINVAL;
441                 break;
442         case V4L2_CID_AUDIO_VOLUME:
443                 if ((ctl->value >= -83) && (ctl->value <= 24)) {
444                         port->ctl_volume = ctl->value;
445                         saa7164_api_set_audio_volume(port, port->ctl_volume);
446                 } else
447                         ret = -EINVAL;
448                 break;
449         default:
450                 ret = -EINVAL;
451         }
452
453         return ret;
454 }
455
456 static int saa7164_get_ctrl(struct saa7164_port *port,
457         struct v4l2_ext_control *ctrl)
458 {
459         struct saa7164_vbi_params *params = &port->vbi_params;
460
461         switch (ctrl->id) {
462         case V4L2_CID_MPEG_STREAM_TYPE:
463                 ctrl->value = params->stream_type;
464                 break;
465         case V4L2_CID_MPEG_AUDIO_MUTE:
466                 ctrl->value = params->ctl_mute;
467                 break;
468         case V4L2_CID_MPEG_VIDEO_ASPECT:
469                 ctrl->value = params->ctl_aspect;
470                 break;
471         case V4L2_CID_MPEG_VIDEO_B_FRAMES:
472                 ctrl->value = params->refdist;
473                 break;
474         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
475                 ctrl->value = params->gop_size;
476                 break;
477         default:
478                 return -EINVAL;
479         }
480         return 0;
481 }
482
483 static int vidioc_g_ext_ctrls(struct file *file, void *priv,
484         struct v4l2_ext_controls *ctrls)
485 {
486         struct saa7164_vbi_fh *fh = file->private_data;
487         struct saa7164_port *port = fh->port;
488         int i, err = 0;
489
490         if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
491                 for (i = 0; i < ctrls->count; i++) {
492                         struct v4l2_ext_control *ctrl = ctrls->controls + i;
493
494                         err = saa7164_get_ctrl(port, ctrl);
495                         if (err) {
496                                 ctrls->error_idx = i;
497                                 break;
498                         }
499                 }
500                 return err;
501
502         }
503
504         return -EINVAL;
505 }
506
507 static int saa7164_try_ctrl(struct v4l2_ext_control *ctrl, int ac3)
508 {
509         int ret = -EINVAL;
510
511         switch (ctrl->id) {
512         case V4L2_CID_MPEG_STREAM_TYPE:
513                 if ((ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_PS) ||
514                         (ctrl->value == V4L2_MPEG_STREAM_TYPE_MPEG2_TS))
515                         ret = 0;
516                 break;
517         case V4L2_CID_MPEG_AUDIO_MUTE:
518                 if ((ctrl->value >= 0) &&
519                         (ctrl->value <= 1))
520                         ret = 0;
521                 break;
522         case V4L2_CID_MPEG_VIDEO_ASPECT:
523                 if ((ctrl->value >= V4L2_MPEG_VIDEO_ASPECT_1x1) &&
524                         (ctrl->value <= V4L2_MPEG_VIDEO_ASPECT_221x100))
525                         ret = 0;
526                 break;
527         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
528                 if ((ctrl->value >= 0) &&
529                         (ctrl->value <= 255))
530                         ret = 0;
531                 break;
532         case V4L2_CID_MPEG_VIDEO_B_FRAMES:
533                 if ((ctrl->value >= 1) &&
534                         (ctrl->value <= 3))
535                         ret = 0;
536                 break;
537         default:
538                 ret = -EINVAL;
539         }
540
541         return ret;
542 }
543
544 static int vidioc_try_ext_ctrls(struct file *file, void *priv,
545         struct v4l2_ext_controls *ctrls)
546 {
547         int i, err = 0;
548
549         if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
550                 for (i = 0; i < ctrls->count; i++) {
551                         struct v4l2_ext_control *ctrl = ctrls->controls + i;
552
553                         err = saa7164_try_ctrl(ctrl, 0);
554                         if (err) {
555                                 ctrls->error_idx = i;
556                                 break;
557                         }
558                 }
559                 return err;
560         }
561
562         return -EINVAL;
563 }
564
565 static int saa7164_set_ctrl(struct saa7164_port *port,
566         struct v4l2_ext_control *ctrl)
567 {
568         struct saa7164_vbi_params *params = &port->vbi_params;
569         int ret = 0;
570
571         switch (ctrl->id) {
572         case V4L2_CID_MPEG_STREAM_TYPE:
573                 params->stream_type = ctrl->value;
574                 break;
575         case V4L2_CID_MPEG_AUDIO_MUTE:
576                 params->ctl_mute = ctrl->value;
577                 ret = saa7164_api_audio_mute(port, params->ctl_mute);
578                 if (ret != SAA_OK) {
579                         printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
580                                 ret);
581                         ret = -EIO;
582                 }
583                 break;
584         case V4L2_CID_MPEG_VIDEO_ASPECT:
585                 params->ctl_aspect = ctrl->value;
586                 ret = saa7164_api_set_aspect_ratio(port);
587                 if (ret != SAA_OK) {
588                         printk(KERN_ERR "%s() error, ret = 0x%x\n", __func__,
589                                 ret);
590                         ret = -EIO;
591                 }
592                 break;
593         case V4L2_CID_MPEG_VIDEO_B_FRAMES:
594                 params->refdist = ctrl->value;
595                 break;
596         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
597                 params->gop_size = ctrl->value;
598                 break;
599         default:
600                 return -EINVAL;
601         }
602
603         /* TODO: Update the hardware */
604
605         return ret;
606 }
607
608 static int vidioc_s_ext_ctrls(struct file *file, void *priv,
609         struct v4l2_ext_controls *ctrls)
610 {
611         struct saa7164_vbi_fh *fh = file->private_data;
612         struct saa7164_port *port = fh->port;
613         int i, err = 0;
614
615         if (ctrls->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
616                 for (i = 0; i < ctrls->count; i++) {
617                         struct v4l2_ext_control *ctrl = ctrls->controls + i;
618
619                         err = saa7164_try_ctrl(ctrl, 0);
620                         if (err) {
621                                 ctrls->error_idx = i;
622                                 break;
623                         }
624                         err = saa7164_set_ctrl(port, ctrl);
625                         if (err) {
626                                 ctrls->error_idx = i;
627                                 break;
628                         }
629                 }
630                 return err;
631
632         }
633
634         return -EINVAL;
635 }
636
637 static int vidioc_querycap(struct file *file, void  *priv,
638         struct v4l2_capability *cap)
639 {
640         struct saa7164_vbi_fh *fh = file->private_data;
641         struct saa7164_port *port = fh->port;
642         struct saa7164_dev *dev = port->dev;
643
644         strcpy(cap->driver, dev->name);
645         strlcpy(cap->card, saa7164_boards[dev->board].name,
646                 sizeof(cap->card));
647         sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
648
649         cap->capabilities =
650                 V4L2_CAP_VBI_CAPTURE |
651                 V4L2_CAP_READWRITE     |
652                 0;
653
654         cap->capabilities |= V4L2_CAP_TUNER;
655         cap->version = 0;
656
657         return 0;
658 }
659
660 static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
661         struct v4l2_fmtdesc *f)
662 {
663         if (f->index != 0)
664                 return -EINVAL;
665
666         strlcpy(f->description, "VBI", sizeof(f->description));
667         f->pixelformat = V4L2_PIX_FMT_MPEG;
668
669         return 0;
670 }
671
672 static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
673                                 struct v4l2_format *f)
674 {
675         struct saa7164_vbi_fh *fh = file->private_data;
676         struct saa7164_port *port = fh->port;
677         struct saa7164_dev *dev = port->dev;
678
679         f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
680         f->fmt.pix.bytesperline = 0;
681         f->fmt.pix.sizeimage    =
682                 port->ts_packet_size * port->ts_packet_count;
683         f->fmt.pix.colorspace   = 0;
684         f->fmt.pix.width        = port->width;
685         f->fmt.pix.height       = port->height;
686
687         dprintk(DBGLVL_VBI, "VIDIOC_G_FMT: w: %d, h: %d\n",
688                 port->width, port->height);
689
690         return 0;
691 }
692
693 static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
694                                 struct v4l2_format *f)
695 {
696         struct saa7164_vbi_fh *fh = file->private_data;
697         struct saa7164_port *port = fh->port;
698         struct saa7164_dev *dev = port->dev;
699
700         f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
701         f->fmt.pix.bytesperline = 0;
702         f->fmt.pix.sizeimage    =
703                 port->ts_packet_size * port->ts_packet_count;
704         f->fmt.pix.colorspace   = 0;
705         dprintk(DBGLVL_VBI, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
706                 port->width, port->height);
707         return 0;
708 }
709
710 static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
711                                 struct v4l2_format *f)
712 {
713         struct saa7164_vbi_fh *fh = file->private_data;
714         struct saa7164_port *port = fh->port;
715         struct saa7164_dev *dev = port->dev;
716
717         f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
718         f->fmt.pix.bytesperline = 0;
719         f->fmt.pix.sizeimage    =
720                 port->ts_packet_size * port->ts_packet_count;
721         f->fmt.pix.colorspace   = 0;
722
723         dprintk(DBGLVL_VBI, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
724                 f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
725
726         return 0;
727 }
728
729 static int vidioc_log_status(struct file *file, void *priv)
730 {
731         return 0;
732 }
733
734 static int fill_queryctrl(struct saa7164_vbi_params *params,
735         struct v4l2_queryctrl *c)
736 {
737         switch (c->id) {
738         case V4L2_CID_BRIGHTNESS:
739                 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
740         case V4L2_CID_CONTRAST:
741                 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
742         case V4L2_CID_SATURATION:
743                 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
744         case V4L2_CID_HUE:
745                 return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
746         case V4L2_CID_SHARPNESS:
747                 return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
748         case V4L2_CID_MPEG_AUDIO_MUTE:
749                 return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
750         case V4L2_CID_AUDIO_VOLUME:
751                 return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
752         case V4L2_CID_MPEG_STREAM_TYPE:
753                 return v4l2_ctrl_query_fill(c,
754                         V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
755                         V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
756                         1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
757         case V4L2_CID_MPEG_VIDEO_ASPECT:
758                 return v4l2_ctrl_query_fill(c,
759                         V4L2_MPEG_VIDEO_ASPECT_1x1,
760                         V4L2_MPEG_VIDEO_ASPECT_221x100,
761                         1, V4L2_MPEG_VIDEO_ASPECT_4x3);
762         case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
763                 return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
764         case V4L2_CID_MPEG_VIDEO_B_FRAMES:
765                 return v4l2_ctrl_query_fill(c,
766                         1, 3, 1, 1);
767         default:
768                 return -EINVAL;
769         }
770 }
771
772 static int vidioc_queryctrl(struct file *file, void *priv,
773         struct v4l2_queryctrl *c)
774 {
775         struct saa7164_vbi_fh *fh = priv;
776         struct saa7164_port *port = fh->port;
777         int i, next;
778         u32 id = c->id;
779
780         memset(c, 0, sizeof(*c));
781
782         next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
783         c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
784
785         for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
786                 if (next) {
787                         if (c->id < saa7164_v4l2_ctrls[i])
788                                 c->id = saa7164_v4l2_ctrls[i];
789                         else
790                                 continue;
791                 }
792
793                 if (c->id == saa7164_v4l2_ctrls[i])
794                         return fill_queryctrl(&port->vbi_params, c);
795
796                 if (c->id < saa7164_v4l2_ctrls[i])
797                         break;
798         }
799
800         return -EINVAL;
801 }
802
803 static int saa7164_vbi_stop_port(struct saa7164_port *port)
804 {
805         struct saa7164_dev *dev = port->dev;
806         int ret;
807
808         ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
809         if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
810                 printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
811                         __func__, ret);
812                 ret = -EIO;
813         } else {
814                 dprintk(DBGLVL_VBI, "%s()    Stopped\n", __func__);
815                 ret = 0;
816         }
817
818         return ret;
819 }
820
821 static int saa7164_vbi_acquire_port(struct saa7164_port *port)
822 {
823         struct saa7164_dev *dev = port->dev;
824         int ret;
825
826         ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
827         if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
828                 printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
829                         __func__, ret);
830                 ret = -EIO;
831         } else {
832                 dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__);
833                 ret = 0;
834         }
835
836         return ret;
837 }
838
839 static int saa7164_vbi_pause_port(struct saa7164_port *port)
840 {
841         struct saa7164_dev *dev = port->dev;
842         int ret;
843
844         ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
845         if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
846                 printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
847                         __func__, ret);
848                 ret = -EIO;
849         } else {
850                 dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
851                 ret = 0;
852         }
853
854         return ret;
855 }
856
857 /* Firmware is very windows centric, meaning you have to transition
858  * the part through AVStream / KS Windows stages, forwards or backwards.
859  * States are: stopped, acquired (h/w), paused, started.
860  * We have to leave here will all of the soft buffers on the free list,
861  * else the cfg_post() func won't have soft buffers to correctly configure.
862  */
863 static int saa7164_vbi_stop_streaming(struct saa7164_port *port)
864 {
865         struct saa7164_dev *dev = port->dev;
866         struct saa7164_buffer *buf;
867         struct saa7164_user_buffer *ubuf;
868         struct list_head *c, *n;
869         int ret;
870
871         dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
872
873         ret = saa7164_vbi_pause_port(port);
874         ret = saa7164_vbi_acquire_port(port);
875         ret = saa7164_vbi_stop_port(port);
876
877         dprintk(DBGLVL_VBI, "%s(port=%d) Hardware stopped\n", __func__,
878                 port->nr);
879
880         /* Reset the state of any allocated buffer resources */
881         mutex_lock(&port->dmaqueue_lock);
882
883         /* Reset the hard and soft buffer state */
884         list_for_each_safe(c, n, &port->dmaqueue.list) {
885                 buf = list_entry(c, struct saa7164_buffer, list);
886                 buf->flags = SAA7164_BUFFER_FREE;
887                 buf->pos = 0;
888         }
889
890         list_for_each_safe(c, n, &port->list_buf_used.list) {
891                 ubuf = list_entry(c, struct saa7164_user_buffer, list);
892                 ubuf->pos = 0;
893                 list_move_tail(&ubuf->list, &port->list_buf_free.list);
894         }
895
896         mutex_unlock(&port->dmaqueue_lock);
897
898         /* Free any allocated resources */
899         saa7164_vbi_buffers_dealloc(port);
900
901         dprintk(DBGLVL_VBI, "%s(port=%d) Released\n", __func__, port->nr);
902
903         return ret;
904 }
905
906 static int saa7164_vbi_start_streaming(struct saa7164_port *port)
907 {
908         struct saa7164_dev *dev = port->dev;
909         int result, ret = 0;
910
911         dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
912
913         port->done_first_interrupt = 0;
914
915         /* allocate all of the PCIe DMA buffer resources on the fly,
916          * allowing switching between TS and PS payloads without
917          * requiring a complete driver reload.
918          */
919         saa7164_vbi_buffers_alloc(port);
920
921         /* Configure the encoder with any cache values */
922 //      saa7164_api_set_encoder(port);
923 //      saa7164_api_get_encoder(port);
924
925         /* Place the empty buffers on the hardware */
926         saa7164_buffer_cfg_port(port);
927
928         /* Negotiate format */
929         if (saa7164_api_set_vbi_format(port) != SAA_OK) {
930                 printk(KERN_ERR "%s() No supported VBI format\n", __func__);
931                 ret = -EIO;
932                 goto out;
933         }
934
935         /* Acquire the hardware */
936         result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
937         if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
938                 printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
939                         __func__, result);
940
941                 ret = -EIO;
942                 goto out;
943         } else
944                 dprintk(DBGLVL_VBI, "%s()   Acquired\n", __func__);
945
946         /* Pause the hardware */
947         result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
948         if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
949                 printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
950                                 __func__, result);
951
952                 /* Stop the hardware, regardless */
953                 result = saa7164_vbi_stop_port(port);
954                 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
955                         printk(KERN_ERR "%s() pause/forced stop transition "
956                                 "failed, res = 0x%x\n", __func__, result);
957                 }
958
959                 ret = -EIO;
960                 goto out;
961         } else
962                 dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
963
964         /* Start the hardware */
965         result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
966         if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
967                 printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
968                                 __func__, result);
969
970                 /* Stop the hardware, regardless */
971                 result = saa7164_vbi_acquire_port(port);
972                 result = saa7164_vbi_stop_port(port);
973                 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
974                         printk(KERN_ERR "%s() run/forced stop transition "
975                                 "failed, res = 0x%x\n", __func__, result);
976                 }
977
978                 ret = -EIO;
979         } else
980                 dprintk(DBGLVL_VBI, "%s()   Running\n", __func__);
981
982 out:
983         return ret;
984 }
985
986 int saa7164_vbi_fmt(struct file *file, void *priv, struct v4l2_format *f)
987 {
988         /* ntsc */
989         f->fmt.vbi.samples_per_line = 1600;
990         f->fmt.vbi.samples_per_line = 1440;
991         f->fmt.vbi.sampling_rate = 27000000;
992         f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
993         f->fmt.vbi.offset = 0;
994         f->fmt.vbi.flags = 0;
995         f->fmt.vbi.start[0] = 10;
996         f->fmt.vbi.count[0] = 18;
997         f->fmt.vbi.start[1] = 263 + 10 + 1;
998         f->fmt.vbi.count[1] = 18;
999         return 0;
1000 }
1001
1002 static int fops_open(struct file *file)
1003 {
1004         struct saa7164_dev *dev;
1005         struct saa7164_port *port;
1006         struct saa7164_vbi_fh *fh;
1007
1008         port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
1009         if (!port)
1010                 return -ENODEV;
1011
1012         dev = port->dev;
1013
1014         dprintk(DBGLVL_VBI, "%s()\n", __func__);
1015
1016         /* allocate + initialize per filehandle data */
1017         fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1018         if (NULL == fh)
1019                 return -ENOMEM;
1020
1021         file->private_data = fh;
1022         fh->port = port;
1023
1024         return 0;
1025 }
1026
1027 static int fops_release(struct file *file)
1028 {
1029         struct saa7164_vbi_fh *fh = file->private_data;
1030         struct saa7164_port *port = fh->port;
1031         struct saa7164_dev *dev = port->dev;
1032
1033         dprintk(DBGLVL_VBI, "%s()\n", __func__);
1034
1035         /* Shut device down on last close */
1036         if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
1037                 if (atomic_dec_return(&port->v4l_reader_count) == 0) {
1038                         /* stop vbi capture then cancel buffers */
1039                         saa7164_vbi_stop_streaming(port);
1040                 }
1041         }
1042
1043         file->private_data = NULL;
1044         kfree(fh);
1045
1046         return 0;
1047 }
1048
1049 struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
1050 {
1051         struct saa7164_user_buffer *ubuf = 0;
1052         struct saa7164_dev *dev = port->dev;
1053         u32 crc;
1054
1055         mutex_lock(&port->dmaqueue_lock);
1056         if (!list_empty(&port->list_buf_used.list)) {
1057                 ubuf = list_first_entry(&port->list_buf_used.list,
1058                         struct saa7164_user_buffer, list);
1059
1060                 if (crc_checking) {
1061                         crc = crc32(0, ubuf->data, ubuf->actual_size);
1062                         if (crc != ubuf->crc) {
1063                                 printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", __func__,
1064                                         ubuf, ubuf->crc, crc);
1065                         }
1066                 }
1067
1068         }
1069         mutex_unlock(&port->dmaqueue_lock);
1070
1071         dprintk(DBGLVL_VBI, "%s() returns %p\n", __func__, ubuf);
1072
1073         return ubuf;
1074 }
1075
1076 static ssize_t fops_read(struct file *file, char __user *buffer,
1077         size_t count, loff_t *pos)
1078 {
1079         struct saa7164_vbi_fh *fh = file->private_data;
1080         struct saa7164_port *port = fh->port;
1081         struct saa7164_user_buffer *ubuf = NULL;
1082         struct saa7164_dev *dev = port->dev;
1083         int ret = 0;
1084         int rem, cnt;
1085         u8 *p;
1086
1087         port->last_read_msecs_diff = port->last_read_msecs;
1088         port->last_read_msecs = jiffies_to_msecs(jiffies);
1089         port->last_read_msecs_diff = port->last_read_msecs -
1090                 port->last_read_msecs_diff;
1091
1092         saa7164_histogram_update(&port->read_interval,
1093                 port->last_read_msecs_diff);
1094
1095         if (*pos) {
1096                 printk(KERN_ERR "%s() ESPIPE\n", __func__);
1097                 return -ESPIPE;
1098         }
1099
1100         if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
1101                 if (atomic_inc_return(&port->v4l_reader_count) == 1) {
1102
1103                         if (saa7164_vbi_initialize(port) < 0) {
1104                                 printk(KERN_ERR "%s() EINVAL\n", __func__);
1105                                 return -EINVAL;
1106                         }
1107
1108                         saa7164_vbi_start_streaming(port);
1109                         msleep(200);
1110                 }
1111         }
1112
1113         /* blocking wait for buffer */
1114         if ((file->f_flags & O_NONBLOCK) == 0) {
1115                 if (wait_event_interruptible(port->wait_read,
1116                         saa7164_vbi_next_buf(port))) {
1117                                 printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
1118                                 return -ERESTARTSYS;
1119                 }
1120         }
1121
1122         /* Pull the first buffer from the used list */
1123         ubuf = saa7164_vbi_next_buf(port);
1124
1125         while ((count > 0) && ubuf) {
1126
1127                 /* set remaining bytes to copy */
1128                 rem = ubuf->actual_size - ubuf->pos;
1129                 cnt = rem > count ? count : rem;
1130
1131                 p = ubuf->data + ubuf->pos;
1132
1133                 dprintk(DBGLVL_VBI,
1134                         "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
1135                         __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
1136
1137                 if (copy_to_user(buffer, p, cnt)) {
1138                         printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
1139                         if (!ret) {
1140                                 printk(KERN_ERR "%s() EFAULT\n", __func__);
1141                                 ret = -EFAULT;
1142                         }
1143                         goto err;
1144                 }
1145
1146                 ubuf->pos += cnt;
1147                 count -= cnt;
1148                 buffer += cnt;
1149                 ret += cnt;
1150
1151                 if (ubuf->pos > ubuf->actual_size) {
1152                         printk(KERN_ERR "read() pos > actual, huh?\n");
1153                 }
1154
1155                 if (ubuf->pos == ubuf->actual_size) {
1156
1157                         /* finished with current buffer, take next buffer */
1158
1159                         /* Requeue the buffer on the free list */
1160                         ubuf->pos = 0;
1161
1162                         mutex_lock(&port->dmaqueue_lock);
1163                         list_move_tail(&ubuf->list, &port->list_buf_free.list);
1164                         mutex_unlock(&port->dmaqueue_lock);
1165
1166                         /* Dequeue next */
1167                         if ((file->f_flags & O_NONBLOCK) == 0) {
1168                                 if (wait_event_interruptible(port->wait_read,
1169                                         saa7164_vbi_next_buf(port))) {
1170                                                 break;
1171                                 }
1172                         }
1173                         ubuf = saa7164_vbi_next_buf(port);
1174                 }
1175         }
1176 err:
1177         if (!ret && !ubuf) {
1178                 printk(KERN_ERR "%s() EAGAIN\n", __func__);
1179                 ret = -EAGAIN;
1180         }
1181
1182         return ret;
1183 }
1184
1185 static unsigned int fops_poll(struct file *file, poll_table *wait)
1186 {
1187         struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data;
1188         struct saa7164_port *port = fh->port;
1189         struct saa7164_user_buffer *ubuf;
1190         unsigned int mask = 0;
1191
1192         port->last_poll_msecs_diff = port->last_poll_msecs;
1193         port->last_poll_msecs = jiffies_to_msecs(jiffies);
1194         port->last_poll_msecs_diff = port->last_poll_msecs -
1195                 port->last_poll_msecs_diff;
1196
1197         saa7164_histogram_update(&port->poll_interval,
1198                 port->last_poll_msecs_diff);
1199
1200         if (!video_is_registered(port->v4l_device)) {
1201                 return -EIO;
1202         }
1203
1204         if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
1205                 if (atomic_inc_return(&port->v4l_reader_count) == 1) {
1206                         if (saa7164_vbi_initialize(port) < 0)
1207                                 return -EINVAL;
1208                         saa7164_vbi_start_streaming(port);
1209                         msleep(200);
1210                 }
1211         }
1212
1213         /* blocking wait for buffer */
1214         if ((file->f_flags & O_NONBLOCK) == 0) {
1215                 if (wait_event_interruptible(port->wait_read,
1216                         saa7164_vbi_next_buf(port))) {
1217                                 return -ERESTARTSYS;
1218                 }
1219         }
1220
1221         /* Pull the first buffer from the used list */
1222         ubuf = list_first_entry(&port->list_buf_used.list,
1223                 struct saa7164_user_buffer, list);
1224
1225         if (ubuf)
1226                 mask |= POLLIN | POLLRDNORM;
1227
1228         return mask;
1229 }
1230 static const struct v4l2_file_operations vbi_fops = {
1231         .owner          = THIS_MODULE,
1232         .open           = fops_open,
1233         .release        = fops_release,
1234         .read           = fops_read,
1235         .poll           = fops_poll,
1236         .unlocked_ioctl = video_ioctl2,
1237 };
1238
1239 static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
1240         .vidioc_s_std            = vidioc_s_std,
1241         .vidioc_enum_input       = vidioc_enum_input,
1242         .vidioc_g_input          = vidioc_g_input,
1243         .vidioc_s_input          = vidioc_s_input,
1244         .vidioc_g_tuner          = vidioc_g_tuner,
1245         .vidioc_s_tuner          = vidioc_s_tuner,
1246         .vidioc_g_frequency      = vidioc_g_frequency,
1247         .vidioc_s_frequency      = vidioc_s_frequency,
1248         .vidioc_s_ctrl           = vidioc_s_ctrl,
1249         .vidioc_g_ctrl           = vidioc_g_ctrl,
1250         .vidioc_querycap         = vidioc_querycap,
1251         .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1252         .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
1253         .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
1254         .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_cap,
1255         .vidioc_g_ext_ctrls      = vidioc_g_ext_ctrls,
1256         .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
1257         .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
1258         .vidioc_log_status       = vidioc_log_status,
1259         .vidioc_queryctrl        = vidioc_queryctrl,
1260 //      .vidioc_g_chip_ident     = saa7164_g_chip_ident,
1261 #ifdef CONFIG_VIDEO_ADV_DEBUG
1262 //      .vidioc_g_register       = saa7164_g_register,
1263 //      .vidioc_s_register       = saa7164_s_register,
1264 #endif
1265         .vidioc_g_fmt_vbi_cap    = saa7164_vbi_fmt,
1266         .vidioc_try_fmt_vbi_cap  = saa7164_vbi_fmt,
1267         .vidioc_s_fmt_vbi_cap    = saa7164_vbi_fmt,
1268 };
1269
1270 static struct video_device saa7164_vbi_template = {
1271         .name          = "saa7164",
1272         .fops          = &vbi_fops,
1273         .ioctl_ops     = &vbi_ioctl_ops,
1274         .minor         = -1,
1275         .tvnorms       = SAA7164_NORMS,
1276         .current_norm  = V4L2_STD_NTSC_M,
1277 };
1278
1279 static struct video_device *saa7164_vbi_alloc(
1280         struct saa7164_port *port,
1281         struct pci_dev *pci,
1282         struct video_device *template,
1283         char *type)
1284 {
1285         struct video_device *vfd;
1286         struct saa7164_dev *dev = port->dev;
1287
1288         dprintk(DBGLVL_VBI, "%s()\n", __func__);
1289
1290         vfd = video_device_alloc();
1291         if (NULL == vfd)
1292                 return NULL;
1293
1294         *vfd = *template;
1295         snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
1296                 type, saa7164_boards[dev->board].name);
1297
1298         vfd->parent  = &pci->dev;
1299         vfd->release = video_device_release;
1300         return vfd;
1301 }
1302
1303 int saa7164_vbi_register(struct saa7164_port *port)
1304 {
1305         struct saa7164_dev *dev = port->dev;
1306         int result = -ENODEV;
1307
1308         dprintk(DBGLVL_VBI, "%s()\n", __func__);
1309
1310         if (port->type != SAA7164_MPEG_VBI)
1311                 BUG();
1312
1313         /* Sanity check that the PCI configuration space is active */
1314         if (port->hwcfg.BARLocation == 0) {
1315                 printk(KERN_ERR "%s() failed "
1316                        "(errno = %d), NO PCI configuration\n",
1317                         __func__, result);
1318                 result = -ENOMEM;
1319                 goto failed;
1320         }
1321
1322         /* Establish VBI defaults here */
1323
1324         /* Allocate and register the video device node */
1325         port->v4l_device = saa7164_vbi_alloc(port,
1326                 dev->pci, &saa7164_vbi_template, "vbi");
1327
1328         if (port->v4l_device == NULL) {
1329                 printk(KERN_INFO "%s: can't allocate vbi device\n",
1330                         dev->name);
1331                 result = -ENOMEM;
1332                 goto failed;
1333         }
1334
1335         video_set_drvdata(port->v4l_device, port);
1336         result = video_register_device(port->v4l_device,
1337                 VFL_TYPE_VBI, -1);
1338         if (result < 0) {
1339                 printk(KERN_INFO "%s: can't register vbi device\n",
1340                         dev->name);
1341                 /* TODO: We're going to leak here if we don't dealloc
1342                  The buffers above. The unreg function can't deal wit it.
1343                 */
1344                 goto failed;
1345         }
1346
1347         printk(KERN_INFO "%s: registered device vbi%d [vbi]\n",
1348                 dev->name, port->v4l_device->num);
1349
1350         /* Configure the hardware defaults */
1351
1352         result = 0;
1353 failed:
1354         return result;
1355 }
1356
1357 void saa7164_vbi_unregister(struct saa7164_port *port)
1358 {
1359         struct saa7164_dev *dev = port->dev;
1360
1361         dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
1362
1363         if (port->type != SAA7164_MPEG_VBI)
1364                 BUG();
1365
1366         if (port->v4l_device) {
1367                 if (port->v4l_device->minor != -1)
1368                         video_unregister_device(port->v4l_device);
1369                 else
1370                         video_device_release(port->v4l_device);
1371
1372                 port->v4l_device = NULL;
1373         }
1374
1375 }