]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/staging/comedi/drivers/me_daq.c
Merge remote-tracking branch 'staging/staging-next'
[karo-tx-linux.git] / drivers / staging / comedi / drivers / me_daq.c
index 91104050a203787f190b8d6a744496953144951b..3bf0caa18ab04a7af4046a74deba09252b82dbca 100644 (file)
@@ -243,12 +243,18 @@ static int me_ai_insn_read(struct comedi_device *dev,
        unsigned int chan = CR_CHAN(insn->chanspec);
        unsigned int range = CR_RANGE(insn->chanspec);
        unsigned int aref = CR_AREF(insn->chanspec);
-       unsigned short val;
-       int ret;
+       unsigned int val;
+       int ret = 0;
+       int i;
 
-       /* stop any running conversion */
-       devpriv->ctrl1 &= ~ME_CTRL1_ADC_MODE_MASK;
-       writew(devpriv->ctrl1, dev->mmio + ME_CTRL1_REG);
+       /*
+        * For differential operation, there are only 8 input channels
+        * and only bipolar ranges are available.
+        */
+       if (aref & AREF_DIFF) {
+               if (chan > 7 || comedi_range_is_unipolar(s, range))
+                       return -EINVAL;
+       }
 
        /* clear chanlist and ad fifo */
        devpriv->ctrl2 &= ~(ME_CTRL2_ADFIFO_ENA | ME_CTRL2_CHANLIST_ENA);
@@ -272,24 +278,27 @@ static int me_ai_insn_read(struct comedi_device *dev,
        devpriv->ctrl1 |= ME_CTRL1_ADC_MODE_SOFT_TRIG;
        writew(devpriv->ctrl1, dev->mmio + ME_CTRL1_REG);
 
-       /* start ai conversion */
-       readw(dev->mmio + ME_CTRL1_REG);
+       for (i = 0; i < insn->n; i++) {
+               /* start ai conversion */
+               readw(dev->mmio + ME_CTRL1_REG);
 
-       /* wait for ADC fifo not empty flag */
-       ret = comedi_timeout(dev, s, insn, me_ai_eoc, 0);
-       if (ret)
-               return ret;
+               /* wait for ADC fifo not empty flag */
+               ret = comedi_timeout(dev, s, insn, me_ai_eoc, 0);
+               if (ret)
+                       break;
+
+               /* get value from ADC fifo */
+               val = readw(dev->mmio + ME_AI_FIFO_REG) & s->maxdata;
 
-       /* get value from ADC fifo */
-       val = readw(dev->mmio + ME_AI_FIFO_REG);
-       val = (val ^ 0x800) & 0x0fff;
-       data[0] = val;
+               /* munge 2's complement value to offset binary */
+               data[i] = comedi_offset_munge(s, val);
+       }
 
        /* stop any running conversion */
        devpriv->ctrl1 &= ~ME_CTRL1_ADC_MODE_MASK;
        writew(devpriv->ctrl1, dev->mmio + ME_CTRL1_REG);
 
-       return 1;
+       return ret ? ret : insn->n;
 }
 
 static int me_ao_insn_write(struct comedi_device *dev,
@@ -472,7 +481,7 @@ static int me_auto_attach(struct comedi_device *dev,
 
        s = &dev->subdevices[0];
        s->type         = COMEDI_SUBD_AI;
-       s->subdev_flags = SDF_READABLE | SDF_COMMON;
+       s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_DIFF;
        s->n_chan       = 16;
        s->maxdata      = 0x0fff;
        s->len_chanlist = 16;