|
23 | 23 | #include <linux/iio/iio.h>
|
24 | 24 | #include <linux/iio/triggered_buffer.h>
|
25 | 25 | #include <linux/iio/trigger_consumer.h>
|
| 26 | +#include <linux/minmax.h> |
26 | 27 | #include <linux/property.h>
|
27 | 28 | #include <linux/regmap.h>
|
28 | 29 | #include <linux/regulator/consumer.h>
|
@@ -225,7 +226,11 @@ static const struct iio_chan_spec ad4695_channel_template = {
|
225 | 226 | .indexed = 1,
|
226 | 227 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
|
227 | 228 | BIT(IIO_CHAN_INFO_SCALE) |
|
228 |
| - BIT(IIO_CHAN_INFO_OFFSET), |
| 229 | + BIT(IIO_CHAN_INFO_OFFSET) | |
| 230 | + BIT(IIO_CHAN_INFO_CALIBSCALE) | |
| 231 | + BIT(IIO_CHAN_INFO_CALIBBIAS), |
| 232 | + .info_mask_separate_available = BIT(IIO_CHAN_INFO_CALIBSCALE) | |
| 233 | + BIT(IIO_CHAN_INFO_CALIBBIAS), |
229 | 234 | .scan_type = {
|
230 | 235 | .sign = 'u',
|
231 | 236 | .realbits = 16,
|
@@ -619,7 +624,8 @@ static int ad4695_read_raw(struct iio_dev *indio_dev,
|
619 | 624 | struct ad4695_state *st = iio_priv(indio_dev);
|
620 | 625 | struct ad4695_channel_config *cfg = &st->channels_cfg[chan->scan_index];
|
621 | 626 | u8 realbits = chan->scan_type.realbits;
|
622 |
| - int ret; |
| 627 | + unsigned int reg_val; |
| 628 | + int ret, tmp; |
623 | 629 |
|
624 | 630 | switch (mask) {
|
625 | 631 | case IIO_CHAN_INFO_RAW:
|
@@ -670,6 +676,152 @@ static int ad4695_read_raw(struct iio_dev *indio_dev,
|
670 | 676 | default:
|
671 | 677 | return -EINVAL;
|
672 | 678 | }
|
| 679 | + case IIO_CHAN_INFO_CALIBSCALE: |
| 680 | + switch (chan->type) { |
| 681 | + case IIO_VOLTAGE: |
| 682 | + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { |
| 683 | + ret = regmap_read(st->regmap16, |
| 684 | + AD4695_REG_GAIN_IN(chan->scan_index), |
| 685 | + ®_val); |
| 686 | + if (ret) |
| 687 | + return ret; |
| 688 | + |
| 689 | + *val = reg_val; |
| 690 | + *val2 = 15; |
| 691 | + |
| 692 | + return IIO_VAL_FRACTIONAL_LOG2; |
| 693 | + } |
| 694 | + unreachable(); |
| 695 | + default: |
| 696 | + return -EINVAL; |
| 697 | + } |
| 698 | + case IIO_CHAN_INFO_CALIBBIAS: |
| 699 | + switch (chan->type) { |
| 700 | + case IIO_VOLTAGE: |
| 701 | + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { |
| 702 | + ret = regmap_read(st->regmap16, |
| 703 | + AD4695_REG_OFFSET_IN(chan->scan_index), |
| 704 | + ®_val); |
| 705 | + if (ret) |
| 706 | + return ret; |
| 707 | + |
| 708 | + tmp = sign_extend32(reg_val, 15); |
| 709 | + |
| 710 | + *val = tmp / 4; |
| 711 | + *val2 = abs(tmp) % 4 * MICRO / 4; |
| 712 | + |
| 713 | + if (tmp < 0 && *val2) { |
| 714 | + *val *= -1; |
| 715 | + *val2 *= -1; |
| 716 | + } |
| 717 | + |
| 718 | + return IIO_VAL_INT_PLUS_MICRO; |
| 719 | + } |
| 720 | + unreachable(); |
| 721 | + default: |
| 722 | + return -EINVAL; |
| 723 | + } |
| 724 | + default: |
| 725 | + return -EINVAL; |
| 726 | + } |
| 727 | +} |
| 728 | + |
| 729 | +static int ad4695_write_raw(struct iio_dev *indio_dev, |
| 730 | + struct iio_chan_spec const *chan, |
| 731 | + int val, int val2, long mask) |
| 732 | +{ |
| 733 | + struct ad4695_state *st = iio_priv(indio_dev); |
| 734 | + unsigned int reg_val; |
| 735 | + |
| 736 | + iio_device_claim_direct_scoped(return -EBUSY, indio_dev) { |
| 737 | + switch (mask) { |
| 738 | + case IIO_CHAN_INFO_CALIBSCALE: |
| 739 | + switch (chan->type) { |
| 740 | + case IIO_VOLTAGE: |
| 741 | + if (val < 0 || val2 < 0) |
| 742 | + reg_val = 0; |
| 743 | + else if (val > 1) |
| 744 | + reg_val = U16_MAX; |
| 745 | + else |
| 746 | + reg_val = (val * (1 << 16) + |
| 747 | + mul_u64_u32_div(val2, 1 << 16, |
| 748 | + MICRO)) / 2; |
| 749 | + |
| 750 | + return regmap_write(st->regmap16, |
| 751 | + AD4695_REG_GAIN_IN(chan->scan_index), |
| 752 | + reg_val); |
| 753 | + default: |
| 754 | + return -EINVAL; |
| 755 | + } |
| 756 | + case IIO_CHAN_INFO_CALIBBIAS: |
| 757 | + switch (chan->type) { |
| 758 | + case IIO_VOLTAGE: |
| 759 | + if (val2 >= 0 && val > S16_MAX / 4) |
| 760 | + reg_val = S16_MAX; |
| 761 | + else if ((val2 < 0 ? -val : val) < S16_MIN / 4) |
| 762 | + reg_val = S16_MIN; |
| 763 | + else if (val2 < 0) |
| 764 | + reg_val = clamp_t(int, |
| 765 | + -(val * 4 + -val2 * 4 / MICRO), |
| 766 | + S16_MIN, S16_MAX); |
| 767 | + else if (val < 0) |
| 768 | + reg_val = clamp_t(int, |
| 769 | + val * 4 - val2 * 4 / MICRO, |
| 770 | + S16_MIN, S16_MAX); |
| 771 | + else |
| 772 | + reg_val = clamp_t(int, |
| 773 | + val * 4 + val2 * 4 / MICRO, |
| 774 | + S16_MIN, S16_MAX); |
| 775 | + |
| 776 | + return regmap_write(st->regmap16, |
| 777 | + AD4695_REG_OFFSET_IN(chan->scan_index), |
| 778 | + reg_val); |
| 779 | + default: |
| 780 | + return -EINVAL; |
| 781 | + } |
| 782 | + default: |
| 783 | + return -EINVAL; |
| 784 | + } |
| 785 | + } |
| 786 | + unreachable(); |
| 787 | +} |
| 788 | + |
| 789 | +static int ad4695_read_avail(struct iio_dev *indio_dev, |
| 790 | + struct iio_chan_spec const *chan, |
| 791 | + const int **vals, int *type, int *length, |
| 792 | + long mask) |
| 793 | +{ |
| 794 | + static const int ad4695_calibscale_available[6] = { |
| 795 | + /* Range of 0 (inclusive) to 2 (exclusive) */ |
| 796 | + 0, 15, 1, 15, U16_MAX, 15 |
| 797 | + }; |
| 798 | + static const int ad4695_calibbias_available[6] = { |
| 799 | + /* |
| 800 | + * Datasheet says FSR/8 which translates to signed/4. The step |
| 801 | + * depends on oversampling ratio which is always 1 for now. |
| 802 | + */ |
| 803 | + S16_MIN / 4, 0, 0, MICRO / 4, S16_MAX / 4, S16_MAX % 4 * MICRO / 4 |
| 804 | + }; |
| 805 | + |
| 806 | + switch (mask) { |
| 807 | + case IIO_CHAN_INFO_CALIBSCALE: |
| 808 | + switch (chan->type) { |
| 809 | + case IIO_VOLTAGE: |
| 810 | + *vals = ad4695_calibscale_available; |
| 811 | + *type = IIO_VAL_FRACTIONAL_LOG2; |
| 812 | + return IIO_AVAIL_RANGE; |
| 813 | + default: |
| 814 | + return -EINVAL; |
| 815 | + } |
| 816 | + case IIO_CHAN_INFO_CALIBBIAS: |
| 817 | + switch (chan->type) { |
| 818 | + case IIO_VOLTAGE: |
| 819 | + *vals = ad4695_calibbias_available; |
| 820 | + *type = IIO_VAL_INT_PLUS_MICRO; |
| 821 | + return IIO_AVAIL_RANGE; |
| 822 | + default: |
| 823 | + return -EINVAL; |
| 824 | + } |
673 | 825 | default:
|
674 | 826 | return -EINVAL;
|
675 | 827 | }
|
@@ -705,6 +857,8 @@ static int ad4695_debugfs_reg_access(struct iio_dev *indio_dev,
|
705 | 857 |
|
706 | 858 | static const struct iio_info ad4695_info = {
|
707 | 859 | .read_raw = &ad4695_read_raw,
|
| 860 | + .write_raw = &ad4695_write_raw, |
| 861 | + .read_avail = &ad4695_read_avail, |
708 | 862 | .debugfs_reg_access = &ad4695_debugfs_reg_access,
|
709 | 863 | };
|
710 | 864 |
|
|
0 commit comments