• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/sound/isa/sb/
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 */
47void 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 */
60unsigned 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 */
75void 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 */
89unsigned 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
109snd_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 */
133static void __devinit
134snd_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 */
145static void __devinit
146snd_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 */
158static int __devinit
159snd_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 */
184static void __devinit
185init_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 */
225static void __devinit
226init_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 */
237static 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
259static 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
281static 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
303static 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 */
329static void __devinit
330send_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 */
351static void __devinit
352init_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 arbitary 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 */
377static void __devinit
378size_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
460snd_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 */
505static void __devinit
506snd_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
555static 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
570static 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
590snd_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
633struct 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 */
642static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
643static 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
655snd_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
670snd_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
704struct 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 */
711static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
712static 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
763enum { 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
769static 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
782snd_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
798snd_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 */
824static 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
833static 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
841static 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
862static 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
872static 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 */
885static 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
894static 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
902static 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
929static 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
939static 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 */
952static 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
961static 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
969static 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
991static 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
1001static 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
1012static 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 */
1024static int __devinit
1025snd_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 */
1055static 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 */
1066static 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 */
1075int __devinit
1076snd_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) && \
1133	defined(CONFIG_SND_SEQUENCER_MODULE))
1134	if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
1135			       sizeof(struct snd_emu8000*), &awe) >= 0) {
1136		strcpy(awe->name, "EMU-8000");
1137		*(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
1138	}
1139#else
1140	awe = NULL;
1141#endif
1142	if (awe_ret)
1143		*awe_ret = awe;
1144
1145	return 0;
1146}
1147
1148
1149/*
1150 * exported stuff
1151 */
1152
1153EXPORT_SYMBOL(snd_emu8000_poke);
1154EXPORT_SYMBOL(snd_emu8000_peek);
1155EXPORT_SYMBOL(snd_emu8000_poke_dw);
1156EXPORT_SYMBOL(snd_emu8000_peek_dw);
1157EXPORT_SYMBOL(snd_emu8000_dma_chan);
1158EXPORT_SYMBOL(snd_emu8000_init_fm);
1159EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
1160EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
1161EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
1162EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
1163EXPORT_SYMBOL(snd_emu8000_update_equalizer);
1164