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