• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/sound/pci/ctxfi/
1/**
2 * Copyright (C) 2008, Creative Technology Ltd. All Rights Reserved.
3 *
4 * This source file is released under GPL v2 license (no other versions).
5 * See the COPYING file included in the main directory of this source
6 * distribution for the license terms and conditions.
7 *
8 * @File	ctmixer.c
9 *
10 * @Brief
11 * This file contains the implementation of alsa mixer device functions.
12 *
13 * @Author	Liu Chun
14 * @Date 	May 28 2008
15 *
16 */
17
18
19#include "ctmixer.h"
20#include "ctamixer.h"
21#include <linux/slab.h>
22#include <sound/core.h>
23#include <sound/control.h>
24#include <sound/asoundef.h>
25#include <sound/pcm.h>
26#include <sound/tlv.h>
27
28enum CT_SUM_CTL {
29	SUM_IN_F,
30	SUM_IN_R,
31	SUM_IN_C,
32	SUM_IN_S,
33	SUM_IN_F_C,
34
35	NUM_CT_SUMS
36};
37
38enum CT_AMIXER_CTL {
39	/* volume control mixers */
40	AMIXER_MASTER_F,
41	AMIXER_MASTER_R,
42	AMIXER_MASTER_C,
43	AMIXER_MASTER_S,
44	AMIXER_PCM_F,
45	AMIXER_PCM_R,
46	AMIXER_PCM_C,
47	AMIXER_PCM_S,
48	AMIXER_SPDIFI,
49	AMIXER_LINEIN,
50	AMIXER_MIC,
51	AMIXER_SPDIFO,
52	AMIXER_WAVE_F,
53	AMIXER_WAVE_R,
54	AMIXER_WAVE_C,
55	AMIXER_WAVE_S,
56	AMIXER_MASTER_F_C,
57	AMIXER_PCM_F_C,
58	AMIXER_SPDIFI_C,
59	AMIXER_LINEIN_C,
60	AMIXER_MIC_C,
61
62	/* this should always be the last one */
63	NUM_CT_AMIXERS
64};
65
66enum CTALSA_MIXER_CTL {
67	/* volume control mixers */
68	MIXER_MASTER_P,
69	MIXER_PCM_P,
70	MIXER_LINEIN_P,
71	MIXER_MIC_P,
72	MIXER_SPDIFI_P,
73	MIXER_SPDIFO_P,
74	MIXER_WAVEF_P,
75	MIXER_WAVER_P,
76	MIXER_WAVEC_P,
77	MIXER_WAVES_P,
78	MIXER_MASTER_C,
79	MIXER_PCM_C,
80	MIXER_LINEIN_C,
81	MIXER_MIC_C,
82	MIXER_SPDIFI_C,
83
84	/* switch control mixers */
85	MIXER_PCM_C_S,
86	MIXER_LINEIN_C_S,
87	MIXER_MIC_C_S,
88	MIXER_SPDIFI_C_S,
89	MIXER_LINEIN_P_S,
90	MIXER_SPDIFO_P_S,
91	MIXER_SPDIFI_P_S,
92	MIXER_WAVEF_P_S,
93	MIXER_WAVER_P_S,
94	MIXER_WAVEC_P_S,
95	MIXER_WAVES_P_S,
96	MIXER_DIGITAL_IO_S,
97	MIXER_IEC958_MASK,
98	MIXER_IEC958_DEFAULT,
99	MIXER_IEC958_STREAM,
100
101	/* this should always be the last one */
102	NUM_CTALSA_MIXERS
103};
104
105#define VOL_MIXER_START		MIXER_MASTER_P
106#define VOL_MIXER_END		MIXER_SPDIFI_C
107#define VOL_MIXER_NUM		(VOL_MIXER_END - VOL_MIXER_START + 1)
108#define SWH_MIXER_START		MIXER_PCM_C_S
109#define SWH_MIXER_END		MIXER_DIGITAL_IO_S
110#define SWH_CAPTURE_START	MIXER_PCM_C_S
111#define SWH_CAPTURE_END		MIXER_SPDIFI_C_S
112
113#define CHN_NUM		2
114
115struct ct_kcontrol_init {
116	unsigned char ctl;
117	char *name;
118};
119
120static struct ct_kcontrol_init
121ct_kcontrol_init_table[NUM_CTALSA_MIXERS] = {
122	[MIXER_MASTER_P] = {
123		.ctl = 1,
124		.name = "Master Playback Volume",
125	},
126	[MIXER_MASTER_C] = {
127		.ctl = 1,
128		.name = "Master Capture Volume",
129	},
130	[MIXER_PCM_P] = {
131		.ctl = 1,
132		.name = "PCM Playback Volume",
133	},
134	[MIXER_PCM_C] = {
135		.ctl = 1,
136		.name = "PCM Capture Volume",
137	},
138	[MIXER_LINEIN_P] = {
139		.ctl = 1,
140		.name = "Line-in Playback Volume",
141	},
142	[MIXER_LINEIN_C] = {
143		.ctl = 1,
144		.name = "Line-in Capture Volume",
145	},
146	[MIXER_MIC_P] = {
147		.ctl = 1,
148		.name = "Mic Playback Volume",
149	},
150	[MIXER_MIC_C] = {
151		.ctl = 1,
152		.name = "Mic Capture Volume",
153	},
154	[MIXER_SPDIFI_P] = {
155		.ctl = 1,
156		.name = "S/PDIF-in Playback Volume",
157	},
158	[MIXER_SPDIFI_C] = {
159		.ctl = 1,
160		.name = "S/PDIF-in Capture Volume",
161	},
162	[MIXER_SPDIFO_P] = {
163		.ctl = 1,
164		.name = "S/PDIF-out Playback Volume",
165	},
166	[MIXER_WAVEF_P] = {
167		.ctl = 1,
168		.name = "Front Playback Volume",
169	},
170	[MIXER_WAVES_P] = {
171		.ctl = 1,
172		.name = "Side Playback Volume",
173	},
174	[MIXER_WAVEC_P] = {
175		.ctl = 1,
176		.name = "Center/LFE Playback Volume",
177	},
178	[MIXER_WAVER_P] = {
179		.ctl = 1,
180		.name = "Surround Playback Volume",
181	},
182
183	[MIXER_PCM_C_S] = {
184		.ctl = 1,
185		.name = "PCM Capture Switch",
186	},
187	[MIXER_LINEIN_C_S] = {
188		.ctl = 1,
189		.name = "Line-in Capture Switch",
190	},
191	[MIXER_MIC_C_S] = {
192		.ctl = 1,
193		.name = "Mic Capture Switch",
194	},
195	[MIXER_SPDIFI_C_S] = {
196		.ctl = 1,
197		.name = "S/PDIF-in Capture Switch",
198	},
199	[MIXER_LINEIN_P_S] = {
200		.ctl = 1,
201		.name = "Line-in Playback Switch",
202	},
203	[MIXER_SPDIFO_P_S] = {
204		.ctl = 1,
205		.name = "S/PDIF-out Playback Switch",
206	},
207	[MIXER_SPDIFI_P_S] = {
208		.ctl = 1,
209		.name = "S/PDIF-in Playback Switch",
210	},
211	[MIXER_WAVEF_P_S] = {
212		.ctl = 1,
213		.name = "Front Playback Switch",
214	},
215	[MIXER_WAVES_P_S] = {
216		.ctl = 1,
217		.name = "Side Playback Switch",
218	},
219	[MIXER_WAVEC_P_S] = {
220		.ctl = 1,
221		.name = "Center/LFE Playback Switch",
222	},
223	[MIXER_WAVER_P_S] = {
224		.ctl = 1,
225		.name = "Surround Playback Switch",
226	},
227	[MIXER_DIGITAL_IO_S] = {
228		.ctl = 0,
229		.name = "Digit-IO Playback Switch",
230	},
231};
232
233static void
234ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
235
236static void
237ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
238
239static struct snd_kcontrol *kctls[2] = {NULL};
240
241static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
242{
243	switch (alsa_index) {
244	case MIXER_MASTER_P:	return AMIXER_MASTER_F;
245	case MIXER_MASTER_C:	return AMIXER_MASTER_F_C;
246	case MIXER_PCM_P:	return AMIXER_PCM_F;
247	case MIXER_PCM_C:
248	case MIXER_PCM_C_S:	return AMIXER_PCM_F_C;
249	case MIXER_LINEIN_P:	return AMIXER_LINEIN;
250	case MIXER_LINEIN_C:
251	case MIXER_LINEIN_C_S:	return AMIXER_LINEIN_C;
252	case MIXER_MIC_P:	return AMIXER_MIC;
253	case MIXER_MIC_C:
254	case MIXER_MIC_C_S:	return AMIXER_MIC_C;
255	case MIXER_SPDIFI_P:	return AMIXER_SPDIFI;
256	case MIXER_SPDIFI_C:
257	case MIXER_SPDIFI_C_S:	return AMIXER_SPDIFI_C;
258	case MIXER_SPDIFO_P:	return AMIXER_SPDIFO;
259	case MIXER_WAVEF_P:	return AMIXER_WAVE_F;
260	case MIXER_WAVES_P:	return AMIXER_WAVE_S;
261	case MIXER_WAVEC_P:	return AMIXER_WAVE_C;
262	case MIXER_WAVER_P:	return AMIXER_WAVE_R;
263	default:		return NUM_CT_AMIXERS;
264	}
265}
266
267static enum CT_AMIXER_CTL get_recording_amixer(enum CT_AMIXER_CTL index)
268{
269	switch (index) {
270	case AMIXER_MASTER_F:	return AMIXER_MASTER_F_C;
271	case AMIXER_PCM_F:	return AMIXER_PCM_F_C;
272	case AMIXER_SPDIFI:	return AMIXER_SPDIFI_C;
273	case AMIXER_LINEIN:	return AMIXER_LINEIN_C;
274	case AMIXER_MIC:	return AMIXER_MIC_C;
275	default:		return NUM_CT_AMIXERS;
276	}
277}
278
279static unsigned char
280get_switch_state(struct ct_mixer *mixer, enum CTALSA_MIXER_CTL type)
281{
282	return (mixer->switch_state & (0x1 << (type - SWH_MIXER_START)))
283		? 1 : 0;
284}
285
286static void
287set_switch_state(struct ct_mixer *mixer,
288		 enum CTALSA_MIXER_CTL type, unsigned char state)
289{
290	if (state)
291		mixer->switch_state |= (0x1 << (type - SWH_MIXER_START));
292	else
293		mixer->switch_state &= ~(0x1 << (type - SWH_MIXER_START));
294}
295
296
297#define VOL_SCALE	0x1c
298#define VOL_MAX		0x100
299
300static const DECLARE_TLV_DB_SCALE(ct_vol_db_scale, -6400, 25, 1);
301
302static int ct_alsa_mix_volume_info(struct snd_kcontrol *kcontrol,
303				   struct snd_ctl_elem_info *uinfo)
304{
305	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
306	uinfo->count = 2;
307	uinfo->value.integer.min = 0;
308	uinfo->value.integer.max = VOL_MAX;
309
310	return 0;
311}
312
313static int ct_alsa_mix_volume_get(struct snd_kcontrol *kcontrol,
314				  struct snd_ctl_elem_value *ucontrol)
315{
316	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
317	enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
318	struct amixer *amixer;
319	int i, val;
320
321	for (i = 0; i < 2; i++) {
322		amixer = ((struct ct_mixer *)atc->mixer)->
323						amixers[type*CHN_NUM+i];
324		val = amixer->ops->get_scale(amixer) / VOL_SCALE;
325		if (val < 0)
326			val = 0;
327		else if (val > VOL_MAX)
328			val = VOL_MAX;
329		ucontrol->value.integer.value[i] = val;
330	}
331
332	return 0;
333}
334
335static int ct_alsa_mix_volume_put(struct snd_kcontrol *kcontrol,
336				  struct snd_ctl_elem_value *ucontrol)
337{
338	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
339	struct ct_mixer *mixer = atc->mixer;
340	enum CT_AMIXER_CTL type = get_amixer_index(kcontrol->private_value);
341	struct amixer *amixer;
342	int i, j, val, oval, change = 0;
343
344	for (i = 0; i < 2; i++) {
345		val = ucontrol->value.integer.value[i];
346		if (val < 0)
347			val = 0;
348		else if (val > VOL_MAX)
349			val = VOL_MAX;
350		val *= VOL_SCALE;
351		amixer = mixer->amixers[type*CHN_NUM+i];
352		oval = amixer->ops->get_scale(amixer);
353		if (val != oval) {
354			amixer->ops->set_scale(amixer, val);
355			amixer->ops->commit_write(amixer);
356			change = 1;
357			/* Synchronize Master/PCM playback AMIXERs. */
358			if (AMIXER_MASTER_F == type || AMIXER_PCM_F == type) {
359				for (j = 1; j < 4; j++) {
360					amixer = mixer->
361						amixers[(type+j)*CHN_NUM+i];
362					amixer->ops->set_scale(amixer, val);
363					amixer->ops->commit_write(amixer);
364				}
365			}
366		}
367	}
368
369	return change;
370}
371
372static struct snd_kcontrol_new vol_ctl = {
373	.access		= SNDRV_CTL_ELEM_ACCESS_READWRITE |
374			  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
375	.iface		= SNDRV_CTL_ELEM_IFACE_MIXER,
376	.info		= ct_alsa_mix_volume_info,
377	.get		= ct_alsa_mix_volume_get,
378	.put		= ct_alsa_mix_volume_put,
379	.tlv		= { .p =  ct_vol_db_scale },
380};
381
382static void
383do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
384{
385
386	if (MIXER_LINEIN_C_S == type) {
387		atc->select_line_in(atc);
388		set_switch_state(atc->mixer, MIXER_MIC_C_S, 0);
389		snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
390							&kctls[1]->id);
391	} else if (MIXER_MIC_C_S == type) {
392		atc->select_mic_in(atc);
393		set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0);
394		snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
395							&kctls[0]->id);
396	}
397}
398
399static void
400do_digit_io_switch(struct ct_atc *atc, int state)
401{
402	struct ct_mixer *mixer = atc->mixer;
403
404	if (state) {
405		atc->select_digit_io(atc);
406		atc->spdif_out_unmute(atc,
407				get_switch_state(mixer, MIXER_SPDIFO_P_S));
408		atc->spdif_in_unmute(atc, 1);
409		atc->line_in_unmute(atc, 0);
410		return;
411	}
412
413	if (get_switch_state(mixer, MIXER_LINEIN_C_S))
414		atc->select_line_in(atc);
415	else if (get_switch_state(mixer, MIXER_MIC_C_S))
416		atc->select_mic_in(atc);
417
418	atc->spdif_out_unmute(atc, 0);
419	atc->spdif_in_unmute(atc, 0);
420	atc->line_in_unmute(atc, 1);
421	return;
422}
423
424static void do_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type, int state)
425{
426	struct ct_mixer *mixer = atc->mixer;
427
428	/* Do changes in mixer. */
429	if ((SWH_CAPTURE_START <= type) && (SWH_CAPTURE_END >= type)) {
430		if (state) {
431			ct_mixer_recording_select(mixer,
432						  get_amixer_index(type));
433		} else {
434			ct_mixer_recording_unselect(mixer,
435						    get_amixer_index(type));
436		}
437	}
438	/* Do changes out of mixer. */
439	if (state && (MIXER_LINEIN_C_S == type || MIXER_MIC_C_S == type))
440		do_line_mic_switch(atc, type);
441	else if (MIXER_WAVEF_P_S == type)
442		atc->line_front_unmute(atc, state);
443	else if (MIXER_WAVES_P_S == type)
444		atc->line_surround_unmute(atc, state);
445	else if (MIXER_WAVEC_P_S == type)
446		atc->line_clfe_unmute(atc, state);
447	else if (MIXER_WAVER_P_S == type)
448		atc->line_rear_unmute(atc, state);
449	else if (MIXER_LINEIN_P_S == type)
450		atc->line_in_unmute(atc, state);
451	else if (MIXER_SPDIFO_P_S == type)
452		atc->spdif_out_unmute(atc, state);
453	else if (MIXER_SPDIFI_P_S == type)
454		atc->spdif_in_unmute(atc, state);
455	else if (MIXER_DIGITAL_IO_S == type)
456		do_digit_io_switch(atc, state);
457
458	return;
459}
460
461static int ct_alsa_mix_switch_info(struct snd_kcontrol *kcontrol,
462				   struct snd_ctl_elem_info *uinfo)
463{
464	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
465	uinfo->count = 1;
466	uinfo->value.integer.min = 0;
467	uinfo->value.integer.max = 1;
468	uinfo->value.integer.step = 1;
469
470	return 0;
471}
472
473static int ct_alsa_mix_switch_get(struct snd_kcontrol *kcontrol,
474				  struct snd_ctl_elem_value *ucontrol)
475{
476	struct ct_mixer *mixer =
477		((struct ct_atc *)snd_kcontrol_chip(kcontrol))->mixer;
478	enum CTALSA_MIXER_CTL type = kcontrol->private_value;
479
480	ucontrol->value.integer.value[0] = get_switch_state(mixer, type);
481	return 0;
482}
483
484static int ct_alsa_mix_switch_put(struct snd_kcontrol *kcontrol,
485				  struct snd_ctl_elem_value *ucontrol)
486{
487	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
488	struct ct_mixer *mixer = atc->mixer;
489	enum CTALSA_MIXER_CTL type = kcontrol->private_value;
490	int state;
491
492	state = ucontrol->value.integer.value[0];
493	if (get_switch_state(mixer, type) == state)
494		return 0;
495
496	set_switch_state(mixer, type, state);
497	do_switch(atc, type, state);
498
499	return 1;
500}
501
502static struct snd_kcontrol_new swh_ctl = {
503	.access		= SNDRV_CTL_ELEM_ACCESS_READWRITE,
504	.iface		= SNDRV_CTL_ELEM_IFACE_MIXER,
505	.info		= ct_alsa_mix_switch_info,
506	.get		= ct_alsa_mix_switch_get,
507	.put		= ct_alsa_mix_switch_put
508};
509
510static int ct_spdif_info(struct snd_kcontrol *kcontrol,
511			 struct snd_ctl_elem_info *uinfo)
512{
513	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
514	uinfo->count = 1;
515	return 0;
516}
517
518static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
519			     struct snd_ctl_elem_value *ucontrol)
520{
521	ucontrol->value.iec958.status[0] = 0xff;
522	ucontrol->value.iec958.status[1] = 0xff;
523	ucontrol->value.iec958.status[2] = 0xff;
524	ucontrol->value.iec958.status[3] = 0xff;
525	return 0;
526}
527
528static int ct_spdif_default_get(struct snd_kcontrol *kcontrol,
529				struct snd_ctl_elem_value *ucontrol)
530{
531	unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF;
532
533	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
534	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
535	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
536	ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
537
538	return 0;
539}
540
541static int ct_spdif_get(struct snd_kcontrol *kcontrol,
542			struct snd_ctl_elem_value *ucontrol)
543{
544	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
545	unsigned int status;
546
547	atc->spdif_out_get_status(atc, &status);
548	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
549	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
550	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
551	ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
552
553	return 0;
554}
555
556static int ct_spdif_put(struct snd_kcontrol *kcontrol,
557			struct snd_ctl_elem_value *ucontrol)
558{
559	struct ct_atc *atc = snd_kcontrol_chip(kcontrol);
560	int change;
561	unsigned int status, old_status;
562
563	status = (ucontrol->value.iec958.status[0] << 0) |
564		 (ucontrol->value.iec958.status[1] << 8) |
565		 (ucontrol->value.iec958.status[2] << 16) |
566		 (ucontrol->value.iec958.status[3] << 24);
567
568	atc->spdif_out_get_status(atc, &old_status);
569	change = (old_status != status);
570	if (change)
571		atc->spdif_out_set_status(atc, status);
572
573	return change;
574}
575
576static struct snd_kcontrol_new iec958_mask_ctl = {
577	.access		= SNDRV_CTL_ELEM_ACCESS_READ,
578	.iface		= SNDRV_CTL_ELEM_IFACE_PCM,
579	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),
580	.count		= 1,
581	.info		= ct_spdif_info,
582	.get		= ct_spdif_get_mask,
583	.private_value	= MIXER_IEC958_MASK
584};
585
586static struct snd_kcontrol_new iec958_default_ctl = {
587	.iface		= SNDRV_CTL_ELEM_IFACE_PCM,
588	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
589	.count		= 1,
590	.info		= ct_spdif_info,
591	.get		= ct_spdif_default_get,
592	.put		= ct_spdif_put,
593	.private_value	= MIXER_IEC958_DEFAULT
594};
595
596static struct snd_kcontrol_new iec958_ctl = {
597	.access		= SNDRV_CTL_ELEM_ACCESS_READWRITE,
598	.iface		= SNDRV_CTL_ELEM_IFACE_PCM,
599	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, PCM_STREAM),
600	.count		= 1,
601	.info		= ct_spdif_info,
602	.get		= ct_spdif_get,
603	.put		= ct_spdif_put,
604	.private_value	= MIXER_IEC958_STREAM
605};
606
607#define NUM_IEC958_CTL 3
608
609static int
610ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
611{
612	struct snd_kcontrol *kctl;
613	int err;
614
615	kctl = snd_ctl_new1(new, mixer->atc);
616	if (!kctl)
617		return -ENOMEM;
618
619	if (SNDRV_CTL_ELEM_IFACE_PCM == kctl->id.iface)
620		kctl->id.device = IEC958;
621
622	err = snd_ctl_add(mixer->atc->card, kctl);
623	if (err)
624		return err;
625
626	switch (new->private_value) {
627	case MIXER_LINEIN_C_S:
628		kctls[0] = kctl; break;
629	case MIXER_MIC_C_S:
630		kctls[1] = kctl; break;
631	default:
632		break;
633	}
634
635	return 0;
636}
637
638static int ct_mixer_kcontrols_create(struct ct_mixer *mixer)
639{
640	enum CTALSA_MIXER_CTL type;
641	struct ct_atc *atc = mixer->atc;
642	int err;
643
644	/* Create snd kcontrol instances on demand */
645	for (type = VOL_MIXER_START; type <= VOL_MIXER_END; type++) {
646		if (ct_kcontrol_init_table[type].ctl) {
647			vol_ctl.name = ct_kcontrol_init_table[type].name;
648			vol_ctl.private_value = (unsigned long)type;
649			err = ct_mixer_kcontrol_new(mixer, &vol_ctl);
650			if (err)
651				return err;
652		}
653	}
654
655	ct_kcontrol_init_table[MIXER_DIGITAL_IO_S].ctl =
656					atc->have_digit_io_switch(atc);
657	for (type = SWH_MIXER_START; type <= SWH_MIXER_END; type++) {
658		if (ct_kcontrol_init_table[type].ctl) {
659			swh_ctl.name = ct_kcontrol_init_table[type].name;
660			swh_ctl.private_value = (unsigned long)type;
661			err = ct_mixer_kcontrol_new(mixer, &swh_ctl);
662			if (err)
663				return err;
664		}
665	}
666
667	err = ct_mixer_kcontrol_new(mixer, &iec958_mask_ctl);
668	if (err)
669		return err;
670
671	err = ct_mixer_kcontrol_new(mixer, &iec958_default_ctl);
672	if (err)
673		return err;
674
675	err = ct_mixer_kcontrol_new(mixer, &iec958_ctl);
676	if (err)
677		return err;
678
679	atc->line_front_unmute(atc, 1);
680	set_switch_state(mixer, MIXER_WAVEF_P_S, 1);
681	atc->line_surround_unmute(atc, 0);
682	set_switch_state(mixer, MIXER_WAVES_P_S, 0);
683	atc->line_clfe_unmute(atc, 0);
684	set_switch_state(mixer, MIXER_WAVEC_P_S, 0);
685	atc->line_rear_unmute(atc, 0);
686	set_switch_state(mixer, MIXER_WAVER_P_S, 0);
687	atc->spdif_out_unmute(atc, 0);
688	set_switch_state(mixer, MIXER_SPDIFO_P_S, 0);
689	atc->line_in_unmute(atc, 0);
690	set_switch_state(mixer, MIXER_LINEIN_P_S, 0);
691	atc->spdif_in_unmute(atc, 0);
692	set_switch_state(mixer, MIXER_SPDIFI_P_S, 0);
693
694	set_switch_state(mixer, MIXER_PCM_C_S, 1);
695	set_switch_state(mixer, MIXER_LINEIN_C_S, 1);
696	set_switch_state(mixer, MIXER_SPDIFI_C_S, 1);
697
698	return 0;
699}
700
701static void
702ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
703{
704	struct amixer *amix_d;
705	struct sum *sum_c;
706	int i;
707
708	for (i = 0; i < 2; i++) {
709		amix_d = mixer->amixers[type*CHN_NUM+i];
710		sum_c = mixer->sums[SUM_IN_F_C*CHN_NUM+i];
711		amix_d->ops->set_sum(amix_d, sum_c);
712		amix_d->ops->commit_write(amix_d);
713	}
714}
715
716static void
717ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type)
718{
719	struct amixer *amix_d;
720	int i;
721
722	for (i = 0; i < 2; i++) {
723		amix_d = mixer->amixers[type*CHN_NUM+i];
724		amix_d->ops->set_sum(amix_d, NULL);
725		amix_d->ops->commit_write(amix_d);
726	}
727}
728
729static int ct_mixer_get_resources(struct ct_mixer *mixer)
730{
731	struct sum_mgr *sum_mgr;
732	struct sum *sum;
733	struct sum_desc sum_desc = {0};
734	struct amixer_mgr *amixer_mgr;
735	struct amixer *amixer;
736	struct amixer_desc am_desc = {0};
737	int err;
738	int i;
739
740	/* Allocate sum resources for mixer obj */
741	sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
742	sum_desc.msr = mixer->atc->msr;
743	for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
744		err = sum_mgr->get_sum(sum_mgr, &sum_desc, &sum);
745		if (err) {
746			printk(KERN_ERR "ctxfi:Failed to get sum resources for "
747					  "front output!\n");
748			break;
749		}
750		mixer->sums[i] = sum;
751	}
752	if (err)
753		goto error1;
754
755	/* Allocate amixer resources for mixer obj */
756	amixer_mgr = (struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
757	am_desc.msr = mixer->atc->msr;
758	for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
759		err = amixer_mgr->get_amixer(amixer_mgr, &am_desc, &amixer);
760		if (err) {
761			printk(KERN_ERR "ctxfi:Failed to get amixer resources "
762			       "for mixer obj!\n");
763			break;
764		}
765		mixer->amixers[i] = amixer;
766	}
767	if (err)
768		goto error2;
769
770	return 0;
771
772error2:
773	for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
774		if (NULL != mixer->amixers[i]) {
775			amixer = mixer->amixers[i];
776			amixer_mgr->put_amixer(amixer_mgr, amixer);
777			mixer->amixers[i] = NULL;
778		}
779	}
780error1:
781	for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
782		if (NULL != mixer->sums[i]) {
783			sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
784			mixer->sums[i] = NULL;
785		}
786	}
787
788	return err;
789}
790
791static int ct_mixer_get_mem(struct ct_mixer **rmixer)
792{
793	struct ct_mixer *mixer;
794	int err;
795
796	*rmixer = NULL;
797	/* Allocate mem for mixer obj */
798	mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
799	if (!mixer)
800		return -ENOMEM;
801
802	mixer->amixers = kzalloc(sizeof(void *)*(NUM_CT_AMIXERS*CHN_NUM),
803				 GFP_KERNEL);
804	if (!mixer->amixers) {
805		err = -ENOMEM;
806		goto error1;
807	}
808	mixer->sums = kzalloc(sizeof(void *)*(NUM_CT_SUMS*CHN_NUM), GFP_KERNEL);
809	if (!mixer->sums) {
810		err = -ENOMEM;
811		goto error2;
812	}
813
814	*rmixer = mixer;
815	return 0;
816
817error2:
818	kfree(mixer->amixers);
819error1:
820	kfree(mixer);
821	return err;
822}
823
824static int ct_mixer_topology_build(struct ct_mixer *mixer)
825{
826	struct sum *sum;
827	struct amixer *amix_d, *amix_s;
828	enum CT_AMIXER_CTL i, j;
829
830	/* Build topology from destination to source */
831
832	/* Set up Master mixer */
833	for (i = AMIXER_MASTER_F, j = SUM_IN_F;
834					i <= AMIXER_MASTER_S; i++, j++) {
835		amix_d = mixer->amixers[i*CHN_NUM];
836		sum = mixer->sums[j*CHN_NUM];
837		amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
838		amix_d = mixer->amixers[i*CHN_NUM+1];
839		sum = mixer->sums[j*CHN_NUM+1];
840		amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
841	}
842
843	/* Set up Wave-out mixer */
844	for (i = AMIXER_WAVE_F, j = AMIXER_MASTER_F;
845					i <= AMIXER_WAVE_S; i++, j++) {
846		amix_d = mixer->amixers[i*CHN_NUM];
847		amix_s = mixer->amixers[j*CHN_NUM];
848		amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
849		amix_d = mixer->amixers[i*CHN_NUM+1];
850		amix_s = mixer->amixers[j*CHN_NUM+1];
851		amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
852	}
853
854	/* Set up S/PDIF-out mixer */
855	amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM];
856	amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM];
857	amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
858	amix_d = mixer->amixers[AMIXER_SPDIFO*CHN_NUM+1];
859	amix_s = mixer->amixers[AMIXER_MASTER_F*CHN_NUM+1];
860	amix_d->ops->setup(amix_d, &amix_s->rsc, INIT_VOL, NULL);
861
862	/* Set up PCM-in mixer */
863	for (i = AMIXER_PCM_F, j = SUM_IN_F; i <= AMIXER_PCM_S; i++, j++) {
864		amix_d = mixer->amixers[i*CHN_NUM];
865		sum = mixer->sums[j*CHN_NUM];
866		amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
867		amix_d = mixer->amixers[i*CHN_NUM+1];
868		sum = mixer->sums[j*CHN_NUM+1];
869		amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
870	}
871
872	/* Set up Line-in mixer */
873	amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM];
874	sum = mixer->sums[SUM_IN_F*CHN_NUM];
875	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
876	amix_d = mixer->amixers[AMIXER_LINEIN*CHN_NUM+1];
877	sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
878	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
879
880	/* Set up Mic-in mixer */
881	amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM];
882	sum = mixer->sums[SUM_IN_F*CHN_NUM];
883	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
884	amix_d = mixer->amixers[AMIXER_MIC*CHN_NUM+1];
885	sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
886	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
887
888	/* Set up S/PDIF-in mixer */
889	amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM];
890	sum = mixer->sums[SUM_IN_F*CHN_NUM];
891	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
892	amix_d = mixer->amixers[AMIXER_SPDIFI*CHN_NUM+1];
893	sum = mixer->sums[SUM_IN_F*CHN_NUM+1];
894	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
895
896	/* Set up Master recording mixer */
897	amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM];
898	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
899	amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
900	amix_d = mixer->amixers[AMIXER_MASTER_F_C*CHN_NUM+1];
901	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
902	amix_d->ops->setup(amix_d, &sum->rsc, INIT_VOL, NULL);
903
904	/* Set up PCM-in recording mixer */
905	amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM];
906	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
907	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
908	amix_d = mixer->amixers[AMIXER_PCM_F_C*CHN_NUM+1];
909	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
910	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
911
912	/* Set up Line-in recording mixer */
913	amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM];
914	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
915	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
916	amix_d = mixer->amixers[AMIXER_LINEIN_C*CHN_NUM+1];
917	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
918	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
919
920	/* Set up Mic-in recording mixer */
921	amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM];
922	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
923	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
924	amix_d = mixer->amixers[AMIXER_MIC_C*CHN_NUM+1];
925	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
926	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
927
928	/* Set up S/PDIF-in recording mixer */
929	amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM];
930	sum = mixer->sums[SUM_IN_F_C*CHN_NUM];
931	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
932	amix_d = mixer->amixers[AMIXER_SPDIFI_C*CHN_NUM+1];
933	sum = mixer->sums[SUM_IN_F_C*CHN_NUM+1];
934	amix_d->ops->setup(amix_d, NULL, INIT_VOL, sum);
935
936	return 0;
937}
938
939static int mixer_set_input_port(struct amixer *amixer, struct rsc *rsc)
940{
941	amixer->ops->set_input(amixer, rsc);
942	amixer->ops->commit_write(amixer);
943
944	return 0;
945}
946
947static enum CT_AMIXER_CTL port_to_amixer(enum MIXER_PORT_T type)
948{
949	switch (type) {
950	case MIX_WAVE_FRONT:	return AMIXER_WAVE_F;
951	case MIX_WAVE_SURROUND:	return AMIXER_WAVE_S;
952	case MIX_WAVE_CENTLFE:	return AMIXER_WAVE_C;
953	case MIX_WAVE_REAR:	return AMIXER_WAVE_R;
954	case MIX_PCMO_FRONT:	return AMIXER_MASTER_F_C;
955	case MIX_SPDIF_OUT:	return AMIXER_SPDIFO;
956	case MIX_LINE_IN:	return AMIXER_LINEIN;
957	case MIX_MIC_IN:	return AMIXER_MIC;
958	case MIX_SPDIF_IN:	return AMIXER_SPDIFI;
959	case MIX_PCMI_FRONT:	return AMIXER_PCM_F;
960	case MIX_PCMI_SURROUND:	return AMIXER_PCM_S;
961	case MIX_PCMI_CENTLFE:	return AMIXER_PCM_C;
962	case MIX_PCMI_REAR:	return AMIXER_PCM_R;
963	default: 		return 0;
964	}
965}
966
967static int mixer_get_output_ports(struct ct_mixer *mixer,
968				  enum MIXER_PORT_T type,
969				  struct rsc **rleft, struct rsc **rright)
970{
971	enum CT_AMIXER_CTL amix = port_to_amixer(type);
972
973	if (NULL != rleft)
974		*rleft = &((struct amixer *)mixer->amixers[amix*CHN_NUM])->rsc;
975
976	if (NULL != rright)
977		*rright =
978			&((struct amixer *)mixer->amixers[amix*CHN_NUM+1])->rsc;
979
980	return 0;
981}
982
983static int mixer_set_input_left(struct ct_mixer *mixer,
984				enum MIXER_PORT_T type, struct rsc *rsc)
985{
986	enum CT_AMIXER_CTL amix = port_to_amixer(type);
987
988	mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
989	amix = get_recording_amixer(amix);
990	if (amix < NUM_CT_AMIXERS)
991		mixer_set_input_port(mixer->amixers[amix*CHN_NUM], rsc);
992
993	return 0;
994}
995
996static int
997mixer_set_input_right(struct ct_mixer *mixer,
998		      enum MIXER_PORT_T type, struct rsc *rsc)
999{
1000	enum CT_AMIXER_CTL amix = port_to_amixer(type);
1001
1002	mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1003	amix = get_recording_amixer(amix);
1004	if (amix < NUM_CT_AMIXERS)
1005		mixer_set_input_port(mixer->amixers[amix*CHN_NUM+1], rsc);
1006
1007	return 0;
1008}
1009
1010#ifdef CONFIG_PM
1011static int mixer_resume(struct ct_mixer *mixer)
1012{
1013	int i, state;
1014	struct amixer *amixer;
1015
1016	/* resume topology and volume gain. */
1017	for (i = 0; i < NUM_CT_AMIXERS*CHN_NUM; i++) {
1018		amixer = mixer->amixers[i];
1019		amixer->ops->commit_write(amixer);
1020	}
1021
1022	/* resume switch state. */
1023	for (i = SWH_MIXER_START; i <= SWH_MIXER_END; i++) {
1024		state = get_switch_state(mixer, i);
1025		do_switch(mixer->atc, i, state);
1026	}
1027
1028	return 0;
1029}
1030#endif
1031
1032int ct_mixer_destroy(struct ct_mixer *mixer)
1033{
1034	struct sum_mgr *sum_mgr = (struct sum_mgr *)mixer->atc->rsc_mgrs[SUM];
1035	struct amixer_mgr *amixer_mgr =
1036			(struct amixer_mgr *)mixer->atc->rsc_mgrs[AMIXER];
1037	struct amixer *amixer;
1038	int i = 0;
1039
1040	/* Release amixer resources */
1041	for (i = 0; i < (NUM_CT_AMIXERS * CHN_NUM); i++) {
1042		if (NULL != mixer->amixers[i]) {
1043			amixer = mixer->amixers[i];
1044			amixer_mgr->put_amixer(amixer_mgr, amixer);
1045		}
1046	}
1047
1048	/* Release sum resources */
1049	for (i = 0; i < (NUM_CT_SUMS * CHN_NUM); i++) {
1050		if (NULL != mixer->sums[i])
1051			sum_mgr->put_sum(sum_mgr, (struct sum *)mixer->sums[i]);
1052	}
1053
1054	/* Release mem assigned to mixer object */
1055	kfree(mixer->sums);
1056	kfree(mixer->amixers);
1057	kfree(mixer);
1058
1059	return 0;
1060}
1061
1062int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer)
1063{
1064	struct ct_mixer *mixer;
1065	int err;
1066
1067	*rmixer = NULL;
1068
1069	/* Allocate mem for mixer obj */
1070	err = ct_mixer_get_mem(&mixer);
1071	if (err)
1072		return err;
1073
1074	mixer->switch_state = 0;
1075	mixer->atc = atc;
1076	/* Set operations */
1077	mixer->get_output_ports = mixer_get_output_ports;
1078	mixer->set_input_left = mixer_set_input_left;
1079	mixer->set_input_right = mixer_set_input_right;
1080#ifdef CONFIG_PM
1081	mixer->resume = mixer_resume;
1082#endif
1083
1084	/* Allocate chip resources for mixer obj */
1085	err = ct_mixer_get_resources(mixer);
1086	if (err)
1087		goto error;
1088
1089	/* Build internal mixer topology */
1090	ct_mixer_topology_build(mixer);
1091
1092	*rmixer = mixer;
1093
1094	return 0;
1095
1096error:
1097	ct_mixer_destroy(mixer);
1098	return err;
1099}
1100
1101int ct_alsa_mix_create(struct ct_atc *atc,
1102		       enum CTALSADEVS device,
1103		       const char *device_name)
1104{
1105	int err;
1106
1107	/* Create snd kcontrol instances on demand */
1108	/* vol_ctl.device = swh_ctl.device = device; */ /* better w/ device 0 */
1109	err = ct_mixer_kcontrols_create((struct ct_mixer *)atc->mixer);
1110	if (err)
1111		return err;
1112
1113	strcpy(atc->card->mixername, device_name);
1114
1115	return 0;
1116}
1117