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