X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fpci%2Fnm256%2Fnm256.c;h=33e0d6b52ad9fbf0ab86252473d15d0a00b2d62d;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=e65e7de31f263008f73eeadc20bdd974dc8d03e3;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index e65e7de31..33e0d6b52 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c @@ -61,26 +61,28 @@ static int force_ac97[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disable static int buffer_top[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* not specified */ static int use_cache[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */ static int vaio_hack[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */ -static int boot_devs; +static int reset_workaround[SNDRV_CARDS]; -module_param_array(index, int, boot_devs, 0444); +module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); -module_param_array(id, charp, boot_devs, 0444); +module_param_array(id, charp, NULL, 0444); MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); -module_param_array(enable, bool, boot_devs, 0444); +module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable this soundcard."); -module_param_array(playback_bufsize, int, boot_devs, 0444); +module_param_array(playback_bufsize, int, NULL, 0444); MODULE_PARM_DESC(playback_bufsize, "DAC frame size in kB for " CARD_NAME " soundcard."); -module_param_array(capture_bufsize, int, boot_devs, 0444); +module_param_array(capture_bufsize, int, NULL, 0444); MODULE_PARM_DESC(capture_bufsize, "ADC frame size in kB for " CARD_NAME " soundcard."); -module_param_array(force_ac97, bool, boot_devs, 0444); +module_param_array(force_ac97, bool, NULL, 0444); MODULE_PARM_DESC(force_ac97, "Force to use AC97 codec for " CARD_NAME " soundcard."); -module_param_array(buffer_top, int, boot_devs, 0444); +module_param_array(buffer_top, int, NULL, 0444); MODULE_PARM_DESC(buffer_top, "Set the top address of audio buffer for " CARD_NAME " soundcard."); -module_param_array(use_cache, bool, boot_devs, 0444); +module_param_array(use_cache, bool, NULL, 0444); MODULE_PARM_DESC(use_cache, "Enable the cache for coefficient table access."); -module_param_array(vaio_hack, bool, boot_devs, 0444); +module_param_array(vaio_hack, bool, NULL, 0444); MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks."); +module_param_array(reset_workaround, bool, NULL, 0444); +MODULE_PARM_DESC(reset_workaround, "Enable AC97 RESET workaround for some laptops."); /* * hw definitions @@ -190,7 +192,7 @@ struct snd_nm256_stream { u32 buf; /* offset from chip->buffer */ int bufsize; /* buffer size in bytes */ - unsigned long bufptr; /* mapped pointer */ + void __iomem *bufptr; /* mapped pointer */ unsigned long bufptr_addr; /* physical address of the mapped pointer */ int dma_size; /* buffer size of the substream in bytes */ @@ -205,11 +207,11 @@ struct snd_nm256 { snd_card_t *card; - unsigned long cport; /* control port */ + void __iomem *cport; /* control port */ struct resource *res_cport; /* its resource */ unsigned long cport_addr; /* physical address */ - unsigned long buffer; /* buffer */ + void __iomem *buffer; /* buffer */ struct resource *res_buffer; /* its resource */ unsigned long buffer_addr; /* buffer phyiscal address */ @@ -222,7 +224,7 @@ struct snd_nm256 { unsigned int coeffs_current: 1; /* coeff. table is loaded? */ unsigned int use_cache: 1; /* use one big coef. table */ - unsigned int latitude_workaround: 1; /* Dell Latitude LS workaround needed */ + unsigned int reset_workaround: 1; /* Workaround for some laptops to avoid freeze */ int mixer_base; /* register offset of ac97 mixer */ int mixer_status_offset; /* offset of mixer status reg. */ @@ -329,7 +331,7 @@ snd_nm256_write_buffer(nm256_t *chip, void *src, int offset, int size) return; } #endif - memcpy_toio((void *)chip->buffer + offset, src, size); + memcpy_toio(chip->buffer + offset, src, size); } /* @@ -887,8 +889,8 @@ snd_nm256_pcm(nm256_t *chip, int device) for (i = 0; i < 2; i++) { nm256_stream_t *s = &chip->streams[i]; - s->bufptr = chip->buffer + s->buf - chip->buffer_start; - s->bufptr_addr = chip->buffer_addr + s->buf - chip->buffer_start; + s->bufptr = chip->buffer + (s->buf - chip->buffer_start); + s->bufptr_addr = chip->buffer_addr + (s->buf - chip->buffer_start); } err = snd_pcm_new(chip->card, chip->card->driver, device, @@ -1128,7 +1130,7 @@ snd_nm256_ac97_read(ac97_t *ac97, unsigned short reg) return 0; res = snd_nm256_readw(chip, chip->mixer_base + reg); /* Magic delay. Bleah yucky. */ - udelay(1000); + msleep(1); return res; } @@ -1149,7 +1151,7 @@ snd_nm256_ac97_write(ac97_t *ac97, /* Wait for the write to take, too. */ while (tries-- > 0) { snd_nm256_writew(chip, base + reg, val); - udelay(1000); /* a little delay here seems better.. */ + msleep(1); /* a little delay here seems better.. */ if (snd_nm256_ac97_ready(chip)) return; } @@ -1162,16 +1164,14 @@ snd_nm256_ac97_reset(ac97_t *ac97) { nm256_t *chip = ac97->private_data; - spin_lock(&chip->reg_lock); /* Reset the mixer. 'Tis magic! */ snd_nm256_writeb(chip, 0x6c0, 1); - if (chip->latitude_workaround) { + if (! chip->reset_workaround) { /* Dell latitude LS will lock up by this */ snd_nm256_writeb(chip, 0x6cc, 0x87); } snd_nm256_writeb(chip, 0x6cc, 0x80); snd_nm256_writeb(chip, 0x6cc, 0x0); - spin_unlock(&chip->reg_lock); } /* create an ac97 mixer interface */ @@ -1226,13 +1226,13 @@ static int __devinit snd_nm256_peek_for_sig(nm256_t *chip) { /* The signature is located 1K below the end of video RAM. */ - unsigned long temp; + void __iomem *temp; /* Default buffer end is 5120 bytes below the top of RAM. */ unsigned long pointer_found = chip->buffer_end - 0x1400; u32 sig; - temp = (unsigned long) ioremap_nocache(chip->buffer_addr + chip->buffer_end - 0x400, 16); - if (temp == 0) { + temp = ioremap_nocache(chip->buffer_addr + chip->buffer_end - 0x400, 16); + if (temp == NULL) { snd_printk("Unable to scan for card signature in video RAM\n"); return -EBUSY; } @@ -1248,7 +1248,7 @@ snd_nm256_peek_for_sig(nm256_t *chip) pointer < chip->buffer_size || pointer > chip->buffer_end) { snd_printk("invalid signature found: 0x%x\n", pointer); - iounmap((void *)temp); + iounmap(temp); return -ENODEV; } else { pointer_found = pointer; @@ -1256,7 +1256,7 @@ snd_nm256_peek_for_sig(nm256_t *chip) } } - iounmap((void *)temp); + iounmap(temp); chip->buffer_end = pointer_found; return 0; @@ -1274,7 +1274,7 @@ static int nm256_suspend(snd_card_t *card, unsigned int state) snd_pcm_suspend_all(chip->pcm); snd_ac97_suspend(chip->ac97); chip->coeffs_current = 0; - snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); + pci_disable_device(chip->pci); return 0; } @@ -1289,7 +1289,6 @@ static int nm256_resume(snd_card_t *card, unsigned int state) /* restore ac97 */ snd_ac97_resume(chip->ac97); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; } #endif /* CONFIG_PM */ @@ -1305,9 +1304,9 @@ static int snd_nm256_free(nm256_t *chip) synchronize_irq(chip->irq); if (chip->cport) - iounmap((void *) chip->cport); + iounmap(chip->cport); if (chip->buffer) - iounmap((void *) chip->buffer); + iounmap(chip->buffer); if (chip->res_cport) { release_resource(chip->res_cport); kfree_nocheck(chip->res_cport); @@ -1319,6 +1318,7 @@ static int snd_nm256_free(nm256_t *chip) if (chip->irq >= 0) free_irq(chip->irq, (void*)chip); + pci_disable_device(chip->pci); kfree(chip); return 0; } @@ -1343,13 +1343,17 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, .dev_free = snd_nm256_dev_free, }; u32 addr; - u16 subsystem_vendor, subsystem_device; *chip_ret = NULL; + if ((err = pci_enable_device(pci)) < 0) + return err; + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) + if (chip == NULL) { + pci_disable_device(pci); return -ENOMEM; + } chip->card = card; chip->pci = pci; @@ -1380,8 +1384,8 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, err = -EBUSY; goto __error; } - chip->cport = (unsigned long) ioremap_nocache(chip->cport_addr, NM_PORT2_SIZE); - if (chip->cport == 0) { + chip->cport = ioremap_nocache(chip->cport_addr, NM_PORT2_SIZE); + if (chip->cport == NULL) { snd_printk("unable to map control port %lx\n", chip->cport_addr); err = -ENOMEM; goto __error; @@ -1445,8 +1449,8 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, err = -EBUSY; goto __error; } - chip->buffer = (unsigned long) ioremap_nocache(chip->buffer_addr, chip->buffer_size); - if (chip->buffer == 0) { + chip->buffer = ioremap_nocache(chip->buffer_addr, chip->buffer_size); + if (chip->buffer == NULL) { err = -ENOMEM; snd_printk("unable to map ring buffer at %lx\n", chip->buffer_addr); goto __error; @@ -1480,27 +1484,8 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, chip->coeffs_current = 0; - /* check workarounds */ - chip->latitude_workaround = 1; - pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); - pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device); - if (subsystem_vendor == 0x104d && subsystem_device == 0x8041) { - /* this workaround will cause lock-up after suspend/resume on Sony PCG-F305 */ - chip->latitude_workaround = 0; - } - if (subsystem_vendor == 0x1028 && subsystem_device == 0x0080) { - /* this workaround will cause lock-up after suspend/resume on a Dell laptop */ - chip->latitude_workaround = 0; - } - snd_nm256_init_chip(chip); - if ((err = snd_nm256_pcm(chip, 0)) < 0) - goto __error; - - if ((err = snd_nm256_mixer(chip)) < 0) - goto __error; - // pci_set_master(pci); /* needed? */ snd_card_set_pm_callback(card, nm256_suspend, nm256_resume, chip); @@ -1525,11 +1510,15 @@ struct nm256_quirk { int type; }; -#define NM_BLACKLISTED 1 +enum { NM_BLACKLISTED, NM_RESET_WORKAROUND }; static struct nm256_quirk nm256_quirks[] __devinitdata = { /* HP omnibook 4150 has cs4232 codec internally */ { .vendor = 0x103c, .device = 0x0007, .type = NM_BLACKLISTED }, + /* Sony PCG-F305 */ + { .vendor = 0x104d, .device = 0x8041, .type = NM_RESET_WORKAROUND }, + /* Dell Latitude LS */ + { .vendor = 0x1028, .device = 0x0080, .type = NM_RESET_WORKAROUND }, { } /* terminator */ }; @@ -1545,9 +1534,6 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, struct nm256_quirk *q; u16 subsystem_vendor, subsystem_device; - if ((err = pci_enable_device(pci)) < 0) - return err; - if (dev >= SNDRV_CARDS) return -ENODEV; if (!enable[dev]) { @@ -1560,9 +1546,13 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, for (q = nm256_quirks; q->vendor; q++) { if (q->vendor == subsystem_vendor && q->device == subsystem_device) { - if (q->type == NM_BLACKLISTED) { + switch (q->type) { + case NM_BLACKLISTED: printk(KERN_INFO "nm256: The device is blacklisted. Loading stopped\n"); return -ENODEV; + case NM_RESET_WORKAROUND: + reset_workaround[dev] = 1; + break; } } } @@ -1611,6 +1601,17 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, return err; } + if (reset_workaround[dev]) { + snd_printdd(KERN_INFO "nm256: reset_workaround activated\n"); + chip->reset_workaround = 1; + } + + if ((err = snd_nm256_pcm(chip, 0)) < 0 || + (err = snd_nm256_mixer(chip)) < 0) { + snd_card_free(card); + return err; + } + sprintf(card->shortname, "NeoMagic %s", card->driver); sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %d", card->shortname,