vserver 1.9.3
[linux-2.6.git] / sound / pci / ice1712 / aureon.c
1 /*
2  *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
3  *
4  *   Lowlevel functions for Terratec Aureon cards
5  *
6  *      Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  *
22  *
23  * NOTES:
24  *
25  * - we reuse the akm4xxx_t record for storing the wm8770 codec data.
26  *   both wm and akm codecs are pretty similar, so we can integrate
27  *   both controls in the future, once if wm codecs are reused in
28  *   many boards.
29  *
30  * - writing over SPI is implemented but reading is not yet.
31  *   the SPDIF-in channel status, etc. can be read from CS chip.
32  *
33  * - DAC digital volumes are not implemented in the mixer.
34  *   if they show better response than DAC analog volumes, we can use them
35  *   instead.
36  *
37  * - Aureon boards are equipped with AC97 codec, too.  it's used to do
38  *   the analog mixing but not easily controllable (it's not connected
39  *   directly from envy24ht chip).  so let's leave it as it is.
40  *
41  *
42  *   Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
43  *      Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
44  *
45  *   version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
46  *       added 64x/128x oversampling switch (should be 64x only for 96khz)
47  *       fixed some recording labels (still need to check the rest)
48  *       recording is working probably thanks to correct wm8770 initialization
49  *
50  *   version 0.5: Initial release:
51  *           working: analog output, mixer, headphone amplifier switch
52  *       not working: prety much everything else, at least i could verify that
53  *                    we have no digital output, no capture, pretty bad clicks and poops
54  *                    on mixer switch and other coll stuff.
55  *
56  * - Prodigy boards are equipped with AC97 STAC9744 chip , too.  it's used to do
57  *   the analog mixing but not easily controllable (it's not connected
58  *   directly from envy24ht chip).  so let's leave it as it is.
59  *
60  */      
61
62 #include <sound/driver.h>
63 #include <asm/io.h>
64 #include <linux/delay.h>
65 #include <linux/interrupt.h>
66 #include <linux/init.h>
67 #include <linux/slab.h>
68 #include <sound/core.h>
69
70 #include "ice1712.h"
71 #include "envy24ht.h"
72 #include "aureon.h"
73
74 /* WM8770 registers */
75 #define WM_DAC_ATTEN            0x00    /* DAC1-8 analog attenuation */
76 #define WM_DAC_MASTER_ATTEN     0x08    /* DAC master analog attenuation */
77 #define WM_DAC_DIG_ATTEN        0x09    /* DAC1-8 digital attenuation */
78 #define WM_DAC_DIG_MASTER_ATTEN 0x11    /* DAC master digital attenuation */
79 #define WM_PHASE_SWAP           0x12    /* DAC phase */
80 #define WM_DAC_CTRL1            0x13    /* DAC control bits */
81 #define WM_MUTE                 0x14    /* mute controls */
82 #define WM_DAC_CTRL2            0x15    /* de-emphasis and zefo-flag */
83 #define WM_INT_CTRL             0x16    /* interface control */
84 #define WM_MASTER               0x17    /* master clock and mode */
85 #define WM_POWERDOWN            0x18    /* power-down controls */
86 #define WM_ADC_GAIN             0x19    /* ADC gain L(19)/R(1a) */
87 #define WM_ADC_MUX              0x1b    /* input MUX */
88 #define WM_OUT_MUX1             0x1c    /* output MUX */
89 #define WM_OUT_MUX2             0x1e    /* output MUX */
90 #define WM_RESET                0x1f    /* software reset */
91
92
93 /*
94  * write data in the SPI mode
95  */
96 static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
97 {
98         unsigned int tmp;
99         unsigned int cscs;
100         int i;
101
102         tmp = snd_ice1712_gpio_read(ice);
103
104         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
105                 cscs = PRODIGY_CS8415_CS;
106         else
107                 cscs = AUREON_CS8415_CS;
108
109         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_WM_DATA|AUREON_WM_CLK|
110                                          AUREON_WM_CS|cscs));
111         tmp |= AUREON_WM_RW;
112         tmp &= ~cs;
113         snd_ice1712_gpio_write(ice, tmp);
114         udelay(1);
115
116         for (i = bits - 1; i >= 0; i--) {
117                 tmp &= ~AUREON_WM_CLK;
118                 snd_ice1712_gpio_write(ice, tmp);
119                 udelay(1);
120                 if (data & (1 << i))
121                         tmp |= AUREON_WM_DATA;
122                 else
123                         tmp &= ~AUREON_WM_DATA;
124                 snd_ice1712_gpio_write(ice, tmp);
125                 udelay(1);
126                 tmp |= AUREON_WM_CLK;
127                 snd_ice1712_gpio_write(ice, tmp);
128                 udelay(1);
129         }
130
131         tmp &= ~AUREON_WM_CLK;
132         tmp |= cs;
133         snd_ice1712_gpio_write(ice, tmp);
134         udelay(1);
135         tmp |= AUREON_WM_CLK;
136         snd_ice1712_gpio_write(ice, tmp);
137         udelay(1);
138 }
139      
140
141 /*
142  * get the current register value of WM codec
143  */
144 static unsigned short wm_get(ice1712_t *ice, int reg)
145 {
146         reg <<= 1;
147         return ((unsigned short)ice->akm[0].images[reg] << 8) |
148                 ice->akm[0].images[reg + 1];
149 }
150
151 /*
152  * set the register value of WM codec
153  */
154 static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
155 {
156         aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
157 }
158
159 /*
160  * set the register value of WM codec and remember it
161  */
162 static void wm_put(ice1712_t *ice, int reg, unsigned short val)
163 {
164         wm_put_nocache(ice, reg, val);
165         reg <<= 1;
166         ice->akm[0].images[reg] = val >> 8;
167         ice->akm[0].images[reg + 1] = val;
168 }
169
170 /*
171  */
172 static int aureon_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
173 {
174         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
175         uinfo->count = 1;
176         uinfo->value.integer.min = 0;
177         uinfo->value.integer.max = 1;
178         return 0;
179 }
180
181 /*
182  * DAC mute control
183  */
184 #define wm_dac_mute_info        aureon_mono_bool_info
185
186 static int wm_dac_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
187 {
188         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
189         unsigned short val;
190
191         down(&ice->gpio_mutex);
192         val = wm_get(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_MUTE);
193         ucontrol->value.integer.value[0] = ~val>>4 & 0x1;
194         up(&ice->gpio_mutex);
195         return 0;
196 }
197
198 static int wm_dac_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
199 {
200         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
201         unsigned short new, old;
202         int change;
203
204         snd_ice1712_save_gpio_status(ice);
205         old = wm_get(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_MUTE);
206         new = (~ucontrol->value.integer.value[0]<<4&0x10) | (old&~0x10);
207         change = (new != old);
208         if (change)
209                 wm_put(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_MUTE, new);
210         snd_ice1712_restore_gpio_status(ice);
211
212         return change;
213 }
214
215 /*
216  * DAC volume attenuation mixer control
217  */
218 static int wm_dac_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
219 {
220         int voices = kcontrol->private_value >> 8;
221         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
222         uinfo->count = voices;
223         uinfo->value.integer.min = 0;           /* mute (-101dB) */
224         uinfo->value.integer.max = 101;         /* 0dB */
225         return 0;
226 }
227
228 static int wm_dac_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
229 {
230         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
231         int i, idx, ofs, voices;
232         unsigned short vol;
233
234         voices = kcontrol->private_value >> 8;
235         ofs = kcontrol->private_value & 0xff;
236         down(&ice->gpio_mutex);
237         for (i = 0; i < voices; i++) {
238                 idx  = WM_DAC_ATTEN + ofs + i;
239                 vol = wm_get(ice, idx) & 0x7f;
240                 if (vol <= 0x1a)
241                         ucontrol->value.integer.value[i] = 0;
242                 else
243                         ucontrol->value.integer.value[i] = vol - 0x1a;
244         }
245         up(&ice->gpio_mutex);
246         return 0;
247 }
248
249 static int wm_dac_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
250 {
251         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
252         int i, idx, ofs, voices;
253         unsigned short ovol, nvol;
254         int change = 0;
255
256         voices = kcontrol->private_value >> 8;
257         ofs = kcontrol->private_value & 0xff;
258         snd_ice1712_save_gpio_status(ice);
259         for (i = 0; i < voices; i++) {
260                 idx  = WM_DAC_ATTEN + ofs + i;
261                 nvol = ucontrol->value.integer.value[i] + 0x1a;
262                 ovol = wm_get(ice, idx) & 0x7f;
263                 if (ovol != nvol) {
264                         if (nvol <= 0x1a && ovol <= 0x1a)
265                                 continue;
266                         wm_put(ice, idx, nvol | 0x80); /* zero-detect, prelatch */
267                         wm_put_nocache(ice, idx, nvol | 0x180); /* update */
268                         change = 1;
269                 }
270         }
271         snd_ice1712_restore_gpio_status(ice);
272         return change;
273 }
274
275 /* digital master volume */
276 #define MASTER_0dB 0xff
277 #define MASTER_RES 128  /* -64dB */
278 #define MASTER_MIN (MASTER_0dB - MASTER_RES)
279 static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
280 {
281         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
282         uinfo->count = 1;
283         uinfo->value.integer.min = 0;           /* mute (-64dB) */
284         uinfo->value.integer.max = MASTER_RES;  /* 0dB */
285         return 0;
286 }
287
288 static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
289 {
290         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
291         unsigned short val;
292
293         down(&ice->gpio_mutex);
294         val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
295         val = val > MASTER_MIN ? (val - MASTER_MIN) : 0;
296         ucontrol->value.integer.value[0] = val;
297         up(&ice->gpio_mutex);
298         return 0;
299 }
300
301 static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
302 {
303         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
304         unsigned short ovol, nvol;
305         int change = 0;
306
307         snd_ice1712_save_gpio_status(ice);
308         nvol = ucontrol->value.integer.value[0];
309         nvol = (nvol ? (nvol + MASTER_MIN) : 0) & 0xff;
310         ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
311         if (ovol != nvol) {
312                 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
313                 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
314                 change = 1;
315         }
316         snd_ice1712_restore_gpio_status(ice);
317         return change;
318 }
319
320 /*
321  * ADC mute control
322  */
323 static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
324 {
325         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
326         uinfo->count = 2;
327         uinfo->value.integer.min = 0;
328         uinfo->value.integer.max = 1;
329         return 0;
330 }
331
332 static int wm_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
333 {
334         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
335         unsigned short val;
336         int i;
337
338         down(&ice->gpio_mutex);
339         for (i = 0; i < 2; i++) {
340                 val = wm_get(ice, WM_ADC_GAIN + i);
341                 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
342         }
343         up(&ice->gpio_mutex);
344         return 0;
345 }
346
347 static int wm_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
348 {
349         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
350         unsigned short new, old;
351         int i, change = 0;
352
353         snd_ice1712_save_gpio_status(ice);
354         for (i = 0; i < 2; i++) {
355                 old = wm_get(ice, WM_ADC_GAIN + i);
356                 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
357                 if (new != old) {
358                         wm_put(ice, snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)+WM_ADC_GAIN, new);
359                         change = 1;
360                 }
361         }
362         snd_ice1712_restore_gpio_status(ice);
363
364         return change;
365 }
366
367 /*
368  * ADC gain mixer control
369  */
370 static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
371 {
372         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
373         uinfo->count = 2;
374         uinfo->value.integer.min = 0;           /* -12dB */
375         uinfo->value.integer.max = 0x1f;        /* 19dB */
376         return 0;
377 }
378
379 static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
380 {
381         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
382         int i, idx;
383         unsigned short vol;
384
385         down(&ice->gpio_mutex);
386         for (i = 0; i < 2; i++) {
387                 idx = WM_ADC_GAIN + i;
388                 vol = wm_get(ice, idx) & 0x1f;
389                 ucontrol->value.integer.value[i] = vol;
390         }
391         up(&ice->gpio_mutex);
392         return 0;
393 }
394
395 static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
396 {
397         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
398         int i, idx;
399         unsigned short ovol, nvol;
400         int change = 0;
401
402         snd_ice1712_save_gpio_status(ice);
403         for (i = 0; i < 2; i++) {
404                 idx  = WM_ADC_GAIN + i;
405                 nvol = ucontrol->value.integer.value[i];
406                 ovol = wm_get(ice, idx);
407                 if ((ovol & 0x1f) != nvol) {
408                         wm_put(ice, idx, nvol | (ovol & ~0x1f));
409                         change = 1;
410                 }
411         }
412         snd_ice1712_restore_gpio_status(ice);
413         return change;
414 }
415
416 /*
417  * ADC input mux mixer control
418  */
419 static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
420 {
421         static char *texts[] = {
422                 "CD",           //AIN1
423                 "Aux",          //AIN2
424                 "Line",         //AIN3
425                 "Mic",          //AIN4
426                 "AC97"          //AIN5
427         };
428         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
429         uinfo->count = 2;
430         uinfo->value.enumerated.items = 5;
431         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
432                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
433         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
434         return 0;
435 }
436
437 static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
438 {
439         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
440         unsigned short val;
441
442         down(&ice->gpio_mutex);
443         val = wm_get(ice, WM_ADC_MUX);
444         ucontrol->value.integer.value[0] = val & 7;
445         ucontrol->value.integer.value[1] = (val >> 4) & 7;
446         up(&ice->gpio_mutex);
447         return 0;
448 }
449
450 static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
451 {
452         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
453         unsigned short oval, nval;
454         int change;
455
456         snd_ice1712_save_gpio_status(ice);
457         oval = wm_get(ice, WM_ADC_MUX);
458         nval = oval & ~0x77;
459         nval |= ucontrol->value.integer.value[0] & 7;
460         nval |= (ucontrol->value.integer.value[1] & 7) << 4;
461         change = (oval != nval);
462         if (change)
463                 wm_put(ice, WM_ADC_MUX, nval);
464         snd_ice1712_restore_gpio_status(ice);
465         return 0;
466 }
467
468 /*
469  * Headphone Amplifier
470  */
471 static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
472 {
473         unsigned int tmp, tmp2;
474
475         tmp2 = tmp = snd_ice1712_gpio_read(ice);
476         if (enable)
477                 tmp |= AUREON_HP_SEL;
478         else
479                 tmp &= ~ AUREON_HP_SEL;
480         if (tmp != tmp2) {
481                 snd_ice1712_gpio_write(ice, tmp);
482                 return 1;
483         }
484         return 0;
485 }
486
487 static int aureon_get_headphone_amp(ice1712_t *ice)
488 {
489         unsigned int tmp = snd_ice1712_gpio_read(ice);
490
491         return ( tmp & AUREON_HP_SEL )!= 0;
492 }
493
494 #define aureon_hpamp_info       aureon_mono_bool_info
495
496 static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
497 {
498         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
499
500         ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
501         return 0;
502 }
503
504
505 static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
506 {
507         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
508
509         return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
510 }
511
512 /*
513  * Deemphasis
514  */
515
516 #define aureon_deemp_info       aureon_mono_bool_info
517
518 static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
519 {
520         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
521         ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
522         return 0;
523 }
524
525 static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
526 {
527         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
528         int temp, temp2;
529         temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
530         if (ucontrol->value.integer.value[0])
531                 temp |= 0xf;
532         else
533                 temp &= ~0xf;
534         if (temp != temp2) {
535                 wm_put(ice, WM_DAC_CTRL2, temp);
536                 return 1;
537         }
538         return 0;
539 }
540
541 /*
542  * ADC Oversampling
543  */
544 static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
545 {
546         static char *texts[2] = { "128x", "64x" };
547
548         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
549         uinfo->count = 1;
550         uinfo->value.enumerated.items = 2;
551
552         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
553                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
554         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
555
556         return 0;
557 }
558
559 static int aureon_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
560 {
561         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
562         ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
563         return 0;
564 }
565
566 static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
567 {
568         int temp, temp2;
569         ice1712_t *ice = snd_kcontrol_chip(kcontrol);
570
571         temp2 = temp = wm_get(ice, WM_MASTER);
572
573         if (ucontrol->value.enumerated.item[0])
574                 temp |= 0x8;
575         else
576                 temp &= ~0x8;
577
578         if (temp != temp2) {
579                 wm_put(ice, WM_MASTER, temp);
580                 return 1;
581         }
582         return 0;
583 }
584
585 /*
586  * mixers
587  */
588
589 static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
590         {
591                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
592                 .name = "Front Playback Volume",
593                 .info = wm_dac_vol_info,
594                 .get = wm_dac_vol_get,
595                 .put = wm_dac_vol_put,
596                 .private_value = (2 << 8) | 0
597         },
598         {
599                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
600                 .name = "Rear Playback Volume",
601                 .info = wm_dac_vol_info,
602                 .get = wm_dac_vol_get,
603                 .put = wm_dac_vol_put,
604                 .private_value = (2 << 8) | 2
605         },
606         {
607                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
608                 .name = "Center Playback Volume",
609                 .info = wm_dac_vol_info,
610                 .get = wm_dac_vol_get,
611                 .put = wm_dac_vol_put,
612                 .private_value = (1 << 8) | 4
613         },
614         {
615                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
616                 .name = "LFE Playback Volume",
617                 .info = wm_dac_vol_info,
618                 .get = wm_dac_vol_get,
619                 .put = wm_dac_vol_put,
620                 .private_value = (1 << 8) | 5
621         },
622         {
623                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
624                 .name = "Side Playback Volume",
625                 .info = wm_dac_vol_info,
626                 .get = wm_dac_vol_get,
627                 .put = wm_dac_vol_put,
628                 .private_value = (2 << 8) | 6
629         }
630 };
631
632 static snd_kcontrol_new_t wm_controls[] __devinitdata = {
633         {
634                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
635                 .name = "Master Playback Switch",
636                 .info = wm_dac_mute_info,
637                 .get = wm_dac_mute_get,
638                 .put = wm_dac_mute_put,
639         },
640         {
641                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
642                 .name = "Master Playback Volume",
643                 .info = wm_master_vol_info,
644                 .get = wm_master_vol_get,
645                 .put = wm_master_vol_put,
646         },
647         {
648                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
649                 .name = "Capture Switch",
650                 .info = wm_adc_mute_info,
651                 .get = wm_adc_mute_get,
652                 .put = wm_adc_mute_put,
653
654         },
655         {
656                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
657                 .name = "Capture Volume",
658                 .info = wm_adc_vol_info,
659                 .get = wm_adc_vol_get,
660                 .put = wm_adc_vol_put,
661         },
662         {
663                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
664                 .name = "Capture Source",
665                 .info = wm_adc_mux_info,
666                 .get = wm_adc_mux_get,
667                 .put = wm_adc_mux_put,
668         },
669         {
670                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
671                 .name = "Headphone Amplifier Switch",
672                 .info = aureon_hpamp_info,
673                 .get = aureon_hpamp_get,
674                 .put = aureon_hpamp_put
675         },
676         {
677                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
678                 .name = "DAC Deemphasis Switch",
679                 .info = aureon_deemp_info,
680                 .get = aureon_deemp_get,
681                 .put = aureon_deemp_put
682         },
683         {
684                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
685                 .name = "ADC Oversampling",
686                 .info = aureon_oversampling_info,
687                 .get = aureon_oversampling_get,
688                 .put = aureon_oversampling_put
689         },
690 };
691
692
693 static int __devinit aureon_add_controls(ice1712_t *ice)
694 {
695         unsigned int i, counts;
696         int err;
697
698         counts = ARRAY_SIZE(aureon_dac_controls);
699         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
700                 counts--; /* no side */
701         for (i = 0; i < counts; i++) {
702                 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
703                 if (err < 0)
704                         return err;
705         }
706
707         for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
708                 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
709                 if (err < 0)
710                         return err;
711         }
712         return 0;
713 }
714
715
716 /*
717  * initialize the chip
718  */
719 static int __devinit aureon_init(ice1712_t *ice)
720 {
721         static unsigned short wm_inits_aureon[] = {
722                 /* These come first to reduce init pop noise */
723                 0x1b, 0x000,            /* ADC Mux */
724                 0x1c, 0x009,            /* Out Mux1 */
725                 0x1d, 0x009,            /* Out Mux2 */
726
727                 0x18, 0x000,            /* All power-up */
728
729                 0x16, 0x122,            /* I2S, normal polarity, 24bit */
730                 0x17, 0x022,            /* 256fs, slave mode */
731                 0x00, 0,                /* DAC1 analog mute */
732                 0x01, 0,                /* DAC2 analog mute */
733                 0x02, 0,                /* DAC3 analog mute */
734                 0x03, 0,                /* DAC4 analog mute */
735                 0x04, 0,                /* DAC5 analog mute */
736                 0x05, 0,                /* DAC6 analog mute */
737                 0x06, 0,                /* DAC7 analog mute */
738                 0x07, 0,                /* DAC8 analog mute */
739                 0x08, 0x100,            /* master analog mute */
740                 0x09, 0xff,             /* DAC1 digital full */
741                 0x0a, 0xff,             /* DAC2 digital full */
742                 0x0b, 0xff,             /* DAC3 digital full */
743                 0x0c, 0xff,             /* DAC4 digital full */
744                 0x0d, 0xff,             /* DAC5 digital full */
745                 0x0e, 0xff,             /* DAC6 digital full */
746                 0x0f, 0xff,             /* DAC7 digital full */
747                 0x10, 0xff,             /* DAC8 digital full */
748                 0x11, 0x1ff,            /* master digital full */
749                 0x12, 0x000,            /* phase normal */
750                 0x13, 0x090,            /* unmute DAC L/R */
751                 0x14, 0x000,            /* all unmute */
752                 0x15, 0x000,            /* no deemphasis, no ZFLG */
753                 0x19, 0x000,            /* -12dB ADC/L */
754                 0x1a, 0x000,            /* -12dB ADC/R */
755                 (unsigned short)-1
756         };
757         static unsigned short wm_inits_prodigy[] = {
758
759                 /* These come first to reduce init pop noise */
760                 0x1b, 0x000,            /* ADC Mux */
761                 0x1c, 0x009,            /* Out Mux1 */
762                 0x1d, 0x009,            /* Out Mux2 */
763
764                 0x18, 0x000,            /* All power-up */
765
766                 0x16, 0x022,            /* I2S, normal polarity, 24bit, high-pass on */
767                 0x17, 0x006,            /* 128fs, slave mode */
768
769                 0x00, 0,                /* DAC1 analog mute */
770                 0x01, 0,                /* DAC2 analog mute */
771                 0x02, 0,                /* DAC3 analog mute */
772                 0x03, 0,                /* DAC4 analog mute */
773                 0x04, 0,                /* DAC5 analog mute */
774                 0x05, 0,                /* DAC6 analog mute */
775                 0x06, 0,                /* DAC7 analog mute */
776                 0x07, 0,                /* DAC8 analog mute */
777                 0x08, 0x100,            /* master analog mute */
778
779                 0x09, 0x7f,             /* DAC1 digital full */
780                 0x0a, 0x7f,             /* DAC2 digital full */
781                 0x0b, 0x7f,             /* DAC3 digital full */
782                 0x0c, 0x7f,             /* DAC4 digital full */
783                 0x0d, 0x7f,             /* DAC5 digital full */
784                 0x0e, 0x7f,             /* DAC6 digital full */
785                 0x0f, 0x7f,             /* DAC7 digital full */
786                 0x10, 0x7f,             /* DAC8 digital full */
787                 0x11, 0x1FF,            /* master digital full */
788
789                 0x12, 0x000,            /* phase normal */
790                 0x13, 0x090,            /* unmute DAC L/R */
791                 0x14, 0x000,            /* all unmute */
792                 0x15, 0x000,            /* no deemphasis, no ZFLG */
793
794                 0x19, 0x000,            /* -12dB ADC/L */
795                 0x1a, 0x000,            /* -12dB ADC/R */
796                 (unsigned short)-1
797
798         };
799         static unsigned short cs_inits[] = {
800                 0x0441, /* RUN */
801                 0x0100, /* no mute */
802                 0x0200, /* */
803                 0x0600, /* slave, 24bit */
804                 (unsigned short)-1
805         };
806         unsigned int tmp;
807         unsigned short *p;
808         unsigned int cscs;
809
810         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
811                 ice->num_total_dacs = 6;
812                 ice->num_total_adcs = 2;
813         } else {
814                 /* aureon 7.1 and prodigy 7.1 */
815                 ice->num_total_dacs = 8;
816                 ice->num_total_adcs = 2;
817         }
818
819         /* to remeber the register values */
820         ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
821         if (! ice->akm)
822                 return -ENOMEM;
823         ice->akm_codecs = 1;
824
825         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
826                 cscs = PRODIGY_CS8415_CS;
827         else
828                 cscs = AUREON_CS8415_CS;
829
830         snd_ice1712_gpio_set_dir(ice, 0xbfffff); /* fix this for the time being */
831
832         /* reset the wm codec as the SPI mode */
833         snd_ice1712_save_gpio_status(ice);
834         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|
835                                          cscs|AUREON_HP_SEL));
836         tmp = snd_ice1712_gpio_read(ice);
837         tmp &= ~AUREON_WM_RESET;
838         snd_ice1712_gpio_write(ice, tmp);
839         udelay(1);
840         tmp |= AUREON_WM_CS | cscs;
841         snd_ice1712_gpio_write(ice, tmp);
842         udelay(1);
843         tmp |= AUREON_WM_RESET;
844         snd_ice1712_gpio_write(ice, tmp);
845         udelay(1);
846
847         /* initialize WM8770 codec */
848         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
849                 p = wm_inits_prodigy;
850         else
851                 p = wm_inits_aureon;
852         for (; *p != (unsigned short)-1; p += 2)
853                 wm_put(ice, p[0], p[1]);
854
855         /* initialize CS8415A codec */
856         for (p = cs_inits; *p != (unsigned short)-1; p++)
857                 aureon_spi_write(ice, cscs,
858                                  *p | 0x200000, 24);
859
860         aureon_set_headphone_amp(ice, 1);
861
862         snd_ice1712_restore_gpio_status(ice);
863
864         return 0;
865 }
866
867
868 /*
869  * Aureon boards don't provide the EEPROM data except for the vendor IDs.
870  * hence the driver needs to sets up it properly.
871  */
872
873 static unsigned char aureon51_eeprom[] __devinitdata = {
874         0x0a,   /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
875         0x80,   /* ACLINK: I2S */
876         0xf8,   /* I2S: vol, 96k, 24bit, 192k */
877         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
878         0xff,   /* GPIO_DIR */
879         0xff,   /* GPIO_DIR1 */
880         0xbf,   /* GPIO_DIR2 */
881         0xff,   /* GPIO_MASK */
882         0xff,   /* GPIO_MASK1 */
883         0xff,   /* GPIO_MASK2 */
884         0x00,   /* GPIO_STATE */
885         0x00,   /* GPIO_STATE1 */
886         0x00,   /* GPIO_STATE2 */
887 };
888
889 static unsigned char aureon71_eeprom[] __devinitdata = {
890         0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
891         0x80,   /* ACLINK: I2S */
892         0xf8,   /* I2S: vol, 96k, 24bit, 192k */
893         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
894         0xff,   /* GPIO_DIR */
895         0xff,   /* GPIO_DIR1 */
896         0xbf,   /* GPIO_DIR2 */
897         0x00,   /* GPIO_MASK */
898         0x00,   /* GPIO_MASK1 */
899         0x00,   /* GPIO_MASK2 */
900         0x00,   /* GPIO_STATE */
901         0x00,   /* GPIO_STATE1 */
902         0x00,   /* GPIO_STATE2 */
903 };
904
905 static unsigned char prodigy71_eeprom[] __devinitdata = {
906         0x0b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
907         0x80,   /* ACLINK: I2S */
908         0xf8,   /* I2S: vol, 96k, 24bit, 192k */
909         0xc3,   /* SPDIF: out-en, out-int, spdif-in */
910         0xff,   /* GPIO_DIR */
911         0xff,   /* GPIO_DIR1 */
912         0xbf,   /* GPIO_DIR2 */
913         0x00,   /* GPIO_MASK */
914         0x00,   /* GPIO_MASK1 */
915         0x00,   /* GPIO_MASK2 */
916         0x00,   /* GPIO_STATE */
917         0x00,   /* GPIO_STATE1 */
918         0x00,   /* GPIO_STATE2 */
919 };
920
921 /* entry point */
922 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
923         {
924                 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
925                 .name = "Terratec Aureon 5.1-Sky",
926                 .model = "aureon51",
927                 .chip_init = aureon_init,
928                 .build_controls = aureon_add_controls,
929                 .eeprom_size = sizeof(aureon51_eeprom),
930                 .eeprom_data = aureon51_eeprom,
931                 .driver = "Aureon51",
932         },
933         {
934                 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
935                 .name = "Terratec Aureon 7.1-Space",
936                 .model = "aureon71",
937                 .chip_init = aureon_init,
938                 .build_controls = aureon_add_controls,
939                 .eeprom_size = sizeof(aureon71_eeprom),
940                 .eeprom_data = aureon71_eeprom,
941                 .driver = "Aureon71",
942         },
943         {
944                 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
945                 .name = "Terratec Aureon 7.1-Universe",
946                 /* model not needed - identical with 7.1-Space */
947                 .chip_init = aureon_init,
948                 .build_controls = aureon_add_controls,
949                 .eeprom_size = sizeof(aureon71_eeprom),
950                 .eeprom_data = aureon71_eeprom,
951                 .driver = "Aureon71",
952         },
953         {
954                 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
955                 .name = "Audiotrak Prodigy 7.1",
956                 .model = "prodigy71",
957                 .chip_init = aureon_init,
958                 .build_controls = aureon_add_controls,
959                 .eeprom_size = sizeof(prodigy71_eeprom),
960                 .eeprom_data = prodigy71_eeprom,
961                 .driver = "Prodigy71", /* should be identical with Aureon71 */
962         },
963         { } /* terminator */
964 };