blob: 03e8c16789527c217880b59a25cbb20e1a3c6223 [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:
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200367 if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) {
368 change = -EIO;
369 goto __error;
370 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700371 for (j = 0; j < 5; j++)
372 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]);
373 break;
374 case EMU10K1_GPR_TRANSLATION_TREBLE:
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200375 if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) {
376 change = -EIO;
377 goto __error;
378 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 for (j = 0; j < 5; j++)
380 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]);
381 break;
382 case EMU10K1_GPR_TRANSLATION_ONOFF:
383 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, onoff_table[val]);
384 break;
385 }
386 }
387 __error:
388 spin_unlock_irqrestore(&emu->reg_lock, flags);
389 return change;
390}
391
392/*
393 * Interrupt handler
394 */
395
396static void snd_emu10k1_fx8010_interrupt(emu10k1_t *emu)
397{
398 snd_emu10k1_fx8010_irq_t *irq, *nirq;
399
400 irq = emu->fx8010.irq_handlers;
401 while (irq) {
402 nirq = irq->next; /* irq ptr can be removed from list */
403 if (snd_emu10k1_ptr_read(emu, emu->gpr_base + irq->gpr_running, 0) & 0xffff0000) {
404 if (irq->handler)
405 irq->handler(emu, irq->private_data);
406 snd_emu10k1_ptr_write(emu, emu->gpr_base + irq->gpr_running, 0, 1);
407 }
408 irq = nirq;
409 }
410}
411
412int snd_emu10k1_fx8010_register_irq_handler(emu10k1_t *emu,
413 snd_fx8010_irq_handler_t *handler,
414 unsigned char gpr_running,
415 void *private_data,
416 snd_emu10k1_fx8010_irq_t **r_irq)
417{
418 snd_emu10k1_fx8010_irq_t *irq;
419 unsigned long flags;
420
Linus Torvalds1da177e2005-04-16 15:20:36 -0700421 irq = kmalloc(sizeof(*irq), GFP_ATOMIC);
422 if (irq == NULL)
423 return -ENOMEM;
424 irq->handler = handler;
425 irq->gpr_running = gpr_running;
426 irq->private_data = private_data;
427 irq->next = NULL;
428 spin_lock_irqsave(&emu->fx8010.irq_lock, flags);
429 if (emu->fx8010.irq_handlers == NULL) {
430 emu->fx8010.irq_handlers = irq;
431 emu->dsp_interrupt = snd_emu10k1_fx8010_interrupt;
432 snd_emu10k1_intr_enable(emu, INTE_FXDSPENABLE);
433 } else {
434 irq->next = emu->fx8010.irq_handlers;
435 emu->fx8010.irq_handlers = irq;
436 }
437 spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
438 if (r_irq)
439 *r_irq = irq;
440 return 0;
441}
442
443int snd_emu10k1_fx8010_unregister_irq_handler(emu10k1_t *emu,
444 snd_emu10k1_fx8010_irq_t *irq)
445{
446 snd_emu10k1_fx8010_irq_t *tmp;
447 unsigned long flags;
448
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 spin_lock_irqsave(&emu->fx8010.irq_lock, flags);
450 if ((tmp = emu->fx8010.irq_handlers) == irq) {
451 emu->fx8010.irq_handlers = tmp->next;
452 if (emu->fx8010.irq_handlers == NULL) {
453 snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
454 emu->dsp_interrupt = NULL;
455 }
456 } else {
457 while (tmp && tmp->next != irq)
458 tmp = tmp->next;
459 if (tmp)
460 tmp->next = tmp->next->next;
461 }
462 spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
463 kfree(irq);
464 return 0;
465}
466
467/*************************************************************************
468 * EMU10K1 effect manager
469 *************************************************************************/
470
471static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
472 u32 op, u32 r, u32 a, u32 x, u32 y)
473{
474 u_int32_t *code;
475 snd_assert(*ptr < 512, return);
Clemens Ladisch4d233592005-09-05 10:35:20 +0200476 code = (u_int32_t __force *)icode->code + (*ptr) * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477 set_bit(*ptr, icode->code_valid);
478 code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
479 code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
480 (*ptr)++;
481}
482
483#define OP(icode, ptr, op, r, a, x, y) \
484 snd_emu10k1_write_op(icode, ptr, op, r, a, x, y)
485
486static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
487 u32 op, u32 r, u32 a, u32 x, u32 y)
488{
489 u_int32_t *code;
490 snd_assert(*ptr < 1024, return);
Clemens Ladisch4d233592005-09-05 10:35:20 +0200491 code = (u_int32_t __force *)icode->code + (*ptr) * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 set_bit(*ptr, icode->code_valid);
493 code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
494 code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
495 (*ptr)++;
496}
497
498#define A_OP(icode, ptr, op, r, a, x, y) \
499 snd_emu10k1_audigy_write_op(icode, ptr, op, r, a, x, y)
500
501static void snd_emu10k1_efx_write(emu10k1_t *emu, unsigned int pc, unsigned int data)
502{
503 pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
504 snd_emu10k1_ptr_write(emu, pc, 0, data);
505}
506
507unsigned int snd_emu10k1_efx_read(emu10k1_t *emu, unsigned int pc)
508{
509 pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
510 return snd_emu10k1_ptr_read(emu, pc, 0);
511}
512
513static int snd_emu10k1_gpr_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
514{
515 int gpr;
516 u32 val;
517
518 for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
519 if (!test_bit(gpr, icode->gpr_valid))
520 continue;
521 if (get_user(val, &icode->gpr_map[gpr]))
522 return -EFAULT;
523 snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val);
524 }
525 return 0;
526}
527
528static int snd_emu10k1_gpr_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
529{
530 int gpr;
531 u32 val;
532
533 for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
534 set_bit(gpr, icode->gpr_valid);
535 val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0);
536 if (put_user(val, &icode->gpr_map[gpr]))
537 return -EFAULT;
538 }
539 return 0;
540}
541
542static int snd_emu10k1_tram_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
543{
544 int tram;
545 u32 addr, val;
546
547 for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
548 if (!test_bit(tram, icode->tram_valid))
549 continue;
550 if (get_user(val, &icode->tram_data_map[tram]) ||
551 get_user(addr, &icode->tram_addr_map[tram]))
552 return -EFAULT;
553 snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val);
554 if (!emu->audigy) {
555 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr);
556 } else {
557 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr << 12);
558 snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, addr >> 20);
559 }
560 }
561 return 0;
562}
563
564static int snd_emu10k1_tram_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
565{
566 int tram;
567 u32 val, addr;
568
569 memset(icode->tram_valid, 0, sizeof(icode->tram_valid));
570 for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
571 set_bit(tram, icode->tram_valid);
572 val = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0);
573 if (!emu->audigy) {
574 addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0);
575 } else {
576 addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12;
577 addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20;
578 }
579 if (put_user(val, &icode->tram_data_map[tram]) ||
580 put_user(addr, &icode->tram_addr_map[tram]))
581 return -EFAULT;
582 }
583 return 0;
584}
585
586static int snd_emu10k1_code_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
587{
588 u32 pc, lo, hi;
589
590 for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
591 if (!test_bit(pc / 2, icode->code_valid))
592 continue;
593 if (get_user(lo, &icode->code[pc + 0]) ||
594 get_user(hi, &icode->code[pc + 1]))
595 return -EFAULT;
596 snd_emu10k1_efx_write(emu, pc + 0, lo);
597 snd_emu10k1_efx_write(emu, pc + 1, hi);
598 }
599 return 0;
600}
601
602static int snd_emu10k1_code_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
603{
604 u32 pc;
605
606 memset(icode->code_valid, 0, sizeof(icode->code_valid));
607 for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
608 set_bit(pc / 2, icode->code_valid);
609 if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0]))
610 return -EFAULT;
611 if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1]))
612 return -EFAULT;
613 }
614 return 0;
615}
616
617static snd_emu10k1_fx8010_ctl_t *snd_emu10k1_look_for_ctl(emu10k1_t *emu, snd_ctl_elem_id_t *id)
618{
619 snd_emu10k1_fx8010_ctl_t *ctl;
620 snd_kcontrol_t *kcontrol;
621 struct list_head *list;
622
623 list_for_each(list, &emu->fx8010.gpr_ctl) {
624 ctl = emu10k1_gpr_ctl(list);
625 kcontrol = ctl->kcontrol;
626 if (kcontrol->id.iface == id->iface &&
627 !strcmp(kcontrol->id.name, id->name) &&
628 kcontrol->id.index == id->index)
629 return ctl;
630 }
631 return NULL;
632}
633
634static int snd_emu10k1_verify_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
635{
636 unsigned int i;
637 snd_ctl_elem_id_t __user *_id;
638 snd_ctl_elem_id_t id;
639 emu10k1_fx8010_control_gpr_t __user *_gctl;
640 emu10k1_fx8010_control_gpr_t *gctl;
641 int err;
642
643 for (i = 0, _id = icode->gpr_del_controls;
644 i < icode->gpr_del_control_count; i++, _id++) {
645 if (copy_from_user(&id, _id, sizeof(id)))
646 return -EFAULT;
647 if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)
648 return -ENOENT;
649 }
650 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
651 if (! gctl)
652 return -ENOMEM;
653 err = 0;
654 for (i = 0, _gctl = icode->gpr_add_controls;
655 i < icode->gpr_add_control_count; i++, _gctl++) {
656 if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
657 err = -EFAULT;
658 goto __error;
659 }
660 if (snd_emu10k1_look_for_ctl(emu, &gctl->id))
661 continue;
662 down_read(&emu->card->controls_rwsem);
663 if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) {
664 up_read(&emu->card->controls_rwsem);
665 err = -EEXIST;
666 goto __error;
667 }
668 up_read(&emu->card->controls_rwsem);
669 if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
670 gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
671 err = -EINVAL;
672 goto __error;
673 }
674 }
675 for (i = 0, _gctl = icode->gpr_list_controls;
676 i < icode->gpr_list_control_count; i++, _gctl++) {
677 /* FIXME: we need to check the WRITE access */
678 if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
679 err = -EFAULT;
680 goto __error;
681 }
682 }
683 __error:
684 kfree(gctl);
685 return err;
686}
687
688static void snd_emu10k1_ctl_private_free(snd_kcontrol_t *kctl)
689{
690 snd_emu10k1_fx8010_ctl_t *ctl;
691
692 ctl = (snd_emu10k1_fx8010_ctl_t *)kctl->private_value;
693 kctl->private_value = 0;
694 list_del(&ctl->list);
695 kfree(ctl);
696}
697
698static int snd_emu10k1_add_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
699{
700 unsigned int i, j;
701 emu10k1_fx8010_control_gpr_t __user *_gctl;
702 emu10k1_fx8010_control_gpr_t *gctl;
703 snd_emu10k1_fx8010_ctl_t *ctl, *nctl;
704 snd_kcontrol_new_t knew;
705 snd_kcontrol_t *kctl;
706 snd_ctl_elem_value_t *val;
707 int err = 0;
708
709 val = (snd_ctl_elem_value_t *)kmalloc(sizeof(*val), GFP_KERNEL);
710 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
711 nctl = kmalloc(sizeof(*nctl), GFP_KERNEL);
712 if (!val || !gctl || !nctl) {
713 err = -ENOMEM;
714 goto __error;
715 }
716
717 for (i = 0, _gctl = icode->gpr_add_controls;
718 i < icode->gpr_add_control_count; i++, _gctl++) {
719 if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
720 err = -EFAULT;
721 goto __error;
722 }
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200723 if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
724 gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
725 err = -EINVAL;
726 goto __error;
727 }
728 if (! gctl->id.name[0]) {
729 err = -EINVAL;
730 goto __error;
731 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id);
733 memset(&knew, 0, sizeof(knew));
734 knew.iface = gctl->id.iface;
735 knew.name = gctl->id.name;
736 knew.index = gctl->id.index;
737 knew.device = gctl->id.device;
738 knew.subdevice = gctl->id.subdevice;
739 knew.info = snd_emu10k1_gpr_ctl_info;
740 knew.get = snd_emu10k1_gpr_ctl_get;
741 knew.put = snd_emu10k1_gpr_ctl_put;
742 memset(nctl, 0, sizeof(*nctl));
743 nctl->vcount = gctl->vcount;
744 nctl->count = gctl->count;
745 for (j = 0; j < 32; j++) {
746 nctl->gpr[j] = gctl->gpr[j];
747 nctl->value[j] = ~gctl->value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
748 val->value.integer.value[j] = gctl->value[j];
749 }
750 nctl->min = gctl->min;
751 nctl->max = gctl->max;
752 nctl->translation = gctl->translation;
753 if (ctl == NULL) {
754 ctl = (snd_emu10k1_fx8010_ctl_t *)kmalloc(sizeof(*ctl), GFP_KERNEL);
755 if (ctl == NULL) {
756 err = -ENOMEM;
757 goto __error;
758 }
759 knew.private_value = (unsigned long)ctl;
760 *ctl = *nctl;
761 if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) {
762 kfree(ctl);
763 goto __error;
764 }
765 kctl->private_free = snd_emu10k1_ctl_private_free;
766 ctl->kcontrol = kctl;
767 list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl);
768 } else {
769 /* overwrite */
770 nctl->list = ctl->list;
771 nctl->kcontrol = ctl->kcontrol;
772 *ctl = *nctl;
773 snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
774 SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id);
775 }
776 snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val);
777 }
778 __error:
779 kfree(nctl);
780 kfree(gctl);
781 kfree(val);
782 return err;
783}
784
785static int snd_emu10k1_del_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
786{
787 unsigned int i;
788 snd_ctl_elem_id_t id;
789 snd_ctl_elem_id_t __user *_id;
790 snd_emu10k1_fx8010_ctl_t *ctl;
791 snd_card_t *card = emu->card;
792
793 for (i = 0, _id = icode->gpr_del_controls;
794 i < icode->gpr_del_control_count; i++, _id++) {
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200795 if (copy_from_user(&id, _id, sizeof(id)))
796 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 down_write(&card->controls_rwsem);
798 ctl = snd_emu10k1_look_for_ctl(emu, &id);
799 if (ctl)
800 snd_ctl_remove(card, ctl->kcontrol);
801 up_write(&card->controls_rwsem);
802 }
803 return 0;
804}
805
806static int snd_emu10k1_list_controls(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
807{
808 unsigned int i = 0, j;
809 unsigned int total = 0;
810 emu10k1_fx8010_control_gpr_t *gctl;
811 emu10k1_fx8010_control_gpr_t __user *_gctl;
812 snd_emu10k1_fx8010_ctl_t *ctl;
813 snd_ctl_elem_id_t *id;
814 struct list_head *list;
815
816 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
817 if (! gctl)
818 return -ENOMEM;
819
820 _gctl = icode->gpr_list_controls;
821 list_for_each(list, &emu->fx8010.gpr_ctl) {
822 ctl = emu10k1_gpr_ctl(list);
823 total++;
824 if (_gctl && i < icode->gpr_list_control_count) {
825 memset(gctl, 0, sizeof(*gctl));
826 id = &ctl->kcontrol->id;
827 gctl->id.iface = id->iface;
828 strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
829 gctl->id.index = id->index;
830 gctl->id.device = id->device;
831 gctl->id.subdevice = id->subdevice;
832 gctl->vcount = ctl->vcount;
833 gctl->count = ctl->count;
834 for (j = 0; j < 32; j++) {
835 gctl->gpr[j] = ctl->gpr[j];
836 gctl->value[j] = ctl->value[j];
837 }
838 gctl->min = ctl->min;
839 gctl->max = ctl->max;
840 gctl->translation = ctl->translation;
841 if (copy_to_user(_gctl, gctl, sizeof(*gctl))) {
842 kfree(gctl);
843 return -EFAULT;
844 }
845 _gctl++;
846 i++;
847 }
848 }
849 icode->gpr_list_control_total = total;
850 kfree(gctl);
851 return 0;
852}
853
854static int snd_emu10k1_icode_poke(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
855{
856 int err = 0;
857
858 down(&emu->fx8010.lock);
859 if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0)
860 goto __error;
861 strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
862 /* stop FX processor - this may be dangerous, but it's better to miss
863 some samples than generate wrong ones - [jk] */
864 if (emu->audigy)
865 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP);
866 else
867 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);
868 /* ok, do the main job */
869 if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 ||
870 (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 ||
871 (err = snd_emu10k1_tram_poke(emu, icode)) < 0 ||
872 (err = snd_emu10k1_code_poke(emu, icode)) < 0 ||
873 (err = snd_emu10k1_add_controls(emu, icode)) < 0)
874 goto __error;
875 /* start FX processor when the DSP code is updated */
876 if (emu->audigy)
877 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
878 else
879 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
880 __error:
881 up(&emu->fx8010.lock);
882 return err;
883}
884
885static int snd_emu10k1_icode_peek(emu10k1_t *emu, emu10k1_fx8010_code_t *icode)
886{
887 int err;
888
889 down(&emu->fx8010.lock);
890 strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name));
891 /* ok, do the main job */
892 err = snd_emu10k1_gpr_peek(emu, icode);
893 if (err >= 0)
894 err = snd_emu10k1_tram_peek(emu, icode);
895 if (err >= 0)
896 err = snd_emu10k1_code_peek(emu, icode);
897 if (err >= 0)
898 err = snd_emu10k1_list_controls(emu, icode);
899 up(&emu->fx8010.lock);
900 return err;
901}
902
903static int snd_emu10k1_ipcm_poke(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
904{
905 unsigned int i;
906 int err = 0;
907 snd_emu10k1_fx8010_pcm_t *pcm;
908
909 if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
910 return -EINVAL;
911 if (ipcm->channels > 32)
912 return -EINVAL;
913 pcm = &emu->fx8010.pcm[ipcm->substream];
914 down(&emu->fx8010.lock);
915 spin_lock_irq(&emu->reg_lock);
916 if (pcm->opened) {
917 err = -EBUSY;
918 goto __error;
919 }
920 if (ipcm->channels == 0) { /* remove */
921 pcm->valid = 0;
922 } else {
923 /* FIXME: we need to add universal code to the PCM transfer routine */
924 if (ipcm->channels != 2) {
925 err = -EINVAL;
926 goto __error;
927 }
928 pcm->valid = 1;
929 pcm->opened = 0;
930 pcm->channels = ipcm->channels;
931 pcm->tram_start = ipcm->tram_start;
932 pcm->buffer_size = ipcm->buffer_size;
933 pcm->gpr_size = ipcm->gpr_size;
934 pcm->gpr_count = ipcm->gpr_count;
935 pcm->gpr_tmpcount = ipcm->gpr_tmpcount;
936 pcm->gpr_ptr = ipcm->gpr_ptr;
937 pcm->gpr_trigger = ipcm->gpr_trigger;
938 pcm->gpr_running = ipcm->gpr_running;
939 for (i = 0; i < pcm->channels; i++)
940 pcm->etram[i] = ipcm->etram[i];
941 }
942 __error:
943 spin_unlock_irq(&emu->reg_lock);
944 up(&emu->fx8010.lock);
945 return err;
946}
947
948static int snd_emu10k1_ipcm_peek(emu10k1_t *emu, emu10k1_fx8010_pcm_t *ipcm)
949{
950 unsigned int i;
951 int err = 0;
952 snd_emu10k1_fx8010_pcm_t *pcm;
953
954 if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
955 return -EINVAL;
956 pcm = &emu->fx8010.pcm[ipcm->substream];
957 down(&emu->fx8010.lock);
958 spin_lock_irq(&emu->reg_lock);
959 ipcm->channels = pcm->channels;
960 ipcm->tram_start = pcm->tram_start;
961 ipcm->buffer_size = pcm->buffer_size;
962 ipcm->gpr_size = pcm->gpr_size;
963 ipcm->gpr_ptr = pcm->gpr_ptr;
964 ipcm->gpr_count = pcm->gpr_count;
965 ipcm->gpr_tmpcount = pcm->gpr_tmpcount;
966 ipcm->gpr_trigger = pcm->gpr_trigger;
967 ipcm->gpr_running = pcm->gpr_running;
968 for (i = 0; i < pcm->channels; i++)
969 ipcm->etram[i] = pcm->etram[i];
970 ipcm->res1 = ipcm->res2 = 0;
971 ipcm->pad = 0;
972 spin_unlock_irq(&emu->reg_lock);
973 up(&emu->fx8010.lock);
974 return err;
975}
976
Mikael Magnussonedf8e452005-09-13 11:32:58 +0200977#define SND_EMU10K1_GPR_CONTROLS 44
978#define SND_EMU10K1_INPUTS 12
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979#define SND_EMU10K1_PLAYBACK_CHANNELS 8
980#define SND_EMU10K1_CAPTURE_CHANNELS 4
981
982static void __devinit snd_emu10k1_init_mono_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
983{
984 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
985 strcpy(ctl->id.name, name);
986 ctl->vcount = ctl->count = 1;
987 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
988 ctl->min = 0;
989 ctl->max = 100;
990 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
991}
992
993static void __devinit snd_emu10k1_init_stereo_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
994{
995 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
996 strcpy(ctl->id.name, name);
997 ctl->vcount = ctl->count = 2;
998 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
999 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
1000 ctl->min = 0;
1001 ctl->max = 100;
1002 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
1003}
1004
1005static void __devinit snd_emu10k1_init_mono_onoff_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
1006{
1007 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1008 strcpy(ctl->id.name, name);
1009 ctl->vcount = ctl->count = 1;
1010 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1011 ctl->min = 0;
1012 ctl->max = 1;
1013 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
1014}
1015
1016static void __devinit snd_emu10k1_init_stereo_onoff_control(emu10k1_fx8010_control_gpr_t *ctl, const char *name, int gpr, int defval)
1017{
1018 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1019 strcpy(ctl->id.name, name);
1020 ctl->vcount = ctl->count = 2;
1021 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1022 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
1023 ctl->min = 0;
1024 ctl->max = 1;
1025 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
1026}
1027
1028
1029/*
1030 * initial DSP configuration for Audigy
1031 */
1032
1033static int __devinit _snd_emu10k1_audigy_init_efx(emu10k1_t *emu)
1034{
1035 int err, i, z, gpr, nctl;
1036 const int playback = 10;
1037 const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
1038 const int stereo_mix = capture + 2;
1039 const int tmp = 0x88;
1040 u32 ptr;
1041 emu10k1_fx8010_code_t *icode = NULL;
1042 emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;
1043 u32 *gpr_map;
1044 mm_segment_t seg;
1045
1046 spin_lock_init(&emu->fx8010.irq_lock);
1047 INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
1048
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001049 if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL ||
Linus Torvalds1da177e2005-04-16 15:20:36 -07001050 (icode->gpr_map = (u_int32_t __user *)kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
1051 (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {
1052 err = -ENOMEM;
1053 goto __err;
1054 }
Clemens Ladisch4d233592005-09-05 10:35:20 +02001055 gpr_map = (u32 __force *)icode->gpr_map;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056
1057 icode->tram_data_map = icode->gpr_map + 512;
1058 icode->tram_addr_map = icode->tram_data_map + 256;
1059 icode->code = icode->tram_addr_map + 256;
1060
1061 /* clear free GPRs */
1062 for (i = 0; i < 512; i++)
1063 set_bit(i, icode->gpr_valid);
1064
1065 /* clear TRAM data & address lines */
1066 for (i = 0; i < 256; i++)
1067 set_bit(i, icode->tram_valid);
1068
1069 strcpy(icode->name, "Audigy DSP code for ALSA");
1070 ptr = 0;
1071 nctl = 0;
1072 gpr = stereo_mix + 10;
1073
1074 /* stop FX processor */
1075 snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
1076
1077 /* PCM front Playback Volume (independent from stereo mix) */
1078 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
1079 A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
1080 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100);
1081 gpr += 2;
1082
1083 /* PCM Surround Playback (independent from stereo mix) */
1084 A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR));
1085 A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
1086 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100);
1087 gpr += 2;
1088
1089 /* PCM Side Playback (independent from stereo mix) */
Lee Revell2b637da2005-03-30 13:51:18 +02001090 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001091 A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
1092 A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
1093 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
1094 gpr += 2;
1095 }
1096
1097 /* PCM Center Playback (independent from stereo mix) */
1098 A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER));
1099 snd_emu10k1_init_mono_control(&controls[nctl++], "PCM Center Playback Volume", gpr, 100);
1100 gpr++;
1101
1102 /* PCM LFE Playback (independent from stereo mix) */
1103 A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LFE));
1104 snd_emu10k1_init_mono_control(&controls[nctl++], "PCM LFE Playback Volume", gpr, 100);
1105 gpr++;
1106
1107 /*
1108 * Stereo Mix
1109 */
1110 /* Wave (PCM) Playback Volume (will be renamed later) */
1111 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
1112 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
1113 snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
1114 gpr += 2;
1115
1116 /* Synth Playback */
1117 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
1118 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
1119 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100);
1120 gpr += 2;
1121
1122 /* Wave (PCM) Capture */
1123 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
1124 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
1125 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0);
1126 gpr += 2;
1127
1128 /* Synth Capture */
1129 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
1130 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
1131 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0);
1132 gpr += 2;
1133
1134 /*
1135 * inputs
1136 */
1137#define A_ADD_VOLUME_IN(var,vol,input) \
1138A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
1139
1140 /* AC'97 Playback Volume - used only for mic (renamed later) */
1141 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L);
1142 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R);
1143 snd_emu10k1_init_stereo_control(&controls[nctl++], "AMic Playback Volume", gpr, 0);
1144 gpr += 2;
1145 /* AC'97 Capture Volume - used only for mic */
1146 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AC97_L);
1147 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AC97_R);
1148 snd_emu10k1_init_stereo_control(&controls[nctl++], "Mic Capture Volume", gpr, 0);
1149 gpr += 2;
1150
1151 /* mic capture buffer */
1152 A_OP(icode, &ptr, iINTERP, A_EXTOUT(A_EXTOUT_MIC_CAP), A_EXTIN(A_EXTIN_AC97_L), 0xcd, A_EXTIN(A_EXTIN_AC97_R));
1153
1154 /* Audigy CD Playback Volume */
1155 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L);
1156 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R);
1157 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001158 emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001159 gpr, 0);
1160 gpr += 2;
1161 /* Audigy CD Capture Volume */
1162 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
1163 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
1164 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001165 emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001166 gpr, 0);
1167 gpr += 2;
1168
1169 /* Optical SPDIF Playback Volume */
1170 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_OPT_SPDIF_L);
1171 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001172 snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173 gpr += 2;
1174 /* Optical SPDIF Capture Volume */
1175 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_OPT_SPDIF_L);
1176 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001177 snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",CAPTURE,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178 gpr += 2;
1179
1180 /* Line2 Playback Volume */
1181 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L);
1182 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R);
1183 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001184 emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 gpr, 0);
1186 gpr += 2;
1187 /* Line2 Capture Volume */
1188 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L);
1189 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R);
1190 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001191 emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 gpr, 0);
1193 gpr += 2;
1194
1195 /* Philips ADC Playback Volume */
1196 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_ADC_L);
1197 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_ADC_R);
1198 snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Playback Volume", gpr, 0);
1199 gpr += 2;
1200 /* Philips ADC Capture Volume */
1201 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_ADC_L);
1202 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_ADC_R);
1203 snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Capture Volume", gpr, 0);
1204 gpr += 2;
1205
1206 /* Aux2 Playback Volume */
1207 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L);
1208 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R);
1209 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001210 emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211 gpr, 0);
1212 gpr += 2;
1213 /* Aux2 Capture Volume */
1214 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L);
1215 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R);
1216 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001217 emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218 gpr, 0);
1219 gpr += 2;
1220
1221 /* Stereo Mix Front Playback Volume */
1222 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_GPR(playback), A_GPR(gpr), A_GPR(stereo_mix));
1223 A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_GPR(playback+1), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1224 snd_emu10k1_init_stereo_control(&controls[nctl++], "Front Playback Volume", gpr, 100);
1225 gpr += 2;
1226
1227 /* Stereo Mix Surround Playback */
1228 A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_GPR(playback+2), A_GPR(gpr), A_GPR(stereo_mix));
1229 A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_GPR(playback+3), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1230 snd_emu10k1_init_stereo_control(&controls[nctl++], "Surround Playback Volume", gpr, 0);
1231 gpr += 2;
1232
1233 /* Stereo Mix Center Playback */
1234 /* Center = sub = Left/2 + Right/2 */
1235 A_OP(icode, &ptr, iINTERP, A_GPR(tmp), A_GPR(stereo_mix), 0xcd, A_GPR(stereo_mix+1));
1236 A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_GPR(playback+4), A_GPR(gpr), A_GPR(tmp));
1237 snd_emu10k1_init_mono_control(&controls[nctl++], "Center Playback Volume", gpr, 0);
1238 gpr++;
1239
1240 /* Stereo Mix LFE Playback */
1241 A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp));
1242 snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
1243 gpr++;
1244
Lee Revell2b637da2005-03-30 13:51:18 +02001245 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001246 /* Stereo Mix Side Playback */
1247 A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
1248 A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1249 snd_emu10k1_init_stereo_control(&controls[nctl++], "Side Playback Volume", gpr, 0);
1250 gpr += 2;
1251 }
1252
1253 /*
1254 * outputs
1255 */
1256#define A_PUT_OUTPUT(out,src) A_OP(icode, &ptr, iACC3, A_EXTOUT(out), A_C_00000000, A_C_00000000, A_GPR(src))
1257#define A_PUT_STEREO_OUTPUT(out1,out2,src) \
1258 {A_PUT_OUTPUT(out1,src); A_PUT_OUTPUT(out2,src+1);}
1259
1260#define _A_SWITCH(icode, ptr, dst, src, sw) \
1261 A_OP((icode), ptr, iMACINT0, dst, A_C_00000000, src, sw);
1262#define A_SWITCH(icode, ptr, dst, src, sw) \
1263 _A_SWITCH(icode, ptr, A_GPR(dst), A_GPR(src), A_GPR(sw))
1264#define _A_SWITCH_NEG(icode, ptr, dst, src) \
1265 A_OP((icode), ptr, iANDXOR, dst, src, A_C_00000001, A_C_00000001);
1266#define A_SWITCH_NEG(icode, ptr, dst, src) \
1267 _A_SWITCH_NEG(icode, ptr, A_GPR(dst), A_GPR(src))
1268
1269
1270 /*
1271 * Process tone control
1272 */
1273 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), A_GPR(playback + 0), A_C_00000000, A_C_00000000); /* left */
1274 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), A_GPR(playback + 1), A_C_00000000, A_C_00000000); /* right */
1275 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 */
1276 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 */
1277 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
1278 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 +02001279 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 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 */
1281 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 */
1282 }
1283
1284
1285 ctl = &controls[nctl + 0];
1286 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1287 strcpy(ctl->id.name, "Tone Control - Bass");
1288 ctl->vcount = 2;
1289 ctl->count = 10;
1290 ctl->min = 0;
1291 ctl->max = 40;
1292 ctl->value[0] = ctl->value[1] = 20;
1293 ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
1294 ctl = &controls[nctl + 1];
1295 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1296 strcpy(ctl->id.name, "Tone Control - Treble");
1297 ctl->vcount = 2;
1298 ctl->count = 10;
1299 ctl->min = 0;
1300 ctl->max = 40;
1301 ctl->value[0] = ctl->value[1] = 20;
1302 ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
1303
1304#define BASS_GPR 0x8c
1305#define TREBLE_GPR 0x96
1306
1307 for (z = 0; z < 5; z++) {
1308 int j;
1309 for (j = 0; j < 2; j++) {
1310 controls[nctl + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j;
1311 controls[nctl + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
1312 }
1313 }
1314 for (z = 0; z < 4; z++) { /* front/rear/center-lfe/side */
1315 int j, k, l, d;
1316 for (j = 0; j < 2; j++) { /* left/right */
1317 k = 0xb0 + (z * 8) + (j * 4);
1318 l = 0xe0 + (z * 8) + (j * 4);
1319 d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j;
1320
1321 A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(d), A_GPR(BASS_GPR + 0 + j));
1322 A_OP(icode, &ptr, iMACMV, A_GPR(k+1), A_GPR(k), A_GPR(k+1), A_GPR(BASS_GPR + 4 + j));
1323 A_OP(icode, &ptr, iMACMV, A_GPR(k), A_GPR(d), A_GPR(k), A_GPR(BASS_GPR + 2 + j));
1324 A_OP(icode, &ptr, iMACMV, A_GPR(k+3), A_GPR(k+2), A_GPR(k+3), A_GPR(BASS_GPR + 8 + j));
1325 A_OP(icode, &ptr, iMAC0, A_GPR(k+2), A_GPR_ACCU, A_GPR(k+2), A_GPR(BASS_GPR + 6 + j));
1326 A_OP(icode, &ptr, iACC3, A_GPR(k+2), A_GPR(k+2), A_GPR(k+2), A_C_00000000);
1327
1328 A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(k+2), A_GPR(TREBLE_GPR + 0 + j));
1329 A_OP(icode, &ptr, iMACMV, A_GPR(l+1), A_GPR(l), A_GPR(l+1), A_GPR(TREBLE_GPR + 4 + j));
1330 A_OP(icode, &ptr, iMACMV, A_GPR(l), A_GPR(k+2), A_GPR(l), A_GPR(TREBLE_GPR + 2 + j));
1331 A_OP(icode, &ptr, iMACMV, A_GPR(l+3), A_GPR(l+2), A_GPR(l+3), A_GPR(TREBLE_GPR + 8 + j));
1332 A_OP(icode, &ptr, iMAC0, A_GPR(l+2), A_GPR_ACCU, A_GPR(l+2), A_GPR(TREBLE_GPR + 6 + j));
1333 A_OP(icode, &ptr, iMACINT0, A_GPR(l+2), A_C_00000000, A_GPR(l+2), A_C_00000010);
1334
1335 A_OP(icode, &ptr, iACC3, A_GPR(d), A_GPR(l+2), A_C_00000000, A_C_00000000);
1336
1337 if (z == 2) /* center */
1338 break;
1339 }
1340 }
1341 nctl += 2;
1342
1343#undef BASS_GPR
1344#undef TREBLE_GPR
1345
1346 for (z = 0; z < 8; z++) {
1347 A_SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
1348 A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
1349 A_SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
1350 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1351 }
1352 snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0);
1353 gpr += 2;
1354
1355 /* Master volume (will be renamed later) */
1356 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));
1357 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));
1358 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));
1359 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));
1360 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));
1361 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));
1362 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));
1363 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));
1364 snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
1365 gpr += 2;
1366
1367 /* analog speakers */
1368 A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1369 A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
1370 A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
1371 A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
Lee Revell2b637da2005-03-30 13:51:18 +02001372 if (emu->card_capabilities->spk71)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373 A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
1374
1375 /* headphone */
1376 A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1377
1378 /* digital outputs */
1379 /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
1380
1381 /* IEC958 Optical Raw Playback Switch */
1382 gpr_map[gpr++] = 0;
1383 gpr_map[gpr++] = 0x1008;
1384 gpr_map[gpr++] = 0xffff0000;
1385 for (z = 0; z < 2; z++) {
1386 A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000);
1387 A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001);
1388 A_OP(icode, &ptr, iACC3, A_GPR(tmp + 2), A_C_00000000, A_C_00010000, A_GPR(tmp + 2));
1389 A_OP(icode, &ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_GPR(gpr - 1), A_C_00000000);
1390 A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z);
1391 A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
1392 A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
1393 if ((z==1) && (emu->card_capabilities->spdif_bug)) {
1394 /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */
Takashi Iwai99b359b2005-10-20 18:26:44 +02001395 snd_printk(KERN_INFO "Installing spdif_bug patch: %s\n", emu->card_capabilities->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396 A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000);
1397 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1398 } else {
1399 A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1400 }
1401 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001402 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 -07001403 gpr += 2;
1404
1405 A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
1406 A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
1407 A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
1408
1409 /* ADC buffer */
1410#ifdef EMU10K1_CAPTURE_DIGITAL_OUT
1411 A_PUT_STEREO_OUTPUT(A_EXTOUT_ADC_CAP_L, A_EXTOUT_ADC_CAP_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1412#else
1413 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture);
1414 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
1415#endif
1416
1417 /* EFX capture - capture the 16 EXTINs */
1418 for (z = 0; z < 16; z++) {
1419 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
1420 }
1421
1422 /*
1423 * ok, set up done..
1424 */
1425
1426 if (gpr > tmp) {
1427 snd_BUG();
1428 err = -EIO;
1429 goto __err;
1430 }
1431 /* clear remaining instruction memory */
1432 while (ptr < 0x400)
1433 A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0);
1434
1435 seg = snd_enter_user();
1436 icode->gpr_add_control_count = nctl;
1437 icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
1438 err = snd_emu10k1_icode_poke(emu, icode);
1439 snd_leave_user(seg);
1440
1441 __err:
1442 kfree(controls);
1443 if (icode != NULL) {
Clemens Ladisch4d233592005-09-05 10:35:20 +02001444 kfree((void __force *)icode->gpr_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 kfree(icode);
1446 }
1447 return err;
1448}
1449
1450
1451/*
1452 * initial DSP configuration for Emu10k1
1453 */
1454
1455/* when volume = max, then copy only to avoid volume modification */
1456/* with iMAC0 (negative values) */
1457static void __devinit _volume(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
1458{
1459 OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
1460 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1461 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001);
1462 OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
1463}
1464static void __devinit _volume_add(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
1465{
1466 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1467 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1468 OP(icode, ptr, iMACINT0, dst, dst, src, C_00000001);
1469 OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
1470 OP(icode, ptr, iMAC0, dst, dst, src, vol);
1471}
1472static void __devinit _volume_out(emu10k1_fx8010_code_t *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
1473{
1474 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1475 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1476 OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
1477 OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
1478 OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
1479}
1480
1481#define VOLUME(icode, ptr, dst, src, vol) \
1482 _volume(icode, ptr, GPR(dst), GPR(src), GPR(vol))
1483#define VOLUME_IN(icode, ptr, dst, src, vol) \
1484 _volume(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))
1485#define VOLUME_ADD(icode, ptr, dst, src, vol) \
1486 _volume_add(icode, ptr, GPR(dst), GPR(src), GPR(vol))
1487#define VOLUME_ADDIN(icode, ptr, dst, src, vol) \
1488 _volume_add(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))
1489#define VOLUME_OUT(icode, ptr, dst, src, vol) \
1490 _volume_out(icode, ptr, EXTOUT(dst), GPR(src), GPR(vol))
1491#define _SWITCH(icode, ptr, dst, src, sw) \
1492 OP((icode), ptr, iMACINT0, dst, C_00000000, src, sw);
1493#define SWITCH(icode, ptr, dst, src, sw) \
1494 _SWITCH(icode, ptr, GPR(dst), GPR(src), GPR(sw))
1495#define SWITCH_IN(icode, ptr, dst, src, sw) \
1496 _SWITCH(icode, ptr, GPR(dst), EXTIN(src), GPR(sw))
1497#define _SWITCH_NEG(icode, ptr, dst, src) \
1498 OP((icode), ptr, iANDXOR, dst, src, C_00000001, C_00000001);
1499#define SWITCH_NEG(icode, ptr, dst, src) \
1500 _SWITCH_NEG(icode, ptr, GPR(dst), GPR(src))
1501
1502
1503static int __devinit _snd_emu10k1_init_efx(emu10k1_t *emu)
1504{
1505 int err, i, z, gpr, tmp, playback, capture;
1506 u32 ptr;
1507 emu10k1_fx8010_code_t *icode;
1508 emu10k1_fx8010_pcm_t *ipcm = NULL;
1509 emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;
1510 u32 *gpr_map;
1511 mm_segment_t seg;
1512
1513 spin_lock_init(&emu->fx8010.irq_lock);
1514 INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
1515
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001516 if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517 return -ENOMEM;
1518 if ((icode->gpr_map = (u_int32_t __user *)kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
1519 (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL ||
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001520 (ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL)) == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521 err = -ENOMEM;
1522 goto __err;
1523 }
Clemens Ladisch4d233592005-09-05 10:35:20 +02001524 gpr_map = (u32 __force *)icode->gpr_map;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
1526 icode->tram_data_map = icode->gpr_map + 256;
1527 icode->tram_addr_map = icode->tram_data_map + 160;
1528 icode->code = icode->tram_addr_map + 160;
1529
1530 /* clear free GPRs */
1531 for (i = 0; i < 256; i++)
1532 set_bit(i, icode->gpr_valid);
1533
1534 /* clear TRAM data & address lines */
1535 for (i = 0; i < 160; i++)
1536 set_bit(i, icode->tram_valid);
1537
1538 strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela");
1539 ptr = 0; i = 0;
Mikael Magnussonedf8e452005-09-13 11:32:58 +02001540 /* we have 12 inputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541 playback = SND_EMU10K1_INPUTS;
1542 /* we have 6 playback channels and tone control doubles */
1543 capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2);
1544 gpr = capture + SND_EMU10K1_CAPTURE_CHANNELS;
1545 tmp = 0x88; /* we need 4 temporary GPR */
1546 /* from 0x8c to 0xff is the area for tone control */
1547
1548 /* stop FX processor */
1549 snd_emu10k1_ptr_write(emu, DBG, 0, (emu->fx8010.dbg = 0) | EMU10K1_DBG_SINGLE_STEP);
1550
1551 /*
1552 * Process FX Buses
1553 */
1554 OP(icode, &ptr, iMACINT0, GPR(0), C_00000000, FXBUS(FXBUS_PCM_LEFT), C_00000004);
1555 OP(icode, &ptr, iMACINT0, GPR(1), C_00000000, FXBUS(FXBUS_PCM_RIGHT), C_00000004);
1556 OP(icode, &ptr, iMACINT0, GPR(2), C_00000000, FXBUS(FXBUS_MIDI_LEFT), C_00000004);
1557 OP(icode, &ptr, iMACINT0, GPR(3), C_00000000, FXBUS(FXBUS_MIDI_RIGHT), C_00000004);
1558 OP(icode, &ptr, iMACINT0, GPR(4), C_00000000, FXBUS(FXBUS_PCM_LEFT_REAR), C_00000004);
1559 OP(icode, &ptr, iMACINT0, GPR(5), C_00000000, FXBUS(FXBUS_PCM_RIGHT_REAR), C_00000004);
1560 OP(icode, &ptr, iMACINT0, GPR(6), C_00000000, FXBUS(FXBUS_PCM_CENTER), C_00000004);
1561 OP(icode, &ptr, iMACINT0, GPR(7), C_00000000, FXBUS(FXBUS_PCM_LFE), C_00000004);
1562 OP(icode, &ptr, iMACINT0, GPR(8), C_00000000, C_00000000, C_00000000); /* S/PDIF left */
1563 OP(icode, &ptr, iMACINT0, GPR(9), C_00000000, C_00000000, C_00000000); /* S/PDIF right */
Mikael Magnussonedf8e452005-09-13 11:32:58 +02001564 OP(icode, &ptr, iMACINT0, GPR(10), C_00000000, FXBUS(FXBUS_PCM_LEFT_FRONT), C_00000004);
1565 OP(icode, &ptr, iMACINT0, GPR(11), C_00000000, FXBUS(FXBUS_PCM_RIGHT_FRONT), C_00000004);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566
1567 /* Raw S/PDIF PCM */
1568 ipcm->substream = 0;
1569 ipcm->channels = 2;
1570 ipcm->tram_start = 0;
1571 ipcm->buffer_size = (64 * 1024) / 2;
1572 ipcm->gpr_size = gpr++;
1573 ipcm->gpr_ptr = gpr++;
1574 ipcm->gpr_count = gpr++;
1575 ipcm->gpr_tmpcount = gpr++;
1576 ipcm->gpr_trigger = gpr++;
1577 ipcm->gpr_running = gpr++;
1578 ipcm->etram[0] = 0;
1579 ipcm->etram[1] = 1;
1580
1581 gpr_map[gpr + 0] = 0xfffff000;
1582 gpr_map[gpr + 1] = 0xffff0000;
1583 gpr_map[gpr + 2] = 0x70000000;
1584 gpr_map[gpr + 3] = 0x00000007;
1585 gpr_map[gpr + 4] = 0x001f << 11;
1586 gpr_map[gpr + 5] = 0x001c << 11;
1587 gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */
1588 gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */
1589 gpr_map[gpr + 8] = 0x2000000 + (2<<11);
1590 gpr_map[gpr + 9] = 0x4000000 + (2<<11);
1591 gpr_map[gpr + 10] = 1<<11;
1592 gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */
1593 gpr_map[gpr + 12] = 0;
1594
1595 /* if the trigger flag is not set, skip */
1596 /* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000);
1597 /* 01: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_ZERO, GPR(gpr + 6));
1598 /* if the running flag is set, we're running */
1599 /* 02: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_running), C_00000000, C_00000000);
1600 /* 03: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000004);
1601 /* wait until ((GPR_DBAC>>11) & 0x1f) == 0x1c) */
1602 /* 04: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), GPR_DBAC, GPR(gpr + 4), C_00000000);
1603 /* 05: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(gpr + 5));
1604 /* 06: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 7));
1605 /* 07: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000010, C_00000001, C_00000000);
1606
1607 /* 08: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000000, C_00000001);
1608 /* 09: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), GPR(gpr + 12), C_ffffffff, C_00000000);
1609 /* 0a: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 11));
1610 /* 0b: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000001, C_00000000, C_00000000);
1611
1612 /* 0c: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[0]), GPR(gpr + 0), C_00000000);
1613 /* 0d: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000);
1614 /* 0e: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2));
1615 /* 0f: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001);
1616 /* 10: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(8), GPR(gpr + 1), GPR(gpr + 2));
1617
1618 /* 11: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[1]), GPR(gpr + 0), C_00000000);
1619 /* 12: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000);
1620 /* 13: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2));
1621 /* 14: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001);
1622 /* 15: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(9), GPR(gpr + 1), GPR(gpr + 2));
1623
1624 /* 16: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(ipcm->gpr_ptr), C_00000001, C_00000000);
1625 /* 17: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(ipcm->gpr_size));
1626 /* 18: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_MINUS, C_00000001);
1627 /* 19: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), C_00000000, C_00000000, C_00000000);
1628 /* 1a: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_ptr), GPR(tmp + 0), C_00000000, C_00000000);
1629
1630 /* 1b: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_tmpcount), C_ffffffff, C_00000000);
1631 /* 1c: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1632 /* 1d: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_count), C_00000000, C_00000000);
1633 /* 1e: */ OP(icode, &ptr, iACC3, GPR_IRQ, C_80000000, C_00000000, C_00000000);
1634 /* 1f: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000001, C_00010000);
1635
1636 /* 20: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00010000, C_00000001);
1637 /* 21: */ OP(icode, &ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000002);
1638
1639 /* 22: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[0]), GPR(gpr + 8), GPR_DBAC, C_ffffffff);
1640 /* 23: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[1]), GPR(gpr + 9), GPR_DBAC, C_ffffffff);
1641
1642 /* 24: */
1643 gpr += 13;
1644
1645 /* Wave Playback Volume */
1646 for (z = 0; z < 2; z++)
1647 VOLUME(icode, &ptr, playback + z, z, gpr + z);
1648 snd_emu10k1_init_stereo_control(controls + i++, "Wave Playback Volume", gpr, 100);
1649 gpr += 2;
1650
1651 /* Wave Surround Playback Volume */
1652 for (z = 0; z < 2; z++)
1653 VOLUME(icode, &ptr, playback + 2 + z, z, gpr + z);
1654 snd_emu10k1_init_stereo_control(controls + i++, "Wave Surround Playback Volume", gpr, 0);
1655 gpr += 2;
1656
1657 /* Wave Center/LFE Playback Volume */
1658 OP(icode, &ptr, iACC3, GPR(tmp + 0), FXBUS(FXBUS_PCM_LEFT), FXBUS(FXBUS_PCM_RIGHT), C_00000000);
1659 OP(icode, &ptr, iMACINT0, GPR(tmp + 0), C_00000000, GPR(tmp + 0), C_00000002);
1660 VOLUME(icode, &ptr, playback + 4, tmp + 0, gpr);
1661 snd_emu10k1_init_mono_control(controls + i++, "Wave Center Playback Volume", gpr++, 0);
1662 VOLUME(icode, &ptr, playback + 5, tmp + 0, gpr);
1663 snd_emu10k1_init_mono_control(controls + i++, "Wave LFE Playback Volume", gpr++, 0);
1664
1665 /* Wave Capture Volume + Switch */
1666 for (z = 0; z < 2; z++) {
1667 SWITCH(icode, &ptr, tmp + 0, z, gpr + 2 + z);
1668 VOLUME(icode, &ptr, capture + z, tmp + 0, gpr + z);
1669 }
1670 snd_emu10k1_init_stereo_control(controls + i++, "Wave Capture Volume", gpr, 0);
1671 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0);
1672 gpr += 4;
1673
1674 /* Synth Playback Volume */
1675 for (z = 0; z < 2; z++)
1676 VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z);
1677 snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100);
1678 gpr += 2;
1679
1680 /* Synth Capture Volume + Switch */
1681 for (z = 0; z < 2; z++) {
1682 SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z);
1683 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1684 }
1685 snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0);
1686 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0);
1687 gpr += 4;
1688
1689 /* Surround Digital Playback Volume (renamed later without Digital) */
1690 for (z = 0; z < 2; z++)
1691 VOLUME_ADD(icode, &ptr, playback + 2 + z, 4 + z, gpr + z);
1692 snd_emu10k1_init_stereo_control(controls + i++, "Surround Digital Playback Volume", gpr, 100);
1693 gpr += 2;
1694
1695 /* Surround Capture Volume + Switch */
1696 for (z = 0; z < 2; z++) {
1697 SWITCH(icode, &ptr, tmp + 0, 4 + z, gpr + 2 + z);
1698 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1699 }
1700 snd_emu10k1_init_stereo_control(controls + i++, "Surround Capture Volume", gpr, 0);
1701 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Surround Capture Switch", gpr + 2, 0);
1702 gpr += 4;
1703
1704 /* Center Playback Volume (renamed later without Digital) */
1705 VOLUME_ADD(icode, &ptr, playback + 4, 6, gpr);
1706 snd_emu10k1_init_mono_control(controls + i++, "Center Digital Playback Volume", gpr++, 100);
1707
1708 /* LFE Playback Volume + Switch (renamed later without Digital) */
1709 VOLUME_ADD(icode, &ptr, playback + 5, 7, gpr);
1710 snd_emu10k1_init_mono_control(controls + i++, "LFE Digital Playback Volume", gpr++, 100);
1711
Mikael Magnussonedf8e452005-09-13 11:32:58 +02001712 /* Front Playback Volume */
1713 for (z = 0; z < 2; z++)
1714 VOLUME_ADD(icode, &ptr, playback + z, 10 + z, gpr + z);
1715 snd_emu10k1_init_stereo_control(controls + i++, "Front Playback Volume", gpr, 100);
1716 gpr += 2;
1717
1718 /* Front Capture Volume + Switch */
1719 for (z = 0; z < 2; z++) {
1720 SWITCH(icode, &ptr, tmp + 0, 10 + z, gpr + 2);
1721 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1722 }
1723 snd_emu10k1_init_stereo_control(controls + i++, "Front Capture Volume", gpr, 0);
1724 snd_emu10k1_init_mono_onoff_control(controls + i++, "Front Capture Switch", gpr + 2, 0);
1725 gpr += 3;
1726
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727 /*
1728 * Process inputs
1729 */
1730
1731 if (emu->fx8010.extin_mask & ((1<<EXTIN_AC97_L)|(1<<EXTIN_AC97_R))) {
1732 /* AC'97 Playback Volume */
1733 VOLUME_ADDIN(icode, &ptr, playback + 0, EXTIN_AC97_L, gpr); gpr++;
1734 VOLUME_ADDIN(icode, &ptr, playback + 1, EXTIN_AC97_R, gpr); gpr++;
1735 snd_emu10k1_init_stereo_control(controls + i++, "AC97 Playback Volume", gpr-2, 0);
1736 /* AC'97 Capture Volume */
1737 VOLUME_ADDIN(icode, &ptr, capture + 0, EXTIN_AC97_L, gpr); gpr++;
1738 VOLUME_ADDIN(icode, &ptr, capture + 1, EXTIN_AC97_R, gpr); gpr++;
1739 snd_emu10k1_init_stereo_control(controls + i++, "AC97 Capture Volume", gpr-2, 100);
1740 }
1741
1742 if (emu->fx8010.extin_mask & ((1<<EXTIN_SPDIF_CD_L)|(1<<EXTIN_SPDIF_CD_R))) {
1743 /* IEC958 TTL Playback Volume */
1744 for (z = 0; z < 2; z++)
1745 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_SPDIF_CD_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001746 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747 gpr += 2;
1748
1749 /* IEC958 TTL Capture Volume + Switch */
1750 for (z = 0; z < 2; z++) {
1751 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_SPDIF_CD_L + z, gpr + 2 + z);
1752 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1753 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001754 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",CAPTURE,VOLUME), gpr, 0);
1755 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 -07001756 gpr += 4;
1757 }
1758
1759 if (emu->fx8010.extin_mask & ((1<<EXTIN_ZOOM_L)|(1<<EXTIN_ZOOM_R))) {
1760 /* Zoom Video Playback Volume */
1761 for (z = 0; z < 2; z++)
1762 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_ZOOM_L + z, gpr + z);
1763 snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Playback Volume", gpr, 0);
1764 gpr += 2;
1765
1766 /* Zoom Video Capture Volume + Switch */
1767 for (z = 0; z < 2; z++) {
1768 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_ZOOM_L + z, gpr + 2 + z);
1769 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1770 }
1771 snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Capture Volume", gpr, 0);
1772 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Zoom Video Capture Switch", gpr + 2, 0);
1773 gpr += 4;
1774 }
1775
1776 if (emu->fx8010.extin_mask & ((1<<EXTIN_TOSLINK_L)|(1<<EXTIN_TOSLINK_R))) {
1777 /* IEC958 Optical Playback Volume */
1778 for (z = 0; z < 2; z++)
1779 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_TOSLINK_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001780 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 gpr += 2;
1782
1783 /* IEC958 Optical Capture Volume */
1784 for (z = 0; z < 2; z++) {
1785 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_TOSLINK_L + z, gpr + 2 + z);
1786 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1787 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001788 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",CAPTURE,VOLUME), gpr, 0);
1789 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 -07001790 gpr += 4;
1791 }
1792
1793 if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE1_L)|(1<<EXTIN_LINE1_R))) {
1794 /* Line LiveDrive Playback Volume */
1795 for (z = 0; z < 2; z++)
1796 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE1_L + z, gpr + z);
1797 snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Playback Volume", gpr, 0);
1798 gpr += 2;
1799
1800 /* Line LiveDrive Capture Volume + Switch */
1801 for (z = 0; z < 2; z++) {
1802 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE1_L + z, gpr + 2 + z);
1803 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1804 }
1805 snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Capture Volume", gpr, 0);
1806 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line LiveDrive Capture Switch", gpr + 2, 0);
1807 gpr += 4;
1808 }
1809
1810 if (emu->fx8010.extin_mask & ((1<<EXTIN_COAX_SPDIF_L)|(1<<EXTIN_COAX_SPDIF_R))) {
1811 /* IEC958 Coax Playback Volume */
1812 for (z = 0; z < 2; z++)
1813 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_COAX_SPDIF_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001814 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001815 gpr += 2;
1816
1817 /* IEC958 Coax Capture Volume + Switch */
1818 for (z = 0; z < 2; z++) {
1819 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_COAX_SPDIF_L + z, gpr + 2 + z);
1820 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1821 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001822 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",CAPTURE,VOLUME), gpr, 0);
1823 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 -07001824 gpr += 4;
1825 }
1826
1827 if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE2_L)|(1<<EXTIN_LINE2_R))) {
1828 /* Line LiveDrive Playback Volume */
1829 for (z = 0; z < 2; z++)
1830 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE2_L + z, gpr + z);
1831 snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Playback Volume", gpr, 0);
1832 controls[i-1].id.index = 1;
1833 gpr += 2;
1834
1835 /* Line LiveDrive Capture Volume */
1836 for (z = 0; z < 2; z++) {
1837 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE2_L + z, gpr + 2 + z);
1838 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1839 }
1840 snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Capture Volume", gpr, 0);
1841 controls[i-1].id.index = 1;
1842 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line2 LiveDrive Capture Switch", gpr + 2, 0);
1843 controls[i-1].id.index = 1;
1844 gpr += 4;
1845 }
1846
1847 /*
1848 * Process tone control
1849 */
1850 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), GPR(playback + 0), C_00000000, C_00000000); /* left */
1851 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), GPR(playback + 1), C_00000000, C_00000000); /* right */
1852 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2), GPR(playback + 2), C_00000000, C_00000000); /* rear left */
1853 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), GPR(playback + 3), C_00000000, C_00000000); /* rear right */
1854 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), GPR(playback + 4), C_00000000, C_00000000); /* center */
1855 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), GPR(playback + 5), C_00000000, C_00000000); /* LFE */
1856
1857 ctl = &controls[i + 0];
1858 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1859 strcpy(ctl->id.name, "Tone Control - Bass");
1860 ctl->vcount = 2;
1861 ctl->count = 10;
1862 ctl->min = 0;
1863 ctl->max = 40;
1864 ctl->value[0] = ctl->value[1] = 20;
1865 ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
1866 ctl = &controls[i + 1];
1867 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1868 strcpy(ctl->id.name, "Tone Control - Treble");
1869 ctl->vcount = 2;
1870 ctl->count = 10;
1871 ctl->min = 0;
1872 ctl->max = 40;
1873 ctl->value[0] = ctl->value[1] = 20;
1874 ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
1875
1876#define BASS_GPR 0x8c
1877#define TREBLE_GPR 0x96
1878
1879 for (z = 0; z < 5; z++) {
1880 int j;
1881 for (j = 0; j < 2; j++) {
1882 controls[i + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j;
1883 controls[i + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
1884 }
1885 }
1886 for (z = 0; z < 3; z++) { /* front/rear/center-lfe */
1887 int j, k, l, d;
1888 for (j = 0; j < 2; j++) { /* left/right */
1889 k = 0xa0 + (z * 8) + (j * 4);
1890 l = 0xd0 + (z * 8) + (j * 4);
1891 d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j;
1892
1893 OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(d), GPR(BASS_GPR + 0 + j));
1894 OP(icode, &ptr, iMACMV, GPR(k+1), GPR(k), GPR(k+1), GPR(BASS_GPR + 4 + j));
1895 OP(icode, &ptr, iMACMV, GPR(k), GPR(d), GPR(k), GPR(BASS_GPR + 2 + j));
1896 OP(icode, &ptr, iMACMV, GPR(k+3), GPR(k+2), GPR(k+3), GPR(BASS_GPR + 8 + j));
1897 OP(icode, &ptr, iMAC0, GPR(k+2), GPR_ACCU, GPR(k+2), GPR(BASS_GPR + 6 + j));
1898 OP(icode, &ptr, iACC3, GPR(k+2), GPR(k+2), GPR(k+2), C_00000000);
1899
1900 OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(k+2), GPR(TREBLE_GPR + 0 + j));
1901 OP(icode, &ptr, iMACMV, GPR(l+1), GPR(l), GPR(l+1), GPR(TREBLE_GPR + 4 + j));
1902 OP(icode, &ptr, iMACMV, GPR(l), GPR(k+2), GPR(l), GPR(TREBLE_GPR + 2 + j));
1903 OP(icode, &ptr, iMACMV, GPR(l+3), GPR(l+2), GPR(l+3), GPR(TREBLE_GPR + 8 + j));
1904 OP(icode, &ptr, iMAC0, GPR(l+2), GPR_ACCU, GPR(l+2), GPR(TREBLE_GPR + 6 + j));
1905 OP(icode, &ptr, iMACINT0, GPR(l+2), C_00000000, GPR(l+2), C_00000010);
1906
1907 OP(icode, &ptr, iACC3, GPR(d), GPR(l+2), C_00000000, C_00000000);
1908
1909 if (z == 2) /* center */
1910 break;
1911 }
1912 }
1913 i += 2;
1914
1915#undef BASS_GPR
1916#undef TREBLE_GPR
1917
1918 for (z = 0; z < 6; z++) {
1919 SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
1920 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
1921 SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
1922 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
1923 }
1924 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Tone Control - Switch", gpr, 0);
1925 gpr += 2;
1926
1927 /*
1928 * Process outputs
1929 */
1930 if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_L)|(1<<EXTOUT_AC97_R))) {
1931 /* AC'97 Playback Volume */
1932
1933 for (z = 0; z < 2; z++)
1934 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), C_00000000, C_00000000);
1935 }
1936
1937 if (emu->fx8010.extout_mask & ((1<<EXTOUT_TOSLINK_L)|(1<<EXTOUT_TOSLINK_R))) {
1938 /* IEC958 Optical Raw Playback Switch */
1939
1940 for (z = 0; z < 2; z++) {
1941 SWITCH(icode, &ptr, tmp + 0, 8 + z, gpr + z);
1942 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
1943 SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
1944 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_TOSLINK_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
1945#ifdef EMU10K1_CAPTURE_DIGITAL_OUT
1946 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
1947#endif
1948 }
1949
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001950 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 -07001951 gpr += 2;
1952 }
1953
1954 if (emu->fx8010.extout_mask & ((1<<EXTOUT_HEADPHONE_L)|(1<<EXTOUT_HEADPHONE_R))) {
1955 /* Headphone Playback Volume */
1956
1957 for (z = 0; z < 2; z++) {
1958 SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4 + z, gpr + 2 + z);
1959 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 2 + z);
1960 SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
1961 OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
1962 VOLUME_OUT(icode, &ptr, EXTOUT_HEADPHONE_L + z, tmp + 0, gpr + z);
1963 }
1964
1965 snd_emu10k1_init_stereo_control(controls + i++, "Headphone Playback Volume", gpr + 0, 0);
1966 controls[i-1].id.index = 1; /* AC'97 can have also Headphone control */
1967 snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone Center Playback Switch", gpr + 2, 0);
1968 controls[i-1].id.index = 1;
1969 snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone LFE Playback Switch", gpr + 3, 0);
1970 controls[i-1].id.index = 1;
1971
1972 gpr += 4;
1973 }
1974
1975 if (emu->fx8010.extout_mask & ((1<<EXTOUT_REAR_L)|(1<<EXTOUT_REAR_R)))
1976 for (z = 0; z < 2; z++)
1977 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000);
1978
1979 if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_REAR_L)|(1<<EXTOUT_AC97_REAR_R)))
1980 for (z = 0; z < 2; z++)
1981 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000);
1982
1983 if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_CENTER)) {
1984#ifndef EMU10K1_CENTER_LFE_FROM_FRONT
1985 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000);
1986 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000);
1987#else
1988 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000);
1989 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000);
1990#endif
1991 }
1992
1993 if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_LFE)) {
1994#ifndef EMU10K1_CENTER_LFE_FROM_FRONT
1995 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000);
1996 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000);
1997#else
1998 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000);
1999 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000);
2000#endif
2001 }
2002
2003#ifndef EMU10K1_CAPTURE_DIGITAL_OUT
2004 for (z = 0; z < 2; z++)
2005 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(capture + z), C_00000000, C_00000000);
2006#endif
2007
2008 if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP))
2009 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
2010
2011 /* EFX capture - capture the 16 EXTINS */
Lee Revell2b637da2005-03-30 13:51:18 +02002012 if (emu->card_capabilities->sblive51) {
2013 /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER
2014 * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording.
2015 *
2016 * Since only 14 of the 16 EXTINs are used, this is not a big problem.
2017 * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
2018 * 0 and 3, then the rest of the EXTINs to the corresponding FX capture
2019 * channel. Multitrack recorders will still see the center/lfe output signal
2020 * on the second and third channels.
2021 */
2022 OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
2023 OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
2024 OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
2025 OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
2026 for (z = 4; z < 14; z++)
2027 OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
2028 } else {
2029 for (z = 0; z < 16; z++)
2030 OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002031 }
Lee Revell2b637da2005-03-30 13:51:18 +02002032
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033
2034 if (gpr > tmp) {
2035 snd_BUG();
2036 err = -EIO;
2037 goto __err;
2038 }
2039 if (i > SND_EMU10K1_GPR_CONTROLS) {
2040 snd_BUG();
2041 err = -EIO;
2042 goto __err;
2043 }
2044
2045 /* clear remaining instruction memory */
2046 while (ptr < 0x200)
2047 OP(icode, &ptr, iACC3, C_00000000, C_00000000, C_00000000, C_00000000);
2048
2049 if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0)
2050 goto __err;
2051 seg = snd_enter_user();
2052 icode->gpr_add_control_count = i;
2053 icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
2054 err = snd_emu10k1_icode_poke(emu, icode);
2055 snd_leave_user(seg);
2056 if (err >= 0)
2057 err = snd_emu10k1_ipcm_poke(emu, ipcm);
2058 __err:
2059 kfree(ipcm);
2060 kfree(controls);
2061 if (icode != NULL) {
Clemens Ladisch4d233592005-09-05 10:35:20 +02002062 kfree((void __force *)icode->gpr_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063 kfree(icode);
2064 }
2065 return err;
2066}
2067
2068int __devinit snd_emu10k1_init_efx(emu10k1_t *emu)
2069{
2070 if (emu->audigy)
2071 return _snd_emu10k1_audigy_init_efx(emu);
2072 else
2073 return _snd_emu10k1_init_efx(emu);
2074}
2075
2076void snd_emu10k1_free_efx(emu10k1_t *emu)
2077{
2078 /* stop processor */
2079 if (emu->audigy)
2080 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = A_DBG_SINGLE_STEP);
2081 else
2082 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP);
2083}
2084
2085#if 0 // FIXME: who use them?
2086int snd_emu10k1_fx8010_tone_control_activate(emu10k1_t *emu, int output)
2087{
Takashi Iwai7c22f1a2005-10-10 11:46:31 +02002088 if (output < 0 || output >= 6)
2089 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002090 snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 1);
2091 return 0;
2092}
2093
2094int snd_emu10k1_fx8010_tone_control_deactivate(emu10k1_t *emu, int output)
2095{
Takashi Iwai7c22f1a2005-10-10 11:46:31 +02002096 if (output < 0 || output >= 6)
2097 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002098 snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 0);
2099 return 0;
2100}
2101#endif
2102
2103int snd_emu10k1_fx8010_tram_setup(emu10k1_t *emu, u32 size)
2104{
2105 u8 size_reg = 0;
2106
2107 /* size is in samples */
2108 if (size != 0) {
2109 size = (size - 1) >> 13;
2110
2111 while (size) {
2112 size >>= 1;
2113 size_reg++;
2114 }
2115 size = 0x2000 << size_reg;
2116 }
2117 if ((emu->fx8010.etram_pages.bytes / 2) == size)
2118 return 0;
2119 spin_lock_irq(&emu->emu_lock);
2120 outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG);
2121 spin_unlock_irq(&emu->emu_lock);
2122 snd_emu10k1_ptr_write(emu, TCB, 0, 0);
2123 snd_emu10k1_ptr_write(emu, TCBS, 0, 0);
2124 if (emu->fx8010.etram_pages.area != NULL) {
2125 snd_dma_free_pages(&emu->fx8010.etram_pages);
2126 emu->fx8010.etram_pages.area = NULL;
2127 emu->fx8010.etram_pages.bytes = 0;
2128 }
2129
2130 if (size > 0) {
2131 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
2132 size * 2, &emu->fx8010.etram_pages) < 0)
2133 return -ENOMEM;
2134 memset(emu->fx8010.etram_pages.area, 0, size * 2);
2135 snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr);
2136 snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg);
2137 spin_lock_irq(&emu->emu_lock);
2138 outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
2139 spin_unlock_irq(&emu->emu_lock);
2140 }
2141
2142 return 0;
2143}
2144
2145static int snd_emu10k1_fx8010_open(snd_hwdep_t * hw, struct file *file)
2146{
2147 return 0;
2148}
2149
2150static void copy_string(char *dst, char *src, char *null, int idx)
2151{
2152 if (src == NULL)
2153 sprintf(dst, "%s %02X", null, idx);
2154 else
2155 strcpy(dst, src);
2156}
2157
2158static int snd_emu10k1_fx8010_info(emu10k1_t *emu, emu10k1_fx8010_info_t *info)
2159{
2160 char **fxbus, **extin, **extout;
2161 unsigned short fxbus_mask, extin_mask, extout_mask;
2162 int res;
2163
2164 memset(info, 0, sizeof(info));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 info->internal_tram_size = emu->fx8010.itram_size;
2166 info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
2167 fxbus = fxbuses;
2168 extin = emu->audigy ? audigy_ins : creative_ins;
2169 extout = emu->audigy ? audigy_outs : creative_outs;
2170 fxbus_mask = emu->fx8010.fxbus_mask;
2171 extin_mask = emu->fx8010.extin_mask;
2172 extout_mask = emu->fx8010.extout_mask;
2173 for (res = 0; res < 16; res++, fxbus++, extin++, extout++) {
2174 copy_string(info->fxbus_names[res], fxbus_mask & (1 << res) ? *fxbus : NULL, "FXBUS", res);
2175 copy_string(info->extin_names[res], extin_mask & (1 << res) ? *extin : NULL, "Unused", res);
2176 copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res);
2177 }
2178 for (res = 16; res < 32; res++, extout++)
2179 copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res);
2180 info->gpr_controls = emu->fx8010.gpr_count;
2181 return 0;
2182}
2183
2184static int snd_emu10k1_fx8010_ioctl(snd_hwdep_t * hw, struct file *file, unsigned int cmd, unsigned long arg)
2185{
2186 emu10k1_t *emu = hw->private_data;
2187 emu10k1_fx8010_info_t *info;
2188 emu10k1_fx8010_code_t *icode;
2189 emu10k1_fx8010_pcm_t *ipcm;
2190 unsigned int addr;
2191 void __user *argp = (void __user *)arg;
2192 int res;
2193
2194 switch (cmd) {
2195 case SNDRV_EMU10K1_IOCTL_INFO:
2196 info = (emu10k1_fx8010_info_t *)kmalloc(sizeof(*info), GFP_KERNEL);
2197 if (!info)
2198 return -ENOMEM;
2199 if ((res = snd_emu10k1_fx8010_info(emu, info)) < 0) {
2200 kfree(info);
2201 return res;
2202 }
2203 if (copy_to_user(argp, info, sizeof(*info))) {
2204 kfree(info);
2205 return -EFAULT;
2206 }
2207 kfree(info);
2208 return 0;
2209 case SNDRV_EMU10K1_IOCTL_CODE_POKE:
2210 if (!capable(CAP_SYS_ADMIN))
2211 return -EPERM;
2212 icode = (emu10k1_fx8010_code_t *)kmalloc(sizeof(*icode), GFP_KERNEL);
2213 if (icode == NULL)
2214 return -ENOMEM;
2215 if (copy_from_user(icode, argp, sizeof(*icode))) {
2216 kfree(icode);
2217 return -EFAULT;
2218 }
2219 res = snd_emu10k1_icode_poke(emu, icode);
2220 kfree(icode);
2221 return res;
2222 case SNDRV_EMU10K1_IOCTL_CODE_PEEK:
2223 icode = (emu10k1_fx8010_code_t *)kmalloc(sizeof(*icode), GFP_KERNEL);
2224 if (icode == NULL)
2225 return -ENOMEM;
2226 if (copy_from_user(icode, argp, sizeof(*icode))) {
2227 kfree(icode);
2228 return -EFAULT;
2229 }
2230 res = snd_emu10k1_icode_peek(emu, icode);
2231 if (res == 0 && copy_to_user(argp, icode, sizeof(*icode))) {
2232 kfree(icode);
2233 return -EFAULT;
2234 }
2235 kfree(icode);
2236 return res;
2237 case SNDRV_EMU10K1_IOCTL_PCM_POKE:
2238 ipcm = (emu10k1_fx8010_pcm_t *)kmalloc(sizeof(*ipcm), GFP_KERNEL);
2239 if (ipcm == NULL)
2240 return -ENOMEM;
2241 if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
2242 kfree(ipcm);
2243 return -EFAULT;
2244 }
2245 res = snd_emu10k1_ipcm_poke(emu, ipcm);
2246 kfree(ipcm);
2247 return res;
2248 case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
Takashi Iwaie560d8d2005-09-09 14:21:46 +02002249 ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250 if (ipcm == NULL)
2251 return -ENOMEM;
2252 if (copy_from_user(ipcm, argp, sizeof(*ipcm))) {
2253 kfree(ipcm);
2254 return -EFAULT;
2255 }
2256 res = snd_emu10k1_ipcm_peek(emu, ipcm);
2257 if (res == 0 && copy_to_user(argp, ipcm, sizeof(*ipcm))) {
2258 kfree(ipcm);
2259 return -EFAULT;
2260 }
2261 kfree(ipcm);
2262 return res;
2263 case SNDRV_EMU10K1_IOCTL_TRAM_SETUP:
2264 if (!capable(CAP_SYS_ADMIN))
2265 return -EPERM;
2266 if (get_user(addr, (unsigned int __user *)argp))
2267 return -EFAULT;
2268 down(&emu->fx8010.lock);
2269 res = snd_emu10k1_fx8010_tram_setup(emu, addr);
2270 up(&emu->fx8010.lock);
2271 return res;
2272 case SNDRV_EMU10K1_IOCTL_STOP:
2273 if (!capable(CAP_SYS_ADMIN))
2274 return -EPERM;
2275 if (emu->audigy)
2276 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP);
2277 else
2278 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP);
2279 return 0;
2280 case SNDRV_EMU10K1_IOCTL_CONTINUE:
2281 if (!capable(CAP_SYS_ADMIN))
2282 return -EPERM;
2283 if (emu->audigy)
2284 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = 0);
2285 else
2286 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = 0);
2287 return 0;
2288 case SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER:
2289 if (!capable(CAP_SYS_ADMIN))
2290 return -EPERM;
2291 if (emu->audigy)
2292 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_ZC);
2293 else
2294 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_ZC);
2295 udelay(10);
2296 if (emu->audigy)
2297 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
2298 else
2299 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
2300 return 0;
2301 case SNDRV_EMU10K1_IOCTL_SINGLE_STEP:
2302 if (!capable(CAP_SYS_ADMIN))
2303 return -EPERM;
2304 if (get_user(addr, (unsigned int __user *)argp))
2305 return -EFAULT;
2306 if (addr > 0x1ff)
2307 return -EINVAL;
2308 if (emu->audigy)
2309 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | addr);
2310 else
2311 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | addr);
2312 udelay(10);
2313 if (emu->audigy)
2314 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | A_DBG_STEP_ADDR | addr);
2315 else
2316 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | EMU10K1_DBG_STEP | addr);
2317 return 0;
2318 case SNDRV_EMU10K1_IOCTL_DBG_READ:
2319 if (emu->audigy)
2320 addr = snd_emu10k1_ptr_read(emu, A_DBG, 0);
2321 else
2322 addr = snd_emu10k1_ptr_read(emu, DBG, 0);
2323 if (put_user(addr, (unsigned int __user *)argp))
2324 return -EFAULT;
2325 return 0;
2326 }
2327 return -ENOTTY;
2328}
2329
2330static int snd_emu10k1_fx8010_release(snd_hwdep_t * hw, struct file *file)
2331{
2332 return 0;
2333}
2334
2335int __devinit snd_emu10k1_fx8010_new(emu10k1_t *emu, int device, snd_hwdep_t ** rhwdep)
2336{
2337 snd_hwdep_t *hw;
2338 int err;
2339
2340 if (rhwdep)
2341 *rhwdep = NULL;
2342 if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0)
2343 return err;
2344 strcpy(hw->name, "EMU10K1 (FX8010)");
2345 hw->iface = SNDRV_HWDEP_IFACE_EMU10K1;
2346 hw->ops.open = snd_emu10k1_fx8010_open;
2347 hw->ops.ioctl = snd_emu10k1_fx8010_ioctl;
2348 hw->ops.release = snd_emu10k1_fx8010_release;
2349 hw->private_data = emu;
2350 if (rhwdep)
2351 *rhwdep = hw;
2352 return 0;
2353}