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