diff options
author | Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com> | 2014-09-15 23:54:00 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2014-11-08 07:24:50 -0500 |
commit | 995863cc8e3e2ab08a8ff18dc937c7a32a7479e0 (patch) | |
tree | 09e90251206871f360f11e0904c9948070329c76 | |
parent | 5e62863aea463c9bf24538315327d0922be35d64 (diff) |
iio: jsa1212: Add JSA1212 proximity/ALS sensor
This patch adds a new driver for solteam opto JSA1212 proximity and
ambient light sensor.
Basic details of the chip can be found here.
http://www.solteamopto.com.tw/detail.php?ms=3&po_unit=2&pt_unit=29&p_unit=120
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.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/jsa1212.c | 471 |
3 files changed, 482 insertions, 0 deletions
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 5bea821adcae..2e2ba12f55fc 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig | |||
@@ -109,6 +109,16 @@ config HID_SENSOR_PROX | |||
109 | To compile this driver as a module, choose M here: the | 109 | To compile this driver as a module, choose M here: the |
110 | module will be called hid-sensor-prox. | 110 | module will be called hid-sensor-prox. |
111 | 111 | ||
112 | config JSA1212 | ||
113 | tristate "JSA1212 ALS and proximity sensor driver" | ||
114 | depends on I2C | ||
115 | help | ||
116 | Say Y here if you want to build a IIO driver for JSA1212 | ||
117 | proximity & ALS sensor device. | ||
118 | |||
119 | To compile this driver as a module, choose M here: | ||
120 | the module will be called jsa1212. | ||
121 | |||
112 | config SENSORS_LM3533 | 122 | config SENSORS_LM3533 |
113 | tristate "LM3533 ambient light sensor" | 123 | tristate "LM3533 ambient light sensor" |
114 | depends on MFD_LM3533 | 124 | depends on MFD_LM3533 |
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile index 47877a36cc12..74656c19a899 100644 --- a/drivers/iio/light/Makefile +++ b/drivers/iio/light/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o | |||
12 | obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o | 12 | obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o |
13 | obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o | 13 | obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o |
14 | obj-$(CONFIG_ISL29125) += isl29125.o | 14 | obj-$(CONFIG_ISL29125) += isl29125.o |
15 | obj-$(CONFIG_JSA1212) += jsa1212.o | ||
15 | obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o | 16 | obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o |
16 | obj-$(CONFIG_LTR501) += ltr501.o | 17 | obj-$(CONFIG_LTR501) += ltr501.o |
17 | obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o | 18 | obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o |
diff --git a/drivers/iio/light/jsa1212.c b/drivers/iio/light/jsa1212.c new file mode 100644 index 000000000000..29de7e7d9562 --- /dev/null +++ b/drivers/iio/light/jsa1212.c | |||
@@ -0,0 +1,471 @@ | |||
1 | /* | ||
2 | * JSA1212 Ambient Light & Proximity Sensor Driver | ||
3 | * | ||
4 | * Copyright (c) 2014, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by 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 | * JSA1212 I2C slave address: 0x44(ADDR tied to GND), 0x45(ADDR tied to VDD) | ||
16 | * | ||
17 | * TODO: Interrupt support, thresholds, range support. | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/acpi.h> | ||
27 | #include <linux/regmap.h> | ||
28 | #include <linux/iio/iio.h> | ||
29 | #include <linux/iio/sysfs.h> | ||
30 | |||
31 | /* JSA1212 reg address */ | ||
32 | #define JSA1212_CONF_REG 0x01 | ||
33 | #define JSA1212_INT_REG 0x02 | ||
34 | #define JSA1212_PXS_LT_REG 0x03 | ||
35 | #define JSA1212_PXS_HT_REG 0x04 | ||
36 | #define JSA1212_ALS_TH1_REG 0x05 | ||
37 | #define JSA1212_ALS_TH2_REG 0x06 | ||
38 | #define JSA1212_ALS_TH3_REG 0x07 | ||
39 | #define JSA1212_PXS_DATA_REG 0x08 | ||
40 | #define JSA1212_ALS_DT1_REG 0x09 | ||
41 | #define JSA1212_ALS_DT2_REG 0x0A | ||
42 | #define JSA1212_ALS_RNG_REG 0x0B | ||
43 | #define JSA1212_MAX_REG 0x0C | ||
44 | |||
45 | /* JSA1212 reg masks */ | ||
46 | #define JSA1212_CONF_MASK 0xFF | ||
47 | #define JSA1212_INT_MASK 0xFF | ||
48 | #define JSA1212_PXS_LT_MASK 0xFF | ||
49 | #define JSA1212_PXS_HT_MASK 0xFF | ||
50 | #define JSA1212_ALS_TH1_MASK 0xFF | ||
51 | #define JSA1212_ALS_TH2_LT_MASK 0x0F | ||
52 | #define JSA1212_ALS_TH2_HT_MASK 0xF0 | ||
53 | #define JSA1212_ALS_TH3_MASK 0xFF | ||
54 | #define JSA1212_PXS_DATA_MASK 0xFF | ||
55 | #define JSA1212_ALS_DATA_MASK 0x0FFF | ||
56 | #define JSA1212_ALS_DT1_MASK 0xFF | ||
57 | #define JSA1212_ALS_DT2_MASK 0x0F | ||
58 | #define JSA1212_ALS_RNG_MASK 0x07 | ||
59 | |||
60 | /* JSA1212 CONF REG bits */ | ||
61 | #define JSA1212_CONF_PXS_MASK 0x80 | ||
62 | #define JSA1212_CONF_PXS_ENABLE 0x80 | ||
63 | #define JSA1212_CONF_PXS_DISABLE 0x00 | ||
64 | #define JSA1212_CONF_ALS_MASK 0x04 | ||
65 | #define JSA1212_CONF_ALS_ENABLE 0x04 | ||
66 | #define JSA1212_CONF_ALS_DISABLE 0x00 | ||
67 | #define JSA1212_CONF_IRDR_MASK 0x08 | ||
68 | /* Proxmity sensing IRDR current sink settings */ | ||
69 | #define JSA1212_CONF_IRDR_200MA 0x08 | ||
70 | #define JSA1212_CONF_IRDR_100MA 0x00 | ||
71 | #define JSA1212_CONF_PXS_SLP_MASK 0x70 | ||
72 | #define JSA1212_CONF_PXS_SLP_0MS 0x70 | ||
73 | #define JSA1212_CONF_PXS_SLP_12MS 0x60 | ||
74 | #define JSA1212_CONF_PXS_SLP_50MS 0x50 | ||
75 | #define JSA1212_CONF_PXS_SLP_75MS 0x40 | ||
76 | #define JSA1212_CONF_PXS_SLP_100MS 0x30 | ||
77 | #define JSA1212_CONF_PXS_SLP_200MS 0x20 | ||
78 | #define JSA1212_CONF_PXS_SLP_400MS 0x10 | ||
79 | #define JSA1212_CONF_PXS_SLP_800MS 0x00 | ||
80 | |||
81 | /* JSA1212 INT REG bits */ | ||
82 | #define JSA1212_INT_CTRL_MASK 0x01 | ||
83 | #define JSA1212_INT_CTRL_EITHER 0x00 | ||
84 | #define JSA1212_INT_CTRL_BOTH 0x01 | ||
85 | #define JSA1212_INT_ALS_PRST_MASK 0x06 | ||
86 | #define JSA1212_INT_ALS_PRST_1CONV 0x00 | ||
87 | #define JSA1212_INT_ALS_PRST_4CONV 0x02 | ||
88 | #define JSA1212_INT_ALS_PRST_8CONV 0x04 | ||
89 | #define JSA1212_INT_ALS_PRST_16CONV 0x06 | ||
90 | #define JSA1212_INT_ALS_FLAG_MASK 0x08 | ||
91 | #define JSA1212_INT_ALS_FLAG_CLR 0x00 | ||
92 | #define JSA1212_INT_PXS_PRST_MASK 0x60 | ||
93 | #define JSA1212_INT_PXS_PRST_1CONV 0x00 | ||
94 | #define JSA1212_INT_PXS_PRST_4CONV 0x20 | ||
95 | #define JSA1212_INT_PXS_PRST_8CONV 0x40 | ||
96 | #define JSA1212_INT_PXS_PRST_16CONV 0x60 | ||
97 | #define JSA1212_INT_PXS_FLAG_MASK 0x80 | ||
98 | #define JSA1212_INT_PXS_FLAG_CLR 0x00 | ||
99 | |||
100 | /* JSA1212 ALS RNG REG bits */ | ||
101 | #define JSA1212_ALS_RNG_0_2048 0x00 | ||
102 | #define JSA1212_ALS_RNG_0_1024 0x01 | ||
103 | #define JSA1212_ALS_RNG_0_512 0x02 | ||
104 | #define JSA1212_ALS_RNG_0_256 0x03 | ||
105 | #define JSA1212_ALS_RNG_0_128 0x04 | ||
106 | |||
107 | /* JSA1212 INT threshold range */ | ||
108 | #define JSA1212_ALS_TH_MIN 0x0000 | ||
109 | #define JSA1212_ALS_TH_MAX 0x0FFF | ||
110 | #define JSA1212_PXS_TH_MIN 0x00 | ||
111 | #define JSA1212_PXS_TH_MAX 0xFF | ||
112 | |||
113 | #define JSA1212_ALS_DELAY_MS 200 | ||
114 | #define JSA1212_PXS_DELAY_MS 100 | ||
115 | |||
116 | #define JSA1212_DRIVER_NAME "jsa1212" | ||
117 | #define JSA1212_REGMAP_NAME "jsa1212_regmap" | ||
118 | |||
119 | enum jsa1212_op_mode { | ||
120 | JSA1212_OPMODE_ALS_EN, | ||
121 | JSA1212_OPMODE_PXS_EN, | ||
122 | }; | ||
123 | |||
124 | struct jsa1212_data { | ||
125 | struct i2c_client *client; | ||
126 | struct mutex lock; | ||
127 | u8 als_rng_idx; | ||
128 | bool als_en; /* ALS enable status */ | ||
129 | bool pxs_en; /* proximity enable status */ | ||
130 | struct regmap *regmap; | ||
131 | }; | ||
132 | |||
133 | /* ALS range idx to val mapping */ | ||
134 | static const int jsa1212_als_range_val[] = {2048, 1024, 512, 256, 128, | ||
135 | 128, 128, 128}; | ||
136 | |||
137 | /* Enables or disables ALS function based on status */ | ||
138 | static int jsa1212_als_enable(struct jsa1212_data *data, u8 status) | ||
139 | { | ||
140 | int ret; | ||
141 | |||
142 | ret = regmap_update_bits(data->regmap, JSA1212_CONF_REG, | ||
143 | JSA1212_CONF_ALS_MASK, | ||
144 | status); | ||
145 | if (ret < 0) | ||
146 | return ret; | ||
147 | |||
148 | data->als_en = !!status; | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | /* Enables or disables PXS function based on status */ | ||
154 | static int jsa1212_pxs_enable(struct jsa1212_data *data, u8 status) | ||
155 | { | ||
156 | int ret; | ||
157 | |||
158 | ret = regmap_update_bits(data->regmap, JSA1212_CONF_REG, | ||
159 | JSA1212_CONF_PXS_MASK, | ||
160 | status); | ||
161 | if (ret < 0) | ||
162 | return ret; | ||
163 | |||
164 | data->pxs_en = !!status; | ||
165 | |||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int jsa1212_read_als_data(struct jsa1212_data *data, | ||
170 | unsigned int *val) | ||
171 | { | ||
172 | int ret; | ||
173 | __le16 als_data; | ||
174 | |||
175 | ret = jsa1212_als_enable(data, JSA1212_CONF_ALS_ENABLE); | ||
176 | if (ret < 0) | ||
177 | return ret; | ||
178 | |||
179 | /* Delay for data output */ | ||
180 | msleep(JSA1212_ALS_DELAY_MS); | ||
181 | |||
182 | /* Read 12 bit data */ | ||
183 | ret = regmap_bulk_read(data->regmap, JSA1212_ALS_DT1_REG, &als_data, 2); | ||
184 | if (ret < 0) { | ||
185 | dev_err(&data->client->dev, "als data read err\n"); | ||
186 | goto als_data_read_err; | ||
187 | } | ||
188 | |||
189 | *val = le16_to_cpu(als_data); | ||
190 | |||
191 | als_data_read_err: | ||
192 | return jsa1212_als_enable(data, JSA1212_CONF_ALS_DISABLE); | ||
193 | } | ||
194 | |||
195 | static int jsa1212_read_pxs_data(struct jsa1212_data *data, | ||
196 | unsigned int *val) | ||
197 | { | ||
198 | int ret; | ||
199 | unsigned int pxs_data; | ||
200 | |||
201 | ret = jsa1212_pxs_enable(data, JSA1212_CONF_PXS_ENABLE); | ||
202 | if (ret < 0) | ||
203 | return ret; | ||
204 | |||
205 | /* Delay for data output */ | ||
206 | msleep(JSA1212_PXS_DELAY_MS); | ||
207 | |||
208 | /* Read out all data */ | ||
209 | ret = regmap_read(data->regmap, JSA1212_PXS_DATA_REG, &pxs_data); | ||
210 | if (ret < 0) { | ||
211 | dev_err(&data->client->dev, "pxs data read err\n"); | ||
212 | goto pxs_data_read_err; | ||
213 | } | ||
214 | |||
215 | *val = pxs_data & JSA1212_PXS_DATA_MASK; | ||
216 | |||
217 | pxs_data_read_err: | ||
218 | return jsa1212_pxs_enable(data, JSA1212_CONF_PXS_DISABLE); | ||
219 | } | ||
220 | |||
221 | static int jsa1212_read_raw(struct iio_dev *indio_dev, | ||
222 | struct iio_chan_spec const *chan, | ||
223 | int *val, int *val2, long mask) | ||
224 | { | ||
225 | int ret; | ||
226 | struct jsa1212_data *data = iio_priv(indio_dev); | ||
227 | |||
228 | switch (mask) { | ||
229 | case IIO_CHAN_INFO_RAW: | ||
230 | mutex_lock(&data->lock); | ||
231 | switch (chan->type) { | ||
232 | case IIO_LIGHT: | ||
233 | ret = jsa1212_read_als_data(data, val); | ||
234 | break; | ||
235 | case IIO_PROXIMITY: | ||
236 | ret = jsa1212_read_pxs_data(data, val); | ||
237 | break; | ||
238 | default: | ||
239 | ret = -EINVAL; | ||
240 | break; | ||
241 | } | ||
242 | mutex_unlock(&data->lock); | ||
243 | return ret < 0 ? ret : IIO_VAL_INT; | ||
244 | case IIO_CHAN_INFO_SCALE: | ||
245 | switch (chan->type) { | ||
246 | case IIO_LIGHT: | ||
247 | *val = jsa1212_als_range_val[data->als_rng_idx]; | ||
248 | *val2 = BIT(12); /* Max 12 bit value */ | ||
249 | return IIO_VAL_FRACTIONAL; | ||
250 | default: | ||
251 | break; | ||
252 | } | ||
253 | break; | ||
254 | default: | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | return -EINVAL; | ||
259 | } | ||
260 | |||
261 | static const struct iio_chan_spec jsa1212_channels[] = { | ||
262 | { | ||
263 | .type = IIO_LIGHT, | ||
264 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | | ||
265 | BIT(IIO_CHAN_INFO_SCALE), | ||
266 | }, | ||
267 | { | ||
268 | .type = IIO_PROXIMITY, | ||
269 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), | ||
270 | } | ||
271 | }; | ||
272 | |||
273 | static const struct iio_info jsa1212_info = { | ||
274 | .driver_module = THIS_MODULE, | ||
275 | .read_raw = &jsa1212_read_raw, | ||
276 | }; | ||
277 | |||
278 | static int jsa1212_chip_init(struct jsa1212_data *data) | ||
279 | { | ||
280 | int ret; | ||
281 | |||
282 | ret = regmap_write(data->regmap, JSA1212_CONF_REG, | ||
283 | (JSA1212_CONF_PXS_SLP_50MS | | ||
284 | JSA1212_CONF_IRDR_200MA)); | ||
285 | if (ret < 0) | ||
286 | return ret; | ||
287 | |||
288 | ret = regmap_write(data->regmap, JSA1212_INT_REG, | ||
289 | JSA1212_INT_ALS_PRST_4CONV); | ||
290 | if (ret < 0) | ||
291 | return ret; | ||
292 | |||
293 | data->als_rng_idx = JSA1212_ALS_RNG_0_2048; | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static bool jsa1212_is_volatile_reg(struct device *dev, unsigned int reg) | ||
299 | { | ||
300 | switch (reg) { | ||
301 | case JSA1212_PXS_DATA_REG: | ||
302 | case JSA1212_ALS_DT1_REG: | ||
303 | case JSA1212_ALS_DT2_REG: | ||
304 | case JSA1212_INT_REG: | ||
305 | return true; | ||
306 | default: | ||
307 | return false; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | static struct regmap_config jsa1212_regmap_config = { | ||
312 | .name = JSA1212_REGMAP_NAME, | ||
313 | .reg_bits = 8, | ||
314 | .val_bits = 8, | ||
315 | .max_register = JSA1212_MAX_REG, | ||
316 | .cache_type = REGCACHE_RBTREE, | ||
317 | .volatile_reg = jsa1212_is_volatile_reg, | ||
318 | }; | ||
319 | |||
320 | static int jsa1212_probe(struct i2c_client *client, | ||
321 | const struct i2c_device_id *id) | ||
322 | { | ||
323 | struct jsa1212_data *data; | ||
324 | struct iio_dev *indio_dev; | ||
325 | struct regmap *regmap; | ||
326 | int ret; | ||
327 | |||
328 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | ||
329 | return -ENODEV; | ||
330 | |||
331 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); | ||
332 | if (!indio_dev) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | regmap = devm_regmap_init_i2c(client, &jsa1212_regmap_config); | ||
336 | if (IS_ERR(regmap)) { | ||
337 | dev_err(&client->dev, "Regmap initialization failed.\n"); | ||
338 | return PTR_ERR(regmap); | ||
339 | } | ||
340 | |||
341 | data = iio_priv(indio_dev); | ||
342 | |||
343 | i2c_set_clientdata(client, indio_dev); | ||
344 | data->client = client; | ||
345 | data->regmap = regmap; | ||
346 | |||
347 | mutex_init(&data->lock); | ||
348 | |||
349 | ret = jsa1212_chip_init(data); | ||
350 | if (ret < 0) | ||
351 | return ret; | ||
352 | |||
353 | indio_dev->dev.parent = &client->dev; | ||
354 | indio_dev->channels = jsa1212_channels; | ||
355 | indio_dev->num_channels = ARRAY_SIZE(jsa1212_channels); | ||
356 | indio_dev->name = JSA1212_DRIVER_NAME; | ||
357 | indio_dev->modes = INDIO_DIRECT_MODE; | ||
358 | |||
359 | indio_dev->info = &jsa1212_info; | ||
360 | |||
361 | ret = iio_device_register(indio_dev); | ||
362 | if (ret < 0) | ||
363 | dev_err(&client->dev, "%s: register device failed\n", __func__); | ||
364 | |||
365 | return ret; | ||
366 | } | ||
367 | |||
368 | /* power off the device */ | ||
369 | static int jsa1212_power_off(struct jsa1212_data *data) | ||
370 | { | ||
371 | int ret; | ||
372 | |||
373 | mutex_lock(&data->lock); | ||
374 | |||
375 | ret = regmap_update_bits(data->regmap, JSA1212_CONF_REG, | ||
376 | JSA1212_CONF_ALS_MASK | | ||
377 | JSA1212_CONF_PXS_MASK, | ||
378 | JSA1212_CONF_ALS_DISABLE | | ||
379 | JSA1212_CONF_PXS_DISABLE); | ||
380 | |||
381 | if (ret < 0) | ||
382 | dev_err(&data->client->dev, "power off cmd failed\n"); | ||
383 | |||
384 | mutex_unlock(&data->lock); | ||
385 | |||
386 | return ret; | ||
387 | } | ||
388 | |||
389 | static int jsa1212_remove(struct i2c_client *client) | ||
390 | { | ||
391 | struct iio_dev *indio_dev = i2c_get_clientdata(client); | ||
392 | struct jsa1212_data *data = iio_priv(indio_dev); | ||
393 | |||
394 | iio_device_unregister(indio_dev); | ||
395 | |||
396 | return jsa1212_power_off(data); | ||
397 | } | ||
398 | |||
399 | #ifdef CONFIG_PM_SLEEP | ||
400 | static int jsa1212_suspend(struct device *dev) | ||
401 | { | ||
402 | struct jsa1212_data *data; | ||
403 | |||
404 | data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | ||
405 | |||
406 | return jsa1212_power_off(data); | ||
407 | } | ||
408 | |||
409 | static int jsa1212_resume(struct device *dev) | ||
410 | { | ||
411 | int ret = 0; | ||
412 | struct jsa1212_data *data; | ||
413 | |||
414 | data = iio_priv(i2c_get_clientdata(to_i2c_client(dev))); | ||
415 | |||
416 | mutex_lock(&data->lock); | ||
417 | |||
418 | if (data->als_en) { | ||
419 | ret = jsa1212_als_enable(data, JSA1212_CONF_ALS_ENABLE); | ||
420 | if (ret < 0) { | ||
421 | dev_err(dev, "als resume failed\n"); | ||
422 | goto unlock_and_ret; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | if (data->pxs_en) { | ||
427 | ret = jsa1212_pxs_enable(data, JSA1212_CONF_PXS_ENABLE); | ||
428 | if (ret < 0) | ||
429 | dev_err(dev, "pxs resume failed\n"); | ||
430 | } | ||
431 | |||
432 | unlock_and_ret: | ||
433 | mutex_unlock(&data->lock); | ||
434 | return ret; | ||
435 | } | ||
436 | |||
437 | static SIMPLE_DEV_PM_OPS(jsa1212_pm_ops, jsa1212_suspend, jsa1212_resume); | ||
438 | |||
439 | #define JSA1212_PM_OPS (&jsa1212_pm_ops) | ||
440 | #else | ||
441 | #define JSA1212_PM_OPS NULL | ||
442 | #endif | ||
443 | |||
444 | static const struct acpi_device_id jsa1212_acpi_match[] = { | ||
445 | {"JSA1212", 0}, | ||
446 | { }, | ||
447 | }; | ||
448 | MODULE_DEVICE_TABLE(acpi, jsa1212_acpi_match); | ||
449 | |||
450 | static const struct i2c_device_id jsa1212_id[] = { | ||
451 | { JSA1212_DRIVER_NAME, 0 }, | ||
452 | { } | ||
453 | }; | ||
454 | MODULE_DEVICE_TABLE(i2c, jsa1212_id); | ||
455 | |||
456 | static struct i2c_driver jsa1212_driver = { | ||
457 | .driver = { | ||
458 | .name = JSA1212_DRIVER_NAME, | ||
459 | .pm = JSA1212_PM_OPS, | ||
460 | .owner = THIS_MODULE, | ||
461 | .acpi_match_table = ACPI_PTR(jsa1212_acpi_match), | ||
462 | }, | ||
463 | .probe = jsa1212_probe, | ||
464 | .remove = jsa1212_remove, | ||
465 | .id_table = jsa1212_id, | ||
466 | }; | ||
467 | module_i2c_driver(jsa1212_driver); | ||
468 | |||
469 | MODULE_AUTHOR("Sathya Kuppuswamy <sathyanarayanan.kuppuswamy@linux.intel.com>"); | ||
470 | MODULE_DESCRIPTION("JSA1212 proximity/ambient light sensor driver"); | ||
471 | MODULE_LICENSE("GPL v2"); | ||