diff options
author | Adriana Reus <adriana.reus@intel.com> | 2015-11-24 05:59:48 -0500 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2015-12-02 13:42:03 -0500 |
commit | c3304c212326cfcabb1faf6a0035d0c631778d5b (patch) | |
tree | 797b21c5146f0b6ee5eb721b4583cb199277c5f8 | |
parent | 930cc0f39b07a830e6939c5634f9a310f306c4b1 (diff) |
iio: light: us5182d: Add property for choosing default power mode
This chip supports two power modes.
1. "one-shot" mode - the chip activates and executes one complete
conversion loop and then shuts itself down. This is the default mode
chosen for raw reads.
2. "continuous" mode - the chip takes continuous measurements.
Continuous mode is more expensive power-wise but may be more reliable.
Add a property so that if preferred, the default power mode for raw
reads can be set to continuous.
Separate one-shot enabling in a separate function that will be used
depending on the chosen power mode. Also create a function for
powering the chip on and off.
Signed-off-by: Adriana Reus <adriana.reus@intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r-- | drivers/iio/light/us5182d.c | 90 |
1 files changed, 78 insertions, 12 deletions
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c index 49dab3cb3e23..855f183ba216 100644 --- a/drivers/iio/light/us5182d.c +++ b/drivers/iio/light/us5182d.c | |||
@@ -99,6 +99,11 @@ enum mode { | |||
99 | US5182D_PX_ONLY | 99 | US5182D_PX_ONLY |
100 | }; | 100 | }; |
101 | 101 | ||
102 | enum pmode { | ||
103 | US5182D_CONTINUOUS, | ||
104 | US5182D_ONESHOT | ||
105 | }; | ||
106 | |||
102 | struct us5182d_data { | 107 | struct us5182d_data { |
103 | struct i2c_client *client; | 108 | struct i2c_client *client; |
104 | struct mutex lock; | 109 | struct mutex lock; |
@@ -112,6 +117,9 @@ struct us5182d_data { | |||
112 | u16 *us5182d_dark_ths; | 117 | u16 *us5182d_dark_ths; |
113 | 118 | ||
114 | u8 opmode; | 119 | u8 opmode; |
120 | u8 power_mode; | ||
121 | |||
122 | bool default_continuous; | ||
115 | }; | 123 | }; |
116 | 124 | ||
117 | static IIO_CONST_ATTR(in_illuminance_scale_available, | 125 | static IIO_CONST_ATTR(in_illuminance_scale_available, |
@@ -130,13 +138,11 @@ static const struct { | |||
130 | u8 reg; | 138 | u8 reg; |
131 | u8 val; | 139 | u8 val; |
132 | } us5182d_regvals[] = { | 140 | } us5182d_regvals[] = { |
133 | {US5182D_REG_CFG0, (US5182D_CFG0_SHUTDOWN_EN | | 141 | {US5182D_REG_CFG0, US5182D_CFG0_WORD_ENABLE}, |
134 | US5182D_CFG0_WORD_ENABLE)}, | ||
135 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, | 142 | {US5182D_REG_CFG1, US5182D_CFG1_ALS_RES16}, |
136 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | | 143 | {US5182D_REG_CFG2, (US5182D_CFG2_PX_RES16 | |
137 | US5182D_CFG2_PXGAIN_DEFAULT)}, | 144 | US5182D_CFG2_PXGAIN_DEFAULT)}, |
138 | {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100}, | 145 | {US5182D_REG_CFG3, US5182D_CFG3_LED_CURRENT100}, |
139 | {US5182D_REG_MODE_STORE, US5182D_STORE_MODE}, | ||
140 | {US5182D_REG_CFG4, 0x00}, | 146 | {US5182D_REG_CFG4, 0x00}, |
141 | }; | 147 | }; |
142 | 148 | ||
@@ -169,7 +175,7 @@ static int us5182d_get_als(struct us5182d_data *data) | |||
169 | return result; | 175 | return result; |
170 | } | 176 | } |
171 | 177 | ||
172 | static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) | 178 | static int us5182d_oneshot_en(struct us5182d_data *data) |
173 | { | 179 | { |
174 | int ret; | 180 | int ret; |
175 | 181 | ||
@@ -183,6 +189,20 @@ static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) | |||
183 | */ | 189 | */ |
184 | ret = ret | US5182D_CFG0_ONESHOT_EN; | 190 | ret = ret | US5182D_CFG0_ONESHOT_EN; |
185 | 191 | ||
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 | |||
186 | /* update mode */ | 206 | /* update mode */ |
187 | ret = ret & ~US5182D_OPMODE_MASK; | 207 | ret = ret & ~US5182D_OPMODE_MASK; |
188 | ret = ret | (mode << US5182D_OPMODE_SHIFT); | 208 | ret = ret | (mode << US5182D_OPMODE_SHIFT); |
@@ -196,9 +216,6 @@ static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) | |||
196 | if (ret < 0) | 216 | if (ret < 0) |
197 | return ret; | 217 | return ret; |
198 | 218 | ||
199 | if (mode == data->opmode) | ||
200 | return 0; | ||
201 | |||
202 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE, | 219 | ret = i2c_smbus_write_byte_data(data->client, US5182D_REG_MODE_STORE, |
203 | US5182D_STORE_MODE); | 220 | US5182D_STORE_MODE); |
204 | if (ret < 0) | 221 | if (ret < 0) |
@@ -210,6 +227,23 @@ static int us5182d_set_opmode(struct us5182d_data *data, u8 mode) | |||
210 | return 0; | 227 | return 0; |
211 | } | 228 | } |
212 | 229 | ||
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 | |||
213 | static int us5182d_read_raw(struct iio_dev *indio_dev, | 247 | static int us5182d_read_raw(struct iio_dev *indio_dev, |
214 | struct iio_chan_spec const *chan, int *val, | 248 | struct iio_chan_spec const *chan, int *val, |
215 | int *val2, long mask) | 249 | int *val2, long mask) |
@@ -222,6 +256,11 @@ static int us5182d_read_raw(struct iio_dev *indio_dev, | |||
222 | switch (chan->type) { | 256 | switch (chan->type) { |
223 | case IIO_LIGHT: | 257 | case IIO_LIGHT: |
224 | mutex_lock(&data->lock); | 258 | mutex_lock(&data->lock); |
259 | if (data->power_mode == US5182D_ONESHOT) { | ||
260 | ret = us5182d_oneshot_en(data); | ||
261 | if (ret < 0) | ||
262 | goto out_err; | ||
263 | } | ||
225 | ret = us5182d_set_opmode(data, US5182D_OPMODE_ALS); | 264 | ret = us5182d_set_opmode(data, US5182D_OPMODE_ALS); |
226 | if (ret < 0) | 265 | if (ret < 0) |
227 | goto out_err; | 266 | goto out_err; |
@@ -234,6 +273,11 @@ static int us5182d_read_raw(struct iio_dev *indio_dev, | |||
234 | return IIO_VAL_INT; | 273 | return IIO_VAL_INT; |
235 | case IIO_PROXIMITY: | 274 | case IIO_PROXIMITY: |
236 | mutex_lock(&data->lock); | 275 | mutex_lock(&data->lock); |
276 | if (data->power_mode == US5182D_ONESHOT) { | ||
277 | ret = us5182d_oneshot_en(data); | ||
278 | if (ret < 0) | ||
279 | goto out_err; | ||
280 | } | ||
237 | ret = us5182d_set_opmode(data, US5182D_OPMODE_PX); | 281 | ret = us5182d_set_opmode(data, US5182D_OPMODE_PX); |
238 | if (ret < 0) | 282 | if (ret < 0) |
239 | goto out_err; | 283 | goto out_err; |
@@ -368,6 +412,7 @@ static int us5182d_init(struct iio_dev *indio_dev) | |||
368 | return ret; | 412 | return ret; |
369 | 413 | ||
370 | data->opmode = 0; | 414 | data->opmode = 0; |
415 | data->power_mode = US5182D_CONTINUOUS; | ||
371 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { | 416 | for (i = 0; i < ARRAY_SIZE(us5182d_regvals); i++) { |
372 | ret = i2c_smbus_write_byte_data(data->client, | 417 | ret = i2c_smbus_write_byte_data(data->client, |
373 | us5182d_regvals[i].reg, | 418 | us5182d_regvals[i].reg, |
@@ -376,7 +421,15 @@ static int us5182d_init(struct iio_dev *indio_dev) | |||
376 | return ret; | 421 | return ret; |
377 | } | 422 | } |
378 | 423 | ||
379 | return 0; | 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; | ||
380 | } | 433 | } |
381 | 434 | ||
382 | static void us5182d_get_platform_data(struct iio_dev *indio_dev) | 435 | static void us5182d_get_platform_data(struct iio_dev *indio_dev) |
@@ -399,6 +452,8 @@ static void us5182d_get_platform_data(struct iio_dev *indio_dev) | |||
399 | "upisemi,lower-dark-gain", | 452 | "upisemi,lower-dark-gain", |
400 | &data->lower_dark_gain)) | 453 | &data->lower_dark_gain)) |
401 | data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT; | 454 | data->lower_dark_gain = US5182D_REG_AUTO_LDARK_GAIN_DEFAULT; |
455 | data->default_continuous = device_property_read_bool(&data->client->dev, | ||
456 | "upisemi,continuous"); | ||
402 | } | 457 | } |
403 | 458 | ||
404 | static int us5182d_dark_gain_config(struct iio_dev *indio_dev) | 459 | static int us5182d_dark_gain_config(struct iio_dev *indio_dev) |
@@ -464,16 +519,27 @@ static int us5182d_probe(struct i2c_client *client, | |||
464 | 519 | ||
465 | ret = us5182d_dark_gain_config(indio_dev); | 520 | ret = us5182d_dark_gain_config(indio_dev); |
466 | if (ret < 0) | 521 | if (ret < 0) |
467 | return ret; | 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; | ||
468 | 533 | ||
469 | return iio_device_register(indio_dev); | ||
470 | } | 534 | } |
471 | 535 | ||
472 | static int us5182d_remove(struct i2c_client *client) | 536 | static int us5182d_remove(struct i2c_client *client) |
473 | { | 537 | { |
538 | struct us5182d_data *data = iio_priv(i2c_get_clientdata(client)); | ||
539 | |||
474 | iio_device_unregister(i2c_get_clientdata(client)); | 540 | iio_device_unregister(i2c_get_clientdata(client)); |
475 | return i2c_smbus_write_byte_data(client, US5182D_REG_CFG0, | 541 | |
476 | US5182D_CFG0_SHUTDOWN_EN); | 542 | return us5182d_shutdown_en(data, US5182D_CFG0_SHUTDOWN_EN); |
477 | } | 543 | } |
478 | 544 | ||
479 | static const struct acpi_device_id us5182d_acpi_match[] = { | 545 | static const struct acpi_device_id us5182d_acpi_match[] = { |