Commit fe9b76ef authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] [ac97 core] added AC97_SCAP_DETECT_BY_VENDOR flag

AC97 Codec Core,Intel8x0 driver
This patch adds a AC97_SCAP_DETECT_BY_VENDOR flag for Xbox. If the flag
is set, the AC97 codec is detected only by reading of a reasonable
vendor ID. It seems that Xbox has accessible only vendor/device ID
registers for reading. Also, a new xbox parameter for snd-intel8x0
has been introduced to let user force this behaviour.
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent 8214d5f8
......@@ -355,6 +355,7 @@
#define AC97_SCAP_SKIP_MODEM (1<<5) /* skip modem part of codec */
#define AC97_SCAP_INDEP_SDIN (1<<6) /* independent SDIN */
#define AC97_SCAP_INV_EAPD (1<<7) /* inverted EAPD */
#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */
/* ac97->flags */
#define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */
......
......@@ -1766,9 +1766,10 @@ void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
{
unsigned long end_time;
unsigned short val;
end_time = jiffies + timeout;
do {
unsigned short ext_mid;
/* use preliminary reads to settle the communication */
snd_ac97_read(ac97, AC97_RESET);
......@@ -1776,17 +1777,24 @@ static int ac97_reset_wait(ac97_t *ac97, int timeout, int with_modem)
snd_ac97_read(ac97, AC97_VENDOR_ID2);
/* modem? */
if (with_modem) {
ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
if (ext_mid != 0xffff && (ext_mid & 1) != 0)
val = snd_ac97_read(ac97, AC97_EXTENDED_MID);
if (val != 0xffff && (val & 1) != 0)
return 0;
}
if (ac97->scaps & AC97_SCAP_DETECT_BY_VENDOR) {
/* probably only Xbox issue - all registers are read as zero */
val = snd_ac97_read(ac97, AC97_VENDOR_ID1);
if (val != 0 && val != 0xffff)
return 0;
} else {
/* because the PCM or MASTER volume registers can be modified,
* the REC_GAIN register is used for tests
*/
/* test if we can write to the record gain volume register */
snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
if ((snd_ac97_read(ac97, AC97_REC_GAIN) & 0x7fff) == 0x0a05)
return 0;
}
/* because the PCM or MASTER volume registers can be modified,
* the REC_GAIN register is used for tests
*/
/* test if we can write to the record gain volume register */
snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
if ((snd_ac97_read(ac97, AC97_REC_GAIN) & 0x7fff) == 0x0a05)
return 0;
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(1);
} while (time_after_eq(end_time, jiffies));
......
......@@ -68,6 +68,7 @@ static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card *
static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
static int ac97_quirk[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = AC97_TUNE_DEFAULT};
static int buggy_irq[SNDRV_CARDS];
static int xbox[SNDRV_CARDS];
static int boot_devs;
module_param_array(index, int, boot_devs, 0444);
......@@ -82,6 +83,8 @@ module_param_array(ac97_quirk, int, boot_devs, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
module_param_array(buggy_irq, bool, boot_devs, 0444);
MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
module_param_array(xbox, bool, boot_devs, 0444);
MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
/*
* Direct registers
......@@ -405,6 +408,7 @@ struct _snd_intel8x0 {
in_sdin_init: 1;
int fix_nocache: 1; /* workaround for 440MX */
int buggy_irq: 1; /* workaround for buggy mobos */
int xbox: 1; /* workaround for Xbox AC'97 detection */
ac97_bus_t *ac97_bus;
ac97_t *ac97[3];
......@@ -1907,6 +1911,8 @@ static int __devinit snd_intel8x0_mixer(intel8x0_t *chip, int ac97_clock, int ac
ac97.private_data = chip;
ac97.private_free = snd_intel8x0_mixer_free_ac97;
ac97.scaps = AC97_SCAP_SKIP_MODEM;
if (chip->xbox)
ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR;
if (chip->device_type != DEVICE_ALI) {
glob_sta = igetdword(chip, ICHREG(GLOB_STA));
ops = &standard_bus_ops;
......@@ -2691,6 +2697,8 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
}
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) {
snd_card_free(card);
......
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