16ef80706SPavel Hofman /* 26ef80706SPavel Hofman * ALSA driver for ICEnsemble VT1724 (Envy24HT) 36ef80706SPavel Hofman * 46ef80706SPavel Hofman * Lowlevel functions for Infrasonic Quartet 56ef80706SPavel Hofman * 66ef80706SPavel Hofman * Copyright (c) 2009 Pavel Hofman <pavel.hofman@ivitera.com> 76ef80706SPavel Hofman * 86ef80706SPavel Hofman * 96ef80706SPavel Hofman * This program is free software; you can redistribute it and/or modify 106ef80706SPavel Hofman * it under the terms of the GNU General Public License as published by 116ef80706SPavel Hofman * the Free Software Foundation; either version 2 of the License, or 126ef80706SPavel Hofman * (at your option) any later version. 136ef80706SPavel Hofman * 146ef80706SPavel Hofman * This program is distributed in the hope that it will be useful, 156ef80706SPavel Hofman * but WITHOUT ANY WARRANTY; without even the implied warranty of 166ef80706SPavel Hofman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 176ef80706SPavel Hofman * GNU General Public License for more details. 186ef80706SPavel Hofman * 196ef80706SPavel Hofman * You should have received a copy of the GNU General Public License 206ef80706SPavel Hofman * along with this program; if not, write to the Free Software 216ef80706SPavel Hofman * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 226ef80706SPavel Hofman * 236ef80706SPavel Hofman */ 246ef80706SPavel Hofman 256ef80706SPavel Hofman #include <linux/delay.h> 266ef80706SPavel Hofman #include <linux/interrupt.h> 276ef80706SPavel Hofman #include <linux/init.h> 286ef80706SPavel Hofman #include <linux/slab.h> 29*338e17d3SJoey Pabalinas #include <linux/string.h> 306ef80706SPavel Hofman #include <sound/core.h> 316ef80706SPavel Hofman #include <sound/tlv.h> 326ef80706SPavel Hofman #include <sound/info.h> 336ef80706SPavel Hofman 346ef80706SPavel Hofman #include "ice1712.h" 356ef80706SPavel Hofman #include "envy24ht.h" 366ef80706SPavel Hofman #include <sound/ak4113.h> 376ef80706SPavel Hofman #include "quartet.h" 386ef80706SPavel Hofman 396ef80706SPavel Hofman struct qtet_spec { 406ef80706SPavel Hofman struct ak4113 *ak4113; 416ef80706SPavel Hofman unsigned int scr; /* system control register */ 426ef80706SPavel Hofman unsigned int mcr; /* monitoring control register */ 436ef80706SPavel Hofman unsigned int cpld; /* cpld register */ 446ef80706SPavel Hofman }; 456ef80706SPavel Hofman 466ef80706SPavel Hofman struct qtet_kcontrol_private { 476ef80706SPavel Hofman unsigned int bit; 486ef80706SPavel Hofman void (*set_register)(struct snd_ice1712 *ice, unsigned int val); 496ef80706SPavel Hofman unsigned int (*get_register)(struct snd_ice1712 *ice); 50597da2e4STakashi Iwai const char * const texts[2]; 516ef80706SPavel Hofman }; 526ef80706SPavel Hofman 536ef80706SPavel Hofman enum { 546ef80706SPavel Hofman IN12_SEL = 0, 556ef80706SPavel Hofman IN34_SEL, 566ef80706SPavel Hofman AIN34_SEL, 576ef80706SPavel Hofman COAX_OUT, 586ef80706SPavel Hofman IN12_MON12, 596ef80706SPavel Hofman IN12_MON34, 606ef80706SPavel Hofman IN34_MON12, 616ef80706SPavel Hofman IN34_MON34, 626ef80706SPavel Hofman OUT12_MON34, 636ef80706SPavel Hofman OUT34_MON12, 646ef80706SPavel Hofman }; 656ef80706SPavel Hofman 66a2af050fSTakashi Iwai static const char * const ext_clock_names[3] = {"IEC958 In", "Word Clock 1xFS", 676ef80706SPavel Hofman "Word Clock 256xFS"}; 686ef80706SPavel Hofman 696ef80706SPavel Hofman /* chip address on I2C bus */ 706ef80706SPavel Hofman #define AK4113_ADDR 0x26 /* S/PDIF receiver */ 716ef80706SPavel Hofman 726ef80706SPavel Hofman /* chip address on SPI bus */ 736ef80706SPavel Hofman #define AK4620_ADDR 0x02 /* ADC/DAC */ 746ef80706SPavel Hofman 756ef80706SPavel Hofman 766ef80706SPavel Hofman /* 776ef80706SPavel Hofman * GPIO pins 786ef80706SPavel Hofman */ 796ef80706SPavel Hofman 806ef80706SPavel Hofman /* GPIO0 - O - DATA0, def. 0 */ 816ef80706SPavel Hofman #define GPIO_D0 (1<<0) 826ef80706SPavel Hofman /* GPIO1 - I/O - DATA1, Jack Detect Input0 (0:present, 1:missing), def. 1 */ 836ef80706SPavel Hofman #define GPIO_D1_JACKDTC0 (1<<1) 846ef80706SPavel Hofman /* GPIO2 - I/O - DATA2, Jack Detect Input1 (0:present, 1:missing), def. 1 */ 856ef80706SPavel Hofman #define GPIO_D2_JACKDTC1 (1<<2) 866ef80706SPavel Hofman /* GPIO3 - I/O - DATA3, def. 1 */ 876ef80706SPavel Hofman #define GPIO_D3 (1<<3) 886ef80706SPavel Hofman /* GPIO4 - I/O - DATA4, SPI CDTO, def. 1 */ 896ef80706SPavel Hofman #define GPIO_D4_SPI_CDTO (1<<4) 906ef80706SPavel Hofman /* GPIO5 - I/O - DATA5, SPI CCLK, def. 1 */ 916ef80706SPavel Hofman #define GPIO_D5_SPI_CCLK (1<<5) 926ef80706SPavel Hofman /* GPIO6 - I/O - DATA6, Cable Detect Input (0:detected, 1:not detected */ 936ef80706SPavel Hofman #define GPIO_D6_CD (1<<6) 946ef80706SPavel Hofman /* GPIO7 - I/O - DATA7, Device Detect Input (0:detected, 1:not detected */ 956ef80706SPavel Hofman #define GPIO_D7_DD (1<<7) 966ef80706SPavel Hofman /* GPIO8 - O - CPLD Chip Select, def. 1 */ 976ef80706SPavel Hofman #define GPIO_CPLD_CSN (1<<8) 986ef80706SPavel Hofman /* GPIO9 - O - CPLD register read/write (0:write, 1:read), def. 0 */ 996ef80706SPavel Hofman #define GPIO_CPLD_RW (1<<9) 1006ef80706SPavel Hofman /* GPIO10 - O - SPI Chip Select for CODEC#0, def. 1 */ 1016ef80706SPavel Hofman #define GPIO_SPI_CSN0 (1<<10) 1026ef80706SPavel Hofman /* GPIO11 - O - SPI Chip Select for CODEC#1, def. 1 */ 1036ef80706SPavel Hofman #define GPIO_SPI_CSN1 (1<<11) 1046ef80706SPavel Hofman /* GPIO12 - O - Ex. Register Output Enable (0:enable, 1:disable), def. 1, 1056ef80706SPavel Hofman * init 0 */ 1066ef80706SPavel Hofman #define GPIO_EX_GPIOE (1<<12) 1076ef80706SPavel Hofman /* GPIO13 - O - Ex. Register0 Chip Select for System Control Register, 1086ef80706SPavel Hofman * def. 1 */ 1096ef80706SPavel Hofman #define GPIO_SCR (1<<13) 1106ef80706SPavel Hofman /* GPIO14 - O - Ex. Register1 Chip Select for Monitor Control Register, 1116ef80706SPavel Hofman * def. 1 */ 1126ef80706SPavel Hofman #define GPIO_MCR (1<<14) 1136ef80706SPavel Hofman 1146ef80706SPavel Hofman #define GPIO_SPI_ALL (GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK |\ 1156ef80706SPavel Hofman GPIO_SPI_CSN0 | GPIO_SPI_CSN1) 1166ef80706SPavel Hofman 1176ef80706SPavel Hofman #define GPIO_DATA_MASK (GPIO_D0 | GPIO_D1_JACKDTC0 | \ 1186ef80706SPavel Hofman GPIO_D2_JACKDTC1 | GPIO_D3 | \ 1196ef80706SPavel Hofman GPIO_D4_SPI_CDTO | GPIO_D5_SPI_CCLK | \ 1206ef80706SPavel Hofman GPIO_D6_CD | GPIO_D7_DD) 1216ef80706SPavel Hofman 1226ef80706SPavel Hofman /* System Control Register GPIO_SCR data bits */ 1236ef80706SPavel Hofman /* Mic/Line select relay (0:line, 1:mic) */ 1246ef80706SPavel Hofman #define SCR_RELAY GPIO_D0 1256ef80706SPavel Hofman /* Phantom power drive control (0:5V, 1:48V) */ 1266ef80706SPavel Hofman #define SCR_PHP_V GPIO_D1_JACKDTC0 1276ef80706SPavel Hofman /* H/W mute control (0:Normal, 1:Mute) */ 1286ef80706SPavel Hofman #define SCR_MUTE GPIO_D2_JACKDTC1 1296ef80706SPavel Hofman /* Phantom power control (0:Phantom on, 1:off) */ 1306ef80706SPavel Hofman #define SCR_PHP GPIO_D3 1316ef80706SPavel Hofman /* Analog input 1/2 Source Select */ 1326ef80706SPavel Hofman #define SCR_AIN12_SEL0 GPIO_D4_SPI_CDTO 1336ef80706SPavel Hofman #define SCR_AIN12_SEL1 GPIO_D5_SPI_CCLK 1346ef80706SPavel Hofman /* Analog input 3/4 Source Select (0:line, 1:hi-z) */ 1356ef80706SPavel Hofman #define SCR_AIN34_SEL GPIO_D6_CD 1366ef80706SPavel Hofman /* Codec Power Down (0:power down, 1:normal) */ 1376ef80706SPavel Hofman #define SCR_CODEC_PDN GPIO_D7_DD 1386ef80706SPavel Hofman 1396ef80706SPavel Hofman #define SCR_AIN12_LINE (0) 1406ef80706SPavel Hofman #define SCR_AIN12_MIC (SCR_AIN12_SEL0) 1416ef80706SPavel Hofman #define SCR_AIN12_LOWCUT (SCR_AIN12_SEL1 | SCR_AIN12_SEL0) 1426ef80706SPavel Hofman 1436ef80706SPavel Hofman /* Monitor Control Register GPIO_MCR data bits */ 1446ef80706SPavel Hofman /* Input 1/2 to Monitor 1/2 (0:off, 1:on) */ 1456ef80706SPavel Hofman #define MCR_IN12_MON12 GPIO_D0 1466ef80706SPavel Hofman /* Input 1/2 to Monitor 3/4 (0:off, 1:on) */ 1476ef80706SPavel Hofman #define MCR_IN12_MON34 GPIO_D1_JACKDTC0 1486ef80706SPavel Hofman /* Input 3/4 to Monitor 1/2 (0:off, 1:on) */ 1496ef80706SPavel Hofman #define MCR_IN34_MON12 GPIO_D2_JACKDTC1 1506ef80706SPavel Hofman /* Input 3/4 to Monitor 3/4 (0:off, 1:on) */ 1516ef80706SPavel Hofman #define MCR_IN34_MON34 GPIO_D3 1526ef80706SPavel Hofman /* Output to Monitor 1/2 (0:off, 1:on) */ 1536ef80706SPavel Hofman #define MCR_OUT34_MON12 GPIO_D4_SPI_CDTO 1546ef80706SPavel Hofman /* Output to Monitor 3/4 (0:off, 1:on) */ 1556ef80706SPavel Hofman #define MCR_OUT12_MON34 GPIO_D5_SPI_CCLK 1566ef80706SPavel Hofman 1576ef80706SPavel Hofman /* CPLD Register DATA bits */ 1586ef80706SPavel Hofman /* Clock Rate Select */ 1596ef80706SPavel Hofman #define CPLD_CKS0 GPIO_D0 1606ef80706SPavel Hofman #define CPLD_CKS1 GPIO_D1_JACKDTC0 1616ef80706SPavel Hofman #define CPLD_CKS2 GPIO_D2_JACKDTC1 1626ef80706SPavel Hofman /* Sync Source Select (0:Internal, 1:External) */ 1636ef80706SPavel Hofman #define CPLD_SYNC_SEL GPIO_D3 1646ef80706SPavel Hofman /* Word Clock FS Select (0:FS, 1:256FS) */ 1656ef80706SPavel Hofman #define CPLD_WORD_SEL GPIO_D4_SPI_CDTO 1666ef80706SPavel Hofman /* Coaxial Output Source (IS-Link) (0:SPDIF, 1:I2S) */ 1676ef80706SPavel Hofman #define CPLD_COAX_OUT GPIO_D5_SPI_CCLK 1686ef80706SPavel Hofman /* Input 1/2 Source Select (0:Analog12, 1:An34) */ 1696ef80706SPavel Hofman #define CPLD_IN12_SEL GPIO_D6_CD 1706ef80706SPavel Hofman /* Input 3/4 Source Select (0:Analog34, 1:Digital In) */ 1716ef80706SPavel Hofman #define CPLD_IN34_SEL GPIO_D7_DD 1726ef80706SPavel Hofman 1736ef80706SPavel Hofman /* internal clock (CPLD_SYNC_SEL = 0) options */ 1746ef80706SPavel Hofman #define CPLD_CKS_44100HZ (0) 1756ef80706SPavel Hofman #define CPLD_CKS_48000HZ (CPLD_CKS0) 1766ef80706SPavel Hofman #define CPLD_CKS_88200HZ (CPLD_CKS1) 1776ef80706SPavel Hofman #define CPLD_CKS_96000HZ (CPLD_CKS1 | CPLD_CKS0) 1786ef80706SPavel Hofman #define CPLD_CKS_176400HZ (CPLD_CKS2) 1796ef80706SPavel Hofman #define CPLD_CKS_192000HZ (CPLD_CKS2 | CPLD_CKS0) 1806ef80706SPavel Hofman 1816ef80706SPavel Hofman #define CPLD_CKS_MASK (CPLD_CKS0 | CPLD_CKS1 | CPLD_CKS2) 1826ef80706SPavel Hofman 1836ef80706SPavel Hofman /* external clock (CPLD_SYNC_SEL = 1) options */ 1846ef80706SPavel Hofman /* external clock - SPDIF */ 1856ef80706SPavel Hofman #define CPLD_EXT_SPDIF (0 | CPLD_SYNC_SEL) 1866ef80706SPavel Hofman /* external clock - WordClock 1xfs */ 1876ef80706SPavel Hofman #define CPLD_EXT_WORDCLOCK_1FS (CPLD_CKS1 | CPLD_SYNC_SEL) 1886ef80706SPavel Hofman /* external clock - WordClock 256xfs */ 1896ef80706SPavel Hofman #define CPLD_EXT_WORDCLOCK_256FS (CPLD_CKS1 | CPLD_WORD_SEL |\ 1906ef80706SPavel Hofman CPLD_SYNC_SEL) 1916ef80706SPavel Hofman 1926ef80706SPavel Hofman #define EXT_SPDIF_TYPE 0 1936ef80706SPavel Hofman #define EXT_WORDCLOCK_1FS_TYPE 1 1946ef80706SPavel Hofman #define EXT_WORDCLOCK_256FS_TYPE 2 1956ef80706SPavel Hofman 1966ef80706SPavel Hofman #define AK4620_DFS0 (1<<0) 1976ef80706SPavel Hofman #define AK4620_DFS1 (1<<1) 1986ef80706SPavel Hofman #define AK4620_CKS0 (1<<2) 1996ef80706SPavel Hofman #define AK4620_CKS1 (1<<3) 2006ef80706SPavel Hofman /* Clock and Format Control register */ 2016ef80706SPavel Hofman #define AK4620_DFS_REG 0x02 2026ef80706SPavel Hofman 2036ef80706SPavel Hofman /* Deem and Volume Control register */ 2046ef80706SPavel Hofman #define AK4620_DEEMVOL_REG 0x03 2056ef80706SPavel Hofman #define AK4620_SMUTE (1<<7) 2066ef80706SPavel Hofman 2076ef80706SPavel Hofman /* 2086ef80706SPavel Hofman * Conversion from int value to its binary form. Used for debugging. 2096ef80706SPavel Hofman * The output buffer must be allocated prior to calling the function. 2106ef80706SPavel Hofman */ 2116ef80706SPavel Hofman static char *get_binary(char *buffer, int value) 2126ef80706SPavel Hofman { 2136ef80706SPavel Hofman int i, j, pos; 2146ef80706SPavel Hofman pos = 0; 2156ef80706SPavel Hofman for (i = 0; i < 4; ++i) { 2166ef80706SPavel Hofman for (j = 0; j < 8; ++j) { 2176ef80706SPavel Hofman if (value & (1 << (31-(i*8 + j)))) 2186ef80706SPavel Hofman buffer[pos] = '1'; 2196ef80706SPavel Hofman else 2206ef80706SPavel Hofman buffer[pos] = '0'; 2216ef80706SPavel Hofman pos++; 2226ef80706SPavel Hofman } 2236ef80706SPavel Hofman if (i < 3) { 2246ef80706SPavel Hofman buffer[pos] = ' '; 2256ef80706SPavel Hofman pos++; 2266ef80706SPavel Hofman } 2276ef80706SPavel Hofman } 2286ef80706SPavel Hofman buffer[pos] = '\0'; 2296ef80706SPavel Hofman return buffer; 2306ef80706SPavel Hofman } 2316ef80706SPavel Hofman 2326ef80706SPavel Hofman /* 2336ef80706SPavel Hofman * Initial setup of the conversion array GPIO <-> rate 2346ef80706SPavel Hofman */ 235965f19beSTakashi Iwai static const unsigned int qtet_rates[] = { 2366ef80706SPavel Hofman 44100, 48000, 88200, 2376ef80706SPavel Hofman 96000, 176400, 192000, 2386ef80706SPavel Hofman }; 2396ef80706SPavel Hofman 240965f19beSTakashi Iwai static const unsigned int cks_vals[] = { 2416ef80706SPavel Hofman CPLD_CKS_44100HZ, CPLD_CKS_48000HZ, CPLD_CKS_88200HZ, 2426ef80706SPavel Hofman CPLD_CKS_96000HZ, CPLD_CKS_176400HZ, CPLD_CKS_192000HZ, 2436ef80706SPavel Hofman }; 2446ef80706SPavel Hofman 245965f19beSTakashi Iwai static const struct snd_pcm_hw_constraint_list qtet_rates_info = { 2466ef80706SPavel Hofman .count = ARRAY_SIZE(qtet_rates), 2476ef80706SPavel Hofman .list = qtet_rates, 2486ef80706SPavel Hofman .mask = 0, 2496ef80706SPavel Hofman }; 2506ef80706SPavel Hofman 2516ef80706SPavel Hofman static void qtet_ak4113_write(void *private_data, unsigned char reg, 2526ef80706SPavel Hofman unsigned char val) 2536ef80706SPavel Hofman { 2546ef80706SPavel Hofman snd_vt1724_write_i2c((struct snd_ice1712 *)private_data, AK4113_ADDR, 2556ef80706SPavel Hofman reg, val); 2566ef80706SPavel Hofman } 2576ef80706SPavel Hofman 2586ef80706SPavel Hofman static unsigned char qtet_ak4113_read(void *private_data, unsigned char reg) 2596ef80706SPavel Hofman { 2606ef80706SPavel Hofman return snd_vt1724_read_i2c((struct snd_ice1712 *)private_data, 2616ef80706SPavel Hofman AK4113_ADDR, reg); 2626ef80706SPavel Hofman } 2636ef80706SPavel Hofman 2646ef80706SPavel Hofman 2656ef80706SPavel Hofman /* 2666ef80706SPavel Hofman * AK4620 section 2676ef80706SPavel Hofman */ 2686ef80706SPavel Hofman 2696ef80706SPavel Hofman /* 2706ef80706SPavel Hofman * Write data to addr register of ak4620 2716ef80706SPavel Hofman */ 2726ef80706SPavel Hofman static void qtet_akm_write(struct snd_akm4xxx *ak, int chip, 2736ef80706SPavel Hofman unsigned char addr, unsigned char data) 2746ef80706SPavel Hofman { 2756ef80706SPavel Hofman unsigned int tmp, orig_dir; 2766ef80706SPavel Hofman int idx; 2776ef80706SPavel Hofman unsigned int addrdata; 2786ef80706SPavel Hofman struct snd_ice1712 *ice = ak->private_data[0]; 2796ef80706SPavel Hofman 2806ef80706SPavel Hofman if (snd_BUG_ON(chip < 0 || chip >= 4)) 2816ef80706SPavel Hofman return; 2826dfb5affSTakashi Iwai /*dev_dbg(ice->card->dev, "Writing to AK4620: chip=%d, addr=0x%x, 2836ef80706SPavel Hofman data=0x%x\n", chip, addr, data);*/ 2846ef80706SPavel Hofman orig_dir = ice->gpio.get_dir(ice); 2856ef80706SPavel Hofman ice->gpio.set_dir(ice, orig_dir | GPIO_SPI_ALL); 2866ef80706SPavel Hofman /* set mask - only SPI bits */ 2876ef80706SPavel Hofman ice->gpio.set_mask(ice, ~GPIO_SPI_ALL); 2886ef80706SPavel Hofman 2896ef80706SPavel Hofman tmp = ice->gpio.get_data(ice); 2906ef80706SPavel Hofman /* high all */ 2916ef80706SPavel Hofman tmp |= GPIO_SPI_ALL; 2926ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 2936ef80706SPavel Hofman udelay(100); 2946ef80706SPavel Hofman /* drop chip select */ 2956ef80706SPavel Hofman if (chip) 2966ef80706SPavel Hofman /* CODEC 1 */ 2976ef80706SPavel Hofman tmp &= ~GPIO_SPI_CSN1; 2986ef80706SPavel Hofman else 2996ef80706SPavel Hofman tmp &= ~GPIO_SPI_CSN0; 3006ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 3016ef80706SPavel Hofman udelay(100); 3026ef80706SPavel Hofman 3036ef80706SPavel Hofman /* build I2C address + data byte */ 3046ef80706SPavel Hofman addrdata = (AK4620_ADDR << 6) | 0x20 | (addr & 0x1f); 3056ef80706SPavel Hofman addrdata = (addrdata << 8) | data; 3066ef80706SPavel Hofman for (idx = 15; idx >= 0; idx--) { 3076ef80706SPavel Hofman /* drop clock */ 3086ef80706SPavel Hofman tmp &= ~GPIO_D5_SPI_CCLK; 3096ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 3106ef80706SPavel Hofman udelay(100); 3116ef80706SPavel Hofman /* set data */ 3126ef80706SPavel Hofman if (addrdata & (1 << idx)) 3136ef80706SPavel Hofman tmp |= GPIO_D4_SPI_CDTO; 3146ef80706SPavel Hofman else 3156ef80706SPavel Hofman tmp &= ~GPIO_D4_SPI_CDTO; 3166ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 3176ef80706SPavel Hofman udelay(100); 3186ef80706SPavel Hofman /* raise clock */ 3196ef80706SPavel Hofman tmp |= GPIO_D5_SPI_CCLK; 3206ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 3216ef80706SPavel Hofman udelay(100); 3226ef80706SPavel Hofman } 3236ef80706SPavel Hofman /* all back to 1 */ 3246ef80706SPavel Hofman tmp |= GPIO_SPI_ALL; 3256ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 3266ef80706SPavel Hofman udelay(100); 3276ef80706SPavel Hofman 3286ef80706SPavel Hofman /* return all gpios to non-writable */ 3296ef80706SPavel Hofman ice->gpio.set_mask(ice, 0xffffff); 3306ef80706SPavel Hofman /* restore GPIOs direction */ 3316ef80706SPavel Hofman ice->gpio.set_dir(ice, orig_dir); 3326ef80706SPavel Hofman } 3336ef80706SPavel Hofman 3346ef80706SPavel Hofman static void qtet_akm_set_regs(struct snd_akm4xxx *ak, unsigned char addr, 3356ef80706SPavel Hofman unsigned char mask, unsigned char value) 3366ef80706SPavel Hofman { 3376ef80706SPavel Hofman unsigned char tmp; 3386ef80706SPavel Hofman int chip; 3396ef80706SPavel Hofman for (chip = 0; chip < ak->num_chips; chip++) { 3406ef80706SPavel Hofman tmp = snd_akm4xxx_get(ak, chip, addr); 3416ef80706SPavel Hofman /* clear the bits */ 3426ef80706SPavel Hofman tmp &= ~mask; 3436ef80706SPavel Hofman /* set the new bits */ 3446ef80706SPavel Hofman tmp |= value; 3456ef80706SPavel Hofman snd_akm4xxx_write(ak, chip, addr, tmp); 3466ef80706SPavel Hofman } 3476ef80706SPavel Hofman } 3486ef80706SPavel Hofman 3496ef80706SPavel Hofman /* 3506ef80706SPavel Hofman * change the rate of AK4620 3516ef80706SPavel Hofman */ 3526ef80706SPavel Hofman static void qtet_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate) 3536ef80706SPavel Hofman { 3546ef80706SPavel Hofman unsigned char ak4620_dfs; 3556ef80706SPavel Hofman 3566ef80706SPavel Hofman if (rate == 0) /* no hint - S/PDIF input is master or the new spdif 3576ef80706SPavel Hofman input rate undetected, simply return */ 3586ef80706SPavel Hofman return; 3596ef80706SPavel Hofman 3606ef80706SPavel Hofman /* adjust DFS on codecs - see datasheet */ 3616ef80706SPavel Hofman if (rate > 108000) 3626ef80706SPavel Hofman ak4620_dfs = AK4620_DFS1 | AK4620_CKS1; 3636ef80706SPavel Hofman else if (rate > 54000) 3646ef80706SPavel Hofman ak4620_dfs = AK4620_DFS0 | AK4620_CKS0; 3656ef80706SPavel Hofman else 3666ef80706SPavel Hofman ak4620_dfs = 0; 3676ef80706SPavel Hofman 3686ef80706SPavel Hofman /* set new value */ 3696ef80706SPavel Hofman qtet_akm_set_regs(ak, AK4620_DFS_REG, AK4620_DFS0 | AK4620_DFS1 | 3706ef80706SPavel Hofman AK4620_CKS0 | AK4620_CKS1, ak4620_dfs); 3716ef80706SPavel Hofman } 3726ef80706SPavel Hofman 3736ef80706SPavel Hofman #define AK_CONTROL(xname, xch) { .name = xname, .num_channels = xch } 3746ef80706SPavel Hofman 3756ef80706SPavel Hofman #define PCM_12_PLAYBACK_VOLUME "PCM 1/2 Playback Volume" 3766ef80706SPavel Hofman #define PCM_34_PLAYBACK_VOLUME "PCM 3/4 Playback Volume" 3776ef80706SPavel Hofman #define PCM_12_CAPTURE_VOLUME "PCM 1/2 Capture Volume" 3786ef80706SPavel Hofman #define PCM_34_CAPTURE_VOLUME "PCM 3/4 Capture Volume" 3796ef80706SPavel Hofman 3806ef80706SPavel Hofman static const struct snd_akm4xxx_dac_channel qtet_dac[] = { 3816ef80706SPavel Hofman AK_CONTROL(PCM_12_PLAYBACK_VOLUME, 2), 3826ef80706SPavel Hofman AK_CONTROL(PCM_34_PLAYBACK_VOLUME, 2), 3836ef80706SPavel Hofman }; 3846ef80706SPavel Hofman 3856ef80706SPavel Hofman static const struct snd_akm4xxx_adc_channel qtet_adc[] = { 3866ef80706SPavel Hofman AK_CONTROL(PCM_12_CAPTURE_VOLUME, 2), 3876ef80706SPavel Hofman AK_CONTROL(PCM_34_CAPTURE_VOLUME, 2), 3886ef80706SPavel Hofman }; 3896ef80706SPavel Hofman 3903135432eSBhumika Goyal static const struct snd_akm4xxx akm_qtet_dac = { 3916ef80706SPavel Hofman .type = SND_AK4620, 3926ef80706SPavel Hofman .num_dacs = 4, /* DAC1 - Output 12 3936ef80706SPavel Hofman */ 3946ef80706SPavel Hofman .num_adcs = 4, /* ADC1 - Input 12 3956ef80706SPavel Hofman */ 3966ef80706SPavel Hofman .ops = { 3976ef80706SPavel Hofman .write = qtet_akm_write, 3986ef80706SPavel Hofman .set_rate_val = qtet_akm_set_rate_val, 3996ef80706SPavel Hofman }, 4006ef80706SPavel Hofman .dac_info = qtet_dac, 4016ef80706SPavel Hofman .adc_info = qtet_adc, 4026ef80706SPavel Hofman }; 4036ef80706SPavel Hofman 4046ef80706SPavel Hofman /* Communication routines with the CPLD */ 4056ef80706SPavel Hofman 4066ef80706SPavel Hofman 4076ef80706SPavel Hofman /* Writes data to external register reg, both reg and data are 4086ef80706SPavel Hofman * GPIO representations */ 4096ef80706SPavel Hofman static void reg_write(struct snd_ice1712 *ice, unsigned int reg, 4106ef80706SPavel Hofman unsigned int data) 4116ef80706SPavel Hofman { 4126ef80706SPavel Hofman unsigned int tmp; 4136ef80706SPavel Hofman 4146ef80706SPavel Hofman mutex_lock(&ice->gpio_mutex); 4156ef80706SPavel Hofman /* set direction of used GPIOs*/ 4166ef80706SPavel Hofman /* all outputs */ 4176ef80706SPavel Hofman tmp = 0x00ffff; 4186ef80706SPavel Hofman ice->gpio.set_dir(ice, tmp); 4196ef80706SPavel Hofman /* mask - writable bits */ 4206ef80706SPavel Hofman ice->gpio.set_mask(ice, ~(tmp)); 4216ef80706SPavel Hofman /* write the data */ 4226ef80706SPavel Hofman tmp = ice->gpio.get_data(ice); 4236ef80706SPavel Hofman tmp &= ~GPIO_DATA_MASK; 4246ef80706SPavel Hofman tmp |= data; 4256ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 4266ef80706SPavel Hofman udelay(100); 4276ef80706SPavel Hofman /* drop output enable */ 4286ef80706SPavel Hofman tmp &= ~GPIO_EX_GPIOE; 4296ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 4306ef80706SPavel Hofman udelay(100); 4316ef80706SPavel Hofman /* drop the register gpio */ 4326ef80706SPavel Hofman tmp &= ~reg; 4336ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 4346ef80706SPavel Hofman udelay(100); 4356ef80706SPavel Hofman /* raise the register GPIO */ 4366ef80706SPavel Hofman tmp |= reg; 4376ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 4386ef80706SPavel Hofman udelay(100); 4396ef80706SPavel Hofman 4406ef80706SPavel Hofman /* raise all data gpios */ 4416ef80706SPavel Hofman tmp |= GPIO_DATA_MASK; 4426ef80706SPavel Hofman ice->gpio.set_data(ice, tmp); 4436ef80706SPavel Hofman /* mask - immutable bits */ 4446ef80706SPavel Hofman ice->gpio.set_mask(ice, 0xffffff); 4456ef80706SPavel Hofman /* outputs only 8-15 */ 4466ef80706SPavel Hofman ice->gpio.set_dir(ice, 0x00ff00); 4476ef80706SPavel Hofman mutex_unlock(&ice->gpio_mutex); 4486ef80706SPavel Hofman } 4496ef80706SPavel Hofman 4506ef80706SPavel Hofman static unsigned int get_scr(struct snd_ice1712 *ice) 4516ef80706SPavel Hofman { 4526ef80706SPavel Hofman struct qtet_spec *spec = ice->spec; 4536ef80706SPavel Hofman return spec->scr; 4546ef80706SPavel Hofman } 4556ef80706SPavel Hofman 4566ef80706SPavel Hofman static unsigned int get_mcr(struct snd_ice1712 *ice) 4576ef80706SPavel Hofman { 4586ef80706SPavel Hofman struct qtet_spec *spec = ice->spec; 4596ef80706SPavel Hofman return spec->mcr; 4606ef80706SPavel Hofman } 4616ef80706SPavel Hofman 4626ef80706SPavel Hofman static unsigned int get_cpld(struct snd_ice1712 *ice) 4636ef80706SPavel Hofman { 4646ef80706SPavel Hofman struct qtet_spec *spec = ice->spec; 4656ef80706SPavel Hofman return spec->cpld; 4666ef80706SPavel Hofman } 4676ef80706SPavel Hofman 4686ef80706SPavel Hofman static void set_scr(struct snd_ice1712 *ice, unsigned int val) 4696ef80706SPavel Hofman { 4706ef80706SPavel Hofman struct qtet_spec *spec = ice->spec; 4716ef80706SPavel Hofman reg_write(ice, GPIO_SCR, val); 4726ef80706SPavel Hofman spec->scr = val; 4736ef80706SPavel Hofman } 4746ef80706SPavel Hofman 4756ef80706SPavel Hofman static void set_mcr(struct snd_ice1712 *ice, unsigned int val) 4766ef80706SPavel Hofman { 4776ef80706SPavel Hofman struct qtet_spec *spec = ice->spec; 4786ef80706SPavel Hofman reg_write(ice, GPIO_MCR, val); 4796ef80706SPavel Hofman spec->mcr = val; 4806ef80706SPavel Hofman } 4816ef80706SPavel Hofman 4826ef80706SPavel Hofman static void set_cpld(struct snd_ice1712 *ice, unsigned int val) 4836ef80706SPavel Hofman { 4846ef80706SPavel Hofman struct qtet_spec *spec = ice->spec; 4856ef80706SPavel Hofman reg_write(ice, GPIO_CPLD_CSN, val); 4866ef80706SPavel Hofman spec->cpld = val; 4876ef80706SPavel Hofman } 4883270f0ddSTakashi Iwai 4896ef80706SPavel Hofman static void proc_regs_read(struct snd_info_entry *entry, 4906ef80706SPavel Hofman struct snd_info_buffer *buffer) 4916ef80706SPavel Hofman { 4926ef80706SPavel Hofman struct snd_ice1712 *ice = entry->private_data; 4936ef80706SPavel Hofman char bin_buffer[36]; 4946ef80706SPavel Hofman 4956ef80706SPavel Hofman snd_iprintf(buffer, "SCR: %s\n", get_binary(bin_buffer, 4966ef80706SPavel Hofman get_scr(ice))); 4976ef80706SPavel Hofman snd_iprintf(buffer, "MCR: %s\n", get_binary(bin_buffer, 4986ef80706SPavel Hofman get_mcr(ice))); 4996ef80706SPavel Hofman snd_iprintf(buffer, "CPLD: %s\n", get_binary(bin_buffer, 5006ef80706SPavel Hofman get_cpld(ice))); 5016ef80706SPavel Hofman } 5026ef80706SPavel Hofman 5036ef80706SPavel Hofman static void proc_init(struct snd_ice1712 *ice) 5046ef80706SPavel Hofman { 5056ef80706SPavel Hofman struct snd_info_entry *entry; 5066ef80706SPavel Hofman if (!snd_card_proc_new(ice->card, "quartet", &entry)) 5076ef80706SPavel Hofman snd_info_set_text_ops(entry, ice, proc_regs_read); 5086ef80706SPavel Hofman } 5096ef80706SPavel Hofman 5106ef80706SPavel Hofman static int qtet_mute_get(struct snd_kcontrol *kcontrol, 5116ef80706SPavel Hofman struct snd_ctl_elem_value *ucontrol) 5126ef80706SPavel Hofman { 5136ef80706SPavel Hofman struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 5146ef80706SPavel Hofman unsigned int val; 5156ef80706SPavel Hofman val = get_scr(ice) & SCR_MUTE; 5166ef80706SPavel Hofman ucontrol->value.integer.value[0] = (val) ? 0 : 1; 5176ef80706SPavel Hofman return 0; 5186ef80706SPavel Hofman } 5196ef80706SPavel Hofman 5206ef80706SPavel Hofman static int qtet_mute_put(struct snd_kcontrol *kcontrol, 5216ef80706SPavel Hofman struct snd_ctl_elem_value *ucontrol) 5226ef80706SPavel Hofman { 5236ef80706SPavel Hofman struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 5246ef80706SPavel Hofman unsigned int old, new, smute; 5256ef80706SPavel Hofman old = get_scr(ice) & SCR_MUTE; 5266ef80706SPavel Hofman if (ucontrol->value.integer.value[0]) { 5276ef80706SPavel Hofman /* unmute */ 5286ef80706SPavel Hofman new = 0; 5296ef80706SPavel Hofman /* un-smuting DAC */ 5306ef80706SPavel Hofman smute = 0; 5316ef80706SPavel Hofman } else { 5326ef80706SPavel Hofman /* mute */ 5336ef80706SPavel Hofman new = SCR_MUTE; 5346ef80706SPavel Hofman /* smuting DAC */ 5356ef80706SPavel Hofman smute = AK4620_SMUTE; 5366ef80706SPavel Hofman } 5376ef80706SPavel Hofman if (old != new) { 5386ef80706SPavel Hofman struct snd_akm4xxx *ak = ice->akm; 5396ef80706SPavel Hofman set_scr(ice, (get_scr(ice) & ~SCR_MUTE) | new); 5406ef80706SPavel Hofman /* set smute */ 5416ef80706SPavel Hofman qtet_akm_set_regs(ak, AK4620_DEEMVOL_REG, AK4620_SMUTE, smute); 5426ef80706SPavel Hofman return 1; 5436ef80706SPavel Hofman } 5446ef80706SPavel Hofman /* no change */ 5456ef80706SPavel Hofman return 0; 5466ef80706SPavel Hofman } 5476ef80706SPavel Hofman 5486ef80706SPavel Hofman static int qtet_ain12_enum_info(struct snd_kcontrol *kcontrol, 5496ef80706SPavel Hofman struct snd_ctl_elem_info *uinfo) 5506ef80706SPavel Hofman { 551a2af050fSTakashi Iwai static const char * const texts[3] = 552a2af050fSTakashi Iwai {"Line In 1/2", "Mic", "Mic + Low-cut"}; 553597da2e4STakashi Iwai return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts); 5546ef80706SPavel Hofman } 5556ef80706SPavel Hofman 5566ef80706SPavel Hofman static int qtet_ain12_sw_get(struct snd_kcontrol *kcontrol, 5576ef80706SPavel Hofman struct snd_ctl_elem_value *ucontrol) 5586ef80706SPavel Hofman { 5596ef80706SPavel Hofman struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 5606ef80706SPavel Hofman unsigned int val, result; 5616ef80706SPavel Hofman val = get_scr(ice) & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); 5626ef80706SPavel Hofman switch (val) { 5636ef80706SPavel Hofman case SCR_AIN12_LINE: 5646ef80706SPavel Hofman result = 0; 5656ef80706SPavel Hofman break; 5666ef80706SPavel Hofman case SCR_AIN12_MIC: 5676ef80706SPavel Hofman result = 1; 5686ef80706SPavel Hofman break; 5696ef80706SPavel Hofman case SCR_AIN12_LOWCUT: 5706ef80706SPavel Hofman result = 2; 5716ef80706SPavel Hofman break; 5726ef80706SPavel Hofman default: 5736ef80706SPavel Hofman /* BUG - no other combinations allowed */ 5746ef80706SPavel Hofman snd_BUG(); 5756ef80706SPavel Hofman result = 0; 5766ef80706SPavel Hofman } 5776ef80706SPavel Hofman ucontrol->value.integer.value[0] = result; 5786ef80706SPavel Hofman return 0; 5796ef80706SPavel Hofman } 5806ef80706SPavel Hofman 5816ef80706SPavel Hofman static int qtet_ain12_sw_put(struct snd_kcontrol *kcontrol, 5826ef80706SPavel Hofman struct snd_ctl_elem_value *ucontrol) 5836ef80706SPavel Hofman { 5846ef80706SPavel Hofman struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 5856ef80706SPavel Hofman unsigned int old, new, tmp, masked_old; 5866ef80706SPavel Hofman old = new = get_scr(ice); 5876ef80706SPavel Hofman masked_old = old & (SCR_AIN12_SEL1 | SCR_AIN12_SEL0); 5886ef80706SPavel Hofman tmp = ucontrol->value.integer.value[0]; 5896ef80706SPavel Hofman if (tmp == 2) 5906ef80706SPavel Hofman tmp = 3; /* binary 10 is not supported */ 5916ef80706SPavel Hofman tmp <<= 4; /* shifting to SCR_AIN12_SEL0 */ 5926ef80706SPavel Hofman if (tmp != masked_old) { 5936ef80706SPavel Hofman /* change requested */ 5946ef80706SPavel Hofman switch (tmp) { 5956ef80706SPavel Hofman case SCR_AIN12_LINE: 5966ef80706SPavel Hofman new = old & ~(SCR_AIN12_SEL1 | SCR_AIN12_SEL0); 5976ef80706SPavel Hofman set_scr(ice, new); 5986ef80706SPavel Hofman /* turn off relay */ 5996ef80706SPavel Hofman new &= ~SCR_RELAY; 6006ef80706SPavel Hofman set_scr(ice, new); 6016ef80706SPavel Hofman break; 6026ef80706SPavel Hofman case SCR_AIN12_MIC: 6036ef80706SPavel Hofman /* turn on relay */ 6046ef80706SPavel Hofman new = old | SCR_RELAY; 6056ef80706SPavel Hofman set_scr(ice, new); 6066ef80706SPavel Hofman new = (new & ~SCR_AIN12_SEL1) | SCR_AIN12_SEL0; 6076ef80706SPavel Hofman set_scr(ice, new); 6086ef80706SPavel Hofman break; 6096ef80706SPavel Hofman case SCR_AIN12_LOWCUT: 6106ef80706SPavel Hofman /* turn on relay */ 6116ef80706SPavel Hofman new = old | SCR_RELAY; 6126ef80706SPavel Hofman set_scr(ice, new); 6136ef80706SPavel Hofman new |= SCR_AIN12_SEL1 | SCR_AIN12_SEL0; 6146ef80706SPavel Hofman set_scr(ice, new); 6156ef80706SPavel Hofman break; 6166ef80706SPavel Hofman default: 6176ef80706SPavel Hofman snd_BUG(); 6186ef80706SPavel Hofman } 6196ef80706SPavel Hofman return 1; 6206ef80706SPavel Hofman } 6216ef80706SPavel Hofman /* no change */ 6226ef80706SPavel Hofman return 0; 6236ef80706SPavel Hofman } 6246ef80706SPavel Hofman 6256ef80706SPavel Hofman static int qtet_php_get(struct snd_kcontrol *kcontrol, 6266ef80706SPavel Hofman struct snd_ctl_elem_value *ucontrol) 6276ef80706SPavel Hofman { 6286ef80706SPavel Hofman struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 6296ef80706SPavel Hofman unsigned int val; 6306ef80706SPavel Hofman /* if phantom voltage =48V, phantom on */ 6316ef80706SPavel Hofman val = get_scr(ice) & SCR_PHP_V; 6326ef80706SPavel Hofman ucontrol->value.integer.value[0] = val ? 1 : 0; 6336ef80706SPavel Hofman return 0; 6346ef80706SPavel Hofman } 6356ef80706SPavel Hofman 6366ef80706SPavel Hofman static int qtet_php_put(struct snd_kcontrol *kcontrol, 6376ef80706SPavel Hofman struct snd_ctl_elem_value *ucontrol) 6386ef80706SPavel Hofman { 6396ef80706SPavel Hofman struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 6406ef80706SPavel Hofman unsigned int old, new; 6416ef80706SPavel Hofman old = new = get_scr(ice); 6426ef80706SPavel Hofman if (ucontrol->value.integer.value[0] /* phantom on requested */ 6436ef80706SPavel Hofman && (~old & SCR_PHP_V)) /* 0 = voltage 5V */ { 6446ef80706SPavel Hofman /* is off, turn on */ 6456ef80706SPavel Hofman /* turn voltage on first, = 1 */ 6466ef80706SPavel Hofman new = old | SCR_PHP_V; 6476ef80706SPavel Hofman set_scr(ice, new); 6486ef80706SPavel Hofman /* turn phantom on, = 0 */ 6496ef80706SPavel Hofman new &= ~SCR_PHP; 6506ef80706SPavel Hofman set_scr(ice, new); 6516ef80706SPavel Hofman } else if (!ucontrol->value.integer.value[0] && (old & SCR_PHP_V)) { 6526ef80706SPavel Hofman /* phantom off requested and 1 = voltage 48V */ 6536ef80706SPavel Hofman /* is on, turn off */ 6546ef80706SPavel Hofman /* turn voltage off first, = 0 */ 6556ef80706SPavel Hofman new = old & ~SCR_PHP_V; 6566ef80706SPavel Hofman set_scr(ice, new); 6576ef80706SPavel Hofman /* turn phantom off, = 1 */ 6586ef80706SPavel Hofman new |= SCR_PHP; 6596ef80706SPavel Hofman set_scr(ice, new); 6606ef80706SPavel Hofman } 6616ef80706SPavel Hofman if (old != new) 6626ef80706SPavel Hofman return 1; 6636ef80706SPavel Hofman /* no change */ 6646ef80706SPavel Hofman return 0; 6656ef80706SPavel Hofman } 6666ef80706SPavel Hofman 6676ef80706SPavel Hofman #define PRIV_SW(xid, xbit, xreg) [xid] = {.bit = xbit,\ 6686ef80706SPavel Hofman .set_register = set_##xreg,\ 6696ef80706SPavel Hofman .get_register = get_##xreg, } 6706ef80706SPavel Hofman 6716ef80706SPavel Hofman 6726ef80706SPavel Hofman #define PRIV_ENUM2(xid, xbit, xreg, xtext1, xtext2) [xid] = {.bit = xbit,\ 6736ef80706SPavel Hofman .set_register = set_##xreg,\ 6746ef80706SPavel Hofman .get_register = get_##xreg,\ 6756ef80706SPavel Hofman .texts = {xtext1, xtext2} } 6766ef80706SPavel Hofman 6776ef80706SPavel Hofman static struct qtet_kcontrol_private qtet_privates[] = { 6786ef80706SPavel Hofman PRIV_ENUM2(IN12_SEL, CPLD_IN12_SEL, cpld, "An In 1/2", "An In 3/4"), 6796ef80706SPavel Hofman PRIV_ENUM2(IN34_SEL, CPLD_IN34_SEL, cpld, "An In 3/4", "IEC958 In"), 6806ef80706SPavel Hofman PRIV_ENUM2(AIN34_SEL, SCR_AIN34_SEL, scr, "Line In 3/4", "Hi-Z"), 6816ef80706SPavel Hofman PRIV_ENUM2(COAX_OUT, CPLD_COAX_OUT, cpld, "IEC958", "I2S"), 6826ef80706SPavel Hofman PRIV_SW(IN12_MON12, MCR_IN12_MON12, mcr), 6836ef80706SPavel Hofman PRIV_SW(IN12_MON34, MCR_IN12_MON34, mcr), 6846ef80706SPavel Hofman PRIV_SW(IN34_MON12, MCR_IN34_MON12, mcr), 6856ef80706SPavel Hofman PRIV_SW(IN34_MON34, MCR_IN34_MON34, mcr), 6866ef80706SPavel Hofman PRIV_SW(OUT12_MON34, MCR_OUT12_MON34, mcr), 6876ef80706SPavel Hofman PRIV_SW(OUT34_MON12, MCR_OUT34_MON12, mcr), 6886ef80706SPavel Hofman }; 6896ef80706SPavel Hofman 6906ef80706SPavel Hofman static int qtet_enum_info(struct snd_kcontrol *kcontrol, 6916ef80706SPavel Hofman struct snd_ctl_elem_info *uinfo) 6926ef80706SPavel Hofman { 6936ef80706SPavel Hofman struct qtet_kcontrol_private private = 6946ef80706SPavel Hofman qtet_privates[kcontrol->private_value]; 695597da2e4STakashi Iwai return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(private.texts), 696597da2e4STakashi Iwai private.texts); 6976ef80706SPavel Hofman } 6986ef80706SPavel Hofman 6996ef80706SPavel Hofman static int qtet_sw_get(struct snd_kcontrol *kcontrol, 7006ef80706SPavel Hofman struct snd_ctl_elem_value *ucontrol) 7016ef80706SPavel Hofman { 7026ef80706SPavel Hofman struct qtet_kcontrol_private private = 7036ef80706SPavel Hofman qtet_privates[kcontrol->private_value]; 7046ef80706SPavel Hofman struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 7056ef80706SPavel Hofman ucontrol->value.integer.value[0] = 7066ef80706SPavel Hofman (private.get_register(ice) & private.bit) ? 1 : 0; 7076ef80706SPavel Hofman return 0; 7086ef80706SPavel Hofman } 7096ef80706SPavel Hofman 7106ef80706SPavel Hofman static int qtet_sw_put(struct snd_kcontrol *kcontrol, 7116ef80706SPavel Hofman struct snd_ctl_elem_value *ucontrol) 7126ef80706SPavel Hofman { 7136ef80706SPavel Hofman struct qtet_kcontrol_private private = 7146ef80706SPavel Hofman qtet_privates[kcontrol->private_value]; 7156ef80706SPavel Hofman struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 7166ef80706SPavel Hofman unsigned int old, new; 7176ef80706SPavel Hofman old = private.get_register(ice); 7186ef80706SPavel Hofman if (ucontrol->value.integer.value[0]) 7196ef80706SPavel Hofman new = old | private.bit; 7206ef80706SPavel Hofman else 7216ef80706SPavel Hofman new = old & ~private.bit; 7226ef80706SPavel Hofman if (old != new) { 7236ef80706SPavel Hofman private.set_register(ice, new); 7246ef80706SPavel Hofman return 1; 7256ef80706SPavel Hofman } 7266ef80706SPavel Hofman /* no change */ 7276ef80706SPavel Hofman return 0; 7286ef80706SPavel Hofman } 7296ef80706SPavel Hofman 7306ef80706SPavel Hofman #define qtet_sw_info snd_ctl_boolean_mono_info 7316ef80706SPavel Hofman 7326ef80706SPavel Hofman #define QTET_CONTROL(xname, xtype, xpriv) \ 7336ef80706SPavel Hofman {.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ 7346ef80706SPavel Hofman .name = xname,\ 7356ef80706SPavel Hofman .info = qtet_##xtype##_info,\ 7366ef80706SPavel Hofman .get = qtet_sw_get,\ 7376ef80706SPavel Hofman .put = qtet_sw_put,\ 7386ef80706SPavel Hofman .private_value = xpriv } 7396ef80706SPavel Hofman 740e23e7a14SBill Pemberton static struct snd_kcontrol_new qtet_controls[] = { 7416ef80706SPavel Hofman { 7426ef80706SPavel Hofman .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 7436ef80706SPavel Hofman .name = "Master Playback Switch", 7446ef80706SPavel Hofman .info = qtet_sw_info, 7456ef80706SPavel Hofman .get = qtet_mute_get, 7466ef80706SPavel Hofman .put = qtet_mute_put, 7476ef80706SPavel Hofman .private_value = 0 7486ef80706SPavel Hofman }, 7496ef80706SPavel Hofman { 7506ef80706SPavel Hofman .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 7516ef80706SPavel Hofman .name = "Phantom Power", 7526ef80706SPavel Hofman .info = qtet_sw_info, 7536ef80706SPavel Hofman .get = qtet_php_get, 7546ef80706SPavel Hofman .put = qtet_php_put, 7556ef80706SPavel Hofman .private_value = 0 7566ef80706SPavel Hofman }, 7576ef80706SPavel Hofman { 7586ef80706SPavel Hofman .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 7596ef80706SPavel Hofman .name = "Analog In 1/2 Capture Switch", 7606ef80706SPavel Hofman .info = qtet_ain12_enum_info, 7616ef80706SPavel Hofman .get = qtet_ain12_sw_get, 7626ef80706SPavel Hofman .put = qtet_ain12_sw_put, 7636ef80706SPavel Hofman .private_value = 0 7646ef80706SPavel Hofman }, 7656ef80706SPavel Hofman QTET_CONTROL("Analog In 3/4 Capture Switch", enum, AIN34_SEL), 7666ef80706SPavel Hofman QTET_CONTROL("PCM In 1/2 Capture Switch", enum, IN12_SEL), 7676ef80706SPavel Hofman QTET_CONTROL("PCM In 3/4 Capture Switch", enum, IN34_SEL), 7686ef80706SPavel Hofman QTET_CONTROL("Coax Output Source", enum, COAX_OUT), 7696ef80706SPavel Hofman QTET_CONTROL("Analog In 1/2 to Monitor 1/2", sw, IN12_MON12), 7706ef80706SPavel Hofman QTET_CONTROL("Analog In 1/2 to Monitor 3/4", sw, IN12_MON34), 7716ef80706SPavel Hofman QTET_CONTROL("Analog In 3/4 to Monitor 1/2", sw, IN34_MON12), 7726ef80706SPavel Hofman QTET_CONTROL("Analog In 3/4 to Monitor 3/4", sw, IN34_MON34), 7736ef80706SPavel Hofman QTET_CONTROL("Output 1/2 to Monitor 3/4", sw, OUT12_MON34), 7746ef80706SPavel Hofman QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12), 7756ef80706SPavel Hofman }; 7766ef80706SPavel Hofman 777e23e7a14SBill Pemberton static char *slave_vols[] = { 7786ef80706SPavel Hofman PCM_12_PLAYBACK_VOLUME, 7796ef80706SPavel Hofman PCM_34_PLAYBACK_VOLUME, 7806ef80706SPavel Hofman NULL 7816ef80706SPavel Hofman }; 7826ef80706SPavel Hofman 783e23e7a14SBill Pemberton static 7846ef80706SPavel Hofman DECLARE_TLV_DB_SCALE(qtet_master_db_scale, -6350, 50, 1); 7856ef80706SPavel Hofman 786e23e7a14SBill Pemberton static struct snd_kcontrol *ctl_find(struct snd_card *card, 7876ef80706SPavel Hofman const char *name) 7886ef80706SPavel Hofman { 789*338e17d3SJoey Pabalinas struct snd_ctl_elem_id sid = {0}; 790*338e17d3SJoey Pabalinas 791*338e17d3SJoey Pabalinas strlcpy(sid.name, name, sizeof(sid.name)); 7926ef80706SPavel Hofman sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 7936ef80706SPavel Hofman return snd_ctl_find_id(card, &sid); 7946ef80706SPavel Hofman } 7956ef80706SPavel Hofman 796e23e7a14SBill Pemberton static void add_slaves(struct snd_card *card, 797a2af050fSTakashi Iwai struct snd_kcontrol *master, char * const *list) 7986ef80706SPavel Hofman { 7996ef80706SPavel Hofman for (; *list; list++) { 8006ef80706SPavel Hofman struct snd_kcontrol *slave = ctl_find(card, *list); 8016ef80706SPavel Hofman if (slave) 8026ef80706SPavel Hofman snd_ctl_add_slave(master, slave); 8036ef80706SPavel Hofman } 8046ef80706SPavel Hofman } 8056ef80706SPavel Hofman 806e23e7a14SBill Pemberton static int qtet_add_controls(struct snd_ice1712 *ice) 8076ef80706SPavel Hofman { 8086ef80706SPavel Hofman struct qtet_spec *spec = ice->spec; 8096ef80706SPavel Hofman int err, i; 8106ef80706SPavel Hofman struct snd_kcontrol *vmaster; 8116ef80706SPavel Hofman err = snd_ice1712_akm4xxx_build_controls(ice); 8126ef80706SPavel Hofman if (err < 0) 8136ef80706SPavel Hofman return err; 8146ef80706SPavel Hofman for (i = 0; i < ARRAY_SIZE(qtet_controls); i++) { 8156ef80706SPavel Hofman err = snd_ctl_add(ice->card, 8166ef80706SPavel Hofman snd_ctl_new1(&qtet_controls[i], ice)); 8176ef80706SPavel Hofman if (err < 0) 8186ef80706SPavel Hofman return err; 8196ef80706SPavel Hofman } 8206ef80706SPavel Hofman 8216ef80706SPavel Hofman /* Create virtual master control */ 8226ef80706SPavel Hofman vmaster = snd_ctl_make_virtual_master("Master Playback Volume", 8236ef80706SPavel Hofman qtet_master_db_scale); 8246ef80706SPavel Hofman if (!vmaster) 8256ef80706SPavel Hofman return -ENOMEM; 8266ef80706SPavel Hofman add_slaves(ice->card, vmaster, slave_vols); 8276ef80706SPavel Hofman err = snd_ctl_add(ice->card, vmaster); 8286ef80706SPavel Hofman if (err < 0) 8296ef80706SPavel Hofman return err; 8306ef80706SPavel Hofman /* only capture SPDIF over AK4113 */ 831387417b5SSudip Mukherjee return snd_ak4113_build(spec->ak4113, 8326ef80706SPavel Hofman ice->pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream); 8336ef80706SPavel Hofman } 8346ef80706SPavel Hofman 8356ef80706SPavel Hofman static inline int qtet_is_spdif_master(struct snd_ice1712 *ice) 8366ef80706SPavel Hofman { 8376ef80706SPavel Hofman /* CPLD_SYNC_SEL: 0 = internal, 1 = external (i.e. spdif master) */ 8386ef80706SPavel Hofman return (get_cpld(ice) & CPLD_SYNC_SEL) ? 1 : 0; 8396ef80706SPavel Hofman } 8406ef80706SPavel Hofman 8416ef80706SPavel Hofman static unsigned int qtet_get_rate(struct snd_ice1712 *ice) 8426ef80706SPavel Hofman { 8436ef80706SPavel Hofman int i; 8446ef80706SPavel Hofman unsigned char result; 8456ef80706SPavel Hofman 8466ef80706SPavel Hofman result = get_cpld(ice) & CPLD_CKS_MASK; 8476ef80706SPavel Hofman for (i = 0; i < ARRAY_SIZE(cks_vals); i++) 8486ef80706SPavel Hofman if (cks_vals[i] == result) 8496ef80706SPavel Hofman return qtet_rates[i]; 8506ef80706SPavel Hofman return 0; 8516ef80706SPavel Hofman } 8526ef80706SPavel Hofman 8536ef80706SPavel Hofman static int get_cks_val(int rate) 8546ef80706SPavel Hofman { 8556ef80706SPavel Hofman int i; 8566ef80706SPavel Hofman for (i = 0; i < ARRAY_SIZE(qtet_rates); i++) 8576ef80706SPavel Hofman if (qtet_rates[i] == rate) 8586ef80706SPavel Hofman return cks_vals[i]; 8596ef80706SPavel Hofman return 0; 8606ef80706SPavel Hofman } 8616ef80706SPavel Hofman 8626ef80706SPavel Hofman /* setting new rate */ 8636ef80706SPavel Hofman static void qtet_set_rate(struct snd_ice1712 *ice, unsigned int rate) 8646ef80706SPavel Hofman { 8656ef80706SPavel Hofman unsigned int new; 8666ef80706SPavel Hofman unsigned char val; 8676ef80706SPavel Hofman /* switching ice1724 to external clock - supplied by ext. circuits */ 8686ef80706SPavel Hofman val = inb(ICEMT1724(ice, RATE)); 8696ef80706SPavel Hofman outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); 8706ef80706SPavel Hofman 8716ef80706SPavel Hofman new = (get_cpld(ice) & ~CPLD_CKS_MASK) | get_cks_val(rate); 8726ef80706SPavel Hofman /* switch to internal clock, drop CPLD_SYNC_SEL */ 8736ef80706SPavel Hofman new &= ~CPLD_SYNC_SEL; 8746dfb5affSTakashi Iwai /* dev_dbg(ice->card->dev, "QT - set_rate: old %x, new %x\n", 8756ef80706SPavel Hofman get_cpld(ice), new); */ 8766ef80706SPavel Hofman set_cpld(ice, new); 8776ef80706SPavel Hofman } 8786ef80706SPavel Hofman 8796ef80706SPavel Hofman static inline unsigned char qtet_set_mclk(struct snd_ice1712 *ice, 8806ef80706SPavel Hofman unsigned int rate) 8816ef80706SPavel Hofman { 8826ef80706SPavel Hofman /* no change in master clock */ 8836ef80706SPavel Hofman return 0; 8846ef80706SPavel Hofman } 8856ef80706SPavel Hofman 8866ef80706SPavel Hofman /* setting clock to external - SPDIF */ 8876ef80706SPavel Hofman static int qtet_set_spdif_clock(struct snd_ice1712 *ice, int type) 8886ef80706SPavel Hofman { 8896ef80706SPavel Hofman unsigned int old, new; 8906ef80706SPavel Hofman 8916ef80706SPavel Hofman old = new = get_cpld(ice); 8926ef80706SPavel Hofman new &= ~(CPLD_CKS_MASK | CPLD_WORD_SEL); 8936ef80706SPavel Hofman switch (type) { 8946ef80706SPavel Hofman case EXT_SPDIF_TYPE: 8956ef80706SPavel Hofman new |= CPLD_EXT_SPDIF; 8966ef80706SPavel Hofman break; 8976ef80706SPavel Hofman case EXT_WORDCLOCK_1FS_TYPE: 8986ef80706SPavel Hofman new |= CPLD_EXT_WORDCLOCK_1FS; 8996ef80706SPavel Hofman break; 9006ef80706SPavel Hofman case EXT_WORDCLOCK_256FS_TYPE: 9016ef80706SPavel Hofman new |= CPLD_EXT_WORDCLOCK_256FS; 9026ef80706SPavel Hofman break; 9036ef80706SPavel Hofman default: 9046ef80706SPavel Hofman snd_BUG(); 9056ef80706SPavel Hofman } 9066ef80706SPavel Hofman if (old != new) { 9076ef80706SPavel Hofman set_cpld(ice, new); 9086ef80706SPavel Hofman /* changed */ 9096ef80706SPavel Hofman return 1; 9106ef80706SPavel Hofman } 9116ef80706SPavel Hofman return 0; 9126ef80706SPavel Hofman } 9136ef80706SPavel Hofman 9146ef80706SPavel Hofman static int qtet_get_spdif_master_type(struct snd_ice1712 *ice) 9156ef80706SPavel Hofman { 9166ef80706SPavel Hofman unsigned int val; 9176ef80706SPavel Hofman int result; 9186ef80706SPavel Hofman val = get_cpld(ice); 9196ef80706SPavel Hofman /* checking only rate/clock-related bits */ 9206ef80706SPavel Hofman val &= (CPLD_CKS_MASK | CPLD_WORD_SEL | CPLD_SYNC_SEL); 9216ef80706SPavel Hofman if (!(val & CPLD_SYNC_SEL)) { 9226ef80706SPavel Hofman /* switched to internal clock, is not any external type */ 9236ef80706SPavel Hofman result = -1; 9246ef80706SPavel Hofman } else { 9256ef80706SPavel Hofman switch (val) { 9266ef80706SPavel Hofman case (CPLD_EXT_SPDIF): 9276ef80706SPavel Hofman result = EXT_SPDIF_TYPE; 9286ef80706SPavel Hofman break; 9296ef80706SPavel Hofman case (CPLD_EXT_WORDCLOCK_1FS): 9306ef80706SPavel Hofman result = EXT_WORDCLOCK_1FS_TYPE; 9316ef80706SPavel Hofman break; 9326ef80706SPavel Hofman case (CPLD_EXT_WORDCLOCK_256FS): 9336ef80706SPavel Hofman result = EXT_WORDCLOCK_256FS_TYPE; 9346ef80706SPavel Hofman break; 9356ef80706SPavel Hofman default: 9366ef80706SPavel Hofman /* undefined combination of external clock setup */ 9376ef80706SPavel Hofman snd_BUG(); 9386ef80706SPavel Hofman result = 0; 9396ef80706SPavel Hofman } 9406ef80706SPavel Hofman } 9416ef80706SPavel Hofman return result; 9426ef80706SPavel Hofman } 9436ef80706SPavel Hofman 9446ef80706SPavel Hofman /* Called when ak4113 detects change in the input SPDIF stream */ 9456ef80706SPavel Hofman static void qtet_ak4113_change(struct ak4113 *ak4113, unsigned char c0, 9466ef80706SPavel Hofman unsigned char c1) 9476ef80706SPavel Hofman { 9486ef80706SPavel Hofman struct snd_ice1712 *ice = ak4113->change_callback_private; 9496ef80706SPavel Hofman int rate; 9506ef80706SPavel Hofman if ((qtet_get_spdif_master_type(ice) == EXT_SPDIF_TYPE) && 9516ef80706SPavel Hofman c1) { 9526ef80706SPavel Hofman /* only for SPDIF master mode, rate was changed */ 9536ef80706SPavel Hofman rate = snd_ak4113_external_rate(ak4113); 9546dfb5affSTakashi Iwai /* dev_dbg(ice->card->dev, "ak4113 - input rate changed to %d\n", 9556ef80706SPavel Hofman rate); */ 9566ef80706SPavel Hofman qtet_akm_set_rate_val(ice->akm, rate); 9576ef80706SPavel Hofman } 9586ef80706SPavel Hofman } 9596ef80706SPavel Hofman 9606ef80706SPavel Hofman /* 9616ef80706SPavel Hofman * If clock slaved to SPDIF-IN, setting runtime rate 9626ef80706SPavel Hofman * to the detected external rate 9636ef80706SPavel Hofman */ 9646ef80706SPavel Hofman static void qtet_spdif_in_open(struct snd_ice1712 *ice, 9656ef80706SPavel Hofman struct snd_pcm_substream *substream) 9666ef80706SPavel Hofman { 9676ef80706SPavel Hofman struct qtet_spec *spec = ice->spec; 9686ef80706SPavel Hofman struct snd_pcm_runtime *runtime = substream->runtime; 9696ef80706SPavel Hofman int rate; 9706ef80706SPavel Hofman 9716ef80706SPavel Hofman if (qtet_get_spdif_master_type(ice) != EXT_SPDIF_TYPE) 9726ef80706SPavel Hofman /* not external SPDIF, no rate limitation */ 9736ef80706SPavel Hofman return; 9746ef80706SPavel Hofman /* only external SPDIF can detect incoming sample rate */ 9756ef80706SPavel Hofman rate = snd_ak4113_external_rate(spec->ak4113); 9766ef80706SPavel Hofman if (rate >= runtime->hw.rate_min && rate <= runtime->hw.rate_max) { 9776ef80706SPavel Hofman runtime->hw.rate_min = rate; 9786ef80706SPavel Hofman runtime->hw.rate_max = rate; 9796ef80706SPavel Hofman } 9806ef80706SPavel Hofman } 9816ef80706SPavel Hofman 9826ef80706SPavel Hofman /* 9836ef80706SPavel Hofman * initialize the chip 9846ef80706SPavel Hofman */ 985e23e7a14SBill Pemberton static int qtet_init(struct snd_ice1712 *ice) 9866ef80706SPavel Hofman { 9876ef80706SPavel Hofman static const unsigned char ak4113_init_vals[] = { 9886ef80706SPavel Hofman /* AK4113_REG_PWRDN */ AK4113_RST | AK4113_PWN | 9896ef80706SPavel Hofman AK4113_OCKS0 | AK4113_OCKS1, 9906ef80706SPavel Hofman /* AK4113_REQ_FORMAT */ AK4113_DIF_I24I2S | AK4113_VTX | 9916ef80706SPavel Hofman AK4113_DEM_OFF | AK4113_DEAU, 9926ef80706SPavel Hofman /* AK4113_REG_IO0 */ AK4113_OPS2 | AK4113_TXE | 9936ef80706SPavel Hofman AK4113_XTL_24_576M, 9946ef80706SPavel Hofman /* AK4113_REG_IO1 */ AK4113_EFH_1024LRCLK | AK4113_IPS(0), 9956ef80706SPavel Hofman /* AK4113_REG_INT0_MASK */ 0, 9966ef80706SPavel Hofman /* AK4113_REG_INT1_MASK */ 0, 9976ef80706SPavel Hofman /* AK4113_REG_DATDTS */ 0, 9986ef80706SPavel Hofman }; 9996ef80706SPavel Hofman int err; 10006ef80706SPavel Hofman struct qtet_spec *spec; 10016ef80706SPavel Hofman struct snd_akm4xxx *ak; 10026ef80706SPavel Hofman unsigned char val; 10036ef80706SPavel Hofman 10046ef80706SPavel Hofman /* switching ice1724 to external clock - supplied by ext. circuits */ 10056ef80706SPavel Hofman val = inb(ICEMT1724(ice, RATE)); 10066ef80706SPavel Hofman outb(val | VT1724_SPDIF_MASTER, ICEMT1724(ice, RATE)); 10076ef80706SPavel Hofman 10086ef80706SPavel Hofman spec = kzalloc(sizeof(*spec), GFP_KERNEL); 10096ef80706SPavel Hofman if (!spec) 10106ef80706SPavel Hofman return -ENOMEM; 10116ef80706SPavel Hofman /* qtet is clocked by Xilinx array */ 10126ef80706SPavel Hofman ice->hw_rates = &qtet_rates_info; 10136ef80706SPavel Hofman ice->is_spdif_master = qtet_is_spdif_master; 10146ef80706SPavel Hofman ice->get_rate = qtet_get_rate; 10156ef80706SPavel Hofman ice->set_rate = qtet_set_rate; 10166ef80706SPavel Hofman ice->set_mclk = qtet_set_mclk; 10176ef80706SPavel Hofman ice->set_spdif_clock = qtet_set_spdif_clock; 10186ef80706SPavel Hofman ice->get_spdif_master_type = qtet_get_spdif_master_type; 10196ef80706SPavel Hofman ice->ext_clock_names = ext_clock_names; 10206ef80706SPavel Hofman ice->ext_clock_count = ARRAY_SIZE(ext_clock_names); 10216ef80706SPavel Hofman /* since Qtet can detect correct SPDIF-in rate, all streams can be 10226ef80706SPavel Hofman * limited to this specific rate */ 10236ef80706SPavel Hofman ice->spdif.ops.open = ice->pro_open = qtet_spdif_in_open; 10246ef80706SPavel Hofman ice->spec = spec; 10256ef80706SPavel Hofman 10266ef80706SPavel Hofman /* Mute Off */ 10276ef80706SPavel Hofman /* SCR Initialize*/ 10286ef80706SPavel Hofman /* keep codec power down first */ 10296ef80706SPavel Hofman set_scr(ice, SCR_PHP); 10306ef80706SPavel Hofman udelay(1); 10316ef80706SPavel Hofman /* codec power up */ 10326ef80706SPavel Hofman set_scr(ice, SCR_PHP | SCR_CODEC_PDN); 10336ef80706SPavel Hofman 10346ef80706SPavel Hofman /* MCR Initialize */ 10356ef80706SPavel Hofman set_mcr(ice, 0); 10366ef80706SPavel Hofman 10376ef80706SPavel Hofman /* CPLD Initialize */ 10386ef80706SPavel Hofman set_cpld(ice, 0); 10396ef80706SPavel Hofman 10406ef80706SPavel Hofman 10416ef80706SPavel Hofman ice->num_total_dacs = 2; 10426ef80706SPavel Hofman ice->num_total_adcs = 2; 10436ef80706SPavel Hofman 10446ef80706SPavel Hofman ice->akm = kcalloc(2, sizeof(struct snd_akm4xxx), GFP_KERNEL); 10456ef80706SPavel Hofman ak = ice->akm; 10466ef80706SPavel Hofman if (!ak) 10476ef80706SPavel Hofman return -ENOMEM; 10486ef80706SPavel Hofman /* only one codec with two chips */ 10496ef80706SPavel Hofman ice->akm_codecs = 1; 10506ef80706SPavel Hofman err = snd_ice1712_akm4xxx_init(ak, &akm_qtet_dac, NULL, ice); 10516ef80706SPavel Hofman if (err < 0) 10526ef80706SPavel Hofman return err; 10536ef80706SPavel Hofman err = snd_ak4113_create(ice->card, 10546ef80706SPavel Hofman qtet_ak4113_read, 10556ef80706SPavel Hofman qtet_ak4113_write, 10566ef80706SPavel Hofman ak4113_init_vals, 10576ef80706SPavel Hofman ice, &spec->ak4113); 10586ef80706SPavel Hofman if (err < 0) 10596ef80706SPavel Hofman return err; 10606ef80706SPavel Hofman /* callback for codecs rate setting */ 10616ef80706SPavel Hofman spec->ak4113->change_callback = qtet_ak4113_change; 10626ef80706SPavel Hofman spec->ak4113->change_callback_private = ice; 10636ef80706SPavel Hofman /* AK41143 in Quartet can detect external rate correctly 10646ef80706SPavel Hofman * (i.e. check_flags = 0) */ 10656ef80706SPavel Hofman spec->ak4113->check_flags = 0; 10666ef80706SPavel Hofman 10676ef80706SPavel Hofman proc_init(ice); 10686ef80706SPavel Hofman 10696ef80706SPavel Hofman qtet_set_rate(ice, 44100); 10706ef80706SPavel Hofman return 0; 10716ef80706SPavel Hofman } 10726ef80706SPavel Hofman 1073e23e7a14SBill Pemberton static unsigned char qtet_eeprom[] = { 10746ef80706SPavel Hofman [ICE_EEP2_SYSCONF] = 0x28, /* clock 256(24MHz), mpu401, 1xADC, 10756ef80706SPavel Hofman 1xDACs, SPDIF in */ 10766ef80706SPavel Hofman [ICE_EEP2_ACLINK] = 0x80, /* I2S */ 10776ef80706SPavel Hofman [ICE_EEP2_I2S] = 0x78, /* 96k, 24bit, 192k */ 10786ef80706SPavel Hofman [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, in, out-ext */ 10796ef80706SPavel Hofman [ICE_EEP2_GPIO_DIR] = 0x00, /* 0-7 inputs, switched to output 10806ef80706SPavel Hofman only during output operations */ 10816ef80706SPavel Hofman [ICE_EEP2_GPIO_DIR1] = 0xff, /* 8-15 outputs */ 10826ef80706SPavel Hofman [ICE_EEP2_GPIO_DIR2] = 0x00, 10836ef80706SPavel Hofman [ICE_EEP2_GPIO_MASK] = 0xff, /* changed only for OUT operations */ 10846ef80706SPavel Hofman [ICE_EEP2_GPIO_MASK1] = 0x00, 10856ef80706SPavel Hofman [ICE_EEP2_GPIO_MASK2] = 0xff, 10866ef80706SPavel Hofman 10876ef80706SPavel Hofman [ICE_EEP2_GPIO_STATE] = 0x00, /* inputs */ 10886ef80706SPavel Hofman [ICE_EEP2_GPIO_STATE1] = 0x7d, /* all 1, but GPIO_CPLD_RW 10896ef80706SPavel Hofman and GPIO15 always zero */ 10906ef80706SPavel Hofman [ICE_EEP2_GPIO_STATE2] = 0x00, /* inputs */ 10916ef80706SPavel Hofman }; 10926ef80706SPavel Hofman 10936ef80706SPavel Hofman /* entry point */ 1094e23e7a14SBill Pemberton struct snd_ice1712_card_info snd_vt1724_qtet_cards[] = { 10956ef80706SPavel Hofman { 10966ef80706SPavel Hofman .subvendor = VT1724_SUBDEVICE_QTET, 10976ef80706SPavel Hofman .name = "Infrasonic Quartet", 10986ef80706SPavel Hofman .model = "quartet", 10996ef80706SPavel Hofman .chip_init = qtet_init, 11006ef80706SPavel Hofman .build_controls = qtet_add_controls, 11016ef80706SPavel Hofman .eeprom_size = sizeof(qtet_eeprom), 11026ef80706SPavel Hofman .eeprom_data = qtet_eeprom, 11036ef80706SPavel Hofman }, 11046ef80706SPavel Hofman { } /* terminator */ 11056ef80706SPavel Hofman }; 1106