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 <linux/slab.h>
22 #include <sound/core.h>
23 #include <sound/control.h>
24 #include <sound/asoundef.h>
25 #include <sound/pcm.h>
26 #include <sound/tlv.h>
39 /* volume control mixers */
62 /* this should always be the last one */
66 enum CTALSA_MIXER_CTL
{
67 /* volume control mixers */
84 /* switch control mixers */
99 /* this should always be the last one */
103 #define VOL_MIXER_START MIXER_MASTER_P
104 #define VOL_MIXER_END MIXER_SPDIFI_C
105 #define VOL_MIXER_NUM (VOL_MIXER_END - VOL_MIXER_START + 1)
106 #define SWH_MIXER_START MIXER_PCM_C_S
107 #define SWH_MIXER_END MIXER_DIGITAL_IO_S
108 #define SWH_CAPTURE_START MIXER_PCM_C_S
109 #define SWH_CAPTURE_END MIXER_SPDIFI_C_S
113 struct ct_kcontrol_init
{
118 static struct ct_kcontrol_init
119 ct_kcontrol_init_table
[NUM_CTALSA_MIXERS
] = {
122 .name
= "Master Playback Volume",
126 .name
= "Master Capture Volume",
130 .name
= "PCM Playback Volume",
134 .name
= "PCM Capture Volume",
138 .name
= "Line Playback Volume",
142 .name
= "Line Capture Volume",
146 .name
= "Mic Playback Volume",
150 .name
= "Mic Capture Volume",
154 .name
= "IEC958 Playback Volume",
158 .name
= "IEC958 Capture Volume",
162 .name
= "Digital Playback Volume",
166 .name
= "Front Playback Volume",
170 .name
= "Side Playback Volume",
174 .name
= "Center/LFE Playback Volume",
178 .name
= "Surround Playback Volume",
182 .name
= "PCM Capture Switch",
184 [MIXER_LINEIN_C_S
] = {
186 .name
= "Line Capture Switch",
190 .name
= "Mic Capture Switch",
192 [MIXER_SPDIFI_C_S
] = {
194 .name
= "IEC958 Capture Switch",
196 [MIXER_SPDIFO_P_S
] = {
198 .name
= "Digital Playback Switch",
200 [MIXER_WAVEF_P_S
] = {
202 .name
= "Front Playback Switch",
204 [MIXER_WAVES_P_S
] = {
206 .name
= "Side Playback Switch",
208 [MIXER_WAVEC_P_S
] = {
210 .name
= "Center/LFE Playback Switch",
212 [MIXER_WAVER_P_S
] = {
214 .name
= "Surround Playback Switch",
216 [MIXER_DIGITAL_IO_S
] = {
218 .name
= "Digit-IO Playback Switch",
223 ct_mixer_recording_select(struct ct_mixer
*mixer
, enum CT_AMIXER_CTL type
);
226 ct_mixer_recording_unselect(struct ct_mixer
*mixer
, enum CT_AMIXER_CTL type
);
228 /* FIXME: this static looks like it would fail if more than one card was */
230 static struct snd_kcontrol
*kctls
[2] = {NULL
};
232 static enum CT_AMIXER_CTL
get_amixer_index(enum CTALSA_MIXER_CTL alsa_index
)
234 switch (alsa_index
) {
235 case MIXER_MASTER_P
: return AMIXER_MASTER_F
;
236 case MIXER_MASTER_C
: return AMIXER_MASTER_F_C
;
237 case MIXER_PCM_P
: return AMIXER_PCM_F
;
239 case MIXER_PCM_C_S
: return AMIXER_PCM_F_C
;
240 case MIXER_LINEIN_P
: return AMIXER_LINEIN
;
242 case MIXER_LINEIN_C_S
: return AMIXER_LINEIN_C
;
243 case MIXER_MIC_P
: return AMIXER_MIC
;
245 case MIXER_MIC_C_S
: return AMIXER_MIC_C
;
246 case MIXER_SPDIFI_P
: return AMIXER_SPDIFI
;
248 case MIXER_SPDIFI_C_S
: return AMIXER_SPDIFI_C
;
249 case MIXER_SPDIFO_P
: return AMIXER_SPDIFO
;
250 case MIXER_WAVEF_P
: return AMIXER_WAVE_F
;
251 case MIXER_WAVES_P
: return AMIXER_WAVE_S
;
252 case MIXER_WAVEC_P
: return AMIXER_WAVE_C
;
253 case MIXER_WAVER_P
: return AMIXER_WAVE_R
;
254 default: return NUM_CT_AMIXERS
;
258 static enum CT_AMIXER_CTL
get_recording_amixer(enum CT_AMIXER_CTL index
)
261 case AMIXER_MASTER_F
: return AMIXER_MASTER_F_C
;
262 case AMIXER_PCM_F
: return AMIXER_PCM_F_C
;
263 case AMIXER_SPDIFI
: return AMIXER_SPDIFI_C
;
264 case AMIXER_LINEIN
: return AMIXER_LINEIN_C
;
265 case AMIXER_MIC
: return AMIXER_MIC_C
;
266 default: return NUM_CT_AMIXERS
;
271 get_switch_state(struct ct_mixer
*mixer
, enum CTALSA_MIXER_CTL type
)
273 return (mixer
->switch_state
& (0x1 << (type
- SWH_MIXER_START
)))
278 set_switch_state(struct ct_mixer
*mixer
,
279 enum CTALSA_MIXER_CTL type
, unsigned char state
)
282 mixer
->switch_state
|= (0x1 << (type
- SWH_MIXER_START
));
284 mixer
->switch_state
&= ~(0x1 << (type
- SWH_MIXER_START
));
288 /* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
289 * from 2^-6 to (1+1023/1024) */
290 static unsigned int uint16_to_float14(unsigned int x
)
302 for (i
= 0; !(x
& 0x400); i
++)
305 x
= (((7 - i
) & 0x7) << 10) | (x
& 0x3ff);
310 static unsigned int float14_to_uint16(unsigned int x
)
327 #endif /* not used */
329 #define VOL_SCALE 0x1c
330 #define VOL_MAX 0x100
332 static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale
, -6400, 25, 1);
334 static int ct_alsa_mix_volume_info(struct snd_kcontrol
*kcontrol
,
335 struct snd_ctl_elem_info
*uinfo
)
337 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
339 uinfo
->value
.integer
.min
= 0;
340 uinfo
->value
.integer
.max
= VOL_MAX
;
345 static int ct_alsa_mix_volume_get(struct snd_kcontrol
*kcontrol
,
346 struct snd_ctl_elem_value
*ucontrol
)
348 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
349 enum CT_AMIXER_CTL type
= get_amixer_index(kcontrol
->private_value
);
350 struct amixer
*amixer
;
353 for (i
= 0; i
< 2; i
++) {
354 amixer
= ((struct ct_mixer
*)atc
->mixer
)->
355 amixers
[type
*CHN_NUM
+i
];
356 val
= amixer
->ops
->get_scale(amixer
) / VOL_SCALE
;
359 else if (val
> VOL_MAX
)
361 ucontrol
->value
.integer
.value
[i
] = val
;
367 static int ct_alsa_mix_volume_put(struct snd_kcontrol
*kcontrol
,
368 struct snd_ctl_elem_value
*ucontrol
)
370 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
371 struct ct_mixer
*mixer
= atc
->mixer
;
372 enum CT_AMIXER_CTL type
= get_amixer_index(kcontrol
->private_value
);
373 struct amixer
*amixer
;
374 int i
, j
, val
, oval
, change
= 0;
376 for (i
= 0; i
< 2; i
++) {
377 val
= ucontrol
->value
.integer
.value
[i
];
380 else if (val
> VOL_MAX
)
383 amixer
= mixer
->amixers
[type
*CHN_NUM
+i
];
384 oval
= amixer
->ops
->get_scale(amixer
);
386 amixer
->ops
->set_scale(amixer
, val
);
387 amixer
->ops
->commit_write(amixer
);
389 /* Synchronize Master/PCM playback AMIXERs. */
390 if (AMIXER_MASTER_F
== type
|| AMIXER_PCM_F
== type
) {
391 for (j
= 1; j
< 4; j
++) {
393 amixers
[(type
+j
)*CHN_NUM
+i
];
394 amixer
->ops
->set_scale(amixer
, val
);
395 amixer
->ops
->commit_write(amixer
);
404 static struct snd_kcontrol_new vol_ctl
= {
405 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
|
406 SNDRV_CTL_ELEM_ACCESS_TLV_READ
,
407 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
408 .info
= ct_alsa_mix_volume_info
,
409 .get
= ct_alsa_mix_volume_get
,
410 .put
= ct_alsa_mix_volume_put
,
411 .tlv
= { .p
= ct_vol_db_scale
},
414 static int output_switch_info(struct snd_kcontrol
*kcontrol
,
415 struct snd_ctl_elem_info
*info
)
417 static const char *const names
[3] = {
418 "FP Headphones", "Headphones", "Speakers"
421 return snd_ctl_enum_info(info
, 1, 3, names
);
424 static int output_switch_get(struct snd_kcontrol
*kcontrol
,
425 struct snd_ctl_elem_value
*ucontrol
)
427 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
428 ucontrol
->value
.enumerated
.item
[0] = atc
->output_switch_get(atc
);
432 static int output_switch_put(struct snd_kcontrol
*kcontrol
,
433 struct snd_ctl_elem_value
*ucontrol
)
435 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
436 if (ucontrol
->value
.enumerated
.item
[0] > 2)
438 return atc
->output_switch_put(atc
, ucontrol
->value
.enumerated
.item
[0]);
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
,
449 static int mic_source_switch_info(struct snd_kcontrol
*kcontrol
,
450 struct snd_ctl_elem_info
*info
)
452 static const char *const names
[3] = {
453 "Mic", "FP Mic", "Aux"
456 return snd_ctl_enum_info(info
, 1, 3, names
);
459 static int mic_source_switch_get(struct snd_kcontrol
*kcontrol
,
460 struct snd_ctl_elem_value
*ucontrol
)
462 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
463 ucontrol
->value
.enumerated
.item
[0] = atc
->mic_source_switch_get(atc
);
467 static int mic_source_switch_put(struct snd_kcontrol
*kcontrol
,
468 struct snd_ctl_elem_value
*ucontrol
)
470 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
471 if (ucontrol
->value
.enumerated
.item
[0] > 2)
473 return atc
->mic_source_switch_put(atc
,
474 ucontrol
->value
.enumerated
.item
[0]);
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
,
486 do_line_mic_switch(struct ct_atc
*atc
, enum CTALSA_MIXER_CTL type
)
489 if (MIXER_LINEIN_C_S
== type
) {
490 atc
->select_line_in(atc
);
491 set_switch_state(atc
->mixer
, MIXER_MIC_C_S
, 0);
492 snd_ctl_notify(atc
->card
, SNDRV_CTL_EVENT_MASK_VALUE
,
494 } else if (MIXER_MIC_C_S
== type
) {
495 atc
->select_mic_in(atc
);
496 set_switch_state(atc
->mixer
, MIXER_LINEIN_C_S
, 0);
497 snd_ctl_notify(atc
->card
, SNDRV_CTL_EVENT_MASK_VALUE
,
503 do_digit_io_switch(struct ct_atc
*atc
, int state
)
505 struct ct_mixer
*mixer
= atc
->mixer
;
508 atc
->select_digit_io(atc
);
509 atc
->spdif_out_unmute(atc
,
510 get_switch_state(mixer
, MIXER_SPDIFO_P_S
));
511 atc
->spdif_in_unmute(atc
, 1);
512 atc
->line_in_unmute(atc
, 0);
516 if (get_switch_state(mixer
, MIXER_LINEIN_C_S
))
517 atc
->select_line_in(atc
);
518 else if (get_switch_state(mixer
, MIXER_MIC_C_S
))
519 atc
->select_mic_in(atc
);
521 atc
->spdif_out_unmute(atc
, 0);
522 atc
->spdif_in_unmute(atc
, 0);
523 atc
->line_in_unmute(atc
, 1);
527 static void do_switch(struct ct_atc
*atc
, enum CTALSA_MIXER_CTL type
, int state
)
529 struct ct_mixer
*mixer
= atc
->mixer
;
530 struct capabilities cap
= atc
->capabilities(atc
);
532 /* Do changes in mixer. */
533 if ((SWH_CAPTURE_START
<= type
) && (SWH_CAPTURE_END
>= type
)) {
535 ct_mixer_recording_select(mixer
,
536 get_amixer_index(type
));
538 ct_mixer_recording_unselect(mixer
,
539 get_amixer_index(type
));
542 /* Do changes out of mixer. */
543 if (!cap
.dedicated_mic
&&
544 (MIXER_LINEIN_C_S
== type
|| MIXER_MIC_C_S
== type
)) {
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
);
554 else if (MIXER_WAVEF_P_S
== type
)
555 atc
->line_front_unmute(atc
, state
);
556 else if (MIXER_WAVES_P_S
== type
)
557 atc
->line_surround_unmute(atc
, state
);
558 else if (MIXER_WAVEC_P_S
== type
)
559 atc
->line_clfe_unmute(atc
, state
);
560 else if (MIXER_WAVER_P_S
== type
)
561 atc
->line_rear_unmute(atc
, state
);
562 else if (MIXER_SPDIFO_P_S
== type
)
563 atc
->spdif_out_unmute(atc
, state
);
564 else if (MIXER_DIGITAL_IO_S
== type
)
565 do_digit_io_switch(atc
, state
);
570 static int ct_alsa_mix_switch_info(struct snd_kcontrol
*kcontrol
,
571 struct snd_ctl_elem_info
*uinfo
)
573 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
575 uinfo
->value
.integer
.min
= 0;
576 uinfo
->value
.integer
.max
= 1;
577 uinfo
->value
.integer
.step
= 1;
582 static int ct_alsa_mix_switch_get(struct snd_kcontrol
*kcontrol
,
583 struct snd_ctl_elem_value
*ucontrol
)
585 struct ct_mixer
*mixer
=
586 ((struct ct_atc
*)snd_kcontrol_chip(kcontrol
))->mixer
;
587 enum CTALSA_MIXER_CTL type
= kcontrol
->private_value
;
589 ucontrol
->value
.integer
.value
[0] = get_switch_state(mixer
, type
);
593 static int ct_alsa_mix_switch_put(struct snd_kcontrol
*kcontrol
,
594 struct snd_ctl_elem_value
*ucontrol
)
596 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
597 struct ct_mixer
*mixer
= atc
->mixer
;
598 enum CTALSA_MIXER_CTL type
= kcontrol
->private_value
;
601 state
= ucontrol
->value
.integer
.value
[0];
602 if (get_switch_state(mixer
, type
) == state
)
605 set_switch_state(mixer
, type
, state
);
606 do_switch(atc
, type
, state
);
611 static struct snd_kcontrol_new swh_ctl
= {
612 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
613 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
614 .info
= ct_alsa_mix_switch_info
,
615 .get
= ct_alsa_mix_switch_get
,
616 .put
= ct_alsa_mix_switch_put
619 static int ct_spdif_info(struct snd_kcontrol
*kcontrol
,
620 struct snd_ctl_elem_info
*uinfo
)
622 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_IEC958
;
627 static int ct_spdif_get_mask(struct snd_kcontrol
*kcontrol
,
628 struct snd_ctl_elem_value
*ucontrol
)
630 ucontrol
->value
.iec958
.status
[0] = 0xff;
631 ucontrol
->value
.iec958
.status
[1] = 0xff;
632 ucontrol
->value
.iec958
.status
[2] = 0xff;
633 ucontrol
->value
.iec958
.status
[3] = 0xff;
637 static int ct_spdif_get(struct snd_kcontrol
*kcontrol
,
638 struct snd_ctl_elem_value
*ucontrol
)
640 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
643 atc
->spdif_out_get_status(atc
, &status
);
646 status
= SNDRV_PCM_DEFAULT_CON_SPDIF
;
648 ucontrol
->value
.iec958
.status
[0] = (status
>> 0) & 0xff;
649 ucontrol
->value
.iec958
.status
[1] = (status
>> 8) & 0xff;
650 ucontrol
->value
.iec958
.status
[2] = (status
>> 16) & 0xff;
651 ucontrol
->value
.iec958
.status
[3] = (status
>> 24) & 0xff;
656 static int ct_spdif_put(struct snd_kcontrol
*kcontrol
,
657 struct snd_ctl_elem_value
*ucontrol
)
659 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
661 unsigned int status
, old_status
;
663 status
= (ucontrol
->value
.iec958
.status
[0] << 0) |
664 (ucontrol
->value
.iec958
.status
[1] << 8) |
665 (ucontrol
->value
.iec958
.status
[2] << 16) |
666 (ucontrol
->value
.iec958
.status
[3] << 24);
668 atc
->spdif_out_get_status(atc
, &old_status
);
669 change
= (old_status
!= status
);
671 atc
->spdif_out_set_status(atc
, status
);
676 static struct snd_kcontrol_new iec958_mask_ctl
= {
677 .access
= SNDRV_CTL_ELEM_ACCESS_READ
,
678 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
679 .name
= SNDRV_CTL_NAME_IEC958("", PLAYBACK
, MASK
),
681 .info
= ct_spdif_info
,
682 .get
= ct_spdif_get_mask
,
683 .private_value
= MIXER_IEC958_MASK
686 static struct snd_kcontrol_new iec958_default_ctl
= {
687 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
688 .name
= SNDRV_CTL_NAME_IEC958("", PLAYBACK
, DEFAULT
),
690 .info
= ct_spdif_info
,
693 .private_value
= MIXER_IEC958_DEFAULT
696 static struct snd_kcontrol_new iec958_ctl
= {
697 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
698 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
699 .name
= SNDRV_CTL_NAME_IEC958("", PLAYBACK
, PCM_STREAM
),
701 .info
= ct_spdif_info
,
704 .private_value
= MIXER_IEC958_STREAM
707 #define NUM_IEC958_CTL 3
710 ct_mixer_kcontrol_new(struct ct_mixer
*mixer
, struct snd_kcontrol_new
*new)
712 struct snd_kcontrol
*kctl
;
715 kctl
= snd_ctl_new1(new, mixer
->atc
);
719 if (SNDRV_CTL_ELEM_IFACE_PCM
== kctl
->id
.iface
)
720 kctl
->id
.device
= IEC958
;
722 err
= snd_ctl_add(mixer
->atc
->card
, kctl
);
726 switch (new->private_value
) {
727 case MIXER_LINEIN_C_S
:
728 kctls
[0] = kctl
; break;
730 kctls
[1] = kctl
; break;
738 static int ct_mixer_kcontrols_create(struct ct_mixer
*mixer
)
740 enum CTALSA_MIXER_CTL type
;
741 struct ct_atc
*atc
= mixer
->atc
;
742 struct capabilities cap
= atc
->capabilities(atc
);
745 /* Create snd kcontrol instances on demand */
746 for (type
= VOL_MIXER_START
; type
<= VOL_MIXER_END
; type
++) {
747 if (ct_kcontrol_init_table
[type
].ctl
) {
748 vol_ctl
.name
= ct_kcontrol_init_table
[type
].name
;
749 vol_ctl
.private_value
= (unsigned long)type
;
750 err
= ct_mixer_kcontrol_new(mixer
, &vol_ctl
);
756 ct_kcontrol_init_table
[MIXER_DIGITAL_IO_S
].ctl
= cap
.digit_io_switch
;
758 for (type
= SWH_MIXER_START
; type
<= SWH_MIXER_END
; type
++) {
759 if (ct_kcontrol_init_table
[type
].ctl
) {
760 swh_ctl
.name
= ct_kcontrol_init_table
[type
].name
;
761 swh_ctl
.private_value
= (unsigned long)type
;
762 err
= ct_mixer_kcontrol_new(mixer
, &swh_ctl
);
768 err
= ct_mixer_kcontrol_new(mixer
, &iec958_mask_ctl
);
772 err
= ct_mixer_kcontrol_new(mixer
, &iec958_default_ctl
);
776 err
= ct_mixer_kcontrol_new(mixer
, &iec958_ctl
);
780 if (cap
.output_switch
) {
781 err
= ct_mixer_kcontrol_new(mixer
, &output_ctl
);
786 if (cap
.mic_source_switch
) {
787 err
= ct_mixer_kcontrol_new(mixer
, &mic_source_ctl
);
791 atc
->line_front_unmute(atc
, 1);
792 set_switch_state(mixer
, MIXER_WAVEF_P_S
, 1);
793 atc
->line_surround_unmute(atc
, 0);
794 set_switch_state(mixer
, MIXER_WAVES_P_S
, 0);
795 atc
->line_clfe_unmute(atc
, 0);
796 set_switch_state(mixer
, MIXER_WAVEC_P_S
, 0);
797 atc
->line_rear_unmute(atc
, 0);
798 set_switch_state(mixer
, MIXER_WAVER_P_S
, 0);
799 atc
->spdif_out_unmute(atc
, 0);
800 set_switch_state(mixer
, MIXER_SPDIFO_P_S
, 0);
801 atc
->line_in_unmute(atc
, 0);
802 if (cap
.dedicated_mic
)
803 atc
->mic_unmute(atc
, 0);
804 atc
->spdif_in_unmute(atc
, 0);
805 set_switch_state(mixer
, MIXER_PCM_C_S
, 0);
806 set_switch_state(mixer
, MIXER_LINEIN_C_S
, 0);
807 set_switch_state(mixer
, MIXER_SPDIFI_C_S
, 0);
813 ct_mixer_recording_select(struct ct_mixer
*mixer
, enum CT_AMIXER_CTL type
)
815 struct amixer
*amix_d
;
819 for (i
= 0; i
< 2; i
++) {
820 amix_d
= mixer
->amixers
[type
*CHN_NUM
+i
];
821 sum_c
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+i
];
822 amix_d
->ops
->set_sum(amix_d
, sum_c
);
823 amix_d
->ops
->commit_write(amix_d
);
828 ct_mixer_recording_unselect(struct ct_mixer
*mixer
, enum CT_AMIXER_CTL type
)
830 struct amixer
*amix_d
;
833 for (i
= 0; i
< 2; i
++) {
834 amix_d
= mixer
->amixers
[type
*CHN_NUM
+i
];
835 amix_d
->ops
->set_sum(amix_d
, NULL
);
836 amix_d
->ops
->commit_write(amix_d
);
840 static int ct_mixer_get_resources(struct ct_mixer
*mixer
)
842 struct sum_mgr
*sum_mgr
;
844 struct sum_desc sum_desc
= {0};
845 struct amixer_mgr
*amixer_mgr
;
846 struct amixer
*amixer
;
847 struct amixer_desc am_desc
= {0};
851 /* Allocate sum resources for mixer obj */
852 sum_mgr
= (struct sum_mgr
*)mixer
->atc
->rsc_mgrs
[SUM
];
853 sum_desc
.msr
= mixer
->atc
->msr
;
854 for (i
= 0; i
< (NUM_CT_SUMS
* CHN_NUM
); i
++) {
855 err
= sum_mgr
->get_sum(sum_mgr
, &sum_desc
, &sum
);
857 printk(KERN_ERR
"ctxfi:Failed to get sum resources for "
861 mixer
->sums
[i
] = sum
;
866 /* Allocate amixer resources for mixer obj */
867 amixer_mgr
= (struct amixer_mgr
*)mixer
->atc
->rsc_mgrs
[AMIXER
];
868 am_desc
.msr
= mixer
->atc
->msr
;
869 for (i
= 0; i
< (NUM_CT_AMIXERS
* CHN_NUM
); i
++) {
870 err
= amixer_mgr
->get_amixer(amixer_mgr
, &am_desc
, &amixer
);
872 printk(KERN_ERR
"ctxfi:Failed to get amixer resources "
876 mixer
->amixers
[i
] = amixer
;
884 for (i
= 0; i
< (NUM_CT_AMIXERS
* CHN_NUM
); i
++) {
885 if (NULL
!= mixer
->amixers
[i
]) {
886 amixer
= mixer
->amixers
[i
];
887 amixer_mgr
->put_amixer(amixer_mgr
, amixer
);
888 mixer
->amixers
[i
] = NULL
;
892 for (i
= 0; i
< (NUM_CT_SUMS
* CHN_NUM
); i
++) {
893 if (NULL
!= mixer
->sums
[i
]) {
894 sum_mgr
->put_sum(sum_mgr
, (struct sum
*)mixer
->sums
[i
]);
895 mixer
->sums
[i
] = NULL
;
902 static int ct_mixer_get_mem(struct ct_mixer
**rmixer
)
904 struct ct_mixer
*mixer
;
908 /* Allocate mem for mixer obj */
909 mixer
= kzalloc(sizeof(*mixer
), GFP_KERNEL
);
913 mixer
->amixers
= kzalloc(sizeof(void *)*(NUM_CT_AMIXERS
*CHN_NUM
),
915 if (!mixer
->amixers
) {
919 mixer
->sums
= kzalloc(sizeof(void *)*(NUM_CT_SUMS
*CHN_NUM
), GFP_KERNEL
);
929 kfree(mixer
->amixers
);
935 static int ct_mixer_topology_build(struct ct_mixer
*mixer
)
938 struct amixer
*amix_d
, *amix_s
;
939 enum CT_AMIXER_CTL i
, j
;
941 /* Build topology from destination to source */
943 /* Set up Master mixer */
944 for (i
= AMIXER_MASTER_F
, j
= SUM_IN_F
;
945 i
<= AMIXER_MASTER_S
; i
++, j
++) {
946 amix_d
= mixer
->amixers
[i
*CHN_NUM
];
947 sum
= mixer
->sums
[j
*CHN_NUM
];
948 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
949 amix_d
= mixer
->amixers
[i
*CHN_NUM
+1];
950 sum
= mixer
->sums
[j
*CHN_NUM
+1];
951 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
954 /* Set up Wave-out mixer */
955 for (i
= AMIXER_WAVE_F
, j
= AMIXER_MASTER_F
;
956 i
<= AMIXER_WAVE_S
; i
++, j
++) {
957 amix_d
= mixer
->amixers
[i
*CHN_NUM
];
958 amix_s
= mixer
->amixers
[j
*CHN_NUM
];
959 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
960 amix_d
= mixer
->amixers
[i
*CHN_NUM
+1];
961 amix_s
= mixer
->amixers
[j
*CHN_NUM
+1];
962 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
965 /* Set up S/PDIF-out mixer */
966 amix_d
= mixer
->amixers
[AMIXER_SPDIFO
*CHN_NUM
];
967 amix_s
= mixer
->amixers
[AMIXER_MASTER_F
*CHN_NUM
];
968 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
969 amix_d
= mixer
->amixers
[AMIXER_SPDIFO
*CHN_NUM
+1];
970 amix_s
= mixer
->amixers
[AMIXER_MASTER_F
*CHN_NUM
+1];
971 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
973 /* Set up PCM-in mixer */
974 for (i
= AMIXER_PCM_F
, j
= SUM_IN_F
; i
<= AMIXER_PCM_S
; i
++, j
++) {
975 amix_d
= mixer
->amixers
[i
*CHN_NUM
];
976 sum
= mixer
->sums
[j
*CHN_NUM
];
977 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
978 amix_d
= mixer
->amixers
[i
*CHN_NUM
+1];
979 sum
= mixer
->sums
[j
*CHN_NUM
+1];
980 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
983 /* Set up Line-in mixer */
984 amix_d
= mixer
->amixers
[AMIXER_LINEIN
*CHN_NUM
];
985 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
];
986 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
987 amix_d
= mixer
->amixers
[AMIXER_LINEIN
*CHN_NUM
+1];
988 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
+1];
989 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
991 /* Set up Mic-in mixer */
992 amix_d
= mixer
->amixers
[AMIXER_MIC
*CHN_NUM
];
993 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
];
994 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
995 amix_d
= mixer
->amixers
[AMIXER_MIC
*CHN_NUM
+1];
996 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
+1];
997 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
999 /* Set up S/PDIF-in mixer */
1000 amix_d
= mixer
->amixers
[AMIXER_SPDIFI
*CHN_NUM
];
1001 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
];
1002 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1003 amix_d
= mixer
->amixers
[AMIXER_SPDIFI
*CHN_NUM
+1];
1004 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
+1];
1005 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1007 /* Set up Master recording mixer */
1008 amix_d
= mixer
->amixers
[AMIXER_MASTER_F_C
*CHN_NUM
];
1009 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1010 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
1011 amix_d
= mixer
->amixers
[AMIXER_MASTER_F_C
*CHN_NUM
+1];
1012 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1013 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
1015 /* Set up PCM-in recording mixer */
1016 amix_d
= mixer
->amixers
[AMIXER_PCM_F_C
*CHN_NUM
];
1017 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1018 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1019 amix_d
= mixer
->amixers
[AMIXER_PCM_F_C
*CHN_NUM
+1];
1020 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1021 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1023 /* Set up Line-in recording mixer */
1024 amix_d
= mixer
->amixers
[AMIXER_LINEIN_C
*CHN_NUM
];
1025 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1026 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1027 amix_d
= mixer
->amixers
[AMIXER_LINEIN_C
*CHN_NUM
+1];
1028 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1029 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1031 /* Set up Mic-in recording mixer */
1032 amix_d
= mixer
->amixers
[AMIXER_MIC_C
*CHN_NUM
];
1033 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1034 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1035 amix_d
= mixer
->amixers
[AMIXER_MIC_C
*CHN_NUM
+1];
1036 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1037 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1039 /* Set up S/PDIF-in recording mixer */
1040 amix_d
= mixer
->amixers
[AMIXER_SPDIFI_C
*CHN_NUM
];
1041 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1042 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1043 amix_d
= mixer
->amixers
[AMIXER_SPDIFI_C
*CHN_NUM
+1];
1044 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1045 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1050 static int mixer_set_input_port(struct amixer
*amixer
, struct rsc
*rsc
)
1052 amixer
->ops
->set_input(amixer
, rsc
);
1053 amixer
->ops
->commit_write(amixer
);
1058 static enum CT_AMIXER_CTL
port_to_amixer(enum MIXER_PORT_T type
)
1061 case MIX_WAVE_FRONT
: return AMIXER_WAVE_F
;
1062 case MIX_WAVE_SURROUND
: return AMIXER_WAVE_S
;
1063 case MIX_WAVE_CENTLFE
: return AMIXER_WAVE_C
;
1064 case MIX_WAVE_REAR
: return AMIXER_WAVE_R
;
1065 case MIX_PCMO_FRONT
: return AMIXER_MASTER_F_C
;
1066 case MIX_SPDIF_OUT
: return AMIXER_SPDIFO
;
1067 case MIX_LINE_IN
: return AMIXER_LINEIN
;
1068 case MIX_MIC_IN
: return AMIXER_MIC
;
1069 case MIX_SPDIF_IN
: return AMIXER_SPDIFI
;
1070 case MIX_PCMI_FRONT
: return AMIXER_PCM_F
;
1071 case MIX_PCMI_SURROUND
: return AMIXER_PCM_S
;
1072 case MIX_PCMI_CENTLFE
: return AMIXER_PCM_C
;
1073 case MIX_PCMI_REAR
: return AMIXER_PCM_R
;
1078 static int mixer_get_output_ports(struct ct_mixer
*mixer
,
1079 enum MIXER_PORT_T type
,
1080 struct rsc
**rleft
, struct rsc
**rright
)
1082 enum CT_AMIXER_CTL amix
= port_to_amixer(type
);
1085 *rleft
= &((struct amixer
*)mixer
->amixers
[amix
*CHN_NUM
])->rsc
;
1089 &((struct amixer
*)mixer
->amixers
[amix
*CHN_NUM
+1])->rsc
;
1094 static int mixer_set_input_left(struct ct_mixer
*mixer
,
1095 enum MIXER_PORT_T type
, struct rsc
*rsc
)
1097 enum CT_AMIXER_CTL amix
= port_to_amixer(type
);
1099 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
], rsc
);
1100 amix
= get_recording_amixer(amix
);
1101 if (amix
< NUM_CT_AMIXERS
)
1102 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
], rsc
);
1108 mixer_set_input_right(struct ct_mixer
*mixer
,
1109 enum MIXER_PORT_T type
, struct rsc
*rsc
)
1111 enum CT_AMIXER_CTL amix
= port_to_amixer(type
);
1113 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
+1], rsc
);
1114 amix
= get_recording_amixer(amix
);
1115 if (amix
< NUM_CT_AMIXERS
)
1116 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
+1], rsc
);
1122 static int mixer_resume(struct ct_mixer
*mixer
)
1125 struct amixer
*amixer
;
1127 /* resume topology and volume gain. */
1128 for (i
= 0; i
< NUM_CT_AMIXERS
*CHN_NUM
; i
++) {
1129 amixer
= mixer
->amixers
[i
];
1130 amixer
->ops
->commit_write(amixer
);
1133 /* resume switch state. */
1134 for (i
= SWH_MIXER_START
; i
<= SWH_MIXER_END
; i
++) {
1135 state
= get_switch_state(mixer
, i
);
1136 do_switch(mixer
->atc
, i
, state
);
1143 int ct_mixer_destroy(struct ct_mixer
*mixer
)
1145 struct sum_mgr
*sum_mgr
= (struct sum_mgr
*)mixer
->atc
->rsc_mgrs
[SUM
];
1146 struct amixer_mgr
*amixer_mgr
=
1147 (struct amixer_mgr
*)mixer
->atc
->rsc_mgrs
[AMIXER
];
1148 struct amixer
*amixer
;
1151 /* Release amixer resources */
1152 for (i
= 0; i
< (NUM_CT_AMIXERS
* CHN_NUM
); i
++) {
1153 if (NULL
!= mixer
->amixers
[i
]) {
1154 amixer
= mixer
->amixers
[i
];
1155 amixer_mgr
->put_amixer(amixer_mgr
, amixer
);
1159 /* Release sum resources */
1160 for (i
= 0; i
< (NUM_CT_SUMS
* CHN_NUM
); i
++) {
1161 if (NULL
!= mixer
->sums
[i
])
1162 sum_mgr
->put_sum(sum_mgr
, (struct sum
*)mixer
->sums
[i
]);
1165 /* Release mem assigned to mixer object */
1167 kfree(mixer
->amixers
);
1173 int ct_mixer_create(struct ct_atc
*atc
, struct ct_mixer
**rmixer
)
1175 struct ct_mixer
*mixer
;
1180 /* Allocate mem for mixer obj */
1181 err
= ct_mixer_get_mem(&mixer
);
1185 mixer
->switch_state
= 0;
1187 /* Set operations */
1188 mixer
->get_output_ports
= mixer_get_output_ports
;
1189 mixer
->set_input_left
= mixer_set_input_left
;
1190 mixer
->set_input_right
= mixer_set_input_right
;
1192 mixer
->resume
= mixer_resume
;
1195 /* Allocate chip resources for mixer obj */
1196 err
= ct_mixer_get_resources(mixer
);
1200 /* Build internal mixer topology */
1201 ct_mixer_topology_build(mixer
);
1208 ct_mixer_destroy(mixer
);
1212 int ct_alsa_mix_create(struct ct_atc
*atc
,
1213 enum CTALSADEVS device
,
1214 const char *device_name
)
1218 /* Create snd kcontrol instances on demand */
1219 /* vol_ctl.device = swh_ctl.device = device; */ /* better w/ device 0 */
1220 err
= ct_mixer_kcontrols_create((struct ct_mixer
*)atc
->mixer
);
1224 strcpy(atc
->card
->mixername
, device_name
);