xref: /linux/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Rockchip Camera Interface (CIF) Driver
4  *
5  * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
6  * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
7  * Copyright (C) 2025 Collabora, Ltd.
8  */
9 
10 #include <linux/interrupt.h>
11 
12 #include <media/mipi-csi2.h>
13 #include <media/v4l2-common.h>
14 #include <media/v4l2-event.h>
15 #include <media/v4l2-fh.h>
16 #include <media/v4l2-fwnode.h>
17 #include <media/v4l2-ioctl.h>
18 #include <media/v4l2-mc.h>
19 #include <media/v4l2-subdev.h>
20 
21 #include "rkcif-capture-mipi.h"
22 #include "rkcif-common.h"
23 #include "rkcif-interface.h"
24 #include "rkcif-regs.h"
25 #include "rkcif-stream.h"
26 
27 #define RK3568_MIPI_CTRL0_HIGH_ALIGN  BIT(31)
28 #define RK3568_MIPI_CTRL0_UV_SWAP_EN  BIT(7)
29 #define RK3568_MIPI_CTRL0_COMPACT_EN  BIT(6)
30 #define RK3568_MIPI_CTRL0_CROP_EN     BIT(5)
31 #define RK3568_MIPI_CTRL0_WRDDR(type) ((type) << 1)
32 
33 #define RKCIF_MIPI_CTRL0_DT_ID(id)    ((id) << 10)
34 #define RKCIF_MIPI_CTRL0_VC_ID(id)    ((id) << 8)
35 #define RKCIF_MIPI_CTRL0_CAP_EN	      BIT(0)
36 
37 #define RKCIF_MIPI_INT_FRAME0_END(id) BIT(8 + (id) * 2 + 0)
38 #define RKCIF_MIPI_INT_FRAME1_END(id) BIT(8 + (id) * 2 + 1)
39 
40 static const struct rkcif_output_fmt mipi_out_fmts[] = {
41 	/* YUV formats */
42 	{
43 		.fourcc = V4L2_PIX_FMT_YUYV,
44 		.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
45 		.depth = 16,
46 		.cplanes = 1,
47 		.mipi = {
48 			.dt = MIPI_CSI2_DT_YUV422_8B,
49 			.type = RKCIF_MIPI_TYPE_RAW8,
50 		},
51 	},
52 	{
53 		.fourcc = V4L2_PIX_FMT_UYVY,
54 		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
55 		.depth = 16,
56 		.cplanes = 1,
57 		.mipi = {
58 			.dt = MIPI_CSI2_DT_YUV422_8B,
59 			.type = RKCIF_MIPI_TYPE_RAW8,
60 		},
61 	},
62 	{
63 		.fourcc = V4L2_PIX_FMT_YVYU,
64 		.mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
65 		.depth = 16,
66 		.cplanes = 1,
67 		.mipi = {
68 			.dt = MIPI_CSI2_DT_YUV422_8B,
69 			.type = RKCIF_MIPI_TYPE_RAW8,
70 		},
71 	},
72 	{
73 		.fourcc = V4L2_PIX_FMT_VYUY,
74 		.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
75 		.depth = 16,
76 		.cplanes = 1,
77 		.mipi = {
78 			.dt = MIPI_CSI2_DT_YUV422_8B,
79 			.type = RKCIF_MIPI_TYPE_RAW8,
80 		},
81 	},
82 	/* RGB formats */
83 	{
84 		.fourcc = V4L2_PIX_FMT_RGB24,
85 		.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
86 		.depth = 24,
87 		.cplanes = 1,
88 		.mipi = {
89 			.dt = MIPI_CSI2_DT_RGB888,
90 			.type = RKCIF_MIPI_TYPE_RGB888,
91 		},
92 	},
93 	{
94 		.fourcc = V4L2_PIX_FMT_BGR24,
95 		.mbus_code = MEDIA_BUS_FMT_BGR888_1X24,
96 		.depth = 24,
97 		.cplanes = 1,
98 		.mipi = {
99 			.dt = MIPI_CSI2_DT_RGB888,
100 			.type = RKCIF_MIPI_TYPE_RGB888,
101 		},
102 	},
103 	/* Bayer formats */
104 	{
105 		.fourcc = V4L2_PIX_FMT_SBGGR8,
106 		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
107 		.depth = 8,
108 		.cplanes = 1,
109 		.mipi = {
110 			.dt = MIPI_CSI2_DT_RAW8,
111 			.type = RKCIF_MIPI_TYPE_RAW8,
112 		},
113 	},
114 	{
115 		.fourcc = V4L2_PIX_FMT_SGBRG8,
116 		.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
117 		.depth = 8,
118 		.cplanes = 1,
119 		.mipi = {
120 			.dt = MIPI_CSI2_DT_RAW8,
121 			.type = RKCIF_MIPI_TYPE_RAW8,
122 		},
123 	},
124 	{
125 		.fourcc = V4L2_PIX_FMT_SGRBG8,
126 		.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
127 		.depth = 8,
128 		.cplanes = 1,
129 		.mipi = {
130 			.dt = MIPI_CSI2_DT_RAW8,
131 			.type = RKCIF_MIPI_TYPE_RAW8,
132 		},
133 	},
134 	{
135 		.fourcc = V4L2_PIX_FMT_SRGGB8,
136 		.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
137 		.depth = 8,
138 		.cplanes = 1,
139 		.mipi = {
140 			.dt = MIPI_CSI2_DT_RAW8,
141 			.type = RKCIF_MIPI_TYPE_RAW8,
142 		},
143 	},
144 	{
145 		.fourcc = V4L2_PIX_FMT_SBGGR10,
146 		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
147 		.depth = 10,
148 		.cplanes = 1,
149 		.mipi = {
150 			.dt = MIPI_CSI2_DT_RAW10,
151 			.type = RKCIF_MIPI_TYPE_RAW10,
152 		},
153 	},
154 	{
155 		.fourcc = V4L2_PIX_FMT_SBGGR10P,
156 		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
157 		.depth = 10,
158 		.cplanes = 1,
159 		.mipi = {
160 			.dt = MIPI_CSI2_DT_RAW10,
161 			.compact = true,
162 			.type = RKCIF_MIPI_TYPE_RAW10,
163 		},
164 	},
165 	{
166 		.fourcc = V4L2_PIX_FMT_SGBRG10,
167 		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
168 		.depth = 10,
169 		.cplanes = 1,
170 		.mipi = {
171 			.dt = MIPI_CSI2_DT_RAW10,
172 			.type = RKCIF_MIPI_TYPE_RAW10,
173 		},
174 	},
175 	{
176 		.fourcc = V4L2_PIX_FMT_SGBRG10P,
177 		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
178 		.depth = 10,
179 		.cplanes = 1,
180 		.mipi = {
181 			.dt = MIPI_CSI2_DT_RAW10,
182 			.compact = true,
183 			.type = RKCIF_MIPI_TYPE_RAW10,
184 		},
185 	},
186 	{
187 		.fourcc = V4L2_PIX_FMT_SGRBG10,
188 		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
189 		.depth = 10,
190 		.cplanes = 1,
191 		.mipi = {
192 			.dt = MIPI_CSI2_DT_RAW10,
193 			.type = RKCIF_MIPI_TYPE_RAW10,
194 		},
195 	},
196 	{
197 		.fourcc = V4L2_PIX_FMT_SGRBG10P,
198 		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
199 		.depth = 10,
200 		.cplanes = 1,
201 		.mipi = {
202 			.dt = MIPI_CSI2_DT_RAW10,
203 			.compact = true,
204 			.type = RKCIF_MIPI_TYPE_RAW10,
205 		},
206 	},
207 	{
208 		.fourcc = V4L2_PIX_FMT_SRGGB10,
209 		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
210 		.depth = 10,
211 		.cplanes = 1,
212 		.mipi = {
213 			.dt = MIPI_CSI2_DT_RAW10,
214 			.type = RKCIF_MIPI_TYPE_RAW10,
215 		},
216 	},
217 	{
218 		.fourcc = V4L2_PIX_FMT_SRGGB10P,
219 		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
220 		.depth = 10,
221 		.cplanes = 1,
222 		.mipi = {
223 			.dt = MIPI_CSI2_DT_RAW10,
224 			.compact = true,
225 			.type = RKCIF_MIPI_TYPE_RAW10,
226 		},
227 	},
228 	{
229 		.fourcc = V4L2_PIX_FMT_SBGGR12,
230 		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
231 		.depth = 12,
232 		.cplanes = 1,
233 		.mipi = {
234 			.dt = MIPI_CSI2_DT_RAW12,
235 			.type = RKCIF_MIPI_TYPE_RAW12,
236 		},
237 	},
238 	{
239 		.fourcc = V4L2_PIX_FMT_SBGGR12P,
240 		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
241 		.depth = 12,
242 		.cplanes = 1,
243 		.mipi = {
244 			.dt = MIPI_CSI2_DT_RAW12,
245 			.compact = true,
246 			.type = RKCIF_MIPI_TYPE_RAW12,
247 		},
248 	},
249 	{
250 		.fourcc = V4L2_PIX_FMT_SGBRG12,
251 		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
252 		.depth = 12,
253 		.cplanes = 1,
254 		.mipi = {
255 			.dt = MIPI_CSI2_DT_RAW12,
256 			.type = RKCIF_MIPI_TYPE_RAW12,
257 		},
258 	},
259 	{
260 		.fourcc = V4L2_PIX_FMT_SGBRG12P,
261 		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
262 		.depth = 12,
263 		.cplanes = 1,
264 		.mipi = {
265 			.dt = MIPI_CSI2_DT_RAW12,
266 			.compact = true,
267 			.type = RKCIF_MIPI_TYPE_RAW12,
268 		},
269 	},
270 	{
271 		.fourcc = V4L2_PIX_FMT_SGRBG12,
272 		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
273 		.depth = 12,
274 		.cplanes = 1,
275 		.mipi = {
276 			.dt = MIPI_CSI2_DT_RAW12,
277 			.type = RKCIF_MIPI_TYPE_RAW12,
278 		},
279 	},
280 	{
281 		.fourcc = V4L2_PIX_FMT_SGRBG12P,
282 		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
283 		.depth = 12,
284 		.cplanes = 1,
285 		.mipi = {
286 			.dt = MIPI_CSI2_DT_RAW12,
287 			.compact = true,
288 			.type = RKCIF_MIPI_TYPE_RAW12,
289 		},
290 	},
291 	{
292 		.fourcc = V4L2_PIX_FMT_SRGGB12,
293 		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
294 		.depth = 12,
295 		.cplanes = 1,
296 		.mipi = {
297 			.dt = MIPI_CSI2_DT_RAW12,
298 			.type = RKCIF_MIPI_TYPE_RAW12,
299 		},
300 	},
301 	{
302 		.fourcc = V4L2_PIX_FMT_SRGGB12P,
303 		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
304 		.depth = 12,
305 		.cplanes = 1,
306 		.mipi = {
307 			.dt = MIPI_CSI2_DT_RAW12,
308 			.compact = true,
309 			.type = RKCIF_MIPI_TYPE_RAW12,
310 		},
311 	},
312 };
313 
314 static const struct rkcif_input_fmt mipi_in_fmts[] = {
315 	/* YUV formats */
316 	{
317 		.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
318 	},
319 	{
320 		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
321 	},
322 	{
323 		.mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
324 	},
325 	{
326 		.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
327 	},
328 	/* RGB formats */
329 	{
330 		.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
331 	},
332 	{
333 		.mbus_code = MEDIA_BUS_FMT_BGR888_1X24,
334 	},
335 	/* Bayer formats */
336 	{
337 		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
338 	},
339 	{
340 		.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
341 	},
342 	{
343 		.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
344 	},
345 	{
346 		.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
347 	},
348 	{
349 		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
350 	},
351 	{
352 		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
353 	},
354 	{
355 		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
356 	},
357 	{
358 		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
359 	},
360 	{
361 		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
362 	},
363 	{
364 		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
365 	},
366 	{
367 		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
368 	},
369 	{
370 		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
371 	},
372 };
373 
374 static u32
375 rkcif_rk3568_mipi_ctrl0(struct rkcif_stream *stream,
376 			const struct rkcif_output_fmt *active_out_fmt)
377 {
378 	u32 ctrl0 = 0;
379 
380 	ctrl0 |= RKCIF_MIPI_CTRL0_DT_ID(active_out_fmt->mipi.dt);
381 	ctrl0 |= RKCIF_MIPI_CTRL0_CAP_EN;
382 	ctrl0 |= RK3568_MIPI_CTRL0_CROP_EN;
383 
384 	if (active_out_fmt->mipi.compact)
385 		ctrl0 |= RK3568_MIPI_CTRL0_COMPACT_EN;
386 
387 	switch (active_out_fmt->mipi.type) {
388 	case RKCIF_MIPI_TYPE_RAW8:
389 		break;
390 	case RKCIF_MIPI_TYPE_RAW10:
391 		ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x1);
392 		break;
393 	case RKCIF_MIPI_TYPE_RAW12:
394 		ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x2);
395 		break;
396 	case RKCIF_MIPI_TYPE_RGB888:
397 		ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x3);
398 		break;
399 	case RKCIF_MIPI_TYPE_YUV422SP:
400 		ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x4);
401 		break;
402 	case RKCIF_MIPI_TYPE_YUV420SP:
403 		ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x5);
404 		break;
405 	case RKCIF_MIPI_TYPE_YUV400:
406 		ctrl0 |= RK3568_MIPI_CTRL0_WRDDR(0x6);
407 		break;
408 	default:
409 		break;
410 	}
411 
412 	return ctrl0;
413 }
414 
415 const struct rkcif_mipi_match_data rkcif_rk3568_vicap_mipi_match_data = {
416 	.mipi_num = 1,
417 	.mipi_ctrl0 = rkcif_rk3568_mipi_ctrl0,
418 	.regs = {
419 		[RKCIF_MIPI_CTRL] = 0x20,
420 		[RKCIF_MIPI_INTEN] = 0xa4,
421 		[RKCIF_MIPI_INTSTAT] = 0xa8,
422 	},
423 	.regs_id = {
424 		[RKCIF_ID0] = {
425 			[RKCIF_MIPI_CTRL0] = 0x00,
426 			[RKCIF_MIPI_CTRL1] = 0x04,
427 			[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x24,
428 			[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x2c,
429 			[RKCIF_MIPI_FRAME0_VLW_Y] = 0x34,
430 			[RKCIF_MIPI_FRAME0_VLW_UV] = 0x3c,
431 			[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x28,
432 			[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x30,
433 			[RKCIF_MIPI_FRAME1_VLW_Y] = 0x38,
434 			[RKCIF_MIPI_FRAME1_VLW_UV] = 0x40,
435 			[RKCIF_MIPI_CROP_START] = 0xbc,
436 		},
437 		[RKCIF_ID1] = {
438 			[RKCIF_MIPI_CTRL0] = 0x08,
439 			[RKCIF_MIPI_CTRL1] = 0x0c,
440 			[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x44,
441 			[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x4c,
442 			[RKCIF_MIPI_FRAME0_VLW_Y] = 0x54,
443 			[RKCIF_MIPI_FRAME0_VLW_UV] = 0x5c,
444 			[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x48,
445 			[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x50,
446 			[RKCIF_MIPI_FRAME1_VLW_Y] = 0x58,
447 			[RKCIF_MIPI_FRAME1_VLW_UV] = 0x60,
448 			[RKCIF_MIPI_CROP_START] = 0xc0,
449 		},
450 		[RKCIF_ID2] = {
451 			[RKCIF_MIPI_CTRL0] = 0x10,
452 			[RKCIF_MIPI_CTRL1] = 0x14,
453 			[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x64,
454 			[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x6c,
455 			[RKCIF_MIPI_FRAME0_VLW_Y] = 0x74,
456 			[RKCIF_MIPI_FRAME0_VLW_UV] = 0x7c,
457 			[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x68,
458 			[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x70,
459 			[RKCIF_MIPI_FRAME1_VLW_Y] = 0x78,
460 			[RKCIF_MIPI_FRAME1_VLW_UV] = 0x80,
461 			[RKCIF_MIPI_CROP_START] = 0xc4,
462 		},
463 		[RKCIF_ID3] = {
464 			[RKCIF_MIPI_CTRL0] = 0x18,
465 			[RKCIF_MIPI_CTRL1] = 0x1c,
466 			[RKCIF_MIPI_FRAME0_ADDR_Y] = 0x84,
467 			[RKCIF_MIPI_FRAME0_ADDR_UV] = 0x8c,
468 			[RKCIF_MIPI_FRAME0_VLW_Y] = 0x94,
469 			[RKCIF_MIPI_FRAME0_VLW_UV] = 0x9c,
470 			[RKCIF_MIPI_FRAME1_ADDR_Y] = 0x88,
471 			[RKCIF_MIPI_FRAME1_ADDR_UV] = 0x90,
472 			[RKCIF_MIPI_FRAME1_VLW_Y] = 0x98,
473 			[RKCIF_MIPI_FRAME1_VLW_UV] = 0xa0,
474 			[RKCIF_MIPI_CROP_START] = 0xc8,
475 		},
476 	},
477 	.blocks = {
478 		{
479 			.offset = 0x80,
480 		},
481 	},
482 };
483 
484 static inline unsigned int rkcif_mipi_get_reg(struct rkcif_interface *interface,
485 					      unsigned int index)
486 {
487 	struct rkcif_device *rkcif = interface->rkcif;
488 	unsigned int block, offset, reg;
489 
490 	block = interface->index - RKCIF_MIPI_BASE;
491 
492 	if (WARN_ON_ONCE(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) ||
493 	    WARN_ON_ONCE(index > RKCIF_MIPI_REGISTER_MAX))
494 		return RKCIF_REGISTER_NOTSUPPORTED;
495 
496 	offset = rkcif->match_data->mipi->blocks[block].offset;
497 	reg = rkcif->match_data->mipi->regs[index];
498 	if (reg == RKCIF_REGISTER_NOTSUPPORTED)
499 		return reg;
500 
501 	return offset + reg;
502 }
503 
504 static inline unsigned int rkcif_mipi_id_get_reg(struct rkcif_stream *stream,
505 						 unsigned int index)
506 {
507 	struct rkcif_device *rkcif = stream->rkcif;
508 	unsigned int block, id, offset, reg;
509 
510 	block = stream->interface->index - RKCIF_MIPI_BASE;
511 	id = stream->id;
512 
513 	if (WARN_ON_ONCE(block > RKCIF_MIPI_MAX - RKCIF_MIPI_BASE) ||
514 	    WARN_ON_ONCE(id > RKCIF_ID_MAX) ||
515 	    WARN_ON_ONCE(index > RKCIF_MIPI_ID_REGISTER_MAX))
516 		return RKCIF_REGISTER_NOTSUPPORTED;
517 
518 	offset = rkcif->match_data->mipi->blocks[block].offset;
519 	reg = rkcif->match_data->mipi->regs_id[id][index];
520 	if (reg == RKCIF_REGISTER_NOTSUPPORTED)
521 		return reg;
522 
523 	return offset + reg;
524 }
525 
526 static inline __maybe_unused void
527 rkcif_mipi_write(struct rkcif_interface *interface, unsigned int index, u32 val)
528 {
529 	unsigned int addr = rkcif_mipi_get_reg(interface, index);
530 
531 	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
532 		return;
533 
534 	writel(val, interface->rkcif->base_addr + addr);
535 }
536 
537 static inline __maybe_unused void
538 rkcif_mipi_stream_write(struct rkcif_stream *stream, unsigned int index,
539 			u32 val)
540 {
541 	unsigned int addr = rkcif_mipi_id_get_reg(stream, index);
542 
543 	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
544 		return;
545 
546 	writel(val, stream->rkcif->base_addr + addr);
547 }
548 
549 static inline __maybe_unused u32
550 rkcif_mipi_read(struct rkcif_interface *interface, unsigned int index)
551 {
552 	unsigned int addr = rkcif_mipi_get_reg(interface, index);
553 
554 	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
555 		return 0;
556 
557 	return readl(interface->rkcif->base_addr + addr);
558 }
559 
560 static inline __maybe_unused u32
561 rkcif_mipi_stream_read(struct rkcif_stream *stream, unsigned int index)
562 {
563 	unsigned int addr = rkcif_mipi_id_get_reg(stream, index);
564 
565 	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
566 		return 0;
567 
568 	return readl(stream->rkcif->base_addr + addr);
569 }
570 
571 static void rkcif_mipi_queue_buffer(struct rkcif_stream *stream,
572 				    unsigned int index)
573 {
574 	struct rkcif_buffer *buffer = stream->buffers[index];
575 	u32 frm_addr_y, frm_addr_uv;
576 
577 	frm_addr_y = index ? RKCIF_MIPI_FRAME1_ADDR_Y :
578 			     RKCIF_MIPI_FRAME0_ADDR_Y;
579 	frm_addr_uv = index ? RKCIF_MIPI_FRAME1_ADDR_UV :
580 			      RKCIF_MIPI_FRAME0_ADDR_UV;
581 
582 	rkcif_mipi_stream_write(stream, frm_addr_y,
583 				buffer->buff_addr[RKCIF_PLANE_Y]);
584 	rkcif_mipi_stream_write(stream, frm_addr_uv,
585 				buffer->buff_addr[RKCIF_PLANE_UV]);
586 }
587 
588 static int rkcif_mipi_start_streaming(struct rkcif_stream *stream)
589 {
590 	struct rkcif_interface *interface = stream->interface;
591 	const struct rkcif_output_fmt *active_out_fmt;
592 	const struct rkcif_mipi_match_data *match_data;
593 	struct v4l2_subdev_state *state;
594 	u32 ctrl0 = 0, ctrl1 = 0, int_temp = 0, int_mask = 0, vlw = 0;
595 	u16 height, width;
596 	int ret = -EINVAL;
597 
598 	state = v4l2_subdev_lock_and_get_active_state(&interface->sd);
599 
600 	active_out_fmt = rkcif_stream_find_output_fmt(stream, false,
601 						      stream->pix.pixelformat);
602 	if (!active_out_fmt)
603 		goto out;
604 
605 	height = stream->pix.height;
606 	width = stream->pix.width;
607 	vlw = stream->pix.plane_fmt[0].bytesperline;
608 
609 	match_data = stream->rkcif->match_data->mipi;
610 	if (match_data->mipi_ctrl0)
611 		ctrl0 = match_data->mipi_ctrl0(stream, active_out_fmt);
612 
613 	ctrl1 = RKCIF_XY_COORD(width, height);
614 
615 	int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id);
616 	int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id);
617 
618 	int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN);
619 	int_temp |= int_mask;
620 	rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp);
621 
622 	int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
623 	int_temp &= ~int_mask;
624 	rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp);
625 
626 	rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_Y, vlw);
627 	rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_Y, vlw);
628 	rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME0_VLW_UV, vlw);
629 	rkcif_mipi_stream_write(stream, RKCIF_MIPI_FRAME1_VLW_UV, vlw);
630 	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, 0x0);
631 	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL1, ctrl1);
632 	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, ctrl0);
633 
634 	ret = 0;
635 
636 out:
637 	v4l2_subdev_unlock_state(state);
638 	return ret;
639 }
640 
641 static void rkcif_mipi_stop_streaming(struct rkcif_stream *stream)
642 {
643 	struct rkcif_interface *interface = stream->interface;
644 	struct v4l2_subdev_state *state;
645 	u32 int_temp = 0, int_mask = 0;
646 
647 	state = v4l2_subdev_lock_and_get_active_state(&interface->sd);
648 
649 	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CTRL0, 0);
650 
651 	int_mask |= RKCIF_MIPI_INT_FRAME0_END(stream->id);
652 	int_mask |= RKCIF_MIPI_INT_FRAME1_END(stream->id);
653 
654 	int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTEN);
655 	int_temp &= ~int_mask;
656 	rkcif_mipi_write(interface, RKCIF_MIPI_INTEN, int_temp);
657 
658 	int_temp = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
659 	int_temp &= ~int_mask;
660 	rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, int_temp);
661 
662 	stream->stopping = false;
663 
664 	v4l2_subdev_unlock_state(state);
665 }
666 
667 static void rkcif_mipi_set_crop(struct rkcif_stream *stream, u16 left, u16 top)
668 {
669 	u32 val;
670 
671 	val = RKCIF_XY_COORD(left, top);
672 	rkcif_mipi_stream_write(stream, RKCIF_MIPI_CROP_START, val);
673 }
674 
675 irqreturn_t rkcif_mipi_isr(int irq, void *ctx)
676 {
677 	struct device *dev = ctx;
678 	struct rkcif_device *rkcif = dev_get_drvdata(dev);
679 	irqreturn_t ret = IRQ_NONE;
680 	u32 intstat;
681 
682 	for (unsigned int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
683 		enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
684 		struct rkcif_interface *interface = &rkcif->interfaces[index];
685 
686 		intstat = rkcif_mipi_read(interface, RKCIF_MIPI_INTSTAT);
687 		rkcif_mipi_write(interface, RKCIF_MIPI_INTSTAT, intstat);
688 
689 		for (unsigned int j = 0; j < interface->streams_num; j++) {
690 			struct rkcif_stream *stream = &interface->streams[j];
691 
692 			if (intstat & RKCIF_MIPI_INT_FRAME0_END(stream->id) ||
693 			    intstat & RKCIF_MIPI_INT_FRAME1_END(stream->id)) {
694 				ret = IRQ_HANDLED;
695 
696 				if (stream->stopping) {
697 					rkcif_mipi_stop_streaming(stream);
698 					wake_up(&stream->wq_stopped);
699 					continue;
700 				}
701 
702 				rkcif_stream_pingpong(stream);
703 			}
704 		}
705 	}
706 
707 	return ret;
708 }
709 
710 int rkcif_mipi_register(struct rkcif_device *rkcif)
711 {
712 	int ret;
713 
714 	if (!rkcif->match_data->mipi)
715 		return 0;
716 
717 	for (unsigned int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
718 		enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
719 		struct rkcif_interface *interface = &rkcif->interfaces[index];
720 
721 		interface->index = index;
722 		interface->type = RKCIF_IF_MIPI;
723 		interface->in_fmts = mipi_in_fmts;
724 		interface->in_fmts_num = ARRAY_SIZE(mipi_in_fmts);
725 		interface->set_crop = rkcif_mipi_set_crop;
726 		interface->streams_num = 0;
727 		ret = rkcif_interface_register(rkcif, interface);
728 		if (ret)
729 			continue;
730 
731 		for (unsigned int j = 0; j < RKCIF_ID_MAX; j++) {
732 			struct rkcif_stream *stream = &interface->streams[j];
733 
734 			stream->id = j;
735 			stream->interface = interface;
736 			stream->out_fmts = mipi_out_fmts;
737 			stream->out_fmts_num = ARRAY_SIZE(mipi_out_fmts);
738 			stream->queue_buffer = rkcif_mipi_queue_buffer;
739 			stream->start_streaming = rkcif_mipi_start_streaming;
740 			stream->stop_streaming = rkcif_mipi_stop_streaming;
741 			ret = rkcif_stream_register(rkcif, stream);
742 			if (ret)
743 				goto err;
744 			interface->streams_num++;
745 		}
746 	}
747 
748 	return 0;
749 
750 err:
751 	for (unsigned int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
752 		enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
753 		struct rkcif_interface *interface = &rkcif->interfaces[index];
754 
755 		for (unsigned int j = 0; j < interface->streams_num; j++)
756 			rkcif_stream_unregister(&interface->streams[j]);
757 
758 		rkcif_interface_unregister(interface);
759 	}
760 	return ret;
761 }
762 
763 void rkcif_mipi_unregister(struct rkcif_device *rkcif)
764 {
765 	if (!rkcif->match_data->mipi)
766 		return;
767 
768 	for (unsigned int i = 0; i < rkcif->match_data->mipi->mipi_num; i++) {
769 		enum rkcif_interface_index index = RKCIF_MIPI_BASE + i;
770 		struct rkcif_interface *interface = &rkcif->interfaces[index];
771 
772 		for (unsigned int j = 0; j < interface->streams_num; j++)
773 			rkcif_stream_unregister(&interface->streams[j]);
774 
775 		rkcif_interface_unregister(interface);
776 	}
777 }
778