Commit | Line | Data |
---|---|---|
c14f8abe AR |
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 | ||
c3304c21 AR |
102 | enum pmode { |
103 | US5182D_CONTINUOUS, | |
104 | US5182D_ONESHOT | |
105 | }; | |
106 | ||
c14f8abe AR |
107 | struct us5182d_data { |
108 | struct i2c_client *client; | |
109 | struct mutex lock; | |
110 | ||
111 | /* Glass attenuation factor */ | |
112 | u32 ga; | |
113 | ||
114 | /* Dark gain tuning */ | |
115 | u8 lower_dark_gain; | |
116 | u8 upper_dark_gain; | |
117 | u16 *us5182d_dark_ths; | |
118 | ||
119 | u8 opmode; | |
c3304c21 AR |
120 | u8 power_mode; |
121 | ||
122 | bool default_continuous; | |
c14f8abe AR |
123 | }; |
124 | ||
125 | static IIO_CONST_ATTR(in_illuminance_scale_available, | |
126 | "0.0021 0.0039 0.0076 0.0196 0.0336 0.061 0.1078 0.1885"); | |
127 | ||
128 | static struct attribute *us5182d_attrs[] = { | |
129 | &iio_const_attr_in_illuminance_scale_available.dev_attr.attr, | |
130 | NULL | |
131 | }; | |
132 | ||
133 | static const struct attribute_group us5182d_attr_group = { | |
134 | .attrs = us5182d_attrs, | |
135 | }; | |
136 | ||
137 | static const struct { | |
138 | u8 reg; | |
139 | u8 val; | |
140 | } us5182d_regvals[] = { | |
c3304c21 | 141 | {US5182D_REG_CFG0, US5182D_CFG0_WORD_ENABLE}, |
c14f8abe AR |
142 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, |
143 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | | |
144 | US5182D_CFG2_PXGAIN_DEFAULT)}, | |
145 | {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100}, | |
c14f8abe AR |
146 | {US5182D_REG_CFG4, 0x00}, |
147 | }; | |
148 | ||
149 | static const struct iio_chan_spec us5182d_channels[] = { | |
150 | { | |
151 | .type = IIO_LIGHT, | |
152 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | |
153 | BIT(IIO_CHAN_INFO_SCALE), | |
154 | }, | |
155 | { | |
156 | .type = IIO_PROXIMITY, | |
157 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | |
158 | } | |
159 | }; | |
160 | ||
161 | static int us5182d_get_als(struct us5182d_data *data) | |
162 | { | |
163 | int ret; | |
164 | unsigned long result; | |
165 | ||
166 | ret = i2c_smbus_read_word_data(data->client, | |
167 | US5182D_REG_ADL); | |
168 | if (ret < 0) | |
169 | return ret; | |
170 | ||
171 | result = ret * data->ga / US5182D_GA_RESOLUTION; | |
172 | if (result > 0xffff) | |
173 | result = 0xffff; | |
174 | ||
175 | return result; | |
176 | } | |
177 | ||
c3304c21 | 178 | static int us5182d_oneshot_en(struct us5182d_data *data) |
c14f8abe AR |
179 | { |
180 | int ret; | |
181 | ||
182 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | |
183 | if (ret < 0) | |
184 | return ret; | |
185 | ||
186 | /* | |
187 | * In oneshot mode the chip will power itself down after taking the | |
188 | * required measurement. | |
189 | */ | |
190 | ret = ret | US5182D_CFG0_ONESHOT_EN; | |
191 | ||
c3304c21 AR |
192 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret); |
193 | } | |
194 | ||
195 | static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) | |
196 | { | |
197 | int ret; | |
198 | ||
199 | if (mode == data->opmode) | |
200 | return 0; | |
201 | ||
202 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | |
203 | if (ret < 0) | |
204 | return ret; | |
205 | ||
c14f8abe AR |
206 | /* update mode */ |
207 | ret = ret & ~US5182D_OPMODE_MASK; | |
208 | ret = ret | (mode << US5182D_OPMODE_SHIFT); | |
209 | ||
210 | /* | |
211 | * After updating the operating mode, the chip requires that | |
212 | * the operation is stored, by writing 1 in the STORE_MODE | |
213 | * register (auto-clearing). | |
214 | */ | |
215 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret); | |
216 | if (ret < 0) | |
217 | return ret; | |
218 | ||
c14f8abe AR |
219 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE, |
220 | US5182D_STORE_MODE); | |
221 | if (ret < 0) | |
222 | return ret; | |
223 | ||
224 | data->opmode = mode; | |
225 | msleep(US5182D_OPSTORE_SLEEP_TIME); | |
226 | ||
227 | return 0; | |
228 | } | |
229 | ||
c3304c21 AR |
230 | static int us5182d_shutdown_en(struct us5182d_data *data, u8 state) |
231 | { | |
232 | int ret; | |
233 | ||
234 | if (data->power_mode == US5182D_ONESHOT) | |
235 | return 0; | |
236 | ||
237 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG0); | |
238 | if (ret < 0) | |
239 | return ret; | |
240 | ||
241 | ret = ret & ~US5182D_CFG0_SHUTDOWN_EN; | |
242 | ret = ret | state; | |
243 | ||
244 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG0, ret); | |
245 | } | |
246 | ||
c14f8abe AR |
247 | static int us5182d_read_raw(struct iio_dev *indio_dev, |
248 | struct iio_chan_spec const *chan, int *val, | |
249 | int *val2, long mask) | |
250 | { | |
251 | struct us5182d_data *data = iio_priv(indio_dev); | |
252 | int ret; | |
253 | ||
254 | switch (mask) { | |
255 | case IIO_CHAN_INFO_RAW: | |
256 | switch (chan->type) { | |
257 | case IIO_LIGHT: | |
258 | mutex_lock(&data->lock); | |
c3304c21 AR |
259 | if (data->power_mode == US5182D_ONESHOT) { |
260 | ret = us5182d_oneshot_en(data); | |
261 | if (ret < 0) | |
262 | goto out_err; | |
263 | } | |
c14f8abe AR |
264 | ret = us5182d_set_opmode(data, US5182D_OPMODE_ALS); |
265 | if (ret < 0) | |
266 | goto out_err; | |
267 | ||
268 | ret = us5182d_get_als(data); | |
269 | if (ret < 0) | |
270 | goto out_err; | |
271 | mutex_unlock(&data->lock); | |
272 | *val = ret; | |
273 | return IIO_VAL_INT; | |
274 | case IIO_PROXIMITY: | |
275 | mutex_lock(&data->lock); | |
c3304c21 AR |
276 | if (data->power_mode == US5182D_ONESHOT) { |
277 | ret = us5182d_oneshot_en(data); | |
278 | if (ret < 0) | |
279 | goto out_err; | |
280 | } | |
c14f8abe AR |
281 | ret = us5182d_set_opmode(data, US5182D_OPMODE_PX); |
282 | if (ret < 0) | |
283 | goto out_err; | |
284 | ||
285 | ret = i2c_smbus_read_word_data(data->client, | |
286 | US5182D_REG_PDL); | |
287 | if (ret < 0) | |
288 | goto out_err; | |
289 | mutex_unlock(&data->lock); | |
290 | *val = ret; | |
291 | return IIO_VAL_INT; | |
292 | default: | |
293 | return -EINVAL; | |
294 | } | |
295 | ||
296 | case IIO_CHAN_INFO_SCALE: | |
297 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); | |
298 | if (ret < 0) | |
299 | return ret; | |
300 | ||
301 | *val = 0; | |
302 | *val2 = us5182d_scales[ret & US5182D_AGAIN_MASK]; | |
303 | ||
304 | return IIO_VAL_INT_PLUS_MICRO; | |
305 | default: | |
306 | return -EINVAL; | |
307 | } | |
308 | ||
309 | return -EINVAL; | |
310 | out_err: | |
311 | mutex_unlock(&data->lock); | |
312 | return ret; | |
313 | } | |
314 | ||
315 | /** | |
316 | * us5182d_update_dark_th - update Darh_Th registers | |
317 | * @data us5182d_data structure | |
318 | * @index index in us5182d_dark_ths array to use for the updated value | |
319 | * | |
320 | * Function needs to be called with a lock held because it needs two i2c write | |
321 | * byte operations as these registers (0x27 0x28) don't work in word mode | |
322 | * accessing. | |
323 | */ | |
324 | static int us5182d_update_dark_th(struct us5182d_data *data, int index) | |
325 | { | |
326 | __be16 dark_th = cpu_to_be16(data->us5182d_dark_ths[index]); | |
327 | int ret; | |
328 | ||
329 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH, | |
330 | ((u8 *)&dark_th)[0]); | |
331 | if (ret < 0) | |
332 | return ret; | |
333 | ||
334 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_UDARK_TH + 1, | |
335 | ((u8 *)&dark_th)[1]); | |
336 | } | |
337 | ||
338 | /** | |
339 | * us5182d_apply_scale - update the ALS scale | |
340 | * @data us5182d_data structure | |
341 | * @index index in us5182d_scales array to use for the updated value | |
342 | * | |
343 | * Function needs to be called with a lock held as we're having more than one | |
344 | * i2c operation. | |
345 | */ | |
346 | static int us5182d_apply_scale(struct us5182d_data *data, int index) | |
347 | { | |
348 | int ret; | |
349 | ||
350 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CFG1); | |
351 | if (ret < 0) | |
352 | return ret; | |
353 | ||
354 | ret = ret & (~US5182D_AGAIN_MASK); | |
355 | ret |= index; | |
356 | ||
357 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG1, ret); | |
358 | if (ret < 0) | |
359 | return ret; | |
360 | ||
361 | return us5182d_update_dark_th(data, index); | |
362 | } | |
363 | ||
364 | static int us5182d_write_raw(struct iio_dev *indio_dev, | |
365 | struct iio_chan_spec const *chan, int val, | |
366 | int val2, long mask) | |
367 | { | |
368 | struct us5182d_data *data = iio_priv(indio_dev); | |
369 | int ret, i; | |
370 | ||
371 | switch (mask) { | |
372 | case IIO_CHAN_INFO_SCALE: | |
373 | if (val != 0) | |
374 | return -EINVAL; | |
375 | for (i = 0; i < ARRAY_SIZE(us5182d_scales); i++) | |
376 | if (val2 == us5182d_scales[i]) { | |
377 | mutex_lock(&data->lock); | |
378 | ret = us5182d_apply_scale(data, i); | |
379 | mutex_unlock(&data->lock); | |
380 | return ret; | |
381 | } | |
382 | break; | |
383 | default: | |
384 | return -EINVAL; | |
385 | } | |
386 | ||
387 | return -EINVAL; | |
388 | } | |
389 | ||
390 | static const struct iio_info us5182d_info = { | |
391 | .driver_module = THIS_MODULE, | |
392 | .read_raw = us5182d_read_raw, | |
393 | .write_raw = us5182d_write_raw, | |
394 | .attrs = &us5182d_attr_group, | |
395 | }; | |
396 | ||
397 | static int us5182d_reset(struct iio_dev *indio_dev) | |
398 | { | |
399 | struct us5182d_data *data = iio_priv(indio_dev); | |
400 | ||
401 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_CFG3, | |
402 | US5182D_RESET_CHIP); | |
403 | } | |
404 | ||
405 | static int us5182d_init(struct iio_dev *indio_dev) | |
406 | { | |
407 | struct us5182d_data *data = iio_priv(indio_dev); | |
408 | int i, ret; | |
409 | ||
410 | ret = us5182d_reset(indio_dev); | |
411 | if (ret < 0) | |
412 | return ret; | |
413 | ||
414 | data->opmode = 0; | |
c3304c21 | 415 | data->power_mode = US5182D_CONTINUOUS; |
c14f8abe AR |
416 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { |
417 | ret = i2c_smbus_write_byte_data(data->client, | |
418 | us5182d_regvals[i].reg, | |
419 | us5182d_regvals[i].val); | |
420 | if (ret < 0) | |
421 | return ret; | |
422 | } | |
423 | ||
c3304c21 AR |
424 | if (!data->default_continuous) { |
425 | ret = us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN); | |
426 | if (ret < 0) | |
427 | return ret; | |
428 | data->power_mode = US5182D_ONESHOT; | |
429 | } | |
430 | ||
431 | ||
432 | return ret; | |
c14f8abe AR |
433 | } |
434 | ||
435 | static void us5182d_get_platform_data(struct iio_dev *indio_dev) | |
436 | { | |
437 | struct us5182d_data *data = iio_priv(indio_dev); | |
438 | ||
439 | if (device_property_read_u32(&data->client->dev, "upisemi,glass-coef", | |
440 | &data->ga)) | |
441 | data->ga = US5182D_GA_RESOLUTION; | |
442 | if (device_property_read_u16_array(&data->client->dev, | |
443 | "upisemi,dark-ths", | |
444 | data->us5182d_dark_ths, | |
445 | ARRAY_SIZE(us5182d_dark_ths_vals))) | |
446 | data->us5182d_dark_ths = us5182d_dark_ths_vals; | |
447 | if (device_property_read_u8(&data->client->dev, | |
448 | "upisemi,upper-dark-gain", | |
449 | &data->upper_dark_gain)) | |
450 | data->upper_dark_gain = US5182D_REG_AUTO_HDARK_GAIN_DEFAULT; | |
451 | if (device_property_read_u8(&data->client->dev, | |
452 | "upisemi,lower-dark-gain", | |
453 | &data->lower_dark_gain)) | |
454 | data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT; | |
c3304c21 AR |
455 | data->default_continuous = device_property_read_bool(&data->client->dev, |
456 | "upisemi,continuous"); | |
c14f8abe AR |
457 | } |
458 | ||
459 | static int us5182d_dark_gain_config(struct iio_dev *indio_dev) | |
460 | { | |
461 | struct us5182d_data *data = iio_priv(indio_dev); | |
462 | int ret; | |
463 | ||
464 | ret = us5182d_update_dark_th(data, US5182D_CFG1_AGAIN_DEFAULT); | |
465 | if (ret < 0) | |
466 | return ret; | |
467 | ||
468 | ret = i2c_smbus_write_byte_data(data->client, | |
469 | US5182D_REG_AUTO_LDARK_GAIN, | |
470 | data->lower_dark_gain); | |
471 | if (ret < 0) | |
472 | return ret; | |
473 | ||
474 | ret = i2c_smbus_write_byte_data(data->client, | |
475 | US5182D_REG_AUTO_HDARK_GAIN, | |
476 | data->upper_dark_gain); | |
477 | if (ret < 0) | |
478 | return ret; | |
479 | ||
480 | return i2c_smbus_write_byte_data(data->client, US5182D_REG_DARK_AUTO_EN, | |
481 | US5182D_REG_DARK_AUTO_EN_DEFAULT); | |
482 | } | |
483 | ||
484 | static int us5182d_probe(struct i2c_client *client, | |
485 | const struct i2c_device_id *id) | |
486 | { | |
487 | struct us5182d_data *data; | |
488 | struct iio_dev *indio_dev; | |
489 | int ret; | |
490 | ||
491 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | |
492 | if (!indio_dev) | |
493 | return -ENOMEM; | |
494 | ||
495 | data = iio_priv(indio_dev); | |
496 | i2c_set_clientdata(client, indio_dev); | |
497 | data->client = client; | |
498 | ||
499 | mutex_init(&data->lock); | |
500 | ||
501 | indio_dev->dev.parent = &client->dev; | |
502 | indio_dev->info = &us5182d_info; | |
503 | indio_dev->name = US5182D_DRV_NAME; | |
504 | indio_dev->channels = us5182d_channels; | |
505 | indio_dev->num_channels = ARRAY_SIZE(us5182d_channels); | |
506 | indio_dev->modes = INDIO_DIRECT_MODE; | |
507 | ||
508 | ret = i2c_smbus_read_byte_data(data->client, US5182D_REG_CHIPID); | |
509 | if (ret != US5182D_CHIPID) { | |
510 | dev_err(&data->client->dev, | |
511 | "Failed to detect US5182 light chip\n"); | |
512 | return (ret < 0) ? ret : -ENODEV; | |
513 | } | |
514 | ||
515 | us5182d_get_platform_data(indio_dev); | |
516 | ret = us5182d_init(indio_dev); | |
517 | if (ret < 0) | |
518 | return ret; | |
519 | ||
520 | ret = us5182d_dark_gain_config(indio_dev); | |
521 | if (ret < 0) | |
c3304c21 AR |
522 | goto out_err; |
523 | ||
524 | ret = iio_device_register(indio_dev); | |
525 | if (ret < 0) | |
526 | goto out_err; | |
527 | ||
528 | return 0; | |
529 | ||
530 | out_err: | |
531 | us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN); | |
532 | return ret; | |
c14f8abe | 533 | |
c14f8abe AR |
534 | } |
535 | ||
536 | static int us5182d_remove(struct i2c_client *client) | |
537 | { | |
c3304c21 AR |
538 | struct us5182d_data *data = iio_priv(i2c_get_clientdata(client)); |
539 | ||
c14f8abe | 540 | iio_device_unregister(i2c_get_clientdata(client)); |
c3304c21 AR |
541 | |
542 | return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN); | |
c14f8abe AR |
543 | } |
544 | ||
545 | static const struct acpi_device_id us5182d_acpi_match[] = { | |
546 | { "USD5182", 0}, | |
547 | {} | |
548 | }; | |
549 | ||
550 | MODULE_DEVICE_TABLE(acpi, us5182d_acpi_match); | |
551 | ||
552 | static const struct i2c_device_id us5182d_id[] = { | |
553 | {"usd5182", 0}, | |
554 | {} | |
555 | }; | |
556 | ||
557 | MODULE_DEVICE_TABLE(i2c, us5182d_id); | |
558 | ||
559 | static struct i2c_driver us5182d_driver = { | |
560 | .driver = { | |
561 | .name = US5182D_DRV_NAME, | |
562 | .acpi_match_table = ACPI_PTR(us5182d_acpi_match), | |
563 | }, | |
564 | .probe = us5182d_probe, | |
565 | .remove = us5182d_remove, | |
566 | .id_table = us5182d_id, | |
567 | ||
568 | }; | |
569 | module_i2c_driver(us5182d_driver); | |
570 | ||
571 | MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>"); | |
572 | MODULE_DESCRIPTION("Driver for us5182d Proximity and Light Sensor"); | |
573 | MODULE_LICENSE("GPL v2"); |