xref: /OK3568_Linux_fs/kernel/drivers/media/i2c/preisp-dummy.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * pisp_dmy driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (C) 2020 Rockchip Electronics Co., Ltd.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/clk.h>
9*4882a593Smuzhiyun #include <linux/device.h>
10*4882a593Smuzhiyun #include <linux/delay.h>
11*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
12*4882a593Smuzhiyun #include <linux/i2c.h>
13*4882a593Smuzhiyun #include <linux/module.h>
14*4882a593Smuzhiyun #include <linux/pm_runtime.h>
15*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
16*4882a593Smuzhiyun #include <linux/sysfs.h>
17*4882a593Smuzhiyun #include <media/media-entity.h>
18*4882a593Smuzhiyun #include <media/v4l2-async.h>
19*4882a593Smuzhiyun #include <media/v4l2-ctrls.h>
20*4882a593Smuzhiyun #include <media/v4l2-subdev.h>
21*4882a593Smuzhiyun #include <media/v4l2-fwnode.h>
22*4882a593Smuzhiyun #include <linux/pinctrl/consumer.h>
23*4882a593Smuzhiyun #include <linux/of.h>
24*4882a593Smuzhiyun #include <linux/of_device.h>
25*4882a593Smuzhiyun #include <linux/of_graph.h>
26*4882a593Smuzhiyun #include <linux/of_platform.h>
27*4882a593Smuzhiyun #include <linux/of_gpio.h>
28*4882a593Smuzhiyun #include <linux/mfd/syscon.h>
29*4882a593Smuzhiyun #include <linux/version.h>
30*4882a593Smuzhiyun #include <linux/rk-camera-module.h>
31*4882a593Smuzhiyun #include <linux/rk-preisp.h>
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun #define DRIVER_VERSION				KERNEL_VERSION(0, 0x01, 0x0)
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #ifndef V4L2_CID_DIGITAL_GAIN
36*4882a593Smuzhiyun #define V4L2_CID_DIGITAL_GAIN			V4L2_CID_GAIN
37*4882a593Smuzhiyun #endif
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun #define PISP_DMY_XVCLK_FREQ			24000000
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun #define OF_CAMERA_PINCTRL_STATE_DEFAULT		"rockchip,camera_default"
42*4882a593Smuzhiyun #define OF_CAMERA_PINCTRL_STATE_SLEEP		"rockchip,camera_sleep"
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun #define OF_CAMERA_MODULE_REGULATORS		"rockchip,regulator-names"
45*4882a593Smuzhiyun #define OF_CAMERA_MODULE_REGULATOR_VOLTAGES	"rockchip,regulator-voltages"
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun #define PISP_DMY_NAME				"pisp_dmy"
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun struct pisp_dmy_gpio {
50*4882a593Smuzhiyun 	int pltfrm_gpio;
51*4882a593Smuzhiyun 	const char *label;
52*4882a593Smuzhiyun 	enum of_gpio_flags active_low;
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun struct pisp_dmy_regulator {
56*4882a593Smuzhiyun 	struct regulator *regulator;
57*4882a593Smuzhiyun 	u32 min_uV;
58*4882a593Smuzhiyun 	u32 max_uV;
59*4882a593Smuzhiyun };
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun struct pisp_dmy_regulators {
62*4882a593Smuzhiyun 	u32 cnt;
63*4882a593Smuzhiyun 	struct pisp_dmy_regulator *regulator;
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun struct pisp_dmy {
67*4882a593Smuzhiyun 	struct i2c_client	*client;
68*4882a593Smuzhiyun 	struct clk		*xvclk;
69*4882a593Smuzhiyun 	struct gpio_desc	*rst_gpio;
70*4882a593Smuzhiyun 	struct gpio_desc	*rst2_gpio;
71*4882a593Smuzhiyun 	struct gpio_desc	*pd_gpio;
72*4882a593Smuzhiyun 	struct gpio_desc	*pd2_gpio;
73*4882a593Smuzhiyun 	struct gpio_desc	*pwd_gpio;
74*4882a593Smuzhiyun 	struct gpio_desc	*pwd2_gpio;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	struct pinctrl		*pinctrl;
77*4882a593Smuzhiyun 	struct pinctrl_state	*pins_default;
78*4882a593Smuzhiyun 	struct pinctrl_state	*pins_sleep;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	struct v4l2_subdev	subdev;
81*4882a593Smuzhiyun 	struct media_pad	pad;
82*4882a593Smuzhiyun 	struct mutex		mutex;
83*4882a593Smuzhiyun 	bool			power_on;
84*4882a593Smuzhiyun 	struct pisp_dmy_regulators regulators;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	u32			module_index;
87*4882a593Smuzhiyun 	const char		*module_facing;
88*4882a593Smuzhiyun 	const char		*module_name;
89*4882a593Smuzhiyun 	const char		*len_name;
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun #define to_pisp_dmy(sd) container_of(sd, struct pisp_dmy, subdev)
93*4882a593Smuzhiyun 
__pisp_dmy_power_on(struct pisp_dmy * pisp_dmy)94*4882a593Smuzhiyun static int __pisp_dmy_power_on(struct pisp_dmy *pisp_dmy)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	u32 i;
97*4882a593Smuzhiyun 	int ret;
98*4882a593Smuzhiyun 	struct pisp_dmy_regulator *regulator;
99*4882a593Smuzhiyun 	struct device *dev = &pisp_dmy->client->dev;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(pisp_dmy->pins_default)) {
102*4882a593Smuzhiyun 		ret = pinctrl_select_state(pisp_dmy->pinctrl,
103*4882a593Smuzhiyun 					   pisp_dmy->pins_default);
104*4882a593Smuzhiyun 		if (ret < 0)
105*4882a593Smuzhiyun 			dev_err(dev, "could not set pins. ret=%d\n", ret);
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	ret = clk_prepare_enable(pisp_dmy->xvclk);
109*4882a593Smuzhiyun 	if (ret < 0) {
110*4882a593Smuzhiyun 		dev_err(dev, "Failed to enable xvclk\n");
111*4882a593Smuzhiyun 		return ret;
112*4882a593Smuzhiyun 	}
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	if (pisp_dmy->regulators.regulator) {
115*4882a593Smuzhiyun 		for (i = 0; i < pisp_dmy->regulators.cnt; i++) {
116*4882a593Smuzhiyun 			regulator = pisp_dmy->regulators.regulator + i;
117*4882a593Smuzhiyun 			if (IS_ERR(regulator->regulator))
118*4882a593Smuzhiyun 				continue;
119*4882a593Smuzhiyun 			regulator_set_voltage(
120*4882a593Smuzhiyun 				regulator->regulator,
121*4882a593Smuzhiyun 				regulator->min_uV,
122*4882a593Smuzhiyun 				regulator->max_uV);
123*4882a593Smuzhiyun 			if (regulator_enable(regulator->regulator)) {
124*4882a593Smuzhiyun 				dev_err(dev,
125*4882a593Smuzhiyun 					"regulator_enable failed!\n");
126*4882a593Smuzhiyun 				goto disable_clk;
127*4882a593Smuzhiyun 			}
128*4882a593Smuzhiyun 		}
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 	usleep_range(3000, 5000);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->pwd_gpio)) {
133*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->pwd_gpio, 1);
134*4882a593Smuzhiyun 		usleep_range(3000, 5000);
135*4882a593Smuzhiyun 	}
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->pwd2_gpio)) {
138*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->pwd2_gpio, 1);
139*4882a593Smuzhiyun 		usleep_range(3000, 5000);
140*4882a593Smuzhiyun 	}
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->pd_gpio)) {
143*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->pd_gpio, 1);
144*4882a593Smuzhiyun 		usleep_range(1500, 2000);
145*4882a593Smuzhiyun 	}
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->pd2_gpio)) {
148*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->pd2_gpio, 1);
149*4882a593Smuzhiyun 		usleep_range(1500, 2000);
150*4882a593Smuzhiyun 	}
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->rst_gpio)) {
153*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->rst_gpio, 0);
154*4882a593Smuzhiyun 		usleep_range(1500, 2000);
155*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->rst_gpio, 1);
156*4882a593Smuzhiyun 	}
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->rst2_gpio)) {
159*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->rst2_gpio, 0);
160*4882a593Smuzhiyun 		usleep_range(1500, 2000);
161*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->rst2_gpio, 1);
162*4882a593Smuzhiyun 	}
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	return 0;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun disable_clk:
167*4882a593Smuzhiyun 	clk_disable_unprepare(pisp_dmy->xvclk);
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	return ret;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
__pisp_dmy_power_off(struct pisp_dmy * pisp_dmy)172*4882a593Smuzhiyun static void __pisp_dmy_power_off(struct pisp_dmy *pisp_dmy)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	u32 i;
175*4882a593Smuzhiyun 	int ret;
176*4882a593Smuzhiyun 	struct pisp_dmy_regulator *regulator;
177*4882a593Smuzhiyun 	struct device *dev = &pisp_dmy->client->dev;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->pd_gpio))
180*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->pd_gpio, 0);
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->pd2_gpio))
183*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->pd2_gpio, 0);
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun 	clk_disable_unprepare(pisp_dmy->xvclk);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->rst_gpio))
188*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->rst_gpio, 0);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->rst2_gpio))
191*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->rst2_gpio, 0);
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->pwd_gpio))
194*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->pwd_gpio, 0);
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->pwd2_gpio))
197*4882a593Smuzhiyun 		gpiod_direction_output(pisp_dmy->pwd2_gpio, 0);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	if (!IS_ERR_OR_NULL(pisp_dmy->pins_sleep)) {
200*4882a593Smuzhiyun 		ret = pinctrl_select_state(pisp_dmy->pinctrl,
201*4882a593Smuzhiyun 					   pisp_dmy->pins_sleep);
202*4882a593Smuzhiyun 		if (ret < 0)
203*4882a593Smuzhiyun 			dev_err(dev, "could not set pins\n");
204*4882a593Smuzhiyun 	}
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	if (pisp_dmy->regulators.regulator) {
207*4882a593Smuzhiyun 		for (i = 0; i < pisp_dmy->regulators.cnt; i++) {
208*4882a593Smuzhiyun 			regulator = pisp_dmy->regulators.regulator + i;
209*4882a593Smuzhiyun 			if (IS_ERR(regulator->regulator))
210*4882a593Smuzhiyun 				continue;
211*4882a593Smuzhiyun 			regulator_disable(regulator->regulator);
212*4882a593Smuzhiyun 		}
213*4882a593Smuzhiyun 	}
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
pisp_dmy_power(struct v4l2_subdev * sd,int on)216*4882a593Smuzhiyun static int pisp_dmy_power(struct v4l2_subdev *sd, int on)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	struct pisp_dmy *pisp_dmy = to_pisp_dmy(sd);
219*4882a593Smuzhiyun 	int ret = 0;
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun 	mutex_lock(&pisp_dmy->mutex);
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 	/* If the power state is not modified - no work to do. */
224*4882a593Smuzhiyun 	if (pisp_dmy->power_on == !!on)
225*4882a593Smuzhiyun 		goto exit;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	if (on) {
228*4882a593Smuzhiyun 		ret = __pisp_dmy_power_on(pisp_dmy);
229*4882a593Smuzhiyun 		if (ret < 0)
230*4882a593Smuzhiyun 			goto exit;
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 		pisp_dmy->power_on = true;
233*4882a593Smuzhiyun 	} else {
234*4882a593Smuzhiyun 		__pisp_dmy_power_off(pisp_dmy);
235*4882a593Smuzhiyun 		pisp_dmy->power_on = false;
236*4882a593Smuzhiyun 	}
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun exit:
239*4882a593Smuzhiyun 	mutex_unlock(&pisp_dmy->mutex);
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	return ret;
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun 
pisp_dmy_get_module_inf(struct pisp_dmy * pisp_dmy,struct rkmodule_inf * inf)244*4882a593Smuzhiyun static void pisp_dmy_get_module_inf(struct pisp_dmy *pisp_dmy,
245*4882a593Smuzhiyun 				    struct rkmodule_inf *inf)
246*4882a593Smuzhiyun {
247*4882a593Smuzhiyun 	memset(inf, 0, sizeof(*inf));
248*4882a593Smuzhiyun 	strlcpy(inf->base.sensor, PISP_DMY_NAME, sizeof(inf->base.sensor));
249*4882a593Smuzhiyun 	strlcpy(inf->base.module, pisp_dmy->module_name,
250*4882a593Smuzhiyun 		sizeof(inf->base.module));
251*4882a593Smuzhiyun 	strlcpy(inf->base.lens, pisp_dmy->len_name, sizeof(inf->base.lens));
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
pisp_dmy_ioctl(struct v4l2_subdev * sd,unsigned int cmd,void * arg)254*4882a593Smuzhiyun static long pisp_dmy_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun 	struct pisp_dmy *pisp_dmy = to_pisp_dmy(sd);
257*4882a593Smuzhiyun 	long ret = 0;
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun 	switch (cmd) {
260*4882a593Smuzhiyun 	case RKMODULE_GET_MODULE_INFO:
261*4882a593Smuzhiyun 		pisp_dmy_get_module_inf(pisp_dmy, (struct rkmodule_inf *)arg);
262*4882a593Smuzhiyun 		break;
263*4882a593Smuzhiyun 	default:
264*4882a593Smuzhiyun 		ret = -ENOTTY;
265*4882a593Smuzhiyun 		break;
266*4882a593Smuzhiyun 	}
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun 	return ret;
269*4882a593Smuzhiyun }
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
pisp_dmy_compat_ioctl32(struct v4l2_subdev * sd,unsigned int cmd,unsigned long arg)272*4882a593Smuzhiyun static long pisp_dmy_compat_ioctl32(struct v4l2_subdev *sd,
273*4882a593Smuzhiyun 				    unsigned int cmd, unsigned long arg)
274*4882a593Smuzhiyun {
275*4882a593Smuzhiyun 	void __user *up = compat_ptr(arg);
276*4882a593Smuzhiyun 	struct rkmodule_inf *inf;
277*4882a593Smuzhiyun 	struct rkmodule_awb_cfg *cfg;
278*4882a593Smuzhiyun 	long ret;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	switch (cmd) {
281*4882a593Smuzhiyun 	case RKMODULE_GET_MODULE_INFO:
282*4882a593Smuzhiyun 		inf = kzalloc(sizeof(*inf), GFP_KERNEL);
283*4882a593Smuzhiyun 		if (!inf) {
284*4882a593Smuzhiyun 			ret = -ENOMEM;
285*4882a593Smuzhiyun 			return ret;
286*4882a593Smuzhiyun 		}
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 		ret = pisp_dmy_ioctl(sd, cmd, inf);
289*4882a593Smuzhiyun 		if (!ret)
290*4882a593Smuzhiyun 			if (copy_to_user(up, inf, sizeof(*inf))) {
291*4882a593Smuzhiyun 				kfree(inf);
292*4882a593Smuzhiyun 				return -EFAULT;
293*4882a593Smuzhiyun 			}
294*4882a593Smuzhiyun 		kfree(inf);
295*4882a593Smuzhiyun 		break;
296*4882a593Smuzhiyun 	case RKMODULE_AWB_CFG:
297*4882a593Smuzhiyun 		cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
298*4882a593Smuzhiyun 		if (!cfg) {
299*4882a593Smuzhiyun 			ret = -ENOMEM;
300*4882a593Smuzhiyun 			return ret;
301*4882a593Smuzhiyun 		}
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 		if (copy_from_user(cfg, up, sizeof(*cfg))) {
304*4882a593Smuzhiyun 			kfree(cfg);
305*4882a593Smuzhiyun 			return -EFAULT;
306*4882a593Smuzhiyun 		}
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 		ret = pisp_dmy_ioctl(sd, cmd, cfg);
309*4882a593Smuzhiyun 		kfree(cfg);
310*4882a593Smuzhiyun 		break;
311*4882a593Smuzhiyun 	default:
312*4882a593Smuzhiyun 		ret = -ENOIOCTLCMD;
313*4882a593Smuzhiyun 		break;
314*4882a593Smuzhiyun 	}
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	return ret;
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun #endif
319*4882a593Smuzhiyun 
pisp_dmy_runtime_resume(struct device * dev)320*4882a593Smuzhiyun static int pisp_dmy_runtime_resume(struct device *dev)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
323*4882a593Smuzhiyun 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
324*4882a593Smuzhiyun 	struct pisp_dmy *pisp_dmy = to_pisp_dmy(sd);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	return __pisp_dmy_power_on(pisp_dmy);
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun 
pisp_dmy_runtime_suspend(struct device * dev)329*4882a593Smuzhiyun static int pisp_dmy_runtime_suspend(struct device *dev)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	struct i2c_client *client = to_i2c_client(dev);
332*4882a593Smuzhiyun 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
333*4882a593Smuzhiyun 	struct pisp_dmy *pisp_dmy = to_pisp_dmy(sd);
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	__pisp_dmy_power_off(pisp_dmy);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	return 0;
338*4882a593Smuzhiyun }
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun static const struct dev_pm_ops pisp_dmy_pm_ops = {
341*4882a593Smuzhiyun 	SET_RUNTIME_PM_OPS(pisp_dmy_runtime_suspend,
342*4882a593Smuzhiyun 			   pisp_dmy_runtime_resume, NULL)
343*4882a593Smuzhiyun };
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun static const struct v4l2_subdev_core_ops pisp_dmy_core_ops = {
346*4882a593Smuzhiyun 	.s_power = pisp_dmy_power,
347*4882a593Smuzhiyun 	.ioctl = pisp_dmy_ioctl,
348*4882a593Smuzhiyun #ifdef CONFIG_COMPAT
349*4882a593Smuzhiyun 	.compat_ioctl32 = pisp_dmy_compat_ioctl32,
350*4882a593Smuzhiyun #endif
351*4882a593Smuzhiyun };
352*4882a593Smuzhiyun 
353*4882a593Smuzhiyun static const struct v4l2_subdev_ops pisp_dmy_subdev_ops = {
354*4882a593Smuzhiyun 	.core = &pisp_dmy_core_ops,
355*4882a593Smuzhiyun };
356*4882a593Smuzhiyun 
pisp_dmy_analyze_dts(struct pisp_dmy * pisp_dmy)357*4882a593Smuzhiyun static int pisp_dmy_analyze_dts(struct pisp_dmy *pisp_dmy)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	int ret;
360*4882a593Smuzhiyun 	int elem_size, elem_index;
361*4882a593Smuzhiyun 	const char *str = "";
362*4882a593Smuzhiyun 	struct property *prop;
363*4882a593Smuzhiyun 	struct pisp_dmy_regulator *regulator;
364*4882a593Smuzhiyun 	struct device *dev = &pisp_dmy->client->dev;
365*4882a593Smuzhiyun 	struct device_node *np = of_node_get(dev->of_node);
366*4882a593Smuzhiyun 
367*4882a593Smuzhiyun 	pisp_dmy->xvclk = devm_clk_get(dev, "xvclk");
368*4882a593Smuzhiyun 	if (IS_ERR(pisp_dmy->xvclk)) {
369*4882a593Smuzhiyun 		dev_err(dev, "Failed to get xvclk\n");
370*4882a593Smuzhiyun 		return -EINVAL;
371*4882a593Smuzhiyun 	}
372*4882a593Smuzhiyun 	ret = clk_set_rate(pisp_dmy->xvclk, PISP_DMY_XVCLK_FREQ);
373*4882a593Smuzhiyun 	if (ret < 0) {
374*4882a593Smuzhiyun 		dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
375*4882a593Smuzhiyun 		return ret;
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun 	if (clk_get_rate(pisp_dmy->xvclk) != PISP_DMY_XVCLK_FREQ)
378*4882a593Smuzhiyun 		dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun 	pisp_dmy->pinctrl = devm_pinctrl_get(dev);
381*4882a593Smuzhiyun 	if (!IS_ERR(pisp_dmy->pinctrl)) {
382*4882a593Smuzhiyun 		pisp_dmy->pins_default =
383*4882a593Smuzhiyun 			pinctrl_lookup_state(pisp_dmy->pinctrl,
384*4882a593Smuzhiyun 					     OF_CAMERA_PINCTRL_STATE_DEFAULT);
385*4882a593Smuzhiyun 		if (IS_ERR(pisp_dmy->pins_default))
386*4882a593Smuzhiyun 			dev_err(dev, "could not get default pinstate\n");
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 		pisp_dmy->pins_sleep =
389*4882a593Smuzhiyun 			pinctrl_lookup_state(pisp_dmy->pinctrl,
390*4882a593Smuzhiyun 					     OF_CAMERA_PINCTRL_STATE_SLEEP);
391*4882a593Smuzhiyun 		if (IS_ERR(pisp_dmy->pins_sleep))
392*4882a593Smuzhiyun 			dev_err(dev, "could not get sleep pinstate\n");
393*4882a593Smuzhiyun 	} else {
394*4882a593Smuzhiyun 		dev_err(dev, "no pinctrl\n");
395*4882a593Smuzhiyun 	}
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	elem_size = of_property_count_elems_of_size(
398*4882a593Smuzhiyun 		np,
399*4882a593Smuzhiyun 		OF_CAMERA_MODULE_REGULATOR_VOLTAGES,
400*4882a593Smuzhiyun 		sizeof(u32));
401*4882a593Smuzhiyun 	prop = of_find_property(
402*4882a593Smuzhiyun 		np,
403*4882a593Smuzhiyun 		OF_CAMERA_MODULE_REGULATORS,
404*4882a593Smuzhiyun 		NULL);
405*4882a593Smuzhiyun 	if (elem_size > 0 && !IS_ERR_OR_NULL(prop)) {
406*4882a593Smuzhiyun 		pisp_dmy->regulators.regulator =
407*4882a593Smuzhiyun 			devm_kzalloc(&pisp_dmy->client->dev,
408*4882a593Smuzhiyun 				     elem_size * sizeof(struct pisp_dmy_regulator),
409*4882a593Smuzhiyun 				     GFP_KERNEL);
410*4882a593Smuzhiyun 		if (!pisp_dmy->regulators.regulator) {
411*4882a593Smuzhiyun 			dev_err(dev, "could not malloc pisp_dmy_regulator\n");
412*4882a593Smuzhiyun 			return -ENOMEM;
413*4882a593Smuzhiyun 		}
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 		pisp_dmy->regulators.cnt = elem_size;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 		str = NULL;
418*4882a593Smuzhiyun 		elem_index = 0;
419*4882a593Smuzhiyun 		regulator = pisp_dmy->regulators.regulator;
420*4882a593Smuzhiyun 		do {
421*4882a593Smuzhiyun 			str = of_prop_next_string(prop, str);
422*4882a593Smuzhiyun 			if (!str) {
423*4882a593Smuzhiyun 				dev_err(dev, "%s is not match %s in dts\n",
424*4882a593Smuzhiyun 					OF_CAMERA_MODULE_REGULATORS,
425*4882a593Smuzhiyun 					OF_CAMERA_MODULE_REGULATOR_VOLTAGES);
426*4882a593Smuzhiyun 				break;
427*4882a593Smuzhiyun 			}
428*4882a593Smuzhiyun 			regulator->regulator =
429*4882a593Smuzhiyun 				devm_regulator_get_optional(dev, str);
430*4882a593Smuzhiyun 			if (IS_ERR(regulator->regulator))
431*4882a593Smuzhiyun 				dev_err(dev, "devm_regulator_get %s failed\n",
432*4882a593Smuzhiyun 					str);
433*4882a593Smuzhiyun 			of_property_read_u32_index(
434*4882a593Smuzhiyun 				np,
435*4882a593Smuzhiyun 				OF_CAMERA_MODULE_REGULATOR_VOLTAGES,
436*4882a593Smuzhiyun 				elem_index++,
437*4882a593Smuzhiyun 				&regulator->min_uV);
438*4882a593Smuzhiyun 			regulator->max_uV = regulator->min_uV;
439*4882a593Smuzhiyun 			regulator++;
440*4882a593Smuzhiyun 		} while (--elem_size);
441*4882a593Smuzhiyun 	}
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	pisp_dmy->pd_gpio = devm_gpiod_get(dev, "pd", GPIOD_OUT_LOW);
444*4882a593Smuzhiyun 	if (IS_ERR(pisp_dmy->pd_gpio))
445*4882a593Smuzhiyun 		dev_warn(dev, "can not find pd-gpios, error %ld\n",
446*4882a593Smuzhiyun 			 PTR_ERR(pisp_dmy->pd_gpio));
447*4882a593Smuzhiyun 
448*4882a593Smuzhiyun 	pisp_dmy->pd2_gpio = devm_gpiod_get(dev, "pd2", GPIOD_OUT_LOW);
449*4882a593Smuzhiyun 	if (IS_ERR(pisp_dmy->pd2_gpio))
450*4882a593Smuzhiyun 		dev_warn(dev, "can not find pd2-gpios, error %ld\n",
451*4882a593Smuzhiyun 			 PTR_ERR(pisp_dmy->pd2_gpio));
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	pisp_dmy->rst_gpio = devm_gpiod_get(dev, "rst", GPIOD_OUT_LOW);
454*4882a593Smuzhiyun 	if (IS_ERR(pisp_dmy->rst_gpio))
455*4882a593Smuzhiyun 		dev_warn(dev, "can not find rst-gpios, error %ld\n",
456*4882a593Smuzhiyun 			 PTR_ERR(pisp_dmy->rst_gpio));
457*4882a593Smuzhiyun 
458*4882a593Smuzhiyun 	pisp_dmy->rst2_gpio = devm_gpiod_get(dev, "rst2", GPIOD_OUT_LOW);
459*4882a593Smuzhiyun 	if (IS_ERR(pisp_dmy->rst2_gpio))
460*4882a593Smuzhiyun 		dev_warn(dev, "can not find rst2-gpios, error %ld\n",
461*4882a593Smuzhiyun 			 PTR_ERR(pisp_dmy->rst2_gpio));
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	pisp_dmy->pwd_gpio = devm_gpiod_get(dev, "pwd", GPIOD_OUT_HIGH);
464*4882a593Smuzhiyun 	if (IS_ERR(pisp_dmy->pwd_gpio))
465*4882a593Smuzhiyun 		dev_warn(dev, "can not find pwd-gpios, error %ld\n",
466*4882a593Smuzhiyun 			 PTR_ERR(pisp_dmy->pwd_gpio));
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 	pisp_dmy->pwd2_gpio = devm_gpiod_get(dev, "pwd2", GPIOD_OUT_HIGH);
469*4882a593Smuzhiyun 	if (IS_ERR(pisp_dmy->pwd2_gpio))
470*4882a593Smuzhiyun 		dev_warn(dev, "can not find pwd2-gpios, error %ld\n",
471*4882a593Smuzhiyun 			 PTR_ERR(pisp_dmy->pwd2_gpio));
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun 	return 0;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun 
pisp_dmy_probe(struct i2c_client * client,const struct i2c_device_id * id)476*4882a593Smuzhiyun static int pisp_dmy_probe(struct i2c_client *client,
477*4882a593Smuzhiyun 			const struct i2c_device_id *id)
478*4882a593Smuzhiyun {
479*4882a593Smuzhiyun 	struct device *dev = &client->dev;
480*4882a593Smuzhiyun 	struct device_node *node = dev->of_node;
481*4882a593Smuzhiyun 	struct pisp_dmy *pisp_dmy;
482*4882a593Smuzhiyun 	struct v4l2_subdev *sd;
483*4882a593Smuzhiyun 	int ret;
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 	dev_info(dev, "driver version: %02x.%02x.%02x",
486*4882a593Smuzhiyun 		 DRIVER_VERSION >> 16,
487*4882a593Smuzhiyun 		 (DRIVER_VERSION & 0xff00) >> 8,
488*4882a593Smuzhiyun 		 DRIVER_VERSION & 0x00ff);
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun 	pisp_dmy = devm_kzalloc(dev, sizeof(*pisp_dmy), GFP_KERNEL);
491*4882a593Smuzhiyun 	if (!pisp_dmy)
492*4882a593Smuzhiyun 		return -ENOMEM;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 	ret = of_property_read_u32(node, RKMODULE_CAMERA_MODULE_INDEX,
495*4882a593Smuzhiyun 				   &pisp_dmy->module_index);
496*4882a593Smuzhiyun 	ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_FACING,
497*4882a593Smuzhiyun 				       &pisp_dmy->module_facing);
498*4882a593Smuzhiyun 	ret |= of_property_read_string(node, RKMODULE_CAMERA_MODULE_NAME,
499*4882a593Smuzhiyun 				       &pisp_dmy->module_name);
500*4882a593Smuzhiyun 	ret |= of_property_read_string(node, RKMODULE_CAMERA_LENS_NAME,
501*4882a593Smuzhiyun 				       &pisp_dmy->len_name);
502*4882a593Smuzhiyun 	if (ret) {
503*4882a593Smuzhiyun 		dev_err(dev, "could not get module information!\n");
504*4882a593Smuzhiyun 		return -EINVAL;
505*4882a593Smuzhiyun 	}
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	pisp_dmy->client = client;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	ret = pisp_dmy_analyze_dts(pisp_dmy);
510*4882a593Smuzhiyun 	if (ret) {
511*4882a593Smuzhiyun 		dev_err(dev, "Failed to analyze dts\n");
512*4882a593Smuzhiyun 		return ret;
513*4882a593Smuzhiyun 	}
514*4882a593Smuzhiyun 
515*4882a593Smuzhiyun 	mutex_init(&pisp_dmy->mutex);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 	sd = &pisp_dmy->subdev;
518*4882a593Smuzhiyun 	v4l2_i2c_subdev_init(sd, client, &pisp_dmy_subdev_ops);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	__pisp_dmy_power_on(pisp_dmy);
521*4882a593Smuzhiyun 
522*4882a593Smuzhiyun 	pm_runtime_set_active(dev);
523*4882a593Smuzhiyun 	pm_runtime_enable(dev);
524*4882a593Smuzhiyun 	pm_runtime_idle(dev);
525*4882a593Smuzhiyun 
526*4882a593Smuzhiyun 	return 0;
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun 
pisp_dmy_remove(struct i2c_client * client)529*4882a593Smuzhiyun static int pisp_dmy_remove(struct i2c_client *client)
530*4882a593Smuzhiyun {
531*4882a593Smuzhiyun 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
532*4882a593Smuzhiyun 	struct pisp_dmy *pisp_dmy = to_pisp_dmy(sd);
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun 	mutex_destroy(&pisp_dmy->mutex);
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun 	pm_runtime_disable(&client->dev);
537*4882a593Smuzhiyun 	if (!pm_runtime_status_suspended(&client->dev))
538*4882a593Smuzhiyun 		__pisp_dmy_power_off(pisp_dmy);
539*4882a593Smuzhiyun 	pm_runtime_set_suspended(&client->dev);
540*4882a593Smuzhiyun 
541*4882a593Smuzhiyun 	return 0;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun 
544*4882a593Smuzhiyun #if IS_ENABLED(CONFIG_OF)
545*4882a593Smuzhiyun static const struct of_device_id pisp_dmy_of_match[] = {
546*4882a593Smuzhiyun 	{ .compatible = "pisp_dmy" },
547*4882a593Smuzhiyun 	{},
548*4882a593Smuzhiyun };
549*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, pisp_dmy_of_match);
550*4882a593Smuzhiyun #endif
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun static const struct i2c_device_id pisp_dmy_match_id[] = {
553*4882a593Smuzhiyun 	{ "pisp_dmy", 0 },
554*4882a593Smuzhiyun 	{ },
555*4882a593Smuzhiyun };
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun static struct i2c_driver pisp_dmy_i2c_driver = {
558*4882a593Smuzhiyun 	.driver = {
559*4882a593Smuzhiyun 		.name = PISP_DMY_NAME,
560*4882a593Smuzhiyun 		.pm = &pisp_dmy_pm_ops,
561*4882a593Smuzhiyun 		.of_match_table = of_match_ptr(pisp_dmy_of_match),
562*4882a593Smuzhiyun 	},
563*4882a593Smuzhiyun 	.probe		= &pisp_dmy_probe,
564*4882a593Smuzhiyun 	.remove		= &pisp_dmy_remove,
565*4882a593Smuzhiyun 	.id_table	= pisp_dmy_match_id,
566*4882a593Smuzhiyun };
567*4882a593Smuzhiyun 
sensor_mod_init(void)568*4882a593Smuzhiyun static int __init sensor_mod_init(void)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun 	return i2c_add_driver(&pisp_dmy_i2c_driver);
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun 
sensor_mod_exit(void)573*4882a593Smuzhiyun static void __exit sensor_mod_exit(void)
574*4882a593Smuzhiyun {
575*4882a593Smuzhiyun 	i2c_del_driver(&pisp_dmy_i2c_driver);
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun device_initcall_sync(sensor_mod_init);
579*4882a593Smuzhiyun module_exit(sensor_mod_exit);
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun MODULE_DESCRIPTION("preisp dummy sensor driver");
582*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
583