staging: comedi: cb_pcimdas: support analog input programmable ranges
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Wed, 25 Feb 2015 23:28:39 +0000 (16:28 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Mar 2015 02:56:30 +0000 (18:56 -0800)
The hardware uses a switch on the board to select if the analog inputs
are bipolar or uinipolar. The gain is programmable to allow the following
input ranges:

  Gain  Bipolar   Unipolar
    0   +/-10V    0 to 10V
    1   +/-5V     0 to 5V
    2   +/-2.5V   0 to 2.5V
    3   +/-1.25V  0 to 1.25V

Add the necessary code to the driver to allow the user to select the
desired range.

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

index ddaa61c1cc314ba309db6400f3366034c713571d..5d08ca439bc994a6ced99b687ad91f9d1f6b24f4 100644 (file)
 #define RESID_COUNT_H 13
 #define RESID_COUNT_L 14
 
+static const struct comedi_lrange cb_pcimdas_ai_bip_range = {
+       4, {
+               BIP_RANGE(10),
+               BIP_RANGE(5),
+               BIP_RANGE(2.5),
+               BIP_RANGE(1.25)
+       }
+};
+
+static const struct comedi_lrange cb_pcimdas_ai_uni_range = {
+       4, {
+               UNI_RANGE(10),
+               UNI_RANGE(5),
+               UNI_RANGE(2.5),
+               UNI_RANGE(1.25)
+       }
+};
+
 /*
  * this structure is for data unique to this hardware driver.  If
  * several hardware drivers keep similar information in this structure,
@@ -105,9 +123,10 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
                               struct comedi_insn *insn, unsigned int *data)
 {
        struct cb_pcimdas_private *devpriv = dev->private;
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       unsigned int range = CR_RANGE(insn->chanspec);
        int n;
        unsigned int d;
-       int chan = CR_CHAN(insn->chanspec);
        unsigned short chanlims;
        int ret;
 
@@ -123,8 +142,8 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
        /* set bursting off, conversions on */
        outb(0x01, devpriv->BADR3 + 6);
 
-       /* set range to 10V. UP/BP is controlled by a switch on the board */
-       outb(0x00, devpriv->BADR3 + 7);
+       /* set range */
+       outb(range, devpriv->BADR3 + 7);
 
        /*
         * write channel limits to multiplexer, set Low (bits 0-3) and
@@ -185,6 +204,20 @@ static bool cb_pcimdas_is_ai_se(struct comedi_device *dev)
        return status & 0x20;
 }
 
+static bool cb_pcimdas_is_ai_uni(struct comedi_device *dev)
+{
+       struct cb_pcimdas_private *devpriv = dev->private;
+       unsigned int status;
+
+       /*
+        * The Analog Input range polarity is set with the
+        * Analog Input Polarity Switch on the board. The
+        * inputs can be set to Unipolar or Bipolar ranges.
+        */
+       status = inb(devpriv->BADR3 + 2);
+       return status & 0x40;
+}
+
 static int cb_pcimdas_auto_attach(struct comedi_device *dev,
                                            unsigned long context_unused)
 {
@@ -222,7 +255,8 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
                s->n_chan       = 8;
        }
        s->maxdata = 0xffff;
-       s->range_table = &range_unknown;
+       s->range_table  = cb_pcimdas_is_ai_uni(dev) ? &cb_pcimdas_ai_uni_range
+                                                   : &cb_pcimdas_ai_bip_range;
        s->len_chanlist = 1;    /*  This is the maximum chanlist length that */
        /*  the board can handle */
        s->insn_read = cb_pcimdas_ai_rinsn;