diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 179 |
1 files changed, 172 insertions, 7 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e5f8d3b699ec..f1cdce4c8a63 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -122,6 +122,8 @@ enum { | |||
122 | /* ALC269 models */ | 122 | /* ALC269 models */ |
123 | enum { | 123 | enum { |
124 | ALC269_BASIC, | 124 | ALC269_BASIC, |
125 | ALC269_ASUS_EEEPC_P703, | ||
126 | ALC269_ASUS_EEEPC_P901, | ||
125 | ALC269_AUTO, | 127 | ALC269_AUTO, |
126 | ALC269_MODEL_LAST /* last tag */ | 128 | ALC269_MODEL_LAST /* last tag */ |
127 | }; | 129 | }; |
@@ -10946,7 +10948,23 @@ static int patch_alc268(struct hda_codec *codec) | |||
10946 | 10948 | ||
10947 | static hda_nid_t alc269_adc_nids[1] = { | 10949 | static hda_nid_t alc269_adc_nids[1] = { |
10948 | /* ADC1 */ | 10950 | /* ADC1 */ |
10949 | 0x07, | 10951 | 0x08, |
10952 | }; | ||
10953 | |||
10954 | static struct hda_input_mux alc269_eeepc_dmic_capture_source = { | ||
10955 | .num_items = 2, | ||
10956 | .items = { | ||
10957 | { "i-Mic", 0x5 }, | ||
10958 | { "e-Mic", 0x0 }, | ||
10959 | }, | ||
10960 | }; | ||
10961 | |||
10962 | static struct hda_input_mux alc269_eeepc_amic_capture_source = { | ||
10963 | .num_items = 2, | ||
10964 | .items = { | ||
10965 | { "i-Mic", 0x1 }, | ||
10966 | { "e-Mic", 0x0 }, | ||
10967 | }, | ||
10950 | }; | 10968 | }; |
10951 | 10969 | ||
10952 | #define alc269_modes alc260_modes | 10970 | #define alc269_modes alc260_modes |
@@ -10968,10 +10986,27 @@ static struct snd_kcontrol_new alc269_base_mixer[] = { | |||
10968 | { } /* end */ | 10986 | { } /* end */ |
10969 | }; | 10987 | }; |
10970 | 10988 | ||
10989 | /* bind volumes of both NID 0x0c and 0x0d */ | ||
10990 | static struct hda_bind_ctls alc269_epc_bind_vol = { | ||
10991 | .ops = &snd_hda_bind_vol, | ||
10992 | .values = { | ||
10993 | HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT), | ||
10994 | HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT), | ||
10995 | 0 | ||
10996 | }, | ||
10997 | }; | ||
10998 | |||
10999 | static struct snd_kcontrol_new alc269_eeepc_mixer[] = { | ||
11000 | HDA_CODEC_MUTE("iSpeaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
11001 | HDA_BIND_VOL("LineOut Playback Volume", &alc269_epc_bind_vol), | ||
11002 | HDA_CODEC_MUTE("LineOut Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
11003 | { } /* end */ | ||
11004 | }; | ||
11005 | |||
10971 | /* capture mixer elements */ | 11006 | /* capture mixer elements */ |
10972 | static struct snd_kcontrol_new alc269_capture_mixer[] = { | 11007 | static struct snd_kcontrol_new alc269_capture_mixer[] = { |
10973 | HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT), | 11008 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), |
10974 | HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT), | 11009 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), |
10975 | { | 11010 | { |
10976 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 11011 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
10977 | /* The multiple "Capture Source" controls confuse alsamixer | 11012 | /* The multiple "Capture Source" controls confuse alsamixer |
@@ -10987,6 +11022,13 @@ static struct snd_kcontrol_new alc269_capture_mixer[] = { | |||
10987 | { } /* end */ | 11022 | { } /* end */ |
10988 | }; | 11023 | }; |
10989 | 11024 | ||
11025 | /* capture mixer elements */ | ||
11026 | static struct snd_kcontrol_new alc269_epc_capture_mixer[] = { | ||
11027 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
11028 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
11029 | { } /* end */ | ||
11030 | }; | ||
11031 | |||
10990 | /* | 11032 | /* |
10991 | * generic initialization of ADC, input mixers and output mixers | 11033 | * generic initialization of ADC, input mixers and output mixers |
10992 | */ | 11034 | */ |
@@ -10994,7 +11036,7 @@ static struct hda_verb alc269_init_verbs[] = { | |||
10994 | /* | 11036 | /* |
10995 | * Unmute ADC0 and set the default input to mic-in | 11037 | * Unmute ADC0 and set the default input to mic-in |
10996 | */ | 11038 | */ |
10997 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 11039 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
10998 | 11040 | ||
10999 | /* Mute input amps (PCBeep, Line In, Mic 1 & Mic 2) of the | 11041 | /* Mute input amps (PCBeep, Line In, Mic 1 & Mic 2) of the |
11000 | * analog-loopback mixer widget | 11042 | * analog-loopback mixer widget |
@@ -11057,6 +11099,98 @@ static struct hda_verb alc269_init_verbs[] = { | |||
11057 | { } | 11099 | { } |
11058 | }; | 11100 | }; |
11059 | 11101 | ||
11102 | static struct hda_verb alc269_eeepc_dmic_init_verbs[] = { | ||
11103 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
11104 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x05}, | ||
11105 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | ||
11106 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))}, | ||
11107 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
11108 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
11109 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
11110 | {} | ||
11111 | }; | ||
11112 | |||
11113 | static struct hda_verb alc269_eeepc_amic_init_verbs[] = { | ||
11114 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
11115 | {0x23, AC_VERB_SET_CONNECT_SEL, 0x01}, | ||
11116 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 }, | ||
11117 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))}, | ||
11118 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT}, | ||
11119 | {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT}, | ||
11120 | {} | ||
11121 | }; | ||
11122 | |||
11123 | /* toggle speaker-output according to the hp-jack state */ | ||
11124 | static void alc269_speaker_automute(struct hda_codec *codec) | ||
11125 | { | ||
11126 | unsigned int present; | ||
11127 | unsigned int bits; | ||
11128 | |||
11129 | present = snd_hda_codec_read(codec, 0x15, 0, | ||
11130 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
11131 | bits = present ? AMP_IN_MUTE(0) : 0; | ||
11132 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0, | ||
11133 | AMP_IN_MUTE(0), bits); | ||
11134 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | ||
11135 | AMP_IN_MUTE(0), bits); | ||
11136 | } | ||
11137 | |||
11138 | static void alc269_eeepc_dmic_automute(struct hda_codec *codec) | ||
11139 | { | ||
11140 | unsigned int present; | ||
11141 | |||
11142 | present = snd_hda_codec_read(codec, 0x18, 0, AC_VERB_GET_PIN_SENSE, 0) | ||
11143 | & AC_PINSENSE_PRESENCE; | ||
11144 | snd_hda_codec_write(codec, 0x23, 0, AC_VERB_SET_CONNECT_SEL, | ||
11145 | present ? 0 : 5); | ||
11146 | } | ||
11147 | |||
11148 | static void alc269_eeepc_amic_automute(struct hda_codec *codec) | ||
11149 | { | ||
11150 | unsigned int present; | ||
11151 | |||
11152 | present = snd_hda_codec_read(codec, 0x18, 0, AC_VERB_GET_PIN_SENSE, 0) | ||
11153 | & AC_PINSENSE_PRESENCE; | ||
11154 | snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
11155 | present ? AMP_IN_UNMUTE(0) : AMP_IN_MUTE(0)); | ||
11156 | snd_hda_codec_write(codec, 0x24, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
11157 | present ? AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1)); | ||
11158 | } | ||
11159 | |||
11160 | /* unsolicited event for HP jack sensing */ | ||
11161 | static void alc269_eeepc_dmic_unsol_event(struct hda_codec *codec, | ||
11162 | unsigned int res) | ||
11163 | { | ||
11164 | if ((res >> 26) == ALC880_HP_EVENT) | ||
11165 | alc269_speaker_automute(codec); | ||
11166 | |||
11167 | if ((res >> 26) == ALC880_MIC_EVENT) | ||
11168 | alc269_eeepc_dmic_automute(codec); | ||
11169 | } | ||
11170 | |||
11171 | static void alc269_eeepc_dmic_inithook(struct hda_codec *codec) | ||
11172 | { | ||
11173 | alc269_speaker_automute(codec); | ||
11174 | alc269_eeepc_dmic_automute(codec); | ||
11175 | } | ||
11176 | |||
11177 | /* unsolicited event for HP jack sensing */ | ||
11178 | static void alc269_eeepc_amic_unsol_event(struct hda_codec *codec, | ||
11179 | unsigned int res) | ||
11180 | { | ||
11181 | if ((res >> 26) == ALC880_HP_EVENT) | ||
11182 | alc269_speaker_automute(codec); | ||
11183 | |||
11184 | if ((res >> 26) == ALC880_MIC_EVENT) | ||
11185 | alc269_eeepc_amic_automute(codec); | ||
11186 | } | ||
11187 | |||
11188 | static void alc269_eeepc_amic_inithook(struct hda_codec *codec) | ||
11189 | { | ||
11190 | alc269_speaker_automute(codec); | ||
11191 | alc269_eeepc_amic_automute(codec); | ||
11192 | } | ||
11193 | |||
11060 | /* add playback controls from the parsed DAC table */ | 11194 | /* add playback controls from the parsed DAC table */ |
11061 | static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec, | 11195 | static int alc269_auto_create_multi_out_ctls(struct alc_spec *spec, |
11062 | const struct auto_pin_cfg *cfg) | 11196 | const struct auto_pin_cfg *cfg) |
@@ -11188,6 +11322,9 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
11188 | if (err < 0) | 11322 | if (err < 0) |
11189 | return err; | 11323 | return err; |
11190 | 11324 | ||
11325 | spec->mixers[spec->num_mixers] = alc269_capture_mixer; | ||
11326 | spec->num_mixers++; | ||
11327 | |||
11191 | return 1; | 11328 | return 1; |
11192 | } | 11329 | } |
11193 | 11330 | ||
@@ -11215,12 +11352,16 @@ static const char *alc269_models[ALC269_MODEL_LAST] = { | |||
11215 | }; | 11352 | }; |
11216 | 11353 | ||
11217 | static struct snd_pci_quirk alc269_cfg_tbl[] = { | 11354 | static struct snd_pci_quirk alc269_cfg_tbl[] = { |
11355 | SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A", | ||
11356 | ALC269_ASUS_EEEPC_P703), | ||
11357 | SND_PCI_QUIRK(0x1043, 0x831a, "ASUS Eeepc P901", | ||
11358 | ALC269_ASUS_EEEPC_P901), | ||
11218 | {} | 11359 | {} |
11219 | }; | 11360 | }; |
11220 | 11361 | ||
11221 | static struct alc_config_preset alc269_presets[] = { | 11362 | static struct alc_config_preset alc269_presets[] = { |
11222 | [ALC269_BASIC] = { | 11363 | [ALC269_BASIC] = { |
11223 | .mixers = { alc269_base_mixer }, | 11364 | .mixers = { alc269_base_mixer, alc269_capture_mixer }, |
11224 | .init_verbs = { alc269_init_verbs }, | 11365 | .init_verbs = { alc269_init_verbs }, |
11225 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | 11366 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), |
11226 | .dac_nids = alc269_dac_nids, | 11367 | .dac_nids = alc269_dac_nids, |
@@ -11229,6 +11370,32 @@ static struct alc_config_preset alc269_presets[] = { | |||
11229 | .channel_mode = alc269_modes, | 11370 | .channel_mode = alc269_modes, |
11230 | .input_mux = &alc269_capture_source, | 11371 | .input_mux = &alc269_capture_source, |
11231 | }, | 11372 | }, |
11373 | [ALC269_ASUS_EEEPC_P703] = { | ||
11374 | .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer }, | ||
11375 | .init_verbs = { alc269_init_verbs, | ||
11376 | alc269_eeepc_amic_init_verbs }, | ||
11377 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
11378 | .dac_nids = alc269_dac_nids, | ||
11379 | .hp_nid = 0x03, | ||
11380 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
11381 | .channel_mode = alc269_modes, | ||
11382 | .input_mux = &alc269_eeepc_amic_capture_source, | ||
11383 | .unsol_event = alc269_eeepc_amic_unsol_event, | ||
11384 | .init_hook = alc269_eeepc_amic_inithook, | ||
11385 | }, | ||
11386 | [ALC269_ASUS_EEEPC_P901] = { | ||
11387 | .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer}, | ||
11388 | .init_verbs = { alc269_init_verbs, | ||
11389 | alc269_eeepc_dmic_init_verbs }, | ||
11390 | .num_dacs = ARRAY_SIZE(alc269_dac_nids), | ||
11391 | .dac_nids = alc269_dac_nids, | ||
11392 | .hp_nid = 0x03, | ||
11393 | .num_channel_mode = ARRAY_SIZE(alc269_modes), | ||
11394 | .channel_mode = alc269_modes, | ||
11395 | .input_mux = &alc269_eeepc_dmic_capture_source, | ||
11396 | .unsol_event = alc269_eeepc_dmic_unsol_event, | ||
11397 | .init_hook = alc269_eeepc_dmic_inithook, | ||
11398 | }, | ||
11232 | }; | 11399 | }; |
11233 | 11400 | ||
11234 | static int patch_alc269(struct hda_codec *codec) | 11401 | static int patch_alc269(struct hda_codec *codec) |
@@ -11282,8 +11449,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
11282 | 11449 | ||
11283 | spec->adc_nids = alc269_adc_nids; | 11450 | spec->adc_nids = alc269_adc_nids; |
11284 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); | 11451 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); |
11285 | spec->mixers[spec->num_mixers] = alc269_capture_mixer; | ||
11286 | spec->num_mixers++; | ||
11287 | 11452 | ||
11288 | codec->patch_ops = alc_patch_ops; | 11453 | codec->patch_ops = alc_patch_ops; |
11289 | if (board_config == ALC269_AUTO) | 11454 | if (board_config == ALC269_AUTO) |