Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

media: rcar-vin: Add support for V4L2_FIELD_SEQ_{TB,BT}

The hardware does not support capturing the field types
V4L2_FIELD_SEQ_TB and V4L2_FIELD_SEQ_BT. To capture in these formats the
driver needs to adjust the offset of the capture buffer and capture
twice to each vb2 buffer.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>

authored by

Niklas Söderlund and committed by
Mauro Carvalho Chehab
7e0cfdad e72b7359

+83 -9
+59 -9
drivers/media/platform/rcar-vin/rcar-dma.c
··· 535 535 536 536 /* Set scaling coefficient */ 537 537 crop_height = vin->crop.height; 538 - if (V4L2_FIELD_IS_INTERLACED(vin->format.field)) 538 + if (V4L2_FIELD_HAS_BOTH(vin->format.field)) 539 539 crop_height *= 2; 540 540 541 541 ys = 0; ··· 564 564 rvin_write(vin, 0, VNSLPOC_REG); 565 565 rvin_write(vin, vin->format.width - 1, VNEPPOC_REG); 566 566 567 - if (V4L2_FIELD_IS_INTERLACED(vin->format.field)) 567 + if (V4L2_FIELD_HAS_BOTH(vin->format.field)) 568 568 rvin_write(vin, vin->format.height / 2 - 1, VNELPOC_REG); 569 569 else 570 570 rvin_write(vin, vin->format.height - 1, VNELPOC_REG); ··· 626 626 case V4L2_FIELD_INTERLACED_BT: 627 627 vnmc = VNMC_IM_FULL | VNMC_FOC; 628 628 break; 629 + case V4L2_FIELD_SEQ_TB: 630 + case V4L2_FIELD_SEQ_BT: 629 631 case V4L2_FIELD_NONE: 630 632 vnmc = VNMC_IM_ODD_EVEN; 631 633 progressive = true; ··· 844 842 struct rvin_buffer *buf; 845 843 struct vb2_v4l2_buffer *vbuf; 846 844 dma_addr_t phys_addr; 845 + int prev; 847 846 848 847 /* A already populated slot shall never be overwritten. */ 849 848 if (WARN_ON(vin->buf_hw[slot].buffer)) 850 849 return; 851 850 852 - vin_dbg(vin, "Filling HW slot: %d\n", slot); 851 + prev = (slot == 0 ? HW_BUFFER_NUM : slot) - 1; 853 852 854 - if (list_empty(&vin->buf_list)) { 853 + if (vin->buf_hw[prev].type == HALF_TOP) { 854 + vbuf = vin->buf_hw[prev].buffer; 855 + vin->buf_hw[slot].buffer = vbuf; 856 + vin->buf_hw[slot].type = HALF_BOTTOM; 857 + switch (vin->format.pixelformat) { 858 + case V4L2_PIX_FMT_NV12: 859 + case V4L2_PIX_FMT_NV16: 860 + phys_addr = vin->buf_hw[prev].phys + 861 + vin->format.sizeimage / 4; 862 + break; 863 + default: 864 + phys_addr = vin->buf_hw[prev].phys + 865 + vin->format.sizeimage / 2; 866 + break; 867 + } 868 + } else if (list_empty(&vin->buf_list)) { 855 869 vin->buf_hw[slot].buffer = NULL; 870 + vin->buf_hw[slot].type = FULL; 856 871 phys_addr = vin->scratch_phys; 857 872 } else { 858 873 /* Keep track of buffer we give to HW */ ··· 878 859 list_del_init(to_buf_list(vbuf)); 879 860 vin->buf_hw[slot].buffer = vbuf; 880 861 862 + vin->buf_hw[slot].type = 863 + V4L2_FIELD_IS_SEQUENTIAL(vin->format.field) ? 864 + HALF_TOP : FULL; 865 + 881 866 /* Setup DMA */ 882 867 phys_addr = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0); 883 868 } 884 869 870 + vin_dbg(vin, "Filling HW slot: %d type: %d buffer: %p\n", 871 + slot, vin->buf_hw[slot].type, vin->buf_hw[slot].buffer); 872 + 873 + vin->buf_hw[slot].phys = phys_addr; 885 874 rvin_set_slot_addr(vin, slot, phys_addr); 886 875 } 887 876 888 877 static int rvin_capture_start(struct rvin_dev *vin) 889 878 { 890 879 int slot, ret; 880 + 881 + for (slot = 0; slot < HW_BUFFER_NUM; slot++) { 882 + vin->buf_hw[slot].buffer = NULL; 883 + vin->buf_hw[slot].type = FULL; 884 + } 891 885 892 886 for (slot = 0; slot < HW_BUFFER_NUM; slot++) 893 887 rvin_fill_hw_slot(vin, slot); ··· 986 954 987 955 /* Capture frame */ 988 956 if (vin->buf_hw[slot].buffer) { 957 + /* 958 + * Nothing to do but refill the hardware slot if 959 + * capture only filled first half of vb2 buffer. 960 + */ 961 + if (vin->buf_hw[slot].type == HALF_TOP) { 962 + vin->buf_hw[slot].buffer = NULL; 963 + rvin_fill_hw_slot(vin, slot); 964 + goto done; 965 + } 966 + 989 967 vin->buf_hw[slot].buffer->field = 990 968 rvin_get_active_field(vin, vnms); 991 969 vin->buf_hw[slot].buffer->sequence = vin->sequence; ··· 1023 981 enum vb2_buffer_state state) 1024 982 { 1025 983 struct rvin_buffer *buf, *node; 1026 - int i; 984 + struct vb2_v4l2_buffer *freed[HW_BUFFER_NUM]; 985 + unsigned int i, n; 1027 986 1028 987 for (i = 0; i < HW_BUFFER_NUM; i++) { 1029 - if (vin->buf_hw[i].buffer) { 1030 - vb2_buffer_done(&vin->buf_hw[i].buffer->vb2_buf, 1031 - state); 1032 - vin->buf_hw[i].buffer = NULL; 988 + freed[i] = vin->buf_hw[i].buffer; 989 + vin->buf_hw[i].buffer = NULL; 990 + 991 + for (n = 0; n < i; n++) { 992 + if (freed[i] == freed[n]) { 993 + freed[i] = NULL; 994 + break; 995 + } 1033 996 } 997 + 998 + if (freed[i]) 999 + vb2_buffer_done(&freed[i]->vb2_buf, state); 1034 1000 } 1035 1001 1036 1002 list_for_each_entry_safe(buf, node, &vin->buf_list, list) {
+5
drivers/media/platform/rcar-vin/rcar-v4l2.c
··· 118 118 break; 119 119 } 120 120 121 + if (V4L2_FIELD_IS_SEQUENTIAL(pix->field)) 122 + align = 0x80; 123 + 121 124 return ALIGN(pix->width, align) * fmt->bpp; 122 125 } 123 126 ··· 151 148 case V4L2_FIELD_INTERLACED_BT: 152 149 case V4L2_FIELD_INTERLACED: 153 150 case V4L2_FIELD_ALTERNATE: 151 + case V4L2_FIELD_SEQ_TB: 152 + case V4L2_FIELD_SEQ_BT: 154 153 break; 155 154 default: 156 155 pix->field = RVIN_DEFAULT_FIELD;
+19
drivers/media/platform/rcar-vin/rcar-vin.h
··· 61 61 }; 62 62 63 63 /** 64 + * enum rvin_buffer_type 65 + * 66 + * Describes how a buffer is given to the hardware. To be able 67 + * to capture SEQ_TB/BT it's needed to capture to the same vb2 68 + * buffer twice so the type of buffer needs to be kept. 69 + * 70 + * FULL - One capture fills the whole vb2 buffer 71 + * HALF_TOP - One capture fills the top half of the vb2 buffer 72 + * HALF_BOTTOM - One capture fills the bottom half of the vb2 buffer 73 + */ 74 + enum rvin_buffer_type { 75 + FULL, 76 + HALF_TOP, 77 + HALF_BOTTOM, 78 + }; 79 + 80 + /** 64 81 * struct rvin_video_format - Data format stored in memory 65 82 * @fourcc: Pixelformat 66 83 * @bpp: Bytes per pixel ··· 223 206 spinlock_t qlock; 224 207 struct { 225 208 struct vb2_v4l2_buffer *buffer; 209 + enum rvin_buffer_type type; 210 + dma_addr_t phys; 226 211 } buf_hw[HW_BUFFER_NUM]; 227 212 struct list_head buf_list; 228 213 unsigned int sequence;