ALSA: hda - Support max codecs to 8 for nvidia hda controller
[safe/jmp/linux-2.6] / sound / pci / hda / hda_intel.c
index 6abaa6b..b104757 100644 (file)
@@ -60,10 +60,14 @@ static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
 static int probe_only[SNDRV_CARDS];
 static int single_cmd;
-static int enable_msi;
+static int enable_msi = -1;
 #ifdef CONFIG_SND_HDA_PATCH_LOADER
 static char *patch[SNDRV_CARDS];
 #endif
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+static int beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
+                                       CONFIG_SND_HDA_INPUT_BEEP_MODE};
+#endif
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -91,6 +95,11 @@ MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
 module_param_array(patch, charp, NULL, 0444);
 MODULE_PARM_DESC(patch, "Patch file for Intel HD audio interface.");
 #endif
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+module_param_array(beep_mode, int, NULL, 0444);
+MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
+                           "(0=off, 1=on, 2=mute switch on/off) (default=1).");
+#endif
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
@@ -116,6 +125,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
                         "{Intel, ICH9},"
                         "{Intel, ICH10},"
                         "{Intel, PCH},"
+                        "{Intel, CPT},"
                         "{Intel, SCH},"
                         "{ATI, SB450},"
                         "{ATI, SB600},"
@@ -250,8 +260,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define AZX_MAX_FRAG           32
 /* max buffer size - no h/w limit, you can increase as you like */
 #define AZX_MAX_BUF_SIZE       (1024*1024*1024)
-/* max number of PCM devics per card */
-#define AZX_MAX_PCMS           8
 
 /* RIRB int mask: overrun[2], response[0] */
 #define RIRB_INT_RESPONSE      0x01
@@ -259,8 +267,9 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define RIRB_INT_MASK          0x05
 
 /* STATESTS int mask: S3,SD2,SD1,SD0 */
-#define AZX_MAX_CODECS         4
-#define STATESTS_INT_MASK      0x0f
+#define AZX_MAX_CODECS         8
+#define AZX_DEFAULT_CODECS     4
+#define STATESTS_INT_MASK      ((1 << AZX_MAX_CODECS) - 1)
 
 /* SD_CTL bits */
 #define SD_CTL_STREAM_RESET    0x01    /* stream reset bit */
@@ -347,6 +356,7 @@ struct azx_dev {
                                         */
        unsigned char stream_tag;       /* assigned stream */
        unsigned char index;            /* stream index */
+       int device;                     /* last device number assigned to */
 
        unsigned int opened :1;
        unsigned int running :1;
@@ -368,8 +378,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 {
@@ -398,12 +408,13 @@ struct azx {
        struct azx_dev *azx_dev;
 
        /* PCM */
-       struct snd_pcm *pcm[AZX_MAX_PCMS];
+       struct snd_pcm *pcm[HDA_MAX_PCMS];
 
        /* HD codec */
        unsigned short codec_mask;
        int  codec_probe_mask; /* copied from probe_mask option */
        struct hda_bus *bus;
+       unsigned int beep_mode;
 
        /* CORB/RIRB */
        struct azx_rb corb;
@@ -415,6 +426,7 @@ struct azx {
 
        /* flags */
        int position_fix;
+       int poll_count;
        unsigned int running :1;
        unsigned int initialized :1;
        unsigned int single_cmd :1;
@@ -425,7 +437,7 @@ struct azx {
        unsigned int probing :1; /* codec probing phase */
 
        /* for debugging */
-       unsigned int last_cmd;  /* last issued command (to sync) */
+       unsigned int last_cmd[AZX_MAX_CODECS];
 
        /* for pending irqs */
        struct work_struct irq_pending_work;
@@ -437,6 +449,7 @@ struct azx {
 /* driver types */
 enum {
        AZX_DRIVER_ICH,
+       AZX_DRIVER_PCH,
        AZX_DRIVER_SCH,
        AZX_DRIVER_ATI,
        AZX_DRIVER_ATIHDMI,
@@ -451,6 +464,7 @@ enum {
 
 static char *driver_short_names[] __devinitdata = {
        [AZX_DRIVER_ICH] = "HDA Intel",
+       [AZX_DRIVER_PCH] = "HDA Intel PCH",
        [AZX_DRIVER_SCH] = "HDA Intel MID",
        [AZX_DRIVER_ATI] = "HDA ATI SB",
        [AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",
@@ -495,7 +509,7 @@ static char *driver_short_names[] __devinitdata = {
 #define get_azx_dev(substream) (substream->runtime->private_data)
 
 static int azx_acquire_irq(struct azx *chip, int do_disconnect);
-
+static int azx_send_cmd(struct hda_bus *bus, unsigned int val);
 /*
  * Interface for HD codec
  */
@@ -520,6 +534,7 @@ static int azx_alloc_cmd_io(struct azx *chip)
 
 static void azx_init_cmd_io(struct azx *chip)
 {
+       spin_lock_irq(&chip->reg_lock);
        /* CORB set up */
        chip->corb.addr = chip->rb.addr;
        chip->corb.buf = (u32 *)chip->rb.area;
@@ -538,7 +553,8 @@ static void azx_init_cmd_io(struct azx *chip)
        /* RIRB set up */
        chip->rirb.addr = chip->rb.addr + 2048;
        chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
-       chip->rirb.wp = chip->rirb.rp = chip->rirb.cmds = 0;
+       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));
 
@@ -550,30 +566,60 @@ static void azx_init_cmd_io(struct azx *chip)
        azx_writew(chip, RINTCNT, 1);
        /* enable rirb dma and response irq */
        azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
+       spin_unlock_irq(&chip->reg_lock);
 }
 
 static void azx_free_cmd_io(struct azx *chip)
 {
+       spin_lock_irq(&chip->reg_lock);
        /* disable ringbuffer DMAs */
        azx_writeb(chip, RIRBCTL, 0);
        azx_writeb(chip, CORBCTL, 0);
+       spin_unlock_irq(&chip->reg_lock);
+}
+
+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;
 
+       spin_lock_irq(&chip->reg_lock);
+
        /* add command to corb */
        wp = azx_readb(chip, CORBWP);
        wp++;
        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);
 
        return 0;
@@ -585,13 +631,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;
@@ -599,34 +646,44 @@ 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]--;
+               } else
+                       snd_printk(KERN_ERR SFX "spurious response %#x:%#x, "
+                                  "last cmd=%#08x\n",
+                                  res, res_ex,
+                                  chip->last_cmd[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;
+       int do_poll = 0;
 
  again:
        timeout = jiffies + msecs_to_jiffies(1000);
        for (;;) {
-               if (chip->polling_mode) {
+               if (chip->polling_mode || do_poll) {
                        spin_lock_irq(&chip->reg_lock);
                        azx_update_rirb(chip);
                        spin_unlock_irq(&chip->reg_lock);
                }
-               if (!chip->rirb.cmds) {
+               if (!chip->rirb.cmds[addr]) {
                        smp_rmb();
                        bus->rirb_error = 0;
-                       return chip->rirb.res; /* the last value */
+
+                       if (!do_poll)
+                               chip->poll_count = 0;
+                       return chip->rirb.res[addr]; /* the last value */
                }
                if (time_after(jiffies, timeout))
                        break;
@@ -638,9 +695,28 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
                }
        }
 
+       if (!chip->polling_mode && chip->poll_count < 2) {
+               snd_printdd(SFX "azx_get_response timeout, "
+                          "polling the codec once: last cmd=0x%08x\n",
+                          chip->last_cmd[addr]);
+               do_poll = 1;
+               chip->poll_count++;
+               goto again;
+       }
+
+
+       if (!chip->polling_mode) {
+               snd_printk(KERN_WARNING SFX "azx_get_response timeout, "
+                          "switching to polling mode: last cmd=0x%08x\n",
+                          chip->last_cmd[addr]);
+               chip->polling_mode = 1;
+               goto again;
+       }
+
        if (chip->msi) {
                snd_printk(KERN_WARNING SFX "No response from codec, "
-                          "disabling MSI: last cmd=0x%08x\n", chip->last_cmd);
+                          "disabling MSI: last cmd=0x%08x\n",
+                          chip->last_cmd[addr]);
                free_irq(chip->irq, chip);
                chip->irq = -1;
                pci_disable_msi(chip->pci);
@@ -652,14 +728,6 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
                goto again;
        }
 
-       if (!chip->polling_mode) {
-               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;
-               goto again;
-       }
-
        if (chip->probing) {
                /* If this critical timeout happens during the codec probing
                 * phase, this is likely an access to a non-existing codec
@@ -679,12 +747,13 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
 
        snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
                   "switching to single_cmd mode: last cmd=0x%08x\n",
-                  chip->last_cmd);
+                  chip->last_cmd[addr]);
        chip->single_cmd = 1;
        bus->response_reset = 0;
-       /* re-initialize CORB/RIRB */
+       /* release CORB/RIRB */
        azx_free_cmd_io(chip);
-       azx_init_cmd_io(chip);
+       /* disable unsolicited responses */
+       azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL);
        return -1;
 }
 
@@ -699,7 +768,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
  */
 
 /* receive a response */
-static int azx_single_wait_for_response(struct azx *chip)
+static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
 {
        int timeout = 50;
 
@@ -707,7 +776,7 @@ static int azx_single_wait_for_response(struct azx *chip)
                /* check IRV busy bit */
                if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
                        /* reuse rirb.res as the response return value */
-                       chip->rirb.res = azx_readl(chip, IR);
+                       chip->rirb.res[addr] = azx_readl(chip, IR);
                        return 0;
                }
                udelay(1);
@@ -715,7 +784,7 @@ static int azx_single_wait_for_response(struct azx *chip)
        if (printk_ratelimit())
                snd_printd(SFX "get_response timeout: IRS=0x%x\n",
                           azx_readw(chip, IRS));
-       chip->rirb.res = -1;
+       chip->rirb.res[addr] = -1;
        return -EIO;
 }
 
@@ -723,6 +792,7 @@ static int azx_single_wait_for_response(struct azx *chip)
 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;
@@ -735,7 +805,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 azx_single_wait_for_response(chip);
+                       return azx_single_wait_for_response(chip, addr);
                }
                udelay(1);
        }
@@ -746,10 +816,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;
-       return chip->rirb.res;
+       return chip->rirb.res[addr];
 }
 
 /*
@@ -764,7 +835,7 @@ static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
 {
        struct azx *chip = bus->private_data;
 
-       chip->last_cmd = val;
+       chip->last_cmd[azx_command_addr(val)] = val;
        if (chip->single_cmd)
                return azx_single_send_cmd(bus, val);
        else
@@ -772,13 +843,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
@@ -822,7 +894,9 @@ static int azx_reset(struct azx *chip)
        }
 
        /* Accept unsolicited responses */
-       azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UNSOL);
+       if (!chip->single_cmd)
+               azx_writel(chip, GCTL, azx_readl(chip, GCTL) |
+                          ICH6_GCTL_UNSOL);
 
        /* detect codecs */
        if (!chip->codec_mask) {
@@ -896,8 +970,8 @@ static void azx_stream_start(struct azx *chip, struct azx_dev *azx_dev)
        azx_dev->insufficient = 1;
 
        /* enable SIE */
-       azx_writeb(chip, INTCTL,
-                  azx_readb(chip, INTCTL) | (1 << azx_dev->index));
+       azx_writel(chip, INTCTL,
+                  azx_readl(chip, INTCTL) | (1 << azx_dev->index));
        /* set DMA start and interrupt mask */
        azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
                      SD_CTL_DMA_START | SD_INT_MASK);
@@ -916,8 +990,8 @@ static void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev)
 {
        azx_stream_clear(chip, azx_dev);
        /* disable SIE */
-       azx_writeb(chip, INTCTL,
-                  azx_readb(chip, INTCTL) & ~(1 << azx_dev->index));
+       azx_writel(chip, INTCTL,
+                  azx_readl(chip, INTCTL) & ~(1 << azx_dev->index));
 }
 
 
@@ -937,7 +1011,8 @@ static void azx_init_chip(struct azx *chip)
        azx_int_enable(chip);
 
        /* initialize the codec command I/O */
-       azx_init_cmd_io(chip);
+       if (!chip->single_cmd)
+               azx_init_cmd_io(chip);
 
        /* program the position buffer */
        azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
@@ -992,6 +1067,7 @@ static void azx_init_pci(struct azx *chip)
                                0x01, NVIDIA_HDA_ENABLE_COHBIT);
                break;
        case AZX_DRIVER_SCH:
+       case AZX_DRIVER_PCH:
                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,
@@ -1250,10 +1326,12 @@ static int probe_codec(struct azx *chip, int addr)
                (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
        unsigned int res;
 
+       mutex_lock(&chip->bus->cmd_mutex);
        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;
+       mutex_unlock(&chip->bus->cmd_mutex);
        if (res == -1)
                return -EIO;
        snd_printdd(SFX "codec #%d probed OK\n", addr);
@@ -1275,7 +1353,7 @@ static void azx_bus_reset(struct hda_bus *bus)
        if (chip->initialized) {
                int i;
 
-               for (i = 0; i < AZX_MAX_PCMS; i++)
+               for (i = 0; i < HDA_MAX_PCMS; i++)
                        snd_pcm_suspend_all(chip->pcm[i]);
                snd_hda_suspend(chip->bus);
                snd_hda_resume(chip->bus);
@@ -1290,6 +1368,7 @@ static void azx_bus_reset(struct hda_bus *bus)
 
 /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
 static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
+       [AZX_DRIVER_NVIDIA] = 8,
        [AZX_DRIVER_TERA] = 1,
 };
 
@@ -1322,7 +1401,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
        codecs = 0;
        max_slots = azx_max_codecs[chip->driver_type];
        if (!max_slots)
-               max_slots = AZX_MAX_CODECS;
+               max_slots = AZX_DEFAULT_CODECS;
 
        /* First try to probe all given codec slots */
        for (c = 0; c < max_slots; c++) {
@@ -1337,7 +1416,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
                                chip->codec_mask &= ~(1 << c);
                                /* More badly, accessing to a non-existing
                                 * codec often screws up the controller chip,
-                                * and distrubs the further communications.
+                                * and disturbs the further communications.
                                 * Thus if an error occurs during probing,
                                 * better to reset the controller chip to
                                 * get back to the sanity state.
@@ -1355,6 +1434,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
                        err = snd_hda_codec_new(chip->bus, c, &codec);
                        if (err < 0)
                                continue;
+                       codec->beep_mode = chip->beep_mode;
                        codecs++;
                }
        }
@@ -1381,10 +1461,13 @@ static int __devinit azx_codec_configure(struct azx *chip)
  */
 
 /* assign a stream for the PCM */
-static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
+static inline struct azx_dev *
+azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
 {
        int dev, i, nums;
-       if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
+       struct azx_dev *res = NULL;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                dev = chip->playback_index_offset;
                nums = chip->playback_streams;
        } else {
@@ -1393,10 +1476,15 @@ static inline struct azx_dev *azx_assign_device(struct azx *chip, int stream)
        }
        for (i = 0; i < nums; i++, dev++)
                if (!chip->azx_dev[dev].opened) {
-                       chip->azx_dev[dev].opened = 1;
-                       return &chip->azx_dev[dev];
+                       res = &chip->azx_dev[dev];
+                       if (res->device == substream->pcm->device)
+                               break;
                }
-       return NULL;
+       if (res) {
+               res->opened = 1;
+               res->device = substream->pcm->device;
+       }
+       return res;
 }
 
 /* release the assigned stream */
@@ -1445,7 +1533,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        int err;
 
        mutex_lock(&chip->open_mutex);
-       azx_dev = azx_assign_device(chip, substream->stream);
+       azx_dev = azx_assign_device(chip, substream);
        if (azx_dev == NULL) {
                mutex_unlock(&chip->open_mutex);
                return -EBUSY;
@@ -1470,6 +1558,17 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
                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;
@@ -1478,13 +1577,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);
-
-       if (snd_BUG_ON(!runtime->hw.channels_min || !runtime->hw.channels_max))
-               return -EINVAL;
-       if (snd_BUG_ON(!runtime->hw.formats))
-               return -EINVAL;
-       if (snd_BUG_ON(!runtime->hw.rates))
-               return -EINVAL;
        return 0;
 }
 
@@ -1805,6 +1897,12 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 
        if (!bdl_pos_adj[chip->dev_index])
                return 1; /* no delayed ack */
+       if (azx_dev->period_bytes == 0) {
+               printk(KERN_WARNING
+                      "hda-intel: Divide by zero was avoided "
+                      "in azx_dev->period_bytes.\n");
+               return 0;
+       }
        if (pos % azx_dev->period_bytes > azx_dev->period_bytes / 2)
                return 0; /* NG - it's below the period boundary */
        return 1; /* OK, it's fine */
@@ -1892,7 +1990,7 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
        int pcm_dev = cpcm->device;
        int s, err;
 
-       if (pcm_dev >= AZX_MAX_PCMS) {
+       if (pcm_dev >= HDA_MAX_PCMS) {
                snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n",
                           pcm_dev);
                return -EINVAL;
@@ -1970,7 +2068,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
 {
        if (request_irq(chip->pci->irq, azx_interrupt,
                        chip->msi ? 0 : IRQF_SHARED,
-                       "HDA Intel", chip)) {
+                       "hda_intel", chip)) {
                printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
                       "disabling device\n", chip->pci->irq);
                if (do_disconnect)
@@ -2018,7 +2116,8 @@ static void azx_power_notify(struct hda_bus *bus)
        }
        if (power_on)
                azx_init_chip(chip);
-       else if (chip->running && power_save_controller)
+       else if (chip->running && power_save_controller &&
+                !bus->power_keep_link_on)
                azx_stop_chip(chip);
 }
 #endif /* CONFIG_SND_HDA_POWER_SAVE */
@@ -2047,7 +2146,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
        azx_clear_irq_pending(chip);
-       for (i = 0; i < AZX_MAX_PCMS; i++)
+       for (i = 0; i < HDA_MAX_PCMS; i++)
                snd_pcm_suspend_all(chip->pcm[i]);
        if (chip->initialized)
                snd_hda_suspend(chip->bus);
@@ -2101,6 +2200,7 @@ static int azx_resume(struct pci_dev *pci)
 static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
 {
        struct azx *chip = container_of(nb, struct azx, reboot_notifier);
+       snd_hda_bus_reboot_notify(chip->bus);
        azx_stop_chip(chip);
        return NOTIFY_OK;
 }
@@ -2168,7 +2268,10 @@ static int azx_dev_free(struct snd_device *device)
 static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
        {}
 };
 
@@ -2250,6 +2353,33 @@ static void __devinit check_probe_mask(struct azx *chip, int dev)
        }
 }
 
+/*
+ * white/black-list for enable_msi
+ */
+static struct snd_pci_quirk msi_black_list[] __devinitdata = {
+       SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */
+       SND_PCI_QUIRK(0x1043, 0x829c, "ASUS", 0), /* nvidia */
+       {}
+};
+
+static void __devinit check_msi(struct azx *chip)
+{
+       const struct snd_pci_quirk *q;
+
+       if (enable_msi >= 0) {
+               chip->msi = !!enable_msi;
+               return;
+       }
+       chip->msi = 1;  /* enable MSI as default */
+       q = snd_pci_quirk_lookup(chip->pci, msi_black_list);
+       if (q) {
+               printk(KERN_INFO
+                      "hda_intel: msi for device %04x:%04x set to %d\n",
+                      q->subvendor, q->subdevice, q->value);
+               chip->msi = q->value;
+       }
+}
+
 
 /*
  * constructor
@@ -2284,7 +2414,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        chip->pci = pci;
        chip->irq = -1;
        chip->driver_type = driver_type;
-       chip->msi = enable_msi;
+       check_msi(chip);
        chip->dev_index = dev;
        INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
 
@@ -2296,6 +2426,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        if (bdl_pos_adj[dev] < 0) {
                switch (chip->driver_type) {
                case AZX_DRIVER_ICH:
+               case AZX_DRIVER_PCH:
                        bdl_pos_adj[dev] = 1;
                        break;
                default:
@@ -2344,8 +2475,23 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        gcap = azx_readw(chip, GCAP);
        snd_printdd(SFX "chipset global capabilities = 0x%x\n", gcap);
 
-       /* ATI chips seems buggy about 64bit DMA addresses */
-       if (chip->driver_type == AZX_DRIVER_ATI)
+       /* 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);
+               }
+       }
+
+       /* disable 64bit DMA address for Teradici */
+       /* it does not work with device 6549:1200 subsys e4a2:040b */
+       if (chip->driver_type == AZX_DRIVER_TERA)
                gcap &= ~ICH6_GCAP_64OK;
 
        /* allow 64bit DMA address if supported by H/W */
@@ -2490,6 +2636,10 @@ static int __devinit azx_probe(struct pci_dev *pci,
                goto out_free;
        card->private_data = chip;
 
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+       chip->beep_mode = beep_mode[dev];
+#endif
+
        /* create codec instances */
        err = azx_codec_create(chip, model[dev]);
        if (err < 0)
@@ -2555,6 +2705,8 @@ static struct pci_device_id azx_ids[] = {
        { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
        /* PCH */
        { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH },
+       /* CPT */
+       { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH },
        /* SCH */
        { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
        /* ATI SB 450/600 */
@@ -2582,28 +2734,10 @@ static struct pci_device_id azx_ids[] = {
        /* ULI M5461 */
        { PCI_DEVICE(0x10b9, 0x5461), .driver_data = AZX_DRIVER_ULI },
        /* NVIDIA MCP */
-       { PCI_DEVICE(0x10de, 0x026c), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0371), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x03e4), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x03f0), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x044a), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x044b), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x055c), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x055d), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0774), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0775), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0776), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0777), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x07fc), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x07fd), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0ac0), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0ac1), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0ac2), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0ac3), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0d94), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0d95), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0d96), .driver_data = AZX_DRIVER_NVIDIA },
-       { PCI_DEVICE(0x10de, 0x0d97), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID),
+         .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+         .class_mask = 0xffffff,
+         .driver_data = AZX_DRIVER_NVIDIA },
        /* Teradici */
        { PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
        /* Creative X-Fi (CA0110-IBG) */
@@ -2620,11 +2754,15 @@ static struct pci_device_id azx_ids[] = {
        /* 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 */
+       /* AMD/ATI 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,
          .class_mask = 0xffffff,
          .driver_data = AZX_DRIVER_GENERIC },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_ANY_ID),
+         .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
+         .class_mask = 0xffffff,
+         .driver_data = AZX_DRIVER_GENERIC },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);