Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
0004  *
0005  * @File    ctmixer.c
0006  *
0007  * @Brief
0008  * This file contains the implementation of alsa mixer device functions.
0009  *
0010  * @Author  Liu Chun
0011  * @Date    May 28 2008
0012  */
0013 
0014 
0015 #include "ctmixer.h"
0016 #include "ctamixer.h"
0017 #include <linux/slab.h>
0018 #include <sound/core.h>
0019 #include <sound/control.h>
0020 #include <sound/asoundef.h>
0021 #include <sound/pcm.h>
0022 #include <sound/tlv.h>
0023 
0024 enum CT_SUM_CTL {
0025     SUM_IN_F,
0026     SUM_IN_R,
0027     SUM_IN_C,
0028     SUM_IN_S,
0029     SUM_IN_F_C,
0030 
0031     NUM_CT_SUMS
0032 };
0033 
0034 enum CT_AMIXER_CTL {
0035     /* volume control mixers */
0036     AMIXER_MASTER_F,
0037     AMIXER_MASTER_R,
0038     AMIXER_MASTER_C,
0039     AMIXER_MASTER_S,
0040     AMIXER_PCM_F,
0041     AMIXER_PCM_R,
0042     AMIXER_PCM_C,
0043     AMIXER_PCM_S,
0044     AMIXER_SPDIFI,
0045     AMIXER_LINEIN,
0046     AMIXER_MIC,
0047     AMIXER_SPDIFO,
0048     AMIXER_WAVE_F,
0049     AMIXER_WAVE_R,
0050     AMIXER_WAVE_C,
0051     AMIXER_WAVE_S,
0052     AMIXER_MASTER_F_C,
0053     AMIXER_PCM_F_C,
0054     AMIXER_SPDIFI_C,
0055     AMIXER_LINEIN_C,
0056     AMIXER_MIC_C,
0057 
0058     /* this should always be the last one */
0059     NUM_CT_AMIXERS
0060 };
0061 
0062 enum CTALSA_MIXER_CTL {
0063     /* volume control mixers */
0064     MIXER_MASTER_P,
0065     MIXER_PCM_P,
0066     MIXER_LINEIN_P,
0067     MIXER_MIC_P,
0068     MIXER_SPDIFI_P,
0069     MIXER_SPDIFO_P,
0070     MIXER_WAVEF_P,
0071     MIXER_WAVER_P,
0072     MIXER_WAVEC_P,
0073     MIXER_WAVES_P,
0074     MIXER_MASTER_C,
0075     MIXER_PCM_C,
0076     MIXER_LINEIN_C,
0077     MIXER_MIC_C,
0078     MIXER_SPDIFI_C,
0079 
0080     /* switch control mixers */
0081     MIXER_PCM_C_S,
0082     MIXER_LINEIN_C_S,
0083     MIXER_MIC_C_S,
0084     MIXER_SPDIFI_C_S,
0085     MIXER_SPDIFO_P_S,
0086     MIXER_WAVEF_P_S,
0087     MIXER_WAVER_P_S,
0088     MIXER_WAVEC_P_S,
0089     MIXER_WAVES_P_S,
0090     MIXER_DIGITAL_IO_S,
0091     MIXER_IEC958_MASK,
0092     MIXER_IEC958_DEFAULT,
0093     MIXER_IEC958_STREAM,
0094 
0095     /* this should always be the last one */
0096     NUM_CTALSA_MIXERS
0097 };
0098 
0099 #define VOL_MIXER_START     MIXER_MASTER_P
0100 #define VOL_MIXER_END       MIXER_SPDIFI_C
0101 #define VOL_MIXER_NUM       (VOL_MIXER_END - VOL_MIXER_START + 1)
0102 #define SWH_MIXER_START     MIXER_PCM_C_S
0103 #define SWH_MIXER_END       MIXER_DIGITAL_IO_S
0104 #define SWH_CAPTURE_START   MIXER_PCM_C_S
0105 #define SWH_CAPTURE_END     MIXER_SPDIFI_C_S
0106 
0107 #define CHN_NUM     2
0108 
0109 struct ct_kcontrol_init {
0110     unsigned char ctl;
0111     char *name;
0112 };
0113 
0114 static struct ct_kcontrol_init
0115 ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
0116     [MIXER_MASTER_P] = {
0117         .ctl = 1,
0118         .name = "Master Playback Volume",
0119     },
0120     [MIXER_MASTER_C] = {
0121         .ctl = 1,
0122         .name = "Master Capture Volume",
0123     },
0124     [MIXER_PCM_P] = {
0125         .ctl = 1,
0126         .name = "PCM Playback Volume",
0127     },
0128     [MIXER_PCM_C] = {
0129         .ctl = 1,
0130         .name = "PCM Capture Volume",
0131     },
0132     [MIXER_LINEIN_P] = {
0133         .ctl = 1,
0134         .name = "Line Playback Volume",
0135     },
0136     [MIXER_LINEIN_C] = {
0137         .ctl = 1,
0138         .name = "Line Capture Volume",
0139     },
0140     [MIXER_MIC_P] = {
0141         .ctl = 1,
0142         .name = "Mic Playback Volume",
0143     },
0144     [MIXER_MIC_C] = {
0145         .ctl = 1,
0146         .name = "Mic Capture Volume",
0147     },
0148     [MIXER_SPDIFI_P] = {
0149         .ctl = 1,
0150         .name = "IEC958 Playback Volume",
0151     },
0152     [MIXER_SPDIFI_C] = {
0153         .ctl = 1,
0154         .name = "IEC958 Capture Volume",
0155     },
0156     [MIXER_SPDIFO_P] = {
0157         .ctl = 1,
0158         .name = "Digital Playback Volume",
0159     },
0160     [MIXER_WAVEF_P] = {
0161         .ctl = 1,
0162         .name = "Front Playback Volume",
0163     },
0164     [MIXER_WAVES_P] = {
0165         .ctl = 1,
0166         .name = "Side Playback Volume",
0167     },
0168     [MIXER_WAVEC_P] = {
0169         .ctl = 1,
0170         .name = "Center/LFE Playback Volume",
0171     },
0172     [MIXER_WAVER_P] = {
0173         .ctl = 1,
0174         .name = "Surround Playback Volume",
0175     },
0176     [MIXER_PCM_C_S] = {
0177         .ctl = 1,
0178         .name = "PCM Capture Switch",
0179     },
0180     [MIXER_LINEIN_C_S] = {
0181         .ctl = 1,
0182         .name = "Line Capture Switch",
0183     },
0184     [MIXER_MIC_C_S] = {
0185         .ctl = 1,
0186         .name = "Mic Capture Switch",
0187     },
0188     [MIXER_SPDIFI_C_S] = {
0189         .ctl = 1,
0190         .name = "IEC958 Capture Switch",
0191     },
0192     [MIXER_SPDIFO_P_S] = {
0193         .ctl = 1,
0194         .name = "Digital Playback Switch",
0195     },
0196     [MIXER_WAVEF_P_S] = {
0197         .ctl = 1,
0198         .name = "Front Playback Switch",
0199     },
0200     [MIXER_WAVES_P_S] = {
0201         .ctl = 1,
0202         .name = "Side Playback Switch",
0203     },
0204     [MIXER_WAVEC_P_S] = {
0205         .ctl = 1,
0206         .name = "Center/LFE Playback Switch",
0207     },
0208     [MIXER_WAVER_P_S] = {
0209         .ctl = 1,
0210         .name = "Surround Playback Switch",
0211     },
0212     [MIXER_DIGITAL_IO_S] = {
0213         .ctl = 0,
0214         .name = "Digit-IO Playback Switch",
0215     },
0216 };
0217 
0218 static void
0219 ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
0220 
0221 static void
0222 ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
0223 
0224 /* FIXME: this static looks like it would fail if more than one card was */
0225 /* installed. */
0226 static struct snd_kcontrol *kctls[2] = {NULL};
0227 
0228 static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
0229 {
0230     switch (alsa_index) {
0231     case MIXER_MASTER_P:    return AMIXER_MASTER_F;
0232     case MIXER_MASTER_C:    return AMIXER_MASTER_F_C;
0233     case MIXER_PCM_P:   return AMIXER_PCM_F;
0234     case MIXER_PCM_C:
0235     case MIXER_PCM_C_S: return AMIXER_PCM_F_C;
0236     case MIXER_LINEIN_P:    return AMIXER_LINEIN;
0237     case MIXER_LINEIN_C:
0238     case MIXER_LINEIN_C_S:  return AMIXER_LINEIN_C;
0239     case MIXER_MIC_P:   return AMIXER_MIC;
0240     case MIXER_MIC_C:
0241     case MIXER_MIC_C_S: return AMIXER_MIC_C;
0242     case MIXER_SPDIFI_P:    return AMIXER_SPDIFI;
0243     case MIXER_SPDIFI_C:
0244     case MIXER_SPDIFI_C_S:  return AMIXER_SPDIFI_C;
0245     case MIXER_SPDIFO_P:    return AMIXER_SPDIFO;
0246     case MIXER_WAVEF_P: return AMIXER_WAVE_F;
0247     case MIXER_WAVES_P: return AMIXER_WAVE_S;
0248     case MIXER_WAVEC_P: return AMIXER_WAVE_C;
0249     case MIXER_WAVER_P: return AMIXER_WAVE_R;
0250     default:        return NUM_CT_AMIXERS;
0251     }
0252 }
0253 
0254 static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index)
0255 {
0256     switch (index) {
0257     case AMIXER_MASTER_F:   return AMIXER_MASTER_F_C;
0258     case AMIXER_PCM_F:  return AMIXER_PCM_F_C;
0259     case AMIXER_SPDIFI: return AMIXER_SPDIFI_C;
0260     case AMIXER_LINEIN: return AMIXER_LINEIN_C;
0261     case AMIXER_MIC:    return AMIXER_MIC_C;
0262     default:        return NUM_CT_AMIXERS;
0263     }
0264 }
0265 
0266 static unsigned char
0267 get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type)
0268 {
0269     return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START)))
0270         ? 1 : 0;
0271 }
0272 
0273 static void
0274 set_switch_state(struct ct_mixer *mixer,
0275          enum CTALSA_MIXER_CTL type, unsigned char state)
0276 {
0277     if (state)
0278         mixer->switch_state |= (0x1 << (type - SWH_MIXER_START));
0279     else
0280         mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
0281 }
0282 
0283 #if 0 /* not used */
0284 /* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
0285  * from 2^-6 to (1+1023/1024) */
0286 static unsigned int uint16_to_float14(unsigned int x)
0287 {
0288     unsigned int i;
0289 
0290     if (x < 17)
0291         return 0;
0292 
0293     x *= 2031;
0294     x /= 65535;
0295     x += 16;
0296 
0297     /* i <= 6 */
0298     for (i = 0; !(x & 0x400); i++)
0299         x <<= 1;
0300 
0301     x = (((7 - i) & 0x7) << 10) | (x & 0x3ff);
0302 
0303     return x;
0304 }
0305 
0306 static unsigned int float14_to_uint16(unsigned int x)
0307 {
0308     unsigned int e;
0309 
0310     if (!x)
0311         return x;
0312 
0313     e = (x >> 10) & 0x7;
0314     x &= 0x3ff;
0315     x += 1024;
0316     x >>= (7 - e);
0317     x -= 16;
0318     x *= 65535;
0319     x /= 2031;
0320 
0321     return x;
0322 }
0323 #endif /* not used */
0324 
0325 #define VOL_SCALE   0x1c
0326 #define VOL_MAX     0x100
0327 
0328 static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1);
0329 
0330 static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
0331                    struct snd_ctl_elem_info *uinfo)
0332 {
0333     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0334     uinfo->count = 2;
0335     uinfo->value.integer.min = 0;
0336     uinfo->value.integer.max = VOL_MAX;
0337 
0338     return 0;
0339 }
0340 
0341 static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
0342                   struct snd_ctl_elem_value *ucontrol)
0343 {
0344     struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
0345     enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
0346     struct amixer *amixer;
0347     int i, val;
0348 
0349     for (i = 0; i < 2; i++) {
0350         amixer = ((struct ct_mixer *)atc->mixer)->
0351                         amixers[type*CHN_NUM+i];
0352         val = amixer->ops->get_scale(amixer) / VOL_SCALE;
0353         if (val < 0)
0354             val = 0;
0355         else if (val > VOL_MAX)
0356             val = VOL_MAX;
0357         ucontrol->value.integer.value[i] = val;
0358     }
0359 
0360     return 0;
0361 }
0362 
0363 static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
0364                   struct snd_ctl_elem_value *ucontrol)
0365 {
0366     struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
0367     struct ct_mixer *mixer = atc->mixer;
0368     enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
0369     struct amixer *amixer;
0370     int i, j, val, oval, change = 0;
0371 
0372     for (i = 0; i < 2; i++) {
0373         val = ucontrol->value.integer.value[i];
0374         if (val < 0)
0375             val = 0;
0376         else if (val > VOL_MAX)
0377             val = VOL_MAX;
0378         val *= VOL_SCALE;
0379         amixer = mixer->amixers[type*CHN_NUM+i];
0380         oval = amixer->ops->get_scale(amixer);
0381         if (val != oval) {
0382             amixer->ops->set_scale(amixer, val);
0383             amixer->ops->commit_write(amixer);
0384             change = 1;
0385             /* Synchronize Master/PCM playback AMIXERs. */
0386             if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) {
0387                 for (j = 1; j < 4; j++) {
0388                     amixer = mixer->
0389                         amixers[(type+j)*CHN_NUM+i];
0390                     amixer->ops->set_scale(amixer, val);
0391                     amixer->ops->commit_write(amixer);
0392                 }
0393             }
0394         }
0395     }
0396 
0397     return change;
0398 }
0399 
0400 static struct snd_kcontrol_new vol_ctl = {
0401     .access     = SNDRV_CTL_ELEM_ACCESS_READWRITE |
0402               SNDRV_CTL_ELEM_ACCESS_TLV_READ,
0403     .iface      = SNDRV_CTL_ELEM_IFACE_MIXER,
0404     .info       = ct_alsa_mix_volume_info,
0405     .get        = ct_alsa_mix_volume_get,
0406     .put        = ct_alsa_mix_volume_put,
0407     .tlv        = { .p =  ct_vol_db_scale },
0408 };
0409 
0410 static int output_switch_info(struct snd_kcontrol *kcontrol,
0411                   struct snd_ctl_elem_info *info)
0412 {
0413     static const char *const names[3] = {
0414       "FP Headphones", "Headphones", "Speakers"
0415     };
0416 
0417     return snd_ctl_enum_info(info, 1, 3, names);
0418 }
0419 
0420 static int output_switch_get(struct snd_kcontrol *kcontrol,
0421                  struct snd_ctl_elem_value *ucontrol)
0422 {
0423     struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
0424     ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc);
0425     return 0;
0426 }
0427 
0428 static int output_switch_put(struct snd_kcontrol *kcontrol,
0429                  struct snd_ctl_elem_value *ucontrol)
0430 {
0431     struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
0432     if (ucontrol->value.enumerated.item[0] > 2)
0433         return -EINVAL;
0434     return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]);
0435 }
0436 
0437 static struct snd_kcontrol_new output_ctl = {
0438     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0439     .name = "Analog Output Playback Enum",
0440     .info = output_switch_info,
0441     .get = output_switch_get,
0442     .put = output_switch_put,
0443 };
0444 
0445 static int mic_source_switch_info(struct snd_kcontrol *kcontrol,
0446                   struct snd_ctl_elem_info *info)
0447 {
0448     static const char *const names[3] = {
0449       "Mic", "FP Mic", "Aux"
0450     };
0451 
0452     return snd_ctl_enum_info(info, 1, 3, names);
0453 }
0454 
0455 static int mic_source_switch_get(struct snd_kcontrol *kcontrol,
0456                  struct snd_ctl_elem_value *ucontrol)
0457 {
0458     struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
0459     ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc);
0460     return 0;
0461 }
0462 
0463 static int mic_source_switch_put(struct snd_kcontrol *kcontrol,
0464                  struct snd_ctl_elem_value *ucontrol)
0465 {
0466     struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
0467     if (ucontrol->value.enumerated.item[0] > 2)
0468         return -EINVAL;
0469     return atc->mic_source_switch_put(atc,
0470                     ucontrol->value.enumerated.item[0]);
0471 }
0472 
0473 static struct snd_kcontrol_new mic_source_ctl = {
0474     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0475     .name = "Mic Source Capture Enum",
0476     .info = mic_source_switch_info,
0477     .get = mic_source_switch_get,
0478     .put = mic_source_switch_put,
0479 };
0480 
0481 static void
0482 do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
0483 {
0484 
0485     if (MIXER_LINEIN_C_S == type) {
0486         atc->select_line_in(atc);
0487         set_switch_state(atc->mixer, MIXER_MIC_C_S, 0);
0488         snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
0489                             &kctls[1]->id);
0490     } else if (MIXER_MIC_C_S == type) {
0491         atc->select_mic_in(atc);
0492         set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0);
0493         snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
0494                             &kctls[0]->id);
0495     }
0496 }
0497 
0498 static void
0499 do_digit_io_switch(struct ct_atc *atc, int state)
0500 {
0501     struct ct_mixer *mixer = atc->mixer;
0502 
0503     if (state) {
0504         atc->select_digit_io(atc);
0505         atc->spdif_out_unmute(atc,
0506                 get_switch_state(mixer, MIXER_SPDIFO_P_S));
0507         atc->spdif_in_unmute(atc, 1);
0508         atc->line_in_unmute(atc, 0);
0509         return;
0510     }
0511 
0512     if (get_switch_state(mixer, MIXER_LINEIN_C_S))
0513         atc->select_line_in(atc);
0514     else if (get_switch_state(mixer, MIXER_MIC_C_S))
0515         atc->select_mic_in(atc);
0516 
0517     atc->spdif_out_unmute(atc, 0);
0518     atc->spdif_in_unmute(atc, 0);
0519     atc->line_in_unmute(atc, 1);
0520     return;
0521 }
0522 
0523 static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
0524 {
0525     struct ct_mixer *mixer = atc->mixer;
0526     struct capabilities cap = atc->capabilities(atc);
0527 
0528     /* Do changes in mixer. */
0529     if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
0530         if (state) {
0531             ct_mixer_recording_select(mixer,
0532                           get_amixer_index(type));
0533         } else {
0534             ct_mixer_recording_unselect(mixer,
0535                             get_amixer_index(type));
0536         }
0537     }
0538     /* Do changes out of mixer. */
0539     if (!cap.dedicated_mic &&
0540         (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) {
0541         if (state)
0542             do_line_mic_switch(atc, type);
0543         atc->line_in_unmute(atc, state);
0544     } else if (cap.dedicated_mic && (MIXER_LINEIN_C_S == type))
0545         atc->line_in_unmute(atc, state);
0546     else if (cap.dedicated_mic && (MIXER_MIC_C_S == type))
0547         atc->mic_unmute(atc, state);
0548     else if (MIXER_SPDIFI_C_S == type)
0549         atc->spdif_in_unmute(atc, state);
0550     else if (MIXER_WAVEF_P_S == type)
0551         atc->line_front_unmute(atc, state);
0552     else if (MIXER_WAVES_P_S == type)
0553         atc->line_surround_unmute(atc, state);
0554     else if (MIXER_WAVEC_P_S == type)
0555         atc->line_clfe_unmute(atc, state);
0556     else if (MIXER_WAVER_P_S == type)
0557         atc->line_rear_unmute(atc, state);
0558     else if (MIXER_SPDIFO_P_S == type)
0559         atc->spdif_out_unmute(atc, state);
0560     else if (MIXER_DIGITAL_IO_S == type)
0561         do_digit_io_switch(atc, state);
0562 
0563     return;
0564 }
0565 
0566 static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol,
0567                    struct snd_ctl_elem_info *uinfo)
0568 {
0569     uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
0570     uinfo->count = 1;
0571     uinfo->value.integer.min = 0;
0572     uinfo->value.integer.max = 1;
0573     uinfo->value.integer.step = 1;
0574 
0575     return 0;
0576 }
0577 
0578 static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol,
0579                   struct snd_ctl_elem_value *ucontrol)
0580 {
0581     struct ct_mixer *mixer =
0582         ((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer;
0583     enum CTALSA_MIXER_CTL type = kcontrol->private_value;
0584 
0585     ucontrol->value.integer.value[0] = get_switch_state(mixer, type);
0586     return 0;
0587 }
0588 
0589 static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol,
0590                   struct snd_ctl_elem_value *ucontrol)
0591 {
0592     struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
0593     struct ct_mixer *mixer = atc->mixer;
0594     enum CTALSA_MIXER_CTL type = kcontrol->private_value;
0595     int state;
0596 
0597     state = ucontrol->value.integer.value[0];
0598     if (get_switch_state(mixer, type) == state)
0599         return 0;
0600 
0601     set_switch_state(mixer, type, state);
0602     do_switch(atc, type, state);
0603 
0604     return 1;
0605 }
0606 
0607 static struct snd_kcontrol_new swh_ctl = {
0608     .access     = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0609     .iface      = SNDRV_CTL_ELEM_IFACE_MIXER,
0610     .info       = ct_alsa_mix_switch_info,
0611     .get        = ct_alsa_mix_switch_get,
0612     .put        = ct_alsa_mix_switch_put
0613 };
0614 
0615 static int ct_spdif_info(struct snd_kcontrol *kcontrol,
0616              struct snd_ctl_elem_info *uinfo)
0617 {
0618     uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
0619     uinfo->count = 1;
0620     return 0;
0621 }
0622 
0623 static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
0624                  struct snd_ctl_elem_value *ucontrol)
0625 {
0626     ucontrol->value.iec958.status[0] = 0xff;
0627     ucontrol->value.iec958.status[1] = 0xff;
0628     ucontrol->value.iec958.status[2] = 0xff;
0629     ucontrol->value.iec958.status[3] = 0xff;
0630     return 0;
0631 }
0632 
0633 static int ct_spdif_get(struct snd_kcontrol *kcontrol,
0634             struct snd_ctl_elem_value *ucontrol)
0635 {
0636     struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
0637     unsigned int status;
0638 
0639     atc->spdif_out_get_status(atc, &status);
0640 
0641     if (status == 0)
0642         status = SNDRV_PCM_DEFAULT_CON_SPDIF;
0643 
0644     ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
0645     ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
0646     ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
0647     ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
0648 
0649     return 0;
0650 }
0651 
0652 static int ct_spdif_put(struct snd_kcontrol *kcontrol,
0653             struct snd_ctl_elem_value *ucontrol)
0654 {
0655     struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
0656     int change;
0657     unsigned int status, old_status;
0658 
0659     status = (ucontrol->value.iec958.status[0] << 0) |
0660          (ucontrol->value.iec958.status[1] << 8) |
0661          (ucontrol->value.iec958.status[2] << 16) |
0662          (ucontrol->value.iec958.status[3] << 24);
0663 
0664     atc->spdif_out_get_status(atc, &old_status);
0665     change = (old_status != status);
0666     if (change)
0667         atc->spdif_out_set_status(atc, status);
0668 
0669     return change;
0670 }
0671 
0672 static struct snd_kcontrol_new iec958_mask_ctl = {
0673     .access     = SNDRV_CTL_ELEM_ACCESS_READ,
0674     .iface      = SNDRV_CTL_ELEM_IFACE_PCM,
0675     .name       = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
0676     .count      = 1,
0677     .info       = ct_spdif_info,
0678     .get        = ct_spdif_get_mask,
0679     .private_value  = MIXER_IEC958_MASK
0680 };
0681 
0682 static struct snd_kcontrol_new iec958_default_ctl = {
0683     .iface      = SNDRV_CTL_ELEM_IFACE_PCM,
0684     .name       = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
0685     .count      = 1,
0686     .info       = ct_spdif_info,
0687     .get        = ct_spdif_get,
0688     .put        = ct_spdif_put,
0689     .private_value  = MIXER_IEC958_DEFAULT
0690 };
0691 
0692 static struct snd_kcontrol_new iec958_ctl = {
0693     .access     = SNDRV_CTL_ELEM_ACCESS_READWRITE,
0694     .iface      = SNDRV_CTL_ELEM_IFACE_PCM,
0695     .name       = SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
0696     .count      = 1,
0697     .info       = ct_spdif_info,
0698     .get        = ct_spdif_get,
0699     .put        = ct_spdif_put,
0700     .private_value  = MIXER_IEC958_STREAM
0701 };
0702 
0703 #define NUM_IEC958_CTL 3
0704 
0705 static int
0706 ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
0707 {
0708     struct snd_kcontrol *kctl;
0709     int err;
0710 
0711     kctl = snd_ctl_new1(new, mixer->atc);
0712     if (!kctl)
0713         return -ENOMEM;
0714 
0715     if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface)
0716         kctl->id.device = IEC958;
0717 
0718     err = snd_ctl_add(mixer->atc->card, kctl);
0719     if (err)
0720         return err;
0721 
0722     switch (new->private_value) {
0723     case MIXER_LINEIN_C_S:
0724         kctls[0] = kctl; break;
0725     case MIXER_MIC_C_S:
0726         kctls[1] = kctl; break;
0727     default:
0728         break;
0729     }
0730 
0731     return 0;
0732 }
0733 
0734 static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
0735 {
0736     enum CTALSA_MIXER_CTL type;
0737     struct ct_atc *atc = mixer->atc;
0738     struct capabilities cap = atc->capabilities(atc);
0739     int err;
0740 
0741     /* Create snd kcontrol instances on demand */
0742     for (type = VOL_MIXER_START; type <= VOL_MIXER_END; type++) {
0743         if (ct_kcontrol_init_table[type].ctl) {
0744             vol_ctl.name = ct_kcontrol_init_table[type].name;
0745             vol_ctl.private_value = (unsigned long)type;
0746             err = ct_mixer_kcontrol_new(mixer, &vol_ctl);
0747             if (err)
0748                 return err;
0749         }
0750     }
0751 
0752     ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch;
0753 
0754     for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) {
0755         if (ct_kcontrol_init_table[type].ctl) {
0756             swh_ctl.name = ct_kcontrol_init_table[type].name;
0757             swh_ctl.private_value = (unsigned long)type;
0758             err = ct_mixer_kcontrol_new(mixer, &swh_ctl);
0759             if (err)
0760                 return err;
0761         }
0762     }
0763 
0764     err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl);
0765     if (err)
0766         return err;
0767 
0768     err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl);
0769     if (err)
0770         return err;
0771 
0772     err = ct_mixer_kcontrol_new(mixer, &iec958_ctl);
0773     if (err)
0774         return err;
0775 
0776     if (cap.output_switch) {
0777         err = ct_mixer_kcontrol_new(mixer, &output_ctl);
0778         if (err)
0779             return err;
0780     }
0781 
0782     if (cap.mic_source_switch) {
0783         err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl);
0784         if (err)
0785             return err;
0786     }
0787     atc->line_front_unmute(atc, 1);
0788     set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
0789     atc->line_surround_unmute(atc, 0);
0790     set_switch_state(mixer, MIXER_WAVES_P_S, 0);
0791     atc->line_clfe_unmute(atc, 0);
0792     set_switch_state(mixer, MIXER_WAVEC_P_S, 0);
0793     atc->line_rear_unmute(atc, 0);
0794     set_switch_state(mixer, MIXER_WAVER_P_S, 0);
0795     atc->spdif_out_unmute(atc, 0);
0796     set_switch_state(mixer, MIXER_SPDIFO_P_S, 0);
0797     atc->line_in_unmute(atc, 0);
0798     if (cap.dedicated_mic)
0799         atc->mic_unmute(atc, 0);
0800     atc->spdif_in_unmute(atc, 0);
0801     set_switch_state(mixer, MIXER_PCM_C_S, 0);
0802     set_switch_state(mixer, MIXER_LINEIN_C_S, 0);
0803     set_switch_state(mixer, MIXER_SPDIFI_C_S, 0);
0804 
0805     return 0;
0806 }
0807 
0808 static void
0809 ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
0810 {
0811     struct amixer *amix_d;
0812     struct sum *sum_c;
0813     int i;
0814 
0815     for (i = 0; i < 2; i++) {
0816         amix_d = mixer->amixers[type*CHN_NUM+i];
0817         sum_c = mixer->sums[SUM_IN_F_C*CHN_NUM+i];
0818         amix_d->ops->set_sum(amix_d, sum_c);
0819         amix_d->ops->commit_write(amix_d);
0820     }
0821 }
0822 
0823 static void
0824 ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
0825 {
0826     struct amixer *amix_d;
0827     int i;
0828 
0829     for (i = 0; i < 2; i++) {
0830         amix_d = mixer->amixers[type*CHN_NUM+i];
0831         amix_d->ops->set_sum(amix_d, NULL);
0832         amix_d->ops->commit_write(amix_d);
0833     }
0834 }
0835 
0836 static int ct_mixer_get_resources(struct ct_mixer *mixer)
0837 {
0838     struct sum_mgr *sum_mgr;
0839     struct sum *sum;
0840     struct sum_desc sum_desc = {0};
0841     struct amixer_mgr *amixer_mgr;
0842     struct amixer *amixer;
0843     struct amixer_desc am_desc = {0};
0844     int err;
0845     int i;
0846 
0847     /* Allocate sum resources for mixer obj */
0848     sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
0849     sum_desc.msr = mixer->atc->msr;
0850     for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
0851         err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum);
0852         if (err) {
0853             dev_err(mixer->atc->card->dev,
0854                 "Failed to get sum resources for front output!\n");
0855             break;
0856         }
0857         mixer->sums[i] = sum;
0858     }
0859     if (err)
0860         goto error1;
0861 
0862     /* Allocate amixer resources for mixer obj */
0863     amixer_mgr = (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
0864     am_desc.msr = mixer->atc->msr;
0865     for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
0866         err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer);
0867         if (err) {
0868             dev_err(mixer->atc->card->dev,
0869                 "Failed to get amixer resources for mixer obj!\n");
0870             break;
0871         }
0872         mixer->amixers[i] = amixer;
0873     }
0874     if (err)
0875         goto error2;
0876 
0877     return 0;
0878 
0879 error2:
0880     for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
0881         if (NULL != mixer->amixers[i]) {
0882             amixer = mixer->amixers[i];
0883             amixer_mgr->put_amixer(amixer_mgr, amixer);
0884             mixer->amixers[i] = NULL;
0885         }
0886     }
0887 error1:
0888     for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
0889         if (NULL != mixer->sums[i]) {
0890             sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
0891             mixer->sums[i] = NULL;
0892         }
0893     }
0894 
0895     return err;
0896 }
0897 
0898 static int ct_mixer_get_mem(struct ct_mixer **rmixer)
0899 {
0900     struct ct_mixer *mixer;
0901     int err;
0902 
0903     *rmixer = NULL;
0904     /* Allocate mem for mixer obj */
0905     mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
0906     if (!mixer)
0907         return -ENOMEM;
0908 
0909     mixer->amixers = kcalloc(NUM_CT_AMIXERS * CHN_NUM, sizeof(void *),
0910                  GFP_KERNEL);
0911     if (!mixer->amixers) {
0912         err = -ENOMEM;
0913         goto error1;
0914     }
0915     mixer->sums = kcalloc(NUM_CT_SUMS * CHN_NUM, sizeof(void *),
0916                   GFP_KERNEL);
0917     if (!mixer->sums) {
0918         err = -ENOMEM;
0919         goto error2;
0920     }
0921 
0922     *rmixer = mixer;
0923     return 0;
0924 
0925 error2:
0926     kfree(mixer->amixers);
0927 error1:
0928     kfree(mixer);
0929     return err;
0930 }
0931 
0932 static int ct_mixer_topology_build(struct ct_mixer *mixer)
0933 {
0934     struct sum *sum;
0935     struct amixer *amix_d, *amix_s;
0936     enum CT_AMIXER_CTL i, j;
0937     enum CT_SUM_CTL k;
0938 
0939     /* Build topology from destination to source */
0940 
0941     /* Set up Master mixer */
0942     for (i = AMIXER_MASTER_F, k = SUM_IN_F;
0943                     i <= AMIXER_MASTER_S; i++, k++) {
0944         amix_d = mixer->amixers[i*CHN_NUM];
0945         sum = mixer->sums[k*CHN_NUM];
0946         amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
0947         amix_d = mixer->amixers[i*CHN_NUM+1];
0948         sum = mixer->sums[k*CHN_NUM+1];
0949         amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
0950     }
0951 
0952     /* Set up Wave-out mixer */
0953     for (i = AMIXER_WAVE_F, j = AMIXER_MASTER_F;
0954                     i <= AMIXER_WAVE_S; i++, j++) {
0955         amix_d = mixer->amixers[i*CHN_NUM];
0956         amix_s = mixer->amixers[j*CHN_NUM];
0957         amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
0958         amix_d = mixer->amixers[i*CHN_NUM+1];
0959         amix_s = mixer->amixers[j*CHN_NUM+1];
0960         amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
0961     }
0962 
0963     /* Set up S/PDIF-out mixer */
0964     amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM];
0965     amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM];
0966     amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
0967     amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM+1];
0968     amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM+1];
0969     amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
0970 
0971     /* Set up PCM-in mixer */
0972     for (i = AMIXER_PCM_F, k = SUM_IN_F; i <= AMIXER_PCM_S; i++, k++) {
0973         amix_d = mixer->amixers[i*CHN_NUM];
0974         sum = mixer->sums[k*CHN_NUM];
0975         amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
0976         amix_d = mixer->amixers[i*CHN_NUM+1];
0977         sum = mixer->sums[k*CHN_NUM+1];
0978         amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
0979     }
0980 
0981     /* Set up Line-in mixer */
0982     amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM];
0983     sum = mixer->sums[SUM_IN_F*CHN_NUM];
0984     amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
0985     amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM+1];
0986     sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
0987     amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
0988 
0989     /* Set up Mic-in mixer */
0990     amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM];
0991     sum = mixer->sums[SUM_IN_F*CHN_NUM];
0992     amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
0993     amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM+1];
0994     sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
0995     amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
0996 
0997     /* Set up S/PDIF-in mixer */
0998     amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM];
0999     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);
1004 
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);
1012 
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);
1020 
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);
1028 
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);
1036 
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);
1044 
1045     return 0;
1046 }
1047 
1048 static int mixer_set_input_port(struct amixer *amixer, struct rsc *rsc)
1049 {
1050     amixer->ops->set_input(amixer, rsc);
1051     amixer->ops->commit_write(amixer);
1052 
1053     return 0;
1054 }
1055 
1056 static enum CT_AMIXER_CTL port_to_amixer(enum MIXER_PORT_T type)
1057 {
1058     switch (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;
1072     default:        return 0;
1073     }
1074 }
1075 
1076 static int mixer_get_output_ports(struct ct_mixer *mixer,
1077                   enum MIXER_PORT_T type,
1078                   struct rsc **rleft, struct rsc **rright)
1079 {
1080     enum CT_AMIXER_CTL amix = port_to_amixer(type);
1081 
1082     if (NULL != rleft)
1083         *rleft = &((struct amixer *)mixer->amixers[amix*CHN_NUM])->rsc;
1084 
1085     if (NULL != rright)
1086         *rright =
1087             &((struct amixer *)mixer->amixers[amix*CHN_NUM+1])->rsc;
1088 
1089     return 0;
1090 }
1091 
1092 static int mixer_set_input_left(struct ct_mixer *mixer,
1093                 enum MIXER_PORT_T type, struct rsc *rsc)
1094 {
1095     enum CT_AMIXER_CTL amix = port_to_amixer(type);
1096 
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);
1101 
1102     return 0;
1103 }
1104 
1105 static int
1106 mixer_set_input_right(struct ct_mixer *mixer,
1107               enum MIXER_PORT_T type, struct rsc *rsc)
1108 {
1109     enum CT_AMIXER_CTL amix = port_to_amixer(type);
1110 
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);
1115 
1116     return 0;
1117 }
1118 
1119 #ifdef CONFIG_PM_SLEEP
1120 static int mixer_resume(struct ct_mixer *mixer)
1121 {
1122     int i, state;
1123     struct amixer *amixer;
1124 
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);
1129     }
1130 
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);
1135     }
1136 
1137     return 0;
1138 }
1139 #endif
1140 
1141 int ct_mixer_destroy(struct ct_mixer *mixer)
1142 {
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;
1147     int i = 0;
1148 
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);
1154         }
1155     }
1156 
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]);
1161     }
1162 
1163     /* Release mem assigned to mixer object */
1164     kfree(mixer->sums);
1165     kfree(mixer->amixers);
1166     kfree(mixer);
1167 
1168     return 0;
1169 }
1170 
1171 int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer)
1172 {
1173     struct ct_mixer *mixer;
1174     int err;
1175 
1176     *rmixer = NULL;
1177 
1178     /* Allocate mem for mixer obj */
1179     err = ct_mixer_get_mem(&mixer);
1180     if (err)
1181         return err;
1182 
1183     mixer->switch_state = 0;
1184     mixer->atc = atc;
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;
1191 #endif
1192 
1193     /* Allocate chip resources for mixer obj */
1194     err = ct_mixer_get_resources(mixer);
1195     if (err)
1196         goto error;
1197 
1198     /* Build internal mixer topology */
1199     ct_mixer_topology_build(mixer);
1200 
1201     *rmixer = mixer;
1202 
1203     return 0;
1204 
1205 error:
1206     ct_mixer_destroy(mixer);
1207     return err;
1208 }
1209 
1210 int ct_alsa_mix_create(struct ct_atc *atc,
1211                enum CTALSADEVS device,
1212                const char *device_name)
1213 {
1214     int err;
1215 
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);
1219     if (err)
1220         return err;
1221 
1222     strcpy(atc->card->mixername, device_name);
1223 
1224     return 0;
1225 }