aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ctxfi/ctmixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/ctxfi/ctmixer.c')
-rw-r--r--sound/pci/ctxfi/ctmixer.c145
1 files changed, 112 insertions, 33 deletions
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c
index c3519ff42fbb..0cc13eeef8da 100644
--- a/sound/pci/ctxfi/ctmixer.c
+++ b/sound/pci/ctxfi/ctmixer.c
@@ -86,9 +86,7 @@ enum CTALSA_MIXER_CTL {
86 MIXER_LINEIN_C_S, 86 MIXER_LINEIN_C_S,
87 MIXER_MIC_C_S, 87 MIXER_MIC_C_S,
88 MIXER_SPDIFI_C_S, 88 MIXER_SPDIFI_C_S,
89 MIXER_LINEIN_P_S,
90 MIXER_SPDIFO_P_S, 89 MIXER_SPDIFO_P_S,
91 MIXER_SPDIFI_P_S,
92 MIXER_WAVEF_P_S, 90 MIXER_WAVEF_P_S,
93 MIXER_WAVER_P_S, 91 MIXER_WAVER_P_S,
94 MIXER_WAVEC_P_S, 92 MIXER_WAVEC_P_S,
@@ -137,11 +135,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
137 }, 135 },
138 [MIXER_LINEIN_P] = { 136 [MIXER_LINEIN_P] = {
139 .ctl = 1, 137 .ctl = 1,
140 .name = "Line-in Playback Volume", 138 .name = "Line Playback Volume",
141 }, 139 },
142 [MIXER_LINEIN_C] = { 140 [MIXER_LINEIN_C] = {
143 .ctl = 1, 141 .ctl = 1,
144 .name = "Line-in Capture Volume", 142 .name = "Line Capture Volume",
145 }, 143 },
146 [MIXER_MIC_P] = { 144 [MIXER_MIC_P] = {
147 .ctl = 1, 145 .ctl = 1,
@@ -153,15 +151,15 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
153 }, 151 },
154 [MIXER_SPDIFI_P] = { 152 [MIXER_SPDIFI_P] = {
155 .ctl = 1, 153 .ctl = 1,
156 .name = "S/PDIF-in Playback Volume", 154 .name = "IEC958 Playback Volume",
157 }, 155 },
158 [MIXER_SPDIFI_C] = { 156 [MIXER_SPDIFI_C] = {
159 .ctl = 1, 157 .ctl = 1,
160 .name = "S/PDIF-in Capture Volume", 158 .name = "IEC958 Capture Volume",
161 }, 159 },
162 [MIXER_SPDIFO_P] = { 160 [MIXER_SPDIFO_P] = {
163 .ctl = 1, 161 .ctl = 1,
164 .name = "S/PDIF-out Playback Volume", 162 .name = "Digital Playback Volume",
165 }, 163 },
166 [MIXER_WAVEF_P] = { 164 [MIXER_WAVEF_P] = {
167 .ctl = 1, 165 .ctl = 1,
@@ -179,14 +177,13 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
179 .ctl = 1, 177 .ctl = 1,
180 .name = "Surround Playback Volume", 178 .name = "Surround Playback Volume",
181 }, 179 },
182
183 [MIXER_PCM_C_S] = { 180 [MIXER_PCM_C_S] = {
184 .ctl = 1, 181 .ctl = 1,
185 .name = "PCM Capture Switch", 182 .name = "PCM Capture Switch",
186 }, 183 },
187 [MIXER_LINEIN_C_S] = { 184 [MIXER_LINEIN_C_S] = {
188 .ctl = 1, 185 .ctl = 1,
189 .name = "Line-in Capture Switch", 186 .name = "Line Capture Switch",
190 }, 187 },
191 [MIXER_MIC_C_S] = { 188 [MIXER_MIC_C_S] = {
192 .ctl = 1, 189 .ctl = 1,
@@ -194,19 +191,11 @@ ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
194 }, 191 },
195 [MIXER_SPDIFI_C_S] = { 192 [MIXER_SPDIFI_C_S] = {
196 .ctl = 1, 193 .ctl = 1,
197 .name = "S/PDIF-in Capture Switch", 194 .name = "IEC958 Capture Switch",
198 },
199 [MIXER_LINEIN_P_S] = {
200 .ctl = 1,
201 .name = "Line-in Playback Switch",
202 }, 195 },
203 [MIXER_SPDIFO_P_S] = { 196 [MIXER_SPDIFO_P_S] = {
204 .ctl = 1, 197 .ctl = 1,
205 .name = "S/PDIF-out Playback Switch", 198 .name = "Digital Playback Switch",
206 },
207 [MIXER_SPDIFI_P_S] = {
208 .ctl = 1,
209 .name = "S/PDIF-in Playback Switch",
210 }, 199 },
211 [MIXER_WAVEF_P_S] = { 200 [MIXER_WAVEF_P_S] = {
212 .ctl = 1, 201 .ctl = 1,
@@ -236,6 +225,8 @@ ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
236static void 225static void
237ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); 226ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
238 227
228/* FIXME: this static looks like it would fail if more than one card was */
229/* installed. */
239static struct snd_kcontrol *kctls[2] = {NULL}; 230static struct snd_kcontrol *kctls[2] = {NULL};
240 231
241static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) 232static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
@@ -420,6 +411,77 @@ static struct snd_kcontrol_new vol_ctl = {
420 .tlv = { .p = ct_vol_db_scale }, 411 .tlv = { .p = ct_vol_db_scale },
421}; 412};
422 413
414static int output_switch_info(struct snd_kcontrol *kcontrol,
415 struct snd_ctl_elem_info *info)
416{
417 static const char *const names[3] = {
418 "FP Headphones", "Headphones", "Speakers"
419 };
420
421 return snd_ctl_enum_info(info, 1, 3, names);
422}
423
424static int output_switch_get(struct snd_kcontrol *kcontrol,
425 struct snd_ctl_elem_value *ucontrol)
426{
427 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
428 ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc);
429 return 0;
430}
431
432static int output_switch_put(struct snd_kcontrol *kcontrol,
433 struct snd_ctl_elem_value *ucontrol)
434{
435 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
436 if (ucontrol->value.enumerated.item[0] > 2)
437 return -EINVAL;
438 return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]);
439}
440
441static struct snd_kcontrol_new output_ctl = {
442 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
443 .name = "Analog Output Playback Enum",
444 .info = output_switch_info,
445 .get = output_switch_get,
446 .put = output_switch_put,
447};
448
449static int mic_source_switch_info(struct snd_kcontrol *kcontrol,
450 struct snd_ctl_elem_info *info)
451{
452 static const char *const names[3] = {
453 "Mic", "FP Mic", "Aux"
454 };
455
456 return snd_ctl_enum_info(info, 1, 3, names);
457}
458
459static int mic_source_switch_get(struct snd_kcontrol *kcontrol,
460 struct snd_ctl_elem_value *ucontrol)
461{
462 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
463 ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc);
464 return 0;
465}
466
467static int mic_source_switch_put(struct snd_kcontrol *kcontrol,
468 struct snd_ctl_elem_value *ucontrol)
469{
470 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
471 if (ucontrol->value.enumerated.item[0] > 2)
472 return -EINVAL;
473 return atc->mic_source_switch_put(atc,
474 ucontrol->value.enumerated.item[0]);
475}
476
477static struct snd_kcontrol_new mic_source_ctl = {
478 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
479 .name = "Mic Source Capture Enum",
480 .info = mic_source_switch_info,
481 .get = mic_source_switch_get,
482 .put = mic_source_switch_put,
483};
484
423static void 485static void
424do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) 486do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
425{ 487{
@@ -465,6 +527,7 @@ do_digit_io_switch(struct ct_atc *atc, int state)
465static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) 527static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
466{ 528{
467 struct ct_mixer *mixer = atc->mixer; 529 struct ct_mixer *mixer = atc->mixer;
530 struct capabilities cap = atc->capabilities(atc);
468 531
469 /* Do changes in mixer. */ 532 /* Do changes in mixer. */
470 if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) { 533 if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
@@ -477,8 +540,17 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
477 } 540 }
478 } 541 }
479 /* Do changes out of mixer. */ 542 /* Do changes out of mixer. */
480 if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) 543 if (!cap.dedicated_mic &&
481 do_line_mic_switch(atc, type); 544 (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) {
545 if (state)
546 do_line_mic_switch(atc, type);
547 atc->line_in_unmute(atc, state);
548 } else if (cap.dedicated_mic && (MIXER_LINEIN_C_S == type))
549 atc->line_in_unmute(atc, state);
550 else if (cap.dedicated_mic && (MIXER_MIC_C_S == type))
551 atc->mic_unmute(atc, state);
552 else if (MIXER_SPDIFI_C_S == type)
553 atc->spdif_in_unmute(atc, state);
482 else if (MIXER_WAVEF_P_S == type) 554 else if (MIXER_WAVEF_P_S == type)
483 atc->line_front_unmute(atc, state); 555 atc->line_front_unmute(atc, state);
484 else if (MIXER_WAVES_P_S == type) 556 else if (MIXER_WAVES_P_S == type)
@@ -487,12 +559,8 @@ static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
487 atc->line_clfe_unmute(atc, state); 559 atc->line_clfe_unmute(atc, state);
488 else if (MIXER_WAVER_P_S == type) 560 else if (MIXER_WAVER_P_S == type)
489 atc->line_rear_unmute(atc, state); 561 atc->line_rear_unmute(atc, state);
490 else if (MIXER_LINEIN_P_S == type)
491 atc->line_in_unmute(atc, state);
492 else if (MIXER_SPDIFO_P_S == type) 562 else if (MIXER_SPDIFO_P_S == type)
493 atc->spdif_out_unmute(atc, state); 563 atc->spdif_out_unmute(atc, state);
494 else if (MIXER_SPDIFI_P_S == type)
495 atc->spdif_in_unmute(atc, state);
496 else if (MIXER_DIGITAL_IO_S == type) 564 else if (MIXER_DIGITAL_IO_S == type)
497 do_digit_io_switch(atc, state); 565 do_digit_io_switch(atc, state);
498 566
@@ -671,6 +739,7 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
671{ 739{
672 enum CTALSA_MIXER_CTL type; 740 enum CTALSA_MIXER_CTL type;
673 struct ct_atc *atc = mixer->atc; 741 struct ct_atc *atc = mixer->atc;
742 struct capabilities cap = atc->capabilities(atc);
674 int err; 743 int err;
675 744
676 /* Create snd kcontrol instances on demand */ 745 /* Create snd kcontrol instances on demand */
@@ -684,8 +753,8 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
684 } 753 }
685 } 754 }
686 755
687 ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = 756 ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch;
688 atc->have_digit_io_switch(atc); 757
689 for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) { 758 for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) {
690 if (ct_kcontrol_init_table[type].ctl) { 759 if (ct_kcontrol_init_table[type].ctl) {
691 swh_ctl.name = ct_kcontrol_init_table[type].name; 760 swh_ctl.name = ct_kcontrol_init_table[type].name;
@@ -708,6 +777,17 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
708 if (err) 777 if (err)
709 return err; 778 return err;
710 779
780 if (cap.output_switch) {
781 err = ct_mixer_kcontrol_new(mixer, &output_ctl);
782 if (err)
783 return err;
784 }
785
786 if (cap.mic_source_switch) {
787 err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl);
788 if (err)
789 return err;
790 }
711 atc->line_front_unmute(atc, 1); 791 atc->line_front_unmute(atc, 1);
712 set_switch_state(mixer, MIXER_WAVEF_P_S, 1); 792 set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
713 atc->line_surround_unmute(atc, 0); 793 atc->line_surround_unmute(atc, 0);
@@ -719,13 +799,12 @@ static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
719 atc->spdif_out_unmute(atc, 0); 799 atc->spdif_out_unmute(atc, 0);
720 set_switch_state(mixer, MIXER_SPDIFO_P_S, 0); 800 set_switch_state(mixer, MIXER_SPDIFO_P_S, 0);
721 atc->line_in_unmute(atc, 0); 801 atc->line_in_unmute(atc, 0);
722 set_switch_state(mixer, MIXER_LINEIN_P_S, 0); 802 if (cap.dedicated_mic)
803 atc->mic_unmute(atc, 0);
723 atc->spdif_in_unmute(atc, 0); 804 atc->spdif_in_unmute(atc, 0);
724 set_switch_state(mixer, MIXER_SPDIFI_P_S, 0); 805 set_switch_state(mixer, MIXER_PCM_C_S, 0);
725 806 set_switch_state(mixer, MIXER_LINEIN_C_S, 0);
726 set_switch_state(mixer, MIXER_PCM_C_S, 1); 807 set_switch_state(mixer, MIXER_SPDIFI_C_S, 0);
727 set_switch_state(mixer, MIXER_LINEIN_C_S, 1);
728 set_switch_state(mixer, MIXER_SPDIFI_C_S, 1);
729 808
730 return 0; 809 return 0;
731} 810}