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