1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * drivers/media/i2c/ad5820.c |
4 | * |
5 | * AD5820 DAC driver for camera voice coil focus. |
6 | * |
7 | * Copyright (C) 2008 Nokia Corporation |
8 | * Copyright (C) 2007 Texas Instruments |
9 | * Copyright (C) 2016 Pavel Machek <pavel@ucw.cz> |
10 | * |
11 | * Contact: Tuukka Toivonen <tuukkat76@gmail.com> |
12 | * Sakari Ailus <sakari.ailus@iki.fi> |
13 | * |
14 | * Based on af_d88.c by Texas Instruments. |
15 | */ |
16 | |
17 | #include <linux/errno.h> |
18 | #include <linux/i2c.h> |
19 | #include <linux/kernel.h> |
20 | #include <linux/module.h> |
21 | #include <linux/regulator/consumer.h> |
22 | #include <linux/gpio/consumer.h> |
23 | |
24 | #include <media/v4l2-ctrls.h> |
25 | #include <media/v4l2-device.h> |
26 | #include <media/v4l2-subdev.h> |
27 | |
28 | /* Register definitions */ |
29 | #define AD5820_POWER_DOWN (1 << 15) |
30 | #define AD5820_DAC_SHIFT 4 |
31 | #define AD5820_RAMP_MODE_LINEAR (0 << 3) |
32 | #define AD5820_RAMP_MODE_64_16 (1 << 3) |
33 | |
34 | #define CODE_TO_RAMP_US(s) ((s) == 0 ? 0 : (1 << ((s) - 1)) * 50) |
35 | #define RAMP_US_TO_CODE(c) fls(((c) + ((c)>>1)) / 50) |
36 | |
37 | #define to_ad5820_device(sd) container_of(sd, struct ad5820_device, subdev) |
38 | |
39 | struct ad5820_device { |
40 | struct v4l2_subdev subdev; |
41 | struct ad5820_platform_data *platform_data; |
42 | struct regulator *vana; |
43 | |
44 | struct v4l2_ctrl_handler ctrls; |
45 | u32 focus_absolute; |
46 | u32 focus_ramp_time; |
47 | u32 focus_ramp_mode; |
48 | |
49 | struct gpio_desc *enable_gpio; |
50 | |
51 | struct mutex power_lock; |
52 | int power_count; |
53 | |
54 | bool standby; |
55 | }; |
56 | |
57 | static int ad5820_write(struct ad5820_device *coil, u16 data) |
58 | { |
59 | struct i2c_client *client = v4l2_get_subdevdata(sd: &coil->subdev); |
60 | struct i2c_msg msg; |
61 | __be16 be_data; |
62 | int r; |
63 | |
64 | if (!client->adapter) |
65 | return -ENODEV; |
66 | |
67 | be_data = cpu_to_be16(data); |
68 | msg.addr = client->addr; |
69 | msg.flags = 0; |
70 | msg.len = 2; |
71 | msg.buf = (u8 *)&be_data; |
72 | |
73 | r = i2c_transfer(adap: client->adapter, msgs: &msg, num: 1); |
74 | if (r < 0) { |
75 | dev_err(&client->dev, "write failed, error %d\n" , r); |
76 | return r; |
77 | } |
78 | |
79 | return 0; |
80 | } |
81 | |
82 | /* |
83 | * Calculate status word and write it to the device based on current |
84 | * values of V4L2 controls. It is assumed that the stored V4L2 control |
85 | * values are properly limited and rounded. |
86 | */ |
87 | static int ad5820_update_hw(struct ad5820_device *coil) |
88 | { |
89 | u16 status; |
90 | |
91 | status = RAMP_US_TO_CODE(coil->focus_ramp_time); |
92 | status |= coil->focus_ramp_mode |
93 | ? AD5820_RAMP_MODE_64_16 : AD5820_RAMP_MODE_LINEAR; |
94 | status |= coil->focus_absolute << AD5820_DAC_SHIFT; |
95 | |
96 | if (coil->standby) |
97 | status |= AD5820_POWER_DOWN; |
98 | |
99 | return ad5820_write(coil, data: status); |
100 | } |
101 | |
102 | /* |
103 | * Power handling |
104 | */ |
105 | static int ad5820_power_off(struct ad5820_device *coil, bool standby) |
106 | { |
107 | int ret = 0, ret2; |
108 | |
109 | /* |
110 | * Go to standby first as real power off my be denied by the hardware |
111 | * (single power line control for both coil and sensor). |
112 | */ |
113 | if (standby) { |
114 | coil->standby = true; |
115 | ret = ad5820_update_hw(coil); |
116 | } |
117 | |
118 | gpiod_set_value_cansleep(desc: coil->enable_gpio, value: 0); |
119 | |
120 | ret2 = regulator_disable(regulator: coil->vana); |
121 | if (ret) |
122 | return ret; |
123 | return ret2; |
124 | } |
125 | |
126 | static int ad5820_power_on(struct ad5820_device *coil, bool restore) |
127 | { |
128 | int ret; |
129 | |
130 | ret = regulator_enable(regulator: coil->vana); |
131 | if (ret < 0) |
132 | return ret; |
133 | |
134 | gpiod_set_value_cansleep(desc: coil->enable_gpio, value: 1); |
135 | |
136 | if (restore) { |
137 | /* Restore the hardware settings. */ |
138 | coil->standby = false; |
139 | ret = ad5820_update_hw(coil); |
140 | if (ret) |
141 | goto fail; |
142 | } |
143 | return 0; |
144 | |
145 | fail: |
146 | gpiod_set_value_cansleep(desc: coil->enable_gpio, value: 0); |
147 | coil->standby = true; |
148 | regulator_disable(regulator: coil->vana); |
149 | |
150 | return ret; |
151 | } |
152 | |
153 | /* |
154 | * V4L2 controls |
155 | */ |
156 | static int ad5820_set_ctrl(struct v4l2_ctrl *ctrl) |
157 | { |
158 | struct ad5820_device *coil = |
159 | container_of(ctrl->handler, struct ad5820_device, ctrls); |
160 | |
161 | switch (ctrl->id) { |
162 | case V4L2_CID_FOCUS_ABSOLUTE: |
163 | coil->focus_absolute = ctrl->val; |
164 | return ad5820_update_hw(coil); |
165 | } |
166 | |
167 | return 0; |
168 | } |
169 | |
170 | static const struct v4l2_ctrl_ops ad5820_ctrl_ops = { |
171 | .s_ctrl = ad5820_set_ctrl, |
172 | }; |
173 | |
174 | |
175 | static int ad5820_init_controls(struct ad5820_device *coil) |
176 | { |
177 | v4l2_ctrl_handler_init(&coil->ctrls, 1); |
178 | |
179 | /* |
180 | * V4L2_CID_FOCUS_ABSOLUTE |
181 | * |
182 | * Minimum current is 0 mA, maximum is 100 mA. Thus, 1 code is |
183 | * equivalent to 100/1023 = 0.0978 mA. Nevertheless, we do not use [mA] |
184 | * for focus position, because it is meaningless for user. Meaningful |
185 | * would be to use focus distance or even its inverse, but since the |
186 | * driver doesn't have sufficiently knowledge to do the conversion, we |
187 | * will just use abstract codes here. In any case, smaller value = focus |
188 | * position farther from camera. The default zero value means focus at |
189 | * infinity, and also least current consumption. |
190 | */ |
191 | v4l2_ctrl_new_std(hdl: &coil->ctrls, ops: &ad5820_ctrl_ops, |
192 | V4L2_CID_FOCUS_ABSOLUTE, min: 0, max: 1023, step: 1, def: 0); |
193 | |
194 | if (coil->ctrls.error) |
195 | return coil->ctrls.error; |
196 | |
197 | coil->focus_absolute = 0; |
198 | coil->focus_ramp_time = 0; |
199 | coil->focus_ramp_mode = 0; |
200 | |
201 | coil->subdev.ctrl_handler = &coil->ctrls; |
202 | |
203 | return 0; |
204 | } |
205 | |
206 | /* |
207 | * V4L2 subdev operations |
208 | */ |
209 | static int ad5820_registered(struct v4l2_subdev *subdev) |
210 | { |
211 | struct ad5820_device *coil = to_ad5820_device(subdev); |
212 | |
213 | return ad5820_init_controls(coil); |
214 | } |
215 | |
216 | static int |
217 | ad5820_set_power(struct v4l2_subdev *subdev, int on) |
218 | { |
219 | struct ad5820_device *coil = to_ad5820_device(subdev); |
220 | int ret = 0; |
221 | |
222 | mutex_lock(&coil->power_lock); |
223 | |
224 | /* |
225 | * If the power count is modified from 0 to != 0 or from != 0 to 0, |
226 | * update the power state. |
227 | */ |
228 | if (coil->power_count == !on) { |
229 | ret = on ? ad5820_power_on(coil, restore: true) : |
230 | ad5820_power_off(coil, standby: true); |
231 | if (ret < 0) |
232 | goto done; |
233 | } |
234 | |
235 | /* Update the power count. */ |
236 | coil->power_count += on ? 1 : -1; |
237 | WARN_ON(coil->power_count < 0); |
238 | |
239 | done: |
240 | mutex_unlock(lock: &coil->power_lock); |
241 | return ret; |
242 | } |
243 | |
244 | static int ad5820_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
245 | { |
246 | return ad5820_set_power(subdev: sd, on: 1); |
247 | } |
248 | |
249 | static int ad5820_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) |
250 | { |
251 | return ad5820_set_power(subdev: sd, on: 0); |
252 | } |
253 | |
254 | static const struct v4l2_subdev_core_ops ad5820_core_ops = { |
255 | .s_power = ad5820_set_power, |
256 | }; |
257 | |
258 | static const struct v4l2_subdev_ops ad5820_ops = { |
259 | .core = &ad5820_core_ops, |
260 | }; |
261 | |
262 | static const struct v4l2_subdev_internal_ops ad5820_internal_ops = { |
263 | .registered = ad5820_registered, |
264 | .open = ad5820_open, |
265 | .close = ad5820_close, |
266 | }; |
267 | |
268 | /* |
269 | * I2C driver |
270 | */ |
271 | static int __maybe_unused ad5820_suspend(struct device *dev) |
272 | { |
273 | struct v4l2_subdev *subdev = dev_get_drvdata(dev); |
274 | struct ad5820_device *coil = to_ad5820_device(subdev); |
275 | |
276 | if (!coil->power_count) |
277 | return 0; |
278 | |
279 | return ad5820_power_off(coil, standby: false); |
280 | } |
281 | |
282 | static int __maybe_unused ad5820_resume(struct device *dev) |
283 | { |
284 | struct v4l2_subdev *subdev = dev_get_drvdata(dev); |
285 | struct ad5820_device *coil = to_ad5820_device(subdev); |
286 | |
287 | if (!coil->power_count) |
288 | return 0; |
289 | |
290 | return ad5820_power_on(coil, restore: true); |
291 | } |
292 | |
293 | static int ad5820_probe(struct i2c_client *client) |
294 | { |
295 | struct ad5820_device *coil; |
296 | int ret; |
297 | |
298 | coil = devm_kzalloc(dev: &client->dev, size: sizeof(*coil), GFP_KERNEL); |
299 | if (!coil) |
300 | return -ENOMEM; |
301 | |
302 | coil->vana = devm_regulator_get(dev: &client->dev, id: "VANA" ); |
303 | if (IS_ERR(ptr: coil->vana)) |
304 | return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: coil->vana), |
305 | fmt: "could not get regulator for vana\n" ); |
306 | |
307 | coil->enable_gpio = devm_gpiod_get_optional(dev: &client->dev, con_id: "enable" , |
308 | flags: GPIOD_OUT_LOW); |
309 | if (IS_ERR(ptr: coil->enable_gpio)) |
310 | return dev_err_probe(dev: &client->dev, err: PTR_ERR(ptr: coil->enable_gpio), |
311 | fmt: "could not get enable gpio\n" ); |
312 | |
313 | mutex_init(&coil->power_lock); |
314 | |
315 | v4l2_i2c_subdev_init(sd: &coil->subdev, client, ops: &ad5820_ops); |
316 | coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
317 | coil->subdev.internal_ops = &ad5820_internal_ops; |
318 | coil->subdev.entity.function = MEDIA_ENT_F_LENS; |
319 | strscpy(coil->subdev.name, "ad5820 focus" , sizeof(coil->subdev.name)); |
320 | |
321 | ret = media_entity_pads_init(entity: &coil->subdev.entity, num_pads: 0, NULL); |
322 | if (ret < 0) |
323 | goto clean_mutex; |
324 | |
325 | ret = v4l2_async_register_subdev(sd: &coil->subdev); |
326 | if (ret < 0) |
327 | goto clean_entity; |
328 | |
329 | return ret; |
330 | |
331 | clean_entity: |
332 | media_entity_cleanup(entity: &coil->subdev.entity); |
333 | clean_mutex: |
334 | mutex_destroy(lock: &coil->power_lock); |
335 | return ret; |
336 | } |
337 | |
338 | static void ad5820_remove(struct i2c_client *client) |
339 | { |
340 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); |
341 | struct ad5820_device *coil = to_ad5820_device(subdev); |
342 | |
343 | v4l2_async_unregister_subdev(sd: &coil->subdev); |
344 | v4l2_ctrl_handler_free(hdl: &coil->ctrls); |
345 | media_entity_cleanup(entity: &coil->subdev.entity); |
346 | mutex_destroy(lock: &coil->power_lock); |
347 | } |
348 | |
349 | static const struct i2c_device_id ad5820_id_table[] = { |
350 | { "ad5820" , 0 }, |
351 | { "ad5821" , 0 }, |
352 | { } |
353 | }; |
354 | MODULE_DEVICE_TABLE(i2c, ad5820_id_table); |
355 | |
356 | static const struct of_device_id ad5820_of_table[] = { |
357 | { .compatible = "adi,ad5820" }, |
358 | { .compatible = "adi,ad5821" }, |
359 | { } |
360 | }; |
361 | MODULE_DEVICE_TABLE(of, ad5820_of_table); |
362 | |
363 | static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume); |
364 | |
365 | static struct i2c_driver ad5820_i2c_driver = { |
366 | .driver = { |
367 | .name = "ad5820" , |
368 | .pm = &ad5820_pm, |
369 | .of_match_table = ad5820_of_table, |
370 | }, |
371 | .probe = ad5820_probe, |
372 | .remove = ad5820_remove, |
373 | .id_table = ad5820_id_table, |
374 | }; |
375 | |
376 | module_i2c_driver(ad5820_i2c_driver); |
377 | |
378 | MODULE_AUTHOR("Tuukka Toivonen" ); |
379 | MODULE_DESCRIPTION("AD5820 camera lens driver" ); |
380 | MODULE_LICENSE("GPL" ); |
381 | |