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
rk3568_dvp_grf_setup(struct rkcif_device * rkcif)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
rkcif_dvp_get_addr(struct rkcif_device * rkcif,unsigned int index)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
rkcif_dvp_write(struct rkcif_device * rkcif,unsigned int index,u32 val)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
rkcif_dvp_read(struct rkcif_device * rkcif,unsigned int index)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
rkcif_dvp_queue_buffer(struct rkcif_stream * stream,unsigned int index)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
rkcif_dvp_start_streaming(struct rkcif_stream * stream)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
rkcif_dvp_stop_streaming(struct rkcif_stream * stream)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
rkcif_dvp_reset_stream(struct rkcif_device * rkcif)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
rkcif_dvp_set_crop(struct rkcif_stream * stream,u16 left,u16 top)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
rkcif_dvp_isr(int irq,void * ctx)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
rkcif_dvp_register(struct rkcif_device * rkcif)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
rkcif_dvp_unregister(struct rkcif_device * rkcif)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