11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright (c) by Jaroslav Kysela <perex@suse.cz>, 31da177e4SLinus Torvalds * Takashi Iwai <tiwai@suse.de> 41da177e4SLinus Torvalds * Creative Labs, Inc. 51da177e4SLinus Torvalds * Routines for control of EMU10K1 chips / mixer routines 61da177e4SLinus Torvalds * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> 71da177e4SLinus Torvalds * 89f4bd5ddSJames Courtier-Dutton * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk> 99f4bd5ddSJames Courtier-Dutton * Added EMU 1010 support. 109f4bd5ddSJames Courtier-Dutton * 111da177e4SLinus Torvalds * BUGS: 121da177e4SLinus Torvalds * -- 131da177e4SLinus Torvalds * 141da177e4SLinus Torvalds * TODO: 151da177e4SLinus Torvalds * -- 161da177e4SLinus Torvalds * 171da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or modify 181da177e4SLinus Torvalds * it under the terms of the GNU General Public License as published by 191da177e4SLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 201da177e4SLinus Torvalds * (at your option) any later version. 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * This program is distributed in the hope that it will be useful, 231da177e4SLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 241da177e4SLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 251da177e4SLinus Torvalds * GNU General Public License for more details. 261da177e4SLinus Torvalds * 271da177e4SLinus Torvalds * You should have received a copy of the GNU General Public License 281da177e4SLinus Torvalds * along with this program; if not, write to the Free Software 291da177e4SLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 301da177e4SLinus Torvalds * 311da177e4SLinus Torvalds */ 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds #include <sound/driver.h> 341da177e4SLinus Torvalds #include <linux/time.h> 351da177e4SLinus Torvalds #include <linux/init.h> 361da177e4SLinus Torvalds #include <sound/core.h> 371da177e4SLinus Torvalds #include <sound/emu10k1.h> 38b0dbdaeaSJames Courtier-Dutton #include <linux/delay.h> 39184c1e2cSJames Courtier-Dutton #include <sound/tlv.h> 40184c1e2cSJames Courtier-Dutton 41184c1e2cSJames Courtier-Dutton #include "p17v.h" 421da177e4SLinus Torvalds 431da177e4SLinus Torvalds #define AC97_ID_STAC9758 0x83847658 441da177e4SLinus Torvalds 450cb29ea0STakashi Iwai static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */ 46184c1e2cSJames Courtier-Dutton 47eb4698f3STakashi Iwai static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 481da177e4SLinus Torvalds { 491da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 501da177e4SLinus Torvalds uinfo->count = 1; 511da177e4SLinus Torvalds return 0; 521da177e4SLinus Torvalds } 531da177e4SLinus Torvalds 54eb4698f3STakashi Iwai static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol, 55eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 561da177e4SLinus Torvalds { 57eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 581da177e4SLinus Torvalds unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 591da177e4SLinus Torvalds unsigned long flags; 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 621da177e4SLinus Torvalds ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; 631da177e4SLinus Torvalds ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; 641da177e4SLinus Torvalds ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; 651da177e4SLinus Torvalds ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; 661da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 671da177e4SLinus Torvalds return 0; 681da177e4SLinus Torvalds } 691da177e4SLinus Torvalds 70eb4698f3STakashi Iwai static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol, 71eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 721da177e4SLinus Torvalds { 731da177e4SLinus Torvalds ucontrol->value.iec958.status[0] = 0xff; 741da177e4SLinus Torvalds ucontrol->value.iec958.status[1] = 0xff; 751da177e4SLinus Torvalds ucontrol->value.iec958.status[2] = 0xff; 761da177e4SLinus Torvalds ucontrol->value.iec958.status[3] = 0xff; 771da177e4SLinus Torvalds return 0; 781da177e4SLinus Torvalds } 791da177e4SLinus Torvalds 8013d45709SPavel Hofman /* 8113d45709SPavel Hofman * Items labels in enum mixer controls assigning source data to 8213d45709SPavel Hofman * each destination 8313d45709SPavel Hofman */ 849f4bd5ddSJames Courtier-Dutton static char *emu1010_src_texts[] = { 859f4bd5ddSJames Courtier-Dutton "Silence", 869f4bd5ddSJames Courtier-Dutton "Dock Mic A", 879f4bd5ddSJames Courtier-Dutton "Dock Mic B", 889f4bd5ddSJames Courtier-Dutton "Dock ADC1 Left", 899f4bd5ddSJames Courtier-Dutton "Dock ADC1 Right", 909f4bd5ddSJames Courtier-Dutton "Dock ADC2 Left", 919f4bd5ddSJames Courtier-Dutton "Dock ADC2 Right", 929f4bd5ddSJames Courtier-Dutton "Dock ADC3 Left", 939f4bd5ddSJames Courtier-Dutton "Dock ADC3 Right", 949f4bd5ddSJames Courtier-Dutton "0202 ADC Left", 959f4bd5ddSJames Courtier-Dutton "0202 ADC Right", 969f4bd5ddSJames Courtier-Dutton "0202 SPDIF Left", 979f4bd5ddSJames Courtier-Dutton "0202 SPDIF Right", 989f4bd5ddSJames Courtier-Dutton "ADAT 0", 999f4bd5ddSJames Courtier-Dutton "ADAT 1", 1009f4bd5ddSJames Courtier-Dutton "ADAT 2", 1019f4bd5ddSJames Courtier-Dutton "ADAT 3", 1029f4bd5ddSJames Courtier-Dutton "ADAT 4", 1039f4bd5ddSJames Courtier-Dutton "ADAT 5", 1049f4bd5ddSJames Courtier-Dutton "ADAT 6", 1059f4bd5ddSJames Courtier-Dutton "ADAT 7", 1069f4bd5ddSJames Courtier-Dutton "DSP 0", 1079f4bd5ddSJames Courtier-Dutton "DSP 1", 1089f4bd5ddSJames Courtier-Dutton "DSP 2", 1099f4bd5ddSJames Courtier-Dutton "DSP 3", 1109f4bd5ddSJames Courtier-Dutton "DSP 4", 1119f4bd5ddSJames Courtier-Dutton "DSP 5", 1129f4bd5ddSJames Courtier-Dutton "DSP 6", 1139f4bd5ddSJames Courtier-Dutton "DSP 7", 1149f4bd5ddSJames Courtier-Dutton "DSP 8", 1159f4bd5ddSJames Courtier-Dutton "DSP 9", 1169f4bd5ddSJames Courtier-Dutton "DSP 10", 1179f4bd5ddSJames Courtier-Dutton "DSP 11", 1189f4bd5ddSJames Courtier-Dutton "DSP 12", 1199f4bd5ddSJames Courtier-Dutton "DSP 13", 1209f4bd5ddSJames Courtier-Dutton "DSP 14", 1219f4bd5ddSJames Courtier-Dutton "DSP 15", 1229f4bd5ddSJames Courtier-Dutton "DSP 16", 1239f4bd5ddSJames Courtier-Dutton "DSP 17", 1249f4bd5ddSJames Courtier-Dutton "DSP 18", 1259f4bd5ddSJames Courtier-Dutton "DSP 19", 1269f4bd5ddSJames Courtier-Dutton "DSP 20", 1279f4bd5ddSJames Courtier-Dutton "DSP 21", 1289f4bd5ddSJames Courtier-Dutton "DSP 22", 1299f4bd5ddSJames Courtier-Dutton "DSP 23", 1309f4bd5ddSJames Courtier-Dutton "DSP 24", 1319f4bd5ddSJames Courtier-Dutton "DSP 25", 1329f4bd5ddSJames Courtier-Dutton "DSP 26", 1339f4bd5ddSJames Courtier-Dutton "DSP 27", 1349f4bd5ddSJames Courtier-Dutton "DSP 28", 1359f4bd5ddSJames Courtier-Dutton "DSP 29", 1369f4bd5ddSJames Courtier-Dutton "DSP 30", 1379f4bd5ddSJames Courtier-Dutton "DSP 31", 1389f4bd5ddSJames Courtier-Dutton }; 1399f4bd5ddSJames Courtier-Dutton 14013d45709SPavel Hofman /* 14113d45709SPavel Hofman * List of data sources available for each destination 14213d45709SPavel Hofman */ 1439f4bd5ddSJames Courtier-Dutton static unsigned int emu1010_src_regs[] = { 1449f4bd5ddSJames Courtier-Dutton EMU_SRC_SILENCE,/* 0 */ 1459f4bd5ddSJames Courtier-Dutton EMU_SRC_DOCK_MIC_A1, /* 1 */ 1469f4bd5ddSJames Courtier-Dutton EMU_SRC_DOCK_MIC_B1, /* 2 */ 1479f4bd5ddSJames Courtier-Dutton EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */ 1489f4bd5ddSJames Courtier-Dutton EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */ 1499f4bd5ddSJames Courtier-Dutton EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */ 1509f4bd5ddSJames Courtier-Dutton EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */ 1519f4bd5ddSJames Courtier-Dutton EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */ 1529f4bd5ddSJames Courtier-Dutton EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */ 1539f4bd5ddSJames Courtier-Dutton EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */ 1549f4bd5ddSJames Courtier-Dutton EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */ 1559f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */ 1569f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */ 1579f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_ADAT, /* 13 */ 1589f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_ADAT+1, /* 14 */ 1599f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_ADAT+2, /* 15 */ 1609f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_ADAT+3, /* 16 */ 1619f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_ADAT+4, /* 17 */ 1629f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_ADAT+5, /* 18 */ 1639f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_ADAT+6, /* 19 */ 1649f4bd5ddSJames Courtier-Dutton EMU_SRC_HANA_ADAT+7, /* 20 */ 1659f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A, /* 21 */ 1669f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+1, /* 22 */ 1679f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+2, /* 23 */ 1689f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+3, /* 24 */ 1699f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+4, /* 25 */ 1709f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+5, /* 26 */ 1719f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+6, /* 27 */ 1729f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+7, /* 28 */ 1739f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+8, /* 29 */ 1749f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+9, /* 30 */ 1759f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+0xa, /* 31 */ 1769f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+0xb, /* 32 */ 1779f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+0xc, /* 33 */ 1789f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+0xd, /* 34 */ 1799f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+0xe, /* 35 */ 1809f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32A+0xf, /* 36 */ 1819f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B, /* 37 */ 1829f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+1, /* 38 */ 1839f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+2, /* 39 */ 1849f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+3, /* 40 */ 1859f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+4, /* 41 */ 1869f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+5, /* 42 */ 1879f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+6, /* 43 */ 1889f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+7, /* 44 */ 1899f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+8, /* 45 */ 1909f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+9, /* 46 */ 1919f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+0xa, /* 47 */ 1929f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+0xb, /* 48 */ 1939f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+0xc, /* 49 */ 1949f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+0xd, /* 50 */ 1959f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+0xe, /* 51 */ 1969f4bd5ddSJames Courtier-Dutton EMU_SRC_ALICE_EMU32B+0xf, /* 52 */ 1979f4bd5ddSJames Courtier-Dutton }; 1989f4bd5ddSJames Courtier-Dutton 19913d45709SPavel Hofman /* 20013d45709SPavel Hofman * Data destinations - physical EMU outputs. 20113d45709SPavel Hofman * Each destination has an enum mixer control to choose a data source 20213d45709SPavel Hofman */ 2039f4bd5ddSJames Courtier-Dutton static unsigned int emu1010_output_dst[] = { 2049f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_DAC1_LEFT1, /* 0 */ 2059f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */ 2069f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_DAC2_LEFT1, /* 2 */ 2079f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */ 2089f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_DAC3_LEFT1, /* 4 */ 2099f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */ 2109f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_DAC4_LEFT1, /* 6 */ 2119f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */ 2129f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_PHONES_LEFT1, /* 8 */ 2139f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */ 2149f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */ 2159f4bd5ddSJames Courtier-Dutton EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */ 2169f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_SPDIF_LEFT1, /* 12 */ 2179f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */ 2189f4bd5ddSJames Courtier-Dutton EMU_DST_HAMOA_DAC_LEFT1, /* 14 */ 2199f4bd5ddSJames Courtier-Dutton EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */ 2209f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_ADAT, /* 16 */ 2219f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_ADAT+1, /* 17 */ 2229f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_ADAT+2, /* 18 */ 2239f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_ADAT+3, /* 19 */ 2249f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_ADAT+4, /* 20 */ 2259f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_ADAT+5, /* 21 */ 2269f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_ADAT+6, /* 22 */ 2279f4bd5ddSJames Courtier-Dutton EMU_DST_HANA_ADAT+7, /* 23 */ 2289f4bd5ddSJames Courtier-Dutton }; 2299f4bd5ddSJames Courtier-Dutton 23013d45709SPavel Hofman /* 23113d45709SPavel Hofman * Data destinations - HANA outputs going to Alice2 (audigy) for 23213d45709SPavel Hofman * capture (EMU32 + I2S links) 23313d45709SPavel Hofman * Each destination has an enum mixer control to choose a data source 23413d45709SPavel Hofman */ 2359f4bd5ddSJames Courtier-Dutton static unsigned int emu1010_input_dst[] = { 2369f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_0, 2379f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_1, 2389f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_2, 2399f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_3, 2409f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_4, 2419f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_5, 2429f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_6, 2439f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_7, 2449f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_8, 2459f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_9, 2469f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_A, 2479f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_B, 2489f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_C, 2499f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_D, 2509f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_E, 2519f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_F, 2529f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S0_LEFT, 2539f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S0_RIGHT, 2549f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S1_LEFT, 2559f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S1_RIGHT, 2569f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S2_LEFT, 2579f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S2_RIGHT, 2589f4bd5ddSJames Courtier-Dutton }; 2599f4bd5ddSJames Courtier-Dutton 2609f4bd5ddSJames Courtier-Dutton static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 2619f4bd5ddSJames Courtier-Dutton { 2629f4bd5ddSJames Courtier-Dutton uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 2639f4bd5ddSJames Courtier-Dutton uinfo->count = 1; 2649f4bd5ddSJames Courtier-Dutton uinfo->value.enumerated.items = 53; 2659f4bd5ddSJames Courtier-Dutton if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 2669f4bd5ddSJames Courtier-Dutton uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 2679f4bd5ddSJames Courtier-Dutton strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]); 2689f4bd5ddSJames Courtier-Dutton return 0; 2699f4bd5ddSJames Courtier-Dutton } 2709f4bd5ddSJames Courtier-Dutton 2719f4bd5ddSJames Courtier-Dutton static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol, 2729f4bd5ddSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 2739f4bd5ddSJames Courtier-Dutton { 2749f4bd5ddSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 2759f4bd5ddSJames Courtier-Dutton int channel; 2769f4bd5ddSJames Courtier-Dutton 2779f4bd5ddSJames Courtier-Dutton channel = (kcontrol->private_value) & 0xff; 2789f4bd5ddSJames Courtier-Dutton ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel]; 2799f4bd5ddSJames Courtier-Dutton return 0; 2809f4bd5ddSJames Courtier-Dutton } 2819f4bd5ddSJames Courtier-Dutton 2829f4bd5ddSJames Courtier-Dutton static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol, 2839f4bd5ddSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 2849f4bd5ddSJames Courtier-Dutton { 2859f4bd5ddSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 2869f4bd5ddSJames Courtier-Dutton int change = 0; 2879f4bd5ddSJames Courtier-Dutton unsigned int val; 2889f4bd5ddSJames Courtier-Dutton int channel; 2899f4bd5ddSJames Courtier-Dutton 2909f4bd5ddSJames Courtier-Dutton channel = (kcontrol->private_value) & 0xff; 2919f4bd5ddSJames Courtier-Dutton if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) { 2929f4bd5ddSJames Courtier-Dutton val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0]; 2939f4bd5ddSJames Courtier-Dutton change = 1; 2949f4bd5ddSJames Courtier-Dutton snd_emu1010_fpga_link_dst_src_write(emu, 2959f4bd5ddSJames Courtier-Dutton emu1010_output_dst[channel], emu1010_src_regs[val]); 2969f4bd5ddSJames Courtier-Dutton } 2979f4bd5ddSJames Courtier-Dutton return change; 2989f4bd5ddSJames Courtier-Dutton } 2999f4bd5ddSJames Courtier-Dutton 3009f4bd5ddSJames Courtier-Dutton static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol, 3019f4bd5ddSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 3029f4bd5ddSJames Courtier-Dutton { 3039f4bd5ddSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 3049f4bd5ddSJames Courtier-Dutton int channel; 3059f4bd5ddSJames Courtier-Dutton 3069f4bd5ddSJames Courtier-Dutton channel = (kcontrol->private_value) & 0xff; 3079f4bd5ddSJames Courtier-Dutton ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel]; 3089f4bd5ddSJames Courtier-Dutton return 0; 3099f4bd5ddSJames Courtier-Dutton } 3109f4bd5ddSJames Courtier-Dutton 3119f4bd5ddSJames Courtier-Dutton static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol, 3129f4bd5ddSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 3139f4bd5ddSJames Courtier-Dutton { 3149f4bd5ddSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 3159f4bd5ddSJames Courtier-Dutton int change = 0; 3169f4bd5ddSJames Courtier-Dutton unsigned int val; 3179f4bd5ddSJames Courtier-Dutton int channel; 3189f4bd5ddSJames Courtier-Dutton 3199f4bd5ddSJames Courtier-Dutton channel = (kcontrol->private_value) & 0xff; 3209f4bd5ddSJames Courtier-Dutton if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) { 3219f4bd5ddSJames Courtier-Dutton val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0]; 3229f4bd5ddSJames Courtier-Dutton change = 1; 3239f4bd5ddSJames Courtier-Dutton snd_emu1010_fpga_link_dst_src_write(emu, 3249f4bd5ddSJames Courtier-Dutton emu1010_input_dst[channel], emu1010_src_regs[val]); 3259f4bd5ddSJames Courtier-Dutton } 3269f4bd5ddSJames Courtier-Dutton return change; 3279f4bd5ddSJames Courtier-Dutton } 3289f4bd5ddSJames Courtier-Dutton 3299f4bd5ddSJames Courtier-Dutton #define EMU1010_SOURCE_OUTPUT(xname,chid) \ 3309f4bd5ddSJames Courtier-Dutton { \ 3319f4bd5ddSJames Courtier-Dutton .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 3329f4bd5ddSJames Courtier-Dutton .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 3339f4bd5ddSJames Courtier-Dutton .info = snd_emu1010_input_output_source_info, \ 3349f4bd5ddSJames Courtier-Dutton .get = snd_emu1010_output_source_get, \ 3359f4bd5ddSJames Courtier-Dutton .put = snd_emu1010_output_source_put, \ 3369f4bd5ddSJames Courtier-Dutton .private_value = chid \ 3379f4bd5ddSJames Courtier-Dutton } 3389f4bd5ddSJames Courtier-Dutton 3399f4bd5ddSJames Courtier-Dutton static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = { 3404c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0), 3414c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1), 3424c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2), 3434c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3), 3444c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4), 3454c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5), 3464c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6), 3474c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7), 3484c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8), 3494c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9), 3504c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa), 3514c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb), 3524c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc), 3534c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd), 3544c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe), 3554c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf), 3564c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10), 3574c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11), 3584c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12), 3594c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13), 3604c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14), 3614c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15), 3624c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16), 3634c07c818SJames Courtier-Dutton EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17), 3649f4bd5ddSJames Courtier-Dutton }; 3659f4bd5ddSJames Courtier-Dutton 3669f4bd5ddSJames Courtier-Dutton #define EMU1010_SOURCE_INPUT(xname,chid) \ 3679f4bd5ddSJames Courtier-Dutton { \ 3689f4bd5ddSJames Courtier-Dutton .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 3699f4bd5ddSJames Courtier-Dutton .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 3709f4bd5ddSJames Courtier-Dutton .info = snd_emu1010_input_output_source_info, \ 3719f4bd5ddSJames Courtier-Dutton .get = snd_emu1010_input_source_get, \ 3729f4bd5ddSJames Courtier-Dutton .put = snd_emu1010_input_source_put, \ 3739f4bd5ddSJames Courtier-Dutton .private_value = chid \ 3749f4bd5ddSJames Courtier-Dutton } 3759f4bd5ddSJames Courtier-Dutton 3769f4bd5ddSJames Courtier-Dutton static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = { 3774c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0), 3784c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1), 3794c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2), 3804c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3), 3814c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4), 3824c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5), 3834c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6), 3844c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7), 3854c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8), 3864c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9), 3874c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa), 3884c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb), 3894c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc), 3904c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd), 3914c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe), 3924c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf), 3934c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10), 3944c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11), 3954c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12), 3964c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13), 3974c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14), 3984c07c818SJames Courtier-Dutton EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15), 3999148cc50SJames Courtier-Dutton }; 4009148cc50SJames Courtier-Dutton 4019148cc50SJames Courtier-Dutton 4029148cc50SJames Courtier-Dutton 403*a5ce8890STakashi Iwai #define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info 4049148cc50SJames Courtier-Dutton 4059148cc50SJames Courtier-Dutton static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 4069148cc50SJames Courtier-Dutton { 4079148cc50SJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 4089148cc50SJames Courtier-Dutton unsigned int mask = kcontrol->private_value & 0xff; 4099148cc50SJames Courtier-Dutton ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0; 4109148cc50SJames Courtier-Dutton return 0; 4119148cc50SJames Courtier-Dutton } 4129148cc50SJames Courtier-Dutton 4139148cc50SJames Courtier-Dutton static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 4149148cc50SJames Courtier-Dutton { 4159148cc50SJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 4169148cc50SJames Courtier-Dutton unsigned int mask = kcontrol->private_value & 0xff; 4179148cc50SJames Courtier-Dutton unsigned int val, cache; 4189148cc50SJames Courtier-Dutton val = ucontrol->value.integer.value[0]; 4199148cc50SJames Courtier-Dutton cache = emu->emu1010.adc_pads; 4209148cc50SJames Courtier-Dutton if (val == 1) 4219148cc50SJames Courtier-Dutton cache = cache | mask; 4229148cc50SJames Courtier-Dutton else 4239148cc50SJames Courtier-Dutton cache = cache & ~mask; 4249148cc50SJames Courtier-Dutton if (cache != emu->emu1010.adc_pads) { 4259148cc50SJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache ); 4269148cc50SJames Courtier-Dutton emu->emu1010.adc_pads = cache; 4279148cc50SJames Courtier-Dutton } 4289148cc50SJames Courtier-Dutton 4299148cc50SJames Courtier-Dutton return 0; 4309148cc50SJames Courtier-Dutton } 4319148cc50SJames Courtier-Dutton 4329148cc50SJames Courtier-Dutton 4339148cc50SJames Courtier-Dutton 4349148cc50SJames Courtier-Dutton #define EMU1010_ADC_PADS(xname,chid) \ 4359148cc50SJames Courtier-Dutton { \ 4369148cc50SJames Courtier-Dutton .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 4379148cc50SJames Courtier-Dutton .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 4389148cc50SJames Courtier-Dutton .info = snd_emu1010_adc_pads_info, \ 4399148cc50SJames Courtier-Dutton .get = snd_emu1010_adc_pads_get, \ 4409148cc50SJames Courtier-Dutton .put = snd_emu1010_adc_pads_put, \ 4419148cc50SJames Courtier-Dutton .private_value = chid \ 4429148cc50SJames Courtier-Dutton } 4439148cc50SJames Courtier-Dutton 4449148cc50SJames Courtier-Dutton static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = { 4459148cc50SJames Courtier-Dutton EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1), 4469148cc50SJames Courtier-Dutton EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2), 4479148cc50SJames Courtier-Dutton EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3), 4489148cc50SJames Courtier-Dutton EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1), 4499148cc50SJames Courtier-Dutton }; 4509148cc50SJames Courtier-Dutton 451*a5ce8890STakashi Iwai #define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info 4529148cc50SJames Courtier-Dutton 4539148cc50SJames Courtier-Dutton static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 4549148cc50SJames Courtier-Dutton { 4559148cc50SJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 4569148cc50SJames Courtier-Dutton unsigned int mask = kcontrol->private_value & 0xff; 4579148cc50SJames Courtier-Dutton ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0; 4589148cc50SJames Courtier-Dutton return 0; 4599148cc50SJames Courtier-Dutton } 4609148cc50SJames Courtier-Dutton 4619148cc50SJames Courtier-Dutton static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 4629148cc50SJames Courtier-Dutton { 4639148cc50SJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 4649148cc50SJames Courtier-Dutton unsigned int mask = kcontrol->private_value & 0xff; 4659148cc50SJames Courtier-Dutton unsigned int val, cache; 4669148cc50SJames Courtier-Dutton val = ucontrol->value.integer.value[0]; 4679148cc50SJames Courtier-Dutton cache = emu->emu1010.dac_pads; 4689148cc50SJames Courtier-Dutton if (val == 1) 4699148cc50SJames Courtier-Dutton cache = cache | mask; 4709148cc50SJames Courtier-Dutton else 4719148cc50SJames Courtier-Dutton cache = cache & ~mask; 4729148cc50SJames Courtier-Dutton if (cache != emu->emu1010.dac_pads) { 4739148cc50SJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache ); 4749148cc50SJames Courtier-Dutton emu->emu1010.dac_pads = cache; 4759148cc50SJames Courtier-Dutton } 4769148cc50SJames Courtier-Dutton 4779148cc50SJames Courtier-Dutton return 0; 4789148cc50SJames Courtier-Dutton } 4799148cc50SJames Courtier-Dutton 4809148cc50SJames Courtier-Dutton 4819148cc50SJames Courtier-Dutton 4829148cc50SJames Courtier-Dutton #define EMU1010_DAC_PADS(xname,chid) \ 4839148cc50SJames Courtier-Dutton { \ 4849148cc50SJames Courtier-Dutton .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 4859148cc50SJames Courtier-Dutton .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 4869148cc50SJames Courtier-Dutton .info = snd_emu1010_dac_pads_info, \ 4879148cc50SJames Courtier-Dutton .get = snd_emu1010_dac_pads_get, \ 4889148cc50SJames Courtier-Dutton .put = snd_emu1010_dac_pads_put, \ 4899148cc50SJames Courtier-Dutton .private_value = chid \ 4909148cc50SJames Courtier-Dutton } 4919148cc50SJames Courtier-Dutton 4929148cc50SJames Courtier-Dutton static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = { 4939148cc50SJames Courtier-Dutton EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1), 4949148cc50SJames Courtier-Dutton EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2), 4959148cc50SJames Courtier-Dutton EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3), 4969148cc50SJames Courtier-Dutton EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4), 4979148cc50SJames Courtier-Dutton EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1), 4989f4bd5ddSJames Courtier-Dutton }; 4999f4bd5ddSJames Courtier-Dutton 500b0dbdaeaSJames Courtier-Dutton 501b0dbdaeaSJames Courtier-Dutton static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol, 502b0dbdaeaSJames Courtier-Dutton struct snd_ctl_elem_info *uinfo) 503b0dbdaeaSJames Courtier-Dutton { 504b0dbdaeaSJames Courtier-Dutton static char *texts[2] = { 505b0dbdaeaSJames Courtier-Dutton "44100", "48000" 506b0dbdaeaSJames Courtier-Dutton }; 507b0dbdaeaSJames Courtier-Dutton 508b0dbdaeaSJames Courtier-Dutton uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 509b0dbdaeaSJames Courtier-Dutton uinfo->count = 1; 510b0dbdaeaSJames Courtier-Dutton uinfo->value.enumerated.items = 2; 511b0dbdaeaSJames Courtier-Dutton if (uinfo->value.enumerated.item > 1) 512b0dbdaeaSJames Courtier-Dutton uinfo->value.enumerated.item = 1; 513b0dbdaeaSJames Courtier-Dutton strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 514b0dbdaeaSJames Courtier-Dutton return 0; 515b0dbdaeaSJames Courtier-Dutton } 516b0dbdaeaSJames Courtier-Dutton 517b0dbdaeaSJames Courtier-Dutton static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol, 518b0dbdaeaSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 519b0dbdaeaSJames Courtier-Dutton { 520b0dbdaeaSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 521b0dbdaeaSJames Courtier-Dutton 522b0dbdaeaSJames Courtier-Dutton ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock; 523b0dbdaeaSJames Courtier-Dutton return 0; 524b0dbdaeaSJames Courtier-Dutton } 525b0dbdaeaSJames Courtier-Dutton 526b0dbdaeaSJames Courtier-Dutton static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol, 527b0dbdaeaSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 528b0dbdaeaSJames Courtier-Dutton { 529b0dbdaeaSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 530b0dbdaeaSJames Courtier-Dutton unsigned int val; 531b0dbdaeaSJames Courtier-Dutton int change = 0; 532b0dbdaeaSJames Courtier-Dutton 533b0dbdaeaSJames Courtier-Dutton val = ucontrol->value.enumerated.item[0] ; 534b0dbdaeaSJames Courtier-Dutton change = (emu->emu1010.internal_clock != val); 535b0dbdaeaSJames Courtier-Dutton if (change) { 536b0dbdaeaSJames Courtier-Dutton emu->emu1010.internal_clock = val; 537b0dbdaeaSJames Courtier-Dutton switch (val) { 538b0dbdaeaSJames Courtier-Dutton case 0: 539b0dbdaeaSJames Courtier-Dutton /* 44100 */ 540b0dbdaeaSJames Courtier-Dutton /* Mute all */ 541b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); 542b0dbdaeaSJames Courtier-Dutton /* Default fallback clock 48kHz */ 543b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K ); 544b0dbdaeaSJames Courtier-Dutton /* Word Clock source, Internal 44.1kHz x1 */ 545b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, 546b0dbdaeaSJames Courtier-Dutton EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X ); 547b0dbdaeaSJames Courtier-Dutton /* Set LEDs on Audio Dock */ 548b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 549b0dbdaeaSJames Courtier-Dutton EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK ); 550b0dbdaeaSJames Courtier-Dutton /* Allow DLL to settle */ 551e40a0b2eSJames Courtier-Dutton msleep(10); 552b0dbdaeaSJames Courtier-Dutton /* Unmute all */ 553b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); 554b0dbdaeaSJames Courtier-Dutton break; 555b0dbdaeaSJames Courtier-Dutton case 1: 556b0dbdaeaSJames Courtier-Dutton /* 48000 */ 557b0dbdaeaSJames Courtier-Dutton /* Mute all */ 558b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE ); 559b0dbdaeaSJames Courtier-Dutton /* Default fallback clock 48kHz */ 560b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K ); 561b0dbdaeaSJames Courtier-Dutton /* Word Clock source, Internal 48kHz x1 */ 562b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, 563b0dbdaeaSJames Courtier-Dutton EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X ); 564b0dbdaeaSJames Courtier-Dutton /* Set LEDs on Audio Dock */ 565b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 566b0dbdaeaSJames Courtier-Dutton EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK ); 567b0dbdaeaSJames Courtier-Dutton /* Allow DLL to settle */ 568e40a0b2eSJames Courtier-Dutton msleep(10); 569b0dbdaeaSJames Courtier-Dutton /* Unmute all */ 570b0dbdaeaSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); 571b0dbdaeaSJames Courtier-Dutton break; 572b0dbdaeaSJames Courtier-Dutton } 573b0dbdaeaSJames Courtier-Dutton } 574b0dbdaeaSJames Courtier-Dutton return change; 575b0dbdaeaSJames Courtier-Dutton } 576b0dbdaeaSJames Courtier-Dutton 577b0dbdaeaSJames Courtier-Dutton static struct snd_kcontrol_new snd_emu1010_internal_clock = 578b0dbdaeaSJames Courtier-Dutton { 579b0dbdaeaSJames Courtier-Dutton .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 580b0dbdaeaSJames Courtier-Dutton .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 581b0dbdaeaSJames Courtier-Dutton .name = "Clock Internal Rate", 582b0dbdaeaSJames Courtier-Dutton .count = 1, 583b0dbdaeaSJames Courtier-Dutton .info = snd_emu1010_internal_clock_info, 584b0dbdaeaSJames Courtier-Dutton .get = snd_emu1010_internal_clock_get, 585b0dbdaeaSJames Courtier-Dutton .put = snd_emu1010_internal_clock_put 586b0dbdaeaSJames Courtier-Dutton }; 587b0dbdaeaSJames Courtier-Dutton 588184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol, 589184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_info *uinfo) 590184c1e2cSJames Courtier-Dutton { 591184c1e2cSJames Courtier-Dutton #if 0 592184c1e2cSJames Courtier-Dutton static char *texts[4] = { 593184c1e2cSJames Courtier-Dutton "Unknown1", "Unknown2", "Mic", "Line" 594184c1e2cSJames Courtier-Dutton }; 595184c1e2cSJames Courtier-Dutton #endif 596184c1e2cSJames Courtier-Dutton static char *texts[2] = { 597184c1e2cSJames Courtier-Dutton "Mic", "Line" 598184c1e2cSJames Courtier-Dutton }; 599184c1e2cSJames Courtier-Dutton 600184c1e2cSJames Courtier-Dutton uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 601184c1e2cSJames Courtier-Dutton uinfo->count = 1; 602184c1e2cSJames Courtier-Dutton uinfo->value.enumerated.items = 2; 603184c1e2cSJames Courtier-Dutton if (uinfo->value.enumerated.item > 1) 604184c1e2cSJames Courtier-Dutton uinfo->value.enumerated.item = 1; 605184c1e2cSJames Courtier-Dutton strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 606184c1e2cSJames Courtier-Dutton return 0; 607184c1e2cSJames Courtier-Dutton } 608184c1e2cSJames Courtier-Dutton 609184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol, 610184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 611184c1e2cSJames Courtier-Dutton { 612184c1e2cSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 613184c1e2cSJames Courtier-Dutton 614184c1e2cSJames Courtier-Dutton ucontrol->value.enumerated.item[0] = emu->i2c_capture_source; 615184c1e2cSJames Courtier-Dutton return 0; 616184c1e2cSJames Courtier-Dutton } 617184c1e2cSJames Courtier-Dutton 618184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol, 619184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 620184c1e2cSJames Courtier-Dutton { 621184c1e2cSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 622184c1e2cSJames Courtier-Dutton unsigned int source_id; 623184c1e2cSJames Courtier-Dutton unsigned int ngain, ogain; 624184c1e2cSJames Courtier-Dutton u32 gpio; 625184c1e2cSJames Courtier-Dutton int change = 0; 626184c1e2cSJames Courtier-Dutton unsigned long flags; 627184c1e2cSJames Courtier-Dutton u32 source; 628184c1e2cSJames Courtier-Dutton /* If the capture source has changed, 629184c1e2cSJames Courtier-Dutton * update the capture volume from the cached value 630184c1e2cSJames Courtier-Dutton * for the particular source. 631184c1e2cSJames Courtier-Dutton */ 632184c1e2cSJames Courtier-Dutton source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */ 633184c1e2cSJames Courtier-Dutton change = (emu->i2c_capture_source != source_id); 634184c1e2cSJames Courtier-Dutton if (change) { 635184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */ 636184c1e2cSJames Courtier-Dutton spin_lock_irqsave(&emu->emu_lock, flags); 637184c1e2cSJames Courtier-Dutton gpio = inl(emu->port + A_IOCFG); 638184c1e2cSJames Courtier-Dutton if (source_id==0) 639184c1e2cSJames Courtier-Dutton outl(gpio | 0x4, emu->port + A_IOCFG); 640184c1e2cSJames Courtier-Dutton else 641184c1e2cSJames Courtier-Dutton outl(gpio & ~0x4, emu->port + A_IOCFG); 642184c1e2cSJames Courtier-Dutton spin_unlock_irqrestore(&emu->emu_lock, flags); 643184c1e2cSJames Courtier-Dutton 644184c1e2cSJames Courtier-Dutton ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ 645184c1e2cSJames Courtier-Dutton ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ 646184c1e2cSJames Courtier-Dutton if (ngain != ogain) 647184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); 648184c1e2cSJames Courtier-Dutton ngain = emu->i2c_capture_volume[source_id][1]; /* Right */ 649184c1e2cSJames Courtier-Dutton ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */ 650184c1e2cSJames Courtier-Dutton if (ngain != ogain) 651184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); 652184c1e2cSJames Courtier-Dutton 653184c1e2cSJames Courtier-Dutton source = 1 << (source_id + 2); 654184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */ 655184c1e2cSJames Courtier-Dutton emu->i2c_capture_source = source_id; 656184c1e2cSJames Courtier-Dutton } 657184c1e2cSJames Courtier-Dutton return change; 658184c1e2cSJames Courtier-Dutton } 659184c1e2cSJames Courtier-Dutton 660184c1e2cSJames Courtier-Dutton static struct snd_kcontrol_new snd_audigy_i2c_capture_source = 661184c1e2cSJames Courtier-Dutton { 662184c1e2cSJames Courtier-Dutton .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 663184c1e2cSJames Courtier-Dutton .name = "Capture Source", 664184c1e2cSJames Courtier-Dutton .info = snd_audigy_i2c_capture_source_info, 665184c1e2cSJames Courtier-Dutton .get = snd_audigy_i2c_capture_source_get, 666184c1e2cSJames Courtier-Dutton .put = snd_audigy_i2c_capture_source_put 667184c1e2cSJames Courtier-Dutton }; 668184c1e2cSJames Courtier-Dutton 669184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol, 670184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_info *uinfo) 671184c1e2cSJames Courtier-Dutton { 672184c1e2cSJames Courtier-Dutton uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 673184c1e2cSJames Courtier-Dutton uinfo->count = 2; 674184c1e2cSJames Courtier-Dutton uinfo->value.integer.min = 0; 675184c1e2cSJames Courtier-Dutton uinfo->value.integer.max = 255; 676184c1e2cSJames Courtier-Dutton return 0; 677184c1e2cSJames Courtier-Dutton } 678184c1e2cSJames Courtier-Dutton 679184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol, 680184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 681184c1e2cSJames Courtier-Dutton { 682184c1e2cSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 683184c1e2cSJames Courtier-Dutton int source_id; 684184c1e2cSJames Courtier-Dutton 685184c1e2cSJames Courtier-Dutton source_id = kcontrol->private_value; 686184c1e2cSJames Courtier-Dutton 687184c1e2cSJames Courtier-Dutton ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0]; 688184c1e2cSJames Courtier-Dutton ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1]; 689184c1e2cSJames Courtier-Dutton return 0; 690184c1e2cSJames Courtier-Dutton } 691184c1e2cSJames Courtier-Dutton 692184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol, 693184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol) 694184c1e2cSJames Courtier-Dutton { 695184c1e2cSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 696184c1e2cSJames Courtier-Dutton unsigned int ogain; 697184c1e2cSJames Courtier-Dutton unsigned int ngain; 698184c1e2cSJames Courtier-Dutton int source_id; 699184c1e2cSJames Courtier-Dutton int change = 0; 700184c1e2cSJames Courtier-Dutton 701184c1e2cSJames Courtier-Dutton source_id = kcontrol->private_value; 702184c1e2cSJames Courtier-Dutton ogain = emu->i2c_capture_volume[source_id][0]; /* Left */ 703184c1e2cSJames Courtier-Dutton ngain = ucontrol->value.integer.value[0]; 704184c1e2cSJames Courtier-Dutton if (ngain > 0xff) 705184c1e2cSJames Courtier-Dutton return 0; 706184c1e2cSJames Courtier-Dutton if (ogain != ngain) { 707184c1e2cSJames Courtier-Dutton if (emu->i2c_capture_source == source_id) 708184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) ); 709184c1e2cSJames Courtier-Dutton emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0]; 710184c1e2cSJames Courtier-Dutton change = 1; 711184c1e2cSJames Courtier-Dutton } 712184c1e2cSJames Courtier-Dutton ogain = emu->i2c_capture_volume[source_id][1]; /* Right */ 713184c1e2cSJames Courtier-Dutton ngain = ucontrol->value.integer.value[1]; 714184c1e2cSJames Courtier-Dutton if (ngain > 0xff) 715184c1e2cSJames Courtier-Dutton return 0; 716184c1e2cSJames Courtier-Dutton if (ogain != ngain) { 717184c1e2cSJames Courtier-Dutton if (emu->i2c_capture_source == source_id) 718184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); 719184c1e2cSJames Courtier-Dutton emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1]; 720184c1e2cSJames Courtier-Dutton change = 1; 721184c1e2cSJames Courtier-Dutton } 722184c1e2cSJames Courtier-Dutton 723184c1e2cSJames Courtier-Dutton return change; 724184c1e2cSJames Courtier-Dutton } 725184c1e2cSJames Courtier-Dutton 726184c1e2cSJames Courtier-Dutton #define I2C_VOLUME(xname,chid) \ 727184c1e2cSJames Courtier-Dutton { \ 728184c1e2cSJames Courtier-Dutton .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 729184c1e2cSJames Courtier-Dutton .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ 730184c1e2cSJames Courtier-Dutton SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 731184c1e2cSJames Courtier-Dutton .info = snd_audigy_i2c_volume_info, \ 732184c1e2cSJames Courtier-Dutton .get = snd_audigy_i2c_volume_get, \ 733184c1e2cSJames Courtier-Dutton .put = snd_audigy_i2c_volume_put, \ 734184c1e2cSJames Courtier-Dutton .tlv = { .p = snd_audigy_db_scale2 }, \ 735184c1e2cSJames Courtier-Dutton .private_value = chid \ 736184c1e2cSJames Courtier-Dutton } 737184c1e2cSJames Courtier-Dutton 738184c1e2cSJames Courtier-Dutton 739184c1e2cSJames Courtier-Dutton static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = { 740184c1e2cSJames Courtier-Dutton I2C_VOLUME("Mic Capture Volume", 0), 741184c1e2cSJames Courtier-Dutton I2C_VOLUME("Line Capture Volume", 0) 742184c1e2cSJames Courtier-Dutton }; 743184c1e2cSJames Courtier-Dutton 7440af68e5eSTakashi Iwai #if 0 745eb4698f3STakashi Iwai static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 7461da177e4SLinus Torvalds { 7471da177e4SLinus Torvalds static char *texts[] = {"44100", "48000", "96000"}; 7481da177e4SLinus Torvalds 7491da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 7501da177e4SLinus Torvalds uinfo->count = 1; 7511da177e4SLinus Torvalds uinfo->value.enumerated.items = 3; 7521da177e4SLinus Torvalds if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 7531da177e4SLinus Torvalds uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1; 7541da177e4SLinus Torvalds strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); 7551da177e4SLinus Torvalds return 0; 7561da177e4SLinus Torvalds } 7571da177e4SLinus Torvalds 758eb4698f3STakashi Iwai static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol, 759eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 7601da177e4SLinus Torvalds { 761eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 7621da177e4SLinus Torvalds unsigned int tmp; 7631da177e4SLinus Torvalds unsigned long flags; 7641da177e4SLinus Torvalds 7651da177e4SLinus Torvalds 7661da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 7671da177e4SLinus Torvalds tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); 7681da177e4SLinus Torvalds switch (tmp & A_SPDIF_RATE_MASK) { 7691da177e4SLinus Torvalds case A_SPDIF_44100: 7701da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 0; 7711da177e4SLinus Torvalds break; 7721da177e4SLinus Torvalds case A_SPDIF_48000: 7731da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 1; 7741da177e4SLinus Torvalds break; 7751da177e4SLinus Torvalds case A_SPDIF_96000: 7761da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 2; 7771da177e4SLinus Torvalds break; 7781da177e4SLinus Torvalds default: 7791da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 1; 7801da177e4SLinus Torvalds } 7811da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 7821da177e4SLinus Torvalds return 0; 7831da177e4SLinus Torvalds } 7841da177e4SLinus Torvalds 785eb4698f3STakashi Iwai static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol, 786eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 7871da177e4SLinus Torvalds { 788eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 7891da177e4SLinus Torvalds int change; 7901da177e4SLinus Torvalds unsigned int reg, val, tmp; 7911da177e4SLinus Torvalds unsigned long flags; 7921da177e4SLinus Torvalds 7931da177e4SLinus Torvalds switch(ucontrol->value.enumerated.item[0]) { 7941da177e4SLinus Torvalds case 0: 7951da177e4SLinus Torvalds val = A_SPDIF_44100; 7961da177e4SLinus Torvalds break; 7971da177e4SLinus Torvalds case 1: 7981da177e4SLinus Torvalds val = A_SPDIF_48000; 7991da177e4SLinus Torvalds break; 8001da177e4SLinus Torvalds case 2: 8011da177e4SLinus Torvalds val = A_SPDIF_96000; 8021da177e4SLinus Torvalds break; 8031da177e4SLinus Torvalds default: 8041da177e4SLinus Torvalds val = A_SPDIF_48000; 8051da177e4SLinus Torvalds break; 8061da177e4SLinus Torvalds } 8071da177e4SLinus Torvalds 8081da177e4SLinus Torvalds 8091da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 8101da177e4SLinus Torvalds reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); 8111da177e4SLinus Torvalds tmp = reg & ~A_SPDIF_RATE_MASK; 8121da177e4SLinus Torvalds tmp |= val; 8131da177e4SLinus Torvalds if ((change = (tmp != reg))) 8141da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); 8151da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 8161da177e4SLinus Torvalds return change; 8171da177e4SLinus Torvalds } 8181da177e4SLinus Torvalds 819eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_audigy_spdif_output_rate = 8201da177e4SLinus Torvalds { 8211da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 8221da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 8231da177e4SLinus Torvalds .name = "Audigy SPDIF Output Sample Rate", 8241da177e4SLinus Torvalds .count = 1, 8251da177e4SLinus Torvalds .info = snd_audigy_spdif_output_rate_info, 8261da177e4SLinus Torvalds .get = snd_audigy_spdif_output_rate_get, 8271da177e4SLinus Torvalds .put = snd_audigy_spdif_output_rate_put 8281da177e4SLinus Torvalds }; 8290af68e5eSTakashi Iwai #endif 8301da177e4SLinus Torvalds 831eb4698f3STakashi Iwai static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol, 832eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 8331da177e4SLinus Torvalds { 834eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 8351da177e4SLinus Torvalds unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 8361da177e4SLinus Torvalds int change; 8371da177e4SLinus Torvalds unsigned int val; 8381da177e4SLinus Torvalds unsigned long flags; 8391da177e4SLinus Torvalds 8401da177e4SLinus Torvalds val = (ucontrol->value.iec958.status[0] << 0) | 8411da177e4SLinus Torvalds (ucontrol->value.iec958.status[1] << 8) | 8421da177e4SLinus Torvalds (ucontrol->value.iec958.status[2] << 16) | 8431da177e4SLinus Torvalds (ucontrol->value.iec958.status[3] << 24); 8441da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 8451da177e4SLinus Torvalds change = val != emu->spdif_bits[idx]; 8461da177e4SLinus Torvalds if (change) { 8471da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val); 8481da177e4SLinus Torvalds emu->spdif_bits[idx] = val; 8491da177e4SLinus Torvalds } 8501da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 8511da177e4SLinus Torvalds return change; 8521da177e4SLinus Torvalds } 8531da177e4SLinus Torvalds 854eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_emu10k1_spdif_mask_control = 8551da177e4SLinus Torvalds { 8561da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ, 8575549d549SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 8581da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), 8591da177e4SLinus Torvalds .count = 4, 8601da177e4SLinus Torvalds .info = snd_emu10k1_spdif_info, 8611da177e4SLinus Torvalds .get = snd_emu10k1_spdif_get_mask 8621da177e4SLinus Torvalds }; 8631da177e4SLinus Torvalds 864eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_emu10k1_spdif_control = 8651da177e4SLinus Torvalds { 8665549d549SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 8671da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 8681da177e4SLinus Torvalds .count = 4, 8691da177e4SLinus Torvalds .info = snd_emu10k1_spdif_info, 8701da177e4SLinus Torvalds .get = snd_emu10k1_spdif_get, 8711da177e4SLinus Torvalds .put = snd_emu10k1_spdif_put 8721da177e4SLinus Torvalds }; 8731da177e4SLinus Torvalds 8741da177e4SLinus Torvalds 875eb4698f3STakashi Iwai static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route) 8761da177e4SLinus Torvalds { 8771da177e4SLinus Torvalds if (emu->audigy) { 8781da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, A_FXRT1, voice, 8791da177e4SLinus Torvalds snd_emu10k1_compose_audigy_fxrt1(route)); 8801da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, A_FXRT2, voice, 8811da177e4SLinus Torvalds snd_emu10k1_compose_audigy_fxrt2(route)); 8821da177e4SLinus Torvalds } else { 8831da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, FXRT, voice, 8841da177e4SLinus Torvalds snd_emu10k1_compose_send_routing(route)); 8851da177e4SLinus Torvalds } 8861da177e4SLinus Torvalds } 8871da177e4SLinus Torvalds 888eb4698f3STakashi Iwai static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume) 8891da177e4SLinus Torvalds { 8901da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]); 8911da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]); 8921da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]); 8931da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]); 8941da177e4SLinus Torvalds if (emu->audigy) { 8951da177e4SLinus Torvalds unsigned int val = ((unsigned int)volume[4] << 24) | 8961da177e4SLinus Torvalds ((unsigned int)volume[5] << 16) | 8971da177e4SLinus Torvalds ((unsigned int)volume[6] << 8) | 8981da177e4SLinus Torvalds (unsigned int)volume[7]; 8991da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice, val); 9001da177e4SLinus Torvalds } 9011da177e4SLinus Torvalds } 9021da177e4SLinus Torvalds 9031da177e4SLinus Torvalds /* PCM stream controls */ 9041da177e4SLinus Torvalds 905eb4698f3STakashi Iwai static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 9061da177e4SLinus Torvalds { 907eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 9081da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 9091da177e4SLinus Torvalds uinfo->count = emu->audigy ? 3*8 : 3*4; 9101da177e4SLinus Torvalds uinfo->value.integer.min = 0; 9111da177e4SLinus Torvalds uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; 9121da177e4SLinus Torvalds return 0; 9131da177e4SLinus Torvalds } 9141da177e4SLinus Torvalds 915eb4698f3STakashi Iwai static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol, 916eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 9171da177e4SLinus Torvalds { 9181da177e4SLinus Torvalds unsigned long flags; 919eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 920eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = 921eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; 9221da177e4SLinus Torvalds int voice, idx; 9231da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4; 9241da177e4SLinus Torvalds int mask = emu->audigy ? 0x3f : 0x0f; 9251da177e4SLinus Torvalds 9261da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 9271da177e4SLinus Torvalds for (voice = 0; voice < 3; voice++) 9281da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++) 9291da177e4SLinus Torvalds ucontrol->value.integer.value[(voice * num_efx) + idx] = 9301da177e4SLinus Torvalds mix->send_routing[voice][idx] & mask; 9311da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 9321da177e4SLinus Torvalds return 0; 9331da177e4SLinus Torvalds } 9341da177e4SLinus Torvalds 935eb4698f3STakashi Iwai static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol, 936eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 9371da177e4SLinus Torvalds { 9381da177e4SLinus Torvalds unsigned long flags; 939eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 940eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = 941eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; 9421da177e4SLinus Torvalds int change = 0, voice, idx, val; 9431da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4; 9441da177e4SLinus Torvalds int mask = emu->audigy ? 0x3f : 0x0f; 9451da177e4SLinus Torvalds 9461da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 9471da177e4SLinus Torvalds for (voice = 0; voice < 3; voice++) 9481da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++) { 9491da177e4SLinus Torvalds val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask; 9501da177e4SLinus Torvalds if (mix->send_routing[voice][idx] != val) { 9511da177e4SLinus Torvalds mix->send_routing[voice][idx] = val; 9521da177e4SLinus Torvalds change = 1; 9531da177e4SLinus Torvalds } 9541da177e4SLinus Torvalds } 9551da177e4SLinus Torvalds if (change && mix->epcm) { 9561da177e4SLinus Torvalds if (mix->epcm->voices[0] && mix->epcm->voices[1]) { 9571da177e4SLinus Torvalds update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number, 9581da177e4SLinus Torvalds &mix->send_routing[1][0]); 9591da177e4SLinus Torvalds update_emu10k1_fxrt(emu, mix->epcm->voices[1]->number, 9601da177e4SLinus Torvalds &mix->send_routing[2][0]); 9611da177e4SLinus Torvalds } else if (mix->epcm->voices[0]) { 9621da177e4SLinus Torvalds update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number, 9631da177e4SLinus Torvalds &mix->send_routing[0][0]); 9641da177e4SLinus Torvalds } 9651da177e4SLinus Torvalds } 9661da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 9671da177e4SLinus Torvalds return change; 9681da177e4SLinus Torvalds } 9691da177e4SLinus Torvalds 970eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_emu10k1_send_routing_control = 9711da177e4SLinus Torvalds { 9721da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 97367ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 9741da177e4SLinus Torvalds .name = "EMU10K1 PCM Send Routing", 9751da177e4SLinus Torvalds .count = 32, 9761da177e4SLinus Torvalds .info = snd_emu10k1_send_routing_info, 9771da177e4SLinus Torvalds .get = snd_emu10k1_send_routing_get, 9781da177e4SLinus Torvalds .put = snd_emu10k1_send_routing_put 9791da177e4SLinus Torvalds }; 9801da177e4SLinus Torvalds 981eb4698f3STakashi Iwai static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 9821da177e4SLinus Torvalds { 983eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 9841da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 9851da177e4SLinus Torvalds uinfo->count = emu->audigy ? 3*8 : 3*4; 9861da177e4SLinus Torvalds uinfo->value.integer.min = 0; 9871da177e4SLinus Torvalds uinfo->value.integer.max = 255; 9881da177e4SLinus Torvalds return 0; 9891da177e4SLinus Torvalds } 9901da177e4SLinus Torvalds 991eb4698f3STakashi Iwai static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol, 992eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 9931da177e4SLinus Torvalds { 9941da177e4SLinus Torvalds unsigned long flags; 995eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 996eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = 997eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; 9981da177e4SLinus Torvalds int idx; 9991da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4; 10001da177e4SLinus Torvalds 10011da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 10021da177e4SLinus Torvalds for (idx = 0; idx < 3*num_efx; idx++) 10031da177e4SLinus Torvalds ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx]; 10041da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 10051da177e4SLinus Torvalds return 0; 10061da177e4SLinus Torvalds } 10071da177e4SLinus Torvalds 1008eb4698f3STakashi Iwai static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol, 1009eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 10101da177e4SLinus Torvalds { 10111da177e4SLinus Torvalds unsigned long flags; 1012eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 1013eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = 1014eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; 10151da177e4SLinus Torvalds int change = 0, idx, val; 10161da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4; 10171da177e4SLinus Torvalds 10181da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 10191da177e4SLinus Torvalds for (idx = 0; idx < 3*num_efx; idx++) { 10201da177e4SLinus Torvalds val = ucontrol->value.integer.value[idx] & 255; 10211da177e4SLinus Torvalds if (mix->send_volume[idx/num_efx][idx%num_efx] != val) { 10221da177e4SLinus Torvalds mix->send_volume[idx/num_efx][idx%num_efx] = val; 10231da177e4SLinus Torvalds change = 1; 10241da177e4SLinus Torvalds } 10251da177e4SLinus Torvalds } 10261da177e4SLinus Torvalds if (change && mix->epcm) { 10271da177e4SLinus Torvalds if (mix->epcm->voices[0] && mix->epcm->voices[1]) { 10281da177e4SLinus Torvalds update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number, 10291da177e4SLinus Torvalds &mix->send_volume[1][0]); 10301da177e4SLinus Torvalds update_emu10k1_send_volume(emu, mix->epcm->voices[1]->number, 10311da177e4SLinus Torvalds &mix->send_volume[2][0]); 10321da177e4SLinus Torvalds } else if (mix->epcm->voices[0]) { 10331da177e4SLinus Torvalds update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number, 10341da177e4SLinus Torvalds &mix->send_volume[0][0]); 10351da177e4SLinus Torvalds } 10361da177e4SLinus Torvalds } 10371da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 10381da177e4SLinus Torvalds return change; 10391da177e4SLinus Torvalds } 10401da177e4SLinus Torvalds 1041eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_emu10k1_send_volume_control = 10421da177e4SLinus Torvalds { 10431da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 104467ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 10451da177e4SLinus Torvalds .name = "EMU10K1 PCM Send Volume", 10461da177e4SLinus Torvalds .count = 32, 10471da177e4SLinus Torvalds .info = snd_emu10k1_send_volume_info, 10481da177e4SLinus Torvalds .get = snd_emu10k1_send_volume_get, 10491da177e4SLinus Torvalds .put = snd_emu10k1_send_volume_put 10501da177e4SLinus Torvalds }; 10511da177e4SLinus Torvalds 1052eb4698f3STakashi Iwai static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 10531da177e4SLinus Torvalds { 10541da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 10551da177e4SLinus Torvalds uinfo->count = 3; 10561da177e4SLinus Torvalds uinfo->value.integer.min = 0; 10571da177e4SLinus Torvalds uinfo->value.integer.max = 0xffff; 10581da177e4SLinus Torvalds return 0; 10591da177e4SLinus Torvalds } 10601da177e4SLinus Torvalds 1061eb4698f3STakashi Iwai static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol, 1062eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 10631da177e4SLinus Torvalds { 1064eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 1065eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = 1066eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; 10671da177e4SLinus Torvalds unsigned long flags; 10681da177e4SLinus Torvalds int idx; 10691da177e4SLinus Torvalds 10701da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 10711da177e4SLinus Torvalds for (idx = 0; idx < 3; idx++) 10721da177e4SLinus Torvalds ucontrol->value.integer.value[idx] = mix->attn[idx]; 10731da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 10741da177e4SLinus Torvalds return 0; 10751da177e4SLinus Torvalds } 10761da177e4SLinus Torvalds 1077eb4698f3STakashi Iwai static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol, 1078eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 10791da177e4SLinus Torvalds { 10801da177e4SLinus Torvalds unsigned long flags; 1081eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 1082eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = 1083eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; 10841da177e4SLinus Torvalds int change = 0, idx, val; 10851da177e4SLinus Torvalds 10861da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 10871da177e4SLinus Torvalds for (idx = 0; idx < 3; idx++) { 10881da177e4SLinus Torvalds val = ucontrol->value.integer.value[idx] & 0xffff; 10891da177e4SLinus Torvalds if (mix->attn[idx] != val) { 10901da177e4SLinus Torvalds mix->attn[idx] = val; 10911da177e4SLinus Torvalds change = 1; 10921da177e4SLinus Torvalds } 10931da177e4SLinus Torvalds } 10941da177e4SLinus Torvalds if (change && mix->epcm) { 10951da177e4SLinus Torvalds if (mix->epcm->voices[0] && mix->epcm->voices[1]) { 10961da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]); 10971da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[1]->number, mix->attn[2]); 10981da177e4SLinus Torvalds } else if (mix->epcm->voices[0]) { 10991da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]); 11001da177e4SLinus Torvalds } 11011da177e4SLinus Torvalds } 11021da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 11031da177e4SLinus Torvalds return change; 11041da177e4SLinus Torvalds } 11051da177e4SLinus Torvalds 1106eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_emu10k1_attn_control = 11071da177e4SLinus Torvalds { 11081da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 110967ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM, 11101da177e4SLinus Torvalds .name = "EMU10K1 PCM Volume", 11111da177e4SLinus Torvalds .count = 32, 11121da177e4SLinus Torvalds .info = snd_emu10k1_attn_info, 11131da177e4SLinus Torvalds .get = snd_emu10k1_attn_get, 11141da177e4SLinus Torvalds .put = snd_emu10k1_attn_put 11151da177e4SLinus Torvalds }; 11161da177e4SLinus Torvalds 11171da177e4SLinus Torvalds /* Mutichannel PCM stream controls */ 11181da177e4SLinus Torvalds 1119eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 11201da177e4SLinus Torvalds { 1121eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 11221da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 11231da177e4SLinus Torvalds uinfo->count = emu->audigy ? 8 : 4; 11241da177e4SLinus Torvalds uinfo->value.integer.min = 0; 11251da177e4SLinus Torvalds uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f; 11261da177e4SLinus Torvalds return 0; 11271da177e4SLinus Torvalds } 11281da177e4SLinus Torvalds 1129eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol, 1130eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 11311da177e4SLinus Torvalds { 11321da177e4SLinus Torvalds unsigned long flags; 1133eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 1134eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = 1135eb4698f3STakashi Iwai &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; 11361da177e4SLinus Torvalds int idx; 11371da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4; 11381da177e4SLinus Torvalds int mask = emu->audigy ? 0x3f : 0x0f; 11391da177e4SLinus Torvalds 11401da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 11411da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++) 11421da177e4SLinus Torvalds ucontrol->value.integer.value[idx] = 11431da177e4SLinus Torvalds mix->send_routing[0][idx] & mask; 11441da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 11451da177e4SLinus Torvalds return 0; 11461da177e4SLinus Torvalds } 11471da177e4SLinus Torvalds 1148eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol, 1149eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 11501da177e4SLinus Torvalds { 11511da177e4SLinus Torvalds unsigned long flags; 1152eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 11531da177e4SLinus Torvalds int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 1154eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; 11551da177e4SLinus Torvalds int change = 0, idx, val; 11561da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4; 11571da177e4SLinus Torvalds int mask = emu->audigy ? 0x3f : 0x0f; 11581da177e4SLinus Torvalds 11591da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 11601da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++) { 11611da177e4SLinus Torvalds val = ucontrol->value.integer.value[idx] & mask; 11621da177e4SLinus Torvalds if (mix->send_routing[0][idx] != val) { 11631da177e4SLinus Torvalds mix->send_routing[0][idx] = val; 11641da177e4SLinus Torvalds change = 1; 11651da177e4SLinus Torvalds } 11661da177e4SLinus Torvalds } 11671da177e4SLinus Torvalds 11681da177e4SLinus Torvalds if (change && mix->epcm) { 11691da177e4SLinus Torvalds if (mix->epcm->voices[ch]) { 11701da177e4SLinus Torvalds update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number, 11711da177e4SLinus Torvalds &mix->send_routing[0][0]); 11721da177e4SLinus Torvalds } 11731da177e4SLinus Torvalds } 11741da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 11751da177e4SLinus Torvalds return change; 11761da177e4SLinus Torvalds } 11771da177e4SLinus Torvalds 1178eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control = 11791da177e4SLinus Torvalds { 11801da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 11811da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 11821da177e4SLinus Torvalds .name = "Multichannel PCM Send Routing", 11831da177e4SLinus Torvalds .count = 16, 11841da177e4SLinus Torvalds .info = snd_emu10k1_efx_send_routing_info, 11851da177e4SLinus Torvalds .get = snd_emu10k1_efx_send_routing_get, 11861da177e4SLinus Torvalds .put = snd_emu10k1_efx_send_routing_put 11871da177e4SLinus Torvalds }; 11881da177e4SLinus Torvalds 1189eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 11901da177e4SLinus Torvalds { 1191eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 11921da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 11931da177e4SLinus Torvalds uinfo->count = emu->audigy ? 8 : 4; 11941da177e4SLinus Torvalds uinfo->value.integer.min = 0; 11951da177e4SLinus Torvalds uinfo->value.integer.max = 255; 11961da177e4SLinus Torvalds return 0; 11971da177e4SLinus Torvalds } 11981da177e4SLinus Torvalds 1199eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol, 1200eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 12011da177e4SLinus Torvalds { 12021da177e4SLinus Torvalds unsigned long flags; 1203eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 1204eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = 1205eb4698f3STakashi Iwai &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; 12061da177e4SLinus Torvalds int idx; 12071da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4; 12081da177e4SLinus Torvalds 12091da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 12101da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++) 12111da177e4SLinus Torvalds ucontrol->value.integer.value[idx] = mix->send_volume[0][idx]; 12121da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 12131da177e4SLinus Torvalds return 0; 12141da177e4SLinus Torvalds } 12151da177e4SLinus Torvalds 1216eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol, 1217eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 12181da177e4SLinus Torvalds { 12191da177e4SLinus Torvalds unsigned long flags; 1220eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 12211da177e4SLinus Torvalds int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 1222eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; 12231da177e4SLinus Torvalds int change = 0, idx, val; 12241da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4; 12251da177e4SLinus Torvalds 12261da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 12271da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++) { 12281da177e4SLinus Torvalds val = ucontrol->value.integer.value[idx] & 255; 12291da177e4SLinus Torvalds if (mix->send_volume[0][idx] != val) { 12301da177e4SLinus Torvalds mix->send_volume[0][idx] = val; 12311da177e4SLinus Torvalds change = 1; 12321da177e4SLinus Torvalds } 12331da177e4SLinus Torvalds } 12341da177e4SLinus Torvalds if (change && mix->epcm) { 12351da177e4SLinus Torvalds if (mix->epcm->voices[ch]) { 12361da177e4SLinus Torvalds update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number, 12371da177e4SLinus Torvalds &mix->send_volume[0][0]); 12381da177e4SLinus Torvalds } 12391da177e4SLinus Torvalds } 12401da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 12411da177e4SLinus Torvalds return change; 12421da177e4SLinus Torvalds } 12431da177e4SLinus Torvalds 12441da177e4SLinus Torvalds 1245eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control = 12461da177e4SLinus Torvalds { 12471da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 12481da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 12491da177e4SLinus Torvalds .name = "Multichannel PCM Send Volume", 12501da177e4SLinus Torvalds .count = 16, 12511da177e4SLinus Torvalds .info = snd_emu10k1_efx_send_volume_info, 12521da177e4SLinus Torvalds .get = snd_emu10k1_efx_send_volume_get, 12531da177e4SLinus Torvalds .put = snd_emu10k1_efx_send_volume_put 12541da177e4SLinus Torvalds }; 12551da177e4SLinus Torvalds 1256eb4698f3STakashi Iwai static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 12571da177e4SLinus Torvalds { 12581da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 12591da177e4SLinus Torvalds uinfo->count = 1; 12601da177e4SLinus Torvalds uinfo->value.integer.min = 0; 12611da177e4SLinus Torvalds uinfo->value.integer.max = 0xffff; 12621da177e4SLinus Torvalds return 0; 12631da177e4SLinus Torvalds } 12641da177e4SLinus Torvalds 1265eb4698f3STakashi Iwai static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol, 1266eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 12671da177e4SLinus Torvalds { 1268eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 1269eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = 1270eb4698f3STakashi Iwai &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)]; 12711da177e4SLinus Torvalds unsigned long flags; 12721da177e4SLinus Torvalds 12731da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 12741da177e4SLinus Torvalds ucontrol->value.integer.value[0] = mix->attn[0]; 12751da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 12761da177e4SLinus Torvalds return 0; 12771da177e4SLinus Torvalds } 12781da177e4SLinus Torvalds 1279eb4698f3STakashi Iwai static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol, 1280eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 12811da177e4SLinus Torvalds { 12821da177e4SLinus Torvalds unsigned long flags; 1283eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 12841da177e4SLinus Torvalds int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 1285eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch]; 12861da177e4SLinus Torvalds int change = 0, val; 12871da177e4SLinus Torvalds 12881da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 12891da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] & 0xffff; 12901da177e4SLinus Torvalds if (mix->attn[0] != val) { 12911da177e4SLinus Torvalds mix->attn[0] = val; 12921da177e4SLinus Torvalds change = 1; 12931da177e4SLinus Torvalds } 12941da177e4SLinus Torvalds if (change && mix->epcm) { 12951da177e4SLinus Torvalds if (mix->epcm->voices[ch]) { 12961da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]); 12971da177e4SLinus Torvalds } 12981da177e4SLinus Torvalds } 12991da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 13001da177e4SLinus Torvalds return change; 13011da177e4SLinus Torvalds } 13021da177e4SLinus Torvalds 1303eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_emu10k1_efx_attn_control = 13041da177e4SLinus Torvalds { 13051da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE, 13061da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM, 13071da177e4SLinus Torvalds .name = "Multichannel PCM Volume", 13081da177e4SLinus Torvalds .count = 16, 13091da177e4SLinus Torvalds .info = snd_emu10k1_efx_attn_info, 13101da177e4SLinus Torvalds .get = snd_emu10k1_efx_attn_get, 13111da177e4SLinus Torvalds .put = snd_emu10k1_efx_attn_put 13121da177e4SLinus Torvalds }; 13131da177e4SLinus Torvalds 1314*a5ce8890STakashi Iwai #define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info 13151da177e4SLinus Torvalds 1316eb4698f3STakashi Iwai static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol, 1317eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 13181da177e4SLinus Torvalds { 1319eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 13201da177e4SLinus Torvalds 13211da177e4SLinus Torvalds if (emu->audigy) 13221da177e4SLinus Torvalds ucontrol->value.integer.value[0] = inl(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0; 13231da177e4SLinus Torvalds else 13241da177e4SLinus Torvalds ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0; 13251da177e4SLinus Torvalds return 0; 13261da177e4SLinus Torvalds } 13271da177e4SLinus Torvalds 1328eb4698f3STakashi Iwai static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol, 1329eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol) 13301da177e4SLinus Torvalds { 13311da177e4SLinus Torvalds unsigned long flags; 1332eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); 13331da177e4SLinus Torvalds unsigned int reg, val; 13341da177e4SLinus Torvalds int change = 0; 13351da177e4SLinus Torvalds 13361da177e4SLinus Torvalds spin_lock_irqsave(&emu->reg_lock, flags); 1337184c1e2cSJames Courtier-Dutton if ( emu->card_capabilities->i2c_adc) { 1338184c1e2cSJames Courtier-Dutton /* Do nothing for Audigy 2 ZS Notebook */ 1339184c1e2cSJames Courtier-Dutton } else if (emu->audigy) { 13401da177e4SLinus Torvalds reg = inl(emu->port + A_IOCFG); 13411da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0; 13421da177e4SLinus Torvalds change = (reg & A_IOCFG_GPOUT0) != val; 13431da177e4SLinus Torvalds if (change) { 13441da177e4SLinus Torvalds reg &= ~A_IOCFG_GPOUT0; 13451da177e4SLinus Torvalds reg |= val; 13461da177e4SLinus Torvalds outl(reg | val, emu->port + A_IOCFG); 13471da177e4SLinus Torvalds } 13481da177e4SLinus Torvalds } 13491da177e4SLinus Torvalds reg = inl(emu->port + HCFG); 13501da177e4SLinus Torvalds val = ucontrol->value.integer.value[0] ? HCFG_GPOUT0 : 0; 13511da177e4SLinus Torvalds change |= (reg & HCFG_GPOUT0) != val; 13521da177e4SLinus Torvalds if (change) { 13531da177e4SLinus Torvalds reg &= ~HCFG_GPOUT0; 13541da177e4SLinus Torvalds reg |= val; 13551da177e4SLinus Torvalds outl(reg | val, emu->port + HCFG); 13561da177e4SLinus Torvalds } 13571da177e4SLinus Torvalds spin_unlock_irqrestore(&emu->reg_lock, flags); 13581da177e4SLinus Torvalds return change; 13591da177e4SLinus Torvalds } 13601da177e4SLinus Torvalds 1361eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_emu10k1_shared_spdif __devinitdata = 13621da177e4SLinus Torvalds { 13631da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 13641da177e4SLinus Torvalds .name = "SB Live Analog/Digital Output Jack", 13651da177e4SLinus Torvalds .info = snd_emu10k1_shared_spdif_info, 13661da177e4SLinus Torvalds .get = snd_emu10k1_shared_spdif_get, 13671da177e4SLinus Torvalds .put = snd_emu10k1_shared_spdif_put 13681da177e4SLinus Torvalds }; 13691da177e4SLinus Torvalds 1370eb4698f3STakashi Iwai static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata = 13711da177e4SLinus Torvalds { 13721da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 13731da177e4SLinus Torvalds .name = "Audigy Analog/Digital Output Jack", 13741da177e4SLinus Torvalds .info = snd_emu10k1_shared_spdif_info, 13751da177e4SLinus Torvalds .get = snd_emu10k1_shared_spdif_get, 13761da177e4SLinus Torvalds .put = snd_emu10k1_shared_spdif_put 13771da177e4SLinus Torvalds }; 13781da177e4SLinus Torvalds 13791da177e4SLinus Torvalds /* 13801da177e4SLinus Torvalds */ 1381eb4698f3STakashi Iwai static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97) 13821da177e4SLinus Torvalds { 1383eb4698f3STakashi Iwai struct snd_emu10k1 *emu = ac97->private_data; 13841da177e4SLinus Torvalds emu->ac97 = NULL; 13851da177e4SLinus Torvalds } 13861da177e4SLinus Torvalds 13871da177e4SLinus Torvalds /* 13881da177e4SLinus Torvalds */ 1389eb4698f3STakashi Iwai static int remove_ctl(struct snd_card *card, const char *name) 13901da177e4SLinus Torvalds { 1391eb4698f3STakashi Iwai struct snd_ctl_elem_id id; 13921da177e4SLinus Torvalds memset(&id, 0, sizeof(id)); 13931da177e4SLinus Torvalds strcpy(id.name, name); 13941da177e4SLinus Torvalds id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 13951da177e4SLinus Torvalds return snd_ctl_remove_id(card, &id); 13961da177e4SLinus Torvalds } 13971da177e4SLinus Torvalds 1398eb4698f3STakashi Iwai static struct snd_kcontrol *ctl_find(struct snd_card *card, const char *name) 13991da177e4SLinus Torvalds { 1400eb4698f3STakashi Iwai struct snd_ctl_elem_id sid; 14011da177e4SLinus Torvalds memset(&sid, 0, sizeof(sid)); 14021da177e4SLinus Torvalds strcpy(sid.name, name); 14031da177e4SLinus Torvalds sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 14041da177e4SLinus Torvalds return snd_ctl_find_id(card, &sid); 14051da177e4SLinus Torvalds } 14061da177e4SLinus Torvalds 1407eb4698f3STakashi Iwai static int rename_ctl(struct snd_card *card, const char *src, const char *dst) 14081da177e4SLinus Torvalds { 1409eb4698f3STakashi Iwai struct snd_kcontrol *kctl = ctl_find(card, src); 14101da177e4SLinus Torvalds if (kctl) { 14111da177e4SLinus Torvalds strcpy(kctl->id.name, dst); 14121da177e4SLinus Torvalds return 0; 14131da177e4SLinus Torvalds } 14141da177e4SLinus Torvalds return -ENOENT; 14151da177e4SLinus Torvalds } 14161da177e4SLinus Torvalds 1417eb4698f3STakashi Iwai int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, 141867ed4161SClemens Ladisch int pcm_device, int multi_device) 14191da177e4SLinus Torvalds { 14201da177e4SLinus Torvalds int err, pcm; 1421eb4698f3STakashi Iwai struct snd_kcontrol *kctl; 1422eb4698f3STakashi Iwai struct snd_card *card = emu->card; 14231da177e4SLinus Torvalds char **c; 14241da177e4SLinus Torvalds static char *emu10k1_remove_ctls[] = { 14251da177e4SLinus Torvalds /* no AC97 mono, surround, center/lfe */ 14261da177e4SLinus Torvalds "Master Mono Playback Switch", 14271da177e4SLinus Torvalds "Master Mono Playback Volume", 14281da177e4SLinus Torvalds "PCM Out Path & Mute", 14291da177e4SLinus Torvalds "Mono Output Select", 14307eae36fbSTakashi Iwai "Front Playback Switch", 14317eae36fbSTakashi Iwai "Front Playback Volume", 14321da177e4SLinus Torvalds "Surround Playback Switch", 14331da177e4SLinus Torvalds "Surround Playback Volume", 14341da177e4SLinus Torvalds "Center Playback Switch", 14351da177e4SLinus Torvalds "Center Playback Volume", 14361da177e4SLinus Torvalds "LFE Playback Switch", 14371da177e4SLinus Torvalds "LFE Playback Volume", 14381da177e4SLinus Torvalds NULL 14391da177e4SLinus Torvalds }; 14401da177e4SLinus Torvalds static char *emu10k1_rename_ctls[] = { 14411da177e4SLinus Torvalds "Surround Digital Playback Volume", "Surround Playback Volume", 14421da177e4SLinus Torvalds "Center Digital Playback Volume", "Center Playback Volume", 14431da177e4SLinus Torvalds "LFE Digital Playback Volume", "LFE Playback Volume", 14441da177e4SLinus Torvalds NULL 14451da177e4SLinus Torvalds }; 14461da177e4SLinus Torvalds static char *audigy_remove_ctls[] = { 14471da177e4SLinus Torvalds /* Master/PCM controls on ac97 of Audigy has no effect */ 144821fdddeaSJames Courtier-Dutton /* On the Audigy2 the AC97 playback is piped into 144921fdddeaSJames Courtier-Dutton * the Philips ADC for 24bit capture */ 14501da177e4SLinus Torvalds "PCM Playback Switch", 14511da177e4SLinus Torvalds "PCM Playback Volume", 14521da177e4SLinus Torvalds "Master Mono Playback Switch", 14531da177e4SLinus Torvalds "Master Mono Playback Volume", 14541da177e4SLinus Torvalds "Master Playback Switch", 14551da177e4SLinus Torvalds "Master Playback Volume", 14561da177e4SLinus Torvalds "PCM Out Path & Mute", 14571da177e4SLinus Torvalds "Mono Output Select", 14581da177e4SLinus Torvalds /* remove unused AC97 capture controls */ 14591da177e4SLinus Torvalds "Capture Source", 14601da177e4SLinus Torvalds "Capture Switch", 14611da177e4SLinus Torvalds "Capture Volume", 14621da177e4SLinus Torvalds "Mic Select", 14631da177e4SLinus Torvalds "Video Playback Switch", 14641da177e4SLinus Torvalds "Video Playback Volume", 14651da177e4SLinus Torvalds "Mic Playback Switch", 14661da177e4SLinus Torvalds "Mic Playback Volume", 14671da177e4SLinus Torvalds NULL 14681da177e4SLinus Torvalds }; 14691da177e4SLinus Torvalds static char *audigy_rename_ctls[] = { 14701da177e4SLinus Torvalds /* use conventional names */ 14711da177e4SLinus Torvalds "Wave Playback Volume", "PCM Playback Volume", 14721da177e4SLinus Torvalds /* "Wave Capture Volume", "PCM Capture Volume", */ 14731da177e4SLinus Torvalds "Wave Master Playback Volume", "Master Playback Volume", 14741da177e4SLinus Torvalds "AMic Playback Volume", "Mic Playback Volume", 14751da177e4SLinus Torvalds NULL 14761da177e4SLinus Torvalds }; 1477184c1e2cSJames Courtier-Dutton static char *audigy_rename_ctls_i2c_adc[] = { 1478184c1e2cSJames Courtier-Dutton //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume", 1479184c1e2cSJames Courtier-Dutton "Line Capture Volume", "Analog Mix Capture Volume", 1480184c1e2cSJames Courtier-Dutton "Wave Playback Volume", "OLD PCM Playback Volume", 1481184c1e2cSJames Courtier-Dutton "Wave Master Playback Volume", "Master Playback Volume", 1482184c1e2cSJames Courtier-Dutton "AMic Playback Volume", "Old Mic Playback Volume", 1483eb41dab6SJames Courtier-Dutton "CD Capture Volume", "IEC958 Optical Capture Volume", 1484184c1e2cSJames Courtier-Dutton NULL 1485184c1e2cSJames Courtier-Dutton }; 1486184c1e2cSJames Courtier-Dutton static char *audigy_remove_ctls_i2c_adc[] = { 1487184c1e2cSJames Courtier-Dutton /* On the Audigy2 ZS Notebook 1488184c1e2cSJames Courtier-Dutton * Capture via WM8775 */ 1489184c1e2cSJames Courtier-Dutton "Mic Capture Volume", 1490184c1e2cSJames Courtier-Dutton "Analog Mix Capture Volume", 1491184c1e2cSJames Courtier-Dutton "Aux Capture Volume", 1492eb41dab6SJames Courtier-Dutton "IEC958 Optical Capture Volume", 1493184c1e2cSJames Courtier-Dutton NULL 1494184c1e2cSJames Courtier-Dutton }; 149521fdddeaSJames Courtier-Dutton static char *audigy_remove_ctls_1361t_adc[] = { 149621fdddeaSJames Courtier-Dutton /* On the Audigy2 the AC97 playback is piped into 149721fdddeaSJames Courtier-Dutton * the Philips ADC for 24bit capture */ 149821fdddeaSJames Courtier-Dutton "PCM Playback Switch", 149921fdddeaSJames Courtier-Dutton "PCM Playback Volume", 150021fdddeaSJames Courtier-Dutton "Master Mono Playback Switch", 150121fdddeaSJames Courtier-Dutton "Master Mono Playback Volume", 150221fdddeaSJames Courtier-Dutton "Capture Source", 150321fdddeaSJames Courtier-Dutton "Capture Switch", 150421fdddeaSJames Courtier-Dutton "Capture Volume", 150521fdddeaSJames Courtier-Dutton "Mic Capture Volume", 150621fdddeaSJames Courtier-Dutton "Headphone Playback Switch", 150721fdddeaSJames Courtier-Dutton "Headphone Playback Volume", 150821fdddeaSJames Courtier-Dutton "3D Control - Center", 150921fdddeaSJames Courtier-Dutton "3D Control - Depth", 151021fdddeaSJames Courtier-Dutton "3D Control - Switch", 151121fdddeaSJames Courtier-Dutton "Line2 Playback Volume", 151221fdddeaSJames Courtier-Dutton "Line2 Capture Volume", 151321fdddeaSJames Courtier-Dutton NULL 151421fdddeaSJames Courtier-Dutton }; 151521fdddeaSJames Courtier-Dutton static char *audigy_rename_ctls_1361t_adc[] = { 151621fdddeaSJames Courtier-Dutton "Master Playback Switch", "Master Capture Switch", 151721fdddeaSJames Courtier-Dutton "Master Playback Volume", "Master Capture Volume", 151821fdddeaSJames Courtier-Dutton "Wave Master Playback Volume", "Master Playback Volume", 151921fdddeaSJames Courtier-Dutton "PC Speaker Playback Switch", "PC Speaker Capture Switch", 152021fdddeaSJames Courtier-Dutton "PC Speaker Playback Volume", "PC Speaker Capture Volume", 152121fdddeaSJames Courtier-Dutton "Phone Playback Switch", "Phone Capture Switch", 152221fdddeaSJames Courtier-Dutton "Phone Playback Volume", "Phone Capture Volume", 152321fdddeaSJames Courtier-Dutton "Mic Playback Switch", "Mic Capture Switch", 152421fdddeaSJames Courtier-Dutton "Mic Playback Volume", "Mic Capture Volume", 152521fdddeaSJames Courtier-Dutton "Line Playback Switch", "Line Capture Switch", 152621fdddeaSJames Courtier-Dutton "Line Playback Volume", "Line Capture Volume", 152721fdddeaSJames Courtier-Dutton "CD Playback Switch", "CD Capture Switch", 152821fdddeaSJames Courtier-Dutton "CD Playback Volume", "CD Capture Volume", 152921fdddeaSJames Courtier-Dutton "Aux Playback Switch", "Aux Capture Switch", 153021fdddeaSJames Courtier-Dutton "Aux Playback Volume", "Aux Capture Volume", 153121fdddeaSJames Courtier-Dutton "Video Playback Switch", "Video Capture Switch", 153221fdddeaSJames Courtier-Dutton "Video Playback Volume", "Video Capture Volume", 153321fdddeaSJames Courtier-Dutton 153421fdddeaSJames Courtier-Dutton NULL 153521fdddeaSJames Courtier-Dutton }; 15361da177e4SLinus Torvalds 15372b637da5SLee Revell if (emu->card_capabilities->ac97_chip) { 1538eb4698f3STakashi Iwai struct snd_ac97_bus *pbus; 1539eb4698f3STakashi Iwai struct snd_ac97_template ac97; 1540eb4698f3STakashi Iwai static struct snd_ac97_bus_ops ops = { 15411da177e4SLinus Torvalds .write = snd_emu10k1_ac97_write, 15421da177e4SLinus Torvalds .read = snd_emu10k1_ac97_read, 15431da177e4SLinus Torvalds }; 15441da177e4SLinus Torvalds 1545b1508693STakashi Iwai if ((err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus)) < 0) 15461da177e4SLinus Torvalds return err; 15471da177e4SLinus Torvalds pbus->no_vra = 1; /* we don't need VRA */ 15481da177e4SLinus Torvalds 15491da177e4SLinus Torvalds memset(&ac97, 0, sizeof(ac97)); 15501da177e4SLinus Torvalds ac97.private_data = emu; 15511da177e4SLinus Torvalds ac97.private_free = snd_emu10k1_mixer_free_ac97; 15521da177e4SLinus Torvalds ac97.scaps = AC97_SCAP_NO_SPDIF; 1553b1508693STakashi Iwai if ((err = snd_ac97_mixer(pbus, &ac97, &emu->ac97)) < 0) { 1554b1508693STakashi Iwai if (emu->card_capabilities->ac97_chip == 1) 15551da177e4SLinus Torvalds return err; 1556b1508693STakashi Iwai snd_printd(KERN_INFO "emu10k1: AC97 is optional on this board\n"); 1557b1508693STakashi Iwai snd_printd(KERN_INFO" Proceeding without ac97 mixers...\n"); 1558b1508693STakashi Iwai snd_device_free(emu->card, pbus); 1559b1508693STakashi Iwai goto no_ac97; /* FIXME: get rid of ugly gotos.. */ 1560b1508693STakashi Iwai } 15611da177e4SLinus Torvalds if (emu->audigy) { 15621da177e4SLinus Torvalds /* set master volume to 0 dB */ 15634d7d7596STakashi Iwai snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000); 15641da177e4SLinus Torvalds /* set capture source to mic */ 15654d7d7596STakashi Iwai snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000); 156621fdddeaSJames Courtier-Dutton if (emu->card_capabilities->adc_1361t) 156721fdddeaSJames Courtier-Dutton c = audigy_remove_ctls_1361t_adc; 156821fdddeaSJames Courtier-Dutton else 15691da177e4SLinus Torvalds c = audigy_remove_ctls; 15701da177e4SLinus Torvalds } else { 15711da177e4SLinus Torvalds /* 15721da177e4SLinus Torvalds * Credits for cards based on STAC9758: 15731da177e4SLinus Torvalds * James Courtier-Dutton <James@superbug.demon.co.uk> 15741da177e4SLinus Torvalds * Voluspa <voluspa@comhem.se> 15751da177e4SLinus Torvalds */ 15761da177e4SLinus Torvalds if (emu->ac97->id == AC97_ID_STAC9758) { 15771da177e4SLinus Torvalds emu->rear_ac97 = 1; 15781da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT); 15792594d960SRolf Stefan Wilke snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202); 15801da177e4SLinus Torvalds } 15811da177e4SLinus Torvalds /* remove unused AC97 controls */ 15824d7d7596STakashi Iwai snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202); 15834d7d7596STakashi Iwai snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202); 15841da177e4SLinus Torvalds c = emu10k1_remove_ctls; 15851da177e4SLinus Torvalds } 15861da177e4SLinus Torvalds for (; *c; c++) 15871da177e4SLinus Torvalds remove_ctl(card, *c); 1588184c1e2cSJames Courtier-Dutton } else if (emu->card_capabilities->i2c_adc) { 1589184c1e2cSJames Courtier-Dutton c = audigy_remove_ctls_i2c_adc; 1590184c1e2cSJames Courtier-Dutton for (; *c; c++) 1591184c1e2cSJames Courtier-Dutton remove_ctl(card, *c); 15921da177e4SLinus Torvalds } else { 1593f12aa40cSTakashi Iwai no_ac97: 15942b637da5SLee Revell if (emu->card_capabilities->ecard) 15951da177e4SLinus Torvalds strcpy(emu->card->mixername, "EMU APS"); 15961da177e4SLinus Torvalds else if (emu->audigy) 15971da177e4SLinus Torvalds strcpy(emu->card->mixername, "SB Audigy"); 15981da177e4SLinus Torvalds else 15991da177e4SLinus Torvalds strcpy(emu->card->mixername, "Emu10k1"); 16001da177e4SLinus Torvalds } 16011da177e4SLinus Torvalds 16021da177e4SLinus Torvalds if (emu->audigy) 160321fdddeaSJames Courtier-Dutton if (emu->card_capabilities->adc_1361t) 160421fdddeaSJames Courtier-Dutton c = audigy_rename_ctls_1361t_adc; 1605184c1e2cSJames Courtier-Dutton else if (emu->card_capabilities->i2c_adc) 1606184c1e2cSJames Courtier-Dutton c = audigy_rename_ctls_i2c_adc; 160721fdddeaSJames Courtier-Dutton else 16081da177e4SLinus Torvalds c = audigy_rename_ctls; 16091da177e4SLinus Torvalds else 16101da177e4SLinus Torvalds c = emu10k1_rename_ctls; 16111da177e4SLinus Torvalds for (; *c; c += 2) 16121da177e4SLinus Torvalds rename_ctl(card, c[0], c[1]); 161321fdddeaSJames Courtier-Dutton 1614e3b9bc0eSJames Courtier-Dutton if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */ 1615e3b9bc0eSJames Courtier-Dutton rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume"); 1616e3b9bc0eSJames Courtier-Dutton rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume"); 1617e3b9bc0eSJames Courtier-Dutton rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume"); 1618e3b9bc0eSJames Courtier-Dutton rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume"); 1619e3b9bc0eSJames Courtier-Dutton remove_ctl(card, "Headphone Playback Switch"); 1620e3b9bc0eSJames Courtier-Dutton remove_ctl(card, "Headphone Playback Volume"); 1621e3b9bc0eSJames Courtier-Dutton remove_ctl(card, "3D Control - Center"); 1622e3b9bc0eSJames Courtier-Dutton remove_ctl(card, "3D Control - Depth"); 1623e3b9bc0eSJames Courtier-Dutton remove_ctl(card, "3D Control - Switch"); 1624e3b9bc0eSJames Courtier-Dutton } 16251da177e4SLinus Torvalds if ((kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu)) == NULL) 16261da177e4SLinus Torvalds return -ENOMEM; 162767ed4161SClemens Ladisch kctl->id.device = pcm_device; 16281da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 16291da177e4SLinus Torvalds return err; 16301da177e4SLinus Torvalds if ((kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu)) == NULL) 16311da177e4SLinus Torvalds return -ENOMEM; 163267ed4161SClemens Ladisch kctl->id.device = pcm_device; 16331da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 16341da177e4SLinus Torvalds return err; 16351da177e4SLinus Torvalds if ((kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu)) == NULL) 16361da177e4SLinus Torvalds return -ENOMEM; 163767ed4161SClemens Ladisch kctl->id.device = pcm_device; 16381da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 16391da177e4SLinus Torvalds return err; 16401da177e4SLinus Torvalds 16411da177e4SLinus Torvalds if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL) 16421da177e4SLinus Torvalds return -ENOMEM; 164367ed4161SClemens Ladisch kctl->id.device = multi_device; 16441da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 16451da177e4SLinus Torvalds return err; 16461da177e4SLinus Torvalds 16471da177e4SLinus Torvalds if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL) 16481da177e4SLinus Torvalds return -ENOMEM; 164967ed4161SClemens Ladisch kctl->id.device = multi_device; 16501da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 16511da177e4SLinus Torvalds return err; 16521da177e4SLinus Torvalds 16531da177e4SLinus Torvalds if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL) 16541da177e4SLinus Torvalds return -ENOMEM; 165567ed4161SClemens Ladisch kctl->id.device = multi_device; 16561da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 16571da177e4SLinus Torvalds return err; 16581da177e4SLinus Torvalds 16591da177e4SLinus Torvalds /* initialize the routing and volume table for each pcm playback stream */ 16601da177e4SLinus Torvalds for (pcm = 0; pcm < 32; pcm++) { 1661eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix; 16621da177e4SLinus Torvalds int v; 16631da177e4SLinus Torvalds 16641da177e4SLinus Torvalds mix = &emu->pcm_mixer[pcm]; 16651da177e4SLinus Torvalds mix->epcm = NULL; 16661da177e4SLinus Torvalds 16671da177e4SLinus Torvalds for (v = 0; v < 4; v++) 16681da177e4SLinus Torvalds mix->send_routing[0][v] = 16691da177e4SLinus Torvalds mix->send_routing[1][v] = 16701da177e4SLinus Torvalds mix->send_routing[2][v] = v; 16711da177e4SLinus Torvalds 16721da177e4SLinus Torvalds memset(&mix->send_volume, 0, sizeof(mix->send_volume)); 16731da177e4SLinus Torvalds mix->send_volume[0][0] = mix->send_volume[0][1] = 16741da177e4SLinus Torvalds mix->send_volume[1][0] = mix->send_volume[2][1] = 255; 16751da177e4SLinus Torvalds 16761da177e4SLinus Torvalds mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff; 16771da177e4SLinus Torvalds } 16781da177e4SLinus Torvalds 16791da177e4SLinus Torvalds /* initialize the routing and volume table for the multichannel playback stream */ 16801da177e4SLinus Torvalds for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) { 1681eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix; 16821da177e4SLinus Torvalds int v; 16831da177e4SLinus Torvalds 16841da177e4SLinus Torvalds mix = &emu->efx_pcm_mixer[pcm]; 16851da177e4SLinus Torvalds mix->epcm = NULL; 16861da177e4SLinus Torvalds 16871da177e4SLinus Torvalds mix->send_routing[0][0] = pcm; 16881da177e4SLinus Torvalds mix->send_routing[0][1] = (pcm == 0) ? 1 : 0; 16891da177e4SLinus Torvalds for (v = 0; v < 2; v++) 16901da177e4SLinus Torvalds mix->send_routing[0][2+v] = 13+v; 16911da177e4SLinus Torvalds if (emu->audigy) 16921da177e4SLinus Torvalds for (v = 0; v < 4; v++) 16931da177e4SLinus Torvalds mix->send_routing[0][4+v] = 60+v; 16941da177e4SLinus Torvalds 16951da177e4SLinus Torvalds memset(&mix->send_volume, 0, sizeof(mix->send_volume)); 16961da177e4SLinus Torvalds mix->send_volume[0][0] = 255; 16971da177e4SLinus Torvalds 16981da177e4SLinus Torvalds mix->attn[0] = 0xffff; 16991da177e4SLinus Torvalds } 17001da177e4SLinus Torvalds 17012b637da5SLee Revell if (! emu->card_capabilities->ecard) { /* FIXME: APS has these controls? */ 17021da177e4SLinus Torvalds /* sb live! and audigy */ 17031da177e4SLinus Torvalds if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL) 17041da177e4SLinus Torvalds return -ENOMEM; 17055549d549SClemens Ladisch if (!emu->audigy) 17065549d549SClemens Ladisch kctl->id.device = emu->pcm_efx->device; 17071da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 17081da177e4SLinus Torvalds return err; 17091da177e4SLinus Torvalds if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu)) == NULL) 17101da177e4SLinus Torvalds return -ENOMEM; 17115549d549SClemens Ladisch if (!emu->audigy) 17125549d549SClemens Ladisch kctl->id.device = emu->pcm_efx->device; 17131da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 17141da177e4SLinus Torvalds return err; 17151da177e4SLinus Torvalds } 17161da177e4SLinus Torvalds 17179f4bd5ddSJames Courtier-Dutton if ( emu->card_capabilities->emu1010) { 171819b99fbaSJames Courtier-Dutton ; /* Disable the snd_audigy_spdif_shared_spdif */ 171919b99fbaSJames Courtier-Dutton } else if (emu->audigy) { 17201da177e4SLinus Torvalds if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL) 17211da177e4SLinus Torvalds return -ENOMEM; 17221da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 17231da177e4SLinus Torvalds return err; 1724001f7589SJames Courtier-Dutton #if 0 17251da177e4SLinus Torvalds if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL) 17261da177e4SLinus Torvalds return -ENOMEM; 17271da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 17281da177e4SLinus Torvalds return err; 1729001f7589SJames Courtier-Dutton #endif 17302b637da5SLee Revell } else if (! emu->card_capabilities->ecard) { 17311da177e4SLinus Torvalds /* sb live! */ 17321da177e4SLinus Torvalds if ((kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu)) == NULL) 17331da177e4SLinus Torvalds return -ENOMEM; 17341da177e4SLinus Torvalds if ((err = snd_ctl_add(card, kctl))) 17351da177e4SLinus Torvalds return err; 17361da177e4SLinus Torvalds } 17372b637da5SLee Revell if (emu->card_capabilities->ca0151_chip) { /* P16V */ 17381da177e4SLinus Torvalds if ((err = snd_p16v_mixer(emu))) 17391da177e4SLinus Torvalds return err; 17401da177e4SLinus Torvalds } 17411da177e4SLinus Torvalds 17429f4bd5ddSJames Courtier-Dutton if ( emu->card_capabilities->emu1010) { 17439f4bd5ddSJames Courtier-Dutton int i; 17449f4bd5ddSJames Courtier-Dutton 17459f4bd5ddSJames Courtier-Dutton for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) { 17469f4bd5ddSJames Courtier-Dutton err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu)); 17479f4bd5ddSJames Courtier-Dutton if (err < 0) 17489f4bd5ddSJames Courtier-Dutton return err; 17499f4bd5ddSJames Courtier-Dutton } 17509f4bd5ddSJames Courtier-Dutton for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) { 17519f4bd5ddSJames Courtier-Dutton err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu)); 17529f4bd5ddSJames Courtier-Dutton if (err < 0) 17539f4bd5ddSJames Courtier-Dutton return err; 17549f4bd5ddSJames Courtier-Dutton } 17559148cc50SJames Courtier-Dutton for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) { 17569148cc50SJames Courtier-Dutton err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu)); 17579148cc50SJames Courtier-Dutton if (err < 0) 17589148cc50SJames Courtier-Dutton return err; 17599148cc50SJames Courtier-Dutton } 17609148cc50SJames Courtier-Dutton for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) { 17619148cc50SJames Courtier-Dutton err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu)); 17629148cc50SJames Courtier-Dutton if (err < 0) 17639148cc50SJames Courtier-Dutton return err; 17649148cc50SJames Courtier-Dutton } 1765b0dbdaeaSJames Courtier-Dutton err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu)); 1766b0dbdaeaSJames Courtier-Dutton if (err < 0) 1767b0dbdaeaSJames Courtier-Dutton return err; 17689f4bd5ddSJames Courtier-Dutton } 17699f4bd5ddSJames Courtier-Dutton 1770184c1e2cSJames Courtier-Dutton if ( emu->card_capabilities->i2c_adc) { 1771184c1e2cSJames Courtier-Dutton int i; 1772184c1e2cSJames Courtier-Dutton 1773184c1e2cSJames Courtier-Dutton err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu)); 1774184c1e2cSJames Courtier-Dutton if (err < 0) 1775184c1e2cSJames Courtier-Dutton return err; 1776184c1e2cSJames Courtier-Dutton 1777184c1e2cSJames Courtier-Dutton for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) { 1778184c1e2cSJames Courtier-Dutton err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu)); 1779184c1e2cSJames Courtier-Dutton if (err < 0) 1780184c1e2cSJames Courtier-Dutton return err; 1781184c1e2cSJames Courtier-Dutton } 1782184c1e2cSJames Courtier-Dutton } 1783184c1e2cSJames Courtier-Dutton 17841da177e4SLinus Torvalds return 0; 17851da177e4SLinus Torvalds } 1786