]> err.no Git - linux-2.6/blobdiff - sound/pci/hda/hda_intel.c
[ALSA] hda_intel: Add the DIDs of nvidia MCP79 HD audio controller to hda_intel.c
[linux-2.6] / sound / pci / hda / hda_intel.c
index 4be36c84b36c7c8354a707d9956430602de45e73..3d9f0bd63ba69e8d1f47fdcac89b1b1346af4e7b 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/dma-mapping.h>
 #include <linux/moduleparam.h>
 #include <linux/init.h>
 #include <linux/slab.h>
@@ -185,35 +186,28 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 
 /* max number of SDs */
 /* ICH, ATI and VIA have 4 playback and 4 capture */
-#define ICH6_CAPTURE_INDEX     0
 #define ICH6_NUM_CAPTURE       4
-#define ICH6_PLAYBACK_INDEX    4
 #define ICH6_NUM_PLAYBACK      4
 
 /* ULI has 6 playback and 5 capture */
-#define ULI_CAPTURE_INDEX      0
 #define ULI_NUM_CAPTURE                5
-#define ULI_PLAYBACK_INDEX     5
 #define ULI_NUM_PLAYBACK       6
 
 /* ATI HDMI has 1 playback and 0 capture */
-#define ATIHDMI_CAPTURE_INDEX  0
 #define ATIHDMI_NUM_CAPTURE    0
-#define ATIHDMI_PLAYBACK_INDEX 0
 #define ATIHDMI_NUM_PLAYBACK   1
 
 /* this number is statically defined for simplicity */
 #define MAX_AZX_DEV            16
 
 /* max number of fragments - we may use more if allocating more pages for BDL */
-#define BDL_SIZE               PAGE_ALIGN(8192)
-#define AZX_MAX_FRAG           (BDL_SIZE / (MAX_AZX_DEV * 16))
+#define BDL_SIZE               4096
+#define AZX_MAX_BDL_ENTRIES    (BDL_SIZE / 16)
+#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_AUDIO_PCMS     6
-#define AZX_MAX_MODEM_PCMS     2
-#define AZX_MAX_PCMS           (AZX_MAX_AUDIO_PCMS + AZX_MAX_MODEM_PCMS)
+#define AZX_MAX_PCMS           8
 
 /* RIRB int mask: overrun[2], response[0] */
 #define RIRB_INT_RESPONSE      0x01
@@ -284,12 +278,10 @@ enum {
  */
 
 struct azx_dev {
-       u32 *bdl;               /* virtual address of the BDL */
-       dma_addr_t bdl_addr;    /* physical address of the BDL */
+       struct snd_dma_buffer bdl; /* BDL buffer */
        u32 *posbuf;            /* position buffer pointer */
 
        unsigned int bufsize;   /* size of the play buffer in bytes */
-       unsigned int fragsize;  /* size of each period in bytes */
        unsigned int frags;     /* number for period in the play buffer */
        unsigned int fifo_size; /* FIFO size */
 
@@ -350,7 +342,6 @@ struct azx {
        struct azx_dev *azx_dev;
 
        /* PCM */
-       unsigned int pcm_devs;
        struct snd_pcm *pcm[AZX_MAX_PCMS];
 
        /* HD codec */
@@ -361,8 +352,7 @@ struct azx {
        struct azx_rb corb;
        struct azx_rb rirb;
 
-       /* BDL, CORB/RIRB and position buffers */
-       struct snd_dma_buffer bdl;
+       /* CORB/RIRB and position buffers */
        struct snd_dma_buffer rb;
        struct snd_dma_buffer posbuf;
 
@@ -965,30 +955,57 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id)
 /*
  * set up BDL entries
  */
-static void azx_setup_periods(struct azx_dev *azx_dev)
+static int azx_setup_periods(struct snd_pcm_substream *substream,
+                            struct azx_dev *azx_dev)
 {
-       u32 *bdl = azx_dev->bdl;
-       dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr;
-       int idx;
+       struct snd_sg_buf *sgbuf = snd_pcm_substream_sgbuf(substream);
+       u32 *bdl;
+       int i, ofs, periods, period_bytes;
 
        /* reset BDL address */
        azx_sd_writel(azx_dev, SD_BDLPL, 0);
        azx_sd_writel(azx_dev, SD_BDLPU, 0);
 
+       period_bytes = snd_pcm_lib_period_bytes(substream);
+       periods = azx_dev->bufsize / period_bytes;
+
        /* program the initial BDL entries */
-       for (idx = 0; idx < azx_dev->frags; idx++) {
-               unsigned int off = idx << 2; /* 4 dword step */
-               dma_addr_t addr = dma_addr + idx * azx_dev->fragsize;
-               /* program the address field of the BDL entry */
-               bdl[off] = cpu_to_le32((u32)addr);
-               bdl[off+1] = cpu_to_le32(upper_32bit(addr));
-
-               /* program the size field of the BDL entry */
-               bdl[off+2] = cpu_to_le32(azx_dev->fragsize);
-
-               /* program the IOC to enable interrupt when buffer completes */
-               bdl[off+3] = cpu_to_le32(0x01);
+       bdl = (u32 *)azx_dev->bdl.area;
+       ofs = 0;
+       azx_dev->frags = 0;
+       for (i = 0; i < periods; i++) {
+               int size, rest;
+               if (i >= AZX_MAX_BDL_ENTRIES) {
+                       snd_printk(KERN_ERR "Too many BDL entries: "
+                                  "buffer=%d, period=%d\n",
+                                  azx_dev->bufsize, period_bytes);
+                       /* reset */
+                       azx_sd_writel(azx_dev, SD_BDLPL, 0);
+                       azx_sd_writel(azx_dev, SD_BDLPU, 0);
+                       return -EINVAL;
+               }
+               rest = period_bytes;
+               do {
+                       dma_addr_t addr = snd_pcm_sgbuf_get_addr(sgbuf, ofs);
+                       /* program the address field of the BDL entry */
+                       bdl[0] = cpu_to_le32((u32)addr);
+                       bdl[1] = cpu_to_le32(upper_32bit(addr));
+                       /* program the size field of the BDL entry */
+                       size = PAGE_SIZE - (ofs % PAGE_SIZE);
+                       if (rest < size)
+                               size = rest;
+                       bdl[2] = cpu_to_le32(size);
+                       /* program the IOC to enable interrupt
+                        * only when the whole fragment is processed
+                        */
+                       rest -= size;
+                       bdl[3] = rest ? 0 : cpu_to_le32(0x01);
+                       bdl += 4;
+                       azx_dev->frags++;
+                       ofs += size;
+               } while (rest > 0);
        }
+       return 0;
 }
 
 /*
@@ -1037,9 +1054,9 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
 
        /* program the BDL address */
        /* lower BDL address */
-       azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl_addr);
+       azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl.addr);
        /* upper BDL address */
-       azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
+       azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl.addr));
 
        /* enable the position buffer */
        if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
@@ -1275,8 +1292,6 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
 
        azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
-       azx_dev->fragsize = snd_pcm_lib_period_bytes(substream);
-       azx_dev->frags = azx_dev->bufsize / azx_dev->fragsize;
        azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
                                                         runtime->channels,
                                                         runtime->format,
@@ -1288,10 +1303,10 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
                return -EINVAL;
        }
 
-       snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, "
-                   "format=0x%x\n",
-                   azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val);
-       azx_setup_periods(azx_dev);
+       snd_printdd("azx_pcm_prepare: bufsize=0x%x, format=0x%x\n",
+                   azx_dev->bufsize, azx_dev->format_val);
+       if (azx_setup_periods(substream, azx_dev) < 0)
+               return -EINVAL;
        azx_setup_controller(chip, azx_dev);
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
                azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
@@ -1378,6 +1393,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
        .prepare = azx_pcm_prepare,
        .trigger = azx_pcm_trigger,
        .pointer = azx_pcm_pointer,
+       .page = snd_pcm_sgbuf_ops_page,
 };
 
 static void azx_pcm_free(struct snd_pcm *pcm)
@@ -1386,7 +1402,7 @@ static void azx_pcm_free(struct snd_pcm *pcm)
 }
 
 static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
-                                     struct hda_pcm *cpcm, int pcm_dev)
+                                     struct hda_pcm *cpcm)
 {
        int err;
        struct snd_pcm *pcm;
@@ -1400,7 +1416,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
 
        snd_assert(cpcm->name, return -EINVAL);
 
-       err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
+       err = snd_pcm_new(chip->card, cpcm->name, cpcm->device,
                          cpcm->stream[0].substreams,
                          cpcm->stream[1].substreams,
                          &pcm);
@@ -1420,62 +1436,70 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops);
        if (cpcm->stream[1].substreams)
                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_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
                                              snd_dma_pci_data(chip->pci),
                                              1024 * 64, 1024 * 1024);
-       chip->pcm[pcm_dev] = pcm;
-       if (chip->pcm_devs < pcm_dev + 1)
-               chip->pcm_devs = pcm_dev + 1;
-
+       chip->pcm[cpcm->device] = pcm;
        return 0;
 }
 
 static int __devinit azx_pcm_create(struct azx *chip)
 {
+       static const char *dev_name[HDA_PCM_NTYPES] = {
+               "Audio", "SPDIF", "HDMI", "Modem"
+       };
+       /* starting device index for each PCM type */
+       static int dev_idx[HDA_PCM_NTYPES] = {
+               [HDA_PCM_TYPE_AUDIO] = 0,
+               [HDA_PCM_TYPE_SPDIF] = 1,
+               [HDA_PCM_TYPE_HDMI] = 3,
+               [HDA_PCM_TYPE_MODEM] = 6
+       };
+       /* normal audio device indices; not linear to keep compatibility */
+       static int audio_idx[4] = { 0, 2, 4, 5 };
        struct hda_codec *codec;
        int c, err;
-       int pcm_dev;
+       int num_devs[HDA_PCM_NTYPES];
 
        err = snd_hda_build_pcms(chip->bus);
        if (err < 0)
                return err;
 
        /* create audio PCMs */
-       pcm_dev = 0;
+       memset(num_devs, 0, sizeof(num_devs));
        list_for_each_entry(codec, &chip->bus->codec_list, list) {
                for (c = 0; c < codec->num_pcms; c++) {
-                       if (codec->pcm_info[c].is_modem)
-                               continue; /* create later */
-                       if (pcm_dev >= AZX_MAX_AUDIO_PCMS) {
-                               snd_printk(KERN_ERR SFX
-                                          "Too many audio PCMs\n");
-                               return -EINVAL;
-                       }
-                       err = create_codec_pcm(chip, codec,
-                                              &codec->pcm_info[c], pcm_dev);
-                       if (err < 0)
-                               return err;
-                       pcm_dev++;
-               }
-       }
-
-       /* create modem PCMs */
-       pcm_dev = AZX_MAX_AUDIO_PCMS;
-       list_for_each_entry(codec, &chip->bus->codec_list, list) {
-               for (c = 0; c < codec->num_pcms; c++) {
-                       if (!codec->pcm_info[c].is_modem)
-                               continue; /* already created */
-                       if (pcm_dev >= AZX_MAX_PCMS) {
-                               snd_printk(KERN_ERR SFX
-                                          "Too many modem PCMs\n");
-                               return -EINVAL;
+                       struct hda_pcm *cpcm = &codec->pcm_info[c];
+                       int type = cpcm->pcm_type;
+                       switch (type) {
+                       case HDA_PCM_TYPE_AUDIO:
+                               if (num_devs[type] >= ARRAY_SIZE(audio_idx)) {
+                                       snd_printk(KERN_WARNING
+                                                  "Too many audio devices\n");
+                                       continue;
+                               }
+                               cpcm->device = audio_idx[num_devs[type]];
+                               break;
+                       case HDA_PCM_TYPE_SPDIF:
+                       case HDA_PCM_TYPE_HDMI:
+                       case HDA_PCM_TYPE_MODEM:
+                               if (num_devs[type]) {
+                                       snd_printk(KERN_WARNING
+                                                  "%s already defined\n",
+                                                  dev_name[type]);
+                                       continue;
+                               }
+                               cpcm->device = dev_idx[type];
+                               break;
+                       default:
+                               snd_printk(KERN_WARNING
+                                          "Invalid PCM type %d\n", type);
+                               continue;
                        }
-                       err = create_codec_pcm(chip, codec,
-                                              &codec->pcm_info[c], pcm_dev);
+                       num_devs[type]++;
+                       err = create_codec_pcm(chip, codec, cpcm);
                        if (err < 0)
                                return err;
-                       chip->pcm[pcm_dev]->dev_class = SNDRV_PCM_CLASS_MODEM;
-                       pcm_dev++;
                }
        }
        return 0;
@@ -1502,10 +1526,7 @@ static int __devinit azx_init_stream(struct azx *chip)
         * and initialize
         */
        for (i = 0; i < chip->num_streams; i++) {
-               unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
                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 = (u32 __iomem *)(chip->posbuf.area + i * 8);
                /* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
                azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
@@ -1587,7 +1608,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
        int i;
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-       for (i = 0; i < chip->pcm_devs; i++)
+       for (i = 0; i < AZX_MAX_PCMS; i++)
                snd_pcm_suspend_all(chip->pcm[i]);
        if (chip->initialized)
                snd_hda_suspend(chip->bus, state);
@@ -1641,8 +1662,9 @@ static int azx_resume(struct pci_dev *pci)
  */
 static int azx_free(struct azx *chip)
 {
+       int i;
+
        if (chip->initialized) {
-               int i;
                for (i = 0; i < chip->num_streams; i++)
                        azx_stream_stop(chip, &chip->azx_dev[i]);
                azx_stop_chip(chip);
@@ -1657,8 +1679,11 @@ static int azx_free(struct azx *chip)
        if (chip->remap_addr)
                iounmap(chip->remap_addr);
 
-       if (chip->bdl.area)
-               snd_dma_free_pages(&chip->bdl);
+       if (chip->azx_dev) {
+               for (i = 0; i < chip->num_streams; i++)
+                       if (chip->azx_dev[i].bdl.area)
+                               snd_dma_free_pages(&chip->azx_dev[i].bdl);
+       }
        if (chip->rb.area)
                snd_dma_free_pages(&chip->rb);
        if (chip->posbuf.area)
@@ -1740,7 +1765,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                                struct azx **rchip)
 {
        struct azx *chip;
-       int err;
+       int i, err;
        unsigned short gcap;
        static struct snd_device_ops ops = {
                .dev_free = azx_dev_free,
@@ -1812,38 +1837,35 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
        gcap = azx_readw(chip, GCAP);
        snd_printdd("chipset global capabilities = 0x%x\n", gcap);
 
-       if (gcap) {
-               /* read number of streams from GCAP register instead of using
-                * hardcoded value
-                */
-               chip->playback_streams = (gcap & (0xF << 12)) >> 12;
-               chip->capture_streams = (gcap & (0xF << 8)) >> 8;
-               chip->playback_index_offset = chip->capture_streams;
-               chip->capture_index_offset = 0;
-       } else {
+       /* allow 64bit DMA address if supported by H/W */
+       if ((gcap & 0x01) && !pci_set_dma_mask(pci, DMA_64BIT_MASK))
+               pci_set_consistent_dma_mask(pci, DMA_64BIT_MASK);
+
+       /* read number of streams from GCAP register instead of using
+        * hardcoded value
+        */
+       chip->capture_streams = (gcap >> 8) & 0x0f;
+       chip->playback_streams = (gcap >> 12) & 0x0f;
+       if (!chip->playback_streams && !chip->capture_streams) {
                /* gcap didn't give any info, switching to old method */
 
                switch (chip->driver_type) {
                case AZX_DRIVER_ULI:
                        chip->playback_streams = ULI_NUM_PLAYBACK;
                        chip->capture_streams = ULI_NUM_CAPTURE;
-                       chip->playback_index_offset = ULI_PLAYBACK_INDEX;
-                       chip->capture_index_offset = ULI_CAPTURE_INDEX;
                        break;
                case AZX_DRIVER_ATIHDMI:
                        chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
                        chip->capture_streams = ATIHDMI_NUM_CAPTURE;
-                       chip->playback_index_offset = ATIHDMI_PLAYBACK_INDEX;
-                       chip->capture_index_offset = ATIHDMI_CAPTURE_INDEX;
                        break;
                default:
                        chip->playback_streams = ICH6_NUM_PLAYBACK;
                        chip->capture_streams = ICH6_NUM_CAPTURE;
-                       chip->playback_index_offset = ICH6_PLAYBACK_INDEX;
-                       chip->capture_index_offset = ICH6_CAPTURE_INDEX;
                        break;
                }
        }
+       chip->capture_index_offset = 0;
+       chip->playback_index_offset = chip->capture_streams;
        chip->num_streams = chip->playback_streams + chip->capture_streams;
        chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev),
                                GFP_KERNEL);
@@ -1852,13 +1874,15 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
                goto errout;
        }
 
-       /* allocate memory for the BDL for each stream */
-       err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
-                                 snd_dma_pci_data(chip->pci),
-                                 BDL_SIZE, &chip->bdl);
-       if (err < 0) {
-               snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
-               goto errout;
+       for (i = 0; i < chip->num_streams; i++) {
+               /* allocate memory for the BDL for each stream */
+               err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
+                                         snd_dma_pci_data(chip->pci),
+                                         BDL_SIZE, &chip->azx_dev[i].bdl);
+               if (err < 0) {
+                       snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
+                       goto errout;
+               }
        }
        /* allocate memory for the position buffer */
        err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
@@ -1994,48 +2018,63 @@ static void __devexit azx_remove(struct pci_dev *pci)
 
 /* PCI IDs */
 static struct pci_device_id azx_ids[] = {
-       { 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */
-       { 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 */
-       { 0x8086, 0x3a3e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
-       { 0x8086, 0x3a6e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH10 */
-       { 0x8086, 0x811b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SCH }, /* SCH*/
-       { 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, 0x960f, 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 */
-       { 0x1002, 0xaa08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV630 HDMI */
-       { 0x1002, 0xaa10, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV610 HDMI */
-       { 0x1002, 0xaa18, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV670 HDMI */
-       { 0x1002, 0xaa20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV635 HDMI */
-       { 0x1002, 0xaa28, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV620 HDMI */
-       { 0x1002, 0xaa30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATIHDMI }, /* ATI RV770 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 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 */
-       { 0x10de, 0x0ac0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
-       { 0x10de, 0x0ac1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
-       { 0x10de, 0x0ac2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
-       { 0x10de, 0x0ac3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP79 */
+       /* ICH 6..10 */
+       { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH },
+       { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH },
+       /* SCH */
+       { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH },
+       /* ATI SB 450/600 */
+       { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI },
+       { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI },
+       /* ATI HDMI */
+       { PCI_DEVICE(0x1002, 0x793b), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0x7919), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0x960f), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa00), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa08), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa10), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa18), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa20), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa28), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa30), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa38), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa40), .driver_data = AZX_DRIVER_ATIHDMI },
+       { PCI_DEVICE(0x1002, 0xaa48), .driver_data = AZX_DRIVER_ATIHDMI },
+       /* VIA VT8251/VT8237A */
+       { PCI_DEVICE(0x1106, 0x3288), .driver_data = AZX_DRIVER_VIA },
+       /* SIS966 */
+       { PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS },
+       /* 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, 0x0bd4), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0bd5), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0bd6), .driver_data = AZX_DRIVER_NVIDIA },
+       { PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
        { 0, }
 };
 MODULE_DEVICE_TABLE(pci, azx_ids);