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