1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * V4L2 Capture ISI subdev driver for i.MX8QXP/QM platform
4 *
5 * ISI is a Image Sensor Interface of i.MX8QXP/QM platform, which
6 * used to process image from camera sensor to memory or DC
7 *
8 * Copyright (c) 2019 NXP Semiconductor
9 */
10
11 #include <linux/device.h>
12 #include <linux/dma-mapping.h>
13 #include <linux/errno.h>
14 #include <linux/kernel.h>
15 #include <linux/media-bus-format.h>
16 #include <linux/minmax.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/string.h>
19 #include <linux/types.h>
20 #include <linux/videodev2.h>
21
22 #include <media/media-entity.h>
23 #include <media/v4l2-ctrls.h>
24 #include <media/v4l2-dev.h>
25 #include <media/v4l2-event.h>
26 #include <media/v4l2-fh.h>
27 #include <media/v4l2-ioctl.h>
28 #include <media/v4l2-subdev.h>
29 #include <media/videobuf2-core.h>
30 #include <media/videobuf2-dma-contig.h>
31 #include <media/videobuf2-v4l2.h>
32
33 #include "imx8-isi-core.h"
34 #include "imx8-isi-regs.h"
35
36 /* Keep the first entry matching MXC_ISI_DEF_PIXEL_FORMAT */
37 static const struct mxc_isi_format_info mxc_isi_formats[] = {
38 /* YUV formats */
39 {
40 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24,
41 .fourcc = V4L2_PIX_FMT_YUYV,
42 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
43 | MXC_ISI_VIDEO_M2M_CAP,
44 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_YUV422_1P8P,
45 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV422_1P8P,
46 .mem_planes = 1,
47 .color_planes = 1,
48 .depth = { 16 },
49 .encoding = MXC_ISI_ENC_YUV,
50 }, {
51 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24,
52 .fourcc = V4L2_PIX_FMT_YUVA32,
53 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
54 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV444_1P8,
55 .mem_planes = 1,
56 .color_planes = 1,
57 .depth = { 32 },
58 .encoding = MXC_ISI_ENC_YUV,
59 }, {
60 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24,
61 .fourcc = V4L2_PIX_FMT_NV12,
62 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
63 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV420_2P8P,
64 .color_planes = 2,
65 .mem_planes = 1,
66 .depth = { 8, 16 },
67 .hsub = 2,
68 .vsub = 2,
69 .encoding = MXC_ISI_ENC_YUV,
70 }, {
71 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24,
72 .fourcc = V4L2_PIX_FMT_NV12M,
73 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
74 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV420_2P8P,
75 .mem_planes = 2,
76 .color_planes = 2,
77 .depth = { 8, 16 },
78 .hsub = 2,
79 .vsub = 2,
80 .encoding = MXC_ISI_ENC_YUV,
81 }, {
82 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24,
83 .fourcc = V4L2_PIX_FMT_NV16,
84 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
85 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV422_2P8P,
86 .color_planes = 2,
87 .mem_planes = 1,
88 .depth = { 8, 16 },
89 .hsub = 2,
90 .vsub = 1,
91 .encoding = MXC_ISI_ENC_YUV,
92 }, {
93 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24,
94 .fourcc = V4L2_PIX_FMT_NV16M,
95 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
96 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV422_2P8P,
97 .mem_planes = 2,
98 .color_planes = 2,
99 .depth = { 8, 16 },
100 .hsub = 2,
101 .vsub = 1,
102 .encoding = MXC_ISI_ENC_YUV,
103 }, {
104 .mbus_code = MEDIA_BUS_FMT_YUV8_1X24,
105 .fourcc = V4L2_PIX_FMT_YUV444M,
106 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
107 .isi_out_format = CHNL_IMG_CTRL_FORMAT_YUV444_3P8P,
108 .mem_planes = 3,
109 .color_planes = 3,
110 .depth = { 8, 8, 8 },
111 .hsub = 1,
112 .vsub = 1,
113 .encoding = MXC_ISI_ENC_YUV,
114 },
115 /* RGB formats */
116 {
117 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
118 .fourcc = V4L2_PIX_FMT_RGB565,
119 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
120 | MXC_ISI_VIDEO_M2M_CAP,
121 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_RGB565,
122 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RGB565,
123 .mem_planes = 1,
124 .color_planes = 1,
125 .depth = { 16 },
126 .encoding = MXC_ISI_ENC_RGB,
127 }, {
128 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
129 .fourcc = V4L2_PIX_FMT_RGB24,
130 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
131 | MXC_ISI_VIDEO_M2M_CAP,
132 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_BGR8P,
133 .isi_out_format = CHNL_IMG_CTRL_FORMAT_BGR888P,
134 .mem_planes = 1,
135 .color_planes = 1,
136 .depth = { 24 },
137 .encoding = MXC_ISI_ENC_RGB,
138 }, {
139 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
140 .fourcc = V4L2_PIX_FMT_BGR24,
141 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
142 | MXC_ISI_VIDEO_M2M_CAP,
143 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_RGB8P,
144 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RGB888P,
145 .mem_planes = 1,
146 .color_planes = 1,
147 .depth = { 24 },
148 .encoding = MXC_ISI_ENC_RGB,
149 }, {
150 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
151 .fourcc = V4L2_PIX_FMT_XBGR32,
152 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_OUT
153 | MXC_ISI_VIDEO_M2M_CAP,
154 .isi_in_format = CHNL_MEM_RD_CTRL_IMG_TYPE_XBGR8,
155 .isi_out_format = CHNL_IMG_CTRL_FORMAT_XRGB888,
156 .mem_planes = 1,
157 .color_planes = 1,
158 .depth = { 32 },
159 .encoding = MXC_ISI_ENC_RGB,
160 }, {
161 .mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
162 .fourcc = V4L2_PIX_FMT_ABGR32,
163 .type = MXC_ISI_VIDEO_CAP | MXC_ISI_VIDEO_M2M_CAP,
164 .isi_out_format = CHNL_IMG_CTRL_FORMAT_ARGB8888,
165 .mem_planes = 1,
166 .color_planes = 1,
167 .depth = { 32 },
168 .encoding = MXC_ISI_ENC_RGB,
169 },
170 /*
171 * RAW formats
172 *
173 * The ISI shifts the 10-bit and 12-bit formats left by 6 and 4 bits
174 * when using CHNL_IMG_CTRL_FORMAT_RAW10 or MXC_ISI_OUT_FMT_RAW12
175 * respectively, to align the bits to the left and pad with zeros in
176 * the LSBs. The corresponding V4L2 formats are however right-aligned,
177 * we have to use CHNL_IMG_CTRL_FORMAT_RAW16 to avoid the left shift.
178 */
179 {
180 .mbus_code = MEDIA_BUS_FMT_Y8_1X8,
181 .fourcc = V4L2_PIX_FMT_GREY,
182 .type = MXC_ISI_VIDEO_CAP,
183 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
184 .mem_planes = 1,
185 .color_planes = 1,
186 .depth = { 8 },
187 .encoding = MXC_ISI_ENC_RAW,
188 }, {
189 .mbus_code = MEDIA_BUS_FMT_Y10_1X10,
190 .fourcc = V4L2_PIX_FMT_Y10,
191 .type = MXC_ISI_VIDEO_CAP,
192 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
193 .mem_planes = 1,
194 .color_planes = 1,
195 .depth = { 16 },
196 .encoding = MXC_ISI_ENC_RAW,
197 }, {
198 .mbus_code = MEDIA_BUS_FMT_Y12_1X12,
199 .fourcc = V4L2_PIX_FMT_Y12,
200 .type = MXC_ISI_VIDEO_CAP,
201 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
202 .mem_planes = 1,
203 .color_planes = 1,
204 .depth = { 16 },
205 .encoding = MXC_ISI_ENC_RAW,
206 }, {
207 .mbus_code = MEDIA_BUS_FMT_Y14_1X14,
208 .fourcc = V4L2_PIX_FMT_Y14,
209 .type = MXC_ISI_VIDEO_CAP,
210 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
211 .mem_planes = 1,
212 .color_planes = 1,
213 .depth = { 16 },
214 .encoding = MXC_ISI_ENC_RAW,
215 }, {
216 .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
217 .fourcc = V4L2_PIX_FMT_SBGGR8,
218 .type = MXC_ISI_VIDEO_CAP,
219 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
220 .mem_planes = 1,
221 .color_planes = 1,
222 .depth = { 8 },
223 .encoding = MXC_ISI_ENC_RAW,
224 }, {
225 .mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
226 .fourcc = V4L2_PIX_FMT_SGBRG8,
227 .type = MXC_ISI_VIDEO_CAP,
228 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
229 .mem_planes = 1,
230 .color_planes = 1,
231 .depth = { 8 },
232 .encoding = MXC_ISI_ENC_RAW,
233 }, {
234 .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
235 .fourcc = V4L2_PIX_FMT_SGRBG8,
236 .type = MXC_ISI_VIDEO_CAP,
237 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
238 .mem_planes = 1,
239 .color_planes = 1,
240 .depth = { 8 },
241 .encoding = MXC_ISI_ENC_RAW,
242 }, {
243 .mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
244 .fourcc = V4L2_PIX_FMT_SRGGB8,
245 .type = MXC_ISI_VIDEO_CAP,
246 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
247 .mem_planes = 1,
248 .color_planes = 1,
249 .depth = { 8 },
250 .encoding = MXC_ISI_ENC_RAW,
251 }, {
252 .mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
253 .fourcc = V4L2_PIX_FMT_SBGGR10,
254 .type = MXC_ISI_VIDEO_CAP,
255 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
256 .mem_planes = 1,
257 .color_planes = 1,
258 .depth = { 16 },
259 .encoding = MXC_ISI_ENC_RAW,
260 }, {
261 .mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
262 .fourcc = V4L2_PIX_FMT_SGBRG10,
263 .type = MXC_ISI_VIDEO_CAP,
264 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
265 .mem_planes = 1,
266 .color_planes = 1,
267 .depth = { 16 },
268 .encoding = MXC_ISI_ENC_RAW,
269 }, {
270 .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
271 .fourcc = V4L2_PIX_FMT_SGRBG10,
272 .type = MXC_ISI_VIDEO_CAP,
273 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
274 .mem_planes = 1,
275 .color_planes = 1,
276 .depth = { 16 },
277 .encoding = MXC_ISI_ENC_RAW,
278 }, {
279 .mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
280 .fourcc = V4L2_PIX_FMT_SRGGB10,
281 .type = MXC_ISI_VIDEO_CAP,
282 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
283 .mem_planes = 1,
284 .color_planes = 1,
285 .depth = { 16 },
286 .encoding = MXC_ISI_ENC_RAW,
287 }, {
288 .mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
289 .fourcc = V4L2_PIX_FMT_SBGGR12,
290 .type = MXC_ISI_VIDEO_CAP,
291 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
292 .mem_planes = 1,
293 .color_planes = 1,
294 .depth = { 16 },
295 .encoding = MXC_ISI_ENC_RAW,
296 }, {
297 .mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
298 .fourcc = V4L2_PIX_FMT_SGBRG12,
299 .type = MXC_ISI_VIDEO_CAP,
300 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
301 .mem_planes = 1,
302 .color_planes = 1,
303 .depth = { 16 },
304 .encoding = MXC_ISI_ENC_RAW,
305 }, {
306 .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
307 .fourcc = V4L2_PIX_FMT_SGRBG12,
308 .type = MXC_ISI_VIDEO_CAP,
309 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
310 .mem_planes = 1,
311 .color_planes = 1,
312 .depth = { 16 },
313 .encoding = MXC_ISI_ENC_RAW,
314 }, {
315 .mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
316 .fourcc = V4L2_PIX_FMT_SRGGB12,
317 .type = MXC_ISI_VIDEO_CAP,
318 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
319 .mem_planes = 1,
320 .color_planes = 1,
321 .depth = { 16 },
322 .encoding = MXC_ISI_ENC_RAW,
323 }, {
324 .mbus_code = MEDIA_BUS_FMT_SBGGR14_1X14,
325 .fourcc = V4L2_PIX_FMT_SBGGR14,
326 .type = MXC_ISI_VIDEO_CAP,
327 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
328 .mem_planes = 1,
329 .color_planes = 1,
330 .depth = { 16 },
331 .encoding = MXC_ISI_ENC_RAW,
332 }, {
333 .mbus_code = MEDIA_BUS_FMT_SGBRG14_1X14,
334 .fourcc = V4L2_PIX_FMT_SGBRG14,
335 .type = MXC_ISI_VIDEO_CAP,
336 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
337 .mem_planes = 1,
338 .color_planes = 1,
339 .depth = { 16 },
340 .encoding = MXC_ISI_ENC_RAW,
341 }, {
342 .mbus_code = MEDIA_BUS_FMT_SGRBG14_1X14,
343 .fourcc = V4L2_PIX_FMT_SGRBG14,
344 .type = MXC_ISI_VIDEO_CAP,
345 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
346 .mem_planes = 1,
347 .color_planes = 1,
348 .depth = { 16 },
349 .encoding = MXC_ISI_ENC_RAW,
350 }, {
351 .mbus_code = MEDIA_BUS_FMT_SRGGB14_1X14,
352 .fourcc = V4L2_PIX_FMT_SRGGB14,
353 .type = MXC_ISI_VIDEO_CAP,
354 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW16,
355 .mem_planes = 1,
356 .color_planes = 1,
357 .depth = { 16 },
358 .encoding = MXC_ISI_ENC_RAW,
359 },
360 /* JPEG */
361 {
362 .mbus_code = MEDIA_BUS_FMT_JPEG_1X8,
363 .fourcc = V4L2_PIX_FMT_MJPEG,
364 .type = MXC_ISI_VIDEO_CAP,
365 .isi_out_format = CHNL_IMG_CTRL_FORMAT_RAW8,
366 .mem_planes = 1,
367 .color_planes = 1,
368 .depth = { 8 },
369 .encoding = MXC_ISI_ENC_RAW,
370 }
371 };
372
373 const struct mxc_isi_format_info *
mxc_isi_format_by_fourcc(u32 fourcc,enum mxc_isi_video_type type)374 mxc_isi_format_by_fourcc(u32 fourcc, enum mxc_isi_video_type type)
375 {
376 unsigned int i;
377
378 for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
379 const struct mxc_isi_format_info *fmt = &mxc_isi_formats[i];
380
381 if (fmt->fourcc == fourcc && fmt->type & type)
382 return fmt;
383 }
384
385 return NULL;
386 }
387
388 const struct mxc_isi_format_info *
mxc_isi_format_enum(unsigned int index,enum mxc_isi_video_type type)389 mxc_isi_format_enum(unsigned int index, enum mxc_isi_video_type type)
390 {
391 unsigned int i;
392
393 for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
394 const struct mxc_isi_format_info *fmt = &mxc_isi_formats[i];
395
396 if (!(fmt->type & type))
397 continue;
398
399 if (!index)
400 return fmt;
401
402 index--;
403 }
404
405 return NULL;
406 }
407
408 const struct mxc_isi_format_info *
mxc_isi_format_try(struct mxc_isi_pipe * pipe,struct v4l2_pix_format_mplane * pix,enum mxc_isi_video_type type)409 mxc_isi_format_try(struct mxc_isi_pipe *pipe, struct v4l2_pix_format_mplane *pix,
410 enum mxc_isi_video_type type)
411 {
412 const struct mxc_isi_format_info *fmt;
413 unsigned int max_width;
414 unsigned int i;
415
416 max_width = pipe->id == pipe->isi->pdata->num_channels - 1
417 ? MXC_ISI_MAX_WIDTH_UNCHAINED
418 : MXC_ISI_MAX_WIDTH_CHAINED;
419
420 fmt = mxc_isi_format_by_fourcc(pix->pixelformat, type);
421 if (!fmt)
422 fmt = &mxc_isi_formats[0];
423
424 pix->width = clamp(pix->width, MXC_ISI_MIN_WIDTH, max_width);
425 pix->height = clamp(pix->height, MXC_ISI_MIN_HEIGHT, MXC_ISI_MAX_HEIGHT);
426 pix->pixelformat = fmt->fourcc;
427 pix->field = V4L2_FIELD_NONE;
428
429 if (pix->colorspace == V4L2_COLORSPACE_DEFAULT) {
430 pix->colorspace = MXC_ISI_DEF_COLOR_SPACE;
431 pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC;
432 pix->quantization = MXC_ISI_DEF_QUANTIZATION;
433 pix->xfer_func = MXC_ISI_DEF_XFER_FUNC;
434 }
435
436 if (pix->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT)
437 pix->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(pix->colorspace);
438 if (pix->quantization == V4L2_QUANTIZATION_DEFAULT) {
439 bool is_rgb = fmt->encoding == MXC_ISI_ENC_RGB;
440
441 pix->quantization =
442 V4L2_MAP_QUANTIZATION_DEFAULT(is_rgb, pix->colorspace,
443 pix->ycbcr_enc);
444 }
445 if (pix->xfer_func == V4L2_XFER_FUNC_DEFAULT)
446 pix->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(pix->colorspace);
447
448 pix->num_planes = fmt->mem_planes;
449
450 for (i = 0; i < fmt->color_planes; ++i) {
451 struct v4l2_plane_pix_format *plane = &pix->plane_fmt[i];
452 unsigned int bpl;
453
454 /* The pitch must be identical for all planes. */
455 if (i == 0)
456 bpl = clamp(plane->bytesperline,
457 pix->width * fmt->depth[0] / 8,
458 65535U);
459 else
460 bpl = pix->plane_fmt[0].bytesperline;
461
462 plane->bytesperline = bpl;
463
464 plane->sizeimage = plane->bytesperline * pix->height;
465 if (i >= 1)
466 plane->sizeimage /= fmt->vsub;
467 }
468
469 /*
470 * For single-planar pixel formats with multiple color planes,
471 * concatenate the size of all planes and clear all planes but the
472 * first one.
473 */
474 if (fmt->color_planes != fmt->mem_planes) {
475 for (i = 1; i < fmt->color_planes; ++i) {
476 struct v4l2_plane_pix_format *plane = &pix->plane_fmt[i];
477
478 pix->plane_fmt[0].sizeimage += plane->sizeimage;
479 plane->bytesperline = 0;
480 plane->sizeimage = 0;
481 }
482 }
483
484 return fmt;
485 }
486
487 /* -----------------------------------------------------------------------------
488 * videobuf2 queue operations
489 */
490
mxc_isi_video_frame_write_done(struct mxc_isi_pipe * pipe,u32 status)491 static void mxc_isi_video_frame_write_done(struct mxc_isi_pipe *pipe,
492 u32 status)
493 {
494 struct mxc_isi_video *video = &pipe->video;
495 struct device *dev = pipe->isi->dev;
496 struct mxc_isi_buffer *next_buf;
497 struct mxc_isi_buffer *buf;
498 enum mxc_isi_buf_id buf_id;
499
500 spin_lock(&video->buf_lock);
501
502 /*
503 * The ISI hardware handles buffers using a ping-pong mechanism with
504 * two sets of destination addresses (with shadow registers to allow
505 * programming addresses for all planes atomically) named BUF1 and
506 * BUF2. Addresses can be loaded and copied to shadow registers at any
507 * at any time.
508 *
509 * The hardware keeps track of which buffer is being written to and
510 * automatically switches to the other buffer at frame end, copying the
511 * corresponding address to another set of shadow registers that track
512 * the address being written to. The active buffer tracking bits are
513 * accessible through the CHNL_STS register.
514 *
515 * BUF1 BUF2 | Event | Action
516 * | |
517 * | | Program initial buffers
518 * | | B0 in BUF1, B1 in BUF2
519 * | Start ISI |
520 * +----+ | |
521 * | B0 | | |
522 * +----+ | |
523 * +----+ | FRM IRQ 0 | B0 complete, BUF2 now active
524 * | B1 | | | Program B2 in BUF1
525 * +----+ | |
526 * +----+ | FRM IRQ 1 | B1 complete, BUF1 now active
527 * | B2 | | | Program B3 in BUF2
528 * +----+ | |
529 * +----+ | FRM IRQ 2 | B2 complete, BUF2 now active
530 * | B3 | | | Program B4 in BUF1
531 * +----+ | |
532 * +----+ | FRM IRQ 3 | B3 complete, BUF1 now active
533 * | B4 | | | Program B5 in BUF2
534 * +----+ | |
535 * ... | |
536 *
537 * Races between address programming and buffer switching can be
538 * detected by checking if a frame end interrupt occurred after
539 * programming the addresses.
540 *
541 * As none of the shadow registers are accessible, races can occur
542 * between address programming and buffer switching. It is possible to
543 * detect the race condition by checking if a frame end interrupt
544 * occurred after programming the addresses, but impossible to
545 * determine if the race has been won or lost.
546 *
547 * In addition to this, we need to use discard buffers if no pending
548 * buffers are available. To simplify handling of discard buffer, we
549 * need to allocate three of them, as two can be active concurrently
550 * and we need to still be able to get hold of a next buffer. The logic
551 * could be improved to use two buffers only, but as all discard
552 * buffers share the same memory, an additional buffer is cheap.
553 */
554
555 /* Check which buffer has just completed. */
556 buf_id = pipe->isi->pdata->buf_active_reverse
557 ? (status & CHNL_STS_BUF1_ACTIVE ? MXC_ISI_BUF2 : MXC_ISI_BUF1)
558 : (status & CHNL_STS_BUF1_ACTIVE ? MXC_ISI_BUF1 : MXC_ISI_BUF2);
559
560 buf = list_first_entry_or_null(&video->out_active,
561 struct mxc_isi_buffer, list);
562
563 /* Safety check, this should really never happen. */
564 if (!buf) {
565 dev_warn(dev, "trying to access empty active list\n");
566 goto done;
567 }
568
569 /*
570 * If the buffer that has completed doesn't match the buffer on the
571 * front of the active list, it means we have lost one frame end
572 * interrupt (or possibly a large odd number of interrupts, although
573 * quite unlikely).
574 *
575 * For instance, if IRQ1 is lost and we handle IRQ2, both B1 and B2
576 * have been completed, but B3 hasn't been programmed, BUF2 still
577 * addresses B1 and the ISI is now writing in B1 instead of B3. We
578 * can't complete B2 as that would result in out-of-order completion.
579 *
580 * The only option is to ignore this interrupt and try again. When IRQ3
581 * will be handled, we will complete B1 and be in sync again.
582 */
583 if (buf->id != buf_id) {
584 dev_dbg(dev, "buffer ID mismatch (expected %u, got %u), skipping\n",
585 buf->id, buf_id);
586
587 /*
588 * Increment the frame count by two to account for the missed
589 * and the ignored interrupts.
590 */
591 video->frame_count += 2;
592 goto done;
593 }
594
595 /* Pick the next buffer and queue it to the hardware. */
596 next_buf = list_first_entry_or_null(&video->out_pending,
597 struct mxc_isi_buffer, list);
598 if (!next_buf) {
599 next_buf = list_first_entry_or_null(&video->out_discard,
600 struct mxc_isi_buffer, list);
601
602 /* Safety check, this should never happen. */
603 if (!next_buf) {
604 dev_warn(dev, "trying to access empty discard list\n");
605 goto done;
606 }
607 }
608
609 mxc_isi_channel_set_outbuf(pipe, next_buf->dma_addrs, buf_id);
610 next_buf->id = buf_id;
611
612 /*
613 * Check if we have raced with the end of frame interrupt. If so, we
614 * can't tell if the ISI has recorded the new address, or is still
615 * using the previous buffer. We must assume the latter as that is the
616 * worst case.
617 *
618 * For instance, if we are handling IRQ1 and now detect the FRM
619 * interrupt, assume B2 has completed and the ISI has switched to BUF2
620 * using B1 just before we programmed B3. Unlike in the previous race
621 * condition, B3 has been programmed and will be written to the next
622 * time the ISI switches to BUF2. We can however handle this exactly as
623 * the first race condition, as we'll program B3 (still at the head of
624 * the pending list) when handling IRQ3.
625 */
626 status = mxc_isi_channel_irq_status(pipe, false);
627 if (status & CHNL_STS_FRM_STRD) {
628 dev_dbg(dev, "raced with frame end interrupt\n");
629 video->frame_count += 2;
630 goto done;
631 }
632
633 /*
634 * The next buffer has been queued successfully, move it to the active
635 * list, and complete the current buffer.
636 */
637 list_move_tail(&next_buf->list, &video->out_active);
638
639 if (!buf->discard) {
640 list_del_init(&buf->list);
641 buf->v4l2_buf.sequence = video->frame_count;
642 buf->v4l2_buf.vb2_buf.timestamp = ktime_get_ns();
643 vb2_buffer_done(&buf->v4l2_buf.vb2_buf, VB2_BUF_STATE_DONE);
644 } else {
645 list_move_tail(&buf->list, &video->out_discard);
646 }
647
648 video->frame_count++;
649
650 done:
651 spin_unlock(&video->buf_lock);
652 }
653
mxc_isi_video_free_discard_buffers(struct mxc_isi_video * video)654 static void mxc_isi_video_free_discard_buffers(struct mxc_isi_video *video)
655 {
656 unsigned int i;
657
658 for (i = 0; i < video->pix.num_planes; i++) {
659 struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i];
660
661 if (!buf->addr)
662 continue;
663
664 dma_free_coherent(video->pipe->isi->dev, buf->size, buf->addr,
665 buf->dma);
666 buf->addr = NULL;
667 }
668 }
669
mxc_isi_video_alloc_discard_buffers(struct mxc_isi_video * video)670 static int mxc_isi_video_alloc_discard_buffers(struct mxc_isi_video *video)
671 {
672 unsigned int i, j;
673
674 /* Allocate memory for each plane. */
675 for (i = 0; i < video->pix.num_planes; i++) {
676 struct mxc_isi_dma_buffer *buf = &video->discard_buffer[i];
677
678 buf->size = PAGE_ALIGN(video->pix.plane_fmt[i].sizeimage);
679 buf->addr = dma_alloc_coherent(video->pipe->isi->dev, buf->size,
680 &buf->dma, GFP_DMA | GFP_KERNEL);
681 if (!buf->addr) {
682 mxc_isi_video_free_discard_buffers(video);
683 return -ENOMEM;
684 }
685
686 dev_dbg(video->pipe->isi->dev,
687 "discard buffer plane %u: %zu bytes @%pad (CPU address %p)\n",
688 i, buf->size, &buf->dma, buf->addr);
689 }
690
691 /* Fill the DMA addresses in the discard buffers. */
692 for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) {
693 struct mxc_isi_buffer *buf = &video->buf_discard[i];
694
695 buf->discard = true;
696
697 for (j = 0; j < video->pix.num_planes; ++j)
698 buf->dma_addrs[j] = video->discard_buffer[j].dma;
699 }
700
701 return 0;
702 }
703
mxc_isi_video_validate_format(struct mxc_isi_video * video)704 static int mxc_isi_video_validate_format(struct mxc_isi_video *video)
705 {
706 const struct v4l2_mbus_framefmt *format;
707 const struct mxc_isi_format_info *info;
708 struct v4l2_subdev_state *state;
709 struct v4l2_subdev *sd = &video->pipe->sd;
710 int ret = 0;
711
712 state = v4l2_subdev_lock_and_get_active_state(sd);
713
714 info = mxc_isi_format_by_fourcc(video->pix.pixelformat,
715 MXC_ISI_VIDEO_CAP);
716 format = v4l2_subdev_get_try_format(sd, state, MXC_ISI_PIPE_PAD_SOURCE);
717
718 if (format->code != info->mbus_code ||
719 format->width != video->pix.width ||
720 format->height != video->pix.height) {
721 dev_dbg(video->pipe->isi->dev,
722 "%s: configuration mismatch, 0x%04x/%ux%u != 0x%04x/%ux%u\n",
723 __func__, format->code, format->width, format->height,
724 info->mbus_code, video->pix.width, video->pix.height);
725 ret = -EINVAL;
726 }
727
728 v4l2_subdev_unlock_state(state);
729
730 return ret;
731 }
732
mxc_isi_video_return_buffers(struct mxc_isi_video * video,enum vb2_buffer_state state)733 static void mxc_isi_video_return_buffers(struct mxc_isi_video *video,
734 enum vb2_buffer_state state)
735 {
736 struct mxc_isi_buffer *buf;
737
738 spin_lock_irq(&video->buf_lock);
739
740 while (!list_empty(&video->out_active)) {
741 buf = list_first_entry(&video->out_active,
742 struct mxc_isi_buffer, list);
743 list_del_init(&buf->list);
744 if (buf->discard)
745 continue;
746
747 vb2_buffer_done(&buf->v4l2_buf.vb2_buf, state);
748 }
749
750 while (!list_empty(&video->out_pending)) {
751 buf = list_first_entry(&video->out_pending,
752 struct mxc_isi_buffer, list);
753 list_del_init(&buf->list);
754 vb2_buffer_done(&buf->v4l2_buf.vb2_buf, state);
755 }
756
757 while (!list_empty(&video->out_discard)) {
758 buf = list_first_entry(&video->out_discard,
759 struct mxc_isi_buffer, list);
760 list_del_init(&buf->list);
761 }
762
763 INIT_LIST_HEAD(&video->out_active);
764 INIT_LIST_HEAD(&video->out_pending);
765 INIT_LIST_HEAD(&video->out_discard);
766
767 spin_unlock_irq(&video->buf_lock);
768 }
769
mxc_isi_video_queue_first_buffers(struct mxc_isi_video * video)770 static void mxc_isi_video_queue_first_buffers(struct mxc_isi_video *video)
771 {
772 unsigned int discard;
773 unsigned int i;
774
775 lockdep_assert_held(&video->buf_lock);
776
777 /*
778 * Queue two ISI channel output buffers. We are not guaranteed to have
779 * any buffer in the pending list when this function is called from the
780 * system resume handler. Use pending buffers as much as possible, and
781 * use discard buffers to fill the remaining slots.
782 */
783
784 /* How many discard buffers do we need to queue first ? */
785 discard = list_empty(&video->out_pending) ? 2
786 : list_is_singular(&video->out_pending) ? 1
787 : 0;
788
789 for (i = 0; i < 2; ++i) {
790 enum mxc_isi_buf_id buf_id = i == 0 ? MXC_ISI_BUF1
791 : MXC_ISI_BUF2;
792 struct mxc_isi_buffer *buf;
793 struct list_head *list;
794
795 list = i < discard ? &video->out_discard : &video->out_pending;
796 buf = list_first_entry(list, struct mxc_isi_buffer, list);
797
798 mxc_isi_channel_set_outbuf(video->pipe, buf->dma_addrs, buf_id);
799 buf->id = buf_id;
800 list_move_tail(&buf->list, &video->out_active);
801 }
802 }
803
to_isi_buffer(struct vb2_v4l2_buffer * v4l2_buf)804 static inline struct mxc_isi_buffer *to_isi_buffer(struct vb2_v4l2_buffer *v4l2_buf)
805 {
806 return container_of(v4l2_buf, struct mxc_isi_buffer, v4l2_buf);
807 }
808
mxc_isi_video_queue_setup(const struct v4l2_pix_format_mplane * format,const struct mxc_isi_format_info * info,unsigned int * num_buffers,unsigned int * num_planes,unsigned int sizes[])809 int mxc_isi_video_queue_setup(const struct v4l2_pix_format_mplane *format,
810 const struct mxc_isi_format_info *info,
811 unsigned int *num_buffers,
812 unsigned int *num_planes, unsigned int sizes[])
813 {
814 unsigned int i;
815
816 if (*num_planes) {
817 if (*num_planes != info->mem_planes)
818 return -EINVAL;
819
820 for (i = 0; i < info->mem_planes; ++i) {
821 if (sizes[i] < format->plane_fmt[i].sizeimage)
822 return -EINVAL;
823 }
824
825 return 0;
826 }
827
828 *num_planes = info->mem_planes;
829
830 for (i = 0; i < info->mem_planes; ++i)
831 sizes[i] = format->plane_fmt[i].sizeimage;
832
833 return 0;
834 }
835
mxc_isi_video_buffer_init(struct vb2_buffer * vb2,dma_addr_t dma_addrs[3],const struct mxc_isi_format_info * info,const struct v4l2_pix_format_mplane * pix)836 void mxc_isi_video_buffer_init(struct vb2_buffer *vb2, dma_addr_t dma_addrs[3],
837 const struct mxc_isi_format_info *info,
838 const struct v4l2_pix_format_mplane *pix)
839 {
840 unsigned int i;
841
842 for (i = 0; i < info->mem_planes; ++i)
843 dma_addrs[i] = vb2_dma_contig_plane_dma_addr(vb2, i);
844
845 /*
846 * For single-planar pixel formats with multiple color planes, split
847 * the buffer into color planes.
848 */
849 if (info->color_planes != info->mem_planes) {
850 unsigned int size = pix->plane_fmt[0].bytesperline * pix->height;
851
852 for (i = 1; i < info->color_planes; ++i) {
853 unsigned int vsub = i > 1 ? info->vsub : 1;
854
855 dma_addrs[i] = dma_addrs[i - 1] + size / vsub;
856 }
857 }
858 }
859
mxc_isi_video_buffer_prepare(struct mxc_isi_dev * isi,struct vb2_buffer * vb2,const struct mxc_isi_format_info * info,const struct v4l2_pix_format_mplane * pix)860 int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2,
861 const struct mxc_isi_format_info *info,
862 const struct v4l2_pix_format_mplane *pix)
863 {
864 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2);
865 unsigned int i;
866
867 for (i = 0; i < info->mem_planes; i++) {
868 unsigned long size = pix->plane_fmt[i].sizeimage;
869
870 if (vb2_plane_size(vb2, i) < size) {
871 dev_err(isi->dev, "User buffer too small (%ld < %ld)\n",
872 vb2_plane_size(vb2, i), size);
873 return -EINVAL;
874 }
875
876 vb2_set_plane_payload(vb2, i, size);
877 }
878
879 v4l2_buf->field = pix->field;
880
881 return 0;
882 }
883
mxc_isi_vb2_queue_setup(struct vb2_queue * q,unsigned int * num_buffers,unsigned int * num_planes,unsigned int sizes[],struct device * alloc_devs[])884 static int mxc_isi_vb2_queue_setup(struct vb2_queue *q,
885 unsigned int *num_buffers,
886 unsigned int *num_planes,
887 unsigned int sizes[],
888 struct device *alloc_devs[])
889 {
890 struct mxc_isi_video *video = vb2_get_drv_priv(q);
891
892 return mxc_isi_video_queue_setup(&video->pix, video->fmtinfo,
893 num_buffers, num_planes, sizes);
894 }
895
mxc_isi_vb2_buffer_init(struct vb2_buffer * vb2)896 static int mxc_isi_vb2_buffer_init(struct vb2_buffer *vb2)
897 {
898 struct mxc_isi_buffer *buf = to_isi_buffer(to_vb2_v4l2_buffer(vb2));
899 struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
900
901 mxc_isi_video_buffer_init(vb2, buf->dma_addrs, video->fmtinfo,
902 &video->pix);
903
904 return 0;
905 }
906
mxc_isi_vb2_buffer_prepare(struct vb2_buffer * vb2)907 static int mxc_isi_vb2_buffer_prepare(struct vb2_buffer *vb2)
908 {
909 struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
910
911 return mxc_isi_video_buffer_prepare(video->pipe->isi, vb2,
912 video->fmtinfo, &video->pix);
913 }
914
mxc_isi_vb2_buffer_queue(struct vb2_buffer * vb2)915 static void mxc_isi_vb2_buffer_queue(struct vb2_buffer *vb2)
916 {
917 struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2);
918 struct mxc_isi_buffer *buf = to_isi_buffer(v4l2_buf);
919 struct mxc_isi_video *video = vb2_get_drv_priv(vb2->vb2_queue);
920
921 spin_lock_irq(&video->buf_lock);
922 list_add_tail(&buf->list, &video->out_pending);
923 spin_unlock_irq(&video->buf_lock);
924 }
925
mxc_isi_video_init_channel(struct mxc_isi_video * video)926 static void mxc_isi_video_init_channel(struct mxc_isi_video *video)
927 {
928 struct mxc_isi_pipe *pipe = video->pipe;
929
930 mxc_isi_channel_get(pipe);
931
932 mutex_lock(video->ctrls.handler.lock);
933 mxc_isi_channel_set_alpha(pipe, video->ctrls.alpha);
934 mxc_isi_channel_set_flip(pipe, video->ctrls.hflip, video->ctrls.vflip);
935 mutex_unlock(video->ctrls.handler.lock);
936
937 mxc_isi_channel_set_output_format(pipe, video->fmtinfo, &video->pix);
938 }
939
mxc_isi_vb2_start_streaming(struct vb2_queue * q,unsigned int count)940 static int mxc_isi_vb2_start_streaming(struct vb2_queue *q, unsigned int count)
941 {
942 struct mxc_isi_video *video = vb2_get_drv_priv(q);
943 unsigned int i;
944 int ret;
945
946 /* Initialize the ISI channel. */
947 mxc_isi_video_init_channel(video);
948
949 spin_lock_irq(&video->buf_lock);
950
951 /* Add the discard buffers to the out_discard list. */
952 for (i = 0; i < ARRAY_SIZE(video->buf_discard); ++i) {
953 struct mxc_isi_buffer *buf = &video->buf_discard[i];
954
955 list_add_tail(&buf->list, &video->out_discard);
956 }
957
958 /* Queue the first buffers. */
959 mxc_isi_video_queue_first_buffers(video);
960
961 /* Clear frame count */
962 video->frame_count = 0;
963
964 spin_unlock_irq(&video->buf_lock);
965
966 ret = mxc_isi_pipe_enable(video->pipe);
967 if (ret)
968 goto error;
969
970 return 0;
971
972 error:
973 mxc_isi_channel_put(video->pipe);
974 mxc_isi_video_return_buffers(video, VB2_BUF_STATE_QUEUED);
975 return ret;
976 }
977
mxc_isi_vb2_stop_streaming(struct vb2_queue * q)978 static void mxc_isi_vb2_stop_streaming(struct vb2_queue *q)
979 {
980 struct mxc_isi_video *video = vb2_get_drv_priv(q);
981
982 mxc_isi_pipe_disable(video->pipe);
983 mxc_isi_channel_put(video->pipe);
984
985 mxc_isi_video_return_buffers(video, VB2_BUF_STATE_ERROR);
986 }
987
988 static const struct vb2_ops mxc_isi_vb2_qops = {
989 .queue_setup = mxc_isi_vb2_queue_setup,
990 .buf_init = mxc_isi_vb2_buffer_init,
991 .buf_prepare = mxc_isi_vb2_buffer_prepare,
992 .buf_queue = mxc_isi_vb2_buffer_queue,
993 .wait_prepare = vb2_ops_wait_prepare,
994 .wait_finish = vb2_ops_wait_finish,
995 .start_streaming = mxc_isi_vb2_start_streaming,
996 .stop_streaming = mxc_isi_vb2_stop_streaming,
997 };
998
999 /* -----------------------------------------------------------------------------
1000 * V4L2 controls
1001 */
1002
ctrl_to_isi_video(struct v4l2_ctrl * ctrl)1003 static inline struct mxc_isi_video *ctrl_to_isi_video(struct v4l2_ctrl *ctrl)
1004 {
1005 return container_of(ctrl->handler, struct mxc_isi_video, ctrls.handler);
1006 }
1007
mxc_isi_video_s_ctrl(struct v4l2_ctrl * ctrl)1008 static int mxc_isi_video_s_ctrl(struct v4l2_ctrl *ctrl)
1009 {
1010 struct mxc_isi_video *video = ctrl_to_isi_video(ctrl);
1011
1012 switch (ctrl->id) {
1013 case V4L2_CID_ALPHA_COMPONENT:
1014 video->ctrls.alpha = ctrl->val;
1015 break;
1016 case V4L2_CID_VFLIP:
1017 video->ctrls.vflip = ctrl->val;
1018 break;
1019 case V4L2_CID_HFLIP:
1020 video->ctrls.hflip = ctrl->val;
1021 break;
1022 }
1023
1024 return 0;
1025 }
1026
1027 static const struct v4l2_ctrl_ops mxc_isi_video_ctrl_ops = {
1028 .s_ctrl = mxc_isi_video_s_ctrl,
1029 };
1030
mxc_isi_video_ctrls_create(struct mxc_isi_video * video)1031 static int mxc_isi_video_ctrls_create(struct mxc_isi_video *video)
1032 {
1033 struct v4l2_ctrl_handler *handler = &video->ctrls.handler;
1034 int ret;
1035
1036 v4l2_ctrl_handler_init(handler, 3);
1037
1038 v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
1039 V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
1040
1041 v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
1042 V4L2_CID_VFLIP, 0, 1, 1, 0);
1043
1044 v4l2_ctrl_new_std(handler, &mxc_isi_video_ctrl_ops,
1045 V4L2_CID_HFLIP, 0, 1, 1, 0);
1046
1047 if (handler->error) {
1048 ret = handler->error;
1049 v4l2_ctrl_handler_free(handler);
1050 return ret;
1051 }
1052
1053 video->vdev.ctrl_handler = handler;
1054
1055 return 0;
1056 }
1057
mxc_isi_video_ctrls_delete(struct mxc_isi_video * video)1058 static void mxc_isi_video_ctrls_delete(struct mxc_isi_video *video)
1059 {
1060 v4l2_ctrl_handler_free(&video->ctrls.handler);
1061 }
1062
1063 /* -----------------------------------------------------------------------------
1064 * V4L2 ioctls
1065 */
1066
mxc_isi_video_querycap(struct file * file,void * priv,struct v4l2_capability * cap)1067 static int mxc_isi_video_querycap(struct file *file, void *priv,
1068 struct v4l2_capability *cap)
1069 {
1070 strscpy(cap->driver, MXC_ISI_DRIVER_NAME, sizeof(cap->driver));
1071 strscpy(cap->card, MXC_ISI_CAPTURE, sizeof(cap->card));
1072
1073 return 0;
1074 }
1075
mxc_isi_video_enum_fmt(struct file * file,void * priv,struct v4l2_fmtdesc * f)1076 static int mxc_isi_video_enum_fmt(struct file *file, void *priv,
1077 struct v4l2_fmtdesc *f)
1078 {
1079 const struct mxc_isi_format_info *fmt;
1080 unsigned int index = f->index;
1081 unsigned int i;
1082
1083 if (f->mbus_code) {
1084 /*
1085 * If a media bus code is specified, only enumerate formats
1086 * compatible with it.
1087 */
1088 for (i = 0; i < ARRAY_SIZE(mxc_isi_formats); i++) {
1089 fmt = &mxc_isi_formats[i];
1090 if (fmt->mbus_code != f->mbus_code)
1091 continue;
1092
1093 if (index == 0)
1094 break;
1095
1096 index--;
1097 }
1098
1099 if (i == ARRAY_SIZE(mxc_isi_formats))
1100 return -EINVAL;
1101 } else {
1102 /* Otherwise, enumerate all formatS. */
1103 if (f->index >= ARRAY_SIZE(mxc_isi_formats))
1104 return -EINVAL;
1105
1106 fmt = &mxc_isi_formats[f->index];
1107 }
1108
1109 f->pixelformat = fmt->fourcc;
1110 f->flags |= V4L2_FMT_FLAG_CSC_COLORSPACE | V4L2_FMT_FLAG_CSC_YCBCR_ENC
1111 | V4L2_FMT_FLAG_CSC_QUANTIZATION | V4L2_FMT_FLAG_CSC_XFER_FUNC;
1112
1113 return 0;
1114 }
1115
mxc_isi_video_g_fmt(struct file * file,void * fh,struct v4l2_format * f)1116 static int mxc_isi_video_g_fmt(struct file *file, void *fh,
1117 struct v4l2_format *f)
1118 {
1119 struct mxc_isi_video *video = video_drvdata(file);
1120
1121 f->fmt.pix_mp = video->pix;
1122
1123 return 0;
1124 }
1125
mxc_isi_video_try_fmt(struct file * file,void * fh,struct v4l2_format * f)1126 static int mxc_isi_video_try_fmt(struct file *file, void *fh,
1127 struct v4l2_format *f)
1128 {
1129 struct mxc_isi_video *video = video_drvdata(file);
1130
1131 mxc_isi_format_try(video->pipe, &f->fmt.pix_mp, MXC_ISI_VIDEO_CAP);
1132 return 0;
1133 }
1134
mxc_isi_video_s_fmt(struct file * file,void * priv,struct v4l2_format * f)1135 static int mxc_isi_video_s_fmt(struct file *file, void *priv,
1136 struct v4l2_format *f)
1137 {
1138 struct mxc_isi_video *video = video_drvdata(file);
1139 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
1140
1141 if (vb2_is_busy(&video->vb2_q))
1142 return -EBUSY;
1143
1144 video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP);
1145 video->pix = *pix;
1146
1147 return 0;
1148 }
1149
mxc_isi_video_streamon(struct file * file,void * priv,enum v4l2_buf_type type)1150 static int mxc_isi_video_streamon(struct file *file, void *priv,
1151 enum v4l2_buf_type type)
1152 {
1153 struct mxc_isi_video *video = video_drvdata(file);
1154 struct media_device *mdev = &video->pipe->isi->media_dev;
1155 struct media_pipeline *pipe;
1156 int ret;
1157
1158 if (vb2_queue_is_busy(&video->vb2_q, file))
1159 return -EBUSY;
1160
1161 /*
1162 * Get a pipeline for the video node and start it. This must be done
1163 * here and not in the queue .start_streaming() handler, so that
1164 * pipeline start errors can be reported from VIDIOC_STREAMON and not
1165 * delayed until subsequent VIDIOC_QBUF calls.
1166 */
1167 mutex_lock(&mdev->graph_mutex);
1168
1169 ret = mxc_isi_pipe_acquire(video->pipe, &mxc_isi_video_frame_write_done);
1170 if (ret) {
1171 mutex_unlock(&mdev->graph_mutex);
1172 return ret;
1173 }
1174
1175 pipe = media_entity_pipeline(&video->vdev.entity) ? : &video->pipe->pipe;
1176
1177 ret = __video_device_pipeline_start(&video->vdev, pipe);
1178 if (ret) {
1179 mutex_unlock(&mdev->graph_mutex);
1180 goto err_release;
1181 }
1182
1183 mutex_unlock(&mdev->graph_mutex);
1184
1185 /* Verify that the video format matches the output of the subdev. */
1186 ret = mxc_isi_video_validate_format(video);
1187 if (ret)
1188 goto err_stop;
1189
1190 /* Allocate buffers for discard operation. */
1191 ret = mxc_isi_video_alloc_discard_buffers(video);
1192 if (ret)
1193 goto err_stop;
1194
1195 ret = vb2_streamon(&video->vb2_q, type);
1196 if (ret)
1197 goto err_free;
1198
1199 video->is_streaming = true;
1200
1201 return 0;
1202
1203 err_free:
1204 mxc_isi_video_free_discard_buffers(video);
1205 err_stop:
1206 video_device_pipeline_stop(&video->vdev);
1207 err_release:
1208 mxc_isi_pipe_release(video->pipe);
1209 return ret;
1210 }
1211
mxc_isi_video_cleanup_streaming(struct mxc_isi_video * video)1212 static void mxc_isi_video_cleanup_streaming(struct mxc_isi_video *video)
1213 {
1214 lockdep_assert_held(&video->lock);
1215
1216 if (!video->is_streaming)
1217 return;
1218
1219 mxc_isi_video_free_discard_buffers(video);
1220 video_device_pipeline_stop(&video->vdev);
1221 mxc_isi_pipe_release(video->pipe);
1222
1223 video->is_streaming = false;
1224 }
1225
mxc_isi_video_streamoff(struct file * file,void * priv,enum v4l2_buf_type type)1226 static int mxc_isi_video_streamoff(struct file *file, void *priv,
1227 enum v4l2_buf_type type)
1228 {
1229 struct mxc_isi_video *video = video_drvdata(file);
1230 int ret;
1231
1232 ret = vb2_ioctl_streamoff(file, priv, type);
1233 if (ret)
1234 return ret;
1235
1236 mxc_isi_video_cleanup_streaming(video);
1237
1238 return 0;
1239 }
1240
mxc_isi_video_enum_framesizes(struct file * file,void * priv,struct v4l2_frmsizeenum * fsize)1241 static int mxc_isi_video_enum_framesizes(struct file *file, void *priv,
1242 struct v4l2_frmsizeenum *fsize)
1243 {
1244 struct mxc_isi_video *video = video_drvdata(file);
1245 const struct mxc_isi_format_info *info;
1246 unsigned int max_width;
1247 unsigned int h_align;
1248 unsigned int v_align;
1249
1250 if (fsize->index)
1251 return -EINVAL;
1252
1253 info = mxc_isi_format_by_fourcc(fsize->pixel_format, MXC_ISI_VIDEO_CAP);
1254 if (!info)
1255 return -EINVAL;
1256
1257 h_align = max_t(unsigned int, info->hsub, 1);
1258 v_align = max_t(unsigned int, info->vsub, 1);
1259
1260 max_width = video->pipe->id == video->pipe->isi->pdata->num_channels - 1
1261 ? MXC_ISI_MAX_WIDTH_UNCHAINED
1262 : MXC_ISI_MAX_WIDTH_CHAINED;
1263
1264 fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
1265 fsize->stepwise.min_width = ALIGN(MXC_ISI_MIN_WIDTH, h_align);
1266 fsize->stepwise.min_height = ALIGN(MXC_ISI_MIN_HEIGHT, v_align);
1267 fsize->stepwise.max_width = ALIGN_DOWN(max_width, h_align);
1268 fsize->stepwise.max_height = ALIGN_DOWN(MXC_ISI_MAX_HEIGHT, v_align);
1269 fsize->stepwise.step_width = h_align;
1270 fsize->stepwise.step_height = v_align;
1271
1272 /*
1273 * The width can be further restricted due to line buffer sharing
1274 * between pipelines when scaling, but we have no way to know here if
1275 * the scaler will be used.
1276 */
1277
1278 return 0;
1279 }
1280
1281 static const struct v4l2_ioctl_ops mxc_isi_video_ioctl_ops = {
1282 .vidioc_querycap = mxc_isi_video_querycap,
1283
1284 .vidioc_enum_fmt_vid_cap = mxc_isi_video_enum_fmt,
1285 .vidioc_try_fmt_vid_cap_mplane = mxc_isi_video_try_fmt,
1286 .vidioc_s_fmt_vid_cap_mplane = mxc_isi_video_s_fmt,
1287 .vidioc_g_fmt_vid_cap_mplane = mxc_isi_video_g_fmt,
1288
1289 .vidioc_reqbufs = vb2_ioctl_reqbufs,
1290 .vidioc_querybuf = vb2_ioctl_querybuf,
1291 .vidioc_qbuf = vb2_ioctl_qbuf,
1292 .vidioc_dqbuf = vb2_ioctl_dqbuf,
1293 .vidioc_expbuf = vb2_ioctl_expbuf,
1294 .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
1295 .vidioc_create_bufs = vb2_ioctl_create_bufs,
1296
1297 .vidioc_streamon = mxc_isi_video_streamon,
1298 .vidioc_streamoff = mxc_isi_video_streamoff,
1299
1300 .vidioc_enum_framesizes = mxc_isi_video_enum_framesizes,
1301
1302 .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
1303 .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
1304 };
1305
1306 /* -----------------------------------------------------------------------------
1307 * Video device file operations
1308 */
1309
mxc_isi_video_open(struct file * file)1310 static int mxc_isi_video_open(struct file *file)
1311 {
1312 struct mxc_isi_video *video = video_drvdata(file);
1313 int ret;
1314
1315 ret = v4l2_fh_open(file);
1316 if (ret)
1317 return ret;
1318
1319 ret = pm_runtime_resume_and_get(video->pipe->isi->dev);
1320 if (ret) {
1321 v4l2_fh_release(file);
1322 return ret;
1323 }
1324
1325 return 0;
1326 }
1327
mxc_isi_video_release(struct file * file)1328 static int mxc_isi_video_release(struct file *file)
1329 {
1330 struct mxc_isi_video *video = video_drvdata(file);
1331 int ret;
1332
1333 ret = vb2_fop_release(file);
1334 if (ret)
1335 dev_err(video->pipe->isi->dev, "%s fail\n", __func__);
1336
1337 mutex_lock(&video->lock);
1338 mxc_isi_video_cleanup_streaming(video);
1339 mutex_unlock(&video->lock);
1340
1341 pm_runtime_put(video->pipe->isi->dev);
1342 return ret;
1343 }
1344
1345 static const struct v4l2_file_operations mxc_isi_video_fops = {
1346 .owner = THIS_MODULE,
1347 .open = mxc_isi_video_open,
1348 .release = mxc_isi_video_release,
1349 .poll = vb2_fop_poll,
1350 .unlocked_ioctl = video_ioctl2,
1351 .mmap = vb2_fop_mmap,
1352 };
1353
1354 /* -----------------------------------------------------------------------------
1355 * Suspend & resume
1356 */
1357
mxc_isi_video_suspend(struct mxc_isi_pipe * pipe)1358 void mxc_isi_video_suspend(struct mxc_isi_pipe *pipe)
1359 {
1360 struct mxc_isi_video *video = &pipe->video;
1361
1362 if (!video->is_streaming)
1363 return;
1364
1365 mxc_isi_pipe_disable(pipe);
1366 mxc_isi_channel_put(pipe);
1367
1368 spin_lock_irq(&video->buf_lock);
1369
1370 /*
1371 * Move the active buffers back to the pending or discard list. We must
1372 * iterate the active list backward and move the buffers to the head of
1373 * the pending list to preserve the buffer queueing order.
1374 */
1375 while (!list_empty(&video->out_active)) {
1376 struct mxc_isi_buffer *buf =
1377 list_last_entry(&video->out_active,
1378 struct mxc_isi_buffer, list);
1379
1380 if (buf->discard)
1381 list_move(&buf->list, &video->out_discard);
1382 else
1383 list_move(&buf->list, &video->out_pending);
1384 }
1385
1386 spin_unlock_irq(&video->buf_lock);
1387 }
1388
mxc_isi_video_resume(struct mxc_isi_pipe * pipe)1389 int mxc_isi_video_resume(struct mxc_isi_pipe *pipe)
1390 {
1391 struct mxc_isi_video *video = &pipe->video;
1392
1393 if (!video->is_streaming)
1394 return 0;
1395
1396 mxc_isi_video_init_channel(video);
1397
1398 spin_lock_irq(&video->buf_lock);
1399 mxc_isi_video_queue_first_buffers(video);
1400 spin_unlock_irq(&video->buf_lock);
1401
1402 return mxc_isi_pipe_enable(pipe);
1403 }
1404
1405 /* -----------------------------------------------------------------------------
1406 * Registration
1407 */
1408
mxc_isi_video_register(struct mxc_isi_pipe * pipe,struct v4l2_device * v4l2_dev)1409 int mxc_isi_video_register(struct mxc_isi_pipe *pipe,
1410 struct v4l2_device *v4l2_dev)
1411 {
1412 struct mxc_isi_video *video = &pipe->video;
1413 struct v4l2_pix_format_mplane *pix = &video->pix;
1414 struct video_device *vdev = &video->vdev;
1415 struct vb2_queue *q = &video->vb2_q;
1416 int ret = -ENOMEM;
1417
1418 video->pipe = pipe;
1419
1420 mutex_init(&video->lock);
1421 spin_lock_init(&video->buf_lock);
1422
1423 pix->width = MXC_ISI_DEF_WIDTH;
1424 pix->height = MXC_ISI_DEF_HEIGHT;
1425 pix->pixelformat = MXC_ISI_DEF_PIXEL_FORMAT;
1426 pix->colorspace = MXC_ISI_DEF_COLOR_SPACE;
1427 pix->ycbcr_enc = MXC_ISI_DEF_YCBCR_ENC;
1428 pix->quantization = MXC_ISI_DEF_QUANTIZATION;
1429 pix->xfer_func = MXC_ISI_DEF_XFER_FUNC;
1430 video->fmtinfo = mxc_isi_format_try(video->pipe, pix, MXC_ISI_VIDEO_CAP);
1431
1432 memset(vdev, 0, sizeof(*vdev));
1433 snprintf(vdev->name, sizeof(vdev->name), "mxc_isi.%d.capture", pipe->id);
1434
1435 vdev->fops = &mxc_isi_video_fops;
1436 vdev->ioctl_ops = &mxc_isi_video_ioctl_ops;
1437 vdev->v4l2_dev = v4l2_dev;
1438 vdev->minor = -1;
1439 vdev->release = video_device_release_empty;
1440 vdev->queue = q;
1441 vdev->lock = &video->lock;
1442
1443 vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE_MPLANE
1444 | V4L2_CAP_IO_MC;
1445 video_set_drvdata(vdev, video);
1446
1447 INIT_LIST_HEAD(&video->out_pending);
1448 INIT_LIST_HEAD(&video->out_active);
1449 INIT_LIST_HEAD(&video->out_discard);
1450
1451 memset(q, 0, sizeof(*q));
1452 q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
1453 q->io_modes = VB2_MMAP | VB2_DMABUF;
1454 q->drv_priv = video;
1455 q->ops = &mxc_isi_vb2_qops;
1456 q->mem_ops = &vb2_dma_contig_memops;
1457 q->buf_struct_size = sizeof(struct mxc_isi_buffer);
1458 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1459 q->min_buffers_needed = 2;
1460 q->lock = &video->lock;
1461 q->dev = pipe->isi->dev;
1462
1463 ret = vb2_queue_init(q);
1464 if (ret)
1465 goto err_free_ctx;
1466
1467 video->pad.flags = MEDIA_PAD_FL_SINK;
1468 vdev->entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
1469 ret = media_entity_pads_init(&vdev->entity, 1, &video->pad);
1470 if (ret)
1471 goto err_free_ctx;
1472
1473 ret = mxc_isi_video_ctrls_create(video);
1474 if (ret)
1475 goto err_me_cleanup;
1476
1477 ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
1478 if (ret)
1479 goto err_ctrl_free;
1480
1481 ret = media_create_pad_link(&pipe->sd.entity,
1482 MXC_ISI_PIPE_PAD_SOURCE,
1483 &vdev->entity, 0,
1484 MEDIA_LNK_FL_IMMUTABLE |
1485 MEDIA_LNK_FL_ENABLED);
1486 if (ret)
1487 goto err_video_unreg;
1488
1489 return 0;
1490
1491 err_video_unreg:
1492 video_unregister_device(vdev);
1493 err_ctrl_free:
1494 mxc_isi_video_ctrls_delete(video);
1495 err_me_cleanup:
1496 media_entity_cleanup(&vdev->entity);
1497 err_free_ctx:
1498 return ret;
1499 }
1500
mxc_isi_video_unregister(struct mxc_isi_pipe * pipe)1501 void mxc_isi_video_unregister(struct mxc_isi_pipe *pipe)
1502 {
1503 struct mxc_isi_video *video = &pipe->video;
1504 struct video_device *vdev = &video->vdev;
1505
1506 mutex_lock(&video->lock);
1507
1508 if (video_is_registered(vdev)) {
1509 video_unregister_device(vdev);
1510 mxc_isi_video_ctrls_delete(video);
1511 media_entity_cleanup(&vdev->entity);
1512 }
1513
1514 mutex_unlock(&video->lock);
1515 }
1516