From bfb0c28ba03a46740c80848ba7b93fafb91de033 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Mon, 14 Jul 2014 12:23:43 -0700 Subject: [PATCH] staging: comedi: ni_mio_common: fix ni_ao_insn_write() Comedi (*insn_write) functions are expected to write insn->n values to the hardware. Fix this function to work like the core expects. Also, don't rely on the return value of ni_ao_comfig_chanlist() to determine if the values need converted to two's complement before writing to the hardware. Use the comedi_range_is_bipolar() and comedi_offset_munge() helpers to clarify the code. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/ni_mio_common.c | 40 +++++++++++++++++++------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index d937eb87cf40..c08b9b63a770 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -3079,23 +3079,43 @@ static int ni_ao_insn_read(struct comedi_device *dev, static int ni_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 ni_private *devpriv = dev->private; unsigned int chan = CR_CHAN(insn->chanspec); - unsigned int invert; + unsigned int range = CR_RANGE(insn->chanspec); + int reg; + int i; - invert = ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); + if (devpriv->is_m_series) + reg = M_Offset_DAC_Direct_Data(chan); + else + reg = (chan) ? DAC1_Direct_Data : DAC0_Direct_Data; - devpriv->ao[chan] = data[0]; + ni_ao_config_chanlist(dev, s, &insn->chanspec, 1, 0); - if (devpriv->is_m_series) { - ni_writew(dev, data[0], M_Offset_DAC_Direct_Data(chan)); - } else - ni_writew(dev, data[0] ^ invert, - (chan) ? DAC1_Direct_Data : DAC0_Direct_Data); + for (i = 0; i < insn->n; i++) { + unsigned int val = data[i]; - return 1; + devpriv->ao[chan] = val; + + if (devpriv->is_m_series) { + /* M-series board always use offset binary values */ + ni_writew(dev, val, reg); + } else { + /* + * Non-M series boards need two's complement values + * for bipolar ranges. + */ + if (comedi_range_is_bipolar(s, range)) + val = comedi_offset_munge(s, val); + + ni_writew(dev, val, reg); + } + } + + return insn->n; } static int ni_ao_insn_write_671x(struct comedi_device *dev, -- 2.11.0