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