aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2006-09-21 05:56:18 -0400
committerJaroslav Kysela <perex@suse.cz>2006-09-23 04:48:01 -0400
commit314634bc81325dcfeb31ed138647d428b1f26cbf (patch)
tree9a230e872a69e13d026eae4cb247b1447b14c88f
parent7ffffecc7c4df08ad89723ca32d936ff09b5b3ff (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>
-rw-r--r--sound/pci/hda/hda_codec.c19
-rw-r--r--sound/pci/hda/patch_sigmatel.c90
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
1412static 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
1408static int stac92xx_init(struct hda_codec *codec) 1421static 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
1496static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) 1511static 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
1521static 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
1559static 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
1539static int stac92xx_resume(struct hda_codec *codec) 1569static int stac92xx_resume(struct hda_codec *codec)
1540{ 1570{