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