• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * vin_core.c for video manage
3  *
4  * Copyright (c) 2017 by Allwinnertech Co., Ltd.  http://www.allwinnertech.com
5  *
6  * Authors:  Zhao Wei <zhaowei@allwinnertech.com>
7  *	Yang Feng <yangfeng@allwinnertech.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13 
14 #include <linux/module.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/init.h>
18 #include <linux/sched.h>
19 #include <linux/slab.h>
20 #include <linux/version.h>
21 #include <linux/mutex.h>
22 #include <linux/videodev2.h>
23 #include <linux/delay.h>
24 #include <linux/string.h>
25 #include <linux/freezer.h>
26 #include <linux/debugfs.h>
27 //#include <linux/mpp.h>
28 
29 #include <linux/io.h>
30 #include <linux/platform_device.h>
31 #include <linux/interrupt.h>
32 #include <linux/i2c.h>
33 #include <linux/moduleparam.h>
34 #include <media/v4l2-device.h>
35 #include <media/v4l2-ioctl.h>
36 #include <media/v4l2-common.h>
37 #include <media/v4l2-mediabus.h>
38 #include <media/v4l2-subdev.h>
39 #include <media/videobuf2-dma-contig.h>
40 
41 #include <linux/regulator/consumer.h>
42 
43 #include "vin_core.h"
44 #include "../vin-cci/cci_helper.h"
45 #include "../utility/config.h"
46 #include "../modules/sensor/camera_cfg.h"
47 #include "../modules/sensor/sensor_helper.h"
48 #include "../utility/vin_io.h"
49 #include "../vin-csi/sunxi_csi.h"
50 #include "../vin-isp/sunxi_isp.h"
51 #include "../vin-vipp/sunxi_scaler.h"
52 #include "../vin-mipi/sunxi_mipi.h"
53 #include "../vin.h"
54 #include "dma_reg.h"
55 
56 #define VIN_CORE_NAME "sunxi-vin-core"
57 
58 struct vin_core *vin_core_gbl[VIN_MAX_DEV];
59 
60 #define VIN_DEBUGFS_BUF_SIZE 768
61 struct vin_debugfs_buffer {
62 	size_t count;
63 	char data[VIN_DEBUGFS_BUF_SIZE*VIN_MAX_DEV];
64 };
65 struct dentry *vi_debugfs_root, *vi_node;
66 size_t vi_status_size[VIN_MAX_DEV];
67 size_t vi_status_size_sum;
68 
69 uint ptn_frame_cnt;
70 
71 #define DEVICE_ATTR_SHOW(name) \
72 static ssize_t name##_show(struct device *dev, \
73 			struct device_attribute *attr, \
74 			char *buf) \
75 {\
76 	return sprintf(buf, "%u\n", name); \
77 }
78 
79 #define DEVICE_ATTR_STORE(name) \
80 static ssize_t name##_store(struct device *dev, \
81 			struct device_attribute *attr, \
82 			const char *buf,\
83 			size_t count) \
84 {\
85 	unsigned long val;\
86 	val = simple_strtoul(buf, NULL, 16);\
87 	name = val;\
88 	vin_print("Set val = 0x%lx\n", val);\
89 	return count;\
90 }
91 
92 DEVICE_ATTR_SHOW(vin_log_mask)
93 DEVICE_ATTR_STORE(vin_log_mask)
94 
95 static DEVICE_ATTR(vin_log_mask, S_IRUGO | S_IWUSR | S_IWGRP,
96 		   vin_log_mask_show, vin_log_mask_store);
97 
98 static struct attribute *vin_attributes[] = {
99 	&dev_attr_vin_log_mask.attr,
100 	NULL
101 };
102 
103 static struct attribute_group vin_attribute_group = {
104 	/*.name = "vin_attrs",*/
105 	.attrs = vin_attributes,
106 };
107 
108 static struct vin_fmt vin_formats[] = {
109 	{
110 		.name		= "RGB565",
111 		.fourcc		= V4L2_PIX_FMT_RGB565,
112 		.depth		= { 16 },
113 		.color		= V4L2_COLORSPACE_SRGB,
114 		.memplanes	= 1,
115 		.colplanes	= 1,
116 		.flags		= VIN_FMT_RGB,
117 	}, {
118 		.name		= "ARGB1555, 16 bpp",
119 		.fourcc		= V4L2_PIX_FMT_RGB555,
120 		.depth		= { 16 },
121 		.color		= V4L2_COLORSPACE_SRGB,
122 		.memplanes	= 1,
123 		.colplanes	= 1,
124 		.flags		= VIN_FMT_RGB | VIN_FMT_OSD,
125 	}, {
126 		.name		= "ARGB4444, 16 bpp",
127 		.fourcc		= V4L2_PIX_FMT_RGB444,
128 		.depth		= { 16 },
129 		.color		= V4L2_COLORSPACE_SRGB,
130 		.memplanes	= 1,
131 		.colplanes	= 1,
132 		.flags		= VIN_FMT_RGB | VIN_FMT_OSD,
133 	}, {
134 		.name		= "ARGB8888, 32 bpp",
135 		.fourcc		= V4L2_PIX_FMT_RGB32,
136 		.depth		= { 32 },
137 		.color		= V4L2_COLORSPACE_SRGB,
138 		.memplanes	= 1,
139 		.colplanes	= 1,
140 		.flags		= VIN_FMT_RGB | VIN_FMT_OSD,
141 	}, {
142 		.name		= "YUV 4:2:2 planar, Y/Cb/Cr",
143 		.fourcc		= V4L2_PIX_FMT_YUV422P,
144 		.depth		= { 16 },
145 		.color		= V4L2_COLORSPACE_JPEG,
146 		.memplanes	= 1,
147 		.colplanes	= 3,
148 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
149 	}, {
150 		.name		= "YUV 4:2:2 planar, Y/CbCr",
151 		.fourcc		= V4L2_PIX_FMT_NV16,
152 		.depth		= { 16 },
153 		.color		= V4L2_COLORSPACE_JPEG,
154 		.memplanes	= 1,
155 		.colplanes	= 2,
156 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
157 	}, {
158 		.name		= "YUV 4:2:2 planar, Y/CbCr",
159 		.fourcc		= V4L2_PIX_FMT_NV16M,
160 		.depth		= { 8, 8 },
161 		.color		= V4L2_COLORSPACE_JPEG,
162 		.memplanes	= 2,
163 		.colplanes	= 2,
164 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
165 	}, {
166 		.name		= "YUV 4:2:2 planar, Y/CrCb",
167 		.fourcc		= V4L2_PIX_FMT_NV61,
168 		.depth		= { 16 },
169 		.color		= V4L2_COLORSPACE_JPEG,
170 		.memplanes	= 1,
171 		.colplanes	= 2,
172 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
173 	}, {
174 		.name		= "YUV 4:2:2 planar, Y/CrCb",
175 		.fourcc		= V4L2_PIX_FMT_NV61M,
176 		.depth		= { 8, 8 },
177 		.color		= V4L2_COLORSPACE_JPEG,
178 		.memplanes	= 2,
179 		.colplanes	= 2,
180 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
181 	}, {
182 		.name		= "YUV 4:2:0 planar, YCbCr",
183 		.fourcc		= V4L2_PIX_FMT_YUV420,
184 		.depth		= { 12 },
185 		.color		= V4L2_COLORSPACE_JPEG,
186 		.memplanes	= 1,
187 		.colplanes	= 3,
188 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
189 	}, {
190 		.name		= "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr",
191 		.fourcc		= V4L2_PIX_FMT_YUV420M,
192 		.color		= V4L2_COLORSPACE_JPEG,
193 		.depth		= { 8, 2, 2 },
194 		.memplanes	= 3,
195 		.colplanes	= 3,
196 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
197 	}, {
198 		.name		= "YUV 4:2:0 planar, YCrCb",
199 		.fourcc		= V4L2_PIX_FMT_YVU420,
200 		.depth		= { 12 },
201 		.color		= V4L2_COLORSPACE_JPEG,
202 		.memplanes	= 1,
203 		.colplanes	= 3,
204 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
205 	}, {
206 		.name		= "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb",
207 		.fourcc		= V4L2_PIX_FMT_YVU420M,
208 		.color		= V4L2_COLORSPACE_JPEG,
209 		.depth		= { 8, 2, 2 },
210 		.memplanes	= 3,
211 		.colplanes	= 3,
212 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
213 	}, {
214 		.name		= "YUV 4:2:0 planar, Y/CbCr",
215 		.fourcc		= V4L2_PIX_FMT_NV12,
216 		.depth		= { 12 },
217 		.color		= V4L2_COLORSPACE_JPEG,
218 		.memplanes	= 1,
219 		.colplanes	= 2,
220 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
221 	}, {
222 		.name		= "YUV 4:2:0 non-contig. 2p, Y/CbCr",
223 		.fourcc		= V4L2_PIX_FMT_NV12M,
224 		.color		= V4L2_COLORSPACE_JPEG,
225 		.depth		= { 8, 4 },
226 		.memplanes	= 2,
227 		.colplanes	= 2,
228 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
229 	}, {
230 		.name		= "YUV 4:2:0 planar, Y/CrCb",
231 		.fourcc		= V4L2_PIX_FMT_NV21,
232 		.depth		= { 12 },
233 		.color		= V4L2_COLORSPACE_JPEG,
234 		.memplanes	= 1,
235 		.colplanes	= 2,
236 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
237 	}, {
238 		.name		= "YUV 4:2:0 non-contig. 2p, Y/CrCb",
239 		.fourcc		= V4L2_PIX_FMT_NV21M,
240 		.color		= V4L2_COLORSPACE_JPEG,
241 		.depth		= { 8, 4 },
242 		.memplanes	= 2,
243 		.colplanes	= 2,
244 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
245 	}, {
246 		.name		= "YUV 4:2:0 non-contig. 2p, tiled",
247 		.fourcc		= V4L2_PIX_FMT_NV12MT,
248 		.color		= V4L2_COLORSPACE_JPEG,
249 		.depth		= { 8, 4 },
250 		.memplanes	= 2,
251 		.colplanes	= 2,
252 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
253 	}, {
254 		.name		= "YUV 4:0:0 planar, GREY",
255 		.fourcc		= V4L2_PIX_FMT_GREY,
256 		.depth		= { 8 },
257 		.color		= V4L2_COLORSPACE_JPEG,
258 		.memplanes	= 1,
259 		.colplanes	= 1,
260 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
261 	}, {
262 		.name		= "YUV 4:2:0 non-contig. 2p, FBC",
263 		.fourcc		= V4L2_PIX_FMT_FBC,
264 		.color		= V4L2_COLORSPACE_JPEG,
265 		.depth		= { 12 },
266 		.memplanes	= 1,
267 		.colplanes	= 2,
268 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
269 	}, {
270 		.name		= "YUV 4:2:0 non-contig. 2p, LBC_2X",
271 		.fourcc		= V4L2_PIX_FMT_LBC_2_0X,
272 		.color		= V4L2_COLORSPACE_JPEG,
273 		.depth		= { 12 },
274 		.memplanes	= 1,
275 		.colplanes	= 1,
276 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
277 	}, {
278 		.name		= "YUV 4:2:0 non-contig. 2p, LBC_2.5X",
279 		.fourcc		= V4L2_PIX_FMT_LBC_2_5X,
280 		.color		= V4L2_COLORSPACE_JPEG,
281 		.depth		= { 12 },
282 		.memplanes	= 1,
283 		.colplanes	= 1,
284 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
285 	}, {
286 		.name		= "YUV 4:2:0 non-contig. 2p, LBC_1X",
287 		.fourcc		= V4L2_PIX_FMT_LBC_1_0X,
288 		.color		= V4L2_COLORSPACE_JPEG,
289 		.depth		= { 12 },
290 		.memplanes	= 1,
291 		.colplanes	= 1,
292 		.flags		= VIN_FMT_YUV | VIN_FMT_RAW,
293 	}, {
294 		.name		= "RAW Bayer BGGR 8bit",
295 		.fourcc		= V4L2_PIX_FMT_SBGGR8,
296 		.depth		= { 8 },
297 		.memplanes	= 1,
298 		.colplanes	= 1,
299 		.mbus_code	= MEDIA_BUS_FMT_SBGGR8_1X8,
300 		.flags		= VIN_FMT_RAW,
301 	}, {
302 		.name		= "RAW Bayer GBRG 8bit",
303 		.fourcc		= V4L2_PIX_FMT_SGBRG8,
304 		.depth		= { 8 },
305 		.memplanes	= 1,
306 		.colplanes	= 1,
307 		.mbus_code	= MEDIA_BUS_FMT_SGBRG8_1X8,
308 		.flags		= VIN_FMT_RAW,
309 	}, {
310 		.name		= "RAW Bayer GRBG 8bit",
311 		.fourcc		= V4L2_PIX_FMT_SGRBG8,
312 		.depth		= { 8 },
313 		.memplanes	= 1,
314 		.colplanes	= 1,
315 		.mbus_code	= MEDIA_BUS_FMT_SGRBG8_1X8,
316 		.flags		= VIN_FMT_RAW,
317 	}, {
318 		.name		= "RAW Bayer RGGB 8bit",
319 		.fourcc		= V4L2_PIX_FMT_SRGGB8,
320 		.depth		= { 8 },
321 		.memplanes	= 1,
322 		.colplanes	= 1,
323 		.mbus_code	= MEDIA_BUS_FMT_SRGGB8_1X8,
324 		.flags		= VIN_FMT_RAW,
325 	}, {
326 		.name		= "RAW Bayer BGGR 10bit",
327 		.fourcc		= V4L2_PIX_FMT_SBGGR10,
328 		.depth		= { 16 },
329 		.memplanes	= 1,
330 		.colplanes	= 1,
331 		.mbus_code	= MEDIA_BUS_FMT_SBGGR10_1X10,
332 		.flags		= VIN_FMT_RAW,
333 	}, {
334 		.name		= "RAW Bayer GBRG 10bit",
335 		.fourcc		= V4L2_PIX_FMT_SGBRG10,
336 		.depth		= { 16 },
337 		.memplanes	= 1,
338 		.colplanes	= 1,
339 		.mbus_code	= MEDIA_BUS_FMT_SGBRG10_1X10,
340 		.flags		= VIN_FMT_RAW,
341 	}, {
342 		.name		= "RAW Bayer GRBG 10bit",
343 		.fourcc		= V4L2_PIX_FMT_SGRBG10,
344 		.depth		= { 16 },
345 		.memplanes	= 1,
346 		.colplanes	= 1,
347 		.mbus_code	= MEDIA_BUS_FMT_SGRBG10_1X10,
348 		.flags		= VIN_FMT_RAW,
349 	}, {
350 		.name		= "RAW Bayer RGGB 10bit",
351 		.fourcc		= V4L2_PIX_FMT_SRGGB10,
352 		.depth		= { 16 },
353 		.memplanes	= 1,
354 		.colplanes	= 1,
355 		.mbus_code	= MEDIA_BUS_FMT_SRGGB10_1X10,
356 		.flags		= VIN_FMT_RAW,
357 	}, {
358 		.name		= "RAW Bayer BGGR 12bit",
359 		.fourcc		= V4L2_PIX_FMT_SBGGR12,
360 		.depth		= { 16 },
361 		.memplanes	= 1,
362 		.colplanes	= 1,
363 		.mbus_code	= MEDIA_BUS_FMT_SBGGR12_1X12,
364 		.flags		= VIN_FMT_RAW,
365 	}, {
366 		.name		= "RAW Bayer GBRG 12bit",
367 		.fourcc		= V4L2_PIX_FMT_SGBRG12,
368 		.depth		= { 16 },
369 		.memplanes	= 1,
370 		.colplanes	= 1,
371 		.mbus_code	= MEDIA_BUS_FMT_SGBRG12_1X12,
372 		.flags		= VIN_FMT_RAW,
373 	}, {
374 		.name		= "RAW Bayer GRBG 12bit",
375 		.fourcc		= V4L2_PIX_FMT_SGRBG12,
376 		.depth		= { 16 },
377 		.memplanes	= 1,
378 		.colplanes	= 1,
379 		.mbus_code	= MEDIA_BUS_FMT_SGRBG12_1X12,
380 		.flags		= VIN_FMT_RAW,
381 	}, {
382 		.name		= "RAW Bayer RGGB 12bit",
383 		.fourcc		= V4L2_PIX_FMT_SRGGB12,
384 		.depth		= { 16 },
385 		.memplanes	= 1,
386 		.colplanes	= 1,
387 		.mbus_code	= MEDIA_BUS_FMT_SRGGB12_1X12,
388 		.flags		= VIN_FMT_RAW,
389 	}, {
390 		.name		= "YUV 4:2:2 packed, YCbYCr",
391 		.fourcc		= V4L2_PIX_FMT_YUYV,
392 		.depth		= { 16 },
393 		.color		= V4L2_COLORSPACE_JPEG,
394 		.memplanes	= 1,
395 		.colplanes	= 1,
396 		.mbus_code	= MEDIA_BUS_FMT_YUYV8_2X8,
397 		.flags		= VIN_FMT_YUV,
398 	}, {
399 		.name		= "YUV 4:2:2 packed, CbYCrY",
400 		.fourcc		= V4L2_PIX_FMT_UYVY,
401 		.depth		= { 16 },
402 		.color		= V4L2_COLORSPACE_JPEG,
403 		.memplanes	= 1,
404 		.colplanes	= 1,
405 		.mbus_code	= MEDIA_BUS_FMT_UYVY8_2X8,
406 		.flags		= VIN_FMT_YUV,
407 	}, {
408 		.name		= "YUV 4:2:2 packed, CrYCbY",
409 		.fourcc		= V4L2_PIX_FMT_VYUY,
410 		.depth		= { 16 },
411 		.color		= V4L2_COLORSPACE_JPEG,
412 		.memplanes	= 1,
413 		.colplanes	= 1,
414 		.mbus_code	= MEDIA_BUS_FMT_VYUY8_2X8,
415 		.flags		= VIN_FMT_YUV,
416 	}, {
417 		.name		= "YUV 4:2:2 packed, YCrYCb",
418 		.fourcc		= V4L2_PIX_FMT_YVYU,
419 		.depth		= { 16 },
420 		.color		= V4L2_COLORSPACE_JPEG,
421 		.memplanes	= 1,
422 		.colplanes	= 1,
423 		.mbus_code	= MEDIA_BUS_FMT_YVYU8_2X8,
424 		.flags		= VIN_FMT_YUV,
425 	}, {
426 		.name		= "YUV 4:2:2 packed, YCbYCr",
427 		.fourcc		= V4L2_PIX_FMT_YUYV,
428 		.depth		= { 16 },
429 		.color		= V4L2_COLORSPACE_JPEG,
430 		.memplanes	= 1,
431 		.colplanes	= 1,
432 		.mbus_code	= MEDIA_BUS_FMT_YUYV8_1X16,
433 		.flags		= VIN_FMT_YUV,
434 	}, {
435 		.name		= "YUV 4:2:2 packed, CbYCrY",
436 		.fourcc		= V4L2_PIX_FMT_UYVY,
437 		.depth		= { 16 },
438 		.color		= V4L2_COLORSPACE_JPEG,
439 		.memplanes	= 1,
440 		.colplanes	= 1,
441 		.mbus_code	= MEDIA_BUS_FMT_UYVY8_1X16,
442 		.flags		= VIN_FMT_YUV,
443 	}, {
444 		.name		= "YUV 4:2:2 packed, CrYCbY",
445 		.fourcc		= V4L2_PIX_FMT_VYUY,
446 		.depth		= { 16 },
447 		.color		= V4L2_COLORSPACE_JPEG,
448 		.memplanes	= 1,
449 		.colplanes	= 1,
450 		.mbus_code	= MEDIA_BUS_FMT_VYUY8_1X16,
451 		.flags		= VIN_FMT_YUV,
452 	}, {
453 		.name		= "YUV 4:2:2 packed, YCrYCb",
454 		.fourcc		= V4L2_PIX_FMT_YVYU,
455 		.depth		= { 16 },
456 		.color		= V4L2_COLORSPACE_JPEG,
457 		.memplanes	= 1,
458 		.colplanes	= 1,
459 		.mbus_code	= MEDIA_BUS_FMT_YVYU8_1X16,
460 		.flags		= VIN_FMT_YUV,
461 	}, {
462 		.name           = "YUV 4:2:2 packed, CbYCrY",
463 		.fourcc         = V4L2_PIX_FMT_UYVY,
464 		.depth          = { 20 },
465 		.color          = V4L2_COLORSPACE_JPEG,
466 		.memplanes      = 1,
467 		.colplanes      = 1,
468 		.mbus_code      = MEDIA_BUS_FMT_UYVY10_2X10,
469 		.flags          = VIN_FMT_YUV,
470 	}, {
471 		.name           = "YUV 4:2:2 packed, CbYCrY",
472 		.fourcc         = V4L2_PIX_FMT_VYUY,
473 		.depth          = { 20 },
474 		.color          = V4L2_COLORSPACE_JPEG,
475 		.memplanes      = 1,
476 		.colplanes      = 1,
477 		.mbus_code      = MEDIA_BUS_FMT_VYUY10_2X10,
478 		.flags          = VIN_FMT_YUV,
479 	}, {
480 		.name           = "YUV 4:2:2 packed, CbYCrY",
481 		.fourcc         = V4L2_PIX_FMT_YVYU,
482 		.depth          = { 20 },
483 		.color          = V4L2_COLORSPACE_JPEG,
484 		.memplanes      = 1,
485 		.colplanes      = 1,
486 		.mbus_code      = MEDIA_BUS_FMT_YVYU10_2X10,
487 		.flags          = VIN_FMT_YUV,
488 	}, {
489 		.name           = "YUV 4:2:2 packed, CbYCrY",
490 		.fourcc         = V4L2_PIX_FMT_YUYV,
491 		.depth          = { 20 },
492 		.color          = V4L2_COLORSPACE_JPEG,
493 		.memplanes      = 1,
494 		.colplanes      = 1,
495 		.mbus_code      = MEDIA_BUS_FMT_YUYV10_2X10,
496 		.flags          = VIN_FMT_YUV,
497 	},
498 };
499 
vin_find_format(const u32 * pixelformat,const u32 * mbus_code,unsigned int mask,int index,bool have_code)500 struct vin_fmt *vin_find_format(const u32 *pixelformat, const u32 *mbus_code,
501 				  unsigned int mask, int index, bool have_code)
502 {
503 	struct vin_fmt *fmt, *def_fmt = NULL;
504 	unsigned int i;
505 	int id = 0;
506 
507 	if (index >= (int)ARRAY_SIZE(vin_formats))
508 		return NULL;
509 
510 	for (i = 0; i < ARRAY_SIZE(vin_formats); ++i) {
511 		fmt = &vin_formats[i];
512 
513 		if (!(fmt->flags & mask))
514 			continue;
515 		if (have_code && (fmt->mbus_code == 0))
516 			continue;
517 
518 		if (pixelformat && fmt->fourcc == *pixelformat)
519 			return fmt;
520 		if (mbus_code && fmt->mbus_code == *mbus_code)
521 			return fmt;
522 		if (index == id)
523 			def_fmt = fmt;
524 		id++;
525 	}
526 	return def_fmt;
527 }
528 
vin_status_dump(struct vin_core * vinc,char * buf,size_t size)529 static size_t vin_status_dump(struct vin_core *vinc, char *buf, size_t size)
530 {
531 	struct vin_md *vind = dev_get_drvdata(vinc->v4l2_dev->dev);
532 	size_t count = 0;
533 	char out_fmt[10] = {'\0'};
534 	char in_fmt[10] = {'\0'};
535 	char in_bus[10] = {'\0'};
536 	char isp_mode[10] = {'\0'};
537 
538 	switch (vinc->vid_cap.frame.fmt.mbus_code) {
539 	case MEDIA_BUS_FMT_UYVY8_2X8:
540 	case MEDIA_BUS_FMT_UYVY8_1X16:
541 		sprintf(in_fmt, "%s", "UYVY8");
542 		break;
543 	case MEDIA_BUS_FMT_VYUY8_2X8:
544 	case MEDIA_BUS_FMT_VYUY8_1X16:
545 		sprintf(in_fmt, "%s", "VYUY8");
546 		break;
547 	case MEDIA_BUS_FMT_YUYV8_2X8:
548 	case MEDIA_BUS_FMT_YUYV8_1X16:
549 		sprintf(in_fmt, "%s", "YUYV8");
550 		break;
551 	case MEDIA_BUS_FMT_YVYU8_2X8:
552 	case MEDIA_BUS_FMT_YVYU8_1X16:
553 		sprintf(in_fmt, "%s", "YVYU8");
554 		break;
555 	case MEDIA_BUS_FMT_SBGGR8_1X8:
556 		sprintf(in_fmt, "%s", "BGGR8");
557 		break;
558 	case MEDIA_BUS_FMT_SGBRG8_1X8:
559 		sprintf(in_fmt, "%s", "GBRG8");
560 		break;
561 	case MEDIA_BUS_FMT_SGRBG8_1X8:
562 		sprintf(in_fmt, "%s", "GRBG8");
563 		break;
564 	case MEDIA_BUS_FMT_SRGGB8_1X8:
565 		sprintf(in_fmt, "%s", "RGGB8");
566 		break;
567 	case MEDIA_BUS_FMT_SBGGR10_1X10:
568 		sprintf(in_fmt, "%s", "BGGR10");
569 		break;
570 	case MEDIA_BUS_FMT_SGBRG10_1X10:
571 		sprintf(in_fmt, "%s", "GBRG10");
572 		break;
573 	case MEDIA_BUS_FMT_SGRBG10_1X10:
574 		sprintf(in_fmt, "%s", "GRBG10");
575 		break;
576 	case MEDIA_BUS_FMT_SRGGB10_1X10:
577 		sprintf(in_fmt, "%s", "RGGB10");
578 		break;
579 	case MEDIA_BUS_FMT_SBGGR12_1X12:
580 		sprintf(in_fmt, "%s", "BGGR12");
581 		break;
582 	case MEDIA_BUS_FMT_SGBRG12_1X12:
583 		sprintf(in_fmt, "%s", "GBRG12");
584 		break;
585 	case MEDIA_BUS_FMT_SGRBG12_1X12:
586 		sprintf(in_fmt, "%s", "GRBG12");
587 		break;
588 	case MEDIA_BUS_FMT_SRGGB12_1X12:
589 		sprintf(in_fmt, "%s", "RGGB12");
590 		break;
591 	default:
592 		sprintf(in_fmt, "%s", "NULL");
593 		break;
594 	}
595 
596 	switch (vinc->vid_cap.frame.fmt.fourcc) {
597 	case V4L2_PIX_FMT_YUV420:
598 		sprintf(out_fmt, "%s", "YUV420");
599 		break;
600 	case V4L2_PIX_FMT_YUV420M:
601 		sprintf(out_fmt, "%s", "YUV420M");
602 		break;
603 	case V4L2_PIX_FMT_YVU420:
604 		sprintf(out_fmt, "%s", "YVU420");
605 		break;
606 	case V4L2_PIX_FMT_YVU420M:
607 		sprintf(out_fmt, "%s", "YVU420M");
608 		break;
609 	case V4L2_PIX_FMT_NV21:
610 		sprintf(out_fmt, "%s", "NV21");
611 		break;
612 	case V4L2_PIX_FMT_NV21M:
613 		sprintf(out_fmt, "%s", "NV21M");
614 		break;
615 	case V4L2_PIX_FMT_NV12:
616 		sprintf(out_fmt, "%s", "NV12");
617 		break;
618 	case V4L2_PIX_FMT_NV12M:
619 		sprintf(out_fmt, "%s", "NV12M");
620 		break;
621 	case V4L2_PIX_FMT_NV16:
622 		sprintf(out_fmt, "%s", "NV16");
623 		break;
624 	case V4L2_PIX_FMT_NV61:
625 		sprintf(out_fmt, "%s", "NV61");
626 		break;
627 	case V4L2_PIX_FMT_FBC:
628 		sprintf(out_fmt, "%s", "FBC");
629 		break;
630 	case V4L2_PIX_FMT_LBC_2_0X:
631 		sprintf(out_fmt, "%s", "LBC_2X");
632 		break;
633 	case V4L2_PIX_FMT_LBC_2_5X:
634 		sprintf(out_fmt, "%s", "LBC_2.5X");
635 		break;
636 	case V4L2_PIX_FMT_LBC_1_0X:
637 		sprintf(out_fmt, "%s", "LBC_1X");
638 		break;
639 	default:
640 		sprintf(out_fmt, "%s", "NULL");
641 		break;
642 	}
643 
644 	switch (vinc->vid_cap.frame.fmt.mbus_type) {
645 	case V4L2_MBUS_PARALLEL:
646 		sprintf(in_bus, "%s", "PARALLEL");
647 		break;
648 	case V4L2_MBUS_BT656:
649 		sprintf(in_bus, "%s", "BT656");
650 		break;
651 	case V4L2_MBUS_CSI2_DPHY:
652 		sprintf(in_bus, "%s", "MIPI");
653 		break;
654 	case V4L2_MBUS_SUBLVDS:
655 		sprintf(in_bus, "%s", "SUBLVDS");
656 		break;
657 	case V4L2_MBUS_HISPI:
658 		sprintf(in_bus, "%s", "HISPI");
659 		break;
660 	default:
661 		sprintf(in_bus, "%s", "NULL");
662 		break;
663 	}
664 
665 	switch (vinc->vid_cap.isp_wdr_mode) {
666 	case ISP_NORMAL_MODE:
667 		sprintf(isp_mode, "%s", "NORMAL");
668 		break;
669 	case ISP_DOL_WDR_MODE:
670 		sprintf(isp_mode, "%s", "DOL_WDR");
671 		break;
672 	case ISP_COMANDING_MODE:
673 		sprintf(isp_mode, "%s", "CMD_WDR");
674 		break;
675 	case ISP_SEHDR_MODE:
676 		sprintf(isp_mode, "%s", "SEHDR");
677 		break;
678 	default:
679 		sprintf(isp_mode, "%s", "NULL");
680 		break;
681 	}
682 
683 	if (vinc->id == 0) {
684 		count += scnprintf(buf + count, size - count, "*****************************************************\n");
685 		count += scnprintf(buf + count, size - count, "VIN hardware feature list:\n"
686 				"mcsi %d, ncsi %d, parser %d, isp %d, vipp %d, dma %d\n"
687 				"CSI_VERSION: CSI%x_%x, ISP_VERSION: ISP%x_%x\n"
688 				"CSI_TOP: %ld, CSI_ISP: %ld\n",
689 				vind->csic_fl.mcsi_num,	vind->csic_fl.ncsi_num,
690 				vind->csic_fl.parser_num, vind->csic_fl.isp_num,
691 				vind->csic_fl.vipp_num,	vind->csic_fl.dma_num,
692 				vind->csic_ver.ver_big,	vind->csic_ver.ver_small,
693 				vind->isp_ver_major, vind->isp_ver_minor,
694 				clk_get_rate(vind->clk[VIN_TOP_CLK].clock),
695 				clk_get_rate(vind->isp_clk[VIN_ISP_CLK].clock));
696 		vind->csi_bd_tatol = 0;
697 		count += scnprintf(buf + count, size - count, "*****************************************************\n");
698 	}
699 
700 	if (vinc->mipi_sel == 0xff) {
701 #ifdef SUPPORT_ISP_TDM
702 		if (vinc->tdm_rx_sel == 0xff) {
703 			count += scnprintf(buf + count, size - count, "vi%u:\n%s => csi%d => isp%d => vipp%d\n",
704 				vinc->id, vinc->vid_cap.pipe.sd[VIN_IND_SENSOR]->name,
705 				vinc->csi_sel, vinc->isp_sel, vinc->vipp_sel);
706 		} else {
707 			count += scnprintf(buf + count, size - count, "vi%u:\n%s => csi%d => tdm_rx%d => isp%d => vipp%d\n",
708 				vinc->id, vinc->vid_cap.pipe.sd[VIN_IND_SENSOR]->name,
709 				vinc->csi_sel, vinc->tdm_rx_sel, vinc->isp_sel, vinc->vipp_sel);
710 		}
711 #else
712 	count += scnprintf(buf + count, size - count, "vi%u:\n%s => csi%d => isp%d => vipp%d\n",
713 			vinc->id, vinc->vid_cap.pipe.sd[VIN_IND_SENSOR]->name,
714 			vinc->csi_sel, vinc->isp_sel, vinc->vipp_sel);
715 #endif
716 	} else {
717 #ifdef SUPPORT_ISP_TDM
718 		if (vinc->tdm_rx_sel == 0xff) {
719 			count += scnprintf(buf + count, size - count, "vi%u:\n%s => mipi%d => csi%d => isp%d => vipp%d\n",
720 				vinc->id, vinc->vid_cap.pipe.sd[VIN_IND_SENSOR]->name,
721 				vinc->mipi_sel, vinc->csi_sel, vinc->isp_sel, vinc->vipp_sel);
722 		} else {
723 			count += scnprintf(buf + count, size - count, "vi%u:\n%s => mipi%d => csi%d => tdm_rx%d => isp%d => vipp%d\n",
724 				vinc->id, vinc->vid_cap.pipe.sd[VIN_IND_SENSOR]->name,
725 				vinc->mipi_sel, vinc->csi_sel, vinc->tdm_rx_sel, vinc->isp_sel, vinc->vipp_sel);
726 		}
727 #else
728 	count += scnprintf(buf + count, size - count, "vi%u:\n%s => mipi%d => csi%d => isp%d => vipp%d\n",
729 			vinc->id, vinc->vid_cap.pipe.sd[VIN_IND_SENSOR]->name,
730 			vinc->mipi_sel, vinc->csi_sel, vinc->isp_sel, vinc->vipp_sel);
731 #endif
732 
733 	}
734 
735 	count += scnprintf(buf + count, size - count,
736 			   "input => hoff: %u, voff: %u, w: %u, h: %u, fmt: %s\n"
737 			   "output => width: %u, height: %u, fmt: %s\n"
738 			   "interface: %s, isp_mode: %s, hflip: %u, vflip: %u\n",
739 			   vinc->vin_status.h_off, vinc->vin_status.v_off,
740 			   vinc->vin_status.width, vinc->vin_status.height, in_fmt,
741 			   vinc->vid_cap.frame.o_width, vinc->vid_cap.frame.o_height,
742 			   out_fmt, in_bus, isp_mode, vinc->hflip, vinc->vflip);
743 
744 	count += scnprintf(buf + count, size - count,
745 			   "prs_in => x: %d, y: %d, hb: %d, hs: %d\n",
746 			   vinc->vin_status.prs_in.input_ht, vinc->vin_status.prs_in.input_vt,
747 			   vinc->vin_status.prs_in.input_hb, vinc->vin_status.prs_in.input_hs);
748 
749 	count += scnprintf(buf + count, size - count,
750 			   "buf => cnt: %u size: %u rest: %u, mode: %s\n",
751 			   vinc->vin_status.buf_cnt,
752 			   vinc->vin_status.buf_size,
753 			   vinc->vin_status.buf_rest,
754 #ifndef BUF_AUTO_UPDATE
755 			   "software_update");
756 #else
757 			   "hardware_update");
758 #endif
759 	count += scnprintf(buf + count, size - count,
760 			   "frame => cnt: %u, lost_cnt: %u, error_cnt: %u\n"
761 			   "internal => avg: %u(ms), max: %u(ms), min: %u(ms)\n"
762 			   "CSI Bandwidth: %d\n",
763 			   vinc->vin_status.frame_cnt,
764 			   vinc->vin_status.lost_cnt,
765 			   vinc->vin_status.err_cnt,
766 			   vinc->vin_status.frame_internal/1000,
767 			   vinc->vin_status.max_internal/1000,
768 			   vinc->vin_status.min_internal/1000,
769 			   vinc->bandwidth = vinc->vin_status.buf_size * (1000/vinc->vin_status.frame_internal/1000));
770 	vind->csi_bd_tatol += vinc->bandwidth;
771 	count += scnprintf(buf + count, size - count, "*****************************************************\n");
772 
773 	if (vinc->id == VIN_MAX_DEV - 1) {
774 		count += scnprintf(buf + count, size - count, "CSI Bandwidth total %dM, ISP Bandwidth total %dM\n",
775 							vind->csi_bd_tatol/(1024*1024), vind->isp_bd_tatol/(1024*1024));
776 		count += scnprintf(buf + count, size - count, "*****************************************************\n");
777 	}
778 	return count;
779 }
780 
vin_debugfs_open(struct inode * inode,struct file * file)781 static int vin_debugfs_open(struct inode *inode, struct file *file)
782 {
783 	struct vin_debugfs_buffer *buf;
784 	int i = 0;
785 
786 	buf = kmalloc(sizeof(*buf), GFP_KERNEL);
787 	if (buf == NULL)
788 		return -ENOMEM;
789 
790 	vi_status_size_sum = 0;
791 	for (i = 0; i < VIN_MAX_DEV; i++) {
792 		if (vin_core_gbl[i] != NULL)
793 			vi_status_size[i] = vin_status_dump(vin_core_gbl[i],
794 						buf->data + vi_status_size_sum,
795 						sizeof(buf->data) - vi_status_size_sum);
796 						vi_status_size_sum += vi_status_size[i];
797 	}
798 	buf->count = vi_status_size_sum;
799 	file->private_data = buf;
800 	return 0;
801 }
802 
803 #if !(IS_ENABLED(CONFIG_DEBUG_FS))
vi_node_show(struct device * dev,struct device_attribute * attr,char * buf)804 static ssize_t vi_node_show(struct device *dev,
805 		struct device_attribute *attr, char *buf)
806 {
807 	struct vin_debugfs_buffer *vd_buf;
808 	int i = 0;
809 
810 	vd_buf = kmalloc(sizeof(*vd_buf), GFP_KERNEL);
811 	if (vd_buf == NULL)
812 		return -ENOMEM;
813 
814 	vi_status_size_sum = 0;
815 	for (i = 0; i < VIN_MAX_DEV; i++) {
816 		if (vin_core_gbl[i] != NULL)
817 			vi_status_size[i] = vin_status_dump(vin_core_gbl[i],
818 						vd_buf->data + vi_status_size_sum,
819 						sizeof(vd_buf->data) - vi_status_size_sum);
820 						vi_status_size_sum += vi_status_size[i];
821 	}
822 	return strlcpy(buf, vd_buf->data, vi_status_size_sum);
823 }
824 
825 static DEVICE_ATTR(vi, S_IRUGO, vi_node_show, NULL);
826 #endif
827 
vin_debugfs_read(struct file * file,char __user * user_buf,size_t nbytes,loff_t * ppos)828 static ssize_t vin_debugfs_read(struct file *file, char __user *user_buf,
829 				      size_t nbytes, loff_t *ppos)
830 {
831 	struct vin_debugfs_buffer *buf = file->private_data;
832 
833 	return simple_read_from_buffer(user_buf, nbytes, ppos, buf->data,
834 				       buf->count);
835 }
836 
vin_debugfs_release(struct inode * inode,struct file * file)837 static int vin_debugfs_release(struct inode *inode, struct file *file)
838 {
839 	kfree(file->private_data);
840 	file->private_data = NULL;
841 
842 	return 0;
843 }
844 
845 static const struct file_operations vin_debugfs_fops = {
846 	.owner = THIS_MODULE,
847 	.open = vin_debugfs_open,
848 	.llseek = no_llseek,
849 	.read = vin_debugfs_read,
850 	.release = vin_debugfs_release,
851 };
vin_get_timestamp(struct timeval * tv)852 void vin_get_timestamp(struct timeval *tv)
853 {
854 	struct timespec64 ts64;
855 
856 	ktime_get_ts64(&ts64);
857 	tv->tv_sec = ts64.tv_sec;
858 	tv->tv_usec = ts64.tv_nsec / NSEC_PER_USEC;
859 }
860 
__vin_get_frame_internal(struct vin_core * vinc)861 static void __vin_get_frame_internal(struct vin_core *vinc)
862 {
863 	struct timeval ts;
864 
865 	vin_get_timestamp(&ts);
866 	if (vinc->vin_status.frame_cnt > 2) {
867 		vinc->vin_status.frame_internal = (ts.tv_sec * 1000000 + ts.tv_usec - vinc->vid_cap.ts.tv_sec * 1000000 - vinc->vid_cap.ts.tv_usec);
868 		if (vinc->vin_status.frame_internal > vinc->vin_status.max_internal)
869 			vinc->vin_status.max_internal = vinc->vin_status.frame_internal;
870 		if ((vinc->vin_status.frame_internal < vinc->vin_status.min_internal) || (vinc->vin_status.min_internal == 0))
871 			vinc->vin_status.min_internal = vinc->vin_status.frame_internal;
872 	}
873 	vinc->vid_cap.ts = ts;
874 }
875 
vin_get_rest_buf_cnt(struct vin_core * vinc)876 void vin_get_rest_buf_cnt(struct vin_core *vinc)
877 {
878 	struct list_head *buf_next = NULL;
879 
880 	vinc->vin_status.buf_rest = 0;
881 	buf_next = vinc->vid_cap.vidq_active.next;
882 	while ((&vinc->vid_cap.vidq_active) != buf_next) {
883 		vinc->vin_status.buf_rest++;
884 		buf_next = buf_next->next;
885 		if (vinc->vin_status.buf_rest >= VIDEO_MAX_FRAME)
886 			break;
887 	}
888 }
889 #ifndef BUF_AUTO_UPDATE
__vin_osd_auto_reverse(struct vin_core * vinc)890 static void __vin_osd_auto_reverse(struct vin_core *vinc)
891 {
892 #if defined CONFIG_ARCH_SUN8IW12P1
893 	int fps = 30;
894 
895 	if (vinc->vin_status.frame_internal) {
896 		fps = USEC_PER_SEC / vinc->vin_status.frame_internal;
897 		fps = fps < 5 ? 30 : fps;
898 	}
899 
900 	if (vinc->vid_cap.osd.overlay_en && !(vinc->vin_status.frame_cnt % (fps / 5))) {
901 		unsigned int osd_stat[MAX_OVERLAY_NUM];
902 		unsigned int inverse[MAX_OVERLAY_NUM];
903 		int i;
904 
905 		sunxi_vipp_get_osd_stat(vinc->vipp_sel, &osd_stat[0]);
906 		for (i = 0; i < vinc->vid_cap.osd.overlay_cnt; i++) {
907 			if (vinc->vid_cap.osd.inverse_close[i]) {
908 				inverse[i] = 0;
909 				continue;
910 			}
911 			osd_stat[i] /= (vinc->vid_cap.osd.ov_win[i].width * vinc->vid_cap.osd.ov_win[i].height);
912 			if (abs(osd_stat[i] - vinc->vid_cap.osd.y_bmp_avp[i]) < 80)
913 				inverse[i] = 1;
914 			else
915 				inverse[i] = 0;
916 		}
917 		vipp_osd_inverse(vinc->vipp_sel, inverse, vinc->vid_cap.osd.overlay_cnt);
918 	}
919 #endif
920 }
921 
__vin_ptn_update(struct vin_core * vinc)922 static void __vin_ptn_update(struct vin_core *vinc)
923 {
924 #ifdef SUPPORT_PTN
925 	if (!vinc->ptn_cfg.ptn_en)
926 		return;
927 	if (vinc->ptn_cfg.ptn_type > 0) {
928 		ptn_frame_cnt++;
929 		if (ptn_frame_cnt%(vinc->ptn_cfg.ptn_type) == 0) {
930 			if (ptn_frame_cnt/(vinc->ptn_cfg.ptn_type) < 3)
931 				csic_ptn_addr(0, (unsigned long)(vinc->ptn_cfg.ptn_buf.dma_addr));
932 			else
933 				csic_ptn_addr(0, (unsigned long)(vinc->ptn_cfg.ptn_buf.dma_addr + (ptn_frame_cnt/vinc->ptn_cfg.ptn_type-2)%3 * vinc->ptn_cfg.ptn_buf.size / 3));
934 			csic_ptn_generation_en(0, 1);
935 		}
936 	} else {
937 		csic_ptn_generation_en(0, 1);
938 	}
939 #endif
940 }
941 #endif
942 
vin_vsync_isr(struct vin_vid_cap * cap)943 void vin_vsync_isr(struct vin_vid_cap *cap)
944 {
945 	struct v4l2_event event;
946 	struct vin_vsync_event_data *data = (void *)event.u.data;
947 
948 	memset(&event, 0, sizeof(event));
949 	event.type = V4L2_EVENT_VSYNC;
950 	event.id = 0;
951 
952 	data->frame_number = cap->vinc->vin_status.frame_cnt;
953 	v4l2_event_queue(&cap->vdev, &event);
954 }
955 
956 /*
957  *  the interrupt routine
958  */
vin_isr(int irq,void * priv)959 static irqreturn_t vin_isr(int irq, void *priv)
960 {
961 	unsigned long flags;
962 	struct vin_buffer *buf;
963 	struct vin_vid_cap *cap = (struct vin_vid_cap *)priv;
964 	struct vin_core *vinc = cap->vinc;
965 	struct dma_int_status status;
966 	int need_callback = 0;
967 	bool display_sync = false;
968 #ifndef BUF_AUTO_UPDATE
969 	struct dma_output_size size;
970 #else
971 	struct list_head *buf_next = NULL;
972 	u64 timestamp_ns;
973 	int i;
974 #endif
975 
976 	if (vin_streaming(cap) == 0) {
977 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_ALL);
978 		return IRQ_HANDLED;
979 	}
980 
981 	if (cap->special_active == 1)
982 		need_callback = 0;
983 
984 #ifdef CONFIG_DISPPLAY_SYNC
985 	if (vinc->id == disp_sync_video)
986 		display_sync = true;
987 #endif
988 
989 	csic_dma_int_get_status(vinc->vipp_sel, &status);
990 
991 	vin_timer_update(vinc, 2000);
992 
993 	spin_lock_irqsave(&cap->slock, flags);
994 
995 	/* exception handle */
996 	if ((status.buf_0_overflow) || (status.buf_1_overflow) ||
997 	    (status.buf_2_overflow) || (status.hblank_overflow)) {
998 		if ((status.buf_0_overflow) || (status.buf_1_overflow) || (status.buf_2_overflow)) {
999 			csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_BUF_0_OVERFLOW | DMA_INT_BUF_1_OVERFLOW | DMA_INT_BUF_2_OVERFLOW);
1000 			vinc->vin_status.err_cnt++;
1001 			vin_err("video%d fifo overflow, CSI frame count is %d\n", vinc->id, vinc->vin_status.frame_cnt);
1002 		}
1003 		if (status.hblank_overflow) {
1004 			csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_HBLANK_OVERFLOW);
1005 			vinc->vin_status.err_cnt++;
1006 			vin_err("video%d hblank overflow, CSI frame count is %d\n", vinc->id, vinc->vin_status.frame_cnt);
1007 		}
1008 		sunxi_isp_reset(v4l2_get_subdevdata(cap->pipe.sd[VIN_IND_ISP]));
1009 	}
1010 
1011 	if (status.fbc_ovhd_wrddr_full) {
1012 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_FBC_OVHD_WRDDR_FULL);
1013 		/*when open isp debug please ignore fbc error!*/
1014 		if (!vinc->isp_dbg.debug_en)
1015 			vin_err("video%d fbc overhead write ddr full\n", vinc->id);
1016 	}
1017 
1018 	if (status.fbc_data_wrddr_full) {
1019 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_FBC_DATA_WRDDR_FULL);
1020 		vin_err("video%d fbc data write ddr full\n", vinc->id);
1021 	}
1022 
1023 	if (status.lbc_hb) {
1024 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_LBC_HB);
1025 		vin_err("video%d lbc hblanking less than 48 bk_clk cycles\n", vinc->id);
1026 	}
1027 #ifndef BUF_AUTO_UPDATE
1028 	if (status.vsync_trig) {
1029 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_VSYNC_TRIG);
1030 		vinc->vin_status.frame_cnt++;
1031 		csic_prs_input_para_get(vinc->csi_sel, 0, &vinc->vin_status.prs_in);
1032 		vin_vsync_isr(cap);
1033 		if (vinc->large_image == 2) {
1034 			size.hor_len = cap->frame.o_width / 2;
1035 			size.ver_len = cap->frame.o_height;
1036 			size.hor_start = cap->frame.offs_h;
1037 			size.ver_start = cap->frame.offs_v;
1038 			if (vinc->vin_status.frame_cnt % 2 == 0)
1039 				size.hor_start = 32;
1040 			csic_dma_output_size_cfg(vinc->vipp_sel, &size);
1041 		}
1042 		if (cap->capture_mode != V4L2_MODE_IMAGE && !display_sync) {
1043 			if (cap->first_flag && vinc->large_image != 2) {
1044 				if ((&cap->vidq_active) == cap->vidq_active.next->next->next) {
1045 					vin_log(VIN_LOG_VIDEO, "Only two buffer left for video%d\n", vinc->id);
1046 					vinc->vin_status.lost_cnt++;
1047 					goto unlock;
1048 				}
1049 				buf = list_entry(cap->vidq_active.next, struct vin_buffer, list);
1050 				buf->vb.sequence = csic_dma_get_frame_cnt(vinc->vipp_sel);
1051 				buf->vb.vb2_buf.timestamp = ktime_get_ns();
1052 				buf->vb.sequence = vinc->vin_status.frame_cnt;
1053 				list_del(&buf->list);
1054 
1055 				if (cap->frame_delay_cnt > 0) {
1056 					if (cap->frame_delay_cnt >= 5)
1057 						cap->frame_delay_cnt = 5;
1058 					list_add_tail(&buf->list, &cap->vidq_active);
1059 					cap->frame_delay_cnt--;
1060 					vinc->vin_status.lost_cnt++;
1061 				} else {
1062 					if (cap->special_active == 1) {
1063 						list_add_tail(&buf->list, &cap->vidq_done);
1064 						need_callback = 1;
1065 					} else
1066 						vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
1067 				}
1068 			}
1069 			if (list_empty(&cap->vidq_active) || cap->vidq_active.next->next == &cap->vidq_active) {
1070 				vin_log(VIN_LOG_VIDEO, "No active queue to serve\n");
1071 				goto unlock;
1072 			}
1073 
1074 #ifdef SUPPORT_PTN
1075 			if (vinc->large_image == 1)
1076 				csic_dma_buffer_address(vinc->vipp_sel, CSI_BUF_0_A, (unsigned long)vinc->ptn_cfg.ptn_buf.dma_addr);
1077 			else if ((vinc->large_image == 2) && (vinc->vin_status.frame_cnt % 2)) {
1078 				buf = list_entry(cap->vidq_active.next, struct vin_buffer, list);
1079 				vin_set_addr(vinc, &buf->vb.vb2_buf, &vinc->vid_cap.frame, &vinc->vid_cap.frame.paddr);
1080 			} else {
1081 				buf = list_entry(cap->vidq_active.next->next, struct vin_buffer, list);
1082 				vin_set_addr(vinc, &buf->vb.vb2_buf, &vinc->vid_cap.frame, &vinc->vid_cap.frame.paddr);
1083 			}
1084 #else
1085 			buf = list_entry(cap->vidq_active.next->next, struct vin_buffer, list);
1086 			vin_set_addr(vinc, &buf->vb.vb2_buf, &vinc->vid_cap.frame, &vinc->vid_cap.frame.paddr);
1087 #endif
1088 		}
1089 #ifdef CONFIG_DISPPLAY_SYNC
1090 		if (cap->first_flag == 1 && display_sync) {
1091 			buf = list_entry(cap->vidq_active.next, struct vin_buffer, list);
1092 			buf->vb.sequence = csic_dma_get_frame_cnt(vinc->vipp_sel);
1093 			buf->vb.vb2_buf.timestamp = ktime_get_ns();
1094 			list_del(&buf->list);
1095 			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
1096 			cap->first_flag++;
1097 		}
1098 #endif
1099 		if (cap->first_flag == 0) {
1100 			cap->first_flag++;
1101 			vin_log(VIN_LOG_VIDEO, "video%d first frame!\n", vinc->id);
1102 		}
1103 	}
1104 
1105 	/*when open isp debug line count interrupt would not come!*/
1106 	if (status.line_cnt_flag) {
1107 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_LINE_CNT);
1108 		vin_log(VIN_LOG_VIDEO, "video%d line_cnt interrupt!\n", vinc->id);
1109 	}
1110 
1111 	if (status.capture_done) {
1112 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_CAPTURE_DONE);
1113 		if (cap->capture_mode == V4L2_MODE_IMAGE) {
1114 			vin_log(VIN_LOG_VIDEO, "capture image mode!\n");
1115 			buf = list_entry(cap->vidq_active.next, struct vin_buffer, list);
1116 			buf->vb.vb2_buf.timestamp = ktime_get_ns();
1117 			list_del(&buf->list);
1118 			if (cap->special_active == 1) {
1119 				list_add_tail(&buf->list, &cap->vidq_done);
1120 				need_callback = 1;
1121 			} else
1122 				vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
1123 		}
1124 	}
1125 
1126 	if (status.frame_done) {
1127 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_FRAME_DONE);
1128 
1129 		__vin_ptn_update(vinc);
1130 
1131 		if (!display_sync) {
1132 			vin_get_rest_buf_cnt(vinc);
1133 
1134 			if (list_empty(&cap->vidq_active) || cap->vidq_active.next->next == &cap->vidq_active) {
1135 				vin_log(VIN_LOG_VIDEO, "No active queue to serve\n");
1136 				goto unlock;
1137 			}
1138 
1139 			/* video buffer handle */
1140 			if ((&cap->vidq_active) == cap->vidq_active.next->next->next) {
1141 				vin_log(VIN_LOG_VIDEO, "Only two buffer left for video%d\n", vinc->id);
1142 				vin_get_timestamp(&cap->ts);
1143 				goto unlock;
1144 			}
1145 			buf = list_entry(cap->vidq_active.next, struct vin_buffer, list);
1146 
1147 			/* Nobody is waiting on this buffer */
1148 			if (!cap->special_active) {
1149 				if (!waitqueue_active(&buf->vb.vb2_buf.vb2_queue->done_wq))
1150 					vin_log(VIN_LOG_VIDEO, "Nobody is waiting on video%d buffer%d\n",
1151 						vinc->id, buf->vb.vb2_buf.index);
1152 			}
1153 		}
1154 
1155 		__vin_get_frame_internal(vinc);
1156 
1157 		if (vinc->large_image == 2) {
1158 			if (vinc->vin_status.frame_cnt % 2 == 0) {
1159 				list_del(&buf->list);
1160 				vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
1161 			}
1162 		}
1163 		__vin_osd_auto_reverse(vinc);
1164 	}
1165 #else
1166 	if (status.vsync_trig) {
1167 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_VSYNC_TRIG);
1168 		vinc->vin_status.frame_cnt++;
1169 		csic_prs_input_para_get(vinc->csi_sel, 0, &vinc->vin_status.prs_in);
1170 		vin_vsync_isr(cap);
1171 		vin_get_rest_buf_cnt(vinc);
1172 		__vin_get_frame_internal(vinc);
1173 	}
1174 
1175 	if (status.frm_lost) {
1176 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_FRM_LOST);
1177 		vinc->vin_status.frame_cnt++;
1178 		vinc->vin_status.lost_cnt++;
1179 		vin_log(VIN_LOG_VIDEO, "video%d Frame lost interrupt!\n", vinc->id);
1180 	}
1181 
1182 	if (status.buf_addr_fifo) {
1183 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_BUF_ADDR_FIFO);
1184 		vin_log(VIN_LOG_VIDEO, "video%d buf addr set interrupt!\n", vinc->id);
1185 	}
1186 
1187 	if (status.capture_done) {
1188 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_CAPTURE_DONE);
1189 		if (cap->capture_mode == V4L2_MODE_IMAGE) {
1190 			vin_log(VIN_LOG_VIDEO, "capture image mode!\n");
1191 			buf = list_entry(cap->vidq_active.next, struct vin_buffer, list);
1192 			buf->vb.vb2_buf.timestamp = ktime_get_ns();
1193 			list_del(&buf->list);
1194 			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
1195 		}
1196 	}
1197 
1198 	if (status.stored_frm_cnt) {
1199 		csic_dma_int_clear_status(vinc->vipp_sel, DMA_INT_STORED_FRM_CNT);
1200 		timestamp_ns = ktime_get_ns();
1201 		buf_next = cap->vidq_active.next;
1202 		for (i = 0; i < cap->threshold.stored_frm_threshold; i++) {
1203 			buf = list_entry(buf_next, struct vin_buffer, list);
1204 			if (list_empty(&cap->vidq_active) || (&cap->vidq_active) == cap->vidq_active.next->next) {
1205 				vin_log(VIN_LOG_VIDEO, "video%d rest buf <= 1!\n", vinc->id);
1206 				goto unlock;
1207 			}
1208 			/* Nobody is waiting on this buffer */
1209 			if (!waitqueue_active(&buf->vb.vb2_buf.vb2_queue->done_wq))
1210 				vin_log(VIN_LOG_VIDEO, "Nobody is waiting on video%d buffer%d\n", vinc->id, buf->vb.vb2_buf.index);
1211 			buf->vb.sequence = csic_dma_get_frame_cnt(vinc->vipp_sel) - (cap->threshold.stored_frm_threshold - 1) + i;
1212 			buf->vb.vb2_buf.timestamp = timestamp_ns - ((cap->threshold.stored_frm_threshold - 1 - i) *
1213 							vinc->vin_status.frame_internal * 1000);
1214 			buf->vb.sequence = vinc->vin_status.frame_cnt - (cap->threshold.stored_frm_threshold - 1) + i;
1215 
1216 			buf_next = buf_next->next;
1217 			list_del(&buf->list);
1218 			vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
1219 		}
1220 	}
1221 #endif
1222 
1223 unlock:
1224 	spin_unlock_irqrestore(&cap->slock, flags);
1225 
1226 	if (cap->special_active && need_callback && cap->vin_buffer_process)
1227 		cap->vin_buffer_process(vinc->id);
1228 
1229 	return IRQ_HANDLED;
1230 }
1231 
vin_irq_request(struct vin_core * vinc,int i)1232 static int vin_irq_request(struct vin_core *vinc, int i)
1233 {
1234 	int ret;
1235 	struct device_node *np = vinc->pdev->dev.of_node;
1236 	/*get irq resource */
1237 	vinc->irq = irq_of_parse_and_map(np, i);
1238 	if (vinc->irq <= 0) {
1239 		vin_err("failed to get CSI DMA IRQ resource\n");
1240 		return -ENXIO;
1241 	}
1242 
1243 	ret = request_irq(vinc->irq, vin_isr, IRQF_SHARED,
1244 			vinc->pdev->name, &vinc->vid_cap);
1245 
1246 	if (ret) {
1247 		vin_err("failed to install CSI DMA irq (%d)\n", ret);
1248 		return -ENXIO;
1249 	}
1250 	return 0;
1251 }
1252 
vin_irq_release(struct vin_core * vinc)1253 static void vin_irq_release(struct vin_core *vinc)
1254 {
1255 	if (vinc->irq > 0)
1256 		free_irq(vinc->irq, &vinc->vid_cap);
1257 }
1258 
1259 #ifdef CONFIG_PM_SLEEP
vin_core_suspend(struct device * d)1260 int vin_core_suspend(struct device *d)
1261 {
1262 	struct vin_core *vinc = (struct vin_core *)dev_get_drvdata(d);
1263 	struct vin_vid_cap *cap = &vinc->vid_cap;
1264 	__maybe_unused struct isp_dev *isp;
1265 	__maybe_unused int ret;
1266 
1267 	vin_log(VIN_LOG_POWER, "%s\n", __func__);
1268 	if (!vinc->vid_cap.registered)
1269 		return 0;
1270 	if (test_and_set_bit(VIN_LPM, &vinc->vid_cap.state))
1271 		return 0;
1272 
1273 	if (vin_busy(cap)) {
1274 #if defined CONFIG_ARCH_SUN8IW16P1 || defined CONFIG_ARCH_SUN8IW19P1
1275 		vin_timer_del(vinc);
1276 
1277 		mutex_lock(&cap->vdev.entity.graph_obj.mdev->graph_mutex);
1278 		if (!cap->pipe.sd[VIN_IND_SENSOR]->entity.use_count) {
1279 			vin_err("%s is not used, cannot be suspend!\n", cap->pipe.sd[VIN_IND_SENSOR]->name);
1280 			mutex_unlock(&cap->vdev.entity.graph_obj.mdev->graph_mutex);
1281 			return -1;
1282 		}
1283 
1284 		if (cap->pipe.sd[VIN_IND_ISP] != NULL) {
1285 			isp = container_of(cap->pipe.sd[VIN_IND_ISP], struct isp_dev, subdev);
1286 			isp->runtime_flag = 1;
1287 		}
1288 
1289 		clear_bit(VIN_STREAM, &cap->state);
1290 		ret = vin_pipeline_call(vinc, set_stream, &cap->pipe, 0);
1291 		if (ret)
1292 			vin_err("vin pipeline streamoff failed!\n");
1293 
1294 		ret = vin_pipeline_call(vinc, close, &cap->pipe);
1295 		if (ret)
1296 			vin_err("vin pipeline close failed!\n");
1297 
1298 		v4l2_subdev_call(cap->pipe.sd[VIN_IND_ISP], core, init, 0);
1299 		mutex_unlock(&cap->vdev.entity.graph_obj.mdev->graph_mutex);
1300 		vin_log(VIN_LOG_POWER, "vinc%d suspend streamoff and close pipeline at %s!\n", vinc->id, __func__);
1301 #else
1302 		vin_print("before %s please close video%d\n", __func__, vinc->id);
1303 #endif
1304 	}
1305 	return 0;
1306 }
vin_core_resume(struct device * d)1307 int vin_core_resume(struct device *d)
1308 {
1309 	struct vin_core *vinc = (struct vin_core *)dev_get_drvdata(d);
1310 	struct vin_vid_cap *cap = &vinc->vid_cap;
1311 	__maybe_unused struct isp_dev *isp;
1312 	__maybe_unused struct sensor_info *info = container_of(cap->pipe.sd[VIN_IND_SENSOR], struct sensor_info, sd);
1313 #ifdef CONFIG_ENABLE_SENSOR_FLIP_OPTION
1314 	struct v4l2_control c;
1315 #endif
1316 
1317 	__maybe_unused int ret;
1318 
1319 	vin_log(VIN_LOG_POWER, "%s\n", __func__);
1320 	if (!vinc->vid_cap.registered)
1321 		return 0;
1322 
1323 	if (!test_and_clear_bit(VIN_LPM, &vinc->vid_cap.state)) {
1324 		vin_print("VIN not suspend!\n");
1325 		return 0;
1326 	}
1327 
1328 	if (vin_busy(cap)) {
1329 #if defined CONFIG_ARCH_SUN8IW16P1 || defined CONFIG_ARCH_SUN8IW19P1
1330 		mutex_lock(&cap->vdev.entity.graph_obj.mdev->graph_mutex);
1331 		if (cap->pipe.sd[VIN_IND_ISP] != NULL) {
1332 			isp = container_of(cap->pipe.sd[VIN_IND_ISP], struct isp_dev, subdev);
1333 			isp->runtime_flag = 0;
1334 		}
1335 
1336 		ret = vin_pipeline_call(vinc, open, &cap->pipe, &cap->vdev.entity, true);
1337 		if (ret < 0)
1338 			vin_err("vin pipeline open failed (%d)!\n", ret);
1339 
1340 		v4l2_subdev_call(cap->pipe.sd[VIN_IND_ISP], core, init, 1);
1341 		if (ret < 0)
1342 			vin_err("ISP init error at %s\n", __func__);
1343 
1344 		ret = v4l2_subdev_call(cap->pipe.sd[VIN_IND_SCALER], core, init, 1);
1345 		if (ret < 0)
1346 			vin_err("SCALER init error at %s\n", __func__);
1347 
1348 		if (info) {
1349 			vinc->exp_gain.exp_val = info->exp;
1350 			vinc->exp_gain.gain_val = info->gain;
1351 			vinc->stream_idx = info->stream_seq + 1;
1352 		}
1353 		vin_timer_init(vinc);
1354 		vin_pipeline_call(cap->vinc, set_stream, &cap->pipe, cap->vinc->stream_idx);
1355 		set_bit(VIN_STREAM, &cap->state);
1356 
1357 #ifdef CONFIG_ENABLE_SENSOR_FLIP_OPTION
1358 		if (vinc->sensor_hflip) {
1359 			c.id = V4L2_CID_HFLIP;
1360 			c.value = vinc->sensor_hflip;
1361 			sensor_flip_option(cap, c);
1362 		}
1363 		if (vinc->sensor_vflip) {
1364 			c.id = V4L2_CID_VFLIP;
1365 			c.value = vinc->sensor_vflip;
1366 			sensor_flip_option(cap, c);
1367 		}
1368 #endif
1369 
1370 		if (cap->vinc->exp_gain.exp_val && cap->vinc->exp_gain.gain_val) {
1371 			v4l2_subdev_call(cap->pipe.sd[VIN_IND_SENSOR], core, ioctl,
1372 				VIDIOC_VIN_SENSOR_EXP_GAIN, &cap->vinc->exp_gain);
1373 		}
1374 		mutex_unlock(&cap->vdev.entity.graph_obj.mdev->graph_mutex);
1375 		vin_log(VIN_LOG_POWER, "vinc%d resume open pipeline and streamon at %s!\n", vinc->id, __func__);
1376 #else
1377 		vin_print("after %s please open video%d\n", __func__, vinc->id);
1378 #endif
1379 	}
1380 	return 0;
1381 }
1382 #endif
1383 
1384 #ifdef CONFIG_PM
vin_core_runtime_suspend(struct device * d)1385 int vin_core_runtime_suspend(struct device *d)
1386 {
1387 	vin_log(VIN_LOG_POWER, "%s\n", __func__);
1388 	return 0;
1389 }
vin_core_runtime_resume(struct device * d)1390 int vin_core_runtime_resume(struct device *d)
1391 {
1392 	vin_log(VIN_LOG_POWER, "%s\n", __func__);
1393 	return 0;
1394 }
vin_core_runtime_idle(struct device * d)1395 int vin_core_runtime_idle(struct device *d)
1396 {
1397 	if (d) {
1398 		pm_runtime_mark_last_busy(d);
1399 		pm_request_autosuspend(d);
1400 	} else {
1401 		vin_err("%s, vfe device is null\n", __func__);
1402 	}
1403 	return 0;
1404 }
1405 #endif
vin_core_shutdown(struct platform_device * pdev)1406 static void vin_core_shutdown(struct platform_device *pdev)
1407 {
1408 #if defined(CONFIG_PM) || defined(CONFIG_SUSPEND)
1409 	struct vin_core *vinc = (struct vin_core *)dev_get_drvdata(&pdev->dev);
1410 	struct vin_vid_cap *cap = &vinc->vid_cap;
1411 	struct isp_dev *isp = NULL;
1412 	int ret;
1413 
1414 	if (!vin_busy(cap)) {
1415 		vin_warn("video%d device have been closed!\n", vinc->id);
1416 		return;
1417 	}
1418 
1419 	if (vin_streaming(cap))
1420 		vin_timer_del(vinc);
1421 
1422 	mutex_lock(&cap->vdev.entity.graph_obj.mdev->graph_mutex);
1423 	if (!cap->pipe.sd[VIN_IND_SENSOR]->entity.use_count) {
1424 		vin_err("%s is not used, cannot be shutdown!\n", cap->pipe.sd[VIN_IND_SENSOR]->name);
1425 		mutex_unlock(&cap->vdev.entity.graph_obj.mdev->graph_mutex);
1426 		return;
1427 	}
1428 
1429 	if (vin_streaming(cap)) {
1430 		clear_bit(VIN_STREAM, &cap->state);
1431 		if (cap->pipe.sd[VIN_IND_ISP] != NULL) {
1432 			isp = container_of(cap->pipe.sd[VIN_IND_ISP], struct isp_dev, subdev);
1433 			isp->nosend_ispoff = 1;
1434 		}
1435 		vin_pipeline_call(vinc, set_stream, &cap->pipe, 0);
1436 	}
1437 
1438 	ret = vin_pipeline_call(vinc, close, &cap->pipe);
1439 	if (ret)
1440 		vin_err("vin pipeline close failed!\n");
1441 
1442 	set_bit(VIN_LPM, &cap->state);
1443 	clear_bit(VIN_BUSY, &cap->state);
1444 	mutex_unlock(&cap->vdev.entity.graph_obj.mdev->graph_mutex);
1445 	vin_log(VIN_LOG_VIDEO, "video%d shutdown\n", vinc->id);
1446 #endif
1447 }
1448 
1449 static const struct dev_pm_ops vin_core_runtime_pm_ops = {
1450 	SET_SYSTEM_SLEEP_PM_OPS(vin_core_suspend, vin_core_resume)
1451 	SET_RUNTIME_PM_OPS(vin_core_runtime_suspend, vin_core_runtime_resume,
1452 			       vin_core_runtime_idle)
1453 };
1454 
vin_core_probe(struct platform_device * pdev)1455 static int vin_core_probe(struct platform_device *pdev)
1456 {
1457 	struct device_node *np = pdev->dev.of_node;
1458 	struct vin_core *vinc;
1459 	char property_name[32] = { 0 };
1460 	int ret = 0;
1461 
1462 	vin_log(VIN_LOG_VIDEO, "%s\n", __func__);
1463 	/*request mem for vinc */
1464 	vinc = kzalloc(sizeof(struct vin_core), GFP_KERNEL);
1465 	if (!vinc) {
1466 		vin_err("request vinc mem failed!\n");
1467 		ret = -ENOMEM;
1468 		goto ekzalloc;
1469 	}
1470 
1471 	of_property_read_u32(np, "device_id", &pdev->id);
1472 	if (pdev->id < 0) {
1473 		vin_err("vin core failed to get device id\n");
1474 		ret = -EINVAL;
1475 		goto freedev;
1476 	}
1477 
1478 	sprintf(property_name, "vinc%d_rear_sensor_sel", pdev->id);
1479 	if (of_property_read_u32(np, property_name, &vinc->rear_sensor))
1480 		vinc->rear_sensor = 0;
1481 
1482 	sprintf(property_name, "vinc%d_front_sensor_sel", pdev->id);
1483 	if (of_property_read_u32(np, property_name, &vinc->front_sensor))
1484 		vinc->front_sensor = 1;
1485 
1486 	sprintf(property_name, "vinc%d_csi_sel", pdev->id);
1487 	if (of_property_read_u32(np, property_name, &vinc->csi_sel))
1488 		vinc->csi_sel = 0;
1489 
1490 	sprintf(property_name, "vinc%d_mipi_sel", pdev->id);
1491 	if (of_property_read_u32(np, property_name, &vinc->mipi_sel))
1492 		vinc->mipi_sel = 0xff;
1493 
1494 	sprintf(property_name, "vinc%d_isp_sel", pdev->id);
1495 	if (of_property_read_u32(np, property_name, &vinc->isp_sel))
1496 		vinc->isp_sel = 0;
1497 
1498 	sprintf(property_name, "vinc%d_isp_tx_ch", pdev->id);
1499 	if (of_property_read_u32(np, property_name, &vinc->isp_tx_ch))
1500 		vinc->isp_tx_ch = 0;
1501 
1502 	sprintf(property_name, "vinc%d_tdm_rx_sel", pdev->id);
1503 	if (of_property_read_u32(np, property_name, &vinc->tdm_rx_sel))
1504 		vinc->tdm_rx_sel = 0;
1505 
1506 	vinc->vipp_sel = pdev->id;
1507 
1508 	vinc->id = pdev->id;
1509 	vinc->pdev = pdev;
1510 
1511 	vinc->base = of_iomap(np, 0);
1512 	if (!vinc->base) {
1513 		vinc->is_empty = 1;
1514 		vinc->base = kzalloc(0x100, GFP_KERNEL);
1515 		if (!vinc->base) {
1516 			ret = -EIO;
1517 			goto freedev;
1518 		}
1519 	}
1520 
1521 	csic_dma_set_base_addr(vinc->id, (unsigned long)vinc->base);
1522 
1523 	dev_set_drvdata(&vinc->pdev->dev, vinc);
1524 
1525 
1526 	vin_core_gbl[vinc->id] = vinc;
1527 
1528 	vin_log(VIN_LOG_VIDEO, "vinc->id = %d\n", vinc->id);
1529 	vin_log(VIN_LOG_VIDEO, "rear_sensor_sel = %d\n", vinc->rear_sensor);
1530 	vin_log(VIN_LOG_VIDEO, "front_sensor_sel = %d\n", vinc->front_sensor);
1531 	vin_log(VIN_LOG_VIDEO, "csi_sel = %d\n", vinc->csi_sel);
1532 	vin_log(VIN_LOG_VIDEO, "mipi_sel = %d\n", vinc->mipi_sel);
1533 	vin_log(VIN_LOG_VIDEO, "isp_sel = %d\n", vinc->isp_sel);
1534 	vin_log(VIN_LOG_VIDEO, "isp_tx_ch = %d\n", vinc->isp_tx_ch);
1535 	vin_log(VIN_LOG_VIDEO, "vipp_sel = %d\n", vinc->vipp_sel);
1536 	vin_log(VIN_LOG_VIDEO, "tdm_rx_sel = %d\n", vinc->tdm_rx_sel);
1537 
1538 	vin_irq_request(vinc, 0);
1539 
1540 	ret = vin_initialize_capture_subdev(vinc);
1541 	if (ret)
1542 		goto unmap;
1543 
1544 	/*initial parameter */
1545 	ret = sysfs_create_group(&vinc->pdev->dev.kobj, &vin_attribute_group);
1546 	if (ret) {
1547 		vin_err("sysfs_create_group failed!\n");
1548 		goto unmap;
1549 	}
1550 
1551 #ifdef CONFIG_PM
1552 	pm_runtime_enable(&pdev->dev);
1553 #endif
1554 	return 0;
1555 unmap:
1556 	if (!vinc->is_empty)
1557 		iounmap(vinc->base);
1558 	else
1559 		kfree(vinc->base);
1560 freedev:
1561 	kfree(vinc);
1562 ekzalloc:
1563 	vin_err("%s error!\n", __func__);
1564 	return ret;
1565 }
1566 
vin_core_remove(struct platform_device * pdev)1567 static int vin_core_remove(struct platform_device *pdev)
1568 {
1569 	struct vin_core *vinc = (struct vin_core *)dev_get_drvdata(&pdev->dev);
1570 
1571 	sysfs_remove_group(&vinc->pdev->dev.kobj, &vin_attribute_group);
1572 #ifdef CONFIG_PM
1573 	pm_runtime_disable(&vinc->pdev->dev);
1574 #endif
1575 	vin_irq_release(vinc);
1576 	vin_cleanup_capture_subdev(vinc);
1577 	if (vinc->base) {
1578 		if (!vinc->is_empty)
1579 			iounmap(vinc->base);
1580 		else
1581 			kfree(vinc->base);
1582 	}
1583 	kfree(vinc);
1584 	vin_log(VIN_LOG_VIDEO, "%s end\n", __func__);
1585 	return 0;
1586 }
1587 
1588 #if IS_ENABLED(CONFIG_DEBUG_FS)
sunxi_vin_debug_register_driver(void)1589 int sunxi_vin_debug_register_driver(void)
1590 {
1591 #if IS_ENABLED(CONFIG_SUNXI_MPP)
1592 	vi_debugfs_root = debugfs_mpp_root;
1593 #else
1594 	vi_debugfs_root = debugfs_create_dir("mpp", NULL);
1595 #endif
1596 	if (vi_debugfs_root == NULL)
1597 		return -ENOENT;
1598 
1599 	vi_node = debugfs_create_file("vi", 0444, vi_debugfs_root,
1600 				   NULL, &vin_debugfs_fops);
1601 	if (IS_ERR_OR_NULL(vi_node)) {
1602 		vin_err("Unable to create debugfs status file.\n");
1603 		vi_debugfs_root = NULL;
1604 		return -ENODEV;
1605 	}
1606 
1607 	return 0;
1608 }
1609 #else
sunxi_vin_debug_register_driver(void)1610 int sunxi_vin_debug_register_driver(void)
1611 {
1612 	struct vin_core *vinc;
1613 	int ret, i;
1614 
1615 	for (i = 0; i < VIN_MAX_DEV; i++) {
1616 		vinc = sunxi_vin_core_get_dev(i);
1617 		if (vinc)
1618 			break;
1619 	}
1620 	if (!vinc && vinc->v4l2_dev && vinc->v4l2_dev->dev)
1621 		return -1;
1622 	ret = device_create_file(vinc->v4l2_dev->dev, &dev_attr_vi);
1623 	if (ret) {
1624 		vin_err("vin debug node register fail\n");
1625 		return ret;
1626 	}
1627 	return 0;
1628 }
1629 #endif
1630 
1631 #if IS_ENABLED(CONFIG_DEBUG_FS)
sunxi_vin_debug_unregister_driver(void)1632 void sunxi_vin_debug_unregister_driver(void)
1633 {
1634 	if (vi_debugfs_root == NULL)
1635 		return;
1636 #if IS_ENABLED(CONFIG_SUNXI_MPP)
1637 	debugfs_remove_recursive(vi_node);
1638 #else
1639 	debugfs_remove_recursive(vi_debugfs_root);
1640 	vi_debugfs_root = NULL;
1641 #endif
1642 }
1643 #else
sunxi_vin_debug_unregister_driver(void)1644 void sunxi_vin_debug_unregister_driver(void)
1645 {
1646 	struct vin_core *vinc;
1647 	int i;
1648 
1649 	for (i = 0; i < VIN_MAX_DEV; i++) {
1650 		vinc = sunxi_vin_core_get_dev(i);
1651 		if (vinc)
1652 			break;
1653 	}
1654 	if (!vinc && vinc->v4l2_dev && vinc->v4l2_dev->dev)
1655 		return;
1656 	device_remove_file(vinc->v4l2_dev->dev, &dev_attr_vi);
1657 }
1658 #endif
1659 
1660 static const struct of_device_id sunxi_vin_core_match[] = {
1661 	{.compatible = "allwinner,sunxi-vin-core",},
1662 	{},
1663 };
1664 
1665 static struct platform_driver vin_core_driver = {
1666 	.probe = vin_core_probe,
1667 	.remove = vin_core_remove,
1668 	.shutdown = vin_core_shutdown,
1669 	.driver = {
1670 		   .name = VIN_CORE_NAME,
1671 		   .owner = THIS_MODULE,
1672 		   .of_match_table = sunxi_vin_core_match,
1673 		   .pm = &vin_core_runtime_pm_ops,
1674 		   },
1675 };
sunxi_vin_core_register_driver(void)1676 int sunxi_vin_core_register_driver(void)
1677 {
1678 	int ret;
1679 
1680 	vin_log(VIN_LOG_VIDEO, "vin core register driver\n");
1681 	ret = platform_driver_register(&vin_core_driver);
1682 	return ret;
1683 }
1684 
sunxi_vin_core_unregister_driver(void)1685 void sunxi_vin_core_unregister_driver(void)
1686 {
1687 	vin_log(VIN_LOG_VIDEO, "vin core unregister driver\n");
1688 	platform_driver_unregister(&vin_core_driver);
1689 }
1690 
sunxi_vin_core_get_dev(int index)1691 struct vin_core *sunxi_vin_core_get_dev(int index)
1692 {
1693 	return vin_core_gbl[index];
1694 }
1695 
1696