diff options
Diffstat (limited to 'drivers/media/pci/cx88/cx88-video.c')
-rw-r--r-- | drivers/media/pci/cx88/cx88-video.c | 871 |
1 files changed, 264 insertions, 607 deletions
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c index ce27e6d4f16e..a64ae31ae142 100644 --- a/drivers/media/pci/cx88/cx88-video.c +++ b/drivers/media/pci/cx88/cx88-video.c | |||
@@ -70,10 +70,6 @@ static unsigned int irq_debug; | |||
70 | module_param(irq_debug,int,0644); | 70 | module_param(irq_debug,int,0644); |
71 | MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); | 71 | MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]"); |
72 | 72 | ||
73 | static unsigned int vid_limit = 16; | ||
74 | module_param(vid_limit,int,0644); | ||
75 | MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes"); | ||
76 | |||
77 | #define dprintk(level,fmt, arg...) if (video_debug >= level) \ | 73 | #define dprintk(level,fmt, arg...) if (video_debug >= level) \ |
78 | printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) | 74 | printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg) |
79 | 75 | ||
@@ -297,56 +293,6 @@ enum { | |||
297 | CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls), | 293 | CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls), |
298 | }; | 294 | }; |
299 | 295 | ||
300 | /* ------------------------------------------------------------------- */ | ||
301 | /* resource management */ | ||
302 | |||
303 | static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit) | ||
304 | { | ||
305 | struct cx88_core *core = dev->core; | ||
306 | if (fh->resources & bit) | ||
307 | /* have it already allocated */ | ||
308 | return 1; | ||
309 | |||
310 | /* is it free? */ | ||
311 | mutex_lock(&core->lock); | ||
312 | if (dev->resources & bit) { | ||
313 | /* no, someone else uses it */ | ||
314 | mutex_unlock(&core->lock); | ||
315 | return 0; | ||
316 | } | ||
317 | /* it's free, grab it */ | ||
318 | fh->resources |= bit; | ||
319 | dev->resources |= bit; | ||
320 | dprintk(1,"res: get %d\n",bit); | ||
321 | mutex_unlock(&core->lock); | ||
322 | return 1; | ||
323 | } | ||
324 | |||
325 | static | ||
326 | int res_check(struct cx8800_fh *fh, unsigned int bit) | ||
327 | { | ||
328 | return (fh->resources & bit); | ||
329 | } | ||
330 | |||
331 | static | ||
332 | int res_locked(struct cx8800_dev *dev, unsigned int bit) | ||
333 | { | ||
334 | return (dev->resources & bit); | ||
335 | } | ||
336 | |||
337 | static | ||
338 | void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits) | ||
339 | { | ||
340 | struct cx88_core *core = dev->core; | ||
341 | BUG_ON((fh->resources & bits) != bits); | ||
342 | |||
343 | mutex_lock(&core->lock); | ||
344 | fh->resources &= ~bits; | ||
345 | dev->resources &= ~bits; | ||
346 | dprintk(1,"res: put %d\n",bits); | ||
347 | mutex_unlock(&core->lock); | ||
348 | } | ||
349 | |||
350 | /* ------------------------------------------------------------------ */ | 296 | /* ------------------------------------------------------------------ */ |
351 | 297 | ||
352 | int cx88_video_mux(struct cx88_core *core, unsigned int input) | 298 | int cx88_video_mux(struct cx88_core *core, unsigned int input) |
@@ -419,8 +365,8 @@ static int start_video_dma(struct cx8800_dev *dev, | |||
419 | /* setup fifo + format */ | 365 | /* setup fifo + format */ |
420 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], | 366 | cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21], |
421 | buf->bpl, buf->risc.dma); | 367 | buf->bpl, buf->risc.dma); |
422 | cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field); | 368 | cx88_set_scale(core, core->width, core->height, core->field); |
423 | cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma); | 369 | cx_write(MO_COLOR_CTRL, dev->fmt->cxformat | ColorFormatGamma); |
424 | 370 | ||
425 | /* reset counter */ | 371 | /* reset counter */ |
426 | cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET); | 372 | cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET); |
@@ -470,433 +416,211 @@ static int restart_video_queue(struct cx8800_dev *dev, | |||
470 | struct cx88_dmaqueue *q) | 416 | struct cx88_dmaqueue *q) |
471 | { | 417 | { |
472 | struct cx88_core *core = dev->core; | 418 | struct cx88_core *core = dev->core; |
473 | struct cx88_buffer *buf, *prev; | 419 | struct cx88_buffer *buf; |
474 | 420 | ||
475 | if (!list_empty(&q->active)) { | 421 | if (!list_empty(&q->active)) { |
476 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | 422 | buf = list_entry(q->active.next, struct cx88_buffer, list); |
477 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", | 423 | dprintk(2,"restart_queue [%p/%d]: restart dma\n", |
478 | buf, buf->vb.i); | 424 | buf, buf->vb.v4l2_buf.index); |
479 | start_video_dma(dev, q, buf); | 425 | start_video_dma(dev, q, buf); |
480 | list_for_each_entry(buf, &q->active, vb.queue) | 426 | list_for_each_entry(buf, &q->active, list) |
481 | buf->count = q->count++; | 427 | buf->count = q->count++; |
482 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | prev = NULL; | ||
487 | for (;;) { | ||
488 | if (list_empty(&q->queued)) | ||
489 | return 0; | ||
490 | buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); | ||
491 | if (NULL == prev) { | ||
492 | list_move_tail(&buf->vb.queue, &q->active); | ||
493 | start_video_dma(dev, q, buf); | ||
494 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
495 | buf->count = q->count++; | ||
496 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
497 | dprintk(2,"[%p/%d] restart_queue - first active\n", | ||
498 | buf,buf->vb.i); | ||
499 | |||
500 | } else if (prev->vb.width == buf->vb.width && | ||
501 | prev->vb.height == buf->vb.height && | ||
502 | prev->fmt == buf->fmt) { | ||
503 | list_move_tail(&buf->vb.queue, &q->active); | ||
504 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
505 | buf->count = q->count++; | ||
506 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
507 | dprintk(2,"[%p/%d] restart_queue - move to active\n", | ||
508 | buf,buf->vb.i); | ||
509 | } else { | ||
510 | return 0; | ||
511 | } | ||
512 | prev = buf; | ||
513 | } | 428 | } |
429 | return 0; | ||
514 | } | 430 | } |
515 | 431 | ||
516 | /* ------------------------------------------------------------------ */ | 432 | /* ------------------------------------------------------------------ */ |
517 | 433 | ||
518 | static int | 434 | static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, |
519 | buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size) | 435 | unsigned int *num_buffers, unsigned int *num_planes, |
436 | unsigned int sizes[], void *alloc_ctxs[]) | ||
520 | { | 437 | { |
521 | struct cx8800_fh *fh = q->priv_data; | 438 | struct cx8800_dev *dev = q->drv_priv; |
522 | struct cx8800_dev *dev = fh->dev; | 439 | struct cx88_core *core = dev->core; |
523 | 440 | ||
524 | *size = dev->fmt->depth * dev->width * dev->height >> 3; | 441 | *num_planes = 1; |
525 | if (0 == *count) | 442 | sizes[0] = (dev->fmt->depth * core->width * core->height) >> 3; |
526 | *count = 32; | ||
527 | if (*size * *count > vid_limit * 1024 * 1024) | ||
528 | *count = (vid_limit * 1024 * 1024) / *size; | ||
529 | return 0; | 443 | return 0; |
530 | } | 444 | } |
531 | 445 | ||
532 | static int | 446 | static int buffer_prepare(struct vb2_buffer *vb) |
533 | buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
534 | enum v4l2_field field) | ||
535 | { | 447 | { |
536 | struct cx8800_fh *fh = q->priv_data; | 448 | struct cx8800_dev *dev = vb->vb2_queue->drv_priv; |
537 | struct cx8800_dev *dev = fh->dev; | ||
538 | struct cx88_core *core = dev->core; | 449 | struct cx88_core *core = dev->core; |
539 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 450 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); |
540 | struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); | 451 | struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); |
541 | int rc, init_buffer = 0; | 452 | int rc; |
542 | 453 | ||
543 | BUG_ON(NULL == dev->fmt); | 454 | buf->bpl = core->width * dev->fmt->depth >> 3; |
544 | if (dev->width < 48 || dev->width > norm_maxw(core->tvnorm) || | ||
545 | dev->height < 32 || dev->height > norm_maxh(core->tvnorm)) | ||
546 | return -EINVAL; | ||
547 | buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3; | ||
548 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | ||
549 | return -EINVAL; | ||
550 | 455 | ||
551 | if (buf->fmt != dev->fmt || | 456 | if (vb2_plane_size(vb, 0) < core->height * buf->bpl) |
552 | buf->vb.width != dev->width || | 457 | return -EINVAL; |
553 | buf->vb.height != dev->height || | 458 | vb2_set_plane_payload(vb, 0, core->height * buf->bpl); |
554 | buf->vb.field != field) { | ||
555 | buf->fmt = dev->fmt; | ||
556 | buf->vb.width = dev->width; | ||
557 | buf->vb.height = dev->height; | ||
558 | buf->vb.field = field; | ||
559 | init_buffer = 1; | ||
560 | } | ||
561 | 459 | ||
562 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 460 | rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); |
563 | init_buffer = 1; | 461 | if (!rc) |
564 | if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL))) | 462 | return -EIO; |
565 | goto fail; | ||
566 | } | ||
567 | 463 | ||
568 | if (init_buffer) { | 464 | switch (core->field) { |
569 | buf->bpl = buf->vb.width * buf->fmt->depth >> 3; | 465 | case V4L2_FIELD_TOP: |
570 | switch (buf->vb.field) { | 466 | cx88_risc_buffer(dev->pci, &buf->risc, |
571 | case V4L2_FIELD_TOP: | 467 | sgt->sgl, 0, UNSET, |
572 | cx88_risc_buffer(dev->pci, &buf->risc, | 468 | buf->bpl, 0, core->height); |
573 | dma->sglist, 0, UNSET, | 469 | break; |
574 | buf->bpl, 0, buf->vb.height); | 470 | case V4L2_FIELD_BOTTOM: |
575 | break; | 471 | cx88_risc_buffer(dev->pci, &buf->risc, |
576 | case V4L2_FIELD_BOTTOM: | 472 | sgt->sgl, UNSET, 0, |
577 | cx88_risc_buffer(dev->pci, &buf->risc, | 473 | buf->bpl, 0, core->height); |
578 | dma->sglist, UNSET, 0, | 474 | break; |
579 | buf->bpl, 0, buf->vb.height); | 475 | case V4L2_FIELD_SEQ_TB: |
580 | break; | 476 | cx88_risc_buffer(dev->pci, &buf->risc, |
581 | case V4L2_FIELD_INTERLACED: | 477 | sgt->sgl, |
582 | cx88_risc_buffer(dev->pci, &buf->risc, | 478 | 0, buf->bpl * (core->height >> 1), |
583 | dma->sglist, 0, buf->bpl, | 479 | buf->bpl, 0, |
584 | buf->bpl, buf->bpl, | 480 | core->height >> 1); |
585 | buf->vb.height >> 1); | 481 | break; |
586 | break; | 482 | case V4L2_FIELD_SEQ_BT: |
587 | case V4L2_FIELD_SEQ_TB: | 483 | cx88_risc_buffer(dev->pci, &buf->risc, |
588 | cx88_risc_buffer(dev->pci, &buf->risc, | 484 | sgt->sgl, |
589 | dma->sglist, | 485 | buf->bpl * (core->height >> 1), 0, |
590 | 0, buf->bpl * (buf->vb.height >> 1), | 486 | buf->bpl, 0, |
591 | buf->bpl, 0, | 487 | core->height >> 1); |
592 | buf->vb.height >> 1); | 488 | break; |
593 | break; | 489 | case V4L2_FIELD_INTERLACED: |
594 | case V4L2_FIELD_SEQ_BT: | 490 | default: |
595 | cx88_risc_buffer(dev->pci, &buf->risc, | 491 | cx88_risc_buffer(dev->pci, &buf->risc, |
596 | dma->sglist, | 492 | sgt->sgl, 0, buf->bpl, |
597 | buf->bpl * (buf->vb.height >> 1), 0, | 493 | buf->bpl, buf->bpl, |
598 | buf->bpl, 0, | 494 | core->height >> 1); |
599 | buf->vb.height >> 1); | 495 | break; |
600 | break; | ||
601 | default: | ||
602 | BUG(); | ||
603 | } | ||
604 | } | 496 | } |
605 | dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", | 497 | dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", |
606 | buf, buf->vb.i, | 498 | buf, buf->vb.v4l2_buf.index, |
607 | dev->width, dev->height, dev->fmt->depth, dev->fmt->name, | 499 | core->width, core->height, dev->fmt->depth, dev->fmt->name, |
608 | (unsigned long)buf->risc.dma); | 500 | (unsigned long)buf->risc.dma); |
609 | |||
610 | buf->vb.state = VIDEOBUF_PREPARED; | ||
611 | return 0; | 501 | return 0; |
502 | } | ||
503 | |||
504 | static void buffer_finish(struct vb2_buffer *vb) | ||
505 | { | ||
506 | struct cx8800_dev *dev = vb->vb2_queue->drv_priv; | ||
507 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
508 | struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); | ||
509 | struct cx88_riscmem *risc = &buf->risc; | ||
510 | |||
511 | if (risc->cpu) | ||
512 | pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); | ||
513 | memset(risc, 0, sizeof(*risc)); | ||
612 | 514 | ||
613 | fail: | 515 | dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); |
614 | cx88_free_buffer(q,buf); | ||
615 | return rc; | ||
616 | } | 516 | } |
617 | 517 | ||
618 | static void | 518 | static void buffer_queue(struct vb2_buffer *vb) |
619 | buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | ||
620 | { | 519 | { |
621 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 520 | struct cx8800_dev *dev = vb->vb2_queue->drv_priv; |
521 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
622 | struct cx88_buffer *prev; | 522 | struct cx88_buffer *prev; |
623 | struct cx8800_fh *fh = vq->priv_data; | ||
624 | struct cx8800_dev *dev = fh->dev; | ||
625 | struct cx88_core *core = dev->core; | 523 | struct cx88_core *core = dev->core; |
626 | struct cx88_dmaqueue *q = &dev->vidq; | 524 | struct cx88_dmaqueue *q = &dev->vidq; |
627 | 525 | ||
628 | /* add jump to stopper */ | 526 | /* add jump to start */ |
629 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | 527 | buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8); |
630 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | 528 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC); |
529 | buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8); | ||
631 | 530 | ||
632 | if (!list_empty(&q->queued)) { | 531 | if (list_empty(&q->active)) { |
633 | list_add_tail(&buf->vb.queue,&q->queued); | 532 | list_add_tail(&buf->list, &q->active); |
634 | buf->vb.state = VIDEOBUF_QUEUED; | ||
635 | dprintk(2,"[%p/%d] buffer_queue - append to queued\n", | ||
636 | buf, buf->vb.i); | ||
637 | |||
638 | } else if (list_empty(&q->active)) { | ||
639 | list_add_tail(&buf->vb.queue,&q->active); | ||
640 | start_video_dma(dev, q, buf); | 533 | start_video_dma(dev, q, buf); |
641 | buf->vb.state = VIDEOBUF_ACTIVE; | ||
642 | buf->count = q->count++; | 534 | buf->count = q->count++; |
643 | mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT); | ||
644 | dprintk(2,"[%p/%d] buffer_queue - first active\n", | 535 | dprintk(2,"[%p/%d] buffer_queue - first active\n", |
645 | buf, buf->vb.i); | 536 | buf, buf->vb.v4l2_buf.index); |
646 | 537 | ||
647 | } else { | 538 | } else { |
648 | prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue); | 539 | buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1); |
649 | if (prev->vb.width == buf->vb.width && | 540 | prev = list_entry(q->active.prev, struct cx88_buffer, list); |
650 | prev->vb.height == buf->vb.height && | 541 | list_add_tail(&buf->list, &q->active); |
651 | prev->fmt == buf->fmt) { | 542 | buf->count = q->count++; |
652 | list_add_tail(&buf->vb.queue,&q->active); | 543 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
653 | buf->vb.state = VIDEOBUF_ACTIVE; | 544 | dprintk(2, "[%p/%d] buffer_queue - append to active\n", |
654 | buf->count = q->count++; | 545 | buf, buf->vb.v4l2_buf.index); |
655 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | ||
656 | dprintk(2,"[%p/%d] buffer_queue - append to active\n", | ||
657 | buf, buf->vb.i); | ||
658 | |||
659 | } else { | ||
660 | list_add_tail(&buf->vb.queue,&q->queued); | ||
661 | buf->vb.state = VIDEOBUF_QUEUED; | ||
662 | dprintk(2,"[%p/%d] buffer_queue - first queued\n", | ||
663 | buf, buf->vb.i); | ||
664 | } | ||
665 | } | 546 | } |
666 | } | 547 | } |
667 | 548 | ||
668 | static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | 549 | static int start_streaming(struct vb2_queue *q, unsigned int count) |
669 | { | 550 | { |
670 | struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb); | 551 | struct cx8800_dev *dev = q->drv_priv; |
552 | struct cx88_dmaqueue *dmaq = &dev->vidq; | ||
553 | struct cx88_buffer *buf = list_entry(dmaq->active.next, | ||
554 | struct cx88_buffer, list); | ||
671 | 555 | ||
672 | cx88_free_buffer(q,buf); | 556 | start_video_dma(dev, dmaq, buf); |
557 | return 0; | ||
673 | } | 558 | } |
674 | 559 | ||
675 | static const struct videobuf_queue_ops cx8800_video_qops = { | 560 | static void stop_streaming(struct vb2_queue *q) |
676 | .buf_setup = buffer_setup, | ||
677 | .buf_prepare = buffer_prepare, | ||
678 | .buf_queue = buffer_queue, | ||
679 | .buf_release = buffer_release, | ||
680 | }; | ||
681 | |||
682 | /* ------------------------------------------------------------------ */ | ||
683 | |||
684 | |||
685 | /* ------------------------------------------------------------------ */ | ||
686 | |||
687 | static struct videobuf_queue *get_queue(struct file *file) | ||
688 | { | 561 | { |
689 | struct video_device *vdev = video_devdata(file); | 562 | struct cx8800_dev *dev = q->drv_priv; |
690 | struct cx8800_fh *fh = file->private_data; | 563 | struct cx88_core *core = dev->core; |
564 | struct cx88_dmaqueue *dmaq = &dev->vidq; | ||
565 | unsigned long flags; | ||
691 | 566 | ||
692 | switch (vdev->vfl_type) { | 567 | cx_clear(MO_VID_DMACNTRL, 0x11); |
693 | case VFL_TYPE_GRABBER: | 568 | cx_clear(VID_CAPTURE_CONTROL, 0x06); |
694 | return &fh->vidq; | 569 | spin_lock_irqsave(&dev->slock, flags); |
695 | case VFL_TYPE_VBI: | 570 | while (!list_empty(&dmaq->active)) { |
696 | return &fh->vbiq; | 571 | struct cx88_buffer *buf = list_entry(dmaq->active.next, |
697 | default: | 572 | struct cx88_buffer, list); |
698 | BUG(); | 573 | |
574 | list_del(&buf->list); | ||
575 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
699 | } | 576 | } |
577 | spin_unlock_irqrestore(&dev->slock, flags); | ||
700 | } | 578 | } |
701 | 579 | ||
702 | static int get_resource(struct file *file) | 580 | static struct vb2_ops cx8800_video_qops = { |
703 | { | 581 | .queue_setup = queue_setup, |
704 | struct video_device *vdev = video_devdata(file); | 582 | .buf_prepare = buffer_prepare, |
583 | .buf_finish = buffer_finish, | ||
584 | .buf_queue = buffer_queue, | ||
585 | .wait_prepare = vb2_ops_wait_prepare, | ||
586 | .wait_finish = vb2_ops_wait_finish, | ||
587 | .start_streaming = start_streaming, | ||
588 | .stop_streaming = stop_streaming, | ||
589 | }; | ||
705 | 590 | ||
706 | switch (vdev->vfl_type) { | 591 | /* ------------------------------------------------------------------ */ |
707 | case VFL_TYPE_GRABBER: | ||
708 | return RESOURCE_VIDEO; | ||
709 | case VFL_TYPE_VBI: | ||
710 | return RESOURCE_VBI; | ||
711 | default: | ||
712 | BUG(); | ||
713 | } | ||
714 | } | ||
715 | 592 | ||
716 | static int video_open(struct file *file) | 593 | static int radio_open(struct file *file) |
717 | { | 594 | { |
718 | struct video_device *vdev = video_devdata(file); | ||
719 | struct cx8800_dev *dev = video_drvdata(file); | 595 | struct cx8800_dev *dev = video_drvdata(file); |
720 | struct cx88_core *core = dev->core; | 596 | struct cx88_core *core = dev->core; |
721 | struct cx8800_fh *fh; | 597 | int ret = v4l2_fh_open(file); |
722 | enum v4l2_buf_type type = 0; | ||
723 | int radio = 0; | ||
724 | 598 | ||
725 | switch (vdev->vfl_type) { | 599 | if (ret) |
726 | case VFL_TYPE_GRABBER: | 600 | return ret; |
727 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
728 | break; | ||
729 | case VFL_TYPE_VBI: | ||
730 | type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
731 | break; | ||
732 | case VFL_TYPE_RADIO: | ||
733 | radio = 1; | ||
734 | break; | ||
735 | } | ||
736 | |||
737 | dprintk(1, "open dev=%s radio=%d type=%s\n", | ||
738 | video_device_node_name(vdev), radio, v4l2_type_names[type]); | ||
739 | |||
740 | /* allocate + initialize per filehandle data */ | ||
741 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | ||
742 | if (unlikely(!fh)) | ||
743 | return -ENOMEM; | ||
744 | |||
745 | v4l2_fh_init(&fh->fh, vdev); | ||
746 | file->private_data = fh; | ||
747 | fh->dev = dev; | ||
748 | 601 | ||
749 | mutex_lock(&core->lock); | 602 | cx_write(MO_GP3_IO, core->board.radio.gpio3); |
750 | 603 | cx_write(MO_GP0_IO, core->board.radio.gpio0); | |
751 | videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops, | 604 | cx_write(MO_GP1_IO, core->board.radio.gpio1); |
752 | &dev->pci->dev, &dev->slock, | 605 | cx_write(MO_GP2_IO, core->board.radio.gpio2); |
753 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 606 | if (core->board.radio.audioroute) { |
754 | V4L2_FIELD_INTERLACED, | 607 | if (core->sd_wm8775) { |
755 | sizeof(struct cx88_buffer), | 608 | call_all(core, audio, s_routing, |
756 | fh, NULL); | ||
757 | videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops, | ||
758 | &dev->pci->dev, &dev->slock, | ||
759 | V4L2_BUF_TYPE_VBI_CAPTURE, | ||
760 | V4L2_FIELD_SEQ_TB, | ||
761 | sizeof(struct cx88_buffer), | ||
762 | fh, NULL); | ||
763 | |||
764 | if (vdev->vfl_type == VFL_TYPE_RADIO) { | ||
765 | dprintk(1,"video_open: setting radio device\n"); | ||
766 | cx_write(MO_GP3_IO, core->board.radio.gpio3); | ||
767 | cx_write(MO_GP0_IO, core->board.radio.gpio0); | ||
768 | cx_write(MO_GP1_IO, core->board.radio.gpio1); | ||
769 | cx_write(MO_GP2_IO, core->board.radio.gpio2); | ||
770 | if (core->board.radio.audioroute) { | ||
771 | if (core->sd_wm8775) { | ||
772 | call_all(core, audio, s_routing, | ||
773 | core->board.radio.audioroute, 0, 0); | 609 | core->board.radio.audioroute, 0, 0); |
774 | } | ||
775 | /* "I2S ADC mode" */ | ||
776 | core->tvaudio = WW_I2SADC; | ||
777 | cx88_set_tvaudio(core); | ||
778 | } else { | ||
779 | /* FM Mode */ | ||
780 | core->tvaudio = WW_FM; | ||
781 | cx88_set_tvaudio(core); | ||
782 | cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1); | ||
783 | } | 610 | } |
784 | call_all(core, tuner, s_radio); | 611 | /* "I2S ADC mode" */ |
785 | } | 612 | core->tvaudio = WW_I2SADC; |
786 | 613 | cx88_set_tvaudio(core); | |
787 | core->users++; | ||
788 | mutex_unlock(&core->lock); | ||
789 | v4l2_fh_add(&fh->fh); | ||
790 | |||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | static ssize_t | ||
795 | video_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
796 | { | ||
797 | struct video_device *vdev = video_devdata(file); | ||
798 | struct cx8800_fh *fh = file->private_data; | ||
799 | |||
800 | switch (vdev->vfl_type) { | ||
801 | case VFL_TYPE_GRABBER: | ||
802 | if (res_locked(fh->dev,RESOURCE_VIDEO)) | ||
803 | return -EBUSY; | ||
804 | return videobuf_read_one(&fh->vidq, data, count, ppos, | ||
805 | file->f_flags & O_NONBLOCK); | ||
806 | case VFL_TYPE_VBI: | ||
807 | if (!res_get(fh->dev,fh,RESOURCE_VBI)) | ||
808 | return -EBUSY; | ||
809 | return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1, | ||
810 | file->f_flags & O_NONBLOCK); | ||
811 | default: | ||
812 | BUG(); | ||
813 | } | ||
814 | } | ||
815 | |||
816 | static unsigned int | ||
817 | video_poll(struct file *file, struct poll_table_struct *wait) | ||
818 | { | ||
819 | struct video_device *vdev = video_devdata(file); | ||
820 | struct cx8800_fh *fh = file->private_data; | ||
821 | struct cx88_buffer *buf; | ||
822 | unsigned int rc = v4l2_ctrl_poll(file, wait); | ||
823 | |||
824 | if (vdev->vfl_type == VFL_TYPE_VBI) { | ||
825 | if (!res_get(fh->dev,fh,RESOURCE_VBI)) | ||
826 | return rc | POLLERR; | ||
827 | return rc | videobuf_poll_stream(file, &fh->vbiq, wait); | ||
828 | } | ||
829 | mutex_lock(&fh->vidq.vb_lock); | ||
830 | if (res_check(fh,RESOURCE_VIDEO)) { | ||
831 | /* streaming capture */ | ||
832 | if (list_empty(&fh->vidq.stream)) | ||
833 | goto done; | ||
834 | buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream); | ||
835 | } else { | 614 | } else { |
836 | /* read() capture */ | 615 | /* FM Mode */ |
837 | buf = (struct cx88_buffer*)fh->vidq.read_buf; | 616 | core->tvaudio = WW_FM; |
838 | if (NULL == buf) | 617 | cx88_set_tvaudio(core); |
839 | goto done; | 618 | cx88_set_stereo(core, V4L2_TUNER_MODE_STEREO, 1); |
840 | } | ||
841 | poll_wait(file, &buf->vb.done, wait); | ||
842 | if (buf->vb.state == VIDEOBUF_DONE || | ||
843 | buf->vb.state == VIDEOBUF_ERROR) | ||
844 | rc |= POLLIN|POLLRDNORM; | ||
845 | done: | ||
846 | mutex_unlock(&fh->vidq.vb_lock); | ||
847 | return rc; | ||
848 | } | ||
849 | |||
850 | static int video_release(struct file *file) | ||
851 | { | ||
852 | struct cx8800_fh *fh = file->private_data; | ||
853 | struct cx8800_dev *dev = fh->dev; | ||
854 | |||
855 | /* turn off overlay */ | ||
856 | if (res_check(fh, RESOURCE_OVERLAY)) { | ||
857 | /* FIXME */ | ||
858 | res_free(dev,fh,RESOURCE_OVERLAY); | ||
859 | } | ||
860 | |||
861 | /* stop video capture */ | ||
862 | if (res_check(fh, RESOURCE_VIDEO)) { | ||
863 | videobuf_queue_cancel(&fh->vidq); | ||
864 | res_free(dev,fh,RESOURCE_VIDEO); | ||
865 | } | 619 | } |
866 | if (fh->vidq.read_buf) { | 620 | call_all(core, tuner, s_radio); |
867 | buffer_release(&fh->vidq,fh->vidq.read_buf); | ||
868 | kfree(fh->vidq.read_buf); | ||
869 | } | ||
870 | |||
871 | /* stop vbi capture */ | ||
872 | if (res_check(fh, RESOURCE_VBI)) { | ||
873 | videobuf_stop(&fh->vbiq); | ||
874 | res_free(dev,fh,RESOURCE_VBI); | ||
875 | } | ||
876 | |||
877 | videobuf_mmap_free(&fh->vidq); | ||
878 | videobuf_mmap_free(&fh->vbiq); | ||
879 | |||
880 | mutex_lock(&dev->core->lock); | ||
881 | v4l2_fh_del(&fh->fh); | ||
882 | v4l2_fh_exit(&fh->fh); | ||
883 | file->private_data = NULL; | ||
884 | kfree(fh); | ||
885 | |||
886 | dev->core->users--; | ||
887 | if (!dev->core->users) | ||
888 | call_all(dev->core, core, s_power, 0); | ||
889 | mutex_unlock(&dev->core->lock); | ||
890 | |||
891 | return 0; | 621 | return 0; |
892 | } | 622 | } |
893 | 623 | ||
894 | static int | ||
895 | video_mmap(struct file *file, struct vm_area_struct * vma) | ||
896 | { | ||
897 | return videobuf_mmap_mapper(get_queue(file), vma); | ||
898 | } | ||
899 | |||
900 | /* ------------------------------------------------------------------ */ | 624 | /* ------------------------------------------------------------------ */ |
901 | /* VIDEO CTRL IOCTLS */ | 625 | /* VIDEO CTRL IOCTLS */ |
902 | 626 | ||
@@ -999,12 +723,12 @@ static int cx8800_s_aud_ctrl(struct v4l2_ctrl *ctrl) | |||
999 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 723 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
1000 | struct v4l2_format *f) | 724 | struct v4l2_format *f) |
1001 | { | 725 | { |
1002 | struct cx8800_fh *fh = priv; | 726 | struct cx8800_dev *dev = video_drvdata(file); |
1003 | struct cx8800_dev *dev = fh->dev; | 727 | struct cx88_core *core = dev->core; |
1004 | 728 | ||
1005 | f->fmt.pix.width = dev->width; | 729 | f->fmt.pix.width = core->width; |
1006 | f->fmt.pix.height = dev->height; | 730 | f->fmt.pix.height = core->height; |
1007 | f->fmt.pix.field = fh->vidq.field; | 731 | f->fmt.pix.field = core->field; |
1008 | f->fmt.pix.pixelformat = dev->fmt->fourcc; | 732 | f->fmt.pix.pixelformat = dev->fmt->fourcc; |
1009 | f->fmt.pix.bytesperline = | 733 | f->fmt.pix.bytesperline = |
1010 | (f->fmt.pix.width * dev->fmt->depth) >> 3; | 734 | (f->fmt.pix.width * dev->fmt->depth) >> 3; |
@@ -1017,7 +741,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, | |||
1017 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 741 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
1018 | struct v4l2_format *f) | 742 | struct v4l2_format *f) |
1019 | { | 743 | { |
1020 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 744 | struct cx8800_dev *dev = video_drvdata(file); |
745 | struct cx88_core *core = dev->core; | ||
1021 | const struct cx8800_fmt *fmt; | 746 | const struct cx8800_fmt *fmt; |
1022 | enum v4l2_field field; | 747 | enum v4l2_field field; |
1023 | unsigned int maxw, maxh; | 748 | unsigned int maxw, maxh; |
@@ -1026,30 +751,30 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
1026 | if (NULL == fmt) | 751 | if (NULL == fmt) |
1027 | return -EINVAL; | 752 | return -EINVAL; |
1028 | 753 | ||
1029 | field = f->fmt.pix.field; | 754 | maxw = norm_maxw(core->tvnorm); |
1030 | maxw = norm_maxw(core->tvnorm); | 755 | maxh = norm_maxh(core->tvnorm); |
1031 | maxh = norm_maxh(core->tvnorm); | ||
1032 | 756 | ||
1033 | if (V4L2_FIELD_ANY == field) { | 757 | field = f->fmt.pix.field; |
1034 | field = (f->fmt.pix.height > maxh/2) | ||
1035 | ? V4L2_FIELD_INTERLACED | ||
1036 | : V4L2_FIELD_BOTTOM; | ||
1037 | } | ||
1038 | 758 | ||
1039 | switch (field) { | 759 | switch (field) { |
1040 | case V4L2_FIELD_TOP: | 760 | case V4L2_FIELD_TOP: |
1041 | case V4L2_FIELD_BOTTOM: | 761 | case V4L2_FIELD_BOTTOM: |
1042 | maxh = maxh / 2; | ||
1043 | break; | ||
1044 | case V4L2_FIELD_INTERLACED: | 762 | case V4L2_FIELD_INTERLACED: |
763 | case V4L2_FIELD_SEQ_BT: | ||
764 | case V4L2_FIELD_SEQ_TB: | ||
1045 | break; | 765 | break; |
1046 | default: | 766 | default: |
1047 | return -EINVAL; | 767 | field = (f->fmt.pix.height > maxh / 2) |
768 | ? V4L2_FIELD_INTERLACED | ||
769 | : V4L2_FIELD_BOTTOM; | ||
770 | break; | ||
1048 | } | 771 | } |
772 | if (V4L2_FIELD_HAS_T_OR_B(field)) | ||
773 | maxh /= 2; | ||
1049 | 774 | ||
1050 | f->fmt.pix.field = field; | ||
1051 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, | 775 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, |
1052 | &f->fmt.pix.height, 32, maxh, 0, 0); | 776 | &f->fmt.pix.height, 32, maxh, 0, 0); |
777 | f->fmt.pix.field = field; | ||
1053 | f->fmt.pix.bytesperline = | 778 | f->fmt.pix.bytesperline = |
1054 | (f->fmt.pix.width * fmt->depth) >> 3; | 779 | (f->fmt.pix.width * fmt->depth) >> 3; |
1055 | f->fmt.pix.sizeimage = | 780 | f->fmt.pix.sizeimage = |
@@ -1061,16 +786,20 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
1061 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 786 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
1062 | struct v4l2_format *f) | 787 | struct v4l2_format *f) |
1063 | { | 788 | { |
1064 | struct cx8800_fh *fh = priv; | 789 | struct cx8800_dev *dev = video_drvdata(file); |
1065 | struct cx8800_dev *dev = fh->dev; | 790 | struct cx88_core *core = dev->core; |
1066 | int err = vidioc_try_fmt_vid_cap (file,priv,f); | 791 | int err = vidioc_try_fmt_vid_cap (file,priv,f); |
1067 | 792 | ||
1068 | if (0 != err) | 793 | if (0 != err) |
1069 | return err; | 794 | return err; |
1070 | dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | 795 | if (vb2_is_busy(&dev->vb2_vidq) || vb2_is_busy(&dev->vb2_vbiq)) |
1071 | dev->width = f->fmt.pix.width; | 796 | return -EBUSY; |
1072 | dev->height = f->fmt.pix.height; | 797 | if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq)) |
1073 | fh->vidq.field = f->fmt.pix.field; | 798 | return -EBUSY; |
799 | dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat); | ||
800 | core->width = f->fmt.pix.width; | ||
801 | core->height = f->fmt.pix.height; | ||
802 | core->field = f->fmt.pix.field; | ||
1074 | return 0; | 803 | return 0; |
1075 | } | 804 | } |
1076 | 805 | ||
@@ -1104,8 +833,8 @@ EXPORT_SYMBOL(cx88_querycap); | |||
1104 | static int vidioc_querycap(struct file *file, void *priv, | 833 | static int vidioc_querycap(struct file *file, void *priv, |
1105 | struct v4l2_capability *cap) | 834 | struct v4l2_capability *cap) |
1106 | { | 835 | { |
1107 | struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev; | 836 | struct cx8800_dev *dev = video_drvdata(file); |
1108 | struct cx88_core *core = dev->core; | 837 | struct cx88_core *core = dev->core; |
1109 | 838 | ||
1110 | strcpy(cap->driver, "cx8800"); | 839 | strcpy(cap->driver, "cx8800"); |
1111 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); | 840 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); |
@@ -1125,64 +854,10 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, | |||
1125 | return 0; | 854 | return 0; |
1126 | } | 855 | } |
1127 | 856 | ||
1128 | static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) | ||
1129 | { | ||
1130 | return videobuf_reqbufs(get_queue(file), p); | ||
1131 | } | ||
1132 | |||
1133 | static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1134 | { | ||
1135 | return videobuf_querybuf(get_queue(file), p); | ||
1136 | } | ||
1137 | |||
1138 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1139 | { | ||
1140 | return videobuf_qbuf(get_queue(file), p); | ||
1141 | } | ||
1142 | |||
1143 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
1144 | { | ||
1145 | return videobuf_dqbuf(get_queue(file), p, | ||
1146 | file->f_flags & O_NONBLOCK); | ||
1147 | } | ||
1148 | |||
1149 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
1150 | { | ||
1151 | struct video_device *vdev = video_devdata(file); | ||
1152 | struct cx8800_fh *fh = priv; | ||
1153 | struct cx8800_dev *dev = fh->dev; | ||
1154 | |||
1155 | if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
1156 | (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
1157 | return -EINVAL; | ||
1158 | |||
1159 | if (unlikely(!res_get(dev, fh, get_resource(file)))) | ||
1160 | return -EBUSY; | ||
1161 | return videobuf_streamon(get_queue(file)); | ||
1162 | } | ||
1163 | |||
1164 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
1165 | { | ||
1166 | struct video_device *vdev = video_devdata(file); | ||
1167 | struct cx8800_fh *fh = priv; | ||
1168 | struct cx8800_dev *dev = fh->dev; | ||
1169 | int err, res; | ||
1170 | |||
1171 | if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) || | ||
1172 | (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE)) | ||
1173 | return -EINVAL; | ||
1174 | |||
1175 | res = get_resource(file); | ||
1176 | err = videobuf_streamoff(get_queue(file)); | ||
1177 | if (err < 0) | ||
1178 | return err; | ||
1179 | res_free(dev,fh,res); | ||
1180 | return 0; | ||
1181 | } | ||
1182 | |||
1183 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) | 857 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) |
1184 | { | 858 | { |
1185 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 859 | struct cx8800_dev *dev = video_drvdata(file); |
860 | struct cx88_core *core = dev->core; | ||
1186 | 861 | ||
1187 | *tvnorm = core->tvnorm; | 862 | *tvnorm = core->tvnorm; |
1188 | return 0; | 863 | return 0; |
@@ -1190,13 +865,10 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) | |||
1190 | 865 | ||
1191 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms) | 866 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms) |
1192 | { | 867 | { |
1193 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 868 | struct cx8800_dev *dev = video_drvdata(file); |
1194 | 869 | struct cx88_core *core = dev->core; | |
1195 | mutex_lock(&core->lock); | ||
1196 | cx88_set_tvnorm(core, tvnorms); | ||
1197 | mutex_unlock(&core->lock); | ||
1198 | 870 | ||
1199 | return 0; | 871 | return cx88_set_tvnorm(core, tvnorms); |
1200 | } | 872 | } |
1201 | 873 | ||
1202 | /* only one input in this sample driver */ | 874 | /* only one input in this sample driver */ |
@@ -1233,13 +905,15 @@ EXPORT_SYMBOL(cx88_enum_input); | |||
1233 | static int vidioc_enum_input (struct file *file, void *priv, | 905 | static int vidioc_enum_input (struct file *file, void *priv, |
1234 | struct v4l2_input *i) | 906 | struct v4l2_input *i) |
1235 | { | 907 | { |
1236 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 908 | struct cx8800_dev *dev = video_drvdata(file); |
909 | struct cx88_core *core = dev->core; | ||
1237 | return cx88_enum_input (core,i); | 910 | return cx88_enum_input (core,i); |
1238 | } | 911 | } |
1239 | 912 | ||
1240 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | 913 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) |
1241 | { | 914 | { |
1242 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 915 | struct cx8800_dev *dev = video_drvdata(file); |
916 | struct cx88_core *core = dev->core; | ||
1243 | 917 | ||
1244 | *i = core->input; | 918 | *i = core->input; |
1245 | return 0; | 919 | return 0; |
@@ -1247,24 +921,24 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | |||
1247 | 921 | ||
1248 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) | 922 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) |
1249 | { | 923 | { |
1250 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 924 | struct cx8800_dev *dev = video_drvdata(file); |
925 | struct cx88_core *core = dev->core; | ||
1251 | 926 | ||
1252 | if (i >= 4) | 927 | if (i >= 4) |
1253 | return -EINVAL; | 928 | return -EINVAL; |
1254 | if (0 == INPUT(i).type) | 929 | if (0 == INPUT(i).type) |
1255 | return -EINVAL; | 930 | return -EINVAL; |
1256 | 931 | ||
1257 | mutex_lock(&core->lock); | ||
1258 | cx88_newstation(core); | 932 | cx88_newstation(core); |
1259 | cx88_video_mux(core,i); | 933 | cx88_video_mux(core,i); |
1260 | mutex_unlock(&core->lock); | ||
1261 | return 0; | 934 | return 0; |
1262 | } | 935 | } |
1263 | 936 | ||
1264 | static int vidioc_g_tuner (struct file *file, void *priv, | 937 | static int vidioc_g_tuner (struct file *file, void *priv, |
1265 | struct v4l2_tuner *t) | 938 | struct v4l2_tuner *t) |
1266 | { | 939 | { |
1267 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 940 | struct cx8800_dev *dev = video_drvdata(file); |
941 | struct cx88_core *core = dev->core; | ||
1268 | u32 reg; | 942 | u32 reg; |
1269 | 943 | ||
1270 | if (unlikely(UNSET == core->board.tuner_type)) | 944 | if (unlikely(UNSET == core->board.tuner_type)) |
@@ -1286,7 +960,8 @@ static int vidioc_g_tuner (struct file *file, void *priv, | |||
1286 | static int vidioc_s_tuner (struct file *file, void *priv, | 960 | static int vidioc_s_tuner (struct file *file, void *priv, |
1287 | const struct v4l2_tuner *t) | 961 | const struct v4l2_tuner *t) |
1288 | { | 962 | { |
1289 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 963 | struct cx8800_dev *dev = video_drvdata(file); |
964 | struct cx88_core *core = dev->core; | ||
1290 | 965 | ||
1291 | if (UNSET == core->board.tuner_type) | 966 | if (UNSET == core->board.tuner_type) |
1292 | return -EINVAL; | 967 | return -EINVAL; |
@@ -1300,8 +975,8 @@ static int vidioc_s_tuner (struct file *file, void *priv, | |||
1300 | static int vidioc_g_frequency (struct file *file, void *priv, | 975 | static int vidioc_g_frequency (struct file *file, void *priv, |
1301 | struct v4l2_frequency *f) | 976 | struct v4l2_frequency *f) |
1302 | { | 977 | { |
1303 | struct cx8800_fh *fh = priv; | 978 | struct cx8800_dev *dev = video_drvdata(file); |
1304 | struct cx88_core *core = fh->dev->core; | 979 | struct cx88_core *core = dev->core; |
1305 | 980 | ||
1306 | if (unlikely(UNSET == core->board.tuner_type)) | 981 | if (unlikely(UNSET == core->board.tuner_type)) |
1307 | return -EINVAL; | 982 | return -EINVAL; |
@@ -1325,7 +1000,6 @@ int cx88_set_freq (struct cx88_core *core, | |||
1325 | if (unlikely(f->tuner != 0)) | 1000 | if (unlikely(f->tuner != 0)) |
1326 | return -EINVAL; | 1001 | return -EINVAL; |
1327 | 1002 | ||
1328 | mutex_lock(&core->lock); | ||
1329 | cx88_newstation(core); | 1003 | cx88_newstation(core); |
1330 | call_all(core, tuner, s_frequency, f); | 1004 | call_all(core, tuner, s_frequency, f); |
1331 | call_all(core, tuner, g_frequency, &new_freq); | 1005 | call_all(core, tuner, g_frequency, &new_freq); |
@@ -1335,8 +1009,6 @@ int cx88_set_freq (struct cx88_core *core, | |||
1335 | msleep (10); | 1009 | msleep (10); |
1336 | cx88_set_tvaudio(core); | 1010 | cx88_set_tvaudio(core); |
1337 | 1011 | ||
1338 | mutex_unlock(&core->lock); | ||
1339 | |||
1340 | return 0; | 1012 | return 0; |
1341 | } | 1013 | } |
1342 | EXPORT_SYMBOL(cx88_set_freq); | 1014 | EXPORT_SYMBOL(cx88_set_freq); |
@@ -1344,8 +1016,8 @@ EXPORT_SYMBOL(cx88_set_freq); | |||
1344 | static int vidioc_s_frequency (struct file *file, void *priv, | 1016 | static int vidioc_s_frequency (struct file *file, void *priv, |
1345 | const struct v4l2_frequency *f) | 1017 | const struct v4l2_frequency *f) |
1346 | { | 1018 | { |
1347 | struct cx8800_fh *fh = priv; | 1019 | struct cx8800_dev *dev = video_drvdata(file); |
1348 | struct cx88_core *core = fh->dev->core; | 1020 | struct cx88_core *core = dev->core; |
1349 | 1021 | ||
1350 | return cx88_set_freq(core, f); | 1022 | return cx88_set_freq(core, f); |
1351 | } | 1023 | } |
@@ -1354,7 +1026,8 @@ static int vidioc_s_frequency (struct file *file, void *priv, | |||
1354 | static int vidioc_g_register (struct file *file, void *fh, | 1026 | static int vidioc_g_register (struct file *file, void *fh, |
1355 | struct v4l2_dbg_register *reg) | 1027 | struct v4l2_dbg_register *reg) |
1356 | { | 1028 | { |
1357 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; | 1029 | struct cx8800_dev *dev = video_drvdata(file); |
1030 | struct cx88_core *core = dev->core; | ||
1358 | 1031 | ||
1359 | /* cx2388x has a 24-bit register space */ | 1032 | /* cx2388x has a 24-bit register space */ |
1360 | reg->val = cx_read(reg->reg & 0xfffffc); | 1033 | reg->val = cx_read(reg->reg & 0xfffffc); |
@@ -1365,7 +1038,8 @@ static int vidioc_g_register (struct file *file, void *fh, | |||
1365 | static int vidioc_s_register (struct file *file, void *fh, | 1038 | static int vidioc_s_register (struct file *file, void *fh, |
1366 | const struct v4l2_dbg_register *reg) | 1039 | const struct v4l2_dbg_register *reg) |
1367 | { | 1040 | { |
1368 | struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core; | 1041 | struct cx8800_dev *dev = video_drvdata(file); |
1042 | struct cx88_core *core = dev->core; | ||
1369 | 1043 | ||
1370 | cx_write(reg->reg & 0xfffffc, reg->val); | 1044 | cx_write(reg->reg & 0xfffffc, reg->val); |
1371 | return 0; | 1045 | return 0; |
@@ -1379,7 +1053,8 @@ static int vidioc_s_register (struct file *file, void *fh, | |||
1379 | static int radio_g_tuner (struct file *file, void *priv, | 1053 | static int radio_g_tuner (struct file *file, void *priv, |
1380 | struct v4l2_tuner *t) | 1054 | struct v4l2_tuner *t) |
1381 | { | 1055 | { |
1382 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 1056 | struct cx8800_dev *dev = video_drvdata(file); |
1057 | struct cx88_core *core = dev->core; | ||
1383 | 1058 | ||
1384 | if (unlikely(t->index > 0)) | 1059 | if (unlikely(t->index > 0)) |
1385 | return -EINVAL; | 1060 | return -EINVAL; |
@@ -1393,7 +1068,8 @@ static int radio_g_tuner (struct file *file, void *priv, | |||
1393 | static int radio_s_tuner (struct file *file, void *priv, | 1068 | static int radio_s_tuner (struct file *file, void *priv, |
1394 | const struct v4l2_tuner *t) | 1069 | const struct v4l2_tuner *t) |
1395 | { | 1070 | { |
1396 | struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core; | 1071 | struct cx8800_dev *dev = video_drvdata(file); |
1072 | struct cx88_core *core = dev->core; | ||
1397 | 1073 | ||
1398 | if (0 != t->index) | 1074 | if (0 != t->index) |
1399 | return -EINVAL; | 1075 | return -EINVAL; |
@@ -1404,32 +1080,6 @@ static int radio_s_tuner (struct file *file, void *priv, | |||
1404 | 1080 | ||
1405 | /* ----------------------------------------------------------- */ | 1081 | /* ----------------------------------------------------------- */ |
1406 | 1082 | ||
1407 | static void cx8800_vid_timeout(unsigned long data) | ||
1408 | { | ||
1409 | struct cx8800_dev *dev = (struct cx8800_dev*)data; | ||
1410 | struct cx88_core *core = dev->core; | ||
1411 | struct cx88_dmaqueue *q = &dev->vidq; | ||
1412 | struct cx88_buffer *buf; | ||
1413 | unsigned long flags; | ||
1414 | |||
1415 | cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]); | ||
1416 | |||
1417 | cx_clear(MO_VID_DMACNTRL, 0x11); | ||
1418 | cx_clear(VID_CAPTURE_CONTROL, 0x06); | ||
1419 | |||
1420 | spin_lock_irqsave(&dev->slock,flags); | ||
1421 | while (!list_empty(&q->active)) { | ||
1422 | buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); | ||
1423 | list_del(&buf->vb.queue); | ||
1424 | buf->vb.state = VIDEOBUF_ERROR; | ||
1425 | wake_up(&buf->vb.done); | ||
1426 | printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name, | ||
1427 | buf, buf->vb.i, (unsigned long)buf->risc.dma); | ||
1428 | } | ||
1429 | restart_video_queue(dev,q); | ||
1430 | spin_unlock_irqrestore(&dev->slock,flags); | ||
1431 | } | ||
1432 | |||
1433 | static const char *cx88_vid_irqs[32] = { | 1083 | static const char *cx88_vid_irqs[32] = { |
1434 | "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", | 1084 | "y_risci1", "u_risci1", "v_risci1", "vbi_risc1", |
1435 | "y_risci2", "u_risci2", "v_risci2", "vbi_risc2", | 1085 | "y_risci2", "u_risci2", "v_risci2", "vbi_risc2", |
@@ -1476,22 +1126,6 @@ static void cx8800_vid_irq(struct cx8800_dev *dev) | |||
1476 | cx88_wakeup(core, &dev->vbiq, count); | 1126 | cx88_wakeup(core, &dev->vbiq, count); |
1477 | spin_unlock(&dev->slock); | 1127 | spin_unlock(&dev->slock); |
1478 | } | 1128 | } |
1479 | |||
1480 | /* risc2 y */ | ||
1481 | if (status & 0x10) { | ||
1482 | dprintk(2,"stopper video\n"); | ||
1483 | spin_lock(&dev->slock); | ||
1484 | restart_video_queue(dev,&dev->vidq); | ||
1485 | spin_unlock(&dev->slock); | ||
1486 | } | ||
1487 | |||
1488 | /* risc2 vbi */ | ||
1489 | if (status & 0x80) { | ||
1490 | dprintk(2,"stopper vbi\n"); | ||
1491 | spin_lock(&dev->slock); | ||
1492 | cx8800_restart_vbi_queue(dev,&dev->vbiq); | ||
1493 | spin_unlock(&dev->slock); | ||
1494 | } | ||
1495 | } | 1129 | } |
1496 | 1130 | ||
1497 | static irqreturn_t cx8800_irq(int irq, void *dev_id) | 1131 | static irqreturn_t cx8800_irq(int irq, void *dev_id) |
@@ -1530,11 +1164,11 @@ static irqreturn_t cx8800_irq(int irq, void *dev_id) | |||
1530 | static const struct v4l2_file_operations video_fops = | 1164 | static const struct v4l2_file_operations video_fops = |
1531 | { | 1165 | { |
1532 | .owner = THIS_MODULE, | 1166 | .owner = THIS_MODULE, |
1533 | .open = video_open, | 1167 | .open = v4l2_fh_open, |
1534 | .release = video_release, | 1168 | .release = vb2_fop_release, |
1535 | .read = video_read, | 1169 | .read = vb2_fop_read, |
1536 | .poll = video_poll, | 1170 | .poll = vb2_fop_poll, |
1537 | .mmap = video_mmap, | 1171 | .mmap = vb2_fop_mmap, |
1538 | .unlocked_ioctl = video_ioctl2, | 1172 | .unlocked_ioctl = video_ioctl2, |
1539 | }; | 1173 | }; |
1540 | 1174 | ||
@@ -1544,17 +1178,17 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1544 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1178 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
1545 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 1179 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, |
1546 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 1180 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
1547 | .vidioc_reqbufs = vidioc_reqbufs, | 1181 | .vidioc_reqbufs = vb2_ioctl_reqbufs, |
1548 | .vidioc_querybuf = vidioc_querybuf, | 1182 | .vidioc_querybuf = vb2_ioctl_querybuf, |
1549 | .vidioc_qbuf = vidioc_qbuf, | 1183 | .vidioc_qbuf = vb2_ioctl_qbuf, |
1550 | .vidioc_dqbuf = vidioc_dqbuf, | 1184 | .vidioc_dqbuf = vb2_ioctl_dqbuf, |
1551 | .vidioc_g_std = vidioc_g_std, | 1185 | .vidioc_g_std = vidioc_g_std, |
1552 | .vidioc_s_std = vidioc_s_std, | 1186 | .vidioc_s_std = vidioc_s_std, |
1553 | .vidioc_enum_input = vidioc_enum_input, | 1187 | .vidioc_enum_input = vidioc_enum_input, |
1554 | .vidioc_g_input = vidioc_g_input, | 1188 | .vidioc_g_input = vidioc_g_input, |
1555 | .vidioc_s_input = vidioc_s_input, | 1189 | .vidioc_s_input = vidioc_s_input, |
1556 | .vidioc_streamon = vidioc_streamon, | 1190 | .vidioc_streamon = vb2_ioctl_streamon, |
1557 | .vidioc_streamoff = vidioc_streamoff, | 1191 | .vidioc_streamoff = vb2_ioctl_streamoff, |
1558 | .vidioc_g_tuner = vidioc_g_tuner, | 1192 | .vidioc_g_tuner = vidioc_g_tuner, |
1559 | .vidioc_s_tuner = vidioc_s_tuner, | 1193 | .vidioc_s_tuner = vidioc_s_tuner, |
1560 | .vidioc_g_frequency = vidioc_g_frequency, | 1194 | .vidioc_g_frequency = vidioc_g_frequency, |
@@ -1579,17 +1213,17 @@ static const struct v4l2_ioctl_ops vbi_ioctl_ops = { | |||
1579 | .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt, | 1213 | .vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt, |
1580 | .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt, | 1214 | .vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt, |
1581 | .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt, | 1215 | .vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt, |
1582 | .vidioc_reqbufs = vidioc_reqbufs, | 1216 | .vidioc_reqbufs = vb2_ioctl_reqbufs, |
1583 | .vidioc_querybuf = vidioc_querybuf, | 1217 | .vidioc_querybuf = vb2_ioctl_querybuf, |
1584 | .vidioc_qbuf = vidioc_qbuf, | 1218 | .vidioc_qbuf = vb2_ioctl_qbuf, |
1585 | .vidioc_dqbuf = vidioc_dqbuf, | 1219 | .vidioc_dqbuf = vb2_ioctl_dqbuf, |
1586 | .vidioc_g_std = vidioc_g_std, | 1220 | .vidioc_g_std = vidioc_g_std, |
1587 | .vidioc_s_std = vidioc_s_std, | 1221 | .vidioc_s_std = vidioc_s_std, |
1588 | .vidioc_enum_input = vidioc_enum_input, | 1222 | .vidioc_enum_input = vidioc_enum_input, |
1589 | .vidioc_g_input = vidioc_g_input, | 1223 | .vidioc_g_input = vidioc_g_input, |
1590 | .vidioc_s_input = vidioc_s_input, | 1224 | .vidioc_s_input = vidioc_s_input, |
1591 | .vidioc_streamon = vidioc_streamon, | 1225 | .vidioc_streamon = vb2_ioctl_streamon, |
1592 | .vidioc_streamoff = vidioc_streamoff, | 1226 | .vidioc_streamoff = vb2_ioctl_streamoff, |
1593 | .vidioc_g_tuner = vidioc_g_tuner, | 1227 | .vidioc_g_tuner = vidioc_g_tuner, |
1594 | .vidioc_s_tuner = vidioc_s_tuner, | 1228 | .vidioc_s_tuner = vidioc_s_tuner, |
1595 | .vidioc_g_frequency = vidioc_g_frequency, | 1229 | .vidioc_g_frequency = vidioc_g_frequency, |
@@ -1610,9 +1244,9 @@ static const struct video_device cx8800_vbi_template = { | |||
1610 | static const struct v4l2_file_operations radio_fops = | 1244 | static const struct v4l2_file_operations radio_fops = |
1611 | { | 1245 | { |
1612 | .owner = THIS_MODULE, | 1246 | .owner = THIS_MODULE, |
1613 | .open = video_open, | 1247 | .open = radio_open, |
1614 | .poll = v4l2_ctrl_poll, | 1248 | .poll = v4l2_ctrl_poll, |
1615 | .release = video_release, | 1249 | .release = v4l2_fh_release, |
1616 | .unlocked_ioctl = video_ioctl2, | 1250 | .unlocked_ioctl = video_ioctl2, |
1617 | }; | 1251 | }; |
1618 | 1252 | ||
@@ -1676,6 +1310,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1676 | { | 1310 | { |
1677 | struct cx8800_dev *dev; | 1311 | struct cx8800_dev *dev; |
1678 | struct cx88_core *core; | 1312 | struct cx88_core *core; |
1313 | struct vb2_queue *q; | ||
1679 | int err; | 1314 | int err; |
1680 | int i; | 1315 | int i; |
1681 | 1316 | ||
@@ -1713,25 +1348,12 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1713 | 1348 | ||
1714 | /* initialize driver struct */ | 1349 | /* initialize driver struct */ |
1715 | spin_lock_init(&dev->slock); | 1350 | spin_lock_init(&dev->slock); |
1716 | core->tvnorm = V4L2_STD_NTSC_M; | ||
1717 | 1351 | ||
1718 | /* init video dma queues */ | 1352 | /* init video dma queues */ |
1719 | INIT_LIST_HEAD(&dev->vidq.active); | 1353 | INIT_LIST_HEAD(&dev->vidq.active); |
1720 | INIT_LIST_HEAD(&dev->vidq.queued); | ||
1721 | dev->vidq.timeout.function = cx8800_vid_timeout; | ||
1722 | dev->vidq.timeout.data = (unsigned long)dev; | ||
1723 | init_timer(&dev->vidq.timeout); | ||
1724 | cx88_risc_stopper(dev->pci,&dev->vidq.stopper, | ||
1725 | MO_VID_DMACNTRL,0x11,0x00); | ||
1726 | 1354 | ||
1727 | /* init vbi dma queues */ | 1355 | /* init vbi dma queues */ |
1728 | INIT_LIST_HEAD(&dev->vbiq.active); | 1356 | INIT_LIST_HEAD(&dev->vbiq.active); |
1729 | INIT_LIST_HEAD(&dev->vbiq.queued); | ||
1730 | dev->vbiq.timeout.function = cx8800_vbi_timeout; | ||
1731 | dev->vbiq.timeout.data = (unsigned long)dev; | ||
1732 | init_timer(&dev->vbiq.timeout); | ||
1733 | cx88_risc_stopper(dev->pci,&dev->vbiq.stopper, | ||
1734 | MO_VID_DMACNTRL,0x88,0x00); | ||
1735 | 1357 | ||
1736 | /* get irq */ | 1358 | /* get irq */ |
1737 | err = request_irq(pci_dev->irq, cx8800_irq, | 1359 | err = request_irq(pci_dev->irq, cx8800_irq, |
@@ -1820,9 +1442,10 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1820 | /* Sets device info at pci_dev */ | 1442 | /* Sets device info at pci_dev */ |
1821 | pci_set_drvdata(pci_dev, dev); | 1443 | pci_set_drvdata(pci_dev, dev); |
1822 | 1444 | ||
1823 | dev->width = 320; | 1445 | dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); |
1824 | dev->height = 240; | 1446 | |
1825 | dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24); | 1447 | /* Maintain a reference so cx88-blackbird can query the 8800 device. */ |
1448 | core->v4ldev = dev; | ||
1826 | 1449 | ||
1827 | /* initial device configuration */ | 1450 | /* initial device configuration */ |
1828 | mutex_lock(&core->lock); | 1451 | mutex_lock(&core->lock); |
@@ -1831,11 +1454,44 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1831 | v4l2_ctrl_handler_setup(&core->audio_hdl); | 1454 | v4l2_ctrl_handler_setup(&core->audio_hdl); |
1832 | cx88_video_mux(core, 0); | 1455 | cx88_video_mux(core, 0); |
1833 | 1456 | ||
1457 | q = &dev->vb2_vidq; | ||
1458 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1459 | q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; | ||
1460 | q->gfp_flags = GFP_DMA32; | ||
1461 | q->min_buffers_needed = 2; | ||
1462 | q->drv_priv = dev; | ||
1463 | q->buf_struct_size = sizeof(struct cx88_buffer); | ||
1464 | q->ops = &cx8800_video_qops; | ||
1465 | q->mem_ops = &vb2_dma_sg_memops; | ||
1466 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
1467 | q->lock = &core->lock; | ||
1468 | |||
1469 | err = vb2_queue_init(q); | ||
1470 | if (err < 0) | ||
1471 | goto fail_unreg; | ||
1472 | |||
1473 | q = &dev->vb2_vbiq; | ||
1474 | q->type = V4L2_BUF_TYPE_VBI_CAPTURE; | ||
1475 | q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; | ||
1476 | q->gfp_flags = GFP_DMA32; | ||
1477 | q->min_buffers_needed = 2; | ||
1478 | q->drv_priv = dev; | ||
1479 | q->buf_struct_size = sizeof(struct cx88_buffer); | ||
1480 | q->ops = &cx8800_vbi_qops; | ||
1481 | q->mem_ops = &vb2_dma_sg_memops; | ||
1482 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
1483 | q->lock = &core->lock; | ||
1484 | |||
1485 | err = vb2_queue_init(q); | ||
1486 | if (err < 0) | ||
1487 | goto fail_unreg; | ||
1488 | |||
1834 | /* register v4l devices */ | 1489 | /* register v4l devices */ |
1835 | dev->video_dev = cx88_vdev_init(core,dev->pci, | 1490 | dev->video_dev = cx88_vdev_init(core,dev->pci, |
1836 | &cx8800_video_template,"video"); | 1491 | &cx8800_video_template,"video"); |
1837 | video_set_drvdata(dev->video_dev, dev); | 1492 | video_set_drvdata(dev->video_dev, dev); |
1838 | dev->video_dev->ctrl_handler = &core->video_hdl; | 1493 | dev->video_dev->ctrl_handler = &core->video_hdl; |
1494 | dev->video_dev->queue = &dev->vb2_vidq; | ||
1839 | err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, | 1495 | err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER, |
1840 | video_nr[core->nr]); | 1496 | video_nr[core->nr]); |
1841 | if (err < 0) { | 1497 | if (err < 0) { |
@@ -1848,6 +1504,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1848 | 1504 | ||
1849 | dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); | 1505 | dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi"); |
1850 | video_set_drvdata(dev->vbi_dev, dev); | 1506 | video_set_drvdata(dev->vbi_dev, dev); |
1507 | dev->vbi_dev->queue = &dev->vb2_vbiq; | ||
1851 | err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, | 1508 | err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI, |
1852 | vbi_nr[core->nr]); | 1509 | vbi_nr[core->nr]); |
1853 | if (err < 0) { | 1510 | if (err < 0) { |
@@ -1875,7 +1532,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev, | |||
1875 | } | 1532 | } |
1876 | 1533 | ||
1877 | /* start tvaudio thread */ | 1534 | /* start tvaudio thread */ |
1878 | if (core->board.tuner_type != TUNER_ABSENT) { | 1535 | if (core->board.tuner_type != UNSET) { |
1879 | core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio"); | 1536 | core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio"); |
1880 | if (IS_ERR(core->kthread)) { | 1537 | if (IS_ERR(core->kthread)) { |
1881 | err = PTR_ERR(core->kthread); | 1538 | err = PTR_ERR(core->kthread); |
@@ -1892,6 +1549,7 @@ fail_unreg: | |||
1892 | free_irq(pci_dev->irq, dev); | 1549 | free_irq(pci_dev->irq, dev); |
1893 | mutex_unlock(&core->lock); | 1550 | mutex_unlock(&core->lock); |
1894 | fail_core: | 1551 | fail_core: |
1552 | core->v4ldev = NULL; | ||
1895 | cx88_core_put(core,dev->pci); | 1553 | cx88_core_put(core,dev->pci); |
1896 | fail_free: | 1554 | fail_free: |
1897 | kfree(dev); | 1555 | kfree(dev); |
@@ -1913,15 +1571,16 @@ static void cx8800_finidev(struct pci_dev *pci_dev) | |||
1913 | cx88_ir_stop(core); | 1571 | cx88_ir_stop(core); |
1914 | 1572 | ||
1915 | cx88_shutdown(core); /* FIXME */ | 1573 | cx88_shutdown(core); /* FIXME */ |
1916 | pci_disable_device(pci_dev); | ||
1917 | 1574 | ||
1918 | /* unregister stuff */ | 1575 | /* unregister stuff */ |
1919 | 1576 | ||
1920 | free_irq(pci_dev->irq, dev); | 1577 | free_irq(pci_dev->irq, dev); |
1921 | cx8800_unregister_video(dev); | 1578 | cx8800_unregister_video(dev); |
1579 | pci_disable_device(pci_dev); | ||
1580 | |||
1581 | core->v4ldev = NULL; | ||
1922 | 1582 | ||
1923 | /* free memory */ | 1583 | /* free memory */ |
1924 | btcx_riscmem_free(dev->pci,&dev->vidq.stopper); | ||
1925 | cx88_core_put(core,dev->pci); | 1584 | cx88_core_put(core,dev->pci); |
1926 | kfree(dev); | 1585 | kfree(dev); |
1927 | } | 1586 | } |
@@ -1938,12 +1597,10 @@ static int cx8800_suspend(struct pci_dev *pci_dev, pm_message_t state) | |||
1938 | if (!list_empty(&dev->vidq.active)) { | 1597 | if (!list_empty(&dev->vidq.active)) { |
1939 | printk("%s/0: suspend video\n", core->name); | 1598 | printk("%s/0: suspend video\n", core->name); |
1940 | stop_video_dma(dev); | 1599 | stop_video_dma(dev); |
1941 | del_timer(&dev->vidq.timeout); | ||
1942 | } | 1600 | } |
1943 | if (!list_empty(&dev->vbiq.active)) { | 1601 | if (!list_empty(&dev->vbiq.active)) { |
1944 | printk("%s/0: suspend vbi\n", core->name); | 1602 | printk("%s/0: suspend vbi\n", core->name); |
1945 | cx8800_stop_vbi_dma(dev); | 1603 | cx8800_stop_vbi_dma(dev); |
1946 | del_timer(&dev->vbiq.timeout); | ||
1947 | } | 1604 | } |
1948 | spin_unlock_irqrestore(&dev->slock, flags); | 1605 | spin_unlock_irqrestore(&dev->slock, flags); |
1949 | 1606 | ||