11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
3c1017a4cSJaroslav Kysela * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
41da177e4SLinus Torvalds * Takashi Iwai <tiwai@suse.de>
56d68d9cbSOswald Buddenhagen * Lee Revell <rlrevell@joe-job.com>
66d68d9cbSOswald Buddenhagen * James Courtier-Dutton <James@superbug.co.uk>
76d68d9cbSOswald Buddenhagen * Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
81da177e4SLinus Torvalds * Creative Labs, Inc.
91da177e4SLinus Torvalds *
106d68d9cbSOswald Buddenhagen * Routines for control of EMU10K1 chips / mixer routines
111da177e4SLinus Torvalds */
121da177e4SLinus Torvalds
131da177e4SLinus Torvalds #include <linux/time.h>
141da177e4SLinus Torvalds #include <linux/init.h>
151da177e4SLinus Torvalds #include <sound/core.h>
161da177e4SLinus Torvalds #include <sound/emu10k1.h>
17b0dbdaeaSJames Courtier-Dutton #include <linux/delay.h>
18184c1e2cSJames Courtier-Dutton #include <sound/tlv.h>
19184c1e2cSJames Courtier-Dutton
20184c1e2cSJames Courtier-Dutton #include "p17v.h"
211da177e4SLinus Torvalds
221da177e4SLinus Torvalds #define AC97_ID_STAC9758 0x83847658
231da177e4SLinus Torvalds
240cb29ea0STakashi Iwai static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */
25184c1e2cSJames Courtier-Dutton
26536438f1SOswald Buddenhagen
add_ctls(struct snd_emu10k1 * emu,const struct snd_kcontrol_new * tpl,const char * const * ctls,unsigned nctls)27536438f1SOswald Buddenhagen static int add_ctls(struct snd_emu10k1 *emu, const struct snd_kcontrol_new *tpl,
28536438f1SOswald Buddenhagen const char * const *ctls, unsigned nctls)
29536438f1SOswald Buddenhagen {
30536438f1SOswald Buddenhagen struct snd_kcontrol_new kctl = *tpl;
31536438f1SOswald Buddenhagen int err;
32536438f1SOswald Buddenhagen
33536438f1SOswald Buddenhagen for (unsigned i = 0; i < nctls; i++) {
34536438f1SOswald Buddenhagen kctl.name = ctls[i];
35536438f1SOswald Buddenhagen kctl.private_value = i;
36536438f1SOswald Buddenhagen err = snd_ctl_add(emu->card, snd_ctl_new1(&kctl, emu));
37536438f1SOswald Buddenhagen if (err < 0)
38536438f1SOswald Buddenhagen return err;
39536438f1SOswald Buddenhagen }
40536438f1SOswald Buddenhagen return 0;
41536438f1SOswald Buddenhagen }
42536438f1SOswald Buddenhagen
43536438f1SOswald Buddenhagen
snd_emu10k1_spdif_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)44eb4698f3STakashi Iwai static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
451da177e4SLinus Torvalds {
461da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
471da177e4SLinus Torvalds uinfo->count = 1;
481da177e4SLinus Torvalds return 0;
491da177e4SLinus Torvalds }
501da177e4SLinus Torvalds
snd_emu10k1_spdif_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)51eb4698f3STakashi Iwai static int snd_emu10k1_spdif_get(struct snd_kcontrol *kcontrol,
52eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
531da177e4SLinus Torvalds {
54eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
551da177e4SLinus Torvalds unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
561da177e4SLinus Torvalds
5774415a36SJames Courtier-Dutton /* Limit: emu->spdif_bits */
5874415a36SJames Courtier-Dutton if (idx >= 3)
5974415a36SJames Courtier-Dutton return -EINVAL;
601da177e4SLinus Torvalds ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff;
611da177e4SLinus Torvalds ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff;
621da177e4SLinus Torvalds ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff;
631da177e4SLinus Torvalds ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff;
641da177e4SLinus Torvalds return 0;
651da177e4SLinus Torvalds }
661da177e4SLinus Torvalds
snd_emu10k1_spdif_get_mask(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)67eb4698f3STakashi Iwai static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
68eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
691da177e4SLinus Torvalds {
701da177e4SLinus Torvalds ucontrol->value.iec958.status[0] = 0xff;
711da177e4SLinus Torvalds ucontrol->value.iec958.status[1] = 0xff;
721da177e4SLinus Torvalds ucontrol->value.iec958.status[2] = 0xff;
731da177e4SLinus Torvalds ucontrol->value.iec958.status[3] = 0xff;
741da177e4SLinus Torvalds return 0;
751da177e4SLinus Torvalds }
761da177e4SLinus Torvalds
77dc39bb3eSOswald Buddenhagen #define PAIR_PS(base, one, two, sfx) base " " one sfx, base " " two sfx
78dc39bb3eSOswald Buddenhagen #define LR_PS(base, sfx) PAIR_PS(base, "Left", "Right", sfx)
799f4bd5ddSJames Courtier-Dutton
80dc39bb3eSOswald Buddenhagen #define ADAT_PS(pfx, sfx) \
81dc39bb3eSOswald Buddenhagen pfx "ADAT 0" sfx, pfx "ADAT 1" sfx, pfx "ADAT 2" sfx, pfx "ADAT 3" sfx, \
82dc39bb3eSOswald Buddenhagen pfx "ADAT 4" sfx, pfx "ADAT 5" sfx, pfx "ADAT 6" sfx, pfx "ADAT 7" sfx
831c02e366SCtirad Fertr
84dc39bb3eSOswald Buddenhagen #define PAIR_REGS(base, one, two) \
85dc39bb3eSOswald Buddenhagen base ## one ## 1, \
86dc39bb3eSOswald Buddenhagen base ## two ## 1
871c02e366SCtirad Fertr
88dc39bb3eSOswald Buddenhagen #define LR_REGS(base) PAIR_REGS(base, _LEFT, _RIGHT)
89dc39bb3eSOswald Buddenhagen
90dc39bb3eSOswald Buddenhagen #define ADAT_REGS(base) \
91dc39bb3eSOswald Buddenhagen base+0, base+1, base+2, base+3, base+4, base+5, base+6, base+7
921c02e366SCtirad Fertr
9313d45709SPavel Hofman /*
9413d45709SPavel Hofman * List of data sources available for each destination
9513d45709SPavel Hofman */
96dc39bb3eSOswald Buddenhagen
97dc39bb3eSOswald Buddenhagen #define DSP_TEXTS \
98dc39bb3eSOswald Buddenhagen "DSP 0", "DSP 1", "DSP 2", "DSP 3", "DSP 4", "DSP 5", "DSP 6", "DSP 7", \
99dc39bb3eSOswald Buddenhagen "DSP 8", "DSP 9", "DSP 10", "DSP 11", "DSP 12", "DSP 13", "DSP 14", "DSP 15", \
100dc39bb3eSOswald Buddenhagen "DSP 16", "DSP 17", "DSP 18", "DSP 19", "DSP 20", "DSP 21", "DSP 22", "DSP 23", \
101dc39bb3eSOswald Buddenhagen "DSP 24", "DSP 25", "DSP 26", "DSP 27", "DSP 28", "DSP 29", "DSP 30", "DSP 31"
102dc39bb3eSOswald Buddenhagen
103dc39bb3eSOswald Buddenhagen #define PAIR_TEXTS(base, one, two) PAIR_PS(base, one, two, "")
104dc39bb3eSOswald Buddenhagen #define LR_TEXTS(base) LR_PS(base, "")
105dc39bb3eSOswald Buddenhagen #define ADAT_TEXTS(pfx) ADAT_PS(pfx, "")
106dc39bb3eSOswald Buddenhagen
107dc39bb3eSOswald Buddenhagen #define EMU32_SRC_REGS \
108dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A, \
109dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+1, \
110dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+2, \
111dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+3, \
112dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+4, \
113dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+5, \
114dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+6, \
115dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+7, \
116dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+8, \
117dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+9, \
118dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0xa, \
119dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0xb, \
120dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0xc, \
121dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0xd, \
122dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0xe, \
123dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0xf, \
124dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B, \
125dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+1, \
126dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+2, \
127dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+3, \
128dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+4, \
129dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+5, \
130dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+6, \
131dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+7, \
132dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+8, \
133dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+9, \
134dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+0xa, \
135dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+0xb, \
136dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+0xc, \
137dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+0xd, \
138dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+0xe, \
139dc39bb3eSOswald Buddenhagen EMU_SRC_ALICE_EMU32B+0xf
140dc39bb3eSOswald Buddenhagen
1416f3609f8SOswald Buddenhagen /* 1010 rev1 */
1426f3609f8SOswald Buddenhagen
143dc39bb3eSOswald Buddenhagen #define EMU1010_COMMON_TEXTS \
144dc39bb3eSOswald Buddenhagen "Silence", \
145dc39bb3eSOswald Buddenhagen PAIR_TEXTS("Dock Mic", "A", "B"), \
146dc39bb3eSOswald Buddenhagen LR_TEXTS("Dock ADC1"), \
147dc39bb3eSOswald Buddenhagen LR_TEXTS("Dock ADC2"), \
148dc39bb3eSOswald Buddenhagen LR_TEXTS("Dock ADC3"), \
149dc39bb3eSOswald Buddenhagen LR_TEXTS("0202 ADC"), \
150dc39bb3eSOswald Buddenhagen LR_TEXTS("1010 SPDIF"), \
151dc39bb3eSOswald Buddenhagen ADAT_TEXTS("1010 ")
152dc39bb3eSOswald Buddenhagen
153dc39bb3eSOswald Buddenhagen static const char * const emu1010_src_texts[] = {
154dc39bb3eSOswald Buddenhagen EMU1010_COMMON_TEXTS,
155dc39bb3eSOswald Buddenhagen DSP_TEXTS,
1569f4bd5ddSJames Courtier-Dutton };
1579f4bd5ddSJames Courtier-Dutton
158dc39bb3eSOswald Buddenhagen static const unsigned short emu1010_src_regs[] = {
159dc39bb3eSOswald Buddenhagen EMU_SRC_SILENCE,
160dc39bb3eSOswald Buddenhagen PAIR_REGS(EMU_SRC_DOCK_MIC, _A, _B),
161dc39bb3eSOswald Buddenhagen LR_REGS(EMU_SRC_DOCK_ADC1),
162dc39bb3eSOswald Buddenhagen LR_REGS(EMU_SRC_DOCK_ADC2),
163dc39bb3eSOswald Buddenhagen LR_REGS(EMU_SRC_DOCK_ADC3),
164dc39bb3eSOswald Buddenhagen LR_REGS(EMU_SRC_HAMOA_ADC),
165dc39bb3eSOswald Buddenhagen LR_REGS(EMU_SRC_HANA_SPDIF),
166dc39bb3eSOswald Buddenhagen ADAT_REGS(EMU_SRC_HANA_ADAT),
167dc39bb3eSOswald Buddenhagen EMU32_SRC_REGS,
168dc39bb3eSOswald Buddenhagen };
169dc39bb3eSOswald Buddenhagen static_assert(ARRAY_SIZE(emu1010_src_regs) == ARRAY_SIZE(emu1010_src_texts));
170dc39bb3eSOswald Buddenhagen
171f69d705dSOswald Buddenhagen /* 1010 rev2 */
172f69d705dSOswald Buddenhagen
173f69d705dSOswald Buddenhagen #define EMU1010b_COMMON_TEXTS \
174f69d705dSOswald Buddenhagen "Silence", \
175f69d705dSOswald Buddenhagen PAIR_TEXTS("Dock Mic", "A", "B"), \
176f69d705dSOswald Buddenhagen LR_TEXTS("Dock ADC1"), \
177f69d705dSOswald Buddenhagen LR_TEXTS("Dock ADC2"), \
178f69d705dSOswald Buddenhagen LR_TEXTS("0202 ADC"), \
179f69d705dSOswald Buddenhagen LR_TEXTS("Dock SPDIF"), \
180f69d705dSOswald Buddenhagen LR_TEXTS("1010 SPDIF"), \
181f69d705dSOswald Buddenhagen ADAT_TEXTS("Dock "), \
182f69d705dSOswald Buddenhagen ADAT_TEXTS("1010 ")
183f69d705dSOswald Buddenhagen
184f69d705dSOswald Buddenhagen static const char * const emu1010b_src_texts[] = {
185f69d705dSOswald Buddenhagen EMU1010b_COMMON_TEXTS,
186f69d705dSOswald Buddenhagen DSP_TEXTS,
187f69d705dSOswald Buddenhagen };
188f69d705dSOswald Buddenhagen
189f69d705dSOswald Buddenhagen static const unsigned short emu1010b_src_regs[] = {
190f69d705dSOswald Buddenhagen EMU_SRC_SILENCE,
191f69d705dSOswald Buddenhagen PAIR_REGS(EMU_SRC_DOCK_MIC, _A, _B),
192f69d705dSOswald Buddenhagen LR_REGS(EMU_SRC_DOCK_ADC1),
193f69d705dSOswald Buddenhagen LR_REGS(EMU_SRC_DOCK_ADC2),
194f69d705dSOswald Buddenhagen LR_REGS(EMU_SRC_HAMOA_ADC),
195f69d705dSOswald Buddenhagen LR_REGS(EMU_SRC_MDOCK_SPDIF),
196f69d705dSOswald Buddenhagen LR_REGS(EMU_SRC_HANA_SPDIF),
197f69d705dSOswald Buddenhagen ADAT_REGS(EMU_SRC_MDOCK_ADAT),
198f69d705dSOswald Buddenhagen ADAT_REGS(EMU_SRC_HANA_ADAT),
199f69d705dSOswald Buddenhagen EMU32_SRC_REGS,
200f69d705dSOswald Buddenhagen };
201f69d705dSOswald Buddenhagen static_assert(ARRAY_SIZE(emu1010b_src_regs) == ARRAY_SIZE(emu1010b_src_texts));
202f69d705dSOswald Buddenhagen
2031c02e366SCtirad Fertr /* 1616(m) cardbus */
204dc39bb3eSOswald Buddenhagen
205dc39bb3eSOswald Buddenhagen #define EMU1616_COMMON_TEXTS \
206dc39bb3eSOswald Buddenhagen "Silence", \
207dc39bb3eSOswald Buddenhagen PAIR_TEXTS("Mic", "A", "B"), \
208dc39bb3eSOswald Buddenhagen LR_TEXTS("ADC1"), \
209dc39bb3eSOswald Buddenhagen LR_TEXTS("ADC2"), \
210dc39bb3eSOswald Buddenhagen LR_TEXTS("SPDIF"), \
211dc39bb3eSOswald Buddenhagen ADAT_TEXTS("")
212dc39bb3eSOswald Buddenhagen
213dc39bb3eSOswald Buddenhagen static const char * const emu1616_src_texts[] = {
214dc39bb3eSOswald Buddenhagen EMU1616_COMMON_TEXTS,
215dc39bb3eSOswald Buddenhagen DSP_TEXTS,
216dc39bb3eSOswald Buddenhagen };
217dc39bb3eSOswald Buddenhagen
2189b00a1e9SOswald Buddenhagen static const unsigned short emu1616_src_regs[] = {
2191c02e366SCtirad Fertr EMU_SRC_SILENCE,
220dc39bb3eSOswald Buddenhagen PAIR_REGS(EMU_SRC_DOCK_MIC, _A, _B),
221dc39bb3eSOswald Buddenhagen LR_REGS(EMU_SRC_DOCK_ADC1),
222dc39bb3eSOswald Buddenhagen LR_REGS(EMU_SRC_DOCK_ADC2),
223dc39bb3eSOswald Buddenhagen LR_REGS(EMU_SRC_MDOCK_SPDIF),
224dc39bb3eSOswald Buddenhagen ADAT_REGS(EMU_SRC_MDOCK_ADAT),
225dc39bb3eSOswald Buddenhagen EMU32_SRC_REGS,
2261c02e366SCtirad Fertr };
227dc39bb3eSOswald Buddenhagen static_assert(ARRAY_SIZE(emu1616_src_regs) == ARRAY_SIZE(emu1616_src_texts));
2281c02e366SCtirad Fertr
2296f3609f8SOswald Buddenhagen /* 0404 rev1 & rev2 */
2306f3609f8SOswald Buddenhagen
2316f3609f8SOswald Buddenhagen #define EMU0404_COMMON_TEXTS \
2326f3609f8SOswald Buddenhagen "Silence", \
2336f3609f8SOswald Buddenhagen LR_TEXTS("ADC"), \
2346f3609f8SOswald Buddenhagen LR_TEXTS("SPDIF")
2356f3609f8SOswald Buddenhagen
2366f3609f8SOswald Buddenhagen static const char * const emu0404_src_texts[] = {
2376f3609f8SOswald Buddenhagen EMU0404_COMMON_TEXTS,
2386f3609f8SOswald Buddenhagen DSP_TEXTS,
2396f3609f8SOswald Buddenhagen };
2406f3609f8SOswald Buddenhagen
2416f3609f8SOswald Buddenhagen static const unsigned short emu0404_src_regs[] = {
2426f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
2436f3609f8SOswald Buddenhagen LR_REGS(EMU_SRC_HAMOA_ADC),
2446f3609f8SOswald Buddenhagen LR_REGS(EMU_SRC_HANA_SPDIF),
2456f3609f8SOswald Buddenhagen EMU32_SRC_REGS,
2466f3609f8SOswald Buddenhagen };
2476f3609f8SOswald Buddenhagen static_assert(ARRAY_SIZE(emu0404_src_regs) == ARRAY_SIZE(emu0404_src_texts));
2486f3609f8SOswald Buddenhagen
24913d45709SPavel Hofman /*
25013d45709SPavel Hofman * Data destinations - physical EMU outputs.
25113d45709SPavel Hofman * Each destination has an enum mixer control to choose a data source
25213d45709SPavel Hofman */
253536438f1SOswald Buddenhagen
254536438f1SOswald Buddenhagen #define LR_CTLS(base) LR_PS(base, " Playback Enum")
255536438f1SOswald Buddenhagen #define ADAT_CTLS(pfx) ADAT_PS(pfx, " Playback Enum")
256536438f1SOswald Buddenhagen
2576f3609f8SOswald Buddenhagen /* 1010 rev1 */
2586f3609f8SOswald Buddenhagen
259536438f1SOswald Buddenhagen static const char * const emu1010_output_texts[] = {
260536438f1SOswald Buddenhagen LR_CTLS("Dock DAC1"),
261536438f1SOswald Buddenhagen LR_CTLS("Dock DAC2"),
262536438f1SOswald Buddenhagen LR_CTLS("Dock DAC3"),
263536438f1SOswald Buddenhagen LR_CTLS("Dock DAC4"),
264536438f1SOswald Buddenhagen LR_CTLS("Dock Phones"),
265536438f1SOswald Buddenhagen LR_CTLS("Dock SPDIF"),
266536438f1SOswald Buddenhagen LR_CTLS("0202 DAC"),
267536438f1SOswald Buddenhagen LR_CTLS("1010 SPDIF"),
268536438f1SOswald Buddenhagen ADAT_CTLS("1010 "),
2699f4bd5ddSJames Courtier-Dutton };
270216abe45SOswald Buddenhagen static_assert(ARRAY_SIZE(emu1010_output_texts) <= NUM_OUTPUT_DESTS);
2719f4bd5ddSJames Courtier-Dutton
272536438f1SOswald Buddenhagen static const unsigned short emu1010_output_dst[] = {
273536438f1SOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC1),
274536438f1SOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC2),
275536438f1SOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC3),
276536438f1SOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC4),
277536438f1SOswald Buddenhagen LR_REGS(EMU_DST_DOCK_PHONES),
278536438f1SOswald Buddenhagen LR_REGS(EMU_DST_DOCK_SPDIF),
279536438f1SOswald Buddenhagen LR_REGS(EMU_DST_HAMOA_DAC),
280536438f1SOswald Buddenhagen LR_REGS(EMU_DST_HANA_SPDIF),
281536438f1SOswald Buddenhagen ADAT_REGS(EMU_DST_HANA_ADAT),
2821c02e366SCtirad Fertr };
283536438f1SOswald Buddenhagen static_assert(ARRAY_SIZE(emu1010_output_dst) == ARRAY_SIZE(emu1010_output_texts));
284536438f1SOswald Buddenhagen
2851fc710f0SOswald Buddenhagen static const unsigned short emu1010_output_dflt[] = {
2861fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
2871fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
2881fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5,
2891fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+6, EMU_SRC_ALICE_EMU32A+7,
2901fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
2911fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
2921fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
2931fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
2941fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1, EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
2951fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5, EMU_SRC_ALICE_EMU32A+6, EMU_SRC_ALICE_EMU32A+7,
2961fc710f0SOswald Buddenhagen };
2971fc710f0SOswald Buddenhagen static_assert(ARRAY_SIZE(emu1010_output_dflt) == ARRAY_SIZE(emu1010_output_dst));
2981fc710f0SOswald Buddenhagen
299f69d705dSOswald Buddenhagen /* 1010 rev2 */
300f69d705dSOswald Buddenhagen
301f69d705dSOswald Buddenhagen static const char * const snd_emu1010b_output_texts[] = {
302f69d705dSOswald Buddenhagen LR_CTLS("Dock DAC1"),
303f69d705dSOswald Buddenhagen LR_CTLS("Dock DAC2"),
304f69d705dSOswald Buddenhagen LR_CTLS("Dock DAC3"),
305f69d705dSOswald Buddenhagen LR_CTLS("Dock SPDIF"),
306f69d705dSOswald Buddenhagen ADAT_CTLS("Dock "),
307f69d705dSOswald Buddenhagen LR_CTLS("0202 DAC"),
308f69d705dSOswald Buddenhagen LR_CTLS("1010 SPDIF"),
309f69d705dSOswald Buddenhagen ADAT_CTLS("1010 "),
310f69d705dSOswald Buddenhagen };
311216abe45SOswald Buddenhagen static_assert(ARRAY_SIZE(snd_emu1010b_output_texts) <= NUM_OUTPUT_DESTS);
312f69d705dSOswald Buddenhagen
313f69d705dSOswald Buddenhagen static const unsigned short emu1010b_output_dst[] = {
314f69d705dSOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC1),
315f69d705dSOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC2),
316f69d705dSOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC3),
317f69d705dSOswald Buddenhagen LR_REGS(EMU_DST_MDOCK_SPDIF),
318f69d705dSOswald Buddenhagen ADAT_REGS(EMU_DST_MDOCK_ADAT),
319f69d705dSOswald Buddenhagen LR_REGS(EMU_DST_HAMOA_DAC),
320f69d705dSOswald Buddenhagen LR_REGS(EMU_DST_HANA_SPDIF),
321f69d705dSOswald Buddenhagen ADAT_REGS(EMU_DST_HANA_ADAT),
322f69d705dSOswald Buddenhagen };
323f69d705dSOswald Buddenhagen static_assert(ARRAY_SIZE(emu1010b_output_dst) == ARRAY_SIZE(snd_emu1010b_output_texts));
324f69d705dSOswald Buddenhagen
325f69d705dSOswald Buddenhagen static const unsigned short emu1010b_output_dflt[] = {
326f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
327f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
328f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5,
329f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
330f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1, EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
331f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5, EMU_SRC_ALICE_EMU32A+6, EMU_SRC_ALICE_EMU32A+7,
332f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
333f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
334f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1, EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
335f69d705dSOswald Buddenhagen EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5, EMU_SRC_ALICE_EMU32A+6, EMU_SRC_ALICE_EMU32A+7,
336f69d705dSOswald Buddenhagen };
337f69d705dSOswald Buddenhagen
338536438f1SOswald Buddenhagen /* 1616(m) cardbus */
339536438f1SOswald Buddenhagen
340536438f1SOswald Buddenhagen static const char * const snd_emu1616_output_texts[] = {
341536438f1SOswald Buddenhagen LR_CTLS("Dock DAC1"),
342536438f1SOswald Buddenhagen LR_CTLS("Dock DAC2"),
343536438f1SOswald Buddenhagen LR_CTLS("Dock DAC3"),
344536438f1SOswald Buddenhagen LR_CTLS("Dock SPDIF"),
345536438f1SOswald Buddenhagen ADAT_CTLS("Dock "),
346536438f1SOswald Buddenhagen LR_CTLS("Mana DAC"),
347536438f1SOswald Buddenhagen };
348216abe45SOswald Buddenhagen static_assert(ARRAY_SIZE(snd_emu1616_output_texts) <= NUM_OUTPUT_DESTS);
349536438f1SOswald Buddenhagen
350536438f1SOswald Buddenhagen static const unsigned short emu1616_output_dst[] = {
351536438f1SOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC1),
352536438f1SOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC2),
353536438f1SOswald Buddenhagen LR_REGS(EMU_DST_DOCK_DAC3),
354536438f1SOswald Buddenhagen LR_REGS(EMU_DST_MDOCK_SPDIF),
355536438f1SOswald Buddenhagen ADAT_REGS(EMU_DST_MDOCK_ADAT),
356536438f1SOswald Buddenhagen EMU_DST_MANA_DAC_LEFT, EMU_DST_MANA_DAC_RIGHT,
357536438f1SOswald Buddenhagen };
358536438f1SOswald Buddenhagen static_assert(ARRAY_SIZE(emu1616_output_dst) == ARRAY_SIZE(snd_emu1616_output_texts));
3591c02e366SCtirad Fertr
3601fc710f0SOswald Buddenhagen static const unsigned short emu1616_output_dflt[] = {
3611fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
3621fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
3631fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5,
3641fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
3651fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1, EMU_SRC_ALICE_EMU32A+2, EMU_SRC_ALICE_EMU32A+3,
3661fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+4, EMU_SRC_ALICE_EMU32A+5, EMU_SRC_ALICE_EMU32A+6, EMU_SRC_ALICE_EMU32A+7,
3671fc710f0SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
3681fc710f0SOswald Buddenhagen };
3691fc710f0SOswald Buddenhagen static_assert(ARRAY_SIZE(emu1616_output_dflt) == ARRAY_SIZE(emu1616_output_dst));
3701fc710f0SOswald Buddenhagen
3716f3609f8SOswald Buddenhagen /* 0404 rev1 & rev2 */
3726f3609f8SOswald Buddenhagen
3736f3609f8SOswald Buddenhagen static const char * const snd_emu0404_output_texts[] = {
3746f3609f8SOswald Buddenhagen LR_CTLS("DAC"),
3756f3609f8SOswald Buddenhagen LR_CTLS("SPDIF"),
3766f3609f8SOswald Buddenhagen };
377216abe45SOswald Buddenhagen static_assert(ARRAY_SIZE(snd_emu0404_output_texts) <= NUM_OUTPUT_DESTS);
3786f3609f8SOswald Buddenhagen
3796f3609f8SOswald Buddenhagen static const unsigned short emu0404_output_dst[] = {
3806f3609f8SOswald Buddenhagen LR_REGS(EMU_DST_HAMOA_DAC),
3816f3609f8SOswald Buddenhagen LR_REGS(EMU_DST_HANA_SPDIF),
3826f3609f8SOswald Buddenhagen };
3836f3609f8SOswald Buddenhagen static_assert(ARRAY_SIZE(emu0404_output_dst) == ARRAY_SIZE(snd_emu0404_output_texts));
3846f3609f8SOswald Buddenhagen
3856f3609f8SOswald Buddenhagen static const unsigned short emu0404_output_dflt[] = {
3866f3609f8SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
3876f3609f8SOswald Buddenhagen EMU_SRC_ALICE_EMU32A+0, EMU_SRC_ALICE_EMU32A+1,
3886f3609f8SOswald Buddenhagen };
3896f3609f8SOswald Buddenhagen static_assert(ARRAY_SIZE(emu0404_output_dflt) == ARRAY_SIZE(emu0404_output_dst));
3906f3609f8SOswald Buddenhagen
39113d45709SPavel Hofman /*
392a869057cSOswald Buddenhagen * Data destinations - FPGA outputs going to Alice2 (Audigy) for
39313d45709SPavel Hofman * capture (EMU32 + I2S links)
39413d45709SPavel Hofman * Each destination has an enum mixer control to choose a data source
39513d45709SPavel Hofman */
396536438f1SOswald Buddenhagen
397536438f1SOswald Buddenhagen static const char * const emu1010_input_texts[] = {
398536438f1SOswald Buddenhagen "DSP 0 Capture Enum",
399536438f1SOswald Buddenhagen "DSP 1 Capture Enum",
400536438f1SOswald Buddenhagen "DSP 2 Capture Enum",
401536438f1SOswald Buddenhagen "DSP 3 Capture Enum",
402536438f1SOswald Buddenhagen "DSP 4 Capture Enum",
403536438f1SOswald Buddenhagen "DSP 5 Capture Enum",
404536438f1SOswald Buddenhagen "DSP 6 Capture Enum",
405536438f1SOswald Buddenhagen "DSP 7 Capture Enum",
406536438f1SOswald Buddenhagen "DSP 8 Capture Enum",
407536438f1SOswald Buddenhagen "DSP 9 Capture Enum",
408536438f1SOswald Buddenhagen "DSP A Capture Enum",
409536438f1SOswald Buddenhagen "DSP B Capture Enum",
410536438f1SOswald Buddenhagen "DSP C Capture Enum",
411536438f1SOswald Buddenhagen "DSP D Capture Enum",
412536438f1SOswald Buddenhagen "DSP E Capture Enum",
413536438f1SOswald Buddenhagen "DSP F Capture Enum",
414536438f1SOswald Buddenhagen /* These exist only on rev1 EMU1010 cards. */
415536438f1SOswald Buddenhagen "DSP 10 Capture Enum",
416536438f1SOswald Buddenhagen "DSP 11 Capture Enum",
417536438f1SOswald Buddenhagen "DSP 12 Capture Enum",
418536438f1SOswald Buddenhagen "DSP 13 Capture Enum",
419536438f1SOswald Buddenhagen "DSP 14 Capture Enum",
420536438f1SOswald Buddenhagen "DSP 15 Capture Enum",
421536438f1SOswald Buddenhagen };
422216abe45SOswald Buddenhagen static_assert(ARRAY_SIZE(emu1010_input_texts) <= NUM_INPUT_DESTS);
423536438f1SOswald Buddenhagen
4249b00a1e9SOswald Buddenhagen static const unsigned short emu1010_input_dst[] = {
4259f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_0,
4269f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_1,
4279f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_2,
4289f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_3,
4299f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_4,
4309f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_5,
4319f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_6,
4329f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_7,
4339f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_8,
4349f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_9,
4359f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_A,
4369f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_B,
4379f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_C,
4389f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_D,
4399f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_E,
4409f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE2_EMU32_F,
441a869057cSOswald Buddenhagen /* These exist only on rev1 EMU1010 cards. */
4429f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S0_LEFT,
4439f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S0_RIGHT,
4449f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S1_LEFT,
4459f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S1_RIGHT,
4469f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S2_LEFT,
4479f4bd5ddSJames Courtier-Dutton EMU_DST_ALICE_I2S2_RIGHT,
4489f4bd5ddSJames Courtier-Dutton };
449536438f1SOswald Buddenhagen static_assert(ARRAY_SIZE(emu1010_input_dst) == ARRAY_SIZE(emu1010_input_texts));
4509f4bd5ddSJames Courtier-Dutton
4511fc710f0SOswald Buddenhagen static const unsigned short emu1010_input_dflt[] = {
4521fc710f0SOswald Buddenhagen EMU_SRC_DOCK_MIC_A1,
4531fc710f0SOswald Buddenhagen EMU_SRC_DOCK_MIC_B1,
4541fc710f0SOswald Buddenhagen EMU_SRC_HAMOA_ADC_LEFT1,
4551fc710f0SOswald Buddenhagen EMU_SRC_HAMOA_ADC_RIGHT1,
4561fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC1_LEFT1,
4571fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC1_RIGHT1,
4581fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC2_LEFT1,
4591fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC2_RIGHT1,
4601fc710f0SOswald Buddenhagen /* Pavel Hofman - setting defaults for all capture channels.
4611fc710f0SOswald Buddenhagen * Defaults only, users will set their own values anyways, let's
4621fc710f0SOswald Buddenhagen * just copy/paste. */
4631fc710f0SOswald Buddenhagen EMU_SRC_DOCK_MIC_A1,
4641fc710f0SOswald Buddenhagen EMU_SRC_DOCK_MIC_B1,
4651fc710f0SOswald Buddenhagen EMU_SRC_HAMOA_ADC_LEFT1,
4661fc710f0SOswald Buddenhagen EMU_SRC_HAMOA_ADC_RIGHT1,
4671fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC1_LEFT1,
4681fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC1_RIGHT1,
4691fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC2_LEFT1,
4701fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC2_RIGHT1,
4711fc710f0SOswald Buddenhagen
4721fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC1_LEFT1,
4731fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC1_RIGHT1,
4741fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC2_LEFT1,
4751fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC2_RIGHT1,
4761fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC3_LEFT1,
4771fc710f0SOswald Buddenhagen EMU_SRC_DOCK_ADC3_RIGHT1,
4781fc710f0SOswald Buddenhagen };
4791fc710f0SOswald Buddenhagen static_assert(ARRAY_SIZE(emu1010_input_dflt) == ARRAY_SIZE(emu1010_input_dst));
4801fc710f0SOswald Buddenhagen
4816f3609f8SOswald Buddenhagen static const unsigned short emu0404_input_dflt[] = {
4826f3609f8SOswald Buddenhagen EMU_SRC_HAMOA_ADC_LEFT1,
4836f3609f8SOswald Buddenhagen EMU_SRC_HAMOA_ADC_RIGHT1,
4846f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4856f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4866f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4876f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4886f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4896f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4906f3609f8SOswald Buddenhagen EMU_SRC_HANA_SPDIF_LEFT1,
4916f3609f8SOswald Buddenhagen EMU_SRC_HANA_SPDIF_RIGHT1,
4926f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4936f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4946f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4956f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4966f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4976f3609f8SOswald Buddenhagen EMU_SRC_SILENCE,
4986f3609f8SOswald Buddenhagen };
4996f3609f8SOswald Buddenhagen
500511cbe8fSOswald Buddenhagen struct snd_emu1010_routing_info {
501511cbe8fSOswald Buddenhagen const char * const *src_texts;
50297f1582eSOswald Buddenhagen const char * const *out_texts;
503511cbe8fSOswald Buddenhagen const unsigned short *src_regs;
504511cbe8fSOswald Buddenhagen const unsigned short *out_regs;
505511cbe8fSOswald Buddenhagen const unsigned short *in_regs;
5061fc710f0SOswald Buddenhagen const unsigned short *out_dflts;
5071fc710f0SOswald Buddenhagen const unsigned short *in_dflts;
508511cbe8fSOswald Buddenhagen unsigned n_srcs;
509511cbe8fSOswald Buddenhagen unsigned n_outs;
510511cbe8fSOswald Buddenhagen unsigned n_ins;
511511cbe8fSOswald Buddenhagen };
512511cbe8fSOswald Buddenhagen
513816967d5STom Rix static const struct snd_emu1010_routing_info emu1010_routing_info[] = {
514511cbe8fSOswald Buddenhagen {
5156f3609f8SOswald Buddenhagen /* rev1 1010 */
516511cbe8fSOswald Buddenhagen .src_regs = emu1010_src_regs,
517511cbe8fSOswald Buddenhagen .src_texts = emu1010_src_texts,
518511cbe8fSOswald Buddenhagen .n_srcs = ARRAY_SIZE(emu1010_src_texts),
519511cbe8fSOswald Buddenhagen
5201fc710f0SOswald Buddenhagen .out_dflts = emu1010_output_dflt,
521511cbe8fSOswald Buddenhagen .out_regs = emu1010_output_dst,
52297f1582eSOswald Buddenhagen .out_texts = emu1010_output_texts,
523511cbe8fSOswald Buddenhagen .n_outs = ARRAY_SIZE(emu1010_output_dst),
524511cbe8fSOswald Buddenhagen
5251fc710f0SOswald Buddenhagen .in_dflts = emu1010_input_dflt,
526511cbe8fSOswald Buddenhagen .in_regs = emu1010_input_dst,
527511cbe8fSOswald Buddenhagen .n_ins = ARRAY_SIZE(emu1010_input_dst),
528511cbe8fSOswald Buddenhagen },
529511cbe8fSOswald Buddenhagen {
530f69d705dSOswald Buddenhagen /* rev2 1010 */
531f69d705dSOswald Buddenhagen .src_regs = emu1010b_src_regs,
532f69d705dSOswald Buddenhagen .src_texts = emu1010b_src_texts,
533f69d705dSOswald Buddenhagen .n_srcs = ARRAY_SIZE(emu1010b_src_texts),
534f69d705dSOswald Buddenhagen
535f69d705dSOswald Buddenhagen .out_dflts = emu1010b_output_dflt,
536f69d705dSOswald Buddenhagen .out_regs = emu1010b_output_dst,
537f69d705dSOswald Buddenhagen .out_texts = snd_emu1010b_output_texts,
538f69d705dSOswald Buddenhagen .n_outs = ARRAY_SIZE(emu1010b_output_dst),
539f69d705dSOswald Buddenhagen
540f69d705dSOswald Buddenhagen .in_dflts = emu1010_input_dflt,
541f69d705dSOswald Buddenhagen .in_regs = emu1010_input_dst,
542f69d705dSOswald Buddenhagen .n_ins = ARRAY_SIZE(emu1010_input_dst) - 6,
543f69d705dSOswald Buddenhagen },
544f69d705dSOswald Buddenhagen {
545511cbe8fSOswald Buddenhagen /* 1616(m) cardbus */
546511cbe8fSOswald Buddenhagen .src_regs = emu1616_src_regs,
547511cbe8fSOswald Buddenhagen .src_texts = emu1616_src_texts,
548511cbe8fSOswald Buddenhagen .n_srcs = ARRAY_SIZE(emu1616_src_texts),
549511cbe8fSOswald Buddenhagen
5501fc710f0SOswald Buddenhagen .out_dflts = emu1616_output_dflt,
551511cbe8fSOswald Buddenhagen .out_regs = emu1616_output_dst,
55297f1582eSOswald Buddenhagen .out_texts = snd_emu1616_output_texts,
553511cbe8fSOswald Buddenhagen .n_outs = ARRAY_SIZE(emu1616_output_dst),
554511cbe8fSOswald Buddenhagen
5551fc710f0SOswald Buddenhagen .in_dflts = emu1010_input_dflt,
556511cbe8fSOswald Buddenhagen .in_regs = emu1010_input_dst,
557511cbe8fSOswald Buddenhagen .n_ins = ARRAY_SIZE(emu1010_input_dst) - 6,
558511cbe8fSOswald Buddenhagen },
5596f3609f8SOswald Buddenhagen {
5606f3609f8SOswald Buddenhagen /* 0404 */
5616f3609f8SOswald Buddenhagen .src_regs = emu0404_src_regs,
5626f3609f8SOswald Buddenhagen .src_texts = emu0404_src_texts,
5636f3609f8SOswald Buddenhagen .n_srcs = ARRAY_SIZE(emu0404_src_texts),
5646f3609f8SOswald Buddenhagen
5656f3609f8SOswald Buddenhagen .out_dflts = emu0404_output_dflt,
5666f3609f8SOswald Buddenhagen .out_regs = emu0404_output_dst,
5676f3609f8SOswald Buddenhagen .out_texts = snd_emu0404_output_texts,
5686f3609f8SOswald Buddenhagen .n_outs = ARRAY_SIZE(emu0404_output_dflt),
5696f3609f8SOswald Buddenhagen
5706f3609f8SOswald Buddenhagen .in_dflts = emu0404_input_dflt,
5716f3609f8SOswald Buddenhagen .in_regs = emu1010_input_dst,
5726f3609f8SOswald Buddenhagen .n_ins = ARRAY_SIZE(emu1010_input_dst) - 6,
5736f3609f8SOswald Buddenhagen },
574511cbe8fSOswald Buddenhagen };
575511cbe8fSOswald Buddenhagen
emu1010_idx(struct snd_emu10k1 * emu)576511cbe8fSOswald Buddenhagen static unsigned emu1010_idx(struct snd_emu10k1 *emu)
577511cbe8fSOswald Buddenhagen {
5786f3609f8SOswald Buddenhagen return emu->card_capabilities->emu_model - 1;
579511cbe8fSOswald Buddenhagen }
580511cbe8fSOswald Buddenhagen
snd_emu1010_output_source_apply(struct snd_emu10k1 * emu,int channel,int src)581511cbe8fSOswald Buddenhagen static void snd_emu1010_output_source_apply(struct snd_emu10k1 *emu,
582511cbe8fSOswald Buddenhagen int channel, int src)
583511cbe8fSOswald Buddenhagen {
584511cbe8fSOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
585511cbe8fSOswald Buddenhagen &emu1010_routing_info[emu1010_idx(emu)];
586511cbe8fSOswald Buddenhagen
587511cbe8fSOswald Buddenhagen snd_emu1010_fpga_link_dst_src_write(emu,
588511cbe8fSOswald Buddenhagen emu_ri->out_regs[channel], emu_ri->src_regs[src]);
589511cbe8fSOswald Buddenhagen }
590511cbe8fSOswald Buddenhagen
snd_emu1010_input_source_apply(struct snd_emu10k1 * emu,int channel,int src)591511cbe8fSOswald Buddenhagen static void snd_emu1010_input_source_apply(struct snd_emu10k1 *emu,
592511cbe8fSOswald Buddenhagen int channel, int src)
593511cbe8fSOswald Buddenhagen {
594511cbe8fSOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
595511cbe8fSOswald Buddenhagen &emu1010_routing_info[emu1010_idx(emu)];
596511cbe8fSOswald Buddenhagen
597511cbe8fSOswald Buddenhagen snd_emu1010_fpga_link_dst_src_write(emu,
598511cbe8fSOswald Buddenhagen emu_ri->in_regs[channel], emu_ri->src_regs[src]);
599511cbe8fSOswald Buddenhagen }
600511cbe8fSOswald Buddenhagen
snd_emu1010_apply_sources(struct snd_emu10k1 * emu)6011fc710f0SOswald Buddenhagen static void snd_emu1010_apply_sources(struct snd_emu10k1 *emu)
6021fc710f0SOswald Buddenhagen {
6031fc710f0SOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
6041fc710f0SOswald Buddenhagen &emu1010_routing_info[emu1010_idx(emu)];
6051fc710f0SOswald Buddenhagen
6061fc710f0SOswald Buddenhagen for (unsigned i = 0; i < emu_ri->n_outs; i++)
6071fc710f0SOswald Buddenhagen snd_emu1010_output_source_apply(
6081fc710f0SOswald Buddenhagen emu, i, emu->emu1010.output_source[i]);
6091fc710f0SOswald Buddenhagen for (unsigned i = 0; i < emu_ri->n_ins; i++)
6101fc710f0SOswald Buddenhagen snd_emu1010_input_source_apply(
6111fc710f0SOswald Buddenhagen emu, i, emu->emu1010.input_source[i]);
6121fc710f0SOswald Buddenhagen }
6131fc710f0SOswald Buddenhagen
emu1010_map_source(const struct snd_emu1010_routing_info * emu_ri,unsigned val)6141fc710f0SOswald Buddenhagen static u8 emu1010_map_source(const struct snd_emu1010_routing_info *emu_ri,
6151fc710f0SOswald Buddenhagen unsigned val)
6161fc710f0SOswald Buddenhagen {
6171fc710f0SOswald Buddenhagen for (unsigned i = 0; i < emu_ri->n_srcs; i++)
6181fc710f0SOswald Buddenhagen if (val == emu_ri->src_regs[i])
6191fc710f0SOswald Buddenhagen return i;
6201fc710f0SOswald Buddenhagen return 0;
6211fc710f0SOswald Buddenhagen }
6221fc710f0SOswald Buddenhagen
snd_emu1010_input_output_source_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)6231c02e366SCtirad Fertr static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol,
6241c02e366SCtirad Fertr struct snd_ctl_elem_info *uinfo)
6259f4bd5ddSJames Courtier-Dutton {
6261c02e366SCtirad Fertr struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
627511cbe8fSOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
628511cbe8fSOswald Buddenhagen &emu1010_routing_info[emu1010_idx(emu)];
6291c02e366SCtirad Fertr
630511cbe8fSOswald Buddenhagen return snd_ctl_enum_info(uinfo, 1, emu_ri->n_srcs, emu_ri->src_texts);
6319f4bd5ddSJames Courtier-Dutton }
6329f4bd5ddSJames Courtier-Dutton
snd_emu1010_output_source_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)6339f4bd5ddSJames Courtier-Dutton static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
6349f4bd5ddSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
6359f4bd5ddSJames Courtier-Dutton {
6369f4bd5ddSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
637511cbe8fSOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
638511cbe8fSOswald Buddenhagen &emu1010_routing_info[emu1010_idx(emu)];
639511cbe8fSOswald Buddenhagen unsigned channel = kcontrol->private_value;
6409f4bd5ddSJames Courtier-Dutton
641511cbe8fSOswald Buddenhagen if (channel >= emu_ri->n_outs)
64274415a36SJames Courtier-Dutton return -EINVAL;
6439f4bd5ddSJames Courtier-Dutton ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
6449f4bd5ddSJames Courtier-Dutton return 0;
6459f4bd5ddSJames Courtier-Dutton }
6469f4bd5ddSJames Courtier-Dutton
snd_emu1010_output_source_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)6479f4bd5ddSJames Courtier-Dutton static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
6489f4bd5ddSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
6499f4bd5ddSJames Courtier-Dutton {
6509f4bd5ddSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
651511cbe8fSOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
652511cbe8fSOswald Buddenhagen &emu1010_routing_info[emu1010_idx(emu)];
653511cbe8fSOswald Buddenhagen unsigned val = ucontrol->value.enumerated.item[0];
654511cbe8fSOswald Buddenhagen unsigned channel = kcontrol->private_value;
655511cbe8fSOswald Buddenhagen int change;
6569f4bd5ddSJames Courtier-Dutton
657511cbe8fSOswald Buddenhagen if (val >= emu_ri->n_srcs)
658aa299d01STakashi Iwai return -EINVAL;
659511cbe8fSOswald Buddenhagen if (channel >= emu_ri->n_outs)
66074415a36SJames Courtier-Dutton return -EINVAL;
661511cbe8fSOswald Buddenhagen change = (emu->emu1010.output_source[channel] != val);
662511cbe8fSOswald Buddenhagen if (change) {
663aa299d01STakashi Iwai emu->emu1010.output_source[channel] = val;
664*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_lock(emu);
665511cbe8fSOswald Buddenhagen snd_emu1010_output_source_apply(emu, channel, val);
666*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_unlock(emu);
667511cbe8fSOswald Buddenhagen }
668511cbe8fSOswald Buddenhagen return change;
6699f4bd5ddSJames Courtier-Dutton }
6709f4bd5ddSJames Courtier-Dutton
671536438f1SOswald Buddenhagen static const struct snd_kcontrol_new emu1010_output_source_ctl = {
672536438f1SOswald Buddenhagen .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
673536438f1SOswald Buddenhagen .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
674536438f1SOswald Buddenhagen .info = snd_emu1010_input_output_source_info,
675536438f1SOswald Buddenhagen .get = snd_emu1010_output_source_get,
676536438f1SOswald Buddenhagen .put = snd_emu1010_output_source_put
677536438f1SOswald Buddenhagen };
678536438f1SOswald Buddenhagen
snd_emu1010_input_source_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)6799f4bd5ddSJames Courtier-Dutton static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
6809f4bd5ddSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
6819f4bd5ddSJames Courtier-Dutton {
6829f4bd5ddSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
683511cbe8fSOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
684511cbe8fSOswald Buddenhagen &emu1010_routing_info[emu1010_idx(emu)];
685511cbe8fSOswald Buddenhagen unsigned channel = kcontrol->private_value;
6869f4bd5ddSJames Courtier-Dutton
687511cbe8fSOswald Buddenhagen if (channel >= emu_ri->n_ins)
68874415a36SJames Courtier-Dutton return -EINVAL;
6899f4bd5ddSJames Courtier-Dutton ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
6909f4bd5ddSJames Courtier-Dutton return 0;
6919f4bd5ddSJames Courtier-Dutton }
6929f4bd5ddSJames Courtier-Dutton
snd_emu1010_input_source_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)6939f4bd5ddSJames Courtier-Dutton static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
6949f4bd5ddSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
6959f4bd5ddSJames Courtier-Dutton {
6969f4bd5ddSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
697511cbe8fSOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
698511cbe8fSOswald Buddenhagen &emu1010_routing_info[emu1010_idx(emu)];
699511cbe8fSOswald Buddenhagen unsigned val = ucontrol->value.enumerated.item[0];
700511cbe8fSOswald Buddenhagen unsigned channel = kcontrol->private_value;
701511cbe8fSOswald Buddenhagen int change;
7029f4bd5ddSJames Courtier-Dutton
703511cbe8fSOswald Buddenhagen if (val >= emu_ri->n_srcs)
704aa299d01STakashi Iwai return -EINVAL;
705511cbe8fSOswald Buddenhagen if (channel >= emu_ri->n_ins)
70674415a36SJames Courtier-Dutton return -EINVAL;
707511cbe8fSOswald Buddenhagen change = (emu->emu1010.input_source[channel] != val);
708511cbe8fSOswald Buddenhagen if (change) {
709aa299d01STakashi Iwai emu->emu1010.input_source[channel] = val;
710*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_lock(emu);
711511cbe8fSOswald Buddenhagen snd_emu1010_input_source_apply(emu, channel, val);
712*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_unlock(emu);
713511cbe8fSOswald Buddenhagen }
714511cbe8fSOswald Buddenhagen return change;
7159f4bd5ddSJames Courtier-Dutton }
7169f4bd5ddSJames Courtier-Dutton
717536438f1SOswald Buddenhagen static const struct snd_kcontrol_new emu1010_input_source_ctl = {
718536438f1SOswald Buddenhagen .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
719536438f1SOswald Buddenhagen .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
720536438f1SOswald Buddenhagen .info = snd_emu1010_input_output_source_info,
721536438f1SOswald Buddenhagen .get = snd_emu1010_input_source_get,
722536438f1SOswald Buddenhagen .put = snd_emu1010_input_source_put
7239f4bd5ddSJames Courtier-Dutton };
7249f4bd5ddSJames Courtier-Dutton
add_emu1010_source_mixers(struct snd_emu10k1 * emu)72597f1582eSOswald Buddenhagen static int add_emu1010_source_mixers(struct snd_emu10k1 *emu)
72697f1582eSOswald Buddenhagen {
72797f1582eSOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
72897f1582eSOswald Buddenhagen &emu1010_routing_info[emu1010_idx(emu)];
72997f1582eSOswald Buddenhagen int err;
73097f1582eSOswald Buddenhagen
73197f1582eSOswald Buddenhagen err = add_ctls(emu, &emu1010_output_source_ctl,
73297f1582eSOswald Buddenhagen emu_ri->out_texts, emu_ri->n_outs);
73397f1582eSOswald Buddenhagen if (err < 0)
73497f1582eSOswald Buddenhagen return err;
73597f1582eSOswald Buddenhagen err = add_ctls(emu, &emu1010_input_source_ctl,
73697f1582eSOswald Buddenhagen emu1010_input_texts, emu_ri->n_ins);
73797f1582eSOswald Buddenhagen return err;
73897f1582eSOswald Buddenhagen }
73997f1582eSOswald Buddenhagen
7401c02e366SCtirad Fertr
741536438f1SOswald Buddenhagen static const char * const snd_emu1010_adc_pads[] = {
742f69d705dSOswald Buddenhagen "ADC1 14dB PAD 0202 Capture Switch",
743536438f1SOswald Buddenhagen "ADC1 14dB PAD Audio Dock Capture Switch",
744536438f1SOswald Buddenhagen "ADC2 14dB PAD Audio Dock Capture Switch",
745536438f1SOswald Buddenhagen "ADC3 14dB PAD Audio Dock Capture Switch",
7461c02e366SCtirad Fertr };
7471c02e366SCtirad Fertr
748536438f1SOswald Buddenhagen static const unsigned short snd_emu1010_adc_pad_regs[] = {
749f69d705dSOswald Buddenhagen EMU_HANA_0202_ADC_PAD1,
750536438f1SOswald Buddenhagen EMU_HANA_DOCK_ADC_PAD1,
751536438f1SOswald Buddenhagen EMU_HANA_DOCK_ADC_PAD2,
752536438f1SOswald Buddenhagen EMU_HANA_DOCK_ADC_PAD3,
7539148cc50SJames Courtier-Dutton };
7549148cc50SJames Courtier-Dutton
755a5ce8890STakashi Iwai #define snd_emu1010_adc_pads_info snd_ctl_boolean_mono_info
7569148cc50SJames Courtier-Dutton
snd_emu1010_adc_pads_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)7579148cc50SJames Courtier-Dutton static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7589148cc50SJames Courtier-Dutton {
7599148cc50SJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
760536438f1SOswald Buddenhagen unsigned int mask = snd_emu1010_adc_pad_regs[kcontrol->private_value];
761536438f1SOswald Buddenhagen
7629148cc50SJames Courtier-Dutton ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
7639148cc50SJames Courtier-Dutton return 0;
7649148cc50SJames Courtier-Dutton }
7659148cc50SJames Courtier-Dutton
snd_emu1010_adc_pads_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)7669148cc50SJames Courtier-Dutton static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7679148cc50SJames Courtier-Dutton {
7689148cc50SJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
769536438f1SOswald Buddenhagen unsigned int mask = snd_emu1010_adc_pad_regs[kcontrol->private_value];
7709148cc50SJames Courtier-Dutton unsigned int val, cache;
771deb1200fSOswald Buddenhagen int change;
772deb1200fSOswald Buddenhagen
7739148cc50SJames Courtier-Dutton val = ucontrol->value.integer.value[0];
7749148cc50SJames Courtier-Dutton cache = emu->emu1010.adc_pads;
7759148cc50SJames Courtier-Dutton if (val == 1)
7769148cc50SJames Courtier-Dutton cache = cache | mask;
7779148cc50SJames Courtier-Dutton else
7789148cc50SJames Courtier-Dutton cache = cache & ~mask;
779deb1200fSOswald Buddenhagen change = (cache != emu->emu1010.adc_pads);
780deb1200fSOswald Buddenhagen if (change) {
781*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_write_lock(emu, EMU_HANA_ADC_PADS, cache );
7829148cc50SJames Courtier-Dutton emu->emu1010.adc_pads = cache;
7839148cc50SJames Courtier-Dutton }
7849148cc50SJames Courtier-Dutton
785deb1200fSOswald Buddenhagen return change;
7869148cc50SJames Courtier-Dutton }
7879148cc50SJames Courtier-Dutton
788536438f1SOswald Buddenhagen static const struct snd_kcontrol_new emu1010_adc_pads_ctl = {
789536438f1SOswald Buddenhagen .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
790536438f1SOswald Buddenhagen .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
791536438f1SOswald Buddenhagen .info = snd_emu1010_adc_pads_info,
792536438f1SOswald Buddenhagen .get = snd_emu1010_adc_pads_get,
793536438f1SOswald Buddenhagen .put = snd_emu1010_adc_pads_put
794536438f1SOswald Buddenhagen };
7959148cc50SJames Courtier-Dutton
7969148cc50SJames Courtier-Dutton
797536438f1SOswald Buddenhagen static const char * const snd_emu1010_dac_pads[] = {
798f69d705dSOswald Buddenhagen "DAC1 0202 14dB PAD Playback Switch",
799536438f1SOswald Buddenhagen "DAC1 Audio Dock 14dB PAD Playback Switch",
800536438f1SOswald Buddenhagen "DAC2 Audio Dock 14dB PAD Playback Switch",
801536438f1SOswald Buddenhagen "DAC3 Audio Dock 14dB PAD Playback Switch",
802536438f1SOswald Buddenhagen "DAC4 Audio Dock 14dB PAD Playback Switch",
803536438f1SOswald Buddenhagen };
8049148cc50SJames Courtier-Dutton
805536438f1SOswald Buddenhagen static const unsigned short snd_emu1010_dac_regs[] = {
806f69d705dSOswald Buddenhagen EMU_HANA_0202_DAC_PAD1,
807536438f1SOswald Buddenhagen EMU_HANA_DOCK_DAC_PAD1,
808536438f1SOswald Buddenhagen EMU_HANA_DOCK_DAC_PAD2,
809536438f1SOswald Buddenhagen EMU_HANA_DOCK_DAC_PAD3,
810536438f1SOswald Buddenhagen EMU_HANA_DOCK_DAC_PAD4,
8119148cc50SJames Courtier-Dutton };
8129148cc50SJames Courtier-Dutton
813a5ce8890STakashi Iwai #define snd_emu1010_dac_pads_info snd_ctl_boolean_mono_info
8149148cc50SJames Courtier-Dutton
snd_emu1010_dac_pads_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)8159148cc50SJames Courtier-Dutton static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8169148cc50SJames Courtier-Dutton {
8179148cc50SJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
818536438f1SOswald Buddenhagen unsigned int mask = snd_emu1010_dac_regs[kcontrol->private_value];
819536438f1SOswald Buddenhagen
8209148cc50SJames Courtier-Dutton ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
8219148cc50SJames Courtier-Dutton return 0;
8229148cc50SJames Courtier-Dutton }
8239148cc50SJames Courtier-Dutton
snd_emu1010_dac_pads_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)8249148cc50SJames Courtier-Dutton static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8259148cc50SJames Courtier-Dutton {
8269148cc50SJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
827536438f1SOswald Buddenhagen unsigned int mask = snd_emu1010_dac_regs[kcontrol->private_value];
8289148cc50SJames Courtier-Dutton unsigned int val, cache;
829cc766807SOswald Buddenhagen int change;
830cc766807SOswald Buddenhagen
8319148cc50SJames Courtier-Dutton val = ucontrol->value.integer.value[0];
8329148cc50SJames Courtier-Dutton cache = emu->emu1010.dac_pads;
8339148cc50SJames Courtier-Dutton if (val == 1)
8349148cc50SJames Courtier-Dutton cache = cache | mask;
8359148cc50SJames Courtier-Dutton else
8369148cc50SJames Courtier-Dutton cache = cache & ~mask;
837cc766807SOswald Buddenhagen change = (cache != emu->emu1010.dac_pads);
838cc766807SOswald Buddenhagen if (change) {
839*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_write_lock(emu, EMU_HANA_DAC_PADS, cache );
8409148cc50SJames Courtier-Dutton emu->emu1010.dac_pads = cache;
8419148cc50SJames Courtier-Dutton }
8429148cc50SJames Courtier-Dutton
843cc766807SOswald Buddenhagen return change;
8449148cc50SJames Courtier-Dutton }
8459148cc50SJames Courtier-Dutton
846536438f1SOswald Buddenhagen static const struct snd_kcontrol_new emu1010_dac_pads_ctl = {
847536438f1SOswald Buddenhagen .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
848536438f1SOswald Buddenhagen .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
849536438f1SOswald Buddenhagen .info = snd_emu1010_dac_pads_info,
850536438f1SOswald Buddenhagen .get = snd_emu1010_dac_pads_get,
851536438f1SOswald Buddenhagen .put = snd_emu1010_dac_pads_put
8529f4bd5ddSJames Courtier-Dutton };
8539f4bd5ddSJames Courtier-Dutton
854b0dbdaeaSJames Courtier-Dutton
85597f1582eSOswald Buddenhagen struct snd_emu1010_pads_info {
85697f1582eSOswald Buddenhagen const char * const *adc_ctls, * const *dac_ctls;
85797f1582eSOswald Buddenhagen unsigned n_adc_ctls, n_dac_ctls;
85897f1582eSOswald Buddenhagen };
85997f1582eSOswald Buddenhagen
860816967d5STom Rix static const struct snd_emu1010_pads_info emu1010_pads_info[] = {
86197f1582eSOswald Buddenhagen {
8626f3609f8SOswald Buddenhagen /* rev1 1010 */
86397f1582eSOswald Buddenhagen .adc_ctls = snd_emu1010_adc_pads,
86497f1582eSOswald Buddenhagen .n_adc_ctls = ARRAY_SIZE(snd_emu1010_adc_pads),
86597f1582eSOswald Buddenhagen .dac_ctls = snd_emu1010_dac_pads,
86697f1582eSOswald Buddenhagen .n_dac_ctls = ARRAY_SIZE(snd_emu1010_dac_pads),
86797f1582eSOswald Buddenhagen },
86897f1582eSOswald Buddenhagen {
869f69d705dSOswald Buddenhagen /* rev2 1010 */
87097f1582eSOswald Buddenhagen .adc_ctls = snd_emu1010_adc_pads,
871f69d705dSOswald Buddenhagen .n_adc_ctls = ARRAY_SIZE(snd_emu1010_adc_pads) - 1,
87297f1582eSOswald Buddenhagen .dac_ctls = snd_emu1010_dac_pads,
873f69d705dSOswald Buddenhagen .n_dac_ctls = ARRAY_SIZE(snd_emu1010_dac_pads) - 1,
874f69d705dSOswald Buddenhagen },
875f69d705dSOswald Buddenhagen {
876f69d705dSOswald Buddenhagen /* 1616(m) cardbus */
877f69d705dSOswald Buddenhagen .adc_ctls = snd_emu1010_adc_pads + 1,
878f69d705dSOswald Buddenhagen .n_adc_ctls = ARRAY_SIZE(snd_emu1010_adc_pads) - 2,
879f69d705dSOswald Buddenhagen .dac_ctls = snd_emu1010_dac_pads + 1,
88097f1582eSOswald Buddenhagen .n_dac_ctls = ARRAY_SIZE(snd_emu1010_dac_pads) - 2,
88197f1582eSOswald Buddenhagen },
8826f3609f8SOswald Buddenhagen {
8836f3609f8SOswald Buddenhagen /* 0404 */
8846f3609f8SOswald Buddenhagen .adc_ctls = NULL,
8856f3609f8SOswald Buddenhagen .n_adc_ctls = 0,
8866f3609f8SOswald Buddenhagen .dac_ctls = NULL,
8876f3609f8SOswald Buddenhagen .n_dac_ctls = 0,
8886f3609f8SOswald Buddenhagen },
88997f1582eSOswald Buddenhagen };
89097f1582eSOswald Buddenhagen
89160985241SOswald Buddenhagen static const char * const emu1010_clock_texts[] = {
89260985241SOswald Buddenhagen "44100", "48000", "SPDIF", "ADAT", "Dock", "BNC"
89360985241SOswald Buddenhagen };
89460985241SOswald Buddenhagen
89560985241SOswald Buddenhagen static const u8 emu1010_clock_vals[] = {
89660985241SOswald Buddenhagen EMU_HANA_WCLOCK_INT_44_1K,
89760985241SOswald Buddenhagen EMU_HANA_WCLOCK_INT_48K,
89860985241SOswald Buddenhagen EMU_HANA_WCLOCK_HANA_SPDIF_IN,
89960985241SOswald Buddenhagen EMU_HANA_WCLOCK_HANA_ADAT_IN,
90060985241SOswald Buddenhagen EMU_HANA_WCLOCK_2ND_HANA,
90160985241SOswald Buddenhagen EMU_HANA_WCLOCK_SYNC_BNC,
90260985241SOswald Buddenhagen };
90360985241SOswald Buddenhagen
90460985241SOswald Buddenhagen static const char * const emu0404_clock_texts[] = {
90560985241SOswald Buddenhagen "44100", "48000", "SPDIF", "BNC"
90660985241SOswald Buddenhagen };
90760985241SOswald Buddenhagen
90860985241SOswald Buddenhagen static const u8 emu0404_clock_vals[] = {
90960985241SOswald Buddenhagen EMU_HANA_WCLOCK_INT_44_1K,
91060985241SOswald Buddenhagen EMU_HANA_WCLOCK_INT_48K,
91160985241SOswald Buddenhagen EMU_HANA_WCLOCK_HANA_SPDIF_IN,
91260985241SOswald Buddenhagen EMU_HANA_WCLOCK_SYNC_BNC,
91360985241SOswald Buddenhagen };
91460985241SOswald Buddenhagen
91560985241SOswald Buddenhagen struct snd_emu1010_clock_info {
91660985241SOswald Buddenhagen const char * const *texts;
91760985241SOswald Buddenhagen const u8 *vals;
91860985241SOswald Buddenhagen unsigned num;
91960985241SOswald Buddenhagen };
92060985241SOswald Buddenhagen
92160985241SOswald Buddenhagen static const struct snd_emu1010_clock_info emu1010_clock_info[] = {
92260985241SOswald Buddenhagen {
92360985241SOswald Buddenhagen // rev1 1010
92460985241SOswald Buddenhagen .texts = emu1010_clock_texts,
92560985241SOswald Buddenhagen .vals = emu1010_clock_vals,
92660985241SOswald Buddenhagen .num = ARRAY_SIZE(emu1010_clock_vals),
92760985241SOswald Buddenhagen },
92860985241SOswald Buddenhagen {
92960985241SOswald Buddenhagen // rev2 1010
93060985241SOswald Buddenhagen .texts = emu1010_clock_texts,
93160985241SOswald Buddenhagen .vals = emu1010_clock_vals,
93260985241SOswald Buddenhagen .num = ARRAY_SIZE(emu1010_clock_vals) - 1,
93360985241SOswald Buddenhagen },
93460985241SOswald Buddenhagen {
93560985241SOswald Buddenhagen // 1616(m) CardBus
93660985241SOswald Buddenhagen .texts = emu1010_clock_texts,
93760985241SOswald Buddenhagen // TODO: determine what is actually available.
93860985241SOswald Buddenhagen // Pedantically, *every* source comes from the 2nd FPGA, as the
93960985241SOswald Buddenhagen // card itself has no own (digital) audio ports. The user manual
94060985241SOswald Buddenhagen // claims that ADAT and S/PDIF clock sources are separate, which
94160985241SOswald Buddenhagen // can mean two things: either E-MU mapped the dock's sources to
94260985241SOswald Buddenhagen // the primary ones, or they determine the meaning of the "Dock"
94360985241SOswald Buddenhagen // source depending on how the ports are actually configured
94460985241SOswald Buddenhagen // (which the 2nd FPGA must be doing anyway).
94560985241SOswald Buddenhagen .vals = emu1010_clock_vals,
94660985241SOswald Buddenhagen .num = ARRAY_SIZE(emu1010_clock_vals),
94760985241SOswald Buddenhagen },
94860985241SOswald Buddenhagen {
94960985241SOswald Buddenhagen // 0404
95060985241SOswald Buddenhagen .texts = emu0404_clock_texts,
95160985241SOswald Buddenhagen .vals = emu0404_clock_vals,
95260985241SOswald Buddenhagen .num = ARRAY_SIZE(emu0404_clock_vals),
95360985241SOswald Buddenhagen },
95460985241SOswald Buddenhagen };
95597f1582eSOswald Buddenhagen
snd_emu1010_clock_source_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)95613598862SOswald Buddenhagen static int snd_emu1010_clock_source_info(struct snd_kcontrol *kcontrol,
957b0dbdaeaSJames Courtier-Dutton struct snd_ctl_elem_info *uinfo)
958b0dbdaeaSJames Courtier-Dutton {
95960985241SOswald Buddenhagen struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
96060985241SOswald Buddenhagen const struct snd_emu1010_clock_info *emu_ci =
96160985241SOswald Buddenhagen &emu1010_clock_info[emu1010_idx(emu)];
962b0dbdaeaSJames Courtier-Dutton
96360985241SOswald Buddenhagen return snd_ctl_enum_info(uinfo, 1, emu_ci->num, emu_ci->texts);
964b0dbdaeaSJames Courtier-Dutton }
965b0dbdaeaSJames Courtier-Dutton
snd_emu1010_clock_source_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)96613598862SOswald Buddenhagen static int snd_emu1010_clock_source_get(struct snd_kcontrol *kcontrol,
967b0dbdaeaSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
968b0dbdaeaSJames Courtier-Dutton {
969b0dbdaeaSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
970b0dbdaeaSJames Courtier-Dutton
97113598862SOswald Buddenhagen ucontrol->value.enumerated.item[0] = emu->emu1010.clock_source;
972b0dbdaeaSJames Courtier-Dutton return 0;
973b0dbdaeaSJames Courtier-Dutton }
974b0dbdaeaSJames Courtier-Dutton
snd_emu1010_clock_source_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)97513598862SOswald Buddenhagen static int snd_emu1010_clock_source_put(struct snd_kcontrol *kcontrol,
976b0dbdaeaSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
977b0dbdaeaSJames Courtier-Dutton {
978b0dbdaeaSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
97960985241SOswald Buddenhagen const struct snd_emu1010_clock_info *emu_ci =
98060985241SOswald Buddenhagen &emu1010_clock_info[emu1010_idx(emu)];
981b0dbdaeaSJames Courtier-Dutton unsigned int val;
982b0dbdaeaSJames Courtier-Dutton int change = 0;
983b0dbdaeaSJames Courtier-Dutton
984b0dbdaeaSJames Courtier-Dutton val = ucontrol->value.enumerated.item[0] ;
98560985241SOswald Buddenhagen if (val >= emu_ci->num)
98674415a36SJames Courtier-Dutton return -EINVAL;
987*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_lock(emu);
988c960b012SOswald Buddenhagen spin_lock_irq(&emu->reg_lock);
98913598862SOswald Buddenhagen change = (emu->emu1010.clock_source != val);
990b0dbdaeaSJames Courtier-Dutton if (change) {
99113598862SOswald Buddenhagen emu->emu1010.clock_source = val;
99260985241SOswald Buddenhagen emu->emu1010.wclock = emu_ci->vals[val];
993c960b012SOswald Buddenhagen snd_emu1010_update_clock(emu);
994edec7bbbSJames Courtier-Dutton
995edec7bbbSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE);
99660985241SOswald Buddenhagen snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, emu->emu1010.wclock);
997c960b012SOswald Buddenhagen spin_unlock_irq(&emu->reg_lock);
998c960b012SOswald Buddenhagen
99960985241SOswald Buddenhagen msleep(10); // Allow DLL to settle
1000edec7bbbSJames Courtier-Dutton snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
1001c960b012SOswald Buddenhagen } else {
1002c960b012SOswald Buddenhagen spin_unlock_irq(&emu->reg_lock);
1003b0dbdaeaSJames Courtier-Dutton }
1004*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_unlock(emu);
1005b0dbdaeaSJames Courtier-Dutton return change;
1006b0dbdaeaSJames Courtier-Dutton }
1007b0dbdaeaSJames Courtier-Dutton
100813598862SOswald Buddenhagen static const struct snd_kcontrol_new snd_emu1010_clock_source =
1009b0dbdaeaSJames Courtier-Dutton {
1010b0dbdaeaSJames Courtier-Dutton .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
1011b0dbdaeaSJames Courtier-Dutton .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
101213598862SOswald Buddenhagen .name = "Clock Source",
1013b0dbdaeaSJames Courtier-Dutton .count = 1,
101413598862SOswald Buddenhagen .info = snd_emu1010_clock_source_info,
101513598862SOswald Buddenhagen .get = snd_emu1010_clock_source_get,
101613598862SOswald Buddenhagen .put = snd_emu1010_clock_source_put
101713598862SOswald Buddenhagen };
101813598862SOswald Buddenhagen
snd_emu1010_clock_fallback_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)101913598862SOswald Buddenhagen static int snd_emu1010_clock_fallback_info(struct snd_kcontrol *kcontrol,
102013598862SOswald Buddenhagen struct snd_ctl_elem_info *uinfo)
102113598862SOswald Buddenhagen {
102213598862SOswald Buddenhagen static const char * const texts[2] = {
102313598862SOswald Buddenhagen "44100", "48000"
102413598862SOswald Buddenhagen };
102513598862SOswald Buddenhagen
102613598862SOswald Buddenhagen return snd_ctl_enum_info(uinfo, 1, 2, texts);
102713598862SOswald Buddenhagen }
102813598862SOswald Buddenhagen
snd_emu1010_clock_fallback_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)102913598862SOswald Buddenhagen static int snd_emu1010_clock_fallback_get(struct snd_kcontrol *kcontrol,
103013598862SOswald Buddenhagen struct snd_ctl_elem_value *ucontrol)
103113598862SOswald Buddenhagen {
103213598862SOswald Buddenhagen struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
103313598862SOswald Buddenhagen
103413598862SOswald Buddenhagen ucontrol->value.enumerated.item[0] = emu->emu1010.clock_fallback;
103513598862SOswald Buddenhagen return 0;
103613598862SOswald Buddenhagen }
103713598862SOswald Buddenhagen
snd_emu1010_clock_fallback_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)103813598862SOswald Buddenhagen static int snd_emu1010_clock_fallback_put(struct snd_kcontrol *kcontrol,
103913598862SOswald Buddenhagen struct snd_ctl_elem_value *ucontrol)
104013598862SOswald Buddenhagen {
104113598862SOswald Buddenhagen struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
104213598862SOswald Buddenhagen unsigned int val = ucontrol->value.enumerated.item[0];
104313598862SOswald Buddenhagen int change;
104413598862SOswald Buddenhagen
104513598862SOswald Buddenhagen if (val >= 2)
104613598862SOswald Buddenhagen return -EINVAL;
104713598862SOswald Buddenhagen change = (emu->emu1010.clock_fallback != val);
104813598862SOswald Buddenhagen if (change) {
104913598862SOswald Buddenhagen emu->emu1010.clock_fallback = val;
1050*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_write_lock(emu, EMU_HANA_DEFCLOCK, 1 - val);
105113598862SOswald Buddenhagen }
105213598862SOswald Buddenhagen return change;
105313598862SOswald Buddenhagen }
105413598862SOswald Buddenhagen
105513598862SOswald Buddenhagen static const struct snd_kcontrol_new snd_emu1010_clock_fallback =
105613598862SOswald Buddenhagen {
105713598862SOswald Buddenhagen .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
105813598862SOswald Buddenhagen .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
105913598862SOswald Buddenhagen .name = "Clock Fallback",
106013598862SOswald Buddenhagen .count = 1,
106113598862SOswald Buddenhagen .info = snd_emu1010_clock_fallback_info,
106213598862SOswald Buddenhagen .get = snd_emu1010_clock_fallback_get,
106313598862SOswald Buddenhagen .put = snd_emu1010_clock_fallback_put
1064b0dbdaeaSJames Courtier-Dutton };
1065b0dbdaeaSJames Courtier-Dutton
snd_emu1010_optical_out_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)106699dcab46SMichael Gernoth static int snd_emu1010_optical_out_info(struct snd_kcontrol *kcontrol,
106799dcab46SMichael Gernoth struct snd_ctl_elem_info *uinfo)
106899dcab46SMichael Gernoth {
106999dcab46SMichael Gernoth static const char * const texts[2] = {
107099dcab46SMichael Gernoth "SPDIF", "ADAT"
107199dcab46SMichael Gernoth };
107299dcab46SMichael Gernoth
107399dcab46SMichael Gernoth return snd_ctl_enum_info(uinfo, 1, 2, texts);
107499dcab46SMichael Gernoth }
107599dcab46SMichael Gernoth
snd_emu1010_optical_out_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)107699dcab46SMichael Gernoth static int snd_emu1010_optical_out_get(struct snd_kcontrol *kcontrol,
107799dcab46SMichael Gernoth struct snd_ctl_elem_value *ucontrol)
107899dcab46SMichael Gernoth {
107999dcab46SMichael Gernoth struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
108099dcab46SMichael Gernoth
108199dcab46SMichael Gernoth ucontrol->value.enumerated.item[0] = emu->emu1010.optical_out;
108299dcab46SMichael Gernoth return 0;
108399dcab46SMichael Gernoth }
108499dcab46SMichael Gernoth
snd_emu1010_optical_out_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)108599dcab46SMichael Gernoth static int snd_emu1010_optical_out_put(struct snd_kcontrol *kcontrol,
108699dcab46SMichael Gernoth struct snd_ctl_elem_value *ucontrol)
108799dcab46SMichael Gernoth {
108899dcab46SMichael Gernoth struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
108999dcab46SMichael Gernoth unsigned int val;
109099dcab46SMichael Gernoth u32 tmp;
109199dcab46SMichael Gernoth int change = 0;
109299dcab46SMichael Gernoth
109399dcab46SMichael Gernoth val = ucontrol->value.enumerated.item[0];
109499dcab46SMichael Gernoth /* Limit: uinfo->value.enumerated.items = 2; */
109599dcab46SMichael Gernoth if (val >= 2)
109699dcab46SMichael Gernoth return -EINVAL;
109799dcab46SMichael Gernoth change = (emu->emu1010.optical_out != val);
109899dcab46SMichael Gernoth if (change) {
109999dcab46SMichael Gernoth emu->emu1010.optical_out = val;
11009d2f3863SOswald Buddenhagen tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
11019d2f3863SOswald Buddenhagen (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
1102*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
110399dcab46SMichael Gernoth }
110499dcab46SMichael Gernoth return change;
110599dcab46SMichael Gernoth }
110699dcab46SMichael Gernoth
1107f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu1010_optical_out = {
110899dcab46SMichael Gernoth .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
110999dcab46SMichael Gernoth .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
111099dcab46SMichael Gernoth .name = "Optical Output Mode",
111199dcab46SMichael Gernoth .count = 1,
111299dcab46SMichael Gernoth .info = snd_emu1010_optical_out_info,
111399dcab46SMichael Gernoth .get = snd_emu1010_optical_out_get,
111499dcab46SMichael Gernoth .put = snd_emu1010_optical_out_put
111599dcab46SMichael Gernoth };
111699dcab46SMichael Gernoth
snd_emu1010_optical_in_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)111799dcab46SMichael Gernoth static int snd_emu1010_optical_in_info(struct snd_kcontrol *kcontrol,
111899dcab46SMichael Gernoth struct snd_ctl_elem_info *uinfo)
111999dcab46SMichael Gernoth {
112099dcab46SMichael Gernoth static const char * const texts[2] = {
112199dcab46SMichael Gernoth "SPDIF", "ADAT"
112299dcab46SMichael Gernoth };
112399dcab46SMichael Gernoth
112499dcab46SMichael Gernoth return snd_ctl_enum_info(uinfo, 1, 2, texts);
112599dcab46SMichael Gernoth }
112699dcab46SMichael Gernoth
snd_emu1010_optical_in_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)112799dcab46SMichael Gernoth static int snd_emu1010_optical_in_get(struct snd_kcontrol *kcontrol,
112899dcab46SMichael Gernoth struct snd_ctl_elem_value *ucontrol)
112999dcab46SMichael Gernoth {
113099dcab46SMichael Gernoth struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
113199dcab46SMichael Gernoth
113299dcab46SMichael Gernoth ucontrol->value.enumerated.item[0] = emu->emu1010.optical_in;
113399dcab46SMichael Gernoth return 0;
113499dcab46SMichael Gernoth }
113599dcab46SMichael Gernoth
snd_emu1010_optical_in_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)113699dcab46SMichael Gernoth static int snd_emu1010_optical_in_put(struct snd_kcontrol *kcontrol,
113799dcab46SMichael Gernoth struct snd_ctl_elem_value *ucontrol)
113899dcab46SMichael Gernoth {
113999dcab46SMichael Gernoth struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
114099dcab46SMichael Gernoth unsigned int val;
114199dcab46SMichael Gernoth u32 tmp;
114299dcab46SMichael Gernoth int change = 0;
114399dcab46SMichael Gernoth
114499dcab46SMichael Gernoth val = ucontrol->value.enumerated.item[0];
114599dcab46SMichael Gernoth /* Limit: uinfo->value.enumerated.items = 2; */
114699dcab46SMichael Gernoth if (val >= 2)
114799dcab46SMichael Gernoth return -EINVAL;
114899dcab46SMichael Gernoth change = (emu->emu1010.optical_in != val);
114999dcab46SMichael Gernoth if (change) {
115099dcab46SMichael Gernoth emu->emu1010.optical_in = val;
11519d2f3863SOswald Buddenhagen tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : EMU_HANA_OPTICAL_IN_SPDIF) |
11529d2f3863SOswald Buddenhagen (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : EMU_HANA_OPTICAL_OUT_SPDIF);
1153*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_write_lock(emu, EMU_HANA_OPTICAL_TYPE, tmp);
115499dcab46SMichael Gernoth }
115599dcab46SMichael Gernoth return change;
115699dcab46SMichael Gernoth }
115799dcab46SMichael Gernoth
1158f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu1010_optical_in = {
115999dcab46SMichael Gernoth .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
116099dcab46SMichael Gernoth .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
116199dcab46SMichael Gernoth .name = "Optical Input Mode",
116299dcab46SMichael Gernoth .count = 1,
116399dcab46SMichael Gernoth .info = snd_emu1010_optical_in_info,
116499dcab46SMichael Gernoth .get = snd_emu1010_optical_in_get,
116599dcab46SMichael Gernoth .put = snd_emu1010_optical_in_put
116699dcab46SMichael Gernoth };
116799dcab46SMichael Gernoth
snd_audigy_i2c_capture_source_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1168184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
1169184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_info *uinfo)
1170184c1e2cSJames Courtier-Dutton {
1171184c1e2cSJames Courtier-Dutton #if 0
11721541c66dSTakashi Iwai static const char * const texts[4] = {
1173184c1e2cSJames Courtier-Dutton "Unknown1", "Unknown2", "Mic", "Line"
1174184c1e2cSJames Courtier-Dutton };
1175184c1e2cSJames Courtier-Dutton #endif
11761541c66dSTakashi Iwai static const char * const texts[2] = {
1177184c1e2cSJames Courtier-Dutton "Mic", "Line"
1178184c1e2cSJames Courtier-Dutton };
1179184c1e2cSJames Courtier-Dutton
11801541c66dSTakashi Iwai return snd_ctl_enum_info(uinfo, 1, 2, texts);
1181184c1e2cSJames Courtier-Dutton }
1182184c1e2cSJames Courtier-Dutton
snd_audigy_i2c_capture_source_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1183184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
1184184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
1185184c1e2cSJames Courtier-Dutton {
1186184c1e2cSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1187184c1e2cSJames Courtier-Dutton
1188184c1e2cSJames Courtier-Dutton ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
1189184c1e2cSJames Courtier-Dutton return 0;
1190184c1e2cSJames Courtier-Dutton }
1191184c1e2cSJames Courtier-Dutton
snd_audigy_i2c_capture_source_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1192184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
1193184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
1194184c1e2cSJames Courtier-Dutton {
1195184c1e2cSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1196184c1e2cSJames Courtier-Dutton unsigned int source_id;
1197184c1e2cSJames Courtier-Dutton unsigned int ngain, ogain;
1198a1c87c0bSOswald Buddenhagen u16 gpio;
1199184c1e2cSJames Courtier-Dutton int change = 0;
1200184c1e2cSJames Courtier-Dutton u32 source;
1201184c1e2cSJames Courtier-Dutton /* If the capture source has changed,
1202184c1e2cSJames Courtier-Dutton * update the capture volume from the cached value
1203184c1e2cSJames Courtier-Dutton * for the particular source.
1204184c1e2cSJames Courtier-Dutton */
120574415a36SJames Courtier-Dutton source_id = ucontrol->value.enumerated.item[0];
120674415a36SJames Courtier-Dutton /* Limit: uinfo->value.enumerated.items = 2; */
120774415a36SJames Courtier-Dutton /* emu->i2c_capture_volume */
120874415a36SJames Courtier-Dutton if (source_id >= 2)
120974415a36SJames Courtier-Dutton return -EINVAL;
1210184c1e2cSJames Courtier-Dutton change = (emu->i2c_capture_source != source_id);
1211184c1e2cSJames Courtier-Dutton if (change) {
1212184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
121367192cc0SOswald Buddenhagen spin_lock_irq(&emu->emu_lock);
1214a1c87c0bSOswald Buddenhagen gpio = inw(emu->port + A_IOCFG);
1215184c1e2cSJames Courtier-Dutton if (source_id==0)
1216a1c87c0bSOswald Buddenhagen outw(gpio | 0x4, emu->port + A_IOCFG);
1217184c1e2cSJames Courtier-Dutton else
1218a1c87c0bSOswald Buddenhagen outw(gpio & ~0x4, emu->port + A_IOCFG);
121967192cc0SOswald Buddenhagen spin_unlock_irq(&emu->emu_lock);
1220184c1e2cSJames Courtier-Dutton
1221184c1e2cSJames Courtier-Dutton ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
1222184c1e2cSJames Courtier-Dutton ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
1223184c1e2cSJames Courtier-Dutton if (ngain != ogain)
1224184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
1225184c1e2cSJames Courtier-Dutton ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
1226184c1e2cSJames Courtier-Dutton ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
1227184c1e2cSJames Courtier-Dutton if (ngain != ogain)
1228184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
1229184c1e2cSJames Courtier-Dutton
1230184c1e2cSJames Courtier-Dutton source = 1 << (source_id + 2);
1231184c1e2cSJames Courtier-Dutton snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
1232184c1e2cSJames Courtier-Dutton emu->i2c_capture_source = source_id;
1233184c1e2cSJames Courtier-Dutton }
1234184c1e2cSJames Courtier-Dutton return change;
1235184c1e2cSJames Courtier-Dutton }
1236184c1e2cSJames Courtier-Dutton
1237f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_audigy_i2c_capture_source =
1238184c1e2cSJames Courtier-Dutton {
1239184c1e2cSJames Courtier-Dutton .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1240184c1e2cSJames Courtier-Dutton .name = "Capture Source",
1241184c1e2cSJames Courtier-Dutton .info = snd_audigy_i2c_capture_source_info,
1242184c1e2cSJames Courtier-Dutton .get = snd_audigy_i2c_capture_source_get,
1243184c1e2cSJames Courtier-Dutton .put = snd_audigy_i2c_capture_source_put
1244184c1e2cSJames Courtier-Dutton };
1245184c1e2cSJames Courtier-Dutton
snd_audigy_i2c_volume_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1246184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
1247184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_info *uinfo)
1248184c1e2cSJames Courtier-Dutton {
1249184c1e2cSJames Courtier-Dutton uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1250184c1e2cSJames Courtier-Dutton uinfo->count = 2;
1251184c1e2cSJames Courtier-Dutton uinfo->value.integer.min = 0;
1252184c1e2cSJames Courtier-Dutton uinfo->value.integer.max = 255;
1253184c1e2cSJames Courtier-Dutton return 0;
1254184c1e2cSJames Courtier-Dutton }
1255184c1e2cSJames Courtier-Dutton
snd_audigy_i2c_volume_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1256184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
1257184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
1258184c1e2cSJames Courtier-Dutton {
1259184c1e2cSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
126074415a36SJames Courtier-Dutton unsigned int source_id;
1261184c1e2cSJames Courtier-Dutton
1262184c1e2cSJames Courtier-Dutton source_id = kcontrol->private_value;
126374415a36SJames Courtier-Dutton /* Limit: emu->i2c_capture_volume */
126474415a36SJames Courtier-Dutton /* capture_source: uinfo->value.enumerated.items = 2 */
126574415a36SJames Courtier-Dutton if (source_id >= 2)
126674415a36SJames Courtier-Dutton return -EINVAL;
1267184c1e2cSJames Courtier-Dutton
1268184c1e2cSJames Courtier-Dutton ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
1269184c1e2cSJames Courtier-Dutton ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
1270184c1e2cSJames Courtier-Dutton return 0;
1271184c1e2cSJames Courtier-Dutton }
1272184c1e2cSJames Courtier-Dutton
snd_audigy_i2c_volume_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1273184c1e2cSJames Courtier-Dutton static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
1274184c1e2cSJames Courtier-Dutton struct snd_ctl_elem_value *ucontrol)
1275184c1e2cSJames Courtier-Dutton {
1276184c1e2cSJames Courtier-Dutton struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1277184c1e2cSJames Courtier-Dutton unsigned int ogain;
127814a29565SOswald Buddenhagen unsigned int ngain0, ngain1;
127974415a36SJames Courtier-Dutton unsigned int source_id;
1280184c1e2cSJames Courtier-Dutton int change = 0;
1281184c1e2cSJames Courtier-Dutton
1282184c1e2cSJames Courtier-Dutton source_id = kcontrol->private_value;
128374415a36SJames Courtier-Dutton /* Limit: emu->i2c_capture_volume */
128474415a36SJames Courtier-Dutton /* capture_source: uinfo->value.enumerated.items = 2 */
128574415a36SJames Courtier-Dutton if (source_id >= 2)
128674415a36SJames Courtier-Dutton return -EINVAL;
128714a29565SOswald Buddenhagen ngain0 = ucontrol->value.integer.value[0];
128814a29565SOswald Buddenhagen ngain1 = ucontrol->value.integer.value[1];
128914a29565SOswald Buddenhagen if (ngain0 > 0xff)
129014a29565SOswald Buddenhagen return -EINVAL;
129114a29565SOswald Buddenhagen if (ngain1 > 0xff)
129214a29565SOswald Buddenhagen return -EINVAL;
1293184c1e2cSJames Courtier-Dutton ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
129414a29565SOswald Buddenhagen if (ogain != ngain0) {
1295184c1e2cSJames Courtier-Dutton if (emu->i2c_capture_source == source_id)
129614a29565SOswald Buddenhagen snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ngain0);
129714a29565SOswald Buddenhagen emu->i2c_capture_volume[source_id][0] = ngain0;
1298184c1e2cSJames Courtier-Dutton change = 1;
1299184c1e2cSJames Courtier-Dutton }
1300184c1e2cSJames Courtier-Dutton ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
130114a29565SOswald Buddenhagen if (ogain != ngain1) {
1302184c1e2cSJames Courtier-Dutton if (emu->i2c_capture_source == source_id)
130314a29565SOswald Buddenhagen snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ngain1);
130414a29565SOswald Buddenhagen emu->i2c_capture_volume[source_id][1] = ngain1;
1305184c1e2cSJames Courtier-Dutton change = 1;
1306184c1e2cSJames Courtier-Dutton }
1307184c1e2cSJames Courtier-Dutton
1308184c1e2cSJames Courtier-Dutton return change;
1309184c1e2cSJames Courtier-Dutton }
1310184c1e2cSJames Courtier-Dutton
1311536438f1SOswald Buddenhagen static const struct snd_kcontrol_new i2c_volume_ctl = {
1312536438f1SOswald Buddenhagen .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1313536438f1SOswald Buddenhagen .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
1314536438f1SOswald Buddenhagen SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1315536438f1SOswald Buddenhagen .info = snd_audigy_i2c_volume_info,
1316536438f1SOswald Buddenhagen .get = snd_audigy_i2c_volume_get,
1317536438f1SOswald Buddenhagen .put = snd_audigy_i2c_volume_put,
1318536438f1SOswald Buddenhagen .tlv = { .p = snd_audigy_db_scale2 }
1319536438f1SOswald Buddenhagen };
1320184c1e2cSJames Courtier-Dutton
1321536438f1SOswald Buddenhagen static const char * const snd_audigy_i2c_volume_ctls[] = {
1322536438f1SOswald Buddenhagen "Mic Capture Volume",
1323536438f1SOswald Buddenhagen "Line Capture Volume",
1324184c1e2cSJames Courtier-Dutton };
1325184c1e2cSJames Courtier-Dutton
13260af68e5eSTakashi Iwai #if 0
1327eb4698f3STakashi Iwai static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
13281da177e4SLinus Torvalds {
13291541c66dSTakashi Iwai static const char * const texts[] = {"44100", "48000", "96000"};
13301da177e4SLinus Torvalds
13311541c66dSTakashi Iwai return snd_ctl_enum_info(uinfo, 1, 3, texts);
13321da177e4SLinus Torvalds }
13331da177e4SLinus Torvalds
1334eb4698f3STakashi Iwai static int snd_audigy_spdif_output_rate_get(struct snd_kcontrol *kcontrol,
1335eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
13361da177e4SLinus Torvalds {
1337eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
13381da177e4SLinus Torvalds unsigned int tmp;
13391da177e4SLinus Torvalds
13401da177e4SLinus Torvalds tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
13411da177e4SLinus Torvalds switch (tmp & A_SPDIF_RATE_MASK) {
13421da177e4SLinus Torvalds case A_SPDIF_44100:
13431da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 0;
13441da177e4SLinus Torvalds break;
13451da177e4SLinus Torvalds case A_SPDIF_48000:
13461da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 1;
13471da177e4SLinus Torvalds break;
13481da177e4SLinus Torvalds case A_SPDIF_96000:
13491da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 2;
13501da177e4SLinus Torvalds break;
13511da177e4SLinus Torvalds default:
13521da177e4SLinus Torvalds ucontrol->value.enumerated.item[0] = 1;
13531da177e4SLinus Torvalds }
13541da177e4SLinus Torvalds return 0;
13551da177e4SLinus Torvalds }
13561da177e4SLinus Torvalds
1357eb4698f3STakashi Iwai static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
1358eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
13591da177e4SLinus Torvalds {
1360eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
13611da177e4SLinus Torvalds int change;
13621da177e4SLinus Torvalds unsigned int reg, val, tmp;
13631da177e4SLinus Torvalds
13641da177e4SLinus Torvalds switch(ucontrol->value.enumerated.item[0]) {
13651da177e4SLinus Torvalds case 0:
13661da177e4SLinus Torvalds val = A_SPDIF_44100;
13671da177e4SLinus Torvalds break;
13681da177e4SLinus Torvalds case 1:
13691da177e4SLinus Torvalds val = A_SPDIF_48000;
13701da177e4SLinus Torvalds break;
13711da177e4SLinus Torvalds case 2:
13721da177e4SLinus Torvalds val = A_SPDIF_96000;
13731da177e4SLinus Torvalds break;
13741da177e4SLinus Torvalds default:
13751da177e4SLinus Torvalds val = A_SPDIF_48000;
13761da177e4SLinus Torvalds break;
13771da177e4SLinus Torvalds }
13781da177e4SLinus Torvalds
13791da177e4SLinus Torvalds
138067192cc0SOswald Buddenhagen spin_lock_irq(&emu->reg_lock);
13811da177e4SLinus Torvalds reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
13821da177e4SLinus Torvalds tmp = reg & ~A_SPDIF_RATE_MASK;
13831da177e4SLinus Torvalds tmp |= val;
138412bda107STakashi Iwai change = (tmp != reg);
138512bda107STakashi Iwai if (change)
13861da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
138767192cc0SOswald Buddenhagen spin_unlock_irq(&emu->reg_lock);
13881da177e4SLinus Torvalds return change;
13891da177e4SLinus Torvalds }
13901da177e4SLinus Torvalds
1391b4e5e707STakashi Iwai static const struct snd_kcontrol_new snd_audigy_spdif_output_rate =
13921da177e4SLinus Torvalds {
13931da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
13941da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
13951da177e4SLinus Torvalds .name = "Audigy SPDIF Output Sample Rate",
13961da177e4SLinus Torvalds .count = 1,
13971da177e4SLinus Torvalds .info = snd_audigy_spdif_output_rate_info,
13981da177e4SLinus Torvalds .get = snd_audigy_spdif_output_rate_get,
13991da177e4SLinus Torvalds .put = snd_audigy_spdif_output_rate_put
14001da177e4SLinus Torvalds };
14010af68e5eSTakashi Iwai #endif
14021da177e4SLinus Torvalds
snd_emu10k1_spdif_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1403eb4698f3STakashi Iwai static int snd_emu10k1_spdif_put(struct snd_kcontrol *kcontrol,
1404eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
14051da177e4SLinus Torvalds {
1406eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
14071da177e4SLinus Torvalds unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
14081da177e4SLinus Torvalds int change;
14091da177e4SLinus Torvalds unsigned int val;
14101da177e4SLinus Torvalds
141174415a36SJames Courtier-Dutton /* Limit: emu->spdif_bits */
141274415a36SJames Courtier-Dutton if (idx >= 3)
141374415a36SJames Courtier-Dutton return -EINVAL;
14141da177e4SLinus Torvalds val = (ucontrol->value.iec958.status[0] << 0) |
14151da177e4SLinus Torvalds (ucontrol->value.iec958.status[1] << 8) |
14161da177e4SLinus Torvalds (ucontrol->value.iec958.status[2] << 16) |
14171da177e4SLinus Torvalds (ucontrol->value.iec958.status[3] << 24);
14181da177e4SLinus Torvalds change = val != emu->spdif_bits[idx];
14191da177e4SLinus Torvalds if (change) {
14201da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, SPCS0 + idx, 0, val);
14211da177e4SLinus Torvalds emu->spdif_bits[idx] = val;
14221da177e4SLinus Torvalds }
14231da177e4SLinus Torvalds return change;
14241da177e4SLinus Torvalds }
14251da177e4SLinus Torvalds
1426f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu10k1_spdif_mask_control =
14271da177e4SLinus Torvalds {
14281da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READ,
14295549d549SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM,
14301da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
14317583cb51STakashi Iwai .count = 3,
14321da177e4SLinus Torvalds .info = snd_emu10k1_spdif_info,
14331da177e4SLinus Torvalds .get = snd_emu10k1_spdif_get_mask
14341da177e4SLinus Torvalds };
14351da177e4SLinus Torvalds
1436f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu10k1_spdif_control =
14371da177e4SLinus Torvalds {
14385549d549SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM,
14391da177e4SLinus Torvalds .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
14407583cb51STakashi Iwai .count = 3,
14411da177e4SLinus Torvalds .info = snd_emu10k1_spdif_info,
14421da177e4SLinus Torvalds .get = snd_emu10k1_spdif_get,
14431da177e4SLinus Torvalds .put = snd_emu10k1_spdif_put
14441da177e4SLinus Torvalds };
14451da177e4SLinus Torvalds
14461da177e4SLinus Torvalds
update_emu10k1_fxrt(struct snd_emu10k1 * emu,int voice,unsigned char * route)1447eb4698f3STakashi Iwai static void update_emu10k1_fxrt(struct snd_emu10k1 *emu, int voice, unsigned char *route)
14481da177e4SLinus Torvalds {
14491da177e4SLinus Torvalds if (emu->audigy) {
145046055699SOswald Buddenhagen snd_emu10k1_ptr_write_multiple(emu, voice,
145146055699SOswald Buddenhagen A_FXRT1, snd_emu10k1_compose_audigy_fxrt1(route),
145246055699SOswald Buddenhagen A_FXRT2, snd_emu10k1_compose_audigy_fxrt2(route),
145346055699SOswald Buddenhagen REGLIST_END);
14541da177e4SLinus Torvalds } else {
14551da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, FXRT, voice,
14561da177e4SLinus Torvalds snd_emu10k1_compose_send_routing(route));
14571da177e4SLinus Torvalds }
14581da177e4SLinus Torvalds }
14591da177e4SLinus Torvalds
update_emu10k1_send_volume(struct snd_emu10k1 * emu,int voice,unsigned char * volume)1460eb4698f3STakashi Iwai static void update_emu10k1_send_volume(struct snd_emu10k1 *emu, int voice, unsigned char *volume)
14611da177e4SLinus Torvalds {
14621da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_A, voice, volume[0]);
14631da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, PTRX_FXSENDAMOUNT_B, voice, volume[1]);
14641da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, PSST_FXSENDAMOUNT_C, voice, volume[2]);
14651da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, DSL_FXSENDAMOUNT_D, voice, volume[3]);
14661da177e4SLinus Torvalds if (emu->audigy) {
146751d652f4SOswald Buddenhagen snd_emu10k1_ptr_write(emu, A_SENDAMOUNTS, voice,
146851d652f4SOswald Buddenhagen snd_emu10k1_compose_audigy_sendamounts(volume));
14691da177e4SLinus Torvalds }
14701da177e4SLinus Torvalds }
14711da177e4SLinus Torvalds
14721da177e4SLinus Torvalds /* PCM stream controls */
14731da177e4SLinus Torvalds
snd_emu10k1_send_routing_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1474eb4698f3STakashi Iwai static int snd_emu10k1_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
14751da177e4SLinus Torvalds {
1476eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
14771da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
14781da177e4SLinus Torvalds uinfo->count = emu->audigy ? 3*8 : 3*4;
14791da177e4SLinus Torvalds uinfo->value.integer.min = 0;
14801da177e4SLinus Torvalds uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
14811da177e4SLinus Torvalds return 0;
14821da177e4SLinus Torvalds }
14831da177e4SLinus Torvalds
snd_emu10k1_send_routing_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1484eb4698f3STakashi Iwai static int snd_emu10k1_send_routing_get(struct snd_kcontrol *kcontrol,
1485eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
14861da177e4SLinus Torvalds {
1487eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1488eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix =
1489eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
14901da177e4SLinus Torvalds int voice, idx;
14911da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4;
14921da177e4SLinus Torvalds int mask = emu->audigy ? 0x3f : 0x0f;
14931da177e4SLinus Torvalds
14941da177e4SLinus Torvalds for (voice = 0; voice < 3; voice++)
14951da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++)
14961da177e4SLinus Torvalds ucontrol->value.integer.value[(voice * num_efx) + idx] =
14971da177e4SLinus Torvalds mix->send_routing[voice][idx] & mask;
14981da177e4SLinus Torvalds return 0;
14991da177e4SLinus Torvalds }
15001da177e4SLinus Torvalds
snd_emu10k1_send_routing_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1501eb4698f3STakashi Iwai static int snd_emu10k1_send_routing_put(struct snd_kcontrol *kcontrol,
1502eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
15031da177e4SLinus Torvalds {
1504eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1505eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix =
1506eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
15071da177e4SLinus Torvalds int change = 0, voice, idx, val;
15081da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4;
15091da177e4SLinus Torvalds int mask = emu->audigy ? 0x3f : 0x0f;
15101da177e4SLinus Torvalds
151167192cc0SOswald Buddenhagen spin_lock_irq(&emu->reg_lock);
15121da177e4SLinus Torvalds for (voice = 0; voice < 3; voice++)
15131da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++) {
15141da177e4SLinus Torvalds val = ucontrol->value.integer.value[(voice * num_efx) + idx] & mask;
15151da177e4SLinus Torvalds if (mix->send_routing[voice][idx] != val) {
15161da177e4SLinus Torvalds mix->send_routing[voice][idx] = val;
15171da177e4SLinus Torvalds change = 1;
15181da177e4SLinus Torvalds }
15191da177e4SLinus Torvalds }
1520a915d604SOswald Buddenhagen if (change && mix->epcm && mix->epcm->voices[0]) {
1521a915d604SOswald Buddenhagen if (!mix->epcm->voices[0]->last) {
15221da177e4SLinus Torvalds update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
15231da177e4SLinus Torvalds &mix->send_routing[1][0]);
1524a915d604SOswald Buddenhagen update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number + 1,
15251da177e4SLinus Torvalds &mix->send_routing[2][0]);
1526a915d604SOswald Buddenhagen } else {
15271da177e4SLinus Torvalds update_emu10k1_fxrt(emu, mix->epcm->voices[0]->number,
15281da177e4SLinus Torvalds &mix->send_routing[0][0]);
15291da177e4SLinus Torvalds }
15301da177e4SLinus Torvalds }
153167192cc0SOswald Buddenhagen spin_unlock_irq(&emu->reg_lock);
15321da177e4SLinus Torvalds return change;
15331da177e4SLinus Torvalds }
15341da177e4SLinus Torvalds
1535f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu10k1_send_routing_control =
15361da177e4SLinus Torvalds {
15371da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
153867ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM,
15391da177e4SLinus Torvalds .name = "EMU10K1 PCM Send Routing",
15401da177e4SLinus Torvalds .count = 32,
15411da177e4SLinus Torvalds .info = snd_emu10k1_send_routing_info,
15421da177e4SLinus Torvalds .get = snd_emu10k1_send_routing_get,
15431da177e4SLinus Torvalds .put = snd_emu10k1_send_routing_put
15441da177e4SLinus Torvalds };
15451da177e4SLinus Torvalds
snd_emu10k1_send_volume_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1546eb4698f3STakashi Iwai static int snd_emu10k1_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
15471da177e4SLinus Torvalds {
1548eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
15491da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
15501da177e4SLinus Torvalds uinfo->count = emu->audigy ? 3*8 : 3*4;
15511da177e4SLinus Torvalds uinfo->value.integer.min = 0;
15521da177e4SLinus Torvalds uinfo->value.integer.max = 255;
15531da177e4SLinus Torvalds return 0;
15541da177e4SLinus Torvalds }
15551da177e4SLinus Torvalds
snd_emu10k1_send_volume_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1556eb4698f3STakashi Iwai static int snd_emu10k1_send_volume_get(struct snd_kcontrol *kcontrol,
1557eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
15581da177e4SLinus Torvalds {
1559eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1560eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix =
1561eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
15621da177e4SLinus Torvalds int idx;
15631da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4;
15641da177e4SLinus Torvalds
15651da177e4SLinus Torvalds for (idx = 0; idx < 3*num_efx; idx++)
15661da177e4SLinus Torvalds ucontrol->value.integer.value[idx] = mix->send_volume[idx/num_efx][idx%num_efx];
15671da177e4SLinus Torvalds return 0;
15681da177e4SLinus Torvalds }
15691da177e4SLinus Torvalds
snd_emu10k1_send_volume_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1570eb4698f3STakashi Iwai static int snd_emu10k1_send_volume_put(struct snd_kcontrol *kcontrol,
1571eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
15721da177e4SLinus Torvalds {
1573eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1574eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix =
1575eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
15761da177e4SLinus Torvalds int change = 0, idx, val;
15771da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4;
15781da177e4SLinus Torvalds
157967192cc0SOswald Buddenhagen spin_lock_irq(&emu->reg_lock);
15801da177e4SLinus Torvalds for (idx = 0; idx < 3*num_efx; idx++) {
15811da177e4SLinus Torvalds val = ucontrol->value.integer.value[idx] & 255;
15821da177e4SLinus Torvalds if (mix->send_volume[idx/num_efx][idx%num_efx] != val) {
15831da177e4SLinus Torvalds mix->send_volume[idx/num_efx][idx%num_efx] = val;
15841da177e4SLinus Torvalds change = 1;
15851da177e4SLinus Torvalds }
15861da177e4SLinus Torvalds }
1587a915d604SOswald Buddenhagen if (change && mix->epcm && mix->epcm->voices[0]) {
1588a915d604SOswald Buddenhagen if (!mix->epcm->voices[0]->last) {
15891da177e4SLinus Torvalds update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
15901da177e4SLinus Torvalds &mix->send_volume[1][0]);
1591a915d604SOswald Buddenhagen update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number + 1,
15921da177e4SLinus Torvalds &mix->send_volume[2][0]);
1593a915d604SOswald Buddenhagen } else {
15941da177e4SLinus Torvalds update_emu10k1_send_volume(emu, mix->epcm->voices[0]->number,
15951da177e4SLinus Torvalds &mix->send_volume[0][0]);
15961da177e4SLinus Torvalds }
15971da177e4SLinus Torvalds }
159867192cc0SOswald Buddenhagen spin_unlock_irq(&emu->reg_lock);
15991da177e4SLinus Torvalds return change;
16001da177e4SLinus Torvalds }
16011da177e4SLinus Torvalds
1602f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu10k1_send_volume_control =
16031da177e4SLinus Torvalds {
16041da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
160567ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM,
16061da177e4SLinus Torvalds .name = "EMU10K1 PCM Send Volume",
16071da177e4SLinus Torvalds .count = 32,
16081da177e4SLinus Torvalds .info = snd_emu10k1_send_volume_info,
16091da177e4SLinus Torvalds .get = snd_emu10k1_send_volume_get,
16101da177e4SLinus Torvalds .put = snd_emu10k1_send_volume_put
16111da177e4SLinus Torvalds };
16121da177e4SLinus Torvalds
snd_emu10k1_attn_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1613eb4698f3STakashi Iwai static int snd_emu10k1_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
16141da177e4SLinus Torvalds {
16151da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
16161da177e4SLinus Torvalds uinfo->count = 3;
16171da177e4SLinus Torvalds uinfo->value.integer.min = 0;
1618bcdbd3b7SOswald Buddenhagen uinfo->value.integer.max = 0x1fffd;
16191da177e4SLinus Torvalds return 0;
16201da177e4SLinus Torvalds }
16211da177e4SLinus Torvalds
snd_emu10k1_attn_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1622eb4698f3STakashi Iwai static int snd_emu10k1_attn_get(struct snd_kcontrol *kcontrol,
1623eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
16241da177e4SLinus Torvalds {
1625eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1626eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix =
1627eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
16281da177e4SLinus Torvalds int idx;
16291da177e4SLinus Torvalds
16301da177e4SLinus Torvalds for (idx = 0; idx < 3; idx++)
1631bcdbd3b7SOswald Buddenhagen ucontrol->value.integer.value[idx] = mix->attn[idx] * 0xffffU / 0x8000U;
16321da177e4SLinus Torvalds return 0;
16331da177e4SLinus Torvalds }
16341da177e4SLinus Torvalds
snd_emu10k1_attn_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1635eb4698f3STakashi Iwai static int snd_emu10k1_attn_put(struct snd_kcontrol *kcontrol,
1636eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
16371da177e4SLinus Torvalds {
1638eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1639eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix =
1640eb4698f3STakashi Iwai &emu->pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
16411da177e4SLinus Torvalds int change = 0, idx, val;
16421da177e4SLinus Torvalds
164367192cc0SOswald Buddenhagen spin_lock_irq(&emu->reg_lock);
16441da177e4SLinus Torvalds for (idx = 0; idx < 3; idx++) {
1645bcdbd3b7SOswald Buddenhagen unsigned uval = ucontrol->value.integer.value[idx] & 0x1ffff;
1646bcdbd3b7SOswald Buddenhagen val = uval * 0x8000U / 0xffffU;
16471da177e4SLinus Torvalds if (mix->attn[idx] != val) {
16481da177e4SLinus Torvalds mix->attn[idx] = val;
16491da177e4SLinus Torvalds change = 1;
16501da177e4SLinus Torvalds }
16511da177e4SLinus Torvalds }
1652a915d604SOswald Buddenhagen if (change && mix->epcm && mix->epcm->voices[0]) {
1653a915d604SOswald Buddenhagen if (!mix->epcm->voices[0]->last) {
16541da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[1]);
1655a915d604SOswald Buddenhagen snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number + 1, mix->attn[2]);
1656a915d604SOswald Buddenhagen } else {
16571da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[0]->number, mix->attn[0]);
16581da177e4SLinus Torvalds }
16591da177e4SLinus Torvalds }
166067192cc0SOswald Buddenhagen spin_unlock_irq(&emu->reg_lock);
16611da177e4SLinus Torvalds return change;
16621da177e4SLinus Torvalds }
16631da177e4SLinus Torvalds
1664f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu10k1_attn_control =
16651da177e4SLinus Torvalds {
16661da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
166767ed4161SClemens Ladisch .iface = SNDRV_CTL_ELEM_IFACE_PCM,
16681da177e4SLinus Torvalds .name = "EMU10K1 PCM Volume",
16691da177e4SLinus Torvalds .count = 32,
16701da177e4SLinus Torvalds .info = snd_emu10k1_attn_info,
16711da177e4SLinus Torvalds .get = snd_emu10k1_attn_get,
16721da177e4SLinus Torvalds .put = snd_emu10k1_attn_put
16731da177e4SLinus Torvalds };
16741da177e4SLinus Torvalds
16751da177e4SLinus Torvalds /* Mutichannel PCM stream controls */
16761da177e4SLinus Torvalds
snd_emu10k1_efx_send_routing_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1677eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_routing_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
16781da177e4SLinus Torvalds {
1679eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
16801da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
16811da177e4SLinus Torvalds uinfo->count = emu->audigy ? 8 : 4;
16821da177e4SLinus Torvalds uinfo->value.integer.min = 0;
16831da177e4SLinus Torvalds uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
16841da177e4SLinus Torvalds return 0;
16851da177e4SLinus Torvalds }
16861da177e4SLinus Torvalds
snd_emu10k1_efx_send_routing_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1687eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_routing_get(struct snd_kcontrol *kcontrol,
1688eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
16891da177e4SLinus Torvalds {
1690eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1691eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix =
1692eb4698f3STakashi Iwai &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
16931da177e4SLinus Torvalds int idx;
16941da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4;
16951da177e4SLinus Torvalds int mask = emu->audigy ? 0x3f : 0x0f;
16961da177e4SLinus Torvalds
16971da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++)
16981da177e4SLinus Torvalds ucontrol->value.integer.value[idx] =
16991da177e4SLinus Torvalds mix->send_routing[0][idx] & mask;
17001da177e4SLinus Torvalds return 0;
17011da177e4SLinus Torvalds }
17021da177e4SLinus Torvalds
snd_emu10k1_efx_send_routing_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1703eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_routing_put(struct snd_kcontrol *kcontrol,
1704eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
17051da177e4SLinus Torvalds {
1706eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
17071da177e4SLinus Torvalds int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1708eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
17091da177e4SLinus Torvalds int change = 0, idx, val;
17101da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4;
17111da177e4SLinus Torvalds int mask = emu->audigy ? 0x3f : 0x0f;
17121da177e4SLinus Torvalds
171367192cc0SOswald Buddenhagen spin_lock_irq(&emu->reg_lock);
17141da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++) {
17151da177e4SLinus Torvalds val = ucontrol->value.integer.value[idx] & mask;
17161da177e4SLinus Torvalds if (mix->send_routing[0][idx] != val) {
17171da177e4SLinus Torvalds mix->send_routing[0][idx] = val;
17181da177e4SLinus Torvalds change = 1;
17191da177e4SLinus Torvalds }
17201da177e4SLinus Torvalds }
17211da177e4SLinus Torvalds
17221da177e4SLinus Torvalds if (change && mix->epcm) {
17231da177e4SLinus Torvalds if (mix->epcm->voices[ch]) {
17241da177e4SLinus Torvalds update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
17251da177e4SLinus Torvalds &mix->send_routing[0][0]);
17261da177e4SLinus Torvalds }
17271da177e4SLinus Torvalds }
172867192cc0SOswald Buddenhagen spin_unlock_irq(&emu->reg_lock);
17291da177e4SLinus Torvalds return change;
17301da177e4SLinus Torvalds }
17311da177e4SLinus Torvalds
1732f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu10k1_efx_send_routing_control =
17331da177e4SLinus Torvalds {
17341da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
17351da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM,
17361da177e4SLinus Torvalds .name = "Multichannel PCM Send Routing",
17371da177e4SLinus Torvalds .count = 16,
17381da177e4SLinus Torvalds .info = snd_emu10k1_efx_send_routing_info,
17391da177e4SLinus Torvalds .get = snd_emu10k1_efx_send_routing_get,
17401da177e4SLinus Torvalds .put = snd_emu10k1_efx_send_routing_put
17411da177e4SLinus Torvalds };
17421da177e4SLinus Torvalds
snd_emu10k1_efx_send_volume_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1743eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
17441da177e4SLinus Torvalds {
1745eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
17461da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
17471da177e4SLinus Torvalds uinfo->count = emu->audigy ? 8 : 4;
17481da177e4SLinus Torvalds uinfo->value.integer.min = 0;
17491da177e4SLinus Torvalds uinfo->value.integer.max = 255;
17501da177e4SLinus Torvalds return 0;
17511da177e4SLinus Torvalds }
17521da177e4SLinus Torvalds
snd_emu10k1_efx_send_volume_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1753eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_volume_get(struct snd_kcontrol *kcontrol,
1754eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
17551da177e4SLinus Torvalds {
1756eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1757eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix =
1758eb4698f3STakashi Iwai &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
17591da177e4SLinus Torvalds int idx;
17601da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4;
17611da177e4SLinus Torvalds
17621da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++)
17631da177e4SLinus Torvalds ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
17641da177e4SLinus Torvalds return 0;
17651da177e4SLinus Torvalds }
17661da177e4SLinus Torvalds
snd_emu10k1_efx_send_volume_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1767eb4698f3STakashi Iwai static int snd_emu10k1_efx_send_volume_put(struct snd_kcontrol *kcontrol,
1768eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
17691da177e4SLinus Torvalds {
1770eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
17711da177e4SLinus Torvalds int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1772eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
17731da177e4SLinus Torvalds int change = 0, idx, val;
17741da177e4SLinus Torvalds int num_efx = emu->audigy ? 8 : 4;
17751da177e4SLinus Torvalds
177667192cc0SOswald Buddenhagen spin_lock_irq(&emu->reg_lock);
17771da177e4SLinus Torvalds for (idx = 0; idx < num_efx; idx++) {
17781da177e4SLinus Torvalds val = ucontrol->value.integer.value[idx] & 255;
17791da177e4SLinus Torvalds if (mix->send_volume[0][idx] != val) {
17801da177e4SLinus Torvalds mix->send_volume[0][idx] = val;
17811da177e4SLinus Torvalds change = 1;
17821da177e4SLinus Torvalds }
17831da177e4SLinus Torvalds }
17841da177e4SLinus Torvalds if (change && mix->epcm) {
17851da177e4SLinus Torvalds if (mix->epcm->voices[ch]) {
17861da177e4SLinus Torvalds update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
17871da177e4SLinus Torvalds &mix->send_volume[0][0]);
17881da177e4SLinus Torvalds }
17891da177e4SLinus Torvalds }
179067192cc0SOswald Buddenhagen spin_unlock_irq(&emu->reg_lock);
17911da177e4SLinus Torvalds return change;
17921da177e4SLinus Torvalds }
17931da177e4SLinus Torvalds
17941da177e4SLinus Torvalds
1795f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu10k1_efx_send_volume_control =
17961da177e4SLinus Torvalds {
17971da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
17981da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM,
17991da177e4SLinus Torvalds .name = "Multichannel PCM Send Volume",
18001da177e4SLinus Torvalds .count = 16,
18011da177e4SLinus Torvalds .info = snd_emu10k1_efx_send_volume_info,
18021da177e4SLinus Torvalds .get = snd_emu10k1_efx_send_volume_get,
18031da177e4SLinus Torvalds .put = snd_emu10k1_efx_send_volume_put
18041da177e4SLinus Torvalds };
18051da177e4SLinus Torvalds
snd_emu10k1_efx_attn_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)1806eb4698f3STakashi Iwai static int snd_emu10k1_efx_attn_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
18071da177e4SLinus Torvalds {
18081da177e4SLinus Torvalds uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
18091da177e4SLinus Torvalds uinfo->count = 1;
18101da177e4SLinus Torvalds uinfo->value.integer.min = 0;
1811bcdbd3b7SOswald Buddenhagen uinfo->value.integer.max = 0x1fffd;
18121da177e4SLinus Torvalds return 0;
18131da177e4SLinus Torvalds }
18141da177e4SLinus Torvalds
snd_emu10k1_efx_attn_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1815eb4698f3STakashi Iwai static int snd_emu10k1_efx_attn_get(struct snd_kcontrol *kcontrol,
1816eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
18171da177e4SLinus Torvalds {
1818eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1819eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix =
1820eb4698f3STakashi Iwai &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
18211da177e4SLinus Torvalds
1822bcdbd3b7SOswald Buddenhagen ucontrol->value.integer.value[0] = mix->attn[0] * 0xffffU / 0x8000U;
18231da177e4SLinus Torvalds return 0;
18241da177e4SLinus Torvalds }
18251da177e4SLinus Torvalds
snd_emu10k1_efx_attn_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1826eb4698f3STakashi Iwai static int snd_emu10k1_efx_attn_put(struct snd_kcontrol *kcontrol,
1827eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
18281da177e4SLinus Torvalds {
1829eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
18301da177e4SLinus Torvalds int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
1831eb4698f3STakashi Iwai struct snd_emu10k1_pcm_mixer *mix = &emu->efx_pcm_mixer[ch];
18321da177e4SLinus Torvalds int change = 0, val;
1833bcdbd3b7SOswald Buddenhagen unsigned uval;
18341da177e4SLinus Torvalds
183567192cc0SOswald Buddenhagen spin_lock_irq(&emu->reg_lock);
1836bcdbd3b7SOswald Buddenhagen uval = ucontrol->value.integer.value[0] & 0x1ffff;
1837bcdbd3b7SOswald Buddenhagen val = uval * 0x8000U / 0xffffU;
18381da177e4SLinus Torvalds if (mix->attn[0] != val) {
18391da177e4SLinus Torvalds mix->attn[0] = val;
18401da177e4SLinus Torvalds change = 1;
18411da177e4SLinus Torvalds }
18421da177e4SLinus Torvalds if (change && mix->epcm) {
18431da177e4SLinus Torvalds if (mix->epcm->voices[ch]) {
18441da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
18451da177e4SLinus Torvalds }
18461da177e4SLinus Torvalds }
184767192cc0SOswald Buddenhagen spin_unlock_irq(&emu->reg_lock);
18481da177e4SLinus Torvalds return change;
18491da177e4SLinus Torvalds }
18501da177e4SLinus Torvalds
1851f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu10k1_efx_attn_control =
18521da177e4SLinus Torvalds {
18531da177e4SLinus Torvalds .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
18541da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_PCM,
18551da177e4SLinus Torvalds .name = "Multichannel PCM Volume",
18561da177e4SLinus Torvalds .count = 16,
18571da177e4SLinus Torvalds .info = snd_emu10k1_efx_attn_info,
18581da177e4SLinus Torvalds .get = snd_emu10k1_efx_attn_get,
18591da177e4SLinus Torvalds .put = snd_emu10k1_efx_attn_put
18601da177e4SLinus Torvalds };
18611da177e4SLinus Torvalds
1862a5ce8890STakashi Iwai #define snd_emu10k1_shared_spdif_info snd_ctl_boolean_mono_info
18631da177e4SLinus Torvalds
snd_emu10k1_shared_spdif_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1864eb4698f3STakashi Iwai static int snd_emu10k1_shared_spdif_get(struct snd_kcontrol *kcontrol,
1865eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
18661da177e4SLinus Torvalds {
1867eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
18681da177e4SLinus Torvalds
18691da177e4SLinus Torvalds if (emu->audigy)
1870a1c87c0bSOswald Buddenhagen ucontrol->value.integer.value[0] = inw(emu->port + A_IOCFG) & A_IOCFG_GPOUT0 ? 1 : 0;
18711da177e4SLinus Torvalds else
18721da177e4SLinus Torvalds ucontrol->value.integer.value[0] = inl(emu->port + HCFG) & HCFG_GPOUT0 ? 1 : 0;
1873d2cd74b1STakashi Iwai if (emu->card_capabilities->invert_shared_spdif)
1874d2cd74b1STakashi Iwai ucontrol->value.integer.value[0] =
1875d2cd74b1STakashi Iwai !ucontrol->value.integer.value[0];
1876d2cd74b1STakashi Iwai
18771da177e4SLinus Torvalds return 0;
18781da177e4SLinus Torvalds }
18791da177e4SLinus Torvalds
snd_emu10k1_shared_spdif_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)1880eb4698f3STakashi Iwai static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
1881eb4698f3STakashi Iwai struct snd_ctl_elem_value *ucontrol)
18821da177e4SLinus Torvalds {
1883eb4698f3STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
1884d2cd74b1STakashi Iwai unsigned int reg, val, sw;
18851da177e4SLinus Torvalds int change = 0;
18861da177e4SLinus Torvalds
1887d2cd74b1STakashi Iwai sw = ucontrol->value.integer.value[0];
1888d2cd74b1STakashi Iwai if (emu->card_capabilities->invert_shared_spdif)
1889d2cd74b1STakashi Iwai sw = !sw;
189067192cc0SOswald Buddenhagen spin_lock_irq(&emu->emu_lock);
1891184c1e2cSJames Courtier-Dutton if ( emu->card_capabilities->i2c_adc) {
1892184c1e2cSJames Courtier-Dutton /* Do nothing for Audigy 2 ZS Notebook */
1893184c1e2cSJames Courtier-Dutton } else if (emu->audigy) {
1894a1c87c0bSOswald Buddenhagen reg = inw(emu->port + A_IOCFG);
1895d2cd74b1STakashi Iwai val = sw ? A_IOCFG_GPOUT0 : 0;
18961da177e4SLinus Torvalds change = (reg & A_IOCFG_GPOUT0) != val;
18971da177e4SLinus Torvalds if (change) {
18981da177e4SLinus Torvalds reg &= ~A_IOCFG_GPOUT0;
18991da177e4SLinus Torvalds reg |= val;
1900a1c87c0bSOswald Buddenhagen outw(reg | val, emu->port + A_IOCFG);
19011da177e4SLinus Torvalds }
19021da177e4SLinus Torvalds }
19031da177e4SLinus Torvalds reg = inl(emu->port + HCFG);
1904d2cd74b1STakashi Iwai val = sw ? HCFG_GPOUT0 : 0;
19051da177e4SLinus Torvalds change |= (reg & HCFG_GPOUT0) != val;
19061da177e4SLinus Torvalds if (change) {
19071da177e4SLinus Torvalds reg &= ~HCFG_GPOUT0;
19081da177e4SLinus Torvalds reg |= val;
19091da177e4SLinus Torvalds outl(reg | val, emu->port + HCFG);
19101da177e4SLinus Torvalds }
191167192cc0SOswald Buddenhagen spin_unlock_irq(&emu->emu_lock);
19121da177e4SLinus Torvalds return change;
19131da177e4SLinus Torvalds }
19141da177e4SLinus Torvalds
1915f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_emu10k1_shared_spdif =
19161da177e4SLinus Torvalds {
19171da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
19181da177e4SLinus Torvalds .name = "SB Live Analog/Digital Output Jack",
19191da177e4SLinus Torvalds .info = snd_emu10k1_shared_spdif_info,
19201da177e4SLinus Torvalds .get = snd_emu10k1_shared_spdif_get,
19211da177e4SLinus Torvalds .put = snd_emu10k1_shared_spdif_put
19221da177e4SLinus Torvalds };
19231da177e4SLinus Torvalds
1924f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_audigy_shared_spdif =
19251da177e4SLinus Torvalds {
19261da177e4SLinus Torvalds .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
19271da177e4SLinus Torvalds .name = "Audigy Analog/Digital Output Jack",
19281da177e4SLinus Torvalds .info = snd_emu10k1_shared_spdif_info,
19291da177e4SLinus Torvalds .get = snd_emu10k1_shared_spdif_get,
19301da177e4SLinus Torvalds .put = snd_emu10k1_shared_spdif_put
19311da177e4SLinus Torvalds };
19321da177e4SLinus Torvalds
193316950e09STakashi Iwai /* workaround for too low volume on Audigy due to 16bit/24bit conversion */
193416950e09STakashi Iwai
193516950e09STakashi Iwai #define snd_audigy_capture_boost_info snd_ctl_boolean_mono_info
193616950e09STakashi Iwai
snd_audigy_capture_boost_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)193716950e09STakashi Iwai static int snd_audigy_capture_boost_get(struct snd_kcontrol *kcontrol,
193816950e09STakashi Iwai struct snd_ctl_elem_value *ucontrol)
193916950e09STakashi Iwai {
194016950e09STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
194116950e09STakashi Iwai unsigned int val;
194216950e09STakashi Iwai
194316950e09STakashi Iwai /* FIXME: better to use a cached version */
194416950e09STakashi Iwai val = snd_ac97_read(emu->ac97, AC97_REC_GAIN);
194516950e09STakashi Iwai ucontrol->value.integer.value[0] = !!val;
194616950e09STakashi Iwai return 0;
194716950e09STakashi Iwai }
194816950e09STakashi Iwai
snd_audigy_capture_boost_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)194916950e09STakashi Iwai static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol,
195016950e09STakashi Iwai struct snd_ctl_elem_value *ucontrol)
195116950e09STakashi Iwai {
195216950e09STakashi Iwai struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
195316950e09STakashi Iwai unsigned int val;
195416950e09STakashi Iwai
195516950e09STakashi Iwai if (ucontrol->value.integer.value[0])
195616950e09STakashi Iwai val = 0x0f0f;
195716950e09STakashi Iwai else
195816950e09STakashi Iwai val = 0;
195916950e09STakashi Iwai return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val);
196016950e09STakashi Iwai }
196116950e09STakashi Iwai
1962f3b827e0SBhumika Goyal static const struct snd_kcontrol_new snd_audigy_capture_boost =
196316950e09STakashi Iwai {
196416950e09STakashi Iwai .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
19652a52feb1SMaciej S. Szmigiero .name = "Mic Extra Boost",
196616950e09STakashi Iwai .info = snd_audigy_capture_boost_info,
196716950e09STakashi Iwai .get = snd_audigy_capture_boost_get,
196816950e09STakashi Iwai .put = snd_audigy_capture_boost_put
196916950e09STakashi Iwai };
197016950e09STakashi Iwai
197116950e09STakashi Iwai
19721da177e4SLinus Torvalds /*
19731da177e4SLinus Torvalds */
snd_emu10k1_mixer_free_ac97(struct snd_ac97 * ac97)1974eb4698f3STakashi Iwai static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
19751da177e4SLinus Torvalds {
1976eb4698f3STakashi Iwai struct snd_emu10k1 *emu = ac97->private_data;
19771da177e4SLinus Torvalds emu->ac97 = NULL;
19781da177e4SLinus Torvalds }
19791da177e4SLinus Torvalds
19801da177e4SLinus Torvalds /*
19811da177e4SLinus Torvalds */
remove_ctl(struct snd_card * card,const char * name)1982eb4698f3STakashi Iwai static int remove_ctl(struct snd_card *card, const char *name)
19831da177e4SLinus Torvalds {
1984eb4698f3STakashi Iwai struct snd_ctl_elem_id id;
19851da177e4SLinus Torvalds memset(&id, 0, sizeof(id));
19861da177e4SLinus Torvalds strcpy(id.name, name);
19871da177e4SLinus Torvalds id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
19881da177e4SLinus Torvalds return snd_ctl_remove_id(card, &id);
19891da177e4SLinus Torvalds }
19901da177e4SLinus Torvalds
rename_ctl(struct snd_card * card,const char * src,const char * dst)1991eb4698f3STakashi Iwai static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
19921da177e4SLinus Torvalds {
1993aa9e9180STakashi Iwai struct snd_kcontrol *kctl = snd_ctl_find_id_mixer(card, src);
19941da177e4SLinus Torvalds if (kctl) {
199536476b81SMaciej S. Szmigiero snd_ctl_rename(card, kctl, dst);
19961da177e4SLinus Torvalds return 0;
19971da177e4SLinus Torvalds }
19981da177e4SLinus Torvalds return -ENOENT;
19991da177e4SLinus Torvalds }
20001da177e4SLinus Torvalds
snd_emu10k1_mixer(struct snd_emu10k1 * emu,int pcm_device,int multi_device)2001e23e7a14SBill Pemberton int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
200267ed4161SClemens Ladisch int pcm_device, int multi_device)
20031da177e4SLinus Torvalds {
2004155e3d3bSOswald Buddenhagen int err;
2005eb4698f3STakashi Iwai struct snd_kcontrol *kctl;
2006eb4698f3STakashi Iwai struct snd_card *card = emu->card;
20076fddce26STakashi Iwai const char * const *c;
20086fddce26STakashi Iwai static const char * const emu10k1_remove_ctls[] = {
20091da177e4SLinus Torvalds /* no AC97 mono, surround, center/lfe */
20101da177e4SLinus Torvalds "Master Mono Playback Switch",
20111da177e4SLinus Torvalds "Master Mono Playback Volume",
20121da177e4SLinus Torvalds "PCM Out Path & Mute",
20131da177e4SLinus Torvalds "Mono Output Select",
20141da177e4SLinus Torvalds "Surround Playback Switch",
20151da177e4SLinus Torvalds "Surround Playback Volume",
20161da177e4SLinus Torvalds "Center Playback Switch",
20171da177e4SLinus Torvalds "Center Playback Volume",
20181da177e4SLinus Torvalds "LFE Playback Switch",
20191da177e4SLinus Torvalds "LFE Playback Volume",
20201da177e4SLinus Torvalds NULL
20211da177e4SLinus Torvalds };
20226fddce26STakashi Iwai static const char * const emu10k1_rename_ctls[] = {
20231da177e4SLinus Torvalds "Surround Digital Playback Volume", "Surround Playback Volume",
20241da177e4SLinus Torvalds "Center Digital Playback Volume", "Center Playback Volume",
20251da177e4SLinus Torvalds "LFE Digital Playback Volume", "LFE Playback Volume",
20261da177e4SLinus Torvalds NULL
20271da177e4SLinus Torvalds };
20286fddce26STakashi Iwai static const char * const audigy_remove_ctls[] = {
20291da177e4SLinus Torvalds /* Master/PCM controls on ac97 of Audigy has no effect */
203021fdddeaSJames Courtier-Dutton /* On the Audigy2 the AC97 playback is piped into
203121fdddeaSJames Courtier-Dutton * the Philips ADC for 24bit capture */
20321da177e4SLinus Torvalds "PCM Playback Switch",
20331da177e4SLinus Torvalds "PCM Playback Volume",
20341da177e4SLinus Torvalds "Master Playback Switch",
20351da177e4SLinus Torvalds "Master Playback Volume",
20361da177e4SLinus Torvalds "PCM Out Path & Mute",
20371da177e4SLinus Torvalds "Mono Output Select",
20381da177e4SLinus Torvalds /* remove unused AC97 capture controls */
20391da177e4SLinus Torvalds "Capture Source",
20401da177e4SLinus Torvalds "Capture Switch",
20411da177e4SLinus Torvalds "Capture Volume",
20421da177e4SLinus Torvalds "Mic Select",
2043274b2000SMaciej S. Szmigiero "Headphone Playback Switch",
2044274b2000SMaciej S. Szmigiero "Headphone Playback Volume",
2045274b2000SMaciej S. Szmigiero "3D Control - Center",
2046274b2000SMaciej S. Szmigiero "3D Control - Depth",
2047274b2000SMaciej S. Szmigiero "3D Control - Switch",
20481da177e4SLinus Torvalds "Video Playback Switch",
20491da177e4SLinus Torvalds "Video Playback Volume",
20501da177e4SLinus Torvalds "Mic Playback Switch",
20511da177e4SLinus Torvalds "Mic Playback Volume",
2052274b2000SMaciej S. Szmigiero "External Amplifier",
20531da177e4SLinus Torvalds NULL
20541da177e4SLinus Torvalds };
20556fddce26STakashi Iwai static const char * const audigy_rename_ctls[] = {
20561da177e4SLinus Torvalds /* use conventional names */
20571da177e4SLinus Torvalds "Wave Playback Volume", "PCM Playback Volume",
20581da177e4SLinus Torvalds /* "Wave Capture Volume", "PCM Capture Volume", */
20591da177e4SLinus Torvalds "Wave Master Playback Volume", "Master Playback Volume",
20601da177e4SLinus Torvalds "AMic Playback Volume", "Mic Playback Volume",
206152051942SMaciej S. Szmigiero "Master Mono Playback Switch", "Phone Output Playback Switch",
206252051942SMaciej S. Szmigiero "Master Mono Playback Volume", "Phone Output Playback Volume",
20631da177e4SLinus Torvalds NULL
20641da177e4SLinus Torvalds };
20656fddce26STakashi Iwai static const char * const audigy_rename_ctls_i2c_adc[] = {
2066184c1e2cSJames Courtier-Dutton //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
2067184c1e2cSJames Courtier-Dutton "Line Capture Volume", "Analog Mix Capture Volume",
2068184c1e2cSJames Courtier-Dutton "Wave Playback Volume", "OLD PCM Playback Volume",
2069184c1e2cSJames Courtier-Dutton "Wave Master Playback Volume", "Master Playback Volume",
2070184c1e2cSJames Courtier-Dutton "AMic Playback Volume", "Old Mic Playback Volume",
2071eb41dab6SJames Courtier-Dutton "CD Capture Volume", "IEC958 Optical Capture Volume",
2072184c1e2cSJames Courtier-Dutton NULL
2073184c1e2cSJames Courtier-Dutton };
20746fddce26STakashi Iwai static const char * const audigy_remove_ctls_i2c_adc[] = {
2075184c1e2cSJames Courtier-Dutton /* On the Audigy2 ZS Notebook
2076184c1e2cSJames Courtier-Dutton * Capture via WM8775 */
2077184c1e2cSJames Courtier-Dutton "Mic Capture Volume",
2078184c1e2cSJames Courtier-Dutton "Analog Mix Capture Volume",
2079184c1e2cSJames Courtier-Dutton "Aux Capture Volume",
2080eb41dab6SJames Courtier-Dutton "IEC958 Optical Capture Volume",
2081184c1e2cSJames Courtier-Dutton NULL
2082184c1e2cSJames Courtier-Dutton };
20836fddce26STakashi Iwai static const char * const audigy_remove_ctls_1361t_adc[] = {
208421fdddeaSJames Courtier-Dutton /* On the Audigy2 the AC97 playback is piped into
208521fdddeaSJames Courtier-Dutton * the Philips ADC for 24bit capture */
208621fdddeaSJames Courtier-Dutton "PCM Playback Switch",
208721fdddeaSJames Courtier-Dutton "PCM Playback Volume",
208821fdddeaSJames Courtier-Dutton "Capture Source",
208921fdddeaSJames Courtier-Dutton "Capture Switch",
209021fdddeaSJames Courtier-Dutton "Capture Volume",
209121fdddeaSJames Courtier-Dutton "Mic Capture Volume",
209221fdddeaSJames Courtier-Dutton "Headphone Playback Switch",
209321fdddeaSJames Courtier-Dutton "Headphone Playback Volume",
209421fdddeaSJames Courtier-Dutton "3D Control - Center",
209521fdddeaSJames Courtier-Dutton "3D Control - Depth",
209621fdddeaSJames Courtier-Dutton "3D Control - Switch",
209721fdddeaSJames Courtier-Dutton "Line2 Playback Volume",
209821fdddeaSJames Courtier-Dutton "Line2 Capture Volume",
209921fdddeaSJames Courtier-Dutton NULL
210021fdddeaSJames Courtier-Dutton };
21016fddce26STakashi Iwai static const char * const audigy_rename_ctls_1361t_adc[] = {
210221fdddeaSJames Courtier-Dutton "Master Playback Switch", "Master Capture Switch",
210321fdddeaSJames Courtier-Dutton "Master Playback Volume", "Master Capture Volume",
210421fdddeaSJames Courtier-Dutton "Wave Master Playback Volume", "Master Playback Volume",
2105d355c82aSJaroslav Kysela "Beep Playback Switch", "Beep Capture Switch",
2106d355c82aSJaroslav Kysela "Beep Playback Volume", "Beep Capture Volume",
210721fdddeaSJames Courtier-Dutton "Phone Playback Switch", "Phone Capture Switch",
210821fdddeaSJames Courtier-Dutton "Phone Playback Volume", "Phone Capture Volume",
210921fdddeaSJames Courtier-Dutton "Mic Playback Switch", "Mic Capture Switch",
211021fdddeaSJames Courtier-Dutton "Mic Playback Volume", "Mic Capture Volume",
211121fdddeaSJames Courtier-Dutton "Line Playback Switch", "Line Capture Switch",
211221fdddeaSJames Courtier-Dutton "Line Playback Volume", "Line Capture Volume",
211321fdddeaSJames Courtier-Dutton "CD Playback Switch", "CD Capture Switch",
211421fdddeaSJames Courtier-Dutton "CD Playback Volume", "CD Capture Volume",
211521fdddeaSJames Courtier-Dutton "Aux Playback Switch", "Aux Capture Switch",
211621fdddeaSJames Courtier-Dutton "Aux Playback Volume", "Aux Capture Volume",
211721fdddeaSJames Courtier-Dutton "Video Playback Switch", "Video Capture Switch",
211821fdddeaSJames Courtier-Dutton "Video Playback Volume", "Video Capture Volume",
211952051942SMaciej S. Szmigiero "Master Mono Playback Switch", "Phone Output Playback Switch",
212052051942SMaciej S. Szmigiero "Master Mono Playback Volume", "Phone Output Playback Volume",
212121fdddeaSJames Courtier-Dutton NULL
212221fdddeaSJames Courtier-Dutton };
21231da177e4SLinus Torvalds
21242b637da5SLee Revell if (emu->card_capabilities->ac97_chip) {
2125eb4698f3STakashi Iwai struct snd_ac97_bus *pbus;
2126eb4698f3STakashi Iwai struct snd_ac97_template ac97;
212751055da5STakashi Iwai static const struct snd_ac97_bus_ops ops = {
21281da177e4SLinus Torvalds .write = snd_emu10k1_ac97_write,
21291da177e4SLinus Torvalds .read = snd_emu10k1_ac97_read,
21301da177e4SLinus Torvalds };
21311da177e4SLinus Torvalds
213212bda107STakashi Iwai err = snd_ac97_bus(emu->card, 0, &ops, NULL, &pbus);
213312bda107STakashi Iwai if (err < 0)
21341da177e4SLinus Torvalds return err;
21351da177e4SLinus Torvalds pbus->no_vra = 1; /* we don't need VRA */
21361da177e4SLinus Torvalds
21371da177e4SLinus Torvalds memset(&ac97, 0, sizeof(ac97));
21381da177e4SLinus Torvalds ac97.private_data = emu;
21391da177e4SLinus Torvalds ac97.private_free = snd_emu10k1_mixer_free_ac97;
21401da177e4SLinus Torvalds ac97.scaps = AC97_SCAP_NO_SPDIF;
214112bda107STakashi Iwai err = snd_ac97_mixer(pbus, &ac97, &emu->ac97);
214212bda107STakashi Iwai if (err < 0) {
2143b1508693STakashi Iwai if (emu->card_capabilities->ac97_chip == 1)
21441da177e4SLinus Torvalds return err;
21456f002b02STakashi Iwai dev_info(emu->card->dev,
21466f002b02STakashi Iwai "AC97 is optional on this board\n");
21476f002b02STakashi Iwai dev_info(emu->card->dev,
21486f002b02STakashi Iwai "Proceeding without ac97 mixers...\n");
2149b1508693STakashi Iwai snd_device_free(emu->card, pbus);
2150b1508693STakashi Iwai goto no_ac97; /* FIXME: get rid of ugly gotos.. */
2151b1508693STakashi Iwai }
21521da177e4SLinus Torvalds if (emu->audigy) {
21531da177e4SLinus Torvalds /* set master volume to 0 dB */
21544d7d7596STakashi Iwai snd_ac97_write_cache(emu->ac97, AC97_MASTER, 0x0000);
21551da177e4SLinus Torvalds /* set capture source to mic */
21564d7d7596STakashi Iwai snd_ac97_write_cache(emu->ac97, AC97_REC_SEL, 0x0000);
215752051942SMaciej S. Szmigiero /* set mono output (TAD) to mic */
215852051942SMaciej S. Szmigiero snd_ac97_update_bits(emu->ac97, AC97_GENERAL_PURPOSE,
215952051942SMaciej S. Szmigiero 0x0200, 0x0200);
216021fdddeaSJames Courtier-Dutton if (emu->card_capabilities->adc_1361t)
216121fdddeaSJames Courtier-Dutton c = audigy_remove_ctls_1361t_adc;
216221fdddeaSJames Courtier-Dutton else
21631da177e4SLinus Torvalds c = audigy_remove_ctls;
21641da177e4SLinus Torvalds } else {
21651da177e4SLinus Torvalds /*
21661da177e4SLinus Torvalds * Credits for cards based on STAC9758:
21671da177e4SLinus Torvalds * James Courtier-Dutton <James@superbug.demon.co.uk>
21681da177e4SLinus Torvalds * Voluspa <voluspa@comhem.se>
21691da177e4SLinus Torvalds */
21701da177e4SLinus Torvalds if (emu->ac97->id == AC97_ID_STAC9758) {
21711da177e4SLinus Torvalds emu->rear_ac97 = 1;
21721da177e4SLinus Torvalds snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
21732594d960SRolf Stefan Wilke snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
2174b6a48404SRaymond Yau remove_ctl(card,"Front Playback Volume");
2175b6a48404SRaymond Yau remove_ctl(card,"Front Playback Switch");
21761da177e4SLinus Torvalds }
21771da177e4SLinus Torvalds /* remove unused AC97 controls */
21784d7d7596STakashi Iwai snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
21794d7d7596STakashi Iwai snd_ac97_write_cache(emu->ac97, AC97_CENTER_LFE_MASTER, 0x0202);
21801da177e4SLinus Torvalds c = emu10k1_remove_ctls;
21811da177e4SLinus Torvalds }
21821da177e4SLinus Torvalds for (; *c; c++)
21831da177e4SLinus Torvalds remove_ctl(card, *c);
2184184c1e2cSJames Courtier-Dutton } else if (emu->card_capabilities->i2c_adc) {
2185184c1e2cSJames Courtier-Dutton c = audigy_remove_ctls_i2c_adc;
2186184c1e2cSJames Courtier-Dutton for (; *c; c++)
2187184c1e2cSJames Courtier-Dutton remove_ctl(card, *c);
21881da177e4SLinus Torvalds } else {
2189f12aa40cSTakashi Iwai no_ac97:
21902b637da5SLee Revell if (emu->card_capabilities->ecard)
21911da177e4SLinus Torvalds strcpy(emu->card->mixername, "EMU APS");
21921da177e4SLinus Torvalds else if (emu->audigy)
21931da177e4SLinus Torvalds strcpy(emu->card->mixername, "SB Audigy");
21941da177e4SLinus Torvalds else
21951da177e4SLinus Torvalds strcpy(emu->card->mixername, "Emu10k1");
21961da177e4SLinus Torvalds }
21971da177e4SLinus Torvalds
21981da177e4SLinus Torvalds if (emu->audigy)
219921fdddeaSJames Courtier-Dutton if (emu->card_capabilities->adc_1361t)
220021fdddeaSJames Courtier-Dutton c = audigy_rename_ctls_1361t_adc;
2201184c1e2cSJames Courtier-Dutton else if (emu->card_capabilities->i2c_adc)
2202184c1e2cSJames Courtier-Dutton c = audigy_rename_ctls_i2c_adc;
220321fdddeaSJames Courtier-Dutton else
22041da177e4SLinus Torvalds c = audigy_rename_ctls;
22051da177e4SLinus Torvalds else
22061da177e4SLinus Torvalds c = emu10k1_rename_ctls;
22071da177e4SLinus Torvalds for (; *c; c += 2)
22081da177e4SLinus Torvalds rename_ctl(card, c[0], c[1]);
220921fdddeaSJames Courtier-Dutton
2210e217b960SRaymond Yau if (emu->card_capabilities->subsystem == 0x80401102) { /* SB Live! Platinum CT4760P */
2211e217b960SRaymond Yau remove_ctl(card, "Center Playback Volume");
2212e217b960SRaymond Yau remove_ctl(card, "LFE Playback Volume");
2213e217b960SRaymond Yau remove_ctl(card, "Wave Center Playback Volume");
2214e217b960SRaymond Yau remove_ctl(card, "Wave LFE Playback Volume");
2215e217b960SRaymond Yau }
2216e3b9bc0eSJames Courtier-Dutton if (emu->card_capabilities->subsystem == 0x20071102) { /* Audigy 4 Pro */
2217e3b9bc0eSJames Courtier-Dutton rename_ctl(card, "Line2 Capture Volume", "Line1/Mic Capture Volume");
2218e3b9bc0eSJames Courtier-Dutton rename_ctl(card, "Analog Mix Capture Volume", "Line2 Capture Volume");
2219e3b9bc0eSJames Courtier-Dutton rename_ctl(card, "Aux2 Capture Volume", "Line3 Capture Volume");
2220e3b9bc0eSJames Courtier-Dutton rename_ctl(card, "Mic Capture Volume", "Unknown1 Capture Volume");
2221e3b9bc0eSJames Courtier-Dutton }
222212bda107STakashi Iwai kctl = emu->ctl_send_routing = snd_ctl_new1(&snd_emu10k1_send_routing_control, emu);
222312bda107STakashi Iwai if (!kctl)
22241da177e4SLinus Torvalds return -ENOMEM;
222567ed4161SClemens Ladisch kctl->id.device = pcm_device;
222612bda107STakashi Iwai err = snd_ctl_add(card, kctl);
222712bda107STakashi Iwai if (err)
22281da177e4SLinus Torvalds return err;
222912bda107STakashi Iwai kctl = emu->ctl_send_volume = snd_ctl_new1(&snd_emu10k1_send_volume_control, emu);
223012bda107STakashi Iwai if (!kctl)
22311da177e4SLinus Torvalds return -ENOMEM;
223267ed4161SClemens Ladisch kctl->id.device = pcm_device;
223312bda107STakashi Iwai err = snd_ctl_add(card, kctl);
223412bda107STakashi Iwai if (err)
22351da177e4SLinus Torvalds return err;
223612bda107STakashi Iwai kctl = emu->ctl_attn = snd_ctl_new1(&snd_emu10k1_attn_control, emu);
223712bda107STakashi Iwai if (!kctl)
22381da177e4SLinus Torvalds return -ENOMEM;
223967ed4161SClemens Ladisch kctl->id.device = pcm_device;
224012bda107STakashi Iwai err = snd_ctl_add(card, kctl);
224112bda107STakashi Iwai if (err)
22421da177e4SLinus Torvalds return err;
22431da177e4SLinus Torvalds
224412bda107STakashi Iwai kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu);
224512bda107STakashi Iwai if (!kctl)
22461da177e4SLinus Torvalds return -ENOMEM;
224767ed4161SClemens Ladisch kctl->id.device = multi_device;
224812bda107STakashi Iwai err = snd_ctl_add(card, kctl);
224912bda107STakashi Iwai if (err)
22501da177e4SLinus Torvalds return err;
22511da177e4SLinus Torvalds
225212bda107STakashi Iwai kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu);
225312bda107STakashi Iwai if (!kctl)
22541da177e4SLinus Torvalds return -ENOMEM;
225567ed4161SClemens Ladisch kctl->id.device = multi_device;
225612bda107STakashi Iwai err = snd_ctl_add(card, kctl);
225712bda107STakashi Iwai if (err)
22581da177e4SLinus Torvalds return err;
22591da177e4SLinus Torvalds
226012bda107STakashi Iwai kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu);
226112bda107STakashi Iwai if (!kctl)
22621da177e4SLinus Torvalds return -ENOMEM;
226367ed4161SClemens Ladisch kctl->id.device = multi_device;
226412bda107STakashi Iwai err = snd_ctl_add(card, kctl);
226512bda107STakashi Iwai if (err)
22661da177e4SLinus Torvalds return err;
22671da177e4SLinus Torvalds
2268a8661af5SOswald Buddenhagen if (!emu->card_capabilities->ecard && !emu->card_capabilities->emu_model) {
22691da177e4SLinus Torvalds /* sb live! and audigy */
227012bda107STakashi Iwai kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu);
227112bda107STakashi Iwai if (!kctl)
22721da177e4SLinus Torvalds return -ENOMEM;
22735549d549SClemens Ladisch if (!emu->audigy)
22745549d549SClemens Ladisch kctl->id.device = emu->pcm_efx->device;
227512bda107STakashi Iwai err = snd_ctl_add(card, kctl);
227612bda107STakashi Iwai if (err)
22771da177e4SLinus Torvalds return err;
227812bda107STakashi Iwai kctl = snd_ctl_new1(&snd_emu10k1_spdif_control, emu);
227912bda107STakashi Iwai if (!kctl)
22801da177e4SLinus Torvalds return -ENOMEM;
22815549d549SClemens Ladisch if (!emu->audigy)
22825549d549SClemens Ladisch kctl->id.device = emu->pcm_efx->device;
228312bda107STakashi Iwai err = snd_ctl_add(card, kctl);
228412bda107STakashi Iwai if (err)
22851da177e4SLinus Torvalds return err;
22861da177e4SLinus Torvalds }
22871da177e4SLinus Torvalds
2288190d2c46SJames Courtier-Dutton if (emu->card_capabilities->emu_model) {
228919b99fbaSJames Courtier-Dutton ; /* Disable the snd_audigy_spdif_shared_spdif */
229019b99fbaSJames Courtier-Dutton } else if (emu->audigy) {
229112bda107STakashi Iwai kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu);
229212bda107STakashi Iwai if (!kctl)
22931da177e4SLinus Torvalds return -ENOMEM;
229412bda107STakashi Iwai err = snd_ctl_add(card, kctl);
229512bda107STakashi Iwai if (err)
22961da177e4SLinus Torvalds return err;
2297001f7589SJames Courtier-Dutton #if 0
229812bda107STakashi Iwai kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu);
229912bda107STakashi Iwai if (!kctl)
23001da177e4SLinus Torvalds return -ENOMEM;
230112bda107STakashi Iwai err = snd_ctl_add(card, kctl);
230212bda107STakashi Iwai if (err)
23031da177e4SLinus Torvalds return err;
2304001f7589SJames Courtier-Dutton #endif
23052b637da5SLee Revell } else if (! emu->card_capabilities->ecard) {
23061da177e4SLinus Torvalds /* sb live! */
230712bda107STakashi Iwai kctl = snd_ctl_new1(&snd_emu10k1_shared_spdif, emu);
230812bda107STakashi Iwai if (!kctl)
23091da177e4SLinus Torvalds return -ENOMEM;
231012bda107STakashi Iwai err = snd_ctl_add(card, kctl);
231112bda107STakashi Iwai if (err)
23121da177e4SLinus Torvalds return err;
23131da177e4SLinus Torvalds }
23142b637da5SLee Revell if (emu->card_capabilities->ca0151_chip) { /* P16V */
231512bda107STakashi Iwai err = snd_p16v_mixer(emu);
231612bda107STakashi Iwai if (err)
23171da177e4SLinus Torvalds return err;
23181da177e4SLinus Torvalds }
23191da177e4SLinus Torvalds
23201fc710f0SOswald Buddenhagen if (emu->card_capabilities->emu_model) {
23211fc710f0SOswald Buddenhagen unsigned i, emu_idx = emu1010_idx(emu);
23221fc710f0SOswald Buddenhagen const struct snd_emu1010_routing_info *emu_ri =
23231fc710f0SOswald Buddenhagen &emu1010_routing_info[emu_idx];
232497f1582eSOswald Buddenhagen const struct snd_emu1010_pads_info *emu_pi = &emu1010_pads_info[emu_idx];
23251fc710f0SOswald Buddenhagen
23261fc710f0SOswald Buddenhagen for (i = 0; i < emu_ri->n_ins; i++)
23271fc710f0SOswald Buddenhagen emu->emu1010.input_source[i] =
23281fc710f0SOswald Buddenhagen emu1010_map_source(emu_ri, emu_ri->in_dflts[i]);
23291fc710f0SOswald Buddenhagen for (i = 0; i < emu_ri->n_outs; i++)
23301fc710f0SOswald Buddenhagen emu->emu1010.output_source[i] =
23311fc710f0SOswald Buddenhagen emu1010_map_source(emu_ri, emu_ri->out_dflts[i]);
2332*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_lock(emu);
23331fc710f0SOswald Buddenhagen snd_emu1010_apply_sources(emu);
2334*2d3f4810SOswald Buddenhagen snd_emu1010_fpga_unlock(emu);
23351fc710f0SOswald Buddenhagen
2336c960b012SOswald Buddenhagen kctl = emu->ctl_clock_source = snd_ctl_new1(&snd_emu1010_clock_source, emu);
2337c960b012SOswald Buddenhagen err = snd_ctl_add(card, kctl);
233813598862SOswald Buddenhagen if (err < 0)
233913598862SOswald Buddenhagen return err;
234013598862SOswald Buddenhagen err = snd_ctl_add(card,
234113598862SOswald Buddenhagen snd_ctl_new1(&snd_emu1010_clock_fallback, emu));
23421c02e366SCtirad Fertr if (err < 0)
23431c02e366SCtirad Fertr return err;
234497f1582eSOswald Buddenhagen
234597f1582eSOswald Buddenhagen err = add_ctls(emu, &emu1010_adc_pads_ctl,
234697f1582eSOswald Buddenhagen emu_pi->adc_ctls, emu_pi->n_adc_ctls);
234797f1582eSOswald Buddenhagen if (err < 0)
234897f1582eSOswald Buddenhagen return err;
234997f1582eSOswald Buddenhagen err = add_ctls(emu, &emu1010_dac_pads_ctl,
235097f1582eSOswald Buddenhagen emu_pi->dac_ctls, emu_pi->n_dac_ctls);
235197f1582eSOswald Buddenhagen if (err < 0)
235297f1582eSOswald Buddenhagen return err;
235397f1582eSOswald Buddenhagen
23546f3609f8SOswald Buddenhagen if (!emu->card_capabilities->no_adat) {
235599dcab46SMichael Gernoth err = snd_ctl_add(card,
235699dcab46SMichael Gernoth snd_ctl_new1(&snd_emu1010_optical_out, emu));
235799dcab46SMichael Gernoth if (err < 0)
235899dcab46SMichael Gernoth return err;
235999dcab46SMichael Gernoth err = snd_ctl_add(card,
236099dcab46SMichael Gernoth snd_ctl_new1(&snd_emu1010_optical_in, emu));
236199dcab46SMichael Gernoth if (err < 0)
236299dcab46SMichael Gernoth return err;
23636f3609f8SOswald Buddenhagen }
23641c02e366SCtirad Fertr
236597f1582eSOswald Buddenhagen err = add_emu1010_source_mixers(emu);
236699dcab46SMichael Gernoth if (err < 0)
236799dcab46SMichael Gernoth return err;
23689f4bd5ddSJames Courtier-Dutton }
23699f4bd5ddSJames Courtier-Dutton
2370184c1e2cSJames Courtier-Dutton if ( emu->card_capabilities->i2c_adc) {
2371184c1e2cSJames Courtier-Dutton err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
2372184c1e2cSJames Courtier-Dutton if (err < 0)
2373184c1e2cSJames Courtier-Dutton return err;
2374184c1e2cSJames Courtier-Dutton
2375536438f1SOswald Buddenhagen err = add_ctls(emu, &i2c_volume_ctl,
2376536438f1SOswald Buddenhagen snd_audigy_i2c_volume_ctls,
2377536438f1SOswald Buddenhagen ARRAY_SIZE(snd_audigy_i2c_volume_ctls));
2378184c1e2cSJames Courtier-Dutton if (err < 0)
2379184c1e2cSJames Courtier-Dutton return err;
2380184c1e2cSJames Courtier-Dutton }
2381184c1e2cSJames Courtier-Dutton
238216950e09STakashi Iwai if (emu->card_capabilities->ac97_chip && emu->audigy) {
238316950e09STakashi Iwai err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_capture_boost,
238416950e09STakashi Iwai emu));
238516950e09STakashi Iwai if (err < 0)
238616950e09STakashi Iwai return err;
238716950e09STakashi Iwai }
238816950e09STakashi Iwai
23891da177e4SLinus Torvalds return 0;
23901da177e4SLinus Torvalds }
2391