saa7164-vbi.c (19716B)
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 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | 205 V4L2_CAP_TUNER | V4L2_CAP_VBI_CAPTURE | 206 V4L2_CAP_DEVICE_CAPS; 207 return 0; 208} 209 210static int saa7164_vbi_stop_port(struct saa7164_port *port) 211{ 212 struct saa7164_dev *dev = port->dev; 213 int ret; 214 215 ret = saa7164_api_transition_port(port, SAA_DMASTATE_STOP); 216 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) { 217 printk(KERN_ERR "%s() stop transition failed, ret = 0x%x\n", 218 __func__, ret); 219 ret = -EIO; 220 } else { 221 dprintk(DBGLVL_VBI, "%s() Stopped\n", __func__); 222 ret = 0; 223 } 224 225 return ret; 226} 227 228static int saa7164_vbi_acquire_port(struct saa7164_port *port) 229{ 230 struct saa7164_dev *dev = port->dev; 231 int ret; 232 233 ret = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE); 234 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) { 235 printk(KERN_ERR "%s() acquire transition failed, ret = 0x%x\n", 236 __func__, ret); 237 ret = -EIO; 238 } else { 239 dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__); 240 ret = 0; 241 } 242 243 return ret; 244} 245 246static int saa7164_vbi_pause_port(struct saa7164_port *port) 247{ 248 struct saa7164_dev *dev = port->dev; 249 int ret; 250 251 ret = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE); 252 if ((ret != SAA_OK) && (ret != SAA_ERR_ALREADY_STOPPED)) { 253 printk(KERN_ERR "%s() pause transition failed, ret = 0x%x\n", 254 __func__, ret); 255 ret = -EIO; 256 } else { 257 dprintk(DBGLVL_VBI, "%s() Paused\n", __func__); 258 ret = 0; 259 } 260 261 return ret; 262} 263 264/* Firmware is very windows centric, meaning you have to transition 265 * the part through AVStream / KS Windows stages, forwards or backwards. 266 * States are: stopped, acquired (h/w), paused, started. 267 * We have to leave here will all of the soft buffers on the free list, 268 * else the cfg_post() func won't have soft buffers to correctly configure. 269 */ 270static int saa7164_vbi_stop_streaming(struct saa7164_port *port) 271{ 272 struct saa7164_dev *dev = port->dev; 273 struct saa7164_buffer *buf; 274 struct saa7164_user_buffer *ubuf; 275 struct list_head *c, *n; 276 int ret; 277 278 dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr); 279 280 ret = saa7164_vbi_pause_port(port); 281 ret = saa7164_vbi_acquire_port(port); 282 ret = saa7164_vbi_stop_port(port); 283 284 dprintk(DBGLVL_VBI, "%s(port=%d) Hardware stopped\n", __func__, 285 port->nr); 286 287 /* Reset the state of any allocated buffer resources */ 288 mutex_lock(&port->dmaqueue_lock); 289 290 /* Reset the hard and soft buffer state */ 291 list_for_each_safe(c, n, &port->dmaqueue.list) { 292 buf = list_entry(c, struct saa7164_buffer, list); 293 buf->flags = SAA7164_BUFFER_FREE; 294 buf->pos = 0; 295 } 296 297 list_for_each_safe(c, n, &port->list_buf_used.list) { 298 ubuf = list_entry(c, struct saa7164_user_buffer, list); 299 ubuf->pos = 0; 300 list_move_tail(&ubuf->list, &port->list_buf_free.list); 301 } 302 303 mutex_unlock(&port->dmaqueue_lock); 304 305 /* Free any allocated resources */ 306 saa7164_vbi_buffers_dealloc(port); 307 308 dprintk(DBGLVL_VBI, "%s(port=%d) Released\n", __func__, port->nr); 309 310 return ret; 311} 312 313static int saa7164_vbi_start_streaming(struct saa7164_port *port) 314{ 315 struct saa7164_dev *dev = port->dev; 316 int result, ret = 0; 317 318 dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr); 319 320 port->done_first_interrupt = 0; 321 322 /* allocate all of the PCIe DMA buffer resources on the fly, 323 * allowing switching between TS and PS payloads without 324 * requiring a complete driver reload. 325 */ 326 saa7164_vbi_buffers_alloc(port); 327 328 /* Configure the encoder with any cache values */ 329#if 0 330 saa7164_api_set_encoder(port); 331 saa7164_api_get_encoder(port); 332#endif 333 334 /* Place the empty buffers on the hardware */ 335 saa7164_buffer_cfg_port(port); 336 337 /* Negotiate format */ 338 if (saa7164_api_set_vbi_format(port) != SAA_OK) { 339 printk(KERN_ERR "%s() No supported VBI format\n", __func__); 340 ret = -EIO; 341 goto out; 342 } 343 344 /* Acquire the hardware */ 345 result = saa7164_api_transition_port(port, SAA_DMASTATE_ACQUIRE); 346 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) { 347 printk(KERN_ERR "%s() acquire transition failed, res = 0x%x\n", 348 __func__, result); 349 350 ret = -EIO; 351 goto out; 352 } else 353 dprintk(DBGLVL_VBI, "%s() Acquired\n", __func__); 354 355 /* Pause the hardware */ 356 result = saa7164_api_transition_port(port, SAA_DMASTATE_PAUSE); 357 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) { 358 printk(KERN_ERR "%s() pause transition failed, res = 0x%x\n", 359 __func__, result); 360 361 /* Stop the hardware, regardless */ 362 result = saa7164_vbi_stop_port(port); 363 if (result != SAA_OK) { 364 printk(KERN_ERR "%s() pause/forced stop transition failed, res = 0x%x\n", 365 __func__, result); 366 } 367 368 ret = -EIO; 369 goto out; 370 } else 371 dprintk(DBGLVL_VBI, "%s() Paused\n", __func__); 372 373 /* Start the hardware */ 374 result = saa7164_api_transition_port(port, SAA_DMASTATE_RUN); 375 if ((result != SAA_OK) && (result != SAA_ERR_ALREADY_STOPPED)) { 376 printk(KERN_ERR "%s() run transition failed, result = 0x%x\n", 377 __func__, result); 378 379 /* Stop the hardware, regardless */ 380 result = saa7164_vbi_acquire_port(port); 381 result = saa7164_vbi_stop_port(port); 382 if (result != SAA_OK) { 383 printk(KERN_ERR "%s() run/forced stop transition failed, res = 0x%x\n", 384 __func__, result); 385 } 386 387 ret = -EIO; 388 } else 389 dprintk(DBGLVL_VBI, "%s() Running\n", __func__); 390 391out: 392 return ret; 393} 394 395static int saa7164_vbi_fmt(struct file *file, void *priv, 396 struct v4l2_format *f) 397{ 398 /* ntsc */ 399 f->fmt.vbi.samples_per_line = 1440; 400 f->fmt.vbi.sampling_rate = 27000000; 401 f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY; 402 f->fmt.vbi.offset = 0; 403 f->fmt.vbi.flags = 0; 404 f->fmt.vbi.start[0] = 10; 405 f->fmt.vbi.count[0] = 18; 406 f->fmt.vbi.start[1] = 263 + 10 + 1; 407 f->fmt.vbi.count[1] = 18; 408 memset(f->fmt.vbi.reserved, 0, sizeof(f->fmt.vbi.reserved)); 409 return 0; 410} 411 412static int fops_open(struct file *file) 413{ 414 struct saa7164_dev *dev; 415 struct saa7164_port *port; 416 struct saa7164_vbi_fh *fh; 417 418 port = (struct saa7164_port *)video_get_drvdata(video_devdata(file)); 419 if (!port) 420 return -ENODEV; 421 422 dev = port->dev; 423 424 dprintk(DBGLVL_VBI, "%s()\n", __func__); 425 426 /* allocate + initialize per filehandle data */ 427 fh = kzalloc(sizeof(*fh), GFP_KERNEL); 428 if (NULL == fh) 429 return -ENOMEM; 430 431 fh->port = port; 432 v4l2_fh_init(&fh->fh, video_devdata(file)); 433 v4l2_fh_add(&fh->fh); 434 file->private_data = fh; 435 436 return 0; 437} 438 439static int fops_release(struct file *file) 440{ 441 struct saa7164_vbi_fh *fh = file->private_data; 442 struct saa7164_port *port = fh->port; 443 struct saa7164_dev *dev = port->dev; 444 445 dprintk(DBGLVL_VBI, "%s()\n", __func__); 446 447 /* Shut device down on last close */ 448 if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) { 449 if (atomic_dec_return(&port->v4l_reader_count) == 0) { 450 /* stop vbi capture then cancel buffers */ 451 saa7164_vbi_stop_streaming(port); 452 } 453 } 454 455 v4l2_fh_del(&fh->fh); 456 v4l2_fh_exit(&fh->fh); 457 kfree(fh); 458 459 return 0; 460} 461 462static struct 463saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port) 464{ 465 struct saa7164_user_buffer *ubuf = NULL; 466 struct saa7164_dev *dev = port->dev; 467 u32 crc; 468 469 mutex_lock(&port->dmaqueue_lock); 470 if (!list_empty(&port->list_buf_used.list)) { 471 ubuf = list_first_entry(&port->list_buf_used.list, 472 struct saa7164_user_buffer, list); 473 474 if (crc_checking) { 475 crc = crc32(0, ubuf->data, ubuf->actual_size); 476 if (crc != ubuf->crc) { 477 printk(KERN_ERR "%s() ubuf %p crc became invalid, was 0x%x became 0x%x\n", 478 __func__, 479 ubuf, ubuf->crc, crc); 480 } 481 } 482 483 } 484 mutex_unlock(&port->dmaqueue_lock); 485 486 dprintk(DBGLVL_VBI, "%s() returns %p\n", __func__, ubuf); 487 488 return ubuf; 489} 490 491static ssize_t fops_read(struct file *file, char __user *buffer, 492 size_t count, loff_t *pos) 493{ 494 struct saa7164_vbi_fh *fh = file->private_data; 495 struct saa7164_port *port = fh->port; 496 struct saa7164_user_buffer *ubuf = NULL; 497 struct saa7164_dev *dev = port->dev; 498 int ret = 0; 499 int rem, cnt; 500 u8 *p; 501 502 port->last_read_msecs_diff = port->last_read_msecs; 503 port->last_read_msecs = jiffies_to_msecs(jiffies); 504 port->last_read_msecs_diff = port->last_read_msecs - 505 port->last_read_msecs_diff; 506 507 saa7164_histogram_update(&port->read_interval, 508 port->last_read_msecs_diff); 509 510 if (*pos) { 511 printk(KERN_ERR "%s() ESPIPE\n", __func__); 512 return -ESPIPE; 513 } 514 515 if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { 516 if (atomic_inc_return(&port->v4l_reader_count) == 1) { 517 518 if (saa7164_vbi_initialize(port) < 0) { 519 printk(KERN_ERR "%s() EINVAL\n", __func__); 520 return -EINVAL; 521 } 522 523 saa7164_vbi_start_streaming(port); 524 msleep(200); 525 } 526 } 527 528 /* blocking wait for buffer */ 529 if ((file->f_flags & O_NONBLOCK) == 0) { 530 if (wait_event_interruptible(port->wait_read, 531 saa7164_vbi_next_buf(port))) { 532 printk(KERN_ERR "%s() ERESTARTSYS\n", __func__); 533 return -ERESTARTSYS; 534 } 535 } 536 537 /* Pull the first buffer from the used list */ 538 ubuf = saa7164_vbi_next_buf(port); 539 540 while ((count > 0) && ubuf) { 541 542 /* set remaining bytes to copy */ 543 rem = ubuf->actual_size - ubuf->pos; 544 cnt = rem > count ? count : rem; 545 546 p = ubuf->data + ubuf->pos; 547 548 dprintk(DBGLVL_VBI, 549 "%s() count=%d cnt=%d rem=%d buf=%p buf->pos=%d\n", 550 __func__, (int)count, cnt, rem, ubuf, ubuf->pos); 551 552 if (copy_to_user(buffer, p, cnt)) { 553 printk(KERN_ERR "%s() copy_to_user failed\n", __func__); 554 if (!ret) { 555 printk(KERN_ERR "%s() EFAULT\n", __func__); 556 ret = -EFAULT; 557 } 558 goto err; 559 } 560 561 ubuf->pos += cnt; 562 count -= cnt; 563 buffer += cnt; 564 ret += cnt; 565 566 if (ubuf->pos > ubuf->actual_size) 567 printk(KERN_ERR "read() pos > actual, huh?\n"); 568 569 if (ubuf->pos == ubuf->actual_size) { 570 571 /* finished with current buffer, take next buffer */ 572 573 /* Requeue the buffer on the free list */ 574 ubuf->pos = 0; 575 576 mutex_lock(&port->dmaqueue_lock); 577 list_move_tail(&ubuf->list, &port->list_buf_free.list); 578 mutex_unlock(&port->dmaqueue_lock); 579 580 /* Dequeue next */ 581 if ((file->f_flags & O_NONBLOCK) == 0) { 582 if (wait_event_interruptible(port->wait_read, 583 saa7164_vbi_next_buf(port))) { 584 break; 585 } 586 } 587 ubuf = saa7164_vbi_next_buf(port); 588 } 589 } 590err: 591 if (!ret && !ubuf) { 592 printk(KERN_ERR "%s() EAGAIN\n", __func__); 593 ret = -EAGAIN; 594 } 595 596 return ret; 597} 598 599static __poll_t fops_poll(struct file *file, poll_table *wait) 600{ 601 struct saa7164_vbi_fh *fh = (struct saa7164_vbi_fh *)file->private_data; 602 struct saa7164_port *port = fh->port; 603 __poll_t mask = 0; 604 605 port->last_poll_msecs_diff = port->last_poll_msecs; 606 port->last_poll_msecs = jiffies_to_msecs(jiffies); 607 port->last_poll_msecs_diff = port->last_poll_msecs - 608 port->last_poll_msecs_diff; 609 610 saa7164_histogram_update(&port->poll_interval, 611 port->last_poll_msecs_diff); 612 613 if (!video_is_registered(port->v4l_device)) 614 return EPOLLERR; 615 616 if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { 617 if (atomic_inc_return(&port->v4l_reader_count) == 1) { 618 if (saa7164_vbi_initialize(port) < 0) 619 return EPOLLERR; 620 saa7164_vbi_start_streaming(port); 621 msleep(200); 622 } 623 } 624 625 /* blocking wait for buffer */ 626 if ((file->f_flags & O_NONBLOCK) == 0) { 627 if (wait_event_interruptible(port->wait_read, 628 saa7164_vbi_next_buf(port))) { 629 return EPOLLERR; 630 } 631 } 632 633 /* Pull the first buffer from the used list */ 634 if (!list_empty(&port->list_buf_used.list)) 635 mask |= EPOLLIN | EPOLLRDNORM; 636 637 return mask; 638} 639static const struct v4l2_file_operations vbi_fops = { 640 .owner = THIS_MODULE, 641 .open = fops_open, 642 .release = fops_release, 643 .read = fops_read, 644 .poll = fops_poll, 645 .unlocked_ioctl = video_ioctl2, 646}; 647 648static const struct v4l2_ioctl_ops vbi_ioctl_ops = { 649 .vidioc_s_std = vidioc_s_std, 650 .vidioc_g_std = vidioc_g_std, 651 .vidioc_enum_input = saa7164_enum_input, 652 .vidioc_g_input = vidioc_g_input, 653 .vidioc_s_input = vidioc_s_input, 654 .vidioc_g_tuner = saa7164_g_tuner, 655 .vidioc_s_tuner = saa7164_s_tuner, 656 .vidioc_g_frequency = vidioc_g_frequency, 657 .vidioc_s_frequency = vidioc_s_frequency, 658 .vidioc_querycap = vidioc_querycap, 659 .vidioc_g_fmt_vbi_cap = saa7164_vbi_fmt, 660 .vidioc_try_fmt_vbi_cap = saa7164_vbi_fmt, 661 .vidioc_s_fmt_vbi_cap = saa7164_vbi_fmt, 662}; 663 664static struct video_device saa7164_vbi_template = { 665 .name = "saa7164", 666 .fops = &vbi_fops, 667 .ioctl_ops = &vbi_ioctl_ops, 668 .minor = -1, 669 .tvnorms = SAA7164_NORMS, 670 .device_caps = V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE | 671 V4L2_CAP_TUNER, 672}; 673 674static struct video_device *saa7164_vbi_alloc( 675 struct saa7164_port *port, 676 struct pci_dev *pci, 677 struct video_device *template, 678 char *type) 679{ 680 struct video_device *vfd; 681 struct saa7164_dev *dev = port->dev; 682 683 dprintk(DBGLVL_VBI, "%s()\n", __func__); 684 685 vfd = video_device_alloc(); 686 if (NULL == vfd) 687 return NULL; 688 689 *vfd = *template; 690 snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, 691 type, saa7164_boards[dev->board].name); 692 693 vfd->v4l2_dev = &dev->v4l2_dev; 694 vfd->release = video_device_release; 695 return vfd; 696} 697 698int saa7164_vbi_register(struct saa7164_port *port) 699{ 700 struct saa7164_dev *dev = port->dev; 701 int result = -ENODEV; 702 703 dprintk(DBGLVL_VBI, "%s()\n", __func__); 704 705 BUG_ON(port->type != SAA7164_MPEG_VBI); 706 707 /* Sanity check that the PCI configuration space is active */ 708 if (port->hwcfg.BARLocation == 0) { 709 printk(KERN_ERR "%s() failed (errno = %d), NO PCI configuration\n", 710 __func__, result); 711 result = -ENOMEM; 712 goto failed; 713 } 714 715 /* Establish VBI defaults here */ 716 717 /* Allocate and register the video device node */ 718 port->v4l_device = saa7164_vbi_alloc(port, 719 dev->pci, &saa7164_vbi_template, "vbi"); 720 721 if (!port->v4l_device) { 722 printk(KERN_INFO "%s: can't allocate vbi device\n", 723 dev->name); 724 result = -ENOMEM; 725 goto failed; 726 } 727 728 port->enc_port = &dev->ports[port->nr - 2]; 729 video_set_drvdata(port->v4l_device, port); 730 result = video_register_device(port->v4l_device, 731 VFL_TYPE_VBI, -1); 732 if (result < 0) { 733 printk(KERN_INFO "%s: can't register vbi device\n", 734 dev->name); 735 /* TODO: We're going to leak here if we don't dealloc 736 The buffers above. The unreg function can't deal wit it. 737 */ 738 goto failed; 739 } 740 741 printk(KERN_INFO "%s: registered device vbi%d [vbi]\n", 742 dev->name, port->v4l_device->num); 743 744 /* Configure the hardware defaults */ 745 746 result = 0; 747failed: 748 return result; 749} 750 751void saa7164_vbi_unregister(struct saa7164_port *port) 752{ 753 struct saa7164_dev *dev = port->dev; 754 755 dprintk(DBGLVL_VBI, "%s(port=%d)\n", __func__, port->nr); 756 757 BUG_ON(port->type != SAA7164_MPEG_VBI); 758 759 if (port->v4l_device) { 760 if (port->v4l_device->minor != -1) 761 video_unregister_device(port->v4l_device); 762 else 763 video_device_release(port->v4l_device); 764 765 port->v4l_device = NULL; 766 } 767 768}