xref: /linux/sound/pci/ctxfi/ctmixer.c (revision 9611c0ce215a66770ccbe5c126bf57ba8c31bcad)
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 
24 enum 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 
34 enum 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 
62 enum 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 
109 struct ct_kcontrol_init {
110 	unsigned char ctl;
111 	char *name;
112 };
113 
114 static struct ct_kcontrol_init
115 ct_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 
218 static void
219 ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
220 
221 static void
222 ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
223 
224 static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
225 {
226 	switch (alsa_index) {
227 	case MIXER_MASTER_P:	return AMIXER_MASTER_F;
228 	case MIXER_MASTER_C:	return AMIXER_MASTER_F_C;
229 	case MIXER_PCM_P:	return AMIXER_PCM_F;
230 	case MIXER_PCM_C:
231 	case MIXER_PCM_C_S:	return AMIXER_PCM_F_C;
232 	case MIXER_LINEIN_P:	return AMIXER_LINEIN;
233 	case MIXER_LINEIN_C:
234 	case MIXER_LINEIN_C_S:	return AMIXER_LINEIN_C;
235 	case MIXER_MIC_P:	return AMIXER_MIC;
236 	case MIXER_MIC_C:
237 	case MIXER_MIC_C_S:	return AMIXER_MIC_C;
238 	case MIXER_SPDIFI_P:	return AMIXER_SPDIFI;
239 	case MIXER_SPDIFI_C:
240 	case MIXER_SPDIFI_C_S:	return AMIXER_SPDIFI_C;
241 	case MIXER_SPDIFO_P:	return AMIXER_SPDIFO;
242 	case MIXER_WAVEF_P:	return AMIXER_WAVE_F;
243 	case MIXER_WAVES_P:	return AMIXER_WAVE_S;
244 	case MIXER_WAVEC_P:	return AMIXER_WAVE_C;
245 	case MIXER_WAVER_P:	return AMIXER_WAVE_R;
246 	default:		return NUM_CT_AMIXERS;
247 	}
248 }
249 
250 static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index)
251 {
252 	switch (index) {
253 	case AMIXER_MASTER_F:	return AMIXER_MASTER_F_C;
254 	case AMIXER_PCM_F:	return AMIXER_PCM_F_C;
255 	case AMIXER_SPDIFI:	return AMIXER_SPDIFI_C;
256 	case AMIXER_LINEIN:	return AMIXER_LINEIN_C;
257 	case AMIXER_MIC:	return AMIXER_MIC_C;
258 	default:		return NUM_CT_AMIXERS;
259 	}
260 }
261 
262 static unsigned char
263 get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type)
264 {
265 	return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START)))
266 		? 1 : 0;
267 }
268 
269 static void
270 set_switch_state(struct ct_mixer *mixer,
271 		 enum CTALSA_MIXER_CTL type, unsigned char state)
272 {
273 	if (state)
274 		mixer->switch_state |= (0x1 << (type - SWH_MIXER_START));
275 	else
276 		mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
277 }
278 
279 #if 0 /* not used */
280 /* Map integer value ranging from 0 to 65535 to 14-bit float value ranging
281  * from 2^-6 to (1+1023/1024) */
282 static unsigned int uint16_to_float14(unsigned int x)
283 {
284 	unsigned int i;
285 
286 	if (x < 17)
287 		return 0;
288 
289 	x *= 2031;
290 	x /= 65535;
291 	x += 16;
292 
293 	/* i <= 6 */
294 	for (i = 0; !(x & 0x400); i++)
295 		x <<= 1;
296 
297 	x = (((7 - i) & 0x7) << 10) | (x & 0x3ff);
298 
299 	return x;
300 }
301 
302 static unsigned int float14_to_uint16(unsigned int x)
303 {
304 	unsigned int e;
305 
306 	if (!x)
307 		return x;
308 
309 	e = (x >> 10) & 0x7;
310 	x &= 0x3ff;
311 	x += 1024;
312 	x >>= (7 - e);
313 	x -= 16;
314 	x *= 65535;
315 	x /= 2031;
316 
317 	return x;
318 }
319 #endif /* not used */
320 
321 #define VOL_SCALE	0x1c
322 #define VOL_MAX		0x100
323 
324 static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1);
325 
326 static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
327 				   struct snd_ctl_elem_info *uinfo)
328 {
329 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
330 	uinfo->count = 2;
331 	uinfo->value.integer.min = 0;
332 	uinfo->value.integer.max = VOL_MAX;
333 
334 	return 0;
335 }
336 
337 static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
338 				  struct snd_ctl_elem_value *ucontrol)
339 {
340 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
341 	enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
342 	struct amixer *amixer;
343 	int i, val;
344 
345 	for (i = 0; i < 2; i++) {
346 		amixer = ((struct ct_mixer *)atc->mixer)->
347 						amixers[type*CHN_NUM+i];
348 		val = amixer->ops->get_scale(amixer) / VOL_SCALE;
349 		if (val < 0)
350 			val = 0;
351 		else if (val > VOL_MAX)
352 			val = VOL_MAX;
353 		ucontrol->value.integer.value[i] = val;
354 	}
355 
356 	return 0;
357 }
358 
359 static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
360 				  struct snd_ctl_elem_value *ucontrol)
361 {
362 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
363 	struct ct_mixer *mixer = atc->mixer;
364 	enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
365 	struct amixer *amixer;
366 	int i, j, val, oval, change = 0;
367 
368 	for (i = 0; i < 2; i++) {
369 		val = ucontrol->value.integer.value[i];
370 		if (val < 0)
371 			val = 0;
372 		else if (val > VOL_MAX)
373 			val = VOL_MAX;
374 		val *= VOL_SCALE;
375 		amixer = mixer->amixers[type*CHN_NUM+i];
376 		oval = amixer->ops->get_scale(amixer);
377 		if (val != oval) {
378 			amixer->ops->set_scale(amixer, val);
379 			amixer->ops->commit_write(amixer);
380 			change = 1;
381 			/* Synchronize Master/PCM playback AMIXERs. */
382 			if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) {
383 				for (j = 1; j < 4; j++) {
384 					amixer = mixer->
385 						amixers[(type+j)*CHN_NUM+i];
386 					amixer->ops->set_scale(amixer, val);
387 					amixer->ops->commit_write(amixer);
388 				}
389 			}
390 		}
391 	}
392 
393 	return change;
394 }
395 
396 static struct snd_kcontrol_new vol_ctl = {
397 	.access		= SNDRV_CTL_ELEM_ACCESS_READWRITE |
398 			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
399 	.iface		= SNDRV_CTL_ELEM_IFACE_MIXER,
400 	.info		= ct_alsa_mix_volume_info,
401 	.get		= ct_alsa_mix_volume_get,
402 	.put		= ct_alsa_mix_volume_put,
403 	.tlv		= { .p =  ct_vol_db_scale },
404 };
405 
406 static int output_switch_info(struct snd_kcontrol *kcontrol,
407 			      struct snd_ctl_elem_info *info)
408 {
409 	static const char *const names[3] = {
410 	  "FP Headphones", "Headphones", "Speakers"
411 	};
412 
413 	return snd_ctl_enum_info(info, 1, 3, names);
414 }
415 
416 static int output_switch_get(struct snd_kcontrol *kcontrol,
417 			     struct snd_ctl_elem_value *ucontrol)
418 {
419 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
420 	ucontrol->value.enumerated.item[0] = atc->output_switch_get(atc);
421 	return 0;
422 }
423 
424 static int output_switch_put(struct snd_kcontrol *kcontrol,
425 			     struct snd_ctl_elem_value *ucontrol)
426 {
427 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
428 	if (ucontrol->value.enumerated.item[0] > 2)
429 		return -EINVAL;
430 	return atc->output_switch_put(atc, ucontrol->value.enumerated.item[0]);
431 }
432 
433 static struct snd_kcontrol_new output_ctl = {
434 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
435 	.name = "Analog Output Playback Enum",
436 	.info = output_switch_info,
437 	.get = output_switch_get,
438 	.put = output_switch_put,
439 };
440 
441 static int mic_source_switch_info(struct snd_kcontrol *kcontrol,
442 			      struct snd_ctl_elem_info *info)
443 {
444 	static const char *const names[3] = {
445 	  "Mic", "FP Mic", "Aux"
446 	};
447 
448 	return snd_ctl_enum_info(info, 1, 3, names);
449 }
450 
451 static int mic_source_switch_get(struct snd_kcontrol *kcontrol,
452 			     struct snd_ctl_elem_value *ucontrol)
453 {
454 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
455 	ucontrol->value.enumerated.item[0] = atc->mic_source_switch_get(atc);
456 	return 0;
457 }
458 
459 static int mic_source_switch_put(struct snd_kcontrol *kcontrol,
460 			     struct snd_ctl_elem_value *ucontrol)
461 {
462 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
463 	if (ucontrol->value.enumerated.item[0] > 2)
464 		return -EINVAL;
465 	return atc->mic_source_switch_put(atc,
466 					ucontrol->value.enumerated.item[0]);
467 }
468 
469 static struct snd_kcontrol_new mic_source_ctl = {
470 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
471 	.name = "Mic Source Capture Enum",
472 	.info = mic_source_switch_info,
473 	.get = mic_source_switch_get,
474 	.put = mic_source_switch_put,
475 };
476 
477 static void
478 do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
479 {
480 	struct ct_mixer *mixer = atc->mixer;
481 
482 	if (MIXER_LINEIN_C_S == type) {
483 		atc->select_line_in(atc);
484 		set_switch_state(mixer, MIXER_MIC_C_S, 0);
485 		snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
486 			       &mixer->line_mic_kctls[1]->id);
487 	} else if (MIXER_MIC_C_S == type) {
488 		atc->select_mic_in(atc);
489 		set_switch_state(mixer, MIXER_LINEIN_C_S, 0);
490 		snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
491 			       &mixer->line_mic_kctls[0]->id);
492 	}
493 }
494 
495 static void
496 do_digit_io_switch(struct ct_atc *atc, int state)
497 {
498 	struct ct_mixer *mixer = atc->mixer;
499 
500 	if (state) {
501 		atc->select_digit_io(atc);
502 		atc->spdif_out_unmute(atc,
503 				get_switch_state(mixer, MIXER_SPDIFO_P_S));
504 		atc->spdif_in_unmute(atc, 1);
505 		atc->line_in_unmute(atc, 0);
506 		return;
507 	}
508 
509 	if (get_switch_state(mixer, MIXER_LINEIN_C_S))
510 		atc->select_line_in(atc);
511 	else if (get_switch_state(mixer, MIXER_MIC_C_S))
512 		atc->select_mic_in(atc);
513 
514 	atc->spdif_out_unmute(atc, 0);
515 	atc->spdif_in_unmute(atc, 0);
516 	atc->line_in_unmute(atc, 1);
517 	return;
518 }
519 
520 static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
521 {
522 	struct ct_mixer *mixer = atc->mixer;
523 	struct capabilities cap = atc->capabilities(atc);
524 
525 	/* Do changes in mixer. */
526 	if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
527 		if (state) {
528 			ct_mixer_recording_select(mixer,
529 						  get_amixer_index(type));
530 		} else {
531 			ct_mixer_recording_unselect(mixer,
532 						    get_amixer_index(type));
533 		}
534 	}
535 	/* Do changes out of mixer. */
536 	if (!cap.dedicated_mic &&
537 	    (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type)) {
538 		if (state)
539 			do_line_mic_switch(atc, type);
540 		atc->line_in_unmute(atc, state);
541 	} else if (cap.dedicated_mic && (MIXER_LINEIN_C_S == type))
542 		atc->line_in_unmute(atc, state);
543 	else if (cap.dedicated_mic && (MIXER_MIC_C_S == type))
544 		atc->mic_unmute(atc, state);
545 	else if (MIXER_SPDIFI_C_S == type)
546 		atc->spdif_in_unmute(atc, state);
547 	else if (MIXER_WAVEF_P_S == type) {
548 		if (cap.dedicated_rca) {
549 			atc->rca_unmute(atc, atc->rca_state ? 0 : state);
550 			atc->line_front_unmute(atc, atc->rca_state ? state : 0);
551 		} else {
552 			atc->line_front_unmute(atc, state);
553 		}
554 	}
555 	else if (MIXER_WAVES_P_S == type)
556 		atc->line_surround_unmute(atc, state);
557 	else if (MIXER_WAVEC_P_S == type)
558 		atc->line_clfe_unmute(atc, state);
559 	else if (MIXER_WAVER_P_S == type)
560 		atc->line_rear_unmute(atc, state);
561 	else if (MIXER_SPDIFO_P_S == type)
562 		atc->spdif_out_unmute(atc, state);
563 	else if (MIXER_DIGITAL_IO_S == type)
564 		do_digit_io_switch(atc, state);
565 
566 	return;
567 }
568 
569 static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol,
570 				   struct snd_ctl_elem_info *uinfo)
571 {
572 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
573 	uinfo->count = 1;
574 	uinfo->value.integer.min = 0;
575 	uinfo->value.integer.max = 1;
576 	uinfo->value.integer.step = 1;
577 
578 	return 0;
579 }
580 
581 static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol,
582 				  struct snd_ctl_elem_value *ucontrol)
583 {
584 	struct ct_mixer *mixer =
585 		((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer;
586 	enum CTALSA_MIXER_CTL type = kcontrol->private_value;
587 
588 	ucontrol->value.integer.value[0] = get_switch_state(mixer, type);
589 	return 0;
590 }
591 
592 static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol,
593 				  struct snd_ctl_elem_value *ucontrol)
594 {
595 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
596 	struct ct_mixer *mixer = atc->mixer;
597 	enum CTALSA_MIXER_CTL type = kcontrol->private_value;
598 	int state;
599 
600 	state = ucontrol->value.integer.value[0];
601 	if (get_switch_state(mixer, type) == state)
602 		return 0;
603 
604 	set_switch_state(mixer, type, state);
605 	do_switch(atc, type, state);
606 
607 	return 1;
608 }
609 
610 static struct snd_kcontrol_new swh_ctl = {
611 	.access		= SNDRV_CTL_ELEM_ACCESS_READWRITE,
612 	.iface		= SNDRV_CTL_ELEM_IFACE_MIXER,
613 	.info		= ct_alsa_mix_switch_info,
614 	.get		= ct_alsa_mix_switch_get,
615 	.put		= ct_alsa_mix_switch_put
616 };
617 
618 static int dedicated_rca_info(struct snd_kcontrol *kcontrol,
619 			      struct snd_ctl_elem_info *info)
620 {
621 	static const char *const names[2] = {
622 	  "RCA", "Front"
623 	};
624 
625 	return snd_ctl_enum_info(info, 1, 2, names);
626 }
627 
628 static int dedicated_rca_get(struct snd_kcontrol *kcontrol,
629 			     struct snd_ctl_elem_value *ucontrol)
630 {
631 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
632 
633 	ucontrol->value.enumerated.item[0] = atc->rca_state;
634 	return 0;
635 }
636 
637 static int dedicated_rca_put(struct snd_kcontrol *kcontrol,
638 			     struct snd_ctl_elem_value *ucontrol)
639 {
640 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
641 	unsigned int rca_state = ucontrol->value.enumerated.item[0];
642 	unsigned char state;
643 
644 	if (rca_state > 1)
645 		return -EINVAL;
646 
647 	if (rca_state == atc->rca_state)
648 		return 0;
649 
650 	state = get_switch_state(atc->mixer, MIXER_WAVEF_P_S);
651 	do_switch(atc, MIXER_WAVEF_P_S, 0);
652 
653 	atc->rca_state = rca_state;
654 	atc->dedicated_rca_select(atc);
655 
656 	do_switch(atc, MIXER_WAVEF_P_S, state);
657 
658 	return 1;
659 }
660 
661 static struct snd_kcontrol_new rca_ctl = {
662 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
663 	.name = "Analog Playback Route",
664 	.info = dedicated_rca_info,
665 	.get = dedicated_rca_get,
666 	.put = dedicated_rca_put,
667 };
668 
669 static int ct_spdif_info(struct snd_kcontrol *kcontrol,
670 			 struct snd_ctl_elem_info *uinfo)
671 {
672 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
673 	uinfo->count = 1;
674 	return 0;
675 }
676 
677 static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
678 			     struct snd_ctl_elem_value *ucontrol)
679 {
680 	ucontrol->value.iec958.status[0] = 0xff;
681 	ucontrol->value.iec958.status[1] = 0xff;
682 	ucontrol->value.iec958.status[2] = 0xff;
683 	ucontrol->value.iec958.status[3] = 0xff;
684 	return 0;
685 }
686 
687 static int ct_spdif_get(struct snd_kcontrol *kcontrol,
688 			struct snd_ctl_elem_value *ucontrol)
689 {
690 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
691 	unsigned int status;
692 
693 	atc->spdif_out_get_status(atc, &status);
694 
695 	if (status == 0)
696 		status = SNDRV_PCM_DEFAULT_CON_SPDIF;
697 
698 	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
699 	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
700 	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
701 	ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
702 
703 	return 0;
704 }
705 
706 static int ct_spdif_put(struct snd_kcontrol *kcontrol,
707 			struct snd_ctl_elem_value *ucontrol)
708 {
709 	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
710 	int change;
711 	unsigned int status, old_status;
712 
713 	status = (ucontrol->value.iec958.status[0] << 0) |
714 		 (ucontrol->value.iec958.status[1] << 8) |
715 		 (ucontrol->value.iec958.status[2] << 16) |
716 		 (ucontrol->value.iec958.status[3] << 24);
717 
718 	atc->spdif_out_get_status(atc, &old_status);
719 	change = (old_status != status);
720 	if (change)
721 		atc->spdif_out_set_status(atc, status);
722 
723 	return change;
724 }
725 
726 static struct snd_kcontrol_new iec958_mask_ctl = {
727 	.access		= SNDRV_CTL_ELEM_ACCESS_READ,
728 	.iface		= SNDRV_CTL_ELEM_IFACE_PCM,
729 	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
730 	.count		= 1,
731 	.info		= ct_spdif_info,
732 	.get		= ct_spdif_get_mask,
733 	.private_value	= MIXER_IEC958_MASK
734 };
735 
736 static struct snd_kcontrol_new iec958_default_ctl = {
737 	.iface		= SNDRV_CTL_ELEM_IFACE_PCM,
738 	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
739 	.count		= 1,
740 	.info		= ct_spdif_info,
741 	.get		= ct_spdif_get,
742 	.put		= ct_spdif_put,
743 	.private_value	= MIXER_IEC958_DEFAULT
744 };
745 
746 static struct snd_kcontrol_new iec958_ctl = {
747 	.access		= SNDRV_CTL_ELEM_ACCESS_READWRITE,
748 	.iface		= SNDRV_CTL_ELEM_IFACE_PCM,
749 	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
750 	.count		= 1,
751 	.info		= ct_spdif_info,
752 	.get		= ct_spdif_get,
753 	.put		= ct_spdif_put,
754 	.private_value	= MIXER_IEC958_STREAM
755 };
756 
757 #define NUM_IEC958_CTL 3
758 
759 static int
760 ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
761 {
762 	struct snd_kcontrol *kctl;
763 	int err;
764 
765 	kctl = snd_ctl_new1(new, mixer->atc);
766 	if (!kctl)
767 		return -ENOMEM;
768 
769 	if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface)
770 		kctl->id.device = IEC958;
771 
772 	err = snd_ctl_add(mixer->atc->card, kctl);
773 	if (err)
774 		return err;
775 
776 	switch (new->private_value) {
777 	case MIXER_LINEIN_C_S:
778 		mixer->line_mic_kctls[0] = kctl; break;
779 	case MIXER_MIC_C_S:
780 		mixer->line_mic_kctls[1] = kctl; break;
781 	default:
782 		break;
783 	}
784 
785 	return 0;
786 }
787 
788 static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
789 {
790 	enum CTALSA_MIXER_CTL type;
791 	struct ct_atc *atc = mixer->atc;
792 	struct capabilities cap = atc->capabilities(atc);
793 	int err;
794 
795 	/* Create snd kcontrol instances on demand */
796 	for (type = VOL_MIXER_START; type <= VOL_MIXER_END; type++) {
797 		if (ct_kcontrol_init_table[type].ctl) {
798 			vol_ctl.name = ct_kcontrol_init_table[type].name;
799 			vol_ctl.private_value = (unsigned long)type;
800 			err = ct_mixer_kcontrol_new(mixer, &vol_ctl);
801 			if (err)
802 				return err;
803 		}
804 	}
805 
806 	ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl = cap.digit_io_switch;
807 
808 	for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) {
809 		if (ct_kcontrol_init_table[type].ctl) {
810 			swh_ctl.name = ct_kcontrol_init_table[type].name;
811 			swh_ctl.private_value = (unsigned long)type;
812 			err = ct_mixer_kcontrol_new(mixer, &swh_ctl);
813 			if (err)
814 				return err;
815 		}
816 	}
817 
818 	err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl);
819 	if (err)
820 		return err;
821 
822 	err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl);
823 	if (err)
824 		return err;
825 
826 	err = ct_mixer_kcontrol_new(mixer, &iec958_ctl);
827 	if (err)
828 		return err;
829 
830 	if (cap.output_switch) {
831 		err = ct_mixer_kcontrol_new(mixer, &output_ctl);
832 		if (err)
833 			return err;
834 	}
835 
836 	if (cap.mic_source_switch) {
837 		err = ct_mixer_kcontrol_new(mixer, &mic_source_ctl);
838 		if (err)
839 			return err;
840 	}
841 
842 	if (cap.dedicated_rca) {
843 		err = ct_mixer_kcontrol_new(mixer, &rca_ctl);
844 		if (err)
845 			return err;
846 
847 		atc->line_front_unmute(atc, 0);
848 		atc->rca_unmute(atc, 1);
849 	} else {
850 		atc->line_front_unmute(atc, 1);
851 	}
852 	set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
853 	atc->line_surround_unmute(atc, 0);
854 	set_switch_state(mixer, MIXER_WAVES_P_S, 0);
855 	atc->line_clfe_unmute(atc, 0);
856 	set_switch_state(mixer, MIXER_WAVEC_P_S, 0);
857 	atc->line_rear_unmute(atc, 0);
858 	set_switch_state(mixer, MIXER_WAVER_P_S, 0);
859 	atc->spdif_out_unmute(atc, 0);
860 	set_switch_state(mixer, MIXER_SPDIFO_P_S, 0);
861 	atc->line_in_unmute(atc, 0);
862 	if (cap.dedicated_mic)
863 		atc->mic_unmute(atc, 0);
864 	atc->spdif_in_unmute(atc, 0);
865 	set_switch_state(mixer, MIXER_PCM_C_S, 0);
866 	set_switch_state(mixer, MIXER_LINEIN_C_S, 0);
867 	set_switch_state(mixer, MIXER_SPDIFI_C_S, 0);
868 
869 	return 0;
870 }
871 
872 static void
873 ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
874 {
875 	struct amixer *amix_d;
876 	struct sum *sum_c;
877 	int i;
878 
879 	for (i = 0; i < 2; i++) {
880 		amix_d = mixer->amixers[type*CHN_NUM+i];
881 		sum_c = mixer->sums[SUM_IN_F_C*CHN_NUM+i];
882 		amix_d->ops->set_sum(amix_d, sum_c);
883 		amix_d->ops->commit_write(amix_d);
884 	}
885 }
886 
887 static void
888 ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
889 {
890 	struct amixer *amix_d;
891 	int i;
892 
893 	for (i = 0; i < 2; i++) {
894 		amix_d = mixer->amixers[type*CHN_NUM+i];
895 		amix_d->ops->set_sum(amix_d, NULL);
896 		amix_d->ops->commit_write(amix_d);
897 	}
898 }
899 
900 static int ct_mixer_get_resources(struct ct_mixer *mixer)
901 {
902 	struct sum_mgr *sum_mgr;
903 	struct sum *sum;
904 	struct sum_desc sum_desc = {0};
905 	struct amixer_mgr *amixer_mgr;
906 	struct amixer *amixer;
907 	struct amixer_desc am_desc = {0};
908 	int err;
909 	int i;
910 
911 	/* Allocate sum resources for mixer obj */
912 	sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
913 	sum_desc.msr = mixer->atc->msr;
914 	for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
915 		err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum);
916 		if (err) {
917 			dev_err(mixer->atc->card->dev,
918 				"Failed to get sum resources for front output!\n");
919 			break;
920 		}
921 		mixer->sums[i] = sum;
922 	}
923 	if (err)
924 		goto error1;
925 
926 	/* Allocate amixer resources for mixer obj */
927 	amixer_mgr = (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
928 	am_desc.msr = mixer->atc->msr;
929 	for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
930 		err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer);
931 		if (err) {
932 			dev_err(mixer->atc->card->dev,
933 				"Failed to get amixer resources for mixer obj!\n");
934 			break;
935 		}
936 		mixer->amixers[i] = amixer;
937 	}
938 	if (err)
939 		goto error2;
940 
941 	return 0;
942 
943 error2:
944 	for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
945 		if (NULL != mixer->amixers[i]) {
946 			amixer = mixer->amixers[i];
947 			amixer_mgr->put_amixer(amixer_mgr, amixer);
948 			mixer->amixers[i] = NULL;
949 		}
950 	}
951 error1:
952 	for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
953 		if (NULL != mixer->sums[i]) {
954 			sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
955 			mixer->sums[i] = NULL;
956 		}
957 	}
958 
959 	return err;
960 }
961 
962 static int ct_mixer_get_mem(struct ct_mixer **rmixer)
963 {
964 	struct ct_mixer *mixer;
965 	size_t alloc_size;
966 
967 	*rmixer = NULL;
968 	/* Allocate mem for mixer obj */
969 	alloc_size = struct_size(mixer, amixers, NUM_CT_AMIXERS * CHN_NUM);
970 	alloc_size += sizeof(*mixer->sums) * NUM_CT_SUMS * CHN_NUM;
971 	mixer = kzalloc(alloc_size, GFP_KERNEL);
972 	if (!mixer)
973 		return -ENOMEM;
974 
975 	mixer->sums = (struct sum **)(mixer->amixers + (NUM_CT_AMIXERS * CHN_NUM));
976 
977 	*rmixer = mixer;
978 	return 0;
979 }
980 
981 static int ct_mixer_topology_build(struct ct_mixer *mixer)
982 {
983 	struct sum *sum;
984 	struct amixer *amix_d, *amix_s;
985 	enum CT_AMIXER_CTL i, j;
986 	enum CT_SUM_CTL k;
987 
988 	/* Build topology from destination to source */
989 
990 	/* Set up Master mixer */
991 	for (i = AMIXER_MASTER_F, k = SUM_IN_F;
992 					i <= AMIXER_MASTER_S; i++, k++) {
993 		amix_d = mixer->amixers[i*CHN_NUM];
994 		sum = mixer->sums[k*CHN_NUM];
995 		amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
996 		amix_d = mixer->amixers[i*CHN_NUM+1];
997 		sum = mixer->sums[k*CHN_NUM+1];
998 		amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
999 	}
1000 
1001 	/* Set up Wave-out mixer */
1002 	for (i = AMIXER_WAVE_F, j = AMIXER_MASTER_F;
1003 					i <= AMIXER_WAVE_S; i++, j++) {
1004 		amix_d = mixer->amixers[i*CHN_NUM];
1005 		amix_s = mixer->amixers[j*CHN_NUM];
1006 		amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
1007 		amix_d = mixer->amixers[i*CHN_NUM+1];
1008 		amix_s = mixer->amixers[j*CHN_NUM+1];
1009 		amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
1010 	}
1011 
1012 	/* Set up S/PDIF-out mixer */
1013 	amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM];
1014 	amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM];
1015 	amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
1016 	amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM+1];
1017 	amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM+1];
1018 	amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
1019 
1020 	/* Set up PCM-in mixer */
1021 	for (i = AMIXER_PCM_F, k = SUM_IN_F; i <= AMIXER_PCM_S; i++, k++) {
1022 		amix_d = mixer->amixers[i*CHN_NUM];
1023 		sum = mixer->sums[k*CHN_NUM];
1024 		amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1025 		amix_d = mixer->amixers[i*CHN_NUM+1];
1026 		sum = mixer->sums[k*CHN_NUM+1];
1027 		amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1028 	}
1029 
1030 	/* Set up Line-in mixer */
1031 	amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM];
1032 	sum = mixer->sums[SUM_IN_F*CHN_NUM];
1033 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1034 	amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM+1];
1035 	sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
1036 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1037 
1038 	/* Set up Mic-in mixer */
1039 	amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM];
1040 	sum = mixer->sums[SUM_IN_F*CHN_NUM];
1041 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1042 	amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM+1];
1043 	sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
1044 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1045 
1046 	/* Set up S/PDIF-in mixer */
1047 	amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM];
1048 	sum = mixer->sums[SUM_IN_F*CHN_NUM];
1049 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1050 	amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM+1];
1051 	sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
1052 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1053 
1054 	/* Set up Master recording mixer */
1055 	amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM];
1056 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1057 	amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
1058 	amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM+1];
1059 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1060 	amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
1061 
1062 	/* Set up PCM-in recording mixer */
1063 	amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM];
1064 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1065 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1066 	amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM+1];
1067 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1068 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1069 
1070 	/* Set up Line-in recording mixer */
1071 	amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM];
1072 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1073 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1074 	amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM+1];
1075 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1076 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1077 
1078 	/* Set up Mic-in recording mixer */
1079 	amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM];
1080 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1081 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1082 	amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM+1];
1083 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1084 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1085 
1086 	/* Set up S/PDIF-in recording mixer */
1087 	amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM];
1088 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
1089 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1090 	amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM+1];
1091 	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
1092 	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
1093 
1094 	return 0;
1095 }
1096 
1097 static int mixer_set_input_port(struct amixer *amixer, struct rsc *rsc)
1098 {
1099 	amixer->ops->set_input(amixer, rsc);
1100 	amixer->ops->commit_write(amixer);
1101 
1102 	return 0;
1103 }
1104 
1105 static enum CT_AMIXER_CTL port_to_amixer(enum MIXER_PORT_T type)
1106 {
1107 	switch (type) {
1108 	case MIX_WAVE_FRONT:	return AMIXER_WAVE_F;
1109 	case MIX_WAVE_SURROUND:	return AMIXER_WAVE_S;
1110 	case MIX_WAVE_CENTLFE:	return AMIXER_WAVE_C;
1111 	case MIX_WAVE_REAR:	return AMIXER_WAVE_R;
1112 	case MIX_PCMO_FRONT:	return AMIXER_MASTER_F_C;
1113 	case MIX_SPDIF_OUT:	return AMIXER_SPDIFO;
1114 	case MIX_LINE_IN:	return AMIXER_LINEIN;
1115 	case MIX_MIC_IN:	return AMIXER_MIC;
1116 	case MIX_SPDIF_IN:	return AMIXER_SPDIFI;
1117 	case MIX_PCMI_FRONT:	return AMIXER_PCM_F;
1118 	case MIX_PCMI_SURROUND:	return AMIXER_PCM_S;
1119 	case MIX_PCMI_CENTLFE:	return AMIXER_PCM_C;
1120 	case MIX_PCMI_REAR:	return AMIXER_PCM_R;
1121 	default: 		return 0;
1122 	}
1123 }
1124 
1125 static int mixer_get_output_ports(struct ct_mixer *mixer,
1126 				  enum MIXER_PORT_T type,
1127 				  struct rsc **rleft, struct rsc **rright)
1128 {
1129 	enum CT_AMIXER_CTL amix = port_to_amixer(type);
1130 
1131 	if (NULL != rleft)
1132 		*rleft = &((struct amixer *)mixer->amixers[amix*CHN_NUM])->rsc;
1133 
1134 	if (NULL != rright)
1135 		*rright =
1136 			&((struct amixer *)mixer->amixers[amix*CHN_NUM+1])->rsc;
1137 
1138 	return 0;
1139 }
1140 
1141 static int mixer_set_input_left(struct ct_mixer *mixer,
1142 				enum MIXER_PORT_T type, struct rsc *rsc)
1143 {
1144 	enum CT_AMIXER_CTL amix = port_to_amixer(type);
1145 
1146 	mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1147 	amix = get_recording_amixer(amix);
1148 	if (amix < NUM_CT_AMIXERS)
1149 		mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
1150 
1151 	return 0;
1152 }
1153 
1154 static int
1155 mixer_set_input_right(struct ct_mixer *mixer,
1156 		      enum MIXER_PORT_T type, struct rsc *rsc)
1157 {
1158 	enum CT_AMIXER_CTL amix = port_to_amixer(type);
1159 
1160 	mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1161 	amix = get_recording_amixer(amix);
1162 	if (amix < NUM_CT_AMIXERS)
1163 		mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1164 
1165 	return 0;
1166 }
1167 
1168 #ifdef CONFIG_PM_SLEEP
1169 static int mixer_resume(struct ct_mixer *mixer)
1170 {
1171 	int i, state;
1172 	struct amixer *amixer;
1173 
1174 	/* resume topology and volume gain. */
1175 	for (i = 0; i < NUM_CT_AMIXERS*CHN_NUM; i++) {
1176 		amixer = mixer->amixers[i];
1177 		amixer->ops->commit_write(amixer);
1178 	}
1179 
1180 	/* resume switch state. */
1181 	for (i = SWH_MIXER_START; i <= SWH_MIXER_END; i++) {
1182 		state = get_switch_state(mixer, i);
1183 		do_switch(mixer->atc, i, state);
1184 	}
1185 
1186 	return 0;
1187 }
1188 #endif
1189 
1190 int ct_mixer_destroy(struct ct_mixer *mixer)
1191 {
1192 	struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
1193 	struct amixer_mgr *amixer_mgr =
1194 			(struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
1195 	struct amixer *amixer;
1196 	int i = 0;
1197 
1198 	/* Release amixer resources */
1199 	for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
1200 		if (NULL != mixer->amixers[i]) {
1201 			amixer = mixer->amixers[i];
1202 			amixer_mgr->put_amixer(amixer_mgr, amixer);
1203 		}
1204 	}
1205 
1206 	/* Release sum resources */
1207 	for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
1208 		if (NULL != mixer->sums[i])
1209 			sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
1210 	}
1211 
1212 	/* Release mem assigned to mixer object */
1213 	kfree(mixer);
1214 
1215 	return 0;
1216 }
1217 
1218 int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer)
1219 {
1220 	struct ct_mixer *mixer;
1221 	int err;
1222 
1223 	*rmixer = NULL;
1224 
1225 	/* Allocate mem for mixer obj */
1226 	err = ct_mixer_get_mem(&mixer);
1227 	if (err)
1228 		return err;
1229 
1230 	mixer->switch_state = 0;
1231 	mixer->atc = atc;
1232 	/* Set operations */
1233 	mixer->get_output_ports = mixer_get_output_ports;
1234 	mixer->set_input_left = mixer_set_input_left;
1235 	mixer->set_input_right = mixer_set_input_right;
1236 #ifdef CONFIG_PM_SLEEP
1237 	mixer->resume = mixer_resume;
1238 #endif
1239 
1240 	/* Allocate chip resources for mixer obj */
1241 	err = ct_mixer_get_resources(mixer);
1242 	if (err)
1243 		goto error;
1244 
1245 	/* Build internal mixer topology */
1246 	ct_mixer_topology_build(mixer);
1247 
1248 	*rmixer = mixer;
1249 
1250 	return 0;
1251 
1252 error:
1253 	ct_mixer_destroy(mixer);
1254 	return err;
1255 }
1256 
1257 int ct_alsa_mix_create(struct ct_atc *atc,
1258 		       enum CTALSADEVS device,
1259 		       const char *device_name)
1260 {
1261 	int err;
1262 
1263 	/* Create snd kcontrol instances on demand */
1264 	/* vol_ctl.device = swh_ctl.device = device; */ /* better w/ device 0 */
1265 	err = ct_mixer_kcontrols_create((struct ct_mixer *)atc->mixer);
1266 	if (err)
1267 		return err;
1268 
1269 	strscpy(atc->card->mixername, device_name);
1270 
1271 	return 0;
1272 }
1273