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