xref: /linux/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c (revision 79d2e1919a2728ef49d938eb20ebd5903c14dfb0)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing)
4  * Author: Yong Deng <yong.deng@magewell.com>
5  * Copyright 2021-2022 Bootlin
6  * Author: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
7  */
8 
9 #include <linux/of.h>
10 #include <linux/regmap.h>
11 #include <media/v4l2-device.h>
12 #include <media/v4l2-event.h>
13 #include <media/v4l2-ioctl.h>
14 #include <media/v4l2-mc.h>
15 #include <media/videobuf2-dma-contig.h>
16 #include <media/videobuf2-v4l2.h>
17 
18 #include "sun6i_csi.h"
19 #include "sun6i_csi_bridge.h"
20 #include "sun6i_csi_capture.h"
21 #include "sun6i_csi_reg.h"
22 
23 /* Helpers */
24 
25 void sun6i_csi_capture_dimensions(struct sun6i_csi_device *csi_dev,
26 				  unsigned int *width, unsigned int *height)
27 {
28 	if (width)
29 		*width = csi_dev->capture.format.fmt.pix.width;
30 	if (height)
31 		*height = csi_dev->capture.format.fmt.pix.height;
32 }
33 
34 void sun6i_csi_capture_format(struct sun6i_csi_device *csi_dev,
35 			      u32 *pixelformat, u32 *field)
36 {
37 	if (pixelformat)
38 		*pixelformat = csi_dev->capture.format.fmt.pix.pixelformat;
39 
40 	if (field)
41 		*field = csi_dev->capture.format.fmt.pix.field;
42 }
43 
44 /* Format */
45 
46 static const struct sun6i_csi_capture_format sun6i_csi_capture_formats[] = {
47 	/* Bayer */
48 	{
49 		.pixelformat		= V4L2_PIX_FMT_SBGGR8,
50 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8,
51 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8,
52 	},
53 	{
54 		.pixelformat		= V4L2_PIX_FMT_SGBRG8,
55 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8,
56 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8,
57 	},
58 	{
59 		.pixelformat		= V4L2_PIX_FMT_SGRBG8,
60 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8,
61 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8,
62 	},
63 	{
64 		.pixelformat		= V4L2_PIX_FMT_SRGGB8,
65 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8,
66 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8,
67 	},
68 	{
69 		.pixelformat		= V4L2_PIX_FMT_SBGGR10,
70 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_10,
71 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_10,
72 	},
73 	{
74 		.pixelformat		= V4L2_PIX_FMT_SGBRG10,
75 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_10,
76 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_10,
77 	},
78 	{
79 		.pixelformat		= V4L2_PIX_FMT_SGRBG10,
80 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_10,
81 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_10,
82 	},
83 	{
84 		.pixelformat		= V4L2_PIX_FMT_SRGGB10,
85 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_10,
86 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_10,
87 	},
88 	{
89 		.pixelformat		= V4L2_PIX_FMT_SBGGR12,
90 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_12,
91 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_12,
92 	},
93 	{
94 		.pixelformat		= V4L2_PIX_FMT_SGBRG12,
95 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_12,
96 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_12,
97 	},
98 	{
99 		.pixelformat		= V4L2_PIX_FMT_SGRBG12,
100 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_12,
101 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_12,
102 	},
103 	{
104 		.pixelformat		= V4L2_PIX_FMT_SRGGB12,
105 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_12,
106 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_12,
107 	},
108 	/* RGB */
109 	{
110 		.pixelformat		= V4L2_PIX_FMT_RGB565,
111 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RGB565,
112 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RGB565,
113 	},
114 	{
115 		.pixelformat		= V4L2_PIX_FMT_RGB565X,
116 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RGB565,
117 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RGB565,
118 	},
119 	/* YUV422 */
120 	{
121 		.pixelformat		= V4L2_PIX_FMT_YUYV,
122 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8,
123 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8,
124 		.input_format_raw	= true,
125 		.hsize_len_factor	= 2,
126 	},
127 	{
128 		.pixelformat		= V4L2_PIX_FMT_YVYU,
129 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8,
130 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8,
131 		.input_format_raw	= true,
132 		.hsize_len_factor	= 2,
133 	},
134 	{
135 		.pixelformat		= V4L2_PIX_FMT_UYVY,
136 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8,
137 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8,
138 		.input_format_raw	= true,
139 		.hsize_len_factor	= 2,
140 	},
141 	{
142 		.pixelformat		= V4L2_PIX_FMT_VYUY,
143 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8,
144 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8,
145 		.input_format_raw	= true,
146 		.hsize_len_factor	= 2,
147 	},
148 	{
149 		.pixelformat		= V4L2_PIX_FMT_NV16,
150 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_YUV422SP,
151 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_YUV422SP,
152 	},
153 	{
154 		.pixelformat		= V4L2_PIX_FMT_NV61,
155 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_YUV422SP,
156 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_YUV422SP,
157 		.input_yuv_seq_invert	= true,
158 	},
159 	{
160 		.pixelformat		= V4L2_PIX_FMT_YUV422P,
161 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_YUV422P,
162 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_YUV422P,
163 	},
164 	/* YUV420 */
165 	{
166 		.pixelformat		= V4L2_PIX_FMT_NV12_16L16,
167 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420MB,
168 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420MB,
169 	},
170 	{
171 		.pixelformat		= V4L2_PIX_FMT_NV12,
172 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420SP,
173 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420SP,
174 	},
175 	{
176 		.pixelformat		= V4L2_PIX_FMT_NV21,
177 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420SP,
178 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420SP,
179 		.input_yuv_seq_invert	= true,
180 	},
181 
182 	{
183 		.pixelformat		= V4L2_PIX_FMT_YUV420,
184 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420P,
185 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420P,
186 	},
187 	{
188 		.pixelformat		= V4L2_PIX_FMT_YVU420,
189 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_YUV420P,
190 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_YUV420P,
191 		.input_yuv_seq_invert	= true,
192 	},
193 	/* Compressed */
194 	{
195 		.pixelformat		= V4L2_PIX_FMT_JPEG,
196 		.output_format_frame	= SUN6I_CSI_OUTPUT_FMT_FRAME_RAW_8,
197 		.output_format_field	= SUN6I_CSI_OUTPUT_FMT_FIELD_RAW_8,
198 	},
199 };
200 
201 const
202 struct sun6i_csi_capture_format *sun6i_csi_capture_format_find(u32 pixelformat)
203 {
204 	unsigned int i;
205 
206 	for (i = 0; i < ARRAY_SIZE(sun6i_csi_capture_formats); i++)
207 		if (sun6i_csi_capture_formats[i].pixelformat == pixelformat)
208 			return &sun6i_csi_capture_formats[i];
209 
210 	return NULL;
211 }
212 
213 /* RAW formats need an exact match between pixel and mbus formats. */
214 static const
215 struct sun6i_csi_capture_format_match sun6i_csi_capture_format_matches[] = {
216 	/* YUV420 */
217 	{
218 		.pixelformat	= V4L2_PIX_FMT_YUYV,
219 		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
220 	},
221 	{
222 		.pixelformat	= V4L2_PIX_FMT_YUYV,
223 		.mbus_code	= MEDIA_BUS_FMT_YUYV8_1X16,
224 	},
225 	{
226 		.pixelformat	= V4L2_PIX_FMT_YVYU,
227 		.mbus_code	= MEDIA_BUS_FMT_YVYU8_2X8,
228 	},
229 	{
230 		.pixelformat	= V4L2_PIX_FMT_YVYU,
231 		.mbus_code	= MEDIA_BUS_FMT_YVYU8_1X16,
232 	},
233 	{
234 		.pixelformat	= V4L2_PIX_FMT_UYVY,
235 		.mbus_code	= MEDIA_BUS_FMT_UYVY8_2X8,
236 	},
237 	{
238 		.pixelformat	= V4L2_PIX_FMT_UYVY,
239 		.mbus_code	= MEDIA_BUS_FMT_UYVY8_1X16,
240 	},
241 	{
242 		.pixelformat	= V4L2_PIX_FMT_VYUY,
243 		.mbus_code	= MEDIA_BUS_FMT_VYUY8_2X8,
244 	},
245 	{
246 		.pixelformat	= V4L2_PIX_FMT_VYUY,
247 		.mbus_code	= MEDIA_BUS_FMT_VYUY8_1X16,
248 	},
249 	/* RGB */
250 	{
251 		.pixelformat	= V4L2_PIX_FMT_RGB565,
252 		.mbus_code	= MEDIA_BUS_FMT_RGB565_2X8_LE,
253 	},
254 	{
255 		.pixelformat	= V4L2_PIX_FMT_RGB565X,
256 		.mbus_code	= MEDIA_BUS_FMT_RGB565_2X8_BE,
257 	},
258 	/* Bayer */
259 	{
260 		.pixelformat	= V4L2_PIX_FMT_SBGGR8,
261 		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
262 	},
263 	{
264 		.pixelformat	= V4L2_PIX_FMT_SGBRG8,
265 		.mbus_code	= MEDIA_BUS_FMT_SGBRG8_1X8,
266 	},
267 	{
268 		.pixelformat	= V4L2_PIX_FMT_SGRBG8,
269 		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
270 	},
271 	{
272 		.pixelformat	= V4L2_PIX_FMT_SRGGB8,
273 		.mbus_code	= MEDIA_BUS_FMT_SRGGB8_1X8,
274 	},
275 	{
276 		.pixelformat	= V4L2_PIX_FMT_SBGGR10,
277 		.mbus_code	= MEDIA_BUS_FMT_SBGGR10_1X10,
278 	},
279 	{
280 		.pixelformat	= V4L2_PIX_FMT_SGBRG10,
281 		.mbus_code	= MEDIA_BUS_FMT_SGBRG10_1X10,
282 	},
283 	{
284 		.pixelformat	= V4L2_PIX_FMT_SGRBG10,
285 		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
286 	},
287 	{
288 		.pixelformat	= V4L2_PIX_FMT_SRGGB10,
289 		.mbus_code	= MEDIA_BUS_FMT_SRGGB10_1X10,
290 	},
291 	{
292 		.pixelformat	= V4L2_PIX_FMT_SBGGR12,
293 		.mbus_code	= MEDIA_BUS_FMT_SBGGR12_1X12,
294 	},
295 	{
296 		.pixelformat	= V4L2_PIX_FMT_SGBRG12,
297 		.mbus_code	= MEDIA_BUS_FMT_SGBRG12_1X12,
298 	},
299 	{
300 		.pixelformat	= V4L2_PIX_FMT_SGRBG12,
301 		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
302 	},
303 	{
304 		.pixelformat	= V4L2_PIX_FMT_SRGGB12,
305 		.mbus_code	= MEDIA_BUS_FMT_SRGGB12_1X12,
306 	},
307 	/* Compressed */
308 	{
309 		.pixelformat	= V4L2_PIX_FMT_JPEG,
310 		.mbus_code	= MEDIA_BUS_FMT_JPEG_1X8,
311 	},
312 };
313 
314 static bool sun6i_csi_capture_format_match(u32 pixelformat, u32 mbus_code)
315 {
316 	unsigned int i;
317 
318 	for (i = 0; i < ARRAY_SIZE(sun6i_csi_capture_format_matches); i++) {
319 		const struct sun6i_csi_capture_format_match *match =
320 			&sun6i_csi_capture_format_matches[i];
321 
322 		if (match->pixelformat == pixelformat &&
323 		    match->mbus_code == mbus_code)
324 			return true;
325 	}
326 
327 	return false;
328 }
329 
330 /* Capture */
331 
332 static void
333 sun6i_csi_capture_buffer_configure(struct sun6i_csi_device *csi_dev,
334 				   struct sun6i_csi_buffer *csi_buffer)
335 {
336 	struct regmap *regmap = csi_dev->regmap;
337 	const struct v4l2_format_info *info;
338 	struct vb2_buffer *vb2_buffer;
339 	unsigned int width, height;
340 	dma_addr_t address;
341 	u32 pixelformat;
342 
343 	vb2_buffer = &csi_buffer->v4l2_buffer.vb2_buf;
344 	address = vb2_dma_contig_plane_dma_addr(vb2_buffer, 0);
345 
346 	regmap_write(regmap, SUN6I_CSI_CH_FIFO0_ADDR_REG,
347 		     SUN6I_CSI_ADDR_VALUE(address));
348 
349 	sun6i_csi_capture_dimensions(csi_dev, &width, &height);
350 	sun6i_csi_capture_format(csi_dev, &pixelformat, NULL);
351 
352 	info = v4l2_format_info(pixelformat);
353 	/* Unsupported formats are single-plane, so we can stop here. */
354 	if (!info)
355 		return;
356 
357 	if (info->comp_planes > 1) {
358 		address += info->bpp[0] * width * height;
359 
360 		regmap_write(regmap, SUN6I_CSI_CH_FIFO1_ADDR_REG,
361 			     SUN6I_CSI_ADDR_VALUE(address));
362 	}
363 
364 	if (info->comp_planes > 2) {
365 		address += info->bpp[1] * DIV_ROUND_UP(width, info->hdiv) *
366 			   DIV_ROUND_UP(height, info->vdiv);
367 
368 		regmap_write(regmap, SUN6I_CSI_CH_FIFO2_ADDR_REG,
369 			     SUN6I_CSI_ADDR_VALUE(address));
370 	}
371 }
372 
373 void sun6i_csi_capture_configure(struct sun6i_csi_device *csi_dev)
374 {
375 	struct regmap *regmap = csi_dev->regmap;
376 	const struct sun6i_csi_capture_format *format;
377 	const struct v4l2_format_info *info;
378 	u32 hsize_len, vsize_len;
379 	u32 luma_line, chroma_line = 0;
380 	u32 pixelformat, field;
381 	u32 width, height;
382 
383 	sun6i_csi_capture_dimensions(csi_dev, &width, &height);
384 	sun6i_csi_capture_format(csi_dev, &pixelformat, &field);
385 
386 	format = sun6i_csi_capture_format_find(pixelformat);
387 	if (WARN_ON(!format))
388 		return;
389 
390 	hsize_len = width;
391 	vsize_len = height;
392 
393 	/*
394 	 * When using 8-bit raw input/output (for packed YUV), we need to adapt
395 	 * the width to account for the difference in bpp when it's not 8-bit.
396 	 */
397 	if (format->hsize_len_factor)
398 		hsize_len *= format->hsize_len_factor;
399 
400 	regmap_write(regmap, SUN6I_CSI_CH_HSIZE_REG,
401 		     SUN6I_CSI_CH_HSIZE_LEN(hsize_len) |
402 		     SUN6I_CSI_CH_HSIZE_START(0));
403 
404 	regmap_write(regmap, SUN6I_CSI_CH_VSIZE_REG,
405 		     SUN6I_CSI_CH_VSIZE_LEN(vsize_len) |
406 		     SUN6I_CSI_CH_VSIZE_START(0));
407 
408 	switch (pixelformat) {
409 	case V4L2_PIX_FMT_RGB565X:
410 		luma_line = width * 2;
411 		break;
412 	case V4L2_PIX_FMT_NV12_16L16:
413 		luma_line = width;
414 		chroma_line = width;
415 		break;
416 	case V4L2_PIX_FMT_JPEG:
417 		luma_line = width;
418 		break;
419 	default:
420 		info = v4l2_format_info(pixelformat);
421 		if (WARN_ON(!info))
422 			return;
423 
424 		luma_line = width * info->bpp[0];
425 
426 		if (info->comp_planes > 1)
427 			chroma_line = width * info->bpp[1] / info->hdiv;
428 		break;
429 	}
430 
431 	regmap_write(regmap, SUN6I_CSI_CH_BUF_LEN_REG,
432 		     SUN6I_CSI_CH_BUF_LEN_CHROMA_LINE(chroma_line) |
433 		     SUN6I_CSI_CH_BUF_LEN_LUMA_LINE(luma_line));
434 }
435 
436 /* State */
437 
438 static void sun6i_csi_capture_state_cleanup(struct sun6i_csi_device *csi_dev,
439 					    bool error)
440 {
441 	struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
442 	struct sun6i_csi_buffer **csi_buffer_states[] = {
443 		&state->pending, &state->current, &state->complete,
444 	};
445 	struct sun6i_csi_buffer *csi_buffer;
446 	struct vb2_buffer *vb2_buffer;
447 	unsigned long flags;
448 	unsigned int i;
449 
450 	spin_lock_irqsave(&state->lock, flags);
451 
452 	for (i = 0; i < ARRAY_SIZE(csi_buffer_states); i++) {
453 		csi_buffer = *csi_buffer_states[i];
454 		if (!csi_buffer)
455 			continue;
456 
457 		vb2_buffer = &csi_buffer->v4l2_buffer.vb2_buf;
458 		vb2_buffer_done(vb2_buffer, error ? VB2_BUF_STATE_ERROR :
459 				VB2_BUF_STATE_QUEUED);
460 
461 		*csi_buffer_states[i] = NULL;
462 	}
463 
464 	list_for_each_entry(csi_buffer, &state->queue, list) {
465 		vb2_buffer = &csi_buffer->v4l2_buffer.vb2_buf;
466 		vb2_buffer_done(vb2_buffer, error ? VB2_BUF_STATE_ERROR :
467 				VB2_BUF_STATE_QUEUED);
468 	}
469 
470 	INIT_LIST_HEAD(&state->queue);
471 
472 	spin_unlock_irqrestore(&state->lock, flags);
473 }
474 
475 void sun6i_csi_capture_state_update(struct sun6i_csi_device *csi_dev)
476 {
477 	struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
478 	struct sun6i_csi_buffer *csi_buffer;
479 	unsigned long flags;
480 
481 	spin_lock_irqsave(&state->lock, flags);
482 
483 	if (list_empty(&state->queue))
484 		goto complete;
485 
486 	if (state->pending)
487 		goto complete;
488 
489 	csi_buffer = list_first_entry(&state->queue, struct sun6i_csi_buffer,
490 				      list);
491 
492 	sun6i_csi_capture_buffer_configure(csi_dev, csi_buffer);
493 
494 	list_del(&csi_buffer->list);
495 
496 	state->pending = csi_buffer;
497 
498 complete:
499 	spin_unlock_irqrestore(&state->lock, flags);
500 }
501 
502 static void sun6i_csi_capture_state_complete(struct sun6i_csi_device *csi_dev)
503 {
504 	struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
505 	unsigned long flags;
506 
507 	spin_lock_irqsave(&state->lock, flags);
508 
509 	if (!state->pending)
510 		goto complete;
511 
512 	state->complete = state->current;
513 	state->current = state->pending;
514 	state->pending = NULL;
515 
516 	if (state->complete) {
517 		struct sun6i_csi_buffer *csi_buffer = state->complete;
518 		struct vb2_buffer *vb2_buffer =
519 			&csi_buffer->v4l2_buffer.vb2_buf;
520 
521 		vb2_buffer->timestamp = ktime_get_ns();
522 		csi_buffer->v4l2_buffer.sequence = state->sequence;
523 
524 		vb2_buffer_done(vb2_buffer, VB2_BUF_STATE_DONE);
525 
526 		state->complete = NULL;
527 	}
528 
529 complete:
530 	spin_unlock_irqrestore(&state->lock, flags);
531 }
532 
533 void sun6i_csi_capture_frame_done(struct sun6i_csi_device *csi_dev)
534 {
535 	struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
536 	unsigned long flags;
537 
538 	spin_lock_irqsave(&state->lock, flags);
539 	state->sequence++;
540 	spin_unlock_irqrestore(&state->lock, flags);
541 }
542 
543 void sun6i_csi_capture_sync(struct sun6i_csi_device *csi_dev)
544 {
545 	sun6i_csi_capture_state_complete(csi_dev);
546 	sun6i_csi_capture_state_update(csi_dev);
547 }
548 
549 /* Queue */
550 
551 static int sun6i_csi_capture_queue_setup(struct vb2_queue *queue,
552 					 unsigned int *buffers_count,
553 					 unsigned int *planes_count,
554 					 unsigned int sizes[],
555 					 struct device *alloc_devs[])
556 {
557 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
558 	unsigned int size = csi_dev->capture.format.fmt.pix.sizeimage;
559 
560 	if (*planes_count)
561 		return sizes[0] < size ? -EINVAL : 0;
562 
563 	*planes_count = 1;
564 	sizes[0] = size;
565 
566 	return 0;
567 }
568 
569 static int sun6i_csi_capture_buffer_prepare(struct vb2_buffer *buffer)
570 {
571 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(buffer->vb2_queue);
572 	struct sun6i_csi_capture *capture = &csi_dev->capture;
573 	struct v4l2_device *v4l2_dev = csi_dev->v4l2_dev;
574 	struct vb2_v4l2_buffer *v4l2_buffer = to_vb2_v4l2_buffer(buffer);
575 	unsigned long size = capture->format.fmt.pix.sizeimage;
576 
577 	if (vb2_plane_size(buffer, 0) < size) {
578 		v4l2_err(v4l2_dev, "buffer too small (%lu < %lu)\n",
579 			 vb2_plane_size(buffer, 0), size);
580 		return -EINVAL;
581 	}
582 
583 	vb2_set_plane_payload(buffer, 0, size);
584 
585 	v4l2_buffer->field = capture->format.fmt.pix.field;
586 
587 	return 0;
588 }
589 
590 static void sun6i_csi_capture_buffer_queue(struct vb2_buffer *buffer)
591 {
592 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(buffer->vb2_queue);
593 	struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
594 	struct vb2_v4l2_buffer *v4l2_buffer = to_vb2_v4l2_buffer(buffer);
595 	struct sun6i_csi_buffer *csi_buffer =
596 		container_of(v4l2_buffer, struct sun6i_csi_buffer, v4l2_buffer);
597 	unsigned long flags;
598 
599 	spin_lock_irqsave(&state->lock, flags);
600 	list_add_tail(&csi_buffer->list, &state->queue);
601 	spin_unlock_irqrestore(&state->lock, flags);
602 }
603 
604 static int sun6i_csi_capture_start_streaming(struct vb2_queue *queue,
605 					     unsigned int count)
606 {
607 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
608 	struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
609 	struct video_device *video_dev = &csi_dev->capture.video_dev;
610 	struct v4l2_subdev *subdev = &csi_dev->bridge.subdev;
611 	int ret;
612 
613 	state->sequence = 0;
614 
615 	ret = video_device_pipeline_alloc_start(video_dev);
616 	if (ret < 0)
617 		goto error_state;
618 
619 	state->streaming = true;
620 
621 	ret = v4l2_subdev_call(subdev, video, s_stream, 1);
622 	if (ret && ret != -ENOIOCTLCMD)
623 		goto error_streaming;
624 
625 	return 0;
626 
627 error_streaming:
628 	state->streaming = false;
629 
630 	video_device_pipeline_stop(video_dev);
631 
632 error_state:
633 	sun6i_csi_capture_state_cleanup(csi_dev, false);
634 
635 	return ret;
636 }
637 
638 static void sun6i_csi_capture_stop_streaming(struct vb2_queue *queue)
639 {
640 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
641 	struct sun6i_csi_capture_state *state = &csi_dev->capture.state;
642 	struct video_device *video_dev = &csi_dev->capture.video_dev;
643 	struct v4l2_subdev *subdev = &csi_dev->bridge.subdev;
644 
645 	v4l2_subdev_call(subdev, video, s_stream, 0);
646 
647 	state->streaming = false;
648 
649 	video_device_pipeline_stop(video_dev);
650 
651 	sun6i_csi_capture_state_cleanup(csi_dev, true);
652 }
653 
654 static const struct vb2_ops sun6i_csi_capture_queue_ops = {
655 	.queue_setup		= sun6i_csi_capture_queue_setup,
656 	.buf_prepare		= sun6i_csi_capture_buffer_prepare,
657 	.buf_queue		= sun6i_csi_capture_buffer_queue,
658 	.start_streaming	= sun6i_csi_capture_start_streaming,
659 	.stop_streaming		= sun6i_csi_capture_stop_streaming,
660 };
661 
662 /* V4L2 Device */
663 
664 static void sun6i_csi_capture_format_prepare(struct v4l2_format *format)
665 {
666 	struct v4l2_pix_format *pix_format = &format->fmt.pix;
667 	const struct v4l2_format_info *info;
668 	unsigned int width, height;
669 
670 	v4l_bound_align_image(&pix_format->width, SUN6I_CSI_CAPTURE_WIDTH_MIN,
671 			      SUN6I_CSI_CAPTURE_WIDTH_MAX, 1,
672 			      &pix_format->height, SUN6I_CSI_CAPTURE_HEIGHT_MIN,
673 			      SUN6I_CSI_CAPTURE_HEIGHT_MAX, 1, 0);
674 
675 	if (!sun6i_csi_capture_format_find(pix_format->pixelformat))
676 		pix_format->pixelformat =
677 			sun6i_csi_capture_formats[0].pixelformat;
678 
679 	width = pix_format->width;
680 	height = pix_format->height;
681 
682 	info = v4l2_format_info(pix_format->pixelformat);
683 
684 	switch (pix_format->pixelformat) {
685 	case V4L2_PIX_FMT_NV12_16L16:
686 		pix_format->bytesperline = width * 12 / 8;
687 		pix_format->sizeimage = pix_format->bytesperline * height;
688 		break;
689 	case V4L2_PIX_FMT_JPEG:
690 		pix_format->bytesperline = width;
691 		pix_format->sizeimage = pix_format->bytesperline * height;
692 		break;
693 	default:
694 		v4l2_fill_pixfmt(pix_format, pix_format->pixelformat,
695 				 width, height);
696 		break;
697 	}
698 
699 	if (pix_format->field == V4L2_FIELD_ANY)
700 		pix_format->field = V4L2_FIELD_NONE;
701 
702 	if (pix_format->pixelformat == V4L2_PIX_FMT_JPEG)
703 		pix_format->colorspace = V4L2_COLORSPACE_JPEG;
704 	else if (info && info->pixel_enc == V4L2_PIXEL_ENC_BAYER)
705 		pix_format->colorspace = V4L2_COLORSPACE_RAW;
706 	else
707 		pix_format->colorspace = V4L2_COLORSPACE_SRGB;
708 
709 	pix_format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
710 	pix_format->quantization = V4L2_QUANTIZATION_DEFAULT;
711 	pix_format->xfer_func = V4L2_XFER_FUNC_DEFAULT;
712 }
713 
714 static int sun6i_csi_capture_querycap(struct file *file, void *private,
715 				      struct v4l2_capability *capability)
716 {
717 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
718 	struct video_device *video_dev = &csi_dev->capture.video_dev;
719 
720 	strscpy(capability->driver, SUN6I_CSI_NAME, sizeof(capability->driver));
721 	strscpy(capability->card, video_dev->name, sizeof(capability->card));
722 	snprintf(capability->bus_info, sizeof(capability->bus_info),
723 		 "platform:%s", dev_name(csi_dev->dev));
724 
725 	return 0;
726 }
727 
728 static int sun6i_csi_capture_enum_fmt(struct file *file, void *private,
729 				      struct v4l2_fmtdesc *fmtdesc)
730 {
731 	u32 index = fmtdesc->index;
732 
733 	if (index >= ARRAY_SIZE(sun6i_csi_capture_formats))
734 		return -EINVAL;
735 
736 	fmtdesc->pixelformat = sun6i_csi_capture_formats[index].pixelformat;
737 
738 	return 0;
739 }
740 
741 static int sun6i_csi_capture_g_fmt(struct file *file, void *private,
742 				   struct v4l2_format *format)
743 {
744 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
745 
746 	*format = csi_dev->capture.format;
747 
748 	return 0;
749 }
750 
751 static int sun6i_csi_capture_s_fmt(struct file *file, void *private,
752 				   struct v4l2_format *format)
753 {
754 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
755 	struct sun6i_csi_capture *capture = &csi_dev->capture;
756 
757 	if (vb2_is_busy(&capture->queue))
758 		return -EBUSY;
759 
760 	sun6i_csi_capture_format_prepare(format);
761 
762 	csi_dev->capture.format = *format;
763 
764 	return 0;
765 }
766 
767 static int sun6i_csi_capture_try_fmt(struct file *file, void *private,
768 				     struct v4l2_format *format)
769 {
770 	sun6i_csi_capture_format_prepare(format);
771 
772 	return 0;
773 }
774 
775 static int sun6i_csi_capture_enum_input(struct file *file, void *private,
776 					struct v4l2_input *input)
777 {
778 	if (input->index != 0)
779 		return -EINVAL;
780 
781 	input->type = V4L2_INPUT_TYPE_CAMERA;
782 	strscpy(input->name, "Camera", sizeof(input->name));
783 
784 	return 0;
785 }
786 
787 static int sun6i_csi_capture_g_input(struct file *file, void *private,
788 				     unsigned int *index)
789 {
790 	*index = 0;
791 
792 	return 0;
793 }
794 
795 static int sun6i_csi_capture_s_input(struct file *file, void *private,
796 				     unsigned int index)
797 {
798 	if (index != 0)
799 		return -EINVAL;
800 
801 	return 0;
802 }
803 
804 static const struct v4l2_ioctl_ops sun6i_csi_capture_ioctl_ops = {
805 	.vidioc_querycap		= sun6i_csi_capture_querycap,
806 
807 	.vidioc_enum_fmt_vid_cap	= sun6i_csi_capture_enum_fmt,
808 	.vidioc_g_fmt_vid_cap		= sun6i_csi_capture_g_fmt,
809 	.vidioc_s_fmt_vid_cap		= sun6i_csi_capture_s_fmt,
810 	.vidioc_try_fmt_vid_cap		= sun6i_csi_capture_try_fmt,
811 
812 	.vidioc_enum_input		= sun6i_csi_capture_enum_input,
813 	.vidioc_g_input			= sun6i_csi_capture_g_input,
814 	.vidioc_s_input			= sun6i_csi_capture_s_input,
815 
816 	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
817 	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
818 	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
819 	.vidioc_querybuf		= vb2_ioctl_querybuf,
820 	.vidioc_expbuf			= vb2_ioctl_expbuf,
821 	.vidioc_qbuf			= vb2_ioctl_qbuf,
822 	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
823 	.vidioc_streamon		= vb2_ioctl_streamon,
824 	.vidioc_streamoff		= vb2_ioctl_streamoff,
825 };
826 
827 /* V4L2 File */
828 
829 static int sun6i_csi_capture_open(struct file *file)
830 {
831 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
832 	struct sun6i_csi_capture *capture = &csi_dev->capture;
833 	int ret;
834 
835 	if (mutex_lock_interruptible(&capture->lock))
836 		return -ERESTARTSYS;
837 
838 	ret = v4l2_pipeline_pm_get(&capture->video_dev.entity);
839 	if (ret < 0)
840 		goto error_lock;
841 
842 	ret = v4l2_fh_open(file);
843 	if (ret < 0)
844 		goto error_pipeline;
845 
846 	mutex_unlock(&capture->lock);
847 
848 	return 0;
849 
850 error_pipeline:
851 	v4l2_pipeline_pm_put(&capture->video_dev.entity);
852 
853 error_lock:
854 	mutex_unlock(&capture->lock);
855 
856 	return ret;
857 }
858 
859 static int sun6i_csi_capture_close(struct file *file)
860 {
861 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
862 	struct sun6i_csi_capture *capture = &csi_dev->capture;
863 
864 	mutex_lock(&capture->lock);
865 
866 	_vb2_fop_release(file, NULL);
867 	v4l2_pipeline_pm_put(&capture->video_dev.entity);
868 
869 	mutex_unlock(&capture->lock);
870 
871 	return 0;
872 }
873 
874 static const struct v4l2_file_operations sun6i_csi_capture_fops = {
875 	.owner		= THIS_MODULE,
876 	.open		= sun6i_csi_capture_open,
877 	.release	= sun6i_csi_capture_close,
878 	.unlocked_ioctl	= video_ioctl2,
879 	.mmap		= vb2_fop_mmap,
880 	.poll		= vb2_fop_poll
881 };
882 
883 /* Media Entity */
884 
885 static int sun6i_csi_capture_link_validate(struct media_link *link)
886 {
887 	struct video_device *video_dev =
888 		media_entity_to_video_device(link->sink->entity);
889 	struct sun6i_csi_device *csi_dev = video_get_drvdata(video_dev);
890 	struct v4l2_device *v4l2_dev = csi_dev->v4l2_dev;
891 	const struct sun6i_csi_capture_format *capture_format;
892 	const struct sun6i_csi_bridge_format *bridge_format;
893 	unsigned int capture_width, capture_height;
894 	unsigned int bridge_width, bridge_height;
895 	const struct v4l2_format_info *format_info;
896 	u32 pixelformat, capture_field;
897 	u32 mbus_code, bridge_field;
898 	bool match;
899 
900 	sun6i_csi_capture_dimensions(csi_dev, &capture_width, &capture_height);
901 
902 	sun6i_csi_capture_format(csi_dev, &pixelformat, &capture_field);
903 	capture_format = sun6i_csi_capture_format_find(pixelformat);
904 	if (WARN_ON(!capture_format))
905 		return -EINVAL;
906 
907 	sun6i_csi_bridge_dimensions(csi_dev, &bridge_width, &bridge_height);
908 
909 	sun6i_csi_bridge_format(csi_dev, &mbus_code, &bridge_field);
910 	bridge_format = sun6i_csi_bridge_format_find(mbus_code);
911 	if (WARN_ON(!bridge_format))
912 		return -EINVAL;
913 
914 	/* No cropping/scaling is supported. */
915 	if (capture_width != bridge_width || capture_height != bridge_height) {
916 		v4l2_err(v4l2_dev,
917 			 "invalid input/output dimensions: %ux%u/%ux%u\n",
918 			 bridge_width, bridge_height, capture_width,
919 			 capture_height);
920 		return -EINVAL;
921 	}
922 
923 	format_info = v4l2_format_info(pixelformat);
924 	/* Some formats are not listed. */
925 	if (!format_info)
926 		return 0;
927 
928 	if (format_info->pixel_enc == V4L2_PIXEL_ENC_BAYER &&
929 	    bridge_format->input_format != SUN6I_CSI_INPUT_FMT_RAW)
930 		goto invalid;
931 
932 	if (format_info->pixel_enc == V4L2_PIXEL_ENC_RGB &&
933 	    bridge_format->input_format != SUN6I_CSI_INPUT_FMT_RAW)
934 		goto invalid;
935 
936 	if (format_info->pixel_enc == V4L2_PIXEL_ENC_YUV) {
937 		if (bridge_format->input_format != SUN6I_CSI_INPUT_FMT_YUV420 &&
938 		    bridge_format->input_format != SUN6I_CSI_INPUT_FMT_YUV422)
939 			goto invalid;
940 
941 		/* YUV420 input can't produce YUV422 output. */
942 		if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_YUV420 &&
943 		    format_info->vdiv == 1)
944 			goto invalid;
945 	}
946 
947 	/* With raw input mode, we need a 1:1 match between input and output. */
948 	if (bridge_format->input_format == SUN6I_CSI_INPUT_FMT_RAW ||
949 	    capture_format->input_format_raw) {
950 		match = sun6i_csi_capture_format_match(pixelformat, mbus_code);
951 		if (!match)
952 			goto invalid;
953 	}
954 
955 	return 0;
956 
957 invalid:
958 	v4l2_err(v4l2_dev, "invalid input/output format combination\n");
959 	return -EINVAL;
960 }
961 
962 static const struct media_entity_operations sun6i_csi_capture_media_ops = {
963 	.link_validate = sun6i_csi_capture_link_validate
964 };
965 
966 /* Capture */
967 
968 int sun6i_csi_capture_setup(struct sun6i_csi_device *csi_dev)
969 {
970 	struct sun6i_csi_capture *capture = &csi_dev->capture;
971 	struct sun6i_csi_capture_state *state = &capture->state;
972 	struct v4l2_device *v4l2_dev = csi_dev->v4l2_dev;
973 	struct v4l2_subdev *bridge_subdev = &csi_dev->bridge.subdev;
974 	struct video_device *video_dev = &capture->video_dev;
975 	struct vb2_queue *queue = &capture->queue;
976 	struct media_pad *pad = &capture->pad;
977 	struct v4l2_format *format = &csi_dev->capture.format;
978 	struct v4l2_pix_format *pix_format = &format->fmt.pix;
979 	int ret;
980 
981 	/* This may happen with multiple bridge notifier bound calls. */
982 	if (state->setup)
983 		return 0;
984 
985 	/* State */
986 
987 	INIT_LIST_HEAD(&state->queue);
988 	spin_lock_init(&state->lock);
989 
990 	/* Media Entity */
991 
992 	video_dev->entity.ops = &sun6i_csi_capture_media_ops;
993 
994 	/* Media Pad */
995 
996 	pad->flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
997 
998 	ret = media_entity_pads_init(&video_dev->entity, 1, pad);
999 	if (ret < 0)
1000 		return ret;
1001 
1002 	/* Queue */
1003 
1004 	mutex_init(&capture->lock);
1005 
1006 	queue->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1007 	queue->io_modes = VB2_MMAP | VB2_DMABUF;
1008 	queue->buf_struct_size = sizeof(struct sun6i_csi_buffer);
1009 	queue->ops = &sun6i_csi_capture_queue_ops;
1010 	queue->mem_ops = &vb2_dma_contig_memops;
1011 	queue->min_queued_buffers = 2;
1012 	queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1013 	queue->lock = &capture->lock;
1014 	queue->dev = csi_dev->dev;
1015 	queue->drv_priv = csi_dev;
1016 
1017 	ret = vb2_queue_init(queue);
1018 	if (ret) {
1019 		v4l2_err(v4l2_dev, "failed to initialize vb2 queue: %d\n", ret);
1020 		goto error_media_entity;
1021 	}
1022 
1023 	/* V4L2 Format */
1024 
1025 	format->type = queue->type;
1026 	pix_format->pixelformat = sun6i_csi_capture_formats[0].pixelformat;
1027 	pix_format->width = 1280;
1028 	pix_format->height = 720;
1029 	pix_format->field = V4L2_FIELD_NONE;
1030 
1031 	sun6i_csi_capture_format_prepare(format);
1032 
1033 	/* Video Device */
1034 
1035 	strscpy(video_dev->name, SUN6I_CSI_CAPTURE_NAME,
1036 		sizeof(video_dev->name));
1037 	video_dev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
1038 	video_dev->vfl_dir = VFL_DIR_RX;
1039 	video_dev->release = video_device_release_empty;
1040 	video_dev->fops = &sun6i_csi_capture_fops;
1041 	video_dev->ioctl_ops = &sun6i_csi_capture_ioctl_ops;
1042 	video_dev->v4l2_dev = v4l2_dev;
1043 	video_dev->queue = queue;
1044 	video_dev->lock = &capture->lock;
1045 
1046 	video_set_drvdata(video_dev, csi_dev);
1047 
1048 	ret = video_register_device(video_dev, VFL_TYPE_VIDEO, -1);
1049 	if (ret < 0) {
1050 		v4l2_err(v4l2_dev, "failed to register video device: %d\n",
1051 			 ret);
1052 		goto error_media_entity;
1053 	}
1054 
1055 	/* Media Pad Link */
1056 
1057 	ret = media_create_pad_link(&bridge_subdev->entity,
1058 				    SUN6I_CSI_BRIDGE_PAD_SOURCE,
1059 				    &video_dev->entity, 0,
1060 				    csi_dev->isp_available ? 0 :
1061 				    MEDIA_LNK_FL_ENABLED |
1062 				    MEDIA_LNK_FL_IMMUTABLE);
1063 	if (ret < 0) {
1064 		v4l2_err(v4l2_dev, "failed to create %s:%u -> %s:%u link\n",
1065 			 bridge_subdev->entity.name,
1066 			 SUN6I_CSI_BRIDGE_PAD_SOURCE,
1067 			 video_dev->entity.name, 0);
1068 		goto error_video_device;
1069 	}
1070 
1071 	state->setup = true;
1072 
1073 	return 0;
1074 
1075 error_video_device:
1076 	vb2_video_unregister_device(video_dev);
1077 
1078 error_media_entity:
1079 	media_entity_cleanup(&video_dev->entity);
1080 
1081 	mutex_destroy(&capture->lock);
1082 
1083 	return ret;
1084 }
1085 
1086 void sun6i_csi_capture_cleanup(struct sun6i_csi_device *csi_dev)
1087 {
1088 	struct sun6i_csi_capture *capture = &csi_dev->capture;
1089 	struct video_device *video_dev = &capture->video_dev;
1090 
1091 	/* This may happen if async registration failed to complete. */
1092 	if (!capture->state.setup)
1093 		return;
1094 
1095 	vb2_video_unregister_device(video_dev);
1096 	media_entity_cleanup(&video_dev->entity);
1097 	mutex_destroy(&capture->lock);
1098 
1099 	capture->state.setup = false;
1100 }
1101