diff options
author | Matt Porter <mporter@embeddedalley.com> | 2006-10-26 11:12:59 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2007-02-09 03:01:12 -0500 |
commit | 8b65727bf07abc0b3fdac4fcf2f90c5882d65f4f (patch) | |
tree | 4a2cbbf8a977bae26e3fd34970076d53fc831fa7 /sound/pci | |
parent | 06bf2f495aabfdbe9d5db7b910fa75dd7f72131a (diff) |
[ALSA] hda: add dig mic support for sigmatel codecs
Adds support for digital microphone pin widgets on SigmaTel codecs.
Enables support only on the 9205 codecs for now.
Signed-off-by: Matt Porter <mporter@embeddedalley.com>
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/patch_sigmatel.c | 130 |
1 files changed, 125 insertions, 5 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index fe51ef3e49d2..8f52372d66a2 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #define STAC_922X_MODELS 4 /* number of 922x models */ | 44 | #define STAC_922X_MODELS 4 /* number of 922x models */ |
45 | #define STAC_D965_3ST 4 | 45 | #define STAC_D965_3ST 4 |
46 | #define STAC_D965_5ST 5 | 46 | #define STAC_D965_5ST 5 |
47 | #define STAC_927X_MODELS 6 /* number of 922x models */ | 47 | #define STAC_927X_MODELS 6 /* number of 927x models */ |
48 | 48 | ||
49 | struct sigmatel_spec { | 49 | struct sigmatel_spec { |
50 | struct snd_kcontrol_new *mixers[4]; | 50 | struct snd_kcontrol_new *mixers[4]; |
@@ -67,6 +67,9 @@ struct sigmatel_spec { | |||
67 | unsigned int num_adcs; | 67 | unsigned int num_adcs; |
68 | hda_nid_t *mux_nids; | 68 | hda_nid_t *mux_nids; |
69 | unsigned int num_muxes; | 69 | unsigned int num_muxes; |
70 | hda_nid_t *dmic_nids; | ||
71 | unsigned int num_dmics; | ||
72 | hda_nid_t dmux_nid; | ||
70 | hda_nid_t dig_in_nid; | 73 | hda_nid_t dig_in_nid; |
71 | 74 | ||
72 | /* pin widgets */ | 75 | /* pin widgets */ |
@@ -80,6 +83,8 @@ struct sigmatel_spec { | |||
80 | struct snd_kcontrol_new *mixer; | 83 | struct snd_kcontrol_new *mixer; |
81 | 84 | ||
82 | /* capture source */ | 85 | /* capture source */ |
86 | struct hda_input_mux *dinput_mux; | ||
87 | unsigned int cur_dmux; | ||
83 | struct hda_input_mux *input_mux; | 88 | struct hda_input_mux *input_mux; |
84 | unsigned int cur_mux[3]; | 89 | unsigned int cur_mux[3]; |
85 | 90 | ||
@@ -92,6 +97,7 @@ struct sigmatel_spec { | |||
92 | struct auto_pin_cfg autocfg; | 97 | struct auto_pin_cfg autocfg; |
93 | unsigned int num_kctl_alloc, num_kctl_used; | 98 | unsigned int num_kctl_alloc, num_kctl_used; |
94 | struct snd_kcontrol_new *kctl_alloc; | 99 | struct snd_kcontrol_new *kctl_alloc; |
100 | struct hda_input_mux private_dimux; | ||
95 | struct hda_input_mux private_imux; | 101 | struct hda_input_mux private_imux; |
96 | }; | 102 | }; |
97 | 103 | ||
@@ -131,6 +137,10 @@ static hda_nid_t stac9205_mux_nids[2] = { | |||
131 | 0x19, 0x1a | 137 | 0x19, 0x1a |
132 | }; | 138 | }; |
133 | 139 | ||
140 | static hda_nid_t stac9205_dmic_nids[3] = { | ||
141 | 0x17, 0x18, 0 | ||
142 | }; | ||
143 | |||
134 | static hda_nid_t stac9200_pin_nids[8] = { | 144 | static hda_nid_t stac9200_pin_nids[8] = { |
135 | 0x08, 0x09, 0x0d, 0x0e, | 145 | 0x08, 0x09, 0x0d, 0x0e, |
136 | 0x0f, 0x10, 0x11, 0x12, | 146 | 0x0f, 0x10, 0x11, 0x12, |
@@ -154,6 +164,34 @@ static hda_nid_t stac9205_pin_nids[12] = { | |||
154 | 164 | ||
155 | }; | 165 | }; |
156 | 166 | ||
167 | static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol, | ||
168 | struct snd_ctl_elem_info *uinfo) | ||
169 | { | ||
170 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
171 | struct sigmatel_spec *spec = codec->spec; | ||
172 | return snd_hda_input_mux_info(spec->dinput_mux, uinfo); | ||
173 | } | ||
174 | |||
175 | static int stac92xx_dmux_enum_get(struct snd_kcontrol *kcontrol, | ||
176 | struct snd_ctl_elem_value *ucontrol) | ||
177 | { | ||
178 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
179 | struct sigmatel_spec *spec = codec->spec; | ||
180 | |||
181 | ucontrol->value.enumerated.item[0] = spec->cur_dmux; | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int stac92xx_dmux_enum_put(struct snd_kcontrol *kcontrol, | ||
186 | struct snd_ctl_elem_value *ucontrol) | ||
187 | { | ||
188 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
189 | struct sigmatel_spec *spec = codec->spec; | ||
190 | |||
191 | return snd_hda_input_mux_put(codec, spec->dinput_mux, ucontrol, | ||
192 | spec->dmux_nid, &spec->cur_dmux); | ||
193 | } | ||
194 | |||
157 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 195 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
158 | { | 196 | { |
159 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 197 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
@@ -281,6 +319,14 @@ static snd_kcontrol_new_t stac927x_mixer[] = { | |||
281 | static snd_kcontrol_new_t stac9205_mixer[] = { | 319 | static snd_kcontrol_new_t stac9205_mixer[] = { |
282 | { | 320 | { |
283 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 321 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
322 | .name = "Digital Input Source", | ||
323 | .count = 1, | ||
324 | .info = stac92xx_dmux_enum_info, | ||
325 | .get = stac92xx_dmux_enum_get, | ||
326 | .put = stac92xx_dmux_enum_put, | ||
327 | }, | ||
328 | { | ||
329 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
284 | .name = "Input Source", | 330 | .name = "Input Source", |
285 | .count = 1, | 331 | .count = 1, |
286 | .info = stac92xx_mux_enum_info, | 332 | .info = stac92xx_mux_enum_info, |
@@ -585,8 +631,8 @@ static struct hda_board_config stac927x_cfg_tbl[] = { | |||
585 | 631 | ||
586 | static unsigned int ref9205_pin_configs[12] = { | 632 | static unsigned int ref9205_pin_configs[12] = { |
587 | 0x40000100, 0x40000100, 0x01016011, 0x01014010, | 633 | 0x40000100, 0x40000100, 0x01016011, 0x01014010, |
588 | 0x01813122, 0x01a19021, 0x40000100, 0x40000100, | 634 | 0x01813122, 0x01a19021, 0x40000100, 0x40000100, |
589 | 0x40000100, 0x40000100, 0x01441030, 0x01c41030 | 635 | 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030 |
590 | }; | 636 | }; |
591 | 637 | ||
592 | static unsigned int *stac9205_brd_tbl[] = { | 638 | static unsigned int *stac9205_brd_tbl[] = { |
@@ -1154,6 +1200,58 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
1154 | return 0; | 1200 | return 0; |
1155 | } | 1201 | } |
1156 | 1202 | ||
1203 | /* labels for dmic mux inputs */ | ||
1204 | const char *stac92xx_dmic_labels[5] = { | ||
1205 | "Analog Inputs", "Digital Mic 1", "Digital Mic 2", | ||
1206 | "Digital Mic 3", "Digital Mic 4" | ||
1207 | }; | ||
1208 | |||
1209 | /* create playback/capture controls for input pins on dmic capable codecs */ | ||
1210 | static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | ||
1211 | const struct auto_pin_cfg *cfg) | ||
1212 | { | ||
1213 | struct sigmatel_spec *spec = codec->spec; | ||
1214 | struct hda_input_mux *dimux = &spec->private_dimux; | ||
1215 | hda_nid_t con_lst[HDA_MAX_NUM_INPUTS]; | ||
1216 | int i, j; | ||
1217 | |||
1218 | dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; | ||
1219 | dimux->items[dimux->num_items].index = 0; | ||
1220 | dimux->num_items++; | ||
1221 | |||
1222 | for (i = 0; i < spec->num_dmics; i++) { | ||
1223 | int index; | ||
1224 | int num_cons; | ||
1225 | unsigned int def_conf; | ||
1226 | |||
1227 | def_conf = snd_hda_codec_read(codec, | ||
1228 | spec->dmic_nids[i], | ||
1229 | 0, | ||
1230 | AC_VERB_GET_CONFIG_DEFAULT, | ||
1231 | 0); | ||
1232 | if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE) | ||
1233 | continue; | ||
1234 | |||
1235 | num_cons = snd_hda_get_connections(codec, | ||
1236 | spec->dmux_nid, | ||
1237 | con_lst, | ||
1238 | HDA_MAX_NUM_INPUTS); | ||
1239 | for (j = 0; j < num_cons; j++) | ||
1240 | if (con_lst[j] == spec->dmic_nids[i]) { | ||
1241 | index = j; | ||
1242 | goto found; | ||
1243 | } | ||
1244 | continue; | ||
1245 | found: | ||
1246 | dimux->items[dimux->num_items].label = | ||
1247 | stac92xx_dmic_labels[dimux->num_items]; | ||
1248 | dimux->items[dimux->num_items].index = index; | ||
1249 | dimux->num_items++; | ||
1250 | } | ||
1251 | |||
1252 | return 0; | ||
1253 | } | ||
1254 | |||
1157 | /* create playback/capture controls for input pins */ | 1255 | /* create playback/capture controls for input pins */ |
1158 | static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) | 1256 | static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) |
1159 | { | 1257 | { |
@@ -1238,7 +1336,9 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
1238 | struct sigmatel_spec *spec = codec->spec; | 1336 | struct sigmatel_spec *spec = codec->spec; |
1239 | int err; | 1337 | int err; |
1240 | 1338 | ||
1241 | if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) | 1339 | if ((err = snd_hda_parse_pin_def_config(codec, |
1340 | &spec->autocfg, | ||
1341 | spec->dmic_nids)) < 0) | ||
1242 | return err; | 1342 | return err; |
1243 | if (! spec->autocfg.line_outs) | 1343 | if (! spec->autocfg.line_outs) |
1244 | return 0; /* can't find valid pin config */ | 1344 | return 0; /* can't find valid pin config */ |
@@ -1254,6 +1354,11 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
1254 | (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) | 1354 | (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) |
1255 | return err; | 1355 | return err; |
1256 | 1356 | ||
1357 | if (spec->num_dmics > 0) | ||
1358 | if ((err = stac92xx_auto_create_dmic_input_ctls(codec, | ||
1359 | &spec->autocfg)) < 0) | ||
1360 | return err; | ||
1361 | |||
1257 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 1362 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
1258 | if (spec->multiout.max_channels > 2) | 1363 | if (spec->multiout.max_channels > 2) |
1259 | spec->surr_switch = 1; | 1364 | spec->surr_switch = 1; |
@@ -1267,6 +1372,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
1267 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 1372 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; |
1268 | 1373 | ||
1269 | spec->input_mux = &spec->private_imux; | 1374 | spec->input_mux = &spec->private_imux; |
1375 | spec->dinput_mux = &spec->private_dimux; | ||
1270 | 1376 | ||
1271 | return 1; | 1377 | return 1; |
1272 | } | 1378 | } |
@@ -1366,6 +1472,7 @@ static int stac9200_parse_auto_config(struct hda_codec *codec) | |||
1366 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | 1472 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; |
1367 | 1473 | ||
1368 | spec->input_mux = &spec->private_imux; | 1474 | spec->input_mux = &spec->private_imux; |
1475 | spec->dinput_mux = &spec->private_dimux; | ||
1369 | 1476 | ||
1370 | return 1; | 1477 | return 1; |
1371 | } | 1478 | } |
@@ -1448,6 +1555,11 @@ static int stac92xx_init(struct hda_codec *codec) | |||
1448 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 1555 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
1449 | } | 1556 | } |
1450 | } | 1557 | } |
1558 | if (spec->num_dmics > 0) | ||
1559 | for (i = 0; i < spec->num_dmics; i++) | ||
1560 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], | ||
1561 | AC_PINCTL_IN_EN); | ||
1562 | |||
1451 | if (cfg->dig_out_pin) | 1563 | if (cfg->dig_out_pin) |
1452 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, | 1564 | stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, |
1453 | AC_PINCTL_OUT_EN); | 1565 | AC_PINCTL_OUT_EN); |
@@ -1618,6 +1730,7 @@ static int patch_stac9200(struct hda_codec *codec) | |||
1618 | spec->adc_nids = stac9200_adc_nids; | 1730 | spec->adc_nids = stac9200_adc_nids; |
1619 | spec->mux_nids = stac9200_mux_nids; | 1731 | spec->mux_nids = stac9200_mux_nids; |
1620 | spec->num_muxes = 1; | 1732 | spec->num_muxes = 1; |
1733 | spec->num_dmics = 0; | ||
1621 | 1734 | ||
1622 | spec->init = stac9200_core_init; | 1735 | spec->init = stac9200_core_init; |
1623 | spec->mixer = stac9200_mixer; | 1736 | spec->mixer = stac9200_mixer; |
@@ -1663,6 +1776,7 @@ static int patch_stac922x(struct hda_codec *codec) | |||
1663 | spec->adc_nids = stac922x_adc_nids; | 1776 | spec->adc_nids = stac922x_adc_nids; |
1664 | spec->mux_nids = stac922x_mux_nids; | 1777 | spec->mux_nids = stac922x_mux_nids; |
1665 | spec->num_muxes = 2; | 1778 | spec->num_muxes = 2; |
1779 | spec->num_dmics = 0; | ||
1666 | 1780 | ||
1667 | spec->init = stac922x_core_init; | 1781 | spec->init = stac922x_core_init; |
1668 | spec->mixer = stac922x_mixer; | 1782 | spec->mixer = stac922x_mixer; |
@@ -1714,6 +1828,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
1714 | spec->adc_nids = stac927x_adc_nids; | 1828 | spec->adc_nids = stac927x_adc_nids; |
1715 | spec->mux_nids = stac927x_mux_nids; | 1829 | spec->mux_nids = stac927x_mux_nids; |
1716 | spec->num_muxes = 3; | 1830 | spec->num_muxes = 3; |
1831 | spec->num_dmics = 0; | ||
1717 | spec->init = d965_core_init; | 1832 | spec->init = d965_core_init; |
1718 | spec->mixer = stac9227_mixer; | 1833 | spec->mixer = stac9227_mixer; |
1719 | break; | 1834 | break; |
@@ -1721,6 +1836,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
1721 | spec->adc_nids = stac927x_adc_nids; | 1836 | spec->adc_nids = stac927x_adc_nids; |
1722 | spec->mux_nids = stac927x_mux_nids; | 1837 | spec->mux_nids = stac927x_mux_nids; |
1723 | spec->num_muxes = 3; | 1838 | spec->num_muxes = 3; |
1839 | spec->num_dmics = 0; | ||
1724 | spec->init = d965_core_init; | 1840 | spec->init = d965_core_init; |
1725 | spec->mixer = stac9227_mixer; | 1841 | spec->mixer = stac9227_mixer; |
1726 | break; | 1842 | break; |
@@ -1728,6 +1844,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
1728 | spec->adc_nids = stac927x_adc_nids; | 1844 | spec->adc_nids = stac927x_adc_nids; |
1729 | spec->mux_nids = stac927x_mux_nids; | 1845 | spec->mux_nids = stac927x_mux_nids; |
1730 | spec->num_muxes = 3; | 1846 | spec->num_muxes = 3; |
1847 | spec->num_dmics = 0; | ||
1731 | spec->init = stac927x_core_init; | 1848 | spec->init = stac927x_core_init; |
1732 | spec->mixer = stac927x_mixer; | 1849 | spec->mixer = stac927x_mixer; |
1733 | } | 1850 | } |
@@ -1773,7 +1890,10 @@ static int patch_stac9205(struct hda_codec *codec) | |||
1773 | 1890 | ||
1774 | spec->adc_nids = stac9205_adc_nids; | 1891 | spec->adc_nids = stac9205_adc_nids; |
1775 | spec->mux_nids = stac9205_mux_nids; | 1892 | spec->mux_nids = stac9205_mux_nids; |
1776 | spec->num_muxes = 3; | 1893 | spec->num_muxes = 2; |
1894 | spec->dmic_nids = stac9205_dmic_nids; | ||
1895 | spec->num_dmics = 2; | ||
1896 | spec->dmux_nid = 0x1d; | ||
1777 | 1897 | ||
1778 | spec->init = stac9205_core_init; | 1898 | spec->init = stac9205_core_init; |
1779 | spec->mixer = stac9205_mixer; | 1899 | spec->mixer = stac9205_mixer; |