.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * TI VPE mem2mem driver, based on the virtual v4l2-mem2mem example driver |
---|
3 | 4 | * |
---|
.. | .. |
---|
11 | 12 | * Marek Szyprowski, <m.szyprowski@samsung.com> |
---|
12 | 13 | * |
---|
13 | 14 | * 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 |
---|
18 | 15 | */ |
---|
19 | 16 | |
---|
20 | 17 | #include <linux/delay.h> |
---|
.. | .. |
---|
55 | 52 | #define MIN_W 32 |
---|
56 | 53 | #define MIN_H 32 |
---|
57 | 54 | #define MAX_W 2048 |
---|
58 | | -#define MAX_H 1184 |
---|
| 55 | +#define MAX_H 2048 |
---|
59 | 56 | |
---|
60 | 57 | /* required alignments */ |
---|
61 | 58 | #define S_ALIGN 0 /* multiple of 1 */ |
---|
.. | .. |
---|
227 | 224 | |
---|
228 | 225 | /* driver info for each of the supported video formats */ |
---|
229 | 226 | struct vpe_fmt { |
---|
230 | | - char *name; /* human-readable name */ |
---|
231 | 227 | u32 fourcc; /* standard format identifier */ |
---|
232 | 228 | u8 types; /* CAPTURE and/or OUTPUT */ |
---|
233 | 229 | u8 coplanar; /* set for unpacked Luma and Chroma */ |
---|
.. | .. |
---|
237 | 233 | |
---|
238 | 234 | static struct vpe_fmt vpe_formats[] = { |
---|
239 | 235 | { |
---|
240 | | - .name = "NV16 YUV 422 co-planar", |
---|
241 | 236 | .fourcc = V4L2_PIX_FMT_NV16, |
---|
242 | 237 | .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, |
---|
243 | 238 | .coplanar = 1, |
---|
.. | .. |
---|
246 | 241 | }, |
---|
247 | 242 | }, |
---|
248 | 243 | { |
---|
249 | | - .name = "NV12 YUV 420 co-planar", |
---|
250 | 244 | .fourcc = V4L2_PIX_FMT_NV12, |
---|
251 | 245 | .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, |
---|
252 | 246 | .coplanar = 1, |
---|
.. | .. |
---|
255 | 249 | }, |
---|
256 | 250 | }, |
---|
257 | 251 | { |
---|
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 | + { |
---|
259 | 260 | .fourcc = V4L2_PIX_FMT_YUYV, |
---|
260 | 261 | .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, |
---|
261 | 262 | .coplanar = 0, |
---|
.. | .. |
---|
263 | 264 | }, |
---|
264 | 265 | }, |
---|
265 | 266 | { |
---|
266 | | - .name = "UYVY 422 packed", |
---|
267 | 267 | .fourcc = V4L2_PIX_FMT_UYVY, |
---|
268 | 268 | .types = VPE_FMT_TYPE_CAPTURE | VPE_FMT_TYPE_OUTPUT, |
---|
269 | 269 | .coplanar = 0, |
---|
.. | .. |
---|
271 | 271 | }, |
---|
272 | 272 | }, |
---|
273 | 273 | { |
---|
274 | | - .name = "RGB888 packed", |
---|
275 | 274 | .fourcc = V4L2_PIX_FMT_RGB24, |
---|
276 | 275 | .types = VPE_FMT_TYPE_CAPTURE, |
---|
277 | 276 | .coplanar = 0, |
---|
.. | .. |
---|
279 | 278 | }, |
---|
280 | 279 | }, |
---|
281 | 280 | { |
---|
282 | | - .name = "ARGB32", |
---|
283 | 281 | .fourcc = V4L2_PIX_FMT_RGB32, |
---|
284 | 282 | .types = VPE_FMT_TYPE_CAPTURE, |
---|
285 | 283 | .coplanar = 0, |
---|
.. | .. |
---|
287 | 285 | }, |
---|
288 | 286 | }, |
---|
289 | 287 | { |
---|
290 | | - .name = "BGR888 packed", |
---|
291 | 288 | .fourcc = V4L2_PIX_FMT_BGR24, |
---|
292 | 289 | .types = VPE_FMT_TYPE_CAPTURE, |
---|
293 | 290 | .coplanar = 0, |
---|
.. | .. |
---|
295 | 292 | }, |
---|
296 | 293 | }, |
---|
297 | 294 | { |
---|
298 | | - .name = "ABGR32", |
---|
299 | 295 | .fourcc = V4L2_PIX_FMT_BGR32, |
---|
300 | 296 | .types = VPE_FMT_TYPE_CAPTURE, |
---|
301 | 297 | .coplanar = 0, |
---|
.. | .. |
---|
303 | 299 | }, |
---|
304 | 300 | }, |
---|
305 | 301 | { |
---|
306 | | - .name = "RGB565", |
---|
307 | 302 | .fourcc = V4L2_PIX_FMT_RGB565, |
---|
308 | 303 | .types = VPE_FMT_TYPE_CAPTURE, |
---|
309 | 304 | .coplanar = 0, |
---|
.. | .. |
---|
311 | 306 | }, |
---|
312 | 307 | }, |
---|
313 | 308 | { |
---|
314 | | - .name = "RGB5551", |
---|
315 | 309 | .fourcc = V4L2_PIX_FMT_RGB555, |
---|
316 | 310 | .types = VPE_FMT_TYPE_CAPTURE, |
---|
317 | 311 | .coplanar = 0, |
---|
.. | .. |
---|
325 | 319 | * there is one source queue and one destination queue for each m2m context. |
---|
326 | 320 | */ |
---|
327 | 321 | 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; |
---|
334 | 324 | unsigned int flags; |
---|
335 | | - unsigned int sizeimage[VPE_MAX_PLANES]; /* image size in memory */ |
---|
336 | 325 | struct v4l2_rect c_rect; /* crop/compose rectangle */ |
---|
337 | 326 | struct vpe_fmt *fmt; /* format info */ |
---|
338 | 327 | }; |
---|
.. | .. |
---|
342 | 331 | #define Q_DATA_MODE_TILED BIT(1) |
---|
343 | 332 | #define Q_DATA_INTERLACED_ALTERNATE BIT(2) |
---|
344 | 333 | #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) |
---|
345 | 338 | |
---|
346 | 339 | #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) |
---|
348 | 342 | |
---|
349 | 343 | enum { |
---|
350 | 344 | Q_DATA_SRC = 0, |
---|
.. | .. |
---|
700 | 694 | * Cfg Mode 1: YUV422 source, disable upsampler, DEI is de-interlacing. |
---|
701 | 695 | */ |
---|
702 | 696 | |
---|
703 | | - if (fmt->fourcc == V4L2_PIX_FMT_NV12) |
---|
| 697 | + if (fmt->fourcc == V4L2_PIX_FMT_NV12 || |
---|
| 698 | + fmt->fourcc == V4L2_PIX_FMT_NV21) |
---|
704 | 699 | cfg_mode = 0; |
---|
705 | 700 | |
---|
706 | 701 | write_field(us1_reg0, cfg_mode, VPE_US_MODE_MASK, VPE_US_MODE_SHIFT); |
---|
.. | .. |
---|
715 | 710 | struct vpe_fmt *fmt = ctx->q_data[Q_DATA_SRC].fmt; |
---|
716 | 711 | int line_mode = 1; |
---|
717 | 712 | |
---|
718 | | - if (fmt->fourcc == V4L2_PIX_FMT_NV12) |
---|
| 713 | + if (fmt->fourcc == V4L2_PIX_FMT_NV12 || |
---|
| 714 | + fmt->fourcc == V4L2_PIX_FMT_NV21) |
---|
719 | 715 | line_mode = 0; /* double lines to line buffer */ |
---|
720 | 716 | |
---|
721 | 717 | /* regs for now */ |
---|
.. | .. |
---|
760 | 756 | static void set_dst_registers(struct vpe_ctx *ctx) |
---|
761 | 757 | { |
---|
762 | 758 | struct vpe_mmr_adb *mmr_adb = ctx->mmr_adb.addr; |
---|
763 | | - enum v4l2_colorspace clrspc = ctx->q_data[Q_DATA_DST].colorspace; |
---|
764 | 759 | struct vpe_fmt *fmt = ctx->q_data[Q_DATA_DST].fmt; |
---|
| 760 | + const struct v4l2_format_info *finfo; |
---|
765 | 761 | u32 val = 0; |
---|
766 | 762 | |
---|
767 | | - if (clrspc == V4L2_COLORSPACE_SRGB) { |
---|
| 763 | + finfo = v4l2_format_info(fmt->fourcc); |
---|
| 764 | + if (v4l2_is_format_rgb(finfo)) { |
---|
768 | 765 | val |= VPE_RGB_OUT_SELECT; |
---|
769 | 766 | vpdma_set_bg_color(ctx->dev->vpdma, |
---|
770 | 767 | (struct vpdma_data_format *)fmt->vpdma_fmt[0], 0xff); |
---|
.. | .. |
---|
777 | 774 | */ |
---|
778 | 775 | val |= VPE_DS_SRC_DEI_SCALER | VPE_CSC_SRC_DEI_SCALER; |
---|
779 | 776 | |
---|
780 | | - if (fmt->fourcc != V4L2_PIX_FMT_NV12) |
---|
| 777 | + if (fmt->fourcc != V4L2_PIX_FMT_NV12 && |
---|
| 778 | + fmt->fourcc != V4L2_PIX_FMT_NV21) |
---|
781 | 779 | val |= VPE_DS_BYPASS; |
---|
782 | 780 | |
---|
783 | 781 | mmr_adb->out_fmt_reg[0] = val; |
---|
.. | .. |
---|
866 | 864 | unsigned int src_h = s_q_data->c_rect.height; |
---|
867 | 865 | unsigned int dst_w = d_q_data->c_rect.width; |
---|
868 | 866 | unsigned int dst_h = d_q_data->c_rect.height; |
---|
| 867 | + struct v4l2_pix_format_mplane *spix; |
---|
869 | 868 | size_t mv_buf_size; |
---|
870 | 869 | int ret; |
---|
871 | 870 | |
---|
872 | 871 | ctx->sequence = 0; |
---|
873 | 872 | ctx->field = V4L2_FIELD_TOP; |
---|
| 873 | + spix = &s_q_data->format.fmt.pix_mp; |
---|
874 | 874 | |
---|
875 | 875 | if ((s_q_data->flags & Q_IS_INTERLACED) && |
---|
876 | 876 | !(d_q_data->flags & Q_IS_INTERLACED)) { |
---|
.. | .. |
---|
881 | 881 | /* |
---|
882 | 882 | * we make sure that the source image has a 16 byte aligned |
---|
883 | 883 | * 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 |
---|
885 | 885 | * extra space will not be used by the de-interlacer, but will |
---|
886 | 886 | * ensure that vpdma operates correctly |
---|
887 | 887 | */ |
---|
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; |
---|
891 | 891 | |
---|
892 | 892 | ctx->deinterlacing = true; |
---|
893 | 893 | src_h <<= 1; |
---|
.. | .. |
---|
907 | 907 | set_dei_regs(ctx); |
---|
908 | 908 | |
---|
909 | 909 | 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); |
---|
911 | 911 | |
---|
912 | 912 | sc_set_hs_coeffs(ctx->dev->sc, ctx->sc_coeff_h.addr, src_w, dst_w); |
---|
913 | 913 | sc_set_vs_coeffs(ctx->dev->sc, ctx->sc_coeff_v.addr, src_h, dst_h); |
---|
.. | .. |
---|
917 | 917 | src_w, src_h, dst_w, dst_h); |
---|
918 | 918 | |
---|
919 | 919 | 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); |
---|
928 | 920 | } |
---|
929 | 921 | |
---|
930 | 922 | /* |
---|
.. | .. |
---|
1029 | 1021 | struct vpe_fmt *fmt = q_data->fmt; |
---|
1030 | 1022 | const struct vpdma_data_format *vpdma_fmt; |
---|
1031 | 1023 | int mv_buf_selector = !ctx->src_mv_buf_selector; |
---|
| 1024 | + struct v4l2_pix_format_mplane *pix; |
---|
1032 | 1025 | dma_addr_t dma_addr; |
---|
1033 | 1026 | u32 flags = 0; |
---|
1034 | 1027 | u32 offset = 0; |
---|
.. | .. |
---|
1038 | 1031 | vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV]; |
---|
1039 | 1032 | dma_addr = ctx->mv_buf_dma[mv_buf_selector]; |
---|
1040 | 1033 | 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, |
---|
1042 | 1036 | VPDMA_STRIDE_ALIGN); |
---|
1043 | 1037 | } else { |
---|
1044 | 1038 | /* to incorporate interleaved formats */ |
---|
1045 | 1039 | int plane = fmt->coplanar ? p_data->vb_part : 0; |
---|
1046 | 1040 | |
---|
| 1041 | + pix = &q_data->format.fmt.pix_mp; |
---|
1047 | 1042 | vpdma_fmt = fmt->vpdma_fmt[plane]; |
---|
1048 | 1043 | /* |
---|
1049 | 1044 | * If we are using a single plane buffer and |
---|
1050 | 1045 | * we need to set a separate vpdma chroma channel. |
---|
1051 | 1046 | */ |
---|
1052 | | - if (q_data->nplanes == 1 && plane) { |
---|
| 1047 | + if (pix->num_planes == 1 && plane) { |
---|
1053 | 1048 | dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); |
---|
1054 | 1049 | /* Compute required offset */ |
---|
1055 | | - offset = q_data->bytesperline[0] * q_data->height; |
---|
| 1050 | + offset = pix->plane_fmt[0].bytesperline * pix->height; |
---|
1056 | 1051 | } else { |
---|
1057 | 1052 | dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane); |
---|
1058 | 1053 | /* Use address as is, no offset */ |
---|
.. | .. |
---|
1066 | 1061 | } |
---|
1067 | 1062 | /* Apply the offset */ |
---|
1068 | 1063 | dma_addr += offset; |
---|
1069 | | - stride = q_data->bytesperline[VPE_LUMA]; |
---|
| 1064 | + stride = pix->plane_fmt[VPE_LUMA].bytesperline; |
---|
1070 | 1065 | } |
---|
1071 | 1066 | |
---|
1072 | 1067 | if (q_data->flags & Q_DATA_FRAME_1D) |
---|
.. | .. |
---|
1077 | 1072 | vpdma_set_max_size(ctx->dev->vpdma, VPDMA_MAX_SIZE1, |
---|
1078 | 1073 | MAX_W, MAX_H); |
---|
1079 | 1074 | |
---|
1080 | | - vpdma_add_out_dtd(&ctx->desc_list, q_data->width, |
---|
| 1075 | + vpdma_add_out_dtd(&ctx->desc_list, pix->width, |
---|
1081 | 1076 | stride, &q_data->c_rect, |
---|
1082 | 1077 | vpdma_fmt, dma_addr, MAX_OUT_WIDTH_REG1, |
---|
1083 | 1078 | MAX_OUT_HEIGHT_REG1, p_data->channel, flags); |
---|
.. | .. |
---|
1090 | 1085 | struct vb2_buffer *vb = &ctx->src_vbs[p_data->vb_index]->vb2_buf; |
---|
1091 | 1086 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
---|
1092 | 1087 | struct vpe_fmt *fmt = q_data->fmt; |
---|
| 1088 | + struct v4l2_pix_format_mplane *pix; |
---|
1093 | 1089 | const struct vpdma_data_format *vpdma_fmt; |
---|
1094 | 1090 | int mv_buf_selector = ctx->src_mv_buf_selector; |
---|
1095 | 1091 | int field = vbuf->field == V4L2_FIELD_BOTTOM; |
---|
.. | .. |
---|
1099 | 1095 | u32 offset = 0; |
---|
1100 | 1096 | u32 stride; |
---|
1101 | 1097 | |
---|
| 1098 | + pix = &q_data->format.fmt.pix_mp; |
---|
1102 | 1099 | if (port == VPE_PORT_MV_IN) { |
---|
1103 | 1100 | vpdma_fmt = &vpdma_misc_fmts[VPDMA_DATA_FMT_MV]; |
---|
1104 | 1101 | 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, |
---|
1106 | 1103 | VPDMA_STRIDE_ALIGN); |
---|
1107 | 1104 | } else { |
---|
1108 | 1105 | /* to incorporate interleaved formats */ |
---|
.. | .. |
---|
1113 | 1110 | * If we are using a single plane buffer and |
---|
1114 | 1111 | * we need to set a separate vpdma chroma channel. |
---|
1115 | 1112 | */ |
---|
1116 | | - if (q_data->nplanes == 1 && plane) { |
---|
| 1113 | + if (pix->num_planes == 1 && plane) { |
---|
1117 | 1114 | dma_addr = vb2_dma_contig_plane_dma_addr(vb, 0); |
---|
1118 | 1115 | /* Compute required offset */ |
---|
1119 | | - offset = q_data->bytesperline[0] * q_data->height; |
---|
| 1116 | + offset = pix->plane_fmt[0].bytesperline * pix->height; |
---|
1120 | 1117 | } else { |
---|
1121 | 1118 | dma_addr = vb2_dma_contig_plane_dma_addr(vb, plane); |
---|
1122 | 1119 | /* Use address as is, no offset */ |
---|
.. | .. |
---|
1130 | 1127 | } |
---|
1131 | 1128 | /* Apply the offset */ |
---|
1132 | 1129 | dma_addr += offset; |
---|
1133 | | - stride = q_data->bytesperline[VPE_LUMA]; |
---|
| 1130 | + stride = pix->plane_fmt[VPE_LUMA].bytesperline; |
---|
1134 | 1131 | |
---|
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; |
---|
1142 | 1148 | |
---|
1143 | 1149 | 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 | + |
---|
1151 | 1159 | if (plane) |
---|
1152 | 1160 | height /= 2; |
---|
1153 | | - dma_addr += q_data->width * height * bpp; |
---|
| 1161 | + |
---|
| 1162 | + dma_addr += pix->width * height * bpp; |
---|
1154 | 1163 | } |
---|
1155 | 1164 | } |
---|
1156 | 1165 | } |
---|
.. | .. |
---|
1163 | 1172 | frame_width = q_data->c_rect.width; |
---|
1164 | 1173 | frame_height = q_data->c_rect.height; |
---|
1165 | 1174 | |
---|
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)) |
---|
1167 | 1177 | frame_height /= 2; |
---|
1168 | 1178 | |
---|
1169 | | - vpdma_add_in_dtd(&ctx->desc_list, q_data->width, stride, |
---|
| 1179 | + vpdma_add_in_dtd(&ctx->desc_list, pix->width, stride, |
---|
1170 | 1180 | &q_data->c_rect, vpdma_fmt, dma_addr, |
---|
1171 | 1181 | p_data->channel, field, flags, frame_width, |
---|
1172 | 1182 | frame_height, 0, 0); |
---|
.. | .. |
---|
1203 | 1213 | struct sc_data *sc = ctx->dev->sc; |
---|
1204 | 1214 | struct vpe_q_data *d_q_data = &ctx->q_data[Q_DATA_DST]; |
---|
1205 | 1215 | struct vpe_q_data *s_q_data = &ctx->q_data[Q_DATA_SRC]; |
---|
| 1216 | + const struct v4l2_format_info *d_finfo; |
---|
1206 | 1217 | |
---|
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 |
---|
1213 | 1228 | */ |
---|
1214 | 1229 | ctx->src_vbs[0] = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); |
---|
1215 | 1230 | WARN_ON(ctx->src_vbs[0] == NULL); |
---|
.. | .. |
---|
1273 | 1288 | if (ctx->deinterlacing) |
---|
1274 | 1289 | add_out_dtd(ctx, VPE_PORT_MV_OUT); |
---|
1275 | 1290 | |
---|
1276 | | - if (d_q_data->colorspace == V4L2_COLORSPACE_SRGB) { |
---|
| 1291 | + if (v4l2_is_format_rgb(d_finfo)) { |
---|
1277 | 1292 | add_out_dtd(ctx, VPE_PORT_RGB_OUT); |
---|
1278 | 1293 | } else { |
---|
1279 | 1294 | add_out_dtd(ctx, VPE_PORT_LUMA_OUT); |
---|
.. | .. |
---|
1315 | 1330 | } |
---|
1316 | 1331 | |
---|
1317 | 1332 | /* 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)) { |
---|
1319 | 1334 | vpdma_add_sync_on_channel_ctd(&ctx->desc_list, |
---|
1320 | 1335 | VPE_CHAN_RGB_OUT); |
---|
1321 | 1336 | } else { |
---|
.. | .. |
---|
1505 | 1520 | static int vpe_querycap(struct file *file, void *priv, |
---|
1506 | 1521 | struct v4l2_capability *cap) |
---|
1507 | 1522 | { |
---|
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)); |
---|
1510 | 1525 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", |
---|
1511 | 1526 | 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; |
---|
1514 | 1527 | return 0; |
---|
1515 | 1528 | } |
---|
1516 | 1529 | |
---|
.. | .. |
---|
1533 | 1546 | if (!fmt) |
---|
1534 | 1547 | return -EINVAL; |
---|
1535 | 1548 | |
---|
1536 | | - strncpy(f->description, fmt->name, sizeof(f->description) - 1); |
---|
1537 | 1549 | f->pixelformat = fmt->fourcc; |
---|
1538 | 1550 | return 0; |
---|
1539 | 1551 | } |
---|
.. | .. |
---|
1550 | 1562 | static int vpe_g_fmt(struct file *file, void *priv, struct v4l2_format *f) |
---|
1551 | 1563 | { |
---|
1552 | 1564 | 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; |
---|
1554 | 1566 | struct vb2_queue *vq; |
---|
1555 | 1567 | struct vpe_q_data *q_data; |
---|
1556 | | - int i; |
---|
1557 | 1568 | |
---|
1558 | 1569 | vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); |
---|
1559 | 1570 | if (!vq) |
---|
1560 | 1571 | return -EINVAL; |
---|
1561 | 1572 | |
---|
1562 | 1573 | q_data = get_q_data(ctx, f->type); |
---|
| 1574 | + if (!q_data) |
---|
| 1575 | + return -EINVAL; |
---|
1563 | 1576 | |
---|
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; |
---|
1568 | 1578 | |
---|
1569 | | - if (V4L2_TYPE_IS_OUTPUT(f->type)) { |
---|
1570 | | - pix->colorspace = q_data->colorspace; |
---|
1571 | | - } else { |
---|
| 1579 | + if (V4L2_TYPE_IS_CAPTURE(f->type)) { |
---|
1572 | 1580 | struct vpe_q_data *s_q_data; |
---|
| 1581 | + struct v4l2_pix_format_mplane *spix; |
---|
1573 | 1582 | |
---|
1574 | | - /* get colorspace from the source queue */ |
---|
| 1583 | + /* get colorimetry from the source queue */ |
---|
1575 | 1584 | s_q_data = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE); |
---|
| 1585 | + spix = &s_q_data->format.fmt.pix_mp; |
---|
1576 | 1586 | |
---|
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; |
---|
1585 | 1591 | } |
---|
1586 | 1592 | |
---|
1587 | 1593 | return 0; |
---|
.. | .. |
---|
1595 | 1601 | unsigned int w_align; |
---|
1596 | 1602 | int i, depth, depth_bytes, height; |
---|
1597 | 1603 | unsigned int stride = 0; |
---|
| 1604 | + const struct v4l2_format_info *finfo; |
---|
1598 | 1605 | |
---|
1599 | 1606 | if (!fmt || !(fmt->types & type)) { |
---|
1600 | 1607 | vpe_dbg(ctx->dev, "Fourcc format (0x%08x) invalid.\n", |
---|
.. | .. |
---|
1602 | 1609 | fmt = __find_format(V4L2_PIX_FMT_YUYV); |
---|
1603 | 1610 | } |
---|
1604 | 1611 | |
---|
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) |
---|
1607 | 1616 | pix->field = V4L2_FIELD_NONE; |
---|
1608 | 1617 | |
---|
1609 | 1618 | depth = fmt->vpdma_fmt[VPE_LUMA]->depth; |
---|
.. | .. |
---|
1652 | 1661 | pix->num_planes = 1; |
---|
1653 | 1662 | |
---|
1654 | 1663 | pix->pixelformat = fmt->fourcc; |
---|
| 1664 | + finfo = v4l2_format_info(fmt->fourcc); |
---|
1655 | 1665 | |
---|
1656 | 1666 | /* |
---|
1657 | 1667 | * 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. |
---|
1659 | 1669 | */ |
---|
1660 | | - if (pix->field == V4L2_FIELD_SEQ_TB) |
---|
| 1670 | + if (pix->field == V4L2_FIELD_SEQ_TB || pix->field == V4L2_FIELD_SEQ_BT) |
---|
1661 | 1671 | height = pix->height / 2; |
---|
1662 | 1672 | else |
---|
1663 | 1673 | height = pix->height; |
---|
1664 | 1674 | |
---|
1665 | 1675 | 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)) { |
---|
1670 | 1677 | pix->colorspace = V4L2_COLORSPACE_SRGB; |
---|
1671 | 1678 | } else { |
---|
1672 | 1679 | if (height > 1280) /* HD */ |
---|
.. | .. |
---|
1714 | 1721 | |
---|
1715 | 1722 | static int vpe_try_fmt(struct file *file, void *priv, struct v4l2_format *f) |
---|
1716 | 1723 | { |
---|
1717 | | - struct vpe_ctx *ctx = file2ctx(file); |
---|
| 1724 | + struct vpe_ctx *ctx = file->private_data; |
---|
1718 | 1725 | struct vpe_fmt *fmt = find_format(f); |
---|
1719 | 1726 | |
---|
1720 | 1727 | if (V4L2_TYPE_IS_OUTPUT(f->type)) |
---|
.. | .. |
---|
1726 | 1733 | static int __vpe_s_fmt(struct vpe_ctx *ctx, struct v4l2_format *f) |
---|
1727 | 1734 | { |
---|
1728 | 1735 | 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; |
---|
1730 | 1737 | struct vpe_q_data *q_data; |
---|
1731 | 1738 | struct vb2_queue *vq; |
---|
1732 | | - int i; |
---|
1733 | 1739 | |
---|
1734 | 1740 | vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type); |
---|
1735 | 1741 | if (!vq) |
---|
.. | .. |
---|
1744 | 1750 | if (!q_data) |
---|
1745 | 1751 | return -EINVAL; |
---|
1746 | 1752 | |
---|
| 1753 | + qpix = &q_data->format.fmt.pix_mp; |
---|
1747 | 1754 | 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; |
---|
1760 | 1756 | |
---|
1761 | 1757 | q_data->c_rect.left = 0; |
---|
1762 | 1758 | 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; |
---|
1765 | 1761 | |
---|
1766 | | - if (q_data->field == V4L2_FIELD_ALTERNATE) |
---|
| 1762 | + if (qpix->field == V4L2_FIELD_ALTERNATE) |
---|
1767 | 1763 | 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) |
---|
1769 | 1765 | 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; |
---|
1770 | 1768 | else |
---|
1771 | 1769 | q_data->flags &= ~Q_IS_INTERLACED; |
---|
1772 | 1770 | |
---|
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) |
---|
1775 | 1773 | q_data->c_rect.height /= 2; |
---|
1776 | 1774 | |
---|
1777 | 1775 | 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) |
---|
1781 | 1779 | vpe_dbg(ctx->dev, " bpl_uv %d\n", |
---|
1782 | | - q_data->bytesperline[VPE_CHROMA]); |
---|
| 1780 | + pix->plane_fmt[1].bytesperline); |
---|
1783 | 1781 | |
---|
1784 | 1782 | return 0; |
---|
1785 | 1783 | } |
---|
.. | .. |
---|
1787 | 1785 | static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) |
---|
1788 | 1786 | { |
---|
1789 | 1787 | int ret; |
---|
1790 | | - struct vpe_ctx *ctx = file2ctx(file); |
---|
| 1788 | + struct vpe_ctx *ctx = file->private_data; |
---|
1791 | 1789 | |
---|
1792 | 1790 | ret = vpe_try_fmt(file, priv, f); |
---|
1793 | 1791 | if (ret) |
---|
.. | .. |
---|
1808 | 1806 | static int __vpe_try_selection(struct vpe_ctx *ctx, struct v4l2_selection *s) |
---|
1809 | 1807 | { |
---|
1810 | 1808 | struct vpe_q_data *q_data; |
---|
| 1809 | + struct v4l2_pix_format_mplane *pix; |
---|
1811 | 1810 | int height; |
---|
1812 | 1811 | |
---|
1813 | 1812 | if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && |
---|
.. | .. |
---|
1817 | 1816 | q_data = get_q_data(ctx, s->type); |
---|
1818 | 1817 | if (!q_data) |
---|
1819 | 1818 | return -EINVAL; |
---|
| 1819 | + |
---|
| 1820 | + pix = &q_data->format.fmt.pix_mp; |
---|
1820 | 1821 | |
---|
1821 | 1822 | switch (s->target) { |
---|
1822 | 1823 | case V4L2_SEL_TGT_COMPOSE: |
---|
.. | .. |
---|
1844 | 1845 | } |
---|
1845 | 1846 | |
---|
1846 | 1847 | /* |
---|
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 |
---|
1848 | 1849 | * the field height, not the buffer height |
---|
1849 | 1850 | */ |
---|
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; |
---|
1852 | 1853 | else |
---|
1853 | | - height = q_data->height; |
---|
| 1854 | + height = pix->height; |
---|
1854 | 1855 | |
---|
1855 | 1856 | if (s->r.top < 0 || s->r.left < 0) { |
---|
1856 | 1857 | vpe_err(ctx->dev, "negative values for top and left\n"); |
---|
1857 | 1858 | s->r.top = s->r.left = 0; |
---|
1858 | 1859 | } |
---|
1859 | 1860 | |
---|
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, |
---|
1861 | 1862 | &s->r.height, MIN_H, height, H_ALIGN, S_ALIGN); |
---|
1862 | 1863 | |
---|
1863 | 1864 | /* 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; |
---|
1868 | 1869 | |
---|
1869 | 1870 | return 0; |
---|
1870 | 1871 | } |
---|
.. | .. |
---|
1872 | 1873 | static int vpe_g_selection(struct file *file, void *fh, |
---|
1873 | 1874 | struct v4l2_selection *s) |
---|
1874 | 1875 | { |
---|
1875 | | - struct vpe_ctx *ctx = file2ctx(file); |
---|
| 1876 | + struct vpe_ctx *ctx = file->private_data; |
---|
1876 | 1877 | struct vpe_q_data *q_data; |
---|
| 1878 | + struct v4l2_pix_format_mplane *pix; |
---|
1877 | 1879 | bool use_c_rect = false; |
---|
1878 | 1880 | |
---|
1879 | 1881 | if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) && |
---|
.. | .. |
---|
1883 | 1885 | q_data = get_q_data(ctx, s->type); |
---|
1884 | 1886 | if (!q_data) |
---|
1885 | 1887 | return -EINVAL; |
---|
| 1888 | + |
---|
| 1889 | + pix = &q_data->format.fmt.pix_mp; |
---|
1886 | 1890 | |
---|
1887 | 1891 | switch (s->target) { |
---|
1888 | 1892 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: |
---|
.. | .. |
---|
1922 | 1926 | */ |
---|
1923 | 1927 | s->r.left = 0; |
---|
1924 | 1928 | 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; |
---|
1927 | 1931 | } |
---|
1928 | 1932 | |
---|
1929 | 1933 | return 0; |
---|
.. | .. |
---|
1933 | 1937 | static int vpe_s_selection(struct file *file, void *fh, |
---|
1934 | 1938 | struct v4l2_selection *s) |
---|
1935 | 1939 | { |
---|
1936 | | - struct vpe_ctx *ctx = file2ctx(file); |
---|
| 1940 | + struct vpe_ctx *ctx = file->private_data; |
---|
1937 | 1941 | struct vpe_q_data *q_data; |
---|
1938 | 1942 | struct v4l2_selection sel = *s; |
---|
1939 | 1943 | int ret; |
---|
.. | .. |
---|
1991 | 1995 | static const struct v4l2_ioctl_ops vpe_ioctl_ops = { |
---|
1992 | 1996 | .vidioc_querycap = vpe_querycap, |
---|
1993 | 1997 | |
---|
1994 | | - .vidioc_enum_fmt_vid_cap_mplane = vpe_enum_fmt, |
---|
| 1998 | + .vidioc_enum_fmt_vid_cap = vpe_enum_fmt, |
---|
1995 | 1999 | .vidioc_g_fmt_vid_cap_mplane = vpe_g_fmt, |
---|
1996 | 2000 | .vidioc_try_fmt_vid_cap_mplane = vpe_try_fmt, |
---|
1997 | 2001 | .vidioc_s_fmt_vid_cap_mplane = vpe_s_fmt, |
---|
1998 | 2002 | |
---|
1999 | | - .vidioc_enum_fmt_vid_out_mplane = vpe_enum_fmt, |
---|
| 2003 | + .vidioc_enum_fmt_vid_out = vpe_enum_fmt, |
---|
2000 | 2004 | .vidioc_g_fmt_vid_out_mplane = vpe_g_fmt, |
---|
2001 | 2005 | .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, |
---|
2002 | 2006 | .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, |
---|
.. | .. |
---|
2026 | 2030 | int i; |
---|
2027 | 2031 | struct vpe_ctx *ctx = vb2_get_drv_priv(vq); |
---|
2028 | 2032 | struct vpe_q_data *q_data; |
---|
| 2033 | + struct v4l2_pix_format_mplane *pix; |
---|
2029 | 2034 | |
---|
2030 | 2035 | q_data = get_q_data(ctx, vq->type); |
---|
| 2036 | + if (!q_data) |
---|
| 2037 | + return -EINVAL; |
---|
2031 | 2038 | |
---|
2032 | | - *nplanes = q_data->nplanes; |
---|
| 2039 | + pix = &q_data->format.fmt.pix_mp; |
---|
| 2040 | + *nplanes = pix->num_planes; |
---|
2033 | 2041 | |
---|
2034 | 2042 | for (i = 0; i < *nplanes; i++) |
---|
2035 | | - sizes[i] = q_data->sizeimage[i]; |
---|
| 2043 | + sizes[i] = pix->plane_fmt[i].sizeimage; |
---|
2036 | 2044 | |
---|
2037 | 2045 | vpe_dbg(ctx->dev, "get %d buffer(s) of size %d", *nbuffers, |
---|
2038 | 2046 | sizes[VPE_LUMA]); |
---|
2039 | | - if (q_data->nplanes == 2) |
---|
| 2047 | + if (*nplanes == 2) |
---|
2040 | 2048 | vpe_dbg(ctx->dev, " and %d\n", sizes[VPE_CHROMA]); |
---|
2041 | 2049 | |
---|
2042 | 2050 | return 0; |
---|
.. | .. |
---|
2047 | 2055 | struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); |
---|
2048 | 2056 | struct vpe_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); |
---|
2049 | 2057 | struct vpe_q_data *q_data; |
---|
2050 | | - int i, num_planes; |
---|
| 2058 | + struct v4l2_pix_format_mplane *pix; |
---|
| 2059 | + int i; |
---|
2051 | 2060 | |
---|
2052 | 2061 | vpe_dbg(ctx->dev, "type: %d\n", vb->vb2_queue->type); |
---|
2053 | 2062 | |
---|
2054 | 2063 | 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; |
---|
2056 | 2068 | |
---|
2057 | 2069 | if (vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
---|
2058 | 2070 | if (!(q_data->flags & Q_IS_INTERLACED)) { |
---|
.. | .. |
---|
2060 | 2072 | } else { |
---|
2061 | 2073 | if (vbuf->field != V4L2_FIELD_TOP && |
---|
2062 | 2074 | 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) |
---|
2064 | 2077 | return -EINVAL; |
---|
2065 | 2078 | } |
---|
2066 | 2079 | } |
---|
2067 | 2080 | |
---|
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) { |
---|
2070 | 2083 | vpe_err(ctx->dev, |
---|
2071 | 2084 | "data will not fit into plane (%lu < %lu)\n", |
---|
2072 | 2085 | vb2_plane_size(vb, i), |
---|
2073 | | - (long) q_data->sizeimage[i]); |
---|
| 2086 | + (long)pix->plane_fmt[i].sizeimage); |
---|
2074 | 2087 | return -EINVAL; |
---|
2075 | 2088 | } |
---|
2076 | 2089 | } |
---|
2077 | 2090 | |
---|
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); |
---|
2080 | 2093 | |
---|
2081 | 2094 | return 0; |
---|
2082 | 2095 | } |
---|
.. | .. |
---|
2261 | 2274 | struct vpe_q_data *s_q_data; |
---|
2262 | 2275 | struct v4l2_ctrl_handler *hdl; |
---|
2263 | 2276 | struct vpe_ctx *ctx; |
---|
| 2277 | + struct v4l2_pix_format_mplane *pix; |
---|
2264 | 2278 | int ret; |
---|
2265 | 2279 | |
---|
2266 | 2280 | vpe_dbg(dev, "vpe_open\n"); |
---|
.. | .. |
---|
2296 | 2310 | init_adb_hdrs(ctx); |
---|
2297 | 2311 | |
---|
2298 | 2312 | v4l2_fh_init(&ctx->fh, video_devdata(file)); |
---|
2299 | | - file->private_data = &ctx->fh; |
---|
| 2313 | + file->private_data = ctx; |
---|
2300 | 2314 | |
---|
2301 | 2315 | hdl = &ctx->hdl; |
---|
2302 | 2316 | v4l2_ctrl_handler_init(hdl, 1); |
---|
.. | .. |
---|
2309 | 2323 | v4l2_ctrl_handler_setup(hdl); |
---|
2310 | 2324 | |
---|
2311 | 2325 | s_q_data = &ctx->q_data[Q_DATA_SRC]; |
---|
| 2326 | + pix = &s_q_data->format.fmt.pix_mp; |
---|
2312 | 2327 | 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 * |
---|
2317 | 2334 | 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; |
---|
2322 | 2343 | s_q_data->c_rect.left = 0; |
---|
2323 | 2344 | 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; |
---|
2326 | 2347 | s_q_data->flags = 0; |
---|
2327 | 2348 | |
---|
2328 | 2349 | 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; |
---|
2329 | 2352 | |
---|
2330 | 2353 | set_dei_shadow_registers(ctx); |
---|
2331 | 2354 | set_src_registers(ctx); |
---|
.. | .. |
---|
2381 | 2404 | static int vpe_release(struct file *file) |
---|
2382 | 2405 | { |
---|
2383 | 2406 | struct vpe_dev *dev = video_drvdata(file); |
---|
2384 | | - struct vpe_ctx *ctx = file2ctx(file); |
---|
| 2407 | + struct vpe_ctx *ctx = file->private_data; |
---|
2385 | 2408 | |
---|
2386 | 2409 | vpe_dbg(dev, "releasing instance %p\n", ctx); |
---|
2387 | 2410 | |
---|
.. | .. |
---|
2435 | 2458 | .minor = -1, |
---|
2436 | 2459 | .release = video_device_release_empty, |
---|
2437 | 2460 | .vfl_dir = VFL_DIR_M2M, |
---|
| 2461 | + .device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING, |
---|
2438 | 2462 | }; |
---|
2439 | 2463 | |
---|
2440 | 2464 | static const struct v4l2_m2m_ops m2m_ops = { |
---|
.. | .. |
---|
2478 | 2502 | vfd->lock = &dev->dev_mutex; |
---|
2479 | 2503 | vfd->v4l2_dev = &dev->v4l2_dev; |
---|
2480 | 2504 | |
---|
2481 | | - ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); |
---|
| 2505 | + ret = video_register_device(vfd, VFL_TYPE_VIDEO, 0); |
---|
2482 | 2506 | if (ret) { |
---|
2483 | 2507 | vpe_err(dev, "Failed to register video device\n"); |
---|
2484 | 2508 | |
---|
.. | .. |
---|
2501 | 2525 | struct vpe_dev *dev; |
---|
2502 | 2526 | int ret, irq, func; |
---|
2503 | 2527 | |
---|
| 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 | + |
---|
2504 | 2535 | dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); |
---|
2505 | 2536 | if (!dev) |
---|
2506 | 2537 | return -ENOMEM; |
---|
.. | .. |
---|
2515 | 2546 | mutex_init(&dev->dev_mutex); |
---|
2516 | 2547 | |
---|
2517 | 2548 | 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 | + |
---|
2519 | 2555 | /* |
---|
2520 | 2556 | * HACK: we get resource info from device tree in the form of a list of |
---|
2521 | 2557 | * VPE sub blocks, the driver currently uses only the base of vpe_top |
---|
.. | .. |
---|
2610 | 2646 | #if defined(CONFIG_OF) |
---|
2611 | 2647 | static const struct of_device_id vpe_of_match[] = { |
---|
2612 | 2648 | { |
---|
2613 | | - .compatible = "ti,vpe", |
---|
| 2649 | + .compatible = "ti,dra7-vpe", |
---|
2614 | 2650 | }, |
---|
2615 | 2651 | {}, |
---|
2616 | 2652 | }; |
---|