ALSA: hda: track CIRB/CORB command/response states for each codec
[pandora-kernel.git] / sound / pci / hda / hda_intel.c
index 3128e1a..19e67a1 100644 (file)
@@ -128,21 +128,33 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
                         "{ULI, M5461}}");
 MODULE_DESCRIPTION("Intel HDA driver");
 
+#ifdef CONFIG_SND_VERBOSE_PRINTK
+#define SFX    /* nop */
+#else
 #define SFX    "hda-intel: "
-
+#endif
 
 /*
  * registers
  */
 #define ICH6_REG_GCAP                  0x00
+#define   ICH6_GCAP_64OK       (1 << 0)   /* 64bit address support */
+#define   ICH6_GCAP_NSDO       (3 << 1)   /* # of serial data out signals */
+#define   ICH6_GCAP_BSS                (31 << 3)  /* # of bidirectional streams */
+#define   ICH6_GCAP_ISS                (15 << 8)  /* # of input streams */
+#define   ICH6_GCAP_OSS                (15 << 12) /* # of output streams */
 #define ICH6_REG_VMIN                  0x02
 #define ICH6_REG_VMAJ                  0x03
 #define ICH6_REG_OUTPAY                        0x04
 #define ICH6_REG_INPAY                 0x06
 #define ICH6_REG_GCTL                  0x08
+#define   ICH6_GCTL_RESET      (1 << 0)   /* controller reset */
+#define   ICH6_GCTL_FCNTRL     (1 << 1)   /* flush control */
+#define   ICH6_GCTL_UNSOL      (1 << 8)   /* accept unsol. response enable */
 #define ICH6_REG_WAKEEN                        0x0c
 #define ICH6_REG_STATESTS              0x0e
 #define ICH6_REG_GSTS                  0x10
+#define   ICH6_GSTS_FSTS       (1 << 1)   /* flush status */
 #define ICH6_REG_INTCTL                        0x20
 #define ICH6_REG_INTSTS                        0x24
 #define ICH6_REG_WALCLK                        0x30
@@ -150,17 +162,27 @@ MODULE_DESCRIPTION("Intel HDA driver");
 #define ICH6_REG_CORBLBASE             0x40
 #define ICH6_REG_CORBUBASE             0x44
 #define ICH6_REG_CORBWP                        0x48
-#define ICH6_REG_CORBRP                        0x4A
+#define ICH6_REG_CORBRP                        0x4a
+#define   ICH6_CORBRP_RST      (1 << 15)  /* read pointer reset */
 #define ICH6_REG_CORBCTL               0x4c
+#define   ICH6_CORBCTL_RUN     (1 << 1)   /* enable DMA */
+#define   ICH6_CORBCTL_CMEIE   (1 << 0)   /* enable memory error irq */
 #define ICH6_REG_CORBSTS               0x4d
+#define   ICH6_CORBSTS_CMEI    (1 << 0)   /* memory error indication */
 #define ICH6_REG_CORBSIZE              0x4e
 
 #define ICH6_REG_RIRBLBASE             0x50
 #define ICH6_REG_RIRBUBASE             0x54
 #define ICH6_REG_RIRBWP                        0x58
+#define   ICH6_RIRBWP_RST      (1 << 15)  /* write pointer reset */
 #define ICH6_REG_RINTCNT               0x5a
 #define ICH6_REG_RIRBCTL               0x5c
+#define   ICH6_RBCTL_IRQ_EN    (1 << 0)   /* enable IRQ */
+#define   ICH6_RBCTL_DMA_EN    (1 << 1)   /* enable DMA */
+#define   ICH6_RBCTL_OVERRUN_EN        (1 << 2)   /* enable overrun irq */
 #define ICH6_REG_RIRBSTS               0x5d
+#define   ICH6_RBSTS_IRQ       (1 << 0)   /* response irq */
+#define   ICH6_RBSTS_OVERRUN   (1 << 2)   /* overrun irq */
 #define ICH6_REG_RIRBSIZE              0x5e
 
 #define ICH6_REG_IC                    0x60
@@ -231,7 +253,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 
 /* STATESTS int mask: S3,SD2,SD1,SD0 */
 #define AZX_MAX_CODECS         4
-#define STATESTS_INT_MASK      0x0f
+#define STATESTS_INT_MASK      ((1 << AZX_MAX_CODECS) - 1)
 
 /* SD_CTL bits */
 #define SD_CTL_STREAM_RESET    0x01    /* stream reset bit */
@@ -257,16 +279,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define ICH6_INT_CTRL_EN       0x40000000 /* controller interrupt enable bit */
 #define ICH6_INT_GLOBAL_EN     0x80000000 /* global interrupt enable bit */
 
-/* GCTL unsolicited response enable bit */
-#define ICH6_GCTL_UREN         (1<<8)
-
-/* GCTL reset bit */
-#define ICH6_GCTL_RESET                (1<<0)
-
-/* CORB/RIRB control, read/write pointer */
-#define ICH6_RBCTL_DMA_EN      0x02    /* enable DMA */
-#define ICH6_RBCTL_IRQ_EN      0x01    /* enable IRQ */
-#define ICH6_RBRWP_CLR         0x8000  /* read/write pointer clear */
 /* below are so far hardcoded - should read registers in future */
 #define ICH6_MAX_CORB_ENTRIES  256
 #define ICH6_MAX_RIRB_ENTRIES  256
@@ -349,8 +361,8 @@ struct azx_rb {
        dma_addr_t addr;        /* physical address of CORB/RIRB buffer */
        /* for RIRB */
        unsigned short rp, wp;  /* read/write pointers */
-       int cmds;               /* number of pending requests */
-       u32 res;                /* last read value */
+       int cmds[AZX_MAX_CODECS];       /* number of pending requests */
+       u32 res[AZX_MAX_CODECS];        /* last read value */
 };
 
 struct azx {
@@ -512,25 +524,26 @@ static void azx_init_cmd_io(struct azx *chip)
        /* set the corb write pointer to 0 */
        azx_writew(chip, CORBWP, 0);
        /* reset the corb hw read pointer */
-       azx_writew(chip, CORBRP, ICH6_RBRWP_CLR);
+       azx_writew(chip, CORBRP, ICH6_CORBRP_RST);
        /* enable corb dma */
-       azx_writeb(chip, CORBCTL, ICH6_RBCTL_DMA_EN);
+       azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN);
 
        /* RIRB set up */
        chip->rirb.addr = chip->rb.addr + 2048;
        chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
+       chip->rirb.wp = chip->rirb.rp = 0;
+       memset(chip->rirb.cmds, 0, sizeof(chip->rirb.cmds));
        azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
        azx_writel(chip, RIRBUBASE, upper_32_bits(chip->rirb.addr));
 
        /* set the rirb size to 256 entries (ULI requires explicitly) */
        azx_writeb(chip, RIRBSIZE, 0x02);
        /* reset the rirb hw write pointer */
-       azx_writew(chip, RIRBWP, ICH6_RBRWP_CLR);
+       azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
        /* set N=1, get RIRB response interrupt for new entry */
        azx_writew(chip, RINTCNT, 1);
        /* enable rirb dma and response irq */
        azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
-       chip->rirb.rp = chip->rirb.cmds = 0;
 }
 
 static void azx_free_cmd_io(struct azx *chip)
@@ -540,10 +553,35 @@ static void azx_free_cmd_io(struct azx *chip)
        azx_writeb(chip, CORBCTL, 0);
 }
 
+static unsigned int azx_command_addr(u32 cmd)
+{
+       unsigned int addr = cmd >> 28;
+
+       if (addr >= AZX_MAX_CODECS) {
+               snd_BUG();
+               addr = 0;
+       }
+
+       return addr;
+}
+
+static unsigned int azx_response_addr(u32 res)
+{
+       unsigned int addr = res & 0xf;
+
+       if (addr >= AZX_MAX_CODECS) {
+               snd_BUG();
+               addr = 0;
+       }
+
+       return addr;
+}
+
 /* send a command */
 static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
 {
        struct azx *chip = bus->private_data;
+       unsigned int addr = azx_command_addr(val);
        unsigned int wp;
 
        /* add command to corb */
@@ -552,7 +590,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
        wp %= ICH6_MAX_CORB_ENTRIES;
 
        spin_lock_irq(&chip->reg_lock);
-       chip->rirb.cmds++;
+       chip->rirb.cmds[addr]++;
        chip->corb.buf[wp] = cpu_to_le32(val);
        azx_writel(chip, CORBWP, wp);
        spin_unlock_irq(&chip->reg_lock);
@@ -566,13 +604,14 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
 static void azx_update_rirb(struct azx *chip)
 {
        unsigned int rp, wp;
+       unsigned int addr;
        u32 res, res_ex;
 
        wp = azx_readb(chip, RIRBWP);
        if (wp == chip->rirb.wp)
                return;
        chip->rirb.wp = wp;
-               
+
        while (chip->rirb.rp != wp) {
                chip->rirb.rp++;
                chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
@@ -580,18 +619,20 @@ static void azx_update_rirb(struct azx *chip)
                rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
                res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
                res = le32_to_cpu(chip->rirb.buf[rp]);
+               addr = azx_response_addr(res_ex);
                if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
                        snd_hda_queue_unsol_event(chip->bus, res, res_ex);
-               else if (chip->rirb.cmds) {
-                       chip->rirb.res = res;
+               else if (chip->rirb.cmds[addr]) {
+                       chip->rirb.res[addr] = res;
                        smp_wmb();
-                       chip->rirb.cmds--;
+                       chip->rirb.cmds[addr]--;
                }
        }
 }
 
 /* receive a response */
-static unsigned int azx_rirb_get_response(struct hda_bus *bus)
+static unsigned int azx_rirb_get_response(struct hda_bus *bus,
+                                         unsigned int addr)
 {
        struct azx *chip = bus->private_data;
        unsigned long timeout;
@@ -604,9 +645,10 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
                        azx_update_rirb(chip);
                        spin_unlock_irq(&chip->reg_lock);
                }
-               if (!chip->rirb.cmds) {
+               if (!chip->rirb.cmds[addr]) {
                        smp_rmb();
-                       return chip->rirb.res; /* the last value */
+                       bus->rirb_error = 0;
+                       return chip->rirb.res[addr]; /* the last value */
                }
                if (time_after(jiffies, timeout))
                        break;
@@ -619,19 +661,21 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
        }
 
        if (chip->msi) {
-               snd_printk(KERN_WARNING "hda_intel: No response from codec, "
+               snd_printk(KERN_WARNING SFX "No response from codec, "
                           "disabling MSI: last cmd=0x%08x\n", chip->last_cmd);
                free_irq(chip->irq, chip);
                chip->irq = -1;
                pci_disable_msi(chip->pci);
                chip->msi = 0;
-               if (azx_acquire_irq(chip, 1) < 0)
+               if (azx_acquire_irq(chip, 1) < 0) {
+                       bus->rirb_error = 1;
                        return -1;
+               }
                goto again;
        }
 
        if (!chip->polling_mode) {
-               snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, "
+               snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
                           "switching to polling mode: last cmd=0x%08x\n",
                           chip->last_cmd);
                chip->polling_mode = 1;
@@ -646,14 +690,23 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
                return -1;
        }
 
+       /* a fatal communication error; need either to reset or to fallback
+        * to the single_cmd mode
+        */
+       bus->rirb_error = 1;
+       if (bus->allow_bus_reset && !bus->response_reset && !bus->in_reset) {
+               bus->response_reset = 1;
+               return -1; /* give a chance to retry */
+       }
+
        snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
                   "switching to single_cmd mode: last cmd=0x%08x\n",
                   chip->last_cmd);
-       chip->rirb.rp = azx_readb(chip, RIRBWP);
-       chip->rirb.cmds = 0;
-       /* switch to single_cmd mode */
        chip->single_cmd = 1;
+       bus->response_reset = 0;
+       /* re-initialize CORB/RIRB */
        azx_free_cmd_io(chip);
+       azx_init_cmd_io(chip);
        return -1;
 }
 
@@ -667,12 +720,35 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
  *       I left the codes, however, for debugging/testing purposes.
  */
 
+/* receive a response */
+static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
+{
+       int timeout = 50;
+
+       while (timeout--) {
+               /* check IRV busy bit */
+               if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
+                       /* reuse rirb.res as the response return value */
+                       chip->rirb.res[addr] = azx_readl(chip, IR);
+                       return 0;
+               }
+               udelay(1);
+       }
+       if (printk_ratelimit())
+               snd_printd(SFX "get_response timeout: IRS=0x%x\n",
+                          azx_readw(chip, IRS));
+       chip->rirb.res[addr] = -1;
+       return -EIO;
+}
+
 /* send a command */
 static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
 {
        struct azx *chip = bus->private_data;
+       unsigned int addr = azx_command_addr(val);
        int timeout = 50;
 
+       bus->rirb_error = 0;
        while (timeout--) {
                /* check ICB busy bit */
                if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) {
@@ -682,7 +758,7 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
                        azx_writel(chip, IC, val);
                        azx_writew(chip, IRS, azx_readw(chip, IRS) |
                                   ICH6_IRS_BUSY);
-                       return 0;
+                       return azx_single_wait_for_response(chip, addr);
                }
                udelay(1);
        }
@@ -693,21 +769,11 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
 }
 
 /* receive a response */
-static unsigned int azx_single_get_response(struct hda_bus *bus)
+static unsigned int azx_single_get_response(struct hda_bus *bus,
+                                           unsigned int addr)
 {
        struct azx *chip = bus->private_data;
-       int timeout = 50;
-
-       while (timeout--) {
-               /* check IRV busy bit */
-               if (azx_readw(chip, IRS) & ICH6_IRS_VALID)
-                       return azx_readl(chip, IR);
-               udelay(1);
-       }
-       if (printk_ratelimit())
-               snd_printd(SFX "get_response timeout: IRS=0x%x\n",
-                          azx_readw(chip, IRS));
-       return (unsigned int)-1;
+       return chip->rirb.res[addr];
 }
 
 /*
@@ -730,13 +796,14 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
 }
 
 /* get a response */
-static unsigned int azx_get_response(struct hda_bus *bus)
+static unsigned int azx_get_response(struct hda_bus *bus,
+                                    unsigned int addr)
 {
        struct azx *chip = bus->private_data;
        if (chip->single_cmd)
-               return azx_single_get_response(bus);
+               return azx_single_get_response(bus, addr);
        else
-               return azx_rirb_get_response(bus);
+               return azx_rirb_get_response(bus, addr);
 }
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
@@ -775,17 +842,17 @@ static int azx_reset(struct azx *chip)
 
        /* check to see if controller is ready */
        if (!azx_readb(chip, GCTL)) {
-               snd_printd("azx_reset: controller not ready!\n");
+               snd_printd(SFX "azx_reset: controller not ready!\n");
                return -EBUSY;
        }
 
        /* Accept unsolicited responses */
-       azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN);
+       azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UNSOL);
 
        /* detect codecs */
        if (!chip->codec_mask) {
                chip->codec_mask = azx_readw(chip, STATESTS);
-               snd_printdd("codec_mask = 0x%x\n", chip->codec_mask);
+               snd_printdd(SFX "codec_mask = 0x%x\n", chip->codec_mask);
        }
 
        return 0;
@@ -895,8 +962,7 @@ static void azx_init_chip(struct azx *chip)
        azx_int_enable(chip);
 
        /* initialize the codec command I/O */
-       if (!chip->single_cmd)
-               azx_init_cmd_io(chip);
+       azx_init_cmd_io(chip);
 
        /* program the position buffer */
        azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
@@ -953,12 +1019,12 @@ static void azx_init_pci(struct azx *chip)
        case AZX_DRIVER_SCH:
                pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop);
                if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) {
-                       pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, \
+                       pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC,
                                snoop & (~INTEL_SCH_HDA_DEVC_NOSNOOP));
                        pci_read_config_word(chip->pci,
                                INTEL_SCH_HDA_DEVC, &snoop);
-                       snd_printdd("HDA snoop disabled, enabling ... %s\n",\
-                               (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) \
+                       snd_printdd(SFX "HDA snoop disabled, enabling ... %s\n",
+                               (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
                                ? "Failed" : "OK");
                }
                break;
@@ -1012,7 +1078,7 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
        /* clear rirb int */
        status = azx_readb(chip, RIRBSTS);
        if (status & RIRB_INT_MASK) {
-               if (!chip->single_cmd && (status & RIRB_INT_RESPONSE))
+               if (status & RIRB_INT_RESPONSE)
                        azx_update_rirb(chip);
                azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
        }
@@ -1098,7 +1164,7 @@ static int azx_setup_periods(struct azx *chip,
                                pos_align;
                pos_adj = frames_to_bytes(runtime, pos_adj);
                if (pos_adj >= period_bytes) {
-                       snd_printk(KERN_WARNING "Too big adjustment %d\n",
+                       snd_printk(KERN_WARNING SFX "Too big adjustment %d\n",
                                   bdl_pos_adj[chip->dev_index]);
                        pos_adj = 0;
                } else {
@@ -1122,7 +1188,7 @@ static int azx_setup_periods(struct azx *chip,
        return 0;
 
  error:
-       snd_printk(KERN_ERR "Too many BDL entries: buffer=%d, period=%d\n",
+       snd_printk(KERN_ERR SFX "Too many BDL entries: buffer=%d, period=%d\n",
                   azx_dev->bufsize, period_bytes);
        return -EINVAL;
 }
@@ -1211,11 +1277,11 @@ static int probe_codec(struct azx *chip, int addr)
 
        chip->probing = 1;
        azx_send_cmd(chip->bus, cmd);
-       res = azx_get_response(chip->bus);
+       res = azx_get_response(chip->bus, addr);
        chip->probing = 0;
        if (res == -1)
                return -EIO;
-       snd_printdd("hda_intel: codec #%d probed OK\n", addr);
+       snd_printdd(SFX "codec #%d probed OK\n", addr);
        return 0;
 }
 
@@ -1223,6 +1289,26 @@ static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
                                 struct hda_pcm *cpcm);
 static void azx_stop_chip(struct azx *chip);
 
+static void azx_bus_reset(struct hda_bus *bus)
+{
+       struct azx *chip = bus->private_data;
+
+       bus->in_reset = 1;
+       azx_stop_chip(chip);
+       azx_init_chip(chip);
+#ifdef CONFIG_PM
+       if (chip->initialized) {
+               int i;
+
+               for (i = 0; i < AZX_MAX_PCMS; i++)
+                       snd_pcm_suspend_all(chip->pcm[i]);
+               snd_hda_suspend(chip->bus);
+               snd_hda_resume(chip->bus);
+       }
+#endif
+       bus->in_reset = 0;
+}
+
 /*
  * Codec initialization
  */
@@ -1246,6 +1332,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
        bus_temp.ops.command = azx_send_cmd;
        bus_temp.ops.get_response = azx_get_response;
        bus_temp.ops.attach_pcm = azx_attach_pcm_stream;
+       bus_temp.ops.bus_reset = azx_bus_reset;
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        bus_temp.power_save = &power_save;
        bus_temp.ops.pm_notify = azx_power_notify;
@@ -1270,8 +1357,8 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
                                /* Some BIOSen give you wrong codec addresses
                                 * that don't exist
                                 */
-                               snd_printk(KERN_WARNING
-                                          "hda_intel: Codec #%d probe error; "
+                               snd_printk(KERN_WARNING SFX
+                                          "Codec #%d probe error; "
                                           "disabling it...\n", c);
                                chip->codec_mask &= ~(1 << c);
                                /* More badly, accessing to a non-existing
@@ -1399,6 +1486,18 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
                mutex_unlock(&chip->open_mutex);
                return err;
        }
+       snd_pcm_limit_hw_rates(runtime);
+       /* sanity check */
+       if (snd_BUG_ON(!runtime->hw.channels_min) ||
+           snd_BUG_ON(!runtime->hw.channels_max) ||
+           snd_BUG_ON(!runtime->hw.formats) ||
+           snd_BUG_ON(!runtime->hw.rates)) {
+               azx_release_device(azx_dev);
+               hinfo->ops.close(hinfo, apcm->codec, substream);
+               snd_hda_power_down(apcm->codec);
+               mutex_unlock(&chip->open_mutex);
+               return -EINVAL;
+       }
        spin_lock_irqsave(&chip->reg_lock, flags);
        azx_dev->substream = substream;
        azx_dev->running = 0;
@@ -1407,7 +1506,6 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        runtime->private_data = azx_dev;
        snd_pcm_set_sync(substream);
        mutex_unlock(&chip->open_mutex);
-
        return 0;
 }
 
@@ -1487,7 +1585,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
        bufsize = snd_pcm_lib_buffer_bytes(substream);
        period_bytes = snd_pcm_lib_period_bytes(substream);
 
-       snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
+       snd_printdd(SFX "azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
                    bufsize, format_val);
 
        if (bufsize != azx_dev->bufsize ||
@@ -1830,7 +1928,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
                          &pcm);
        if (err < 0)
                return err;
-       strcpy(pcm->name, cpcm->name);
+       strlcpy(pcm->name, cpcm->name, sizeof(pcm->name));
        apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
        if (apcm == NULL)
                return -ENOMEM;
@@ -1973,7 +2071,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
        for (i = 0; i < AZX_MAX_PCMS; i++)
                snd_pcm_suspend_all(chip->pcm[i]);
        if (chip->initialized)
-               snd_hda_suspend(chip->bus, state);
+               snd_hda_suspend(chip->bus);
        azx_stop_chip(chip);
        if (chip->irq >= 0) {
                free_irq(chip->irq, chip);
@@ -2265,14 +2363,24 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        synchronize_irq(chip->irq);
 
        gcap = azx_readw(chip, GCAP);
-       snd_printdd("chipset global capabilities = 0x%x\n", gcap);
-
-       /* ATI chips seems buggy about 64bit DMA addresses */
-       if (chip->driver_type == AZX_DRIVER_ATI)
-               gcap &= ~0x01;
+       snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap);
+
+       /* disable SB600 64bit support for safety */
+       if ((chip->driver_type == AZX_DRIVER_ATI) ||
+           (chip->driver_type == AZX_DRIVER_ATIHDMI)) {
+               struct pci_dev *p_smbus;
+               p_smbus = pci_get_device(PCI_VENDOR_ID_ATI,
+                                        PCI_DEVICE_ID_ATI_SBX00_SMBUS,
+                                        NULL);
+               if (p_smbus) {
+                       if (p_smbus->revision < 0x30)
+                               gcap &= ~ICH6_GCAP_64OK;
+                       pci_dev_put(p_smbus);
+               }
+       }
 
        /* allow 64bit DMA address if supported by H/W */
-       if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
+       if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
                pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
        else {
                pci_set_dma_mask(pci, DMA_BIT_MASK(32));
@@ -2309,7 +2417,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
                                GFP_KERNEL);
        if (!chip->azx_dev) {
-               snd_printk(KERN_ERR "cannot malloc azx_dev\n");
+               snd_printk(KERN_ERR SFX "cannot malloc azx_dev\n");
                goto errout;
        }
 
@@ -2332,11 +2440,9 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                goto errout;
        }
        /* allocate CORB/RIRB */
-       if (!chip->single_cmd) {
-               err = azx_alloc_cmd_io(chip);
-               if (err < 0)
-                       goto errout;
-       }
+       err = azx_alloc_cmd_io(chip);
+       if (err < 0)
+               goto errout;
 
        /* initialize streams */
        azx_init_stream(chip);
@@ -2359,9 +2465,11 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        }
 
        strcpy(card->driver, "HDA-Intel");
-       strcpy(card->shortname, driver_short_names[chip->driver_type]);
-       sprintf(card->longname, "%s at 0x%lx irq %i",
-               card->shortname, chip->addr, chip->irq);
+       strlcpy(card->shortname, driver_short_names[chip->driver_type],
+               sizeof(card->shortname));
+       snprintf(card->longname, sizeof(card->longname),
+                "%s at 0x%lx irq %i",
+                card->shortname, chip->addr, chip->irq);
 
        *rchip = chip;
        return 0;
@@ -2514,6 +2622,20 @@ static struct pci_device_id azx_ids[] = {
        { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA },
        /* Teradici */
        { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
+       /* Creative X-Fi (CA0110-IBG) */
+#if !defined(CONFIG_SND_CTXFI) && !defined(CONFIG_SND_CTXFI_MODULE)
+       /* the following entry conflicts with snd-ctxfi driver,
+        * as ctxfi driver mutates from HD-audio to native mode with
+        * a special command sequence.
+        */
+       { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID),
+         .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+         .class_mask = 0xffffff,
+         .driver_data = AZX_DRIVER_GENERIC },
+#else
+       /* this entry seems still valid -- i.e. without emu20kx chip */
+       { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_GENERIC },
+#endif
        /* AMD Generic, PCI class code and Vendor ID for HD Audio */
        { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
          .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,