1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
8 * This file contains the implementation of alsa mixer device functions.
17 #include <linux/slab.h>
18 #include <sound/core.h>
19 #include <sound/control.h>
20 #include <sound/asoundef.h>
21 #include <sound/pcm.h>
22 #include <sound/tlv.h>
35 /* volume control mixers */
58 /* this should always be the last one */
62 enum CTALSA_MIXER_CTL
{
63 /* volume control mixers */
80 /* switch control mixers */
95 /* this should always be the last one */
99 #define VOL_MIXER_START MIXER_MASTER_P
100 #define VOL_MIXER_END MIXER_SPDIFI_C
101 #define VOL_MIXER_NUM (VOL_MIXER_END - VOL_MIXER_START + 1)
102 #define SWH_MIXER_START MIXER_PCM_C_S
103 #define SWH_MIXER_END MIXER_DIGITAL_IO_S
104 #define SWH_CAPTURE_START MIXER_PCM_C_S
105 #define SWH_CAPTURE_END MIXER_SPDIFI_C_S
109 struct ct_kcontrol_init
{
114 static struct ct_kcontrol_init
115 ct_kcontrol_init_table
[NUM_CTALSA_MIXERS
] = {
118 .name
= "Master Playback Volume",
122 .name
= "Master Capture Volume",
126 .name
= "PCM Playback Volume",
130 .name
= "PCM Capture Volume",
134 .name
= "Line Playback Volume",
138 .name
= "Line Capture Volume",
142 .name
= "Mic Playback Volume",
146 .name
= "Mic Capture Volume",
150 .name
= "IEC958 Playback Volume",
154 .name
= "IEC958 Capture Volume",
158 .name
= "Digital Playback Volume",
162 .name
= "Front Playback Volume",
166 .name
= "Side Playback Volume",
170 .name
= "Center/LFE Playback Volume",
174 .name
= "Surround Playback Volume",
178 .name
= "PCM Capture Switch",
180 [MIXER_LINEIN_C_S
] = {
182 .name
= "Line Capture Switch",
186 .name
= "Mic Capture Switch",
188 [MIXER_SPDIFI_C_S
] = {
190 .name
= "IEC958 Capture Switch",
192 [MIXER_SPDIFO_P_S
] = {
194 .name
= "Digital Playback Switch",
196 [MIXER_WAVEF_P_S
] = {
198 .name
= "Front Playback Switch",
200 [MIXER_WAVES_P_S
] = {
202 .name
= "Side Playback Switch",
204 [MIXER_WAVEC_P_S
] = {
206 .name
= "Center/LFE Playback Switch",
208 [MIXER_WAVER_P_S
] = {
210 .name
= "Surround Playback Switch",
212 [MIXER_DIGITAL_IO_S
] = {
214 .name
= "Digit-IO Playback Switch",
219 ct_mixer_recording_select(struct ct_mixer
*mixer
, enum CT_AMIXER_CTL type
);
222 ct_mixer_recording_unselect(struct ct_mixer
*mixer
, enum CT_AMIXER_CTL type
);
224 /* FIXME: this static looks like it would fail if more than one card was */
226 static struct snd_kcontrol
*kctls
[2] = {NULL
};
228 static enum CT_AMIXER_CTL
get_amixer_index(enum CTALSA_MIXER_CTL alsa_index
)
230 switch (alsa_index
) {
231 case MIXER_MASTER_P
: return AMIXER_MASTER_F
;
232 case MIXER_MASTER_C
: return AMIXER_MASTER_F_C
;
233 case MIXER_PCM_P
: return AMIXER_PCM_F
;
235 case MIXER_PCM_C_S
: return AMIXER_PCM_F_C
;
236 case MIXER_LINEIN_P
: return AMIXER_LINEIN
;
238 case MIXER_LINEIN_C_S
: return AMIXER_LINEIN_C
;
239 case MIXER_MIC_P
: return AMIXER_MIC
;
241 case MIXER_MIC_C_S
: return AMIXER_MIC_C
;
242 case MIXER_SPDIFI_P
: return AMIXER_SPDIFI
;
244 case MIXER_SPDIFI_C_S
: return AMIXER_SPDIFI_C
;
245 case MIXER_SPDIFO_P
: return AMIXER_SPDIFO
;
246 case MIXER_WAVEF_P
: return AMIXER_WAVE_F
;
247 case MIXER_WAVES_P
: return AMIXER_WAVE_S
;
248 case MIXER_WAVEC_P
: return AMIXER_WAVE_C
;
249 case MIXER_WAVER_P
: return AMIXER_WAVE_R
;
250 default: return NUM_CT_AMIXERS
;
254 static enum CT_AMIXER_CTL
get_recording_amixer(enum CT_AMIXER_CTL index
)
257 case AMIXER_MASTER_F
: return AMIXER_MASTER_F_C
;
258 case AMIXER_PCM_F
: return AMIXER_PCM_F_C
;
259 case AMIXER_SPDIFI
: return AMIXER_SPDIFI_C
;
260 case AMIXER_LINEIN
: return AMIXER_LINEIN_C
;
261 case AMIXER_MIC
: return AMIXER_MIC_C
;
262 default: return NUM_CT_AMIXERS
;
267 get_switch_state(struct ct_mixer
*mixer
, enum CTALSA_MIXER_CTL type
)
269 return (mixer
->switch_state
& (0x1 << (type
- SWH_MIXER_START
)))
274 set_switch_state(struct ct_mixer
*mixer
,
275 enum CTALSA_MIXER_CTL type
, unsigned char state
)
278 mixer
->switch_state
|= (0x1 << (type
- SWH_MIXER_START
));
280 mixer
->switch_state
&= ~(0x1 << (type
- SWH_MIXER_START
));
284 /* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
285 * from 2^-6 to (1+1023/1024) */
286 static unsigned int uint16_to_float14(unsigned int x
)
298 for (i
= 0; !(x
& 0x400); i
++)
301 x
= (((7 - i
) & 0x7) << 10) | (x
& 0x3ff);
306 static unsigned int float14_to_uint16(unsigned int x
)
323 #endif /* not used */
325 #define VOL_SCALE 0x1c
326 #define VOL_MAX 0x100
328 static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale
, -6400, 25, 1);
330 static int ct_alsa_mix_volume_info(struct snd_kcontrol
*kcontrol
,
331 struct snd_ctl_elem_info
*uinfo
)
333 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
335 uinfo
->value
.integer
.min
= 0;
336 uinfo
->value
.integer
.max
= VOL_MAX
;
341 static int ct_alsa_mix_volume_get(struct snd_kcontrol
*kcontrol
,
342 struct snd_ctl_elem_value
*ucontrol
)
344 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
345 enum CT_AMIXER_CTL type
= get_amixer_index(kcontrol
->private_value
);
346 struct amixer
*amixer
;
349 for (i
= 0; i
< 2; i
++) {
350 amixer
= ((struct ct_mixer
*)atc
->mixer
)->
351 amixers
[type
*CHN_NUM
+i
];
352 val
= amixer
->ops
->get_scale(amixer
) / VOL_SCALE
;
355 else if (val
> VOL_MAX
)
357 ucontrol
->value
.integer
.value
[i
] = val
;
363 static int ct_alsa_mix_volume_put(struct snd_kcontrol
*kcontrol
,
364 struct snd_ctl_elem_value
*ucontrol
)
366 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
367 struct ct_mixer
*mixer
= atc
->mixer
;
368 enum CT_AMIXER_CTL type
= get_amixer_index(kcontrol
->private_value
);
369 struct amixer
*amixer
;
370 int i
, j
, val
, oval
, change
= 0;
372 for (i
= 0; i
< 2; i
++) {
373 val
= ucontrol
->value
.integer
.value
[i
];
376 else if (val
> VOL_MAX
)
379 amixer
= mixer
->amixers
[type
*CHN_NUM
+i
];
380 oval
= amixer
->ops
->get_scale(amixer
);
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 SNDRV_CTL_ELEM_ACCESS_TLV_READ
,
403 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
404 .info
= ct_alsa_mix_volume_info
,
405 .get
= ct_alsa_mix_volume_get
,
406 .put
= ct_alsa_mix_volume_put
,
407 .tlv
= { .p
= ct_vol_db_scale
},
410 static int output_switch_info(struct snd_kcontrol
*kcontrol
,
411 struct snd_ctl_elem_info
*info
)
413 static const char *const names
[3] = {
414 "FP Headphones", "Headphones", "Speakers"
417 return snd_ctl_enum_info(info
, 1, 3, names
);
420 static int output_switch_get(struct snd_kcontrol
*kcontrol
,
421 struct snd_ctl_elem_value
*ucontrol
)
423 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
424 ucontrol
->value
.enumerated
.item
[0] = atc
->output_switch_get(atc
);
428 static int output_switch_put(struct snd_kcontrol
*kcontrol
,
429 struct snd_ctl_elem_value
*ucontrol
)
431 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
432 if (ucontrol
->value
.enumerated
.item
[0] > 2)
434 return atc
->output_switch_put(atc
, ucontrol
->value
.enumerated
.item
[0]);
437 static struct snd_kcontrol_new output_ctl
= {
438 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
439 .name
= "Analog Output Playback Enum",
440 .info
= output_switch_info
,
441 .get
= output_switch_get
,
442 .put
= output_switch_put
,
445 static int mic_source_switch_info(struct snd_kcontrol
*kcontrol
,
446 struct snd_ctl_elem_info
*info
)
448 static const char *const names
[3] = {
449 "Mic", "FP Mic", "Aux"
452 return snd_ctl_enum_info(info
, 1, 3, names
);
455 static int mic_source_switch_get(struct snd_kcontrol
*kcontrol
,
456 struct snd_ctl_elem_value
*ucontrol
)
458 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
459 ucontrol
->value
.enumerated
.item
[0] = atc
->mic_source_switch_get(atc
);
463 static int mic_source_switch_put(struct snd_kcontrol
*kcontrol
,
464 struct snd_ctl_elem_value
*ucontrol
)
466 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
467 if (ucontrol
->value
.enumerated
.item
[0] > 2)
469 return atc
->mic_source_switch_put(atc
,
470 ucontrol
->value
.enumerated
.item
[0]);
473 static struct snd_kcontrol_new mic_source_ctl
= {
474 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
475 .name
= "Mic Source Capture Enum",
476 .info
= mic_source_switch_info
,
477 .get
= mic_source_switch_get
,
478 .put
= mic_source_switch_put
,
482 do_line_mic_switch(struct ct_atc
*atc
, enum CTALSA_MIXER_CTL type
)
485 if (MIXER_LINEIN_C_S
== type
) {
486 atc
->select_line_in(atc
);
487 set_switch_state(atc
->mixer
, MIXER_MIC_C_S
, 0);
488 snd_ctl_notify(atc
->card
, SNDRV_CTL_EVENT_MASK_VALUE
,
490 } else if (MIXER_MIC_C_S
== type
) {
491 atc
->select_mic_in(atc
);
492 set_switch_state(atc
->mixer
, MIXER_LINEIN_C_S
, 0);
493 snd_ctl_notify(atc
->card
, SNDRV_CTL_EVENT_MASK_VALUE
,
499 do_digit_io_switch(struct ct_atc
*atc
, int state
)
501 struct ct_mixer
*mixer
= atc
->mixer
;
504 atc
->select_digit_io(atc
);
505 atc
->spdif_out_unmute(atc
,
506 get_switch_state(mixer
, MIXER_SPDIFO_P_S
));
507 atc
->spdif_in_unmute(atc
, 1);
508 atc
->line_in_unmute(atc
, 0);
512 if (get_switch_state(mixer
, MIXER_LINEIN_C_S
))
513 atc
->select_line_in(atc
);
514 else if (get_switch_state(mixer
, MIXER_MIC_C_S
))
515 atc
->select_mic_in(atc
);
517 atc
->spdif_out_unmute(atc
, 0);
518 atc
->spdif_in_unmute(atc
, 0);
519 atc
->line_in_unmute(atc
, 1);
523 static void do_switch(struct ct_atc
*atc
, enum CTALSA_MIXER_CTL type
, int state
)
525 struct ct_mixer
*mixer
= atc
->mixer
;
526 struct capabilities cap
= atc
->capabilities(atc
);
528 /* Do changes in mixer. */
529 if ((SWH_CAPTURE_START
<= type
) && (SWH_CAPTURE_END
>= type
)) {
531 ct_mixer_recording_select(mixer
,
532 get_amixer_index(type
));
534 ct_mixer_recording_unselect(mixer
,
535 get_amixer_index(type
));
538 /* Do changes out of mixer. */
539 if (!cap
.dedicated_mic
&&
540 (MIXER_LINEIN_C_S
== type
|| MIXER_MIC_C_S
== type
)) {
542 do_line_mic_switch(atc
, type
);
543 atc
->line_in_unmute(atc
, state
);
544 } else if (cap
.dedicated_mic
&& (MIXER_LINEIN_C_S
== type
))
545 atc
->line_in_unmute(atc
, state
);
546 else if (cap
.dedicated_mic
&& (MIXER_MIC_C_S
== type
))
547 atc
->mic_unmute(atc
, state
);
548 else if (MIXER_SPDIFI_C_S
== type
)
549 atc
->spdif_in_unmute(atc
, state
);
550 else if (MIXER_WAVEF_P_S
== type
)
551 atc
->line_front_unmute(atc
, state
);
552 else if (MIXER_WAVES_P_S
== type
)
553 atc
->line_surround_unmute(atc
, state
);
554 else if (MIXER_WAVEC_P_S
== type
)
555 atc
->line_clfe_unmute(atc
, state
);
556 else if (MIXER_WAVER_P_S
== type
)
557 atc
->line_rear_unmute(atc
, state
);
558 else if (MIXER_SPDIFO_P_S
== type
)
559 atc
->spdif_out_unmute(atc
, state
);
560 else if (MIXER_DIGITAL_IO_S
== type
)
561 do_digit_io_switch(atc
, state
);
566 static int ct_alsa_mix_switch_info(struct snd_kcontrol
*kcontrol
,
567 struct snd_ctl_elem_info
*uinfo
)
569 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
571 uinfo
->value
.integer
.min
= 0;
572 uinfo
->value
.integer
.max
= 1;
573 uinfo
->value
.integer
.step
= 1;
578 static int ct_alsa_mix_switch_get(struct snd_kcontrol
*kcontrol
,
579 struct snd_ctl_elem_value
*ucontrol
)
581 struct ct_mixer
*mixer
=
582 ((struct ct_atc
*)snd_kcontrol_chip(kcontrol
))->mixer
;
583 enum CTALSA_MIXER_CTL type
= kcontrol
->private_value
;
585 ucontrol
->value
.integer
.value
[0] = get_switch_state(mixer
, type
);
589 static int ct_alsa_mix_switch_put(struct snd_kcontrol
*kcontrol
,
590 struct snd_ctl_elem_value
*ucontrol
)
592 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
593 struct ct_mixer
*mixer
= atc
->mixer
;
594 enum CTALSA_MIXER_CTL type
= kcontrol
->private_value
;
597 state
= ucontrol
->value
.integer
.value
[0];
598 if (get_switch_state(mixer
, type
) == state
)
601 set_switch_state(mixer
, type
, state
);
602 do_switch(atc
, type
, state
);
607 static struct snd_kcontrol_new swh_ctl
= {
608 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
609 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
610 .info
= ct_alsa_mix_switch_info
,
611 .get
= ct_alsa_mix_switch_get
,
612 .put
= ct_alsa_mix_switch_put
615 static int ct_spdif_info(struct snd_kcontrol
*kcontrol
,
616 struct snd_ctl_elem_info
*uinfo
)
618 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_IEC958
;
623 static int ct_spdif_get_mask(struct snd_kcontrol
*kcontrol
,
624 struct snd_ctl_elem_value
*ucontrol
)
626 ucontrol
->value
.iec958
.status
[0] = 0xff;
627 ucontrol
->value
.iec958
.status
[1] = 0xff;
628 ucontrol
->value
.iec958
.status
[2] = 0xff;
629 ucontrol
->value
.iec958
.status
[3] = 0xff;
633 static int ct_spdif_get(struct snd_kcontrol
*kcontrol
,
634 struct snd_ctl_elem_value
*ucontrol
)
636 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
639 atc
->spdif_out_get_status(atc
, &status
);
642 status
= SNDRV_PCM_DEFAULT_CON_SPDIF
;
644 ucontrol
->value
.iec958
.status
[0] = (status
>> 0) & 0xff;
645 ucontrol
->value
.iec958
.status
[1] = (status
>> 8) & 0xff;
646 ucontrol
->value
.iec958
.status
[2] = (status
>> 16) & 0xff;
647 ucontrol
->value
.iec958
.status
[3] = (status
>> 24) & 0xff;
652 static int ct_spdif_put(struct snd_kcontrol
*kcontrol
,
653 struct snd_ctl_elem_value
*ucontrol
)
655 struct ct_atc
*atc
= snd_kcontrol_chip(kcontrol
);
657 unsigned int status
, old_status
;
659 status
= (ucontrol
->value
.iec958
.status
[0] << 0) |
660 (ucontrol
->value
.iec958
.status
[1] << 8) |
661 (ucontrol
->value
.iec958
.status
[2] << 16) |
662 (ucontrol
->value
.iec958
.status
[3] << 24);
664 atc
->spdif_out_get_status(atc
, &old_status
);
665 change
= (old_status
!= status
);
667 atc
->spdif_out_set_status(atc
, status
);
672 static struct snd_kcontrol_new iec958_mask_ctl
= {
673 .access
= SNDRV_CTL_ELEM_ACCESS_READ
,
674 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
675 .name
= SNDRV_CTL_NAME_IEC958("", PLAYBACK
, MASK
),
677 .info
= ct_spdif_info
,
678 .get
= ct_spdif_get_mask
,
679 .private_value
= MIXER_IEC958_MASK
682 static struct snd_kcontrol_new iec958_default_ctl
= {
683 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
684 .name
= SNDRV_CTL_NAME_IEC958("", PLAYBACK
, DEFAULT
),
686 .info
= ct_spdif_info
,
689 .private_value
= MIXER_IEC958_DEFAULT
692 static struct snd_kcontrol_new iec958_ctl
= {
693 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
694 .iface
= SNDRV_CTL_ELEM_IFACE_PCM
,
695 .name
= SNDRV_CTL_NAME_IEC958("", PLAYBACK
, PCM_STREAM
),
697 .info
= ct_spdif_info
,
700 .private_value
= MIXER_IEC958_STREAM
703 #define NUM_IEC958_CTL 3
706 ct_mixer_kcontrol_new(struct ct_mixer
*mixer
, struct snd_kcontrol_new
*new)
708 struct snd_kcontrol
*kctl
;
711 kctl
= snd_ctl_new1(new, mixer
->atc
);
715 if (SNDRV_CTL_ELEM_IFACE_PCM
== kctl
->id
.iface
)
716 kctl
->id
.device
= IEC958
;
718 err
= snd_ctl_add(mixer
->atc
->card
, kctl
);
722 switch (new->private_value
) {
723 case MIXER_LINEIN_C_S
:
724 kctls
[0] = kctl
; break;
726 kctls
[1] = kctl
; break;
734 static int ct_mixer_kcontrols_create(struct ct_mixer
*mixer
)
736 enum CTALSA_MIXER_CTL type
;
737 struct ct_atc
*atc
= mixer
->atc
;
738 struct capabilities cap
= atc
->capabilities(atc
);
741 /* Create snd kcontrol instances on demand */
742 for (type
= VOL_MIXER_START
; type
<= VOL_MIXER_END
; type
++) {
743 if (ct_kcontrol_init_table
[type
].ctl
) {
744 vol_ctl
.name
= ct_kcontrol_init_table
[type
].name
;
745 vol_ctl
.private_value
= (unsigned long)type
;
746 err
= ct_mixer_kcontrol_new(mixer
, &vol_ctl
);
752 ct_kcontrol_init_table
[MIXER_DIGITAL_IO_S
].ctl
= cap
.digit_io_switch
;
754 for (type
= SWH_MIXER_START
; type
<= SWH_MIXER_END
; type
++) {
755 if (ct_kcontrol_init_table
[type
].ctl
) {
756 swh_ctl
.name
= ct_kcontrol_init_table
[type
].name
;
757 swh_ctl
.private_value
= (unsigned long)type
;
758 err
= ct_mixer_kcontrol_new(mixer
, &swh_ctl
);
764 err
= ct_mixer_kcontrol_new(mixer
, &iec958_mask_ctl
);
768 err
= ct_mixer_kcontrol_new(mixer
, &iec958_default_ctl
);
772 err
= ct_mixer_kcontrol_new(mixer
, &iec958_ctl
);
776 if (cap
.output_switch
) {
777 err
= ct_mixer_kcontrol_new(mixer
, &output_ctl
);
782 if (cap
.mic_source_switch
) {
783 err
= ct_mixer_kcontrol_new(mixer
, &mic_source_ctl
);
787 atc
->line_front_unmute(atc
, 1);
788 set_switch_state(mixer
, MIXER_WAVEF_P_S
, 1);
789 atc
->line_surround_unmute(atc
, 0);
790 set_switch_state(mixer
, MIXER_WAVES_P_S
, 0);
791 atc
->line_clfe_unmute(atc
, 0);
792 set_switch_state(mixer
, MIXER_WAVEC_P_S
, 0);
793 atc
->line_rear_unmute(atc
, 0);
794 set_switch_state(mixer
, MIXER_WAVER_P_S
, 0);
795 atc
->spdif_out_unmute(atc
, 0);
796 set_switch_state(mixer
, MIXER_SPDIFO_P_S
, 0);
797 atc
->line_in_unmute(atc
, 0);
798 if (cap
.dedicated_mic
)
799 atc
->mic_unmute(atc
, 0);
800 atc
->spdif_in_unmute(atc
, 0);
801 set_switch_state(mixer
, MIXER_PCM_C_S
, 0);
802 set_switch_state(mixer
, MIXER_LINEIN_C_S
, 0);
803 set_switch_state(mixer
, MIXER_SPDIFI_C_S
, 0);
809 ct_mixer_recording_select(struct ct_mixer
*mixer
, enum CT_AMIXER_CTL type
)
811 struct amixer
*amix_d
;
815 for (i
= 0; i
< 2; i
++) {
816 amix_d
= mixer
->amixers
[type
*CHN_NUM
+i
];
817 sum_c
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+i
];
818 amix_d
->ops
->set_sum(amix_d
, sum_c
);
819 amix_d
->ops
->commit_write(amix_d
);
824 ct_mixer_recording_unselect(struct ct_mixer
*mixer
, enum CT_AMIXER_CTL type
)
826 struct amixer
*amix_d
;
829 for (i
= 0; i
< 2; i
++) {
830 amix_d
= mixer
->amixers
[type
*CHN_NUM
+i
];
831 amix_d
->ops
->set_sum(amix_d
, NULL
);
832 amix_d
->ops
->commit_write(amix_d
);
836 static int ct_mixer_get_resources(struct ct_mixer
*mixer
)
838 struct sum_mgr
*sum_mgr
;
840 struct sum_desc sum_desc
= {0};
841 struct amixer_mgr
*amixer_mgr
;
842 struct amixer
*amixer
;
843 struct amixer_desc am_desc
= {0};
847 /* Allocate sum resources for mixer obj */
848 sum_mgr
= (struct sum_mgr
*)mixer
->atc
->rsc_mgrs
[SUM
];
849 sum_desc
.msr
= mixer
->atc
->msr
;
850 for (i
= 0; i
< (NUM_CT_SUMS
* CHN_NUM
); i
++) {
851 err
= sum_mgr
->get_sum(sum_mgr
, &sum_desc
, &sum
);
853 dev_err(mixer
->atc
->card
->dev
,
854 "Failed to get sum resources for front output!\n");
857 mixer
->sums
[i
] = sum
;
862 /* Allocate amixer resources for mixer obj */
863 amixer_mgr
= (struct amixer_mgr
*)mixer
->atc
->rsc_mgrs
[AMIXER
];
864 am_desc
.msr
= mixer
->atc
->msr
;
865 for (i
= 0; i
< (NUM_CT_AMIXERS
* CHN_NUM
); i
++) {
866 err
= amixer_mgr
->get_amixer(amixer_mgr
, &am_desc
, &amixer
);
868 dev_err(mixer
->atc
->card
->dev
,
869 "Failed to get amixer resources for mixer obj!\n");
872 mixer
->amixers
[i
] = amixer
;
880 for (i
= 0; i
< (NUM_CT_AMIXERS
* CHN_NUM
); i
++) {
881 if (NULL
!= mixer
->amixers
[i
]) {
882 amixer
= mixer
->amixers
[i
];
883 amixer_mgr
->put_amixer(amixer_mgr
, amixer
);
884 mixer
->amixers
[i
] = NULL
;
888 for (i
= 0; i
< (NUM_CT_SUMS
* CHN_NUM
); i
++) {
889 if (NULL
!= mixer
->sums
[i
]) {
890 sum_mgr
->put_sum(sum_mgr
, (struct sum
*)mixer
->sums
[i
]);
891 mixer
->sums
[i
] = NULL
;
898 static int ct_mixer_get_mem(struct ct_mixer
**rmixer
)
900 struct ct_mixer
*mixer
;
904 /* Allocate mem for mixer obj */
905 mixer
= kzalloc(sizeof(*mixer
), GFP_KERNEL
);
909 mixer
->amixers
= kcalloc(NUM_CT_AMIXERS
* CHN_NUM
, sizeof(void *),
911 if (!mixer
->amixers
) {
915 mixer
->sums
= kcalloc(NUM_CT_SUMS
* CHN_NUM
, sizeof(void *),
926 kfree(mixer
->amixers
);
932 static int ct_mixer_topology_build(struct ct_mixer
*mixer
)
935 struct amixer
*amix_d
, *amix_s
;
936 enum CT_AMIXER_CTL i
, j
;
939 /* Build topology from destination to source */
941 /* Set up Master mixer */
942 for (i
= AMIXER_MASTER_F
, k
= SUM_IN_F
;
943 i
<= AMIXER_MASTER_S
; i
++, k
++) {
944 amix_d
= mixer
->amixers
[i
*CHN_NUM
];
945 sum
= mixer
->sums
[k
*CHN_NUM
];
946 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
947 amix_d
= mixer
->amixers
[i
*CHN_NUM
+1];
948 sum
= mixer
->sums
[k
*CHN_NUM
+1];
949 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
952 /* Set up Wave-out mixer */
953 for (i
= AMIXER_WAVE_F
, j
= AMIXER_MASTER_F
;
954 i
<= AMIXER_WAVE_S
; i
++, j
++) {
955 amix_d
= mixer
->amixers
[i
*CHN_NUM
];
956 amix_s
= mixer
->amixers
[j
*CHN_NUM
];
957 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
958 amix_d
= mixer
->amixers
[i
*CHN_NUM
+1];
959 amix_s
= mixer
->amixers
[j
*CHN_NUM
+1];
960 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
963 /* Set up S/PDIF-out mixer */
964 amix_d
= mixer
->amixers
[AMIXER_SPDIFO
*CHN_NUM
];
965 amix_s
= mixer
->amixers
[AMIXER_MASTER_F
*CHN_NUM
];
966 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
967 amix_d
= mixer
->amixers
[AMIXER_SPDIFO
*CHN_NUM
+1];
968 amix_s
= mixer
->amixers
[AMIXER_MASTER_F
*CHN_NUM
+1];
969 amix_d
->ops
->setup(amix_d
, &amix_s
->rsc
, INIT_VOL
, NULL
);
971 /* Set up PCM-in mixer */
972 for (i
= AMIXER_PCM_F
, k
= SUM_IN_F
; i
<= AMIXER_PCM_S
; i
++, k
++) {
973 amix_d
= mixer
->amixers
[i
*CHN_NUM
];
974 sum
= mixer
->sums
[k
*CHN_NUM
];
975 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
976 amix_d
= mixer
->amixers
[i
*CHN_NUM
+1];
977 sum
= mixer
->sums
[k
*CHN_NUM
+1];
978 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
981 /* Set up Line-in mixer */
982 amix_d
= mixer
->amixers
[AMIXER_LINEIN
*CHN_NUM
];
983 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
];
984 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
985 amix_d
= mixer
->amixers
[AMIXER_LINEIN
*CHN_NUM
+1];
986 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
+1];
987 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
989 /* Set up Mic-in mixer */
990 amix_d
= mixer
->amixers
[AMIXER_MIC
*CHN_NUM
];
991 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
];
992 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
993 amix_d
= mixer
->amixers
[AMIXER_MIC
*CHN_NUM
+1];
994 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
+1];
995 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
997 /* Set up S/PDIF-in mixer */
998 amix_d
= mixer
->amixers
[AMIXER_SPDIFI
*CHN_NUM
];
999 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
];
1000 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1001 amix_d
= mixer
->amixers
[AMIXER_SPDIFI
*CHN_NUM
+1];
1002 sum
= mixer
->sums
[SUM_IN_F
*CHN_NUM
+1];
1003 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1005 /* Set up Master recording mixer */
1006 amix_d
= mixer
->amixers
[AMIXER_MASTER_F_C
*CHN_NUM
];
1007 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1008 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
1009 amix_d
= mixer
->amixers
[AMIXER_MASTER_F_C
*CHN_NUM
+1];
1010 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1011 amix_d
->ops
->setup(amix_d
, &sum
->rsc
, INIT_VOL
, NULL
);
1013 /* Set up PCM-in recording mixer */
1014 amix_d
= mixer
->amixers
[AMIXER_PCM_F_C
*CHN_NUM
];
1015 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1016 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1017 amix_d
= mixer
->amixers
[AMIXER_PCM_F_C
*CHN_NUM
+1];
1018 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1019 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1021 /* Set up Line-in recording mixer */
1022 amix_d
= mixer
->amixers
[AMIXER_LINEIN_C
*CHN_NUM
];
1023 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1024 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1025 amix_d
= mixer
->amixers
[AMIXER_LINEIN_C
*CHN_NUM
+1];
1026 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1027 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1029 /* Set up Mic-in recording mixer */
1030 amix_d
= mixer
->amixers
[AMIXER_MIC_C
*CHN_NUM
];
1031 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1032 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1033 amix_d
= mixer
->amixers
[AMIXER_MIC_C
*CHN_NUM
+1];
1034 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1035 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1037 /* Set up S/PDIF-in recording mixer */
1038 amix_d
= mixer
->amixers
[AMIXER_SPDIFI_C
*CHN_NUM
];
1039 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
];
1040 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1041 amix_d
= mixer
->amixers
[AMIXER_SPDIFI_C
*CHN_NUM
+1];
1042 sum
= mixer
->sums
[SUM_IN_F_C
*CHN_NUM
+1];
1043 amix_d
->ops
->setup(amix_d
, NULL
, INIT_VOL
, sum
);
1048 static int mixer_set_input_port(struct amixer
*amixer
, struct rsc
*rsc
)
1050 amixer
->ops
->set_input(amixer
, rsc
);
1051 amixer
->ops
->commit_write(amixer
);
1056 static enum CT_AMIXER_CTL
port_to_amixer(enum MIXER_PORT_T type
)
1059 case MIX_WAVE_FRONT
: return AMIXER_WAVE_F
;
1060 case MIX_WAVE_SURROUND
: return AMIXER_WAVE_S
;
1061 case MIX_WAVE_CENTLFE
: return AMIXER_WAVE_C
;
1062 case MIX_WAVE_REAR
: return AMIXER_WAVE_R
;
1063 case MIX_PCMO_FRONT
: return AMIXER_MASTER_F_C
;
1064 case MIX_SPDIF_OUT
: return AMIXER_SPDIFO
;
1065 case MIX_LINE_IN
: return AMIXER_LINEIN
;
1066 case MIX_MIC_IN
: return AMIXER_MIC
;
1067 case MIX_SPDIF_IN
: return AMIXER_SPDIFI
;
1068 case MIX_PCMI_FRONT
: return AMIXER_PCM_F
;
1069 case MIX_PCMI_SURROUND
: return AMIXER_PCM_S
;
1070 case MIX_PCMI_CENTLFE
: return AMIXER_PCM_C
;
1071 case MIX_PCMI_REAR
: return AMIXER_PCM_R
;
1076 static int mixer_get_output_ports(struct ct_mixer
*mixer
,
1077 enum MIXER_PORT_T type
,
1078 struct rsc
**rleft
, struct rsc
**rright
)
1080 enum CT_AMIXER_CTL amix
= port_to_amixer(type
);
1083 *rleft
= &((struct amixer
*)mixer
->amixers
[amix
*CHN_NUM
])->rsc
;
1087 &((struct amixer
*)mixer
->amixers
[amix
*CHN_NUM
+1])->rsc
;
1092 static int mixer_set_input_left(struct ct_mixer
*mixer
,
1093 enum MIXER_PORT_T type
, struct rsc
*rsc
)
1095 enum CT_AMIXER_CTL amix
= port_to_amixer(type
);
1097 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
], rsc
);
1098 amix
= get_recording_amixer(amix
);
1099 if (amix
< NUM_CT_AMIXERS
)
1100 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
], rsc
);
1106 mixer_set_input_right(struct ct_mixer
*mixer
,
1107 enum MIXER_PORT_T type
, struct rsc
*rsc
)
1109 enum CT_AMIXER_CTL amix
= port_to_amixer(type
);
1111 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
+1], rsc
);
1112 amix
= get_recording_amixer(amix
);
1113 if (amix
< NUM_CT_AMIXERS
)
1114 mixer_set_input_port(mixer
->amixers
[amix
*CHN_NUM
+1], rsc
);
1119 #ifdef CONFIG_PM_SLEEP
1120 static int mixer_resume(struct ct_mixer
*mixer
)
1123 struct amixer
*amixer
;
1125 /* resume topology and volume gain. */
1126 for (i
= 0; i
< NUM_CT_AMIXERS
*CHN_NUM
; i
++) {
1127 amixer
= mixer
->amixers
[i
];
1128 amixer
->ops
->commit_write(amixer
);
1131 /* resume switch state. */
1132 for (i
= SWH_MIXER_START
; i
<= SWH_MIXER_END
; i
++) {
1133 state
= get_switch_state(mixer
, i
);
1134 do_switch(mixer
->atc
, i
, state
);
1141 int ct_mixer_destroy(struct ct_mixer
*mixer
)
1143 struct sum_mgr
*sum_mgr
= (struct sum_mgr
*)mixer
->atc
->rsc_mgrs
[SUM
];
1144 struct amixer_mgr
*amixer_mgr
=
1145 (struct amixer_mgr
*)mixer
->atc
->rsc_mgrs
[AMIXER
];
1146 struct amixer
*amixer
;
1149 /* Release amixer resources */
1150 for (i
= 0; i
< (NUM_CT_AMIXERS
* CHN_NUM
); i
++) {
1151 if (NULL
!= mixer
->amixers
[i
]) {
1152 amixer
= mixer
->amixers
[i
];
1153 amixer_mgr
->put_amixer(amixer_mgr
, amixer
);
1157 /* Release sum resources */
1158 for (i
= 0; i
< (NUM_CT_SUMS
* CHN_NUM
); i
++) {
1159 if (NULL
!= mixer
->sums
[i
])
1160 sum_mgr
->put_sum(sum_mgr
, (struct sum
*)mixer
->sums
[i
]);
1163 /* Release mem assigned to mixer object */
1165 kfree(mixer
->amixers
);
1171 int ct_mixer_create(struct ct_atc
*atc
, struct ct_mixer
**rmixer
)
1173 struct ct_mixer
*mixer
;
1178 /* Allocate mem for mixer obj */
1179 err
= ct_mixer_get_mem(&mixer
);
1183 mixer
->switch_state
= 0;
1185 /* Set operations */
1186 mixer
->get_output_ports
= mixer_get_output_ports
;
1187 mixer
->set_input_left
= mixer_set_input_left
;
1188 mixer
->set_input_right
= mixer_set_input_right
;
1189 #ifdef CONFIG_PM_SLEEP
1190 mixer
->resume
= mixer_resume
;
1193 /* Allocate chip resources for mixer obj */
1194 err
= ct_mixer_get_resources(mixer
);
1198 /* Build internal mixer topology */
1199 ct_mixer_topology_build(mixer
);
1206 ct_mixer_destroy(mixer
);
1210 int ct_alsa_mix_create(struct ct_atc
*atc
,
1211 enum CTALSADEVS device
,
1212 const char *device_name
)
1216 /* Create snd kcontrol instances on demand */
1217 /* vol_ctl.device = swh_ctl.device = device; */ /* better w/ device 0 */
1218 err
= ct_mixer_kcontrols_create((struct ct_mixer
*)atc
->mixer
);
1222 strcpy(atc
->card
->mixername
, device_name
);