blob: 7a9401462c1c698a0a8f21e2135a613d1efb5a0b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Jaroslav Kyselac1017a42007-10-15 09:50:19 +02002 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 * Creative Labs, Inc.
4 * Routines for effect processor FX8010
5 *
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01006 * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
7 * Added EMU 1010 support.
8 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 * BUGS:
10 * --
11 *
12 * TODO:
13 * --
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
29 */
30
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include <linux/pci.h>
Randy.Dunlapc59ede72006-01-11 12:17:46 -080032#include <linux/capability.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include <linux/delay.h>
34#include <linux/slab.h>
Andreas Schwabbd01e7b2005-12-05 15:12:20 +010035#include <linux/vmalloc.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include <linux/init.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010037#include <linux/mutex.h>
Clemens Ladisch4daf7a02010-05-25 09:04:49 +020038#include <linux/moduleparam.h>
Ingo Molnar62932df2006-01-16 16:34:20 +010039
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <sound/core.h>
James Courtier-Dutton31508f82006-07-22 17:02:10 +010041#include <sound/tlv.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#include <sound/emu10k1.h>
43
44#if 0 /* for testing purposes - digital out -> capture */
45#define EMU10K1_CAPTURE_DIGITAL_OUT
46#endif
47#if 0 /* for testing purposes - set S/PDIF to AC3 output */
48#define EMU10K1_SET_AC3_IEC958
49#endif
50#if 0 /* for testing purposes - feed the front signal to Center/LFE outputs */
51#define EMU10K1_CENTER_LFE_FROM_FRONT
52#endif
53
Clemens Ladisch4daf7a02010-05-25 09:04:49 +020054static bool high_res_gpr_volume;
55module_param(high_res_gpr_volume, bool, 0444);
56MODULE_PARM_DESC(high_res_gpr_volume, "GPR mixer controls use 31-bit range.");
57
Linus Torvalds1da177e2005-04-16 15:20:36 -070058/*
59 * Tables
60 */
61
62static char *fxbuses[16] = {
63 /* 0x00 */ "PCM Left",
64 /* 0x01 */ "PCM Right",
65 /* 0x02 */ "PCM Surround Left",
66 /* 0x03 */ "PCM Surround Right",
67 /* 0x04 */ "MIDI Left",
68 /* 0x05 */ "MIDI Right",
69 /* 0x06 */ "Center",
70 /* 0x07 */ "LFE",
71 /* 0x08 */ NULL,
72 /* 0x09 */ NULL,
73 /* 0x0a */ NULL,
74 /* 0x0b */ NULL,
75 /* 0x0c */ "MIDI Reverb",
76 /* 0x0d */ "MIDI Chorus",
77 /* 0x0e */ NULL,
78 /* 0x0f */ NULL
79};
80
81static char *creative_ins[16] = {
82 /* 0x00 */ "AC97 Left",
83 /* 0x01 */ "AC97 Right",
84 /* 0x02 */ "TTL IEC958 Left",
85 /* 0x03 */ "TTL IEC958 Right",
86 /* 0x04 */ "Zoom Video Left",
87 /* 0x05 */ "Zoom Video Right",
88 /* 0x06 */ "Optical IEC958 Left",
89 /* 0x07 */ "Optical IEC958 Right",
90 /* 0x08 */ "Line/Mic 1 Left",
91 /* 0x09 */ "Line/Mic 1 Right",
92 /* 0x0a */ "Coaxial IEC958 Left",
93 /* 0x0b */ "Coaxial IEC958 Right",
94 /* 0x0c */ "Line/Mic 2 Left",
95 /* 0x0d */ "Line/Mic 2 Right",
96 /* 0x0e */ NULL,
97 /* 0x0f */ NULL
98};
99
100static char *audigy_ins[16] = {
101 /* 0x00 */ "AC97 Left",
102 /* 0x01 */ "AC97 Right",
103 /* 0x02 */ "Audigy CD Left",
104 /* 0x03 */ "Audigy CD Right",
105 /* 0x04 */ "Optical IEC958 Left",
106 /* 0x05 */ "Optical IEC958 Right",
107 /* 0x06 */ NULL,
108 /* 0x07 */ NULL,
109 /* 0x08 */ "Line/Mic 2 Left",
110 /* 0x09 */ "Line/Mic 2 Right",
111 /* 0x0a */ "SPDIF Left",
112 /* 0x0b */ "SPDIF Right",
113 /* 0x0c */ "Aux2 Left",
114 /* 0x0d */ "Aux2 Right",
115 /* 0x0e */ NULL,
116 /* 0x0f */ NULL
117};
118
119static char *creative_outs[32] = {
120 /* 0x00 */ "AC97 Left",
121 /* 0x01 */ "AC97 Right",
122 /* 0x02 */ "Optical IEC958 Left",
123 /* 0x03 */ "Optical IEC958 Right",
124 /* 0x04 */ "Center",
125 /* 0x05 */ "LFE",
126 /* 0x06 */ "Headphone Left",
127 /* 0x07 */ "Headphone Right",
128 /* 0x08 */ "Surround Left",
129 /* 0x09 */ "Surround Right",
130 /* 0x0a */ "PCM Capture Left",
131 /* 0x0b */ "PCM Capture Right",
132 /* 0x0c */ "MIC Capture",
133 /* 0x0d */ "AC97 Surround Left",
134 /* 0x0e */ "AC97 Surround Right",
135 /* 0x0f */ NULL,
136 /* 0x10 */ NULL,
137 /* 0x11 */ "Analog Center",
138 /* 0x12 */ "Analog LFE",
139 /* 0x13 */ NULL,
140 /* 0x14 */ NULL,
141 /* 0x15 */ NULL,
142 /* 0x16 */ NULL,
143 /* 0x17 */ NULL,
144 /* 0x18 */ NULL,
145 /* 0x19 */ NULL,
146 /* 0x1a */ NULL,
147 /* 0x1b */ NULL,
148 /* 0x1c */ NULL,
149 /* 0x1d */ NULL,
150 /* 0x1e */ NULL,
151 /* 0x1f */ NULL,
152};
153
154static char *audigy_outs[32] = {
155 /* 0x00 */ "Digital Front Left",
156 /* 0x01 */ "Digital Front Right",
157 /* 0x02 */ "Digital Center",
158 /* 0x03 */ "Digital LEF",
159 /* 0x04 */ "Headphone Left",
160 /* 0x05 */ "Headphone Right",
161 /* 0x06 */ "Digital Rear Left",
162 /* 0x07 */ "Digital Rear Right",
163 /* 0x08 */ "Front Left",
164 /* 0x09 */ "Front Right",
165 /* 0x0a */ "Center",
166 /* 0x0b */ "LFE",
167 /* 0x0c */ NULL,
168 /* 0x0d */ NULL,
169 /* 0x0e */ "Rear Left",
170 /* 0x0f */ "Rear Right",
171 /* 0x10 */ "AC97 Front Left",
172 /* 0x11 */ "AC97 Front Right",
173 /* 0x12 */ "ADC Caputre Left",
174 /* 0x13 */ "ADC Capture Right",
175 /* 0x14 */ NULL,
176 /* 0x15 */ NULL,
177 /* 0x16 */ NULL,
178 /* 0x17 */ NULL,
179 /* 0x18 */ NULL,
180 /* 0x19 */ NULL,
181 /* 0x1a */ NULL,
182 /* 0x1b */ NULL,
183 /* 0x1c */ NULL,
184 /* 0x1d */ NULL,
185 /* 0x1e */ NULL,
186 /* 0x1f */ NULL,
187};
188
189static const u32 bass_table[41][5] = {
190 { 0x3e4f844f, 0x84ed4cc3, 0x3cc69927, 0x7b03553a, 0xc4da8486 },
191 { 0x3e69a17a, 0x84c280fb, 0x3cd77cd4, 0x7b2f2a6f, 0xc4b08d1d },
192 { 0x3e82ff42, 0x849991d5, 0x3ce7466b, 0x7b5917c6, 0xc48863ee },
193 { 0x3e9bab3c, 0x847267f0, 0x3cf5ffe8, 0x7b813560, 0xc461f22c },
194 { 0x3eb3b275, 0x844ced29, 0x3d03b295, 0x7ba79a1c, 0xc43d223b },
195 { 0x3ecb2174, 0x84290c8b, 0x3d106714, 0x7bcc5ba3, 0xc419dfa5 },
196 { 0x3ee2044b, 0x8406b244, 0x3d1c2561, 0x7bef8e77, 0xc3f8170f },
197 { 0x3ef86698, 0x83e5cb96, 0x3d26f4d8, 0x7c114600, 0xc3d7b625 },
198 { 0x3f0e5390, 0x83c646c9, 0x3d30dc39, 0x7c319498, 0xc3b8ab97 },
199 { 0x3f23d60b, 0x83a81321, 0x3d39e1af, 0x7c508b9c, 0xc39ae704 },
200 { 0x3f38f884, 0x838b20d2, 0x3d420ad2, 0x7c6e3b75, 0xc37e58f1 },
201 { 0x3f4dc52c, 0x836f60ef, 0x3d495cab, 0x7c8ab3a6, 0xc362f2be },
202 { 0x3f6245e8, 0x8354c565, 0x3d4fdbb8, 0x7ca602d6, 0xc348a69b },
203 { 0x3f76845f, 0x833b40ec, 0x3d558bf0, 0x7cc036df, 0xc32f677c },
204 { 0x3f8a8a03, 0x8322c6fb, 0x3d5a70c4, 0x7cd95cd7, 0xc317290b },
205 { 0x3f9e6014, 0x830b4bc3, 0x3d5e8d25, 0x7cf1811a, 0xc2ffdfa5 },
206 { 0x3fb20fae, 0x82f4c420, 0x3d61e37f, 0x7d08af56, 0xc2e9804a },
207 { 0x3fc5a1cc, 0x82df2592, 0x3d6475c3, 0x7d1ef294, 0xc2d40096 },
208 { 0x3fd91f55, 0x82ca6632, 0x3d664564, 0x7d345541, 0xc2bf56b9 },
209 { 0x3fec9120, 0x82b67cac, 0x3d675356, 0x7d48e138, 0xc2ab796e },
210 { 0x40000000, 0x82a36037, 0x3d67a012, 0x7d5c9fc9, 0xc2985fee },
211 { 0x401374c7, 0x8291088a, 0x3d672b93, 0x7d6f99c3, 0xc28601f2 },
212 { 0x4026f857, 0x827f6dd7, 0x3d65f559, 0x7d81d77c, 0xc27457a3 },
213 { 0x403a939f, 0x826e88c5, 0x3d63fc63, 0x7d9360d4, 0xc2635996 },
214 { 0x404e4faf, 0x825e5266, 0x3d613f32, 0x7da43d42, 0xc25300c6 },
215 { 0x406235ba, 0x824ec434, 0x3d5dbbc3, 0x7db473d7, 0xc243468e },
216 { 0x40764f1f, 0x823fd80c, 0x3d596f8f, 0x7dc40b44, 0xc23424a2 },
217 { 0x408aa576, 0x82318824, 0x3d545787, 0x7dd309e2, 0xc2259509 },
218 { 0x409f4296, 0x8223cf0b, 0x3d4e7012, 0x7de175b5, 0xc2179218 },
219 { 0x40b430a0, 0x8216a7a1, 0x3d47b505, 0x7def5475, 0xc20a1670 },
220 { 0x40c97a0a, 0x820a0d12, 0x3d4021a1, 0x7dfcab8d, 0xc1fd1cf5 },
221 { 0x40df29a6, 0x81fdfad6, 0x3d37b08d, 0x7e098028, 0xc1f0a0ca },
222 { 0x40f54ab1, 0x81f26ca9, 0x3d2e5bd1, 0x7e15d72b, 0xc1e49d52 },
223 { 0x410be8da, 0x81e75e89, 0x3d241cce, 0x7e21b544, 0xc1d90e24 },
224 { 0x41231051, 0x81dcccb3, 0x3d18ec37, 0x7e2d1ee6, 0xc1cdef10 },
225 { 0x413acdd0, 0x81d2b39e, 0x3d0cc20a, 0x7e38184e, 0xc1c33c13 },
226 { 0x41532ea7, 0x81c90ffb, 0x3cff9585, 0x7e42a58b, 0xc1b8f15a },
227 { 0x416c40cd, 0x81bfdeb2, 0x3cf15d21, 0x7e4cca7c, 0xc1af0b3f },
228 { 0x418612ea, 0x81b71cdc, 0x3ce20e85, 0x7e568ad3, 0xc1a58640 },
229 { 0x41a0b465, 0x81aec7c5, 0x3cd19e7c, 0x7e5fea1e, 0xc19c5f03 },
230 { 0x41bc3573, 0x81a6dcea, 0x3cc000e9, 0x7e68ebc2, 0xc1939250 }
231};
232
233static const u32 treble_table[41][5] = {
234 { 0x0125cba9, 0xfed5debd, 0x00599b6c, 0x0d2506da, 0xfa85b354 },
235 { 0x0142f67e, 0xfeb03163, 0x0066cd0f, 0x0d14c69d, 0xfa914473 },
236 { 0x016328bd, 0xfe860158, 0x0075b7f2, 0x0d03eb27, 0xfa9d32d2 },
237 { 0x0186b438, 0xfe56c982, 0x00869234, 0x0cf27048, 0xfaa97fca },
238 { 0x01adf358, 0xfe21f5fe, 0x00999842, 0x0ce051c2, 0xfab62ca5 },
239 { 0x01d949fa, 0xfde6e287, 0x00af0d8d, 0x0ccd8b4a, 0xfac33aa7 },
240 { 0x02092669, 0xfda4d8bf, 0x00c73d4c, 0x0cba1884, 0xfad0ab07 },
241 { 0x023e0268, 0xfd5b0e4a, 0x00e27b54, 0x0ca5f509, 0xfade7ef2 },
242 { 0x0278645c, 0xfd08a2b0, 0x01012509, 0x0c911c63, 0xfaecb788 },
243 { 0x02b8e091, 0xfcac9d1a, 0x0123a262, 0x0c7b8a14, 0xfafb55df },
244 { 0x03001a9a, 0xfc45e9ce, 0x014a6709, 0x0c65398f, 0xfb0a5aff },
245 { 0x034ec6d7, 0xfbd3576b, 0x0175f397, 0x0c4e2643, 0xfb19c7e4 },
246 { 0x03a5ac15, 0xfb5393ee, 0x01a6d6ed, 0x0c364b94, 0xfb299d7c },
247 { 0x0405a562, 0xfac52968, 0x01ddafae, 0x0c1da4e2, 0xfb39dca5 },
248 { 0x046fa3fe, 0xfa267a66, 0x021b2ddd, 0x0c042d8d, 0xfb4a8631 },
249 { 0x04e4b17f, 0xf975be0f, 0x0260149f, 0x0be9e0f2, 0xfb5b9ae0 },
250 { 0x0565f220, 0xf8b0fbe5, 0x02ad3c29, 0x0bceba73, 0xfb6d1b60 },
251 { 0x05f4a745, 0xf7d60722, 0x030393d4, 0x0bb2b578, 0xfb7f084d },
252 { 0x06923236, 0xf6e279bd, 0x03642465, 0x0b95cd75, 0xfb916233 },
253 { 0x07401713, 0xf5d3aef9, 0x03d01283, 0x0b77fded, 0xfba42984 },
254 { 0x08000000, 0xf4a6bd88, 0x0448a161, 0x0b594278, 0xfbb75e9f },
255 { 0x08d3c097, 0xf3587131, 0x04cf35a4, 0x0b3996c9, 0xfbcb01cb },
256 { 0x09bd59a2, 0xf1e543f9, 0x05655880, 0x0b18f6b2, 0xfbdf1333 },
257 { 0x0abefd0f, 0xf04956ca, 0x060cbb12, 0x0af75e2c, 0xfbf392e8 },
258 { 0x0bdb123e, 0xee806984, 0x06c739fe, 0x0ad4c962, 0xfc0880dd },
259 { 0x0d143a94, 0xec85d287, 0x0796e150, 0x0ab134b0, 0xfc1ddce5 },
260 { 0x0e6d5664, 0xea547598, 0x087df0a0, 0x0a8c9cb6, 0xfc33a6ad },
261 { 0x0fe98a2a, 0xe7e6ba35, 0x097edf83, 0x0a66fe5b, 0xfc49ddc2 },
262 { 0x118c4421, 0xe536813a, 0x0a9c6248, 0x0a4056d7, 0xfc608185 },
263 { 0x1359422e, 0xe23d19eb, 0x0bd96efb, 0x0a18a3bf, 0xfc77912c },
264 { 0x1554982b, 0xdef33645, 0x0d3942bd, 0x09efe312, 0xfc8f0bc1 },
265 { 0x1782b68a, 0xdb50deb1, 0x0ebf676d, 0x09c6133f, 0xfca6f019 },
266 { 0x19e8715d, 0xd74d64fd, 0x106fb999, 0x099b3337, 0xfcbf3cd6 },
267 { 0x1c8b07b8, 0xd2df56ab, 0x124e6ec8, 0x096f4274, 0xfcd7f060 },
268 { 0x1f702b6d, 0xcdfc6e92, 0x14601c10, 0x0942410b, 0xfcf108e5 },
269 { 0x229e0933, 0xc89985cd, 0x16a9bcfa, 0x09142fb5, 0xfd0a8451 },
270 { 0x261b5118, 0xc2aa8409, 0x1930bab6, 0x08e50fdc, 0xfd24604d },
271 { 0x29ef3f5d, 0xbc224f28, 0x1bfaf396, 0x08b4e3aa, 0xfd3e9a3b },
272 { 0x2e21a59b, 0xb4f2ba46, 0x1f0ec2d6, 0x0883ae15, 0xfd592f33 },
273 { 0x32baf44b, 0xad0c7429, 0x227308a3, 0x085172eb, 0xfd741bfd },
274 { 0x37c4448b, 0xa45ef51d, 0x262f3267, 0x081e36dc, 0xfd8f5d14 }
275};
276
James Courtier-Dutton7012b2d2006-07-28 22:27:56 +0100277/* dB gain = (float) 20 * log10( float(db_table_value) / 0x8000000 ) */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700278static const u32 db_table[101] = {
279 0x00000000, 0x01571f82, 0x01674b41, 0x01783a1b, 0x0189f540,
280 0x019c8651, 0x01aff763, 0x01c45306, 0x01d9a446, 0x01eff6b8,
281 0x0207567a, 0x021fd03d, 0x0239714c, 0x02544792, 0x027061a1,
282 0x028dcebb, 0x02ac9edc, 0x02cce2bf, 0x02eeabe8, 0x03120cb0,
283 0x0337184e, 0x035de2df, 0x03868173, 0x03b10a18, 0x03dd93e9,
284 0x040c3713, 0x043d0cea, 0x04702ff3, 0x04a5bbf2, 0x04ddcdfb,
285 0x0518847f, 0x0555ff62, 0x05966005, 0x05d9c95d, 0x06206005,
286 0x066a4a52, 0x06b7b067, 0x0708bc4c, 0x075d9a01, 0x07b6779d,
287 0x08138561, 0x0874f5d5, 0x08dafde1, 0x0945d4ed, 0x09b5b4fd,
288 0x0a2adad1, 0x0aa58605, 0x0b25f936, 0x0bac7a24, 0x0c3951d8,
289 0x0ccccccc, 0x0d673b17, 0x0e08f093, 0x0eb24510, 0x0f639481,
290 0x101d3f2d, 0x10dfa9e6, 0x11ab3e3f, 0x12806ac3, 0x135fa333,
291 0x144960c5, 0x153e2266, 0x163e6cfe, 0x174acbb7, 0x1863d04d,
292 0x198a1357, 0x1abe349f, 0x1c00db77, 0x1d52b712, 0x1eb47ee6,
293 0x2026f30f, 0x21aadcb6, 0x23410e7e, 0x24ea64f9, 0x26a7c71d,
294 0x287a26c4, 0x2a62812c, 0x2c61df84, 0x2e795779, 0x30aa0bcf,
295 0x32f52cfe, 0x355bf9d8, 0x37dfc033, 0x3a81dda4, 0x3d43c038,
296 0x4026e73c, 0x432ce40f, 0x46575af8, 0x49a8040f, 0x4d20ac2a,
297 0x50c335d3, 0x54919a57, 0x588dead1, 0x5cba514a, 0x611911ea,
298 0x65ac8c2f, 0x6a773c39, 0x6f7bbc23, 0x74bcc56c, 0x7a3d3272,
299 0x7fffffff,
300};
301
James Courtier-Dutton31508f82006-07-22 17:02:10 +0100302/* EMU10k1/EMU10k2 DSP control db gain */
Takashi Iwai0cb29ea2007-01-29 15:33:49 +0100303static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1);
Clemens Ladisch4daf7a02010-05-25 09:04:49 +0200304static const DECLARE_TLV_DB_LINEAR(snd_emu10k1_db_linear, TLV_DB_GAIN_MUTE, 0);
James Courtier-Dutton31508f82006-07-22 17:02:10 +0100305
Linus Torvalds1da177e2005-04-16 15:20:36 -0700306static const u32 onoff_table[2] = {
307 0x00000000, 0x00000001
308};
309
310/*
311 */
312
313static inline mm_segment_t snd_enter_user(void)
314{
315 mm_segment_t fs = get_fs();
316 set_fs(get_ds());
317 return fs;
318}
319
320static inline void snd_leave_user(mm_segment_t fs)
321{
322 set_fs(fs);
323}
324
325/*
326 * controls
327 */
328
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100329static int snd_emu10k1_gpr_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100331 struct snd_emu10k1_fx8010_ctl *ctl =
332 (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333
334 if (ctl->min == 0 && ctl->max == 1)
335 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
336 else
337 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
338 uinfo->count = ctl->vcount;
339 uinfo->value.integer.min = ctl->min;
340 uinfo->value.integer.max = ctl->max;
341 return 0;
342}
343
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100344static int snd_emu10k1_gpr_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700345{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100346 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
347 struct snd_emu10k1_fx8010_ctl *ctl =
348 (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349 unsigned long flags;
350 unsigned int i;
351
352 spin_lock_irqsave(&emu->reg_lock, flags);
353 for (i = 0; i < ctl->vcount; i++)
354 ucontrol->value.integer.value[i] = ctl->value[i];
355 spin_unlock_irqrestore(&emu->reg_lock, flags);
356 return 0;
357}
358
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100359static int snd_emu10k1_gpr_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700360{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100361 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
362 struct snd_emu10k1_fx8010_ctl *ctl =
363 (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700364 unsigned long flags;
365 unsigned int nval, val;
366 unsigned int i, j;
367 int change = 0;
368
369 spin_lock_irqsave(&emu->reg_lock, flags);
370 for (i = 0; i < ctl->vcount; i++) {
371 nval = ucontrol->value.integer.value[i];
372 if (nval < ctl->min)
373 nval = ctl->min;
374 if (nval > ctl->max)
375 nval = ctl->max;
376 if (nval != ctl->value[i])
377 change = 1;
378 val = ctl->value[i] = nval;
379 switch (ctl->translation) {
380 case EMU10K1_GPR_TRANSLATION_NONE:
381 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, val);
382 break;
383 case EMU10K1_GPR_TRANSLATION_TABLE100:
384 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]);
385 break;
386 case EMU10K1_GPR_TRANSLATION_BASS:
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200387 if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) {
388 change = -EIO;
389 goto __error;
390 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700391 for (j = 0; j < 5; j++)
392 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]);
393 break;
394 case EMU10K1_GPR_TRANSLATION_TREBLE:
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200395 if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) {
396 change = -EIO;
397 goto __error;
398 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399 for (j = 0; j < 5; j++)
400 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]);
401 break;
402 case EMU10K1_GPR_TRANSLATION_ONOFF:
403 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, onoff_table[val]);
404 break;
405 }
406 }
407 __error:
408 spin_unlock_irqrestore(&emu->reg_lock, flags);
409 return change;
410}
411
412/*
413 * Interrupt handler
414 */
415
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100416static void snd_emu10k1_fx8010_interrupt(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700417{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100418 struct snd_emu10k1_fx8010_irq *irq, *nirq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700419
420 irq = emu->fx8010.irq_handlers;
421 while (irq) {
422 nirq = irq->next; /* irq ptr can be removed from list */
423 if (snd_emu10k1_ptr_read(emu, emu->gpr_base + irq->gpr_running, 0) & 0xffff0000) {
424 if (irq->handler)
425 irq->handler(emu, irq->private_data);
426 snd_emu10k1_ptr_write(emu, emu->gpr_base + irq->gpr_running, 0, 1);
427 }
428 irq = nirq;
429 }
430}
431
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100432int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
433 snd_fx8010_irq_handler_t *handler,
434 unsigned char gpr_running,
435 void *private_data,
436 struct snd_emu10k1_fx8010_irq **r_irq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100438 struct snd_emu10k1_fx8010_irq *irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 unsigned long flags;
440
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 irq = kmalloc(sizeof(*irq), GFP_ATOMIC);
442 if (irq == NULL)
443 return -ENOMEM;
444 irq->handler = handler;
445 irq->gpr_running = gpr_running;
446 irq->private_data = private_data;
447 irq->next = NULL;
448 spin_lock_irqsave(&emu->fx8010.irq_lock, flags);
449 if (emu->fx8010.irq_handlers == NULL) {
450 emu->fx8010.irq_handlers = irq;
451 emu->dsp_interrupt = snd_emu10k1_fx8010_interrupt;
452 snd_emu10k1_intr_enable(emu, INTE_FXDSPENABLE);
453 } else {
454 irq->next = emu->fx8010.irq_handlers;
455 emu->fx8010.irq_handlers = irq;
456 }
457 spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
458 if (r_irq)
459 *r_irq = irq;
460 return 0;
461}
462
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100463int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
464 struct snd_emu10k1_fx8010_irq *irq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100466 struct snd_emu10k1_fx8010_irq *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467 unsigned long flags;
468
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469 spin_lock_irqsave(&emu->fx8010.irq_lock, flags);
470 if ((tmp = emu->fx8010.irq_handlers) == irq) {
471 emu->fx8010.irq_handlers = tmp->next;
472 if (emu->fx8010.irq_handlers == NULL) {
473 snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
474 emu->dsp_interrupt = NULL;
475 }
476 } else {
477 while (tmp && tmp->next != irq)
478 tmp = tmp->next;
479 if (tmp)
480 tmp->next = tmp->next->next;
481 }
482 spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
483 kfree(irq);
484 return 0;
485}
486
487/*************************************************************************
488 * EMU10K1 effect manager
489 *************************************************************************/
490
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100491static void snd_emu10k1_write_op(struct snd_emu10k1_fx8010_code *icode,
492 unsigned int *ptr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 u32 op, u32 r, u32 a, u32 x, u32 y)
494{
495 u_int32_t *code;
Takashi Iwaida3cec32008-08-08 17:12:14 +0200496 if (snd_BUG_ON(*ptr >= 512))
497 return;
Clemens Ladisch4d233592005-09-05 10:35:20 +0200498 code = (u_int32_t __force *)icode->code + (*ptr) * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499 set_bit(*ptr, icode->code_valid);
500 code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
501 code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
502 (*ptr)++;
503}
504
505#define OP(icode, ptr, op, r, a, x, y) \
506 snd_emu10k1_write_op(icode, ptr, op, r, a, x, y)
507
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100508static void snd_emu10k1_audigy_write_op(struct snd_emu10k1_fx8010_code *icode,
509 unsigned int *ptr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510 u32 op, u32 r, u32 a, u32 x, u32 y)
511{
512 u_int32_t *code;
Takashi Iwaida3cec32008-08-08 17:12:14 +0200513 if (snd_BUG_ON(*ptr >= 1024))
514 return;
Clemens Ladisch4d233592005-09-05 10:35:20 +0200515 code = (u_int32_t __force *)icode->code + (*ptr) * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 set_bit(*ptr, icode->code_valid);
517 code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
518 code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
519 (*ptr)++;
520}
521
522#define A_OP(icode, ptr, op, r, a, x, y) \
523 snd_emu10k1_audigy_write_op(icode, ptr, op, r, a, x, y)
524
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100525static void snd_emu10k1_efx_write(struct snd_emu10k1 *emu, unsigned int pc, unsigned int data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
527 pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
528 snd_emu10k1_ptr_write(emu, pc, 0, data);
529}
530
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100531unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532{
533 pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
534 return snd_emu10k1_ptr_read(emu, pc, 0);
535}
536
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100537static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu,
538 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539{
540 int gpr;
541 u32 val;
542
543 for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
544 if (!test_bit(gpr, icode->gpr_valid))
545 continue;
546 if (get_user(val, &icode->gpr_map[gpr]))
547 return -EFAULT;
548 snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val);
549 }
550 return 0;
551}
552
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100553static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu,
554 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555{
556 int gpr;
557 u32 val;
558
559 for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
560 set_bit(gpr, icode->gpr_valid);
561 val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0);
562 if (put_user(val, &icode->gpr_map[gpr]))
563 return -EFAULT;
564 }
565 return 0;
566}
567
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100568static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu,
569 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570{
571 int tram;
572 u32 addr, val;
573
574 for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
575 if (!test_bit(tram, icode->tram_valid))
576 continue;
577 if (get_user(val, &icode->tram_data_map[tram]) ||
578 get_user(addr, &icode->tram_addr_map[tram]))
579 return -EFAULT;
580 snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val);
581 if (!emu->audigy) {
582 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr);
583 } else {
584 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr << 12);
585 snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, addr >> 20);
586 }
587 }
588 return 0;
589}
590
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100591static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu,
592 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 int tram;
595 u32 val, addr;
596
597 memset(icode->tram_valid, 0, sizeof(icode->tram_valid));
598 for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
599 set_bit(tram, icode->tram_valid);
600 val = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0);
601 if (!emu->audigy) {
602 addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0);
603 } else {
604 addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12;
605 addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20;
606 }
607 if (put_user(val, &icode->tram_data_map[tram]) ||
608 put_user(addr, &icode->tram_addr_map[tram]))
609 return -EFAULT;
610 }
611 return 0;
612}
613
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100614static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu,
615 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616{
617 u32 pc, lo, hi;
618
619 for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
620 if (!test_bit(pc / 2, icode->code_valid))
621 continue;
622 if (get_user(lo, &icode->code[pc + 0]) ||
623 get_user(hi, &icode->code[pc + 1]))
624 return -EFAULT;
625 snd_emu10k1_efx_write(emu, pc + 0, lo);
626 snd_emu10k1_efx_write(emu, pc + 1, hi);
627 }
628 return 0;
629}
630
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100631static int snd_emu10k1_code_peek(struct snd_emu10k1 *emu,
632 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633{
634 u32 pc;
635
636 memset(icode->code_valid, 0, sizeof(icode->code_valid));
637 for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
638 set_bit(pc / 2, icode->code_valid);
639 if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0]))
640 return -EFAULT;
641 if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1]))
642 return -EFAULT;
643 }
644 return 0;
645}
646
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100647static struct snd_emu10k1_fx8010_ctl *
648snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100650 struct snd_emu10k1_fx8010_ctl *ctl;
651 struct snd_kcontrol *kcontrol;
Matthias Kaehlckec2d70512007-09-17 14:41:16 +0200652
653 list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700654 kcontrol = ctl->kcontrol;
655 if (kcontrol->id.iface == id->iface &&
656 !strcmp(kcontrol->id.name, id->name) &&
657 kcontrol->id.index == id->index)
658 return ctl;
659 }
660 return NULL;
661}
662
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100663#define MAX_TLV_SIZE 256
664
Takashi Iwai0cb29ea2007-01-29 15:33:49 +0100665static unsigned int *copy_tlv(const unsigned int __user *_tlv)
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100666{
667 unsigned int data[2];
668 unsigned int *tlv;
669
670 if (!_tlv)
671 return NULL;
672 if (copy_from_user(data, _tlv, sizeof(data)))
673 return NULL;
674 if (data[1] >= MAX_TLV_SIZE)
675 return NULL;
Takashi Iwai6735e572008-01-19 10:33:07 +0100676 tlv = kmalloc(data[1] + sizeof(data), GFP_KERNEL);
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100677 if (!tlv)
678 return NULL;
679 memcpy(tlv, data, sizeof(data));
680 if (copy_from_user(tlv + 2, _tlv + 2, data[1])) {
681 kfree(tlv);
682 return NULL;
683 }
684 return tlv;
685}
686
687static int copy_gctl(struct snd_emu10k1 *emu,
688 struct snd_emu10k1_fx8010_control_gpr *gctl,
689 struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
690 int idx)
691{
692 struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
693
694 if (emu->support_tlv)
695 return copy_from_user(gctl, &_gctl[idx], sizeof(*gctl));
696 octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
697 if (copy_from_user(gctl, &octl[idx], sizeof(*octl)))
698 return -EFAULT;
699 gctl->tlv = NULL;
700 return 0;
701}
702
703static int copy_gctl_to_user(struct snd_emu10k1 *emu,
704 struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
705 struct snd_emu10k1_fx8010_control_gpr *gctl,
706 int idx)
707{
708 struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
709
710 if (emu->support_tlv)
711 return copy_to_user(&_gctl[idx], gctl, sizeof(*gctl));
712
713 octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
714 return copy_to_user(&octl[idx], gctl, sizeof(*octl));
715}
716
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100717static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
718 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719{
720 unsigned int i;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100721 struct snd_ctl_elem_id __user *_id;
722 struct snd_ctl_elem_id id;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100723 struct snd_emu10k1_fx8010_control_gpr *gctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 int err;
725
726 for (i = 0, _id = icode->gpr_del_controls;
727 i < icode->gpr_del_control_count; i++, _id++) {
728 if (copy_from_user(&id, _id, sizeof(id)))
729 return -EFAULT;
730 if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)
731 return -ENOENT;
732 }
733 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
734 if (! gctl)
735 return -ENOMEM;
736 err = 0;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100737 for (i = 0; i < icode->gpr_add_control_count; i++) {
738 if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 err = -EFAULT;
740 goto __error;
741 }
742 if (snd_emu10k1_look_for_ctl(emu, &gctl->id))
743 continue;
744 down_read(&emu->card->controls_rwsem);
745 if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) {
746 up_read(&emu->card->controls_rwsem);
747 err = -EEXIST;
748 goto __error;
749 }
750 up_read(&emu->card->controls_rwsem);
751 if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
752 gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
753 err = -EINVAL;
754 goto __error;
755 }
756 }
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100757 for (i = 0; i < icode->gpr_list_control_count; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 /* FIXME: we need to check the WRITE access */
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100759 if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 err = -EFAULT;
761 goto __error;
762 }
763 }
764 __error:
765 kfree(gctl);
766 return err;
767}
768
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100769static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100771 struct snd_emu10k1_fx8010_ctl *ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700772
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100773 ctl = (struct snd_emu10k1_fx8010_ctl *) kctl->private_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700774 kctl->private_value = 0;
775 list_del(&ctl->list);
776 kfree(ctl);
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100777 if (kctl->tlv.p)
778 kfree(kctl->tlv.p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779}
780
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100781static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
782 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
784 unsigned int i, j;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100785 struct snd_emu10k1_fx8010_control_gpr *gctl;
786 struct snd_emu10k1_fx8010_ctl *ctl, *nctl;
787 struct snd_kcontrol_new knew;
788 struct snd_kcontrol *kctl;
789 struct snd_ctl_elem_value *val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700790 int err = 0;
791
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100792 val = kmalloc(sizeof(*val), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
794 nctl = kmalloc(sizeof(*nctl), GFP_KERNEL);
795 if (!val || !gctl || !nctl) {
796 err = -ENOMEM;
797 goto __error;
798 }
799
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100800 for (i = 0; i < icode->gpr_add_control_count; i++) {
801 if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802 err = -EFAULT;
803 goto __error;
804 }
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200805 if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
806 gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
807 err = -EINVAL;
808 goto __error;
809 }
810 if (! gctl->id.name[0]) {
811 err = -EINVAL;
812 goto __error;
813 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700814 ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id);
815 memset(&knew, 0, sizeof(knew));
816 knew.iface = gctl->id.iface;
817 knew.name = gctl->id.name;
818 knew.index = gctl->id.index;
819 knew.device = gctl->id.device;
820 knew.subdevice = gctl->id.subdevice;
821 knew.info = snd_emu10k1_gpr_ctl_info;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100822 knew.tlv.p = copy_tlv(gctl->tlv);
823 if (knew.tlv.p)
James Courtier-Dutton31508f82006-07-22 17:02:10 +0100824 knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
825 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 knew.get = snd_emu10k1_gpr_ctl_get;
827 knew.put = snd_emu10k1_gpr_ctl_put;
828 memset(nctl, 0, sizeof(*nctl));
829 nctl->vcount = gctl->vcount;
830 nctl->count = gctl->count;
831 for (j = 0; j < 32; j++) {
832 nctl->gpr[j] = gctl->gpr[j];
833 nctl->value[j] = ~gctl->value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
834 val->value.integer.value[j] = gctl->value[j];
835 }
836 nctl->min = gctl->min;
837 nctl->max = gctl->max;
838 nctl->translation = gctl->translation;
839 if (ctl == NULL) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100840 ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841 if (ctl == NULL) {
842 err = -ENOMEM;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100843 kfree(knew.tlv.p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 goto __error;
845 }
846 knew.private_value = (unsigned long)ctl;
847 *ctl = *nctl;
848 if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) {
849 kfree(ctl);
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100850 kfree(knew.tlv.p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700851 goto __error;
852 }
853 kctl->private_free = snd_emu10k1_ctl_private_free;
854 ctl->kcontrol = kctl;
855 list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl);
856 } else {
857 /* overwrite */
858 nctl->list = ctl->list;
859 nctl->kcontrol = ctl->kcontrol;
860 *ctl = *nctl;
861 snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
862 SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id);
863 }
864 snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val);
865 }
866 __error:
867 kfree(nctl);
868 kfree(gctl);
869 kfree(val);
870 return err;
871}
872
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100873static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu,
874 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875{
876 unsigned int i;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100877 struct snd_ctl_elem_id id;
878 struct snd_ctl_elem_id __user *_id;
879 struct snd_emu10k1_fx8010_ctl *ctl;
880 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881
882 for (i = 0, _id = icode->gpr_del_controls;
883 i < icode->gpr_del_control_count; i++, _id++) {
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200884 if (copy_from_user(&id, _id, sizeof(id)))
885 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700886 down_write(&card->controls_rwsem);
887 ctl = snd_emu10k1_look_for_ctl(emu, &id);
888 if (ctl)
889 snd_ctl_remove(card, ctl->kcontrol);
890 up_write(&card->controls_rwsem);
891 }
892 return 0;
893}
894
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100895static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
896 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700897{
898 unsigned int i = 0, j;
899 unsigned int total = 0;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100900 struct snd_emu10k1_fx8010_control_gpr *gctl;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100901 struct snd_emu10k1_fx8010_ctl *ctl;
902 struct snd_ctl_elem_id *id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903
904 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
905 if (! gctl)
906 return -ENOMEM;
907
Matthias Kaehlckec2d70512007-09-17 14:41:16 +0200908 list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700909 total++;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100910 if (icode->gpr_list_controls &&
911 i < icode->gpr_list_control_count) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700912 memset(gctl, 0, sizeof(*gctl));
913 id = &ctl->kcontrol->id;
914 gctl->id.iface = id->iface;
915 strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
916 gctl->id.index = id->index;
917 gctl->id.device = id->device;
918 gctl->id.subdevice = id->subdevice;
919 gctl->vcount = ctl->vcount;
920 gctl->count = ctl->count;
921 for (j = 0; j < 32; j++) {
922 gctl->gpr[j] = ctl->gpr[j];
923 gctl->value[j] = ctl->value[j];
924 }
925 gctl->min = ctl->min;
926 gctl->max = ctl->max;
927 gctl->translation = ctl->translation;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100928 if (copy_gctl_to_user(emu, icode->gpr_list_controls,
929 gctl, i)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 kfree(gctl);
931 return -EFAULT;
932 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700933 i++;
934 }
935 }
936 icode->gpr_list_control_total = total;
937 kfree(gctl);
938 return 0;
939}
940
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100941static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu,
942 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700943{
944 int err = 0;
945
Ingo Molnar62932df2006-01-16 16:34:20 +0100946 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947 if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0)
948 goto __error;
949 strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
950 /* stop FX processor - this may be dangerous, but it's better to miss
951 some samples than generate wrong ones - [jk] */
952 if (emu->audigy)
953 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP);
954 else
955 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);
956 /* ok, do the main job */
957 if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 ||
958 (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 ||
959 (err = snd_emu10k1_tram_poke(emu, icode)) < 0 ||
960 (err = snd_emu10k1_code_poke(emu, icode)) < 0 ||
961 (err = snd_emu10k1_add_controls(emu, icode)) < 0)
962 goto __error;
963 /* start FX processor when the DSP code is updated */
964 if (emu->audigy)
965 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
966 else
967 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
968 __error:
Ingo Molnar62932df2006-01-16 16:34:20 +0100969 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 return err;
971}
972
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100973static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu,
974 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975{
976 int err;
977
Ingo Molnar62932df2006-01-16 16:34:20 +0100978 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name));
980 /* ok, do the main job */
981 err = snd_emu10k1_gpr_peek(emu, icode);
982 if (err >= 0)
983 err = snd_emu10k1_tram_peek(emu, icode);
984 if (err >= 0)
985 err = snd_emu10k1_code_peek(emu, icode);
986 if (err >= 0)
987 err = snd_emu10k1_list_controls(emu, icode);
Ingo Molnar62932df2006-01-16 16:34:20 +0100988 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989 return err;
990}
991
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100992static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu,
993 struct snd_emu10k1_fx8010_pcm_rec *ipcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994{
995 unsigned int i;
996 int err = 0;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100997 struct snd_emu10k1_fx8010_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700998
999 if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
1000 return -EINVAL;
1001 if (ipcm->channels > 32)
1002 return -EINVAL;
1003 pcm = &emu->fx8010.pcm[ipcm->substream];
Ingo Molnar62932df2006-01-16 16:34:20 +01001004 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005 spin_lock_irq(&emu->reg_lock);
1006 if (pcm->opened) {
1007 err = -EBUSY;
1008 goto __error;
1009 }
1010 if (ipcm->channels == 0) { /* remove */
1011 pcm->valid = 0;
1012 } else {
1013 /* FIXME: we need to add universal code to the PCM transfer routine */
1014 if (ipcm->channels != 2) {
1015 err = -EINVAL;
1016 goto __error;
1017 }
1018 pcm->valid = 1;
1019 pcm->opened = 0;
1020 pcm->channels = ipcm->channels;
1021 pcm->tram_start = ipcm->tram_start;
1022 pcm->buffer_size = ipcm->buffer_size;
1023 pcm->gpr_size = ipcm->gpr_size;
1024 pcm->gpr_count = ipcm->gpr_count;
1025 pcm->gpr_tmpcount = ipcm->gpr_tmpcount;
1026 pcm->gpr_ptr = ipcm->gpr_ptr;
1027 pcm->gpr_trigger = ipcm->gpr_trigger;
1028 pcm->gpr_running = ipcm->gpr_running;
1029 for (i = 0; i < pcm->channels; i++)
1030 pcm->etram[i] = ipcm->etram[i];
1031 }
1032 __error:
1033 spin_unlock_irq(&emu->reg_lock);
Ingo Molnar62932df2006-01-16 16:34:20 +01001034 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035 return err;
1036}
1037
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001038static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu,
1039 struct snd_emu10k1_fx8010_pcm_rec *ipcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001040{
1041 unsigned int i;
1042 int err = 0;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001043 struct snd_emu10k1_fx8010_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044
1045 if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
1046 return -EINVAL;
1047 pcm = &emu->fx8010.pcm[ipcm->substream];
Ingo Molnar62932df2006-01-16 16:34:20 +01001048 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 spin_lock_irq(&emu->reg_lock);
1050 ipcm->channels = pcm->channels;
1051 ipcm->tram_start = pcm->tram_start;
1052 ipcm->buffer_size = pcm->buffer_size;
1053 ipcm->gpr_size = pcm->gpr_size;
1054 ipcm->gpr_ptr = pcm->gpr_ptr;
1055 ipcm->gpr_count = pcm->gpr_count;
1056 ipcm->gpr_tmpcount = pcm->gpr_tmpcount;
1057 ipcm->gpr_trigger = pcm->gpr_trigger;
1058 ipcm->gpr_running = pcm->gpr_running;
1059 for (i = 0; i < pcm->channels; i++)
1060 ipcm->etram[i] = pcm->etram[i];
1061 ipcm->res1 = ipcm->res2 = 0;
1062 ipcm->pad = 0;
1063 spin_unlock_irq(&emu->reg_lock);
Ingo Molnar62932df2006-01-16 16:34:20 +01001064 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 return err;
1066}
1067
Mikael Magnussonedf8e452005-09-13 11:32:58 +02001068#define SND_EMU10K1_GPR_CONTROLS 44
1069#define SND_EMU10K1_INPUTS 12
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070#define SND_EMU10K1_PLAYBACK_CHANNELS 8
1071#define SND_EMU10K1_CAPTURE_CHANNELS 4
1072
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001073static void __devinit
1074snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1075 const char *name, int gpr, int defval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001076{
1077 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1078 strcpy(ctl->id.name, name);
1079 ctl->vcount = ctl->count = 1;
1080 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
Clemens Ladisch4daf7a02010-05-25 09:04:49 +02001081 if (high_res_gpr_volume) {
1082 ctl->min = 0;
1083 ctl->max = 0x7fffffff;
1084 ctl->tlv = snd_emu10k1_db_linear;
1085 ctl->translation = EMU10K1_GPR_TRANSLATION_NONE;
1086 } else {
1087 ctl->min = 0;
1088 ctl->max = 100;
1089 ctl->tlv = snd_emu10k1_db_scale1;
1090 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
1091 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092}
1093
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001094static void __devinit
1095snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1096 const char *name, int gpr, int defval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097{
1098 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1099 strcpy(ctl->id.name, name);
1100 ctl->vcount = ctl->count = 2;
1101 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1102 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
Clemens Ladisch4daf7a02010-05-25 09:04:49 +02001103 if (high_res_gpr_volume) {
1104 ctl->min = 0;
1105 ctl->max = 0x7fffffff;
1106 ctl->tlv = snd_emu10k1_db_linear;
1107 ctl->translation = EMU10K1_GPR_TRANSLATION_NONE;
1108 } else {
1109 ctl->min = 0;
1110 ctl->max = 100;
1111 ctl->tlv = snd_emu10k1_db_scale1;
1112 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
1113 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114}
1115
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001116static void __devinit
1117snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1118 const char *name, int gpr, int defval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001119{
1120 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1121 strcpy(ctl->id.name, name);
1122 ctl->vcount = ctl->count = 1;
1123 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1124 ctl->min = 0;
1125 ctl->max = 1;
1126 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
1127}
1128
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001129static void __devinit
1130snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1131 const char *name, int gpr, int defval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132{
1133 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1134 strcpy(ctl->id.name, name);
1135 ctl->vcount = ctl->count = 2;
1136 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1137 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
1138 ctl->min = 0;
1139 ctl->max = 1;
1140 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
1141}
1142
Pavel Hofman13d45702007-06-11 12:21:20 +02001143/*
1144 * Used for emu1010 - conversion from 32-bit capture inputs from HANA
1145 * to 2 x 16-bit registers in audigy - their values are read via DMA.
1146 * Conversion is performed by Audigy DSP instructions of FX8010.
1147 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001148static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
1149 struct snd_emu10k1_fx8010_code *icode,
1150 u32 *ptr, int tmp, int bit_shifter16,
1151 int reg_in, int reg_out)
1152{
1153 A_OP(icode, ptr, iACC3, A_GPR(tmp + 1), reg_in, A_C_00000000, A_C_00000000);
1154 A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp + 1), A_GPR(bit_shifter16 - 1), A_C_00000000);
1155 A_OP(icode, ptr, iTSTNEG, A_GPR(tmp + 2), A_GPR(tmp), A_C_80000000, A_GPR(bit_shifter16 - 2));
1156 A_OP(icode, ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_C_80000000, A_C_00000000);
1157 A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp), A_GPR(bit_shifter16 - 3), A_C_00000000);
1158 A_OP(icode, ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A_GPR(tmp), A_C_00010000);
1159 A_OP(icode, ptr, iANDXOR, reg_out, A_GPR(tmp), A_C_ffffffff, A_GPR(tmp + 2));
1160 A_OP(icode, ptr, iACC3, reg_out + 1, A_GPR(tmp + 1), A_C_00000000, A_C_00000000);
1161 return 1;
1162}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
1164/*
1165 * initial DSP configuration for Audigy
1166 */
1167
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001168static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169{
1170 int err, i, z, gpr, nctl;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001171 int bit_shifter16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001172 const int playback = 10;
1173 const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
1174 const int stereo_mix = capture + 2;
1175 const int tmp = 0x88;
1176 u32 ptr;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001177 struct snd_emu10k1_fx8010_code *icode = NULL;
1178 struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001179 u32 *gpr_map;
1180 mm_segment_t seg;
1181
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001182 if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL ||
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001183 (icode->gpr_map = (u_int32_t __user *)
1184 kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t),
1185 GFP_KERNEL)) == NULL ||
1186 (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
1187 sizeof(*controls), GFP_KERNEL)) == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188 err = -ENOMEM;
1189 goto __err;
1190 }
Clemens Ladisch4d233592005-09-05 10:35:20 +02001191 gpr_map = (u32 __force *)icode->gpr_map;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
1193 icode->tram_data_map = icode->gpr_map + 512;
1194 icode->tram_addr_map = icode->tram_data_map + 256;
1195 icode->code = icode->tram_addr_map + 256;
1196
1197 /* clear free GPRs */
1198 for (i = 0; i < 512; i++)
1199 set_bit(i, icode->gpr_valid);
1200
1201 /* clear TRAM data & address lines */
1202 for (i = 0; i < 256; i++)
1203 set_bit(i, icode->tram_valid);
1204
1205 strcpy(icode->name, "Audigy DSP code for ALSA");
1206 ptr = 0;
1207 nctl = 0;
1208 gpr = stereo_mix + 10;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001209 gpr_map[gpr++] = 0x00007fff;
1210 gpr_map[gpr++] = 0x00008000;
1211 gpr_map[gpr++] = 0x0000ffff;
1212 bit_shifter16 = gpr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001213
1214 /* stop FX processor */
1215 snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
1216
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001217#if 1
Pavel Hofman13d45702007-06-11 12:21:20 +02001218 /* PCM front Playback Volume (independent from stereo mix)
1219 * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31)
1220 * where gpr contains attenuation from corresponding mixer control
1221 * (snd_emu10k1_init_stereo_control)
1222 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001223 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
1224 A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
1225 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100);
1226 gpr += 2;
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001227
Linus Torvalds1da177e2005-04-16 15:20:36 -07001228 /* PCM Surround Playback (independent from stereo mix) */
1229 A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR));
1230 A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
1231 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100);
1232 gpr += 2;
1233
1234 /* PCM Side Playback (independent from stereo mix) */
Lee Revell2b637da2005-03-30 13:51:18 +02001235 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001236 A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
1237 A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
1238 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
1239 gpr += 2;
1240 }
1241
1242 /* PCM Center Playback (independent from stereo mix) */
1243 A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER));
1244 snd_emu10k1_init_mono_control(&controls[nctl++], "PCM Center Playback Volume", gpr, 100);
1245 gpr++;
1246
1247 /* PCM LFE Playback (independent from stereo mix) */
1248 A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LFE));
1249 snd_emu10k1_init_mono_control(&controls[nctl++], "PCM LFE Playback Volume", gpr, 100);
1250 gpr++;
1251
1252 /*
1253 * Stereo Mix
1254 */
1255 /* Wave (PCM) Playback Volume (will be renamed later) */
1256 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
1257 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
1258 snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
1259 gpr += 2;
1260
1261 /* Synth Playback */
1262 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
1263 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
1264 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100);
1265 gpr += 2;
1266
1267 /* Wave (PCM) Capture */
1268 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
1269 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
1270 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0);
1271 gpr += 2;
1272
1273 /* Synth Capture */
1274 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
1275 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
1276 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0);
1277 gpr += 2;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001278
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279 /*
1280 * inputs
1281 */
1282#define A_ADD_VOLUME_IN(var,vol,input) \
1283A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
1284
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001285 /* emu1212 DSP 0 and DSP 1 Capture */
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00001286 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001287 if (emu->card_capabilities->ca0108_chip) {
1288 /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */
1289 A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001);
1290 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_GPR(tmp));
1291 A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x1), A_C_00000001);
1292 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr), A_GPR(tmp));
1293 } else {
1294 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0));
1295 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1));
1296 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001297 snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0);
1298 gpr += 2;
1299 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 /* AC'97 Playback Volume - used only for mic (renamed later) */
1301 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L);
1302 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R);
1303 snd_emu10k1_init_stereo_control(&controls[nctl++], "AMic Playback Volume", gpr, 0);
1304 gpr += 2;
1305 /* AC'97 Capture Volume - used only for mic */
1306 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AC97_L);
1307 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AC97_R);
1308 snd_emu10k1_init_stereo_control(&controls[nctl++], "Mic Capture Volume", gpr, 0);
1309 gpr += 2;
1310
1311 /* mic capture buffer */
1312 A_OP(icode, &ptr, iINTERP, A_EXTOUT(A_EXTOUT_MIC_CAP), A_EXTIN(A_EXTIN_AC97_L), 0xcd, A_EXTIN(A_EXTIN_AC97_R));
1313
1314 /* Audigy CD Playback Volume */
1315 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L);
1316 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_SPDIF_CD_R);
1317 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001318 emu->card_capabilities->ac97_chip ? "Audigy CD Playback Volume" : "CD Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001319 gpr, 0);
1320 gpr += 2;
1321 /* Audigy CD Capture Volume */
1322 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
1323 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
1324 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001325 emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 gpr, 0);
1327 gpr += 2;
1328
1329 /* Optical SPDIF Playback Volume */
1330 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_OPT_SPDIF_L);
1331 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001332 snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 gpr += 2;
1334 /* Optical SPDIF Capture Volume */
1335 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_OPT_SPDIF_L);
1336 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001337 snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",CAPTURE,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001338 gpr += 2;
1339
1340 /* Line2 Playback Volume */
1341 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L);
1342 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_LINE2_R);
1343 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001344 emu->card_capabilities->ac97_chip ? "Line2 Playback Volume" : "Line Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 gpr, 0);
1346 gpr += 2;
1347 /* Line2 Capture Volume */
1348 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L);
1349 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R);
1350 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001351 emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 gpr, 0);
1353 gpr += 2;
1354
1355 /* Philips ADC Playback Volume */
1356 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_ADC_L);
1357 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_ADC_R);
1358 snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Playback Volume", gpr, 0);
1359 gpr += 2;
1360 /* Philips ADC Capture Volume */
1361 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_ADC_L);
1362 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_ADC_R);
1363 snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Capture Volume", gpr, 0);
1364 gpr += 2;
1365
1366 /* Aux2 Playback Volume */
1367 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L);
1368 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AUX2_R);
1369 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001370 emu->card_capabilities->ac97_chip ? "Aux2 Playback Volume" : "Aux Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371 gpr, 0);
1372 gpr += 2;
1373 /* Aux2 Capture Volume */
1374 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L);
1375 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R);
1376 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001377 emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 gpr, 0);
1379 gpr += 2;
1380
1381 /* Stereo Mix Front Playback Volume */
1382 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_GPR(playback), A_GPR(gpr), A_GPR(stereo_mix));
1383 A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_GPR(playback+1), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1384 snd_emu10k1_init_stereo_control(&controls[nctl++], "Front Playback Volume", gpr, 100);
1385 gpr += 2;
1386
1387 /* Stereo Mix Surround Playback */
1388 A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_GPR(playback+2), A_GPR(gpr), A_GPR(stereo_mix));
1389 A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_GPR(playback+3), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1390 snd_emu10k1_init_stereo_control(&controls[nctl++], "Surround Playback Volume", gpr, 0);
1391 gpr += 2;
1392
1393 /* Stereo Mix Center Playback */
1394 /* Center = sub = Left/2 + Right/2 */
1395 A_OP(icode, &ptr, iINTERP, A_GPR(tmp), A_GPR(stereo_mix), 0xcd, A_GPR(stereo_mix+1));
1396 A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_GPR(playback+4), A_GPR(gpr), A_GPR(tmp));
1397 snd_emu10k1_init_mono_control(&controls[nctl++], "Center Playback Volume", gpr, 0);
1398 gpr++;
1399
1400 /* Stereo Mix LFE Playback */
1401 A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp));
1402 snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
1403 gpr++;
1404
Lee Revell2b637da2005-03-30 13:51:18 +02001405 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406 /* Stereo Mix Side Playback */
1407 A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
1408 A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1409 snd_emu10k1_init_stereo_control(&controls[nctl++], "Side Playback Volume", gpr, 0);
1410 gpr += 2;
1411 }
1412
1413 /*
1414 * outputs
1415 */
1416#define A_PUT_OUTPUT(out,src) A_OP(icode, &ptr, iACC3, A_EXTOUT(out), A_C_00000000, A_C_00000000, A_GPR(src))
1417#define A_PUT_STEREO_OUTPUT(out1,out2,src) \
1418 {A_PUT_OUTPUT(out1,src); A_PUT_OUTPUT(out2,src+1);}
1419
1420#define _A_SWITCH(icode, ptr, dst, src, sw) \
1421 A_OP((icode), ptr, iMACINT0, dst, A_C_00000000, src, sw);
1422#define A_SWITCH(icode, ptr, dst, src, sw) \
1423 _A_SWITCH(icode, ptr, A_GPR(dst), A_GPR(src), A_GPR(sw))
1424#define _A_SWITCH_NEG(icode, ptr, dst, src) \
1425 A_OP((icode), ptr, iANDXOR, dst, src, A_C_00000001, A_C_00000001);
1426#define A_SWITCH_NEG(icode, ptr, dst, src) \
1427 _A_SWITCH_NEG(icode, ptr, A_GPR(dst), A_GPR(src))
1428
1429
1430 /*
1431 * Process tone control
1432 */
1433 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), A_GPR(playback + 0), A_C_00000000, A_C_00000000); /* left */
1434 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), A_GPR(playback + 1), A_C_00000000, A_C_00000000); /* right */
1435 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 */
1436 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 */
1437 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
1438 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 +02001439 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001440 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 */
1441 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 */
1442 }
1443
1444
1445 ctl = &controls[nctl + 0];
1446 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1447 strcpy(ctl->id.name, "Tone Control - Bass");
1448 ctl->vcount = 2;
1449 ctl->count = 10;
1450 ctl->min = 0;
1451 ctl->max = 40;
1452 ctl->value[0] = ctl->value[1] = 20;
1453 ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
1454 ctl = &controls[nctl + 1];
1455 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1456 strcpy(ctl->id.name, "Tone Control - Treble");
1457 ctl->vcount = 2;
1458 ctl->count = 10;
1459 ctl->min = 0;
1460 ctl->max = 40;
1461 ctl->value[0] = ctl->value[1] = 20;
1462 ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
1463
1464#define BASS_GPR 0x8c
1465#define TREBLE_GPR 0x96
1466
1467 for (z = 0; z < 5; z++) {
1468 int j;
1469 for (j = 0; j < 2; j++) {
1470 controls[nctl + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j;
1471 controls[nctl + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
1472 }
1473 }
1474 for (z = 0; z < 4; z++) { /* front/rear/center-lfe/side */
1475 int j, k, l, d;
1476 for (j = 0; j < 2; j++) { /* left/right */
1477 k = 0xb0 + (z * 8) + (j * 4);
1478 l = 0xe0 + (z * 8) + (j * 4);
1479 d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j;
1480
1481 A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(d), A_GPR(BASS_GPR + 0 + j));
1482 A_OP(icode, &ptr, iMACMV, A_GPR(k+1), A_GPR(k), A_GPR(k+1), A_GPR(BASS_GPR + 4 + j));
1483 A_OP(icode, &ptr, iMACMV, A_GPR(k), A_GPR(d), A_GPR(k), A_GPR(BASS_GPR + 2 + j));
1484 A_OP(icode, &ptr, iMACMV, A_GPR(k+3), A_GPR(k+2), A_GPR(k+3), A_GPR(BASS_GPR + 8 + j));
1485 A_OP(icode, &ptr, iMAC0, A_GPR(k+2), A_GPR_ACCU, A_GPR(k+2), A_GPR(BASS_GPR + 6 + j));
1486 A_OP(icode, &ptr, iACC3, A_GPR(k+2), A_GPR(k+2), A_GPR(k+2), A_C_00000000);
1487
1488 A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(k+2), A_GPR(TREBLE_GPR + 0 + j));
1489 A_OP(icode, &ptr, iMACMV, A_GPR(l+1), A_GPR(l), A_GPR(l+1), A_GPR(TREBLE_GPR + 4 + j));
1490 A_OP(icode, &ptr, iMACMV, A_GPR(l), A_GPR(k+2), A_GPR(l), A_GPR(TREBLE_GPR + 2 + j));
1491 A_OP(icode, &ptr, iMACMV, A_GPR(l+3), A_GPR(l+2), A_GPR(l+3), A_GPR(TREBLE_GPR + 8 + j));
1492 A_OP(icode, &ptr, iMAC0, A_GPR(l+2), A_GPR_ACCU, A_GPR(l+2), A_GPR(TREBLE_GPR + 6 + j));
1493 A_OP(icode, &ptr, iMACINT0, A_GPR(l+2), A_C_00000000, A_GPR(l+2), A_C_00000010);
1494
1495 A_OP(icode, &ptr, iACC3, A_GPR(d), A_GPR(l+2), A_C_00000000, A_C_00000000);
1496
1497 if (z == 2) /* center */
1498 break;
1499 }
1500 }
1501 nctl += 2;
1502
1503#undef BASS_GPR
1504#undef TREBLE_GPR
1505
1506 for (z = 0; z < 8; z++) {
1507 A_SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
1508 A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
1509 A_SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
1510 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1511 }
1512 snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0);
1513 gpr += 2;
1514
1515 /* Master volume (will be renamed later) */
1516 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));
1517 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));
1518 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));
1519 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));
1520 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));
1521 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));
1522 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));
1523 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));
1524 snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
1525 gpr += 2;
1526
1527 /* analog speakers */
1528 A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1529 A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
1530 A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
1531 A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
Lee Revell2b637da2005-03-30 13:51:18 +02001532 if (emu->card_capabilities->spk71)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001533 A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
1534
1535 /* headphone */
1536 A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1537
1538 /* digital outputs */
1539 /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00001540 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001541 /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */
Takashi Iwai28a97c12009-02-05 16:08:14 +01001542 snd_printk(KERN_INFO "EMU outputs on\n");
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001543 for (z = 0; z < 8; z++) {
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001544 if (emu->card_capabilities->ca0108_chip) {
1545 A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
1546 } else {
1547 A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
1548 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001549 }
1550 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552 /* IEC958 Optical Raw Playback Switch */
1553 gpr_map[gpr++] = 0;
1554 gpr_map[gpr++] = 0x1008;
1555 gpr_map[gpr++] = 0xffff0000;
1556 for (z = 0; z < 2; z++) {
1557 A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000);
1558 A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001);
1559 A_OP(icode, &ptr, iACC3, A_GPR(tmp + 2), A_C_00000000, A_C_00010000, A_GPR(tmp + 2));
1560 A_OP(icode, &ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_GPR(gpr - 1), A_C_00000000);
1561 A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z);
1562 A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
1563 A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
1564 if ((z==1) && (emu->card_capabilities->spdif_bug)) {
1565 /* 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 +02001566 snd_printk(KERN_INFO "Installing spdif_bug patch: %s\n", emu->card_capabilities->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001567 A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000);
1568 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1569 } else {
1570 A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1571 }
1572 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001573 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 -07001574 gpr += 2;
1575
1576 A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
1577 A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
1578 A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
1579
1580 /* ADC buffer */
1581#ifdef EMU10K1_CAPTURE_DIGITAL_OUT
1582 A_PUT_STEREO_OUTPUT(A_EXTOUT_ADC_CAP_L, A_EXTOUT_ADC_CAP_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1583#else
1584 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture);
1585 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
1586#endif
1587
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00001588 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001589 if (emu->card_capabilities->ca0108_chip) {
Takashi Iwai28a97c12009-02-05 16:08:14 +01001590 snd_printk(KERN_INFO "EMU2 inputs on\n");
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001591 for (z = 0; z < 0x10; z++) {
1592 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp,
1593 bit_shifter16,
1594 A3_EMU32IN(z),
1595 A_FXBUS2(z*2) );
1596 }
1597 } else {
Takashi Iwai28a97c12009-02-05 16:08:14 +01001598 snd_printk(KERN_INFO "EMU inputs on\n");
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001599 /* Capture 16 (originally 8) channels of S32_LE sound */
1600
Takashi Iwai28a97c12009-02-05 16:08:14 +01001601 /*
1602 printk(KERN_DEBUG "emufx.c: gpr=0x%x, tmp=0x%x\n",
1603 gpr, tmp);
1604 */
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001605 /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
1606 /* A_P16VIN(0) is delayed by one sample,
1607 * so all other A_P16VIN channels will need to also be delayed
1608 */
1609 /* Left ADC in. 1 of 2 */
1610 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
1611 /* Right ADC in 1 of 2 */
1612 gpr_map[gpr++] = 0x00000000;
1613 /* Delaying by one sample: instead of copying the input
1614 * value A_P16VIN to output A_FXBUS2 as in the first channel,
1615 * we use an auxiliary register, delaying the value by one
1616 * sample
1617 */
1618 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
1619 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
1620 gpr_map[gpr++] = 0x00000000;
1621 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) );
1622 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000);
1623 gpr_map[gpr++] = 0x00000000;
1624 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) );
1625 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
1626 /* For 96kHz mode */
1627 /* Left ADC in. 2 of 2 */
1628 gpr_map[gpr++] = 0x00000000;
1629 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
1630 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
1631 /* Right ADC in 2 of 2 */
1632 gpr_map[gpr++] = 0x00000000;
1633 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
1634 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000);
1635 gpr_map[gpr++] = 0x00000000;
1636 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) );
1637 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000);
1638 gpr_map[gpr++] = 0x00000000;
1639 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
1640 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
1641 /* Pavel Hofman - we still have voices, A_FXBUS2s, and
1642 * A_P16VINs available -
1643 * let's add 8 more capture channels - total of 16
1644 */
1645 gpr_map[gpr++] = 0x00000000;
1646 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1647 bit_shifter16,
1648 A_GPR(gpr - 1),
1649 A_FXBUS2(0x10));
1650 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8),
1651 A_C_00000000, A_C_00000000);
1652 gpr_map[gpr++] = 0x00000000;
1653 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1654 bit_shifter16,
1655 A_GPR(gpr - 1),
1656 A_FXBUS2(0x12));
1657 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9),
1658 A_C_00000000, A_C_00000000);
1659 gpr_map[gpr++] = 0x00000000;
1660 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1661 bit_shifter16,
1662 A_GPR(gpr - 1),
1663 A_FXBUS2(0x14));
1664 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa),
1665 A_C_00000000, A_C_00000000);
1666 gpr_map[gpr++] = 0x00000000;
1667 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1668 bit_shifter16,
1669 A_GPR(gpr - 1),
1670 A_FXBUS2(0x16));
1671 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb),
1672 A_C_00000000, A_C_00000000);
1673 gpr_map[gpr++] = 0x00000000;
1674 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1675 bit_shifter16,
1676 A_GPR(gpr - 1),
1677 A_FXBUS2(0x18));
1678 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc),
1679 A_C_00000000, A_C_00000000);
1680 gpr_map[gpr++] = 0x00000000;
1681 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1682 bit_shifter16,
1683 A_GPR(gpr - 1),
1684 A_FXBUS2(0x1a));
1685 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd),
1686 A_C_00000000, A_C_00000000);
1687 gpr_map[gpr++] = 0x00000000;
1688 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1689 bit_shifter16,
1690 A_GPR(gpr - 1),
1691 A_FXBUS2(0x1c));
1692 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe),
1693 A_C_00000000, A_C_00000000);
1694 gpr_map[gpr++] = 0x00000000;
1695 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1696 bit_shifter16,
1697 A_GPR(gpr - 1),
1698 A_FXBUS2(0x1e));
1699 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf),
1700 A_C_00000000, A_C_00000000);
1701 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001702
1703#if 0
1704 for (z = 4; z < 8; z++) {
1705 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
1706 }
1707 for (z = 0xc; z < 0x10; z++) {
1708 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
1709 }
1710#endif
1711 } else {
1712 /* EFX capture - capture the 16 EXTINs */
1713 /* Capture 16 channels of S16_LE sound */
1714 for (z = 0; z < 16; z++) {
1715 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
1716 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 }
1718
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001719#endif /* JCD test */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001720 /*
1721 * ok, set up done..
1722 */
1723
1724 if (gpr > tmp) {
1725 snd_BUG();
1726 err = -EIO;
1727 goto __err;
1728 }
1729 /* clear remaining instruction memory */
1730 while (ptr < 0x400)
1731 A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0);
1732
1733 seg = snd_enter_user();
1734 icode->gpr_add_control_count = nctl;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001735 icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01001736 emu->support_tlv = 1; /* support TLV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 err = snd_emu10k1_icode_poke(emu, icode);
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01001738 emu->support_tlv = 0; /* clear again */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001739 snd_leave_user(seg);
1740
1741 __err:
1742 kfree(controls);
1743 if (icode != NULL) {
Clemens Ladisch4d233592005-09-05 10:35:20 +02001744 kfree((void __force *)icode->gpr_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001745 kfree(icode);
1746 }
1747 return err;
1748}
1749
1750
1751/*
1752 * initial DSP configuration for Emu10k1
1753 */
1754
1755/* when volume = max, then copy only to avoid volume modification */
1756/* with iMAC0 (negative values) */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001757static void __devinit _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758{
1759 OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
1760 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1761 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001);
1762 OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
1763}
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001764static void __devinit _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001765{
1766 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1767 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1768 OP(icode, ptr, iMACINT0, dst, dst, src, C_00000001);
1769 OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
1770 OP(icode, ptr, iMAC0, dst, dst, src, vol);
1771}
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001772static void __devinit _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001773{
1774 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1775 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1776 OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
1777 OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
1778 OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
1779}
1780
1781#define VOLUME(icode, ptr, dst, src, vol) \
1782 _volume(icode, ptr, GPR(dst), GPR(src), GPR(vol))
1783#define VOLUME_IN(icode, ptr, dst, src, vol) \
1784 _volume(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))
1785#define VOLUME_ADD(icode, ptr, dst, src, vol) \
1786 _volume_add(icode, ptr, GPR(dst), GPR(src), GPR(vol))
1787#define VOLUME_ADDIN(icode, ptr, dst, src, vol) \
1788 _volume_add(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))
1789#define VOLUME_OUT(icode, ptr, dst, src, vol) \
1790 _volume_out(icode, ptr, EXTOUT(dst), GPR(src), GPR(vol))
1791#define _SWITCH(icode, ptr, dst, src, sw) \
1792 OP((icode), ptr, iMACINT0, dst, C_00000000, src, sw);
1793#define SWITCH(icode, ptr, dst, src, sw) \
1794 _SWITCH(icode, ptr, GPR(dst), GPR(src), GPR(sw))
1795#define SWITCH_IN(icode, ptr, dst, src, sw) \
1796 _SWITCH(icode, ptr, GPR(dst), EXTIN(src), GPR(sw))
1797#define _SWITCH_NEG(icode, ptr, dst, src) \
1798 OP((icode), ptr, iANDXOR, dst, src, C_00000001, C_00000001);
1799#define SWITCH_NEG(icode, ptr, dst, src) \
1800 _SWITCH_NEG(icode, ptr, GPR(dst), GPR(src))
1801
1802
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001803static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001804{
1805 int err, i, z, gpr, tmp, playback, capture;
1806 u32 ptr;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001807 struct snd_emu10k1_fx8010_code *icode;
1808 struct snd_emu10k1_fx8010_pcm_rec *ipcm = NULL;
1809 struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001810 u32 *gpr_map;
1811 mm_segment_t seg;
1812
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001813 if ((icode = kzalloc(sizeof(*icode), GFP_KERNEL)) == NULL)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001814 return -ENOMEM;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001815 if ((icode->gpr_map = (u_int32_t __user *)
1816 kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t),
1817 GFP_KERNEL)) == NULL ||
1818 (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
1819 sizeof(struct snd_emu10k1_fx8010_control_gpr),
1820 GFP_KERNEL)) == NULL ||
Takashi Iwaie560d8d2005-09-09 14:21:46 +02001821 (ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL)) == NULL) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001822 err = -ENOMEM;
1823 goto __err;
1824 }
Clemens Ladisch4d233592005-09-05 10:35:20 +02001825 gpr_map = (u32 __force *)icode->gpr_map;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001826
1827 icode->tram_data_map = icode->gpr_map + 256;
1828 icode->tram_addr_map = icode->tram_data_map + 160;
1829 icode->code = icode->tram_addr_map + 160;
1830
1831 /* clear free GPRs */
1832 for (i = 0; i < 256; i++)
1833 set_bit(i, icode->gpr_valid);
1834
1835 /* clear TRAM data & address lines */
1836 for (i = 0; i < 160; i++)
1837 set_bit(i, icode->tram_valid);
1838
1839 strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela");
1840 ptr = 0; i = 0;
Mikael Magnussonedf8e452005-09-13 11:32:58 +02001841 /* we have 12 inputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001842 playback = SND_EMU10K1_INPUTS;
1843 /* we have 6 playback channels and tone control doubles */
1844 capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2);
1845 gpr = capture + SND_EMU10K1_CAPTURE_CHANNELS;
1846 tmp = 0x88; /* we need 4 temporary GPR */
1847 /* from 0x8c to 0xff is the area for tone control */
1848
1849 /* stop FX processor */
1850 snd_emu10k1_ptr_write(emu, DBG, 0, (emu->fx8010.dbg = 0) | EMU10K1_DBG_SINGLE_STEP);
1851
1852 /*
1853 * Process FX Buses
1854 */
1855 OP(icode, &ptr, iMACINT0, GPR(0), C_00000000, FXBUS(FXBUS_PCM_LEFT), C_00000004);
1856 OP(icode, &ptr, iMACINT0, GPR(1), C_00000000, FXBUS(FXBUS_PCM_RIGHT), C_00000004);
1857 OP(icode, &ptr, iMACINT0, GPR(2), C_00000000, FXBUS(FXBUS_MIDI_LEFT), C_00000004);
1858 OP(icode, &ptr, iMACINT0, GPR(3), C_00000000, FXBUS(FXBUS_MIDI_RIGHT), C_00000004);
1859 OP(icode, &ptr, iMACINT0, GPR(4), C_00000000, FXBUS(FXBUS_PCM_LEFT_REAR), C_00000004);
1860 OP(icode, &ptr, iMACINT0, GPR(5), C_00000000, FXBUS(FXBUS_PCM_RIGHT_REAR), C_00000004);
1861 OP(icode, &ptr, iMACINT0, GPR(6), C_00000000, FXBUS(FXBUS_PCM_CENTER), C_00000004);
1862 OP(icode, &ptr, iMACINT0, GPR(7), C_00000000, FXBUS(FXBUS_PCM_LFE), C_00000004);
1863 OP(icode, &ptr, iMACINT0, GPR(8), C_00000000, C_00000000, C_00000000); /* S/PDIF left */
1864 OP(icode, &ptr, iMACINT0, GPR(9), C_00000000, C_00000000, C_00000000); /* S/PDIF right */
Mikael Magnussonedf8e452005-09-13 11:32:58 +02001865 OP(icode, &ptr, iMACINT0, GPR(10), C_00000000, FXBUS(FXBUS_PCM_LEFT_FRONT), C_00000004);
1866 OP(icode, &ptr, iMACINT0, GPR(11), C_00000000, FXBUS(FXBUS_PCM_RIGHT_FRONT), C_00000004);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001867
1868 /* Raw S/PDIF PCM */
1869 ipcm->substream = 0;
1870 ipcm->channels = 2;
1871 ipcm->tram_start = 0;
1872 ipcm->buffer_size = (64 * 1024) / 2;
1873 ipcm->gpr_size = gpr++;
1874 ipcm->gpr_ptr = gpr++;
1875 ipcm->gpr_count = gpr++;
1876 ipcm->gpr_tmpcount = gpr++;
1877 ipcm->gpr_trigger = gpr++;
1878 ipcm->gpr_running = gpr++;
1879 ipcm->etram[0] = 0;
1880 ipcm->etram[1] = 1;
1881
1882 gpr_map[gpr + 0] = 0xfffff000;
1883 gpr_map[gpr + 1] = 0xffff0000;
1884 gpr_map[gpr + 2] = 0x70000000;
1885 gpr_map[gpr + 3] = 0x00000007;
1886 gpr_map[gpr + 4] = 0x001f << 11;
1887 gpr_map[gpr + 5] = 0x001c << 11;
1888 gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */
1889 gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */
1890 gpr_map[gpr + 8] = 0x2000000 + (2<<11);
1891 gpr_map[gpr + 9] = 0x4000000 + (2<<11);
1892 gpr_map[gpr + 10] = 1<<11;
1893 gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */
1894 gpr_map[gpr + 12] = 0;
1895
1896 /* if the trigger flag is not set, skip */
1897 /* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000);
1898 /* 01: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_ZERO, GPR(gpr + 6));
1899 /* if the running flag is set, we're running */
1900 /* 02: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_running), C_00000000, C_00000000);
1901 /* 03: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000004);
1902 /* wait until ((GPR_DBAC>>11) & 0x1f) == 0x1c) */
1903 /* 04: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), GPR_DBAC, GPR(gpr + 4), C_00000000);
1904 /* 05: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(gpr + 5));
1905 /* 06: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 7));
1906 /* 07: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000010, C_00000001, C_00000000);
1907
1908 /* 08: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000000, C_00000001);
1909 /* 09: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), GPR(gpr + 12), C_ffffffff, C_00000000);
1910 /* 0a: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 11));
1911 /* 0b: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000001, C_00000000, C_00000000);
1912
1913 /* 0c: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[0]), GPR(gpr + 0), C_00000000);
1914 /* 0d: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000);
1915 /* 0e: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2));
1916 /* 0f: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001);
1917 /* 10: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(8), GPR(gpr + 1), GPR(gpr + 2));
1918
1919 /* 11: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[1]), GPR(gpr + 0), C_00000000);
1920 /* 12: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000);
1921 /* 13: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2));
1922 /* 14: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001);
1923 /* 15: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(9), GPR(gpr + 1), GPR(gpr + 2));
1924
1925 /* 16: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(ipcm->gpr_ptr), C_00000001, C_00000000);
1926 /* 17: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(ipcm->gpr_size));
1927 /* 18: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_MINUS, C_00000001);
1928 /* 19: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), C_00000000, C_00000000, C_00000000);
1929 /* 1a: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_ptr), GPR(tmp + 0), C_00000000, C_00000000);
1930
1931 /* 1b: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_tmpcount), C_ffffffff, C_00000000);
1932 /* 1c: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1933 /* 1d: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_count), C_00000000, C_00000000);
1934 /* 1e: */ OP(icode, &ptr, iACC3, GPR_IRQ, C_80000000, C_00000000, C_00000000);
1935 /* 1f: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000001, C_00010000);
1936
1937 /* 20: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00010000, C_00000001);
1938 /* 21: */ OP(icode, &ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000002);
1939
1940 /* 22: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[0]), GPR(gpr + 8), GPR_DBAC, C_ffffffff);
1941 /* 23: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[1]), GPR(gpr + 9), GPR_DBAC, C_ffffffff);
1942
1943 /* 24: */
1944 gpr += 13;
1945
1946 /* Wave Playback Volume */
1947 for (z = 0; z < 2; z++)
1948 VOLUME(icode, &ptr, playback + z, z, gpr + z);
1949 snd_emu10k1_init_stereo_control(controls + i++, "Wave Playback Volume", gpr, 100);
1950 gpr += 2;
1951
1952 /* Wave Surround Playback Volume */
1953 for (z = 0; z < 2; z++)
1954 VOLUME(icode, &ptr, playback + 2 + z, z, gpr + z);
1955 snd_emu10k1_init_stereo_control(controls + i++, "Wave Surround Playback Volume", gpr, 0);
1956 gpr += 2;
1957
1958 /* Wave Center/LFE Playback Volume */
1959 OP(icode, &ptr, iACC3, GPR(tmp + 0), FXBUS(FXBUS_PCM_LEFT), FXBUS(FXBUS_PCM_RIGHT), C_00000000);
1960 OP(icode, &ptr, iMACINT0, GPR(tmp + 0), C_00000000, GPR(tmp + 0), C_00000002);
1961 VOLUME(icode, &ptr, playback + 4, tmp + 0, gpr);
1962 snd_emu10k1_init_mono_control(controls + i++, "Wave Center Playback Volume", gpr++, 0);
1963 VOLUME(icode, &ptr, playback + 5, tmp + 0, gpr);
1964 snd_emu10k1_init_mono_control(controls + i++, "Wave LFE Playback Volume", gpr++, 0);
1965
1966 /* Wave Capture Volume + Switch */
1967 for (z = 0; z < 2; z++) {
1968 SWITCH(icode, &ptr, tmp + 0, z, gpr + 2 + z);
1969 VOLUME(icode, &ptr, capture + z, tmp + 0, gpr + z);
1970 }
1971 snd_emu10k1_init_stereo_control(controls + i++, "Wave Capture Volume", gpr, 0);
1972 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0);
1973 gpr += 4;
1974
1975 /* Synth Playback Volume */
1976 for (z = 0; z < 2; z++)
1977 VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z);
1978 snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100);
1979 gpr += 2;
1980
1981 /* Synth Capture Volume + Switch */
1982 for (z = 0; z < 2; z++) {
1983 SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z);
1984 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
1985 }
1986 snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0);
1987 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0);
1988 gpr += 4;
1989
1990 /* Surround Digital Playback Volume (renamed later without Digital) */
1991 for (z = 0; z < 2; z++)
1992 VOLUME_ADD(icode, &ptr, playback + 2 + z, 4 + z, gpr + z);
1993 snd_emu10k1_init_stereo_control(controls + i++, "Surround Digital Playback Volume", gpr, 100);
1994 gpr += 2;
1995
1996 /* Surround Capture Volume + Switch */
1997 for (z = 0; z < 2; z++) {
1998 SWITCH(icode, &ptr, tmp + 0, 4 + z, gpr + 2 + z);
1999 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2000 }
2001 snd_emu10k1_init_stereo_control(controls + i++, "Surround Capture Volume", gpr, 0);
2002 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Surround Capture Switch", gpr + 2, 0);
2003 gpr += 4;
2004
2005 /* Center Playback Volume (renamed later without Digital) */
2006 VOLUME_ADD(icode, &ptr, playback + 4, 6, gpr);
2007 snd_emu10k1_init_mono_control(controls + i++, "Center Digital Playback Volume", gpr++, 100);
2008
2009 /* LFE Playback Volume + Switch (renamed later without Digital) */
2010 VOLUME_ADD(icode, &ptr, playback + 5, 7, gpr);
2011 snd_emu10k1_init_mono_control(controls + i++, "LFE Digital Playback Volume", gpr++, 100);
2012
Mikael Magnussonedf8e452005-09-13 11:32:58 +02002013 /* Front Playback Volume */
2014 for (z = 0; z < 2; z++)
2015 VOLUME_ADD(icode, &ptr, playback + z, 10 + z, gpr + z);
2016 snd_emu10k1_init_stereo_control(controls + i++, "Front Playback Volume", gpr, 100);
2017 gpr += 2;
2018
2019 /* Front Capture Volume + Switch */
2020 for (z = 0; z < 2; z++) {
2021 SWITCH(icode, &ptr, tmp + 0, 10 + z, gpr + 2);
2022 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2023 }
2024 snd_emu10k1_init_stereo_control(controls + i++, "Front Capture Volume", gpr, 0);
2025 snd_emu10k1_init_mono_onoff_control(controls + i++, "Front Capture Switch", gpr + 2, 0);
2026 gpr += 3;
2027
Linus Torvalds1da177e2005-04-16 15:20:36 -07002028 /*
2029 * Process inputs
2030 */
2031
2032 if (emu->fx8010.extin_mask & ((1<<EXTIN_AC97_L)|(1<<EXTIN_AC97_R))) {
2033 /* AC'97 Playback Volume */
2034 VOLUME_ADDIN(icode, &ptr, playback + 0, EXTIN_AC97_L, gpr); gpr++;
2035 VOLUME_ADDIN(icode, &ptr, playback + 1, EXTIN_AC97_R, gpr); gpr++;
2036 snd_emu10k1_init_stereo_control(controls + i++, "AC97 Playback Volume", gpr-2, 0);
2037 /* AC'97 Capture Volume */
2038 VOLUME_ADDIN(icode, &ptr, capture + 0, EXTIN_AC97_L, gpr); gpr++;
2039 VOLUME_ADDIN(icode, &ptr, capture + 1, EXTIN_AC97_R, gpr); gpr++;
2040 snd_emu10k1_init_stereo_control(controls + i++, "AC97 Capture Volume", gpr-2, 100);
2041 }
2042
2043 if (emu->fx8010.extin_mask & ((1<<EXTIN_SPDIF_CD_L)|(1<<EXTIN_SPDIF_CD_R))) {
2044 /* IEC958 TTL Playback Volume */
2045 for (z = 0; z < 2; z++)
2046 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_SPDIF_CD_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002047 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 gpr += 2;
2049
2050 /* IEC958 TTL Capture Volume + Switch */
2051 for (z = 0; z < 2; z++) {
2052 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_SPDIF_CD_L + z, gpr + 2 + z);
2053 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2054 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002055 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",CAPTURE,VOLUME), gpr, 0);
2056 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 -07002057 gpr += 4;
2058 }
2059
2060 if (emu->fx8010.extin_mask & ((1<<EXTIN_ZOOM_L)|(1<<EXTIN_ZOOM_R))) {
2061 /* Zoom Video Playback Volume */
2062 for (z = 0; z < 2; z++)
2063 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_ZOOM_L + z, gpr + z);
2064 snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Playback Volume", gpr, 0);
2065 gpr += 2;
2066
2067 /* Zoom Video Capture Volume + Switch */
2068 for (z = 0; z < 2; z++) {
2069 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_ZOOM_L + z, gpr + 2 + z);
2070 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2071 }
2072 snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Capture Volume", gpr, 0);
2073 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Zoom Video Capture Switch", gpr + 2, 0);
2074 gpr += 4;
2075 }
2076
2077 if (emu->fx8010.extin_mask & ((1<<EXTIN_TOSLINK_L)|(1<<EXTIN_TOSLINK_R))) {
2078 /* IEC958 Optical Playback Volume */
2079 for (z = 0; z < 2; z++)
2080 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_TOSLINK_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002081 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002082 gpr += 2;
2083
2084 /* IEC958 Optical Capture Volume */
2085 for (z = 0; z < 2; z++) {
2086 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_TOSLINK_L + z, gpr + 2 + z);
2087 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2088 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002089 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",CAPTURE,VOLUME), gpr, 0);
2090 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 -07002091 gpr += 4;
2092 }
2093
2094 if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE1_L)|(1<<EXTIN_LINE1_R))) {
2095 /* Line LiveDrive Playback Volume */
2096 for (z = 0; z < 2; z++)
2097 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE1_L + z, gpr + z);
2098 snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Playback Volume", gpr, 0);
2099 gpr += 2;
2100
2101 /* Line LiveDrive Capture Volume + Switch */
2102 for (z = 0; z < 2; z++) {
2103 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE1_L + z, gpr + 2 + z);
2104 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2105 }
2106 snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Capture Volume", gpr, 0);
2107 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line LiveDrive Capture Switch", gpr + 2, 0);
2108 gpr += 4;
2109 }
2110
2111 if (emu->fx8010.extin_mask & ((1<<EXTIN_COAX_SPDIF_L)|(1<<EXTIN_COAX_SPDIF_R))) {
2112 /* IEC958 Coax Playback Volume */
2113 for (z = 0; z < 2; z++)
2114 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_COAX_SPDIF_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002115 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116 gpr += 2;
2117
2118 /* IEC958 Coax Capture Volume + Switch */
2119 for (z = 0; z < 2; z++) {
2120 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_COAX_SPDIF_L + z, gpr + 2 + z);
2121 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2122 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002123 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",CAPTURE,VOLUME), gpr, 0);
2124 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 -07002125 gpr += 4;
2126 }
2127
2128 if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE2_L)|(1<<EXTIN_LINE2_R))) {
2129 /* Line LiveDrive Playback Volume */
2130 for (z = 0; z < 2; z++)
2131 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE2_L + z, gpr + z);
2132 snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Playback Volume", gpr, 0);
2133 controls[i-1].id.index = 1;
2134 gpr += 2;
2135
2136 /* Line LiveDrive Capture Volume */
2137 for (z = 0; z < 2; z++) {
2138 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE2_L + z, gpr + 2 + z);
2139 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2140 }
2141 snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Capture Volume", gpr, 0);
2142 controls[i-1].id.index = 1;
2143 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line2 LiveDrive Capture Switch", gpr + 2, 0);
2144 controls[i-1].id.index = 1;
2145 gpr += 4;
2146 }
2147
2148 /*
2149 * Process tone control
2150 */
2151 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), GPR(playback + 0), C_00000000, C_00000000); /* left */
2152 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), GPR(playback + 1), C_00000000, C_00000000); /* right */
2153 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2), GPR(playback + 2), C_00000000, C_00000000); /* rear left */
2154 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), GPR(playback + 3), C_00000000, C_00000000); /* rear right */
2155 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), GPR(playback + 4), C_00000000, C_00000000); /* center */
2156 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), GPR(playback + 5), C_00000000, C_00000000); /* LFE */
2157
2158 ctl = &controls[i + 0];
2159 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2160 strcpy(ctl->id.name, "Tone Control - Bass");
2161 ctl->vcount = 2;
2162 ctl->count = 10;
2163 ctl->min = 0;
2164 ctl->max = 40;
2165 ctl->value[0] = ctl->value[1] = 20;
2166 ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
2167 ctl = &controls[i + 1];
2168 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2169 strcpy(ctl->id.name, "Tone Control - Treble");
2170 ctl->vcount = 2;
2171 ctl->count = 10;
2172 ctl->min = 0;
2173 ctl->max = 40;
2174 ctl->value[0] = ctl->value[1] = 20;
2175 ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
2176
2177#define BASS_GPR 0x8c
2178#define TREBLE_GPR 0x96
2179
2180 for (z = 0; z < 5; z++) {
2181 int j;
2182 for (j = 0; j < 2; j++) {
2183 controls[i + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j;
2184 controls[i + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
2185 }
2186 }
2187 for (z = 0; z < 3; z++) { /* front/rear/center-lfe */
2188 int j, k, l, d;
2189 for (j = 0; j < 2; j++) { /* left/right */
2190 k = 0xa0 + (z * 8) + (j * 4);
2191 l = 0xd0 + (z * 8) + (j * 4);
2192 d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j;
2193
2194 OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(d), GPR(BASS_GPR + 0 + j));
2195 OP(icode, &ptr, iMACMV, GPR(k+1), GPR(k), GPR(k+1), GPR(BASS_GPR + 4 + j));
2196 OP(icode, &ptr, iMACMV, GPR(k), GPR(d), GPR(k), GPR(BASS_GPR + 2 + j));
2197 OP(icode, &ptr, iMACMV, GPR(k+3), GPR(k+2), GPR(k+3), GPR(BASS_GPR + 8 + j));
2198 OP(icode, &ptr, iMAC0, GPR(k+2), GPR_ACCU, GPR(k+2), GPR(BASS_GPR + 6 + j));
2199 OP(icode, &ptr, iACC3, GPR(k+2), GPR(k+2), GPR(k+2), C_00000000);
2200
2201 OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(k+2), GPR(TREBLE_GPR + 0 + j));
2202 OP(icode, &ptr, iMACMV, GPR(l+1), GPR(l), GPR(l+1), GPR(TREBLE_GPR + 4 + j));
2203 OP(icode, &ptr, iMACMV, GPR(l), GPR(k+2), GPR(l), GPR(TREBLE_GPR + 2 + j));
2204 OP(icode, &ptr, iMACMV, GPR(l+3), GPR(l+2), GPR(l+3), GPR(TREBLE_GPR + 8 + j));
2205 OP(icode, &ptr, iMAC0, GPR(l+2), GPR_ACCU, GPR(l+2), GPR(TREBLE_GPR + 6 + j));
2206 OP(icode, &ptr, iMACINT0, GPR(l+2), C_00000000, GPR(l+2), C_00000010);
2207
2208 OP(icode, &ptr, iACC3, GPR(d), GPR(l+2), C_00000000, C_00000000);
2209
2210 if (z == 2) /* center */
2211 break;
2212 }
2213 }
2214 i += 2;
2215
2216#undef BASS_GPR
2217#undef TREBLE_GPR
2218
2219 for (z = 0; z < 6; z++) {
2220 SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
2221 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
2222 SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
2223 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
2224 }
2225 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Tone Control - Switch", gpr, 0);
2226 gpr += 2;
2227
2228 /*
2229 * Process outputs
2230 */
2231 if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_L)|(1<<EXTOUT_AC97_R))) {
2232 /* AC'97 Playback Volume */
2233
2234 for (z = 0; z < 2; z++)
2235 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), C_00000000, C_00000000);
2236 }
2237
2238 if (emu->fx8010.extout_mask & ((1<<EXTOUT_TOSLINK_L)|(1<<EXTOUT_TOSLINK_R))) {
2239 /* IEC958 Optical Raw Playback Switch */
2240
2241 for (z = 0; z < 2; z++) {
2242 SWITCH(icode, &ptr, tmp + 0, 8 + z, gpr + z);
2243 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
2244 SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
2245 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_TOSLINK_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
2246#ifdef EMU10K1_CAPTURE_DIGITAL_OUT
2247 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
2248#endif
2249 }
2250
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002251 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 -07002252 gpr += 2;
2253 }
2254
2255 if (emu->fx8010.extout_mask & ((1<<EXTOUT_HEADPHONE_L)|(1<<EXTOUT_HEADPHONE_R))) {
2256 /* Headphone Playback Volume */
2257
2258 for (z = 0; z < 2; z++) {
2259 SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4 + z, gpr + 2 + z);
2260 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 2 + z);
2261 SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
2262 OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
2263 VOLUME_OUT(icode, &ptr, EXTOUT_HEADPHONE_L + z, tmp + 0, gpr + z);
2264 }
2265
2266 snd_emu10k1_init_stereo_control(controls + i++, "Headphone Playback Volume", gpr + 0, 0);
2267 controls[i-1].id.index = 1; /* AC'97 can have also Headphone control */
2268 snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone Center Playback Switch", gpr + 2, 0);
2269 controls[i-1].id.index = 1;
2270 snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone LFE Playback Switch", gpr + 3, 0);
2271 controls[i-1].id.index = 1;
2272
2273 gpr += 4;
2274 }
2275
2276 if (emu->fx8010.extout_mask & ((1<<EXTOUT_REAR_L)|(1<<EXTOUT_REAR_R)))
2277 for (z = 0; z < 2; z++)
2278 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000);
2279
2280 if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_REAR_L)|(1<<EXTOUT_AC97_REAR_R)))
2281 for (z = 0; z < 2; z++)
2282 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000);
2283
2284 if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_CENTER)) {
2285#ifndef EMU10K1_CENTER_LFE_FROM_FRONT
2286 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000);
2287 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000);
2288#else
2289 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000);
2290 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000);
2291#endif
2292 }
2293
2294 if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_LFE)) {
2295#ifndef EMU10K1_CENTER_LFE_FROM_FRONT
2296 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000);
2297 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000);
2298#else
2299 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000);
2300 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000);
2301#endif
2302 }
2303
2304#ifndef EMU10K1_CAPTURE_DIGITAL_OUT
2305 for (z = 0; z < 2; z++)
2306 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(capture + z), C_00000000, C_00000000);
2307#endif
2308
2309 if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP))
2310 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
2311
2312 /* EFX capture - capture the 16 EXTINS */
Lee Revell2b637da2005-03-30 13:51:18 +02002313 if (emu->card_capabilities->sblive51) {
2314 /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER
2315 * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording.
2316 *
2317 * Since only 14 of the 16 EXTINs are used, this is not a big problem.
2318 * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
2319 * 0 and 3, then the rest of the EXTINs to the corresponding FX capture
2320 * channel. Multitrack recorders will still see the center/lfe output signal
2321 * on the second and third channels.
2322 */
2323 OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
2324 OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
2325 OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
2326 OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
2327 for (z = 4; z < 14; z++)
2328 OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
2329 } else {
2330 for (z = 0; z < 16; z++)
2331 OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002332 }
Lee Revell2b637da2005-03-30 13:51:18 +02002333
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334
2335 if (gpr > tmp) {
2336 snd_BUG();
2337 err = -EIO;
2338 goto __err;
2339 }
2340 if (i > SND_EMU10K1_GPR_CONTROLS) {
2341 snd_BUG();
2342 err = -EIO;
2343 goto __err;
2344 }
2345
2346 /* clear remaining instruction memory */
2347 while (ptr < 0x200)
2348 OP(icode, &ptr, iACC3, C_00000000, C_00000000, C_00000000, C_00000000);
2349
2350 if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0)
2351 goto __err;
2352 seg = snd_enter_user();
2353 icode->gpr_add_control_count = i;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002354 icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01002355 emu->support_tlv = 1; /* support TLV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002356 err = snd_emu10k1_icode_poke(emu, icode);
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01002357 emu->support_tlv = 0; /* clear again */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358 snd_leave_user(seg);
2359 if (err >= 0)
2360 err = snd_emu10k1_ipcm_poke(emu, ipcm);
2361 __err:
2362 kfree(ipcm);
2363 kfree(controls);
2364 if (icode != NULL) {
Clemens Ladisch4d233592005-09-05 10:35:20 +02002365 kfree((void __force *)icode->gpr_map);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002366 kfree(icode);
2367 }
2368 return err;
2369}
2370
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002371int __devinit snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372{
Takashi Iwai09668b42005-11-17 16:14:10 +01002373 spin_lock_init(&emu->fx8010.irq_lock);
2374 INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 if (emu->audigy)
2376 return _snd_emu10k1_audigy_init_efx(emu);
2377 else
2378 return _snd_emu10k1_init_efx(emu);
2379}
2380
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002381void snd_emu10k1_free_efx(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002382{
2383 /* stop processor */
2384 if (emu->audigy)
2385 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = A_DBG_SINGLE_STEP);
2386 else
2387 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP);
2388}
2389
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002390#if 0 /* FIXME: who use them? */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002391int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392{
Takashi Iwai7c22f1a2005-10-10 11:46:31 +02002393 if (output < 0 || output >= 6)
2394 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 1);
2396 return 0;
2397}
2398
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002399int snd_emu10k1_fx8010_tone_control_deactivate(struct snd_emu10k1 *emu, int output)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002400{
Takashi Iwai7c22f1a2005-10-10 11:46:31 +02002401 if (output < 0 || output >= 6)
2402 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 0);
2404 return 0;
2405}
2406#endif
2407
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002408int snd_emu10k1_fx8010_tram_setup(struct snd_emu10k1 *emu, u32 size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002409{
2410 u8 size_reg = 0;
2411
2412 /* size is in samples */
2413 if (size != 0) {
2414 size = (size - 1) >> 13;
2415
2416 while (size) {
2417 size >>= 1;
2418 size_reg++;
2419 }
2420 size = 0x2000 << size_reg;
2421 }
2422 if ((emu->fx8010.etram_pages.bytes / 2) == size)
2423 return 0;
2424 spin_lock_irq(&emu->emu_lock);
2425 outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG);
2426 spin_unlock_irq(&emu->emu_lock);
2427 snd_emu10k1_ptr_write(emu, TCB, 0, 0);
2428 snd_emu10k1_ptr_write(emu, TCBS, 0, 0);
2429 if (emu->fx8010.etram_pages.area != NULL) {
2430 snd_dma_free_pages(&emu->fx8010.etram_pages);
2431 emu->fx8010.etram_pages.area = NULL;
2432 emu->fx8010.etram_pages.bytes = 0;
2433 }
2434
2435 if (size > 0) {
2436 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
2437 size * 2, &emu->fx8010.etram_pages) < 0)
2438 return -ENOMEM;
2439 memset(emu->fx8010.etram_pages.area, 0, size * 2);
2440 snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr);
2441 snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg);
2442 spin_lock_irq(&emu->emu_lock);
2443 outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
Takashi Iwai09668b42005-11-17 16:14:10 +01002444 spin_unlock_irq(&emu->emu_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 }
2446
2447 return 0;
2448}
2449
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002450static int snd_emu10k1_fx8010_open(struct snd_hwdep * hw, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002451{
2452 return 0;
2453}
2454
2455static void copy_string(char *dst, char *src, char *null, int idx)
2456{
2457 if (src == NULL)
2458 sprintf(dst, "%s %02X", null, idx);
2459 else
2460 strcpy(dst, src);
2461}
2462
Mariusz Kozlowski51882452007-08-11 11:06:09 +02002463static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu,
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002464 struct snd_emu10k1_fx8010_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465{
2466 char **fxbus, **extin, **extout;
2467 unsigned short fxbus_mask, extin_mask, extout_mask;
2468 int res;
2469
Linus Torvalds1da177e2005-04-16 15:20:36 -07002470 info->internal_tram_size = emu->fx8010.itram_size;
2471 info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
2472 fxbus = fxbuses;
2473 extin = emu->audigy ? audigy_ins : creative_ins;
2474 extout = emu->audigy ? audigy_outs : creative_outs;
2475 fxbus_mask = emu->fx8010.fxbus_mask;
2476 extin_mask = emu->fx8010.extin_mask;
2477 extout_mask = emu->fx8010.extout_mask;
2478 for (res = 0; res < 16; res++, fxbus++, extin++, extout++) {
2479 copy_string(info->fxbus_names[res], fxbus_mask & (1 << res) ? *fxbus : NULL, "FXBUS", res);
2480 copy_string(info->extin_names[res], extin_mask & (1 << res) ? *extin : NULL, "Unused", res);
2481 copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res);
2482 }
2483 for (res = 16; res < 32; res++, extout++)
2484 copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res);
2485 info->gpr_controls = emu->fx8010.gpr_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486}
2487
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002488static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, unsigned int cmd, unsigned long arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002490 struct snd_emu10k1 *emu = hw->private_data;
2491 struct snd_emu10k1_fx8010_info *info;
2492 struct snd_emu10k1_fx8010_code *icode;
2493 struct snd_emu10k1_fx8010_pcm_rec *ipcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002494 unsigned int addr;
2495 void __user *argp = (void __user *)arg;
2496 int res;
2497
2498 switch (cmd) {
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01002499 case SNDRV_EMU10K1_IOCTL_PVERSION:
2500 emu->support_tlv = 1;
2501 return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 case SNDRV_EMU10K1_IOCTL_INFO:
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002503 info = kmalloc(sizeof(*info), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002504 if (!info)
2505 return -ENOMEM;
Mariusz Kozlowski51882452007-08-11 11:06:09 +02002506 snd_emu10k1_fx8010_info(emu, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 if (copy_to_user(argp, info, sizeof(*info))) {
2508 kfree(info);
2509 return -EFAULT;
2510 }
2511 kfree(info);
2512 return 0;
2513 case SNDRV_EMU10K1_IOCTL_CODE_POKE:
2514 if (!capable(CAP_SYS_ADMIN))
2515 return -EPERM;
Li Zefan336500f2009-04-10 09:44:31 +08002516
2517 icode = memdup_user(argp, sizeof(*icode));
2518 if (IS_ERR(icode))
2519 return PTR_ERR(icode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002520 res = snd_emu10k1_icode_poke(emu, icode);
2521 kfree(icode);
2522 return res;
2523 case SNDRV_EMU10K1_IOCTL_CODE_PEEK:
Li Zefan336500f2009-04-10 09:44:31 +08002524 icode = memdup_user(argp, sizeof(*icode));
2525 if (IS_ERR(icode))
2526 return PTR_ERR(icode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 res = snd_emu10k1_icode_peek(emu, icode);
2528 if (res == 0 && copy_to_user(argp, icode, sizeof(*icode))) {
2529 kfree(icode);
2530 return -EFAULT;
2531 }
2532 kfree(icode);
2533 return res;
2534 case SNDRV_EMU10K1_IOCTL_PCM_POKE:
Li Zefan336500f2009-04-10 09:44:31 +08002535 ipcm = memdup_user(argp, sizeof(*ipcm));
2536 if (IS_ERR(ipcm))
2537 return PTR_ERR(ipcm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 res = snd_emu10k1_ipcm_poke(emu, ipcm);
2539 kfree(ipcm);
2540 return res;
2541 case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
Li Zefan336500f2009-04-10 09:44:31 +08002542 ipcm = memdup_user(argp, sizeof(*ipcm));
2543 if (IS_ERR(ipcm))
2544 return PTR_ERR(ipcm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 res = snd_emu10k1_ipcm_peek(emu, ipcm);
2546 if (res == 0 && copy_to_user(argp, ipcm, sizeof(*ipcm))) {
2547 kfree(ipcm);
2548 return -EFAULT;
2549 }
2550 kfree(ipcm);
2551 return res;
2552 case SNDRV_EMU10K1_IOCTL_TRAM_SETUP:
2553 if (!capable(CAP_SYS_ADMIN))
2554 return -EPERM;
2555 if (get_user(addr, (unsigned int __user *)argp))
2556 return -EFAULT;
Ingo Molnar62932df2006-01-16 16:34:20 +01002557 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 res = snd_emu10k1_fx8010_tram_setup(emu, addr);
Ingo Molnar62932df2006-01-16 16:34:20 +01002559 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 return res;
2561 case SNDRV_EMU10K1_IOCTL_STOP:
2562 if (!capable(CAP_SYS_ADMIN))
2563 return -EPERM;
2564 if (emu->audigy)
2565 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP);
2566 else
2567 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP);
2568 return 0;
2569 case SNDRV_EMU10K1_IOCTL_CONTINUE:
2570 if (!capable(CAP_SYS_ADMIN))
2571 return -EPERM;
2572 if (emu->audigy)
2573 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = 0);
2574 else
2575 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = 0);
2576 return 0;
2577 case SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER:
2578 if (!capable(CAP_SYS_ADMIN))
2579 return -EPERM;
2580 if (emu->audigy)
2581 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_ZC);
2582 else
2583 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_ZC);
2584 udelay(10);
2585 if (emu->audigy)
2586 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
2587 else
2588 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
2589 return 0;
2590 case SNDRV_EMU10K1_IOCTL_SINGLE_STEP:
2591 if (!capable(CAP_SYS_ADMIN))
2592 return -EPERM;
2593 if (get_user(addr, (unsigned int __user *)argp))
2594 return -EFAULT;
2595 if (addr > 0x1ff)
2596 return -EINVAL;
2597 if (emu->audigy)
2598 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | addr);
2599 else
2600 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | addr);
2601 udelay(10);
2602 if (emu->audigy)
2603 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | A_DBG_STEP_ADDR | addr);
2604 else
2605 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | EMU10K1_DBG_STEP | addr);
2606 return 0;
2607 case SNDRV_EMU10K1_IOCTL_DBG_READ:
2608 if (emu->audigy)
2609 addr = snd_emu10k1_ptr_read(emu, A_DBG, 0);
2610 else
2611 addr = snd_emu10k1_ptr_read(emu, DBG, 0);
2612 if (put_user(addr, (unsigned int __user *)argp))
2613 return -EFAULT;
2614 return 0;
2615 }
2616 return -ENOTTY;
2617}
2618
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002619static int snd_emu10k1_fx8010_release(struct snd_hwdep * hw, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620{
2621 return 0;
2622}
2623
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002624int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct snd_hwdep ** rhwdep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002625{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002626 struct snd_hwdep *hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002627 int err;
2628
2629 if (rhwdep)
2630 *rhwdep = NULL;
2631 if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0)
2632 return err;
2633 strcpy(hw->name, "EMU10K1 (FX8010)");
2634 hw->iface = SNDRV_HWDEP_IFACE_EMU10K1;
2635 hw->ops.open = snd_emu10k1_fx8010_open;
2636 hw->ops.ioctl = snd_emu10k1_fx8010_ioctl;
2637 hw->ops.release = snd_emu10k1_fx8010_release;
2638 hw->private_data = emu;
2639 if (rhwdep)
2640 *rhwdep = hw;
2641 return 0;
2642}
Takashi Iwai09668b42005-11-17 16:14:10 +01002643
2644#ifdef CONFIG_PM
2645int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
2646{
2647 int len;
2648
2649 len = emu->audigy ? 0x200 : 0x100;
2650 emu->saved_gpr = kmalloc(len * 4, GFP_KERNEL);
2651 if (! emu->saved_gpr)
2652 return -ENOMEM;
2653 len = emu->audigy ? 0x100 : 0xa0;
2654 emu->tram_val_saved = kmalloc(len * 4, GFP_KERNEL);
2655 emu->tram_addr_saved = kmalloc(len * 4, GFP_KERNEL);
2656 if (! emu->tram_val_saved || ! emu->tram_addr_saved)
2657 return -ENOMEM;
2658 len = emu->audigy ? 2 * 1024 : 2 * 512;
2659 emu->saved_icode = vmalloc(len * 4);
2660 if (! emu->saved_icode)
2661 return -ENOMEM;
2662 return 0;
2663}
2664
2665void snd_emu10k1_efx_free_pm_buffer(struct snd_emu10k1 *emu)
2666{
2667 kfree(emu->saved_gpr);
2668 kfree(emu->tram_val_saved);
2669 kfree(emu->tram_addr_saved);
2670 vfree(emu->saved_icode);
2671}
2672
2673/*
2674 * save/restore GPR, TRAM and codes
2675 */
2676void snd_emu10k1_efx_suspend(struct snd_emu10k1 *emu)
2677{
2678 int i, len;
2679
2680 len = emu->audigy ? 0x200 : 0x100;
2681 for (i = 0; i < len; i++)
2682 emu->saved_gpr[i] = snd_emu10k1_ptr_read(emu, emu->gpr_base + i, 0);
2683
2684 len = emu->audigy ? 0x100 : 0xa0;
2685 for (i = 0; i < len; i++) {
2686 emu->tram_val_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + i, 0);
2687 emu->tram_addr_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + i, 0);
2688 if (emu->audigy) {
2689 emu->tram_addr_saved[i] >>= 12;
2690 emu->tram_addr_saved[i] |=
2691 snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + i, 0) << 20;
2692 }
2693 }
2694
2695 len = emu->audigy ? 2 * 1024 : 2 * 512;
2696 for (i = 0; i < len; i++)
2697 emu->saved_icode[i] = snd_emu10k1_efx_read(emu, i);
2698}
2699
2700void snd_emu10k1_efx_resume(struct snd_emu10k1 *emu)
2701{
2702 int i, len;
2703
2704 /* set up TRAM */
2705 if (emu->fx8010.etram_pages.bytes > 0) {
2706 unsigned size, size_reg = 0;
2707 size = emu->fx8010.etram_pages.bytes / 2;
2708 size = (size - 1) >> 13;
2709 while (size) {
2710 size >>= 1;
2711 size_reg++;
2712 }
2713 outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG);
2714 snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr);
2715 snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg);
2716 outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
2717 }
2718
2719 if (emu->audigy)
2720 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP);
2721 else
2722 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);
2723
2724 len = emu->audigy ? 0x200 : 0x100;
2725 for (i = 0; i < len; i++)
2726 snd_emu10k1_ptr_write(emu, emu->gpr_base + i, 0, emu->saved_gpr[i]);
2727
2728 len = emu->audigy ? 0x100 : 0xa0;
2729 for (i = 0; i < len; i++) {
2730 snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + i, 0,
2731 emu->tram_val_saved[i]);
2732 if (! emu->audigy)
2733 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0,
2734 emu->tram_addr_saved[i]);
2735 else {
2736 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0,
2737 emu->tram_addr_saved[i] << 12);
2738 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0,
2739 emu->tram_addr_saved[i] >> 20);
2740 }
2741 }
2742
2743 len = emu->audigy ? 2 * 1024 : 2 * 512;
2744 for (i = 0; i < len; i++)
2745 snd_emu10k1_efx_write(emu, i, emu->saved_icode[i]);
2746
2747 /* start FX processor when the DSP code is updated */
2748 if (emu->audigy)
2749 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
2750 else
2751 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
2752}
2753#endif