Merge branch 'lpc32xx/dts' of git://git.antcom.de/linux-2.6 into next/dt
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / comedi / drivers / cb_pcidda.c
1 /*
2     comedi/drivers/cb_pcidda.c
3     This intends to be a driver for the ComputerBoards / MeasurementComputing
4     PCI-DDA series.
5
6          Copyright (C) 2001 Ivan Martinez <ivanmr@altavista.com>
7     Copyright (C) 2001 Frank Mori Hess <fmhess@users.sourceforge.net>
8
9     COMEDI - Linux Control and Measurement Device Interface
10     Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
11
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; either version 2 of the License, or
15     (at your option) any later version.
16
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20     GNU General Public License for more details.
21
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 */
27 /*
28 Driver: cb_pcidda
29 Description: MeasurementComputing PCI-DDA series
30 Author: Ivan Martinez <ivanmr@altavista.com>, Frank Mori Hess <fmhess@users.sourceforge.net>
31 Status: Supports 08/16, 04/16, 02/16, 08/12, 04/12, and 02/12
32 Devices: [Measurement Computing] PCI-DDA08/12 (cb_pcidda), PCI-DDA04/12,
33   PCI-DDA02/12, PCI-DDA08/16, PCI-DDA04/16, PCI-DDA02/16
34
35 Configuration options:
36   [0] - PCI bus of device (optional)
37   [1] - PCI slot of device (optional)
38   If bus/slot is not specified, the first available PCI
39   device will be used.
40
41 Only simple analog output writing is supported.
42
43 So far it has only been tested with:
44   - PCI-DDA08/12
45 Please report success/failure with other different cards to
46 <comedi@comedi.org>.
47 */
48
49 #include "../comedidev.h"
50
51 #include "8255.h"
52
53 /* PCI vendor number of ComputerBoards */
54 #define PCI_VENDOR_ID_CB        0x1307
55 #define EEPROM_SIZE     128     /*  number of entries in eeprom */
56 /* maximum number of ao channels for supported boards */
57 #define MAX_AO_CHANNELS 8
58
59 /* PCI-DDA base addresses */
60 #define DIGITALIO_BADRINDEX     2
61         /*  DIGITAL I/O is pci_dev->resource[2] */
62 #define DIGITALIO_SIZE 8
63         /*  DIGITAL I/O uses 8 I/O port addresses */
64 #define DAC_BADRINDEX   3
65         /*  DAC is pci_dev->resource[3] */
66
67 /* Digital I/O registers */
68 #define PORT1A 0                /*  PORT 1A DATA */
69
70 #define PORT1B 1                /*  PORT 1B DATA */
71
72 #define PORT1C 2                /*  PORT 1C DATA */
73
74 #define CONTROL1 3              /*  CONTROL REGISTER 1 */
75
76 #define PORT2A 4                /*  PORT 2A DATA */
77
78 #define PORT2B 5                /*  PORT 2B DATA */
79
80 #define PORT2C 6                /*  PORT 2C DATA */
81
82 #define CONTROL2 7              /*  CONTROL REGISTER 2 */
83
84 /* DAC registers */
85 #define DACONTROL       0       /*  D/A CONTROL REGISTER */
86 #define SU      0000001         /*  Simultaneous update enabled */
87 #define NOSU    0000000         /*  Simultaneous update disabled */
88 #define ENABLEDAC       0000002 /*  Enable specified DAC */
89 #define DISABLEDAC      0000000 /*  Disable specified DAC */
90 #define RANGE2V5        0000000 /*  2.5V */
91 #define RANGE5V 0000200         /*  5V */
92 #define RANGE10V        0000300 /*  10V */
93 #define UNIP    0000400         /*  Unipolar outputs */
94 #define BIP     0000000         /*  Bipolar outputs */
95
96 #define DACALIBRATION1  4       /*  D/A CALIBRATION REGISTER 1 */
97 /* write bits */
98 /* serial data input for eeprom, caldacs, reference dac */
99 #define SERIAL_IN_BIT   0x1
100 #define CAL_CHANNEL_MASK        (0x7 << 1)
101 #define CAL_CHANNEL_BITS(channel)       (((channel) << 1) & CAL_CHANNEL_MASK)
102 /* read bits */
103 #define CAL_COUNTER_MASK        0x1f
104 /* calibration counter overflow status bit */
105 #define CAL_COUNTER_OVERFLOW_BIT        0x20
106 /* analog output is less than reference dac voltage */
107 #define AO_BELOW_REF_BIT        0x40
108 #define SERIAL_OUT_BIT  0x80    /*  serial data out, for reading from eeprom */
109
110 #define DACALIBRATION2  6       /*  D/A CALIBRATION REGISTER 2 */
111 #define SELECT_EEPROM_BIT       0x1     /*  send serial data in to eeprom */
112 /* don't send serial data to MAX542 reference dac */
113 #define DESELECT_REF_DAC_BIT    0x2
114 /* don't send serial data to caldac n */
115 #define DESELECT_CALDAC_BIT(n)  (0x4 << (n))
116 /* manual says to set this bit with no explanation */
117 #define DUMMY_BIT       0x40
118
119 #define DADATA  8               /*  FIRST D/A DATA REGISTER (0) */
120
121 static const struct comedi_lrange cb_pcidda_ranges = {
122         6,
123         {
124          BIP_RANGE(10),
125          BIP_RANGE(5),
126          BIP_RANGE(2.5),
127          UNI_RANGE(10),
128          UNI_RANGE(5),
129          UNI_RANGE(2.5),
130          }
131 };
132
133 /*
134  * Board descriptions for two imaginary boards.  Describing the
135  * boards in this way is optional, and completely driver-dependent.
136  * Some drivers use arrays such as this, other do not.
137  */
138 struct cb_pcidda_board {
139         const char *name;
140         char status;            /*  Driver status: */
141
142         /*
143          * 0 - tested
144          * 1 - manual read, not tested
145          * 2 - manual not read
146          */
147
148         unsigned short device_id;
149         int ao_chans;
150         int ao_bits;
151         const struct comedi_lrange *ranges;
152 };
153
154 static const struct cb_pcidda_board cb_pcidda_boards[] = {
155         {
156          .name = "pci-dda02/12",
157          .status = 1,
158          .device_id = 0x20,
159          .ao_chans = 2,
160          .ao_bits = 12,
161          .ranges = &cb_pcidda_ranges,
162          },
163         {
164          .name = "pci-dda04/12",
165          .status = 1,
166          .device_id = 0x21,
167          .ao_chans = 4,
168          .ao_bits = 12,
169          .ranges = &cb_pcidda_ranges,
170          },
171         {
172          .name = "pci-dda08/12",
173          .status = 0,
174          .device_id = 0x22,
175          .ao_chans = 8,
176          .ao_bits = 12,
177          .ranges = &cb_pcidda_ranges,
178          },
179         {
180          .name = "pci-dda02/16",
181          .status = 2,
182          .device_id = 0x23,
183          .ao_chans = 2,
184          .ao_bits = 16,
185          .ranges = &cb_pcidda_ranges,
186          },
187         {
188          .name = "pci-dda04/16",
189          .status = 2,
190          .device_id = 0x24,
191          .ao_chans = 4,
192          .ao_bits = 16,
193          .ranges = &cb_pcidda_ranges,
194          },
195         {
196          .name = "pci-dda08/16",
197          .status = 0,
198          .device_id = 0x25,
199          .ao_chans = 8,
200          .ao_bits = 16,
201          .ranges = &cb_pcidda_ranges,
202          },
203 };
204
205 /*
206  * Useful for shorthand access to the particular board structure
207  */
208 #define thisboard ((const struct cb_pcidda_board *)dev->board_ptr)
209
210 /*
211  * this structure is for data unique to this hardware driver.  If
212  * several hardware drivers keep similar information in this structure,
213  * feel free to suggest moving the variable to the struct comedi_device
214  * struct.
215  */
216 struct cb_pcidda_private {
217         int data;
218
219         unsigned long digitalio;
220         unsigned long dac;
221
222         /* unsigned long control_status; */
223         /* unsigned long adc_fifo; */
224
225         /* bits last written to da calibration register 1 */
226         unsigned int dac_cal1_bits;
227         /* current range settings for output channels */
228         unsigned int ao_range[MAX_AO_CHANNELS];
229         u16 eeprom_data[EEPROM_SIZE];   /*  software copy of board's eeprom */
230 };
231
232 /*
233  * most drivers define the following macro to make it easy to
234  * access the private structure.
235  */
236 #define devpriv ((struct cb_pcidda_private *)dev->private)
237
238 /* static int cb_pcidda_ai_rinsn(struct comedi_device *dev,struct comedi_subdevice *s,struct comedi_insn *insn,unsigned int *data); */
239 static int cb_pcidda_ao_winsn(struct comedi_device *dev,
240                               struct comedi_subdevice *s,
241                               struct comedi_insn *insn, unsigned int *data);
242
243 /* static int cb_pcidda_ai_cmd(struct comedi_device *dev, struct *comedi_subdevice *s);*/
244 /* static int cb_pcidda_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_cmd *cmd); */
245 /* static int cb_pcidda_ns_to_timer(unsigned int *ns,int *round); */
246
247 static unsigned int cb_pcidda_serial_in(struct comedi_device *dev);
248 static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
249                                  unsigned int num_bits);
250 static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
251                                           unsigned int address);
252 static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
253                                 unsigned int range);
254
255 static struct pci_dev *cb_pcidda_find_pci_dev(struct comedi_device *dev,
256                                               struct comedi_devconfig *it)
257 {
258         struct pci_dev *pcidev = NULL;
259         int bus = it->options[0];
260         int slot = it->options[1];
261         int i;
262
263         for_each_pci_dev(pcidev) {
264                 if (bus || slot) {
265                         if (bus != pcidev->bus->number ||
266                             slot != PCI_SLOT(pcidev->devfn))
267                                 continue;
268                 }
269                 if (pcidev->vendor != PCI_VENDOR_ID_CB)
270                         continue;
271
272                 for (i = 0; i < ARRAY_SIZE(cb_pcidda_boards); i++) {
273                         if (cb_pcidda_boards[i].device_id != pcidev->device)
274                                 continue;
275                         dev->board_ptr = cb_pcidda_boards + i;
276                         return pcidev;
277                 }
278         }
279         dev_err(dev->class_dev,
280                 "No supported board found! (req. bus %d, slot %d)\n",
281                 bus, slot);
282         return NULL;
283 }
284
285 /*
286  * Attach is called by the Comedi core to configure the driver
287  * for a particular board.
288  */
289 static int cb_pcidda_attach(struct comedi_device *dev,
290                             struct comedi_devconfig *it)
291 {
292         struct pci_dev *pcidev;
293         struct comedi_subdevice *s;
294         int index;
295         int ret;
296
297 /*
298  * Allocate the private structure area.
299  */
300         if (alloc_private(dev, sizeof(struct cb_pcidda_private)) < 0)
301                 return -ENOMEM;
302
303         pcidev = cb_pcidda_find_pci_dev(dev, it);
304         if (!pcidev)
305                 return -EIO;
306         comedi_set_hw_dev(dev, &pcidev->dev);
307
308         /*
309          * Enable PCI device and request regions.
310          */
311         if (comedi_pci_enable(pcidev, thisboard->name)) {
312                 dev_err(dev->class_dev,
313                         "cb_pcidda: failed to enable PCI device and request regions\n");
314                 return -EIO;
315         }
316
317 /*
318  * Allocate the I/O ports.
319  */
320         devpriv->digitalio = pci_resource_start(pcidev, DIGITALIO_BADRINDEX);
321         devpriv->dac = pci_resource_start(pcidev, DAC_BADRINDEX);
322         dev->iobase = devpriv->dac;
323
324 /*
325  * Warn about the status of the driver.
326  */
327         if (thisboard->status == 2)
328                 printk
329                     ("WARNING: DRIVER FOR THIS BOARD NOT CHECKED WITH MANUAL. "
330                      "WORKS ASSUMING FULL COMPATIBILITY WITH PCI-DDA08/12. "
331                      "PLEASE REPORT USAGE TO <ivanmr@altavista.com>.\n");
332
333 /*
334  * Initialize dev->board_name.
335  */
336         dev->board_name = thisboard->name;
337
338         ret = comedi_alloc_subdevices(dev, 3);
339         if (ret)
340                 return ret;
341
342         s = dev->subdevices + 0;
343         /* analog output subdevice */
344         s->type = COMEDI_SUBD_AO;
345         s->subdev_flags = SDF_WRITABLE;
346         s->n_chan = thisboard->ao_chans;
347         s->maxdata = (1 << thisboard->ao_bits) - 1;
348         s->range_table = thisboard->ranges;
349         s->insn_write = cb_pcidda_ao_winsn;
350
351         /* s->subdev_flags |= SDF_CMD_READ; */
352         /* s->do_cmd = cb_pcidda_ai_cmd; */
353         /* s->do_cmdtest = cb_pcidda_ai_cmdtest; */
354
355         /*  two 8255 digital io subdevices */
356         s = dev->subdevices + 1;
357         subdev_8255_init(dev, s, NULL, devpriv->digitalio);
358         s = dev->subdevices + 2;
359         subdev_8255_init(dev, s, NULL, devpriv->digitalio + PORT2A);
360
361         dev_dbg(dev->class_dev, "eeprom:\n");
362         for (index = 0; index < EEPROM_SIZE; index++) {
363                 devpriv->eeprom_data[index] = cb_pcidda_read_eeprom(dev, index);
364                 dev_dbg(dev->class_dev, "%i:0x%x\n", index,
365                         devpriv->eeprom_data[index]);
366         }
367
368         /*  set calibrations dacs */
369         for (index = 0; index < thisboard->ao_chans; index++)
370                 cb_pcidda_calibrate(dev, index, devpriv->ao_range[index]);
371
372         return 1;
373 }
374
375 static void cb_pcidda_detach(struct comedi_device *dev)
376 {
377         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
378
379         if (pcidev) {
380                 if (dev->iobase)
381                         comedi_pci_disable(pcidev);
382                 pci_dev_put(pcidev);
383         }
384         if (dev->subdevices) {
385                 subdev_8255_cleanup(dev, dev->subdevices + 1);
386                 subdev_8255_cleanup(dev, dev->subdevices + 2);
387         }
388 }
389
390 /*
391  * I will program this later... ;-)
392  */
393 #if 0
394 static int cb_pcidda_ai_cmd(struct comedi_device *dev,
395                             struct comedi_subdevice *s)
396 {
397         printk("cb_pcidda_ai_cmd\n");
398         printk("subdev: %d\n", cmd->subdev);
399         printk("flags: %d\n", cmd->flags);
400         printk("start_src: %d\n", cmd->start_src);
401         printk("start_arg: %d\n", cmd->start_arg);
402         printk("scan_begin_src: %d\n", cmd->scan_begin_src);
403         printk("convert_src: %d\n", cmd->convert_src);
404         printk("convert_arg: %d\n", cmd->convert_arg);
405         printk("scan_end_src: %d\n", cmd->scan_end_src);
406         printk("scan_end_arg: %d\n", cmd->scan_end_arg);
407         printk("stop_src: %d\n", cmd->stop_src);
408         printk("stop_arg: %d\n", cmd->stop_arg);
409         printk("chanlist_len: %d\n", cmd->chanlist_len);
410 }
411 #endif
412
413 #if 0
414 static int cb_pcidda_ai_cmdtest(struct comedi_device *dev,
415                                 struct comedi_subdevice *s,
416                                 struct comedi_cmd *cmd)
417 {
418         int err = 0;
419         int tmp;
420
421         /* cmdtest tests a particular command to see if it is valid.
422          * Using the cmdtest ioctl, a user can create a valid cmd
423          * and then have it executes by the cmd ioctl.
424          *
425          * cmdtest returns 1,2,3,4 or 0, depending on which tests
426          * the command passes. */
427
428         /* step 1: make sure trigger sources are trivially valid */
429
430         tmp = cmd->start_src;
431         cmd->start_src &= TRIG_NOW;
432         if (!cmd->start_src || tmp != cmd->start_src)
433                 err++;
434
435         tmp = cmd->scan_begin_src;
436         cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
437         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
438                 err++;
439
440         tmp = cmd->convert_src;
441         cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
442         if (!cmd->convert_src || tmp != cmd->convert_src)
443                 err++;
444
445         tmp = cmd->scan_end_src;
446         cmd->scan_end_src &= TRIG_COUNT;
447         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
448                 err++;
449
450         tmp = cmd->stop_src;
451         cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
452         if (!cmd->stop_src || tmp != cmd->stop_src)
453                 err++;
454
455         if (err)
456                 return 1;
457
458         /*
459          * step 2: make sure trigger sources are unique and mutually
460          * compatible
461          */
462
463         /* note that mutual compatibility is not an issue here */
464         if (cmd->scan_begin_src != TRIG_TIMER
465             && cmd->scan_begin_src != TRIG_EXT)
466                 err++;
467         if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
468                 err++;
469         if (cmd->stop_src != TRIG_TIMER && cmd->stop_src != TRIG_EXT)
470                 err++;
471
472         if (err)
473                 return 2;
474
475         /* step 3: make sure arguments are trivially compatible */
476
477         if (cmd->start_arg != 0) {
478                 cmd->start_arg = 0;
479                 err++;
480         }
481 #define MAX_SPEED       10000   /* in nanoseconds */
482 #define MIN_SPEED       1000000000      /* in nanoseconds */
483
484         if (cmd->scan_begin_src == TRIG_TIMER) {
485                 if (cmd->scan_begin_arg < MAX_SPEED) {
486                         cmd->scan_begin_arg = MAX_SPEED;
487                         err++;
488                 }
489                 if (cmd->scan_begin_arg > MIN_SPEED) {
490                         cmd->scan_begin_arg = MIN_SPEED;
491                         err++;
492                 }
493         } else {
494                 /* external trigger */
495                 /* should be level/edge, hi/lo specification here */
496                 /* should specify multiple external triggers */
497                 if (cmd->scan_begin_arg > 9) {
498                         cmd->scan_begin_arg = 9;
499                         err++;
500                 }
501         }
502         if (cmd->convert_src == TRIG_TIMER) {
503                 if (cmd->convert_arg < MAX_SPEED) {
504                         cmd->convert_arg = MAX_SPEED;
505                         err++;
506                 }
507                 if (cmd->convert_arg > MIN_SPEED) {
508                         cmd->convert_arg = MIN_SPEED;
509                         err++;
510                 }
511         } else {
512                 /* external trigger */
513                 /* see above */
514                 if (cmd->convert_arg > 9) {
515                         cmd->convert_arg = 9;
516                         err++;
517                 }
518         }
519
520         if (cmd->scan_end_arg != cmd->chanlist_len) {
521                 cmd->scan_end_arg = cmd->chanlist_len;
522                 err++;
523         }
524         if (cmd->stop_src == TRIG_COUNT) {
525                 if (cmd->stop_arg > 0x00ffffff) {
526                         cmd->stop_arg = 0x00ffffff;
527                         err++;
528                 }
529         } else {
530                 /* TRIG_NONE */
531                 if (cmd->stop_arg != 0) {
532                         cmd->stop_arg = 0;
533                         err++;
534                 }
535         }
536
537         if (err)
538                 return 3;
539
540         /* step 4: fix up any arguments */
541
542         if (cmd->scan_begin_src == TRIG_TIMER) {
543                 tmp = cmd->scan_begin_arg;
544                 cb_pcidda_ns_to_timer(&cmd->scan_begin_arg,
545                                       cmd->flags & TRIG_ROUND_MASK);
546                 if (tmp != cmd->scan_begin_arg)
547                         err++;
548         }
549         if (cmd->convert_src == TRIG_TIMER) {
550                 tmp = cmd->convert_arg;
551                 cb_pcidda_ns_to_timer(&cmd->convert_arg,
552                                       cmd->flags & TRIG_ROUND_MASK);
553                 if (tmp != cmd->convert_arg)
554                         err++;
555                 if (cmd->scan_begin_src == TRIG_TIMER &&
556                     cmd->scan_begin_arg <
557                     cmd->convert_arg * cmd->scan_end_arg) {
558                         cmd->scan_begin_arg =
559                             cmd->convert_arg * cmd->scan_end_arg;
560                         err++;
561                 }
562         }
563
564         if (err)
565                 return 4;
566
567         return 0;
568 }
569 #endif
570
571 /* This function doesn't require a particular form, this is just
572  * what happens to be used in some of the drivers.  It should
573  * convert ns nanoseconds to a counter value suitable for programming
574  * the device.  Also, it should adjust ns so that it cooresponds to
575  * the actual time that the device will use. */
576 #if 0
577 static int cb_pcidda_ns_to_timer(unsigned int *ns, int round)
578 {
579         /* trivial timer */
580         return *ns;
581 }
582 #endif
583
584 static int cb_pcidda_ao_winsn(struct comedi_device *dev,
585                               struct comedi_subdevice *s,
586                               struct comedi_insn *insn, unsigned int *data)
587 {
588         unsigned int command;
589         unsigned int channel, range;
590
591         channel = CR_CHAN(insn->chanspec);
592         range = CR_RANGE(insn->chanspec);
593
594         /*  adjust calibration dacs if range has changed */
595         if (range != devpriv->ao_range[channel])
596                 cb_pcidda_calibrate(dev, channel, range);
597
598         /* output channel configuration */
599         command = NOSU | ENABLEDAC;
600
601         /* output channel range */
602         switch (range) {
603         case 0:
604                 command |= BIP | RANGE10V;
605                 break;
606         case 1:
607                 command |= BIP | RANGE5V;
608                 break;
609         case 2:
610                 command |= BIP | RANGE2V5;
611                 break;
612         case 3:
613                 command |= UNIP | RANGE10V;
614                 break;
615         case 4:
616                 command |= UNIP | RANGE5V;
617                 break;
618         case 5:
619                 command |= UNIP | RANGE2V5;
620                 break;
621         }
622
623         /* output channel specification */
624         command |= channel << 2;
625         outw(command, devpriv->dac + DACONTROL);
626
627         /* write data */
628         outw(data[0], devpriv->dac + DADATA + channel * 2);
629
630         /* return the number of samples read/written */
631         return 1;
632 }
633
634 /* lowlevel read from eeprom */
635 static unsigned int cb_pcidda_serial_in(struct comedi_device *dev)
636 {
637         unsigned int value = 0;
638         int i;
639         const int value_width = 16;     /*  number of bits wide values are */
640
641         for (i = 1; i <= value_width; i++) {
642                 /*  read bits most significant bit first */
643                 if (inw_p(devpriv->dac + DACALIBRATION1) & SERIAL_OUT_BIT)
644                         value |= 1 << (value_width - i);
645         }
646
647         return value;
648 }
649
650 /* lowlevel write to eeprom/dac */
651 static void cb_pcidda_serial_out(struct comedi_device *dev, unsigned int value,
652                                  unsigned int num_bits)
653 {
654         int i;
655
656         for (i = 1; i <= num_bits; i++) {
657                 /*  send bits most significant bit first */
658                 if (value & (1 << (num_bits - i)))
659                         devpriv->dac_cal1_bits |= SERIAL_IN_BIT;
660                 else
661                         devpriv->dac_cal1_bits &= ~SERIAL_IN_BIT;
662                 outw_p(devpriv->dac_cal1_bits, devpriv->dac + DACALIBRATION1);
663         }
664 }
665
666 /* reads a 16 bit value from board's eeprom */
667 static unsigned int cb_pcidda_read_eeprom(struct comedi_device *dev,
668                                           unsigned int address)
669 {
670         unsigned int i;
671         unsigned int cal2_bits;
672         unsigned int value;
673         /* one caldac for every two dac channels */
674         const int max_num_caldacs = 4;
675         /* bits to send to tell eeprom we want to read */
676         const int read_instruction = 0x6;
677         const int instruction_length = 3;
678         const int address_length = 8;
679
680         /*  send serial output stream to eeprom */
681         cal2_bits = SELECT_EEPROM_BIT | DESELECT_REF_DAC_BIT | DUMMY_BIT;
682         /*  deactivate caldacs (one caldac for every two channels) */
683         for (i = 0; i < max_num_caldacs; i++)
684                 cal2_bits |= DESELECT_CALDAC_BIT(i);
685         outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
686
687         /*  tell eeprom we want to read */
688         cb_pcidda_serial_out(dev, read_instruction, instruction_length);
689         /*  send address we want to read from */
690         cb_pcidda_serial_out(dev, address, address_length);
691
692         value = cb_pcidda_serial_in(dev);
693
694         /*  deactivate eeprom */
695         cal2_bits &= ~SELECT_EEPROM_BIT;
696         outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
697
698         return value;
699 }
700
701 /* writes to 8 bit calibration dacs */
702 static void cb_pcidda_write_caldac(struct comedi_device *dev,
703                                    unsigned int caldac, unsigned int channel,
704                                    unsigned int value)
705 {
706         unsigned int cal2_bits;
707         unsigned int i;
708         /* caldacs use 3 bit channel specification */
709         const int num_channel_bits = 3;
710         const int num_caldac_bits = 8;  /*  8 bit calibration dacs */
711         /* one caldac for every two dac channels */
712         const int max_num_caldacs = 4;
713
714         /* write 3 bit channel */
715         cb_pcidda_serial_out(dev, channel, num_channel_bits);
716         /*  write 8 bit caldac value */
717         cb_pcidda_serial_out(dev, value, num_caldac_bits);
718
719 /*
720 * latch stream into appropriate caldac deselect reference dac
721 */
722         cal2_bits = DESELECT_REF_DAC_BIT | DUMMY_BIT;
723         /*  deactivate caldacs (one caldac for every two channels) */
724         for (i = 0; i < max_num_caldacs; i++)
725                 cal2_bits |= DESELECT_CALDAC_BIT(i);
726         /*  activate the caldac we want */
727         cal2_bits &= ~DESELECT_CALDAC_BIT(caldac);
728         outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
729         /*  deactivate caldac */
730         cal2_bits |= DESELECT_CALDAC_BIT(caldac);
731         outw_p(cal2_bits, devpriv->dac + DACALIBRATION2);
732 }
733
734 /* returns caldac that calibrates given analog out channel */
735 static unsigned int caldac_number(unsigned int channel)
736 {
737         return channel / 2;
738 }
739
740 /* returns caldac channel that provides fine gain for given ao channel */
741 static unsigned int fine_gain_channel(unsigned int ao_channel)
742 {
743         return 4 * (ao_channel % 2);
744 }
745
746 /* returns caldac channel that provides coarse gain for given ao channel */
747 static unsigned int coarse_gain_channel(unsigned int ao_channel)
748 {
749         return 1 + 4 * (ao_channel % 2);
750 }
751
752 /* returns caldac channel that provides coarse offset for given ao channel */
753 static unsigned int coarse_offset_channel(unsigned int ao_channel)
754 {
755         return 2 + 4 * (ao_channel % 2);
756 }
757
758 /* returns caldac channel that provides fine offset for given ao channel */
759 static unsigned int fine_offset_channel(unsigned int ao_channel)
760 {
761         return 3 + 4 * (ao_channel % 2);
762 }
763
764 /* returns eeprom address that provides offset for given ao channel and range */
765 static unsigned int offset_eeprom_address(unsigned int ao_channel,
766                                           unsigned int range)
767 {
768         return 0x7 + 2 * range + 12 * ao_channel;
769 }
770
771 /*
772  * returns eeprom address that provides gain calibration for given ao
773  * channel and range
774  */
775 static unsigned int gain_eeprom_address(unsigned int ao_channel,
776                                         unsigned int range)
777 {
778         return 0x8 + 2 * range + 12 * ao_channel;
779 }
780
781 /*
782  * returns upper byte of eeprom entry, which gives the coarse adjustment
783  * values
784  */
785 static unsigned int eeprom_coarse_byte(unsigned int word)
786 {
787         return (word >> 8) & 0xff;
788 }
789
790 /* returns lower byte of eeprom entry, which gives the fine adjustment values */
791 static unsigned int eeprom_fine_byte(unsigned int word)
792 {
793         return word & 0xff;
794 }
795
796 /* set caldacs to eeprom values for given channel and range */
797 static void cb_pcidda_calibrate(struct comedi_device *dev, unsigned int channel,
798                                 unsigned int range)
799 {
800         unsigned int coarse_offset, fine_offset, coarse_gain, fine_gain;
801
802         /* remember range so we can tell when we need to readjust calibration */
803         devpriv->ao_range[channel] = range;
804
805         /*  get values from eeprom data */
806         coarse_offset =
807             eeprom_coarse_byte(devpriv->eeprom_data
808                                [offset_eeprom_address(channel, range)]);
809         fine_offset =
810             eeprom_fine_byte(devpriv->eeprom_data
811                              [offset_eeprom_address(channel, range)]);
812         coarse_gain =
813             eeprom_coarse_byte(devpriv->eeprom_data
814                                [gain_eeprom_address(channel, range)]);
815         fine_gain =
816             eeprom_fine_byte(devpriv->eeprom_data
817                              [gain_eeprom_address(channel, range)]);
818
819         /*  set caldacs */
820         cb_pcidda_write_caldac(dev, caldac_number(channel),
821                                coarse_offset_channel(channel), coarse_offset);
822         cb_pcidda_write_caldac(dev, caldac_number(channel),
823                                fine_offset_channel(channel), fine_offset);
824         cb_pcidda_write_caldac(dev, caldac_number(channel),
825                                coarse_gain_channel(channel), coarse_gain);
826         cb_pcidda_write_caldac(dev, caldac_number(channel),
827                                fine_gain_channel(channel), fine_gain);
828 }
829
830 static struct comedi_driver cb_pcidda_driver = {
831         .driver_name    = "cb_pcidda",
832         .module         = THIS_MODULE,
833         .attach         = cb_pcidda_attach,
834         .detach         = cb_pcidda_detach,
835 };
836
837 static int __devinit cb_pcidda_pci_probe(struct pci_dev *dev,
838                                          const struct pci_device_id *ent)
839 {
840         return comedi_pci_auto_config(dev, &cb_pcidda_driver);
841 }
842
843 static void __devexit cb_pcidda_pci_remove(struct pci_dev *dev)
844 {
845         comedi_pci_auto_unconfig(dev);
846 }
847
848 static DEFINE_PCI_DEVICE_TABLE(cb_pcidda_pci_table) = {
849         { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0020) },
850         { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0021) },
851         { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0022) },
852         { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0023) },
853         { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0024) },
854         { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0025) },
855         { 0 }
856 };
857 MODULE_DEVICE_TABLE(pci, cb_pcidda_pci_table);
858
859 static struct pci_driver cb_pcidda_pci_driver = {
860         .name           = "cb_pcidda",
861         .id_table       = cb_pcidda_pci_table,
862         .probe          = cb_pcidda_pci_probe,
863         .remove         = __devexit_p(cb_pcidda_pci_remove),
864 };
865 module_comedi_pci_driver(cb_pcidda_driver, cb_pcidda_pci_driver);
866
867 MODULE_AUTHOR("Comedi http://www.comedi.org");
868 MODULE_DESCRIPTION("Comedi low-level driver");
869 MODULE_LICENSE("GPL");