| .. | .. |
|---|
| 85 | 85 | #define VNMC_INF_YUV8_BT601 (1 << 16) |
|---|
| 86 | 86 | #define VNMC_INF_YUV10_BT656 (2 << 16) |
|---|
| 87 | 87 | #define VNMC_INF_YUV10_BT601 (3 << 16) |
|---|
| 88 | +#define VNMC_INF_RAW8 (4 << 16) |
|---|
| 88 | 89 | #define VNMC_INF_YUV16 (5 << 16) |
|---|
| 89 | 90 | #define VNMC_INF_RGB888 (6 << 16) |
|---|
| 90 | 91 | #define VNMC_VUP (1 << 10) |
|---|
| .. | .. |
|---|
| 111 | 112 | #define VNIE_EFE (1 << 1) |
|---|
| 112 | 113 | |
|---|
| 113 | 114 | /* Video n Data Mode Register bits */ |
|---|
| 115 | +#define VNDMR_A8BIT(n) (((n) & 0xff) << 24) |
|---|
| 116 | +#define VNDMR_A8BIT_MASK (0xff << 24) |
|---|
| 114 | 117 | #define VNDMR_EXRGB (1 << 8) |
|---|
| 115 | 118 | #define VNDMR_BPSM (1 << 4) |
|---|
| 119 | +#define VNDMR_ABIT (1 << 2) |
|---|
| 116 | 120 | #define VNDMR_DTMD_YCSEP (1 << 1) |
|---|
| 117 | | -#define VNDMR_DTMD_ARGB1555 (1 << 0) |
|---|
| 121 | +#define VNDMR_DTMD_ARGB (1 << 0) |
|---|
| 122 | +#define VNDMR_DTMD_YCSEP_420 (3 << 0) |
|---|
| 118 | 123 | |
|---|
| 119 | 124 | /* Video n Data Mode Register 2 bits */ |
|---|
| 120 | 125 | #define VNDMR2_VPS (1 << 30) |
|---|
| 121 | 126 | #define VNDMR2_HPS (1 << 29) |
|---|
| 122 | 127 | #define VNDMR2_CES (1 << 28) |
|---|
| 128 | +#define VNDMR2_YDS (1 << 22) |
|---|
| 123 | 129 | #define VNDMR2_FTEV (1 << 17) |
|---|
| 124 | 130 | #define VNDMR2_VLV(n) ((n & 0xf) << 12) |
|---|
| 125 | 131 | |
|---|
| .. | .. |
|---|
| 486 | 492 | } |
|---|
| 487 | 493 | |
|---|
| 488 | 494 | /* Use previous value if its XS value is closer */ |
|---|
| 489 | | - if (p_prev_set && p_set && |
|---|
| 495 | + if (p_prev_set && |
|---|
| 490 | 496 | xs - p_prev_set->xs_value < p_set->xs_value - xs) |
|---|
| 491 | 497 | p_set = p_prev_set; |
|---|
| 492 | 498 | |
|---|
| .. | .. |
|---|
| 526 | 532 | |
|---|
| 527 | 533 | static void rvin_crop_scale_comp_gen2(struct rvin_dev *vin) |
|---|
| 528 | 534 | { |
|---|
| 535 | + unsigned int crop_height; |
|---|
| 529 | 536 | u32 xs, ys; |
|---|
| 530 | 537 | |
|---|
| 531 | 538 | /* Set scaling coefficient */ |
|---|
| 539 | + crop_height = vin->crop.height; |
|---|
| 540 | + if (V4L2_FIELD_HAS_BOTH(vin->format.field)) |
|---|
| 541 | + crop_height *= 2; |
|---|
| 542 | + |
|---|
| 532 | 543 | ys = 0; |
|---|
| 533 | | - if (vin->crop.height != vin->compose.height) |
|---|
| 534 | | - ys = (4096 * vin->crop.height) / vin->compose.height; |
|---|
| 544 | + if (crop_height != vin->compose.height) |
|---|
| 545 | + ys = (4096 * crop_height) / vin->compose.height; |
|---|
| 535 | 546 | rvin_write(vin, ys, VNYS_REG); |
|---|
| 536 | 547 | |
|---|
| 537 | 548 | xs = 0; |
|---|
| .. | .. |
|---|
| 554 | 565 | rvin_write(vin, 0, VNSPPOC_REG); |
|---|
| 555 | 566 | rvin_write(vin, 0, VNSLPOC_REG); |
|---|
| 556 | 567 | rvin_write(vin, vin->format.width - 1, VNEPPOC_REG); |
|---|
| 557 | | - switch (vin->format.field) { |
|---|
| 558 | | - case V4L2_FIELD_INTERLACED: |
|---|
| 559 | | - case V4L2_FIELD_INTERLACED_TB: |
|---|
| 560 | | - case V4L2_FIELD_INTERLACED_BT: |
|---|
| 568 | + |
|---|
| 569 | + if (V4L2_FIELD_HAS_BOTH(vin->format.field)) |
|---|
| 561 | 570 | rvin_write(vin, vin->format.height / 2 - 1, VNELPOC_REG); |
|---|
| 562 | | - break; |
|---|
| 563 | | - default: |
|---|
| 571 | + else |
|---|
| 564 | 572 | rvin_write(vin, vin->format.height - 1, VNELPOC_REG); |
|---|
| 565 | | - break; |
|---|
| 566 | | - } |
|---|
| 567 | 573 | |
|---|
| 568 | 574 | vin_dbg(vin, |
|---|
| 569 | 575 | "Pre-Clip: %ux%u@%u:%u YS: %d XS: %d Post-Clip: %ux%u@%u:%u\n", |
|---|
| .. | .. |
|---|
| 574 | 580 | |
|---|
| 575 | 581 | void rvin_crop_scale_comp(struct rvin_dev *vin) |
|---|
| 576 | 582 | { |
|---|
| 583 | + const struct rvin_video_format *fmt; |
|---|
| 584 | + u32 stride; |
|---|
| 585 | + |
|---|
| 577 | 586 | /* Set Start/End Pixel/Line Pre-Clip */ |
|---|
| 578 | 587 | rvin_write(vin, vin->crop.left, VNSPPRC_REG); |
|---|
| 579 | 588 | rvin_write(vin, vin->crop.left + vin->crop.width - 1, VNEPPRC_REG); |
|---|
| 580 | | - |
|---|
| 581 | | - switch (vin->format.field) { |
|---|
| 582 | | - case V4L2_FIELD_INTERLACED: |
|---|
| 583 | | - case V4L2_FIELD_INTERLACED_TB: |
|---|
| 584 | | - case V4L2_FIELD_INTERLACED_BT: |
|---|
| 585 | | - rvin_write(vin, vin->crop.top / 2, VNSLPRC_REG); |
|---|
| 586 | | - rvin_write(vin, (vin->crop.top + vin->crop.height) / 2 - 1, |
|---|
| 587 | | - VNELPRC_REG); |
|---|
| 588 | | - break; |
|---|
| 589 | | - default: |
|---|
| 590 | | - rvin_write(vin, vin->crop.top, VNSLPRC_REG); |
|---|
| 591 | | - rvin_write(vin, vin->crop.top + vin->crop.height - 1, |
|---|
| 592 | | - VNELPRC_REG); |
|---|
| 593 | | - break; |
|---|
| 594 | | - } |
|---|
| 589 | + rvin_write(vin, vin->crop.top, VNSLPRC_REG); |
|---|
| 590 | + rvin_write(vin, vin->crop.top + vin->crop.height - 1, VNELPRC_REG); |
|---|
| 595 | 591 | |
|---|
| 596 | 592 | /* TODO: Add support for the UDS scaler. */ |
|---|
| 597 | 593 | if (vin->info->model != RCAR_GEN3) |
|---|
| 598 | 594 | rvin_crop_scale_comp_gen2(vin); |
|---|
| 599 | 595 | |
|---|
| 600 | | - if (vin->format.pixelformat == V4L2_PIX_FMT_NV16) |
|---|
| 601 | | - rvin_write(vin, ALIGN(vin->format.width, 0x20), VNIS_REG); |
|---|
| 602 | | - else |
|---|
| 603 | | - rvin_write(vin, ALIGN(vin->format.width, 0x10), VNIS_REG); |
|---|
| 596 | + fmt = rvin_format_from_pixel(vin, vin->format.pixelformat); |
|---|
| 597 | + stride = vin->format.bytesperline / fmt->bpp; |
|---|
| 598 | + |
|---|
| 599 | + /* For RAW8 format bpp is 1, but the hardware process RAW8 |
|---|
| 600 | + * format in 2 pixel unit hence configure VNIS_REG as stride / 2. |
|---|
| 601 | + */ |
|---|
| 602 | + switch (vin->format.pixelformat) { |
|---|
| 603 | + case V4L2_PIX_FMT_SBGGR8: |
|---|
| 604 | + case V4L2_PIX_FMT_SGBRG8: |
|---|
| 605 | + case V4L2_PIX_FMT_SGRBG8: |
|---|
| 606 | + case V4L2_PIX_FMT_SRGGB8: |
|---|
| 607 | + stride /= 2; |
|---|
| 608 | + break; |
|---|
| 609 | + default: |
|---|
| 610 | + break; |
|---|
| 611 | + } |
|---|
| 612 | + |
|---|
| 613 | + rvin_write(vin, stride, VNIS_REG); |
|---|
| 604 | 614 | } |
|---|
| 605 | 615 | |
|---|
| 606 | 616 | /* ----------------------------------------------------------------------------- |
|---|
| .. | .. |
|---|
| 632 | 642 | case V4L2_FIELD_INTERLACED_BT: |
|---|
| 633 | 643 | vnmc = VNMC_IM_FULL | VNMC_FOC; |
|---|
| 634 | 644 | break; |
|---|
| 645 | + case V4L2_FIELD_SEQ_TB: |
|---|
| 646 | + case V4L2_FIELD_SEQ_BT: |
|---|
| 635 | 647 | case V4L2_FIELD_NONE: |
|---|
| 636 | 648 | vnmc = VNMC_IM_ODD_EVEN; |
|---|
| 637 | 649 | progressive = true; |
|---|
| 650 | + break; |
|---|
| 651 | + case V4L2_FIELD_ALTERNATE: |
|---|
| 652 | + vnmc = VNMC_IM_ODD_EVEN; |
|---|
| 638 | 653 | break; |
|---|
| 639 | 654 | default: |
|---|
| 640 | 655 | vnmc = VNMC_IM_ODD; |
|---|
| .. | .. |
|---|
| 677 | 692 | |
|---|
| 678 | 693 | input_is_yuv = true; |
|---|
| 679 | 694 | break; |
|---|
| 695 | + case MEDIA_BUS_FMT_SBGGR8_1X8: |
|---|
| 696 | + case MEDIA_BUS_FMT_SGBRG8_1X8: |
|---|
| 697 | + case MEDIA_BUS_FMT_SGRBG8_1X8: |
|---|
| 698 | + case MEDIA_BUS_FMT_SRGGB8_1X8: |
|---|
| 699 | + vnmc |= VNMC_INF_RAW8; |
|---|
| 700 | + break; |
|---|
| 680 | 701 | default: |
|---|
| 681 | 702 | break; |
|---|
| 682 | 703 | } |
|---|
| 683 | 704 | |
|---|
| 684 | | - /* Enable VSYNC Field Toogle mode after one VSYNC input */ |
|---|
| 705 | + /* Enable VSYNC Field Toggle mode after one VSYNC input */ |
|---|
| 685 | 706 | if (vin->info->model == RCAR_GEN3) |
|---|
| 686 | 707 | dmr2 = VNDMR2_FTEV; |
|---|
| 687 | 708 | else |
|---|
| .. | .. |
|---|
| 689 | 710 | |
|---|
| 690 | 711 | if (!vin->is_csi) { |
|---|
| 691 | 712 | /* Hsync Signal Polarity Select */ |
|---|
| 692 | | - if (!(vin->parallel->mbus_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) |
|---|
| 713 | + if (!(vin->parallel->bus.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) |
|---|
| 693 | 714 | dmr2 |= VNDMR2_HPS; |
|---|
| 694 | 715 | |
|---|
| 695 | 716 | /* Vsync Signal Polarity Select */ |
|---|
| 696 | | - if (!(vin->parallel->mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) |
|---|
| 717 | + if (!(vin->parallel->bus.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) |
|---|
| 697 | 718 | dmr2 |= VNDMR2_VPS; |
|---|
| 698 | 719 | |
|---|
| 699 | 720 | /* Data Enable Polarity Select */ |
|---|
| 700 | | - if (vin->parallel->mbus_flags & V4L2_MBUS_DATA_ENABLE_LOW) |
|---|
| 721 | + if (vin->parallel->bus.flags & V4L2_MBUS_DATA_ENABLE_LOW) |
|---|
| 701 | 722 | dmr2 |= VNDMR2_CES; |
|---|
| 723 | + |
|---|
| 724 | + switch (vin->mbus_code) { |
|---|
| 725 | + case MEDIA_BUS_FMT_UYVY8_2X8: |
|---|
| 726 | + if (vin->parallel->bus.bus_width == 8 && |
|---|
| 727 | + vin->parallel->bus.data_shift == 8) |
|---|
| 728 | + dmr2 |= VNDMR2_YDS; |
|---|
| 729 | + break; |
|---|
| 730 | + default: |
|---|
| 731 | + break; |
|---|
| 732 | + } |
|---|
| 702 | 733 | } |
|---|
| 703 | 734 | |
|---|
| 704 | 735 | /* |
|---|
| 705 | 736 | * Output format |
|---|
| 706 | 737 | */ |
|---|
| 707 | 738 | switch (vin->format.pixelformat) { |
|---|
| 739 | + case V4L2_PIX_FMT_NV12: |
|---|
| 708 | 740 | case V4L2_PIX_FMT_NV16: |
|---|
| 709 | 741 | rvin_write(vin, |
|---|
| 710 | | - ALIGN(vin->format.width * vin->format.height, 0x80), |
|---|
| 711 | | - VNUVAOF_REG); |
|---|
| 712 | | - dmr = VNDMR_DTMD_YCSEP; |
|---|
| 742 | + ALIGN(vin->format.bytesperline * vin->format.height, |
|---|
| 743 | + 0x80), VNUVAOF_REG); |
|---|
| 744 | + dmr = vin->format.pixelformat == V4L2_PIX_FMT_NV12 ? |
|---|
| 745 | + VNDMR_DTMD_YCSEP_420 : VNDMR_DTMD_YCSEP; |
|---|
| 713 | 746 | output_is_yuv = true; |
|---|
| 714 | 747 | break; |
|---|
| 715 | 748 | case V4L2_PIX_FMT_YUYV: |
|---|
| .. | .. |
|---|
| 721 | 754 | output_is_yuv = true; |
|---|
| 722 | 755 | break; |
|---|
| 723 | 756 | case V4L2_PIX_FMT_XRGB555: |
|---|
| 724 | | - dmr = VNDMR_DTMD_ARGB1555; |
|---|
| 757 | + dmr = VNDMR_DTMD_ARGB; |
|---|
| 725 | 758 | break; |
|---|
| 726 | 759 | case V4L2_PIX_FMT_RGB565: |
|---|
| 727 | 760 | dmr = 0; |
|---|
| .. | .. |
|---|
| 729 | 762 | case V4L2_PIX_FMT_XBGR32: |
|---|
| 730 | 763 | /* Note: not supported on M1 */ |
|---|
| 731 | 764 | dmr = VNDMR_EXRGB; |
|---|
| 765 | + break; |
|---|
| 766 | + case V4L2_PIX_FMT_ARGB555: |
|---|
| 767 | + dmr = (vin->alpha ? VNDMR_ABIT : 0) | VNDMR_DTMD_ARGB; |
|---|
| 768 | + break; |
|---|
| 769 | + case V4L2_PIX_FMT_ABGR32: |
|---|
| 770 | + dmr = VNDMR_A8BIT(vin->alpha) | VNDMR_EXRGB | VNDMR_DTMD_ARGB; |
|---|
| 771 | + break; |
|---|
| 772 | + case V4L2_PIX_FMT_SBGGR8: |
|---|
| 773 | + case V4L2_PIX_FMT_SGBRG8: |
|---|
| 774 | + case V4L2_PIX_FMT_SGRBG8: |
|---|
| 775 | + case V4L2_PIX_FMT_SRGGB8: |
|---|
| 776 | + dmr = 0; |
|---|
| 732 | 777 | break; |
|---|
| 733 | 778 | default: |
|---|
| 734 | 779 | vin_err(vin, "Invalid pixelformat (0x%x)\n", |
|---|
| .. | .. |
|---|
| 788 | 833 | return rvin_read(vin, VNMS_REG) & VNMS_CA; |
|---|
| 789 | 834 | } |
|---|
| 790 | 835 | |
|---|
| 836 | +static enum v4l2_field rvin_get_active_field(struct rvin_dev *vin, u32 vnms) |
|---|
| 837 | +{ |
|---|
| 838 | + if (vin->format.field == V4L2_FIELD_ALTERNATE) { |
|---|
| 839 | + /* If FS is set it is an Even field. */ |
|---|
| 840 | + if (vnms & VNMS_FS) |
|---|
| 841 | + return V4L2_FIELD_BOTTOM; |
|---|
| 842 | + return V4L2_FIELD_TOP; |
|---|
| 843 | + } |
|---|
| 844 | + |
|---|
| 845 | + return vin->format.field; |
|---|
| 846 | +} |
|---|
| 847 | + |
|---|
| 791 | 848 | static void rvin_set_slot_addr(struct rvin_dev *vin, int slot, dma_addr_t addr) |
|---|
| 792 | 849 | { |
|---|
| 793 | 850 | const struct rvin_video_format *fmt; |
|---|
| 794 | 851 | int offsetx, offsety; |
|---|
| 795 | 852 | dma_addr_t offset; |
|---|
| 796 | 853 | |
|---|
| 797 | | - fmt = rvin_format_from_pixel(vin->format.pixelformat); |
|---|
| 854 | + fmt = rvin_format_from_pixel(vin, vin->format.pixelformat); |
|---|
| 798 | 855 | |
|---|
| 799 | 856 | /* |
|---|
| 800 | 857 | * There is no HW support for composition do the beast we can |
|---|
| .. | .. |
|---|
| 825 | 882 | struct rvin_buffer *buf; |
|---|
| 826 | 883 | struct vb2_v4l2_buffer *vbuf; |
|---|
| 827 | 884 | dma_addr_t phys_addr; |
|---|
| 885 | + int prev; |
|---|
| 828 | 886 | |
|---|
| 829 | 887 | /* A already populated slot shall never be overwritten. */ |
|---|
| 830 | | - if (WARN_ON(vin->queue_buf[slot] != NULL)) |
|---|
| 888 | + if (WARN_ON(vin->buf_hw[slot].buffer)) |
|---|
| 831 | 889 | return; |
|---|
| 832 | 890 | |
|---|
| 833 | | - vin_dbg(vin, "Filling HW slot: %d\n", slot); |
|---|
| 891 | + prev = (slot == 0 ? HW_BUFFER_NUM : slot) - 1; |
|---|
| 834 | 892 | |
|---|
| 835 | | - if (list_empty(&vin->buf_list)) { |
|---|
| 836 | | - vin->queue_buf[slot] = NULL; |
|---|
| 893 | + if (vin->buf_hw[prev].type == HALF_TOP) { |
|---|
| 894 | + vbuf = vin->buf_hw[prev].buffer; |
|---|
| 895 | + vin->buf_hw[slot].buffer = vbuf; |
|---|
| 896 | + vin->buf_hw[slot].type = HALF_BOTTOM; |
|---|
| 897 | + switch (vin->format.pixelformat) { |
|---|
| 898 | + case V4L2_PIX_FMT_NV12: |
|---|
| 899 | + case V4L2_PIX_FMT_NV16: |
|---|
| 900 | + phys_addr = vin->buf_hw[prev].phys + |
|---|
| 901 | + vin->format.sizeimage / 4; |
|---|
| 902 | + break; |
|---|
| 903 | + default: |
|---|
| 904 | + phys_addr = vin->buf_hw[prev].phys + |
|---|
| 905 | + vin->format.sizeimage / 2; |
|---|
| 906 | + break; |
|---|
| 907 | + } |
|---|
| 908 | + } else if (list_empty(&vin->buf_list)) { |
|---|
| 909 | + vin->buf_hw[slot].buffer = NULL; |
|---|
| 910 | + vin->buf_hw[slot].type = FULL; |
|---|
| 837 | 911 | phys_addr = vin->scratch_phys; |
|---|
| 838 | 912 | } else { |
|---|
| 839 | 913 | /* Keep track of buffer we give to HW */ |
|---|
| 840 | 914 | buf = list_entry(vin->buf_list.next, struct rvin_buffer, list); |
|---|
| 841 | 915 | vbuf = &buf->vb; |
|---|
| 842 | 916 | list_del_init(to_buf_list(vbuf)); |
|---|
| 843 | | - vin->queue_buf[slot] = vbuf; |
|---|
| 917 | + vin->buf_hw[slot].buffer = vbuf; |
|---|
| 918 | + |
|---|
| 919 | + vin->buf_hw[slot].type = |
|---|
| 920 | + V4L2_FIELD_IS_SEQUENTIAL(vin->format.field) ? |
|---|
| 921 | + HALF_TOP : FULL; |
|---|
| 844 | 922 | |
|---|
| 845 | 923 | /* Setup DMA */ |
|---|
| 846 | 924 | phys_addr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); |
|---|
| 847 | 925 | } |
|---|
| 848 | 926 | |
|---|
| 927 | + vin_dbg(vin, "Filling HW slot: %d type: %d buffer: %p\n", |
|---|
| 928 | + slot, vin->buf_hw[slot].type, vin->buf_hw[slot].buffer); |
|---|
| 929 | + |
|---|
| 930 | + vin->buf_hw[slot].phys = phys_addr; |
|---|
| 849 | 931 | rvin_set_slot_addr(vin, slot, phys_addr); |
|---|
| 850 | 932 | } |
|---|
| 851 | 933 | |
|---|
| 852 | 934 | static int rvin_capture_start(struct rvin_dev *vin) |
|---|
| 853 | 935 | { |
|---|
| 854 | 936 | int slot, ret; |
|---|
| 937 | + |
|---|
| 938 | + for (slot = 0; slot < HW_BUFFER_NUM; slot++) { |
|---|
| 939 | + vin->buf_hw[slot].buffer = NULL; |
|---|
| 940 | + vin->buf_hw[slot].type = FULL; |
|---|
| 941 | + } |
|---|
| 855 | 942 | |
|---|
| 856 | 943 | for (slot = 0; slot < HW_BUFFER_NUM; slot++) |
|---|
| 857 | 944 | rvin_fill_hw_slot(vin, slot); |
|---|
| .. | .. |
|---|
| 936 | 1023 | } |
|---|
| 937 | 1024 | |
|---|
| 938 | 1025 | /* Capture frame */ |
|---|
| 939 | | - if (vin->queue_buf[slot]) { |
|---|
| 940 | | - vin->queue_buf[slot]->field = vin->format.field; |
|---|
| 941 | | - vin->queue_buf[slot]->sequence = vin->sequence; |
|---|
| 942 | | - vin->queue_buf[slot]->vb2_buf.timestamp = ktime_get_ns(); |
|---|
| 943 | | - vb2_buffer_done(&vin->queue_buf[slot]->vb2_buf, |
|---|
| 1026 | + if (vin->buf_hw[slot].buffer) { |
|---|
| 1027 | + /* |
|---|
| 1028 | + * Nothing to do but refill the hardware slot if |
|---|
| 1029 | + * capture only filled first half of vb2 buffer. |
|---|
| 1030 | + */ |
|---|
| 1031 | + if (vin->buf_hw[slot].type == HALF_TOP) { |
|---|
| 1032 | + vin->buf_hw[slot].buffer = NULL; |
|---|
| 1033 | + rvin_fill_hw_slot(vin, slot); |
|---|
| 1034 | + goto done; |
|---|
| 1035 | + } |
|---|
| 1036 | + |
|---|
| 1037 | + vin->buf_hw[slot].buffer->field = |
|---|
| 1038 | + rvin_get_active_field(vin, vnms); |
|---|
| 1039 | + vin->buf_hw[slot].buffer->sequence = vin->sequence; |
|---|
| 1040 | + vin->buf_hw[slot].buffer->vb2_buf.timestamp = ktime_get_ns(); |
|---|
| 1041 | + vb2_buffer_done(&vin->buf_hw[slot].buffer->vb2_buf, |
|---|
| 944 | 1042 | VB2_BUF_STATE_DONE); |
|---|
| 945 | | - vin->queue_buf[slot] = NULL; |
|---|
| 1043 | + vin->buf_hw[slot].buffer = NULL; |
|---|
| 946 | 1044 | } else { |
|---|
| 947 | 1045 | /* Scratch buffer was used, dropping frame. */ |
|---|
| 948 | 1046 | vin_dbg(vin, "Dropping frame %u\n", vin->sequence); |
|---|
| .. | .. |
|---|
| 963 | 1061 | enum vb2_buffer_state state) |
|---|
| 964 | 1062 | { |
|---|
| 965 | 1063 | struct rvin_buffer *buf, *node; |
|---|
| 966 | | - int i; |
|---|
| 1064 | + struct vb2_v4l2_buffer *freed[HW_BUFFER_NUM]; |
|---|
| 1065 | + unsigned int i, n; |
|---|
| 967 | 1066 | |
|---|
| 968 | 1067 | for (i = 0; i < HW_BUFFER_NUM; i++) { |
|---|
| 969 | | - if (vin->queue_buf[i]) { |
|---|
| 970 | | - vb2_buffer_done(&vin->queue_buf[i]->vb2_buf, |
|---|
| 971 | | - state); |
|---|
| 972 | | - vin->queue_buf[i] = NULL; |
|---|
| 1068 | + freed[i] = vin->buf_hw[i].buffer; |
|---|
| 1069 | + vin->buf_hw[i].buffer = NULL; |
|---|
| 1070 | + |
|---|
| 1071 | + for (n = 0; n < i; n++) { |
|---|
| 1072 | + if (freed[i] == freed[n]) { |
|---|
| 1073 | + freed[i] = NULL; |
|---|
| 1074 | + break; |
|---|
| 1075 | + } |
|---|
| 973 | 1076 | } |
|---|
| 1077 | + |
|---|
| 1078 | + if (freed[i]) |
|---|
| 1079 | + vb2_buffer_done(&freed[i]->vb2_buf, state); |
|---|
| 974 | 1080 | } |
|---|
| 975 | 1081 | |
|---|
| 976 | 1082 | list_for_each_entry_safe(buf, node, &vin->buf_list, list) { |
|---|
| .. | .. |
|---|
| 1042 | 1148 | case MEDIA_BUS_FMT_UYVY8_2X8: |
|---|
| 1043 | 1149 | case MEDIA_BUS_FMT_UYVY10_2X10: |
|---|
| 1044 | 1150 | case MEDIA_BUS_FMT_RGB888_1X24: |
|---|
| 1045 | | - vin->mbus_code = fmt.format.code; |
|---|
| 1151 | + break; |
|---|
| 1152 | + case MEDIA_BUS_FMT_SBGGR8_1X8: |
|---|
| 1153 | + if (vin->format.pixelformat != V4L2_PIX_FMT_SBGGR8) |
|---|
| 1154 | + return -EPIPE; |
|---|
| 1155 | + break; |
|---|
| 1156 | + case MEDIA_BUS_FMT_SGBRG8_1X8: |
|---|
| 1157 | + if (vin->format.pixelformat != V4L2_PIX_FMT_SGBRG8) |
|---|
| 1158 | + return -EPIPE; |
|---|
| 1159 | + break; |
|---|
| 1160 | + case MEDIA_BUS_FMT_SGRBG8_1X8: |
|---|
| 1161 | + if (vin->format.pixelformat != V4L2_PIX_FMT_SGRBG8) |
|---|
| 1162 | + return -EPIPE; |
|---|
| 1163 | + break; |
|---|
| 1164 | + case MEDIA_BUS_FMT_SRGGB8_1X8: |
|---|
| 1165 | + if (vin->format.pixelformat != V4L2_PIX_FMT_SRGGB8) |
|---|
| 1166 | + return -EPIPE; |
|---|
| 1046 | 1167 | break; |
|---|
| 1047 | 1168 | default: |
|---|
| 1048 | 1169 | return -EPIPE; |
|---|
| 1049 | 1170 | } |
|---|
| 1171 | + vin->mbus_code = fmt.format.code; |
|---|
| 1050 | 1172 | |
|---|
| 1051 | 1173 | switch (fmt.format.field) { |
|---|
| 1052 | 1174 | case V4L2_FIELD_TOP: |
|---|
| .. | .. |
|---|
| 1064 | 1186 | case V4L2_FIELD_TOP: |
|---|
| 1065 | 1187 | case V4L2_FIELD_BOTTOM: |
|---|
| 1066 | 1188 | case V4L2_FIELD_NONE: |
|---|
| 1189 | + case V4L2_FIELD_ALTERNATE: |
|---|
| 1067 | 1190 | break; |
|---|
| 1068 | 1191 | case V4L2_FIELD_INTERLACED_TB: |
|---|
| 1069 | 1192 | case V4L2_FIELD_INTERLACED_BT: |
|---|
| .. | .. |
|---|
| 1273 | 1396 | vin->state = STOPPED; |
|---|
| 1274 | 1397 | |
|---|
| 1275 | 1398 | for (i = 0; i < HW_BUFFER_NUM; i++) |
|---|
| 1276 | | - vin->queue_buf[i] = NULL; |
|---|
| 1399 | + vin->buf_hw[i].buffer = NULL; |
|---|
| 1277 | 1400 | |
|---|
| 1278 | 1401 | /* buffer queue */ |
|---|
| 1279 | 1402 | q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
|---|
| .. | .. |
|---|
| 1343 | 1466 | |
|---|
| 1344 | 1467 | pm_runtime_put(vin->dev); |
|---|
| 1345 | 1468 | |
|---|
| 1346 | | - return ret; |
|---|
| 1469 | + return 0; |
|---|
| 1470 | +} |
|---|
| 1471 | + |
|---|
| 1472 | +void rvin_set_alpha(struct rvin_dev *vin, unsigned int alpha) |
|---|
| 1473 | +{ |
|---|
| 1474 | + unsigned long flags; |
|---|
| 1475 | + u32 dmr; |
|---|
| 1476 | + |
|---|
| 1477 | + spin_lock_irqsave(&vin->qlock, flags); |
|---|
| 1478 | + |
|---|
| 1479 | + vin->alpha = alpha; |
|---|
| 1480 | + |
|---|
| 1481 | + if (vin->state == STOPPED) |
|---|
| 1482 | + goto out; |
|---|
| 1483 | + |
|---|
| 1484 | + switch (vin->format.pixelformat) { |
|---|
| 1485 | + case V4L2_PIX_FMT_ARGB555: |
|---|
| 1486 | + dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_ABIT; |
|---|
| 1487 | + if (vin->alpha) |
|---|
| 1488 | + dmr |= VNDMR_ABIT; |
|---|
| 1489 | + break; |
|---|
| 1490 | + case V4L2_PIX_FMT_ABGR32: |
|---|
| 1491 | + dmr = rvin_read(vin, VNDMR_REG) & ~VNDMR_A8BIT_MASK; |
|---|
| 1492 | + dmr |= VNDMR_A8BIT(vin->alpha); |
|---|
| 1493 | + break; |
|---|
| 1494 | + default: |
|---|
| 1495 | + goto out; |
|---|
| 1496 | + } |
|---|
| 1497 | + |
|---|
| 1498 | + rvin_write(vin, dmr, VNDMR_REG); |
|---|
| 1499 | +out: |
|---|
| 1500 | + spin_unlock_irqrestore(&vin->qlock, flags); |
|---|
| 1347 | 1501 | } |
|---|