[ALSA] intel8x0 - Fix irq handler registration
[safe/jmp/linux-2.6] / sound / pci / intel8x0.c
index fc2fba8..0801083 100644 (file)
@@ -69,7 +69,7 @@ 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;
+static int buggy_irq = -1; /* auto-check */
 static int xbox;
 
 module_param(index, int, 0444);
@@ -89,7 +89,7 @@ MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 c
 
 /* just for backward compatibility */
 static int enable;
-module_param(enable, int, 0444);
+module_param(enable, bool, 0444);
 static int joystick;
 module_param(joystick, int, 0444);
 
@@ -538,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 */
@@ -553,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);
 }
@@ -567,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);
@@ -575,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;
                }
        }
@@ -1766,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",
@@ -2138,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)
@@ -2173,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:
@@ -2448,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];
@@ -2484,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))
                        ;
@@ -2563,7 +2568,6 @@ struct ich_reg_info {
 static int __devinit snd_intel8x0_create(snd_card_t * card,
                                         struct pci_dev *pci,
                                         unsigned long device_type,
-                                        int buggy_sem,
                                         intel8x0_t ** r_intel8x0)
 {
        intel8x0_t *chip;
@@ -2621,18 +2625,17 @@ static int __devinit snd_intel8x0_create(snd_card_t * card,
        chip->card = card;
        chip->pci = pci;
        chip->irq = -1;
-       chip->buggy_semaphore = buggy_sem;
+
+       /* 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);
@@ -2651,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;
                }
@@ -2664,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;
                }
@@ -2673,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 */
@@ -2732,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;
@@ -2818,15 +2826,21 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
                }
        }
 
+       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,
-                                      buggy_semaphore, &chip)) < 0) {
+                                      &chip)) < 0) {
                snd_card_free(card);
                return err;
        }
-       if (buggy_irq)
-               chip->buggy_irq = 1;
-       if (xbox)
-               chip->xbox = 1;
 
        if ((err = snd_intel8x0_mixer(chip, ac97_clock, ac97_quirk)) < 0) {
                snd_card_free(card);