aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ice1712/aureon.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/pci/ice1712/aureon.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'sound/pci/ice1712/aureon.c')
-rw-r--r--sound/pci/ice1712/aureon.c1948
1 files changed, 1948 insertions, 0 deletions
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
new file mode 100644
index 000000000000..4405d96cbedf
--- /dev/null
+++ b/sound/pci/ice1712/aureon.c
@@ -0,0 +1,1948 @@
1/*
2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
3 *
4 * Lowlevel functions for Terratec Aureon cards
5 *
6 * Copyright (c) 2003 Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 *
23 * NOTES:
24 *
25 * - we reuse the akm4xxx_t record for storing the wm8770 codec data.
26 * both wm and akm codecs are pretty similar, so we can integrate
27 * both controls in the future, once if wm codecs are reused in
28 * many boards.
29 *
30 * - 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 <sound/driver.h>
51#include <asm/io.h>
52#include <linux/delay.h>
53#include <linux/interrupt.h>
54#include <linux/init.h>
55#include <linux/slab.h>
56#include <sound/core.h>
57
58#include "ice1712.h"
59#include "envy24ht.h"
60#include "aureon.h"
61
62/* WM8770 registers */
63#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
64#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
65#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
66#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
67#define WM_PHASE_SWAP 0x12 /* DAC phase */
68#define WM_DAC_CTRL1 0x13 /* DAC control bits */
69#define WM_MUTE 0x14 /* mute controls */
70#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
71#define WM_INT_CTRL 0x16 /* interface control */
72#define WM_MASTER 0x17 /* master clock and mode */
73#define WM_POWERDOWN 0x18 /* power-down controls */
74#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
75#define WM_ADC_MUX 0x1b /* input MUX */
76#define WM_OUT_MUX1 0x1c /* output MUX */
77#define WM_OUT_MUX2 0x1e /* output MUX */
78#define WM_RESET 0x1f /* software reset */
79
80/* CS8415A registers */
81#define CS8415_CTRL1 0x01
82#define CS8415_CTRL2 0x02
83#define CS8415_QSUB 0x14
84#define CS8415_RATIO 0x1E
85#define CS8415_C_BUFFER 0x20
86#define CS8415_ID 0x7F
87
88static void aureon_ac97_write(ice1712_t *ice, unsigned short reg, unsigned short val) {
89 unsigned int tmp;
90
91 /* Send address to XILINX chip */
92 tmp = (snd_ice1712_gpio_read(ice) & ~0xFF) | (reg & 0x7F);
93 snd_ice1712_gpio_write(ice, tmp);
94 udelay(10);
95 tmp |= AUREON_AC97_ADDR;
96 snd_ice1712_gpio_write(ice, tmp);
97 udelay(10);
98 tmp &= ~AUREON_AC97_ADDR;
99 snd_ice1712_gpio_write(ice, tmp);
100 udelay(10);
101
102 /* Send low-order byte to XILINX chip */
103 tmp &= ~AUREON_AC97_DATA_MASK;
104 tmp |= val & AUREON_AC97_DATA_MASK;
105 snd_ice1712_gpio_write(ice, tmp);
106 udelay(10);
107 tmp |= AUREON_AC97_DATA_LOW;
108 snd_ice1712_gpio_write(ice, tmp);
109 udelay(10);
110 tmp &= ~AUREON_AC97_DATA_LOW;
111 snd_ice1712_gpio_write(ice, tmp);
112 udelay(10);
113
114 /* Send high-order byte to XILINX chip */
115 tmp &= ~AUREON_AC97_DATA_MASK;
116 tmp |= (val >> 8) & AUREON_AC97_DATA_MASK;
117
118 snd_ice1712_gpio_write(ice, tmp);
119 udelay(10);
120 tmp |= AUREON_AC97_DATA_HIGH;
121 snd_ice1712_gpio_write(ice, tmp);
122 udelay(10);
123 tmp &= ~AUREON_AC97_DATA_HIGH;
124 snd_ice1712_gpio_write(ice, tmp);
125 udelay(10);
126
127 /* Instruct XILINX chip to parse the data to the STAC9744 chip */
128 tmp |= AUREON_AC97_COMMIT;
129 snd_ice1712_gpio_write(ice, tmp);
130 udelay(10);
131 tmp &= ~AUREON_AC97_COMMIT;
132 snd_ice1712_gpio_write(ice, tmp);
133 udelay(10);
134
135 /* Store the data in out private buffer */
136 ice->spec.aureon.stac9744[(reg & 0x7F) >> 1] = val;
137}
138
139static unsigned short aureon_ac97_read(ice1712_t *ice, unsigned short reg)
140{
141 return ice->spec.aureon.stac9744[(reg & 0x7F) >> 1];
142}
143
144/*
145 * Initialize STAC9744 chip
146 */
147static int aureon_ac97_init (ice1712_t *ice) {
148 int i;
149 static unsigned short ac97_defaults[] = {
150 0x00, 0x9640,
151 0x02, 0x8000,
152 0x04, 0x8000,
153 0x06, 0x8000,
154 0x0C, 0x8008,
155 0x0E, 0x8008,
156 0x10, 0x8808,
157 0x12, 0x8808,
158 0x14, 0x8808,
159 0x16, 0x8808,
160 0x18, 0x8808,
161 0x1C, 0x8000,
162 0x26, 0x000F,
163 0x28, 0x0201,
164 0x2C, 0xBB80,
165 0x32, 0xBB80,
166 0x7C, 0x8384,
167 0x7E, 0x7644,
168 (unsigned short)-1
169 };
170 unsigned int tmp;
171
172 /* Cold reset */
173 tmp = (snd_ice1712_gpio_read(ice) | AUREON_AC97_RESET) & ~AUREON_AC97_DATA_MASK;
174 snd_ice1712_gpio_write(ice, tmp);
175 udelay(3);
176
177 tmp &= ~AUREON_AC97_RESET;
178 snd_ice1712_gpio_write(ice, tmp);
179 udelay(3);
180
181 tmp |= AUREON_AC97_RESET;
182 snd_ice1712_gpio_write(ice, tmp);
183 udelay(3);
184
185 memset(&ice->spec.aureon.stac9744, 0, sizeof(ice->spec.aureon.stac9744));
186 for (i=0; ac97_defaults[i] != (unsigned short)-1; i+=2)
187 ice->spec.aureon.stac9744[(ac97_defaults[i]) >> 1] = ac97_defaults[i+1];
188
189 aureon_ac97_write(ice, AC97_MASTER, 0x0000); // Unmute AC'97 master volume permanently - muting is done by WM8770
190
191 return 0;
192}
193
194#define AUREON_AC97_STEREO 0x80
195
196/*
197 * AC'97 volume controls
198 */
199static int aureon_ac97_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
200{
201 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
202 uinfo->count = kcontrol->private_value & AUREON_AC97_STEREO ? 2 : 1;
203 uinfo->value.integer.min = 0;
204 uinfo->value.integer.max = 31;
205 return 0;
206}
207
208static int aureon_ac97_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
209{
210 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
211 unsigned short vol;
212
213 down(&ice->gpio_mutex);
214
215 vol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
216 ucontrol->value.integer.value[0] = 0x1F - (vol & 0x1F);
217 if (kcontrol->private_value & AUREON_AC97_STEREO)
218 ucontrol->value.integer.value[1] = 0x1F - ((vol >> 8) & 0x1F);
219
220 up(&ice->gpio_mutex);
221 return 0;
222}
223
224static int aureon_ac97_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
225{
226 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
227 unsigned short ovol, nvol;
228 int change;
229
230 snd_ice1712_save_gpio_status(ice);
231
232 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
233 nvol = (0x1F - ucontrol->value.integer.value[0]) & 0x001F;
234 if (kcontrol->private_value & AUREON_AC97_STEREO)
235 nvol |= ((0x1F - ucontrol->value.integer.value[1]) << 8) & 0x1F00;
236 nvol |= ovol & ~0x1F1F;
237
238 if ((change = (ovol != nvol)))
239 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
240
241 snd_ice1712_restore_gpio_status(ice);
242
243 return change;
244}
245
246/*
247 * AC'97 mute controls
248 */
249#define aureon_ac97_mute_info aureon_mono_bool_info
250
251static int aureon_ac97_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
252{
253 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
254
255 down(&ice->gpio_mutex);
256
257 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, kcontrol->private_value & 0x7F) & 0x8000 ? 0 : 1;
258
259 up(&ice->gpio_mutex);
260 return 0;
261}
262
263static int aureon_ac97_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
264{
265 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
266 unsigned short ovol, nvol;
267 int change;
268
269 snd_ice1712_save_gpio_status(ice);
270
271 ovol = aureon_ac97_read(ice, kcontrol->private_value & 0x7F);
272 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x8000) | (ovol & ~ 0x8000);
273
274 if ((change = (ovol != nvol)))
275 aureon_ac97_write(ice, kcontrol->private_value & 0x7F, nvol);
276
277 snd_ice1712_restore_gpio_status(ice);
278
279 return change;
280}
281
282/*
283 * AC'97 mute controls
284 */
285#define aureon_ac97_micboost_info aureon_mono_bool_info
286
287static int aureon_ac97_micboost_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
288{
289 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
290
291 down(&ice->gpio_mutex);
292
293 ucontrol->value.integer.value[0] = aureon_ac97_read(ice, AC97_MIC) & 0x0020 ? 0 : 1;
294
295 up(&ice->gpio_mutex);
296 return 0;
297}
298
299static int aureon_ac97_micboost_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
300{
301 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
302 unsigned short ovol, nvol;
303 int change;
304
305 snd_ice1712_save_gpio_status(ice);
306
307 ovol = aureon_ac97_read(ice, AC97_MIC);
308 nvol = (ucontrol->value.integer.value[0] ? 0x0000 : 0x0020) | (ovol & ~0x0020);
309
310 if ((change = (ovol != nvol)))
311 aureon_ac97_write(ice, AC97_MIC, nvol);
312
313 snd_ice1712_restore_gpio_status(ice);
314
315 return change;
316}
317
318/*
319 * write data in the SPI mode
320 */
321static void aureon_spi_write(ice1712_t *ice, unsigned int cs, unsigned int data, int bits)
322{
323 unsigned int tmp;
324 int i;
325
326 tmp = snd_ice1712_gpio_read(ice);
327
328 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RW|AUREON_SPI_MOSI|AUREON_SPI_CLK|
329 AUREON_WM_CS|AUREON_CS8415_CS));
330 tmp |= AUREON_WM_RW;
331 tmp &= ~cs;
332 snd_ice1712_gpio_write(ice, tmp);
333 udelay(1);
334
335 for (i = bits - 1; i >= 0; i--) {
336 tmp &= ~AUREON_SPI_CLK;
337 snd_ice1712_gpio_write(ice, tmp);
338 udelay(1);
339 if (data & (1 << i))
340 tmp |= AUREON_SPI_MOSI;
341 else
342 tmp &= ~AUREON_SPI_MOSI;
343 snd_ice1712_gpio_write(ice, tmp);
344 udelay(1);
345 tmp |= AUREON_SPI_CLK;
346 snd_ice1712_gpio_write(ice, tmp);
347 udelay(1);
348 }
349
350 tmp &= ~AUREON_SPI_CLK;
351 tmp |= cs;
352 snd_ice1712_gpio_write(ice, tmp);
353 udelay(1);
354 tmp |= AUREON_SPI_CLK;
355 snd_ice1712_gpio_write(ice, tmp);
356 udelay(1);
357}
358
359/*
360 * Read data in SPI mode
361 */
362static void aureon_spi_read(ice1712_t *ice, unsigned int cs, unsigned int data, int bits, unsigned char *buffer, int size) {
363 int i, j;
364 unsigned int tmp;
365
366 tmp = (snd_ice1712_gpio_read(ice) & ~AUREON_SPI_CLK) | AUREON_CS8415_CS|AUREON_WM_CS;
367 snd_ice1712_gpio_write(ice, tmp);
368 tmp &= ~cs;
369 snd_ice1712_gpio_write(ice, tmp);
370 udelay(1);
371
372 for (i=bits-1; i>=0; i--) {
373 if (data & (1 << i))
374 tmp |= AUREON_SPI_MOSI;
375 else
376 tmp &= ~AUREON_SPI_MOSI;
377 snd_ice1712_gpio_write(ice, tmp);
378 udelay(1);
379
380 tmp |= AUREON_SPI_CLK;
381 snd_ice1712_gpio_write(ice, tmp);
382 udelay(1);
383
384 tmp &= ~AUREON_SPI_CLK;
385 snd_ice1712_gpio_write(ice, tmp);
386 udelay(1);
387 }
388
389 for (j=0; j<size; j++) {
390 unsigned char outdata = 0;
391 for (i=7; i>=0; i--) {
392 tmp = snd_ice1712_gpio_read(ice);
393 outdata <<= 1;
394 outdata |= (tmp & AUREON_SPI_MISO) ? 1 : 0;
395 udelay(1);
396
397 tmp |= AUREON_SPI_CLK;
398 snd_ice1712_gpio_write(ice, tmp);
399 udelay(1);
400
401 tmp &= ~AUREON_SPI_CLK;
402 snd_ice1712_gpio_write(ice, tmp);
403 udelay(1);
404 }
405 buffer[j] = outdata;
406 }
407
408 tmp |= cs;
409 snd_ice1712_gpio_write(ice, tmp);
410}
411
412static unsigned char aureon_cs8415_get(ice1712_t *ice, int reg) {
413 unsigned char val;
414 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
415 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, &val, 1);
416 return val;
417}
418
419static void aureon_cs8415_read(ice1712_t *ice, int reg, unsigned char *buffer, int size) {
420 aureon_spi_write(ice, AUREON_CS8415_CS, 0x2000 | reg, 16);
421 aureon_spi_read(ice, AUREON_CS8415_CS, 0x21, 8, buffer, size);
422}
423
424static void aureon_cs8415_put(ice1712_t *ice, int reg, unsigned char val) {
425 aureon_spi_write(ice, AUREON_CS8415_CS, 0x200000 | (reg << 8) | val, 24);
426}
427
428/*
429 * get the current register value of WM codec
430 */
431static unsigned short wm_get(ice1712_t *ice, int reg)
432{
433 reg <<= 1;
434 return ((unsigned short)ice->akm[0].images[reg] << 8) |
435 ice->akm[0].images[reg + 1];
436}
437
438/*
439 * set the register value of WM codec
440 */
441static void wm_put_nocache(ice1712_t *ice, int reg, unsigned short val)
442{
443 aureon_spi_write(ice, AUREON_WM_CS, (reg << 9) | (val & 0x1ff), 16);
444}
445
446/*
447 * set the register value of WM codec and remember it
448 */
449static void wm_put(ice1712_t *ice, int reg, unsigned short val)
450{
451 wm_put_nocache(ice, reg, val);
452 reg <<= 1;
453 ice->akm[0].images[reg] = val >> 8;
454 ice->akm[0].images[reg + 1] = val;
455}
456
457/*
458 */
459static int aureon_mono_bool_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
460{
461 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
462 uinfo->count = 1;
463 uinfo->value.integer.min = 0;
464 uinfo->value.integer.max = 1;
465 return 0;
466}
467
468/*
469 * AC'97 master playback mute controls (Mute on WM8770 chip)
470 */
471#define aureon_ac97_mmute_info aureon_mono_bool_info
472
473static int aureon_ac97_mmute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
474{
475 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
476
477 down(&ice->gpio_mutex);
478
479 ucontrol->value.integer.value[0] = (wm_get(ice, WM_OUT_MUX1) >> 1) & 0x01;
480
481 up(&ice->gpio_mutex);
482 return 0;
483}
484
485static int aureon_ac97_mmute_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
486 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
487 unsigned short ovol, nvol;
488 int change;
489
490 snd_ice1712_save_gpio_status(ice);
491
492 ovol = wm_get(ice, WM_OUT_MUX1);
493 nvol = (ovol & ~0x02) | (ucontrol->value.integer.value[0] ? 0x02 : 0x00);
494 if ((change = (ovol != nvol)))
495 wm_put(ice, WM_OUT_MUX1, nvol);
496
497 snd_ice1712_restore_gpio_status(ice);
498
499 return change;
500}
501
502/*
503 * Logarithmic volume values for WM8770
504 * Computed as 20 * Log10(255 / x)
505 */
506static unsigned char wm_vol[256] = {
507 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
508 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
509 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
510 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
511 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
512 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,
513 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,
514 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,
515 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,
516 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,
517 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,
518 0, 0
519};
520
521#define WM_VOL_MAX (sizeof(wm_vol) - 1)
522#define WM_VOL_MUTE 0x8000
523
524static void wm_set_vol(ice1712_t *ice, unsigned int index, unsigned short vol, unsigned short master)
525{
526 unsigned char nvol;
527
528 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
529 nvol = 0;
530 else
531 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
532
533 wm_put(ice, index, nvol);
534 wm_put_nocache(ice, index, 0x180 | nvol);
535}
536
537/*
538 * DAC mute control
539 */
540#define wm_pcm_mute_info aureon_mono_bool_info
541
542static int wm_pcm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
543{
544 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
545
546 down(&ice->gpio_mutex);
547 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
548 up(&ice->gpio_mutex);
549 return 0;
550}
551
552static int wm_pcm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
553{
554 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
555 unsigned short nval, oval;
556 int change;
557
558 snd_ice1712_save_gpio_status(ice);
559 oval = wm_get(ice, WM_MUTE);
560 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
561 if ((change = (nval != oval)))
562 wm_put(ice, WM_MUTE, nval);
563 snd_ice1712_restore_gpio_status(ice);
564
565 return change;
566}
567
568/*
569 * Master volume attenuation mixer control
570 */
571static int wm_master_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
572{
573 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
574 uinfo->count = 2;
575 uinfo->value.integer.min = 0;
576 uinfo->value.integer.max = WM_VOL_MAX;
577 return 0;
578}
579
580static int wm_master_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
581{
582 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
583 int i;
584 for (i=0; i<2; i++)
585 ucontrol->value.integer.value[i] = ice->spec.aureon.master[i] & ~WM_VOL_MUTE;
586 return 0;
587}
588
589static int wm_master_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
590{
591 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
592 int ch, change = 0;
593
594 snd_ice1712_save_gpio_status(ice);
595 for (ch = 0; ch < 2; ch++) {
596 if (ucontrol->value.integer.value[ch] != ice->spec.aureon.master[ch]) {
597 int dac;
598 ice->spec.aureon.master[ch] &= WM_VOL_MUTE;
599 ice->spec.aureon.master[ch] |= ucontrol->value.integer.value[ch];
600 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
601 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
602 ice->spec.aureon.vol[dac + ch],
603 ice->spec.aureon.master[ch]);
604 change = 1;
605 }
606 }
607 snd_ice1712_restore_gpio_status(ice);
608 return change;
609}
610
611/*
612 * DAC volume attenuation mixer control
613 */
614static int wm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
615{
616 int voices = kcontrol->private_value >> 8;
617 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
618 uinfo->count = voices;
619 uinfo->value.integer.min = 0; /* mute (-101dB) */
620 uinfo->value.integer.max = 0x7F; /* 0dB */
621 return 0;
622}
623
624static int wm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
625{
626 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
627 int i, ofs, voices;
628
629 voices = kcontrol->private_value >> 8;
630 ofs = kcontrol->private_value & 0xff;
631 for (i = 0; i < voices; i++)
632 ucontrol->value.integer.value[i] = ice->spec.aureon.vol[ofs+i] & ~WM_VOL_MUTE;
633 return 0;
634}
635
636static int wm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
637{
638 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
639 int i, idx, ofs, voices;
640 int change = 0;
641
642 voices = kcontrol->private_value >> 8;
643 ofs = kcontrol->private_value & 0xff;
644 snd_ice1712_save_gpio_status(ice);
645 for (i = 0; i < voices; i++) {
646 idx = WM_DAC_ATTEN + ofs + i;
647 if (ucontrol->value.integer.value[i] != ice->spec.aureon.vol[ofs+i]) {
648 ice->spec.aureon.vol[ofs+i] &= WM_VOL_MUTE;
649 ice->spec.aureon.vol[ofs+i] |= ucontrol->value.integer.value[i];
650 wm_set_vol(ice, idx, ice->spec.aureon.vol[ofs+i],
651 ice->spec.aureon.master[i]);
652 change = 1;
653 }
654 }
655 snd_ice1712_restore_gpio_status(ice);
656 return change;
657}
658
659/*
660 * WM8770 mute control
661 */
662static int wm_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
663 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
664 uinfo->count = kcontrol->private_value >> 8;
665 uinfo->value.integer.min = 0;
666 uinfo->value.integer.max = 1;
667 return 0;
668}
669
670static int wm_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
671{
672 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
673 int voices, ofs, i;
674
675 voices = kcontrol->private_value >> 8;
676 ofs = kcontrol->private_value & 0xFF;
677
678 for (i = 0; i < voices; i++)
679 ucontrol->value.integer.value[i] = (ice->spec.aureon.vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
680 return 0;
681}
682
683static int wm_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
684{
685 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
686 int change = 0, voices, ofs, i;
687
688 voices = kcontrol->private_value >> 8;
689 ofs = kcontrol->private_value & 0xFF;
690
691 snd_ice1712_save_gpio_status(ice);
692 for (i = 0; i < voices; i++) {
693 int val = (ice->spec.aureon.vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
694 if (ucontrol->value.integer.value[i] != val) {
695 ice->spec.aureon.vol[ofs + i] &= ~WM_VOL_MUTE;
696 ice->spec.aureon.vol[ofs + i] |=
697 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
698 wm_set_vol(ice, ofs + i, ice->spec.aureon.vol[ofs + i],
699 ice->spec.aureon.master[i]);
700 change = 1;
701 }
702 }
703 snd_ice1712_restore_gpio_status(ice);
704
705 return change;
706}
707
708/*
709 * WM8770 master mute control
710 */
711static int wm_master_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
712 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
713 uinfo->count = 2;
714 uinfo->value.integer.min = 0;
715 uinfo->value.integer.max = 1;
716 return 0;
717}
718
719static int wm_master_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
720{
721 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
722
723 ucontrol->value.integer.value[0] = (ice->spec.aureon.master[0] & WM_VOL_MUTE) ? 0 : 1;
724 ucontrol->value.integer.value[1] = (ice->spec.aureon.master[1] & WM_VOL_MUTE) ? 0 : 1;
725 return 0;
726}
727
728static int wm_master_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
729{
730 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
731 int change = 0, i;
732
733 snd_ice1712_save_gpio_status(ice);
734 for (i = 0; i < 2; i++) {
735 int val = (ice->spec.aureon.master[i] & WM_VOL_MUTE) ? 0 : 1;
736 if (ucontrol->value.integer.value[i] != val) {
737 int dac;
738 ice->spec.aureon.master[i] &= ~WM_VOL_MUTE;
739 ice->spec.aureon.master[i] |=
740 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
741 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
742 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
743 ice->spec.aureon.vol[dac + i],
744 ice->spec.aureon.master[i]);
745 change = 1;
746 }
747 }
748 snd_ice1712_restore_gpio_status(ice);
749
750 return change;
751}
752
753/* digital master volume */
754#define PCM_0dB 0xff
755#define PCM_RES 128 /* -64dB */
756#define PCM_MIN (PCM_0dB - PCM_RES)
757static int wm_pcm_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
758{
759 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
760 uinfo->count = 1;
761 uinfo->value.integer.min = 0; /* mute (-64dB) */
762 uinfo->value.integer.max = PCM_RES; /* 0dB */
763 return 0;
764}
765
766static int wm_pcm_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
767{
768 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
769 unsigned short val;
770
771 down(&ice->gpio_mutex);
772 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
773 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
774 ucontrol->value.integer.value[0] = val;
775 up(&ice->gpio_mutex);
776 return 0;
777}
778
779static int wm_pcm_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
780{
781 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
782 unsigned short ovol, nvol;
783 int change = 0;
784
785 snd_ice1712_save_gpio_status(ice);
786 nvol = ucontrol->value.integer.value[0];
787 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
788 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
789 if (ovol != nvol) {
790 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
791 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
792 change = 1;
793 }
794 snd_ice1712_restore_gpio_status(ice);
795 return change;
796}
797
798/*
799 * ADC mute control
800 */
801static int wm_adc_mute_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
802{
803 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
804 uinfo->count = 2;
805 uinfo->value.integer.min = 0;
806 uinfo->value.integer.max = 1;
807 return 0;
808}
809
810static int wm_adc_mute_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
811{
812 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
813 unsigned short val;
814 int i;
815
816 down(&ice->gpio_mutex);
817 for (i = 0; i < 2; i++) {
818 val = wm_get(ice, WM_ADC_GAIN + i);
819 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
820 }
821 up(&ice->gpio_mutex);
822 return 0;
823}
824
825static int wm_adc_mute_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
826{
827 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
828 unsigned short new, old;
829 int i, change = 0;
830
831 snd_ice1712_save_gpio_status(ice);
832 for (i = 0; i < 2; i++) {
833 old = wm_get(ice, WM_ADC_GAIN + i);
834 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
835 if (new != old) {
836 wm_put(ice, WM_ADC_GAIN + i, new);
837 change = 1;
838 }
839 }
840 snd_ice1712_restore_gpio_status(ice);
841
842 return change;
843}
844
845/*
846 * ADC gain mixer control
847 */
848static int wm_adc_vol_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
849{
850 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
851 uinfo->count = 2;
852 uinfo->value.integer.min = 0; /* -12dB */
853 uinfo->value.integer.max = 0x1f; /* 19dB */
854 return 0;
855}
856
857static int wm_adc_vol_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
858{
859 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
860 int i, idx;
861 unsigned short vol;
862
863 down(&ice->gpio_mutex);
864 for (i = 0; i < 2; i++) {
865 idx = WM_ADC_GAIN + i;
866 vol = wm_get(ice, idx) & 0x1f;
867 ucontrol->value.integer.value[i] = vol;
868 }
869 up(&ice->gpio_mutex);
870 return 0;
871}
872
873static int wm_adc_vol_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
874{
875 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
876 int i, idx;
877 unsigned short ovol, nvol;
878 int change = 0;
879
880 snd_ice1712_save_gpio_status(ice);
881 for (i = 0; i < 2; i++) {
882 idx = WM_ADC_GAIN + i;
883 nvol = ucontrol->value.integer.value[i];
884 ovol = wm_get(ice, idx);
885 if ((ovol & 0x1f) != nvol) {
886 wm_put(ice, idx, nvol | (ovol & ~0x1f));
887 change = 1;
888 }
889 }
890 snd_ice1712_restore_gpio_status(ice);
891 return change;
892}
893
894/*
895 * ADC input mux mixer control
896 */
897static int wm_adc_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
898{
899 static char *texts[] = {
900 "CD", //AIN1
901 "Aux", //AIN2
902 "Line", //AIN3
903 "Mic", //AIN4
904 "AC97" //AIN5
905 };
906 static char *universe_texts[] = {
907 "Aux1", //AIN1
908 "CD", //AIN2
909 "Phono", //AIN3
910 "Line", //AIN4
911 "Aux2", //AIN5
912 "Mic", //AIN6
913 "Aux3", //AIN7
914 "AC97" //AIN8
915 };
916 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
917
918 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
919 uinfo->count = 2;
920 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
921 uinfo->value.enumerated.items = 8;
922 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
923 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
924 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
925 }
926 else {
927 uinfo->value.enumerated.items = 5;
928 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
929 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
930 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
931 }
932 return 0;
933}
934
935static int wm_adc_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
936{
937 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
938 unsigned short val;
939
940 down(&ice->gpio_mutex);
941 val = wm_get(ice, WM_ADC_MUX);
942 ucontrol->value.integer.value[0] = val & 7;
943 ucontrol->value.integer.value[1] = (val >> 4) & 7;
944 up(&ice->gpio_mutex);
945 return 0;
946}
947
948static int wm_adc_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
949{
950 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
951 unsigned short oval, nval;
952 int change;
953
954 snd_ice1712_save_gpio_status(ice);
955 oval = wm_get(ice, WM_ADC_MUX);
956 nval = oval & ~0x77;
957 nval |= ucontrol->value.integer.value[0] & 7;
958 nval |= (ucontrol->value.integer.value[1] & 7) << 4;
959 change = (oval != nval);
960 if (change)
961 wm_put(ice, WM_ADC_MUX, nval);
962 snd_ice1712_restore_gpio_status(ice);
963 return 0;
964}
965
966/*
967 * CS8415 Input mux
968 */
969static int aureon_cs8415_mux_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
970{
971 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
972 static char *aureon_texts[] = {
973 "CD", //RXP0
974 "Optical" //RXP1
975 };
976 static char *prodigy_texts[] = {
977 "CD",
978 "Coax"
979 };
980 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
981 uinfo->count = 1;
982 uinfo->value.enumerated.items = 2;
983 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
984 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
985 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
986 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
987 else
988 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
989 return 0;
990}
991
992static int aureon_cs8415_mux_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
993{
994 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
995
996 //snd_ice1712_save_gpio_status(ice);
997 //val = aureon_cs8415_get(ice, CS8415_CTRL2);
998 ucontrol->value.integer.value[0] = ice->spec.aureon.cs8415_mux;
999 //snd_ice1712_restore_gpio_status(ice);
1000 return 0;
1001}
1002
1003static int aureon_cs8415_mux_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
1004{
1005 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1006 unsigned short oval, nval;
1007 int change;
1008
1009 snd_ice1712_save_gpio_status(ice);
1010 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1011 nval = oval & ~0x07;
1012 nval |= ucontrol->value.integer.value[0] & 7;
1013 change = (oval != nval);
1014 if (change)
1015 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1016 snd_ice1712_restore_gpio_status(ice);
1017 ice->spec.aureon.cs8415_mux = ucontrol->value.integer.value[0];
1018 return change;
1019}
1020
1021static int aureon_cs8415_rate_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1022{
1023 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1024 uinfo->count = 1;
1025 uinfo->value.integer.min = 0;
1026 uinfo->value.integer.max = 192000;
1027 return 0;
1028}
1029
1030static int aureon_cs8415_rate_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1031{
1032 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1033 unsigned char ratio;
1034 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1035 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1036 return 0;
1037}
1038
1039/*
1040 * CS8415A Mute
1041 */
1042static int aureon_cs8415_mute_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1043{
1044 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1045 uinfo->count = 1;
1046 return 0;
1047}
1048
1049static int aureon_cs8415_mute_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1050{
1051 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1052 snd_ice1712_save_gpio_status(ice);
1053 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1054 snd_ice1712_restore_gpio_status(ice);
1055 return 0;
1056}
1057
1058static int aureon_cs8415_mute_put (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1059{
1060 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1061 unsigned char oval, nval;
1062 int change;
1063 snd_ice1712_save_gpio_status(ice);
1064 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1065 if (ucontrol->value.integer.value[0])
1066 nval = oval & ~0x20;
1067 else
1068 nval = oval | 0x20;
1069 if ((change = (oval != nval)))
1070 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1071 snd_ice1712_restore_gpio_status(ice);
1072 return change;
1073}
1074
1075/*
1076 * CS8415A Q-Sub info
1077 */
1078static int aureon_cs8415_qsub_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
1079 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1080 uinfo->count = 10;
1081 return 0;
1082}
1083
1084static int aureon_cs8415_qsub_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
1085 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1086
1087 snd_ice1712_save_gpio_status(ice);
1088 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1089 snd_ice1712_restore_gpio_status(ice);
1090
1091 return 0;
1092}
1093
1094static int aureon_cs8415_spdif_info (snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) {
1095 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1096 uinfo->count = 1;
1097 return 0;
1098}
1099
1100static int aureon_cs8415_mask_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
1101 memset(ucontrol->value.iec958.status, 0xFF, 24);
1102 return 0;
1103}
1104
1105static int aureon_cs8415_spdif_get (snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) {
1106 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1107
1108 snd_ice1712_save_gpio_status(ice);
1109 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1110 snd_ice1712_restore_gpio_status(ice);
1111 return 0;
1112}
1113
1114/*
1115 * Headphone Amplifier
1116 */
1117static int aureon_set_headphone_amp(ice1712_t *ice, int enable)
1118{
1119 unsigned int tmp, tmp2;
1120
1121 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1122 if (enable)
1123 tmp |= AUREON_HP_SEL;
1124 else
1125 tmp &= ~ AUREON_HP_SEL;
1126 if (tmp != tmp2) {
1127 snd_ice1712_gpio_write(ice, tmp);
1128 return 1;
1129 }
1130 return 0;
1131}
1132
1133static int aureon_get_headphone_amp(ice1712_t *ice)
1134{
1135 unsigned int tmp = snd_ice1712_gpio_read(ice);
1136
1137 return ( tmp & AUREON_HP_SEL )!= 0;
1138}
1139
1140#define aureon_hpamp_info aureon_mono_bool_info
1141
1142static int aureon_hpamp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1143{
1144 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1145
1146 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1147 return 0;
1148}
1149
1150
1151static int aureon_hpamp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1152{
1153 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1154
1155 return aureon_set_headphone_amp(ice,ucontrol->value.integer.value[0]);
1156}
1157
1158/*
1159 * Deemphasis
1160 */
1161
1162#define aureon_deemp_info aureon_mono_bool_info
1163
1164static int aureon_deemp_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1165{
1166 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1167 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1168 return 0;
1169}
1170
1171static int aureon_deemp_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1172{
1173 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1174 int temp, temp2;
1175 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1176 if (ucontrol->value.integer.value[0])
1177 temp |= 0xf;
1178 else
1179 temp &= ~0xf;
1180 if (temp != temp2) {
1181 wm_put(ice, WM_DAC_CTRL2, temp);
1182 return 1;
1183 }
1184 return 0;
1185}
1186
1187/*
1188 * ADC Oversampling
1189 */
1190static int aureon_oversampling_info(snd_kcontrol_t *k, snd_ctl_elem_info_t *uinfo)
1191{
1192 static char *texts[2] = { "128x", "64x" };
1193
1194 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1195 uinfo->count = 1;
1196 uinfo->value.enumerated.items = 2;
1197
1198 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1199 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1200 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1201
1202 return 0;
1203}
1204
1205static int aureon_oversampling_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1206{
1207 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1208 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1209 return 0;
1210}
1211
1212static int aureon_oversampling_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1213{
1214 int temp, temp2;
1215 ice1712_t *ice = snd_kcontrol_chip(kcontrol);
1216
1217 temp2 = temp = wm_get(ice, WM_MASTER);
1218
1219 if (ucontrol->value.enumerated.item[0])
1220 temp |= 0x8;
1221 else
1222 temp &= ~0x8;
1223
1224 if (temp != temp2) {
1225 wm_put(ice, WM_MASTER, temp);
1226 return 1;
1227 }
1228 return 0;
1229}
1230
1231/*
1232 * mixers
1233 */
1234
1235static snd_kcontrol_new_t aureon_dac_controls[] __devinitdata = {
1236 {
1237 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1238 .name = "Master Playback Switch",
1239 .info = wm_master_mute_info,
1240 .get = wm_master_mute_get,
1241 .put = wm_master_mute_put
1242 },
1243 {
1244 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1245 .name = "Master Playback Volume",
1246 .info = wm_master_vol_info,
1247 .get = wm_master_vol_get,
1248 .put = wm_master_vol_put
1249 },
1250 {
1251 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1252 .name = "Front Playback Switch",
1253 .info = wm_mute_info,
1254 .get = wm_mute_get,
1255 .put = wm_mute_put,
1256 .private_value = (2 << 8) | 0
1257 },
1258 {
1259 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1260 .name = "Front Playback Volume",
1261 .info = wm_vol_info,
1262 .get = wm_vol_get,
1263 .put = wm_vol_put,
1264 .private_value = (2 << 8) | 0
1265 },
1266 {
1267 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1268 .name = "Rear Playback Switch",
1269 .info = wm_mute_info,
1270 .get = wm_mute_get,
1271 .put = wm_mute_put,
1272 .private_value = (2 << 8) | 2
1273 },
1274 {
1275 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1276 .name = "Rear Playback Volume",
1277 .info = wm_vol_info,
1278 .get = wm_vol_get,
1279 .put = wm_vol_put,
1280 .private_value = (2 << 8) | 2
1281 },
1282 {
1283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1284 .name = "Center Playback Switch",
1285 .info = wm_mute_info,
1286 .get = wm_mute_get,
1287 .put = wm_mute_put,
1288 .private_value = (1 << 8) | 4
1289 },
1290 {
1291 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1292 .name = "Center Playback Volume",
1293 .info = wm_vol_info,
1294 .get = wm_vol_get,
1295 .put = wm_vol_put,
1296 .private_value = (1 << 8) | 4
1297 },
1298 {
1299 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1300 .name = "LFE Playback Switch",
1301 .info = wm_mute_info,
1302 .get = wm_mute_get,
1303 .put = wm_mute_put,
1304 .private_value = (1 << 8) | 5
1305 },
1306 {
1307 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1308 .name = "LFE Playback Volume",
1309 .info = wm_vol_info,
1310 .get = wm_vol_get,
1311 .put = wm_vol_put,
1312 .private_value = (1 << 8) | 5
1313 },
1314 {
1315 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1316 .name = "Side Playback Switch",
1317 .info = wm_mute_info,
1318 .get = wm_mute_get,
1319 .put = wm_mute_put,
1320 .private_value = (2 << 8) | 6
1321 },
1322 {
1323 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1324 .name = "Side Playback Volume",
1325 .info = wm_vol_info,
1326 .get = wm_vol_get,
1327 .put = wm_vol_put,
1328 .private_value = (2 << 8) | 6
1329 }
1330};
1331
1332static snd_kcontrol_new_t wm_controls[] __devinitdata = {
1333 {
1334 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1335 .name = "PCM Playback Switch",
1336 .info = wm_pcm_mute_info,
1337 .get = wm_pcm_mute_get,
1338 .put = wm_pcm_mute_put
1339 },
1340 {
1341 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1342 .name = "PCM Playback Volume",
1343 .info = wm_pcm_vol_info,
1344 .get = wm_pcm_vol_get,
1345 .put = wm_pcm_vol_put
1346 },
1347 {
1348 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1349 .name = "Capture Switch",
1350 .info = wm_adc_mute_info,
1351 .get = wm_adc_mute_get,
1352 .put = wm_adc_mute_put,
1353 },
1354 {
1355 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1356 .name = "Capture Volume",
1357 .info = wm_adc_vol_info,
1358 .get = wm_adc_vol_get,
1359 .put = wm_adc_vol_put
1360 },
1361 {
1362 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1363 .name = "Capture Source",
1364 .info = wm_adc_mux_info,
1365 .get = wm_adc_mux_get,
1366 .put = wm_adc_mux_put,
1367 .private_value = 5
1368 },
1369 {
1370 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1371 .name = "External Amplifier",
1372 .info = aureon_hpamp_info,
1373 .get = aureon_hpamp_get,
1374 .put = aureon_hpamp_put
1375 },
1376 {
1377 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1378 .name = "DAC Deemphasis Switch",
1379 .info = aureon_deemp_info,
1380 .get = aureon_deemp_get,
1381 .put = aureon_deemp_put
1382 },
1383 {
1384 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1385 .name = "ADC Oversampling",
1386 .info = aureon_oversampling_info,
1387 .get = aureon_oversampling_get,
1388 .put = aureon_oversampling_put
1389 }
1390};
1391
1392static snd_kcontrol_new_t ac97_controls[] __devinitdata = {
1393 {
1394 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1395 .name = "AC97 Playback Switch",
1396 .info = aureon_ac97_mmute_info,
1397 .get = aureon_ac97_mmute_get,
1398 .put = aureon_ac97_mmute_put,
1399 .private_value = AC97_MASTER
1400 },
1401 {
1402 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1403 .name = "AC97 Playback Volume",
1404 .info = aureon_ac97_vol_info,
1405 .get = aureon_ac97_vol_get,
1406 .put = aureon_ac97_vol_put,
1407 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1408 },
1409 {
1410 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1411 .name = "CD Playback Switch",
1412 .info = aureon_ac97_mute_info,
1413 .get = aureon_ac97_mute_get,
1414 .put = aureon_ac97_mute_put,
1415 .private_value = AC97_CD
1416 },
1417 {
1418 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1419 .name = "CD Playback Volume",
1420 .info = aureon_ac97_vol_info,
1421 .get = aureon_ac97_vol_get,
1422 .put = aureon_ac97_vol_put,
1423 .private_value = AC97_CD|AUREON_AC97_STEREO
1424 },
1425 {
1426 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1427 .name = "Aux Playback Switch",
1428 .info = aureon_ac97_mute_info,
1429 .get = aureon_ac97_mute_get,
1430 .put = aureon_ac97_mute_put,
1431 .private_value = AC97_AUX,
1432 },
1433 {
1434 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1435 .name = "Aux Playback Volume",
1436 .info = aureon_ac97_vol_info,
1437 .get = aureon_ac97_vol_get,
1438 .put = aureon_ac97_vol_put,
1439 .private_value = AC97_AUX|AUREON_AC97_STEREO
1440 },
1441 {
1442 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1443 .name = "Line Playback Switch",
1444 .info = aureon_ac97_mute_info,
1445 .get = aureon_ac97_mute_get,
1446 .put = aureon_ac97_mute_put,
1447 .private_value = AC97_LINE
1448 },
1449 {
1450 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1451 .name = "Line Playback Volume",
1452 .info = aureon_ac97_vol_info,
1453 .get = aureon_ac97_vol_get,
1454 .put = aureon_ac97_vol_put,
1455 .private_value = AC97_LINE|AUREON_AC97_STEREO
1456 },
1457 {
1458 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1459 .name = "Mic Playback Switch",
1460 .info = aureon_ac97_mute_info,
1461 .get = aureon_ac97_mute_get,
1462 .put = aureon_ac97_mute_put,
1463 .private_value = AC97_MIC
1464 },
1465 {
1466 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1467 .name = "Mic Playback Volume",
1468 .info = aureon_ac97_vol_info,
1469 .get = aureon_ac97_vol_get,
1470 .put = aureon_ac97_vol_put,
1471 .private_value = AC97_MIC
1472 },
1473 {
1474 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1475 .name = "Mic Boost (+20dB)",
1476 .info = aureon_ac97_micboost_info,
1477 .get = aureon_ac97_micboost_get,
1478 .put = aureon_ac97_micboost_put
1479 }
1480};
1481
1482static snd_kcontrol_new_t universe_ac97_controls[] __devinitdata = {
1483 {
1484 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1485 .name = "AC97 Playback Switch",
1486 .info = aureon_ac97_mmute_info,
1487 .get = aureon_ac97_mmute_get,
1488 .put = aureon_ac97_mmute_put,
1489 .private_value = AC97_MASTER
1490 },
1491 {
1492 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1493 .name = "AC97 Playback Volume",
1494 .info = aureon_ac97_vol_info,
1495 .get = aureon_ac97_vol_get,
1496 .put = aureon_ac97_vol_put,
1497 .private_value = AC97_MASTER|AUREON_AC97_STEREO
1498 },
1499 {
1500 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1501 .name = "CD Playback Switch",
1502 .info = aureon_ac97_mute_info,
1503 .get = aureon_ac97_mute_get,
1504 .put = aureon_ac97_mute_put,
1505 .private_value = AC97_AUX
1506 },
1507 {
1508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509 .name = "CD Playback Volume",
1510 .info = aureon_ac97_vol_info,
1511 .get = aureon_ac97_vol_get,
1512 .put = aureon_ac97_vol_put,
1513 .private_value = AC97_AUX|AUREON_AC97_STEREO
1514 },
1515 {
1516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1517 .name = "Phono Playback Switch",
1518 .info = aureon_ac97_mute_info,
1519 .get = aureon_ac97_mute_get,
1520 .put = aureon_ac97_mute_put,
1521 .private_value = AC97_CD,
1522 },
1523 {
1524 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1525 .name = "Phono Playback Volume",
1526 .info = aureon_ac97_vol_info,
1527 .get = aureon_ac97_vol_get,
1528 .put = aureon_ac97_vol_put,
1529 .private_value = AC97_CD|AUREON_AC97_STEREO
1530 },
1531 {
1532 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1533 .name = "Line Playback Switch",
1534 .info = aureon_ac97_mute_info,
1535 .get = aureon_ac97_mute_get,
1536 .put = aureon_ac97_mute_put,
1537 .private_value = AC97_LINE
1538 },
1539 {
1540 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1541 .name = "Line Playback Volume",
1542 .info = aureon_ac97_vol_info,
1543 .get = aureon_ac97_vol_get,
1544 .put = aureon_ac97_vol_put,
1545 .private_value = AC97_LINE|AUREON_AC97_STEREO
1546 },
1547 {
1548 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1549 .name = "Mic Playback Switch",
1550 .info = aureon_ac97_mute_info,
1551 .get = aureon_ac97_mute_get,
1552 .put = aureon_ac97_mute_put,
1553 .private_value = AC97_MIC
1554 },
1555 {
1556 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1557 .name = "Mic Playback Volume",
1558 .info = aureon_ac97_vol_info,
1559 .get = aureon_ac97_vol_get,
1560 .put = aureon_ac97_vol_put,
1561 .private_value = AC97_MIC
1562 },
1563 {
1564 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1565 .name = "Mic Boost (+20dB)",
1566 .info = aureon_ac97_micboost_info,
1567 .get = aureon_ac97_micboost_get,
1568 .put = aureon_ac97_micboost_put
1569 },
1570 {
1571 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1572 .name = "Aux Playback Switch",
1573 .info = aureon_ac97_mute_info,
1574 .get = aureon_ac97_mute_get,
1575 .put = aureon_ac97_mute_put,
1576 .private_value = AC97_VIDEO,
1577 },
1578 {
1579 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1580 .name = "Aux Playback Volume",
1581 .info = aureon_ac97_vol_info,
1582 .get = aureon_ac97_vol_get,
1583 .put = aureon_ac97_vol_put,
1584 .private_value = AC97_VIDEO|AUREON_AC97_STEREO
1585 }
1586};
1587
1588
1589static snd_kcontrol_new_t cs8415_controls[] __devinitdata = {
1590 {
1591 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1592 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
1593 .info = aureon_cs8415_mute_info,
1594 .get = aureon_cs8415_mute_get,
1595 .put = aureon_cs8415_mute_put
1596 },
1597 {
1598 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1599 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Source",
1600 .info = aureon_cs8415_mux_info,
1601 .get = aureon_cs8415_mux_get,
1602 .put = aureon_cs8415_mux_put,
1603 },
1604 {
1605 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1606 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ",CAPTURE,DEFAULT),
1607 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1608 .info = aureon_cs8415_qsub_info,
1609 .get = aureon_cs8415_qsub_get,
1610 },
1611 {
1612 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1613 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
1614 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1615 .info = aureon_cs8415_spdif_info,
1616 .get = aureon_cs8415_mask_get
1617 },
1618 {
1619 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1620 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
1621 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1622 .info = aureon_cs8415_spdif_info,
1623 .get = aureon_cs8415_spdif_get
1624 },
1625 {
1626 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1627 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,NONE) "Rate",
1628 .access =SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1629 .info = aureon_cs8415_rate_info,
1630 .get = aureon_cs8415_rate_get
1631 }
1632};
1633
1634
1635static int __devinit aureon_add_controls(ice1712_t *ice)
1636{
1637 unsigned int i, counts;
1638 int err;
1639
1640 counts = ARRAY_SIZE(aureon_dac_controls);
1641 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1642 counts -= 2; /* no side */
1643 for (i = 0; i < counts; i++) {
1644 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1645 if (err < 0)
1646 return err;
1647 }
1648
1649 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1650 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1651 if (err < 0)
1652 return err;
1653 }
1654
1655 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1656 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1657 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1658 if (err < 0)
1659 return err;
1660 }
1661 }
1662 else {
1663 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1664 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1665 if (err < 0)
1666 return err;
1667 }
1668 }
1669
1670 {
1671 unsigned char id;
1672 snd_ice1712_save_gpio_status(ice);
1673 id = aureon_cs8415_get(ice, CS8415_ID);
1674 if (id != 0x41)
1675 snd_printk("No CS8415 chip. Skipping CS8415 controls.\n");
1676 else if ((id & 0x0F) != 0x01)
1677 snd_printk("Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1678 else {
1679 for (i = 0; i< ARRAY_SIZE(cs8415_controls); i++) {
1680 snd_kcontrol_t *kctl;
1681 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1682 if (err < 0)
1683 return err;
1684 if (i > 1)
1685 kctl->id.device = ice->pcm->device;
1686 }
1687 }
1688 snd_ice1712_restore_gpio_status(ice);
1689 }
1690
1691 return 0;
1692}
1693
1694
1695/*
1696 * initialize the chip
1697 */
1698static int __devinit aureon_init(ice1712_t *ice)
1699{
1700 static unsigned short wm_inits_aureon[] = {
1701 /* These come first to reduce init pop noise */
1702 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1703 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1704 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1705
1706 0x18, 0x000, /* All power-up */
1707
1708 0x16, 0x122, /* I2S, normal polarity, 24bit */
1709 0x17, 0x022, /* 256fs, slave mode */
1710 0x00, 0, /* DAC1 analog mute */
1711 0x01, 0, /* DAC2 analog mute */
1712 0x02, 0, /* DAC3 analog mute */
1713 0x03, 0, /* DAC4 analog mute */
1714 0x04, 0, /* DAC5 analog mute */
1715 0x05, 0, /* DAC6 analog mute */
1716 0x06, 0, /* DAC7 analog mute */
1717 0x07, 0, /* DAC8 analog mute */
1718 0x08, 0x100, /* master analog mute */
1719 0x09, 0xff, /* DAC1 digital full */
1720 0x0a, 0xff, /* DAC2 digital full */
1721 0x0b, 0xff, /* DAC3 digital full */
1722 0x0c, 0xff, /* DAC4 digital full */
1723 0x0d, 0xff, /* DAC5 digital full */
1724 0x0e, 0xff, /* DAC6 digital full */
1725 0x0f, 0xff, /* DAC7 digital full */
1726 0x10, 0xff, /* DAC8 digital full */
1727 0x11, 0x1ff, /* master digital full */
1728 0x12, 0x000, /* phase normal */
1729 0x13, 0x090, /* unmute DAC L/R */
1730 0x14, 0x000, /* all unmute */
1731 0x15, 0x000, /* no deemphasis, no ZFLG */
1732 0x19, 0x000, /* -12dB ADC/L */
1733 0x1a, 0x000, /* -12dB ADC/R */
1734 (unsigned short)-1
1735 };
1736 static unsigned short wm_inits_prodigy[] = {
1737
1738 /* These come first to reduce init pop noise */
1739 0x1b, 0x000, /* ADC Mux */
1740 0x1c, 0x009, /* Out Mux1 */
1741 0x1d, 0x009, /* Out Mux2 */
1742
1743 0x18, 0x000, /* All power-up */
1744
1745 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
1746 0x17, 0x006, /* 128fs, slave mode */
1747
1748 0x00, 0, /* DAC1 analog mute */
1749 0x01, 0, /* DAC2 analog mute */
1750 0x02, 0, /* DAC3 analog mute */
1751 0x03, 0, /* DAC4 analog mute */
1752 0x04, 0, /* DAC5 analog mute */
1753 0x05, 0, /* DAC6 analog mute */
1754 0x06, 0, /* DAC7 analog mute */
1755 0x07, 0, /* DAC8 analog mute */
1756 0x08, 0x100, /* master analog mute */
1757
1758 0x09, 0x7f, /* DAC1 digital full */
1759 0x0a, 0x7f, /* DAC2 digital full */
1760 0x0b, 0x7f, /* DAC3 digital full */
1761 0x0c, 0x7f, /* DAC4 digital full */
1762 0x0d, 0x7f, /* DAC5 digital full */
1763 0x0e, 0x7f, /* DAC6 digital full */
1764 0x0f, 0x7f, /* DAC7 digital full */
1765 0x10, 0x7f, /* DAC8 digital full */
1766 0x11, 0x1FF, /* master digital full */
1767
1768 0x12, 0x000, /* phase normal */
1769 0x13, 0x090, /* unmute DAC L/R */
1770 0x14, 0x000, /* all unmute */
1771 0x15, 0x000, /* no deemphasis, no ZFLG */
1772
1773 0x19, 0x000, /* -12dB ADC/L */
1774 0x1a, 0x000, /* -12dB ADC/R */
1775 (unsigned short)-1
1776
1777 };
1778 static unsigned short cs_inits[] = {
1779 0x0441, /* RUN */
1780 0x0180, /* no mute, OMCK output on RMCK pin */
1781 0x0201, /* S/PDIF source on RXP1 */
1782 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
1783 (unsigned short)-1
1784 };
1785 unsigned int tmp;
1786 unsigned short *p;
1787 int err, i;
1788
1789 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
1790 ice->num_total_dacs = 6;
1791 ice->num_total_adcs = 2;
1792 } else {
1793 /* aureon 7.1 and prodigy 7.1 */
1794 ice->num_total_dacs = 8;
1795 ice->num_total_adcs = 2;
1796 }
1797
1798 /* to remeber the register values of CS8415 */
1799 ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
1800 if (! ice->akm)
1801 return -ENOMEM;
1802 ice->akm_codecs = 1;
1803
1804 if ((err = aureon_ac97_init(ice)) != 0)
1805 return err;
1806
1807 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
1808
1809 /* reset the wm codec as the SPI mode */
1810 snd_ice1712_save_gpio_status(ice);
1811 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
1812
1813 tmp = snd_ice1712_gpio_read(ice);
1814 tmp &= ~AUREON_WM_RESET;
1815 snd_ice1712_gpio_write(ice, tmp);
1816 udelay(1);
1817 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
1818 snd_ice1712_gpio_write(ice, tmp);
1819 udelay(1);
1820 tmp |= AUREON_WM_RESET;
1821 snd_ice1712_gpio_write(ice, tmp);
1822 udelay(1);
1823
1824 /* initialize WM8770 codec */
1825 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1826 p = wm_inits_prodigy;
1827 else
1828 p = wm_inits_aureon;
1829 for (; *p != (unsigned short)-1; p += 2)
1830 wm_put(ice, p[0], p[1]);
1831
1832 /* initialize CS8415A codec */
1833 for (p = cs_inits; *p != (unsigned short)-1; p++)
1834 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
1835 ice->spec.aureon.cs8415_mux = 1;
1836
1837 aureon_set_headphone_amp(ice, 1);
1838
1839 snd_ice1712_restore_gpio_status(ice);
1840
1841 ice->spec.aureon.master[0] = WM_VOL_MUTE;
1842 ice->spec.aureon.master[1] = WM_VOL_MUTE;
1843 for (i = 0; i < ice->num_total_dacs; i++) {
1844 ice->spec.aureon.vol[i] = WM_VOL_MUTE;
1845 wm_set_vol(ice, i, ice->spec.aureon.vol[i], ice->spec.aureon.master[i % 2]);
1846 }
1847
1848 return 0;
1849}
1850
1851
1852/*
1853 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
1854 * hence the driver needs to sets up it properly.
1855 */
1856
1857static unsigned char aureon51_eeprom[] __devinitdata = {
1858 0x0a, /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */
1859 0x80, /* ACLINK: I2S */
1860 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1861 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1862 0xff, /* GPIO_DIR */
1863 0xff, /* GPIO_DIR1 */
1864 0x5f, /* GPIO_DIR2 */
1865 0x00, /* GPIO_MASK */
1866 0x00, /* GPIO_MASK1 */
1867 0x00, /* GPIO_MASK2 */
1868 0x00, /* GPIO_STATE */
1869 0x00, /* GPIO_STATE1 */
1870 0x00, /* GPIO_STATE2 */
1871};
1872
1873static unsigned char aureon71_eeprom[] __devinitdata = {
1874 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1875 0x80, /* ACLINK: I2S */
1876 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1877 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1878 0xff, /* GPIO_DIR */
1879 0xff, /* GPIO_DIR1 */
1880 0x5f, /* GPIO_DIR2 */
1881 0x00, /* GPIO_MASK */
1882 0x00, /* GPIO_MASK1 */
1883 0x00, /* GPIO_MASK2 */
1884 0x00, /* GPIO_STATE */
1885 0x00, /* GPIO_STATE1 */
1886 0x00, /* GPIO_STATE2 */
1887};
1888
1889static unsigned char prodigy71_eeprom[] __devinitdata = {
1890 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
1891 0x80, /* ACLINK: I2S */
1892 0xfc, /* I2S: vol, 96k, 24bit, 192k */
1893 0xc3, /* SPDIF: out-en, out-int, spdif-in */
1894 0xff, /* GPIO_DIR */
1895 0xff, /* GPIO_DIR1 */
1896 0x5f, /* GPIO_DIR2 */
1897 0x00, /* GPIO_MASK */
1898 0x00, /* GPIO_MASK1 */
1899 0x00, /* GPIO_MASK2 */
1900 0x00, /* GPIO_STATE */
1901 0x00, /* GPIO_STATE1 */
1902 0x00, /* GPIO_STATE2 */
1903};
1904
1905/* entry point */
1906struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
1907 {
1908 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
1909 .name = "Terratec Aureon 5.1-Sky",
1910 .model = "aureon51",
1911 .chip_init = aureon_init,
1912 .build_controls = aureon_add_controls,
1913 .eeprom_size = sizeof(aureon51_eeprom),
1914 .eeprom_data = aureon51_eeprom,
1915 .driver = "Aureon51",
1916 },
1917 {
1918 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
1919 .name = "Terratec Aureon 7.1-Space",
1920 .model = "aureon71",
1921 .chip_init = aureon_init,
1922 .build_controls = aureon_add_controls,
1923 .eeprom_size = sizeof(aureon71_eeprom),
1924 .eeprom_data = aureon71_eeprom,
1925 .driver = "Aureon71",
1926 },
1927 {
1928 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
1929 .name = "Terratec Aureon 7.1-Universe",
1930 .model = "universe",
1931 .chip_init = aureon_init,
1932 .build_controls = aureon_add_controls,
1933 .eeprom_size = sizeof(aureon71_eeprom),
1934 .eeprom_data = aureon71_eeprom,
1935 .driver = "Aureon71Universe",
1936 },
1937 {
1938 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
1939 .name = "Audiotrak Prodigy 7.1",
1940 .model = "prodigy71",
1941 .chip_init = aureon_init,
1942 .build_controls = aureon_add_controls,
1943 .eeprom_size = sizeof(prodigy71_eeprom),
1944 .eeprom_data = prodigy71_eeprom,
1945 .driver = "Prodigy71", /* should be identical with Aureon71 */
1946 },
1947 { } /* terminator */
1948};