diff options
Diffstat (limited to 'sound/pci/ctxfi/ctmixer.c')
-rw-r--r-- | sound/pci/ctxfi/ctmixer.c | 145 |
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); | |||
236 | static void | 225 | static void |
237 | ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type); | 226 | ct_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. */ | ||
239 | static struct snd_kcontrol *kctls[2] = {NULL}; | 230 | static struct snd_kcontrol *kctls[2] = {NULL}; |
240 | 231 | ||
241 | static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index) | 232 | static 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 | ||
414 | static 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 | |||
424 | static 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 | |||
432 | static 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 | |||
441 | static 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 | |||
449 | static 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 | |||
459 | static 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 | |||
467 | static 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 | |||
477 | static 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 | |||
423 | static void | 485 | static void |
424 | do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type) | 486 | do_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) | |||
465 | static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state) | 527 | static 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 | } |