diff options
Diffstat (limited to 'sound/pci/hda/patch_realtek.c')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 298 |
1 files changed, 242 insertions, 56 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4c6c9ec8ea5b..66bbdb60f50b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -52,6 +52,7 @@ enum { | |||
52 | ALC880_CLEVO, | 52 | ALC880_CLEVO, |
53 | ALC880_TCL_S700, | 53 | ALC880_TCL_S700, |
54 | ALC880_LG, | 54 | ALC880_LG, |
55 | ALC880_LG_LW, | ||
55 | #ifdef CONFIG_SND_DEBUG | 56 | #ifdef CONFIG_SND_DEBUG |
56 | ALC880_TEST, | 57 | ALC880_TEST, |
57 | #endif | 58 | #endif |
@@ -131,6 +132,7 @@ struct alc_spec { | |||
131 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ | 132 | hda_nid_t dig_in_nid; /* digital-in NID; optional */ |
132 | 133 | ||
133 | /* capture source */ | 134 | /* capture source */ |
135 | unsigned int num_mux_defs; | ||
134 | const struct hda_input_mux *input_mux; | 136 | const struct hda_input_mux *input_mux; |
135 | unsigned int cur_mux[3]; | 137 | unsigned int cur_mux[3]; |
136 | 138 | ||
@@ -172,6 +174,7 @@ struct alc_config_preset { | |||
172 | hda_nid_t dig_in_nid; | 174 | hda_nid_t dig_in_nid; |
173 | unsigned int num_channel_mode; | 175 | unsigned int num_channel_mode; |
174 | const struct hda_channel_mode *channel_mode; | 176 | const struct hda_channel_mode *channel_mode; |
177 | unsigned int num_mux_defs; | ||
175 | const struct hda_input_mux *input_mux; | 178 | const struct hda_input_mux *input_mux; |
176 | void (*unsol_event)(struct hda_codec *, unsigned int); | 179 | void (*unsol_event)(struct hda_codec *, unsigned int); |
177 | void (*init_hook)(struct hda_codec *); | 180 | void (*init_hook)(struct hda_codec *); |
@@ -185,7 +188,10 @@ static int alc_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ | |||
185 | { | 188 | { |
186 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 189 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
187 | struct alc_spec *spec = codec->spec; | 190 | struct alc_spec *spec = codec->spec; |
188 | return snd_hda_input_mux_info(spec->input_mux, uinfo); | 191 | unsigned int mux_idx = snd_ctl_get_ioffidx(kcontrol, &uinfo->id); |
192 | if (mux_idx >= spec->num_mux_defs) | ||
193 | mux_idx = 0; | ||
194 | return snd_hda_input_mux_info(&spec->input_mux[mux_idx], uinfo); | ||
189 | } | 195 | } |
190 | 196 | ||
191 | static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 197 | static int alc_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) |
@@ -203,7 +209,8 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
203 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 209 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
204 | struct alc_spec *spec = codec->spec; | 210 | struct alc_spec *spec = codec->spec; |
205 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 211 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
206 | return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, | 212 | unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx; |
213 | return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol, | ||
207 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); | 214 | spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]); |
208 | } | 215 | } |
209 | 216 | ||
@@ -245,7 +252,8 @@ static int alc_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_va | |||
245 | * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these | 252 | * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these |
246 | * are requested. Therefore order this list so that this behaviour will not | 253 | * are requested. Therefore order this list so that this behaviour will not |
247 | * cause problems when mixer clients move through the enum sequentially. | 254 | * cause problems when mixer clients move through the enum sequentially. |
248 | * NIDs 0x0f and 0x10 have been observed to have this behaviour. | 255 | * NIDs 0x0f and 0x10 have been observed to have this behaviour as of |
256 | * March 2006. | ||
249 | */ | 257 | */ |
250 | static char *alc_pin_mode_names[] = { | 258 | static char *alc_pin_mode_names[] = { |
251 | "Mic 50pc bias", "Mic 80pc bias", | 259 | "Mic 50pc bias", "Mic 80pc bias", |
@@ -255,19 +263,27 @@ static unsigned char alc_pin_mode_values[] = { | |||
255 | PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, | 263 | PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP, |
256 | }; | 264 | }; |
257 | /* The control can present all 5 options, or it can limit the options based | 265 | /* The control can present all 5 options, or it can limit the options based |
258 | * in the pin being assumed to be exclusively an input or an output pin. | 266 | * in the pin being assumed to be exclusively an input or an output pin. In |
267 | * addition, "input" pins may or may not process the mic bias option | ||
268 | * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to | ||
269 | * accept requests for bias as of chip versions up to March 2006) and/or | ||
270 | * wiring in the computer. | ||
259 | */ | 271 | */ |
260 | #define ALC_PIN_DIR_IN 0x00 | 272 | #define ALC_PIN_DIR_IN 0x00 |
261 | #define ALC_PIN_DIR_OUT 0x01 | 273 | #define ALC_PIN_DIR_OUT 0x01 |
262 | #define ALC_PIN_DIR_INOUT 0x02 | 274 | #define ALC_PIN_DIR_INOUT 0x02 |
275 | #define ALC_PIN_DIR_IN_NOMICBIAS 0x03 | ||
276 | #define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04 | ||
263 | 277 | ||
264 | /* Info about the pin modes supported by the three different pin directions. | 278 | /* Info about the pin modes supported by the different pin direction modes. |
265 | * For each direction the minimum and maximum values are given. | 279 | * For each direction the minimum and maximum values are given. |
266 | */ | 280 | */ |
267 | static signed char alc_pin_mode_dir_info[3][2] = { | 281 | static signed char alc_pin_mode_dir_info[5][2] = { |
268 | { 0, 2 }, /* ALC_PIN_DIR_IN */ | 282 | { 0, 2 }, /* ALC_PIN_DIR_IN */ |
269 | { 3, 4 }, /* ALC_PIN_DIR_OUT */ | 283 | { 3, 4 }, /* ALC_PIN_DIR_OUT */ |
270 | { 0, 4 }, /* ALC_PIN_DIR_INOUT */ | 284 | { 0, 4 }, /* ALC_PIN_DIR_INOUT */ |
285 | { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */ | ||
286 | { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */ | ||
271 | }; | 287 | }; |
272 | #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) | 288 | #define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0]) |
273 | #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) | 289 | #define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1]) |
@@ -329,9 +345,10 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
329 | * input modes. | 345 | * input modes. |
330 | * | 346 | * |
331 | * Dynamically switching the input/output buffers probably | 347 | * Dynamically switching the input/output buffers probably |
332 | * reduces noise slightly, particularly on input. However, | 348 | * reduces noise slightly (particularly on input) so we'll |
333 | * havingboth input and output buffers enabled | 349 | * do it. However, having both input and output buffers |
334 | * simultaneously doesn't seem to be problematic. | 350 | * enabled simultaneously doesn't seem to be problematic if |
351 | * this turns out to be necessary in the future. | ||
335 | */ | 352 | */ |
336 | if (val <= 2) { | 353 | if (val <= 2) { |
337 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, | 354 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -483,6 +500,9 @@ static void setup_preset(struct alc_spec *spec, const struct alc_config_preset * | |||
483 | spec->multiout.dig_out_nid = preset->dig_out_nid; | 500 | spec->multiout.dig_out_nid = preset->dig_out_nid; |
484 | spec->multiout.hp_nid = preset->hp_nid; | 501 | spec->multiout.hp_nid = preset->hp_nid; |
485 | 502 | ||
503 | spec->num_mux_defs = preset->num_mux_defs; | ||
504 | if (! spec->num_mux_defs) | ||
505 | spec->num_mux_defs = 1; | ||
486 | spec->input_mux = preset->input_mux; | 506 | spec->input_mux = preset->input_mux; |
487 | 507 | ||
488 | spec->num_adc_nids = preset->num_adc_nids; | 508 | spec->num_adc_nids = preset->num_adc_nids; |
@@ -1427,6 +1447,82 @@ static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1427 | } | 1447 | } |
1428 | 1448 | ||
1429 | /* | 1449 | /* |
1450 | * LG LW20 | ||
1451 | * | ||
1452 | * Pin assignment: | ||
1453 | * Speaker-out: 0x14 | ||
1454 | * Mic-In: 0x18 | ||
1455 | * Built-in Mic-In: 0x19 (?) | ||
1456 | * HP-Out: 0x1b | ||
1457 | * SPDIF-Out: 0x1e | ||
1458 | */ | ||
1459 | |||
1460 | /* seems analog CD is not working */ | ||
1461 | static struct hda_input_mux alc880_lg_lw_capture_source = { | ||
1462 | .num_items = 2, | ||
1463 | .items = { | ||
1464 | { "Mic", 0x0 }, | ||
1465 | { "Internal Mic", 0x1 }, | ||
1466 | }, | ||
1467 | }; | ||
1468 | |||
1469 | static struct snd_kcontrol_new alc880_lg_lw_mixer[] = { | ||
1470 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
1471 | HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT), | ||
1472 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
1473 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
1474 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
1475 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
1476 | { } /* end */ | ||
1477 | }; | ||
1478 | |||
1479 | static struct hda_verb alc880_lg_lw_init_verbs[] = { | ||
1480 | /* set capture source to mic-in */ | ||
1481 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1482 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1483 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
1484 | {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)}, | ||
1485 | /* speaker-out */ | ||
1486 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1487 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1488 | /* HP-out */ | ||
1489 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1490 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
1491 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1492 | /* mic-in to input */ | ||
1493 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1494 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1495 | /* built-in mic */ | ||
1496 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
1497 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
1498 | /* jack sense */ | ||
1499 | {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | 0x1}, | ||
1500 | { } | ||
1501 | }; | ||
1502 | |||
1503 | /* toggle speaker-output according to the hp-jack state */ | ||
1504 | static void alc880_lg_lw_automute(struct hda_codec *codec) | ||
1505 | { | ||
1506 | unsigned int present; | ||
1507 | |||
1508 | present = snd_hda_codec_read(codec, 0x1b, 0, | ||
1509 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
1510 | snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0, | ||
1511 | 0x80, present ? 0x80 : 0); | ||
1512 | snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0, | ||
1513 | 0x80, present ? 0x80 : 0); | ||
1514 | } | ||
1515 | |||
1516 | static void alc880_lg_lw_unsol_event(struct hda_codec *codec, unsigned int res) | ||
1517 | { | ||
1518 | /* Looks like the unsol event is incompatible with the standard | ||
1519 | * definition. 4bit tag is placed at 28 bit! | ||
1520 | */ | ||
1521 | if ((res >> 28) == 0x01) | ||
1522 | alc880_lg_lw_automute(codec); | ||
1523 | } | ||
1524 | |||
1525 | /* | ||
1430 | * Common callbacks | 1526 | * Common callbacks |
1431 | */ | 1527 | */ |
1432 | 1528 | ||
@@ -2078,6 +2174,9 @@ static struct hda_board_config alc880_cfg_tbl[] = { | |||
2078 | { .modelname = "lg", .config = ALC880_LG }, | 2174 | { .modelname = "lg", .config = ALC880_LG }, |
2079 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG }, | 2175 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG }, |
2080 | 2176 | ||
2177 | { .modelname = "lg-lw", .config = ALC880_LG_LW }, | ||
2178 | { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW }, | ||
2179 | |||
2081 | #ifdef CONFIG_SND_DEBUG | 2180 | #ifdef CONFIG_SND_DEBUG |
2082 | { .modelname = "test", .config = ALC880_TEST }, | 2181 | { .modelname = "test", .config = ALC880_TEST }, |
2083 | #endif | 2182 | #endif |
@@ -2268,6 +2367,19 @@ static struct alc_config_preset alc880_presets[] = { | |||
2268 | .unsol_event = alc880_lg_unsol_event, | 2367 | .unsol_event = alc880_lg_unsol_event, |
2269 | .init_hook = alc880_lg_automute, | 2368 | .init_hook = alc880_lg_automute, |
2270 | }, | 2369 | }, |
2370 | [ALC880_LG_LW] = { | ||
2371 | .mixers = { alc880_lg_lw_mixer }, | ||
2372 | .init_verbs = { alc880_volume_init_verbs, | ||
2373 | alc880_lg_lw_init_verbs }, | ||
2374 | .num_dacs = 1, | ||
2375 | .dac_nids = alc880_dac_nids, | ||
2376 | .dig_out_nid = ALC880_DIGOUT_NID, | ||
2377 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | ||
2378 | .channel_mode = alc880_2_jack_modes, | ||
2379 | .input_mux = &alc880_lg_lw_capture_source, | ||
2380 | .unsol_event = alc880_lg_lw_unsol_event, | ||
2381 | .init_hook = alc880_lg_lw_automute, | ||
2382 | }, | ||
2271 | #ifdef CONFIG_SND_DEBUG | 2383 | #ifdef CONFIG_SND_DEBUG |
2272 | [ALC880_TEST] = { | 2384 | [ALC880_TEST] = { |
2273 | .mixers = { alc880_test_mixer }, | 2385 | .mixers = { alc880_test_mixer }, |
@@ -2593,6 +2705,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
2593 | 2705 | ||
2594 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; | 2706 | spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs; |
2595 | 2707 | ||
2708 | spec->num_mux_defs = 1; | ||
2596 | spec->input_mux = &spec->private_imux; | 2709 | spec->input_mux = &spec->private_imux; |
2597 | 2710 | ||
2598 | return 1; | 2711 | return 1; |
@@ -2722,30 +2835,56 @@ static struct hda_input_mux alc260_capture_source = { | |||
2722 | }; | 2835 | }; |
2723 | 2836 | ||
2724 | /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, | 2837 | /* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack, |
2725 | * headphone jack and the internal CD lines. | 2838 | * headphone jack and the internal CD lines since these are the only pins at |
2839 | * which audio can appear. For flexibility, also allow the option of | ||
2840 | * recording the mixer output on the second ADC (ADC0 doesn't have a | ||
2841 | * connection to the mixer output). | ||
2726 | */ | 2842 | */ |
2727 | static struct hda_input_mux alc260_fujitsu_capture_source = { | 2843 | static struct hda_input_mux alc260_fujitsu_capture_sources[2] = { |
2728 | .num_items = 3, | 2844 | { |
2729 | .items = { | 2845 | .num_items = 3, |
2730 | { "Mic/Line", 0x0 }, | 2846 | .items = { |
2731 | { "CD", 0x4 }, | 2847 | { "Mic/Line", 0x0 }, |
2732 | { "Headphone", 0x2 }, | 2848 | { "CD", 0x4 }, |
2849 | { "Headphone", 0x2 }, | ||
2850 | }, | ||
2733 | }, | 2851 | }, |
2852 | { | ||
2853 | .num_items = 4, | ||
2854 | .items = { | ||
2855 | { "Mic/Line", 0x0 }, | ||
2856 | { "CD", 0x4 }, | ||
2857 | { "Headphone", 0x2 }, | ||
2858 | { "Mixer", 0x5 }, | ||
2859 | }, | ||
2860 | }, | ||
2861 | |||
2734 | }; | 2862 | }; |
2735 | 2863 | ||
2736 | /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configutation to | 2864 | /* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to |
2737 | * the Fujitsu S702x, but jacks are marked differently. We won't allow | 2865 | * the Fujitsu S702x, but jacks are marked differently. |
2738 | * retasking the Headphone jack, so it won't be available here. | ||
2739 | */ | 2866 | */ |
2740 | static struct hda_input_mux alc260_acer_capture_source = { | 2867 | static struct hda_input_mux alc260_acer_capture_sources[2] = { |
2741 | .num_items = 3, | 2868 | { |
2742 | .items = { | 2869 | .num_items = 4, |
2743 | { "Mic", 0x0 }, | 2870 | .items = { |
2744 | { "Line", 0x2 }, | 2871 | { "Mic", 0x0 }, |
2745 | { "CD", 0x4 }, | 2872 | { "Line", 0x2 }, |
2873 | { "CD", 0x4 }, | ||
2874 | { "Headphone", 0x5 }, | ||
2875 | }, | ||
2876 | }, | ||
2877 | { | ||
2878 | .num_items = 5, | ||
2879 | .items = { | ||
2880 | { "Mic", 0x0 }, | ||
2881 | { "Line", 0x2 }, | ||
2882 | { "CD", 0x4 }, | ||
2883 | { "Headphone", 0x6 }, | ||
2884 | { "Mixer", 0x5 }, | ||
2885 | }, | ||
2746 | }, | 2886 | }, |
2747 | }; | 2887 | }; |
2748 | |||
2749 | /* | 2888 | /* |
2750 | * This is just place-holder, so there's something for alc_build_pcms to look | 2889 | * This is just place-holder, so there's something for alc_build_pcms to look |
2751 | * at when it calculates the maximum number of channels. ALC260 has no mixer | 2890 | * at when it calculates the maximum number of channels. ALC260 has no mixer |
@@ -2806,6 +2945,9 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = { | |||
2806 | { } /* end */ | 2945 | { } /* end */ |
2807 | }; | 2946 | }; |
2808 | 2947 | ||
2948 | /* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12, | ||
2949 | * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10. | ||
2950 | */ | ||
2809 | static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | 2951 | static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { |
2810 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), | 2952 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT), |
2811 | HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), | 2953 | HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT), |
@@ -2822,9 +2964,28 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = { | |||
2822 | { } /* end */ | 2964 | { } /* end */ |
2823 | }; | 2965 | }; |
2824 | 2966 | ||
2967 | /* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current | ||
2968 | * versions of the ALC260 don't act on requests to enable mic bias from NID | ||
2969 | * 0x0f (used to drive the headphone jack in these laptops). The ALC260 | ||
2970 | * datasheet doesn't mention this restriction. At this stage it's not clear | ||
2971 | * whether this behaviour is intentional or is a hardware bug in chip | ||
2972 | * revisions available in early 2006. Therefore for now allow the | ||
2973 | * "Headphone Jack Mode" control to span all choices, but if it turns out | ||
2974 | * that the lack of mic bias for this NID is intentional we could change the | ||
2975 | * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
2976 | * | ||
2977 | * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006 | ||
2978 | * don't appear to make the mic bias available from the "line" jack, even | ||
2979 | * though the NID used for this jack (0x14) can supply it. The theory is | ||
2980 | * that perhaps Acer have included blocking capacitors between the ALC260 | ||
2981 | * and the output jack. If this turns out to be the case for all such | ||
2982 | * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT | ||
2983 | * to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
2984 | */ | ||
2825 | static struct snd_kcontrol_new alc260_acer_mixer[] = { | 2985 | static struct snd_kcontrol_new alc260_acer_mixer[] = { |
2826 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), | 2986 | HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), |
2827 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), | 2987 | HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), |
2988 | ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), | ||
2828 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), | 2989 | HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), |
2829 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), | 2990 | HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), |
2830 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), | 2991 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), |
@@ -3038,7 +3199,8 @@ static struct hda_verb alc260_hp_3013_init_verbs[] = { | |||
3038 | }; | 3199 | }; |
3039 | 3200 | ||
3040 | /* Initialisation sequence for ALC260 as configured in Fujitsu S702x | 3201 | /* Initialisation sequence for ALC260 as configured in Fujitsu S702x |
3041 | * laptops. | 3202 | * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD |
3203 | * audio = 0x16, internal speaker = 0x10. | ||
3042 | */ | 3204 | */ |
3043 | static struct hda_verb alc260_fujitsu_init_verbs[] = { | 3205 | static struct hda_verb alc260_fujitsu_init_verbs[] = { |
3044 | /* Disable all GPIOs */ | 3206 | /* Disable all GPIOs */ |
@@ -3185,10 +3347,10 @@ static struct hda_verb alc260_acer_init_verbs[] = { | |||
3185 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, | 3347 | {0x04, AC_VERB_SET_CONNECT_SEL, 0x00}, |
3186 | 3348 | ||
3187 | /* Do similar with the second ADC: mute capture input amp and | 3349 | /* Do similar with the second ADC: mute capture input amp and |
3188 | * set ADC connection to line (on line1 pin) | 3350 | * set ADC connection to mic to match ALSA's default state. |
3189 | */ | 3351 | */ |
3190 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | 3352 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, |
3191 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x02}, | 3353 | {0x05, AC_VERB_SET_CONNECT_SEL, 0x00}, |
3192 | 3354 | ||
3193 | /* Mute all inputs to mixer widget (even unconnected ones) */ | 3355 | /* Mute all inputs to mixer widget (even unconnected ones) */ |
3194 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ | 3356 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */ |
@@ -3213,26 +3375,35 @@ static hda_nid_t alc260_test_dac_nids[1] = { | |||
3213 | static hda_nid_t alc260_test_adc_nids[2] = { | 3375 | static hda_nid_t alc260_test_adc_nids[2] = { |
3214 | 0x04, 0x05, | 3376 | 0x04, 0x05, |
3215 | }; | 3377 | }; |
3216 | /* This is a bit messy since the two input muxes in the ALC260 have slight | 3378 | /* For testing the ALC260, each input MUX needs its own definition since |
3217 | * variations in their signal assignments. The ideal way to deal with this | 3379 | * the signal assignments are different. This assumes that the first ADC |
3218 | * is to extend alc_spec.input_mux to allow a different input MUX for each | 3380 | * is NID 0x04. |
3219 | * ADC. For the purposes of the test model it's sufficient to just list | ||
3220 | * both options for affected signal indices. The separate input mux | ||
3221 | * functionality only needs to be considered if a model comes along which | ||
3222 | * actually uses signals 0x5, 0x6 and 0x7 for something which makes sense to | ||
3223 | * record. | ||
3224 | */ | 3381 | */ |
3225 | static struct hda_input_mux alc260_test_capture_source = { | 3382 | static struct hda_input_mux alc260_test_capture_sources[2] = { |
3226 | .num_items = 8, | 3383 | { |
3227 | .items = { | 3384 | .num_items = 7, |
3228 | { "MIC1 pin", 0x0 }, | 3385 | .items = { |
3229 | { "MIC2 pin", 0x1 }, | 3386 | { "MIC1 pin", 0x0 }, |
3230 | { "LINE1 pin", 0x2 }, | 3387 | { "MIC2 pin", 0x1 }, |
3231 | { "LINE2 pin", 0x3 }, | 3388 | { "LINE1 pin", 0x2 }, |
3232 | { "CD pin", 0x4 }, | 3389 | { "LINE2 pin", 0x3 }, |
3233 | { "LINE-OUT pin (cap1), Mixer (cap2)", 0x5 }, | 3390 | { "CD pin", 0x4 }, |
3234 | { "HP-OUT pin (cap1), LINE-OUT pin (cap2)", 0x6 }, | 3391 | { "LINE-OUT pin", 0x5 }, |
3235 | { "HP-OUT pin (cap2 only)", 0x7 }, | 3392 | { "HP-OUT pin", 0x6 }, |
3393 | }, | ||
3394 | }, | ||
3395 | { | ||
3396 | .num_items = 8, | ||
3397 | .items = { | ||
3398 | { "MIC1 pin", 0x0 }, | ||
3399 | { "MIC2 pin", 0x1 }, | ||
3400 | { "LINE1 pin", 0x2 }, | ||
3401 | { "LINE2 pin", 0x3 }, | ||
3402 | { "CD pin", 0x4 }, | ||
3403 | { "Mixer", 0x5 }, | ||
3404 | { "LINE-OUT pin", 0x6 }, | ||
3405 | { "HP-OUT pin", 0x7 }, | ||
3406 | }, | ||
3236 | }, | 3407 | }, |
3237 | }; | 3408 | }; |
3238 | static struct snd_kcontrol_new alc260_test_mixer[] = { | 3409 | static struct snd_kcontrol_new alc260_test_mixer[] = { |
@@ -3244,7 +3415,17 @@ static struct snd_kcontrol_new alc260_test_mixer[] = { | |||
3244 | HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), | 3415 | HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT), |
3245 | HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), | 3416 | HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT), |
3246 | 3417 | ||
3247 | /* Modes for retasking pin widgets */ | 3418 | /* Modes for retasking pin widgets |
3419 | * Note: the ALC260 doesn't seem to act on requests to enable mic | ||
3420 | * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't | ||
3421 | * mention this restriction. At this stage it's not clear whether | ||
3422 | * this behaviour is intentional or is a hardware bug in chip | ||
3423 | * revisions available at least up until early 2006. Therefore for | ||
3424 | * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all | ||
3425 | * choices, but if it turns out that the lack of mic bias for these | ||
3426 | * NIDs is intentional we could change their modes from | ||
3427 | * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS. | ||
3428 | */ | ||
3248 | ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), | 3429 | ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT), |
3249 | ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), | 3430 | ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT), |
3250 | ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), | 3431 | ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT), |
@@ -3606,6 +3787,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec) | |||
3606 | 3787 | ||
3607 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; | 3788 | spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs; |
3608 | 3789 | ||
3790 | spec->num_mux_defs = 1; | ||
3609 | spec->input_mux = &spec->private_imux; | 3791 | spec->input_mux = &spec->private_imux; |
3610 | 3792 | ||
3611 | /* check whether NID 0x04 is valid */ | 3793 | /* check whether NID 0x04 is valid */ |
@@ -3711,7 +3893,8 @@ static struct alc_config_preset alc260_presets[] = { | |||
3711 | .adc_nids = alc260_dual_adc_nids, | 3893 | .adc_nids = alc260_dual_adc_nids, |
3712 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 3894 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
3713 | .channel_mode = alc260_modes, | 3895 | .channel_mode = alc260_modes, |
3714 | .input_mux = &alc260_fujitsu_capture_source, | 3896 | .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources), |
3897 | .input_mux = alc260_fujitsu_capture_sources, | ||
3715 | }, | 3898 | }, |
3716 | [ALC260_ACER] = { | 3899 | [ALC260_ACER] = { |
3717 | .mixers = { alc260_acer_mixer, | 3900 | .mixers = { alc260_acer_mixer, |
@@ -3723,7 +3906,8 @@ static struct alc_config_preset alc260_presets[] = { | |||
3723 | .adc_nids = alc260_dual_adc_nids, | 3906 | .adc_nids = alc260_dual_adc_nids, |
3724 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 3907 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
3725 | .channel_mode = alc260_modes, | 3908 | .channel_mode = alc260_modes, |
3726 | .input_mux = &alc260_acer_capture_source, | 3909 | .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources), |
3910 | .input_mux = alc260_acer_capture_sources, | ||
3727 | }, | 3911 | }, |
3728 | #ifdef CONFIG_SND_DEBUG | 3912 | #ifdef CONFIG_SND_DEBUG |
3729 | [ALC260_TEST] = { | 3913 | [ALC260_TEST] = { |
@@ -3736,7 +3920,8 @@ static struct alc_config_preset alc260_presets[] = { | |||
3736 | .adc_nids = alc260_test_adc_nids, | 3920 | .adc_nids = alc260_test_adc_nids, |
3737 | .num_channel_mode = ARRAY_SIZE(alc260_modes), | 3921 | .num_channel_mode = ARRAY_SIZE(alc260_modes), |
3738 | .channel_mode = alc260_modes, | 3922 | .channel_mode = alc260_modes, |
3739 | .input_mux = &alc260_test_capture_source, | 3923 | .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources), |
3924 | .input_mux = alc260_test_capture_sources, | ||
3740 | }, | 3925 | }, |
3741 | #endif | 3926 | #endif |
3742 | }; | 3927 | }; |
@@ -3828,7 +4013,6 @@ static struct hda_input_mux alc882_capture_source = { | |||
3828 | { "CD", 0x4 }, | 4013 | { "CD", 0x4 }, |
3829 | }, | 4014 | }, |
3830 | }; | 4015 | }; |
3831 | |||
3832 | #define alc882_mux_enum_info alc_mux_enum_info | 4016 | #define alc882_mux_enum_info alc_mux_enum_info |
3833 | #define alc882_mux_enum_get alc_mux_enum_get | 4017 | #define alc882_mux_enum_get alc_mux_enum_get |
3834 | 4018 | ||
@@ -4730,6 +4914,7 @@ static int alc262_parse_auto_config(struct hda_codec *codec) | |||
4730 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 4914 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; |
4731 | 4915 | ||
4732 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; | 4916 | spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs; |
4917 | spec->num_mux_defs = 1; | ||
4733 | spec->input_mux = &spec->private_imux; | 4918 | spec->input_mux = &spec->private_imux; |
4734 | 4919 | ||
4735 | return 1; | 4920 | return 1; |
@@ -5406,6 +5591,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
5406 | 5591 | ||
5407 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; | 5592 | spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs; |
5408 | 5593 | ||
5594 | spec->num_mux_defs = 1; | ||
5409 | spec->input_mux = &spec->private_imux; | 5595 | spec->input_mux = &spec->private_imux; |
5410 | 5596 | ||
5411 | spec->adc_nids = alc861_adc_nids; | 5597 | spec->adc_nids = alc861_adc_nids; |