hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/media/platform/ti-vpe/vpe.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * TI VPE mem2mem driver, based on the virtual v4l2-mem2mem example driver
34 *
....@@ -11,10 +12,6 @@
1112 * Marek Szyprowski, <m.szyprowski@samsung.com>
1213 *
1314 * Based on the virtual v4l2-mem2mem example device
14
- *
15
- * This program is free software; you can redistribute it and/or modify it
16
- * under the terms of the GNU General Public License version 2 as published by
17
- * the Free Software Foundation
1815 */
1916
2017 #include <linux/delay.h>
....@@ -55,7 +52,7 @@
5552 #define MIN_W 32
5653 #define MIN_H 32
5754 #define MAX_W 2048
58
-#define MAX_H 1184
55
+#define MAX_H 2048
5956
6057 /* required alignments */
6158 #define S_ALIGN 0 /* multiple of 1 */
....@@ -227,7 +224,6 @@
227224
228225 /* driver info for each of the supported video formats */
229226 struct vpe_fmt {
230
- char *name; /* human-readable name */
231227 u32 fourcc; /* standard format identifier */
232228 u8 types; /* CAPTURE and/or OUTPUT */
233229 u8 coplanar; /* set for unpacked Luma and Chroma */
....@@ -237,7 +233,6 @@
237233
238234 static struct vpe_fmt vpe_formats[] = {
239235 {
240
- .name = "NV16 YUV 422 co-planar",
241236 .fourcc = V4L2_PIX_FMT_NV16,
242237 .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
243238 .coplanar = 1,
....@@ -246,7 +241,6 @@
246241 },
247242 },
248243 {
249
- .name = "NV12 YUV 420 co-planar",
250244 .fourcc = V4L2_PIX_FMT_NV12,
251245 .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
252246 .coplanar = 1,
....@@ -255,7 +249,14 @@
255249 },
256250 },
257251 {
258
- .name = "YUYV 422 packed",
252
+ .fourcc = V4L2_PIX_FMT_NV21,
253
+ .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
254
+ .coplanar = 1,
255
+ .vpdma_fmt = { &vpdma_yuv_fmts[VPDMA_DATA_FMT_Y420],
256
+ &vpdma_yuv_fmts[VPDMA_DATA_FMT_CB420],
257
+ },
258
+ },
259
+ {
259260 .fourcc = V4L2_PIX_FMT_YUYV,
260261 .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
261262 .coplanar = 0,
....@@ -263,7 +264,6 @@
263264 },
264265 },
265266 {
266
- .name = "UYVY 422 packed",
267267 .fourcc = V4L2_PIX_FMT_UYVY,
268268 .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT,
269269 .coplanar = 0,
....@@ -271,7 +271,6 @@
271271 },
272272 },
273273 {
274
- .name = "RGB888 packed",
275274 .fourcc = V4L2_PIX_FMT_RGB24,
276275 .types = VPE_FMT_TYPE_CAPTURE,
277276 .coplanar = 0,
....@@ -279,7 +278,6 @@
279278 },
280279 },
281280 {
282
- .name = "ARGB32",
283281 .fourcc = V4L2_PIX_FMT_RGB32,
284282 .types = VPE_FMT_TYPE_CAPTURE,
285283 .coplanar = 0,
....@@ -287,7 +285,6 @@
287285 },
288286 },
289287 {
290
- .name = "BGR888 packed",
291288 .fourcc = V4L2_PIX_FMT_BGR24,
292289 .types = VPE_FMT_TYPE_CAPTURE,
293290 .coplanar = 0,
....@@ -295,7 +292,6 @@
295292 },
296293 },
297294 {
298
- .name = "ABGR32",
299295 .fourcc = V4L2_PIX_FMT_BGR32,
300296 .types = VPE_FMT_TYPE_CAPTURE,
301297 .coplanar = 0,
....@@ -303,7 +299,6 @@
303299 },
304300 },
305301 {
306
- .name = "RGB565",
307302 .fourcc = V4L2_PIX_FMT_RGB565,
308303 .types = VPE_FMT_TYPE_CAPTURE,
309304 .coplanar = 0,
....@@ -311,7 +306,6 @@
311306 },
312307 },
313308 {
314
- .name = "RGB5551",
315309 .fourcc = V4L2_PIX_FMT_RGB555,
316310 .types = VPE_FMT_TYPE_CAPTURE,
317311 .coplanar = 0,
....@@ -325,14 +319,9 @@
325319 * there is one source queue and one destination queue for each m2m context.
326320 */
327321 struct vpe_q_data {
328
- unsigned int width; /* frame width */
329
- unsigned int height; /* frame height */
330
- unsigned int nplanes; /* Current number of planes */
331
- unsigned int bytesperline[VPE_MAX_PLANES]; /* bytes per line in memory */
332
- enum v4l2_colorspace colorspace;
333
- enum v4l2_field field; /* supported field value */
322
+ /* current v4l2 format info */
323
+ struct v4l2_format format;
334324 unsigned int flags;
335
- unsigned int sizeimage[VPE_MAX_PLANES]; /* image size in memory */
336325 struct v4l2_rect c_rect; /* crop/compose rectangle */
337326 struct vpe_fmt *fmt; /* format info */
338327 };
....@@ -342,9 +331,14 @@
342331 #define Q_DATA_MODE_TILED BIT(1)
343332 #define Q_DATA_INTERLACED_ALTERNATE BIT(2)
344333 #define Q_DATA_INTERLACED_SEQ_TB BIT(3)
334
+#define Q_DATA_INTERLACED_SEQ_BT BIT(4)
335
+
336
+#define Q_IS_SEQ_XX (Q_DATA_INTERLACED_SEQ_TB | \
337
+ Q_DATA_INTERLACED_SEQ_BT)
345338
346339 #define Q_IS_INTERLACED (Q_DATA_INTERLACED_ALTERNATE | \
347
- Q_DATA_INTERLACED_SEQ_TB)
340
+ Q_DATA_INTERLACED_SEQ_TB | \
341
+ Q_DATA_INTERLACED_SEQ_BT)
348342
349343 enum {
350344 Q_DATA_SRC = 0,
....@@ -700,7 +694,8 @@
700694 * Cfg Mode 1: YUV422 source, disable upsampler, DEI is de-interlacing.
701695 */
702696
703
- if (fmt->fourcc == V4L2_PIX_FMT_NV12)
697
+ if (fmt->fourcc == V4L2_PIX_FMT_NV12 ||
698
+ fmt->fourcc == V4L2_PIX_FMT_NV21)
704699 cfg_mode = 0;
705700
706701 write_field(us1_reg0, cfg_mode, VPE_US_MODE_MASK, VPE_US_MODE_SHIFT);
....@@ -715,7 +710,8 @@
715710 struct vpe_fmt *fmt = ctx->q_data[Q_DATA_SRC].fmt;
716711 int line_mode = 1;
717712
718
- if (fmt->fourcc == V4L2_PIX_FMT_NV12)
713
+ if (fmt->fourcc == V4L2_PIX_FMT_NV12 ||
714
+ fmt->fourcc == V4L2_PIX_FMT_NV21)
719715 line_mode = 0; /* double lines to line buffer */
720716
721717 /* regs for now */
....@@ -760,11 +756,12 @@
760756 static void set_dst_registers(struct vpe_ctx *ctx)
761757 {
762758 struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr;
763
- enum v4l2_colorspace clrspc = ctx->q_data[Q_DATA_DST].colorspace;
764759 struct vpe_fmt *fmt = ctx->q_data[Q_DATA_DST].fmt;
760
+ const struct v4l2_format_info *finfo;
765761 u32 val = 0;
766762
767
- if (clrspc == V4L2_COLORSPACE_SRGB) {
763
+ finfo = v4l2_format_info(fmt->fourcc);
764
+ if (v4l2_is_format_rgb(finfo)) {
768765 val |= VPE_RGB_OUT_SELECT;
769766 vpdma_set_bg_color(ctx->dev->vpdma,
770767 (struct vpdma_data_format *)fmt->vpdma_fmt[0], 0xff);
....@@ -777,7 +774,8 @@
777774 */
778775 val |= VPE_DS_SRC_DEI_SCALER | VPE_CSC_SRC_DEI_SCALER;
779776
780
- if (fmt->fourcc != V4L2_PIX_FMT_NV12)
777
+ if (fmt->fourcc != V4L2_PIX_FMT_NV12 &&
778
+ fmt->fourcc != V4L2_PIX_FMT_NV21)
781779 val |= VPE_DS_BYPASS;
782780
783781 mmr_adb->out_fmt_reg[0] = val;
....@@ -866,11 +864,13 @@
866864 unsigned int src_h = s_q_data->c_rect.height;
867865 unsigned int dst_w = d_q_data->c_rect.width;
868866 unsigned int dst_h = d_q_data->c_rect.height;
867
+ struct v4l2_pix_format_mplane *spix;
869868 size_t mv_buf_size;
870869 int ret;
871870
872871 ctx->sequence = 0;
873872 ctx->field = V4L2_FIELD_TOP;
873
+ spix = &s_q_data->format.fmt.pix_mp;
874874
875875 if ((s_q_data->flags & Q_IS_INTERLACED) &&
876876 !(d_q_data->flags & Q_IS_INTERLACED)) {
....@@ -881,13 +881,13 @@
881881 /*
882882 * we make sure that the source image has a 16 byte aligned
883883 * stride, we need to do the same for the motion vector buffer
884
- * by aligning it's stride to the next 16 byte boundry. this
884
+ * by aligning it's stride to the next 16 byte boundary. this
885885 * extra space will not be used by the de-interlacer, but will
886886 * ensure that vpdma operates correctly
887887 */
888
- bytes_per_line = ALIGN((s_q_data->width * mv->depth) >> 3,
889
- VPDMA_STRIDE_ALIGN);
890
- mv_buf_size = bytes_per_line * s_q_data->height;
888
+ bytes_per_line = ALIGN((spix->width * mv->depth) >> 3,
889
+ VPDMA_STRIDE_ALIGN);
890
+ mv_buf_size = bytes_per_line * spix->height;
891891
892892 ctx->deinterlacing = true;
893893 src_h <<= 1;
....@@ -907,7 +907,7 @@
907907 set_dei_regs(ctx);
908908
909909 csc_set_coeff(ctx->dev->csc, &mmr_adb->csc_regs[0],
910
- s_q_data->colorspace, d_q_data->colorspace);
910
+ &s_q_data->format, &d_q_data->format);
911911
912912 sc_set_hs_coeffs(ctx->dev->sc, ctx->sc_coeff_h.addr, src_w, dst_w);
913913 sc_set_vs_coeffs(ctx->dev->sc, ctx->sc_coeff_v.addr, src_h, dst_h);
....@@ -917,14 +917,6 @@
917917 src_w, src_h, dst_w, dst_h);
918918
919919 return 0;
920
-}
921
-
922
-/*
923
- * Return the vpe_ctx structure for a given struct file
924
- */
925
-static struct vpe_ctx *file2ctx(struct file *file)
926
-{
927
- return container_of(file->private_data, struct vpe_ctx, fh);
928920 }
929921
930922 /*
....@@ -1029,6 +1021,7 @@
10291021 struct vpe_fmt *fmt = q_data->fmt;
10301022 const struct vpdma_data_format *vpdma_fmt;
10311023 int mv_buf_selector = !ctx->src_mv_buf_selector;
1024
+ struct v4l2_pix_format_mplane *pix;
10321025 dma_addr_t dma_addr;
10331026 u32 flags = 0;
10341027 u32 offset = 0;
....@@ -1038,21 +1031,23 @@
10381031 vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
10391032 dma_addr = ctx->mv_buf_dma[mv_buf_selector];
10401033 q_data = &ctx->q_data[Q_DATA_SRC];
1041
- stride = ALIGN((q_data->width * vpdma_fmt->depth) >> 3,
1034
+ pix = &q_data->format.fmt.pix_mp;
1035
+ stride = ALIGN((pix->width * vpdma_fmt->depth) >> 3,
10421036 VPDMA_STRIDE_ALIGN);
10431037 } else {
10441038 /* to incorporate interleaved formats */
10451039 int plane = fmt->coplanar ? p_data->vb_part : 0;
10461040
1041
+ pix = &q_data->format.fmt.pix_mp;
10471042 vpdma_fmt = fmt->vpdma_fmt[plane];
10481043 /*
10491044 * If we are using a single plane buffer and
10501045 * we need to set a separate vpdma chroma channel.
10511046 */
1052
- if (q_data->nplanes == 1 && plane) {
1047
+ if (pix->num_planes == 1 && plane) {
10531048 dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
10541049 /* Compute required offset */
1055
- offset = q_data->bytesperline[0] * q_data->height;
1050
+ offset = pix->plane_fmt[0].bytesperline * pix->height;
10561051 } else {
10571052 dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane);
10581053 /* Use address as is, no offset */
....@@ -1066,7 +1061,7 @@
10661061 }
10671062 /* Apply the offset */
10681063 dma_addr += offset;
1069
- stride = q_data->bytesperline[VPE_LUMA];
1064
+ stride = pix->plane_fmt[VPE_LUMA].bytesperline;
10701065 }
10711066
10721067 if (q_data->flags & Q_DATA_FRAME_1D)
....@@ -1077,7 +1072,7 @@
10771072 vpdma_set_max_size(ctx->dev->vpdma, VPDMA_MAX_SIZE1,
10781073 MAX_W, MAX_H);
10791074
1080
- vpdma_add_out_dtd(&ctx->desc_list, q_data->width,
1075
+ vpdma_add_out_dtd(&ctx->desc_list, pix->width,
10811076 stride, &q_data->c_rect,
10821077 vpdma_fmt, dma_addr, MAX_OUT_WIDTH_REG1,
10831078 MAX_OUT_HEIGHT_REG1, p_data->channel, flags);
....@@ -1090,6 +1085,7 @@
10901085 struct vb2_buffer *vb = &ctx->src_vbs[p_data->vb_index]->vb2_buf;
10911086 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
10921087 struct vpe_fmt *fmt = q_data->fmt;
1088
+ struct v4l2_pix_format_mplane *pix;
10931089 const struct vpdma_data_format *vpdma_fmt;
10941090 int mv_buf_selector = ctx->src_mv_buf_selector;
10951091 int field = vbuf->field == V4L2_FIELD_BOTTOM;
....@@ -1099,10 +1095,11 @@
10991095 u32 offset = 0;
11001096 u32 stride;
11011097
1098
+ pix = &q_data->format.fmt.pix_mp;
11021099 if (port == VPE_PORT_MV_IN) {
11031100 vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
11041101 dma_addr = ctx->mv_buf_dma[mv_buf_selector];
1105
- stride = ALIGN((q_data->width * vpdma_fmt->depth) >> 3,
1102
+ stride = ALIGN((pix->width * vpdma_fmt->depth) >> 3,
11061103 VPDMA_STRIDE_ALIGN);
11071104 } else {
11081105 /* to incorporate interleaved formats */
....@@ -1113,10 +1110,10 @@
11131110 * If we are using a single plane buffer and
11141111 * we need to set a separate vpdma chroma channel.
11151112 */
1116
- if (q_data->nplanes == 1 && plane) {
1113
+ if (pix->num_planes == 1 && plane) {
11171114 dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
11181115 /* Compute required offset */
1119
- offset = q_data->bytesperline[0] * q_data->height;
1116
+ offset = pix->plane_fmt[0].bytesperline * pix->height;
11201117 } else {
11211118 dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane);
11221119 /* Use address as is, no offset */
....@@ -1130,27 +1127,39 @@
11301127 }
11311128 /* Apply the offset */
11321129 dma_addr += offset;
1133
- stride = q_data->bytesperline[VPE_LUMA];
1130
+ stride = pix->plane_fmt[VPE_LUMA].bytesperline;
11341131
1135
- if (q_data->flags & Q_DATA_INTERLACED_SEQ_TB) {
1136
- /*
1137
- * Use top or bottom field from same vb alternately
1138
- * f,f-1,f-2 = TBT when seq is even
1139
- * f,f-1,f-2 = BTB when seq is odd
1140
- */
1141
- field = (p_data->vb_index + (ctx->sequence % 2)) % 2;
1132
+ /*
1133
+ * field used in VPDMA desc = 0 (top) / 1 (bottom)
1134
+ * Use top or bottom field from same vb alternately
1135
+ * For each de-interlacing operation, f,f-1,f-2 should be one
1136
+ * of TBT or BTB
1137
+ */
1138
+ if (q_data->flags & Q_DATA_INTERLACED_SEQ_TB ||
1139
+ q_data->flags & Q_DATA_INTERLACED_SEQ_BT) {
1140
+ /* Select initial value based on format */
1141
+ if (q_data->flags & Q_DATA_INTERLACED_SEQ_BT)
1142
+ field = 1;
1143
+ else
1144
+ field = 0;
1145
+
1146
+ /* Toggle for each vb_index and each operation */
1147
+ field = (field + p_data->vb_index + ctx->sequence) % 2;
11421148
11431149 if (field) {
1144
- /*
1145
- * bottom field of a SEQ_TB buffer
1146
- * Skip the top field data by
1147
- */
1148
- int height = q_data->height / 2;
1149
- int bpp = fmt->fourcc == V4L2_PIX_FMT_NV12 ?
1150
- 1 : (vpdma_fmt->depth >> 3);
1150
+ int height = pix->height / 2;
1151
+ int bpp;
1152
+
1153
+ if (fmt->fourcc == V4L2_PIX_FMT_NV12 ||
1154
+ fmt->fourcc == V4L2_PIX_FMT_NV21)
1155
+ bpp = 1;
1156
+ else
1157
+ bpp = vpdma_fmt->depth >> 3;
1158
+
11511159 if (plane)
11521160 height /= 2;
1153
- dma_addr += q_data->width * height * bpp;
1161
+
1162
+ dma_addr += pix->width * height * bpp;
11541163 }
11551164 }
11561165 }
....@@ -1163,10 +1172,11 @@
11631172 frame_width = q_data->c_rect.width;
11641173 frame_height = q_data->c_rect.height;
11651174
1166
- if (p_data->vb_part && fmt->fourcc == V4L2_PIX_FMT_NV12)
1175
+ if (p_data->vb_part && (fmt->fourcc == V4L2_PIX_FMT_NV12 ||
1176
+ fmt->fourcc == V4L2_PIX_FMT_NV21))
11671177 frame_height /= 2;
11681178
1169
- vpdma_add_in_dtd(&ctx->desc_list, q_data->width, stride,
1179
+ vpdma_add_in_dtd(&ctx->desc_list, pix->width, stride,
11701180 &q_data->c_rect, vpdma_fmt, dma_addr,
11711181 p_data->channel, field, flags, frame_width,
11721182 frame_height, 0, 0);
....@@ -1203,13 +1213,18 @@
12031213 struct sc_data *sc = ctx->dev->sc;
12041214 struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST];
12051215 struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC];
1216
+ const struct v4l2_format_info *d_finfo;
12061217
1207
- if (ctx->deinterlacing && s_q_data->flags & Q_DATA_INTERLACED_SEQ_TB &&
1208
- ctx->sequence % 2 == 0) {
1209
- /* When using SEQ_TB buffers, When using it first time,
1210
- * No need to remove the buffer as the next field is present
1211
- * in the same buffer. (so that job_ready won't fail)
1212
- * It will be removed when using bottom field
1218
+ d_finfo = v4l2_format_info(d_q_data->fmt->fourcc);
1219
+
1220
+ if (ctx->deinterlacing && s_q_data->flags & Q_IS_SEQ_XX &&
1221
+ ctx->sequence % 2 == 0) {
1222
+ /* When using SEQ_XX type buffers, each buffer has two fields
1223
+ * each buffer has two fields (top & bottom)
1224
+ * Removing one buffer is actually getting two fields
1225
+ * Alternate between two operations:-
1226
+ * Even : consume one field but DO NOT REMOVE from queue
1227
+ * Odd : consume other field and REMOVE from queue
12131228 */
12141229 ctx->src_vbs[0] = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
12151230 WARN_ON(ctx->src_vbs[0] == NULL);
....@@ -1273,7 +1288,7 @@
12731288 if (ctx->deinterlacing)
12741289 add_out_dtd(ctx, VPE_PORT_MV_OUT);
12751290
1276
- if (d_q_data->colorspace == V4L2_COLORSPACE_SRGB) {
1291
+ if (v4l2_is_format_rgb(d_finfo)) {
12771292 add_out_dtd(ctx, VPE_PORT_RGB_OUT);
12781293 } else {
12791294 add_out_dtd(ctx, VPE_PORT_LUMA_OUT);
....@@ -1315,7 +1330,7 @@
13151330 }
13161331
13171332 /* sync on channel control descriptors for output ports */
1318
- if (d_q_data->colorspace == V4L2_COLORSPACE_SRGB) {
1333
+ if (v4l2_is_format_rgb(d_finfo)) {
13191334 vpdma_add_sync_on_channel_ctd(&ctx->desc_list,
13201335 VPE_CHAN_RGB_OUT);
13211336 } else {
....@@ -1505,12 +1520,10 @@
15051520 static int vpe_querycap(struct file *file, void *priv,
15061521 struct v4l2_capability *cap)
15071522 {
1508
- strncpy(cap->driver, VPE_MODULE_NAME, sizeof(cap->driver) - 1);
1509
- strncpy(cap->card, VPE_MODULE_NAME, sizeof(cap->card) - 1);
1523
+ strscpy(cap->driver, VPE_MODULE_NAME, sizeof(cap->driver));
1524
+ strscpy(cap->card, VPE_MODULE_NAME, sizeof(cap->card));
15101525 snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
15111526 VPE_MODULE_NAME);
1512
- cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
1513
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
15141527 return 0;
15151528 }
15161529
....@@ -1533,7 +1546,6 @@
15331546 if (!fmt)
15341547 return -EINVAL;
15351548
1536
- strncpy(f->description, fmt->name, sizeof(f->description) - 1);
15371549 f->pixelformat = fmt->fourcc;
15381550 return 0;
15391551 }
....@@ -1550,38 +1562,32 @@
15501562 static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
15511563 {
15521564 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
1553
- struct vpe_ctx *ctx = file2ctx(file);
1565
+ struct vpe_ctx *ctx = file->private_data;
15541566 struct vb2_queue *vq;
15551567 struct vpe_q_data *q_data;
1556
- int i;
15571568
15581569 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
15591570 if (!vq)
15601571 return -EINVAL;
15611572
15621573 q_data = get_q_data(ctx, f->type);
1574
+ if (!q_data)
1575
+ return -EINVAL;
15631576
1564
- pix->width = q_data->width;
1565
- pix->height = q_data->height;
1566
- pix->pixelformat = q_data->fmt->fourcc;
1567
- pix->field = q_data->field;
1577
+ *f = q_data->format;
15681578
1569
- if (V4L2_TYPE_IS_OUTPUT(f->type)) {
1570
- pix->colorspace = q_data->colorspace;
1571
- } else {
1579
+ if (V4L2_TYPE_IS_CAPTURE(f->type)) {
15721580 struct vpe_q_data *s_q_data;
1581
+ struct v4l2_pix_format_mplane *spix;
15731582
1574
- /* get colorspace from the source queue */
1583
+ /* get colorimetry from the source queue */
15751584 s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE);
1585
+ spix = &s_q_data->format.fmt.pix_mp;
15761586
1577
- pix->colorspace = s_q_data->colorspace;
1578
- }
1579
-
1580
- pix->num_planes = q_data->nplanes;
1581
-
1582
- for (i = 0; i < pix->num_planes; i++) {
1583
- pix->plane_fmt[i].bytesperline = q_data->bytesperline[i];
1584
- pix->plane_fmt[i].sizeimage = q_data->sizeimage[i];
1587
+ pix->colorspace = spix->colorspace;
1588
+ pix->xfer_func = spix->xfer_func;
1589
+ pix->ycbcr_enc = spix->ycbcr_enc;
1590
+ pix->quantization = spix->quantization;
15851591 }
15861592
15871593 return 0;
....@@ -1595,6 +1601,7 @@
15951601 unsigned int w_align;
15961602 int i, depth, depth_bytes, height;
15971603 unsigned int stride = 0;
1604
+ const struct v4l2_format_info *finfo;
15981605
15991606 if (!fmt || !(fmt->types & type)) {
16001607 vpe_dbg(ctx->dev, "Fourcc format (0x%08x) invalid.\n",
....@@ -1602,8 +1609,10 @@
16021609 fmt = __find_format(V4L2_PIX_FMT_YUYV);
16031610 }
16041611
1605
- if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE
1606
- && pix->field != V4L2_FIELD_SEQ_TB)
1612
+ if (pix->field != V4L2_FIELD_NONE &&
1613
+ pix->field != V4L2_FIELD_ALTERNATE &&
1614
+ pix->field != V4L2_FIELD_SEQ_TB &&
1615
+ pix->field != V4L2_FIELD_SEQ_BT)
16071616 pix->field = V4L2_FIELD_NONE;
16081617
16091618 depth = fmt->vpdma_fmt[VPE_LUMA]->depth;
....@@ -1652,21 +1661,19 @@
16521661 pix->num_planes = 1;
16531662
16541663 pix->pixelformat = fmt->fourcc;
1664
+ finfo = v4l2_format_info(fmt->fourcc);
16551665
16561666 /*
16571667 * For the actual image parameters, we need to consider the field
1658
- * height of the image for SEQ_TB buffers.
1668
+ * height of the image for SEQ_XX buffers.
16591669 */
1660
- if (pix->field == V4L2_FIELD_SEQ_TB)
1670
+ if (pix->field == V4L2_FIELD_SEQ_TB || pix->field == V4L2_FIELD_SEQ_BT)
16611671 height = pix->height / 2;
16621672 else
16631673 height = pix->height;
16641674
16651675 if (!pix->colorspace) {
1666
- if (fmt->fourcc == V4L2_PIX_FMT_RGB24 ||
1667
- fmt->fourcc == V4L2_PIX_FMT_BGR24 ||
1668
- fmt->fourcc == V4L2_PIX_FMT_RGB32 ||
1669
- fmt->fourcc == V4L2_PIX_FMT_BGR32) {
1676
+ if (v4l2_is_format_rgb(finfo)) {
16701677 pix->colorspace = V4L2_COLORSPACE_SRGB;
16711678 } else {
16721679 if (height > 1280) /* HD */
....@@ -1714,7 +1721,7 @@
17141721
17151722 static int vpe_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
17161723 {
1717
- struct vpe_ctx *ctx = file2ctx(file);
1724
+ struct vpe_ctx *ctx = file->private_data;
17181725 struct vpe_fmt *fmt = find_format(f);
17191726
17201727 if (V4L2_TYPE_IS_OUTPUT(f->type))
....@@ -1726,10 +1733,9 @@
17261733 static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f)
17271734 {
17281735 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
1729
- struct v4l2_plane_pix_format *plane_fmt;
1736
+ struct v4l2_pix_format_mplane *qpix;
17301737 struct vpe_q_data *q_data;
17311738 struct vb2_queue *vq;
1732
- int i;
17331739
17341740 vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
17351741 if (!vq)
....@@ -1744,42 +1750,34 @@
17441750 if (!q_data)
17451751 return -EINVAL;
17461752
1753
+ qpix = &q_data->format.fmt.pix_mp;
17471754 q_data->fmt = find_format(f);
1748
- q_data->width = pix->width;
1749
- q_data->height = pix->height;
1750
- q_data->colorspace = pix->colorspace;
1751
- q_data->field = pix->field;
1752
- q_data->nplanes = pix->num_planes;
1753
-
1754
- for (i = 0; i < pix->num_planes; i++) {
1755
- plane_fmt = &pix->plane_fmt[i];
1756
-
1757
- q_data->bytesperline[i] = plane_fmt->bytesperline;
1758
- q_data->sizeimage[i] = plane_fmt->sizeimage;
1759
- }
1755
+ q_data->format = *f;
17601756
17611757 q_data->c_rect.left = 0;
17621758 q_data->c_rect.top = 0;
1763
- q_data->c_rect.width = q_data->width;
1764
- q_data->c_rect.height = q_data->height;
1759
+ q_data->c_rect.width = pix->width;
1760
+ q_data->c_rect.height = pix->height;
17651761
1766
- if (q_data->field == V4L2_FIELD_ALTERNATE)
1762
+ if (qpix->field == V4L2_FIELD_ALTERNATE)
17671763 q_data->flags |= Q_DATA_INTERLACED_ALTERNATE;
1768
- else if (q_data->field == V4L2_FIELD_SEQ_TB)
1764
+ else if (qpix->field == V4L2_FIELD_SEQ_TB)
17691765 q_data->flags |= Q_DATA_INTERLACED_SEQ_TB;
1766
+ else if (qpix->field == V4L2_FIELD_SEQ_BT)
1767
+ q_data->flags |= Q_DATA_INTERLACED_SEQ_BT;
17701768 else
17711769 q_data->flags &= ~Q_IS_INTERLACED;
17721770
1773
- /* the crop height is halved for the case of SEQ_TB buffers */
1774
- if (q_data->flags & Q_DATA_INTERLACED_SEQ_TB)
1771
+ /* the crop height is halved for the case of SEQ_XX buffers */
1772
+ if (q_data->flags & Q_IS_SEQ_XX)
17751773 q_data->c_rect.height /= 2;
17761774
17771775 vpe_dbg(ctx->dev, "Setting format for type %d, wxh: %dx%d, fmt: %d bpl_y %d",
1778
- f->type, q_data->width, q_data->height, q_data->fmt->fourcc,
1779
- q_data->bytesperline[VPE_LUMA]);
1780
- if (q_data->nplanes == 2)
1776
+ f->type, pix->width, pix->height, pix->pixelformat,
1777
+ pix->plane_fmt[0].bytesperline);
1778
+ if (pix->num_planes == 2)
17811779 vpe_dbg(ctx->dev, " bpl_uv %d\n",
1782
- q_data->bytesperline[VPE_CHROMA]);
1780
+ pix->plane_fmt[1].bytesperline);
17831781
17841782 return 0;
17851783 }
....@@ -1787,7 +1785,7 @@
17871785 static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
17881786 {
17891787 int ret;
1790
- struct vpe_ctx *ctx = file2ctx(file);
1788
+ struct vpe_ctx *ctx = file->private_data;
17911789
17921790 ret = vpe_try_fmt(file, priv, f);
17931791 if (ret)
....@@ -1808,6 +1806,7 @@
18081806 static int __vpe_try_selection(struct vpe_ctx *ctx, struct v4l2_selection *s)
18091807 {
18101808 struct vpe_q_data *q_data;
1809
+ struct v4l2_pix_format_mplane *pix;
18111810 int height;
18121811
18131812 if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
....@@ -1817,6 +1816,8 @@
18171816 q_data = get_q_data(ctx, s->type);
18181817 if (!q_data)
18191818 return -EINVAL;
1819
+
1820
+ pix = &q_data->format.fmt.pix_mp;
18201821
18211822 switch (s->target) {
18221823 case V4L2_SEL_TGT_COMPOSE:
....@@ -1844,27 +1845,27 @@
18441845 }
18451846
18461847 /*
1847
- * For SEQ_TB buffers, crop height should be less than the height of
1848
+ * For SEQ_XX buffers, crop height should be less than the height of
18481849 * the field height, not the buffer height
18491850 */
1850
- if (q_data->flags & Q_DATA_INTERLACED_SEQ_TB)
1851
- height = q_data->height / 2;
1851
+ if (q_data->flags & Q_IS_SEQ_XX)
1852
+ height = pix->height / 2;
18521853 else
1853
- height = q_data->height;
1854
+ height = pix->height;
18541855
18551856 if (s->r.top < 0 || s->r.left < 0) {
18561857 vpe_err(ctx->dev, "negative values for top and left\n");
18571858 s->r.top = s->r.left = 0;
18581859 }
18591860
1860
- v4l_bound_align_image(&s->r.width, MIN_W, q_data->width, 1,
1861
+ v4l_bound_align_image(&s->r.width, MIN_W, pix->width, 1,
18611862 &s->r.height, MIN_H, height, H_ALIGN, S_ALIGN);
18621863
18631864 /* adjust left/top if cropping rectangle is out of bounds */
1864
- if (s->r.left + s->r.width > q_data->width)
1865
- s->r.left = q_data->width - s->r.width;
1866
- if (s->r.top + s->r.height > q_data->height)
1867
- s->r.top = q_data->height - s->r.height;
1865
+ if (s->r.left + s->r.width > pix->width)
1866
+ s->r.left = pix->width - s->r.width;
1867
+ if (s->r.top + s->r.height > pix->height)
1868
+ s->r.top = pix->height - s->r.height;
18681869
18691870 return 0;
18701871 }
....@@ -1872,8 +1873,9 @@
18721873 static int vpe_g_selection(struct file *file, void *fh,
18731874 struct v4l2_selection *s)
18741875 {
1875
- struct vpe_ctx *ctx = file2ctx(file);
1876
+ struct vpe_ctx *ctx = file->private_data;
18761877 struct vpe_q_data *q_data;
1878
+ struct v4l2_pix_format_mplane *pix;
18771879 bool use_c_rect = false;
18781880
18791881 if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
....@@ -1883,6 +1885,8 @@
18831885 q_data = get_q_data(ctx, s->type);
18841886 if (!q_data)
18851887 return -EINVAL;
1888
+
1889
+ pix = &q_data->format.fmt.pix_mp;
18861890
18871891 switch (s->target) {
18881892 case V4L2_SEL_TGT_COMPOSE_DEFAULT:
....@@ -1922,8 +1926,8 @@
19221926 */
19231927 s->r.left = 0;
19241928 s->r.top = 0;
1925
- s->r.width = q_data->width;
1926
- s->r.height = q_data->height;
1929
+ s->r.width = pix->width;
1930
+ s->r.height = pix->height;
19271931 }
19281932
19291933 return 0;
....@@ -1933,7 +1937,7 @@
19331937 static int vpe_s_selection(struct file *file, void *fh,
19341938 struct v4l2_selection *s)
19351939 {
1936
- struct vpe_ctx *ctx = file2ctx(file);
1940
+ struct vpe_ctx *ctx = file->private_data;
19371941 struct vpe_q_data *q_data;
19381942 struct v4l2_selection sel = *s;
19391943 int ret;
....@@ -1991,12 +1995,12 @@
19911995 static const struct v4l2_ioctl_ops vpe_ioctl_ops = {
19921996 .vidioc_querycap = vpe_querycap,
19931997
1994
- .vidioc_enum_fmt_vid_cap_mplane = vpe_enum_fmt,
1998
+ .vidioc_enum_fmt_vid_cap = vpe_enum_fmt,
19951999 .vidioc_g_fmt_vid_cap_mplane = vpe_g_fmt,
19962000 .vidioc_try_fmt_vid_cap_mplane = vpe_try_fmt,
19972001 .vidioc_s_fmt_vid_cap_mplane = vpe_s_fmt,
19982002
1999
- .vidioc_enum_fmt_vid_out_mplane = vpe_enum_fmt,
2003
+ .vidioc_enum_fmt_vid_out = vpe_enum_fmt,
20002004 .vidioc_g_fmt_vid_out_mplane = vpe_g_fmt,
20012005 .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt,
20022006 .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt,
....@@ -2026,17 +2030,21 @@
20262030 int i;
20272031 struct vpe_ctx *ctx = vb2_get_drv_priv(vq);
20282032 struct vpe_q_data *q_data;
2033
+ struct v4l2_pix_format_mplane *pix;
20292034
20302035 q_data = get_q_data(ctx, vq->type);
2036
+ if (!q_data)
2037
+ return -EINVAL;
20312038
2032
- *nplanes = q_data->nplanes;
2039
+ pix = &q_data->format.fmt.pix_mp;
2040
+ *nplanes = pix->num_planes;
20332041
20342042 for (i = 0; i < *nplanes; i++)
2035
- sizes[i] = q_data->sizeimage[i];
2043
+ sizes[i] = pix->plane_fmt[i].sizeimage;
20362044
20372045 vpe_dbg(ctx->dev, "get %d buffer(s) of size %d", *nbuffers,
20382046 sizes[VPE_LUMA]);
2039
- if (q_data->nplanes == 2)
2047
+ if (*nplanes == 2)
20402048 vpe_dbg(ctx->dev, " and %d\n", sizes[VPE_CHROMA]);
20412049
20422050 return 0;
....@@ -2047,12 +2055,16 @@
20472055 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
20482056 struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
20492057 struct vpe_q_data *q_data;
2050
- int i, num_planes;
2058
+ struct v4l2_pix_format_mplane *pix;
2059
+ int i;
20512060
20522061 vpe_dbg(ctx->dev, "type: %d\n", vb->vb2_queue->type);
20532062
20542063 q_data = get_q_data(ctx, vb->vb2_queue->type);
2055
- num_planes = q_data->nplanes;
2064
+ if (!q_data)
2065
+ return -EINVAL;
2066
+
2067
+ pix = &q_data->format.fmt.pix_mp;
20562068
20572069 if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
20582070 if (!(q_data->flags & Q_IS_INTERLACED)) {
....@@ -2060,23 +2072,24 @@
20602072 } else {
20612073 if (vbuf->field != V4L2_FIELD_TOP &&
20622074 vbuf->field != V4L2_FIELD_BOTTOM &&
2063
- vbuf->field != V4L2_FIELD_SEQ_TB)
2075
+ vbuf->field != V4L2_FIELD_SEQ_TB &&
2076
+ vbuf->field != V4L2_FIELD_SEQ_BT)
20642077 return -EINVAL;
20652078 }
20662079 }
20672080
2068
- for (i = 0; i < num_planes; i++) {
2069
- if (vb2_plane_size(vb, i) < q_data->sizeimage[i]) {
2081
+ for (i = 0; i < pix->num_planes; i++) {
2082
+ if (vb2_plane_size(vb, i) < pix->plane_fmt[i].sizeimage) {
20702083 vpe_err(ctx->dev,
20712084 "data will not fit into plane (%lu < %lu)\n",
20722085 vb2_plane_size(vb, i),
2073
- (long) q_data->sizeimage[i]);
2086
+ (long)pix->plane_fmt[i].sizeimage);
20742087 return -EINVAL;
20752088 }
20762089 }
20772090
2078
- for (i = 0; i < num_planes; i++)
2079
- vb2_set_plane_payload(vb, i, q_data->sizeimage[i]);
2091
+ for (i = 0; i < pix->num_planes; i++)
2092
+ vb2_set_plane_payload(vb, i, pix->plane_fmt[i].sizeimage);
20802093
20812094 return 0;
20822095 }
....@@ -2261,6 +2274,7 @@
22612274 struct vpe_q_data *s_q_data;
22622275 struct v4l2_ctrl_handler *hdl;
22632276 struct vpe_ctx *ctx;
2277
+ struct v4l2_pix_format_mplane *pix;
22642278 int ret;
22652279
22662280 vpe_dbg(dev, "vpe_open\n");
....@@ -2296,7 +2310,7 @@
22962310 init_adb_hdrs(ctx);
22972311
22982312 v4l2_fh_init(&ctx->fh, video_devdata(file));
2299
- file->private_data = &ctx->fh;
2313
+ file->private_data = ctx;
23002314
23012315 hdl = &ctx->hdl;
23022316 v4l2_ctrl_handler_init(hdl, 1);
....@@ -2309,23 +2323,32 @@
23092323 v4l2_ctrl_handler_setup(hdl);
23102324
23112325 s_q_data = &ctx->q_data[Q_DATA_SRC];
2326
+ pix = &s_q_data->format.fmt.pix_mp;
23122327 s_q_data->fmt = __find_format(V4L2_PIX_FMT_YUYV);
2313
- s_q_data->width = 1920;
2314
- s_q_data->height = 1080;
2315
- s_q_data->nplanes = 1;
2316
- s_q_data->bytesperline[VPE_LUMA] = (s_q_data->width *
2328
+ pix->pixelformat = s_q_data->fmt->fourcc;
2329
+ s_q_data->format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
2330
+ pix->width = 1920;
2331
+ pix->height = 1080;
2332
+ pix->num_planes = 1;
2333
+ pix->plane_fmt[VPE_LUMA].bytesperline = (pix->width *
23172334 s_q_data->fmt->vpdma_fmt[VPE_LUMA]->depth) >> 3;
2318
- s_q_data->sizeimage[VPE_LUMA] = (s_q_data->bytesperline[VPE_LUMA] *
2319
- s_q_data->height);
2320
- s_q_data->colorspace = V4L2_COLORSPACE_REC709;
2321
- s_q_data->field = V4L2_FIELD_NONE;
2335
+ pix->plane_fmt[VPE_LUMA].sizeimage =
2336
+ pix->plane_fmt[VPE_LUMA].bytesperline *
2337
+ pix->height;
2338
+ pix->colorspace = V4L2_COLORSPACE_REC709;
2339
+ pix->xfer_func = V4L2_XFER_FUNC_DEFAULT;
2340
+ pix->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
2341
+ pix->quantization = V4L2_QUANTIZATION_DEFAULT;
2342
+ pix->field = V4L2_FIELD_NONE;
23222343 s_q_data->c_rect.left = 0;
23232344 s_q_data->c_rect.top = 0;
2324
- s_q_data->c_rect.width = s_q_data->width;
2325
- s_q_data->c_rect.height = s_q_data->height;
2345
+ s_q_data->c_rect.width = pix->width;
2346
+ s_q_data->c_rect.height = pix->height;
23262347 s_q_data->flags = 0;
23272348
23282349 ctx->q_data[Q_DATA_DST] = *s_q_data;
2350
+ ctx->q_data[Q_DATA_DST].format.type =
2351
+ V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
23292352
23302353 set_dei_shadow_registers(ctx);
23312354 set_src_registers(ctx);
....@@ -2381,7 +2404,7 @@
23812404 static int vpe_release(struct file *file)
23822405 {
23832406 struct vpe_dev *dev = video_drvdata(file);
2384
- struct vpe_ctx *ctx = file2ctx(file);
2407
+ struct vpe_ctx *ctx = file->private_data;
23852408
23862409 vpe_dbg(dev, "releasing instance %p\n", ctx);
23872410
....@@ -2435,6 +2458,7 @@
24352458 .minor = -1,
24362459 .release = video_device_release_empty,
24372460 .vfl_dir = VFL_DIR_M2M,
2461
+ .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING,
24382462 };
24392463
24402464 static const struct v4l2_m2m_ops m2m_ops = {
....@@ -2478,7 +2502,7 @@
24782502 vfd->lock = &dev->dev_mutex;
24792503 vfd->v4l2_dev = &dev->v4l2_dev;
24802504
2481
- ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
2505
+ ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0);
24822506 if (ret) {
24832507 vpe_err(dev, "Failed to register video device\n");
24842508
....@@ -2501,6 +2525,13 @@
25012525 struct vpe_dev *dev;
25022526 int ret, irq, func;
25032527
2528
+ ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
2529
+ if (ret) {
2530
+ dev_err(&pdev->dev,
2531
+ "32-bit consistent DMA enable failed\n");
2532
+ return ret;
2533
+ }
2534
+
25042535 dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
25052536 if (!dev)
25062537 return -ENOMEM;
....@@ -2515,7 +2546,12 @@
25152546 mutex_init(&dev->dev_mutex);
25162547
25172548 dev->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2518
- "vpe_top");
2549
+ "vpe_top");
2550
+ if (!dev->res) {
2551
+ dev_err(&pdev->dev, "missing 'vpe_top' resources data\n");
2552
+ return -ENODEV;
2553
+ }
2554
+
25192555 /*
25202556 * HACK: we get resource info from device tree in the form of a list of
25212557 * VPE sub blocks, the driver currently uses only the base of vpe_top
....@@ -2610,7 +2646,7 @@
26102646 #if defined(CONFIG_OF)
26112647 static const struct of_device_id vpe_of_match[] = {
26122648 {
2613
- .compatible = "ti,vpe",
2649
+ .compatible = "ti,dra7-vpe",
26142650 },
26152651 {},
26162652 };