forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-10-09 244b2c5ca8b14627e4a17755e5922221e121c771
kernel/drivers/iio/light/al3320a.c
....@@ -1,21 +1,21 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * AL3320A - Dyna Image Ambient Light Sensor
34 *
45 * Copyright (c) 2014, Intel Corporation.
56 *
6
- * This file is subject to the terms and conditions of version 2 of
7
- * the GNU General Public License. See the file COPYING in the main
8
- * directory of this archive for more details.
9
- *
107 * IIO driver for AL3320A (7-bit I2C slave address 0x1C).
118 *
129 * TODO: interrupt support, thresholds
13
- *
10
+ * When the driver will get support for interrupt handling, then interrupt
11
+ * will need to be disabled before turning sensor OFF in order to avoid
12
+ * potential races with the interrupt handling.
1413 */
1514
16
-#include <linux/module.h>
17
-#include <linux/init.h>
15
+#include <linux/bitfield.h>
1816 #include <linux/i2c.h>
17
+#include <linux/module.h>
18
+#include <linux/of.h>
1919
2020 #include <linux/iio/iio.h>
2121 #include <linux/iio/sysfs.h>
....@@ -40,8 +40,7 @@
4040 #define AL3320A_CONFIG_DISABLE 0x00
4141 #define AL3320A_CONFIG_ENABLE 0x01
4242
43
-#define AL3320A_GAIN_SHIFT 1
44
-#define AL3320A_GAIN_MASK (BIT(2) | BIT(1))
43
+#define AL3320A_GAIN_MASK GENMASK(2, 1)
4544
4645 /* chip params default values */
4746 #define AL3320A_DEFAULT_MEAN_TIME 4
....@@ -83,18 +82,31 @@
8382 .attrs = al3320a_attributes,
8483 };
8584
85
+static int al3320a_set_pwr(struct i2c_client *client, bool pwr)
86
+{
87
+ u8 val = pwr ? AL3320A_CONFIG_ENABLE : AL3320A_CONFIG_DISABLE;
88
+ return i2c_smbus_write_byte_data(client, AL3320A_REG_CONFIG, val);
89
+}
90
+
91
+static void al3320a_set_pwr_off(void *_data)
92
+{
93
+ struct al3320a_data *data = _data;
94
+
95
+ al3320a_set_pwr(data->client, false);
96
+}
97
+
8698 static int al3320a_init(struct al3320a_data *data)
8799 {
88100 int ret;
89101
90
- /* power on */
91
- ret = i2c_smbus_write_byte_data(data->client, AL3320A_REG_CONFIG,
92
- AL3320A_CONFIG_ENABLE);
102
+ ret = al3320a_set_pwr(data->client, true);
103
+
93104 if (ret < 0)
94105 return ret;
95106
96107 ret = i2c_smbus_write_byte_data(data->client, AL3320A_REG_CONFIG_RANGE,
97
- AL3320A_RANGE_3 << AL3320A_GAIN_SHIFT);
108
+ FIELD_PREP(AL3320A_GAIN_MASK,
109
+ AL3320A_RANGE_3));
98110 if (ret < 0)
99111 return ret;
100112
....@@ -137,7 +149,7 @@
137149 if (ret < 0)
138150 return ret;
139151
140
- ret = (ret & AL3320A_GAIN_MASK) >> AL3320A_GAIN_SHIFT;
152
+ ret = FIELD_GET(AL3320A_GAIN_MASK, ret);
141153 *val = al3320a_scales[ret][0];
142154 *val2 = al3320a_scales[ret][1];
143155
....@@ -156,11 +168,13 @@
156168 switch (mask) {
157169 case IIO_CHAN_INFO_SCALE:
158170 for (i = 0; i < ARRAY_SIZE(al3320a_scales); i++) {
159
- if (val == al3320a_scales[i][0] &&
160
- val2 == al3320a_scales[i][1])
161
- return i2c_smbus_write_byte_data(data->client,
171
+ if (val != al3320a_scales[i][0] ||
172
+ val2 != al3320a_scales[i][1])
173
+ continue;
174
+
175
+ return i2c_smbus_write_byte_data(data->client,
162176 AL3320A_REG_CONFIG_RANGE,
163
- i << AL3320A_GAIN_SHIFT);
177
+ FIELD_PREP(AL3320A_GAIN_MASK, i));
164178 }
165179 break;
166180 }
....@@ -188,7 +202,6 @@
188202 i2c_set_clientdata(client, indio_dev);
189203 data->client = client;
190204
191
- indio_dev->dev.parent = &client->dev;
192205 indio_dev->info = &al3320a_info;
193206 indio_dev->name = AL3320A_DRV_NAME;
194207 indio_dev->channels = al3320a_channels;
....@@ -200,14 +213,27 @@
200213 dev_err(&client->dev, "al3320a chip init failed\n");
201214 return ret;
202215 }
216
+
217
+ ret = devm_add_action_or_reset(&client->dev,
218
+ al3320a_set_pwr_off,
219
+ data);
220
+ if (ret < 0)
221
+ return ret;
222
+
203223 return devm_iio_device_register(&client->dev, indio_dev);
204224 }
205225
206
-static int al3320a_remove(struct i2c_client *client)
226
+static int __maybe_unused al3320a_suspend(struct device *dev)
207227 {
208
- return i2c_smbus_write_byte_data(client, AL3320A_REG_CONFIG,
209
- AL3320A_CONFIG_DISABLE);
228
+ return al3320a_set_pwr(to_i2c_client(dev), false);
210229 }
230
+
231
+static int __maybe_unused al3320a_resume(struct device *dev)
232
+{
233
+ return al3320a_set_pwr(to_i2c_client(dev), true);
234
+}
235
+
236
+static SIMPLE_DEV_PM_OPS(al3320a_pm_ops, al3320a_suspend, al3320a_resume);
211237
212238 static const struct i2c_device_id al3320a_id[] = {
213239 {"al3320a", 0},
....@@ -215,12 +241,19 @@
215241 };
216242 MODULE_DEVICE_TABLE(i2c, al3320a_id);
217243
244
+static const struct of_device_id al3320a_of_match[] = {
245
+ { .compatible = "dynaimage,al3320a", },
246
+ {},
247
+};
248
+MODULE_DEVICE_TABLE(of, al3320a_of_match);
249
+
218250 static struct i2c_driver al3320a_driver = {
219251 .driver = {
220252 .name = AL3320A_DRV_NAME,
253
+ .of_match_table = al3320a_of_match,
254
+ .pm = &al3320a_pm_ops,
221255 },
222256 .probe = al3320a_probe,
223
- .remove = al3320a_remove,
224257 .id_table = al3320a_id,
225258 };
226259