Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
se.c
Go to the documentation of this file.
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 
355  char *name;
356  enum {
363  } target;
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 {
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;
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));
611  for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) {
612  cont.private_value = i;
613  cont.name = se200pci_cont[i].name;
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;
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:
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 };