OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [sound/] [isa/] [sb/] [emu8000.c] - Blame information for rev 3

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.