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