summaryrefslogtreecommitdiff
path: root/drivers/staging/comedi/drivers/pcl812.c
diff options
context:
space:
mode:
authorH Hartley Sweeten <hsweeten@visionengravers.com>2014-03-04 11:30:15 -0700
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-03-06 17:06:18 -0800
commit4384aaadc2289cc15a606205e6a897dd524cd0f8 (patch)
tree8e205300c76bdc53c5c5057fc5947b1023da555f /drivers/staging/comedi/drivers/pcl812.c
parent598e61e6dd42cc865ca34a1213054946a99489ff (diff)
staging: comedi: pcl812: cleanup setup_range_channel()
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>
Diffstat (limited to 'drivers/staging/comedi/drivers/pcl812.c')
-rw-r--r--drivers/staging/comedi/drivers/pcl812.c109
1 files changed, 50 insertions, 59 deletions
diff --git a/drivers/staging/comedi/drivers/pcl812.c b/drivers/staging/comedi/drivers/pcl812.c
index 7e105c872b95..862e3792668b 100644
--- a/drivers/staging/comedi/drivers/pcl812.c
+++ b/drivers/staging/comedi/drivers/pcl812.c
@@ -141,8 +141,11 @@
#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: