X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=drivers%2Fstaging%2Fcomedi%2Fdrivers%2Fcb_pcidas.c;h=86e3d200bb216f2fd914ff1323342837bef91115;hb=a1c76758987eac334a7dffcb0b50e597da4ded77;hp=1c38cd5f846c2595a32c16af82836d133846a6c6;hpb=c39e050d21d107d26183be0f22b89eccccdbe61c;p=cascardo%2Flinux.git diff --git a/drivers/staging/comedi/drivers/cb_pcidas.c b/drivers/staging/comedi/drivers/cb_pcidas.c index 1c38cd5f846c..86e3d200bb21 100644 --- a/drivers/staging/comedi/drivers/cb_pcidas.c +++ b/drivers/staging/comedi/drivers/cb_pcidas.c @@ -346,8 +346,6 @@ struct cb_pcidas_private { /* divisors of master clock for analog input pacing */ unsigned int divisor1; unsigned int divisor2; - /* number of analog input samples remaining */ - unsigned int count; /* bits to write to registers */ unsigned int adc_fifo_bits; unsigned int s5933_intcsr_bits; @@ -358,10 +356,6 @@ struct cb_pcidas_private { /* divisors of master clock for analog output pacing */ unsigned int ao_divisor1; unsigned int ao_divisor2; - /* number of analog output samples remaining */ - unsigned int ao_count; - unsigned int caldac_value[NUM_CHANNELS_8800]; - unsigned int trimpot_value[NUM_CHANNELS_8402]; unsigned int dac08_value; unsigned int calibration_source; }; @@ -596,25 +590,14 @@ static void write_calibration_bitstream(struct comedi_device *dev, } } -static int caldac_8800_write(struct comedi_device *dev, unsigned int address, - uint8_t value) +static void caldac_8800_write(struct comedi_device *dev, + unsigned int chan, uint8_t val) { struct cb_pcidas_private *devpriv = dev->private; - static const int num_caldac_channels = 8; static const int bitstream_length = 11; - unsigned int bitstream = ((address & 0x7) << 8) | value; + unsigned int bitstream = ((chan & 0x7) << 8) | val; static const int caldac_8800_udelay = 1; - if (address >= num_caldac_channels) { - dev_err(dev->class_dev, "illegal caldac channel\n"); - return -1; - } - - if (value == devpriv->caldac_value[address]) - return 1; - - devpriv->caldac_value[address] = value; - write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream, bitstream_length); @@ -623,28 +606,25 @@ static int caldac_8800_write(struct comedi_device *dev, unsigned int address, devpriv->control_status + CALIBRATION_REG); udelay(caldac_8800_udelay); outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG); - - return 1; } -static int caldac_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int cb_pcidas_caldac_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - const unsigned int channel = CR_CHAN(insn->chanspec); - - return caldac_8800_write(dev, channel, data[0]); -} + unsigned int chan = CR_CHAN(insn->chanspec); -static int caldac_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct cb_pcidas_private *devpriv = dev->private; + if (insn->n) { + unsigned int val = data[insn->n - 1]; - data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)]; + if (s->readback[chan] != val) { + caldac_8800_write(dev, chan, val); + s->readback[chan] = val; + } + } - return 1; + return insn->n; } /* 1602/16 pregain offset */ @@ -740,50 +720,41 @@ static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel, return 0; } -static int cb_pcidas_trimpot_write(struct comedi_device *dev, - unsigned int channel, unsigned int value) +static void cb_pcidas_trimpot_write(struct comedi_device *dev, + unsigned int chan, unsigned int val) { const struct cb_pcidas_board *thisboard = dev->board_ptr; - struct cb_pcidas_private *devpriv = dev->private; - - if (devpriv->trimpot_value[channel] == value) - return 1; - devpriv->trimpot_value[channel] = value; switch (thisboard->trimpot) { case AD7376: - trimpot_7376_write(dev, value); + trimpot_7376_write(dev, val); break; case AD8402: - trimpot_8402_write(dev, channel, value); + trimpot_8402_write(dev, chan, val); break; default: dev_err(dev->class_dev, "driver bug?\n"); - return -1; + break; } - - return 1; } -static int trimpot_write_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) +static int cb_pcidas_trimpot_insn_write(struct comedi_device *dev, + struct comedi_subdevice *s, + struct comedi_insn *insn, + unsigned int *data) { - unsigned int channel = CR_CHAN(insn->chanspec); + unsigned int chan = CR_CHAN(insn->chanspec); - return cb_pcidas_trimpot_write(dev, channel, data[0]); -} + if (insn->n) { + unsigned int val = data[insn->n - 1]; -static int trimpot_read_insn(struct comedi_device *dev, - struct comedi_subdevice *s, - struct comedi_insn *insn, unsigned int *data) -{ - struct cb_pcidas_private *devpriv = dev->private; - unsigned int channel = CR_CHAN(insn->chanspec); - - data[0] = devpriv->trimpot_value[channel]; + if (s->readback[chan] != val) { + cb_pcidas_trimpot_write(dev, chan, val); + s->readback[chan] = val; + } + } - return 1; + return insn->n; } static int cb_pcidas_ai_check_chanlist(struct comedi_device *dev, @@ -976,9 +947,6 @@ static int cb_pcidas_ai_cmd(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER || cmd->convert_src == TRIG_TIMER) cb_pcidas_ai_load_counters(dev); - /* set number of conversions */ - if (cmd->stop_src == TRIG_COUNT) - devpriv->count = cmd->chanlist_len * cmd->stop_arg; /* enable interrupts */ spin_lock_irqsave(&dev->spinlock, flags); devpriv->adc_fifo_bits |= INTE; @@ -1139,17 +1107,12 @@ static void cb_pcidas_ao_load_fifo(struct comedi_device *dev, unsigned int nsamples) { struct cb_pcidas_private *devpriv = dev->private; - struct comedi_cmd *cmd = &s->async->cmd; unsigned int nbytes; - if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < nsamples) - nsamples = devpriv->ao_count; - + nsamples = comedi_nsamples_left(s, nsamples); nbytes = comedi_buf_read_samples(s, devpriv->ao_buffer, nsamples); - nsamples = comedi_bytes_to_samples(s, nbytes); - if (cmd->stop_src == TRIG_COUNT) - devpriv->ao_count -= nsamples; + nsamples = comedi_bytes_to_samples(s, nbytes); outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, nsamples); } @@ -1231,9 +1194,6 @@ static int cb_pcidas_ao_cmd(struct comedi_device *dev, if (cmd->scan_begin_src == TRIG_TIMER) cb_pcidas_ao_load_counters(dev); - /* set number of conversions */ - if (cmd->stop_src == TRIG_COUNT) - devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg; /* set pacer source */ spin_lock_irqsave(&dev->spinlock, flags); switch (cmd->scan_begin_src) { @@ -1291,13 +1251,13 @@ static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status) devpriv->control_status + INT_ADCFIFO); spin_unlock_irqrestore(&dev->spinlock, flags); if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) { - if (cmd->stop_src == TRIG_NONE || - (cmd->stop_src == TRIG_COUNT - && devpriv->ao_count)) { + if (cmd->stop_src == TRIG_COUNT && + async->scans_done >= cmd->stop_arg) { + async->events |= COMEDI_CB_EOA; + } else { dev_err(dev->class_dev, "dac fifo underflow\n"); async->events |= COMEDI_CB_ERROR; } - async->events |= COMEDI_CB_EOA; } } else if (status & DAHFI) { cb_pcidas_ao_load_fifo(dev, s, thisboard->fifo_size / 2); @@ -1352,17 +1312,15 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) /* if fifo half-full */ if (status & ADHFI) { /* read data */ - num_samples = half_fifo; - if (cmd->stop_src == TRIG_COUNT && - num_samples > devpriv->count) { - num_samples = devpriv->count; - } + num_samples = comedi_nsamples_left(s, half_fifo); insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer, num_samples); comedi_buf_write_samples(s, devpriv->ai_buffer, num_samples); - devpriv->count -= num_samples; - if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) + + if (cmd->stop_src == TRIG_COUNT && + async->scans_done >= cmd->stop_arg) async->events |= COMEDI_CB_EOA; + /* clear half-full interrupt latch */ spin_lock_irqsave(&dev->spinlock, flags); outw(devpriv->adc_fifo_bits | INT, @@ -1379,9 +1337,9 @@ static irqreturn_t cb_pcidas_interrupt(int irq, void *d) break; val = inw(devpriv->adc_fifo); comedi_buf_write_samples(s, &val, 1); + if (cmd->stop_src == TRIG_COUNT && - --devpriv->count == 0) { - /* end of acquisition */ + async->scans_done >= cmd->stop_arg) { async->events |= COMEDI_CB_EOA; break; } @@ -1495,7 +1453,6 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, s->range_table = &cb_pcidas_ao_ranges; /* default to no fifo (*insn_write) */ s->insn_write = cb_pcidas_ao_nofifo_winsn; - s->insn_read = comedi_readback_insn_read; ret = comedi_alloc_subdev_readback(s); if (ret) @@ -1534,10 +1491,16 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; s->n_chan = NUM_CHANNELS_8800; s->maxdata = 0xff; - s->insn_read = caldac_read_insn; - s->insn_write = caldac_write_insn; - for (i = 0; i < s->n_chan; i++) + s->insn_write = cb_pcidas_caldac_insn_write; + + ret = comedi_alloc_subdev_readback(s); + if (ret) + return ret; + + for (i = 0; i < s->n_chan; i++) { caldac_8800_write(dev, i, s->maxdata / 2); + s->readback[i] = s->maxdata / 2; + } /* trim potentiometer */ s = &dev->subdevices[5]; @@ -1550,10 +1513,16 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev, s->n_chan = NUM_CHANNELS_8402; s->maxdata = 0xff; } - s->insn_read = trimpot_read_insn; - s->insn_write = trimpot_write_insn; - for (i = 0; i < s->n_chan; i++) + s->insn_write = cb_pcidas_trimpot_insn_write; + + ret = comedi_alloc_subdev_readback(s); + if (ret) + return ret; + + for (i = 0; i < s->n_chan; i++) { cb_pcidas_trimpot_write(dev, i, s->maxdata / 2); + s->readback[i] = s->maxdata / 2; + } /* dac08 caldac */ s = &dev->subdevices[6];