- patches.arch/x86_mce_intel_decode_physical_address.patch:
[linux-flexiantxendom0-3.2.10.git] / drivers / staging / iio / adc / max1363_ring.c
index f94fe2d..56688dc 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/sysfs.h>
 #include <linux/list.h>
 #include <linux/i2c.h>
+#include <linux/bitops.h>
 
 #include "../iio.h"
 #include "../ring_generic.h"
 
 #include "max1363.h"
 
-ssize_t max1363_scan_from_ring(struct device *dev,
-                              struct device_attribute *attr,
-                              char *buf)
+/* Todo: test this */
+int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
 {
-       struct iio_dev *dev_info = dev_get_drvdata(dev);
-       struct max1363_state *info = dev_info->dev_data;
-       int i, ret, len = 0;
-       char *ring_data;
+       unsigned long numvals;
+       int count = 0, ret;
+       u8 *ring_data;
+       if (!(st->current_mode->modemask & mask)) {
+               ret = -EBUSY;
+               goto error_ret;
+       }
+       numvals = hweight_long(st->current_mode->modemask);
 
-       ring_data = kmalloc(info->current_mode->numvals*2, GFP_KERNEL);
+       ring_data = kmalloc(numvals*2, GFP_KERNEL);
        if (ring_data == NULL) {
                ret = -ENOMEM;
                goto error_ret;
        }
-       ret = dev_info->ring->access.read_last(dev_info->ring, ring_data);
+       ret = st->indio_dev->ring->access.read_last(st->indio_dev->ring,
+                                               ring_data);
        if (ret)
                goto error_free_ring_data;
-       len += sprintf(buf+len, "ring ");
-       for (i = 0; i < info->current_mode->numvals; i++)
-               len += sprintf(buf + len, "%d ",
-                              ((int)(ring_data[i*2 + 0] & 0x0F) << 8)
-                              + ((int)(ring_data[i*2 + 1])));
-       len += sprintf(buf + len, "\n");
-       kfree(ring_data);
-
-       return len;
+       /* Need a count of channels prior to this one */
+       mask >>= 1;
+       while (mask) {
+               if (mask & st->current_mode->modemask)
+                       count++;
+               mask >>= 1;
+       }
+       if (st->chip_info->bits != 8)
+               ret = ((int)(ring_data[count*2 + 0] & 0x0F) << 8)
+                       + (int)(ring_data[count*2 + 1]);
+       else
+               ret = ring_data[count];
 
 error_free_ring_data:
        kfree(ring_data);
@@ -70,9 +78,25 @@ static int max1363_ring_preenable(struct iio_dev *indio_dev)
 {
        struct max1363_state *st = indio_dev->dev_data;
        size_t d_size;
+       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(st->indio_dev->scan_mask,
+                                       st->chip_info);
+       if (!st->current_mode)
+               return -EINVAL;
+
+       max1363_set_scan_mode(st);
+
+       numvals = hweight_long(st->current_mode->modemask);
        if (indio_dev->ring->access.set_bpd) {
-               d_size = st->current_mode->numvals*2 + sizeof(s64);
+               if (st->chip_info->bits != 8)
+                       d_size = numvals*2 + sizeof(s64);
+               else
+                       d_size = numvals + sizeof(s64);
                if (d_size % 8)
                        d_size += 8 - (d_size % 8);
                indio_dev->ring->access.set_bpd(indio_dev->ring, d_size);
@@ -118,7 +142,7 @@ static int max1363_ring_predisable(struct iio_dev *indio_dev)
  * then.  Some triggers will generate their own time stamp.  Currently
  * there is no way of notifying them when no one cares.
  **/
-void max1363_poll_func_th(struct iio_dev *indio_dev)
+static void max1363_poll_func_th(struct iio_dev *indio_dev)
 {
        struct max1363_state *st = indio_dev->dev_data;
 
@@ -145,9 +169,13 @@ static void max1363_poll_bh_to_ring(struct work_struct *work_s)
        __u8 *rxbuf;
        int b_sent;
        size_t d_size;
+       unsigned long numvals = hweight_long(st->current_mode->modemask);
 
        /* Ensure the timestamp is 8 byte aligned */
-       d_size = st->current_mode->numvals*2 + sizeof(s64);
+       if (st->chip_info->bits != 8)
+               d_size = numvals*2 + sizeof(s64);
+       else
+               d_size = numvals + sizeof(s64);
        if (d_size % sizeof(s64))
                d_size += sizeof(s64) - (d_size % sizeof(s64));
 
@@ -159,16 +187,16 @@ static void max1363_poll_bh_to_ring(struct work_struct *work_s)
         * might as well have this test in here in the meantime as it does
         * no harm.
         */
-       if (st->current_mode->numvals == 0)
+       if (numvals == 0)
                return;
 
        rxbuf = kmalloc(d_size, GFP_KERNEL);
        if (rxbuf == NULL)
                return;
-
-       b_sent = i2c_master_recv(st->client,
-                                rxbuf,
-                                st->current_mode->numvals*2);
+       if (st->chip_info->bits != 8)
+               b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
+       else
+               b_sent = i2c_master_recv(st->client, rxbuf, numvals);
        if (b_sent < 0)
                goto done;
 
@@ -238,5 +266,5 @@ void max1363_uninitialize_ring(struct iio_ring_buffer *ring)
 
 int max1363_initialize_ring(struct iio_ring_buffer *ring)
 {
-       return iio_ring_buffer_register(ring);
+       return iio_ring_buffer_register(ring, 0);
 };