in drivers/ni_mio_common.c [1703:1819]
static void ni_load_channelgain_list(struct comedi_device *dev,
struct comedi_subdevice *s,
unsigned int n_chan, unsigned int *list)
{
const struct ni_board_struct *board = dev->board_ptr;
struct ni_private *devpriv = dev->private;
unsigned int offset = (s->maxdata + 1) >> 1;
unsigned int chan, range, aref;
unsigned int i;
unsigned int hi, lo;
unsigned int dither;
if (devpriv->is_m_series) {
ni_m_series_load_channelgain_list(dev, n_chan, list);
return;
}
if (n_chan == 1 && !devpriv->is_611x && !devpriv->is_6143) {
if (devpriv->changain_state &&
devpriv->changain_spec == list[0]) {
/* ready to go. */
return;
}
devpriv->changain_state = 1;
devpriv->changain_spec = list[0];
} else {
devpriv->changain_state = 0;
}
ni_stc_writew(dev, 1, NISTC_CFG_MEM_CLR_REG);
/* Set up Calibration mode if required */
if (devpriv->is_6143) {
if ((list[0] & CR_ALT_SOURCE) &&
!devpriv->ai_calib_source_enabled) {
/* Strobe Relay enable bit */
ni_writew(dev, devpriv->ai_calib_source |
NI6143_CALIB_CHAN_RELAY_ON,
NI6143_CALIB_CHAN_REG);
ni_writew(dev, devpriv->ai_calib_source,
NI6143_CALIB_CHAN_REG);
devpriv->ai_calib_source_enabled = 1;
/* Allow relays to change */
msleep_interruptible(100);
} else if (!(list[0] & CR_ALT_SOURCE) &&
devpriv->ai_calib_source_enabled) {
/* Strobe Relay disable bit */
ni_writew(dev, devpriv->ai_calib_source |
NI6143_CALIB_CHAN_RELAY_OFF,
NI6143_CALIB_CHAN_REG);
ni_writew(dev, devpriv->ai_calib_source,
NI6143_CALIB_CHAN_REG);
devpriv->ai_calib_source_enabled = 0;
/* Allow relays to change */
msleep_interruptible(100);
}
}
for (i = 0; i < n_chan; i++) {
if (!devpriv->is_6143 && (list[i] & CR_ALT_SOURCE))
chan = devpriv->ai_calib_source;
else
chan = CR_CHAN(list[i]);
aref = CR_AREF(list[i]);
range = CR_RANGE(list[i]);
dither = (list[i] & CR_ALT_FILTER) != 0;
/* fix the external/internal range differences */
range = ni_gainlkup[board->gainlkup][range];
if (devpriv->is_611x)
devpriv->ai_offset[i] = offset;
else
devpriv->ai_offset[i] = (range & 0x100) ? 0 : offset;
hi = 0;
if ((list[i] & CR_ALT_SOURCE)) {
if (devpriv->is_611x)
ni_writew(dev, CR_CHAN(list[i]) & 0x0003,
NI611X_CALIB_CHAN_SEL_REG);
} else {
if (devpriv->is_611x)
aref = AREF_DIFF;
else if (devpriv->is_6143)
aref = AREF_OTHER;
switch (aref) {
case AREF_DIFF:
hi |= NI_E_AI_CFG_HI_TYPE_DIFF;
break;
case AREF_COMMON:
hi |= NI_E_AI_CFG_HI_TYPE_COMMON;
break;
case AREF_GROUND:
hi |= NI_E_AI_CFG_HI_TYPE_GROUND;
break;
case AREF_OTHER:
break;
}
}
hi |= NI_E_AI_CFG_HI_CHAN(chan);
ni_writew(dev, hi, NI_E_AI_CFG_HI_REG);
if (!devpriv->is_6143) {
lo = NI_E_AI_CFG_LO_GAIN(range);
if (i == n_chan - 1)
lo |= NI_E_AI_CFG_LO_LAST_CHAN;
if (dither)
lo |= NI_E_AI_CFG_LO_DITHER;
ni_writew(dev, lo, NI_E_AI_CFG_LO_REG);
}
}
/* prime the channel/gain list */
if (!devpriv->is_611x && !devpriv->is_6143)
ni_prime_channelgain_list(dev);
}