summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorH Hartley Sweeten <hsweeten@visionengravers.com>2015-08-17 16:58:22 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-09-12 18:24:21 -0700
commit09c5d6c83ec3bd56ee1ebef8bec42956b32ca7eb (patch)
tree9e6a829b9b7bbca5cf07baed045d66a91adc741f /drivers
parent12911c2d6ae64315edb721cc142cc6d4b20db8b5 (diff)
downloadlinux-stable-09c5d6c83ec3bd56ee1ebef8bec42956b32ca7eb.tar.gz
linux-stable-09c5d6c83ec3bd56ee1ebef8bec42956b32ca7eb.tar.bz2
linux-stable-09c5d6c83ec3bd56ee1ebef8bec42956b32ca7eb.zip
staging: comedi: s526: wait for analog output conversions to complete
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/comedi/drivers/s526.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/staging/comedi/drivers/s526.c b/drivers/staging/comedi/drivers/s526.c
index 242db7d9dfb3..152be955f8ab 100644
--- a/drivers/staging/comedi/drivers/s526.c
+++ b/drivers/staging/comedi/drivers/s526.c
@@ -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;