18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * ALSA driver for ICEnsemble VT1724 (Envy24HT) 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Lowlevel functions for ONKYO WAVIO SE-90PCI and SE-200PCI 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (c) 2007 Shin-ya Okada sh_okada(at)d4.dion.ne.jp 88c2ecf20Sopenharmony_ci * (at) -> @ 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/delay.h> 128c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <sound/core.h> 168c2ecf20Sopenharmony_ci#include <sound/tlv.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include "ice1712.h" 198c2ecf20Sopenharmony_ci#include "envy24ht.h" 208c2ecf20Sopenharmony_ci#include "se.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistruct se_spec { 238c2ecf20Sopenharmony_ci struct { 248c2ecf20Sopenharmony_ci unsigned char ch1, ch2; 258c2ecf20Sopenharmony_ci } vol[8]; 268c2ecf20Sopenharmony_ci}; 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/****************************************************************************/ 298c2ecf20Sopenharmony_ci/* ONKYO WAVIO SE-200PCI */ 308c2ecf20Sopenharmony_ci/****************************************************************************/ 318c2ecf20Sopenharmony_ci/* 328c2ecf20Sopenharmony_ci * system configuration ICE_EEP2_SYSCONF=0x4b 338c2ecf20Sopenharmony_ci * XIN1 49.152MHz 348c2ecf20Sopenharmony_ci * not have UART 358c2ecf20Sopenharmony_ci * one stereo ADC and a S/PDIF receiver connected 368c2ecf20Sopenharmony_ci * four stereo DACs connected 378c2ecf20Sopenharmony_ci * 388c2ecf20Sopenharmony_ci * AC-Link configuration ICE_EEP2_ACLINK=0x80 398c2ecf20Sopenharmony_ci * use I2C, not use AC97 408c2ecf20Sopenharmony_ci * 418c2ecf20Sopenharmony_ci * I2S converters feature ICE_EEP2_I2S=0x78 428c2ecf20Sopenharmony_ci * I2S codec has no volume/mute control feature 438c2ecf20Sopenharmony_ci * I2S codec supports 96KHz and 192KHz 448c2ecf20Sopenharmony_ci * I2S codec 24bits 458c2ecf20Sopenharmony_ci * 468c2ecf20Sopenharmony_ci * S/PDIF configuration ICE_EEP2_SPDIF=0xc3 478c2ecf20Sopenharmony_ci * Enable integrated S/PDIF transmitter 488c2ecf20Sopenharmony_ci * internal S/PDIF out implemented 498c2ecf20Sopenharmony_ci * S/PDIF is stereo 508c2ecf20Sopenharmony_ci * External S/PDIF out implemented 518c2ecf20Sopenharmony_ci * 528c2ecf20Sopenharmony_ci * 538c2ecf20Sopenharmony_ci * ** connected chips ** 548c2ecf20Sopenharmony_ci * 558c2ecf20Sopenharmony_ci * WM8740 568c2ecf20Sopenharmony_ci * A 2ch-DAC of main outputs. 578c2ecf20Sopenharmony_ci * It setuped as I2S mode by wire, so no way to setup from software. 588c2ecf20Sopenharmony_ci * The sample-rate are automatically changed. 598c2ecf20Sopenharmony_ci * ML/I2S (28pin) --------+ 608c2ecf20Sopenharmony_ci * MC/DM1 (27pin) -- 5V | 618c2ecf20Sopenharmony_ci * MD/DM0 (26pin) -- GND | 628c2ecf20Sopenharmony_ci * MUTEB (25pin) -- NC | 638c2ecf20Sopenharmony_ci * MODE (24pin) -- GND | 648c2ecf20Sopenharmony_ci * CSBIW (23pin) --------+ 658c2ecf20Sopenharmony_ci * | 668c2ecf20Sopenharmony_ci * RSTB (22pin) --R(1K)-+ 678c2ecf20Sopenharmony_ci * Probably it reduce the noise from the control line. 688c2ecf20Sopenharmony_ci * 698c2ecf20Sopenharmony_ci * WM8766 708c2ecf20Sopenharmony_ci * A 6ch-DAC for surrounds. 718c2ecf20Sopenharmony_ci * It's control wire was connected to GPIOxx (3-wire serial interface) 728c2ecf20Sopenharmony_ci * ML/I2S (11pin) -- GPIO18 738c2ecf20Sopenharmony_ci * MC/IWL (12pin) -- GPIO17 748c2ecf20Sopenharmony_ci * MD/DM (13pin) -- GPIO16 758c2ecf20Sopenharmony_ci * MUTE (14pin) -- GPIO01 768c2ecf20Sopenharmony_ci * 778c2ecf20Sopenharmony_ci * WM8776 788c2ecf20Sopenharmony_ci * A 2ch-ADC(with 10ch-selector) plus 2ch-DAC. 798c2ecf20Sopenharmony_ci * It's control wire was connected to SDA/SCLK (2-wire serial interface) 808c2ecf20Sopenharmony_ci * MODE (16pin) -- R(1K) -- GND 818c2ecf20Sopenharmony_ci * CE (17pin) -- R(1K) -- GND 2-wire mode (address=0x34) 828c2ecf20Sopenharmony_ci * DI (18pin) -- SDA 838c2ecf20Sopenharmony_ci * CL (19pin) -- SCLK 848c2ecf20Sopenharmony_ci * 858c2ecf20Sopenharmony_ci * 868c2ecf20Sopenharmony_ci * ** output pins and device names ** 878c2ecf20Sopenharmony_ci * 888c2ecf20Sopenharmony_ci * 7.1ch name -- output connector color -- device (-D option) 898c2ecf20Sopenharmony_ci * 908c2ecf20Sopenharmony_ci * FRONT 2ch -- green -- plughw:0,0 918c2ecf20Sopenharmony_ci * CENTER(Lch) SUBWOOFER(Rch) -- black -- plughw:0,2,0 928c2ecf20Sopenharmony_ci * SURROUND 2ch -- orange -- plughw:0,2,1 938c2ecf20Sopenharmony_ci * SURROUND BACK 2ch -- white -- plughw:0,2,2 948c2ecf20Sopenharmony_ci * 958c2ecf20Sopenharmony_ci */ 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci/****************************************************************************/ 998c2ecf20Sopenharmony_ci/* WM8740 interface */ 1008c2ecf20Sopenharmony_ci/****************************************************************************/ 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic void se200pci_WM8740_init(struct snd_ice1712 *ice) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci /* nothing to do */ 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic void se200pci_WM8740_set_pro_rate(struct snd_ice1712 *ice, 1098c2ecf20Sopenharmony_ci unsigned int rate) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci /* nothing to do */ 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci/****************************************************************************/ 1168c2ecf20Sopenharmony_ci/* WM8766 interface */ 1178c2ecf20Sopenharmony_ci/****************************************************************************/ 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic void se200pci_WM8766_write(struct snd_ice1712 *ice, 1208c2ecf20Sopenharmony_ci unsigned int addr, unsigned int data) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci unsigned int st; 1238c2ecf20Sopenharmony_ci unsigned int bits; 1248c2ecf20Sopenharmony_ci int i; 1258c2ecf20Sopenharmony_ci const unsigned int DATA = 0x010000; 1268c2ecf20Sopenharmony_ci const unsigned int CLOCK = 0x020000; 1278c2ecf20Sopenharmony_ci const unsigned int LOAD = 0x040000; 1288c2ecf20Sopenharmony_ci const unsigned int ALL_MASK = (DATA | CLOCK | LOAD); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci snd_ice1712_save_gpio_status(ice); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci st = ((addr & 0x7f) << 9) | (data & 0x1ff); 1338c2ecf20Sopenharmony_ci snd_ice1712_gpio_set_dir(ice, ice->gpio.direction | ALL_MASK); 1348c2ecf20Sopenharmony_ci snd_ice1712_gpio_set_mask(ice, ice->gpio.write_mask & ~ALL_MASK); 1358c2ecf20Sopenharmony_ci bits = snd_ice1712_gpio_read(ice) & ~ALL_MASK; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, bits); 1388c2ecf20Sopenharmony_ci for (i = 0; i < 16; i++) { 1398c2ecf20Sopenharmony_ci udelay(1); 1408c2ecf20Sopenharmony_ci bits &= ~CLOCK; 1418c2ecf20Sopenharmony_ci st = (st << 1); 1428c2ecf20Sopenharmony_ci if (st & 0x10000) 1438c2ecf20Sopenharmony_ci bits |= DATA; 1448c2ecf20Sopenharmony_ci else 1458c2ecf20Sopenharmony_ci bits &= ~DATA; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, bits); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci udelay(1); 1508c2ecf20Sopenharmony_ci bits |= CLOCK; 1518c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, bits); 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci udelay(1); 1558c2ecf20Sopenharmony_ci bits |= LOAD; 1568c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, bits); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci udelay(1); 1598c2ecf20Sopenharmony_ci bits |= (DATA | CLOCK); 1608c2ecf20Sopenharmony_ci snd_ice1712_gpio_write(ice, bits); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci snd_ice1712_restore_gpio_status(ice); 1638c2ecf20Sopenharmony_ci} 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_cistatic void se200pci_WM8766_set_volume(struct snd_ice1712 *ice, int ch, 1668c2ecf20Sopenharmony_ci unsigned int vol1, unsigned int vol2) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci switch (ch) { 1698c2ecf20Sopenharmony_ci case 0: 1708c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x000, vol1); 1718c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x001, vol2 | 0x100); 1728c2ecf20Sopenharmony_ci break; 1738c2ecf20Sopenharmony_ci case 1: 1748c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x004, vol1); 1758c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x005, vol2 | 0x100); 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci case 2: 1788c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x006, vol1); 1798c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x007, vol2 | 0x100); 1808c2ecf20Sopenharmony_ci break; 1818c2ecf20Sopenharmony_ci } 1828c2ecf20Sopenharmony_ci} 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_cistatic void se200pci_WM8766_init(struct snd_ice1712 *ice) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x1f, 0x000); /* RESET ALL */ 1878c2ecf20Sopenharmony_ci udelay(10); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci se200pci_WM8766_set_volume(ice, 0, 0, 0); /* volume L=0 R=0 */ 1908c2ecf20Sopenharmony_ci se200pci_WM8766_set_volume(ice, 1, 0, 0); /* volume L=0 R=0 */ 1918c2ecf20Sopenharmony_ci se200pci_WM8766_set_volume(ice, 2, 0, 0); /* volume L=0 R=0 */ 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x03, 0x022); /* serial mode I2S-24bits */ 1948c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */ 1958c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x12, 0x000); /* MDP=0 */ 1968c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x15, 0x000); /* MDP=0 */ 1978c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x09, 0x000); /* demp=off mute=off */ 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x02, 0x124); /* ch-assign L=L R=R RESET */ 2008c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x02, 0x120); /* ch-assign L=L R=R */ 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic void se200pci_WM8766_set_pro_rate(struct snd_ice1712 *ice, 2048c2ecf20Sopenharmony_ci unsigned int rate) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci if (rate > 96000) 2078c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x0a, 0x000); /* MCLK=128fs */ 2088c2ecf20Sopenharmony_ci else 2098c2ecf20Sopenharmony_ci se200pci_WM8766_write(ice, 0x0a, 0x080); /* MCLK=256fs */ 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci/****************************************************************************/ 2148c2ecf20Sopenharmony_ci/* WM8776 interface */ 2158c2ecf20Sopenharmony_ci/****************************************************************************/ 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistatic void se200pci_WM8776_write(struct snd_ice1712 *ice, 2188c2ecf20Sopenharmony_ci unsigned int addr, unsigned int data) 2198c2ecf20Sopenharmony_ci{ 2208c2ecf20Sopenharmony_ci unsigned int val; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci val = (addr << 9) | data; 2238c2ecf20Sopenharmony_ci snd_vt1724_write_i2c(ice, 0x34, val >> 8, val & 0xff); 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_cistatic void se200pci_WM8776_set_output_volume(struct snd_ice1712 *ice, 2288c2ecf20Sopenharmony_ci unsigned int vol1, unsigned int vol2) 2298c2ecf20Sopenharmony_ci{ 2308c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x03, vol1); 2318c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x04, vol2 | 0x100); 2328c2ecf20Sopenharmony_ci} 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_cistatic void se200pci_WM8776_set_input_volume(struct snd_ice1712 *ice, 2358c2ecf20Sopenharmony_ci unsigned int vol1, unsigned int vol2) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x0e, vol1); 2388c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x0f, vol2 | 0x100); 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic const char * const se200pci_sel[] = { 2428c2ecf20Sopenharmony_ci "LINE-IN", "CD-IN", "MIC-IN", "ALL-MIX", NULL 2438c2ecf20Sopenharmony_ci}; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice, 2468c2ecf20Sopenharmony_ci unsigned int sel) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci static const unsigned char vals[] = { 2498c2ecf20Sopenharmony_ci /* LINE, CD, MIC, ALL, GND */ 2508c2ecf20Sopenharmony_ci 0x10, 0x04, 0x08, 0x1c, 0x03 2518c2ecf20Sopenharmony_ci }; 2528c2ecf20Sopenharmony_ci if (sel > 4) 2538c2ecf20Sopenharmony_ci sel = 4; 2548c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x15, vals[sel]); 2558c2ecf20Sopenharmony_ci} 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_cistatic void se200pci_WM8776_set_afl(struct snd_ice1712 *ice, unsigned int afl) 2588c2ecf20Sopenharmony_ci{ 2598c2ecf20Sopenharmony_ci /* AFL -- After Fader Listening */ 2608c2ecf20Sopenharmony_ci if (afl) 2618c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x16, 0x005); 2628c2ecf20Sopenharmony_ci else 2638c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x16, 0x001); 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_cistatic const char * const se200pci_agc[] = { 2678c2ecf20Sopenharmony_ci "Off", "LimiterMode", "ALCMode", NULL 2688c2ecf20Sopenharmony_ci}; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci /* AGC -- Auto Gain Control of the input */ 2738c2ecf20Sopenharmony_ci switch (agc) { 2748c2ecf20Sopenharmony_ci case 0: 2758c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x11, 0x000); /* Off */ 2768c2ecf20Sopenharmony_ci break; 2778c2ecf20Sopenharmony_ci case 1: 2788c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x10, 0x07b); 2798c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x11, 0x100); /* LimiterMode */ 2808c2ecf20Sopenharmony_ci break; 2818c2ecf20Sopenharmony_ci case 2: 2828c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x10, 0x1fb); 2838c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x11, 0x100); /* ALCMode */ 2848c2ecf20Sopenharmony_ci break; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_cistatic void se200pci_WM8776_init(struct snd_ice1712 *ice) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci int i; 2918c2ecf20Sopenharmony_ci static const unsigned short default_values[] = { 2928c2ecf20Sopenharmony_ci 0x100, 0x100, 0x100, 2938c2ecf20Sopenharmony_ci 0x100, 0x100, 0x100, 2948c2ecf20Sopenharmony_ci 0x000, 0x090, 0x000, 0x000, 2958c2ecf20Sopenharmony_ci 0x022, 0x022, 0x022, 2968c2ecf20Sopenharmony_ci 0x008, 0x0cf, 0x0cf, 0x07b, 0x000, 2978c2ecf20Sopenharmony_ci 0x032, 0x000, 0x0a6, 0x001, 0x001 2988c2ecf20Sopenharmony_ci }; 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x17, 0x000); /* reset all */ 3018c2ecf20Sopenharmony_ci /* ADC and DAC interface is I2S 24bits mode */ 3028c2ecf20Sopenharmony_ci /* The sample-rate are automatically changed */ 3038c2ecf20Sopenharmony_ci udelay(10); 3048c2ecf20Sopenharmony_ci /* BUT my board can not do reset all, so I load all by manually. */ 3058c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(default_values); i++) 3068c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, i, default_values[i]); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci se200pci_WM8776_set_input_selector(ice, 0); 3098c2ecf20Sopenharmony_ci se200pci_WM8776_set_afl(ice, 0); 3108c2ecf20Sopenharmony_ci se200pci_WM8776_set_agc(ice, 0); 3118c2ecf20Sopenharmony_ci se200pci_WM8776_set_input_volume(ice, 0, 0); 3128c2ecf20Sopenharmony_ci se200pci_WM8776_set_output_volume(ice, 0, 0); 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci /* head phone mute and power down */ 3158c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x00, 0); 3168c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x01, 0); 3178c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x02, 0x100); 3188c2ecf20Sopenharmony_ci se200pci_WM8776_write(ice, 0x0d, 0x080); 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic void se200pci_WM8776_set_pro_rate(struct snd_ice1712 *ice, 3228c2ecf20Sopenharmony_ci unsigned int rate) 3238c2ecf20Sopenharmony_ci{ 3248c2ecf20Sopenharmony_ci /* nothing to do */ 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci/****************************************************************************/ 3298c2ecf20Sopenharmony_ci/* runtime interface */ 3308c2ecf20Sopenharmony_ci/****************************************************************************/ 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic void se200pci_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci se200pci_WM8740_set_pro_rate(ice, rate); 3358c2ecf20Sopenharmony_ci se200pci_WM8766_set_pro_rate(ice, rate); 3368c2ecf20Sopenharmony_ci se200pci_WM8776_set_pro_rate(ice, rate); 3378c2ecf20Sopenharmony_ci} 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_cistruct se200pci_control { 3408c2ecf20Sopenharmony_ci const char *name; 3418c2ecf20Sopenharmony_ci enum { 3428c2ecf20Sopenharmony_ci WM8766, 3438c2ecf20Sopenharmony_ci WM8776in, 3448c2ecf20Sopenharmony_ci WM8776out, 3458c2ecf20Sopenharmony_ci WM8776sel, 3468c2ecf20Sopenharmony_ci WM8776agc, 3478c2ecf20Sopenharmony_ci WM8776afl 3488c2ecf20Sopenharmony_ci } target; 3498c2ecf20Sopenharmony_ci enum { VOLUME1, VOLUME2, BOOLEAN, ENUM } type; 3508c2ecf20Sopenharmony_ci int ch; 3518c2ecf20Sopenharmony_ci const char * const *member; 3528c2ecf20Sopenharmony_ci const char *comment; 3538c2ecf20Sopenharmony_ci}; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_cistatic const struct se200pci_control se200pci_cont[] = { 3568c2ecf20Sopenharmony_ci { 3578c2ecf20Sopenharmony_ci .name = "Front Playback Volume", 3588c2ecf20Sopenharmony_ci .target = WM8776out, 3598c2ecf20Sopenharmony_ci .type = VOLUME1, 3608c2ecf20Sopenharmony_ci .comment = "Front(green)" 3618c2ecf20Sopenharmony_ci }, 3628c2ecf20Sopenharmony_ci { 3638c2ecf20Sopenharmony_ci .name = "Side Playback Volume", 3648c2ecf20Sopenharmony_ci .target = WM8766, 3658c2ecf20Sopenharmony_ci .type = VOLUME1, 3668c2ecf20Sopenharmony_ci .ch = 1, 3678c2ecf20Sopenharmony_ci .comment = "Surround(orange)" 3688c2ecf20Sopenharmony_ci }, 3698c2ecf20Sopenharmony_ci { 3708c2ecf20Sopenharmony_ci .name = "Surround Playback Volume", 3718c2ecf20Sopenharmony_ci .target = WM8766, 3728c2ecf20Sopenharmony_ci .type = VOLUME1, 3738c2ecf20Sopenharmony_ci .ch = 2, 3748c2ecf20Sopenharmony_ci .comment = "SurroundBack(white)" 3758c2ecf20Sopenharmony_ci }, 3768c2ecf20Sopenharmony_ci { 3778c2ecf20Sopenharmony_ci .name = "CLFE Playback Volume", 3788c2ecf20Sopenharmony_ci .target = WM8766, 3798c2ecf20Sopenharmony_ci .type = VOLUME1, 3808c2ecf20Sopenharmony_ci .ch = 0, 3818c2ecf20Sopenharmony_ci .comment = "Center(Lch)&SubWoofer(Rch)(black)" 3828c2ecf20Sopenharmony_ci }, 3838c2ecf20Sopenharmony_ci { 3848c2ecf20Sopenharmony_ci .name = "Capture Volume", 3858c2ecf20Sopenharmony_ci .target = WM8776in, 3868c2ecf20Sopenharmony_ci .type = VOLUME2 3878c2ecf20Sopenharmony_ci }, 3888c2ecf20Sopenharmony_ci { 3898c2ecf20Sopenharmony_ci .name = "Capture Select", 3908c2ecf20Sopenharmony_ci .target = WM8776sel, 3918c2ecf20Sopenharmony_ci .type = ENUM, 3928c2ecf20Sopenharmony_ci .member = se200pci_sel 3938c2ecf20Sopenharmony_ci }, 3948c2ecf20Sopenharmony_ci { 3958c2ecf20Sopenharmony_ci .name = "AGC Capture Mode", 3968c2ecf20Sopenharmony_ci .target = WM8776agc, 3978c2ecf20Sopenharmony_ci .type = ENUM, 3988c2ecf20Sopenharmony_ci .member = se200pci_agc 3998c2ecf20Sopenharmony_ci }, 4008c2ecf20Sopenharmony_ci { 4018c2ecf20Sopenharmony_ci .name = "AFL Bypass Playback Switch", 4028c2ecf20Sopenharmony_ci .target = WM8776afl, 4038c2ecf20Sopenharmony_ci .type = BOOLEAN 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci}; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_cistatic int se200pci_get_enum_count(int n) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci const char * const *member; 4108c2ecf20Sopenharmony_ci int c; 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci member = se200pci_cont[n].member; 4138c2ecf20Sopenharmony_ci if (!member) 4148c2ecf20Sopenharmony_ci return 0; 4158c2ecf20Sopenharmony_ci for (c = 0; member[c]; c++) 4168c2ecf20Sopenharmony_ci ; 4178c2ecf20Sopenharmony_ci return c; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic int se200pci_cont_volume_info(struct snd_kcontrol *kc, 4218c2ecf20Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 4248c2ecf20Sopenharmony_ci uinfo->count = 2; 4258c2ecf20Sopenharmony_ci uinfo->value.integer.min = 0; /* mute */ 4268c2ecf20Sopenharmony_ci uinfo->value.integer.max = 0xff; /* 0dB */ 4278c2ecf20Sopenharmony_ci return 0; 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci#define se200pci_cont_boolean_info snd_ctl_boolean_mono_info 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic int se200pci_cont_enum_info(struct snd_kcontrol *kc, 4338c2ecf20Sopenharmony_ci struct snd_ctl_elem_info *uinfo) 4348c2ecf20Sopenharmony_ci{ 4358c2ecf20Sopenharmony_ci int n, c; 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci n = kc->private_value; 4388c2ecf20Sopenharmony_ci c = se200pci_get_enum_count(n); 4398c2ecf20Sopenharmony_ci if (!c) 4408c2ecf20Sopenharmony_ci return -EINVAL; 4418c2ecf20Sopenharmony_ci return snd_ctl_enum_info(uinfo, 1, c, se200pci_cont[n].member); 4428c2ecf20Sopenharmony_ci} 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_cistatic int se200pci_cont_volume_get(struct snd_kcontrol *kc, 4458c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *uc) 4468c2ecf20Sopenharmony_ci{ 4478c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kc); 4488c2ecf20Sopenharmony_ci struct se_spec *spec = ice->spec; 4498c2ecf20Sopenharmony_ci int n = kc->private_value; 4508c2ecf20Sopenharmony_ci uc->value.integer.value[0] = spec->vol[n].ch1; 4518c2ecf20Sopenharmony_ci uc->value.integer.value[1] = spec->vol[n].ch2; 4528c2ecf20Sopenharmony_ci return 0; 4538c2ecf20Sopenharmony_ci} 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic int se200pci_cont_boolean_get(struct snd_kcontrol *kc, 4568c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *uc) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kc); 4598c2ecf20Sopenharmony_ci struct se_spec *spec = ice->spec; 4608c2ecf20Sopenharmony_ci int n = kc->private_value; 4618c2ecf20Sopenharmony_ci uc->value.integer.value[0] = spec->vol[n].ch1; 4628c2ecf20Sopenharmony_ci return 0; 4638c2ecf20Sopenharmony_ci} 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_cistatic int se200pci_cont_enum_get(struct snd_kcontrol *kc, 4668c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *uc) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kc); 4698c2ecf20Sopenharmony_ci struct se_spec *spec = ice->spec; 4708c2ecf20Sopenharmony_ci int n = kc->private_value; 4718c2ecf20Sopenharmony_ci uc->value.enumerated.item[0] = spec->vol[n].ch1; 4728c2ecf20Sopenharmony_ci return 0; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic void se200pci_cont_update(struct snd_ice1712 *ice, int n) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci struct se_spec *spec = ice->spec; 4788c2ecf20Sopenharmony_ci switch (se200pci_cont[n].target) { 4798c2ecf20Sopenharmony_ci case WM8766: 4808c2ecf20Sopenharmony_ci se200pci_WM8766_set_volume(ice, 4818c2ecf20Sopenharmony_ci se200pci_cont[n].ch, 4828c2ecf20Sopenharmony_ci spec->vol[n].ch1, 4838c2ecf20Sopenharmony_ci spec->vol[n].ch2); 4848c2ecf20Sopenharmony_ci break; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci case WM8776in: 4878c2ecf20Sopenharmony_ci se200pci_WM8776_set_input_volume(ice, 4888c2ecf20Sopenharmony_ci spec->vol[n].ch1, 4898c2ecf20Sopenharmony_ci spec->vol[n].ch2); 4908c2ecf20Sopenharmony_ci break; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci case WM8776out: 4938c2ecf20Sopenharmony_ci se200pci_WM8776_set_output_volume(ice, 4948c2ecf20Sopenharmony_ci spec->vol[n].ch1, 4958c2ecf20Sopenharmony_ci spec->vol[n].ch2); 4968c2ecf20Sopenharmony_ci break; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci case WM8776sel: 4998c2ecf20Sopenharmony_ci se200pci_WM8776_set_input_selector(ice, 5008c2ecf20Sopenharmony_ci spec->vol[n].ch1); 5018c2ecf20Sopenharmony_ci break; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci case WM8776agc: 5048c2ecf20Sopenharmony_ci se200pci_WM8776_set_agc(ice, spec->vol[n].ch1); 5058c2ecf20Sopenharmony_ci break; 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci case WM8776afl: 5088c2ecf20Sopenharmony_ci se200pci_WM8776_set_afl(ice, spec->vol[n].ch1); 5098c2ecf20Sopenharmony_ci break; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci default: 5128c2ecf20Sopenharmony_ci break; 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci} 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_cistatic int se200pci_cont_volume_put(struct snd_kcontrol *kc, 5178c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *uc) 5188c2ecf20Sopenharmony_ci{ 5198c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kc); 5208c2ecf20Sopenharmony_ci struct se_spec *spec = ice->spec; 5218c2ecf20Sopenharmony_ci int n = kc->private_value; 5228c2ecf20Sopenharmony_ci unsigned int vol1, vol2; 5238c2ecf20Sopenharmony_ci int changed; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci changed = 0; 5268c2ecf20Sopenharmony_ci vol1 = uc->value.integer.value[0] & 0xff; 5278c2ecf20Sopenharmony_ci vol2 = uc->value.integer.value[1] & 0xff; 5288c2ecf20Sopenharmony_ci if (spec->vol[n].ch1 != vol1) { 5298c2ecf20Sopenharmony_ci spec->vol[n].ch1 = vol1; 5308c2ecf20Sopenharmony_ci changed = 1; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci if (spec->vol[n].ch2 != vol2) { 5338c2ecf20Sopenharmony_ci spec->vol[n].ch2 = vol2; 5348c2ecf20Sopenharmony_ci changed = 1; 5358c2ecf20Sopenharmony_ci } 5368c2ecf20Sopenharmony_ci if (changed) 5378c2ecf20Sopenharmony_ci se200pci_cont_update(ice, n); 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci return changed; 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ci 5428c2ecf20Sopenharmony_cistatic int se200pci_cont_boolean_put(struct snd_kcontrol *kc, 5438c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *uc) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kc); 5468c2ecf20Sopenharmony_ci struct se_spec *spec = ice->spec; 5478c2ecf20Sopenharmony_ci int n = kc->private_value; 5488c2ecf20Sopenharmony_ci unsigned int vol1; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci vol1 = !!uc->value.integer.value[0]; 5518c2ecf20Sopenharmony_ci if (spec->vol[n].ch1 != vol1) { 5528c2ecf20Sopenharmony_ci spec->vol[n].ch1 = vol1; 5538c2ecf20Sopenharmony_ci se200pci_cont_update(ice, n); 5548c2ecf20Sopenharmony_ci return 1; 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci return 0; 5578c2ecf20Sopenharmony_ci} 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_cistatic int se200pci_cont_enum_put(struct snd_kcontrol *kc, 5608c2ecf20Sopenharmony_ci struct snd_ctl_elem_value *uc) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci struct snd_ice1712 *ice = snd_kcontrol_chip(kc); 5638c2ecf20Sopenharmony_ci struct se_spec *spec = ice->spec; 5648c2ecf20Sopenharmony_ci int n = kc->private_value; 5658c2ecf20Sopenharmony_ci unsigned int vol1; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci vol1 = uc->value.enumerated.item[0]; 5688c2ecf20Sopenharmony_ci if (vol1 >= se200pci_get_enum_count(n)) 5698c2ecf20Sopenharmony_ci return -EINVAL; 5708c2ecf20Sopenharmony_ci if (spec->vol[n].ch1 != vol1) { 5718c2ecf20Sopenharmony_ci spec->vol[n].ch1 = vol1; 5728c2ecf20Sopenharmony_ci se200pci_cont_update(ice, n); 5738c2ecf20Sopenharmony_ci return 1; 5748c2ecf20Sopenharmony_ci } 5758c2ecf20Sopenharmony_ci return 0; 5768c2ecf20Sopenharmony_ci} 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_gain1, -12750, 50, 1); 5798c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_gain2, -10350, 50, 1); 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_cistatic int se200pci_add_controls(struct snd_ice1712 *ice) 5828c2ecf20Sopenharmony_ci{ 5838c2ecf20Sopenharmony_ci int i; 5848c2ecf20Sopenharmony_ci struct snd_kcontrol_new cont; 5858c2ecf20Sopenharmony_ci int err; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci memset(&cont, 0, sizeof(cont)); 5888c2ecf20Sopenharmony_ci cont.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 5898c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(se200pci_cont); i++) { 5908c2ecf20Sopenharmony_ci cont.private_value = i; 5918c2ecf20Sopenharmony_ci cont.name = se200pci_cont[i].name; 5928c2ecf20Sopenharmony_ci cont.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; 5938c2ecf20Sopenharmony_ci cont.tlv.p = NULL; 5948c2ecf20Sopenharmony_ci switch (se200pci_cont[i].type) { 5958c2ecf20Sopenharmony_ci case VOLUME1: 5968c2ecf20Sopenharmony_ci case VOLUME2: 5978c2ecf20Sopenharmony_ci cont.info = se200pci_cont_volume_info; 5988c2ecf20Sopenharmony_ci cont.get = se200pci_cont_volume_get; 5998c2ecf20Sopenharmony_ci cont.put = se200pci_cont_volume_put; 6008c2ecf20Sopenharmony_ci cont.access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; 6018c2ecf20Sopenharmony_ci if (se200pci_cont[i].type == VOLUME1) 6028c2ecf20Sopenharmony_ci cont.tlv.p = db_scale_gain1; 6038c2ecf20Sopenharmony_ci else 6048c2ecf20Sopenharmony_ci cont.tlv.p = db_scale_gain2; 6058c2ecf20Sopenharmony_ci break; 6068c2ecf20Sopenharmony_ci case BOOLEAN: 6078c2ecf20Sopenharmony_ci cont.info = se200pci_cont_boolean_info; 6088c2ecf20Sopenharmony_ci cont.get = se200pci_cont_boolean_get; 6098c2ecf20Sopenharmony_ci cont.put = se200pci_cont_boolean_put; 6108c2ecf20Sopenharmony_ci break; 6118c2ecf20Sopenharmony_ci case ENUM: 6128c2ecf20Sopenharmony_ci cont.info = se200pci_cont_enum_info; 6138c2ecf20Sopenharmony_ci cont.get = se200pci_cont_enum_get; 6148c2ecf20Sopenharmony_ci cont.put = se200pci_cont_enum_put; 6158c2ecf20Sopenharmony_ci break; 6168c2ecf20Sopenharmony_ci default: 6178c2ecf20Sopenharmony_ci snd_BUG(); 6188c2ecf20Sopenharmony_ci return -EINVAL; 6198c2ecf20Sopenharmony_ci } 6208c2ecf20Sopenharmony_ci err = snd_ctl_add(ice->card, snd_ctl_new1(&cont, ice)); 6218c2ecf20Sopenharmony_ci if (err < 0) 6228c2ecf20Sopenharmony_ci return err; 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci return 0; 6268c2ecf20Sopenharmony_ci} 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci/****************************************************************************/ 6308c2ecf20Sopenharmony_ci/* ONKYO WAVIO SE-90PCI */ 6318c2ecf20Sopenharmony_ci/****************************************************************************/ 6328c2ecf20Sopenharmony_ci/* 6338c2ecf20Sopenharmony_ci * system configuration ICE_EEP2_SYSCONF=0x4b 6348c2ecf20Sopenharmony_ci * AC-Link configuration ICE_EEP2_ACLINK=0x80 6358c2ecf20Sopenharmony_ci * I2S converters feature ICE_EEP2_I2S=0x78 6368c2ecf20Sopenharmony_ci * S/PDIF configuration ICE_EEP2_SPDIF=0xc3 6378c2ecf20Sopenharmony_ci * 6388c2ecf20Sopenharmony_ci * ** connected chip ** 6398c2ecf20Sopenharmony_ci * 6408c2ecf20Sopenharmony_ci * WM8716 6418c2ecf20Sopenharmony_ci * A 2ch-DAC of main outputs. 6428c2ecf20Sopenharmony_ci * It setuped as I2S mode by wire, so no way to setup from software. 6438c2ecf20Sopenharmony_ci * ML/I2S (28pin) -- +5V 6448c2ecf20Sopenharmony_ci * MC/DM1 (27pin) -- GND 6458c2ecf20Sopenharmony_ci * MC/DM0 (26pin) -- GND 6468c2ecf20Sopenharmony_ci * MUTEB (25pin) -- open (internal pull-up) 6478c2ecf20Sopenharmony_ci * MODE (24pin) -- GND 6488c2ecf20Sopenharmony_ci * CSBIWO (23pin) -- +5V 6498c2ecf20Sopenharmony_ci * 6508c2ecf20Sopenharmony_ci */ 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci /* Nothing to do for this chip. */ 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci/****************************************************************************/ 6568c2ecf20Sopenharmony_ci/* probe/initialize/setup */ 6578c2ecf20Sopenharmony_ci/****************************************************************************/ 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_cistatic int se_init(struct snd_ice1712 *ice) 6608c2ecf20Sopenharmony_ci{ 6618c2ecf20Sopenharmony_ci struct se_spec *spec; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci spec = kzalloc(sizeof(*spec), GFP_KERNEL); 6648c2ecf20Sopenharmony_ci if (!spec) 6658c2ecf20Sopenharmony_ci return -ENOMEM; 6668c2ecf20Sopenharmony_ci ice->spec = spec; 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE90PCI) { 6698c2ecf20Sopenharmony_ci ice->num_total_dacs = 2; 6708c2ecf20Sopenharmony_ci ice->num_total_adcs = 0; 6718c2ecf20Sopenharmony_ci ice->vt1720 = 1; 6728c2ecf20Sopenharmony_ci return 0; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci } else if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) { 6758c2ecf20Sopenharmony_ci ice->num_total_dacs = 8; 6768c2ecf20Sopenharmony_ci ice->num_total_adcs = 2; 6778c2ecf20Sopenharmony_ci se200pci_WM8740_init(ice); 6788c2ecf20Sopenharmony_ci se200pci_WM8766_init(ice); 6798c2ecf20Sopenharmony_ci se200pci_WM8776_init(ice); 6808c2ecf20Sopenharmony_ci ice->gpio.set_pro_rate = se200pci_set_pro_rate; 6818c2ecf20Sopenharmony_ci return 0; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci return -ENOENT; 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_cistatic int se_add_controls(struct snd_ice1712 *ice) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci int err; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci err = 0; 6928c2ecf20Sopenharmony_ci /* nothing to do for VT1724_SUBDEVICE_SE90PCI */ 6938c2ecf20Sopenharmony_ci if (ice->eeprom.subvendor == VT1724_SUBDEVICE_SE200PCI) 6948c2ecf20Sopenharmony_ci err = se200pci_add_controls(ice); 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci return err; 6978c2ecf20Sopenharmony_ci} 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci/****************************************************************************/ 7018c2ecf20Sopenharmony_ci/* entry point */ 7028c2ecf20Sopenharmony_ci/****************************************************************************/ 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_cistatic const unsigned char se200pci_eeprom[] = { 7058c2ecf20Sopenharmony_ci [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */ 7068c2ecf20Sopenharmony_ci [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 7078c2ecf20Sopenharmony_ci [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */ 7088c2ecf20Sopenharmony_ci [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR] = 0x02, /* WM8766 mute 1=output */ 7118c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR1] = 0x00, /* not used */ 7128c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_DIR2] = 0x07, /* WM8766 ML/MC/MD 1=output */ 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK] = 0x00, /* 0=writable */ 7158c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK1] = 0x00, /* 0=writable */ 7168c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_MASK2] = 0x00, /* 0=writable */ 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE] = 0x00, /* WM8766 mute=0 */ 7198c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE1] = 0x00, /* not used */ 7208c2ecf20Sopenharmony_ci [ICE_EEP2_GPIO_STATE2] = 0x07, /* WM8766 ML/MC/MD */ 7218c2ecf20Sopenharmony_ci}; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_cistatic const unsigned char se90pci_eeprom[] = { 7248c2ecf20Sopenharmony_ci [ICE_EEP2_SYSCONF] = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */ 7258c2ecf20Sopenharmony_ci [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 7268c2ecf20Sopenharmony_ci [ICE_EEP2_I2S] = 0x78, /* 96k-ok, 24bit, 192k-ok */ 7278c2ecf20Sopenharmony_ci [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */ 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci /* ALL GPIO bits are in input mode */ 7308c2ecf20Sopenharmony_ci}; 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_cistruct snd_ice1712_card_info snd_vt1724_se_cards[] = { 7338c2ecf20Sopenharmony_ci { 7348c2ecf20Sopenharmony_ci .subvendor = VT1724_SUBDEVICE_SE200PCI, 7358c2ecf20Sopenharmony_ci .name = "ONKYO SE200PCI", 7368c2ecf20Sopenharmony_ci .model = "se200pci", 7378c2ecf20Sopenharmony_ci .chip_init = se_init, 7388c2ecf20Sopenharmony_ci .build_controls = se_add_controls, 7398c2ecf20Sopenharmony_ci .eeprom_size = sizeof(se200pci_eeprom), 7408c2ecf20Sopenharmony_ci .eeprom_data = se200pci_eeprom, 7418c2ecf20Sopenharmony_ci }, 7428c2ecf20Sopenharmony_ci { 7438c2ecf20Sopenharmony_ci .subvendor = VT1724_SUBDEVICE_SE90PCI, 7448c2ecf20Sopenharmony_ci .name = "ONKYO SE90PCI", 7458c2ecf20Sopenharmony_ci .model = "se90pci", 7468c2ecf20Sopenharmony_ci .chip_init = se_init, 7478c2ecf20Sopenharmony_ci .build_controls = se_add_controls, 7488c2ecf20Sopenharmony_ci .eeprom_size = sizeof(se90pci_eeprom), 7498c2ecf20Sopenharmony_ci .eeprom_data = se90pci_eeprom, 7508c2ecf20Sopenharmony_ci }, 7518c2ecf20Sopenharmony_ci {} /*terminator*/ 7528c2ecf20Sopenharmony_ci}; 753