Commit 9f94a3c8 authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] Add reset_workaround module option

Documentation,NM256 driver
- The workaround for some laptops like Dell Latitude LS can be
  specified via reset_workaround module option, too.
- The check of reset_workaround is merged into the quirk table.
- The spinlock in AC97 reset callback is removed.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 43e80011
...@@ -809,6 +809,7 @@ Module parameters ...@@ -809,6 +809,7 @@ Module parameters
buffer_top - specify buffer top address buffer_top - specify buffer top address
use_cache - 0 or 1 (disabled by default) use_cache - 0 or 1 (disabled by default)
vaio_hack - alias buffer_top=0x25a800 vaio_hack - alias buffer_top=0x25a800
reset_workaround - enable AC97 RESET workaround for some laptops
Module supports autoprobe and multiple chips (max 8). Module supports autoprobe and multiple chips (max 8).
...@@ -834,6 +835,11 @@ Module parameters ...@@ -834,6 +835,11 @@ Module parameters
but some doesn't have ISA PnP. You'll need to speicfy isapnp=0 but some doesn't have ISA PnP. You'll need to speicfy isapnp=0
and proper hardware parameters in the case without ISA PnP. and proper hardware parameters in the case without ISA PnP.
Note: some laptops need a workaround for AC97 RESET. For the
known hardware like Dell Latitude LS and Sony PCG-F305, this
workaround is enabled automatically. For other laptops with a
hard freeze, you can try reset_workaround=1 option.
Note: This driver is really crappy. It's a porting from the Note: This driver is really crappy. It's a porting from the
OSS driver, which is a result of black-magic reverse engineering. OSS driver, which is a result of black-magic reverse engineering.
The detection of codec will fail if the driver is loaded *after* The detection of codec will fail if the driver is loaded *after*
......
...@@ -61,6 +61,7 @@ static int force_ac97[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disable ...@@ -61,6 +61,7 @@ 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 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 use_cache[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */
static int vaio_hack[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */ static int vaio_hack[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0}; /* disabled */
static int reset_workaround[SNDRV_CARDS];
static int boot_devs; static int boot_devs;
module_param_array(index, int, boot_devs, 0444); module_param_array(index, int, boot_devs, 0444);
...@@ -81,6 +82,8 @@ module_param_array(use_cache, bool, boot_devs, 0444); ...@@ -81,6 +82,8 @@ module_param_array(use_cache, bool, boot_devs, 0444);
MODULE_PARM_DESC(use_cache, "Enable the cache for coefficient table access."); 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, boot_devs, 0444);
MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks."); MODULE_PARM_DESC(vaio_hack, "Enable workaround for Sony VAIO notebooks.");
module_param_array(reset_workaround, bool, boot_devs, 0444);
MODULE_PARM_DESC(reset_workaround, "Enable AC97 RESET workaround for some laptops.");
/* /*
* hw definitions * hw definitions
...@@ -222,7 +225,7 @@ struct snd_nm256 { ...@@ -222,7 +225,7 @@ struct snd_nm256 {
unsigned int coeffs_current: 1; /* coeff. table is loaded? */ unsigned int coeffs_current: 1; /* coeff. table is loaded? */
unsigned int use_cache: 1; /* use one big coef. table */ 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_base; /* register offset of ac97 mixer */
int mixer_status_offset; /* offset of mixer status reg. */ int mixer_status_offset; /* offset of mixer status reg. */
...@@ -1162,16 +1165,14 @@ snd_nm256_ac97_reset(ac97_t *ac97) ...@@ -1162,16 +1165,14 @@ snd_nm256_ac97_reset(ac97_t *ac97)
{ {
nm256_t *chip = ac97->private_data; nm256_t *chip = ac97->private_data;
spin_lock(&chip->reg_lock);
/* Reset the mixer. 'Tis magic! */ /* Reset the mixer. 'Tis magic! */
snd_nm256_writeb(chip, 0x6c0, 1); snd_nm256_writeb(chip, 0x6c0, 1);
if (chip->latitude_workaround) { if (! chip->reset_workaround) {
/* Dell latitude LS will lock up by this */ /* Dell latitude LS will lock up by this */
snd_nm256_writeb(chip, 0x6cc, 0x87); snd_nm256_writeb(chip, 0x6cc, 0x87);
} }
snd_nm256_writeb(chip, 0x6cc, 0x80); snd_nm256_writeb(chip, 0x6cc, 0x80);
snd_nm256_writeb(chip, 0x6cc, 0x0); snd_nm256_writeb(chip, 0x6cc, 0x0);
spin_unlock(&chip->reg_lock);
} }
/* create an ac97 mixer interface */ /* create an ac97 mixer interface */
...@@ -1343,7 +1344,6 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, ...@@ -1343,7 +1344,6 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
.dev_free = snd_nm256_dev_free, .dev_free = snd_nm256_dev_free,
}; };
u32 addr; u32 addr;
u16 subsystem_vendor, subsystem_device;
*chip_ret = NULL; *chip_ret = NULL;
...@@ -1480,19 +1480,6 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci, ...@@ -1480,19 +1480,6 @@ snd_nm256_create(snd_card_t *card, struct pci_dev *pci,
chip->coeffs_current = 0; 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); snd_nm256_init_chip(chip);
if ((err = snd_nm256_pcm(chip, 0)) < 0) if ((err = snd_nm256_pcm(chip, 0)) < 0)
...@@ -1525,11 +1512,15 @@ struct nm256_quirk { ...@@ -1525,11 +1512,15 @@ struct nm256_quirk {
int type; int type;
}; };
#define NM_BLACKLISTED 1 enum { NM_BLACKLISTED, NM_RESET_WORKAROUND };
static struct nm256_quirk nm256_quirks[] __devinitdata = { static struct nm256_quirk nm256_quirks[] __devinitdata = {
/* HP omnibook 4150 has cs4232 codec internally */ /* HP omnibook 4150 has cs4232 codec internally */
{ .vendor = 0x103c, .device = 0x0007, .type = NM_BLACKLISTED }, { .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 */ { } /* terminator */
}; };
...@@ -1560,9 +1551,13 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, ...@@ -1560,9 +1551,13 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci,
for (q = nm256_quirks; q->vendor; q++) { for (q = nm256_quirks; q->vendor; q++) {
if (q->vendor == subsystem_vendor && q->device == subsystem_device) { 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"); printk(KERN_INFO "nm256: The device is blacklisted. Loading stopped\n");
return -ENODEV; return -ENODEV;
case NM_RESET_WORKAROUND:
reset_workaround[dev] = 1;
break;
} }
} }
} }
...@@ -1611,6 +1606,11 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci, ...@@ -1611,6 +1606,11 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci,
return err; return err;
} }
if (reset_workaround[dev]) {
snd_printdd(KERN_INFO "nm256: reset_workaround activated\n");
chip->reset_workaround = 1;
}
sprintf(card->shortname, "NeoMagic %s", card->driver); sprintf(card->shortname, "NeoMagic %s", card->driver);
sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %d", sprintf(card->longname, "%s at 0x%lx & 0x%lx, irq %d",
card->shortname, card->shortname,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment