Commit ac3ae21b authored by Jaroslav Kysela's avatar Jaroslav Kysela Committed by Linus Torvalds

ALSA CVS update - Clemens Ladisch <clemens@ladisch.de>

AC97 Codec Core
don't clobber other bits in SERIAL_CFG register with AD codecs when changing codec selection bits
parent 6d95ddce
...@@ -396,11 +396,14 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho ...@@ -396,11 +396,14 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned sho
ac97->spec.ad18xx.pcmreg[codec] = new; ac97->spec.ad18xx.pcmreg[codec] = new;
spin_unlock(&ac97->reg_lock); spin_unlock(&ac97->reg_lock);
/* select single codec */ /* select single codec */
ac97->bus->write(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); ac97->bus->write(ac97, AC97_AD_SERIAL_CFG,
(ac97->regs[AC97_AD_SERIAL_CFG] & ~0x7000) |
ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
/* update PCM bits */ /* update PCM bits */
ac97->bus->write(ac97, AC97_PCM, new); ac97->bus->write(ac97, AC97_PCM, new);
/* select all codecs */ /* select all codecs */
ac97->bus->write(ac97, AC97_AD_SERIAL_CFG, 0x7000); ac97->bus->write(ac97, AC97_AD_SERIAL_CFG,
ac97->regs[AC97_AD_SERIAL_CFG] | 0x7000);
} else } else
spin_unlock(&ac97->reg_lock); spin_unlock(&ac97->reg_lock);
up(&ac97->spec.ad18xx.mutex); up(&ac97->spec.ad18xx.mutex);
...@@ -2032,11 +2035,12 @@ void snd_ac97_resume(ac97_t *ac97) ...@@ -2032,11 +2035,12 @@ void snd_ac97_resume(ac97_t *ac97)
if (! ac97->spec.ad18xx.id[codec]) if (! ac97->spec.ad18xx.id[codec])
continue; continue;
/* select single codec */ /* select single codec */
ac97->bus->write(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
ac97->bus->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]); ac97->bus->write(ac97, AC97_AD_CODEC_CFG, ac97->spec.ad18xx.codec_cfg[codec]);
} }
/* select all codecs */ /* select all codecs */
ac97->bus->write(ac97, AC97_AD_SERIAL_CFG, 0x7000); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
} }
/* restore ac97 status */ /* restore ac97 status */
...@@ -2055,12 +2059,13 @@ void snd_ac97_resume(ac97_t *ac97) ...@@ -2055,12 +2059,13 @@ void snd_ac97_resume(ac97_t *ac97)
if (! ac97->spec.ad18xx.id[codec]) if (! ac97->spec.ad18xx.id[codec])
continue; continue;
/* select single codec */ /* select single codec */
ac97->bus->write(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]);
/* update PCM bits */ /* update PCM bits */
ac97->bus->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]); ac97->bus->write(ac97, AC97_PCM, ac97->spec.ad18xx.pcmreg[codec]);
} }
/* select all codecs */ /* select all codecs */
ac97->bus->write(ac97, AC97_AD_SERIAL_CFG, 0x7000); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
continue; continue;
} else if (i == AC97_AD_TEST || } else if (i == AC97_AD_TEST ||
i == AC97_AD_CODEC_CFG || i == AC97_AD_CODEC_CFG ||
......
...@@ -562,8 +562,11 @@ int patch_conexant(ac97_t * ac97) ...@@ -562,8 +562,11 @@ int patch_conexant(ac97_t * ac97)
*/ */
int patch_ad1819(ac97_t * ac97) int patch_ad1819(ac97_t * ac97)
{ {
unsigned short scfg;
// patch for Analog Devices // patch for Analog Devices
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000); /* select all codecs */ scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x7000); /* select all codecs */
return 0; return 0;
} }
...@@ -572,7 +575,7 @@ static unsigned short patch_ad1881_unchained(ac97_t * ac97, int idx, unsigned sh ...@@ -572,7 +575,7 @@ static unsigned short patch_ad1881_unchained(ac97_t * ac97, int idx, unsigned sh
unsigned short val; unsigned short val;
// test for unchained codec // test for unchained codec
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, mask); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, mask);
snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); /* ID0C, ID1C, SDIE = off */ snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0000); /* ID0C, ID1C, SDIE = off */
val = snd_ac97_read(ac97, AC97_VENDOR_ID2); val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
if ((val & 0xff40) != 0x5340) if ((val & 0xff40) != 0x5340)
...@@ -588,7 +591,7 @@ static int patch_ad1881_chained1(ac97_t * ac97, int idx, unsigned short codec_bi ...@@ -588,7 +591,7 @@ static int patch_ad1881_chained1(ac97_t * ac97, int idx, unsigned short codec_bi
static int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 }; static int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
unsigned short val; unsigned short val;
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, cfg_bits[idx]); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, cfg_bits[idx]);
snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004); // SDIE snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0004); // SDIE
val = snd_ac97_read(ac97, AC97_VENDOR_ID2); val = snd_ac97_read(ac97, AC97_VENDOR_ID2);
if ((val & 0xff40) != 0x5340) if ((val & 0xff40) != 0x5340)
...@@ -611,7 +614,8 @@ static void patch_ad1881_chained(ac97_t * ac97, int unchained_idx, int cidx1, in ...@@ -611,7 +614,8 @@ static void patch_ad1881_chained(ac97_t * ac97, int unchained_idx, int cidx1, in
if (cidx1 < 0 && cidx2 < 0) if (cidx1 < 0 && cidx2 < 0)
return; return;
// test for chained codecs // test for chained codecs
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[unchained_idx]); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
ac97->spec.ad18xx.unchained[unchained_idx]);
snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002); // ID1C snd_ac97_write_cache(ac97, AC97_AD_CODEC_CFG, 0x0002); // ID1C
ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002; ac97->spec.ad18xx.codec_cfg[unchained_idx] = 0x0002;
if (cidx1 >= 0) { if (cidx1 >= 0) {
...@@ -634,10 +638,13 @@ int patch_ad1881(ac97_t * ac97) ...@@ -634,10 +638,13 @@ int patch_ad1881(ac97_t * ac97)
// patch for Analog Devices // patch for Analog Devices
unsigned short codecs[3]; unsigned short codecs[3];
unsigned short val;
int idx, num; int idx, num;
init_MUTEX(&ac97->spec.ad18xx.mutex); init_MUTEX(&ac97->spec.ad18xx.mutex);
val = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, val);
codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12)); codecs[0] = patch_ad1881_unchained(ac97, 0, (1<<12));
codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14)); codecs[1] = patch_ad1881_unchained(ac97, 1, (1<<14));
codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13)); codecs[2] = patch_ad1881_unchained(ac97, 2, (1<<13));
...@@ -659,7 +666,7 @@ int patch_ad1881(ac97_t * ac97) ...@@ -659,7 +666,7 @@ int patch_ad1881(ac97_t * ac97)
__end: __end:
/* select all codecs */ /* select all codecs */
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
/* check if only one codec is present */ /* check if only one codec is present */
for (idx = num = 0; idx < 3; idx++) for (idx = num = 0; idx < 3; idx++)
if (ac97->spec.ad18xx.id[idx]) if (ac97->spec.ad18xx.id[idx])
......
...@@ -241,12 +241,13 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff ...@@ -241,12 +241,13 @@ static void snd_ac97_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buff
for (idx = 0; idx < 3; idx++) for (idx = 0; idx < 3; idx++)
if (ac97->spec.ad18xx.id[idx]) { if (ac97->spec.ad18xx.id[idx]) {
/* select single codec */ /* select single codec */
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
snd_ac97_proc_read_main(ac97, buffer, idx); snd_ac97_proc_read_main(ac97, buffer, idx);
snd_iprintf(buffer, "\n\n"); snd_iprintf(buffer, "\n\n");
} }
/* select all codecs */ /* select all codecs */
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
up(&ac97->spec.ad18xx.mutex); up(&ac97->spec.ad18xx.mutex);
snd_iprintf(buffer, "\nAD18XX configuration\n"); snd_iprintf(buffer, "\nAD18XX configuration\n");
...@@ -285,11 +286,12 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry, ...@@ -285,11 +286,12 @@ static void snd_ac97_proc_regs_read(snd_info_entry_t *entry,
for (idx = 0; idx < 3; idx++) for (idx = 0; idx < 3; idx++)
if (ac97->spec.ad18xx.id[idx]) { if (ac97->spec.ad18xx.id[idx]) {
/* select single codec */ /* select single codec */
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000,
ac97->spec.ad18xx.unchained[idx] | ac97->spec.ad18xx.chained[idx]);
snd_ac97_proc_regs_read_main(ac97, buffer, idx); snd_ac97_proc_regs_read_main(ac97, buffer, idx);
} }
/* select all codecs */ /* select all codecs */
snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, 0x7000); snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
up(&ac97->spec.ad18xx.mutex); up(&ac97->spec.ad18xx.mutex);
} else { } else {
snd_ac97_proc_regs_read_main(ac97, buffer, 0); snd_ac97_proc_regs_read_main(ac97, buffer, 0);
......
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