📄 ac97_patch.c
字号:
AC97_SINGLE("Capture Switch", AC97_CD, 15, 1, 1),AC97_ENUM("Capture Volume Steps", wm9713_enum[4]),AC97_DOUBLE("Capture Volume", AC97_CD, 8, 0, 15, 0),AC97_SINGLE("Capture ZC Switch", AC97_CD, 7, 1, 0),AC97_ENUM("Capture to Headphone Mux", wm9713_enum[1]),AC97_SINGLE("Capture to Headphone Volume", AC97_VIDEO, 11, 7, 1),AC97_ENUM("Capture to Mono Mux", wm9713_enum[2]),AC97_SINGLE("Capture to Mono Boost (+20dB) Switch", AC97_VIDEO, 8, 1, 0),AC97_SINGLE("Capture ADC Boost (+20dB) Switch", AC97_VIDEO, 6, 1, 0),AC97_ENUM("Capture Select", wm9713_enum[3]),AC97_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),AC97_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),AC97_SINGLE("ALC Decay Time ", AC97_CODEC_CLASS_REV, 4, 15, 0),AC97_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),AC97_ENUM("ALC Function", wm9713_enum[5]),AC97_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),AC97_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 0),AC97_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),AC97_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),AC97_ENUM("ALC NG Type", wm9713_enum[13]),AC97_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 0),AC97_DOUBLE("Master ZC Switch", AC97_MASTER, 14, 6, 1, 0),AC97_DOUBLE("Headphone ZC Switch", AC97_HEADPHONE, 14, 6, 1, 0),AC97_DOUBLE("Out3/4 ZC Switch", AC97_MASTER_MONO, 14, 6, 1, 0),AC97_SINGLE("Master Right Switch", AC97_MASTER, 7, 1, 1),AC97_SINGLE("Headphone Right Switch", AC97_HEADPHONE, 7, 1, 1),AC97_SINGLE("Out3/4 Right Switch", AC97_MASTER_MONO, 7, 1, 1),AC97_SINGLE("Mono In to Headphone Switch", AC97_MASTER_TONE, 15, 1, 1),AC97_SINGLE("Mono In to Master Switch", AC97_MASTER_TONE, 14, 1, 1),AC97_SINGLE("Mono In Volume", AC97_MASTER_TONE, 8, 31, 1),AC97_SINGLE("Mono Switch", AC97_MASTER_TONE, 7, 1, 1),AC97_SINGLE("Mono ZC Switch", AC97_MASTER_TONE, 6, 1, 0),AC97_SINGLE("Mono Volume", AC97_MASTER_TONE, 0, 31, 1),AC97_SINGLE("PC Beep to Headphone Switch", AC97_AUX, 15, 1, 1),AC97_SINGLE("PC Beep to Headphone Volume", AC97_AUX, 12, 7, 1),AC97_SINGLE("PC Beep to Master Switch", AC97_AUX, 11, 1, 1),AC97_SINGLE("PC Beep to Master Volume", AC97_AUX, 8, 7, 1),AC97_SINGLE("PC Beep to Mono Switch", AC97_AUX, 7, 1, 1),AC97_SINGLE("PC Beep to Mono Volume", AC97_AUX, 4, 7, 1),AC97_SINGLE("Voice to Headphone Switch", AC97_PCM, 15, 1, 1),AC97_SINGLE("Voice to Headphone Volume", AC97_PCM, 12, 7, 1),AC97_SINGLE("Voice to Master Switch", AC97_PCM, 11, 1, 1),AC97_SINGLE("Voice to Master Volume", AC97_PCM, 8, 7, 1),AC97_SINGLE("Voice to Mono Switch", AC97_PCM, 7, 1, 1),AC97_SINGLE("Voice to Mono Volume", AC97_PCM, 4, 7, 1),AC97_SINGLE("Aux to Headphone Switch", AC97_REC_SEL, 15, 1, 1),AC97_SINGLE("Aux to Headphone Volume", AC97_REC_SEL, 12, 7, 1),AC97_SINGLE("Aux to Master Switch", AC97_REC_SEL, 11, 1, 1),AC97_SINGLE("Aux to Master Volume", AC97_REC_SEL, 8, 7, 1),AC97_SINGLE("Aux to Mono Switch", AC97_REC_SEL, 7, 1, 1),AC97_SINGLE("Aux to Mono Volume", AC97_REC_SEL, 4, 7, 1),AC97_ENUM("Mono Input Mux", wm9713_enum[6]),AC97_ENUM("Master Input Mux", wm9713_enum[7]),AC97_ENUM("Headphone Input Mux", wm9713_enum[8]),AC97_ENUM("Out 3 Input Mux", wm9713_enum[9]),AC97_ENUM("Out 4 Input Mux", wm9713_enum[10]),AC97_ENUM("Bass Control", wm9713_enum[12]),AC97_SINGLE("Bass Cut-off Switch", AC97_GENERAL_PURPOSE, 12, 1, 1),AC97_SINGLE("Tone Cut-off Switch", AC97_GENERAL_PURPOSE, 4, 1, 1),AC97_SINGLE("Playback Attenuate (-6dB) Switch", AC97_GENERAL_PURPOSE, 6, 1, 0),AC97_SINGLE("Bass Volume", AC97_GENERAL_PURPOSE, 8, 15, 1),AC97_SINGLE("Tone Volume", AC97_GENERAL_PURPOSE, 0, 15, 1),};static const struct snd_kcontrol_new wm13_snd_ac97_controls_3d[] = {AC97_ENUM("Inv Input Mux", wm9713_enum[11]),AC97_SINGLE("3D Upper Cut-off Switch", AC97_REC_GAIN_MIC, 5, 1, 0),AC97_SINGLE("3D Lower Cut-off Switch", AC97_REC_GAIN_MIC, 4, 1, 0),AC97_SINGLE("3D Depth", AC97_REC_GAIN_MIC, 0, 15, 1),};static int patch_wolfson_wm9713_3d (struct snd_ac97 * ac97){ int err, i; for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_3d); i++) { if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_3d[i], ac97))) < 0) return err; } return 0;}static int patch_wolfson_wm9713_specific(struct snd_ac97 * ac97){ int err, i; for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls); i++) { if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls[i], ac97))) < 0) return err; } snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808); snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808); snd_ac97_write_cache(ac97, AC97_MIC, 0x0808); snd_ac97_write_cache(ac97, AC97_LINE, 0x00da); snd_ac97_write_cache(ac97, AC97_CD, 0x0808); snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612); snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0); return 0;}#ifdef CONFIG_PMstatic void patch_wolfson_wm9713_suspend (struct snd_ac97 * ac97){ snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff); snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff);}static void patch_wolfson_wm9713_resume (struct snd_ac97 * ac97){ snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00); snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810); snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);}#endifstatic struct snd_ac97_build_ops patch_wolfson_wm9713_ops = { .build_specific = patch_wolfson_wm9713_specific, .build_3d = patch_wolfson_wm9713_3d,#ifdef CONFIG_PM .suspend = patch_wolfson_wm9713_suspend, .resume = patch_wolfson_wm9713_resume#endif};static int patch_wolfson13(struct snd_ac97 * ac97){ /* WM9713, WM9714 */ ac97->build_ops = &patch_wolfson_wm9713_ops; ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE | AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD | AC97_HAS_NO_TONE | AC97_HAS_NO_STD_PCM; ac97->scaps &= ~AC97_SCAP_MODEM; snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00); snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810); snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0); return 0;}/* * Tritech codec */static int patch_tritech_tr28028(struct snd_ac97 * ac97){ snd_ac97_write_cache(ac97, 0x26, 0x0300); snd_ac97_write_cache(ac97, 0x26, 0x0000); snd_ac97_write_cache(ac97, AC97_SURROUND_MASTER, 0x0000); snd_ac97_write_cache(ac97, AC97_SPDIF, 0x0000); return 0;}/* * Sigmatel STAC97xx codecs */static int patch_sigmatel_stac9700_3d(struct snd_ac97 * ac97){ struct snd_kcontrol *kctl; int err; 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_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0); snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); return 0;}static int patch_sigmatel_stac9708_3d(struct snd_ac97 * ac97){ struct snd_kcontrol *kctl; int err; 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_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_SINGLE_VALUE(AC97_3D_CONTROL, 2, 3, 0); snd_ac97_write_cache(ac97, AC97_3D_CONTROL, 0x0000); return 0;}static const struct snd_kcontrol_new snd_ac97_sigmatel_4speaker =AC97_SINGLE("Sigmatel 4-Speaker Stereo Playback Switch", AC97_SIGMATEL_DAC2INVERT, 2, 1, 0);static const struct snd_kcontrol_new snd_ac97_sigmatel_phaseinvert =AC97_SINGLE("Sigmatel Surround Phase Inversion Playback Switch", AC97_SIGMATEL_DAC2INVERT, 3, 1, 0);static const struct snd_kcontrol_new snd_ac97_sigmatel_controls[] = {AC97_SINGLE("Sigmatel DAC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 1, 1, 0),AC97_SINGLE("Sigmatel ADC 6dB Attenuate", AC97_SIGMATEL_ANALOG, 0, 1, 0)};static int patch_sigmatel_stac97xx_specific(struct snd_ac97 * ac97){ int err; snd_ac97_write_cache(ac97, AC97_SIGMATEL_ANALOG, snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) & ~0x0003); if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 1)) if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[0], 1)) < 0) return err; if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_ANALOG, 0)) if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_controls[1], 1)) < 0) return err; if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 2)) if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_4speaker, 1)) < 0) return err; if (snd_ac97_try_bit(ac97, AC97_SIGMATEL_DAC2INVERT, 3)) if ((err = patch_build_controls(ac97, &snd_ac97_sigmatel_phaseinvert, 1)) < 0) return err; return 0;}static struct snd_ac97_build_ops patch_sigmatel_stac9700_ops = { .build_3d = patch_sigmatel_stac9700_3d, .build_specific = patch_sigmatel_stac97xx_specific};static int patch_sigmatel_stac9700(struct snd_ac97 * ac97){ ac97->build_ops = &patch_sigmatel_stac9700_ops; return 0;}static int snd_ac97_stac9708_put_bias(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int err; mutex_lock(&ac97->page_mutex); snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba); err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010, (ucontrol->value.integer.value[0] & 1) << 4); snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0); mutex_unlock(&ac97->page_mutex); return err;}static const struct snd_kcontrol_new snd_ac97_stac9708_bias_control = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Sigmatel Output Bias Switch", .info = snd_ac97_info_volsw, .get = snd_ac97_get_volsw, .put = snd_ac97_stac9708_put_bias, .private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),};static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97){ int err; /* the register bit is writable, but the function is not implemented: */ snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL); snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback"); if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0) return err; 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};static int patch_sigmatel_stac9708(struct snd_ac97 * ac97){ unsigned int codec72, codec6c; ac97->build_ops = &patch_sigmatel_stac9708_ops; ac97->caps |= 0x10; /* HP (sigmatel surround) support */ codec72 = snd_ac97_read(ac97, AC97_SIGMATEL_BIAS2) & 0x8000; codec6c = snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG); if ((codec72==0) && (codec6c==0)) { snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1000); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0007); } else if ((codec72==0x8000) && (codec6c==0)) { snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x1001); snd_ac97_write_cache(ac97, AC97_SIGMATEL_DAC2INVERT, 0x0008); } else if ((codec72==0x8000) && (codec6c==0x0080)) { /* nothing */ } snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); return 0;}static int patch_sigmatel_stac9721(struct snd_ac97 * ac97){ ac97->build_ops = &patch_sigmatel_stac9700_ops; if (snd_ac97_read(ac97, AC97_SIGMATEL_ANALOG) == 0) { // patch for SigmaTel snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x4000); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002); } snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); return 0;}static int patch_sigmatel_stac9744(struct snd_ac97 * ac97){ // patch for SigmaTel ac97->build_ops = &patch_sigmatel_stac9700_ops; snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */ snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002); snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); return 0;}static int patch_sigmatel_stac9756(struct snd_ac97 * ac97){ // patch for SigmaTel ac97->build_ops = &patch_sigmatel_stac9700_ops; snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_CIC2, 0x0000); /* is this correct? --jk */ snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS1, 0xabba); snd_ac97_write_cache(ac97, AC97_SIGMATEL_BIAS2, 0x0002); snd_ac97_write_cache(ac97, AC97_SIGMATEL_MULTICHN, 0x0000); return 0;}static int snd_ac97_stac9758_output_jack_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[5] = { "Input/Disabled", "Front Output", "Rear Output", "Center/LFE Output", "Mixer Output" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 5; if (uinfo->value.enumerated.item > 4) uinfo->value.enumerated.item = 4; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static int snd_ac97_stac9758_output_jack_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int shift = kcontrol->private_value; unsigned short val; val = ac97->regs[AC97_SIGMATEL_OUTSEL] >> shift; if (!(val & 4)) ucontrol->value.enumerated.item[0] = 0; else ucontrol->value.enumerated.item[0] = 1 + (val & 3); return 0;}static int snd_ac97_stac9758_output_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -