xref: /linux/drivers/media/platform/rockchip/rkcif/rkcif-capture-dvp.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) 2020 Maxime Chevallier <maxime.chevallier@bootlin.com>
7  * Copyright (C) 2023 Mehdi Djait <mehdi.djait@bootlin.com>
8  * Copyright (C) 2025 Michael Riesch <michael.riesch@wolfvision.net>
9  * Copyright (C) 2025 Collabora, Ltd.
10  */
11 
12 #include <media/v4l2-common.h>
13 #include <media/v4l2-fwnode.h>
14 #include <media/v4l2-mc.h>
15 #include <media/v4l2-subdev.h>
16 
17 #include "rkcif-capture-dvp.h"
18 #include "rkcif-common.h"
19 #include "rkcif-interface.h"
20 #include "rkcif-regs.h"
21 #include "rkcif-stream.h"
22 
23 static const struct rkcif_output_fmt dvp_out_fmts[] = {
24 	{
25 		.fourcc = V4L2_PIX_FMT_NV16,
26 		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 |
27 			       RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV,
28 		.cplanes = 2,
29 	},
30 	{
31 		.fourcc = V4L2_PIX_FMT_NV16M,
32 		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 |
33 			       RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV,
34 		.cplanes = 2,
35 	},
36 	{
37 		.fourcc = V4L2_PIX_FMT_NV61,
38 		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 |
39 			       RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU,
40 		.cplanes = 2,
41 	},
42 	{
43 		.fourcc = V4L2_PIX_FMT_NV61M,
44 		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_422 |
45 			       RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU,
46 		.cplanes = 2,
47 	},
48 	{
49 		.fourcc = V4L2_PIX_FMT_NV12,
50 		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 |
51 			       RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV,
52 		.cplanes = 2,
53 	},
54 	{
55 		.fourcc = V4L2_PIX_FMT_NV12M,
56 		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 |
57 			       RKCIF_FORMAT_UV_STORAGE_ORDER_UVUV,
58 		.cplanes = 2,
59 	},
60 	{
61 		.fourcc = V4L2_PIX_FMT_NV21,
62 		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 |
63 			       RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU,
64 		.cplanes = 2,
65 	},
66 	{
67 		.fourcc = V4L2_PIX_FMT_NV21M,
68 		.dvp_fmt_val = RKCIF_FORMAT_YUV_OUTPUT_420 |
69 			       RKCIF_FORMAT_UV_STORAGE_ORDER_VUVU,
70 		.cplanes = 2,
71 	},
72 	{
73 		.fourcc = V4L2_PIX_FMT_RGB24,
74 		.cplanes = 1,
75 	},
76 	{
77 		.fourcc = V4L2_PIX_FMT_RGB565,
78 		.cplanes = 1,
79 	},
80 	{
81 		.fourcc = V4L2_PIX_FMT_BGR666,
82 		.cplanes = 1,
83 	},
84 	{
85 		.fourcc = V4L2_PIX_FMT_SRGGB8,
86 		.cplanes = 1,
87 	},
88 	{
89 		.fourcc = V4L2_PIX_FMT_SGRBG8,
90 		.cplanes = 1,
91 	},
92 	{
93 		.fourcc = V4L2_PIX_FMT_SGBRG8,
94 		.cplanes = 1,
95 	},
96 	{
97 		.fourcc = V4L2_PIX_FMT_SBGGR8,
98 		.cplanes = 1,
99 	},
100 	{
101 		.fourcc = V4L2_PIX_FMT_SRGGB10,
102 		.cplanes = 1,
103 	},
104 	{
105 		.fourcc = V4L2_PIX_FMT_SGRBG10,
106 		.cplanes = 1,
107 	},
108 	{
109 		.fourcc = V4L2_PIX_FMT_SGBRG10,
110 		.cplanes = 1,
111 	},
112 	{
113 		.fourcc = V4L2_PIX_FMT_SBGGR10,
114 		.cplanes = 1,
115 	},
116 	{
117 		.fourcc = V4L2_PIX_FMT_SRGGB12,
118 		.cplanes = 1,
119 	},
120 	{
121 		.fourcc = V4L2_PIX_FMT_SGRBG12,
122 		.cplanes = 1,
123 	},
124 	{
125 		.fourcc = V4L2_PIX_FMT_SGBRG12,
126 		.cplanes = 1,
127 	},
128 	{
129 		.fourcc = V4L2_PIX_FMT_SBGGR12,
130 		.cplanes = 1,
131 	},
132 	{
133 		.fourcc = V4L2_PIX_FMT_SBGGR16,
134 		.cplanes = 1,
135 	},
136 	{
137 		.fourcc = V4L2_PIX_FMT_Y16,
138 		.cplanes = 1,
139 	},
140 };
141 
142 static const struct rkcif_input_fmt px30_dvp_in_fmts[] = {
143 	{
144 		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
145 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
146 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV,
147 		.fmt_type = RKCIF_FMT_TYPE_YUV,
148 		.field = V4L2_FIELD_NONE,
149 	},
150 	{
151 		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
152 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
153 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV,
154 		.fmt_type = RKCIF_FMT_TYPE_YUV,
155 		.field = V4L2_FIELD_INTERLACED,
156 	},
157 	{
158 		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
159 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
160 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU,
161 		.fmt_type = RKCIF_FMT_TYPE_YUV,
162 		.field = V4L2_FIELD_NONE,
163 	},
164 	{
165 		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
166 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
167 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU,
168 		.fmt_type = RKCIF_FMT_TYPE_YUV,
169 		.field = V4L2_FIELD_INTERLACED,
170 	},
171 	{
172 		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
173 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
174 			       RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY,
175 		.fmt_type = RKCIF_FMT_TYPE_YUV,
176 		.field = V4L2_FIELD_NONE,
177 	},
178 	{
179 		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
180 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
181 			       RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY,
182 		.fmt_type = RKCIF_FMT_TYPE_YUV,
183 		.field = V4L2_FIELD_INTERLACED,
184 	},
185 	{
186 		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
187 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
188 			       RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY,
189 		.fmt_type = RKCIF_FMT_TYPE_YUV,
190 		.field = V4L2_FIELD_NONE,
191 	},
192 	{
193 		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
194 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
195 			       RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY,
196 		.fmt_type = RKCIF_FMT_TYPE_YUV,
197 		.field = V4L2_FIELD_INTERLACED,
198 	},
199 	{
200 		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
201 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
202 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
203 		.fmt_type = RKCIF_FMT_TYPE_RAW,
204 		.field = V4L2_FIELD_NONE,
205 	},
206 	{
207 		.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
208 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
209 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
210 		.fmt_type = RKCIF_FMT_TYPE_RAW,
211 		.field = V4L2_FIELD_NONE,
212 	},
213 	{
214 		.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
215 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
216 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
217 		.fmt_type = RKCIF_FMT_TYPE_RAW,
218 		.field = V4L2_FIELD_NONE,
219 	},
220 	{
221 		.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
222 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
223 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
224 		.fmt_type = RKCIF_FMT_TYPE_RAW,
225 		.field = V4L2_FIELD_NONE,
226 	},
227 	{
228 		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
229 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
230 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
231 		.fmt_type = RKCIF_FMT_TYPE_RAW,
232 		.field = V4L2_FIELD_NONE,
233 	},
234 	{
235 		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
236 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
237 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
238 		.fmt_type = RKCIF_FMT_TYPE_RAW,
239 		.field = V4L2_FIELD_NONE,
240 	},
241 	{
242 		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
243 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
244 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
245 		.fmt_type = RKCIF_FMT_TYPE_RAW,
246 		.field = V4L2_FIELD_NONE,
247 	},
248 	{
249 		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
250 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
251 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
252 		.fmt_type = RKCIF_FMT_TYPE_RAW,
253 		.field = V4L2_FIELD_NONE,
254 	},
255 	{
256 		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
257 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
258 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
259 		.fmt_type = RKCIF_FMT_TYPE_RAW,
260 		.field = V4L2_FIELD_NONE,
261 	},
262 	{
263 		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
264 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
265 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
266 		.fmt_type = RKCIF_FMT_TYPE_RAW,
267 		.field = V4L2_FIELD_NONE,
268 	},
269 	{
270 		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
271 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
272 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
273 		.fmt_type = RKCIF_FMT_TYPE_RAW,
274 		.field = V4L2_FIELD_NONE,
275 	},
276 	{
277 		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
278 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
279 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
280 		.fmt_type = RKCIF_FMT_TYPE_RAW,
281 		.field = V4L2_FIELD_NONE,
282 	},
283 	{
284 		.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
285 		.field = V4L2_FIELD_NONE,
286 	},
287 	{
288 		.mbus_code = MEDIA_BUS_FMT_Y8_1X8,
289 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
290 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
291 		.fmt_type = RKCIF_FMT_TYPE_RAW,
292 		.field = V4L2_FIELD_NONE,
293 	},
294 	{
295 		.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
296 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
297 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
298 		.fmt_type = RKCIF_FMT_TYPE_RAW,
299 		.field = V4L2_FIELD_NONE,
300 	},
301 	{
302 		.mbus_code = MEDIA_BUS_FMT_Y12_1X12,
303 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
304 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
305 		.fmt_type = RKCIF_FMT_TYPE_RAW,
306 		.field = V4L2_FIELD_NONE,
307 	}
308 };
309 
310 const struct rkcif_dvp_match_data rkcif_px30_vip_dvp_match_data = {
311 	.in_fmts = px30_dvp_in_fmts,
312 	.in_fmts_num = ARRAY_SIZE(px30_dvp_in_fmts),
313 	.out_fmts = dvp_out_fmts,
314 	.out_fmts_num = ARRAY_SIZE(dvp_out_fmts),
315 	.has_scaler = true,
316 	.regs = {
317 		[RKCIF_DVP_CTRL] = 0x00,
318 		[RKCIF_DVP_INTEN] = 0x04,
319 		[RKCIF_DVP_INTSTAT] = 0x08,
320 		[RKCIF_DVP_FOR] = 0x0c,
321 		[RKCIF_DVP_LINE_NUM_ADDR] = 0x10,
322 		[RKCIF_DVP_FRM0_ADDR_Y] = 0x14,
323 		[RKCIF_DVP_FRM0_ADDR_UV] = 0x18,
324 		[RKCIF_DVP_FRM1_ADDR_Y] = 0x1c,
325 		[RKCIF_DVP_FRM1_ADDR_UV] = 0x20,
326 		[RKCIF_DVP_VIR_LINE_WIDTH] = 0x24,
327 		[RKCIF_DVP_SET_SIZE] = 0x28,
328 		[RKCIF_DVP_SCL_CTRL] = 0x48,
329 		[RKCIF_DVP_FRAME_STATUS] = 0x60,
330 		[RKCIF_DVP_LAST_LINE] = 0x68,
331 		[RKCIF_DVP_LAST_PIX] = 0x6c,
332 	},
333 };
334 
335 static const struct rkcif_input_fmt rk3568_dvp_in_fmts[] = {
336 	{
337 		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
338 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
339 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV,
340 		.fmt_type = RKCIF_FMT_TYPE_YUV,
341 		.field = V4L2_FIELD_NONE,
342 	},
343 	{
344 		.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
345 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
346 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV,
347 		.fmt_type = RKCIF_FMT_TYPE_YUV,
348 		.field = V4L2_FIELD_INTERLACED,
349 	},
350 	{
351 		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
352 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
353 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU,
354 		.fmt_type = RKCIF_FMT_TYPE_YUV,
355 		.field = V4L2_FIELD_NONE,
356 	},
357 	{
358 		.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
359 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
360 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU,
361 		.fmt_type = RKCIF_FMT_TYPE_YUV,
362 		.field = V4L2_FIELD_INTERLACED,
363 	},
364 	{
365 		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
366 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
367 			       RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY,
368 		.fmt_type = RKCIF_FMT_TYPE_YUV,
369 		.field = V4L2_FIELD_NONE,
370 	},
371 	{
372 		.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
373 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
374 			       RKCIF_FORMAT_YUV_INPUT_ORDER_UYVY,
375 		.fmt_type = RKCIF_FMT_TYPE_YUV,
376 		.field = V4L2_FIELD_INTERLACED,
377 	},
378 	{
379 		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
380 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
381 			       RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY,
382 		.fmt_type = RKCIF_FMT_TYPE_YUV,
383 		.field = V4L2_FIELD_NONE,
384 	},
385 	{
386 		.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
387 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
388 			       RKCIF_FORMAT_YUV_INPUT_ORDER_VYUY,
389 		.fmt_type = RKCIF_FMT_TYPE_YUV,
390 		.field = V4L2_FIELD_INTERLACED,
391 	},
392 	{
393 		.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
394 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
395 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV |
396 			       RKCIF_FORMAT_INPUT_MODE_BT1120 |
397 			       RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS,
398 		.field = V4L2_FIELD_NONE,
399 	},
400 	{
401 		.mbus_code = MEDIA_BUS_FMT_YUYV8_1X16,
402 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
403 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV |
404 			       RKCIF_FORMAT_INPUT_MODE_BT1120,
405 		.field = V4L2_FIELD_INTERLACED,
406 	},
407 	{
408 		.mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
409 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
410 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU |
411 			       RKCIF_FORMAT_INPUT_MODE_BT1120 |
412 			       RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS,
413 		.field = V4L2_FIELD_NONE,
414 	},
415 	{
416 		.mbus_code = MEDIA_BUS_FMT_YVYU8_1X16,
417 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
418 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU |
419 			       RKCIF_FORMAT_INPUT_MODE_BT1120,
420 		.field = V4L2_FIELD_INTERLACED,
421 	},
422 	{
423 		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
424 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
425 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV |
426 			       RKCIF_FORMAT_INPUT_MODE_BT1120 |
427 			       RKCIF_FORMAT_BT1120_YC_SWAP |
428 			       RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS,
429 		.field = V4L2_FIELD_NONE,
430 	},
431 	{
432 		.mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
433 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
434 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YUYV |
435 			       RKCIF_FORMAT_BT1120_YC_SWAP |
436 			       RKCIF_FORMAT_INPUT_MODE_BT1120,
437 		.field = V4L2_FIELD_INTERLACED,
438 	},
439 	{
440 		.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
441 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
442 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU |
443 			       RKCIF_FORMAT_INPUT_MODE_BT1120 |
444 			       RKCIF_FORMAT_BT1120_YC_SWAP |
445 			       RKCIF_FORMAT_BT1120_TRANSMIT_PROGRESS,
446 		.field = V4L2_FIELD_NONE,
447 	},
448 	{
449 		.mbus_code = MEDIA_BUS_FMT_VYUY8_1X16,
450 		.dvp_fmt_val = RKCIF_FORMAT_YUV_INPUT_422 |
451 			       RKCIF_FORMAT_YUV_INPUT_ORDER_YVYU |
452 			       RKCIF_FORMAT_BT1120_YC_SWAP |
453 			       RKCIF_FORMAT_INPUT_MODE_BT1120,
454 		.field = V4L2_FIELD_INTERLACED,
455 	},
456 	{
457 		.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
458 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
459 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
460 		.fmt_type = RKCIF_FMT_TYPE_RAW,
461 		.field = V4L2_FIELD_NONE,
462 	},
463 	{
464 		.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
465 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
466 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
467 		.fmt_type = RKCIF_FMT_TYPE_RAW,
468 		.field = V4L2_FIELD_NONE,
469 	},
470 	{
471 		.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
472 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
473 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
474 		.fmt_type = RKCIF_FMT_TYPE_RAW,
475 		.field = V4L2_FIELD_NONE,
476 	},
477 	{
478 		.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
479 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
480 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
481 		.fmt_type = RKCIF_FMT_TYPE_RAW,
482 		.field = V4L2_FIELD_NONE,
483 	},
484 	{
485 		.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
486 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
487 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
488 		.fmt_type = RKCIF_FMT_TYPE_RAW,
489 		.field = V4L2_FIELD_NONE,
490 	},
491 	{
492 		.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
493 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
494 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
495 		.fmt_type = RKCIF_FMT_TYPE_RAW,
496 		.field = V4L2_FIELD_NONE,
497 	},
498 	{
499 		.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
500 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
501 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
502 		.fmt_type = RKCIF_FMT_TYPE_RAW,
503 		.field = V4L2_FIELD_NONE,
504 	},
505 	{
506 		.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
507 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
508 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
509 		.fmt_type = RKCIF_FMT_TYPE_RAW,
510 		.field = V4L2_FIELD_NONE,
511 	},
512 	{
513 		.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
514 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
515 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
516 		.fmt_type = RKCIF_FMT_TYPE_RAW,
517 		.field = V4L2_FIELD_NONE,
518 	},
519 	{
520 		.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
521 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
522 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
523 		.fmt_type = RKCIF_FMT_TYPE_RAW,
524 		.field = V4L2_FIELD_NONE,
525 	},
526 	{
527 		.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
528 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
529 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
530 		.fmt_type = RKCIF_FMT_TYPE_RAW,
531 		.field = V4L2_FIELD_NONE,
532 	},
533 	{
534 		.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
535 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
536 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
537 		.fmt_type = RKCIF_FMT_TYPE_RAW,
538 		.field = V4L2_FIELD_NONE,
539 	},
540 	{
541 		.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
542 		.field = V4L2_FIELD_NONE,
543 	},
544 	{
545 		.mbus_code = MEDIA_BUS_FMT_Y8_1X8,
546 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
547 			       RKCIF_FORMAT_RAW_DATA_WIDTH_8,
548 		.fmt_type = RKCIF_FMT_TYPE_RAW,
549 		.field = V4L2_FIELD_NONE,
550 	},
551 	{
552 		.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
553 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
554 			       RKCIF_FORMAT_RAW_DATA_WIDTH_10,
555 		.fmt_type = RKCIF_FMT_TYPE_RAW,
556 		.field = V4L2_FIELD_NONE,
557 	},
558 	{
559 		.mbus_code = MEDIA_BUS_FMT_Y12_1X12,
560 		.dvp_fmt_val = RKCIF_FORMAT_INPUT_MODE_RAW |
561 			       RKCIF_FORMAT_RAW_DATA_WIDTH_12,
562 		.fmt_type = RKCIF_FMT_TYPE_RAW,
563 		.field = V4L2_FIELD_NONE,
564 	},
565 };
566 
567 static void rk3568_dvp_grf_setup(struct rkcif_device *rkcif)
568 {
569 	u32 con1 = RK3568_GRF_WRITE_ENABLE(RK3568_GRF_VI_CON1_CIF_DATAPATH |
570 					   RK3568_GRF_VI_CON1_CIF_CLK_DELAYNUM);
571 
572 	if (!rkcif->grf)
573 		return;
574 
575 	con1 |= rkcif->interfaces[RKCIF_DVP].dvp.dvp_clk_delay &
576 		RK3568_GRF_VI_CON1_CIF_CLK_DELAYNUM;
577 
578 	if (rkcif->interfaces[RKCIF_DVP].vep.bus.parallel.flags &
579 	    V4L2_MBUS_PCLK_SAMPLE_DUALEDGE)
580 		con1 |= RK3568_GRF_VI_CON1_CIF_DATAPATH;
581 
582 	regmap_write(rkcif->grf, RK3568_GRF_VI_CON1, con1);
583 }
584 
585 const struct rkcif_dvp_match_data rkcif_rk3568_vicap_dvp_match_data = {
586 	.in_fmts = rk3568_dvp_in_fmts,
587 	.in_fmts_num = ARRAY_SIZE(rk3568_dvp_in_fmts),
588 	.out_fmts = dvp_out_fmts,
589 	.out_fmts_num = ARRAY_SIZE(dvp_out_fmts),
590 	.setup = rk3568_dvp_grf_setup,
591 	.has_scaler = false,
592 	.regs = {
593 		[RKCIF_DVP_CTRL] = 0x00,
594 		[RKCIF_DVP_INTEN] = 0x04,
595 		[RKCIF_DVP_INTSTAT] = 0x08,
596 		[RKCIF_DVP_FOR] = 0x0c,
597 		[RKCIF_DVP_LINE_NUM_ADDR] = 0x2c,
598 		[RKCIF_DVP_FRM0_ADDR_Y] = 0x14,
599 		[RKCIF_DVP_FRM0_ADDR_UV] = 0x18,
600 		[RKCIF_DVP_FRM1_ADDR_Y] = 0x1c,
601 		[RKCIF_DVP_FRM1_ADDR_UV] = 0x20,
602 		[RKCIF_DVP_VIR_LINE_WIDTH] = 0x24,
603 		[RKCIF_DVP_SET_SIZE] = 0x28,
604 		[RKCIF_DVP_CROP] = 0x34,
605 		[RKCIF_DVP_FRAME_STATUS] = 0x3c,
606 		[RKCIF_DVP_LAST_LINE] = 0x44,
607 		[RKCIF_DVP_LAST_PIX] = 0x48,
608 	},
609 };
610 
611 static inline unsigned int rkcif_dvp_get_addr(struct rkcif_device *rkcif,
612 					      unsigned int index)
613 {
614 	if (WARN_ON_ONCE(index >= RKCIF_DVP_REGISTER_MAX))
615 		return RKCIF_REGISTER_NOTSUPPORTED;
616 
617 	return rkcif->match_data->dvp->regs[index];
618 }
619 
620 static inline __maybe_unused void rkcif_dvp_write(struct rkcif_device *rkcif,
621 						  unsigned int index, u32 val)
622 {
623 	unsigned int addr = rkcif_dvp_get_addr(rkcif, index);
624 
625 	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
626 		return;
627 
628 	writel(val, rkcif->base_addr + addr);
629 }
630 
631 static inline __maybe_unused u32 rkcif_dvp_read(struct rkcif_device *rkcif,
632 						unsigned int index)
633 {
634 	unsigned int addr = rkcif_dvp_get_addr(rkcif, index);
635 
636 	if (addr == RKCIF_REGISTER_NOTSUPPORTED)
637 		return 0;
638 
639 	return readl(rkcif->base_addr + addr);
640 }
641 
642 static void rkcif_dvp_queue_buffer(struct rkcif_stream *stream,
643 				   unsigned int index)
644 {
645 	struct rkcif_device *rkcif = stream->rkcif;
646 	struct rkcif_buffer *buffer = stream->buffers[index];
647 	u32 frm_addr_y, frm_addr_uv;
648 
649 	frm_addr_y = index ? RKCIF_DVP_FRM1_ADDR_Y : RKCIF_DVP_FRM0_ADDR_Y;
650 	frm_addr_uv = index ? RKCIF_DVP_FRM1_ADDR_UV : RKCIF_DVP_FRM0_ADDR_UV;
651 
652 	rkcif_dvp_write(rkcif, frm_addr_y, buffer->buff_addr[RKCIF_PLANE_Y]);
653 	rkcif_dvp_write(rkcif, frm_addr_uv, buffer->buff_addr[RKCIF_PLANE_UV]);
654 }
655 
656 static int rkcif_dvp_start_streaming(struct rkcif_stream *stream)
657 {
658 	struct rkcif_device *rkcif = stream->rkcif;
659 	struct rkcif_interface *interface = stream->interface;
660 	struct v4l2_mbus_config_parallel *parallel;
661 	struct v4l2_mbus_framefmt *source_fmt;
662 	struct v4l2_subdev_state *state;
663 	const struct rkcif_input_fmt *active_in_fmt;
664 	const struct rkcif_output_fmt *active_out_fmt;
665 	u32 val = 0;
666 	int ret = -EINVAL;
667 
668 	state = v4l2_subdev_lock_and_get_active_state(&interface->sd);
669 	source_fmt = v4l2_subdev_state_get_format(state, RKCIF_IF_PAD_SRC,
670 						  stream->id);
671 	if (!source_fmt)
672 		goto out;
673 
674 	active_in_fmt = rkcif_interface_find_input_fmt(interface, false,
675 						       source_fmt->code);
676 	active_out_fmt = rkcif_stream_find_output_fmt(stream, false,
677 						      stream->pix.pixelformat);
678 	if (!active_in_fmt || !active_out_fmt)
679 		goto out;
680 
681 	parallel = &interface->vep.bus.parallel;
682 	if (parallel->bus_width == 16 &&
683 	    (parallel->flags & V4L2_MBUS_PCLK_SAMPLE_DUALEDGE))
684 		val |= RKCIF_FORMAT_BT1120_CLOCK_DOUBLE_EDGES;
685 	val |= active_in_fmt->dvp_fmt_val;
686 	val |= active_out_fmt->dvp_fmt_val;
687 	rkcif_dvp_write(rkcif, RKCIF_DVP_FOR, val);
688 
689 	val = stream->pix.width;
690 	if (active_in_fmt->fmt_type == RKCIF_FMT_TYPE_RAW)
691 		val = stream->pix.width * 2;
692 	rkcif_dvp_write(rkcif, RKCIF_DVP_VIR_LINE_WIDTH, val);
693 
694 	val = RKCIF_XY_COORD(stream->pix.width, stream->pix.height);
695 	rkcif_dvp_write(rkcif, RKCIF_DVP_SET_SIZE, val);
696 
697 	rkcif_dvp_write(rkcif, RKCIF_DVP_FRAME_STATUS, RKCIF_FRAME_STAT_CLS);
698 	rkcif_dvp_write(rkcif, RKCIF_DVP_INTSTAT, RKCIF_INTSTAT_CLS);
699 	if (rkcif->match_data->dvp->has_scaler) {
700 		val = active_in_fmt->fmt_type == RKCIF_FMT_TYPE_YUV ?
701 			      RKCIF_SCL_CTRL_ENABLE_YUV_16BIT_BYPASS :
702 			      RKCIF_SCL_CTRL_ENABLE_RAW_16BIT_BYPASS;
703 		rkcif_dvp_write(rkcif, RKCIF_DVP_SCL_CTRL, val);
704 	}
705 
706 	rkcif_dvp_write(rkcif, RKCIF_DVP_INTEN,
707 			RKCIF_INTEN_FRAME_END_EN |
708 			RKCIF_INTEN_PST_INF_FRAME_END_EN);
709 
710 	rkcif_dvp_write(rkcif, RKCIF_DVP_CTRL,
711 			RKCIF_CTRL_AXI_BURST_16 | RKCIF_CTRL_MODE_PINGPONG |
712 			RKCIF_CTRL_ENABLE_CAPTURE);
713 
714 	ret = 0;
715 
716 out:
717 	v4l2_subdev_unlock_state(state);
718 	return ret;
719 }
720 
721 static void rkcif_dvp_stop_streaming(struct rkcif_stream *stream)
722 {
723 	struct rkcif_device *rkcif = stream->rkcif;
724 	u32 val;
725 
726 	val = rkcif_dvp_read(rkcif, RKCIF_DVP_CTRL);
727 	rkcif_dvp_write(rkcif, RKCIF_DVP_CTRL,
728 			val & (~RKCIF_CTRL_ENABLE_CAPTURE));
729 	rkcif_dvp_write(rkcif, RKCIF_DVP_INTEN, 0x0);
730 	rkcif_dvp_write(rkcif, RKCIF_DVP_INTSTAT, 0x3ff);
731 	rkcif_dvp_write(rkcif, RKCIF_DVP_FRAME_STATUS, 0x0);
732 
733 	stream->stopping = false;
734 }
735 
736 static void rkcif_dvp_reset_stream(struct rkcif_device *rkcif)
737 {
738 	u32 ctl = rkcif_dvp_read(rkcif, RKCIF_DVP_CTRL);
739 
740 	rkcif_dvp_write(rkcif, RKCIF_DVP_CTRL,
741 			ctl & (~RKCIF_CTRL_ENABLE_CAPTURE));
742 	rkcif_dvp_write(rkcif, RKCIF_DVP_CTRL, ctl | RKCIF_CTRL_ENABLE_CAPTURE);
743 }
744 
745 static void rkcif_dvp_set_crop(struct rkcif_stream *stream, u16 left, u16 top)
746 {
747 	struct rkcif_device *rkcif = stream->rkcif;
748 	u32 val;
749 
750 	val = RKCIF_XY_COORD(left, top);
751 	rkcif_dvp_write(rkcif, RKCIF_DVP_CROP, val);
752 }
753 
754 irqreturn_t rkcif_dvp_isr(int irq, void *ctx)
755 {
756 	struct device *dev = ctx;
757 	struct rkcif_device *rkcif = dev_get_drvdata(dev);
758 	struct rkcif_stream *stream;
759 	u32 intstat, lastline, lastpix, cif_frmst;
760 	irqreturn_t ret = IRQ_NONE;
761 
762 	if (!rkcif->match_data->dvp)
763 		return ret;
764 
765 	intstat = rkcif_dvp_read(rkcif, RKCIF_DVP_INTSTAT);
766 	cif_frmst = rkcif_dvp_read(rkcif, RKCIF_DVP_FRAME_STATUS);
767 	lastline = RKCIF_FETCH_Y(rkcif_dvp_read(rkcif, RKCIF_DVP_LAST_LINE));
768 	lastpix = RKCIF_FETCH_Y(rkcif_dvp_read(rkcif, RKCIF_DVP_LAST_PIX));
769 
770 	if (intstat & RKCIF_INTSTAT_FRAME_END) {
771 		rkcif_dvp_write(rkcif, RKCIF_DVP_INTSTAT,
772 				RKCIF_INTSTAT_FRAME_END_CLR |
773 				RKCIF_INTSTAT_LINE_END_CLR);
774 
775 		stream = &rkcif->interfaces[RKCIF_DVP].streams[RKCIF_ID0];
776 
777 		if (stream->stopping) {
778 			rkcif_dvp_stop_streaming(stream);
779 			wake_up(&stream->wq_stopped);
780 			ret = IRQ_HANDLED;
781 			goto out;
782 		}
783 
784 		if (lastline != stream->pix.height) {
785 			v4l2_err(&rkcif->v4l2_dev,
786 				 "bad frame, irq:%#x frmst:%#x size:%dx%d\n",
787 				 intstat, cif_frmst, lastpix, lastline);
788 
789 			rkcif_dvp_reset_stream(rkcif);
790 		}
791 
792 		rkcif_stream_pingpong(stream);
793 
794 		ret = IRQ_HANDLED;
795 	}
796 out:
797 	return ret;
798 }
799 
800 int rkcif_dvp_register(struct rkcif_device *rkcif)
801 {
802 	struct rkcif_interface *interface;
803 	unsigned int streams_num;
804 	int ret;
805 
806 	if (!rkcif->match_data->dvp)
807 		return 0;
808 
809 	interface = &rkcif->interfaces[RKCIF_DVP];
810 	interface->index = RKCIF_DVP;
811 	interface->type = RKCIF_IF_DVP;
812 	interface->in_fmts = rkcif->match_data->dvp->in_fmts;
813 	interface->in_fmts_num = rkcif->match_data->dvp->in_fmts_num;
814 	interface->set_crop = rkcif_dvp_set_crop;
815 	ret = rkcif_interface_register(rkcif, interface);
816 	if (ret)
817 		return ret;
818 
819 	if (rkcif->match_data->dvp->setup)
820 		rkcif->match_data->dvp->setup(rkcif);
821 
822 	streams_num = rkcif->match_data->dvp->has_ids ? 4 : 1;
823 	for (unsigned int i = 0; i < streams_num; i++) {
824 		struct rkcif_stream *stream = &interface->streams[i];
825 
826 		stream->id = i;
827 		stream->interface = interface;
828 		stream->out_fmts = rkcif->match_data->dvp->out_fmts;
829 		stream->out_fmts_num = rkcif->match_data->dvp->out_fmts_num;
830 		stream->queue_buffer = rkcif_dvp_queue_buffer;
831 		stream->start_streaming = rkcif_dvp_start_streaming;
832 		stream->stop_streaming = rkcif_dvp_stop_streaming;
833 
834 		ret = rkcif_stream_register(rkcif, stream);
835 		if (ret)
836 			goto err_streams_unregister;
837 
838 		interface->streams_num++;
839 	}
840 
841 	return 0;
842 
843 err_streams_unregister:
844 	for (unsigned int i = 0; i < interface->streams_num; i++)
845 		rkcif_stream_unregister(&interface->streams[i]);
846 
847 	rkcif_interface_unregister(interface);
848 
849 	return ret;
850 }
851 
852 void rkcif_dvp_unregister(struct rkcif_device *rkcif)
853 {
854 	struct rkcif_interface *interface;
855 
856 	if (!rkcif->match_data->dvp)
857 		return;
858 
859 	interface = &rkcif->interfaces[RKCIF_DVP];
860 
861 	for (unsigned int i = 0; i < interface->streams_num; i++)
862 		rkcif_stream_unregister(&interface->streams[i]);
863 
864 	rkcif_interface_unregister(interface);
865 }
866