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