diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 121 |
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 | |||
1070 | static int stac92xx_add_dyn_out_pins(struct hda_codec *codec, struct auto_pin_cfg *cfg) | 1070 | static 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 | |||
1127 | static 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 */ | ||
1125 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | 1146 | static 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 | ||
1205 | static int check_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | 1260 | static 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); |