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