Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/ice1712/phase.c
10818 views
1
/*
2
* ALSA driver for ICEnsemble ICE1724 (Envy24)
3
*
4
* Lowlevel functions for Terratec PHASE 22
5
*
6
* Copyright (c) 2005 Misha Zhilin <[email protected]>
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
*
22
*/
23
24
/* PHASE 22 overview:
25
* Audio controller: VIA Envy24HT-S (slightly trimmed down Envy24HT, 4in/4out)
26
* Analog chip: AK4524 (partially via Philip's 74HCT125)
27
* Digital receiver: CS8414-CS (supported in this release)
28
* PHASE 22 revision 2.0 and Terrasoniq/Musonik TS22PCI have CS8416
29
* (support status unknown, please test and report)
30
*
31
* Envy connects to AK4524
32
* - CS directly from GPIO 10
33
* - CCLK via 74HCT125's gate #4 from GPIO 4
34
* - CDTI via 74HCT125's gate #2 from GPIO 5
35
* CDTI may be completely blocked by 74HCT125's gate #1
36
* controlled by GPIO 3
37
*/
38
39
/* PHASE 28 overview:
40
* Audio controller: VIA Envy24HT (full untrimmed version, 4in/8out)
41
* Analog chip: WM8770 (8 channel 192k DAC, 2 channel 96k ADC)
42
* Digital receiver: CS8414-CS (supported in this release)
43
*/
44
45
#include <asm/io.h>
46
#include <linux/delay.h>
47
#include <linux/interrupt.h>
48
#include <linux/init.h>
49
#include <linux/slab.h>
50
#include <linux/mutex.h>
51
52
#include <sound/core.h>
53
54
#include "ice1712.h"
55
#include "envy24ht.h"
56
#include "phase.h"
57
#include <sound/tlv.h>
58
59
/* AC97 register cache for Phase28 */
60
struct phase28_spec {
61
unsigned short master[2];
62
unsigned short vol[8];
63
};
64
65
/* WM8770 registers */
66
#define WM_DAC_ATTEN 0x00 /* DAC1-8 analog attenuation */
67
#define WM_DAC_MASTER_ATTEN 0x08 /* DAC master analog attenuation */
68
#define WM_DAC_DIG_ATTEN 0x09 /* DAC1-8 digital attenuation */
69
#define WM_DAC_DIG_MASTER_ATTEN 0x11 /* DAC master digital attenuation */
70
#define WM_PHASE_SWAP 0x12 /* DAC phase */
71
#define WM_DAC_CTRL1 0x13 /* DAC control bits */
72
#define WM_MUTE 0x14 /* mute controls */
73
#define WM_DAC_CTRL2 0x15 /* de-emphasis and zefo-flag */
74
#define WM_INT_CTRL 0x16 /* interface control */
75
#define WM_MASTER 0x17 /* master clock and mode */
76
#define WM_POWERDOWN 0x18 /* power-down controls */
77
#define WM_ADC_GAIN 0x19 /* ADC gain L(19)/R(1a) */
78
#define WM_ADC_MUX 0x1b /* input MUX */
79
#define WM_OUT_MUX1 0x1c /* output MUX */
80
#define WM_OUT_MUX2 0x1e /* output MUX */
81
#define WM_RESET 0x1f /* software reset */
82
83
84
/*
85
* Logarithmic volume values for WM8770
86
* Computed as 20 * Log10(255 / x)
87
*/
88
static const unsigned char wm_vol[256] = {
89
127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24,
90
24, 23, 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18,
91
17, 17, 17, 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14,
92
14, 13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11,
93
11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9,
94
9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7,
95
7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5,
96
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
97
4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
98
3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
99
2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
100
1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
101
};
102
103
#define WM_VOL_MAX (sizeof(wm_vol) - 1)
104
#define WM_VOL_MUTE 0x8000
105
106
static struct snd_akm4xxx akm_phase22 __devinitdata = {
107
.type = SND_AK4524,
108
.num_dacs = 2,
109
.num_adcs = 2,
110
};
111
112
static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
113
.caddr = 2,
114
.cif = 1,
115
.data_mask = 1 << 4,
116
.clk_mask = 1 << 5,
117
.cs_mask = 1 << 10,
118
.cs_addr = 1 << 10,
119
.cs_none = 0,
120
.add_flags = 1 << 3,
121
.mask_flags = 0,
122
};
123
124
static int __devinit phase22_init(struct snd_ice1712 *ice)
125
{
126
struct snd_akm4xxx *ak;
127
int err;
128
129
/* Configure DAC/ADC description for generic part of ice1724 */
130
switch (ice->eeprom.subvendor) {
131
case VT1724_SUBDEVICE_PHASE22:
132
case VT1724_SUBDEVICE_TS22:
133
ice->num_total_dacs = 2;
134
ice->num_total_adcs = 2;
135
ice->vt1720 = 1; /* Envy24HT-S have 16 bit wide GPIO */
136
break;
137
default:
138
snd_BUG();
139
return -EINVAL;
140
}
141
142
/* Initialize analog chips */
143
ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
144
ak = ice->akm;
145
if (!ak)
146
return -ENOMEM;
147
ice->akm_codecs = 1;
148
switch (ice->eeprom.subvendor) {
149
case VT1724_SUBDEVICE_PHASE22:
150
case VT1724_SUBDEVICE_TS22:
151
err = snd_ice1712_akm4xxx_init(ak, &akm_phase22,
152
&akm_phase22_priv, ice);
153
if (err < 0)
154
return err;
155
break;
156
}
157
158
return 0;
159
}
160
161
static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
162
{
163
int err = 0;
164
165
switch (ice->eeprom.subvendor) {
166
case VT1724_SUBDEVICE_PHASE22:
167
case VT1724_SUBDEVICE_TS22:
168
err = snd_ice1712_akm4xxx_build_controls(ice);
169
if (err < 0)
170
return err;
171
}
172
return 0;
173
}
174
175
static unsigned char phase22_eeprom[] __devinitdata = {
176
[ICE_EEP2_SYSCONF] = 0x28, /* clock 512, mpu 401,
177
spdif-in/1xADC, 1xDACs */
178
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
179
[ICE_EEP2_I2S] = 0xf0, /* vol, 96k, 24bit */
180
[ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
181
[ICE_EEP2_GPIO_DIR] = 0xff,
182
[ICE_EEP2_GPIO_DIR1] = 0xff,
183
[ICE_EEP2_GPIO_DIR2] = 0xff,
184
[ICE_EEP2_GPIO_MASK] = 0x00,
185
[ICE_EEP2_GPIO_MASK1] = 0x00,
186
[ICE_EEP2_GPIO_MASK2] = 0x00,
187
[ICE_EEP2_GPIO_STATE] = 0x00,
188
[ICE_EEP2_GPIO_STATE1] = 0x00,
189
[ICE_EEP2_GPIO_STATE2] = 0x00,
190
};
191
192
static unsigned char phase28_eeprom[] __devinitdata = {
193
[ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401,
194
spdif-in/1xADC, 4xDACs */
195
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
196
[ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
197
[ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
198
[ICE_EEP2_GPIO_DIR] = 0xff,
199
[ICE_EEP2_GPIO_DIR1] = 0xff,
200
[ICE_EEP2_GPIO_DIR2] = 0x5f,
201
[ICE_EEP2_GPIO_MASK] = 0x00,
202
[ICE_EEP2_GPIO_MASK1] = 0x00,
203
[ICE_EEP2_GPIO_MASK2] = 0x00,
204
[ICE_EEP2_GPIO_STATE] = 0x00,
205
[ICE_EEP2_GPIO_STATE1] = 0x00,
206
[ICE_EEP2_GPIO_STATE2] = 0x00,
207
};
208
209
/*
210
* write data in the SPI mode
211
*/
212
static void phase28_spi_write(struct snd_ice1712 *ice, unsigned int cs,
213
unsigned int data, int bits)
214
{
215
unsigned int tmp;
216
int i;
217
218
tmp = snd_ice1712_gpio_read(ice);
219
220
snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RW|PHASE28_SPI_MOSI|
221
PHASE28_SPI_CLK|PHASE28_WM_CS));
222
tmp |= PHASE28_WM_RW;
223
tmp &= ~cs;
224
snd_ice1712_gpio_write(ice, tmp);
225
udelay(1);
226
227
for (i = bits - 1; i >= 0; i--) {
228
tmp &= ~PHASE28_SPI_CLK;
229
snd_ice1712_gpio_write(ice, tmp);
230
udelay(1);
231
if (data & (1 << i))
232
tmp |= PHASE28_SPI_MOSI;
233
else
234
tmp &= ~PHASE28_SPI_MOSI;
235
snd_ice1712_gpio_write(ice, tmp);
236
udelay(1);
237
tmp |= PHASE28_SPI_CLK;
238
snd_ice1712_gpio_write(ice, tmp);
239
udelay(1);
240
}
241
242
tmp &= ~PHASE28_SPI_CLK;
243
tmp |= cs;
244
snd_ice1712_gpio_write(ice, tmp);
245
udelay(1);
246
tmp |= PHASE28_SPI_CLK;
247
snd_ice1712_gpio_write(ice, tmp);
248
udelay(1);
249
}
250
251
/*
252
* get the current register value of WM codec
253
*/
254
static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
255
{
256
reg <<= 1;
257
return ((unsigned short)ice->akm[0].images[reg] << 8) |
258
ice->akm[0].images[reg + 1];
259
}
260
261
/*
262
* set the register value of WM codec
263
*/
264
static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
265
{
266
phase28_spi_write(ice, PHASE28_WM_CS, (reg << 9) | (val & 0x1ff), 16);
267
}
268
269
/*
270
* set the register value of WM codec and remember it
271
*/
272
static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
273
{
274
wm_put_nocache(ice, reg, val);
275
reg <<= 1;
276
ice->akm[0].images[reg] = val >> 8;
277
ice->akm[0].images[reg + 1] = val;
278
}
279
280
static void wm_set_vol(struct snd_ice1712 *ice, unsigned int index,
281
unsigned short vol, unsigned short master)
282
{
283
unsigned char nvol;
284
285
if ((master & WM_VOL_MUTE) || (vol & WM_VOL_MUTE))
286
nvol = 0;
287
else
288
nvol = 127 - wm_vol[(((vol & ~WM_VOL_MUTE) *
289
(master & ~WM_VOL_MUTE)) / 127) & WM_VOL_MAX];
290
291
wm_put(ice, index, nvol);
292
wm_put_nocache(ice, index, 0x180 | nvol);
293
}
294
295
/*
296
* DAC mute control
297
*/
298
#define wm_pcm_mute_info snd_ctl_boolean_mono_info
299
300
static int wm_pcm_mute_get(struct snd_kcontrol *kcontrol,
301
struct snd_ctl_elem_value *ucontrol)
302
{
303
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
304
305
mutex_lock(&ice->gpio_mutex);
306
ucontrol->value.integer.value[0] = (wm_get(ice, WM_MUTE) & 0x10) ?
307
0 : 1;
308
mutex_unlock(&ice->gpio_mutex);
309
return 0;
310
}
311
312
static int wm_pcm_mute_put(struct snd_kcontrol *kcontrol,
313
struct snd_ctl_elem_value *ucontrol)
314
{
315
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
316
unsigned short nval, oval;
317
int change;
318
319
snd_ice1712_save_gpio_status(ice);
320
oval = wm_get(ice, WM_MUTE);
321
nval = (oval & ~0x10) | (ucontrol->value.integer.value[0] ? 0 : 0x10);
322
change = (nval != oval);
323
if (change)
324
wm_put(ice, WM_MUTE, nval);
325
snd_ice1712_restore_gpio_status(ice);
326
327
return change;
328
}
329
330
/*
331
* Master volume attenuation mixer control
332
*/
333
static int wm_master_vol_info(struct snd_kcontrol *kcontrol,
334
struct snd_ctl_elem_info *uinfo)
335
{
336
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
337
uinfo->count = 2;
338
uinfo->value.integer.min = 0;
339
uinfo->value.integer.max = WM_VOL_MAX;
340
return 0;
341
}
342
343
static int wm_master_vol_get(struct snd_kcontrol *kcontrol,
344
struct snd_ctl_elem_value *ucontrol)
345
{
346
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
347
struct phase28_spec *spec = ice->spec;
348
int i;
349
for (i = 0; i < 2; i++)
350
ucontrol->value.integer.value[i] = spec->master[i] &
351
~WM_VOL_MUTE;
352
return 0;
353
}
354
355
static int wm_master_vol_put(struct snd_kcontrol *kcontrol,
356
struct snd_ctl_elem_value *ucontrol)
357
{
358
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
359
struct phase28_spec *spec = ice->spec;
360
int ch, change = 0;
361
362
snd_ice1712_save_gpio_status(ice);
363
for (ch = 0; ch < 2; ch++) {
364
unsigned int vol = ucontrol->value.integer.value[ch];
365
if (vol > WM_VOL_MAX)
366
continue;
367
vol |= spec->master[ch] & WM_VOL_MUTE;
368
if (vol != spec->master[ch]) {
369
int dac;
370
spec->master[ch] = vol;
371
for (dac = 0; dac < ice->num_total_dacs; dac += 2)
372
wm_set_vol(ice, WM_DAC_ATTEN + dac + ch,
373
spec->vol[dac + ch],
374
spec->master[ch]);
375
change = 1;
376
}
377
}
378
snd_ice1712_restore_gpio_status(ice);
379
return change;
380
}
381
382
static int __devinit phase28_init(struct snd_ice1712 *ice)
383
{
384
static const unsigned short wm_inits_phase28[] = {
385
/* These come first to reduce init pop noise */
386
0x1b, 0x044, /* ADC Mux (AC'97 source) */
387
0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
388
0x1d, 0x009, /* Out Mux2 (VOUT2 = DAC, VOUT3 = DAC) */
389
390
0x18, 0x000, /* All power-up */
391
392
0x16, 0x122, /* I2S, normal polarity, 24bit */
393
0x17, 0x022, /* 256fs, slave mode */
394
0x00, 0, /* DAC1 analog mute */
395
0x01, 0, /* DAC2 analog mute */
396
0x02, 0, /* DAC3 analog mute */
397
0x03, 0, /* DAC4 analog mute */
398
0x04, 0, /* DAC5 analog mute */
399
0x05, 0, /* DAC6 analog mute */
400
0x06, 0, /* DAC7 analog mute */
401
0x07, 0, /* DAC8 analog mute */
402
0x08, 0x100, /* master analog mute */
403
0x09, 0xff, /* DAC1 digital full */
404
0x0a, 0xff, /* DAC2 digital full */
405
0x0b, 0xff, /* DAC3 digital full */
406
0x0c, 0xff, /* DAC4 digital full */
407
0x0d, 0xff, /* DAC5 digital full */
408
0x0e, 0xff, /* DAC6 digital full */
409
0x0f, 0xff, /* DAC7 digital full */
410
0x10, 0xff, /* DAC8 digital full */
411
0x11, 0x1ff, /* master digital full */
412
0x12, 0x000, /* phase normal */
413
0x13, 0x090, /* unmute DAC L/R */
414
0x14, 0x000, /* all unmute */
415
0x15, 0x000, /* no deemphasis, no ZFLG */
416
0x19, 0x000, /* -12dB ADC/L */
417
0x1a, 0x000, /* -12dB ADC/R */
418
(unsigned short)-1
419
};
420
421
unsigned int tmp;
422
struct snd_akm4xxx *ak;
423
struct phase28_spec *spec;
424
const unsigned short *p;
425
int i;
426
427
ice->num_total_dacs = 8;
428
ice->num_total_adcs = 2;
429
430
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
431
if (!spec)
432
return -ENOMEM;
433
ice->spec = spec;
434
435
/* Initialize analog chips */
436
ice->akm = kzalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
437
ak = ice->akm;
438
if (!ak)
439
return -ENOMEM;
440
ice->akm_codecs = 1;
441
442
snd_ice1712_gpio_set_dir(ice, 0x5fffff); /* fix this for time being */
443
444
/* reset the wm codec as the SPI mode */
445
snd_ice1712_save_gpio_status(ice);
446
snd_ice1712_gpio_set_mask(ice, ~(PHASE28_WM_RESET|PHASE28_WM_CS|
447
PHASE28_HP_SEL));
448
449
tmp = snd_ice1712_gpio_read(ice);
450
tmp &= ~PHASE28_WM_RESET;
451
snd_ice1712_gpio_write(ice, tmp);
452
udelay(1);
453
tmp |= PHASE28_WM_CS;
454
snd_ice1712_gpio_write(ice, tmp);
455
udelay(1);
456
tmp |= PHASE28_WM_RESET;
457
snd_ice1712_gpio_write(ice, tmp);
458
udelay(1);
459
460
p = wm_inits_phase28;
461
for (; *p != (unsigned short)-1; p += 2)
462
wm_put(ice, p[0], p[1]);
463
464
snd_ice1712_restore_gpio_status(ice);
465
466
spec->master[0] = WM_VOL_MUTE;
467
spec->master[1] = WM_VOL_MUTE;
468
for (i = 0; i < ice->num_total_dacs; i++) {
469
spec->vol[i] = WM_VOL_MUTE;
470
wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]);
471
}
472
473
return 0;
474
}
475
476
/*
477
* DAC volume attenuation mixer control
478
*/
479
static int wm_vol_info(struct snd_kcontrol *kcontrol,
480
struct snd_ctl_elem_info *uinfo)
481
{
482
int voices = kcontrol->private_value >> 8;
483
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
484
uinfo->count = voices;
485
uinfo->value.integer.min = 0; /* mute (-101dB) */
486
uinfo->value.integer.max = 0x7F; /* 0dB */
487
return 0;
488
}
489
490
static int wm_vol_get(struct snd_kcontrol *kcontrol,
491
struct snd_ctl_elem_value *ucontrol)
492
{
493
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
494
struct phase28_spec *spec = ice->spec;
495
int i, ofs, voices;
496
497
voices = kcontrol->private_value >> 8;
498
ofs = kcontrol->private_value & 0xff;
499
for (i = 0; i < voices; i++)
500
ucontrol->value.integer.value[i] =
501
spec->vol[ofs+i] & ~WM_VOL_MUTE;
502
return 0;
503
}
504
505
static int wm_vol_put(struct snd_kcontrol *kcontrol,
506
struct snd_ctl_elem_value *ucontrol)
507
{
508
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
509
struct phase28_spec *spec = ice->spec;
510
int i, idx, ofs, voices;
511
int change = 0;
512
513
voices = kcontrol->private_value >> 8;
514
ofs = kcontrol->private_value & 0xff;
515
snd_ice1712_save_gpio_status(ice);
516
for (i = 0; i < voices; i++) {
517
unsigned int vol;
518
vol = ucontrol->value.integer.value[i];
519
if (vol > 0x7f)
520
continue;
521
vol |= spec->vol[ofs+i] & WM_VOL_MUTE;
522
if (vol != spec->vol[ofs+i]) {
523
spec->vol[ofs+i] = vol;
524
idx = WM_DAC_ATTEN + ofs + i;
525
wm_set_vol(ice, idx, spec->vol[ofs+i],
526
spec->master[i]);
527
change = 1;
528
}
529
}
530
snd_ice1712_restore_gpio_status(ice);
531
return change;
532
}
533
534
/*
535
* WM8770 mute control
536
*/
537
static int wm_mute_info(struct snd_kcontrol *kcontrol,
538
struct snd_ctl_elem_info *uinfo) {
539
uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
540
uinfo->count = kcontrol->private_value >> 8;
541
uinfo->value.integer.min = 0;
542
uinfo->value.integer.max = 1;
543
return 0;
544
}
545
546
static int wm_mute_get(struct snd_kcontrol *kcontrol,
547
struct snd_ctl_elem_value *ucontrol)
548
{
549
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
550
struct phase28_spec *spec = ice->spec;
551
int voices, ofs, i;
552
553
voices = kcontrol->private_value >> 8;
554
ofs = kcontrol->private_value & 0xFF;
555
556
for (i = 0; i < voices; i++)
557
ucontrol->value.integer.value[i] =
558
(spec->vol[ofs+i] & WM_VOL_MUTE) ? 0 : 1;
559
return 0;
560
}
561
562
static int wm_mute_put(struct snd_kcontrol *kcontrol,
563
struct snd_ctl_elem_value *ucontrol)
564
{
565
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
566
struct phase28_spec *spec = ice->spec;
567
int change = 0, voices, ofs, i;
568
569
voices = kcontrol->private_value >> 8;
570
ofs = kcontrol->private_value & 0xFF;
571
572
snd_ice1712_save_gpio_status(ice);
573
for (i = 0; i < voices; i++) {
574
int val = (spec->vol[ofs + i] & WM_VOL_MUTE) ? 0 : 1;
575
if (ucontrol->value.integer.value[i] != val) {
576
spec->vol[ofs + i] &= ~WM_VOL_MUTE;
577
spec->vol[ofs + i] |=
578
ucontrol->value.integer.value[i] ? 0 :
579
WM_VOL_MUTE;
580
wm_set_vol(ice, ofs + i, spec->vol[ofs + i],
581
spec->master[i]);
582
change = 1;
583
}
584
}
585
snd_ice1712_restore_gpio_status(ice);
586
587
return change;
588
}
589
590
/*
591
* WM8770 master mute control
592
*/
593
#define wm_master_mute_info snd_ctl_boolean_stereo_info
594
595
static int wm_master_mute_get(struct snd_kcontrol *kcontrol,
596
struct snd_ctl_elem_value *ucontrol)
597
{
598
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
599
struct phase28_spec *spec = ice->spec;
600
601
ucontrol->value.integer.value[0] =
602
(spec->master[0] & WM_VOL_MUTE) ? 0 : 1;
603
ucontrol->value.integer.value[1] =
604
(spec->master[1] & WM_VOL_MUTE) ? 0 : 1;
605
return 0;
606
}
607
608
static int wm_master_mute_put(struct snd_kcontrol *kcontrol,
609
struct snd_ctl_elem_value *ucontrol)
610
{
611
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
612
struct phase28_spec *spec = ice->spec;
613
int change = 0, i;
614
615
snd_ice1712_save_gpio_status(ice);
616
for (i = 0; i < 2; i++) {
617
int val = (spec->master[i] & WM_VOL_MUTE) ? 0 : 1;
618
if (ucontrol->value.integer.value[i] != val) {
619
int dac;
620
spec->master[i] &= ~WM_VOL_MUTE;
621
spec->master[i] |=
622
ucontrol->value.integer.value[i] ? 0 :
623
WM_VOL_MUTE;
624
for (dac = 0; dac < ice->num_total_dacs; dac += 2)
625
wm_set_vol(ice, WM_DAC_ATTEN + dac + i,
626
spec->vol[dac + i],
627
spec->master[i]);
628
change = 1;
629
}
630
}
631
snd_ice1712_restore_gpio_status(ice);
632
633
return change;
634
}
635
636
/* digital master volume */
637
#define PCM_0dB 0xff
638
#define PCM_RES 128 /* -64dB */
639
#define PCM_MIN (PCM_0dB - PCM_RES)
640
static int wm_pcm_vol_info(struct snd_kcontrol *kcontrol,
641
struct snd_ctl_elem_info *uinfo)
642
{
643
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
644
uinfo->count = 1;
645
uinfo->value.integer.min = 0; /* mute (-64dB) */
646
uinfo->value.integer.max = PCM_RES; /* 0dB */
647
return 0;
648
}
649
650
static int wm_pcm_vol_get(struct snd_kcontrol *kcontrol,
651
struct snd_ctl_elem_value *ucontrol)
652
{
653
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
654
unsigned short val;
655
656
mutex_lock(&ice->gpio_mutex);
657
val = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
658
val = val > PCM_MIN ? (val - PCM_MIN) : 0;
659
ucontrol->value.integer.value[0] = val;
660
mutex_unlock(&ice->gpio_mutex);
661
return 0;
662
}
663
664
static int wm_pcm_vol_put(struct snd_kcontrol *kcontrol,
665
struct snd_ctl_elem_value *ucontrol)
666
{
667
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
668
unsigned short ovol, nvol;
669
int change = 0;
670
671
nvol = ucontrol->value.integer.value[0];
672
if (nvol > PCM_RES)
673
return -EINVAL;
674
snd_ice1712_save_gpio_status(ice);
675
nvol = (nvol ? (nvol + PCM_MIN) : 0) & 0xff;
676
ovol = wm_get(ice, WM_DAC_DIG_MASTER_ATTEN) & 0xff;
677
if (ovol != nvol) {
678
wm_put(ice, WM_DAC_DIG_MASTER_ATTEN, nvol); /* prelatch */
679
/* update */
680
wm_put_nocache(ice, WM_DAC_DIG_MASTER_ATTEN, nvol | 0x100);
681
change = 1;
682
}
683
snd_ice1712_restore_gpio_status(ice);
684
return change;
685
}
686
687
/*
688
* Deemphasis
689
*/
690
#define phase28_deemp_info snd_ctl_boolean_mono_info
691
692
static int phase28_deemp_get(struct snd_kcontrol *kcontrol,
693
struct snd_ctl_elem_value *ucontrol)
694
{
695
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
696
ucontrol->value.integer.value[0] = (wm_get(ice, WM_DAC_CTRL2) & 0xf) ==
697
0xf;
698
return 0;
699
}
700
701
static int phase28_deemp_put(struct snd_kcontrol *kcontrol,
702
struct snd_ctl_elem_value *ucontrol)
703
{
704
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
705
int temp, temp2;
706
temp = wm_get(ice, WM_DAC_CTRL2);
707
temp2 = temp;
708
if (ucontrol->value.integer.value[0])
709
temp |= 0xf;
710
else
711
temp &= ~0xf;
712
if (temp != temp2) {
713
wm_put(ice, WM_DAC_CTRL2, temp);
714
return 1;
715
}
716
return 0;
717
}
718
719
/*
720
* ADC Oversampling
721
*/
722
static int phase28_oversampling_info(struct snd_kcontrol *k,
723
struct snd_ctl_elem_info *uinfo)
724
{
725
static char *texts[2] = { "128x", "64x" };
726
727
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
728
uinfo->count = 1;
729
uinfo->value.enumerated.items = 2;
730
731
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
732
uinfo->value.enumerated.item = uinfo->value.enumerated.items -
733
1;
734
strcpy(uinfo->value.enumerated.name,
735
texts[uinfo->value.enumerated.item]);
736
737
return 0;
738
}
739
740
static int phase28_oversampling_get(struct snd_kcontrol *kcontrol,
741
struct snd_ctl_elem_value *ucontrol)
742
{
743
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
744
ucontrol->value.enumerated.item[0] = (wm_get(ice, WM_MASTER) & 0x8) ==
745
0x8;
746
return 0;
747
}
748
749
static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
750
struct snd_ctl_elem_value *ucontrol)
751
{
752
int temp, temp2;
753
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
754
755
temp = wm_get(ice, WM_MASTER);
756
temp2 = temp;
757
758
if (ucontrol->value.enumerated.item[0])
759
temp |= 0x8;
760
else
761
temp &= ~0x8;
762
763
if (temp != temp2) {
764
wm_put(ice, WM_MASTER, temp);
765
return 1;
766
}
767
return 0;
768
}
769
770
static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
771
static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
772
773
static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
774
{
775
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
776
.name = "Master Playback Switch",
777
.info = wm_master_mute_info,
778
.get = wm_master_mute_get,
779
.put = wm_master_mute_put
780
},
781
{
782
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
783
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
784
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
785
.name = "Master Playback Volume",
786
.info = wm_master_vol_info,
787
.get = wm_master_vol_get,
788
.put = wm_master_vol_put,
789
.tlv = { .p = db_scale_wm_dac }
790
},
791
{
792
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
793
.name = "Front Playback Switch",
794
.info = wm_mute_info,
795
.get = wm_mute_get,
796
.put = wm_mute_put,
797
.private_value = (2 << 8) | 0
798
},
799
{
800
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
801
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
802
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
803
.name = "Front Playback Volume",
804
.info = wm_vol_info,
805
.get = wm_vol_get,
806
.put = wm_vol_put,
807
.private_value = (2 << 8) | 0,
808
.tlv = { .p = db_scale_wm_dac }
809
},
810
{
811
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
812
.name = "Rear Playback Switch",
813
.info = wm_mute_info,
814
.get = wm_mute_get,
815
.put = wm_mute_put,
816
.private_value = (2 << 8) | 2
817
},
818
{
819
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
820
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
821
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
822
.name = "Rear Playback Volume",
823
.info = wm_vol_info,
824
.get = wm_vol_get,
825
.put = wm_vol_put,
826
.private_value = (2 << 8) | 2,
827
.tlv = { .p = db_scale_wm_dac }
828
},
829
{
830
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
831
.name = "Center Playback Switch",
832
.info = wm_mute_info,
833
.get = wm_mute_get,
834
.put = wm_mute_put,
835
.private_value = (1 << 8) | 4
836
},
837
{
838
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
839
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
840
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
841
.name = "Center Playback Volume",
842
.info = wm_vol_info,
843
.get = wm_vol_get,
844
.put = wm_vol_put,
845
.private_value = (1 << 8) | 4,
846
.tlv = { .p = db_scale_wm_dac }
847
},
848
{
849
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
850
.name = "LFE Playback Switch",
851
.info = wm_mute_info,
852
.get = wm_mute_get,
853
.put = wm_mute_put,
854
.private_value = (1 << 8) | 5
855
},
856
{
857
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
858
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
859
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
860
.name = "LFE Playback Volume",
861
.info = wm_vol_info,
862
.get = wm_vol_get,
863
.put = wm_vol_put,
864
.private_value = (1 << 8) | 5,
865
.tlv = { .p = db_scale_wm_dac }
866
},
867
{
868
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
869
.name = "Side Playback Switch",
870
.info = wm_mute_info,
871
.get = wm_mute_get,
872
.put = wm_mute_put,
873
.private_value = (2 << 8) | 6
874
},
875
{
876
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
877
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
878
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
879
.name = "Side Playback Volume",
880
.info = wm_vol_info,
881
.get = wm_vol_get,
882
.put = wm_vol_put,
883
.private_value = (2 << 8) | 6,
884
.tlv = { .p = db_scale_wm_dac }
885
}
886
};
887
888
static struct snd_kcontrol_new wm_controls[] __devinitdata = {
889
{
890
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
891
.name = "PCM Playback Switch",
892
.info = wm_pcm_mute_info,
893
.get = wm_pcm_mute_get,
894
.put = wm_pcm_mute_put
895
},
896
{
897
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
898
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
899
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
900
.name = "PCM Playback Volume",
901
.info = wm_pcm_vol_info,
902
.get = wm_pcm_vol_get,
903
.put = wm_pcm_vol_put,
904
.tlv = { .p = db_scale_wm_pcm }
905
},
906
{
907
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
908
.name = "DAC Deemphasis Switch",
909
.info = phase28_deemp_info,
910
.get = phase28_deemp_get,
911
.put = phase28_deemp_put
912
},
913
{
914
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
915
.name = "ADC Oversampling",
916
.info = phase28_oversampling_info,
917
.get = phase28_oversampling_get,
918
.put = phase28_oversampling_put
919
}
920
};
921
922
static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
923
{
924
unsigned int i, counts;
925
int err;
926
927
counts = ARRAY_SIZE(phase28_dac_controls);
928
for (i = 0; i < counts; i++) {
929
err = snd_ctl_add(ice->card,
930
snd_ctl_new1(&phase28_dac_controls[i],
931
ice));
932
if (err < 0)
933
return err;
934
}
935
936
for (i = 0; i < ARRAY_SIZE(wm_controls); i++) {
937
err = snd_ctl_add(ice->card,
938
snd_ctl_new1(&wm_controls[i], ice));
939
if (err < 0)
940
return err;
941
}
942
943
return 0;
944
}
945
946
struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
947
{
948
.subvendor = VT1724_SUBDEVICE_PHASE22,
949
.name = "Terratec PHASE 22",
950
.model = "phase22",
951
.chip_init = phase22_init,
952
.build_controls = phase22_add_controls,
953
.eeprom_size = sizeof(phase22_eeprom),
954
.eeprom_data = phase22_eeprom,
955
},
956
{
957
.subvendor = VT1724_SUBDEVICE_PHASE28,
958
.name = "Terratec PHASE 28",
959
.model = "phase28",
960
.chip_init = phase28_init,
961
.build_controls = phase28_add_controls,
962
.eeprom_size = sizeof(phase28_eeprom),
963
.eeprom_data = phase28_eeprom,
964
},
965
{
966
.subvendor = VT1724_SUBDEVICE_TS22,
967
.name = "Terrasoniq TS22 PCI",
968
.model = "TS22",
969
.chip_init = phase22_init,
970
.build_controls = phase22_add_controls,
971
.eeprom_size = sizeof(phase22_eeprom),
972
.eeprom_data = phase22_eeprom,
973
},
974
{ } /* terminator */
975
};
976
977