diff options
author | Matthew Ranostay <mranostay@embeddedalley.com> | 2008-09-07 06:03:41 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-09-09 03:11:41 -0400 |
commit | d9737751eb7f2f3f6e973834ea9f215e855d46ea (patch) | |
tree | f05edb13c14d0f56c77e6b750acd8ecc13a46ac0 /sound/pci | |
parent | f14d8e975054ae186eba229485a213dfcc7a25da (diff) |
ALSA: hda: SPDIF mux controls
Dynamically create mux controls for SPDIF outs on certain IDT/Sigmatel codecs.
Signed-off-by: Matthew Ranostay <mranostay@embeddedalley.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 114 |
1 files changed, 112 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index c72c748322a1..8ff7b95c34e5 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -173,6 +173,9 @@ struct sigmatel_spec { | |||
173 | unsigned int num_dmics; | 173 | unsigned int num_dmics; |
174 | hda_nid_t *dmux_nids; | 174 | hda_nid_t *dmux_nids; |
175 | unsigned int num_dmuxes; | 175 | unsigned int num_dmuxes; |
176 | hda_nid_t *smux_nids; | ||
177 | unsigned int num_smuxes; | ||
178 | |||
176 | hda_nid_t dig_in_nid; | 179 | hda_nid_t dig_in_nid; |
177 | hda_nid_t mono_nid; | 180 | hda_nid_t mono_nid; |
178 | hda_nid_t anabeep_nid; | 181 | hda_nid_t anabeep_nid; |
@@ -193,6 +196,8 @@ struct sigmatel_spec { | |||
193 | unsigned int cur_dmux[2]; | 196 | unsigned int cur_dmux[2]; |
194 | struct hda_input_mux *input_mux; | 197 | struct hda_input_mux *input_mux; |
195 | unsigned int cur_mux[3]; | 198 | unsigned int cur_mux[3]; |
199 | struct hda_input_mux *sinput_mux; | ||
200 | unsigned int cur_smux[2]; | ||
196 | unsigned int powerdown_adcs; | 201 | unsigned int powerdown_adcs; |
197 | 202 | ||
198 | /* i/o switches */ | 203 | /* i/o switches */ |
@@ -209,6 +214,7 @@ struct sigmatel_spec { | |||
209 | struct snd_kcontrol_new *kctl_alloc; | 214 | struct snd_kcontrol_new *kctl_alloc; |
210 | struct hda_input_mux private_dimux; | 215 | struct hda_input_mux private_dimux; |
211 | struct hda_input_mux private_imux; | 216 | struct hda_input_mux private_imux; |
217 | struct hda_input_mux private_smux; | ||
212 | struct hda_input_mux private_mono_mux; | 218 | struct hda_input_mux private_mono_mux; |
213 | }; | 219 | }; |
214 | 220 | ||
@@ -251,6 +257,10 @@ static hda_nid_t stac92hd73xx_dmux_nids[2] = { | |||
251 | 0x20, 0x21, | 257 | 0x20, 0x21, |
252 | }; | 258 | }; |
253 | 259 | ||
260 | static hda_nid_t stac92hd73xx_smux_nids[2] = { | ||
261 | 0x22, 0x23, | ||
262 | }; | ||
263 | |||
254 | #define STAC92HD83XXX_NUM_DMICS 2 | 264 | #define STAC92HD83XXX_NUM_DMICS 2 |
255 | static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { | 265 | static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { |
256 | 0x11, 0x12, 0 | 266 | 0x11, 0x12, 0 |
@@ -294,6 +304,10 @@ static hda_nid_t stac92hd71bxx_dmux_nids[1] = { | |||
294 | 0x1c, | 304 | 0x1c, |
295 | }; | 305 | }; |
296 | 306 | ||
307 | static hda_nid_t stac92hd71bxx_smux_nids[2] = { | ||
308 | 0x24, 0x25, | ||
309 | }; | ||
310 | |||
297 | static hda_nid_t stac92hd71bxx_dac_nids[1] = { | 311 | static hda_nid_t stac92hd71bxx_dac_nids[1] = { |
298 | 0x10, /*0x11, */ | 312 | 0x10, /*0x11, */ |
299 | }; | 313 | }; |
@@ -340,6 +354,10 @@ static hda_nid_t stac927x_mux_nids[3] = { | |||
340 | 0x15, 0x16, 0x17 | 354 | 0x15, 0x16, 0x17 |
341 | }; | 355 | }; |
342 | 356 | ||
357 | static hda_nid_t stac927x_smux_nids[1] = { | ||
358 | 0x21, | ||
359 | }; | ||
360 | |||
343 | static hda_nid_t stac927x_dac_nids[6] = { | 361 | static hda_nid_t stac927x_dac_nids[6] = { |
344 | 0x02, 0x03, 0x04, 0x05, 0x06, 0 | 362 | 0x02, 0x03, 0x04, 0x05, 0x06, 0 |
345 | }; | 363 | }; |
@@ -365,6 +383,10 @@ static hda_nid_t stac9205_dmux_nids[1] = { | |||
365 | 0x1d, | 383 | 0x1d, |
366 | }; | 384 | }; |
367 | 385 | ||
386 | static hda_nid_t stac9205_smux_nids[1] = { | ||
387 | 0x21, | ||
388 | }; | ||
389 | |||
368 | #define STAC9205_NUM_DMICS 2 | 390 | #define STAC9205_NUM_DMICS 2 |
369 | static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { | 391 | static hda_nid_t stac9205_dmic_nids[STAC9205_NUM_DMICS + 1] = { |
370 | 0x17, 0x18, 0 | 392 | 0x17, 0x18, 0 |
@@ -388,7 +410,7 @@ static hda_nid_t stac922x_pin_nids[10] = { | |||
388 | static hda_nid_t stac92hd73xx_pin_nids[13] = { | 410 | static hda_nid_t stac92hd73xx_pin_nids[13] = { |
389 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 411 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, |
390 | 0x0f, 0x10, 0x11, 0x12, 0x13, | 412 | 0x0f, 0x10, 0x11, 0x12, 0x13, |
391 | 0x14, 0x1e, 0x22 | 413 | 0x14, 0x22, 0x23 |
392 | }; | 414 | }; |
393 | 415 | ||
394 | static hda_nid_t stac92hd83xxx_pin_nids[14] = { | 416 | static hda_nid_t stac92hd83xxx_pin_nids[14] = { |
@@ -443,6 +465,36 @@ static int stac92xx_dmux_enum_put(struct snd_kcontrol *kcontrol, | |||
443 | spec->dmux_nids[dmux_idx], &spec->cur_dmux[dmux_idx]); | 465 | spec->dmux_nids[dmux_idx], &spec->cur_dmux[dmux_idx]); |
444 | } | 466 | } |
445 | 467 | ||
468 | static int stac92xx_smux_enum_info(struct snd_kcontrol *kcontrol, | ||
469 | struct snd_ctl_elem_info *uinfo) | ||
470 | { | ||
471 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
472 | struct sigmatel_spec *spec = codec->spec; | ||
473 | return snd_hda_input_mux_info(spec->sinput_mux, uinfo); | ||
474 | } | ||
475 | |||
476 | static int stac92xx_smux_enum_get(struct snd_kcontrol *kcontrol, | ||
477 | struct snd_ctl_elem_value *ucontrol) | ||
478 | { | ||
479 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
480 | struct sigmatel_spec *spec = codec->spec; | ||
481 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
482 | |||
483 | ucontrol->value.enumerated.item[0] = spec->cur_smux[smux_idx]; | ||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, | ||
488 | struct snd_ctl_elem_value *ucontrol) | ||
489 | { | ||
490 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
491 | struct sigmatel_spec *spec = codec->spec; | ||
492 | unsigned int smux_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
493 | |||
494 | return snd_hda_input_mux_put(codec, spec->sinput_mux, ucontrol, | ||
495 | spec->smux_nids[smux_idx], &spec->cur_smux[smux_idx]); | ||
496 | } | ||
497 | |||
446 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | 498 | static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) |
447 | { | 499 | { |
448 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 500 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
@@ -993,6 +1045,15 @@ static struct snd_kcontrol_new stac_dmux_mixer = { | |||
993 | .put = stac92xx_dmux_enum_put, | 1045 | .put = stac92xx_dmux_enum_put, |
994 | }; | 1046 | }; |
995 | 1047 | ||
1048 | static struct snd_kcontrol_new stac_smux_mixer = { | ||
1049 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1050 | .name = "IEC958 Mux", | ||
1051 | /* count set later */ | ||
1052 | .info = stac92xx_smux_enum_info, | ||
1053 | .get = stac92xx_smux_enum_get, | ||
1054 | .put = stac92xx_smux_enum_put, | ||
1055 | }; | ||
1056 | |||
996 | static const char *slave_vols[] = { | 1057 | static const char *slave_vols[] = { |
997 | "Front Playback Volume", | 1058 | "Front Playback Volume", |
998 | "Surround Playback Volume", | 1059 | "Surround Playback Volume", |
@@ -1044,6 +1105,13 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1044 | if (err < 0) | 1105 | if (err < 0) |
1045 | return err; | 1106 | return err; |
1046 | } | 1107 | } |
1108 | if (spec->num_smuxes > 0) { | ||
1109 | stac_smux_mixer.count = spec->num_smuxes; | ||
1110 | err = snd_ctl_add(codec->bus->card, | ||
1111 | snd_ctl_new1(&stac_smux_mixer, codec)); | ||
1112 | if (err < 0) | ||
1113 | return err; | ||
1114 | } | ||
1047 | 1115 | ||
1048 | if (spec->multiout.dig_out_nid) { | 1116 | if (spec->multiout.dig_out_nid) { |
1049 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | 1117 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); |
@@ -2811,6 +2879,34 @@ static int stac92xx_auto_create_mux_input_ctls(struct hda_codec *codec) | |||
2811 | return 0; | 2879 | return 0; |
2812 | }; | 2880 | }; |
2813 | 2881 | ||
2882 | static const char *stac92xx_spdif_labels[3] = { | ||
2883 | "Digital Playback", "Analog Mux 1", "Analog Mux 2" | ||
2884 | }; | ||
2885 | |||
2886 | static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec) | ||
2887 | { | ||
2888 | struct sigmatel_spec *spec = codec->spec; | ||
2889 | struct hda_input_mux *spdif_mux = &spec->private_smux; | ||
2890 | int i, num_cons; | ||
2891 | hda_nid_t con_lst[ARRAY_SIZE(stac92xx_spdif_labels)]; | ||
2892 | |||
2893 | num_cons = snd_hda_get_connections(codec, | ||
2894 | spec->smux_nids[0], | ||
2895 | con_lst, | ||
2896 | HDA_MAX_NUM_INPUTS); | ||
2897 | if (!num_cons || num_cons > ARRAY_SIZE(stac92xx_spdif_labels)) | ||
2898 | return -EINVAL; | ||
2899 | |||
2900 | for (i = 0; i < num_cons; i++) { | ||
2901 | spdif_mux->items[spdif_mux->num_items].label = | ||
2902 | stac92xx_spdif_labels[i]; | ||
2903 | spdif_mux->items[spdif_mux->num_items].index = i; | ||
2904 | spdif_mux->num_items++; | ||
2905 | } | ||
2906 | |||
2907 | return 0; | ||
2908 | } | ||
2909 | |||
2814 | /* labels for dmic mux inputs */ | 2910 | /* labels for dmic mux inputs */ |
2815 | static const char *stac92xx_dmic_labels[5] = { | 2911 | static const char *stac92xx_dmic_labels[5] = { |
2816 | "Analog Inputs", "Digital Mic 1", "Digital Mic 2", | 2912 | "Analog Inputs", "Digital Mic 1", "Digital Mic 2", |
@@ -3114,6 +3210,11 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3114 | if (err < 0) | 3210 | if (err < 0) |
3115 | return err; | 3211 | return err; |
3116 | } | 3212 | } |
3213 | if (spec->num_smuxes > 0) { | ||
3214 | err = stac92xx_auto_create_spdif_mux_ctls(codec); | ||
3215 | if (err < 0) | ||
3216 | return err; | ||
3217 | } | ||
3117 | 3218 | ||
3118 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3219 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
3119 | if (spec->multiout.max_channels > 2) | 3220 | if (spec->multiout.max_channels > 2) |
@@ -3130,6 +3231,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3130 | spec->input_mux = &spec->private_imux; | 3231 | spec->input_mux = &spec->private_imux; |
3131 | if (!spec->dinput_mux) | 3232 | if (!spec->dinput_mux) |
3132 | spec->dinput_mux = &spec->private_dimux; | 3233 | spec->dinput_mux = &spec->private_dimux; |
3234 | spec->sinput_mux = &spec->private_smux; | ||
3133 | spec->mono_mux = &spec->private_mono_mux; | 3235 | spec->mono_mux = &spec->private_mono_mux; |
3134 | 3236 | ||
3135 | return 1; | 3237 | return 1; |
@@ -3800,10 +3902,12 @@ again: | |||
3800 | spec->adc_nids = stac92hd73xx_adc_nids; | 3902 | spec->adc_nids = stac92hd73xx_adc_nids; |
3801 | spec->dmic_nids = stac92hd73xx_dmic_nids; | 3903 | spec->dmic_nids = stac92hd73xx_dmic_nids; |
3802 | spec->dmux_nids = stac92hd73xx_dmux_nids; | 3904 | spec->dmux_nids = stac92hd73xx_dmux_nids; |
3905 | spec->smux_nids = stac92hd73xx_smux_nids; | ||
3803 | 3906 | ||
3804 | spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids); | 3907 | spec->num_muxes = ARRAY_SIZE(stac92hd73xx_mux_nids); |
3805 | spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids); | 3908 | spec->num_adcs = ARRAY_SIZE(stac92hd73xx_adc_nids); |
3806 | spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids); | 3909 | spec->num_dmuxes = ARRAY_SIZE(stac92hd73xx_dmux_nids); |
3910 | spec->num_smuxes = ARRAY_SIZE(stac92hd73xx_smux_nids); | ||
3807 | spec->dinput_mux = &stac92hd73xx_dmux; | 3911 | spec->dinput_mux = &stac92hd73xx_dmux; |
3808 | /* GPIO0 High = Enable EAPD */ | 3912 | /* GPIO0 High = Enable EAPD */ |
3809 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; | 3913 | spec->eapd_mask = spec->gpio_mask = spec->gpio_dir = 0x1; |
@@ -3842,7 +3946,7 @@ again: | |||
3842 | spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); | 3946 | spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids); |
3843 | spec->pwr_nids = stac92hd73xx_pwr_nids; | 3947 | spec->pwr_nids = stac92hd73xx_pwr_nids; |
3844 | 3948 | ||
3845 | err = stac92xx_parse_auto_config(codec, 0x22, 0x24); | 3949 | err = stac92xx_parse_auto_config(codec, 0x25, 0x27); |
3846 | 3950 | ||
3847 | if (!err) { | 3951 | if (!err) { |
3848 | if (spec->board_config < 0) { | 3952 | if (spec->board_config < 0) { |
@@ -4081,11 +4185,13 @@ again: | |||
4081 | spec->adc_nids = stac92hd71bxx_adc_nids; | 4185 | spec->adc_nids = stac92hd71bxx_adc_nids; |
4082 | spec->dmic_nids = stac92hd71bxx_dmic_nids; | 4186 | spec->dmic_nids = stac92hd71bxx_dmic_nids; |
4083 | spec->dmux_nids = stac92hd71bxx_dmux_nids; | 4187 | spec->dmux_nids = stac92hd71bxx_dmux_nids; |
4188 | spec->smux_nids = stac92hd71bxx_smux_nids; | ||
4084 | spec->pwr_nids = stac92hd71bxx_pwr_nids; | 4189 | spec->pwr_nids = stac92hd71bxx_pwr_nids; |
4085 | 4190 | ||
4086 | spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); | 4191 | spec->num_muxes = ARRAY_SIZE(stac92hd71bxx_mux_nids); |
4087 | spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); | 4192 | spec->num_adcs = ARRAY_SIZE(stac92hd71bxx_adc_nids); |
4088 | spec->num_dmics = STAC92HD71BXX_NUM_DMICS; | 4193 | spec->num_dmics = STAC92HD71BXX_NUM_DMICS; |
4194 | spec->num_smuxes = ARRAY_SIZE(stac92hd71bxx_smux_nids); | ||
4089 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); | 4195 | spec->num_dmuxes = ARRAY_SIZE(stac92hd71bxx_dmux_nids); |
4090 | 4196 | ||
4091 | spec->multiout.num_dacs = 1; | 4197 | spec->multiout.num_dacs = 1; |
@@ -4254,6 +4360,8 @@ static int patch_stac927x(struct hda_codec *codec) | |||
4254 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); | 4360 | spec->num_adcs = ARRAY_SIZE(stac927x_adc_nids); |
4255 | spec->mux_nids = stac927x_mux_nids; | 4361 | spec->mux_nids = stac927x_mux_nids; |
4256 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); | 4362 | spec->num_muxes = ARRAY_SIZE(stac927x_mux_nids); |
4363 | spec->smux_nids = stac927x_smux_nids; | ||
4364 | spec->num_smuxes = ARRAY_SIZE(stac927x_smux_nids); | ||
4257 | spec->dac_list = stac927x_dac_nids; | 4365 | spec->dac_list = stac927x_dac_nids; |
4258 | spec->multiout.dac_nids = spec->dac_nids; | 4366 | spec->multiout.dac_nids = spec->dac_nids; |
4259 | 4367 | ||
@@ -4375,6 +4483,8 @@ static int patch_stac9205(struct hda_codec *codec) | |||
4375 | spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids); | 4483 | spec->num_adcs = ARRAY_SIZE(stac9205_adc_nids); |
4376 | spec->mux_nids = stac9205_mux_nids; | 4484 | spec->mux_nids = stac9205_mux_nids; |
4377 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); | 4485 | spec->num_muxes = ARRAY_SIZE(stac9205_mux_nids); |
4486 | spec->smux_nids = stac9205_smux_nids; | ||
4487 | spec->num_smuxes = ARRAY_SIZE(stac9205_smux_nids); | ||
4378 | spec->dmic_nids = stac9205_dmic_nids; | 4488 | spec->dmic_nids = stac9205_dmic_nids; |
4379 | spec->num_dmics = STAC9205_NUM_DMICS; | 4489 | spec->num_dmics = STAC9205_NUM_DMICS; |
4380 | spec->dmux_nids = stac9205_dmux_nids; | 4490 | spec->dmux_nids = stac9205_dmux_nids; |