From: H Hartley Sweeten Date: Tue, 9 Apr 2013 01:19:06 +0000 (-0700) Subject: staging: comedi: rti800: fix rti800_ao_insn_write() X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=853fc892239b4fb1b4d8a80b6d8c3f65061ff5bb;p=linux-beck.git staging: comedi: rti800: fix rti800_ao_insn_write() This board has two independent analog output channels. Each channel has its own 12-bit D.A converter. Each channel can be set to output a unipolar 10V or bipolar 10V signal. This selection is handled by a jumper on the board and configured by the user with options[5] and [7] passed during the attach of the board. The two channels can also be configured with jumpers to use straight binary or two's complement data. The user configures the data type with options[6] and [8] when attaching. Currently, this driver uses the dac0 selection, option[6], for both channels. Fix the rti800_ao_insn_write() function to properly use the configuration specified by the user. Change the dac[01]_coding in the private data to a simple bool array, dac_2comp. Add some local vars to hold the registers offsets needed to write to the DAC. Only the last value written to the DAC needs to be cached for readback, Signed-off-by: H Hartley Sweeten Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/comedi/drivers/rti800.c b/drivers/staging/comedi/drivers/rti800.c index 7617969a4d92..226c0d52ff00 100644 --- a/drivers/staging/comedi/drivers/rti800.c +++ b/drivers/staging/comedi/drivers/rti800.c @@ -153,9 +153,7 @@ struct rti800_private { enum { adc_2comp, adc_straight } adc_coding; - enum { - dac_2comp, dac_straight - } dac0_coding, dac1_coding; + bool dac_2comp[2]; const struct comedi_lrange *ao_range_type_list[2]; unsigned int ao_readback[2]; int muxgain_bits; @@ -235,24 +233,28 @@ static int rti800_ao_insn_read(struct comedi_device *dev, static int rti800_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) + struct comedi_insn *insn, + unsigned int *data) { struct rti800_private *devpriv = dev->private; int chan = CR_CHAN(insn->chanspec); - int d; + int reg_lo = chan ? RTI800_DAC1LO : RTI800_DAC0LO; + int reg_hi = chan ? RTI800_DAC1HI : RTI800_DAC0HI; + int val = devpriv->ao_readback[chan]; int i; for (i = 0; i < insn->n; i++) { - devpriv->ao_readback[chan] = d = data[i]; - if (devpriv->dac0_coding == dac_2comp) - d ^= 0x800; - - outb(d & 0xff, - dev->iobase + (chan ? RTI800_DAC1LO : RTI800_DAC0LO)); - outb(d >> 8, - dev->iobase + (chan ? RTI800_DAC1HI : RTI800_DAC0HI)); + val = data[i]; + if (devpriv->dac_2comp[chan]) + val ^= 0x800; + + outb(val & 0xff, dev->iobase + reg_lo); + outb((val >> 8) & 0xff, dev->iobase + reg_hi); } - return i; + + devpriv->ao_readback[chan] = val; + + return insn->n; } static int rti800_di_insn_bits(struct comedi_device *dev, @@ -325,8 +327,8 @@ static int rti800_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->private = devpriv; devpriv->adc_coding = it->options[4]; - devpriv->dac0_coding = it->options[6]; - devpriv->dac1_coding = it->options[8]; + devpriv->dac_2comp[0] = (it->options[6] == 0); + devpriv->dac_2comp[1] = (it->options[8] == 0); devpriv->muxgain_bits = -1; ret = comedi_alloc_subdevices(dev, 4);