]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/staging/comedi/drivers/s526.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[mv-sheeva.git] / drivers / staging / comedi / drivers / s526.c
index b89e1ec267c5d3dab0a578d760641d822fe4683b..07c21e686f270b69a92baa5689ce52a230347e5a 100644 (file)
@@ -43,6 +43,7 @@ comedi_config /dev/comedi0 s526 0x2C0,0x3
 
 #include "../comedidev.h"
 #include <linux/ioport.h>
+#include <asm/byteorder.h>
 
 #define S526_SIZE 64
 
@@ -113,6 +114,7 @@ static const int s526_ports[] = {
 };
 
 struct counter_mode_register_t {
+#if defined (__LITTLE_ENDIAN_BITFIELD)
        unsigned short coutSource:1;
        unsigned short coutPolarity:1;
        unsigned short autoLoadResetRcap:3;
@@ -124,12 +126,27 @@ struct counter_mode_register_t {
        unsigned short outputRegLatchCtrl:1;
        unsigned short preloadRegSel:1;
        unsigned short reserved:1;
+ #elif defined(__BIG_ENDIAN_BITFIELD)
+       unsigned short reserved:1;
+       unsigned short preloadRegSel:1;
+       unsigned short outputRegLatchCtrl:1;
+       unsigned short countDirCtrl:1;
+       unsigned short countDir:1;
+       unsigned short clockSource:2;
+       unsigned short ctEnableCtrl:2;
+       unsigned short hwCtEnableSource:2;
+       unsigned short autoLoadResetRcap:3;
+       unsigned short coutPolarity:1;
+       unsigned short coutSource:1;
+#else
+#error Unknown bit field order
+#endif
 };
 
-union {
+union cmReg {
        struct counter_mode_register_t reg;
        unsigned short value;
-} cmReg;
+};
 
 #define MAX_GPCT_CONFIG_DATA 6
 
@@ -285,6 +302,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        int i, n;
 /* short value; */
 /* int subdev_channel = 0; */
+       union cmReg cmReg;
 
        printk("comedi%d: s526: ", dev->minor);
 
@@ -375,7 +393,7 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        if (thisboard->have_dio) {
                s->type = COMEDI_SUBD_DIO;
                s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
-               s->n_chan = 2;
+               s->n_chan = 8;
                s->maxdata = 1;
                s->range_table = &range_digital;
                s->insn_bits = s526_dio_insn_bits;
@@ -435,11 +453,11 @@ static int s526_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        udelay(1000);
        printk("Read back mode reg=0x%04x\n", inw(ADDR_CHAN_REG(REG_C0M, n)));
 
-       /*  Load the pre-laod register high word */
+       /*  Load the pre-load register high word */
 /* value = (short) (0x55); */
 /* outw(value, ADDR_CHAN_REG(REG_C0H, n)); */
 
-       /*  Load the pre-laod register low word */
+       /*  Load the pre-load register low word */
 /* value = (short)(0xaa55); */
 /* outw(value, ADDR_CHAN_REG(REG_C0L, n)); */
 
@@ -516,6 +534,7 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
        int subdev_channel = CR_CHAN(insn->chanspec);   /*  Unpack chanspec */
        int i;
        short value;
+       union cmReg cmReg;
 
 /* printk("s526: GPCT_INSN_CONFIG: Configuring Channel %d\n", subdev_channel); */
 
@@ -568,19 +587,8 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
 
 #if 1
                /*  Set Counter Mode Register */
-               cmReg.reg.coutSource = 0;       /*  out RCAP */
-               cmReg.reg.coutPolarity = 0;     /*  Polarity inverted */
-               cmReg.reg.autoLoadResetRcap = 0;        /*  Auto load disabled */
-               cmReg.reg.hwCtEnableSource = 2; /*  NOT RCAP */
-               cmReg.reg.ctEnableCtrl = 1;     /*  1: Software,  >1 : Hardware */
-               cmReg.reg.clockSource = 3;      /*  x4 */
-               cmReg.reg.countDir = 0; /*  up */
-               cmReg.reg.countDirCtrl = 0;     /*  quadrature */
-               cmReg.reg.outputRegLatchCtrl = 0;       /*  latch on read */
-               cmReg.reg.preloadRegSel = 0;    /*  PR0 */
-               cmReg.reg.reserved = 0;
+               cmReg.value = insn->data[1] & 0xFFFF;
 
-               /*  Set Counter Mode Register */
 /* printk("s526: Counter Mode register=%x\n", cmReg.value); */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
@@ -615,11 +623,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.value = (short)(insn->data[1] & 0xFFFF);
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register high word */
+               /*  Load the pre-load register high word */
                value = (short)((insn->data[2] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register low word */
+               /*  Load the pre-load register low word */
                value = (short)(insn->data[2] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
@@ -653,11 +661,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.reg.preloadRegSel = 0;    /*  PR0 */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register 0 high word */
+               /*  Load the pre-load register 0 high word */
                value = (short)((insn->data[2] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register 0 low word */
+               /*  Load the pre-load register 0 low word */
                value = (short)(insn->data[2] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
@@ -666,17 +674,17 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.reg.preloadRegSel = 1;    /*  PR1 */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register 1 high word */
+               /*  Load the pre-load register 1 high word */
                value = (short)((insn->data[3] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register 1 low word */
+               /*  Load the pre-load register 1 low word */
                value = (short)(insn->data[3] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
                /*  Write the Counter Control Register */
-               if (insn->data[3] != 0) {
-                       value = (short)(insn->data[3] & 0xFFFF);
+               if (insn->data[4] != 0) {
+                       value = (short)(insn->data[4] & 0xFFFF);
                        outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
                }
                break;
@@ -698,11 +706,11 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.reg.preloadRegSel = 0;    /*  PR0 */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register 0 high word */
+               /*  Load the pre-load register 0 high word */
                value = (short)((insn->data[2] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register 0 low word */
+               /*  Load the pre-load register 0 low word */
                value = (short)(insn->data[2] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
@@ -711,17 +719,17 @@ static int s526_gpct_insn_config(struct comedi_device *dev,
                cmReg.reg.preloadRegSel = 1;    /*  PR1 */
                outw(cmReg.value, ADDR_CHAN_REG(REG_C0M, subdev_channel));
 
-               /*  Load the pre-laod register 1 high word */
+               /*  Load the pre-load register 1 high word */
                value = (short)((insn->data[3] >> 16) & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0H, subdev_channel));
 
-               /*  Load the pre-laod register 1 low word */
+               /*  Load the pre-load register 1 low word */
                value = (short)(insn->data[3] & 0xFFFF);
                outw(value, ADDR_CHAN_REG(REG_C0L, subdev_channel));
 
                /*  Write the Counter Control Register */
-               if (insn->data[3] != 0) {
-                       value = (short)(insn->data[3] & 0xFFFF);
+               if (insn->data[4] != 0) {
+                       value = (short)(insn->data[4] & 0xFFFF);
                        outw(value, ADDR_CHAN_REG(REG_C0C, subdev_channel));
                }
                break;
@@ -741,6 +749,7 @@ static int s526_gpct_winsn(struct comedi_device *dev,
 {
        int subdev_channel = CR_CHAN(insn->chanspec);   /*  Unpack chanspec */
        short value;
+       union cmReg cmReg;
 
        printk("s526: GPCT_INSN_WRITE on channel %d\n", subdev_channel);
        cmReg.value = inw(ADDR_CHAN_REG(REG_C0M, subdev_channel));
@@ -775,9 +784,8 @@ static int s526_gpct_winsn(struct comedi_device *dev,
                        (devpriv->s526_gpct_config[subdev_channel]).data[1] =
                            insn->data[1];
                } else {
-                       printk("%d \t %d\n", insn->data[1], insn->data[2]);
-                       printk
-                           ("s526: INSN_WRITE: PTG: Problem with Pulse params\n");
+                       printk("s526: INSN_WRITE: PTG: Problem with Pulse params -> %d %d\n",
+                               insn->data[0], insn->data[1]);
                        return -EINVAL;
                }
 
@@ -949,7 +957,7 @@ static int s526_dio_insn_bits(struct comedi_device *dev,
        data[1] = inw(ADDR_REG(REG_DIO)) & 0xFF;        /*  low 8 bits are the data */
        /* or we could just return the software copy of the output values if
         * it was a purely digital output subdevice */
-       /* data[1]=s->state; */
+       /* data[1]=s->state & 0xFF; */
 
        return 2;
 }
@@ -959,28 +967,33 @@ static int s526_dio_insn_config(struct comedi_device *dev,
                                struct comedi_insn *insn, unsigned int *data)
 {
        int chan = CR_CHAN(insn->chanspec);
-       short value;
+       int group, mask;
 
        printk("S526 DIO insn_config\n");
 
-       if (insn->n != 1)
-               return -EINVAL;
-
-       value = inw(ADDR_REG(REG_DIO));
-
        /* The input or output configuration of each digital line is
         * configured by a special insn_config instruction.  chanspec
         * contains the channel to be changed, and data[0] contains the
         * value COMEDI_INPUT or COMEDI_OUTPUT. */
 
-       if (data[0] == COMEDI_OUTPUT) {
-               value |= 1 << (chan + 10);      /*  bit 10/11 set the group 1/2's mode */
-               s->io_bits |= (0xF << chan);
-       } else {
-               value &= ~(1 << (chan + 10));   /*  1 is output, 0 is input. */
-               s->io_bits &= ~(0xF << chan);
+       group = chan >> 2;
+       mask = 0xF << (group << 2);
+       switch (data[0]) {
+       case INSN_CONFIG_DIO_OUTPUT:
+               s->state |= 1 << (group + 10);  // bit 10/11 set the group 1/2's mode
+               s->io_bits |= mask;
+               break;
+       case INSN_CONFIG_DIO_INPUT:
+               s->state &= ~(1 << (group + 10));// 1 is output, 0 is input.
+               s->io_bits &= ~mask;
+               break;
+       case INSN_CONFIG_DIO_QUERY:
+               data[1] = (s->io_bits & mask) ? COMEDI_OUTPUT : COMEDI_INPUT;
+               return insn->n;
+       default:
+               return -EINVAL;
        }
-       outw(value, ADDR_REG(REG_DIO));
+       outw(s->state, ADDR_REG(REG_DIO));
 
        return 1;
 }