1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4 * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
5 * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
6 *
7 * Routines for control of EMU8000 chip
8 */
9
10#include <linux/wait.h>
11#include <linux/sched/signal.h>
12#include <linux/slab.h>
13#include <linux/ioport.h>
14#include <linux/export.h>
15#include <linux/delay.h>
16#include <linux/io.h>
17#include <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 */
36void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
37{
38 guard(spinlock_irqsave)(l: &emu->reg_lock);
39 if (reg != emu->last_reg) {
40 outw(value: (unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
41 emu->last_reg = reg;
42 }
43 outw(value: (unsigned short)val, port); /* Send data */
44}
45
46/* Read a word */
47unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
48{
49 guard(spinlock_irqsave)(l: &emu->reg_lock);
50 if (reg != emu->last_reg) {
51 outw(value: (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 */
58void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
59{
60 guard(spinlock_irqsave)(l: &emu->reg_lock);
61 if (reg != emu->last_reg) {
62 outw(value: (unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
63 emu->last_reg = reg;
64 }
65 outw(value: (unsigned short)val, port); /* Send low word of data */
66 outw(value: (unsigned short)(val>>16), port: port+2); /* Send high word of data */
67}
68
69/* Read a double word */
70unsigned 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)(l: &emu->reg_lock);
75 if (reg != emu->last_reg) {
76 outw(value: (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: port+2) << 16);
81}
82
83/*
84 * Set up / close a channel to be used for DMA.
85 */
86/*exported*/ void
87snd_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 */
111static void
112snd_emu8000_read_wait(struct snd_emu8000 *emu)
113{
114 while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
115 schedule_timeout_interruptible(timeout: 1);
116 if (signal_pending(current))
117 break;
118 }
119}
120
121/*
122 */
123static void
124snd_emu8000_write_wait(struct snd_emu8000 *emu)
125{
126 while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
127 schedule_timeout_interruptible(timeout: 1);
128 if (signal_pending(current))
129 break;
130 }
131}
132
133/*
134 * detect a card at the given port
135 */
136static int
137snd_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 */
162static void
163init_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 */
203static void
204init_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 */
215static 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
237static 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
259static 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
281static 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 */
307static void
308send_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 */
329static void
330init_arrays(struct snd_emu8000 *emu)
331{
332 send_array(emu, data: init1, ARRAY_SIZE(init1)/4);
333
334 msleep(msecs: (1024 * 1000) / 44100); /* wait for 1024 clocks */
335 send_array(emu, data: init2, ARRAY_SIZE(init2)/4);
336 send_array(emu, data: 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, data: 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 */
355static void
356size_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, ch: 0, EMU8000_RAM_WRITE);
367 snd_emu8000_dma_chan(emu, ch: 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
421skip_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(timeout: 1);
427 if (signal_pending(current))
428 break;
429 }
430 snd_emu8000_dma_chan(emu, ch: 0, EMU8000_RAM_CLOSE);
431 snd_emu8000_dma_chan(emu, ch: 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
446snd_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)), val: 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)), val: 0x4828);
476 /* this is really odd part.. */
477 outb(value: 0x3C, EMU8000_PTR(emu));
478 outb(value: 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 */
489static void
490snd_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
539static 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
554static 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
574snd_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
617struct 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 */
626static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
627static 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
639snd_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(to: &rec, from: buf, n: sizeof(rec)))
647 return -EFAULT;
648 chorus_parm[mode] = rec;
649 chorus_defined[mode] = 1;
650 return 0;
651}
652
653/*exported*/ void
654snd_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
688struct 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 */
695static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
696static 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
747enum { 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
753static 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
766snd_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(to: &rec, from: buf, n: sizeof(rec)))
775 return -EFAULT;
776 reverb_parm[mode] = rec;
777 reverb_defined[mode] = 1;
778 return 0;
779}
780
781/*exported*/ void
782snd_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, reg: reverb_cmds[i].cmd, val: reverb_parm[effect].parms[i]);
797 }
798}
799
800
801/*----------------------------------------------------------------
802 * mixer interface
803 *----------------------------------------------------------------*/
804
805/*
806 * bass/treble
807 */
808static 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
817static 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
825static 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
845static 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
855static 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 */
868static 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
877static 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
885static 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
911static 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
921static 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 */
934static 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
943static 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
951static 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
972static 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
982static 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
993static 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 */
1005static int
1006snd_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(kcontrolnew: mixer_defs[i], private_data: emu);
1019 err = snd_ctl_add(card, kcontrol: 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, kcontrol: emu->controls[i]);
1029 return err;
1030}
1031
1032/*
1033 * initialize and register emu8000 synth device.
1034 */
1035int
1036snd_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(dev: card->dev, size: 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(emu: hw) < 0)
1075 return -ENODEV;
1076
1077 snd_emu8000_init_hw(emu: hw);
1078 err = snd_emu8000_create_mixer(card, emu: hw);
1079 if (err < 0)
1080 return err;
1081#if IS_ENABLED(CONFIG_SND_SEQUENCER)
1082 if (snd_seq_device_new(card, device: index, SNDRV_SEQ_DEV_ID_EMU8000,
1083 argsize: sizeof(struct snd_emu8000*), result: &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
1101EXPORT_SYMBOL(snd_emu8000_poke);
1102EXPORT_SYMBOL(snd_emu8000_peek);
1103EXPORT_SYMBOL(snd_emu8000_poke_dw);
1104EXPORT_SYMBOL(snd_emu8000_peek_dw);
1105EXPORT_SYMBOL(snd_emu8000_dma_chan);
1106EXPORT_SYMBOL(snd_emu8000_init_fm);
1107EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
1108EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
1109EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
1110EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
1111EXPORT_SYMBOL(snd_emu8000_update_equalizer);
1112

source code of linux/sound/isa/sb/emu8000.c