summaryrefslogtreecommitdiff
path: root/drivers/staging/comedi/drivers/ni_65xx.c
diff options
context:
space:
mode:
authorIan Abbott <abbotti@mev.co.uk>2014-07-23 10:41:20 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-07-24 15:01:24 -0700
commit3443d1c6d1b0914447b253e6ae0194cc9e2cf137 (patch)
treeff227777d8e2649092baca1865ad29631931dbef /drivers/staging/comedi/drivers/ni_65xx.c
parenta5e7d93da17715aacbad64951a49aadb06071a4d (diff)
staging: comedi: ni_65xx: support INSN_CONFIG_DIGITAL_TRIG
The "edge detection interrupt" subdevice supports the `INSN_CONFIG_CHANGE_NOTIFY` comedi instruction which is only supported by one other driver. It is limited to the first 32 channels, but boards supported by this driver support edge detection on all digital I/O, digital input and digital output channels. The `INSN_CONFIG_DIGITAL_TRIG` comedi instruction is more flexible as it supports more than 32 channels (with multiple instructions). It can also support level detection, but the hardware does not support that. Add partial support for the `INSN_CONFIG_DIGITAL_TRIG` instruction, but only for edge detection. Since `INSN_CONFIG_CHANGE_NOTIFY` can only deal with 32 channels, make it disable edge detection for any remaining channels. Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/comedi/drivers/ni_65xx.c')
-rw-r--r--drivers/staging/comedi/drivers/ni_65xx.c39
1 files changed, 36 insertions, 3 deletions
diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c
index f7566fe461b4..ddf9135d605c 100644
--- a/drivers/staging/comedi/drivers/ni_65xx.c
+++ b/drivers/staging/comedi/drivers/ni_65xx.c
@@ -365,6 +365,16 @@ static void ni_65xx_update_edge_detection(struct comedi_device *dev,
}
}
+static void ni_65xx_disable_edge_detection(struct comedi_device *dev)
+{
+ /* clear edge detection for channels 0 to 31 */
+ ni_65xx_update_edge_detection(dev, 0, 0, 0);
+ /* clear edge detection for channels 32 to 63 */
+ ni_65xx_update_edge_detection(dev, 32, 0, 0);
+ /* clear edge detection for channels 64 to 95 */
+ ni_65xx_update_edge_detection(dev, 64, 0, 0);
+}
+
static int ni_65xx_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn,
@@ -599,10 +609,33 @@ static int ni_65xx_intr_insn_config(struct comedi_device *dev,
if (insn->n != 3)
return -EINVAL;
- /*
- * This only works for the first 4 ports (32 channels)!
- */
+ /* update edge detection for channels 0 to 31 */
ni_65xx_update_edge_detection(dev, 0, data[1], data[2]);
+ /* clear edge detection for channels 32 to 63 */
+ ni_65xx_update_edge_detection(dev, 32, 0, 0);
+ /* clear edge detection for channels 64 to 95 */
+ ni_65xx_update_edge_detection(dev, 64, 0, 0);
+ break;
+ case INSN_CONFIG_DIGITAL_TRIG:
+ /* check trigger number */
+ if (data[1] != 0)
+ return -EINVAL;
+ /* check digital trigger operation */
+ switch (data[2]) {
+ case COMEDI_DIGITAL_TRIG_DISABLE:
+ ni_65xx_disable_edge_detection(dev);
+ break;
+ case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
+ /*
+ * update edge detection for channels data[3]
+ * to (data[3] + 31)
+ */
+ ni_65xx_update_edge_detection(dev, data[3],
+ data[4], data[5]);
+ break;
+ default:
+ return -EINVAL;
+ }
break;
default:
return -EINVAL;