Update of /cvsroot/alsa/alsa-kernel/pci/ac97 In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25233/ac97
Modified Files: ac97_codec.c ac97_pcm.c Log Message: - fixed the possibl ac97 register cache mismatch. - added the detection of spdif sample rates. Index: ac97_codec.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_codec.c,v retrieving revision 1.125 retrieving revision 1.126 diff -u -r1.125 -r1.126 --- ac97_codec.c 29 Mar 2004 07:05:00 -0000 1.125 +++ ac97_codec.c 4 Apr 2004 16:03:58 -0000 1.126 @@ -299,6 +299,16 @@ return ac97->bus->read(ac97, reg); } +/* read a register - return the cached value if already read */ +static inline unsigned short snd_ac97_read_cache(ac97_t *ac97, unsigned short reg) +{ + if (! test_bit(reg, ac97->reg_accessed)) { + ac97->regs[reg] = ac97->bus->read(ac97, reg); + // set_bit(reg, ac97->reg_accessed); + } + return ac97->regs[reg]; +} + /** * snd_ac97_write_cache - write a value on the given register and update the cache * @ac97: the ac97 instance @@ -370,7 +380,7 @@ if (!snd_ac97_valid_reg(ac97, reg)) return -EINVAL; spin_lock(&ac97->reg_lock); - old = ac97->regs[reg]; + old = snd_ac97_read_cache(ac97, reg); new = (old & ~mask) | value; change = old != new; if (change) { @@ -385,25 +395,26 @@ static int snd_ac97_ad18xx_update_pcm_bits(ac97_t *ac97, int codec, unsigned short mask, unsigned short value) { int change; - unsigned short old, new; + unsigned short old, new, cfg; down(&ac97->spec.ad18xx.mutex); spin_lock(&ac97->reg_lock); old = ac97->spec.ad18xx.pcmreg[codec]; new = (old & ~mask) | value; + cfg = snd_ac97_read_cache(ac97, AC97_AD_SERIAL_CFG); change = old != new; if (change) { ac97->spec.ad18xx.pcmreg[codec] = new; spin_unlock(&ac97->reg_lock); /* select single codec */ ac97->bus->write(ac97, AC97_AD_SERIAL_CFG, - (ac97->regs[AC97_AD_SERIAL_CFG] & ~0x7000) | + (cfg & ~0x7000) | ac97->spec.ad18xx.unchained[codec] | ac97->spec.ad18xx.chained[codec]); /* update PCM bits */ ac97->bus->write(ac97, AC97_PCM, new); /* select all codecs */ ac97->bus->write(ac97, AC97_AD_SERIAL_CFG, - ac97->regs[AC97_AD_SERIAL_CFG] | 0x7000); + cfg | 0x7000); } else spin_unlock(&ac97->reg_lock); up(&ac97->spec.ad18xx.mutex); @@ -435,7 +446,7 @@ ac97_t *ac97 = snd_kcontrol_chip(kcontrol); unsigned short val; - val = ac97->regs[AC97_REC_SEL]; + val = snd_ac97_read_cache(ac97, AC97_REC_SEL); ucontrol->value.enumerated.item[0] = (val >> 8) & 7; ucontrol->value.enumerated.item[1] = (val >> 0) & 7; return 0; @@ -493,7 +504,7 @@ int shift = (kcontrol->private_value >> 8) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - val = (ac97->regs[reg] >> shift) & 1; + val = (snd_ac97_read_cache(ac97, reg) >> shift) & 1; if (invert) val ^= 1; ucontrol->value.enumerated.item[0] = val; @@ -535,7 +546,7 @@ int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - ucontrol->value.integer.value[0] = (ac97->regs[reg] >> shift) & mask; + ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask; if (invert) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; return 0; @@ -582,8 +593,8 @@ int invert = (kcontrol->private_value >> 24) & 0xff; spin_lock(&ac97->reg_lock); - ucontrol->value.integer.value[0] = (ac97->regs[reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (ac97->regs[reg] >> shift_right) & mask; + ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift_left) & mask; + ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> shift_right) & mask; spin_unlock(&ac97->reg_lock); if (invert) { ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; @@ -796,7 +807,7 @@ AC97_CXR_SPDIF_MASK | AC97_CXR_COPYRGT, v); } else { - unsigned short extst = ac97->regs[AC97_EXTENDED_STATUS]; + unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ change |= snd_ac97_update_bits(ac97, AC97_SPDIF, 0x3fff, val); @@ -822,13 +833,13 @@ mask <<= shift; value <<= shift; spin_lock(&ac97->reg_lock); - old = ac97->regs[reg]; + old = snd_ac97_read_cache(ac97, reg); new = (old & ~mask) | value; spin_unlock(&ac97->reg_lock); if (old != new) { int change; - unsigned short extst = ac97->regs[AC97_EXTENDED_STATUS]; + unsigned short extst = snd_ac97_read_cache(ac97, AC97_EXTENDED_STATUS); snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); /* turn off */ change = snd_ac97_update_bits(ac97, reg, mask, value); if (extst & AC97_EA_SPDIF) @@ -1572,6 +1583,26 @@ *r_result = result; } +/* check AC97_SPDIF register to accept which sample rates */ +static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97) +{ + unsigned int result = 0; + int i; + static unsigned short ctl_bits[] = { + AC97_SC_SPSR_44K, AC97_SC_SPSR_32K, AC97_SC_SPSR_48K + }; + static unsigned int rate_bits[] = { + SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_32000, SNDRV_PCM_RATE_48000 + }; + + for (i = 0; i < (int)ARRAY_SIZE(ctl_bits); i++) { + snd_ac97_update_bits(ac97, AC97_SPDIF, AC97_SC_SPSR_MASK, ctl_bits[i]); + if ((snd_ac97_read(ac97, AC97_SPDIF) & AC97_SC_SPSR_MASK) == ctl_bits[i]) + result |= rate_bits[i]; + } + return result; +} + void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem) { const ac97_codec_id_t *pid; @@ -1889,9 +1920,7 @@ else if (ac97->id == AC97_ID_CM9739) ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; else - ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | - SNDRV_PCM_RATE_44100 | - SNDRV_PCM_RATE_32000; + ac97->rates[AC97_RATES_SPDIF] = snd_ac97_determine_spdif_rates(ac97); } if (ac97->ext_id & AC97_EI_VRM) { /* MIC VRA support */ snd_ac97_determine_rates(ac97, AC97_PCM_MIC_ADC_RATE, 0, &ac97->rates[AC97_RATES_MIC_ADC]); Index: ac97_pcm.c =================================================================== RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_pcm.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- ac97_pcm.c 29 Mar 2004 06:58:36 -0000 1.12 +++ ac97_pcm.c 4 Apr 2004 16:03:59 -0000 1.13 @@ -210,7 +210,7 @@ } spin_lock(&ac97->reg_lock); - old = ac97->regs[reg] & mask; + old = snd_ac97_read(ac97, reg) & mask; spin_unlock(&ac97->reg_lock); if (old != bits) { snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS, AC97_EA_SPDIF, 0); ------------------------------------------------------- This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click _______________________________________________ Alsa-cvslog mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/alsa-cvslog