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

Modified Files:
        ac97_codec.c ac97_patch.c 
Log Message:
- fixed ALC100/P Master/PCM volume handling (h/w bug)
- added ALC65x JACK quirk
- disabled IC5 PERL mobo quirk
- fixed Mic/Center sharing switch on ALC65x.
- fixed Mic BIAS on ALC650.
- added extra delay in the resume if needed.
- renamed "External Amplifier Power Down" to "External Amplifier"
- added a workaround for the reversed EAPD of cs46xx voyetra.


Index: ac97_codec.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_codec.c,v
retrieving revision 1.122
retrieving revision 1.123
diff -u -r1.122 -r1.123
--- ac97_codec.c        20 Feb 2004 14:44:48 -0000      1.122
+++ ac97_codec.c        5 Mar 2004 12:04:43 -0000       1.123
@@ -105,9 +105,7 @@
 { 0x41445372, 0xffffffff, "AD1981A",           patch_ad1981a,  NULL },
 { 0x41445374, 0xffffffff, "AD1981B",           patch_ad1981b,  NULL },
 { 0x41445375, 0xffffffff, "AD1985",            patch_ad1985,   NULL },
-{ 0x414c4300, 0xfffffff0, "RL5306",            NULL,           NULL },
-{ 0x414c4310, 0xfffffff0, "RL5382",            NULL,           NULL },
-{ 0x414c4320, 0xfffffff0, "RL5383",            NULL,           NULL },
+{ 0x414c4300, 0xffffff00, "ALC100/100P",       NULL,           NULL },
 { 0x414c4710, 0xfffffff0, "ALC200/200P",       NULL,           NULL },
 { 0x414c4720, 0xfffffff0, "ALC650",            patch_alc650,   NULL },
 { 0x414c4721, 0xfffffff0, "ALC650D",           patch_alc650,   NULL },
@@ -274,6 +272,11 @@
 {
        if (!snd_ac97_valid_reg(ac97, reg))
                return;
+       if ((ac97->id & 0xffffff00) == 0x414c4300) {
+               /* Fix H/W bug of ALC100/100P */
+               if (reg == AC97_MASTER || reg == AC97_HEADPHONE)
+                       ac97->bus->write(ac97, AC97_RESET, 0);  /* reset audio codec */
+       }
        ac97->bus->write(ac97, reg, value);
 }
 
@@ -689,7 +692,7 @@
 };
 
 static const snd_kcontrol_new_t snd_ac97_control_eapd =
-AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0);
+AC97_SINGLE("External Amplifier", AC97_POWERDOWN, 15, 1, 1);
 
 static int snd_ac97_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * 
uinfo)
 {
@@ -1940,6 +1943,15 @@
                        return -ENOMEM;
                }
        }
+       /* make sure the proper powerdown bits are cleared */
+       if (ac97->scaps) {
+               reg = snd_ac97_read(ac97, AC97_EXTENDED_ID);
+               if (ac97->scaps & AC97_SCAP_SURROUND_DAC) 
+                       reg &= ~AC97_EA_PRJ;
+               if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) 
+                       reg &= ~(AC97_EA_PRI | AC97_EA_PRK);
+               snd_ac97_write_cache(ac97, AC97_EXTENDED_ID, reg);
+       }
        snd_ac97_proc_init(ac97);
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ac97, &ops)) < 0) {
                snd_ac97_free(ac97);
@@ -1994,11 +2006,18 @@
        snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0);
 
        snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]);
-       snd_ac97_write(ac97, AC97_MASTER, 0x8101);
+       ac97->bus->write(ac97, AC97_MASTER, 0x8101);
        for (i = 0; i < 10; i++) {
                if (snd_ac97_read(ac97, AC97_MASTER) == 0x8101)
                        break;
-               mdelay(1);
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(1);
+       }
+       /* FIXME: extra delay */
+       ac97->bus->write(ac97, AC97_MASTER, 0x8000);
+       if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000) {
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout(HZ/4);
        }
 __reset_ready:
 
@@ -2139,12 +2158,30 @@
 static int tune_ad_sharing(ac97_t *ac97)
 {
        unsigned short scfg;
+       if ((ac97->id & 0xffffff00) != 0x41445300) {
+               snd_printk(KERN_ERR "ac97_quirk AD_SHARING is only for AD codecs\n");
+               return -EINVAL;
+       }
        /* Turn on OMS bit to route microphone to back panel */
        scfg = snd_ac97_read(ac97, AC97_AD_SERIAL_CFG);
        snd_ac97_write_cache(ac97, AC97_AD_SERIAL_CFG, scfg | 0x0200);
        return 0;
 }
 
+static const snd_kcontrol_new_t snd_ac97_alc_jack_detect = 
+AC97_SINGLE("Jack Detect", AC97_ALC650_CLOCK, 5, 1, 0);
+
+static int tune_alc_jack(ac97_t *ac97)
+{
+       if ((ac97->id & 0xffffff00) != 0x414c4700) {
+               snd_printk(KERN_ERR "ac97_quirk ALC_JACK is only for Realtek 
codecs\n");
+               return -EINVAL;
+       }
+       snd_ac97_update_bits(ac97, 0x7a, 0x20, 0x20); /* select jack detect function */
+       snd_ac97_update_bits(ac97, 0x7a, 0x01, 0x01); /* Line-out auto mute */
+       return snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&snd_ac97_alc_jack_detect, 
ac97));
+}
+
 static int apply_quirk(ac97_t *ac97, int quirk)
 {
        switch (quirk) {
@@ -2158,6 +2195,8 @@
                return swap_surround(ac97);
        case AC97_TUNE_AD_SHARING:
                return tune_ad_sharing(ac97);
+       case AC97_TUNE_ALC_JACK:
+               return tune_alc_jack(ac97);
        }
        return -EINVAL;
 }

Index: ac97_patch.c
===================================================================
RCS file: /cvsroot/alsa/alsa-kernel/pci/ac97/ac97_patch.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -r1.37 -r1.38
--- ac97_patch.c        11 Feb 2004 19:41:18 -0000      1.37
+++ ac97_patch.c        5 Mar 2004 12:04:44 -0000       1.38
@@ -292,6 +292,9 @@
        return 0;
 }
 
+/*
+ * Tritech codec
+ */
 int patch_tritech_tr28028(ac97_t * ac97)
 {
        snd_ac97_write_cache(ac97, 0x26, 0x0300);
@@ -301,6 +304,9 @@
        return 0;
 }
 
+/*
+ * Sigmatel STAC97xx codecs
+ */
 static int patch_sigmatel_stac9700_3d(ac97_t * ac97)
 {
        snd_kcontrol_t *kctl;
@@ -441,6 +447,9 @@
        return 0;
 }
 
+/*
+ * Cirrus Logic CS42xx codecs
+ */
 static const snd_kcontrol_new_t snd_ac97_cirrus_controls_spdif[2] = {
        AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CSR_SPDIF, 15, 1, 
0),
        AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "AC97-SPSA", 
AC97_CSR_ACMODE, 0, 3, 0)
@@ -499,6 +508,9 @@
        return patch_cirrus_spdif(ac97);
 }
 
+/*
+ * Conexant codecs
+ */
 static const snd_kcontrol_new_t snd_ac97_conexant_controls_spdif[1] = {
        AC97_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), AC97_CXR_AUDIO_MISC, 3, 
1, 0),
 };
@@ -530,6 +542,9 @@
        return 0;
 }
 
+/*
+ * Analog Device AD18xx, AD19xx codecs
+ */
 int patch_ad1819(ac97_t * ac97)
 {
        // patch for Analog Devices
@@ -992,6 +1007,36 @@
        return 0;
 }
 
+/*
+ * realtek ALC65x codecs
+ */
+static int snd_ac97_alc650_mic_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * 
ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+        ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 
1;
+        return 0;
+}
+
+static int snd_ac97_alc650_mic_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t * 
ucontrol)
+{
+        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+       int change, val;
+       val = !!(snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10));
+       change = (ucontrol->value.integer.value[0] != val);
+       if (change) {
+               /* disable/enable vref */
+               snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
+                                    ucontrol->value.integer.value[0] ? (1 << 12) : 0);
+               /* turn on/off center-on-mic */
+               snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
+                                    ucontrol->value.integer.value[0] ? (1 << 10) : 0);
+               /* GPIO0 high for mic */
+               snd_ac97_update_bits(ac97, AC97_ALC650_GPIO_STATUS, 0x100,
+                                    ucontrol->value.integer.value[0] ? 0 : 0x100);
+        }
+        return change;
+}
+
 static const snd_kcontrol_new_t snd_ac97_controls_alc650[] = {
        AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0),
        AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0),
@@ -1014,41 +1059,13 @@
        AC97_SINGLE("Center/LFE DAC Switch", AC97_ALC650_LFE_DAC_VOL, 15, 1, 1),
        AC97_DOUBLE("Center/LFE DAC Volume", AC97_ALC650_LFE_DAC_VOL, 8, 0, 31, 1),
 #endif
-};
-
-static const snd_kcontrol_new_t snd_ac97_control_alc650_mic =
-AC97_SINGLE("Mic As Center/LFE", AC97_ALC650_MULTICH, 10, 1, 0);
-
-static int snd_ac97_alc650_mic_gpio_get(snd_kcontrol_t *kcontrol, 
snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        ucontrol->value.integer.value[0] = (ac97->regs[AC97_ALC650_MULTICH] >> 10) & 
1;
-        return 0;
-}
-
-static int snd_ac97_alc650_mic_gpio_put(snd_kcontrol_t *kcontrol, 
snd_ctl_elem_value_t * ucontrol)
-{
-        ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-        int change;
-        change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
-                                      ucontrol->value.integer.value[0] ? (1 << 10) : 
0);
-        if (change) {
-                /* GPIO0 write for mic */
-                snd_ac97_update_bits(ac97, 0x76, 0x01, 0x01);
-                /* GPIO0 high for mic */
-                snd_ac97_update_bits(ac97, 0x78, 0x100,
-                                     ucontrol->value.integer.value[0] ? 0 : 0x100);
-        }
-        return change;
-}
-
-static const snd_kcontrol_new_t snd_ac97_control_alc650_mic_gpio = {
-        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-        .name = "Mic As Center/LFE",
-        .info = snd_ac97_info_single,
-        .get = snd_ac97_alc650_mic_gpio_get,
-        .put = snd_ac97_alc650_mic_gpio_put,
-        .private_value = (1 << 16), /* for info */
+       {
+               .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+               .name = "Mic As Center/LFE",
+               .info = snd_ac97_info_single,
+               .get = snd_ac97_alc650_mic_get,
+               .put = snd_ac97_alc650_mic_put,
+       },
 };
 
 static const snd_kcontrol_new_t snd_ac97_spdif_controls_alc650[] = {
@@ -1063,11 +1080,6 @@
 
        if ((err = patch_build_controls(ac97, snd_ac97_controls_alc650, 
ARRAY_SIZE(snd_ac97_controls_alc650))) < 0)
                return err;
-       if ((err = patch_build_controls(ac97,
-                                       ac97->spec.dev_flags ?
-                                               &snd_ac97_control_alc650_mic :
-                                               &snd_ac97_control_alc650_mic_gpio, 1)) 
< 0)
-               return err;
        if (ac97->ext_id & AC97_EI_SPDIF) {
                if ((err = patch_build_controls(ac97, snd_ac97_spdif_controls_alc650, 
ARRAY_SIZE(snd_ac97_spdif_controls_alc650))) < 0)
                        return err;
@@ -1095,31 +1107,25 @@
                snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x8000);
 
        /* Enable SPDIF-IN only on Rev.E and above */
-       if (ac97->spec.dev_flags) {
-               /* enable spdif in */
-               snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK,
-                                    snd_ac97_read(ac97, AC97_ALC650_CLOCK) | 0x03);
-       }
+       val = snd_ac97_read(ac97, AC97_ALC650_CLOCK);
+       /* SPDIF IN with pin 47 */
+       if (ac97->spec.dev_flags)
+               val |= 0x03; /* enable */
+       else
+               val &= ~0x03; /* disable */
+       snd_ac97_write_cache(ac97, AC97_ALC650_CLOCK, val);
 
        val = snd_ac97_read(ac97, AC97_ALC650_MULTICH);
        val &= ~0xc000; /* slot: 3,4,7,8,6,9 */
+       val &= ~(1 << 10); /* center-on-mic off */
        snd_ac97_write_cache(ac97, AC97_ALC650_MULTICH, val);
 
-       if (! ac97->spec.dev_flags) {
-               /* set GPIO */
-               int mic_off;
-               mic_off = snd_ac97_read(ac97, AC97_ALC650_MULTICH) & (1 << 10);
-               /* GPIO0 direction */
-               val = snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP);
-               val |= 0x01;
-               snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP, val);
-               val = snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS);
-               if (mic_off)
-                       val &= ~0x100;
-               else
-                       val = val | 0x100;
-               snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS, val);
-       }
+       /* set GPIO0 for mic bias */
+       /* GPIO0 pin output, no interrupt, high */
+       snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_SETUP,
+                            snd_ac97_read(ac97, AC97_ALC650_GPIO_SETUP) | 0x01);
+       snd_ac97_write_cache(ac97, AC97_ALC650_GPIO_STATUS,
+                            (snd_ac97_read(ac97, AC97_ALC650_GPIO_STATUS) | 0x100) & 
~0x10);
 
        /* full DAC volume */
        snd_ac97_write_cache(ac97, AC97_ALC650_SURR_DAC_VOL, 0x0808);
@@ -1139,7 +1145,8 @@
         ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
         int change;
 
-       snd_ac97_update_bits(ac97, 0x7a, 1 << 12, /* misc control; vrefout disable */
+       /* misc control; vrefout disable */
+       snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
                             ucontrol->value.integer.value[0] ? (1 << 12) : 0);
        change = snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 10,
                                      ucontrol->value.integer.value[0] ? (1 << 10) : 
0);
@@ -1251,6 +1258,9 @@
        return 0;
 }
 
+/*
+ * C-Media CM97xx codecs
+ */
 static const snd_kcontrol_new_t snd_ac97_cm9738_controls[] = {
        AC97_SINGLE("Line-In As Surround", AC97_CM9738_VENDOR_CTRL, 10, 1, 0),
        AC97_SINGLE("Duplicate Front", AC97_CM9738_VENDOR_CTRL, 13, 1, 0),
@@ -1360,7 +1370,10 @@
        /* bit 13: enable internal vref output for mic */
        /* bit 12: enable center/lfe */
        /* bit 14: 0 = SPDIF, 1 = EAPD */
-       snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, 0x3000);
+       val = (1 << 12) | (1 << 13);
+       if (! (ac97->ext_id & AC97_EI_SPDIF))
+               val |= (1 << 14);
+       snd_ac97_write_cache(ac97, AC97_CM9739_MULTI_CHAN, val);
 
        /* FIXME: set up GPIO */
        snd_ac97_write_cache(ac97, 0x70, 0x0100);
@@ -1369,6 +1382,9 @@
        return 0;
 }
 
+/*
+ * VIA VT1616 codec
+ */
 static const snd_kcontrol_new_t snd_ac97_controls_vt1616[] = {
 AC97_SINGLE("DC Offset removal", 0x5a, 10, 1, 0),
 AC97_SINGLE("Alternate Level to Surround Out", 0x5a, 15, 1, 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

Reply via email to