~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/isa/sb/emu8000.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php