aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
authorSteve Longerbeam <stevel@embeddedalley.com>2007-05-03 14:50:03 -0400
committerJaroslav Kysela <perex@suse.cz>2007-05-11 10:56:15 -0400
commit7b043899992e5d9c0b1a620cdad9158d2e5484d7 (patch)
tree5d613f2bdb33a858fd10fb5b98518979a7329009 /sound/pci/hda/patch_sigmatel.c
parent7e0af29d6f3964bec3d72c6caeb87a603e660fdf (diff)
[ALSA] hda-codec - bug fixes for stac92xx HDA codecs.
* fixed surround playback on stac922x. Pin direction control bits were not being set correctly in stac92xx_set_pinctl(). Specifically it would refuse to set the port as an output if the port was already configured as an input. Last hunk (#8). * fixed an input mux bug on 92xx codecs. When there is more than one possible input calculated for the muxes, the actual mux widget never gets set from its reset default, which is index 0, in the stac9221 case that is port E. So alsamixer/amixer/gnome-mixer report the Mic as being the selected input source, but in fact is something else (line-in port E in stac9221 case). Another problem with this is that if you actually try to set the mux input to 'Mic', nothing happens because *cur_val == idx (see snd_hda_input_mux_put). You have to actually toggle input source to line-in then back to mic to actually set the mux widget. Hunk #7. * fixed some typos in patch_sigmatel.c. Hunk #6. * fix to stac92xx_add_dyn_out_pins() that fixes surround playback on codecs with less that 4 DACs (stac9205 for example). It reads the widget caps cache created by hda_codec to count the total number of analog DACs found. It then uses that to determine whether there will be enough independent DACs available for line/mic switch controls. Hunk #1, #2, and #3. * improvements to stac92xx_auto_fill_dac_nids() to make it more general. This fixes surround playback on some codecs in combination with the fix to stac92xx_add_dyn_out_pins() above. It reads the full connection list now, instead of just the first entry, and then locates an analog DAC in the list. If one is found and it's free, assign it to that line-out. If no free DAC is found for the line-out, return -ENODEV. It also makes sure to actually select the chosen DAC if more than one DAC is input to the pin. Hunks #4, #5. Signed-off-by: Steve Longerbeam <stevel@embeddedalley.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c121
1 files changed, 87 insertions, 34 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index ebf7dde92d59..93ae9c250767 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1070,11 +1070,23 @@ static int stac92xx_add_control(struct sigmatel_spec *spec, int type, const char
1070static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg) 1070static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg)
1071{ 1071{
1072 struct sigmatel_spec *spec = codec->spec; 1072 struct sigmatel_spec *spec = codec->spec;
1073 unsigned int wcaps, wtype;
1074 int i, num_dacs = 0;
1075
1076 /* use the wcaps cache to count all DACs available for line-outs */
1077 for (i = 0; i < codec->num_nodes; i++) {
1078 wcaps = codec->wcaps[i];
1079 wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
1080 if (wtype == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL))
1081 num_dacs++;
1082 }
1073 1083
1084 snd_printdd("%s: total dac count=%d\n", __func__, num_dacs);
1085
1074 switch (cfg->line_outs) { 1086 switch (cfg->line_outs) {
1075 case 3: 1087 case 3:
1076 /* add line-in as side */ 1088 /* add line-in as side */
1077 if (cfg->input_pins[AUTO_PIN_LINE]) { 1089 if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 3) {
1078 cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE]; 1090 cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_LINE];
1079 spec->line_switch = 1; 1091 spec->line_switch = 1;
1080 cfg->line_outs++; 1092 cfg->line_outs++;
@@ -1082,12 +1094,12 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf
1082 break; 1094 break;
1083 case 2: 1095 case 2:
1084 /* add line-in as clfe and mic as side */ 1096 /* add line-in as clfe and mic as side */
1085 if (cfg->input_pins[AUTO_PIN_LINE]) { 1097 if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 2) {
1086 cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE]; 1098 cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_LINE];
1087 spec->line_switch = 1; 1099 spec->line_switch = 1;
1088 cfg->line_outs++; 1100 cfg->line_outs++;
1089 } 1101 }
1090 if (cfg->input_pins[AUTO_PIN_MIC]) { 1102 if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 3) {
1091 cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC]; 1103 cfg->line_out_pins[3] = cfg->input_pins[AUTO_PIN_MIC];
1092 spec->mic_switch = 1; 1104 spec->mic_switch = 1;
1093 cfg->line_outs++; 1105 cfg->line_outs++;
@@ -1095,12 +1107,12 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf
1095 break; 1107 break;
1096 case 1: 1108 case 1:
1097 /* add line-in as surr and mic as clfe */ 1109 /* add line-in as surr and mic as clfe */
1098 if (cfg->input_pins[AUTO_PIN_LINE]) { 1110 if (cfg->input_pins[AUTO_PIN_LINE] && num_dacs > 1) {
1099 cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE]; 1111 cfg->line_out_pins[1] = cfg->input_pins[AUTO_PIN_LINE];
1100 spec->line_switch = 1; 1112 spec->line_switch = 1;
1101 cfg->line_outs++; 1113 cfg->line_outs++;
1102 } 1114 }
1103 if (cfg->input_pins[AUTO_PIN_MIC]) { 1115 if (cfg->input_pins[AUTO_PIN_MIC] && num_dacs > 2) {
1104 cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC]; 1116 cfg->line_out_pins[2] = cfg->input_pins[AUTO_PIN_MIC];
1105 spec->mic_switch = 1; 1117 spec->mic_switch = 1;
1106 cfg->line_outs++; 1118 cfg->line_outs++;
@@ -1111,33 +1123,76 @@ static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cf
1111 return 0; 1123 return 0;
1112} 1124}
1113 1125
1126
1127static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
1128{
1129 int i;
1130
1131 for (i = 0; i < spec->multiout.num_dacs; i++) {
1132 if (spec->multiout.dac_nids[i] == nid)
1133 return 1;
1134 }
1135
1136 return 0;
1137}
1138
1114/* 1139/*
1115 * XXX The line_out pin widget connection list may not be set to the 1140 * Fill in the dac_nids table from the parsed pin configuration
1116 * desired DAC nid. This is the case on 927x where ports A and B can 1141 * This function only works when every pin in line_out_pins[]
1117 * be routed to several DACs. 1142 * contains atleast one DAC in its connection list. Some 92xx
1118 * 1143 * codecs are not connected directly to a DAC, such as the 9200
1119 * This requires an analysis of the line-out/hp pin configuration 1144 * and 9202/925x. For those, dac_nids[] must be hard-coded.
1120 * to provide a best fit for pin/DAC configurations that are routable.
1121 * For now, 927x DAC4 is not supported and 927x DAC1 output to ports
1122 * A and B is not supported.
1123 */ 1145 */
1124/* fill in the dac_nids table from the parsed pin configuration */
1125static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, 1146static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec,
1126 const struct auto_pin_cfg *cfg) 1147 const struct auto_pin_cfg *cfg)
1127{ 1148{
1128 struct sigmatel_spec *spec = codec->spec; 1149 struct sigmatel_spec *spec = codec->spec;
1129 hda_nid_t nid; 1150 int i, j, conn_len = 0;
1130 int i; 1151 hda_nid_t nid, conn[HDA_MAX_CONNECTIONS];
1131 1152 unsigned int wcaps, wtype;
1132 /* check the pins hardwired to audio widget */ 1153
1133 for (i = 0; i < cfg->line_outs; i++) { 1154 for (i = 0; i < cfg->line_outs; i++) {
1134 nid = cfg->line_out_pins[i]; 1155 nid = cfg->line_out_pins[i];
1135 spec->multiout.dac_nids[i] = snd_hda_codec_read(codec, nid, 0, 1156 conn_len = snd_hda_get_connections(codec, nid, conn,
1136 AC_VERB_GET_CONNECT_LIST, 0) & 0xff; 1157 HDA_MAX_CONNECTIONS);
1137 } 1158 for (j = 0; j < conn_len; j++) {
1159 wcaps = snd_hda_param_read(codec, conn[j],
1160 AC_PAR_AUDIO_WIDGET_CAP);
1161 wtype = (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
1162
1163 if (wtype != AC_WID_AUD_OUT ||
1164 (wcaps & AC_WCAP_DIGITAL))
1165 continue;
1166 /* conn[j] is a DAC routed to this line-out */
1167 if (!is_in_dac_nids(spec, conn[j]))
1168 break;
1169 }
1170
1171 if (j == conn_len) {
1172 /* error out, no available DAC found */
1173 snd_printk(KERN_ERR
1174 "%s: No available DAC for pin 0x%x\n",
1175 __func__, nid);
1176 return -ENODEV;
1177 }
1178
1179 spec->multiout.dac_nids[i] = conn[j];
1180 spec->multiout.num_dacs++;
1181 if (conn_len > 1) {
1182 /* select this DAC in the pin's input mux */
1183 snd_hda_codec_write(codec, nid, 0,
1184 AC_VERB_SET_CONNECT_SEL, j);
1138 1185
1139 spec->multiout.num_dacs = cfg->line_outs; 1186 }
1187 }
1140 1188
1189 snd_printd("dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n",
1190 spec->multiout.num_dacs,
1191 spec->multiout.dac_nids[0],
1192 spec->multiout.dac_nids[1],
1193 spec->multiout.dac_nids[2],
1194 spec->multiout.dac_nids[3],
1195 spec->multiout.dac_nids[4]);
1141 return 0; 1196 return 0;
1142} 1197}
1143 1198
@@ -1204,12 +1259,8 @@ static int stac92xx_auto_create_multi_out_ctls(struct sigmatel_spec *spec,
1204 1259
1205static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) 1260static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
1206{ 1261{
1207 int i; 1262 if (is_in_dac_nids(spec, nid))
1208 1263 return 1;
1209 for (i = 0; i < spec->multiout.num_dacs; i++) {
1210 if (spec->multiout.dac_nids[i] == nid)
1211 return 1;
1212 }
1213 if (spec->multiout.hp_nid == nid) 1264 if (spec->multiout.hp_nid == nid)
1214 return 1; 1265 return 1;
1215 return 0; 1266 return 0;
@@ -1251,12 +1302,10 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
1251 add_spec_dacs(spec, nid); 1302 add_spec_dacs(spec, nid);
1252 } 1303 }
1253 for (i = 0; i < cfg->speaker_outs; i++) { 1304 for (i = 0; i < cfg->speaker_outs; i++) {
1254 nid = snd_hda_codec_read(codec, cfg->speaker_pins[0], 0, 1305 nid = snd_hda_codec_read(codec, cfg->speaker_pins[i], 0,
1255 AC_VERB_GET_CONNECT_LIST, 0) & 0xff; 1306 AC_VERB_GET_CONNECT_LIST, 0) & 0xff;
1256 if (check_in_dac_nids(spec, nid)) 1307 if (check_in_dac_nids(spec, nid))
1257 nid = 0; 1308 nid = 0;
1258 if (check_in_dac_nids(spec, nid))
1259 nid = 0;
1260 if (! nid) 1309 if (! nid)
1261 continue; 1310 continue;
1262 add_spec_dacs(spec, nid); 1311 add_spec_dacs(spec, nid);
@@ -1370,7 +1419,7 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
1370 imux->num_items++; 1419 imux->num_items++;
1371 } 1420 }
1372 1421
1373 if (imux->num_items == 1) { 1422 if (imux->num_items) {
1374 /* 1423 /*
1375 * Set the current input for the muxes. 1424 * Set the current input for the muxes.
1376 * The STAC9221 has two input muxes with identical source 1425 * The STAC9221 has two input muxes with identical source
@@ -1690,8 +1739,12 @@ static void stac92xx_set_pinctl(struct hda_codec *codec, hda_nid_t nid,
1690{ 1739{
1691 unsigned int pin_ctl = snd_hda_codec_read(codec, nid, 1740 unsigned int pin_ctl = snd_hda_codec_read(codec, nid,
1692 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00); 1741 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0x00);
1693 if (flag == AC_PINCTL_OUT_EN && (pin_ctl & AC_PINCTL_IN_EN)) 1742
1694 return; 1743 /* if setting pin direction bits, clear the current
1744 direction bits first */
1745 if (flag & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN))
1746 pin_ctl &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
1747
1695 snd_hda_codec_write(codec, nid, 0, 1748 snd_hda_codec_write(codec, nid, 0,
1696 AC_VERB_SET_PIN_WIDGET_CONTROL, 1749 AC_VERB_SET_PIN_WIDGET_CONTROL,
1697 pin_ctl | flag); 1750 pin_ctl | flag);