staging: comedi: pcmmio: cleanup ao_winsn()

Rename this function to have namespace associated with the driver.

Refactor the function to remove the extra write to the command register
to set the range before writing the DAC value. Since the range is constant
for the entire comedi_insn it only needs to be set once. All writes to the
DAC after that will use the same range.

Define the register map for the analog output 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>
This commit is contained in:
H Hartley Sweeten 2013-12-09 15:30:47 -07:00 committed by Greg Kroah-Hartman
parent a81f87e9a0
commit 68533c7b8e
1 changed files with 85 additions and 63 deletions

View File

@ -102,6 +102,29 @@ Configuration Options:
#define PCMMIO_AI_RESOURCE_REG 0x03
#define PCMMIO_AI_2ND_ADC_OFFSET 0x04
#define PCMMIO_AO_LSB_REG 0x08
#define PCMMIO_AO_LSB_SPAN(x) (((x) & 0xf) << 0)
#define PCMMIO_AO_MSB_REG 0x09
#define PCMMIO_AO_CMD_REG 0x0a
#define PCMMIO_AO_CMD_WR_SPAN (0x2 << 4)
#define PCMMIO_AO_CMD_WR_CODE (0x3 << 4)
#define PCMMIO_AO_CMD_UPDATE (0x4 << 4)
#define PCMMIO_AO_CMD_UPDATE_ALL (0x5 << 4)
#define PCMMIO_AO_CMD_WR_SPAN_UPDATE (0x6 << 4)
#define PCMMIO_AO_CMD_WR_CODE_UPDATE (0x7 << 4)
#define PCMMIO_AO_CMD_WR_SPAN_UPDATE_ALL (0x8 << 4)
#define PCMMIO_AO_CMD_WR_CODE_UPDATE_ALL (0x9 << 4)
#define PCMMIO_AO_CMD_RD_B1_SPAN (0xa << 4)
#define PCMMIO_AO_CMD_RD_B1_CODE (0xb << 4)
#define PCMMIO_AO_CMD_RD_B2_SPAN (0xc << 4)
#define PCMMIO_AO_CMD_RD_B2_CODE (0xd << 4)
#define PCMMIO_AO_CMD_NOP (0xf << 4)
#define PCMMIO_AO_CMD_CHAN_SEL(x) (((x) & 0x03) << 1)
#define PCMMIO_AO_CMD_CHAN_SEL_ALL (0x0f << 0)
#define PCMMIO_AO_STATUS_REG 0x0b
#define PCMMIO_AO_RESOURCE_ENA_REG 0x0b
#define PCMMIO_AO_2ND_DAC_OFFSET 0x04
/* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */
#define CHANS_PER_PORT 8
#define PORTS_PER_ASIC 6
@ -880,53 +903,51 @@ static int wait_dac_ready(unsigned long iobase)
return 1;
}
static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
static int pcmmio_ao_insn_write(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
unsigned int *data)
{
struct pcmmio_private *devpriv = dev->private;
unsigned long iobase = dev->iobase + 8;
unsigned int iooffset = 0;
int n;
for (n = 0; n < insn->n; n++) {
unsigned chan = CR_CHAN(insn->chanspec), range =
CR_RANGE(insn->chanspec);
if (chan < s->n_chan) {
unsigned char command_byte = 0, range_byte =
range & ((1 << 4) - 1);
if (chan >= 4)
chan -= 4, iooffset += 4;
/* set the range.. */
outb(range_byte, iobase + iooffset + 0);
outb(0, iobase + iooffset + 1);
/* tell it to begin */
command_byte = (chan << 1) | 0x60;
outb(command_byte, iobase + iooffset + 2);
wait_dac_ready(iobase + iooffset);
/* low order byte */
outb(data[n] & 0xff, iobase + iooffset + 0);
/* high order byte */
outb((data[n] >> 8) & 0xff, iobase + iooffset + 1);
unsigned long iobase = dev->iobase;
unsigned int chan = CR_CHAN(insn->chanspec);
unsigned int range = CR_RANGE(insn->chanspec);
unsigned int val = devpriv->ao_readback[chan];
unsigned char cmd = 0;
int i;
/*
* set bit 4 of command byte to indicate
* data is loaded and trigger conversion
* The PCM-MIO has two Linear Tech LTC2704 DAC devices. Each device
* is a 4-channel converter with software-selectable output range.
*/
command_byte = 0x70 | (chan << 1);
/* trigger converion */
outb(command_byte, iobase + iooffset + 2);
wait_dac_ready(iobase + iooffset);
if (chan > 3) {
cmd |= PCMMIO_AO_CMD_CHAN_SEL(chan - 4);
iobase += PCMMIO_AO_2ND_DAC_OFFSET;
} else {
cmd |= PCMMIO_AO_CMD_CHAN_SEL(chan);
}
/* save to shadow register for ao_rinsn */
devpriv->ao_readback[chan] = data[n];
/* set the range for the channel */
outb(PCMMIO_AO_LSB_SPAN(range), iobase + PCMMIO_AO_LSB_REG);
outb(0, iobase + PCMMIO_AO_MSB_REG);
outb(cmd | PCMMIO_AO_CMD_WR_SPAN_UPDATE, iobase + PCMMIO_AO_CMD_REG);
wait_dac_ready(iobase);
for (i = 0; i < insn->n; i++) {
val = data[i];
/* write the data to the channel */
outb(val & 0xff, iobase + PCMMIO_AO_LSB_REG);
outb((val >> 8) & 0xff, iobase + PCMMIO_AO_MSB_REG);
outb(cmd | PCMMIO_AO_CMD_WR_CODE_UPDATE,
iobase + PCMMIO_AO_CMD_REG);
wait_dac_ready(iobase);
devpriv->ao_readback[chan] = val;
}
}
return n;
return insn->n;
}
static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
@ -996,11 +1017,12 @@ static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
s->n_chan = 8;
s->len_chanlist = s->n_chan;
s->insn_read = ao_rinsn;
s->insn_write = ao_winsn;
s->insn_write = pcmmio_ao_insn_write;
/* initialize the resource enable register by clearing it */
outb(0, dev->iobase + 8 + 3);
outb(0, dev->iobase + 8 + 4 + 3);
outb(0, dev->iobase + PCMMIO_AO_RESOURCE_ENA_REG);
outb(0, dev->iobase + PCMMIO_AO_2ND_DAC_OFFSET +
PCMMIO_AO_RESOURCE_ENA_REG);
port = 0;
asic = 0;