xref: /OK3568_Linux_fs/kernel/drivers/video/rockchip/vehicle/vehicle_main.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * drivers/video/rockchip/video/vehicle_main.c
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2022 Rockchip Electronics Co.Ltd
6*4882a593Smuzhiyun  * Authors:
7*4882a593Smuzhiyun  *	Zhiqin Wei <wzq@rock-chips.com>
8*4882a593Smuzhiyun  *      <randy.wang@rock-chips.com>
9*4882a593Smuzhiyun  *	Jianwei Fan <jianwei.fan@rock-chips.com>
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #define CAMMODULE_NAME    "vehicle_main"
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/delay.h>
17*4882a593Smuzhiyun #include <linux/errno.h>
18*4882a593Smuzhiyun #include <linux/kernel.h>
19*4882a593Smuzhiyun #include <linux/time.h>
20*4882a593Smuzhiyun #include <linux/platform_device.h>
21*4882a593Smuzhiyun #include <linux/init.h>
22*4882a593Smuzhiyun #include <linux/kthread.h>
23*4882a593Smuzhiyun #include <linux/fb.h>
24*4882a593Smuzhiyun #include <linux/clk.h>
25*4882a593Smuzhiyun #include <linux/clkdev.h>
26*4882a593Smuzhiyun #include <linux/completion.h>
27*4882a593Smuzhiyun #include <linux/wakelock.h>
28*4882a593Smuzhiyun #include <linux/of_gpio.h>
29*4882a593Smuzhiyun #include <linux/of_address.h>
30*4882a593Smuzhiyun #include <linux/of_irq.h>
31*4882a593Smuzhiyun #include <linux/pm_runtime.h>
32*4882a593Smuzhiyun #include <linux/interrupt.h>
33*4882a593Smuzhiyun #include "vehicle_flinger.h"
34*4882a593Smuzhiyun #include "vehicle_cfg.h"
35*4882a593Smuzhiyun #include "vehicle_ad.h"
36*4882a593Smuzhiyun #include "vehicle_main.h"
37*4882a593Smuzhiyun #include "vehicle_cif.h"
38*4882a593Smuzhiyun #include "vehicle_gpio.h"
39*4882a593Smuzhiyun #include <linux/version.h>
40*4882a593Smuzhiyun #include "../../../media/platform/rockchip/cif/dev.h"
41*4882a593Smuzhiyun #include "../../../phy/rockchip/phy-rockchip-csi2-dphy-common.h"
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun #define DRIVER_VERSION		KERNEL_VERSION(0, 0x03, 0x02)
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun static bool flinger_inited;
46*4882a593Smuzhiyun static bool TEST_GPIO = true;
47*4882a593Smuzhiyun static bool dvr_apk_need_start;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun enum {
50*4882a593Smuzhiyun 	STATE_CLOSE = 0,
51*4882a593Smuzhiyun 	STATE_OPEN,
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun struct vehicle {
55*4882a593Smuzhiyun 	struct device	*dev;
56*4882a593Smuzhiyun 	struct pinctrl *pinctrl;
57*4882a593Smuzhiyun 	struct pinctrl_state *pins_default;
58*4882a593Smuzhiyun 	struct wake_lock wake_lock;
59*4882a593Smuzhiyun 	struct gpio_detect gpio_data;
60*4882a593Smuzhiyun 	struct vehicle_cif cif;
61*4882a593Smuzhiyun 	struct vehicle_ad_dev ad;
62*4882a593Smuzhiyun 	int mirror;
63*4882a593Smuzhiyun 	wait_queue_head_t vehicle_wait;
64*4882a593Smuzhiyun 	atomic_t vehicle_atomic;
65*4882a593Smuzhiyun 	int state;
66*4882a593Smuzhiyun 	bool android_is_ready;
67*4882a593Smuzhiyun 	bool gpio_over;
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static struct vehicle *g_vehicle;
71*4882a593Smuzhiyun 
vehicle_parse_dt(struct vehicle * vehicle_info)72*4882a593Smuzhiyun static int vehicle_parse_dt(struct vehicle *vehicle_info)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	struct device	*dev = vehicle_info->dev;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	/*  1. pinctrl */
77*4882a593Smuzhiyun 	vehicle_info->pinctrl = devm_pinctrl_get(dev);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	if (IS_ERR(vehicle_info->pinctrl)) {
80*4882a593Smuzhiyun 		dev_err(dev, "pinctrl get failed, maybe unuse\n");
81*4882a593Smuzhiyun 	} else {
82*4882a593Smuzhiyun 		vehicle_info->pins_default = pinctrl_lookup_state(vehicle_info->pinctrl,
83*4882a593Smuzhiyun 				"default");
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 		if (IS_ERR(vehicle_info->pins_default))
86*4882a593Smuzhiyun 			dev_err(dev, "get default pinstate failed\n");
87*4882a593Smuzhiyun 	}
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	return 0;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
vehicle_ad_stat_change_notify(void)92*4882a593Smuzhiyun void vehicle_ad_stat_change_notify(void)
93*4882a593Smuzhiyun {
94*4882a593Smuzhiyun 	if (g_vehicle) {
95*4882a593Smuzhiyun 		VEHICLE_INFO("ad state change! set atpmic to 1!\n");
96*4882a593Smuzhiyun 		atomic_set(&g_vehicle->vehicle_atomic, 1);
97*4882a593Smuzhiyun 	}
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun 
vehicle_cif_stat_change_notify(void)100*4882a593Smuzhiyun void vehicle_cif_stat_change_notify(void)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	if (g_vehicle) {
103*4882a593Smuzhiyun 		VEHICLE_INFO("cif state change! set atpmic to 1!\n");
104*4882a593Smuzhiyun 		atomic_set(&g_vehicle->vehicle_atomic, 1);
105*4882a593Smuzhiyun 	}
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
vehicle_gpio_stat_change_notify(void)108*4882a593Smuzhiyun void vehicle_gpio_stat_change_notify(void)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun 	if (g_vehicle && !g_vehicle->gpio_over) {
111*4882a593Smuzhiyun 		VEHICLE_INFO("reverse gpio state change! set atpmic to 1!\n");
112*4882a593Smuzhiyun 		atomic_set(&g_vehicle->vehicle_atomic, 1);
113*4882a593Smuzhiyun 	}
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
vehicle_cif_error_notify(int last_line)116*4882a593Smuzhiyun void vehicle_cif_error_notify(int last_line)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun 	if (g_vehicle) {
119*4882a593Smuzhiyun 		VEHICLE_INFO("cif error notify\n");
120*4882a593Smuzhiyun 		vehicle_ad_check_cif_error(&g_vehicle->ad, last_line);
121*4882a593Smuzhiyun 	}
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun 
vehicle_open(struct vehicle_cfg * v_cfg)124*4882a593Smuzhiyun static void vehicle_open(struct vehicle_cfg *v_cfg)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun 	VEHICLE_INFO("%s enter: android_is_ready ?= %d",
127*4882a593Smuzhiyun 			__func__, g_vehicle->android_is_ready);
128*4882a593Smuzhiyun 	vehicle_flinger_reverse_open(v_cfg, g_vehicle->android_is_ready);
129*4882a593Smuzhiyun 	vehicle_cif_reverse_open(v_cfg);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
vehicle_close(void)132*4882a593Smuzhiyun static void vehicle_close(void)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	vehicle_cif_reverse_close();
135*4882a593Smuzhiyun 	vehicle_flinger_reverse_close(g_vehicle->android_is_ready);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
vehicle_open_close(void)138*4882a593Smuzhiyun static void vehicle_open_close(void)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	vehicle_cif_reverse_close();
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
vehicle_state_change(struct vehicle * v)143*4882a593Smuzhiyun static int vehicle_state_change(struct vehicle *v)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun 	struct vehicle_cfg *v_cfg;
146*4882a593Smuzhiyun 	struct gpio_detect *gpiod = &v->gpio_data;
147*4882a593Smuzhiyun 	bool gpio_reverse_on;
148*4882a593Smuzhiyun 	int ret = 0;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	/*  1. get ad sensor cfg */
151*4882a593Smuzhiyun 	v_cfg = vehicle_ad_get_vehicle_cfg();
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	if (!v_cfg) {
154*4882a593Smuzhiyun 		VEHICLE_DGERR("v_cfg is NULL, if for test continue.\n");
155*4882a593Smuzhiyun 		return -ENODEV;
156*4882a593Smuzhiyun 	}
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	if (!flinger_inited) {
159*4882a593Smuzhiyun 		do {
160*4882a593Smuzhiyun 			/*  2. flinger */
161*4882a593Smuzhiyun 			VEHICLE_DG("%s: flinger init start\r\n", __func__);
162*4882a593Smuzhiyun 			ret = vehicle_flinger_init(v->dev, v_cfg);
163*4882a593Smuzhiyun 			if (ret < 0) {
164*4882a593Smuzhiyun 				VEHICLE_DG("rk_vehicle_system_main: flinger init failed\r\n");
165*4882a593Smuzhiyun 				msleep(20);
166*4882a593Smuzhiyun 			}
167*4882a593Smuzhiyun 		} while (ret);
168*4882a593Smuzhiyun 	}
169*4882a593Smuzhiyun 	VEHICLE_DG("%s: flinger init success\r\n", __func__);
170*4882a593Smuzhiyun 	flinger_inited = true;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	gpio_reverse_on = vehicle_gpio_reverse_check(gpiod);
173*4882a593Smuzhiyun 	gpio_reverse_on = TEST_GPIO & gpio_reverse_on;
174*4882a593Smuzhiyun 	VEHICLE_INFO(
175*4882a593Smuzhiyun 	"%s, gpio = reverse %s, width = %d, sensor_ready = %d, state=%d dvr_apk_need_start = %d\n",
176*4882a593Smuzhiyun 	__func__, gpio_reverse_on ? "on" : "over",
177*4882a593Smuzhiyun 	v_cfg->width, v_cfg->ad_ready, v->state, dvr_apk_need_start);
178*4882a593Smuzhiyun 	if (v_cfg->mbus_flags & V4L2_MBUS_CSI2_CONTINUOUS_CLOCK) {
179*4882a593Smuzhiyun 		switch (v->state) {
180*4882a593Smuzhiyun 		case STATE_CLOSE:
181*4882a593Smuzhiyun 			if (dvr_apk_need_start) {
182*4882a593Smuzhiyun 				vehicle_open(v_cfg);
183*4882a593Smuzhiyun 				msleep(20);
184*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
185*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
186*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
187*4882a593Smuzhiyun 				v->state = STATE_OPEN;
188*4882a593Smuzhiyun 			}
189*4882a593Smuzhiyun 			if (gpio_reverse_on) {
190*4882a593Smuzhiyun 				vehicle_open(v_cfg);
191*4882a593Smuzhiyun 				msleep(20);
192*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
193*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
194*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
195*4882a593Smuzhiyun 				v->state = STATE_OPEN;
196*4882a593Smuzhiyun 			}
197*4882a593Smuzhiyun 			break;
198*4882a593Smuzhiyun 		case STATE_OPEN:
199*4882a593Smuzhiyun 			/*  reverse exit || video loss */
200*4882a593Smuzhiyun 			if (!dvr_apk_need_start && (!gpio_reverse_on || !v_cfg->ad_ready)) {
201*4882a593Smuzhiyun 				vehicle_close();
202*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
203*4882a593Smuzhiyun 				v->state = STATE_CLOSE;
204*4882a593Smuzhiyun 			} else if (gpio_reverse_on && !v->android_is_ready) { //video fmt change
205*4882a593Smuzhiyun 				vehicle_open_close();
206*4882a593Smuzhiyun 				vehicle_open(v_cfg);
207*4882a593Smuzhiyun 				msleep(100);
208*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
209*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
210*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
211*4882a593Smuzhiyun 			} else if (!gpio_reverse_on && dvr_apk_need_start) {
212*4882a593Smuzhiyun 				vehicle_close();
213*4882a593Smuzhiyun 				vehicle_open(v_cfg);
214*4882a593Smuzhiyun 				msleep(20);
215*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
216*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
217*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
218*4882a593Smuzhiyun 			}
219*4882a593Smuzhiyun 			break;
220*4882a593Smuzhiyun 		}
221*4882a593Smuzhiyun 	} else if (v_cfg->mbus_flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK) {
222*4882a593Smuzhiyun 		switch (v->state) {
223*4882a593Smuzhiyun 		case STATE_CLOSE:
224*4882a593Smuzhiyun 			if (dvr_apk_need_start) {
225*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
226*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
227*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
228*4882a593Smuzhiyun 				msleep(20);
229*4882a593Smuzhiyun 				vehicle_open(v_cfg);
230*4882a593Smuzhiyun 				v->state = STATE_OPEN;
231*4882a593Smuzhiyun 			}
232*4882a593Smuzhiyun 			if (gpio_reverse_on) {
233*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
234*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
235*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
236*4882a593Smuzhiyun 				msleep(20);
237*4882a593Smuzhiyun 				vehicle_open(v_cfg);
238*4882a593Smuzhiyun 				v->state = STATE_OPEN;
239*4882a593Smuzhiyun 			}
240*4882a593Smuzhiyun 			break;
241*4882a593Smuzhiyun 		case STATE_OPEN:
242*4882a593Smuzhiyun 			/*  reverse exit || video loss */
243*4882a593Smuzhiyun 			if (!dvr_apk_need_start && (!gpio_reverse_on || !v_cfg->ad_ready)) {
244*4882a593Smuzhiyun 				vehicle_close();
245*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
246*4882a593Smuzhiyun 				v->state = STATE_CLOSE;
247*4882a593Smuzhiyun 			} else if (gpio_reverse_on && !v->android_is_ready) { //video fmt change
248*4882a593Smuzhiyun 				vehicle_open_close();
249*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
250*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
251*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
252*4882a593Smuzhiyun 				msleep(100);
253*4882a593Smuzhiyun 				vehicle_open(v_cfg);
254*4882a593Smuzhiyun 			} else if (!gpio_reverse_on && dvr_apk_need_start) {
255*4882a593Smuzhiyun 				vehicle_close();
256*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
257*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
258*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
259*4882a593Smuzhiyun 				msleep(20);
260*4882a593Smuzhiyun 				vehicle_open(v_cfg);
261*4882a593Smuzhiyun 			}
262*4882a593Smuzhiyun 			break;
263*4882a593Smuzhiyun 		}
264*4882a593Smuzhiyun 	} else {
265*4882a593Smuzhiyun 		switch (v->state) {
266*4882a593Smuzhiyun 		case STATE_CLOSE:
267*4882a593Smuzhiyun 			if (dvr_apk_need_start) {
268*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
269*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
270*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
271*4882a593Smuzhiyun 				msleep(20);
272*4882a593Smuzhiyun 				vehicle_open(v_cfg);
273*4882a593Smuzhiyun 				v->state = STATE_OPEN;
274*4882a593Smuzhiyun 			}
275*4882a593Smuzhiyun 			if (gpio_reverse_on) {
276*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
277*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
278*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
279*4882a593Smuzhiyun 				msleep(20);
280*4882a593Smuzhiyun 				vehicle_open(v_cfg);
281*4882a593Smuzhiyun 				v->state = STATE_OPEN;
282*4882a593Smuzhiyun 			}
283*4882a593Smuzhiyun 			break;
284*4882a593Smuzhiyun 		case STATE_OPEN:
285*4882a593Smuzhiyun 			/*  reverse exit || video loss */
286*4882a593Smuzhiyun 			if (!dvr_apk_need_start && (!gpio_reverse_on || !v_cfg->ad_ready)) {
287*4882a593Smuzhiyun 				vehicle_close();
288*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
289*4882a593Smuzhiyun 				v->state = STATE_CLOSE;
290*4882a593Smuzhiyun 			} else if (gpio_reverse_on && !v->android_is_ready) { //video fmt change
291*4882a593Smuzhiyun 				vehicle_open_close();
292*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
293*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
294*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
295*4882a593Smuzhiyun 				msleep(100);
296*4882a593Smuzhiyun 				vehicle_open(v_cfg);
297*4882a593Smuzhiyun 			} else if (!gpio_reverse_on && dvr_apk_need_start) {
298*4882a593Smuzhiyun 				vehicle_close();
299*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 0);
300*4882a593Smuzhiyun 				vehicle_ad_channel_set(&g_vehicle->ad, 0);
301*4882a593Smuzhiyun 				vehicle_ad_stream(&v->ad, 1);
302*4882a593Smuzhiyun 				msleep(20);
303*4882a593Smuzhiyun 				vehicle_open(v_cfg);
304*4882a593Smuzhiyun 			}
305*4882a593Smuzhiyun 			break;
306*4882a593Smuzhiyun 		}
307*4882a593Smuzhiyun 	}
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	return 0;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
vehicle_probe(struct platform_device * pdev)312*4882a593Smuzhiyun static int vehicle_probe(struct platform_device *pdev)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun 	struct vehicle *vehicle_info;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	dev_info(&pdev->dev, "driver version: %02x.%02x.%02x",
317*4882a593Smuzhiyun 		 DRIVER_VERSION >> 16,
318*4882a593Smuzhiyun 		 (DRIVER_VERSION & 0xff00) >> 8,
319*4882a593Smuzhiyun 		 DRIVER_VERSION & 0x00ff);
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	vehicle_info = devm_kzalloc(&pdev->dev,
322*4882a593Smuzhiyun 				    sizeof(struct vehicle), GFP_KERNEL);
323*4882a593Smuzhiyun 	if (!vehicle_info)
324*4882a593Smuzhiyun 		return -ENOMEM;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	vehicle_info->dev = &pdev->dev;
327*4882a593Smuzhiyun 	vehicle_info->gpio_data.dev = &pdev->dev;
328*4882a593Smuzhiyun 	vehicle_info->cif.dev = &pdev->dev;
329*4882a593Smuzhiyun 	vehicle_info->ad.dev = &pdev->dev;
330*4882a593Smuzhiyun 
331*4882a593Smuzhiyun 	dev_set_name(vehicle_info->dev, "vehicle_main");
332*4882a593Smuzhiyun 	if (!pdev->dev.of_node)
333*4882a593Smuzhiyun 		return -EINVAL;
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	vehicle_parse_dt(vehicle_info);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if (vehicle_parse_sensor(&vehicle_info->ad) < 0) {
338*4882a593Smuzhiyun 		VEHICLE_DGERR("parse sensor failed!\n");
339*4882a593Smuzhiyun 		return -EINVAL;
340*4882a593Smuzhiyun 	}
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	wake_lock_init(&vehicle_info->wake_lock, WAKE_LOCK_SUSPEND, "vehicle");
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun 	dev_info(vehicle_info->dev, "vehicle driver probe success\n");
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun 	init_waitqueue_head(&vehicle_info->vehicle_wait);
347*4882a593Smuzhiyun 	atomic_set(&vehicle_info->vehicle_atomic, 0);
348*4882a593Smuzhiyun 	vehicle_info->state = STATE_CLOSE;
349*4882a593Smuzhiyun 	vehicle_info->android_is_ready = false;
350*4882a593Smuzhiyun 	vehicle_info->gpio_over = false;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	g_vehicle = vehicle_info;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	return 0;
355*4882a593Smuzhiyun }
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun #if defined(CONFIG_OF)
358*4882a593Smuzhiyun static const struct of_device_id vehicle_of_match[] = {
359*4882a593Smuzhiyun 	{ .compatible = "rockchip,vehicle", },
360*4882a593Smuzhiyun 	{},
361*4882a593Smuzhiyun };
362*4882a593Smuzhiyun #endif
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun static struct platform_driver vehicle_driver = {
365*4882a593Smuzhiyun 	.driver     = {
366*4882a593Smuzhiyun 		.name   = "vehicle",
367*4882a593Smuzhiyun 		.owner  = THIS_MODULE,
368*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(vehicle_of_match),
369*4882a593Smuzhiyun 	},
370*4882a593Smuzhiyun 	.probe      = vehicle_probe,
371*4882a593Smuzhiyun };
372*4882a593Smuzhiyun 
vehicle_android_is_ready_notify(void)373*4882a593Smuzhiyun void vehicle_android_is_ready_notify(void)
374*4882a593Smuzhiyun {
375*4882a593Smuzhiyun 	if (g_vehicle)
376*4882a593Smuzhiyun 		g_vehicle->android_is_ready = true;
377*4882a593Smuzhiyun 	TEST_GPIO = !TEST_GPIO;
378*4882a593Smuzhiyun 	atomic_set(&g_vehicle->vehicle_atomic, 1);
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun 
vehicle_apk_state_change(char data[22])381*4882a593Smuzhiyun void vehicle_apk_state_change(char data[22])
382*4882a593Smuzhiyun {
383*4882a593Smuzhiyun 	if (memcmp(data, "11", 2) == 0)
384*4882a593Smuzhiyun 		dvr_apk_need_start = true;
385*4882a593Smuzhiyun 	else if (memcmp(data, "10", 2) == 0)
386*4882a593Smuzhiyun 		dvr_apk_need_start = false;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	if (g_vehicle)
389*4882a593Smuzhiyun 		atomic_set(&g_vehicle->vehicle_atomic, 1);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun 
vehicle_exit_complete_notify(struct vehicle * v)392*4882a593Smuzhiyun static void vehicle_exit_complete_notify(struct vehicle *v)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	char *status = NULL;
395*4882a593Smuzhiyun 	char *envp[2];
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	if (!v)
398*4882a593Smuzhiyun 		return;
399*4882a593Smuzhiyun 	status = kasprintf(GFP_KERNEL, "vehicle_exit=done");
400*4882a593Smuzhiyun 	envp[0] = status;
401*4882a593Smuzhiyun 	envp[1] = NULL;
402*4882a593Smuzhiyun 	wake_lock_timeout(&v->wake_lock, 5 * HZ);
403*4882a593Smuzhiyun 	kobject_uevent_env(&v->dev->kobj, KOBJ_CHANGE, envp);
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	kfree(status);
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun 
rk_vehicle_system_main(void * arg)408*4882a593Smuzhiyun static int rk_vehicle_system_main(void *arg)
409*4882a593Smuzhiyun {
410*4882a593Smuzhiyun 	int ret = -1;
411*4882a593Smuzhiyun 	struct vehicle *v = g_vehicle;
412*4882a593Smuzhiyun 	int loop_times = 0;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	if (!g_vehicle) {
415*4882a593Smuzhiyun 		VEHICLE_DGERR("vehicle probe failed, g_vehicle is NULL.\n");
416*4882a593Smuzhiyun 		goto VEHICLE_EXIT;
417*4882a593Smuzhiyun 	}
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	/*  0. gpio init and check state */
420*4882a593Smuzhiyun 	ret = vehicle_gpio_init(&v->gpio_data, v->ad.ad_name);
421*4882a593Smuzhiyun 	if (ret < 0) {
422*4882a593Smuzhiyun 		VEHICLE_DGERR("%s: gpio init failed\r\n", __func__);
423*4882a593Smuzhiyun 		goto VEHICLE_GPIO_DEINIT;
424*4882a593Smuzhiyun 	}
425*4882a593Smuzhiyun 	VEHICLE_DG("vehicle_gpio_init ok!\n");
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun 	/*  1.ad */
428*4882a593Smuzhiyun 	VEHICLE_DG("%s: vehicle_ad_init start\r\n", __func__);
429*4882a593Smuzhiyun 	/* config mclk first */
430*4882a593Smuzhiyun 	ret = vehicle_cif_init_mclk(&v->cif);
431*4882a593Smuzhiyun 	ret |= vehicle_ad_init(&v->ad);
432*4882a593Smuzhiyun 	if (ret < 0) {
433*4882a593Smuzhiyun 		VEHICLE_DGERR("%s: ad init failed\r\n", __func__);
434*4882a593Smuzhiyun 		goto VEHICLE_AD_DEINIT;
435*4882a593Smuzhiyun 	}
436*4882a593Smuzhiyun 	VEHICLE_DG("vehicle_ad_init ok!\r\n");
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 	/*  3. cif init */
439*4882a593Smuzhiyun 	ret = vehicle_cif_init(&v->cif);
440*4882a593Smuzhiyun 	if (ret < 0) {
441*4882a593Smuzhiyun 		VEHICLE_DGERR("%s: cif init failed\r\n", __func__);
442*4882a593Smuzhiyun 		goto VEHICLE_CIF_DEINIT;
443*4882a593Smuzhiyun 	}
444*4882a593Smuzhiyun 	VEHICLE_DG("%s: vehicle_cif_init ok!\r\n", __func__);
445*4882a593Smuzhiyun 	pm_runtime_enable(v->dev);
446*4882a593Smuzhiyun 	pm_runtime_get_sync(v->dev);
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	//while (STATE_OPEN == v->state || !v->vehicle_need_exit) {
449*4882a593Smuzhiyun 	while (v->state == STATE_OPEN || !v->android_is_ready) {
450*4882a593Smuzhiyun 		if (v->android_is_ready && !v->state)
451*4882a593Smuzhiyun 			v->gpio_over = true;
452*4882a593Smuzhiyun 		wait_event_timeout(v->vehicle_wait,
453*4882a593Smuzhiyun 				   atomic_read(&v->vehicle_atomic),
454*4882a593Smuzhiyun 				   msecs_to_jiffies(100));
455*4882a593Smuzhiyun 		if (atomic_read(&v->vehicle_atomic)) {
456*4882a593Smuzhiyun 			atomic_set(&v->vehicle_atomic, 0);
457*4882a593Smuzhiyun 			vehicle_state_change(v);
458*4882a593Smuzhiyun 		}
459*4882a593Smuzhiyun 		VEHICLE_DG("loop time(%d) \r\n", loop_times);
460*4882a593Smuzhiyun 		loop_times++;
461*4882a593Smuzhiyun 	}
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun VEHICLE_CIF_DEINIT:
464*4882a593Smuzhiyun 	vehicle_cif_deinit(&v->cif);
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun VEHICLE_AD_DEINIT:
467*4882a593Smuzhiyun 	vehicle_ad_deinit();
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun VEHICLE_GPIO_DEINIT:
470*4882a593Smuzhiyun 	vehicle_gpio_deinit(&v->gpio_data);
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	/*Init normal drivers*/
473*4882a593Smuzhiyun VEHICLE_EXIT:
474*4882a593Smuzhiyun 	if (flinger_inited)
475*4882a593Smuzhiyun 		vehicle_flinger_deinit();
476*4882a593Smuzhiyun 	// if (v && v->pinctrl)
477*4882a593Smuzhiyun 	//	pinctrl_put(v->pinctrl);
478*4882a593Smuzhiyun 	vehicle_to_v4l2_drv_init();
479*4882a593Smuzhiyun 	msleep(500);
480*4882a593Smuzhiyun 	rockchip_csi2_dphy_hw_init();
481*4882a593Smuzhiyun 	rockchip_csi2_dphy_init();
482*4882a593Smuzhiyun 	rk_cif_plat_drv_init();
483*4882a593Smuzhiyun 	// rkcif_csi2_plat_drv_init();
484*4882a593Smuzhiyun 	rkcif_clr_unready_dev();
485*4882a593Smuzhiyun #ifdef CONFIG_GPIO_DET
486*4882a593Smuzhiyun 	//gpio_det_init();
487*4882a593Smuzhiyun #endif
488*4882a593Smuzhiyun 	// msleep(1000);
489*4882a593Smuzhiyun 	vehicle_exit_complete_notify(v);
490*4882a593Smuzhiyun 	return 0;
491*4882a593Smuzhiyun }
492*4882a593Smuzhiyun 
vehicle_system_start(void)493*4882a593Smuzhiyun static int __init vehicle_system_start(void)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun 	platform_driver_register(&vehicle_driver);
496*4882a593Smuzhiyun 	kthread_run(rk_vehicle_system_main, NULL, "vehicle main");
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun 	return 0;
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun 
501*4882a593Smuzhiyun subsys_initcall_sync(vehicle_system_start);
502