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