aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
authorKailang Yang <kailang@realtek.com>2010-08-17 04:39:22 -0400
committerTakashi Iwai <tiwai@suse.de>2010-08-17 04:39:22 -0400
commitc69aefabe004d24e6eedf83b6f253647f77dfc43 (patch)
tree95367c68b4a57096a2bf96bba6c1d8a620e005aa /sound/pci/hda
parentc3e68fad88143fd1fe8fe640207fb19c0f087dbc (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>
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/patch_realtek.c176
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 */
19051static 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
19079static 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
19089static 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
19047static struct snd_kcontrol_new alc680_base_mixer[] = { 19100static 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
19057static struct snd_kcontrol_new alc680_capture_mixer[] = { 19112static 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
19122static 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
19132static 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 */
19070static struct hda_verb alc680_init_verbs[] = { 19141static 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 */
19166static 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
19177static 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
19194static 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
19203static 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 */
19091static int alc680_new_analog_output(struct alc_spec *spec, hda_nid_t nid, 19210static 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
19201static 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[] = {
19279static struct alc_config_preset alc680_presets[] = { 19391static 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;