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