staging: comedi: pcmad: properly handle analog input encoding configuration
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Wed, 5 Jun 2013 22:38:37 +0000 (15:38 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 6 Jun 2013 19:01:35 +0000 (12:01 -0700)
The comedi_config utility is used to attach to this board. One of the
configuration options passed by the user sets the analog input encoding
for straight binary or two's complement data. The hardware produces
straight binary data when jumpered for 5V unipolar inputs and two's
complement data when jumpered for +-10V bipolar inputs.

Use the configuration option to correctly set the comedi_subdevice
range_table.

We can then use a helper function to determine what the range is when
reading the analog inputs. This allows removing the 'twos_comp' variable
from the private data (which was actually never used).

Since the private data is now empty, remove it completely.

Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/comedi/drivers/pcmad.c

index 86597fc..8028e47 100644 (file)
@@ -34,8 +34,8 @@
  *        0 = single-ended (16 channels)
  *        1 = differential (8 channels)
  *   [3] - Analog input encoding (must match jumpers)
- *        0 = straight binary
- *        1 = two's complement
+ *        0 = straight binary (0-5V input range)
+ *        1 = two's complement (+-10V input range)
  */
 
 #include <linux/interrupt.h>
@@ -63,10 +63,6 @@ static const struct pcmad_board_struct pcmad_boards[] = {
        },
 };
 
-struct pcmad_priv_struct {
-       int twos_comp;
-};
-
 #define TIMEOUT        100
 
 static int pcmad_ai_wait_for_eoc(struct comedi_device *dev,
@@ -81,13 +77,19 @@ static int pcmad_ai_wait_for_eoc(struct comedi_device *dev,
        return -ETIME;
 }
 
+static bool pcmad_range_is_bipolar(struct comedi_subdevice *s,
+                                  unsigned int range)
+{
+       return s->range_table->range[range].min < 0;
+}
+
 static int pcmad_ai_insn_read(struct comedi_device *dev,
                              struct comedi_subdevice *s,
                              struct comedi_insn *insn,
                              unsigned int *data)
 {
-       struct pcmad_priv_struct *devpriv = dev->private;
        unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int range = CR_RANGE(insn->chanspec);
        unsigned int val;
        int ret;
        int i;
@@ -102,8 +104,10 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
                val = inb(dev->iobase + PCMAD_LSB) |
                      (inb(dev->iobase + PCMAD_MSB) << 8);
 
-               if (devpriv->twos_comp)
+               if (pcmad_range_is_bipolar(s, range)) {
+                       /* munge the two's complement value */
                        val ^= ((s->maxdata + 1) >> 1);
+               }
 
                data[i] = val;
        }
@@ -114,7 +118,6 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
 static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
        const struct pcmad_board_struct *board = comedi_board(dev);
-       struct pcmad_priv_struct *devpriv;
        struct comedi_subdevice *s;
        int ret;
 
@@ -126,11 +129,6 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (ret)
                return ret;
 
-       devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
-       if (!devpriv)
-               return -ENOMEM;
-       dev->private = devpriv;
-
        s = &dev->subdevices[0];
        s->type         = COMEDI_SUBD_AI;
        if (it->options[1]) {
@@ -144,7 +142,7 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        }
        s->len_chanlist = 1;
        s->maxdata      = board->ai_maxdata;
-       s->range_table  = &range_unknown;
+       s->range_table  = it->options[2] ? &range_bipolar10 : &range_unipolar5;
        s->insn_read    = pcmad_ai_insn_read;
 
        return 0;