diff options
author | Kailang Yang <kailang@realtek.com> | 2010-08-17 04:39:22 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2010-08-17 04:39:22 -0400 |
commit | c69aefabe004d24e6eedf83b6f253647f77dfc43 (patch) | |
tree | 95367c68b4a57096a2bf96bba6c1d8a620e005aa | |
parent | c3e68fad88143fd1fe8fe640207fb19c0f087dbc (diff) |
ALSA: hda - Fix ALC680 base model capture
- Fix capture mixer elements for ALC680 base model
- Support auto change ADC for recording from MIC
- Cancel capture source assigned in auto mode.
Signed-off-by: Kailang Yang <kailang@realtek.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 176 |
1 files changed, 144 insertions, 32 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 2cd1ae809e46..a4dd04524e43 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -19030,6 +19030,7 @@ static int patch_alc888(struct hda_codec *codec) | |||
19030 | /* | 19030 | /* |
19031 | * ALC680 support | 19031 | * ALC680 support |
19032 | */ | 19032 | */ |
19033 | #define ALC680_DIGIN_NID ALC880_DIGIN_NID | ||
19033 | #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID | 19034 | #define ALC680_DIGOUT_NID ALC880_DIGOUT_NID |
19034 | #define alc680_modes alc260_modes | 19035 | #define alc680_modes alc260_modes |
19035 | 19036 | ||
@@ -19044,23 +19045,93 @@ static hda_nid_t alc680_adc_nids[3] = { | |||
19044 | 0x07, 0x08, 0x09 | 19045 | 0x07, 0x08, 0x09 |
19045 | }; | 19046 | }; |
19046 | 19047 | ||
19048 | /* | ||
19049 | * Analog capture ADC cgange | ||
19050 | */ | ||
19051 | static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
19052 | struct hda_codec *codec, | ||
19053 | unsigned int stream_tag, | ||
19054 | unsigned int format, | ||
19055 | struct snd_pcm_substream *substream) | ||
19056 | { | ||
19057 | struct alc_spec *spec = codec->spec; | ||
19058 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
19059 | unsigned int pre_mic, pre_line; | ||
19060 | |||
19061 | pre_mic = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); | ||
19062 | pre_line = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_LINE]); | ||
19063 | |||
19064 | spec->cur_adc_stream_tag = stream_tag; | ||
19065 | spec->cur_adc_format = format; | ||
19066 | |||
19067 | if (pre_mic || pre_line) { | ||
19068 | if (pre_mic) | ||
19069 | snd_hda_codec_setup_stream(codec, 0x08, stream_tag, 0, | ||
19070 | format); | ||
19071 | else | ||
19072 | snd_hda_codec_setup_stream(codec, 0x09, stream_tag, 0, | ||
19073 | format); | ||
19074 | } else | ||
19075 | snd_hda_codec_setup_stream(codec, 0x07, stream_tag, 0, format); | ||
19076 | return 0; | ||
19077 | } | ||
19078 | |||
19079 | static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
19080 | struct hda_codec *codec, | ||
19081 | struct snd_pcm_substream *substream) | ||
19082 | { | ||
19083 | snd_hda_codec_cleanup_stream(codec, 0x07); | ||
19084 | snd_hda_codec_cleanup_stream(codec, 0x08); | ||
19085 | snd_hda_codec_cleanup_stream(codec, 0x09); | ||
19086 | return 0; | ||
19087 | } | ||
19088 | |||
19089 | static struct hda_pcm_stream alc680_pcm_analog_auto_capture = { | ||
19090 | .substreams = 1, /* can be overridden */ | ||
19091 | .channels_min = 2, | ||
19092 | .channels_max = 2, | ||
19093 | /* NID is set in alc_build_pcms */ | ||
19094 | .ops = { | ||
19095 | .prepare = alc680_capture_pcm_prepare, | ||
19096 | .cleanup = alc680_capture_pcm_cleanup | ||
19097 | }, | ||
19098 | }; | ||
19099 | |||
19047 | static struct snd_kcontrol_new alc680_base_mixer[] = { | 19100 | static struct snd_kcontrol_new alc680_base_mixer[] = { |
19048 | /* output mixer control */ | 19101 | /* output mixer control */ |
19049 | HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), | 19102 | HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), |
19050 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | 19103 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), |
19051 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT), | 19104 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT), |
19052 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT), | 19105 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT), |
19106 | HDA_CODEC_VOLUME("Int Mic Boost", 0x12, 0, HDA_INPUT), | ||
19053 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | 19107 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), |
19108 | HDA_CODEC_VOLUME("Line In Boost", 0x19, 0, HDA_INPUT), | ||
19054 | { } | 19109 | { } |
19055 | }; | 19110 | }; |
19056 | 19111 | ||
19057 | static struct snd_kcontrol_new alc680_capture_mixer[] = { | 19112 | static struct hda_bind_ctls alc680_bind_cap_vol = { |
19058 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 19113 | .ops = &snd_hda_bind_vol, |
19059 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 19114 | .values = { |
19060 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT), | 19115 | HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT), |
19061 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT), | 19116 | HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT), |
19062 | HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT), | 19117 | HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT), |
19063 | HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT), | 19118 | 0 |
19119 | }, | ||
19120 | }; | ||
19121 | |||
19122 | static struct hda_bind_ctls alc680_bind_cap_switch = { | ||
19123 | .ops = &snd_hda_bind_sw, | ||
19124 | .values = { | ||
19125 | HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT), | ||
19126 | HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT), | ||
19127 | HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT), | ||
19128 | 0 | ||
19129 | }, | ||
19130 | }; | ||
19131 | |||
19132 | static struct snd_kcontrol_new alc680_master_capture_mixer[] = { | ||
19133 | HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol), | ||
19134 | HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch), | ||
19064 | { } /* end */ | 19135 | { } /* end */ |
19065 | }; | 19136 | }; |
19066 | 19137 | ||
@@ -19068,25 +19139,73 @@ static struct snd_kcontrol_new alc680_capture_mixer[] = { | |||
19068 | * generic initialization of ADC, input mixers and output mixers | 19139 | * generic initialization of ADC, input mixers and output mixers |
19069 | */ | 19140 | */ |
19070 | static struct hda_verb alc680_init_verbs[] = { | 19141 | static struct hda_verb alc680_init_verbs[] = { |
19071 | /* Unmute DAC0-1 and set vol = 0 */ | 19142 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
19072 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 19143 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
19073 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | 19144 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
19074 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
19075 | 19145 | ||
19076 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 19146 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, |
19077 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | 19147 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
19078 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, | 19148 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
19079 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | 19149 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
19080 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | 19150 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, |
19151 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
19081 | 19152 | ||
19082 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 19153 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
19083 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 19154 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
19084 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 19155 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
19085 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 19156 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
19086 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | 19157 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, |
19158 | |||
19159 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
19160 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, | ||
19161 | |||
19087 | { } | 19162 | { } |
19088 | }; | 19163 | }; |
19089 | 19164 | ||
19165 | /* toggle speaker-output according to the hp-jack state */ | ||
19166 | static void alc680_base_setup(struct hda_codec *codec) | ||
19167 | { | ||
19168 | struct alc_spec *spec = codec->spec; | ||
19169 | |||
19170 | spec->autocfg.hp_pins[0] = 0x16; | ||
19171 | spec->autocfg.speaker_pins[0] = 0x14; | ||
19172 | spec->autocfg.speaker_pins[1] = 0x15; | ||
19173 | spec->autocfg.input_pins[AUTO_PIN_MIC] = 0x18; | ||
19174 | spec->autocfg.input_pins[AUTO_PIN_LINE] = 0x19; | ||
19175 | } | ||
19176 | |||
19177 | static void alc680_rec_autoswitch(struct hda_codec *codec) | ||
19178 | { | ||
19179 | struct alc_spec *spec = codec->spec; | ||
19180 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
19181 | unsigned int present; | ||
19182 | hda_nid_t new_adc; | ||
19183 | |||
19184 | present = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); | ||
19185 | |||
19186 | new_adc = present ? 0x8 : 0x7; | ||
19187 | __snd_hda_codec_cleanup_stream(codec, !present ? 0x8 : 0x7, 1); | ||
19188 | snd_hda_codec_setup_stream(codec, new_adc, | ||
19189 | spec->cur_adc_stream_tag, 0, | ||
19190 | spec->cur_adc_format); | ||
19191 | |||
19192 | } | ||
19193 | |||
19194 | static void alc680_unsol_event(struct hda_codec *codec, | ||
19195 | unsigned int res) | ||
19196 | { | ||
19197 | if ((res >> 26) == ALC880_HP_EVENT) | ||
19198 | alc_automute_amp(codec); | ||
19199 | if ((res >> 26) == ALC880_MIC_EVENT) | ||
19200 | alc680_rec_autoswitch(codec); | ||
19201 | } | ||
19202 | |||
19203 | static void alc680_inithook(struct hda_codec *codec) | ||
19204 | { | ||
19205 | alc_automute_amp(codec); | ||
19206 | alc680_rec_autoswitch(codec); | ||
19207 | } | ||
19208 | |||
19090 | /* create input playback/capture controls for the given pin */ | 19209 | /* create input playback/capture controls for the given pin */ |
19091 | static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | 19210 | static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid, |
19092 | const char *ctlname, int idx) | 19211 | const char *ctlname, int idx) |
@@ -19197,13 +19316,7 @@ static void alc680_auto_init_hp_out(struct hda_codec *codec) | |||
19197 | #define alc680_pcm_analog_capture alc880_pcm_analog_capture | 19316 | #define alc680_pcm_analog_capture alc880_pcm_analog_capture |
19198 | #define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture | 19317 | #define alc680_pcm_analog_alt_capture alc880_pcm_analog_alt_capture |
19199 | #define alc680_pcm_digital_playback alc880_pcm_digital_playback | 19318 | #define alc680_pcm_digital_playback alc880_pcm_digital_playback |
19200 | 19319 | #define alc680_pcm_digital_capture alc880_pcm_digital_capture | |
19201 | static struct hda_input_mux alc680_capture_source = { | ||
19202 | .num_items = 1, | ||
19203 | .items = { | ||
19204 | { "Mic", 0x0 }, | ||
19205 | }, | ||
19206 | }; | ||
19207 | 19320 | ||
19208 | /* | 19321 | /* |
19209 | * BIOS auto configuration | 19322 | * BIOS auto configuration |
@@ -19218,6 +19331,7 @@ static int alc680_parse_auto_config(struct hda_codec *codec) | |||
19218 | alc680_ignore); | 19331 | alc680_ignore); |
19219 | if (err < 0) | 19332 | if (err < 0) |
19220 | return err; | 19333 | return err; |
19334 | |||
19221 | if (!spec->autocfg.line_outs) { | 19335 | if (!spec->autocfg.line_outs) { |
19222 | if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { | 19336 | if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) { |
19223 | spec->multiout.max_channels = 2; | 19337 | spec->multiout.max_channels = 2; |
@@ -19239,8 +19353,6 @@ static int alc680_parse_auto_config(struct hda_codec *codec) | |||
19239 | add_mixer(spec, spec->kctls.list); | 19353 | add_mixer(spec, spec->kctls.list); |
19240 | 19354 | ||
19241 | add_verb(spec, alc680_init_verbs); | 19355 | add_verb(spec, alc680_init_verbs); |
19242 | spec->num_mux_defs = 1; | ||
19243 | spec->input_mux = &alc680_capture_source; | ||
19244 | 19356 | ||
19245 | err = alc_auto_add_mic_boost(codec); | 19357 | err = alc_auto_add_mic_boost(codec); |
19246 | if (err < 0) | 19358 | if (err < 0) |
@@ -19279,17 +19391,17 @@ static struct snd_pci_quirk alc680_cfg_tbl[] = { | |||
19279 | static struct alc_config_preset alc680_presets[] = { | 19391 | static struct alc_config_preset alc680_presets[] = { |
19280 | [ALC680_BASE] = { | 19392 | [ALC680_BASE] = { |
19281 | .mixers = { alc680_base_mixer }, | 19393 | .mixers = { alc680_base_mixer }, |
19282 | .cap_mixer = alc680_capture_mixer, | 19394 | .cap_mixer = alc680_master_capture_mixer, |
19283 | .init_verbs = { alc680_init_verbs }, | 19395 | .init_verbs = { alc680_init_verbs }, |
19284 | .num_dacs = ARRAY_SIZE(alc680_dac_nids), | 19396 | .num_dacs = ARRAY_SIZE(alc680_dac_nids), |
19285 | .dac_nids = alc680_dac_nids, | 19397 | .dac_nids = alc680_dac_nids, |
19286 | .num_adc_nids = ARRAY_SIZE(alc680_adc_nids), | ||
19287 | .adc_nids = alc680_adc_nids, | ||
19288 | .hp_nid = 0x04, | ||
19289 | .dig_out_nid = ALC680_DIGOUT_NID, | 19398 | .dig_out_nid = ALC680_DIGOUT_NID, |
19290 | .num_channel_mode = ARRAY_SIZE(alc680_modes), | 19399 | .num_channel_mode = ARRAY_SIZE(alc680_modes), |
19291 | .channel_mode = alc680_modes, | 19400 | .channel_mode = alc680_modes, |
19292 | .input_mux = &alc680_capture_source, | 19401 | .unsol_event = alc680_unsol_event, |
19402 | .setup = alc680_base_setup, | ||
19403 | .init_hook = alc680_inithook, | ||
19404 | |||
19293 | }, | 19405 | }, |
19294 | }; | 19406 | }; |
19295 | 19407 | ||
@@ -19333,9 +19445,9 @@ static int patch_alc680(struct hda_codec *codec) | |||
19333 | setup_preset(codec, &alc680_presets[board_config]); | 19445 | setup_preset(codec, &alc680_presets[board_config]); |
19334 | 19446 | ||
19335 | spec->stream_analog_playback = &alc680_pcm_analog_playback; | 19447 | spec->stream_analog_playback = &alc680_pcm_analog_playback; |
19336 | spec->stream_analog_capture = &alc680_pcm_analog_capture; | 19448 | spec->stream_analog_capture = &alc680_pcm_analog_auto_capture; |
19337 | spec->stream_analog_alt_capture = &alc680_pcm_analog_alt_capture; | ||
19338 | spec->stream_digital_playback = &alc680_pcm_digital_playback; | 19449 | spec->stream_digital_playback = &alc680_pcm_digital_playback; |
19450 | spec->stream_digital_capture = &alc680_pcm_digital_capture; | ||
19339 | 19451 | ||
19340 | if (!spec->adc_nids) { | 19452 | if (!spec->adc_nids) { |
19341 | spec->adc_nids = alc680_adc_nids; | 19453 | spec->adc_nids = alc680_adc_nids; |