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

Reply via email to