diff options
| -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; |
