diff options
Diffstat (limited to 'drivers/media/pci/cx88/cx88-blackbird.c')
-rw-r--r-- | drivers/media/pci/cx88/cx88-blackbird.c | 565 |
1 files changed, 253 insertions, 312 deletions
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c index 150bb76e7839..4160ca4e5413 100644 --- a/drivers/media/pci/cx88/cx88-blackbird.c +++ b/drivers/media/pci/cx88/cx88-blackbird.c | |||
@@ -45,10 +45,6 @@ MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE | |||
45 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
46 | MODULE_VERSION(CX88_VERSION); | 46 | MODULE_VERSION(CX88_VERSION); |
47 | 47 | ||
48 | static unsigned int mpegbufs = 32; | ||
49 | module_param(mpegbufs,int,0644); | ||
50 | MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32"); | ||
51 | |||
52 | static unsigned int debug; | 48 | static unsigned int debug; |
53 | module_param(debug,int,0644); | 49 | module_param(debug,int,0644); |
54 | MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); | 50 | MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); |
@@ -326,13 +322,13 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat | |||
326 | memory_read(dev->core, dev->mailbox - 4, &value); | 322 | memory_read(dev->core, dev->mailbox - 4, &value); |
327 | if (value != 0x12345678) { | 323 | if (value != 0x12345678) { |
328 | dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n"); | 324 | dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n"); |
329 | return -1; | 325 | return -EIO; |
330 | } | 326 | } |
331 | 327 | ||
332 | memory_read(dev->core, dev->mailbox, &flag); | 328 | memory_read(dev->core, dev->mailbox, &flag); |
333 | if (flag) { | 329 | if (flag) { |
334 | dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag); | 330 | dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag); |
335 | return -1; | 331 | return -EIO; |
336 | } | 332 | } |
337 | 333 | ||
338 | flag |= 1; /* tell 'em we're working on it */ | 334 | flag |= 1; /* tell 'em we're working on it */ |
@@ -352,14 +348,14 @@ static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 dat | |||
352 | memory_write(dev->core, dev->mailbox, flag); | 348 | memory_write(dev->core, dev->mailbox, flag); |
353 | 349 | ||
354 | /* wait for firmware to handle the API command */ | 350 | /* wait for firmware to handle the API command */ |
355 | timeout = jiffies + msecs_to_jiffies(10); | 351 | timeout = jiffies + msecs_to_jiffies(1000); |
356 | for (;;) { | 352 | for (;;) { |
357 | memory_read(dev->core, dev->mailbox, &flag); | 353 | memory_read(dev->core, dev->mailbox, &flag); |
358 | if (0 != (flag & 4)) | 354 | if (0 != (flag & 4)) |
359 | break; | 355 | break; |
360 | if (time_after(jiffies,timeout)) { | 356 | if (time_after(jiffies,timeout)) { |
361 | dprintk(0, "ERROR: API Mailbox timeout\n"); | 357 | dprintk(0, "ERROR: API Mailbox timeout %x\n", command); |
362 | return -1; | 358 | return -EIO; |
363 | } | 359 | } |
364 | udelay(10); | 360 | udelay(10); |
365 | } | 361 | } |
@@ -420,7 +416,7 @@ static int blackbird_find_mailbox(struct cx8802_dev *dev) | |||
420 | } | 416 | } |
421 | } | 417 | } |
422 | dprintk(0, "Mailbox signature values not found!\n"); | 418 | dprintk(0, "Mailbox signature values not found!\n"); |
423 | return -1; | 419 | return -EIO; |
424 | } | 420 | } |
425 | 421 | ||
426 | static int blackbird_load_firmware(struct cx8802_dev *dev) | 422 | static int blackbird_load_firmware(struct cx8802_dev *dev) |
@@ -432,7 +428,7 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) | |||
432 | int i, retval = 0; | 428 | int i, retval = 0; |
433 | u32 value = 0; | 429 | u32 value = 0; |
434 | u32 checksum = 0; | 430 | u32 checksum = 0; |
435 | u32 *dataptr; | 431 | __le32 *dataptr; |
436 | 432 | ||
437 | retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); | 433 | retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); |
438 | retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); | 434 | retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); |
@@ -449,29 +445,28 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) | |||
449 | 445 | ||
450 | 446 | ||
451 | if (retval != 0) { | 447 | if (retval != 0) { |
452 | dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n", | 448 | pr_err("Hotplug firmware request failed (%s).\n", |
453 | CX2341X_FIRM_ENC_FILENAME); | 449 | CX2341X_FIRM_ENC_FILENAME); |
454 | dprintk(0, "Please fix your hotplug setup, the board will " | 450 | pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n"); |
455 | "not work without firmware loaded!\n"); | 451 | return -EIO; |
456 | return -1; | ||
457 | } | 452 | } |
458 | 453 | ||
459 | if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { | 454 | if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { |
460 | dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n", | 455 | pr_err("Firmware size mismatch (have %zd, expected %d)\n", |
461 | firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); | 456 | firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); |
462 | release_firmware(firmware); | 457 | release_firmware(firmware); |
463 | return -1; | 458 | return -EINVAL; |
464 | } | 459 | } |
465 | 460 | ||
466 | if (0 != memcmp(firmware->data, magic, 8)) { | 461 | if (0 != memcmp(firmware->data, magic, 8)) { |
467 | dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n"); | 462 | pr_err("Firmware magic mismatch, wrong file?\n"); |
468 | release_firmware(firmware); | 463 | release_firmware(firmware); |
469 | return -1; | 464 | return -EINVAL; |
470 | } | 465 | } |
471 | 466 | ||
472 | /* transfer to the chip */ | 467 | /* transfer to the chip */ |
473 | dprintk(1,"Loading firmware ...\n"); | 468 | dprintk(1,"Loading firmware ...\n"); |
474 | dataptr = (u32*)firmware->data; | 469 | dataptr = (__le32 *)firmware->data; |
475 | for (i = 0; i < (firmware->size >> 2); i++) { | 470 | for (i = 0; i < (firmware->size >> 2); i++) { |
476 | value = le32_to_cpu(*dataptr); | 471 | value = le32_to_cpu(*dataptr); |
477 | checksum += ~value; | 472 | checksum += ~value; |
@@ -484,12 +479,11 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) | |||
484 | memory_read(dev->core, i, &value); | 479 | memory_read(dev->core, i, &value); |
485 | checksum -= ~value; | 480 | checksum -= ~value; |
486 | } | 481 | } |
482 | release_firmware(firmware); | ||
487 | if (checksum) { | 483 | if (checksum) { |
488 | dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n"); | 484 | pr_err("Firmware load might have failed (checksum mismatch).\n"); |
489 | release_firmware(firmware); | 485 | return -EIO; |
490 | return -1; | ||
491 | } | 486 | } |
492 | release_firmware(firmware); | ||
493 | dprintk(0, "Firmware upload successful.\n"); | 487 | dprintk(0, "Firmware upload successful.\n"); |
494 | 488 | ||
495 | retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); | 489 | retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); |
@@ -521,12 +515,14 @@ DB* DVD | MPEG2 | 720x576PAL | CBR | 600 :Good | 6000 Kbps | 25fps | M | |||
521 | 515 | ||
522 | static void blackbird_codec_settings(struct cx8802_dev *dev) | 516 | static void blackbird_codec_settings(struct cx8802_dev *dev) |
523 | { | 517 | { |
518 | struct cx88_core *core = dev->core; | ||
519 | |||
524 | /* assign frame size */ | 520 | /* assign frame size */ |
525 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, | 521 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, |
526 | dev->height, dev->width); | 522 | core->height, core->width); |
527 | 523 | ||
528 | dev->cxhdl.width = dev->width; | 524 | dev->cxhdl.width = core->width; |
529 | dev->cxhdl.height = dev->height; | 525 | dev->cxhdl.height = core->height; |
530 | cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50); | 526 | cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50); |
531 | cx2341x_handler_setup(&dev->cxhdl); | 527 | cx2341x_handler_setup(&dev->cxhdl); |
532 | } | 528 | } |
@@ -540,9 +536,6 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
540 | dprintk(1,"Initialize codec\n"); | 536 | dprintk(1,"Initialize codec\n"); |
541 | retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ | 537 | retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */ |
542 | if (retval < 0) { | 538 | if (retval < 0) { |
543 | |||
544 | dev->mpeg_active = 0; | ||
545 | |||
546 | /* ping was not successful, reset and upload firmware */ | 539 | /* ping was not successful, reset and upload firmware */ |
547 | cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ | 540 | cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ |
548 | cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ | 541 | cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ |
@@ -589,9 +582,8 @@ static int blackbird_initialize_codec(struct cx8802_dev *dev) | |||
589 | return 0; | 582 | return 0; |
590 | } | 583 | } |
591 | 584 | ||
592 | static int blackbird_start_codec(struct file *file, void *priv) | 585 | static int blackbird_start_codec(struct cx8802_dev *dev) |
593 | { | 586 | { |
594 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | ||
595 | struct cx88_core *core = dev->core; | 587 | struct cx88_core *core = dev->core; |
596 | /* start capturing to the host interface */ | 588 | /* start capturing to the host interface */ |
597 | u32 reg; | 589 | u32 reg; |
@@ -627,7 +619,6 @@ static int blackbird_start_codec(struct file *file, void *priv) | |||
627 | BLACKBIRD_RAW_BITS_NONE | 619 | BLACKBIRD_RAW_BITS_NONE |
628 | ); | 620 | ); |
629 | 621 | ||
630 | dev->mpeg_active = 1; | ||
631 | return 0; | 622 | return 0; |
632 | } | 623 | } |
633 | 624 | ||
@@ -641,51 +632,139 @@ static int blackbird_stop_codec(struct cx8802_dev *dev) | |||
641 | 632 | ||
642 | cx2341x_handler_set_busy(&dev->cxhdl, 0); | 633 | cx2341x_handler_set_busy(&dev->cxhdl, 0); |
643 | 634 | ||
644 | dev->mpeg_active = 0; | ||
645 | return 0; | 635 | return 0; |
646 | } | 636 | } |
647 | 637 | ||
648 | /* ------------------------------------------------------------------ */ | 638 | /* ------------------------------------------------------------------ */ |
649 | 639 | ||
650 | static int bb_buf_setup(struct videobuf_queue *q, | 640 | static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt, |
651 | unsigned int *count, unsigned int *size) | 641 | unsigned int *num_buffers, unsigned int *num_planes, |
642 | unsigned int sizes[], void *alloc_ctxs[]) | ||
652 | { | 643 | { |
653 | struct cx8802_fh *fh = q->priv_data; | 644 | struct cx8802_dev *dev = q->drv_priv; |
654 | |||
655 | fh->dev->ts_packet_size = 188 * 4; /* was: 512 */ | ||
656 | fh->dev->ts_packet_count = mpegbufs; /* was: 100 */ | ||
657 | 645 | ||
658 | *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count; | 646 | *num_planes = 1; |
659 | *count = fh->dev->ts_packet_count; | 647 | dev->ts_packet_size = 188 * 4; |
648 | dev->ts_packet_count = 32; | ||
649 | sizes[0] = dev->ts_packet_size * dev->ts_packet_count; | ||
660 | return 0; | 650 | return 0; |
661 | } | 651 | } |
662 | 652 | ||
663 | static int | 653 | static int buffer_prepare(struct vb2_buffer *vb) |
664 | bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | ||
665 | enum v4l2_field field) | ||
666 | { | 654 | { |
667 | struct cx8802_fh *fh = q->priv_data; | 655 | struct cx8802_dev *dev = vb->vb2_queue->drv_priv; |
668 | return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field); | 656 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); |
657 | |||
658 | return cx8802_buf_prepare(vb->vb2_queue, dev, buf); | ||
669 | } | 659 | } |
670 | 660 | ||
671 | static void | 661 | static void buffer_finish(struct vb2_buffer *vb) |
672 | bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
673 | { | 662 | { |
674 | struct cx8802_fh *fh = q->priv_data; | 663 | struct cx8802_dev *dev = vb->vb2_queue->drv_priv; |
675 | cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb); | 664 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); |
665 | struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0); | ||
666 | struct cx88_riscmem *risc = &buf->risc; | ||
667 | |||
668 | if (risc->cpu) | ||
669 | pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma); | ||
670 | memset(risc, 0, sizeof(*risc)); | ||
671 | |||
672 | dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE); | ||
676 | } | 673 | } |
677 | 674 | ||
678 | static void | 675 | static void buffer_queue(struct vb2_buffer *vb) |
679 | bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) | ||
680 | { | 676 | { |
681 | cx88_free_buffer(q, (struct cx88_buffer*)vb); | 677 | struct cx8802_dev *dev = vb->vb2_queue->drv_priv; |
678 | struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb); | ||
679 | |||
680 | cx8802_buf_queue(dev, buf); | ||
681 | } | ||
682 | |||
683 | static int start_streaming(struct vb2_queue *q, unsigned int count) | ||
684 | { | ||
685 | struct cx8802_dev *dev = q->drv_priv; | ||
686 | struct cx88_dmaqueue *dmaq = &dev->mpegq; | ||
687 | struct cx8802_driver *drv; | ||
688 | struct cx88_buffer *buf; | ||
689 | unsigned long flags; | ||
690 | int err; | ||
691 | |||
692 | /* Make sure we can acquire the hardware */ | ||
693 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
694 | if (!drv) { | ||
695 | dprintk(1, "%s: blackbird driver is not loaded\n", __func__); | ||
696 | err = -ENODEV; | ||
697 | goto fail; | ||
698 | } | ||
699 | |||
700 | err = drv->request_acquire(drv); | ||
701 | if (err != 0) { | ||
702 | dprintk(1, "%s: Unable to acquire hardware, %d\n", __func__, err); | ||
703 | goto fail; | ||
704 | } | ||
705 | |||
706 | if (blackbird_initialize_codec(dev) < 0) { | ||
707 | drv->request_release(drv); | ||
708 | err = -EINVAL; | ||
709 | goto fail; | ||
710 | } | ||
711 | |||
712 | err = blackbird_start_codec(dev); | ||
713 | if (err == 0) { | ||
714 | buf = list_entry(dmaq->active.next, struct cx88_buffer, list); | ||
715 | cx8802_start_dma(dev, dmaq, buf); | ||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | fail: | ||
720 | spin_lock_irqsave(&dev->slock, flags); | ||
721 | while (!list_empty(&dmaq->active)) { | ||
722 | struct cx88_buffer *buf = list_entry(dmaq->active.next, | ||
723 | struct cx88_buffer, list); | ||
724 | |||
725 | list_del(&buf->list); | ||
726 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED); | ||
727 | } | ||
728 | spin_unlock_irqrestore(&dev->slock, flags); | ||
729 | return err; | ||
682 | } | 730 | } |
683 | 731 | ||
684 | static struct videobuf_queue_ops blackbird_qops = { | 732 | static void stop_streaming(struct vb2_queue *q) |
685 | .buf_setup = bb_buf_setup, | 733 | { |
686 | .buf_prepare = bb_buf_prepare, | 734 | struct cx8802_dev *dev = q->drv_priv; |
687 | .buf_queue = bb_buf_queue, | 735 | struct cx88_dmaqueue *dmaq = &dev->mpegq; |
688 | .buf_release = bb_buf_release, | 736 | struct cx8802_driver *drv = NULL; |
737 | unsigned long flags; | ||
738 | |||
739 | cx8802_cancel_buffers(dev); | ||
740 | blackbird_stop_codec(dev); | ||
741 | |||
742 | /* Make sure we release the hardware */ | ||
743 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
744 | WARN_ON(!drv); | ||
745 | if (drv) | ||
746 | drv->request_release(drv); | ||
747 | |||
748 | spin_lock_irqsave(&dev->slock, flags); | ||
749 | while (!list_empty(&dmaq->active)) { | ||
750 | struct cx88_buffer *buf = list_entry(dmaq->active.next, | ||
751 | struct cx88_buffer, list); | ||
752 | |||
753 | list_del(&buf->list); | ||
754 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
755 | } | ||
756 | spin_unlock_irqrestore(&dev->slock, flags); | ||
757 | } | ||
758 | |||
759 | static struct vb2_ops blackbird_qops = { | ||
760 | .queue_setup = queue_setup, | ||
761 | .buf_prepare = buffer_prepare, | ||
762 | .buf_finish = buffer_finish, | ||
763 | .buf_queue = buffer_queue, | ||
764 | .wait_prepare = vb2_ops_wait_prepare, | ||
765 | .wait_finish = vb2_ops_wait_finish, | ||
766 | .start_streaming = start_streaming, | ||
767 | .stop_streaming = stop_streaming, | ||
689 | }; | 768 | }; |
690 | 769 | ||
691 | /* ------------------------------------------------------------------ */ | 770 | /* ------------------------------------------------------------------ */ |
@@ -693,8 +772,8 @@ static struct videobuf_queue_ops blackbird_qops = { | |||
693 | static int vidioc_querycap(struct file *file, void *priv, | 772 | static int vidioc_querycap(struct file *file, void *priv, |
694 | struct v4l2_capability *cap) | 773 | struct v4l2_capability *cap) |
695 | { | 774 | { |
696 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | 775 | struct cx8802_dev *dev = video_drvdata(file); |
697 | struct cx88_core *core = dev->core; | 776 | struct cx88_core *core = dev->core; |
698 | 777 | ||
699 | strcpy(cap->driver, "cx88_blackbird"); | 778 | strcpy(cap->driver, "cx88_blackbird"); |
700 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); | 779 | sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci)); |
@@ -714,131 +793,111 @@ static int vidioc_enum_fmt_vid_cap (struct file *file, void *priv, | |||
714 | return 0; | 793 | return 0; |
715 | } | 794 | } |
716 | 795 | ||
717 | static int vidioc_g_fmt_vid_cap (struct file *file, void *priv, | 796 | static int vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
718 | struct v4l2_format *f) | 797 | struct v4l2_format *f) |
719 | { | 798 | { |
720 | struct cx8802_fh *fh = priv; | 799 | struct cx8802_dev *dev = video_drvdata(file); |
721 | struct cx8802_dev *dev = fh->dev; | 800 | struct cx88_core *core = dev->core; |
722 | 801 | ||
723 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 802 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; |
724 | f->fmt.pix.bytesperline = 0; | 803 | f->fmt.pix.bytesperline = 0; |
725 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */ | 804 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; |
726 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 805 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
727 | f->fmt.pix.width = dev->width; | 806 | f->fmt.pix.width = core->width; |
728 | f->fmt.pix.height = dev->height; | 807 | f->fmt.pix.height = core->height; |
729 | f->fmt.pix.field = fh->mpegq.field; | 808 | f->fmt.pix.field = core->field; |
730 | dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n", | ||
731 | dev->width, dev->height, fh->mpegq.field ); | ||
732 | return 0; | 809 | return 0; |
733 | } | 810 | } |
734 | 811 | ||
735 | static int vidioc_try_fmt_vid_cap (struct file *file, void *priv, | 812 | static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
736 | struct v4l2_format *f) | 813 | struct v4l2_format *f) |
737 | { | 814 | { |
738 | struct cx8802_fh *fh = priv; | 815 | struct cx8802_dev *dev = video_drvdata(file); |
739 | struct cx8802_dev *dev = fh->dev; | 816 | struct cx88_core *core = dev->core; |
817 | unsigned maxw, maxh; | ||
818 | enum v4l2_field field; | ||
740 | 819 | ||
741 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 820 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; |
742 | f->fmt.pix.bytesperline = 0; | 821 | f->fmt.pix.bytesperline = 0; |
743 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */ | 822 | f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count; |
744 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 823 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; |
745 | dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n", | 824 | |
746 | dev->width, dev->height, fh->mpegq.field ); | 825 | maxw = norm_maxw(core->tvnorm); |
826 | maxh = norm_maxh(core->tvnorm); | ||
827 | |||
828 | field = f->fmt.pix.field; | ||
829 | |||
830 | switch (field) { | ||
831 | case V4L2_FIELD_TOP: | ||
832 | case V4L2_FIELD_BOTTOM: | ||
833 | case V4L2_FIELD_INTERLACED: | ||
834 | case V4L2_FIELD_SEQ_BT: | ||
835 | case V4L2_FIELD_SEQ_TB: | ||
836 | break; | ||
837 | default: | ||
838 | field = (f->fmt.pix.height > maxh / 2) | ||
839 | ? V4L2_FIELD_INTERLACED | ||
840 | : V4L2_FIELD_BOTTOM; | ||
841 | break; | ||
842 | } | ||
843 | if (V4L2_FIELD_HAS_T_OR_B(field)) | ||
844 | maxh /= 2; | ||
845 | |||
846 | v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2, | ||
847 | &f->fmt.pix.height, 32, maxh, 0, 0); | ||
848 | f->fmt.pix.field = field; | ||
747 | return 0; | 849 | return 0; |
748 | } | 850 | } |
749 | 851 | ||
750 | static int vidioc_s_fmt_vid_cap (struct file *file, void *priv, | 852 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
751 | struct v4l2_format *f) | 853 | struct v4l2_format *f) |
752 | { | 854 | { |
753 | struct cx8802_fh *fh = priv; | 855 | struct cx8802_dev *dev = video_drvdata(file); |
754 | struct cx8802_dev *dev = fh->dev; | ||
755 | struct cx88_core *core = dev->core; | 856 | struct cx88_core *core = dev->core; |
756 | 857 | ||
757 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG; | 858 | if (vb2_is_busy(&dev->vb2_mpegq)) |
758 | f->fmt.pix.bytesperline = 0; | 859 | return -EBUSY; |
759 | f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */ | 860 | if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) || |
760 | f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; | 861 | vb2_is_busy(&core->v4ldev->vb2_vbiq))) |
761 | dev->width = f->fmt.pix.width; | 862 | return -EBUSY; |
762 | dev->height = f->fmt.pix.height; | 863 | vidioc_try_fmt_vid_cap(file, priv, f); |
763 | fh->mpegq.field = f->fmt.pix.field; | 864 | core->width = f->fmt.pix.width; |
865 | core->height = f->fmt.pix.height; | ||
866 | core->field = f->fmt.pix.field; | ||
764 | cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); | 867 | cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field); |
765 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, | 868 | blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, |
766 | f->fmt.pix.height, f->fmt.pix.width); | 869 | f->fmt.pix.height, f->fmt.pix.width); |
767 | dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n", | ||
768 | f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field ); | ||
769 | return 0; | 870 | return 0; |
770 | } | 871 | } |
771 | 872 | ||
772 | static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p) | ||
773 | { | ||
774 | struct cx8802_fh *fh = priv; | ||
775 | return (videobuf_reqbufs(&fh->mpegq, p)); | ||
776 | } | ||
777 | |||
778 | static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
779 | { | ||
780 | struct cx8802_fh *fh = priv; | ||
781 | return (videobuf_querybuf(&fh->mpegq, p)); | ||
782 | } | ||
783 | |||
784 | static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
785 | { | ||
786 | struct cx8802_fh *fh = priv; | ||
787 | return (videobuf_qbuf(&fh->mpegq, p)); | ||
788 | } | ||
789 | |||
790 | static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p) | ||
791 | { | ||
792 | struct cx8802_fh *fh = priv; | ||
793 | return (videobuf_dqbuf(&fh->mpegq, p, | ||
794 | file->f_flags & O_NONBLOCK)); | ||
795 | } | ||
796 | |||
797 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | ||
798 | { | ||
799 | struct cx8802_fh *fh = priv; | ||
800 | struct cx8802_dev *dev = fh->dev; | ||
801 | |||
802 | if (!dev->mpeg_active) | ||
803 | blackbird_start_codec(file, fh); | ||
804 | return videobuf_streamon(&fh->mpegq); | ||
805 | } | ||
806 | |||
807 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | ||
808 | { | ||
809 | struct cx8802_fh *fh = priv; | ||
810 | struct cx8802_dev *dev = fh->dev; | ||
811 | |||
812 | if (dev->mpeg_active) | ||
813 | blackbird_stop_codec(dev); | ||
814 | return videobuf_streamoff(&fh->mpegq); | ||
815 | } | ||
816 | |||
817 | static int vidioc_s_frequency (struct file *file, void *priv, | 873 | static int vidioc_s_frequency (struct file *file, void *priv, |
818 | const struct v4l2_frequency *f) | 874 | const struct v4l2_frequency *f) |
819 | { | 875 | { |
820 | struct cx8802_fh *fh = priv; | 876 | struct cx8802_dev *dev = video_drvdata(file); |
821 | struct cx8802_dev *dev = fh->dev; | 877 | struct cx88_core *core = dev->core; |
822 | struct cx88_core *core = dev->core; | 878 | bool streaming; |
823 | 879 | ||
824 | if (unlikely(UNSET == core->board.tuner_type)) | 880 | if (unlikely(UNSET == core->board.tuner_type)) |
825 | return -EINVAL; | 881 | return -EINVAL; |
826 | if (unlikely(f->tuner != 0)) | 882 | if (unlikely(f->tuner != 0)) |
827 | return -EINVAL; | 883 | return -EINVAL; |
828 | if (dev->mpeg_active) | 884 | streaming = vb2_start_streaming_called(&dev->vb2_mpegq); |
885 | if (streaming) | ||
829 | blackbird_stop_codec(dev); | 886 | blackbird_stop_codec(dev); |
830 | 887 | ||
831 | cx88_set_freq (core,f); | 888 | cx88_set_freq (core,f); |
832 | blackbird_initialize_codec(dev); | 889 | blackbird_initialize_codec(dev); |
833 | cx88_set_scale(dev->core, dev->width, dev->height, | 890 | cx88_set_scale(core, core->width, core->height, |
834 | fh->mpegq.field); | 891 | core->field); |
892 | if (streaming) | ||
893 | blackbird_start_codec(dev); | ||
835 | return 0; | 894 | return 0; |
836 | } | 895 | } |
837 | 896 | ||
838 | static int vidioc_log_status (struct file *file, void *priv) | 897 | static int vidioc_log_status (struct file *file, void *priv) |
839 | { | 898 | { |
840 | struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev; | 899 | struct cx8802_dev *dev = video_drvdata(file); |
841 | struct cx88_core *core = dev->core; | 900 | struct cx88_core *core = dev->core; |
842 | char name[32 + 2]; | 901 | char name[32 + 2]; |
843 | 902 | ||
844 | snprintf(name, sizeof(name), "%s/2", core->name); | 903 | snprintf(name, sizeof(name), "%s/2", core->name); |
@@ -850,15 +909,16 @@ static int vidioc_log_status (struct file *file, void *priv) | |||
850 | static int vidioc_enum_input (struct file *file, void *priv, | 909 | static int vidioc_enum_input (struct file *file, void *priv, |
851 | struct v4l2_input *i) | 910 | struct v4l2_input *i) |
852 | { | 911 | { |
853 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 912 | struct cx8802_dev *dev = video_drvdata(file); |
913 | struct cx88_core *core = dev->core; | ||
854 | return cx88_enum_input (core,i); | 914 | return cx88_enum_input (core,i); |
855 | } | 915 | } |
856 | 916 | ||
857 | static int vidioc_g_frequency (struct file *file, void *priv, | 917 | static int vidioc_g_frequency (struct file *file, void *priv, |
858 | struct v4l2_frequency *f) | 918 | struct v4l2_frequency *f) |
859 | { | 919 | { |
860 | struct cx8802_fh *fh = priv; | 920 | struct cx8802_dev *dev = video_drvdata(file); |
861 | struct cx88_core *core = fh->dev->core; | 921 | struct cx88_core *core = dev->core; |
862 | 922 | ||
863 | if (unlikely(UNSET == core->board.tuner_type)) | 923 | if (unlikely(UNSET == core->board.tuner_type)) |
864 | return -EINVAL; | 924 | return -EINVAL; |
@@ -873,7 +933,8 @@ static int vidioc_g_frequency (struct file *file, void *priv, | |||
873 | 933 | ||
874 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | 934 | static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) |
875 | { | 935 | { |
876 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 936 | struct cx8802_dev *dev = video_drvdata(file); |
937 | struct cx88_core *core = dev->core; | ||
877 | 938 | ||
878 | *i = core->input; | 939 | *i = core->input; |
879 | return 0; | 940 | return 0; |
@@ -881,24 +942,24 @@ static int vidioc_g_input (struct file *file, void *priv, unsigned int *i) | |||
881 | 942 | ||
882 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) | 943 | static int vidioc_s_input (struct file *file, void *priv, unsigned int i) |
883 | { | 944 | { |
884 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 945 | struct cx8802_dev *dev = video_drvdata(file); |
946 | struct cx88_core *core = dev->core; | ||
885 | 947 | ||
886 | if (i >= 4) | 948 | if (i >= 4) |
887 | return -EINVAL; | 949 | return -EINVAL; |
888 | if (0 == INPUT(i).type) | 950 | if (0 == INPUT(i).type) |
889 | return -EINVAL; | 951 | return -EINVAL; |
890 | 952 | ||
891 | mutex_lock(&core->lock); | ||
892 | cx88_newstation(core); | 953 | cx88_newstation(core); |
893 | cx88_video_mux(core,i); | 954 | cx88_video_mux(core,i); |
894 | mutex_unlock(&core->lock); | ||
895 | return 0; | 955 | return 0; |
896 | } | 956 | } |
897 | 957 | ||
898 | static int vidioc_g_tuner (struct file *file, void *priv, | 958 | static int vidioc_g_tuner (struct file *file, void *priv, |
899 | struct v4l2_tuner *t) | 959 | struct v4l2_tuner *t) |
900 | { | 960 | { |
901 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 961 | struct cx8802_dev *dev = video_drvdata(file); |
962 | struct cx88_core *core = dev->core; | ||
902 | u32 reg; | 963 | u32 reg; |
903 | 964 | ||
904 | if (unlikely(UNSET == core->board.tuner_type)) | 965 | if (unlikely(UNSET == core->board.tuner_type)) |
@@ -920,7 +981,8 @@ static int vidioc_g_tuner (struct file *file, void *priv, | |||
920 | static int vidioc_s_tuner (struct file *file, void *priv, | 981 | static int vidioc_s_tuner (struct file *file, void *priv, |
921 | const struct v4l2_tuner *t) | 982 | const struct v4l2_tuner *t) |
922 | { | 983 | { |
923 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 984 | struct cx8802_dev *dev = video_drvdata(file); |
985 | struct cx88_core *core = dev->core; | ||
924 | 986 | ||
925 | if (UNSET == core->board.tuner_type) | 987 | if (UNSET == core->board.tuner_type) |
926 | return -EINVAL; | 988 | return -EINVAL; |
@@ -933,7 +995,8 @@ static int vidioc_s_tuner (struct file *file, void *priv, | |||
933 | 995 | ||
934 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) | 996 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) |
935 | { | 997 | { |
936 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | 998 | struct cx8802_dev *dev = video_drvdata(file); |
999 | struct cx88_core *core = dev->core; | ||
937 | 1000 | ||
938 | *tvnorm = core->tvnorm; | 1001 | *tvnorm = core->tvnorm; |
939 | return 0; | 1002 | return 0; |
@@ -941,155 +1004,20 @@ static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm) | |||
941 | 1004 | ||
942 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) | 1005 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id) |
943 | { | 1006 | { |
944 | struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core; | ||
945 | |||
946 | mutex_lock(&core->lock); | ||
947 | cx88_set_tvnorm(core, id); | ||
948 | mutex_unlock(&core->lock); | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | /* FIXME: cx88_ioctl_hook not implemented */ | ||
953 | |||
954 | static int mpeg_open(struct file *file) | ||
955 | { | ||
956 | struct video_device *vdev = video_devdata(file); | ||
957 | struct cx8802_dev *dev = video_drvdata(file); | 1007 | struct cx8802_dev *dev = video_drvdata(file); |
958 | struct cx8802_fh *fh; | 1008 | struct cx88_core *core = dev->core; |
959 | struct cx8802_driver *drv = NULL; | ||
960 | int err; | ||
961 | |||
962 | dprintk( 1, "%s\n", __func__); | ||
963 | |||
964 | mutex_lock(&dev->core->lock); | ||
965 | |||
966 | /* Make sure we can acquire the hardware */ | ||
967 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
968 | if (!drv) { | ||
969 | dprintk(1, "%s: blackbird driver is not loaded\n", __func__); | ||
970 | mutex_unlock(&dev->core->lock); | ||
971 | return -ENODEV; | ||
972 | } | ||
973 | |||
974 | err = drv->request_acquire(drv); | ||
975 | if (err != 0) { | ||
976 | dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err); | ||
977 | mutex_unlock(&dev->core->lock); | ||
978 | return err; | ||
979 | } | ||
980 | |||
981 | if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) { | ||
982 | drv->request_release(drv); | ||
983 | mutex_unlock(&dev->core->lock); | ||
984 | return -EINVAL; | ||
985 | } | ||
986 | dprintk(1, "open dev=%s\n", video_device_node_name(vdev)); | ||
987 | |||
988 | /* allocate + initialize per filehandle data */ | ||
989 | fh = kzalloc(sizeof(*fh),GFP_KERNEL); | ||
990 | if (NULL == fh) { | ||
991 | drv->request_release(drv); | ||
992 | mutex_unlock(&dev->core->lock); | ||
993 | return -ENOMEM; | ||
994 | } | ||
995 | v4l2_fh_init(&fh->fh, vdev); | ||
996 | file->private_data = fh; | ||
997 | fh->dev = dev; | ||
998 | |||
999 | videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops, | ||
1000 | &dev->pci->dev, &dev->slock, | ||
1001 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | ||
1002 | V4L2_FIELD_INTERLACED, | ||
1003 | sizeof(struct cx88_buffer), | ||
1004 | fh, NULL); | ||
1005 | |||
1006 | /* FIXME: locking against other video device */ | ||
1007 | cx88_set_scale(dev->core, dev->width, dev->height, | ||
1008 | fh->mpegq.field); | ||
1009 | |||
1010 | dev->core->mpeg_users++; | ||
1011 | mutex_unlock(&dev->core->lock); | ||
1012 | v4l2_fh_add(&fh->fh); | ||
1013 | return 0; | ||
1014 | } | ||
1015 | |||
1016 | static int mpeg_release(struct file *file) | ||
1017 | { | ||
1018 | struct cx8802_fh *fh = file->private_data; | ||
1019 | struct cx8802_dev *dev = fh->dev; | ||
1020 | struct cx8802_driver *drv = NULL; | ||
1021 | |||
1022 | mutex_lock(&dev->core->lock); | ||
1023 | |||
1024 | if (dev->mpeg_active && dev->core->mpeg_users == 1) | ||
1025 | blackbird_stop_codec(dev); | ||
1026 | |||
1027 | cx8802_cancel_buffers(fh->dev); | ||
1028 | /* stop mpeg capture */ | ||
1029 | videobuf_stop(&fh->mpegq); | ||
1030 | |||
1031 | videobuf_mmap_free(&fh->mpegq); | ||
1032 | |||
1033 | v4l2_fh_del(&fh->fh); | ||
1034 | v4l2_fh_exit(&fh->fh); | ||
1035 | file->private_data = NULL; | ||
1036 | kfree(fh); | ||
1037 | |||
1038 | /* Make sure we release the hardware */ | ||
1039 | drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD); | ||
1040 | WARN_ON(!drv); | ||
1041 | if (drv) | ||
1042 | drv->request_release(drv); | ||
1043 | |||
1044 | dev->core->mpeg_users--; | ||
1045 | |||
1046 | mutex_unlock(&dev->core->lock); | ||
1047 | |||
1048 | return 0; | ||
1049 | } | ||
1050 | |||
1051 | static ssize_t | ||
1052 | mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos) | ||
1053 | { | ||
1054 | struct cx8802_fh *fh = file->private_data; | ||
1055 | struct cx8802_dev *dev = fh->dev; | ||
1056 | |||
1057 | if (!dev->mpeg_active) | ||
1058 | blackbird_start_codec(file, fh); | ||
1059 | |||
1060 | return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0, | ||
1061 | file->f_flags & O_NONBLOCK); | ||
1062 | } | ||
1063 | |||
1064 | static unsigned int | ||
1065 | mpeg_poll(struct file *file, struct poll_table_struct *wait) | ||
1066 | { | ||
1067 | unsigned long req_events = poll_requested_events(wait); | ||
1068 | struct cx8802_fh *fh = file->private_data; | ||
1069 | struct cx8802_dev *dev = fh->dev; | ||
1070 | |||
1071 | if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM))) | ||
1072 | blackbird_start_codec(file, fh); | ||
1073 | |||
1074 | return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait); | ||
1075 | } | ||
1076 | |||
1077 | static int | ||
1078 | mpeg_mmap(struct file *file, struct vm_area_struct * vma) | ||
1079 | { | ||
1080 | struct cx8802_fh *fh = file->private_data; | ||
1081 | 1009 | ||
1082 | return videobuf_mmap_mapper(&fh->mpegq, vma); | 1010 | return cx88_set_tvnorm(core, id); |
1083 | } | 1011 | } |
1084 | 1012 | ||
1085 | static const struct v4l2_file_operations mpeg_fops = | 1013 | static const struct v4l2_file_operations mpeg_fops = |
1086 | { | 1014 | { |
1087 | .owner = THIS_MODULE, | 1015 | .owner = THIS_MODULE, |
1088 | .open = mpeg_open, | 1016 | .open = v4l2_fh_open, |
1089 | .release = mpeg_release, | 1017 | .release = vb2_fop_release, |
1090 | .read = mpeg_read, | 1018 | .read = vb2_fop_read, |
1091 | .poll = mpeg_poll, | 1019 | .poll = vb2_fop_poll, |
1092 | .mmap = mpeg_mmap, | 1020 | .mmap = vb2_fop_mmap, |
1093 | .unlocked_ioctl = video_ioctl2, | 1021 | .unlocked_ioctl = video_ioctl2, |
1094 | }; | 1022 | }; |
1095 | 1023 | ||
@@ -1099,12 +1027,12 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | |||
1099 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1027 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
1100 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, | 1028 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap, |
1101 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 1029 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
1102 | .vidioc_reqbufs = vidioc_reqbufs, | 1030 | .vidioc_reqbufs = vb2_ioctl_reqbufs, |
1103 | .vidioc_querybuf = vidioc_querybuf, | 1031 | .vidioc_querybuf = vb2_ioctl_querybuf, |
1104 | .vidioc_qbuf = vidioc_qbuf, | 1032 | .vidioc_qbuf = vb2_ioctl_qbuf, |
1105 | .vidioc_dqbuf = vidioc_dqbuf, | 1033 | .vidioc_dqbuf = vb2_ioctl_dqbuf, |
1106 | .vidioc_streamon = vidioc_streamon, | 1034 | .vidioc_streamon = vb2_ioctl_streamon, |
1107 | .vidioc_streamoff = vidioc_streamoff, | 1035 | .vidioc_streamoff = vb2_ioctl_streamoff, |
1108 | .vidioc_s_frequency = vidioc_s_frequency, | 1036 | .vidioc_s_frequency = vidioc_s_frequency, |
1109 | .vidioc_log_status = vidioc_log_status, | 1037 | .vidioc_log_status = vidioc_log_status, |
1110 | .vidioc_enum_input = vidioc_enum_input, | 1038 | .vidioc_enum_input = vidioc_enum_input, |
@@ -1189,11 +1117,12 @@ static int blackbird_register_video(struct cx8802_dev *dev) | |||
1189 | { | 1117 | { |
1190 | int err; | 1118 | int err; |
1191 | 1119 | ||
1192 | dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci, | 1120 | dev->mpeg_dev = cx88_vdev_init(dev->core, dev->pci, |
1193 | &cx8802_mpeg_template,"mpeg"); | 1121 | &cx8802_mpeg_template, "mpeg"); |
1194 | dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl; | 1122 | dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl; |
1195 | video_set_drvdata(dev->mpeg_dev, dev); | 1123 | video_set_drvdata(dev->mpeg_dev, dev); |
1196 | err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1); | 1124 | dev->mpeg_dev->queue = &dev->vb2_mpegq; |
1125 | err = video_register_device(dev->mpeg_dev, VFL_TYPE_GRABBER, -1); | ||
1197 | if (err < 0) { | 1126 | if (err < 0) { |
1198 | printk(KERN_INFO "%s/2: can't register mpeg device\n", | 1127 | printk(KERN_INFO "%s/2: can't register mpeg device\n", |
1199 | dev->core->name); | 1128 | dev->core->name); |
@@ -1210,6 +1139,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1210 | { | 1139 | { |
1211 | struct cx88_core *core = drv->core; | 1140 | struct cx88_core *core = drv->core; |
1212 | struct cx8802_dev *dev = core->dvbdev; | 1141 | struct cx8802_dev *dev = core->dvbdev; |
1142 | struct vb2_queue *q; | ||
1213 | int err; | 1143 | int err; |
1214 | 1144 | ||
1215 | dprintk( 1, "%s\n", __func__); | 1145 | dprintk( 1, "%s\n", __func__); |
@@ -1223,15 +1153,9 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1223 | if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD)) | 1153 | if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD)) |
1224 | goto fail_core; | 1154 | goto fail_core; |
1225 | 1155 | ||
1226 | dev->width = 720; | ||
1227 | if (core->tvnorm & V4L2_STD_525_60) { | ||
1228 | dev->height = 480; | ||
1229 | } else { | ||
1230 | dev->height = 576; | ||
1231 | } | ||
1232 | dev->cxhdl.port = CX2341X_PORT_STREAMING; | 1156 | dev->cxhdl.port = CX2341X_PORT_STREAMING; |
1233 | dev->cxhdl.width = dev->width; | 1157 | dev->cxhdl.width = core->width; |
1234 | dev->cxhdl.height = dev->height; | 1158 | dev->cxhdl.height = core->height; |
1235 | dev->cxhdl.func = blackbird_mbox_func; | 1159 | dev->cxhdl.func = blackbird_mbox_func; |
1236 | dev->cxhdl.priv = dev; | 1160 | dev->cxhdl.priv = dev; |
1237 | err = cx2341x_handler_init(&dev->cxhdl, 36); | 1161 | err = cx2341x_handler_init(&dev->cxhdl, 36); |
@@ -1250,13 +1174,30 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv) | |||
1250 | // init_controls(core); | 1174 | // init_controls(core); |
1251 | cx88_set_tvnorm(core,core->tvnorm); | 1175 | cx88_set_tvnorm(core,core->tvnorm); |
1252 | cx88_video_mux(core,0); | 1176 | cx88_video_mux(core,0); |
1253 | cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576); | 1177 | cx2341x_handler_set_50hz(&dev->cxhdl, core->height == 576); |
1254 | cx2341x_handler_setup(&dev->cxhdl); | 1178 | cx2341x_handler_setup(&dev->cxhdl); |
1179 | |||
1180 | q = &dev->vb2_mpegq; | ||
1181 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1182 | q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ; | ||
1183 | q->gfp_flags = GFP_DMA32; | ||
1184 | q->min_buffers_needed = 2; | ||
1185 | q->drv_priv = dev; | ||
1186 | q->buf_struct_size = sizeof(struct cx88_buffer); | ||
1187 | q->ops = &blackbird_qops; | ||
1188 | q->mem_ops = &vb2_dma_sg_memops; | ||
1189 | q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; | ||
1190 | q->lock = &core->lock; | ||
1191 | |||
1192 | err = vb2_queue_init(q); | ||
1193 | if (err < 0) | ||
1194 | goto fail_core; | ||
1195 | |||
1255 | blackbird_register_video(dev); | 1196 | blackbird_register_video(dev); |
1256 | 1197 | ||
1257 | return 0; | 1198 | return 0; |
1258 | 1199 | ||
1259 | fail_core: | 1200 | fail_core: |
1260 | return err; | 1201 | return err; |
1261 | } | 1202 | } |
1262 | 1203 | ||