drm/i915: make hw page ioremap use ioremap_wc
[linux-2.6-block.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,
151 * skipping ack cycles inbetween
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
0cb29ea0
TI
692static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
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
1da177e4
LT
698/*
699 * Logarithmic volume values for WM8770
700 * Computed as 20 * Log10(255 / x)
701 */
32b47da0 702static const unsigned char wm_vol[256] = {
1da177e4
LT
703 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
704 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
705 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
706 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11,
707 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 8,
708 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,
709 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,
710 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,
711 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,
712 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,
713 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,
714 0, 0
715};
716
717#define WM_VOL_MAX (sizeof(wm_vol) - 1)
718#define WM_VOL_MUTE 0x8000
719
ab0c7d72 720static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index, unsigned short vol, unsigned short master)
1da177e4
LT
721{
722 unsigned char nvol;
1ce211a9 723
1da177e4
LT
724 if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
725 nvol = 0;
726 else
727 nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) * (master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
1ce211a9 728
1da177e4
LT
729 wm_put(ice, index, nvol);
730 wm_put_nocache(ice, index, 0x180 | nvol);
731}
732
733/*
734 * DAC mute control
735 */
a5ce8890 736#define wm_pcm_mute_info snd_ctl_boolean_mono_info
1da177e4 737
ab0c7d72 738static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 739{
ab0c7d72 740 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4 741
62932df8 742 mutex_lock(&ice->gpio_mutex);
1da177e4 743 ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ? 0 : 1;
62932df8 744 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
745 return 0;
746}
747
ab0c7d72 748static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 749{
ab0c7d72 750 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
751 unsigned short nval, oval;
752 int change;
753
754 snd_ice1712_save_gpio_status(ice);
755 oval = wm_get(ice, WM_MUTE);
756 nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
1ce211a9
AB
757 change = (oval != nval);
758 if (change)
1da177e4
LT
759 wm_put(ice, WM_MUTE, nval);
760 snd_ice1712_restore_gpio_status(ice);
761
762 return change;
763}
764
765/*
766 * Master volume attenuation mixer control
767 */
ab0c7d72 768static int wm_master_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
769{
770 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
771 uinfo->count = 2;
772 uinfo->value.integer.min = 0;
773 uinfo->value.integer.max = WM_VOL_MAX;
774 return 0;
775}
776
ab0c7d72 777static int wm_master_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 778{
ab0c7d72 779 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 780 struct aureon_spec *spec = ice->spec;
1da177e4 781 int i;
1ce211a9 782 for (i = 0; i < 2; i++)
7cda8ba9
TI
783 ucontrol->value.integer.value[i] =
784 spec->master[i] & ~WM_VOL_MUTE;
1da177e4
LT
785 return 0;
786}
787
ab0c7d72 788static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 789{
ab0c7d72 790 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 791 struct aureon_spec *spec = ice->spec;
1da177e4
LT
792 int ch, change = 0;
793
794 snd_ice1712_save_gpio_status(ice);
795 for (ch = 0; ch < 2; ch++) {
9cd17cd2
TI
796 unsigned int vol = ucontrol->value.integer.value[ch];
797 if (vol > WM_VOL_MAX)
798 continue;
7cda8ba9
TI
799 vol |= spec->master[ch] & WM_VOL_MUTE;
800 if (vol != spec->master[ch]) {
1da177e4 801 int dac;
7cda8ba9 802 spec->master[ch] = vol;
1da177e4
LT
803 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
804 wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
7cda8ba9
TI
805 spec->vol[dac + ch],
806 spec->master[ch]);
1da177e4
LT
807 change = 1;
808 }
809 }
810 snd_ice1712_restore_gpio_status(ice);
811 return change;
812}
813
814/*
815 * DAC volume attenuation mixer control
816 */
ab0c7d72 817static int wm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
818{
819 int voices = kcontrol->private_value >> 8;
820 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
821 uinfo->count = voices;
822 uinfo->value.integer.min = 0; /* mute (-101dB) */
823 uinfo->value.integer.max = 0x7F; /* 0dB */
824 return 0;
825}
826
ab0c7d72 827static int wm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 828{
ab0c7d72 829 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 830 struct aureon_spec *spec = ice->spec;
1da177e4
LT
831 int i, ofs, voices;
832
833 voices = kcontrol->private_value >> 8;
834 ofs = kcontrol->private_value & 0xff;
835 for (i = 0; i < voices; i++)
7cda8ba9
TI
836 ucontrol->value.integer.value[i] =
837 spec->vol[ofs+i] & ~WM_VOL_MUTE;
1da177e4
LT
838 return 0;
839}
840
ab0c7d72 841static int wm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 842{
ab0c7d72 843 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 844 struct aureon_spec *spec = ice->spec;
1da177e4
LT
845 int i, idx, ofs, voices;
846 int change = 0;
847
848 voices = kcontrol->private_value >> 8;
849 ofs = kcontrol->private_value & 0xff;
850 snd_ice1712_save_gpio_status(ice);
851 for (i = 0; i < voices; i++) {
9cd17cd2
TI
852 unsigned int vol = ucontrol->value.integer.value[i];
853 if (vol > 0x7f)
854 continue;
7cda8ba9
TI
855 vol |= spec->vol[ofs+i];
856 if (vol != spec->vol[ofs+i]) {
857 spec->vol[ofs+i] = vol;
9cd17cd2 858 idx = WM_DAC_ATTEN + ofs + i;
7cda8ba9
TI
859 wm_set_vol(ice, idx, spec->vol[ofs + i],
860 spec->master[i]);
1da177e4
LT
861 change = 1;
862 }
863 }
864 snd_ice1712_restore_gpio_status(ice);
865 return change;
866}
867
868/*
869 * WM8770 mute control
870 */
1ce211a9
AB
871static int wm_mute_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
872{
1da177e4
LT
873 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
874 uinfo->count = kcontrol->private_value >> 8;
875 uinfo->value.integer.min = 0;
876 uinfo->value.integer.max = 1;
877 return 0;
878}
879
ab0c7d72 880static int wm_mute_get(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 884 int voices, ofs, i;
1ce211a9 885
1da177e4
LT
886 voices = kcontrol->private_value >> 8;
887 ofs = kcontrol->private_value & 0xFF;
888
889 for (i = 0; i < voices; i++)
7cda8ba9
TI
890 ucontrol->value.integer.value[i] =
891 (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
1da177e4
LT
892 return 0;
893}
894
ab0c7d72 895static int wm_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 896{
ab0c7d72 897 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 898 struct aureon_spec *spec = ice->spec;
1da177e4
LT
899 int change = 0, voices, ofs, i;
900
901 voices = kcontrol->private_value >> 8;
902 ofs = kcontrol->private_value & 0xFF;
903
904 snd_ice1712_save_gpio_status(ice);
905 for (i = 0; i < voices; i++) {
7cda8ba9 906 int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
1da177e4 907 if (ucontrol->value.integer.value[i] != val) {
7cda8ba9
TI
908 spec->vol[ofs + i] &= ~WM_VOL_MUTE;
909 spec->vol[ofs + i] |=
1da177e4 910 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
7cda8ba9
TI
911 wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
912 spec->master[i]);
1da177e4
LT
913 change = 1;
914 }
915 }
916 snd_ice1712_restore_gpio_status(ice);
917
918 return change;
919}
920
921/*
922 * WM8770 master mute control
923 */
a5ce8890 924#define wm_master_mute_info snd_ctl_boolean_stereo_info
1da177e4 925
ab0c7d72 926static int wm_master_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 927{
ab0c7d72 928 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 929 struct aureon_spec *spec = ice->spec;
1ce211a9 930
7cda8ba9
TI
931 ucontrol->value.integer.value[0] =
932 (spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
933 ucontrol->value.integer.value[1] =
934 (spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
1da177e4
LT
935 return 0;
936}
937
ab0c7d72 938static int wm_master_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 939{
ab0c7d72 940 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 941 struct aureon_spec *spec = ice->spec;
1da177e4
LT
942 int change = 0, i;
943
944 snd_ice1712_save_gpio_status(ice);
945 for (i = 0; i < 2; i++) {
7cda8ba9 946 int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
1da177e4
LT
947 if (ucontrol->value.integer.value[i] != val) {
948 int dac;
7cda8ba9
TI
949 spec->master[i] &= ~WM_VOL_MUTE;
950 spec->master[i] |=
1da177e4
LT
951 ucontrol->value.integer.value[i] ? 0 : WM_VOL_MUTE;
952 for (dac = 0; dac < ice->num_total_dacs; dac += 2)
953 wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
7cda8ba9
TI
954 spec->vol[dac + i],
955 spec->master[i]);
1da177e4
LT
956 change = 1;
957 }
958 }
959 snd_ice1712_restore_gpio_status(ice);
960
961 return change;
962}
963
964/* digital master volume */
965#define PCM_0dB 0xff
966#define PCM_RES 128 /* -64dB */
967#define PCM_MIN (PCM_0dB - PCM_RES)
ab0c7d72 968static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
969{
970 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
971 uinfo->count = 1;
972 uinfo->value.integer.min = 0; /* mute (-64dB) */
973 uinfo->value.integer.max = PCM_RES; /* 0dB */
974 return 0;
975}
976
ab0c7d72 977static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 978{
ab0c7d72 979 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
980 unsigned short val;
981
62932df8 982 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
983 val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
984 val = val > PCM_MIN ? (val - PCM_MIN) : 0;
985 ucontrol->value.integer.value[0] = val;
62932df8 986 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
987 return 0;
988}
989
ab0c7d72 990static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 991{
ab0c7d72 992 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
993 unsigned short ovol, nvol;
994 int change = 0;
995
1da177e4 996 nvol = ucontrol->value.integer.value[0];
9cd17cd2
TI
997 if (nvol > PCM_RES)
998 return -EINVAL;
999 snd_ice1712_save_gpio_status(ice);
1da177e4
LT
1000 nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
1001 ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
1002 if (ovol != nvol) {
1003 wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
1004 wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100); /* update */
1005 change = 1;
1006 }
1007 snd_ice1712_restore_gpio_status(ice);
1008 return change;
1009}
1010
1011/*
1012 * ADC mute control
1013 */
a5ce8890 1014#define wm_adc_mute_info snd_ctl_boolean_stereo_info
1da177e4 1015
ab0c7d72 1016static int wm_adc_mute_get(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 val;
1020 int i;
1021
62932df8 1022 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
1023 for (i = 0; i < 2; i++) {
1024 val = wm_get(ice, WM_ADC_GAIN + i);
1025 ucontrol->value.integer.value[i] = ~val>>5 & 0x1;
1026 }
62932df8 1027 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
1028 return 0;
1029}
1030
ab0c7d72 1031static int wm_adc_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1032{
ab0c7d72 1033 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1034 unsigned short new, old;
1035 int i, change = 0;
1036
1037 snd_ice1712_save_gpio_status(ice);
1038 for (i = 0; i < 2; i++) {
1039 old = wm_get(ice, WM_ADC_GAIN + i);
1040 new = (~ucontrol->value.integer.value[i]<<5&0x20) | (old&~0x20);
1041 if (new != old) {
1042 wm_put(ice, WM_ADC_GAIN + i, new);
1043 change = 1;
1044 }
1045 }
1046 snd_ice1712_restore_gpio_status(ice);
1047
1048 return change;
1049}
1050
1051/*
1052 * ADC gain mixer control
1053 */
ab0c7d72 1054static int wm_adc_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
1055{
1056 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1057 uinfo->count = 2;
1058 uinfo->value.integer.min = 0; /* -12dB */
1059 uinfo->value.integer.max = 0x1f; /* 19dB */
1060 return 0;
1061}
1062
ab0c7d72 1063static int wm_adc_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1064{
ab0c7d72 1065 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1066 int i, idx;
1067 unsigned short vol;
1068
62932df8 1069 mutex_lock(&ice->gpio_mutex);
1da177e4
LT
1070 for (i = 0; i < 2; i++) {
1071 idx = WM_ADC_GAIN + i;
1072 vol = wm_get(ice, idx) & 0x1f;
1073 ucontrol->value.integer.value[i] = vol;
1074 }
62932df8 1075 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
1076 return 0;
1077}
1078
ab0c7d72 1079static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1080{
ab0c7d72 1081 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1082 int i, idx;
1083 unsigned short ovol, nvol;
1084 int change = 0;
1085
1086 snd_ice1712_save_gpio_status(ice);
1087 for (i = 0; i < 2; i++) {
1088 idx = WM_ADC_GAIN + i;
9cd17cd2 1089 nvol = ucontrol->value.integer.value[i] & 0x1f;
1da177e4
LT
1090 ovol = wm_get(ice, idx);
1091 if ((ovol & 0x1f) != nvol) {
1092 wm_put(ice, idx, nvol | (ovol & ~0x1f));
1093 change = 1;
1094 }
1095 }
1096 snd_ice1712_restore_gpio_status(ice);
1097 return change;
1098}
1099
1100/*
1101 * ADC input mux mixer control
1102 */
ab0c7d72 1103static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4 1104{
32b47da0 1105 static const char * const texts[] = {
1ce211a9
AB
1106 "CD", /* AIN1 */
1107 "Aux", /* AIN2 */
1108 "Line", /* AIN3 */
1109 "Mic", /* AIN4 */
1110 "AC97" /* AIN5 */
1da177e4 1111 };
32b47da0 1112 static const char * const universe_texts[] = {
1ce211a9
AB
1113 "Aux1", /* AIN1 */
1114 "CD", /* AIN2 */
1115 "Phono", /* AIN3 */
1116 "Line", /* AIN4 */
1117 "Aux2", /* AIN5 */
1118 "Mic", /* AIN6 */
1119 "Aux3", /* AIN7 */
1120 "AC97" /* AIN8 */
1da177e4 1121 };
ab0c7d72 1122 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1123
1124 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1125 uinfo->count = 2;
1126 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1127 uinfo->value.enumerated.items = 8;
1128 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1129 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1130 strcpy(uinfo->value.enumerated.name, universe_texts[uinfo->value.enumerated.item]);
1ce211a9 1131 } else {
1da177e4
LT
1132 uinfo->value.enumerated.items = 5;
1133 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1134 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1135 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1136 }
1137 return 0;
1138}
1139
ab0c7d72 1140static int wm_adc_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1141{
ab0c7d72 1142 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1143 unsigned short val;
1144
62932df8 1145 mutex_lock(&ice->gpio_mutex);
1da177e4 1146 val = wm_get(ice, WM_ADC_MUX);
6682025e
TI
1147 ucontrol->value.enumerated.item[0] = val & 7;
1148 ucontrol->value.enumerated.item[1] = (val >> 4) & 7;
62932df8 1149 mutex_unlock(&ice->gpio_mutex);
1da177e4
LT
1150 return 0;
1151}
1152
ab0c7d72 1153static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1154{
ab0c7d72 1155 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1156 unsigned short oval, nval;
1157 int change;
1158
1159 snd_ice1712_save_gpio_status(ice);
1160 oval = wm_get(ice, WM_ADC_MUX);
1161 nval = oval & ~0x77;
6682025e
TI
1162 nval |= ucontrol->value.enumerated.item[0] & 7;
1163 nval |= (ucontrol->value.enumerated.item[1] & 7) << 4;
1da177e4
LT
1164 change = (oval != nval);
1165 if (change)
1166 wm_put(ice, WM_ADC_MUX, nval);
1167 snd_ice1712_restore_gpio_status(ice);
63786d06 1168 return change;
1da177e4
LT
1169}
1170
1171/*
1172 * CS8415 Input mux
1173 */
ab0c7d72 1174static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4 1175{
ab0c7d72 1176 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
32b47da0 1177 static const char * const aureon_texts[] = {
1ce211a9
AB
1178 "CD", /* RXP0 */
1179 "Optical" /* RXP1 */
1da177e4 1180 };
32b47da0 1181 static const char * const prodigy_texts[] = {
1da177e4
LT
1182 "CD",
1183 "Coax"
1184 };
1185 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1186 uinfo->count = 1;
1187 uinfo->value.enumerated.items = 2;
1188 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1189 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1190 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71)
1191 strcpy(uinfo->value.enumerated.name, prodigy_texts[uinfo->value.enumerated.item]);
1192 else
1193 strcpy(uinfo->value.enumerated.name, aureon_texts[uinfo->value.enumerated.item]);
1194 return 0;
1195}
1196
ab0c7d72 1197static int aureon_cs8415_mux_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1198{
ab0c7d72 1199 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 1200 struct aureon_spec *spec = ice->spec;
1da177e4 1201
1ce211a9
AB
1202 /* snd_ice1712_save_gpio_status(ice); */
1203 /* val = aureon_cs8415_get(ice, CS8415_CTRL2); */
7cda8ba9 1204 ucontrol->value.enumerated.item[0] = spec->cs8415_mux;
1ce211a9 1205 /* snd_ice1712_restore_gpio_status(ice); */
1da177e4
LT
1206 return 0;
1207}
1208
ab0c7d72 1209static int aureon_cs8415_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1210{
ab0c7d72 1211 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
7cda8ba9 1212 struct aureon_spec *spec = ice->spec;
1da177e4
LT
1213 unsigned short oval, nval;
1214 int change;
1215
1216 snd_ice1712_save_gpio_status(ice);
1217 oval = aureon_cs8415_get(ice, CS8415_CTRL2);
1218 nval = oval & ~0x07;
6682025e 1219 nval |= ucontrol->value.enumerated.item[0] & 7;
1da177e4
LT
1220 change = (oval != nval);
1221 if (change)
1222 aureon_cs8415_put(ice, CS8415_CTRL2, nval);
1223 snd_ice1712_restore_gpio_status(ice);
7cda8ba9 1224 spec->cs8415_mux = ucontrol->value.enumerated.item[0];
1da177e4
LT
1225 return change;
1226}
1227
1ce211a9 1228static int aureon_cs8415_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
1229{
1230 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1231 uinfo->count = 1;
1232 uinfo->value.integer.min = 0;
1233 uinfo->value.integer.max = 192000;
1234 return 0;
1235}
1236
1ce211a9 1237static int aureon_cs8415_rate_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1238{
ab0c7d72 1239 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1240 unsigned char ratio;
1241 ratio = aureon_cs8415_get(ice, CS8415_RATIO);
1242 ucontrol->value.integer.value[0] = (int)((unsigned int)ratio * 750);
1243 return 0;
1244}
1245
1246/*
1247 * CS8415A Mute
1248 */
a5ce8890 1249#define aureon_cs8415_mute_info snd_ctl_boolean_mono_info
1da177e4 1250
1ce211a9 1251static int aureon_cs8415_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1252{
ab0c7d72 1253 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1254 snd_ice1712_save_gpio_status(ice);
1255 ucontrol->value.integer.value[0] = (aureon_cs8415_get(ice, CS8415_CTRL1) & 0x20) ? 0 : 1;
1256 snd_ice1712_restore_gpio_status(ice);
1257 return 0;
1258}
1259
1ce211a9 1260static int aureon_cs8415_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1261{
ab0c7d72 1262 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1263 unsigned char oval, nval;
1264 int change;
1265 snd_ice1712_save_gpio_status(ice);
1266 oval = aureon_cs8415_get(ice, CS8415_CTRL1);
1267 if (ucontrol->value.integer.value[0])
1268 nval = oval & ~0x20;
1269 else
1270 nval = oval | 0x20;
1ce211a9
AB
1271 change = (oval != nval);
1272 if (change)
1da177e4
LT
1273 aureon_cs8415_put(ice, CS8415_CTRL1, nval);
1274 snd_ice1712_restore_gpio_status(ice);
1275 return change;
1276}
1277
1278/*
1279 * CS8415A Q-Sub info
1280 */
1ce211a9
AB
1281static int aureon_cs8415_qsub_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1282{
1da177e4
LT
1283 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
1284 uinfo->count = 10;
1285 return 0;
1286}
1287
1ce211a9
AB
1288static int aureon_cs8415_qsub_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1289{
ab0c7d72 1290 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1ce211a9 1291
1da177e4
LT
1292 snd_ice1712_save_gpio_status(ice);
1293 aureon_cs8415_read(ice, CS8415_QSUB, ucontrol->value.bytes.data, 10);
1294 snd_ice1712_restore_gpio_status(ice);
1295
1296 return 0;
1297}
1298
1ce211a9
AB
1299static int aureon_cs8415_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1300{
1da177e4
LT
1301 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
1302 uinfo->count = 1;
1303 return 0;
1304}
1305
1ce211a9
AB
1306static int aureon_cs8415_mask_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1307{
1da177e4
LT
1308 memset(ucontrol->value.iec958.status, 0xFF, 24);
1309 return 0;
1310}
1311
1ce211a9
AB
1312static int aureon_cs8415_spdif_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1313{
ab0c7d72 1314 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1315
1316 snd_ice1712_save_gpio_status(ice);
1317 aureon_cs8415_read(ice, CS8415_C_BUFFER, ucontrol->value.iec958.status, 24);
1318 snd_ice1712_restore_gpio_status(ice);
1319 return 0;
1320}
1321
1322/*
1323 * Headphone Amplifier
1324 */
ab0c7d72 1325static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1da177e4
LT
1326{
1327 unsigned int tmp, tmp2;
1328
1329 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1330 if (enable)
cdf88efa
TK
1331 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1332 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
c5130271
TI
1333 tmp |= AUREON_HP_SEL;
1334 else
1335 tmp |= PRODIGY_HP_SEL;
1da177e4 1336 else
cdf88efa
TK
1337 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1338 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1ce211a9 1339 tmp &= ~AUREON_HP_SEL;
c5130271 1340 else
1ce211a9 1341 tmp &= ~PRODIGY_HP_SEL;
1da177e4
LT
1342 if (tmp != tmp2) {
1343 snd_ice1712_gpio_write(ice, tmp);
1344 return 1;
1345 }
1346 return 0;
1347}
1348
ab0c7d72 1349static int aureon_get_headphone_amp(struct snd_ice1712 *ice)
1da177e4
LT
1350{
1351 unsigned int tmp = snd_ice1712_gpio_read(ice);
1352
1ce211a9 1353 return (tmp & AUREON_HP_SEL) != 0;
1da177e4
LT
1354}
1355
a5ce8890 1356#define aureon_hpamp_info snd_ctl_boolean_mono_info
1da177e4 1357
ab0c7d72 1358static int aureon_hpamp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1359{
ab0c7d72 1360 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1361
1362 ucontrol->value.integer.value[0] = aureon_get_headphone_amp(ice);
1363 return 0;
1364}
1365
1366
ab0c7d72 1367static int aureon_hpamp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1368{
ab0c7d72 1369 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4 1370
1ce211a9 1371 return aureon_set_headphone_amp(ice, ucontrol->value.integer.value[0]);
1da177e4
LT
1372}
1373
1374/*
1375 * Deemphasis
1376 */
1377
a5ce8890 1378#define aureon_deemp_info snd_ctl_boolean_mono_info
1da177e4 1379
ab0c7d72 1380static int aureon_deemp_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1381{
ab0c7d72 1382 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1383 ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) == 0xf;
1384 return 0;
1385}
1386
ab0c7d72 1387static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1388{
ab0c7d72 1389 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1390 int temp, temp2;
1391 temp2 = temp = wm_get(ice, WM_DAC_CTRL2);
1392 if (ucontrol->value.integer.value[0])
1393 temp |= 0xf;
1394 else
1395 temp &= ~0xf;
1396 if (temp != temp2) {
1397 wm_put(ice, WM_DAC_CTRL2, temp);
1398 return 1;
1399 }
1400 return 0;
1401}
1402
1403/*
1404 * ADC Oversampling
1405 */
ab0c7d72 1406static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1da177e4 1407{
32b47da0 1408 static const char * const texts[2] = { "128x", "64x" };
1da177e4
LT
1409
1410 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1411 uinfo->count = 1;
1412 uinfo->value.enumerated.items = 2;
1413
1414 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1415 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
1416 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1417
1ce211a9 1418 return 0;
1da177e4
LT
1419}
1420
ab0c7d72 1421static int aureon_oversampling_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4 1422{
ab0c7d72 1423 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1424 ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) == 0x8;
1425 return 0;
1426}
1427
ab0c7d72 1428static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
1429{
1430 int temp, temp2;
ab0c7d72 1431 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1da177e4
LT
1432
1433 temp2 = temp = wm_get(ice, WM_MASTER);
1434
1435 if (ucontrol->value.enumerated.item[0])
1436 temp |= 0x8;
1437 else
1438 temp &= ~0x8;
1439
1440 if (temp != temp2) {
1441 wm_put(ice, WM_MASTER, temp);
1442 return 1;
1443 }
1444 return 0;
1445}
1446
1447/*
1448 * mixers
1449 */
1450
1b60f6b0 1451static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1da177e4
LT
1452 {
1453 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1454 .name = "Master Playback Switch",
1455 .info = wm_master_mute_info,
1456 .get = wm_master_mute_get,
1457 .put = wm_master_mute_put
1458 },
1459 {
1460 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1461 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9 1462 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1463 .name = "Master Playback Volume",
1464 .info = wm_master_vol_info,
1465 .get = wm_master_vol_get,
f640c320
TI
1466 .put = wm_master_vol_put,
1467 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1468 },
1469 {
1470 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1471 .name = "Front Playback Switch",
1472 .info = wm_mute_info,
1473 .get = wm_mute_get,
1474 .put = wm_mute_put,
1475 .private_value = (2 << 8) | 0
1476 },
1477 {
1478 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1479 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9 1480 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1481 .name = "Front Playback Volume",
1482 .info = wm_vol_info,
1483 .get = wm_vol_get,
1484 .put = wm_vol_put,
f640c320
TI
1485 .private_value = (2 << 8) | 0,
1486 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1487 },
1488 {
1489 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1490 .name = "Rear Playback Switch",
1491 .info = wm_mute_info,
1492 .get = wm_mute_get,
1493 .put = wm_mute_put,
1494 .private_value = (2 << 8) | 2
1495 },
1496 {
1497 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1498 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9 1499 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1500 .name = "Rear Playback Volume",
1501 .info = wm_vol_info,
1502 .get = wm_vol_get,
1503 .put = wm_vol_put,
f640c320
TI
1504 .private_value = (2 << 8) | 2,
1505 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1506 },
1507 {
1508 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1509 .name = "Center Playback Switch",
1510 .info = wm_mute_info,
1511 .get = wm_mute_get,
1512 .put = wm_mute_put,
1513 .private_value = (1 << 8) | 4
1514 },
1515 {
1516 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1517 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9 1518 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1519 .name = "Center Playback Volume",
1520 .info = wm_vol_info,
1521 .get = wm_vol_get,
1522 .put = wm_vol_put,
f640c320
TI
1523 .private_value = (1 << 8) | 4,
1524 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1525 },
1526 {
1527 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1528 .name = "LFE Playback Switch",
1529 .info = wm_mute_info,
1530 .get = wm_mute_get,
1531 .put = wm_mute_put,
1532 .private_value = (1 << 8) | 5
1533 },
1534 {
1535 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1536 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9 1537 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1538 .name = "LFE Playback Volume",
1539 .info = wm_vol_info,
1540 .get = wm_vol_get,
1541 .put = wm_vol_put,
f640c320
TI
1542 .private_value = (1 << 8) | 5,
1543 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1544 },
1545 {
1546 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1547 .name = "Side Playback Switch",
1548 .info = wm_mute_info,
1549 .get = wm_mute_get,
1550 .put = wm_mute_put,
1551 .private_value = (2 << 8) | 6
1552 },
1553 {
1554 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1555 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9 1556 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1557 .name = "Side Playback Volume",
1558 .info = wm_vol_info,
1559 .get = wm_vol_get,
1560 .put = wm_vol_put,
f640c320
TI
1561 .private_value = (2 << 8) | 6,
1562 .tlv = { .p = db_scale_wm_dac }
1da177e4
LT
1563 }
1564};
1565
1b60f6b0 1566static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1ce211a9
AB
1567 {
1568 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1da177e4
LT
1569 .name = "PCM Playback Switch",
1570 .info = wm_pcm_mute_info,
1571 .get = wm_pcm_mute_get,
1572 .put = wm_pcm_mute_put
1ce211a9
AB
1573 },
1574 {
1575 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1576 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9 1577 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1578 .name = "PCM Playback Volume",
1579 .info = wm_pcm_vol_info,
1580 .get = wm_pcm_vol_get,
f640c320
TI
1581 .put = wm_pcm_vol_put,
1582 .tlv = { .p = db_scale_wm_pcm }
1ce211a9 1583 },
1da177e4
LT
1584 {
1585 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1586 .name = "Capture Switch",
1587 .info = wm_adc_mute_info,
1588 .get = wm_adc_mute_get,
1589 .put = wm_adc_mute_put,
1590 },
1591 {
1592 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1593 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9 1594 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1da177e4
LT
1595 .name = "Capture Volume",
1596 .info = wm_adc_vol_info,
1597 .get = wm_adc_vol_get,
f640c320
TI
1598 .put = wm_adc_vol_put,
1599 .tlv = { .p = db_scale_wm_adc }
1da177e4
LT
1600 },
1601 {
1602 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1603 .name = "Capture Source",
1604 .info = wm_adc_mux_info,
1605 .get = wm_adc_mux_get,
1606 .put = wm_adc_mux_put,
1607 .private_value = 5
1608 },
1609 {
1610 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1611 .name = "External Amplifier",
1612 .info = aureon_hpamp_info,
1613 .get = aureon_hpamp_get,
1614 .put = aureon_hpamp_put
1615 },
1616 {
1617 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1618 .name = "DAC Deemphasis Switch",
1619 .info = aureon_deemp_info,
1620 .get = aureon_deemp_get,
1621 .put = aureon_deemp_put
1622 },
1623 {
1624 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1625 .name = "ADC Oversampling",
1626 .info = aureon_oversampling_info,
1627 .get = aureon_oversampling_get,
1628 .put = aureon_oversampling_put
1629 }
1630};
1631
1b60f6b0 1632static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1ce211a9
AB
1633 {
1634 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1da177e4
LT
1635 .name = "AC97 Playback Switch",
1636 .info = aureon_ac97_mmute_info,
1637 .get = aureon_ac97_mmute_get,
1638 .put = aureon_ac97_mmute_put,
1639 .private_value = AC97_MASTER
1ce211a9
AB
1640 },
1641 {
1642 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1643 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1644 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1645 .name = "AC97 Playback Volume",
1646 .info = aureon_ac97_vol_info,
1647 .get = aureon_ac97_vol_get,
1648 .put = aureon_ac97_vol_put,
1649 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
f640c320 1650 .tlv = { .p = db_scale_ac97_master }
1ce211a9
AB
1651 },
1652 {
1653 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1654 .name = "CD Playback Switch",
1655 .info = aureon_ac97_mute_info,
1656 .get = aureon_ac97_mute_get,
1657 .put = aureon_ac97_mute_put,
1658 .private_value = AC97_CD
1659 },
1660 {
1661 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1662 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1663 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1664 .name = "CD Playback Volume",
1665 .info = aureon_ac97_vol_info,
1666 .get = aureon_ac97_vol_get,
1667 .put = aureon_ac97_vol_put,
1668 .private_value = AC97_CD|AUREON_AC97_STEREO,
f640c320 1669 .tlv = { .p = db_scale_ac97_gain }
1ce211a9
AB
1670 },
1671 {
1672 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1673 .name = "Aux Playback Switch",
1674 .info = aureon_ac97_mute_info,
1675 .get = aureon_ac97_mute_get,
1676 .put = aureon_ac97_mute_put,
1677 .private_value = AC97_AUX,
1678 },
1679 {
1680 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1681 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1682 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1683 .name = "Aux Playback Volume",
1684 .info = aureon_ac97_vol_info,
1685 .get = aureon_ac97_vol_get,
1686 .put = aureon_ac97_vol_put,
1687 .private_value = AC97_AUX|AUREON_AC97_STEREO,
f640c320 1688 .tlv = { .p = db_scale_ac97_gain }
1ce211a9
AB
1689 },
1690 {
1691 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1692 .name = "Line Playback Switch",
1693 .info = aureon_ac97_mute_info,
1694 .get = aureon_ac97_mute_get,
1695 .put = aureon_ac97_mute_put,
1696 .private_value = AC97_LINE
1697 },
1698 {
1699 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1700 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1701 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1702 .name = "Line Playback Volume",
1703 .info = aureon_ac97_vol_info,
1704 .get = aureon_ac97_vol_get,
1705 .put = aureon_ac97_vol_put,
1706 .private_value = AC97_LINE|AUREON_AC97_STEREO,
f640c320 1707 .tlv = { .p = db_scale_ac97_gain }
1ce211a9
AB
1708 },
1709 {
1710 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1711 .name = "Mic Playback Switch",
1712 .info = aureon_ac97_mute_info,
1713 .get = aureon_ac97_mute_get,
1714 .put = aureon_ac97_mute_put,
1715 .private_value = AC97_MIC
1716 },
1717 {
1718 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1719 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1720 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1721 .name = "Mic Playback Volume",
1722 .info = aureon_ac97_vol_info,
1723 .get = aureon_ac97_vol_get,
1724 .put = aureon_ac97_vol_put,
1725 .private_value = AC97_MIC,
f640c320 1726 .tlv = { .p = db_scale_ac97_gain }
1ce211a9
AB
1727 },
1728 {
1729 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1730 .name = "Mic Boost (+20dB)",
1731 .info = aureon_ac97_micboost_info,
1732 .get = aureon_ac97_micboost_get,
1733 .put = aureon_ac97_micboost_put
1734 }
1da177e4
LT
1735};
1736
1b60f6b0 1737static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1ce211a9
AB
1738 {
1739 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1da177e4
LT
1740 .name = "AC97 Playback Switch",
1741 .info = aureon_ac97_mmute_info,
1742 .get = aureon_ac97_mmute_get,
1743 .put = aureon_ac97_mmute_put,
1744 .private_value = AC97_MASTER
1ce211a9
AB
1745 },
1746 {
1747 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1748 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1749 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1750 .name = "AC97 Playback Volume",
1751 .info = aureon_ac97_vol_info,
1752 .get = aureon_ac97_vol_get,
1753 .put = aureon_ac97_vol_put,
1754 .private_value = AC97_MASTER|AUREON_AC97_STEREO,
f640c320 1755 .tlv = { .p = db_scale_ac97_master }
1ce211a9
AB
1756 },
1757 {
1758 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1759 .name = "CD Playback Switch",
1760 .info = aureon_ac97_mute_info,
1761 .get = aureon_ac97_mute_get,
1762 .put = aureon_ac97_mute_put,
1763 .private_value = AC97_AUX
1764 },
1765 {
1766 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1767 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1768 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1769 .name = "CD Playback Volume",
1770 .info = aureon_ac97_vol_info,
1771 .get = aureon_ac97_vol_get,
1772 .put = aureon_ac97_vol_put,
1773 .private_value = AC97_AUX|AUREON_AC97_STEREO,
f640c320 1774 .tlv = { .p = db_scale_ac97_gain }
1ce211a9
AB
1775 },
1776 {
1777 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1778 .name = "Phono Playback Switch",
1779 .info = aureon_ac97_mute_info,
1780 .get = aureon_ac97_mute_get,
1781 .put = aureon_ac97_mute_put,
1782 .private_value = AC97_CD
1783 },
1784 {
1785 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1786 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1787 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1788 .name = "Phono Playback Volume",
1789 .info = aureon_ac97_vol_info,
1790 .get = aureon_ac97_vol_get,
1791 .put = aureon_ac97_vol_put,
1792 .private_value = AC97_CD|AUREON_AC97_STEREO,
f640c320 1793 .tlv = { .p = db_scale_ac97_gain }
1ce211a9
AB
1794 },
1795 {
1796 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1797 .name = "Line Playback Switch",
1798 .info = aureon_ac97_mute_info,
1799 .get = aureon_ac97_mute_get,
1800 .put = aureon_ac97_mute_put,
1801 .private_value = AC97_LINE
1802 },
1803 {
1804 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1805 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1806 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1807 .name = "Line Playback Volume",
1808 .info = aureon_ac97_vol_info,
1809 .get = aureon_ac97_vol_get,
1810 .put = aureon_ac97_vol_put,
1811 .private_value = AC97_LINE|AUREON_AC97_STEREO,
f640c320 1812 .tlv = { .p = db_scale_ac97_gain }
1ce211a9
AB
1813 },
1814 {
1815 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1816 .name = "Mic Playback Switch",
1817 .info = aureon_ac97_mute_info,
1818 .get = aureon_ac97_mute_get,
1819 .put = aureon_ac97_mute_put,
1820 .private_value = AC97_MIC
1821 },
1822 {
1823 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1824 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1825 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1826 .name = "Mic Playback Volume",
1827 .info = aureon_ac97_vol_info,
1828 .get = aureon_ac97_vol_get,
1829 .put = aureon_ac97_vol_put,
1830 .private_value = AC97_MIC,
f640c320 1831 .tlv = { .p = db_scale_ac97_gain }
1ce211a9
AB
1832 },
1833 {
1834 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1835 .name = "Mic Boost (+20dB)",
1836 .info = aureon_ac97_micboost_info,
1837 .get = aureon_ac97_micboost_get,
1838 .put = aureon_ac97_micboost_put
1839 },
1840 {
1841 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1842 .name = "Aux Playback Switch",
1843 .info = aureon_ac97_mute_info,
1844 .get = aureon_ac97_mute_get,
1845 .put = aureon_ac97_mute_put,
1846 .private_value = AC97_VIDEO,
1847 },
1848 {
1849 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
f640c320 1850 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1ce211a9
AB
1851 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
1852 .name = "Aux Playback Volume",
1853 .info = aureon_ac97_vol_info,
1854 .get = aureon_ac97_vol_get,
1855 .put = aureon_ac97_vol_put,
1856 .private_value = AC97_VIDEO|AUREON_AC97_STEREO,
f640c320 1857 .tlv = { .p = db_scale_ac97_gain }
1ce211a9 1858 },
af9b70ac
MR
1859 {
1860 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1861 .name = "Aux Source",
1862 .info = aureon_universe_inmux_info,
1863 .get = aureon_universe_inmux_get,
1864 .put = aureon_universe_inmux_put
1865 }
1866
1da177e4
LT
1867};
1868
1b60f6b0 1869static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1da177e4
LT
1870 {
1871 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1ce211a9 1872 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
1da177e4
LT
1873 .info = aureon_cs8415_mute_info,
1874 .get = aureon_cs8415_mute_get,
1875 .put = aureon_cs8415_mute_put
1876 },
1ce211a9
AB
1877 {
1878 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1879 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Source",
1da177e4
LT
1880 .info = aureon_cs8415_mux_info,
1881 .get = aureon_cs8415_mux_get,
1882 .put = aureon_cs8415_mux_put,
1883 },
1884 {
1885 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1ce211a9 1886 .name = SNDRV_CTL_NAME_IEC958("Q-subcode ", CAPTURE, DEFAULT),
1da177e4
LT
1887 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1888 .info = aureon_cs8415_qsub_info,
1889 .get = aureon_cs8415_qsub_get,
1890 },
1891 {
1892 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1ce211a9 1893 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
1da177e4
LT
1894 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1895 .info = aureon_cs8415_spdif_info,
1896 .get = aureon_cs8415_mask_get
1897 },
1898 {
1899 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1ce211a9 1900 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
1da177e4
LT
1901 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1902 .info = aureon_cs8415_spdif_info,
1903 .get = aureon_cs8415_spdif_get
1904 },
1905 {
1906 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1ce211a9
AB
1907 .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, NONE) "Rate",
1908 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
1da177e4
LT
1909 .info = aureon_cs8415_rate_info,
1910 .get = aureon_cs8415_rate_get
1911 }
1912};
1913
ab0c7d72 1914static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1da177e4
LT
1915{
1916 unsigned int i, counts;
1917 int err;
1918
1919 counts = ARRAY_SIZE(aureon_dac_controls);
1920 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY)
1921 counts -= 2; /* no side */
1922 for (i = 0; i < counts; i++) {
1923 err = snd_ctl_add(ice->card, snd_ctl_new1(&aureon_dac_controls[i], ice));
1924 if (err < 0)
1925 return err;
1926 }
1927
1928 for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
1929 err = snd_ctl_add(ice->card, snd_ctl_new1(&wm_controls[i], ice));
1930 if (err < 0)
1931 return err;
1932 }
1ce211a9 1933
1da177e4
LT
1934 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON71_UNIVERSE) {
1935 for (i = 0; i < ARRAY_SIZE(universe_ac97_controls); i++) {
1936 err = snd_ctl_add(ice->card, snd_ctl_new1(&universe_ac97_controls[i], ice));
1937 if (err < 0)
1938 return err;
1939 }
1ce211a9 1940 } else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
cdf88efa 1941 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1da177e4
LT
1942 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1943 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1944 if (err < 0)
1945 return err;
1946 }
1947 }
1948
cdf88efa
TK
1949 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1950 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1da177e4
LT
1951 unsigned char id;
1952 snd_ice1712_save_gpio_status(ice);
1953 id = aureon_cs8415_get(ice, CS8415_ID);
1954 if (id != 0x41)
99b359ba 1955 snd_printk(KERN_INFO "No CS8415 chip. Skipping CS8415 controls.\n");
1da177e4 1956 else if ((id & 0x0F) != 0x01)
99b359ba 1957 snd_printk(KERN_INFO "Detected unsupported CS8415 rev. (%c)\n", (char)((id & 0x0F) + 'A' - 1));
1da177e4 1958 else {
1ce211a9 1959 for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
ab0c7d72 1960 struct snd_kcontrol *kctl;
1da177e4
LT
1961 err = snd_ctl_add(ice->card, (kctl = snd_ctl_new1(&cs8415_controls[i], ice)));
1962 if (err < 0)
1963 return err;
1964 if (i > 1)
1965 kctl->id.device = ice->pcm->device;
1966 }
1967 }
1968 snd_ice1712_restore_gpio_status(ice);
1969 }
1ce211a9 1970
1da177e4
LT
1971 return 0;
1972}
1973
1974
1975/*
1976 * initialize the chip
1977 */
ab0c7d72 1978static int __devinit aureon_init(struct snd_ice1712 *ice)
1da177e4 1979{
32b47da0 1980 static const unsigned short wm_inits_aureon[] = {
1da177e4
LT
1981 /* These come first to reduce init pop noise */
1982 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1983 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
1984 0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
1985
1986 0x18, 0x000, /* All power-up */
1987
1988 0x16, 0x122, /* I2S, normal polarity, 24bit */
1989 0x17, 0x022, /* 256fs, slave mode */
1990 0x00, 0, /* DAC1 analog mute */
1991 0x01, 0, /* DAC2 analog mute */
1992 0x02, 0, /* DAC3 analog mute */
1993 0x03, 0, /* DAC4 analog mute */
1994 0x04, 0, /* DAC5 analog mute */
1995 0x05, 0, /* DAC6 analog mute */
1996 0x06, 0, /* DAC7 analog mute */
1997 0x07, 0, /* DAC8 analog mute */
1998 0x08, 0x100, /* master analog mute */
1999 0x09, 0xff, /* DAC1 digital full */
2000 0x0a, 0xff, /* DAC2 digital full */
2001 0x0b, 0xff, /* DAC3 digital full */
2002 0x0c, 0xff, /* DAC4 digital full */
2003 0x0d, 0xff, /* DAC5 digital full */
2004 0x0e, 0xff, /* DAC6 digital full */
2005 0x0f, 0xff, /* DAC7 digital full */
2006 0x10, 0xff, /* DAC8 digital full */
2007 0x11, 0x1ff, /* master digital full */
2008 0x12, 0x000, /* phase normal */
2009 0x13, 0x090, /* unmute DAC L/R */
2010 0x14, 0x000, /* all unmute */
2011 0x15, 0x000, /* no deemphasis, no ZFLG */
2012 0x19, 0x000, /* -12dB ADC/L */
2013 0x1a, 0x000, /* -12dB ADC/R */
2014 (unsigned short)-1
2015 };
32b47da0 2016 static const unsigned short wm_inits_prodigy[] = {
1da177e4
LT
2017
2018 /* These come first to reduce init pop noise */
2019 0x1b, 0x000, /* ADC Mux */
2020 0x1c, 0x009, /* Out Mux1 */
2021 0x1d, 0x009, /* Out Mux2 */
2022
2023 0x18, 0x000, /* All power-up */
2024
2025 0x16, 0x022, /* I2S, normal polarity, 24bit, high-pass on */
2026 0x17, 0x006, /* 128fs, slave mode */
2027
2028 0x00, 0, /* DAC1 analog mute */
2029 0x01, 0, /* DAC2 analog mute */
2030 0x02, 0, /* DAC3 analog mute */
2031 0x03, 0, /* DAC4 analog mute */
2032 0x04, 0, /* DAC5 analog mute */
2033 0x05, 0, /* DAC6 analog mute */
2034 0x06, 0, /* DAC7 analog mute */
2035 0x07, 0, /* DAC8 analog mute */
2036 0x08, 0x100, /* master analog mute */
2037
2038 0x09, 0x7f, /* DAC1 digital full */
2039 0x0a, 0x7f, /* DAC2 digital full */
2040 0x0b, 0x7f, /* DAC3 digital full */
2041 0x0c, 0x7f, /* DAC4 digital full */
2042 0x0d, 0x7f, /* DAC5 digital full */
2043 0x0e, 0x7f, /* DAC6 digital full */
2044 0x0f, 0x7f, /* DAC7 digital full */
2045 0x10, 0x7f, /* DAC8 digital full */
2046 0x11, 0x1FF, /* master digital full */
2047
2048 0x12, 0x000, /* phase normal */
2049 0x13, 0x090, /* unmute DAC L/R */
2050 0x14, 0x000, /* all unmute */
2051 0x15, 0x000, /* no deemphasis, no ZFLG */
2052
2053 0x19, 0x000, /* -12dB ADC/L */
2054 0x1a, 0x000, /* -12dB ADC/R */
2055 (unsigned short)-1
2056
2057 };
32b47da0 2058 static const unsigned short cs_inits[] = {
1da177e4
LT
2059 0x0441, /* RUN */
2060 0x0180, /* no mute, OMCK output on RMCK pin */
2061 0x0201, /* S/PDIF source on RXP1 */
2062 0x0605, /* slave, 24bit, MSB on second OSCLK, SDOUT for right channel when OLRCK is high */
2063 (unsigned short)-1
2064 };
7cda8ba9 2065 struct aureon_spec *spec;
1da177e4 2066 unsigned int tmp;
32b47da0 2067 const unsigned short *p;
1da177e4
LT
2068 int err, i;
2069
7cda8ba9
TI
2070 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
2071 if (!spec)
2072 return -ENOMEM;
2073 ice->spec = spec;
2074
1da177e4
LT
2075 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
2076 ice->num_total_dacs = 6;
2077 ice->num_total_adcs = 2;
2078 } else {
2079 /* aureon 7.1 and prodigy 7.1 */
2080 ice->num_total_dacs = 8;
2081 ice->num_total_adcs = 2;
2082 }
2083
2084 /* to remeber the register values of CS8415 */
ab0c7d72 2085 ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
1ce211a9 2086 if (!ice->akm)
1da177e4
LT
2087 return -ENOMEM;
2088 ice->akm_codecs = 1;
1ce211a9
AB
2089
2090 err = aureon_ac97_init(ice);
2091 if (err != 0)
1da177e4
LT
2092 return err;
2093
2094 snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for the time being */
2095
2096 /* reset the wm codec as the SPI mode */
2097 snd_ice1712_save_gpio_status(ice);
2098 snd_ice1712_gpio_set_mask(ice, ~(AUREON_WM_RESET|AUREON_WM_CS|AUREON_CS8415_CS|AUREON_HP_SEL));
2099
2100 tmp = snd_ice1712_gpio_read(ice);
2101 tmp &= ~AUREON_WM_RESET;
2102 snd_ice1712_gpio_write(ice, tmp);
2103 udelay(1);
2104 tmp |= AUREON_WM_CS | AUREON_CS8415_CS;
2105 snd_ice1712_gpio_write(ice, tmp);
2106 udelay(1);
2107 tmp |= AUREON_WM_RESET;
2108 snd_ice1712_gpio_write(ice, tmp);
2109 udelay(1);
2110
2111 /* initialize WM8770 codec */
45fe722b 2112 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
cdf88efa 2113 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
1ce211a9 2114 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
1da177e4
LT
2115 p = wm_inits_prodigy;
2116 else
2117 p = wm_inits_aureon;
2118 for (; *p != (unsigned short)-1; p += 2)
2119 wm_put(ice, p[0], p[1]);
2120
2121 /* initialize CS8415A codec */
cdf88efa
TK
2122 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2123 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
45fe722b
TI
2124 for (p = cs_inits; *p != (unsigned short)-1; p++)
2125 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
7cda8ba9 2126 spec->cs8415_mux = 1;
1da177e4 2127
45fe722b
TI
2128 aureon_set_headphone_amp(ice, 1);
2129 }
1da177e4
LT
2130
2131 snd_ice1712_restore_gpio_status(ice);
af9b70ac 2132
1ce211a9 2133 /* initialize PCA9554 pin directions & set default input */
af9b70ac
MR
2134 aureon_pca9554_write(ice, PCA9554_DIR, 0x00);
2135 aureon_pca9554_write(ice, PCA9554_OUT, 0x00); /* internal AUX */
1ce211a9 2136
7cda8ba9
TI
2137 spec->master[0] = WM_VOL_MUTE;
2138 spec->master[1] = WM_VOL_MUTE;
1da177e4 2139 for (i = 0; i < ice->num_total_dacs; i++) {
7cda8ba9
TI
2140 spec->vol[i] = WM_VOL_MUTE;
2141 wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
1da177e4
LT
2142 }
2143
2144 return 0;
2145}
2146
2147
2148/*
2149 * Aureon boards don't provide the EEPROM data except for the vendor IDs.
2150 * hence the driver needs to sets up it properly.
2151 */
2152
1b60f6b0 2153static unsigned char aureon51_eeprom[] __devinitdata = {
189bc171
TI
2154 [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
2155 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2156 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2157 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2158 [ICE_EEP2_GPIO_DIR] = 0xff,
2159 [ICE_EEP2_GPIO_DIR1] = 0xff,
2160 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2161 [ICE_EEP2_GPIO_MASK] = 0x00,
2162 [ICE_EEP2_GPIO_MASK1] = 0x00,
2163 [ICE_EEP2_GPIO_MASK2] = 0x00,
2164 [ICE_EEP2_GPIO_STATE] = 0x00,
2165 [ICE_EEP2_GPIO_STATE1] = 0x00,
2166 [ICE_EEP2_GPIO_STATE2] = 0x00,
1da177e4
LT
2167};
2168
1b60f6b0 2169static unsigned char aureon71_eeprom[] __devinitdata = {
189bc171
TI
2170 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
2171 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2172 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2173 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2174 [ICE_EEP2_GPIO_DIR] = 0xff,
2175 [ICE_EEP2_GPIO_DIR1] = 0xff,
2176 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2177 [ICE_EEP2_GPIO_MASK] = 0x00,
2178 [ICE_EEP2_GPIO_MASK1] = 0x00,
2179 [ICE_EEP2_GPIO_MASK2] = 0x00,
2180 [ICE_EEP2_GPIO_STATE] = 0x00,
2181 [ICE_EEP2_GPIO_STATE1] = 0x00,
2182 [ICE_EEP2_GPIO_STATE2] = 0x00,
1da177e4 2183};
189bc171 2184#define prodigy71_eeprom aureon71_eeprom
1da177e4 2185
c1805ddd
MR
2186static unsigned char aureon71_universe_eeprom[] __devinitdata = {
2187 [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC,
2188 * 4DACs
2189 */
2190 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2191 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2192 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2193 [ICE_EEP2_GPIO_DIR] = 0xff,
2194 [ICE_EEP2_GPIO_DIR1] = 0xff,
2195 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2196 [ICE_EEP2_GPIO_MASK] = 0x00,
2197 [ICE_EEP2_GPIO_MASK1] = 0x00,
2198 [ICE_EEP2_GPIO_MASK2] = 0x00,
2199 [ICE_EEP2_GPIO_STATE] = 0x00,
2200 [ICE_EEP2_GPIO_STATE1] = 0x00,
2201 [ICE_EEP2_GPIO_STATE2] = 0x00,
2202};
2203
1b60f6b0 2204static unsigned char prodigy71lt_eeprom[] __devinitdata = {
189bc171
TI
2205 [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
2206 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2207 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2208 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2209 [ICE_EEP2_GPIO_DIR] = 0xff,
2210 [ICE_EEP2_GPIO_DIR1] = 0xff,
2211 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2212 [ICE_EEP2_GPIO_MASK] = 0x00,
2213 [ICE_EEP2_GPIO_MASK1] = 0x00,
2214 [ICE_EEP2_GPIO_MASK2] = 0x00,
2215 [ICE_EEP2_GPIO_STATE] = 0x00,
2216 [ICE_EEP2_GPIO_STATE1] = 0x00,
2217 [ICE_EEP2_GPIO_STATE2] = 0x00,
cdf88efa 2218};
189bc171 2219#define prodigy71xt_eeprom prodigy71lt_eeprom
45fe722b 2220
1da177e4 2221/* entry point */
1b60f6b0 2222struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
1da177e4
LT
2223 {
2224 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2225 .name = "Terratec Aureon 5.1-Sky",
2226 .model = "aureon51",
2227 .chip_init = aureon_init,
2228 .build_controls = aureon_add_controls,
2229 .eeprom_size = sizeof(aureon51_eeprom),
2230 .eeprom_data = aureon51_eeprom,
2231 .driver = "Aureon51",
2232 },
2233 {
2234 .subvendor = VT1724_SUBDEVICE_AUREON71_SPACE,
2235 .name = "Terratec Aureon 7.1-Space",
2236 .model = "aureon71",
2237 .chip_init = aureon_init,
2238 .build_controls = aureon_add_controls,
2239 .eeprom_size = sizeof(aureon71_eeprom),
2240 .eeprom_data = aureon71_eeprom,
2241 .driver = "Aureon71",
2242 },
1ce211a9
AB
2243 {
2244 .subvendor = VT1724_SUBDEVICE_AUREON71_UNIVERSE,
2245 .name = "Terratec Aureon 7.1-Universe",
1da177e4 2246 .model = "universe",
1ce211a9
AB
2247 .chip_init = aureon_init,
2248 .build_controls = aureon_add_controls,
c1805ddd
MR
2249 .eeprom_size = sizeof(aureon71_universe_eeprom),
2250 .eeprom_data = aureon71_universe_eeprom,
9f37c5b3 2251 .driver = "Aureon71Univ", /* keep in 15 letters */
1da177e4
LT
2252 },
2253 {
2254 .subvendor = VT1724_SUBDEVICE_PRODIGY71,
2255 .name = "Audiotrak Prodigy 7.1",
2256 .model = "prodigy71",
2257 .chip_init = aureon_init,
2258 .build_controls = aureon_add_controls,
2259 .eeprom_size = sizeof(prodigy71_eeprom),
2260 .eeprom_data = prodigy71_eeprom,
2261 .driver = "Prodigy71", /* should be identical with Aureon71 */
2262 },
45fe722b
TI
2263 {
2264 .subvendor = VT1724_SUBDEVICE_PRODIGY71LT,
2265 .name = "Audiotrak Prodigy 7.1 LT",
2266 .model = "prodigy71lt",
2267 .chip_init = aureon_init,
2268 .build_controls = aureon_add_controls,
2269 .eeprom_size = sizeof(prodigy71lt_eeprom),
2270 .eeprom_data = prodigy71lt_eeprom,
2271 .driver = "Prodigy71LT",
2272 },
cdf88efa
TK
2273 {
2274 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2275 .name = "Audiotrak Prodigy 7.1 XT",
2276 .model = "prodigy71xt",
2277 .chip_init = aureon_init,
2278 .build_controls = aureon_add_controls,
2279 .eeprom_size = sizeof(prodigy71xt_eeprom),
2280 .eeprom_data = prodigy71xt_eeprom,
2281 .driver = "Prodigy71LT",
2282 },
1da177e4
LT
2283 { } /* terminator */
2284};