linux/drivers/media/pci/saa7164/saa7164-vbi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Driver for the NXP SAA7164 PCIe bridge
   4 *
   5 *  Copyright (c) 2010-2015 Steven Toth <stoth@kernellabs.com>
   6 */
   7
   8#include "saa7164.h"
   9
  10/* Take the encoder configuration from the port struct and
  11 * flush it to the hardware.
  12 */
  13static void saa7164_vbi_configure(struct saa7164_port *port)
  14{
  15        struct saa7164_dev *dev = port->dev;
  16        dprintk(DBGLVL_VBI, "%s()\n", __func__);
  17
  18        port->vbi_params.width = port->enc_port->width;
  19        port->vbi_params.height = port->enc_port->height;
  20        port->vbi_params.is_50hz =
  21                (port->enc_port->encodernorm.id & V4L2_STD_625_50) != 0;
  22
  23        /* Set up the DIF (enable it) for analog mode by default */
  24        saa7164_api_initialize_dif(port);
  25        dprintk(DBGLVL_VBI, "%s() ends\n", __func__);
  26}
  27
  28static int saa7164_vbi_buffers_dealloc(struct saa7164_port *port)
  29{
  30        struct list_head *c, *n, *p, *q, *l, *v;
  31        struct saa7164_dev *dev = port->dev;
  32        struct saa7164_buffer *buf;
  33        struct saa7164_user_buffer *ubuf;
  34
  35        /* Remove any allocated buffers */
  36        mutex_lock(&port->dmaqueue_lock);
  37
  38        dprintk(DBGLVL_VBI, "%s(port=%d) dmaqueue\n", __func__, port->nr);
  39        list_for_each_safe(c, n, &port->dmaqueue.list) {
  40                buf = list_entry(c, struct saa7164_buffer, list);
  41                list_del(c);
  42                saa7164_buffer_dealloc(buf);
  43        }
  44
  45        dprintk(DBGLVL_VBI, "%s(port=%d) used\n", __func__, port->nr);
  46        list_for_each_safe(p, q, &port->list_buf_used.list) {
  47                ubuf = list_entry(p, struct saa7164_user_buffer, list);
  48                list_del(p);
  49                saa7164_buffer_dealloc_user(ubuf);
  50        }
  51
  52        dprintk(DBGLVL_VBI, "%s(port=%d) free\n", __func__, port->nr);
  53        list_for_each_safe(l, v, &port->list_buf_free.list) {
  54                ubuf = list_entry(l, struct saa7164_user_buffer, list);
  55                list_del(l);
  56                saa7164_buffer_dealloc_user(ubuf);
  57        }
  58
  59        mutex_unlock(&port->dmaqueue_lock);
  60        dprintk(DBGLVL_VBI, "%s(port=%d) done\n", __func__, port->nr);
  61
  62        return 0;
  63}
  64
  65/* Dynamic buffer switch at vbi start time */
  66static int saa7164_vbi_buffers_alloc(struct saa7164_port *port)
  67{
  68        struct saa7164_dev *dev = port->dev;
  69        struct saa7164_buffer *buf;
  70        struct saa7164_user_buffer *ubuf;
  71        struct tmHWStreamParameters *params = &port->hw_streamingparams;
  72        int result = -ENODEV, i;
  73        int len = 0;
  74
  75        dprintk(DBGLVL_VBI, "%s()\n", __func__);
  76
  77        /* TODO: NTSC SPECIFIC */
  78        /* Init and establish defaults */
  79        params->samplesperline = 1440;
  80        params->numberoflines = 12;
  81        params->numberoflines = 18;
  82        params->pitch = 1600;
  83        params->pitch = 1440;
  84        params->numpagetables = 2 +
  85                ((params->numberoflines * params->pitch) / PAGE_SIZE);
  86        params->bitspersample = 8;
  87        params->linethreshold = 0;
  88        params->pagetablelistvirt = NULL;
  89        params->pagetablelistphys = NULL;
  90        params->numpagetableentries = port->hwcfg.buffercount;
  91
  92        /* Allocate the PCI resources, buffers (hard) */
  93        for (i = 0; i < port->hwcfg.buffercount; i++) {
  94                buf = saa7164_buffer_alloc(port,
  95                        params->numberoflines *
  96                        params->pitch);
  97
  98                if (!buf) {
  99                        printk(KERN_ERR "%s() failed (errno = %d), unable to allocate buffer\n",
 100                                __func__, result);
 101                        result = -ENOMEM;
 102                        goto failed;
 103                } else {
 104
 105                        mutex_lock(&port->dmaqueue_lock);
 106                        list_add_tail(&buf->list, &port->dmaqueue.list);
 107                        mutex_unlock(&port->dmaqueue_lock);
 108
 109                }
 110        }
 111
 112        /* Allocate some kernel buffers for copying
 113         * to userpsace.
 114         */
 115        len = params->numberoflines * params->pitch;
 116
 117        if (vbi_buffers < 16)
 118                vbi_buffers = 16;
 119        if (vbi_buffers > 512)
 120                vbi_buffers = 512;
 121
 122        for (i = 0; i < vbi_buffers; i++) {
 123
 124                ubuf = saa7164_buffer_alloc_user(dev, len);
 125                if (ubuf) {
 126                        mutex_lock(&port->dmaqueue_lock);
 127                        list_add_tail(&ubuf->list, &port->list_buf_free.list);
 128                        mutex_unlock(&port->dmaqueue_lock);
 129                }
 130
 131        }
 132
 133        result = 0;
 134
 135failed:
 136        return result;
 137}
 138
 139
 140static int saa7164_vbi_initialize(struct saa7164_port *port)
 141{
 142        saa7164_vbi_configure(port);
 143        return 0;
 144}
 145
 146/* -- V4L2 --------------------------------------------------------- */
 147static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 148{
 149        struct saa7164_vbi_fh *fh = file->private_data;
 150
 151        return saa7164_s_std(fh->port->enc_port, id);
 152}
 153
 154static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
 155{
 156        struct saa7164_encoder_fh *fh = file->private_data;
 157
 158        return saa7164_g_std(fh->port->enc_port, id);
 159}
 160
 161static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
 162{
 163        struct saa7164_vbi_fh *fh = file->private_data;
 164
 165        return saa7164_g_input(fh->port->enc_port, i);
 166}
 167
 168static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
 169{
 170        struct saa7164_vbi_fh *fh = file->private_data;
 171
 172        return saa7164_s_input(fh->port->enc_port, i);
 173}
 174
 175static int vidioc_g_frequency(struct file *file, void *priv,
 176        struct v4l2_frequency *f)
 177{
 178        struct saa7164_vbi_fh *fh = file->private_data;
 179
 180        return saa7164_g_frequency(fh->port->enc_port, f);
 181}
 182
 183static int vidioc_s_frequency(struct file *file, void *priv,
 184        const struct v4l2_frequency *f)
 185{
 186        struct saa7164_vbi_fh *fh = file->private_data;
 187        int ret = saa7164_s_frequency(fh->port->enc_port, f);
 188
 189        if (ret == 0)
 190                saa7164_vbi_initialize(fh->port);
 191        return ret;
 192}
 193
 194static int vidioc_querycap(struct file *file, void  *priv,
 195        struct v4l2_capability *cap)
 196{
 197        struct saa7164_vbi_fh *fh = file->private_data;
 198        struct saa7164_port *port = fh->port;
 199        struct saa7164_dev *dev = port->dev;
 200
 201        strscpy(cap->driver, dev->name, sizeof(cap->driver));
 202        strscpy(cap->card, saa7164_boards[dev->board].name,
 203                sizeof(cap->card));
 204        sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
 205        cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
 206                            V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE |
 207                            V4L2_CAP_DEVICE_CAPS;
 208        return 0;
 209}
 210
 211static int saa7164_vbi_stop_port(struct saa7164_port *port)
 212{
 213        struct saa7164_dev *dev = port->dev;
 214        int ret;
 215
 216        ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP);
 217        if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
 218                printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n",
 219                        __func__, ret);
 220                ret = -EIO;
 221        } else {
 222                dprintk(DBGLVL_VBI, "%s()    Stopped\n", __func__);
 223                ret = 0;
 224        }
 225
 226        return ret;
 227}
 228
 229static int saa7164_vbi_acquire_port(struct saa7164_port *port)
 230{
 231        struct saa7164_dev *dev = port->dev;
 232        int ret;
 233
 234        ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
 235        if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
 236                printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n",
 237                        __func__, ret);
 238                ret = -EIO;
 239        } else {
 240                dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__);
 241                ret = 0;
 242        }
 243
 244        return ret;
 245}
 246
 247static int saa7164_vbi_pause_port(struct saa7164_port *port)
 248{
 249        struct saa7164_dev *dev = port->dev;
 250        int ret;
 251
 252        ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
 253        if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) {
 254                printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n",
 255                        __func__, ret);
 256                ret = -EIO;
 257        } else {
 258                dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
 259                ret = 0;
 260        }
 261
 262        return ret;
 263}
 264
 265/* Firmware is very windows centric, meaning you have to transition
 266 * the part through AVStream / KS Windows stages, forwards or backwards.
 267 * States are: stopped, acquired (h/w), paused, started.
 268 * We have to leave here will all of the soft buffers on the free list,
 269 * else the cfg_post() func won't have soft buffers to correctly configure.
 270 */
 271static int saa7164_vbi_stop_streaming(struct saa7164_port *port)
 272{
 273        struct saa7164_dev *dev = port->dev;
 274        struct saa7164_buffer *buf;
 275        struct saa7164_user_buffer *ubuf;
 276        struct list_head *c, *n;
 277        int ret;
 278
 279        dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
 280
 281        ret = saa7164_vbi_pause_port(port);
 282        ret = saa7164_vbi_acquire_port(port);
 283        ret = saa7164_vbi_stop_port(port);
 284
 285        dprintk(DBGLVL_VBI, "%s(port=%d) Hardware stopped\n", __func__,
 286                port->nr);
 287
 288        /* Reset the state of any allocated buffer resources */
 289        mutex_lock(&port->dmaqueue_lock);
 290
 291        /* Reset the hard and soft buffer state */
 292        list_for_each_safe(c, n, &port->dmaqueue.list) {
 293                buf = list_entry(c, struct saa7164_buffer, list);
 294                buf->flags = SAA7164_BUFFER_FREE;
 295                buf->pos = 0;
 296        }
 297
 298        list_for_each_safe(c, n, &port->list_buf_used.list) {
 299                ubuf = list_entry(c, struct saa7164_user_buffer, list);
 300                ubuf->pos = 0;
 301                list_move_tail(&ubuf->list, &port->list_buf_free.list);
 302        }
 303
 304        mutex_unlock(&port->dmaqueue_lock);
 305
 306        /* Free any allocated resources */
 307        saa7164_vbi_buffers_dealloc(port);
 308
 309        dprintk(DBGLVL_VBI, "%s(port=%d) Released\n", __func__, port->nr);
 310
 311        return ret;
 312}
 313
 314static int saa7164_vbi_start_streaming(struct saa7164_port *port)
 315{
 316        struct saa7164_dev *dev = port->dev;
 317        int result, ret = 0;
 318
 319        dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
 320
 321        port->done_first_interrupt = 0;
 322
 323        /* allocate all of the PCIe DMA buffer resources on the fly,
 324         * allowing switching between TS and PS payloads without
 325         * requiring a complete driver reload.
 326         */
 327        saa7164_vbi_buffers_alloc(port);
 328
 329        /* Configure the encoder with any cache values */
 330#if 0
 331        saa7164_api_set_encoder(port);
 332        saa7164_api_get_encoder(port);
 333#endif
 334
 335        /* Place the empty buffers on the hardware */
 336        saa7164_buffer_cfg_port(port);
 337
 338        /* Negotiate format */
 339        if (saa7164_api_set_vbi_format(port) != SAA_OK) {
 340                printk(KERN_ERR "%s() No supported VBI format\n", __func__);
 341                ret = -EIO;
 342                goto out;
 343        }
 344
 345        /* Acquire the hardware */
 346        result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE);
 347        if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
 348                printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n",
 349                        __func__, result);
 350
 351                ret = -EIO;
 352                goto out;
 353        } else
 354                dprintk(DBGLVL_VBI, "%s()   Acquired\n", __func__);
 355
 356        /* Pause the hardware */
 357        result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE);
 358        if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
 359                printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n",
 360                                __func__, result);
 361
 362                /* Stop the hardware, regardless */
 363                result = saa7164_vbi_stop_port(port);
 364                if (result != SAA_OK) {
 365                        printk(KERN_ERR "%s() pause/forced stop transition failed, res = 0x%x\n",
 366                               __func__, result);
 367                }
 368
 369                ret = -EIO;
 370                goto out;
 371        } else
 372                dprintk(DBGLVL_VBI, "%s()   Paused\n", __func__);
 373
 374        /* Start the hardware */
 375        result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN);
 376        if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) {
 377                printk(KERN_ERR "%s() run transition failed, result = 0x%x\n",
 378                                __func__, result);
 379
 380                /* Stop the hardware, regardless */
 381                result = saa7164_vbi_acquire_port(port);
 382                result = saa7164_vbi_stop_port(port);
 383                if (result != SAA_OK) {
 384                        printk(KERN_ERR "%s() run/forced stop transition failed, res = 0x%x\n",
 385                               __func__, result);
 386                }
 387
 388                ret = -EIO;
 389        } else
 390                dprintk(DBGLVL_VBI, "%s()   Running\n", __func__);
 391
 392out:
 393        return ret;
 394}
 395
 396static int saa7164_vbi_fmt(struct file *file, void *priv,
 397                           struct v4l2_format *f)
 398{
 399        /* ntsc */
 400        f->fmt.vbi.samples_per_line = 1440;
 401        f->fmt.vbi.sampling_rate = 27000000;
 402        f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
 403        f->fmt.vbi.offset = 0;
 404        f->fmt.vbi.flags = 0;
 405        f->fmt.vbi.start[0] = 10;
 406        f->fmt.vbi.count[0] = 18;
 407        f->fmt.vbi.start[1] = 263 + 10 + 1;
 408        f->fmt.vbi.count[1] = 18;
 409        memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved));
 410        return 0;
 411}
 412
 413static int fops_open(struct file *file)
 414{
 415        struct saa7164_dev *dev;
 416        struct saa7164_port *port;
 417        struct saa7164_vbi_fh *fh;
 418
 419        port = (struct saa7164_port *)video_get_drvdata(video_devdata(file));
 420        if (!port)
 421                return -ENODEV;
 422
 423        dev = port->dev;
 424
 425        dprintk(DBGLVL_VBI, "%s()\n", __func__);
 426
 427        /* allocate + initialize per filehandle data */
 428        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
 429        if (NULL == fh)
 430                return -ENOMEM;
 431
 432        fh->port = port;
 433        v4l2_fh_init(&fh->fh, video_devdata(file));
 434        v4l2_fh_add(&fh->fh);
 435        file->private_data = fh;
 436
 437        return 0;
 438}
 439
 440static int fops_release(struct file *file)
 441{
 442        struct saa7164_vbi_fh *fh = file->private_data;
 443        struct saa7164_port *port = fh->port;
 444        struct saa7164_dev *dev = port->dev;
 445
 446        dprintk(DBGLVL_VBI, "%s()\n", __func__);
 447
 448        /* Shut device down on last close */
 449        if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
 450                if (atomic_dec_return(&port->v4l_reader_count) == 0) {
 451                        /* stop vbi capture then cancel buffers */
 452                        saa7164_vbi_stop_streaming(port);
 453                }
 454        }
 455
 456        v4l2_fh_del(&fh->fh);
 457        v4l2_fh_exit(&fh->fh);
 458        kfree(fh);
 459
 460        return 0;
 461}
 462
 463static struct
 464saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
 465{
 466        struct saa7164_user_buffer *ubuf = NULL;
 467        struct saa7164_dev *dev = port->dev;
 468        u32 crc;
 469
 470        mutex_lock(&port->dmaqueue_lock);
 471        if (!list_empty(&port->list_buf_used.list)) {
 472                ubuf = list_first_entry(&port->list_buf_used.list,
 473                        struct saa7164_user_buffer, list);
 474
 475                if (crc_checking) {
 476                        crc = crc32(0, ubuf->data, ubuf->actual_size);
 477                        if (crc != ubuf->crc) {
 478                                printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n",
 479                                        __func__,
 480                                        ubuf, ubuf->crc, crc);
 481                        }
 482                }
 483
 484        }
 485        mutex_unlock(&port->dmaqueue_lock);
 486
 487        dprintk(DBGLVL_VBI, "%s() returns %p\n", __func__, ubuf);
 488
 489        return ubuf;
 490}
 491
 492static ssize_t fops_read(struct file *file, char __user *buffer,
 493        size_t count, loff_t *pos)
 494{
 495        struct saa7164_vbi_fh *fh = file->private_data;
 496        struct saa7164_port *port = fh->port;
 497        struct saa7164_user_buffer *ubuf = NULL;
 498        struct saa7164_dev *dev = port->dev;
 499        int ret = 0;
 500        int rem, cnt;
 501        u8 *p;
 502
 503        port->last_read_msecs_diff = port->last_read_msecs;
 504        port->last_read_msecs = jiffies_to_msecs(jiffies);
 505        port->last_read_msecs_diff = port->last_read_msecs -
 506                port->last_read_msecs_diff;
 507
 508        saa7164_histogram_update(&port->read_interval,
 509                port->last_read_msecs_diff);
 510
 511        if (*pos) {
 512                printk(KERN_ERR "%s() ESPIPE\n", __func__);
 513                return -ESPIPE;
 514        }
 515
 516        if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
 517                if (atomic_inc_return(&port->v4l_reader_count) == 1) {
 518
 519                        if (saa7164_vbi_initialize(port) < 0) {
 520                                printk(KERN_ERR "%s() EINVAL\n", __func__);
 521                                return -EINVAL;
 522                        }
 523
 524                        saa7164_vbi_start_streaming(port);
 525                        msleep(200);
 526                }
 527        }
 528
 529        /* blocking wait for buffer */
 530        if ((file->f_flags & O_NONBLOCK) == 0) {
 531                if (wait_event_interruptible(port->wait_read,
 532                        saa7164_vbi_next_buf(port))) {
 533                                printk(KERN_ERR "%s() ERESTARTSYS\n", __func__);
 534                                return -ERESTARTSYS;
 535                }
 536        }
 537
 538        /* Pull the first buffer from the used list */
 539        ubuf = saa7164_vbi_next_buf(port);
 540
 541        while ((count > 0) && ubuf) {
 542
 543                /* set remaining bytes to copy */
 544                rem = ubuf->actual_size - ubuf->pos;
 545                cnt = rem > count ? count : rem;
 546
 547                p = ubuf->data + ubuf->pos;
 548
 549                dprintk(DBGLVL_VBI,
 550                        "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n",
 551                        __func__, (int)count, cnt, rem, ubuf, ubuf->pos);
 552
 553                if (copy_to_user(buffer, p, cnt)) {
 554                        printk(KERN_ERR "%s() copy_to_user failed\n", __func__);
 555                        if (!ret) {
 556                                printk(KERN_ERR "%s() EFAULT\n", __func__);
 557                                ret = -EFAULT;
 558                        }
 559                        goto err;
 560                }
 561
 562                ubuf->pos += cnt;
 563                count -= cnt;
 564                buffer += cnt;
 565                ret += cnt;
 566
 567                if (ubuf->pos > ubuf->actual_size)
 568                        printk(KERN_ERR "read() pos > actual, huh?\n");
 569
 570                if (ubuf->pos == ubuf->actual_size) {
 571
 572                        /* finished with current buffer, take next buffer */
 573
 574                        /* Requeue the buffer on the free list */
 575                        ubuf->pos = 0;
 576
 577                        mutex_lock(&port->dmaqueue_lock);
 578                        list_move_tail(&ubuf->list, &port->list_buf_free.list);
 579                        mutex_unlock(&port->dmaqueue_lock);
 580
 581                        /* Dequeue next */
 582                        if ((file->f_flags & O_NONBLOCK) == 0) {
 583                                if (wait_event_interruptible(port->wait_read,
 584                                        saa7164_vbi_next_buf(port))) {
 585                                                break;
 586                                }
 587                        }
 588                        ubuf = saa7164_vbi_next_buf(port);
 589                }
 590        }
 591err:
 592        if (!ret && !ubuf) {
 593                printk(KERN_ERR "%s() EAGAIN\n", __func__);
 594                ret = -EAGAIN;
 595        }
 596
 597        return ret;
 598}
 599
 600static __poll_t fops_poll(struct file *file, poll_table *wait)
 601{
 602        struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data;
 603        struct saa7164_port *port = fh->port;
 604        __poll_t mask = 0;
 605
 606        port->last_poll_msecs_diff = port->last_poll_msecs;
 607        port->last_poll_msecs = jiffies_to_msecs(jiffies);
 608        port->last_poll_msecs_diff = port->last_poll_msecs -
 609                port->last_poll_msecs_diff;
 610
 611        saa7164_histogram_update(&port->poll_interval,
 612                port->last_poll_msecs_diff);
 613
 614        if (!video_is_registered(port->v4l_device))
 615                return EPOLLERR;
 616
 617        if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
 618                if (atomic_inc_return(&port->v4l_reader_count) == 1) {
 619                        if (saa7164_vbi_initialize(port) < 0)
 620                                return EPOLLERR;
 621                        saa7164_vbi_start_streaming(port);
 622                        msleep(200);
 623                }
 624        }
 625
 626        /* blocking wait for buffer */
 627        if ((file->f_flags & O_NONBLOCK) == 0) {
 628                if (wait_event_interruptible(port->wait_read,
 629                        saa7164_vbi_next_buf(port))) {
 630                                return EPOLLERR;
 631                }
 632        }
 633
 634        /* Pull the first buffer from the used list */
 635        if (!list_empty(&port->list_buf_used.list))
 636                mask |= EPOLLIN | EPOLLRDNORM;
 637
 638        return mask;
 639}
 640static const struct v4l2_file_operations vbi_fops = {
 641        .owner          = THIS_MODULE,
 642        .open           = fops_open,
 643        .release        = fops_release,
 644        .read           = fops_read,
 645        .poll           = fops_poll,
 646        .unlocked_ioctl = video_ioctl2,
 647};
 648
 649static const struct v4l2_ioctl_ops vbi_ioctl_ops = {
 650        .vidioc_s_std            = vidioc_s_std,
 651        .vidioc_g_std            = vidioc_g_std,
 652        .vidioc_enum_input       = saa7164_enum_input,
 653        .vidioc_g_input          = vidioc_g_input,
 654        .vidioc_s_input          = vidioc_s_input,
 655        .vidioc_g_tuner          = saa7164_g_tuner,
 656        .vidioc_s_tuner          = saa7164_s_tuner,
 657        .vidioc_g_frequency      = vidioc_g_frequency,
 658        .vidioc_s_frequency      = vidioc_s_frequency,
 659        .vidioc_querycap         = vidioc_querycap,
 660        .vidioc_g_fmt_vbi_cap    = saa7164_vbi_fmt,
 661        .vidioc_try_fmt_vbi_cap  = saa7164_vbi_fmt,
 662        .vidioc_s_fmt_vbi_cap    = saa7164_vbi_fmt,
 663};
 664
 665static struct video_device saa7164_vbi_template = {
 666        .name          = "saa7164",
 667        .fops          = &vbi_fops,
 668        .ioctl_ops     = &vbi_ioctl_ops,
 669        .minor         = -1,
 670        .tvnorms       = SAA7164_NORMS,
 671        .device_caps   = V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE |
 672                         V4L2_CAP_TUNER,
 673};
 674
 675static struct video_device *saa7164_vbi_alloc(
 676        struct saa7164_port *port,
 677        struct pci_dev *pci,
 678        struct video_device *template,
 679        char *type)
 680{
 681        struct video_device *vfd;
 682        struct saa7164_dev *dev = port->dev;
 683
 684        dprintk(DBGLVL_VBI, "%s()\n", __func__);
 685
 686        vfd = video_device_alloc();
 687        if (NULL == vfd)
 688                return NULL;
 689
 690        *vfd = *template;
 691        snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
 692                type, saa7164_boards[dev->board].name);
 693
 694        vfd->v4l2_dev  = &dev->v4l2_dev;
 695        vfd->release = video_device_release;
 696        return vfd;
 697}
 698
 699int saa7164_vbi_register(struct saa7164_port *port)
 700{
 701        struct saa7164_dev *dev = port->dev;
 702        int result = -ENODEV;
 703
 704        dprintk(DBGLVL_VBI, "%s()\n", __func__);
 705
 706        if (port->type != SAA7164_MPEG_VBI)
 707                BUG();
 708
 709        /* Sanity check that the PCI configuration space is active */
 710        if (port->hwcfg.BARLocation == 0) {
 711                printk(KERN_ERR "%s() failed (errno = %d), NO PCI configuration\n",
 712                        __func__, result);
 713                result = -ENOMEM;
 714                goto failed;
 715        }
 716
 717        /* Establish VBI defaults here */
 718
 719        /* Allocate and register the video device node */
 720        port->v4l_device = saa7164_vbi_alloc(port,
 721                dev->pci, &saa7164_vbi_template, "vbi");
 722
 723        if (!port->v4l_device) {
 724                printk(KERN_INFO "%s: can't allocate vbi device\n",
 725                        dev->name);
 726                result = -ENOMEM;
 727                goto failed;
 728        }
 729
 730        port->enc_port = &dev->ports[port->nr - 2];
 731        video_set_drvdata(port->v4l_device, port);
 732        result = video_register_device(port->v4l_device,
 733                VFL_TYPE_VBI, -1);
 734        if (result < 0) {
 735                printk(KERN_INFO "%s: can't register vbi device\n",
 736                        dev->name);
 737                /* TODO: We're going to leak here if we don't dealloc
 738                 The buffers above. The unreg function can't deal wit it.
 739                */
 740                goto failed;
 741        }
 742
 743        printk(KERN_INFO "%s: registered device vbi%d [vbi]\n",
 744                dev->name, port->v4l_device->num);
 745
 746        /* Configure the hardware defaults */
 747
 748        result = 0;
 749failed:
 750        return result;
 751}
 752
 753void saa7164_vbi_unregister(struct saa7164_port *port)
 754{
 755        struct saa7164_dev *dev = port->dev;
 756
 757        dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr);
 758
 759        if (port->type != SAA7164_MPEG_VBI)
 760                BUG();
 761
 762        if (port->v4l_device) {
 763                if (port->v4l_device->minor != -1)
 764                        video_unregister_device(port->v4l_device);
 765                else
 766                        video_device_release(port->v4l_device);
 767
 768                port->v4l_device = NULL;
 769        }
 770
 771}
 772