📄 patch_realtek.c
字号:
struct hda_codec *codec, struct snd_pcm_substream *substream){ struct alc_spec *spec = codec->spec; return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);}static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, unsigned int format, struct snd_pcm_substream *substream){ struct alc_spec *spec = codec->spec; return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag, format, substream);}static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream){ struct alc_spec *spec = codec->spec; return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);}/* * Digital out */static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream){ struct alc_spec *spec = codec->spec; return snd_hda_multi_out_dig_open(codec, &spec->multiout);}static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream){ struct alc_spec *spec = codec->spec; return snd_hda_multi_out_dig_close(codec, &spec->multiout);}/* * Analog capture */static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo, struct hda_codec *codec, unsigned int stream_tag, unsigned int format, struct snd_pcm_substream *substream){ struct alc_spec *spec = codec->spec; snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], stream_tag, 0, format); return 0;}static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, struct hda_codec *codec, struct snd_pcm_substream *substream){ struct alc_spec *spec = codec->spec; snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0); return 0;}/* */static struct hda_pcm_stream alc880_pcm_analog_playback = { .substreams = 1, .channels_min = 2, .channels_max = 8, /* NID is set in alc_build_pcms */ .ops = { .open = alc880_playback_pcm_open, .prepare = alc880_playback_pcm_prepare, .cleanup = alc880_playback_pcm_cleanup },};static struct hda_pcm_stream alc880_pcm_analog_capture = { .substreams = 2, .channels_min = 2, .channels_max = 2, /* NID is set in alc_build_pcms */ .ops = { .prepare = alc880_capture_pcm_prepare, .cleanup = alc880_capture_pcm_cleanup },};static struct hda_pcm_stream alc880_pcm_digital_playback = { .substreams = 1, .channels_min = 2, .channels_max = 2, /* NID is set in alc_build_pcms */ .ops = { .open = alc880_dig_playback_pcm_open, .close = alc880_dig_playback_pcm_close },};static struct hda_pcm_stream alc880_pcm_digital_capture = { .substreams = 1, .channels_min = 2, .channels_max = 2, /* NID is set in alc_build_pcms */};static int alc_build_pcms(struct hda_codec *codec){ struct alc_spec *spec = codec->spec; struct hda_pcm *info = spec->pcm_rec; int i; codec->num_pcms = 1; codec->pcm_info = info; info->name = spec->stream_name_analog; if (spec->stream_analog_playback) { snd_assert(spec->multiout.dac_nids, return -EINVAL); info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback); info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; } if (spec->stream_analog_capture) { snd_assert(spec->adc_nids, return -EINVAL); info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture); info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0]; } if (spec->channel_mode) { info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0; for (i = 0; i < spec->num_channel_mode; i++) { if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) { info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels; } } } if (spec->multiout.dig_out_nid || spec->dig_in_nid) { codec->num_pcms++; info++; info->name = spec->stream_name_digital; if (spec->multiout.dig_out_nid && spec->stream_digital_playback) { info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback); info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid; } if (spec->dig_in_nid && spec->stream_digital_capture) { info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture); info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid; } } return 0;}static void alc_free(struct hda_codec *codec){ struct alc_spec *spec = codec->spec; unsigned int i; if (! spec) return; if (spec->kctl_alloc) { for (i = 0; i < spec->num_kctl_used; i++) kfree(spec->kctl_alloc[i].name); kfree(spec->kctl_alloc); } kfree(spec);}/* */static struct hda_codec_ops alc_patch_ops = { .build_controls = alc_build_controls, .build_pcms = alc_build_pcms, .init = alc_init, .free = alc_free,#ifdef CONFIG_PM .resume = alc_resume,#endif};/* * Test configuration for debugging * * Almost all inputs/outputs are enabled. I/O pins can be configured via * enum controls. */#ifdef CONFIG_SND_DEBUGstatic hda_nid_t alc880_test_dac_nids[4] = { 0x02, 0x03, 0x04, 0x05};static struct hda_input_mux alc880_test_capture_source = { .num_items = 5, .items = { { "In-1", 0x0 }, { "In-2", 0x1 }, { "In-3", 0x2 }, { "In-4", 0x3 }, { "CD", 0x4 }, },};static struct hda_channel_mode alc880_test_modes[4] = { { 2, NULL }, { 4, NULL }, { 6, NULL }, { 8, NULL },};static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[] = { "N/A", "Line Out", "HP Out", "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 8; if (uinfo->value.enumerated.item >= 8) uinfo->value.enumerated.item = 7; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = (hda_nid_t)kcontrol->private_value; unsigned int pin_ctl, item = 0; pin_ctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); if (pin_ctl & AC_PINCTL_OUT_EN) { if (pin_ctl & AC_PINCTL_HP_EN) item = 2; else item = 1; } else if (pin_ctl & AC_PINCTL_IN_EN) { switch (pin_ctl & AC_PINCTL_VREFEN) { case AC_PINCTL_VREF_HIZ: item = 3; break; case AC_PINCTL_VREF_50: item = 4; break; case AC_PINCTL_VREF_GRD: item = 5; break; case AC_PINCTL_VREF_80: item = 6; break; case AC_PINCTL_VREF_100: item = 7; break; } } ucontrol->value.enumerated.item[0] = item; return 0;}static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = (hda_nid_t)kcontrol->private_value; static unsigned int ctls[] = { 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN, AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ, AC_PINCTL_IN_EN | AC_PINCTL_VREF_50, AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD, AC_PINCTL_IN_EN | AC_PINCTL_VREF_80, AC_PINCTL_IN_EN | AC_PINCTL_VREF_100, }; unsigned int old_ctl, new_ctl; old_ctl = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0); new_ctl = ctls[ucontrol->value.enumerated.item[0]]; if (old_ctl != new_ctl) { snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, new_ctl); snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, ucontrol->value.enumerated.item[0] >= 3 ? 0xb080 : 0xb000); return 1; } return 0;}static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo){ static char *texts[] = { "Front", "Surround", "CLFE", "Side" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 4; if (uinfo->value.enumerated.item >= 4) uinfo->value.enumerated.item = 3; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = (hda_nid_t)kcontrol->private_value; unsigned int sel; sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0); ucontrol->value.enumerated.item[0] = sel & 3; return 0;}static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct hda_codec *codec = snd_kcontrol_chip(kcontrol); hda_nid_t nid = (hda_nid_t)kcontrol->private_value; unsigned int sel; sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3; if (ucontrol->value.enumerated.item[0] != sel) { sel = ucontrol->value.enumerated.item[0] & 3; snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, sel); return 1; } return 0;}#define PIN_CTL_TEST(xname,nid) { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .info = alc_test_pin_ctl_info, \ .get = alc_test_pin_ctl_get, \ .put = alc_test_pin_ctl_put, \ .private_value = nid \ }#define PIN_SRC_TEST(xname,nid) { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ .name = xname, \ .info = alc_test_pin_src_info, \ .get = alc_test_pin_src_get, \ .put = alc_test_pin_src_put, \ .private_value = nid \ }static struct snd_kcontrol_new alc880_test_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT), HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT), HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), PIN_CTL_TEST("Front Pin Mode", 0x14), PIN_CTL_TEST("Surround Pin Mode", 0x15), PIN_CTL_TEST("CLFE Pin Mode", 0x16), PIN_CTL_TEST("Side Pin Mode", 0x17), PIN_CTL_TEST("In-1 Pin Mode", 0x18), PIN_CTL_TEST("In-2 Pin Mode", 0x19), PIN_CTL_TEST("In-3 Pin Mode", 0x1a), PIN_CTL_TEST("In-4 Pin Mode", 0x1b), PIN_SRC_TEST("In-1 Pin Source", 0x18), PIN_SRC_TEST("In-2 Pin Source", 0x19), PIN_SRC_TEST("In-3 Pin Source", 0x1a), PIN_SRC_TEST("In-4 Pin Source", 0x1b), HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT), HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT), HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT), HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT), HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT), HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT), HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT), HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT), {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -