File Index
Files and directories
Sign in
FILE

rkcif-capture-dvp.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/platform/rockchip/rkcif/rkcif-capture-dvp.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) 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
 23static 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
142static 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
310const 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
335static 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
567static 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
585const 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
611static 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
620static 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
631static 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
642static 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
656static 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
716out:
717	v4l2_subdev_unlock_state(state);
718	return ret;
719}
720
721static 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
736static 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
745static 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
754irqreturn_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	}
796out:
797	return ret;
798}
799
800int 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
843err_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
852void 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}
~/ Read-only file preview.