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