blob: 52c559d9e09b844a14828e56990e805bf95ec1a2 [file] [log] [blame]
Daniel Balutaefa86e9f2015-06-17 12:42:51 +03001/*
2 * RPR-0521 ROHM Ambient Light and Proximity Sensor
3 *
4 * Copyright (c) 2015, Intel Corporation.
5 *
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 *
10 * IIO driver for RPR-0521RS (7-bit I2C slave address 0x38).
11 *
Mikko Koivunen484c3142017-05-18 15:12:51 +030012 * TODO: illuminance channel, buffer
Daniel Balutaefa86e9f2015-06-17 12:42:51 +030013 */
14
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/i2c.h>
18#include <linux/regmap.h>
19#include <linux/delay.h>
20#include <linux/acpi.h>
21
22#include <linux/iio/iio.h>
23#include <linux/iio/sysfs.h>
24#include <linux/pm_runtime.h>
25
26#define RPR0521_REG_SYSTEM_CTRL 0x40
27#define RPR0521_REG_MODE_CTRL 0x41
28#define RPR0521_REG_ALS_CTRL 0x42
29#define RPR0521_REG_PXS_CTRL 0x43
30#define RPR0521_REG_PXS_DATA 0x44 /* 16-bit, little endian */
31#define RPR0521_REG_ALS_DATA0 0x46 /* 16-bit, little endian */
32#define RPR0521_REG_ALS_DATA1 0x48 /* 16-bit, little endian */
33#define RPR0521_REG_ID 0x92
34
35#define RPR0521_MODE_ALS_MASK BIT(7)
36#define RPR0521_MODE_PXS_MASK BIT(6)
37#define RPR0521_MODE_MEAS_TIME_MASK GENMASK(3, 0)
38#define RPR0521_ALS_DATA0_GAIN_MASK GENMASK(5, 4)
39#define RPR0521_ALS_DATA0_GAIN_SHIFT 4
40#define RPR0521_ALS_DATA1_GAIN_MASK GENMASK(3, 2)
41#define RPR0521_ALS_DATA1_GAIN_SHIFT 2
42#define RPR0521_PXS_GAIN_MASK GENMASK(5, 4)
43#define RPR0521_PXS_GAIN_SHIFT 4
44
45#define RPR0521_MODE_ALS_ENABLE BIT(7)
46#define RPR0521_MODE_ALS_DISABLE 0x00
47#define RPR0521_MODE_PXS_ENABLE BIT(6)
48#define RPR0521_MODE_PXS_DISABLE 0x00
49
50#define RPR0521_MANUFACT_ID 0xE0
51#define RPR0521_DEFAULT_MEAS_TIME 0x06 /* ALS - 100ms, PXS - 100ms */
52
53#define RPR0521_DRV_NAME "RPR0521"
54#define RPR0521_REGMAP_NAME "rpr0521_regmap"
55
56#define RPR0521_SLEEP_DELAY_MS 2000
57
58#define RPR0521_ALS_SCALE_AVAIL "0.007812 0.015625 0.5 1"
59#define RPR0521_PXS_SCALE_AVAIL "0.125 0.5 1"
60
61struct rpr0521_gain {
62 int scale;
63 int uscale;
64};
65
66static const struct rpr0521_gain rpr0521_als_gain[4] = {
67 {1, 0}, /* x1 */
68 {0, 500000}, /* x2 */
69 {0, 15625}, /* x64 */
70 {0, 7812}, /* x128 */
71};
72
73static const struct rpr0521_gain rpr0521_pxs_gain[3] = {
74 {1, 0}, /* x1 */
75 {0, 500000}, /* x2 */
76 {0, 125000}, /* x4 */
77};
78
79enum rpr0521_channel {
80 RPR0521_CHAN_ALS_DATA0,
81 RPR0521_CHAN_ALS_DATA1,
82 RPR0521_CHAN_PXS,
83};
84
85struct rpr0521_reg_desc {
86 u8 address;
87 u8 device_mask;
88};
89
90static const struct rpr0521_reg_desc rpr0521_data_reg[] = {
91 [RPR0521_CHAN_ALS_DATA0] = {
92 .address = RPR0521_REG_ALS_DATA0,
93 .device_mask = RPR0521_MODE_ALS_MASK,
94 },
95 [RPR0521_CHAN_ALS_DATA1] = {
96 .address = RPR0521_REG_ALS_DATA1,
97 .device_mask = RPR0521_MODE_ALS_MASK,
98 },
99 [RPR0521_CHAN_PXS] = {
100 .address = RPR0521_REG_PXS_DATA,
101 .device_mask = RPR0521_MODE_PXS_MASK,
102 },
103};
104
105static const struct rpr0521_gain_info {
106 u8 reg;
107 u8 mask;
108 u8 shift;
109 const struct rpr0521_gain *gain;
110 int size;
111} rpr0521_gain[] = {
112 [RPR0521_CHAN_ALS_DATA0] = {
113 .reg = RPR0521_REG_ALS_CTRL,
114 .mask = RPR0521_ALS_DATA0_GAIN_MASK,
115 .shift = RPR0521_ALS_DATA0_GAIN_SHIFT,
116 .gain = rpr0521_als_gain,
117 .size = ARRAY_SIZE(rpr0521_als_gain),
118 },
119 [RPR0521_CHAN_ALS_DATA1] = {
120 .reg = RPR0521_REG_ALS_CTRL,
121 .mask = RPR0521_ALS_DATA1_GAIN_MASK,
122 .shift = RPR0521_ALS_DATA1_GAIN_SHIFT,
123 .gain = rpr0521_als_gain,
124 .size = ARRAY_SIZE(rpr0521_als_gain),
125 },
126 [RPR0521_CHAN_PXS] = {
127 .reg = RPR0521_REG_PXS_CTRL,
128 .mask = RPR0521_PXS_GAIN_MASK,
129 .shift = RPR0521_PXS_GAIN_SHIFT,
130 .gain = rpr0521_pxs_gain,
131 .size = ARRAY_SIZE(rpr0521_pxs_gain),
132 },
133};
134
135struct rpr0521_data {
136 struct i2c_client *client;
137
138 /* protect device params updates (e.g state, gain) */
139 struct mutex lock;
140
141 /* device active status */
142 bool als_dev_en;
143 bool pxs_dev_en;
144
Mikko Koivunen484c3142017-05-18 15:12:51 +0300145 /* optimize runtime pm ops - enable/disable device only if needed */
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300146 bool als_ps_need_en;
147 bool pxs_ps_need_en;
Mikko Koivunen484c3142017-05-18 15:12:51 +0300148 bool als_need_dis;
149 bool pxs_need_dis;
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300150
151 struct regmap *regmap;
152};
153
154static IIO_CONST_ATTR(in_intensity_scale_available, RPR0521_ALS_SCALE_AVAIL);
155static IIO_CONST_ATTR(in_proximity_scale_available, RPR0521_PXS_SCALE_AVAIL);
156
157static struct attribute *rpr0521_attributes[] = {
158 &iio_const_attr_in_intensity_scale_available.dev_attr.attr,
159 &iio_const_attr_in_proximity_scale_available.dev_attr.attr,
160 NULL,
161};
162
163static const struct attribute_group rpr0521_attribute_group = {
164 .attrs = rpr0521_attributes,
165};
166
167static const struct iio_chan_spec rpr0521_channels[] = {
168 {
169 .type = IIO_INTENSITY,
170 .modified = 1,
171 .address = RPR0521_CHAN_ALS_DATA0,
172 .channel2 = IIO_MOD_LIGHT_BOTH,
173 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
174 BIT(IIO_CHAN_INFO_SCALE),
175 },
176 {
177 .type = IIO_INTENSITY,
178 .modified = 1,
179 .address = RPR0521_CHAN_ALS_DATA1,
180 .channel2 = IIO_MOD_LIGHT_IR,
181 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
182 BIT(IIO_CHAN_INFO_SCALE),
183 },
184 {
185 .type = IIO_PROXIMITY,
186 .address = RPR0521_CHAN_PXS,
187 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
188 BIT(IIO_CHAN_INFO_SCALE),
189 }
190};
191
192static int rpr0521_als_enable(struct rpr0521_data *data, u8 status)
193{
194 int ret;
195
196 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
197 RPR0521_MODE_ALS_MASK,
198 status);
199 if (ret < 0)
200 return ret;
201
Mikko Koivunenf87fa262017-05-18 15:12:49 +0300202 if (status & RPR0521_MODE_ALS_MASK)
203 data->als_dev_en = true;
204 else
205 data->als_dev_en = false;
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300206
207 return 0;
208}
209
210static int rpr0521_pxs_enable(struct rpr0521_data *data, u8 status)
211{
212 int ret;
213
214 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
215 RPR0521_MODE_PXS_MASK,
216 status);
217 if (ret < 0)
218 return ret;
219
Mikko Koivunenf87fa262017-05-18 15:12:49 +0300220 if (status & RPR0521_MODE_PXS_MASK)
221 data->pxs_dev_en = true;
222 else
223 data->pxs_dev_en = false;
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300224
225 return 0;
226}
227
228/**
229 * rpr0521_set_power_state - handles runtime PM state and sensors enabled status
230 *
231 * @data: rpr0521 device private data
232 * @on: state to be set for devices in @device_mask
233 * @device_mask: bitmask specifying for which device we need to update @on state
234 *
Mikko Koivunen484c3142017-05-18 15:12:51 +0300235 * Calls for this function must be balanced so that each ON should have matching
236 * OFF. Otherwise pm usage_count gets out of sync.
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300237 */
238static int rpr0521_set_power_state(struct rpr0521_data *data, bool on,
239 u8 device_mask)
240{
241#ifdef CONFIG_PM
242 int ret;
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300243
244 if (device_mask & RPR0521_MODE_ALS_MASK) {
Mikko Koivunen484c3142017-05-18 15:12:51 +0300245 data->als_ps_need_en = on;
246 data->als_need_dis = !on;
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300247 }
248
249 if (device_mask & RPR0521_MODE_PXS_MASK) {
Mikko Koivunen484c3142017-05-18 15:12:51 +0300250 data->pxs_ps_need_en = on;
251 data->pxs_need_dis = !on;
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300252 }
253
Mikko Koivunen484c3142017-05-18 15:12:51 +0300254 /*
255 * On: _resume() is called only when we are suspended
256 * Off: _suspend() is called after delay if _resume() is not
257 * called before that.
258 * Note: If either measurement is re-enabled before _suspend(),
259 * both stay enabled until _suspend().
260 */
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300261 if (on) {
262 ret = pm_runtime_get_sync(&data->client->dev);
263 } else {
264 pm_runtime_mark_last_busy(&data->client->dev);
265 ret = pm_runtime_put_autosuspend(&data->client->dev);
266 }
267 if (ret < 0) {
268 dev_err(&data->client->dev,
269 "Failed: rpr0521_set_power_state for %d, ret %d\n",
270 on, ret);
271 if (on)
272 pm_runtime_put_noidle(&data->client->dev);
273
274 return ret;
275 }
Mikko Koivunen484c3142017-05-18 15:12:51 +0300276
277 if (on) {
278 /* If _resume() was not called, enable measurement now. */
279 if (data->als_ps_need_en) {
280 ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
281 if (ret)
282 return ret;
283 data->als_ps_need_en = false;
284 }
285
286 if (data->pxs_ps_need_en) {
287 ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
288 if (ret)
289 return ret;
290 data->pxs_ps_need_en = false;
291 }
292 }
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300293#endif
294 return 0;
295}
296
297static int rpr0521_get_gain(struct rpr0521_data *data, int chan,
298 int *val, int *val2)
299{
300 int ret, reg, idx;
301
302 ret = regmap_read(data->regmap, rpr0521_gain[chan].reg, &reg);
303 if (ret < 0)
304 return ret;
305
306 idx = (rpr0521_gain[chan].mask & reg) >> rpr0521_gain[chan].shift;
307 *val = rpr0521_gain[chan].gain[idx].scale;
308 *val2 = rpr0521_gain[chan].gain[idx].uscale;
309
310 return 0;
311}
312
313static int rpr0521_set_gain(struct rpr0521_data *data, int chan,
314 int val, int val2)
315{
316 int i, idx = -EINVAL;
317
318 /* get gain index */
319 for (i = 0; i < rpr0521_gain[chan].size; i++)
320 if (val == rpr0521_gain[chan].gain[i].scale &&
321 val2 == rpr0521_gain[chan].gain[i].uscale) {
322 idx = i;
323 break;
324 }
325
326 if (idx < 0)
327 return idx;
328
329 return regmap_update_bits(data->regmap, rpr0521_gain[chan].reg,
330 rpr0521_gain[chan].mask,
331 idx << rpr0521_gain[chan].shift);
332}
333
334static int rpr0521_read_raw(struct iio_dev *indio_dev,
335 struct iio_chan_spec const *chan, int *val,
336 int *val2, long mask)
337{
338 struct rpr0521_data *data = iio_priv(indio_dev);
339 int ret;
340 u8 device_mask;
341 __le16 raw_data;
342
343 switch (mask) {
344 case IIO_CHAN_INFO_RAW:
345 if (chan->type != IIO_INTENSITY && chan->type != IIO_PROXIMITY)
346 return -EINVAL;
347
348 device_mask = rpr0521_data_reg[chan->address].device_mask;
349
350 mutex_lock(&data->lock);
351 ret = rpr0521_set_power_state(data, true, device_mask);
352 if (ret < 0) {
353 mutex_unlock(&data->lock);
354 return ret;
355 }
356
357 ret = regmap_bulk_read(data->regmap,
358 rpr0521_data_reg[chan->address].address,
Mikko Koivunenae591652017-05-18 15:12:52 +0300359 &raw_data, sizeof(raw_data));
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300360 if (ret < 0) {
361 rpr0521_set_power_state(data, false, device_mask);
362 mutex_unlock(&data->lock);
363 return ret;
364 }
365
366 ret = rpr0521_set_power_state(data, false, device_mask);
367 mutex_unlock(&data->lock);
368 if (ret < 0)
369 return ret;
370
371 *val = le16_to_cpu(raw_data);
372
373 return IIO_VAL_INT;
Mikko Koivunen624c3892017-05-18 15:12:53 +0300374
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300375 case IIO_CHAN_INFO_SCALE:
376 mutex_lock(&data->lock);
377 ret = rpr0521_get_gain(data, chan->address, val, val2);
378 mutex_unlock(&data->lock);
379 if (ret < 0)
380 return ret;
381
382 return IIO_VAL_INT_PLUS_MICRO;
Mikko Koivunen624c3892017-05-18 15:12:53 +0300383
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300384 default:
385 return -EINVAL;
386 }
387}
388
389static int rpr0521_write_raw(struct iio_dev *indio_dev,
390 struct iio_chan_spec const *chan, int val,
391 int val2, long mask)
392{
393 struct rpr0521_data *data = iio_priv(indio_dev);
394 int ret;
395
396 switch (mask) {
397 case IIO_CHAN_INFO_SCALE:
398 mutex_lock(&data->lock);
399 ret = rpr0521_set_gain(data, chan->address, val, val2);
400 mutex_unlock(&data->lock);
401
402 return ret;
Mikko Koivunen624c3892017-05-18 15:12:53 +0300403
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300404 default:
405 return -EINVAL;
406 }
407}
408
409static const struct iio_info rpr0521_info = {
410 .driver_module = THIS_MODULE,
411 .read_raw = rpr0521_read_raw,
412 .write_raw = rpr0521_write_raw,
413 .attrs = &rpr0521_attribute_group,
414};
415
416static int rpr0521_init(struct rpr0521_data *data)
417{
418 int ret;
419 int id;
420
421 ret = regmap_read(data->regmap, RPR0521_REG_ID, &id);
422 if (ret < 0) {
423 dev_err(&data->client->dev, "Failed to read REG_ID register\n");
424 return ret;
425 }
426
427 if (id != RPR0521_MANUFACT_ID) {
428 dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n",
429 id, RPR0521_MANUFACT_ID);
430 return -ENODEV;
431 }
432
433 /* set default measurement time - 100 ms for both ALS and PS */
434 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
435 RPR0521_MODE_MEAS_TIME_MASK,
436 RPR0521_DEFAULT_MEAS_TIME);
437 if (ret) {
438 pr_err("regmap_update_bits returned %d\n", ret);
439 return ret;
440 }
441
Mikko Koivunen484c3142017-05-18 15:12:51 +0300442#ifndef CONFIG_PM
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300443 ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
444 if (ret < 0)
445 return ret;
446 ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
447 if (ret < 0)
448 return ret;
Mikko Koivunen484c3142017-05-18 15:12:51 +0300449#endif
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300450
451 return 0;
452}
453
454static int rpr0521_poweroff(struct rpr0521_data *data)
455{
456 int ret;
457
458 ret = regmap_update_bits(data->regmap, RPR0521_REG_MODE_CTRL,
459 RPR0521_MODE_ALS_MASK |
460 RPR0521_MODE_PXS_MASK,
461 RPR0521_MODE_ALS_DISABLE |
462 RPR0521_MODE_PXS_DISABLE);
463 if (ret < 0)
464 return ret;
465
466 data->als_dev_en = false;
467 data->pxs_dev_en = false;
468
469 return 0;
470}
471
472static bool rpr0521_is_volatile_reg(struct device *dev, unsigned int reg)
473{
474 switch (reg) {
475 case RPR0521_REG_MODE_CTRL:
476 case RPR0521_REG_ALS_CTRL:
477 case RPR0521_REG_PXS_CTRL:
478 return false;
479 default:
480 return true;
481 }
482}
483
484static const struct regmap_config rpr0521_regmap_config = {
485 .name = RPR0521_REGMAP_NAME,
486
487 .reg_bits = 8,
488 .val_bits = 8,
489
490 .max_register = RPR0521_REG_ID,
491 .cache_type = REGCACHE_RBTREE,
492 .volatile_reg = rpr0521_is_volatile_reg,
493};
494
495static int rpr0521_probe(struct i2c_client *client,
496 const struct i2c_device_id *id)
497{
498 struct rpr0521_data *data;
499 struct iio_dev *indio_dev;
500 struct regmap *regmap;
501 int ret;
502
503 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
504 if (!indio_dev)
505 return -ENOMEM;
506
507 regmap = devm_regmap_init_i2c(client, &rpr0521_regmap_config);
508 if (IS_ERR(regmap)) {
509 dev_err(&client->dev, "regmap_init failed!\n");
510 return PTR_ERR(regmap);
511 }
512
513 data = iio_priv(indio_dev);
514 i2c_set_clientdata(client, indio_dev);
515 data->client = client;
516 data->regmap = regmap;
517
518 mutex_init(&data->lock);
519
520 indio_dev->dev.parent = &client->dev;
521 indio_dev->info = &rpr0521_info;
522 indio_dev->name = RPR0521_DRV_NAME;
523 indio_dev->channels = rpr0521_channels;
524 indio_dev->num_channels = ARRAY_SIZE(rpr0521_channels);
525 indio_dev->modes = INDIO_DIRECT_MODE;
526
527 ret = rpr0521_init(data);
528 if (ret < 0) {
529 dev_err(&client->dev, "rpr0521 chip init failed\n");
530 return ret;
531 }
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300532
533 ret = pm_runtime_set_active(&client->dev);
534 if (ret < 0)
Mikko Koivunen12d74942017-05-18 15:12:50 +0300535 goto err_poweroff;
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300536
537 pm_runtime_enable(&client->dev);
538 pm_runtime_set_autosuspend_delay(&client->dev, RPR0521_SLEEP_DELAY_MS);
539 pm_runtime_use_autosuspend(&client->dev);
540
Mikko Koivunen12d74942017-05-18 15:12:50 +0300541 ret = iio_device_register(indio_dev);
542 if (ret)
543 goto err_pm_disable;
544
545 return 0;
546
547err_pm_disable:
548 pm_runtime_disable(&client->dev);
549 pm_runtime_set_suspended(&client->dev);
550 pm_runtime_put_noidle(&client->dev);
551err_poweroff:
552 rpr0521_poweroff(data);
553
554 return ret;
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300555}
556
557static int rpr0521_remove(struct i2c_client *client)
558{
559 struct iio_dev *indio_dev = i2c_get_clientdata(client);
560
Adriana Reus7d0ead52015-11-05 16:25:29 +0200561 iio_device_unregister(indio_dev);
562
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300563 pm_runtime_disable(&client->dev);
564 pm_runtime_set_suspended(&client->dev);
565 pm_runtime_put_noidle(&client->dev);
566
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300567 rpr0521_poweroff(iio_priv(indio_dev));
568
569 return 0;
570}
571
572#ifdef CONFIG_PM
573static int rpr0521_runtime_suspend(struct device *dev)
574{
575 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
576 struct rpr0521_data *data = iio_priv(indio_dev);
577 int ret;
578
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300579 mutex_lock(&data->lock);
Mikko Koivunen484c3142017-05-18 15:12:51 +0300580 /* If measurements are enabled, enable them on resume */
581 if (!data->als_need_dis)
582 data->als_ps_need_en = data->als_dev_en;
583 if (!data->pxs_need_dis)
584 data->pxs_ps_need_en = data->pxs_dev_en;
585
586 /* disable channels and sets {als,pxs}_dev_en to false */
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300587 ret = rpr0521_poweroff(data);
Mikko Koivunen484c3142017-05-18 15:12:51 +0300588 regcache_mark_dirty(data->regmap);
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300589 mutex_unlock(&data->lock);
590
591 return ret;
592}
593
594static int rpr0521_runtime_resume(struct device *dev)
595{
596 struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
597 struct rpr0521_data *data = iio_priv(indio_dev);
598 int ret;
599
Mikko Koivunen484c3142017-05-18 15:12:51 +0300600 regcache_sync(data->regmap);
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300601 if (data->als_ps_need_en) {
602 ret = rpr0521_als_enable(data, RPR0521_MODE_ALS_ENABLE);
603 if (ret < 0)
604 return ret;
605 data->als_ps_need_en = false;
606 }
607
608 if (data->pxs_ps_need_en) {
609 ret = rpr0521_pxs_enable(data, RPR0521_MODE_PXS_ENABLE);
610 if (ret < 0)
611 return ret;
612 data->pxs_ps_need_en = false;
613 }
Mikko Koivunen484c3142017-05-18 15:12:51 +0300614 msleep(100); //wait for first measurement result
Daniel Balutaefa86e9f2015-06-17 12:42:51 +0300615
616 return 0;
617}
618#endif
619
620static const struct dev_pm_ops rpr0521_pm_ops = {
621 SET_RUNTIME_PM_OPS(rpr0521_runtime_suspend,
622 rpr0521_runtime_resume, NULL)
623};
624
625static const struct acpi_device_id rpr0521_acpi_match[] = {
626 {"RPR0521", 0},
627 { }
628};
629MODULE_DEVICE_TABLE(acpi, rpr0521_acpi_match);
630
631static const struct i2c_device_id rpr0521_id[] = {
632 {"rpr0521", 0},
633 { }
634};
635
636MODULE_DEVICE_TABLE(i2c, rpr0521_id);
637
638static struct i2c_driver rpr0521_driver = {
639 .driver = {
640 .name = RPR0521_DRV_NAME,
641 .pm = &rpr0521_pm_ops,
642 .acpi_match_table = ACPI_PTR(rpr0521_acpi_match),
643 },
644 .probe = rpr0521_probe,
645 .remove = rpr0521_remove,
646 .id_table = rpr0521_id,
647};
648
649module_i2c_driver(rpr0521_driver);
650
651MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
652MODULE_DESCRIPTION("RPR0521 ROHM Ambient Light and Proximity Sensor driver");
653MODULE_LICENSE("GPL v2");