From c7549d770a27cbdb521ea9ed646c1fc242d77a0a Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Wed, 25 Feb 2015 16:28:39 -0700 Subject: [PATCH] staging: comedi: cb_pcimdas: support analog input programmable ranges The hardware uses a switch on the board to select if the analog inputs are bipolar or uinipolar. The gain is programmable to allow the following input ranges: Gain Bipolar Unipolar 0 +/-10V 0 to 10V 1 +/-5V 0 to 5V 2 +/-2.5V 0 to 2.5V 3 +/-1.25V 0 to 1.25V Add the necessary code to the driver to allow the user to select the desired range. Signed-off-by: H Hartley Sweeten Reviewed-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/cb_pcimdas.c | 42 +++++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/drivers/staging/comedi/drivers/cb_pcimdas.c b/drivers/staging/comedi/drivers/cb_pcimdas.c index ddaa61c1cc31..5d08ca439bc9 100644 --- a/drivers/staging/comedi/drivers/cb_pcimdas.c +++ b/drivers/staging/comedi/drivers/cb_pcimdas.c @@ -74,6 +74,24 @@ #define RESID_COUNT_H 13 #define RESID_COUNT_L 14 +static const struct comedi_lrange cb_pcimdas_ai_bip_range = { + 4, { + BIP_RANGE(10), + BIP_RANGE(5), + BIP_RANGE(2.5), + BIP_RANGE(1.25) + } +}; + +static const struct comedi_lrange cb_pcimdas_ai_uni_range = { + 4, { + UNI_RANGE(10), + UNI_RANGE(5), + UNI_RANGE(2.5), + UNI_RANGE(1.25) + } +}; + /* * this structure is for data unique to this hardware driver. If * several hardware drivers keep similar information in this structure, @@ -105,9 +123,10 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev, struct comedi_insn *insn, unsigned int *data) { struct cb_pcimdas_private *devpriv = dev->private; + unsigned int chan = CR_CHAN(insn->chanspec); + unsigned int range = CR_RANGE(insn->chanspec); int n; unsigned int d; - int chan = CR_CHAN(insn->chanspec); unsigned short chanlims; int ret; @@ -123,8 +142,8 @@ static int cb_pcimdas_ai_rinsn(struct comedi_device *dev, /* set bursting off, conversions on */ outb(0x01, devpriv->BADR3 + 6); - /* set range to 10V. UP/BP is controlled by a switch on the board */ - outb(0x00, devpriv->BADR3 + 7); + /* set range */ + outb(range, devpriv->BADR3 + 7); /* * write channel limits to multiplexer, set Low (bits 0-3) and @@ -185,6 +204,20 @@ static bool cb_pcimdas_is_ai_se(struct comedi_device *dev) return status & 0x20; } +static bool cb_pcimdas_is_ai_uni(struct comedi_device *dev) +{ + struct cb_pcimdas_private *devpriv = dev->private; + unsigned int status; + + /* + * The Analog Input range polarity is set with the + * Analog Input Polarity Switch on the board. The + * inputs can be set to Unipolar or Bipolar ranges. + */ + status = inb(devpriv->BADR3 + 2); + return status & 0x40; +} + static int cb_pcimdas_auto_attach(struct comedi_device *dev, unsigned long context_unused) { @@ -222,7 +255,8 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev, s->n_chan = 8; } s->maxdata = 0xffff; - s->range_table = &range_unknown; + s->range_table = cb_pcimdas_is_ai_uni(dev) ? &cb_pcimdas_ai_uni_range + : &cb_pcimdas_ai_bip_range; s->len_chanlist = 1; /* This is the maximum chanlist length that */ /* the board can handle */ s->insn_read = cb_pcimdas_ai_rinsn; -- 2.34.1