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