cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ctmixer.c (30599B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
      4 *
      5 * @File	ctmixer.c
      6 *
      7 * @Brief
      8 * This file contains the implementation of alsa mixer device functions.
      9 *
     10 * @Author	Liu Chun
     11 * @Date 	May 28 2008
     12 */
     13
     14
     15#include "ctmixer.h"
     16#include "ctamixer.h"
     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>
     23
     24enum CT_SUM_CTL {
     25	SUM_IN_F,
     26	SUM_IN_R,
     27	SUM_IN_C,
     28	SUM_IN_S,
     29	SUM_IN_F_C,
     30
     31	NUM_CT_SUMS
     32};
     33
     34enum CT_AMIXER_CTL {
     35	/* volume control mixers */
     36	AMIXER_MASTER_F,
     37	AMIXER_MASTER_R,
     38	AMIXER_MASTER_C,
     39	AMIXER_MASTER_S,
     40	AMIXER_PCM_F,
     41	AMIXER_PCM_R,
     42	AMIXER_PCM_C,
     43	AMIXER_PCM_S,
     44	AMIXER_SPDIFI,
     45	AMIXER_LINEIN,
     46	AMIXER_MIC,
     47	AMIXER_SPDIFO,
     48	AMIXER_WAVE_F,
     49	AMIXER_WAVE_R,
     50	AMIXER_WAVE_C,
     51	AMIXER_WAVE_S,
     52	AMIXER_MASTER_F_C,
     53	AMIXER_PCM_F_C,
     54	AMIXER_SPDIFI_C,
     55	AMIXER_LINEIN_C,
     56	AMIXER_MIC_C,
     57
     58	/* this should always be the last one */
     59	NUM_CT_AMIXERS
     60};
     61
     62enum CTALSA_MIXER_CTL {
     63	/* volume control mixers */
     64	MIXER_MASTER_P,
     65	MIXER_PCM_P,
     66	MIXER_LINEIN_P,
     67	MIXER_MIC_P,
     68	MIXER_SPDIFI_P,
     69	MIXER_SPDIFO_P,
     70	MIXER_WAVEF_P,
     71	MIXER_WAVER_P,
     72	MIXER_WAVEC_P,
     73	MIXER_WAVES_P,
     74	MIXER_MASTER_C,
     75	MIXER_PCM_C,
     76	MIXER_LINEIN_C,
     77	MIXER_MIC_C,
     78	MIXER_SPDIFI_C,
     79
     80	/* switch control mixers */
     81	MIXER_PCM_C_S,
     82	MIXER_LINEIN_C_S,
     83	MIXER_MIC_C_S,
     84	MIXER_SPDIFI_C_S,
     85	MIXER_SPDIFO_P_S,
     86	MIXER_WAVEF_P_S,
     87	MIXER_WAVER_P_S,
     88	MIXER_WAVEC_P_S,
     89	MIXER_WAVES_P_S,
     90	MIXER_DIGITAL_IO_S,
     91	MIXER_IEC958_MASK,
     92	MIXER_IEC958_DEFAULT,
     93	MIXER_IEC958_STREAM,
     94
     95	/* this should always be the last one */
     96	NUM_CTALSA_MIXERS
     97};
     98
     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
    106
    107#define CHN_NUM		2
    108
    109struct ct_kcontrol_init {
    110	unsigned char ctl;
    111	char *name;
    112};
    113
    114static struct ct_kcontrol_init
    115ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
    116	[MIXER_MASTER_P] = {
    117		.ctl = 1,
    118		.name = "Master Playback Volume",
    119	},
    120	[MIXER_MASTER_C] = {
    121		.ctl = 1,
    122		.name = "Master Capture Volume",
    123	},
    124	[MIXER_PCM_P] = {
    125		.ctl = 1,
    126		.name = "PCM Playback Volume",
    127	},
    128	[MIXER_PCM_C] = {
    129		.ctl = 1,
    130		.name = "PCM Capture Volume",
    131	},
    132	[MIXER_LINEIN_P] = {
    133		.ctl = 1,
    134		.name = "Line Playback Volume",
    135	},
    136	[MIXER_LINEIN_C] = {
    137		.ctl = 1,
    138		.name = "Line Capture Volume",
    139	},
    140	[MIXER_MIC_P] = {
    141		.ctl = 1,
    142		.name = "Mic Playback Volume",
    143	},
    144	[MIXER_MIC_C] = {
    145		.ctl = 1,
    146		.name = "Mic Capture Volume",
    147	},
    148	[MIXER_SPDIFI_P] = {
    149		.ctl = 1,
    150		.name = "IEC958 Playback Volume",
    151	},
    152	[MIXER_SPDIFI_C] = {
    153		.ctl = 1,
    154		.name = "IEC958 Capture Volume",
    155	},
    156	[MIXER_SPDIFO_P] = {
    157		.ctl = 1,
    158		.name = "Digital Playback Volume",
    159	},
    160	[MIXER_WAVEF_P] = {
    161		.ctl = 1,
    162		.name = "Front Playback Volume",
    163	},
    164	[MIXER_WAVES_P] = {
    165		.ctl = 1,
    166		.name = "Side Playback Volume",
    167	},
    168	[MIXER_WAVEC_P] = {
    169		.ctl = 1,
    170		.name = "Center/LFE Playback Volume",
    171	},
    172	[MIXER_WAVER_P] = {
    173		.ctl = 1,
    174		.name = "Surround Playback Volume",
    175	},
    176	[MIXER_PCM_C_S] = {
    177		.ctl = 1,
    178		.name = "PCM Capture Switch",
    179	},
    180	[MIXER_LINEIN_C_S] = {
    181		.ctl = 1,
    182		.name = "Line Capture Switch",
    183	},
    184	[MIXER_MIC_C_S] = {
    185		.ctl = 1,
    186		.name = "Mic Capture Switch",
    187	},
    188	[MIXER_SPDIFI_C_S] = {
    189		.ctl = 1,
    190		.name = "IEC958 Capture Switch",
    191	},
    192	[MIXER_SPDIFO_P_S] = {
    193		.ctl = 1,
    194		.name = "Digital Playback Switch",
    195	},
    196	[MIXER_WAVEF_P_S] = {
    197		.ctl = 1,
    198		.name = "Front Playback Switch",
    199	},
    200	[MIXER_WAVES_P_S] = {
    201		.ctl = 1,
    202		.name = "Side Playback Switch",
    203	},
    204	[MIXER_WAVEC_P_S] = {
    205		.ctl = 1,
    206		.name = "Center/LFE Playback Switch",
    207	},
    208	[MIXER_WAVER_P_S] = {
    209		.ctl = 1,
    210		.name = "Surround Playback Switch",
    211	},
    212	[MIXER_DIGITAL_IO_S] = {
    213		.ctl = 0,
    214		.name = "Digit-IO Playback Switch",
    215	},
    216};
    217
    218static void
    219ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
    220
    221static void
    222ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
    223
    224/* FIXME: this static looks like it would fail if more than one card was */
    225/* installed. */
    226static struct snd_kcontrol *kctls[2] = {NULL};
    227
    228static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
    229{
    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;
    234	case MIXER_PCM_C:
    235	case MIXER_PCM_C_S:	return AMIXER_PCM_F_C;
    236	case MIXER_LINEIN_P:	return AMIXER_LINEIN;
    237	case MIXER_LINEIN_C:
    238	case MIXER_LINEIN_C_S:	return AMIXER_LINEIN_C;
    239	case MIXER_MIC_P:	return AMIXER_MIC;
    240	case MIXER_MIC_C:
    241	case MIXER_MIC_C_S:	return AMIXER_MIC_C;
    242	case MIXER_SPDIFI_P:	return AMIXER_SPDIFI;
    243	case MIXER_SPDIFI_C:
    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;
    251	}
    252}
    253
    254static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index)
    255{
    256	switch (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;
    263	}
    264}
    265
    266static unsigned char
    267get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type)
    268{
    269	return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START)))
    270		? 1 : 0;
    271}
    272
    273static void
    274set_switch_state(struct ct_mixer *mixer,
    275		 enum CTALSA_MIXER_CTL type, unsigned char state)
    276{
    277	if (state)
    278		mixer->switch_state |= (0x1 << (type - SWH_MIXER_START));
    279	else
    280		mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
    281}
    282
    283#if 0 /* not used */
    284/* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
    285 * from 2^-6 to (1+1023/1024) */
    286static unsigned int uint16_to_float14(unsigned int x)
    287{
    288	unsigned int i;
    289
    290	if (x < 17)
    291		return 0;
    292
    293	x *= 2031;
    294	x /= 65535;
    295	x += 16;
    296
    297	/* i <= 6 */
    298	for (i = 0; !(x & 0x400); i++)
    299		x <<= 1;
    300
    301	x = (((7 - i) & 0x7) << 10) | (x & 0x3ff);
    302
    303	return x;
    304}
    305
    306static unsigned int float14_to_uint16(unsigned int x)
    307{
    308	unsigned int e;
    309
    310	if (!x)
    311		return x;
    312
    313	e = (x >> 10) & 0x7;
    314	x &= 0x3ff;
    315	x += 1024;
    316	x >>= (7 - e);
    317	x -= 16;
    318	x *= 65535;
    319	x /= 2031;
    320
    321	return x;
    322}
    323#endif /* not used */
    324
    325#define VOL_SCALE	0x1c
    326#define VOL_MAX		0x100
    327
    328static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1);
    329
    330static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
    331				   struct snd_ctl_elem_info *uinfo)
    332{
    333	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
    334	uinfo->count = 2;
    335	uinfo->value.integer.min = 0;
    336	uinfo->value.integer.max = VOL_MAX;
    337
    338	return 0;
    339}
    340
    341static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
    342				  struct snd_ctl_elem_value *ucontrol)
    343{
    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;
    347	int i, val;
    348
    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;
    353		if (val < 0)
    354			val = 0;
    355		else if (val > VOL_MAX)
    356			val = VOL_MAX;
    357		ucontrol->value.integer.value[i] = val;
    358	}
    359
    360	return 0;
    361}
    362
    363static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
    364				  struct snd_ctl_elem_value *ucontrol)
    365{
    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;
    371
    372	for (i = 0; i < 2; i++) {
    373		val = ucontrol->value.integer.value[i];
    374		if (val < 0)
    375			val = 0;
    376		else if (val > VOL_MAX)
    377			val = VOL_MAX;
    378		val *= VOL_SCALE;
    379		amixer = mixer->amixers[type*CHN_NUM+i];
    380		oval = amixer->ops->get_scale(amixer);
    381		if (val != oval) {
    382			amixer->ops->set_scale(amixer, val);
    383			amixer->ops->commit_write(amixer);
    384			change = 1;
    385			/* Synchronize Master/PCM playback AMIXERs. */
    386			if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) {
    387				for (j = 1; j < 4; j++) {
    388					amixer = mixer->
    389						amixers[(type+j)*CHN_NUM+i];
    390					amixer->ops->set_scale(amixer, val);
    391					amixer->ops->commit_write(amixer);
    392				}
    393			}
    394		}
    395	}
    396
    397	return change;
    398}
    399
    400static 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 },
    408};
    409
    410static int output_switch_info(struct snd_kcontrol *kcontrol,
    411			      struct snd_ctl_elem_info *info)
    412{
    413	static const char *const names[3] = {
    414	  "FP Headphones", "Headphones", "Speakers"
    415	};
    416
    417	return snd_ctl_enum_info(info, 1, 3, names);
    418}
    419
    420static int output_switch_get(struct snd_kcontrol *kcontrol,
    421			     struct snd_ctl_elem_value *ucontrol)
    422{
    423	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
    424	ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc);
    425	return 0;
    426}
    427
    428static int output_switch_put(struct snd_kcontrol *kcontrol,
    429			     struct snd_ctl_elem_value *ucontrol)
    430{
    431	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
    432	if (ucontrol->value.enumerated.item[0] > 2)
    433		return -EINVAL;
    434	return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]);
    435}
    436
    437static 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,
    443};
    444
    445static int mic_source_switch_info(struct snd_kcontrol *kcontrol,
    446			      struct snd_ctl_elem_info *info)
    447{
    448	static const char *const names[3] = {
    449	  "Mic", "FP Mic", "Aux"
    450	};
    451
    452	return snd_ctl_enum_info(info, 1, 3, names);
    453}
    454
    455static int mic_source_switch_get(struct snd_kcontrol *kcontrol,
    456			     struct snd_ctl_elem_value *ucontrol)
    457{
    458	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
    459	ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc);
    460	return 0;
    461}
    462
    463static int mic_source_switch_put(struct snd_kcontrol *kcontrol,
    464			     struct snd_ctl_elem_value *ucontrol)
    465{
    466	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
    467	if (ucontrol->value.enumerated.item[0] > 2)
    468		return -EINVAL;
    469	return atc->mic_source_switch_put(atc,
    470					ucontrol->value.enumerated.item[0]);
    471}
    472
    473static 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,
    479};
    480
    481static void
    482do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
    483{
    484
    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,
    489							&kctls[1]->id);
    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,
    494							&kctls[0]->id);
    495	}
    496}
    497
    498static void
    499do_digit_io_switch(struct ct_atc *atc, int state)
    500{
    501	struct ct_mixer *mixer = atc->mixer;
    502
    503	if (state) {
    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);
    509		return;
    510	}
    511
    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);
    516
    517	atc->spdif_out_unmute(atc, 0);
    518	atc->spdif_in_unmute(atc, 0);
    519	atc->line_in_unmute(atc, 1);
    520	return;
    521}
    522
    523static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
    524{
    525	struct ct_mixer *mixer = atc->mixer;
    526	struct capabilities cap = atc->capabilities(atc);
    527
    528	/* Do changes in mixer. */
    529	if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
    530		if (state) {
    531			ct_mixer_recording_select(mixer,
    532						  get_amixer_index(type));
    533		} else {
    534			ct_mixer_recording_unselect(mixer,
    535						    get_amixer_index(type));
    536		}
    537	}
    538	/* Do changes out of mixer. */
    539	if (!cap.dedicated_mic &&
    540	    (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) {
    541		if (state)
    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);
    562
    563	return;
    564}
    565
    566static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol,
    567				   struct snd_ctl_elem_info *uinfo)
    568{
    569	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
    570	uinfo->count = 1;
    571	uinfo->value.integer.min = 0;
    572	uinfo->value.integer.max = 1;
    573	uinfo->value.integer.step = 1;
    574
    575	return 0;
    576}
    577
    578static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol,
    579				  struct snd_ctl_elem_value *ucontrol)
    580{
    581	struct ct_mixer *mixer =
    582		((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer;
    583	enum CTALSA_MIXER_CTL type = kcontrol->private_value;
    584
    585	ucontrol->value.integer.value[0] = get_switch_state(mixer, type);
    586	return 0;
    587}
    588
    589static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol,
    590				  struct snd_ctl_elem_value *ucontrol)
    591{
    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;
    595	int state;
    596
    597	state = ucontrol->value.integer.value[0];
    598	if (get_switch_state(mixer, type) == state)
    599		return 0;
    600
    601	set_switch_state(mixer, type, state);
    602	do_switch(atc, type, state);
    603
    604	return 1;
    605}
    606
    607static 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
    613};
    614
    615static int ct_spdif_info(struct snd_kcontrol *kcontrol,
    616			 struct snd_ctl_elem_info *uinfo)
    617{
    618	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
    619	uinfo->count = 1;
    620	return 0;
    621}
    622
    623static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
    624			     struct snd_ctl_elem_value *ucontrol)
    625{
    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;
    630	return 0;
    631}
    632
    633static int ct_spdif_get(struct snd_kcontrol *kcontrol,
    634			struct snd_ctl_elem_value *ucontrol)
    635{
    636	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
    637	unsigned int status;
    638
    639	atc->spdif_out_get_status(atc, &status);
    640
    641	if (status == 0)
    642		status = SNDRV_PCM_DEFAULT_CON_SPDIF;
    643
    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;
    648
    649	return 0;
    650}
    651
    652static int ct_spdif_put(struct snd_kcontrol *kcontrol,
    653			struct snd_ctl_elem_value *ucontrol)
    654{
    655	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
    656	int change;
    657	unsigned int status, old_status;
    658
    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);
    663
    664	atc->spdif_out_get_status(atc, &old_status);
    665	change = (old_status != status);
    666	if (change)
    667		atc->spdif_out_set_status(atc, status);
    668
    669	return change;
    670}
    671
    672static 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),
    676	.count		= 1,
    677	.info		= ct_spdif_info,
    678	.get		= ct_spdif_get_mask,
    679	.private_value	= MIXER_IEC958_MASK
    680};
    681
    682static struct snd_kcontrol_new iec958_default_ctl = {
    683	.iface		= SNDRV_CTL_ELEM_IFACE_PCM,
    684	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
    685	.count		= 1,
    686	.info		= ct_spdif_info,
    687	.get		= ct_spdif_get,
    688	.put		= ct_spdif_put,
    689	.private_value	= MIXER_IEC958_DEFAULT
    690};
    691
    692static 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),
    696	.count		= 1,
    697	.info		= ct_spdif_info,
    698	.get		= ct_spdif_get,
    699	.put		= ct_spdif_put,
    700	.private_value	= MIXER_IEC958_STREAM
    701};
    702
    703#define NUM_IEC958_CTL 3
    704
    705static int
    706ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
    707{
    708	struct snd_kcontrol *kctl;
    709	int err;
    710
    711	kctl = snd_ctl_new1(new, mixer->atc);
    712	if (!kctl)
    713		return -ENOMEM;
    714
    715	if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface)
    716		kctl->id.device = IEC958;
    717
    718	err = snd_ctl_add(mixer->atc->card, kctl);
    719	if (err)
    720		return err;
    721
    722	switch (new->private_value) {
    723	case MIXER_LINEIN_C_S:
    724		kctls[0] = kctl; break;
    725	case MIXER_MIC_C_S:
    726		kctls[1] = kctl; break;
    727	default:
    728		break;
    729	}
    730
    731	return 0;
    732}
    733
    734static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
    735{
    736	enum CTALSA_MIXER_CTL type;
    737	struct ct_atc *atc = mixer->atc;
    738	struct capabilities cap = atc->capabilities(atc);
    739	int err;
    740
    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);
    747			if (err)
    748				return err;
    749		}
    750	}
    751
    752	ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch;
    753
    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);
    759			if (err)
    760				return err;
    761		}
    762	}
    763
    764	err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl);
    765	if (err)
    766		return err;
    767
    768	err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl);
    769	if (err)
    770		return err;
    771
    772	err = ct_mixer_kcontrol_new(mixer, &iec958_ctl);
    773	if (err)
    774		return err;
    775
    776	if (cap.output_switch) {
    777		err = ct_mixer_kcontrol_new(mixer, &output_ctl);
    778		if (err)
    779			return err;
    780	}
    781
    782	if (cap.mic_source_switch) {
    783		err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl);
    784		if (err)
    785			return err;
    786	}
    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);
    804
    805	return 0;
    806}
    807
    808static void
    809ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
    810{
    811	struct amixer *amix_d;
    812	struct sum *sum_c;
    813	int i;
    814
    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);
    820	}
    821}
    822
    823static void
    824ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
    825{
    826	struct amixer *amix_d;
    827	int i;
    828
    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);
    833	}
    834}
    835
    836static int ct_mixer_get_resources(struct ct_mixer *mixer)
    837{
    838	struct sum_mgr *sum_mgr;
    839	struct sum *sum;
    840	struct sum_desc sum_desc = {0};
    841	struct amixer_mgr *amixer_mgr;
    842	struct amixer *amixer;
    843	struct amixer_desc am_desc = {0};
    844	int err;
    845	int i;
    846
    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);
    852		if (err) {
    853			dev_err(mixer->atc->card->dev,
    854				"Failed to get sum resources for front output!\n");
    855			break;
    856		}
    857		mixer->sums[i] = sum;
    858	}
    859	if (err)
    860		goto error1;
    861
    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);
    867		if (err) {
    868			dev_err(mixer->atc->card->dev,
    869				"Failed to get amixer resources for mixer obj!\n");
    870			break;
    871		}
    872		mixer->amixers[i] = amixer;
    873	}
    874	if (err)
    875		goto error2;
    876
    877	return 0;
    878
    879error2:
    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;
    885		}
    886	}
    887error1:
    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;
    892		}
    893	}
    894
    895	return err;
    896}
    897
    898static int ct_mixer_get_mem(struct ct_mixer **rmixer)
    899{
    900	struct ct_mixer *mixer;
    901	int err;
    902
    903	*rmixer = NULL;
    904	/* Allocate mem for mixer obj */
    905	mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
    906	if (!mixer)
    907		return -ENOMEM;
    908
    909	mixer->amixers = kcalloc(NUM_CT_AMIXERS * CHN_NUM, sizeof(void *),
    910				 GFP_KERNEL);
    911	if (!mixer->amixers) {
    912		err = -ENOMEM;
    913		goto error1;
    914	}
    915	mixer->sums = kcalloc(NUM_CT_SUMS * CHN_NUM, sizeof(void *),
    916			      GFP_KERNEL);
    917	if (!mixer->sums) {
    918		err = -ENOMEM;
    919		goto error2;
    920	}
    921
    922	*rmixer = mixer;
    923	return 0;
    924
    925error2:
    926	kfree(mixer->amixers);
    927error1:
    928	kfree(mixer);
    929	return err;
    930}
    931
    932static int ct_mixer_topology_build(struct ct_mixer *mixer)
    933{
    934	struct sum *sum;
    935	struct amixer *amix_d, *amix_s;
    936	enum CT_AMIXER_CTL i, j;
    937	enum CT_SUM_CTL k;
    938
    939	/* Build topology from destination to source */
    940
    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);
    950	}
    951
    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);
    961	}
    962
    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);
    970
    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);
    979	}
    980
    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);
    988
    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);
    996
    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);
   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
   1048static 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
   1056static 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
   1076static 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
   1092static 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
   1105static int
   1106mixer_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
   1120static 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
   1141int 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
   1171int 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
   1205error:
   1206	ct_mixer_destroy(mixer);
   1207	return err;
   1208}
   1209
   1210int 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}