Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/sound/pci/ice1712/se.c
10817 views
1
/*
2
* ALSA driver for ICEnsemble VT1724 (Envy24HT)
3
*
4
* Lowlevel functions for ONKYO WAVIO SE-90PCI and SE-200PCI
5
*
6
* Copyright (c) 2007 Shin-ya Okada sh_okada(at)d4.dion.ne.jp
7
* (at) -> @
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22
*
23
*/
24
25
#include <asm/io.h>
26
#include <linux/delay.h>
27
#include <linux/interrupt.h>
28
#include <linux/init.h>
29
#include <linux/slab.h>
30
#include <sound/core.h>
31
#include <sound/tlv.h>
32
33
#include "ice1712.h"
34
#include "envy24ht.h"
35
#include "se.h"
36
37
struct se_spec {
38
struct {
39
unsigned char ch1, ch2;
40
} vol[8];
41
};
42
43
/****************************************************************************/
44
/* ONKYO WAVIO SE-200PCI */
45
/****************************************************************************/
46
/*
47
* system configuration ICE_EEP2_SYSCONF=0x4b
48
* XIN1 49.152MHz
49
* not have UART
50
* one stereo ADC and a S/PDIF receiver connected
51
* four stereo DACs connected
52
*
53
* AC-Link configuration ICE_EEP2_ACLINK=0x80
54
* use I2C, not use AC97
55
*
56
* I2S converters feature ICE_EEP2_I2S=0x78
57
* I2S codec has no volume/mute control feature
58
* I2S codec supports 96KHz and 192KHz
59
* I2S codec 24bits
60
*
61
* S/PDIF configuration ICE_EEP2_SPDIF=0xc3
62
* Enable integrated S/PDIF transmitter
63
* internal S/PDIF out implemented
64
* S/PDIF is stereo
65
* External S/PDIF out implemented
66
*
67
*
68
* ** connected chips **
69
*
70
* WM8740
71
* A 2ch-DAC of main outputs.
72
* It setuped as I2S mode by wire, so no way to setup from software.
73
* The sample-rate are automatically changed.
74
* ML/I2S (28pin) --------+
75
* MC/DM1 (27pin) -- 5V |
76
* MD/DM0 (26pin) -- GND |
77
* MUTEB (25pin) -- NC |
78
* MODE (24pin) -- GND |
79
* CSBIW (23pin) --------+
80
* |
81
* RSTB (22pin) --R(1K)-+
82
* Probably it reduce the noise from the control line.
83
*
84
* WM8766
85
* A 6ch-DAC for surrounds.
86
* It's control wire was connected to GPIOxx (3-wire serial interface)
87
* ML/I2S (11pin) -- GPIO18
88
* MC/IWL (12pin) -- GPIO17
89
* MD/DM (13pin) -- GPIO16
90
* MUTE (14pin) -- GPIO01
91
*
92
* WM8776
93
* A 2ch-ADC(with 10ch-selector) plus 2ch-DAC.
94
* It's control wire was connected to SDA/SCLK (2-wire serial interface)
95
* MODE (16pin) -- R(1K) -- GND
96
* CE (17pin) -- R(1K) -- GND 2-wire mode (address=0x34)
97
* DI (18pin) -- SDA
98
* CL (19pin) -- SCLK
99
*
100
*
101
* ** output pins and device names **
102
*
103
* 7.1ch name -- output connector color -- device (-D option)
104
*
105
* FRONT 2ch -- green -- plughw:0,0
106
* CENTER(Lch) SUBWOOFER(Rch) -- black -- plughw:0,2,0
107
* SURROUND 2ch -- orange -- plughw:0,2,1
108
* SURROUND BACK 2ch -- white -- plughw:0,2,2
109
*
110
*/
111
112
113
/****************************************************************************/
114
/* WM8740 interface */
115
/****************************************************************************/
116
117
static void __devinit se200pci_WM8740_init(struct snd_ice1712 *ice)
118
{
119
/* nothing to do */
120
}
121
122
123
static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice,
124
unsigned int rate)
125
{
126
/* nothing to do */
127
}
128
129
130
/****************************************************************************/
131
/* WM8766 interface */
132
/****************************************************************************/
133
134
static void se200pci_WM8766_write(struct snd_ice1712 *ice,
135
unsigned int addr, unsigned int data)
136
{
137
unsigned int st;
138
unsigned int bits;
139
int i;
140
const unsigned int DATA = 0x010000;
141
const unsigned int CLOCK = 0x020000;
142
const unsigned int LOAD = 0x040000;
143
const unsigned int ALL_MASK = (DATA | CLOCK | LOAD);
144
145
snd_ice1712_save_gpio_status(ice);
146
147
st = ((addr & 0x7f) << 9) | (data & 0x1ff);
148
snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | ALL_MASK);
149
snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~ALL_MASK);
150
bits = snd_ice1712_gpio_read(ice) & ~ALL_MASK;
151
152
snd_ice1712_gpio_write(ice, bits);
153
for (i = 0; i < 16; i++) {
154
udelay(1);
155
bits &= ~CLOCK;
156
st = (st << 1);
157
if (st & 0x10000)
158
bits |= DATA;
159
else
160
bits &= ~DATA;
161
162
snd_ice1712_gpio_write(ice, bits);
163
164
udelay(1);
165
bits |= CLOCK;
166
snd_ice1712_gpio_write(ice, bits);
167
}
168
169
udelay(1);
170
bits |= LOAD;
171
snd_ice1712_gpio_write(ice, bits);
172
173
udelay(1);
174
bits |= (DATA | CLOCK);
175
snd_ice1712_gpio_write(ice, bits);
176
177
snd_ice1712_restore_gpio_status(ice);
178
}
179
180
static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch,
181
unsigned int vol1, unsigned int vol2)
182
{
183
switch (ch) {
184
case 0:
185
se200pci_WM8766_write(ice, 0x000, vol1);
186
se200pci_WM8766_write(ice, 0x001, vol2 | 0x100);
187
break;
188
case 1:
189
se200pci_WM8766_write(ice, 0x004, vol1);
190
se200pci_WM8766_write(ice, 0x005, vol2 | 0x100);
191
break;
192
case 2:
193
se200pci_WM8766_write(ice, 0x006, vol1);
194
se200pci_WM8766_write(ice, 0x007, vol2 | 0x100);
195
break;
196
}
197
}
198
199
static void __devinit se200pci_WM8766_init(struct snd_ice1712 *ice)
200
{
201
se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */
202
udelay(10);
203
204
se200pci_WM8766_set_volume(ice, 0, 0, 0); /* volume L=0 R=0 */
205
se200pci_WM8766_set_volume(ice, 1, 0, 0); /* volume L=0 R=0 */
206
se200pci_WM8766_set_volume(ice, 2, 0, 0); /* volume L=0 R=0 */
207
208
se200pci_WM8766_write(ice, 0x03, 0x022); /* serial mode I2S-24bits */
209
se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
210
se200pci_WM8766_write(ice, 0x12, 0x000); /* MDP=0 */
211
se200pci_WM8766_write(ice, 0x15, 0x000); /* MDP=0 */
212
se200pci_WM8766_write(ice, 0x09, 0x000); /* demp=off mute=off */
213
214
se200pci_WM8766_write(ice, 0x02, 0x124); /* ch-assign L=L R=R RESET */
215
se200pci_WM8766_write(ice, 0x02, 0x120); /* ch-assign L=L R=R */
216
}
217
218
static void se200pci_WM8766_set_pro_rate(struct snd_ice1712 *ice,
219
unsigned int rate)
220
{
221
if (rate > 96000)
222
se200pci_WM8766_write(ice, 0x0a, 0x000); /* MCLK=128fs */
223
else
224
se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
225
}
226
227
228
/****************************************************************************/
229
/* WM8776 interface */
230
/****************************************************************************/
231
232
static void se200pci_WM8776_write(struct snd_ice1712 *ice,
233
unsigned int addr, unsigned int data)
234
{
235
unsigned int val;
236
237
val = (addr << 9) | data;
238
snd_vt1724_write_i2c(ice, 0x34, val >> 8, val & 0xff);
239
}
240
241
242
static void se200pci_WM8776_set_output_volume(struct snd_ice1712 *ice,
243
unsigned int vol1, unsigned int vol2)
244
{
245
se200pci_WM8776_write(ice, 0x03, vol1);
246
se200pci_WM8776_write(ice, 0x04, vol2 | 0x100);
247
}
248
249
static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice,
250
unsigned int vol1, unsigned int vol2)
251
{
252
se200pci_WM8776_write(ice, 0x0e, vol1);
253
se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100);
254
}
255
256
static const char *se200pci_sel[] = {
257
"LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
258
};
259
260
static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice,
261
unsigned int sel)
262
{
263
static unsigned char vals[] = {
264
/* LINE, CD, MIC, ALL, GND */
265
0x10, 0x04, 0x08, 0x1c, 0x03
266
};
267
if (sel > 4)
268
sel = 4;
269
se200pci_WM8776_write(ice, 0x15, vals[sel]);
270
}
271
272
static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
273
{
274
/* AFL -- After Fader Listening */
275
if (afl)
276
se200pci_WM8776_write(ice, 0x16, 0x005);
277
else
278
se200pci_WM8776_write(ice, 0x16, 0x001);
279
}
280
281
static const char *se200pci_agc[] = {
282
"Off", "LimiterMode", "ALCMode", NULL
283
};
284
285
static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
286
{
287
/* AGC -- Auto Gain Control of the input */
288
switch (agc) {
289
case 0:
290
se200pci_WM8776_write(ice, 0x11, 0x000); /* Off */
291
break;
292
case 1:
293
se200pci_WM8776_write(ice, 0x10, 0x07b);
294
se200pci_WM8776_write(ice, 0x11, 0x100); /* LimiterMode */
295
break;
296
case 2:
297
se200pci_WM8776_write(ice, 0x10, 0x1fb);
298
se200pci_WM8776_write(ice, 0x11, 0x100); /* ALCMode */
299
break;
300
}
301
}
302
303
static void __devinit se200pci_WM8776_init(struct snd_ice1712 *ice)
304
{
305
int i;
306
static unsigned short __devinitdata default_values[] = {
307
0x100, 0x100, 0x100,
308
0x100, 0x100, 0x100,
309
0x000, 0x090, 0x000, 0x000,
310
0x022, 0x022, 0x022,
311
0x008, 0x0cf, 0x0cf, 0x07b, 0x000,
312
0x032, 0x000, 0x0a6, 0x001, 0x001
313
};
314
315
se200pci_WM8776_write(ice, 0x17, 0x000); /* reset all */
316
/* ADC and DAC interface is I2S 24bits mode */
317
/* The sample-rate are automatically changed */
318
udelay(10);
319
/* BUT my board can not do reset all, so I load all by manually. */
320
for (i = 0; i < ARRAY_SIZE(default_values); i++)
321
se200pci_WM8776_write(ice, i, default_values[i]);
322
323
se200pci_WM8776_set_input_selector(ice, 0);
324
se200pci_WM8776_set_afl(ice, 0);
325
se200pci_WM8776_set_agc(ice, 0);
326
se200pci_WM8776_set_input_volume(ice, 0, 0);
327
se200pci_WM8776_set_output_volume(ice, 0, 0);
328
329
/* head phone mute and power down */
330
se200pci_WM8776_write(ice, 0x00, 0);
331
se200pci_WM8776_write(ice, 0x01, 0);
332
se200pci_WM8776_write(ice, 0x02, 0x100);
333
se200pci_WM8776_write(ice, 0x0d, 0x080);
334
}
335
336
static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice,
337
unsigned int rate)
338
{
339
/* nothing to do */
340
}
341
342
343
/****************************************************************************/
344
/* runtime interface */
345
/****************************************************************************/
346
347
static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
348
{
349
se200pci_WM8740_set_pro_rate(ice, rate);
350
se200pci_WM8766_set_pro_rate(ice, rate);
351
se200pci_WM8776_set_pro_rate(ice, rate);
352
}
353
354
struct se200pci_control {
355
char *name;
356
enum {
357
WM8766,
358
WM8776in,
359
WM8776out,
360
WM8776sel,
361
WM8776agc,
362
WM8776afl
363
} target;
364
enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type;
365
int ch;
366
const char **member;
367
const char *comment;
368
};
369
370
static const struct se200pci_control se200pci_cont[] = {
371
{
372
.name = "Front Playback Volume",
373
.target = WM8776out,
374
.type = VOLUME1,
375
.comment = "Front(green)"
376
},
377
{
378
.name = "Side Playback Volume",
379
.target = WM8766,
380
.type = VOLUME1,
381
.ch = 1,
382
.comment = "Surround(orange)"
383
},
384
{
385
.name = "Surround Playback Volume",
386
.target = WM8766,
387
.type = VOLUME1,
388
.ch = 2,
389
.comment = "SurroundBack(white)"
390
},
391
{
392
.name = "CLFE Playback Volume",
393
.target = WM8766,
394
.type = VOLUME1,
395
.ch = 0,
396
.comment = "Center(Lch)&SubWoofer(Rch)(black)"
397
},
398
{
399
.name = "Capture Volume",
400
.target = WM8776in,
401
.type = VOLUME2
402
},
403
{
404
.name = "Capture Select",
405
.target = WM8776sel,
406
.type = ENUM,
407
.member = se200pci_sel
408
},
409
{
410
.name = "AGC Capture Mode",
411
.target = WM8776agc,
412
.type = ENUM,
413
.member = se200pci_agc
414
},
415
{
416
.name = "AFL Bypass Playback Switch",
417
.target = WM8776afl,
418
.type = BOOLEAN
419
}
420
};
421
422
static int se200pci_get_enum_count(int n)
423
{
424
const char **member;
425
int c;
426
427
member = se200pci_cont[n].member;
428
if (!member)
429
return 0;
430
for (c = 0; member[c]; c++)
431
;
432
return c;
433
}
434
435
static int se200pci_cont_volume_info(struct snd_kcontrol *kc,
436
struct snd_ctl_elem_info *uinfo)
437
{
438
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
439
uinfo->count = 2;
440
uinfo->value.integer.min = 0; /* mute */
441
uinfo->value.integer.max = 0xff; /* 0dB */
442
return 0;
443
}
444
445
#define se200pci_cont_boolean_info snd_ctl_boolean_mono_info
446
447
static int se200pci_cont_enum_info(struct snd_kcontrol *kc,
448
struct snd_ctl_elem_info *uinfo)
449
{
450
int n, c;
451
452
n = kc->private_value;
453
c = se200pci_get_enum_count(n);
454
if (!c)
455
return -EINVAL;
456
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
457
uinfo->count = 1;
458
uinfo->value.enumerated.items = c;
459
if (uinfo->value.enumerated.item >= c)
460
uinfo->value.enumerated.item = c - 1;
461
strcpy(uinfo->value.enumerated.name,
462
se200pci_cont[n].member[uinfo->value.enumerated.item]);
463
return 0;
464
}
465
466
static int se200pci_cont_volume_get(struct snd_kcontrol *kc,
467
struct snd_ctl_elem_value *uc)
468
{
469
struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
470
struct se_spec *spec = ice->spec;
471
int n = kc->private_value;
472
uc->value.integer.value[0] = spec->vol[n].ch1;
473
uc->value.integer.value[1] = spec->vol[n].ch2;
474
return 0;
475
}
476
477
static int se200pci_cont_boolean_get(struct snd_kcontrol *kc,
478
struct snd_ctl_elem_value *uc)
479
{
480
struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
481
struct se_spec *spec = ice->spec;
482
int n = kc->private_value;
483
uc->value.integer.value[0] = spec->vol[n].ch1;
484
return 0;
485
}
486
487
static int se200pci_cont_enum_get(struct snd_kcontrol *kc,
488
struct snd_ctl_elem_value *uc)
489
{
490
struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
491
struct se_spec *spec = ice->spec;
492
int n = kc->private_value;
493
uc->value.enumerated.item[0] = spec->vol[n].ch1;
494
return 0;
495
}
496
497
static void se200pci_cont_update(struct snd_ice1712 *ice, int n)
498
{
499
struct se_spec *spec = ice->spec;
500
switch (se200pci_cont[n].target) {
501
case WM8766:
502
se200pci_WM8766_set_volume(ice,
503
se200pci_cont[n].ch,
504
spec->vol[n].ch1,
505
spec->vol[n].ch2);
506
break;
507
508
case WM8776in:
509
se200pci_WM8776_set_input_volume(ice,
510
spec->vol[n].ch1,
511
spec->vol[n].ch2);
512
break;
513
514
case WM8776out:
515
se200pci_WM8776_set_output_volume(ice,
516
spec->vol[n].ch1,
517
spec->vol[n].ch2);
518
break;
519
520
case WM8776sel:
521
se200pci_WM8776_set_input_selector(ice,
522
spec->vol[n].ch1);
523
break;
524
525
case WM8776agc:
526
se200pci_WM8776_set_agc(ice, spec->vol[n].ch1);
527
break;
528
529
case WM8776afl:
530
se200pci_WM8776_set_afl(ice, spec->vol[n].ch1);
531
break;
532
533
default:
534
break;
535
}
536
}
537
538
static int se200pci_cont_volume_put(struct snd_kcontrol *kc,
539
struct snd_ctl_elem_value *uc)
540
{
541
struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
542
struct se_spec *spec = ice->spec;
543
int n = kc->private_value;
544
unsigned int vol1, vol2;
545
int changed;
546
547
changed = 0;
548
vol1 = uc->value.integer.value[0] & 0xff;
549
vol2 = uc->value.integer.value[1] & 0xff;
550
if (spec->vol[n].ch1 != vol1) {
551
spec->vol[n].ch1 = vol1;
552
changed = 1;
553
}
554
if (spec->vol[n].ch2 != vol2) {
555
spec->vol[n].ch2 = vol2;
556
changed = 1;
557
}
558
if (changed)
559
se200pci_cont_update(ice, n);
560
561
return changed;
562
}
563
564
static int se200pci_cont_boolean_put(struct snd_kcontrol *kc,
565
struct snd_ctl_elem_value *uc)
566
{
567
struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
568
struct se_spec *spec = ice->spec;
569
int n = kc->private_value;
570
unsigned int vol1;
571
572
vol1 = !!uc->value.integer.value[0];
573
if (spec->vol[n].ch1 != vol1) {
574
spec->vol[n].ch1 = vol1;
575
se200pci_cont_update(ice, n);
576
return 1;
577
}
578
return 0;
579
}
580
581
static int se200pci_cont_enum_put(struct snd_kcontrol *kc,
582
struct snd_ctl_elem_value *uc)
583
{
584
struct snd_ice1712 *ice = snd_kcontrol_chip(kc);
585
struct se_spec *spec = ice->spec;
586
int n = kc->private_value;
587
unsigned int vol1;
588
589
vol1 = uc->value.enumerated.item[0];
590
if (vol1 >= se200pci_get_enum_count(n))
591
return -EINVAL;
592
if (spec->vol[n].ch1 != vol1) {
593
spec->vol[n].ch1 = vol1;
594
se200pci_cont_update(ice, n);
595
return 1;
596
}
597
return 0;
598
}
599
600
static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
601
static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
602
603
static int __devinit se200pci_add_controls(struct snd_ice1712 *ice)
604
{
605
int i;
606
struct snd_kcontrol_new cont;
607
int err;
608
609
memset(&cont, 0, sizeof(cont));
610
cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
611
for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) {
612
cont.private_value = i;
613
cont.name = se200pci_cont[i].name;
614
cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
615
cont.tlv.p = NULL;
616
switch (se200pci_cont[i].type) {
617
case VOLUME1:
618
case VOLUME2:
619
cont.info = se200pci_cont_volume_info;
620
cont.get = se200pci_cont_volume_get;
621
cont.put = se200pci_cont_volume_put;
622
cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
623
if (se200pci_cont[i].type == VOLUME1)
624
cont.tlv.p = db_scale_gain1;
625
else
626
cont.tlv.p = db_scale_gain2;
627
break;
628
case BOOLEAN:
629
cont.info = se200pci_cont_boolean_info;
630
cont.get = se200pci_cont_boolean_get;
631
cont.put = se200pci_cont_boolean_put;
632
break;
633
case ENUM:
634
cont.info = se200pci_cont_enum_info;
635
cont.get = se200pci_cont_enum_get;
636
cont.put = se200pci_cont_enum_put;
637
break;
638
default:
639
snd_BUG();
640
return -EINVAL;
641
}
642
err = snd_ctl_add(ice->card, snd_ctl_new1(&cont, ice));
643
if (err < 0)
644
return err;
645
}
646
647
return 0;
648
}
649
650
651
/****************************************************************************/
652
/* ONKYO WAVIO SE-90PCI */
653
/****************************************************************************/
654
/*
655
* system configuration ICE_EEP2_SYSCONF=0x4b
656
* AC-Link configuration ICE_EEP2_ACLINK=0x80
657
* I2S converters feature ICE_EEP2_I2S=0x78
658
* S/PDIF configuration ICE_EEP2_SPDIF=0xc3
659
*
660
* ** connected chip **
661
*
662
* WM8716
663
* A 2ch-DAC of main outputs.
664
* It setuped as I2S mode by wire, so no way to setup from software.
665
* ML/I2S (28pin) -- +5V
666
* MC/DM1 (27pin) -- GND
667
* MC/DM0 (26pin) -- GND
668
* MUTEB (25pin) -- open (internal pull-up)
669
* MODE (24pin) -- GND
670
* CSBIWO (23pin) -- +5V
671
*
672
*/
673
674
/* Nothing to do for this chip. */
675
676
677
/****************************************************************************/
678
/* probe/initialize/setup */
679
/****************************************************************************/
680
681
static int __devinit se_init(struct snd_ice1712 *ice)
682
{
683
struct se_spec *spec;
684
685
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
686
if (!spec)
687
return -ENOMEM;
688
ice->spec = spec;
689
690
if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE90PCI) {
691
ice->num_total_dacs = 2;
692
ice->num_total_adcs = 0;
693
ice->vt1720 = 1;
694
return 0;
695
696
} else if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) {
697
ice->num_total_dacs = 8;
698
ice->num_total_adcs = 2;
699
se200pci_WM8740_init(ice);
700
se200pci_WM8766_init(ice);
701
se200pci_WM8776_init(ice);
702
ice->gpio.set_pro_rate = se200pci_set_pro_rate;
703
return 0;
704
}
705
706
return -ENOENT;
707
}
708
709
static int __devinit se_add_controls(struct snd_ice1712 *ice)
710
{
711
int err;
712
713
err = 0;
714
/* nothing to do for VT1724_SUBDEVICE_SE90PCI */
715
if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI)
716
err = se200pci_add_controls(ice);
717
718
return err;
719
}
720
721
722
/****************************************************************************/
723
/* entry point */
724
/****************************************************************************/
725
726
static unsigned char se200pci_eeprom[] __devinitdata = {
727
[ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
728
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
729
[ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
730
[ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
731
732
[ICE_EEP2_GPIO_DIR] = 0x02, /* WM8766 mute 1=output */
733
[ICE_EEP2_GPIO_DIR1] = 0x00, /* not used */
734
[ICE_EEP2_GPIO_DIR2] = 0x07, /* WM8766 ML/MC/MD 1=output */
735
736
[ICE_EEP2_GPIO_MASK] = 0x00, /* 0=writable */
737
[ICE_EEP2_GPIO_MASK1] = 0x00, /* 0=writable */
738
[ICE_EEP2_GPIO_MASK2] = 0x00, /* 0=writable */
739
740
[ICE_EEP2_GPIO_STATE] = 0x00, /* WM8766 mute=0 */
741
[ICE_EEP2_GPIO_STATE1] = 0x00, /* not used */
742
[ICE_EEP2_GPIO_STATE2] = 0x07, /* WM8766 ML/MC/MD */
743
};
744
745
static unsigned char se90pci_eeprom[] __devinitdata = {
746
[ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
747
[ICE_EEP2_ACLINK] = 0x80, /* I2S */
748
[ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
749
[ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
750
751
/* ALL GPIO bits are in input mode */
752
};
753
754
struct snd_ice1712_card_info snd_vt1724_se_cards[] __devinitdata = {
755
{
756
.subvendor = VT1724_SUBDEVICE_SE200PCI,
757
.name = "ONKYO SE200PCI",
758
.model = "se200pci",
759
.chip_init = se_init,
760
.build_controls = se_add_controls,
761
.eeprom_size = sizeof(se200pci_eeprom),
762
.eeprom_data = se200pci_eeprom,
763
},
764
{
765
.subvendor = VT1724_SUBDEVICE_SE90PCI,
766
.name = "ONKYO SE90PCI",
767
.model = "se90pci",
768
.chip_init = se_init,
769
.build_controls = se_add_controls,
770
.eeprom_size = sizeof(se90pci_eeprom),
771
.eeprom_data = se90pci_eeprom,
772
},
773
{} /*terminator*/
774
};
775
776