diff options
author | Takashi Iwai <tiwai@suse.de> | 2006-09-21 05:56:18 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-09-23 04:48:01 -0400 |
commit | 314634bc81325dcfeb31ed138647d428b1f26cbf (patch) | |
tree | 9a230e872a69e13d026eae4cb247b1447b14c88f /sound | |
parent | 7ffffecc7c4df08ad89723ca32d936ff09b5b3ff (diff) |
[ALSA] hda-codec - Fix mic input with STAC92xx codecs
Fixed mic input with STAC92xx codecs. The mic pin was sometimes set to
OUTPUT by the headphone jack detection.
Also, try to assign a secondary mic as front-mic (or vice versa)
in the auto-detection if possible.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 19 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 90 |
2 files changed, 74 insertions, 35 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 07360996caaa..9c3d7ac08068 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2079,12 +2079,21 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, struct auto_pin_cfg *c | |||
2079 | cfg->hp_pins[cfg->hp_outs] = nid; | 2079 | cfg->hp_pins[cfg->hp_outs] = nid; |
2080 | cfg->hp_outs++; | 2080 | cfg->hp_outs++; |
2081 | break; | 2081 | break; |
2082 | case AC_JACK_MIC_IN: | 2082 | case AC_JACK_MIC_IN: { |
2083 | if (loc == AC_JACK_LOC_FRONT) | 2083 | int preferred, alt; |
2084 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = nid; | 2084 | if (loc == AC_JACK_LOC_FRONT) { |
2085 | else | 2085 | preferred = AUTO_PIN_FRONT_MIC; |
2086 | cfg->input_pins[AUTO_PIN_MIC] = nid; | 2086 | alt = AUTO_PIN_MIC; |
2087 | } else { | ||
2088 | preferred = AUTO_PIN_MIC; | ||
2089 | alt = AUTO_PIN_FRONT_MIC; | ||
2090 | } | ||
2091 | if (!cfg->input_pins[preferred]) | ||
2092 | cfg->input_pins[preferred] = nid; | ||
2093 | else if (!cfg->input_pins[alt]) | ||
2094 | cfg->input_pins[alt] = nid; | ||
2087 | break; | 2095 | break; |
2096 | } | ||
2088 | case AC_JACK_LINE_IN: | 2097 | case AC_JACK_LINE_IN: |
2089 | if (loc == AC_JACK_LOC_FRONT) | 2098 | if (loc == AC_JACK_LOC_FRONT) |
2090 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; | 2099 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7cc064265204..92f48a725853 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -36,7 +36,6 @@ | |||
36 | 36 | ||
37 | #define NUM_CONTROL_ALLOC 32 | 37 | #define NUM_CONTROL_ALLOC 32 |
38 | #define STAC_HP_EVENT 0x37 | 38 | #define STAC_HP_EVENT 0x37 |
39 | #define STAC_UNSOL_ENABLE (AC_USRSP_EN | STAC_HP_EVENT) | ||
40 | 39 | ||
41 | #define STAC_REF 0 | 40 | #define STAC_REF 0 |
42 | #define STAC_D945GTP3 1 | 41 | #define STAC_D945GTP3 1 |
@@ -1164,23 +1163,28 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
1164 | int i, j, k; | 1163 | int i, j, k; |
1165 | 1164 | ||
1166 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 1165 | for (i = 0; i < AUTO_PIN_LAST; i++) { |
1167 | int index = -1; | 1166 | int index; |
1168 | if (cfg->input_pins[i]) { | 1167 | |
1169 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | 1168 | if (!cfg->input_pins[i]) |
1170 | 1169 | continue; | |
1171 | for (j=0; j<spec->num_muxes; j++) { | 1170 | index = -1; |
1172 | int num_cons = snd_hda_get_connections(codec, spec->mux_nids[j], con_lst, HDA_MAX_NUM_INPUTS); | 1171 | for (j = 0; j < spec->num_muxes; j++) { |
1173 | for (k=0; k<num_cons; k++) | 1172 | int num_cons; |
1174 | if (con_lst[k] == cfg->input_pins[i]) { | 1173 | num_cons = snd_hda_get_connections(codec, |
1175 | index = k; | 1174 | spec->mux_nids[j], |
1176 | break; | 1175 | con_lst, |
1177 | } | 1176 | HDA_MAX_NUM_INPUTS); |
1178 | if (index >= 0) | 1177 | for (k = 0; k < num_cons; k++) |
1179 | break; | 1178 | if (con_lst[k] == cfg->input_pins[i]) { |
1180 | } | 1179 | index = k; |
1181 | imux->items[imux->num_items].index = index; | 1180 | goto found; |
1182 | imux->num_items++; | 1181 | } |
1183 | } | 1182 | } |
1183 | continue; | ||
1184 | found: | ||
1185 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | ||
1186 | imux->items[imux->num_items].index = index; | ||
1187 | imux->num_items++; | ||
1184 | } | 1188 | } |
1185 | 1189 | ||
1186 | if (imux->num_items == 1) { | 1190 | if (imux->num_items == 1) { |
@@ -1405,6 +1409,15 @@ static void stac922x_gpio_mute(struct hda_codec *codec, int pin, int muted) | |||
1405 | AC_VERB_SET_GPIO_DATA, gpiostate); | 1409 | AC_VERB_SET_GPIO_DATA, gpiostate); |
1406 | } | 1410 | } |
1407 | 1411 | ||
1412 | static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | ||
1413 | unsigned int event) | ||
1414 | { | ||
1415 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) | ||
1416 | snd_hda_codec_write(codec, nid, 0, | ||
1417 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1418 | (AC_USRSP_EN | event)); | ||
1419 | } | ||
1420 | |||
1408 | static int stac92xx_init(struct hda_codec *codec) | 1421 | static int stac92xx_init(struct hda_codec *codec) |
1409 | { | 1422 | { |
1410 | struct sigmatel_spec *spec = codec->spec; | 1423 | struct sigmatel_spec *spec = codec->spec; |
@@ -1417,13 +1430,13 @@ static int stac92xx_init(struct hda_codec *codec) | |||
1417 | if (spec->hp_detect) { | 1430 | if (spec->hp_detect) { |
1418 | /* Enable unsolicited responses on the HP widget */ | 1431 | /* Enable unsolicited responses on the HP widget */ |
1419 | for (i = 0; i < cfg->hp_outs; i++) | 1432 | for (i = 0; i < cfg->hp_outs; i++) |
1420 | if (get_wcaps(codec, cfg->hp_pins[i]) & AC_WCAP_UNSOL_CAP) | 1433 | enable_pin_detect(codec, cfg->hp_pins[i], |
1421 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, | 1434 | STAC_HP_EVENT); |
1422 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1423 | STAC_UNSOL_ENABLE); | ||
1424 | /* fake event to set up pins */ | 1435 | /* fake event to set up pins */ |
1425 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); | 1436 | codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26); |
1426 | /* enable the headphones by default. If/when unsol_event detection works, this will be ignored */ | 1437 | /* enable the headphones by default. |
1438 | * If/when unsol_event detection works, this will be ignored | ||
1439 | */ | ||
1427 | stac92xx_auto_init_hp_out(codec); | 1440 | stac92xx_auto_init_hp_out(codec); |
1428 | } else { | 1441 | } else { |
1429 | stac92xx_auto_init_multi_out(codec); | 1442 | stac92xx_auto_init_multi_out(codec); |
@@ -1478,6 +1491,8 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1478 | { | 1491 | { |
1479 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, | 1492 | unsigned int pin_ctl = snd_hda_codec_read(codec, nid, |
1480 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); | 1493 | 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); |
1494 | if (flag == AC_PINCTL_OUT_EN && (pin_ctl & AC_PINCTL_IN_EN)) | ||
1495 | return; | ||
1481 | snd_hda_codec_write(codec, nid, 0, | 1496 | snd_hda_codec_write(codec, nid, 0, |
1482 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1497 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1483 | pin_ctl | flag); | 1498 | pin_ctl | flag); |
@@ -1493,21 +1508,27 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid, | |||
1493 | pin_ctl & ~flag); | 1508 | pin_ctl & ~flag); |
1494 | } | 1509 | } |
1495 | 1510 | ||
1496 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 1511 | static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) |
1512 | { | ||
1513 | if (!nid) | ||
1514 | return 0; | ||
1515 | if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) | ||
1516 | & (1 << 31)) | ||
1517 | return 1; | ||
1518 | return 0; | ||
1519 | } | ||
1520 | |||
1521 | static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res) | ||
1497 | { | 1522 | { |
1498 | struct sigmatel_spec *spec = codec->spec; | 1523 | struct sigmatel_spec *spec = codec->spec; |
1499 | struct auto_pin_cfg *cfg = &spec->autocfg; | 1524 | struct auto_pin_cfg *cfg = &spec->autocfg; |
1500 | int i, presence; | 1525 | int i, presence; |
1501 | 1526 | ||
1502 | if ((res >> 26) != STAC_HP_EVENT) | ||
1503 | return; | ||
1504 | |||
1505 | presence = 0; | 1527 | presence = 0; |
1506 | for (i = 0; i < cfg->hp_outs; i++) { | 1528 | for (i = 0; i < cfg->hp_outs; i++) { |
1507 | int p = snd_hda_codec_read(codec, cfg->hp_pins[i], 0, | 1529 | presence = get_pin_presence(codec, cfg->hp_pins[i]); |
1508 | AC_VERB_GET_PIN_SENSE, 0x00); | 1530 | if (presence) |
1509 | if (p & (1 << 31)) | 1531 | break; |
1510 | presence++; | ||
1511 | } | 1532 | } |
1512 | 1533 | ||
1513 | if (presence) { | 1534 | if (presence) { |
@@ -1535,6 +1556,15 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1535 | } | 1556 | } |
1536 | } | 1557 | } |
1537 | 1558 | ||
1559 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
1560 | { | ||
1561 | switch (res >> 26) { | ||
1562 | case STAC_HP_EVENT: | ||
1563 | stac92xx_hp_detect(codec, res); | ||
1564 | break; | ||
1565 | } | ||
1566 | } | ||
1567 | |||
1538 | #ifdef CONFIG_PM | 1568 | #ifdef CONFIG_PM |
1539 | static int stac92xx_resume(struct hda_codec *codec) | 1569 | static int stac92xx_resume(struct hda_codec *codec) |
1540 | { | 1570 | { |