1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * vehicle sensor nvp6188
4 *
5 * Copyright (C) 2022 Rockchip Electronics Co.Ltd
6 * Authors:
7 * wpzz <randy.wang@rock-chips.com>
8 * Jianwei Fan <jianwei.fan@rock-chips.com>
9 *
10 */
11
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/delay.h>
16 #include <linux/sched.h>
17 #include <linux/errno.h>
18 #include <linux/sysctl.h>
19 #include <linux/interrupt.h>
20 #include <linux/platform_device.h>
21 #include <linux/proc_fs.h>
22 #include <linux/suspend.h>
23 #include <linux/delay.h>
24 #include <linux/io.h>
25 #include <linux/irq.h>
26 #include <linux/uaccess.h>
27 #include <linux/of_gpio.h>
28 #include <linux/of_irq.h>
29 #include "vehicle_cfg.h"
30 #include "vehicle_main.h"
31 #include "vehicle_ad.h"
32 #include "vehicle_ad_nvp6188.h"
33
34 enum {
35 CVSTD_720P60 = 0,
36 CVSTD_720P50,
37 CVSTD_1080P30,
38 CVSTD_1080P25,
39 CVSTD_720P30,
40 CVSTD_720P25,
41 CVSTD_SVGAP30,
42 CVSTD_SD,
43 CVSTD_NTSC,
44 CVSTD_PAL
45 };
46
47 enum {
48 FORCE_PAL_WIDTH = 960,
49 FORCE_PAL_HEIGHT = 576,
50 FORCE_NTSC_WIDTH = 960,
51 FORCE_NTSC_HEIGHT = 480,
52 FORCE_SVGA_WIDTH = 800,
53 FORCE_SVGA_HEIGHT = 600,
54 FORCE_720P_WIDTH = 1280,
55 FORCE_720P_HEIGHT = 720,
56 FORCE_1080P_WIDTH = 1920,
57 FORCE_1080P_HEIGHT = 1080,
58 FORCE_CIF_OUTPUT_FORMAT = CIF_OUTPUT_FORMAT_420,
59 };
60
61 enum {
62 VIDEO_UNPLUG,
63 VIDEO_IN,
64 VIDEO_LOCKED,
65 VIDEO_UNLOCK
66 };
67
68 #define NVP6188_LINK_FREQ_1458M (1458000000UL >> 1)
69
70 static struct vehicle_ad_dev *nvp6188_g_addev;
71 static int cvstd_mode = CVSTD_1080P25;
72 //static int cvstd_old = CVSTD_720P25;
73 static int cvstd_state = VIDEO_UNPLUG;
74 // static int cvstd_old_state = VIDEO_UNLOCK;
75
76 static bool g_nvp6188_streaming;
77
78 #define NVP6188_CHIP_ID 0xD3
79 #define NVP6188_CHIP_ID2 0xD0
80
81 #define _MIPI_PORT0_
82 #ifdef _MIPI_PORT0_
83 #define _MAR_BANK_ 0x20
84 #define _MTX_BANK_ 0x23
85 #else
86 #define _MAR_BANK_ 0x30
87 #define _MTX_BANK_ 0x33
88 #endif
89
90 #define NVP_RESO_960H_NSTC_VALUE 0x00
91 #define NVP_RESO_960H_PAL_VALUE 0x10
92 #define NVP_RESO_720P_NSTC_VALUE 0x20
93 #define NVP_RESO_720P_PAL_VALUE 0x21
94 #define NVP_RESO_1080P_NSTC_VALUE 0x30
95 #define NVP_RESO_1080P_PAL_VALUE 0x31
96 #define NVP_RESO_960P_NSTC_VALUE 0xa0
97 #define NVP_RESO_960P_PAL_VALUE 0xa1
98
99 enum nvp6188_support_reso {
100 NVP_RESO_UNKNOWN = 0,
101 NVP_RESO_960H_PAL,
102 NVP_RESO_720P_PAL,
103 NVP_RESO_960P_PAL,
104 NVP_RESO_1080P_PAL,
105 NVP_RESO_960H_NSTC,
106 NVP_RESO_720P_NSTC,
107 NVP_RESO_960P_NSTC,
108 NVP_RESO_1080P_NSTC,
109 };
110
111 struct regval {
112 u8 addr;
113 u8 val;
114 };
115
116 static __maybe_unused const struct regval common_setting_1458M_regs[] = {
117 {0xff, 0x00},
118 {0x80, 0x0f},
119 {0x00, 0x10},
120 {0x01, 0x10},
121 {0x02, 0x10},
122 {0x03, 0x10},
123 {0x22, 0x0b},
124 {0x23, 0x41},
125 {0x26, 0x0b},
126 {0x27, 0x41},
127 {0x2a, 0x0b},
128 {0x2b, 0x41},
129 {0x2e, 0x0b},
130 {0x2f, 0x41},
131
132 {0xff, 0x01},
133 {0x98, 0x30},
134 {0xed, 0x00},
135
136 {0xff, 0x05+0},
137 {0x00, 0xd0},
138 {0x01, 0x22},
139 {0x47, 0xee},
140 {0x50, 0xc6},
141 {0x57, 0x00},
142 {0x58, 0x77},
143 {0x5b, 0x41},
144 {0x5c, 0x78},
145 {0xB8, 0xB8},
146
147 {0xff, 0x05+1},
148 {0x00, 0xd0},
149 {0x01, 0x22},
150 {0x47, 0xee},
151 {0x50, 0xc6},
152 {0x57, 0x00},
153 {0x58, 0x77},
154 {0x5b, 0x41},
155 {0x5c, 0x78},
156 {0xB8, 0xB8},
157
158 {0xff, 0x05+2},
159 {0x00, 0xd0},
160 {0x01, 0x22},
161 {0x47, 0xee},
162 {0x50, 0xc6},
163 {0x57, 0x00},
164 {0x58, 0x77},
165 {0x5b, 0x41},
166 {0x5c, 0x78},
167 {0xB8, 0xB8},
168
169 {0xff, 0x05+3},
170 {0x00, 0xd0},
171 {0x01, 0x22},
172 {0x47, 0xee},
173 {0x50, 0xc6},
174 {0x57, 0x00},
175 {0x58, 0x77},
176 {0x5b, 0x41},
177 {0x5c, 0x78},
178 {0xB8, 0xB8},
179
180 {0xff, 0x09},
181 {0x50, 0x30},
182 {0x51, 0x6f},
183 {0x52, 0x67},
184 {0x53, 0x48},
185 {0x54, 0x30},
186 {0x55, 0x6f},
187 {0x56, 0x67},
188 {0x57, 0x48},
189 {0x58, 0x30},
190 {0x59, 0x6f},
191 {0x5a, 0x67},
192 {0x5b, 0x48},
193 {0x5c, 0x30},
194 {0x5d, 0x6f},
195 {0x5e, 0x67},
196 {0x5f, 0x48},
197
198 {0xff, 0x0a},
199 {0x25, 0x10},
200 {0x27, 0x1e},
201 {0x30, 0xac},
202 {0x31, 0x78},
203 {0x32, 0x17},
204 {0x33, 0xc1},
205 {0x34, 0x40},
206 {0x35, 0x00},
207 {0x36, 0xc3},
208 {0x37, 0x0a},
209 {0x38, 0x00},
210 {0x39, 0x02},
211 {0x3a, 0x00},
212 {0x3b, 0xb2},
213 {0xa5, 0x10},
214 {0xa7, 0x1e},
215 {0xb0, 0xac},
216 {0xb1, 0x78},
217 {0xb2, 0x17},
218 {0xb3, 0xc1},
219 {0xb4, 0x40},
220 {0xb5, 0x00},
221 {0xb6, 0xc3},
222 {0xb7, 0x0a},
223 {0xb8, 0x00},
224 {0xb9, 0x02},
225 {0xba, 0x00},
226 {0xbb, 0xb2},
227 {0xff, 0x0b},
228 {0x25, 0x10},
229 {0x27, 0x1e},
230 {0x30, 0xac},
231 {0x31, 0x78},
232 {0x32, 0x17},
233 {0x33, 0xc1},
234 {0x34, 0x40},
235 {0x35, 0x00},
236 {0x36, 0xc3},
237 {0x37, 0x0a},
238 {0x38, 0x00},
239 {0x39, 0x02},
240 {0x3a, 0x00},
241 {0x3b, 0xb2},
242 {0xa5, 0x10},
243 {0xa7, 0x1e},
244 {0xb0, 0xac},
245 {0xb1, 0x78},
246 {0xb2, 0x17},
247 {0xb3, 0xc1},
248 {0xb4, 0x40},
249 {0xb5, 0x00},
250 {0xb6, 0xc3},
251 {0xb7, 0x0a},
252 {0xb8, 0x00},
253 {0xb9, 0x02},
254 {0xba, 0x00},
255 {0xbb, 0xb2},
256
257 {0xff, 0x13},
258 {0x05, 0xa0},
259 {0x31, 0xff},
260 {0x07, 0x47},
261 {0x12, 0x04},
262 {0x1e, 0x1f},
263 {0x1f, 0x27},
264 {0x2e, 0x10},
265 {0x2f, 0xc8},
266 {0x31, 0xff},
267 {0x32, 0x00},
268 {0x33, 0x00},
269 {0x72, 0x05},
270 {0x7a, 0xf0},
271 {0xff, _MAR_BANK_},
272 {0x10, 0xff},
273 {0x11, 0xff},
274
275 {0x30, 0x0f},
276 {0x32, 0xff},
277 {0x34, 0xcd},
278 {0x36, 0x04},
279 {0x38, 0xff},
280 {0x3c, 0x01},
281 {0x3d, 0x11},
282 {0x3e, 0x11},
283 {0x45, 0x60},
284 {0x46, 0x49},
285
286 {0xff, _MTX_BANK_},
287 {0xe9, 0x03},
288 {0x03, 0x02},
289 {0x01, 0xe4},
290 {0x00, 0x7d},
291 {0x01, 0xe0},
292 {0x02, 0xa0},
293 {0x20, 0x1e},
294 {0x20, 0x1f},
295 {0x04, 0x6c},
296 {0x45, 0xcd},
297 {0x46, 0x42},
298 {0x47, 0x36},
299 {0x48, 0x0f},
300 {0x65, 0xcd},
301 {0x66, 0x42},
302 {0x67, 0x0e},
303 {0x68, 0x0f},
304 {0x85, 0xcd},
305 {0x86, 0x42},
306 {0x87, 0x0e},
307 {0x88, 0x0f},
308 {0xa5, 0xcd},
309 {0xa6, 0x42},
310 {0xa7, 0x0e},
311 {0xa8, 0x0f},
312 {0xc5, 0xcd},
313 {0xc6, 0x42},
314 {0xc7, 0x0e},
315 {0xc8, 0x0f},
316 {0xeb, 0x8d},
317
318 {0xff, _MAR_BANK_},
319 {0x00, 0xff},
320 {0x40, 0x01},
321 {0x40, 0x00},
322 {0xff, 0x01},
323 {0x97, 0x00},
324 {0x97, 0x0f},
325
326 {0xff, 0x00}, //test pattern
327 {0x78, 0xba},
328 {0x79, 0xac},
329 {0xff, 0x05},
330 {0x2c, 0x08},
331 {0x6a, 0x80},
332 {0xff, 0x06},
333 {0x2c, 0x08},
334 {0x6a, 0x80},
335 {0xff, 0x07},
336 {0x2c, 0x08},
337 {0x6a, 0x80},
338 {0xff, 0x08},
339 {0x2c, 0x08},
340 {0x6a, 0x80},
341 };
342
343 static __maybe_unused const struct regval auto_detect_regs[] = {
344 {0xFF, 0x13},
345 {0x30, 0x7f},
346 {0x70, 0xf0},
347
348 {0xFF, 0x00},
349 {0x00, 0x18},
350 {0x01, 0x18},
351 {0x02, 0x18},
352 {0x03, 0x18},
353
354 {0x00, 0x10},
355 {0x01, 0x10},
356 {0x02, 0x10},
357 {0x03, 0x10},
358 };
359
nvp6188_reinit_parameter(struct vehicle_ad_dev * ad,unsigned char cvstd)360 static void nvp6188_reinit_parameter(struct vehicle_ad_dev *ad, unsigned char cvstd)
361 {
362 int i = 0;
363
364 switch (cvstd) {
365 case CVSTD_720P25:
366 ad->cfg.width = 1280;
367 ad->cfg.height = 720;
368 ad->cfg.start_x = 0;
369 ad->cfg.start_y = 0;
370 ad->cfg.input_format = CIF_INPUT_FORMAT_YUV;
371 ad->cfg.output_format = FORCE_CIF_OUTPUT_FORMAT;
372 ad->cfg.field_order = 0;
373 ad->cfg.yuv_order = 0;/*00 - UYVY*/
374 ad->cfg.href = 0;
375 ad->cfg.vsync = 0;
376 ad->cfg.frame_rate = 25;
377 ad->cfg.mipi_freq = NVP6188_LINK_FREQ_1458M;
378 break;
379
380 case CVSTD_1080P25:
381 ad->cfg.width = 1920;
382 ad->cfg.height = 1080;
383 ad->cfg.start_x = 0;
384 ad->cfg.start_y = 0;
385 ad->cfg.input_format = CIF_INPUT_FORMAT_YUV;
386 ad->cfg.output_format = FORCE_CIF_OUTPUT_FORMAT;
387 ad->cfg.field_order = 0;
388 ad->cfg.yuv_order = 0;/*00 - UYVY*/
389 ad->cfg.href = 0;
390 ad->cfg.vsync = 0;
391 ad->cfg.frame_rate = 25;
392 ad->cfg.mipi_freq = NVP6188_LINK_FREQ_1458M;
393 break;
394
395 case CVSTD_NTSC:
396 ad->cfg.width = 960;
397 ad->cfg.height = 480;
398 ad->cfg.start_x = 0;
399 ad->cfg.start_y = 0;
400 ad->cfg.input_format = CIF_INPUT_FORMAT_YUV;
401 ad->cfg.output_format = FORCE_CIF_OUTPUT_FORMAT;
402 ad->cfg.field_order = 0;
403 ad->cfg.yuv_order = 0;/*00 - UYVY*/
404 ad->cfg.href = 0;
405 ad->cfg.vsync = 0;
406 ad->cfg.frame_rate = 25;
407 ad->cfg.mipi_freq = NVP6188_LINK_FREQ_1458M;
408 break;
409
410 default:
411 ad->cfg.width = 1920;
412 ad->cfg.height = 1080;
413 ad->cfg.start_x = 0;
414 ad->cfg.start_y = 0;
415 ad->cfg.input_format = CIF_INPUT_FORMAT_YUV;
416 ad->cfg.output_format = FORCE_CIF_OUTPUT_FORMAT;
417 ad->cfg.field_order = 0;
418 ad->cfg.yuv_order = 0;/*00 - UYVY*/
419 ad->cfg.href = 0;
420 ad->cfg.vsync = 0;
421 ad->cfg.frame_rate = 25;
422 ad->cfg.mipi_freq = NVP6188_LINK_FREQ_1458M;
423 break;
424 }
425 ad->cfg.type = V4L2_MBUS_CSI2_DPHY;
426 ad->cfg.mbus_flags = V4L2_MBUS_CSI2_4_LANE | V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK |
427 V4L2_MBUS_CSI2_CHANNELS;
428 ad->cfg.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8;
429
430 switch (ad->cfg.mbus_flags & V4L2_MBUS_CSI2_LANES) {
431 case V4L2_MBUS_CSI2_1_LANE:
432 ad->cfg.lanes = 1;
433 break;
434 case V4L2_MBUS_CSI2_2_LANE:
435 ad->cfg.lanes = 2;
436 break;
437 case V4L2_MBUS_CSI2_3_LANE:
438 ad->cfg.lanes = 3;
439 break;
440 case V4L2_MBUS_CSI2_4_LANE:
441 ad->cfg.lanes = 4;
442 break;
443 default:
444 ad->cfg.lanes = 1;
445 break;
446 }
447
448 /* fix crop info from dts config */
449 for (i = 0; i < 4; i++) {
450 if ((ad->defrects[i].width == ad->cfg.width) &&
451 (ad->defrects[i].height == ad->cfg.height)) {
452 ad->cfg.start_x = ad->defrects[i].crop_x;
453 ad->cfg.start_y = ad->defrects[i].crop_y;
454 ad->cfg.width = ad->defrects[i].crop_width;
455 ad->cfg.height = ad->defrects[i].crop_height;
456 }
457 }
458 }
459
460 /* sensor register write */
nvp6188_write_reg(struct vehicle_ad_dev * ad,u8 reg,u8 val)461 static int nvp6188_write_reg(struct vehicle_ad_dev *ad, u8 reg, u8 val)
462 {
463 struct i2c_msg msg;
464 u8 buf[2];
465 int ret;
466
467 buf[0] = reg & 0xFF;
468 buf[1] = val;
469
470 msg.addr = ad->i2c_add;
471 msg.flags = 0;
472 msg.buf = buf;
473 msg.len = sizeof(buf);
474
475 ret = i2c_transfer(ad->adapter, &msg, 1);
476 if (ret >= 0) {
477 usleep_range(300, 400);
478 return 0;
479 }
480
481 VEHICLE_DGERR("nvp6188 write reg(0x%x val:0x%x) failed !\n", reg, val);
482
483 return ret;
484 }
485
nvp6188_write_array(struct vehicle_ad_dev * ad,const struct regval * regs,int size)486 static int nvp6188_write_array(struct vehicle_ad_dev *ad,
487 const struct regval *regs, int size)
488 {
489 int i, ret = 0;
490
491 i = 0;
492 while (i < size) {
493 ret = nvp6188_write_reg(ad, regs[i].addr, regs[i].val);
494 if (ret) {
495 VEHICLE_DGERR("%s failed !\n", __func__);
496 break;
497 }
498 i++;
499 }
500
501 return ret;
502 }
503
504 /* sensor register read */
nvp6188_read_reg(struct vehicle_ad_dev * ad,u8 reg,u8 * val)505 static int nvp6188_read_reg(struct vehicle_ad_dev *ad, u8 reg, u8 *val)
506 {
507 struct i2c_msg msg[2];
508 u8 buf[1];
509 int ret;
510
511 buf[0] = reg & 0xFF;
512
513 msg[0].addr = ad->i2c_add;
514 msg[0].flags = 0;
515 msg[0].buf = buf;
516 msg[0].len = sizeof(buf);
517
518 msg[1].addr = ad->i2c_add;
519 msg[1].flags = 0 | I2C_M_RD;
520 msg[1].buf = buf;
521 msg[1].len = 1;
522
523 ret = i2c_transfer(ad->adapter, msg, 2);
524 if (ret >= 0) {
525 *val = buf[0];
526 return 0;
527 }
528
529 VEHICLE_DGERR("nvp6188 read reg(0x%x) failed !\n", reg);
530
531 return ret;
532 }
533
nv6188_read_vfc(struct vehicle_ad_dev * ad,unsigned char ch)534 static unsigned char nv6188_read_vfc(struct vehicle_ad_dev *ad, unsigned char ch)
535 {
536 unsigned char ch_vfc = 0xff;
537
538 nvp6188_write_reg(ad, 0xff, 0x05 + ch);
539 nvp6188_read_reg(ad, 0xf0, &ch_vfc);
540 return ch_vfc;
541 }
542
nvp6188_read_all_vfc(struct vehicle_ad_dev * ad,u8 * ch_vfc)543 static __maybe_unused int nvp6188_read_all_vfc(struct vehicle_ad_dev *ad,
544 u8 *ch_vfc)
545 {
546 int ret = 0;
547 int check_cnt = 0, ch = 0;
548
549 ret = nvp6188_write_array(ad,
550 auto_detect_regs, ARRAY_SIZE(auto_detect_regs));
551 if (ret)
552 VEHICLE_DGERR("write auto_detect_regs failed %d", ret);
553
554 ret = -1;
555 while ((check_cnt++) < 50) {
556 for (ch = 0; ch < 4; ch++)
557 ch_vfc[ch] = nv6188_read_vfc(ad, ch);
558
559 if (ch_vfc[0] != 0xff || ch_vfc[1] != 0xff ||
560 ch_vfc[2] != 0xff || ch_vfc[3] != 0xff) {
561 ret = 0;
562 if (ch == 3) {
563 VEHICLE_DGERR("try check cnt %d", check_cnt);
564 break;
565 }
566 } else {
567 usleep_range(20 * 1000, 40 * 1000);
568 }
569 }
570
571 if (ret)
572 VEHICLE_DGERR("read vfc failed %d", ret);
573 else
574 VEHICLE_INFO("read vfc 0x%2x 0x%2x 0x%2x 0x%2x",
575 ch_vfc[0], ch_vfc[1], ch_vfc[2], ch_vfc[3]);
576
577 return ret;
578 }
579
nvp6188_auto_detect_fmt(struct vehicle_ad_dev * ad)580 static __maybe_unused int nvp6188_auto_detect_fmt(struct vehicle_ad_dev *ad)
581 {
582 int ret = 0;
583 int ch = 0;
584 unsigned char ch_vfc[4] = { 0xff, 0xff, 0xff, 0xff };
585 unsigned char val_13x70 = 0, val_13x71 = 0;
586
587 if (nvp6188_read_all_vfc(ad, ch_vfc))
588 return -1;
589 ch = ad->ad_chl;
590 // for (ch = 0; ch < 4; ch++) {
591 nvp6188_write_reg(ad, 0xFF, 0x13);
592 nvp6188_read_reg(ad, 0x70, &val_13x70);
593 val_13x70 |= (0x01 << ch);
594 nvp6188_write_reg(ad, 0x70, val_13x70);
595 nvp6188_read_reg(ad, 0x71, &val_13x71);
596 val_13x71 |= (0x01 << ch);
597 nvp6188_write_reg(ad, 0x71, val_13x71);
598 switch (ch_vfc[ch]) {
599 case NVP_RESO_960H_NSTC_VALUE:
600 VEHICLE_INFO("channel %d det 960h nstc", ch);
601 ad->channel_reso[ch] = NVP_RESO_960H_NSTC;
602 break;
603 case NVP_RESO_960H_PAL_VALUE:
604 VEHICLE_INFO("channel %d det 960h pal", ch);
605 ad->channel_reso[ch] = NVP_RESO_960H_PAL;
606 break;
607 case NVP_RESO_720P_NSTC_VALUE:
608 VEHICLE_INFO("channel %d det 720p nstc", ch);
609 ad->channel_reso[ch] = NVP_RESO_720P_NSTC;
610 break;
611 case NVP_RESO_720P_PAL_VALUE:
612 VEHICLE_INFO("channel %d det 720p pal", ch);
613 ad->channel_reso[ch] = NVP_RESO_720P_PAL;
614 break;
615 case NVP_RESO_1080P_NSTC_VALUE:
616 VEHICLE_INFO("channel %d det 1080p nstc", ch);
617 ad->channel_reso[ch] = NVP_RESO_1080P_NSTC;
618 break;
619 case NVP_RESO_1080P_PAL_VALUE:
620 VEHICLE_INFO("channel %d det 1080p pal", ch);
621 ad->channel_reso[ch] = NVP_RESO_1080P_PAL;
622 break;
623 case NVP_RESO_960P_NSTC_VALUE:
624 VEHICLE_INFO("channel %d det 960p nstc", ch);
625 ad->channel_reso[ch] = NVP_RESO_960P_NSTC;
626 break;
627 case NVP_RESO_960P_PAL_VALUE:
628 VEHICLE_INFO("channel %d det 960p pal", ch);
629 ad->channel_reso[ch] = NVP_RESO_960P_PAL;
630 break;
631 default:
632 VEHICLE_INFO("channel %d not detect, def 1080p pal\n", ch);
633 ad->channel_reso[ch] = NVP_RESO_1080P_PAL;
634 break;
635 }
636 // }
637 return ret;
638 }
639
640 //each channel setting
641 /*
642 * 960x480i
643 * ch : 0 ~ 3
644 * ntpal: 1:25p, 0:30p
645 */
nv6188_set_chn_960h(struct vehicle_ad_dev * ad,u8 ch,u8 ntpal)646 static __maybe_unused void nv6188_set_chn_960h(struct vehicle_ad_dev *ad, u8 ch,
647 u8 ntpal)
648 {
649 unsigned char val_0x54 = 0, val_20x01 = 0;
650
651 VEHICLE_INFO("%s ch %d ntpal %d", __func__, ch, ntpal);
652 nvp6188_write_reg(ad, 0xff, 0x00);
653 nvp6188_write_reg(ad, 0x08 + ch, ntpal ? 0xdd : 0xa0);
654 nvp6188_write_reg(ad, 0x18 + ch, 0x08);
655 nvp6188_write_reg(ad, 0x22 + ch * 4, 0x0b);
656 nvp6188_write_reg(ad, 0x23 + ch * 4, 0x41);
657 nvp6188_write_reg(ad, 0x30 + ch, 0x12);
658 nvp6188_write_reg(ad, 0x34 + ch, 0x01);
659 nvp6188_read_reg(ad, 0x54, &val_0x54);
660 if (ntpal)
661 val_0x54 &= ~(0x10 << ch);
662 else
663 val_0x54 |= (0x10 << ch);
664 nvp6188_write_reg(ad, 0x54, val_0x54);
665 nvp6188_write_reg(ad, 0x58 + ch, ntpal ? 0x80 : 0x90);
666 nvp6188_write_reg(ad, 0x5c + ch, ntpal ? 0xbe : 0xbc);
667 nvp6188_write_reg(ad, 0x64 + ch, ntpal ? 0xa0 : 0x81);
668 nvp6188_write_reg(ad, 0x81 + ch, ntpal ? 0xf0 : 0xe0);
669 nvp6188_write_reg(ad, 0x85 + ch, 0x00);
670 nvp6188_write_reg(ad, 0x89 + ch, 0x00);
671 nvp6188_write_reg(ad, ch + 0x8e, 0x00);
672 nvp6188_write_reg(ad, 0xa0 + ch, 0x05);
673
674 nvp6188_write_reg(ad, 0xff, 0x01);
675 nvp6188_write_reg(ad, 0x84 + ch, 0x02);
676 nvp6188_write_reg(ad, 0x88 + ch, 0x00);
677 nvp6188_write_reg(ad, 0x8c + ch, 0x40);
678 nvp6188_write_reg(ad, 0xa0 + ch, 0x20);
679 nvp6188_write_reg(ad, 0xed, 0x00);
680
681 nvp6188_write_reg(ad, 0xff, 0x05 + ch);
682 nvp6188_write_reg(ad, 0x01, 0x22);
683 nvp6188_write_reg(ad, 0x05, 0x00);
684 nvp6188_write_reg(ad, 0x08, 0x55);
685 nvp6188_write_reg(ad, 0x25, 0xdc);
686 nvp6188_write_reg(ad, 0x28, 0x80);
687 nvp6188_write_reg(ad, 0x2f, 0x00);
688 nvp6188_write_reg(ad, 0x30, 0xe0);
689 nvp6188_write_reg(ad, 0x31, 0x43);
690 nvp6188_write_reg(ad, 0x32, 0xa2);
691 nvp6188_write_reg(ad, 0x47, 0x04);
692 nvp6188_write_reg(ad, 0x50, 0x84);
693 nvp6188_write_reg(ad, 0x57, 0x00);
694 nvp6188_write_reg(ad, 0x58, 0x77);
695 nvp6188_write_reg(ad, 0x5b, 0x43);
696 nvp6188_write_reg(ad, 0x5c, 0x78);
697 nvp6188_write_reg(ad, 0x5f, 0x00);
698 nvp6188_write_reg(ad, 0x62, 0x20);
699 nvp6188_write_reg(ad, 0x7b, 0x00);
700 nvp6188_write_reg(ad, 0x7c, 0x01);
701 nvp6188_write_reg(ad, 0x7d, 0x80);
702 nvp6188_write_reg(ad, 0x80, 0x00);
703 nvp6188_write_reg(ad, 0x90, 0x01);
704 nvp6188_write_reg(ad, 0xa9, 0x00);
705 nvp6188_write_reg(ad, 0xb5, 0x00);
706 nvp6188_write_reg(ad, 0xb8, 0xb9);
707 nvp6188_write_reg(ad, 0xb9, 0x72);
708 nvp6188_write_reg(ad, 0xd1, 0x00);
709 nvp6188_write_reg(ad, 0xd5, 0x80);
710
711 nvp6188_write_reg(ad, 0xff, 0x09);
712 nvp6188_write_reg(ad, 0x96 + ch * 0x20, 0x10);
713 nvp6188_write_reg(ad, 0x98 + ch * 0x20, ntpal ? 0xc0 : 0xe0);
714 nvp6188_write_reg(ad, ch * 0x20 + 0x9e, 0x00);
715
716 nvp6188_write_reg(ad, 0xff, _MAR_BANK_);
717 nvp6188_read_reg(ad, 0x01, &val_20x01);
718 val_20x01 &= (~(0x03 << (ch * 2)));
719 val_20x01 |= (0x02 << (ch * 2));
720 nvp6188_write_reg(ad, 0x01, val_20x01);
721 nvp6188_write_reg(ad, 0x12 + ch * 2, 0xe0);
722 nvp6188_write_reg(ad, 0x13 + ch * 2, 0x01);
723 }
724
725 //each channel setting
726 /*
727 * 1280x720p
728 * ch : 0 ~ 3
729 * ntpal: 1:25p, 0:30p
730 */
nv6188_set_chn_720p(struct vehicle_ad_dev * ad,u8 ch,u8 ntpal)731 static __maybe_unused void nv6188_set_chn_720p(struct vehicle_ad_dev *ad, u8 ch,
732 u8 ntpal)
733 {
734 unsigned char val_0x54 = 0, val_20x01 = 0;
735
736 VEHICLE_INFO("%s ch %d ntpal %d", __func__, ch, ntpal);
737 nvp6188_write_reg(ad, 0xff, 0x00);
738 nvp6188_write_reg(ad, 0x08 + ch, 0x00);
739 nvp6188_write_reg(ad, 0x18 + ch, 0x3f);
740 nvp6188_write_reg(ad, 0x30 + ch, 0x12);
741 nvp6188_write_reg(ad, 0x34 + ch, 0x00);
742 nvp6188_read_reg(ad, 0x54, &val_0x54);
743 val_0x54 &= ~(0x10 << ch);
744 nvp6188_write_reg(ad, 0x54, val_0x54);
745 nvp6188_write_reg(ad, 0x58 + ch, ntpal ? 0x80 : 0x80);
746 nvp6188_write_reg(ad, 0x5c + ch, ntpal ? 0x00 : 0x00);
747 nvp6188_write_reg(ad, 0x64 + ch, ntpal ? 0x01 : 0x01);
748 nvp6188_write_reg(ad, 0x81 + ch, ntpal ? 0x0d : 0x0c);
749 nvp6188_write_reg(ad, 0x85 + ch, 0x00);
750 nvp6188_write_reg(ad, 0x89 + ch, 0x00);
751 nvp6188_write_reg(ad, ch + 0x8e, 0x00);
752 nvp6188_write_reg(ad, 0xa0 + ch, 0x05);
753
754 nvp6188_write_reg(ad, 0xff, 0x01);
755 nvp6188_write_reg(ad, 0x84 + ch, 0x02);
756 nvp6188_write_reg(ad, 0x88 + ch, 0x00);
757 nvp6188_write_reg(ad, 0x8c + ch, 0x40);
758 nvp6188_write_reg(ad, 0xa0 + ch, 0x20);
759
760 nvp6188_write_reg(ad, 0xff, 0x05 + ch);
761 nvp6188_write_reg(ad, 0x01, 0x22);
762 nvp6188_write_reg(ad, 0x05, 0x04);
763 nvp6188_write_reg(ad, 0x08, 0x55);
764 nvp6188_write_reg(ad, 0x25, 0xdc);
765 nvp6188_write_reg(ad, 0x28, 0x80);
766 nvp6188_write_reg(ad, 0x2f, 0x00);
767 nvp6188_write_reg(ad, 0x30, 0xe0);
768 nvp6188_write_reg(ad, 0x31, 0x43);
769 nvp6188_write_reg(ad, 0x32, 0xa2);
770 nvp6188_write_reg(ad, 0x47, 0xee);
771 nvp6188_write_reg(ad, 0x50, 0xc6);
772 nvp6188_write_reg(ad, 0x57, 0x00);
773 nvp6188_write_reg(ad, 0x58, 0x77);
774 nvp6188_write_reg(ad, 0x5b, 0x41);
775 nvp6188_write_reg(ad, 0x5c, 0x7C);
776 nvp6188_write_reg(ad, 0x5f, 0x00);
777 nvp6188_write_reg(ad, 0x62, 0x20);
778 nvp6188_write_reg(ad, 0x7b, 0x11);
779 nvp6188_write_reg(ad, 0x7c, 0x01);
780 nvp6188_write_reg(ad, 0x7d, 0x80);
781 nvp6188_write_reg(ad, 0x80, 0x00);
782 nvp6188_write_reg(ad, 0x90, 0x01);
783 nvp6188_write_reg(ad, 0xa9, 0x00);
784 nvp6188_write_reg(ad, 0xb5, 0x40);
785 nvp6188_write_reg(ad, 0xb8, 0x39);
786 nvp6188_write_reg(ad, 0xb9, 0x72);
787 nvp6188_write_reg(ad, 0xd1, 0x00);
788 nvp6188_write_reg(ad, 0xd5, 0x80);
789
790 nvp6188_write_reg(ad, 0xff, 0x09);
791 nvp6188_write_reg(ad, 0x96 + ch * 0x20, 0x00);
792 nvp6188_write_reg(ad, 0x98 + ch * 0x20, 0x00);
793 nvp6188_write_reg(ad, ch * 0x20 + 0x9e, 0x00);
794
795 nvp6188_write_reg(ad, 0xff, _MAR_BANK_);
796 nvp6188_read_reg(ad, 0x01, &val_20x01);
797 val_20x01 &= (~(0x03 << (ch * 2)));
798 val_20x01 |= (0x01 << (ch * 2));
799 nvp6188_write_reg(ad, 0x01, val_20x01);
800 nvp6188_write_reg(ad, 0x12 + ch * 2, 0x80);
801 nvp6188_write_reg(ad, 0x13 + ch * 2, 0x02);
802 }
803
804 //each channel setting
805 /*
806 * 1920x1080p
807 * ch : 0 ~ 3
808 * ntpal: 1:25p, 0:30p
809 */
nv6188_set_chn_1080p(struct vehicle_ad_dev * ad,u8 ch,u8 ntpal)810 static __maybe_unused void nv6188_set_chn_1080p(struct vehicle_ad_dev *ad, u8 ch,
811 u8 ntpal)
812 {
813 unsigned char val_0x54 = 0, val_20x01 = 0;
814
815 VEHICLE_INFO("%s ch %d ntpal %d", __func__, ch, ntpal);
816 nvp6188_write_reg(ad, 0xff, 0x00);
817 nvp6188_write_reg(ad, 0x08 + ch, 0x00);
818 nvp6188_write_reg(ad, 0x18 + ch, 0x3f);
819 nvp6188_write_reg(ad, 0x30 + ch, 0x12);
820 nvp6188_write_reg(ad, 0x34 + ch, 0x00);
821 nvp6188_read_reg(ad, 0x54, &val_0x54);
822 val_0x54 &= ~(0x10 << ch);
823 nvp6188_write_reg(ad, 0x54, val_0x54);
824 nvp6188_write_reg(ad, 0x58 + ch, ntpal ? 0x80 : 0x80);
825 nvp6188_write_reg(ad, 0x5c + ch, ntpal ? 0x00 : 0x00);
826 nvp6188_write_reg(ad, 0x64 + ch, ntpal ? 0x01 : 0x01);
827 nvp6188_write_reg(ad, 0x81 + ch, ntpal ? 0x03 : 0x02);
828 nvp6188_write_reg(ad, 0x85 + ch, 0x00);
829 nvp6188_write_reg(ad, 0x89 + ch, 0x10);
830 nvp6188_write_reg(ad, ch + 0x8e, 0x00);
831 nvp6188_write_reg(ad, 0xa0 + ch, 0x05);
832
833 nvp6188_write_reg(ad, 0xff, 0x01);
834 nvp6188_write_reg(ad, 0x84 + ch, 0x02);
835 nvp6188_write_reg(ad, 0x88 + ch, 0x00);
836 nvp6188_write_reg(ad, 0x8c + ch, 0x40);
837 nvp6188_write_reg(ad, 0xa0 + ch, 0x20);
838
839 nvp6188_write_reg(ad, 0xff, 0x05 + ch);
840 nvp6188_write_reg(ad, 0x01, 0x22);
841 nvp6188_write_reg(ad, 0x05, 0x04);
842 nvp6188_write_reg(ad, 0x08, 0x55);
843 nvp6188_write_reg(ad, 0x25, 0xdc);
844 nvp6188_write_reg(ad, 0x28, 0x80);
845 nvp6188_write_reg(ad, 0x2f, 0x00);
846 nvp6188_write_reg(ad, 0x30, 0xe0);
847 nvp6188_write_reg(ad, 0x31, 0x41);
848 nvp6188_write_reg(ad, 0x32, 0xa2);
849 nvp6188_write_reg(ad, 0x47, 0xee);
850 nvp6188_write_reg(ad, 0x50, 0xc6);
851 nvp6188_write_reg(ad, 0x57, 0x00);
852 nvp6188_write_reg(ad, 0x58, 0x77);
853 nvp6188_write_reg(ad, 0x5b, 0x41);
854 nvp6188_write_reg(ad, 0x5c, 0x7C);
855 nvp6188_write_reg(ad, 0x5f, 0x00);
856 nvp6188_write_reg(ad, 0x62, 0x20);
857 nvp6188_write_reg(ad, 0x7b, 0x11);
858 nvp6188_write_reg(ad, 0x7c, 0x01);
859 nvp6188_write_reg(ad, 0x7d, 0x80);
860 nvp6188_write_reg(ad, 0x80, 0x00);
861 nvp6188_write_reg(ad, 0x90, 0x01);
862 nvp6188_write_reg(ad, 0xa9, 0x00);
863 nvp6188_write_reg(ad, 0xb5, 0x40);
864 nvp6188_write_reg(ad, 0xb8, 0x39);
865 nvp6188_write_reg(ad, 0xb9, 0x72);
866 nvp6188_write_reg(ad, 0xd1, 0x00);
867 nvp6188_write_reg(ad, 0xd5, 0x80);
868
869 nvp6188_write_reg(ad, 0xff, 0x09);
870 nvp6188_write_reg(ad, 0x96 + ch * 0x20, 0x00);
871 nvp6188_write_reg(ad, 0x98 + ch * 0x20, 0x00);
872 nvp6188_write_reg(ad, ch * 0x20 + 0x9e, 0x00);
873
874 nvp6188_write_reg(ad, 0xff, _MAR_BANK_);
875 nvp6188_read_reg(ad, 0x01, &val_20x01);
876 val_20x01 &= (~(0x03 << (ch * 2)));
877 nvp6188_write_reg(ad, 0x01, val_20x01);
878 nvp6188_write_reg(ad, 0x12 + ch * 2, 0xc0);
879 nvp6188_write_reg(ad, 0x13 + ch * 2, 0x03);
880 }
881
nvp6188_manual_mode(struct vehicle_ad_dev * ad)882 static __maybe_unused void nvp6188_manual_mode(struct vehicle_ad_dev *ad)
883 {
884 int i, reso;
885
886 for (i = 3; i >= 0; i--) {
887 reso = ad->channel_reso[i];
888 switch (reso) {
889 case NVP_RESO_960H_PAL:
890 nv6188_set_chn_960h(ad, i, 1);
891 break;
892 case NVP_RESO_720P_PAL:
893 nv6188_set_chn_720p(ad, i, 1);
894 break;
895 case NVP_RESO_1080P_PAL:
896 nv6188_set_chn_1080p(ad, i, 1);
897 break;
898 case NVP_RESO_960H_NSTC:
899 nv6188_set_chn_960h(ad, i, 0);
900 break;
901 case NVP_RESO_720P_NSTC:
902 nv6188_set_chn_720p(ad, i, 0);
903 break;
904 case NVP_RESO_1080P_NSTC:
905 nv6188_set_chn_1080p(ad, i, 0);
906 break;
907 default:
908 nv6188_set_chn_1080p(ad, i, 1);
909 break;
910 }
911 }
912 }
913
nvp6188_channel_set(struct vehicle_ad_dev * ad,int channel)914 void nvp6188_channel_set(struct vehicle_ad_dev *ad, int channel)
915 {
916 ad->ad_chl = channel;
917 VEHICLE_DG("%s, channel set(%d)", __func__, ad->ad_chl);
918 }
919
nvp6188_ad_get_cfg(struct vehicle_cfg ** cfg)920 int nvp6188_ad_get_cfg(struct vehicle_cfg **cfg)
921 {
922 if (!nvp6188_g_addev)
923 return -1;
924
925 switch (cvstd_state) {
926 case VIDEO_UNPLUG:
927 nvp6188_g_addev->cfg.ad_ready = false;
928 break;
929 case VIDEO_LOCKED:
930 nvp6188_g_addev->cfg.ad_ready = true;
931 break;
932 case VIDEO_IN:
933 nvp6188_g_addev->cfg.ad_ready = false;
934 break;
935 }
936
937 nvp6188_g_addev->cfg.ad_ready = true;
938
939 *cfg = &nvp6188_g_addev->cfg;
940
941 return 0;
942 }
943
nvp6188_ad_check_cif_error(struct vehicle_ad_dev * ad,int last_line)944 void nvp6188_ad_check_cif_error(struct vehicle_ad_dev *ad, int last_line)
945 {
946 VEHICLE_INFO("%s, last_line %d\n", __func__, last_line);
947
948 if (last_line < 1)
949 return;
950
951 ad->cif_error_last_line = last_line;
952 if (cvstd_mode == CVSTD_PAL) {
953 if (last_line == FORCE_NTSC_HEIGHT) {
954 if (ad->state_check_work.state_check_wq)
955 queue_delayed_work(
956 ad->state_check_work.state_check_wq,
957 &ad->state_check_work.work,
958 msecs_to_jiffies(0));
959 }
960 } else if (cvstd_mode == CVSTD_NTSC) {
961 if (last_line == FORCE_PAL_HEIGHT) {
962 if (ad->state_check_work.state_check_wq)
963 queue_delayed_work(
964 ad->state_check_work.state_check_wq,
965 &ad->state_check_work.work,
966 msecs_to_jiffies(0));
967 }
968 } else if (cvstd_mode == CVSTD_1080P25) {
969 if (last_line == FORCE_1080P_HEIGHT) {
970 if (ad->state_check_work.state_check_wq)
971 queue_delayed_work(
972 ad->state_check_work.state_check_wq,
973 &ad->state_check_work.work,
974 msecs_to_jiffies(0));
975 }
976 } else if (cvstd_mode == CVSTD_720P25) {
977 if (last_line == FORCE_720P_HEIGHT) {
978 if (ad->state_check_work.state_check_wq)
979 queue_delayed_work(
980 ad->state_check_work.state_check_wq,
981 &ad->state_check_work.work,
982 msecs_to_jiffies(0));
983 }
984 }
985 }
986
nvp6188_check_id(struct vehicle_ad_dev * ad)987 int nvp6188_check_id(struct vehicle_ad_dev *ad)
988 {
989 int ret = 0;
990 u8 pid = 0;
991
992 ret = vehicle_sensor_write(ad, 0xFF, 0x00);
993 ret |= vehicle_sensor_read(ad, 0xf4, &pid);
994 if (ret)
995 return ret;
996
997 if (pid != NVP6188_CHIP_ID && pid != NVP6188_CHIP_ID2) {
998 VEHICLE_DGERR("%s: expected 0xd0/d3, detected: 0x%02x !",
999 ad->ad_name, pid);
1000 ret = -EINVAL;
1001 } else {
1002 VEHICLE_INFO("%s Found NVP6188 sensor: id(0x%2x) !\n", __func__, pid);
1003 }
1004
1005 return ret;
1006 }
1007
__nvp6188_start_stream(struct vehicle_ad_dev * ad)1008 static int __nvp6188_start_stream(struct vehicle_ad_dev *ad)
1009 {
1010 int ret;
1011 int array_size = 0;
1012
1013 array_size = ARRAY_SIZE(common_setting_1458M_regs);
1014
1015 ret = nvp6188_write_array(ad,
1016 common_setting_1458M_regs, array_size);
1017 if (ret) {
1018 VEHICLE_INFO(" nvp6188 start stream: wrote global reg failed");
1019 return ret;
1020 }
1021
1022 nvp6188_auto_detect_fmt(ad);
1023 nvp6188_manual_mode(ad);
1024 nvp6188_write_reg(ad, 0xff, 0x20);
1025 nvp6188_write_reg(ad, 0xff, 0xff);
1026 msleep(50);
1027
1028 return 0;
1029 }
1030
__nvp6188_stop_stream(struct vehicle_ad_dev * ad)1031 static int __nvp6188_stop_stream(struct vehicle_ad_dev *ad)
1032 {
1033 nvp6188_write_reg(ad, 0xff, 0x20);
1034 nvp6188_write_reg(ad, 0x00, 0x00);
1035 nvp6188_write_reg(ad, 0x40, 0x01);
1036 nvp6188_write_reg(ad, 0x40, 0x00);
1037
1038 return 0;
1039 }
1040
nvp6188_stream(struct vehicle_ad_dev * ad,int enable)1041 int nvp6188_stream(struct vehicle_ad_dev *ad, int enable)
1042 {
1043 VEHICLE_INFO("%s on(%d)\n", __func__, enable);
1044
1045 g_nvp6188_streaming = (enable != 0);
1046 if (g_nvp6188_streaming) {
1047 __nvp6188_start_stream(ad);
1048 if (ad->state_check_work.state_check_wq)
1049 queue_delayed_work(ad->state_check_work.state_check_wq,
1050 &ad->state_check_work.work, msecs_to_jiffies(200));
1051 } else {
1052 __nvp6188_stop_stream(ad);
1053 if (ad->state_check_work.state_check_wq)
1054 cancel_delayed_work_sync(&ad->state_check_work.work);
1055 VEHICLE_DG("%s(%d): cancel_queue_delayed_work!\n", __func__, __LINE__);
1056 }
1057
1058 return 0;
1059 }
1060
nvp6188_power_on(struct vehicle_ad_dev * ad)1061 static void nvp6188_power_on(struct vehicle_ad_dev *ad)
1062 {
1063 if (gpio_is_valid(ad->power)) {
1064 gpio_request(ad->power, "nvp6188_power");
1065 gpio_direction_output(ad->power, ad->pwr_active);
1066 /* gpio_set_value(ad->power, ad->pwr_active); */
1067 }
1068
1069 if (gpio_is_valid(ad->powerdown)) {
1070 gpio_request(ad->powerdown, "nvp6188_pwd");
1071 gpio_direction_output(ad->powerdown, 1);
1072 /* gpio_set_value(ad->powerdown, !ad->pwdn_active); */
1073 }
1074
1075 if (gpio_is_valid(ad->reset)) {
1076 gpio_request(ad->reset, "nvp6188_rst");
1077 gpio_direction_output(ad->reset, 0);
1078 usleep_range(1500, 2000);
1079 gpio_direction_output(ad->reset, 1);
1080 }
1081 }
1082
nvp6188_power_off(struct vehicle_ad_dev * ad)1083 static void nvp6188_power_off(struct vehicle_ad_dev *ad)
1084 {
1085 if (gpio_is_valid(ad->reset))
1086 gpio_free(ad->reset);
1087 if (gpio_is_valid(ad->power))
1088 gpio_free(ad->power);
1089 if (gpio_is_valid(ad->powerdown))
1090 gpio_free(ad->powerdown);
1091 }
1092
nvp6188_auto_detect_hotplug(struct vehicle_ad_dev * ad)1093 static __maybe_unused int nvp6188_auto_detect_hotplug(struct vehicle_ad_dev *ad)
1094 {
1095 nvp6188_write_reg(ad, 0xff, 0x00);
1096 nvp6188_read_reg(ad, 0xa8, &ad->detect_status);
1097
1098 ad->detect_status = ~ad->detect_status;
1099
1100 return 0;
1101 }
1102
nvp6188_check_state_work(struct work_struct * work)1103 static void nvp6188_check_state_work(struct work_struct *work)
1104 {
1105 struct vehicle_ad_dev *ad;
1106
1107 ad = nvp6188_g_addev;
1108 nvp6188_auto_detect_hotplug(ad);
1109
1110 if (ad->detect_status != ad->last_detect_status) {
1111 ad->last_detect_status = ad->detect_status;
1112 vehicle_ad_stat_change_notify();
1113 }
1114
1115 if (g_nvp6188_streaming) {
1116 queue_delayed_work(ad->state_check_work.state_check_wq,
1117 &ad->state_check_work.work, msecs_to_jiffies(100));
1118 }
1119 }
1120
nvp6188_ad_deinit(void)1121 int nvp6188_ad_deinit(void)
1122 {
1123 struct vehicle_ad_dev *ad;
1124
1125 ad = nvp6188_g_addev;
1126
1127 if (!ad)
1128 return -1;
1129
1130 if (ad->state_check_work.state_check_wq) {
1131 cancel_delayed_work_sync(&ad->state_check_work.work);
1132 flush_delayed_work(&ad->state_check_work.work);
1133 flush_workqueue(ad->state_check_work.state_check_wq);
1134 destroy_workqueue(ad->state_check_work.state_check_wq);
1135 }
1136
1137 nvp6188_power_off(ad);
1138
1139 return 0;
1140 }
1141
get_ad_mode_from_fix_format(int fix_format)1142 static __maybe_unused int get_ad_mode_from_fix_format(int fix_format)
1143 {
1144 int mode = -1;
1145
1146 switch (fix_format) {
1147 case AD_FIX_FORMAT_PAL:
1148 case AD_FIX_FORMAT_NTSC:
1149 case AD_FIX_FORMAT_720P_50FPS:
1150 case AD_FIX_FORMAT_720P_30FPS:
1151 case AD_FIX_FORMAT_720P_25FPS:
1152 mode = CVSTD_720P25;
1153 break;
1154 case AD_FIX_FORMAT_1080P_30FPS:
1155 case AD_FIX_FORMAT_1080P_25FPS:
1156
1157 default:
1158 mode = CVSTD_720P25;
1159 break;
1160 }
1161
1162 return mode;
1163 }
1164
nvp6188_ad_init(struct vehicle_ad_dev * ad)1165 int nvp6188_ad_init(struct vehicle_ad_dev *ad)
1166 {
1167 int val;
1168 int i = 0;
1169
1170 nvp6188_g_addev = ad;
1171
1172 /* 1. i2c init */
1173 while (ad->adapter == NULL) {
1174 ad->adapter = i2c_get_adapter(ad->i2c_chl);
1175 usleep_range(10000, 12000);
1176 }
1177 if (ad->adapter == NULL)
1178 return -ENODEV;
1179
1180 if (!i2c_check_functionality(ad->adapter, I2C_FUNC_I2C))
1181 return -EIO;
1182
1183 /* 2. ad power on sequence */
1184 nvp6188_power_on(ad);
1185
1186 while (++i < 5) {
1187 usleep_range(1000, 1200);
1188 val = vehicle_generic_sensor_read(ad, 0xf0);
1189 if (val != 0xff)
1190 break;
1191 VEHICLE_INFO("nvp6188_init i2c_reg_read fail\n");
1192 }
1193
1194 nvp6188_reinit_parameter(ad, cvstd_mode);
1195 ad->last_detect_status = true;
1196
1197 /* create workqueue to detect signal change */
1198 INIT_DELAYED_WORK(&ad->state_check_work.work, nvp6188_check_state_work);
1199 ad->state_check_work.state_check_wq =
1200 create_singlethread_workqueue("vehicle-ad-nvp6188");
1201
1202 queue_delayed_work(ad->state_check_work.state_check_wq,
1203 &ad->state_check_work.work, msecs_to_jiffies(100));
1204
1205 return 0;
1206 }
1207