root/drivers/media/common/saa7146/saa7146_fops.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. saa7146_res_get
  2. saa7146_res_free
  3. saa7146_dma_free
  4. saa7146_buffer_queue
  5. saa7146_buffer_finish
  6. saa7146_buffer_next
  7. saa7146_buffer_timeout
  8. fops_open
  9. fops_release
  10. fops_mmap
  11. __fops_poll
  12. fops_poll
  13. fops_read
  14. fops_write
  15. vv_callback
  16. saa7146_vv_init
  17. saa7146_vv_release
  18. saa7146_register_device
  19. saa7146_unregister_device
  20. saa7146_vv_init_module
  21. saa7146_vv_cleanup_module

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   3 
   4 #include <media/drv-intf/saa7146_vv.h>
   5 #include <linux/module.h>
   6 
   7 /****************************************************************************/
   8 /* resource management functions, shamelessly stolen from saa7134 driver */
   9 
  10 int saa7146_res_get(struct saa7146_fh *fh, unsigned int bit)
  11 {
  12         struct saa7146_dev *dev = fh->dev;
  13         struct saa7146_vv *vv = dev->vv_data;
  14 
  15         if (fh->resources & bit) {
  16                 DEB_D("already allocated! want: 0x%02x, cur:0x%02x\n",
  17                       bit, vv->resources);
  18                 /* have it already allocated */
  19                 return 1;
  20         }
  21 
  22         /* is it free? */
  23         if (vv->resources & bit) {
  24                 DEB_D("locked! vv->resources:0x%02x, we want:0x%02x\n",
  25                       vv->resources, bit);
  26                 /* no, someone else uses it */
  27                 return 0;
  28         }
  29         /* it's free, grab it */
  30         fh->resources |= bit;
  31         vv->resources |= bit;
  32         DEB_D("res: get 0x%02x, cur:0x%02x\n", bit, vv->resources);
  33         return 1;
  34 }
  35 
  36 void saa7146_res_free(struct saa7146_fh *fh, unsigned int bits)
  37 {
  38         struct saa7146_dev *dev = fh->dev;
  39         struct saa7146_vv *vv = dev->vv_data;
  40 
  41         BUG_ON((fh->resources & bits) != bits);
  42 
  43         fh->resources &= ~bits;
  44         vv->resources &= ~bits;
  45         DEB_D("res: put 0x%02x, cur:0x%02x\n", bits, vv->resources);
  46 }
  47 
  48 
  49 /********************************************************************************/
  50 /* common dma functions */
  51 
  52 void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
  53                                                 struct saa7146_buf *buf)
  54 {
  55         struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
  56         DEB_EE("dev:%p, buf:%p\n", dev, buf);
  57 
  58         BUG_ON(in_interrupt());
  59 
  60         videobuf_waiton(q, &buf->vb, 0, 0);
  61         videobuf_dma_unmap(q->dev, dma);
  62         videobuf_dma_free(dma);
  63         buf->vb.state = VIDEOBUF_NEEDS_INIT;
  64 }
  65 
  66 
  67 /********************************************************************************/
  68 /* common buffer functions */
  69 
  70 int saa7146_buffer_queue(struct saa7146_dev *dev,
  71                          struct saa7146_dmaqueue *q,
  72                          struct saa7146_buf *buf)
  73 {
  74         assert_spin_locked(&dev->slock);
  75         DEB_EE("dev:%p, dmaq:%p, buf:%p\n", dev, q, buf);
  76 
  77         BUG_ON(!q);
  78 
  79         if (NULL == q->curr) {
  80                 q->curr = buf;
  81                 DEB_D("immediately activating buffer %p\n", buf);
  82                 buf->activate(dev,buf,NULL);
  83         } else {
  84                 list_add_tail(&buf->vb.queue,&q->queue);
  85                 buf->vb.state = VIDEOBUF_QUEUED;
  86                 DEB_D("adding buffer %p to queue. (active buffer present)\n",
  87                       buf);
  88         }
  89         return 0;
  90 }
  91 
  92 void saa7146_buffer_finish(struct saa7146_dev *dev,
  93                            struct saa7146_dmaqueue *q,
  94                            int state)
  95 {
  96         assert_spin_locked(&dev->slock);
  97         DEB_EE("dev:%p, dmaq:%p, state:%d\n", dev, q, state);
  98         DEB_EE("q->curr:%p\n", q->curr);
  99 
 100         BUG_ON(!q->curr);
 101 
 102         /* finish current buffer */
 103         if (NULL == q->curr) {
 104                 DEB_D("aiii. no current buffer\n");
 105                 return;
 106         }
 107 
 108         q->curr->vb.state = state;
 109         q->curr->vb.ts = ktime_get_ns();
 110         wake_up(&q->curr->vb.done);
 111 
 112         q->curr = NULL;
 113 }
 114 
 115 void saa7146_buffer_next(struct saa7146_dev *dev,
 116                          struct saa7146_dmaqueue *q, int vbi)
 117 {
 118         struct saa7146_buf *buf,*next = NULL;
 119 
 120         BUG_ON(!q);
 121 
 122         DEB_INT("dev:%p, dmaq:%p, vbi:%d\n", dev, q, vbi);
 123 
 124         assert_spin_locked(&dev->slock);
 125         if (!list_empty(&q->queue)) {
 126                 /* activate next one from queue */
 127                 buf = list_entry(q->queue.next,struct saa7146_buf,vb.queue);
 128                 list_del(&buf->vb.queue);
 129                 if (!list_empty(&q->queue))
 130                         next = list_entry(q->queue.next,struct saa7146_buf, vb.queue);
 131                 q->curr = buf;
 132                 DEB_INT("next buffer: buf:%p, prev:%p, next:%p\n",
 133                         buf, q->queue.prev, q->queue.next);
 134                 buf->activate(dev,buf,next);
 135         } else {
 136                 DEB_INT("no next buffer. stopping.\n");
 137                 if( 0 != vbi ) {
 138                         /* turn off video-dma3 */
 139                         saa7146_write(dev,MC1, MASK_20);
 140                 } else {
 141                         /* nothing to do -- just prevent next video-dma1 transfer
 142                            by lowering the protection address */
 143 
 144                         // fixme: fix this for vflip != 0
 145 
 146                         saa7146_write(dev, PROT_ADDR1, 0);
 147                         saa7146_write(dev, MC2, (MASK_02|MASK_18));
 148 
 149                         /* write the address of the rps-program */
 150                         saa7146_write(dev, RPS_ADDR0, dev->d_rps0.dma_handle);
 151                         /* turn on rps */
 152                         saa7146_write(dev, MC1, (MASK_12 | MASK_28));
 153 
 154 /*
 155                         printk("vdma%d.base_even:     0x%08x\n", 1,saa7146_read(dev,BASE_EVEN1));
 156                         printk("vdma%d.base_odd:      0x%08x\n", 1,saa7146_read(dev,BASE_ODD1));
 157                         printk("vdma%d.prot_addr:     0x%08x\n", 1,saa7146_read(dev,PROT_ADDR1));
 158                         printk("vdma%d.base_page:     0x%08x\n", 1,saa7146_read(dev,BASE_PAGE1));
 159                         printk("vdma%d.pitch:         0x%08x\n", 1,saa7146_read(dev,PITCH1));
 160                         printk("vdma%d.num_line_byte: 0x%08x\n", 1,saa7146_read(dev,NUM_LINE_BYTE1));
 161 */
 162                 }
 163                 del_timer(&q->timeout);
 164         }
 165 }
 166 
 167 void saa7146_buffer_timeout(struct timer_list *t)
 168 {
 169         struct saa7146_dmaqueue *q = from_timer(q, t, timeout);
 170         struct saa7146_dev *dev = q->dev;
 171         unsigned long flags;
 172 
 173         DEB_EE("dev:%p, dmaq:%p\n", dev, q);
 174 
 175         spin_lock_irqsave(&dev->slock,flags);
 176         if (q->curr) {
 177                 DEB_D("timeout on %p\n", q->curr);
 178                 saa7146_buffer_finish(dev,q,VIDEOBUF_ERROR);
 179         }
 180 
 181         /* we don't restart the transfer here like other drivers do. when
 182            a streaming capture is disabled, the timeout function will be
 183            called for the current buffer. if we activate the next buffer now,
 184            we mess up our capture logic. if a timeout occurs on another buffer,
 185            then something is seriously broken before, so no need to buffer the
 186            next capture IMHO... */
 187 /*
 188         saa7146_buffer_next(dev,q);
 189 */
 190         spin_unlock_irqrestore(&dev->slock,flags);
 191 }
 192 
 193 /********************************************************************************/
 194 /* file operations */
 195 
 196 static int fops_open(struct file *file)
 197 {
 198         struct video_device *vdev = video_devdata(file);
 199         struct saa7146_dev *dev = video_drvdata(file);
 200         struct saa7146_fh *fh = NULL;
 201         int result = 0;
 202 
 203         DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
 204 
 205         if (mutex_lock_interruptible(vdev->lock))
 206                 return -ERESTARTSYS;
 207 
 208         DEB_D("using: %p\n", dev);
 209 
 210         /* check if an extension is registered */
 211         if( NULL == dev->ext ) {
 212                 DEB_S("no extension registered for this device\n");
 213                 result = -ENODEV;
 214                 goto out;
 215         }
 216 
 217         /* allocate per open data */
 218         fh = kzalloc(sizeof(*fh),GFP_KERNEL);
 219         if (NULL == fh) {
 220                 DEB_S("cannot allocate memory for per open data\n");
 221                 result = -ENOMEM;
 222                 goto out;
 223         }
 224 
 225         v4l2_fh_init(&fh->fh, vdev);
 226 
 227         file->private_data = &fh->fh;
 228         fh->dev = dev;
 229 
 230         if (vdev->vfl_type == VFL_TYPE_VBI) {
 231                 DEB_S("initializing vbi...\n");
 232                 if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
 233                         result = saa7146_vbi_uops.open(dev,file);
 234                 if (dev->ext_vv_data->vbi_fops.open)
 235                         dev->ext_vv_data->vbi_fops.open(file);
 236         } else {
 237                 DEB_S("initializing video...\n");
 238                 result = saa7146_video_uops.open(dev,file);
 239         }
 240 
 241         if (0 != result) {
 242                 goto out;
 243         }
 244 
 245         if( 0 == try_module_get(dev->ext->module)) {
 246                 result = -EINVAL;
 247                 goto out;
 248         }
 249 
 250         result = 0;
 251         v4l2_fh_add(&fh->fh);
 252 out:
 253         if (fh && result != 0) {
 254                 kfree(fh);
 255                 file->private_data = NULL;
 256         }
 257         mutex_unlock(vdev->lock);
 258         return result;
 259 }
 260 
 261 static int fops_release(struct file *file)
 262 {
 263         struct video_device *vdev = video_devdata(file);
 264         struct saa7146_fh  *fh  = file->private_data;
 265         struct saa7146_dev *dev = fh->dev;
 266 
 267         DEB_EE("file:%p\n", file);
 268 
 269         mutex_lock(vdev->lock);
 270 
 271         if (vdev->vfl_type == VFL_TYPE_VBI) {
 272                 if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
 273                         saa7146_vbi_uops.release(dev,file);
 274                 if (dev->ext_vv_data->vbi_fops.release)
 275                         dev->ext_vv_data->vbi_fops.release(file);
 276         } else {
 277                 saa7146_video_uops.release(dev,file);
 278         }
 279 
 280         v4l2_fh_del(&fh->fh);
 281         v4l2_fh_exit(&fh->fh);
 282         module_put(dev->ext->module);
 283         file->private_data = NULL;
 284         kfree(fh);
 285 
 286         mutex_unlock(vdev->lock);
 287 
 288         return 0;
 289 }
 290 
 291 static int fops_mmap(struct file *file, struct vm_area_struct * vma)
 292 {
 293         struct video_device *vdev = video_devdata(file);
 294         struct saa7146_fh *fh = file->private_data;
 295         struct videobuf_queue *q;
 296         int res;
 297 
 298         switch (vdev->vfl_type) {
 299         case VFL_TYPE_GRABBER: {
 300                 DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, vma:%p\n",
 301                        file, vma);
 302                 q = &fh->video_q;
 303                 break;
 304                 }
 305         case VFL_TYPE_VBI: {
 306                 DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, vma:%p\n",
 307                        file, vma);
 308                 if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
 309                         return -ENODEV;
 310                 q = &fh->vbi_q;
 311                 break;
 312                 }
 313         default:
 314                 BUG();
 315         }
 316 
 317         if (mutex_lock_interruptible(vdev->lock))
 318                 return -ERESTARTSYS;
 319         res = videobuf_mmap_mapper(q, vma);
 320         mutex_unlock(vdev->lock);
 321         return res;
 322 }
 323 
 324 static __poll_t __fops_poll(struct file *file, struct poll_table_struct *wait)
 325 {
 326         struct video_device *vdev = video_devdata(file);
 327         struct saa7146_fh *fh = file->private_data;
 328         struct videobuf_buffer *buf = NULL;
 329         struct videobuf_queue *q;
 330         __poll_t res = v4l2_ctrl_poll(file, wait);
 331 
 332         DEB_EE("file:%p, poll:%p\n", file, wait);
 333 
 334         if (vdev->vfl_type == VFL_TYPE_VBI) {
 335                 if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_SLICED_VBI_OUTPUT)
 336                         return res | EPOLLOUT | EPOLLWRNORM;
 337                 if( 0 == fh->vbi_q.streaming )
 338                         return res | videobuf_poll_stream(file, &fh->vbi_q, wait);
 339                 q = &fh->vbi_q;
 340         } else {
 341                 DEB_D("using video queue\n");
 342                 q = &fh->video_q;
 343         }
 344 
 345         if (!list_empty(&q->stream))
 346                 buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
 347 
 348         if (!buf) {
 349                 DEB_D("buf == NULL!\n");
 350                 return res | EPOLLERR;
 351         }
 352 
 353         poll_wait(file, &buf->done, wait);
 354         if (buf->state == VIDEOBUF_DONE || buf->state == VIDEOBUF_ERROR) {
 355                 DEB_D("poll succeeded!\n");
 356                 return res | EPOLLIN | EPOLLRDNORM;
 357         }
 358 
 359         DEB_D("nothing to poll for, buf->state:%d\n", buf->state);
 360         return res;
 361 }
 362 
 363 static __poll_t fops_poll(struct file *file, struct poll_table_struct *wait)
 364 {
 365         struct video_device *vdev = video_devdata(file);
 366         __poll_t res;
 367 
 368         mutex_lock(vdev->lock);
 369         res = __fops_poll(file, wait);
 370         mutex_unlock(vdev->lock);
 371         return res;
 372 }
 373 
 374 static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 375 {
 376         struct video_device *vdev = video_devdata(file);
 377         struct saa7146_fh *fh = file->private_data;
 378         int ret;
 379 
 380         switch (vdev->vfl_type) {
 381         case VFL_TYPE_GRABBER:
 382 /*
 383                 DEB_EE("V4L2_BUF_TYPE_VIDEO_CAPTURE: file:%p, data:%p, count:%lun",
 384                        file, data, (unsigned long)count);
 385 */
 386                 return saa7146_video_uops.read(file,data,count,ppos);
 387         case VFL_TYPE_VBI:
 388 /*
 389                 DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
 390                        file, data, (unsigned long)count);
 391 */
 392                 if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) {
 393                         if (mutex_lock_interruptible(vdev->lock))
 394                                 return -ERESTARTSYS;
 395                         ret = saa7146_vbi_uops.read(file, data, count, ppos);
 396                         mutex_unlock(vdev->lock);
 397                         return ret;
 398                 }
 399                 return -EINVAL;
 400         default:
 401                 BUG();
 402         }
 403 }
 404 
 405 static ssize_t fops_write(struct file *file, const char __user *data, size_t count, loff_t *ppos)
 406 {
 407         struct video_device *vdev = video_devdata(file);
 408         struct saa7146_fh *fh = file->private_data;
 409         int ret;
 410 
 411         switch (vdev->vfl_type) {
 412         case VFL_TYPE_GRABBER:
 413                 return -EINVAL;
 414         case VFL_TYPE_VBI:
 415                 if (fh->dev->ext_vv_data->vbi_fops.write) {
 416                         if (mutex_lock_interruptible(vdev->lock))
 417                                 return -ERESTARTSYS;
 418                         ret = fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
 419                         mutex_unlock(vdev->lock);
 420                         return ret;
 421                 }
 422                 return -EINVAL;
 423         default:
 424                 BUG();
 425         }
 426 }
 427 
 428 static const struct v4l2_file_operations video_fops =
 429 {
 430         .owner          = THIS_MODULE,
 431         .open           = fops_open,
 432         .release        = fops_release,
 433         .read           = fops_read,
 434         .write          = fops_write,
 435         .poll           = fops_poll,
 436         .mmap           = fops_mmap,
 437         .unlocked_ioctl = video_ioctl2,
 438 };
 439 
 440 static void vv_callback(struct saa7146_dev *dev, unsigned long status)
 441 {
 442         u32 isr = status;
 443 
 444         DEB_INT("dev:%p, isr:0x%08x\n", dev, (u32)status);
 445 
 446         if (0 != (isr & (MASK_27))) {
 447                 DEB_INT("irq: RPS0 (0x%08x)\n", isr);
 448                 saa7146_video_uops.irq_done(dev,isr);
 449         }
 450 
 451         if (0 != (isr & (MASK_28))) {
 452                 u32 mc2 = saa7146_read(dev, MC2);
 453                 if( 0 != (mc2 & MASK_15)) {
 454                         DEB_INT("irq: RPS1 vbi workaround (0x%08x)\n", isr);
 455                         wake_up(&dev->vv_data->vbi_wq);
 456                         saa7146_write(dev,MC2, MASK_31);
 457                         return;
 458                 }
 459                 DEB_INT("irq: RPS1 (0x%08x)\n", isr);
 460                 saa7146_vbi_uops.irq_done(dev,isr);
 461         }
 462 }
 463 
 464 static const struct v4l2_ctrl_ops saa7146_ctrl_ops = {
 465         .s_ctrl = saa7146_s_ctrl,
 466 };
 467 
 468 int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
 469 {
 470         struct v4l2_ctrl_handler *hdl = &dev->ctrl_handler;
 471         struct v4l2_pix_format *fmt;
 472         struct v4l2_vbi_format *vbi;
 473         struct saa7146_vv *vv;
 474         int err;
 475 
 476         err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev);
 477         if (err)
 478                 return err;
 479 
 480         v4l2_ctrl_handler_init(hdl, 6);
 481         v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
 482                 V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
 483         v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
 484                 V4L2_CID_CONTRAST, 0, 127, 1, 64);
 485         v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
 486                 V4L2_CID_SATURATION, 0, 127, 1, 64);
 487         v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
 488                 V4L2_CID_VFLIP, 0, 1, 1, 0);
 489         v4l2_ctrl_new_std(hdl, &saa7146_ctrl_ops,
 490                 V4L2_CID_HFLIP, 0, 1, 1, 0);
 491         if (hdl->error) {
 492                 err = hdl->error;
 493                 v4l2_ctrl_handler_free(hdl);
 494                 return err;
 495         }
 496         dev->v4l2_dev.ctrl_handler = hdl;
 497 
 498         vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL);
 499         if (vv == NULL) {
 500                 ERR("out of memory. aborting.\n");
 501                 v4l2_ctrl_handler_free(hdl);
 502                 return -ENOMEM;
 503         }
 504         ext_vv->vid_ops = saa7146_video_ioctl_ops;
 505         ext_vv->vbi_ops = saa7146_vbi_ioctl_ops;
 506         ext_vv->core_ops = &saa7146_video_ioctl_ops;
 507 
 508         DEB_EE("dev:%p\n", dev);
 509 
 510         /* set default values for video parts of the saa7146 */
 511         saa7146_write(dev, BCS_CTRL, 0x80400040);
 512 
 513         /* enable video-port pins */
 514         saa7146_write(dev, MC1, (MASK_10 | MASK_26));
 515 
 516         /* save per-device extension data (one extension can
 517            handle different devices that might need different
 518            configuration data) */
 519         dev->ext_vv_data = ext_vv;
 520 
 521         vv->d_clipping.cpu_addr =
 522                 pci_zalloc_consistent(dev->pci, SAA7146_CLIPPING_MEM,
 523                                       &vv->d_clipping.dma_handle);
 524         if( NULL == vv->d_clipping.cpu_addr ) {
 525                 ERR("out of memory. aborting.\n");
 526                 kfree(vv);
 527                 v4l2_ctrl_handler_free(hdl);
 528                 return -1;
 529         }
 530 
 531         saa7146_video_uops.init(dev,vv);
 532         if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
 533                 saa7146_vbi_uops.init(dev,vv);
 534 
 535         vv->ov_fb.fmt.width = vv->standard->h_max_out;
 536         vv->ov_fb.fmt.height = vv->standard->v_max_out;
 537         vv->ov_fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
 538         vv->ov_fb.fmt.bytesperline = 2 * vv->ov_fb.fmt.width;
 539         vv->ov_fb.fmt.sizeimage = vv->ov_fb.fmt.bytesperline * vv->ov_fb.fmt.height;
 540         vv->ov_fb.fmt.colorspace = V4L2_COLORSPACE_SRGB;
 541 
 542         fmt = &vv->video_fmt;
 543         fmt->width = 384;
 544         fmt->height = 288;
 545         fmt->pixelformat = V4L2_PIX_FMT_BGR24;
 546         fmt->field = V4L2_FIELD_ANY;
 547         fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 548         fmt->bytesperline = 3 * fmt->width;
 549         fmt->sizeimage = fmt->bytesperline * fmt->height;
 550 
 551         vbi = &vv->vbi_fmt;
 552         vbi->sampling_rate      = 27000000;
 553         vbi->offset             = 248; /* todo */
 554         vbi->samples_per_line   = 720 * 2;
 555         vbi->sample_format      = V4L2_PIX_FMT_GREY;
 556 
 557         /* fixme: this only works for PAL */
 558         vbi->start[0] = 5;
 559         vbi->count[0] = 16;
 560         vbi->start[1] = 312;
 561         vbi->count[1] = 16;
 562 
 563         timer_setup(&vv->vbi_read_timeout, NULL, 0);
 564 
 565         vv->ov_fb.capability = V4L2_FBUF_CAP_LIST_CLIPPING;
 566         vv->ov_fb.flags = V4L2_FBUF_FLAG_PRIMARY;
 567         dev->vv_data = vv;
 568         dev->vv_callback = &vv_callback;
 569 
 570         return 0;
 571 }
 572 EXPORT_SYMBOL_GPL(saa7146_vv_init);
 573 
 574 int saa7146_vv_release(struct saa7146_dev* dev)
 575 {
 576         struct saa7146_vv *vv = dev->vv_data;
 577 
 578         DEB_EE("dev:%p\n", dev);
 579 
 580         v4l2_device_unregister(&dev->v4l2_dev);
 581         pci_free_consistent(dev->pci, SAA7146_CLIPPING_MEM, vv->d_clipping.cpu_addr, vv->d_clipping.dma_handle);
 582         v4l2_ctrl_handler_free(&dev->ctrl_handler);
 583         kfree(vv);
 584         dev->vv_data = NULL;
 585         dev->vv_callback = NULL;
 586 
 587         return 0;
 588 }
 589 EXPORT_SYMBOL_GPL(saa7146_vv_release);
 590 
 591 int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev,
 592                             char *name, int type)
 593 {
 594         int err;
 595         int i;
 596 
 597         DEB_EE("dev:%p, name:'%s', type:%d\n", dev, name, type);
 598 
 599         vfd->fops = &video_fops;
 600         if (type == VFL_TYPE_GRABBER)
 601                 vfd->ioctl_ops = &dev->ext_vv_data->vid_ops;
 602         else
 603                 vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;
 604         vfd->release = video_device_release_empty;
 605         vfd->lock = &dev->v4l2_lock;
 606         vfd->v4l2_dev = &dev->v4l2_dev;
 607         vfd->tvnorms = 0;
 608         for (i = 0; i < dev->ext_vv_data->num_stds; i++)
 609                 vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
 610         strscpy(vfd->name, name, sizeof(vfd->name));
 611         vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
 612                            V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
 613         vfd->device_caps |= dev->ext_vv_data->capabilities;
 614         if (type == VFL_TYPE_GRABBER)
 615                 vfd->device_caps &=
 616                         ~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT);
 617         else
 618                 vfd->device_caps &=
 619                         ~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO);
 620         video_set_drvdata(vfd, dev);
 621 
 622         err = video_register_device(vfd, type, -1);
 623         if (err < 0) {
 624                 ERR("cannot register v4l2 device. skipping.\n");
 625                 return err;
 626         }
 627 
 628         pr_info("%s: registered device %s [v4l2]\n",
 629                 dev->name, video_device_node_name(vfd));
 630         return 0;
 631 }
 632 EXPORT_SYMBOL_GPL(saa7146_register_device);
 633 
 634 int saa7146_unregister_device(struct video_device *vfd, struct saa7146_dev *dev)
 635 {
 636         DEB_EE("dev:%p\n", dev);
 637 
 638         video_unregister_device(vfd);
 639         return 0;
 640 }
 641 EXPORT_SYMBOL_GPL(saa7146_unregister_device);
 642 
 643 static int __init saa7146_vv_init_module(void)
 644 {
 645         return 0;
 646 }
 647 
 648 
 649 static void __exit saa7146_vv_cleanup_module(void)
 650 {
 651 }
 652 
 653 module_init(saa7146_vv_init_module);
 654 module_exit(saa7146_vv_cleanup_module);
 655 
 656 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
 657 MODULE_DESCRIPTION("video4linux driver for saa7146-based hardware");
 658 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */