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>
6 * Routines for control of EMU8000 chip
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.
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.
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
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 <sound/core.h>
29 #include <sound/emu8000.h>
30 #include <sound/emu8000_reg.h>
32 #include <asm/uaccess.h>
33 #include <linux/init.h>
34 #include <sound/control.h>
35 #include <sound/initval.h>
38 * emu8000 register controls
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.
47 void snd_emu8000_poke(emu8000_t *emu, unsigned int port, unsigned int reg, unsigned int val)
50 spin_lock_irqsave(&emu->reg_lock, flags);
51 if (reg != emu->last_reg) {
52 outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
55 outw((unsigned short)val, port); /* Send data */
56 spin_unlock_irqrestore(&emu->reg_lock, flags);
60 unsigned short snd_emu8000_peek(emu8000_t *emu, unsigned int port, unsigned int reg)
64 spin_lock_irqsave(&emu->reg_lock, flags);
65 if (reg != emu->last_reg) {
66 outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
69 res = inw(port); /* Read data */
70 spin_unlock_irqrestore(&emu->reg_lock, flags);
74 /* Write a double word */
75 void snd_emu8000_poke_dw(emu8000_t *emu, unsigned int port, unsigned int reg, unsigned int val)
78 spin_lock_irqsave(&emu->reg_lock, flags);
79 if (reg != emu->last_reg) {
80 outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
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);
88 /* Read a double word */
89 unsigned int snd_emu8000_peek_dw(emu8000_t *emu, unsigned int port, unsigned int reg)
94 spin_lock_irqsave(&emu->reg_lock, flags);
95 if (reg != emu->last_reg) {
96 outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
99 low = inw(port); /* Read low word of data */
100 res = low + (inw(port+2) << 16);
101 spin_unlock_irqrestore(&emu->reg_lock, flags);
106 * Set up / close a channel to be used for DMA.
109 snd_emu8000_dma_chan(emu8000_t *emu, int ch, int mode)
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);
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);
128 EMU8000_CCCA_WRITE(emu, ch, 0x04000000 | right_bit);
134 snd_emu8000_read_wait(emu8000_t *emu)
136 while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
137 set_current_state(TASK_INTERRUPTIBLE);
139 if (signal_pending(current))
147 snd_emu8000_write_wait(emu8000_t *emu)
149 while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
150 set_current_state(TASK_INTERRUPTIBLE);
152 if (signal_pending(current))
158 * detect a card at the given port
161 snd_emu8000_detect(emu8000_t *emu)
164 EMU8000_HWCF1_WRITE(emu, 0x0059);
165 EMU8000_HWCF2_WRITE(emu, 0x0020);
166 EMU8000_HWCF3_WRITE(emu, 0x0000);
167 /* Check for a recognisable emu8000 */
169 if ((EMU8000_U1_READ(emu) & 0x000f) != 0x000c)
172 if ((EMU8000_HWCF1_READ(emu) & 0x007e) != 0x0058)
174 if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003)
177 snd_printdd("EMU8000 [0x%lx]: Synth chip found\n",
184 * intiailize audio channels
187 init_audio(emu8000_t *emu)
191 /* turn off envelope engines */
192 for (ch = 0; ch < EMU8000_CHANNELS; ch++)
193 EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
195 /* reset all other parameters to zero */
196 for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
197 EMU8000_ENVVOL_WRITE(emu, ch, 0);
198 EMU8000_ENVVAL_WRITE(emu, ch, 0);
199 EMU8000_DCYSUS_WRITE(emu, ch, 0);
200 EMU8000_ATKHLDV_WRITE(emu, ch, 0);
201 EMU8000_LFO1VAL_WRITE(emu, ch, 0);
202 EMU8000_ATKHLD_WRITE(emu, ch, 0);
203 EMU8000_LFO2VAL_WRITE(emu, ch, 0);
204 EMU8000_IP_WRITE(emu, ch, 0);
205 EMU8000_IFATN_WRITE(emu, ch, 0);
206 EMU8000_PEFE_WRITE(emu, ch, 0);
207 EMU8000_FMMOD_WRITE(emu, ch, 0);
208 EMU8000_TREMFRQ_WRITE(emu, ch, 0);
209 EMU8000_FM2FRQ2_WRITE(emu, ch, 0);
210 EMU8000_PTRX_WRITE(emu, ch, 0);
211 EMU8000_VTFT_WRITE(emu, ch, 0);
212 EMU8000_PSST_WRITE(emu, ch, 0);
213 EMU8000_CSL_WRITE(emu, ch, 0);
214 EMU8000_CCCA_WRITE(emu, ch, 0);
217 for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
218 EMU8000_CPF_WRITE(emu, ch, 0);
219 EMU8000_CVCF_WRITE(emu, ch, 0);
225 * initialize DMA address
228 init_dma(emu8000_t *emu)
230 EMU8000_SMALR_WRITE(emu, 0);
231 EMU8000_SMARR_WRITE(emu, 0);
232 EMU8000_SMALW_WRITE(emu, 0);
233 EMU8000_SMARW_WRITE(emu, 0);
237 * initialization arrays; from ADIP
239 static unsigned short init1[128] /*__devinitdata*/ = {
240 0x03ff, 0x0030, 0x07ff, 0x0130, 0x0bff, 0x0230, 0x0fff, 0x0330,
241 0x13ff, 0x0430, 0x17ff, 0x0530, 0x1bff, 0x0630, 0x1fff, 0x0730,
242 0x23ff, 0x0830, 0x27ff, 0x0930, 0x2bff, 0x0a30, 0x2fff, 0x0b30,
243 0x33ff, 0x0c30, 0x37ff, 0x0d30, 0x3bff, 0x0e30, 0x3fff, 0x0f30,
245 0x43ff, 0x0030, 0x47ff, 0x0130, 0x4bff, 0x0230, 0x4fff, 0x0330,
246 0x53ff, 0x0430, 0x57ff, 0x0530, 0x5bff, 0x0630, 0x5fff, 0x0730,
247 0x63ff, 0x0830, 0x67ff, 0x0930, 0x6bff, 0x0a30, 0x6fff, 0x0b30,
248 0x73ff, 0x0c30, 0x77ff, 0x0d30, 0x7bff, 0x0e30, 0x7fff, 0x0f30,
250 0x83ff, 0x0030, 0x87ff, 0x0130, 0x8bff, 0x0230, 0x8fff, 0x0330,
251 0x93ff, 0x0430, 0x97ff, 0x0530, 0x9bff, 0x0630, 0x9fff, 0x0730,
252 0xa3ff, 0x0830, 0xa7ff, 0x0930, 0xabff, 0x0a30, 0xafff, 0x0b30,
253 0xb3ff, 0x0c30, 0xb7ff, 0x0d30, 0xbbff, 0x0e30, 0xbfff, 0x0f30,
255 0xc3ff, 0x0030, 0xc7ff, 0x0130, 0xcbff, 0x0230, 0xcfff, 0x0330,
256 0xd3ff, 0x0430, 0xd7ff, 0x0530, 0xdbff, 0x0630, 0xdfff, 0x0730,
257 0xe3ff, 0x0830, 0xe7ff, 0x0930, 0xebff, 0x0a30, 0xefff, 0x0b30,
258 0xf3ff, 0x0c30, 0xf7ff, 0x0d30, 0xfbff, 0x0e30, 0xffff, 0x0f30,
261 static unsigned short init2[128] /*__devinitdata*/ = {
262 0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
263 0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
264 0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
265 0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
267 0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
268 0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
269 0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
270 0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
272 0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
273 0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
274 0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
275 0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
277 0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
278 0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
279 0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
280 0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
283 static unsigned short init3[128] /*__devinitdata*/ = {
284 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
285 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
286 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
287 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
289 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
290 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
291 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
292 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
294 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
295 0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
296 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
297 0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
299 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
300 0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
301 0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
302 0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
305 static unsigned short init4[128] /*__devinitdata*/ = {
306 0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
307 0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
308 0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
309 0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
311 0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
312 0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
313 0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
314 0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
316 0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
317 0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
318 0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
319 0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
321 0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
322 0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
323 0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
324 0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
327 /* send an initialization array
328 * Taken from the oss driver, not obvious from the doc how this
332 send_array(emu8000_t *emu, unsigned short *data, int size)
338 for (i = 0; i < size; i++, p++)
339 EMU8000_INIT1_WRITE(emu, i, *p);
340 for (i = 0; i < size; i++, p++)
341 EMU8000_INIT2_WRITE(emu, i, *p);
342 for (i = 0; i < size; i++, p++)
343 EMU8000_INIT3_WRITE(emu, i, *p);
344 for (i = 0; i < size; i++, p++)
345 EMU8000_INIT4_WRITE(emu, i, *p);
348 #define NELEM(arr) (sizeof(arr)/sizeof((arr)[0]))
352 * Send initialization arrays to start up, this just follows the
353 * initialisation sequence in the adip.
356 init_arrays(emu8000_t *emu)
358 send_array(emu, init1, NELEM(init1)/4);
360 set_current_state(TASK_INTERRUPTIBLE);
361 schedule_timeout((HZ * (44099 + 1024)) / 44100); /* wait for 1024 clocks */
362 send_array(emu, init2, NELEM(init2)/4);
363 send_array(emu, init3, NELEM(init3)/4);
365 EMU8000_HWCF4_WRITE(emu, 0);
366 EMU8000_HWCF5_WRITE(emu, 0x83);
367 EMU8000_HWCF6_WRITE(emu, 0x8000);
369 send_array(emu, init4, NELEM(init4)/4);
373 #define UNIQUE_ID1 0xa5b9
374 #define UNIQUE_ID2 0x9d53
377 * Size the onboard memory.
378 * This is written so as not to need arbitary delays after the write. It
379 * seems that the only way to do this is to use the one channel and keep
380 * reallocating between read and write.
383 size_dram(emu8000_t *emu)
387 if (emu->dram_checked)
392 /* write out a magic number */
393 snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);
394 snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ);
395 EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET);
396 EMU8000_SMLD_WRITE(emu, UNIQUE_ID1);
397 snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */
399 while (size < EMU8000_MAX_DRAM) {
401 size += 512 * 1024; /* increment 512kbytes */
403 /* Write a unique data on the test address.
404 * if the address is out of range, the data is written on
405 * 0x200000(=EMU8000_DRAM_OFFSET). Then the id word is
406 * changed by this data.
408 /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/
409 EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
410 EMU8000_SMLD_WRITE(emu, UNIQUE_ID2);
411 snd_emu8000_write_wait(emu);
414 * read the data on the just written DRAM address
415 * if not the same then we have reached the end of ram.
417 /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/
418 EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
419 /*snd_emu8000_read_wait(emu);*/
420 EMU8000_SMLD_READ(emu); /* discard stale data */
421 if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
422 break; /* we must have wrapped around */
424 snd_emu8000_read_wait(emu);
427 * If it is the same it could be that the address just
428 * wraps back to the beginning; so check to see if the
429 * initial value has been overwritten.
431 EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
432 EMU8000_SMLD_READ(emu); /* discard stale data */
433 if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
434 break; /* we must have wrapped around */
435 snd_emu8000_read_wait(emu);
438 /* wait until FULL bit in SMAxW register is false */
439 for (i = 0; i < 10000; i++) {
440 if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0)
442 set_current_state(TASK_INTERRUPTIBLE);
444 if (signal_pending(current))
447 snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE);
448 snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE);
450 snd_printdd("EMU8000 [0x%lx]: %d Kb on-board memory detected\n",
451 emu->port1, size/1024);
453 emu->mem_size = size;
454 emu->dram_checked = 1;
459 * Initiailise the FM section. You have to do this to use sample RAM
460 * and therefore lose 2 voices.
463 snd_emu8000_init_fm(emu8000_t *emu)
467 /* Initialize the last two channels for DRAM refresh and producing
468 the reverb and chorus effects for Yamaha OPL-3 synthesizer */
470 /* 31: FM left channel, 0xffffe0-0xffffe8 */
471 EMU8000_DCYSUSV_WRITE(emu, 30, 0x80);
472 EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */
473 EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24));
474 EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8));
475 EMU8000_CPF_WRITE(emu, 30, 0);
476 EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3);
478 /* 32: FM right channel, 0xfffff0-0xfffff8 */
479 EMU8000_DCYSUSV_WRITE(emu, 31, 0x80);
480 EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */
481 EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24));
482 EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8));
483 EMU8000_CPF_WRITE(emu, 31, 0x8000);
484 EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3);
486 snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0);
488 spin_lock_irqsave(&emu->reg_lock, flags);
489 while (!(inw(EMU8000_PTR(emu)) & 0x1000))
491 while ((inw(EMU8000_PTR(emu)) & 0x1000))
493 spin_unlock_irqrestore(&emu->reg_lock, flags);
494 snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828);
495 /* this is really odd part.. */
496 outb(0x3C, EMU8000_PTR(emu));
497 outb(0, EMU8000_DATA1(emu));
499 /* skew volume & cutoff */
500 EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF);
501 EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF);
506 * The main initialization routine.
509 snd_emu8000_init_hw(emu8000_t *emu)
513 emu->last_reg = 0xffff; /* reset the last register index */
515 /* initialize hardware configuration */
516 EMU8000_HWCF1_WRITE(emu, 0x0059);
517 EMU8000_HWCF2_WRITE(emu, 0x0020);
519 /* disable audio; this seems to reduce a clicking noise a bit.. */
520 EMU8000_HWCF3_WRITE(emu, 0);
522 /* initialize audio channels */
528 /* initialize init arrays */
532 * Initialize the FM section of the AWE32, this is needed
533 * for DRAM refresh as well
535 snd_emu8000_init_fm(emu);
537 /* terminate all voices */
538 for (i = 0; i < EMU8000_DRAM_VOICES; i++)
539 EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F);
541 /* check DRAM memory size */
545 EMU8000_HWCF3_WRITE(emu, 0x4);
547 /* set equzlier, chorus and reverb modes */
548 snd_emu8000_update_equalizer(emu);
549 snd_emu8000_update_chorus_mode(emu);
550 snd_emu8000_update_reverb_mode(emu);
554 /*----------------------------------------------------------------
555 * Bass/Treble Equalizer
556 *----------------------------------------------------------------*/
558 static unsigned short bass_parm[12][3] = {
559 {0xD26A, 0xD36A, 0x0000}, /* -12 dB */
560 {0xD25B, 0xD35B, 0x0000}, /* -8 */
561 {0xD24C, 0xD34C, 0x0000}, /* -6 */
562 {0xD23D, 0xD33D, 0x0000}, /* -4 */
563 {0xD21F, 0xD31F, 0x0000}, /* -2 */
564 {0xC208, 0xC308, 0x0001}, /* 0 (HW default) */
565 {0xC219, 0xC319, 0x0001}, /* +2 */
566 {0xC22A, 0xC32A, 0x0001}, /* +4 */
567 {0xC24C, 0xC34C, 0x0001}, /* +6 */
568 {0xC26E, 0xC36E, 0x0001}, /* +8 */
569 {0xC248, 0xC384, 0x0002}, /* +10 */
570 {0xC26A, 0xC36A, 0x0002}, /* +12 dB */
573 static unsigned short treble_parm[12][9] = {
574 {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
575 {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
576 {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
577 {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
578 {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
579 {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
580 {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
581 {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
582 {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
583 {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
584 {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
585 {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002} /* +12 dB */
590 * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
593 snd_emu8000_update_equalizer(emu8000_t *emu)
596 int bass = emu->bass_level;
597 int treble = emu->treble_level;
599 if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
601 EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]);
602 EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]);
603 EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]);
604 EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]);
605 EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]);
606 EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]);
607 EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]);
608 EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]);
609 EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]);
610 EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]);
611 w = bass_parm[bass][2] + treble_parm[treble][8];
612 EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262));
613 EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362));
617 /*----------------------------------------------------------------
618 * Chorus mode control
619 *----------------------------------------------------------------*/
622 * chorus mode parameters
624 #define SNDRV_EMU8000_CHORUS_1 0
625 #define SNDRV_EMU8000_CHORUS_2 1
626 #define SNDRV_EMU8000_CHORUS_3 2
627 #define SNDRV_EMU8000_CHORUS_4 3
628 #define SNDRV_EMU8000_CHORUS_FEEDBACK 4
629 #define SNDRV_EMU8000_CHORUS_FLANGER 5
630 #define SNDRV_EMU8000_CHORUS_SHORTDELAY 6
631 #define SNDRV_EMU8000_CHORUS_SHORTDELAY2 7
632 #define SNDRV_EMU8000_CHORUS_PREDEFINED 8
633 /* user can define chorus modes up to 32 */
634 #define SNDRV_EMU8000_CHORUS_NUMBERS 32
636 typedef struct soundfont_chorus_fx_t {
637 unsigned short feedback; /* feedback level (0xE600-0xE6FF) */
638 unsigned short delay_offset; /* delay (0-0x0DA3) [1/44100 sec] */
639 unsigned short lfo_depth; /* LFO depth (0xBC00-0xBCFF) */
640 unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
641 unsigned int lfo_freq; /* LFO freq LFO freq (0-0xFFFFFFFF) */
642 } soundfont_chorus_fx_t;
644 /* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
645 static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
646 static soundfont_chorus_fx_t chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
647 {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
648 {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
649 {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
650 {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
651 {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
652 {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
653 {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */
654 {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */
658 snd_emu8000_load_chorus_fx(emu8000_t *emu, int mode, const void __user *buf, long len)
660 soundfont_chorus_fx_t rec;
661 if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) {
662 snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode);
665 if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
667 chorus_parm[mode] = rec;
668 chorus_defined[mode] = 1;
673 snd_emu8000_update_chorus_mode(emu8000_t *emu)
675 int effect = emu->chorus_mode;
676 if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS ||
677 (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect]))
679 EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback);
680 EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset);
681 EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth);
682 EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay);
683 EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq);
684 EMU8000_HWCF6_WRITE(emu, 0x8000);
685 EMU8000_HWCF7_WRITE(emu, 0x0000);
688 /*----------------------------------------------------------------
689 * Reverb mode control
690 *----------------------------------------------------------------*/
693 * reverb mode parameters
695 #define SNDRV_EMU8000_REVERB_ROOM1 0
696 #define SNDRV_EMU8000_REVERB_ROOM2 1
697 #define SNDRV_EMU8000_REVERB_ROOM3 2
698 #define SNDRV_EMU8000_REVERB_HALL1 3
699 #define SNDRV_EMU8000_REVERB_HALL2 4
700 #define SNDRV_EMU8000_REVERB_PLATE 5
701 #define SNDRV_EMU8000_REVERB_DELAY 6
702 #define SNDRV_EMU8000_REVERB_PANNINGDELAY 7
703 #define SNDRV_EMU8000_REVERB_PREDEFINED 8
704 /* user can define reverb modes up to 32 */
705 #define SNDRV_EMU8000_REVERB_NUMBERS 32
707 typedef struct soundfont_reverb_fx_t {
708 unsigned short parms[28];
709 } soundfont_reverb_fx_t;
711 /* reverb mode settings; write the following 28 data of 16 bit length
712 * on the corresponding ports in the reverb_cmds array
714 static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
715 static soundfont_reverb_fx_t reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
717 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
718 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
719 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
720 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
723 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
724 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
725 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
726 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
729 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
730 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
731 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
732 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
735 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
736 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
737 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
738 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
741 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
742 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
743 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
744 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
747 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
748 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
749 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
750 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
753 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
754 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
755 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
756 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
758 {{ /* panning delay */
759 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
760 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
761 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
762 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
766 enum { DATA1, DATA2 };
767 #define AWE_INIT1(c) EMU8000_CMD(2,c), DATA1
768 #define AWE_INIT2(c) EMU8000_CMD(2,c), DATA2
769 #define AWE_INIT3(c) EMU8000_CMD(3,c), DATA1
770 #define AWE_INIT4(c) EMU8000_CMD(3,c), DATA2
772 static struct reverb_cmd_pair {
773 unsigned short cmd, port;
774 } reverb_cmds[28] = {
775 {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
776 {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
777 {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
778 {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
779 {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
780 {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
781 {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
785 snd_emu8000_load_reverb_fx(emu8000_t *emu, int mode, const void __user *buf, long len)
787 soundfont_reverb_fx_t rec;
789 if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) {
790 snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode);
793 if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
795 reverb_parm[mode] = rec;
796 reverb_defined[mode] = 1;
801 snd_emu8000_update_reverb_mode(emu8000_t *emu)
803 int effect = emu->reverb_mode;
806 if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS ||
807 (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect]))
809 for (i = 0; i < 28; i++) {
811 if (reverb_cmds[i].port == DATA1)
812 port = EMU8000_DATA1(emu);
814 port = EMU8000_DATA2(emu);
815 snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]);
820 /*----------------------------------------------------------------
822 *----------------------------------------------------------------*/
824 #define chip_t emu8000_t
829 static int mixer_bass_treble_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
831 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
833 uinfo->value.integer.min = 0;
834 uinfo->value.integer.max = 11;
838 static int mixer_bass_treble_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
840 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
842 ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level;
846 static int mixer_bass_treble_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
848 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
853 val1 = ucontrol->value.integer.value[0] % 12;
854 spin_lock_irqsave(&emu->control_lock, flags);
855 if (kcontrol->private_value) {
856 change = val1 != emu->treble_level;
857 emu->treble_level = val1;
859 change = val1 != emu->bass_level;
860 emu->bass_level = val1;
862 spin_unlock_irqrestore(&emu->control_lock, flags);
863 snd_emu8000_update_equalizer(emu);
867 static snd_kcontrol_new_t mixer_bass_control =
869 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
870 .name = "Synth Tone Control - Bass",
871 .info = mixer_bass_treble_info,
872 .get = mixer_bass_treble_get,
873 .put = mixer_bass_treble_put,
877 static snd_kcontrol_new_t mixer_treble_control =
879 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
880 .name = "Synth Tone Control - Treble",
881 .info = mixer_bass_treble_info,
882 .get = mixer_bass_treble_get,
883 .put = mixer_bass_treble_put,
890 static int mixer_chorus_reverb_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
892 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
894 uinfo->value.integer.min = 0;
895 uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1);
899 static int mixer_chorus_reverb_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
901 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
903 ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode;
907 static int mixer_chorus_reverb_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
909 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
914 spin_lock_irqsave(&emu->control_lock, flags);
915 if (kcontrol->private_value) {
916 val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS;
917 change = val1 != emu->chorus_mode;
918 emu->chorus_mode = val1;
920 val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS;
921 change = val1 != emu->reverb_mode;
922 emu->reverb_mode = val1;
924 spin_unlock_irqrestore(&emu->control_lock, flags);
926 if (kcontrol->private_value)
927 snd_emu8000_update_chorus_mode(emu);
929 snd_emu8000_update_reverb_mode(emu);
934 static snd_kcontrol_new_t mixer_chorus_mode_control =
936 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
937 .name = "Chorus Mode",
938 .info = mixer_chorus_reverb_info,
939 .get = mixer_chorus_reverb_get,
940 .put = mixer_chorus_reverb_put,
944 static snd_kcontrol_new_t mixer_reverb_mode_control =
946 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
947 .name = "Reverb Mode",
948 .info = mixer_chorus_reverb_info,
949 .get = mixer_chorus_reverb_get,
950 .put = mixer_chorus_reverb_put,
955 * FM OPL3 chorus/reverb depth
957 static int mixer_fm_depth_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
959 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
961 uinfo->value.integer.min = 0;
962 uinfo->value.integer.max = 255;
966 static int mixer_fm_depth_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
968 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
970 ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth;
974 static int mixer_fm_depth_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
976 emu8000_t *emu = snd_kcontrol_chip(kcontrol);
981 val1 = ucontrol->value.integer.value[0] % 256;
982 spin_lock_irqsave(&emu->control_lock, flags);
983 if (kcontrol->private_value) {
984 change = val1 != emu->fm_chorus_depth;
985 emu->fm_chorus_depth = val1;
987 change = val1 != emu->fm_reverb_depth;
988 emu->fm_reverb_depth = val1;
990 spin_unlock_irqrestore(&emu->control_lock, flags);
992 snd_emu8000_init_fm(emu);
996 static snd_kcontrol_new_t mixer_fm_chorus_depth_control =
998 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
999 .name = "FM Chorus Depth",
1000 .info = mixer_fm_depth_info,
1001 .get = mixer_fm_depth_get,
1002 .put = mixer_fm_depth_put,
1006 static snd_kcontrol_new_t mixer_fm_reverb_depth_control =
1008 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1009 .name = "FM Reverb Depth",
1010 .info = mixer_fm_depth_info,
1011 .get = mixer_fm_depth_get,
1012 .put = mixer_fm_depth_put,
1017 static snd_kcontrol_new_t *mixer_defs[EMU8000_NUM_CONTROLS] = {
1018 &mixer_bass_control,
1019 &mixer_treble_control,
1020 &mixer_chorus_mode_control,
1021 &mixer_reverb_mode_control,
1022 &mixer_fm_chorus_depth_control,
1023 &mixer_fm_reverb_depth_control,
1027 * create and attach mixer elements for WaveTable treble/bass controls
1030 snd_emu8000_create_mixer(snd_card_t *card, emu8000_t *emu)
1034 snd_assert(emu != NULL && card != NULL, return -EINVAL);
1036 spin_lock_init(&emu->control_lock);
1038 memset(emu->controls, 0, sizeof(emu->controls));
1039 for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1040 if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0)
1046 for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1047 down_write(&card->controls_rwsem);
1048 if (emu->controls[i])
1049 snd_ctl_remove(card, emu->controls[i]);
1050 up_write(&card->controls_rwsem);
1059 static int snd_emu8000_free(emu8000_t *hw)
1061 if (hw->res_port1) {
1062 release_resource(hw->res_port1);
1063 kfree_nocheck(hw->res_port1);
1065 if (hw->res_port2) {
1066 release_resource(hw->res_port2);
1067 kfree_nocheck(hw->res_port2);
1069 if (hw->res_port3) {
1070 release_resource(hw->res_port3);
1071 kfree_nocheck(hw->res_port3);
1073 snd_magic_kfree(hw);
1079 static int snd_emu8000_dev_free(snd_device_t *device)
1081 emu8000_t *hw = snd_magic_cast(emu8000_t, device->device_data, return -ENXIO);
1082 return snd_emu8000_free(hw);
1086 * initialize and register emu8000 synth device.
1089 snd_emu8000_new(snd_card_t *card, int index, long port, int seq_ports, snd_seq_device_t **awe_ret)
1091 snd_seq_device_t *awe;
1094 static snd_device_ops_t ops = {
1095 .dev_free = snd_emu8000_dev_free,
1104 hw = snd_magic_kcalloc(emu8000_t, 0, GFP_KERNEL);
1107 spin_lock_init(&hw->reg_lock);
1110 hw->port2 = port + 0x400;
1111 hw->port3 = port + 0x800;
1112 if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) ||
1113 !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) ||
1114 !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) {
1115 snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
1116 snd_emu8000_free(hw);
1121 hw->seq_ports = seq_ports;
1123 hw->treble_level = 9;
1124 hw->chorus_mode = 2;
1125 hw->reverb_mode = 4;
1126 hw->fm_chorus_depth = 0;
1127 hw->fm_reverb_depth = 0;
1129 if (snd_emu8000_detect(hw) < 0) {
1130 snd_emu8000_free(hw);
1134 snd_emu8000_init_hw(hw);
1135 if ((err = snd_emu8000_create_mixer(card, hw)) < 0) {
1136 snd_emu8000_free(hw);
1140 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, hw, &ops)) < 0) {
1141 snd_emu8000_free(hw);
1144 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
1145 if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
1146 sizeof(emu8000_t*), &awe) >= 0) {
1147 strcpy(awe->name, "EMU-8000");
1148 *(emu8000_t**)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
1164 EXPORT_SYMBOL(snd_emu8000_poke);
1165 EXPORT_SYMBOL(snd_emu8000_peek);
1166 EXPORT_SYMBOL(snd_emu8000_poke_dw);
1167 EXPORT_SYMBOL(snd_emu8000_peek_dw);
1168 EXPORT_SYMBOL(snd_emu8000_dma_chan);
1169 EXPORT_SYMBOL(snd_emu8000_init_fm);
1170 EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
1171 EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
1172 EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
1173 EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
1174 EXPORT_SYMBOL(snd_emu8000_update_equalizer);