[ALSA] intel8x0 - Fix irq handler registration
[safe/jmp/linux-2.6] / sound / pci / intel8x0.c
index cc16f95..0801083 100644 (file)
@@ -64,92 +64,38 @@ MODULE_SUPPORTED_DEVICE("{{Intel,82801AA-ICH},"
                "{AMD,AMD8111},"
                "{ALI,M5455}}");
 
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;     /* Enable this card */
-static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
-static char *ac97_quirk[SNDRV_CARDS];
-static int buggy_irq[SNDRV_CARDS];
-static int xbox[SNDRV_CARDS];
-
-#ifdef SUPPORT_MIDI
-static int mpu_port[SNDRV_CARDS]; /* disabled */
-#endif
-
-module_param_array(index, int, NULL, 0444);
+static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
+static char *id = SNDRV_DEFAULT_STR1;  /* ID for this card */
+static int ac97_clock = 0;
+static char *ac97_quirk;
+static int buggy_semaphore;
+static int buggy_irq = -1; /* auto-check */
+static int xbox;
+
+module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
-module_param_array(id, charp, NULL, 0444);
+module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard.");
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable Intel i8x0 soundcard.");
-module_param_array(ac97_clock, int, NULL, 0444);
+module_param(ac97_clock, int, 0444);
 MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
-module_param_array(ac97_quirk, charp, NULL, 0444);
+module_param(ac97_quirk, charp, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
-module_param_array(buggy_irq, bool, NULL, 0444);
+module_param(buggy_semaphore, bool, 0444);
+MODULE_PARM_DESC(buggy_semaphore, "Enable workaround for hardwares with problematic codec semaphores.");
+module_param(buggy_irq, bool, 0444);
 MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
-module_param_array(xbox, bool, NULL, 0444);
+module_param(xbox, bool, 0444);
 MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
 
+/* just for backward compatibility */
+static int enable;
+module_param(enable, bool, 0444);
+static int joystick;
+module_param(joystick, int, 0444);
+
 /*
  *  Direct registers
  */
-
-#ifndef PCI_DEVICE_ID_INTEL_82801
-#define PCI_DEVICE_ID_INTEL_82801       0x2415
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82901
-#define PCI_DEVICE_ID_INTEL_82901       0x2425
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_82801BA
-#define PCI_DEVICE_ID_INTEL_82801BA     0x2445
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_440MX
-#define PCI_DEVICE_ID_INTEL_440MX       0x7195
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH3
-#define PCI_DEVICE_ID_INTEL_ICH3       0x2485
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH4
-#define PCI_DEVICE_ID_INTEL_ICH4       0x24c5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH5
-#define PCI_DEVICE_ID_INTEL_ICH5       0x24d5
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB_5
-#define PCI_DEVICE_ID_INTEL_ESB_5      0x25a6
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_18
-#define PCI_DEVICE_ID_INTEL_ICH6_18    0x266e
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH7_20
-#define PCI_DEVICE_ID_INTEL_ICH7_20    0x27de
-#endif
-#ifndef PCI_DEVICE_ID_INTEL_ESB2_14
-#define PCI_DEVICE_ID_INTEL_ESB2_14    0x2698
-#endif
-#ifndef PCI_DEVICE_ID_SI_7012
-#define PCI_DEVICE_ID_SI_7012          0x7012
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP_AUDIO 0x01b1
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK804_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO 0x0059
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO        0x006a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK8_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO        0x00da
-#endif
-#ifndef PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO
-#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO        0x00ea
-#endif
-
 enum { DEVICE_INTEL, DEVICE_INTEL_ICH4, DEVICE_SIS, DEVICE_ALI, DEVICE_NFORCE };
 
 #define ICHREG(x) ICH_REG_##x
@@ -389,6 +335,7 @@ typedef struct {
        struct ac97_pcm *pcm;
        int pcm_open_flag;
        unsigned int page_attr_changed: 1;
+       unsigned int suspended: 1;
 } ichdev_t;
 
 typedef struct _snd_intel8x0 intel8x0_t;
@@ -422,8 +369,10 @@ struct _snd_intel8x0 {
        unsigned fix_nocache: 1;        /* workaround for 440MX */
        unsigned buggy_irq: 1;          /* workaround for buggy mobos */
        unsigned xbox: 1;               /* workaround for Xbox AC'97 detection */
+       unsigned buggy_semaphore: 1;    /* workaround for buggy codec semaphore */
 
        int spdif_idx;  /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
+       unsigned int sdm_saved; /* SDM reg value */
 
        ac97_bus_t *ac97_bus;
        ac97_t *ac97[3];
@@ -575,6 +524,9 @@ static int snd_intel8x0_codec_semaphore(intel8x0_t *chip, unsigned int codec)
        if ((igetdword(chip, ICHREG(GLOB_STA)) & codec) == 0)
                return -EIO;
 
+       if (chip->buggy_semaphore)
+               return 0; /* just ignore ... */
+
        /* Anyone holding a semaphore for 1 msec should be shot... */
        time = 100;
        do {
@@ -586,7 +538,7 @@ static int snd_intel8x0_codec_semaphore(intel8x0_t *chip, unsigned int codec)
        /* access to some forbidden (non existant) ac97 registers will not
         * reset the semaphore. So even if you don't get the semaphore, still
         * continue the access. We don't need the semaphore anyway. */
-       snd_printk("codec_semaphore: semaphore is not ready [0x%x][0x%x]\n",
+       snd_printk(KERN_ERR "codec_semaphore: semaphore is not ready [0x%x][0x%x]\n",
                        igetbyte(chip, ICHREG(ACC_SEMA)), igetdword(chip, ICHREG(GLOB_STA)));
        iagetword(chip, 0);     /* clear semaphore flag */
        /* I don't care about the semaphore */
@@ -601,7 +553,7 @@ static void snd_intel8x0_codec_write(ac97_t *ac97,
        
        if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) {
                if (! chip->in_ac97_init)
-                       snd_printk("codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg);
+                       snd_printk(KERN_ERR "codec_write %d: semaphore is not ready for register 0x%x\n", ac97->num, reg);
        }
        iaputword(chip, reg + ac97->num * 0x80, val);
 }
@@ -615,7 +567,7 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
 
        if (snd_intel8x0_codec_semaphore(chip, ac97->num) < 0) {
                if (! chip->in_ac97_init)
-                       snd_printk("codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg);
+                       snd_printk(KERN_ERR "codec_read %d: semaphore is not ready for register 0x%x\n", ac97->num, reg);
                res = 0xffff;
        } else {
                res = iagetword(chip, reg + ac97->num * 0x80);
@@ -623,7 +575,7 @@ static unsigned short snd_intel8x0_codec_read(ac97_t *ac97,
                        /* reset RCS and preserve other R/WC bits */
                        iputdword(chip, ICHREG(GLOB_STA), tmp & ~(ICH_SRI|ICH_PRI|ICH_TRI|ICH_GSCI));
                        if (! chip->in_ac97_init)
-                               snd_printk("codec_read %d: read timeout for register 0x%x\n", ac97->num, reg);
+                               snd_printk(KERN_ERR "codec_read %d: read timeout for register 0x%x\n", ac97->num, reg);
                        res = 0xffff;
                }
        }
@@ -654,16 +606,19 @@ static int snd_intel8x0_ali_codec_ready(intel8x0_t *chip, int mask)
                if (val & mask)
                        return 0;
        }
-       snd_printd(KERN_WARNING "intel8x0: AC97 codec ready timeout.\n");
+       if (! chip->in_ac97_init)
+               snd_printd(KERN_WARNING "intel8x0: AC97 codec ready timeout.\n");
        return -EBUSY;
 }
 
 static int snd_intel8x0_ali_codec_semaphore(intel8x0_t *chip)
 {
        int time = 100;
+       if (chip->buggy_semaphore)
+               return 0; /* just ignore ... */
        while (time-- && (igetdword(chip, ICHREG(ALI_CAS)) & ALI_CAS_SEM_BUSY))
                udelay(1);
-       if (! time)
+       if (! time && ! chip->in_ac97_init)
                snd_printk(KERN_WARNING "ali_codec_semaphore timeout\n");
        return snd_intel8x0_ali_codec_ready(chip, ALI_CSPSR_CODEC_READY);
 }
@@ -861,12 +816,16 @@ static int snd_intel8x0_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
        unsigned long port = ichdev->reg_offset;
 
        switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_RESUME:
+               ichdev->suspended = 0;
+               /* fallthru */
+       case SNDRV_PCM_TRIGGER_START:
                val = ICH_IOCE | ICH_STARTBM;
                break;
-       case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_SUSPEND:
+               ichdev->suspended = 1;
+               /* fallthru */
+       case SNDRV_PCM_TRIGGER_STOP:
                val = 0;
                break;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -898,9 +857,11 @@ static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
 
        val = igetdword(chip, ICHREG(ALI_DMACR));
        switch (cmd) {
+       case SNDRV_PCM_TRIGGER_RESUME:
+               ichdev->suspended = 0;
+               /* fallthru */
        case SNDRV_PCM_TRIGGER_START:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-       case SNDRV_PCM_TRIGGER_RESUME:
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                        /* clear FIFO for synchronization of channels */
                        fifo = igetdword(chip, fiforeg[ichdev->ali_slot / 4]);
@@ -912,9 +873,11 @@ static int snd_intel8x0_ali_trigger(snd_pcm_substream_t *substream, int cmd)
                val &= ~(1 << (ichdev->ali_slot + 16)); /* clear PAUSE flag */
                iputdword(chip, ICHREG(ALI_DMACR), val | (1 << ichdev->ali_slot)); /* start DMA */
                break;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               ichdev->suspended = 1;
+               /* fallthru */
        case SNDRV_PCM_TRIGGER_STOP:
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
                iputdword(chip, ICHREG(ALI_DMACR), val | (1 << (ichdev->ali_slot + 16))); /* pause */
                iputbyte(chip, port + ICH_REG_OFF_CR, 0);
                while (igetbyte(chip, port + ICH_REG_OFF_CR))
@@ -993,6 +956,8 @@ static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
 {
        unsigned int cnt;
        int dbl = runtime->rate > 48000;
+
+       spin_lock_irq(&chip->reg_lock);
        switch (chip->device_type) {
        case DEVICE_ALI:
                cnt = igetdword(chip, ICHREG(ALI_SCR));
@@ -1036,6 +1001,7 @@ static void snd_intel8x0_setup_pcm_out(intel8x0_t *chip,
                iputdword(chip, ICHREG(GLOB_CNT), cnt);
                break;
        }
+       spin_unlock_irq(&chip->reg_lock);
 }
 
 static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
@@ -1047,15 +1013,12 @@ static int snd_intel8x0_pcm_prepare(snd_pcm_substream_t * substream)
        ichdev->physbuf = runtime->dma_addr;
        ichdev->size = snd_pcm_lib_buffer_bytes(substream);
        ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
-       spin_lock_irq(&chip->reg_lock);
        if (ichdev->ichd == ICHD_PCMOUT) {
                snd_intel8x0_setup_pcm_out(chip, runtime);
-               if (chip->device_type == DEVICE_INTEL_ICH4) {
+               if (chip->device_type == DEVICE_INTEL_ICH4)
                        ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
-               }
        }
        snd_intel8x0_setup_periods(chip, ichdev);
-       spin_unlock_irq(&chip->reg_lock);
        return 0;
 }
 
@@ -1749,6 +1712,18 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
                .type = AC97_TUNE_ALC_JACK
        },
        {
+               .subvendor = 0x1014,
+               .subdevice = 0x0267,
+               .name = "IBM NetVista A30p",    /* AD1981B */
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .subvendor = 0x1025,
+               .subdevice = 0x0083,
+               .name = "Acer Aspire 3003LCi",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
                .subvendor = 0x1028,
                .subdevice = 0x00d8,
                .name = "Dell Precision 530",   /* AD1885 */
@@ -1791,6 +1766,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
                .type = AC97_TUNE_HP_ONLY
        },
        {
+               .subvendor = 0x1028,
+               .subdevice = 0x0191,
+               .name = "Dell Inspiron 8600",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
                .subvendor = 0x103c,
                .subdevice = 0x006d,
                .name = "HP zv5000",
@@ -1816,6 +1797,18 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
        },
        {
                .subvendor = 0x103c,
+               .subdevice = 0x0934,
+               .name = "HP nx8220",
+               .type = AC97_TUNE_MUTE_LED
+       },
+       {
+               .subvendor = 0x103c,
+               .subdevice = 0x099c,
+               .name = "HP nx6110",    /* AD1981B */
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
+               .subvendor = 0x103c,
                .subdevice = 0x129d,
                .name = "HP xw8000",
                .type = AC97_TUNE_HP_ONLY
@@ -1869,6 +1862,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
                .type = AC97_TUNE_HP_ONLY
        },
        {
+               .subvendor = 0x10cf,
+               .subdevice = 0x12ec,
+               .name = "Fujitsu-Siemens 4010",
+               .type = AC97_TUNE_HP_ONLY
+       },
+       {
                .subvendor = 0x10f1,
                .subdevice = 0x2665,
                .name = "Fujitsu-Siemens Celsius",      /* AD1981? */
@@ -2037,7 +2036,6 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, const
        if ((err = snd_ac97_bus(chip->card, 0, ops, chip, &pbus)) < 0)
                goto __err;
        pbus->private_free = snd_intel8x0_mixer_free_ac97_bus;
-       pbus->shared_type = AC97_SHARED_TYPE_ICH;       /* shared with modem driver */
        if (ac97_clock >= 8000 && ac97_clock <= 48000)
                pbus->clock = ac97_clock;
        /* FIXME: my test board doesn't work well with VRA... */
@@ -2146,14 +2144,13 @@ static void do_ali_reset(intel8x0_t *chip)
        iputdword(chip, ICHREG(ALI_FIFOCR2), 0x83838383);
        iputdword(chip, ICHREG(ALI_FIFOCR3), 0x83838383);
        iputdword(chip, ICHREG(ALI_INTERFACECR),
-                 ICH_ALI_IF_MC|ICH_ALI_IF_PI|ICH_ALI_IF_PO);
+                 ICH_ALI_IF_PI|ICH_ALI_IF_PO);
        iputdword(chip, ICHREG(ALI_INTERRUPTCR), 0x00000000);
        iputdword(chip, ICHREG(ALI_INTERRUPTSR), 0x00000000);
 }
 
 #define do_delay(chip) do {\
-       set_current_state(TASK_UNINTERRUPTIBLE);\
-       schedule_timeout(1);\
+       schedule_timeout_uninterruptible(1);\
 } while (0)
 
 static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing)
@@ -2181,7 +2178,7 @@ static int snd_intel8x0_ich_chip_init(intel8x0_t *chip, int probing)
                        goto __ok;
                do_delay(chip);
        } while (time_after_eq(end_time, jiffies));
-       snd_printk("AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT)));
+       snd_printk(KERN_ERR "AC'97 warm reset still in progress? [0x%x]\n", igetdword(chip, ICHREG(GLOB_CNT)));
        return -EIO;
 
       __ok:
@@ -2373,6 +2370,11 @@ static int intel8x0_suspend(snd_card_t *card, pm_message_t state)
        for (i = 0; i < 3; i++)
                if (chip->ac97[i])
                        snd_ac97_suspend(chip->ac97[i]);
+       if (chip->device_type == DEVICE_INTEL_ICH4)
+               chip->sdm_saved = igetbyte(chip, ICHREG(SDM));
+
+       if (chip->irq >= 0)
+               free_irq(chip->irq, (void *)chip);
        pci_disable_device(chip->pci);
        return 0;
 }
@@ -2384,7 +2386,19 @@ static int intel8x0_resume(snd_card_t *card)
 
        pci_enable_device(chip->pci);
        pci_set_master(chip->pci);
-       snd_intel8x0_chip_init(chip, 0);
+       request_irq(chip->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip);
+       synchronize_irq(chip->irq);
+       snd_intel8x0_chip_init(chip, 1);
+
+       /* re-initialize mixer stuff */
+       if (chip->device_type == DEVICE_INTEL_ICH4) {
+               /* enable separate SDINs for ICH4 */
+               iputbyte(chip, ICHREG(SDM), chip->sdm_saved);
+               /* use slot 10/11 for SPDIF */
+               iputdword(chip, ICHREG(GLOB_CNT),
+                         (igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK) |
+                         ICH_PCM_SPDIF_1011);
+       }
 
        /* refill nocache */
        if (chip->fix_nocache)
@@ -2406,6 +2420,20 @@ static int intel8x0_resume(snd_card_t *card)
                }
        }
 
+       /* resume status */
+       for (i = 0; i < chip->bdbars_count; i++) {
+               ichdev_t *ichdev = &chip->ichd[i];
+               unsigned long port = ichdev->reg_offset;
+               if (! ichdev->substream || ! ichdev->suspended)
+                       continue;
+               if (ichdev->ichd == ICHD_PCMOUT)
+                       snd_intel8x0_setup_pcm_out(chip, ichdev->substream->runtime);
+               iputdword(chip, port + ICH_REG_OFF_BDBAR, ichdev->bdbar_addr);
+               iputbyte(chip, port + ICH_REG_OFF_LVI, ichdev->lvi);
+               iputbyte(chip, port + ICH_REG_OFF_CIV, ichdev->civ);
+               iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
+       }
+
        return 0;
 }
 #endif /* CONFIG_PM */
@@ -2425,7 +2453,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
 
        subs = chip->pcm[0]->streams[0].substream;
        if (! subs || subs->dma_buffer.bytes < INTEL8X0_TESTBUF_SIZE) {
-               snd_printk("no playback buffer allocated - aborting measure ac97 clock\n");
+               snd_printk(KERN_WARNING "no playback buffer allocated - aborting measure ac97 clock\n");
                return;
        }
        ichdev = &chip->ichd[ICHD_PCMOUT];
@@ -2451,8 +2479,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
        }
        do_gettimeofday(&start_time);
        spin_unlock_irq(&chip->reg_lock);
-       set_current_state(TASK_UNINTERRUPTIBLE);
-       schedule_timeout(HZ / 20);
+       msleep(50);
        spin_lock_irq(&chip->reg_lock);
        /* check the position */
        pos = ichdev->fragsize1;
@@ -2462,7 +2489,7 @@ static void __devinit intel8x0_measure_ac97_clock(intel8x0_t *chip)
        do_gettimeofday(&stop_time);
        /* stop */
        if (chip->device_type == DEVICE_ALI) {
-               iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 8));
+               iputdword(chip, ICHREG(ALI_DMACR), 1 << (ichdev->ali_slot + 16));
                iputbyte(chip, port + ICH_REG_OFF_CR, 0);
                while (igetbyte(chip, port + ICH_REG_OFF_CR))
                        ;
@@ -2588,7 +2615,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
        if ((err = pci_enable_device(pci)) < 0)
                return err;
 
-       chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+       chip = kzalloc(sizeof(*chip), GFP_KERNEL);
        if (chip == NULL) {
                pci_disable_device(pci);
                return -ENOMEM;
@@ -2599,16 +2626,16 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
        chip->pci = pci;
        chip->irq = -1;
 
+       /* module parameters */
+       chip->buggy_irq = buggy_irq;
+       chip->buggy_semaphore = buggy_semaphore;
+       if (xbox)
+               chip->xbox = 1;
+
        if (pci->vendor == PCI_VENDOR_ID_INTEL &&
            pci->device == PCI_DEVICE_ID_INTEL_440MX)
                chip->fix_nocache = 1; /* enable workaround */
 
-       /* some Nforce[2] and ICH boards have problems with IRQ handling.
-        * Needs to return IRQ_HANDLED for unknown irqs.
-        */
-       if (device_type == DEVICE_NFORCE)
-               chip->buggy_irq = 1;
-
        if ((err = pci_request_regions(pci, card->shortname)) < 0) {
                kfree(chip);
                pci_disable_device(pci);
@@ -2627,7 +2654,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
                chip->remap_addr = ioremap_nocache(chip->addr,
                                                   pci_resource_len(pci, 2));
                if (chip->remap_addr == NULL) {
-                       snd_printk("AC'97 space ioremap problem\n");
+                       snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
                        snd_intel8x0_free(chip);
                        return -EIO;
                }
@@ -2640,7 +2667,7 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
                chip->remap_bmaddr = ioremap_nocache(chip->bmaddr,
                                                     pci_resource_len(pci, 3));
                if (chip->remap_bmaddr == NULL) {
-                       snd_printk("Controller space ioremap problem\n");
+                       snd_printk(KERN_ERR "Controller space ioremap problem\n");
                        snd_intel8x0_free(chip);
                        return -EIO;
                }
@@ -2649,15 +2676,6 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
        }
 
  port_inited:
-       if (request_irq(pci->irq, snd_intel8x0_interrupt, SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
-               snd_printk("unable to grab IRQ %d\n", pci->irq);
-               snd_intel8x0_free(chip);
-               return -EBUSY;
-       }
-       chip->irq = pci->irq;
-       pci_set_master(pci);
-       synchronize_irq(chip->irq);
-
        chip->bdbars_count = bdbars[device_type];
 
        /* initialize offsets */
@@ -2708,13 +2726,27 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
        int_sta_masks = 0;
        for (i = 0; i < chip->bdbars_count; i++) {
                ichdev = &chip->ichd[i];
-               ichdev->bdbar = ((u32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2);
-               ichdev->bdbar_addr = chip->bdbars.addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
+               ichdev->bdbar = ((u32 *)chip->bdbars.area) +
+                       (i * ICH_MAX_FRAGS * 2);
+               ichdev->bdbar_addr = chip->bdbars.addr +
+                       (i * sizeof(u32) * ICH_MAX_FRAGS * 2);
                int_sta_masks |= ichdev->int_sta_mask;
        }
-       chip->int_sta_reg = device_type == DEVICE_ALI ? ICH_REG_ALI_INTERRUPTSR : ICH_REG_GLOB_STA;
+       chip->int_sta_reg = device_type == DEVICE_ALI ?
+               ICH_REG_ALI_INTERRUPTSR : ICH_REG_GLOB_STA;
        chip->int_sta_mask = int_sta_masks;
 
+       /* request irq after initializaing int_sta_mask, etc */
+       if (request_irq(pci->irq, snd_intel8x0_interrupt,
+                       SA_INTERRUPT|SA_SHIRQ, card->shortname, (void *)chip)) {
+               snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+               snd_intel8x0_free(chip);
+               return -EBUSY;
+       }
+       chip->irq = pci->irq;
+       pci_set_master(pci);
+       synchronize_irq(chip->irq);
+
        if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) {
                snd_intel8x0_free(chip);
                return err;
@@ -2737,19 +2769,19 @@ static struct shortname_table {
        unsigned int id;
        const char *s;
 } shortnames[] __devinitdata = {
-       { PCI_DEVICE_ID_INTEL_82801, "Intel 82801AA-ICH" },
-       { PCI_DEVICE_ID_INTEL_82901, "Intel 82901AB-ICH0" },
-       { PCI_DEVICE_ID_INTEL_82801BA, "Intel 82801BA-ICH2" },
+       { PCI_DEVICE_ID_INTEL_82801AA_5, "Intel 82801AA-ICH" },
+       { PCI_DEVICE_ID_INTEL_82801AB_5, "Intel 82901AB-ICH0" },
+       { PCI_DEVICE_ID_INTEL_82801BA_4, "Intel 82801BA-ICH2" },
        { PCI_DEVICE_ID_INTEL_440MX, "Intel 440MX" },
-       { PCI_DEVICE_ID_INTEL_ICH3, "Intel 82801CA-ICH3" },
-       { PCI_DEVICE_ID_INTEL_ICH4, "Intel 82801DB-ICH4" },
-       { PCI_DEVICE_ID_INTEL_ICH5, "Intel ICH5" },
+       { PCI_DEVICE_ID_INTEL_82801CA_5, "Intel 82801CA-ICH3" },
+       { PCI_DEVICE_ID_INTEL_82801DB_5, "Intel 82801DB-ICH4" },
+       { PCI_DEVICE_ID_INTEL_82801EB_5, "Intel ICH5" },
        { PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" },
        { PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" },
        { PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" },
        { PCI_DEVICE_ID_INTEL_ESB2_14, "Intel ESB2" },
        { PCI_DEVICE_ID_SI_7012, "SiS SI7012" },
-       { PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
+       { PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO, "NVidia nForce" },
        { PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO, "NVidia nForce2" },
        { PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO, "NVidia nForce3" },
        { PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO, "NVidia CK8S" },
@@ -2765,20 +2797,12 @@ static struct shortname_table {
 static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
                                        const struct pci_device_id *pci_id)
 {
-       static int dev;
        snd_card_t *card;
        intel8x0_t *chip;
        int err;
        struct shortname_table *name;
 
-       if (dev >= SNDRV_CARDS)
-               return -ENODEV;
-       if (!enable[dev]) {
-               dev++;
-               return -ENOENT;
-       }
-
-       card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+       card = snd_card_new(index, id, THIS_MODULE, 0);
        if (card == NULL)
                return -ENOMEM;
 
@@ -2802,16 +2826,23 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
                }
        }
 
-       if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data, &chip)) < 0) {
+       if (buggy_irq < 0) {
+               /* some Nforce[2] and ICH boards have problems with IRQ handling.
+                * Needs to return IRQ_HANDLED for unknown irqs.
+                */
+               if (pci_id->driver_data == DEVICE_NFORCE)
+                       buggy_irq = 1;
+               else
+                       buggy_irq = 0;
+       }
+
+       if ((err = snd_intel8x0_create(card, pci, pci_id->driver_data,
+                                      &chip)) < 0) {
                snd_card_free(card);
                return err;
        }
-       if (buggy_irq[dev])
-               chip->buggy_irq = 1;
-       if (xbox[dev])
-               chip->xbox = 1;
 
-       if ((err = snd_intel8x0_mixer(chip, ac97_clock[dev], ac97_quirk[dev])) < 0) {
+       if ((err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk)) < 0) {
                snd_card_free(card);
                return err;
        }
@@ -2826,7 +2857,7 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
                 "%s with %s at %#lx, irq %i", card->shortname,
                 snd_ac97_get_short_name(chip->ac97[0]), chip->addr, chip->irq);
 
-       if (! ac97_clock[dev])
+       if (! ac97_clock)
                intel8x0_measure_ac97_clock(chip);
 
        if ((err = snd_card_register(card)) < 0) {
@@ -2834,7 +2865,6 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
                return err;
        }
        pci_set_drvdata(pci, card);
-       dev++;
        return 0;
 }
 
@@ -2846,6 +2876,7 @@ static void __devexit snd_intel8x0_remove(struct pci_dev *pci)
 
 static struct pci_driver driver = {
        .name = "Intel ICH",
+       .owner = THIS_MODULE,
        .id_table = snd_intel8x0_ids,
        .probe = snd_intel8x0_probe,
        .remove = __devexit_p(snd_intel8x0_remove),