aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/ice1712
diff options
context:
space:
mode:
authorShin-ya Okada <sh_okada at d4.dion.ne.jp>2007-10-23 09:08:18 -0400
committerJaroslav Kysela <perex@perex.cz>2008-01-31 11:29:09 -0500
commitf31639b8c5916f58441b529c9c364715921b29af (patch)
tree799ccf968dcc87215674fbb8cd686ea1ef881301 /sound/pci/ice1712
parent18fe4ac25811ff4006844b6e575acdc9103cbaba (diff)
[ALSA] ice1724 - Add support of Onkyo SE-90PCI and SE-200PCI
Added the support for Onkyo SE-90PCI and SE-200PCI boards. Signed-off-by: Shin-ya Okada <sh_okada at d4.dion.ne.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
Diffstat (limited to 'sound/pci/ice1712')
-rw-r--r--sound/pci/ice1712/Makefile2
-rw-r--r--sound/pci/ice1712/ice1712.h6
-rw-r--r--sound/pci/ice1712/ice1724.c3
-rw-r--r--sound/pci/ice1712/se.c700
-rw-r--r--sound/pci/ice1712/se.h15
5 files changed, 725 insertions, 1 deletions
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
index 65ce66adba5a..ee86a1de72f8 100644
--- a/sound/pci/ice1712/Makefile
+++ b/sound/pci/ice1712/Makefile
@@ -5,7 +5,7 @@
5 5
6snd-ice17xx-ak4xxx-objs := ak4xxx.o 6snd-ice17xx-ak4xxx-objs := ak4xxx.o
7snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o 7snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
8snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o wtm.o 8snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o wtm.o se.o
9 9
10# Toplevel Module Dependency 10# Toplevel Module Dependency
11obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o 11obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index 58640afa5404..3c3cac3dc08b 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -400,6 +400,12 @@ struct snd_ice1712 {
400 struct { 400 struct {
401 struct ak4114 *ak4114; 401 struct ak4114 *ak4114;
402 } prodigy192; 402 } prodigy192;
403 struct {
404 struct {
405 unsigned char ch1, ch2;
406 } vol[8];
407 } se;
408
403 } spec; 409 } spec;
404 410
405}; 411};
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 0b0bbb0d96b9..357bdbe21c8f 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -51,6 +51,7 @@
51#include "juli.h" 51#include "juli.h"
52#include "phase.h" 52#include "phase.h"
53#include "wtm.h" 53#include "wtm.h"
54#include "se.h"
54 55
55MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 56MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
56MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); 57MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
@@ -65,6 +66,7 @@ MODULE_SUPPORTED_DEVICE("{"
65 JULI_DEVICE_DESC 66 JULI_DEVICE_DESC
66 PHASE_DEVICE_DESC 67 PHASE_DEVICE_DESC
67 WTM_DEVICE_DESC 68 WTM_DEVICE_DESC
69 SE_DEVICE_DESC
68 "{VIA,VT1720}," 70 "{VIA,VT1720},"
69 "{VIA,VT1724}," 71 "{VIA,VT1724},"
70 "{ICEnsemble,Generic ICE1724}," 72 "{ICEnsemble,Generic ICE1724},"
@@ -1933,6 +1935,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
1933 snd_vt1724_juli_cards, 1935 snd_vt1724_juli_cards,
1934 snd_vt1724_phase_cards, 1936 snd_vt1724_phase_cards,
1935 snd_vt1724_wtm_cards, 1937 snd_vt1724_wtm_cards,
1938 snd_vt1724_se_cards,
1936 NULL, 1939 NULL,
1937}; 1940};
1938 1941
diff --git a/sound/pci/ice1712/se.c b/sound/pci/ice1712/se.c
new file mode 100644
index 000000000000..ebfe2454a08b
--- /dev/null
+++ b/sound/pci/ice1712/se.c
@@ -0,0 +1,700 @@
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 <sound/driver.h>
26#include <asm/io.h>
27#include <linux/delay.h>
28#include <linux/interrupt.h>
29#include <linux/init.h>
30#include <linux/slab.h>
31#include <sound/core.h>
32#include <sound/tlv.h>
33
34#include "ice1712.h"
35#include "envy24ht.h"
36#include "se.h"
37
38
39/****************************************************************************/
40/* ONKYO WAVIO SE-200PCI */
41/****************************************************************************/
42/*
43 * system configuration ICE_EEP2_SYSCONF=0x4b
44 * XIN1 49.152MHz
45 * not have UART
46 * one stereo ADC and a S/PDIF receiver connected
47 * four stereo DACs connected
48 *
49 * AC-Link configuration ICE_EEP2_ACLINK=0x80
50 * use I2C, not use AC97
51 *
52 * I2S converters feature ICE_EEP2_I2S=0x78
53 * I2S codec has no volume/mute control feature
54 * I2S codec supports 96KHz and 192KHz
55 * I2S codec 24bits
56 *
57 * S/PDIF configuration ICE_EEP2_SPDIF=0xc3
58 * Enable integrated S/PDIF transmitter
59 * internal S/PDIF out implemented
60 * S/PDIF is stereo
61 * External S/PDIF out implemented
62 *
63 *
64 * ** connected chips **
65 *
66 * WM8740
67 * A 2ch-DAC of main outputs.
68 * It setuped as I2S mode by wire, so no way to setup from software.
69 * The sample-rate are automatically changed.
70 * ML/I2S (28pin) --------+
71 * MC/DM1 (27pin) -- 5V |
72 * MD/DM0 (26pin) -- GND |
73 * MUTEB (25pin) -- NC |
74 * MODE (24pin) -- GND |
75 * CSBIW (23pin) --------+
76 * |
77 * RSTB (22pin) --R(1K)-+
78 * Probably it reduce the noise from the control line.
79 *
80 * WM8766
81 * A 6ch-DAC for surrounds.
82 * It's control wire was connected to GPIOxx (3-wire serial interface)
83 * ML/I2S (11pin) -- GPIO18
84 * MC/IWL (12pin) -- GPIO17
85 * MD/DM (13pin) -- GPIO16
86 * MUTE (14pin) -- GPIO01
87 *
88 * WM8776
89 * A 2ch-ADC(with 10ch-selector) plus 2ch-DAC.
90 * It's control wire was connected to SDA/SCLK (2-wire serial interface)
91 * MODE (16pin) -- R(1K) -- GND
92 * CE (17pin) -- R(1K) -- GND 2-wire mode (address=0x34)
93 * DI (18pin) -- SDA
94 * CL (19pin) -- SCLK
95 *
96 *
97 * ** output pins and device names **
98 *
99 * 7.1ch name -- output connector color -- device (-D option)
100 *
101 * FRONT 2ch -- green -- plughw:0,0
102 * CENTER(Lch) SUBWOOFER(Rch) -- black -- plughw:0,2,0
103 * SURROUND 2ch -- orange -- plughw:0,2,1
104 * SURROUND BACK 2ch -- white -- plughw:0,2,2
105 *
106 */
107
108
109/****************************************************************************/
110/* WM8740 interface */
111/****************************************************************************/
112
113static void __devinit se200pci_WM8740_init(struct snd_ice1712 *ice)
114{
115 /* nothing to do */
116}
117
118
119static void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice,
120 unsigned int rate)
121{
122 /* nothing to do */
123}
124
125
126/****************************************************************************/
127/* WM8766 interface */
128/****************************************************************************/
129
130static void se200pci_WM8766_write(struct snd_ice1712 *ice,
131 unsigned int addr, unsigned int data)
132{
133 unsigned int st;
134 unsigned int bits;
135 int i;
136 const unsigned int DATA = 0x010000;
137 const unsigned int CLOCK = 0x020000;
138 const unsigned int LOAD = 0x040000;
139 const unsigned int ALL_MASK = (DATA | CLOCK | LOAD);
140
141 snd_ice1712_save_gpio_status(ice);
142
143 st = ((addr & 0x7f) << 9) | (data & 0x1ff);
144 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | ALL_MASK);
145 snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~ALL_MASK);
146 bits = snd_ice1712_gpio_read(ice) & ~ALL_MASK;
147
148 snd_ice1712_gpio_write(ice, bits);
149 for (i = 0; i < 16; i++) {
150 udelay(1);
151 bits &= ~CLOCK;
152 st = (st << 1);
153 if (st & 0x10000)
154 bits |= DATA;
155 else
156 bits &= ~DATA;
157
158 snd_ice1712_gpio_write(ice, bits);
159
160 udelay(1);
161 bits |= CLOCK;
162 snd_ice1712_gpio_write(ice, bits);
163 }
164
165 udelay(1);
166 bits |= LOAD;
167 snd_ice1712_gpio_write(ice, bits);
168
169 udelay(1);
170 bits |= (DATA | CLOCK);
171 snd_ice1712_gpio_write(ice, bits);
172
173 snd_ice1712_restore_gpio_status(ice);
174}
175
176static void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch,
177 unsigned int vol1, unsigned int vol2)
178{
179 switch (ch) {
180 case 0:
181 se200pci_WM8766_write(ice, 0x000, vol1);
182 se200pci_WM8766_write(ice, 0x001, vol2 | 0x100);
183 break;
184 case 1:
185 se200pci_WM8766_write(ice, 0x004, vol1);
186 se200pci_WM8766_write(ice, 0x005, vol2 | 0x100);
187 break;
188 case 2:
189 se200pci_WM8766_write(ice, 0x006, vol1);
190 se200pci_WM8766_write(ice, 0x007, vol2 | 0x100);
191 break;
192 }
193}
194
195static void __devinit se200pci_WM8766_init(struct snd_ice1712 *ice)
196{
197 se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */
198 udelay(10);
199
200 se200pci_WM8766_set_volume(ice, 0, 0, 0); /* volume L=0 R=0 */
201 se200pci_WM8766_set_volume(ice, 1, 0, 0); /* volume L=0 R=0 */
202 se200pci_WM8766_set_volume(ice, 2, 0, 0); /* volume L=0 R=0 */
203
204 se200pci_WM8766_write(ice, 0x03, 0x022); /* serial mode I2S-24bits */
205 se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
206 se200pci_WM8766_write(ice, 0x12, 0x000); /* MDP=0 */
207 se200pci_WM8766_write(ice, 0x15, 0x000); /* MDP=0 */
208 se200pci_WM8766_write(ice, 0x09, 0x000); /* demp=off mute=off */
209
210 se200pci_WM8766_write(ice, 0x02, 0x124); /* ch-assign L=L R=R RESET */
211 se200pci_WM8766_write(ice, 0x02, 0x120); /* ch-assign L=L R=R */
212}
213
214static void se200pci_WM8766_set_pro_rate(struct snd_ice1712 *ice,
215 unsigned int rate)
216{
217 if (rate > 96000)
218 se200pci_WM8766_write(ice, 0x0a, 0x000); /* MCLK=128fs */
219 else
220 se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */
221}
222
223
224/****************************************************************************/
225/* WM8776 interface */
226/****************************************************************************/
227
228static void se200pci_WM8776_write(struct snd_ice1712 *ice,
229 unsigned int addr, unsigned int data)
230{
231 unsigned int val;
232
233 val = (addr << 9) | data;
234 snd_vt1724_write_i2c(ice, 0x34, val >> 8, val & 0xff);
235}
236
237
238static void se200pci_WM8776_set_output_volume(struct snd_ice1712 *ice,
239 unsigned int vol1, unsigned int vol2)
240{
241 se200pci_WM8776_write(ice, 0x03, vol1);
242 se200pci_WM8776_write(ice, 0x04, vol2 | 0x100);
243}
244
245static void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice,
246 unsigned int vol1, unsigned int vol2)
247{
248 se200pci_WM8776_write(ice, 0x0e, vol1);
249 se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100);
250}
251
252static const char *se200pci_sel[] = {
253 "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL
254};
255
256static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice,
257 unsigned int sel)
258{
259 static unsigned char vals[] = {
260 /* LINE, CD, MIC, ALL, GND */
261 0x10, 0x04, 0x08, 0x1c, 0x03
262 };
263 if (sel > 4)
264 sel = 4;
265 se200pci_WM8776_write(ice, 0x15, vals[sel]);
266}
267
268static void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl)
269{
270 /* AFL -- After Fader Listening */
271 if (afl)
272 se200pci_WM8776_write(ice, 0x16, 0x005);
273 else
274 se200pci_WM8776_write(ice, 0x16, 0x001);
275}
276
277static const char *se200pci_agc[] = {
278 "Off", "LimiterMode", "ALCMode", NULL
279};
280
281static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
282{
283 /* AGC -- Auto Gain Control of the input */
284 switch (agc) {
285 case 0:
286 se200pci_WM8776_write(ice, 0x11, 0x000); /* Off */
287 break;
288 case 1:
289 se200pci_WM8776_write(ice, 0x10, 0x07b);
290 se200pci_WM8776_write(ice, 0x11, 0x100); /* LimiterMode */
291 break;
292 case 2:
293 se200pci_WM8776_write(ice, 0x10, 0x1fb);
294 se200pci_WM8776_write(ice, 0x11, 0x100); /* ALCMode */
295 break;
296 }
297}
298
299static void __devinit se200pci_WM8776_init(struct snd_ice1712 *ice)
300{
301 int i;
302 static unsigned short __devinitdata default_values[] = {
303 0x100, 0x100, 0x100,
304 0x100, 0x100, 0x100,
305 0x000, 0x090, 0x000, 0x000,
306 0x022, 0x022, 0x022,
307 0x008, 0x0cf, 0x0cf, 0x07b, 0x000,
308 0x032, 0x000, 0x0a6, 0x001, 0x001
309 };
310
311 se200pci_WM8776_write(ice, 0x17, 0x000); /* reset all */
312 /* ADC and DAC interface is I2S 24bits mode */
313 /* The sample-rate are automatically changed */
314 udelay(10);
315 /* BUT my board can not do reset all, so I load all by manually. */
316 for (i = 0; i < ARRAY_SIZE(default_values); i++)
317 se200pci_WM8776_write(ice, i, default_values[i]);
318
319 se200pci_WM8776_set_input_selector(ice, 0);
320 se200pci_WM8776_set_afl(ice, 0);
321 se200pci_WM8776_set_agc(ice, 0);
322 se200pci_WM8776_set_input_volume(ice, 0, 0);
323 se200pci_WM8776_set_output_volume(ice, 0, 0);
324
325 /* head phone mute and power down */
326 se200pci_WM8776_write(ice, 0x00, 0);
327 se200pci_WM8776_write(ice, 0x01, 0);
328 se200pci_WM8776_write(ice, 0x02, 0x100);
329 se200pci_WM8776_write(ice, 0x0d, 0x080);
330}
331
332static void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice,
333 unsigned int rate)
334{
335 /* nothing to do */
336}
337
338
339/****************************************************************************/
340/* runtime interface */
341/****************************************************************************/
342
343static void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate)
344{
345 se200pci_WM8740_set_pro_rate(ice, rate);
346 se200pci_WM8766_set_pro_rate(ice, rate);
347 se200pci_WM8776_set_pro_rate(ice, rate);
348}
349
350struct se200pci_control {
351 char *name;
352 enum {
353 WM8766,
354 WM8776in,
355 WM8776out,
356 WM8776sel,
357 WM8776agc,
358 WM8776afl
359 } target;
360 enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type;
361 int ch;
362 const char **member;
363 const char *comment;
364};
365
366static const struct se200pci_control se200pci_cont[] = {
367 {
368 .name = "Front Playback Volume",
369 .target = WM8776out,
370 .type = VOLUME1,
371 .comment = "Front(green)"
372 },
373 {
374 .name = "Side Playback Volume",
375 .target = WM8766,
376 .type = VOLUME1,
377 .ch = 1,
378 .comment = "Surround(orange)"
379 },
380 {
381 .name = "Surround Playback Volume",
382 .target = WM8766,
383 .type = VOLUME1,
384 .ch = 2,
385 .comment = "SurroundBack(white)"
386 },
387 {
388 .name = "CLFE Playback Volume",
389 .target = WM8766,
390 .type = VOLUME1,
391 .ch = 0,
392 .comment = "Center(Lch)&SubWoofer(Rch)(black)"
393 },
394 {
395 .name = "Capture Volume",
396 .target = WM8776in,
397 .type = VOLUME2
398 },
399 {
400 .name = "Capture Select",
401 .target = WM8776sel,
402 .type = ENUM,
403 .member = se200pci_sel
404 },
405 {
406 .name = "AGC Capture Mode",
407 .target = WM8776agc,
408 .type = ENUM,
409 .member = se200pci_agc
410 },
411 {
412 .name = "AFL Bypass Playback Switch",
413 .target = WM8776afl,
414 .type = BOOLEAN
415 }
416};
417
418static int se200pci_cont_info(struct snd_kcontrol *kc,
419 struct snd_ctl_elem_info *uinfo)
420{
421 struct snd_ice1712 *ice;
422 int n;
423 int c;
424 const char **member;
425
426 ice = snd_kcontrol_chip(kc);
427 n = kc->private_value;
428
429 if (se200pci_cont[n].type == VOLUME1 ||
430 se200pci_cont[n].type == VOLUME2) {
431 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
432 uinfo->count = 2;
433 uinfo->value.integer.min = 0; /* mute */
434 uinfo->value.integer.max = 0xff; /* 0dB */
435
436 } else if (se200pci_cont[n].type == BOOLEAN) {
437 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
438 uinfo->count = 1;
439 uinfo->value.integer.min = 0;
440 uinfo->value.integer.max = 1;
441
442 } else if (se200pci_cont[n].type == ENUM) {
443 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
444 member = se200pci_cont[n].member;
445 if (member == NULL)
446 return -EINVAL;
447 for (c = 0; member[c]; c++)
448 ;
449
450 uinfo->count = 1;
451 uinfo->value.enumerated.items = c;
452 if (uinfo->value.enumerated.item >= c)
453 uinfo->value.enumerated.item = c - 1;
454 strcpy(uinfo->value.enumerated.name,
455 member[uinfo->value.enumerated.item]);
456 }
457
458 return 0;
459}
460
461static int se200pci_cont_get(struct snd_kcontrol *kc,
462 struct snd_ctl_elem_value *uc)
463{
464 struct snd_ice1712 *ice;
465 int n;
466
467 ice = snd_kcontrol_chip(kc);
468 n = kc->private_value;
469 if (se200pci_cont[n].type == VOLUME1 ||
470 se200pci_cont[n].type == VOLUME2) {
471 uc->value.integer.value[0] = ice->spec.se.vol[n].ch1;
472 uc->value.integer.value[1] = ice->spec.se.vol[n].ch2;
473
474 } else if (se200pci_cont[n].type == BOOLEAN ||
475 se200pci_cont[n].type == ENUM)
476 uc->value.integer.value[0] = ice->spec.se.vol[n].ch1;
477
478 return 0;
479}
480
481static int se200pci_cont_put(struct snd_kcontrol *kc,
482 struct snd_ctl_elem_value *uc)
483{
484 struct snd_ice1712 *ice;
485 int n;
486 unsigned int vol1, vol2;
487 int changed;
488
489 ice = snd_kcontrol_chip(kc);
490 n = kc->private_value;
491
492 changed = 0;
493 vol1 = 0; vol2 = 0;
494 if (se200pci_cont[n].type == VOLUME1 ||
495 se200pci_cont[n].type == VOLUME2) {
496 vol1 = uc->value.integer.value[0];
497 vol2 = uc->value.integer.value[1];
498 if (ice->spec.se.vol[n].ch1 != vol1)
499 changed = 1;
500 if (ice->spec.se.vol[n].ch2 != vol2)
501 changed = 1;
502 ice->spec.se.vol[n].ch1 = vol1;
503 ice->spec.se.vol[n].ch2 = vol2;
504
505 } else if (se200pci_cont[n].type == BOOLEAN ||
506 se200pci_cont[n].type == ENUM) {
507 vol1 = uc->value.integer.value[0];
508 if (ice->spec.se.vol[n].ch1 != vol1)
509 changed = 1;
510 ice->spec.se.vol[n].ch1 = vol1;
511 }
512
513 switch (se200pci_cont[n].target) {
514 case WM8766:
515 se200pci_WM8766_set_volume(ice,
516 se200pci_cont[n].ch, vol1, vol2);
517 break;
518
519 case WM8776in:
520 se200pci_WM8776_set_input_volume(ice, vol1, vol2);
521 break;
522
523 case WM8776out:
524 se200pci_WM8776_set_output_volume(ice, vol1, vol2);
525 break;
526
527 case WM8776sel:
528 se200pci_WM8776_set_input_selector(ice, vol1);
529 break;
530
531 case WM8776agc:
532 se200pci_WM8776_set_agc(ice, vol1);
533 break;
534
535 case WM8776afl:
536 se200pci_WM8776_set_afl(ice, vol1);
537 break;
538
539 default:
540 break;
541 }
542
543 return changed;
544}
545
546static const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1);
547static const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1);
548
549static int __devinit se200pci_add_controls(struct snd_ice1712 *ice)
550{
551 int i;
552 struct snd_kcontrol_new cont;
553 int err;
554
555 memset(&cont, 0, sizeof(cont));
556 cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
557 cont.info = se200pci_cont_info;
558 cont.get = se200pci_cont_get;
559 cont.put = se200pci_cont_put;
560 for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) {
561 cont.private_value = i;
562 cont.name = se200pci_cont[i].name;
563 cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
564 cont.tlv.p = NULL;
565 if (se200pci_cont[i].type == VOLUME1 ||
566 se200pci_cont[i].type == VOLUME2) {
567
568 cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
569
570 if (se200pci_cont[i].type == VOLUME1)
571 cont.tlv.p = db_scale_gain1;
572 else
573 cont.tlv.p = db_scale_gain2;
574 }
575 err = snd_ctl_add(ice->card, snd_ctl_new1(&cont, ice));
576 if (err < 0)
577 return err;
578 }
579
580 return 0;
581}
582
583
584/****************************************************************************/
585/* ONKYO WAVIO SE-90PCI */
586/****************************************************************************/
587/*
588 * system configuration ICE_EEP2_SYSCONF=0x4b
589 * AC-Link configuration ICE_EEP2_ACLINK=0x80
590 * I2S converters feature ICE_EEP2_I2S=0x78
591 * S/PDIF configuration ICE_EEP2_SPDIF=0xc3
592 *
593 * ** connected chip **
594 *
595 * WM8716
596 * A 2ch-DAC of main outputs.
597 * It setuped as I2S mode by wire, so no way to setup from software.
598 * ML/I2S (28pin) -- +5V
599 * MC/DM1 (27pin) -- GND
600 * MC/DM0 (26pin) -- GND
601 * MUTEB (25pin) -- open (internal pull-up)
602 * MODE (24pin) -- GND
603 * CSBIWO (23pin) -- +5V
604 *
605 */
606
607 /* Nothing to do for this chip. */
608
609
610/****************************************************************************/
611/* probe/initialize/setup */
612/****************************************************************************/
613
614static int __devinit se_init(struct snd_ice1712 *ice)
615{
616 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE90PCI) {
617 ice->num_total_dacs = 2;
618 ice->num_total_adcs = 0;
619 ice->vt1720 = 1;
620 return 0;
621
622 } else if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) {
623 ice->num_total_dacs = 8;
624 ice->num_total_adcs = 2;
625 se200pci_WM8740_init(ice);
626 se200pci_WM8766_init(ice);
627 se200pci_WM8776_init(ice);
628 ice->gpio.set_pro_rate = se200pci_set_pro_rate;
629 return 0;
630 }
631
632 return -ENOENT;
633}
634
635static int __devinit se_add_controls(struct snd_ice1712 *ice)
636{
637 int err;
638
639 err = 0;
640 /* nothing to do for VT1724_SUBDEVICE_SE90PCI */
641 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI)
642 err = se200pci_add_controls(ice);
643
644 return err;
645}
646
647
648/****************************************************************************/
649/* entry point */
650/****************************************************************************/
651
652static unsigned char se200pci_eeprom[] __devinitdata = {
653 [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
654 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
655 [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
656 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
657
658 [ICE_EEP2_GPIO_DIR] = 0x02, /* WM8766 mute 1=output */
659 [ICE_EEP2_GPIO_DIR1] = 0x00, /* not used */
660 [ICE_EEP2_GPIO_DIR2] = 0x07, /* WM8766 ML/MC/MD 1=output */
661
662 [ICE_EEP2_GPIO_MASK] = 0x00, /* 0=writable */
663 [ICE_EEP2_GPIO_MASK1] = 0x00, /* 0=writable */
664 [ICE_EEP2_GPIO_MASK2] = 0x00, /* 0=writable */
665
666 [ICE_EEP2_GPIO_STATE] = 0x00, /* WM8766 mute=0 */
667 [ICE_EEP2_GPIO_STATE1] = 0x00, /* not used */
668 [ICE_EEP2_GPIO_STATE2] = 0x07, /* WM8766 ML/MC/MD */
669};
670
671static unsigned char se90pci_eeprom[] __devinitdata = {
672 [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
673 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
674 [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */
675 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
676
677 /* ALL GPIO bits are in input mode */
678};
679
680struct snd_ice1712_card_info snd_vt1724_se_cards[] __devinitdata = {
681 {
682 .subvendor = VT1724_SUBDEVICE_SE200PCI,
683 .name = "ONKYO SE200PCI",
684 .model = "se200pci",
685 .chip_init = se_init,
686 .build_controls = se_add_controls,
687 .eeprom_size = sizeof(se200pci_eeprom),
688 .eeprom_data = se200pci_eeprom,
689 },
690 {
691 .subvendor = VT1724_SUBDEVICE_SE90PCI,
692 .name = "ONKYO SE90PCI",
693 .model = "se90pci",
694 .chip_init = se_init,
695 .build_controls = se_add_controls,
696 .eeprom_size = sizeof(se90pci_eeprom),
697 .eeprom_data = se90pci_eeprom,
698 },
699 {} /*terminator*/
700};
diff --git a/sound/pci/ice1712/se.h b/sound/pci/ice1712/se.h
new file mode 100644
index 000000000000..0b0a9dabdcfb
--- /dev/null
+++ b/sound/pci/ice1712/se.h
@@ -0,0 +1,15 @@
1#ifndef __SOUND_SE_H
2#define __SOUND_SE_H
3
4/* ID */
5#define SE_DEVICE_DESC \
6 "{ONKYO INC,SE-90PCI},"\
7 "{ONKYO INC,SE-200PCI},"
8
9#define VT1724_SUBDEVICE_SE90PCI 0xb161000
10#define VT1724_SUBDEVICE_SE200PCI 0xb160100
11
12/* entry struct */
13extern struct snd_ice1712_card_info snd_vt1724_se_cards[];
14
15#endif /* __SOUND_SE_H */