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