diff options
author | Adriana Reus <adriana.reus@intel.com> | 2015-09-16 04:14:11 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2015-09-23 15:23:27 -0400 |
commit | c14f8abe5304ba46b898cd381a0857fd61f87200 (patch) | |
tree | d6d2dcb02b6b24a32d9efdf406c40374657ad8b9 | |
parent | fd2bb310ca3d3621a0f201e018e1292dca95df6e (diff) |
iio: light: Add support for UPISEMI uS5182d als and proximity sensor
Add support for UPISEMI us5182d als and proximity sensor.
Supports raw readings.
Data sheet for this device can be found here:
http://www.upi-semi.com/temp/uS5182D-DS-P0103-temp.pdf
Signed-off-by: Adriana Reus <adriana.reus@intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r-- | drivers/iio/light/Kconfig | 10 | ||||
-rw-r--r-- | drivers/iio/light/Makefile | 1 | ||||
-rw-r--r-- | drivers/iio/light/us5182d.c | 507 |
3 files changed, 518 insertions, 0 deletions
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 19b9a173fe61..cfd3df8416bb 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig | |||
@@ -300,6 +300,16 @@ config TSL4531 | |||
300 | To compile this driver as a module, choose M here: the | 300 | To compile this driver as a module, choose M here: the |
301 | module will be called tsl4531. | 301 | module will be called tsl4531. |
302 | 302 | ||
303 | config US5182D | ||
304 | tristate "UPISEMI light and proximity sensor" | ||
305 | depends on I2C | ||
306 | help | ||
307 | If you say yes here you get support for the UPISEMI US5182D | ||
308 | ambient light and proximity sensor. | ||
309 | |||
310 | This driver can also be built as a module. If so, the module | ||
311 | will be called us5182d. | ||
312 | |||
303 | config VCNL4000 | 313 | config VCNL4000 |
304 | tristate "VCNL4000 combined ALS and proximity sensor" | 314 | tristate "VCNL4000 combined ALS and proximity sensor" |
305 | depends on I2C | 315 | depends on I2C |
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 7b2244550747..b2c31053db0c 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile | |||
@@ -28,4 +28,5 @@ obj-$(CONFIG_STK3310) += stk3310.o | |||
28 | obj-$(CONFIG_TCS3414) += tcs3414.o | 28 | obj-$(CONFIG_TCS3414) += tcs3414.o |
29 | obj-$(CONFIG_TCS3472) += tcs3472.o | 29 | obj-$(CONFIG_TCS3472) += tcs3472.o |
30 | obj-$(CONFIG_TSL4531) += tsl4531.o | 30 | obj-$(CONFIG_TSL4531) += tsl4531.o |
31 | obj-$(CONFIG_US5182D) += us5182d.o | ||
31 | obj-$(CONFIG_VCNL4000) += vcnl4000.o | 32 | obj-$(CONFIG_VCNL4000) += vcnl4000.o |
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c new file mode 100644 index 000000000000..49dab3cb3e23 --- /dev/null +++ b/drivers/iio/light/us5182d.c | |||
@@ -0,0 +1,507 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015 Intel Corporation | ||
3 | * | ||
4 | * Driver for UPISEMI us5182d Proximity and Ambient Light Sensor. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License version 2 as published by | ||
8 | * the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * To do: Interrupt support. | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/acpi.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/iio/iio.h> | ||
24 | #include <linux/iio/sysfs.h> | ||
25 | #include <linux/mutex.h> | ||
26 | |||
27 | #define US5182D_REG_CFG0 0x00 | ||
28 | #define US5182D_CFG0_ONESHOT_EN BIT(6) | ||
29 | #define US5182D_CFG0_SHUTDOWN_EN BIT(7) | ||
30 | #define US5182D_CFG0_WORD_ENABLE BIT(0) | ||
31 | |||
32 | #define US5182D_REG_CFG1 0x01 | ||
33 | #define US5182D_CFG1_ALS_RES16 BIT(4) | ||
34 | #define US5182D_CFG1_AGAIN_DEFAULT 0x00 | ||
35 | |||
36 | #define US5182D_REG_CFG2 0x02 | ||
37 | #define US5182D_CFG2_PX_RES16 BIT(4) | ||
38 | #define US5182D_CFG2_PXGAIN_DEFAULT BIT(2) | ||
39 | |||
40 | #define US5182D_REG_CFG3 0x03 | ||
41 | #define US5182D_CFG3_LED_CURRENT100 (BIT(4) | BIT(5)) | ||
42 | |||
43 | #define US5182D_REG_CFG4 0x10 | ||
44 | |||
45 | /* | ||
46 | * Registers for tuning the auto dark current cancelling feature. | ||
47 | * DARK_TH(reg 0x27,0x28) - threshold (counts) for auto dark cancelling. | ||
48 | * when ALS > DARK_TH --> ALS_Code = ALS - Upper(0x2A) * Dark | ||
49 | * when ALS < DARK_TH --> ALS_Code = ALS - Lower(0x29) * Dark | ||
50 | */ | ||
51 | #define US5182D_REG_UDARK_TH 0x27 | ||
52 | #define US5182D_REG_DARK_AUTO_EN 0x2b | ||
53 | #define US5182D_REG_AUTO_LDARK_GAIN 0x29 | ||
54 | #define US5182D_REG_AUTO_HDARK_GAIN 0x2a | ||
55 | |||
56 | #define US5182D_OPMODE_ALS 0x01 | ||
57 | #define US5182D_OPMODE_PX 0x02 | ||
58 | #define US5182D_OPMODE_SHIFT 4 | ||
59 | |||
60 | #define US5182D_REG_DARK_AUTO_EN_DEFAULT 0x80 | ||
61 | #define US5182D_REG_AUTO_LDARK_GAIN_DEFAULT 0x16 | ||
62 | #define US5182D_REG_AUTO_HDARK_GAIN_DEFAULT 0x00 | ||
63 | |||
64 | #define US5182D_REG_ADL 0x0c | ||
65 | #define US5182D_REG_PDL 0x0e | ||
66 | |||
67 | #define US5182D_REG_MODE_STORE 0x21 | ||
68 | #define US5182D_STORE_MODE 0x01 | ||
69 | |||
70 | #define US5182D_REG_CHIPID 0xb2 | ||
71 | |||
72 | #define US5182D_OPMODE_MASK GENMASK(5, 4) | ||
73 | #define US5182D_AGAIN_MASK 0x07 | ||
74 | #define US5182D_RESET_CHIP 0x01 | ||
75 | |||
76 | #define US5182D_CHIPID 0x26 | ||
77 | #define US5182D_DRV_NAME "us5182d" | ||
78 | |||
79 | #define US5182D_GA_RESOLUTION 1000 | ||
80 | |||
81 | #define US5182D_READ_BYTE 1 | ||
82 | #define US5182D_READ_WORD 2 | ||
83 | #define US5182D_OPSTORE_SLEEP_TIME 20 /* ms */ | ||
84 | |||
85 | /* Available ranges: [12354, 7065, 3998, 2202, 1285, 498, 256, 138] lux */ | ||
86 | static const int us5182d_scales[] = {188500, 107800, 61000, 33600, 19600, 7600, | ||
87 | 3900, 2100}; | ||
88 | |||
89 | /* | ||
90 | * Experimental thresholds that work with US5182D sensor on evaluation board | ||
91 | * roughly between 12-32 lux | ||
92 | */ | ||
93 | static u16 us5182d_dark_ths_vals[] = {170, 200, 512, 512, 800, 2000, 4000, | ||
94 | 8000}; | ||
95 | |||
96 | enum mode { | ||
97 | US5182D_ALS_PX, | ||
98 | US5182D_ALS_ONLY, | ||
99 | US5182D_PX_ONLY | ||
100 | }; | ||
101 | |||
102 | struct us5182d_data { | ||
103 | struct i2c_client *client; | ||
104 | struct mutex lock; | ||
105 | |||
106 | /* Glass attenuation factor */ | ||
107 | u32 ga; | ||
108 | |||
109 | /* Dark gain tuning */ | ||
110 | u8 lower_dark_gain; | ||
111 | u8 upper_dark_gain; | ||
112 | u16 *us5182d_dark_ths; | ||
113 | |||
114 | u8 opmode; | ||
115 | }; | ||
116 | |||
117 | static IIO_CONST_ATTR(in_illuminance_scale_available, | ||
118 | "0.0021 0.0039 0.0076 0.0196 0.0336 0.061 0.1078 0.1885"); | ||
119 | |||
120 | static struct attribute *us5182d_attrs[] = { | ||
121 | &iio_const_attr_in_illuminance_scale_available.dev_attr.attr, | ||
122 | NULL | ||
123 | }; | ||
124 | |||
125 | static const struct attribute_group us5182d_attr_group = { | ||
126 | .attrs = us5182d_attrs, | ||
127 | }; | ||
128 | |||
129 | static const struct { | ||
130 | u8 reg; | ||
131 | u8 val; | ||
132 | } us5182d_regvals[] = { | ||
133 | {US5182D_REG_CFG0, (US5182D_CFG0_SHUTDOWN_EN | | ||
134 | US5182D_CFG0_WORD_ENABLE)}, | ||
135 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, | ||
136 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | | ||
137 | US5182D_CFG2_PXGAIN_DEFAULT)}, | ||
138 | {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100}, | ||
139 | {US5182D_REG_MODE_STORE, US5182D_STORE_MODE}, | ||
140 | {US5182D_REG_CFG4, 0x00}, | ||
141 | }; | ||
142 | |||
143 | static const struct iio_chan_spec us5182d_channels[] = { | ||
144 | { | ||
145 | .type = IIO_LIGHT, | ||
146 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | ||
147 | BIT(IIO_CHAN_INFO_SCALE), | ||
148 | }, | ||
149 | { | ||
150 | .type = IIO_PROXIMITY, | ||
151 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
152 | } | ||
153 | }; | ||
154 | |||
155 | static int us5182d_get_als(struct us5182d_data *data) | ||
156 | { | ||
157 | int ret; | ||
158 | unsigned long result; | ||
159 | |||
160 | ret = i2c_smbus_read_word_data(data->client, | ||
161 | US5182D_REG_ADL); | ||
162 | if (ret < 0) | ||
163 | return ret; | ||
164 | |||
165 | result = ret * data->ga / US5182D_GA_RESOLUTION; | ||
166 | if (result > 0xffff) | ||
167 | result = 0xffff; | ||
168 | |||
169 | return result; | ||
170 | } | ||
171 | |||
172 | static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) | ||
173 | { | ||
174 | int ret; | ||
175 | |||
176 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | ||
177 | if (ret < 0) | ||
178 | return ret; | ||
179 | |||
180 | /* | ||
181 | * In oneshot mode the chip will power itself down after taking the | ||
182 | * required measurement. | ||
183 | */ | ||
184 | ret = ret | US5182D_CFG0_ONESHOT_EN; | ||
185 | |||
186 | /* update mode */ | ||
187 | ret = ret & ~US5182D_OPMODE_MASK; | ||
188 | ret = ret | (mode << US5182D_OPMODE_SHIFT); | ||
189 | |||
190 | /* | ||
191 | * After updating the operating mode, the chip requires that | ||
192 | * the operation is stored, by writing 1 in the STORE_MODE | ||
193 | * register (auto-clearing). | ||
194 | */ | ||
195 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret); | ||
196 | if (ret < 0) | ||
197 | return ret; | ||
198 | |||
199 | if (mode == data->opmode) | ||
200 | return 0; | ||
201 | |||
202 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE, | ||
203 | US5182D_STORE_MODE); | ||
204 | if (ret < 0) | ||
205 | return ret; | ||
206 | |||
207 | data->opmode = mode; | ||
208 | msleep(US5182D_OPSTORE_SLEEP_TIME); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static int us5182d_read_raw(struct iio_dev *indio_dev, | ||
214 | struct iio_chan_spec const *chan, int *val, | ||
215 | int *val2, long mask) | ||
216 | { | ||
217 | struct us5182d_data *data = iio_priv(indio_dev); | ||
218 | int ret; | ||
219 | |||
220 | switch (mask) { | ||
221 | case IIO_CHAN_INFO_RAW: | ||
222 | switch (chan->type) { | ||
223 | case IIO_LIGHT: | ||
224 | mutex_lock(&data->lock); | ||
225 | ret = us5182d_set_opmode(data, US5182D_OPMODE_ALS); | ||
226 | if (ret < 0) | ||
227 | goto out_err; | ||
228 | |||
229 | ret = us5182d_get_als(data); | ||
230 | if (ret < 0) | ||
231 | goto out_err; | ||
232 | mutex_unlock(&data->lock); | ||
233 | *val = ret; | ||
234 | return IIO_VAL_INT; | ||
235 | case IIO_PROXIMITY: | ||
236 | mutex_lock(&data->lock); | ||
237 | ret = us5182d_set_opmode(data, US5182D_OPMODE_PX); | ||
238 | if (ret < 0) | ||
239 | goto out_err; | ||
240 | |||
241 | ret = i2c_smbus_read_word_data(data->client, | ||
242 | US5182D_REG_PDL); | ||
243 | if (ret < 0) | ||
244 | goto out_err; | ||
245 | mutex_unlock(&data->lock); | ||
246 | *val = ret; | ||
247 | return IIO_VAL_INT; | ||
248 | default: | ||
249 | return -EINVAL; | ||
250 | } | ||
251 | |||
252 | case IIO_CHAN_INFO_SCALE: | ||
253 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); | ||
254 | if (ret < 0) | ||
255 | return ret; | ||
256 | |||
257 | *val = 0; | ||
258 | *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK]; | ||
259 | |||
260 | return IIO_VAL_INT_PLUS_MICRO; | ||
261 | default: | ||
262 | return -EINVAL; | ||
263 | } | ||
264 | |||
265 | return -EINVAL; | ||
266 | out_err: | ||
267 | mutex_unlock(&data->lock); | ||
268 | return ret; | ||
269 | } | ||
270 | |||
271 | /** | ||
272 | * us5182d_update_dark_th - update Darh_Th registers | ||
273 | * @data us5182d_data structure | ||
274 | * @index index in us5182d_dark_ths array to use for the updated value | ||
275 | * | ||
276 | * Function needs to be called with a lock held because it needs two i2c write | ||
277 | * byte operations as these registers (0x27 0x28) don't work in word mode | ||
278 | * accessing. | ||
279 | */ | ||
280 | static int us5182d_update_dark_th(struct us5182d_data *data, int index) | ||
281 | { | ||
282 | __be16 dark_th = cpu_to_be16(data->us5182d_dark_ths[index]); | ||
283 | int ret; | ||
284 | |||
285 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH, | ||
286 | ((u8 *)&dark_th)[0]); | ||
287 | if (ret < 0) | ||
288 | return ret; | ||
289 | |||
290 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH + 1, | ||
291 | ((u8 *)&dark_th)[1]); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * us5182d_apply_scale - update the ALS scale | ||
296 | * @data us5182d_data structure | ||
297 | * @index index in us5182d_scales array to use for the updated value | ||
298 | * | ||
299 | * Function needs to be called with a lock held as we're having more than one | ||
300 | * i2c operation. | ||
301 | */ | ||
302 | static int us5182d_apply_scale(struct us5182d_data *data, int index) | ||
303 | { | ||
304 | int ret; | ||
305 | |||
306 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); | ||
307 | if (ret < 0) | ||
308 | return ret; | ||
309 | |||
310 | ret = ret & (~US5182D_AGAIN_MASK); | ||
311 | ret |= index; | ||
312 | |||
313 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG1, ret); | ||
314 | if (ret < 0) | ||
315 | return ret; | ||
316 | |||
317 | return us5182d_update_dark_th(data, index); | ||
318 | } | ||
319 | |||
320 | static int us5182d_write_raw(struct iio_dev *indio_dev, | ||
321 | struct iio_chan_spec const *chan, int val, | ||
322 | int val2, long mask) | ||
323 | { | ||
324 | struct us5182d_data *data = iio_priv(indio_dev); | ||
325 | int ret, i; | ||
326 | |||
327 | switch (mask) { | ||
328 | case IIO_CHAN_INFO_SCALE: | ||
329 | if (val != 0) | ||
330 | return -EINVAL; | ||
331 | for (i = 0; i < ARRAY_SIZE(us5182d_scales); i++) | ||
332 | if (val2 == us5182d_scales[i]) { | ||
333 | mutex_lock(&data->lock); | ||
334 | ret = us5182d_apply_scale(data, i); | ||
335 | mutex_unlock(&data->lock); | ||
336 | return ret; | ||
337 | } | ||
338 | break; | ||
339 | default: | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | |||
343 | return -EINVAL; | ||
344 | } | ||
345 | |||
346 | static const struct iio_info us5182d_info = { | ||
347 | .driver_module = THIS_MODULE, | ||
348 | .read_raw = us5182d_read_raw, | ||
349 | .write_raw = us5182d_write_raw, | ||
350 | .attrs = &us5182d_attr_group, | ||
351 | }; | ||
352 | |||
353 | static int us5182d_reset(struct iio_dev *indio_dev) | ||
354 | { | ||
355 | struct us5182d_data *data = iio_priv(indio_dev); | ||
356 | |||
357 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG3, | ||
358 | US5182D_RESET_CHIP); | ||
359 | } | ||
360 | |||
361 | static int us5182d_init(struct iio_dev *indio_dev) | ||
362 | { | ||
363 | struct us5182d_data *data = iio_priv(indio_dev); | ||
364 | int i, ret; | ||
365 | |||
366 | ret = us5182d_reset(indio_dev); | ||
367 | if (ret < 0) | ||
368 | return ret; | ||
369 | |||
370 | data->opmode = 0; | ||
371 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { | ||
372 | ret = i2c_smbus_write_byte_data(data->client, | ||
373 | us5182d_regvals[i].reg, | ||
374 | us5182d_regvals[i].val); | ||
375 | if (ret < 0) | ||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static void us5182d_get_platform_data(struct iio_dev *indio_dev) | ||
383 | { | ||
384 | struct us5182d_data *data = iio_priv(indio_dev); | ||
385 | |||
386 | if (device_property_read_u32(&data->client->dev, "upisemi,glass-coef", | ||
387 | &data->ga)) | ||
388 | data->ga = US5182D_GA_RESOLUTION; | ||
389 | if (device_property_read_u16_array(&data->client->dev, | ||
390 | "upisemi,dark-ths", | ||
391 | data->us5182d_dark_ths, | ||
392 | ARRAY_SIZE(us5182d_dark_ths_vals))) | ||
393 | data->us5182d_dark_ths = us5182d_dark_ths_vals; | ||
394 | if (device_property_read_u8(&data->client->dev, | ||
395 | "upisemi,upper-dark-gain", | ||
396 | &data->upper_dark_gain)) | ||
397 | data->upper_dark_gain = US5182D_REG_AUTO_HDARK_GAIN_DEFAULT; | ||
398 | if (device_property_read_u8(&data->client->dev, | ||
399 | "upisemi,lower-dark-gain", | ||
400 | &data->lower_dark_gain)) | ||
401 | data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT; | ||
402 | } | ||
403 | |||
404 | static int us5182d_dark_gain_config(struct iio_dev *indio_dev) | ||
405 | { | ||
406 | struct us5182d_data *data = iio_priv(indio_dev); | ||
407 | int ret; | ||
408 | |||
409 | ret = us5182d_update_dark_th(data, US5182D_CFG1_AGAIN_DEFAULT); | ||
410 | if (ret < 0) | ||
411 | return ret; | ||
412 | |||
413 | ret = i2c_smbus_write_byte_data(data->client, | ||
414 | US5182D_REG_AUTO_LDARK_GAIN, | ||
415 | data->lower_dark_gain); | ||
416 | if (ret < 0) | ||
417 | return ret; | ||
418 | |||
419 | ret = i2c_smbus_write_byte_data(data->client, | ||
420 | US5182D_REG_AUTO_HDARK_GAIN, | ||
421 | data->upper_dark_gain); | ||
422 | if (ret < 0) | ||
423 | return ret; | ||
424 | |||
425 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_DARK_AUTO_EN, | ||
426 | US5182D_REG_DARK_AUTO_EN_DEFAULT); | ||
427 | } | ||
428 | |||
429 | static int us5182d_probe(struct i2c_client *client, | ||
430 | const struct i2c_device_id *id) | ||
431 | { | ||
432 | struct us5182d_data *data; | ||
433 | struct iio_dev *indio_dev; | ||
434 | int ret; | ||
435 | |||
436 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
437 | if (!indio_dev) | ||
438 | return -ENOMEM; | ||
439 | |||
440 | data = iio_priv(indio_dev); | ||
441 | i2c_set_clientdata(client, indio_dev); | ||
442 | data->client = client; | ||
443 | |||
444 | mutex_init(&data->lock); | ||
445 | |||
446 | indio_dev->dev.parent = &client->dev; | ||
447 | indio_dev->info = &us5182d_info; | ||
448 | indio_dev->name = US5182D_DRV_NAME; | ||
449 | indio_dev->channels = us5182d_channels; | ||
450 | indio_dev->num_channels = ARRAY_SIZE(us5182d_channels); | ||
451 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
452 | |||
453 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CHIPID); | ||
454 | if (ret != US5182D_CHIPID) { | ||
455 | dev_err(&data->client->dev, | ||
456 | "Failed to detect US5182 light chip\n"); | ||
457 | return (ret < 0) ? ret : -ENODEV; | ||
458 | } | ||
459 | |||
460 | us5182d_get_platform_data(indio_dev); | ||
461 | ret = us5182d_init(indio_dev); | ||
462 | if (ret < 0) | ||
463 | return ret; | ||
464 | |||
465 | ret = us5182d_dark_gain_config(indio_dev); | ||
466 | if (ret < 0) | ||
467 | return ret; | ||
468 | |||
469 | return iio_device_register(indio_dev); | ||
470 | } | ||
471 | |||
472 | static int us5182d_remove(struct i2c_client *client) | ||
473 | { | ||
474 | iio_device_unregister(i2c_get_clientdata(client)); | ||
475 | return i2c_smbus_write_byte_data(client, US5182D_REG_CFG0, | ||
476 | US5182D_CFG0_SHUTDOWN_EN); | ||
477 | } | ||
478 | |||
479 | static const struct acpi_device_id us5182d_acpi_match[] = { | ||
480 | { "USD5182", 0}, | ||
481 | {} | ||
482 | }; | ||
483 | |||
484 | MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match); | ||
485 | |||
486 | static const struct i2c_device_id us5182d_id[] = { | ||
487 | {"usd5182", 0}, | ||
488 | {} | ||
489 | }; | ||
490 | |||
491 | MODULE_DEVICE_TABLE(i2c, us5182d_id); | ||
492 | |||
493 | static struct i2c_driver us5182d_driver = { | ||
494 | .driver = { | ||
495 | .name = US5182D_DRV_NAME, | ||
496 | .acpi_match_table = ACPI_PTR(us5182d_acpi_match), | ||
497 | }, | ||
498 | .probe = us5182d_probe, | ||
499 | .remove = us5182d_remove, | ||
500 | .id_table = us5182d_id, | ||
501 | |||
502 | }; | ||
503 | module_i2c_driver(us5182d_driver); | ||
504 | |||
505 | MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>"); | ||
506 | MODULE_DESCRIPTION("Driver for us5182d Proximity and Light Sensor"); | ||
507 | MODULE_LICENSE("GPL v2"); | ||