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