]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'topic/pcxhr-update' into to-push
authorTakashi Iwai <tiwai@suse.de>
Thu, 25 Dec 2008 10:40:31 +0000 (11:40 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 25 Dec 2008 10:40:31 +0000 (11:40 +0100)
1  2 
sound/pci/pcxhr/pcxhr.c
sound/pci/pcxhr/pcxhr_core.c

diff --combined sound/pci/pcxhr/pcxhr.c
index 471ee27e6c8ad9d6f9ca7fbf401d6b64edca3429,0327925828d105b74813d8c7d8b3728a2b195000..27cf2c28d1131eac14cf96ac3b55eb34c51ec543
  #include "pcxhr_mixer.h"
  #include "pcxhr_hwdep.h"
  #include "pcxhr_core.h"
+ #include "pcxhr_mix22.h"
  
  #define DRIVER_NAME "pcxhr"
  
- MODULE_AUTHOR("Markus Bollinger <bollinger@digigram.com>");
+ MODULE_AUTHOR("Markus Bollinger <bollinger@digigram.com>, "
+             "Marc Titinger <titinger@digigram.com>");
  MODULE_DESCRIPTION("Digigram " DRIVER_NAME " " PCXHR_DRIVER_VERSION_STRING);
  MODULE_LICENSE("GPL");
  MODULE_SUPPORTED_DEVICE("{{Digigram," DRIVER_NAME "}}");
  
- static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;            /* Index 0-MAX */
- static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;             /* ID for this card */
- static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;    /* Enable this card */
- static int mono[SNDRV_CARDS];                                 /* capture in mono only */
+ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;    /* Index 0-MAX */
+ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;     /* ID for this card */
+ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+ static int mono[SNDRV_CARDS];                         /* capture  mono only */
  
  module_param_array(index, int, NULL, 0444);
  MODULE_PARM_DESC(index, "Index value for Digigram " DRIVER_NAME " soundcard");
@@@ -67,18 -69,58 +69,58 @@@ enum 
        PCI_ID_PCX882HR,
        PCI_ID_VX881HR,
        PCI_ID_PCX881HR,
+       PCI_ID_VX882E,
+       PCI_ID_PCX882E,
+       PCI_ID_VX881E,
+       PCI_ID_PCX881E,
+       PCI_ID_VX1222HR,
        PCI_ID_PCX1222HR,
+       PCI_ID_VX1221HR,
        PCI_ID_PCX1221HR,
+       PCI_ID_VX1222E,
+       PCI_ID_PCX1222E,
+       PCI_ID_VX1221E,
+       PCI_ID_PCX1221E,
+       PCI_ID_VX222HR,
+       PCI_ID_VX222E,
+       PCI_ID_PCX22HR,
+       PCI_ID_PCX22E,
+       PCI_ID_VX222HRMIC,
+       PCI_ID_VX222E_MIC,
+       PCI_ID_PCX924HR,
+       PCI_ID_PCX924E,
+       PCI_ID_PCX924HRMIC,
+       PCI_ID_PCX924E_MIC,
        PCI_ID_LAST
  };
  
  static struct pci_device_id pcxhr_ids[] = {
-       { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, },   /* VX882HR */
-       { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, },  /* PCX882HR */
-       { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, },   /* VX881HR */
-       { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, },  /* PCX881HR */
-       { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, }, /* PCX1222HR */
-       { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, }, /* PCX1221HR */
+       { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, },
+       { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, },
+       { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, },
+       { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, },
+       { 0x10b5, 0x9056, 0x1369, 0xb021, 0, 0, PCI_ID_VX882E, },
+       { 0x10b5, 0x9056, 0x1369, 0xb121, 0, 0, PCI_ID_PCX882E, },
+       { 0x10b5, 0x9056, 0x1369, 0xb221, 0, 0, PCI_ID_VX881E, },
+       { 0x10b5, 0x9056, 0x1369, 0xb321, 0, 0, PCI_ID_PCX881E, },
+       { 0x10b5, 0x9656, 0x1369, 0xb401, 0, 0, PCI_ID_VX1222HR, },
+       { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, },
+       { 0x10b5, 0x9656, 0x1369, 0xb601, 0, 0, PCI_ID_VX1221HR, },
+       { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, },
+       { 0x10b5, 0x9056, 0x1369, 0xb421, 0, 0, PCI_ID_VX1222E, },
+       { 0x10b5, 0x9056, 0x1369, 0xb521, 0, 0, PCI_ID_PCX1222E, },
+       { 0x10b5, 0x9056, 0x1369, 0xb621, 0, 0, PCI_ID_VX1221E, },
+       { 0x10b5, 0x9056, 0x1369, 0xb721, 0, 0, PCI_ID_PCX1221E, },
+       { 0x10b5, 0x9056, 0x1369, 0xba01, 0, 0, PCI_ID_VX222HR, },
+       { 0x10b5, 0x9056, 0x1369, 0xba21, 0, 0, PCI_ID_VX222E, },
+       { 0x10b5, 0x9056, 0x1369, 0xbd01, 0, 0, PCI_ID_PCX22HR, },
+       { 0x10b5, 0x9056, 0x1369, 0xbd21, 0, 0, PCI_ID_PCX22E, },
+       { 0x10b5, 0x9056, 0x1369, 0xbc01, 0, 0, PCI_ID_VX222HRMIC, },
+       { 0x10b5, 0x9056, 0x1369, 0xbc21, 0, 0, PCI_ID_VX222E_MIC, },
+       { 0x10b5, 0x9056, 0x1369, 0xbb01, 0, 0, PCI_ID_PCX924HR, },
+       { 0x10b5, 0x9056, 0x1369, 0xbb21, 0, 0, PCI_ID_PCX924E, },
+       { 0x10b5, 0x9056, 0x1369, 0xbf01, 0, 0, PCI_ID_PCX924HRMIC, },
+       { 0x10b5, 0x9056, 0x1369, 0xbf21, 0, 0, PCI_ID_PCX924E_MIC, },
        { 0, }
  };
  
@@@ -88,27 -130,55 +130,55 @@@ struct board_parameters 
        char* board_name;
        short playback_chips;
        short capture_chips;
+       short fw_file_set;
        short firmware_num;
  };
  static struct board_parameters pcxhr_board_params[] = {
- [PCI_ID_VX882HR] =    { "VX882HR",   4, 4, 41, },
- [PCI_ID_PCX882HR] =   { "PCX882HR",  4, 4, 41, },
- [PCI_ID_VX881HR] =    { "VX881HR",   4, 4, 41, },
- [PCI_ID_PCX881HR] =   { "PCX881HR",  4, 4, 41, },
- [PCI_ID_PCX1222HR] =  { "PCX1222HR", 6, 1, 42, },
- [PCI_ID_PCX1221HR] =  { "PCX1221HR", 6, 1, 42, },
+ [PCI_ID_VX882HR] =      { "VX882HR",      4, 4, 0, 41 },
+ [PCI_ID_PCX882HR] =     { "PCX882HR",     4, 4, 0, 41 },
+ [PCI_ID_VX881HR] =      { "VX881HR",      4, 4, 0, 41 },
+ [PCI_ID_PCX881HR] =     { "PCX881HR",     4, 4, 0, 41 },
+ [PCI_ID_VX882E] =       { "VX882e",       4, 4, 1, 41 },
+ [PCI_ID_PCX882E] =      { "PCX882e",      4, 4, 1, 41 },
+ [PCI_ID_VX881E] =       { "VX881e",       4, 4, 1, 41 },
+ [PCI_ID_PCX881E] =      { "PCX881e",      4, 4, 1, 41 },
+ [PCI_ID_VX1222HR] =     { "VX1222HR",     6, 1, 2, 42 },
+ [PCI_ID_PCX1222HR] =    { "PCX1222HR",    6, 1, 2, 42 },
+ [PCI_ID_VX1221HR] =     { "VX1221HR",     6, 1, 2, 42 },
+ [PCI_ID_PCX1221HR] =    { "PCX1221HR",    6, 1, 2, 42 },
+ [PCI_ID_VX1222E] =      { "VX1222e",      6, 1, 3, 42 },
+ [PCI_ID_PCX1222E] =     { "PCX1222e",     6, 1, 3, 42 },
+ [PCI_ID_VX1221E] =      { "VX1221e",      6, 1, 3, 42 },
+ [PCI_ID_PCX1221E] =     { "PCX1221e",     6, 1, 3, 42 },
+ [PCI_ID_VX222HR] =      { "VX222HR",      1, 1, 4, 44 },
+ [PCI_ID_VX222E] =       { "VX222e",       1, 1, 4, 44 },
+ [PCI_ID_PCX22HR] =      { "PCX22HR",      1, 0, 4, 44 },
+ [PCI_ID_PCX22E] =       { "PCX22e",       1, 0, 4, 44 },
+ [PCI_ID_VX222HRMIC] =   { "VX222HR-Mic",  1, 1, 5, 44 },
+ [PCI_ID_VX222E_MIC] =   { "VX222e-Mic",   1, 1, 5, 44 },
+ [PCI_ID_PCX924HR] =     { "PCX924HR",     1, 1, 5, 44 },
+ [PCI_ID_PCX924E] =      { "PCX924e",      1, 1, 5, 44 },
+ [PCI_ID_PCX924HRMIC] =  { "PCX924HR-Mic", 1, 1, 5, 44 },
+ [PCI_ID_PCX924E_MIC] =  { "PCX924e-Mic",  1, 1, 5, 44 },
  };
  
+ /* boards without hw AES1 and SRC onboard are all using fw_file_set==4 */
+ /* VX222HR, VX222e, PCX22HR and PCX22e */
+ #define PCXHR_BOARD_HAS_AES1(x) (x->fw_file_set != 4)
+ /* some boards do not support 192kHz on digital AES input plugs */
+ #define PCXHR_BOARD_AESIN_NO_192K(x) ((x->capture_chips == 0) || \
+                                     (x->fw_file_set == 0)   || \
+                                     (x->fw_file_set == 2))
  
  static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
                                   unsigned int* realfreq)
  {
        unsigned int reg;
  
-       if (freq < 6900 || freq > 110250)
+       if (freq < 6900 || freq > 110000)
                return -EINVAL;
-       reg = (28224000 * 10) / freq;
-       reg = (reg + 5) / 10;
+       reg = (28224000 * 2) / freq;
+       reg = (reg - 1) / 2;
        if (reg < 0x200)
                *pllreg = reg + 0x800;
        else if (reg < 0x400)
                reg &= ~3;
        }
        if (realfreq)
-               *realfreq = ((28224000 * 10) / reg + 5) / 10;
+               *realfreq = (28224000 / (reg + 1));
        return 0;
  }
  
  #define PCXHR_FREQ_AES_3              0x03
  #define PCXHR_FREQ_AES_4              0x0d
  
- #define PCXHR_MODIFY_CLOCK_S_BIT      0x04
- #define PCXHR_IRQ_TIMER_FREQ          92000
- #define PCXHR_IRQ_TIMER_PERIOD                48
  static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
                               unsigned int *reg, unsigned int *freq)
  {
                        err = pcxhr_send_msg(mgr, &rmh);
                        if (err < 0) {
                                snd_printk(KERN_ERR
-                                          "error CMD_ACCESS_IO_WRITE for PLL register : %x!\n",
-                                          err );
+                                          "error CMD_ACCESS_IO_WRITE "
+                                          "for PLL register : %x!\n", err);
                                return err;
                        }
                }
                break;
-       case PCXHR_CLOCK_TYPE_WORD_CLOCK :      val = PCXHR_FREQ_WORD_CLOCK;    break;
-       case PCXHR_CLOCK_TYPE_AES_SYNC :        val = PCXHR_FREQ_SYNC_AES;      break;
-       case PCXHR_CLOCK_TYPE_AES_1 :           val = PCXHR_FREQ_AES_1;         break;
-       case PCXHR_CLOCK_TYPE_AES_2 :           val = PCXHR_FREQ_AES_2;         break;
-       case PCXHR_CLOCK_TYPE_AES_3 :           val = PCXHR_FREQ_AES_3;         break;
-       case PCXHR_CLOCK_TYPE_AES_4 :           val = PCXHR_FREQ_AES_4;         break;
-       default : return -EINVAL;
+       case PCXHR_CLOCK_TYPE_WORD_CLOCK:
+               val = PCXHR_FREQ_WORD_CLOCK;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_SYNC:
+               val = PCXHR_FREQ_SYNC_AES;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_1:
+               val = PCXHR_FREQ_AES_1;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_2:
+               val = PCXHR_FREQ_AES_2;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_3:
+               val = PCXHR_FREQ_AES_3;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_4:
+               val = PCXHR_FREQ_AES_4;
+               break;
+       default:
+               return -EINVAL;
        }
        *reg = val;
        *freq = realfreq;
  }
  
  
- int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
+ static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr,
+                              unsigned int rate,
+                              int *changed)
  {
        unsigned int val, realfreq, speed;
        struct pcxhr_rmh rmh;
-       int err, changed;
-       if (rate == 0)
-               return 0; /* nothing to do */
+       int err;
  
        err = pcxhr_get_clock_reg(mgr, rate, &val, &realfreq);
        if (err)
        else
                speed = 2;      /* quad speed */
        if (mgr->codec_speed != speed) {
-               pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);      /* mute outputs */
+               pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* mute outputs */
                rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
+               if (DSP_EXT_CMD_SET(mgr)) {
+                       rmh.cmd[1]  = 1;
+                       rmh.cmd_len = 2;
+               }
                err = pcxhr_send_msg(mgr, &rmh);
                if (err)
                        return err;
  
-               pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);      /* set speed ratio */
+               pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set speed ratio */
                rmh.cmd[0] |= IO_NUM_SPEED_RATIO;
                rmh.cmd[1] = speed;
                rmh.cmd_len = 2;
        }
        /* set the new frequency */
        snd_printdd("clock register : set %x\n", val);
-       err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK, val, &changed);
+       err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK,
+                                         val, changed);
        if (err)
                return err;
        mgr->sample_rate_real = realfreq;
        mgr->cur_clock_type = mgr->use_clock_type;
  
        /* unmute after codec speed modes */
        if (mgr->codec_speed != speed) {
-               pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);       /* unmute outputs */
+               pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* unmute outputs */
                rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
+               if (DSP_EXT_CMD_SET(mgr)) {
+                       rmh.cmd[1]  = 1;
+                       rmh.cmd_len = 2;
+               }
                err = pcxhr_send_msg(mgr, &rmh);
                if (err)
                        return err;
-               mgr->codec_speed = speed;                       /* save new codec speed */
+               mgr->codec_speed = speed;       /* save new codec speed */
        }
  
+       snd_printdd("pcxhr_sub_set_clock to %dHz (realfreq=%d)\n",
+                   rate, realfreq);
+       return 0;
+ }
+ #define PCXHR_MODIFY_CLOCK_S_BIT      0x04
+ #define PCXHR_IRQ_TIMER_FREQ          92000
+ #define PCXHR_IRQ_TIMER_PERIOD                48
+ int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
+ {
+       struct pcxhr_rmh rmh;
+       int err, changed;
+       if (rate == 0)
+               return 0; /* nothing to do */
+       if (mgr->is_hr_stereo)
+               err = hr222_sub_set_clock(mgr, rate, &changed);
+       else
+               err = pcxhr_sub_set_clock(mgr, rate, &changed);
+       if (err)
+               return err;
        if (changed) {
                pcxhr_init_rmh(&rmh, CMD_MODIFY_CLOCK);
-               rmh.cmd[0] |= PCXHR_MODIFY_CLOCK_S_BIT;         /* resync fifos  */
+               rmh.cmd[0] |= PCXHR_MODIFY_CLOCK_S_BIT; /* resync fifos  */
                if (rate < PCXHR_IRQ_TIMER_FREQ)
                        rmh.cmd[1] = PCXHR_IRQ_TIMER_PERIOD;
                else
                if (err)
                        return err;
        }
-       snd_printdd("pcxhr_set_clock to %dHz (realfreq=%d)\n", rate, realfreq);
        return 0;
  }
  
  
- int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_type,
-                            int *sample_rate)
+ static int pcxhr_sub_get_external_clock(struct pcxhr_mgr *mgr,
+                                       enum pcxhr_clock_type clock_type,
+                                       int *sample_rate)
  {
        struct pcxhr_rmh rmh;
        unsigned char reg;
        int err, rate;
  
        switch (clock_type) {
-       case PCXHR_CLOCK_TYPE_WORD_CLOCK :      reg = REG_STATUS_WORD_CLOCK;    break;
-       case PCXHR_CLOCK_TYPE_AES_SYNC :        reg = REG_STATUS_AES_SYNC;      break;
-       case PCXHR_CLOCK_TYPE_AES_1 :           reg = REG_STATUS_AES_1;         break;
-       case PCXHR_CLOCK_TYPE_AES_2 :           reg = REG_STATUS_AES_2;         break;
-       case PCXHR_CLOCK_TYPE_AES_3 :           reg = REG_STATUS_AES_3;         break;
-       case PCXHR_CLOCK_TYPE_AES_4 :           reg = REG_STATUS_AES_4;         break;
-       default : return -EINVAL;
+       case PCXHR_CLOCK_TYPE_WORD_CLOCK:
+               reg = REG_STATUS_WORD_CLOCK;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_SYNC:
+               reg = REG_STATUS_AES_SYNC;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_1:
+               reg = REG_STATUS_AES_1;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_2:
+               reg = REG_STATUS_AES_2;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_3:
+               reg = REG_STATUS_AES_3;
+               break;
+       case PCXHR_CLOCK_TYPE_AES_4:
+               reg = REG_STATUS_AES_4;
+               break;
+       default:
+               return -EINVAL;
        }
        pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
        rmh.cmd_len = 2;
                err = pcxhr_send_msg(mgr, &rmh);
                if (err)
                        return err;
-               udelay(100);            /* wait minimum 2 sample_frames at 32kHz ! */
+               udelay(100);    /* wait minimum 2 sample_frames at 32kHz ! */
                mgr->last_reg_stat = reg;
        }
        rmh.cmd[1]  = REG_STATUS_CURRENT;
  }
  
  
+ int pcxhr_get_external_clock(struct pcxhr_mgr *mgr,
+                            enum pcxhr_clock_type clock_type,
+                            int *sample_rate)
+ {
+       if (mgr->is_hr_stereo)
+               return hr222_get_external_clock(mgr, clock_type,
+                                               sample_rate);
+       else
+               return pcxhr_sub_get_external_clock(mgr, clock_type,
+                                                   sample_rate);
+ }
  /*
   *  start or stop playback/capture substream
   */
@@@ -350,7 -488,8 +488,8 @@@ static int pcxhr_set_stream_state(struc
                start = 1;
        else {
                if (stream->status != PCXHR_STREAM_STATUS_SCHEDULE_STOP) {
-                       snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state CANNOT be stopped\n");
+                       snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state "
+                                  "CANNOT be stopped\n");
                        return -EINVAL;
                }
                start = 0;
                return -EINVAL;
  
        stream->timer_abs_periods = 0;
-       stream->timer_period_frag = 0;            /* reset theoretical stream pos */
+       stream->timer_period_frag = 0;  /* reset theoretical stream pos */
        stream->timer_buf_periods = 0;
        stream->timer_is_synced = 0;
  
-       stream_mask = stream->pipe->is_capture ? 1 : 1<<stream->substream->number;
+       stream_mask =
+         stream->pipe->is_capture ? 1 : 1<<stream->substream->number;
  
        pcxhr_init_rmh(&rmh, start ? CMD_START_STREAM : CMD_STOP_STREAM);
        pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture,
  
        err = pcxhr_send_msg(chip->mgr, &rmh);
        if (err)
-               snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state err=%x;\n", err);
-       stream->status = start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
+               snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state err=%x;\n",
+                          err);
+       stream->status =
+         start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
        return err;
  }
  
@@@ -399,13 -541,15 +541,15 @@@ static int pcxhr_set_format(struct pcxh
                header = HEADER_FMT_BASE_LIN;
                break;
        case SNDRV_PCM_FORMAT_S16_LE:
-               header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS | HEADER_FMT_INTEL;
+               header = HEADER_FMT_BASE_LIN |
+                        HEADER_FMT_16BITS | HEADER_FMT_INTEL;
                break;
        case SNDRV_PCM_FORMAT_S16_BE:
                header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS;
                break;
        case SNDRV_PCM_FORMAT_S24_3LE:
-               header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS | HEADER_FMT_INTEL;
+               header = HEADER_FMT_BASE_LIN |
+                        HEADER_FMT_24BITS | HEADER_FMT_INTEL;
                break;
        case SNDRV_PCM_FORMAT_S24_3BE:
                header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS;
                header = HEADER_FMT_BASE_FLOAT | HEADER_FMT_INTEL;
                break;
        default:
-               snd_printk(KERN_ERR "error pcxhr_set_format() : unknown format\n");
+               snd_printk(KERN_ERR
+                          "error pcxhr_set_format() : unknown format\n");
                return -EINVAL;
        }
        chip = snd_pcm_substream_chip(stream->substream);
        is_capture = stream->pipe->is_capture;
        stream_num = is_capture ? 0 : stream->substream->number;
  
-       pcxhr_init_rmh(&rmh, is_capture ? CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
-       pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, stream_num, 0);
-       if (is_capture)
-               rmh.cmd[0] |= 1<<12;
+       pcxhr_init_rmh(&rmh, is_capture ?
+                      CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
+       pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio,
+                                 stream_num, 0);
+       if (is_capture) {
+               /* bug with old dsp versions: */
+               /* bit 12 also sets the format of the playback stream */
+               if (DSP_EXT_CMD_SET(chip->mgr))
+                       rmh.cmd[0] |= 1<<10;
+               else
+                       rmh.cmd[0] |= 1<<12;
+       }
        rmh.cmd[1] = 0;
-       rmh.cmd[2] = header >> 8;
-       rmh.cmd[3] = (header & 0xff) << 16;
-       rmh.cmd_len = 4;
+       rmh.cmd_len = 2;
+       if (DSP_EXT_CMD_SET(chip->mgr)) {
+               /* add channels and set bit 19 if channels>2 */
+               rmh.cmd[1] = stream->channels;
+               if (!is_capture) {
+                       /* playback : add channel mask to command */
+                       rmh.cmd[2] = (stream->channels == 1) ? 0x01 : 0x03;
+                       rmh.cmd_len = 3;
+               }
+       }
+       rmh.cmd[rmh.cmd_len++] = header >> 8;
+       rmh.cmd[rmh.cmd_len++] = (header & 0xff) << 16;
        err = pcxhr_send_msg(chip->mgr, &rmh);
        if (err)
                snd_printk(KERN_ERR "ERROR pcxhr_set_format err=%x;\n", err);
@@@ -456,30 -618,38 +618,38 @@@ static int pcxhr_update_r_buffer(struc
        is_capture = (subs->stream == SNDRV_PCM_STREAM_CAPTURE);
        stream_num = is_capture ? 0 : subs->number;
  
-       snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
+       snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : "
+                   "addr(%p) bytes(%zx) subs(%d)\n",
                    is_capture ? 'c' : 'p',
                    chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
                    subs->runtime->dma_bytes, subs->number);
  
        pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS);
-       pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, stream_num, 0);
+       pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio,
+                                 stream_num, 0);
  
        /* max buffer size is 2 MByte */
        snd_BUG_ON(subs->runtime->dma_bytes >= 0x200000);
-       rmh.cmd[1] = subs->runtime->dma_bytes * 8;              /* size in bits */
-       rmh.cmd[2] = subs->runtime->dma_addr >> 24;             /* most significant byte */
-       rmh.cmd[2] |= 1<<19;                                    /* this is a circular buffer */
-       rmh.cmd[3] = subs->runtime->dma_addr & MASK_DSP_WORD;   /* least 3 significant bytes */
+       /* size in bits */
+       rmh.cmd[1] = subs->runtime->dma_bytes * 8;
+       /* most significant byte */
+       rmh.cmd[2] = subs->runtime->dma_addr >> 24;
+       /* this is a circular buffer */
+       rmh.cmd[2] |= 1<<19;
+       /* least 3 significant bytes */
+       rmh.cmd[3] = subs->runtime->dma_addr & MASK_DSP_WORD;
        rmh.cmd_len = 4;
        err = pcxhr_send_msg(chip->mgr, &rmh);
        if (err)
-               snd_printk(KERN_ERR "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err);
+               snd_printk(KERN_ERR
+                          "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err);
        return err;
  }
  
  
  #if 0
- static int pcxhr_pipe_sample_count(struct pcxhr_stream *stream, snd_pcm_uframes_t *sample_count)
+ static int pcxhr_pipe_sample_count(struct pcxhr_stream *stream,
+                                  snd_pcm_uframes_t *sample_count)
  {
        struct pcxhr_rmh rmh;
        int err;
@@@ -533,8 -703,8 +703,8 @@@ static void pcxhr_trigger_tasklet(unsig
                for (j = 0; j < chip->nb_streams_play; j++) {
                        if (pcxhr_stream_scheduled_get_pipe(&chip->playback_stream[j], &pipe)) {
                                playback_mask |= (1 << pipe->first_audio);
-                               break;  /* add only once, as all playback streams of
-                                        * one chip use the same pipe
+                               break;  /* add only once, as all playback
+                                        * streams of one chip use the same pipe
                                         */
                        }
                }
                return;
        }
  
-       snd_printdd("pcxhr_trigger_tasklet : playback_mask=%x capture_mask=%x\n",
+       snd_printdd("pcxhr_trigger_tasklet : "
+                   "playback_mask=%x capture_mask=%x\n",
                    playback_mask, capture_mask);
  
        /* synchronous stop of all the pipes concerned */
        err = pcxhr_set_pipe_state(mgr,  playback_mask, capture_mask, 0);
        if (err) {
                mutex_unlock(&mgr->setup_mutex);
-               snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error stop pipes (P%x C%x)\n",
+               snd_printk(KERN_ERR "pcxhr_trigger_tasklet : "
+                          "error stop pipes (P%x C%x)\n",
                           playback_mask, capture_mask);
                return;
        }
  
-       /* unfortunately the dsp lost format and buffer info with the stop pipe */
+       /* the dsp lost format and buffer info with the stop pipe */
        for (i = 0; i < mgr->num_cards; i++) {
                struct pcxhr_stream *stream;
                chip = mgr->chip[i];
        err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
        if (err) {
                mutex_unlock(&mgr->setup_mutex);
-               snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error start pipes (P%x C%x)\n",
+               snd_printk(KERN_ERR "pcxhr_trigger_tasklet : "
+                          "error start pipes (P%x C%x)\n",
                           playback_mask, capture_mask);
                return;
        }
  
-       /* put the streams into the running state now (increment pointer by interrupt) */
+       /* put the streams into the running state now
+        * (increment pointer by interrupt)
+        */
        spin_lock_irqsave(&mgr->lock, flags);
        for ( i =0; i < mgr->num_cards; i++) {
                struct pcxhr_stream *stream;
                        stream = &chip->playback_stream[j];
                        if (stream->status == PCXHR_STREAM_STATUS_STARTED) {
                                /* playback will already have advanced ! */
-                               stream->timer_period_frag += PCXHR_GRANULARITY;
+                               stream->timer_period_frag += mgr->granularity;
                                stream->status = PCXHR_STREAM_STATUS_RUNNING;
                        }
                }
@@@ -653,7 -828,7 +828,7 @@@ static int pcxhr_trigger(struct snd_pcm
                                        PCXHR_STREAM_STATUS_SCHEDULE_RUN;
                                snd_pcm_trigger_done(s, subs);
                        }
 -                      tasklet_hi_schedule(&chip->mgr->trigger_taskq);
 +                      tasklet_schedule(&chip->mgr->trigger_taskq);
                } else {
                        stream = subs->runtime->private_data;
                        snd_printdd("Only one Substream %c %d\n",
@@@ -697,12 -872,14 +872,14 @@@ static int pcxhr_hardware_timer(struct 
  
        pcxhr_init_rmh(&rmh, CMD_SET_TIMER_INTERRUPT);
        if (start) {
-               mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;    /* last dsp time invalid */
-               rmh.cmd[0] |= PCXHR_GRANULARITY;
+               /* last dsp time invalid */
+               mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
+               rmh.cmd[0] |= mgr->granularity;
        }
        err = pcxhr_send_msg(mgr, &rmh);
        if (err < 0)
-               snd_printk(KERN_ERR "error pcxhr_hardware_timer err(%x)\n", err);
+               snd_printk(KERN_ERR "error pcxhr_hardware_timer err(%x)\n",
+                          err);
        return err;
  }
  
@@@ -713,38 -890,16 +890,16 @@@ static int pcxhr_prepare(struct snd_pcm
  {
        struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
        struct pcxhr_mgr *mgr = chip->mgr;
-       /*
-       struct pcxhr_stream *stream = (pcxhr_stream_t*)subs->runtime->private_data;
-       */
        int err = 0;
  
        snd_printdd("pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n",
                    subs->runtime->period_size, subs->runtime->periods,
                    subs->runtime->buffer_size);
  
-       /*
-       if(subs->runtime->period_size <= PCXHR_GRANULARITY) {
-               snd_printk(KERN_ERR "pcxhr_prepare : error period_size too small (%x)\n",
-                          (unsigned int)subs->runtime->period_size);
-               return -EINVAL;
-       }
-       */
        mutex_lock(&mgr->setup_mutex);
  
        do {
-               /* if the stream was stopped before, format and buffer were reset */
-               /*
-               if(stream->status == PCXHR_STREAM_STATUS_STOPPED) {
-                       err = pcxhr_set_format(stream);
-                       if(err) break;
-                       err = pcxhr_update_r_buffer(stream);
-                       if(err) break;
-               }
-               */
                /* only the first stream can choose the sample rate */
-               /* the further opened streams will be limited to its frequency (see open) */
                /* set the clock only once (first stream) */
                if (mgr->sample_rate != subs->runtime->rate) {
                        err = pcxhr_set_clock(mgr, subs->runtime->rate);
@@@ -787,22 -942,9 +942,9 @@@ static int pcxhr_hw_params(struct snd_p
        stream->channels = channels;
        stream->format = format;
  
-       /* set the format to the board */
-       /*
-       err = pcxhr_set_format(stream);
-       if(err) {
-               mutex_unlock(&mgr->setup_mutex);
-               return err;
-       }
-       */
        /* allocate buffer */
        err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw));
  
-       /*
-       if (err > 0) {
-               err = pcxhr_update_r_buffer(stream);
-       }
-       */
        mutex_unlock(&mgr->setup_mutex);
  
        return err;
@@@ -820,14 -962,18 +962,18 @@@ static int pcxhr_hw_free(struct snd_pcm
   */
  static struct snd_pcm_hardware pcxhr_caps =
  {
-       .info             = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
-                             SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
-                             0 /*SNDRV_PCM_INFO_PAUSE*/),
-       .formats          = ( SNDRV_PCM_FMTBIT_U8 |
-                             SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
-                             SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
-                             SNDRV_PCM_FMTBIT_FLOAT_LE ),
-       .rates            = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
+       .info             = (SNDRV_PCM_INFO_MMAP |
+                            SNDRV_PCM_INFO_INTERLEAVED |
+                            SNDRV_PCM_INFO_MMAP_VALID |
+                            SNDRV_PCM_INFO_SYNC_START),
+       .formats          = (SNDRV_PCM_FMTBIT_U8 |
+                            SNDRV_PCM_FMTBIT_S16_LE |
+                            SNDRV_PCM_FMTBIT_S16_BE |
+                            SNDRV_PCM_FMTBIT_S24_3LE |
+                            SNDRV_PCM_FMTBIT_S24_3BE |
+                            SNDRV_PCM_FMTBIT_FLOAT_LE),
+       .rates            = (SNDRV_PCM_RATE_CONTINUOUS |
+                            SNDRV_PCM_RATE_8000_192000),
        .rate_min         = 8000,
        .rate_max         = 192000,
        .channels_min     = 1,
@@@ -847,6 -993,7 +993,7 @@@ static int pcxhr_open(struct snd_pcm_su
        struct pcxhr_mgr       *mgr = chip->mgr;
        struct snd_pcm_runtime *runtime = subs->runtime;
        struct pcxhr_stream    *stream;
+       int err;
  
        mutex_lock(&mgr->setup_mutex);
  
                return -EBUSY;
        }
  
+       /* float format support is in some cases buggy on stereo cards */
+       if (mgr->is_hr_stereo)
+               runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_FLOAT_LE;
+       /* buffer-size should better be multiple of period-size */
+       err = snd_pcm_hw_constraint_integer(runtime,
+                                           SNDRV_PCM_HW_PARAM_PERIODS);
+       if (err < 0) {
+               mutex_unlock(&mgr->setup_mutex);
+               return err;
+       }
        /* if a sample rate is already used or fixed by external clock,
         * the stream cannot change
         */
                                mutex_unlock(&mgr->setup_mutex);
                                return -EBUSY;
                        }
-                       runtime->hw.rate_min = runtime->hw.rate_max = external_rate;
+                       runtime->hw.rate_min = external_rate;
+                       runtime->hw.rate_max = external_rate;
                }
        }
  
  
        runtime->private_data = stream;
  
-       snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
-       snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
+       /* better get a divisor of granularity values (96 or 192) */
+       snd_pcm_hw_constraint_step(runtime, 0,
+                                  SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32);
+       snd_pcm_hw_constraint_step(runtime, 0,
+                                  SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32);
        snd_pcm_set_sync(subs);
  
        mgr->ref_count_rate++;
@@@ -919,11 -1081,12 +1081,12 @@@ static int pcxhr_close(struct snd_pcm_s
  
        mutex_lock(&mgr->setup_mutex);
  
-       snd_printdd("pcxhr_close chip%d subs%d\n", chip->chip_idx, subs->number);
+       snd_printdd("pcxhr_close chip%d subs%d\n",
+                   chip->chip_idx, subs->number);
  
        /* sample rate released */
        if (--mgr->ref_count_rate == 0) {
-               mgr->sample_rate = 0;           /* the sample rate is no more locked */
+               mgr->sample_rate = 0;   /* the sample rate is no more locked */
                pcxhr_hardware_timer(mgr, 0);   /* stop the DSP-timer */
        }
  
@@@ -1016,7 -1179,8 +1179,8 @@@ static int pcxhr_chip_dev_free(struct s
  
  /*
   */
- static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card, int idx)
+ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr,
+                                 struct snd_card *card, int idx)
  {
        int err;
        struct snd_pcxhr *chip;
                .dev_free = pcxhr_chip_dev_free,
        };
  
 -      mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 +      chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        if (! chip) {
                snd_printk(KERN_ERR "cannot allocate chip\n");
                return -ENOMEM;
  
        if (idx < mgr->capture_chips) {
                if (mgr->mono_capture)
-                       chip->nb_streams_capt = 2;      /* 2 mono streams (left+right) */
+                       chip->nb_streams_capt = 2;      /* 2 mono streams */
                else
                        chip->nb_streams_capt = 1;      /* or 1 stereo stream */
        }
                return err;
        }
  
 +      mgr->chip[idx] = chip;
        snd_card_set_dev(card, &mgr->pci->dev);
  
        return 0;
  }
  
  /* proc interface */
- static void pcxhr_proc_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+ static void pcxhr_proc_info(struct snd_info_entry *entry,
+                           struct snd_info_buffer *buffer)
  {
        struct snd_pcxhr *chip = entry->private_data;
        struct pcxhr_mgr *mgr = chip->mgr;
                short ver_maj = (mgr->dsp_version >> 16) & 0xff;
                short ver_min = (mgr->dsp_version >> 8) & 0xff;
                short ver_build = mgr->dsp_version & 0xff;
-               snd_iprintf(buffer, "module version %s\n", PCXHR_DRIVER_VERSION_STRING);
-               snd_iprintf(buffer, "dsp version %d.%d.%d\n", ver_maj, ver_min, ver_build);
+               snd_iprintf(buffer, "module version %s\n",
+                           PCXHR_DRIVER_VERSION_STRING);
+               snd_iprintf(buffer, "dsp version %d.%d.%d\n",
+                           ver_maj, ver_min, ver_build);
                if (mgr->board_has_analog)
                        snd_iprintf(buffer, "analog io available\n");
                else
                        if (ref > 0) {
                                if (mgr->sample_rate_real != 0 &&
                                    mgr->sample_rate_real != 48000) {
-                                       ref = (ref * 48000) / mgr->sample_rate_real;
-                                       if (mgr->sample_rate_real >= PCXHR_IRQ_TIMER_FREQ)
+                                       ref = (ref * 48000) /
+                                         mgr->sample_rate_real;
+                                       if (mgr->sample_rate_real >=
+                                           PCXHR_IRQ_TIMER_FREQ)
                                                ref *= 2;
                                }
                                cur = 100 - (100 * cur) / ref;
                                snd_iprintf(buffer, "cpu load    %d%%\n", cur);
-                               snd_iprintf(buffer, "buffer pool %d/%d kWords\n",
+                               snd_iprintf(buffer, "buffer pool %d/%d\n",
                                            rmh.stat[2], rmh.stat[3]);
                        }
                }
-               snd_iprintf(buffer, "dma granularity : %d\n", PCXHR_GRANULARITY);
-               snd_iprintf(buffer, "dsp time errors : %d\n", mgr->dsp_time_err);
+               snd_iprintf(buffer, "dma granularity : %d\n",
+                           mgr->granularity);
+               snd_iprintf(buffer, "dsp time errors : %d\n",
+                           mgr->dsp_time_err);
                snd_iprintf(buffer, "dsp async pipe xrun errors : %d\n",
                            mgr->async_err_pipe_xrun);
                snd_iprintf(buffer, "dsp async stream xrun errors : %d\n",
                rmh.cmd_idx = CMD_LAST_INDEX;
                if( ! pcxhr_send_msg(mgr, &rmh) ) {
                        int i;
+                       if (rmh.stat_len > 8)
+                               rmh.stat_len = 8;
                        for (i = 0; i < rmh.stat_len; i++)
-                               snd_iprintf(buffer, "debug[%02d] = %06x\n", i,  rmh.stat[i]);
+                               snd_iprintf(buffer, "debug[%02d] = %06x\n",
+                                           i,  rmh.stat[i]);
                }
        } else
                snd_iprintf(buffer, "no firmware loaded\n");
        snd_iprintf(buffer, "\n");
  }
- static void pcxhr_proc_sync(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
+ static void pcxhr_proc_sync(struct snd_info_entry *entry,
+                           struct snd_info_buffer *buffer)
  {
        struct snd_pcxhr *chip = entry->private_data;
        struct pcxhr_mgr *mgr = chip->mgr;
-       static char *texts[7] = {
-               "Internal", "Word", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
+       static const char *textsHR22[3] = {
+               "Internal", "AES Sync", "AES 1"
+       };
+       static const char *textsPCXHR[7] = {
+               "Internal", "Word", "AES Sync",
+               "AES 1", "AES 2", "AES 3", "AES 4"
        };
+       const char **texts;
+       int max_clock;
+       if (mgr->is_hr_stereo) {
+               texts = textsHR22;
+               max_clock = HR22_CLOCK_TYPE_MAX;
+       } else {
+               texts = textsPCXHR;
+               max_clock = PCXHR_CLOCK_TYPE_MAX;
+       }
  
        snd_iprintf(buffer, "\n%s\n", mgr->longname);
-       snd_iprintf(buffer, "Current Sample Clock\t: %s\n", texts[mgr->cur_clock_type]);
-       snd_iprintf(buffer, "Current Sample Rate\t= %d\n", mgr->sample_rate_real);
+       snd_iprintf(buffer, "Current Sample Clock\t: %s\n",
+                   texts[mgr->cur_clock_type]);
+       snd_iprintf(buffer, "Current Sample Rate\t= %d\n",
+                   mgr->sample_rate_real);
        /* commands available when embedded DSP is running */
        if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
                int i, err, sample_rate;
-               for (i = PCXHR_CLOCK_TYPE_WORD_CLOCK; i< (3 + mgr->capture_chips); i++) {
+               for (i = 1; i <= max_clock; i++) {
                        err = pcxhr_get_external_clock(mgr, i, &sample_rate);
                        if (err)
                                break;
-                       snd_iprintf(buffer, "%s Clock\t\t= %d\n", texts[i], sample_rate);
+                       snd_iprintf(buffer, "%s Clock\t\t= %d\n",
+                                   texts[i], sample_rate);
                }
        } else
                snd_iprintf(buffer, "no firmware loaded\n");
@@@ -1195,7 -1384,8 +1385,8 @@@ static int pcxhr_free(struct pcxhr_mgr 
  /*
   *    probe function - creates the card manager
   */
- static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+ static int __devinit pcxhr_probe(struct pci_dev *pci,
+                                const struct pci_device_id *pci_id)
  {
        static int dev;
        struct pcxhr_mgr *mgr;
  
        /* check if we can restrict PCI DMA transfers to 32 bits */
        if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) {
-               snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
+               snd_printk(KERN_ERR "architecture does not support "
+                          "32bit PCI busmaster DMA\n");
                pci_disable_device(pci);
                return -ENXIO;
        }
                pci_disable_device(pci);
                return -ENODEV;
        }
-       card_name = pcxhr_board_params[pci_id->driver_data].board_name;
-       mgr->playback_chips = pcxhr_board_params[pci_id->driver_data].playback_chips;
-       mgr->capture_chips  = pcxhr_board_params[pci_id->driver_data].capture_chips;
-       mgr->firmware_num  = pcxhr_board_params[pci_id->driver_data].firmware_num;
+       card_name =
+               pcxhr_board_params[pci_id->driver_data].board_name;
+       mgr->playback_chips =
+               pcxhr_board_params[pci_id->driver_data].playback_chips;
+       mgr->capture_chips  =
+               pcxhr_board_params[pci_id->driver_data].capture_chips;
+       mgr->fw_file_set =
+               pcxhr_board_params[pci_id->driver_data].fw_file_set;
+       mgr->firmware_num  =
+               pcxhr_board_params[pci_id->driver_data].firmware_num;
        mgr->mono_capture = mono[dev];
+       mgr->is_hr_stereo = (mgr->playback_chips == 1);
+       mgr->board_has_aes1 = PCXHR_BOARD_HAS_AES1(mgr);
+       mgr->board_aes_in_192k = !PCXHR_BOARD_AESIN_NO_192K(mgr);
+       if (mgr->is_hr_stereo)
+               mgr->granularity = PCXHR_GRANULARITY_HR22;
+       else
+               mgr->granularity = PCXHR_GRANULARITY;
  
        /* resource assignment */
        if ((err = pci_request_regions(pci, card_name)) < 0) {
        mgr->irq = pci->irq;
  
        sprintf(mgr->shortname, "Digigram %s", card_name);
-       sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, 0x%lx irq %i", mgr->shortname,
+       sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, 0x%lx irq %i",
+               mgr->shortname,
                mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq);
  
        /* ISR spinlock  */
        mutex_init(&mgr->setup_mutex);
  
        /* init taslket */
-       tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, (unsigned long) mgr);
-       tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet, (unsigned long) mgr);
+       tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet,
+                    (unsigned long) mgr);
+       tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet,
+                    (unsigned long) mgr);
        mgr->prmh = kmalloc(sizeof(*mgr->prmh) + 
-                           sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS - PCXHR_SIZE_MAX_STATUS),
+                           sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
+                                          PCXHR_SIZE_MAX_STATUS),
                            GFP_KERNEL);
        if (! mgr->prmh) {
                pcxhr_free(mgr);
                else
                        idx = index[dev] + i;
  
-               snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : card_name, i);
+               snprintf(tmpid, sizeof(tmpid), "%s-%d",
+                        id[dev] ? id[dev] : card_name, i);
                card = snd_card_new(idx, tmpid, THIS_MODULE, 0);
  
                if (! card) {
                sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i);
  
                if ((err = pcxhr_create(mgr, card, i)) < 0) {
 +                      snd_card_free(card);
                        pcxhr_free(mgr);
                        return err;
                }
index 4a5481f9781fec6e742786e3e45c4df7f1607f0e,d5f18226261d8b770f2569c1358d670516b31da9..833e7180ad2de0d0a3f66683274a4446c57dc4e4
@@@ -132,13 -132,15 +132,15 @@@ static int pcxhr_check_reg_bit(struct p
                *read = PCXHR_INPB(mgr, reg);
                if ((*read & mask) == bit) {
                        if (i > 100)
-                               snd_printdd("ATTENTION! check_reg(%x) loopcount=%d\n",
+                               snd_printdd("ATTENTION! check_reg(%x) "
+                                           "loopcount=%d\n",
                                            reg, i);
                        return 0;
                }
                i++;
        } while (time_after_eq(end_time, jiffies));
-       snd_printk(KERN_ERR "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=0x%x\n",
+       snd_printk(KERN_ERR
+                  "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=%x\n",
                   reg, mask, *read);
        return -EIO;
  }
  #define PCXHR_IT_TEST_XILINX          (0x0000003C | PCXHR_MASK_IT_HF1 | \
                                         PCXHR_MASK_IT_MANAGE_HF5)
  #define PCXHR_IT_DOWNLOAD_BOOT                (0x0000000C | PCXHR_MASK_IT_HF1 | \
-                                        PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT)
+                                        PCXHR_MASK_IT_MANAGE_HF5 | \
+                                        PCXHR_MASK_IT_WAIT)
  #define PCXHR_IT_RESET_BOARD_FUNC     (0x0000000C | PCXHR_MASK_IT_HF0 | \
-                                        PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT_EXTRA)
+                                        PCXHR_MASK_IT_MANAGE_HF5 | \
+                                        PCXHR_MASK_IT_WAIT_EXTRA)
  #define PCXHR_IT_DOWNLOAD_DSP         (0x0000000C | \
-                                        PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT)
+                                        PCXHR_MASK_IT_MANAGE_HF5 | \
+                                        PCXHR_MASK_IT_WAIT)
  #define PCXHR_IT_DEBUG                        (0x0000005A | PCXHR_MASK_IT_NO_HF0_HF1)
  #define PCXHR_IT_RESET_SEMAPHORE      (0x0000005C | PCXHR_MASK_IT_NO_HF0_HF1)
  #define PCXHR_IT_MESSAGE              (0x00000074 | PCXHR_MASK_IT_NO_HF0_HF1)
  #define PCXHR_IT_RESET_CHK            (0x00000076 | PCXHR_MASK_IT_NO_HF0_HF1)
  #define PCXHR_IT_UPDATE_RBUFFER               (0x00000078 | PCXHR_MASK_IT_NO_HF0_HF1)
  
- static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, unsigned int itdsp, int atomic)
+ static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr,
+                            unsigned int itdsp, int atomic)
  {
        int err;
        unsigned char reg;
        if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) {
                /* clear hf5 bit */
                PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0,
-                           PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & ~PCXHR_MBOX0_HF5);
+                           PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) &
+                           ~PCXHR_MBOX0_HF5);
        }
        if ((itdsp & PCXHR_MASK_IT_NO_HF0_HF1) == 0) {
-               reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ;
+               reg = (PCXHR_ICR_HI08_RREQ |
+                      PCXHR_ICR_HI08_TREQ |
+                      PCXHR_ICR_HI08_HDRQ);
                if (itdsp & PCXHR_MASK_IT_HF0)
                        reg |= PCXHR_ICR_HI08_HF0;
                if (itdsp & PCXHR_MASK_IT_HF1)
                        reg |= PCXHR_ICR_HI08_HF1;
                PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg);
        }
-       reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) | PCXHR_CVR_HI08_HC);
+       reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) |
+                             PCXHR_CVR_HI08_HC);
        PCXHR_OUTPB(mgr, PCXHR_DSP_CVR, reg);
        if (itdsp & PCXHR_MASK_IT_WAIT) {
                if (atomic)
        }
        if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) {
                /* wait for hf5 bit */
-               err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5,
-                                         PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, &reg);
+               err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0,
+                                         PCXHR_MBOX0_HF5,
+                                         PCXHR_MBOX0_HF5,
+                                         PCXHR_TIMEOUT_DSP,
+                                         &reg);
                if (err) {
-                       snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT HF5\n");
+                       snd_printk(KERN_ERR
+                                  "pcxhr_send_it_dsp : TIMEOUT HF5\n");
                        return err;
                }
        }
@@@ -263,7 -277,8 +277,8 @@@ void pcxhr_enable_dsp(struct pcxhr_mgr 
  /*
   * load the xilinx image
   */
- int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilinx, int second)
+ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr,
+                            const struct firmware *xilinx, int second)
  {
        unsigned int i;
        unsigned int chipsc;
        /* test first xilinx */
        chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC);
        /* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */
-       /* this bit will always be 1; no possibility to test presence of first xilinx */
+       /* this bit will always be 1;
+        * no possibility to test presence of first xilinx
+        */
        if(second) {
                if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) {
                        snd_printk(KERN_ERR "error loading first xilinx\n");
                data = *image;
                mask = 0x80;
                while (mask) {
-                       chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | PCXHR_CHIPSC_DATA_IN);
+                       chipsc &= ~(PCXHR_CHIPSC_DATA_CLK |
+                                   PCXHR_CHIPSC_DATA_IN);
                        if (data & mask)
                                chipsc |= PCXHR_CHIPSC_DATA_IN;
                        PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc);
@@@ -330,15 -348,20 +348,20 @@@ static int pcxhr_download_dsp(struct pc
                data = dsp->data + i;
                if (i == 0) {
                        /* test data header consistency */
-                       len = (unsigned int)((data[0]<<16) + (data[1]<<8) + data[2]);
-                       if (len && dsp->size != (len + 2) * 3)
+                       len = (unsigned int)((data[0]<<16) +
+                                            (data[1]<<8) +
+                                            data[2]);
+                       if (len && (dsp->size != (len + 2) * 3))
                                return -EINVAL;
                }
                /* wait DSP ready for new transfer */
-               err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
-                                         PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &dummy);
+               err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+                                         PCXHR_ISR_HI08_TRDY,
+                                         PCXHR_ISR_HI08_TRDY,
+                                         PCXHR_TIMEOUT_DSP, &dummy);
                if (err) {
-                       snd_printk(KERN_ERR "dsp loading error at position %d\n", i);
+                       snd_printk(KERN_ERR
+                                  "dsp loading error at position %d\n", i);
                        return err;
                }
                /* send host data */
  /*
   * load the eeprom image
   */
- int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, const struct firmware *eeprom)
+ int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr,
+                            const struct firmware *eeprom)
  {
        int err;
        unsigned char reg;
        /* init value of the ICR register */
        reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ;
        if (PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & PCXHR_MBOX0_BOOT_HERE) {
-               /* no need to load the eeprom binary, but init the HI08 interface */
+               /* no need to load the eeprom binary,
+                * but init the HI08 interface
+                */
                PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg | PCXHR_ICR_HI08_INIT);
                msleep(PCXHR_WAIT_DEFAULT);
                PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg);
@@@ -429,8 -455,10 +455,10 @@@ int pcxhr_load_dsp_binary(struct pcxhr_
        if (err)
                return err;
        /* wait for chk bit */
-       return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,
-                                  PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &dummy);
+       return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+                                  PCXHR_ISR_HI08_CHK,
+                                  PCXHR_ISR_HI08_CHK,
+                                  PCXHR_TIMEOUT_DSP, &dummy);
  }
  
  
@@@ -443,8 -471,8 +471,8 @@@ struct pcxhr_cmd_info 
  /* RMH status type */
  enum {
        RMH_SSIZE_FIXED = 0,    /* status size fix (st_length = 0..x) */
-       RMH_SSIZE_ARG = 1,      /* status size given in the LSB byte (used with st_length = 1) */
-       RMH_SSIZE_MASK = 2,     /* status size given in bitmask  (used with st_length = 1) */
+       RMH_SSIZE_ARG = 1,      /* status size given in the LSB byte */
+       RMH_SSIZE_MASK = 2,     /* status size given in bitmask */
  };
  
  /*
@@@ -474,7 -502,7 +502,7 @@@ static struct pcxhr_cmd_info pcxhr_dsp_
  [CMD_UPDATE_R_BUFFERS] =              { 0x840000, 0, RMH_SSIZE_FIXED },
  [CMD_FORMAT_STREAM_OUT] =             { 0x860000, 0, RMH_SSIZE_FIXED },
  [CMD_FORMAT_STREAM_IN] =              { 0x870000, 0, RMH_SSIZE_FIXED },
- [CMD_STREAM_SAMPLE_COUNT] =           { 0x902000, 2, RMH_SSIZE_FIXED },       /* stat_len = nb_streams * 2 */
+ [CMD_STREAM_SAMPLE_COUNT] =           { 0x902000, 2, RMH_SSIZE_FIXED },
  [CMD_AUDIO_LEVEL_ADJUST] =            { 0xc22000, 0, RMH_SSIZE_FIXED },
  };
  
@@@ -524,10 -552,13 +552,13 @@@ static int pcxhr_read_rmh_status(struc
  
        for (i = 0; i < rmh->stat_len; i++) {
                /* wait for receiver full */
-               err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,
-                                         PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);
+               err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+                                         PCXHR_ISR_HI08_RXDF,
+                                         PCXHR_ISR_HI08_RXDF,
+                                         PCXHR_TIMEOUT_DSP, &reg);
                if (err) {
-                       snd_printk(KERN_ERR "ERROR RMH stat: ISR:RXDF=1 (ISR = %x; i=%d )\n",
+                       snd_printk(KERN_ERR "ERROR RMH stat: "
+                                  "ISR:RXDF=1 (ISR = %x; i=%d )\n",
                                   reg, i);
                        return err;
                }
                data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);
  
                /* need to update rmh->stat_len on the fly ?? */
-               if (i==0) {
+               if (!i) {
                        if (rmh->dsp_stat != RMH_SSIZE_FIXED) {
                                if (rmh->dsp_stat == RMH_SSIZE_ARG) {
-                                       rmh->stat_len = (u16)(data & 0x0000ff) + 1;
+                                       rmh->stat_len = (data & 0x0000ff) + 1;
                                        data &= 0xffff00;
                                } else {
                                        /* rmh->dsp_stat == RMH_SSIZE_MASK */
                        rmh->stat[i] = data;
        }
        if (rmh->stat_len > max_stat_len) {
-               snd_printdd("PCXHR : rmh->stat_len=%x too big\n", rmh->stat_len);
+               snd_printdd("PCXHR : rmh->stat_len=%x too big\n",
+                           rmh->stat_len);
                rmh->stat_len = max_stat_len;
        }
        return 0;
@@@ -605,7 -637,8 +637,8 @@@ static int pcxhr_send_msg_nolock(struc
                data &= 0xff7fff;       /* MASK_1_WORD_COMMAND */
  #ifdef CONFIG_SND_DEBUG_VERBOSE
        if (rmh->cmd_idx < CMD_LAST_INDEX)
-               snd_printdd("MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]);
+               snd_printdd("MSG cmd[0]=%x (%s)\n",
+                           data, cmd_names[rmh->cmd_idx]);
  #endif
  
        err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
        if (rmh->cmd_len > 1) {
                /* send length */
                data = rmh->cmd_len - 1;
-               err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
-                                         PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &reg);
+               err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+                                         PCXHR_ISR_HI08_TRDY,
+                                         PCXHR_ISR_HI08_TRDY,
+                                         PCXHR_TIMEOUT_DSP, &reg);
                if (err)
                        return err;
                PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF);
        /* test status ISR */
        if (reg & PCXHR_ISR_HI08_ERR) {
                /* ERROR, wait for receiver full */
-               err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,
-                                         PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);
+               err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
+                                         PCXHR_ISR_HI08_RXDF,
+                                         PCXHR_ISR_HI08_RXDF,
+                                         PCXHR_TIMEOUT_DSP, &reg);
                if (err) {
                        snd_printk(KERN_ERR "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg);
                        return err;
                data  = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16;
                data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8;
                data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);
-               snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n", rmh->cmd_idx, data);
+               snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n",
+                          rmh->cmd_idx, data);
                err = -EINVAL;
        } else {
                /* read the response data */
@@@ -732,8 -770,9 +770,9 @@@ int pcxhr_send_msg(struct pcxhr_mgr *mg
  static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr)
  {
        int start_mask = PCXHR_INPL(mgr, PCXHR_PLX_MBOX2);
-       /* least segnificant 12 bits are the pipe states for the playback audios */
-       /* next 12 bits are the pipe states for the capture audios
+       /* least segnificant 12 bits are the pipe states
+        * for the playback audios
+        * next 12 bits are the pipe states for the capture audios
         * (PCXHR_PIPE_STATE_CAPTURE_OFFSET)
         */
        start_mask &= 0xffffff;
  #define PCXHR_PIPE_STATE_CAPTURE_OFFSET               12
  #define MAX_WAIT_FOR_DSP                      20
  
- static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, int audio_mask, int *retry)
+ static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr,
+                                   int audio_mask, int *retry)
  {
        struct pcxhr_rmh rmh;
        int err;
                        } else {
                                /* can start capture pipe */
                                pcxhr_set_pipe_cmd_params(&rmh, 1, audio -
-                                                         PCXHR_PIPE_STATE_CAPTURE_OFFSET,
-                                                         0, 0);
+                                               PCXHR_PIPE_STATE_CAPTURE_OFFSET,
+                                               0, 0);
                        }
                        err = pcxhr_send_msg(mgr, &rmh);
                        if (err) {
                                snd_printk(KERN_ERR
-                                          "error pipe start (CMD_CAN_START_PIPE) err=%x!\n",
+                                          "error pipe start "
+                                          "(CMD_CAN_START_PIPE) err=%x!\n",
                                           err);
                                return err;
                        }
-                       /* if the pipe couldn't be prepaired for start, retry it later */
+                       /* if the pipe couldn't be prepaired for start,
+                        * retry it later
+                        */
                        if (rmh.stat[0] == 0)
                                *retry |= (1<<audio);
                }
@@@ -795,14 -838,14 +838,14 @@@ static int pcxhr_stop_pipes(struct pcxh
                        } else {
                                /* stop capture pipe */
                                pcxhr_set_pipe_cmd_params(&rmh, 1, audio -
-                                                         PCXHR_PIPE_STATE_CAPTURE_OFFSET,
-                                                         0, 0);
+                                               PCXHR_PIPE_STATE_CAPTURE_OFFSET,
+                                               0, 0);
                        }
                        err = pcxhr_send_msg(mgr, &rmh);
                        if (err) {
                                snd_printk(KERN_ERR
-                                          "error pipe stop (CMD_STOP_PIPE) err=%x!\n",
-                                          err);
+                                          "error pipe stop "
+                                          "(CMD_STOP_PIPE) err=%x!\n", err);
                                return err;
                        }
                }
@@@ -822,15 -865,16 +865,16 @@@ static int pcxhr_toggle_pipes(struct pc
                if (audio_mask & 1) {
                        pcxhr_init_rmh(&rmh, CMD_CONF_PIPE);
                        if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET)
-                               pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0, 1 << audio);
+                               pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0,
+                                                         1 << audio);
                        else
                                pcxhr_set_pipe_cmd_params(&rmh, 1, 0, 0,
                                                          1 << (audio - PCXHR_PIPE_STATE_CAPTURE_OFFSET));
                        err = pcxhr_send_msg(mgr, &rmh);
                        if (err) {
                                snd_printk(KERN_ERR
-                                          "error pipe start (CMD_CONF_PIPE) err=%x!\n",
-                                          err);
+                                          "error pipe start "
+                                          "(CMD_CONF_PIPE) err=%x!\n", err);
                                return err;
                        }
                }
        pcxhr_init_rmh(&rmh, CMD_SEND_IRQA);
        err = pcxhr_send_msg(mgr, &rmh);
        if (err) {
-               snd_printk(KERN_ERR "error pipe start (CMD_SEND_IRQA) err=%x!\n", err );
+               snd_printk(KERN_ERR
+                          "error pipe start (CMD_SEND_IRQA) err=%x!\n",
+                          err);
                return err;
        }
        return 0;
  
  
  
- int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_mask, int start)
+ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask,
+                        int capture_mask, int start)
  {
        int state, i, err;
        int audio_mask;
        struct timeval my_tv1, my_tv2;
        do_gettimeofday(&my_tv1);
  #endif
-       audio_mask = (playback_mask | (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET));
+       audio_mask = (playback_mask |
+                     (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET));
        /* current pipe state (playback + record) */
        state = pcxhr_pipes_running(mgr);
        snd_printdd("pcxhr_set_pipe_state %s (mask %x current %x)\n",
                    start ? "START" : "STOP", audio_mask, state);
        if (start) {
-               audio_mask &= ~state;   /* start only pipes that are not yet started */
+               /* start only pipes that are not yet started */
+               audio_mask &= ~state;
                state = audio_mask;
                for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
                        err = pcxhr_prepair_pipe_start(mgr, state, &state);
                        if (err)
                                return err;
                        if (state == 0)
-                               break;  /* success, all pipes prepaired for start */
-                       mdelay(1);              /* otherwise wait 1 millisecond and retry */
+                               break;  /* success, all pipes prepaired */
+                       mdelay(1);      /* wait 1 millisecond and retry */
                }
        } else {
                audio_mask &= state;    /* stop only pipes that are started */
                if ((state & audio_mask) == (start ? audio_mask : 0))
                        break;
                if (++i >= MAX_WAIT_FOR_DSP * 100) {
-                       snd_printk(KERN_ERR "error pipe start/stop (ED_NO_RESPONSE_AT_IRQA)\n");
+                       snd_printk(KERN_ERR "error pipe start/stop\n");
                        return -EBUSY;
                }
                udelay(10);                     /* wait 10 microseconds */
@@@ -918,7 -967,8 +967,8 @@@ int pcxhr_write_io_num_reg_cont(struct 
  
        spin_lock_irqsave(&mgr->msg_lock, flags);
        if ((mgr->io_num_reg_cont & mask) == value) {
-               snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n", mask, value);
+               snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n",
+                           mask, value);
                if (changed)
                        *changed = 0;
                spin_unlock_irqrestore(&mgr->msg_lock, flags);
@@@ -971,7 -1021,8 +1021,8 @@@ static int pcxhr_handle_async_err(struc
                err = ((err >> 12) & 0xfff);
        if (!err)
                return 0;
-       snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n", err_src_name[err_src],
+       snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n",
+                   err_src_name[err_src],
                    is_capture ? "Record" : "Play", pipe, err);
        if (err == 0xe01)
                mgr->async_err_stream_xrun++;
@@@ -996,6 -1047,13 +1047,13 @@@ void pcxhr_msg_tasklet(unsigned long ar
                snd_printdd("TASKLET : PCXHR_IRQ_TIME_CODE event occured\n");
        if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY)
                snd_printdd("TASKLET : PCXHR_IRQ_NOTIFY event occured\n");
+       if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) {
+               /* clear events FREQ_CHANGE and TIME_CODE */
+               pcxhr_init_rmh(prmh, CMD_TEST_IT);
+               err = pcxhr_send_msg(mgr, prmh);
+               snd_printdd("CMD_TEST_IT : err=%x, stat=%x\n",
+                           err, prmh->stat[0]);
+       }
        if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) {
                snd_printdd("TASKLET : PCXHR_IRQ_ASYNC event occured\n");
  
                prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS;
                err = pcxhr_send_msg(mgr, prmh);
                if (err)
-                       snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n", err);
+                       snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n",
+                                  err);
                i = 1;
                while (i < prmh->stat_len) {
-                       int nb_audio = (prmh->stat[i] >> FIELD_SIZE) & MASK_FIRST_FIELD;
-                       int nb_stream = (prmh->stat[i] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD;
+                       int nb_audio = ((prmh->stat[i] >> FIELD_SIZE) &
+                                       MASK_FIRST_FIELD);
+                       int nb_stream = ((prmh->stat[i] >> (2*FIELD_SIZE)) &
+                                        MASK_FIRST_FIELD);
                        int pipe = prmh->stat[i] & MASK_FIRST_FIELD;
                        int is_capture = prmh->stat[i] & 0x400000;
                        u32 err2;
  
                        if (prmh->stat[i] & 0x800000) { /* if BIT_END */
                                snd_printdd("TASKLET : End%sPipe %d\n",
-                                           is_capture ? "Record" : "Play", pipe);
+                                           is_capture ? "Record" : "Play",
+                                           pipe);
                        }
                        i++;
                        err2 = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
@@@ -1062,7 -1124,7 +1124,7 @@@ static u_int64_t pcxhr_stream_read_posi
        pcxhr_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);
        pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture,
                                  stream->pipe->first_audio, 0, stream_mask);
-       /* rmh.stat_len = 2; */         /* 2 resp data for each stream of the pipe */
+       /* rmh.stat_len = 2; */ /* 2 resp data for each stream of the pipe */
  
        err = pcxhr_send_msg(mgr, &rmh);
        if (err)
        hw_sample_count += (u_int64_t)rmh.stat[1];
  
        snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n",
-                   stream->pipe->is_capture ? 'C':'P', stream->substream->number,
+                   stream->pipe->is_capture ? 'C' : 'P',
+                   stream->substream->number,
                    (long unsigned int)hw_sample_count,
                    (long unsigned int)(stream->timer_abs_periods +
-                                       stream->timer_period_frag + PCXHR_GRANULARITY));
+                                       stream->timer_period_frag +
+                                       mgr->granularity));
        return hw_sample_count;
  }
  
  static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
-                                  struct pcxhr_stream *stream, int samples_to_add)
+                                  struct pcxhr_stream *stream,
+                                  int samples_to_add)
  {
-       if (stream->substream && (stream->status == PCXHR_STREAM_STATUS_RUNNING)) {
+       if (stream->substream &&
+           (stream->status == PCXHR_STREAM_STATUS_RUNNING)) {
                u_int64_t new_sample_count;
                int elapsed = 0;
                int hardware_read = 0;
                if (samples_to_add < 0) {
                        stream->timer_is_synced = 0;
                        /* add default if no hardware_read possible */
-                       samples_to_add = PCXHR_GRANULARITY;
+                       samples_to_add = mgr->granularity;
                }
  
                if (!stream->timer_is_synced) {
-                       if (stream->timer_abs_periods != 0 ||
-                           stream->timer_period_frag + PCXHR_GRANULARITY >=
-                           runtime->period_size) {
-                               new_sample_count = pcxhr_stream_read_position(mgr, stream);
+                       if ((stream->timer_abs_periods != 0) ||
+                           ((stream->timer_period_frag + samples_to_add) >=
+                           runtime->period_size)) {
+                               new_sample_count =
+                                 pcxhr_stream_read_position(mgr, stream);
                                hardware_read = 1;
-                               if (new_sample_count >= PCXHR_GRANULARITY_MIN) {
-                                       /* sub security offset because of jitter and
-                                        * finer granularity of dsp time (MBOX4)
+                               if (new_sample_count >= mgr->granularity) {
+                                       /* sub security offset because of
+                                        * jitter and finer granularity of
+                                        * dsp time (MBOX4)
                                         */
-                                       new_sample_count -= PCXHR_GRANULARITY_MIN;
+                                       new_sample_count -= mgr->granularity;
                                        stream->timer_is_synced = 1;
                                }
                        }
                                stream->timer_buf_periods = 0;
                        stream->timer_abs_periods = new_elapse_pos;
                }
-               if (new_sample_count >= stream->timer_abs_periods)
-                       stream->timer_period_frag = (u_int32_t)(new_sample_count -
-                                                               stream->timer_abs_periods);
-               else
-                       snd_printk(KERN_ERR "ERROR new_sample_count too small ??? %lx\n",
+               if (new_sample_count >= stream->timer_abs_periods) {
+                       stream->timer_period_frag =
+                               (u_int32_t)(new_sample_count -
+                                           stream->timer_abs_periods);
+               } else {
+                       snd_printk(KERN_ERR
+                                  "ERROR new_sample_count too small ??? %ld\n",
                                   (long unsigned int)new_sample_count);
+               }
  
                if (elapsed) {
                        spin_unlock(&mgr->lock);
        }
  }
  
  irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
  {
        struct pcxhr_mgr *mgr = dev_id;
        reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS);
        if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) {
                spin_unlock(&mgr->lock);
-               return IRQ_NONE;        /* this device did not cause the interrupt */
+               /* this device did not cause the interrupt */
+               return IRQ_NONE;
        }
  
        /* clear interrupt */
        if (reg & PCXHR_IRQ_TIMER) {
                int timer_toggle = reg & PCXHR_IRQ_TIMER;
                /* is a 24 bit counter */
-               int dsp_time_new = PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
+               int dsp_time_new =
+                       PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
                int dsp_time_diff = dsp_time_new - mgr->dsp_time_last;
  
-               if (dsp_time_diff < 0 && mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID) {
+               if ((dsp_time_diff < 0) &&
+                   (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) {
                        snd_printdd("ERROR DSP TIME old(%d) new(%d) -> "
                                    "resynchronize all streams\n",
                                    mgr->dsp_time_last, dsp_time_new);
                }
  #ifdef CONFIG_SND_DEBUG_VERBOSE
                if (dsp_time_diff == 0)
-                       snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", dsp_time_new);
-               else if (dsp_time_diff >= (2*PCXHR_GRANULARITY))
+                       snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n",
+                                   dsp_time_new);
+               else if (dsp_time_diff >= (2*mgr->granularity))
                        snd_printdd("ERROR DSP TIME TOO BIG old(%d) add(%d)\n",
-                                   mgr->dsp_time_last, dsp_time_new - mgr->dsp_time_last);
+                                   mgr->dsp_time_last,
+                                   dsp_time_new - mgr->dsp_time_last);
+               else if (dsp_time_diff % mgr->granularity)
+                       snd_printdd("ERROR DSP TIME increased by %d\n",
+                                   dsp_time_diff);
  #endif
                mgr->dsp_time_last = dsp_time_new;
  
-               if (timer_toggle == mgr->timer_toggle)
+               if (timer_toggle == mgr->timer_toggle) {
                        snd_printdd("ERROR TIMER TOGGLE\n");
+                       mgr->dsp_time_err++;
+               }
                mgr->timer_toggle = timer_toggle;
  
                reg &= ~PCXHR_IRQ_TIMER;
                for (i = 0; i < mgr->num_cards; i++) {
                        chip = mgr->chip[i];
                        for (j = 0; j < chip->nb_streams_capt; j++)
-                               pcxhr_update_timer_pos(mgr, &chip->capture_stream[j],
-                                                      dsp_time_diff);
+                               pcxhr_update_timer_pos(mgr,
+                                               &chip->capture_stream[j],
+                                               dsp_time_diff);
                }
                for (i = 0; i < mgr->num_cards; i++) {
                        chip = mgr->chip[i];
                        for (j = 0; j < chip->nb_streams_play; j++)
-                               pcxhr_update_timer_pos(mgr, &chip->playback_stream[j],
-                                                      dsp_time_diff);
+                               pcxhr_update_timer_pos(mgr,
+                                               &chip->playback_stream[j],
+                                               dsp_time_diff);
                }
        }
        /* other irq's handled in the tasklet */
        if (reg & PCXHR_IRQ_MASK) {
-               /* as we didn't request any notifications, some kind of xrun error
-                * will probably occured
-                */
-               /* better resynchronize all streams next interrupt : */
-               mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
-               
+               if (reg & PCXHR_IRQ_ASYNC) {
+                       /* as we didn't request any async notifications,
+                        * some kind of xrun error will probably occured
+                        */
+                       /* better resynchronize all streams next interrupt : */
+                       mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
+               }
                mgr->src_it_dsp = reg;
 -              tasklet_hi_schedule(&mgr->msg_taskq);
 +              tasklet_schedule(&mgr->msg_taskq);
        }
  #ifdef CONFIG_SND_DEBUG_VERBOSE
        if (reg & PCXHR_FATAL_DSP_ERR)