2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
11 * This file contains the implementation of alsa mixer device functions.
21 #include <sound/core.h>
22 #include <sound/control.h>
23 #include <sound/asoundef.h>
24 #include <sound/pcm.h>
25 #include <linux/slab.h>
38 /* volume control mixers */
61 /* this should always be the last one */
65 enum CTALSA_MIXER_CTL {
66 /* volume control mixers */
83 /* switch control mixers */
100 /* this should always be the last one */
104 #define VOL_MIXER_START MIXER_MASTER_P
105 #define VOL_MIXER_END MIXER_SPDIFI_C
106 #define VOL_MIXER_NUM (VOL_MIXER_END - VOL_MIXER_START + 1)
107 #define SWH_MIXER_START MIXER_PCM_C_S
108 #define SWH_MIXER_END MIXER_DIGITAL_IO_S
109 #define SWH_CAPTURE_START MIXER_PCM_C_S
110 #define SWH_CAPTURE_END MIXER_SPDIFI_C_S
114 struct ct_kcontrol_init {
119 static struct ct_kcontrol_init
120 ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
123 .name = "Master Playback Volume",
127 .name = "Master Capture Volume",
131 .name = "PCM Playback Volume",
135 .name = "PCM Capture Volume",
139 .name = "Line-in Playback Volume",
143 .name = "Line-in Capture Volume",
147 .name = "Mic Playback Volume",
151 .name = "Mic Capture Volume",
155 .name = "S/PDIF-in Playback Volume",
159 .name = "S/PDIF-in Capture Volume",
163 .name = "S/PDIF-out Playback Volume",
167 .name = "Front Playback Volume",
171 .name = "Surround Playback Volume",
175 .name = "Center/LFE Playback Volume",
179 .name = "Rear Playback Volume",
184 .name = "PCM Capture Switch",
186 [MIXER_LINEIN_C_S] = {
188 .name = "Line-in Capture Switch",
192 .name = "Mic Capture Switch",
194 [MIXER_SPDIFI_C_S] = {
196 .name = "S/PDIF-in Capture Switch",
198 [MIXER_LINEIN_P_S] = {
200 .name = "Line-in Playback Switch",
202 [MIXER_SPDIFO_P_S] = {
204 .name = "S/PDIF-out Playback Switch",
206 [MIXER_SPDIFI_P_S] = {
208 .name = "S/PDIF-in Playback Switch",
210 [MIXER_WAVEF_P_S] = {
212 .name = "Front Playback Switch",
214 [MIXER_WAVES_P_S] = {
216 .name = "Surround Playback Switch",
218 [MIXER_WAVEC_P_S] = {
220 .name = "Center/LFE Playback Switch",
222 [MIXER_WAVER_P_S] = {
224 .name = "Rear Playback Switch",
226 [MIXER_DIGITAL_IO_S] = {
228 .name = "Digit-IO Playback Switch",
233 ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
236 ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
238 static struct snd_kcontrol *kctls[2] = {NULL};
240 static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
242 switch (alsa_index) {
243 case MIXER_MASTER_P: return AMIXER_MASTER_F;
244 case MIXER_MASTER_C: return AMIXER_MASTER_F_C;
245 case MIXER_PCM_P: return AMIXER_PCM_F;
247 case MIXER_PCM_C_S: return AMIXER_PCM_F_C;
248 case MIXER_LINEIN_P: return AMIXER_LINEIN;
250 case MIXER_LINEIN_C_S: return AMIXER_LINEIN_C;
251 case MIXER_MIC_P: return AMIXER_MIC;
253 case MIXER_MIC_C_S: return AMIXER_MIC_C;
254 case MIXER_SPDIFI_P: return AMIXER_SPDIFI;
256 case MIXER_SPDIFI_C_S: return AMIXER_SPDIFI_C;
257 case MIXER_SPDIFO_P: return AMIXER_SPDIFO;
258 case MIXER_WAVEF_P: return AMIXER_WAVE_F;
259 case MIXER_WAVES_P: return AMIXER_WAVE_S;
260 case MIXER_WAVEC_P: return AMIXER_WAVE_C;
261 case MIXER_WAVER_P: return AMIXER_WAVE_R;
262 default: return NUM_CT_AMIXERS;
266 static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index)
269 case AMIXER_MASTER_F: return AMIXER_MASTER_F_C;
270 case AMIXER_PCM_F: return AMIXER_PCM_F_C;
271 case AMIXER_SPDIFI: return AMIXER_SPDIFI_C;
272 case AMIXER_LINEIN: return AMIXER_LINEIN_C;
273 case AMIXER_MIC: return AMIXER_MIC_C;
274 default: return NUM_CT_AMIXERS;
279 get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type)
281 return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START)))
286 set_switch_state(struct ct_mixer *mixer,
287 enum CTALSA_MIXER_CTL type, unsigned char state)
290 mixer->switch_state |= (0x1 << (type - SWH_MIXER_START));
292 mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
295 /* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
296 * from 2^-6 to (1+1023/1024) */
297 static unsigned int uint16_to_float14(unsigned int x)
309 for (i = 0; !(x & 0x400); i++)
312 x = (((7 - i) & 0x7) << 10) | (x & 0x3ff);
317 static unsigned int float14_to_uint16(unsigned int x)
335 static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
336 struct snd_ctl_elem_info *uinfo)
338 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
340 uinfo->value.integer.min = 0;
341 uinfo->value.integer.max = 43690;
342 uinfo->value.integer.step = 128;
347 static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
348 struct snd_ctl_elem_value *ucontrol)
350 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
351 enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
352 struct amixer *amixer = NULL;
355 for (i = 0; i < 2; i++) {
356 amixer = ((struct ct_mixer *)atc->mixer)->
357 amixers[type*CHN_NUM+i];
358 /* Convert 14-bit float-point scale to 16-bit integer volume */
359 ucontrol->value.integer.value[i] =
360 (float14_to_uint16(amixer->ops->get_scale(amixer)) & 0xffff);
366 static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
367 struct snd_ctl_elem_value *ucontrol)
369 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
370 struct ct_mixer *mixer = atc->mixer;
371 enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
372 struct amixer *amixer = NULL;
373 int i = 0, j = 0, change = 0, val = 0;
375 for (i = 0; i < 2; i++) {
376 /* Convert 16-bit integer volume to 14-bit float-point scale */
377 val = (ucontrol->value.integer.value[i] & 0xffff);
378 amixer = mixer->amixers[type*CHN_NUM+i];
379 if ((float14_to_uint16(amixer->ops->get_scale(amixer)) & 0xff80)
381 val = uint16_to_float14(val);
382 amixer->ops->set_scale(amixer, val);
383 amixer->ops->commit_write(amixer);
385 /* Synchronize Master/PCM playback AMIXERs. */
386 if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) {
387 for (j = 1; j < 4; j++) {
389 amixers[(type+j)*CHN_NUM+i];
390 amixer->ops->set_scale(amixer, val);
391 amixer->ops->commit_write(amixer);
400 static struct snd_kcontrol_new vol_ctl = {
401 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
402 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
403 .info = ct_alsa_mix_volume_info,
404 .get = ct_alsa_mix_volume_get,
405 .put = ct_alsa_mix_volume_put
409 do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
412 if (MIXER_LINEIN_C_S == type) {
413 atc->select_line_in(atc);
414 set_switch_state(atc->mixer, MIXER_MIC_C_S, 0);
415 snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
417 } else if (MIXER_MIC_C_S == type) {
418 atc->select_mic_in(atc);
419 set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0);
420 snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
426 do_digit_io_switch(struct ct_atc *atc, int state)
428 struct ct_mixer *mixer = atc->mixer;
431 atc->select_digit_io(atc);
432 atc->spdif_out_unmute(atc,
433 get_switch_state(mixer, MIXER_SPDIFO_P_S));
434 atc->spdif_in_unmute(atc, 1);
435 atc->line_in_unmute(atc, 0);
439 if (get_switch_state(mixer, MIXER_LINEIN_C_S))
440 atc->select_line_in(atc);
441 else if (get_switch_state(mixer, MIXER_MIC_C_S))
442 atc->select_mic_in(atc);
444 atc->spdif_out_unmute(atc, 0);
445 atc->spdif_in_unmute(atc, 0);
446 atc->line_in_unmute(atc, 1);
450 static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol,
451 struct snd_ctl_elem_info *uinfo)
453 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
455 uinfo->value.integer.min = 0;
456 uinfo->value.integer.max = 1;
457 uinfo->value.integer.step = 1;
462 static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol,
463 struct snd_ctl_elem_value *ucontrol)
465 struct ct_mixer *mixer =
466 ((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer;
467 enum CTALSA_MIXER_CTL type = kcontrol->private_value;
469 ucontrol->value.integer.value[0] = get_switch_state(mixer, type);
473 static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol,
474 struct snd_ctl_elem_value *ucontrol)
476 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
477 struct ct_mixer *mixer = atc->mixer;
478 enum CTALSA_MIXER_CTL type = kcontrol->private_value;
481 state = ucontrol->value.integer.value[0];
482 if (get_switch_state(mixer, type) == state)
485 set_switch_state(mixer, type, state);
486 /* Do changes in mixer. */
487 if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
489 ct_mixer_recording_select(mixer,
490 get_amixer_index(type));
492 ct_mixer_recording_unselect(mixer,
493 get_amixer_index(type));
496 /* Do changes out of mixer. */
497 if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type))
498 do_line_mic_switch(atc, type);
499 else if (MIXER_WAVEF_P_S == type)
500 atc->line_front_unmute(atc, state);
501 else if (MIXER_WAVES_P_S == type)
502 atc->line_surround_unmute(atc, state);
503 else if (MIXER_WAVEC_P_S == type)
504 atc->line_clfe_unmute(atc, state);
505 else if (MIXER_WAVER_P_S == type)
506 atc->line_rear_unmute(atc, state);
507 else if (MIXER_LINEIN_P_S == type)
508 atc->line_in_unmute(atc, state);
509 else if (MIXER_SPDIFO_P_S == type)
510 atc->spdif_out_unmute(atc, state);
511 else if (MIXER_SPDIFI_P_S == type)
512 atc->spdif_in_unmute(atc, state);
513 else if (MIXER_DIGITAL_IO_S == type)
514 do_digit_io_switch(atc, state);
519 static struct snd_kcontrol_new swh_ctl = {
520 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
522 .info = ct_alsa_mix_switch_info,
523 .get = ct_alsa_mix_switch_get,
524 .put = ct_alsa_mix_switch_put
527 static int ct_spdif_info(struct snd_kcontrol *kcontrol,
528 struct snd_ctl_elem_info *uinfo)
530 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
535 static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
536 struct snd_ctl_elem_value *ucontrol)
538 ucontrol->value.iec958.status[0] = 0xff;
539 ucontrol->value.iec958.status[1] = 0xff;
540 ucontrol->value.iec958.status[2] = 0xff;
541 ucontrol->value.iec958.status[3] = 0xff;
545 static int ct_spdif_default_get(struct snd_kcontrol *kcontrol,
546 struct snd_ctl_elem_value *ucontrol)
548 unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF;
550 ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
551 ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
552 ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
553 ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
558 static int ct_spdif_get(struct snd_kcontrol *kcontrol,
559 struct snd_ctl_elem_value *ucontrol)
561 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
562 unsigned int status = 0;
564 atc->spdif_out_get_status(atc, &status);
565 ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
566 ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
567 ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
568 ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
573 static int ct_spdif_put(struct snd_kcontrol *kcontrol,
574 struct snd_ctl_elem_value *ucontrol)
576 struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
578 unsigned int status = 0, old_status = 0;
580 status = (ucontrol->value.iec958.status[0] << 0) |
581 (ucontrol->value.iec958.status[1] << 8) |
582 (ucontrol->value.iec958.status[2] << 16) |
583 (ucontrol->value.iec958.status[3] << 24);
585 atc->spdif_out_get_status(atc, &old_status);
586 change = (old_status != status);
588 atc->spdif_out_set_status(atc, status);
593 static struct snd_kcontrol_new iec958_mask_ctl = {
594 .access = SNDRV_CTL_ELEM_ACCESS_READ,
595 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
596 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
598 .info = ct_spdif_info,
599 .get = ct_spdif_get_mask,
600 .private_value = MIXER_IEC958_MASK
603 static struct snd_kcontrol_new iec958_default_ctl = {
604 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
605 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
607 .info = ct_spdif_info,
608 .get = ct_spdif_default_get,
610 .private_value = MIXER_IEC958_DEFAULT
613 static struct snd_kcontrol_new iec958_ctl = {
614 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
615 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
616 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
618 .info = ct_spdif_info,
621 .private_value = MIXER_IEC958_STREAM
624 #define NUM_IEC958_CTL 3
627 ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
629 struct snd_kcontrol *kctl = NULL;
632 kctl = snd_ctl_new1(new, mixer->atc);
636 if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface)
637 kctl->id.device = IEC958;
639 err = snd_ctl_add(mixer->atc->card, kctl);
643 switch (new->private_value) {
644 case MIXER_LINEIN_C_S:
645 kctls[0] = kctl; break;
647 kctls[1] = kctl; break;
655 static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
657 enum CTALSA_MIXER_CTL type = 0;
658 struct ct_atc *atc = mixer->atc;
661 /* Create snd kcontrol instances on demand */
662 for (type = VOL_MIXER_START; type <= VOL_MIXER_END; type++) {
663 if (ct_kcontrol_init_table[type].ctl) {
664 vol_ctl.name = ct_kcontrol_init_table[type].name;
665 vol_ctl.private_value = (unsigned long)type;
666 err = ct_mixer_kcontrol_new(mixer, &vol_ctl);
672 ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl =
673 atc->have_digit_io_switch(atc);
674 for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) {
675 if (ct_kcontrol_init_table[type].ctl) {
676 swh_ctl.name = ct_kcontrol_init_table[type].name;
677 swh_ctl.private_value = (unsigned long)type;
678 err = ct_mixer_kcontrol_new(mixer, &swh_ctl);
684 err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl);
688 err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl);
692 err = ct_mixer_kcontrol_new(mixer, &iec958_ctl);
696 atc->line_front_unmute(atc, 1);
697 set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
698 atc->line_surround_unmute(atc, 0);
699 set_switch_state(mixer, MIXER_WAVES_P_S, 0);
700 atc->line_clfe_unmute(atc, 0);
701 set_switch_state(mixer, MIXER_WAVEC_P_S, 0);
702 atc->line_rear_unmute(atc, 0);
703 set_switch_state(mixer, MIXER_WAVER_P_S, 0);
704 atc->spdif_out_unmute(atc, 0);
705 set_switch_state(mixer, MIXER_SPDIFO_P_S, 0);
706 atc->line_in_unmute(atc, 0);
707 set_switch_state(mixer, MIXER_LINEIN_P_S, 0);
708 atc->spdif_in_unmute(atc, 0);
709 set_switch_state(mixer, MIXER_SPDIFI_P_S, 0);
711 set_switch_state(mixer, MIXER_PCM_C_S, 1);
712 set_switch_state(mixer, MIXER_LINEIN_C_S, 1);
713 set_switch_state(mixer, MIXER_SPDIFI_C_S, 1);
719 ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
721 struct amixer *amix_d = NULL;
722 struct sum *sum_c = NULL;
725 for (i = 0; i < 2; i++) {
726 amix_d = mixer->amixers[type*CHN_NUM+i];
727 sum_c = mixer->sums[SUM_IN_F_C*CHN_NUM+i];
728 amix_d->ops->set_sum(amix_d, sum_c);
729 amix_d->ops->commit_write(amix_d);
734 ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
736 struct amixer *amix_d = NULL;
739 for (i = 0; i < 2; i++) {
740 amix_d = mixer->amixers[type*CHN_NUM+i];
741 amix_d->ops->set_sum(amix_d, NULL);
742 amix_d->ops->commit_write(amix_d);
746 static int ct_mixer_get_resources(struct ct_mixer *mixer)
748 struct sum_mgr *sum_mgr = NULL;
749 struct sum *sum = NULL;
750 struct sum_desc sum_desc = {0};
751 struct amixer_mgr *amixer_mgr = NULL;
752 struct amixer *amixer = NULL;
753 struct amixer_desc am_desc = {0};
757 /* Allocate sum resources for mixer obj */
758 sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
759 sum_desc.msr = mixer->atc->msr;
760 for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
761 err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum);
763 printk(KERN_ERR "Failed to get sum resources for "
767 mixer->sums[i] = sum;
772 /* Allocate amixer resources for mixer obj */
773 amixer_mgr = (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
774 am_desc.msr = mixer->atc->msr;
775 for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
776 err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer);
778 printk(KERN_ERR "Failed to get amixer resources for "
782 mixer->amixers[i] = amixer;
790 for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
791 if (NULL != mixer->amixers[i]) {
792 amixer = mixer->amixers[i];
793 amixer_mgr->put_amixer(amixer_mgr, amixer);
794 mixer->amixers[i] = NULL;
798 for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
799 if (NULL != mixer->sums[i]) {
800 sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
801 mixer->sums[i] = NULL;
808 static int ct_mixer_get_mem(struct ct_mixer **rmixer)
810 struct ct_mixer *mixer = NULL;
814 /* Allocate mem for mixer obj */
815 mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
819 mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM),
821 if (NULL == mixer->amixers) {
825 mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL);
826 if (NULL == mixer->sums) {
835 kfree(mixer->amixers);
841 static int ct_mixer_topology_build(struct ct_mixer *mixer)
843 struct sum *sum = NULL;
844 struct amixer *amix_d = NULL, *amix_s = NULL;
845 enum CT_AMIXER_CTL i = 0, j = 0;
847 /* Build topology from destination to source */
849 /* Set up Master mixer */
850 for (i = AMIXER_MASTER_F, j = SUM_IN_F;
851 i <= AMIXER_MASTER_S; i++, j++) {
852 amix_d = mixer->amixers[i*CHN_NUM];
853 sum = mixer->sums[j*CHN_NUM];
854 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
855 amix_d = mixer->amixers[i*CHN_NUM+1];
856 sum = mixer->sums[j*CHN_NUM+1];
857 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
860 /* Set up Wave-out mixer */
861 for (i = AMIXER_WAVE_F, j = AMIXER_MASTER_F;
862 i <= AMIXER_WAVE_S; i++, j++) {
863 amix_d = mixer->amixers[i*CHN_NUM];
864 amix_s = mixer->amixers[j*CHN_NUM];
865 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
866 amix_d = mixer->amixers[i*CHN_NUM+1];
867 amix_s = mixer->amixers[j*CHN_NUM+1];
868 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
871 /* Set up S/PDIF-out mixer */
872 amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM];
873 amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM];
874 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
875 amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM+1];
876 amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM+1];
877 amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
879 /* Set up PCM-in mixer */
880 for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) {
881 amix_d = mixer->amixers[i*CHN_NUM];
882 sum = mixer->sums[j*CHN_NUM];
883 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
884 amix_d = mixer->amixers[i*CHN_NUM+1];
885 sum = mixer->sums[j*CHN_NUM+1];
886 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
889 /* Set up Line-in mixer */
890 amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM];
891 sum = mixer->sums[SUM_IN_F*CHN_NUM];
892 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
893 amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM+1];
894 sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
895 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
897 /* Set up Mic-in mixer */
898 amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM];
899 sum = mixer->sums[SUM_IN_F*CHN_NUM];
900 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
901 amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM+1];
902 sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
903 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
905 /* Set up S/PDIF-in mixer */
906 amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM];
907 sum = mixer->sums[SUM_IN_F*CHN_NUM];
908 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
909 amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM+1];
910 sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
911 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
913 /* Set up Master recording mixer */
914 amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM];
915 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
916 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
917 amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM+1];
918 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
919 amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
921 /* Set up PCM-in recording mixer */
922 amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM];
923 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
924 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
925 amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM+1];
926 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
927 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
929 /* Set up Line-in recording mixer */
930 amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM];
931 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
932 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
933 amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM+1];
934 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
935 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
937 /* Set up Mic-in recording mixer */
938 amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM];
939 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
940 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
941 amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM+1];
942 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
943 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
945 /* Set up S/PDIF-in recording mixer */
946 amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM];
947 sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
948 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
949 amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM+1];
950 sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
951 amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
956 static int mixer_set_input_port(struct amixer *amixer, struct rsc *rsc)
958 amixer->ops->set_input(amixer, rsc);
959 amixer->ops->commit_write(amixer);
964 static enum CT_AMIXER_CTL port_to_amixer(enum MIXER_PORT_T type)
967 case MIX_WAVE_FRONT: return AMIXER_WAVE_F;
968 case MIX_WAVE_SURROUND: return AMIXER_WAVE_S;
969 case MIX_WAVE_CENTLFE: return AMIXER_WAVE_C;
970 case MIX_WAVE_REAR: return AMIXER_WAVE_R;
971 case MIX_PCMO_FRONT: return AMIXER_MASTER_F_C;
972 case MIX_SPDIF_OUT: return AMIXER_SPDIFO;
973 case MIX_LINE_IN: return AMIXER_LINEIN;
974 case MIX_MIC_IN: return AMIXER_MIC;
975 case MIX_SPDIF_IN: return AMIXER_SPDIFI;
976 case MIX_PCMI_FRONT: return AMIXER_PCM_F;
977 case MIX_PCMI_SURROUND: return AMIXER_PCM_S;
978 case MIX_PCMI_CENTLFE: return AMIXER_PCM_C;
979 case MIX_PCMI_REAR: return AMIXER_PCM_R;
984 static int mixer_get_output_ports(struct ct_mixer *mixer,
985 enum MIXER_PORT_T type,
986 struct rsc **rleft, struct rsc **rright)
988 enum CT_AMIXER_CTL amix = port_to_amixer(type);
991 *rleft = &((struct amixer *)mixer->amixers[amix*CHN_NUM])->rsc;
995 &((struct amixer *)mixer->amixers[amix*CHN_NUM+1])->rsc;
1000 static int mixer_set_input_left(struct ct_mixer *mixer,
1001 enum MIXER_PORT_T type, struct rsc *rsc)
1003 enum CT_AMIXER_CTL amix = port_to_amixer(type);
1005 mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1006 amix = get_recording_amixer(amix);
1007 if (amix < NUM_CT_AMIXERS)
1008 mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1014 mixer_set_input_right(struct ct_mixer *mixer,
1015 enum MIXER_PORT_T type, struct rsc *rsc)
1017 enum CT_AMIXER_CTL amix = port_to_amixer(type);
1019 mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1020 amix = get_recording_amixer(amix);
1021 if (amix < NUM_CT_AMIXERS)
1022 mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1027 int ct_mixer_destroy(struct ct_mixer *mixer)
1029 struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
1030 struct amixer_mgr *amixer_mgr =
1031 (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
1032 struct amixer *amixer = NULL;
1035 /* Release amixer resources */
1036 for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
1037 if (NULL != mixer->amixers[i]) {
1038 amixer = mixer->amixers[i];
1039 amixer_mgr->put_amixer(amixer_mgr, amixer);
1043 /* Release sum resources */
1044 for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
1045 if (NULL != mixer->sums[i])
1046 sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
1049 /* Release mem assigned to mixer object */
1051 kfree(mixer->amixers);
1057 int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer)
1059 struct ct_mixer *mixer = NULL;
1064 /* Allocate mem for mixer obj */
1065 err = ct_mixer_get_mem(&mixer);
1069 mixer->switch_state = 0;
1071 /* Set operations */
1072 mixer->get_output_ports = mixer_get_output_ports;
1073 mixer->set_input_left = mixer_set_input_left;
1074 mixer->set_input_right = mixer_set_input_right;
1076 /* Allocate chip resources for mixer obj */
1077 err = ct_mixer_get_resources(mixer);
1081 /* Build internal mixer topology */
1082 ct_mixer_topology_build(mixer);
1089 ct_mixer_destroy(mixer);
1093 int ct_alsa_mix_create(struct ct_atc *atc,
1094 enum CTALSADEVS device,
1095 const char *device_name)
1099 /* Create snd kcontrol instances on demand */
1100 vol_ctl.device = swh_ctl.device = device;
1101 err = ct_mixer_kcontrols_create((struct ct_mixer *)atc->mixer);
1105 strcpy(atc->card->mixername, device_name);