diff options
author | Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com> | 2014-05-08 17:58:00 -0400 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2014-08-07 06:27:41 -0400 |
commit | a735e3d7f03ab40d746290954baaf535719d9025 (patch) | |
tree | 2fce9f451e56e6775dc0e6864eea20be9be0c249 /drivers/iio | |
parent | 124e1b1d0924ca51ded8bb6f52844b2bc9e485f7 (diff) |
iio: accel: kxcjk-1013: Set adjustable range
This chip can support 3 different ranges. Allowing range specification.
Signed-off-by: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r-- | drivers/iio/accel/kxcjk-1013.c | 100 |
1 files changed, 95 insertions, 5 deletions
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index b32bdd10e0c4..57c515bf0fd2 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c | |||
@@ -82,6 +82,7 @@ struct kxcjk1013_data { | |||
82 | struct mutex mutex; | 82 | struct mutex mutex; |
83 | s16 buffer[8]; | 83 | s16 buffer[8]; |
84 | u8 odr_bits; | 84 | u8 odr_bits; |
85 | u8 range; | ||
85 | bool active_high_intr; | 86 | bool active_high_intr; |
86 | bool trigger_on; | 87 | bool trigger_on; |
87 | }; | 88 | }; |
@@ -97,6 +98,12 @@ enum kxcjk1013_mode { | |||
97 | OPERATION, | 98 | OPERATION, |
98 | }; | 99 | }; |
99 | 100 | ||
101 | enum kxcjk1013_range { | ||
102 | KXCJK1013_RANGE_2G, | ||
103 | KXCJK1013_RANGE_4G, | ||
104 | KXCJK1013_RANGE_8G, | ||
105 | }; | ||
106 | |||
100 | static const struct { | 107 | static const struct { |
101 | int val; | 108 | int val; |
102 | int val2; | 109 | int val2; |
@@ -116,6 +123,14 @@ static const struct { | |||
116 | {0x02, 21000}, {0x03, 11000}, {0x04, 6400}, | 123 | {0x02, 21000}, {0x03, 11000}, {0x04, 6400}, |
117 | {0x05, 3900}, {0x06, 2700}, {0x07, 2100} }; | 124 | {0x05, 3900}, {0x06, 2700}, {0x07, 2100} }; |
118 | 125 | ||
126 | static const struct { | ||
127 | u16 scale; | ||
128 | u8 gsel_0; | ||
129 | u8 gsel_1; | ||
130 | } KXCJK1013_scale_table[] = { {9582, 0, 0}, | ||
131 | {19163, 1, 0}, | ||
132 | {38326, 0, 1} }; | ||
133 | |||
119 | static int kxcjk1013_set_mode(struct kxcjk1013_data *data, | 134 | static int kxcjk1013_set_mode(struct kxcjk1013_data *data, |
120 | enum kxcjk1013_mode mode) | 135 | enum kxcjk1013_mode mode) |
121 | { | 136 | { |
@@ -161,6 +176,32 @@ static int kxcjk1013_get_mode(struct kxcjk1013_data *data, | |||
161 | return 0; | 176 | return 0; |
162 | } | 177 | } |
163 | 178 | ||
179 | static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index) | ||
180 | { | ||
181 | int ret; | ||
182 | |||
183 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_CTRL1); | ||
184 | if (ret < 0) { | ||
185 | dev_err(&data->client->dev, "Error reading reg_ctrl1\n"); | ||
186 | return ret; | ||
187 | } | ||
188 | |||
189 | ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3); | ||
190 | ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4); | ||
191 | |||
192 | ret = i2c_smbus_write_byte_data(data->client, | ||
193 | KXCJK1013_REG_CTRL1, | ||
194 | ret); | ||
195 | if (ret < 0) { | ||
196 | dev_err(&data->client->dev, "Error writing reg_ctrl1\n"); | ||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | data->range = range_index; | ||
201 | |||
202 | return 0; | ||
203 | } | ||
204 | |||
164 | static int kxcjk1013_chip_init(struct kxcjk1013_data *data) | 205 | static int kxcjk1013_chip_init(struct kxcjk1013_data *data) |
165 | { | 206 | { |
166 | int ret; | 207 | int ret; |
@@ -183,10 +224,6 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) | |||
183 | return ret; | 224 | return ret; |
184 | } | 225 | } |
185 | 226 | ||
186 | /* Setting range to 4G */ | ||
187 | ret |= KXCJK1013_REG_CTRL1_BIT_GSEL0; | ||
188 | ret &= ~KXCJK1013_REG_CTRL1_BIT_GSEL1; | ||
189 | |||
190 | /* Set 12 bit mode */ | 227 | /* Set 12 bit mode */ |
191 | ret |= KXCJK1013_REG_CTRL1_BIT_RES; | 228 | ret |= KXCJK1013_REG_CTRL1_BIT_RES; |
192 | 229 | ||
@@ -197,6 +234,14 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data) | |||
197 | return ret; | 234 | return ret; |
198 | } | 235 | } |
199 | 236 | ||
237 | /* Setting range to 4G */ | ||
238 | ret = kxcjk1013_set_range(data, KXCJK1013_RANGE_4G); | ||
239 | if (ret < 0) | ||
240 | return ret; | ||
241 | |||
242 | data->range = KXCJK1013_RANGE_4G; | ||
243 | |||
244 | |||
200 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL); | 245 | ret = i2c_smbus_read_byte_data(data->client, KXCJK1013_REG_DATA_CTRL); |
201 | if (ret < 0) { | 246 | if (ret < 0) { |
202 | dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); | 247 | dev_err(&data->client->dev, "Error reading reg_data_ctrl\n"); |
@@ -403,6 +448,40 @@ static int kxcjk1013_get_acc_reg(struct kxcjk1013_data *data, int axis) | |||
403 | return ret; | 448 | return ret; |
404 | } | 449 | } |
405 | 450 | ||
451 | static int kxcjk1013_set_scale(struct kxcjk1013_data *data, int val) | ||
452 | { | ||
453 | int ret, i; | ||
454 | enum kxcjk1013_mode store_mode; | ||
455 | |||
456 | |||
457 | for (i = 0; i < ARRAY_SIZE(KXCJK1013_scale_table); ++i) { | ||
458 | if (KXCJK1013_scale_table[i].scale == val) { | ||
459 | |||
460 | ret = kxcjk1013_get_mode(data, &store_mode); | ||
461 | if (ret < 0) | ||
462 | return ret; | ||
463 | |||
464 | ret = kxcjk1013_set_mode(data, STANDBY); | ||
465 | if (ret < 0) | ||
466 | return ret; | ||
467 | |||
468 | ret = kxcjk1013_set_range(data, i); | ||
469 | if (ret < 0) | ||
470 | return ret; | ||
471 | |||
472 | if (store_mode == OPERATION) { | ||
473 | ret = kxcjk1013_set_mode(data, OPERATION); | ||
474 | if (ret) | ||
475 | return ret; | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | } | ||
481 | |||
482 | return -EINVAL; | ||
483 | } | ||
484 | |||
406 | static int kxcjk1013_read_raw(struct iio_dev *indio_dev, | 485 | static int kxcjk1013_read_raw(struct iio_dev *indio_dev, |
407 | struct iio_chan_spec const *chan, int *val, | 486 | struct iio_chan_spec const *chan, int *val, |
408 | int *val2, long mask) | 487 | int *val2, long mask) |
@@ -439,7 +518,7 @@ static int kxcjk1013_read_raw(struct iio_dev *indio_dev, | |||
439 | 518 | ||
440 | case IIO_CHAN_INFO_SCALE: | 519 | case IIO_CHAN_INFO_SCALE: |
441 | *val = 0; | 520 | *val = 0; |
442 | *val2 = 19163; /* range +-4g (4/2047*9.806650) */ | 521 | *val2 = KXCJK1013_scale_table[data->range].scale; |
443 | return IIO_VAL_INT_PLUS_MICRO; | 522 | return IIO_VAL_INT_PLUS_MICRO; |
444 | 523 | ||
445 | case IIO_CHAN_INFO_SAMP_FREQ: | 524 | case IIO_CHAN_INFO_SAMP_FREQ: |
@@ -466,6 +545,14 @@ static int kxcjk1013_write_raw(struct iio_dev *indio_dev, | |||
466 | ret = kxcjk1013_set_odr(data, val, val2); | 545 | ret = kxcjk1013_set_odr(data, val, val2); |
467 | mutex_unlock(&data->mutex); | 546 | mutex_unlock(&data->mutex); |
468 | break; | 547 | break; |
548 | case IIO_CHAN_INFO_SCALE: | ||
549 | if (val) | ||
550 | return -EINVAL; | ||
551 | |||
552 | mutex_lock(&data->mutex); | ||
553 | ret = kxcjk1013_set_scale(data, val2); | ||
554 | mutex_unlock(&data->mutex); | ||
555 | break; | ||
469 | default: | 556 | default: |
470 | ret = -EINVAL; | 557 | ret = -EINVAL; |
471 | } | 558 | } |
@@ -487,8 +574,11 @@ static int kxcjk1013_validate_trigger(struct iio_dev *indio_dev, | |||
487 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( | 574 | static IIO_CONST_ATTR_SAMP_FREQ_AVAIL( |
488 | "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600"); | 575 | "0.781000 1.563000 3.125000 6.250000 12.500000 25 50 100 200 400 800 1600"); |
489 | 576 | ||
577 | static IIO_CONST_ATTR(in_accel_scale_available, "0.009582 0.019163 0.038326"); | ||
578 | |||
490 | static struct attribute *kxcjk1013_attributes[] = { | 579 | static struct attribute *kxcjk1013_attributes[] = { |
491 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, | 580 | &iio_const_attr_sampling_frequency_available.dev_attr.attr, |
581 | &iio_const_attr_in_accel_scale_available.dev_attr.attr, | ||
492 | NULL, | 582 | NULL, |
493 | }; | 583 | }; |
494 | 584 | ||