blob: 2f7a03103c91f304a68f686405b88e51222e46ce [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Creative Labs, Inc.
4 * Routines for effect processor FX8010
5 *
6 * BUGS:
7 * --
8 *
9 * TODO:
10 * --
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
26 */
27
28#include <sound/driver.h>
29#include <linux/pci.h>
30#include <linux/delay.h>
31#include <linux/slab.h>
32#include <linux/init.h>
33#include <sound/core.h>
34#include <sound/emu10k1.h>
35
36#if 0 /* for testing purposes - digital out -> capture */
37#define EMU10K1_CAPTURE_DIGITAL_OUT
38#endif
39#if 0 /* for testing purposes - set S/PDIF to AC3 output */
40#define EMU10K1_SET_AC3_IEC958
41#endif
42#if 0 /* for testing purposes - feed the front signal to Center/LFE outputs */
43#define EMU10K1_CENTER_LFE_FROM_FRONT
44#endif
45
46/*
47 * Tables
48 */
49
50static char *fxbuses[16] = {
51 /* 0x00 */ "PCM Left",
52 /* 0x01 */ "PCM Right",
53 /* 0x02 */ "PCM Surround Left",
54 /* 0x03 */ "PCM Surround Right",
55 /* 0x04 */ "MIDI Left",
56 /* 0x05 */ "MIDI Right",
57 /* 0x06 */ "Center",
58 /* 0x07 */ "LFE",
59 /* 0x08 */ NULL,
60 /* 0x09 */ NULL,
61 /* 0x0a */ NULL,
62 /* 0x0b */ NULL,
63 /* 0x0c */ "MIDI Reverb",
64 /* 0x0d */ "MIDI Chorus",
65 /* 0x0e */ NULL,
66 /* 0x0f */ NULL
67};
68
69static char *creative_ins[16] = {
70 /* 0x00 */ "AC97 Left",
71 /* 0x01 */ "AC97 Right",
72 /* 0x02 */ "TTL IEC958 Left",
73 /* 0x03 */ "TTL IEC958 Right",
74 /* 0x04 */ "Zoom Video Left",
75 /* 0x05 */ "Zoom Video Right",
76 /* 0x06 */ "Optical IEC958 Left",
77 /* 0x07 */ "Optical IEC958 Right",
78 /* 0x08 */ "Line/Mic 1 Left",
79 /* 0x09 */ "Line/Mic 1 Right",
80 /* 0x0a */ "Coaxial IEC958 Left",
81 /* 0x0b */ "Coaxial IEC958 Right",
82 /* 0x0c */ "Line/Mic 2 Left",
83 /* 0x0d */ "Line/Mic 2 Right",
84 /* 0x0e */ NULL,
85 /* 0x0f */ NULL
86};
87
88static char *audigy_ins[16] = {
89 /* 0x00 */ "AC97 Left",
90 /* 0x01 */ "AC97 Right",
91 /* 0x02 */ "Audigy CD Left",
92 /* 0x03 */ "Audigy CD Right",
93 /* 0x04 */ "Optical IEC958 Left",
94 /* 0x05 */ "Optical IEC958 Right",
95 /* 0x06 */ NULL,
96 /* 0x07 */ NULL,
97 /* 0x08 */ "Line/Mic 2 Left",
98 /* 0x09 */ "Line/Mic 2 Right",
99 /* 0x0a */ "SPDIF Left",
100 /* 0x0b */ "SPDIF Right",
101 /* 0x0c */ "Aux2 Left",
102 /* 0x0d */ "Aux2 Right",
103 /* 0x0e */ NULL,
104 /* 0x0f */ NULL
105};
106
107static char *creative_outs[32] = {
108 /* 0x00 */ "AC97 Left",
109 /* 0x01 */ "AC97 Right",
110 /* 0x02 */ "Optical IEC958 Left",
111 /* 0x03 */ "Optical IEC958 Right",
112 /* 0x04 */ "Center",
113 /* 0x05 */ "LFE",
114 /* 0x06 */ "Headphone Left",
115 /* 0x07 */ "Headphone Right",
116 /* 0x08 */ "Surround Left",
117 /* 0x09 */ "Surround Right",
118 /* 0x0a */ "PCM Capture Left",
119 /* 0x0b */ "PCM Capture Right",
120 /* 0x0c */ "MIC Capture",
121 /* 0x0d */ "AC97 Surround Left",
122 /* 0x0e */ "AC97 Surround Right",
123 /* 0x0f */ NULL,
124 /* 0x10 */ NULL,
125 /* 0x11 */ "Analog Center",
126 /* 0x12 */ "Analog LFE",
127 /* 0x13 */ NULL,
128 /* 0x14 */ NULL,
129 /* 0x15 */ NULL,
130 /* 0x16 */ NULL,
131 /* 0x17 */ NULL,
132 /* 0x18 */ NULL,
133 /* 0x19 */ NULL,
134 /* 0x1a */ NULL,
135 /* 0x1b */ NULL,
136 /* 0x1c */ NULL,
137 /* 0x1d */ NULL,
138 /* 0x1e */ NULL,
139 /* 0x1f */ NULL,
140};
141
142static char *audigy_outs[32] = {
143 /* 0x00 */ "Digital Front Left",
144 /* 0x01 */ "Digital Front Right",
145 /* 0x02 */ "Digital Center",
146 /* 0x03 */ "Digital LEF",
147 /* 0x04 */ "Headphone Left",
148 /* 0x05 */ "Headphone Right",
149 /* 0x06 */ "Digital Rear Left",
150 /* 0x07 */ "Digital Rear Right",
151 /* 0x08 */ "Front Left",
152 /* 0x09 */ "Front Right",
153 /* 0x0a */ "Center",
154 /* 0x0b */ "LFE",
155 /* 0x0c */ NULL,
156 /* 0x0d */ NULL,
157 /* 0x0e */ "Rear Left",
158 /* 0x0f */ "Rear Right",
159 /* 0x10 */ "AC97 Front Left",
160 /* 0x11 */ "AC97 Front Right",
161 /* 0x12 */ "ADC Caputre Left",
162 /* 0x13 */ "ADC Capture Right",
163 /* 0x14 */ NULL,
164 /* 0x15 */ NULL,
165 /* 0x16 */ NULL,
166 /* 0x17 */ NULL,
167 /* 0x18 */ NULL,
168 /* 0x19 */ NULL,
169 /* 0x1a */ NULL,
170 /* 0x1b */ NULL,
171 /* 0x1c */ NULL,
172 /* 0x1d */ NULL,
173 /* 0x1e */ NULL,
174 /* 0x1f */ NULL,
175};
176
177static const u32 bass_table[41][5] = {
178 { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 },
179 { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d },
180 { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee },
181 { 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c },
182 { 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b },
183 { 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 },
184 { 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f },
185 { 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 },
186 { 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 },
187 { 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 },
188 { 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 },
189 { 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be },
190 { 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b },
191 { 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c },
192 { 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b },
193 { 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 },
194 { 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a },
195 { 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 },
196 { 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 },
197 { 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e },
198 { 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee },
199 { 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 },
200 { 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 },
201 { 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 },
202 { 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 },
203 { 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e },
204 { 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 },
205 { 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 },
206 { 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 },
207 { 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 },
208 { 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 },
209 { 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca },
210 { 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 },
211 { 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 },
212 { 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 },
213 { 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 },
214 { 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a },
215 { 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f },
216 { 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 },
217 { 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 },
218 { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 }
219};
220
221static const u32 treble_table[41][5] = {
222 { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 },
223 { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 },
224 { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 },
225 { 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca },
226 { 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 },
227 { 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 },
228 { 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 },
229 { 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 },
230 { 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 },
231 { 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df },
232 { 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff },
233 { 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 },
234 { 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c },
235 { 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 },
236 { 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 },
237 { 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 },
238 { 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 },
239 { 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d },
240 { 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 },
241 { 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 },
242 { 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f },
243 { 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb },
244 { 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 },
245 { 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 },
246 { 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd },
247 { 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 },
248 { 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad },
249 { 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 },
250 { 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 },
251 { 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c },
252 { 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 },
253 { 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 },
254 { 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 },
255 { 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 },
256 { 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 },
257 { 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 },
258 { 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d },
259 { 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b },
260 { 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 },
261 { 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd },
262 { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 }
263};
264
265static const u32 db_table[101] = {
266 0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540,
267 0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8,
268 0x0207567a, 0x021fd03d, 0x0239714c, 0x02544792, 0x027061a1,
269 0x028dcebb, 0x02ac9edc, 0x02cce2bf, 0x02eeabe8, 0x03120cb0,
270 0x0337184e, 0x035de2df, 0x03868173, 0x03b10a18, 0x03dd93e9,
271 0x040c3713, 0x043d0cea, 0x04702ff3, 0x04a5bbf2, 0x04ddcdfb,
272 0x0518847f, 0x0555ff62, 0x05966005, 0x05d9c95d, 0x06206005,
273 0x066a4a52, 0x06b7b067, 0x0708bc4c, 0x075d9a01, 0x07b6779d,
274 0x08138561, 0x0874f5d5, 0x08dafde1, 0x0945d4ed, 0x09b5b4fd,
275 0x0a2adad1, 0x0aa58605, 0x0b25f936, 0x0bac7a24, 0x0c3951d8,
276 0x0ccccccc, 0x0d673b17, 0x0e08f093, 0x0eb24510, 0x0f639481,
277 0x101d3f2d, 0x10dfa9e6, 0x11ab3e3f, 0x12806ac3, 0x135fa333,
278 0x144960c5, 0x153e2266, 0x163e6cfe, 0x174acbb7, 0x1863d04d,
279 0x198a1357, 0x1abe349f, 0x1c00db77, 0x1d52b712, 0x1eb47ee6,
280 0x2026f30f, 0x21aadcb6, 0x23410e7e, 0x24ea64f9, 0x26a7c71d,
281 0x287a26c4, 0x2a62812c, 0x2c61df84, 0x2e795779, 0x30aa0bcf,
282 0x32f52cfe, 0x355bf9d8, 0x37dfc033, 0x3a81dda4, 0x3d43c038,
283 0x4026e73c, 0x432ce40f, 0x46575af8, 0x49a8040f, 0x4d20ac2a,
284 0x50c335d3, 0x54919a57, 0x588dead1, 0x5cba514a, 0x611911ea,
285 0x65ac8c2f, 0x6a773c39, 0x6f7bbc23, 0x74bcc56c, 0x7a3d3272,
286 0x7fffffff,
287};
288
289static const u32 onoff_table[2] = {
290 0x00000000, 0x00000001
291};
292
293/*
294 */
295
296static inline mm_segment_t snd_enter_user(void)
297{
298 mm_segment_t fs = get_fs();
299 set_fs(get_ds());
300 return fs;
301}
302
303static inline void snd_leave_user(mm_segment_t fs)
304{
305 set_fs(fs);
306}
307
308/*
309 * controls
310 */
311
312static int snd_emu10k1_gpr_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
313{
314 snd_emu10k1_fx8010_ctl_t *ctl = (snd_emu10k1_fx8010_ctl_t *)kcontrol->private_value;
315
316 if (ctl->min == 0 && ctl->max == 1)
317 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
318 else
319 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
320 uinfo->count = ctl->vcount;
321 uinfo->value.integer.min = ctl->min;
322 uinfo->value.integer.max = ctl->max;
323 return 0;
324}
325
326static int snd_emu10k1_gpr_ctl_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
327{
328 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
329 snd_emu10k1_fx8010_ctl_t *ctl = (snd_emu10k1_fx8010_ctl_t *)kcontrol->private_value;
330 unsigned long flags;
331 unsigned int i;
332
333 spin_lock_irqsave(&emu->reg_lock, flags);
334 for (i = 0; i < ctl->vcount; i++)
335 ucontrol->value.integer.value[i] = ctl->value[i];
336 spin_unlock_irqrestore(&emu->reg_lock, flags);
337 return 0;
338}
339
340static int snd_emu10k1_gpr_ctl_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
341{
342 emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
343 snd_emu10k1_fx8010_ctl_t *ctl = (snd_emu10k1_fx8010_ctl_t *)kcontrol->private_value;
344 unsigned long flags;
345 unsigned int nval, val;
346 unsigned int i, j;
347 int change = 0;
348
349 spin_lock_irqsave(&emu->reg_lock, flags);
350 for (i = 0; i < ctl->vcount; i++) {
351 nval = ucontrol->value.integer.value[i];
352 if (nval < ctl->min)
353 nval = ctl->min;
354 if (nval > ctl->max)
355 nval = ctl->max;
356 if (nval != ctl->value[i])
357 change = 1;
358 val = ctl->value[i] = nval;
359 switch (ctl->translation) {
360 case EMU10K1_GPR_TRANSLATION_NONE:
361 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, val);
362 break;
363 case EMU10K1_GPR_TRANSLATION_TABLE100:
364 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]);
365 break;
366 case EMU10K1_GPR_TRANSLATION_BASS:
367 snd_runtime_check((ctl->count % 5) == 0 && (ctl->count / 5) == ctl->vcount, change = -EIO; goto __error);
368 for (j = 0; j < 5; j++)
369 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]);
370 break;
371 case EMU10K1_GPR_TRANSLATION_TREBLE:
372 snd_runtime_check((ctl->count % 5) == 0 && (ctl->count / 5) == ctl->vcount, change = -EIO; goto __error);
373 for (j = 0; j < 5; j++)
374 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]);
375 break;
376 case EMU10K1_GPR_TRANSLATION_ONOFF:
377 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, onoff_table[val]);
378 break;
379 }
380 }
381 __error:
382 spin_unlock_irqrestore(&emu->reg_lock, flags);
383 return change;
384}
385
386/*
387 * Interrupt handler
388 */
389
390static void snd_emu10k1_fx8010_interrupt(emu10k1_t *emu)
391{
392 snd_emu10k1_fx8010_irq_t *irq, *nirq;
393
394 irq = emu->fx8010.irq_handlers;
395 while (irq) {
396 nirq = irq->next; /* irq ptr can be removed from list */
397 if (snd_emu10k1_ptr_read(emu, emu->gpr_base + irq->gpr_running, 0) & 0xffff0000) {
398 if (irq->handler)
399 irq->handler(emu, irq->private_data);
400 snd_emu10k1_ptr_write(emu, emu->gpr_base + irq->gpr_running, 0, 1);
401 }
402 irq = nirq;
403 }
404}
405
406int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
407 snd_fx8010_irq_handler_t *handler,
408 unsigned char gpr_running,
409 void *private_data,
410 snd_emu10k1_fx8010_irq_t **r_irq)
411{
412 snd_emu10k1_fx8010_irq_t *irq;
413 unsigned long flags;
414
415 snd_runtime_check(emu, return -EINVAL);
416 snd_runtime_check(handler, return -EINVAL);
417 irq = kmalloc(sizeof(*irq), GFP_ATOMIC);
418 if (irq == NULL)
419 return -ENOMEM;
420 irq->handler = handler;
421 irq->gpr_running = gpr_running;
422 irq->private_data = private_data;
423 irq->next = NULL;
424 spin_lock_irqsave(&emu->fx8010.irq_lock, flags);
425 if (emu->fx8010.irq_handlers == NULL) {
426 emu->fx8010.irq_handlers = irq;
427 emu->dsp_interrupt = snd_emu10k1_fx8010_interrupt;
428 snd_emu10k1_intr_enable(emu, INTE_FXDSPENABLE);
429 } else {
430 irq->next = emu->fx8010.irq_handlers;
431 emu->fx8010.irq_handlers = irq;
432 }
433 spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
434 if (r_irq)
435 *r_irq = irq;
436 return 0;
437}
438
439int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
440 snd_emu10k1_fx8010_irq_t *irq)
441{
442 snd_emu10k1_fx8010_irq_t *tmp;
443 unsigned long flags;
444
445 snd_runtime_check(irq, return -EINVAL);
446 spin_lock_irqsave(&emu->fx8010.irq_lock, flags);
447 if ((tmp = emu->fx8010.irq_handlers) == irq) {
448 emu->fx8010.irq_handlers = tmp->next;
449 if (emu->fx8010.irq_handlers == NULL) {
450 snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
451 emu->dsp_interrupt = NULL;
452 }
453 } else {
454 while (tmp && tmp->next != irq)
455 tmp = tmp->next;
456 if (tmp)
457 tmp->next = tmp->next->next;
458 }
459 spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
460 kfree(irq);
461 return 0;
462}
463
464/*************************************************************************
465 * EMU10K1 effect manager
466 *************************************************************************/
467
468static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
469 u32 op, u32 r, u32 a, u32 x, u32 y)
470{
471 u_int32_t *code;
472 snd_assert(*ptr < 512, return);
Clemens Ladisch4d233592005-09-05 10:35:20 +0200473 code = (u_int32_t __force *)icode->code + (*ptr) * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 set_bit(*ptr, icode->code_valid);
475 code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
476 code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
477 (*ptr)++;
478}
479
480#define OP(icode, ptr, op, r, a, x, y) \
481 snd_emu10k1_write_op(icode, ptr, op, r, a, x, y)
482
483static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
484 u32 op, u32 r, u32 a, u32 x, u32 y)
485{
486 u_int32_t *code;
487 snd_assert(*ptr < 1024, return);
Clemens Ladisch4d233592005-09-05 10:35:20 +0200488 code = (u_int32_t __force *)icode->code + (*ptr) * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489 set_bit(*ptr, icode->code_valid);
490 code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
491 code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
492 (*ptr)++;
493}
494
495#define A_OP(icode, ptr, op, r, a, x, y) \
496 snd_emu10k1_audigy_write_op(icode, ptr, op, r, a, x, y)
497
498static void snd_emu10k1_efx_write(emu10k1_t *emu, unsigned int pc, unsigned int data)
499{
500 pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
501 snd_emu10k1_ptr_write(emu, pc, 0, data);
502}
503
504unsigned int snd_emu10k1_efx_read(emu10k1_t *emu, unsigned int pc)
505{
506 pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
507 return snd_emu10k1_ptr_read(emu, pc, 0);
508}
509
510static int snd_emu10k1_gpr_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
511{
512 int gpr;
513 u32 val;
514
515 for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
516 if (!test_bit(gpr, icode->gpr_valid))
517 continue;
518 if (get_user(val, &icode->gpr_map[gpr]))
519 return -EFAULT;
520 snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val);
521 }
522 return 0;
523}
524
525static int snd_emu10k1_gpr_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
526{
527 int gpr;
528 u32 val;
529
530 for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
531 set_bit(gpr, icode->gpr_valid);
532 val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0);
533 if (put_user(val, &icode->gpr_map[gpr]))
534 return -EFAULT;
535 }
536 return 0;
537}
538
539static int snd_emu10k1_tram_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
540{
541 int tram;
542 u32 addr, val;
543
544 for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
545 if (!test_bit(tram, icode->tram_valid))
546 continue;
547 if (get_user(val, &icode->tram_data_map[tram]) ||
548 get_user(addr, &icode->tram_addr_map[tram]))
549 return -EFAULT;
550 snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val);
551 if (!emu->audigy) {
552 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr);
553 } else {
554 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr << 12);
555 snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, addr >> 20);
556 }
557 }
558 return 0;
559}
560
561static int snd_emu10k1_tram_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
562{
563 int tram;
564 u32 val, addr;
565
566 memset(icode->tram_valid, 0, sizeof(icode->tram_valid));
567 for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
568 set_bit(tram, icode->tram_valid);
569 val = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0);
570 if (!emu->audigy) {
571 addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0);
572 } else {
573 addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12;
574 addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20;
575 }
576 if (put_user(val, &icode->tram_data_map[tram]) ||
577 put_user(addr, &icode->tram_addr_map[tram]))
578 return -EFAULT;
579 }
580 return 0;
581}
582
583static int snd_emu10k1_code_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
584{
585 u32 pc, lo, hi;
586
587 for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
588 if (!test_bit(pc / 2, icode->code_valid))
589 continue;
590 if (get_user(lo, &icode->code[pc + 0]) ||
591 get_user(hi, &icode->code[pc + 1]))
592 return -EFAULT;
593 snd_emu10k1_efx_write(emu, pc + 0, lo);
594 snd_emu10k1_efx_write(emu, pc + 1, hi);
595 }
596 return 0;
597}
598
599static int snd_emu10k1_code_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
600{
601 u32 pc;
602
603 memset(icode->code_valid, 0, sizeof(icode->code_valid));
604 for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
605 set_bit(pc / 2, icode->code_valid);
606 if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0]))
607 return -EFAULT;
608 if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1]))
609 return -EFAULT;
610 }
611 return 0;
612}
613
614static snd_emu10k1_fx8010_ctl_t *snd_emu10k1_look_for_ctl(emu10k1_t *emu, snd_ctl_elem_id_t *id)
615{
616 snd_emu10k1_fx8010_ctl_t *ctl;
617 snd_kcontrol_t *kcontrol;
618 struct list_head *list;
619
620 list_for_each(list, &emu->fx8010.gpr_ctl) {
621 ctl = emu10k1_gpr_ctl(list);
622 kcontrol = ctl->kcontrol;
623 if (kcontrol->id.iface == id->iface &&
624 !strcmp(kcontrol->id.name, id->name) &&
625 kcontrol->id.index == id->index)
626 return ctl;
627 }
628 return NULL;
629}
630
631static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
632{
633 unsigned int i;
634 snd_ctl_elem_id_t __user *_id;
635 snd_ctl_elem_id_t id;
636 emu10k1_fx8010_control_gpr_t __user *_gctl;
637 emu10k1_fx8010_control_gpr_t *gctl;
638 int err;
639
640 for (i = 0, _id = icode->gpr_del_controls;
641 i < icode->gpr_del_control_count; i++, _id++) {
642 if (copy_from_user(&id, _id, sizeof(id)))
643 return -EFAULT;
644 if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)
645 return -ENOENT;
646 }
647 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
648 if (! gctl)
649 return -ENOMEM;
650 err = 0;
651 for (i = 0, _gctl = icode->gpr_add_controls;
652 i < icode->gpr_add_control_count; i++, _gctl++) {
653 if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
654 err = -EFAULT;
655 goto __error;
656 }
657 if (snd_emu10k1_look_for_ctl(emu, &gctl->id))
658 continue;
659 down_read(&emu->card->controls_rwsem);
660 if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) {
661 up_read(&emu->card->controls_rwsem);
662 err = -EEXIST;
663 goto __error;
664 }
665 up_read(&emu->card->controls_rwsem);
666 if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
667 gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
668 err = -EINVAL;
669 goto __error;
670 }
671 }
672 for (i = 0, _gctl = icode->gpr_list_controls;
673 i < icode->gpr_list_control_count; i++, _gctl++) {
674 /* FIXME: we need to check the WRITE access */
675 if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
676 err = -EFAULT;
677 goto __error;
678 }
679 }
680 __error:
681 kfree(gctl);
682 return err;
683}
684
685static void snd_emu10k1_ctl_private_free(snd_kcontrol_t *kctl)
686{
687 snd_emu10k1_fx8010_ctl_t *ctl;
688
689 ctl = (snd_emu10k1_fx8010_ctl_t *)kctl->private_value;
690 kctl->private_value = 0;
691 list_del(&ctl->list);
692 kfree(ctl);
693}
694
695static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
696{
697 unsigned int i, j;
698 emu10k1_fx8010_control_gpr_t __user *_gctl;
699 emu10k1_fx8010_control_gpr_t *gctl;
700 snd_emu10k1_fx8010_ctl_t *ctl, *nctl;
701 snd_kcontrol_new_t knew;
702 snd_kcontrol_t *kctl;
703 snd_ctl_elem_value_t *val;
704 int err = 0;
705
706 val = (snd_ctl_elem_value_t *)kmalloc(sizeof(*val), GFP_KERNEL);
707 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
708 nctl = kmalloc(sizeof(*nctl), GFP_KERNEL);
709 if (!val || !gctl || !nctl) {
710 err = -ENOMEM;
711 goto __error;
712 }
713
714 for (i = 0, _gctl = icode->gpr_add_controls;
715 i < icode->gpr_add_control_count; i++, _gctl++) {
716 if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
717 err = -EFAULT;
718 goto __error;
719 }
720 snd_runtime_check(gctl->id.iface == SNDRV_CTL_ELEM_IFACE_MIXER ||
721 gctl->id.iface == SNDRV_CTL_ELEM_IFACE_PCM, err = -EINVAL; goto __error);
722 snd_runtime_check(gctl->id.name[0] != '\0', err = -EINVAL; goto __error);
723 ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id);
724 memset(&knew, 0, sizeof(knew));
725 knew.iface = gctl->id.iface;
726 knew.name = gctl->id.name;
727 knew.index = gctl->id.index;
728 knew.device = gctl->id.device;
729 knew.subdevice = gctl->id.subdevice;
730 knew.info = snd_emu10k1_gpr_ctl_info;
731 knew.get = snd_emu10k1_gpr_ctl_get;
732 knew.put = snd_emu10k1_gpr_ctl_put;
733 memset(nctl, 0, sizeof(*nctl));
734 nctl->vcount = gctl->vcount;
735 nctl->count = gctl->count;
736 for (j = 0; j < 32; j++) {
737 nctl->gpr[j] = gctl->gpr[j];
738 nctl->value[j] = ~gctl->value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
739 val->value.integer.value[j] = gctl->value[j];
740 }
741 nctl->min = gctl->min;
742 nctl->max = gctl->max;
743 nctl->translation = gctl->translation;
744 if (ctl == NULL) {
745 ctl = (snd_emu10k1_fx8010_ctl_t *)kmalloc(sizeof(*ctl), GFP_KERNEL);
746 if (ctl == NULL) {
747 err = -ENOMEM;
748 goto __error;
749 }
750 knew.private_value = (unsigned long)ctl;
751 *ctl = *nctl;
752 if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) {
753 kfree(ctl);
754 goto __error;
755 }
756 kctl->private_free = snd_emu10k1_ctl_private_free;
757 ctl->kcontrol = kctl;
758 list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl);
759 } else {
760 /* overwrite */
761 nctl->list = ctl->list;
762 nctl->kcontrol = ctl->kcontrol;
763 *ctl = *nctl;
764 snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
765 SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id);
766 }
767 snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val);
768 }
769 __error:
770 kfree(nctl);
771 kfree(gctl);
772 kfree(val);
773 return err;
774}
775
776static int snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
777{
778 unsigned int i;
779 snd_ctl_elem_id_t id;
780 snd_ctl_elem_id_t __user *_id;
781 snd_emu10k1_fx8010_ctl_t *ctl;
782 snd_card_t *card = emu->card;
783
784 for (i = 0, _id = icode->gpr_del_controls;
785 i < icode->gpr_del_control_count; i++, _id++) {
786 snd_runtime_check(copy_from_user(&id, _id, sizeof(id)) == 0, return -EFAULT);
787 down_write(&card->controls_rwsem);
788 ctl = snd_emu10k1_look_for_ctl(emu, &id);
789 if (ctl)
790 snd_ctl_remove(card, ctl->kcontrol);
791 up_write(&card->controls_rwsem);
792 }
793 return 0;
794}
795
796static int snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
797{
798 unsigned int i = 0, j;
799 unsigned int total = 0;
800 emu10k1_fx8010_control_gpr_t *gctl;
801 emu10k1_fx8010_control_gpr_t __user *_gctl;
802 snd_emu10k1_fx8010_ctl_t *ctl;
803 snd_ctl_elem_id_t *id;
804 struct list_head *list;
805
806 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
807 if (! gctl)
808 return -ENOMEM;
809
810 _gctl = icode->gpr_list_controls;
811 list_for_each(list, &emu->fx8010.gpr_ctl) {
812 ctl = emu10k1_gpr_ctl(list);
813 total++;
814 if (_gctl && i < icode->gpr_list_control_count) {
815 memset(gctl, 0, sizeof(*gctl));
816 id = &ctl->kcontrol->id;
817 gctl->id.iface = id->iface;
818 strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
819 gctl->id.index = id->index;
820 gctl->id.device = id->device;
821 gctl->id.subdevice = id->subdevice;
822 gctl->vcount = ctl->vcount;
823 gctl->count = ctl->count;
824 for (j = 0; j < 32; j++) {
825 gctl->gpr[j] = ctl->gpr[j];
826 gctl->value[j] = ctl->value[j];
827 }
828 gctl->min = ctl->min;
829 gctl->max = ctl->max;
830 gctl->translation = ctl->translation;
831 if (copy_to_user(_gctl, gctl, sizeof(*gctl))) {
832 kfree(gctl);
833 return -EFAULT;
834 }
835 _gctl++;
836 i++;
837 }
838 }
839 icode->gpr_list_control_total = total;
840 kfree(gctl);
841 return 0;
842}
843
844static int snd_emu10k1_icode_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
845{
846 int err = 0;
847
848 down(&emu->fx8010.lock);
849 if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0)
850 goto __error;
851 strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
852 /* stop FX processor - this may be dangerous, but it's better to miss
853 some samples than generate wrong ones - [jk] */
854 if (emu->audigy)
855 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP);
856 else
857 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);
858 /* ok, do the main job */
859 if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 ||
860 (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 ||
861 (err = snd_emu10k1_tram_poke(emu, icode)) < 0 ||
862 (err = snd_emu10k1_code_poke(emu, icode)) < 0 ||
863 (err = snd_emu10k1_add_controls(emu, icode)) < 0)
864 goto __error;
865 /* start FX processor when the DSP code is updated */
866 if (emu->audigy)
867 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
868 else
869 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
870 __error:
871 up(&emu->fx8010.lock);
872 return err;
873}
874
875static int snd_emu10k1_icode_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
876{
877 int err;
878
879 down(&emu->fx8010.lock);
880 strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name));
881 /* ok, do the main job */
882 err = snd_emu10k1_gpr_peek(emu, icode);
883 if (err >= 0)
884 err = snd_emu10k1_tram_peek(emu, icode);
885 if (err >= 0)
886 err = snd_emu10k1_code_peek(emu, icode);
887 if (err >= 0)
888 err = snd_emu10k1_list_controls(emu, icode);
889 up(&emu->fx8010.lock);
890 return err;
891}
892
893static int snd_emu10k1_ipcm_poke(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
894{
895 unsigned int i;
896 int err = 0;
897 snd_emu10k1_fx8010_pcm_t *pcm;
898
899 if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
900 return -EINVAL;
901 if (ipcm->channels > 32)
902 return -EINVAL;
903 pcm = &emu->fx8010.pcm[ipcm->substream];
904 down(&emu->fx8010.lock);
905 spin_lock_irq(&emu->reg_lock);
906 if (pcm->opened) {
907 err = -EBUSY;
908 goto __error;
909 }
910 if (ipcm->channels == 0) { /* remove */
911 pcm->valid = 0;
912 } else {
913 /* FIXME: we need to add universal code to the PCM transfer routine */
914 if (ipcm->channels != 2) {
915 err = -EINVAL;
916 goto __error;
917 }
918 pcm->valid = 1;
919 pcm->opened = 0;
920 pcm->channels = ipcm->channels;
921 pcm->tram_start = ipcm->tram_start;
922 pcm->buffer_size = ipcm->buffer_size;
923 pcm->gpr_size = ipcm->gpr_size;
924 pcm->gpr_count = ipcm->gpr_count;
925 pcm->gpr_tmpcount = ipcm->gpr_tmpcount;
926 pcm->gpr_ptr = ipcm->gpr_ptr;
927 pcm->gpr_trigger = ipcm->gpr_trigger;
928 pcm->gpr_running = ipcm->gpr_running;
929 for (i = 0; i < pcm->channels; i++)
930 pcm->etram[i] = ipcm->etram[i];
931 }
932 __error:
933 spin_unlock_irq(&emu->reg_lock);
934 up(&emu->fx8010.lock);
935 return err;
936}
937
938static int snd_emu10k1_ipcm_peek(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
939{
940 unsigned int i;
941 int err = 0;
942 snd_emu10k1_fx8010_pcm_t *pcm;
943
944 if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
945 return -EINVAL;
946 pcm = &emu->fx8010.pcm[ipcm->substream];
947 down(&emu->fx8010.lock);
948 spin_lock_irq(&emu->reg_lock);
949 ipcm->channels = pcm->channels;
950 ipcm->tram_start = pcm->tram_start;
951 ipcm->buffer_size = pcm->buffer_size;
952 ipcm->gpr_size = pcm->gpr_size;
953 ipcm->gpr_ptr = pcm->gpr_ptr;
954 ipcm->gpr_count = pcm->gpr_count;
955 ipcm->gpr_tmpcount = pcm->gpr_tmpcount;
956 ipcm->gpr_trigger = pcm->gpr_trigger;
957 ipcm->gpr_running = pcm->gpr_running;
958 for (i = 0; i < pcm->channels; i++)
959 ipcm->etram[i] = pcm->etram[i];
960 ipcm->res1 = ipcm->res2 = 0;
961 ipcm->pad = 0;
962 spin_unlock_irq(&emu->reg_lock);
963 up(&emu->fx8010.lock);
964 return err;
965}
966
967#define SND_EMU10K1_GPR_CONTROLS 41
968#define SND_EMU10K1_INPUTS 10
969#define SND_EMU10K1_PLAYBACK_CHANNELS 8
970#define SND_EMU10K1_CAPTURE_CHANNELS 4
971
972static void __devinit snd_emu10k1_init_mono_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
973{
974 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
975 strcpy(ctl->id.name, name);
976 ctl->vcount = ctl->count = 1;
977 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
978 ctl->min = 0;
979 ctl->max = 100;
980 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
981}
982
983static void __devinit snd_emu10k1_init_stereo_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
984{
985 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
986 strcpy(ctl->id.name, name);
987 ctl->vcount = ctl->count = 2;
988 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
989 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
990 ctl->min = 0;
991 ctl->max = 100;
992 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
993}
994
995static void __devinit snd_emu10k1_init_mono_onoff_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
996{
997 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
998 strcpy(ctl->id.name, name);
999 ctl->vcount = ctl->count = 1;
1000 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1001 ctl->min = 0;
1002 ctl->max = 1;
1003 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
1004}
1005
1006static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
1007{
1008 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1009 strcpy(ctl->id.name, name);
1010 ctl->vcount = ctl->count = 2;
1011 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1012 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
1013 ctl->min = 0;
1014 ctl->max = 1;
1015 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
1016}
1017
1018
1019/*
1020 * initial DSP configuration for Audigy
1021 */
1022
1023static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
1024{
1025 int err, i, z, gpr, nctl;
1026 const int playback = 10;
1027 const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
1028 const int stereo_mix = capture + 2;
1029 const int tmp = 0x88;
1030 u32 ptr;
1031 emu10k1_fx8010_code_t *icode = NULL;
1032 emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;
1033 u32 *gpr_map;
1034 mm_segment_t seg;
1035
1036 spin_lock_init(&emu->fx8010.irq_lock);
1037 INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
1038
1039 if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL ||
1040 (icode->gpr_map = (u_int32_t __user *)kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
1041 (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {
1042 err = -ENOMEM;
1043 goto __err;
1044 }
Clemens Ladisch4d233592005-09-05 10:35:20 +02001045 gpr_map = (u32 __force *)icode->gpr_map;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
1047 icode->tram_data_map = icode->gpr_map + 512;
1048 icode->tram_addr_map = icode->tram_data_map + 256;
1049 icode->code = icode->tram_addr_map + 256;
1050
1051 /* clear free GPRs */
1052 for (i = 0; i < 512; i++)
1053 set_bit(i, icode->gpr_valid);
1054
1055 /* clear TRAM data & address lines */
1056 for (i = 0; i < 256; i++)
1057 set_bit(i, icode->tram_valid);
1058
1059 strcpy(icode->name, "Audigy DSP code for ALSA");
1060 ptr = 0;
1061 nctl = 0;
1062 gpr = stereo_mix + 10;
1063
1064 /* stop FX processor */
1065 snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
1066
1067 /* PCM front Playback Volume (independent from stereo mix) */
1068 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
1069 A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
1070 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100);
1071 gpr += 2;
1072
1073 /* PCM Surround Playback (independent from stereo mix) */
1074 A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR));
1075 A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
1076 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100);
1077 gpr += 2;
1078
1079 /* PCM Side Playback (independent from stereo mix) */
Lee Revell2b637da2005-03-30 13:51:18 +02001080 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001081 A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
1082 A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
1083 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
1084 gpr += 2;
1085 }
1086
1087 /* PCM Center Playback (independent from stereo mix) */
1088 A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER));
1089 snd_emu10k1_init_mono_control(&controls[nctl++], "PCM Center Playback Volume", gpr, 100);
1090 gpr++;
1091
1092 /* PCM LFE Playback (independent from stereo mix) */
1093 A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LFE));
1094 snd_emu10k1_init_mono_control(&controls[nctl++], "PCM LFE Playback Volume", gpr, 100);
1095 gpr++;
1096
1097 /*
1098 * Stereo Mix
1099 */
1100 /* Wave (PCM) Playback Volume (will be renamed later) */
1101 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
1102 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
1103 snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
1104 gpr += 2;
1105
1106 /* Synth Playback */
1107 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
1108 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
1109 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100);
1110 gpr += 2;
1111
1112 /* Wave (PCM) Capture */
1113 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
1114 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
1115 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0);
1116 gpr += 2;
1117
1118 /* Synth Capture */
1119 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
1120 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
1121 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0);
1122 gpr += 2;
1123
1124 /*
1125 * inputs
1126 */
1127#define A_ADD_VOLUME_IN(var,vol,input) \
1128A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
1129
1130 /* AC'97 Playback Volume - used only for mic (renamed later) */
1131 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L);
1132 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R);
1133 snd_emu10k1_init_stereo_control(&controls[nctl++], "AMic Playback Volume", gpr, 0);
1134 gpr += 2;
1135 /* AC'97 Capture Volume - used only for mic */
1136 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AC97_L);
1137 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AC97_R);
1138 snd_emu10k1_init_stereo_control(&controls[nctl++], "Mic Capture Volume", gpr, 0);
1139 gpr += 2;
1140
1141 /* mic capture buffer */
1142 A_OP(icode, &ptr, iINTERP, A_EXTOUT(A_EXTOUT_MIC_CAP), A_EXTIN(A_EXTIN_AC97_L), 0xcd, A_EXTIN(A_EXTIN_AC97_R));
1143
1144 /* Audigy CD Playback Volume */
1145 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L);
1146 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R);
1147 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001148 emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001149 gpr, 0);
1150 gpr += 2;
1151 /* Audigy CD Capture Volume */
1152 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
1153 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
1154 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001155 emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 gpr, 0);
1157 gpr += 2;
1158
1159 /* Optical SPDIF Playback Volume */
1160 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_OPT_SPDIF_L);
1161 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001162 snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163 gpr += 2;
1164 /* Optical SPDIF Capture Volume */
1165 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_OPT_SPDIF_L);
1166 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001167 snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",CAPTURE,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001168 gpr += 2;
1169
1170 /* Line2 Playback Volume */
1171 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L);
1172 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R);
1173 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001174 emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175 gpr, 0);
1176 gpr += 2;
1177 /* Line2 Capture Volume */
1178 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L);
1179 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R);
1180 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001181 emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 gpr, 0);
1183 gpr += 2;
1184
1185 /* Philips ADC Playback Volume */
1186 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_ADC_L);
1187 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_ADC_R);
1188 snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Playback Volume", gpr, 0);
1189 gpr += 2;
1190 /* Philips ADC Capture Volume */
1191 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_ADC_L);
1192 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_ADC_R);
1193 snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Capture Volume", gpr, 0);
1194 gpr += 2;
1195
1196 /* Aux2 Playback Volume */
1197 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L);
1198 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R);
1199 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001200 emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201 gpr, 0);
1202 gpr += 2;
1203 /* Aux2 Capture Volume */
1204 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L);
1205 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R);
1206 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001207 emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001208 gpr, 0);
1209 gpr += 2;
1210
1211 /* Stereo Mix Front Playback Volume */
1212 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_GPR(playback), A_GPR(gpr), A_GPR(stereo_mix));
1213 A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_GPR(playback+1), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1214 snd_emu10k1_init_stereo_control(&controls[nctl++], "Front Playback Volume", gpr, 100);
1215 gpr += 2;
1216
1217 /* Stereo Mix Surround Playback */
1218 A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_GPR(playback+2), A_GPR(gpr), A_GPR(stereo_mix));
1219 A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_GPR(playback+3), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1220 snd_emu10k1_init_stereo_control(&controls[nctl++], "Surround Playback Volume", gpr, 0);
1221 gpr += 2;
1222
1223 /* Stereo Mix Center Playback */
1224 /* Center = sub = Left/2 + Right/2 */
1225 A_OP(icode, &ptr, iINTERP, A_GPR(tmp), A_GPR(stereo_mix), 0xcd, A_GPR(stereo_mix+1));
1226 A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_GPR(playback+4), A_GPR(gpr), A_GPR(tmp));
1227 snd_emu10k1_init_mono_control(&controls[nctl++], "Center Playback Volume", gpr, 0);
1228 gpr++;
1229
1230 /* Stereo Mix LFE Playback */
1231 A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp));
1232 snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
1233 gpr++;
1234
Lee Revell2b637da2005-03-30 13:51:18 +02001235 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 /* Stereo Mix Side Playback */
1237 A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
1238 A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1239 snd_emu10k1_init_stereo_control(&controls[nctl++], "Side Playback Volume", gpr, 0);
1240 gpr += 2;
1241 }
1242
1243 /*
1244 * outputs
1245 */
1246#define A_PUT_OUTPUT(out,src) A_OP(icode, &ptr, iACC3, A_EXTOUT(out), A_C_00000000, A_C_00000000, A_GPR(src))
1247#define A_PUT_STEREO_OUTPUT(out1,out2,src) \
1248 {A_PUT_OUTPUT(out1,src); A_PUT_OUTPUT(out2,src+1);}
1249
1250#define _A_SWITCH(icode, ptr, dst, src, sw) \
1251 A_OP((icode), ptr, iMACINT0, dst, A_C_00000000, src, sw);
1252#define A_SWITCH(icode, ptr, dst, src, sw) \
1253 _A_SWITCH(icode, ptr, A_GPR(dst), A_GPR(src), A_GPR(sw))
1254#define _A_SWITCH_NEG(icode, ptr, dst, src) \
1255 A_OP((icode), ptr, iANDXOR, dst, src, A_C_00000001, A_C_00000001);
1256#define A_SWITCH_NEG(icode, ptr, dst, src) \
1257 _A_SWITCH_NEG(icode, ptr, A_GPR(dst), A_GPR(src))
1258
1259
1260 /*
1261 * Process tone control
1262 */
1263 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), A_GPR(playback + 0), A_C_00000000, A_C_00000000); /* left */
1264 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), A_GPR(playback + 1), A_C_00000000, A_C_00000000); /* right */
1265 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2), A_GPR(playback + 2), A_C_00000000, A_C_00000000); /* rear left */
1266 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), A_GPR(playback + 3), A_C_00000000, A_C_00000000); /* rear right */
1267 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
1268 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), A_GPR(playback + 5), A_C_00000000, A_C_00000000); /* LFE */
Lee Revell2b637da2005-03-30 13:51:18 +02001269 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 6), A_GPR(playback + 6), A_C_00000000, A_C_00000000); /* side left */
1271 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 7), A_GPR(playback + 7), A_C_00000000, A_C_00000000); /* side right */
1272 }
1273
1274
1275 ctl = &controls[nctl + 0];
1276 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1277 strcpy(ctl->id.name, "Tone Control - Bass");
1278 ctl->vcount = 2;
1279 ctl->count = 10;
1280 ctl->min = 0;
1281 ctl->max = 40;
1282 ctl->value[0] = ctl->value[1] = 20;
1283 ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
1284 ctl = &controls[nctl + 1];
1285 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1286 strcpy(ctl->id.name, "Tone Control - Treble");
1287 ctl->vcount = 2;
1288 ctl->count = 10;
1289 ctl->min = 0;
1290 ctl->max = 40;
1291 ctl->value[0] = ctl->value[1] = 20;
1292 ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
1293
1294#define BASS_GPR 0x8c
1295#define TREBLE_GPR 0x96
1296
1297 for (z = 0; z < 5; z++) {
1298 int j;
1299 for (j = 0; j < 2; j++) {
1300 controls[nctl + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j;
1301 controls[nctl + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
1302 }
1303 }
1304 for (z = 0; z < 4; z++) { /* front/rear/center-lfe/side */
1305 int j, k, l, d;
1306 for (j = 0; j < 2; j++) { /* left/right */
1307 k = 0xb0 + (z * 8) + (j * 4);
1308 l = 0xe0 + (z * 8) + (j * 4);
1309 d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j;
1310
1311 A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(d), A_GPR(BASS_GPR + 0 + j));
1312 A_OP(icode, &ptr, iMACMV, A_GPR(k+1), A_GPR(k), A_GPR(k+1), A_GPR(BASS_GPR + 4 + j));
1313 A_OP(icode, &ptr, iMACMV, A_GPR(k), A_GPR(d), A_GPR(k), A_GPR(BASS_GPR + 2 + j));
1314 A_OP(icode, &ptr, iMACMV, A_GPR(k+3), A_GPR(k+2), A_GPR(k+3), A_GPR(BASS_GPR + 8 + j));
1315 A_OP(icode, &ptr, iMAC0, A_GPR(k+2), A_GPR_ACCU, A_GPR(k+2), A_GPR(BASS_GPR + 6 + j));
1316 A_OP(icode, &ptr, iACC3, A_GPR(k+2), A_GPR(k+2), A_GPR(k+2), A_C_00000000);
1317
1318 A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(k+2), A_GPR(TREBLE_GPR + 0 + j));
1319 A_OP(icode, &ptr, iMACMV, A_GPR(l+1), A_GPR(l), A_GPR(l+1), A_GPR(TREBLE_GPR + 4 + j));
1320 A_OP(icode, &ptr, iMACMV, A_GPR(l), A_GPR(k+2), A_GPR(l), A_GPR(TREBLE_GPR + 2 + j));
1321 A_OP(icode, &ptr, iMACMV, A_GPR(l+3), A_GPR(l+2), A_GPR(l+3), A_GPR(TREBLE_GPR + 8 + j));
1322 A_OP(icode, &ptr, iMAC0, A_GPR(l+2), A_GPR_ACCU, A_GPR(l+2), A_GPR(TREBLE_GPR + 6 + j));
1323 A_OP(icode, &ptr, iMACINT0, A_GPR(l+2), A_C_00000000, A_GPR(l+2), A_C_00000010);
1324
1325 A_OP(icode, &ptr, iACC3, A_GPR(d), A_GPR(l+2), A_C_00000000, A_C_00000000);
1326
1327 if (z == 2) /* center */
1328 break;
1329 }
1330 }
1331 nctl += 2;
1332
1333#undef BASS_GPR
1334#undef TREBLE_GPR
1335
1336 for (z = 0; z < 8; z++) {
1337 A_SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
1338 A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
1339 A_SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
1340 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1341 }
1342 snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0);
1343 gpr += 2;
1344
1345 /* Master volume (will be renamed later) */
1346 A_OP(icode, &ptr, iMAC0, A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+0+SND_EMU10K1_PLAYBACK_CHANNELS));
1347 A_OP(icode, &ptr, iMAC0, A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+1+SND_EMU10K1_PLAYBACK_CHANNELS));
1348 A_OP(icode, &ptr, iMAC0, A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+2+SND_EMU10K1_PLAYBACK_CHANNELS));
1349 A_OP(icode, &ptr, iMAC0, A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+3+SND_EMU10K1_PLAYBACK_CHANNELS));
1350 A_OP(icode, &ptr, iMAC0, A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+4+SND_EMU10K1_PLAYBACK_CHANNELS));
1351 A_OP(icode, &ptr, iMAC0, A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+5+SND_EMU10K1_PLAYBACK_CHANNELS));
1352 A_OP(icode, &ptr, iMAC0, A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+6+SND_EMU10K1_PLAYBACK_CHANNELS));
1353 A_OP(icode, &ptr, iMAC0, A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS), A_C_00000000, A_GPR(gpr), A_GPR(playback+7+SND_EMU10K1_PLAYBACK_CHANNELS));
1354 snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
1355 gpr += 2;
1356
1357 /* analog speakers */
1358 A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1359 A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
1360 A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
1361 A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
Lee Revell2b637da2005-03-30 13:51:18 +02001362 if (emu->card_capabilities->spk71)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363 A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
1364
1365 /* headphone */
1366 A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1367
1368 /* digital outputs */
1369 /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
1370
1371 /* IEC958 Optical Raw Playback Switch */
1372 gpr_map[gpr++] = 0;
1373 gpr_map[gpr++] = 0x1008;
1374 gpr_map[gpr++] = 0xffff0000;
1375 for (z = 0; z < 2; z++) {
1376 A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000);
1377 A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001);
1378 A_OP(icode, &ptr, iACC3, A_GPR(tmp + 2), A_C_00000000, A_C_00010000, A_GPR(tmp + 2));
1379 A_OP(icode, &ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_GPR(gpr - 1), A_C_00000000);
1380 A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z);
1381 A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
1382 A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
1383 if ((z==1) && (emu->card_capabilities->spdif_bug)) {
1384 /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */
1385 snd_printk("Installing spdif_bug patch: %s\n", emu->card_capabilities->name);
1386 A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000);
1387 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1388 } else {
1389 A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1390 }
1391 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001392 snd_emu10k1_init_stereo_onoff_control(controls + nctl++, SNDRV_CTL_NAME_IEC958("Optical Raw ",PLAYBACK,SWITCH), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393 gpr += 2;
1394
1395 A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
1396 A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
1397 A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
1398
1399 /* ADC buffer */
1400#ifdef EMU10K1_CAPTURE_DIGITAL_OUT
1401 A_PUT_STEREO_OUTPUT(A_EXTOUT_ADC_CAP_L, A_EXTOUT_ADC_CAP_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1402#else
1403 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture);
1404 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
1405#endif
1406
1407 /* EFX capture - capture the 16 EXTINs */
1408 for (z = 0; z < 16; z++) {
1409 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
1410 }
1411
1412 /*
1413 * ok, set up done..
1414 */
1415
1416 if (gpr > tmp) {
1417 snd_BUG();
1418 err = -EIO;
1419 goto __err;
1420 }
1421 /* clear remaining instruction memory */
1422 while (ptr < 0x400)
1423 A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0);
1424
1425 seg = snd_enter_user();
1426 icode->gpr_add_control_count = nctl;
1427 icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
1428 err = snd_emu10k1_icode_poke(emu, icode);
1429 snd_leave_user(seg);
1430
1431 __err:
1432 kfree(controls);
1433 if (icode != NULL) {
Clemens Ladisch4d233592005-09-05 10:35:20 +02001434 kfree((void __force *)icode->gpr_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001435 kfree(icode);
1436 }
1437 return err;
1438}
1439
1440
1441/*
1442 * initial DSP configuration for Emu10k1
1443 */
1444
1445/* when volume = max, then copy only to avoid volume modification */
1446/* with iMAC0 (negative values) */
1447static void __devinit _volume(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
1448{
1449 OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
1450 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1451 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001);
1452 OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
1453}
1454static void __devinit _volume_add(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
1455{
1456 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1457 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1458 OP(icode, ptr, iMACINT0, dst, dst, src, C_00000001);
1459 OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
1460 OP(icode, ptr, iMAC0, dst, dst, src, vol);
1461}
1462static void __devinit _volume_out(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
1463{
1464 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1465 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1466 OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
1467 OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
1468 OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
1469}
1470
1471#define VOLUME(icode, ptr, dst, src, vol) \
1472 _volume(icode, ptr, GPR(dst), GPR(src), GPR(vol))
1473#define VOLUME_IN(icode, ptr, dst, src, vol) \
1474 _volume(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))
1475#define VOLUME_ADD(icode, ptr, dst, src, vol) \
1476 _volume_add(icode, ptr, GPR(dst), GPR(src), GPR(vol))
1477#define VOLUME_ADDIN(icode, ptr, dst, src, vol) \
1478 _volume_add(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))
1479#define VOLUME_OUT(icode, ptr, dst, src, vol) \
1480 _volume_out(icode, ptr, EXTOUT(dst), GPR(src), GPR(vol))
1481#define _SWITCH(icode, ptr, dst, src, sw) \
1482 OP((icode), ptr, iMACINT0, dst, C_00000000, src, sw);
1483#define SWITCH(icode, ptr, dst, src, sw) \
1484 _SWITCH(icode, ptr, GPR(dst), GPR(src), GPR(sw))
1485#define SWITCH_IN(icode, ptr, dst, src, sw) \
1486 _SWITCH(icode, ptr, GPR(dst), EXTIN(src), GPR(sw))
1487#define _SWITCH_NEG(icode, ptr, dst, src) \
1488 OP((icode), ptr, iANDXOR, dst, src, C_00000001, C_00000001);
1489#define SWITCH_NEG(icode, ptr, dst, src) \
1490 _SWITCH_NEG(icode, ptr, GPR(dst), GPR(src))
1491
1492
1493static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
1494{
1495 int err, i, z, gpr, tmp, playback, capture;
1496 u32 ptr;
1497 emu10k1_fx8010_code_t *icode;
1498 emu10k1_fx8010_pcm_t *ipcm = NULL;
1499 emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;
1500 u32 *gpr_map;
1501 mm_segment_t seg;
1502
1503 spin_lock_init(&emu->fx8010.irq_lock);
1504 INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
1505
1506 if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
1507 return -ENOMEM;
1508 if ((icode->gpr_map = (u_int32_t __user *)kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
1509 (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL ||
1510 (ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) {
1511 err = -ENOMEM;
1512 goto __err;
1513 }
Clemens Ladisch4d233592005-09-05 10:35:20 +02001514 gpr_map = (u32 __force *)icode->gpr_map;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515
1516 icode->tram_data_map = icode->gpr_map + 256;
1517 icode->tram_addr_map = icode->tram_data_map + 160;
1518 icode->code = icode->tram_addr_map + 160;
1519
1520 /* clear free GPRs */
1521 for (i = 0; i < 256; i++)
1522 set_bit(i, icode->gpr_valid);
1523
1524 /* clear TRAM data & address lines */
1525 for (i = 0; i < 160; i++)
1526 set_bit(i, icode->tram_valid);
1527
1528 strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela");
1529 ptr = 0; i = 0;
1530 /* we have 10 inputs */
1531 playback = SND_EMU10K1_INPUTS;
1532 /* we have 6 playback channels and tone control doubles */
1533 capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2);
1534 gpr = capture + SND_EMU10K1_CAPTURE_CHANNELS;
1535 tmp = 0x88; /* we need 4 temporary GPR */
1536 /* from 0x8c to 0xff is the area for tone control */
1537
1538 /* stop FX processor */
1539 snd_emu10k1_ptr_write(emu, DBG, 0, (emu->fx8010.dbg = 0) | EMU10K1_DBG_SINGLE_STEP);
1540
1541 /*
1542 * Process FX Buses
1543 */
1544 OP(icode, &ptr, iMACINT0, GPR(0), C_00000000, FXBUS(FXBUS_PCM_LEFT), C_00000004);
1545 OP(icode, &ptr, iMACINT0, GPR(1), C_00000000, FXBUS(FXBUS_PCM_RIGHT), C_00000004);
1546 OP(icode, &ptr, iMACINT0, GPR(2), C_00000000, FXBUS(FXBUS_MIDI_LEFT), C_00000004);
1547 OP(icode, &ptr, iMACINT0, GPR(3), C_00000000, FXBUS(FXBUS_MIDI_RIGHT), C_00000004);
1548 OP(icode, &ptr, iMACINT0, GPR(4), C_00000000, FXBUS(FXBUS_PCM_LEFT_REAR), C_00000004);
1549 OP(icode, &ptr, iMACINT0, GPR(5), C_00000000, FXBUS(FXBUS_PCM_RIGHT_REAR), C_00000004);
1550 OP(icode, &ptr, iMACINT0, GPR(6), C_00000000, FXBUS(FXBUS_PCM_CENTER), C_00000004);
1551 OP(icode, &ptr, iMACINT0, GPR(7), C_00000000, FXBUS(FXBUS_PCM_LFE), C_00000004);
1552 OP(icode, &ptr, iMACINT0, GPR(8), C_00000000, C_00000000, C_00000000); /* S/PDIF left */
1553 OP(icode, &ptr, iMACINT0, GPR(9), C_00000000, C_00000000, C_00000000); /* S/PDIF right */
1554
1555 /* Raw S/PDIF PCM */
1556 ipcm->substream = 0;
1557 ipcm->channels = 2;
1558 ipcm->tram_start = 0;
1559 ipcm->buffer_size = (64 * 1024) / 2;
1560 ipcm->gpr_size = gpr++;
1561 ipcm->gpr_ptr = gpr++;
1562 ipcm->gpr_count = gpr++;
1563 ipcm->gpr_tmpcount = gpr++;
1564 ipcm->gpr_trigger = gpr++;
1565 ipcm->gpr_running = gpr++;
1566 ipcm->etram[0] = 0;
1567 ipcm->etram[1] = 1;
1568
1569 gpr_map[gpr + 0] = 0xfffff000;
1570 gpr_map[gpr + 1] = 0xffff0000;
1571 gpr_map[gpr + 2] = 0x70000000;
1572 gpr_map[gpr + 3] = 0x00000007;
1573 gpr_map[gpr + 4] = 0x001f << 11;
1574 gpr_map[gpr + 5] = 0x001c << 11;
1575 gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */
1576 gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */
1577 gpr_map[gpr + 8] = 0x2000000 + (2<<11);
1578 gpr_map[gpr + 9] = 0x4000000 + (2<<11);
1579 gpr_map[gpr + 10] = 1<<11;
1580 gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */
1581 gpr_map[gpr + 12] = 0;
1582
1583 /* if the trigger flag is not set, skip */
1584 /* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000);
1585 /* 01: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_ZERO, GPR(gpr + 6));
1586 /* if the running flag is set, we're running */
1587 /* 02: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_running), C_00000000, C_00000000);
1588 /* 03: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000004);
1589 /* wait until ((GPR_DBAC>>11) & 0x1f) == 0x1c) */
1590 /* 04: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), GPR_DBAC, GPR(gpr + 4), C_00000000);
1591 /* 05: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(gpr + 5));
1592 /* 06: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 7));
1593 /* 07: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000010, C_00000001, C_00000000);
1594
1595 /* 08: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000000, C_00000001);
1596 /* 09: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), GPR(gpr + 12), C_ffffffff, C_00000000);
1597 /* 0a: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 11));
1598 /* 0b: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000001, C_00000000, C_00000000);
1599
1600 /* 0c: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[0]), GPR(gpr + 0), C_00000000);
1601 /* 0d: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000);
1602 /* 0e: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2));
1603 /* 0f: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001);
1604 /* 10: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(8), GPR(gpr + 1), GPR(gpr + 2));
1605
1606 /* 11: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[1]), GPR(gpr + 0), C_00000000);
1607 /* 12: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000);
1608 /* 13: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2));
1609 /* 14: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001);
1610 /* 15: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(9), GPR(gpr + 1), GPR(gpr + 2));
1611
1612 /* 16: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(ipcm->gpr_ptr), C_00000001, C_00000000);
1613 /* 17: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(ipcm->gpr_size));
1614 /* 18: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_MINUS, C_00000001);
1615 /* 19: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), C_00000000, C_00000000, C_00000000);
1616 /* 1a: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_ptr), GPR(tmp + 0), C_00000000, C_00000000);
1617
1618 /* 1b: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_tmpcount), C_ffffffff, C_00000000);
1619 /* 1c: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1620 /* 1d: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_count), C_00000000, C_00000000);
1621 /* 1e: */ OP(icode, &ptr, iACC3, GPR_IRQ, C_80000000, C_00000000, C_00000000);
1622 /* 1f: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000001, C_00010000);
1623
1624 /* 20: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00010000, C_00000001);
1625 /* 21: */ OP(icode, &ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000002);
1626
1627 /* 22: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[0]), GPR(gpr + 8), GPR_DBAC, C_ffffffff);
1628 /* 23: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[1]), GPR(gpr + 9), GPR_DBAC, C_ffffffff);
1629
1630 /* 24: */
1631 gpr += 13;
1632
1633 /* Wave Playback Volume */
1634 for (z = 0; z < 2; z++)
1635 VOLUME(icode, &ptr, playback + z, z, gpr + z);
1636 snd_emu10k1_init_stereo_control(controls + i++, "Wave Playback Volume", gpr, 100);
1637 gpr += 2;
1638
1639 /* Wave Surround Playback Volume */
1640 for (z = 0; z < 2; z++)
1641 VOLUME(icode, &ptr, playback + 2 + z, z, gpr + z);
1642 snd_emu10k1_init_stereo_control(controls + i++, "Wave Surround Playback Volume", gpr, 0);
1643 gpr += 2;
1644
1645 /* Wave Center/LFE Playback Volume */
1646 OP(icode, &ptr, iACC3, GPR(tmp + 0), FXBUS(FXBUS_PCM_LEFT), FXBUS(FXBUS_PCM_RIGHT), C_00000000);
1647 OP(icode, &ptr, iMACINT0, GPR(tmp + 0), C_00000000, GPR(tmp + 0), C_00000002);
1648 VOLUME(icode, &ptr, playback + 4, tmp + 0, gpr);
1649 snd_emu10k1_init_mono_control(controls + i++, "Wave Center Playback Volume", gpr++, 0);
1650 VOLUME(icode, &ptr, playback + 5, tmp + 0, gpr);
1651 snd_emu10k1_init_mono_control(controls + i++, "Wave LFE Playback Volume", gpr++, 0);
1652
1653 /* Wave Capture Volume + Switch */
1654 for (z = 0; z < 2; z++) {
1655 SWITCH(icode, &ptr, tmp + 0, z, gpr + 2 + z);
1656 VOLUME(icode, &ptr, capture + z, tmp + 0, gpr + z);
1657 }
1658 snd_emu10k1_init_stereo_control(controls + i++, "Wave Capture Volume", gpr, 0);
1659 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0);
1660 gpr += 4;
1661
1662 /* Synth Playback Volume */
1663 for (z = 0; z < 2; z++)
1664 VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z);
1665 snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100);
1666 gpr += 2;
1667
1668 /* Synth Capture Volume + Switch */
1669 for (z = 0; z < 2; z++) {
1670 SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z);
1671 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1672 }
1673 snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0);
1674 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0);
1675 gpr += 4;
1676
1677 /* Surround Digital Playback Volume (renamed later without Digital) */
1678 for (z = 0; z < 2; z++)
1679 VOLUME_ADD(icode, &ptr, playback + 2 + z, 4 + z, gpr + z);
1680 snd_emu10k1_init_stereo_control(controls + i++, "Surround Digital Playback Volume", gpr, 100);
1681 gpr += 2;
1682
1683 /* Surround Capture Volume + Switch */
1684 for (z = 0; z < 2; z++) {
1685 SWITCH(icode, &ptr, tmp + 0, 4 + z, gpr + 2 + z);
1686 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1687 }
1688 snd_emu10k1_init_stereo_control(controls + i++, "Surround Capture Volume", gpr, 0);
1689 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Surround Capture Switch", gpr + 2, 0);
1690 gpr += 4;
1691
1692 /* Center Playback Volume (renamed later without Digital) */
1693 VOLUME_ADD(icode, &ptr, playback + 4, 6, gpr);
1694 snd_emu10k1_init_mono_control(controls + i++, "Center Digital Playback Volume", gpr++, 100);
1695
1696 /* LFE Playback Volume + Switch (renamed later without Digital) */
1697 VOLUME_ADD(icode, &ptr, playback + 5, 7, gpr);
1698 snd_emu10k1_init_mono_control(controls + i++, "LFE Digital Playback Volume", gpr++, 100);
1699
1700 /*
1701 * Process inputs
1702 */
1703
1704 if (emu->fx8010.extin_mask & ((1<<EXTIN_AC97_L)|(1<<EXTIN_AC97_R))) {
1705 /* AC'97 Playback Volume */
1706 VOLUME_ADDIN(icode, &ptr, playback + 0, EXTIN_AC97_L, gpr); gpr++;
1707 VOLUME_ADDIN(icode, &ptr, playback + 1, EXTIN_AC97_R, gpr); gpr++;
1708 snd_emu10k1_init_stereo_control(controls + i++, "AC97 Playback Volume", gpr-2, 0);
1709 /* AC'97 Capture Volume */
1710 VOLUME_ADDIN(icode, &ptr, capture + 0, EXTIN_AC97_L, gpr); gpr++;
1711 VOLUME_ADDIN(icode, &ptr, capture + 1, EXTIN_AC97_R, gpr); gpr++;
1712 snd_emu10k1_init_stereo_control(controls + i++, "AC97 Capture Volume", gpr-2, 100);
1713 }
1714
1715 if (emu->fx8010.extin_mask & ((1<<EXTIN_SPDIF_CD_L)|(1<<EXTIN_SPDIF_CD_R))) {
1716 /* IEC958 TTL Playback Volume */
1717 for (z = 0; z < 2; z++)
1718 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_SPDIF_CD_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001719 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 gpr += 2;
1721
1722 /* IEC958 TTL Capture Volume + Switch */
1723 for (z = 0; z < 2; z++) {
1724 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_SPDIF_CD_L + z, gpr + 2 + z);
1725 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1726 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001727 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",CAPTURE,VOLUME), gpr, 0);
1728 snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",CAPTURE,SWITCH), gpr + 2, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 gpr += 4;
1730 }
1731
1732 if (emu->fx8010.extin_mask & ((1<<EXTIN_ZOOM_L)|(1<<EXTIN_ZOOM_R))) {
1733 /* Zoom Video Playback Volume */
1734 for (z = 0; z < 2; z++)
1735 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_ZOOM_L + z, gpr + z);
1736 snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Playback Volume", gpr, 0);
1737 gpr += 2;
1738
1739 /* Zoom Video Capture Volume + Switch */
1740 for (z = 0; z < 2; z++) {
1741 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_ZOOM_L + z, gpr + 2 + z);
1742 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1743 }
1744 snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Capture Volume", gpr, 0);
1745 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Zoom Video Capture Switch", gpr + 2, 0);
1746 gpr += 4;
1747 }
1748
1749 if (emu->fx8010.extin_mask & ((1<<EXTIN_TOSLINK_L)|(1<<EXTIN_TOSLINK_R))) {
1750 /* IEC958 Optical Playback Volume */
1751 for (z = 0; z < 2; z++)
1752 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_TOSLINK_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001753 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001754 gpr += 2;
1755
1756 /* IEC958 Optical Capture Volume */
1757 for (z = 0; z < 2; z++) {
1758 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_TOSLINK_L + z, gpr + 2 + z);
1759 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1760 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001761 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",CAPTURE,VOLUME), gpr, 0);
1762 snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",CAPTURE,SWITCH), gpr + 2, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001763 gpr += 4;
1764 }
1765
1766 if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE1_L)|(1<<EXTIN_LINE1_R))) {
1767 /* Line LiveDrive Playback Volume */
1768 for (z = 0; z < 2; z++)
1769 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE1_L + z, gpr + z);
1770 snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Playback Volume", gpr, 0);
1771 gpr += 2;
1772
1773 /* Line LiveDrive Capture Volume + Switch */
1774 for (z = 0; z < 2; z++) {
1775 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE1_L + z, gpr + 2 + z);
1776 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1777 }
1778 snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Capture Volume", gpr, 0);
1779 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line LiveDrive Capture Switch", gpr + 2, 0);
1780 gpr += 4;
1781 }
1782
1783 if (emu->fx8010.extin_mask & ((1<<EXTIN_COAX_SPDIF_L)|(1<<EXTIN_COAX_SPDIF_R))) {
1784 /* IEC958 Coax Playback Volume */
1785 for (z = 0; z < 2; z++)
1786 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_COAX_SPDIF_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001787 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001788 gpr += 2;
1789
1790 /* IEC958 Coax Capture Volume + Switch */
1791 for (z = 0; z < 2; z++) {
1792 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_COAX_SPDIF_L + z, gpr + 2 + z);
1793 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1794 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001795 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",CAPTURE,VOLUME), gpr, 0);
1796 snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",CAPTURE,SWITCH), gpr + 2, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001797 gpr += 4;
1798 }
1799
1800 if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE2_L)|(1<<EXTIN_LINE2_R))) {
1801 /* Line LiveDrive Playback Volume */
1802 for (z = 0; z < 2; z++)
1803 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE2_L + z, gpr + z);
1804 snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Playback Volume", gpr, 0);
1805 controls[i-1].id.index = 1;
1806 gpr += 2;
1807
1808 /* Line LiveDrive Capture Volume */
1809 for (z = 0; z < 2; z++) {
1810 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE2_L + z, gpr + 2 + z);
1811 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1812 }
1813 snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Capture Volume", gpr, 0);
1814 controls[i-1].id.index = 1;
1815 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line2 LiveDrive Capture Switch", gpr + 2, 0);
1816 controls[i-1].id.index = 1;
1817 gpr += 4;
1818 }
1819
1820 /*
1821 * Process tone control
1822 */
1823 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), GPR(playback + 0), C_00000000, C_00000000); /* left */
1824 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), GPR(playback + 1), C_00000000, C_00000000); /* right */
1825 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2), GPR(playback + 2), C_00000000, C_00000000); /* rear left */
1826 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), GPR(playback + 3), C_00000000, C_00000000); /* rear right */
1827 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), GPR(playback + 4), C_00000000, C_00000000); /* center */
1828 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), GPR(playback + 5), C_00000000, C_00000000); /* LFE */
1829
1830 ctl = &controls[i + 0];
1831 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1832 strcpy(ctl->id.name, "Tone Control - Bass");
1833 ctl->vcount = 2;
1834 ctl->count = 10;
1835 ctl->min = 0;
1836 ctl->max = 40;
1837 ctl->value[0] = ctl->value[1] = 20;
1838 ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
1839 ctl = &controls[i + 1];
1840 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1841 strcpy(ctl->id.name, "Tone Control - Treble");
1842 ctl->vcount = 2;
1843 ctl->count = 10;
1844 ctl->min = 0;
1845 ctl->max = 40;
1846 ctl->value[0] = ctl->value[1] = 20;
1847 ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
1848
1849#define BASS_GPR 0x8c
1850#define TREBLE_GPR 0x96
1851
1852 for (z = 0; z < 5; z++) {
1853 int j;
1854 for (j = 0; j < 2; j++) {
1855 controls[i + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j;
1856 controls[i + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
1857 }
1858 }
1859 for (z = 0; z < 3; z++) { /* front/rear/center-lfe */
1860 int j, k, l, d;
1861 for (j = 0; j < 2; j++) { /* left/right */
1862 k = 0xa0 + (z * 8) + (j * 4);
1863 l = 0xd0 + (z * 8) + (j * 4);
1864 d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j;
1865
1866 OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(d), GPR(BASS_GPR + 0 + j));
1867 OP(icode, &ptr, iMACMV, GPR(k+1), GPR(k), GPR(k+1), GPR(BASS_GPR + 4 + j));
1868 OP(icode, &ptr, iMACMV, GPR(k), GPR(d), GPR(k), GPR(BASS_GPR + 2 + j));
1869 OP(icode, &ptr, iMACMV, GPR(k+3), GPR(k+2), GPR(k+3), GPR(BASS_GPR + 8 + j));
1870 OP(icode, &ptr, iMAC0, GPR(k+2), GPR_ACCU, GPR(k+2), GPR(BASS_GPR + 6 + j));
1871 OP(icode, &ptr, iACC3, GPR(k+2), GPR(k+2), GPR(k+2), C_00000000);
1872
1873 OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(k+2), GPR(TREBLE_GPR + 0 + j));
1874 OP(icode, &ptr, iMACMV, GPR(l+1), GPR(l), GPR(l+1), GPR(TREBLE_GPR + 4 + j));
1875 OP(icode, &ptr, iMACMV, GPR(l), GPR(k+2), GPR(l), GPR(TREBLE_GPR + 2 + j));
1876 OP(icode, &ptr, iMACMV, GPR(l+3), GPR(l+2), GPR(l+3), GPR(TREBLE_GPR + 8 + j));
1877 OP(icode, &ptr, iMAC0, GPR(l+2), GPR_ACCU, GPR(l+2), GPR(TREBLE_GPR + 6 + j));
1878 OP(icode, &ptr, iMACINT0, GPR(l+2), C_00000000, GPR(l+2), C_00000010);
1879
1880 OP(icode, &ptr, iACC3, GPR(d), GPR(l+2), C_00000000, C_00000000);
1881
1882 if (z == 2) /* center */
1883 break;
1884 }
1885 }
1886 i += 2;
1887
1888#undef BASS_GPR
1889#undef TREBLE_GPR
1890
1891 for (z = 0; z < 6; z++) {
1892 SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
1893 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
1894 SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
1895 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
1896 }
1897 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Tone Control - Switch", gpr, 0);
1898 gpr += 2;
1899
1900 /*
1901 * Process outputs
1902 */
1903 if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_L)|(1<<EXTOUT_AC97_R))) {
1904 /* AC'97 Playback Volume */
1905
1906 for (z = 0; z < 2; z++)
1907 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), C_00000000, C_00000000);
1908 }
1909
1910 if (emu->fx8010.extout_mask & ((1<<EXTOUT_TOSLINK_L)|(1<<EXTOUT_TOSLINK_R))) {
1911 /* IEC958 Optical Raw Playback Switch */
1912
1913 for (z = 0; z < 2; z++) {
1914 SWITCH(icode, &ptr, tmp + 0, 8 + z, gpr + z);
1915 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
1916 SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
1917 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_TOSLINK_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
1918#ifdef EMU10K1_CAPTURE_DIGITAL_OUT
1919 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
1920#endif
1921 }
1922
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001923 snd_emu10k1_init_stereo_onoff_control(controls + i++, SNDRV_CTL_NAME_IEC958("Optical Raw ",PLAYBACK,SWITCH), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001924 gpr += 2;
1925 }
1926
1927 if (emu->fx8010.extout_mask & ((1<<EXTOUT_HEADPHONE_L)|(1<<EXTOUT_HEADPHONE_R))) {
1928 /* Headphone Playback Volume */
1929
1930 for (z = 0; z < 2; z++) {
1931 SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4 + z, gpr + 2 + z);
1932 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 2 + z);
1933 SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
1934 OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
1935 VOLUME_OUT(icode, &ptr, EXTOUT_HEADPHONE_L + z, tmp + 0, gpr + z);
1936 }
1937
1938 snd_emu10k1_init_stereo_control(controls + i++, "Headphone Playback Volume", gpr + 0, 0);
1939 controls[i-1].id.index = 1; /* AC'97 can have also Headphone control */
1940 snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone Center Playback Switch", gpr + 2, 0);
1941 controls[i-1].id.index = 1;
1942 snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone LFE Playback Switch", gpr + 3, 0);
1943 controls[i-1].id.index = 1;
1944
1945 gpr += 4;
1946 }
1947
1948 if (emu->fx8010.extout_mask & ((1<<EXTOUT_REAR_L)|(1<<EXTOUT_REAR_R)))
1949 for (z = 0; z < 2; z++)
1950 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000);
1951
1952 if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_REAR_L)|(1<<EXTOUT_AC97_REAR_R)))
1953 for (z = 0; z < 2; z++)
1954 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000);
1955
1956 if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_CENTER)) {
1957#ifndef EMU10K1_CENTER_LFE_FROM_FRONT
1958 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000);
1959 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000);
1960#else
1961 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000);
1962 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000);
1963#endif
1964 }
1965
1966 if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_LFE)) {
1967#ifndef EMU10K1_CENTER_LFE_FROM_FRONT
1968 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000);
1969 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000);
1970#else
1971 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000);
1972 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000);
1973#endif
1974 }
1975
1976#ifndef EMU10K1_CAPTURE_DIGITAL_OUT
1977 for (z = 0; z < 2; z++)
1978 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(capture + z), C_00000000, C_00000000);
1979#endif
1980
1981 if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP))
1982 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
1983
1984 /* EFX capture - capture the 16 EXTINS */
Lee Revell2b637da2005-03-30 13:51:18 +02001985 if (emu->card_capabilities->sblive51) {
1986 /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER
1987 * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording.
1988 *
1989 * Since only 14 of the 16 EXTINs are used, this is not a big problem.
1990 * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
1991 * 0 and 3, then the rest of the EXTINs to the corresponding FX capture
1992 * channel. Multitrack recorders will still see the center/lfe output signal
1993 * on the second and third channels.
1994 */
1995 OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
1996 OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
1997 OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
1998 OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
1999 for (z = 4; z < 14; z++)
2000 OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
2001 } else {
2002 for (z = 0; z < 16; z++)
2003 OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002004 }
Lee Revell2b637da2005-03-30 13:51:18 +02002005
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006
2007 if (gpr > tmp) {
2008 snd_BUG();
2009 err = -EIO;
2010 goto __err;
2011 }
2012 if (i > SND_EMU10K1_GPR_CONTROLS) {
2013 snd_BUG();
2014 err = -EIO;
2015 goto __err;
2016 }
2017
2018 /* clear remaining instruction memory */
2019 while (ptr < 0x200)
2020 OP(icode, &ptr, iACC3, C_00000000, C_00000000, C_00000000, C_00000000);
2021
2022 if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0)
2023 goto __err;
2024 seg = snd_enter_user();
2025 icode->gpr_add_control_count = i;
2026 icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
2027 err = snd_emu10k1_icode_poke(emu, icode);
2028 snd_leave_user(seg);
2029 if (err >= 0)
2030 err = snd_emu10k1_ipcm_poke(emu, ipcm);
2031 __err:
2032 kfree(ipcm);
2033 kfree(controls);
2034 if (icode != NULL) {
Clemens Ladisch4d233592005-09-05 10:35:20 +02002035 kfree((void __force *)icode->gpr_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002036 kfree(icode);
2037 }
2038 return err;
2039}
2040
2041int __devinit snd_emu10k1_init_efx(emu10k1_t *emu)
2042{
2043 if (emu->audigy)
2044 return _snd_emu10k1_audigy_init_efx(emu);
2045 else
2046 return _snd_emu10k1_init_efx(emu);
2047}
2048
2049void snd_emu10k1_free_efx(emu10k1_t *emu)
2050{
2051 /* stop processor */
2052 if (emu->audigy)
2053 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = A_DBG_SINGLE_STEP);
2054 else
2055 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP);
2056}
2057
2058#if 0 // FIXME: who use them?
2059int snd_emu10k1_fx8010_tone_control_activate(emu10k1_t *emu, int output)
2060{
2061 snd_runtime_check(output >= 0 && output < 6, return -EINVAL);
2062 snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 1);
2063 return 0;
2064}
2065
2066int snd_emu10k1_fx8010_tone_control_deactivate(emu10k1_t *emu, int output)
2067{
2068 snd_runtime_check(output >= 0 && output < 6, return -EINVAL);
2069 snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 0);
2070 return 0;
2071}
2072#endif
2073
2074int snd_emu10k1_fx8010_tram_setup(emu10k1_t *emu, u32 size)
2075{
2076 u8 size_reg = 0;
2077
2078 /* size is in samples */
2079 if (size != 0) {
2080 size = (size - 1) >> 13;
2081
2082 while (size) {
2083 size >>= 1;
2084 size_reg++;
2085 }
2086 size = 0x2000 << size_reg;
2087 }
2088 if ((emu->fx8010.etram_pages.bytes / 2) == size)
2089 return 0;
2090 spin_lock_irq(&emu->emu_lock);
2091 outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG);
2092 spin_unlock_irq(&emu->emu_lock);
2093 snd_emu10k1_ptr_write(emu, TCB, 0, 0);
2094 snd_emu10k1_ptr_write(emu, TCBS, 0, 0);
2095 if (emu->fx8010.etram_pages.area != NULL) {
2096 snd_dma_free_pages(&emu->fx8010.etram_pages);
2097 emu->fx8010.etram_pages.area = NULL;
2098 emu->fx8010.etram_pages.bytes = 0;
2099 }
2100
2101 if (size > 0) {
2102 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
2103 size * 2, &emu->fx8010.etram_pages) < 0)
2104 return -ENOMEM;
2105 memset(emu->fx8010.etram_pages.area, 0, size * 2);
2106 snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr);
2107 snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg);
2108 spin_lock_irq(&emu->emu_lock);
2109 outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
2110 spin_unlock_irq(&emu->emu_lock);
2111 }
2112
2113 return 0;
2114}
2115
2116static int snd_emu10k1_fx8010_open(snd_hwdep_t * hw, struct file *file)
2117{
2118 return 0;
2119}
2120
2121static void copy_string(char *dst, char *src, char *null, int idx)
2122{
2123 if (src == NULL)
2124 sprintf(dst, "%s %02X", null, idx);
2125 else
2126 strcpy(dst, src);
2127}
2128
2129static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
2130{
2131 char **fxbus, **extin, **extout;
2132 unsigned short fxbus_mask, extin_mask, extout_mask;
2133 int res;
2134
2135 memset(info, 0, sizeof(info));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002136 info->internal_tram_size = emu->fx8010.itram_size;
2137 info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
2138 fxbus = fxbuses;
2139 extin = emu->audigy ? audigy_ins : creative_ins;
2140 extout = emu->audigy ? audigy_outs : creative_outs;
2141 fxbus_mask = emu->fx8010.fxbus_mask;
2142 extin_mask = emu->fx8010.extin_mask;
2143 extout_mask = emu->fx8010.extout_mask;
2144 for (res = 0; res < 16; res++, fxbus++, extin++, extout++) {
2145 copy_string(info->fxbus_names[res], fxbus_mask & (1 << res) ? *fxbus : NULL, "FXBUS", res);
2146 copy_string(info->extin_names[res], extin_mask & (1 << res) ? *extin : NULL, "Unused", res);
2147 copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res);
2148 }
2149 for (res = 16; res < 32; res++, extout++)
2150 copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res);
2151 info->gpr_controls = emu->fx8010.gpr_count;
2152 return 0;
2153}
2154
2155static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
2156{
2157 emu10k1_t *emu = hw->private_data;
2158 emu10k1_fx8010_info_t *info;
2159 emu10k1_fx8010_code_t *icode;
2160 emu10k1_fx8010_pcm_t *ipcm;
2161 unsigned int addr;
2162 void __user *argp = (void __user *)arg;
2163 int res;
2164
2165 switch (cmd) {
2166 case SNDRV_EMU10K1_IOCTL_INFO:
2167 info = (emu10k1_fx8010_info_t *)kmalloc(sizeof(*info), GFP_KERNEL);
2168 if (!info)
2169 return -ENOMEM;
2170 if ((res = snd_emu10k1_fx8010_info(emu, info)) < 0) {
2171 kfree(info);
2172 return res;
2173 }
2174 if (copy_to_user(argp, info, sizeof(*info))) {
2175 kfree(info);
2176 return -EFAULT;
2177 }
2178 kfree(info);
2179 return 0;
2180 case SNDRV_EMU10K1_IOCTL_CODE_POKE:
2181 if (!capable(CAP_SYS_ADMIN))
2182 return -EPERM;
2183 icode = (emu10k1_fx8010_code_t *)kmalloc(sizeof(*icode), GFP_KERNEL);
2184 if (icode == NULL)
2185 return -ENOMEM;
2186 if (copy_from_user(icode, argp, sizeof(*icode))) {
2187 kfree(icode);
2188 return -EFAULT;
2189 }
2190 res = snd_emu10k1_icode_poke(emu, icode);
2191 kfree(icode);
2192 return res;
2193 case SNDRV_EMU10K1_IOCTL_CODE_PEEK:
2194 icode = (emu10k1_fx8010_code_t *)kmalloc(sizeof(*icode), GFP_KERNEL);
2195 if (icode == NULL)
2196 return -ENOMEM;
2197 if (copy_from_user(icode, argp, sizeof(*icode))) {
2198 kfree(icode);
2199 return -EFAULT;
2200 }
2201 res = snd_emu10k1_icode_peek(emu, icode);
2202 if (res == 0 && copy_to_user(argp, icode, sizeof(*icode))) {
2203 kfree(icode);
2204 return -EFAULT;
2205 }
2206 kfree(icode);
2207 return res;
2208 case SNDRV_EMU10K1_IOCTL_PCM_POKE:
2209 ipcm = (emu10k1_fx8010_pcm_t *)kmalloc(sizeof(*ipcm), GFP_KERNEL);
2210 if (ipcm == NULL)
2211 return -ENOMEM;
2212 if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
2213 kfree(ipcm);
2214 return -EFAULT;
2215 }
2216 res = snd_emu10k1_ipcm_poke(emu, ipcm);
2217 kfree(ipcm);
2218 return res;
2219 case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
2220 ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL);
2221 if (ipcm == NULL)
2222 return -ENOMEM;
2223 if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
2224 kfree(ipcm);
2225 return -EFAULT;
2226 }
2227 res = snd_emu10k1_ipcm_peek(emu, ipcm);
2228 if (res == 0 && copy_to_user(argp, ipcm, sizeof(*ipcm))) {
2229 kfree(ipcm);
2230 return -EFAULT;
2231 }
2232 kfree(ipcm);
2233 return res;
2234 case SNDRV_EMU10K1_IOCTL_TRAM_SETUP:
2235 if (!capable(CAP_SYS_ADMIN))
2236 return -EPERM;
2237 if (get_user(addr, (unsigned int __user *)argp))
2238 return -EFAULT;
2239 down(&emu->fx8010.lock);
2240 res = snd_emu10k1_fx8010_tram_setup(emu, addr);
2241 up(&emu->fx8010.lock);
2242 return res;
2243 case SNDRV_EMU10K1_IOCTL_STOP:
2244 if (!capable(CAP_SYS_ADMIN))
2245 return -EPERM;
2246 if (emu->audigy)
2247 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP);
2248 else
2249 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP);
2250 return 0;
2251 case SNDRV_EMU10K1_IOCTL_CONTINUE:
2252 if (!capable(CAP_SYS_ADMIN))
2253 return -EPERM;
2254 if (emu->audigy)
2255 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = 0);
2256 else
2257 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = 0);
2258 return 0;
2259 case SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER:
2260 if (!capable(CAP_SYS_ADMIN))
2261 return -EPERM;
2262 if (emu->audigy)
2263 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_ZC);
2264 else
2265 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_ZC);
2266 udelay(10);
2267 if (emu->audigy)
2268 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
2269 else
2270 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
2271 return 0;
2272 case SNDRV_EMU10K1_IOCTL_SINGLE_STEP:
2273 if (!capable(CAP_SYS_ADMIN))
2274 return -EPERM;
2275 if (get_user(addr, (unsigned int __user *)argp))
2276 return -EFAULT;
2277 if (addr > 0x1ff)
2278 return -EINVAL;
2279 if (emu->audigy)
2280 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | addr);
2281 else
2282 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | addr);
2283 udelay(10);
2284 if (emu->audigy)
2285 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | A_DBG_STEP_ADDR | addr);
2286 else
2287 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | EMU10K1_DBG_STEP | addr);
2288 return 0;
2289 case SNDRV_EMU10K1_IOCTL_DBG_READ:
2290 if (emu->audigy)
2291 addr = snd_emu10k1_ptr_read(emu, A_DBG, 0);
2292 else
2293 addr = snd_emu10k1_ptr_read(emu, DBG, 0);
2294 if (put_user(addr, (unsigned int __user *)argp))
2295 return -EFAULT;
2296 return 0;
2297 }
2298 return -ENOTTY;
2299}
2300
2301static int snd_emu10k1_fx8010_release(snd_hwdep_t * hw, struct file *file)
2302{
2303 return 0;
2304}
2305
2306int __devinit snd_emu10k1_fx8010_new(emu10k1_t *emu, int device, snd_hwdep_t ** rhwdep)
2307{
2308 snd_hwdep_t *hw;
2309 int err;
2310
2311 if (rhwdep)
2312 *rhwdep = NULL;
2313 if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0)
2314 return err;
2315 strcpy(hw->name, "EMU10K1 (FX8010)");
2316 hw->iface = SNDRV_HWDEP_IFACE_EMU10K1;
2317 hw->ops.open = snd_emu10k1_fx8010_open;
2318 hw->ops.ioctl = snd_emu10k1_fx8010_ioctl;
2319 hw->ops.release = snd_emu10k1_fx8010_release;
2320 hw->private_data = emu;
2321 if (rhwdep)
2322 *rhwdep = hw;
2323 return 0;
2324}