staging: comedi: s526: wait for analog output conversions to complete
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Mon, 17 Aug 2015 23:58:22 +0000 (16:58 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 13 Sep 2015 01:24:21 +0000 (18:24 -0700)
It's possible for the user to write more than one value to an analog
output channel with the (*insn_write) operation. Use comedi_timeout()
to check the interrupt status register to ensure that each data
conversion is complete before writing the next value.

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/s526.c

index 242db7d9dfb3d969c7f6460cf2c0776c09b63658..152be955f8abd46ddc506f5463fe9456654c4d0a 100644 (file)
@@ -418,16 +418,19 @@ static int s526_ai_insn_config(struct comedi_device *dev,
        return result;
 }
 
-static int s526_ai_eoc(struct comedi_device *dev,
-                      struct comedi_subdevice *s,
-                      struct comedi_insn *insn,
-                      unsigned long context)
+static int s526_eoc(struct comedi_device *dev,
+                   struct comedi_subdevice *s,
+                   struct comedi_insn *insn,
+                   unsigned long context)
 {
        unsigned int status;
 
        status = inw(dev->iobase + S526_INT_STATUS_REG);
-       if (status & S526_INT_AI)
+       if (status & context) {
+               /* we got our eoc event, clear it */
+               outw(context, dev->iobase + S526_INT_STATUS_REG);
                return 0;
+       }
        return -EBUSY;
 }
 
@@ -455,12 +458,10 @@ static int s526_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
                outw(ctrl, dev->iobase + S526_AI_CTRL_REG);
 
                /* wait for conversion to end */
-               ret = comedi_timeout(dev, s, insn, s526_ai_eoc, 0);
+               ret = comedi_timeout(dev, s, insn, s526_eoc, S526_INT_AI);
                if (ret)
                        return ret;
 
-               outw(S526_INT_AI, dev->iobase + S526_INT_STATUS_REG);
-
                d = inw(dev->iobase + S526_AI_REG);
 
                /* munge data */
@@ -479,6 +480,7 @@ static int s526_ao_insn_write(struct comedi_device *dev,
        unsigned int chan = CR_CHAN(insn->chanspec);
        unsigned int ctrl = S526_AO_CTRL_CHAN(chan);
        unsigned int val = s->readback[chan];
+       int ret;
        int i;
 
        outw(ctrl, dev->iobase + S526_AO_CTRL_REG);
@@ -488,6 +490,11 @@ static int s526_ao_insn_write(struct comedi_device *dev,
                val = data[i];
                outw(val, dev->iobase + S526_AO_REG);
                outw(ctrl, dev->iobase + S526_AO_CTRL_REG);
+
+               /* wait for conversion to end */
+               ret = comedi_timeout(dev, s, insn, s526_eoc, S526_INT_AO);
+               if (ret)
+                       return ret;
        }
        s->readback[chan] = val;