Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/pci/ice1712/wtm.c
29266 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* ALSA driver for ICEnsemble VT1724 (Envy24HT)
4
*
5
* Lowlevel functions for Ego Sys Waveterminal 192M
6
*
7
* Copyright (c) 2006 Guedez Clement <[email protected]>
8
* Some functions are taken from the Prodigy192 driver
9
* source
10
*/
11
12
13
14
#include <linux/delay.h>
15
#include <linux/interrupt.h>
16
#include <linux/init.h>
17
#include <sound/core.h>
18
#include <sound/tlv.h>
19
#include <linux/slab.h>
20
21
#include "ice1712.h"
22
#include "envy24ht.h"
23
#include "wtm.h"
24
#include "stac946x.h"
25
26
struct wtm_spec {
27
/* rate change needs atomic mute/unmute of all dacs*/
28
struct mutex mute_mutex;
29
};
30
31
32
/*
33
* 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
34
*/
35
static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
36
unsigned char val)
37
{
38
snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
39
}
40
41
static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
42
{
43
return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
44
}
45
46
/*
47
* 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
48
*/
49
static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
50
unsigned char val)
51
{
52
snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
53
}
54
55
static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
56
{
57
return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
58
}
59
60
61
/*
62
* DAC mute control
63
*/
64
static void stac9460_dac_mute_all(struct snd_ice1712 *ice, unsigned char mute,
65
unsigned short int *change_mask)
66
{
67
unsigned char new, old;
68
int id, idx, change;
69
70
/*stac9460 1*/
71
for (id = 0; id < 7; id++) {
72
if (*change_mask & (0x01 << id)) {
73
if (id == 0)
74
idx = STAC946X_MASTER_VOLUME;
75
else
76
idx = STAC946X_LF_VOLUME - 1 + id;
77
old = stac9460_get(ice, idx);
78
new = (~mute << 7 & 0x80) | (old & ~0x80);
79
change = (new != old);
80
if (change) {
81
stac9460_put(ice, idx, new);
82
*change_mask = *change_mask | (0x01 << id);
83
} else {
84
*change_mask = *change_mask & ~(0x01 << id);
85
}
86
}
87
}
88
89
/*stac9460 2*/
90
for (id = 0; id < 3; id++) {
91
if (*change_mask & (0x01 << (id + 7))) {
92
if (id == 0)
93
idx = STAC946X_MASTER_VOLUME;
94
else
95
idx = STAC946X_LF_VOLUME - 1 + id;
96
old = stac9460_2_get(ice, idx);
97
new = (~mute << 7 & 0x80) | (old & ~0x80);
98
change = (new != old);
99
if (change) {
100
stac9460_2_put(ice, idx, new);
101
*change_mask = *change_mask | (0x01 << id);
102
} else {
103
*change_mask = *change_mask & ~(0x01 << id);
104
}
105
}
106
}
107
}
108
109
110
111
#define stac9460_dac_mute_info snd_ctl_boolean_mono_info
112
113
static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
114
struct snd_ctl_elem_value *ucontrol)
115
{
116
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
117
struct wtm_spec *spec = ice->spec;
118
unsigned char val;
119
int idx, id;
120
121
guard(mutex)(&spec->mute_mutex);
122
123
if (kcontrol->private_value) {
124
idx = STAC946X_MASTER_VOLUME;
125
id = 0;
126
} else {
127
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
128
idx = id + STAC946X_LF_VOLUME;
129
}
130
if (id < 6)
131
val = stac9460_get(ice, idx);
132
else
133
val = stac9460_2_get(ice, idx - 6);
134
ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
135
136
return 0;
137
}
138
139
static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
140
struct snd_ctl_elem_value *ucontrol)
141
{
142
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
143
unsigned char new, old;
144
int id, idx;
145
int change;
146
147
if (kcontrol->private_value) {
148
idx = STAC946X_MASTER_VOLUME;
149
old = stac9460_get(ice, idx);
150
new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
151
(old & ~0x80);
152
change = (new != old);
153
if (change) {
154
stac9460_put(ice, idx, new);
155
stac9460_2_put(ice, idx, new);
156
}
157
} else {
158
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
159
idx = id + STAC946X_LF_VOLUME;
160
if (id < 6)
161
old = stac9460_get(ice, idx);
162
else
163
old = stac9460_2_get(ice, idx - 6);
164
new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
165
(old & ~0x80);
166
change = (new != old);
167
if (change) {
168
if (id < 6)
169
stac9460_put(ice, idx, new);
170
else
171
stac9460_2_put(ice, idx - 6, new);
172
}
173
}
174
return change;
175
}
176
177
/*
178
* DAC volume attenuation mixer control
179
*/
180
static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
181
struct snd_ctl_elem_info *uinfo)
182
{
183
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
184
uinfo->count = 1;
185
uinfo->value.integer.min = 0; /* mute */
186
uinfo->value.integer.max = 0x7f; /* 0dB */
187
return 0;
188
}
189
190
static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
191
struct snd_ctl_elem_value *ucontrol)
192
{
193
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
194
int idx, id;
195
unsigned char vol;
196
197
if (kcontrol->private_value) {
198
idx = STAC946X_MASTER_VOLUME;
199
id = 0;
200
} else {
201
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
202
idx = id + STAC946X_LF_VOLUME;
203
}
204
if (id < 6)
205
vol = stac9460_get(ice, idx) & 0x7f;
206
else
207
vol = stac9460_2_get(ice, idx - 6) & 0x7f;
208
ucontrol->value.integer.value[0] = 0x7f - vol;
209
return 0;
210
}
211
212
static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
213
struct snd_ctl_elem_value *ucontrol)
214
{
215
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
216
int idx, id;
217
unsigned char tmp, ovol, nvol;
218
int change;
219
220
if (kcontrol->private_value) {
221
idx = STAC946X_MASTER_VOLUME;
222
nvol = ucontrol->value.integer.value[0] & 0x7f;
223
tmp = stac9460_get(ice, idx);
224
ovol = 0x7f - (tmp & 0x7f);
225
change = (ovol != nvol);
226
if (change) {
227
stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
228
stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
229
}
230
} else {
231
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
232
idx = id + STAC946X_LF_VOLUME;
233
nvol = ucontrol->value.integer.value[0] & 0x7f;
234
if (id < 6)
235
tmp = stac9460_get(ice, idx);
236
else
237
tmp = stac9460_2_get(ice, idx - 6);
238
ovol = 0x7f - (tmp & 0x7f);
239
change = (ovol != nvol);
240
if (change) {
241
if (id < 6)
242
stac9460_put(ice, idx, (0x7f - nvol) |
243
(tmp & 0x80));
244
else
245
stac9460_2_put(ice, idx-6, (0x7f - nvol) |
246
(tmp & 0x80));
247
}
248
}
249
return change;
250
}
251
252
/*
253
* ADC mute control
254
*/
255
#define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
256
257
static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
258
struct snd_ctl_elem_value *ucontrol)
259
{
260
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
261
unsigned char val;
262
int i, id;
263
264
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
265
if (id == 0) {
266
for (i = 0; i < 2; ++i) {
267
val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
268
ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
269
}
270
} else {
271
for (i = 0; i < 2; ++i) {
272
val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
273
ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
274
}
275
}
276
return 0;
277
}
278
279
static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
280
struct snd_ctl_elem_value *ucontrol)
281
{
282
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
283
unsigned char new, old;
284
int i, reg, id;
285
int change;
286
287
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
288
if (id == 0) {
289
for (i = 0; i < 2; ++i) {
290
reg = STAC946X_MIC_L_VOLUME + i;
291
old = stac9460_get(ice, reg);
292
new = (~ucontrol->value.integer.value[i]<<7&0x80) |
293
(old&~0x80);
294
change = (new != old);
295
if (change)
296
stac9460_put(ice, reg, new);
297
}
298
} else {
299
for (i = 0; i < 2; ++i) {
300
reg = STAC946X_MIC_L_VOLUME + i;
301
old = stac9460_2_get(ice, reg);
302
new = (~ucontrol->value.integer.value[i]<<7&0x80) |
303
(old&~0x80);
304
change = (new != old);
305
if (change)
306
stac9460_2_put(ice, reg, new);
307
}
308
}
309
return change;
310
}
311
312
/*
313
*ADC gain mixer control
314
*/
315
static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
316
struct snd_ctl_elem_info *uinfo)
317
{
318
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
319
uinfo->count = 2;
320
uinfo->value.integer.min = 0; /* 0dB */
321
uinfo->value.integer.max = 0x0f; /* 22.5dB */
322
return 0;
323
}
324
325
static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
326
struct snd_ctl_elem_value *ucontrol)
327
{
328
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
329
int i, reg, id;
330
unsigned char vol;
331
332
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
333
if (id == 0) {
334
for (i = 0; i < 2; ++i) {
335
reg = STAC946X_MIC_L_VOLUME + i;
336
vol = stac9460_get(ice, reg) & 0x0f;
337
ucontrol->value.integer.value[i] = 0x0f - vol;
338
}
339
} else {
340
for (i = 0; i < 2; ++i) {
341
reg = STAC946X_MIC_L_VOLUME + i;
342
vol = stac9460_2_get(ice, reg) & 0x0f;
343
ucontrol->value.integer.value[i] = 0x0f - vol;
344
}
345
}
346
return 0;
347
}
348
349
static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
350
struct snd_ctl_elem_value *ucontrol)
351
{
352
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
353
int i, reg, id;
354
unsigned char ovol, nvol;
355
int change;
356
357
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
358
if (id == 0) {
359
for (i = 0; i < 2; ++i) {
360
reg = STAC946X_MIC_L_VOLUME + i;
361
nvol = ucontrol->value.integer.value[i] & 0x0f;
362
ovol = 0x0f - stac9460_get(ice, reg);
363
change = ((ovol & 0x0f) != nvol);
364
if (change)
365
stac9460_put(ice, reg, (0x0f - nvol) |
366
(ovol & ~0x0f));
367
}
368
} else {
369
for (i = 0; i < 2; ++i) {
370
reg = STAC946X_MIC_L_VOLUME + i;
371
nvol = ucontrol->value.integer.value[i] & 0x0f;
372
ovol = 0x0f - stac9460_2_get(ice, reg);
373
change = ((ovol & 0x0f) != nvol);
374
if (change)
375
stac9460_2_put(ice, reg, (0x0f - nvol) |
376
(ovol & ~0x0f));
377
}
378
}
379
return change;
380
}
381
382
/*
383
* MIC / LINE switch fonction
384
*/
385
static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
386
struct snd_ctl_elem_info *uinfo)
387
{
388
static const char * const texts[2] = { "Line In", "Mic" };
389
390
return snd_ctl_enum_info(uinfo, 1, 2, texts);
391
}
392
393
394
static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
395
struct snd_ctl_elem_value *ucontrol)
396
{
397
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
398
unsigned char val;
399
int id;
400
401
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
402
if (id == 0)
403
val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
404
else
405
val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
406
ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1;
407
return 0;
408
}
409
410
static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
411
struct snd_ctl_elem_value *ucontrol)
412
{
413
struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
414
unsigned char new, old;
415
int change, id;
416
417
id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
418
if (id == 0)
419
old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
420
else
421
old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
422
new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80);
423
change = (new != old);
424
if (change) {
425
if (id == 0)
426
stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
427
else
428
stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
429
}
430
return change;
431
}
432
433
434
/*
435
* Handler for setting correct codec rate - called when rate change is detected
436
*/
437
static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
438
{
439
unsigned char old, new;
440
unsigned short int changed;
441
struct wtm_spec *spec = ice->spec;
442
443
if (rate == 0) /* no hint - S/PDIF input is master, simply return */
444
return;
445
else if (rate <= 48000)
446
new = 0x08; /* 256x, base rate mode */
447
else if (rate <= 96000)
448
new = 0x11; /* 256x, mid rate mode */
449
else
450
new = 0x12; /* 128x, high rate mode */
451
452
old = stac9460_get(ice, STAC946X_MASTER_CLOCKING);
453
if (old == new)
454
return;
455
/* change detected, setting master clock, muting first */
456
/* due to possible conflicts with mute controls - mutexing */
457
guard(mutex)(&spec->mute_mutex);
458
/* we have to remember current mute status for each DAC */
459
changed = 0xFFFF;
460
stac9460_dac_mute_all(ice, 0, &changed);
461
/*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/
462
stac9460_put(ice, STAC946X_MASTER_CLOCKING, new);
463
stac9460_2_put(ice, STAC946X_MASTER_CLOCKING, new);
464
udelay(10);
465
/* unmuting - only originally unmuted dacs -
466
* i.e. those changed when muting */
467
stac9460_dac_mute_all(ice, 1, &changed);
468
}
469
470
471
/*Limits value in dB for fader*/
472
static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
473
static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
474
475
/*
476
* Control tabs
477
*/
478
static const struct snd_kcontrol_new stac9640_controls[] = {
479
{
480
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
481
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
482
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
483
.name = "Master Playback Switch",
484
.info = stac9460_dac_mute_info,
485
.get = stac9460_dac_mute_get,
486
.put = stac9460_dac_mute_put,
487
.private_value = 1,
488
.tlv = { .p = db_scale_dac }
489
},
490
{
491
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
492
.name = "Master Playback Volume",
493
.info = stac9460_dac_vol_info,
494
.get = stac9460_dac_vol_get,
495
.put = stac9460_dac_vol_put,
496
.private_value = 1,
497
},
498
{
499
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
500
.name = "MIC/Line Input Enum",
501
.count = 2,
502
.info = stac9460_mic_sw_info,
503
.get = stac9460_mic_sw_get,
504
.put = stac9460_mic_sw_put,
505
506
},
507
{
508
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
509
.name = "DAC Switch",
510
.count = 8,
511
.info = stac9460_dac_mute_info,
512
.get = stac9460_dac_mute_get,
513
.put = stac9460_dac_mute_put,
514
},
515
{
516
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
517
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
518
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
519
520
.name = "DAC Volume",
521
.count = 8,
522
.info = stac9460_dac_vol_info,
523
.get = stac9460_dac_vol_get,
524
.put = stac9460_dac_vol_put,
525
.tlv = { .p = db_scale_dac }
526
},
527
{
528
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
529
.name = "ADC Switch",
530
.count = 2,
531
.info = stac9460_adc_mute_info,
532
.get = stac9460_adc_mute_get,
533
.put = stac9460_adc_mute_put,
534
},
535
{
536
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
537
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
538
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
539
540
.name = "ADC Volume",
541
.count = 2,
542
.info = stac9460_adc_vol_info,
543
.get = stac9460_adc_vol_get,
544
.put = stac9460_adc_vol_put,
545
.tlv = { .p = db_scale_adc }
546
}
547
};
548
549
550
551
/*INIT*/
552
static int wtm_add_controls(struct snd_ice1712 *ice)
553
{
554
unsigned int i;
555
int err;
556
557
for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
558
err = snd_ctl_add(ice->card,
559
snd_ctl_new1(&stac9640_controls[i], ice));
560
if (err < 0)
561
return err;
562
}
563
return 0;
564
}
565
566
static int wtm_init(struct snd_ice1712 *ice)
567
{
568
static const unsigned short stac_inits_wtm[] = {
569
STAC946X_RESET, 0,
570
STAC946X_MASTER_CLOCKING, 0x11,
571
(unsigned short)-1
572
};
573
const unsigned short *p;
574
struct wtm_spec *spec;
575
576
/*WTM 192M*/
577
ice->num_total_dacs = 8;
578
ice->num_total_adcs = 4;
579
ice->force_rdma1 = 1;
580
581
/*init mutex for dac mute conflict*/
582
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
583
if (!spec)
584
return -ENOMEM;
585
ice->spec = spec;
586
mutex_init(&spec->mute_mutex);
587
588
589
/*initialize codec*/
590
p = stac_inits_wtm;
591
for (; *p != (unsigned short)-1; p += 2) {
592
stac9460_put(ice, p[0], p[1]);
593
stac9460_2_put(ice, p[0], p[1]);
594
}
595
ice->gpio.set_pro_rate = stac9460_set_rate_val;
596
return 0;
597
}
598
599
600
static const unsigned char wtm_eeprom[] = {
601
[ICE_EEP2_SYSCONF] = 0x67, /*SYSCONF: clock 192KHz, mpu401,
602
4ADC, 8DAC */
603
[ICE_EEP2_ACLINK] = 0x80, /* ACLINK : I2S */
604
[ICE_EEP2_I2S] = 0xf8, /* I2S: vol; 96k, 24bit, 192k */
605
[ICE_EEP2_SPDIF] = 0xc1, /*SPDIF: out-en, spidf ext out*/
606
[ICE_EEP2_GPIO_DIR] = 0x9f,
607
[ICE_EEP2_GPIO_DIR1] = 0xff,
608
[ICE_EEP2_GPIO_DIR2] = 0x7f,
609
[ICE_EEP2_GPIO_MASK] = 0x9f,
610
[ICE_EEP2_GPIO_MASK1] = 0xff,
611
[ICE_EEP2_GPIO_MASK2] = 0x7f,
612
[ICE_EEP2_GPIO_STATE] = 0x16,
613
[ICE_EEP2_GPIO_STATE1] = 0x80,
614
[ICE_EEP2_GPIO_STATE2] = 0x00,
615
};
616
617
618
/*entry point*/
619
struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = {
620
{
621
.subvendor = VT1724_SUBDEVICE_WTM,
622
.name = "ESI Waveterminal 192M",
623
.model = "WT192M",
624
.chip_init = wtm_init,
625
.build_controls = wtm_add_controls,
626
.eeprom_size = sizeof(wtm_eeprom),
627
.eeprom_data = wtm_eeprom,
628
},
629
{} /*terminator*/
630
};
631
632