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 dev_err(mixer
->atc
->card
->dev
,
858 "Failed to get sum resources for front output!\n");
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 dev_err(mixer
->atc
->card
->dev
,
873 "Failed to get amixer resources for mixer obj!\n");
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
= kcalloc(NUM_CT_AMIXERS
* CHN_NUM
, sizeof(void *),
915 if (!mixer
->amixers
) {
919 mixer
->sums
= kcalloc(NUM_CT_SUMS
* CHN_NUM
, sizeof(void *),
930 kfree(mixer
->amixers
);
936 static int ct_mixer_topology_build(struct ct_mixer
*mixer
)
939 struct amixer
*amix_d
, *amix_s
;
940 enum CT_AMIXER_CTL i
, j
;
943 /* Build topology from destination to source */
945 /* Set up Master mixer */
946 for (i
= AMIXER_MASTER_F
, k
= SUM_IN_F
;
947 i
<= AMIXER_MASTER_S
; i
++, k
++) {
948 amix_d
= mixer
->amixers
[i
*CHN_NUM
];
949 sum
= mixer
->sums
[k
*CHN_NUM
];
950 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
951 amix_d
= mixer
->amixers
[i
*CHN_NUM
+1];
952 sum
= mixer
->sums
[k
*CHN_NUM
+1];
953 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
956 /* Set up Wave-out mixer */
957 for (i
= AMIXER_WAVE_F
, j
= AMIXER_MASTER_F
;
958 i
<= AMIXER_WAVE_S
; i
++, j
++) {
959 amix_d
= mixer
->amixers
[i
*CHN_NUM
];
960 amix_s
= mixer
->amixers
[j
*CHN_NUM
];
961 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
962 amix_d
= mixer
->amixers
[i
*CHN_NUM
+1];
963 amix_s
= mixer
->amixers
[j
*CHN_NUM
+1];
964 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
967 /* Set up S/PDIF-out mixer */
968 amix_d
= mixer
->amixers
[AMIXER_SPDIFO
*CHN_NUM
];
969 amix_s
= mixer
->amixers
[AMIXER_MASTER_F
*CHN_NUM
];
970 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
971 amix_d
= mixer
->amixers
[AMIXER_SPDIFO
*CHN_NUM
+1];
972 amix_s
= mixer
->amixers
[AMIXER_MASTER_F
*CHN_NUM
+1];
973 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
975 /* Set up PCM-in mixer */
976 for (i
= AMIXER_PCM_F
, k
= SUM_IN_F
; i
<= AMIXER_PCM_S
; i
++, k
++) {
977 amix_d
= mixer
->amixers
[i
*CHN_NUM
];
978 sum
= mixer
->sums
[k
*CHN_NUM
];
979 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
980 amix_d
= mixer
->amixers
[i
*CHN_NUM
+1];
981 sum
= mixer
->sums
[k
*CHN_NUM
+1];
982 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
985 /* Set up Line-in mixer */
986 amix_d
= mixer
->amixers
[AMIXER_LINEIN
*CHN_NUM
];
987 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
];
988 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
989 amix_d
= mixer
->amixers
[AMIXER_LINEIN
*CHN_NUM
+1];
990 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
+1];
991 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
993 /* Set up Mic-in mixer */
994 amix_d
= mixer
->amixers
[AMIXER_MIC
*CHN_NUM
];
995 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
];
996 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
997 amix_d
= mixer
->amixers
[AMIXER_MIC
*CHN_NUM
+1];
998 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
+1];
999 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1001 /* Set up S/PDIF-in mixer */
1002 amix_d
= mixer
->amixers
[AMIXER_SPDIFI
*CHN_NUM
];
1003 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
];
1004 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1005 amix_d
= mixer
->amixers
[AMIXER_SPDIFI
*CHN_NUM
+1];
1006 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
+1];
1007 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1009 /* Set up Master recording mixer */
1010 amix_d
= mixer
->amixers
[AMIXER_MASTER_F_C
*CHN_NUM
];
1011 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1012 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
1013 amix_d
= mixer
->amixers
[AMIXER_MASTER_F_C
*CHN_NUM
+1];
1014 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1015 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
1017 /* Set up PCM-in recording mixer */
1018 amix_d
= mixer
->amixers
[AMIXER_PCM_F_C
*CHN_NUM
];
1019 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1020 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1021 amix_d
= mixer
->amixers
[AMIXER_PCM_F_C
*CHN_NUM
+1];
1022 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1023 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1025 /* Set up Line-in recording mixer */
1026 amix_d
= mixer
->amixers
[AMIXER_LINEIN_C
*CHN_NUM
];
1027 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1028 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1029 amix_d
= mixer
->amixers
[AMIXER_LINEIN_C
*CHN_NUM
+1];
1030 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1031 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1033 /* Set up Mic-in recording mixer */
1034 amix_d
= mixer
->amixers
[AMIXER_MIC_C
*CHN_NUM
];
1035 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1036 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1037 amix_d
= mixer
->amixers
[AMIXER_MIC_C
*CHN_NUM
+1];
1038 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1039 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1041 /* Set up S/PDIF-in recording mixer */
1042 amix_d
= mixer
->amixers
[AMIXER_SPDIFI_C
*CHN_NUM
];
1043 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1044 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1045 amix_d
= mixer
->amixers
[AMIXER_SPDIFI_C
*CHN_NUM
+1];
1046 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1047 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1052 static int mixer_set_input_port(struct amixer
*amixer
, struct rsc
*rsc
)
1054 amixer
->ops
->set_input(amixer
, rsc
);
1055 amixer
->ops
->commit_write(amixer
);
1060 static enum CT_AMIXER_CTL
port_to_amixer(enum MIXER_PORT_T type
)
1063 case MIX_WAVE_FRONT
: return AMIXER_WAVE_F
;
1064 case MIX_WAVE_SURROUND
: return AMIXER_WAVE_S
;
1065 case MIX_WAVE_CENTLFE
: return AMIXER_WAVE_C
;
1066 case MIX_WAVE_REAR
: return AMIXER_WAVE_R
;
1067 case MIX_PCMO_FRONT
: return AMIXER_MASTER_F_C
;
1068 case MIX_SPDIF_OUT
: return AMIXER_SPDIFO
;
1069 case MIX_LINE_IN
: return AMIXER_LINEIN
;
1070 case MIX_MIC_IN
: return AMIXER_MIC
;
1071 case MIX_SPDIF_IN
: return AMIXER_SPDIFI
;
1072 case MIX_PCMI_FRONT
: return AMIXER_PCM_F
;
1073 case MIX_PCMI_SURROUND
: return AMIXER_PCM_S
;
1074 case MIX_PCMI_CENTLFE
: return AMIXER_PCM_C
;
1075 case MIX_PCMI_REAR
: return AMIXER_PCM_R
;
1080 static int mixer_get_output_ports(struct ct_mixer
*mixer
,
1081 enum MIXER_PORT_T type
,
1082 struct rsc
**rleft
, struct rsc
**rright
)
1084 enum CT_AMIXER_CTL amix
= port_to_amixer(type
);
1087 *rleft
= &((struct amixer
*)mixer
->amixers
[amix
*CHN_NUM
])->rsc
;
1091 &((struct amixer
*)mixer
->amixers
[amix
*CHN_NUM
+1])->rsc
;
1096 static int mixer_set_input_left(struct ct_mixer
*mixer
,
1097 enum MIXER_PORT_T type
, struct rsc
*rsc
)
1099 enum CT_AMIXER_CTL amix
= port_to_amixer(type
);
1101 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
], rsc
);
1102 amix
= get_recording_amixer(amix
);
1103 if (amix
< NUM_CT_AMIXERS
)
1104 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
], rsc
);
1110 mixer_set_input_right(struct ct_mixer
*mixer
,
1111 enum MIXER_PORT_T type
, struct rsc
*rsc
)
1113 enum CT_AMIXER_CTL amix
= port_to_amixer(type
);
1115 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
+1], rsc
);
1116 amix
= get_recording_amixer(amix
);
1117 if (amix
< NUM_CT_AMIXERS
)
1118 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
+1], rsc
);
1123 #ifdef CONFIG_PM_SLEEP
1124 static int mixer_resume(struct ct_mixer
*mixer
)
1127 struct amixer
*amixer
;
1129 /* resume topology and volume gain. */
1130 for (i
= 0; i
< NUM_CT_AMIXERS
*CHN_NUM
; i
++) {
1131 amixer
= mixer
->amixers
[i
];
1132 amixer
->ops
->commit_write(amixer
);
1135 /* resume switch state. */
1136 for (i
= SWH_MIXER_START
; i
<= SWH_MIXER_END
; i
++) {
1137 state
= get_switch_state(mixer
, i
);
1138 do_switch(mixer
->atc
, i
, state
);
1145 int ct_mixer_destroy(struct ct_mixer
*mixer
)
1147 struct sum_mgr
*sum_mgr
= (struct sum_mgr
*)mixer
->atc
->rsc_mgrs
[SUM
];
1148 struct amixer_mgr
*amixer_mgr
=
1149 (struct amixer_mgr
*)mixer
->atc
->rsc_mgrs
[AMIXER
];
1150 struct amixer
*amixer
;
1153 /* Release amixer resources */
1154 for (i
= 0; i
< (NUM_CT_AMIXERS
* CHN_NUM
); i
++) {
1155 if (NULL
!= mixer
->amixers
[i
]) {
1156 amixer
= mixer
->amixers
[i
];
1157 amixer_mgr
->put_amixer(amixer_mgr
, amixer
);
1161 /* Release sum resources */
1162 for (i
= 0; i
< (NUM_CT_SUMS
* CHN_NUM
); i
++) {
1163 if (NULL
!= mixer
->sums
[i
])
1164 sum_mgr
->put_sum(sum_mgr
, (struct sum
*)mixer
->sums
[i
]);
1167 /* Release mem assigned to mixer object */
1169 kfree(mixer
->amixers
);
1175 int ct_mixer_create(struct ct_atc
*atc
, struct ct_mixer
**rmixer
)
1177 struct ct_mixer
*mixer
;
1182 /* Allocate mem for mixer obj */
1183 err
= ct_mixer_get_mem(&mixer
);
1187 mixer
->switch_state
= 0;
1189 /* Set operations */
1190 mixer
->get_output_ports
= mixer_get_output_ports
;
1191 mixer
->set_input_left
= mixer_set_input_left
;
1192 mixer
->set_input_right
= mixer_set_input_right
;
1193 #ifdef CONFIG_PM_SLEEP
1194 mixer
->resume
= mixer_resume
;
1197 /* Allocate chip resources for mixer obj */
1198 err
= ct_mixer_get_resources(mixer
);
1202 /* Build internal mixer topology */
1203 ct_mixer_topology_build(mixer
);
1210 ct_mixer_destroy(mixer
);
1214 int ct_alsa_mix_create(struct ct_atc
*atc
,
1215 enum CTALSADEVS device
,
1216 const char *device_name
)
1220 /* Create snd kcontrol instances on demand */
1221 /* vol_ctl.device = swh_ctl.device = device; */ /* better w/ device 0 */
1222 err
= ct_mixer_kcontrols_create((struct ct_mixer
*)atc
->mixer
);
1226 strcpy(atc
->card
->mixername
, device_name
);