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