[PATCH 09/11] staging: comedi: pcmad: properly handle analog input encoding configuration

H Hartley Sweeten hsweeten at visionengravers.com
Wed Jun 5 22:38:37 UTC 2013


The comedi_config utility is used to attach to this board. One of the
configuration options passed by the user sets the analog input encoding
for straight binary or two's complement data. The hardware produces
straight binary data when jumpered for 5V unipolar inputs and two's
complement data when jumpered for +-10V bipolar inputs.

Use the configuration option to correctly set the comedi_subdevice
range_table.

We can then use a helper function to determine what the range is when
reading the analog inputs. This allows removing the 'twos_comp' variable
from the private data (which was actually never used).

Since the private data is now empty, remove it completely.

Signed-off-by: H Hartley Sweeten <hsweeten at visionengravers.com>
Cc: Ian Abbott <abbotti at mev.co.uk>
Cc: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
---
 drivers/staging/comedi/drivers/pcmad.c | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/comedi/drivers/pcmad.c b/drivers/staging/comedi/drivers/pcmad.c
index 86597fc..8028e47 100644
--- a/drivers/staging/comedi/drivers/pcmad.c
+++ b/drivers/staging/comedi/drivers/pcmad.c
@@ -34,8 +34,8 @@
  *	   0 = single-ended (16 channels)
  *	   1 = differential (8 channels)
  *   [3] - Analog input encoding (must match jumpers)
- *	   0 = straight binary
- *	   1 = two's complement
+ *	   0 = straight binary (0-5V input range)
+ *	   1 = two's complement (+-10V input range)
  */
 
 #include <linux/interrupt.h>
@@ -63,10 +63,6 @@ static const struct pcmad_board_struct pcmad_boards[] = {
 	},
 };
 
-struct pcmad_priv_struct {
-	int twos_comp;
-};
-
 #define TIMEOUT	100
 
 static int pcmad_ai_wait_for_eoc(struct comedi_device *dev,
@@ -81,13 +77,19 @@ static int pcmad_ai_wait_for_eoc(struct comedi_device *dev,
 	return -ETIME;
 }
 
+static bool pcmad_range_is_bipolar(struct comedi_subdevice *s,
+				   unsigned int range)
+{
+	return s->range_table->range[range].min < 0;
+}
+
 static int pcmad_ai_insn_read(struct comedi_device *dev,
 			      struct comedi_subdevice *s,
 			      struct comedi_insn *insn,
 			      unsigned int *data)
 {
-	struct pcmad_priv_struct *devpriv = dev->private;
 	unsigned int chan = CR_CHAN(insn->chanspec);
+	unsigned int range = CR_RANGE(insn->chanspec);
 	unsigned int val;
 	int ret;
 	int i;
@@ -102,8 +104,10 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
 		val = inb(dev->iobase + PCMAD_LSB) |
 		      (inb(dev->iobase + PCMAD_MSB) << 8);
 
-		if (devpriv->twos_comp)
+		if (pcmad_range_is_bipolar(s, range)) {
+			/* munge the two's complement value */
 			val ^= ((s->maxdata + 1) >> 1);
+		}
 
 		data[i] = val;
 	}
@@ -114,7 +118,6 @@ static int pcmad_ai_insn_read(struct comedi_device *dev,
 static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
 	const struct pcmad_board_struct *board = comedi_board(dev);
-	struct pcmad_priv_struct *devpriv;
 	struct comedi_subdevice *s;
 	int ret;
 
@@ -126,11 +129,6 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	if (ret)
 		return ret;
 
-	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
-	if (!devpriv)
-		return -ENOMEM;
-	dev->private = devpriv;
-
 	s = &dev->subdevices[0];
 	s->type		= COMEDI_SUBD_AI;
 	if (it->options[1]) {
@@ -144,7 +142,7 @@ static int pcmad_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 	}
 	s->len_chanlist	= 1;
 	s->maxdata	= board->ai_maxdata;
-	s->range_table	= &range_unknown;
+	s->range_table	= it->options[2] ? &range_bipolar10 : &range_unipolar5;
 	s->insn_read	= pcmad_ai_insn_read;
 
 	return 0;
-- 
1.8.1.4




More information about the devel mailing list