staging: comedi: pcl812: cleanup setup_range_channel()
authorH Hartley Sweeten <hsweeten@visionengravers.com>
Tue, 4 Mar 2014 18:30:15 +0000 (11:30 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 7 Mar 2014 01:06:18 +0000 (17:06 -0800)
Move this function to remove the need for the forward declaration. Rename it
so it has namespace associated with the driver. Remove the unnecessary
comedi_subdevice parameter from the function.

The hardware does not support analog input channel scanning so the mux and
range need to be set before each (*insn_read) and when advancing to the next
channel in an async command. Instead of storing the last chan/range in the
private data just store the chanspec to determine if the mux and range need
to be changed.

Refactor pcl812_reset() a bit so we can use the helper function to set the
mux and range.

Define the bits in the mux register to remove the magic values.

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

index 7e105c872b95d6c5b4eea137c54d5bb727fba84e..862e3792668b7ef102314d0249053a86c0a52aae 100644 (file)
 #define PCL812_DI_MSB_REG                      0x07
 #define PCL812_STATUS_REG                      0x08
 #define PCL812_STATUS_DRDY                     (1 << 5)
-#define PCL812_GAIN          9
-#define PCL812_MUX          10
+#define PCL812_RANGE_REG                       0x09
+#define PCL812_MUX_REG                         0x0a
+#define PCL812_MUX_CHAN(x)                     ((x) << 0)
+#define PCL812_MUX_CS0                         (1 << 4)
+#define PCL812_MUX_CS1                         (1 << 5)
 #define PCL812_MODE         11
 #define PCL812_CNTENABLE     10
 #define PCL812_SOFTTRIG             12
@@ -500,8 +503,7 @@ static const struct pcl812_board boardtypes[] = {
 struct pcl812_private {
        unsigned char dma;      /*  >0 use dma ( usedDMA channel) */
        unsigned char range_correction; /*  =1 we must add 1 to range number */
-       unsigned char old_chan_reg;     /*  lastly used chan/gain pair */
-       unsigned char old_gain_reg;
+       unsigned int last_ai_chanspec;
        unsigned char mode_reg_int;     /*  there is stored INT number for some card */
        unsigned int ai_poll_ptr;       /*  how many sampes transfer poll */
        unsigned int ai_act_scan;       /*  how many scans we finished */
@@ -524,10 +526,6 @@ struct pcl812_private {
        unsigned int ai_eos:1;
 };
 
-static void setup_range_channel(struct comedi_device *dev,
-                               struct comedi_subdevice *s,
-                               unsigned int rangechan, char wait);
-
 static void pcl812_start_pacer(struct comedi_device *dev, bool load_timers)
 {
        struct pcl812_private *devpriv = dev->private;
@@ -633,6 +631,41 @@ static void pcl812_ai_setup_next_dma(struct comedi_device *dev,
        enable_dma(devpriv->dma);
 }
 
+static void pcl812_ai_set_chan_range(struct comedi_device *dev,
+                                    unsigned int chanspec, char wait)
+{
+       struct pcl812_private *devpriv = dev->private;
+       unsigned int chan = CR_CHAN(chanspec);
+       unsigned int range = CR_RANGE(chanspec);
+       unsigned int mux = 0;
+
+       if (chanspec == devpriv->last_ai_chanspec)
+               return;
+
+       devpriv->last_ai_chanspec = chanspec;
+
+       if (devpriv->use_mpc508) {
+               if (devpriv->use_diff) {
+                       mux |= PCL812_MUX_CS0 | PCL812_MUX_CS1;
+               } else {
+                       if (chan < 8)
+                               mux |= PCL812_MUX_CS0;
+                       else
+                               mux |= PCL812_MUX_CS1;
+               }
+       }
+
+       outb(mux | PCL812_MUX_CHAN(chan), dev->iobase + PCL812_MUX_REG);
+       outb(range + devpriv->range_correction, dev->iobase + PCL812_RANGE_REG);
+
+       if (wait)
+               /*
+                * XXX this depends on selected range and can be very long for
+                * some high gain ranges!
+                */
+               udelay(devpriv->max_812_ai_mode0_rangewait);
+}
+
 static void pcl812_ai_clear_eoc(struct comedi_device *dev)
 {
        /* writing any value clears the interrupt request */
@@ -761,8 +794,7 @@ static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 
        pcl812_start_pacer(dev, false);
 
-       /*  select first channel and range */
-       setup_range_channel(dev, s, cmd->chanlist[0], 1);
+       pcl812_ai_set_chan_range(dev, cmd->chanlist[0], 1);
 
        if (devpriv->dma) {     /*  check if we can use DMA transfer */
                devpriv->ai_dma = 1;
@@ -851,7 +883,7 @@ static void pcl812_handle_eoc(struct comedi_device *dev,
        if (next_chan >= cmd->chanlist_len)
                next_chan = 0;
        if (cmd->chanlist[s->async->cur_chan] != cmd->chanlist[next_chan])
-               setup_range_channel(dev, s, cmd->chanlist[next_chan], 0);
+               pcl812_ai_set_chan_range(dev, cmd->chanlist[next_chan], 0);
 
        pcl812_ai_next_chan(dev, s);
 }
@@ -956,48 +988,6 @@ static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
        return s->async->buf_write_count - s->async->buf_read_count;
 }
 
-static void setup_range_channel(struct comedi_device *dev,
-                               struct comedi_subdevice *s,
-                               unsigned int rangechan, char wait)
-{
-       struct pcl812_private *devpriv = dev->private;
-       unsigned char chan_reg = CR_CHAN(rangechan);    /*  normal board */
-                                                       /*  gain index */
-       unsigned char gain_reg = CR_RANGE(rangechan) +
-                                devpriv->range_correction;
-
-       if ((chan_reg == devpriv->old_chan_reg)
-           && (gain_reg == devpriv->old_gain_reg))
-               return;         /*  we can return, no change */
-
-       devpriv->old_chan_reg = chan_reg;
-       devpriv->old_gain_reg = gain_reg;
-
-       if (devpriv->use_mpc508) {
-               if (devpriv->use_diff) {
-                       chan_reg = chan_reg | 0x30;     /*  DIFF inputs */
-               } else {
-                       if (chan_reg & 0x80)
-                                                       /*  SE inputs 8-15 */
-                               chan_reg = chan_reg | 0x20;
-                       else
-                                                       /*  SE inputs 0-7 */
-                               chan_reg = chan_reg | 0x10;
-               }
-       }
-
-       outb(chan_reg, dev->iobase + PCL812_MUX);       /* select channel */
-       outb(gain_reg, dev->iobase + PCL812_GAIN);      /* select gain */
-
-
-       if (wait)
-               /*
-                * XXX this depends on selected range and can be very long for
-                * some high gain ranges!
-                */
-               udelay(devpriv->max_812_ai_mode0_rangewait);
-}
-
 static int pcl812_ai_cancel(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
@@ -1025,8 +1015,7 @@ static int pcl812_ai_insn_read(struct comedi_device *dev,
        /* select software trigger */
        outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE);
 
-       /*  select channel and renge */
-       setup_range_channel(dev, s, insn->chanspec, 1);
+       pcl812_ai_set_chan_range(dev, insn->chanspec, 1);
 
        for (i = 0; i < insn->n; i++) {
                pcl812_ai_clear_eoc(dev);
@@ -1110,10 +1099,12 @@ static void pcl812_reset(struct comedi_device *dev)
        const struct pcl812_board *board = comedi_board(dev);
        struct pcl812_private *devpriv = dev->private;
 
-       outb(0, dev->iobase + PCL812_MUX);
-       outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN);
-       devpriv->old_chan_reg = -1;     /*  invalidate chain/gain memory */
-       devpriv->old_gain_reg = -1;
+       /*
+        * Invalidate last_ai_chanspec then set analog input to
+        * known channel/range.
+        */
+       devpriv->last_ai_chanspec = CR_PACK(16, 0, 0);
+       pcl812_ai_set_chan_range(dev, CR_PACK(0, 0, 0), 0);
 
        switch (board->board_type) {
        case boardPCL812PG: