Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 struct snd_akm4xxx 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  * - DAC digital volumes are not implemented in the mixer.
 31  *   if they show better response than DAC analog volumes, we can use them
 32  *   instead.
 33  *
 34  *   Lowlevel functions for AudioTrak Prodigy 7.1 (and possibly 192) cards
 35  *      Copyright (c) 2003 Dimitromanolakis Apostolos <apostol@cs.utoronto.ca>
 36  *
 37  *   version 0.82: Stable / not all features work yet (no communication with AC97 secondary)
 38  *       added 64x/128x oversampling switch (should be 64x only for 96khz)
 39  *       fixed some recording labels (still need to check the rest)
 40  *       recording is working probably thanks to correct wm8770 initialization
 41  *
 42  *   version 0.5: Initial release:
 43  *           working: analog output, mixer, headphone amplifier switch
 44  *       not working: prety much everything else, at least i could verify that
 45  *                    we have no digital output, no capture, pretty bad clicks and poops
 46  *                    on mixer switch and other coll stuff.
 47  *
 48  */      
 49 
 50 #include <asm/io.h>
 51 #include <linux/delay.h>
 52 #include <linux/interrupt.h>
 53 #include <linux/init.h>
 54 #include <linux/slab.h>
 55 #include <linux/mutex.h>
 56 
 57 #include <sound/core.h>
 58 
 59 #include "ice1712.h"
 60 #include "envy24ht.h"
 61 #include "aureon.h"
 62 #include <sound/tlv.h>
 63 
 64 /* AC97 register cache for Aureon */
 65 struct aureon_spec {
 66         unsigned short stac9744[64];
 67         unsigned int cs8415_mux;
 68         unsigned short master[2];
 69         unsigned short vol[8];
 70         unsigned char pca9554_out;
 71 };
 72 
 73 /* WM8770 registers */
 74 #define WM_DAC_ATTEN            0x00    /* DAC1-8 analog attenuation */
 75 #define WM_DAC_MASTER_ATTEN     0x08    /* DAC master analog attenuation */
 76 #define WM_DAC_DIG_ATTEN        0x09    /* DAC1-8 digital attenuation */
 77 #define WM_DAC_DIG_MASTER_ATTEN 0x11    /* DAC master digital attenuation */
 78 #define WM_PHASE_SWAP           0x12    /* DAC phase */
 79 #define WM_DAC_CTRL1            0x13    /* DAC control bits */
 80 #define WM_MUTE                 0x14    /* mute controls */
 81 #define WM_DAC_CTRL2            0x15    /* de-emphasis and zefo-flag */
 82 #define WM_INT_CTRL             0x16    /* interface control */
 83 #define WM_MASTER               0x17    /* master clock and mode */
 84 #define WM_POWERDOWN            0x18    /* power-down controls */
 85 #define WM_ADC_GAIN             0x19    /* ADC gain L(19)/R(1a) */
 86 #define WM_ADC_MUX              0x1b    /* input MUX */
 87 #define WM_OUT_MUX1             0x1c    /* output MUX */
 88 #define WM_OUT_MUX2             0x1e    /* output MUX */
 89 #define WM_RESET                0x1f    /* software reset */
 90 
 91 /* CS8415A registers */
 92 #define CS8415_CTRL1    0x01
 93 #define CS8415_CTRL2    0x02
 94 #define CS8415_QSUB             0x14
 95 #define CS8415_RATIO    0x1E
 96 #define CS8415_C_BUFFER 0x20
 97 #define CS8415_ID               0x7F
 98 
 99 /* PCA9554 registers */
100 #define PCA9554_DEV     0x40            /* I2C device address */
101 #define PCA9554_IN      0x00            /* input port */
102 #define PCA9554_OUT     0x01            /* output port */
103 #define PCA9554_INVERT  0x02            /* input invert */
104 #define PCA9554_DIR     0x03            /* port directions */
105 
106 /*
107  * Aureon Universe additional controls using PCA9554
108  */
109 
110 /*
111  * Send data to pca9554
112  */
113 static void aureon_pca9554_write(struct snd_ice1712 *ice, unsigned char reg,
114                                  unsigned char data)
115 {
116         unsigned int tmp;
117         int i, j;
118         unsigned char dev = PCA9554_DEV;  /* ID 0100000, write */
119         unsigned char val = 0;
120 
121         tmp = snd_ice1712_gpio_read(ice);
122 
123         snd_ice1712_gpio_set_mask(ice, ~(AUREON_SPI_MOSI|AUREON_SPI_CLK|
124                                          AUREON_WM_RW|AUREON_WM_CS|
125                                          AUREON_CS8415_CS));
126         tmp |= AUREON_WM_RW;
127         tmp |= AUREON_CS8415_CS | AUREON_WM_CS; /* disable SPI devices */
128 
129         tmp &= ~AUREON_SPI_MOSI;
130         tmp &= ~AUREON_SPI_CLK;
131         snd_ice1712_gpio_write(ice, tmp);
132         udelay(50);
133 
134         /* 
135          * send i2c stop condition and start condition
136          * to obtain sane state
137          */
138         tmp |= AUREON_SPI_CLK;
139         snd_ice1712_gpio_write(ice, tmp);
140         udelay(50);
141         tmp |= AUREON_SPI_MOSI;
142         snd_ice1712_gpio_write(ice, tmp);
143         udelay(100);
144         tmp &= ~AUREON_SPI_MOSI;
145         snd_ice1712_gpio_write(ice, tmp);
146         udelay(50);
147         tmp &= ~AUREON_SPI_CLK;
148         snd_ice1712_gpio_write(ice, tmp);
149         udelay(100);
150         /*
151          * send device address, command and value,
152          * skipping ack cycles inbetween
153          */
154         for (j = 0; j < 3; j++) {
155                 switch(j) {
156                 case 0: val = dev; break;
157                 case 1: val = reg; break;
158                 case 2: val = data; break;
159                 }
160                 for (i = 7; i >= 0; i--) {
161                         tmp &= ~AUREON_SPI_CLK;
162                         snd_ice1712_gpio_write(ice, tmp);
163                         udelay(40);
164                         if (val & (1 << i))
165                                 tmp |= AUREON_SPI_MOSI;
166                         else
167                                 tmp &= ~AUREON_SPI_MOSI;
168                         snd_ice1712_gpio_write(ice, tmp);
169                         udelay(40);
170                         tmp |= AUREON_SPI_CLK;
171                         snd_ice1712_gpio_write(ice, tmp);
172                         udelay(40);
173                 }
174                 tmp &= ~AUREON_SPI_CLK;
175                 snd_ice1712_gpio_write(ice, tmp);
176                 udelay(40);
177                 tmp |= AUREON_SPI_CLK;
178                 snd_ice1712_gpio_write(ice, tmp);
179                 udelay(40);
180                 tmp &= ~AUREON_SPI_CLK;
181                 snd_ice1712_gpio_write(ice, tmp);
182                 udelay(40);
183         }
184         tmp &= ~AUREON_SPI_CLK;
185         snd_ice1712_gpio_write(ice, tmp);
186         udelay(40);
187         tmp &= ~AUREON_SPI_MOSI;
188         snd_ice1712_gpio_write(ice, tmp);
189         udelay(40);
190         tmp |= AUREON_SPI_CLK;
191         snd_ice1712_gpio_write(ice, tmp);
192         udelay(50);
193         tmp |= AUREON_SPI_MOSI;
194         snd_ice1712_gpio_write(ice, tmp);
195         udelay(100);
196 }
197 
198 static int aureon_universe_inmux_info(struct snd_kcontrol *kcontrol,
199                                       struct snd_ctl_elem_info *uinfo)
200 {
201         char *texts[3] = {"Internal Aux", "Wavetable", "Rear Line-In"};
202 
203         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
204         uinfo->count = 1;
205         uinfo->value.enumerated.items = 3;
206         if(uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
207                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
208         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
209         return 0;
210 }
211 
212 static int aureon_universe_inmux_get(struct snd_kcontrol *kcontrol,
213                                      struct snd_ctl_elem_value *ucontrol)
214 {
215         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
216         struct aureon_spec *spec = ice->spec;
217         ucontrol->value.enumerated.item[0] = spec->pca9554_out;
218         return 0;
219 }
220 
221 static int aureon_universe_inmux_put(struct snd_kcontrol *kcontrol,
222                                      struct snd_ctl_elem_value *ucontrol)
223 {
224         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
225         struct aureon_spec *spec = ice->spec;
226         unsigned char oval, nval;
227         int change;
228 
229         nval = ucontrol->value.enumerated.item[0];
230         if (nval >= 3)
231                 return -EINVAL;
232         snd_ice1712_save_gpio_status(ice);
233         oval = spec->pca9554_out;
234         if ((change = (oval != nval))) {
235                 aureon_pca9554_write(ice, PCA9554_OUT, nval);
236                 spec->pca9554_out = nval;
237         }
238         snd_ice1712_restore_gpio_status(ice);
239         
240         return change;
241 }
242 
243 
244 static void aureon_ac97_write(struct snd_ice1712 *ice, unsigned short reg,
245                               unsigned short val)
246 {
247         struct aureon_spec *spec = ice->spec;
248         unsigned int tmp;
249 
250         /* Send address to XILINX chip */
251         tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
252         snd_ice1712_gpio_write(ice, tmp);
253         udelay(10);
254         tmp |= AUREON_AC97_ADDR;
255         snd_ice1712_gpio_write(ice, tmp);
256         udelay(10);
257         tmp &= ~AUREON_AC97_ADDR;
258         snd_ice1712_gpio_write(ice, tmp);
259         udelay(10);     
260 
261         /* Send low-order byte to XILINX chip */
262         tmp &= ~AUREON_AC97_DATA_MASK;
263         tmp |= val & AUREON_AC97_DATA_MASK;
264         snd_ice1712_gpio_write(ice, tmp);
265         udelay(10);
266         tmp |= AUREON_AC97_DATA_LOW;
267         snd_ice1712_gpio_write(ice, tmp);
268         udelay(10);
269         tmp &= ~AUREON_AC97_DATA_LOW;
270         snd_ice1712_gpio_write(ice, tmp);
271         udelay(10);
272         
273         /* Send high-order byte to XILINX chip */
274         tmp &= ~AUREON_AC97_DATA_MASK;
275         tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
276 
277         snd_ice1712_gpio_write(ice, tmp);
278         udelay(10);
279         tmp |= AUREON_AC97_DATA_HIGH;
280         snd_ice1712_gpio_write(ice, tmp);
281         udelay(10);
282         tmp &= ~AUREON_AC97_DATA_HIGH;
283         snd_ice1712_gpio_write(ice, tmp);
284         udelay(10);
285         
286         /* Instruct XILINX chip to parse the data to the STAC9744 chip */
287         tmp |= AUREON_AC97_COMMIT;
288         snd_ice1712_gpio_write(ice, tmp);
289         udelay(10);
290         tmp &= ~AUREON_AC97_COMMIT;
291         snd_ice1712_gpio_write(ice, tmp);
292         udelay(10);
293         
294         /* Store the data in out private buffer */
295         spec->stac9744[(reg & 0x7F) >> 1] = val;
296 }
297 
298 static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short reg)
299 {
300         struct aureon_spec *spec = ice->spec;
301         return spec->stac9744[(reg & 0x7F) >> 1];
302 }
303 
304 /*
305  * Initialize STAC9744 chip
306  */
307 static int aureon_ac97_init (struct snd_ice1712 *ice)
308 {
309         struct aureon_spec *spec = ice->spec;
310         int i;
311         static const unsigned short ac97_defaults[] = {
312                 0x00, 0x9640,
313                 0x02, 0x8000,
314                 0x04, 0x8000,
315                 0x06, 0x8000,
316                 0x0C, 0x8008,
317                 0x0E, 0x8008,
318                 0x10, 0x8808,
319                 0x12, 0x8808,
320                 0x14, 0x8808,
321                 0x16, 0x8808,
322                 0x18, 0x8808,
323                 0x1C, 0x8000,
324                 0x26, 0x000F,
325                 0x28, 0x0201,
326                 0x2C, 0xBB80,
327                 0x32, 0xBB80,
328                 0x7C, 0x8384,
329                 0x7E, 0x7644,
330                 (unsigned short)-1
331         };
332         unsigned int tmp;
333 
334         /* Cold reset */
335         tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
336         snd_ice1712_gpio_write(ice, tmp);
337         udelay(3);
338         
339         tmp &= ~AUREON_AC97_RESET;
340         snd_ice1712_gpio_write(ice, tmp);
341         udelay(3);
342         
343         tmp |= AUREON_AC97_RESET;
344         snd_ice1712_gpio_write(ice, tmp);
345         udelay(3);
346         
347         memset(&spec->stac9744, 0, sizeof(spec->stac9744));
348         for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
349                 spec->stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
350                 
351         aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
352 
353         return 0;
354 }
355 
356 #define AUREON_AC97_STEREO      0x80
357 
358 /*
359  * AC'97 volume controls
360  */
361 static int aureon_ac97_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
362 {
363         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
364         uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
365         uinfo->value.integer.min = 0;
366         uinfo->value.integer.max = 31;
367         return 0;
368 }
369 
370 static int aureon_ac97_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
371 {
372         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
373         unsigned short vol;
374 
375         mutex_lock(&ice->gpio_mutex);
376 
377         vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
378         ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
379         if (kcontrol->private_value & AUREON_AC97_STEREO)
380                 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
381 
382         mutex_unlock(&ice->gpio_mutex);
383         return 0;
384 }
385 
386 static int aureon_ac97_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
387 {
388         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
389         unsigned short ovol, nvol;
390         int change;
391         
392         snd_ice1712_save_gpio_status(ice);
393 
394         ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
395         nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
396         if (kcontrol->private_value & AUREON_AC97_STEREO)
397                 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
398         nvol |= ovol & ~0x1F1F;
399         
400         if ((change = (ovol != nvol)))
401                 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
402 
403         snd_ice1712_restore_gpio_status(ice);
404 
405         return change;          
406 }
407 
408 /*
409  * AC'97 mute controls
410  */
411 #define aureon_ac97_mute_info   snd_ctl_boolean_mono_info
412 
413 static int aureon_ac97_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
414 {
415         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
416 
417         mutex_lock(&ice->gpio_mutex);
418 
419         ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
420 
421         mutex_unlock(&ice->gpio_mutex);
422         return 0;
423 }
424 
425 static int aureon_ac97_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
426 {
427         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
428         unsigned short ovol, nvol;
429         int change;
430 
431         snd_ice1712_save_gpio_status(ice);
432         
433         ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
434         nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
435         
436         if ((change = (ovol != nvol)))
437                 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
438                 
439         snd_ice1712_restore_gpio_status(ice);
440 
441         return change;
442 }
443 
444 /*
445  * AC'97 mute controls
446  */
447 #define aureon_ac97_micboost_info       snd_ctl_boolean_mono_info
448 
449 static int aureon_ac97_micboost_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
450 {
451         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
452 
453         mutex_lock(&ice->gpio_mutex);
454 
455         ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
456 
457         mutex_unlock(&ice->gpio_mutex);
458         return 0;
459 }
460 
461 static int aureon_ac97_micboost_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
462 {
463         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
464         unsigned short ovol, nvol;
465         int change;
466 
467         snd_ice1712_save_gpio_status(ice);
468         
469         ovol = aureon_ac97_read(ice, AC97_MIC);
470         nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
471         
472         if ((change = (ovol != nvol)))
473                 aureon_ac97_write(ice, AC97_MIC, nvol);
474                 
475         snd_ice1712_restore_gpio_status(ice);
476 
477         return change;
478 }
479 
480 /*
481  * write data in the SPI mode
482  */
483 static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits)
484 {
485         unsigned int tmp;
486         int i;
487         unsigned int mosi, clk;
488 
489         tmp = snd_ice1712_gpio_read(ice);
490 
491         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
492             ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
493                 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
494                 mosi = PRODIGY_SPI_MOSI;
495                 clk = PRODIGY_SPI_CLK;
496         }
497         else {
498                 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
499                                                  AUREON_WM_CS|AUREON_CS8415_CS));
500                 mosi = AUREON_SPI_MOSI;
501                 clk = AUREON_SPI_CLK;
502                 
503                 tmp |= AUREON_WM_RW;
504         }
505         
506         tmp &= ~cs;
507         snd_ice1712_gpio_write(ice, tmp);
508         udelay(1);
509 
510         for (i = bits - 1; i >= 0; i--) {
511                 tmp &= ~clk;
512                 snd_ice1712_gpio_write(ice, tmp);
513                 udelay(1);
514                 if (data & (1 << i))
515                         tmp |= mosi;
516                 else
517                         tmp &= ~mosi;
518                 snd_ice1712_gpio_write(ice, tmp);
519                 udelay(1);
520                 tmp |= clk;
521                 snd_ice1712_gpio_write(ice, tmp);
522                 udelay(1);
523         }
524 
525         tmp &= ~clk;
526         tmp |= cs;
527         snd_ice1712_gpio_write(ice, tmp);
528         udelay(1);
529         tmp |= clk;
530         snd_ice1712_gpio_write(ice, tmp);
531         udelay(1);
532 }
533 
534 /*
535  * Read data in SPI mode
536  */
537 static void aureon_spi_read(struct snd_ice1712 *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
538         int i, j;
539         unsigned int tmp;
540 
541         tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
542         snd_ice1712_gpio_write(ice, tmp);
543         tmp &= ~cs;
544         snd_ice1712_gpio_write(ice, tmp);
545         udelay(1);
546 
547         for (i=bits-1; i>=0; i--) {
548                 if (data & (1 << i))
549                         tmp |= AUREON_SPI_MOSI;
550                 else
551                         tmp &= ~AUREON_SPI_MOSI;
552                 snd_ice1712_gpio_write(ice, tmp);
553                 udelay(1);
554 
555                 tmp |= AUREON_SPI_CLK;
556                 snd_ice1712_gpio_write(ice, tmp);
557                 udelay(1);
558 
559                 tmp &= ~AUREON_SPI_CLK;
560                 snd_ice1712_gpio_write(ice, tmp);
561                 udelay(1);
562         }
563 
564         for (j=0; j<size; j++) {
565                 unsigned char outdata = 0;
566                 for (i=7; i>=0; i--) {
567                         tmp = snd_ice1712_gpio_read(ice);
568                         outdata <<= 1;
569                         outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
570                         udelay(1);
571 
572                         tmp |= AUREON_SPI_CLK;
573                         snd_ice1712_gpio_write(ice, tmp);
574                         udelay(1);
575 
576                         tmp &= ~AUREON_SPI_CLK;
577                         snd_ice1712_gpio_write(ice, tmp);
578                         udelay(1);
579                 }
580                 buffer[j] = outdata;
581         }
582 
583         tmp |= cs;
584         snd_ice1712_gpio_write(ice, tmp);
585 }
586 
587 static unsigned char aureon_cs8415_get(struct snd_ice1712 *ice, int reg) {
588         unsigned char val;
589         aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
590         aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
591         return val;
592 }
593 
594 static void aureon_cs8415_read(struct snd_ice1712 *ice, int reg, unsigned char *buffer, int size) {
595         aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
596         aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
597 }
598 
599 static void aureon_cs8415_put(struct snd_ice1712 *ice, int reg, unsigned char val) {
600         aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
601 }
602 
603 /*
604  * get the current register value of WM codec
605  */
606 static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
607 {
608         reg <<= 1;
609         return ((unsigned short)ice->akm[0].images[reg] << 8) |
610                 ice->akm[0].images[reg + 1];
611 }
612 
613 /*
614  * set the register value of WM codec
615  */
616 static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
617 {
618         aureon_spi_write(ice,
619                          ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
620                            ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
621                          PRODIGY_WM_CS : AUREON_WM_CS),
622                         (reg << 9) | (val & 0x1ff), 16);
623 }
624 
625 /*
626  * set the register value of WM codec and remember it
627  */
628 static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
629 {
630         wm_put_nocache(ice, reg, val);
631         reg <<= 1;
632         ice->akm[0].images[reg] = val >> 8;
633         ice->akm[0].images[reg + 1] = val;
634 }
635 
636 /*
637  */
638 #define aureon_mono_bool_info           snd_ctl_boolean_mono_info
639 
640 /*
641  * AC'97 master playback mute controls (Mute on WM8770 chip)
642  */
643 #define aureon_ac97_mmute_info          snd_ctl_boolean_mono_info
644 
645 static int aureon_ac97_mmute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
646 {
647         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
648 
649         mutex_lock(&ice->gpio_mutex);
650 
651         ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
652 
653         mutex_unlock(&ice->gpio_mutex);
654         return 0;
655 }
656 
657 static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
658         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
659         unsigned short ovol, nvol;
660         int change;
661         
662         snd_ice1712_save_gpio_status(ice);
663         
664         ovol = wm_get(ice, WM_OUT_MUX1);
665         nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
666         if ((change = (ovol != nvol)))
667                 wm_put(ice, WM_OUT_MUX1, nvol);
668                 
669         snd_ice1712_restore_gpio_status(ice);
670 
671         return change;
672 }
673 
674 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
675 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
676 static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
677 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
678 static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
679 
680 /*
681  * Logarithmic volume values for WM8770
682  * Computed as 20 * Log10(255 / x)
683  */
684 static const unsigned char wm_vol[256] = {
685         127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
686         23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
687         17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
688         13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
689         11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
690         8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6,
691         6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
692         5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3,
693         3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
694         2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
695         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
696         0, 0
697 };
698 
699 #define WM_VOL_MAX      (sizeof(wm_vol) - 1)
700 #define WM_VOL_MUTE     0x8000
701 
702 static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
703 {
704         unsigned char nvol;
705         
706         if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
707                 nvol = 0;
708         else
709                 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
710         
711         wm_put(ice, index, nvol);
712         wm_put_nocache(ice, index, 0x180 | nvol);
713 }
714 
715 /*
716  * DAC mute control
717  */
718 #define wm_pcm_mute_info        snd_ctl_boolean_mono_info
719 
720 static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
721 {
722         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
723 
724         mutex_lock(&ice->gpio_mutex);
725         ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
726         mutex_unlock(&ice->gpio_mutex);
727         return 0;
728 }
729 
730 static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
731 {
732         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
733         unsigned short nval, oval;
734         int change;
735 
736         snd_ice1712_save_gpio_status(ice);
737         oval = wm_get(ice, WM_MUTE);
738         nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
739         if ((change = (nval != oval)))
740                 wm_put(ice, WM_MUTE, nval);
741         snd_ice1712_restore_gpio_status(ice);
742 
743         return change;
744 }
745 
746 /*
747  * Master volume attenuation mixer control
748  */
749 static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
750 {
751         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
752         uinfo->count = 2;
753         uinfo->value.integer.min = 0;
754         uinfo->value.integer.max = WM_VOL_MAX;
755         return 0;
756 }
757 
758 static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
759 {
760         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
761         struct aureon_spec *spec = ice->spec;
762         int i;
763         for (i=0; i<2; i++)
764                 ucontrol->value.integer.value[i] =
765                         spec->master[i] & ~WM_VOL_MUTE;
766         return 0;
767 }
768 
769 static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
770 {
771         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
772         struct aureon_spec *spec = ice->spec;
773         int ch, change = 0;
774 
775         snd_ice1712_save_gpio_status(ice);
776         for (ch = 0; ch < 2; ch++) {
777                 unsigned int vol = ucontrol->value.integer.value[ch];
778                 if (vol > WM_VOL_MAX)
779                         continue;
780                 vol |= spec->master[ch] & WM_VOL_MUTE;
781                 if (vol != spec->master[ch]) {
782                         int dac;
783                         spec->master[ch] = vol;
784                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
785                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
786                                            spec->vol[dac + ch],
787                                            spec->master[ch]);
788                         change = 1;
789                 }
790         }
791         snd_ice1712_restore_gpio_status(ice);
792         return change;
793 }
794 
795 /*
796  * DAC volume attenuation mixer control
797  */
798 static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
799 {
800         int voices = kcontrol->private_value >> 8;
801         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
802         uinfo->count = voices;
803         uinfo->value.integer.min = 0;           /* mute (-101dB) */
804         uinfo->value.integer.max = 0x7F;        /* 0dB */
805         return 0;
806 }
807 
808 static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
809 {
810         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
811         struct aureon_spec *spec = ice->spec;
812         int i, ofs, voices;
813 
814         voices = kcontrol->private_value >> 8;
815         ofs = kcontrol->private_value & 0xff;
816         for (i = 0; i < voices; i++)
817                 ucontrol->value.integer.value[i] =
818                         spec->vol[ofs+i] & ~WM_VOL_MUTE;
819         return 0;
820 }
821 
822 static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
823 {
824         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
825         struct aureon_spec *spec = ice->spec;
826         int i, idx, ofs, voices;
827         int change = 0;
828 
829         voices = kcontrol->private_value >> 8;
830         ofs = kcontrol->private_value & 0xff;
831         snd_ice1712_save_gpio_status(ice);
832         for (i = 0; i < voices; i++) {
833                 unsigned int vol = ucontrol->value.integer.value[i];
834                 if (vol > 0x7f)
835                         continue;
836                 vol |= spec->vol[ofs+i];
837                 if (vol != spec->vol[ofs+i]) {
838                         spec->vol[ofs+i] = vol;
839                         idx  = WM_DAC_ATTEN + ofs + i;
840                         wm_set_vol(ice, idx, spec->vol[ofs + i],
841                                    spec->master[i]);
842                         change = 1;
843                 }
844         }
845         snd_ice1712_restore_gpio_status(ice);
846         return change;
847 }
848 
849 /*
850  * WM8770 mute control
851  */
852 static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
853         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
854         uinfo->count = kcontrol->private_value >> 8;
855         uinfo->value.integer.min = 0;
856         uinfo->value.integer.max = 1;
857         return 0;
858 }
859 
860 static int wm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
861 {
862         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
863         struct aureon_spec *spec = ice->spec;
864         int voices, ofs, i;
865         
866         voices = kcontrol->private_value >> 8;
867         ofs = kcontrol->private_value & 0xFF;
868 
869         for (i = 0; i < voices; i++)
870                 ucontrol->value.integer.value[i] =
871                         (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
872         return 0;
873 }
874 
875 static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
876 {
877         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
878         struct aureon_spec *spec = ice->spec;
879         int change = 0, voices, ofs, i;
880 
881         voices = kcontrol->private_value >> 8;
882         ofs = kcontrol->private_value & 0xFF;
883 
884         snd_ice1712_save_gpio_status(ice);
885         for (i = 0; i < voices; i++) {
886                 int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
887                 if (ucontrol->value.integer.value[i] != val) {
888                         spec->vol[ofs + i] &= ~WM_VOL_MUTE;
889                         spec->vol[ofs + i] |=
890                                 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
891                         wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
892                                    spec->master[i]);
893                         change = 1;
894                 }
895         }
896         snd_ice1712_restore_gpio_status(ice);
897 
898         return change;
899 }
900 
901 /*
902  * WM8770 master mute control
903  */
904 #define wm_master_mute_info             snd_ctl_boolean_stereo_info
905 
906 static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
907 {
908         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
909         struct aureon_spec *spec = ice->spec;
910         
911         ucontrol->value.integer.value[0] =
912                 (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
913         ucontrol->value.integer.value[1] =
914                 (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
915         return 0;
916 }
917 
918 static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
919 {
920         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
921         struct aureon_spec *spec = ice->spec;
922         int change = 0, i;
923 
924         snd_ice1712_save_gpio_status(ice);
925         for (i = 0; i < 2; i++) {
926                 int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
927                 if (ucontrol->value.integer.value[i] != val) {
928                         int dac;
929                         spec->master[i] &= ~WM_VOL_MUTE;
930                         spec->master[i] |=
931                                 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
932                         for (dac = 0; dac < ice->num_total_dacs; dac += 2)
933                                 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
934                                            spec->vol[dac + i],
935                                            spec->master[i]);
936                         change = 1;
937                 }
938         }
939         snd_ice1712_restore_gpio_status(ice);
940 
941         return change;
942 }
943 
944 /* digital master volume */
945 #define PCM_0dB 0xff
946 #define PCM_RES 128     /* -64dB */
947 #define PCM_MIN (PCM_0dB - PCM_RES)
948 static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
949 {
950         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
951         uinfo->count = 1;
952         uinfo->value.integer.min = 0;           /* mute (-64dB) */
953         uinfo->value.integer.max = PCM_RES;     /* 0dB */
954         return 0;
955 }
956 
957 static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
958 {
959         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
960         unsigned short val;
961 
962         mutex_lock(&ice->gpio_mutex);
963         val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
964         val = val > PCM_MIN ? (val - PCM_MIN) : 0;
965         ucontrol->value.integer.value[0] = val;
966         mutex_unlock(&ice->gpio_mutex);
967         return 0;
968 }
969 
970 static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
971 {
972         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
973         unsigned short ovol, nvol;
974         int change = 0;
975 
976         nvol = ucontrol->value.integer.value[0];
977         if (nvol > PCM_RES)
978                 return -EINVAL;
979         snd_ice1712_save_gpio_status(ice);
980         nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
981         ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
982         if (ovol != nvol) {
983                 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
984                 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
985                 change = 1;
986         }
987         snd_ice1712_restore_gpio_status(ice);
988         return change;
989 }
990 
991 /*
992  * ADC mute control
993  */
994 #define wm_adc_mute_info                snd_ctl_boolean_stereo_info
995 
996 static int wm_adc_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
997 {
998         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
999         unsigned short val;
1000         int i;
1001 
1002         mutex_lock(&ice->gpio_mutex);
1003         for (i = 0; i < 2; i++) {
1004                 val = wm_get(ice, WM_ADC_GAIN + i);
1005                 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
1006         }
1007         mutex_unlock(&ice->gpio_mutex);
1008         return 0;
1009 }
1010 
1011 static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1012 {
1013         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1014         unsigned short new, old;
1015         int i, change = 0;
1016 
1017         snd_ice1712_save_gpio_status(ice);
1018         for (i = 0; i < 2; i++) {
1019                 old = wm_get(ice, WM_ADC_GAIN + i);
1020                 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1021                 if (new != old) {
1022                         wm_put(ice, WM_ADC_GAIN + i, new);
1023                         change = 1;
1024                 }
1025         }
1026         snd_ice1712_restore_gpio_status(ice);
1027 
1028         return change;
1029 }
1030 
1031 /*
1032  * ADC gain mixer control
1033  */
1034 static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1035 {
1036         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1037         uinfo->count = 2;
1038         uinfo->value.integer.min = 0;           /* -12dB */
1039         uinfo->value.integer.max = 0x1f;        /* 19dB */
1040         return 0;
1041 }
1042 
1043 static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1044 {
1045         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1046         int i, idx;
1047         unsigned short vol;
1048 
1049         mutex_lock(&ice->gpio_mutex);
1050         for (i = 0; i < 2; i++) {
1051                 idx = WM_ADC_GAIN + i;
1052                 vol = wm_get(ice, idx) & 0x1f;
1053                 ucontrol->value.integer.value[i] = vol;
1054         }
1055         mutex_unlock(&ice->gpio_mutex);
1056         return 0;
1057 }
1058 
1059 static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1060 {
1061         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1062         int i, idx;
1063         unsigned short ovol, nvol;
1064         int change = 0;
1065 
1066         snd_ice1712_save_gpio_status(ice);
1067         for (i = 0; i < 2; i++) {
1068                 idx  = WM_ADC_GAIN + i;
1069                 nvol = ucontrol->value.integer.value[i] & 0x1f;
1070                 ovol = wm_get(ice, idx);
1071                 if ((ovol & 0x1f) != nvol) {
1072                         wm_put(ice, idx, nvol | (ovol & ~0x1f));
1073                         change = 1;
1074                 }
1075         }
1076         snd_ice1712_restore_gpio_status(ice);
1077         return change;
1078 }
1079 
1080 /*
1081  * ADC input mux mixer control
1082  */
1083 static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1084 {
1085         static const char * const texts[] = {
1086                 "CD",           //AIN1
1087                 "Aux",          //AIN2
1088                 "Line",         //AIN3
1089                 "Mic",          //AIN4
1090                 "AC97"          //AIN5
1091         };
1092         static const char * const universe_texts[] = {
1093                 "Aux1",         //AIN1
1094                 "CD",           //AIN2
1095                 "Phono",        //AIN3
1096                 "Line",         //AIN4
1097                 "Aux2",         //AIN5
1098                 "Mic",          //AIN6
1099                 "Aux3",         //AIN7
1100                 "AC97"          //AIN8
1101         };
1102         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1103 
1104         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1105         uinfo->count = 2;
1106         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1107                 uinfo->value.enumerated.items = 8;
1108                 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1109                         uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1110                 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1111         }
1112         else {
1113                 uinfo->value.enumerated.items = 5;
1114                 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1115                         uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1116                 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1117         }
1118         return 0;
1119 }
1120 
1121 static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1122 {
1123         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1124         unsigned short val;
1125 
1126         mutex_lock(&ice->gpio_mutex);
1127         val = wm_get(ice, WM_ADC_MUX);
1128         ucontrol->value.enumerated.item[0] = val & 7;
1129         ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
1130         mutex_unlock(&ice->gpio_mutex);
1131         return 0;
1132 }
1133 
1134 static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1135 {
1136         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1137         unsigned short oval, nval;
1138         int change;
1139 
1140         snd_ice1712_save_gpio_status(ice);
1141         oval = wm_get(ice, WM_ADC_MUX);
1142         nval = oval & ~0x77;
1143         nval |= ucontrol->value.enumerated.item[0] & 7;
1144         nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1145         change = (oval != nval);
1146         if (change)
1147                 wm_put(ice, WM_ADC_MUX, nval);
1148         snd_ice1712_restore_gpio_status(ice);
1149         return change;
1150 }
1151 
1152 /*
1153  * CS8415 Input mux
1154  */
1155 static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1156 {
1157         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1158         static const char * const aureon_texts[] = {
1159                 "CD",           //RXP0
1160                 "Optical"       //RXP1
1161         };
1162         static const char * const prodigy_texts[] = {
1163                 "CD",
1164                 "Coax"
1165         };
1166         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1167         uinfo->count = 1;
1168         uinfo->value.enumerated.items = 2;
1169         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1170                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1171         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1172                 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1173         else
1174                 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1175         return 0;
1176 }
1177 
1178 static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1179 {
1180         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1181         struct aureon_spec *spec = ice->spec;
1182 
1183         //snd_ice1712_save_gpio_status(ice);
1184         //val = aureon_cs8415_get(ice, CS8415_CTRL2);
1185         ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1186         //snd_ice1712_restore_gpio_status(ice);
1187         return 0;
1188 }
1189 
1190 static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1191 {
1192         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1193         struct aureon_spec *spec = ice->spec;
1194         unsigned short oval, nval;
1195         int change;
1196 
1197         snd_ice1712_save_gpio_status(ice);
1198         oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1199         nval = oval & ~0x07;
1200         nval |= ucontrol->value.enumerated.item[0] & 7;
1201         change = (oval != nval);
1202         if (change)
1203                 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1204         snd_ice1712_restore_gpio_status(ice);
1205         spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1206         return change;
1207 }
1208 
1209 static int aureon_cs8415_rate_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1210 {
1211         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1212         uinfo->count = 1;
1213         uinfo->value.integer.min = 0;
1214         uinfo->value.integer.max = 192000;
1215         return 0;
1216 }
1217 
1218 static int aureon_cs8415_rate_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1219 {
1220         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1221         unsigned char ratio;
1222         ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1223         ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1224         return 0;
1225 }
1226 
1227 /*
1228  * CS8415A Mute
1229  */
1230 #define aureon_cs8415_mute_info         snd_ctl_boolean_mono_info
1231 
1232 static int aureon_cs8415_mute_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1233 {
1234         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1235         snd_ice1712_save_gpio_status(ice);
1236         ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1237         snd_ice1712_restore_gpio_status(ice);
1238         return 0;
1239 }
1240 
1241 static int aureon_cs8415_mute_put (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1242 {
1243         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1244         unsigned char oval, nval;
1245         int change;
1246         snd_ice1712_save_gpio_status(ice);
1247         oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1248         if (ucontrol->value.integer.value[0])
1249                 nval = oval & ~0x20;
1250         else
1251                 nval = oval | 0x20;
1252         if ((change = (oval != nval)))
1253                 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1254         snd_ice1712_restore_gpio_status(ice);
1255         return change;
1256 }
1257 
1258 /*
1259  * CS8415A Q-Sub info
1260  */
1261 static int aureon_cs8415_qsub_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1262         uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1263         uinfo->count = 10;
1264         return 0;
1265 }
1266 
1267 static int aureon_cs8415_qsub_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1268         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1269         
1270         snd_ice1712_save_gpio_status(ice);
1271         aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1272         snd_ice1712_restore_gpio_status(ice);
1273 
1274         return 0;
1275 }
1276 
1277 static int aureon_cs8415_spdif_info (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
1278         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1279         uinfo->count = 1;
1280         return 0;
1281 }
1282 
1283 static int aureon_cs8415_mask_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1284         memset(ucontrol->value.iec958.status, 0xFF, 24);
1285         return 0;
1286 }
1287 
1288 static int aureon_cs8415_spdif_get (struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) {
1289         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1290 
1291         snd_ice1712_save_gpio_status(ice);
1292         aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1293         snd_ice1712_restore_gpio_status(ice);
1294         return 0;
1295 }
1296 
1297 /*
1298  * Headphone Amplifier
1299  */
1300 static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1301 {
1302         unsigned int tmp, tmp2;
1303 
1304         tmp2 = tmp = snd_ice1712_gpio_read(ice);
1305         if (enable)
1306                 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1307                     ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1308                         tmp |= AUREON_HP_SEL;
1309                 else
1310                         tmp |= PRODIGY_HP_SEL;
1311         else
1312                 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1313                     ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1314                         tmp &= ~ AUREON_HP_SEL;
1315                 else
1316                         tmp &= ~ PRODIGY_HP_SEL;
1317         if (tmp != tmp2) {
1318                 snd_ice1712_gpio_write(ice, tmp);
1319                 return 1;
1320         }
1321         return 0;
1322 }
1323 
1324 static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1325 {
1326         unsigned int tmp = snd_ice1712_gpio_read(ice);
1327 
1328         return ( tmp & AUREON_HP_SEL )!= 0;
1329 }
1330 
1331 #define aureon_hpamp_info       snd_ctl_boolean_mono_info
1332 
1333 static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1334 {
1335         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1336 
1337         ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1338         return 0;
1339 }
1340 
1341 
1342 static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1343 {
1344         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1345 
1346         return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1347 }
1348 
1349 /*
1350  * Deemphasis
1351  */
1352 
1353 #define aureon_deemp_info       snd_ctl_boolean_mono_info
1354 
1355 static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1356 {
1357         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1358         ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1359         return 0;
1360 }
1361 
1362 static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1363 {
1364         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1365         int temp, temp2;
1366         temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1367         if (ucontrol->value.integer.value[0])
1368                 temp |= 0xf;
1369         else
1370                 temp &= ~0xf;
1371         if (temp != temp2) {
1372                 wm_put(ice, WM_DAC_CTRL2, temp);
1373                 return 1;
1374         }
1375         return 0;
1376 }
1377 
1378 /*
1379  * ADC Oversampling
1380  */
1381 static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1382 {
1383         static const char * const texts[2] = { "128x", "64x"    };
1384 
1385         uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1386         uinfo->count = 1;
1387         uinfo->value.enumerated.items = 2;
1388 
1389         if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1390                 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1391         strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1392 
1393         return 0;
1394 }
1395 
1396 static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1397 {
1398         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1399         ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1400         return 0;
1401 }
1402 
1403 static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1404 {
1405         int temp, temp2;
1406         struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1407 
1408         temp2 = temp = wm_get(ice, WM_MASTER);
1409 
1410         if (ucontrol->value.enumerated.item[0])
1411                 temp |= 0x8;
1412         else
1413                 temp &= ~0x8;
1414 
1415         if (temp != temp2) {
1416                 wm_put(ice, WM_MASTER, temp);
1417                 return 1;
1418         }
1419         return 0;
1420 }
1421 
1422 /*
1423  * mixers
1424  */
1425 
1426 static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1427         {
1428                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1429                 .name = "Master Playback Switch",
1430                 .info = wm_master_mute_info,
1431                 .get = wm_master_mute_get,
1432                 .put = wm_master_mute_put
1433         },
1434         {
1435                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1436                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1437                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1438                 .name = "Master Playback Volume",
1439                 .info = wm_master_vol_info,
1440                 .get = wm_master_vol_get,
1441                 .put = wm_master_vol_put,
1442                 .tlv = { .p = db_scale_wm_dac }
1443         },
1444         {
1445                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1446                 .name = "Front Playback Switch",
1447                 .info = wm_mute_info,
1448                 .get = wm_mute_get,
1449                 .put = wm_mute_put,
1450                 .private_value = (2 << 8) | 0
1451         },
1452         {
1453                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1454                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1455                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1456                 .name = "Front Playback Volume",
1457                 .info = wm_vol_info,
1458                 .get = wm_vol_get,
1459                 .put = wm_vol_put,
1460                 .private_value = (2 << 8) | 0,
1461                 .tlv = { .p = db_scale_wm_dac }
1462         },
1463         {
1464                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1465                 .name = "Rear Playback Switch",
1466                 .info = wm_mute_info,
1467                 .get = wm_mute_get,
1468                 .put = wm_mute_put,
1469                 .private_value = (2 << 8) | 2
1470         },
1471         {
1472                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1473                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1474                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1475                 .name = "Rear Playback Volume",
1476                 .info = wm_vol_info,
1477                 .get = wm_vol_get,
1478                 .put = wm_vol_put,
1479                 .private_value = (2 << 8) | 2,
1480                 .tlv = { .p = db_scale_wm_dac }
1481         },
1482         {
1483                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1484                 .name = "Center Playback Switch",
1485                 .info = wm_mute_info,
1486                 .get = wm_mute_get,
1487                 .put = wm_mute_put,
1488                 .private_value = (1 << 8) | 4
1489         },
1490         {
1491                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1492                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1493                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1494                 .name = "Center Playback Volume",
1495                 .info = wm_vol_info,
1496                 .get = wm_vol_get,
1497                 .put = wm_vol_put,
1498                 .private_value = (1 << 8) | 4,
1499                 .tlv = { .p = db_scale_wm_dac }
1500         },
1501         {
1502                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1503                 .name = "LFE Playback Switch",
1504                 .info = wm_mute_info,
1505                 .get = wm_mute_get,
1506                 .put = wm_mute_put,
1507                 .private_value = (1 << 8) | 5
1508         },
1509         {
1510                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1511                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1512                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1513                 .name = "LFE Playback Volume",
1514                 .info = wm_vol_info,
1515                 .get = wm_vol_get,
1516                 .put = wm_vol_put,
1517                 .private_value = (1 << 8) | 5,
1518                 .tlv = { .p = db_scale_wm_dac }
1519         },
1520         {
1521                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1522                 .name = "Side Playback Switch",
1523                 .info = wm_mute_info,
1524                 .get = wm_mute_get,
1525                 .put = wm_mute_put,
1526                 .private_value = (2 << 8) | 6
1527         },
1528         {
1529                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1530                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1531                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1532                 .name = "Side Playback Volume",
1533                 .info = wm_vol_info,
1534                 .get = wm_vol_get,
1535                 .put = wm_vol_put,
1536                 .private_value = (2 << 8) | 6,
1537                 .tlv = { .p = db_scale_wm_dac }
1538         }
1539 };
1540 
1541 static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1542         {
1543                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1544                 .name = "PCM Playback Switch",
1545                 .info = wm_pcm_mute_info,
1546                 .get = wm_pcm_mute_get,
1547                 .put = wm_pcm_mute_put
1548         },
1549         {
1550                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1551                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1552                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1553                 .name = "PCM Playback Volume",
1554                 .info = wm_pcm_vol_info,
1555                 .get = wm_pcm_vol_get,
1556                 .put = wm_pcm_vol_put,
1557                 .tlv = { .p = db_scale_wm_pcm }
1558         },
1559         {
1560                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1561                 .name = "Capture Switch",
1562                 .info = wm_adc_mute_info,
1563                 .get = wm_adc_mute_get,
1564                 .put = wm_adc_mute_put,
1565         },
1566         {
1567                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1568                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1569                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1570                 .name = "Capture Volume",
1571                 .info = wm_adc_vol_info,
1572                 .get = wm_adc_vol_get,
1573                 .put = wm_adc_vol_put,
1574                 .tlv = { .p = db_scale_wm_adc }
1575         },
1576         {
1577                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1578                 .name = "Capture Source",
1579                 .info = wm_adc_mux_info,
1580                 .get = wm_adc_mux_get,
1581                 .put = wm_adc_mux_put,
1582                 .private_value = 5
1583         },
1584         {
1585                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1586                 .name = "External Amplifier",
1587                 .info = aureon_hpamp_info,
1588                 .get = aureon_hpamp_get,
1589                 .put = aureon_hpamp_put
1590         },
1591         {
1592                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1593                 .name = "DAC Deemphasis Switch",
1594                 .info = aureon_deemp_info,
1595                 .get = aureon_deemp_get,
1596                 .put = aureon_deemp_put
1597         },
1598         {
1599                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1600                 .name = "ADC Oversampling",
1601                 .info = aureon_oversampling_info,
1602                 .get = aureon_oversampling_get,
1603                 .put = aureon_oversampling_put
1604         }
1605 };
1606 
1607 static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1608         {
1609                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1610                 .name = "AC97 Playback Switch",
1611                 .info = aureon_ac97_mmute_info,
1612                 .get = aureon_ac97_mmute_get,
1613                 .put = aureon_ac97_mmute_put,
1614                 .private_value = AC97_MASTER
1615         },
1616         {
1617                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1618                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1619                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1620                 .name = "AC97 Playback Volume",
1621                 .info = aureon_ac97_vol_info,
1622                 .get = aureon_ac97_vol_get,
1623                 .put = aureon_ac97_vol_put,
1624                 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1625                 .tlv = { .p = db_scale_ac97_master }
1626         },
1627         {
1628                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1629                 .name = "CD Playback Switch",
1630                 .info = aureon_ac97_mute_info,
1631                 .get = aureon_ac97_mute_get,
1632                 .put = aureon_ac97_mute_put,
1633                 .private_value = AC97_CD
1634         },
1635         {
1636                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1637                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1638                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1639                 .name = "CD Playback Volume",
1640                 .info = aureon_ac97_vol_info,
1641                 .get = aureon_ac97_vol_get,
1642                 .put = aureon_ac97_vol_put,
1643                 .private_value = AC97_CD|AUREON_AC97_STEREO,
1644                 .tlv = { .p = db_scale_ac97_gain }
1645         },
1646         {
1647                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1648                 .name = "Aux Playback Switch",
1649                 .info = aureon_ac97_mute_info,
1650                 .get = aureon_ac97_mute_get,
1651                 .put = aureon_ac97_mute_put,
1652                 .private_value = AC97_AUX,
1653         },
1654         {
1655                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1656                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1657                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1658                 .name = "Aux Playback Volume",
1659                 .info = aureon_ac97_vol_info,
1660                 .get = aureon_ac97_vol_get,
1661                 .put = aureon_ac97_vol_put,
1662                 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1663                 .tlv = { .p = db_scale_ac97_gain }
1664         },
1665         {
1666                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1667                 .name = "Line Playback Switch",
1668                 .info = aureon_ac97_mute_info,
1669                 .get = aureon_ac97_mute_get,
1670                 .put = aureon_ac97_mute_put,
1671                 .private_value = AC97_LINE
1672         },
1673         {
1674                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1675                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1676                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1677                 .name = "Line Playback Volume",
1678                 .info = aureon_ac97_vol_info,
1679                 .get = aureon_ac97_vol_get,
1680                 .put = aureon_ac97_vol_put,
1681                 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1682                 .tlv = { .p = db_scale_ac97_gain }
1683         },
1684         {
1685                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1686                 .name = "Mic Playback Switch",
1687                 .info = aureon_ac97_mute_info,
1688                 .get = aureon_ac97_mute_get,
1689                 .put = aureon_ac97_mute_put,
1690                 .private_value = AC97_MIC
1691         },
1692         {
1693                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1694                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1695                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1696                 .name = "Mic Playback Volume",
1697                 .info = aureon_ac97_vol_info,
1698                 .get = aureon_ac97_vol_get,
1699                 .put = aureon_ac97_vol_put,
1700                 .private_value = AC97_MIC,
1701                 .tlv = { .p = db_scale_ac97_gain }
1702         },
1703         {
1704                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1705                 .name = "Mic Boost (+20dB)",
1706                 .info = aureon_ac97_micboost_info,
1707                 .get = aureon_ac97_micboost_get,
1708                 .put = aureon_ac97_micboost_put
1709         }
1710 };
1711 
1712 static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1713         {
1714                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1715                 .name = "AC97 Playback Switch",
1716                 .info = aureon_ac97_mmute_info,
1717                 .get = aureon_ac97_mmute_get,
1718                 .put = aureon_ac97_mmute_put,
1719                 .private_value = AC97_MASTER
1720         },
1721         {
1722                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1723                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1724                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1725                 .name = "AC97 Playback Volume",
1726                 .info = aureon_ac97_vol_info,
1727                 .get = aureon_ac97_vol_get,
1728                 .put = aureon_ac97_vol_put,
1729                 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
1730                 .tlv = { .p = db_scale_ac97_master }
1731         },
1732         {
1733                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1734                 .name = "CD Playback Switch",
1735                 .info = aureon_ac97_mute_info,
1736                 .get = aureon_ac97_mute_get,
1737                 .put = aureon_ac97_mute_put,
1738                 .private_value = AC97_AUX
1739         },
1740         {
1741                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1742                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1743                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1744                 .name = "CD Playback Volume",
1745                 .info = aureon_ac97_vol_info,
1746                 .get = aureon_ac97_vol_get,
1747                 .put = aureon_ac97_vol_put,
1748                 .private_value = AC97_AUX|AUREON_AC97_STEREO,
1749                 .tlv = { .p = db_scale_ac97_gain }
1750         },
1751         {
1752                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1753                 .name = "Phono Playback Switch",
1754                 .info = aureon_ac97_mute_info,
1755                 .get = aureon_ac97_mute_get,
1756                 .put = aureon_ac97_mute_put,
1757                 .private_value = AC97_CD
1758         },
1759         {
1760                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1761                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1762                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1763                 .name = "Phono Playback Volume",
1764                 .info = aureon_ac97_vol_info,
1765                 .get = aureon_ac97_vol_get,
1766                 .put = aureon_ac97_vol_put,
1767                 .private_value = AC97_CD|AUREON_AC97_STEREO,
1768                 .tlv = { .p = db_scale_ac97_gain }
1769         },
1770         {
1771                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1772                 .name = "Line Playback Switch",
1773                 .info = aureon_ac97_mute_info,
1774                 .get = aureon_ac97_mute_get,
1775                 .put = aureon_ac97_mute_put,
1776                 .private_value = AC97_LINE
1777         },
1778         {
1779                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1780                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1781                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1782                 .name = "Line Playback Volume",
1783                 .info = aureon_ac97_vol_info,
1784                 .get = aureon_ac97_vol_get,
1785                 .put = aureon_ac97_vol_put,
1786                 .private_value = AC97_LINE|AUREON_AC97_STEREO,
1787                 .tlv = { .p = db_scale_ac97_gain }
1788         },
1789         {
1790                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1791                 .name = "Mic Playback Switch",
1792                 .info = aureon_ac97_mute_info,
1793                 .get = aureon_ac97_mute_get,
1794                 .put = aureon_ac97_mute_put,
1795                 .private_value = AC97_MIC
1796         },
1797         {
1798                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1799                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1800                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1801                 .name = "Mic Playback Volume",
1802                 .info = aureon_ac97_vol_info,
1803                 .get = aureon_ac97_vol_get,
1804                 .put = aureon_ac97_vol_put,
1805                 .private_value = AC97_MIC,
1806                 .tlv = { .p = db_scale_ac97_gain }
1807         },
1808         {
1809                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1810                 .name = "Mic Boost (+20dB)",
1811                 .info = aureon_ac97_micboost_info,
1812                 .get = aureon_ac97_micboost_get,
1813                 .put = aureon_ac97_micboost_put
1814         },
1815         {
1816                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1817                 .name = "Aux Playback Switch",
1818                 .info = aureon_ac97_mute_info,
1819                 .get = aureon_ac97_mute_get,
1820                 .put = aureon_ac97_mute_put,
1821                 .private_value = AC97_VIDEO,
1822         },
1823         {
1824                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1825                 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1826                            SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1827                 .name = "Aux Playback Volume",
1828                 .info = aureon_ac97_vol_info,
1829                 .get = aureon_ac97_vol_get,
1830                 .put = aureon_ac97_vol_put,
1831                 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
1832                 .tlv = { .p = db_scale_ac97_gain }
1833         },
1834         {
1835                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1836                 .name = "Aux Source",
1837                 .info = aureon_universe_inmux_info,
1838                 .get = aureon_universe_inmux_get,
1839                 .put = aureon_universe_inmux_put
1840         }
1841 
1842 };
1843 
1844 static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1845         {
1846                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1847                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1848                 .info = aureon_cs8415_mute_info,
1849                 .get = aureon_cs8415_mute_get,
1850                 .put = aureon_cs8415_mute_put
1851         },
1852         {
1853                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1854                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1855                 .info = aureon_cs8415_mux_info,
1856                 .get = aureon_cs8415_mux_get,
1857                 .put = aureon_cs8415_mux_put,
1858         },
1859         {
1860                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1861                 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1862                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1863                 .info = aureon_cs8415_qsub_info,
1864                 .get = aureon_cs8415_qsub_get,
1865         },
1866         {
1867                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1868                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1869                 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1870                 .info = aureon_cs8415_spdif_info,
1871                 .get = aureon_cs8415_mask_get
1872         },
1873         {
1874                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1875                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1876                 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1877                 .info = aureon_cs8415_spdif_info,
1878                 .get = aureon_cs8415_spdif_get
1879         },
1880         {
1881                 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1882                 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1883                 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1884                 .info = aureon_cs8415_rate_info,
1885                 .get = aureon_cs8415_rate_get
1886         }
1887 };
1888 
1889 static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1890 {
1891         unsigned int i, counts;
1892         int err;
1893 
1894         counts = ARRAY_SIZE(aureon_dac_controls);
1895         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1896                 counts -= 2; /* no side */
1897         for (i = 0; i < counts; i++) {
1898                 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1899                 if (err < 0)
1900                         return err;
1901         }
1902 
1903         for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1904                 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1905                 if (err < 0)
1906                         return err;
1907         }
1908         
1909         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1910                 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1911                         err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1912                         if (err < 0)
1913                                 return err;
1914                 }
1915         }
1916         else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1917                  ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1918                 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1919                         err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1920                         if (err < 0)
1921                                 return err;
1922                 }
1923         }
1924 
1925         if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1926             ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1927                 unsigned char id;
1928                 snd_ice1712_save_gpio_status(ice);
1929                 id = aureon_cs8415_get(ice, CS8415_ID);
1930                 if (id != 0x41)
1931                         snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1932                 else if ((id & 0x0F) != 0x01)
1933                         snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1934                 else {
1935                         for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1936                                 struct snd_kcontrol *kctl;
1937                                 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1938                                 if (err < 0)
1939                                         return err;
1940                                 if (i > 1)
1941                                         kctl->id.device = ice->pcm->device;
1942                         }
1943                 }
1944                 snd_ice1712_restore_gpio_status(ice);
1945         }
1946         
1947         return 0;
1948 }
1949 
1950 
1951 /*
1952  * initialize the chip
1953  */
1954 static int __devinit aureon_init(struct snd_ice1712 *ice)
1955 {
1956         static const unsigned short wm_inits_aureon[] = {
1957                 /* These come first to reduce init pop noise */
1958                 0x1b, 0x044,            /* ADC Mux (AC'97 source) */
1959                 0x1c, 0x00B,            /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1960                 0x1d, 0x009,            /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1961 
1962                 0x18, 0x000,            /* All power-up */
1963 
1964                 0x16, 0x122,            /* I2S, normal polarity, 24bit */
1965                 0x17, 0x022,            /* 256fs, slave mode */
1966                 0x00, 0,                /* DAC1 analog mute */
1967                 0x01, 0,                /* DAC2 analog mute */
1968                 0x02, 0,                /* DAC3 analog mute */
1969                 0x03, 0,                /* DAC4 analog mute */
1970                 0x04, 0,                /* DAC5 analog mute */
1971                 0x05, 0,                /* DAC6 analog mute */
1972                 0x06, 0,                /* DAC7 analog mute */
1973                 0x07, 0,                /* DAC8 analog mute */
1974                 0x08, 0x100,            /* master analog mute */
1975                 0x09, 0xff,             /* DAC1 digital full */
1976                 0x0a, 0xff,             /* DAC2 digital full */
1977                 0x0b, 0xff,             /* DAC3 digital full */
1978                 0x0c, 0xff,             /* DAC4 digital full */
1979                 0x0d, 0xff,             /* DAC5 digital full */
1980                 0x0e, 0xff,             /* DAC6 digital full */
1981                 0x0f, 0xff,             /* DAC7 digital full */
1982                 0x10, 0xff,             /* DAC8 digital full */
1983                 0x11, 0x1ff,            /* master digital full */
1984                 0x12, 0x000,            /* phase normal */
1985                 0x13, 0x090,            /* unmute DAC L/R */
1986                 0x14, 0x000,            /* all unmute */
1987                 0x15, 0x000,            /* no deemphasis, no ZFLG */
1988                 0x19, 0x000,            /* -12dB ADC/L */
1989                 0x1a, 0x000,            /* -12dB ADC/R */
1990                 (unsigned short)-1
1991         };
1992         static const unsigned short wm_inits_prodigy[] = {
1993 
1994                 /* These come first to reduce init pop noise */
1995                 0x1b, 0x000,            /* ADC Mux */
1996                 0x1c, 0x009,            /* Out Mux1 */
1997                 0x1d, 0x009,            /* Out Mux2 */
1998 
1999                 0x18, 0x000,            /* All power-up */
2000 
2001                 0x16, 0x022,            /* I2S, normal polarity, 24bit, high-pass on */
2002                 0x17, 0x006,            /* 128fs, slave mode */
2003 
2004                 0x00, 0,                /* DAC1 analog mute */
2005                 0x01, 0,                /* DAC2 analog mute */
2006                 0x02, 0,                /* DAC3 analog mute */
2007                 0x03, 0,                /* DAC4 analog mute */
2008                 0x04, 0,                /* DAC5 analog mute */
2009                 0x05, 0,                /* DAC6 analog mute */
2010                 0x06, 0,                /* DAC7 analog mute */
2011                 0x07, 0,                /* DAC8 analog mute */
2012                 0x08, 0x100,            /* master analog mute */
2013 
2014                 0x09, 0x7f,             /* DAC1 digital full */
2015                 0x0a, 0x7f,             /* DAC2 digital full */
2016                 0x0b, 0x7f,             /* DAC3 digital full */
2017                 0x0c, 0x7f,             /* DAC4 digital full */
2018                 0x0d, 0x7f,             /* DAC5 digital full */
2019                 0x0e, 0x7f,             /* DAC6 digital full */
2020                 0x0f, 0x7f,             /* DAC7 digital full */
2021                 0x10, 0x7f,             /* DAC8 digital full */
2022                 0x11, 0x1FF,            /* master digital full */
2023 
2024                 0x12, 0x000,            /* phase normal */
2025                 0x13, 0x090,            /* unmute DAC L/R */
2026                 0x14, 0x000,            /* all unmute */
2027                 0x15, 0x000,            /* no deemphasis, no ZFLG */
2028 
2029                 0x19, 0x000,            /* -12dB ADC/L */
2030                 0x1a, 0x000,            /* -12dB ADC/R */
2031                 (unsigned short)-1
2032 
2033         };
2034         static const unsigned short cs_inits[] = {
2035                 0x0441, /* RUN */
2036                 0x0180, /* no mute, OMCK output on RMCK pin */
2037                 0x0201, /* S/PDIF source on RXP1 */
2038                 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2039                 (unsigned short)-1
2040         };
2041         struct aureon_spec *spec;
2042         unsigned int tmp;
2043         const unsigned short *p;
2044         int err, i;
2045 
2046         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2047         if (!spec)
2048                 return -ENOMEM;
2049         ice->spec = spec;
2050 
2051         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2052                 ice->num_total_dacs = 6;
2053                 ice->num_total_adcs = 2;
2054         } else {
2055                 /* aureon 7.1 and prodigy 7.1 */
2056                 ice->num_total_dacs = 8;
2057                 ice->num_total_adcs = 2;
2058         }
2059 
2060         /* to remeber the register values of CS8415 */
2061         ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
2062         if (! ice->akm)
2063                 return -ENOMEM;
2064         ice->akm_codecs = 1;
2065         
2066         if ((err = aureon_ac97_init(ice)) != 0)
2067                 return err;
2068 
2069         snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2070 
2071         /* reset the wm codec as the SPI mode */
2072         snd_ice1712_save_gpio_status(ice);
2073         snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2074 
2075         tmp = snd_ice1712_gpio_read(ice);
2076         tmp &= ~AUREON_WM_RESET;
2077         snd_ice1712_gpio_write(ice, tmp);
2078         udelay(1);
2079         tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2080         snd_ice1712_gpio_write(ice, tmp);
2081         udelay(1);
2082         tmp |= AUREON_WM_RESET;
2083         snd_ice1712_gpio_write(ice, tmp);
2084         udelay(1);
2085 
2086         /* initialize WM8770 codec */
2087         if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2088                 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2089                 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2090                 p = wm_inits_prodigy;
2091         else
2092                 p = wm_inits_aureon;
2093         for (; *p != (unsigned short)-1; p += 2)
2094                 wm_put(ice, p[0], p[1]);
2095 
2096         /* initialize CS8415A codec */
2097         if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2098             ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2099                 for (p = cs_inits; *p != (unsigned short)-1; p++)
2100                         aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2101                 spec->cs8415_mux = 1;
2102 
2103                 aureon_set_headphone_amp(ice, 1);
2104         }
2105 
2106         snd_ice1712_restore_gpio_status(ice);
2107 
2108         /* initialize PCA9554 pin directions & set default input*/
2109         aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2110         aureon_pca9554_write(ice, PCA9554_OUT, 0x00);   /* internal AUX */
2111         
2112         spec->master[0] = WM_VOL_MUTE;
2113         spec->master[1] = WM_VOL_MUTE;
2114         for (i = 0; i < ice->num_total_dacs; i++) {
2115                 spec->vol[i] = WM_VOL_MUTE;
2116                 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
2117         }
2118 
2119         return 0;
2120 }
2121 
2122 
2123 /*
2124  * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2125  * hence the driver needs to sets up it properly.
2126  */
2127 
2128 static unsigned char aureon51_eeprom[] __devinitdata = {
2129         [ICE_EEP2_SYSCONF]     = 0x0a,  /* clock 512, spdif-in/ADC, 3DACs */
2130         [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2131         [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2132         [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2133         [ICE_EEP2_GPIO_DIR]    = 0xff,
2134         [ICE_EEP2_GPIO_DIR1]   = 0xff,
2135         [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2136         [ICE_EEP2_GPIO_MASK]   = 0x00,
2137         [ICE_EEP2_GPIO_MASK1]  = 0x00,
2138         [ICE_EEP2_GPIO_MASK2]  = 0x00,
2139         [ICE_EEP2_GPIO_STATE]  = 0x00,
2140         [ICE_EEP2_GPIO_STATE1] = 0x00,
2141         [ICE_EEP2_GPIO_STATE2] = 0x00,
2142 };
2143 
2144 static unsigned char aureon71_eeprom[] __devinitdata = {
2145         [ICE_EEP2_SYSCONF]     = 0x0b,  /* clock 512, spdif-in/ADC, 4DACs */
2146         [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2147         [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2148         [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2149         [ICE_EEP2_GPIO_DIR]    = 0xff,
2150         [ICE_EEP2_GPIO_DIR1]   = 0xff,
2151         [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2152         [ICE_EEP2_GPIO_MASK]   = 0x00,
2153         [ICE_EEP2_GPIO_MASK1]  = 0x00,
2154         [ICE_EEP2_GPIO_MASK2]  = 0x00,
2155         [ICE_EEP2_GPIO_STATE]  = 0x00,
2156         [ICE_EEP2_GPIO_STATE1] = 0x00,
2157         [ICE_EEP2_GPIO_STATE2] = 0x00,
2158 };
2159 #define prodigy71_eeprom aureon71_eeprom
2160 
2161 static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2162         [ICE_EEP2_SYSCONF]     = 0x4b,  /* clock 384, spdif-in/ADC, 4DACs */
2163         [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
2164         [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
2165         [ICE_EEP2_SPDIF]       = 0xc3,  /* out-en, out-int, spdif-in */
2166         [ICE_EEP2_GPIO_DIR]    = 0xff,
2167         [ICE_EEP2_GPIO_DIR1]   = 0xff,
2168         [ICE_EEP2_GPIO_DIR2]   = 0x5f,
2169         [ICE_EEP2_GPIO_MASK]   = 0x00,
2170         [ICE_EEP2_GPIO_MASK1]  = 0x00,
2171         [ICE_EEP2_GPIO_MASK2]  = 0x00,
2172         [ICE_EEP2_GPIO_STATE]  = 0x00,
2173         [ICE_EEP2_GPIO_STATE1] = 0x00,
2174         [ICE_EEP2_GPIO_STATE2] = 0x00,
2175 };
2176 #define prodigy71xt_eeprom prodigy71lt_eeprom
2177 
2178 /* entry point */
2179 struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2180         {
2181                 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2182                 .name = "Terratec Aureon 5.1-Sky",
2183                 .model = "aureon51",
2184                 .chip_init = aureon_init,
2185                 .build_controls = aureon_add_controls,
2186                 .eeprom_size = sizeof(aureon51_eeprom),
2187                 .eeprom_data = aureon51_eeprom,
2188                 .driver = "Aureon51",
2189         },
2190         {
2191                 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2192                 .name = "Terratec Aureon 7.1-Space",
2193                 .model = "aureon71",
2194                 .chip_init = aureon_init,
2195                 .build_controls = aureon_add_controls,
2196                 .eeprom_size = sizeof(aureon71_eeprom),
2197                 .eeprom_data = aureon71_eeprom,
2198                 .driver = "Aureon71",
2199         },
2200         {
2201                 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2202                 .name = "Terratec Aureon 7.1-Universe",
2203                 .model = "universe",
2204                 .chip_init = aureon_init,
2205                 .build_controls = aureon_add_controls,
2206                 .eeprom_size = sizeof(aureon71_eeprom),
2207                 .eeprom_data = aureon71_eeprom,
2208                 .driver = "Aureon71Univ", /* keep in 15 letters */
2209         },
2210         {
2211                 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2212                 .name = "Audiotrak Prodigy 7.1",
2213                 .model = "prodigy71",
2214                 .chip_init = aureon_init,
2215                 .build_controls = aureon_add_controls,
2216                 .eeprom_size = sizeof(prodigy71_eeprom),
2217                 .eeprom_data = prodigy71_eeprom,
2218                 .driver = "Prodigy71", /* should be identical with Aureon71 */
2219         },
2220         {
2221                 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2222                 .name = "Audiotrak Prodigy 7.1 LT",
2223                 .model = "prodigy71lt",
2224                 .chip_init = aureon_init,
2225                 .build_controls = aureon_add_controls,
2226                 .eeprom_size = sizeof(prodigy71lt_eeprom),
2227                 .eeprom_data = prodigy71lt_eeprom,
2228                 .driver = "Prodigy71LT",
2229         },
2230         {
2231                 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2232                 .name = "Audiotrak Prodigy 7.1 XT",
2233                 .model = "prodigy71xt",
2234                 .chip_init = aureon_init,
2235                 .build_controls = aureon_add_controls,
2236                 .eeprom_size = sizeof(prodigy71xt_eeprom),
2237                 .eeprom_data = prodigy71xt_eeprom,
2238                 .driver = "Prodigy71LT",
2239         },
2240         { } /* terminator */
2241 };
2242 
  This page was automatically generated by the LXR engine.