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