File Index
Files and directories
Sign in
FILE

rkcif-capture-mipi.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/rockchip/rkcif/rkcif-capture-mipi.c C
  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
 40static 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
314static 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
374static u32
375rkcif_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
415const 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
484static 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
504static 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
526static inline __maybe_unused void
527rkcif_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
537static inline __maybe_unused void
538rkcif_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
549static inline __maybe_unused u32
550rkcif_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
560static inline __maybe_unused u32
561rkcif_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
571static 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
588static 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
636out:
637	v4l2_subdev_unlock_state(state);
638	return ret;
639}
640
641static 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
667static 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
675irqreturn_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
710int 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
750err:
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
763void 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}
~/ Read-only file preview.