Update of /cvsroot/alsa/alsa-kernel/pci/ac97
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13026/pci/ac97

Modified Files:
        ac97_codec.c ac97_local.h ac97_patch.c ac97_proc.c 
Log Message:
- added the global mutex for ac97_t (ad18xx mutex is removed).
  used to protect paging and AD18xx multi-codecs.
- set PAGE_INT register explicitly before accessing (for STAC9758).
- moved ALC650 revision check to patch_alc650().
- support stereo Mic playback.
- moved STAC9708 quirk to patch_stac9708().
- don't clear PC_BEEP high bits (ac97 2.3 sets frequency there).
- avoid the unnecessary RESET-waiting for audio/modem codec.
- fixed the evaluation of modem codec to call mpatch callback properly.
- determine the SPDIF rate in the build path.
- added suffix argument to snd_ac97_rename|remove|swap_ctl().
- added snd_ac97_rename_vol_ctl().


Index: ac97_codec.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_codec.c,v
retrieving revision 1.132
retrieving revision 1.133
diff -u -r1.132 -r1.133
--- ac97_codec.c        3 May 2004 17:32:57 -0000       1.132
+++ ac97_codec.c        24 May 2004 13:24:42 -0000      1.133
@@ -108,10 +108,10 @@
 { 0x41445375, 0xffffffff, "AD1985",            patch_ad1985,   NULL },
 { 0x414c4300, 0xffffff00, "ALC100/100P",       NULL,           NULL },
 { 0x414c4710, 0xfffffff0, "ALC200/200P",       NULL,           NULL },
+{ 0x414c4721, 0xffffffff, "ALC650D",           NULL,   NULL }, /* already patched */
+{ 0x414c4722, 0xffffffff, "ALC650E",           NULL,   NULL }, /* already patched */
+{ 0x414c4723, 0xffffffff, "ALC650F",           NULL,   NULL }, /* already patched */
 { 0x414c4720, 0xfffffff0, "ALC650",            patch_alc650,   NULL },
-{ 0x414c4721, 0xfffffff0, "ALC650D",           patch_alc650,   NULL },
-{ 0x414c4722, 0xfffffff0, "ALC650E",           patch_alc650,   NULL },
-{ 0x414c4723, 0xfffffff0, "ALC650F",           patch_alc650,   NULL },
 { 0x414c4760, 0xfffffff0, "ALC655",            patch_alc655,   NULL },
 { 0x414c4780, 0xfffffff0, "ALC658",            patch_alc655,   NULL },
 { 0x414c4730, 0xffffffff, "ALC101",            NULL,           NULL },
@@ -398,7 +398,7 @@
        int change;
        unsigned short old, new, cfg;
 
-       down(&ac97->spec.ad18xx.mutex);
+       down(&ac97->mutex);
        spin_lock(&ac97->reg_lock);
        old = ac97->spec.ad18xx.pcmreg[codec];
        new = (old & ~mask) | value;
@@ -418,7 +418,7 @@
                                 cfg | 0x7000);
        } else
                spin_unlock(&ac97->reg_lock);
-       up(&ac97->spec.ad18xx.mutex);
+       up(&ac97->mutex);
        return change;
 }
 
@@ -1120,6 +1120,7 @@
        snd_ac97_write_cache(ac97, reg, 0x8000);
 }
 
+/* check the volume resolution of center/lfe */
 static void snd_ac97_change_volume_params2(ac97_t * ac97, int reg, int shift, 
unsigned char *max)
 {
        unsigned short val, val1;
@@ -1135,6 +1136,7 @@
        snd_ac97_write_cache(ac97, reg, 0x8080);
 }
 
+/* check whether the volume resolution is 4 or 5 bits */
 static void snd_ac97_change_volume_params3(ac97_t * ac97, int reg, unsigned char *max)
 {
        unsigned short val, val1;
@@ -1150,6 +1152,18 @@
        snd_ac97_write_cache(ac97, reg, 0x8000);
 }
 
+/* check whether the volume is mono or stereo */
+static int snd_ac97_is_stereo_vol(ac97_t *ac97, int reg)
+{
+       unsigned short val, val1, val2;
+       val = snd_ac97_read(ac97, reg);
+       val1 = val | 0x8000 | (0x01 << 8);
+       snd_ac97_write(ac97, reg, val1);
+       val2 = snd_ac97_read(ac97, reg);
+       snd_ac97_write(ac97, reg, val); /* restore */
+       return val1 == val2;
+}
+
 static inline int printable(unsigned int x)
 {
        x &= 0xff;
@@ -1239,6 +1253,8 @@
 }
 
 
+static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97);
+
 static int snd_ac97_mixer_build(ac97_t * ac97)
 {
        snd_card_t *card = ac97->bus->card;
@@ -1293,11 +1309,8 @@
        }
 
        /* build headphone controls */
-       if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE) || ac97->id == 
AC97_ID_STAC9708) {
-               const char *name = ac97->id == AC97_ID_STAC9708 ? 
-                       "Sigmatel Surround Playback" :
-                       "Headphone Playback";
-               if ((err = snd_ac97_cmix_new(card, name, AC97_HEADPHONE, 1, ac97)) < 0)
+       if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE)) {
+               if ((err = snd_ac97_cmix_new(card, "Headphone Playback", 
AC97_HEADPHONE, 1, ac97)) < 0)
                        return err;
        }
        
@@ -1332,7 +1345,8 @@
                for (idx = 0; idx < 2; idx++)
                        if ((err = snd_ctl_add(card, 
snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
                                return err;
-               snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x801e);
+               snd_ac97_write_cache(ac97, AC97_PC_BEEP,
+                                    snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e);
        }
        
        /* build Phone controls */
@@ -1349,15 +1363,26 @@
        
        /* build MIC controls */
        snd_ac97_change_volume_params3(ac97, AC97_MIC, &max);
-       for (idx = 0; idx < 3; idx++) {
-               if ((err = snd_ctl_add(card, kctl = 
snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0)
+       if (snd_ac97_is_stereo_vol(ac97, AC97_MIC)) {
+               /* build stereo mic */
+               if ((err = snd_ac97_cmute_new(card, "Mic Playback Switch", AC97_MIC, 
ac97)) < 0)
+                       return err;
+               if ((err = snd_ac97_cvol_new(card, "Mic Playback Volume", AC97_MIC, 
max, ac97)) < 0)
+                       return err;
+               if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_mic[2], 
ac97))) < 0)
                        return err;
-               if (idx == 1) {         // volume
-                       kctl->private_value &= ~(0xff << 16);
-                       kctl->private_value |= (int)max << 16;
+       } else {
+               /* build mono mic */
+               for (idx = 0; idx < 3; idx++) {
+                       if ((err = snd_ctl_add(card, kctl = 
snd_ac97_cnew(&snd_ac97_controls_mic[idx], ac97))) < 0)
+                               return err;
+                       if (idx == 1) {         // volume
+                               kctl->private_value &= ~(0xff << 16);
+                               kctl->private_value |= (int)max << 16;
+                       }
                }
+               snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
        }
-       snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
 
        /* build Line controls */
        if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, 0, ac97)) < 0)
@@ -1520,6 +1545,7 @@
                        /* set default PCM S/PDIF params */
                        /* consumer,PCM audio,no copyright,no preemphasis,PCM 
coder,original,48000Hz */
                        snd_ac97_write_cache(ac97, AC97_SPDIF, 0x2a20);
+                       ac97->rates[AC97_RATES_SPDIF] = 
snd_ac97_determine_spdif_rates(ac97);
                }
                ac97->spdif_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
        }
@@ -1675,7 +1701,7 @@
                if (snd_ac97_read(ac97, AC97_REC_GAIN) == 0x8a05)
                        return 0;
                set_current_state(TASK_UNINTERRUPTIBLE);
-               schedule_timeout(HZ/100);
+               schedule_timeout(1);
        } while (time_after_eq(end_time, jiffies));
        return -ENODEV;
 }
@@ -1774,6 +1800,7 @@
        ac97->bus = bus;
        bus->codec[ac97->num] = ac97;
        spin_lock_init(&ac97->reg_lock);
+       init_MUTEX(&ac97->mutex);
 
        if (ac97->pci) {
                pci_read_config_word(ac97->pci, PCI_SUBSYSTEM_VENDOR_ID, 
&ac97->subsystem_vendor);
@@ -1789,8 +1816,12 @@
                bus->wait(ac97);
        else {
                udelay(50);
-               if (ac97_reset_wait(ac97, HZ/2, 0) < 0 &&
-                   ac97_reset_wait(ac97, HZ/2, 1) < 0) {
+               err = -ENXIO;
+               if (! (ac97->scaps & AC97_SCAP_SKIP_AUDIO))
+                       err = ac97_reset_wait(ac97, HZ/2, 0);
+               if (err < 0 && ! (ac97->scaps & AC97_SCAP_SKIP_MODEM))
+                       err = ac97_reset_wait(ac97, HZ/2, 1);
+               if (err < 0) {
                        snd_printk(KERN_WARNING "AC'97 %d does not respond - RESET\n", 
ac97->num);
                        /* proceed anyway - it's often non-critical */
                }
@@ -1803,20 +1834,6 @@
                snd_ac97_free(ac97);
                return -EIO;
        }
-       /* AC97 audio codec chip revision detection. */
-       /* Currently only Realtek ALC650 detection implemented. */
-       switch(ac97->id & 0xfffffff0) {
-       case 0x414c4720:        /* ALC650 */
-               reg = snd_ac97_read(ac97, AC97_ALC650_REVISION);
-               if (((reg & 0x3f) >= 0) && ((reg & 0x3f) < 3))
-                       ac97->id = 0x414c4720;          /* Old version */
-               else if (((reg & 0x3f) >= 3) && ((reg & 0x3f) < 0x10))
-                       ac97->id = 0x414c4721;          /* D version */
-               else if ((reg&0x30) == 0x10)
-                       ac97->id = 0x414c4722;          /* E version */
-               else if ((reg&0x30) == 0x20)
-                       ac97->id = 0x414c4723;          /* F version */
-        }
        
        /* test for AC'97 */
        if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) 
{
@@ -1865,9 +1882,9 @@
                        if ((snd_ac97_read(ac97, AC97_POWERDOWN) & 0x0f) == 0x0f)
                                goto __ready_ok;
                        set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(HZ/10);
+                       schedule_timeout(1);
                } while (time_after_eq(end_time, jiffies));
-               snd_printk(KERN_ERR "AC'97 %d analog subsections not ready\n", 
ac97->num);
+               snd_printk(KERN_WARNING "AC'97 %d analog subsections not ready\n", 
ac97->num);
        }
 
        /* FIXME: add powerdown control */
@@ -1898,9 +1915,9 @@
                        if ((snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS) & tmp) == tmp)
                                goto __ready_ok;
                        set_current_state(TASK_UNINTERRUPTIBLE);
-                       schedule_timeout(HZ/10);
+                       schedule_timeout(1);
                } while (time_after_eq(end_time, jiffies));
-               snd_printk(KERN_ERR "MC'97 %d converters and GPIO not ready (0x%x)\n", 
ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS));
+               snd_printk(KERN_WARNING "MC'97 %d converters and GPIO not ready 
(0x%x)\n", ac97->num, snd_ac97_read(ac97, AC97_EXTENDED_MSTATUS));
        }
        
       __ready_ok:
@@ -1919,12 +1936,7 @@
        }
        if (ac97->ext_id & AC97_EI_SPDIF) {
                /* codec specific code (patch) should override these values */
-               if (ac97->flags & AC97_CS_SPDIF)
-                       ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | 
SNDRV_PCM_RATE_44100;
-               else if (ac97->id == AC97_ID_CM9739)
-                       ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000;
-               else
-                       ac97->rates[AC97_RATES_SPDIF] = 
snd_ac97_determine_spdif_rates(ac97);
+               ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000 | 
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_32000;
        }
        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]);
@@ -1942,8 +1954,8 @@
        /* additional initializations */
        if (bus->init)
                bus->init(ac97);
-       snd_ac97_get_name(ac97, ac97->id, name, 0);
-       snd_ac97_get_name(NULL, ac97->id, name, 0);  // ac97->id might be changed in 
the special setup code
+       snd_ac97_get_name(ac97, ac97->id, name, !ac97_is_audio(ac97));
+       snd_ac97_get_name(NULL, ac97->id, name, !ac97_is_audio(ac97));  // ac97->id 
might be changed in the special setup code
        if (ac97_is_audio(ac97)) {
                if (card->mixername[0] == '\0') {
                        strcpy(card->mixername, name);
@@ -2151,42 +2163,57 @@
 
 /*
  */
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name)
+static void set_ctl_name(char *dst, const char *src, const char *suffix)
+{
+       if (suffix)
+               sprintf(dst, "%s %s", src, suffix);
+       else
+               strcpy(dst, src);
+}      
+
+int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix)
 {
        snd_ctl_elem_id_t id;
        memset(&id, 0, sizeof(id));
-       strcpy(id.name, name);
+       set_ctl_name(id.name, name, suffix);
        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        return snd_ctl_remove_id(ac97->bus->card, &id);
 }
 
-static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name)
+static snd_kcontrol_t *ctl_find(ac97_t *ac97, const char *name, const char *suffix)
 {
        snd_ctl_elem_id_t sid;
        memset(&sid, 0, sizeof(sid));
-       strcpy(sid.name, name);
+       set_ctl_name(sid.name, name, suffix);
        sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        return snd_ctl_find_id(ac97->bus->card, &sid);
 }
 
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst)
+int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char 
*suffix)
 {
-       snd_kcontrol_t *kctl = ctl_find(ac97, src);
+       snd_kcontrol_t *kctl = ctl_find(ac97, src, suffix);
        if (kctl) {
-               strcpy(kctl->id.name, dst);
+               set_ctl_name(kctl->id.name, dst, suffix);
                return 0;
        }
        return -ENOENT;
 }
 
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2)
+/* rename both Volume and Switch controls - don't check the return value */
+void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst)
+{
+       snd_ac97_rename_ctl(ac97, src, dst, "Switch");
+       snd_ac97_rename_ctl(ac97, src, dst, "Volume");
+}
+
+int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char 
*suffix)
 {
        snd_kcontrol_t *kctl1, *kctl2;
-       kctl1 = ctl_find(ac97, s1);
-       kctl2 = ctl_find(ac97, s2);
+       kctl1 = ctl_find(ac97, s1, suffix);
+       kctl2 = ctl_find(ac97, s2, suffix);
        if (kctl1 && kctl2) {
-               strcpy(kctl1->id.name, s2);
-               strcpy(kctl2->id.name, s1);
+               set_ctl_name(kctl1->id.name, s2, suffix);
+               set_ctl_name(kctl2->id.name, s1, suffix);
                return 0;
        }
        return -ENOENT;
@@ -2194,26 +2221,22 @@
 
 static int swap_headphone(ac97_t *ac97, int remove_master)
 {
-       /* FIXME: error checks.. */
        if (remove_master) {
-               if (ctl_find(ac97, "Headphone Playback Switch") == NULL)
+               if (ctl_find(ac97, "Headphone Playback Switch", NULL) == NULL)
                        return 0;
-               snd_ac97_remove_ctl(ac97, "Master Playback Switch");
-               snd_ac97_remove_ctl(ac97, "Master Playback Volume");
-       } else {
-               snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Line-Out Playback 
Switch");
-               snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Line-Out Playback 
Volume");
-       }
-       snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback 
Switch");
-       snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback 
Volume");
+               snd_ac97_remove_ctl(ac97, "Master Playback", "Switch");
+               snd_ac97_remove_ctl(ac97, "Master Playback", "Volume");
+       } else
+               snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Line-Out Playback");
+       snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
        return 0;
 }
 
 static int swap_surround(ac97_t *ac97)
 {
        /* FIXME: error checks.. */
-       snd_ac97_swap_ctl(ac97, "Master Playback Switch", "Surround Playback Switch");
-       snd_ac97_swap_ctl(ac97, "Master Playback Volume", "Surround Playback Volume");
+       snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Switch");
+       snd_ac97_swap_ctl(ac97, "Master Playback", "Surround Playback", "Volume");
        return 0;
 }
 

Index: ac97_local.h
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_local.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- ac97_local.h        16 Apr 2004 15:01:08 -0000      1.5
+++ ac97_local.h        24 May 2004 13:24:42 -0000      1.6
@@ -38,9 +38,10 @@
 int snd_ac97_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit);
-int snd_ac97_remove_ctl(ac97_t *ac97, const char *name);
-int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst);
-int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2);
+int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix);
+int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char 
*suffix);
+int snd_ac97_swap_ctl(ac97_t *ac97, const char *s1, const char *s2, const char 
*suffix);
+void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst);
 
 /* ac97_proc.c */
 void snd_ac97_bus_proc_init(ac97_bus_t * ac97);

Index: ac97_patch.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_patch.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- ac97_patch.c        11 May 2004 08:32:58 -0000      1.49
+++ ac97_patch.c        24 May 2004 13:24:42 -0000      1.50
@@ -204,7 +204,7 @@
        if ((err = snd_ctl_add(ac97->bus->card, kctl = 
snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
                return err;
        strcpy(kctl->id.name, "3D Control - Wide");
-       kctl->private_value = AC97_3D_CONTROL | (9 << 8) | (7 << 16);
+       kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 9, 7, 0);
        snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
        if ((err = snd_ctl_add(ac97->bus->card, 
snd_ac97_cnew(&snd_ac97_ymf753_controls_speaker, ac97))) < 0)
                return err;
@@ -315,7 +315,7 @@
        if ((err = snd_ctl_add(ac97->bus->card, kctl = 
snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
                return err;
        strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
-       kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+       kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
        snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
        return 0;
 }
@@ -328,11 +328,11 @@
        if ((err = snd_ctl_add(ac97->bus->card, kctl = 
snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
                return err;
        strcpy(kctl->id.name, "3D Control Sigmatel - Depth");
-       kctl->private_value = AC97_3D_CONTROL | (3 << 16);
+       kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 0, 3, 0);
        if ((err = snd_ctl_add(ac97->bus->card, kctl = 
snd_ac97_cnew(&snd_ac97_controls_3d[0], ac97))) < 0)
                return err;
        strcpy(kctl->id.name, "3D Control Sigmatel - Rear Depth");
-       kctl->private_value = AC97_3D_CONTROL | (2 << 8) | (3 << 16);
+       kctl->private_value = AC97_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0);
        snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000);
        return 0;
 }
@@ -373,17 +373,23 @@
        .build_specific = patch_sigmatel_stac97xx_specific
 };
 
-static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
-       .build_3d       = patch_sigmatel_stac9708_3d,
-       .build_specific = patch_sigmatel_stac97xx_specific
-};
-
 int patch_sigmatel_stac9700(ac97_t * ac97)
 {
        ac97->build_ops = &patch_sigmatel_stac9700_ops;
        return 0;
 }
 
+static int patch_sigmatel_stac9708_specific(ac97_t *ac97)
+{
+       snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround 
Playback");
+       return patch_sigmatel_stac97xx_specific(ac97);
+}
+
+static struct snd_ac97_build_ops patch_sigmatel_stac9708_ops = {
+       .build_3d       = patch_sigmatel_stac9708_3d,
+       .build_specific = patch_sigmatel_stac9708_specific
+};
+
 int patch_sigmatel_stac9708(ac97_t * ac97)
 {
        unsigned int codec72, codec6c;
@@ -467,11 +473,11 @@
        int shift = kcontrol->private_value;
        unsigned short val;
 
-       val = ac97->regs[AC97_SIGMATEL_OUTSEL];
-       if (!((val >> shift) & 4))
+       val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift;
+       if (!(val & 4))
                ucontrol->value.enumerated.item[0] = 0;
        else
-               ucontrol->value.enumerated.item[0] = 1 + ((val >> shift) & 3);
+               ucontrol->value.enumerated.item[0] = 1 + (val & 3);
        return 0;
 }
 
@@ -480,6 +486,7 @@
        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
        int shift = kcontrol->private_value;
        unsigned short val;
+       int ret;
 
        if (ucontrol->value.enumerated.item[0] > 4)
                return -EINVAL;
@@ -487,8 +494,12 @@
                val = 0;
        else
                val = 4 | (ucontrol->value.enumerated.item[0] - 1);
-       return snd_ac97_update_bits(ac97, AC97_SIGMATEL_OUTSEL,
-                                   7 << shift, val << shift);
+       down(&ac97->mutex);
+       snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+       ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_OUTSEL,
+                                  7 << shift, val << shift);
+       up(&ac97->mutex);
+       return ret;
 }
 
 static int snd_ac97_stac9758_input_jack_info(snd_kcontrol_t *kcontrol, 
snd_ctl_elem_info_t *uinfo)
@@ -520,9 +531,14 @@
 {
        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
        int shift = kcontrol->private_value;
+       int ret;
 
-       return snd_ac97_update_bits(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
-                                   ucontrol->value.enumerated.item[0] << shift);
+       down(&ac97->mutex);
+       snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+       ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_INSEL, 7 << shift,
+                                  ucontrol->value.enumerated.item[0] << shift);
+       up(&ac97->mutex);
+       return ret;
 }
 
 static int snd_ac97_stac9758_phonesel_info(snd_kcontrol_t *kcontrol, 
snd_ctl_elem_info_t *uinfo)
@@ -549,9 +565,14 @@
 static int snd_ac97_stac9758_phonesel_put(snd_kcontrol_t *kcontrol, 
snd_ctl_elem_value_t *ucontrol)
 {
        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+       int ret;
 
-       return snd_ac97_update_bits(ac97, AC97_SIGMATEL_IOMISC, 3,
-                                   ucontrol->value.enumerated.item[0]);
+       down(&ac97->mutex);
+       snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
+       ret = snd_ac97_update_bits(ac97, AC97_SIGMATEL_IOMISC, 3,
+                                  ucontrol->value.enumerated.item[0]);
+       up(&ac97->mutex);
+       return ret;
 }
 
 #define STAC9758_OUTPUT_JACK(xname, shift) \
@@ -596,6 +617,14 @@
                                   ARRAY_SIZE(snd_ac97_sigmatel_stac9758_controls));
        if (err < 0)
                return err;
+       /* DAC-A direct */
+       snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Front Playback");
+       /* DAC-A to Mix = PCM */
+       /* DAC-B direct = Surround */
+       /* DAC-B to Mix */
+       snd_ac97_rename_vol_ctl(ac97, "Video Playback", "Surround Mix Playback");
+       /* DAC-C direct = Center/LFE */
+
        return 0;
 }
 
@@ -613,16 +642,16 @@
                AC97_SIGMATEL_VARIOUS
        };
        static unsigned short def_regs[4] = {
-               /* OUTSEL */ 0xd794,
+               /* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
                /* IOMISC */ 0x2001,
-               /* INSEL */ 0x0201,
+               /* INSEL */ 0x0201, /* LI:LI, MI:M1 */
                /* VARIOUS */ 0x0040
        };
        static unsigned short m675_regs[4] = {
-               /* OUTSEL */ 0x9040,
-               /* IOMISC */ 0x2102,
-               /* INSEL */ 0x0203,
-               /* VARIOUS */ 0x0041
+               /* OUTSEL */ 0x9040, /* CL:FR, SR:FR, LO:DS, LI:FR, MI:DS */
+               /* IOMISC */ 0x2102, /* HP amp on */
+               /* INSEL */ 0x0203, /* LI:LI, MI:FR */
+               /* VARIOUS */ 0x0041 /* stereo mic */
        };
        unsigned short *pregs = def_regs;
        int i;
@@ -635,6 +664,8 @@
 
        // patch for SigmaTel
        ac97->build_ops = &patch_sigmatel_stac9758_ops;
+       /* FIXME: assume only page 0 for writing cache */
+       snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, AC97_PAGE_VENDOR);
        for (i = 0; i < 4; i++)
                snd_ac97_write_cache(ac97, regs[i], pregs[i]);
 
@@ -654,8 +685,10 @@
 {
        int err;
 
+       /* con mask, pro mask, default */
        if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
                return err;
+       /* switch, spsa */
        if ((err = patch_build_controls(ac97, &snd_ac97_cirrus_controls_spdif[0], 1)) 
< 0)
                return err;
        switch (ac97->id & AC97_ID_CS_MASK) {
@@ -714,8 +747,10 @@
 {
        int err;
 
+       /* con mask, pro mask, default */
        if ((err = patch_build_controls(ac97, &snd_ac97_controls_spdif[0], 3)) < 0)
                return err;
+       /* switch */
        if ((err = patch_build_controls(ac97, &snd_ac97_conexant_controls_spdif[0], 
1)) < 0)
                return err;
        /* set default PCM S/PDIF params */
@@ -734,6 +769,7 @@
        ac97->build_ops = &patch_conexant_ops;
        ac97->flags |= AC97_CX_SPDIF;
         ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
+       ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
        return 0;
 }
 
@@ -821,8 +857,6 @@
        unsigned short val;
        int idx, num;
 
-       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));
@@ -1114,10 +1148,8 @@
 static int patch_ad1888_specific(ac97_t *ac97)
 {
        /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
-       snd_ac97_rename_ctl(ac97, "Master Playback Switch", "Master Surround Playback 
Switch");
-       snd_ac97_rename_ctl(ac97, "Master Playback Volume", "Master Surround Playback 
Volume");
-       snd_ac97_rename_ctl(ac97, "Headphone Playback Switch", "Master Playback 
Switch");
-       snd_ac97_rename_ctl(ac97, "Headphone Playback Volume", "Master Playback 
Volume");
+       snd_ac97_rename_vol_ctl(ac97, "Master Playback", "Master Surround Playback");
+       snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
        return patch_build_controls(ac97, snd_ac97_ad1888_controls, 
ARRAY_SIZE(snd_ac97_ad1888_controls));
 }
 
@@ -1303,6 +1335,17 @@
 
        ac97->build_ops = &patch_alc650_ops;
 
+       /* determine the revision */
+       val = snd_ac97_read(ac97, AC97_ALC650_REVISION) & 0x3f;
+       if (val < 3)
+               ac97->id = 0x414c4720;          /* Old version */
+       else if (val < 0x10)
+               ac97->id = 0x414c4721;          /* D version */
+       else if (val < 0x20)
+               ac97->id = 0x414c4722;          /* E version */
+       else if (val < 0x30)
+               ac97->id = 0x414c4723;          /* F version */
+
        /* revision E or F */
        /* FIXME: what about revision D ? */
        ac97->spec.dev_flags = (ac97->id == 0x414c4722 ||
@@ -1599,8 +1642,10 @@
                /* enable spdif in */
                snd_ac97_write_cache(ac97, AC97_CM9739_SPDIF_CTRL,
                                     snd_ac97_read(ac97, AC97_CM9739_SPDIF_CTRL) | 
0x01);
+               ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
        } else {
                ac97->ext_id &= ~AC97_EI_SPDIF; /* disable extended-id */
+               ac97->rates[AC97_RATES_SPDIF] = 0;
        }
 
        /* set-up multi channel */

Index: ac97_proc.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_proc.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- ac97_proc.c 16 Apr 2004 18:29:12 -0000      1.7
+++ ac97_proc.c 24 May 2004 13:24:42 -0000      1.8
@@ -292,9 +292,9 @@
 {
        ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
        
+       down(&ac97->mutex);
        if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {        // Analog Devices 
AD1881/85/86
                int idx;
-               down(&ac97->spec.ad18xx.mutex);
                for (idx = 0; idx < 3; idx++)
                        if (ac97->spec.ad18xx.id[idx]) {
                                /* select single codec */
@@ -305,7 +305,6 @@
                        }
                /* select all codecs */
                snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
-               up(&ac97->spec.ad18xx.mutex);
                
                snd_iprintf(buffer, "\nAD18XX configuration\n");
                snd_iprintf(buffer, "Unchained        : 0x%04x,0x%04x,0x%04x\n",
@@ -319,6 +318,7 @@
        } else {
                snd_ac97_proc_read_main(ac97, buffer, 0);
        }
+       up(&ac97->mutex);
 }
 
 #ifdef CONFIG_SND_DEBUG
@@ -328,6 +328,7 @@
        ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
        char line[64];
        unsigned int reg, val;
+       down(&ac97->mutex);
        while (!snd_info_get_line(buffer, line, sizeof(line))) {
                if (sscanf(line, "%x %x", &reg, &val) != 2)
                        continue;
@@ -335,6 +336,7 @@
                if (reg < 0x80 && (reg & 1) == 0 && val <= 0xffff)
                        snd_ac97_write_cache(ac97, reg, val);
        }
+       up(&ac97->mutex);
 }
 #endif
 
@@ -353,10 +355,10 @@
 {
        ac97_t *ac97 = snd_magic_cast(ac97_t, entry->private_data, return);
 
+       down(&ac97->mutex);
        if ((ac97->id & 0xffffff40) == AC97_ID_AD1881) {        // Analog Devices 
AD1881/85/86
 
                int idx;
-               down(&ac97->spec.ad18xx.mutex);
                for (idx = 0; idx < 3; idx++)
                        if (ac97->spec.ad18xx.id[idx]) {
                                /* select single codec */
@@ -366,10 +368,10 @@
                        }
                /* select all codecs */
                snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, 0x7000);
-               up(&ac97->spec.ad18xx.mutex);
        } else {
                snd_ac97_proc_regs_read_main(ac97, buffer, 0);
        }       
+       up(&ac97->mutex);
 }
 
 void snd_ac97_proc_init(ac97_t * ac97)



-------------------------------------------------------
This SF.Net email is sponsored by: Oracle 10g
Get certified on the hottest thing ever to hit the market... Oracle 10g. 
Take an Oracle 10g class now, and we'll give you the exam FREE.
http://ads.osdn.com/?ad_id=3149&alloc_id=8166&op=click
_______________________________________________
Alsa-cvslog mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-cvslog

Reply via email to