staging: comedi: addi_apci_3120: fix apci3120_ao_insn_write()
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Mon, 20 Oct 2014 18:34:20 +0000 (11:34 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 29 Oct 2014 07:58:36 +0000 (15:58 +0800)
The comedi core expects (*insn_write) functions to write insn->n values and
return the number of values written or an errno. This function currently
returns insn->n but it only writes a single data value.

Fix the function to work like the core expects.

There are two registers used to update the analog outputs. Offset 0x08 is
used to update channels 0-3 and offset 0x0a to update channels 4-7. Bits
14 and 15 in each register set the mux to select which channel to update.
The lower 14 bits are the value used to set the DAC.

For aesthetics, tidy up the defines used for the register offsets and bits
in the registers.

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/addi-data/hwdrv_apci3120.c
drivers/staging/comedi/drivers/addi_apci_3120.c

index fbe17917cea1c274e386485de74495aacd869364..47b1741758d19154cc53c8efd95e90f684753c4b 100644 (file)
@@ -96,24 +96,12 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
 #define        APCI3120_SET4DIGITALOUTPUTON    1
 #define APCI3120_SET4DIGITALOUTPUTOFF  0
 
-/* analog output SELECT BIT */
-#define APCI3120_ANALOG_OP_CHANNEL_1   0x0000
-#define APCI3120_ANALOG_OP_CHANNEL_2   0x4000
-#define APCI3120_ANALOG_OP_CHANNEL_3   0x8000
-#define APCI3120_ANALOG_OP_CHANNEL_4   0xc000
-#define APCI3120_ANALOG_OP_CHANNEL_5   0x0000
-#define APCI3120_ANALOG_OP_CHANNEL_6   0x4000
-#define APCI3120_ANALOG_OP_CHANNEL_7   0x8000
-#define APCI3120_ANALOG_OP_CHANNEL_8   0xc000
-
 /* Enable external trigger bit in nWrAddress */
 #define APCI3120_ENABLE_EXT_TRIGGER    0x8000
 
 /* ANALOG OUTPUT AND INPUT DEFINE */
 #define APCI3120_UNIPOLAR              0x80
 #define APCI3120_BIPOLAR               0x00
-#define APCI3120_ANALOG_OUTPUT_1       0x08
-#define APCI3120_ANALOG_OUTPUT_2       0x0a
 #define APCI3120_1_GAIN                        0x00
 #define APCI3120_2_GAIN                        0x10
 #define APCI3120_5_GAIN                        0x20
@@ -1923,31 +1911,20 @@ static int apci3120_ao_insn_write(struct comedi_device *dev,
                                  struct comedi_insn *insn,
                                  unsigned int *data)
 {
-       unsigned int ui_Channel;
-       int ret;
-
-       ui_Channel = CR_CHAN(insn->chanspec);
+       unsigned int chan = CR_CHAN(insn->chanspec);
+       int i;
 
-       data[0] = ((((ui_Channel & 0x03) << 14) & 0xC000) | data[0]);
+       for (i = 0; i < insn->n; i++) {
+               unsigned int val = data[i];
+               int ret;
 
-       ret = comedi_timeout(dev, s, insn, apci3120_ao_ready, 0);
-       if (ret)
-               return ret;
+               ret = comedi_timeout(dev, s, insn, apci3120_ao_ready, 0);
+               if (ret)
+                       return ret;
 
-       if (ui_Channel <= 3)
-               /*
-                * for channel 0-3 out at the register 1 (wrDac1-8) data[i]
-                * typecasted to ushort since word write is to be done
-                */
-               outw((unsigned short) data[0],
-                    dev->iobase + APCI3120_ANALOG_OUTPUT_1);
-       else
-               /*
-                * for channel 4-7 out at the register 2 (wrDac5-8) data[i]
-                * typecasted to ushort since word write is to be done
-                */
-               outw((unsigned short) data[0],
-                    dev->iobase + APCI3120_ANALOG_OUTPUT_2);
+               outw(APCI3120_AO_MUX(chan) | APCI3120_AO_DATA(val),
+                    dev->iobase + APCI3120_AO_REG(chan));
+       }
 
        return insn->n;
 }
index 6b4a51db9c9e42542d26b69f49bd2669b71d554c..abc85bf000ff27a33ba0fd66e70b8e8dd48618df 100644 (file)
@@ -7,6 +7,22 @@
 #include "comedi_fc.h"
 #include "amcc_s5933.h"
 
+/*
+ * PCI BAR 0 register map (devpriv->amcc)
+ * see amcc_s5933.h for register and bit defines
+ */
+
+/*
+ * PCI BAR 1 register map (dev->iobase)
+ */
+#define APCI3120_AO_REG(x)                     (0x08 + (((x) / 4) * 2))
+#define APCI3120_AO_MUX(x)                     (((x) & 0x3) << 14)
+#define APCI3120_AO_DATA(x)                    ((x) << 0)
+
+/*
+ * PCI BAR 2 register map (devpriv->addon)
+ */
+
 enum apci3120_boardid {
        BOARD_APCI3120,
        BOARD_APCI3001,