Commit 4384aaad authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

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: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 598e61e6
......@@ -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:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment