blob: 56fc47bd6dbab381ad6b9453fbf1c4cb2e23ceb1 [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
Raymond Yaubfe9fc8a2011-05-20 14:32:04 +0800306/* EMU10K1 bass/treble db gain */
307static const DECLARE_TLV_DB_SCALE(snd_emu10k1_bass_treble_db_scale, -1200, 60, 0);
308
Linus Torvalds1da177e2005-04-16 15:20:36 -0700309static const u32 onoff_table[2] = {
310 0x00000000, 0x00000001
311};
312
313/*
314 */
315
316static inline mm_segment_t snd_enter_user(void)
317{
318 mm_segment_t fs = get_fs();
319 set_fs(get_ds());
320 return fs;
321}
322
323static inline void snd_leave_user(mm_segment_t fs)
324{
325 set_fs(fs);
326}
327
328/*
329 * controls
330 */
331
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100332static int snd_emu10k1_gpr_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700333{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100334 struct snd_emu10k1_fx8010_ctl *ctl =
335 (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336
337 if (ctl->min == 0 && ctl->max == 1)
338 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
339 else
340 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
341 uinfo->count = ctl->vcount;
342 uinfo->value.integer.min = ctl->min;
343 uinfo->value.integer.max = ctl->max;
344 return 0;
345}
346
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100347static int snd_emu10k1_gpr_ctl_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100349 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
350 struct snd_emu10k1_fx8010_ctl *ctl =
351 (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 unsigned long flags;
353 unsigned int i;
354
355 spin_lock_irqsave(&emu->reg_lock, flags);
356 for (i = 0; i < ctl->vcount; i++)
357 ucontrol->value.integer.value[i] = ctl->value[i];
358 spin_unlock_irqrestore(&emu->reg_lock, flags);
359 return 0;
360}
361
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100362static int snd_emu10k1_gpr_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100364 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
365 struct snd_emu10k1_fx8010_ctl *ctl =
366 (struct snd_emu10k1_fx8010_ctl *) kcontrol->private_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 unsigned long flags;
368 unsigned int nval, val;
369 unsigned int i, j;
370 int change = 0;
371
372 spin_lock_irqsave(&emu->reg_lock, flags);
373 for (i = 0; i < ctl->vcount; i++) {
374 nval = ucontrol->value.integer.value[i];
375 if (nval < ctl->min)
376 nval = ctl->min;
377 if (nval > ctl->max)
378 nval = ctl->max;
379 if (nval != ctl->value[i])
380 change = 1;
381 val = ctl->value[i] = nval;
382 switch (ctl->translation) {
383 case EMU10K1_GPR_TRANSLATION_NONE:
384 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, val);
385 break;
386 case EMU10K1_GPR_TRANSLATION_TABLE100:
387 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, db_table[val]);
388 break;
389 case EMU10K1_GPR_TRANSLATION_BASS:
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200390 if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) {
391 change = -EIO;
392 goto __error;
393 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 for (j = 0; j < 5; j++)
395 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, bass_table[val][j]);
396 break;
397 case EMU10K1_GPR_TRANSLATION_TREBLE:
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200398 if ((ctl->count % 5) != 0 || (ctl->count / 5) != ctl->vcount) {
399 change = -EIO;
400 goto __error;
401 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 for (j = 0; j < 5; j++)
403 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[j * ctl->vcount + i], 0, treble_table[val][j]);
404 break;
405 case EMU10K1_GPR_TRANSLATION_ONOFF:
406 snd_emu10k1_ptr_write(emu, emu->gpr_base + ctl->gpr[i], 0, onoff_table[val]);
407 break;
408 }
409 }
410 __error:
411 spin_unlock_irqrestore(&emu->reg_lock, flags);
412 return change;
413}
414
415/*
416 * Interrupt handler
417 */
418
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100419static void snd_emu10k1_fx8010_interrupt(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100421 struct snd_emu10k1_fx8010_irq *irq, *nirq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422
423 irq = emu->fx8010.irq_handlers;
424 while (irq) {
425 nirq = irq->next; /* irq ptr can be removed from list */
426 if (snd_emu10k1_ptr_read(emu, emu->gpr_base + irq->gpr_running, 0) & 0xffff0000) {
427 if (irq->handler)
428 irq->handler(emu, irq->private_data);
429 snd_emu10k1_ptr_write(emu, emu->gpr_base + irq->gpr_running, 0, 1);
430 }
431 irq = nirq;
432 }
433}
434
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100435int snd_emu10k1_fx8010_register_irq_handler(struct snd_emu10k1 *emu,
436 snd_fx8010_irq_handler_t *handler,
437 unsigned char gpr_running,
438 void *private_data,
439 struct snd_emu10k1_fx8010_irq **r_irq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100441 struct snd_emu10k1_fx8010_irq *irq;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442 unsigned long flags;
443
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 irq = kmalloc(sizeof(*irq), GFP_ATOMIC);
445 if (irq == NULL)
446 return -ENOMEM;
447 irq->handler = handler;
448 irq->gpr_running = gpr_running;
449 irq->private_data = private_data;
450 irq->next = NULL;
451 spin_lock_irqsave(&emu->fx8010.irq_lock, flags);
452 if (emu->fx8010.irq_handlers == NULL) {
453 emu->fx8010.irq_handlers = irq;
454 emu->dsp_interrupt = snd_emu10k1_fx8010_interrupt;
455 snd_emu10k1_intr_enable(emu, INTE_FXDSPENABLE);
456 } else {
457 irq->next = emu->fx8010.irq_handlers;
458 emu->fx8010.irq_handlers = irq;
459 }
460 spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
461 if (r_irq)
462 *r_irq = irq;
463 return 0;
464}
465
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100466int snd_emu10k1_fx8010_unregister_irq_handler(struct snd_emu10k1 *emu,
467 struct snd_emu10k1_fx8010_irq *irq)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100469 struct snd_emu10k1_fx8010_irq *tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 unsigned long flags;
471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 spin_lock_irqsave(&emu->fx8010.irq_lock, flags);
473 if ((tmp = emu->fx8010.irq_handlers) == irq) {
474 emu->fx8010.irq_handlers = tmp->next;
475 if (emu->fx8010.irq_handlers == NULL) {
476 snd_emu10k1_intr_disable(emu, INTE_FXDSPENABLE);
477 emu->dsp_interrupt = NULL;
478 }
479 } else {
480 while (tmp && tmp->next != irq)
481 tmp = tmp->next;
482 if (tmp)
483 tmp->next = tmp->next->next;
484 }
485 spin_unlock_irqrestore(&emu->fx8010.irq_lock, flags);
486 kfree(irq);
487 return 0;
488}
489
490/*************************************************************************
491 * EMU10K1 effect manager
492 *************************************************************************/
493
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100494static void snd_emu10k1_write_op(struct snd_emu10k1_fx8010_code *icode,
495 unsigned int *ptr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700496 u32 op, u32 r, u32 a, u32 x, u32 y)
497{
498 u_int32_t *code;
Takashi Iwaida3cec32008-08-08 17:12:14 +0200499 if (snd_BUG_ON(*ptr >= 512))
500 return;
Clemens Ladisch4d233592005-09-05 10:35:20 +0200501 code = (u_int32_t __force *)icode->code + (*ptr) * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 set_bit(*ptr, icode->code_valid);
503 code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
504 code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
505 (*ptr)++;
506}
507
508#define OP(icode, ptr, op, r, a, x, y) \
509 snd_emu10k1_write_op(icode, ptr, op, r, a, x, y)
510
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100511static void snd_emu10k1_audigy_write_op(struct snd_emu10k1_fx8010_code *icode,
512 unsigned int *ptr,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513 u32 op, u32 r, u32 a, u32 x, u32 y)
514{
515 u_int32_t *code;
Takashi Iwaida3cec32008-08-08 17:12:14 +0200516 if (snd_BUG_ON(*ptr >= 1024))
517 return;
Clemens Ladisch4d233592005-09-05 10:35:20 +0200518 code = (u_int32_t __force *)icode->code + (*ptr) * 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 set_bit(*ptr, icode->code_valid);
520 code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
521 code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
522 (*ptr)++;
523}
524
525#define A_OP(icode, ptr, op, r, a, x, y) \
526 snd_emu10k1_audigy_write_op(icode, ptr, op, r, a, x, y)
527
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100528static void snd_emu10k1_efx_write(struct snd_emu10k1 *emu, unsigned int pc, unsigned int data)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529{
530 pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
531 snd_emu10k1_ptr_write(emu, pc, 0, data);
532}
533
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100534unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535{
536 pc += emu->audigy ? A_MICROCODEBASE : MICROCODEBASE;
537 return snd_emu10k1_ptr_read(emu, pc, 0);
538}
539
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100540static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu,
541 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542{
543 int gpr;
544 u32 val;
545
546 for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
547 if (!test_bit(gpr, icode->gpr_valid))
548 continue;
549 if (get_user(val, &icode->gpr_map[gpr]))
550 return -EFAULT;
551 snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val);
552 }
553 return 0;
554}
555
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100556static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu,
557 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
559 int gpr;
560 u32 val;
561
562 for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
563 set_bit(gpr, icode->gpr_valid);
564 val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0);
565 if (put_user(val, &icode->gpr_map[gpr]))
566 return -EFAULT;
567 }
568 return 0;
569}
570
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100571static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu,
572 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573{
574 int tram;
575 u32 addr, val;
576
577 for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
578 if (!test_bit(tram, icode->tram_valid))
579 continue;
580 if (get_user(val, &icode->tram_data_map[tram]) ||
581 get_user(addr, &icode->tram_addr_map[tram]))
582 return -EFAULT;
583 snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val);
584 if (!emu->audigy) {
585 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr);
586 } else {
587 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + tram, 0, addr << 12);
588 snd_emu10k1_ptr_write(emu, A_TANKMEMCTLREGBASE + tram, 0, addr >> 20);
589 }
590 }
591 return 0;
592}
593
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100594static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu,
595 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700596{
597 int tram;
598 u32 val, addr;
599
600 memset(icode->tram_valid, 0, sizeof(icode->tram_valid));
601 for (tram = 0; tram < (emu->audigy ? 0x100 : 0xa0); tram++) {
602 set_bit(tram, icode->tram_valid);
603 val = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + tram, 0);
604 if (!emu->audigy) {
605 addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0);
606 } else {
607 addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12;
608 addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20;
609 }
610 if (put_user(val, &icode->tram_data_map[tram]) ||
611 put_user(addr, &icode->tram_addr_map[tram]))
612 return -EFAULT;
613 }
614 return 0;
615}
616
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100617static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu,
618 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619{
620 u32 pc, lo, hi;
621
622 for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
623 if (!test_bit(pc / 2, icode->code_valid))
624 continue;
625 if (get_user(lo, &icode->code[pc + 0]) ||
626 get_user(hi, &icode->code[pc + 1]))
627 return -EFAULT;
628 snd_emu10k1_efx_write(emu, pc + 0, lo);
629 snd_emu10k1_efx_write(emu, pc + 1, hi);
630 }
631 return 0;
632}
633
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100634static int snd_emu10k1_code_peek(struct snd_emu10k1 *emu,
635 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636{
637 u32 pc;
638
639 memset(icode->code_valid, 0, sizeof(icode->code_valid));
640 for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
641 set_bit(pc / 2, icode->code_valid);
642 if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0]))
643 return -EFAULT;
644 if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1]))
645 return -EFAULT;
646 }
647 return 0;
648}
649
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100650static struct snd_emu10k1_fx8010_ctl *
651snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100653 struct snd_emu10k1_fx8010_ctl *ctl;
654 struct snd_kcontrol *kcontrol;
Matthias Kaehlckec2d70512007-09-17 14:41:16 +0200655
656 list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 kcontrol = ctl->kcontrol;
658 if (kcontrol->id.iface == id->iface &&
659 !strcmp(kcontrol->id.name, id->name) &&
660 kcontrol->id.index == id->index)
661 return ctl;
662 }
663 return NULL;
664}
665
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100666#define MAX_TLV_SIZE 256
667
Takashi Iwai0cb29ea2007-01-29 15:33:49 +0100668static unsigned int *copy_tlv(const unsigned int __user *_tlv)
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100669{
670 unsigned int data[2];
671 unsigned int *tlv;
672
673 if (!_tlv)
674 return NULL;
675 if (copy_from_user(data, _tlv, sizeof(data)))
676 return NULL;
677 if (data[1] >= MAX_TLV_SIZE)
678 return NULL;
Takashi Iwai6735e572008-01-19 10:33:07 +0100679 tlv = kmalloc(data[1] + sizeof(data), GFP_KERNEL);
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100680 if (!tlv)
681 return NULL;
682 memcpy(tlv, data, sizeof(data));
683 if (copy_from_user(tlv + 2, _tlv + 2, data[1])) {
684 kfree(tlv);
685 return NULL;
686 }
687 return tlv;
688}
689
690static int copy_gctl(struct snd_emu10k1 *emu,
691 struct snd_emu10k1_fx8010_control_gpr *gctl,
692 struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
693 int idx)
694{
695 struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
696
697 if (emu->support_tlv)
698 return copy_from_user(gctl, &_gctl[idx], sizeof(*gctl));
699 octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
700 if (copy_from_user(gctl, &octl[idx], sizeof(*octl)))
701 return -EFAULT;
702 gctl->tlv = NULL;
703 return 0;
704}
705
706static int copy_gctl_to_user(struct snd_emu10k1 *emu,
707 struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
708 struct snd_emu10k1_fx8010_control_gpr *gctl,
709 int idx)
710{
711 struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
712
713 if (emu->support_tlv)
714 return copy_to_user(&_gctl[idx], gctl, sizeof(*gctl));
715
716 octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
717 return copy_to_user(&octl[idx], gctl, sizeof(*octl));
718}
719
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100720static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
721 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722{
723 unsigned int i;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100724 struct snd_ctl_elem_id __user *_id;
725 struct snd_ctl_elem_id id;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100726 struct snd_emu10k1_fx8010_control_gpr *gctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 int err;
728
729 for (i = 0, _id = icode->gpr_del_controls;
730 i < icode->gpr_del_control_count; i++, _id++) {
731 if (copy_from_user(&id, _id, sizeof(id)))
732 return -EFAULT;
733 if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)
734 return -ENOENT;
735 }
736 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
737 if (! gctl)
738 return -ENOMEM;
739 err = 0;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100740 for (i = 0; i < icode->gpr_add_control_count; i++) {
741 if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700742 err = -EFAULT;
743 goto __error;
744 }
745 if (snd_emu10k1_look_for_ctl(emu, &gctl->id))
746 continue;
747 down_read(&emu->card->controls_rwsem);
748 if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) {
749 up_read(&emu->card->controls_rwsem);
750 err = -EEXIST;
751 goto __error;
752 }
753 up_read(&emu->card->controls_rwsem);
754 if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
755 gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
756 err = -EINVAL;
757 goto __error;
758 }
759 }
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100760 for (i = 0; i < icode->gpr_list_control_count; i++) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 /* FIXME: we need to check the WRITE access */
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100762 if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700763 err = -EFAULT;
764 goto __error;
765 }
766 }
767 __error:
768 kfree(gctl);
769 return err;
770}
771
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100772static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773{
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100774 struct snd_emu10k1_fx8010_ctl *ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700775
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100776 ctl = (struct snd_emu10k1_fx8010_ctl *) kctl->private_value;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 kctl->private_value = 0;
778 list_del(&ctl->list);
779 kfree(ctl);
Markus Elfring31604d32014-11-03 14:54:36 +0100780 kfree(kctl->tlv.p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781}
782
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100783static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
784 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700785{
786 unsigned int i, j;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100787 struct snd_emu10k1_fx8010_control_gpr *gctl;
788 struct snd_emu10k1_fx8010_ctl *ctl, *nctl;
789 struct snd_kcontrol_new knew;
790 struct snd_kcontrol *kctl;
791 struct snd_ctl_elem_value *val;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700792 int err = 0;
793
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100794 val = kmalloc(sizeof(*val), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700795 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
796 nctl = kmalloc(sizeof(*nctl), GFP_KERNEL);
797 if (!val || !gctl || !nctl) {
798 err = -ENOMEM;
799 goto __error;
800 }
801
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100802 for (i = 0; i < icode->gpr_add_control_count; i++) {
803 if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804 err = -EFAULT;
805 goto __error;
806 }
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200807 if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
808 gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
809 err = -EINVAL;
810 goto __error;
811 }
812 if (! gctl->id.name[0]) {
813 err = -EINVAL;
814 goto __error;
815 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816 ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id);
817 memset(&knew, 0, sizeof(knew));
818 knew.iface = gctl->id.iface;
819 knew.name = gctl->id.name;
820 knew.index = gctl->id.index;
821 knew.device = gctl->id.device;
822 knew.subdevice = gctl->id.subdevice;
823 knew.info = snd_emu10k1_gpr_ctl_info;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100824 knew.tlv.p = copy_tlv(gctl->tlv);
825 if (knew.tlv.p)
James Courtier-Dutton31508f82006-07-22 17:02:10 +0100826 knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
827 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 knew.get = snd_emu10k1_gpr_ctl_get;
829 knew.put = snd_emu10k1_gpr_ctl_put;
830 memset(nctl, 0, sizeof(*nctl));
831 nctl->vcount = gctl->vcount;
832 nctl->count = gctl->count;
833 for (j = 0; j < 32; j++) {
834 nctl->gpr[j] = gctl->gpr[j];
835 nctl->value[j] = ~gctl->value[j]; /* inverted, we want to write new value in gpr_ctl_put() */
836 val->value.integer.value[j] = gctl->value[j];
837 }
838 nctl->min = gctl->min;
839 nctl->max = gctl->max;
840 nctl->translation = gctl->translation;
841 if (ctl == NULL) {
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100842 ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 if (ctl == NULL) {
844 err = -ENOMEM;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100845 kfree(knew.tlv.p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 goto __error;
847 }
848 knew.private_value = (unsigned long)ctl;
849 *ctl = *nctl;
850 if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) {
851 kfree(ctl);
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100852 kfree(knew.tlv.p);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 goto __error;
854 }
855 kctl->private_free = snd_emu10k1_ctl_private_free;
856 ctl->kcontrol = kctl;
857 list_add_tail(&ctl->list, &emu->fx8010.gpr_ctl);
858 } else {
859 /* overwrite */
860 nctl->list = ctl->list;
861 nctl->kcontrol = ctl->kcontrol;
862 *ctl = *nctl;
863 snd_ctl_notify(emu->card, SNDRV_CTL_EVENT_MASK_VALUE |
864 SNDRV_CTL_EVENT_MASK_INFO, &ctl->kcontrol->id);
865 }
866 snd_emu10k1_gpr_ctl_put(ctl->kcontrol, val);
867 }
868 __error:
869 kfree(nctl);
870 kfree(gctl);
871 kfree(val);
872 return err;
873}
874
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100875static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu,
876 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700877{
878 unsigned int i;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100879 struct snd_ctl_elem_id id;
880 struct snd_ctl_elem_id __user *_id;
881 struct snd_emu10k1_fx8010_ctl *ctl;
882 struct snd_card *card = emu->card;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883
884 for (i = 0, _id = icode->gpr_del_controls;
885 i < icode->gpr_del_control_count; i++, _id++) {
Takashi Iwai7c22f1a2005-10-10 11:46:31 +0200886 if (copy_from_user(&id, _id, sizeof(id)))
887 return -EFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700888 down_write(&card->controls_rwsem);
889 ctl = snd_emu10k1_look_for_ctl(emu, &id);
890 if (ctl)
891 snd_ctl_remove(card, ctl->kcontrol);
892 up_write(&card->controls_rwsem);
893 }
894 return 0;
895}
896
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100897static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
898 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700899{
900 unsigned int i = 0, j;
901 unsigned int total = 0;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100902 struct snd_emu10k1_fx8010_control_gpr *gctl;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100903 struct snd_emu10k1_fx8010_ctl *ctl;
904 struct snd_ctl_elem_id *id;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700905
906 gctl = kmalloc(sizeof(*gctl), GFP_KERNEL);
907 if (! gctl)
908 return -ENOMEM;
909
Matthias Kaehlckec2d70512007-09-17 14:41:16 +0200910 list_for_each_entry(ctl, &emu->fx8010.gpr_ctl, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700911 total++;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100912 if (icode->gpr_list_controls &&
913 i < icode->gpr_list_control_count) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914 memset(gctl, 0, sizeof(*gctl));
915 id = &ctl->kcontrol->id;
916 gctl->id.iface = id->iface;
917 strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
918 gctl->id.index = id->index;
919 gctl->id.device = id->device;
920 gctl->id.subdevice = id->subdevice;
921 gctl->vcount = ctl->vcount;
922 gctl->count = ctl->count;
923 for (j = 0; j < 32; j++) {
924 gctl->gpr[j] = ctl->gpr[j];
925 gctl->value[j] = ctl->value[j];
926 }
927 gctl->min = ctl->min;
928 gctl->max = ctl->max;
929 gctl->translation = ctl->translation;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +0100930 if (copy_gctl_to_user(emu, icode->gpr_list_controls,
931 gctl, i)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700932 kfree(gctl);
933 return -EFAULT;
934 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700935 i++;
936 }
937 }
938 icode->gpr_list_control_total = total;
939 kfree(gctl);
940 return 0;
941}
942
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100943static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu,
944 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700945{
946 int err = 0;
947
Ingo Molnar62932df2006-01-16 16:34:20 +0100948 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949 if ((err = snd_emu10k1_verify_controls(emu, icode)) < 0)
950 goto __error;
951 strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
952 /* stop FX processor - this may be dangerous, but it's better to miss
953 some samples than generate wrong ones - [jk] */
954 if (emu->audigy)
955 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP);
956 else
957 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);
958 /* ok, do the main job */
959 if ((err = snd_emu10k1_del_controls(emu, icode)) < 0 ||
960 (err = snd_emu10k1_gpr_poke(emu, icode)) < 0 ||
961 (err = snd_emu10k1_tram_poke(emu, icode)) < 0 ||
962 (err = snd_emu10k1_code_poke(emu, icode)) < 0 ||
963 (err = snd_emu10k1_add_controls(emu, icode)) < 0)
964 goto __error;
965 /* start FX processor when the DSP code is updated */
966 if (emu->audigy)
967 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
968 else
969 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
970 __error:
Ingo Molnar62932df2006-01-16 16:34:20 +0100971 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 return err;
973}
974
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100975static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu,
976 struct snd_emu10k1_fx8010_code *icode)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977{
978 int err;
979
Ingo Molnar62932df2006-01-16 16:34:20 +0100980 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name));
982 /* ok, do the main job */
983 err = snd_emu10k1_gpr_peek(emu, icode);
984 if (err >= 0)
985 err = snd_emu10k1_tram_peek(emu, icode);
986 if (err >= 0)
987 err = snd_emu10k1_code_peek(emu, icode);
988 if (err >= 0)
989 err = snd_emu10k1_list_controls(emu, icode);
Ingo Molnar62932df2006-01-16 16:34:20 +0100990 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 return err;
992}
993
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100994static int snd_emu10k1_ipcm_poke(struct snd_emu10k1 *emu,
995 struct snd_emu10k1_fx8010_pcm_rec *ipcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996{
997 unsigned int i;
998 int err = 0;
Takashi Iwaieb4698f2005-11-17 14:50:13 +0100999 struct snd_emu10k1_fx8010_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001000
1001 if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
1002 return -EINVAL;
1003 if (ipcm->channels > 32)
1004 return -EINVAL;
1005 pcm = &emu->fx8010.pcm[ipcm->substream];
Ingo Molnar62932df2006-01-16 16:34:20 +01001006 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 spin_lock_irq(&emu->reg_lock);
1008 if (pcm->opened) {
1009 err = -EBUSY;
1010 goto __error;
1011 }
1012 if (ipcm->channels == 0) { /* remove */
1013 pcm->valid = 0;
1014 } else {
1015 /* FIXME: we need to add universal code to the PCM transfer routine */
1016 if (ipcm->channels != 2) {
1017 err = -EINVAL;
1018 goto __error;
1019 }
1020 pcm->valid = 1;
1021 pcm->opened = 0;
1022 pcm->channels = ipcm->channels;
1023 pcm->tram_start = ipcm->tram_start;
1024 pcm->buffer_size = ipcm->buffer_size;
1025 pcm->gpr_size = ipcm->gpr_size;
1026 pcm->gpr_count = ipcm->gpr_count;
1027 pcm->gpr_tmpcount = ipcm->gpr_tmpcount;
1028 pcm->gpr_ptr = ipcm->gpr_ptr;
1029 pcm->gpr_trigger = ipcm->gpr_trigger;
1030 pcm->gpr_running = ipcm->gpr_running;
1031 for (i = 0; i < pcm->channels; i++)
1032 pcm->etram[i] = ipcm->etram[i];
1033 }
1034 __error:
1035 spin_unlock_irq(&emu->reg_lock);
Ingo Molnar62932df2006-01-16 16:34:20 +01001036 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037 return err;
1038}
1039
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001040static int snd_emu10k1_ipcm_peek(struct snd_emu10k1 *emu,
1041 struct snd_emu10k1_fx8010_pcm_rec *ipcm)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042{
1043 unsigned int i;
1044 int err = 0;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001045 struct snd_emu10k1_fx8010_pcm *pcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046
1047 if (ipcm->substream >= EMU10K1_FX8010_PCM_COUNT)
1048 return -EINVAL;
1049 pcm = &emu->fx8010.pcm[ipcm->substream];
Ingo Molnar62932df2006-01-16 16:34:20 +01001050 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001051 spin_lock_irq(&emu->reg_lock);
1052 ipcm->channels = pcm->channels;
1053 ipcm->tram_start = pcm->tram_start;
1054 ipcm->buffer_size = pcm->buffer_size;
1055 ipcm->gpr_size = pcm->gpr_size;
1056 ipcm->gpr_ptr = pcm->gpr_ptr;
1057 ipcm->gpr_count = pcm->gpr_count;
1058 ipcm->gpr_tmpcount = pcm->gpr_tmpcount;
1059 ipcm->gpr_trigger = pcm->gpr_trigger;
1060 ipcm->gpr_running = pcm->gpr_running;
1061 for (i = 0; i < pcm->channels; i++)
1062 ipcm->etram[i] = pcm->etram[i];
1063 ipcm->res1 = ipcm->res2 = 0;
1064 ipcm->pad = 0;
1065 spin_unlock_irq(&emu->reg_lock);
Ingo Molnar62932df2006-01-16 16:34:20 +01001066 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 return err;
1068}
1069
Mikael Magnussonedf8e452005-09-13 11:32:58 +02001070#define SND_EMU10K1_GPR_CONTROLS 44
1071#define SND_EMU10K1_INPUTS 12
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072#define SND_EMU10K1_PLAYBACK_CHANNELS 8
1073#define SND_EMU10K1_CAPTURE_CHANNELS 4
1074
Bill Pembertone23e7a12012-12-06 12:35:10 -05001075static void
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001076snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1077 const char *name, int gpr, int defval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001078{
1079 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1080 strcpy(ctl->id.name, name);
1081 ctl->vcount = ctl->count = 1;
1082 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
Clemens Ladisch4daf7a02010-05-25 09:04:49 +02001083 if (high_res_gpr_volume) {
1084 ctl->min = 0;
1085 ctl->max = 0x7fffffff;
1086 ctl->tlv = snd_emu10k1_db_linear;
1087 ctl->translation = EMU10K1_GPR_TRANSLATION_NONE;
1088 } else {
1089 ctl->min = 0;
1090 ctl->max = 100;
1091 ctl->tlv = snd_emu10k1_db_scale1;
1092 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
1093 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094}
1095
Bill Pembertone23e7a12012-12-06 12:35:10 -05001096static void
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001097snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1098 const char *name, int gpr, int defval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001099{
1100 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1101 strcpy(ctl->id.name, name);
1102 ctl->vcount = ctl->count = 2;
1103 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1104 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
Clemens Ladisch4daf7a02010-05-25 09:04:49 +02001105 if (high_res_gpr_volume) {
1106 ctl->min = 0;
1107 ctl->max = 0x7fffffff;
1108 ctl->tlv = snd_emu10k1_db_linear;
1109 ctl->translation = EMU10K1_GPR_TRANSLATION_NONE;
1110 } else {
1111 ctl->min = 0;
1112 ctl->max = 100;
1113 ctl->tlv = snd_emu10k1_db_scale1;
1114 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
1115 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001116}
1117
Bill Pembertone23e7a12012-12-06 12:35:10 -05001118static void
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001119snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1120 const char *name, int gpr, int defval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001121{
1122 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1123 strcpy(ctl->id.name, name);
1124 ctl->vcount = ctl->count = 1;
1125 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1126 ctl->min = 0;
1127 ctl->max = 1;
1128 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
1129}
1130
Bill Pembertone23e7a12012-12-06 12:35:10 -05001131static void
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001132snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1133 const char *name, int gpr, int defval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134{
1135 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1136 strcpy(ctl->id.name, name);
1137 ctl->vcount = ctl->count = 2;
1138 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1139 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
1140 ctl->min = 0;
1141 ctl->max = 1;
1142 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
1143}
1144
Pavel Hofman13d45702007-06-11 12:21:20 +02001145/*
1146 * Used for emu1010 - conversion from 32-bit capture inputs from HANA
1147 * to 2 x 16-bit registers in audigy - their values are read via DMA.
1148 * Conversion is performed by Audigy DSP instructions of FX8010.
1149 */
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001150static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
1151 struct snd_emu10k1_fx8010_code *icode,
1152 u32 *ptr, int tmp, int bit_shifter16,
1153 int reg_in, int reg_out)
1154{
1155 A_OP(icode, ptr, iACC3, A_GPR(tmp + 1), reg_in, A_C_00000000, A_C_00000000);
1156 A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp + 1), A_GPR(bit_shifter16 - 1), A_C_00000000);
1157 A_OP(icode, ptr, iTSTNEG, A_GPR(tmp + 2), A_GPR(tmp), A_C_80000000, A_GPR(bit_shifter16 - 2));
1158 A_OP(icode, ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_C_80000000, A_C_00000000);
1159 A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp), A_GPR(bit_shifter16 - 3), A_C_00000000);
1160 A_OP(icode, ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A_GPR(tmp), A_C_00010000);
1161 A_OP(icode, ptr, iANDXOR, reg_out, A_GPR(tmp), A_C_ffffffff, A_GPR(tmp + 2));
1162 A_OP(icode, ptr, iACC3, reg_out + 1, A_GPR(tmp + 1), A_C_00000000, A_C_00000000);
1163 return 1;
1164}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001165
1166/*
1167 * initial DSP configuration for Audigy
1168 */
1169
Bill Pembertone23e7a12012-12-06 12:35:10 -05001170static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171{
1172 int err, i, z, gpr, nctl;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001173 int bit_shifter16;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174 const int playback = 10;
1175 const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
1176 const int stereo_mix = capture + 2;
1177 const int tmp = 0x88;
1178 u32 ptr;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001179 struct snd_emu10k1_fx8010_code *icode = NULL;
1180 struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181 u32 *gpr_map;
1182 mm_segment_t seg;
1183
Geyslan G. Bemf1b48632013-10-17 19:57:12 -03001184 err = -ENOMEM;
1185 icode = kzalloc(sizeof(*icode), GFP_KERNEL);
1186 if (!icode)
1187 return err;
1188
1189 icode->gpr_map = (u_int32_t __user *) kcalloc(512 + 256 + 256 + 2 * 1024,
1190 sizeof(u_int32_t), GFP_KERNEL);
1191 if (!icode->gpr_map)
1192 goto __err_gpr;
1193 controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
1194 sizeof(*controls), GFP_KERNEL);
1195 if (!controls)
1196 goto __err_ctrls;
1197
Clemens Ladisch4d233592005-09-05 10:35:20 +02001198 gpr_map = (u32 __force *)icode->gpr_map;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199
1200 icode->tram_data_map = icode->gpr_map + 512;
1201 icode->tram_addr_map = icode->tram_data_map + 256;
1202 icode->code = icode->tram_addr_map + 256;
1203
1204 /* clear free GPRs */
1205 for (i = 0; i < 512; i++)
1206 set_bit(i, icode->gpr_valid);
1207
1208 /* clear TRAM data & address lines */
1209 for (i = 0; i < 256; i++)
1210 set_bit(i, icode->tram_valid);
1211
1212 strcpy(icode->name, "Audigy DSP code for ALSA");
1213 ptr = 0;
1214 nctl = 0;
1215 gpr = stereo_mix + 10;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001216 gpr_map[gpr++] = 0x00007fff;
1217 gpr_map[gpr++] = 0x00008000;
1218 gpr_map[gpr++] = 0x0000ffff;
1219 bit_shifter16 = gpr;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220
1221 /* stop FX processor */
1222 snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
1223
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001224#if 1
Pavel Hofman13d45702007-06-11 12:21:20 +02001225 /* PCM front Playback Volume (independent from stereo mix)
1226 * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31)
1227 * where gpr contains attenuation from corresponding mixer control
1228 * (snd_emu10k1_init_stereo_control)
1229 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001230 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
1231 A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT));
1232 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100);
1233 gpr += 2;
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001234
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235 /* PCM Surround Playback (independent from stereo mix) */
1236 A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_REAR));
1237 A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_REAR));
1238 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Surround Playback Volume", gpr, 100);
1239 gpr += 2;
1240
1241 /* PCM Side Playback (independent from stereo mix) */
Lee Revell2b637da2005-03-30 13:51:18 +02001242 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001243 A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_SIDE));
1244 A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_SIDE));
1245 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Side Playback Volume", gpr, 100);
1246 gpr += 2;
1247 }
1248
1249 /* PCM Center Playback (independent from stereo mix) */
1250 A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_CENTER));
1251 snd_emu10k1_init_mono_control(&controls[nctl++], "PCM Center Playback Volume", gpr, 100);
1252 gpr++;
1253
1254 /* PCM LFE Playback (independent from stereo mix) */
1255 A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LFE));
1256 snd_emu10k1_init_mono_control(&controls[nctl++], "PCM LFE Playback Volume", gpr, 100);
1257 gpr++;
1258
1259 /*
1260 * Stereo Mix
1261 */
1262 /* Wave (PCM) Playback Volume (will be renamed later) */
1263 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
1264 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
1265 snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
1266 gpr += 2;
1267
1268 /* Synth Playback */
1269 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
1270 A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
1271 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100);
1272 gpr += 2;
1273
1274 /* Wave (PCM) Capture */
1275 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT));
1276 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT));
1277 snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0);
1278 gpr += 2;
1279
1280 /* Synth Capture */
1281 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
1282 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
1283 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0);
1284 gpr += 2;
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001285
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286 /*
1287 * inputs
1288 */
1289#define A_ADD_VOLUME_IN(var,vol,input) \
1290A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
1291
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001292 /* emu1212 DSP 0 and DSP 1 Capture */
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00001293 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001294 if (emu->card_capabilities->ca0108_chip) {
1295 /* Note:JCD:No longer bit shift lower 16bits to upper 16bits of 32bit value. */
1296 A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x0), A_C_00000001);
1297 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_GPR(tmp));
1298 A_OP(icode, &ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A3_EMU32IN(0x1), A_C_00000001);
1299 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr), A_GPR(tmp));
1300 } else {
1301 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0));
1302 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1));
1303 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001304 snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0);
1305 gpr += 2;
1306 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 /* AC'97 Playback Volume - used only for mic (renamed later) */
1308 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L);
1309 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R);
1310 snd_emu10k1_init_stereo_control(&controls[nctl++], "AMic Playback Volume", gpr, 0);
1311 gpr += 2;
1312 /* AC'97 Capture Volume - used only for mic */
1313 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AC97_L);
1314 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AC97_R);
1315 snd_emu10k1_init_stereo_control(&controls[nctl++], "Mic Capture Volume", gpr, 0);
1316 gpr += 2;
1317
1318 /* mic capture buffer */
1319 A_OP(icode, &ptr, iINTERP, A_EXTOUT(A_EXTOUT_MIC_CAP), A_EXTIN(A_EXTIN_AC97_L), 0xcd, A_EXTIN(A_EXTIN_AC97_R));
1320
1321 /* Audigy CD Playback Volume */
1322 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_SPDIF_CD_L);
1323 A_ADD_VOLUME_IN(stereo_mix+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 Playback Volume" : "CD Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326 gpr, 0);
1327 gpr += 2;
1328 /* Audigy CD Capture Volume */
1329 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_SPDIF_CD_L);
1330 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_SPDIF_CD_R);
1331 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001332 emu->card_capabilities->ac97_chip ? "Audigy CD Capture Volume" : "CD Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 gpr, 0);
1334 gpr += 2;
1335
1336 /* Optical SPDIF Playback Volume */
1337 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_OPT_SPDIF_L);
1338 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001339 snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001340 gpr += 2;
1341 /* Optical SPDIF Capture Volume */
1342 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_OPT_SPDIF_L);
1343 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_OPT_SPDIF_R);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001344 snd_emu10k1_init_stereo_control(&controls[nctl++], SNDRV_CTL_NAME_IEC958("Optical ",CAPTURE,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 gpr += 2;
1346
1347 /* Line2 Playback Volume */
1348 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_LINE2_L);
1349 A_ADD_VOLUME_IN(stereo_mix+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 Playback Volume" : "Line Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001352 gpr, 0);
1353 gpr += 2;
1354 /* Line2 Capture Volume */
1355 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_LINE2_L);
1356 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_LINE2_R);
1357 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001358 emu->card_capabilities->ac97_chip ? "Line2 Capture Volume" : "Line Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001359 gpr, 0);
1360 gpr += 2;
1361
1362 /* Philips ADC Playback Volume */
1363 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_ADC_L);
1364 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_ADC_R);
1365 snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Playback Volume", gpr, 0);
1366 gpr += 2;
1367 /* Philips ADC Capture Volume */
1368 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_ADC_L);
1369 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_ADC_R);
1370 snd_emu10k1_init_stereo_control(&controls[nctl++], "Analog Mix Capture Volume", gpr, 0);
1371 gpr += 2;
1372
1373 /* Aux2 Playback Volume */
1374 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AUX2_L);
1375 A_ADD_VOLUME_IN(stereo_mix+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 Playback Volume" : "Aux Playback Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001378 gpr, 0);
1379 gpr += 2;
1380 /* Aux2 Capture Volume */
1381 A_ADD_VOLUME_IN(capture, gpr, A_EXTIN_AUX2_L);
1382 A_ADD_VOLUME_IN(capture+1, gpr+1, A_EXTIN_AUX2_R);
1383 snd_emu10k1_init_stereo_control(&controls[nctl++],
Lee Revell2b637da2005-03-30 13:51:18 +02001384 emu->card_capabilities->ac97_chip ? "Aux2 Capture Volume" : "Aux Capture Volume",
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 gpr, 0);
1386 gpr += 2;
1387
1388 /* Stereo Mix Front Playback Volume */
1389 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_GPR(playback), A_GPR(gpr), A_GPR(stereo_mix));
1390 A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_GPR(playback+1), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1391 snd_emu10k1_init_stereo_control(&controls[nctl++], "Front Playback Volume", gpr, 100);
1392 gpr += 2;
1393
1394 /* Stereo Mix Surround Playback */
1395 A_OP(icode, &ptr, iMAC0, A_GPR(playback+2), A_GPR(playback+2), A_GPR(gpr), A_GPR(stereo_mix));
1396 A_OP(icode, &ptr, iMAC0, A_GPR(playback+3), A_GPR(playback+3), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1397 snd_emu10k1_init_stereo_control(&controls[nctl++], "Surround Playback Volume", gpr, 0);
1398 gpr += 2;
1399
1400 /* Stereo Mix Center Playback */
1401 /* Center = sub = Left/2 + Right/2 */
1402 A_OP(icode, &ptr, iINTERP, A_GPR(tmp), A_GPR(stereo_mix), 0xcd, A_GPR(stereo_mix+1));
1403 A_OP(icode, &ptr, iMAC0, A_GPR(playback+4), A_GPR(playback+4), A_GPR(gpr), A_GPR(tmp));
1404 snd_emu10k1_init_mono_control(&controls[nctl++], "Center Playback Volume", gpr, 0);
1405 gpr++;
1406
1407 /* Stereo Mix LFE Playback */
1408 A_OP(icode, &ptr, iMAC0, A_GPR(playback+5), A_GPR(playback+5), A_GPR(gpr), A_GPR(tmp));
1409 snd_emu10k1_init_mono_control(&controls[nctl++], "LFE Playback Volume", gpr, 0);
1410 gpr++;
1411
Lee Revell2b637da2005-03-30 13:51:18 +02001412 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 /* Stereo Mix Side Playback */
1414 A_OP(icode, &ptr, iMAC0, A_GPR(playback+6), A_GPR(playback+6), A_GPR(gpr), A_GPR(stereo_mix));
1415 A_OP(icode, &ptr, iMAC0, A_GPR(playback+7), A_GPR(playback+7), A_GPR(gpr+1), A_GPR(stereo_mix+1));
1416 snd_emu10k1_init_stereo_control(&controls[nctl++], "Side Playback Volume", gpr, 0);
1417 gpr += 2;
1418 }
1419
1420 /*
1421 * outputs
1422 */
1423#define A_PUT_OUTPUT(out,src) A_OP(icode, &ptr, iACC3, A_EXTOUT(out), A_C_00000000, A_C_00000000, A_GPR(src))
1424#define A_PUT_STEREO_OUTPUT(out1,out2,src) \
1425 {A_PUT_OUTPUT(out1,src); A_PUT_OUTPUT(out2,src+1);}
1426
1427#define _A_SWITCH(icode, ptr, dst, src, sw) \
1428 A_OP((icode), ptr, iMACINT0, dst, A_C_00000000, src, sw);
1429#define A_SWITCH(icode, ptr, dst, src, sw) \
1430 _A_SWITCH(icode, ptr, A_GPR(dst), A_GPR(src), A_GPR(sw))
1431#define _A_SWITCH_NEG(icode, ptr, dst, src) \
1432 A_OP((icode), ptr, iANDXOR, dst, src, A_C_00000001, A_C_00000001);
1433#define A_SWITCH_NEG(icode, ptr, dst, src) \
1434 _A_SWITCH_NEG(icode, ptr, A_GPR(dst), A_GPR(src))
1435
1436
1437 /*
1438 * Process tone control
1439 */
1440 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), A_GPR(playback + 0), A_C_00000000, A_C_00000000); /* left */
1441 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), A_GPR(playback + 1), A_C_00000000, A_C_00000000); /* right */
1442 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 */
1443 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 */
1444 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), A_GPR(playback + 4), A_C_00000000, A_C_00000000); /* center */
1445 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 +02001446 if (emu->card_capabilities->spk71) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001447 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 */
1448 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 */
1449 }
1450
1451
1452 ctl = &controls[nctl + 0];
1453 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1454 strcpy(ctl->id.name, "Tone Control - Bass");
1455 ctl->vcount = 2;
1456 ctl->count = 10;
1457 ctl->min = 0;
1458 ctl->max = 40;
1459 ctl->value[0] = ctl->value[1] = 20;
1460 ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
1461 ctl = &controls[nctl + 1];
1462 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
1463 strcpy(ctl->id.name, "Tone Control - Treble");
1464 ctl->vcount = 2;
1465 ctl->count = 10;
1466 ctl->min = 0;
1467 ctl->max = 40;
1468 ctl->value[0] = ctl->value[1] = 20;
1469 ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
1470
1471#define BASS_GPR 0x8c
1472#define TREBLE_GPR 0x96
1473
1474 for (z = 0; z < 5; z++) {
1475 int j;
1476 for (j = 0; j < 2; j++) {
1477 controls[nctl + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j;
1478 controls[nctl + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
1479 }
1480 }
1481 for (z = 0; z < 4; z++) { /* front/rear/center-lfe/side */
1482 int j, k, l, d;
1483 for (j = 0; j < 2; j++) { /* left/right */
1484 k = 0xb0 + (z * 8) + (j * 4);
1485 l = 0xe0 + (z * 8) + (j * 4);
1486 d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j;
1487
1488 A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(d), A_GPR(BASS_GPR + 0 + j));
1489 A_OP(icode, &ptr, iMACMV, A_GPR(k+1), A_GPR(k), A_GPR(k+1), A_GPR(BASS_GPR + 4 + j));
1490 A_OP(icode, &ptr, iMACMV, A_GPR(k), A_GPR(d), A_GPR(k), A_GPR(BASS_GPR + 2 + j));
1491 A_OP(icode, &ptr, iMACMV, A_GPR(k+3), A_GPR(k+2), A_GPR(k+3), A_GPR(BASS_GPR + 8 + j));
1492 A_OP(icode, &ptr, iMAC0, A_GPR(k+2), A_GPR_ACCU, A_GPR(k+2), A_GPR(BASS_GPR + 6 + j));
1493 A_OP(icode, &ptr, iACC3, A_GPR(k+2), A_GPR(k+2), A_GPR(k+2), A_C_00000000);
1494
1495 A_OP(icode, &ptr, iMAC0, A_C_00000000, A_C_00000000, A_GPR(k+2), A_GPR(TREBLE_GPR + 0 + j));
1496 A_OP(icode, &ptr, iMACMV, A_GPR(l+1), A_GPR(l), A_GPR(l+1), A_GPR(TREBLE_GPR + 4 + j));
1497 A_OP(icode, &ptr, iMACMV, A_GPR(l), A_GPR(k+2), A_GPR(l), A_GPR(TREBLE_GPR + 2 + j));
1498 A_OP(icode, &ptr, iMACMV, A_GPR(l+3), A_GPR(l+2), A_GPR(l+3), A_GPR(TREBLE_GPR + 8 + j));
1499 A_OP(icode, &ptr, iMAC0, A_GPR(l+2), A_GPR_ACCU, A_GPR(l+2), A_GPR(TREBLE_GPR + 6 + j));
1500 A_OP(icode, &ptr, iMACINT0, A_GPR(l+2), A_C_00000000, A_GPR(l+2), A_C_00000010);
1501
1502 A_OP(icode, &ptr, iACC3, A_GPR(d), A_GPR(l+2), A_C_00000000, A_C_00000000);
1503
1504 if (z == 2) /* center */
1505 break;
1506 }
1507 }
1508 nctl += 2;
1509
1510#undef BASS_GPR
1511#undef TREBLE_GPR
1512
1513 for (z = 0; z < 8; z++) {
1514 A_SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
1515 A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
1516 A_SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
1517 A_OP(icode, &ptr, iACC3, A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1518 }
1519 snd_emu10k1_init_stereo_onoff_control(controls + nctl++, "Tone Control - Switch", gpr, 0);
1520 gpr += 2;
1521
1522 /* Master volume (will be renamed later) */
1523 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));
1524 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));
1525 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));
1526 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));
1527 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));
1528 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));
1529 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));
1530 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));
1531 snd_emu10k1_init_mono_control(&controls[nctl++], "Wave Master Playback Volume", gpr, 0);
1532 gpr += 2;
1533
1534 /* analog speakers */
1535 A_PUT_STEREO_OUTPUT(A_EXTOUT_AFRONT_L, A_EXTOUT_AFRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1536 A_PUT_STEREO_OUTPUT(A_EXTOUT_AREAR_L, A_EXTOUT_AREAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
1537 A_PUT_OUTPUT(A_EXTOUT_ACENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
1538 A_PUT_OUTPUT(A_EXTOUT_ALFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
Lee Revell2b637da2005-03-30 13:51:18 +02001539 if (emu->card_capabilities->spk71)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540 A_PUT_STEREO_OUTPUT(A_EXTOUT_ASIDE_L, A_EXTOUT_ASIDE_R, playback+6 + SND_EMU10K1_PLAYBACK_CHANNELS);
1541
1542 /* headphone */
1543 A_PUT_STEREO_OUTPUT(A_EXTOUT_HEADPHONE_L, A_EXTOUT_HEADPHONE_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1544
1545 /* digital outputs */
1546 /* 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 +00001547 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001548 /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */
Takashi Iwai6f002b02014-02-25 17:02:09 +01001549 dev_info(emu->card->dev, "EMU outputs on\n");
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001550 for (z = 0; z < 8; z++) {
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001551 if (emu->card_capabilities->ca0108_chip) {
1552 A_OP(icode, &ptr, iACC3, A3_EMU32OUT(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
1553 } else {
1554 A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
1555 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001556 }
1557 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
1559 /* IEC958 Optical Raw Playback Switch */
1560 gpr_map[gpr++] = 0;
1561 gpr_map[gpr++] = 0x1008;
1562 gpr_map[gpr++] = 0xffff0000;
1563 for (z = 0; z < 2; z++) {
1564 A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000);
1565 A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001);
1566 A_OP(icode, &ptr, iACC3, A_GPR(tmp + 2), A_C_00000000, A_C_00010000, A_GPR(tmp + 2));
1567 A_OP(icode, &ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_GPR(gpr - 1), A_C_00000000);
1568 A_SWITCH(icode, &ptr, tmp + 0, tmp + 2, gpr + z);
1569 A_SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
1570 A_SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
1571 if ((z==1) && (emu->card_capabilities->spdif_bug)) {
1572 /* Due to a SPDIF output bug on some Audigy cards, this code delays the Right channel by 1 sample */
Takashi Iwai6f002b02014-02-25 17:02:09 +01001573 dev_info(emu->card->dev,
1574 "Installing spdif_bug patch: %s\n",
1575 emu->card_capabilities->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001576 A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(gpr - 3), A_C_00000000, A_C_00000000);
1577 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 3), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1578 } else {
1579 A_OP(icode, &ptr, iACC3, A_EXTOUT(A_EXTOUT_FRONT_L + z), A_GPR(tmp + 0), A_GPR(tmp + 1), A_C_00000000);
1580 }
1581 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02001582 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 -07001583 gpr += 2;
1584
1585 A_PUT_STEREO_OUTPUT(A_EXTOUT_REAR_L, A_EXTOUT_REAR_R, playback+2 + SND_EMU10K1_PLAYBACK_CHANNELS);
1586 A_PUT_OUTPUT(A_EXTOUT_CENTER, playback+4 + SND_EMU10K1_PLAYBACK_CHANNELS);
1587 A_PUT_OUTPUT(A_EXTOUT_LFE, playback+5 + SND_EMU10K1_PLAYBACK_CHANNELS);
1588
1589 /* ADC buffer */
1590#ifdef EMU10K1_CAPTURE_DIGITAL_OUT
1591 A_PUT_STEREO_OUTPUT(A_EXTOUT_ADC_CAP_L, A_EXTOUT_ADC_CAP_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS);
1592#else
1593 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_L, capture);
1594 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
1595#endif
1596
James Courtier-Dutton190d2c42007-11-04 14:08:26 +00001597 if (emu->card_capabilities->emu_model) {
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001598 if (emu->card_capabilities->ca0108_chip) {
Takashi Iwai6f002b02014-02-25 17:02:09 +01001599 dev_info(emu->card->dev, "EMU2 inputs on\n");
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001600 for (z = 0; z < 0x10; z++) {
1601 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp,
1602 bit_shifter16,
1603 A3_EMU32IN(z),
1604 A_FXBUS2(z*2) );
1605 }
1606 } else {
Takashi Iwai6f002b02014-02-25 17:02:09 +01001607 dev_info(emu->card->dev, "EMU inputs on\n");
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001608 /* Capture 16 (originally 8) channels of S32_LE sound */
1609
Takashi Iwai28a97c12009-02-05 16:08:14 +01001610 /*
Takashi Iwai6f002b02014-02-25 17:02:09 +01001611 dev_dbg(emu->card->dev, "emufx.c: gpr=0x%x, tmp=0x%x\n",
Takashi Iwai28a97c12009-02-05 16:08:14 +01001612 gpr, tmp);
1613 */
James Courtier-Dutton90fd5ce2007-07-23 14:01:46 +01001614 /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
1615 /* A_P16VIN(0) is delayed by one sample,
1616 * so all other A_P16VIN channels will need to also be delayed
1617 */
1618 /* Left ADC in. 1 of 2 */
1619 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
1620 /* Right ADC in 1 of 2 */
1621 gpr_map[gpr++] = 0x00000000;
1622 /* Delaying by one sample: instead of copying the input
1623 * value A_P16VIN to output A_FXBUS2 as in the first channel,
1624 * we use an auxiliary register, delaying the value by one
1625 * sample
1626 */
1627 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
1628 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
1629 gpr_map[gpr++] = 0x00000000;
1630 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) );
1631 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000);
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(6) );
1634 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
1635 /* For 96kHz mode */
1636 /* Left ADC in. 2 of 2 */
1637 gpr_map[gpr++] = 0x00000000;
1638 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
1639 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
1640 /* Right ADC in 2 of 2 */
1641 gpr_map[gpr++] = 0x00000000;
1642 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
1643 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000);
1644 gpr_map[gpr++] = 0x00000000;
1645 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) );
1646 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000);
1647 gpr_map[gpr++] = 0x00000000;
1648 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
1649 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
1650 /* Pavel Hofman - we still have voices, A_FXBUS2s, and
1651 * A_P16VINs available -
1652 * let's add 8 more capture channels - total of 16
1653 */
1654 gpr_map[gpr++] = 0x00000000;
1655 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1656 bit_shifter16,
1657 A_GPR(gpr - 1),
1658 A_FXBUS2(0x10));
1659 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8),
1660 A_C_00000000, A_C_00000000);
1661 gpr_map[gpr++] = 0x00000000;
1662 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1663 bit_shifter16,
1664 A_GPR(gpr - 1),
1665 A_FXBUS2(0x12));
1666 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9),
1667 A_C_00000000, A_C_00000000);
1668 gpr_map[gpr++] = 0x00000000;
1669 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1670 bit_shifter16,
1671 A_GPR(gpr - 1),
1672 A_FXBUS2(0x14));
1673 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa),
1674 A_C_00000000, A_C_00000000);
1675 gpr_map[gpr++] = 0x00000000;
1676 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1677 bit_shifter16,
1678 A_GPR(gpr - 1),
1679 A_FXBUS2(0x16));
1680 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb),
1681 A_C_00000000, A_C_00000000);
1682 gpr_map[gpr++] = 0x00000000;
1683 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1684 bit_shifter16,
1685 A_GPR(gpr - 1),
1686 A_FXBUS2(0x18));
1687 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc),
1688 A_C_00000000, A_C_00000000);
1689 gpr_map[gpr++] = 0x00000000;
1690 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1691 bit_shifter16,
1692 A_GPR(gpr - 1),
1693 A_FXBUS2(0x1a));
1694 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd),
1695 A_C_00000000, A_C_00000000);
1696 gpr_map[gpr++] = 0x00000000;
1697 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1698 bit_shifter16,
1699 A_GPR(gpr - 1),
1700 A_FXBUS2(0x1c));
1701 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe),
1702 A_C_00000000, A_C_00000000);
1703 gpr_map[gpr++] = 0x00000000;
1704 snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp,
1705 bit_shifter16,
1706 A_GPR(gpr - 1),
1707 A_FXBUS2(0x1e));
1708 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf),
1709 A_C_00000000, A_C_00000000);
1710 }
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01001711
1712#if 0
1713 for (z = 4; z < 8; z++) {
1714 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
1715 }
1716 for (z = 0xc; z < 0x10; z++) {
1717 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
1718 }
1719#endif
1720 } else {
1721 /* EFX capture - capture the 16 EXTINs */
1722 /* Capture 16 channels of S16_LE sound */
1723 for (z = 0; z < 16; z++) {
1724 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
1725 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001726 }
1727
James Courtier-Dutton19b99fb2005-12-04 18:03:03 +01001728#endif /* JCD test */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 /*
1730 * ok, set up done..
1731 */
1732
1733 if (gpr > tmp) {
1734 snd_BUG();
1735 err = -EIO;
1736 goto __err;
1737 }
1738 /* clear remaining instruction memory */
1739 while (ptr < 0x400)
1740 A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0);
1741
1742 seg = snd_enter_user();
1743 icode->gpr_add_control_count = nctl;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001744 icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01001745 emu->support_tlv = 1; /* support TLV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001746 err = snd_emu10k1_icode_poke(emu, icode);
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01001747 emu->support_tlv = 0; /* clear again */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001748 snd_leave_user(seg);
1749
Geyslan G. Bemf1b48632013-10-17 19:57:12 -03001750__err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001751 kfree(controls);
Geyslan G. Bemf1b48632013-10-17 19:57:12 -03001752__err_ctrls:
1753 kfree((void __force *)icode->gpr_map);
1754__err_gpr:
1755 kfree(icode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001756 return err;
1757}
1758
1759
1760/*
1761 * initial DSP configuration for Emu10k1
1762 */
1763
1764/* when volume = max, then copy only to avoid volume modification */
1765/* with iMAC0 (negative values) */
Bill Pembertone23e7a12012-12-06 12:35:10 -05001766static void _volume(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001767{
1768 OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
1769 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1770 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000001);
1771 OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
1772}
Bill Pembertone23e7a12012-12-06 12:35:10 -05001773static void _volume_add(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001774{
1775 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1776 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1777 OP(icode, ptr, iMACINT0, dst, dst, src, C_00000001);
1778 OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
1779 OP(icode, ptr, iMAC0, dst, dst, src, vol);
1780}
Bill Pembertone23e7a12012-12-06 12:35:10 -05001781static void _volume_out(struct snd_emu10k1_fx8010_code *icode, u32 *ptr, u32 dst, u32 src, u32 vol)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782{
1783 OP(icode, ptr, iANDXOR, C_00000000, vol, C_ffffffff, C_7fffffff);
1784 OP(icode, ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1785 OP(icode, ptr, iACC3, dst, src, C_00000000, C_00000000);
1786 OP(icode, ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000001);
1787 OP(icode, ptr, iMAC0, dst, C_00000000, src, vol);
1788}
1789
1790#define VOLUME(icode, ptr, dst, src, vol) \
1791 _volume(icode, ptr, GPR(dst), GPR(src), GPR(vol))
1792#define VOLUME_IN(icode, ptr, dst, src, vol) \
1793 _volume(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))
1794#define VOLUME_ADD(icode, ptr, dst, src, vol) \
1795 _volume_add(icode, ptr, GPR(dst), GPR(src), GPR(vol))
1796#define VOLUME_ADDIN(icode, ptr, dst, src, vol) \
1797 _volume_add(icode, ptr, GPR(dst), EXTIN(src), GPR(vol))
1798#define VOLUME_OUT(icode, ptr, dst, src, vol) \
1799 _volume_out(icode, ptr, EXTOUT(dst), GPR(src), GPR(vol))
1800#define _SWITCH(icode, ptr, dst, src, sw) \
1801 OP((icode), ptr, iMACINT0, dst, C_00000000, src, sw);
1802#define SWITCH(icode, ptr, dst, src, sw) \
1803 _SWITCH(icode, ptr, GPR(dst), GPR(src), GPR(sw))
1804#define SWITCH_IN(icode, ptr, dst, src, sw) \
1805 _SWITCH(icode, ptr, GPR(dst), EXTIN(src), GPR(sw))
1806#define _SWITCH_NEG(icode, ptr, dst, src) \
1807 OP((icode), ptr, iANDXOR, dst, src, C_00000001, C_00000001);
1808#define SWITCH_NEG(icode, ptr, dst, src) \
1809 _SWITCH_NEG(icode, ptr, GPR(dst), GPR(src))
1810
1811
Bill Pembertone23e7a12012-12-06 12:35:10 -05001812static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001813{
1814 int err, i, z, gpr, tmp, playback, capture;
1815 u32 ptr;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01001816 struct snd_emu10k1_fx8010_code *icode;
1817 struct snd_emu10k1_fx8010_pcm_rec *ipcm = NULL;
1818 struct snd_emu10k1_fx8010_control_gpr *controls = NULL, *ctl;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819 u32 *gpr_map;
1820 mm_segment_t seg;
1821
Geyslan G. Bemf1b48632013-10-17 19:57:12 -03001822 err = -ENOMEM;
1823 icode = kzalloc(sizeof(*icode), GFP_KERNEL);
1824 if (!icode)
1825 return err;
1826
1827 icode->gpr_map = (u_int32_t __user *) kcalloc(256 + 160 + 160 + 2 * 512,
1828 sizeof(u_int32_t), GFP_KERNEL);
1829 if (!icode->gpr_map)
1830 goto __err_gpr;
1831
1832 controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
1833 sizeof(struct snd_emu10k1_fx8010_control_gpr),
1834 GFP_KERNEL);
1835 if (!controls)
1836 goto __err_ctrls;
1837
1838 ipcm = kzalloc(sizeof(*ipcm), GFP_KERNEL);
1839 if (!ipcm)
1840 goto __err_ipcm;
1841
Clemens Ladisch4d233592005-09-05 10:35:20 +02001842 gpr_map = (u32 __force *)icode->gpr_map;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001843
1844 icode->tram_data_map = icode->gpr_map + 256;
1845 icode->tram_addr_map = icode->tram_data_map + 160;
1846 icode->code = icode->tram_addr_map + 160;
1847
1848 /* clear free GPRs */
1849 for (i = 0; i < 256; i++)
1850 set_bit(i, icode->gpr_valid);
1851
1852 /* clear TRAM data & address lines */
1853 for (i = 0; i < 160; i++)
1854 set_bit(i, icode->tram_valid);
1855
1856 strcpy(icode->name, "SB Live! FX8010 code for ALSA v1.2 by Jaroslav Kysela");
1857 ptr = 0; i = 0;
Mikael Magnussonedf8e452005-09-13 11:32:58 +02001858 /* we have 12 inputs */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001859 playback = SND_EMU10K1_INPUTS;
1860 /* we have 6 playback channels and tone control doubles */
1861 capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2);
1862 gpr = capture + SND_EMU10K1_CAPTURE_CHANNELS;
1863 tmp = 0x88; /* we need 4 temporary GPR */
1864 /* from 0x8c to 0xff is the area for tone control */
1865
1866 /* stop FX processor */
1867 snd_emu10k1_ptr_write(emu, DBG, 0, (emu->fx8010.dbg = 0) | EMU10K1_DBG_SINGLE_STEP);
1868
1869 /*
1870 * Process FX Buses
1871 */
1872 OP(icode, &ptr, iMACINT0, GPR(0), C_00000000, FXBUS(FXBUS_PCM_LEFT), C_00000004);
1873 OP(icode, &ptr, iMACINT0, GPR(1), C_00000000, FXBUS(FXBUS_PCM_RIGHT), C_00000004);
1874 OP(icode, &ptr, iMACINT0, GPR(2), C_00000000, FXBUS(FXBUS_MIDI_LEFT), C_00000004);
1875 OP(icode, &ptr, iMACINT0, GPR(3), C_00000000, FXBUS(FXBUS_MIDI_RIGHT), C_00000004);
1876 OP(icode, &ptr, iMACINT0, GPR(4), C_00000000, FXBUS(FXBUS_PCM_LEFT_REAR), C_00000004);
1877 OP(icode, &ptr, iMACINT0, GPR(5), C_00000000, FXBUS(FXBUS_PCM_RIGHT_REAR), C_00000004);
1878 OP(icode, &ptr, iMACINT0, GPR(6), C_00000000, FXBUS(FXBUS_PCM_CENTER), C_00000004);
1879 OP(icode, &ptr, iMACINT0, GPR(7), C_00000000, FXBUS(FXBUS_PCM_LFE), C_00000004);
1880 OP(icode, &ptr, iMACINT0, GPR(8), C_00000000, C_00000000, C_00000000); /* S/PDIF left */
1881 OP(icode, &ptr, iMACINT0, GPR(9), C_00000000, C_00000000, C_00000000); /* S/PDIF right */
Mikael Magnussonedf8e452005-09-13 11:32:58 +02001882 OP(icode, &ptr, iMACINT0, GPR(10), C_00000000, FXBUS(FXBUS_PCM_LEFT_FRONT), C_00000004);
1883 OP(icode, &ptr, iMACINT0, GPR(11), C_00000000, FXBUS(FXBUS_PCM_RIGHT_FRONT), C_00000004);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001884
1885 /* Raw S/PDIF PCM */
1886 ipcm->substream = 0;
1887 ipcm->channels = 2;
1888 ipcm->tram_start = 0;
1889 ipcm->buffer_size = (64 * 1024) / 2;
1890 ipcm->gpr_size = gpr++;
1891 ipcm->gpr_ptr = gpr++;
1892 ipcm->gpr_count = gpr++;
1893 ipcm->gpr_tmpcount = gpr++;
1894 ipcm->gpr_trigger = gpr++;
1895 ipcm->gpr_running = gpr++;
1896 ipcm->etram[0] = 0;
1897 ipcm->etram[1] = 1;
1898
1899 gpr_map[gpr + 0] = 0xfffff000;
1900 gpr_map[gpr + 1] = 0xffff0000;
1901 gpr_map[gpr + 2] = 0x70000000;
1902 gpr_map[gpr + 3] = 0x00000007;
1903 gpr_map[gpr + 4] = 0x001f << 11;
1904 gpr_map[gpr + 5] = 0x001c << 11;
1905 gpr_map[gpr + 6] = (0x22 - 0x01) - 1; /* skip at 01 to 22 */
1906 gpr_map[gpr + 7] = (0x22 - 0x06) - 1; /* skip at 06 to 22 */
1907 gpr_map[gpr + 8] = 0x2000000 + (2<<11);
1908 gpr_map[gpr + 9] = 0x4000000 + (2<<11);
1909 gpr_map[gpr + 10] = 1<<11;
1910 gpr_map[gpr + 11] = (0x24 - 0x0a) - 1; /* skip at 0a to 24 */
1911 gpr_map[gpr + 12] = 0;
1912
1913 /* if the trigger flag is not set, skip */
1914 /* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000);
1915 /* 01: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_ZERO, GPR(gpr + 6));
1916 /* if the running flag is set, we're running */
1917 /* 02: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_running), C_00000000, C_00000000);
1918 /* 03: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000004);
1919 /* wait until ((GPR_DBAC>>11) & 0x1f) == 0x1c) */
1920 /* 04: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), GPR_DBAC, GPR(gpr + 4), C_00000000);
1921 /* 05: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(gpr + 5));
1922 /* 06: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 7));
1923 /* 07: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000010, C_00000001, C_00000000);
1924
1925 /* 08: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000000, C_00000001);
1926 /* 09: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), GPR(gpr + 12), C_ffffffff, C_00000000);
1927 /* 0a: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, GPR(gpr + 11));
1928 /* 0b: */ OP(icode, &ptr, iACC3, GPR(gpr + 12), C_00000001, C_00000000, C_00000000);
1929
1930 /* 0c: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[0]), GPR(gpr + 0), C_00000000);
1931 /* 0d: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000);
1932 /* 0e: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2));
1933 /* 0f: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001);
1934 /* 10: */ OP(icode, &ptr, iANDXOR, GPR(8), GPR(8), GPR(gpr + 1), GPR(gpr + 2));
1935
1936 /* 11: */ OP(icode, &ptr, iANDXOR, GPR(tmp + 0), ETRAM_DATA(ipcm->etram[1]), GPR(gpr + 0), C_00000000);
1937 /* 12: */ OP(icode, &ptr, iLOG, GPR(tmp + 0), GPR(tmp + 0), GPR(gpr + 3), C_00000000);
1938 /* 13: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(tmp + 0), GPR(gpr + 1), GPR(gpr + 2));
1939 /* 14: */ OP(icode, &ptr, iSKIP, C_00000000, GPR_COND, CC_REG_MINUS, C_00000001);
1940 /* 15: */ OP(icode, &ptr, iANDXOR, GPR(9), GPR(9), GPR(gpr + 1), GPR(gpr + 2));
1941
1942 /* 16: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(ipcm->gpr_ptr), C_00000001, C_00000000);
1943 /* 17: */ OP(icode, &ptr, iMACINT0, C_00000000, GPR(tmp + 0), C_ffffffff, GPR(ipcm->gpr_size));
1944 /* 18: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_MINUS, C_00000001);
1945 /* 19: */ OP(icode, &ptr, iACC3, GPR(tmp + 0), C_00000000, C_00000000, C_00000000);
1946 /* 1a: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_ptr), GPR(tmp + 0), C_00000000, C_00000000);
1947
1948 /* 1b: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_tmpcount), C_ffffffff, C_00000000);
1949 /* 1c: */ OP(icode, &ptr, iSKIP, GPR_COND, GPR_COND, CC_REG_NONZERO, C_00000002);
1950 /* 1d: */ OP(icode, &ptr, iACC3, GPR(ipcm->gpr_tmpcount), GPR(ipcm->gpr_count), C_00000000, C_00000000);
1951 /* 1e: */ OP(icode, &ptr, iACC3, GPR_IRQ, C_80000000, C_00000000, C_00000000);
1952 /* 1f: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00000001, C_00010000);
1953
1954 /* 20: */ OP(icode, &ptr, iANDXOR, GPR(ipcm->gpr_running), GPR(ipcm->gpr_running), C_00010000, C_00000001);
1955 /* 21: */ OP(icode, &ptr, iSKIP, C_00000000, C_7fffffff, C_7fffffff, C_00000002);
1956
1957 /* 22: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[0]), GPR(gpr + 8), GPR_DBAC, C_ffffffff);
1958 /* 23: */ OP(icode, &ptr, iMACINT1, ETRAM_ADDR(ipcm->etram[1]), GPR(gpr + 9), GPR_DBAC, C_ffffffff);
1959
1960 /* 24: */
1961 gpr += 13;
1962
1963 /* Wave Playback Volume */
1964 for (z = 0; z < 2; z++)
1965 VOLUME(icode, &ptr, playback + z, z, gpr + z);
1966 snd_emu10k1_init_stereo_control(controls + i++, "Wave Playback Volume", gpr, 100);
1967 gpr += 2;
1968
1969 /* Wave Surround Playback Volume */
1970 for (z = 0; z < 2; z++)
1971 VOLUME(icode, &ptr, playback + 2 + z, z, gpr + z);
1972 snd_emu10k1_init_stereo_control(controls + i++, "Wave Surround Playback Volume", gpr, 0);
1973 gpr += 2;
1974
1975 /* Wave Center/LFE Playback Volume */
1976 OP(icode, &ptr, iACC3, GPR(tmp + 0), FXBUS(FXBUS_PCM_LEFT), FXBUS(FXBUS_PCM_RIGHT), C_00000000);
1977 OP(icode, &ptr, iMACINT0, GPR(tmp + 0), C_00000000, GPR(tmp + 0), C_00000002);
1978 VOLUME(icode, &ptr, playback + 4, tmp + 0, gpr);
1979 snd_emu10k1_init_mono_control(controls + i++, "Wave Center Playback Volume", gpr++, 0);
1980 VOLUME(icode, &ptr, playback + 5, tmp + 0, gpr);
1981 snd_emu10k1_init_mono_control(controls + i++, "Wave LFE Playback Volume", gpr++, 0);
1982
1983 /* Wave Capture Volume + Switch */
1984 for (z = 0; z < 2; z++) {
1985 SWITCH(icode, &ptr, tmp + 0, z, gpr + 2 + z);
1986 VOLUME(icode, &ptr, capture + z, tmp + 0, gpr + z);
1987 }
1988 snd_emu10k1_init_stereo_control(controls + i++, "Wave Capture Volume", gpr, 0);
1989 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0);
1990 gpr += 4;
1991
1992 /* Synth Playback Volume */
1993 for (z = 0; z < 2; z++)
1994 VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z);
1995 snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100);
1996 gpr += 2;
1997
1998 /* Synth Capture Volume + Switch */
1999 for (z = 0; z < 2; z++) {
2000 SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z);
2001 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2002 }
2003 snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0);
2004 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0);
2005 gpr += 4;
2006
2007 /* Surround Digital Playback Volume (renamed later without Digital) */
2008 for (z = 0; z < 2; z++)
2009 VOLUME_ADD(icode, &ptr, playback + 2 + z, 4 + z, gpr + z);
2010 snd_emu10k1_init_stereo_control(controls + i++, "Surround Digital Playback Volume", gpr, 100);
2011 gpr += 2;
2012
2013 /* Surround Capture Volume + Switch */
2014 for (z = 0; z < 2; z++) {
2015 SWITCH(icode, &ptr, tmp + 0, 4 + z, gpr + 2 + z);
2016 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2017 }
2018 snd_emu10k1_init_stereo_control(controls + i++, "Surround Capture Volume", gpr, 0);
2019 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Surround Capture Switch", gpr + 2, 0);
2020 gpr += 4;
2021
2022 /* Center Playback Volume (renamed later without Digital) */
2023 VOLUME_ADD(icode, &ptr, playback + 4, 6, gpr);
2024 snd_emu10k1_init_mono_control(controls + i++, "Center Digital Playback Volume", gpr++, 100);
2025
2026 /* LFE Playback Volume + Switch (renamed later without Digital) */
2027 VOLUME_ADD(icode, &ptr, playback + 5, 7, gpr);
2028 snd_emu10k1_init_mono_control(controls + i++, "LFE Digital Playback Volume", gpr++, 100);
2029
Mikael Magnussonedf8e452005-09-13 11:32:58 +02002030 /* Front Playback Volume */
2031 for (z = 0; z < 2; z++)
2032 VOLUME_ADD(icode, &ptr, playback + z, 10 + z, gpr + z);
2033 snd_emu10k1_init_stereo_control(controls + i++, "Front Playback Volume", gpr, 100);
2034 gpr += 2;
2035
2036 /* Front Capture Volume + Switch */
2037 for (z = 0; z < 2; z++) {
2038 SWITCH(icode, &ptr, tmp + 0, 10 + z, gpr + 2);
2039 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2040 }
2041 snd_emu10k1_init_stereo_control(controls + i++, "Front Capture Volume", gpr, 0);
2042 snd_emu10k1_init_mono_onoff_control(controls + i++, "Front Capture Switch", gpr + 2, 0);
2043 gpr += 3;
2044
Linus Torvalds1da177e2005-04-16 15:20:36 -07002045 /*
2046 * Process inputs
2047 */
2048
2049 if (emu->fx8010.extin_mask & ((1<<EXTIN_AC97_L)|(1<<EXTIN_AC97_R))) {
2050 /* AC'97 Playback Volume */
2051 VOLUME_ADDIN(icode, &ptr, playback + 0, EXTIN_AC97_L, gpr); gpr++;
2052 VOLUME_ADDIN(icode, &ptr, playback + 1, EXTIN_AC97_R, gpr); gpr++;
2053 snd_emu10k1_init_stereo_control(controls + i++, "AC97 Playback Volume", gpr-2, 0);
2054 /* AC'97 Capture Volume */
2055 VOLUME_ADDIN(icode, &ptr, capture + 0, EXTIN_AC97_L, gpr); gpr++;
2056 VOLUME_ADDIN(icode, &ptr, capture + 1, EXTIN_AC97_R, gpr); gpr++;
2057 snd_emu10k1_init_stereo_control(controls + i++, "AC97 Capture Volume", gpr-2, 100);
2058 }
2059
2060 if (emu->fx8010.extin_mask & ((1<<EXTIN_SPDIF_CD_L)|(1<<EXTIN_SPDIF_CD_R))) {
2061 /* IEC958 TTL Playback Volume */
2062 for (z = 0; z < 2; z++)
2063 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_SPDIF_CD_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002064 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065 gpr += 2;
2066
2067 /* IEC958 TTL Capture Volume + Switch */
2068 for (z = 0; z < 2; z++) {
2069 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_SPDIF_CD_L + z, gpr + 2 + z);
2070 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2071 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002072 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("TTL ",CAPTURE,VOLUME), gpr, 0);
2073 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 -07002074 gpr += 4;
2075 }
2076
2077 if (emu->fx8010.extin_mask & ((1<<EXTIN_ZOOM_L)|(1<<EXTIN_ZOOM_R))) {
2078 /* Zoom Video Playback Volume */
2079 for (z = 0; z < 2; z++)
2080 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_ZOOM_L + z, gpr + z);
2081 snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Playback Volume", gpr, 0);
2082 gpr += 2;
2083
2084 /* Zoom Video Capture Volume + Switch */
2085 for (z = 0; z < 2; z++) {
2086 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_ZOOM_L + z, gpr + 2 + z);
2087 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2088 }
2089 snd_emu10k1_init_stereo_control(controls + i++, "Zoom Video Capture Volume", gpr, 0);
2090 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Zoom Video Capture Switch", gpr + 2, 0);
2091 gpr += 4;
2092 }
2093
2094 if (emu->fx8010.extin_mask & ((1<<EXTIN_TOSLINK_L)|(1<<EXTIN_TOSLINK_R))) {
2095 /* IEC958 Optical Playback Volume */
2096 for (z = 0; z < 2; z++)
2097 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_TOSLINK_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002098 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002099 gpr += 2;
2100
2101 /* IEC958 Optical Capture Volume */
2102 for (z = 0; z < 2; z++) {
2103 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_TOSLINK_L + z, gpr + 2 + z);
2104 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2105 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002106 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("LiveDrive ",CAPTURE,VOLUME), gpr, 0);
2107 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 -07002108 gpr += 4;
2109 }
2110
2111 if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE1_L)|(1<<EXTIN_LINE1_R))) {
2112 /* Line LiveDrive Playback Volume */
2113 for (z = 0; z < 2; z++)
2114 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE1_L + z, gpr + z);
2115 snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Playback Volume", gpr, 0);
2116 gpr += 2;
2117
2118 /* Line LiveDrive Capture Volume + Switch */
2119 for (z = 0; z < 2; z++) {
2120 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE1_L + z, gpr + 2 + z);
2121 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2122 }
2123 snd_emu10k1_init_stereo_control(controls + i++, "Line LiveDrive Capture Volume", gpr, 0);
2124 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line LiveDrive Capture Switch", gpr + 2, 0);
2125 gpr += 4;
2126 }
2127
2128 if (emu->fx8010.extin_mask & ((1<<EXTIN_COAX_SPDIF_L)|(1<<EXTIN_COAX_SPDIF_R))) {
2129 /* IEC958 Coax Playback Volume */
2130 for (z = 0; z < 2; z++)
2131 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_COAX_SPDIF_L + z, gpr + z);
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002132 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",PLAYBACK,VOLUME), gpr, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 gpr += 2;
2134
2135 /* IEC958 Coax Capture Volume + Switch */
2136 for (z = 0; z < 2; z++) {
2137 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_COAX_SPDIF_L + z, gpr + 2 + z);
2138 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2139 }
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002140 snd_emu10k1_init_stereo_control(controls + i++, SNDRV_CTL_NAME_IEC958("Coaxial ",CAPTURE,VOLUME), gpr, 0);
2141 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 -07002142 gpr += 4;
2143 }
2144
2145 if (emu->fx8010.extin_mask & ((1<<EXTIN_LINE2_L)|(1<<EXTIN_LINE2_R))) {
2146 /* Line LiveDrive Playback Volume */
2147 for (z = 0; z < 2; z++)
2148 VOLUME_ADDIN(icode, &ptr, playback + z, EXTIN_LINE2_L + z, gpr + z);
2149 snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Playback Volume", gpr, 0);
2150 controls[i-1].id.index = 1;
2151 gpr += 2;
2152
2153 /* Line LiveDrive Capture Volume */
2154 for (z = 0; z < 2; z++) {
2155 SWITCH_IN(icode, &ptr, tmp + 0, EXTIN_LINE2_L + z, gpr + 2 + z);
2156 VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
2157 }
2158 snd_emu10k1_init_stereo_control(controls + i++, "Line2 LiveDrive Capture Volume", gpr, 0);
2159 controls[i-1].id.index = 1;
2160 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Line2 LiveDrive Capture Switch", gpr + 2, 0);
2161 controls[i-1].id.index = 1;
2162 gpr += 4;
2163 }
2164
2165 /*
2166 * Process tone control
2167 */
2168 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), GPR(playback + 0), C_00000000, C_00000000); /* left */
2169 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), GPR(playback + 1), C_00000000, C_00000000); /* right */
2170 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2), GPR(playback + 2), C_00000000, C_00000000); /* rear left */
2171 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 3), GPR(playback + 3), C_00000000, C_00000000); /* rear right */
2172 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), GPR(playback + 4), C_00000000, C_00000000); /* center */
2173 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), GPR(playback + 5), C_00000000, C_00000000); /* LFE */
2174
2175 ctl = &controls[i + 0];
2176 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2177 strcpy(ctl->id.name, "Tone Control - Bass");
2178 ctl->vcount = 2;
2179 ctl->count = 10;
2180 ctl->min = 0;
2181 ctl->max = 40;
2182 ctl->value[0] = ctl->value[1] = 20;
Raymond Yaubfe9fc8a2011-05-20 14:32:04 +08002183 ctl->tlv = snd_emu10k1_bass_treble_db_scale;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002184 ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
2185 ctl = &controls[i + 1];
2186 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2187 strcpy(ctl->id.name, "Tone Control - Treble");
2188 ctl->vcount = 2;
2189 ctl->count = 10;
2190 ctl->min = 0;
2191 ctl->max = 40;
2192 ctl->value[0] = ctl->value[1] = 20;
Raymond Yaubfe9fc8a2011-05-20 14:32:04 +08002193 ctl->tlv = snd_emu10k1_bass_treble_db_scale;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002194 ctl->translation = EMU10K1_GPR_TRANSLATION_TREBLE;
2195
2196#define BASS_GPR 0x8c
2197#define TREBLE_GPR 0x96
2198
2199 for (z = 0; z < 5; z++) {
2200 int j;
2201 for (j = 0; j < 2; j++) {
2202 controls[i + 0].gpr[z * 2 + j] = BASS_GPR + z * 2 + j;
2203 controls[i + 1].gpr[z * 2 + j] = TREBLE_GPR + z * 2 + j;
2204 }
2205 }
2206 for (z = 0; z < 3; z++) { /* front/rear/center-lfe */
2207 int j, k, l, d;
2208 for (j = 0; j < 2; j++) { /* left/right */
2209 k = 0xa0 + (z * 8) + (j * 4);
2210 l = 0xd0 + (z * 8) + (j * 4);
2211 d = playback + SND_EMU10K1_PLAYBACK_CHANNELS + z * 2 + j;
2212
2213 OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(d), GPR(BASS_GPR + 0 + j));
2214 OP(icode, &ptr, iMACMV, GPR(k+1), GPR(k), GPR(k+1), GPR(BASS_GPR + 4 + j));
2215 OP(icode, &ptr, iMACMV, GPR(k), GPR(d), GPR(k), GPR(BASS_GPR + 2 + j));
2216 OP(icode, &ptr, iMACMV, GPR(k+3), GPR(k+2), GPR(k+3), GPR(BASS_GPR + 8 + j));
2217 OP(icode, &ptr, iMAC0, GPR(k+2), GPR_ACCU, GPR(k+2), GPR(BASS_GPR + 6 + j));
2218 OP(icode, &ptr, iACC3, GPR(k+2), GPR(k+2), GPR(k+2), C_00000000);
2219
2220 OP(icode, &ptr, iMAC0, C_00000000, C_00000000, GPR(k+2), GPR(TREBLE_GPR + 0 + j));
2221 OP(icode, &ptr, iMACMV, GPR(l+1), GPR(l), GPR(l+1), GPR(TREBLE_GPR + 4 + j));
2222 OP(icode, &ptr, iMACMV, GPR(l), GPR(k+2), GPR(l), GPR(TREBLE_GPR + 2 + j));
2223 OP(icode, &ptr, iMACMV, GPR(l+3), GPR(l+2), GPR(l+3), GPR(TREBLE_GPR + 8 + j));
2224 OP(icode, &ptr, iMAC0, GPR(l+2), GPR_ACCU, GPR(l+2), GPR(TREBLE_GPR + 6 + j));
2225 OP(icode, &ptr, iMACINT0, GPR(l+2), C_00000000, GPR(l+2), C_00000010);
2226
2227 OP(icode, &ptr, iACC3, GPR(d), GPR(l+2), C_00000000, C_00000000);
2228
2229 if (z == 2) /* center */
2230 break;
2231 }
2232 }
2233 i += 2;
2234
2235#undef BASS_GPR
2236#undef TREBLE_GPR
2237
2238 for (z = 0; z < 6; z++) {
2239 SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, gpr + 0);
2240 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 0);
2241 SWITCH(icode, &ptr, tmp + 1, playback + z, tmp + 1);
2242 OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
2243 }
2244 snd_emu10k1_init_stereo_onoff_control(controls + i++, "Tone Control - Switch", gpr, 0);
2245 gpr += 2;
2246
2247 /*
2248 * Process outputs
2249 */
2250 if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_L)|(1<<EXTOUT_AC97_R))) {
2251 /* AC'97 Playback Volume */
2252
2253 for (z = 0; z < 2; z++)
2254 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), C_00000000, C_00000000);
2255 }
2256
2257 if (emu->fx8010.extout_mask & ((1<<EXTOUT_TOSLINK_L)|(1<<EXTOUT_TOSLINK_R))) {
2258 /* IEC958 Optical Raw Playback Switch */
2259
2260 for (z = 0; z < 2; z++) {
2261 SWITCH(icode, &ptr, tmp + 0, 8 + z, gpr + z);
2262 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + z);
2263 SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
2264 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_TOSLINK_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
2265#ifdef EMU10K1_CAPTURE_DIGITAL_OUT
2266 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
2267#endif
2268 }
2269
Clemens Ladisch10e8d782005-08-03 13:40:08 +02002270 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 -07002271 gpr += 2;
2272 }
2273
2274 if (emu->fx8010.extout_mask & ((1<<EXTOUT_HEADPHONE_L)|(1<<EXTOUT_HEADPHONE_R))) {
2275 /* Headphone Playback Volume */
2276
2277 for (z = 0; z < 2; z++) {
2278 SWITCH(icode, &ptr, tmp + 0, playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4 + z, gpr + 2 + z);
2279 SWITCH_NEG(icode, &ptr, tmp + 1, gpr + 2 + z);
2280 SWITCH(icode, &ptr, tmp + 1, playback + SND_EMU10K1_PLAYBACK_CHANNELS + z, tmp + 1);
2281 OP(icode, &ptr, iACC3, GPR(tmp + 0), GPR(tmp + 0), GPR(tmp + 1), C_00000000);
2282 VOLUME_OUT(icode, &ptr, EXTOUT_HEADPHONE_L + z, tmp + 0, gpr + z);
2283 }
2284
2285 snd_emu10k1_init_stereo_control(controls + i++, "Headphone Playback Volume", gpr + 0, 0);
2286 controls[i-1].id.index = 1; /* AC'97 can have also Headphone control */
2287 snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone Center Playback Switch", gpr + 2, 0);
2288 controls[i-1].id.index = 1;
2289 snd_emu10k1_init_mono_onoff_control(controls + i++, "Headphone LFE Playback Switch", gpr + 3, 0);
2290 controls[i-1].id.index = 1;
2291
2292 gpr += 4;
2293 }
2294
2295 if (emu->fx8010.extout_mask & ((1<<EXTOUT_REAR_L)|(1<<EXTOUT_REAR_R)))
2296 for (z = 0; z < 2; z++)
2297 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000);
2298
2299 if (emu->fx8010.extout_mask & ((1<<EXTOUT_AC97_REAR_L)|(1<<EXTOUT_AC97_REAR_R)))
2300 for (z = 0; z < 2; z++)
2301 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_REAR_L + z), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 2 + z), C_00000000, C_00000000);
2302
2303 if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_CENTER)) {
2304#ifndef EMU10K1_CENTER_LFE_FROM_FRONT
2305 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000);
2306 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 4), C_00000000, C_00000000);
2307#else
2308 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_CENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000);
2309 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ACENTER), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 0), C_00000000, C_00000000);
2310#endif
2311 }
2312
2313 if (emu->fx8010.extout_mask & (1<<EXTOUT_AC97_LFE)) {
2314#ifndef EMU10K1_CENTER_LFE_FROM_FRONT
2315 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000);
2316 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), C_00000000, C_00000000);
2317#else
2318 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_AC97_LFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000);
2319 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ALFE), GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 1), C_00000000, C_00000000);
2320#endif
2321 }
2322
2323#ifndef EMU10K1_CAPTURE_DIGITAL_OUT
2324 for (z = 0; z < 2; z++)
2325 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_ADC_CAP_L + z), GPR(capture + z), C_00000000, C_00000000);
2326#endif
2327
2328 if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP))
2329 OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
2330
2331 /* EFX capture - capture the 16 EXTINS */
Lee Revell2b637da2005-03-30 13:51:18 +02002332 if (emu->card_capabilities->sblive51) {
2333 /* On the Live! 5.1, FXBUS2(1) and FXBUS(2) are shared with EXTOUT_ACENTER
2334 * and EXTOUT_ALFE, so we can't connect inputs to them for multitrack recording.
2335 *
2336 * Since only 14 of the 16 EXTINs are used, this is not a big problem.
2337 * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture
2338 * 0 and 3, then the rest of the EXTINs to the corresponding FX capture
2339 * channel. Multitrack recorders will still see the center/lfe output signal
2340 * on the second and third channels.
2341 */
2342 OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
2343 OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
2344 OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
2345 OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
2346 for (z = 4; z < 14; z++)
2347 OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
2348 } else {
2349 for (z = 0; z < 16; z++)
2350 OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351 }
Lee Revell2b637da2005-03-30 13:51:18 +02002352
Linus Torvalds1da177e2005-04-16 15:20:36 -07002353
2354 if (gpr > tmp) {
2355 snd_BUG();
2356 err = -EIO;
2357 goto __err;
2358 }
2359 if (i > SND_EMU10K1_GPR_CONTROLS) {
2360 snd_BUG();
2361 err = -EIO;
2362 goto __err;
2363 }
2364
2365 /* clear remaining instruction memory */
2366 while (ptr < 0x200)
2367 OP(icode, &ptr, iACC3, C_00000000, C_00000000, C_00000000, C_00000000);
2368
2369 if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0)
2370 goto __err;
2371 seg = snd_enter_user();
2372 icode->gpr_add_control_count = i;
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002373 icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01002374 emu->support_tlv = 1; /* support TLV */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375 err = snd_emu10k1_icode_poke(emu, icode);
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01002376 emu->support_tlv = 0; /* clear again */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 snd_leave_user(seg);
2378 if (err >= 0)
2379 err = snd_emu10k1_ipcm_poke(emu, ipcm);
Geyslan G. Bemf1b48632013-10-17 19:57:12 -03002380__err:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381 kfree(ipcm);
Geyslan G. Bemf1b48632013-10-17 19:57:12 -03002382__err_ipcm:
Linus Torvalds1da177e2005-04-16 15:20:36 -07002383 kfree(controls);
Geyslan G. Bemf1b48632013-10-17 19:57:12 -03002384__err_ctrls:
2385 kfree((void __force *)icode->gpr_map);
2386__err_gpr:
2387 kfree(icode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 return err;
2389}
2390
Bill Pembertone23e7a12012-12-06 12:35:10 -05002391int snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002392{
Takashi Iwai09668b42005-11-17 16:14:10 +01002393 spin_lock_init(&emu->fx8010.irq_lock);
2394 INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395 if (emu->audigy)
2396 return _snd_emu10k1_audigy_init_efx(emu);
2397 else
2398 return _snd_emu10k1_init_efx(emu);
2399}
2400
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002401void snd_emu10k1_free_efx(struct snd_emu10k1 *emu)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402{
2403 /* stop processor */
2404 if (emu->audigy)
2405 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = A_DBG_SINGLE_STEP);
2406 else
2407 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP);
2408}
2409
James Courtier-Dutton9f4bd5d2006-10-01 10:48:04 +01002410#if 0 /* FIXME: who use them? */
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002411int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412{
Takashi Iwai7c22f1a2005-10-10 11:46:31 +02002413 if (output < 0 || output >= 6)
2414 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002415 snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 1);
2416 return 0;
2417}
2418
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002419int snd_emu10k1_fx8010_tone_control_deactivate(struct snd_emu10k1 *emu, int output)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002420{
Takashi Iwai7c22f1a2005-10-10 11:46:31 +02002421 if (output < 0 || output >= 6)
2422 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002423 snd_emu10k1_ptr_write(emu, emu->gpr_base + 0x94 + output, 0, 0);
2424 return 0;
2425}
2426#endif
2427
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002428int snd_emu10k1_fx8010_tram_setup(struct snd_emu10k1 *emu, u32 size)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002429{
2430 u8 size_reg = 0;
2431
2432 /* size is in samples */
2433 if (size != 0) {
2434 size = (size - 1) >> 13;
2435
2436 while (size) {
2437 size >>= 1;
2438 size_reg++;
2439 }
2440 size = 0x2000 << size_reg;
2441 }
2442 if ((emu->fx8010.etram_pages.bytes / 2) == size)
2443 return 0;
2444 spin_lock_irq(&emu->emu_lock);
2445 outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG);
2446 spin_unlock_irq(&emu->emu_lock);
2447 snd_emu10k1_ptr_write(emu, TCB, 0, 0);
2448 snd_emu10k1_ptr_write(emu, TCBS, 0, 0);
2449 if (emu->fx8010.etram_pages.area != NULL) {
2450 snd_dma_free_pages(&emu->fx8010.etram_pages);
2451 emu->fx8010.etram_pages.area = NULL;
2452 emu->fx8010.etram_pages.bytes = 0;
2453 }
2454
2455 if (size > 0) {
2456 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci),
2457 size * 2, &emu->fx8010.etram_pages) < 0)
2458 return -ENOMEM;
2459 memset(emu->fx8010.etram_pages.area, 0, size * 2);
2460 snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr);
2461 snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg);
2462 spin_lock_irq(&emu->emu_lock);
2463 outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
Takashi Iwai09668b42005-11-17 16:14:10 +01002464 spin_unlock_irq(&emu->emu_lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465 }
2466
2467 return 0;
2468}
2469
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002470static int snd_emu10k1_fx8010_open(struct snd_hwdep * hw, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002471{
2472 return 0;
2473}
2474
2475static void copy_string(char *dst, char *src, char *null, int idx)
2476{
2477 if (src == NULL)
2478 sprintf(dst, "%s %02X", null, idx);
2479 else
2480 strcpy(dst, src);
2481}
2482
Mariusz Kozlowski51882452007-08-11 11:06:09 +02002483static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu,
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002484 struct snd_emu10k1_fx8010_info *info)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002485{
2486 char **fxbus, **extin, **extout;
2487 unsigned short fxbus_mask, extin_mask, extout_mask;
2488 int res;
2489
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490 info->internal_tram_size = emu->fx8010.itram_size;
2491 info->external_tram_size = emu->fx8010.etram_pages.bytes / 2;
2492 fxbus = fxbuses;
2493 extin = emu->audigy ? audigy_ins : creative_ins;
2494 extout = emu->audigy ? audigy_outs : creative_outs;
2495 fxbus_mask = emu->fx8010.fxbus_mask;
2496 extin_mask = emu->fx8010.extin_mask;
2497 extout_mask = emu->fx8010.extout_mask;
2498 for (res = 0; res < 16; res++, fxbus++, extin++, extout++) {
2499 copy_string(info->fxbus_names[res], fxbus_mask & (1 << res) ? *fxbus : NULL, "FXBUS", res);
2500 copy_string(info->extin_names[res], extin_mask & (1 << res) ? *extin : NULL, "Unused", res);
2501 copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res);
2502 }
2503 for (res = 16; res < 32; res++, extout++)
2504 copy_string(info->extout_names[res], extout_mask & (1 << res) ? *extout : NULL, "Unused", res);
2505 info->gpr_controls = emu->fx8010.gpr_count;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506}
2507
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002508static 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 -07002509{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002510 struct snd_emu10k1 *emu = hw->private_data;
2511 struct snd_emu10k1_fx8010_info *info;
2512 struct snd_emu10k1_fx8010_code *icode;
2513 struct snd_emu10k1_fx8010_pcm_rec *ipcm;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002514 unsigned int addr;
2515 void __user *argp = (void __user *)arg;
2516 int res;
2517
2518 switch (cmd) {
Takashi Iwaif7ba7fc2007-01-19 18:34:47 +01002519 case SNDRV_EMU10K1_IOCTL_PVERSION:
2520 emu->support_tlv = 1;
2521 return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002522 case SNDRV_EMU10K1_IOCTL_INFO:
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002523 info = kmalloc(sizeof(*info), GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002524 if (!info)
2525 return -ENOMEM;
Mariusz Kozlowski51882452007-08-11 11:06:09 +02002526 snd_emu10k1_fx8010_info(emu, info);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 if (copy_to_user(argp, info, sizeof(*info))) {
2528 kfree(info);
2529 return -EFAULT;
2530 }
2531 kfree(info);
2532 return 0;
2533 case SNDRV_EMU10K1_IOCTL_CODE_POKE:
2534 if (!capable(CAP_SYS_ADMIN))
2535 return -EPERM;
Li Zefan336500f2009-04-10 09:44:31 +08002536
2537 icode = memdup_user(argp, sizeof(*icode));
2538 if (IS_ERR(icode))
2539 return PTR_ERR(icode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 res = snd_emu10k1_icode_poke(emu, icode);
2541 kfree(icode);
2542 return res;
2543 case SNDRV_EMU10K1_IOCTL_CODE_PEEK:
Li Zefan336500f2009-04-10 09:44:31 +08002544 icode = memdup_user(argp, sizeof(*icode));
2545 if (IS_ERR(icode))
2546 return PTR_ERR(icode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547 res = snd_emu10k1_icode_peek(emu, icode);
2548 if (res == 0 && copy_to_user(argp, icode, sizeof(*icode))) {
2549 kfree(icode);
2550 return -EFAULT;
2551 }
2552 kfree(icode);
2553 return res;
2554 case SNDRV_EMU10K1_IOCTL_PCM_POKE:
Li Zefan336500f2009-04-10 09:44:31 +08002555 ipcm = memdup_user(argp, sizeof(*ipcm));
2556 if (IS_ERR(ipcm))
2557 return PTR_ERR(ipcm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 res = snd_emu10k1_ipcm_poke(emu, ipcm);
2559 kfree(ipcm);
2560 return res;
2561 case SNDRV_EMU10K1_IOCTL_PCM_PEEK:
Li Zefan336500f2009-04-10 09:44:31 +08002562 ipcm = memdup_user(argp, sizeof(*ipcm));
2563 if (IS_ERR(ipcm))
2564 return PTR_ERR(ipcm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002565 res = snd_emu10k1_ipcm_peek(emu, ipcm);
2566 if (res == 0 && copy_to_user(argp, ipcm, sizeof(*ipcm))) {
2567 kfree(ipcm);
2568 return -EFAULT;
2569 }
2570 kfree(ipcm);
2571 return res;
2572 case SNDRV_EMU10K1_IOCTL_TRAM_SETUP:
2573 if (!capable(CAP_SYS_ADMIN))
2574 return -EPERM;
2575 if (get_user(addr, (unsigned int __user *)argp))
2576 return -EFAULT;
Ingo Molnar62932df2006-01-16 16:34:20 +01002577 mutex_lock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578 res = snd_emu10k1_fx8010_tram_setup(emu, addr);
Ingo Molnar62932df2006-01-16 16:34:20 +01002579 mutex_unlock(&emu->fx8010.lock);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002580 return res;
2581 case SNDRV_EMU10K1_IOCTL_STOP:
2582 if (!capable(CAP_SYS_ADMIN))
2583 return -EPERM;
2584 if (emu->audigy)
2585 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP);
2586 else
2587 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP);
2588 return 0;
2589 case SNDRV_EMU10K1_IOCTL_CONTINUE:
2590 if (!capable(CAP_SYS_ADMIN))
2591 return -EPERM;
2592 if (emu->audigy)
2593 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg = 0);
2594 else
2595 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = 0);
2596 return 0;
2597 case SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER:
2598 if (!capable(CAP_SYS_ADMIN))
2599 return -EPERM;
2600 if (emu->audigy)
2601 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_ZC);
2602 else
2603 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_ZC);
2604 udelay(10);
2605 if (emu->audigy)
2606 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
2607 else
2608 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
2609 return 0;
2610 case SNDRV_EMU10K1_IOCTL_SINGLE_STEP:
2611 if (!capable(CAP_SYS_ADMIN))
2612 return -EPERM;
2613 if (get_user(addr, (unsigned int __user *)argp))
2614 return -EFAULT;
2615 if (addr > 0x1ff)
2616 return -EINVAL;
2617 if (emu->audigy)
2618 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | addr);
2619 else
2620 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | addr);
2621 udelay(10);
2622 if (emu->audigy)
2623 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg |= A_DBG_SINGLE_STEP | A_DBG_STEP_ADDR | addr);
2624 else
2625 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg |= EMU10K1_DBG_SINGLE_STEP | EMU10K1_DBG_STEP | addr);
2626 return 0;
2627 case SNDRV_EMU10K1_IOCTL_DBG_READ:
2628 if (emu->audigy)
2629 addr = snd_emu10k1_ptr_read(emu, A_DBG, 0);
2630 else
2631 addr = snd_emu10k1_ptr_read(emu, DBG, 0);
2632 if (put_user(addr, (unsigned int __user *)argp))
2633 return -EFAULT;
2634 return 0;
2635 }
2636 return -ENOTTY;
2637}
2638
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002639static int snd_emu10k1_fx8010_release(struct snd_hwdep * hw, struct file *file)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002640{
2641 return 0;
2642}
2643
Lars-Peter Clausenbb814c32015-01-02 12:24:49 +01002644int snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002645{
Takashi Iwaieb4698f2005-11-17 14:50:13 +01002646 struct snd_hwdep *hw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 int err;
2648
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 if ((err = snd_hwdep_new(emu->card, "FX8010", device, &hw)) < 0)
2650 return err;
2651 strcpy(hw->name, "EMU10K1 (FX8010)");
2652 hw->iface = SNDRV_HWDEP_IFACE_EMU10K1;
2653 hw->ops.open = snd_emu10k1_fx8010_open;
2654 hw->ops.ioctl = snd_emu10k1_fx8010_ioctl;
2655 hw->ops.release = snd_emu10k1_fx8010_release;
2656 hw->private_data = emu;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002657 return 0;
2658}
Takashi Iwai09668b42005-11-17 16:14:10 +01002659
Takashi Iwaic7561cd2012-08-14 18:12:04 +02002660#ifdef CONFIG_PM_SLEEP
Bill Pembertone23e7a12012-12-06 12:35:10 -05002661int snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu)
Takashi Iwai09668b42005-11-17 16:14:10 +01002662{
2663 int len;
2664
2665 len = emu->audigy ? 0x200 : 0x100;
2666 emu->saved_gpr = kmalloc(len * 4, GFP_KERNEL);
2667 if (! emu->saved_gpr)
2668 return -ENOMEM;
2669 len = emu->audigy ? 0x100 : 0xa0;
2670 emu->tram_val_saved = kmalloc(len * 4, GFP_KERNEL);
2671 emu->tram_addr_saved = kmalloc(len * 4, GFP_KERNEL);
2672 if (! emu->tram_val_saved || ! emu->tram_addr_saved)
2673 return -ENOMEM;
2674 len = emu->audigy ? 2 * 1024 : 2 * 512;
2675 emu->saved_icode = vmalloc(len * 4);
2676 if (! emu->saved_icode)
2677 return -ENOMEM;
2678 return 0;
2679}
2680
2681void snd_emu10k1_efx_free_pm_buffer(struct snd_emu10k1 *emu)
2682{
2683 kfree(emu->saved_gpr);
2684 kfree(emu->tram_val_saved);
2685 kfree(emu->tram_addr_saved);
2686 vfree(emu->saved_icode);
2687}
2688
2689/*
2690 * save/restore GPR, TRAM and codes
2691 */
2692void snd_emu10k1_efx_suspend(struct snd_emu10k1 *emu)
2693{
2694 int i, len;
2695
2696 len = emu->audigy ? 0x200 : 0x100;
2697 for (i = 0; i < len; i++)
2698 emu->saved_gpr[i] = snd_emu10k1_ptr_read(emu, emu->gpr_base + i, 0);
2699
2700 len = emu->audigy ? 0x100 : 0xa0;
2701 for (i = 0; i < len; i++) {
2702 emu->tram_val_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMDATAREGBASE + i, 0);
2703 emu->tram_addr_saved[i] = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + i, 0);
2704 if (emu->audigy) {
2705 emu->tram_addr_saved[i] >>= 12;
2706 emu->tram_addr_saved[i] |=
2707 snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + i, 0) << 20;
2708 }
2709 }
2710
2711 len = emu->audigy ? 2 * 1024 : 2 * 512;
2712 for (i = 0; i < len; i++)
2713 emu->saved_icode[i] = snd_emu10k1_efx_read(emu, i);
2714}
2715
2716void snd_emu10k1_efx_resume(struct snd_emu10k1 *emu)
2717{
2718 int i, len;
2719
2720 /* set up TRAM */
2721 if (emu->fx8010.etram_pages.bytes > 0) {
2722 unsigned size, size_reg = 0;
2723 size = emu->fx8010.etram_pages.bytes / 2;
2724 size = (size - 1) >> 13;
2725 while (size) {
2726 size >>= 1;
2727 size_reg++;
2728 }
2729 outl(HCFG_LOCKTANKCACHE_MASK | inl(emu->port + HCFG), emu->port + HCFG);
2730 snd_emu10k1_ptr_write(emu, TCB, 0, emu->fx8010.etram_pages.addr);
2731 snd_emu10k1_ptr_write(emu, TCBS, 0, size_reg);
2732 outl(inl(emu->port + HCFG) & ~HCFG_LOCKTANKCACHE_MASK, emu->port + HCFG);
2733 }
2734
2735 if (emu->audigy)
2736 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg | A_DBG_SINGLE_STEP);
2737 else
2738 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg | EMU10K1_DBG_SINGLE_STEP);
2739
2740 len = emu->audigy ? 0x200 : 0x100;
2741 for (i = 0; i < len; i++)
2742 snd_emu10k1_ptr_write(emu, emu->gpr_base + i, 0, emu->saved_gpr[i]);
2743
2744 len = emu->audigy ? 0x100 : 0xa0;
2745 for (i = 0; i < len; i++) {
2746 snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + i, 0,
2747 emu->tram_val_saved[i]);
2748 if (! emu->audigy)
2749 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0,
2750 emu->tram_addr_saved[i]);
2751 else {
2752 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0,
2753 emu->tram_addr_saved[i] << 12);
2754 snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + i, 0,
2755 emu->tram_addr_saved[i] >> 20);
2756 }
2757 }
2758
2759 len = emu->audigy ? 2 * 1024 : 2 * 512;
2760 for (i = 0; i < len; i++)
2761 snd_emu10k1_efx_write(emu, i, emu->saved_icode[i]);
2762
2763 /* start FX processor when the DSP code is updated */
2764 if (emu->audigy)
2765 snd_emu10k1_ptr_write(emu, A_DBG, 0, emu->fx8010.dbg);
2766 else
2767 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg);
2768}
2769#endif