At Tue, 02 Dec 2003 14:57:29 +0100, Thomas Charbonnel wrote: > > Takashi Iwai wrote : > > > ok, then please check /proc/asound/card0/codec97#0/* files whether VRA > > is properly set to 44100Hz during the playback. > > > > > > Takashi > > > > > > Bingo, it seems it's not, indeed :
please try the attached patch. possibly this isn't a fix, but it will print debug messages while probing and opening the pcm. Takashi
Index: alsa-kernel/include/ac97_codec.h =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/include/ac97_codec.h,v retrieving revision 1.35 diff -u -r1.35 ac97_codec.h --- alsa-kernel/include/ac97_codec.h 20 Nov 2003 15:57:50 -0000 1.35 +++ alsa-kernel/include/ac97_codec.h 2 Dec 2003 15:38:37 -0000 @@ -345,7 +345,8 @@ ac97_bus_t *bus; unsigned int stream: 1, /* stream type: 1 = capture */ exclusive: 1, /* exclusive mode, don't override with other pcms */ - copy_flag: 1; /* lowlevel driver must fill all entries */ + copy_flag: 1, /* lowlevel driver must fill all entries */ + spdif: 1; /* spdif pcm */ unsigned short aslots; /* active slots */ unsigned int rates; /* available rates */ struct { Index: alsa-kernel/pci/intel8x0.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/pci/intel8x0.c,v retrieving revision 1.102 diff -u -r1.102 intel8x0.c --- alsa-kernel/pci/intel8x0.c 20 Nov 2003 15:57:50 -0000 1.102 +++ alsa-kernel/pci/intel8x0.c 2 Dec 2003 15:39:03 -0000 @@ -886,6 +886,7 @@ static int snd_intel8x0_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params) { + intel8x0_t *chip = snd_pcm_substream_chip(substream); ichdev_t *ichdev = get_ichdev(substream); int err; @@ -899,8 +900,12 @@ err = snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params), params_channels(hw_params), ichdev->pcm->r[0].slots); - if (err >= 0) + if (err >= 0) { ichdev->pcm_open_flag = 1; + /* FIXME: hack to enable spdif support */ + if (ichdev->ichd == ICHD_PCMOUT && chip->device_type == DEVICE_SIS) + snd_ac97_set_rate(ichdev->pcm->r[0].codec[0], AC97_SPDIF, params_rate(hw_params)); + } return err; } @@ -963,9 +968,6 @@ snd_intel8x0_setup_multi_channels(chip, runtime->channels); spin_unlock(&chip->reg_lock); } - /* FIXME: hack to enable spdif support */ - if (ichdev->ichd == ICHD_PCMOUT && chip->device_type == DEVICE_SIS) - snd_ac97_set_rate(ichdev->pcm->r[0].codec[0], AC97_SPDIF, runtime->rate); snd_intel8x0_setup_periods(chip, ichdev); return 0; } @@ -1590,6 +1592,7 @@ /* S/PDIF PCM */ { .exclusive = 1, + .spdif = 1, .r = { { .slots = (1 << AC97_SLOT_SPDIF_LEFT2) | (1 << AC97_SLOT_SPDIF_RIGHT2) Index: alsa-kernel/pci/ac97/ac97_pcm.c =================================================================== RCS file: /suse/tiwai/cvs/alsa/alsa-kernel/pci/ac97/ac97_pcm.c,v retrieving revision 1.7 diff -u -r1.7 ac97_pcm.c --- alsa-kernel/pci/ac97/ac97_pcm.c 1 Dec 2003 12:52:48 -0000 1.7 +++ alsa-kernel/pci/ac97/ac97_pcm.c 2 Dec 2003 15:44:16 -0000 @@ -165,6 +165,8 @@ return 0xff; if (slot > 11) return 0xff; + if (pcm->spdif) + return AC97_SPDIF; /* pseudo register */ if (pcm->stream == SNDRV_PCM_STREAM_PLAYBACK) return rate_reg_tables[dbl][pcm->r[dbl].rate_table[cidx]][slot - 3]; else @@ -230,6 +232,8 @@ * AC97_PCM_FRONT_DAC_RATE, AC97_PCM_LR_ADC_RATE. * AC97_PCM_SURR_DAC_RATE and AC97_PCM_LFE_DAC_RATE are accepted * if the codec supports them. + * AC97_SPDIF is accepted as a pseudo register to modify the SPDIF + * status bits. * * Returns zero if successful, or a negative error code on failure. */ @@ -257,6 +261,9 @@ if (! (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)) return -EINVAL; break; + case AC97_SPDIF: + /* special case */ + return set_spdif_rate(ac97, rate); default: return -EINVAL; } @@ -350,8 +357,7 @@ if (!ac97_is_audio(ac97)) return 0; slots = (1<<AC97_SLOT_PCM_LEFT)|(1<<AC97_SLOT_PCM_RIGHT); - if (ac97->ext_id & AC97_EI_VRM) - slots |= (1<<AC97_SLOT_MIC); + slots |= (1<<AC97_SLOT_MIC); return slots; } @@ -412,16 +418,19 @@ continue; avail_slots[0][i] = get_pslots(codec, &rate_table[0][i]); avail_slots[1][i] = get_cslots(codec); + printk(KERN_DEBUG "checking codec %d, slots = 0x%x / 0x%x\n", i, avail_slots[0][i], avail_slots[1][i]); if (!(codec->scaps & AC97_SCAP_INDEP_SDIN)) { for (j = 0; j < i; j++) { if (bus->codec[j]) avail_slots[1][i] &= ~avail_slots[1][j]; } + printk(KERN_DEBUG "-> capture slots = 0x%x\n", avail_slots[1][i]); } } /* FIXME: add double rate allocation */ /* first step - exclusive devices */ for (i = 0; i < pcms_count; i++) { + printk(KERN_DEBUG "probing pcm %d\n", i); pcm = &pcms[i]; rpcm = &rpcms[i]; /* low-level driver thinks that it's more clever */ @@ -431,6 +440,7 @@ } rpcm->stream = pcm->stream; rpcm->exclusive = pcm->exclusive; + rpcm->spdif = pcm->spdif; rpcm->private_value = pcm->private_value; rpcm->bus = bus; rpcm->rates = ~0; @@ -438,19 +448,23 @@ for (j = 0; j < 4 && slots; j++) { if (!bus->codec[j]) continue; + printk(KERN_DEBUG ".. probing codec %d, slots = 0x%x\n", j, slots); rates = ~0; if (pcm->exclusive) { /* exclusive access */ tmp = avail_slots[pcm->stream][j] & slots; + printk(KERN_DEBUG ".. tmp = 0x%x\n", tmp); for (k = 0; k < i; k++) { if (rpcm->stream == rpcms[k].stream) tmp &= ~rpcms[k].r[0].rslots[j]; } + printk(KERN_DEBUG ".. tmp = 0x%x\n", tmp); if (tmp) { rpcm->r[0].rslots[j] = tmp; rpcm->r[0].codec[j] = bus->codec[j]; rpcm->r[0].rate_table[j] = rate_table[pcm->stream][j]; rates = get_rates(rpcm, j, tmp, 0); + printk(KERN_DEBUG ".. rslots = 0x%x, rate_table = %d, rates = 0x%x\n", tmp, rpcm->r[0].rate_table[j], rates); avail_slots[pcm->stream][j] &= ~tmp; } } else { @@ -467,6 +481,7 @@ rpcm->r[0].slots |= tmp; rpcm->rates &= rates; } + printk(KERN_DEBUG "--> slots = 0x%x, rates = 0x%x\n", rpcm->r[0].slots, rpcm->rates); } bus->pcms_count = pcms_count; bus->pcms = rpcms; @@ -487,9 +502,11 @@ { ac97_bus_t *bus; int i, cidx, r = 0, ok_flag; - unsigned short reg_ok = 0, reg_ok_new; + unsigned int reg_ok = 0; unsigned char reg; + int err = 0; + printk(KERN_DEBUG "ac97_pcm_open: rate = %d, cfg = %d, slots = 0x%x\n", rate, cfg, slots); if (rate > 48000) /* FIXME: add support for double rate */ return -EINVAL; bus = pcm->bus; @@ -506,27 +523,23 @@ for (i = 3; i < 12; i++) { if (!(slots & (1 << i))) continue; - for (cidx = 0; cidx < 4; cidx++) + ok_flag = 0; + for (cidx = 0; cidx < 4; cidx++) { if (bus->used_slots[pcm->stream][cidx] & (1 << i)) { spin_unlock_irq(&pcm->bus->bus_lock); - return -EBUSY; + err = -EBUSY; + goto error; } - } - for (i = 3; i < 12; i++) { - if (!(slots & (1 << i))) - continue; - ok_flag = 0; - for (cidx = 0; cidx < 4; cidx++) if (pcm->r[r].rslots[cidx] & (1 << i)) { bus->used_slots[pcm->stream][cidx] |= (1 << i); ok_flag++; } + } if (!ok_flag) { spin_unlock_irq(&pcm->bus->bus_lock); snd_printk(KERN_ERR "cannot find configuration for AC97 slot %i\n", i); - pcm->aslots = slots; - snd_ac97_pcm_close(pcm); - return -EAGAIN; + err = -EAGAIN; + goto error; } } spin_unlock_irq(&pcm->bus->bus_lock); @@ -534,23 +547,29 @@ if (!(slots & (1 << i))) continue; for (cidx = 0; cidx < 4; cidx++) { - reg_ok_new = 0; if (pcm->r[r].rslots[cidx] & (1 << i)) { - reg = get_slot_reg(pcm, cidx, i, 0); + reg = get_slot_reg(pcm, cidx, i, r); if (reg == 0xff) { snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i); continue; } if (reg_ok & (1 << (reg - AC97_PCM_FRONT_DAC_RATE))) continue; - snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate); - reg_ok_new |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE)); + printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate); + err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate); + if (err < 0) + snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d\n, err=%d", cidx, reg, rate, err); + reg_ok |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE)); } - reg_ok |= reg_ok_new; } } pcm->aslots = slots; return 0; + + error: + pcm->aslots = slots; + snd_ac97_pcm_close(pcm); + return err; } /**