Skip to content

Commit

Permalink
ALSA: intel8x0: implement ac97_clock whitelist
Browse files Browse the repository at this point in the history
The AC97 clock detection is not accurate in some cases. This patch adds
an initial whitelist for audio devices gathered from RedHat's bugzilla:

https://bugzilla.redhat.com/show_bug.cgi?id=441087

As a side effect, white-listing might speedup kernel booting (AC97 clock
measuring code is not activated).

Signed-off-by: Jaroslav Kysela <perex@perex.cz>
  • Loading branch information
Jaroslav Kysela committed Aug 29, 2008
1 parent d886e87 commit 2b3b548
Showing 1 changed file with 41 additions and 3 deletions.
44 changes: 41 additions & 3 deletions sound/pci/intel8x0.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
module_param(id, charp, 0444);
MODULE_PARM_DESC(id, "ID string for Intel i8x0 soundcard.");
module_param(ac97_clock, int, 0444);
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = whitelist + auto-detect, 1 = force autodetect).");
module_param(ac97_quirk, charp, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
module_param(buggy_semaphore, bool, 0444);
Expand Down Expand Up @@ -2692,6 +2692,38 @@ static void __devinit intel8x0_measure_ac97_clock(struct intel8x0 *chip)
snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0);
}

struct intel8x0_clock_list {
unsigned short subvendor;
unsigned short subdevice;
unsigned int rate;
};

static struct intel8x0_clock_list intel8x0_clock_list[] __devinitdata = {
{ 0x0e11, 0x008a, 41000 }, /* Analog Devices AD1885 */
{ 0x1028, 0x00be, 44100 }, /* Analog Devices AD1885 */
{ 0x1028, 0x0177, 48000 }, /* Analog Devices AD1980 */
{ 0x1043, 0x80f3, 48000 }, /* Analog Devices AD1985 */
{ 0x0000, 0x0000, 00000 } /* terminator */
};

static int __devinit intel8x0_in_clock_list(struct intel8x0 *chip)
{
struct pci_dev *pci = chip->pci;
struct intel8x0_clock_list *wl;

for (wl = intel8x0_clock_list; wl->subvendor; wl++) {
if (wl->subvendor == pci->subsystem_vendor &&
wl->subdevice == pci->subsystem_device) {
printk(KERN_INFO "intel8x0: white list rate for %04x:%04x is %i\n",
pci->subsystem_vendor,
pci->subsystem_device, wl->rate);
chip->ac97_bus->clock = wl->rate;
return 1;
}
}
return 0;
}

#ifdef CONFIG_PROC_FS
static void snd_intel8x0_proc_read(struct snd_info_entry * entry,
struct snd_info_buffer *buffer)
Expand Down Expand Up @@ -3087,8 +3119,14 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
"%s with %s at irq %i", card->shortname,
snd_ac97_get_short_name(chip->ac97[0]), chip->irq);

if (! ac97_clock)
intel8x0_measure_ac97_clock(chip);
if (ac97_clock == 0 || ac97_clock == 1) {
if (ac97_clock == 0) {
if (intel8x0_in_clock_list(chip) == 0)
intel8x0_measure_ac97_clock(chip);
} else {
intel8x0_measure_ac97_clock(chip);
}
}

if ((err = snd_card_register(card)) < 0) {
snd_card_free(card);
Expand Down

0 comments on commit 2b3b548

Please sign in to comment.