linux/drivers/media/video/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 = 0;
 127        params->pagetablelistphys = 0;
 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 kenrel 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        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        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 vidioc_log_status(struct file *file, void *priv)
 734{
 735        return 0;
 736}
 737
 738static int fill_queryctrl(struct saa7164_vbi_params *params,
 739        struct v4l2_queryctrl *c)
 740{
 741        switch (c->id) {
 742        case V4L2_CID_BRIGHTNESS:
 743                return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 127);
 744        case V4L2_CID_CONTRAST:
 745                return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 66);
 746        case V4L2_CID_SATURATION:
 747                return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 62);
 748        case V4L2_CID_HUE:
 749                return v4l2_ctrl_query_fill(c, 0x0, 0xff, 1, 128);
 750        case V4L2_CID_SHARPNESS:
 751                return v4l2_ctrl_query_fill(c, 0x0, 0x0f, 1, 8);
 752        case V4L2_CID_MPEG_AUDIO_MUTE:
 753                return v4l2_ctrl_query_fill(c, 0x0, 0x01, 1, 0);
 754        case V4L2_CID_AUDIO_VOLUME:
 755                return v4l2_ctrl_query_fill(c, -83, 24, 1, 20);
 756        case V4L2_CID_MPEG_STREAM_TYPE:
 757                return v4l2_ctrl_query_fill(c,
 758                        V4L2_MPEG_STREAM_TYPE_MPEG2_PS,
 759                        V4L2_MPEG_STREAM_TYPE_MPEG2_TS,
 760                        1, V4L2_MPEG_STREAM_TYPE_MPEG2_PS);
 761        case V4L2_CID_MPEG_VIDEO_ASPECT:
 762                return v4l2_ctrl_query_fill(c,
 763                        V4L2_MPEG_VIDEO_ASPECT_1x1,
 764                        V4L2_MPEG_VIDEO_ASPECT_221x100,
 765                        1, V4L2_MPEG_VIDEO_ASPECT_4x3);
 766        case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
 767                return v4l2_ctrl_query_fill(c, 1, 255, 1, 15);
 768        case V4L2_CID_MPEG_VIDEO_B_FRAMES:
 769                return v4l2_ctrl_query_fill(c,
 770                        1, 3, 1, 1);
 771        default:
 772                return -EINVAL;
 773        }
 774}
 775
 776static int vidioc_queryctrl(struct file *file, void *priv,
 777        struct v4l2_queryctrl *c)
 778{
 779        struct saa7164_vbi_fh *fh = priv;
 780        struct saa7164_port *port = fh->port;
 781        int i, next;
 782        u32 id = c->id;
 783
 784        memset(c, 0, sizeof(*c));
 785
 786        next = !!(id & V4L2_CTRL_FLAG_NEXT_CTRL);
 787        c->id = id & ~V4L2_CTRL_FLAG_NEXT_CTRL;
 788
 789        for (i = 0; i < ARRAY_SIZE(saa7164_v4l2_ctrls); i++) {
 790                if (next) {
 791                        if (c->id < saa7164_v4l2_ctrls[i])
 792                                c->id = saa7164_v4l2_ctrls[i];
 793                        else
 794                                continue;
 795                }
 796
 797                if (c->id == saa7164_v4l2_ctrls[i])
 798                        return fill_queryctrl(&port->vbi_params, c);
 799
 800                if (c->id < saa7164_v4l2_ctrls[i])
 801                        break;
 802        }
 803
 804        return -EINVAL;
 805}
 806
 807static int saa7164_vbi_stop_port(struct saa7164_port *port)
 808{
 809        struct saa7164_dev *dev = port->dev;
 810        int ret;
 811
 812        ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
 813        if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
 814                printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
 815                        __func__, ret);
 816                ret = -EIO;
 817        } else {
 818                dprintk(DBGLVL_VBI, "%s()    Stopped\n", __func__);
 819                ret = 0;
 820        }
 821
 822        return ret;
 823}
 824
 825static int saa7164_vbi_acquire_port(struct saa7164_port *port)
 826{
 827        struct saa7164_dev *dev = port->dev;
 828        int ret;
 829
 830        ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
 831        if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
 832                printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
 833                        __func__, ret);
 834                ret = -EIO;
 835        } else {
 836                dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__);
 837                ret = 0;
 838        }
 839
 840        return ret;
 841}
 842
 843static int saa7164_vbi_pause_port(struct saa7164_port *port)
 844{
 845        struct saa7164_dev *dev = port->dev;
 846        int ret;
 847
 848        ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
 849        if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
 850                printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
 851                        __func__, ret);
 852                ret = -EIO;
 853        } else {
 854                dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
 855                ret = 0;
 856        }
 857
 858        return ret;
 859}
 860
 861/* Firmware is very windows centric, meaning you have to transition
 862 * the part through AVStream / KS Windows stages, forwards or backwards.
 863 * States are: stopped, acquired (h/w), paused, started.
 864 * We have to leave here will all of the soft buffers on the free list,
 865 * else the cfg_post() func won't have soft buffers to correctly configure.
 866 */
 867static int saa7164_vbi_stop_streaming(struct saa7164_port *port)
 868{
 869        struct saa7164_dev *dev = port->dev;
 870        struct saa7164_buffer *buf;
 871        struct saa7164_user_buffer *ubuf;
 872        struct list_head *c, *n;
 873        int ret;
 874
 875        dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
 876
 877        ret = saa7164_vbi_pause_port(port);
 878        ret = saa7164_vbi_acquire_port(port);
 879        ret = saa7164_vbi_stop_port(port);
 880
 881        dprintk(DBGLVL_VBI, "%s(port=%d) Hardware stopped\n", __func__,
 882                port->nr);
 883
 884        /* Reset the state of any allocated buffer resources */
 885        mutex_lock(&port->dmaqueue_lock);
 886
 887        /* Reset the hard and soft buffer state */
 888        list_for_each_safe(c, n, &port->dmaqueue.list) {
 889                buf = list_entry(c, struct saa7164_buffer, list);
 890                buf->flags = SAA7164_BUFFER_FREE;
 891                buf->pos = 0;
 892        }
 893
 894        list_for_each_safe(c, n, &port->list_buf_used.list) {
 895                ubuf = list_entry(c, struct saa7164_user_buffer, list);
 896                ubuf->pos = 0;
 897                list_move_tail(&ubuf->list, &port->list_buf_free.list);
 898        }
 899
 900        mutex_unlock(&port->dmaqueue_lock);
 901
 902        /* Free any allocated resources */
 903        saa7164_vbi_buffers_dealloc(port);
 904
 905        dprintk(DBGLVL_VBI, "%s(port=%d) Released\n", __func__, port->nr);
 906
 907        return ret;
 908}
 909
 910static int saa7164_vbi_start_streaming(struct saa7164_port *port)
 911{
 912        struct saa7164_dev *dev = port->dev;
 913        int result, ret = 0;
 914
 915        dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
 916
 917        port->done_first_interrupt = 0;
 918
 919        /* allocate all of the PCIe DMA buffer resources on the fly,
 920         * allowing switching between TS and PS payloads without
 921         * requiring a complete driver reload.
 922         */
 923        saa7164_vbi_buffers_alloc(port);
 924
 925        /* Configure the encoder with any cache values */
 926#if 0
 927        saa7164_api_set_encoder(port);
 928        saa7164_api_get_encoder(port);
 929#endif
 930
 931        /* Place the empty buffers on the hardware */
 932        saa7164_buffer_cfg_port(port);
 933
 934        /* Negotiate format */
 935        if (saa7164_api_set_vbi_format(port) != SAA_OK) {
 936                printk(KERN_ERR "%s() No supported VBI format\n", __func__);
 937                ret = -EIO;
 938                goto out;
 939        }
 940
 941        /* Acquire the hardware */
 942        result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
 943        if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
 944                printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
 945                        __func__, result);
 946
 947                ret = -EIO;
 948                goto out;
 949        } else
 950                dprintk(DBGLVL_VBI, "%s()   Acquired\n", __func__);
 951
 952        /* Pause the hardware */
 953        result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
 954        if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
 955                printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
 956                                __func__, result);
 957
 958                /* Stop the hardware, regardless */
 959                result = saa7164_vbi_stop_port(port);
 960                if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
 961                        printk(KERN_ERR "%s() pause/forced stop transition "
 962                                "failed, res = 0x%x\n", __func__, result);
 963                }
 964
 965                ret = -EIO;
 966                goto out;
 967        } else
 968                dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
 969
 970        /* Start the hardware */
 971        result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
 972        if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
 973                printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
 974                                __func__, result);
 975
 976                /* Stop the hardware, regardless */
 977                result = saa7164_vbi_acquire_port(port);
 978                result = saa7164_vbi_stop_port(port);
 979                if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
 980                        printk(KERN_ERR "%s() run/forced stop transition "
 981                                "failed, res = 0x%x\n", __func__, result);
 982                }
 983
 984                ret = -EIO;
 985        } else
 986                dprintk(DBGLVL_VBI, "%s()   Running\n", __func__);
 987
 988out:
 989        return ret;
 990}
 991
 992int saa7164_vbi_fmt(struct file *file, void *priv, struct v4l2_format *f)
 993{
 994        /* ntsc */
 995        f->fmt.vbi.samples_per_line = 1600;
 996        f->fmt.vbi.samples_per_line = 1440;
 997        f->fmt.vbi.sampling_rate = 27000000;
 998        f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
 999        f->fmt.vbi.offset = 0;
1000        f->fmt.vbi.flags = 0;
1001        f->fmt.vbi.start[0] = 10;
1002        f->fmt.vbi.count[0] = 18;
1003        f->fmt.vbi.start[1] = 263 + 10 + 1;
1004        f->fmt.vbi.count[1] = 18;
1005        return 0;
1006}
1007
1008static int fops_open(struct file *file)
1009{
1010        struct saa7164_dev *dev;
1011        struct saa7164_port *port;
1012        struct saa7164_vbi_fh *fh;
1013
1014        port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
1015        if (!port)
1016                return -ENODEV;
1017
1018        dev = port->dev;
1019
1020        dprintk(DBGLVL_VBI, "%s()\n", __func__);
1021
1022        /* allocate + initialize per filehandle data */
1023        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
1024        if (NULL == fh)
1025                return -ENOMEM;
1026
1027        file->private_data = fh;
1028        fh->port = port;
1029
1030        return 0;
1031}
1032
1033static int fops_release(struct file *file)
1034{
1035        struct saa7164_vbi_fh *fh = file->private_data;
1036        struct saa7164_port *port = fh->port;
1037        struct saa7164_dev *dev = port->dev;
1038
1039        dprintk(DBGLVL_VBI, "%s()\n", __func__);
1040
1041        /* Shut device down on last close */
1042        if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
1043                if (atomic_dec_return(&port->v4l_reader_count) == 0) {
1044                        /* stop vbi capture then cancel buffers */
1045                        saa7164_vbi_stop_streaming(port);
1046                }
1047        }
1048
1049        file->private_data = NULL;
1050        kfree(fh);
1051
1052        return 0;
1053}
1054
1055struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
1056{
1057        struct saa7164_user_buffer *ubuf = 0;
1058        struct saa7164_dev *dev = port->dev;
1059        u32 crc;
1060
1061        mutex_lock(&port->dmaqueue_lock);
1062        if (!list_empty(&port->list_buf_used.list)) {
1063                ubuf = list_first_entry(&port->list_buf_used.list,
1064                        struct saa7164_user_buffer, list);
1065
1066                if (crc_checking) {
1067                        crc = crc32(0, ubuf->data, ubuf->actual_size);
1068                        if (crc != ubuf->crc) {
1069                                printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
1070                                        __func__,
1071                                        ubuf, ubuf->crc, crc);
1072                        }
1073                }
1074
1075        }
1076        mutex_unlock(&port->dmaqueue_lock);
1077
1078        dprintk(DBGLVL_VBI, "%s() returns %p\n", __func__, ubuf);
1079
1080        return ubuf;
1081}
1082
1083static ssize_t fops_read(struct file *file, char __user *buffer,
1084        size_t count, loff_t *pos)
1085{
1086        struct saa7164_vbi_fh *fh = file->private_data;
1087        struct saa7164_port *port = fh->port;
1088        struct saa7164_user_buffer *ubuf = NULL;
1089        struct saa7164_dev *dev = port->dev;
1090        int ret = 0;
1091        int rem, cnt;
1092        u8 *p;
1093
1094        port->last_read_msecs_diff = port->last_read_msecs;
1095        port->last_read_msecs = jiffies_to_msecs(jiffies);
1096        port->last_read_msecs_diff = port->last_read_msecs -
1097                port->last_read_msecs_diff;
1098
1099        saa7164_histogram_update(&port->read_interval,
1100                port->last_read_msecs_diff);
1101
1102        if (*pos) {
1103                printk(KERN_ERR "%s() ESPIPE\n", __func__);
1104                return -ESPIPE;
1105        }
1106
1107        if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
1108                if (atomic_inc_return(&port->v4l_reader_count) == 1) {
1109
1110                        if (saa7164_vbi_initialize(port) < 0) {
1111                                printk(KERN_ERR "%s() EINVAL\n", __func__);
1112                                return -EINVAL;
1113                        }
1114
1115                        saa7164_vbi_start_streaming(port);
1116                        msleep(200);
1117                }
1118        }
1119
1120        /* blocking wait for buffer */
1121        if ((file->f_flags & O_NONBLOCK) == 0) {
1122                if (wait_event_interruptible(port->wait_read,
1123                        saa7164_vbi_next_buf(port))) {
1124                                printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
1125                                return -ERESTARTSYS;
1126                }
1127        }
1128
1129        /* Pull the first buffer from the used list */
1130        ubuf = saa7164_vbi_next_buf(port);
1131
1132        while ((count > 0) && ubuf) {
1133
1134                /* set remaining bytes to copy */
1135                rem = ubuf->actual_size - ubuf->pos;
1136                cnt = rem > count ? count : rem;
1137
1138                p = ubuf->data + ubuf->pos;
1139
1140                dprintk(DBGLVL_VBI,
1141                        "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
1142                        __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
1143
1144                if (copy_to_user(buffer, p, cnt)) {
1145                        printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
1146                        if (!ret) {
1147                                printk(KERN_ERR "%s() EFAULT\n", __func__);
1148                                ret = -EFAULT;
1149                        }
1150                        goto err;
1151                }
1152
1153                ubuf->pos += cnt;
1154                count -= cnt;
1155                buffer += cnt;
1156                ret += cnt;
1157
1158                if (ubuf->pos > ubuf->actual_size)
1159                        printk(KERN_ERR "read() pos > actual, huh?\n");
1160
1161                if (ubuf->pos == ubuf->actual_size) {
1162
1163                        /* finished with current buffer, take next buffer */
1164
1165                        /* Requeue the buffer on the free list */
1166                        ubuf->pos = 0;
1167
1168                        mutex_lock(&port->dmaqueue_lock);
1169                        list_move_tail(&ubuf->list, &port->list_buf_free.list);
1170                        mutex_unlock(&port->dmaqueue_lock);
1171
1172                        /* Dequeue next */
1173                        if ((file->f_flags & O_NONBLOCK) == 0) {
1174                                if (wait_event_interruptible(port->wait_read,
1175                                        saa7164_vbi_next_buf(port))) {
1176                                                break;
1177                                }
1178                        }
1179                        ubuf = saa7164_vbi_next_buf(port);
1180                }
1181        }
1182err:
1183        if (!ret && !ubuf) {
1184                printk(KERN_ERR "%s() EAGAIN\n", __func__);
1185                ret = -EAGAIN;
1186        }
1187
1188        return ret;
1189}
1190
1191static unsigned int fops_poll(struct file *file, poll_table *wait)
1192{
1193        struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data;
1194        struct saa7164_port *port = fh->port;
1195        struct saa7164_user_buffer *ubuf;
1196        unsigned int mask = 0;
1197
1198        port->last_poll_msecs_diff = port->last_poll_msecs;
1199        port->last_poll_msecs = jiffies_to_msecs(jiffies);
1200        port->last_poll_msecs_diff = port->last_poll_msecs -
1201                port->last_poll_msecs_diff;
1202
1203        saa7164_histogram_update(&port->poll_interval,
1204                port->last_poll_msecs_diff);
1205
1206        if (!video_is_registered(port->v4l_device))
1207                return -EIO;
1208
1209        if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
1210                if (atomic_inc_return(&port->v4l_reader_count) == 1) {
1211                        if (saa7164_vbi_initialize(port) < 0)
1212                                return -EINVAL;
1213                        saa7164_vbi_start_streaming(port);
1214                        msleep(200);
1215                }
1216        }
1217
1218        /* blocking wait for buffer */
1219        if ((file->f_flags & O_NONBLOCK) == 0) {
1220                if (wait_event_interruptible(port->wait_read,
1221                        saa7164_vbi_next_buf(port))) {
1222                                return -ERESTARTSYS;
1223                }
1224        }
1225
1226        /* Pull the first buffer from the used list */
1227        ubuf = list_first_entry(&port->list_buf_used.list,
1228                struct saa7164_user_buffer, list);
1229
1230        if (ubuf)
1231                mask |= POLLIN | POLLRDNORM;
1232
1233        return mask;
1234}
1235static const struct v4l2_file_operations vbi_fops = {
1236        .owner          = THIS_MODULE,
1237        .open           = fops_open,
1238        .release        = fops_release,
1239        .read           = fops_read,
1240        .poll           = fops_poll,
1241        .unlocked_ioctl = video_ioctl2,
1242};
1243
1244static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
1245        .vidioc_s_std            = vidioc_s_std,
1246        .vidioc_enum_input       = vidioc_enum_input,
1247        .vidioc_g_input          = vidioc_g_input,
1248        .vidioc_s_input          = vidioc_s_input,
1249        .vidioc_g_tuner          = vidioc_g_tuner,
1250        .vidioc_s_tuner          = vidioc_s_tuner,
1251        .vidioc_g_frequency      = vidioc_g_frequency,
1252        .vidioc_s_frequency      = vidioc_s_frequency,
1253        .vidioc_s_ctrl           = vidioc_s_ctrl,
1254        .vidioc_g_ctrl           = vidioc_g_ctrl,
1255        .vidioc_querycap         = vidioc_querycap,
1256        .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
1257        .vidioc_g_fmt_vid_cap    = vidioc_g_fmt_vid_cap,
1258        .vidioc_try_fmt_vid_cap  = vidioc_try_fmt_vid_cap,
1259        .vidioc_s_fmt_vid_cap    = vidioc_s_fmt_vid_cap,
1260        .vidioc_g_ext_ctrls      = vidioc_g_ext_ctrls,
1261        .vidioc_s_ext_ctrls      = vidioc_s_ext_ctrls,
1262        .vidioc_try_ext_ctrls    = vidioc_try_ext_ctrls,
1263        .vidioc_log_status       = vidioc_log_status,
1264        .vidioc_queryctrl        = vidioc_queryctrl,
1265#if 0
1266        .vidioc_g_chip_ident     = saa7164_g_chip_ident,
1267#endif
1268#ifdef CONFIG_VIDEO_ADV_DEBUG
1269#if 0
1270        .vidioc_g_register       = saa7164_g_register,
1271        .vidioc_s_register       = saa7164_s_register,
1272#endif
1273#endif
1274        .vidioc_g_fmt_vbi_cap    = saa7164_vbi_fmt,
1275        .vidioc_try_fmt_vbi_cap  = saa7164_vbi_fmt,
1276        .vidioc_s_fmt_vbi_cap    = saa7164_vbi_fmt,
1277};
1278
1279static struct video_device saa7164_vbi_template = {
1280        .name          = "saa7164",
1281        .fops          = &vbi_fops,
1282        .ioctl_ops     = &vbi_ioctl_ops,
1283        .minor         = -1,
1284        .tvnorms       = SAA7164_NORMS,
1285        .current_norm  = V4L2_STD_NTSC_M,
1286};
1287
1288static struct video_device *saa7164_vbi_alloc(
1289        struct saa7164_port *port,
1290        struct pci_dev *pci,
1291        struct video_device *template,
1292        char *type)
1293{
1294        struct video_device *vfd;
1295        struct saa7164_dev *dev = port->dev;
1296
1297        dprintk(DBGLVL_VBI, "%s()\n", __func__);
1298
1299        vfd = video_device_alloc();
1300        if (NULL == vfd)
1301                return NULL;
1302
1303        *vfd = *template;
1304        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
1305                type, saa7164_boards[dev->board].name);
1306
1307        vfd->parent  = &pci->dev;
1308        vfd->release = video_device_release;
1309        return vfd;
1310}
1311
1312int saa7164_vbi_register(struct saa7164_port *port)
1313{
1314        struct saa7164_dev *dev = port->dev;
1315        int result = -ENODEV;
1316
1317        dprintk(DBGLVL_VBI, "%s()\n", __func__);
1318
1319        if (port->type != SAA7164_MPEG_VBI)
1320                BUG();
1321
1322        /* Sanity check that the PCI configuration space is active */
1323        if (port->hwcfg.BARLocation == 0) {
1324                printk(KERN_ERR "%s() failed "
1325                       "(errno = %d), NO PCI configuration\n",
1326                        __func__, result);
1327                result = -ENOMEM;
1328                goto failed;
1329        }
1330
1331        /* Establish VBI defaults here */
1332
1333        /* Allocate and register the video device node */
1334        port->v4l_device = saa7164_vbi_alloc(port,
1335                dev->pci, &saa7164_vbi_template, "vbi");
1336
1337        if (port->v4l_device == NULL) {
1338                printk(KERN_INFO "%s: can't allocate vbi device\n",
1339                        dev->name);
1340                result = -ENOMEM;
1341                goto failed;
1342        }
1343
1344        video_set_drvdata(port->v4l_device, port);
1345        result = video_register_device(port->v4l_device,
1346                VFL_TYPE_VBI, -1);
1347        if (result < 0) {
1348                printk(KERN_INFO "%s: can't register vbi device\n",
1349                        dev->name);
1350                /* TODO: We're going to leak here if we don't dealloc
1351                 The buffers above. The unreg function can't deal wit it.
1352                */
1353                goto failed;
1354        }
1355
1356        printk(KERN_INFO "%s: registered device vbi%d [vbi]\n",
1357                dev->name, port->v4l_device->num);
1358
1359        /* Configure the hardware defaults */
1360
1361        result = 0;
1362failed:
1363        return result;
1364}
1365
1366void saa7164_vbi_unregister(struct saa7164_port *port)
1367{
1368        struct saa7164_dev *dev = port->dev;
1369
1370        dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
1371
1372        if (port->type != SAA7164_MPEG_VBI)
1373                BUG();
1374
1375        if (port->v4l_device) {
1376                if (port->v4l_device->minor != -1)
1377                        video_unregister_device(port->v4l_device);
1378                else
1379                        video_device_release(port->v4l_device);
1380
1381                port->v4l_device = NULL;
1382        }
1383
1384}
1385