]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/comedi/drivers/dyna_pci10xx.c
staging: comedi: dyna_pci10xx: Set number of AO channels to 1
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / comedi / drivers / dyna_pci10xx.c
CommitLineData
e184e2be 1// SPDX-License-Identifier: GPL-2.0+
16a7373a
PS
2/*
3 * comedi/drivers/dyna_pci10xx.c
4 * Copyright (C) 2011 Prashant Shah, pshah.mumbai@gmail.com
16a7373a
PS
5 */
6
7/*
f94a8c87
IA
8 * Driver: dyna_pci10xx
9 * Description: Dynalog India PCI DAQ Cards, http://www.dynalogindia.com/
10 * Devices: [Dynalog] PCI-1050 (dyna_pci1050)
11 * Author: Prashant Shah <pshah.mumbai@gmail.com>
12 * Status: Stable
13 *
14 * Developed at Automation Labs, Chemical Dept., IIT Bombay, India.
15 * Prof. Kannan Moudgalya <kannan@iitb.ac.in>
16 * http://www.iitb.ac.in
17 *
18 * Notes :
19 * - Dynalog India Pvt. Ltd. does not have a registered PCI Vendor ID and
20 * they are using the PLX Technlogies Vendor ID since that is the PCI Chip
21 * used in the card.
22 * - Dynalog India Pvt. Ltd. has provided the internal register specification
23 * for their cards in their manuals.
24 */
16a7373a 25
ce157f80
HS
26#include <linux/module.h>
27#include <linux/delay.h>
16a7373a
PS
28#include <linux/mutex.h>
29
5ca7653e 30#include "../comedi_pci.h"
33782dd5 31
16a7373a
PS
32#define READ_TIMEOUT 50
33
eff3689b
HS
34static const struct comedi_lrange range_pci1050_ai = {
35 3, {
36 BIP_RANGE(10),
37 BIP_RANGE(5),
38 UNI_RANGE(10)
39 }
16a7373a
PS
40};
41
42static const char range_codes_pci1050_ai[] = { 0x00, 0x10, 0x30 };
43
16a7373a 44struct dyna_pci10xx_private {
16a7373a 45 struct mutex mutex;
b694c4f4 46 unsigned long BADR3;
16a7373a
PS
47};
48
443e6d02
HS
49static int dyna_pci10xx_ai_eoc(struct comedi_device *dev,
50 struct comedi_subdevice *s,
51 struct comedi_insn *insn,
52 unsigned long context)
53{
54 unsigned int status;
55
56 status = inw_p(dev->iobase);
557e3619 57 if (status & BIT(15))
443e6d02
HS
58 return 0;
59 return -EBUSY;
60}
16a7373a 61
16a7373a 62static int dyna_pci10xx_insn_read_ai(struct comedi_device *dev,
6c7d2c8b
HS
63 struct comedi_subdevice *s,
64 struct comedi_insn *insn,
65 unsigned int *data)
16a7373a 66{
af0677c1 67 struct dyna_pci10xx_private *devpriv = dev->private;
443e6d02 68 int n;
16a7373a 69 u16 d = 0;
443e6d02 70 int ret = 0;
16a7373a
PS
71 unsigned int chan, range;
72
73 /* get the channel number and range */
74 chan = CR_CHAN(insn->chanspec);
8fda437d 75 range = range_codes_pci1050_ai[CR_RANGE((insn->chanspec))];
16a7373a
PS
76
77 mutex_lock(&devpriv->mutex);
78 /* convert n samples */
79 for (n = 0; n < insn->n; n++) {
80 /* trigger conversion */
81 smp_mb();
b694c4f4 82 outw_p(0x0000 + range + chan, dev->iobase + 2);
e1ea433d 83 usleep_range(10, 20);
16a7373a 84
443e6d02 85 ret = comedi_timeout(dev, s, insn, dyna_pci10xx_ai_eoc, 0);
dbd446fc 86 if (ret)
443e6d02 87 break;
443e6d02
HS
88
89 /* read data */
90 d = inw_p(dev->iobase);
16a7373a
PS
91 /* mask the first 4 bits - EOC bits */
92 d &= 0x0FFF;
93 data[n] = d;
94 }
95 mutex_unlock(&devpriv->mutex);
96
97 /* return the number of samples read/written */
443e6d02 98 return ret ? ret : n;
16a7373a
PS
99}
100
101/* analog output callback */
102static int dyna_pci10xx_insn_write_ao(struct comedi_device *dev,
6c7d2c8b
HS
103 struct comedi_subdevice *s,
104 struct comedi_insn *insn,
105 unsigned int *data)
16a7373a 106{
af0677c1 107 struct dyna_pci10xx_private *devpriv = dev->private;
16a7373a 108 int n;
16a7373a
PS
109
110 mutex_lock(&devpriv->mutex);
111 for (n = 0; n < insn->n; n++) {
112 smp_mb();
113 /* trigger conversion and write data */
b694c4f4 114 outw_p(data[n], dev->iobase);
e1ea433d 115 usleep_range(10, 20);
16a7373a
PS
116 }
117 mutex_unlock(&devpriv->mutex);
118 return n;
119}
120
121/* digital input bit interface */
122static int dyna_pci10xx_di_insn_bits(struct comedi_device *dev,
6c7d2c8b
HS
123 struct comedi_subdevice *s,
124 struct comedi_insn *insn,
125 unsigned int *data)
16a7373a 126{
af0677c1 127 struct dyna_pci10xx_private *devpriv = dev->private;
16a7373a
PS
128 u16 d = 0;
129
16a7373a
PS
130 mutex_lock(&devpriv->mutex);
131 smp_mb();
132 d = inw_p(devpriv->BADR3);
e1ea433d 133 usleep_range(10, 100);
16a7373a
PS
134
135 /* on return the data[0] contains output and data[1] contains input */
136 data[1] = d;
137 data[0] = s->state;
138 mutex_unlock(&devpriv->mutex);
a2714e3e 139 return insn->n;
16a7373a
PS
140}
141
16a7373a 142static int dyna_pci10xx_do_insn_bits(struct comedi_device *dev,
97f4289a
HS
143 struct comedi_subdevice *s,
144 struct comedi_insn *insn,
145 unsigned int *data)
16a7373a 146{
af0677c1
HS
147 struct dyna_pci10xx_private *devpriv = dev->private;
148
16a7373a 149 mutex_lock(&devpriv->mutex);
97f4289a 150 if (comedi_dio_update_state(s, data)) {
16a7373a
PS
151 smp_mb();
152 outw_p(s->state, devpriv->BADR3);
e1ea433d 153 usleep_range(10, 100);
16a7373a
PS
154 }
155
16a7373a
PS
156 data[1] = s->state;
157 mutex_unlock(&devpriv->mutex);
97f4289a 158
a2714e3e 159 return insn->n;
16a7373a
PS
160}
161
a690b7e5 162static int dyna_pci10xx_auto_attach(struct comedi_device *dev,
6c7d2c8b 163 unsigned long context_unused)
1f20b973 164{
750af5e5 165 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
af0677c1 166 struct dyna_pci10xx_private *devpriv;
1f20b973
HS
167 struct comedi_subdevice *s;
168 int ret;
169
0bdab509 170 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
c34fa261
HS
171 if (!devpriv)
172 return -ENOMEM;
16a7373a 173
818f569f 174 ret = comedi_pci_enable(dev);
690e839f
HS
175 if (ret)
176 return ret;
b694c4f4 177 dev->iobase = pci_resource_start(pcidev, 2);
16a7373a 178 devpriv->BADR3 = pci_resource_start(pcidev, 3);
16a7373a 179
690e839f
HS
180 mutex_init(&devpriv->mutex);
181
8b6c5694 182 ret = comedi_alloc_subdevices(dev, 4);
6bdae560 183 if (ret)
8b6c5694 184 return ret;
16a7373a
PS
185
186 /* analog input */
1b39406b 187 s = &dev->subdevices[0];
16a7373a
PS
188 s->type = COMEDI_SUBD_AI;
189 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
8fda437d 190 s->n_chan = 16;
16a7373a 191 s->maxdata = 0x0FFF;
8fda437d 192 s->range_table = &range_pci1050_ai;
16a7373a
PS
193 s->insn_read = dyna_pci10xx_insn_read_ai;
194
195 /* analog output */
1b39406b 196 s = &dev->subdevices[1];
16a7373a
PS
197 s->type = COMEDI_SUBD_AO;
198 s->subdev_flags = SDF_WRITABLE;
6229fed9 199 s->n_chan = 1;
16a7373a 200 s->maxdata = 0x0FFF;
f2eacff1 201 s->range_table = &range_unipolar10;
16a7373a
PS
202 s->insn_write = dyna_pci10xx_insn_write_ao;
203
204 /* digital input */
1b39406b 205 s = &dev->subdevices[2];
16a7373a 206 s->type = COMEDI_SUBD_DI;
e0025918 207 s->subdev_flags = SDF_READABLE;
8fda437d 208 s->n_chan = 16;
16a7373a
PS
209 s->maxdata = 1;
210 s->range_table = &range_digital;
16a7373a
PS
211 s->insn_bits = dyna_pci10xx_di_insn_bits;
212
213 /* digital output */
1b39406b 214 s = &dev->subdevices[3];
16a7373a 215 s->type = COMEDI_SUBD_DO;
e0025918 216 s->subdev_flags = SDF_WRITABLE;
8fda437d 217 s->n_chan = 16;
16a7373a
PS
218 s->maxdata = 1;
219 s->range_table = &range_digital;
16a7373a
PS
220 s->state = 0;
221 s->insn_bits = dyna_pci10xx_do_insn_bits;
222
690e839f
HS
223 return 0;
224}
225
484ecc95 226static void dyna_pci10xx_detach(struct comedi_device *dev)
16a7373a 227{
af0677c1 228 struct dyna_pci10xx_private *devpriv = dev->private;
06183026 229
aac307f9 230 comedi_pci_detach(dev);
06183026 231 if (devpriv)
16a7373a 232 mutex_destroy(&devpriv->mutex);
16a7373a
PS
233}
234
75e6301b
HS
235static struct comedi_driver dyna_pci10xx_driver = {
236 .driver_name = "dyna_pci10xx",
de9f2db4 237 .module = THIS_MODULE,
750af5e5 238 .auto_attach = dyna_pci10xx_auto_attach,
de9f2db4 239 .detach = dyna_pci10xx_detach,
de9f2db4
HS
240};
241
a690b7e5 242static int dyna_pci10xx_pci_probe(struct pci_dev *dev,
b8f4ac23 243 const struct pci_device_id *id)
16a7373a 244{
b8f4ac23
HS
245 return comedi_pci_auto_config(dev, &dyna_pci10xx_driver,
246 id->driver_data);
16a7373a
PS
247}
248
41e043fc 249static const struct pci_device_id dyna_pci10xx_pci_table[] = {
00f5c774 250 { PCI_DEVICE(PCI_VENDOR_ID_PLX, 0x1050) },
de9f2db4
HS
251 { 0 }
252};
253MODULE_DEVICE_TABLE(pci, dyna_pci10xx_pci_table);
254
75e6301b
HS
255static struct pci_driver dyna_pci10xx_pci_driver = {
256 .name = "dyna_pci10xx",
de9f2db4 257 .id_table = dyna_pci10xx_pci_table,
75e6301b 258 .probe = dyna_pci10xx_pci_probe,
9901a4d7 259 .remove = comedi_pci_auto_unconfig,
16a7373a 260};
75e6301b 261module_comedi_pci_driver(dyna_pci10xx_driver, dyna_pci10xx_pci_driver);
16a7373a
PS
262
263MODULE_LICENSE("GPL");
264MODULE_AUTHOR("Prashant Shah <pshah.mumbai@gmail.com>");
265MODULE_DESCRIPTION("Comedi based drivers for Dynalog PCI DAQ cards");