]> nv-tegra.nvidia Code Review - linux-2.6.git/blobdiff - sound/pci/hda/hda_intel.c
[ALSA] Fix invalid schedule_timeout_interruptible()
[linux-2.6.git] / sound / pci / hda / hda_intel.c
index ce75e07aaa2a7238244938871b6169367fd74d56..c78ff901a57246307ac35cdb76d07289e97b0e37 100644 (file)
@@ -55,6 +55,7 @@ static char *model;
 static int position_fix;
 static int probe_mask = -1;
 static int single_cmd;
+static int enable_msi;
 
 module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -68,6 +69,8 @@ module_param(probe_mask, int, 0444);
 MODULE_PARM_DESC(probe_mask, "Bitmask to probe codecs (default = -1).");
 module_param(single_cmd, bool, 0444);
 MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs (for debugging only).");
+module_param(enable_msi, int, 0);
+MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
 
 
 /* just for backward compatibility */
@@ -80,9 +83,13 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
                         "{Intel, ICH7},"
                         "{Intel, ESB2},"
                         "{Intel, ICH8},"
+                        "{Intel, ICH9},"
                         "{ATI, SB450},"
                         "{ATI, SB600},"
                         "{ATI, RS600},"
+                        "{ATI, RS690},"
+                        "{ATI, RS780},"
+                        "{ATI, R600},"
                         "{VIA, VT8251},"
                         "{VIA, VT8237A},"
                         "{SiS, SIS966},"
@@ -193,8 +200,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define RIRB_INT_MASK          0x05
 
 /* STATESTS int mask: SD2,SD1,SD0 */
+#define AZX_MAX_CODECS         3
 #define STATESTS_INT_MASK      0x07
-#define AZX_MAX_CODECS         4
 
 /* SD_CTL bits */
 #define SD_CTL_STREAM_RESET    0x01    /* stream reset bit */
@@ -252,7 +259,7 @@ enum {
 struct azx_dev {
        u32 *bdl;                       /* virtual address of the BDL */
        dma_addr_t bdl_addr;            /* physical address of the BDL */
-       volatile u32 *posbuf;                   /* position buffer pointer */
+       u32 *posbuf;                    /* position buffer pointer */
 
        unsigned int bufsize;           /* size of the play buffer in bytes */
        unsigned int fragsize;          /* size of each period in bytes */
@@ -271,8 +278,8 @@ struct azx_dev {
        /* for sanity check of position buffer */
        unsigned int period_intr;
 
-       unsigned int opened1;
-       unsigned int running1;
+       unsigned int opened :1;
+       unsigned int running :1;
 };
 
 /* CORB/RIRB */
@@ -330,9 +337,10 @@ struct azx {
 
        /* flags */
        int position_fix;
-       unsigned int initialized: 1;
-       unsigned int single_cmd: 1;
-       unsigned int polling_mode: 1;
+       unsigned int initialized :1;
+       unsigned int single_cmd :1;
+       unsigned int polling_mode :1;
+       unsigned int msi :1;
 };
 
 /* driver types */
@@ -393,6 +401,7 @@ static char *driver_short_names[] __devinitdata = {
  */
 #define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0)
 
+static int azx_acquire_irq(struct azx *chip, int do_disconnect);
 
 /*
  * Interface for HD codec
@@ -517,38 +526,48 @@ static void azx_update_rirb(struct azx *chip)
 static unsigned int azx_rirb_get_response(struct hda_codec *codec)
 {
        struct azx *chip = codec->bus->private_data;
-       int timeout = 50;
+       unsigned long timeout;
 
-       for (;;) {
+ again:
+       timeout = jiffies + msecs_to_jiffies(1000);
+       do {
                if (chip->polling_mode) {
                        spin_lock_irq(&chip->reg_lock);
                        azx_update_rirb(chip);
                        spin_unlock_irq(&chip->reg_lock);
                }
                if (! chip->rirb.cmds)
-                       break;
-               if (! --timeout) {
-                       if (! chip->polling_mode) {
-                               snd_printk(KERN_WARNING "hda_intel: "
-                                          "azx_get_response timeout, "
-                                          "switching to polling mode...\n");
-                               chip->polling_mode = 1;
-                               timeout = 50;
-                               continue;
-                       }
-                       snd_printk(KERN_ERR
-                                  "hda_intel: azx_get_response timeout, "
-                                  "switching to single_cmd mode...\n");
-                       chip->rirb.rp = azx_readb(chip, RIRBWP);
-                       chip->rirb.cmds = 0;
-                       /* switch to single_cmd mode */
-                       chip->single_cmd = 1;
-                       azx_free_cmd_io(chip);
+                       return chip->rirb.res; /* the last value */
+               schedule_timeout(1);
+       } while (time_after_eq(timeout, jiffies));
+
+       if (chip->msi) {
+               snd_printk(KERN_WARNING "hda_intel: No response from codec, "
+                          "disabling MSI...\n");
+               free_irq(chip->irq, chip);
+               chip->irq = -1;
+               pci_disable_msi(chip->pci);
+               chip->msi = 0;
+               if (azx_acquire_irq(chip, 1) < 0)
                        return -1;
-               }
-               msleep(1);
+               goto again;
+       }
+
+       if (!chip->polling_mode) {
+               snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, "
+                          "switching to polling mode...\n");
+               chip->polling_mode = 1;
+               goto again;
        }
-       return chip->rirb.res; /* the last value */
+
+       snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
+                  "switching to single_cmd mode...\n");
+       chip->rirb.rp = azx_readb(chip, RIRBWP);
+       chip->rirb.cmds = 0;
+       /* switch to single_cmd mode */
+       chip->single_cmd = 1;
+       azx_free_cmd_io(chip);
+       return -1;
 }
 
 /*
@@ -658,14 +677,14 @@ static int azx_reset(struct azx *chip)
        azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
 
        count = 50;
-       while (! azx_readb(chip, GCTL) && --count)
+       while (!azx_readb(chip, GCTL) && --count)
                msleep(1);
 
-       /* Brent Chartrand said to wait >= 540us for codecs to intialize */
+       /* Brent Chartrand said to wait >= 540us for codecs to initialize */
        msleep(1);
 
        /* check to see if controller is ready */
-       if (! azx_readb(chip, GCTL)) {
+       if (!azx_readb(chip, GCTL)) {
                snd_printd("azx_reset: controller not ready!\n");
                return -EBUSY;
        }
@@ -674,7 +693,7 @@ static int azx_reset(struct azx *chip)
        azx_writel(chip, GCTL, azx_readl(chip, GCTL) | ICH6_GCTL_UREN);
 
        /* detect codecs */
-       if (! chip->codec_mask) {
+       if (!chip->codec_mask) {
                chip->codec_mask = azx_readw(chip, STATESTS);
                snd_printdd("codec_mask = 0x%x\n", chip->codec_mask);
        }
@@ -782,7 +801,7 @@ static void azx_init_chip(struct azx *chip)
        azx_int_enable(chip);
 
        /* initialize the codec command I/O */
-       if (! chip->single_cmd)
+       if (!chip->single_cmd)
                azx_init_cmd_io(chip);
 
        /* program the position buffer */
@@ -810,7 +829,7 @@ static void azx_init_chip(struct azx *chip)
 /*
  * interrupt handler
  */
-static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
+static irqreturn_t azx_interrupt(int irq, void *dev_id)
 {
        struct azx *chip = dev_id;
        struct azx_dev *azx_dev;
@@ -949,10 +968,20 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
  * Codec initialization
  */
 
+static unsigned int azx_max_codecs[] __devinitdata = {
+       [AZX_DRIVER_ICH] = 3,
+       [AZX_DRIVER_ATI] = 4,
+       [AZX_DRIVER_ATIHDMI] = 4,
+       [AZX_DRIVER_VIA] = 3,           /* FIXME: correct? */
+       [AZX_DRIVER_SIS] = 3,           /* FIXME: correct? */
+       [AZX_DRIVER_ULI] = 3,           /* FIXME: correct? */
+       [AZX_DRIVER_NVIDIA] = 3,        /* FIXME: correct? */
+};
+
 static int __devinit azx_codec_create(struct azx *chip, const char *model)
 {
        struct hda_bus_template bus_temp;
-       int c, codecs, err;
+       int c, codecs, audio_codecs, err;
 
        memset(&bus_temp, 0, sizeof(bus_temp));
        bus_temp.private_data = chip;
@@ -964,16 +993,30 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model)
        if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0)
                return err;
 
-       codecs = 0;
+       codecs = audio_codecs = 0;
        for (c = 0; c < AZX_MAX_CODECS; c++) {
                if ((chip->codec_mask & (1 << c)) & probe_mask) {
-                       err = snd_hda_codec_new(chip->bus, c, NULL);
+                       struct hda_codec *codec;
+                       err = snd_hda_codec_new(chip->bus, c, &codec);
                        if (err < 0)
                                continue;
                        codecs++;
+                       if (codec->afg)
+                               audio_codecs++;
                }
        }
-       if (! codecs) {
+       if (!audio_codecs) {
+               /* probe additional slots if no codec is found */
+               for (; c < azx_max_codecs[chip->driver_type]; c++) {
+                       if ((chip->codec_mask & (1 << c)) & probe_mask) {
+                               err = snd_hda_codec_new(chip->bus, c, NULL);
+                               if (err < 0)
+                                       continue;
+                               codecs++;
+                       }
+               }
+       }
+       if (!codecs) {
                snd_printk(KERN_ERR SFX "no codecs initialized\n");
                return -ENXIO;
        }
@@ -1015,8 +1058,9 @@ static struct snd_pcm_hardware azx_pcm_hw = {
        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                 SNDRV_PCM_INFO_MMAP_VALID |
-                                SNDRV_PCM_INFO_PAUSE /*|*/
-                                /*SNDRV_PCM_INFO_RESUME*/),
+                                /* No full-resume yet implemented */
+                                /* SNDRV_PCM_INFO_RESUME |*/
+                                SNDRV_PCM_INFO_PAUSE),
        .formats =              SNDRV_PCM_FMTBIT_S16_LE,
        .rates =                SNDRV_PCM_RATE_48000,
        .rate_min =             48000,
@@ -1060,6 +1104,10 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
        runtime->hw.rates = hinfo->rates;
        snd_pcm_limit_hw_rates(runtime);
        snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
+                                  128);
+       snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
+                                  128);
        if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) {
                azx_release_device(azx_dev);
                mutex_unlock(&chip->open_mutex);
@@ -1194,7 +1242,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
        if (chip->position_fix == POS_FIX_POSBUF ||
            chip->position_fix == POS_FIX_AUTO) {
                /* use the position buffer */
-               pos = *azx_dev->posbuf;
+               pos = le32_to_cpu(*azx_dev->posbuf);
                if (chip->position_fix == POS_FIX_AUTO &&
                    azx_dev->period_intr == 1 && ! pos) {
                        printk(KERN_WARNING
@@ -1238,7 +1286,12 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
        struct snd_pcm *pcm;
        struct azx_pcm *apcm;
 
-       snd_assert(cpcm->stream[0].substreams || cpcm->stream[1].substreams, return -EINVAL);
+       /* if no substreams are defined for both playback and capture,
+        * it's just a placeholder.  ignore it.
+        */
+       if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
+               return 0;
+
        snd_assert(cpcm->name, return -EINVAL);
 
        err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
@@ -1262,9 +1315,10 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
        snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                                              snd_dma_pci_data(chip->pci),
-                                             1024 * 64, 1024 * 128);
+                                             1024 * 64, 1024 * 1024);
        chip->pcm[pcm_dev] = pcm;
-       chip->pcm_devs = pcm_dev + 1;
+       if (chip->pcm_devs < pcm_dev + 1)
+               chip->pcm_devs = pcm_dev + 1;
 
        return 0;
 }
@@ -1342,7 +1396,7 @@ static int __devinit azx_init_stream(struct azx *chip)
                struct azx_dev *azx_dev = &chip->azx_dev[i];
                azx_dev->bdl = (u32 *)(chip->bdl.area + off);
                azx_dev->bdl_addr = chip->bdl.addr + off;
-               azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
+               azx_dev->posbuf = (u32 __iomem *)(chip->posbuf.area + i * 8);
                /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
                azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
                /* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
@@ -1355,6 +1409,22 @@ static int __devinit azx_init_stream(struct azx *chip)
        return 0;
 }
 
+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)) {
+               printk(KERN_ERR "hda-intel: unable to grab IRQ %d, "
+                      "disabling device\n", chip->pci->irq);
+               if (do_disconnect)
+                       snd_card_disconnect(chip->card);
+               return -1;
+       }
+       chip->irq = chip->pci->irq;
+       pci_intx(chip->pci, !chip->msi);
+       return 0;
+}
+
 
 #ifdef CONFIG_PM
 /*
@@ -1371,8 +1441,16 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
                snd_pcm_suspend_all(chip->pcm[i]);
        snd_hda_suspend(chip->bus, state);
        azx_free_cmd_io(chip);
+       if (chip->irq >= 0) {
+               synchronize_irq(chip->irq);
+               free_irq(chip->irq, chip);
+               chip->irq = -1;
+       }
+       if (chip->msi)
+               pci_disable_msi(chip->pci);
        pci_disable_device(pci);
        pci_save_state(pci);
+       pci_set_power_state(pci, pci_choose_state(pci, state));
        return 0;
 }
 
@@ -1381,9 +1459,20 @@ static int azx_resume(struct pci_dev *pci)
        struct snd_card *card = pci_get_drvdata(pci);
        struct azx *chip = card->private_data;
 
+       pci_set_power_state(pci, PCI_D0);
        pci_restore_state(pci);
-       pci_enable_device(pci);
+       if (pci_enable_device(pci) < 0) {
+               printk(KERN_ERR "hda-intel: pci_enable_device failed, "
+                      "disabling device\n");
+               snd_card_disconnect(card);
+               return -EIO;
+       }
        pci_set_master(pci);
+       if (chip->msi)
+               if (pci_enable_msi(pci) < 0)
+                       chip->msi = 0;
+       if (azx_acquire_irq(chip, 1) < 0)
+               return -EIO;
        azx_init_chip(chip);
        snd_hda_resume(chip->bus);
        snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -1413,13 +1502,14 @@ static int azx_free(struct azx *chip)
                /* disable position buffer */
                azx_writel(chip, DPLBASE, 0);
                azx_writel(chip, DPUBASE, 0);
-
-               /* wait a little for interrupts to finish */
-               msleep(1);
        }
 
-       if (chip->irq >= 0)
+       if (chip->irq >= 0) {
+               synchronize_irq(chip->irq);
                free_irq(chip->irq, (void*)chip);
+       }
+       if (chip->msi)
+               pci_disable_msi(chip->pci);
        if (chip->remap_addr)
                iounmap(chip->remap_addr);
 
@@ -1442,6 +1532,31 @@ static int azx_dev_free(struct snd_device *device)
        return azx_free(device->device_data);
 }
 
+/*
+ * white/black-listing for position_fix
+ */
+static struct snd_pci_quirk position_fix_list[] __devinitdata = {
+       SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
+       {}
+};
+
+static int __devinit check_position_fix(struct azx *chip, int fix)
+{
+       const struct snd_pci_quirk *q;
+
+       if (fix == POS_FIX_AUTO) {
+               q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
+               if (q) {
+                       snd_printdd(KERN_INFO
+                                   "hda_intel: position_fix set to %d "
+                                   "for device %04x:%04x\n",
+                                   q->value, q->subvendor, q->subdevice);
+                       return q->value;
+               }
+       }
+       return fix;
+}
+
 /*
  * constructor
  */
@@ -1450,19 +1565,19 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                                struct azx **rchip)
 {
        struct azx *chip;
-       int err = 0;
+       int err;
        static struct snd_device_ops ops = {
                .dev_free = azx_dev_free,
        };
 
        *rchip = NULL;
        
-       if ((err = pci_enable_device(pci)) < 0)
+       err = pci_enable_device(pci);
+       if (err < 0)
                return err;
 
        chip = kzalloc(sizeof(*chip), GFP_KERNEL);
-       
-       if (NULL == chip) {
+       if (!chip) {
                snd_printk(KERN_ERR SFX "cannot allocate chip\n");
                pci_disable_device(pci);
                return -ENOMEM;
@@ -1474,8 +1589,10 @@ 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;
+
+       chip->position_fix = check_position_fix(chip, position_fix);
 
-       chip->position_fix = position_fix;
        chip->single_cmd = single_cmd;
 
 #if BITS_PER_LONG != 64
@@ -1488,13 +1605,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        }
 #endif
 
-       if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
+       err = pci_request_regions(pci, "ICH HD audio");
+       if (err < 0) {
                kfree(chip);
                pci_disable_device(pci);
                return err;
        }
 
-       chip->addr = pci_resource_start(pci,0);
+       chip->addr = pci_resource_start(pci, 0);
        chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0));
        if (chip->remap_addr == NULL) {
                snd_printk(KERN_ERR SFX "ioremap error\n");
@@ -1502,13 +1620,14 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                goto errout;
        }
 
-       if (request_irq(pci->irq, azx_interrupt, IRQF_DISABLED|IRQF_SHARED,
-                       "HDA Intel", (void*)chip)) {
-               snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
+       if (chip->msi)
+               if (pci_enable_msi(pci) < 0)
+                       chip->msi = 0;
+
+       if (azx_acquire_irq(chip, 0) < 0) {
                err = -EBUSY;
                goto errout;
        }
-       chip->irq = pci->irq;
 
        pci_set_master(pci);
        synchronize_irq(chip->irq);
@@ -1535,7 +1654,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        }
        chip->num_streams = chip->playback_streams + chip->capture_streams;
        chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL);
-       if (! chip->azx_dev) {
+       if (!chip->azx_dev) {
                snd_printk(KERN_ERR "cannot malloc azx_dev\n");
                goto errout;
        }
@@ -1566,7 +1685,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        chip->initialized = 1;
 
        /* codec detection */
-       if (! chip->codec_mask) {
+       if (!chip->codec_mask) {
                snd_printk(KERN_ERR SFX "no codecs found!\n");
                err = -ENODEV;
                goto errout;
@@ -1593,16 +1712,16 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *
 {
        struct snd_card *card;
        struct azx *chip;
-       int err = 0;
+       int err;
 
        card = snd_card_new(index, id, THIS_MODULE, 0);
-       if (NULL == card) {
+       if (!card) {
                snd_printk(KERN_ERR SFX "Error creating card!\n");
                return -ENOMEM;
        }
 
-       if ((err = azx_create(card, pci, pci_id->driver_data,
-                             &chip)) < 0) {
+       err = azx_create(card, pci, pci_id->driver_data, &chip);
+       if (err < 0) {
                snd_card_free(card);
                return err;
        }
@@ -1650,14 +1769,31 @@ static struct pci_device_id azx_ids[] = {
        { 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
        { 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
        { 0x8086, 0x284b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH8 */
+       { 0x8086, 0x293e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
+       { 0x8086, 0x293f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH9 */
        { 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
        { 0x1002, 0x4383, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB600 */
        { 0x1002, 0x793b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS600 HDMI */
+       { 0x1002, 0x7919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS690 HDMI */
+       { 0x1002, 0x960c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RS780 HDMI */
+       { 0x1002, 0xaa00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI R600 HDMI */
        { 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
        { 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
        { 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
-       { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 026c */
-       { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA 0371 */
+       { 0x10de, 0x026c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP51 */
+       { 0x10de, 0x0371, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP55 */
+       { 0x10de, 0x03e4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+       { 0x10de, 0x03f0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP61 */
+       { 0x10de, 0x044a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+       { 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */
+       { 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
+       { 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */
+       { 0x10de, 0x07fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
+       { 0x10de, 0x07fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */
+       { 0x10de, 0x0774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+       { 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+       { 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
+       { 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);