xref: /linux/sound/isa/sb/emu8000.c (revision 60e13231561b3a4c5269bfa1ef6c0569ad6f28ec)
1 /*
2  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
3  *     and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
4  *  Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
5  *
6  *  Routines for control of EMU8000 chip
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22 
23 #include <linux/wait.h>
24 #include <linux/sched.h>
25 #include <linux/slab.h>
26 #include <linux/ioport.h>
27 #include <linux/delay.h>
28 #include <sound/core.h>
29 #include <sound/emu8000.h>
30 #include <sound/emu8000_reg.h>
31 #include <asm/io.h>
32 #include <asm/uaccess.h>
33 #include <linux/init.h>
34 #include <sound/control.h>
35 #include <sound/initval.h>
36 
37 /*
38  * emu8000 register controls
39  */
40 
41 /*
42  * The following routines read and write registers on the emu8000.  They
43  * should always be called via the EMU8000*READ/WRITE macros and never
44  * directly.  The macros handle the port number and command word.
45  */
46 /* Write a word */
47 void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
48 {
49 	unsigned long flags;
50 	spin_lock_irqsave(&emu->reg_lock, flags);
51 	if (reg != emu->last_reg) {
52 		outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
53 		emu->last_reg = reg;
54 	}
55 	outw((unsigned short)val, port); /* Send data */
56 	spin_unlock_irqrestore(&emu->reg_lock, flags);
57 }
58 
59 /* Read a word */
60 unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
61 {
62 	unsigned short res;
63 	unsigned long flags;
64 	spin_lock_irqsave(&emu->reg_lock, flags);
65 	if (reg != emu->last_reg) {
66 		outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
67 		emu->last_reg = reg;
68 	}
69 	res = inw(port);	/* Read data */
70 	spin_unlock_irqrestore(&emu->reg_lock, flags);
71 	return res;
72 }
73 
74 /* Write a double word */
75 void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
76 {
77 	unsigned long flags;
78 	spin_lock_irqsave(&emu->reg_lock, flags);
79 	if (reg != emu->last_reg) {
80 		outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
81 		emu->last_reg = reg;
82 	}
83 	outw((unsigned short)val, port); /* Send low word of data */
84 	outw((unsigned short)(val>>16), port+2); /* Send high word of data */
85 	spin_unlock_irqrestore(&emu->reg_lock, flags);
86 }
87 
88 /* Read a double word */
89 unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
90 {
91 	unsigned short low;
92 	unsigned int res;
93 	unsigned long flags;
94 	spin_lock_irqsave(&emu->reg_lock, flags);
95 	if (reg != emu->last_reg) {
96 		outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
97 		emu->last_reg = reg;
98 	}
99 	low = inw(port);	/* Read low word of data */
100 	res = low + (inw(port+2) << 16);
101 	spin_unlock_irqrestore(&emu->reg_lock, flags);
102 	return res;
103 }
104 
105 /*
106  * Set up / close a channel to be used for DMA.
107  */
108 /*exported*/ void
109 snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
110 {
111 	unsigned right_bit = (mode & EMU8000_RAM_RIGHT) ? 0x01000000 : 0;
112 	mode &= EMU8000_RAM_MODE_MASK;
113 	if (mode == EMU8000_RAM_CLOSE) {
114 		EMU8000_CCCA_WRITE(emu, ch, 0);
115 		EMU8000_DCYSUSV_WRITE(emu, ch, 0x807F);
116 		return;
117 	}
118 	EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
119 	EMU8000_VTFT_WRITE(emu, ch, 0);
120 	EMU8000_CVCF_WRITE(emu, ch, 0);
121 	EMU8000_PTRX_WRITE(emu, ch, 0x40000000);
122 	EMU8000_CPF_WRITE(emu, ch, 0x40000000);
123 	EMU8000_PSST_WRITE(emu, ch, 0);
124 	EMU8000_CSL_WRITE(emu, ch, 0);
125 	if (mode == EMU8000_RAM_WRITE) /* DMA write */
126 		EMU8000_CCCA_WRITE(emu, ch, 0x06000000 | right_bit);
127 	else	   /* DMA read */
128 		EMU8000_CCCA_WRITE(emu, ch, 0x04000000 | right_bit);
129 }
130 
131 /*
132  */
133 static void __devinit
134 snd_emu8000_read_wait(struct snd_emu8000 *emu)
135 {
136 	while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
137 		schedule_timeout_interruptible(1);
138 		if (signal_pending(current))
139 			break;
140 	}
141 }
142 
143 /*
144  */
145 static void __devinit
146 snd_emu8000_write_wait(struct snd_emu8000 *emu)
147 {
148 	while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
149 		schedule_timeout_interruptible(1);
150 		if (signal_pending(current))
151 			break;
152 	}
153 }
154 
155 /*
156  * detect a card at the given port
157  */
158 static int __devinit
159 snd_emu8000_detect(struct snd_emu8000 *emu)
160 {
161 	/* Initialise */
162 	EMU8000_HWCF1_WRITE(emu, 0x0059);
163 	EMU8000_HWCF2_WRITE(emu, 0x0020);
164 	EMU8000_HWCF3_WRITE(emu, 0x0000);
165 	/* Check for a recognisable emu8000 */
166 	/*
167 	if ((EMU8000_U1_READ(emu) & 0x000f) != 0x000c)
168 		return -ENODEV;
169 		*/
170 	if ((EMU8000_HWCF1_READ(emu) & 0x007e) != 0x0058)
171 		return -ENODEV;
172 	if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003)
173 		return -ENODEV;
174 
175 	snd_printdd("EMU8000 [0x%lx]: Synth chip found\n",
176                     emu->port1);
177 	return 0;
178 }
179 
180 
181 /*
182  * intiailize audio channels
183  */
184 static void __devinit
185 init_audio(struct snd_emu8000 *emu)
186 {
187 	int ch;
188 
189 	/* turn off envelope engines */
190 	for (ch = 0; ch < EMU8000_CHANNELS; ch++)
191 		EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
192 
193 	/* reset all other parameters to zero */
194 	for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
195 		EMU8000_ENVVOL_WRITE(emu, ch, 0);
196 		EMU8000_ENVVAL_WRITE(emu, ch, 0);
197 		EMU8000_DCYSUS_WRITE(emu, ch, 0);
198 		EMU8000_ATKHLDV_WRITE(emu, ch, 0);
199 		EMU8000_LFO1VAL_WRITE(emu, ch, 0);
200 		EMU8000_ATKHLD_WRITE(emu, ch, 0);
201 		EMU8000_LFO2VAL_WRITE(emu, ch, 0);
202 		EMU8000_IP_WRITE(emu, ch, 0);
203 		EMU8000_IFATN_WRITE(emu, ch, 0);
204 		EMU8000_PEFE_WRITE(emu, ch, 0);
205 		EMU8000_FMMOD_WRITE(emu, ch, 0);
206 		EMU8000_TREMFRQ_WRITE(emu, ch, 0);
207 		EMU8000_FM2FRQ2_WRITE(emu, ch, 0);
208 		EMU8000_PTRX_WRITE(emu, ch, 0);
209 		EMU8000_VTFT_WRITE(emu, ch, 0);
210 		EMU8000_PSST_WRITE(emu, ch, 0);
211 		EMU8000_CSL_WRITE(emu, ch, 0);
212 		EMU8000_CCCA_WRITE(emu, ch, 0);
213 	}
214 
215 	for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
216 		EMU8000_CPF_WRITE(emu, ch, 0);
217 		EMU8000_CVCF_WRITE(emu, ch, 0);
218 	}
219 }
220 
221 
222 /*
223  * initialize DMA address
224  */
225 static void __devinit
226 init_dma(struct snd_emu8000 *emu)
227 {
228 	EMU8000_SMALR_WRITE(emu, 0);
229 	EMU8000_SMARR_WRITE(emu, 0);
230 	EMU8000_SMALW_WRITE(emu, 0);
231 	EMU8000_SMARW_WRITE(emu, 0);
232 }
233 
234 /*
235  * initialization arrays; from ADIP
236  */
237 static unsigned short init1[128] /*__devinitdata*/ = {
238 	0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
239 	0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
240 	0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
241 	0x33ff, 0x0c30,  0x37ff, 0x0d30, 0x3bff, 0x0e30,  0x3fff, 0x0f30,
242 
243 	0x43ff, 0x0030,  0x47ff, 0x0130, 0x4bff, 0x0230,  0x4fff, 0x0330,
244 	0x53ff, 0x0430,  0x57ff, 0x0530, 0x5bff, 0x0630,  0x5fff, 0x0730,
245 	0x63ff, 0x0830,  0x67ff, 0x0930, 0x6bff, 0x0a30,  0x6fff, 0x0b30,
246 	0x73ff, 0x0c30,  0x77ff, 0x0d30, 0x7bff, 0x0e30,  0x7fff, 0x0f30,
247 
248 	0x83ff, 0x0030,  0x87ff, 0x0130, 0x8bff, 0x0230,  0x8fff, 0x0330,
249 	0x93ff, 0x0430,  0x97ff, 0x0530, 0x9bff, 0x0630,  0x9fff, 0x0730,
250 	0xa3ff, 0x0830,  0xa7ff, 0x0930, 0xabff, 0x0a30,  0xafff, 0x0b30,
251 	0xb3ff, 0x0c30,  0xb7ff, 0x0d30, 0xbbff, 0x0e30,  0xbfff, 0x0f30,
252 
253 	0xc3ff, 0x0030,  0xc7ff, 0x0130, 0xcbff, 0x0230,  0xcfff, 0x0330,
254 	0xd3ff, 0x0430,  0xd7ff, 0x0530, 0xdbff, 0x0630,  0xdfff, 0x0730,
255 	0xe3ff, 0x0830,  0xe7ff, 0x0930, 0xebff, 0x0a30,  0xefff, 0x0b30,
256 	0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
257 };
258 
259 static unsigned short init2[128] /*__devinitdata*/ = {
260 	0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
261 	0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
262 	0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
263 	0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
264 
265 	0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
266 	0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
267 	0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
268 	0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
269 
270 	0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
271 	0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
272 	0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
273 	0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
274 
275 	0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
276 	0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
277 	0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
278 	0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
279 };
280 
281 static unsigned short init3[128] /*__devinitdata*/ = {
282 	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
283 	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
284 	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
285 	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
286 
287 	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
288 	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
289 	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
290 	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
291 
292 	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
293 	0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
294 	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
295 	0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
296 
297 	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
298 	0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
299 	0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
300 	0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
301 };
302 
303 static unsigned short init4[128] /*__devinitdata*/ = {
304 	0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
305 	0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
306 	0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
307 	0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
308 
309 	0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
310 	0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
311 	0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
312 	0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
313 
314 	0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
315 	0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
316 	0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
317 	0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
318 
319 	0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
320 	0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
321 	0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
322 	0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
323 };
324 
325 /* send an initialization array
326  * Taken from the oss driver, not obvious from the doc how this
327  * is meant to work
328  */
329 static void __devinit
330 send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
331 {
332 	int i;
333 	unsigned short *p;
334 
335 	p = data;
336 	for (i = 0; i < size; i++, p++)
337 		EMU8000_INIT1_WRITE(emu, i, *p);
338 	for (i = 0; i < size; i++, p++)
339 		EMU8000_INIT2_WRITE(emu, i, *p);
340 	for (i = 0; i < size; i++, p++)
341 		EMU8000_INIT3_WRITE(emu, i, *p);
342 	for (i = 0; i < size; i++, p++)
343 		EMU8000_INIT4_WRITE(emu, i, *p);
344 }
345 
346 
347 /*
348  * Send initialization arrays to start up, this just follows the
349  * initialisation sequence in the adip.
350  */
351 static void __devinit
352 init_arrays(struct snd_emu8000 *emu)
353 {
354 	send_array(emu, init1, ARRAY_SIZE(init1)/4);
355 
356 	msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */
357 	send_array(emu, init2, ARRAY_SIZE(init2)/4);
358 	send_array(emu, init3, ARRAY_SIZE(init3)/4);
359 
360 	EMU8000_HWCF4_WRITE(emu, 0);
361 	EMU8000_HWCF5_WRITE(emu, 0x83);
362 	EMU8000_HWCF6_WRITE(emu, 0x8000);
363 
364 	send_array(emu, init4, ARRAY_SIZE(init4)/4);
365 }
366 
367 
368 #define UNIQUE_ID1	0xa5b9
369 #define UNIQUE_ID2	0x9d53
370 
371 /*
372  * Size the onboard memory.
373  * This is written so as not to need arbitrary delays after the write. It
374  * seems that the only way to do this is to use the one channel and keep
375  * reallocating between read and write.
376  */
377 static void __devinit
378 size_dram(struct snd_emu8000 *emu)
379 {
380 	int i, size, detected_size;
381 
382 	if (emu->dram_checked)
383 		return;
384 
385 	size = 0;
386 	detected_size = 0;
387 
388 	/* write out a magic number */
389 	snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);
390 	snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ);
391 	EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET);
392 	EMU8000_SMLD_WRITE(emu, UNIQUE_ID1);
393 	snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */
394 
395 	while (size < EMU8000_MAX_DRAM) {
396 
397 		size += 512 * 1024;  /* increment 512kbytes */
398 
399 		/* Write a unique data on the test address.
400 		 * if the address is out of range, the data is written on
401 		 * 0x200000(=EMU8000_DRAM_OFFSET).  Then the id word is
402 		 * changed by this data.
403 		 */
404 		/*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/
405 		EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
406 		EMU8000_SMLD_WRITE(emu, UNIQUE_ID2);
407 		snd_emu8000_write_wait(emu);
408 
409 		/*
410 		 * read the data on the just written DRAM address
411 		 * if not the same then we have reached the end of ram.
412 		 */
413 		/*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/
414 		EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
415 		/*snd_emu8000_read_wait(emu);*/
416 		EMU8000_SMLD_READ(emu); /* discard stale data  */
417 		if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
418 			break; /* no memory at this address */
419 
420 		detected_size = size;
421 
422 		snd_emu8000_read_wait(emu);
423 
424 		/*
425 		 * If it is the same it could be that the address just
426 		 * wraps back to the beginning; so check to see if the
427 		 * initial value has been overwritten.
428 		 */
429 		EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
430 		EMU8000_SMLD_READ(emu); /* discard stale data  */
431 		if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
432 			break; /* we must have wrapped around */
433 		snd_emu8000_read_wait(emu);
434 	}
435 
436 	/* wait until FULL bit in SMAxW register is false */
437 	for (i = 0; i < 10000; i++) {
438 		if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0)
439 			break;
440 		schedule_timeout_interruptible(1);
441 		if (signal_pending(current))
442 			break;
443 	}
444 	snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE);
445 	snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE);
446 
447 	snd_printdd("EMU8000 [0x%lx]: %d Kb on-board memory detected\n",
448 		    emu->port1, detected_size/1024);
449 
450 	emu->mem_size = detected_size;
451 	emu->dram_checked = 1;
452 }
453 
454 
455 /*
456  * Initiailise the FM section.  You have to do this to use sample RAM
457  * and therefore lose 2 voices.
458  */
459 /*exported*/ void
460 snd_emu8000_init_fm(struct snd_emu8000 *emu)
461 {
462 	unsigned long flags;
463 
464 	/* Initialize the last two channels for DRAM refresh and producing
465 	   the reverb and chorus effects for Yamaha OPL-3 synthesizer */
466 
467 	/* 31: FM left channel, 0xffffe0-0xffffe8 */
468 	EMU8000_DCYSUSV_WRITE(emu, 30, 0x80);
469 	EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */
470 	EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24));
471 	EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8));
472 	EMU8000_CPF_WRITE(emu, 30, 0);
473 	EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3);
474 
475 	/* 32: FM right channel, 0xfffff0-0xfffff8 */
476 	EMU8000_DCYSUSV_WRITE(emu, 31, 0x80);
477 	EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */
478 	EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24));
479 	EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8));
480 	EMU8000_CPF_WRITE(emu, 31, 0x8000);
481 	EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3);
482 
483 	snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0);
484 
485 	spin_lock_irqsave(&emu->reg_lock, flags);
486 	while (!(inw(EMU8000_PTR(emu)) & 0x1000))
487 		;
488 	while ((inw(EMU8000_PTR(emu)) & 0x1000))
489 		;
490 	spin_unlock_irqrestore(&emu->reg_lock, flags);
491 	snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828);
492 	/* this is really odd part.. */
493 	outb(0x3C, EMU8000_PTR(emu));
494 	outb(0, EMU8000_DATA1(emu));
495 
496 	/* skew volume & cutoff */
497 	EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF);
498 	EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF);
499 }
500 
501 
502 /*
503  * The main initialization routine.
504  */
505 static void __devinit
506 snd_emu8000_init_hw(struct snd_emu8000 *emu)
507 {
508 	int i;
509 
510 	emu->last_reg = 0xffff; /* reset the last register index */
511 
512 	/* initialize hardware configuration */
513 	EMU8000_HWCF1_WRITE(emu, 0x0059);
514 	EMU8000_HWCF2_WRITE(emu, 0x0020);
515 
516 	/* disable audio; this seems to reduce a clicking noise a bit.. */
517 	EMU8000_HWCF3_WRITE(emu, 0);
518 
519 	/* initialize audio channels */
520 	init_audio(emu);
521 
522 	/* initialize DMA */
523 	init_dma(emu);
524 
525 	/* initialize init arrays */
526 	init_arrays(emu);
527 
528 	/*
529 	 * Initialize the FM section of the AWE32, this is needed
530 	 * for DRAM refresh as well
531 	 */
532 	snd_emu8000_init_fm(emu);
533 
534 	/* terminate all voices */
535 	for (i = 0; i < EMU8000_DRAM_VOICES; i++)
536 		EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F);
537 
538 	/* check DRAM memory size */
539 	size_dram(emu);
540 
541 	/* enable audio */
542 	EMU8000_HWCF3_WRITE(emu, 0x4);
543 
544 	/* set equzlier, chorus and reverb modes */
545 	snd_emu8000_update_equalizer(emu);
546 	snd_emu8000_update_chorus_mode(emu);
547 	snd_emu8000_update_reverb_mode(emu);
548 }
549 
550 
551 /*----------------------------------------------------------------
552  * Bass/Treble Equalizer
553  *----------------------------------------------------------------*/
554 
555 static unsigned short bass_parm[12][3] = {
556 	{0xD26A, 0xD36A, 0x0000}, /* -12 dB */
557 	{0xD25B, 0xD35B, 0x0000}, /*  -8 */
558 	{0xD24C, 0xD34C, 0x0000}, /*  -6 */
559 	{0xD23D, 0xD33D, 0x0000}, /*  -4 */
560 	{0xD21F, 0xD31F, 0x0000}, /*  -2 */
561 	{0xC208, 0xC308, 0x0001}, /*   0 (HW default) */
562 	{0xC219, 0xC319, 0x0001}, /*  +2 */
563 	{0xC22A, 0xC32A, 0x0001}, /*  +4 */
564 	{0xC24C, 0xC34C, 0x0001}, /*  +6 */
565 	{0xC26E, 0xC36E, 0x0001}, /*  +8 */
566 	{0xC248, 0xC384, 0x0002}, /* +10 */
567 	{0xC26A, 0xC36A, 0x0002}, /* +12 dB */
568 };
569 
570 static unsigned short treble_parm[12][9] = {
571 	{0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
572 	{0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
573 	{0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
574 	{0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
575 	{0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
576 	{0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
577 	{0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
578 	{0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
579 	{0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
580 	{0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
581 	{0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
582 	{0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}  /* +12 dB */
583 };
584 
585 
586 /*
587  * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
588  */
589 /*exported*/ void
590 snd_emu8000_update_equalizer(struct snd_emu8000 *emu)
591 {
592 	unsigned short w;
593 	int bass = emu->bass_level;
594 	int treble = emu->treble_level;
595 
596 	if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
597 		return;
598 	EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]);
599 	EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]);
600 	EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]);
601 	EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]);
602 	EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]);
603 	EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]);
604 	EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]);
605 	EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]);
606 	EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]);
607 	EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]);
608 	w = bass_parm[bass][2] + treble_parm[treble][8];
609 	EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262));
610 	EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362));
611 }
612 
613 
614 /*----------------------------------------------------------------
615  * Chorus mode control
616  *----------------------------------------------------------------*/
617 
618 /*
619  * chorus mode parameters
620  */
621 #define SNDRV_EMU8000_CHORUS_1		0
622 #define	SNDRV_EMU8000_CHORUS_2		1
623 #define	SNDRV_EMU8000_CHORUS_3		2
624 #define	SNDRV_EMU8000_CHORUS_4		3
625 #define	SNDRV_EMU8000_CHORUS_FEEDBACK	4
626 #define	SNDRV_EMU8000_CHORUS_FLANGER	5
627 #define	SNDRV_EMU8000_CHORUS_SHORTDELAY	6
628 #define	SNDRV_EMU8000_CHORUS_SHORTDELAY2	7
629 #define SNDRV_EMU8000_CHORUS_PREDEFINED	8
630 /* user can define chorus modes up to 32 */
631 #define SNDRV_EMU8000_CHORUS_NUMBERS	32
632 
633 struct soundfont_chorus_fx {
634 	unsigned short feedback;	/* feedback level (0xE600-0xE6FF) */
635 	unsigned short delay_offset;	/* delay (0-0x0DA3) [1/44100 sec] */
636 	unsigned short lfo_depth;	/* LFO depth (0xBC00-0xBCFF) */
637 	unsigned int delay;	/* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
638 	unsigned int lfo_freq;		/* LFO freq LFO freq (0-0xFFFFFFFF) */
639 };
640 
641 /* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
642 static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
643 static struct soundfont_chorus_fx chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
644 	{0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
645 	{0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
646 	{0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
647 	{0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
648 	{0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
649 	{0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
650 	{0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */
651 	{0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */
652 };
653 
654 /*exported*/ int
655 snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
656 {
657 	struct soundfont_chorus_fx rec;
658 	if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) {
659 		snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode);
660 		return -EINVAL;
661 	}
662 	if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
663 		return -EFAULT;
664 	chorus_parm[mode] = rec;
665 	chorus_defined[mode] = 1;
666 	return 0;
667 }
668 
669 /*exported*/ void
670 snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu)
671 {
672 	int effect = emu->chorus_mode;
673 	if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS ||
674 	    (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect]))
675 		return;
676 	EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback);
677 	EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset);
678 	EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth);
679 	EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay);
680 	EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq);
681 	EMU8000_HWCF6_WRITE(emu, 0x8000);
682 	EMU8000_HWCF7_WRITE(emu, 0x0000);
683 }
684 
685 /*----------------------------------------------------------------
686  * Reverb mode control
687  *----------------------------------------------------------------*/
688 
689 /*
690  * reverb mode parameters
691  */
692 #define	SNDRV_EMU8000_REVERB_ROOM1	0
693 #define SNDRV_EMU8000_REVERB_ROOM2	1
694 #define	SNDRV_EMU8000_REVERB_ROOM3	2
695 #define	SNDRV_EMU8000_REVERB_HALL1	3
696 #define	SNDRV_EMU8000_REVERB_HALL2	4
697 #define	SNDRV_EMU8000_REVERB_PLATE	5
698 #define	SNDRV_EMU8000_REVERB_DELAY	6
699 #define	SNDRV_EMU8000_REVERB_PANNINGDELAY 7
700 #define SNDRV_EMU8000_REVERB_PREDEFINED	8
701 /* user can define reverb modes up to 32 */
702 #define SNDRV_EMU8000_REVERB_NUMBERS	32
703 
704 struct soundfont_reverb_fx {
705 	unsigned short parms[28];
706 };
707 
708 /* reverb mode settings; write the following 28 data of 16 bit length
709  *   on the corresponding ports in the reverb_cmds array
710  */
711 static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
712 static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
713 {{  /* room 1 */
714 	0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
715 	0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
716 	0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
717 	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
718 }},
719 {{  /* room 2 */
720 	0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
721 	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
722 	0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
723 	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
724 }},
725 {{  /* room 3 */
726 	0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
727 	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
728 	0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
729 	0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
730 }},
731 {{  /* hall 1 */
732 	0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
733 	0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
734 	0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
735 	0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
736 }},
737 {{  /* hall 2 */
738 	0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
739 	0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
740 	0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
741 	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
742 }},
743 {{  /* plate */
744 	0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
745 	0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
746 	0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
747 	0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
748 }},
749 {{  /* delay */
750 	0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
751 	0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
752 	0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
753 	0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
754 }},
755 {{  /* panning delay */
756 	0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
757 	0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
758 	0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
759 	0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
760 }},
761 };
762 
763 enum { DATA1, DATA2 };
764 #define AWE_INIT1(c)	EMU8000_CMD(2,c), DATA1
765 #define AWE_INIT2(c)	EMU8000_CMD(2,c), DATA2
766 #define AWE_INIT3(c)	EMU8000_CMD(3,c), DATA1
767 #define AWE_INIT4(c)	EMU8000_CMD(3,c), DATA2
768 
769 static struct reverb_cmd_pair {
770 	unsigned short cmd, port;
771 } reverb_cmds[28] = {
772   {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
773   {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
774   {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
775   {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
776   {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
777   {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
778   {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
779 };
780 
781 /*exported*/ int
782 snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
783 {
784 	struct soundfont_reverb_fx rec;
785 
786 	if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) {
787 		snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode);
788 		return -EINVAL;
789 	}
790 	if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
791 		return -EFAULT;
792 	reverb_parm[mode] = rec;
793 	reverb_defined[mode] = 1;
794 	return 0;
795 }
796 
797 /*exported*/ void
798 snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu)
799 {
800 	int effect = emu->reverb_mode;
801 	int i;
802 
803 	if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS ||
804 	    (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect]))
805 		return;
806 	for (i = 0; i < 28; i++) {
807 		int port;
808 		if (reverb_cmds[i].port == DATA1)
809 			port = EMU8000_DATA1(emu);
810 		else
811 			port = EMU8000_DATA2(emu);
812 		snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]);
813 	}
814 }
815 
816 
817 /*----------------------------------------------------------------
818  * mixer interface
819  *----------------------------------------------------------------*/
820 
821 /*
822  * bass/treble
823  */
824 static int mixer_bass_treble_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
825 {
826 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
827 	uinfo->count = 1;
828 	uinfo->value.integer.min = 0;
829 	uinfo->value.integer.max = 11;
830 	return 0;
831 }
832 
833 static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
834 {
835 	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
836 
837 	ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level;
838 	return 0;
839 }
840 
841 static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
842 {
843 	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
844 	unsigned long flags;
845 	int change;
846 	unsigned short val1;
847 
848 	val1 = ucontrol->value.integer.value[0] % 12;
849 	spin_lock_irqsave(&emu->control_lock, flags);
850 	if (kcontrol->private_value) {
851 		change = val1 != emu->treble_level;
852 		emu->treble_level = val1;
853 	} else {
854 		change = val1 != emu->bass_level;
855 		emu->bass_level = val1;
856 	}
857 	spin_unlock_irqrestore(&emu->control_lock, flags);
858 	snd_emu8000_update_equalizer(emu);
859 	return change;
860 }
861 
862 static struct snd_kcontrol_new mixer_bass_control =
863 {
864 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
865 	.name = "Synth Tone Control - Bass",
866 	.info = mixer_bass_treble_info,
867 	.get = mixer_bass_treble_get,
868 	.put = mixer_bass_treble_put,
869 	.private_value = 0,
870 };
871 
872 static struct snd_kcontrol_new mixer_treble_control =
873 {
874 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
875 	.name = "Synth Tone Control - Treble",
876 	.info = mixer_bass_treble_info,
877 	.get = mixer_bass_treble_get,
878 	.put = mixer_bass_treble_put,
879 	.private_value = 1,
880 };
881 
882 /*
883  * chorus/reverb mode
884  */
885 static int mixer_chorus_reverb_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
886 {
887 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
888 	uinfo->count = 1;
889 	uinfo->value.integer.min = 0;
890 	uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1);
891 	return 0;
892 }
893 
894 static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
895 {
896 	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
897 
898 	ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode;
899 	return 0;
900 }
901 
902 static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
903 {
904 	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
905 	unsigned long flags;
906 	int change;
907 	unsigned short val1;
908 
909 	spin_lock_irqsave(&emu->control_lock, flags);
910 	if (kcontrol->private_value) {
911 		val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS;
912 		change = val1 != emu->chorus_mode;
913 		emu->chorus_mode = val1;
914 	} else {
915 		val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS;
916 		change = val1 != emu->reverb_mode;
917 		emu->reverb_mode = val1;
918 	}
919 	spin_unlock_irqrestore(&emu->control_lock, flags);
920 	if (change) {
921 		if (kcontrol->private_value)
922 			snd_emu8000_update_chorus_mode(emu);
923 		else
924 			snd_emu8000_update_reverb_mode(emu);
925 	}
926 	return change;
927 }
928 
929 static struct snd_kcontrol_new mixer_chorus_mode_control =
930 {
931 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
932 	.name = "Chorus Mode",
933 	.info = mixer_chorus_reverb_info,
934 	.get = mixer_chorus_reverb_get,
935 	.put = mixer_chorus_reverb_put,
936 	.private_value = 1,
937 };
938 
939 static struct snd_kcontrol_new mixer_reverb_mode_control =
940 {
941 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
942 	.name = "Reverb Mode",
943 	.info = mixer_chorus_reverb_info,
944 	.get = mixer_chorus_reverb_get,
945 	.put = mixer_chorus_reverb_put,
946 	.private_value = 0,
947 };
948 
949 /*
950  * FM OPL3 chorus/reverb depth
951  */
952 static int mixer_fm_depth_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
953 {
954 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
955 	uinfo->count = 1;
956 	uinfo->value.integer.min = 0;
957 	uinfo->value.integer.max = 255;
958 	return 0;
959 }
960 
961 static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
962 {
963 	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
964 
965 	ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth;
966 	return 0;
967 }
968 
969 static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
970 {
971 	struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
972 	unsigned long flags;
973 	int change;
974 	unsigned short val1;
975 
976 	val1 = ucontrol->value.integer.value[0] % 256;
977 	spin_lock_irqsave(&emu->control_lock, flags);
978 	if (kcontrol->private_value) {
979 		change = val1 != emu->fm_chorus_depth;
980 		emu->fm_chorus_depth = val1;
981 	} else {
982 		change = val1 != emu->fm_reverb_depth;
983 		emu->fm_reverb_depth = val1;
984 	}
985 	spin_unlock_irqrestore(&emu->control_lock, flags);
986 	if (change)
987 		snd_emu8000_init_fm(emu);
988 	return change;
989 }
990 
991 static struct snd_kcontrol_new mixer_fm_chorus_depth_control =
992 {
993 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
994 	.name = "FM Chorus Depth",
995 	.info = mixer_fm_depth_info,
996 	.get = mixer_fm_depth_get,
997 	.put = mixer_fm_depth_put,
998 	.private_value = 1,
999 };
1000 
1001 static struct snd_kcontrol_new mixer_fm_reverb_depth_control =
1002 {
1003 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1004 	.name = "FM Reverb Depth",
1005 	.info = mixer_fm_depth_info,
1006 	.get = mixer_fm_depth_get,
1007 	.put = mixer_fm_depth_put,
1008 	.private_value = 0,
1009 };
1010 
1011 
1012 static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
1013 	&mixer_bass_control,
1014 	&mixer_treble_control,
1015 	&mixer_chorus_mode_control,
1016 	&mixer_reverb_mode_control,
1017 	&mixer_fm_chorus_depth_control,
1018 	&mixer_fm_reverb_depth_control,
1019 };
1020 
1021 /*
1022  * create and attach mixer elements for WaveTable treble/bass controls
1023  */
1024 static int __devinit
1025 snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
1026 {
1027 	int i, err = 0;
1028 
1029 	if (snd_BUG_ON(!emu || !card))
1030 		return -EINVAL;
1031 
1032 	spin_lock_init(&emu->control_lock);
1033 
1034 	memset(emu->controls, 0, sizeof(emu->controls));
1035 	for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1036 		if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0)
1037 			goto __error;
1038 	}
1039 	return 0;
1040 
1041 __error:
1042 	for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1043 		down_write(&card->controls_rwsem);
1044 		if (emu->controls[i])
1045 			snd_ctl_remove(card, emu->controls[i]);
1046 		up_write(&card->controls_rwsem);
1047 	}
1048 	return err;
1049 }
1050 
1051 
1052 /*
1053  * free resources
1054  */
1055 static int snd_emu8000_free(struct snd_emu8000 *hw)
1056 {
1057 	release_and_free_resource(hw->res_port1);
1058 	release_and_free_resource(hw->res_port2);
1059 	release_and_free_resource(hw->res_port3);
1060 	kfree(hw);
1061 	return 0;
1062 }
1063 
1064 /*
1065  */
1066 static int snd_emu8000_dev_free(struct snd_device *device)
1067 {
1068 	struct snd_emu8000 *hw = device->device_data;
1069 	return snd_emu8000_free(hw);
1070 }
1071 
1072 /*
1073  * initialize and register emu8000 synth device.
1074  */
1075 int __devinit
1076 snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
1077 		struct snd_seq_device **awe_ret)
1078 {
1079 	struct snd_seq_device *awe;
1080 	struct snd_emu8000 *hw;
1081 	int err;
1082 	static struct snd_device_ops ops = {
1083 		.dev_free = snd_emu8000_dev_free,
1084 	};
1085 
1086 	if (awe_ret)
1087 		*awe_ret = NULL;
1088 
1089 	if (seq_ports <= 0)
1090 		return 0;
1091 
1092 	hw = kzalloc(sizeof(*hw), GFP_KERNEL);
1093 	if (hw == NULL)
1094 		return -ENOMEM;
1095 	spin_lock_init(&hw->reg_lock);
1096 	hw->index = index;
1097 	hw->port1 = port;
1098 	hw->port2 = port + 0x400;
1099 	hw->port3 = port + 0x800;
1100 	if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) ||
1101 	    !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) ||
1102 	    !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) {
1103 		snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
1104 		snd_emu8000_free(hw);
1105 		return -EBUSY;
1106 	}
1107 	hw->mem_size = 0;
1108 	hw->card = card;
1109 	hw->seq_ports = seq_ports;
1110 	hw->bass_level = 5;
1111 	hw->treble_level = 9;
1112 	hw->chorus_mode = 2;
1113 	hw->reverb_mode = 4;
1114 	hw->fm_chorus_depth = 0;
1115 	hw->fm_reverb_depth = 0;
1116 
1117 	if (snd_emu8000_detect(hw) < 0) {
1118 		snd_emu8000_free(hw);
1119 		return -ENODEV;
1120 	}
1121 
1122 	snd_emu8000_init_hw(hw);
1123 	if ((err = snd_emu8000_create_mixer(card, hw)) < 0) {
1124 		snd_emu8000_free(hw);
1125 		return err;
1126 	}
1127 
1128 	if ((err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops)) < 0) {
1129 		snd_emu8000_free(hw);
1130 		return err;
1131 	}
1132 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
1133 	if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
1134 			       sizeof(struct snd_emu8000*), &awe) >= 0) {
1135 		strcpy(awe->name, "EMU-8000");
1136 		*(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
1137 	}
1138 #else
1139 	awe = NULL;
1140 #endif
1141 	if (awe_ret)
1142 		*awe_ret = awe;
1143 
1144 	return 0;
1145 }
1146 
1147 
1148 /*
1149  * exported stuff
1150  */
1151 
1152 EXPORT_SYMBOL(snd_emu8000_poke);
1153 EXPORT_SYMBOL(snd_emu8000_peek);
1154 EXPORT_SYMBOL(snd_emu8000_poke_dw);
1155 EXPORT_SYMBOL(snd_emu8000_peek_dw);
1156 EXPORT_SYMBOL(snd_emu8000_dma_chan);
1157 EXPORT_SYMBOL(snd_emu8000_init_fm);
1158 EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
1159 EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
1160 EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
1161 EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
1162 EXPORT_SYMBOL(snd_emu8000_update_equalizer);
1163