.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * drivers/media/i2c/ad5820.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
11 | 12 | * Sakari Ailus <sakari.ailus@iki.fi> |
---|
12 | 13 | * |
---|
13 | 14 | * Based on af_d88.c by Texas Instruments. |
---|
14 | | - * |
---|
15 | | - * This program is free software; you can redistribute it and/or |
---|
16 | | - * modify it under the terms of the GNU General Public License |
---|
17 | | - * version 2 as published by the Free Software Foundation. |
---|
18 | | - * |
---|
19 | | - * This program is distributed in the hope that it will be useful, but |
---|
20 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
21 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
22 | | - * General Public License for more details. |
---|
23 | 15 | */ |
---|
24 | 16 | |
---|
25 | 17 | #include <linux/errno.h> |
---|
.. | .. |
---|
27 | 19 | #include <linux/kernel.h> |
---|
28 | 20 | #include <linux/module.h> |
---|
29 | 21 | #include <linux/regulator/consumer.h> |
---|
| 22 | +#include <linux/gpio/consumer.h> |
---|
30 | 23 | |
---|
31 | 24 | #include <media/v4l2-ctrls.h> |
---|
32 | 25 | #include <media/v4l2-device.h> |
---|
33 | 26 | #include <media/v4l2-subdev.h> |
---|
34 | | - |
---|
35 | | -#define AD5820_NAME "ad5820" |
---|
36 | 27 | |
---|
37 | 28 | /* Register definitions */ |
---|
38 | 29 | #define AD5820_POWER_DOWN (1 << 15) |
---|
.. | .. |
---|
54 | 45 | u32 focus_absolute; |
---|
55 | 46 | u32 focus_ramp_time; |
---|
56 | 47 | u32 focus_ramp_mode; |
---|
| 48 | + |
---|
| 49 | + struct gpio_desc *enable_gpio; |
---|
57 | 50 | |
---|
58 | 51 | struct mutex power_lock; |
---|
59 | 52 | int power_count; |
---|
.. | .. |
---|
122 | 115 | ret = ad5820_update_hw(coil); |
---|
123 | 116 | } |
---|
124 | 117 | |
---|
| 118 | + gpiod_set_value_cansleep(coil->enable_gpio, 0); |
---|
| 119 | + |
---|
125 | 120 | ret2 = regulator_disable(coil->vana); |
---|
126 | 121 | if (ret) |
---|
127 | 122 | return ret; |
---|
.. | .. |
---|
136 | 131 | if (ret < 0) |
---|
137 | 132 | return ret; |
---|
138 | 133 | |
---|
| 134 | + gpiod_set_value_cansleep(coil->enable_gpio, 1); |
---|
| 135 | + |
---|
139 | 136 | if (restore) { |
---|
140 | 137 | /* Restore the hardware settings. */ |
---|
141 | 138 | coil->standby = false; |
---|
.. | .. |
---|
146 | 143 | return 0; |
---|
147 | 144 | |
---|
148 | 145 | fail: |
---|
| 146 | + gpiod_set_value_cansleep(coil->enable_gpio, 0); |
---|
149 | 147 | coil->standby = true; |
---|
150 | 148 | regulator_disable(coil->vana); |
---|
151 | 149 | |
---|
.. | .. |
---|
312 | 310 | return ret; |
---|
313 | 311 | } |
---|
314 | 312 | |
---|
| 313 | + coil->enable_gpio = devm_gpiod_get_optional(&client->dev, "enable", |
---|
| 314 | + GPIOD_OUT_LOW); |
---|
| 315 | + if (IS_ERR(coil->enable_gpio)) { |
---|
| 316 | + ret = PTR_ERR(coil->enable_gpio); |
---|
| 317 | + if (ret != -EPROBE_DEFER) |
---|
| 318 | + dev_err(&client->dev, "could not get enable gpio\n"); |
---|
| 319 | + return ret; |
---|
| 320 | + } |
---|
| 321 | + |
---|
315 | 322 | mutex_init(&coil->power_lock); |
---|
316 | 323 | |
---|
317 | 324 | v4l2_i2c_subdev_init(&coil->subdev, client, &ad5820_ops); |
---|
318 | 325 | coil->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
---|
319 | 326 | coil->subdev.internal_ops = &ad5820_internal_ops; |
---|
320 | | - strcpy(coil->subdev.name, "ad5820 focus"); |
---|
| 327 | + coil->subdev.entity.function = MEDIA_ENT_F_LENS; |
---|
| 328 | + strscpy(coil->subdev.name, "ad5820 focus", sizeof(coil->subdev.name)); |
---|
321 | 329 | |
---|
322 | 330 | ret = media_entity_pads_init(&coil->subdev.entity, 0, NULL); |
---|
323 | 331 | if (ret < 0) |
---|
.. | .. |
---|
349 | 357 | } |
---|
350 | 358 | |
---|
351 | 359 | static const struct i2c_device_id ad5820_id_table[] = { |
---|
352 | | - { AD5820_NAME, 0 }, |
---|
| 360 | + { "ad5820", 0 }, |
---|
| 361 | + { "ad5821", 0 }, |
---|
| 362 | + { "ad5823", 0 }, |
---|
353 | 363 | { } |
---|
354 | 364 | }; |
---|
355 | 365 | MODULE_DEVICE_TABLE(i2c, ad5820_id_table); |
---|
| 366 | + |
---|
| 367 | +static const struct of_device_id ad5820_of_table[] = { |
---|
| 368 | + { .compatible = "adi,ad5820" }, |
---|
| 369 | + { .compatible = "adi,ad5821" }, |
---|
| 370 | + { .compatible = "adi,ad5823" }, |
---|
| 371 | + { } |
---|
| 372 | +}; |
---|
| 373 | +MODULE_DEVICE_TABLE(of, ad5820_of_table); |
---|
356 | 374 | |
---|
357 | 375 | static SIMPLE_DEV_PM_OPS(ad5820_pm, ad5820_suspend, ad5820_resume); |
---|
358 | 376 | |
---|
359 | 377 | static struct i2c_driver ad5820_i2c_driver = { |
---|
360 | 378 | .driver = { |
---|
361 | | - .name = AD5820_NAME, |
---|
| 379 | + .name = "ad5820", |
---|
362 | 380 | .pm = &ad5820_pm, |
---|
| 381 | + .of_match_table = ad5820_of_table, |
---|
363 | 382 | }, |
---|
364 | 383 | .probe = ad5820_probe, |
---|
365 | 384 | .remove = ad5820_remove, |
---|