diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-09-20 11:10:27 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-09-23 04:47:38 -0400 |
commit | eb06ed8f4c2440558ebf465e8baeac6367d90201 (patch) | |
tree | 60501d5c4e918f96d26033b95373f4368ca929e2 /sound/pci | |
parent | 33ef765131bcf82bc5fca3f25d8313fa4df93ce0 (diff) |
[ALSA] hda-codec - Support multiple headphone pins
Some machines have multiple headpohne pins (usually on the lpatop
and on the docking station) while the current hda-codec driver
assumes a single headphone pin. Now it supports multiple hp pins
(at least for detection).
The sigmatel 92xx code supports this new multiple hp pins.
It detects all hp pins for auto-muting, too.
Also, the driver checks speaker pins in addition. In some cases,
all line-out, speaker and hp-pins coexist.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 23 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 4 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 18 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 202 |
5 files changed, 164 insertions, 86 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 8b2c080c85ae..07360996caaa 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2012,7 +2012,7 @@ static int is_in_nid_list(hda_nid_t nid, hda_nid_t *list) | |||
2012 | * in the order of front, rear, CLFE, side, ... | 2012 | * in the order of front, rear, CLFE, side, ... |
2013 | * | 2013 | * |
2014 | * If more extra outputs (speaker and headphone) are found, the pins are | 2014 | * If more extra outputs (speaker and headphone) are found, the pins are |
2015 | * assisnged to hp_pin and speaker_pins[], respectively. If no line-out jack | 2015 | * assisnged to hp_pins[] and speaker_pins[], respectively. If no line-out jack |
2016 | * is detected, one of speaker of HP pins is assigned as the primary | 2016 | * is detected, one of speaker of HP pins is assigned as the primary |
2017 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 2017 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
2018 | * if any analog output exists. | 2018 | * if any analog output exists. |
@@ -2074,7 +2074,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2074 | cfg->speaker_outs++; | 2074 | cfg->speaker_outs++; |
2075 | break; | 2075 | break; |
2076 | case AC_JACK_HP_OUT: | 2076 | case AC_JACK_HP_OUT: |
2077 | cfg->hp_pin = nid; | 2077 | if (cfg->hp_outs >= ARRAY_SIZE(cfg->hp_pins)) |
2078 | continue; | ||
2079 | cfg->hp_pins[cfg->hp_outs] = nid; | ||
2080 | cfg->hp_outs++; | ||
2078 | break; | 2081 | break; |
2079 | case AC_JACK_MIC_IN: | 2082 | case AC_JACK_MIC_IN: |
2080 | if (loc == AC_JACK_LOC_FRONT) | 2083 | if (loc == AC_JACK_LOC_FRONT) |
@@ -2147,8 +2150,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2147 | cfg->speaker_outs, cfg->speaker_pins[0], | 2150 | cfg->speaker_outs, cfg->speaker_pins[0], |
2148 | cfg->speaker_pins[1], cfg->speaker_pins[2], | 2151 | cfg->speaker_pins[1], cfg->speaker_pins[2], |
2149 | cfg->speaker_pins[3], cfg->speaker_pins[4]); | 2152 | cfg->speaker_pins[3], cfg->speaker_pins[4]); |
2150 | snd_printd(" hp=0x%x, dig_out=0x%x, din_in=0x%x\n", | 2153 | snd_printd(" hp_outs=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
2151 | cfg->hp_pin, cfg->dig_out_pin, cfg->dig_in_pin); | 2154 | cfg->hp_outs, cfg->hp_pins[0], |
2155 | cfg->hp_pins[1], cfg->hp_pins[2], | ||
2156 | cfg->hp_pins[3], cfg->hp_pins[4]); | ||
2152 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 2157 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," |
2153 | " cd=0x%x, aux=0x%x\n", | 2158 | " cd=0x%x, aux=0x%x\n", |
2154 | cfg->input_pins[AUTO_PIN_MIC], | 2159 | cfg->input_pins[AUTO_PIN_MIC], |
@@ -2169,10 +2174,12 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2169 | sizeof(cfg->speaker_pins)); | 2174 | sizeof(cfg->speaker_pins)); |
2170 | cfg->speaker_outs = 0; | 2175 | cfg->speaker_outs = 0; |
2171 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | 2176 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); |
2172 | } else if (cfg->hp_pin) { | 2177 | } else if (cfg->hp_outs) { |
2173 | cfg->line_outs = 1; | 2178 | cfg->line_outs = cfg->hp_outs; |
2174 | cfg->line_out_pins[0] = cfg->hp_pin; | 2179 | memcpy(cfg->line_out_pins, cfg->hp_pins, |
2175 | cfg->hp_pin = 0; | 2180 | sizeof(cfg->hp_pins)); |
2181 | cfg->hp_outs = 0; | ||
2182 | memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins)); | ||
2176 | } | 2183 | } |
2177 | } | 2184 | } |
2178 | 2185 | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index ff24266fe353..f9416c36396e 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -229,7 +229,8 @@ struct auto_pin_cfg { | |||
229 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ | 229 | hda_nid_t line_out_pins[5]; /* sorted in the order of Front/Surr/CLFE/Side */ |
230 | int speaker_outs; | 230 | int speaker_outs; |
231 | hda_nid_t speaker_pins[5]; | 231 | hda_nid_t speaker_pins[5]; |
232 | hda_nid_t hp_pin; | 232 | int hp_outs; |
233 | hda_nid_t hp_pins[5]; | ||
233 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 234 | hda_nid_t input_pins[AUTO_PIN_LAST]; |
234 | hda_nid_t dig_out_pin; | 235 | hda_nid_t dig_out_pin; |
235 | hda_nid_t dig_in_pin; | 236 | hda_nid_t dig_in_pin; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 71abc2aa61a6..511df07fa2a3 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -2471,7 +2471,7 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) | |||
2471 | pin = spec->autocfg.speaker_pins[0]; | 2471 | pin = spec->autocfg.speaker_pins[0]; |
2472 | if (pin) /* connect to front */ | 2472 | if (pin) /* connect to front */ |
2473 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2473 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
2474 | pin = spec->autocfg.hp_pin; | 2474 | pin = spec->autocfg.hp_pins[0]; |
2475 | if (pin) /* connect to front */ | 2475 | if (pin) /* connect to front */ |
2476 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 2476 | ad1988_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
2477 | } | 2477 | } |
@@ -2523,7 +2523,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
2523 | (err = ad1988_auto_create_extra_out(codec, | 2523 | (err = ad1988_auto_create_extra_out(codec, |
2524 | spec->autocfg.speaker_pins[0], | 2524 | spec->autocfg.speaker_pins[0], |
2525 | "Speaker")) < 0 || | 2525 | "Speaker")) < 0 || |
2526 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pin, | 2526 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], |
2527 | "Headphone")) < 0 || | 2527 | "Headphone")) < 0 || |
2528 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2528 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
2529 | return err; | 2529 | return err; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index ba9e050e2012..d08d2e399c8f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -2753,7 +2753,7 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) | |||
2753 | pin = spec->autocfg.speaker_pins[0]; | 2753 | pin = spec->autocfg.speaker_pins[0]; |
2754 | if (pin) /* connect to front */ | 2754 | if (pin) /* connect to front */ |
2755 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); | 2755 | alc880_auto_set_output_and_unmute(codec, pin, PIN_OUT, 0); |
2756 | pin = spec->autocfg.hp_pin; | 2756 | pin = spec->autocfg.hp_pins[0]; |
2757 | if (pin) /* connect to front */ | 2757 | if (pin) /* connect to front */ |
2758 | alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 2758 | alc880_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
2759 | } | 2759 | } |
@@ -2794,7 +2794,7 @@ static int alc880_parse_auto_config(struct hda_codec *codec) | |||
2794 | (err = alc880_auto_create_extra_out(spec, | 2794 | (err = alc880_auto_create_extra_out(spec, |
2795 | spec->autocfg.speaker_pins[0], | 2795 | spec->autocfg.speaker_pins[0], |
2796 | "Speaker")) < 0 || | 2796 | "Speaker")) < 0 || |
2797 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pin, | 2797 | (err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0], |
2798 | "Headphone")) < 0 || | 2798 | "Headphone")) < 0 || |
2799 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 2799 | (err = alc880_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
2800 | return err; | 2800 | return err; |
@@ -3736,7 +3736,7 @@ static int alc260_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
3736 | return err; | 3736 | return err; |
3737 | } | 3737 | } |
3738 | 3738 | ||
3739 | nid = cfg->hp_pin; | 3739 | nid = cfg->hp_pins[0]; |
3740 | if (nid) { | 3740 | if (nid) { |
3741 | err = alc260_add_playback_controls(spec, nid, "Headphone"); | 3741 | err = alc260_add_playback_controls(spec, nid, "Headphone"); |
3742 | if (err < 0) | 3742 | if (err < 0) |
@@ -3806,7 +3806,7 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
3806 | if (nid) | 3806 | if (nid) |
3807 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3807 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
3808 | 3808 | ||
3809 | nid = spec->autocfg.hp_pin; | 3809 | nid = spec->autocfg.hp_pins[0]; |
3810 | if (nid) | 3810 | if (nid) |
3811 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); | 3811 | alc260_auto_set_output_and_unmute(codec, nid, PIN_OUT, 0); |
3812 | } | 3812 | } |
@@ -4526,7 +4526,7 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
4526 | struct alc_spec *spec = codec->spec; | 4526 | struct alc_spec *spec = codec->spec; |
4527 | hda_nid_t pin; | 4527 | hda_nid_t pin; |
4528 | 4528 | ||
4529 | pin = spec->autocfg.hp_pin; | 4529 | pin = spec->autocfg.hp_pins[0]; |
4530 | if (pin) /* connect to front */ | 4530 | if (pin) /* connect to front */ |
4531 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ | 4531 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); /* use dac 0 */ |
4532 | } | 4532 | } |
@@ -5207,7 +5207,7 @@ static void alc883_auto_init_hp_out(struct hda_codec *codec) | |||
5207 | struct alc_spec *spec = codec->spec; | 5207 | struct alc_spec *spec = codec->spec; |
5208 | hda_nid_t pin; | 5208 | hda_nid_t pin; |
5209 | 5209 | ||
5210 | pin = spec->autocfg.hp_pin; | 5210 | pin = spec->autocfg.hp_pins[0]; |
5211 | if (pin) /* connect to front */ | 5211 | if (pin) /* connect to front */ |
5212 | /* use dac 0 */ | 5212 | /* use dac 0 */ |
5213 | alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); | 5213 | alc883_auto_set_output_and_unmute(codec, pin, PIN_HP, 0); |
@@ -5630,7 +5630,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, const struct | |||
5630 | return err; | 5630 | return err; |
5631 | } | 5631 | } |
5632 | } | 5632 | } |
5633 | nid = cfg->hp_pin; | 5633 | nid = cfg->hp_pins[0]; |
5634 | if (nid) { | 5634 | if (nid) { |
5635 | /* spec->multiout.hp_nid = 2; */ | 5635 | /* spec->multiout.hp_nid = 2; */ |
5636 | if (nid == 0x16) { | 5636 | if (nid == 0x16) { |
@@ -6630,7 +6630,7 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) | |||
6630 | struct alc_spec *spec = codec->spec; | 6630 | struct alc_spec *spec = codec->spec; |
6631 | hda_nid_t pin; | 6631 | hda_nid_t pin; |
6632 | 6632 | ||
6633 | pin = spec->autocfg.hp_pin; | 6633 | pin = spec->autocfg.hp_pins[0]; |
6634 | if (pin) /* connect to front */ | 6634 | if (pin) /* connect to front */ |
6635 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); | 6635 | alc861_auto_set_output_and_unmute(codec, pin, PIN_HP, spec->multiout.dac_nids[0]); |
6636 | } | 6636 | } |
@@ -6665,7 +6665,7 @@ static int alc861_parse_auto_config(struct hda_codec *codec) | |||
6665 | 6665 | ||
6666 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || | 6666 | if ((err = alc861_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 || |
6667 | (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || | 6667 | (err = alc861_auto_create_multi_out_ctls(spec, &spec->autocfg)) < 0 || |
6668 | (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pin)) < 0 || | 6668 | (err = alc861_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0])) < 0 || |
6669 | (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 6669 | (err = alc861_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) |
6670 | return err; | 6670 | return err; |
6671 | 6671 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index bcbbe111ab95..7cc064265204 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -1011,11 +1011,29 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | |||
1011 | return 0; | 1011 | return 0; |
1012 | } | 1012 | } |
1013 | 1013 | ||
1014 | /* create volume control/switch for the given prefx type */ | ||
1015 | static int create_controls(struct sigmatel_spec *spec, const char *pfx, hda_nid_t nid, int chs) | ||
1016 | { | ||
1017 | char name[32]; | ||
1018 | int err; | ||
1019 | |||
1020 | sprintf(name, "%s Playback Volume", pfx); | ||
1021 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | ||
1022 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
1023 | if (err < 0) | ||
1024 | return err; | ||
1025 | sprintf(name, "%s Playback Switch", pfx); | ||
1026 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | ||
1027 | HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT)); | ||
1028 | if (err < 0) | ||
1029 | return err; | ||
1030 | return 0; | ||
1031 | } | ||
1032 | |||
1014 | /* add playback controls from the parsed DAC table */ | 1033 | /* add playback controls from the parsed DAC table */ |
1015 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | 1034 | static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, |
1016 | const struct auto_pin_cfg *cfg) | 1035 | const struct auto_pin_cfg *cfg) |
1017 | { | 1036 | { |
1018 | char name[32]; | ||
1019 | static const char *chname[4] = { | 1037 | static const char *chname[4] = { |
1020 | "Front", "Surround", NULL /*CLFE*/, "Side" | 1038 | "Front", "Surround", NULL /*CLFE*/, "Side" |
1021 | }; | 1039 | }; |
@@ -1030,26 +1048,15 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
1030 | 1048 | ||
1031 | if (i == 2) { | 1049 | if (i == 2) { |
1032 | /* Center/LFE */ | 1050 | /* Center/LFE */ |
1033 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Center Playback Volume", | 1051 | err = create_controls(spec, "Center", nid, 1); |
1034 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | 1052 | if (err < 0) |
1035 | return err; | 1053 | return err; |
1036 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "LFE Playback Volume", | 1054 | err = create_controls(spec, "LFE", nid, 2); |
1037 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | 1055 | if (err < 0) |
1038 | return err; | ||
1039 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Center Playback Switch", | ||
1040 | HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT))) < 0) | ||
1041 | return err; | ||
1042 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "LFE Playback Switch", | ||
1043 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT))) < 0) | ||
1044 | return err; | 1056 | return err; |
1045 | } else { | 1057 | } else { |
1046 | sprintf(name, "%s Playback Volume", chname[i]); | 1058 | err = create_controls(spec, chname[i], nid, 3); |
1047 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, name, | 1059 | if (err < 0) |
1048 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
1049 | return err; | ||
1050 | sprintf(name, "%s Playback Switch", chname[i]); | ||
1051 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, name, | ||
1052 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | ||
1053 | return err; | 1060 | return err; |
1054 | } | 1061 | } |
1055 | } | 1062 | } |
@@ -1065,39 +1072,85 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec, | |||
1065 | return 0; | 1072 | return 0; |
1066 | } | 1073 | } |
1067 | 1074 | ||
1068 | /* add playback controls for HP output */ | 1075 | static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) |
1069 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, struct auto_pin_cfg *cfg) | ||
1070 | { | 1076 | { |
1071 | struct sigmatel_spec *spec = codec->spec; | 1077 | int i; |
1072 | hda_nid_t pin = cfg->hp_pin; | ||
1073 | hda_nid_t nid; | ||
1074 | int i, err; | ||
1075 | unsigned int wid_caps; | ||
1076 | 1078 | ||
1077 | if (! pin) | 1079 | for (i = 0; i < spec->multiout.num_dacs; i++) { |
1078 | return 0; | 1080 | if (spec->multiout.dac_nids[i] == nid) |
1081 | return 1; | ||
1082 | } | ||
1083 | if (spec->multiout.hp_nid == nid) | ||
1084 | return 1; | ||
1085 | return 0; | ||
1086 | } | ||
1079 | 1087 | ||
1080 | wid_caps = get_wcaps(codec, pin); | 1088 | static int add_spec_dacs(struct sigmatel_spec *spec, hda_nid_t nid) |
1081 | if (wid_caps & AC_WCAP_UNSOL_CAP) | 1089 | { |
1082 | spec->hp_detect = 1; | 1090 | if (!spec->multiout.hp_nid) |
1091 | spec->multiout.hp_nid = nid; | ||
1092 | else if (spec->multiout.num_dacs > 4) { | ||
1093 | printk(KERN_WARNING "stac92xx: No space for DAC 0x%x\n", nid); | ||
1094 | return 1; | ||
1095 | } else { | ||
1096 | spec->multiout.dac_nids[spec->multiout.num_dacs] = nid; | ||
1097 | spec->multiout.num_dacs++; | ||
1098 | } | ||
1099 | return 0; | ||
1100 | } | ||
1083 | 1101 | ||
1084 | nid = snd_hda_codec_read(codec, pin, 0, AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | 1102 | /* add playback controls for Speaker and HP outputs */ |
1085 | for (i = 0; i < cfg->line_outs; i++) { | 1103 | static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, |
1086 | if (! spec->multiout.dac_nids[i]) | 1104 | struct auto_pin_cfg *cfg) |
1105 | { | ||
1106 | struct sigmatel_spec *spec = codec->spec; | ||
1107 | hda_nid_t nid; | ||
1108 | int i, old_num_dacs, err; | ||
1109 | |||
1110 | old_num_dacs = spec->multiout.num_dacs; | ||
1111 | for (i = 0; i < cfg->hp_outs; i++) { | ||
1112 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); | ||
1113 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
1114 | spec->hp_detect = 1; | ||
1115 | nid = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | ||
1116 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
1117 | if (check_in_dac_nids(spec, nid)) | ||
1118 | nid = 0; | ||
1119 | if (! nid) | ||
1087 | continue; | 1120 | continue; |
1088 | if (spec->multiout.dac_nids[i] == nid) | 1121 | add_spec_dacs(spec, nid); |
1089 | return 0; | 1122 | } |
1123 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
1124 | nid = snd_hda_codec_read(codec, cfg->speaker_pins[0], 0, | ||
1125 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
1126 | if (check_in_dac_nids(spec, nid)) | ||
1127 | nid = 0; | ||
1128 | if (check_in_dac_nids(spec, nid)) | ||
1129 | nid = 0; | ||
1130 | if (! nid) | ||
1131 | continue; | ||
1132 | add_spec_dacs(spec, nid); | ||
1090 | } | 1133 | } |
1091 | 1134 | ||
1092 | spec->multiout.hp_nid = nid; | 1135 | for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { |
1093 | 1136 | static const char *pfxs[] = { | |
1094 | /* control HP volume/switch on the output mixer amp */ | 1137 | "Speaker", "External Speaker", "Speaker2", |
1095 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, "Headphone Playback Volume", | 1138 | }; |
1096 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 1139 | err = create_controls(spec, pfxs[i - old_num_dacs], |
1097 | return err; | 1140 | spec->multiout.dac_nids[i], 3); |
1098 | if ((err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, "Headphone Playback Switch", | 1141 | if (err < 0) |
1099 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT))) < 0) | 1142 | return err; |
1100 | return err; | 1143 | } |
1144 | if (spec->multiout.hp_nid) { | ||
1145 | const char *pfx; | ||
1146 | if (old_num_dacs == spec->multiout.num_dacs) | ||
1147 | pfx = "Master"; | ||
1148 | else | ||
1149 | pfx = "Headphone"; | ||
1150 | err = create_controls(spec, pfx, spec->multiout.hp_nid, 3); | ||
1151 | if (err < 0) | ||
1152 | return err; | ||
1153 | } | ||
1101 | 1154 | ||
1102 | return 0; | 1155 | return 0; |
1103 | } | 1156 | } |
@@ -1160,11 +1213,20 @@ static void stac92xx_auto_init_multi_out(struct hda_codec *codec) | |||
1160 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | 1213 | static void stac92xx_auto_init_hp_out(struct hda_codec *codec) |
1161 | { | 1214 | { |
1162 | struct sigmatel_spec *spec = codec->spec; | 1215 | struct sigmatel_spec *spec = codec->spec; |
1163 | hda_nid_t pin; | 1216 | int i; |
1164 | 1217 | ||
1165 | pin = spec->autocfg.hp_pin; | 1218 | for (i = 0; i < spec->autocfg.hp_outs; i++) { |
1166 | if (pin) /* connect to front */ | 1219 | hda_nid_t pin; |
1167 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | 1220 | pin = spec->autocfg.hp_pins[i]; |
1221 | if (pin) /* connect to front */ | ||
1222 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN); | ||
1223 | } | ||
1224 | for (i = 0; i < spec->autocfg.speaker_outs; i++) { | ||
1225 | hda_nid_t pin; | ||
1226 | pin = spec->autocfg.speaker_pins[i]; | ||
1227 | if (pin) /* connect to front */ | ||
1228 | stac92xx_auto_set_pinctl(codec, pin, AC_PINCTL_OUT_EN); | ||
1229 | } | ||
1168 | } | 1230 | } |
1169 | 1231 | ||
1170 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) | 1232 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) |
@@ -1210,7 +1272,7 @@ static int stac9200_auto_create_hp_ctls(struct hda_codec *codec, | |||
1210 | struct auto_pin_cfg *cfg) | 1272 | struct auto_pin_cfg *cfg) |
1211 | { | 1273 | { |
1212 | struct sigmatel_spec *spec = codec->spec; | 1274 | struct sigmatel_spec *spec = codec->spec; |
1213 | hda_nid_t pin = cfg->hp_pin; | 1275 | hda_nid_t pin = cfg->hp_pins[0]; |
1214 | unsigned int wid_caps; | 1276 | unsigned int wid_caps; |
1215 | 1277 | ||
1216 | if (! pin) | 1278 | if (! pin) |
@@ -1266,16 +1328,7 @@ static int stac9200_auto_create_lfe_ctls(struct hda_codec *codec, | |||
1266 | } | 1328 | } |
1267 | 1329 | ||
1268 | if (lfe_pin) { | 1330 | if (lfe_pin) { |
1269 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_VOL, | 1331 | err = create_controls(spec, "LFE", lfe_pin, 1); |
1270 | "LFE Playback Volume", | ||
1271 | HDA_COMPOSE_AMP_VAL(lfe_pin, 1, 0, | ||
1272 | HDA_OUTPUT)); | ||
1273 | if (err < 0) | ||
1274 | return err; | ||
1275 | err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, | ||
1276 | "LFE Playback Switch", | ||
1277 | HDA_COMPOSE_AMP_VAL(lfe_pin, 1, 0, | ||
1278 | HDA_OUTPUT)); | ||
1279 | if (err < 0) | 1332 | if (err < 0) |
1280 | return err; | 1333 | return err; |
1281 | } | 1334 | } |
@@ -1363,9 +1416,11 @@ static int stac92xx_init(struct hda_codec *codec) | |||
1363 | /* set up pins */ | 1416 | /* set up pins */ |
1364 | if (spec->hp_detect) { | 1417 | if (spec->hp_detect) { |
1365 | /* Enable unsolicited responses on the HP widget */ | 1418 | /* Enable unsolicited responses on the HP widget */ |
1366 | snd_hda_codec_write(codec, cfg->hp_pin, 0, | 1419 | for (i = 0; i < cfg->hp_outs; i++) |
1367 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1420 | if (get_wcaps(codec, cfg->hp_pins[i]) & AC_WCAP_UNSOL_CAP) |
1368 | STAC_UNSOL_ENABLE); | 1421 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, |
1422 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1423 | STAC_UNSOL_ENABLE); | ||
1369 | /* fake event to set up pins */ | 1424 | /* fake event to set up pins */ |
1370 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 1425 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); |
1371 | /* enable the headphones by default. If/when unsol_event detection works, this will be ignored */ | 1426 | /* enable the headphones by default. If/when unsol_event detection works, this will be ignored */ |
@@ -1447,21 +1502,36 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1447 | if ((res >> 26) != STAC_HP_EVENT) | 1502 | if ((res >> 26) != STAC_HP_EVENT) |
1448 | return; | 1503 | return; |
1449 | 1504 | ||
1450 | presence = snd_hda_codec_read(codec, cfg->hp_pin, 0, | 1505 | presence = 0; |
1451 | AC_VERB_GET_PIN_SENSE, 0x00) >> 31; | 1506 | for (i = 0; i < cfg->hp_outs; i++) { |
1507 | int p = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | ||
1508 | AC_VERB_GET_PIN_SENSE, 0x00); | ||
1509 | if (p & (1 << 31)) | ||
1510 | presence++; | ||
1511 | } | ||
1452 | 1512 | ||
1453 | if (presence) { | 1513 | if (presence) { |
1454 | /* disable lineouts, enable hp */ | 1514 | /* disable lineouts, enable hp */ |
1455 | for (i = 0; i < cfg->line_outs; i++) | 1515 | for (i = 0; i < cfg->line_outs; i++) |
1456 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], | 1516 | stac92xx_reset_pinctl(codec, cfg->line_out_pins[i], |
1457 | AC_PINCTL_OUT_EN); | 1517 | AC_PINCTL_OUT_EN); |
1458 | stac92xx_set_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | 1518 | for (i = 0; i < cfg->speaker_outs; i++) |
1519 | stac92xx_reset_pinctl(codec, cfg->speaker_pins[i], | ||
1520 | AC_PINCTL_OUT_EN); | ||
1521 | for (i = 0; i < cfg->hp_outs; i++) | ||
1522 | stac92xx_set_pinctl(codec, cfg->hp_pins[i], | ||
1523 | AC_PINCTL_OUT_EN); | ||
1459 | } else { | 1524 | } else { |
1460 | /* enable lineouts, disable hp */ | 1525 | /* enable lineouts, disable hp */ |
1461 | for (i = 0; i < cfg->line_outs; i++) | 1526 | for (i = 0; i < cfg->line_outs; i++) |
1462 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], | 1527 | stac92xx_set_pinctl(codec, cfg->line_out_pins[i], |
1463 | AC_PINCTL_OUT_EN); | 1528 | AC_PINCTL_OUT_EN); |
1464 | stac92xx_reset_pinctl(codec, cfg->hp_pin, AC_PINCTL_OUT_EN); | 1529 | for (i = 0; i < cfg->speaker_outs; i++) |
1530 | stac92xx_set_pinctl(codec, cfg->speaker_pins[i], | ||
1531 | AC_PINCTL_OUT_EN); | ||
1532 | for (i = 0; i < cfg->hp_outs; i++) | ||
1533 | stac92xx_reset_pinctl(codec, cfg->hp_pins[i], | ||
1534 | AC_PINCTL_OUT_EN); | ||
1465 | } | 1535 | } |
1466 | } | 1536 | } |
1467 | 1537 | ||