Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/pci/ice1712/maya44.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 ESI Maya44 cards
6
*
7
* Copyright (c) 2009 Takashi Iwai <[email protected]>
8
* Based on the patches by Rainer Zimmermann <[email protected]>
9
*/
10
11
#include <linux/init.h>
12
#include <linux/slab.h>
13
#include <sound/core.h>
14
#include <sound/control.h>
15
#include <sound/pcm.h>
16
#include <sound/tlv.h>
17
18
#include "ice1712.h"
19
#include "envy24ht.h"
20
#include "maya44.h"
21
22
/* WM8776 register indexes */
23
#define WM8776_REG_HEADPHONE_L 0x00
24
#define WM8776_REG_HEADPHONE_R 0x01
25
#define WM8776_REG_HEADPHONE_MASTER 0x02
26
#define WM8776_REG_DAC_ATTEN_L 0x03
27
#define WM8776_REG_DAC_ATTEN_R 0x04
28
#define WM8776_REG_DAC_ATTEN_MASTER 0x05
29
#define WM8776_REG_DAC_PHASE 0x06
30
#define WM8776_REG_DAC_CONTROL 0x07
31
#define WM8776_REG_DAC_MUTE 0x08
32
#define WM8776_REG_DAC_DEEMPH 0x09
33
#define WM8776_REG_DAC_IF_CONTROL 0x0a
34
#define WM8776_REG_ADC_IF_CONTROL 0x0b
35
#define WM8776_REG_MASTER_MODE_CONTROL 0x0c
36
#define WM8776_REG_POWERDOWN 0x0d
37
#define WM8776_REG_ADC_ATTEN_L 0x0e
38
#define WM8776_REG_ADC_ATTEN_R 0x0f
39
#define WM8776_REG_ADC_ALC1 0x10
40
#define WM8776_REG_ADC_ALC2 0x11
41
#define WM8776_REG_ADC_ALC3 0x12
42
#define WM8776_REG_ADC_NOISE_GATE 0x13
43
#define WM8776_REG_ADC_LIMITER 0x14
44
#define WM8776_REG_ADC_MUX 0x15
45
#define WM8776_REG_OUTPUT_MUX 0x16
46
#define WM8776_REG_RESET 0x17
47
48
#define WM8776_NUM_REGS 0x18
49
50
/* clock ratio identifiers for snd_wm8776_set_rate() */
51
#define WM8776_CLOCK_RATIO_128FS 0
52
#define WM8776_CLOCK_RATIO_192FS 1
53
#define WM8776_CLOCK_RATIO_256FS 2
54
#define WM8776_CLOCK_RATIO_384FS 3
55
#define WM8776_CLOCK_RATIO_512FS 4
56
#define WM8776_CLOCK_RATIO_768FS 5
57
58
enum { WM_VOL_HP, WM_VOL_DAC, WM_VOL_ADC, WM_NUM_VOLS };
59
enum { WM_SW_DAC, WM_SW_BYPASS, WM_NUM_SWITCHES };
60
61
struct snd_wm8776 {
62
unsigned char addr;
63
unsigned short regs[WM8776_NUM_REGS];
64
unsigned char volumes[WM_NUM_VOLS][2];
65
unsigned int switch_bits;
66
};
67
68
struct snd_maya44 {
69
struct snd_ice1712 *ice;
70
struct snd_wm8776 wm[2];
71
struct mutex mutex;
72
};
73
74
75
/* write the given register and save the data to the cache */
76
static void wm8776_write(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
77
unsigned char reg, unsigned short val)
78
{
79
/*
80
* WM8776 registers are up to 9 bits wide, bit 8 is placed in the LSB
81
* of the address field
82
*/
83
snd_vt1724_write_i2c(ice, wm->addr,
84
(reg << 1) | ((val >> 8) & 1),
85
val & 0xff);
86
wm->regs[reg] = val;
87
}
88
89
/*
90
* update the given register with and/or mask and save the data to the cache
91
*/
92
static int wm8776_write_bits(struct snd_ice1712 *ice, struct snd_wm8776 *wm,
93
unsigned char reg,
94
unsigned short mask, unsigned short val)
95
{
96
val |= wm->regs[reg] & ~mask;
97
if (val != wm->regs[reg]) {
98
wm8776_write(ice, wm, reg, val);
99
return 1;
100
}
101
return 0;
102
}
103
104
105
/*
106
* WM8776 volume controls
107
*/
108
109
struct maya_vol_info {
110
unsigned int maxval; /* volume range: 0..maxval */
111
unsigned char regs[2]; /* left and right registers */
112
unsigned short mask; /* value mask */
113
unsigned short offset; /* zero-value offset */
114
unsigned short mute; /* mute bit */
115
unsigned short update; /* update bits */
116
unsigned char mux_bits[2]; /* extra bits for ADC mute */
117
};
118
119
static const struct maya_vol_info vol_info[WM_NUM_VOLS] = {
120
[WM_VOL_HP] = {
121
.maxval = 80,
122
.regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R },
123
.mask = 0x7f,
124
.offset = 0x30,
125
.mute = 0x00,
126
.update = 0x180, /* update and zero-cross enable */
127
},
128
[WM_VOL_DAC] = {
129
.maxval = 255,
130
.regs = { WM8776_REG_DAC_ATTEN_L, WM8776_REG_DAC_ATTEN_R },
131
.mask = 0xff,
132
.offset = 0x01,
133
.mute = 0x00,
134
.update = 0x100, /* zero-cross enable */
135
},
136
[WM_VOL_ADC] = {
137
.maxval = 91,
138
.regs = { WM8776_REG_ADC_ATTEN_L, WM8776_REG_ADC_ATTEN_R },
139
.mask = 0xff,
140
.offset = 0xa5,
141
.mute = 0xa5,
142
.update = 0x100, /* update */
143
.mux_bits = { 0x80, 0x40 }, /* ADCMUX bits */
144
},
145
};
146
147
/*
148
* dB tables
149
*/
150
/* headphone output: mute, -73..+6db (1db step) */
151
static const DECLARE_TLV_DB_SCALE(db_scale_hp, -7400, 100, 1);
152
/* DAC output: mute, -127..0db (0.5db step) */
153
static const DECLARE_TLV_DB_SCALE(db_scale_dac, -12750, 50, 1);
154
/* ADC gain: mute, -21..+24db (0.5db step) */
155
static const DECLARE_TLV_DB_SCALE(db_scale_adc, -2100, 50, 1);
156
157
static int maya_vol_info(struct snd_kcontrol *kcontrol,
158
struct snd_ctl_elem_info *uinfo)
159
{
160
unsigned int idx = kcontrol->private_value;
161
const struct maya_vol_info *vol = &vol_info[idx];
162
163
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
164
uinfo->count = 2;
165
uinfo->value.integer.min = 0;
166
uinfo->value.integer.max = vol->maxval;
167
return 0;
168
}
169
170
static int maya_vol_get(struct snd_kcontrol *kcontrol,
171
struct snd_ctl_elem_value *ucontrol)
172
{
173
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
174
struct snd_wm8776 *wm =
175
&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
176
unsigned int idx = kcontrol->private_value;
177
178
mutex_lock(&chip->mutex);
179
ucontrol->value.integer.value[0] = wm->volumes[idx][0];
180
ucontrol->value.integer.value[1] = wm->volumes[idx][1];
181
mutex_unlock(&chip->mutex);
182
return 0;
183
}
184
185
static int maya_vol_put(struct snd_kcontrol *kcontrol,
186
struct snd_ctl_elem_value *ucontrol)
187
{
188
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
189
struct snd_wm8776 *wm =
190
&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
191
unsigned int idx = kcontrol->private_value;
192
const struct maya_vol_info *vol = &vol_info[idx];
193
unsigned int val, data;
194
int ch, changed = 0;
195
196
mutex_lock(&chip->mutex);
197
for (ch = 0; ch < 2; ch++) {
198
val = ucontrol->value.integer.value[ch];
199
if (val > vol->maxval)
200
val = vol->maxval;
201
if (val == wm->volumes[idx][ch])
202
continue;
203
if (!val)
204
data = vol->mute;
205
else
206
data = (val - 1) + vol->offset;
207
data |= vol->update;
208
changed |= wm8776_write_bits(chip->ice, wm, vol->regs[ch],
209
vol->mask | vol->update, data);
210
if (vol->mux_bits[ch])
211
wm8776_write_bits(chip->ice, wm, WM8776_REG_ADC_MUX,
212
vol->mux_bits[ch],
213
val ? 0 : vol->mux_bits[ch]);
214
wm->volumes[idx][ch] = val;
215
}
216
mutex_unlock(&chip->mutex);
217
return changed;
218
}
219
220
/*
221
* WM8776 switch controls
222
*/
223
224
#define COMPOSE_SW_VAL(idx, reg, mask) ((idx) | ((reg) << 8) | ((mask) << 16))
225
#define GET_SW_VAL_IDX(val) ((val) & 0xff)
226
#define GET_SW_VAL_REG(val) (((val) >> 8) & 0xff)
227
#define GET_SW_VAL_MASK(val) (((val) >> 16) & 0xff)
228
229
#define maya_sw_info snd_ctl_boolean_mono_info
230
231
static int maya_sw_get(struct snd_kcontrol *kcontrol,
232
struct snd_ctl_elem_value *ucontrol)
233
{
234
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
235
struct snd_wm8776 *wm =
236
&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
237
unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
238
239
ucontrol->value.integer.value[0] = (wm->switch_bits >> idx) & 1;
240
return 0;
241
}
242
243
static int maya_sw_put(struct snd_kcontrol *kcontrol,
244
struct snd_ctl_elem_value *ucontrol)
245
{
246
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
247
struct snd_wm8776 *wm =
248
&chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
249
unsigned int idx = GET_SW_VAL_IDX(kcontrol->private_value);
250
unsigned int mask, val;
251
int changed;
252
253
mutex_lock(&chip->mutex);
254
mask = 1 << idx;
255
wm->switch_bits &= ~mask;
256
val = ucontrol->value.integer.value[0];
257
if (val)
258
wm->switch_bits |= mask;
259
mask = GET_SW_VAL_MASK(kcontrol->private_value);
260
changed = wm8776_write_bits(chip->ice, wm,
261
GET_SW_VAL_REG(kcontrol->private_value),
262
mask, val ? mask : 0);
263
mutex_unlock(&chip->mutex);
264
return changed;
265
}
266
267
/*
268
* GPIO pins (known ones for maya44)
269
*/
270
#define GPIO_PHANTOM_OFF 2
271
#define GPIO_MIC_RELAY 4
272
#define GPIO_SPDIF_IN_INV 5
273
#define GPIO_MUST_BE_0 7
274
275
/*
276
* GPIO switch controls
277
*/
278
279
#define COMPOSE_GPIO_VAL(shift, inv) ((shift) | ((inv) << 8))
280
#define GET_GPIO_VAL_SHIFT(val) ((val) & 0xff)
281
#define GET_GPIO_VAL_INV(val) (((val) >> 8) & 1)
282
283
static int maya_set_gpio_bits(struct snd_ice1712 *ice, unsigned int mask,
284
unsigned int bits)
285
{
286
unsigned int data;
287
data = snd_ice1712_gpio_read(ice);
288
if ((data & mask) == bits)
289
return 0;
290
snd_ice1712_gpio_write(ice, (data & ~mask) | bits);
291
return 1;
292
}
293
294
#define maya_gpio_sw_info snd_ctl_boolean_mono_info
295
296
static int maya_gpio_sw_get(struct snd_kcontrol *kcontrol,
297
struct snd_ctl_elem_value *ucontrol)
298
{
299
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
300
unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
301
unsigned int val;
302
303
val = (snd_ice1712_gpio_read(chip->ice) >> shift) & 1;
304
if (GET_GPIO_VAL_INV(kcontrol->private_value))
305
val = !val;
306
ucontrol->value.integer.value[0] = val;
307
return 0;
308
}
309
310
static int maya_gpio_sw_put(struct snd_kcontrol *kcontrol,
311
struct snd_ctl_elem_value *ucontrol)
312
{
313
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
314
unsigned int shift = GET_GPIO_VAL_SHIFT(kcontrol->private_value);
315
unsigned int val, mask;
316
int changed;
317
318
mutex_lock(&chip->mutex);
319
mask = 1 << shift;
320
val = ucontrol->value.integer.value[0];
321
if (GET_GPIO_VAL_INV(kcontrol->private_value))
322
val = !val;
323
val = val ? mask : 0;
324
changed = maya_set_gpio_bits(chip->ice, mask, val);
325
mutex_unlock(&chip->mutex);
326
return changed;
327
}
328
329
/*
330
* capture source selection
331
*/
332
333
/* known working input slots (0-4) */
334
#define MAYA_LINE_IN 1 /* in-2 */
335
#define MAYA_MIC_IN 3 /* in-4 */
336
337
static void wm8776_select_input(struct snd_maya44 *chip, int idx, int line)
338
{
339
wm8776_write_bits(chip->ice, &chip->wm[idx], WM8776_REG_ADC_MUX,
340
0x1f, 1 << line);
341
}
342
343
static int maya_rec_src_info(struct snd_kcontrol *kcontrol,
344
struct snd_ctl_elem_info *uinfo)
345
{
346
static const char * const texts[] = { "Line", "Mic" };
347
348
return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
349
}
350
351
static int maya_rec_src_get(struct snd_kcontrol *kcontrol,
352
struct snd_ctl_elem_value *ucontrol)
353
{
354
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
355
int sel;
356
357
if (snd_ice1712_gpio_read(chip->ice) & (1 << GPIO_MIC_RELAY))
358
sel = 1;
359
else
360
sel = 0;
361
ucontrol->value.enumerated.item[0] = sel;
362
return 0;
363
}
364
365
static int maya_rec_src_put(struct snd_kcontrol *kcontrol,
366
struct snd_ctl_elem_value *ucontrol)
367
{
368
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
369
int sel = ucontrol->value.enumerated.item[0];
370
int changed;
371
372
mutex_lock(&chip->mutex);
373
changed = maya_set_gpio_bits(chip->ice, 1 << GPIO_MIC_RELAY,
374
sel ? (1 << GPIO_MIC_RELAY) : 0);
375
wm8776_select_input(chip, 0, sel ? MAYA_MIC_IN : MAYA_LINE_IN);
376
mutex_unlock(&chip->mutex);
377
return changed;
378
}
379
380
/*
381
* Maya44 routing switch settings have different meanings than the standard
382
* ice1724 switches as defined in snd_vt1724_pro_route_info (ice1724.c).
383
*/
384
static int maya_pb_route_info(struct snd_kcontrol *kcontrol,
385
struct snd_ctl_elem_info *uinfo)
386
{
387
static const char * const texts[] = {
388
"PCM Out", /* 0 */
389
"Input 1", "Input 2", "Input 3", "Input 4"
390
};
391
392
return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
393
}
394
395
static int maya_pb_route_shift(int idx)
396
{
397
static const unsigned char shift[10] =
398
{ 8, 20, 0, 3, 11, 23, 14, 26, 17, 29 };
399
return shift[idx % 10];
400
}
401
402
static int maya_pb_route_get(struct snd_kcontrol *kcontrol,
403
struct snd_ctl_elem_value *ucontrol)
404
{
405
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
406
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
407
ucontrol->value.enumerated.item[0] =
408
snd_ice1724_get_route_val(chip->ice, maya_pb_route_shift(idx));
409
return 0;
410
}
411
412
static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
413
struct snd_ctl_elem_value *ucontrol)
414
{
415
struct snd_maya44 *chip = snd_kcontrol_chip(kcontrol);
416
int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
417
return snd_ice1724_put_route_val(chip->ice,
418
ucontrol->value.enumerated.item[0],
419
maya_pb_route_shift(idx));
420
}
421
422
423
/*
424
* controls to be added
425
*/
426
427
static const struct snd_kcontrol_new maya_controls[] = {
428
{
429
.name = "Crossmix Playback Volume",
430
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
431
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
432
SNDRV_CTL_ELEM_ACCESS_TLV_READ,
433
.info = maya_vol_info,
434
.get = maya_vol_get,
435
.put = maya_vol_put,
436
.tlv = { .p = db_scale_hp },
437
.private_value = WM_VOL_HP,
438
.count = 2,
439
},
440
{
441
.name = "PCM Playback Volume",
442
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
443
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
444
SNDRV_CTL_ELEM_ACCESS_TLV_READ,
445
.info = maya_vol_info,
446
.get = maya_vol_get,
447
.put = maya_vol_put,
448
.tlv = { .p = db_scale_dac },
449
.private_value = WM_VOL_DAC,
450
.count = 2,
451
},
452
{
453
.name = "Line Capture Volume",
454
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
455
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
456
SNDRV_CTL_ELEM_ACCESS_TLV_READ,
457
.info = maya_vol_info,
458
.get = maya_vol_get,
459
.put = maya_vol_put,
460
.tlv = { .p = db_scale_adc },
461
.private_value = WM_VOL_ADC,
462
.count = 2,
463
},
464
{
465
.name = "PCM Playback Switch",
466
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
467
.info = maya_sw_info,
468
.get = maya_sw_get,
469
.put = maya_sw_put,
470
.private_value = COMPOSE_SW_VAL(WM_SW_DAC,
471
WM8776_REG_OUTPUT_MUX, 0x01),
472
.count = 2,
473
},
474
{
475
.name = "Bypass Playback Switch",
476
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
477
.info = maya_sw_info,
478
.get = maya_sw_get,
479
.put = maya_sw_put,
480
.private_value = COMPOSE_SW_VAL(WM_SW_BYPASS,
481
WM8776_REG_OUTPUT_MUX, 0x04),
482
.count = 2,
483
},
484
{
485
.name = "Capture Source",
486
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
487
.info = maya_rec_src_info,
488
.get = maya_rec_src_get,
489
.put = maya_rec_src_put,
490
},
491
{
492
.name = "Mic Phantom Power Switch",
493
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
494
.info = maya_gpio_sw_info,
495
.get = maya_gpio_sw_get,
496
.put = maya_gpio_sw_put,
497
.private_value = COMPOSE_GPIO_VAL(GPIO_PHANTOM_OFF, 1),
498
},
499
{
500
.name = "SPDIF Capture Switch",
501
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
502
.info = maya_gpio_sw_info,
503
.get = maya_gpio_sw_get,
504
.put = maya_gpio_sw_put,
505
.private_value = COMPOSE_GPIO_VAL(GPIO_SPDIF_IN_INV, 1),
506
},
507
{
508
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
509
.name = "H/W Playback Route",
510
.info = maya_pb_route_info,
511
.get = maya_pb_route_get,
512
.put = maya_pb_route_put,
513
.count = 4, /* FIXME: do controls 5-9 have any meaning? */
514
},
515
};
516
517
static int maya44_add_controls(struct snd_ice1712 *ice)
518
{
519
int err, i;
520
521
for (i = 0; i < ARRAY_SIZE(maya_controls); i++) {
522
err = snd_ctl_add(ice->card, snd_ctl_new1(&maya_controls[i],
523
ice->spec));
524
if (err < 0)
525
return err;
526
}
527
return 0;
528
}
529
530
531
/*
532
* initialize a wm8776 chip
533
*/
534
static void wm8776_init(struct snd_ice1712 *ice,
535
struct snd_wm8776 *wm, unsigned int addr)
536
{
537
static const unsigned short inits_wm8776[] = {
538
0x02, 0x100, /* R2: headphone L+R muted + update */
539
0x05, 0x100, /* R5: DAC output L+R muted + update */
540
0x06, 0x000, /* R6: DAC output phase normal */
541
0x07, 0x091, /* R7: DAC enable zero cross detection,
542
normal output */
543
0x08, 0x000, /* R8: DAC soft mute off */
544
0x09, 0x000, /* R9: no deemph, DAC zero detect disabled */
545
0x0a, 0x022, /* R10: DAC I2C mode, std polarities, 24bit */
546
0x0b, 0x022, /* R11: ADC I2C mode, std polarities, 24bit,
547
highpass filter enabled */
548
0x0c, 0x042, /* R12: ADC+DAC slave, ADC+DAC 44,1kHz */
549
0x0d, 0x000, /* R13: all power up */
550
0x0e, 0x100, /* R14: ADC left muted,
551
enable zero cross detection */
552
0x0f, 0x100, /* R15: ADC right muted,
553
enable zero cross detection */
554
/* R16: ALC...*/
555
0x11, 0x000, /* R17: disable ALC */
556
/* R18: ALC...*/
557
/* R19: noise gate...*/
558
0x15, 0x000, /* R21: ADC input mux init, mute all inputs */
559
0x16, 0x001, /* R22: output mux, select DAC */
560
0xff, 0xff
561
};
562
563
const unsigned short *ptr;
564
unsigned char reg;
565
unsigned short data;
566
567
wm->addr = addr;
568
/* enable DAC output; mute bypass, aux & all inputs */
569
wm->switch_bits = (1 << WM_SW_DAC);
570
571
ptr = inits_wm8776;
572
while (*ptr != 0xff) {
573
reg = *ptr++;
574
data = *ptr++;
575
wm8776_write(ice, wm, reg, data);
576
}
577
}
578
579
580
/*
581
* change the rate on the WM8776 codecs.
582
* this assumes that the VT17xx's rate is changed by the calling function.
583
* NOTE: even though the WM8776's are running in slave mode and rate
584
* selection is automatic, we need to call snd_wm8776_set_rate() here
585
* to make sure some flags are set correctly.
586
*/
587
static void set_rate(struct snd_ice1712 *ice, unsigned int rate)
588
{
589
struct snd_maya44 *chip = ice->spec;
590
unsigned int ratio, adc_ratio, val;
591
int i;
592
593
switch (rate) {
594
case 192000:
595
ratio = WM8776_CLOCK_RATIO_128FS;
596
break;
597
case 176400:
598
ratio = WM8776_CLOCK_RATIO_128FS;
599
break;
600
case 96000:
601
ratio = WM8776_CLOCK_RATIO_256FS;
602
break;
603
case 88200:
604
ratio = WM8776_CLOCK_RATIO_384FS;
605
break;
606
case 48000:
607
ratio = WM8776_CLOCK_RATIO_512FS;
608
break;
609
case 44100:
610
ratio = WM8776_CLOCK_RATIO_512FS;
611
break;
612
case 32000:
613
ratio = WM8776_CLOCK_RATIO_768FS;
614
break;
615
case 0:
616
/* no hint - S/PDIF input is master, simply return */
617
return;
618
default:
619
snd_BUG();
620
return;
621
}
622
623
/*
624
* this currently sets the same rate for ADC and DAC, but limits
625
* ADC rate to 256X (96kHz). For 256X mode (96kHz), this sets ADC
626
* oversampling to 64x, as recommended by WM8776 datasheet.
627
* Setting the rate is not really necessary in slave mode.
628
*/
629
adc_ratio = ratio;
630
if (adc_ratio < WM8776_CLOCK_RATIO_256FS)
631
adc_ratio = WM8776_CLOCK_RATIO_256FS;
632
633
val = adc_ratio;
634
if (adc_ratio == WM8776_CLOCK_RATIO_256FS)
635
val |= 8;
636
val |= ratio << 4;
637
638
mutex_lock(&chip->mutex);
639
for (i = 0; i < 2; i++)
640
wm8776_write_bits(ice, &chip->wm[i],
641
WM8776_REG_MASTER_MODE_CONTROL,
642
0x180, val);
643
mutex_unlock(&chip->mutex);
644
}
645
646
/*
647
* supported sample rates (to override the default one)
648
*/
649
650
static const unsigned int rates[] = {
651
32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000
652
};
653
654
/* playback rates: 32..192 kHz */
655
static const struct snd_pcm_hw_constraint_list dac_rates = {
656
.count = ARRAY_SIZE(rates),
657
.list = rates,
658
.mask = 0
659
};
660
661
662
/*
663
* chip addresses on I2C bus
664
*/
665
static const unsigned char wm8776_addr[2] = {
666
0x34, 0x36, /* codec 0 & 1 */
667
};
668
669
/*
670
* initialize the chip
671
*/
672
static int maya44_init(struct snd_ice1712 *ice)
673
{
674
int i;
675
struct snd_maya44 *chip;
676
677
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
678
if (!chip)
679
return -ENOMEM;
680
mutex_init(&chip->mutex);
681
chip->ice = ice;
682
ice->spec = chip;
683
684
/* initialise codecs */
685
ice->num_total_dacs = 4;
686
ice->num_total_adcs = 4;
687
ice->akm_codecs = 0;
688
689
for (i = 0; i < 2; i++) {
690
wm8776_init(ice, &chip->wm[i], wm8776_addr[i]);
691
wm8776_select_input(chip, i, MAYA_LINE_IN);
692
}
693
694
/* set card specific rates */
695
ice->hw_rates = &dac_rates;
696
697
/* register change rate notifier */
698
ice->gpio.set_pro_rate = set_rate;
699
700
/* RDMA1 (2nd input channel) is used for ADC by default */
701
ice->force_rdma1 = 1;
702
703
/* have an own routing control */
704
ice->own_routing = 1;
705
706
return 0;
707
}
708
709
710
/*
711
* Maya44 boards don't provide the EEPROM data except for the vendor IDs.
712
* hence the driver needs to sets up it properly.
713
*/
714
715
static const unsigned char maya44_eeprom[] = {
716
[ICE_EEP2_SYSCONF] = 0x45,
717
/* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
718
[ICE_EEP2_ACLINK] = 0x80,
719
/* I2S */
720
[ICE_EEP2_I2S] = 0xf8,
721
/* vol, 96k, 24bit, 192k */
722
[ICE_EEP2_SPDIF] = 0xc3,
723
/* enable spdif out, spdif out supp, spdif-in, ext spdif out */
724
[ICE_EEP2_GPIO_DIR] = 0xff,
725
[ICE_EEP2_GPIO_DIR1] = 0xff,
726
[ICE_EEP2_GPIO_DIR2] = 0xff,
727
[ICE_EEP2_GPIO_MASK] = 0/*0x9f*/,
728
[ICE_EEP2_GPIO_MASK1] = 0/*0xff*/,
729
[ICE_EEP2_GPIO_MASK2] = 0/*0x7f*/,
730
[ICE_EEP2_GPIO_STATE] = (1 << GPIO_PHANTOM_OFF) |
731
(1 << GPIO_SPDIF_IN_INV),
732
[ICE_EEP2_GPIO_STATE1] = 0x00,
733
[ICE_EEP2_GPIO_STATE2] = 0x00,
734
};
735
736
/* entry point */
737
struct snd_ice1712_card_info snd_vt1724_maya44_cards[] = {
738
{
739
.subvendor = VT1724_SUBDEVICE_MAYA44,
740
.name = "ESI Maya44",
741
.model = "maya44",
742
.chip_init = maya44_init,
743
.build_controls = maya44_add_controls,
744
.eeprom_size = sizeof(maya44_eeprom),
745
.eeprom_data = maya44_eeprom,
746
},
747
{ } /* terminator */
748
};
749
750