* [PATCH 1/7] staging:iio:find iio channel from scan index util function
2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
2011-11-27 13:10 ` [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index Jonathan Cameron
` (5 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron
From: Jonathan Cameron <jic23@cam.ac.uk>
Useful for getting to the channel based on scan mask alone.
Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
drivers/staging/iio/iio.h | 8 ++++++++
drivers/staging/iio/industrialio-core.c | 11 +++++++++++
2 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 4aed915..95d6318 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -323,6 +323,14 @@ struct iio_dev {
};
/**
+ * iio_find_channel_from_si() - get channel from its scan index
+ * @indio_dev: device
+ * @si: scan index to match
+ */
+const struct iio_chan_spec
+*iio_find_channel_from_si(struct iio_dev *indio_dev, int si);
+
+/**
* iio_device_register() - register a device with the IIO subsystem
* @indio_dev: Device structure filled by the device driver
**/
diff --git a/drivers/staging/iio/industrialio-core.c b/drivers/staging/iio/industrialio-core.c
index 55c0b48..3754b85 100644
--- a/drivers/staging/iio/industrialio-core.c
+++ b/drivers/staging/iio/industrialio-core.c
@@ -89,6 +89,17 @@ static const char * const iio_chan_info_postfix[] = {
= "filter_low_pass_3db_frequency",
};
+const struct iio_chan_spec
+*iio_find_channel_from_si(struct iio_dev *indio_dev, int si)
+{
+ int i;
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ if (indio_dev->channels[i].scan_index == si)
+ return &indio_dev->channels[i];
+ return NULL;
+}
+
/**
* struct iio_detected_event_list - list element for events that have occurred
* @list: linked list header
--
1.7.7.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index.
2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
2011-11-27 13:10 ` [PATCH 1/7] staging:iio:find iio channel from scan index util function Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
2011-11-27 13:10 ` [PATCH 3/7] staging:iio: add hook to allow core to perform scan related config Jonathan Cameron
` (4 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron
From: Jonathan Cameron <jic23@cam.ac.uk>
Basically avoids looking it up lots of times.
Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
drivers/staging/iio/buffer.h | 1 +
drivers/staging/iio/industrialio-buffer.c | 3 +++
2 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
index 9de581e..4b8f619 100644
--- a/drivers/staging/iio/buffer.h
+++ b/drivers/staging/iio/buffer.h
@@ -106,6 +106,7 @@ struct iio_buffer {
int scan_count;
long *scan_mask;
bool scan_timestamp;
+ unsigned scan_index_timestamp;
const struct iio_buffer_access_funcs *access;
const struct iio_buffer_setup_ops *setup_ops;
struct list_head scan_el_dev_attr_list;
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
index f757bb7..cae7922 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/staging/iio/industrialio-buffer.c
@@ -313,6 +313,9 @@ int iio_buffer_register(struct iio_dev *indio_dev,
if (ret < 0)
goto error_cleanup_dynamic;
attrcount += ret;
+ if (channels[i].type == IIO_TIMESTAMP)
+ buffer->scan_index_timestamp =
+ channels[i].scan_index;
}
if (indio_dev->masklength && buffer->scan_mask == NULL) {
buffer->scan_mask
--
1.7.7.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 3/7] staging:iio: add hook to allow core to perform scan related config.
2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
2011-11-27 13:10 ` [PATCH 1/7] staging:iio:find iio channel from scan index util function Jonathan Cameron
2011-11-27 13:10 ` [PATCH 2/7] staging:iio:buffer add a cache of the timestamp scan index Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
2011-11-27 13:10 ` [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general Jonathan Cameron
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
drivers/staging/iio/iio.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 95d6318..4fb8f2f 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -262,7 +262,8 @@ struct iio_info {
int val);
int (*validate_trigger)(struct iio_dev *indio_dev,
struct iio_trigger *trig);
-
+ int (*update_scan_mode)(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask);
};
/**
--
1.7.7.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general.
2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
` (2 preceding siblings ...)
2011-11-27 13:10 ` [PATCH 3/7] staging:iio: add hook to allow core to perform scan related config Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
2011-11-28 9:23 ` Lars-Peter Clausen
2011-11-27 13:10 ` [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer Jonathan Cameron
` (2 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron
Also introduces active_scan_mask storage to tell the core what is
really being currently captured from the device (different from
what is desired as often has bonus channels).
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
---
drivers/staging/iio/iio.h | 2 +
drivers/staging/iio/industrialio-buffer.c | 65 +++++++++++++++++-----------
2 files changed, 41 insertions(+), 26 deletions(-)
diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
index 4fb8f2f..c225542 100644
--- a/drivers/staging/iio/iio.h
+++ b/drivers/staging/iio/iio.h
@@ -280,6 +280,7 @@ struct iio_info {
* @available_scan_masks: [DRIVER] optional array of allowed bitmasks
* @masklength: [INTERN] the length of the mask established from
* channels
+ * @active_scan_mask: [INTERN] union of all scan masks requested by buffers
* @trig: [INTERN] current device trigger (buffer modes)
* @pollfunc: [DRIVER] function run on trigger being received
* @channels: [DRIVER] channel specification structure table
@@ -307,6 +308,7 @@ struct iio_dev {
unsigned long *available_scan_masks;
unsigned masklength;
+ unsigned long *active_scan_mask;
struct iio_trigger *trig;
struct iio_poll_func *pollfunc;
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
index cae7922..fb14e37 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/staging/iio/industrialio-buffer.c
@@ -533,32 +533,6 @@ ssize_t iio_buffer_show_enable(struct device *dev,
}
EXPORT_SYMBOL(iio_buffer_show_enable);
-int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
-{
- struct iio_buffer *buffer = indio_dev->buffer;
- size_t size;
- dev_dbg(&indio_dev->dev, "%s\n", __func__);
- /* Check if there are any scan elements enabled, if not fail*/
- if (!(buffer->scan_count || buffer->scan_timestamp))
- return -EINVAL;
- if (buffer->scan_timestamp)
- if (buffer->scan_count)
- /* Timestamp (aligned to s64) and data */
- size = (((buffer->scan_count * buffer->bpe)
- + sizeof(s64) - 1)
- & ~(sizeof(s64) - 1))
- + sizeof(s64);
- else /* Timestamp only */
- size = sizeof(s64);
- else /* Data only */
- size = buffer->scan_count * buffer->bpe;
- buffer->access->set_bytes_per_datum(buffer, size);
-
- return 0;
-}
-EXPORT_SYMBOL(iio_sw_buffer_preenable);
-
-
/* note NULL used as error indicator as it doesn't make sense. */
static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
unsigned int masklength,
@@ -574,6 +548,45 @@ static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
return NULL;
}
+int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct iio_buffer *buffer = indio_dev->buffer;
+ const struct iio_chan_spec *ch;
+ unsigned bytes = 0;
+ int length, i;
+ dev_dbg(&indio_dev->dev, "%s\n", __func__);
+
+ /* How much space will the demuxed element take? */
+ for_each_set_bit(i, buffer->scan_mask,
+ indio_dev->masklength) {
+ ch = iio_find_channel_from_si(indio_dev, i);
+ length = ch->scan_type.storagebits/8;
+ if (bytes % length)
+ bytes += length - bytes % length;
+ bytes += length;
+ }
+ if (buffer->scan_timestamp) {
+ ch = iio_find_channel_from_si(indio_dev,
+ buffer->scan_index_timestamp);
+ length = ch->scan_type.storagebits/8;
+ if (bytes % length)
+ bytes += length - bytes % length;
+ bytes += length;
+ }
+ buffer->access->set_bytes_per_datum(buffer, bytes);
+
+ /* What scan mask do we actually have ?*/
+ if (indio_dev->available_scan_masks)
+ indio_dev->active_scan_mask =
+ iio_scan_mask_match(indio_dev->available_scan_masks,
+ indio_dev->masklength,
+ buffer->scan_mask);
+ else
+ indio_dev->active_scan_mask = buffer->scan_mask;
+ return 0;
+}
+EXPORT_SYMBOL(iio_sw_buffer_preenable);
+
/**
* iio_scan_mask_set() - set particular bit in the scan mask
* @buffer: the buffer whose scan mask we are interested in
--
1.7.7.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general.
2011-11-27 13:10 ` [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general Jonathan Cameron
@ 2011-11-28 9:23 ` Lars-Peter Clausen
2011-12-01 21:17 ` Jonathan Cameron
0 siblings, 1 reply; 16+ messages in thread
From: Lars-Peter Clausen @ 2011-11-28 9:23 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Michael.Hennerich
On 11/27/2011 02:10 PM, Jonathan Cameron wrote:
> Also introduces active_scan_mask storage to tell the core what is
> really being currently captured from the device (different from
> what is desired as often has bonus channels).
>
> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
> ---
> drivers/staging/iio/iio.h | 2 +
> drivers/staging/iio/industrialio-buffer.c | 65 +++++++++++++++++-----------
> 2 files changed, 41 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/staging/iio/iio.h b/drivers/staging/iio/iio.h
> index 4fb8f2f..c225542 100644
> --- a/drivers/staging/iio/iio.h
> +++ b/drivers/staging/iio/iio.h
> @@ -280,6 +280,7 @@ struct iio_info {
> * @available_scan_masks: [DRIVER] optional array of allowed bitmasks
> * @masklength: [INTERN] the length of the mask established from
> * channels
> + * @active_scan_mask: [INTERN] union of all scan masks requested by buffers
> * @trig: [INTERN] current device trigger (buffer modes)
> * @pollfunc: [DRIVER] function run on trigger being received
> * @channels: [DRIVER] channel specification structure table
> @@ -307,6 +308,7 @@ struct iio_dev {
>
> unsigned long *available_scan_masks;
> unsigned masklength;
> + unsigned long *active_scan_mask;
> struct iio_trigger *trig;
> struct iio_poll_func *pollfunc;
>
> diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
> index cae7922..fb14e37 100644
> --- a/drivers/staging/iio/industrialio-buffer.c
> +++ b/drivers/staging/iio/industrialio-buffer.c
> @@ -533,32 +533,6 @@ ssize_t iio_buffer_show_enable(struct device *dev,
> }
> EXPORT_SYMBOL(iio_buffer_show_enable);
>
> -int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
> -{
> - struct iio_buffer *buffer = indio_dev->buffer;
> - size_t size;
> - dev_dbg(&indio_dev->dev, "%s\n", __func__);
> - /* Check if there are any scan elements enabled, if not fail*/
> - if (!(buffer->scan_count || buffer->scan_timestamp))
> - return -EINVAL;
> - if (buffer->scan_timestamp)
> - if (buffer->scan_count)
> - /* Timestamp (aligned to s64) and data */
> - size = (((buffer->scan_count * buffer->bpe)
> - + sizeof(s64) - 1)
> - & ~(sizeof(s64) - 1))
> - + sizeof(s64);
> - else /* Timestamp only */
> - size = sizeof(s64);
> - else /* Data only */
> - size = buffer->scan_count * buffer->bpe;
> - buffer->access->set_bytes_per_datum(buffer, size);
> -
> - return 0;
> -}
> -EXPORT_SYMBOL(iio_sw_buffer_preenable);
> -
> -
> /* note NULL used as error indicator as it doesn't make sense. */
> static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
> unsigned int masklength,
> @@ -574,6 +548,45 @@ static unsigned long *iio_scan_mask_match(unsigned long *av_masks,
> return NULL;
> }
>
> +int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
> +{
> + struct iio_buffer *buffer = indio_dev->buffer;
> + const struct iio_chan_spec *ch;
> + unsigned bytes = 0;
> + int length, i;
> + dev_dbg(&indio_dev->dev, "%s\n", __func__);
> +
> + /* How much space will the demuxed element take? */
> + for_each_set_bit(i, buffer->scan_mask,
> + indio_dev->masklength) {
> + ch = iio_find_channel_from_si(indio_dev, i);
> + length = ch->scan_type.storagebits/8;
> + if (bytes % length)
> + bytes += length - bytes % length;
bytes = ALIGN(bytes, length); would probably make it more obvious what is
going on here.
> + bytes += length;
> + }
> + if (buffer->scan_timestamp) {
> + ch = iio_find_channel_from_si(indio_dev,
> + buffer->scan_index_timestamp);
> + length = ch->scan_type.storagebits/8;
> + if (bytes % length)
> + bytes += length - bytes % length;
> + bytes += length;
> + }
> + buffer->access->set_bytes_per_datum(buffer, bytes);
> +
> + /* What scan mask do we actually have ?*/
> + if (indio_dev->available_scan_masks)
> + indio_dev->active_scan_mask =
> + iio_scan_mask_match(indio_dev->available_scan_masks,
> + indio_dev->masklength,
> + buffer->scan_mask);
> + else
> + indio_dev->active_scan_mask = buffer->scan_mask;
> + return 0;
> +}
> +EXPORT_SYMBOL(iio_sw_buffer_preenable);
> +
> /**
> * iio_scan_mask_set() - set particular bit in the scan mask
> * @buffer: the buffer whose scan mask we are interested in
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general.
2011-11-28 9:23 ` Lars-Peter Clausen
@ 2011-12-01 21:17 ` Jonathan Cameron
0 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2011-12-01 21:17 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: linux-iio, Michael.Hennerich
...
>> +int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
>> +{
>> + struct iio_buffer *buffer = indio_dev->buffer;
>> + const struct iio_chan_spec *ch;
>> + unsigned bytes = 0;
>> + int length, i;
>> + dev_dbg(&indio_dev->dev, "%s\n", __func__);
>> +
>> + /* How much space will the demuxed element take? */
>> + for_each_set_bit(i, buffer->scan_mask,
>> + indio_dev->masklength) {
>> + ch = iio_find_channel_from_si(indio_dev, i);
>> + length = ch->scan_type.storagebits/8;
>> + if (bytes % length)
>> + bytes += length - bytes % length;
>
> bytes = ALIGN(bytes, length); would probably make it more obvious what is
> going on here.
Good idea. Thanks.
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer
2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
` (3 preceding siblings ...)
2011-11-27 13:10 ` [PATCH 4/7] staging:iio: make iio_sw_buffer_preenable much more general Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
2011-11-28 9:39 ` Lars-Peter Clausen
2011-11-27 13:10 ` [PATCH 6/7] staging:iio:adc:max1363 use new demuxing support Jonathan Cameron
2011-11-27 13:10 ` [PATCH 7/7] staging:iio:adc:max1363 correctly set channels as big endian Jonathan Cameron
6 siblings, 1 reply; 16+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron
From: Jonathan Cameron <jic23@cam.ac.uk>
This gives you only what you ask for which is handy
for some devices with weird scan combinations.
Routes all data flow through a core utility function.
That and this demuxing support will be needed to do
demuxing to multiple destinations in kernel.
Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
drivers/staging/iio/buffer.h | 15 +++
drivers/staging/iio/industrialio-buffer.c | 148 ++++++++++++++++++++++++++++-
2 files changed, 159 insertions(+), 4 deletions(-)
diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
index 4b8f619..5282441 100644
--- a/drivers/staging/iio/buffer.h
+++ b/drivers/staging/iio/buffer.h
@@ -95,6 +95,8 @@ struct iio_buffer_setup_ops {
* @access: [DRIVER] buffer access functions associated with the
* implementation.
* @flags: [INTERN] file ops related flags including busy flag.
+ * @demux_list: [INTERN] list of operations required to demux the scan.
+ * @demux_bounce: [INTERN] buffer for doing gather from incoming scan.
**/
struct iio_buffer {
struct iio_dev *indio_dev;
@@ -115,6 +117,8 @@ struct iio_buffer {
bool stufftoread;
unsigned long flags;
const struct attribute_group *attrs;
+ struct list_head demux_list;
+ unsigned char *demux_bounce;
};
/**
@@ -153,6 +157,17 @@ int iio_scan_mask_set(struct iio_buffer *buffer, int bit);
container_of(d, struct iio_buffer, dev)
/**
+ * iio_push_to_buffer() - push to a registered buffer.
+ * @buffer: IIO buffer structure for device
+ * @scan: Full scan.
+ * @timestamp:
+ */
+int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
+ s64 timestamp);
+
+int iio_update_demux(struct iio_dev *indio_dev);
+
+/**
* iio_buffer_register() - register the buffer with IIO core
* @indio_dev: device with the buffer to be registered
**/
diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
index fb14e37..352f9f1 100644
--- a/drivers/staging/iio/industrialio-buffer.c
+++ b/drivers/staging/iio/industrialio-buffer.c
@@ -87,6 +87,7 @@ void iio_chrdev_buffer_release(struct iio_dev *indio_dev)
void iio_buffer_init(struct iio_buffer *buffer, struct iio_dev *indio_dev)
{
+ INIT_LIST_HEAD(&buffer->demux_list);
buffer->indio_dev = indio_dev;
init_waitqueue_head(&buffer->pollq);
}
@@ -128,10 +129,9 @@ static ssize_t iio_scan_el_show(struct device *dev,
int ret;
struct iio_dev *indio_dev = dev_get_drvdata(dev);
- ret = iio_scan_mask_query(indio_dev->buffer,
- to_iio_dev_attr(attr)->address);
- if (ret < 0)
- return ret;
+ ret = test_bit(to_iio_dev_attr(attr)->address,
+ indio_dev->buffer->scan_mask);
+
return sprintf(buf, "%d\n", ret);
}
@@ -583,6 +583,12 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
buffer->scan_mask);
else
indio_dev->active_scan_mask = buffer->scan_mask;
+ iio_update_demux(indio_dev);
+
+ if (indio_dev->info->update_scan_mode)
+ return indio_dev->info
+ ->update_scan_mode(indio_dev,
+ indio_dev->active_scan_mask);
return 0;
}
EXPORT_SYMBOL(iio_sw_buffer_preenable);
@@ -652,3 +658,137 @@ int iio_scan_mask_query(struct iio_buffer *buffer, int bit)
return test_bit(bit, mask);
};
EXPORT_SYMBOL_GPL(iio_scan_mask_query);
+
+/**
+ * struct iio_demux_table() - table describing demux memcpy ops
+ * @from: index to copy from
+ * @to: index to copy to
+ * @length: how many bytes to copy
+ * @l: list head used for management
+ */
+struct iio_demux_table {
+ unsigned from;
+ unsigned to;
+ unsigned length;
+ struct list_head l;
+};
+
+static unsigned char *iio_demux(struct iio_buffer *buffer,
+ unsigned char *datain)
+{
+ struct iio_demux_table *t;
+
+ if (list_empty(&buffer->demux_list))
+ return datain;
+ list_for_each_entry(t, &buffer->demux_list, l)
+ memcpy(buffer->demux_bounce + t->to,
+ datain + t->from, t->length);
+
+ return buffer->demux_bounce;
+}
+
+int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
+ s64 timestamp)
+{
+ unsigned char *dataout = iio_demux(buffer, data);
+
+ return buffer->access->store_to(buffer, dataout, timestamp);
+}
+EXPORT_SYMBOL_GPL(iio_push_to_buffer);
+
+int iio_update_demux(struct iio_dev *indio_dev)
+{
+ const struct iio_chan_spec *ch;
+ struct iio_buffer *buffer = indio_dev->buffer;
+ int ret, in_ind = -1, out_ind, length;
+ unsigned in_loc = 0, out_loc = 0;
+ struct iio_demux_table *p, *q;
+
+ /* Clear out any old demux */
+ list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
+ list_del(&p->l);
+ kfree(p);
+ }
+ kfree(buffer->demux_bounce);
+ buffer->demux_bounce = NULL;
+
+ /* First work out which scan mode we will actually have */
+ if (bitmap_equal(indio_dev->active_scan_mask,
+ buffer->scan_mask,
+ indio_dev->masklength))
+ return 0;
+
+ out_ind = find_first_bit(buffer->scan_mask, indio_dev->masklength);
+ /* Now we have the two masks, work from least sig and build up sizes */
+ while (out_ind != indio_dev->masklength) {
+ in_ind = find_next_bit(indio_dev->active_scan_mask,
+ indio_dev->masklength,
+ in_ind + 1);
+ while (in_ind != out_ind) {
+ in_ind = find_next_bit(indio_dev->active_scan_mask,
+ indio_dev->masklength,
+ in_ind + 1);
+ ch = iio_find_channel_from_si(indio_dev, in_ind);
+ length = ch->scan_type.storagebits/8;
+ /* Make sure we are aligned */
+ in_loc += length;
+ if (in_loc % length)
+ in_loc += length - in_loc % length;
+ }
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL) {
+ ret = -ENOMEM;
+ goto error_clear_mux_table;
+ }
+ ch = iio_find_channel_from_si(indio_dev, in_ind);
+ length = ch->scan_type.storagebits/8;
+ if (out_loc % length)
+ out_loc += length - out_loc % length;
+ if (in_loc % length)
+ in_loc += length - in_loc % length;
+ p->from = in_loc;
+ p->to = out_loc;
+ p->length = length;
+ list_add_tail(&p->l, &buffer->demux_list);
+ out_loc += length;
+ in_loc += length;
+ out_ind = find_next_bit(buffer->scan_mask,
+ indio_dev->masklength,
+ out_ind + 1);
+ }
+ /* Relies on scan_timestamp being last */
+ if (buffer->scan_timestamp) {
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (p == NULL) {
+ ret = -ENOMEM;
+ goto error_clear_mux_table;
+ }
+ ch = iio_find_channel_from_si(indio_dev,
+ buffer->scan_index_timestamp);
+ length = ch->scan_type.storagebits/8;
+ if (out_loc % length)
+ out_loc += length - out_loc % length;
+ if (in_loc % length)
+ in_loc += length - in_loc % length;
+ p->from = in_loc;
+ p->to = out_loc;
+ p->length = length;
+ list_add_tail(&p->l, &buffer->demux_list);
+ out_loc += length;
+ in_loc += length;
+ }
+ buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
+ if (buffer->demux_bounce == NULL) {
+ ret = -ENOMEM;
+ goto error_clear_mux_table;
+ }
+ return 0;
+
+error_clear_mux_table:
+ list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
+ list_del(&p->l);
+ kfree(p);
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(iio_update_demux);
--
1.7.7.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer
2011-11-27 13:10 ` [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer Jonathan Cameron
@ 2011-11-28 9:39 ` Lars-Peter Clausen
2011-12-01 21:34 ` Jonathan Cameron
0 siblings, 1 reply; 16+ messages in thread
From: Lars-Peter Clausen @ 2011-11-28 9:39 UTC (permalink / raw)
To: Jonathan Cameron; +Cc: linux-iio, Michael.Hennerich, Jonathan Cameron
On 11/27/2011 02:10 PM, Jonathan Cameron wrote:
> From: Jonathan Cameron <jic23@cam.ac.uk>
>
> This gives you only what you ask for which is handy
> for some devices with weird scan combinations.
>
> Routes all data flow through a core utility function.
> That and this demuxing support will be needed to do
> demuxing to multiple destinations in kernel.
>
> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
> ---
> drivers/staging/iio/buffer.h | 15 +++
> drivers/staging/iio/industrialio-buffer.c | 148 ++++++++++++++++++++++++++++-
> 2 files changed, 159 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
> index 4b8f619..5282441 100644
> --- a/drivers/staging/iio/buffer.h
> +++ b/drivers/staging/iio/buffer.h
> @@ -95,6 +95,8 @@ struct iio_buffer_setup_ops {
> * @access: [DRIVER] buffer access functions associated with the
> * implementation.
> * @flags: [INTERN] file ops related flags including busy flag.
> + * @demux_list: [INTERN] list of operations required to demux the scan.
> + * @demux_bounce: [INTERN] buffer for doing gather from incoming scan.
> **/
> struct iio_buffer {
> struct iio_dev *indio_dev;
> @@ -115,6 +117,8 @@ struct iio_buffer {
> bool stufftoread;
> unsigned long flags;
> const struct attribute_group *attrs;
> + struct list_head demux_list;
> + unsigned char *demux_bounce;
> };
>
> /**
> @@ -153,6 +157,17 @@ int iio_scan_mask_set(struct iio_buffer *buffer, int bit);
> container_of(d, struct iio_buffer, dev)
>
> /**
> + * iio_push_to_buffer() - push to a registered buffer.
> + * @buffer: IIO buffer structure for device
> + * @scan: Full scan.
> + * @timestamp:
> + */
> +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
> + s64 timestamp);
> +
> +int iio_update_demux(struct iio_dev *indio_dev);
> +
> +/**
> * iio_buffer_register() - register the buffer with IIO core
> * @indio_dev: device with the buffer to be registered
> **/
> diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
> index fb14e37..352f9f1 100644
> --- a/drivers/staging/iio/industrialio-buffer.c
> +++ b/drivers/staging/iio/industrialio-buffer.c
> @@ -87,6 +87,7 @@ void iio_chrdev_buffer_release(struct iio_dev *indio_dev)
>
> void iio_buffer_init(struct iio_buffer *buffer, struct iio_dev *indio_dev)
> {
> + INIT_LIST_HEAD(&buffer->demux_list);
> buffer->indio_dev = indio_dev;
> init_waitqueue_head(&buffer->pollq);
> }
> @@ -128,10 +129,9 @@ static ssize_t iio_scan_el_show(struct device *dev,
> int ret;
> struct iio_dev *indio_dev = dev_get_drvdata(dev);
>
> - ret = iio_scan_mask_query(indio_dev->buffer,
> - to_iio_dev_attr(attr)->address);
> - if (ret < 0)
> - return ret;
> + ret = test_bit(to_iio_dev_attr(attr)->address,
> + indio_dev->buffer->scan_mask);
> +
> return sprintf(buf, "%d\n", ret);
> }
>
> @@ -583,6 +583,12 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
> buffer->scan_mask);
> else
> indio_dev->active_scan_mask = buffer->scan_mask;
> + iio_update_demux(indio_dev);
> +
> + if (indio_dev->info->update_scan_mode)
> + return indio_dev->info
> + ->update_scan_mode(indio_dev,
> + indio_dev->active_scan_mask);
> return 0;
> }
> EXPORT_SYMBOL(iio_sw_buffer_preenable);
> @@ -652,3 +658,137 @@ int iio_scan_mask_query(struct iio_buffer *buffer, int bit)
> return test_bit(bit, mask);
> };
> EXPORT_SYMBOL_GPL(iio_scan_mask_query);
> +
> +/**
> + * struct iio_demux_table() - table describing demux memcpy ops
> + * @from: index to copy from
> + * @to: index to copy to
> + * @length: how many bytes to copy
> + * @l: list head used for management
> + */
> +struct iio_demux_table {
> + unsigned from;
> + unsigned to;
> + unsigned length;
> + struct list_head l;
> +};
> +
> +static unsigned char *iio_demux(struct iio_buffer *buffer,
> + unsigned char *datain)
> +{
> + struct iio_demux_table *t;
> +
> + if (list_empty(&buffer->demux_list))
> + return datain;
> + list_for_each_entry(t, &buffer->demux_list, l)
> + memcpy(buffer->demux_bounce + t->to,
> + datain + t->from, t->length);
> +
> + return buffer->demux_bounce;
> +}
> +
> +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
> + s64 timestamp)
> +{
> + unsigned char *dataout = iio_demux(buffer, data);
> +
> + return buffer->access->store_to(buffer, dataout, timestamp);
> +}
> +EXPORT_SYMBOL_GPL(iio_push_to_buffer);
I wonder if we want to integrate the demuxing into the store_to callbacks of
the buffer, this would avoid the need for the bounce buffer and reduce the
number of memcpys. But maybe we can just add it later.
> +
> +int iio_update_demux(struct iio_dev *indio_dev)
> +{
> + const struct iio_chan_spec *ch;
> + struct iio_buffer *buffer = indio_dev->buffer;
> + int ret, in_ind = -1, out_ind, length;
> + unsigned in_loc = 0, out_loc = 0;
> + struct iio_demux_table *p, *q;
> +
> + /* Clear out any old demux */
> + list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
> + list_del(&p->l);
> + kfree(p);
> + }
> + kfree(buffer->demux_bounce);
> + buffer->demux_bounce = NULL;
> +
> + /* First work out which scan mode we will actually have */
> + if (bitmap_equal(indio_dev->active_scan_mask,
> + buffer->scan_mask,
> + indio_dev->masklength))
> + return 0;
> +
> + out_ind = find_first_bit(buffer->scan_mask, indio_dev->masklength);
> + /* Now we have the two masks, work from least sig and build up sizes */
> + while (out_ind != indio_dev->masklength) {
This looks a bit like an open-coded for_each_set_bit
> + in_ind = find_next_bit(indio_dev->active_scan_mask,
> + indio_dev->masklength,
> + in_ind + 1);
> + while (in_ind != out_ind) {
> + in_ind = find_next_bit(indio_dev->active_scan_mask,
> + indio_dev->masklength,
> + in_ind + 1);
same here for_each_set_bit(in_ind, indio->active_scan_mask, out_ind)
> + ch = iio_find_channel_from_si(indio_dev, in_ind);
> + length = ch->scan_type.storagebits/8;
> + /* Make sure we are aligned */
> + in_loc += length;
> + if (in_loc % length)
> + in_loc += length - in_loc % length;
> + }
> + p = kmalloc(sizeof(*p), GFP_KERNEL);
> + if (p == NULL) {
> + ret = -ENOMEM;
> + goto error_clear_mux_table;
> + }
> + ch = iio_find_channel_from_si(indio_dev, in_ind);
> + length = ch->scan_type.storagebits/8;
> + if (out_loc % length)
> + out_loc += length - out_loc % length;
> + if (in_loc % length)
> + in_loc += length - in_loc % length;
> + p->from = in_loc;
> + p->to = out_loc;
> + p->length = length;
> + list_add_tail(&p->l, &buffer->demux_list);
> + out_loc += length;
> + in_loc += length;
> + out_ind = find_next_bit(buffer->scan_mask,
> + indio_dev->masklength,
> + out_ind + 1);
> + }
> + /* Relies on scan_timestamp being last */
> + if (buffer->scan_timestamp) {
> + p = kmalloc(sizeof(*p), GFP_KERNEL);
> + if (p == NULL) {
> + ret = -ENOMEM;
> + goto error_clear_mux_table;
> + }
> + ch = iio_find_channel_from_si(indio_dev,
> + buffer->scan_index_timestamp);
> + length = ch->scan_type.storagebits/8;
> + if (out_loc % length)
> + out_loc += length - out_loc % length;
> + if (in_loc % length)
> + in_loc += length - in_loc % length;
> + p->from = in_loc;
> + p->to = out_loc;
> + p->length = length;
> + list_add_tail(&p->l, &buffer->demux_list);
> + out_loc += length;
> + in_loc += length;
> + }
> + buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
> + if (buffer->demux_bounce == NULL) {
> + ret = -ENOMEM;
> + goto error_clear_mux_table;
> + }
> + return 0;
> +
> +error_clear_mux_table:
> + list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
> + list_del(&p->l);
> + kfree(p);
> + }
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(iio_update_demux);
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer
2011-11-28 9:39 ` Lars-Peter Clausen
@ 2011-12-01 21:34 ` Jonathan Cameron
0 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2011-12-01 21:34 UTC (permalink / raw)
To: Lars-Peter Clausen; +Cc: linux-iio, Michael.Hennerich, Jonathan Cameron
On 11/28/2011 09:39 AM, Lars-Peter Clausen wrote:
> On 11/27/2011 02:10 PM, Jonathan Cameron wrote:
>> From: Jonathan Cameron <jic23@cam.ac.uk>
>>
>> This gives you only what you ask for which is handy
>> for some devices with weird scan combinations.
>>
>> Routes all data flow through a core utility function.
>> That and this demuxing support will be needed to do
>> demuxing to multiple destinations in kernel.
>>
>> Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
>> ---
>> drivers/staging/iio/buffer.h | 15 +++
>> drivers/staging/iio/industrialio-buffer.c | 148 ++++++++++++++++++++++++++++-
>> 2 files changed, 159 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/staging/iio/buffer.h b/drivers/staging/iio/buffer.h
>> index 4b8f619..5282441 100644
>> --- a/drivers/staging/iio/buffer.h
>> +++ b/drivers/staging/iio/buffer.h
>> @@ -95,6 +95,8 @@ struct iio_buffer_setup_ops {
>> * @access: [DRIVER] buffer access functions associated with the
>> * implementation.
>> * @flags: [INTERN] file ops related flags including busy flag.
>> + * @demux_list: [INTERN] list of operations required to demux the scan.
>> + * @demux_bounce: [INTERN] buffer for doing gather from incoming scan.
>> **/
>> struct iio_buffer {
>> struct iio_dev *indio_dev;
>> @@ -115,6 +117,8 @@ struct iio_buffer {
>> bool stufftoread;
>> unsigned long flags;
>> const struct attribute_group *attrs;
>> + struct list_head demux_list;
>> + unsigned char *demux_bounce;
>> };
>>
>> /**
>> @@ -153,6 +157,17 @@ int iio_scan_mask_set(struct iio_buffer *buffer, int bit);
>> container_of(d, struct iio_buffer, dev)
>>
>> /**
>> + * iio_push_to_buffer() - push to a registered buffer.
>> + * @buffer: IIO buffer structure for device
>> + * @scan: Full scan.
>> + * @timestamp:
>> + */
>> +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
>> + s64 timestamp);
>> +
>> +int iio_update_demux(struct iio_dev *indio_dev);
>> +
>> +/**
>> * iio_buffer_register() - register the buffer with IIO core
>> * @indio_dev: device with the buffer to be registered
>> **/
>> diff --git a/drivers/staging/iio/industrialio-buffer.c b/drivers/staging/iio/industrialio-buffer.c
>> index fb14e37..352f9f1 100644
>> --- a/drivers/staging/iio/industrialio-buffer.c
>> +++ b/drivers/staging/iio/industrialio-buffer.c
>> @@ -87,6 +87,7 @@ void iio_chrdev_buffer_release(struct iio_dev *indio_dev)
>>
>> void iio_buffer_init(struct iio_buffer *buffer, struct iio_dev *indio_dev)
>> {
>> + INIT_LIST_HEAD(&buffer->demux_list);
>> buffer->indio_dev = indio_dev;
>> init_waitqueue_head(&buffer->pollq);
>> }
>> @@ -128,10 +129,9 @@ static ssize_t iio_scan_el_show(struct device *dev,
>> int ret;
>> struct iio_dev *indio_dev = dev_get_drvdata(dev);
>>
>> - ret = iio_scan_mask_query(indio_dev->buffer,
>> - to_iio_dev_attr(attr)->address);
>> - if (ret < 0)
>> - return ret;
>> + ret = test_bit(to_iio_dev_attr(attr)->address,
>> + indio_dev->buffer->scan_mask);
>> +
>> return sprintf(buf, "%d\n", ret);
>> }
>>
>> @@ -583,6 +583,12 @@ int iio_sw_buffer_preenable(struct iio_dev *indio_dev)
>> buffer->scan_mask);
>> else
>> indio_dev->active_scan_mask = buffer->scan_mask;
>> + iio_update_demux(indio_dev);
>> +
>> + if (indio_dev->info->update_scan_mode)
>> + return indio_dev->info
>> + ->update_scan_mode(indio_dev,
>> + indio_dev->active_scan_mask);
>> return 0;
>> }
>> EXPORT_SYMBOL(iio_sw_buffer_preenable);
>> @@ -652,3 +658,137 @@ int iio_scan_mask_query(struct iio_buffer *buffer, int bit)
>> return test_bit(bit, mask);
>> };
>> EXPORT_SYMBOL_GPL(iio_scan_mask_query);
>> +
>> +/**
>> + * struct iio_demux_table() - table describing demux memcpy ops
>> + * @from: index to copy from
>> + * @to: index to copy to
>> + * @length: how many bytes to copy
>> + * @l: list head used for management
>> + */
>> +struct iio_demux_table {
>> + unsigned from;
>> + unsigned to;
>> + unsigned length;
>> + struct list_head l;
>> +};
>> +
>> +static unsigned char *iio_demux(struct iio_buffer *buffer,
>> + unsigned char *datain)
>> +{
>> + struct iio_demux_table *t;
>> +
>> + if (list_empty(&buffer->demux_list))
>> + return datain;
>> + list_for_each_entry(t, &buffer->demux_list, l)
>> + memcpy(buffer->demux_bounce + t->to,
>> + datain + t->from, t->length);
>> +
>> + return buffer->demux_bounce;
>> +}
>> +
>> +int iio_push_to_buffer(struct iio_buffer *buffer, unsigned char *data,
>> + s64 timestamp)
>> +{
>> + unsigned char *dataout = iio_demux(buffer, data);
>> +
>> + return buffer->access->store_to(buffer, dataout, timestamp);
>> +}
>> +EXPORT_SYMBOL_GPL(iio_push_to_buffer);
>
> I wonder if we want to integrate the demuxing into the store_to callbacks of
> the buffer, this would avoid the need for the bounce buffer and reduce the
> number of memcpys. But maybe we can just add it later.
I'd rather do this later than mess too much with the buffers in this
patch. I think we may want to do it the other way around and have
buffers offer a reserve_space and done_with_space pair of callbacks
where the first saves the room and passes back a pointer. Then demux
can occur directly into there rather than the bounce buffer.
Still, same effective result! So not now in my view.
>
> This looks a bit like an open-coded for_each_set_bit
Indeed. Will clean that up.
>
>> + in_ind = find_next_bit(indio_dev->active_scan_mask,
>> + indio_dev->masklength,
>> + in_ind + 1);
>> + while (in_ind != out_ind) {
>> + in_ind = find_next_bit(indio_dev->active_scan_mask,
>> + indio_dev->masklength,
>> + in_ind + 1);
>
> same here for_each_set_bit(in_ind, indio->active_scan_mask, out_ind)
close but not quite. It only counts bits above the previous in_ind
(which is also the previous out_ind). Need a for_each_set_bit_after
function for this.
>
>> + ch = iio_find_channel_from_si(indio_dev, in_ind);
>> + length = ch->scan_type.storagebits/8;
>> + /* Make sure we are aligned */
>> + in_loc += length;
>> + if (in_loc % length)
>> + in_loc += length - in_loc % length;
>> + }
>> + p = kmalloc(sizeof(*p), GFP_KERNEL);
>> + if (p == NULL) {
>> + ret = -ENOMEM;
>> + goto error_clear_mux_table;
>> + }
>> + ch = iio_find_channel_from_si(indio_dev, in_ind);
>> + length = ch->scan_type.storagebits/8;
>> + if (out_loc % length)
>> + out_loc += length - out_loc % length;
>> + if (in_loc % length)
>> + in_loc += length - in_loc % length;
>> + p->from = in_loc;
>> + p->to = out_loc;
>> + p->length = length;
>> + list_add_tail(&p->l, &buffer->demux_list);
>> + out_loc += length;
>> + in_loc += length;
>> + out_ind = find_next_bit(buffer->scan_mask,
>> + indio_dev->masklength,
>> + out_ind + 1);
>> + }
>> + /* Relies on scan_timestamp being last */
>> + if (buffer->scan_timestamp) {
>> + p = kmalloc(sizeof(*p), GFP_KERNEL);
>> + if (p == NULL) {
>> + ret = -ENOMEM;
>> + goto error_clear_mux_table;
>> + }
>> + ch = iio_find_channel_from_si(indio_dev,
>> + buffer->scan_index_timestamp);
>> + length = ch->scan_type.storagebits/8;
>> + if (out_loc % length)
>> + out_loc += length - out_loc % length;
>> + if (in_loc % length)
>> + in_loc += length - in_loc % length;
>> + p->from = in_loc;
>> + p->to = out_loc;
>> + p->length = length;
>> + list_add_tail(&p->l, &buffer->demux_list);
>> + out_loc += length;
>> + in_loc += length;
>> + }
>> + buffer->demux_bounce = kzalloc(out_loc, GFP_KERNEL);
>> + if (buffer->demux_bounce == NULL) {
>> + ret = -ENOMEM;
>> + goto error_clear_mux_table;
>> + }
>> + return 0;
>> +
>> +error_clear_mux_table:
>> + list_for_each_entry_safe(p, q, &buffer->demux_list, l) {
>> + list_del(&p->l);
>> + kfree(p);
>> + }
>> + return ret;
>> +}
>> +EXPORT_SYMBOL_GPL(iio_update_demux);
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-iio" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 6/7] staging:iio:adc:max1363 use new demuxing support.
2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
` (4 preceding siblings ...)
2011-11-27 13:10 ` [PATCH 5/7] staging:iio: add demux optionally to path from device to buffer Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
2011-11-27 13:10 ` [PATCH 7/7] staging:iio:adc:max1363 correctly set channels as big endian Jonathan Cameron
6 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron
From: Jonathan Cameron <jic23@cam.ac.uk>
Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
drivers/staging/iio/adc/max1363.h | 11 +++++-
drivers/staging/iio/adc/max1363_core.c | 4 ++-
drivers/staging/iio/adc/max1363_ring.c | 51 +++++++++-----------------------
3 files changed, 26 insertions(+), 40 deletions(-)
diff --git a/drivers/staging/iio/adc/max1363.h b/drivers/staging/iio/adc/max1363.h
index cbcb08a..fb52783 100644
--- a/drivers/staging/iio/adc/max1363.h
+++ b/drivers/staging/iio/adc/max1363.h
@@ -146,18 +146,25 @@ struct max1363_state {
};
const struct max1363_mode
-*max1363_match_mode(unsigned long *mask, const struct max1363_chip_info *ci);
+*max1363_match_mode(const unsigned long *mask,
+ const struct max1363_chip_info *ci);
int max1363_set_scan_mode(struct max1363_state *st);
#ifdef CONFIG_MAX1363_RING_BUFFER
-
+int max1363_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask);
int max1363_single_channel_from_ring(const long *mask,
struct max1363_state *st);
int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev);
void max1363_ring_cleanup(struct iio_dev *indio_dev);
#else /* CONFIG_MAX1363_RING_BUFFER */
+int max1363_update_scan_mode(struct iio_dev *indio_dev,
+ const long *scan_mask)
+{
+ return 0;
+}
int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
{
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index c3e28e1..7e078fc 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -148,7 +148,8 @@ static const struct max1363_mode max1363_mode_table[] = {
};
const struct max1363_mode
-*max1363_match_mode(unsigned long *mask, const struct max1363_chip_info *ci)
+*max1363_match_mode(const unsigned long *mask,
+const struct max1363_chip_info *ci)
{
int i;
if (mask)
@@ -834,6 +835,7 @@ static const struct iio_info max1363_info = {
.read_event_config = &max1363_read_event_config,
.write_event_config = &max1363_write_event_config,
.read_raw = &max1363_read_raw,
+ .update_scan_mode = &max1363_update_scan_mode,
.driver_module = THIS_MODULE,
.event_attrs = &max1363_event_attribute_group,
};
diff --git a/drivers/staging/iio/adc/max1363_ring.c b/drivers/staging/iio/adc/max1363_ring.c
index 3c5e199..19977a6 100644
--- a/drivers/staging/iio/adc/max1363_ring.c
+++ b/drivers/staging/iio/adc/max1363_ring.c
@@ -57,46 +57,19 @@ error_ret:
return ret;
}
-
-/**
- * max1363_ring_preenable() - setup the parameters of the ring before enabling
- *
- * The complex nature of the setting of the nuber of bytes per datum is due
- * to this driver currently ensuring that the timestamp is stored at an 8
- * byte boundary.
- **/
-static int max1363_ring_preenable(struct iio_dev *indio_dev)
+int max1363_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
{
struct max1363_state *st = iio_priv(indio_dev);
- struct iio_buffer *ring = indio_dev->buffer;
- size_t d_size = 0;
- unsigned long numvals;
/*
* Need to figure out the current mode based upon the requested
* scan mask in iio_dev
*/
- st->current_mode = max1363_match_mode(ring->scan_mask,
- st->chip_info);
+ st->current_mode = max1363_match_mode(scan_mask, st->chip_info);
if (!st->current_mode)
return -EINVAL;
-
max1363_set_scan_mode(st);
-
- numvals = bitmap_weight(st->current_mode->modemask,
- indio_dev->masklength);
- if (ring->access->set_bytes_per_datum) {
- if (ring->scan_timestamp)
- d_size += sizeof(s64);
- if (st->chip_info->bits != 8)
- d_size += numvals*2;
- else
- d_size += numvals;
- if (ring->scan_timestamp && (d_size % 8))
- d_size += 8 - (d_size % 8);
- ring->access->set_bytes_per_datum(ring, d_size);
- }
-
return 0;
}
@@ -114,12 +87,14 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
/* Ensure the timestamp is 8 byte aligned */
if (st->chip_info->bits != 8)
- d_size = numvals*2 + sizeof(s64);
+ d_size = numvals*2;
else
- d_size = numvals + sizeof(s64);
- if (d_size % sizeof(s64))
- d_size += sizeof(s64) - (d_size % sizeof(s64));
-
+ d_size = numvals;
+ if (indio_dev->buffer->scan_timestamp) {
+ d_size += sizeof(s64);
+ if (d_size % sizeof(s64))
+ d_size += sizeof(s64) - (d_size % sizeof(s64));
+ }
/* Monitor mode prevents reading. Whilst not currently implemented
* might as well have this test in here in the meantime as it does
* no harm.
@@ -138,9 +113,11 @@ static irqreturn_t max1363_trigger_handler(int irq, void *p)
goto done;
time_ns = iio_get_time_ns();
+
if (indio_dev->buffer->scan_timestamp)
memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
- indio_dev->buffer->access->store_to(indio_dev->buffer, rxbuf, time_ns);
+ iio_push_to_buffer(indio_dev->buffer, rxbuf, time_ns);
+
done:
iio_trigger_notify_done(indio_dev->trig);
kfree(rxbuf);
@@ -150,7 +127,7 @@ done:
static const struct iio_buffer_setup_ops max1363_ring_setup_ops = {
.postenable = &iio_triggered_buffer_postenable,
- .preenable = &max1363_ring_preenable,
+ .preenable = &iio_sw_buffer_preenable,
.predisable = &iio_triggered_buffer_predisable,
};
--
1.7.7.3
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 7/7] staging:iio:adc:max1363 correctly set channels as big endian.
2011-11-27 13:10 [PATCH 0/7] Add scan demux unit and use it in max1363 Jonathan Cameron
` (5 preceding siblings ...)
2011-11-27 13:10 ` [PATCH 6/7] staging:iio:adc:max1363 use new demuxing support Jonathan Cameron
@ 2011-11-27 13:10 ` Jonathan Cameron
6 siblings, 0 replies; 16+ messages in thread
From: Jonathan Cameron @ 2011-11-27 13:10 UTC (permalink / raw)
To: linux-iio; +Cc: lars, Michael.Hennerich, Jonathan Cameron
From: Jonathan Cameron <jic23@cam.ac.uk>
Also, the differential channels should always have been signed.
Signed-off-by: Jonathan Cameron <jic23@cam.ac.uk>
---
drivers/staging/iio/adc/max1363_core.c | 14 ++++++++++++--
1 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c
index 7e078fc..9febd1b 100644
--- a/drivers/staging/iio/adc/max1363_core.c
+++ b/drivers/staging/iio/adc/max1363_core.c
@@ -298,7 +298,12 @@ static const enum max1363_modes max1363_mode_list[] = {
.channel = num, \
.address = addr, \
.info_mask = MAX1363_INFO_MASK, \
- .scan_type = IIO_ST('u', bits, (bits > 8) ? 16 : 8, 0), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = bits, \
+ .storagebits = (bits > 8) ? 16 : 8, \
+ .endianness = IIO_BE, \
+ }, \
.scan_index = si, \
.event_mask = evmask, \
}
@@ -313,7 +318,12 @@ static const enum max1363_modes max1363_mode_list[] = {
.channel2 = num2, \
.address = addr, \
.info_mask = MAX1363_INFO_MASK, \
- .scan_type = IIO_ST('u', bits, (bits > 8) ? 16 : 8, 0), \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = bits, \
+ .storagebits = (bits > 8) ? 16 : 8, \
+ .endianness = IIO_BE, \
+ }, \
.scan_index = si, \
.event_mask = evmask, \
}
--
1.7.7.3
^ permalink raw reply related [flat|nested] 16+ messages in thread