diff options
Diffstat (limited to 'drivers/staging/iio/ring_generic.h')
-rw-r--r-- | drivers/staging/iio/ring_generic.h | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/drivers/staging/iio/ring_generic.h b/drivers/staging/iio/ring_generic.h index ac017b1..6124353 100644 --- a/drivers/staging/iio/ring_generic.h +++ b/drivers/staging/iio/ring_generic.h @@ -102,6 +102,11 @@ struct iio_ring_access_funcs { * @bytes_per_datum [DEVICE] size of individual datum including timestamp * @bpe: [DEVICE] size of individual channel value * @loopcount: [INTERN] number of times the ring has looped + * @scan_el_attrs: [DRIVER] control of scan elements if that scan mode + * control method is used + * @scan_count: [INTERN] the number of elements in the current scan mode + * @scan_mask: [INTERN] bitmask used in masking scan mode elements + * @scan_timestamp: [INTERN] does the scan mode include a timestamp * @access_handler: [INTERN] chrdev access handling * @ev_int: [INTERN] chrdev interface for the event chrdev * @shared_ev_pointer: [INTERN] the shared event pointer to allow escalation of @@ -124,6 +129,10 @@ struct iio_ring_buffer { int bytes_per_datum; int bpe; int loopcount; + struct attribute_group *scan_el_attrs; + int scan_count; + u32 scan_mask; + bool scan_timestamp; struct iio_handler access_handler; struct iio_event_interface ev_int; struct iio_shared_ev_pointer shared_ev_pointer; @@ -258,6 +267,97 @@ ssize_t iio_scan_el_ts_show(struct device *dev, struct device_attribute *attr, iio_scan_el_ts_store), \ } +/* + * These are mainly provided to allow for a change of implementation if a device + * has a large number of scan elements + */ +#define IIO_MAX_SCAN_LENGTH 31 + +/* note 0 used as error indicator as it doesn't make sense. */ +static inline u32 iio_scan_mask_match(u32 *av_masks, u32 mask) +{ + while (*av_masks) { + if (!(~*av_masks & mask)) + return *av_masks; + av_masks++; + } + return 0; +} + +static inline int iio_scan_mask_query(struct iio_ring_buffer *ring, int bit) +{ + struct iio_dev *dev_info = ring->indio_dev; + u32 mask; + + if (bit > IIO_MAX_SCAN_LENGTH) + return -EINVAL; + + if (!ring->scan_mask) + return 0; + + if (dev_info->available_scan_masks) + mask = iio_scan_mask_match(dev_info->available_scan_masks, + ring->scan_mask); + else + mask = ring->scan_mask; + + if (!mask) + return -EINVAL; + + return !!(mask & (1 << bit)); +}; + +static inline int iio_scan_mask_set(struct iio_ring_buffer *ring, int bit) +{ + struct iio_dev *dev_info = ring->indio_dev; + u32 mask; + u32 trialmask = ring->scan_mask | (1 << bit); + + if (bit > IIO_MAX_SCAN_LENGTH) + return -EINVAL; + if (dev_info->available_scan_masks) { + mask = iio_scan_mask_match(dev_info->available_scan_masks, + trialmask); + if (!mask) + return -EINVAL; + } + ring->scan_mask = trialmask; + ring->scan_count++; + + return 0; +}; + +static inline int iio_scan_mask_clear(struct iio_ring_buffer *ring, int bit) +{ + if (bit > IIO_MAX_SCAN_LENGTH) + return -EINVAL; + ring->scan_mask &= ~(1 << bit); + ring->scan_count--; + return 0; +}; + +/** + * iio_scan_mask_count_to_right() - how many scan elements occur before here + * @dev_info: the iio_device whose scan mode we are querying + * @bit: which number scan element is this + **/ +static inline int iio_scan_mask_count_to_right(struct iio_ring_buffer *ring, + int bit) +{ + int count = 0; + int mask = (1 << bit); + if (bit > IIO_MAX_SCAN_LENGTH) + return -EINVAL; + while (mask) { + mask >>= 1; + if (mask & ring->scan_mask) + count++; + } + + return count; +} + + static inline void iio_put_ring_buffer(struct iio_ring_buffer *ring) { put_device(&ring->dev); |