xref: /linux/drivers/media/i2c/dw9719.c (revision d30c1683aaecb93d2ab95685dc4300a33d3cea7a)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2012 Intel Corporation
3 
4 /*
5  * Based on linux/modules/camera/drivers/media/i2c/imx/dw9719.c from:
6  * https://github.com/ZenfoneArea/android_kernel_asus_zenfone5 and
7  * latte-l-oss/drivers/external_drivers/camera/drivers/media/i2c/micam/dw9761.c
8  * from: https://github.com/MiCode/Xiaomi_Kernel_OpenSource/
9  */
10 
11 #include <linux/delay.h>
12 #include <linux/i2c.h>
13 #include <linux/pm_runtime.h>
14 #include <linux/regulator/consumer.h>
15 #include <linux/types.h>
16 
17 #include <media/v4l2-cci.h>
18 #include <media/v4l2-common.h>
19 #include <media/v4l2-ctrls.h>
20 #include <media/v4l2-subdev.h>
21 
22 #define DW9719_MAX_FOCUS_POS	1023
23 #define DW9719_CTRL_STEPS	16
24 #define DW9719_CTRL_DELAY_US	1000
25 
26 #define DW9718S_PD			CCI_REG8(0)
27 
28 #define DW9718S_CONTROL			CCI_REG8(1)
29 #define DW9718S_CONTROL_SW_LINEAR	BIT(0)
30 #define DW9718S_CONTROL_SAC_SHIFT	1
31 #define DW9718S_CONTROL_SAC_MASK	0x7
32 #define DW9718S_CONTROL_OCP_DISABLE	BIT(4)
33 #define DW9718S_CONTROL_UVLO_DISABLE	BIT(5)
34 #define DW9718S_DEFAULT_SAC		4
35 
36 #define DW9718S_VCM_CURRENT		CCI_REG16(2)
37 
38 #define DW9718S_SW			CCI_REG8(4)
39 #define DW9718S_SW_VCM_FREQ_MASK	0xF
40 #define DW9718S_DEFAULT_VCM_FREQ	0
41 
42 #define DW9718S_SACT			CCI_REG8(5)
43 #define DW9718S_SACT_PERIOD_8_8MS	0x19
44 
45 #define DW9719_INFO			CCI_REG8(0)
46 #define DW9719_ID			0xF1
47 #define DW9761_ID			0xF4
48 
49 #define DW9719_CONTROL			CCI_REG8(2)
50 #define DW9719_STANDBY			0x00
51 #define DW9719_SHUTDOWN			0x01
52 #define DW9719_ENABLE_RINGING		0x02
53 
54 #define DW9719_VCM_CURRENT		CCI_REG16(3)
55 
56 #define DW9719_STATUS			CCI_REG16(5)
57 #define DW9719_STATUS_BUSY		BIT(0)
58 
59 #define DW9719_MODE			CCI_REG8(6)
60 #define DW9719_MODE_SAC_SHIFT		4
61 #define DW9719_DEFAULT_SAC		4
62 #define DW9761_DEFAULT_SAC		6
63 
64 #define DW9719_VCM_FREQ			CCI_REG8(7)
65 #define DW9719_DEFAULT_VCM_FREQ		0x60
66 #define DW9761_DEFAULT_VCM_FREQ		0x3E
67 
68 #define DW9761_VCM_PRELOAD		CCI_REG8(8)
69 #define DW9761_DEFAULT_VCM_PRELOAD	0x73
70 
71 #define DW9800K_DEFAULT_SAC		1
72 #define DW9800K_MODE_SAC_SHIFT		6
73 #define DW9800K_DEFAULT_VCM_FREQ		0x10
74 
75 #define to_dw9719_device(x) container_of(x, struct dw9719_device, sd)
76 
77 enum dw9719_model {
78 	DW9718S,
79 	DW9719,
80 	DW9761,
81 	DW9800K,
82 };
83 
84 struct dw9719_device {
85 	struct v4l2_subdev sd;
86 	struct device *dev;
87 	struct regmap *regmap;
88 	struct regulator *regulator;
89 	enum dw9719_model model;
90 	u32 mode_low_bits;
91 	u32 sac_mode;
92 	u32 vcm_freq;
93 
94 	struct dw9719_v4l2_ctrls {
95 		struct v4l2_ctrl_handler handler;
96 		struct v4l2_ctrl *focus;
97 	} ctrls;
98 };
99 
100 static int dw9719_power_down(struct dw9719_device *dw9719)
101 {
102 	u32 reg_pwr = dw9719->model == DW9718S ? DW9718S_PD : DW9719_CONTROL;
103 
104 	/*
105 	 * Worth engaging the internal SHUTDOWN mode especially due to the
106 	 * regulator being potentially shared with other devices.
107 	 */
108 	if (cci_write(dw9719->regmap, reg_pwr, DW9719_SHUTDOWN, NULL))
109 		dev_err(dw9719->dev, "Error writing to power register\n");
110 	return regulator_disable(dw9719->regulator);
111 }
112 
113 static int dw9719_power_up(struct dw9719_device *dw9719, bool detect)
114 {
115 	u32 reg_pwr = dw9719->model == DW9718S ? DW9718S_PD : DW9719_CONTROL;
116 	u64 val;
117 	int ret;
118 	int err;
119 
120 	ret = regulator_enable(dw9719->regulator);
121 	if (ret)
122 		return ret;
123 
124 	/*
125 	 * Need 100us to transition from SHUTDOWN to STANDBY.
126 	 * Jiggle the SCL pin to wake up the device (even when the regulator is
127 	 * shared) and wait double the time to be sure, as 100us is not enough
128 	 * at least on the DW9718S as found on the motorola-nora smartphone,
129 	 * then retry the write.
130 	 */
131 	cci_write(dw9719->regmap, reg_pwr, DW9719_STANDBY, NULL);
132 	/* the jiggle is expected to fail, don't even log that as error */
133 	fsleep(200);
134 	cci_write(dw9719->regmap, reg_pwr, DW9719_STANDBY, &ret);
135 
136 	if (detect) {
137 		/* These models do not have an INFO register */
138 		switch (dw9719->model) {
139 		case DW9718S:
140 			dw9719->sac_mode = DW9718S_DEFAULT_SAC;
141 			dw9719->vcm_freq = DW9718S_DEFAULT_VCM_FREQ;
142 			goto props;
143 		case DW9800K:
144 			dw9719->sac_mode = DW9800K_DEFAULT_SAC;
145 			dw9719->vcm_freq = DW9800K_DEFAULT_VCM_FREQ;
146 			goto props;
147 		default:
148 			break;
149 		}
150 
151 		ret = cci_read(dw9719->regmap, DW9719_INFO, &val, NULL);
152 		if (ret < 0)
153 			return ret;
154 
155 		switch (val) {
156 		case DW9719_ID:
157 			dw9719->model = DW9719;
158 			dw9719->mode_low_bits = 0x00;
159 			dw9719->sac_mode = DW9719_DEFAULT_SAC;
160 			dw9719->vcm_freq = DW9719_DEFAULT_VCM_FREQ;
161 			break;
162 		case DW9761_ID:
163 			dw9719->model = DW9761;
164 			dw9719->mode_low_bits = 0x01;
165 			dw9719->sac_mode = DW9761_DEFAULT_SAC;
166 			dw9719->vcm_freq = DW9761_DEFAULT_VCM_FREQ;
167 			break;
168 		default:
169 			dev_err(dw9719->dev,
170 				"Error unknown device id 0x%02llx\n", val);
171 			return -ENXIO;
172 		}
173 
174 props:
175 		/* Optional indication of SAC mode select */
176 		device_property_read_u32(dw9719->dev, "dongwoon,sac-mode",
177 					 &dw9719->sac_mode);
178 
179 		/* Optional indication of VCM frequency */
180 		err = device_property_read_u32(dw9719->dev, "dongwoon,vcm-freq",
181 					       &dw9719->vcm_freq);
182 		if (err == 0)
183 			dev_warn(dw9719->dev, "dongwoon,vcm-freq property is deprecated, please use dongwoon,vcm-prescale\n");
184 
185 		/* Optional indication of VCM prescale */
186 		device_property_read_u32(dw9719->dev, "dongwoon,vcm-prescale",
187 					 &dw9719->vcm_freq);
188 	}
189 
190 	switch (dw9719->model) {
191 	case DW9800K:
192 		cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_ENABLE_RINGING, &ret);
193 		cci_write(dw9719->regmap, DW9719_MODE,
194 			  dw9719->sac_mode << DW9800K_MODE_SAC_SHIFT, &ret);
195 		cci_write(dw9719->regmap, DW9719_VCM_FREQ, dw9719->vcm_freq, &ret);
196 		break;
197 	case DW9718S:
198 		/* Datasheet says [OCP/UVLO] should be disabled below 2.5V */
199 		dw9719->sac_mode &= DW9718S_CONTROL_SAC_MASK;
200 		cci_write(dw9719->regmap, DW9718S_CONTROL,
201 			  DW9718S_CONTROL_SW_LINEAR |
202 			  (dw9719->sac_mode << DW9718S_CONTROL_SAC_SHIFT) |
203 			  DW9718S_CONTROL_OCP_DISABLE |
204 			  DW9718S_CONTROL_UVLO_DISABLE, &ret);
205 		cci_write(dw9719->regmap, DW9718S_SACT,
206 			  DW9718S_SACT_PERIOD_8_8MS, &ret);
207 		cci_write(dw9719->regmap, DW9718S_SW,
208 			  dw9719->vcm_freq & DW9718S_SW_VCM_FREQ_MASK, &ret);
209 		break;
210 	case DW9761:
211 		cci_write(dw9719->regmap, DW9761_VCM_PRELOAD,
212 			  DW9761_DEFAULT_VCM_PRELOAD, &ret);
213 		fallthrough;
214 	case DW9719:
215 		cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_ENABLE_RINGING, &ret);
216 		cci_write(dw9719->regmap, DW9719_MODE, dw9719->mode_low_bits |
217 				  (dw9719->sac_mode << DW9719_MODE_SAC_SHIFT), &ret);
218 		cci_write(dw9719->regmap, DW9719_VCM_FREQ, dw9719->vcm_freq, &ret);
219 	}
220 
221 	if (ret)
222 		dw9719_power_down(dw9719);
223 
224 	return ret;
225 }
226 
227 static int dw9719_t_focus_abs(struct dw9719_device *dw9719, s32 value)
228 {
229 	u32 reg = dw9719->model == DW9718S ? DW9718S_VCM_CURRENT
230 					   : DW9719_VCM_CURRENT;
231 	return cci_write(dw9719->regmap, reg, value, NULL);
232 }
233 
234 static int dw9719_set_ctrl(struct v4l2_ctrl *ctrl)
235 {
236 	struct dw9719_device *dw9719 = container_of(ctrl->handler,
237 						    struct dw9719_device,
238 						    ctrls.handler);
239 	int ret;
240 
241 	/* Only apply changes to the controls if the device is powered up */
242 	if (!pm_runtime_get_if_in_use(dw9719->dev))
243 		return 0;
244 
245 	switch (ctrl->id) {
246 	case V4L2_CID_FOCUS_ABSOLUTE:
247 		ret = dw9719_t_focus_abs(dw9719, ctrl->val);
248 		break;
249 	default:
250 		ret = -EINVAL;
251 	}
252 
253 	pm_runtime_put(dw9719->dev);
254 
255 	return ret;
256 }
257 
258 static const struct v4l2_ctrl_ops dw9719_ctrl_ops = {
259 	.s_ctrl = dw9719_set_ctrl,
260 };
261 
262 static int dw9719_suspend(struct device *dev)
263 {
264 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
265 	struct dw9719_device *dw9719 = to_dw9719_device(sd);
266 	int ret;
267 	int val;
268 
269 	for (val = dw9719->ctrls.focus->val; val >= 0;
270 	     val -= DW9719_CTRL_STEPS) {
271 		ret = dw9719_t_focus_abs(dw9719, val);
272 		if (ret)
273 			return ret;
274 
275 		usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10);
276 	}
277 
278 	return dw9719_power_down(dw9719);
279 }
280 
281 static int dw9719_resume(struct device *dev)
282 {
283 	struct v4l2_subdev *sd = dev_get_drvdata(dev);
284 	struct dw9719_device *dw9719 = to_dw9719_device(sd);
285 	int current_focus = dw9719->ctrls.focus->val;
286 	int ret;
287 	int val;
288 
289 	ret = dw9719_power_up(dw9719, false);
290 	if (ret)
291 		return ret;
292 
293 	for (val = current_focus % DW9719_CTRL_STEPS; val < current_focus;
294 	     val += DW9719_CTRL_STEPS) {
295 		ret = dw9719_t_focus_abs(dw9719, val);
296 		if (ret)
297 			goto err_power_down;
298 
299 		usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10);
300 	}
301 
302 	return 0;
303 
304 err_power_down:
305 	dw9719_power_down(dw9719);
306 	return ret;
307 }
308 
309 static int dw9719_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
310 {
311 	return pm_runtime_resume_and_get(sd->dev);
312 }
313 
314 static int dw9719_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
315 {
316 	pm_runtime_put_autosuspend(sd->dev);
317 
318 	return 0;
319 }
320 
321 static const struct v4l2_subdev_internal_ops dw9719_internal_ops = {
322 	.open = dw9719_open,
323 	.close = dw9719_close,
324 };
325 
326 static int dw9719_init_controls(struct dw9719_device *dw9719)
327 {
328 	const struct v4l2_ctrl_ops *ops = &dw9719_ctrl_ops;
329 	int ret;
330 
331 	v4l2_ctrl_handler_init(&dw9719->ctrls.handler, 1);
332 
333 	dw9719->ctrls.focus = v4l2_ctrl_new_std(&dw9719->ctrls.handler, ops,
334 						V4L2_CID_FOCUS_ABSOLUTE, 0,
335 						DW9719_MAX_FOCUS_POS, 1, 0);
336 
337 	if (dw9719->ctrls.handler.error) {
338 		dev_err(dw9719->dev, "Error initialising v4l2 ctrls\n");
339 		ret = dw9719->ctrls.handler.error;
340 		goto err_free_handler;
341 	}
342 
343 	dw9719->sd.ctrl_handler = &dw9719->ctrls.handler;
344 	return 0;
345 
346 err_free_handler:
347 	v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
348 	return ret;
349 }
350 
351 static const struct v4l2_subdev_ops dw9719_ops = { };
352 
353 static int dw9719_probe(struct i2c_client *client)
354 {
355 	struct dw9719_device *dw9719;
356 	int ret;
357 
358 	dw9719 = devm_kzalloc(&client->dev, sizeof(*dw9719), GFP_KERNEL);
359 	if (!dw9719)
360 		return -ENOMEM;
361 
362 	dw9719->model = (enum dw9719_model)(uintptr_t)i2c_get_match_data(client);
363 
364 	dw9719->regmap = devm_cci_regmap_init_i2c(client, 8);
365 	if (IS_ERR(dw9719->regmap))
366 		return PTR_ERR(dw9719->regmap);
367 
368 	dw9719->dev = &client->dev;
369 
370 	dw9719->regulator = devm_regulator_get(&client->dev, "vdd");
371 	if (IS_ERR(dw9719->regulator))
372 		return dev_err_probe(&client->dev, PTR_ERR(dw9719->regulator),
373 				     "getting regulator\n");
374 
375 	v4l2_i2c_subdev_init(&dw9719->sd, client, &dw9719_ops);
376 	dw9719->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
377 	dw9719->sd.internal_ops = &dw9719_internal_ops;
378 
379 	ret = dw9719_init_controls(dw9719);
380 	if (ret)
381 		return ret;
382 
383 	ret = media_entity_pads_init(&dw9719->sd.entity, 0, NULL);
384 	if (ret < 0)
385 		goto err_free_ctrl_handler;
386 
387 	dw9719->sd.entity.function = MEDIA_ENT_F_LENS;
388 
389 	/*
390 	 * We need the driver to work in the event that pm runtime is disable in
391 	 * the kernel, so power up and verify the chip now. In the event that
392 	 * runtime pm is disabled this will leave the chip on, so that the lens
393 	 * will work.
394 	 */
395 
396 	ret = dw9719_power_up(dw9719, true);
397 	if (ret)
398 		goto err_cleanup_media;
399 
400 	pm_runtime_set_active(&client->dev);
401 	pm_runtime_get_noresume(&client->dev);
402 	pm_runtime_enable(&client->dev);
403 
404 	ret = v4l2_async_register_subdev(&dw9719->sd);
405 	if (ret < 0)
406 		goto err_pm_runtime;
407 
408 	pm_runtime_set_autosuspend_delay(&client->dev, 1000);
409 	pm_runtime_use_autosuspend(&client->dev);
410 	pm_runtime_put_autosuspend(&client->dev);
411 
412 	return ret;
413 
414 err_pm_runtime:
415 	pm_runtime_disable(&client->dev);
416 	pm_runtime_put_noidle(&client->dev);
417 	dw9719_power_down(dw9719);
418 err_cleanup_media:
419 	media_entity_cleanup(&dw9719->sd.entity);
420 err_free_ctrl_handler:
421 	v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
422 
423 	return ret;
424 }
425 
426 static void dw9719_remove(struct i2c_client *client)
427 {
428 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
429 	struct dw9719_device *dw9719 =
430 		container_of(sd, struct dw9719_device, sd);
431 
432 	v4l2_async_unregister_subdev(sd);
433 	v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
434 	media_entity_cleanup(&dw9719->sd.entity);
435 
436 	pm_runtime_disable(&client->dev);
437 	if (!pm_runtime_status_suspended(&client->dev))
438 		dw9719_power_down(dw9719);
439 	pm_runtime_set_suspended(&client->dev);
440 }
441 
442 static const struct of_device_id dw9719_of_table[] = {
443 	{ .compatible = "dongwoon,dw9718s", .data = (const void *)DW9718S },
444 	{ .compatible = "dongwoon,dw9719", .data = (const void *)DW9719 },
445 	{ .compatible = "dongwoon,dw9761", .data = (const void *)DW9761 },
446 	{ .compatible = "dongwoon,dw9800k", .data = (const void *)DW9800K },
447 	{ }
448 };
449 MODULE_DEVICE_TABLE(of, dw9719_of_table);
450 
451 static DEFINE_RUNTIME_DEV_PM_OPS(dw9719_pm_ops, dw9719_suspend, dw9719_resume,
452 				 NULL);
453 
454 static struct i2c_driver dw9719_i2c_driver = {
455 	.driver = {
456 		.name = "dw9719",
457 		.pm = pm_sleep_ptr(&dw9719_pm_ops),
458 		.of_match_table = dw9719_of_table,
459 	},
460 	.probe = dw9719_probe,
461 	.remove = dw9719_remove,
462 };
463 module_i2c_driver(dw9719_i2c_driver);
464 
465 MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
466 MODULE_DESCRIPTION("DW9719 VCM Driver");
467 MODULE_LICENSE("GPL");
468