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;
}
/**