aboutsummaryrefslogtreecommitdiffstats
path: root/sound/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/drivers
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'sound/drivers')
-rw-r--r--sound/drivers/Kconfig98
-rw-r--r--sound/drivers/Makefile17
-rw-r--r--sound/drivers/dummy.c643
-rw-r--r--sound/drivers/mpu401/Makefile12
-rw-r--r--sound/drivers/mpu401/mpu401.c229
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c541
-rw-r--r--sound/drivers/mtpav.c795
-rw-r--r--sound/drivers/opl3/Makefile22
-rw-r--r--sound/drivers/opl3/opl3_drums.c223
-rw-r--r--sound/drivers/opl3/opl3_lib.c558
-rw-r--r--sound/drivers/opl3/opl3_midi.c873
-rw-r--r--sound/drivers/opl3/opl3_oss.c356
-rw-r--r--sound/drivers/opl3/opl3_seq.c314
-rw-r--r--sound/drivers/opl3/opl3_synth.c447
-rw-r--r--sound/drivers/opl3/opl3_voice.h52
-rw-r--r--sound/drivers/opl4/Makefile18
-rw-r--r--sound/drivers/opl4/opl4_lib.c281
-rw-r--r--sound/drivers/opl4/opl4_local.h232
-rw-r--r--sound/drivers/opl4/opl4_mixer.c95
-rw-r--r--sound/drivers/opl4/opl4_proc.c166
-rw-r--r--sound/drivers/opl4/opl4_seq.c223
-rw-r--r--sound/drivers/opl4/opl4_synth.c630
-rw-r--r--sound/drivers/opl4/yrw801.c961
-rw-r--r--sound/drivers/serial-u16550.c990
-rw-r--r--sound/drivers/virmidi.c159
-rw-r--r--sound/drivers/vx/Makefile8
-rw-r--r--sound/drivers/vx/vx_cmd.c109
-rw-r--r--sound/drivers/vx/vx_cmd.h246
-rw-r--r--sound/drivers/vx/vx_core.c837
-rw-r--r--sound/drivers/vx/vx_hwdep.c249
-rw-r--r--sound/drivers/vx/vx_mixer.c1000
-rw-r--r--sound/drivers/vx/vx_pcm.c1312
-rw-r--r--sound/drivers/vx/vx_uer.c321
33 files changed, 13017 insertions, 0 deletions
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
new file mode 100644
index 000000000000..3b2bee19e2c0
--- /dev/null
+++ b/sound/drivers/Kconfig
@@ -0,0 +1,98 @@
1# ALSA generic drivers
2
3menu "Generic devices"
4 depends on SND!=n
5
6
7config SND_MPU401_UART
8 tristate
9 select SND_TIMER
10 select SND_RAWMIDI
11
12config SND_OPL3_LIB
13 tristate
14 select SND_TIMER
15 select SND_HWDEP
16
17config SND_OPL4_LIB
18 tristate
19 select SND_TIMER
20 select SND_HWDEP
21
22config SND_VX_LIB
23 tristate
24 select SND_HWDEP
25 select SND_PCM
26
27
28config SND_DUMMY
29 tristate "Dummy (/dev/null) soundcard"
30 depends on SND
31 select SND_PCM
32 help
33 Say Y here to include the dummy driver. This driver does
34 nothing, but emulates various mixer controls and PCM devices.
35
36 You don't need this unless you're testing the hardware support
37 of programs using the ALSA API.
38
39 To compile this driver as a module, choose M here: the module
40 will be called snd-dummy.
41
42config SND_VIRMIDI
43 tristate "Virtual MIDI soundcard"
44 depends on SND_SEQUENCER
45 select SND_TIMER
46 select SND_RAWMIDI
47 help
48 Say Y here to include the virtual MIDI driver. This driver
49 allows to connect applications using raw MIDI devices to
50 sequencer clients.
51
52 If you don't know what MIDI is, say N here.
53
54 To compile this driver as a module, choose M here: the module
55 will be called snd-virmidi.
56
57config SND_MTPAV
58 tristate "MOTU MidiTimePiece AV multiport MIDI"
59 depends on SND
60 select SND_TIMER
61 select SND_RAWMIDI
62 help
63 To use a MOTU MidiTimePiece AV multiport MIDI adapter
64 connected to the parallel port, say Y here and make sure that
65 the standard parallel port driver isn't used for the port.
66
67 To compile this driver as a module, choose M here: the module
68 will be called snd-mtpav.
69
70config SND_SERIAL_U16550
71 tristate "UART16550 serial MIDI driver"
72 depends on SND
73 select SND_TIMER
74 select SND_RAWMIDI
75 help
76 To include support for MIDI serial port interfaces, say Y here
77 and read <file:Documentation/sound/alsa/serial-u16550.txt>.
78 This driver works with serial UARTs 16550 and better.
79
80 This driver accesses the serial port hardware directly, so
81 make sure that the standard serial driver isn't used or
82 deactivated with setserial before loading this driver.
83
84 To compile this driver as a module, choose M here: the module
85 will be called snd-serial-u16550.
86
87config SND_MPU401
88 tristate "Generic MPU-401 UART driver"
89 depends on SND
90 select SND_MPU401_UART
91 help
92 Say Y here to include support for MIDI ports compatible with
93 the Roland MPU-401 interface in UART mode.
94
95 To compile this driver as a module, choose M here: the module
96 will be called snd-mpu401.
97
98endmenu
diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile
new file mode 100644
index 000000000000..cb98c3d662be
--- /dev/null
+++ b/sound/drivers/Makefile
@@ -0,0 +1,17 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-dummy-objs := dummy.o
7snd-mtpav-objs := mtpav.o
8snd-serial-u16550-objs := serial-u16550.o
9snd-virmidi-objs := virmidi.o
10
11# Toplevel Module Dependency
12obj-$(CONFIG_SND_DUMMY) += snd-dummy.o
13obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o
14obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o
15obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o
16
17obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
new file mode 100644
index 000000000000..a61640cf7ae7
--- /dev/null
+++ b/sound/drivers/dummy.c
@@ -0,0 +1,643 @@
1/*
2 * Dummy soundcard
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include <sound/driver.h>
22#include <linux/init.h>
23#include <linux/jiffies.h>
24#include <linux/slab.h>
25#include <linux/time.h>
26#include <linux/wait.h>
27#include <linux/moduleparam.h>
28#include <sound/core.h>
29#include <sound/control.h>
30#include <sound/pcm.h>
31#include <sound/rawmidi.h>
32#include <sound/initval.h>
33
34MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
35MODULE_DESCRIPTION("Dummy soundcard (/dev/null)");
36MODULE_LICENSE("GPL");
37MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
38
39#define MAX_PCM_DEVICES 4
40#define MAX_PCM_SUBSTREAMS 16
41#define MAX_MIDI_DEVICES 2
42
43#if 0 /* emu10k1 emulation */
44#define MAX_BUFFER_SIZE (128 * 1024)
45static int emu10k1_playback_constraints(snd_pcm_runtime_t *runtime)
46{
47 int err;
48 if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
49 return err;
50 if ((err = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 256, UINT_MAX)) < 0)
51 return err;
52 return 0;
53}
54#define add_playback_constraints emu10k1_playback_constraints
55#endif
56
57#if 0 /* RME9652 emulation */
58#define MAX_BUFFER_SIZE (26 * 64 * 1024)
59#define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE
60#define USE_CHANNELS_MIN 26
61#define USE_CHANNELS_MAX 26
62#define USE_PERIODS_MIN 2
63#define USE_PERIODS_MAX 2
64#endif
65
66#if 0 /* ICE1712 emulation */
67#define MAX_BUFFER_SIZE (256 * 1024)
68#define USE_FORMATS SNDRV_PCM_FMTBIT_S32_LE
69#define USE_CHANNELS_MIN 10
70#define USE_CHANNELS_MAX 10
71#define USE_PERIODS_MIN 1
72#define USE_PERIODS_MAX 1024
73#endif
74
75#if 0 /* UDA1341 emulation */
76#define MAX_BUFFER_SIZE (16380)
77#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE
78#define USE_CHANNELS_MIN 2
79#define USE_CHANNELS_MAX 2
80#define USE_PERIODS_MIN 2
81#define USE_PERIODS_MAX 255
82#endif
83
84#if 0 /* simple AC97 bridge (intel8x0) with 48kHz AC97 only codec */
85#define USE_FORMATS SNDRV_PCM_FMTBIT_S16_LE
86#define USE_CHANNELS_MIN 2
87#define USE_CHANNELS_MAX 2
88#define USE_RATE SNDRV_PCM_RATE_48000
89#define USE_RATE_MIN 48000
90#define USE_RATE_MAX 48000
91#endif
92
93
94/* defaults */
95#ifndef MAX_BUFFER_SIZE
96#define MAX_BUFFER_SIZE (64*1024)
97#endif
98#ifndef USE_FORMATS
99#define USE_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
100#endif
101#ifndef USE_RATE
102#define USE_RATE SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000
103#define USE_RATE_MIN 5500
104#define USE_RATE_MAX 48000
105#endif
106#ifndef USE_CHANNELS_MIN
107#define USE_CHANNELS_MIN 1
108#endif
109#ifndef USE_CHANNELS_MAX
110#define USE_CHANNELS_MAX 2
111#endif
112#ifndef USE_PERIODS_MIN
113#define USE_PERIODS_MIN 1
114#endif
115#ifndef USE_PERIODS_MAX
116#define USE_PERIODS_MAX 1024
117#endif
118#ifndef add_playback_constraints
119#define add_playback_constraints(x) 0
120#endif
121#ifndef add_capture_constraints
122#define add_capture_constraints(x) 0
123#endif
124
125static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
126static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
127static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
128static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
129static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
130//static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
131
132module_param_array(index, int, NULL, 0444);
133MODULE_PARM_DESC(index, "Index value for dummy soundcard.");
134module_param_array(id, charp, NULL, 0444);
135MODULE_PARM_DESC(id, "ID string for dummy soundcard.");
136module_param_array(enable, bool, NULL, 0444);
137MODULE_PARM_DESC(enable, "Enable this dummy soundcard.");
138module_param_array(pcm_devs, int, NULL, 0444);
139MODULE_PARM_DESC(pcm_devs, "PCM devices # (0-4) for dummy driver.");
140module_param_array(pcm_substreams, int, NULL, 0444);
141MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-16) for dummy driver.");
142//module_param_array(midi_devs, int, NULL, 0444);
143//MODULE_PARM_DESC(midi_devs, "MIDI devices # (0-2) for dummy driver.");
144
145#define MIXER_ADDR_MASTER 0
146#define MIXER_ADDR_LINE 1
147#define MIXER_ADDR_MIC 2
148#define MIXER_ADDR_SYNTH 3
149#define MIXER_ADDR_CD 4
150#define MIXER_ADDR_LAST 4
151
152typedef struct snd_card_dummy {
153 snd_card_t *card;
154 spinlock_t mixer_lock;
155 int mixer_volume[MIXER_ADDR_LAST+1][2];
156 int capture_source[MIXER_ADDR_LAST+1][2];
157} snd_card_dummy_t;
158
159typedef struct snd_card_dummy_pcm {
160 snd_card_dummy_t *dummy;
161 spinlock_t lock;
162 struct timer_list timer;
163 unsigned int pcm_size;
164 unsigned int pcm_count;
165 unsigned int pcm_bps; /* bytes per second */
166 unsigned int pcm_jiffie; /* bytes per one jiffie */
167 unsigned int pcm_irq_pos; /* IRQ position */
168 unsigned int pcm_buf_pos; /* position in buffer */
169 snd_pcm_substream_t *substream;
170} snd_card_dummy_pcm_t;
171
172static snd_card_t *snd_dummy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
173
174
175static void snd_card_dummy_pcm_timer_start(snd_pcm_substream_t * substream)
176{
177 snd_pcm_runtime_t *runtime = substream->runtime;
178 snd_card_dummy_pcm_t *dpcm = runtime->private_data;
179
180 dpcm->timer.expires = 1 + jiffies;
181 add_timer(&dpcm->timer);
182}
183
184static void snd_card_dummy_pcm_timer_stop(snd_pcm_substream_t * substream)
185{
186 snd_pcm_runtime_t *runtime = substream->runtime;
187 snd_card_dummy_pcm_t *dpcm = runtime->private_data;
188
189 del_timer(&dpcm->timer);
190}
191
192static int snd_card_dummy_playback_trigger(snd_pcm_substream_t * substream,
193 int cmd)
194{
195 if (cmd == SNDRV_PCM_TRIGGER_START) {
196 snd_card_dummy_pcm_timer_start(substream);
197 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
198 snd_card_dummy_pcm_timer_stop(substream);
199 } else {
200 return -EINVAL;
201 }
202 return 0;
203}
204
205static int snd_card_dummy_capture_trigger(snd_pcm_substream_t * substream,
206 int cmd)
207{
208 if (cmd == SNDRV_PCM_TRIGGER_START) {
209 snd_card_dummy_pcm_timer_start(substream);
210 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
211 snd_card_dummy_pcm_timer_stop(substream);
212 } else {
213 return -EINVAL;
214 }
215 return 0;
216}
217
218static int snd_card_dummy_pcm_prepare(snd_pcm_substream_t * substream)
219{
220 snd_pcm_runtime_t *runtime = substream->runtime;
221 snd_card_dummy_pcm_t *dpcm = runtime->private_data;
222 unsigned int bps;
223
224 bps = runtime->rate * runtime->channels;
225 bps *= snd_pcm_format_width(runtime->format);
226 bps /= 8;
227 if (bps <= 0)
228 return -EINVAL;
229 dpcm->pcm_bps = bps;
230 dpcm->pcm_jiffie = bps / HZ;
231 dpcm->pcm_size = snd_pcm_lib_buffer_bytes(substream);
232 dpcm->pcm_count = snd_pcm_lib_period_bytes(substream);
233 dpcm->pcm_irq_pos = 0;
234 dpcm->pcm_buf_pos = 0;
235 return 0;
236}
237
238static int snd_card_dummy_playback_prepare(snd_pcm_substream_t * substream)
239{
240 return snd_card_dummy_pcm_prepare(substream);
241}
242
243static int snd_card_dummy_capture_prepare(snd_pcm_substream_t * substream)
244{
245 return snd_card_dummy_pcm_prepare(substream);
246}
247
248static void snd_card_dummy_pcm_timer_function(unsigned long data)
249{
250 snd_card_dummy_pcm_t *dpcm = (snd_card_dummy_pcm_t *)data;
251
252 dpcm->timer.expires = 1 + jiffies;
253 add_timer(&dpcm->timer);
254 spin_lock_irq(&dpcm->lock);
255 dpcm->pcm_irq_pos += dpcm->pcm_jiffie;
256 dpcm->pcm_buf_pos += dpcm->pcm_jiffie;
257 dpcm->pcm_buf_pos %= dpcm->pcm_size;
258 if (dpcm->pcm_irq_pos >= dpcm->pcm_count) {
259 dpcm->pcm_irq_pos %= dpcm->pcm_count;
260 snd_pcm_period_elapsed(dpcm->substream);
261 }
262 spin_unlock_irq(&dpcm->lock);
263}
264
265static snd_pcm_uframes_t snd_card_dummy_playback_pointer(snd_pcm_substream_t * substream)
266{
267 snd_pcm_runtime_t *runtime = substream->runtime;
268 snd_card_dummy_pcm_t *dpcm = runtime->private_data;
269
270 return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
271}
272
273static snd_pcm_uframes_t snd_card_dummy_capture_pointer(snd_pcm_substream_t * substream)
274{
275 snd_pcm_runtime_t *runtime = substream->runtime;
276 snd_card_dummy_pcm_t *dpcm = runtime->private_data;
277
278 return bytes_to_frames(runtime, dpcm->pcm_buf_pos);
279}
280
281static snd_pcm_hardware_t snd_card_dummy_playback =
282{
283 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
284 SNDRV_PCM_INFO_MMAP_VALID),
285 .formats = USE_FORMATS,
286 .rates = USE_RATE,
287 .rate_min = USE_RATE_MIN,
288 .rate_max = USE_RATE_MAX,
289 .channels_min = USE_CHANNELS_MIN,
290 .channels_max = USE_CHANNELS_MAX,
291 .buffer_bytes_max = MAX_BUFFER_SIZE,
292 .period_bytes_min = 64,
293 .period_bytes_max = MAX_BUFFER_SIZE,
294 .periods_min = USE_PERIODS_MIN,
295 .periods_max = USE_PERIODS_MAX,
296 .fifo_size = 0,
297};
298
299static snd_pcm_hardware_t snd_card_dummy_capture =
300{
301 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
302 SNDRV_PCM_INFO_MMAP_VALID),
303 .formats = USE_FORMATS,
304 .rates = USE_RATE,
305 .rate_min = USE_RATE_MIN,
306 .rate_max = USE_RATE_MAX,
307 .channels_min = USE_CHANNELS_MIN,
308 .channels_max = USE_CHANNELS_MAX,
309 .buffer_bytes_max = MAX_BUFFER_SIZE,
310 .period_bytes_min = 64,
311 .period_bytes_max = MAX_BUFFER_SIZE,
312 .periods_min = USE_PERIODS_MIN,
313 .periods_max = USE_PERIODS_MAX,
314 .fifo_size = 0,
315};
316
317static void snd_card_dummy_runtime_free(snd_pcm_runtime_t *runtime)
318{
319 snd_card_dummy_pcm_t *dpcm = runtime->private_data;
320 kfree(dpcm);
321}
322
323static int snd_card_dummy_hw_params(snd_pcm_substream_t * substream,
324 snd_pcm_hw_params_t * hw_params)
325{
326 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
327}
328
329static int snd_card_dummy_hw_free(snd_pcm_substream_t * substream)
330{
331 return snd_pcm_lib_free_pages(substream);
332}
333
334static int snd_card_dummy_playback_open(snd_pcm_substream_t * substream)
335{
336 snd_pcm_runtime_t *runtime = substream->runtime;
337 snd_card_dummy_pcm_t *dpcm;
338 int err;
339
340 dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
341 if (dpcm == NULL)
342 return -ENOMEM;
343 init_timer(&dpcm->timer);
344 dpcm->timer.data = (unsigned long) dpcm;
345 dpcm->timer.function = snd_card_dummy_pcm_timer_function;
346 spin_lock_init(&dpcm->lock);
347 dpcm->substream = substream;
348 runtime->private_data = dpcm;
349 runtime->private_free = snd_card_dummy_runtime_free;
350 runtime->hw = snd_card_dummy_playback;
351 if (substream->pcm->device & 1) {
352 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
353 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
354 }
355 if (substream->pcm->device & 2)
356 runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
357 if ((err = add_playback_constraints(runtime)) < 0) {
358 kfree(dpcm);
359 return err;
360 }
361
362 return 0;
363}
364
365static int snd_card_dummy_capture_open(snd_pcm_substream_t * substream)
366{
367 snd_pcm_runtime_t *runtime = substream->runtime;
368 snd_card_dummy_pcm_t *dpcm;
369 int err;
370
371 dpcm = kcalloc(1, sizeof(*dpcm), GFP_KERNEL);
372 if (dpcm == NULL)
373 return -ENOMEM;
374 init_timer(&dpcm->timer);
375 dpcm->timer.data = (unsigned long) dpcm;
376 dpcm->timer.function = snd_card_dummy_pcm_timer_function;
377 spin_lock_init(&dpcm->lock);
378 dpcm->substream = substream;
379 runtime->private_data = dpcm;
380 runtime->private_free = snd_card_dummy_runtime_free;
381 runtime->hw = snd_card_dummy_capture;
382 if (substream->pcm->device == 1) {
383 runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
384 runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
385 }
386 if (substream->pcm->device & 2)
387 runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP|SNDRV_PCM_INFO_MMAP_VALID);
388 if ((err = add_capture_constraints(runtime)) < 0) {
389 kfree(dpcm);
390 return err;
391 }
392
393 return 0;
394}
395
396static int snd_card_dummy_playback_close(snd_pcm_substream_t * substream)
397{
398 return 0;
399}
400
401static int snd_card_dummy_capture_close(snd_pcm_substream_t * substream)
402{
403 return 0;
404}
405
406static snd_pcm_ops_t snd_card_dummy_playback_ops = {
407 .open = snd_card_dummy_playback_open,
408 .close = snd_card_dummy_playback_close,
409 .ioctl = snd_pcm_lib_ioctl,
410 .hw_params = snd_card_dummy_hw_params,
411 .hw_free = snd_card_dummy_hw_free,
412 .prepare = snd_card_dummy_playback_prepare,
413 .trigger = snd_card_dummy_playback_trigger,
414 .pointer = snd_card_dummy_playback_pointer,
415};
416
417static snd_pcm_ops_t snd_card_dummy_capture_ops = {
418 .open = snd_card_dummy_capture_open,
419 .close = snd_card_dummy_capture_close,
420 .ioctl = snd_pcm_lib_ioctl,
421 .hw_params = snd_card_dummy_hw_params,
422 .hw_free = snd_card_dummy_hw_free,
423 .prepare = snd_card_dummy_capture_prepare,
424 .trigger = snd_card_dummy_capture_trigger,
425 .pointer = snd_card_dummy_capture_pointer,
426};
427
428static int __init snd_card_dummy_pcm(snd_card_dummy_t *dummy, int device, int substreams)
429{
430 snd_pcm_t *pcm;
431 int err;
432
433 if ((err = snd_pcm_new(dummy->card, "Dummy PCM", device, substreams, substreams, &pcm)) < 0)
434 return err;
435 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_dummy_playback_ops);
436 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_dummy_capture_ops);
437 pcm->private_data = dummy;
438 pcm->info_flags = 0;
439 strcpy(pcm->name, "Dummy PCM");
440 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
441 snd_dma_continuous_data(GFP_KERNEL),
442 0, 64*1024);
443 return 0;
444}
445
446#define DUMMY_VOLUME(xname, xindex, addr) \
447{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
448 .info = snd_dummy_volume_info, \
449 .get = snd_dummy_volume_get, .put = snd_dummy_volume_put, \
450 .private_value = addr }
451
452static int snd_dummy_volume_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
453{
454 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
455 uinfo->count = 2;
456 uinfo->value.integer.min = -50;
457 uinfo->value.integer.max = 100;
458 return 0;
459}
460
461static int snd_dummy_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
462{
463 snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
464 unsigned long flags;
465 int addr = kcontrol->private_value;
466
467 spin_lock_irqsave(&dummy->mixer_lock, flags);
468 ucontrol->value.integer.value[0] = dummy->mixer_volume[addr][0];
469 ucontrol->value.integer.value[1] = dummy->mixer_volume[addr][1];
470 spin_unlock_irqrestore(&dummy->mixer_lock, flags);
471 return 0;
472}
473
474static int snd_dummy_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
475{
476 snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
477 unsigned long flags;
478 int change, addr = kcontrol->private_value;
479 int left, right;
480
481 left = ucontrol->value.integer.value[0];
482 if (left < -50)
483 left = -50;
484 if (left > 100)
485 left = 100;
486 right = ucontrol->value.integer.value[1];
487 if (right < -50)
488 right = -50;
489 if (right > 100)
490 right = 100;
491 spin_lock_irqsave(&dummy->mixer_lock, flags);
492 change = dummy->mixer_volume[addr][0] != left ||
493 dummy->mixer_volume[addr][1] != right;
494 dummy->mixer_volume[addr][0] = left;
495 dummy->mixer_volume[addr][1] = right;
496 spin_unlock_irqrestore(&dummy->mixer_lock, flags);
497 return change;
498}
499
500#define DUMMY_CAPSRC(xname, xindex, addr) \
501{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
502 .info = snd_dummy_capsrc_info, \
503 .get = snd_dummy_capsrc_get, .put = snd_dummy_capsrc_put, \
504 .private_value = addr }
505
506static int snd_dummy_capsrc_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
507{
508 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
509 uinfo->count = 2;
510 uinfo->value.integer.min = 0;
511 uinfo->value.integer.max = 1;
512 return 0;
513}
514
515static int snd_dummy_capsrc_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
516{
517 snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
518 unsigned long flags;
519 int addr = kcontrol->private_value;
520
521 spin_lock_irqsave(&dummy->mixer_lock, flags);
522 ucontrol->value.integer.value[0] = dummy->capture_source[addr][0];
523 ucontrol->value.integer.value[1] = dummy->capture_source[addr][1];
524 spin_unlock_irqrestore(&dummy->mixer_lock, flags);
525 return 0;
526}
527
528static int snd_dummy_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
529{
530 snd_card_dummy_t *dummy = snd_kcontrol_chip(kcontrol);
531 unsigned long flags;
532 int change, addr = kcontrol->private_value;
533 int left, right;
534
535 left = ucontrol->value.integer.value[0] & 1;
536 right = ucontrol->value.integer.value[1] & 1;
537 spin_lock_irqsave(&dummy->mixer_lock, flags);
538 change = dummy->capture_source[addr][0] != left &&
539 dummy->capture_source[addr][1] != right;
540 dummy->capture_source[addr][0] = left;
541 dummy->capture_source[addr][1] = right;
542 spin_unlock_irqrestore(&dummy->mixer_lock, flags);
543 return change;
544}
545
546static snd_kcontrol_new_t snd_dummy_controls[] = {
547DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
548DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),
549DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH),
550DUMMY_CAPSRC("Synth Capture Switch", 0, MIXER_ADDR_MASTER),
551DUMMY_VOLUME("Line Volume", 0, MIXER_ADDR_LINE),
552DUMMY_CAPSRC("Line Capture Switch", 0, MIXER_ADDR_MASTER),
553DUMMY_VOLUME("Mic Volume", 0, MIXER_ADDR_MIC),
554DUMMY_CAPSRC("Mic Capture Switch", 0, MIXER_ADDR_MASTER),
555DUMMY_VOLUME("CD Volume", 0, MIXER_ADDR_CD),
556DUMMY_CAPSRC("CD Capture Switch", 0, MIXER_ADDR_MASTER)
557};
558
559static int __init snd_card_dummy_new_mixer(snd_card_dummy_t * dummy)
560{
561 snd_card_t *card = dummy->card;
562 unsigned int idx;
563 int err;
564
565 snd_assert(dummy != NULL, return -EINVAL);
566 spin_lock_init(&dummy->mixer_lock);
567 strcpy(card->mixername, "Dummy Mixer");
568
569 for (idx = 0; idx < ARRAY_SIZE(snd_dummy_controls); idx++) {
570 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_dummy_controls[idx], dummy))) < 0)
571 return err;
572 }
573 return 0;
574}
575
576static int __init snd_card_dummy_probe(int dev)
577{
578 snd_card_t *card;
579 struct snd_card_dummy *dummy;
580 int idx, err;
581
582 if (!enable[dev])
583 return -ENODEV;
584 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
585 sizeof(struct snd_card_dummy));
586 if (card == NULL)
587 return -ENOMEM;
588 dummy = (struct snd_card_dummy *)card->private_data;
589 dummy->card = card;
590 for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) {
591 if (pcm_substreams[dev] < 1)
592 pcm_substreams[dev] = 1;
593 if (pcm_substreams[dev] > MAX_PCM_SUBSTREAMS)
594 pcm_substreams[dev] = MAX_PCM_SUBSTREAMS;
595 if ((err = snd_card_dummy_pcm(dummy, idx, pcm_substreams[dev])) < 0)
596 goto __nodev;
597 }
598 if ((err = snd_card_dummy_new_mixer(dummy)) < 0)
599 goto __nodev;
600 strcpy(card->driver, "Dummy");
601 strcpy(card->shortname, "Dummy");
602 sprintf(card->longname, "Dummy %i", dev + 1);
603 if ((err = snd_card_register(card)) == 0) {
604 snd_dummy_cards[dev] = card;
605 return 0;
606 }
607 __nodev:
608 snd_card_free(card);
609 return err;
610}
611
612static int __init alsa_card_dummy_init(void)
613{
614 int dev, cards;
615
616 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
617 if (snd_card_dummy_probe(dev) < 0) {
618#ifdef MODULE
619 printk(KERN_ERR "Dummy soundcard #%i not found or device busy\n", dev + 1);
620#endif
621 break;
622 }
623 cards++;
624 }
625 if (!cards) {
626#ifdef MODULE
627 printk(KERN_ERR "Dummy soundcard not found or device busy\n");
628#endif
629 return -ENODEV;
630 }
631 return 0;
632}
633
634static void __exit alsa_card_dummy_exit(void)
635{
636 int idx;
637
638 for (idx = 0; idx < SNDRV_CARDS; idx++)
639 snd_card_free(snd_dummy_cards[idx]);
640}
641
642module_init(alsa_card_dummy_init)
643module_exit(alsa_card_dummy_exit)
diff --git a/sound/drivers/mpu401/Makefile b/sound/drivers/mpu401/Makefile
new file mode 100644
index 000000000000..3fe185d19ae5
--- /dev/null
+++ b/sound/drivers/mpu401/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-mpu401-objs := mpu401.o
7snd-mpu401-uart-objs := mpu401_uart.o
8
9obj-$(CONFIG_SND_MPU401_UART) += snd-mpu401-uart.o
10
11# Toplevel Module Dependency
12obj-$(CONFIG_SND_MPU401) += snd-mpu401.o
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
new file mode 100644
index 000000000000..cb36ecb78697
--- /dev/null
+++ b/sound/drivers/mpu401/mpu401.c
@@ -0,0 +1,229 @@
1/*
2 * Driver for generic MPU-401 boards (UART mode only)
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
4 * Copyright (c) 2004 by Castet Matthieu <castet.matthieu@free.fr>
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <sound/driver.h>
24#include <linux/init.h>
25#include <linux/pnp.h>
26#include <linux/moduleparam.h>
27#include <sound/core.h>
28#include <sound/mpu401.h>
29#include <sound/initval.h>
30
31MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
32MODULE_DESCRIPTION("MPU-401 UART");
33MODULE_LICENSE("GPL");
34
35static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */
36static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
37static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
38#ifdef CONFIG_PNP
39static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
40#endif
41static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */
42static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */
43
44module_param_array(index, int, NULL, 0444);
45MODULE_PARM_DESC(index, "Index value for MPU-401 device.");
46module_param_array(id, charp, NULL, 0444);
47MODULE_PARM_DESC(id, "ID string for MPU-401 device.");
48module_param_array(enable, bool, NULL, 0444);
49MODULE_PARM_DESC(enable, "Enable MPU-401 device.");
50#ifdef CONFIG_PNP
51module_param_array(pnp, bool, NULL, 0444);
52MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device.");
53#endif
54module_param_array(port, long, NULL, 0444);
55MODULE_PARM_DESC(port, "Port # for MPU-401 device.");
56module_param_array(irq, int, NULL, 0444);
57MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
58
59static snd_card_t *snd_mpu401_legacy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
60static int pnp_registered = 0;
61
62static int snd_mpu401_create(int dev, snd_card_t **rcard)
63{
64 snd_card_t *card;
65 int err;
66
67 *rcard = NULL;
68 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
69 if (card == NULL)
70 return -ENOMEM;
71 strcpy(card->driver, "MPU-401 UART");
72 strcpy(card->shortname, card->driver);
73 sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]);
74 if (irq[dev] >= 0) {
75 sprintf(card->longname + strlen(card->longname), "irq %d", irq[dev]);
76 } else {
77 strcat(card->longname, "polled");
78 }
79
80 if (snd_mpu401_uart_new(card, 0,
81 MPU401_HW_MPU401,
82 port[dev], 0,
83 irq[dev], irq[dev] >= 0 ? SA_INTERRUPT : 0, NULL) < 0) {
84 printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
85 snd_card_free(card);
86 return -ENODEV;
87 }
88 if ((err = snd_card_register(card)) < 0) {
89 snd_card_free(card);
90 return err;
91 }
92 *rcard = card;
93 return 0;
94}
95
96static int __devinit snd_mpu401_probe(int dev)
97{
98 if (port[dev] == SNDRV_AUTO_PORT) {
99 snd_printk(KERN_ERR "specify port\n");
100 return -EINVAL;
101 }
102 if (irq[dev] == SNDRV_AUTO_IRQ) {
103 snd_printk(KERN_ERR "specify or disable IRQ\n");
104 return -EINVAL;
105 }
106 return snd_mpu401_create(dev, &snd_mpu401_legacy_cards[dev]);
107}
108
109#ifdef CONFIG_PNP
110
111#define IO_EXTENT 2
112
113static struct pnp_device_id snd_mpu401_pnpids[] = {
114 { .id = "PNPb006" },
115 { .id = "" }
116};
117
118MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids);
119
120static int __init snd_mpu401_pnp(int dev, struct pnp_dev *device,
121 const struct pnp_device_id *id)
122{
123 if (!pnp_port_valid(device, 0) ||
124 pnp_port_flags(device, 0) & IORESOURCE_DISABLED) {
125 snd_printk(KERN_ERR "no PnP port\n");
126 return -ENODEV;
127 }
128 if (pnp_port_len(device, 0) < IO_EXTENT) {
129 snd_printk(KERN_ERR "PnP port length is %ld, expected %d\n",
130 pnp_port_len(device, 0), IO_EXTENT);
131 return -ENODEV;
132 }
133 port[dev] = pnp_port_start(device, 0);
134
135 if (!pnp_irq_valid(device, 0) ||
136 pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) {
137 snd_printk(KERN_WARNING "no PnP irq, using polling\n");
138 irq[dev] = -1;
139 } else {
140 irq[dev] = pnp_irq(device, 0);
141 }
142 return 0;
143}
144
145static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
146 const struct pnp_device_id *id)
147{
148 static int dev;
149 snd_card_t *card;
150 int err;
151
152 for ( ; dev < SNDRV_CARDS; ++dev) {
153 if (!enable[dev] || !pnp[dev])
154 continue;
155 err = snd_mpu401_pnp(dev, pnp_dev, id);
156 if (err < 0)
157 return err;
158 err = snd_mpu401_create(dev, &card);
159 if (err < 0)
160 return err;
161 snd_card_set_dev(card, &pnp_dev->dev);
162 pnp_set_drvdata(pnp_dev, card);
163 ++dev;
164 return 0;
165 }
166 return -ENODEV;
167}
168
169static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev)
170{
171 snd_card_t *card = (snd_card_t *) pnp_get_drvdata(dev);
172
173 snd_card_disconnect(card);
174 snd_card_free_in_thread(card);
175}
176
177static struct pnp_driver snd_mpu401_pnp_driver = {
178 .name = "mpu401",
179 .id_table = snd_mpu401_pnpids,
180 .probe = snd_mpu401_pnp_probe,
181 .remove = __devexit_p(snd_mpu401_pnp_remove),
182};
183#else
184static struct pnp_driver snd_mpu401_pnp_driver;
185#endif
186
187static int __init alsa_card_mpu401_init(void)
188{
189 int dev, devices = 0;
190 int err;
191
192 for (dev = 0; dev < SNDRV_CARDS; dev++) {
193 if (!enable[dev])
194 continue;
195#ifdef CONFIG_PNP
196 if (pnp[dev])
197 continue;
198#endif
199 if (snd_mpu401_probe(dev) >= 0)
200 devices++;
201 }
202 if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) {
203 pnp_registered = 1;
204 devices += err;
205 }
206
207 if (!devices) {
208#ifdef MODULE
209 printk(KERN_ERR "MPU-401 device not found or device busy\n");
210#endif
211 if (pnp_registered)
212 pnp_unregister_driver(&snd_mpu401_pnp_driver);
213 return -ENODEV;
214 }
215 return 0;
216}
217
218static void __exit alsa_card_mpu401_exit(void)
219{
220 int idx;
221
222 if (pnp_registered)
223 pnp_unregister_driver(&snd_mpu401_pnp_driver);
224 for (idx = 0; idx < SNDRV_CARDS; idx++)
225 snd_card_free(snd_mpu401_legacy_cards[idx]);
226}
227
228module_init(alsa_card_mpu401_init)
229module_exit(alsa_card_mpu401_exit)
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
new file mode 100644
index 000000000000..0f83c5241b6b
--- /dev/null
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -0,0 +1,541 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of MPU-401 in UART mode
4 *
5 * MPU-401 supports UART mode which is not capable generate transmit
6 * interrupts thus output is done via polling. Also, if irq < 0, then
7 * input is done also via polling. Do not expect good performance.
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * 13-03-2003:
25 * Added support for different kind of hardware I/O. Build in choices
26 * are port and mmio. For other kind of I/O, set mpu->read and
27 * mpu->write to your own I/O functions.
28 *
29 */
30
31#include <sound/driver.h>
32#include <asm/io.h>
33#include <linux/delay.h>
34#include <linux/init.h>
35#include <linux/slab.h>
36#include <linux/ioport.h>
37#include <linux/interrupt.h>
38#include <linux/errno.h>
39#include <sound/core.h>
40#include <sound/mpu401.h>
41
42MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
43MODULE_DESCRIPTION("Routines for control of MPU-401 in UART mode");
44MODULE_LICENSE("GPL");
45
46static void snd_mpu401_uart_input_read(mpu401_t * mpu);
47static void snd_mpu401_uart_output_write(mpu401_t * mpu);
48
49/*
50
51 */
52
53#define snd_mpu401_input_avail(mpu) (!(mpu->read(mpu, MPU401C(mpu)) & 0x80))
54#define snd_mpu401_output_ready(mpu) (!(mpu->read(mpu, MPU401C(mpu)) & 0x40))
55
56#define MPU401_RESET 0xff
57#define MPU401_ENTER_UART 0x3f
58#define MPU401_ACK 0xfe
59
60/* Build in lowlevel io */
61static void mpu401_write_port(mpu401_t *mpu, unsigned char data, unsigned long addr)
62{
63 outb(data, addr);
64}
65
66static unsigned char mpu401_read_port(mpu401_t *mpu, unsigned long addr)
67{
68 return inb(addr);
69}
70
71static void mpu401_write_mmio(mpu401_t *mpu, unsigned char data, unsigned long addr)
72{
73 writeb(data, (void __iomem *)addr);
74}
75
76static unsigned char mpu401_read_mmio(mpu401_t *mpu, unsigned long addr)
77{
78 return readb((void __iomem *)addr);
79}
80/* */
81
82static void snd_mpu401_uart_clear_rx(mpu401_t *mpu)
83{
84 int timeout = 100000;
85 for (; timeout > 0 && snd_mpu401_input_avail(mpu); timeout--)
86 mpu->read(mpu, MPU401D(mpu));
87#ifdef CONFIG_SND_DEBUG
88 if (timeout <= 0)
89 snd_printk("cmd: clear rx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
90#endif
91}
92
93static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
94{
95 spin_lock(&mpu->input_lock);
96 if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
97 snd_mpu401_uart_input_read(mpu);
98 } else {
99 snd_mpu401_uart_clear_rx(mpu);
100 }
101 spin_unlock(&mpu->input_lock);
102 /* ok. for better Tx performance try do some output when input is done */
103 if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
104 test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
105 spin_lock(&mpu->output_lock);
106 snd_mpu401_uart_output_write(mpu);
107 spin_unlock(&mpu->output_lock);
108 }
109}
110
111/**
112 * snd_mpu401_uart_interrupt - generic MPU401-UART interrupt handler
113 * @irq: the irq number
114 * @dev_id: mpu401 instance
115 * @regs: the reigster
116 *
117 * Processes the interrupt for MPU401-UART i/o.
118 */
119irqreturn_t snd_mpu401_uart_interrupt(int irq, void *dev_id, struct pt_regs *regs)
120{
121 mpu401_t *mpu = dev_id;
122
123 if (mpu == NULL)
124 return IRQ_NONE;
125 _snd_mpu401_uart_interrupt(mpu);
126 return IRQ_HANDLED;
127}
128
129/*
130 * timer callback
131 * reprogram the timer and call the interrupt job
132 */
133static void snd_mpu401_uart_timer(unsigned long data)
134{
135 mpu401_t *mpu = (mpu401_t *)data;
136
137 spin_lock(&mpu->timer_lock);
138 /*mpu->mode |= MPU401_MODE_TIMER;*/
139 mpu->timer.expires = 1 + jiffies;
140 add_timer(&mpu->timer);
141 spin_unlock(&mpu->timer_lock);
142 if (mpu->rmidi)
143 _snd_mpu401_uart_interrupt(mpu);
144}
145
146/*
147 * initialize the timer callback if not programmed yet
148 */
149static void snd_mpu401_uart_add_timer (mpu401_t *mpu, int input)
150{
151 unsigned long flags;
152
153 spin_lock_irqsave (&mpu->timer_lock, flags);
154 if (mpu->timer_invoked == 0) {
155 init_timer(&mpu->timer);
156 mpu->timer.data = (unsigned long)mpu;
157 mpu->timer.function = snd_mpu401_uart_timer;
158 mpu->timer.expires = 1 + jiffies;
159 add_timer(&mpu->timer);
160 }
161 mpu->timer_invoked |= input ? MPU401_MODE_INPUT_TIMER : MPU401_MODE_OUTPUT_TIMER;
162 spin_unlock_irqrestore (&mpu->timer_lock, flags);
163}
164
165/*
166 * remove the timer callback if still active
167 */
168static void snd_mpu401_uart_remove_timer (mpu401_t *mpu, int input)
169{
170 unsigned long flags;
171
172 spin_lock_irqsave (&mpu->timer_lock, flags);
173 if (mpu->timer_invoked) {
174 mpu->timer_invoked &= input ? ~MPU401_MODE_INPUT_TIMER : ~MPU401_MODE_OUTPUT_TIMER;
175 if (! mpu->timer_invoked)
176 del_timer(&mpu->timer);
177 }
178 spin_unlock_irqrestore (&mpu->timer_lock, flags);
179}
180
181/*
182
183 */
184
185static void snd_mpu401_uart_cmd(mpu401_t * mpu, unsigned char cmd, int ack)
186{
187 unsigned long flags;
188 int timeout, ok;
189
190 spin_lock_irqsave(&mpu->input_lock, flags);
191 if (mpu->hardware != MPU401_HW_TRID4DWAVE) {
192 mpu->write(mpu, 0x00, MPU401D(mpu));
193 /*snd_mpu401_uart_clear_rx(mpu);*/
194 }
195 /* ok. standard MPU-401 initialization */
196 if (mpu->hardware != MPU401_HW_SB) {
197 for (timeout = 1000; timeout > 0 && !snd_mpu401_output_ready(mpu); timeout--)
198 udelay(10);
199#ifdef CONFIG_SND_DEBUG
200 if (!timeout)
201 snd_printk("cmd: tx timeout (status = 0x%x)\n", mpu->read(mpu, MPU401C(mpu)));
202#endif
203 }
204 mpu->write(mpu, cmd, MPU401C(mpu));
205 if (ack) {
206 ok = 0;
207 timeout = 10000;
208 while (!ok && timeout-- > 0) {
209 if (snd_mpu401_input_avail(mpu)) {
210 if (mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
211 ok = 1;
212 }
213 }
214 if (!ok && mpu->read(mpu, MPU401D(mpu)) == MPU401_ACK)
215 ok = 1;
216 } else {
217 ok = 1;
218 }
219 spin_unlock_irqrestore(&mpu->input_lock, flags);
220 if (! ok)
221 snd_printk("cmd: 0x%x failed at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
222 // snd_printk("cmd: 0x%x at 0x%lx (status = 0x%x, data = 0x%x)\n", cmd, mpu->port, mpu->read(mpu, MPU401C(mpu)), mpu->read(mpu, MPU401D(mpu)));
223}
224
225/*
226 * input/output open/close - protected by open_mutex in rawmidi.c
227 */
228static int snd_mpu401_uart_input_open(snd_rawmidi_substream_t * substream)
229{
230 mpu401_t *mpu;
231 int err;
232
233 mpu = substream->rmidi->private_data;
234 if (mpu->open_input && (err = mpu->open_input(mpu)) < 0)
235 return err;
236 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode)) {
237 snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
238 snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
239 }
240 mpu->substream_input = substream;
241 set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
242 return 0;
243}
244
245static int snd_mpu401_uart_output_open(snd_rawmidi_substream_t * substream)
246{
247 mpu401_t *mpu;
248 int err;
249
250 mpu = substream->rmidi->private_data;
251 if (mpu->open_output && (err = mpu->open_output(mpu)) < 0)
252 return err;
253 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
254 snd_mpu401_uart_cmd(mpu, MPU401_RESET, 1);
255 snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
256 }
257 mpu->substream_output = substream;
258 set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
259 return 0;
260}
261
262static int snd_mpu401_uart_input_close(snd_rawmidi_substream_t * substream)
263{
264 mpu401_t *mpu;
265
266 mpu = substream->rmidi->private_data;
267 clear_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
268 mpu->substream_input = NULL;
269 if (! test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode))
270 snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
271 if (mpu->close_input)
272 mpu->close_input(mpu);
273 return 0;
274}
275
276static int snd_mpu401_uart_output_close(snd_rawmidi_substream_t * substream)
277{
278 mpu401_t *mpu;
279
280 mpu = substream->rmidi->private_data;
281 clear_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
282 mpu->substream_output = NULL;
283 if (! test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode))
284 snd_mpu401_uart_cmd(mpu, MPU401_RESET, 0);
285 if (mpu->close_output)
286 mpu->close_output(mpu);
287 return 0;
288}
289
290/*
291 * trigger input callback
292 */
293static void snd_mpu401_uart_input_trigger(snd_rawmidi_substream_t * substream, int up)
294{
295 unsigned long flags;
296 mpu401_t *mpu;
297 int max = 64;
298
299 mpu = substream->rmidi->private_data;
300 if (up) {
301 if (! test_and_set_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode)) {
302 /* first time - flush FIFO */
303 while (max-- > 0)
304 mpu->read(mpu, MPU401D(mpu));
305 if (mpu->irq < 0)
306 snd_mpu401_uart_add_timer(mpu, 1);
307 }
308
309 /* read data in advance */
310 spin_lock_irqsave(&mpu->input_lock, flags);
311 snd_mpu401_uart_input_read(mpu);
312 spin_unlock_irqrestore(&mpu->input_lock, flags);
313 } else {
314 if (mpu->irq < 0)
315 snd_mpu401_uart_remove_timer(mpu, 1);
316 clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
317 }
318}
319
320/*
321 * transfer input pending data
322 * call with input_lock spinlock held
323 */
324static void snd_mpu401_uart_input_read(mpu401_t * mpu)
325{
326 int max = 128;
327 unsigned char byte;
328
329 while (max-- > 0) {
330 if (snd_mpu401_input_avail(mpu)) {
331 byte = mpu->read(mpu, MPU401D(mpu));
332 if (test_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
333 snd_rawmidi_receive(mpu->substream_input, &byte, 1);
334 } else {
335 break; /* input not available */
336 }
337 }
338}
339
340/*
341 * Tx FIFO sizes:
342 * CS4237B - 16 bytes
343 * AudioDrive ES1688 - 12 bytes
344 * S3 SonicVibes - 8 bytes
345 * SoundBlaster AWE 64 - 2 bytes (ugly hardware)
346 */
347
348/*
349 * write output pending bytes
350 * call with output_lock spinlock held
351 */
352static void snd_mpu401_uart_output_write(mpu401_t * mpu)
353{
354 unsigned char byte;
355 int max = 256, timeout;
356
357 do {
358 if (snd_rawmidi_transmit_peek(mpu->substream_output, &byte, 1) == 1) {
359 for (timeout = 100; timeout > 0; timeout--) {
360 if (snd_mpu401_output_ready(mpu)) {
361 mpu->write(mpu, byte, MPU401D(mpu));
362 snd_rawmidi_transmit_ack(mpu->substream_output, 1);
363 break;
364 }
365 }
366 if (timeout == 0)
367 break; /* Tx FIFO full - try again later */
368 } else {
369 snd_mpu401_uart_remove_timer (mpu, 0);
370 break; /* no other data - leave the tx loop */
371 }
372 } while (--max > 0);
373}
374
375/*
376 * output trigger callback
377 */
378static void snd_mpu401_uart_output_trigger(snd_rawmidi_substream_t * substream, int up)
379{
380 unsigned long flags;
381 mpu401_t *mpu;
382
383 mpu = substream->rmidi->private_data;
384 if (up) {
385 set_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
386
387 /* try to add the timer at each output trigger,
388 * since the output timer might have been removed in
389 * snd_mpu401_uart_output_write().
390 */
391 snd_mpu401_uart_add_timer(mpu, 0);
392
393 /* output pending data */
394 spin_lock_irqsave(&mpu->output_lock, flags);
395 snd_mpu401_uart_output_write(mpu);
396 spin_unlock_irqrestore(&mpu->output_lock, flags);
397 } else {
398 snd_mpu401_uart_remove_timer(mpu, 0);
399 clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
400 }
401}
402
403/*
404
405 */
406
407static snd_rawmidi_ops_t snd_mpu401_uart_output =
408{
409 .open = snd_mpu401_uart_output_open,
410 .close = snd_mpu401_uart_output_close,
411 .trigger = snd_mpu401_uart_output_trigger,
412};
413
414static snd_rawmidi_ops_t snd_mpu401_uart_input =
415{
416 .open = snd_mpu401_uart_input_open,
417 .close = snd_mpu401_uart_input_close,
418 .trigger = snd_mpu401_uart_input_trigger,
419};
420
421static void snd_mpu401_uart_free(snd_rawmidi_t *rmidi)
422{
423 mpu401_t *mpu = rmidi->private_data;
424 if (mpu->irq_flags && mpu->irq >= 0)
425 free_irq(mpu->irq, (void *) mpu);
426 if (mpu->res) {
427 release_resource(mpu->res);
428 kfree_nocheck(mpu->res);
429 }
430 kfree(mpu);
431}
432
433/**
434 * snd_mpu401_uart_new - create an MPU401-UART instance
435 * @card: the card instance
436 * @device: the device index, zero-based
437 * @hardware: the hardware type, MPU401_HW_XXXX
438 * @port: the base address of MPU401 port
439 * @integrated: non-zero if the port was already reserved by the chip
440 * @irq: the irq number, -1 if no interrupt for mpu
441 * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved.
442 * @rrawmidi: the pointer to store the new rawmidi instance
443 *
444 * Creates a new MPU-401 instance.
445 *
446 * Note that the rawmidi instance is returned on the rrawmidi argument,
447 * not the mpu401 instance itself. To access to the mpu401 instance,
448 * cast from rawmidi->private_data (with mpu401_t magic-cast).
449 *
450 * Returns zero if successful, or a negative error code.
451 */
452int snd_mpu401_uart_new(snd_card_t * card, int device,
453 unsigned short hardware,
454 unsigned long port, int integrated,
455 int irq, int irq_flags,
456 snd_rawmidi_t ** rrawmidi)
457{
458 mpu401_t *mpu;
459 snd_rawmidi_t *rmidi;
460 int err;
461
462 if (rrawmidi)
463 *rrawmidi = NULL;
464 if ((err = snd_rawmidi_new(card, "MPU-401U", device, 1, 1, &rmidi)) < 0)
465 return err;
466 mpu = kcalloc(1, sizeof(*mpu), GFP_KERNEL);
467 if (mpu == NULL) {
468 snd_device_free(card, rmidi);
469 return -ENOMEM;
470 }
471 rmidi->private_data = mpu;
472 rmidi->private_free = snd_mpu401_uart_free;
473 spin_lock_init(&mpu->input_lock);
474 spin_lock_init(&mpu->output_lock);
475 spin_lock_init(&mpu->timer_lock);
476 mpu->hardware = hardware;
477 if (!integrated) {
478 int res_size = hardware == MPU401_HW_PC98II ? 4 : 2;
479 if ((mpu->res = request_region(port, res_size, "MPU401 UART")) == NULL) {
480 snd_printk(KERN_ERR "mpu401_uart: unable to grab port 0x%lx size %d\n", port, res_size);
481 snd_device_free(card, rmidi);
482 return -EBUSY;
483 }
484 }
485 switch (hardware) {
486 case MPU401_HW_AUREAL:
487 mpu->write = mpu401_write_mmio;
488 mpu->read = mpu401_read_mmio;
489 break;
490 default:
491 mpu->write = mpu401_write_port;
492 mpu->read = mpu401_read_port;
493 break;
494 }
495 mpu->port = port;
496 if (hardware == MPU401_HW_PC98II)
497 mpu->cport = port + 2;
498 else
499 mpu->cport = port + 1;
500 if (irq >= 0 && irq_flags) {
501 if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags, "MPU401 UART", (void *) mpu)) {
502 snd_printk(KERN_ERR "mpu401_uart: unable to grab IRQ %d\n", irq);
503 snd_device_free(card, rmidi);
504 return -EBUSY;
505 }
506 }
507 mpu->irq = irq;
508 mpu->irq_flags = irq_flags;
509 if (card->shortname[0])
510 snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI", card->shortname);
511 else
512 sprintf(rmidi->name, "MPU-401 MIDI %d-%d", card->number, device);
513 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mpu401_uart_output);
514 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mpu401_uart_input);
515 rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT |
516 SNDRV_RAWMIDI_INFO_INPUT |
517 SNDRV_RAWMIDI_INFO_DUPLEX;
518 mpu->rmidi = rmidi;
519 if (rrawmidi)
520 *rrawmidi = rmidi;
521 return 0;
522}
523
524EXPORT_SYMBOL(snd_mpu401_uart_interrupt);
525EXPORT_SYMBOL(snd_mpu401_uart_new);
526
527/*
528 * INIT part
529 */
530
531static int __init alsa_mpu401_uart_init(void)
532{
533 return 0;
534}
535
536static void __exit alsa_mpu401_uart_exit(void)
537{
538}
539
540module_init(alsa_mpu401_uart_init)
541module_exit(alsa_mpu401_uart_exit)
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
new file mode 100644
index 000000000000..1280a57c49eb
--- /dev/null
+++ b/sound/drivers/mtpav.c
@@ -0,0 +1,795 @@
1/*
2 * MOTU Midi Timepiece ALSA Main routines
3 * Copyright by Michael T. Mayers (c) Jan 09, 2000
4 * mail: michael@tweakoz.com
5 * Thanks to John Galbraith
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 *
22 * This driver is for the 'Mark Of The Unicorn' (MOTU)
23 * MidiTimePiece AV multiport MIDI interface
24 *
25 * IOPORTS
26 * -------
27 * 8 MIDI Ins and 8 MIDI outs
28 * Video Sync In (BNC), Word Sync Out (BNC),
29 * ADAT Sync Out (DB9)
30 * SMPTE in/out (1/4")
31 * 2 programmable pedal/footswitch inputs and 4 programmable MIDI controller knobs.
32 * Macintosh RS422 serial port
33 * RS422 "network" port for ganging multiple MTP's
34 * PC Parallel Port ( which this driver currently uses )
35 *
36 * MISC FEATURES
37 * -------------
38 * Hardware MIDI routing, merging, and filtering
39 * MIDI Synchronization to Video, ADAT, SMPTE and other Clock sources
40 * 128 'scene' memories, recallable from MIDI program change
41 *
42 *
43 * ChangeLog
44 * Jun 11 2001 Takashi Iwai <tiwai@suse.de>
45 * - Recoded & debugged
46 * - Added timer interrupt for midi outputs
47 * - hwports is between 1 and 8, which specifies the number of hardware ports.
48 * The three global ports, computer, adat and broadcast ports, are created
49 * always after h/w and remote ports.
50 *
51 */
52
53#include <sound/driver.h>
54#include <linux/init.h>
55#include <linux/interrupt.h>
56#include <linux/slab.h>
57#include <linux/ioport.h>
58#include <linux/moduleparam.h>
59#include <sound/core.h>
60#include <sound/initval.h>
61#include <sound/rawmidi.h>
62#include <linux/delay.h>
63
64#include <asm/io.h>
65
66/*
67 * globals
68 */
69MODULE_AUTHOR("Michael T. Mayers");
70MODULE_DESCRIPTION("MOTU MidiTimePiece AV multiport MIDI");
71MODULE_LICENSE("GPL");
72MODULE_SUPPORTED_DEVICE("{{MOTU,MidiTimePiece AV multiport MIDI}}");
73
74// io resources
75#define MTPAV_IOBASE 0x378
76#define MTPAV_IRQ 7
77#define MTPAV_MAX_PORTS 8
78
79static int index = SNDRV_DEFAULT_IDX1;
80static char *id = SNDRV_DEFAULT_STR1;
81static long port = MTPAV_IOBASE; /* 0x378, 0x278 */
82static int irq = MTPAV_IRQ; /* 7, 5 */
83static int hwports = MTPAV_MAX_PORTS; /* use hardware ports 1-8 */
84
85module_param(index, int, 0444);
86MODULE_PARM_DESC(index, "Index value for MotuMTPAV MIDI.");
87module_param(id, charp, 0444);
88MODULE_PARM_DESC(id, "ID string for MotuMTPAV MIDI.");
89module_param(port, long, 0444);
90MODULE_PARM_DESC(port, "Parallel port # for MotuMTPAV MIDI.");
91module_param(irq, int, 0444);
92MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI.");
93module_param(hwports, int, 0444);
94MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
95
96/*
97 * defines
98 */
99//#define USE_FAKE_MTP // don't actually read/write to MTP device (for debugging without an actual unit) (does not work yet)
100
101// parallel port usage masks
102#define SIGS_BYTE 0x08
103#define SIGS_RFD 0x80
104#define SIGS_IRQ 0x40
105#define SIGS_IN0 0x10
106#define SIGS_IN1 0x20
107
108#define SIGC_WRITE 0x04
109#define SIGC_READ 0x08
110#define SIGC_INTEN 0x10
111
112#define DREG 0
113#define SREG 1
114#define CREG 2
115
116//
117#define MTPAV_MODE_INPUT_OPENED 0x01
118#define MTPAV_MODE_OUTPUT_OPENED 0x02
119#define MTPAV_MODE_INPUT_TRIGGERED 0x04
120#define MTPAV_MODE_OUTPUT_TRIGGERED 0x08
121
122#define NUMPORTS (0x12+1)
123
124
125/*
126 */
127
128typedef struct mtpav_port {
129 u8 number;
130 u8 hwport;
131 u8 mode;
132 u8 running_status;
133 snd_rawmidi_substream_t *input;
134 snd_rawmidi_substream_t *output;
135} mtpav_port_t;
136
137typedef struct mtpav {
138 snd_card_t *card;
139 unsigned long port;
140 struct resource *res_port;
141 int irq; /* interrupt (for inputs) */
142 spinlock_t spinlock;
143 int share_irq; /* number of accesses to input interrupts */
144 int istimer; /* number of accesses to timer interrupts */
145 struct timer_list timer; /* timer interrupts for outputs */
146 snd_rawmidi_t *rmidi;
147 int num_ports; /* number of hw ports (1-8) */
148 mtpav_port_t ports[NUMPORTS]; /* all ports including computer, adat and bc */
149
150 u32 inmidiport; /* selected input midi port */
151 u32 inmidistate; /* during midi command 0xf5 */
152
153 u32 outmidihwport; /* selected output midi hw port */
154} mtpav_t;
155
156
157/*
158 * global instance
159 * hey, we handle at most only one card..
160 */
161static mtpav_t *mtp_card;
162
163/*
164 * possible hardware ports (selected by 0xf5 port message)
165 * 0x00 all ports
166 * 0x01 .. 0x08 this MTP's ports 1..8
167 * 0x09 .. 0x10 networked MTP's ports (9..16)
168 * 0x11 networked MTP's computer port
169 * 0x63 to ADAT
170 *
171 * mappig:
172 * subdevice 0 - (X-1) ports
173 * X - (2*X-1) networked ports
174 * X computer
175 * X+1 ADAT
176 * X+2 all ports
177 *
178 * where X = chip->num_ports
179 */
180
181#define MTPAV_PIDX_COMPUTER 0
182#define MTPAV_PIDX_ADAT 1
183#define MTPAV_PIDX_BROADCAST 2
184
185
186static int translate_subdevice_to_hwport(mtpav_t *chip, int subdev)
187{
188 if (subdev < 0)
189 return 0x01; /* invalid - use port 0 as default */
190 else if (subdev < chip->num_ports)
191 return subdev + 1; /* single mtp port */
192 else if (subdev < chip->num_ports * 2)
193 return subdev - chip->num_ports + 0x09; /* remote port */
194 else if (subdev == chip->num_ports * 2 + MTPAV_PIDX_COMPUTER)
195 return 0x11; /* computer port */
196 else if (subdev == chip->num_ports + MTPAV_PIDX_ADAT)
197 return 0x63; /* ADAT */
198 return 0; /* all ports */
199}
200
201static int translate_hwport_to_subdevice(mtpav_t *chip, int hwport)
202{
203 int p;
204 if (hwport <= 0x00) /* all ports */
205 return chip->num_ports + MTPAV_PIDX_BROADCAST;
206 else if (hwport <= 0x08) { /* single port */
207 p = hwport - 1;
208 if (p >= chip->num_ports)
209 p = 0;
210 return p;
211 } else if (hwport <= 0x10) { /* remote port */
212 p = hwport - 0x09 + chip->num_ports;
213 if (p >= chip->num_ports * 2)
214 p = chip->num_ports;
215 return p;
216 } else if (hwport == 0x11) /* computer port */
217 return chip->num_ports + MTPAV_PIDX_COMPUTER;
218 else /* ADAT */
219 return chip->num_ports + MTPAV_PIDX_ADAT;
220}
221
222
223/*
224 */
225
226static u8 snd_mtpav_getreg(mtpav_t *chip, u16 reg)
227{
228 u8 rval = 0;
229
230 if (reg == SREG) {
231 rval = inb(chip->port + SREG);
232 rval = (rval & 0xf8);
233 } else if (reg == CREG) {
234 rval = inb(chip->port + CREG);
235 rval = (rval & 0x1c);
236 }
237
238 return rval;
239}
240
241/*
242 */
243
244static void snd_mtpav_mputreg(mtpav_t *chip, u16 reg, u8 val)
245{
246 if (reg == DREG) {
247 outb(val, chip->port + DREG);
248 } else if (reg == CREG) {
249 outb(val, chip->port + CREG);
250 }
251}
252
253/*
254 */
255
256static void snd_mtpav_wait_rfdhi(mtpav_t *chip)
257{
258 int counts = 10000;
259 u8 sbyte;
260
261 sbyte = snd_mtpav_getreg(chip, SREG);
262 while (!(sbyte & SIGS_RFD) && counts--) {
263 sbyte = snd_mtpav_getreg(chip, SREG);
264 udelay(10);
265 }
266}
267
268static void snd_mtpav_send_byte(mtpav_t *chip, u8 byte)
269{
270 u8 tcbyt;
271 u8 clrwrite;
272 u8 setwrite;
273
274 snd_mtpav_wait_rfdhi(chip);
275
276 /////////////////
277
278 tcbyt = snd_mtpav_getreg(chip, CREG);
279 clrwrite = tcbyt & (SIGC_WRITE ^ 0xff);
280 setwrite = tcbyt | SIGC_WRITE;
281
282 snd_mtpav_mputreg(chip, DREG, byte);
283 snd_mtpav_mputreg(chip, CREG, clrwrite); // clear write bit
284
285 snd_mtpav_mputreg(chip, CREG, setwrite); // set write bit
286
287}
288
289
290/*
291 */
292
293/* call this with spin lock held */
294static void snd_mtpav_output_port_write(mtpav_port_t *port,
295 snd_rawmidi_substream_t *substream)
296{
297 u8 outbyte;
298
299 // Get the outbyte first, so we can emulate running status if
300 // necessary
301 if (snd_rawmidi_transmit(substream, &outbyte, 1) != 1)
302 return;
303
304 // send port change command if necessary
305
306 if (port->hwport != mtp_card->outmidihwport) {
307 mtp_card->outmidihwport = port->hwport;
308
309 snd_mtpav_send_byte(mtp_card, 0xf5);
310 snd_mtpav_send_byte(mtp_card, port->hwport);
311 //snd_printk("new outport: 0x%x\n", (unsigned int) port->hwport);
312
313 if (!(outbyte & 0x80) && port->running_status)
314 snd_mtpav_send_byte(mtp_card, port->running_status);
315 }
316
317 // send data
318
319 do {
320 if (outbyte & 0x80)
321 port->running_status = outbyte;
322
323 snd_mtpav_send_byte(mtp_card, outbyte);
324 } while (snd_rawmidi_transmit(substream, &outbyte, 1) == 1);
325}
326
327static void snd_mtpav_output_write(snd_rawmidi_substream_t * substream)
328{
329 mtpav_port_t *port = &mtp_card->ports[substream->number];
330 unsigned long flags;
331
332 spin_lock_irqsave(&mtp_card->spinlock, flags);
333 snd_mtpav_output_port_write(port, substream);
334 spin_unlock_irqrestore(&mtp_card->spinlock, flags);
335}
336
337
338/*
339 * mtpav control
340 */
341
342static void snd_mtpav_portscan(mtpav_t *chip) // put mtp into smart routing mode
343{
344 u8 p;
345
346 for (p = 0; p < 8; p++) {
347 snd_mtpav_send_byte(chip, 0xf5);
348 snd_mtpav_send_byte(chip, p);
349 snd_mtpav_send_byte(chip, 0xfe);
350 }
351}
352
353/*
354 */
355
356static int snd_mtpav_input_open(snd_rawmidi_substream_t * substream)
357{
358 unsigned long flags;
359 mtpav_port_t *portp = &mtp_card->ports[substream->number];
360
361 //printk("mtpav port: %d opened\n", (int) substream->number);
362 spin_lock_irqsave(&mtp_card->spinlock, flags);
363 portp->mode |= MTPAV_MODE_INPUT_OPENED;
364 portp->input = substream;
365 if (mtp_card->share_irq++ == 0)
366 snd_mtpav_mputreg(mtp_card, CREG, (SIGC_INTEN | SIGC_WRITE)); // enable pport interrupts
367 spin_unlock_irqrestore(&mtp_card->spinlock, flags);
368 return 0;
369}
370
371/*
372 */
373
374static int snd_mtpav_input_close(snd_rawmidi_substream_t *substream)
375{
376 unsigned long flags;
377 mtpav_port_t *portp = &mtp_card->ports[substream->number];
378
379 //printk("mtpav port: %d closed\n", (int) portp);
380
381 spin_lock_irqsave(&mtp_card->spinlock, flags);
382
383 portp->mode &= (~MTPAV_MODE_INPUT_OPENED);
384 portp->input = NULL;
385 if (--mtp_card->share_irq == 0)
386 snd_mtpav_mputreg(mtp_card, CREG, 0); // disable pport interrupts
387
388 spin_unlock_irqrestore(&mtp_card->spinlock, flags);
389 return 0;
390}
391
392/*
393 */
394
395static void snd_mtpav_input_trigger(snd_rawmidi_substream_t * substream, int up)
396{
397 unsigned long flags;
398 mtpav_port_t *portp = &mtp_card->ports[substream->number];
399
400 spin_lock_irqsave(&mtp_card->spinlock, flags);
401 if (up)
402 portp->mode |= MTPAV_MODE_INPUT_TRIGGERED;
403 else
404 portp->mode &= ~MTPAV_MODE_INPUT_TRIGGERED;
405 spin_unlock_irqrestore(&mtp_card->spinlock, flags);
406
407}
408
409
410/*
411 * timer interrupt for outputs
412 */
413
414static void snd_mtpav_output_timer(unsigned long data)
415{
416 unsigned long flags;
417 mtpav_t *chip = (mtpav_t *)data;
418 int p;
419
420 spin_lock_irqsave(&chip->spinlock, flags);
421 /* reprogram timer */
422 chip->timer.expires = 1 + jiffies;
423 add_timer(&chip->timer);
424 /* process each port */
425 for (p = 0; p <= chip->num_ports * 2 + MTPAV_PIDX_BROADCAST; p++) {
426 mtpav_port_t *portp = &mtp_card->ports[p];
427 if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output)
428 snd_mtpav_output_port_write(portp, portp->output);
429 }
430 spin_unlock_irqrestore(&chip->spinlock, flags);
431}
432
433/* spinlock held! */
434static void snd_mtpav_add_output_timer(mtpav_t *chip)
435{
436 init_timer(&chip->timer);
437 chip->timer.function = snd_mtpav_output_timer;
438 chip->timer.data = (unsigned long) mtp_card;
439 chip->timer.expires = 1 + jiffies;
440 add_timer(&chip->timer);
441}
442
443/* spinlock held! */
444static void snd_mtpav_remove_output_timer(mtpav_t *chip)
445{
446 del_timer(&chip->timer);
447}
448
449/*
450 */
451
452static int snd_mtpav_output_open(snd_rawmidi_substream_t * substream)
453{
454 unsigned long flags;
455 mtpav_port_t *portp = &mtp_card->ports[substream->number];
456
457 spin_lock_irqsave(&mtp_card->spinlock, flags);
458 portp->mode |= MTPAV_MODE_OUTPUT_OPENED;
459 portp->output = substream;
460 spin_unlock_irqrestore(&mtp_card->spinlock, flags);
461 return 0;
462};
463
464/*
465 */
466
467static int snd_mtpav_output_close(snd_rawmidi_substream_t * substream)
468{
469 unsigned long flags;
470 mtpav_port_t *portp = &mtp_card->ports[substream->number];
471
472 spin_lock_irqsave(&mtp_card->spinlock, flags);
473 portp->mode &= (~MTPAV_MODE_OUTPUT_OPENED);
474 portp->output = NULL;
475 spin_unlock_irqrestore(&mtp_card->spinlock, flags);
476 return 0;
477};
478
479/*
480 */
481
482static void snd_mtpav_output_trigger(snd_rawmidi_substream_t * substream, int up)
483{
484 unsigned long flags;
485 mtpav_port_t *portp = &mtp_card->ports[substream->number];
486
487 spin_lock_irqsave(&mtp_card->spinlock, flags);
488 if (up) {
489 if (! (portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED)) {
490 if (mtp_card->istimer++ == 0)
491 snd_mtpav_add_output_timer(mtp_card);
492 portp->mode |= MTPAV_MODE_OUTPUT_TRIGGERED;
493 }
494 } else {
495 portp->mode &= ~MTPAV_MODE_OUTPUT_TRIGGERED;
496 if (--mtp_card->istimer == 0)
497 snd_mtpav_remove_output_timer(mtp_card);
498 }
499 spin_unlock_irqrestore(&mtp_card->spinlock, flags);
500
501 if (up)
502 snd_mtpav_output_write(substream);
503}
504
505/*
506 * midi interrupt for inputs
507 */
508
509static void snd_mtpav_inmidi_process(mtpav_t *mcrd, u8 inbyte)
510{
511 mtpav_port_t *portp;
512
513 if ((int)mcrd->inmidiport > mcrd->num_ports * 2 + MTPAV_PIDX_BROADCAST)
514 return;
515
516 portp = &mcrd->ports[mcrd->inmidiport];
517 if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) {
518 snd_rawmidi_receive(portp->input, &inbyte, 1);
519 }
520}
521
522static void snd_mtpav_inmidi_h(mtpav_t * mcrd, u8 inbyte)
523{
524 snd_assert(mcrd, return);
525
526 if (inbyte >= 0xf8) {
527 /* real-time midi code */
528 snd_mtpav_inmidi_process(mcrd, inbyte);
529 return;
530 }
531
532 if (mcrd->inmidistate == 0) { // awaiting command
533 if (inbyte == 0xf5) // MTP port #
534 mcrd->inmidistate = 1;
535 else
536 snd_mtpav_inmidi_process(mcrd, inbyte);
537 } else if (mcrd->inmidistate) {
538 mcrd->inmidiport = translate_hwport_to_subdevice(mcrd, inbyte);
539 mcrd->inmidistate = 0;
540 }
541}
542
543static void snd_mtpav_read_bytes(mtpav_t * mcrd)
544{
545 u8 clrread, setread;
546 u8 mtp_read_byte;
547 u8 sr, cbyt;
548 int i;
549
550 u8 sbyt = snd_mtpav_getreg(mcrd, SREG);
551
552 //printk("snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt);
553
554 if (!(sbyt & SIGS_BYTE))
555 return;
556
557 cbyt = snd_mtpav_getreg(mcrd, CREG);
558 clrread = cbyt & (SIGC_READ ^ 0xff);
559 setread = cbyt | SIGC_READ;
560
561 do {
562
563 mtp_read_byte = 0;
564 for (i = 0; i < 4; i++) {
565 snd_mtpav_mputreg(mcrd, CREG, setread);
566 sr = snd_mtpav_getreg(mcrd, SREG);
567 snd_mtpav_mputreg(mcrd, CREG, clrread);
568
569 sr &= SIGS_IN0 | SIGS_IN1;
570 sr >>= 4;
571 mtp_read_byte |= sr << (i * 2);
572 }
573
574 snd_mtpav_inmidi_h(mcrd, mtp_read_byte);
575
576 sbyt = snd_mtpav_getreg(mcrd, SREG);
577
578 } while (sbyt & SIGS_BYTE);
579}
580
581static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
582{
583 mtpav_t *mcard = dev_id;
584
585 //printk("irqh()\n");
586 spin_lock(&mcard->spinlock);
587 snd_mtpav_read_bytes(mcard);
588 spin_unlock(&mcard->spinlock);
589 return IRQ_HANDLED;
590}
591
592/*
593 * get ISA resources
594 */
595static int snd_mtpav_get_ISA(mtpav_t * mcard)
596{
597 if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
598 snd_printk("MTVAP port 0x%lx is busy\n", port);
599 return -EBUSY;
600 }
601 mcard->port = port;
602 if (request_irq(irq, snd_mtpav_irqh, SA_INTERRUPT, "MOTU MTPAV", (void *)mcard)) {
603 snd_printk("MTVAP IRQ %d busy\n", irq);
604 return -EBUSY;
605 }
606 mcard->irq = irq;
607 return 0;
608}
609
610
611/*
612 */
613
614static snd_rawmidi_ops_t snd_mtpav_output = {
615 .open = snd_mtpav_output_open,
616 .close = snd_mtpav_output_close,
617 .trigger = snd_mtpav_output_trigger,
618};
619
620static snd_rawmidi_ops_t snd_mtpav_input = {
621 .open = snd_mtpav_input_open,
622 .close = snd_mtpav_input_close,
623 .trigger = snd_mtpav_input_trigger,
624};
625
626
627/*
628 * get RAWMIDI resources
629 */
630
631static void snd_mtpav_set_name(mtpav_t *chip, snd_rawmidi_substream_t *substream)
632{
633 if (substream->number >= 0 && substream->number < chip->num_ports)
634 sprintf(substream->name, "MTP direct %d", (substream->number % chip->num_ports) + 1);
635 else if (substream->number >= 8 && substream->number < chip->num_ports * 2)
636 sprintf(substream->name, "MTP remote %d", (substream->number % chip->num_ports) + 1);
637 else if (substream->number == chip->num_ports * 2)
638 strcpy(substream->name, "MTP computer");
639 else if (substream->number == chip->num_ports * 2 + 1)
640 strcpy(substream->name, "MTP ADAT");
641 else
642 strcpy(substream->name, "MTP broadcast");
643}
644
645static int snd_mtpav_get_RAWMIDI(mtpav_t * mcard)
646{
647 int rval = 0;
648 snd_rawmidi_t *rawmidi;
649 snd_rawmidi_substream_t *substream;
650 struct list_head *list;
651
652 //printk("entering snd_mtpav_get_RAWMIDI\n");
653
654 if (hwports < 1)
655 mcard->num_ports = 1;
656 else if (hwports > 8)
657 mcard->num_ports = 8;
658 else
659 mcard->num_ports = hwports;
660
661 if ((rval = snd_rawmidi_new(mcard->card, "MotuMIDI", 0,
662 mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
663 mcard->num_ports * 2 + MTPAV_PIDX_BROADCAST + 1,
664 &mcard->rmidi)) < 0)
665 return rval;
666 rawmidi = mcard->rmidi;
667
668 list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
669 substream = list_entry(list, snd_rawmidi_substream_t, list);
670 snd_mtpav_set_name(mcard, substream);
671 substream->ops = &snd_mtpav_input;
672 }
673 list_for_each(list, &rawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
674 substream = list_entry(list, snd_rawmidi_substream_t, list);
675 snd_mtpav_set_name(mcard, substream);
676 substream->ops = &snd_mtpav_output;
677 mcard->ports[substream->number].hwport = translate_subdevice_to_hwport(mcard, substream->number);
678 }
679 rawmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT |
680 SNDRV_RAWMIDI_INFO_DUPLEX;
681 sprintf(rawmidi->name, "MTP AV MIDI");
682 //printk("exiting snd_mtpav_get_RAWMIDI() \n");
683 return 0;
684}
685
686/*
687 */
688
689static mtpav_t *new_mtpav(void)
690{
691 mtpav_t *ncrd = kcalloc(1, sizeof(*ncrd), GFP_KERNEL);
692 if (ncrd != NULL) {
693 spin_lock_init(&ncrd->spinlock);
694
695 init_timer(&ncrd->timer);
696 ncrd->card = NULL;
697 ncrd->irq = -1;
698 ncrd->share_irq = 0;
699
700 ncrd->inmidiport = 0xffffffff;
701 ncrd->inmidistate = 0;
702 ncrd->outmidihwport = 0xffffffff;
703 }
704 return ncrd;
705}
706
707/*
708 */
709
710static void free_mtpav(mtpav_t * crd)
711{
712 unsigned long flags;
713
714 spin_lock_irqsave(&crd->spinlock, flags);
715 if (crd->istimer > 0)
716 snd_mtpav_remove_output_timer(crd);
717 spin_unlock_irqrestore(&crd->spinlock, flags);
718 if (crd->irq >= 0)
719 free_irq(crd->irq, (void *)crd);
720 if (crd->res_port) {
721 release_resource(crd->res_port);
722 kfree_nocheck(crd->res_port);
723 }
724 kfree(crd);
725}
726
727/*
728 */
729
730static int __init alsa_card_mtpav_init(void)
731{
732 int err = 0;
733 char longname_buffer[80];
734
735 mtp_card = new_mtpav();
736 if (mtp_card == NULL)
737 return -ENOMEM;
738
739 mtp_card->card = snd_card_new(index, id, THIS_MODULE, 0);
740 if (mtp_card->card == NULL) {
741 free_mtpav(mtp_card);
742 return -ENOMEM;
743 }
744
745 err = snd_mtpav_get_ISA(mtp_card);
746 //printk("snd_mtpav_get_ISA returned: %d\n", err);
747 if (err < 0)
748 goto __error;
749
750 strcpy(mtp_card->card->driver, "MTPAV");
751 strcpy(mtp_card->card->shortname, "MTPAV on parallel port");
752 memset(longname_buffer, 0, sizeof(longname_buffer));
753 sprintf(longname_buffer, "MTPAV on parallel port at");
754
755 err = snd_mtpav_get_RAWMIDI(mtp_card);
756 //snd_printk("snd_mtapv_get_RAWMIDI returned: %d\n", err);
757 if (err < 0)
758 goto __error;
759
760 err = snd_card_register(mtp_card->card); // don't snd_card_register until AFTER all cards reources done!
761
762 //printk("snd_card_register returned %d\n", err);
763 if (err < 0)
764 goto __error;
765
766
767 snd_mtpav_portscan(mtp_card);
768
769 printk(KERN_INFO "Motu MidiTimePiece on parallel port irq: %d ioport: 0x%lx\n", irq, port);
770
771 return 0;
772
773 __error:
774 snd_card_free(mtp_card->card);
775 free_mtpav(mtp_card);
776 return err;
777}
778
779/*
780 */
781
782static void __exit alsa_card_mtpav_exit(void)
783{
784 if (mtp_card == NULL)
785 return;
786 if (mtp_card->card)
787 snd_card_free(mtp_card->card);
788 free_mtpav(mtp_card);
789}
790
791/*
792 */
793
794module_init(alsa_card_mtpav_init)
795module_exit(alsa_card_mtpav_exit)
diff --git a/sound/drivers/opl3/Makefile b/sound/drivers/opl3/Makefile
new file mode 100644
index 000000000000..12059785b5cb
--- /dev/null
+++ b/sound/drivers/opl3/Makefile
@@ -0,0 +1,22 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-opl3-lib-objs := opl3_lib.o opl3_synth.o
7snd-opl3-synth-objs := opl3_seq.o opl3_midi.o opl3_drums.o
8ifeq ($(CONFIG_SND_SEQUENCER_OSS),y)
9snd-opl3-synth-objs += opl3_oss.o
10endif
11
12#
13# this function returns:
14# "m" - CONFIG_SND_SEQUENCER is m
15# <empty string> - CONFIG_SND_SEQUENCER is undefined
16# otherwise parameter #1 value
17#
18sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
19
20obj-$(CONFIG_SND_OPL3_LIB) += snd-opl3-lib.o
21obj-$(CONFIG_SND_OPL4_LIB) += snd-opl3-lib.o
22obj-$(call sequencer,$(CONFIG_SND_OPL3_LIB)) += snd-opl3-synth.o
diff --git a/sound/drivers/opl3/opl3_drums.c b/sound/drivers/opl3/opl3_drums.c
new file mode 100644
index 000000000000..f26332680c19
--- /dev/null
+++ b/sound/drivers/opl3/opl3_drums.c
@@ -0,0 +1,223 @@
1/*
2 * Copyright (c) by Uros Bizjak <uros@kss-loka.si>
3 *
4 * OPL2/OPL3/OPL4 FM routines for internal percussion channels
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include "opl3_voice.h"
23
24extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
25
26static char snd_opl3_drum_table[47] =
27{
28 OPL3_BASSDRUM_ON, OPL3_BASSDRUM_ON, OPL3_HIHAT_ON, /* 35 - 37 */
29 OPL3_SNAREDRUM_ON, OPL3_HIHAT_ON, OPL3_SNAREDRUM_ON, /* 38 - 40 */
30 OPL3_BASSDRUM_ON, OPL3_HIHAT_ON, OPL3_BASSDRUM_ON, /* 41 - 43 */
31 OPL3_HIHAT_ON, OPL3_TOMTOM_ON, OPL3_HIHAT_ON, /* 44 - 46 */
32 OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_CYMBAL_ON, /* 47 - 49 */
33
34 OPL3_TOMTOM_ON, OPL3_CYMBAL_ON, OPL3_CYMBAL_ON, /* 50 - 52 */
35 OPL3_CYMBAL_ON, OPL3_CYMBAL_ON, OPL3_CYMBAL_ON, /* 53 - 55 */
36 OPL3_HIHAT_ON, OPL3_CYMBAL_ON, OPL3_TOMTOM_ON, /* 56 - 58 */
37 OPL3_CYMBAL_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 59 - 61 */
38 OPL3_HIHAT_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 62 - 64 */
39
40 OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 65 - 67 */
41 OPL3_TOMTOM_ON, OPL3_HIHAT_ON, OPL3_HIHAT_ON, /* 68 - 70 */
42 OPL3_HIHAT_ON, OPL3_HIHAT_ON, OPL3_TOMTOM_ON, /* 71 - 73 */
43 OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 74 - 76 */
44 OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, OPL3_TOMTOM_ON, /* 77 - 79 */
45 OPL3_CYMBAL_ON, OPL3_CYMBAL_ON /* 80 - 81 */
46};
47
48typedef struct snd_opl3_drum_voice {
49 int voice;
50 int op;
51 unsigned char am_vib;
52 unsigned char ksl_level;
53 unsigned char attack_decay;
54 unsigned char sustain_release;
55 unsigned char feedback_connection;
56 unsigned char wave_select;
57} snd_opl3_drum_voice_t;
58
59typedef struct snd_opl3_drum_note {
60 int voice;
61 unsigned char fnum;
62 unsigned char octave_f;
63 unsigned char feedback_connection;
64} snd_opl3_drum_note_t;
65
66static snd_opl3_drum_voice_t bass_op0 = {6, 0, 0x00, 0x32, 0xf8, 0x66, 0x30, 0x00};
67static snd_opl3_drum_voice_t bass_op1 = {6, 1, 0x00, 0x03, 0xf6, 0x57, 0x30, 0x00};
68static snd_opl3_drum_note_t bass_note = {6, 0x90, 0x09};
69
70static snd_opl3_drum_voice_t hihat = {7, 0, 0x00, 0x03, 0xf0, 0x06, 0x20, 0x00};
71
72static snd_opl3_drum_voice_t snare = {7, 1, 0x00, 0x03, 0xf0, 0x07, 0x20, 0x02};
73static snd_opl3_drum_note_t snare_note = {7, 0xf4, 0x0d};
74
75static snd_opl3_drum_voice_t tomtom = {8, 0, 0x02, 0x03, 0xf0, 0x06, 0x10, 0x00};
76static snd_opl3_drum_note_t tomtom_note = {8, 0xf4, 0x09};
77
78static snd_opl3_drum_voice_t cymbal = {8, 1, 0x04, 0x03, 0xf0, 0x06, 0x10, 0x00};
79
80/*
81 * set drum voice characteristics
82 */
83static void snd_opl3_drum_voice_set(opl3_t *opl3, snd_opl3_drum_voice_t *data)
84{
85 unsigned char op_offset = snd_opl3_regmap[data->voice][data->op];
86 unsigned char voice_offset = data->voice;
87 unsigned short opl3_reg;
88
89 /* Set OPL3 AM_VIB register */
90 opl3_reg = OPL3_LEFT | (OPL3_REG_AM_VIB + op_offset);
91 opl3->command(opl3, opl3_reg, data->am_vib);
92
93 /* Set OPL3 KSL_LEVEL register */
94 opl3_reg = OPL3_LEFT | (OPL3_REG_KSL_LEVEL + op_offset);
95 opl3->command(opl3, opl3_reg, data->ksl_level);
96
97 /* Set OPL3 ATTACK_DECAY register */
98 opl3_reg = OPL3_LEFT | (OPL3_REG_ATTACK_DECAY + op_offset);
99 opl3->command(opl3, opl3_reg, data->attack_decay);
100
101 /* Set OPL3 SUSTAIN_RELEASE register */
102 opl3_reg = OPL3_LEFT | (OPL3_REG_SUSTAIN_RELEASE + op_offset);
103 opl3->command(opl3, opl3_reg, data->sustain_release);
104
105 /* Set OPL3 FEEDBACK_CONNECTION register */
106 opl3_reg = OPL3_LEFT | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset);
107 opl3->command(opl3, opl3_reg, data->feedback_connection);
108
109 /* Select waveform */
110 opl3_reg = OPL3_LEFT | (OPL3_REG_WAVE_SELECT + op_offset);
111 opl3->command(opl3, opl3_reg, data->wave_select);
112}
113
114/*
115 * Set drum voice pitch
116 */
117static void snd_opl3_drum_note_set(opl3_t *opl3, snd_opl3_drum_note_t *data)
118{
119 unsigned char voice_offset = data->voice;
120 unsigned short opl3_reg;
121
122 /* Set OPL3 FNUM_LOW register */
123 opl3_reg = OPL3_LEFT | (OPL3_REG_FNUM_LOW + voice_offset);
124 opl3->command(opl3, opl3_reg, data->fnum);
125
126 /* Set OPL3 KEYON_BLOCK register */
127 opl3_reg = OPL3_LEFT | (OPL3_REG_KEYON_BLOCK + voice_offset);
128 opl3->command(opl3, opl3_reg, data->octave_f);
129}
130
131/*
132 * Set drum voice volume and position
133 */
134static void snd_opl3_drum_vol_set(opl3_t *opl3, snd_opl3_drum_voice_t *data,
135 int vel, snd_midi_channel_t *chan)
136{
137 unsigned char op_offset = snd_opl3_regmap[data->voice][data->op];
138 unsigned char voice_offset = data->voice;
139 unsigned char reg_val;
140 unsigned short opl3_reg;
141
142 /* Set OPL3 KSL_LEVEL register */
143 reg_val = data->ksl_level;
144 snd_opl3_calc_volume(&reg_val, vel, chan);
145 opl3_reg = OPL3_LEFT | (OPL3_REG_KSL_LEVEL + op_offset);
146 opl3->command(opl3, opl3_reg, reg_val);
147
148 /* Set OPL3 FEEDBACK_CONNECTION register */
149 /* Set output voice connection */
150 reg_val = data->feedback_connection | OPL3_STEREO_BITS;
151 if (chan->gm_pan < 43)
152 reg_val &= ~OPL3_VOICE_TO_RIGHT;
153 if (chan->gm_pan > 85)
154 reg_val &= ~OPL3_VOICE_TO_LEFT;
155 opl3_reg = OPL3_LEFT | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset);
156 opl3->command(opl3, opl3_reg, reg_val);
157}
158
159/*
160 * Loads drum voices at init time
161 */
162void snd_opl3_load_drums(opl3_t *opl3)
163{
164 snd_opl3_drum_voice_set(opl3, &bass_op0);
165 snd_opl3_drum_voice_set(opl3, &bass_op1);
166 snd_opl3_drum_note_set(opl3, &bass_note);
167
168 snd_opl3_drum_voice_set(opl3, &hihat);
169
170 snd_opl3_drum_voice_set(opl3, &snare);
171 snd_opl3_drum_note_set(opl3, &snare_note);
172
173 snd_opl3_drum_voice_set(opl3, &tomtom);
174 snd_opl3_drum_note_set(opl3, &tomtom_note);
175
176 snd_opl3_drum_voice_set(opl3, &cymbal);
177}
178
179/*
180 * Switch drum voice on or off
181 */
182void snd_opl3_drum_switch(opl3_t *opl3, int note, int vel, int on_off,
183 snd_midi_channel_t *chan)
184{
185 unsigned char drum_mask;
186 snd_opl3_drum_voice_t *drum_voice;
187
188 if (!(opl3->drum_reg & OPL3_PERCUSSION_ENABLE))
189 return;
190
191 if ((note < 35) || (note > 81))
192 return;
193 drum_mask = snd_opl3_drum_table[note - 35];
194
195 if (on_off) {
196 switch (drum_mask) {
197 case OPL3_BASSDRUM_ON:
198 drum_voice = &bass_op1;
199 break;
200 case OPL3_HIHAT_ON:
201 drum_voice = &hihat;
202 break;
203 case OPL3_SNAREDRUM_ON:
204 drum_voice = &snare;
205 break;
206 case OPL3_TOMTOM_ON:
207 drum_voice = &tomtom;
208 break;
209 case OPL3_CYMBAL_ON:
210 drum_voice = &cymbal;
211 break;
212 default:
213 drum_voice = &tomtom;
214 }
215
216 snd_opl3_drum_vol_set(opl3, drum_voice, vel, chan);
217 opl3->drum_reg |= drum_mask;
218 } else {
219 opl3->drum_reg &= ~drum_mask;
220 }
221 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION,
222 opl3->drum_reg);
223}
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
new file mode 100644
index 000000000000..c313e5205cb8
--- /dev/null
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -0,0 +1,558 @@
1/*
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
3 * Hannu Savolainen 1993-1996,
4 * Rob Hooft
5 *
6 * Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)
7 *
8 * Most if code is ported from OSS/Lite.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26#include <sound/opl3.h>
27#include <asm/io.h>
28#include <linux/delay.h>
29#include <linux/init.h>
30#include <linux/slab.h>
31#include <linux/ioport.h>
32#include <sound/minors.h>
33
34MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>, Hannu Savolainen 1993-1996, Rob Hooft");
35MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)");
36MODULE_LICENSE("GPL");
37
38extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
39
40static void snd_opl2_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
41{
42 unsigned long flags;
43 unsigned long port;
44
45 /*
46 * The original 2-OP synth requires a quite long delay
47 * after writing to a register.
48 */
49
50 port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port;
51
52 spin_lock_irqsave(&opl3->reg_lock, flags);
53
54 outb((unsigned char) cmd, port);
55 udelay(10);
56
57 outb((unsigned char) val, port + 1);
58 udelay(30);
59
60 spin_unlock_irqrestore(&opl3->reg_lock, flags);
61}
62
63static void snd_opl3_command(opl3_t * opl3, unsigned short cmd, unsigned char val)
64{
65 unsigned long flags;
66 unsigned long port;
67
68 /*
69 * The OPL-3 survives with just two INBs
70 * after writing to a register.
71 */
72
73 port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port;
74
75 spin_lock_irqsave(&opl3->reg_lock, flags);
76
77 outb((unsigned char) cmd, port);
78 inb(opl3->l_port);
79 inb(opl3->l_port);
80
81 outb((unsigned char) val, port + 1);
82 inb(opl3->l_port);
83 inb(opl3->l_port);
84
85 spin_unlock_irqrestore(&opl3->reg_lock, flags);
86}
87
88static int snd_opl3_detect(opl3_t * opl3)
89{
90 /*
91 * This function returns 1 if the FM chip is present at the given I/O port
92 * The detection algorithm plays with the timer built in the FM chip and
93 * looks for a change in the status register.
94 *
95 * Note! The timers of the FM chip are not connected to AdLib (and compatible)
96 * boards.
97 *
98 * Note2! The chip is initialized if detected.
99 */
100
101 unsigned char stat1, stat2, signature;
102
103 /* Reset timers 1 and 2 */
104 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK);
105 /* Reset the IRQ of the FM chip */
106 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
107 signature = stat1 = inb(opl3->l_port); /* Status register */
108 if ((stat1 & 0xe0) != 0x00) { /* Should be 0x00 */
109 snd_printd("OPL3: stat1 = 0x%x\n", stat1);
110 return -ENODEV;
111 }
112 /* Set timer1 to 0xff */
113 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 0xff);
114 /* Unmask and start timer 1 */
115 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER2_MASK | OPL3_TIMER1_START);
116 /* Now we have to delay at least 80us */
117 udelay(200);
118 /* Read status after timers have expired */
119 stat2 = inb(opl3->l_port);
120 /* Stop the timers */
121 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK);
122 /* Reset the IRQ of the FM chip */
123 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);
124 if ((stat2 & 0xe0) != 0xc0) { /* There is no YM3812 */
125 snd_printd("OPL3: stat2 = 0x%x\n", stat2);
126 return -ENODEV;
127 }
128
129 /* If the toplevel code knows exactly the type of chip, don't try
130 to detect it. */
131 if (opl3->hardware != OPL3_HW_AUTO)
132 return 0;
133
134 /* There is a FM chip on this address. Detect the type (OPL2 to OPL4) */
135 if (signature == 0x06) { /* OPL2 */
136 opl3->hardware = OPL3_HW_OPL2;
137 } else {
138 /*
139 * If we had an OPL4 chip, opl3->hardware would have been set
140 * by the OPL4 driver; so we can assume OPL3 here.
141 */
142 snd_assert(opl3->r_port != 0, return -ENODEV);
143 opl3->hardware = OPL3_HW_OPL3;
144 }
145 return 0;
146}
147
148/*
149 * AdLib timers
150 */
151
152/*
153 * Timer 1 - 80us
154 */
155
156static int snd_opl3_timer1_start(snd_timer_t * timer)
157{
158 unsigned long flags;
159 unsigned char tmp;
160 unsigned int ticks;
161 opl3_t *opl3;
162
163 opl3 = snd_timer_chip(timer);
164 spin_lock_irqsave(&opl3->timer_lock, flags);
165 ticks = timer->sticks;
166 tmp = (opl3->timer_enable | OPL3_TIMER1_START) & ~OPL3_TIMER1_MASK;
167 opl3->timer_enable = tmp;
168 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 256 - ticks); /* timer 1 count */
169 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */
170 spin_unlock_irqrestore(&opl3->timer_lock, flags);
171 return 0;
172}
173
174static int snd_opl3_timer1_stop(snd_timer_t * timer)
175{
176 unsigned long flags;
177 unsigned char tmp;
178 opl3_t *opl3;
179
180 opl3 = snd_timer_chip(timer);
181 spin_lock_irqsave(&opl3->timer_lock, flags);
182 tmp = (opl3->timer_enable | OPL3_TIMER1_MASK) & ~OPL3_TIMER1_START;
183 opl3->timer_enable = tmp;
184 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */
185 spin_unlock_irqrestore(&opl3->timer_lock, flags);
186 return 0;
187}
188
189/*
190 * Timer 2 - 320us
191 */
192
193static int snd_opl3_timer2_start(snd_timer_t * timer)
194{
195 unsigned long flags;
196 unsigned char tmp;
197 unsigned int ticks;
198 opl3_t *opl3;
199
200 opl3 = snd_timer_chip(timer);
201 spin_lock_irqsave(&opl3->timer_lock, flags);
202 ticks = timer->sticks;
203 tmp = (opl3->timer_enable | OPL3_TIMER2_START) & ~OPL3_TIMER2_MASK;
204 opl3->timer_enable = tmp;
205 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER2, 256 - ticks); /* timer 1 count */
206 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */
207 spin_unlock_irqrestore(&opl3->timer_lock, flags);
208 return 0;
209}
210
211static int snd_opl3_timer2_stop(snd_timer_t * timer)
212{
213 unsigned long flags;
214 unsigned char tmp;
215 opl3_t *opl3;
216
217 opl3 = snd_timer_chip(timer);
218 spin_lock_irqsave(&opl3->timer_lock, flags);
219 tmp = (opl3->timer_enable | OPL3_TIMER2_MASK) & ~OPL3_TIMER2_START;
220 opl3->timer_enable = tmp;
221 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */
222 spin_unlock_irqrestore(&opl3->timer_lock, flags);
223 return 0;
224}
225
226/*
227
228 */
229
230static struct _snd_timer_hardware snd_opl3_timer1 =
231{
232 .flags = SNDRV_TIMER_HW_STOP,
233 .resolution = 80000,
234 .ticks = 256,
235 .start = snd_opl3_timer1_start,
236 .stop = snd_opl3_timer1_stop,
237};
238
239static struct _snd_timer_hardware snd_opl3_timer2 =
240{
241 .flags = SNDRV_TIMER_HW_STOP,
242 .resolution = 320000,
243 .ticks = 256,
244 .start = snd_opl3_timer2_start,
245 .stop = snd_opl3_timer2_stop,
246};
247
248static int snd_opl3_timer1_init(opl3_t * opl3, int timer_no)
249{
250 snd_timer_t *timer = NULL;
251 snd_timer_id_t tid;
252 int err;
253
254 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
255 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
256 tid.card = opl3->card->number;
257 tid.device = timer_no;
258 tid.subdevice = 0;
259 if ((err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer)) >= 0) {
260 strcpy(timer->name, "AdLib timer #1");
261 timer->private_data = opl3;
262 timer->hw = snd_opl3_timer1;
263 }
264 opl3->timer1 = timer;
265 return err;
266}
267
268static int snd_opl3_timer2_init(opl3_t * opl3, int timer_no)
269{
270 snd_timer_t *timer = NULL;
271 snd_timer_id_t tid;
272 int err;
273
274 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
275 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
276 tid.card = opl3->card->number;
277 tid.device = timer_no;
278 tid.subdevice = 0;
279 if ((err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer)) >= 0) {
280 strcpy(timer->name, "AdLib timer #2");
281 timer->private_data = opl3;
282 timer->hw = snd_opl3_timer2;
283 }
284 opl3->timer2 = timer;
285 return err;
286}
287
288/*
289
290 */
291
292void snd_opl3_interrupt(snd_hwdep_t * hw)
293{
294 unsigned char status;
295 opl3_t *opl3;
296 snd_timer_t *timer;
297
298 if (hw == NULL)
299 return;
300
301 opl3 = hw->private_data;
302 status = inb(opl3->l_port);
303#if 0
304 snd_printk("AdLib IRQ status = 0x%x\n", status);
305#endif
306 if (!(status & 0x80))
307 return;
308
309 if (status & 0x40) {
310 timer = opl3->timer1;
311 snd_timer_interrupt(timer, timer->sticks);
312 }
313 if (status & 0x20) {
314 timer = opl3->timer2;
315 snd_timer_interrupt(timer, timer->sticks);
316 }
317}
318
319/*
320
321 */
322
323static int snd_opl3_free(opl3_t *opl3)
324{
325 snd_assert(opl3 != NULL, return -ENXIO);
326 if (opl3->private_free)
327 opl3->private_free(opl3);
328 if (opl3->res_l_port) {
329 release_resource(opl3->res_l_port);
330 kfree_nocheck(opl3->res_l_port);
331 }
332 if (opl3->res_r_port) {
333 release_resource(opl3->res_r_port);
334 kfree_nocheck(opl3->res_r_port);
335 }
336 kfree(opl3);
337 return 0;
338}
339
340static int snd_opl3_dev_free(snd_device_t *device)
341{
342 opl3_t *opl3 = device->device_data;
343 return snd_opl3_free(opl3);
344}
345
346int snd_opl3_new(snd_card_t *card,
347 unsigned short hardware,
348 opl3_t **ropl3)
349{
350 static snd_device_ops_t ops = {
351 .dev_free = snd_opl3_dev_free,
352 };
353 opl3_t *opl3;
354 int err;
355
356 *ropl3 = NULL;
357 opl3 = kcalloc(1, sizeof(*opl3), GFP_KERNEL);
358 if (opl3 == NULL)
359 return -ENOMEM;
360
361 opl3->card = card;
362 opl3->hardware = hardware;
363 spin_lock_init(&opl3->reg_lock);
364 spin_lock_init(&opl3->timer_lock);
365 init_MUTEX(&opl3->access_mutex);
366
367 if ((err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops)) < 0) {
368 snd_opl3_free(opl3);
369 return err;
370 }
371
372 *ropl3 = opl3;
373 return 0;
374}
375
376int snd_opl3_init(opl3_t *opl3)
377{
378 if (! opl3->command) {
379 printk(KERN_ERR "snd_opl3_init: command not defined!\n");
380 return -EINVAL;
381 }
382
383 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
384 /* Melodic mode */
385 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00);
386
387 switch (opl3->hardware & OPL3_HW_MASK) {
388 case OPL3_HW_OPL2:
389 opl3->max_voices = MAX_OPL2_VOICES;
390 break;
391 case OPL3_HW_OPL3:
392 case OPL3_HW_OPL4:
393 opl3->max_voices = MAX_OPL3_VOICES;
394 /* Enter OPL3 mode */
395 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE);
396 }
397 return 0;
398}
399
400int snd_opl3_create(snd_card_t * card,
401 unsigned long l_port,
402 unsigned long r_port,
403 unsigned short hardware,
404 int integrated,
405 opl3_t ** ropl3)
406{
407 opl3_t *opl3;
408 int err;
409
410 *ropl3 = NULL;
411 if ((err = snd_opl3_new(card, hardware, &opl3)) < 0)
412 return err;
413 if (! integrated) {
414 if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) {
415 snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port);
416 snd_opl3_free(opl3);
417 return -EBUSY;
418 }
419 if (r_port != 0 &&
420 (opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) {
421 snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
422 snd_opl3_free(opl3);
423 return -EBUSY;
424 }
425 }
426 opl3->l_port = l_port;
427 opl3->r_port = r_port;
428
429 switch (opl3->hardware) {
430 /* some hardware doesn't support timers */
431 case OPL3_HW_OPL3_SV:
432 case OPL3_HW_OPL3_CS:
433 case OPL3_HW_OPL3_FM801:
434 opl3->command = &snd_opl3_command;
435 break;
436 default:
437 opl3->command = &snd_opl2_command;
438 if ((err = snd_opl3_detect(opl3)) < 0) {
439 snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n",
440 opl3->l_port, opl3->r_port);
441 snd_opl3_free(opl3);
442 return err;
443 }
444 /* detect routine returns correct hardware type */
445 switch (opl3->hardware & OPL3_HW_MASK) {
446 case OPL3_HW_OPL3:
447 case OPL3_HW_OPL4:
448 opl3->command = &snd_opl3_command;
449 }
450 }
451
452 snd_opl3_init(opl3);
453
454 *ropl3 = opl3;
455 return 0;
456}
457
458int snd_opl3_timer_new(opl3_t * opl3, int timer1_dev, int timer2_dev)
459{
460 int err;
461
462 if (timer1_dev >= 0)
463 if ((err = snd_opl3_timer1_init(opl3, timer1_dev)) < 0)
464 return err;
465 if (timer2_dev >= 0) {
466 if ((err = snd_opl3_timer2_init(opl3, timer2_dev)) < 0) {
467 snd_device_free(opl3->card, opl3->timer1);
468 opl3->timer1 = NULL;
469 return err;
470 }
471 }
472 return 0;
473}
474
475int snd_opl3_hwdep_new(opl3_t * opl3,
476 int device, int seq_device,
477 snd_hwdep_t ** rhwdep)
478{
479 snd_hwdep_t *hw;
480 snd_card_t *card = opl3->card;
481 int err;
482
483 if (rhwdep)
484 *rhwdep = NULL;
485
486 /* create hardware dependent device (direct FM) */
487
488 if ((err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw)) < 0) {
489 snd_device_free(card, opl3);
490 return err;
491 }
492 hw->private_data = opl3;
493#ifdef CONFIG_SND_OSSEMUL
494 if (device == 0) {
495 hw->oss_type = SNDRV_OSS_DEVICE_TYPE_DMFM;
496 sprintf(hw->oss_dev, "dmfm%i", card->number);
497 }
498#endif
499 strcpy(hw->name, hw->id);
500 switch (opl3->hardware & OPL3_HW_MASK) {
501 case OPL3_HW_OPL2:
502 strcpy(hw->name, "OPL2 FM");
503 hw->iface = SNDRV_HWDEP_IFACE_OPL2;
504 break;
505 case OPL3_HW_OPL3:
506 strcpy(hw->name, "OPL3 FM");
507 hw->iface = SNDRV_HWDEP_IFACE_OPL3;
508 break;
509 case OPL3_HW_OPL4:
510 strcpy(hw->name, "OPL4 FM");
511 hw->iface = SNDRV_HWDEP_IFACE_OPL4;
512 break;
513 }
514
515 /* operators - only ioctl */
516 hw->ops.open = snd_opl3_open;
517 hw->ops.ioctl = snd_opl3_ioctl;
518 hw->ops.release = snd_opl3_release;
519
520 opl3->seq_dev_num = seq_device;
521#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
522 if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,
523 sizeof(opl3_t*), &opl3->seq_dev) >= 0) {
524 strcpy(opl3->seq_dev->name, hw->name);
525 *(opl3_t**)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3;
526 }
527#endif
528 if (rhwdep)
529 *rhwdep = hw;
530 return 0;
531}
532
533EXPORT_SYMBOL(snd_opl3_interrupt);
534EXPORT_SYMBOL(snd_opl3_new);
535EXPORT_SYMBOL(snd_opl3_init);
536EXPORT_SYMBOL(snd_opl3_create);
537EXPORT_SYMBOL(snd_opl3_timer_new);
538EXPORT_SYMBOL(snd_opl3_hwdep_new);
539
540/* opl3_synth.c */
541EXPORT_SYMBOL(snd_opl3_regmap);
542EXPORT_SYMBOL(snd_opl3_reset);
543
544/*
545 * INIT part
546 */
547
548static int __init alsa_opl3_init(void)
549{
550 return 0;
551}
552
553static void __exit alsa_opl3_exit(void)
554{
555}
556
557module_init(alsa_opl3_init)
558module_exit(alsa_opl3_exit)
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
new file mode 100644
index 000000000000..93d674070b71
--- /dev/null
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -0,0 +1,873 @@
1/*
2 * Copyright (c) by Uros Bizjak <uros@kss-loka.si>
3 *
4 * Midi synth routines for OPL2/OPL3/OPL4 FM
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#undef DEBUG_ALLOC
23#undef DEBUG_MIDI
24
25#include "opl3_voice.h"
26#include <sound/asoundef.h>
27
28extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
29
30extern int use_internal_drums;
31
32/*
33 * The next table looks magical, but it certainly is not. Its values have
34 * been calculated as table[i]=8*log(i/64)/log(2) with an obvious exception
35 * for i=0. This log-table converts a linear volume-scaling (0..127) to a
36 * logarithmic scaling as present in the FM-synthesizer chips. so : Volume
37 * 64 = 0 db = relative volume 0 and: Volume 32 = -6 db = relative
38 * volume -8 it was implemented as a table because it is only 128 bytes and
39 * it saves a lot of log() calculations. (Rob Hooft <hooft@chem.ruu.nl>)
40 */
41
42static char opl3_volume_table[128] =
43{
44 -63, -48, -40, -35, -32, -29, -27, -26,
45 -24, -23, -21, -20, -19, -18, -18, -17,
46 -16, -15, -15, -14, -13, -13, -12, -12,
47 -11, -11, -10, -10, -10, -9, -9, -8,
48 -8, -8, -7, -7, -7, -6, -6, -6,
49 -5, -5, -5, -5, -4, -4, -4, -4,
50 -3, -3, -3, -3, -2, -2, -2, -2,
51 -2, -1, -1, -1, -1, 0, 0, 0,
52 0, 0, 0, 1, 1, 1, 1, 1,
53 1, 2, 2, 2, 2, 2, 2, 2,
54 3, 3, 3, 3, 3, 3, 3, 4,
55 4, 4, 4, 4, 4, 4, 4, 5,
56 5, 5, 5, 5, 5, 5, 5, 5,
57 6, 6, 6, 6, 6, 6, 6, 6,
58 6, 7, 7, 7, 7, 7, 7, 7,
59 7, 7, 7, 8, 8, 8, 8, 8
60};
61
62void snd_opl3_calc_volume(unsigned char *volbyte, int vel,
63 snd_midi_channel_t *chan)
64{
65 int oldvol, newvol, n;
66 int volume;
67
68 volume = (vel * chan->gm_volume * chan->gm_expression) / (127*127);
69 if (volume > 127)
70 volume = 127;
71
72 oldvol = OPL3_TOTAL_LEVEL_MASK - (*volbyte & OPL3_TOTAL_LEVEL_MASK);
73
74 newvol = opl3_volume_table[volume] + oldvol;
75 if (newvol > OPL3_TOTAL_LEVEL_MASK)
76 newvol = OPL3_TOTAL_LEVEL_MASK;
77 else if (newvol < 0)
78 newvol = 0;
79
80 n = OPL3_TOTAL_LEVEL_MASK - (newvol & OPL3_TOTAL_LEVEL_MASK);
81
82 *volbyte = (*volbyte & OPL3_KSL_MASK) | (n & OPL3_TOTAL_LEVEL_MASK);
83}
84
85/*
86 * Converts the note frequency to block and fnum values for the FM chip
87 */
88static short opl3_note_table[16] =
89{
90 305, 323, /* for pitch bending, -2 semitones */
91 343, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647,
92 686, 726 /* for pitch bending, +2 semitones */
93};
94
95static void snd_opl3_calc_pitch(unsigned char *fnum, unsigned char *blocknum,
96 int note, snd_midi_channel_t *chan)
97{
98 int block = ((note / 12) & 0x07) - 1;
99 int idx = (note % 12) + 2;
100 int freq;
101
102 if (chan->midi_pitchbend) {
103 int pitchbend = chan->midi_pitchbend;
104 int segment;
105
106 if (pitchbend > 0x1FFF)
107 pitchbend = 0x1FFF;
108
109 segment = pitchbend / 0x1000;
110 freq = opl3_note_table[idx+segment];
111 freq += ((opl3_note_table[idx+segment+1] - freq) *
112 (pitchbend % 0x1000)) / 0x1000;
113 } else {
114 freq = opl3_note_table[idx];
115 }
116
117 *fnum = (unsigned char) freq;
118 *blocknum = ((freq >> 8) & OPL3_FNUM_HIGH_MASK) |
119 ((block << 2) & OPL3_BLOCKNUM_MASK);
120}
121
122
123#ifdef DEBUG_ALLOC
124static void debug_alloc(opl3_t *opl3, char *s, int voice) {
125 int i;
126 char *str = "x.24";
127
128 printk("time %.5i: %s [%.2i]: ", opl3->use_time, s, voice);
129 for (i = 0; i < opl3->max_voices; i++)
130 printk("%c", *(str + opl3->voices[i].state + 1));
131 printk("\n");
132}
133#endif
134
135/*
136 * Get a FM voice (channel) to play a note on.
137 */
138static int opl3_get_voice(opl3_t *opl3, int instr_4op,
139 snd_midi_channel_t *chan) {
140 int chan_4op_1; /* first voice for 4op instrument */
141 int chan_4op_2; /* second voice for 4op instrument */
142
143 snd_opl3_voice_t *vp, *vp2;
144 unsigned int voice_time;
145 int i;
146
147#ifdef DEBUG_ALLOC
148 char *alloc_type[3] = { "FREE ", "CHEAP ", "EXPENSIVE" };
149#endif
150
151 /* This is our "allocation cost" table */
152 enum {
153 FREE = 0, CHEAP, EXPENSIVE, END
154 };
155
156 /* Keeps track of what we are finding */
157 struct best {
158 unsigned int time;
159 int voice;
160 } best[END];
161 struct best *bp;
162
163 for (i = 0; i < END; i++) {
164 best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */;
165 best[i].voice = -1;
166 }
167
168 /* Look through all the channels for the most suitable. */
169 for (i = 0; i < opl3->max_voices; i++) {
170 vp = &opl3->voices[i];
171
172 if (vp->state == SNDRV_OPL3_ST_NOT_AVAIL)
173 /* skip unavailable channels, allocated by
174 drum voices or by bounded 4op voices) */
175 continue;
176
177 voice_time = vp->time;
178 bp = best;
179
180 chan_4op_1 = ((i < 3) || (i > 8 && i < 12));
181 chan_4op_2 = ((i > 2 && i < 6) || (i > 11 && i < 15));
182 if (instr_4op) {
183 /* allocate 4op voice */
184 /* skip channels unavailable to 4op instrument */
185 if (!chan_4op_1)
186 continue;
187
188 if (vp->state)
189 /* kill one voice, CHEAP */
190 bp++;
191 /* get state of bounded 2op channel
192 to be allocated for 4op instrument */
193 vp2 = &opl3->voices[i + 3];
194 if (vp2->state == SNDRV_OPL3_ST_ON_2OP) {
195 /* kill two voices, EXPENSIVE */
196 bp++;
197 voice_time = (voice_time > vp->time) ?
198 voice_time : vp->time;
199 }
200 } else {
201 /* allocate 2op voice */
202 if ((chan_4op_1) || (chan_4op_2))
203 /* use bounded channels for 2op, CHEAP */
204 bp++;
205 else if (vp->state)
206 /* kill one voice on 2op channel, CHEAP */
207 bp++;
208 /* raise kill cost to EXPENSIVE for all channels */
209 if (vp->state)
210 bp++;
211 }
212 if (voice_time < bp->time) {
213 bp->time = voice_time;
214 bp->voice = i;
215 }
216 }
217
218 for (i = 0; i < END; i++) {
219 if (best[i].voice >= 0) {
220#ifdef DEBUG_ALLOC
221 printk("%s %iop allocation on voice %i\n",
222 alloc_type[i], instr_4op ? 4 : 2,
223 best[i].voice);
224#endif
225 return best[i].voice;
226 }
227 }
228 /* not found */
229 return -1;
230}
231
232/* ------------------------------ */
233
234/*
235 * System timer interrupt function
236 */
237void snd_opl3_timer_func(unsigned long data)
238{
239
240 opl3_t *opl3 = (opl3_t *)data;
241 int again = 0;
242 int i;
243
244 spin_lock(&opl3->sys_timer_lock);
245 for (i = 0; i < opl3->max_voices; i++) {
246 snd_opl3_voice_t *vp = &opl3->voices[i];
247 if (vp->state > 0 && vp->note_off_check) {
248 if (vp->note_off == jiffies)
249 snd_opl3_note_off(opl3, vp->note, 0, vp->chan);
250 else
251 again++;
252 }
253 }
254 if (again) {
255 opl3->tlist.expires = jiffies + 1; /* invoke again */
256 add_timer(&opl3->tlist);
257 } else {
258 opl3->sys_timer_status = 0;
259 }
260 spin_unlock(&opl3->sys_timer_lock);
261}
262
263/*
264 * Start system timer
265 */
266static void snd_opl3_start_timer(opl3_t *opl3)
267{
268 unsigned long flags;
269 spin_lock_irqsave(&opl3->sys_timer_lock, flags);
270 if (! opl3->sys_timer_status) {
271 opl3->tlist.expires = jiffies + 1;
272 add_timer(&opl3->tlist);
273 opl3->sys_timer_status = 1;
274 }
275 spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
276}
277
278/* ------------------------------ */
279
280
281static int snd_opl3_oss_map[MAX_OPL3_VOICES] = {
282 0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17, 3, 4 ,5, 12, 13, 14
283};
284
285/*
286 * Start a note.
287 */
288void snd_opl3_note_on(void *p, int note, int vel, snd_midi_channel_t *chan)
289{
290 opl3_t *opl3;
291 snd_seq_instr_t wanted;
292 snd_seq_kinstr_t *kinstr;
293 int instr_4op;
294
295 int voice;
296 snd_opl3_voice_t *vp, *vp2;
297 unsigned short connect_mask;
298 unsigned char connection;
299 unsigned char vol_op[4];
300
301 int extra_prg = 0;
302
303 unsigned short reg_side;
304 unsigned char op_offset;
305 unsigned char voice_offset;
306 unsigned short opl3_reg;
307 unsigned char reg_val;
308
309 int key = note;
310 unsigned char fnum, blocknum;
311 int i;
312
313 fm_instrument_t *fm;
314 unsigned long flags;
315
316 opl3 = p;
317
318#ifdef DEBUG_MIDI
319 snd_printk("Note on, ch %i, inst %i, note %i, vel %i\n",
320 chan->number, chan->midi_program, note, vel);
321#endif
322 wanted.cluster = 0;
323 wanted.std = SNDRV_SEQ_INSTR_TYPE2_OPL2_3;
324
325 /* in SYNTH mode, application takes care of voices */
326 /* in SEQ mode, drum voice numbers are notes on drum channel */
327 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
328 if (chan->drum_channel) {
329 /* percussion instruments are located in bank 128 */
330 wanted.bank = 128;
331 wanted.prg = note;
332 } else {
333 wanted.bank = chan->gm_bank_select;
334 wanted.prg = chan->midi_program;
335 }
336 } else {
337 /* Prepare for OSS mode */
338 if (chan->number >= MAX_OPL3_VOICES)
339 return;
340
341 /* OSS instruments are located in bank 127 */
342 wanted.bank = 127;
343 wanted.prg = chan->midi_program;
344 }
345
346 spin_lock_irqsave(&opl3->voice_lock, flags);
347
348 if (use_internal_drums) {
349 snd_opl3_drum_switch(opl3, note, vel, 1, chan);
350 spin_unlock_irqrestore(&opl3->voice_lock, flags);
351 return;
352 }
353
354 __extra_prg:
355 kinstr = snd_seq_instr_find(opl3->ilist, &wanted, 1, 0);
356 if (kinstr == NULL) {
357 spin_unlock_irqrestore(&opl3->voice_lock, flags);
358 return;
359 }
360
361 fm = KINSTR_DATA(kinstr);
362
363 switch (fm->type) {
364 case FM_PATCH_OPL2:
365 instr_4op = 0;
366 break;
367 case FM_PATCH_OPL3:
368 if (opl3->hardware >= OPL3_HW_OPL3) {
369 instr_4op = 1;
370 break;
371 }
372 default:
373 snd_seq_instr_free_use(opl3->ilist, kinstr);
374 spin_unlock_irqrestore(&opl3->voice_lock, flags);
375 return;
376 }
377
378#ifdef DEBUG_MIDI
379 snd_printk(" --> OPL%i instrument: %s\n",
380 instr_4op ? 3 : 2, kinstr->name);
381#endif
382 /* in SYNTH mode, application takes care of voices */
383 /* in SEQ mode, allocate voice on free OPL3 channel */
384 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
385 voice = opl3_get_voice(opl3, instr_4op, chan);
386 } else {
387 /* remap OSS voice */
388 voice = snd_opl3_oss_map[chan->number];
389 }
390
391 if (voice < MAX_OPL2_VOICES) {
392 /* Left register block for voices 0 .. 8 */
393 reg_side = OPL3_LEFT;
394 voice_offset = voice;
395 connect_mask = (OPL3_LEFT_4OP_0 << voice_offset) & 0x07;
396 } else {
397 /* Right register block for voices 9 .. 17 */
398 reg_side = OPL3_RIGHT;
399 voice_offset = voice - MAX_OPL2_VOICES;
400 connect_mask = (OPL3_RIGHT_4OP_0 << voice_offset) & 0x38;
401 }
402
403 /* kill voice on channel */
404 vp = &opl3->voices[voice];
405 if (vp->state > 0) {
406 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
407 reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT;
408 opl3->command(opl3, opl3_reg, reg_val);
409 }
410 if (instr_4op) {
411 vp2 = &opl3->voices[voice + 3];
412 if (vp->state > 0) {
413 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK +
414 voice_offset + 3);
415 reg_val = vp->keyon_reg & ~OPL3_KEYON_BIT;
416 opl3->command(opl3, opl3_reg, reg_val);
417 }
418 }
419
420 /* set connection register */
421 if (instr_4op) {
422 if ((opl3->connection_reg ^ connect_mask) & connect_mask) {
423 opl3->connection_reg |= connect_mask;
424 /* set connection bit */
425 opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT;
426 opl3->command(opl3, opl3_reg, opl3->connection_reg);
427 }
428 } else {
429 if ((opl3->connection_reg ^ ~connect_mask) & connect_mask) {
430 opl3->connection_reg &= ~connect_mask;
431 /* clear connection bit */
432 opl3_reg = OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT;
433 opl3->command(opl3, opl3_reg, opl3->connection_reg);
434 }
435 }
436
437#ifdef DEBUG_MIDI
438 snd_printk(" --> setting OPL3 connection: 0x%x\n",
439 opl3->connection_reg);
440#endif
441 /*
442 * calculate volume depending on connection
443 * between FM operators (see include/opl3.h)
444 */
445 for (i = 0; i < (instr_4op ? 4 : 2); i++)
446 vol_op[i] = fm->op[i].ksl_level;
447
448 connection = fm->feedback_connection[0] & 0x01;
449 if (instr_4op) {
450 connection <<= 1;
451 connection |= fm->feedback_connection[1] & 0x01;
452
453 snd_opl3_calc_volume(&vol_op[3], vel, chan);
454 switch (connection) {
455 case 0x03:
456 snd_opl3_calc_volume(&vol_op[2], vel, chan);
457 /* fallthru */
458 case 0x02:
459 snd_opl3_calc_volume(&vol_op[0], vel, chan);
460 break;
461 case 0x01:
462 snd_opl3_calc_volume(&vol_op[1], vel, chan);
463 }
464 } else {
465 snd_opl3_calc_volume(&vol_op[1], vel, chan);
466 if (connection)
467 snd_opl3_calc_volume(&vol_op[0], vel, chan);
468 }
469
470 /* Program the FM voice characteristics */
471 for (i = 0; i < (instr_4op ? 4 : 2); i++) {
472#ifdef DEBUG_MIDI
473 snd_printk(" --> programming operator %i\n", i);
474#endif
475 op_offset = snd_opl3_regmap[voice_offset][i];
476
477 /* Set OPL3 AM_VIB register of requested voice/operator */
478 reg_val = fm->op[i].am_vib;
479 opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset);
480 opl3->command(opl3, opl3_reg, reg_val);
481
482 /* Set OPL3 KSL_LEVEL register of requested voice/operator */
483 reg_val = vol_op[i];
484 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset);
485 opl3->command(opl3, opl3_reg, reg_val);
486
487 /* Set OPL3 ATTACK_DECAY register of requested voice/operator */
488 reg_val = fm->op[i].attack_decay;
489 opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset);
490 opl3->command(opl3, opl3_reg, reg_val);
491
492 /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */
493 reg_val = fm->op[i].sustain_release;
494 opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset);
495 opl3->command(opl3, opl3_reg, reg_val);
496
497 /* Select waveform */
498 reg_val = fm->op[i].wave_select;
499 opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset);
500 opl3->command(opl3, opl3_reg, reg_val);
501 }
502
503 /* Set operator feedback and 2op inter-operator connection */
504 reg_val = fm->feedback_connection[0];
505 /* Set output voice connection */
506 reg_val |= OPL3_STEREO_BITS;
507 if (chan->gm_pan < 43)
508 reg_val &= ~OPL3_VOICE_TO_RIGHT;
509 if (chan->gm_pan > 85)
510 reg_val &= ~OPL3_VOICE_TO_LEFT;
511 opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset);
512 opl3->command(opl3, opl3_reg, reg_val);
513
514 if (instr_4op) {
515 /* Set 4op inter-operator connection */
516 reg_val = fm->feedback_connection[1] & OPL3_CONNECTION_BIT;
517 /* Set output voice connection */
518 reg_val |= OPL3_STEREO_BITS;
519 if (chan->gm_pan < 43)
520 reg_val &= ~OPL3_VOICE_TO_RIGHT;
521 if (chan->gm_pan > 85)
522 reg_val &= ~OPL3_VOICE_TO_LEFT;
523 opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION +
524 voice_offset + 3);
525 opl3->command(opl3, opl3_reg, reg_val);
526 }
527
528 /*
529 * Special treatment of percussion notes for fm:
530 * Requested pitch is really program, and pitch for
531 * device is whatever was specified in the patch library.
532 */
533 if (fm->fix_key)
534 note = fm->fix_key;
535 /*
536 * use transpose if defined in patch library
537 */
538 if (fm->trnsps)
539 note += (fm->trnsps - 64);
540
541 snd_opl3_calc_pitch(&fnum, &blocknum, note, chan);
542
543 /* Set OPL3 FNUM_LOW register of requested voice */
544 opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset);
545 opl3->command(opl3, opl3_reg, fnum);
546
547 opl3->voices[voice].keyon_reg = blocknum;
548
549 /* Set output sound flag */
550 blocknum |= OPL3_KEYON_BIT;
551
552#ifdef DEBUG_MIDI
553 snd_printk(" --> trigger voice %i\n", voice);
554#endif
555 /* Set OPL3 KEYON_BLOCK register of requested voice */
556 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
557 opl3->command(opl3, opl3_reg, blocknum);
558
559 /* kill note after fixed duration (in centiseconds) */
560 if (fm->fix_dur) {
561 opl3->voices[voice].note_off = jiffies +
562 (fm->fix_dur * HZ) / 100;
563 snd_opl3_start_timer(opl3);
564 opl3->voices[voice].note_off_check = 1;
565 } else
566 opl3->voices[voice].note_off_check = 0;
567
568 /* get extra pgm, but avoid possible loops */
569 extra_prg = (extra_prg) ? 0 : fm->modes;
570
571 snd_seq_instr_free_use(opl3->ilist, kinstr);
572
573 /* do the bookkeeping */
574 vp->time = opl3->use_time++;
575 vp->note = key;
576 vp->chan = chan;
577
578 if (instr_4op) {
579 vp->state = SNDRV_OPL3_ST_ON_4OP;
580
581 vp2 = &opl3->voices[voice + 3];
582 vp2->time = opl3->use_time++;
583 vp2->note = key;
584 vp2->chan = chan;
585 vp2->state = SNDRV_OPL3_ST_NOT_AVAIL;
586 } else {
587 if (vp->state == SNDRV_OPL3_ST_ON_4OP) {
588 /* 4op killed by 2op, release bounded voice */
589 vp2 = &opl3->voices[voice + 3];
590 vp2->time = opl3->use_time++;
591 vp2->state = SNDRV_OPL3_ST_OFF;
592 }
593 vp->state = SNDRV_OPL3_ST_ON_2OP;
594 }
595
596#ifdef DEBUG_ALLOC
597 debug_alloc(opl3, "note on ", voice);
598#endif
599
600 /* allocate extra program if specified in patch library */
601 if (extra_prg) {
602 if (extra_prg > 128) {
603 wanted.bank = 128;
604 /* percussions start at 35 */
605 wanted.prg = extra_prg - 128 + 35 - 1;
606 } else {
607 wanted.bank = 0;
608 wanted.prg = extra_prg - 1;
609 }
610#ifdef DEBUG_MIDI
611 snd_printk(" *** allocating extra program\n");
612#endif
613 goto __extra_prg;
614 }
615 spin_unlock_irqrestore(&opl3->voice_lock, flags);
616}
617
618static void snd_opl3_kill_voice(opl3_t *opl3, int voice)
619{
620 unsigned short reg_side;
621 unsigned char voice_offset;
622 unsigned short opl3_reg;
623
624 snd_opl3_voice_t *vp, *vp2;
625
626 snd_assert(voice < MAX_OPL3_VOICES, return);
627
628 vp = &opl3->voices[voice];
629 if (voice < MAX_OPL2_VOICES) {
630 /* Left register block for voices 0 .. 8 */
631 reg_side = OPL3_LEFT;
632 voice_offset = voice;
633 } else {
634 /* Right register block for voices 9 .. 17 */
635 reg_side = OPL3_RIGHT;
636 voice_offset = voice - MAX_OPL2_VOICES;
637 }
638
639 /* kill voice */
640#ifdef DEBUG_MIDI
641 snd_printk(" --> kill voice %i\n", voice);
642#endif
643 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
644 /* clear Key ON bit */
645 opl3->command(opl3, opl3_reg, vp->keyon_reg);
646
647 /* do the bookkeeping */
648 vp->time = opl3->use_time++;
649
650 if (vp->state == SNDRV_OPL3_ST_ON_4OP) {
651 vp2 = &opl3->voices[voice + 3];
652
653 vp2->time = opl3->use_time++;
654 vp2->state = SNDRV_OPL3_ST_OFF;
655 }
656 vp->state = SNDRV_OPL3_ST_OFF;
657#ifdef DEBUG_ALLOC
658 debug_alloc(opl3, "note off", voice);
659#endif
660
661}
662
663/*
664 * Release a note in response to a midi note off.
665 */
666void snd_opl3_note_off(void *p, int note, int vel, snd_midi_channel_t *chan)
667{
668 opl3_t *opl3;
669
670 int voice;
671 snd_opl3_voice_t *vp;
672
673 unsigned long flags;
674
675 opl3 = p;
676
677#ifdef DEBUG_MIDI
678 snd_printk("Note off, ch %i, inst %i, note %i\n",
679 chan->number, chan->midi_program, note);
680#endif
681
682 spin_lock_irqsave(&opl3->voice_lock, flags);
683
684 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
685 if (chan->drum_channel && use_internal_drums) {
686 snd_opl3_drum_switch(opl3, note, vel, 0, chan);
687 spin_unlock_irqrestore(&opl3->voice_lock, flags);
688 return;
689 }
690 /* this loop will hopefully kill all extra voices, because
691 they are grouped by the same channel and note values */
692 for (voice = 0; voice < opl3->max_voices; voice++) {
693 vp = &opl3->voices[voice];
694 if (vp->state > 0 && vp->chan == chan && vp->note == note) {
695 snd_opl3_kill_voice(opl3, voice);
696 }
697 }
698 } else {
699 /* remap OSS voices */
700 if (chan->number < MAX_OPL3_VOICES) {
701 voice = snd_opl3_oss_map[chan->number];
702 snd_opl3_kill_voice(opl3, voice);
703 }
704 }
705 spin_unlock_irqrestore(&opl3->voice_lock, flags);
706}
707
708/*
709 * key pressure change
710 */
711void snd_opl3_key_press(void *p, int note, int vel, snd_midi_channel_t *chan)
712{
713 opl3_t *opl3;
714
715 opl3 = p;
716#ifdef DEBUG_MIDI
717 snd_printk("Key pressure, ch#: %i, inst#: %i\n",
718 chan->number, chan->midi_program);
719#endif
720}
721
722/*
723 * terminate note
724 */
725void snd_opl3_terminate_note(void *p, int note, snd_midi_channel_t *chan)
726{
727 opl3_t *opl3;
728
729 opl3 = p;
730#ifdef DEBUG_MIDI
731 snd_printk("Terminate note, ch#: %i, inst#: %i\n",
732 chan->number, chan->midi_program);
733#endif
734}
735
736static void snd_opl3_update_pitch(opl3_t *opl3, int voice)
737{
738 unsigned short reg_side;
739 unsigned char voice_offset;
740 unsigned short opl3_reg;
741
742 unsigned char fnum, blocknum;
743
744 snd_opl3_voice_t *vp;
745
746 snd_assert(voice < MAX_OPL3_VOICES, return);
747
748 vp = &opl3->voices[voice];
749 if (vp->chan == NULL)
750 return; /* not allocated? */
751
752 if (voice < MAX_OPL2_VOICES) {
753 /* Left register block for voices 0 .. 8 */
754 reg_side = OPL3_LEFT;
755 voice_offset = voice;
756 } else {
757 /* Right register block for voices 9 .. 17 */
758 reg_side = OPL3_RIGHT;
759 voice_offset = voice - MAX_OPL2_VOICES;
760 }
761
762 snd_opl3_calc_pitch(&fnum, &blocknum, vp->note, vp->chan);
763
764 /* Set OPL3 FNUM_LOW register of requested voice */
765 opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset);
766 opl3->command(opl3, opl3_reg, fnum);
767
768 vp->keyon_reg = blocknum;
769
770 /* Set output sound flag */
771 blocknum |= OPL3_KEYON_BIT;
772
773 /* Set OPL3 KEYON_BLOCK register of requested voice */
774 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
775 opl3->command(opl3, opl3_reg, blocknum);
776
777 vp->time = opl3->use_time++;
778}
779
780/*
781 * Update voice pitch controller
782 */
783static void snd_opl3_pitch_ctrl(opl3_t *opl3, snd_midi_channel_t *chan)
784{
785 int voice;
786 snd_opl3_voice_t *vp;
787
788 unsigned long flags;
789
790 spin_lock_irqsave(&opl3->voice_lock, flags);
791
792 if (opl3->synth_mode == SNDRV_OPL3_MODE_SEQ) {
793 for (voice = 0; voice < opl3->max_voices; voice++) {
794 vp = &opl3->voices[voice];
795 if (vp->state > 0 && vp->chan == chan) {
796 snd_opl3_update_pitch(opl3, voice);
797 }
798 }
799 } else {
800 /* remap OSS voices */
801 if (chan->number < MAX_OPL3_VOICES) {
802 voice = snd_opl3_oss_map[chan->number];
803 snd_opl3_update_pitch(opl3, voice);
804 }
805 }
806 spin_unlock_irqrestore(&opl3->voice_lock, flags);
807}
808
809/*
810 * Deal with a controler type event. This includes all types of
811 * control events, not just the midi controllers
812 */
813void snd_opl3_control(void *p, int type, snd_midi_channel_t *chan)
814{
815 opl3_t *opl3;
816
817 opl3 = p;
818#ifdef DEBUG_MIDI
819 snd_printk("Controller, TYPE = %i, ch#: %i, inst#: %i\n",
820 type, chan->number, chan->midi_program);
821#endif
822
823 switch (type) {
824 case MIDI_CTL_MSB_MODWHEEL:
825 if (chan->control[MIDI_CTL_MSB_MODWHEEL] > 63)
826 opl3->drum_reg |= OPL3_VIBRATO_DEPTH;
827 else
828 opl3->drum_reg &= ~OPL3_VIBRATO_DEPTH;
829 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION,
830 opl3->drum_reg);
831 break;
832 case MIDI_CTL_E2_TREMOLO_DEPTH:
833 if (chan->control[MIDI_CTL_E2_TREMOLO_DEPTH] > 63)
834 opl3->drum_reg |= OPL3_TREMOLO_DEPTH;
835 else
836 opl3->drum_reg &= ~OPL3_TREMOLO_DEPTH;
837 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION,
838 opl3->drum_reg);
839 break;
840 case MIDI_CTL_PITCHBEND:
841 snd_opl3_pitch_ctrl(opl3, chan);
842 break;
843 }
844}
845
846/*
847 * NRPN events
848 */
849void snd_opl3_nrpn(void *p, snd_midi_channel_t *chan,
850 snd_midi_channel_set_t *chset)
851{
852 opl3_t *opl3;
853
854 opl3 = p;
855#ifdef DEBUG_MIDI
856 snd_printk("NRPN, ch#: %i, inst#: %i\n",
857 chan->number, chan->midi_program);
858#endif
859}
860
861/*
862 * receive sysex
863 */
864void snd_opl3_sysex(void *p, unsigned char *buf, int len,
865 int parsed, snd_midi_channel_set_t *chset)
866{
867 opl3_t *opl3;
868
869 opl3 = p;
870#ifdef DEBUG_MIDI
871 snd_printk("SYSEX\n");
872#endif
873}
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
new file mode 100644
index 000000000000..33da334ae981
--- /dev/null
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -0,0 +1,356 @@
1/*
2 * Interface for OSS sequencer emulation
3 *
4 * Copyright (C) 2000 Uros Bizjak <uros@kss-loka.si>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "opl3_voice.h"
22#include <linux/slab.h>
23
24static int snd_opl3_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure);
25static int snd_opl3_close_seq_oss(snd_seq_oss_arg_t *arg);
26static int snd_opl3_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd, unsigned long ioarg);
27static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format, const char __user *buf, int offs, int count);
28static int snd_opl3_reset_seq_oss(snd_seq_oss_arg_t *arg);
29
30/* */
31
32static inline mm_segment_t snd_enter_user(void)
33{
34 mm_segment_t fs = get_fs();
35 set_fs(get_ds());
36 return fs;
37}
38
39static inline void snd_leave_user(mm_segment_t fs)
40{
41 set_fs(fs);
42}
43
44/* operators */
45
46extern snd_midi_op_t opl3_ops;
47
48static snd_seq_oss_callback_t oss_callback = {
49 .owner = THIS_MODULE,
50 .open = snd_opl3_open_seq_oss,
51 .close = snd_opl3_close_seq_oss,
52 .ioctl = snd_opl3_ioctl_seq_oss,
53 .load_patch = snd_opl3_load_patch_seq_oss,
54 .reset = snd_opl3_reset_seq_oss,
55};
56
57static int snd_opl3_oss_event_input(snd_seq_event_t *ev, int direct,
58 void *private_data, int atomic, int hop)
59{
60 opl3_t *opl3 = private_data;
61
62 if (ev->type != SNDRV_SEQ_EVENT_OSS)
63 snd_midi_process_event(&opl3_ops, ev, opl3->oss_chset);
64 return 0;
65}
66
67/* ------------------------------ */
68
69static void snd_opl3_oss_free_port(void *private_data)
70{
71 opl3_t *opl3 = private_data;
72
73 snd_midi_channel_free_set(opl3->oss_chset);
74}
75
76static int snd_opl3_oss_create_port(opl3_t * opl3)
77{
78 snd_seq_port_callback_t callbacks;
79 char name[32];
80 int voices, opl_ver;
81
82 voices = (opl3->hardware < OPL3_HW_OPL3) ?
83 MAX_OPL2_VOICES : MAX_OPL3_VOICES;
84 opl3->oss_chset = snd_midi_channel_alloc_set(voices);
85 if (opl3->oss_chset == NULL)
86 return -ENOMEM;
87 opl3->oss_chset->private_data = opl3;
88
89 memset(&callbacks, 0, sizeof(callbacks));
90 callbacks.owner = THIS_MODULE;
91 callbacks.event_input = snd_opl3_oss_event_input;
92 callbacks.private_free = snd_opl3_oss_free_port;
93 callbacks.private_data = opl3;
94
95 opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8;
96 sprintf(name, "OPL%i OSS Port", opl_ver);
97
98 opl3->oss_chset->client = opl3->seq_client;
99 opl3->oss_chset->port = snd_seq_event_port_attach(opl3->seq_client, &callbacks,
100 SNDRV_SEQ_PORT_CAP_WRITE,
101 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
102 SNDRV_SEQ_PORT_TYPE_MIDI_GM |
103 SNDRV_SEQ_PORT_TYPE_SYNTH,
104 voices, voices,
105 name);
106 if (opl3->oss_chset->port < 0) {
107 snd_midi_channel_free_set(opl3->oss_chset);
108 return opl3->oss_chset->port;
109 }
110 return 0;
111}
112
113/* ------------------------------ */
114
115/* register OSS synth */
116void snd_opl3_init_seq_oss(opl3_t *opl3, char *name)
117{
118 snd_seq_oss_reg_t *arg;
119 snd_seq_device_t *dev;
120
121 if (snd_seq_device_new(opl3->card, 0, SNDRV_SEQ_DEV_ID_OSS,
122 sizeof(snd_seq_oss_reg_t), &dev) < 0)
123 return;
124
125 opl3->oss_seq_dev = dev;
126 strlcpy(dev->name, name, sizeof(dev->name));
127 arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
128 arg->type = SYNTH_TYPE_FM;
129 if (opl3->hardware < OPL3_HW_OPL3) {
130 arg->subtype = FM_TYPE_ADLIB;
131 arg->nvoices = MAX_OPL2_VOICES;
132 } else {
133 arg->subtype = FM_TYPE_OPL3;
134 arg->nvoices = MAX_OPL3_VOICES;
135 }
136 arg->oper = oss_callback;
137 arg->private_data = opl3;
138
139 snd_opl3_oss_create_port(opl3);
140
141 /* register to OSS synth table */
142 snd_device_register(opl3->card, dev);
143}
144
145/* unregister */
146void snd_opl3_free_seq_oss(opl3_t *opl3)
147{
148 if (opl3->oss_seq_dev) {
149 snd_device_free(opl3->card, opl3->oss_seq_dev);
150 opl3->oss_seq_dev = NULL;
151 }
152}
153
154/* ------------------------------ */
155
156/* open OSS sequencer */
157static int snd_opl3_open_seq_oss(snd_seq_oss_arg_t *arg, void *closure)
158{
159 opl3_t *opl3 = closure;
160 int err;
161
162 snd_assert(arg != NULL, return -ENXIO);
163
164 if ((err = snd_opl3_synth_setup(opl3)) < 0)
165 return err;
166
167 /* fill the argument data */
168 arg->private_data = opl3;
169 arg->addr.client = opl3->oss_chset->client;
170 arg->addr.port = opl3->oss_chset->port;
171
172 if ((err = snd_opl3_synth_use_inc(opl3)) < 0)
173 return err;
174
175 opl3->synth_mode = SNDRV_OPL3_MODE_SYNTH;
176 return 0;
177}
178
179/* close OSS sequencer */
180static int snd_opl3_close_seq_oss(snd_seq_oss_arg_t *arg)
181{
182 opl3_t *opl3;
183
184 snd_assert(arg != NULL, return -ENXIO);
185 opl3 = arg->private_data;
186
187 snd_opl3_synth_cleanup(opl3);
188
189 snd_opl3_synth_use_dec(opl3);
190 return 0;
191}
192
193/* load patch */
194
195/* offsets for SBI params */
196#define AM_VIB 0
197#define KSL_LEVEL 2
198#define ATTACK_DECAY 4
199#define SUSTAIN_RELEASE 6
200#define WAVE_SELECT 8
201
202/* offset for SBI instrument */
203#define CONNECTION 10
204#define OFFSET_4OP 11
205
206/* from sound_config.h */
207#define SBFM_MAXINSTR 256
208
209static int snd_opl3_load_patch_seq_oss(snd_seq_oss_arg_t *arg, int format,
210 const char __user *buf, int offs, int count)
211{
212 opl3_t *opl3;
213 int err = -EINVAL;
214
215 snd_assert(arg != NULL, return -ENXIO);
216 opl3 = arg->private_data;
217
218 if ((format == FM_PATCH) || (format == OPL3_PATCH)) {
219 struct sbi_instrument sbi;
220
221 size_t size;
222 snd_seq_instr_header_t *put;
223 snd_seq_instr_data_t *data;
224 fm_xinstrument_t *xinstr;
225
226 snd_seq_event_t ev;
227 int i;
228
229 mm_segment_t fs;
230
231 if (count < (int)sizeof(sbi)) {
232 snd_printk("FM Error: Patch record too short\n");
233 return -EINVAL;
234 }
235 if (copy_from_user(&sbi, buf, sizeof(sbi)))
236 return -EFAULT;
237
238 if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) {
239 snd_printk("FM Error: Invalid instrument number %d\n", sbi.channel);
240 return -EINVAL;
241 }
242
243 size = sizeof(*put) + sizeof(fm_xinstrument_t);
244 put = kcalloc(1, size, GFP_KERNEL);
245 if (put == NULL)
246 return -ENOMEM;
247 /* build header */
248 data = &put->data;
249 data->type = SNDRV_SEQ_INSTR_ATYPE_DATA;
250 strcpy(data->data.format, SNDRV_SEQ_INSTR_ID_OPL2_3);
251 /* build data section */
252 xinstr = (fm_xinstrument_t *)(data + 1);
253 xinstr->stype = FM_STRU_INSTR;
254
255 for (i = 0; i < 2; i++) {
256 xinstr->op[i].am_vib = sbi.operators[AM_VIB + i];
257 xinstr->op[i].ksl_level = sbi.operators[KSL_LEVEL + i];
258 xinstr->op[i].attack_decay = sbi.operators[ATTACK_DECAY + i];
259 xinstr->op[i].sustain_release = sbi.operators[SUSTAIN_RELEASE + i];
260 xinstr->op[i].wave_select = sbi.operators[WAVE_SELECT + i];
261 }
262 xinstr->feedback_connection[0] = sbi.operators[CONNECTION];
263
264 if (format == OPL3_PATCH) {
265 xinstr->type = FM_PATCH_OPL3;
266 for (i = 0; i < 2; i++) {
267 xinstr->op[i+2].am_vib = sbi.operators[OFFSET_4OP + AM_VIB + i];
268 xinstr->op[i+2].ksl_level = sbi.operators[OFFSET_4OP + KSL_LEVEL + i];
269 xinstr->op[i+2].attack_decay = sbi.operators[OFFSET_4OP + ATTACK_DECAY + i];
270 xinstr->op[i+2].sustain_release = sbi.operators[OFFSET_4OP + SUSTAIN_RELEASE + i];
271 xinstr->op[i+2].wave_select = sbi.operators[OFFSET_4OP + WAVE_SELECT + i];
272 }
273 xinstr->feedback_connection[1] = sbi.operators[OFFSET_4OP + CONNECTION];
274 } else {
275 xinstr->type = FM_PATCH_OPL2;
276 }
277
278 put->id.instr.std = SNDRV_SEQ_INSTR_TYPE2_OPL2_3;
279 put->id.instr.bank = 127;
280 put->id.instr.prg = sbi.channel;
281 put->cmd = SNDRV_SEQ_INSTR_PUT_CMD_CREATE;
282
283 memset (&ev, 0, sizeof(ev));
284 ev.source.client = SNDRV_SEQ_CLIENT_OSS;
285 ev.dest = arg->addr;
286
287 ev.flags = SNDRV_SEQ_EVENT_LENGTH_VARUSR;
288 ev.queue = SNDRV_SEQ_QUEUE_DIRECT;
289
290 fs = snd_enter_user();
291 __again:
292 ev.type = SNDRV_SEQ_EVENT_INSTR_PUT;
293 ev.data.ext.len = size;
294 ev.data.ext.ptr = put;
295
296 err = snd_seq_instr_event(&opl3->fm_ops, opl3->ilist, &ev,
297 opl3->seq_client, 0, 0);
298 if (err == -EBUSY) {
299 snd_seq_instr_header_t remove;
300
301 memset (&remove, 0, sizeof(remove));
302 remove.cmd = SNDRV_SEQ_INSTR_FREE_CMD_SINGLE;
303 remove.id.instr = put->id.instr;
304
305 /* remove instrument */
306 ev.type = SNDRV_SEQ_EVENT_INSTR_FREE;
307 ev.data.ext.len = sizeof(remove);
308 ev.data.ext.ptr = &remove;
309
310 snd_seq_instr_event(&opl3->fm_ops, opl3->ilist, &ev,
311 opl3->seq_client, 0, 0);
312 goto __again;
313 }
314 snd_leave_user(fs);
315
316 kfree(put);
317 }
318 return err;
319}
320
321/* ioctl */
322static int snd_opl3_ioctl_seq_oss(snd_seq_oss_arg_t *arg, unsigned int cmd,
323 unsigned long ioarg)
324{
325 opl3_t *opl3;
326
327 snd_assert(arg != NULL, return -ENXIO);
328 opl3 = arg->private_data;
329 switch (cmd) {
330 case SNDCTL_FM_LOAD_INSTR:
331 snd_printk("OPL3: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n");
332 return -EINVAL;
333
334 case SNDCTL_SYNTH_MEMAVL:
335 return 0x7fffffff;
336
337 case SNDCTL_FM_4OP_ENABLE:
338 // handled automatically by OPL instrument type
339 return 0;
340
341 default:
342 return -EINVAL;
343 }
344 return 0;
345}
346
347/* reset device */
348static int snd_opl3_reset_seq_oss(snd_seq_oss_arg_t *arg)
349{
350 opl3_t *opl3;
351
352 snd_assert(arg != NULL, return -ENXIO);
353 opl3 = arg->private_data;
354
355 return 0;
356}
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
new file mode 100644
index 000000000000..136964b844de
--- /dev/null
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -0,0 +1,314 @@
1/*
2 * Copyright (c) by Uros Bizjak <uros@kss-loka.si>
3 *
4 * Midi Sequencer interface routines for OPL2/OPL3/OPL4 FM
5 *
6 * OPL2/3 FM instrument loader:
7 * alsa-tools/seq/sbiload/
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 *
23 */
24
25#include "opl3_voice.h"
26#include <linux/init.h>
27#include <linux/moduleparam.h>
28#include <sound/initval.h>
29
30MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
31MODULE_LICENSE("GPL");
32MODULE_DESCRIPTION("ALSA driver for OPL3 FM synth");
33
34int use_internal_drums = 0;
35module_param(use_internal_drums, bool, 0444);
36MODULE_PARM_DESC(use_internal_drums, "Enable internal OPL2/3 drums.");
37
38int snd_opl3_synth_use_inc(opl3_t * opl3)
39{
40 if (!try_module_get(opl3->card->module))
41 return -EFAULT;
42 return 0;
43
44}
45
46void snd_opl3_synth_use_dec(opl3_t * opl3)
47{
48 module_put(opl3->card->module);
49}
50
51int snd_opl3_synth_setup(opl3_t * opl3)
52{
53 int idx;
54
55 down(&opl3->access_mutex);
56 if (opl3->used) {
57 up(&opl3->access_mutex);
58 return -EBUSY;
59 }
60 opl3->used++;
61 up(&opl3->access_mutex);
62
63 snd_opl3_reset(opl3);
64
65 for (idx = 0; idx < MAX_OPL3_VOICES; idx++) {
66 opl3->voices[idx].state = SNDRV_OPL3_ST_OFF;
67 opl3->voices[idx].time = 0;
68 opl3->voices[idx].keyon_reg = 0x00;
69 }
70 opl3->use_time = 0;
71 opl3->connection_reg = 0x00;
72 if (opl3->hardware >= OPL3_HW_OPL3) {
73 /* Clear 4-op connections */
74 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT,
75 opl3->connection_reg);
76 opl3->max_voices = MAX_OPL3_VOICES;
77 }
78 return 0;
79}
80
81void snd_opl3_synth_cleanup(opl3_t * opl3)
82{
83 unsigned long flags;
84
85 /* Stop system timer */
86 spin_lock_irqsave(&opl3->sys_timer_lock, flags);
87 if (opl3->sys_timer_status) {
88 del_timer(&opl3->tlist);
89 opl3->sys_timer_status = 0;
90 }
91 spin_unlock_irqrestore(&opl3->sys_timer_lock, flags);
92
93 snd_opl3_reset(opl3);
94 down(&opl3->access_mutex);
95 opl3->used--;
96 up(&opl3->access_mutex);
97}
98
99static int snd_opl3_synth_use(void *private_data, snd_seq_port_subscribe_t * info)
100{
101 opl3_t *opl3 = private_data;
102 int err;
103
104 if ((err = snd_opl3_synth_setup(opl3)) < 0)
105 return err;
106
107 if (use_internal_drums) {
108 /* Percussion mode */
109 opl3->voices[6].state = opl3->voices[7].state =
110 opl3->voices[8].state = SNDRV_OPL3_ST_NOT_AVAIL;
111 snd_opl3_load_drums(opl3);
112 opl3->drum_reg = OPL3_PERCUSSION_ENABLE;
113 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, opl3->drum_reg);
114 } else {
115 opl3->drum_reg = 0x00;
116 }
117
118 if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) {
119 if ((err = snd_opl3_synth_use_inc(opl3)) < 0)
120 return err;
121 }
122 opl3->synth_mode = SNDRV_OPL3_MODE_SEQ;
123 return 0;
124}
125
126static int snd_opl3_synth_unuse(void *private_data, snd_seq_port_subscribe_t * info)
127{
128 opl3_t *opl3 = private_data;
129
130 snd_opl3_synth_cleanup(opl3);
131
132 if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM)
133 snd_opl3_synth_use_dec(opl3);
134 return 0;
135}
136
137/*
138 * MIDI emulation operators
139 */
140snd_midi_op_t opl3_ops = {
141 .note_on = snd_opl3_note_on,
142 .note_off = snd_opl3_note_off,
143 .key_press = snd_opl3_key_press,
144 .note_terminate = snd_opl3_terminate_note,
145 .control = snd_opl3_control,
146 .nrpn = snd_opl3_nrpn,
147 .sysex = snd_opl3_sysex,
148};
149
150static int snd_opl3_synth_event_input(snd_seq_event_t * ev, int direct,
151 void *private_data, int atomic, int hop)
152{
153 opl3_t *opl3 = private_data;
154
155 if (ev->type >= SNDRV_SEQ_EVENT_INSTR_BEGIN &&
156 ev->type <= SNDRV_SEQ_EVENT_INSTR_CHANGE) {
157 if (direct) {
158 snd_seq_instr_event(&opl3->fm_ops, opl3->ilist, ev,
159 opl3->seq_client, atomic, hop);
160 }
161 } else {
162 snd_midi_process_event(&opl3_ops, ev, opl3->chset);
163 }
164 return 0;
165}
166
167/* ------------------------------ */
168
169static void snd_opl3_synth_free_port(void *private_data)
170{
171 opl3_t *opl3 = private_data;
172
173 snd_midi_channel_free_set(opl3->chset);
174}
175
176static int snd_opl3_synth_create_port(opl3_t * opl3)
177{
178 snd_seq_port_callback_t callbacks;
179 char name[32];
180 int voices, opl_ver;
181
182 voices = (opl3->hardware < OPL3_HW_OPL3) ?
183 MAX_OPL2_VOICES : MAX_OPL3_VOICES;
184 opl3->chset = snd_midi_channel_alloc_set(16);
185 if (opl3->chset == NULL)
186 return -ENOMEM;
187 opl3->chset->private_data = opl3;
188
189 memset(&callbacks, 0, sizeof(callbacks));
190 callbacks.owner = THIS_MODULE;
191 callbacks.use = snd_opl3_synth_use;
192 callbacks.unuse = snd_opl3_synth_unuse;
193 callbacks.event_input = snd_opl3_synth_event_input;
194 callbacks.private_free = snd_opl3_synth_free_port;
195 callbacks.private_data = opl3;
196
197 opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8;
198 sprintf(name, "OPL%i FM Port", opl_ver);
199
200 opl3->chset->client = opl3->seq_client;
201 opl3->chset->port = snd_seq_event_port_attach(opl3->seq_client, &callbacks,
202 SNDRV_SEQ_PORT_CAP_WRITE |
203 SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
204 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
205 SNDRV_SEQ_PORT_TYPE_MIDI_GM |
206 SNDRV_SEQ_PORT_TYPE_SYNTH,
207 16, voices,
208 name);
209 if (opl3->chset->port < 0) {
210 snd_midi_channel_free_set(opl3->chset);
211 return opl3->chset->port;
212 }
213 return 0;
214}
215
216/* ------------------------------ */
217
218static int snd_opl3_seq_new_device(snd_seq_device_t *dev)
219{
220 opl3_t *opl3;
221 int client;
222 snd_seq_client_callback_t callbacks;
223 snd_seq_client_info_t cinfo;
224 int opl_ver;
225
226 opl3 = *(opl3_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
227 if (opl3 == NULL)
228 return -EINVAL;
229
230 spin_lock_init(&opl3->voice_lock);
231
232 opl3->seq_client = -1;
233
234 /* allocate new client */
235 memset(&callbacks, 0, sizeof(callbacks));
236 callbacks.private_data = opl3;
237 callbacks.allow_output = callbacks.allow_input = 1;
238 client = opl3->seq_client =
239 snd_seq_create_kernel_client(opl3->card, opl3->seq_dev_num, &callbacks);
240 if (client < 0)
241 return client;
242
243 /* change name of client */
244 memset(&cinfo, 0, sizeof(cinfo));
245 cinfo.client = client;
246 cinfo.type = KERNEL_CLIENT;
247 opl_ver = (opl3->hardware & OPL3_HW_MASK) >> 8;
248 sprintf(cinfo.name, "OPL%i FM synth", opl_ver);
249 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
250
251 snd_opl3_synth_create_port(opl3);
252
253 /* initialize instrument list */
254 opl3->ilist = snd_seq_instr_list_new();
255 if (opl3->ilist == NULL) {
256 snd_seq_delete_kernel_client(client);
257 opl3->seq_client = -1;
258 return -ENOMEM;
259 }
260 opl3->ilist->flags = SNDRV_SEQ_INSTR_FLG_DIRECT;
261 snd_seq_fm_init(&opl3->fm_ops, NULL);
262
263 /* setup system timer */
264 init_timer(&opl3->tlist);
265 opl3->tlist.function = snd_opl3_timer_func;
266 opl3->tlist.data = (unsigned long) opl3;
267 spin_lock_init(&opl3->sys_timer_lock);
268 opl3->sys_timer_status = 0;
269
270#ifdef CONFIG_SND_SEQUENCER_OSS
271 snd_opl3_init_seq_oss(opl3, cinfo.name);
272#endif
273 return 0;
274}
275
276static int snd_opl3_seq_delete_device(snd_seq_device_t *dev)
277{
278 opl3_t *opl3;
279
280 opl3 = *(opl3_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
281 if (opl3 == NULL)
282 return -EINVAL;
283
284#ifdef CONFIG_SND_SEQUENCER_OSS
285 snd_opl3_free_seq_oss(opl3);
286#endif
287 if (opl3->seq_client >= 0) {
288 snd_seq_delete_kernel_client(opl3->seq_client);
289 opl3->seq_client = -1;
290 }
291 if (opl3->ilist)
292 snd_seq_instr_list_free(&opl3->ilist);
293 return 0;
294}
295
296static int __init alsa_opl3_seq_init(void)
297{
298 static snd_seq_dev_ops_t ops =
299 {
300 snd_opl3_seq_new_device,
301 snd_opl3_seq_delete_device
302 };
303
304 return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL3, &ops,
305 sizeof(opl3_t*));
306}
307
308static void __exit alsa_opl3_seq_exit(void)
309{
310 snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL3);
311}
312
313module_init(alsa_opl3_seq_init)
314module_exit(alsa_opl3_seq_exit)
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
new file mode 100644
index 000000000000..04f9f955e5b7
--- /dev/null
+++ b/sound/drivers/opl3/opl3_synth.c
@@ -0,0 +1,447 @@
1/*
2 * Copyright (c) by Uros Bizjak <uros@kss-loka.si>
3 *
4 * Routines for OPL2/OPL3/OPL4 control
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/opl3.h>
23#include <sound/asound_fm.h>
24
25/*
26 * There is 18 possible 2 OP voices
27 * (9 in the left and 9 in the right).
28 * The first OP is the modulator and 2nd is the carrier.
29 *
30 * The first three voices in the both sides may be connected
31 * with another voice to a 4 OP voice. For example voice 0
32 * can be connected with voice 3. The operators of voice 3 are
33 * used as operators 3 and 4 of the new 4 OP voice.
34 * In this case the 2 OP voice number 0 is the 'first half' and
35 * voice 3 is the second.
36 */
37
38
39/*
40 * Register offset table for OPL2/3 voices,
41 * OPL2 / one OPL3 register array side only
42 */
43
44char snd_opl3_regmap[MAX_OPL2_VOICES][4] =
45{
46/* OP1 OP2 OP3 OP4 */
47/* ------------------------ */
48 { 0x00, 0x03, 0x08, 0x0b },
49 { 0x01, 0x04, 0x09, 0x0c },
50 { 0x02, 0x05, 0x0a, 0x0d },
51
52 { 0x08, 0x0b, 0x00, 0x00 },
53 { 0x09, 0x0c, 0x00, 0x00 },
54 { 0x0a, 0x0d, 0x00, 0x00 },
55
56 { 0x10, 0x13, 0x00, 0x00 }, /* used by percussive voices */
57 { 0x11, 0x14, 0x00, 0x00 }, /* if the percussive mode */
58 { 0x12, 0x15, 0x00, 0x00 } /* is selected (only left reg block) */
59};
60
61/*
62 * prototypes
63 */
64static int snd_opl3_play_note(opl3_t * opl3, snd_dm_fm_note_t * note);
65static int snd_opl3_set_voice(opl3_t * opl3, snd_dm_fm_voice_t * voice);
66static int snd_opl3_set_params(opl3_t * opl3, snd_dm_fm_params_t * params);
67static int snd_opl3_set_mode(opl3_t * opl3, int mode);
68static int snd_opl3_set_connection(opl3_t * opl3, int connection);
69
70/* ------------------------------ */
71
72/*
73 * open the device exclusively
74 */
75int snd_opl3_open(snd_hwdep_t * hw, struct file *file)
76{
77 opl3_t *opl3 = hw->private_data;
78
79 down(&opl3->access_mutex);
80 if (opl3->used) {
81 up(&opl3->access_mutex);
82 return -EAGAIN;
83 }
84 opl3->used++;
85 up(&opl3->access_mutex);
86
87 return 0;
88}
89
90/*
91 * ioctl for hwdep device:
92 */
93int snd_opl3_ioctl(snd_hwdep_t * hw, struct file *file,
94 unsigned int cmd, unsigned long arg)
95{
96 opl3_t *opl3 = hw->private_data;
97 void __user *argp = (void __user *)arg;
98
99 snd_assert(opl3 != NULL, return -EINVAL);
100
101 switch (cmd) {
102 /* get information */
103 case SNDRV_DM_FM_IOCTL_INFO:
104 {
105 snd_dm_fm_info_t info;
106
107 info.fm_mode = opl3->fm_mode;
108 info.rhythm = opl3->rhythm;
109 if (copy_to_user(argp, &info, sizeof(snd_dm_fm_info_t)))
110 return -EFAULT;
111 return 0;
112 }
113
114 case SNDRV_DM_FM_IOCTL_RESET:
115#ifdef CONFIG_SND_OSSEMUL
116 case SNDRV_DM_FM_OSS_IOCTL_RESET:
117#endif
118 snd_opl3_reset(opl3);
119 return 0;
120
121 case SNDRV_DM_FM_IOCTL_PLAY_NOTE:
122#ifdef CONFIG_SND_OSSEMUL
123 case SNDRV_DM_FM_OSS_IOCTL_PLAY_NOTE:
124#endif
125 {
126 snd_dm_fm_note_t note;
127 if (copy_from_user(&note, argp, sizeof(snd_dm_fm_note_t)))
128 return -EFAULT;
129 return snd_opl3_play_note(opl3, &note);
130 }
131
132 case SNDRV_DM_FM_IOCTL_SET_VOICE:
133#ifdef CONFIG_SND_OSSEMUL
134 case SNDRV_DM_FM_OSS_IOCTL_SET_VOICE:
135#endif
136 {
137 snd_dm_fm_voice_t voice;
138 if (copy_from_user(&voice, argp, sizeof(snd_dm_fm_voice_t)))
139 return -EFAULT;
140 return snd_opl3_set_voice(opl3, &voice);
141 }
142
143 case SNDRV_DM_FM_IOCTL_SET_PARAMS:
144#ifdef CONFIG_SND_OSSEMUL
145 case SNDRV_DM_FM_OSS_IOCTL_SET_PARAMS:
146#endif
147 {
148 snd_dm_fm_params_t params;
149 if (copy_from_user(&params, argp, sizeof(snd_dm_fm_params_t)))
150 return -EFAULT;
151 return snd_opl3_set_params(opl3, &params);
152 }
153
154 case SNDRV_DM_FM_IOCTL_SET_MODE:
155#ifdef CONFIG_SND_OSSEMUL
156 case SNDRV_DM_FM_OSS_IOCTL_SET_MODE:
157#endif
158 return snd_opl3_set_mode(opl3, (int) arg);
159
160 case SNDRV_DM_FM_IOCTL_SET_CONNECTION:
161#ifdef CONFIG_SND_OSSEMUL
162 case SNDRV_DM_FM_OSS_IOCTL_SET_OPL:
163#endif
164 return snd_opl3_set_connection(opl3, (int) arg);
165
166#ifdef CONFIG_SND_DEBUG
167 default:
168 snd_printk("unknown IOCTL: 0x%x\n", cmd);
169#endif
170 }
171 return -ENOTTY;
172}
173
174/*
175 * close the device
176 */
177int snd_opl3_release(snd_hwdep_t * hw, struct file *file)
178{
179 opl3_t *opl3 = hw->private_data;
180
181 snd_opl3_reset(opl3);
182 down(&opl3->access_mutex);
183 opl3->used--;
184 up(&opl3->access_mutex);
185
186 return 0;
187}
188
189/* ------------------------------ */
190
191void snd_opl3_reset(opl3_t * opl3)
192{
193 unsigned short opl3_reg;
194
195 unsigned short reg_side;
196 unsigned char voice_offset;
197
198 int max_voices, i;
199
200 max_voices = (opl3->hardware < OPL3_HW_OPL3) ?
201 MAX_OPL2_VOICES : MAX_OPL3_VOICES;
202
203 for (i = 0; i < max_voices; i++) {
204 /* Get register array side and offset of voice */
205 if (i < MAX_OPL2_VOICES) {
206 /* Left register block for voices 0 .. 8 */
207 reg_side = OPL3_LEFT;
208 voice_offset = i;
209 } else {
210 /* Right register block for voices 9 .. 17 */
211 reg_side = OPL3_RIGHT;
212 voice_offset = i - MAX_OPL2_VOICES;
213 }
214 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][0]);
215 opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 1 volume */
216 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + snd_opl3_regmap[voice_offset][1]);
217 opl3->command(opl3, opl3_reg, OPL3_TOTAL_LEVEL_MASK); /* Operator 2 volume */
218
219 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
220 opl3->command(opl3, opl3_reg, 0x00); /* Note off */
221 }
222
223 opl3->max_voices = MAX_OPL2_VOICES;
224 opl3->fm_mode = SNDRV_DM_FM_MODE_OPL2;
225
226 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
227 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00); /* Melodic mode */
228 opl3->rhythm = 0;
229}
230
231
232static int snd_opl3_play_note(opl3_t * opl3, snd_dm_fm_note_t * note)
233{
234 unsigned short reg_side;
235 unsigned char voice_offset;
236
237 unsigned short opl3_reg;
238 unsigned char reg_val;
239
240 /* Voices 0 - 8 in OPL2 mode */
241 /* Voices 0 - 17 in OPL3 mode */
242 if (note->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ?
243 MAX_OPL3_VOICES : MAX_OPL2_VOICES))
244 return -EINVAL;
245
246 /* Get register array side and offset of voice */
247 if (note->voice < MAX_OPL2_VOICES) {
248 /* Left register block for voices 0 .. 8 */
249 reg_side = OPL3_LEFT;
250 voice_offset = note->voice;
251 } else {
252 /* Right register block for voices 9 .. 17 */
253 reg_side = OPL3_RIGHT;
254 voice_offset = note->voice - MAX_OPL2_VOICES;
255 }
256
257 /* Set lower 8 bits of note frequency */
258 reg_val = (unsigned char) note->fnum;
259 opl3_reg = reg_side | (OPL3_REG_FNUM_LOW + voice_offset);
260 opl3->command(opl3, opl3_reg, reg_val);
261
262 reg_val = 0x00;
263 /* Set output sound flag */
264 if (note->key_on)
265 reg_val |= OPL3_KEYON_BIT;
266 /* Set octave */
267 reg_val |= (note->octave << 2) & OPL3_BLOCKNUM_MASK;
268 /* Set higher 2 bits of note frequency */
269 reg_val |= (unsigned char) (note->fnum >> 8) & OPL3_FNUM_HIGH_MASK;
270
271 /* Set OPL3 KEYON_BLOCK register of requested voice */
272 opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
273 opl3->command(opl3, opl3_reg, reg_val);
274
275 return 0;
276}
277
278
279static int snd_opl3_set_voice(opl3_t * opl3, snd_dm_fm_voice_t * voice)
280{
281 unsigned short reg_side;
282 unsigned char op_offset;
283 unsigned char voice_offset;
284
285 unsigned short opl3_reg;
286 unsigned char reg_val;
287
288 /* Only operators 1 and 2 */
289 if (voice->op > 1)
290 return -EINVAL;
291 /* Voices 0 - 8 in OPL2 mode */
292 /* Voices 0 - 17 in OPL3 mode */
293 if (voice->voice >= ((opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) ?
294 MAX_OPL3_VOICES : MAX_OPL2_VOICES))
295 return -EINVAL;
296
297 /* Get register array side and offset of voice */
298 if (voice->voice < MAX_OPL2_VOICES) {
299 /* Left register block for voices 0 .. 8 */
300 reg_side = OPL3_LEFT;
301 voice_offset = voice->voice;
302 } else {
303 /* Right register block for voices 9 .. 17 */
304 reg_side = OPL3_RIGHT;
305 voice_offset = voice->voice - MAX_OPL2_VOICES;
306 }
307 /* Get register offset of operator */
308 op_offset = snd_opl3_regmap[voice_offset][voice->op];
309
310 reg_val = 0x00;
311 /* Set amplitude modulation (tremolo) effect */
312 if (voice->am)
313 reg_val |= OPL3_TREMOLO_ON;
314 /* Set vibrato effect */
315 if (voice->vibrato)
316 reg_val |= OPL3_VIBRATO_ON;
317 /* Set sustaining sound phase */
318 if (voice->do_sustain)
319 reg_val |= OPL3_SUSTAIN_ON;
320 /* Set keyboard scaling bit */
321 if (voice->kbd_scale)
322 reg_val |= OPL3_KSR;
323 /* Set harmonic or frequency multiplier */
324 reg_val |= voice->harmonic & OPL3_MULTIPLE_MASK;
325
326 /* Set OPL3 AM_VIB register of requested voice/operator */
327 opl3_reg = reg_side | (OPL3_REG_AM_VIB + op_offset);
328 opl3->command(opl3, opl3_reg, reg_val);
329
330 /* Set decreasing volume of higher notes */
331 reg_val = (voice->scale_level << 6) & OPL3_KSL_MASK;
332 /* Set output volume */
333 reg_val |= ~voice->volume & OPL3_TOTAL_LEVEL_MASK;
334
335 /* Set OPL3 KSL_LEVEL register of requested voice/operator */
336 opl3_reg = reg_side | (OPL3_REG_KSL_LEVEL + op_offset);
337 opl3->command(opl3, opl3_reg, reg_val);
338
339 /* Set attack phase level */
340 reg_val = (voice->attack << 4) & OPL3_ATTACK_MASK;
341 /* Set decay phase level */
342 reg_val |= voice->decay & OPL3_DECAY_MASK;
343
344 /* Set OPL3 ATTACK_DECAY register of requested voice/operator */
345 opl3_reg = reg_side | (OPL3_REG_ATTACK_DECAY + op_offset);
346 opl3->command(opl3, opl3_reg, reg_val);
347
348 /* Set sustain phase level */
349 reg_val = (voice->sustain << 4) & OPL3_SUSTAIN_MASK;
350 /* Set release phase level */
351 reg_val |= voice->release & OPL3_RELEASE_MASK;
352
353 /* Set OPL3 SUSTAIN_RELEASE register of requested voice/operator */
354 opl3_reg = reg_side | (OPL3_REG_SUSTAIN_RELEASE + op_offset);
355 opl3->command(opl3, opl3_reg, reg_val);
356
357 /* Set inter-operator feedback */
358 reg_val = (voice->feedback << 1) & OPL3_FEEDBACK_MASK;
359 /* Set inter-operator connection */
360 if (voice->connection)
361 reg_val |= OPL3_CONNECTION_BIT;
362 /* OPL-3 only */
363 if (opl3->fm_mode == SNDRV_DM_FM_MODE_OPL3) {
364 if (voice->left)
365 reg_val |= OPL3_VOICE_TO_LEFT;
366 if (voice->right)
367 reg_val |= OPL3_VOICE_TO_RIGHT;
368 }
369 /* Feedback/connection bits are applicable to voice */
370 opl3_reg = reg_side | (OPL3_REG_FEEDBACK_CONNECTION + voice_offset);
371 opl3->command(opl3, opl3_reg, reg_val);
372
373 /* Select waveform */
374 reg_val = voice->waveform & OPL3_WAVE_SELECT_MASK;
375 opl3_reg = reg_side | (OPL3_REG_WAVE_SELECT + op_offset);
376 opl3->command(opl3, opl3_reg, reg_val);
377
378 return 0;
379}
380
381static int snd_opl3_set_params(opl3_t * opl3, snd_dm_fm_params_t * params)
382{
383 unsigned char reg_val;
384
385 reg_val = 0x00;
386 /* Set keyboard split method */
387 if (params->kbd_split)
388 reg_val |= OPL3_KEYBOARD_SPLIT;
389 opl3->command(opl3, OPL3_LEFT | OPL3_REG_KBD_SPLIT, reg_val);
390
391 reg_val = 0x00;
392 /* Set amplitude modulation (tremolo) depth */
393 if (params->am_depth)
394 reg_val |= OPL3_TREMOLO_DEPTH;
395 /* Set vibrato depth */
396 if (params->vib_depth)
397 reg_val |= OPL3_VIBRATO_DEPTH;
398 /* Set percussion mode */
399 if (params->rhythm) {
400 reg_val |= OPL3_PERCUSSION_ENABLE;
401 opl3->rhythm = 1;
402 } else {
403 opl3->rhythm = 0;
404 }
405 /* Play percussion instruments */
406 if (params->bass)
407 reg_val |= OPL3_BASSDRUM_ON;
408 if (params->snare)
409 reg_val |= OPL3_SNAREDRUM_ON;
410 if (params->tomtom)
411 reg_val |= OPL3_TOMTOM_ON;
412 if (params->cymbal)
413 reg_val |= OPL3_CYMBAL_ON;
414 if (params->hihat)
415 reg_val |= OPL3_HIHAT_ON;
416
417 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, reg_val);
418 return 0;
419}
420
421static int snd_opl3_set_mode(opl3_t * opl3, int mode)
422{
423 if ((mode == SNDRV_DM_FM_MODE_OPL3) && (opl3->hardware < OPL3_HW_OPL3))
424 return -EINVAL;
425
426 opl3->fm_mode = mode;
427 if (opl3->hardware >= OPL3_HW_OPL3)
428 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, 0x00); /* Clear 4-op connections */
429
430 return 0;
431}
432
433static int snd_opl3_set_connection(opl3_t * opl3, int connection)
434{
435 unsigned char reg_val;
436
437 /* OPL-3 only */
438 if (opl3->fm_mode != SNDRV_DM_FM_MODE_OPL3)
439 return -EINVAL;
440
441 reg_val = connection & (OPL3_RIGHT_4OP_0 | OPL3_RIGHT_4OP_1 | OPL3_RIGHT_4OP_2 |
442 OPL3_LEFT_4OP_0 | OPL3_LEFT_4OP_1 | OPL3_LEFT_4OP_2);
443 /* Set 4-op connections */
444 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_CONNECTION_SELECT, reg_val);
445
446 return 0;
447}
diff --git a/sound/drivers/opl3/opl3_voice.h b/sound/drivers/opl3/opl3_voice.h
new file mode 100644
index 000000000000..63346a5c3498
--- /dev/null
+++ b/sound/drivers/opl3/opl3_voice.h
@@ -0,0 +1,52 @@
1#ifndef __OPL3_VOICE_H
2#define __OPL3_VOICE_H
3
4/*
5 * Copyright (c) 2000 Uros Bizjak <uros@kss-loka.si>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22#include <sound/opl3.h>
23
24/* Prototypes for opl3_seq.c */
25int snd_opl3_synth_use_inc(opl3_t * opl3);
26void snd_opl3_synth_use_dec(opl3_t * opl3);
27int snd_opl3_synth_setup(opl3_t * opl3);
28void snd_opl3_synth_cleanup(opl3_t * opl3);
29
30/* Prototypes for opl3_midi.c */
31void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan);
32void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan);
33void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *chan);
34void snd_opl3_terminate_note(void *p, int note, snd_midi_channel_t *chan);
35void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan);
36void snd_opl3_nrpn(void *p, snd_midi_channel_t *chan, snd_midi_channel_set_t *chset);
37void snd_opl3_sysex(void *p, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
38
39void snd_opl3_calc_volume(unsigned char *reg, int vel, snd_midi_channel_t *chan);
40void snd_opl3_timer_func(unsigned long data);
41
42/* Prototypes for opl3_drums.c */
43void snd_opl3_load_drums(opl3_t *opl3);
44void snd_opl3_drum_switch(opl3_t *opl3, int note, int on_off, int vel, snd_midi_channel_t *chan);
45
46/* Prototypes for opl3_oss.c */
47#ifdef CONFIG_SND_SEQUENCER_OSS
48void snd_opl3_init_seq_oss(opl3_t *opl3, char *name);
49void snd_opl3_free_seq_oss(opl3_t *opl3);
50#endif
51
52#endif
diff --git a/sound/drivers/opl4/Makefile b/sound/drivers/opl4/Makefile
new file mode 100644
index 000000000000..141aacbaf315
--- /dev/null
+++ b/sound/drivers/opl4/Makefile
@@ -0,0 +1,18 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-opl4-lib-objs := opl4_lib.o opl4_mixer.o opl4_proc.o
7snd-opl4-synth-objs := opl4_seq.o opl4_synth.o yrw801.o
8
9#
10# this function returns:
11# "m" - CONFIG_SND_SEQUENCER is m
12# <empty string> - CONFIG_SND_SEQUENCER is undefined
13# otherwise parameter #1 value
14#
15sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1)))
16
17obj-$(CONFIG_SND_OPL4_LIB) += snd-opl4-lib.o
18obj-$(call sequencer,$(CONFIG_SND_OPL4_LIB)) += snd-opl4-synth.o
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
new file mode 100644
index 000000000000..8261464dade8
--- /dev/null
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -0,0 +1,281 @@
1/*
2 * Functions for accessing OPL4 devices
3 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "opl4_local.h"
21#include <sound/initval.h>
22#include <linux/ioport.h>
23#include <linux/init.h>
24#include <asm/io.h>
25
26MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
27MODULE_DESCRIPTION("OPL4 driver");
28MODULE_LICENSE("GPL");
29
30static void inline snd_opl4_wait(opl4_t *opl4)
31{
32 int timeout = 10;
33 while ((inb(opl4->fm_port) & OPL4_STATUS_BUSY) && --timeout > 0)
34 ;
35}
36
37void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value)
38{
39 snd_opl4_wait(opl4);
40 outb(reg, opl4->pcm_port);
41
42 snd_opl4_wait(opl4);
43 outb(value, opl4->pcm_port + 1);
44}
45
46u8 snd_opl4_read(opl4_t *opl4, u8 reg)
47{
48 snd_opl4_wait(opl4);
49 outb(reg, opl4->pcm_port);
50
51 snd_opl4_wait(opl4);
52 return inb(opl4->pcm_port + 1);
53}
54
55void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size)
56{
57 unsigned long flags;
58 u8 memcfg;
59
60 spin_lock_irqsave(&opl4->reg_lock, flags);
61
62 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
63 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
64
65 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
66 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
67 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
68
69 snd_opl4_wait(opl4);
70 outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
71 snd_opl4_wait(opl4);
72 insb(opl4->pcm_port + 1, buf, size);
73
74 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
75
76 spin_unlock_irqrestore(&opl4->reg_lock, flags);
77}
78
79void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size)
80{
81 unsigned long flags;
82 u8 memcfg;
83
84 spin_lock_irqsave(&opl4->reg_lock, flags);
85
86 memcfg = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
87 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg | OPL4_MODE_BIT);
88
89 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_HIGH, offset >> 16);
90 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_MID, offset >> 8);
91 snd_opl4_write(opl4, OPL4_REG_MEMORY_ADDRESS_LOW, offset);
92
93 snd_opl4_wait(opl4);
94 outb(OPL4_REG_MEMORY_DATA, opl4->pcm_port);
95 snd_opl4_wait(opl4);
96 outsb(opl4->pcm_port + 1, buf, size);
97
98 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, memcfg);
99
100 spin_unlock_irqrestore(&opl4->reg_lock, flags);
101}
102
103static void snd_opl4_enable_opl4(opl4_t *opl4)
104{
105 outb(OPL3_REG_MODE, opl4->fm_port + 2);
106 inb(opl4->fm_port);
107 inb(opl4->fm_port);
108 outb(OPL3_OPL3_ENABLE | OPL3_OPL4_ENABLE, opl4->fm_port + 3);
109 inb(opl4->fm_port);
110 inb(opl4->fm_port);
111}
112
113static int snd_opl4_detect(opl4_t *opl4)
114{
115 u8 id1, id2;
116
117 snd_opl4_enable_opl4(opl4);
118
119 id1 = snd_opl4_read(opl4, OPL4_REG_MEMORY_CONFIGURATION);
120 snd_printdd("OPL4[02]=%02x\n", id1);
121 switch (id1 & OPL4_DEVICE_ID_MASK) {
122 case 0x20:
123 opl4->hardware = OPL3_HW_OPL4;
124 break;
125 case 0x40:
126 opl4->hardware = OPL3_HW_OPL4_ML;
127 break;
128 default:
129 return -ENODEV;
130 }
131
132 snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x00);
133 snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0xff);
134 id1 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_FM);
135 id2 = snd_opl4_read(opl4, OPL4_REG_MIX_CONTROL_PCM);
136 snd_printdd("OPL4 id1=%02x id2=%02x\n", id1, id2);
137 if (id1 != 0x00 || id2 != 0xff)
138 return -ENODEV;
139
140 snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_FM, 0x3f);
141 snd_opl4_write(opl4, OPL4_REG_MIX_CONTROL_PCM, 0x3f);
142 snd_opl4_write(opl4, OPL4_REG_MEMORY_CONFIGURATION, 0x00);
143 return 0;
144}
145
146#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
147static void snd_opl4_seq_dev_free(snd_seq_device_t *seq_dev)
148{
149 opl4_t *opl4 = seq_dev->private_data;
150 opl4->seq_dev = NULL;
151}
152
153static int snd_opl4_create_seq_dev(opl4_t *opl4, int seq_device)
154{
155 opl4->seq_dev_num = seq_device;
156 if (snd_seq_device_new(opl4->card, seq_device, SNDRV_SEQ_DEV_ID_OPL4,
157 sizeof(opl4_t *), &opl4->seq_dev) >= 0) {
158 strcpy(opl4->seq_dev->name, "OPL4 Wavetable");
159 *(opl4_t **)SNDRV_SEQ_DEVICE_ARGPTR(opl4->seq_dev) = opl4;
160 opl4->seq_dev->private_data = opl4;
161 opl4->seq_dev->private_free = snd_opl4_seq_dev_free;
162 }
163 return 0;
164}
165#endif
166
167static void snd_opl4_free(opl4_t *opl4)
168{
169#ifdef CONFIG_PROC_FS
170 snd_opl4_free_proc(opl4);
171#endif
172 if (opl4->res_fm_port) {
173 release_resource(opl4->res_fm_port);
174 kfree_nocheck(opl4->res_fm_port);
175 }
176 if (opl4->res_pcm_port) {
177 release_resource(opl4->res_pcm_port);
178 kfree_nocheck(opl4->res_pcm_port);
179 }
180 kfree(opl4);
181}
182
183static int snd_opl4_dev_free(snd_device_t *device)
184{
185 opl4_t *opl4 = device->device_data;
186 snd_opl4_free(opl4);
187 return 0;
188}
189
190int snd_opl4_create(snd_card_t *card,
191 unsigned long fm_port, unsigned long pcm_port,
192 int seq_device,
193 opl3_t **ropl3, opl4_t **ropl4)
194{
195 opl4_t *opl4;
196 opl3_t *opl3;
197 int err;
198 static snd_device_ops_t ops = {
199 .dev_free = snd_opl4_dev_free
200 };
201
202 if (ropl3)
203 *ropl3 = NULL;
204 if (ropl4)
205 *ropl4 = NULL;
206
207 opl4 = kcalloc(1, sizeof(*opl4), GFP_KERNEL);
208 if (!opl4)
209 return -ENOMEM;
210
211 opl4->res_fm_port = request_region(fm_port, 8, "OPL4 FM");
212 opl4->res_pcm_port = request_region(pcm_port, 8, "OPL4 PCM/MIX");
213 if (!opl4->res_fm_port || !opl4->res_pcm_port) {
214 snd_printk(KERN_ERR "opl4: can't grab ports 0x%lx, 0x%lx\n", fm_port, pcm_port);
215 snd_opl4_free(opl4);
216 return -EBUSY;
217 }
218
219 opl4->card = card;
220 opl4->fm_port = fm_port;
221 opl4->pcm_port = pcm_port;
222 spin_lock_init(&opl4->reg_lock);
223 init_MUTEX(&opl4->access_mutex);
224
225 err = snd_opl4_detect(opl4);
226 if (err < 0) {
227 snd_opl4_free(opl4);
228 snd_printd("OPL4 chip not detected at %#lx/%#lx\n", fm_port, pcm_port);
229 return err;
230 }
231
232 err = snd_device_new(card, SNDRV_DEV_CODEC, opl4, &ops);
233 if (err < 0) {
234 snd_opl4_free(opl4);
235 return err;
236 }
237
238 err = snd_opl3_create(card, fm_port, fm_port + 2, opl4->hardware, 1, &opl3);
239 if (err < 0) {
240 snd_device_free(card, opl4);
241 return err;
242 }
243
244 /* opl3 initialization disabled opl4, so reenable */
245 snd_opl4_enable_opl4(opl4);
246
247 snd_opl4_create_mixer(opl4);
248#ifdef CONFIG_PROC_FS
249 snd_opl4_create_proc(opl4);
250#endif
251
252#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
253 opl4->seq_client = -1;
254 if (opl4->hardware < OPL3_HW_OPL4_ML)
255 snd_opl4_create_seq_dev(opl4, seq_device);
256#endif
257
258 if (ropl3)
259 *ropl3 = opl3;
260 if (ropl4)
261 *ropl4 = opl4;
262 return 0;
263}
264
265EXPORT_SYMBOL(snd_opl4_write);
266EXPORT_SYMBOL(snd_opl4_read);
267EXPORT_SYMBOL(snd_opl4_write_memory);
268EXPORT_SYMBOL(snd_opl4_read_memory);
269EXPORT_SYMBOL(snd_opl4_create);
270
271static int __init alsa_opl4_init(void)
272{
273 return 0;
274}
275
276static void __exit alsa_opl4_exit(void)
277{
278}
279
280module_init(alsa_opl4_init)
281module_exit(alsa_opl4_exit)
diff --git a/sound/drivers/opl4/opl4_local.h b/sound/drivers/opl4/opl4_local.h
new file mode 100644
index 000000000000..c455680843f6
--- /dev/null
+++ b/sound/drivers/opl4/opl4_local.h
@@ -0,0 +1,232 @@
1/*
2 * Local definitions for the OPL4 driver
3 *
4 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed and/or modified under the
17 * terms of the GNU General Public License as published by the Free Software
18 * Foundation; either version 2 of the License, or (at your option) any later
19 * version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
25 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef __OPL4_LOCAL_H
35#define __OPL4_LOCAL_H
36
37#include <sound/opl4.h>
38
39/*
40 * Register numbers
41 */
42
43#define OPL4_REG_TEST0 0x00
44#define OPL4_REG_TEST1 0x01
45
46#define OPL4_REG_MEMORY_CONFIGURATION 0x02
47#define OPL4_MODE_BIT 0x01
48#define OPL4_MTYPE_BIT 0x02
49#define OPL4_TONE_HEADER_MASK 0x1c
50#define OPL4_DEVICE_ID_MASK 0xe0
51
52#define OPL4_REG_MEMORY_ADDRESS_HIGH 0x03
53#define OPL4_REG_MEMORY_ADDRESS_MID 0x04
54#define OPL4_REG_MEMORY_ADDRESS_LOW 0x05
55#define OPL4_REG_MEMORY_DATA 0x06
56
57/*
58 * Offsets to the register banks for voices. To get the
59 * register number just add the voice number to the bank offset.
60 *
61 * Wave Table Number low bits (0x08 to 0x1F)
62 */
63#define OPL4_REG_TONE_NUMBER 0x08
64
65/* Wave Table Number high bit, F-Number low bits (0x20 to 0x37) */
66#define OPL4_REG_F_NUMBER 0x20
67#define OPL4_TONE_NUMBER_BIT8 0x01
68#define OPL4_F_NUMBER_LOW_MASK 0xfe
69
70/* F-Number high bits, Octave, Pseudo-Reverb (0x38 to 0x4F) */
71#define OPL4_REG_OCTAVE 0x38
72#define OPL4_F_NUMBER_HIGH_MASK 0x07
73#define OPL4_BLOCK_MASK 0xf0
74#define OPL4_PSEUDO_REVERB_BIT 0x08
75
76/* Total Level, Level Direct (0x50 to 0x67) */
77#define OPL4_REG_LEVEL 0x50
78#define OPL4_TOTAL_LEVEL_MASK 0xfe
79#define OPL4_LEVEL_DIRECT_BIT 0x01
80
81/* Key On, Damp, LFO RST, CH, Panpot (0x68 to 0x7F) */
82#define OPL4_REG_MISC 0x68
83#define OPL4_KEY_ON_BIT 0x80
84#define OPL4_DAMP_BIT 0x40
85#define OPL4_LFO_RESET_BIT 0x20
86#define OPL4_OUTPUT_CHANNEL_BIT 0x10
87#define OPL4_PAN_POT_MASK 0x0f
88
89/* LFO, VIB (0x80 to 0x97) */
90#define OPL4_REG_LFO_VIBRATO 0x80
91#define OPL4_LFO_FREQUENCY_MASK 0x38
92#define OPL4_VIBRATO_DEPTH_MASK 0x07
93#define OPL4_CHORUS_SEND_MASK 0xc0 /* ML only */
94
95/* Attack / Decay 1 rate (0x98 to 0xAF) */
96#define OPL4_REG_ATTACK_DECAY1 0x98
97#define OPL4_ATTACK_RATE_MASK 0xf0
98#define OPL4_DECAY1_RATE_MASK 0x0f
99
100/* Decay level / 2 rate (0xB0 to 0xC7) */
101#define OPL4_REG_LEVEL_DECAY2 0xb0
102#define OPL4_DECAY_LEVEL_MASK 0xf0
103#define OPL4_DECAY2_RATE_MASK 0x0f
104
105/* Release rate / Rate correction (0xC8 to 0xDF) */
106#define OPL4_REG_RELEASE_CORRECTION 0xc8
107#define OPL4_RELEASE_RATE_MASK 0x0f
108#define OPL4_RATE_INTERPOLATION_MASK 0xf0
109
110/* AM (0xE0 to 0xF7) */
111#define OPL4_REG_TREMOLO 0xe0
112#define OPL4_TREMOLO_DEPTH_MASK 0x07
113#define OPL4_REVERB_SEND_MASK 0xe0 /* ML only */
114
115/* Mixer */
116#define OPL4_REG_MIX_CONTROL_FM 0xf8
117#define OPL4_REG_MIX_CONTROL_PCM 0xf9
118#define OPL4_MIX_LEFT_MASK 0x07
119#define OPL4_MIX_RIGHT_MASK 0x38
120
121#define OPL4_REG_ATC 0xfa
122#define OPL4_ATC_BIT 0x01 /* ???, ML only */
123
124/* bits in the OPL3 Status register */
125#define OPL4_STATUS_BUSY 0x01
126#define OPL4_STATUS_LOAD 0x02
127
128
129#define OPL4_MAX_VOICES 24
130
131#define SNDRV_SEQ_DEV_ID_OPL4 "opl4-synth"
132
133
134typedef struct opl4_sound {
135 u16 tone;
136 s16 pitch_offset;
137 u8 key_scaling;
138 s8 panpot;
139 u8 vibrato;
140 u8 tone_attenuate;
141 u8 volume_factor;
142 u8 reg_lfo_vibrato;
143 u8 reg_attack_decay1;
144 u8 reg_level_decay2;
145 u8 reg_release_correction;
146 u8 reg_tremolo;
147} opl4_sound_t;
148
149typedef struct opl4_region {
150 u8 key_min, key_max;
151 opl4_sound_t sound;
152} opl4_region_t;
153
154typedef struct opl4_region_ptr {
155 int count;
156 const opl4_region_t *regions;
157} opl4_region_ptr_t;
158
159typedef struct opl4_voice {
160 struct list_head list;
161 int number;
162 snd_midi_channel_t *chan;
163 int note;
164 int velocity;
165 const opl4_sound_t *sound;
166 u8 level_direct;
167 u8 reg_f_number;
168 u8 reg_misc;
169 u8 reg_lfo_vibrato;
170} opl4_voice_t;
171
172struct opl4 {
173 unsigned long fm_port;
174 unsigned long pcm_port;
175 struct resource *res_fm_port;
176 struct resource *res_pcm_port;
177 unsigned short hardware;
178 spinlock_t reg_lock;
179 snd_card_t *card;
180
181#ifdef CONFIG_PROC_FS
182 snd_info_entry_t *proc_entry;
183 int memory_access;
184#endif
185 struct semaphore access_mutex;
186
187#if defined(CONFIG_SND_SEQUENCER) || defined(CONFIG_SND_SEQUENCER_MODULE)
188 int used;
189
190 int seq_dev_num;
191 int seq_client;
192 snd_seq_device_t *seq_dev;
193
194 snd_midi_channel_set_t *chset;
195 opl4_voice_t voices[OPL4_MAX_VOICES];
196 struct list_head off_voices;
197 struct list_head on_voices;
198#endif
199};
200
201/* opl4_lib.c */
202void snd_opl4_write(opl4_t *opl4, u8 reg, u8 value);
203u8 snd_opl4_read(opl4_t *opl4, u8 reg);
204void snd_opl4_read_memory(opl4_t *opl4, char *buf, int offset, int size);
205void snd_opl4_write_memory(opl4_t *opl4, const char *buf, int offset, int size);
206
207/* opl4_mixer.c */
208int snd_opl4_create_mixer(opl4_t *opl4);
209
210#ifdef CONFIG_PROC_FS
211/* opl4_proc.c */
212int snd_opl4_create_proc(opl4_t *opl4);
213void snd_opl4_free_proc(opl4_t *opl4);
214#endif
215
216/* opl4_seq.c */
217extern int volume_boost;
218
219/* opl4_synth.c */
220void snd_opl4_synth_reset(opl4_t *opl4);
221void snd_opl4_synth_shutdown(opl4_t *opl4);
222void snd_opl4_note_on(void *p, int note, int vel, snd_midi_channel_t *chan);
223void snd_opl4_note_off(void *p, int note, int vel, snd_midi_channel_t *chan);
224void snd_opl4_terminate_note(void *p, int note, snd_midi_channel_t *chan);
225void snd_opl4_control(void *p, int type, snd_midi_channel_t *chan);
226void snd_opl4_sysex(void *p, unsigned char *buf, int len, int parsed, snd_midi_channel_set_t *chset);
227
228/* yrw801.c */
229int snd_yrw801_detect(opl4_t *opl4);
230extern const opl4_region_ptr_t snd_yrw801_regions[];
231
232#endif /* __OPL4_LOCAL_H */
diff --git a/sound/drivers/opl4/opl4_mixer.c b/sound/drivers/opl4/opl4_mixer.c
new file mode 100644
index 000000000000..ec7a228fbe7e
--- /dev/null
+++ b/sound/drivers/opl4/opl4_mixer.c
@@ -0,0 +1,95 @@
1/*
2 * OPL4 mixer functions
3 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "opl4_local.h"
21#include <sound/control.h>
22
23static int snd_opl4_ctl_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
24{
25 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
26 uinfo->count = 2;
27 uinfo->value.integer.min = 0;
28 uinfo->value.integer.max = 7;
29 return 0;
30}
31
32static int snd_opl4_ctl_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
33{
34 opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
35 unsigned long flags;
36 u8 reg = kcontrol->private_value;
37 u8 value;
38
39 spin_lock_irqsave(&opl4->reg_lock, flags);
40 value = snd_opl4_read(opl4, reg);
41 spin_unlock_irqrestore(&opl4->reg_lock, flags);
42 ucontrol->value.integer.value[0] = 7 - (value & 7);
43 ucontrol->value.integer.value[1] = 7 - ((value >> 3) & 7);
44 return 0;
45}
46
47static int snd_opl4_ctl_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
48{
49 opl4_t *opl4 = snd_kcontrol_chip(kcontrol);
50 unsigned long flags;
51 u8 reg = kcontrol->private_value;
52 u8 value, old_value;
53
54 value = (7 - (ucontrol->value.integer.value[0] & 7)) |
55 ((7 - (ucontrol->value.integer.value[1] & 7)) << 3);
56 spin_lock_irqsave(&opl4->reg_lock, flags);
57 old_value = snd_opl4_read(opl4, reg);
58 snd_opl4_write(opl4, reg, value);
59 spin_unlock_irqrestore(&opl4->reg_lock, flags);
60 return value != old_value;
61}
62
63static snd_kcontrol_new_t snd_opl4_controls[] = {
64 {
65 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
66 .name = "FM Playback Volume",
67 .info = snd_opl4_ctl_info,
68 .get = snd_opl4_ctl_get,
69 .put = snd_opl4_ctl_put,
70 .private_value = OPL4_REG_MIX_CONTROL_FM
71 },
72 {
73 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
74 .name = "Wavetable Playback Volume",
75 .info = snd_opl4_ctl_info,
76 .get = snd_opl4_ctl_get,
77 .put = snd_opl4_ctl_put,
78 .private_value = OPL4_REG_MIX_CONTROL_PCM
79 }
80};
81
82int snd_opl4_create_mixer(opl4_t *opl4)
83{
84 snd_card_t *card = opl4->card;
85 int i, err;
86
87 strcat(card->mixername, ",OPL4");
88
89 for (i = 0; i < 2; ++i) {
90 err = snd_ctl_add(card, snd_ctl_new1(&snd_opl4_controls[i], opl4));
91 if (err < 0)
92 return err;
93 }
94 return 0;
95}
diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c
new file mode 100644
index 000000000000..6a1486258acf
--- /dev/null
+++ b/sound/drivers/opl4/opl4_proc.c
@@ -0,0 +1,166 @@
1/*
2 * Functions for the OPL4 proc file
3 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20#include "opl4_local.h"
21#include <linux/vmalloc.h>
22#include <sound/info.h>
23
24#ifdef CONFIG_PROC_FS
25
26static int snd_opl4_mem_proc_open(snd_info_entry_t *entry,
27 unsigned short mode, void **file_private_data)
28{
29 opl4_t *opl4 = entry->private_data;
30
31 down(&opl4->access_mutex);
32 if (opl4->memory_access) {
33 up(&opl4->access_mutex);
34 return -EBUSY;
35 }
36 opl4->memory_access++;
37 up(&opl4->access_mutex);
38 return 0;
39}
40
41static int snd_opl4_mem_proc_release(snd_info_entry_t *entry,
42 unsigned short mode, void *file_private_data)
43{
44 opl4_t *opl4 = entry->private_data;
45
46 down(&opl4->access_mutex);
47 opl4->memory_access--;
48 up(&opl4->access_mutex);
49 return 0;
50}
51
52static long snd_opl4_mem_proc_read(snd_info_entry_t *entry, void *file_private_data,
53 struct file *file, char __user *_buf,
54 unsigned long count, unsigned long pos)
55{
56 opl4_t *opl4 = entry->private_data;
57 long size;
58 char* buf;
59
60 size = count;
61 if (pos + size > entry->size)
62 size = entry->size - pos;
63 if (size > 0) {
64 buf = vmalloc(size);
65 if (!buf)
66 return -ENOMEM;
67 snd_opl4_read_memory(opl4, buf, pos, size);
68 if (copy_to_user(_buf, buf, size)) {
69 vfree(buf);
70 return -EFAULT;
71 }
72 vfree(buf);
73 return size;
74 }
75 return 0;
76}
77
78static long snd_opl4_mem_proc_write(snd_info_entry_t *entry, void *file_private_data,
79 struct file *file, const char __user *_buf,
80 unsigned long count, unsigned long pos)
81{
82 opl4_t *opl4 = entry->private_data;
83 long size;
84 char *buf;
85
86 size = count;
87 if (pos + size > entry->size)
88 size = entry->size - pos;
89 if (size > 0) {
90 buf = vmalloc(size);
91 if (!buf)
92 return -ENOMEM;
93 if (copy_from_user(buf, _buf, size)) {
94 vfree(buf);
95 return -EFAULT;
96 }
97 snd_opl4_write_memory(opl4, buf, pos, size);
98 vfree(buf);
99 return size;
100 }
101 return 0;
102}
103
104static long long snd_opl4_mem_proc_llseek(snd_info_entry_t *entry, void *file_private_data,
105 struct file *file, long long offset, int orig)
106{
107 switch (orig) {
108 case 0: /* SEEK_SET */
109 file->f_pos = offset;
110 break;
111 case 1: /* SEEK_CUR */
112 file->f_pos += offset;
113 break;
114 case 2: /* SEEK_END, offset is negative */
115 file->f_pos = entry->size + offset;
116 break;
117 default:
118 return -EINVAL;
119 }
120 if (file->f_pos > entry->size)
121 file->f_pos = entry->size;
122 return file->f_pos;
123}
124
125static struct snd_info_entry_ops snd_opl4_mem_proc_ops = {
126 .open = snd_opl4_mem_proc_open,
127 .release = snd_opl4_mem_proc_release,
128 .read = snd_opl4_mem_proc_read,
129 .write = snd_opl4_mem_proc_write,
130 .llseek = snd_opl4_mem_proc_llseek,
131};
132
133int snd_opl4_create_proc(opl4_t *opl4)
134{
135 snd_info_entry_t *entry;
136
137 entry = snd_info_create_card_entry(opl4->card, "opl4-mem", opl4->card->proc_root);
138 if (entry) {
139 if (opl4->hardware < OPL3_HW_OPL4_ML) {
140 /* OPL4 can access 4 MB external ROM/SRAM */
141 entry->mode |= S_IWUSR;
142 entry->size = 4 * 1024 * 1024;
143 } else {
144 /* OPL4-ML has 1 MB internal ROM */
145 entry->size = 1 * 1024 * 1024;
146 }
147 entry->content = SNDRV_INFO_CONTENT_DATA;
148 entry->c.ops = &snd_opl4_mem_proc_ops;
149 entry->module = THIS_MODULE;
150 entry->private_data = opl4;
151 if (snd_info_register(entry) < 0) {
152 snd_info_free_entry(entry);
153 entry = NULL;
154 }
155 }
156 opl4->proc_entry = entry;
157 return 0;
158}
159
160void snd_opl4_free_proc(opl4_t *opl4)
161{
162 if (opl4->proc_entry)
163 snd_info_unregister(opl4->proc_entry);
164}
165
166#endif /* CONFIG_PROC_FS */
diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c
new file mode 100644
index 000000000000..958dfe88479a
--- /dev/null
+++ b/sound/drivers/opl4/opl4_seq.c
@@ -0,0 +1,223 @@
1/*
2 * OPL4 sequencer functions
3 *
4 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed and/or modified under the
17 * terms of the GNU General Public License as published by the Free Software
18 * Foundation; either version 2 of the License, or (at your option) any later
19 * version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
25 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "opl4_local.h"
35#include <linux/init.h>
36#include <linux/moduleparam.h>
37#include <sound/initval.h>
38
39MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
40MODULE_DESCRIPTION("OPL4 wavetable synth driver");
41MODULE_LICENSE("Dual BSD/GPL");
42
43int volume_boost = 8;
44
45module_param(volume_boost, int, 0644);
46MODULE_PARM_DESC(volume_boost, "Additional volume for OPL4 wavetable sounds.");
47
48static int snd_opl4_seq_use_inc(opl4_t *opl4)
49{
50 if (!try_module_get(opl4->card->module))
51 return -EFAULT;
52 return 0;
53}
54
55static void snd_opl4_seq_use_dec(opl4_t *opl4)
56{
57 module_put(opl4->card->module);
58}
59
60static int snd_opl4_seq_use(void *private_data, snd_seq_port_subscribe_t *info)
61{
62 opl4_t *opl4 = private_data;
63 int err;
64
65 down(&opl4->access_mutex);
66
67 if (opl4->used) {
68 up(&opl4->access_mutex);
69 return -EBUSY;
70 }
71 opl4->used++;
72
73 if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM) {
74 err = snd_opl4_seq_use_inc(opl4);
75 if (err < 0) {
76 up(&opl4->access_mutex);
77 return err;
78 }
79 }
80
81 up(&opl4->access_mutex);
82
83 snd_opl4_synth_reset(opl4);
84 return 0;
85}
86
87static int snd_opl4_seq_unuse(void *private_data, snd_seq_port_subscribe_t *info)
88{
89 opl4_t *opl4 = private_data;
90
91 snd_opl4_synth_shutdown(opl4);
92
93 down(&opl4->access_mutex);
94 opl4->used--;
95 up(&opl4->access_mutex);
96
97 if (info->sender.client != SNDRV_SEQ_CLIENT_SYSTEM)
98 snd_opl4_seq_use_dec(opl4);
99 return 0;
100}
101
102static snd_midi_op_t opl4_ops = {
103 .note_on = snd_opl4_note_on,
104 .note_off = snd_opl4_note_off,
105 .note_terminate = snd_opl4_terminate_note,
106 .control = snd_opl4_control,
107 .sysex = snd_opl4_sysex,
108};
109
110static int snd_opl4_seq_event_input(snd_seq_event_t *ev, int direct,
111 void *private_data, int atomic, int hop)
112{
113 opl4_t *opl4 = private_data;
114
115 snd_midi_process_event(&opl4_ops, ev, opl4->chset);
116 return 0;
117}
118
119static void snd_opl4_seq_free_port(void *private_data)
120{
121 opl4_t *opl4 = private_data;
122
123 snd_midi_channel_free_set(opl4->chset);
124}
125
126static int snd_opl4_seq_new_device(snd_seq_device_t *dev)
127{
128 opl4_t *opl4;
129 int client;
130 snd_seq_client_callback_t callbacks;
131 snd_seq_client_info_t cinfo;
132 snd_seq_port_callback_t pcallbacks;
133
134 opl4 = *(opl4_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
135 if (!opl4)
136 return -EINVAL;
137
138 if (snd_yrw801_detect(opl4) < 0)
139 return -ENODEV;
140
141 opl4->chset = snd_midi_channel_alloc_set(16);
142 if (!opl4->chset)
143 return -ENOMEM;
144 opl4->chset->private_data = opl4;
145
146 /* allocate new client */
147 memset(&callbacks, 0, sizeof(callbacks));
148 callbacks.private_data = opl4;
149 callbacks.allow_output = callbacks.allow_input = 1;
150 client = snd_seq_create_kernel_client(opl4->card, opl4->seq_dev_num, &callbacks);
151 if (client < 0) {
152 snd_midi_channel_free_set(opl4->chset);
153 return client;
154 }
155 opl4->seq_client = client;
156 opl4->chset->client = client;
157
158 /* change name of client */
159 memset(&cinfo, 0, sizeof(cinfo));
160 cinfo.client = client;
161 cinfo.type = KERNEL_CLIENT;
162 strcpy(cinfo.name, "OPL4 Wavetable");
163 snd_seq_kernel_client_ctl(client, SNDRV_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo);
164
165 /* create new port */
166 memset(&pcallbacks, 0, sizeof(pcallbacks));
167 pcallbacks.owner = THIS_MODULE;
168 pcallbacks.use = snd_opl4_seq_use;
169 pcallbacks.unuse = snd_opl4_seq_unuse;
170 pcallbacks.event_input = snd_opl4_seq_event_input;
171 pcallbacks.private_free = snd_opl4_seq_free_port;
172 pcallbacks.private_data = opl4;
173
174 opl4->chset->port = snd_seq_event_port_attach(client, &pcallbacks,
175 SNDRV_SEQ_PORT_CAP_WRITE |
176 SNDRV_SEQ_PORT_CAP_SUBS_WRITE,
177 SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC |
178 SNDRV_SEQ_PORT_TYPE_MIDI_GM,
179 16, 24,
180 "OPL4 Wavetable Port");
181 if (opl4->chset->port < 0) {
182 int err = opl4->chset->port;
183 snd_midi_channel_free_set(opl4->chset);
184 snd_seq_delete_kernel_client(client);
185 opl4->seq_client = -1;
186 return err;
187 }
188 return 0;
189}
190
191static int snd_opl4_seq_delete_device(snd_seq_device_t *dev)
192{
193 opl4_t *opl4;
194
195 opl4 = *(opl4_t **)SNDRV_SEQ_DEVICE_ARGPTR(dev);
196 if (!opl4)
197 return -EINVAL;
198
199 if (opl4->seq_client >= 0) {
200 snd_seq_delete_kernel_client(opl4->seq_client);
201 opl4->seq_client = -1;
202 }
203 return 0;
204}
205
206static int __init alsa_opl4_synth_init(void)
207{
208 static snd_seq_dev_ops_t ops = {
209 snd_opl4_seq_new_device,
210 snd_opl4_seq_delete_device
211 };
212
213 return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_OPL4, &ops,
214 sizeof(opl4_t*));
215}
216
217static void __exit alsa_opl4_synth_exit(void)
218{
219 snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_OPL4);
220}
221
222module_init(alsa_opl4_synth_init)
223module_exit(alsa_opl4_synth_exit)
diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c
new file mode 100644
index 000000000000..b146a1c995d9
--- /dev/null
+++ b/sound/drivers/opl4/opl4_synth.c
@@ -0,0 +1,630 @@
1/*
2 * OPL4 MIDI synthesizer functions
3 *
4 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed and/or modified under the
17 * terms of the GNU General Public License as published by the Free Software
18 * Foundation; either version 2 of the License, or (at your option) any later
19 * version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
25 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "opl4_local.h"
35#include <linux/delay.h>
36#include <asm/io.h>
37#include <sound/asoundef.h>
38
39/* GM2 controllers */
40#ifndef MIDI_CTL_RELEASE_TIME
41#define MIDI_CTL_RELEASE_TIME 0x48
42#define MIDI_CTL_ATTACK_TIME 0x49
43#define MIDI_CTL_DECAY_TIME 0x4b
44#define MIDI_CTL_VIBRATO_RATE 0x4c
45#define MIDI_CTL_VIBRATO_DEPTH 0x4d
46#define MIDI_CTL_VIBRATO_DELAY 0x4e
47#endif
48
49/*
50 * This table maps 100/128 cents to F_NUMBER.
51 */
52static const s16 snd_opl4_pitch_map[0x600] = {
53 0x000,0x000,0x001,0x001,0x002,0x002,0x003,0x003,
54 0x004,0x004,0x005,0x005,0x006,0x006,0x006,0x007,
55 0x007,0x008,0x008,0x009,0x009,0x00a,0x00a,0x00b,
56 0x00b,0x00c,0x00c,0x00d,0x00d,0x00d,0x00e,0x00e,
57 0x00f,0x00f,0x010,0x010,0x011,0x011,0x012,0x012,
58 0x013,0x013,0x014,0x014,0x015,0x015,0x015,0x016,
59 0x016,0x017,0x017,0x018,0x018,0x019,0x019,0x01a,
60 0x01a,0x01b,0x01b,0x01c,0x01c,0x01d,0x01d,0x01e,
61 0x01e,0x01e,0x01f,0x01f,0x020,0x020,0x021,0x021,
62 0x022,0x022,0x023,0x023,0x024,0x024,0x025,0x025,
63 0x026,0x026,0x027,0x027,0x028,0x028,0x029,0x029,
64 0x029,0x02a,0x02a,0x02b,0x02b,0x02c,0x02c,0x02d,
65 0x02d,0x02e,0x02e,0x02f,0x02f,0x030,0x030,0x031,
66 0x031,0x032,0x032,0x033,0x033,0x034,0x034,0x035,
67 0x035,0x036,0x036,0x037,0x037,0x038,0x038,0x038,
68 0x039,0x039,0x03a,0x03a,0x03b,0x03b,0x03c,0x03c,
69 0x03d,0x03d,0x03e,0x03e,0x03f,0x03f,0x040,0x040,
70 0x041,0x041,0x042,0x042,0x043,0x043,0x044,0x044,
71 0x045,0x045,0x046,0x046,0x047,0x047,0x048,0x048,
72 0x049,0x049,0x04a,0x04a,0x04b,0x04b,0x04c,0x04c,
73 0x04d,0x04d,0x04e,0x04e,0x04f,0x04f,0x050,0x050,
74 0x051,0x051,0x052,0x052,0x053,0x053,0x054,0x054,
75 0x055,0x055,0x056,0x056,0x057,0x057,0x058,0x058,
76 0x059,0x059,0x05a,0x05a,0x05b,0x05b,0x05c,0x05c,
77 0x05d,0x05d,0x05e,0x05e,0x05f,0x05f,0x060,0x060,
78 0x061,0x061,0x062,0x062,0x063,0x063,0x064,0x064,
79 0x065,0x065,0x066,0x066,0x067,0x067,0x068,0x068,
80 0x069,0x069,0x06a,0x06a,0x06b,0x06b,0x06c,0x06c,
81 0x06d,0x06d,0x06e,0x06e,0x06f,0x06f,0x070,0x071,
82 0x071,0x072,0x072,0x073,0x073,0x074,0x074,0x075,
83 0x075,0x076,0x076,0x077,0x077,0x078,0x078,0x079,
84 0x079,0x07a,0x07a,0x07b,0x07b,0x07c,0x07c,0x07d,
85 0x07d,0x07e,0x07e,0x07f,0x07f,0x080,0x081,0x081,
86 0x082,0x082,0x083,0x083,0x084,0x084,0x085,0x085,
87 0x086,0x086,0x087,0x087,0x088,0x088,0x089,0x089,
88 0x08a,0x08a,0x08b,0x08b,0x08c,0x08d,0x08d,0x08e,
89 0x08e,0x08f,0x08f,0x090,0x090,0x091,0x091,0x092,
90 0x092,0x093,0x093,0x094,0x094,0x095,0x096,0x096,
91 0x097,0x097,0x098,0x098,0x099,0x099,0x09a,0x09a,
92 0x09b,0x09b,0x09c,0x09c,0x09d,0x09d,0x09e,0x09f,
93 0x09f,0x0a0,0x0a0,0x0a1,0x0a1,0x0a2,0x0a2,0x0a3,
94 0x0a3,0x0a4,0x0a4,0x0a5,0x0a6,0x0a6,0x0a7,0x0a7,
95 0x0a8,0x0a8,0x0a9,0x0a9,0x0aa,0x0aa,0x0ab,0x0ab,
96 0x0ac,0x0ad,0x0ad,0x0ae,0x0ae,0x0af,0x0af,0x0b0,
97 0x0b0,0x0b1,0x0b1,0x0b2,0x0b2,0x0b3,0x0b4,0x0b4,
98 0x0b5,0x0b5,0x0b6,0x0b6,0x0b7,0x0b7,0x0b8,0x0b8,
99 0x0b9,0x0ba,0x0ba,0x0bb,0x0bb,0x0bc,0x0bc,0x0bd,
100 0x0bd,0x0be,0x0be,0x0bf,0x0c0,0x0c0,0x0c1,0x0c1,
101 0x0c2,0x0c2,0x0c3,0x0c3,0x0c4,0x0c4,0x0c5,0x0c6,
102 0x0c6,0x0c7,0x0c7,0x0c8,0x0c8,0x0c9,0x0c9,0x0ca,
103 0x0cb,0x0cb,0x0cc,0x0cc,0x0cd,0x0cd,0x0ce,0x0ce,
104 0x0cf,0x0d0,0x0d0,0x0d1,0x0d1,0x0d2,0x0d2,0x0d3,
105 0x0d3,0x0d4,0x0d5,0x0d5,0x0d6,0x0d6,0x0d7,0x0d7,
106 0x0d8,0x0d8,0x0d9,0x0da,0x0da,0x0db,0x0db,0x0dc,
107 0x0dc,0x0dd,0x0de,0x0de,0x0df,0x0df,0x0e0,0x0e0,
108 0x0e1,0x0e1,0x0e2,0x0e3,0x0e3,0x0e4,0x0e4,0x0e5,
109 0x0e5,0x0e6,0x0e7,0x0e7,0x0e8,0x0e8,0x0e9,0x0e9,
110 0x0ea,0x0eb,0x0eb,0x0ec,0x0ec,0x0ed,0x0ed,0x0ee,
111 0x0ef,0x0ef,0x0f0,0x0f0,0x0f1,0x0f1,0x0f2,0x0f3,
112 0x0f3,0x0f4,0x0f4,0x0f5,0x0f5,0x0f6,0x0f7,0x0f7,
113 0x0f8,0x0f8,0x0f9,0x0f9,0x0fa,0x0fb,0x0fb,0x0fc,
114 0x0fc,0x0fd,0x0fd,0x0fe,0x0ff,0x0ff,0x100,0x100,
115 0x101,0x101,0x102,0x103,0x103,0x104,0x104,0x105,
116 0x106,0x106,0x107,0x107,0x108,0x108,0x109,0x10a,
117 0x10a,0x10b,0x10b,0x10c,0x10c,0x10d,0x10e,0x10e,
118 0x10f,0x10f,0x110,0x111,0x111,0x112,0x112,0x113,
119 0x114,0x114,0x115,0x115,0x116,0x116,0x117,0x118,
120 0x118,0x119,0x119,0x11a,0x11b,0x11b,0x11c,0x11c,
121 0x11d,0x11e,0x11e,0x11f,0x11f,0x120,0x120,0x121,
122 0x122,0x122,0x123,0x123,0x124,0x125,0x125,0x126,
123 0x126,0x127,0x128,0x128,0x129,0x129,0x12a,0x12b,
124 0x12b,0x12c,0x12c,0x12d,0x12e,0x12e,0x12f,0x12f,
125 0x130,0x131,0x131,0x132,0x132,0x133,0x134,0x134,
126 0x135,0x135,0x136,0x137,0x137,0x138,0x138,0x139,
127 0x13a,0x13a,0x13b,0x13b,0x13c,0x13d,0x13d,0x13e,
128 0x13e,0x13f,0x140,0x140,0x141,0x141,0x142,0x143,
129 0x143,0x144,0x144,0x145,0x146,0x146,0x147,0x148,
130 0x148,0x149,0x149,0x14a,0x14b,0x14b,0x14c,0x14c,
131 0x14d,0x14e,0x14e,0x14f,0x14f,0x150,0x151,0x151,
132 0x152,0x153,0x153,0x154,0x154,0x155,0x156,0x156,
133 0x157,0x157,0x158,0x159,0x159,0x15a,0x15b,0x15b,
134 0x15c,0x15c,0x15d,0x15e,0x15e,0x15f,0x160,0x160,
135 0x161,0x161,0x162,0x163,0x163,0x164,0x165,0x165,
136 0x166,0x166,0x167,0x168,0x168,0x169,0x16a,0x16a,
137 0x16b,0x16b,0x16c,0x16d,0x16d,0x16e,0x16f,0x16f,
138 0x170,0x170,0x171,0x172,0x172,0x173,0x174,0x174,
139 0x175,0x175,0x176,0x177,0x177,0x178,0x179,0x179,
140 0x17a,0x17a,0x17b,0x17c,0x17c,0x17d,0x17e,0x17e,
141 0x17f,0x180,0x180,0x181,0x181,0x182,0x183,0x183,
142 0x184,0x185,0x185,0x186,0x187,0x187,0x188,0x188,
143 0x189,0x18a,0x18a,0x18b,0x18c,0x18c,0x18d,0x18e,
144 0x18e,0x18f,0x190,0x190,0x191,0x191,0x192,0x193,
145 0x193,0x194,0x195,0x195,0x196,0x197,0x197,0x198,
146 0x199,0x199,0x19a,0x19a,0x19b,0x19c,0x19c,0x19d,
147 0x19e,0x19e,0x19f,0x1a0,0x1a0,0x1a1,0x1a2,0x1a2,
148 0x1a3,0x1a4,0x1a4,0x1a5,0x1a6,0x1a6,0x1a7,0x1a8,
149 0x1a8,0x1a9,0x1a9,0x1aa,0x1ab,0x1ab,0x1ac,0x1ad,
150 0x1ad,0x1ae,0x1af,0x1af,0x1b0,0x1b1,0x1b1,0x1b2,
151 0x1b3,0x1b3,0x1b4,0x1b5,0x1b5,0x1b6,0x1b7,0x1b7,
152 0x1b8,0x1b9,0x1b9,0x1ba,0x1bb,0x1bb,0x1bc,0x1bd,
153 0x1bd,0x1be,0x1bf,0x1bf,0x1c0,0x1c1,0x1c1,0x1c2,
154 0x1c3,0x1c3,0x1c4,0x1c5,0x1c5,0x1c6,0x1c7,0x1c7,
155 0x1c8,0x1c9,0x1c9,0x1ca,0x1cb,0x1cb,0x1cc,0x1cd,
156 0x1cd,0x1ce,0x1cf,0x1cf,0x1d0,0x1d1,0x1d1,0x1d2,
157 0x1d3,0x1d3,0x1d4,0x1d5,0x1d5,0x1d6,0x1d7,0x1d7,
158 0x1d8,0x1d9,0x1d9,0x1da,0x1db,0x1db,0x1dc,0x1dd,
159 0x1dd,0x1de,0x1df,0x1df,0x1e0,0x1e1,0x1e1,0x1e2,
160 0x1e3,0x1e4,0x1e4,0x1e5,0x1e6,0x1e6,0x1e7,0x1e8,
161 0x1e8,0x1e9,0x1ea,0x1ea,0x1eb,0x1ec,0x1ec,0x1ed,
162 0x1ee,0x1ee,0x1ef,0x1f0,0x1f0,0x1f1,0x1f2,0x1f3,
163 0x1f3,0x1f4,0x1f5,0x1f5,0x1f6,0x1f7,0x1f7,0x1f8,
164 0x1f9,0x1f9,0x1fa,0x1fb,0x1fb,0x1fc,0x1fd,0x1fe,
165 0x1fe,0x1ff,0x200,0x200,0x201,0x202,0x202,0x203,
166 0x204,0x205,0x205,0x206,0x207,0x207,0x208,0x209,
167 0x209,0x20a,0x20b,0x20b,0x20c,0x20d,0x20e,0x20e,
168 0x20f,0x210,0x210,0x211,0x212,0x212,0x213,0x214,
169 0x215,0x215,0x216,0x217,0x217,0x218,0x219,0x21a,
170 0x21a,0x21b,0x21c,0x21c,0x21d,0x21e,0x21e,0x21f,
171 0x220,0x221,0x221,0x222,0x223,0x223,0x224,0x225,
172 0x226,0x226,0x227,0x228,0x228,0x229,0x22a,0x22b,
173 0x22b,0x22c,0x22d,0x22d,0x22e,0x22f,0x230,0x230,
174 0x231,0x232,0x232,0x233,0x234,0x235,0x235,0x236,
175 0x237,0x237,0x238,0x239,0x23a,0x23a,0x23b,0x23c,
176 0x23c,0x23d,0x23e,0x23f,0x23f,0x240,0x241,0x241,
177 0x242,0x243,0x244,0x244,0x245,0x246,0x247,0x247,
178 0x248,0x249,0x249,0x24a,0x24b,0x24c,0x24c,0x24d,
179 0x24e,0x24f,0x24f,0x250,0x251,0x251,0x252,0x253,
180 0x254,0x254,0x255,0x256,0x257,0x257,0x258,0x259,
181 0x259,0x25a,0x25b,0x25c,0x25c,0x25d,0x25e,0x25f,
182 0x25f,0x260,0x261,0x262,0x262,0x263,0x264,0x265,
183 0x265,0x266,0x267,0x267,0x268,0x269,0x26a,0x26a,
184 0x26b,0x26c,0x26d,0x26d,0x26e,0x26f,0x270,0x270,
185 0x271,0x272,0x273,0x273,0x274,0x275,0x276,0x276,
186 0x277,0x278,0x279,0x279,0x27a,0x27b,0x27c,0x27c,
187 0x27d,0x27e,0x27f,0x27f,0x280,0x281,0x282,0x282,
188 0x283,0x284,0x285,0x285,0x286,0x287,0x288,0x288,
189 0x289,0x28a,0x28b,0x28b,0x28c,0x28d,0x28e,0x28e,
190 0x28f,0x290,0x291,0x291,0x292,0x293,0x294,0x294,
191 0x295,0x296,0x297,0x298,0x298,0x299,0x29a,0x29b,
192 0x29b,0x29c,0x29d,0x29e,0x29e,0x29f,0x2a0,0x2a1,
193 0x2a1,0x2a2,0x2a3,0x2a4,0x2a5,0x2a5,0x2a6,0x2a7,
194 0x2a8,0x2a8,0x2a9,0x2aa,0x2ab,0x2ab,0x2ac,0x2ad,
195 0x2ae,0x2af,0x2af,0x2b0,0x2b1,0x2b2,0x2b2,0x2b3,
196 0x2b4,0x2b5,0x2b5,0x2b6,0x2b7,0x2b8,0x2b9,0x2b9,
197 0x2ba,0x2bb,0x2bc,0x2bc,0x2bd,0x2be,0x2bf,0x2c0,
198 0x2c0,0x2c1,0x2c2,0x2c3,0x2c4,0x2c4,0x2c5,0x2c6,
199 0x2c7,0x2c7,0x2c8,0x2c9,0x2ca,0x2cb,0x2cb,0x2cc,
200 0x2cd,0x2ce,0x2ce,0x2cf,0x2d0,0x2d1,0x2d2,0x2d2,
201 0x2d3,0x2d4,0x2d5,0x2d6,0x2d6,0x2d7,0x2d8,0x2d9,
202 0x2da,0x2da,0x2db,0x2dc,0x2dd,0x2dd,0x2de,0x2df,
203 0x2e0,0x2e1,0x2e1,0x2e2,0x2e3,0x2e4,0x2e5,0x2e5,
204 0x2e6,0x2e7,0x2e8,0x2e9,0x2e9,0x2ea,0x2eb,0x2ec,
205 0x2ed,0x2ed,0x2ee,0x2ef,0x2f0,0x2f1,0x2f1,0x2f2,
206 0x2f3,0x2f4,0x2f5,0x2f5,0x2f6,0x2f7,0x2f8,0x2f9,
207 0x2f9,0x2fa,0x2fb,0x2fc,0x2fd,0x2fd,0x2fe,0x2ff,
208 0x300,0x301,0x302,0x302,0x303,0x304,0x305,0x306,
209 0x306,0x307,0x308,0x309,0x30a,0x30a,0x30b,0x30c,
210 0x30d,0x30e,0x30f,0x30f,0x310,0x311,0x312,0x313,
211 0x313,0x314,0x315,0x316,0x317,0x318,0x318,0x319,
212 0x31a,0x31b,0x31c,0x31c,0x31d,0x31e,0x31f,0x320,
213 0x321,0x321,0x322,0x323,0x324,0x325,0x326,0x326,
214 0x327,0x328,0x329,0x32a,0x32a,0x32b,0x32c,0x32d,
215 0x32e,0x32f,0x32f,0x330,0x331,0x332,0x333,0x334,
216 0x334,0x335,0x336,0x337,0x338,0x339,0x339,0x33a,
217 0x33b,0x33c,0x33d,0x33e,0x33e,0x33f,0x340,0x341,
218 0x342,0x343,0x343,0x344,0x345,0x346,0x347,0x348,
219 0x349,0x349,0x34a,0x34b,0x34c,0x34d,0x34e,0x34e,
220 0x34f,0x350,0x351,0x352,0x353,0x353,0x354,0x355,
221 0x356,0x357,0x358,0x359,0x359,0x35a,0x35b,0x35c,
222 0x35d,0x35e,0x35f,0x35f,0x360,0x361,0x362,0x363,
223 0x364,0x364,0x365,0x366,0x367,0x368,0x369,0x36a,
224 0x36a,0x36b,0x36c,0x36d,0x36e,0x36f,0x370,0x370,
225 0x371,0x372,0x373,0x374,0x375,0x376,0x377,0x377,
226 0x378,0x379,0x37a,0x37b,0x37c,0x37d,0x37d,0x37e,
227 0x37f,0x380,0x381,0x382,0x383,0x383,0x384,0x385,
228 0x386,0x387,0x388,0x389,0x38a,0x38a,0x38b,0x38c,
229 0x38d,0x38e,0x38f,0x390,0x391,0x391,0x392,0x393,
230 0x394,0x395,0x396,0x397,0x398,0x398,0x399,0x39a,
231 0x39b,0x39c,0x39d,0x39e,0x39f,0x39f,0x3a0,0x3a1,
232 0x3a2,0x3a3,0x3a4,0x3a5,0x3a6,0x3a7,0x3a7,0x3a8,
233 0x3a9,0x3aa,0x3ab,0x3ac,0x3ad,0x3ae,0x3ae,0x3af,
234 0x3b0,0x3b1,0x3b2,0x3b3,0x3b4,0x3b5,0x3b6,0x3b6,
235 0x3b7,0x3b8,0x3b9,0x3ba,0x3bb,0x3bc,0x3bd,0x3be,
236 0x3bf,0x3bf,0x3c0,0x3c1,0x3c2,0x3c3,0x3c4,0x3c5,
237 0x3c6,0x3c7,0x3c7,0x3c8,0x3c9,0x3ca,0x3cb,0x3cc,
238 0x3cd,0x3ce,0x3cf,0x3d0,0x3d1,0x3d1,0x3d2,0x3d3,
239 0x3d4,0x3d5,0x3d6,0x3d7,0x3d8,0x3d9,0x3da,0x3da,
240 0x3db,0x3dc,0x3dd,0x3de,0x3df,0x3e0,0x3e1,0x3e2,
241 0x3e3,0x3e4,0x3e4,0x3e5,0x3e6,0x3e7,0x3e8,0x3e9,
242 0x3ea,0x3eb,0x3ec,0x3ed,0x3ee,0x3ef,0x3ef,0x3f0,
243 0x3f1,0x3f2,0x3f3,0x3f4,0x3f5,0x3f6,0x3f7,0x3f8,
244 0x3f9,0x3fa,0x3fa,0x3fb,0x3fc,0x3fd,0x3fe,0x3ff
245};
246
247/*
248 * Attenuation according to GM recommendations, in -0.375 dB units.
249 * table[v] = 40 * log(v / 127) / -0.375
250 */
251static unsigned char snd_opl4_volume_table[128] = {
252 255,224,192,173,160,150,141,134,
253 128,122,117,113,109,105,102, 99,
254 96, 93, 90, 88, 85, 83, 81, 79,
255 77, 75, 73, 71, 70, 68, 67, 65,
256 64, 62, 61, 59, 58, 57, 56, 54,
257 53, 52, 51, 50, 49, 48, 47, 46,
258 45, 44, 43, 42, 41, 40, 39, 39,
259 38, 37, 36, 35, 34, 34, 33, 32,
260 31, 31, 30, 29, 29, 28, 27, 27,
261 26, 25, 25, 24, 24, 23, 22, 22,
262 21, 21, 20, 19, 19, 18, 18, 17,
263 17, 16, 16, 15, 15, 14, 14, 13,
264 13, 12, 12, 11, 11, 10, 10, 9,
265 9, 9, 8, 8, 7, 7, 6, 6,
266 6, 5, 5, 4, 4, 4, 3, 3,
267 2, 2, 2, 1, 1, 0, 0, 0
268};
269
270/*
271 * Initializes all voices.
272 */
273void snd_opl4_synth_reset(opl4_t *opl4)
274{
275 unsigned long flags;
276 int i;
277
278 spin_lock_irqsave(&opl4->reg_lock, flags);
279 for (i = 0; i < OPL4_MAX_VOICES; i++)
280 snd_opl4_write(opl4, OPL4_REG_MISC + i, OPL4_DAMP_BIT);
281 spin_unlock_irqrestore(&opl4->reg_lock, flags);
282
283 INIT_LIST_HEAD(&opl4->off_voices);
284 INIT_LIST_HEAD(&opl4->on_voices);
285 memset(opl4->voices, 0, sizeof(opl4->voices));
286 for (i = 0; i < OPL4_MAX_VOICES; i++) {
287 opl4->voices[i].number = i;
288 list_add_tail(&opl4->voices[i].list, &opl4->off_voices);
289 }
290
291 snd_midi_channel_set_clear(opl4->chset);
292}
293
294/*
295 * Shuts down all voices.
296 */
297void snd_opl4_synth_shutdown(opl4_t *opl4)
298{
299 unsigned long flags;
300 int i;
301
302 spin_lock_irqsave(&opl4->reg_lock, flags);
303 for (i = 0; i < OPL4_MAX_VOICES; i++)
304 snd_opl4_write(opl4, OPL4_REG_MISC + i,
305 opl4->voices[i].reg_misc & ~OPL4_KEY_ON_BIT);
306 spin_unlock_irqrestore(&opl4->reg_lock, flags);
307}
308
309/*
310 * Executes the callback for all voices playing the specified note.
311 */
312static void snd_opl4_do_for_note(opl4_t *opl4, int note, snd_midi_channel_t *chan,
313 void (*func)(opl4_t *opl4, opl4_voice_t *voice))
314{
315 int i;
316 unsigned long flags;
317 opl4_voice_t *voice;
318
319 spin_lock_irqsave(&opl4->reg_lock, flags);
320 for (i = 0; i < OPL4_MAX_VOICES; i++) {
321 voice = &opl4->voices[i];
322 if (voice->chan == chan && voice->note == note) {
323 func(opl4, voice);
324 }
325 }
326 spin_unlock_irqrestore(&opl4->reg_lock, flags);
327}
328
329/*
330 * Executes the callback for all voices of to the specified channel.
331 */
332static void snd_opl4_do_for_channel(opl4_t *opl4, snd_midi_channel_t *chan,
333 void (*func)(opl4_t *opl4, opl4_voice_t *voice))
334{
335 int i;
336 unsigned long flags;
337 opl4_voice_t *voice;
338
339 spin_lock_irqsave(&opl4->reg_lock, flags);
340 for (i = 0; i < OPL4_MAX_VOICES; i++) {
341 voice = &opl4->voices[i];
342 if (voice->chan == chan) {
343 func(opl4, voice);
344 }
345 }
346 spin_unlock_irqrestore(&opl4->reg_lock, flags);
347}
348
349/*
350 * Executes the callback for all active voices.
351 */
352static void snd_opl4_do_for_all(opl4_t *opl4,
353 void (*func)(opl4_t *opl4, opl4_voice_t *voice))
354{
355 int i;
356 unsigned long flags;
357 opl4_voice_t *voice;
358
359 spin_lock_irqsave(&opl4->reg_lock, flags);
360 for (i = 0; i < OPL4_MAX_VOICES; i++) {
361 voice = &opl4->voices[i];
362 if (voice->chan)
363 func(opl4, voice);
364 }
365 spin_unlock_irqrestore(&opl4->reg_lock, flags);
366}
367
368static void snd_opl4_update_volume(opl4_t *opl4, opl4_voice_t *voice)
369{
370 int att;
371
372 att = voice->sound->tone_attenuate;
373 att += snd_opl4_volume_table[opl4->chset->gs_master_volume & 0x7f];
374 att += snd_opl4_volume_table[voice->chan->gm_volume & 0x7f];
375 att += snd_opl4_volume_table[voice->chan->gm_expression & 0x7f];
376 att += snd_opl4_volume_table[voice->velocity];
377 att = 0x7f - (0x7f - att) * (voice->sound->volume_factor) / 0xfe - volume_boost;
378 if (att < 0)
379 att = 0;
380 else if (att > 0x7e)
381 att = 0x7e;
382 snd_opl4_write(opl4, OPL4_REG_LEVEL + voice->number,
383 (att << 1) | voice->level_direct);
384 voice->level_direct = 0;
385}
386
387static void snd_opl4_update_pan(opl4_t *opl4, opl4_voice_t *voice)
388{
389 int pan = voice->sound->panpot;
390
391 if (!voice->chan->drum_channel)
392 pan += (voice->chan->control[MIDI_CTL_MSB_PAN] - 0x40) >> 3;
393 if (pan < -7)
394 pan = -7;
395 else if (pan > 7)
396 pan = 7;
397 voice->reg_misc = (voice->reg_misc & ~OPL4_PAN_POT_MASK)
398 | (pan & OPL4_PAN_POT_MASK);
399 snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc);
400}
401
402static void snd_opl4_update_vibrato_depth(opl4_t *opl4, opl4_voice_t *voice)
403{
404 int depth;
405
406 if (voice->chan->drum_channel)
407 return;
408 depth = (7 - voice->sound->vibrato)
409 * (voice->chan->control[MIDI_CTL_VIBRATO_DEPTH] & 0x7f);
410 depth = (depth >> 7) + voice->sound->vibrato;
411 voice->reg_lfo_vibrato &= ~OPL4_VIBRATO_DEPTH_MASK;
412 voice->reg_lfo_vibrato |= depth & OPL4_VIBRATO_DEPTH_MASK;
413 snd_opl4_write(opl4, OPL4_REG_LFO_VIBRATO + voice->number,
414 voice->reg_lfo_vibrato);
415}
416
417static void snd_opl4_update_pitch(opl4_t *opl4, opl4_voice_t *voice)
418{
419 snd_midi_channel_t *chan = voice->chan;
420 int note, pitch, octave;
421
422 note = chan->drum_channel ? 60 : voice->note;
423 /*
424 * pitch is in 100/128 cents, so 0x80 is one semitone and
425 * 0x600 is one octave.
426 */
427 pitch = ((note - 60) << 7) * voice->sound->key_scaling / 100 + (60 << 7);
428 pitch += voice->sound->pitch_offset;
429 if (!chan->drum_channel)
430 pitch += chan->gm_rpn_coarse_tuning;
431 pitch += chan->gm_rpn_fine_tuning >> 7;
432 pitch += chan->midi_pitchbend * chan->gm_rpn_pitch_bend_range / 0x2000;
433 if (pitch < 0)
434 pitch = 0;
435 else if (pitch >= 0x6000)
436 pitch = 0x5fff;
437 octave = pitch / 0x600 - 8;
438 pitch = snd_opl4_pitch_map[pitch % 0x600];
439
440 snd_opl4_write(opl4, OPL4_REG_OCTAVE + voice->number,
441 (octave << 4) | ((pitch >> 7) & OPL4_F_NUMBER_HIGH_MASK));
442 voice->reg_f_number = (voice->reg_f_number & OPL4_TONE_NUMBER_BIT8)
443 | ((pitch << 1) & OPL4_F_NUMBER_LOW_MASK);
444 snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice->number, voice->reg_f_number);
445}
446
447static void snd_opl4_update_tone_parameters(opl4_t *opl4, opl4_voice_t *voice)
448{
449 snd_opl4_write(opl4, OPL4_REG_ATTACK_DECAY1 + voice->number,
450 voice->sound->reg_attack_decay1);
451 snd_opl4_write(opl4, OPL4_REG_LEVEL_DECAY2 + voice->number,
452 voice->sound->reg_level_decay2);
453 snd_opl4_write(opl4, OPL4_REG_RELEASE_CORRECTION + voice->number,
454 voice->sound->reg_release_correction);
455 snd_opl4_write(opl4, OPL4_REG_TREMOLO + voice->number,
456 voice->sound->reg_tremolo);
457}
458
459/* allocate one voice */
460static opl4_voice_t *snd_opl4_get_voice(opl4_t *opl4)
461{
462 /* first, try to get the oldest key-off voice */
463 if (!list_empty(&opl4->off_voices))
464 return list_entry(opl4->off_voices.next, opl4_voice_t, list);
465 /* then get the oldest key-on voice */
466 snd_assert(!list_empty(&opl4->on_voices), );
467 return list_entry(opl4->on_voices.next, opl4_voice_t, list);
468}
469
470static void snd_opl4_wait_for_wave_headers(opl4_t *opl4)
471{
472 int timeout = 200;
473
474 while ((inb(opl4->fm_port) & OPL4_STATUS_LOAD) && --timeout > 0)
475 udelay(10);
476}
477
478void snd_opl4_note_on(void *private_data, int note, int vel, snd_midi_channel_t *chan)
479{
480 opl4_t *opl4 = private_data;
481 const opl4_region_ptr_t *regions;
482 opl4_voice_t *voice[2];
483 const opl4_sound_t *sound[2];
484 int voices = 0, i;
485 unsigned long flags;
486
487 /* determine the number of voices and voice parameters */
488 i = chan->drum_channel ? 0x80 : (chan->midi_program & 0x7f);
489 regions = &snd_yrw801_regions[i];
490 for (i = 0; i < regions->count; i++) {
491 if (note >= regions->regions[i].key_min &&
492 note <= regions->regions[i].key_max) {
493 sound[voices] = &regions->regions[i].sound;
494 if (++voices >= 2)
495 break;
496 }
497 }
498
499 /* allocate and initialize the needed voices */
500 spin_lock_irqsave(&opl4->reg_lock, flags);
501 for (i = 0; i < voices; i++) {
502 voice[i] = snd_opl4_get_voice(opl4);
503 list_del(&voice[i]->list);
504 list_add_tail(&voice[i]->list, &opl4->on_voices);
505 voice[i]->chan = chan;
506 voice[i]->note = note;
507 voice[i]->velocity = vel & 0x7f;
508 voice[i]->sound = sound[i];
509 }
510
511 /* set tone number (triggers header loading) */
512 for (i = 0; i < voices; i++) {
513 voice[i]->reg_f_number =
514 (sound[i]->tone >> 8) & OPL4_TONE_NUMBER_BIT8;
515 snd_opl4_write(opl4, OPL4_REG_F_NUMBER + voice[i]->number,
516 voice[i]->reg_f_number);
517 snd_opl4_write(opl4, OPL4_REG_TONE_NUMBER + voice[i]->number,
518 sound[i]->tone & 0xff);
519 }
520
521 /* set parameters which can be set while loading */
522 for (i = 0; i < voices; i++) {
523 voice[i]->reg_misc = OPL4_LFO_RESET_BIT;
524 snd_opl4_update_pan(opl4, voice[i]);
525 snd_opl4_update_pitch(opl4, voice[i]);
526 voice[i]->level_direct = OPL4_LEVEL_DIRECT_BIT;
527 snd_opl4_update_volume(opl4, voice[i]);
528 }
529 spin_unlock_irqrestore(&opl4->reg_lock, flags);
530
531 /* wait for completion of loading */
532 snd_opl4_wait_for_wave_headers(opl4);
533
534 /* set remaining parameters */
535 spin_lock_irqsave(&opl4->reg_lock, flags);
536 for (i = 0; i < voices; i++) {
537 snd_opl4_update_tone_parameters(opl4, voice[i]);
538 voice[i]->reg_lfo_vibrato = voice[i]->sound->reg_lfo_vibrato;
539 snd_opl4_update_vibrato_depth(opl4, voice[i]);
540 }
541
542 /* finally, switch on all voices */
543 for (i = 0; i < voices; i++) {
544 voice[i]->reg_misc =
545 (voice[i]->reg_misc & 0x1f) | OPL4_KEY_ON_BIT;
546 snd_opl4_write(opl4, OPL4_REG_MISC + voice[i]->number,
547 voice[i]->reg_misc);
548 }
549 spin_unlock_irqrestore(&opl4->reg_lock, flags);
550}
551
552static void snd_opl4_voice_off(opl4_t *opl4, opl4_voice_t *voice)
553{
554 list_del(&voice->list);
555 list_add_tail(&voice->list, &opl4->off_voices);
556
557 voice->reg_misc &= ~OPL4_KEY_ON_BIT;
558 snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc);
559}
560
561void snd_opl4_note_off(void *private_data, int note, int vel, snd_midi_channel_t *chan)
562{
563 opl4_t *opl4 = private_data;
564
565 snd_opl4_do_for_note(opl4, note, chan, snd_opl4_voice_off);
566}
567
568static void snd_opl4_terminate_voice(opl4_t *opl4, opl4_voice_t *voice)
569{
570 list_del(&voice->list);
571 list_add_tail(&voice->list, &opl4->off_voices);
572
573 voice->reg_misc = (voice->reg_misc & ~OPL4_KEY_ON_BIT) | OPL4_DAMP_BIT;
574 snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc);
575}
576
577void snd_opl4_terminate_note(void *private_data, int note, snd_midi_channel_t *chan)
578{
579 opl4_t *opl4 = private_data;
580
581 snd_opl4_do_for_note(opl4, note, chan, snd_opl4_terminate_voice);
582}
583
584void snd_opl4_control(void *private_data, int type, snd_midi_channel_t *chan)
585{
586 opl4_t *opl4 = private_data;
587
588 switch (type) {
589 case MIDI_CTL_MSB_MODWHEEL:
590 chan->control[MIDI_CTL_VIBRATO_DEPTH] = chan->control[MIDI_CTL_MSB_MODWHEEL];
591 snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth);
592 break;
593 case MIDI_CTL_MSB_MAIN_VOLUME:
594 snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume);
595 break;
596 case MIDI_CTL_MSB_PAN:
597 snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_pan);
598 break;
599 case MIDI_CTL_MSB_EXPRESSION:
600 snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_volume);
601 break;
602 case MIDI_CTL_VIBRATO_RATE:
603 /* not yet supported */
604 break;
605 case MIDI_CTL_VIBRATO_DEPTH:
606 snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_vibrato_depth);
607 break;
608 case MIDI_CTL_VIBRATO_DELAY:
609 /* not yet supported */
610 break;
611 case MIDI_CTL_E1_REVERB_DEPTH:
612 /*
613 * Each OPL4 voice has a bit called "Pseudo-Reverb", but
614 * IMHO _not_ using it enhances the listening experience.
615 */
616 break;
617 case MIDI_CTL_PITCHBEND:
618 snd_opl4_do_for_channel(opl4, chan, snd_opl4_update_pitch);
619 break;
620 }
621}
622
623void snd_opl4_sysex(void *private_data, unsigned char *buf, int len,
624 int parsed, snd_midi_channel_set_t *chset)
625{
626 opl4_t *opl4 = private_data;
627
628 if (parsed == SNDRV_MIDI_SYSEX_GS_MASTER_VOLUME)
629 snd_opl4_do_for_all(opl4, snd_opl4_update_volume);
630}
diff --git a/sound/drivers/opl4/yrw801.c b/sound/drivers/opl4/yrw801.c
new file mode 100644
index 000000000000..a51174dd3e56
--- /dev/null
+++ b/sound/drivers/opl4/yrw801.c
@@ -0,0 +1,961 @@
1/*
2 * Information about the Yamaha YRW801 wavetable ROM chip
3 *
4 * Copyright (c) 2003 by Clemens Ladisch <clemens@ladisch.de>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions, and the following disclaimer,
12 * without modification.
13 * 2. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * Alternatively, this software may be distributed and/or modified under the
17 * terms of the GNU General Public License as published by the Free Software
18 * Foundation; either version 2 of the License, or (at your option) any later
19 * version.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
25 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include "opl4_local.h"
35
36int snd_yrw801_detect(opl4_t *opl4)
37{
38 char buf[15];
39
40 snd_opl4_read_memory(opl4, buf, 0x001200, 15);
41 if (memcmp(buf, "CopyrightYAMAHA", 15))
42 return -ENODEV;
43 snd_opl4_read_memory(opl4, buf, 0x1ffffe, 2);
44 if (buf[0] != 0x01)
45 return -ENODEV;
46 snd_printdd("YRW801 ROM version %02x.%02x\n", buf[0], buf[1]);
47 return 0;
48}
49
50/*
51 * The instrument definitions are stored statically because, in practice, the
52 * OPL4 is always coupled with a YRW801. Dynamic instrument loading would be
53 * required if downloading sample data to external SRAM was actually supported
54 * by this driver.
55 */
56
57static const opl4_region_t regions_00[] = { /* Acoustic Grand Piano */
58 {0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}},
59 {0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
60 {0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
61 {0x34, 0x39, {0x12f,5290,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
62 {0x3a, 0x3f, {0x130,4260,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}},
63 {0x40, 0x45, {0x131,3625,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}},
64 {0x46, 0x4b, {0x132,3116,100, 0,0,0x04,0xc8,0x20,0xf2,0x14,0x08,0x0}},
65 {0x4c, 0x52, {0x133,2081,100, 0,0,0x03,0xc8,0x20,0xf2,0x14,0x18,0x0}},
66 {0x53, 0x58, {0x134,1444,100, 0,0,0x07,0xc8,0x20,0xf3,0x14,0x18,0x0}},
67 {0x59, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}}
68};
69static const opl4_region_t regions_01[] = { /* Bright Acoustic Piano */
70 {0x14, 0x2d, {0x12c,7474,100, 0,0,0x00,0xc8,0x20,0xf2,0x13,0x08,0x0}},
71 {0x2e, 0x33, {0x12d,6816,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
72 {0x34, 0x39, {0x12e,5899,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
73 {0x3a, 0x3f, {0x12f,5290,100, 0,0,0x00,0xc8,0x20,0xf2,0x14,0x08,0x0}},
74 {0x40, 0x45, {0x130,4260,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}},
75 {0x46, 0x4b, {0x131,3625,100, 0,0,0x0a,0xc8,0x20,0xf2,0x14,0x08,0x0}},
76 {0x4c, 0x52, {0x132,3116,100, 0,0,0x04,0xc8,0x20,0xf2,0x14,0x08,0x0}},
77 {0x53, 0x58, {0x133,2081,100, 0,0,0x07,0xc8,0x20,0xf2,0x14,0x18,0x0}},
78 {0x59, 0x5e, {0x134,1444,100, 0,0,0x0a,0xc8,0x20,0xf3,0x14,0x18,0x0}},
79 {0x5f, 0x6d, {0x135,1915,100, 0,0,0x00,0xc8,0x20,0xf4,0x15,0x08,0x0}}
80};
81static const opl4_region_t regions_02[] = { /* Electric Grand Piano */
82 {0x14, 0x2d, {0x12c,7476,100, 1,0,0x00,0xae,0x20,0xf2,0x13,0x07,0x0}},
83 {0x2e, 0x33, {0x12d,6818,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}},
84 {0x34, 0x39, {0x12e,5901,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}},
85 {0x3a, 0x3f, {0x12f,5292,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}},
86 {0x40, 0x45, {0x130,4262,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}},
87 {0x46, 0x4b, {0x131,3627,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}},
88 {0x4c, 0x52, {0x132,3118,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x07,0x0}},
89 {0x53, 0x58, {0x133,2083,100, 1,0,0x00,0xae,0x20,0xf2,0x14,0x17,0x0}},
90 {0x59, 0x5e, {0x134,1446,100, 1,0,0x00,0xae,0x20,0xf3,0x14,0x17,0x0}},
91 {0x5f, 0x6d, {0x135,1917,100, 1,0,0x00,0xae,0x20,0xf4,0x15,0x07,0x0}},
92 {0x00, 0x7f, {0x06c,6375,100,-1,0,0x00,0xc2,0x28,0xf4,0x23,0x18,0x0}}
93};
94static const opl4_region_t regions_03[] = { /* Honky-Tonk Piano */
95 {0x14, 0x27, {0x12c,7474,100, 0,0,0x00,0xb4,0x20,0xf2,0x13,0x08,0x0}},
96 {0x28, 0x2d, {0x12d,6816,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}},
97 {0x2e, 0x33, {0x12e,5899,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}},
98 {0x34, 0x39, {0x12f,5290,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}},
99 {0x3a, 0x3f, {0x130,4260,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}},
100 {0x40, 0x45, {0x131,3625,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}},
101 {0x46, 0x4b, {0x132,3116,100, 0,0,0x04,0xb4,0x20,0xf2,0x14,0x08,0x0}},
102 {0x4c, 0x52, {0x133,2081,100, 0,0,0x03,0xb4,0x20,0xf2,0x14,0x18,0x0}},
103 {0x53, 0x58, {0x134,1444,100, 0,0,0x07,0xb4,0x20,0xf3,0x14,0x18,0x0}},
104 {0x59, 0x6d, {0x135,1915,100, 0,0,0x00,0xb4,0x20,0xf4,0x15,0x08,0x0}},
105 {0x14, 0x27, {0x12c,7486,100, 0,0,0x00,0xb4,0x20,0xf2,0x13,0x08,0x0}},
106 {0x28, 0x2d, {0x12d,6803,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}},
107 {0x2e, 0x33, {0x12e,5912,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}},
108 {0x34, 0x39, {0x12f,5275,100, 0,0,0x00,0xb4,0x20,0xf2,0x14,0x08,0x0}},
109 {0x3a, 0x3f, {0x130,4274,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}},
110 {0x40, 0x45, {0x131,3611,100, 0,0,0x0a,0xb4,0x20,0xf2,0x14,0x08,0x0}},
111 {0x46, 0x4b, {0x132,3129,100, 0,0,0x04,0xb4,0x20,0xf2,0x14,0x08,0x0}},
112 {0x4c, 0x52, {0x133,2074,100, 0,0,0x07,0xb4,0x20,0xf2,0x14,0x18,0x0}},
113 {0x53, 0x58, {0x134,1457,100, 0,0,0x01,0xb4,0x20,0xf3,0x14,0x18,0x0}},
114 {0x59, 0x6d, {0x135,1903,100, 0,0,0x00,0xb4,0x20,0xf4,0x15,0x08,0x0}}
115};
116static const opl4_region_t regions_04[] = { /* Electric Piano 1 */
117 {0x15, 0x6c, {0x00b,6570,100, 0,0,0x00,0x28,0x38,0xf0,0x00,0x0c,0x0}},
118 {0x00, 0x7f, {0x06c,6375,100, 0,2,0x00,0xb0,0x22,0xf4,0x23,0x19,0x0}}
119};
120static const opl4_region_t regions_05[] = { /* Electric Piano 2 */
121 {0x14, 0x27, {0x12c,7476,100, 0,3,0x00,0xa2,0x1b,0xf2,0x13,0x08,0x0}},
122 {0x28, 0x2d, {0x12d,6818,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}},
123 {0x2e, 0x33, {0x12e,5901,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}},
124 {0x34, 0x39, {0x12f,5292,100, 0,3,0x00,0xa2,0x1b,0xf2,0x14,0x08,0x0}},
125 {0x3a, 0x3f, {0x130,4262,100, 0,3,0x0a,0xa2,0x1b,0xf2,0x14,0x08,0x0}},
126 {0x40, 0x45, {0x131,3627,100, 0,3,0x0a,0xa2,0x1b,0xf2,0x14,0x08,0x0}},
127 {0x46, 0x4b, {0x132,3118,100, 0,3,0x04,0xa2,0x1b,0xf2,0x14,0x08,0x0}},
128 {0x4c, 0x52, {0x133,2083,100, 0,3,0x03,0xa2,0x1b,0xf2,0x14,0x18,0x0}},
129 {0x53, 0x58, {0x134,1446,100, 0,3,0x07,0xa2,0x1b,0xf3,0x14,0x18,0x0}},
130 {0x59, 0x6d, {0x135,1917,100, 0,3,0x00,0xa2,0x1b,0xf4,0x15,0x08,0x0}},
131 {0x14, 0x2d, {0x12c,7472,100, 0,0,0x00,0xa2,0x18,0xf2,0x13,0x08,0x0}},
132 {0x2e, 0x33, {0x12d,6814,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}},
133 {0x34, 0x39, {0x12e,5897,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}},
134 {0x3a, 0x3f, {0x12f,5288,100, 0,0,0x00,0xa2,0x18,0xf2,0x14,0x08,0x0}},
135 {0x40, 0x45, {0x130,4258,100, 0,0,0x0a,0xa2,0x18,0xf2,0x14,0x08,0x0}},
136 {0x46, 0x4b, {0x131,3623,100, 0,0,0x0a,0xa2,0x18,0xf2,0x14,0x08,0x0}},
137 {0x4c, 0x52, {0x132,3114,100, 0,0,0x04,0xa2,0x18,0xf2,0x14,0x08,0x0}},
138 {0x53, 0x58, {0x133,2079,100, 0,0,0x07,0xa2,0x18,0xf2,0x14,0x18,0x0}},
139 {0x59, 0x5e, {0x134,1442,100, 0,0,0x0a,0xa2,0x18,0xf3,0x14,0x18,0x0}},
140 {0x5f, 0x6d, {0x135,1913,100, 0,0,0x00,0xa2,0x18,0xf4,0x15,0x08,0x0}}
141};
142static const opl4_region_t regions_06[] = { /* Harpsichord */
143 {0x15, 0x39, {0x080,5158,100, 0,0,0x00,0xb2,0x20,0xf5,0x24,0x19,0x0}},
144 {0x3a, 0x3f, {0x081,4408,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}},
145 {0x40, 0x45, {0x082,3622,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x09,0x0}},
146 {0x46, 0x4d, {0x083,2843,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x19,0x0}},
147 {0x4e, 0x6c, {0x084,1307,100, 0,0,0x00,0xb2,0x20,0xf5,0x25,0x29,0x0}}
148};
149static const opl4_region_t regions_07[] = { /* Clavinet */
150 {0x15, 0x51, {0x027,5009,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x2b,0x0}},
151 {0x52, 0x6c, {0x028,3495,100, 0,0,0x00,0xd2,0x28,0xf5,0x13,0x3b,0x0}}
152};
153static const opl4_region_t regions_08[] = { /* Celesta */
154 {0x15, 0x6c, {0x02b,3267,100, 0,0,0x00,0xdc,0x20,0xf4,0x15,0x07,0x3}}
155};
156static const opl4_region_t regions_09[] = { /* Glockenspiel */
157 {0x15, 0x78, {0x0f3, 285,100, 0,0,0x00,0xc2,0x28,0xf6,0x25,0x25,0x0}}
158};
159static const opl4_region_t regions_0a[] = { /* Music Box */
160 {0x15, 0x6c, {0x0f3,3362,100, 0,0,0x00,0xb6,0x20,0xa6,0x25,0x25,0x0}},
161 {0x15, 0x6c, {0x101,4773,100, 0,0,0x00,0xaa,0x20,0xd4,0x14,0x16,0x0}}
162};
163static const opl4_region_t regions_0b[] = { /* Vibraphone */
164 {0x15, 0x6c, {0x101,4778,100, 0,0,0x00,0xc0,0x28,0xf4,0x14,0x16,0x4}}
165};
166static const opl4_region_t regions_0c[] = { /* Marimba */
167 {0x15, 0x3f, {0x0f4,4778,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}},
168 {0x40, 0x4c, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x47,0x08,0x0}},
169 {0x4d, 0x5a, {0x0f5,3217,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x08,0x0}},
170 {0x5b, 0x7f, {0x0f5,3218,100, 0,0,0x00,0xc4,0x38,0xf7,0x48,0x18,0x0}}
171};
172static const opl4_region_t regions_0d[] = { /* Xylophone */
173 {0x00, 0x7f, {0x136,1729,100, 0,0,0x00,0xd2,0x38,0xf0,0x06,0x36,0x0}}
174};
175static const opl4_region_t regions_0e[] = { /* Tubular Bell */
176 {0x01, 0x7f, {0x0ff,3999,100, 0,1,0x00,0x90,0x21,0xf4,0xa3,0x25,0x1}}
177};
178static const opl4_region_t regions_0f[] = { /* Dulcimer */
179 {0x00, 0x7f, {0x03f,4236,100, 0,1,0x00,0xbc,0x29,0xf5,0x16,0x07,0x0}},
180 {0x00, 0x7f, {0x040,4236,100, 0,2,0x0e,0x94,0x2a,0xf5,0x16,0x07,0x0}}
181};
182static const opl4_region_t regions_10[] = { /* Drawbar Organ */
183 {0x01, 0x7f, {0x08e,4394,100, 0,2,0x14,0xc2,0x3a,0xf0,0x00,0x0a,0x0}}
184};
185static const opl4_region_t regions_11[] = { /* Percussive Organ */
186 {0x15, 0x3b, {0x08c,6062,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}},
187 {0x3c, 0x6c, {0x08d,2984,100, 0,3,0x00,0xbe,0x3b,0xf0,0x00,0x09,0x0}}
188};
189static const opl4_region_t regions_12[] = { /* Rock Organ */
190 {0x15, 0x30, {0x128,6574,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}},
191 {0x31, 0x3c, {0x129,5040,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}},
192 {0x3d, 0x48, {0x12a,3498,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}},
193 {0x49, 0x54, {0x12b,1957,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}},
194 {0x55, 0x6c, {0x127, 423,100, 0,1,0x00,0xcc,0x39,0xf0,0x00,0x0a,0x0}}
195};
196static const opl4_region_t regions_13[] = { /* Church Organ */
197 {0x15, 0x29, {0x087,7466,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}},
198 {0x2a, 0x30, {0x088,6456,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}},
199 {0x31, 0x38, {0x089,5428,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}},
200 {0x39, 0x41, {0x08a,4408,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}},
201 {0x42, 0x6c, {0x08b,3406,100, 0,1,0x00,0xc4,0x11,0xf0,0x00,0x09,0x0}}
202};
203static const opl4_region_t regions_14[] = { /* Reed Organ */
204 {0x00, 0x53, {0x0ac,5570,100, 0,0,0x06,0xc0,0x38,0xf0,0x00,0x09,0x1}},
205 {0x54, 0x7f, {0x0ad,2497,100, 0,0,0x00,0xc0,0x38,0xf0,0x00,0x09,0x1}}
206};
207static const opl4_region_t regions_15[] = { /* Accordion */
208 {0x15, 0x4c, {0x006,4261,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}},
209 {0x4d, 0x6c, {0x007,1530,100, 0,2,0x00,0xa4,0x22,0x90,0x00,0x09,0x0}},
210 {0x15, 0x6c, {0x070,4391,100, 0,3,0x00,0x8a,0x23,0xa0,0x00,0x09,0x0}}
211};
212static const opl4_region_t regions_16[] = { /* Harmonica */
213 {0x15, 0x6c, {0x070,4408,100, 0,0,0x00,0xae,0x30,0xa0,0x00,0x09,0x2}}
214};
215static const opl4_region_t regions_17[] = { /* Tango Accordion */
216 {0x00, 0x53, {0x0ac,5573,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}},
217 {0x54, 0x7f, {0x0ad,2500,100, 0,0,0x00,0xae,0x38,0xf0,0x00,0x09,0x0}},
218 {0x15, 0x6c, {0x041,8479,100, 0,2,0x00,0x6a,0x3a,0x75,0x20,0x0a,0x0}}
219};
220static const opl4_region_t regions_18[] = { /* Nylon Guitar */
221 {0x15, 0x2f, {0x0b3,6964,100, 0,0,0x05,0xca,0x28,0xf5,0x34,0x09,0x0}},
222 {0x30, 0x36, {0x0b7,5567,100, 0,0,0x0c,0xca,0x28,0xf5,0x34,0x09,0x0}},
223 {0x37, 0x3c, {0x0b5,4653,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}},
224 {0x3d, 0x43, {0x0b4,3892,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x09,0x0}},
225 {0x44, 0x60, {0x0b6,2723,100, 0,0,0x00,0xca,0x28,0xf6,0x35,0x19,0x0}}
226};
227static const opl4_region_t regions_19[] = { /* Steel Guitar */
228 {0x15, 0x31, {0x00c,6937,100, 0,0,0x00,0xbc,0x28,0xf0,0x04,0x19,0x0}},
229 {0x32, 0x38, {0x00d,5410,100, 0,0,0x00,0xbc,0x28,0xf0,0x05,0x09,0x0}},
230 {0x39, 0x47, {0x00e,4379,100, 0,0,0x00,0xbc,0x28,0xf5,0x94,0x09,0x0}},
231 {0x48, 0x6c, {0x00f,2843,100, 0,0,0x00,0xbc,0x28,0xf6,0x95,0x09,0x0}}
232};
233static const opl4_region_t regions_1a[] = { /* Jazz Guitar */
234 {0x15, 0x31, {0x05a,6832,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}},
235 {0x32, 0x3f, {0x05b,4897,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}},
236 {0x40, 0x6c, {0x05c,3218,100, 0,0,0x00,0xca,0x28,0xf6,0x34,0x09,0x0}}
237};
238static const opl4_region_t regions_1b[] = { /* Clean Guitar */
239 {0x15, 0x2c, {0x061,7053,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}},
240 {0x2d, 0x31, {0x060,6434,100, 0,1,0x00,0xb4,0x29,0xf5,0x54,0x0a,0x0}},
241 {0x32, 0x38, {0x063,5764,100, 0,1,0x00,0xbe,0x29,0xf5,0x55,0x0a,0x0}},
242 {0x39, 0x3f, {0x062,4627,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x0a,0x0}},
243 {0x40, 0x44, {0x065,3963,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x1a,0x0}},
244 {0x45, 0x4b, {0x064,3313,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x1a,0x0}},
245 {0x4c, 0x54, {0x066,2462,100, 0,1,0x00,0xb4,0x29,0xf5,0x55,0x2a,0x0}},
246 {0x55, 0x6c, {0x067,1307,100, 0,1,0x00,0xb4,0x29,0xf6,0x56,0x0a,0x0}}
247};
248static const opl4_region_t regions_1c[] = { /* Muted Guitar */
249 {0x01, 0x7f, {0x068,4408,100, 0,0,0x00,0xcc,0x28,0xf6,0x15,0x09,0x0}}
250};
251static const opl4_region_t regions_1d[] = { /* Overdriven Guitar */
252 {0x00, 0x40, {0x0a5,6589,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}},
253 {0x41, 0x7f, {0x0a6,5428,100, 0,1,0x00,0xc0,0x29,0xf2,0x11,0x09,0x0}}
254};
255static const opl4_region_t regions_1e[] = { /* Distortion Guitar */
256 {0x15, 0x2a, {0x051,6928,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
257 {0x2b, 0x2e, {0x052,6433,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
258 {0x2f, 0x32, {0x053,5944,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
259 {0x33, 0x36, {0x054,5391,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
260 {0x37, 0x3a, {0x055,4897,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
261 {0x3b, 0x3e, {0x056,4408,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
262 {0x3f, 0x42, {0x057,3892,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
263 {0x43, 0x46, {0x058,3361,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}},
264 {0x47, 0x6c, {0x059,2784,100, 0,1,0x00,0xbc,0x21,0xa2,0x12,0x0a,0x0}}
265};
266static const opl4_region_t regions_1f[] = { /* Guitar Harmonics */
267 {0x15, 0x44, {0x05e,5499,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}},
268 {0x45, 0x49, {0x05d,4850,100, 0,0,0x00,0xe2,0x28,0xf4,0x24,0x09,0x0}},
269 {0x4a, 0x6c, {0x05f,4259,100, 0,0,0x00,0xce,0x28,0xf4,0x24,0x09,0x0}}
270};
271static const opl4_region_t regions_20[] = { /* Acoustic Bass */
272 {0x15, 0x30, {0x004,8053,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}},
273 {0x31, 0x6c, {0x005,4754,100, 0,0,0x00,0xe2,0x18,0xf5,0x15,0x09,0x0}}
274};
275static const opl4_region_t regions_21[] = { /* Fingered Bass */
276 {0x01, 0x20, {0x04a,8762,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}},
277 {0x21, 0x25, {0x04b,8114,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}},
278 {0x26, 0x2a, {0x04c,7475,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}},
279 {0x2b, 0x7f, {0x04d,6841,100, 0,0,0x00,0xde,0x18,0xf6,0x14,0x09,0x0}}
280};
281static const opl4_region_t regions_22[] = { /* Picked Bass */
282 {0x15, 0x23, {0x04f,7954,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x0a,0x0}},
283 {0x24, 0x2a, {0x050,7318,100, 0,0,0x05,0xcc,0x18,0xf3,0x90,0x1a,0x0}},
284 {0x2b, 0x2f, {0x06b,6654,100, 0,0,0x00,0xcc,0x18,0xf3,0x90,0x2a,0x0}},
285 {0x30, 0x47, {0x069,6031,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}},
286 {0x48, 0x6c, {0x06a,5393,100, 0,0,0x00,0xcc,0x18,0xf5,0xb0,0x0a,0x0}}
287};
288static const opl4_region_t regions_23[] = { /* Fretless Bass */
289 {0x01, 0x7f, {0x04e,5297,100, 0,0,0x00,0xd2,0x10,0xf3,0x63,0x19,0x0}}
290};
291static const opl4_region_t regions_24[] = { /* Slap Bass 1 */
292 {0x15, 0x6c, {0x0a3,7606,100, 0,1,0x00,0xde,0x19,0xf5,0x32,0x1a,0x0}}
293};
294static const opl4_region_t regions_25[] = { /* Slap Bass 2 */
295 {0x01, 0x7f, {0x0a2,6694,100, 0,0,0x00,0xda,0x20,0xb0,0x02,0x09,0x0}}
296};
297static const opl4_region_t regions_26[] = { /* Synth Bass 1 */
298 {0x15, 0x6c, {0x0be,7466,100, 0,1,0x00,0xb8,0x39,0xf4,0x14,0x09,0x0}}
299};
300static const opl4_region_t regions_27[] = { /* Synth Bass 2 */
301 {0x00, 0x7f, {0x117,8103,100, 0,1,0x00,0xca,0x39,0xf3,0x50,0x08,0x0}}
302};
303static const opl4_region_t regions_28[] = { /* Violin */
304 {0x15, 0x3a, {0x105,5158,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
305 {0x3b, 0x3f, {0x102,4754,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
306 {0x40, 0x41, {0x106,4132,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
307 {0x42, 0x44, {0x107,4033,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
308 {0x45, 0x47, {0x108,3580,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
309 {0x48, 0x4a, {0x10a,2957,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
310 {0x4b, 0x4c, {0x10b,2724,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
311 {0x4d, 0x4e, {0x10c,2530,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
312 {0x4f, 0x51, {0x10d,2166,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}},
313 {0x52, 0x6c, {0x109,1825,100, 0,3,0x00,0xcc,0x3b,0xf3,0x20,0x09,0x0}}
314};
315static const opl4_region_t regions_29[] = { /* Viola */
316 {0x15, 0x32, {0x103,5780,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}},
317 {0x33, 0x35, {0x104,5534,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}},
318 {0x36, 0x38, {0x105,5158,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}},
319 {0x39, 0x3d, {0x102,4754,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}},
320 {0x3e, 0x3f, {0x106,4132,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}},
321 {0x40, 0x42, {0x107,4033,100, 0,3,0x00,0xc4,0x3b,0xa3,0x20,0x09,0x0}},
322 {0x43, 0x45, {0x108,3580,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}},
323 {0x46, 0x48, {0x10a,2957,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}},
324 {0x49, 0x4a, {0x10b,2724,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}},
325 {0x4b, 0x4c, {0x10c,2530,100, 0,3,0x00,0xca,0x3b,0xa3,0x20,0x09,0x0}},
326 {0x4d, 0x4f, {0x10d,2166,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}},
327 {0x50, 0x6c, {0x109,1825,100, 0,3,0x00,0xd0,0x3b,0xa3,0x20,0x09,0x0}}
328};
329static const opl4_region_t regions_2a[] = { /* Cello */
330 {0x15, 0x2d, {0x112,6545,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}},
331 {0x2e, 0x37, {0x113,5764,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x08,0x0}},
332 {0x38, 0x3e, {0x115,4378,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}},
333 {0x3f, 0x44, {0x116,3998,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}},
334 {0x45, 0x6c, {0x114,3218,100, 0,3,0x00,0xc0,0x33,0xa0,0x00,0x18,0x0}}
335};
336static const opl4_region_t regions_2b[] = { /* Contrabass */
337 {0x15, 0x29, {0x110,7713,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}},
338 {0x2a, 0x6c, {0x111,6162,100, 0,1,0x00,0xc2,0x19,0x90,0x00,0x09,0x0}}
339};
340static const opl4_region_t regions_2c[] = { /* Tremolo Strings */
341 {0x15, 0x3b, {0x0b0,4810,100, 0,0,0x0a,0xde,0x38,0xf0,0x00,0x07,0x6}},
342 {0x3c, 0x41, {0x035,4035,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}},
343 {0x42, 0x47, {0x033,3129,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}},
344 {0x48, 0x52, {0x034,2625,100, 0,0,0x05,0xde,0x38,0xf0,0x00,0x07,0x6}},
345 {0x53, 0x6c, {0x0af, 936,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x07,0x6}}
346};
347static const opl4_region_t regions_2d[] = { /* Pizzicato Strings */
348 {0x15, 0x32, {0x0b8,6186,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}},
349 {0x33, 0x3b, {0x0b9,5031,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}},
350 {0x3c, 0x42, {0x0bb,4146,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}},
351 {0x43, 0x48, {0x0ba,3245,100, 0,0,0x00,0xc2,0x28,0xf0,0x00,0x05,0x0}},
352 {0x49, 0x6c, {0x0bc,2352,100, 0,0,0x00,0xbc,0x28,0xf0,0x00,0x05,0x0}}
353};
354static const opl4_region_t regions_2e[] = { /* Harp */
355 {0x15, 0x46, {0x07e,3740,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}},
356 {0x47, 0x6c, {0x07f,2319,100, 0,1,0x00,0xd2,0x29,0xf5,0x25,0x07,0x0}}
357};
358static const opl4_region_t regions_2f[] = { /* Timpani */
359 {0x15, 0x6c, {0x100,6570,100, 0,0,0x00,0xf8,0x28,0xf0,0x05,0x16,0x0}}
360};
361static const opl4_region_t regions_30[] = { /* Strings */
362 {0x15, 0x3b, {0x13c,4806,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}},
363 {0x3c, 0x41, {0x13e,4035,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}},
364 {0x42, 0x47, {0x13d,3122,100, 0,0,0x00,0xc8,0x20,0x80,0x00,0x07,0x0}},
365 {0x48, 0x52, {0x13f,2629,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}},
366 {0x53, 0x6c, {0x140, 950,100, 0,0,0x00,0xbe,0x20,0x80,0x00,0x07,0x0}}
367};
368static const opl4_region_t regions_31[] = { /* Slow Strings */
369 {0x15, 0x3b, {0x0b0,4810,100, 0,1,0x0a,0xbe,0x19,0xf0,0x00,0x07,0x0}},
370 {0x3c, 0x41, {0x035,4035,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}},
371 {0x42, 0x47, {0x033,3129,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}},
372 {0x48, 0x52, {0x034,2625,100, 0,1,0x05,0xbe,0x19,0xf0,0x00,0x07,0x0}},
373 {0x53, 0x6c, {0x0af, 936,100, 0,1,0x00,0xbe,0x19,0xf0,0x00,0x07,0x0}}
374};
375static const opl4_region_t regions_32[] = { /* Synth Strings 1 */
376 {0x05, 0x71, {0x002,6045,100,-2,0,0x00,0xa6,0x20,0x93,0x22,0x06,0x0}},
377 {0x15, 0x6c, {0x0ae,3261,100, 2,0,0x00,0xc6,0x20,0x70,0x01,0x06,0x0}}
378};
379static const opl4_region_t regions_33[] = { /* Synth Strings 2 */
380 {0x15, 0x6c, {0x002,4513,100, 5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}},
381 {0x15, 0x6c, {0x002,4501,100,-5,1,0x00,0xb4,0x19,0x70,0x00,0x06,0x0}}
382};
383static const opl4_region_t regions_34[] = { /* Choir Aahs */
384 {0x15, 0x3a, {0x018,5010,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}},
385 {0x3b, 0x40, {0x019,4370,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}},
386 {0x41, 0x47, {0x01a,3478,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}},
387 {0x48, 0x6c, {0x01b,2197,100, 0,2,0x00,0xc2,0x1a,0x70,0x00,0x08,0x0}}
388};
389static const opl4_region_t regions_35[] = { /* Voice Oohs */
390 {0x15, 0x6c, {0x029,3596,100, 0,0,0x00,0xe6,0x20,0xf7,0x20,0x08,0x0}}
391};
392static const opl4_region_t regions_36[] = { /* Synth Voice */
393 {0x15, 0x6c, {0x02a,3482,100, 0,1,0x00,0xc2,0x19,0x85,0x21,0x07,0x0}}
394};
395static const opl4_region_t regions_37[] = { /* Orchestra Hit */
396 {0x15, 0x6c, {0x049,4394,100, 0,0,0x00,0xfe,0x30,0x80,0x05,0x05,0x0}}
397};
398static const opl4_region_t regions_38[] = { /* Trumpet */
399 {0x15, 0x3c, {0x0f6,4706,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}},
400 {0x3d, 0x43, {0x0f8,3894,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}},
401 {0x44, 0x48, {0x0f7,3118,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}},
402 {0x49, 0x4e, {0x0fa,2322,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}},
403 {0x4f, 0x55, {0x0f9,1634,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}},
404 {0x56, 0x6c, {0x0fb, 786,100, 0,2,0x00,0xd6,0x32,0xf3,0x20,0x0a,0x0}}
405};
406static const opl4_region_t regions_39[] = { /* Trombone */
407 {0x15, 0x3a, {0x0f0,5053,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}},
408 {0x3b, 0x3f, {0x0f1,4290,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}},
409 {0x40, 0x6c, {0x0f2,3580,100, 0,1,0x00,0xd6,0x21,0xf0,0x00,0x09,0x0}}
410};
411static const opl4_region_t regions_3a[] = { /* Tuba */
412 {0x15, 0x2d, {0x085,7096,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}},
413 {0x2e, 0x6c, {0x086,6014,100, 0,1,0x00,0xde,0x21,0xf5,0x10,0x09,0x0}}
414};
415static const opl4_region_t regions_3b[] = { /* Muted Trumpet */
416 {0x15, 0x45, {0x0b1,4135,100, 0,0,0x00,0xcc,0x28,0xf3,0x10,0x0a,0x1}},
417 {0x46, 0x6c, {0x0b2,2599,100, 0,0,0x00,0xcc,0x28,0x83,0x10,0x0a,0x1}}
418};
419static const opl4_region_t regions_3c[] = { /* French Horns */
420 {0x15, 0x49, {0x07c,3624,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}},
421 {0x4a, 0x6c, {0x07d,2664,100, 0,2,0x00,0xd0,0x1a,0xf0,0x00,0x09,0x0}}
422};
423static const opl4_region_t regions_3d[] = { /* Brass Section */
424 {0x15, 0x42, {0x0fc,4375,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}},
425 {0x43, 0x6c, {0x0fd,2854,100, 0,0,0x00,0xd6,0x28,0xf0,0x00,0x0a,0x0}}
426};
427static const opl4_region_t regions_3e[] = { /* Synth Brass 1 */
428 {0x01, 0x27, {0x0d3,9094,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
429 {0x28, 0x2d, {0x0da,8335,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
430 {0x2e, 0x33, {0x0d4,7558,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
431 {0x34, 0x39, {0x0db,6785,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
432 {0x3a, 0x3f, {0x0d5,6042,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
433 {0x40, 0x45, {0x0dc,5257,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
434 {0x46, 0x4b, {0x0d6,4493,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
435 {0x4c, 0x51, {0x0dd,3741,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
436 {0x52, 0x57, {0x0d7,3012,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
437 {0x58, 0x5d, {0x0de,2167,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
438 {0x5e, 0x63, {0x0d8,1421,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
439 {0x64, 0x7f, {0x0d9,-115,100,-1,0,0x00,0xbe,0x18,0xa5,0x11,0x08,0x0}},
440 {0x01, 0x27, {0x118,9103,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
441 {0x28, 0x2d, {0x119,8340,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
442 {0x2e, 0x33, {0x11a,7565,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
443 {0x34, 0x39, {0x11b,6804,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
444 {0x3a, 0x3f, {0x11c,6042,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
445 {0x40, 0x45, {0x11d,5277,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
446 {0x46, 0x4b, {0x11e,4520,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
447 {0x4c, 0x51, {0x11f,3741,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
448 {0x52, 0x57, {0x120,3012,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
449 {0x58, 0x5d, {0x121,2166,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
450 {0x5e, 0x64, {0x122,1421,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}},
451 {0x65, 0x7f, {0x123,-115,100, 1,1,0x00,0xbe,0x19,0x85,0x23,0x08,0x0}}
452};
453static const opl4_region_t regions_3f[] = { /* Synth Brass 2 */
454 {0x01, 0x27, {0x118,9113,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
455 {0x28, 0x2d, {0x119,8350,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
456 {0x2e, 0x33, {0x11a,7575,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
457 {0x34, 0x39, {0x11b,6814,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
458 {0x3a, 0x3f, {0x11c,6052,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
459 {0x40, 0x45, {0x11d,5287,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
460 {0x46, 0x4b, {0x11e,4530,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
461 {0x4c, 0x51, {0x11f,3751,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
462 {0x52, 0x57, {0x120,3022,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
463 {0x58, 0x5d, {0x121,2176,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
464 {0x5e, 0x64, {0x122,1431,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
465 {0x65, 0x7f, {0x123,-105,100, 3,6,0x00,0xae,0x26,0x85,0x23,0x08,0x0}},
466 {0x00, 0x7f, {0x124,4034,100,-3,2,0x00,0xea,0x22,0x85,0x23,0x08,0x0}}
467};
468static const opl4_region_t regions_40[] = { /* Soprano Sax */
469 {0x15, 0x3f, {0x0e3,4228,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}},
470 {0x40, 0x45, {0x0e4,3495,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}},
471 {0x46, 0x4b, {0x0e5,2660,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}},
472 {0x4c, 0x51, {0x0e6,2002,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}},
473 {0x52, 0x59, {0x0e7,1186,100, 0,1,0x00,0xd6,0x21,0xf5,0x20,0x0a,0x0}},
474 {0x59, 0x6c, {0x0e8,1730,100, 0,1,0x00,0xc8,0x21,0xf5,0x20,0x0a,0x0}}
475};
476static const opl4_region_t regions_41[] = { /* Alto Sax */
477 {0x15, 0x32, {0x092,6204,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
478 {0x33, 0x35, {0x096,5812,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
479 {0x36, 0x3a, {0x099,5318,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
480 {0x3b, 0x3b, {0x08f,5076,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
481 {0x3c, 0x3e, {0x093,4706,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
482 {0x3f, 0x41, {0x097,4321,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
483 {0x42, 0x44, {0x09a,3893,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
484 {0x45, 0x47, {0x090,3497,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
485 {0x48, 0x4a, {0x094,3119,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
486 {0x4b, 0x4d, {0x098,2726,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
487 {0x4e, 0x50, {0x09b,2393,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
488 {0x51, 0x53, {0x091,2088,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}},
489 {0x54, 0x6c, {0x095,1732,100, 0,1,0x00,0xbe,0x19,0xf5,0x20,0x0b,0x0}}
490};
491static const opl4_region_t regions_42[] = { /* Tenor Sax */
492 {0x24, 0x30, {0x0e9,6301,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
493 {0x31, 0x34, {0x0ea,5781,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
494 {0x35, 0x3a, {0x0eb,5053,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
495 {0x3b, 0x41, {0x0ed,4165,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
496 {0x42, 0x47, {0x0ec,3218,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
497 {0x48, 0x51, {0x0ee,2462,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}},
498 {0x52, 0x6c, {0x0ef,1421,100, 0,1,0x00,0xbc,0x19,0xf4,0x10,0x0b,0x0}}
499};
500static const opl4_region_t regions_43[] = { /* Baritone Sax */
501 {0x15, 0x2d, {0x0df,6714,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}},
502 {0x2e, 0x34, {0x0e1,5552,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}},
503 {0x35, 0x39, {0x0e2,5178,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}},
504 {0x3a, 0x6c, {0x0e0,4437,100, 0,1,0x00,0xce,0x19,0xf0,0x00,0x0a,0x0}}
505};
506static const opl4_region_t regions_44[] = { /* Oboe */
507 {0x15, 0x3c, {0x042,4493,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}},
508 {0x3d, 0x43, {0x044,3702,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}},
509 {0x44, 0x49, {0x043,2956,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}},
510 {0x4a, 0x4f, {0x046,2166,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}},
511 {0x50, 0x55, {0x045,1420,100, 0,1,0x00,0xdc,0x39,0xf4,0x10,0x0a,0x0}},
512 {0x56, 0x6c, {0x047, 630,100, 0,1,0x00,0xe6,0x39,0xf4,0x10,0x0a,0x0}}
513};
514static const opl4_region_t regions_45[] = { /* English Horn */
515 {0x15, 0x38, {0x03c,5098,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}},
516 {0x39, 0x3e, {0x03b,4291,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}},
517 {0x3f, 0x6c, {0x03d,3540,100, 0,1,0x00,0xc4,0x31,0xf0,0x00,0x09,0x0}}
518};
519static const opl4_region_t regions_46[] = { /* Bassoon */
520 {0x15, 0x22, {0x038,7833,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}},
521 {0x23, 0x2e, {0x03a,7070,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}},
522 {0x2f, 0x6c, {0x039,6302,100, 0,1,0x00,0xc6,0x31,0xf0,0x00,0x0b,0x0}}
523};
524static const opl4_region_t regions_47[] = { /* Clarinet */
525 {0x15, 0x3b, {0x09e,5900,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}},
526 {0x3c, 0x41, {0x0a0,5158,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}},
527 {0x42, 0x4a, {0x09f,4260,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}},
528 {0x4b, 0x6c, {0x0a1,2957,100, 0,1,0x00,0xc8,0x29,0xf3,0x20,0x0a,0x0}}
529};
530static const opl4_region_t regions_48[] = { /* Piccolo */
531 {0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}},
532 {0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}},
533 {0x4e, 0x53, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}},
534 {0x54, 0x5f, {0x074,2085,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}},
535 {0x60, 0x6c, {0x075,1421,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}
536};
537static const opl4_region_t regions_49[] = { /* Flute */
538 {0x15, 0x40, {0x071,4803,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}},
539 {0x41, 0x4d, {0x072,3314,100, 0,0,0x00,0xdc,0x38,0xf0,0x00,0x0a,0x2}},
540 {0x4e, 0x6c, {0x073,1731,100, 0,0,0x00,0xe6,0x38,0xf0,0x00,0x0a,0x2}}
541};
542static const opl4_region_t regions_4a[] = { /* Recorder */
543 {0x15, 0x6f, {0x0bd,4897,100, 0,0,0x00,0xec,0x30,0x70,0x00,0x09,0x1}}
544};
545static const opl4_region_t regions_4b[] = { /* Pan Flute */
546 {0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xde,0x38,0xf0,0x00,0x09,0x3}}
547};
548static const opl4_region_t regions_4c[] = { /* Bottle Blow */
549 {0x15, 0x6c, {0x077,2359,100, 0,0,0x00,0xc8,0x38,0xf0,0x00,0x09,0x1}},
550 {0x01, 0x7f, {0x125,7372,100, 0,0,0x1e,0x80,0x00,0xf0,0x00,0x09,0x0}}
551};
552static const opl4_region_t regions_4d[] = { /* Shakuhachi */
553 {0x00, 0x7f, {0x0ab,4548,100, 0,0,0x00,0xd6,0x30,0xf0,0x00,0x0a,0x3}},
554 {0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xa2,0x28,0x70,0x00,0x09,0x2}}
555};
556static const opl4_region_t regions_4e[] = { /* Whistle */
557 {0x00, 0x7f, {0x0aa,1731,100, 0,4,0x00,0xd2,0x2c,0x70,0x00,0x0a,0x0}}
558};
559static const opl4_region_t regions_4f[] = { /* Ocarina */
560 {0x00, 0x7f, {0x0aa,1731,100, 0,1,0x00,0xce,0x29,0x90,0x00,0x0a,0x1}}
561};
562static const opl4_region_t regions_50[] = { /* Square Lead */
563 {0x01, 0x2a, {0x0cc,9853,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}},
564 {0x2b, 0x36, {0x0cd,6785,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}},
565 {0x37, 0x42, {0x0ca,5248,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}},
566 {0x43, 0x4e, {0x0cf,3713,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}},
567 {0x4f, 0x5a, {0x0ce,2176,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}},
568 {0x5b, 0x7f, {0x0cb, 640,100, 3,0,0x00,0xac,0x38,0xc6,0x21,0x09,0x0}},
569 {0x01, 0x2a, {0x0cc,9844,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}},
570 {0x2b, 0x36, {0x0cd,6776,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}},
571 {0x37, 0x42, {0x0ca,5239,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}},
572 {0x43, 0x4e, {0x0cf,3704,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}},
573 {0x4f, 0x5a, {0x0ce,2167,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}},
574 {0x5b, 0x7f, {0x0cb, 631,100,-3,0,0x00,0xac,0x08,0xc6,0x21,0x09,0x0}}
575};
576static const opl4_region_t regions_51[] = { /* Sawtooth Lead */
577 {0x01, 0x27, {0x118,9108,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
578 {0x28, 0x2d, {0x119,8345,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
579 {0x2e, 0x33, {0x11a,7570,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
580 {0x34, 0x39, {0x11b,6809,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
581 {0x3a, 0x3f, {0x11c,6047,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
582 {0x40, 0x45, {0x11d,5282,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
583 {0x46, 0x4b, {0x11e,4525,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
584 {0x4c, 0x51, {0x11f,3746,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
585 {0x52, 0x57, {0x120,3017,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
586 {0x58, 0x5d, {0x121,2171,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
587 {0x5e, 0x66, {0x122,1426,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
588 {0x67, 0x7f, {0x123,-110,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
589 {0x01, 0x27, {0x118,9098,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
590 {0x28, 0x2d, {0x119,8335,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
591 {0x2e, 0x33, {0x11a,7560,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
592 {0x34, 0x39, {0x11b,6799,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
593 {0x3a, 0x3f, {0x11c,6037,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
594 {0x40, 0x45, {0x11d,5272,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
595 {0x46, 0x4b, {0x11e,4515,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
596 {0x4c, 0x51, {0x11f,3736,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
597 {0x52, 0x57, {0x120,3007,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
598 {0x58, 0x5d, {0x121,2161,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
599 {0x5e, 0x66, {0x122,1416,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}},
600 {0x67, 0x7f, {0x123,-120,100, 0,0,0x00,0xc8,0x30,0xf2,0x22,0x0a,0x0}}
601};
602static const opl4_region_t regions_52[] = { /* Calliope Lead */
603 {0x00, 0x7f, {0x0aa,1731,100, 0,0,0x00,0xc2,0x28,0x90,0x00,0x0a,0x2}},
604 {0x15, 0x6c, {0x076,3716,100, 0,0,0x00,0xb6,0x28,0xb0,0x00,0x09,0x2}}
605};
606static const opl4_region_t regions_53[] = { /* Chiffer Lead */
607 {0x00, 0x7f, {0x13a,3665,100, 0,2,0x00,0xcc,0x2a,0xf0,0x10,0x09,0x1}},
608 {0x01, 0x7f, {0x0fe,3660,100, 0,0,0x00,0xbe,0x28,0xf3,0x10,0x17,0x0}}
609};
610static const opl4_region_t regions_54[] = { /* Charang Lead */
611 {0x00, 0x40, {0x0a5,6594,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}},
612 {0x41, 0x7f, {0x0a6,5433,100, 0,3,0x00,0xba,0x33,0xf2,0x11,0x09,0x0}},
613 {0x01, 0x27, {0x118,9098,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
614 {0x28, 0x2d, {0x119,8335,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
615 {0x2e, 0x33, {0x11a,7560,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
616 {0x34, 0x39, {0x11b,6799,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
617 {0x3a, 0x3f, {0x11c,6037,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
618 {0x40, 0x45, {0x11d,5272,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
619 {0x46, 0x4b, {0x11e,4515,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
620 {0x4c, 0x51, {0x11f,3736,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
621 {0x52, 0x57, {0x120,3007,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
622 {0x58, 0x5d, {0x121,2161,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
623 {0x5e, 0x66, {0x122,1416,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}},
624 {0x67, 0x7f, {0x123,-120,100, 0,2,0x00,0xa4,0x2a,0xf2,0x22,0x0e,0x0}}
625};
626static const opl4_region_t regions_55[] = { /* Voice Lead */
627 {0x00, 0x7f, {0x0aa,1739,100, 0,6,0x00,0x8c,0x2e,0x90,0x00,0x0a,0x0}},
628 {0x15, 0x6c, {0x02a,3474,100, 0,1,0x00,0xd8,0x29,0xf0,0x05,0x0a,0x0}}
629};
630static const opl4_region_t regions_56[] = { /* 5ths Lead */
631 {0x01, 0x27, {0x118,8468,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
632 {0x28, 0x2d, {0x119,7705,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
633 {0x2e, 0x33, {0x11a,6930,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
634 {0x34, 0x39, {0x11b,6169,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
635 {0x3a, 0x3f, {0x11c,5407,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
636 {0x40, 0x45, {0x11d,4642,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
637 {0x46, 0x4b, {0x11e,3885,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
638 {0x4c, 0x51, {0x11f,3106,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
639 {0x52, 0x57, {0x120,2377,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
640 {0x58, 0x5d, {0x121,1531,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
641 {0x5e, 0x64, {0x122, 786,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
642 {0x65, 0x7f, {0x123,-750,100, 0,2,0x00,0xd0,0x32,0xf5,0x20,0x08,0x0}},
643 {0x05, 0x71, {0x002,4503,100, 0,1,0x00,0xb8,0x31,0xb3,0x20,0x0b,0x0}}
644};
645static const opl4_region_t regions_57[] = { /* Bass & Lead */
646 {0x00, 0x7f, {0x117,8109,100, 0,1,0x00,0xbc,0x29,0xf3,0x50,0x08,0x0}},
647 {0x01, 0x27, {0x118,9097,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
648 {0x28, 0x2d, {0x119,8334,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
649 {0x2e, 0x33, {0x11a,7559,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
650 {0x34, 0x39, {0x11b,6798,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
651 {0x3a, 0x3f, {0x11c,6036,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
652 {0x40, 0x45, {0x11d,5271,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
653 {0x46, 0x4b, {0x11e,4514,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
654 {0x4c, 0x51, {0x11f,3735,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
655 {0x52, 0x57, {0x120,3006,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
656 {0x58, 0x5d, {0x121,2160,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
657 {0x5e, 0x66, {0x122,1415,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}},
658 {0x67, 0x7f, {0x123,-121,100, 0,2,0x00,0xbc,0x2a,0xf2,0x20,0x0a,0x0}}
659};
660static const opl4_region_t regions_58[] = { /* New Age Pad */
661 {0x15, 0x6c, {0x002,4501,100, 0,4,0x00,0xa4,0x24,0x80,0x01,0x05,0x0}},
662 {0x15, 0x6c, {0x0f3,4253,100, 0,3,0x00,0x8c,0x23,0xa2,0x14,0x06,0x1}}
663};
664static const opl4_region_t regions_59[] = { /* Warm Pad */
665 {0x15, 0x6c, {0x04e,5306,100, 2,2,0x00,0x92,0x2a,0x34,0x23,0x05,0x2}},
666 {0x15, 0x6c, {0x029,3575,100,-2,2,0x00,0xbe,0x22,0x31,0x23,0x06,0x0}}
667};
668static const opl4_region_t regions_5a[] = { /* Polysynth Pad */
669 {0x01, 0x27, {0x118,9111,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
670 {0x28, 0x2d, {0x119,8348,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
671 {0x2e, 0x33, {0x11a,7573,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
672 {0x34, 0x39, {0x11b,6812,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
673 {0x3a, 0x3f, {0x11c,6050,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
674 {0x40, 0x45, {0x11d,5285,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
675 {0x46, 0x4b, {0x11e,4528,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
676 {0x4c, 0x51, {0x11f,3749,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
677 {0x52, 0x57, {0x120,3020,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
678 {0x58, 0x5d, {0x121,2174,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
679 {0x5e, 0x66, {0x122,1429,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
680 {0x67, 0x7f, {0x123,-107,100, 0,3,0x00,0xae,0x23,0xf2,0x20,0x07,0x1}},
681 {0x00, 0x7f, {0x124,4024,100, 0,2,0x00,0xae,0x22,0xe5,0x20,0x08,0x0}}
682};
683static const opl4_region_t regions_5b[] = { /* Choir Pad */
684 {0x15, 0x3a, {0x018,5010,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}},
685 {0x3b, 0x40, {0x019,4370,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}},
686 {0x41, 0x47, {0x01a,3478,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}},
687 {0x48, 0x6c, {0x01b,2197,100, 0,5,0x00,0xb0,0x25,0x70,0x00,0x06,0x0}},
688 {0x15, 0x6c, {0x02a,3482,100, 0,4,0x00,0x98,0x24,0x65,0x21,0x06,0x0}}
689};
690static const opl4_region_t regions_5c[] = { /* Bowed Pad */
691 {0x15, 0x6c, {0x101,4790,100,-1,1,0x00,0xbe,0x19,0x44,0x14,0x16,0x0}},
692 {0x00, 0x7f, {0x0aa,1720,100, 1,1,0x00,0x94,0x19,0x40,0x00,0x06,0x0}}
693};
694static const opl4_region_t regions_5d[] = { /* Metallic Pad */
695 {0x15, 0x31, {0x00c,6943,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}},
696 {0x32, 0x38, {0x00d,5416,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}},
697 {0x39, 0x47, {0x00e,4385,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}},
698 {0x48, 0x6c, {0x00f,2849,100, 0,2,0x00,0xa0,0x0a,0x60,0x03,0x06,0x0}},
699 {0x00, 0x7f, {0x03f,4224,100, 0,1,0x00,0x9c,0x31,0x65,0x16,0x07,0x0}}
700};
701static const opl4_region_t regions_5e[] = { /* Halo Pad */
702 {0x00, 0x7f, {0x124,4038,100, 0,2,0x00,0xa6,0x1a,0x85,0x23,0x08,0x0}},
703 {0x15, 0x6c, {0x02a,3471,100, 0,3,0x00,0xc0,0x1b,0xc0,0x05,0x06,0x0}}
704};
705static const opl4_region_t regions_5f[] = { /* Sweep Pad */
706 {0x01, 0x27, {0x0d3,9100,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
707 {0x28, 0x2d, {0x0da,8341,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
708 {0x2e, 0x33, {0x0d4,7564,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
709 {0x34, 0x39, {0x0db,6791,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
710 {0x3a, 0x3f, {0x0d5,6048,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
711 {0x40, 0x45, {0x0dc,5263,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
712 {0x46, 0x4b, {0x0d6,4499,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
713 {0x4c, 0x51, {0x0dd,3747,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
714 {0x52, 0x57, {0x0d7,3018,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
715 {0x58, 0x5d, {0x0de,2173,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
716 {0x5e, 0x63, {0x0d8,1427,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
717 {0x64, 0x7f, {0x0d9,-109,100, 0,1,0x00,0xce,0x19,0x13,0x11,0x06,0x0}},
718 {0x01, 0x27, {0x0d3,9088,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
719 {0x28, 0x2d, {0x0da,8329,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
720 {0x2e, 0x33, {0x0d4,7552,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
721 {0x34, 0x39, {0x0db,6779,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
722 {0x3a, 0x3f, {0x0d5,6036,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
723 {0x40, 0x45, {0x0dc,5251,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
724 {0x46, 0x4b, {0x0d6,4487,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
725 {0x4c, 0x51, {0x0dd,3735,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
726 {0x52, 0x57, {0x0d7,3006,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
727 {0x58, 0x5d, {0x0de,2161,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
728 {0x5e, 0x63, {0x0d8,1415,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}},
729 {0x64, 0x7f, {0x0d9,-121,100, 0,0,0x00,0xce,0x18,0x13,0x11,0x06,0x0}}
730};
731static const opl4_region_t regions_60[] = { /* Ice Rain */
732 {0x01, 0x7f, {0x04e,9345,100, 0,2,0x00,0xcc,0x22,0xa3,0x63,0x17,0x0}},
733 {0x00, 0x7f, {0x143,5586, 20, 0,2,0x00,0x6e,0x2a,0xf0,0x05,0x05,0x0}}
734};
735static const opl4_region_t regions_61[] = { /* Soundtrack */
736 {0x15, 0x6c, {0x002,4501,100, 0,2,0x00,0xb6,0x2a,0x60,0x01,0x05,0x0}},
737 {0x15, 0x6c, {0x0f3,1160,100, 0,5,0x00,0xa8,0x2d,0x52,0x14,0x06,0x2}}
738};
739static const opl4_region_t regions_62[] = { /* Crystal */
740 {0x15, 0x6c, {0x0f3,1826,100, 0,3,0x00,0xb8,0x33,0xf6,0x25,0x25,0x0}},
741 {0x15, 0x2c, {0x06d,7454,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}},
742 {0x2d, 0x36, {0x06e,5925,100, 0,3,0x00,0xac,0x3b,0x85,0x24,0x06,0x0}},
743 {0x37, 0x6c, {0x06f,4403,100, 0,3,0x09,0xac,0x3b,0x85,0x24,0x06,0x0}}
744};
745static const opl4_region_t regions_63[] = { /* Atmosphere */
746 {0x05, 0x71, {0x002,4509,100, 0,2,0x00,0xc8,0x32,0x73,0x22,0x06,0x1}},
747 {0x15, 0x2f, {0x0b3,6964,100, 0,2,0x05,0xc2,0x32,0xf5,0x34,0x07,0x2}},
748 {0x30, 0x36, {0x0b7,5567,100, 0,2,0x0c,0xc2,0x32,0xf5,0x34,0x07,0x2}},
749 {0x37, 0x3c, {0x0b5,4653,100, 0,2,0x00,0xc2,0x32,0xf6,0x34,0x07,0x2}},
750 {0x3d, 0x43, {0x0b4,3892,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x07,0x2}},
751 {0x44, 0x60, {0x0b6,2723,100, 0,2,0x00,0xc2,0x32,0xf6,0x35,0x17,0x2}}
752};
753static const opl4_region_t regions_64[] = { /* Brightness */
754 {0x00, 0x7f, {0x137,5285,100, 0,2,0x00,0xbe,0x2a,0xa5,0x18,0x08,0x0}},
755 {0x15, 0x6c, {0x02a,3481,100, 0,1,0x00,0xc8,0x29,0x80,0x05,0x05,0x0}}
756};
757static const opl4_region_t regions_65[] = { /* Goblins */
758 {0x15, 0x6c, {0x002,4501,100,-1,2,0x00,0xca,0x2a,0x40,0x01,0x05,0x0}},
759 {0x15, 0x6c, {0x009,9679, 20, 1,4,0x00,0x3c,0x0c,0x22,0x11,0x06,0x0}}
760};
761static const opl4_region_t regions_66[] = { /* Echoes */
762 {0x15, 0x6c, {0x02a,3487,100, 0,3,0x00,0xae,0x2b,0xf5,0x21,0x06,0x0}},
763 {0x00, 0x7f, {0x124,4027,100, 0,3,0x00,0xae,0x2b,0x85,0x23,0x07,0x0}}
764};
765static const opl4_region_t regions_67[] = { /* Sci-Fi */
766 {0x15, 0x31, {0x00c,6940,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}},
767 {0x32, 0x38, {0x00d,5413,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}},
768 {0x39, 0x47, {0x00e,4382,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}},
769 {0x48, 0x6c, {0x00f,2846,100, 0,3,0x00,0xc8,0x2b,0x90,0x05,0x06,0x3}},
770 {0x15, 0x6c, {0x002,4498,100, 0,2,0x00,0xd4,0x22,0x80,0x01,0x05,0x0}}
771};
772static const opl4_region_t regions_68[] = { /* Sitar */
773 {0x00, 0x7f, {0x10f,4408,100, 0,2,0x00,0xc4,0x32,0xf4,0x15,0x16,0x1}}
774};
775static const opl4_region_t regions_69[] = { /* Banjo */
776 {0x15, 0x34, {0x013,5685,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}},
777 {0x35, 0x38, {0x014,5009,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}},
778 {0x39, 0x3c, {0x012,4520,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}},
779 {0x3d, 0x44, {0x015,3622,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}},
780 {0x45, 0x4c, {0x017,2661,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}},
781 {0x4d, 0x6d, {0x016,1632,100, 0,0,0x00,0xdc,0x38,0xf6,0x15,0x09,0x0}}
782};
783static const opl4_region_t regions_6a[] = { /* Shamisen */
784 {0x15, 0x6c, {0x10e,3273,100, 0,0,0x00,0xc0,0x28,0xf7,0x76,0x08,0x0}}
785};
786static const opl4_region_t regions_6b[] = { /* Koto */
787 {0x00, 0x7f, {0x0a9,4033,100, 0,0,0x00,0xc6,0x20,0xf0,0x06,0x07,0x0}}
788};
789static const opl4_region_t regions_6c[] = { /* Kalimba */
790 {0x00, 0x7f, {0x137,3749,100, 0,0,0x00,0xce,0x38,0xf5,0x18,0x08,0x0}}
791};
792static const opl4_region_t regions_6d[] = { /* Bagpipe */
793 {0x15, 0x39, {0x0a4,7683,100, 0,4,0x00,0xc0,0x1c,0xf0,0x00,0x09,0x0}},
794 {0x15, 0x39, {0x0a7,7680,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}},
795 {0x3a, 0x6c, {0x0a8,3697,100, 0,1,0x00,0xaa,0x19,0xf0,0x00,0x09,0x0}}
796};
797static const opl4_region_t regions_6e[] = { /* Fiddle */
798 {0x15, 0x3a, {0x105,5158,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
799 {0x3b, 0x3f, {0x102,4754,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
800 {0x40, 0x41, {0x106,4132,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
801 {0x42, 0x44, {0x107,4033,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
802 {0x45, 0x47, {0x108,3580,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
803 {0x48, 0x4a, {0x10a,2957,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
804 {0x4b, 0x4c, {0x10b,2724,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
805 {0x4d, 0x4e, {0x10c,2530,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
806 {0x4f, 0x51, {0x10d,2166,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}},
807 {0x52, 0x6c, {0x109,1825,100, 0,1,0x00,0xca,0x31,0xf3,0x20,0x09,0x0}}
808};
809static const opl4_region_t regions_6f[] = { /* Shanai */
810 {0x15, 0x6c, {0x041,6946,100, 0,1,0x00,0xc4,0x31,0x95,0x20,0x09,0x0}}
811};
812static const opl4_region_t regions_70[] = { /* Tinkle Bell */
813 {0x15, 0x73, {0x0f3,1821,100, 0,3,0x00,0xc8,0x3b,0xd6,0x25,0x25,0x0}},
814 {0x00, 0x7f, {0x137,5669,100, 0,3,0x00,0x66,0x3b,0xf5,0x18,0x08,0x0}}
815};
816static const opl4_region_t regions_71[] = { /* Agogo */
817 {0x15, 0x74, {0x00b,2474,100, 0,0,0x00,0xd2,0x38,0xf0,0x00,0x09,0x0}}
818};
819static const opl4_region_t regions_72[] = { /* Steel Drums */
820 {0x01, 0x7f, {0x0fe,3670,100, 0,0,0x00,0xca,0x38,0xf3,0x06,0x17,0x1}},
821 {0x15, 0x6c, {0x100,9602,100, 0,0,0x00,0x54,0x38,0xb0,0x05,0x16,0x1}}
822};
823static const opl4_region_t regions_73[] = { /* Woodblock */
824 {0x15, 0x6c, {0x02c,2963, 50, 0,0,0x07,0xd4,0x00,0xf0,0x00,0x09,0x0}}
825};
826static const opl4_region_t regions_74[] = { /* Taiko Drum */
827 {0x13, 0x6c, {0x03e,1194, 50, 0,0,0x00,0xaa,0x38,0xf0,0x04,0x04,0x0}}
828};
829static const opl4_region_t regions_75[] = { /* Melodic Tom */
830 {0x15, 0x6c, {0x0c7,6418, 50, 0,0,0x00,0xe4,0x38,0xf0,0x05,0x01,0x0}}
831};
832static const opl4_region_t regions_76[] = { /* Synth Drum */
833 {0x15, 0x6c, {0x026,3898, 50, 0,0,0x00,0xd0,0x38,0xf0,0x04,0x04,0x0}}
834};
835static const opl4_region_t regions_77[] = { /* Reverse Cymbal */
836 {0x15, 0x6c, {0x031,4138, 50, 0,0,0x00,0xfe,0x38,0x3a,0xf0,0x09,0x0}}
837};
838static const opl4_region_t regions_78[] = { /* Guitar Fret Noise */
839 {0x15, 0x6c, {0x138,5266,100, 0,0,0x00,0xa0,0x38,0xf0,0x00,0x09,0x0}}
840};
841static const opl4_region_t regions_79[] = { /* Breath Noise */
842 {0x01, 0x7f, {0x125,4269,100, 0,0,0x1e,0xd0,0x38,0xf0,0x00,0x09,0x0}}
843};
844static const opl4_region_t regions_7a[] = { /* Seashore */
845 {0x15, 0x6c, {0x008,2965, 20,-2,0,0x00,0xfe,0x00,0x20,0x03,0x04,0x0}},
846 {0x01, 0x7f, {0x037,4394, 20, 2,0,0x14,0xfe,0x00,0x20,0x04,0x05,0x0}}
847};
848static const opl4_region_t regions_7b[] = { /* Bird Tweet */
849 {0x15, 0x6c, {0x009,8078, 5,-4,7,0x00,0xc2,0x0f,0x22,0x12,0x07,0x0}},
850 {0x15, 0x6c, {0x009,3583, 5, 4,5,0x00,0xae,0x15,0x72,0x12,0x07,0x0}}
851};
852static const opl4_region_t regions_7c[] = { /* Telephone Ring */
853 {0x15, 0x6c, {0x003,3602, 10, 0,0,0x00,0xce,0x00,0xf0,0x00,0x0f,0x0}}
854};
855static const opl4_region_t regions_7d[] = { /* Helicopter */
856 {0x0c, 0x7f, {0x001,2965, 10,-2,0,0x00,0xe0,0x08,0x30,0x01,0x07,0x0}},
857 {0x01, 0x7f, {0x037,4394, 10, 2,0,0x44,0x76,0x00,0x30,0x01,0x07,0x0}}
858};
859static const opl4_region_t regions_7e[] = { /* Applause */
860 {0x15, 0x6c, {0x036,8273, 20,-6,7,0x00,0xc4,0x0f,0x70,0x01,0x05,0x0}},
861 {0x15, 0x6c, {0x036,8115, 5, 6,7,0x00,0xc6,0x07,0x70,0x01,0x05,0x0}}
862};
863static const opl4_region_t regions_7f[] = { /* Gun Shot */
864 {0x15, 0x6c, {0x139,2858, 20, 0,0,0x00,0xbe,0x38,0xf0,0x03,0x00,0x0}}
865};
866static const opl4_region_t regions_drums[] = {
867 {0x18, 0x18, {0x0cb,6397,100, 3,0,0x00,0xf4,0x38,0xc9,0x1c,0x0c,0x0}},
868 {0x19, 0x19, {0x0c4,3714,100, 0,0,0x00,0xe0,0x00,0x97,0x19,0x09,0x0}},
869 {0x1a, 0x1a, {0x0c4,3519,100, 0,0,0x00,0xea,0x00,0x61,0x01,0x07,0x0}},
870 {0x1b, 0x1b, {0x0c4,3586,100, 0,0,0x00,0xea,0x00,0xf7,0x19,0x09,0x0}},
871 {0x1c, 0x1c, {0x0c4,3586,100, 0,0,0x00,0xea,0x00,0x81,0x01,0x07,0x0}},
872 {0x1e, 0x1e, {0x0c3,4783,100, 0,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
873 {0x1f, 0x1f, {0x0d1,4042,100, 0,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}},
874 {0x20, 0x20, {0x0d2,5943,100, 0,0,0x00,0xcc,0x00,0xf0,0x00,0x09,0x0}},
875 {0x21, 0x21, {0x011,3842,100, 0,0,0x00,0xea,0x00,0xf0,0x16,0x06,0x0}},
876 {0x23, 0x23, {0x011,4098,100, 0,0,0x00,0xea,0x00,0xf0,0x16,0x06,0x0}},
877 {0x24, 0x24, {0x011,4370,100, 0,0,0x00,0xea,0x00,0xf0,0x00,0x06,0x0}},
878 {0x25, 0x25, {0x0d2,4404,100, 0,0,0x00,0xd6,0x00,0xf0,0x00,0x06,0x0}},
879 {0x26, 0x26, {0x0d1,4298,100, 0,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}},
880 {0x27, 0x27, {0x00a,4403,100,-1,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}},
881 {0x28, 0x28, {0x0d1,4554,100, 0,0,0x00,0xdc,0x00,0xf0,0x07,0x07,0x0}},
882 {0x29, 0x29, {0x0c8,4242,100,-4,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}},
883 {0x2a, 0x2a, {0x079,6160,100, 2,0,0x00,0xe0,0x00,0xf5,0x19,0x09,0x0}},
884 {0x2b, 0x2b, {0x0c8,4626,100,-3,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}},
885 {0x2c, 0x2c, {0x07b,6039,100, 2,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}},
886 {0x2d, 0x2d, {0x0c8,5394,100,-2,0,0x00,0xd6,0x00,0xf6,0x16,0x06,0x0}},
887 {0x2e, 0x2e, {0x07a,5690,100, 2,0,0x00,0xd6,0x00,0xf0,0x00,0x05,0x0}},
888 {0x2f, 0x2f, {0x0c7,5185,100, 2,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}},
889 {0x30, 0x30, {0x0c7,5650,100, 3,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}},
890 {0x31, 0x31, {0x031,4395,100, 2,0,0x00,0xea,0x00,0xf0,0x05,0x05,0x0}},
891 {0x32, 0x32, {0x0c7,6162,100, 4,0,0x00,0xe0,0x00,0xf6,0x17,0x07,0x0}},
892 {0x33, 0x33, {0x02e,4391,100,-2,0,0x00,0xea,0x00,0xf0,0x05,0x05,0x0}},
893 {0x34, 0x34, {0x07a,3009,100,-2,0,0x00,0xea,0x00,0xf2,0x15,0x05,0x0}},
894 {0x35, 0x35, {0x021,4522,100,-3,0,0x00,0xd6,0x00,0xf0,0x05,0x05,0x0}},
895 {0x36, 0x36, {0x025,5163,100, 1,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}},
896 {0x37, 0x37, {0x031,5287,100,-1,0,0x00,0xea,0x00,0xf5,0x16,0x06,0x0}},
897 {0x38, 0x38, {0x01d,4395,100, 2,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}},
898 {0x39, 0x39, {0x031,4647,100,-2,0,0x00,0xea,0x00,0xf4,0x16,0x06,0x0}},
899 {0x3a, 0x3a, {0x09d,4426,100,-4,0,0x00,0xe0,0x00,0xf4,0x17,0x07,0x0}},
900 {0x3b, 0x3b, {0x02e,4659,100,-2,0,0x00,0xea,0x00,0xf0,0x06,0x06,0x0}},
901 {0x3c, 0x3c, {0x01c,4769,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
902 {0x3d, 0x3d, {0x01c,4611,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
903 {0x3e, 0x3e, {0x01e,4402,100,-3,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
904 {0x3f, 0x3f, {0x01f,4387,100,-3,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
905 {0x40, 0x40, {0x01f,3983,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
906 {0x41, 0x41, {0x09c,4526,100, 2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
907 {0x42, 0x42, {0x09c,4016,100, 2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
908 {0x43, 0x43, {0x00b,4739,100,-4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
909 {0x44, 0x44, {0x00b,4179,100,-4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
910 {0x45, 0x45, {0x02f,4787,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}},
911 {0x46, 0x46, {0x030,4665,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}},
912 {0x47, 0x47, {0x144,4519,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x0b,0x0}},
913 {0x48, 0x48, {0x144,4111,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x0b,0x0}},
914 {0x49, 0x49, {0x024,6408,100, 3,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}},
915 {0x4a, 0x4a, {0x024,4144,100, 3,0,0x00,0xcc,0x00,0xf0,0x00,0x09,0x0}},
916 {0x4b, 0x4b, {0x020,4001,100, 2,0,0x00,0xe0,0x00,0xf0,0x00,0x09,0x0}},
917 {0x4c, 0x4c, {0x02c,4402,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
918 {0x4d, 0x4d, {0x02c,3612,100, 4,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
919 {0x4e, 0x4e, {0x022,4129,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
920 {0x4f, 0x4f, {0x023,4147,100,-2,0,0x00,0xea,0x00,0xf0,0x00,0x09,0x0}},
921 {0x50, 0x50, {0x032,4412,100,-4,0,0x00,0xd6,0x00,0xf0,0x08,0x09,0x0}},
922 {0x51, 0x51, {0x032,4385,100,-4,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}},
923 {0x52, 0x52, {0x02f,5935,100,-1,0,0x00,0xd6,0x00,0xf0,0x00,0x09,0x0}}
924};
925
926#define REGION(num) { ARRAY_SIZE(regions ## num), regions ## num }
927const opl4_region_ptr_t snd_yrw801_regions[0x81] = {
928 REGION(_00), REGION(_01), REGION(_02), REGION(_03),
929 REGION(_04), REGION(_05), REGION(_06), REGION(_07),
930 REGION(_08), REGION(_09), REGION(_0a), REGION(_0b),
931 REGION(_0c), REGION(_0d), REGION(_0e), REGION(_0f),
932 REGION(_10), REGION(_11), REGION(_12), REGION(_13),
933 REGION(_14), REGION(_15), REGION(_16), REGION(_17),
934 REGION(_18), REGION(_19), REGION(_1a), REGION(_1b),
935 REGION(_1c), REGION(_1d), REGION(_1e), REGION(_1f),
936 REGION(_20), REGION(_21), REGION(_22), REGION(_23),
937 REGION(_24), REGION(_25), REGION(_26), REGION(_27),
938 REGION(_28), REGION(_29), REGION(_2a), REGION(_2b),
939 REGION(_2c), REGION(_2d), REGION(_2e), REGION(_2f),
940 REGION(_30), REGION(_31), REGION(_32), REGION(_33),
941 REGION(_34), REGION(_35), REGION(_36), REGION(_37),
942 REGION(_38), REGION(_39), REGION(_3a), REGION(_3b),
943 REGION(_3c), REGION(_3d), REGION(_3e), REGION(_3f),
944 REGION(_40), REGION(_41), REGION(_42), REGION(_43),
945 REGION(_44), REGION(_45), REGION(_46), REGION(_47),
946 REGION(_48), REGION(_49), REGION(_4a), REGION(_4b),
947 REGION(_4c), REGION(_4d), REGION(_4e), REGION(_4f),
948 REGION(_50), REGION(_51), REGION(_52), REGION(_53),
949 REGION(_54), REGION(_55), REGION(_56), REGION(_57),
950 REGION(_58), REGION(_59), REGION(_5a), REGION(_5b),
951 REGION(_5c), REGION(_5d), REGION(_5e), REGION(_5f),
952 REGION(_60), REGION(_61), REGION(_62), REGION(_63),
953 REGION(_64), REGION(_65), REGION(_66), REGION(_67),
954 REGION(_68), REGION(_69), REGION(_6a), REGION(_6b),
955 REGION(_6c), REGION(_6d), REGION(_6e), REGION(_6f),
956 REGION(_70), REGION(_71), REGION(_72), REGION(_73),
957 REGION(_74), REGION(_75), REGION(_76), REGION(_77),
958 REGION(_78), REGION(_79), REGION(_7a), REGION(_7b),
959 REGION(_7c), REGION(_7d), REGION(_7e), REGION(_7f),
960 REGION(_drums)
961};
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
new file mode 100644
index 000000000000..964b97e70c84
--- /dev/null
+++ b/sound/drivers/serial-u16550.c
@@ -0,0 +1,990 @@
1/*
2 * serial.c
3 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
4 * Isaku Yamahata <yamahata@private.email.ne.jp>,
5 * George Hansper <ghansper@apana.org.au>,
6 * Hannu Savolainen
7 *
8 * This code is based on the code from ALSA 0.5.9, but heavily rewritten.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 * Sat Mar 31 17:27:57 PST 2001 tim.mann@compaq.com
25 * Added support for the Midiator MS-124T and for the MS-124W in
26 * Single Addressed (S/A) or Multiple Burst (M/B) mode, with
27 * power derived either parasitically from the serial port or
28 * from a separate power supply.
29 *
30 * More documentation can be found in serial-u16550.txt.
31 */
32
33#include <sound/driver.h>
34#include <linux/init.h>
35#include <linux/interrupt.h>
36#include <linux/slab.h>
37#include <linux/ioport.h>
38#include <linux/moduleparam.h>
39#include <sound/core.h>
40#include <sound/rawmidi.h>
41#include <sound/initval.h>
42
43#include <linux/serial_reg.h>
44
45#include <asm/io.h>
46
47MODULE_DESCRIPTION("MIDI serial u16550");
48MODULE_LICENSE("GPL");
49MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}");
50
51#define SNDRV_SERIAL_SOUNDCANVAS 0 /* Roland Soundcanvas; F5 NN selects part */
52#define SNDRV_SERIAL_MS124T 1 /* Midiator MS-124T */
53#define SNDRV_SERIAL_MS124W_SA 2 /* Midiator MS-124W in S/A mode */
54#define SNDRV_SERIAL_MS124W_MB 3 /* Midiator MS-124W in M/B mode */
55#define SNDRV_SERIAL_GENERIC 4 /* Generic Interface */
56#define SNDRV_SERIAL_MAX_ADAPTOR SNDRV_SERIAL_GENERIC
57static char *adaptor_names[] = {
58 "Soundcanvas",
59 "MS-124T",
60 "MS-124W S/A",
61 "MS-124W M/B",
62 "Generic"
63};
64
65#define SNDRV_SERIAL_NORMALBUFF 0 /* Normal blocking buffer operation */
66#define SNDRV_SERIAL_DROPBUFF 1 /* Non-blocking discard operation */
67
68static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
69static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
70static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
71static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x3f8,0x2f8,0x3e8,0x2e8 */
72static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 3,4,5,7,9,10,11,14,15 */
73static int speed[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 38400}; /* 9600,19200,38400,57600,115200 */
74static int base[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 115200}; /* baud base */
75static int outs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */
76static int ins[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */
77static int adaptor[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = SNDRV_SERIAL_SOUNDCANVAS};
78static int droponfull[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS -1)] = SNDRV_SERIAL_NORMALBUFF };
79
80module_param_array(index, int, NULL, 0444);
81MODULE_PARM_DESC(index, "Index value for Serial MIDI.");
82module_param_array(id, charp, NULL, 0444);
83MODULE_PARM_DESC(id, "ID string for Serial MIDI.");
84module_param_array(enable, bool, NULL, 0444);
85MODULE_PARM_DESC(enable, "Enable UART16550A chip.");
86module_param_array(port, long, NULL, 0444);
87MODULE_PARM_DESC(port, "Port # for UART16550A chip.");
88module_param_array(irq, int, NULL, 0444);
89MODULE_PARM_DESC(irq, "IRQ # for UART16550A chip.");
90module_param_array(speed, int, NULL, 0444);
91MODULE_PARM_DESC(speed, "Speed in bauds.");
92module_param_array(base, int, NULL, 0444);
93MODULE_PARM_DESC(base, "Base for divisor in bauds.");
94module_param_array(outs, int, NULL, 0444);
95MODULE_PARM_DESC(outs, "Number of MIDI outputs.");
96module_param_array(ins, int, NULL, 0444);
97MODULE_PARM_DESC(ins, "Number of MIDI inputs.");
98module_param_array(droponfull, bool, NULL, 0444);
99MODULE_PARM_DESC(droponfull, "Flag to enable drop-on-full buffer mode");
100
101module_param_array(adaptor, int, NULL, 0444);
102MODULE_PARM_DESC(adaptor, "Type of adaptor.");
103
104/*#define SNDRV_SERIAL_MS124W_MB_NOCOMBO 1*/ /* Address outs as 0-3 instead of bitmap */
105
106#define SNDRV_SERIAL_MAX_OUTS 16 /* max 64, min 16 */
107#define SNDRV_SERIAL_MAX_INS 16 /* max 64, min 16 */
108
109#define TX_BUFF_SIZE (1<<15) /* Must be 2^n */
110#define TX_BUFF_MASK (TX_BUFF_SIZE - 1)
111
112#define SERIAL_MODE_NOT_OPENED (0)
113#define SERIAL_MODE_INPUT_OPEN (1 << 0)
114#define SERIAL_MODE_OUTPUT_OPEN (1 << 1)
115#define SERIAL_MODE_INPUT_TRIGGERED (1 << 2)
116#define SERIAL_MODE_OUTPUT_TRIGGERED (1 << 3)
117
118typedef struct _snd_uart16550 {
119 snd_card_t *card;
120 snd_rawmidi_t *rmidi;
121 snd_rawmidi_substream_t *midi_output[SNDRV_SERIAL_MAX_OUTS];
122 snd_rawmidi_substream_t *midi_input[SNDRV_SERIAL_MAX_INS];
123
124 int filemode; //open status of file
125
126 spinlock_t open_lock;
127
128 int irq;
129
130 unsigned long base;
131 struct resource *res_base;
132
133 unsigned int speed;
134 unsigned int speed_base;
135 unsigned char divisor;
136
137 unsigned char old_divisor_lsb;
138 unsigned char old_divisor_msb;
139 unsigned char old_line_ctrl_reg;
140
141 // parameter for using of write loop
142 short int fifo_limit; //used in uart16550
143 short int fifo_count; //used in uart16550
144
145 // type of adaptor
146 int adaptor;
147
148 // inputs
149 int prev_in;
150 unsigned char rstatus;
151
152 // outputs
153 int prev_out;
154 unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS];
155
156 // write buffer and its writing/reading position
157 unsigned char tx_buff[TX_BUFF_SIZE];
158 int buff_in_count;
159 int buff_in;
160 int buff_out;
161 int drop_on_full;
162
163 // wait timer
164 unsigned int timer_running:1;
165 struct timer_list buffer_timer;
166
167} snd_uart16550_t;
168
169static snd_card_t *snd_serial_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
170
171inline static void snd_uart16550_add_timer(snd_uart16550_t *uart)
172{
173 if (! uart->timer_running) {
174 /* timer 38600bps * 10bit * 16byte */
175 uart->buffer_timer.expires = jiffies + (HZ+255)/256;
176 uart->timer_running = 1;
177 add_timer(&uart->buffer_timer);
178 }
179}
180
181inline static void snd_uart16550_del_timer(snd_uart16550_t *uart)
182{
183 if (uart->timer_running) {
184 del_timer(&uart->buffer_timer);
185 uart->timer_running = 0;
186 }
187}
188
189/* This macro is only used in snd_uart16550_io_loop */
190inline static void snd_uart16550_buffer_output(snd_uart16550_t *uart)
191{
192 unsigned short buff_out = uart->buff_out;
193 if( uart->buff_in_count > 0 ) {
194 outb(uart->tx_buff[buff_out], uart->base + UART_TX);
195 uart->fifo_count++;
196 buff_out++;
197 buff_out &= TX_BUFF_MASK;
198 uart->buff_out = buff_out;
199 uart->buff_in_count--;
200 }
201}
202
203/* This loop should be called with interrupts disabled
204 * We don't want to interrupt this,
205 * as we're already handling an interrupt
206 */
207static void snd_uart16550_io_loop(snd_uart16550_t * uart)
208{
209 unsigned char c, status;
210 int substream;
211
212 /* recall previous stream */
213 substream = uart->prev_in;
214
215 /* Read Loop */
216 while ((status = inb(uart->base + UART_LSR)) & UART_LSR_DR) {
217 /* while receive data ready */
218 c = inb(uart->base + UART_RX);
219
220 /* keep track of last status byte */
221 if (c & 0x80) {
222 uart->rstatus = c;
223 }
224
225 /* handle stream switch */
226 if (uart->adaptor == SNDRV_SERIAL_GENERIC) {
227 if (uart->rstatus == 0xf5) {
228 if (c <= SNDRV_SERIAL_MAX_INS && c > 0)
229 substream = c - 1;
230 if (c != 0xf5)
231 uart->rstatus = 0; /* prevent future bytes from being interpreted as streams */
232 }
233 else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
234 snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
235 }
236 } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
237 snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
238 }
239
240 if (status & UART_LSR_OE)
241 snd_printk("%s: Overrun on device at 0x%lx\n",
242 uart->rmidi->name, uart->base);
243 }
244
245 /* remember the last stream */
246 uart->prev_in = substream;
247
248 /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not,
249 buffer is never filled. */
250 /* Check write status */
251 if (status & UART_LSR_THRE) {
252 uart->fifo_count = 0;
253 }
254 if (uart->adaptor == SNDRV_SERIAL_MS124W_SA
255 || uart->adaptor == SNDRV_SERIAL_GENERIC) {
256 /* Can't use FIFO, must send only when CTS is true */
257 status = inb(uart->base + UART_MSR);
258 while( (uart->fifo_count == 0) && (status & UART_MSR_CTS) &&
259 (uart->buff_in_count > 0) ) {
260 snd_uart16550_buffer_output(uart);
261 status = inb( uart->base + UART_MSR );
262 }
263 } else {
264 /* Write loop */
265 while (uart->fifo_count < uart->fifo_limit /* Can we write ? */
266 && uart->buff_in_count > 0) /* Do we want to? */
267 snd_uart16550_buffer_output(uart);
268 }
269 if (uart->irq < 0 && uart->buff_in_count > 0)
270 snd_uart16550_add_timer(uart);
271}
272
273/* NOTES ON SERVICING INTERUPTS
274 * ---------------------------
275 * After receiving a interrupt, it is important to indicate to the UART that
276 * this has been done.
277 * For a Rx interrupt, this is done by reading the received byte.
278 * For a Tx interrupt this is done by either:
279 * a) Writing a byte
280 * b) Reading the IIR
281 * It is particularly important to read the IIR if a Tx interrupt is received
282 * when there is no data in tx_buff[], as in this case there no other
283 * indication that the interrupt has been serviced, and it remains outstanding
284 * indefinitely. This has the curious side effect that and no further interrupts
285 * will be generated from this device AT ALL!!.
286 * It is also desirable to clear outstanding interrupts when the device is
287 * opened/closed.
288 *
289 *
290 * Note that some devices need OUT2 to be set before they will generate
291 * interrupts at all. (Possibly tied to an internal pull-up on CTS?)
292 */
293static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id, struct pt_regs *regs)
294{
295 snd_uart16550_t *uart;
296
297 uart = (snd_uart16550_t *) dev_id;
298 spin_lock(&uart->open_lock);
299 if (uart->filemode == SERIAL_MODE_NOT_OPENED) {
300 spin_unlock(&uart->open_lock);
301 return IRQ_NONE;
302 }
303 inb(uart->base + UART_IIR); /* indicate to the UART that the interrupt has been serviced */
304 snd_uart16550_io_loop(uart);
305 spin_unlock(&uart->open_lock);
306 return IRQ_HANDLED;
307}
308
309/* When the polling mode, this function calls snd_uart16550_io_loop. */
310static void snd_uart16550_buffer_timer(unsigned long data)
311{
312 unsigned long flags;
313 snd_uart16550_t *uart;
314
315 uart = (snd_uart16550_t *)data;
316 spin_lock_irqsave(&uart->open_lock, flags);
317 snd_uart16550_del_timer(uart);
318 snd_uart16550_io_loop(uart);
319 spin_unlock_irqrestore(&uart->open_lock, flags);
320}
321
322/*
323 * this method probes, if an uart sits on given port
324 * return 0 if found
325 * return negative error if not found
326 */
327static int __init snd_uart16550_detect(snd_uart16550_t *uart)
328{
329 unsigned long io_base = uart->base;
330 int ok;
331 unsigned char c;
332
333 /* Do some vague tests for the presence of the uart */
334 if (io_base == 0 || io_base == SNDRV_AUTO_PORT) {
335 return -ENODEV; /* Not configured */
336 }
337
338 uart->res_base = request_region(io_base, 8, "Serial MIDI");
339 if (uart->res_base == NULL) {
340 snd_printk(KERN_ERR "u16550: can't grab port 0x%lx\n", io_base);
341 return -EBUSY;
342 }
343
344 ok = 1; /* uart detected unless one of the following tests should fail */
345 /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */
346 outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */
347 c = inb(io_base + UART_IER);
348 /* The top four bits of the IER should always == 0 */
349 if ((c & 0xf0) != 0)
350 ok = 0; /* failed */
351
352 outb(0xaa, io_base + UART_SCR);
353 /* Write arbitrary data into the scratch reg */
354 c = inb(io_base + UART_SCR);
355 /* If it comes back, it's OK */
356 if (c != 0xaa)
357 ok = 0; /* failed */
358
359 outb(0x55, io_base + UART_SCR);
360 /* Write arbitrary data into the scratch reg */
361 c = inb(io_base + UART_SCR);
362 /* If it comes back, it's OK */
363 if (c != 0x55)
364 ok = 0; /* failed */
365
366 return ok;
367}
368
369static void snd_uart16550_do_open(snd_uart16550_t * uart)
370{
371 char byte;
372
373 /* Initialize basic variables */
374 uart->buff_in_count = 0;
375 uart->buff_in = 0;
376 uart->buff_out = 0;
377 uart->fifo_limit = 1;
378 uart->fifo_count = 0;
379 uart->timer_running = 0;
380
381 outb(UART_FCR_ENABLE_FIFO /* Enable FIFO's (if available) */
382 | UART_FCR_CLEAR_RCVR /* Clear receiver FIFO */
383 | UART_FCR_CLEAR_XMIT /* Clear transmitter FIFO */
384 | UART_FCR_TRIGGER_4 /* Set FIFO trigger at 4-bytes */
385 /* NOTE: interrupt generated after T=(time)4-bytes
386 * if less than UART_FCR_TRIGGER bytes received
387 */
388 ,uart->base + UART_FCR); /* FIFO Control Register */
389
390 if ((inb(uart->base + UART_IIR) & 0xf0) == 0xc0)
391 uart->fifo_limit = 16;
392 if (uart->divisor != 0) {
393 uart->old_line_ctrl_reg = inb(uart->base + UART_LCR);
394 outb(UART_LCR_DLAB /* Divisor latch access bit */
395 ,uart->base + UART_LCR); /* Line Control Register */
396 uart->old_divisor_lsb = inb(uart->base + UART_DLL);
397 uart->old_divisor_msb = inb(uart->base + UART_DLM);
398
399 outb(uart->divisor
400 ,uart->base + UART_DLL); /* Divisor Latch Low */
401 outb(0
402 ,uart->base + UART_DLM); /* Divisor Latch High */
403 /* DLAB is reset to 0 in next outb() */
404 }
405 /* Set serial parameters (parity off, etc) */
406 outb(UART_LCR_WLEN8 /* 8 data-bits */
407 | 0 /* 1 stop-bit */
408 | 0 /* parity off */
409 | 0 /* DLAB = 0 */
410 ,uart->base + UART_LCR); /* Line Control Register */
411
412 switch (uart->adaptor) {
413 default:
414 outb(UART_MCR_RTS /* Set Request-To-Send line active */
415 | UART_MCR_DTR /* Set Data-Terminal-Ready line active */
416 | UART_MCR_OUT2 /* Set OUT2 - not always required, but when
417 * it is, it is ESSENTIAL for enabling interrupts
418 */
419 ,uart->base + UART_MCR); /* Modem Control Register */
420 break;
421 case SNDRV_SERIAL_MS124W_SA:
422 case SNDRV_SERIAL_MS124W_MB:
423 /* MS-124W can draw power from RTS and DTR if they
424 are in opposite states. */
425 outb(UART_MCR_RTS | (0&UART_MCR_DTR) | UART_MCR_OUT2,
426 uart->base + UART_MCR);
427 break;
428 case SNDRV_SERIAL_MS124T:
429 /* MS-124T can draw power from RTS and/or DTR (preferably
430 both) if they are both asserted. */
431 outb(UART_MCR_RTS | UART_MCR_DTR | UART_MCR_OUT2,
432 uart->base + UART_MCR);
433 break;
434 }
435
436 if (uart->irq < 0) {
437 byte = (0 & UART_IER_RDI) /* Disable Receiver data interrupt */
438 |(0 & UART_IER_THRI) /* Disable Transmitter holding register empty interrupt */
439 ;
440 } else if (uart->adaptor == SNDRV_SERIAL_MS124W_SA) {
441 byte = UART_IER_RDI /* Enable Receiver data interrupt */
442 | UART_IER_MSI /* Enable Modem status interrupt */
443 ;
444 } else if (uart->adaptor == SNDRV_SERIAL_GENERIC) {
445 byte = UART_IER_RDI /* Enable Receiver data interrupt */
446 | UART_IER_MSI /* Enable Modem status interrupt */
447 | UART_IER_THRI /* Enable Transmitter holding register empty interrupt */
448 ;
449 } else {
450 byte = UART_IER_RDI /* Enable Receiver data interrupt */
451 | UART_IER_THRI /* Enable Transmitter holding register empty interrupt */
452 ;
453 }
454 outb(byte, uart->base + UART_IER); /* Interupt enable Register */
455
456 inb(uart->base + UART_LSR); /* Clear any pre-existing overrun indication */
457 inb(uart->base + UART_IIR); /* Clear any pre-existing transmit interrupt */
458 inb(uart->base + UART_RX); /* Clear any pre-existing receive interrupt */
459}
460
461static void snd_uart16550_do_close(snd_uart16550_t * uart)
462{
463 if (uart->irq < 0)
464 snd_uart16550_del_timer(uart);
465
466 /* NOTE: may need to disable interrupts before de-registering out handler.
467 * For now, the consequences are harmless.
468 */
469
470 outb((0 & UART_IER_RDI) /* Disable Receiver data interrupt */
471 |(0 & UART_IER_THRI) /* Disable Transmitter holding register empty interrupt */
472 ,uart->base + UART_IER); /* Interupt enable Register */
473
474 switch (uart->adaptor) {
475 default:
476 outb((0 & UART_MCR_RTS) /* Deactivate Request-To-Send line */
477 |(0 & UART_MCR_DTR) /* Deactivate Data-Terminal-Ready line */
478 |(0 & UART_MCR_OUT2) /* Deactivate OUT2 */
479 ,uart->base + UART_MCR); /* Modem Control Register */
480 break;
481 case SNDRV_SERIAL_MS124W_SA:
482 case SNDRV_SERIAL_MS124W_MB:
483 /* MS-124W can draw power from RTS and DTR if they
484 are in opposite states; leave it powered. */
485 outb(UART_MCR_RTS | (0&UART_MCR_DTR) | (0&UART_MCR_OUT2),
486 uart->base + UART_MCR);
487 break;
488 case SNDRV_SERIAL_MS124T:
489 /* MS-124T can draw power from RTS and/or DTR (preferably
490 both) if they are both asserted; leave it powered. */
491 outb(UART_MCR_RTS | UART_MCR_DTR | (0&UART_MCR_OUT2),
492 uart->base + UART_MCR);
493 break;
494 }
495
496 inb(uart->base + UART_IIR); /* Clear any outstanding interrupts */
497
498 /* Restore old divisor */
499 if (uart->divisor != 0) {
500 outb(UART_LCR_DLAB /* Divisor latch access bit */
501 ,uart->base + UART_LCR); /* Line Control Register */
502 outb(uart->old_divisor_lsb
503 ,uart->base + UART_DLL); /* Divisor Latch Low */
504 outb(uart->old_divisor_msb
505 ,uart->base + UART_DLM); /* Divisor Latch High */
506 /* Restore old LCR (data bits, stop bits, parity, DLAB) */
507 outb(uart->old_line_ctrl_reg
508 ,uart->base + UART_LCR); /* Line Control Register */
509 }
510}
511
512static int snd_uart16550_input_open(snd_rawmidi_substream_t * substream)
513{
514 unsigned long flags;
515 snd_uart16550_t *uart = substream->rmidi->private_data;
516
517 spin_lock_irqsave(&uart->open_lock, flags);
518 if (uart->filemode == SERIAL_MODE_NOT_OPENED)
519 snd_uart16550_do_open(uart);
520 uart->filemode |= SERIAL_MODE_INPUT_OPEN;
521 uart->midi_input[substream->number] = substream;
522 spin_unlock_irqrestore(&uart->open_lock, flags);
523 return 0;
524}
525
526static int snd_uart16550_input_close(snd_rawmidi_substream_t * substream)
527{
528 unsigned long flags;
529 snd_uart16550_t *uart = substream->rmidi->private_data;
530
531 spin_lock_irqsave(&uart->open_lock, flags);
532 uart->filemode &= ~SERIAL_MODE_INPUT_OPEN;
533 uart->midi_input[substream->number] = NULL;
534 if (uart->filemode == SERIAL_MODE_NOT_OPENED)
535 snd_uart16550_do_close(uart);
536 spin_unlock_irqrestore(&uart->open_lock, flags);
537 return 0;
538}
539
540static void snd_uart16550_input_trigger(snd_rawmidi_substream_t * substream, int up)
541{
542 unsigned long flags;
543 snd_uart16550_t *uart = substream->rmidi->private_data;
544
545 spin_lock_irqsave(&uart->open_lock, flags);
546 if (up) {
547 uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED;
548 } else {
549 uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED;
550 }
551 spin_unlock_irqrestore(&uart->open_lock, flags);
552}
553
554static int snd_uart16550_output_open(snd_rawmidi_substream_t * substream)
555{
556 unsigned long flags;
557 snd_uart16550_t *uart = substream->rmidi->private_data;
558
559 spin_lock_irqsave(&uart->open_lock, flags);
560 if (uart->filemode == SERIAL_MODE_NOT_OPENED)
561 snd_uart16550_do_open(uart);
562 uart->filemode |= SERIAL_MODE_OUTPUT_OPEN;
563 uart->midi_output[substream->number] = substream;
564 spin_unlock_irqrestore(&uart->open_lock, flags);
565 return 0;
566};
567
568static int snd_uart16550_output_close(snd_rawmidi_substream_t * substream)
569{
570 unsigned long flags;
571 snd_uart16550_t *uart = substream->rmidi->private_data;
572
573 spin_lock_irqsave(&uart->open_lock, flags);
574 uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN;
575 uart->midi_output[substream->number] = NULL;
576 if (uart->filemode == SERIAL_MODE_NOT_OPENED)
577 snd_uart16550_do_close(uart);
578 spin_unlock_irqrestore(&uart->open_lock, flags);
579 return 0;
580};
581
582inline static int snd_uart16550_buffer_can_write( snd_uart16550_t *uart, int Num )
583{
584 if( uart->buff_in_count + Num < TX_BUFF_SIZE )
585 return 1;
586 else
587 return 0;
588}
589
590inline static int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte)
591{
592 unsigned short buff_in = uart->buff_in;
593 if( uart->buff_in_count < TX_BUFF_SIZE ) {
594 uart->tx_buff[buff_in] = byte;
595 buff_in++;
596 buff_in &= TX_BUFF_MASK;
597 uart->buff_in = buff_in;
598 uart->buff_in_count++;
599 if (uart->irq < 0) /* polling mode */
600 snd_uart16550_add_timer(uart);
601 return 1;
602 } else
603 return 0;
604}
605
606static int snd_uart16550_output_byte(snd_uart16550_t *uart, snd_rawmidi_substream_t * substream, unsigned char midi_byte)
607{
608 if (uart->buff_in_count == 0 /* Buffer empty? */
609 && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA &&
610 uart->adaptor != SNDRV_SERIAL_GENERIC) ||
611 (uart->fifo_count == 0 /* FIFO empty? */
612 && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */
613
614 /* Tx Buffer Empty - try to write immediately */
615 if ((inb(uart->base + UART_LSR) & UART_LSR_THRE) != 0) {
616 /* Transmitter holding register (and Tx FIFO) empty */
617 uart->fifo_count = 1;
618 outb(midi_byte, uart->base + UART_TX);
619 } else {
620 if (uart->fifo_count < uart->fifo_limit) {
621 uart->fifo_count++;
622 outb(midi_byte, uart->base + UART_TX);
623 } else {
624 /* Cannot write (buffer empty) - put char in buffer */
625 snd_uart16550_write_buffer(uart, midi_byte);
626 }
627 }
628 } else {
629 if( !snd_uart16550_write_buffer(uart, midi_byte) ) {
630 snd_printk("%s: Buffer overrun on device at 0x%lx\n",
631 uart->rmidi->name, uart->base);
632 return 0;
633 }
634 }
635
636 return 1;
637}
638
639static void snd_uart16550_output_write(snd_rawmidi_substream_t * substream)
640{
641 unsigned long flags;
642 unsigned char midi_byte, addr_byte;
643 snd_uart16550_t *uart = substream->rmidi->private_data;
644 char first;
645 static unsigned long lasttime=0;
646
647 /* Interupts are disabled during the updating of the tx_buff,
648 * since it is 'bad' to have two processes updating the same
649 * variables (ie buff_in & buff_out)
650 */
651
652 spin_lock_irqsave(&uart->open_lock, flags);
653
654 if (uart->irq < 0) //polling
655 snd_uart16550_io_loop(uart);
656
657 if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) {
658 while (1) {
659 /* buffer full? */
660 /* in this mode we need two bytes of space */
661 if (uart->buff_in_count > TX_BUFF_SIZE - 2)
662 break;
663 if (snd_rawmidi_transmit(substream, &midi_byte, 1) != 1)
664 break;
665#ifdef SNDRV_SERIAL_MS124W_MB_NOCOMBO
666 /* select exactly one of the four ports */
667 addr_byte = (1 << (substream->number + 4)) | 0x08;
668#else
669 /* select any combination of the four ports */
670 addr_byte = (substream->number << 4) | 0x08;
671 /* ...except none */
672 if (addr_byte == 0x08) addr_byte = 0xf8;
673#endif
674 snd_uart16550_output_byte(uart, substream, addr_byte);
675 /* send midi byte */
676 snd_uart16550_output_byte(uart, substream, midi_byte);
677 }
678 } else {
679 first = 0;
680 while( 1 == snd_rawmidi_transmit_peek(substream, &midi_byte, 1) ) {
681 /* Also send F5 after 3 seconds with no data to handle device disconnect */
682 if (first == 0 && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS ||
683 uart->adaptor == SNDRV_SERIAL_GENERIC) &&
684 (uart->prev_out != substream->number || jiffies-lasttime > 3*HZ)) {
685
686 if( snd_uart16550_buffer_can_write( uart, 3 ) ) {
687 /* Roland Soundcanvas part selection */
688 /* If this substream of the data is different previous
689 substream in this uart, send the change part event */
690 uart->prev_out = substream->number;
691 /* change part */
692 snd_uart16550_output_byte(uart, substream, 0xf5);
693 /* data */
694 snd_uart16550_output_byte(uart, substream, uart->prev_out + 1);
695 /* If midi_byte is a data byte, send the previous status byte */
696 if ((midi_byte < 0x80) && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS))
697 snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]);
698 } else if( !uart->drop_on_full )
699 break;
700
701 }
702
703 /* send midi byte */
704 if( !snd_uart16550_output_byte(uart, substream, midi_byte) && !uart->drop_on_full )
705 break;
706
707 if (midi_byte >= 0x80 && midi_byte < 0xf0)
708 uart->prev_status[uart->prev_out] = midi_byte;
709 first = 1;
710
711 snd_rawmidi_transmit_ack( substream, 1 );
712 }
713 lasttime = jiffies;
714 }
715 spin_unlock_irqrestore(&uart->open_lock, flags);
716}
717
718static void snd_uart16550_output_trigger(snd_rawmidi_substream_t * substream, int up)
719{
720 unsigned long flags;
721 snd_uart16550_t *uart = substream->rmidi->private_data;
722
723 spin_lock_irqsave(&uart->open_lock, flags);
724 if (up) {
725 uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED;
726 } else {
727 uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED;
728 }
729 spin_unlock_irqrestore(&uart->open_lock, flags);
730 if (up)
731 snd_uart16550_output_write(substream);
732}
733
734static snd_rawmidi_ops_t snd_uart16550_output =
735{
736 .open = snd_uart16550_output_open,
737 .close = snd_uart16550_output_close,
738 .trigger = snd_uart16550_output_trigger,
739};
740
741static snd_rawmidi_ops_t snd_uart16550_input =
742{
743 .open = snd_uart16550_input_open,
744 .close = snd_uart16550_input_close,
745 .trigger = snd_uart16550_input_trigger,
746};
747
748static int snd_uart16550_free(snd_uart16550_t *uart)
749{
750 if (uart->irq >= 0)
751 free_irq(uart->irq, (void *)uart);
752 if (uart->res_base) {
753 release_resource(uart->res_base);
754 kfree_nocheck(uart->res_base);
755 }
756 kfree(uart);
757 return 0;
758};
759
760static int snd_uart16550_dev_free(snd_device_t *device)
761{
762 snd_uart16550_t *uart = device->device_data;
763 return snd_uart16550_free(uart);
764}
765
766static int __init snd_uart16550_create(snd_card_t * card,
767 unsigned long iobase,
768 int irq,
769 unsigned int speed,
770 unsigned int base,
771 int adaptor,
772 int droponfull,
773 snd_uart16550_t **ruart)
774{
775 static snd_device_ops_t ops = {
776 .dev_free = snd_uart16550_dev_free,
777 };
778 snd_uart16550_t *uart;
779 int err;
780
781
782 if ((uart = kcalloc(1, sizeof(*uart), GFP_KERNEL)) == NULL)
783 return -ENOMEM;
784 uart->adaptor = adaptor;
785 uart->card = card;
786 spin_lock_init(&uart->open_lock);
787 uart->irq = -1;
788 uart->base = iobase;
789 uart->drop_on_full = droponfull;
790
791 if ((err = snd_uart16550_detect(uart)) <= 0) {
792 printk(KERN_ERR "no UART detected at 0x%lx\n", iobase);
793 return err;
794 }
795
796 if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
797 if (request_irq(irq, snd_uart16550_interrupt,
798 SA_INTERRUPT, "Serial MIDI", (void *) uart)) {
799 snd_printk("irq %d busy. Using Polling.\n", irq);
800 } else {
801 uart->irq = irq;
802 }
803 }
804 uart->divisor = base / speed;
805 uart->speed = base / (unsigned int)uart->divisor;
806 uart->speed_base = base;
807 uart->prev_out = -1;
808 uart->prev_in = 0;
809 uart->rstatus = 0;
810 memset(uart->prev_status, 0x80, sizeof(unsigned char) * SNDRV_SERIAL_MAX_OUTS);
811 init_timer(&uart->buffer_timer);
812 uart->buffer_timer.function = snd_uart16550_buffer_timer;
813 uart->buffer_timer.data = (unsigned long)uart;
814 uart->timer_running = 0;
815
816 /* Register device */
817 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, uart, &ops)) < 0) {
818 snd_uart16550_free(uart);
819 return err;
820 }
821
822 switch (uart->adaptor) {
823 case SNDRV_SERIAL_MS124W_SA:
824 case SNDRV_SERIAL_MS124W_MB:
825 /* MS-124W can draw power from RTS and DTR if they
826 are in opposite states. */
827 outb(UART_MCR_RTS | (0&UART_MCR_DTR), uart->base + UART_MCR);
828 break;
829 case SNDRV_SERIAL_MS124T:
830 /* MS-124T can draw power from RTS and/or DTR (preferably
831 both) if they are asserted. */
832 outb(UART_MCR_RTS | UART_MCR_DTR, uart->base + UART_MCR);
833 break;
834 default:
835 break;
836 }
837
838 if (ruart)
839 *ruart = uart;
840
841 return 0;
842}
843
844static void __init snd_uart16550_substreams(snd_rawmidi_str_t *stream)
845{
846 struct list_head *list;
847
848 list_for_each(list, &stream->substreams) {
849 snd_rawmidi_substream_t *substream = list_entry(list, snd_rawmidi_substream_t, list);
850 sprintf(substream->name, "Serial MIDI %d", substream->number + 1);
851 }
852}
853
854static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, snd_rawmidi_t **rmidi)
855{
856 snd_rawmidi_t *rrawmidi;
857 int err;
858
859 if ((err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, outs, ins, &rrawmidi)) < 0)
860 return err;
861 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input);
862 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output);
863 strcpy(rrawmidi->name, "Serial MIDI");
864 snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
865 snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);
866 rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
867 SNDRV_RAWMIDI_INFO_INPUT |
868 SNDRV_RAWMIDI_INFO_DUPLEX;
869 rrawmidi->private_data = uart;
870 if (rmidi)
871 *rmidi = rrawmidi;
872 return 0;
873}
874
875static int __init snd_serial_probe(int dev)
876{
877 snd_card_t *card;
878 snd_uart16550_t *uart;
879 int err;
880
881 if (!enable[dev])
882 return -ENOENT;
883
884 switch (adaptor[dev]) {
885 case SNDRV_SERIAL_SOUNDCANVAS:
886 ins[dev] = 1;
887 break;
888 case SNDRV_SERIAL_MS124T:
889 case SNDRV_SERIAL_MS124W_SA:
890 outs[dev] = 1;
891 ins[dev] = 1;
892 break;
893 case SNDRV_SERIAL_MS124W_MB:
894 outs[dev] = 16;
895 ins[dev] = 1;
896 break;
897 case SNDRV_SERIAL_GENERIC:
898 break;
899 default:
900 snd_printk("Adaptor type is out of range 0-%d (%d)\n",
901 SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]);
902 return -ENODEV;
903 }
904
905 if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) {
906 snd_printk("Count of outputs is out of range 1-%d (%d)\n",
907 SNDRV_SERIAL_MAX_OUTS, outs[dev]);
908 return -ENODEV;
909 }
910
911 if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) {
912 snd_printk("Count of inputs is out of range 1-%d (%d)\n",
913 SNDRV_SERIAL_MAX_INS, ins[dev]);
914 return -ENODEV;
915 }
916
917 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
918 if (card == NULL)
919 return -ENOMEM;
920
921 strcpy(card->driver, "Serial");
922 strcpy(card->shortname, "Serial MIDI (UART16550A)");
923
924 if ((err = snd_uart16550_create(card,
925 port[dev],
926 irq[dev],
927 speed[dev],
928 base[dev],
929 adaptor[dev],
930 droponfull[dev],
931 &uart)) < 0) {
932 snd_card_free(card);
933 return err;
934 }
935
936 if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0) {
937 snd_card_free(card);
938 return err;
939 }
940
941 sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d",
942 card->shortname,
943 uart->base,
944 uart->irq,
945 uart->speed,
946 (int)uart->divisor,
947 outs[dev],
948 ins[dev],
949 adaptor_names[uart->adaptor],
950 uart->drop_on_full);
951
952 if ((err = snd_card_register(card)) < 0) {
953 snd_card_free(card);
954 return err;
955 }
956 snd_serial_cards[dev] = card;
957 return 0;
958}
959
960static int __init alsa_card_serial_init(void)
961{
962 int dev = 0;
963 int cards = 0;
964
965 for (dev = 0; dev < SNDRV_CARDS; dev++) {
966 if (snd_serial_probe(dev) == 0)
967 cards++;
968 }
969
970 if (cards == 0) {
971#ifdef MODULE
972 printk(KERN_ERR "serial midi soundcard not found or device busy\n");
973#endif
974 return -ENODEV;
975 }
976 return 0;
977}
978
979static void __exit alsa_card_serial_exit(void)
980{
981 int dev;
982
983 for (dev = 0; dev < SNDRV_CARDS; dev++) {
984 if (snd_serial_cards[dev] != NULL)
985 snd_card_free(snd_serial_cards[dev]);
986 }
987}
988
989module_init(alsa_card_serial_init)
990module_exit(alsa_card_serial_exit)
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
new file mode 100644
index 000000000000..5937711e9505
--- /dev/null
+++ b/sound/drivers/virmidi.c
@@ -0,0 +1,159 @@
1/*
2 * Dummy soundcard for virtual rawmidi devices
3 *
4 * Copyright (c) 2000 by Takashi Iwai <tiwai@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22/*
23 * VIRTUAL RAW MIDI DEVICE CARDS
24 *
25 * This dummy card contains up to 4 virtual rawmidi devices.
26 * They are not real rawmidi devices but just associated with sequencer
27 * clients, so that any input/output sources can be connected as a raw
28 * MIDI device arbitrary.
29 * Also, multiple access is allowed to a single rawmidi device.
30 *
31 * Typical usage is like following:
32 * - Load snd-virmidi module.
33 * # modprobe snd-virmidi index=2
34 * Then, sequencer clients 72:0 to 75:0 will be created, which are
35 * mapped from /dev/snd/midiC1D0 to /dev/snd/midiC1D3, respectively.
36 *
37 * - Connect input/output via aconnect.
38 * % aconnect 64:0 72:0 # keyboard input redirection 64:0 -> 72:0
39 * % aconnect 72:0 65:0 # output device redirection 72:0 -> 65:0
40 *
41 * - Run application using a midi device (eg. /dev/snd/midiC1D0)
42 */
43
44#include <sound/driver.h>
45#include <linux/init.h>
46#include <linux/wait.h>
47#include <linux/sched.h>
48#include <linux/moduleparam.h>
49#include <sound/core.h>
50#include <sound/seq_kernel.h>
51#include <sound/seq_virmidi.h>
52#include <sound/initval.h>
53
54/* hack: OSS defines midi_devs, so undefine it (versioned symbols) */
55#undef midi_devs
56
57MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
58MODULE_DESCRIPTION("Dummy soundcard for virtual rawmidi devices");
59MODULE_LICENSE("GPL");
60MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual rawmidi device}}");
61
62#define MAX_MIDI_DEVICES 8
63
64static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
65static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
66static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
67static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
68
69module_param_array(index, int, NULL, 0444);
70MODULE_PARM_DESC(index, "Index value for virmidi soundcard.");
71module_param_array(id, charp, NULL, 0444);
72MODULE_PARM_DESC(id, "ID string for virmidi soundcard.");
73module_param_array(enable, bool, NULL, 0444);
74MODULE_PARM_DESC(enable, "Enable this soundcard.");
75module_param_array(midi_devs, int, NULL, 0444);
76MODULE_PARM_DESC(midi_devs, "MIDI devices # (1-8)");
77
78typedef struct snd_card_virmidi {
79 snd_card_t *card;
80 snd_rawmidi_t *midi[MAX_MIDI_DEVICES];
81} snd_card_virmidi_t;
82
83static snd_card_t *snd_virmidi_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
84
85
86static int __init snd_card_virmidi_probe(int dev)
87{
88 snd_card_t *card;
89 struct snd_card_virmidi *vmidi;
90 int idx, err;
91
92 if (!enable[dev])
93 return -ENODEV;
94 card = snd_card_new(index[dev], id[dev], THIS_MODULE,
95 sizeof(struct snd_card_virmidi));
96 if (card == NULL)
97 return -ENOMEM;
98 vmidi = (struct snd_card_virmidi *)card->private_data;
99 vmidi->card = card;
100
101 if (midi_devs[dev] > MAX_MIDI_DEVICES) {
102 snd_printk("too much midi devices for virmidi %d: force to use %d\n", dev, MAX_MIDI_DEVICES);
103 midi_devs[dev] = MAX_MIDI_DEVICES;
104 }
105 for (idx = 0; idx < midi_devs[dev]; idx++) {
106 snd_rawmidi_t *rmidi;
107 snd_virmidi_dev_t *rdev;
108 if ((err = snd_virmidi_new(card, idx, &rmidi)) < 0)
109 goto __nodev;
110 rdev = rmidi->private_data;
111 vmidi->midi[idx] = rmidi;
112 strcpy(rmidi->name, "Virtual Raw MIDI");
113 rdev->seq_mode = SNDRV_VIRMIDI_SEQ_DISPATCH;
114 }
115
116 strcpy(card->driver, "VirMIDI");
117 strcpy(card->shortname, "VirMIDI");
118 sprintf(card->longname, "Virtual MIDI Card %i", dev + 1);
119 if ((err = snd_card_register(card)) == 0) {
120 snd_virmidi_cards[dev] = card;
121 return 0;
122 }
123 __nodev:
124 snd_card_free(card);
125 return err;
126}
127
128static int __init alsa_card_virmidi_init(void)
129{
130 int dev, cards;
131
132 for (dev = cards = 0; dev < SNDRV_CARDS && enable[dev]; dev++) {
133 if (snd_card_virmidi_probe(dev) < 0) {
134#ifdef MODULE
135 printk(KERN_ERR "Card-VirMIDI #%i not found or device busy\n", dev + 1);
136#endif
137 break;
138 }
139 cards++;
140 }
141 if (!cards) {
142#ifdef MODULE
143 printk(KERN_ERR "Card-VirMIDI soundcard not found or device busy\n");
144#endif
145 return -ENODEV;
146 }
147 return 0;
148}
149
150static void __exit alsa_card_virmidi_exit(void)
151{
152 int dev;
153
154 for (dev = 0; dev < SNDRV_CARDS; dev++)
155 snd_card_free(snd_virmidi_cards[dev]);
156}
157
158module_init(alsa_card_virmidi_init)
159module_exit(alsa_card_virmidi_exit)
diff --git a/sound/drivers/vx/Makefile b/sound/drivers/vx/Makefile
new file mode 100644
index 000000000000..269bd8544a5d
--- /dev/null
+++ b/sound/drivers/vx/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4#
5
6snd-vx-lib-objs := vx_core.o vx_hwdep.o vx_pcm.o vx_mixer.o vx_cmd.o vx_uer.o
7
8obj-$(CONFIG_SND_VX_LIB) += snd-vx-lib.o
diff --git a/sound/drivers/vx/vx_cmd.c b/sound/drivers/vx/vx_cmd.c
new file mode 100644
index 000000000000..7a221349f285
--- /dev/null
+++ b/sound/drivers/vx/vx_cmd.c
@@ -0,0 +1,109 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * DSP commands
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/vx_core.h>
27#include "vx_cmd.h"
28
29/*
30 * Array of DSP commands
31 */
32static struct vx_cmd_info vx_dsp_cmds[] = {
33[CMD_VERSION] = { 0x010000, 2, RMH_SSIZE_FIXED, 1 },
34[CMD_SUPPORTED] = { 0x020000, 1, RMH_SSIZE_FIXED, 2 },
35[CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED, 1 },
36[CMD_SEND_IRQA] = { 0x070001, 1, RMH_SSIZE_FIXED, 0 },
37[CMD_IBL] = { 0x080000, 1, RMH_SSIZE_FIXED, 4 },
38[CMD_ASYNC] = { 0x0A0000, 1, RMH_SSIZE_ARG, 0 },
39[CMD_RES_PIPE] = { 0x400000, 1, RMH_SSIZE_FIXED, 0 },
40[CMD_FREE_PIPE] = { 0x410000, 1, RMH_SSIZE_FIXED, 0 },
41[CMD_CONF_PIPE] = { 0x42A101, 2, RMH_SSIZE_FIXED, 0 },
42[CMD_ABORT_CONF_PIPE] = { 0x42A100, 2, RMH_SSIZE_FIXED, 0 },
43[CMD_PARAM_OUTPUT_PIPE] = { 0x43A000, 2, RMH_SSIZE_FIXED, 0 },
44[CMD_STOP_PIPE] = { 0x470004, 1, RMH_SSIZE_FIXED, 0 },
45[CMD_PIPE_STATE] = { 0x480000, 1, RMH_SSIZE_FIXED, 1 },
46[CMD_PIPE_SPL_COUNT] = { 0x49A000, 2, RMH_SSIZE_FIXED, 2 },
47[CMD_CAN_START_PIPE] = { 0x4b0000, 1, RMH_SSIZE_FIXED, 1 },
48[CMD_SIZE_HBUFFER] = { 0x4C0000, 1, RMH_SSIZE_FIXED, 1 },
49[CMD_START_STREAM] = { 0x80A000, 2, RMH_SSIZE_FIXED, 0 },
50[CMD_START_ONE_STREAM] = { 0x800000, 1, RMH_SSIZE_FIXED, 0 },
51[CMD_PAUSE_STREAM] = { 0x81A000, 2, RMH_SSIZE_FIXED, 0 },
52[CMD_PAUSE_ONE_STREAM] = { 0x810000, 1, RMH_SSIZE_FIXED, 0 },
53[CMD_STREAM_OUT_LEVEL_ADJUST] = { 0x828000, 2, RMH_SSIZE_FIXED, 0 },
54[CMD_STOP_STREAM] = { 0x830000, 1, RMH_SSIZE_FIXED, 0 },
55[CMD_FORMAT_STREAM_OUT] = { 0x868000, 1, RMH_SSIZE_FIXED, 0 },
56[CMD_FORMAT_STREAM_IN] = { 0x878800, 1, RMH_SSIZE_FIXED, 0 },
57[CMD_GET_STREAM_STATE] = { 0x890001, 2, RMH_SSIZE_FIXED, 1 },
58[CMD_DROP_BYTES_AWAY] = { 0x8A8000, 2, RMH_SSIZE_FIXED, 0 },
59[CMD_GET_REMAINING_BYTES] = { 0x8D0800, 1, RMH_SSIZE_FIXED, 2 },
60[CMD_CONNECT_AUDIO] = { 0xC10000, 1, RMH_SSIZE_FIXED, 0 },
61[CMD_AUDIO_LEVEL_ADJUST] = { 0xC2A000, 3, RMH_SSIZE_FIXED, 0 },
62[CMD_AUDIO_VU_PIC_METER] = { 0xC3A003, 2, RMH_SSIZE_FIXED, 1 },
63[CMD_GET_AUDIO_LEVELS] = { 0xC4A000, 2, RMH_SSIZE_FIXED, 0 },
64[CMD_GET_NOTIFY_EVENT] = { 0x4D0000, 1, RMH_SSIZE_ARG, 0 },
65[CMD_INFO_NOTIFIED] = { 0x0B0000, 1, RMH_SSIZE_FIXED, 2 },
66[CMD_ACCESS_IO_FCT] = { 0x098000, 1, RMH_SSIZE_ARG, 0 },
67[CMD_STATUS_R_BUFFERS] = { 0x440000, 1, RMH_SSIZE_ARG, 0 },
68[CMD_UPDATE_R_BUFFERS] = { 0x848000, 4, RMH_SSIZE_FIXED, 0 },
69[CMD_LOAD_EFFECT_CONTEXT] = { 0x0c8000, 3, RMH_SSIZE_FIXED, 1 },
70[CMD_EFFECT_ONE_PIPE] = { 0x458000, 0, RMH_SSIZE_FIXED, 0 },
71[CMD_MODIFY_CLOCK] = { 0x0d0000, 1, RMH_SSIZE_FIXED, 0 },
72[CMD_STREAM1_OUT_SET_N_LEVELS] ={ 0x858000, 3, RMH_SSIZE_FIXED, 0 },
73[CMD_PURGE_STREAM_DCMDS] = { 0x8b8000, 3, RMH_SSIZE_FIXED, 0 },
74[CMD_NOTIFY_PIPE_TIME] = { 0x4e0000, 1, RMH_SSIZE_FIXED, 0 },
75[CMD_LOAD_EFFECT_CONTEXT_PACKET] = { 0x0c8000, 1, RMH_SSIZE_FIXED, 0 },
76[CMD_RELIC_R_BUFFER] = { 0x8e0800, 1, RMH_SSIZE_FIXED, 1 },
77[CMD_RESYNC_AUDIO_INPUTS] = { 0x0e0000, 1, RMH_SSIZE_FIXED, 0 },
78[CMD_NOTIFY_STREAM_TIME] = { 0x8f0000, 1, RMH_SSIZE_FIXED, 0 },
79[CMD_STREAM_SAMPLE_COUNT] = { 0x900000, 1, RMH_SSIZE_FIXED, 2 },
80[CMD_CONFIG_TIME_CODE] = { 0x050000, 2, RMH_SSIZE_FIXED, 0 },
81[CMD_GET_TIME_CODE] = { 0x060000, 1, RMH_SSIZE_FIXED, 5 },
82[CMD_MANAGE_SIGNAL] = { 0x0f0000, 1, RMH_SSIZE_FIXED, 0 },
83[CMD_PARAMETER_STREAM_OUT] = { 0x91A000, 3, RMH_SSIZE_FIXED, 0 },
84[CMD_READ_BOARD_FREQ] = { 0x030000, 1, RMH_SSIZE_FIXED, 2 },
85[CMD_GET_STREAM_LEVELS] = { 0x8c0000, 1, RMH_SSIZE_FIXED, 3 },
86[CMD_PURGE_PIPE_DCMDS] = { 0x4f8000, 3, RMH_SSIZE_FIXED, 0 },
87// [CMD_SET_STREAM_OUT_EFFECTS] = { 0x888000, 34, RMH_SSIZE_FIXED, 0 },
88// [CMD_GET_STREAM_OUT_EFFECTS] = { 0x928000, 2, RMH_SSIZE_FIXED, 32 },
89[CMD_CONNECT_MONITORING] = { 0xC00000, 1, RMH_SSIZE_FIXED, 0 },
90[CMD_STREAM2_OUT_SET_N_LEVELS] = { 0x938000, 3, RMH_SSIZE_FIXED, 0 },
91[CMD_CANCEL_R_BUFFERS] = { 0x948000, 4, RMH_SSIZE_FIXED, 0 },
92[CMD_NOTIFY_END_OF_BUFFER] = { 0x950000, 1, RMH_SSIZE_FIXED, 0 },
93[CMD_GET_STREAM_VU_METER] = { 0x95A000, 2, RMH_SSIZE_ARG, 0 },
94};
95
96/**
97 * vx_init_rmh - initialize the RMH instance
98 * @rmh: the rmh pointer to be initialized
99 * @cmd: the rmh command to be set
100 */
101void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd)
102{
103 snd_assert(cmd < CMD_LAST_INDEX, return);
104 rmh->LgCmd = vx_dsp_cmds[cmd].length;
105 rmh->LgStat = vx_dsp_cmds[cmd].st_length;
106 rmh->DspStat = vx_dsp_cmds[cmd].st_type;
107 rmh->Cmd[0] = vx_dsp_cmds[cmd].opcode;
108}
109
diff --git a/sound/drivers/vx/vx_cmd.h b/sound/drivers/vx/vx_cmd.h
new file mode 100644
index 000000000000..a85248ba3cc5
--- /dev/null
+++ b/sound/drivers/vx/vx_cmd.h
@@ -0,0 +1,246 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * Definitions of DSP commands
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
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#ifndef __VX_CMD_H
24#define __VX_CMD_H
25
26enum {
27 CMD_VERSION,
28 CMD_SUPPORTED,
29 CMD_TEST_IT,
30 CMD_SEND_IRQA,
31 CMD_IBL,
32 CMD_ASYNC,
33 CMD_RES_PIPE,
34 CMD_FREE_PIPE,
35 CMD_CONF_PIPE,
36 CMD_ABORT_CONF_PIPE,
37 CMD_PARAM_OUTPUT_PIPE,
38 CMD_STOP_PIPE,
39 CMD_PIPE_STATE,
40 CMD_PIPE_SPL_COUNT,
41 CMD_CAN_START_PIPE,
42 CMD_SIZE_HBUFFER,
43 CMD_START_STREAM,
44 CMD_START_ONE_STREAM,
45 CMD_PAUSE_STREAM,
46 CMD_PAUSE_ONE_STREAM,
47 CMD_STREAM_OUT_LEVEL_ADJUST,
48 CMD_STOP_STREAM,
49 CMD_FORMAT_STREAM_OUT,
50 CMD_FORMAT_STREAM_IN,
51 CMD_GET_STREAM_STATE,
52 CMD_DROP_BYTES_AWAY,
53 CMD_GET_REMAINING_BYTES,
54 CMD_CONNECT_AUDIO,
55 CMD_AUDIO_LEVEL_ADJUST,
56 CMD_AUDIO_VU_PIC_METER,
57 CMD_GET_AUDIO_LEVELS,
58 CMD_GET_NOTIFY_EVENT,
59 CMD_INFO_NOTIFIED,
60 CMD_ACCESS_IO_FCT,
61 CMD_STATUS_R_BUFFERS,
62 CMD_UPDATE_R_BUFFERS,
63 CMD_LOAD_EFFECT_CONTEXT,
64 CMD_EFFECT_ONE_PIPE,
65 CMD_MODIFY_CLOCK,
66 CMD_STREAM1_OUT_SET_N_LEVELS,
67 CMD_PURGE_STREAM_DCMDS,
68 CMD_NOTIFY_PIPE_TIME,
69 CMD_LOAD_EFFECT_CONTEXT_PACKET,
70 CMD_RELIC_R_BUFFER,
71 CMD_RESYNC_AUDIO_INPUTS,
72 CMD_NOTIFY_STREAM_TIME,
73 CMD_STREAM_SAMPLE_COUNT,
74 CMD_CONFIG_TIME_CODE,
75 CMD_GET_TIME_CODE,
76 CMD_MANAGE_SIGNAL,
77 CMD_PARAMETER_STREAM_OUT,
78 CMD_READ_BOARD_FREQ,
79 CMD_GET_STREAM_LEVELS,
80 CMD_PURGE_PIPE_DCMDS,
81 // CMD_SET_STREAM_OUT_EFFECTS,
82 // CMD_GET_STREAM_OUT_EFFECTS,
83 CMD_CONNECT_MONITORING,
84 CMD_STREAM2_OUT_SET_N_LEVELS,
85 CMD_CANCEL_R_BUFFERS,
86 CMD_NOTIFY_END_OF_BUFFER,
87 CMD_GET_STREAM_VU_METER,
88 CMD_LAST_INDEX
89};
90
91struct vx_cmd_info {
92 unsigned int opcode; /* command word */
93 int length; /* command length (in words) */
94 int st_type; /* status type (RMH_SSIZE_XXX) */
95 int st_length; /* fixed length */
96};
97
98/* Family and code op of some DSP requests. */
99#define CODE_OP_PIPE_TIME 0x004e0000
100#define CODE_OP_START_STREAM 0x00800000
101#define CODE_OP_PAUSE_STREAM 0x00810000
102#define CODE_OP_OUT_STREAM_LEVEL 0x00820000
103#define CODE_OP_UPDATE_R_BUFFERS 0x00840000
104#define CODE_OP_OUT_STREAM1_LEVEL_CURVE 0x00850000
105#define CODE_OP_OUT_STREAM2_LEVEL_CURVE 0x00930000
106#define CODE_OP_OUT_STREAM_FORMAT 0x00860000
107#define CODE_OP_STREAM_TIME 0x008f0000
108#define CODE_OP_OUT_STREAM_EXTRAPARAMETER 0x00910000
109#define CODE_OP_OUT_AUDIO_LEVEL 0x00c20000
110
111#define NOTIFY_LAST_COMMAND 0x00400000
112
113/* Values for a user delay */
114#define DC_DIFFERED_DELAY (1<<BIT_DIFFERED_COMMAND)
115#define DC_NOTIFY_DELAY (1<<BIT_NOTIFIED_COMMAND)
116#define DC_HBUFFER_DELAY (1<<BIT_TIME_RELATIVE_TO_BUFFER)
117#define DC_MULTIPLE_DELAY (1<<BIT_RESERVED)
118#define DC_STREAM_TIME_DELAY (1<<BIT_STREAM_TIME)
119#define DC_CANCELLED_DELAY (1<<BIT_CANCELLED_COMMAND)
120
121/* Values for tiDelayed field in TIME_INFO structure,
122 * and for pbPause field in PLAY_BUFFER_INFO structure
123 */
124#define BIT_DIFFERED_COMMAND 0
125#define BIT_NOTIFIED_COMMAND 1
126#define BIT_TIME_RELATIVE_TO_BUFFER 2
127#define BIT_RESERVED 3
128#define BIT_STREAM_TIME 4
129#define BIT_CANCELLED_COMMAND 5
130
131/* Access to the "Size" field of the response of the CMD_GET_NOTIFY_EVENT request. */
132#define GET_NOTIFY_EVENT_SIZE_FIELD_MASK 0x000000ff
133
134/* DSP commands general masks */
135#define OPCODE_MASK 0x00ff0000
136#define DSP_DIFFERED_COMMAND_MASK 0x0000C000
137
138/* Notifications (NOTIFY_INFO) */
139#define ALL_CMDS_NOTIFIED 0x0000 // reserved
140#define START_STREAM_NOTIFIED 0x0001
141#define PAUSE_STREAM_NOTIFIED 0x0002
142#define OUT_STREAM_LEVEL_NOTIFIED 0x0003
143#define OUT_STREAM_PARAMETER_NOTIFIED 0x0004 // left for backward compatibility
144#define OUT_STREAM_FORMAT_NOTIFIED 0x0004
145#define PIPE_TIME_NOTIFIED 0x0005
146#define OUT_AUDIO_LEVEL_NOTIFIED 0x0006
147#define OUT_STREAM_LEVEL_CURVE_NOTIFIED 0x0007
148#define STREAM_TIME_NOTIFIED 0x0008
149#define OUT_STREAM_EXTRAPARAMETER_NOTIFIED 0x0009
150#define UNKNOWN_COMMAND_NOTIFIED 0xffff
151
152/* Output pipe parameters setting */
153#define MASK_VALID_PIPE_MPEG_PARAM 0x000040
154#define MASK_VALID_PIPE_BACKWARD_PARAM 0x000020
155#define MASK_SET_PIPE_MPEG_PARAM 0x000002
156#define MASK_SET_PIPE_BACKWARD_PARAM 0x000001
157
158#define MASK_DSP_WORD 0x00FFFFFF
159#define MASK_ALL_STREAM 0x00FFFFFF
160#define MASK_DSP_WORD_LEVEL 0x000001FF
161#define MASK_FIRST_FIELD 0x0000001F
162#define FIELD_SIZE 5
163
164#define COMMAND_RECORD_MASK 0x000800
165
166/* PipeManagement definition bits (PIPE_DECL_INFO) */
167#define P_UNDERRUN_SKIP_SOUND_MASK 0x01
168#define P_PREPARE_FOR_MPEG3_MASK 0x02
169#define P_DO_NOT_RESET_ANALOG_LEVELS 0x04
170#define P_ALLOW_UNDER_ALLOCATION_MASK 0x08
171#define P_DATA_MODE_MASK 0x10
172#define P_ASIO_BUFFER_MANAGEMENT_MASK 0x20
173
174#define BIT_SKIP_SOUND 0x08 // bit 3
175#define BIT_DATA_MODE 0x10 // bit 4
176
177/* Bits in the CMD_MODIFY_CLOCK request. */
178#define CMD_MODIFY_CLOCK_FD_BIT 0x00000001
179#define CMD_MODIFY_CLOCK_T_BIT 0x00000002
180#define CMD_MODIFY_CLOCK_S_BIT 0x00000004
181
182/* Access to the results of the CMD_GET_TIME_CODE RMH. */
183#define TIME_CODE_V_MASK 0x00800000
184#define TIME_CODE_N_MASK 0x00400000
185#define TIME_CODE_B_MASK 0x00200000
186#define TIME_CODE_W_MASK 0x00100000
187
188/* Values for the CMD_MANAGE_SIGNAL RMH. */
189#define MANAGE_SIGNAL_TIME_CODE 0x01
190#define MANAGE_SIGNAL_MIDI 0x02
191
192/* Values for the CMD_CONFIG_TIME_CODE RMH. */
193#define CONFIG_TIME_CODE_CANCEL 0x00001000
194
195/* Mask to get only the effective time from the
196 * high word out of the 2 returned by the DSP
197 */
198#define PCX_TIME_HI_MASK 0x000fffff
199
200/* Values for setting a H-Buffer time */
201#define HBUFFER_TIME_HIGH 0x00200000
202#define HBUFFER_TIME_LOW 0x00000000
203
204#define NOTIFY_MASK_TIME_HIGH 0x00400000
205#define MULTIPLE_MASK_TIME_HIGH 0x00100000
206#define STREAM_MASK_TIME_HIGH 0x00800000
207
208
209/*
210 *
211 */
212void vx_init_rmh(struct vx_rmh *rmh, unsigned int cmd);
213
214/**
215 * vx_send_pipe_cmd_params - fill first command word for pipe commands
216 * @rmh: the rmh to be modified
217 * @is_capture: 0 = playback, 1 = capture operation
218 * @param1: first pipe-parameter
219 * @param2: second pipe-parameter
220 */
221static inline void vx_set_pipe_cmd_params(struct vx_rmh *rmh, int is_capture,
222 int param1, int param2)
223{
224 if (is_capture)
225 rmh->Cmd[0] |= COMMAND_RECORD_MASK;
226 rmh->Cmd[0] |= (((u32)param1 & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD;
227
228 if (param2)
229 rmh->Cmd[0] |= ((u32)param2 & MASK_FIRST_FIELD) & MASK_DSP_WORD;
230
231}
232
233/**
234 * vx_set_stream_cmd_params - fill first command word for stream commands
235 * @rmh: the rmh to be modified
236 * @is_capture: 0 = playback, 1 = capture operation
237 * @pipe: the pipe index (zero-based)
238 */
239static inline void vx_set_stream_cmd_params(struct vx_rmh *rmh, int is_capture, int pipe)
240{
241 if (is_capture)
242 rmh->Cmd[0] |= COMMAND_RECORD_MASK;
243 rmh->Cmd[0] |= (((u32)pipe & MASK_FIRST_FIELD) << FIELD_SIZE) & MASK_DSP_WORD;
244}
245
246#endif /* __VX_CMD_H */
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
new file mode 100644
index 000000000000..c6fa5afa3e9a
--- /dev/null
+++ b/sound/drivers/vx/vx_core.c
@@ -0,0 +1,837 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * Hardware core part
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <linux/delay.h>
25#include <linux/slab.h>
26#include <linux/interrupt.h>
27#include <linux/init.h>
28#include <linux/device.h>
29#include <linux/firmware.h>
30#include <sound/core.h>
31#include <sound/pcm.h>
32#include <sound/asoundef.h>
33#include <sound/info.h>
34#include <asm/io.h>
35#include <sound/vx_core.h>
36#include "vx_cmd.h"
37
38MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
39MODULE_DESCRIPTION("Common routines for Digigram VX drivers");
40MODULE_LICENSE("GPL");
41
42
43/*
44 * snd_vx_delay - delay for the specified time
45 * @xmsec: the time to delay in msec
46 */
47void snd_vx_delay(vx_core_t *chip, int xmsec)
48{
49 if (! in_interrupt() && xmsec >= 1000 / HZ)
50 msleep(xmsec);
51 else
52 mdelay(xmsec);
53}
54
55/*
56 * vx_check_reg_bit - wait for the specified bit is set/reset on a register
57 * @reg: register to check
58 * @mask: bit mask
59 * @bit: resultant bit to be checked
60 * @time: time-out of loop in msec
61 *
62 * returns zero if a bit matches, or a negative error code.
63 */
64int snd_vx_check_reg_bit(vx_core_t *chip, int reg, int mask, int bit, int time)
65{
66 unsigned long end_time = jiffies + (time * HZ + 999) / 1000;
67#ifdef CONFIG_SND_DEBUG
68 static char *reg_names[VX_REG_MAX] = {
69 "ICR", "CVR", "ISR", "IVR", "RXH", "RXM", "RXL",
70 "DMA", "CDSP", "RFREQ", "RUER/V2", "DATA", "MEMIRQ",
71 "ACQ", "BIT0", "BIT1", "MIC0", "MIC1", "MIC2",
72 "MIC3", "INTCSR", "CNTRL", "GPIOC",
73 "LOFREQ", "HIFREQ", "CSUER", "RUER"
74 };
75#endif
76 do {
77 if ((snd_vx_inb(chip, reg) & mask) == bit)
78 return 0;
79 //snd_vx_delay(chip, 10);
80 } while (time_after_eq(end_time, jiffies));
81 snd_printd(KERN_DEBUG "vx_check_reg_bit: timeout, reg=%s, mask=0x%x, val=0x%x\n", reg_names[reg], mask, snd_vx_inb(chip, reg));
82 return -EIO;
83}
84
85/*
86 * vx_send_irq_dsp - set command irq bit
87 * @num: the requested IRQ type, IRQ_XXX
88 *
89 * this triggers the specified IRQ request
90 * returns 0 if successful, or a negative error code.
91 *
92 */
93static int vx_send_irq_dsp(vx_core_t *chip, int num)
94{
95 int nirq;
96
97 /* wait for Hc = 0 */
98 if (snd_vx_check_reg_bit(chip, VX_CVR, CVR_HC, 0, 200) < 0)
99 return -EIO;
100
101 nirq = num;
102 if (vx_has_new_dsp(chip))
103 nirq += VXP_IRQ_OFFSET;
104 vx_outb(chip, CVR, (nirq >> 1) | CVR_HC);
105 return 0;
106}
107
108
109/*
110 * vx_reset_chk - reset CHK bit on ISR
111 *
112 * returns 0 if successful, or a negative error code.
113 */
114static int vx_reset_chk(vx_core_t *chip)
115{
116 /* Reset irq CHK */
117 if (vx_send_irq_dsp(chip, IRQ_RESET_CHK) < 0)
118 return -EIO;
119 /* Wait until CHK = 0 */
120 if (vx_check_isr(chip, ISR_CHK, 0, 200) < 0)
121 return -EIO;
122 return 0;
123}
124
125/*
126 * vx_transfer_end - terminate message transfer
127 * @cmd: IRQ message to send (IRQ_MESS_XXX_END)
128 *
129 * returns 0 if successful, or a negative error code.
130 * the error code can be VX-specific, retrieved via vx_get_error().
131 * NB: call with spinlock held!
132 */
133static int vx_transfer_end(vx_core_t *chip, int cmd)
134{
135 int err;
136
137 if ((err = vx_reset_chk(chip)) < 0)
138 return err;
139
140 /* irq MESS_READ/WRITE_END */
141 if ((err = vx_send_irq_dsp(chip, cmd)) < 0)
142 return err;
143
144 /* Wait CHK = 1 */
145 if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0)
146 return err;
147
148 /* If error, Read RX */
149 if ((err = vx_inb(chip, ISR)) & ISR_ERR) {
150 if ((err = vx_wait_for_rx_full(chip)) < 0) {
151 snd_printd(KERN_DEBUG "transfer_end: error in rx_full\n");
152 return err;
153 }
154 err = vx_inb(chip, RXH) << 16;
155 err |= vx_inb(chip, RXM) << 8;
156 err |= vx_inb(chip, RXL);
157 snd_printd(KERN_DEBUG "transfer_end: error = 0x%x\n", err);
158 return -(VX_ERR_MASK | err);
159 }
160 return 0;
161}
162
163/*
164 * vx_read_status - return the status rmh
165 * @rmh: rmh record to store the status
166 *
167 * returns 0 if successful, or a negative error code.
168 * the error code can be VX-specific, retrieved via vx_get_error().
169 * NB: call with spinlock held!
170 */
171static int vx_read_status(vx_core_t *chip, struct vx_rmh *rmh)
172{
173 int i, err, val, size;
174
175 /* no read necessary? */
176 if (rmh->DspStat == RMH_SSIZE_FIXED && rmh->LgStat == 0)
177 return 0;
178
179 /* Wait for RX full (with timeout protection)
180 * The first word of status is in RX
181 */
182 err = vx_wait_for_rx_full(chip);
183 if (err < 0)
184 return err;
185
186 /* Read RX */
187 val = vx_inb(chip, RXH) << 16;
188 val |= vx_inb(chip, RXM) << 8;
189 val |= vx_inb(chip, RXL);
190
191 /* If status given by DSP, let's decode its size */
192 switch (rmh->DspStat) {
193 case RMH_SSIZE_ARG:
194 size = val & 0xff;
195 rmh->Stat[0] = val & 0xffff00;
196 rmh->LgStat = size + 1;
197 break;
198 case RMH_SSIZE_MASK:
199 /* Let's count the arg numbers from a mask */
200 rmh->Stat[0] = val;
201 size = 0;
202 while (val) {
203 if (val & 0x01)
204 size++;
205 val >>= 1;
206 }
207 rmh->LgStat = size + 1;
208 break;
209 default:
210 /* else retrieve the status length given by the driver */
211 size = rmh->LgStat;
212 rmh->Stat[0] = val; /* Val is the status 1st word */
213 size--; /* hence adjust remaining length */
214 break;
215 }
216
217 if (size < 1)
218 return 0;
219 snd_assert(size <= SIZE_MAX_STATUS, return -EINVAL);
220
221 for (i = 1; i <= size; i++) {
222 /* trigger an irq MESS_WRITE_NEXT */
223 err = vx_send_irq_dsp(chip, IRQ_MESS_WRITE_NEXT);
224 if (err < 0)
225 return err;
226 /* Wait for RX full (with timeout protection) */
227 err = vx_wait_for_rx_full(chip);
228 if (err < 0)
229 return err;
230 rmh->Stat[i] = vx_inb(chip, RXH) << 16;
231 rmh->Stat[i] |= vx_inb(chip, RXM) << 8;
232 rmh->Stat[i] |= vx_inb(chip, RXL);
233 }
234
235 return vx_transfer_end(chip, IRQ_MESS_WRITE_END);
236}
237
238
239#define MASK_MORE_THAN_1_WORD_COMMAND 0x00008000
240#define MASK_1_WORD_COMMAND 0x00ff7fff
241
242/*
243 * vx_send_msg_nolock - send a DSP message and read back the status
244 * @rmh: the rmh record to send and receive
245 *
246 * returns 0 if successful, or a negative error code.
247 * the error code can be VX-specific, retrieved via vx_get_error().
248 *
249 * this function doesn't call spinlock at all.
250 */
251int vx_send_msg_nolock(vx_core_t *chip, struct vx_rmh *rmh)
252{
253 int i, err;
254
255 if (chip->chip_status & VX_STAT_IS_STALE)
256 return -EBUSY;
257
258 if ((err = vx_reset_chk(chip)) < 0) {
259 snd_printd(KERN_DEBUG "vx_send_msg: vx_reset_chk error\n");
260 return err;
261 }
262
263#if 0
264 printk(KERN_DEBUG "rmh: cmd = 0x%06x, length = %d, stype = %d\n",
265 rmh->Cmd[0], rmh->LgCmd, rmh->DspStat);
266 if (rmh->LgCmd > 1) {
267 printk(KERN_DEBUG " ");
268 for (i = 1; i < rmh->LgCmd; i++)
269 printk("0x%06x ", rmh->Cmd[i]);
270 printk("\n");
271 }
272#endif
273 /* Check bit M is set according to length of the command */
274 if (rmh->LgCmd > 1)
275 rmh->Cmd[0] |= MASK_MORE_THAN_1_WORD_COMMAND;
276 else
277 rmh->Cmd[0] &= MASK_1_WORD_COMMAND;
278
279 /* Wait for TX empty */
280 if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) {
281 snd_printd(KERN_DEBUG "vx_send_msg: wait tx empty error\n");
282 return err;
283 }
284
285 /* Write Cmd[0] */
286 vx_outb(chip, TXH, (rmh->Cmd[0] >> 16) & 0xff);
287 vx_outb(chip, TXM, (rmh->Cmd[0] >> 8) & 0xff);
288 vx_outb(chip, TXL, rmh->Cmd[0] & 0xff);
289
290 /* Trigger irq MESSAGE */
291 if ((err = vx_send_irq_dsp(chip, IRQ_MESSAGE)) < 0) {
292 snd_printd(KERN_DEBUG "vx_send_msg: send IRQ_MESSAGE error\n");
293 return err;
294 }
295
296 /* Wait for CHK = 1 */
297 if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0)
298 return err;
299
300 /* If error, get error value from RX */
301 if (vx_inb(chip, ISR) & ISR_ERR) {
302 if ((err = vx_wait_for_rx_full(chip)) < 0) {
303 snd_printd(KERN_DEBUG "vx_send_msg: rx_full read error\n");
304 return err;
305 }
306 err = vx_inb(chip, RXH) << 16;
307 err |= vx_inb(chip, RXM) << 8;
308 err |= vx_inb(chip, RXL);
309 snd_printd(KERN_DEBUG "msg got error = 0x%x at cmd[0]\n", err);
310 err = -(VX_ERR_MASK | err);
311 return err;
312 }
313
314 /* Send the other words */
315 if (rmh->LgCmd > 1) {
316 for (i = 1; i < rmh->LgCmd; i++) {
317 /* Wait for TX ready */
318 if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) {
319 snd_printd(KERN_DEBUG "vx_send_msg: tx_ready error\n");
320 return err;
321 }
322
323 /* Write Cmd[i] */
324 vx_outb(chip, TXH, (rmh->Cmd[i] >> 16) & 0xff);
325 vx_outb(chip, TXM, (rmh->Cmd[i] >> 8) & 0xff);
326 vx_outb(chip, TXL, rmh->Cmd[i] & 0xff);
327
328 /* Trigger irq MESS_READ_NEXT */
329 if ((err = vx_send_irq_dsp(chip, IRQ_MESS_READ_NEXT)) < 0) {
330 snd_printd(KERN_DEBUG "vx_send_msg: IRQ_READ_NEXT error\n");
331 return err;
332 }
333 }
334 /* Wait for TX empty */
335 if ((err = vx_wait_isr_bit(chip, ISR_TX_READY)) < 0) {
336 snd_printd(KERN_DEBUG "vx_send_msg: TX_READY error\n");
337 return err;
338 }
339 /* End of transfer */
340 err = vx_transfer_end(chip, IRQ_MESS_READ_END);
341 if (err < 0)
342 return err;
343 }
344
345 return vx_read_status(chip, rmh);
346}
347
348
349/*
350 * vx_send_msg - send a DSP message with spinlock
351 * @rmh: the rmh record to send and receive
352 *
353 * returns 0 if successful, or a negative error code.
354 * see vx_send_msg_nolock().
355 */
356int vx_send_msg(vx_core_t *chip, struct vx_rmh *rmh)
357{
358 unsigned long flags;
359 int err;
360
361 spin_lock_irqsave(&chip->lock, flags);
362 err = vx_send_msg_nolock(chip, rmh);
363 spin_unlock_irqrestore(&chip->lock, flags);
364 return err;
365}
366
367
368/*
369 * vx_send_rih_nolock - send an RIH to xilinx
370 * @cmd: the command to send
371 *
372 * returns 0 if successful, or a negative error code.
373 * the error code can be VX-specific, retrieved via vx_get_error().
374 *
375 * this function doesn't call spinlock at all.
376 *
377 * unlike RMH, no command is sent to DSP.
378 */
379int vx_send_rih_nolock(vx_core_t *chip, int cmd)
380{
381 int err;
382
383 if (chip->chip_status & VX_STAT_IS_STALE)
384 return -EBUSY;
385
386#if 0
387 printk(KERN_DEBUG "send_rih: cmd = 0x%x\n", cmd);
388#endif
389 if ((err = vx_reset_chk(chip)) < 0)
390 return err;
391 /* send the IRQ */
392 if ((err = vx_send_irq_dsp(chip, cmd)) < 0)
393 return err;
394 /* Wait CHK = 1 */
395 if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0)
396 return err;
397 /* If error, read RX */
398 if (vx_inb(chip, ISR) & ISR_ERR) {
399 if ((err = vx_wait_for_rx_full(chip)) < 0)
400 return err;
401 err = vx_inb(chip, RXH) << 16;
402 err |= vx_inb(chip, RXM) << 8;
403 err |= vx_inb(chip, RXL);
404 return -(VX_ERR_MASK | err);
405 }
406 return 0;
407}
408
409
410/*
411 * vx_send_rih - send an RIH with spinlock
412 * @cmd: the command to send
413 *
414 * see vx_send_rih_nolock().
415 */
416int vx_send_rih(vx_core_t *chip, int cmd)
417{
418 unsigned long flags;
419 int err;
420
421 spin_lock_irqsave(&chip->lock, flags);
422 err = vx_send_rih_nolock(chip, cmd);
423 spin_unlock_irqrestore(&chip->lock, flags);
424 return err;
425}
426
427#define END_OF_RESET_WAIT_TIME 500 /* us */
428
429/**
430 * snd_vx_boot_xilinx - boot up the xilinx interface
431 * @boot: the boot record to load
432 */
433int snd_vx_load_boot_image(vx_core_t *chip, const struct firmware *boot)
434{
435 unsigned int i;
436 int no_fillup = vx_has_new_dsp(chip);
437
438 /* check the length of boot image */
439 snd_assert(boot->size > 0, return -EINVAL);
440 snd_assert(boot->size % 3 == 0, return -EINVAL);
441#if 0
442 {
443 /* more strict check */
444 unsigned int c = ((u32)boot->data[0] << 16) | ((u32)boot->data[1] << 8) | boot->data[2];
445 snd_assert(boot->size == (c + 2) * 3, return -EINVAL);
446 }
447#endif
448
449 /* reset dsp */
450 vx_reset_dsp(chip);
451
452 udelay(END_OF_RESET_WAIT_TIME); /* another wait? */
453
454 /* download boot strap */
455 for (i = 0; i < 0x600; i += 3) {
456 if (i >= boot->size) {
457 if (no_fillup)
458 break;
459 if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) {
460 snd_printk(KERN_ERR "dsp boot failed at %d\n", i);
461 return -EIO;
462 }
463 vx_outb(chip, TXH, 0);
464 vx_outb(chip, TXM, 0);
465 vx_outb(chip, TXL, 0);
466 } else {
467 unsigned char *image = boot->data + i;
468 if (vx_wait_isr_bit(chip, ISR_TX_EMPTY) < 0) {
469 snd_printk(KERN_ERR "dsp boot failed at %d\n", i);
470 return -EIO;
471 }
472 vx_outb(chip, TXH, image[0]);
473 vx_outb(chip, TXM, image[1]);
474 vx_outb(chip, TXL, image[2]);
475 }
476 }
477 return 0;
478}
479
480/*
481 * vx_test_irq_src - query the source of interrupts
482 *
483 * called from irq handler only
484 */
485static int vx_test_irq_src(vx_core_t *chip, unsigned int *ret)
486{
487 int err;
488
489 vx_init_rmh(&chip->irq_rmh, CMD_TEST_IT);
490 spin_lock(&chip->lock);
491 err = vx_send_msg_nolock(chip, &chip->irq_rmh);
492 if (err < 0)
493 *ret = 0;
494 else
495 *ret = chip->irq_rmh.Stat[0];
496 spin_unlock(&chip->lock);
497 return err;
498}
499
500
501/*
502 * vx_interrupt - soft irq handler
503 */
504static void vx_interrupt(unsigned long private_data)
505{
506 vx_core_t *chip = (vx_core_t *) private_data;
507 unsigned int events;
508
509 if (chip->chip_status & VX_STAT_IS_STALE)
510 return;
511
512 if (vx_test_irq_src(chip, &events) < 0)
513 return;
514
515#if 0
516 if (events & 0x000800)
517 printk(KERN_ERR "DSP Stream underrun ! IRQ events = 0x%x\n", events);
518#endif
519 // printk(KERN_DEBUG "IRQ events = 0x%x\n", events);
520
521 /* We must prevent any application using this DSP
522 * and block any further request until the application
523 * either unregisters or reloads the DSP
524 */
525 if (events & FATAL_DSP_ERROR) {
526 snd_printk(KERN_ERR "vx_core: fatal DSP error!!\n");
527 return;
528 }
529
530 /* The start on time code conditions are filled (ie the time code
531 * received by the board is equal to one of those given to it).
532 */
533 if (events & TIME_CODE_EVENT_PENDING)
534 ; /* so far, nothing to do yet */
535
536 /* The frequency has changed on the board (UER mode). */
537 if (events & FREQUENCY_CHANGE_EVENT_PENDING)
538 vx_change_frequency(chip);
539
540 /* update the pcm streams */
541 vx_pcm_update_intr(chip, events);
542}
543
544
545/**
546 * snd_vx_irq_handler - interrupt handler
547 */
548irqreturn_t snd_vx_irq_handler(int irq, void *dev, struct pt_regs *regs)
549{
550 vx_core_t *chip = dev;
551
552 if (! (chip->chip_status & VX_STAT_CHIP_INIT) ||
553 (chip->chip_status & VX_STAT_IS_STALE))
554 return IRQ_NONE;
555 if (! vx_test_and_ack(chip))
556 tasklet_hi_schedule(&chip->tq);
557 return IRQ_HANDLED;
558}
559
560
561/*
562 */
563static void vx_reset_board(vx_core_t *chip, int cold_reset)
564{
565 snd_assert(chip->ops->reset_board, return);
566
567 /* current source, later sync'ed with target */
568 chip->audio_source = VX_AUDIO_SRC_LINE;
569 if (cold_reset) {
570 chip->audio_source_target = chip->audio_source;
571 chip->clock_source = INTERNAL_QUARTZ;
572 chip->clock_mode = VX_CLOCK_MODE_AUTO;
573 chip->freq = 48000;
574 chip->uer_detected = VX_UER_MODE_NOT_PRESENT;
575 chip->uer_bits = SNDRV_PCM_DEFAULT_CON_SPDIF;
576 }
577
578 chip->ops->reset_board(chip, cold_reset);
579
580 vx_reset_codec(chip, cold_reset);
581
582 vx_set_internal_clock(chip, chip->freq);
583
584 /* Reset the DSP */
585 vx_reset_dsp(chip);
586
587 if (vx_is_pcmcia(chip)) {
588 /* Acknowledge any pending IRQ and reset the MEMIRQ flag. */
589 vx_test_and_ack(chip);
590 vx_validate_irq(chip, 1);
591 }
592
593 /* init CBits */
594 vx_set_iec958_status(chip, chip->uer_bits);
595}
596
597
598/*
599 * proc interface
600 */
601
602static void vx_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
603{
604 vx_core_t *chip = entry->private_data;
605 static char *audio_src_vxp[] = { "Line", "Mic", "Digital" };
606 static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" };
607 static char *clock_mode[] = { "Auto", "Internal", "External" };
608 static char *clock_src[] = { "Internal", "External" };
609 static char *uer_type[] = { "Consumer", "Professional", "Not Present" };
610
611 snd_iprintf(buffer, "%s\n", chip->card->longname);
612 snd_iprintf(buffer, "Xilinx Firmware: %s\n",
613 chip->chip_status & VX_STAT_XILINX_LOADED ? "Loaded" : "No");
614 snd_iprintf(buffer, "Device Initialized: %s\n",
615 chip->chip_status & VX_STAT_DEVICE_INIT ? "Yes" : "No");
616 snd_iprintf(buffer, "DSP audio info:");
617 if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME)
618 snd_iprintf(buffer, " realtime");
619 if (chip->audio_info & VX_AUDIO_INFO_OFFLINE)
620 snd_iprintf(buffer, " offline");
621 if (chip->audio_info & VX_AUDIO_INFO_MPEG1)
622 snd_iprintf(buffer, " mpeg1");
623 if (chip->audio_info & VX_AUDIO_INFO_MPEG2)
624 snd_iprintf(buffer, " mpeg2");
625 if (chip->audio_info & VX_AUDIO_INFO_LINEAR_8)
626 snd_iprintf(buffer, " linear8");
627 if (chip->audio_info & VX_AUDIO_INFO_LINEAR_16)
628 snd_iprintf(buffer, " linear16");
629 if (chip->audio_info & VX_AUDIO_INFO_LINEAR_24)
630 snd_iprintf(buffer, " linear24");
631 snd_iprintf(buffer, "\n");
632 snd_iprintf(buffer, "Input Source: %s\n", vx_is_pcmcia(chip) ?
633 audio_src_vxp[chip->audio_source] :
634 audio_src_vx2[chip->audio_source]);
635 snd_iprintf(buffer, "Clock Mode: %s\n", clock_mode[chip->clock_mode]);
636 snd_iprintf(buffer, "Clock Source: %s\n", clock_src[chip->clock_source]);
637 snd_iprintf(buffer, "Frequency: %d\n", chip->freq);
638 snd_iprintf(buffer, "Detected Frequency: %d\n", chip->freq_detected);
639 snd_iprintf(buffer, "Detected UER type: %s\n", uer_type[chip->uer_detected]);
640 snd_iprintf(buffer, "Min/Max/Cur IBL: %d/%d/%d (granularity=%d)\n",
641 chip->ibl.min_size, chip->ibl.max_size, chip->ibl.size,
642 chip->ibl.granularity);
643}
644
645static void vx_proc_init(vx_core_t *chip)
646{
647 snd_info_entry_t *entry;
648
649 if (! snd_card_proc_new(chip->card, "vx-status", &entry))
650 snd_info_set_text_ops(entry, chip, 1024, vx_proc_read);
651}
652
653
654/**
655 * snd_vx_dsp_boot - load the DSP boot
656 */
657int snd_vx_dsp_boot(vx_core_t *chip, const struct firmware *boot)
658{
659 int err;
660 int cold_reset = !(chip->chip_status & VX_STAT_DEVICE_INIT);
661
662 vx_reset_board(chip, cold_reset);
663 vx_validate_irq(chip, 0);
664
665 if ((err = snd_vx_load_boot_image(chip, boot)) < 0)
666 return err;
667 snd_vx_delay(chip, 10);
668
669 return 0;
670}
671
672/**
673 * snd_vx_dsp_load - load the DSP image
674 */
675int snd_vx_dsp_load(vx_core_t *chip, const struct firmware *dsp)
676{
677 unsigned int i;
678 int err;
679 unsigned int csum = 0;
680 unsigned char *image, *cptr;
681
682 snd_assert(dsp->size % 3 == 0, return -EINVAL);
683
684 vx_toggle_dac_mute(chip, 1);
685
686 /* Transfert data buffer from PC to DSP */
687 for (i = 0; i < dsp->size; i += 3) {
688 image = dsp->data + i;
689 /* Wait DSP ready for a new read */
690 if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) {
691 printk("dsp loading error at position %d\n", i);
692 return err;
693 }
694 cptr = image;
695 csum ^= *cptr;
696 csum = (csum >> 24) | (csum << 8);
697 vx_outb(chip, TXH, *cptr++);
698 csum ^= *cptr;
699 csum = (csum >> 24) | (csum << 8);
700 vx_outb(chip, TXM, *cptr++);
701 csum ^= *cptr;
702 csum = (csum >> 24) | (csum << 8);
703 vx_outb(chip, TXL, *cptr++);
704 }
705 snd_printdd(KERN_DEBUG "checksum = 0x%08x\n", csum);
706
707 snd_vx_delay(chip, 200);
708
709 if ((err = vx_wait_isr_bit(chip, ISR_CHK)) < 0)
710 return err;
711
712 vx_toggle_dac_mute(chip, 0);
713
714 vx_test_and_ack(chip);
715 vx_validate_irq(chip, 1);
716
717 return 0;
718}
719
720#ifdef CONFIG_PM
721/*
722 * suspend
723 */
724static int snd_vx_suspend(snd_card_t *card, pm_message_t state)
725{
726 vx_core_t *chip = card->pm_private_data;
727 unsigned int i;
728
729 snd_assert(chip, return -EINVAL);
730
731 chip->chip_status |= VX_STAT_IN_SUSPEND;
732 for (i = 0; i < chip->hw->num_codecs; i++)
733 snd_pcm_suspend_all(chip->pcm[i]);
734
735 return 0;
736}
737
738/*
739 * resume
740 */
741static int snd_vx_resume(snd_card_t *card)
742{
743 vx_core_t *chip = card->pm_private_data;
744 int i, err;
745
746 snd_assert(chip, return -EINVAL);
747
748 chip->chip_status &= ~VX_STAT_CHIP_INIT;
749
750 for (i = 0; i < 4; i++) {
751 if (! chip->firmware[i])
752 continue;
753 err = chip->ops->load_dsp(chip, i, chip->firmware[i]);
754 if (err < 0) {
755 snd_printk(KERN_ERR "vx: firmware resume error at DSP %d\n", i);
756 return -EIO;
757 }
758 }
759
760 chip->chip_status |= VX_STAT_CHIP_INIT;
761 chip->chip_status &= ~VX_STAT_IN_SUSPEND;
762
763 return 0;
764}
765
766#endif
767
768/**
769 * snd_vx_create - constructor for vx_core_t
770 * @hw: hardware specific record
771 *
772 * this function allocates the instance and prepare for the hardware
773 * initialization.
774 *
775 * return the instance pointer if successful, NULL in error.
776 */
777vx_core_t *snd_vx_create(snd_card_t *card, struct snd_vx_hardware *hw,
778 struct snd_vx_ops *ops,
779 int extra_size)
780{
781 vx_core_t *chip;
782
783 snd_assert(card && hw && ops, return NULL);
784
785 chip = kcalloc(1, sizeof(*chip) + extra_size, GFP_KERNEL);
786 if (! chip) {
787 snd_printk(KERN_ERR "vx_core: no memory\n");
788 return NULL;
789 }
790 spin_lock_init(&chip->lock);
791 spin_lock_init(&chip->irq_lock);
792 chip->irq = -1;
793 chip->hw = hw;
794 chip->type = hw->type;
795 chip->ops = ops;
796 tasklet_init(&chip->tq, vx_interrupt, (unsigned long)chip);
797 init_MUTEX(&chip->mixer_mutex);
798
799 chip->card = card;
800 card->private_data = chip;
801 strcpy(card->driver, hw->name);
802 sprintf(card->shortname, "Digigram %s", hw->name);
803
804 snd_card_set_pm_callback(card, snd_vx_suspend, snd_vx_resume, chip);
805
806 vx_proc_init(chip);
807
808 return chip;
809}
810
811/*
812 * module entries
813 */
814static int __init alsa_vx_core_init(void)
815{
816 return 0;
817}
818
819static void __exit alsa_vx_core_exit(void)
820{
821}
822
823module_init(alsa_vx_core_init)
824module_exit(alsa_vx_core_exit)
825
826/*
827 * exports
828 */
829EXPORT_SYMBOL(snd_vx_check_reg_bit);
830EXPORT_SYMBOL(snd_vx_create);
831EXPORT_SYMBOL(snd_vx_setup_firmware);
832EXPORT_SYMBOL(snd_vx_free_firmware);
833EXPORT_SYMBOL(snd_vx_irq_handler);
834EXPORT_SYMBOL(snd_vx_delay);
835EXPORT_SYMBOL(snd_vx_dsp_boot);
836EXPORT_SYMBOL(snd_vx_dsp_load);
837EXPORT_SYMBOL(snd_vx_load_boot_image);
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
new file mode 100644
index 000000000000..9a3dc3c3b3de
--- /dev/null
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -0,0 +1,249 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * DSP firmware management
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <linux/device.h>
25#include <linux/firmware.h>
26#include <sound/core.h>
27#include <sound/hwdep.h>
28#include <sound/vx_core.h>
29
30#ifdef SND_VX_FW_LOADER
31
32int snd_vx_setup_firmware(vx_core_t *chip)
33{
34 static char *fw_files[VX_TYPE_NUMS][4] = {
35 [VX_TYPE_BOARD] = {
36 NULL, "x1_1_vx2.xlx", "bd56002.boot", "l_1_vx2.d56",
37 },
38 [VX_TYPE_V2] = {
39 NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56",
40 },
41 [VX_TYPE_MIC] = {
42 NULL, "x1_2_v22.xlx", "bd563v2.boot", "l_1_v22.d56",
43 },
44 [VX_TYPE_VXPOCKET] = {
45 "bx_1_vxp.b56", "x1_1_vxp.xlx", "bd563s3.boot", "l_1_vxp.d56"
46 },
47 [VX_TYPE_VXP440] = {
48 "bx_1_vp4.b56", "x1_1_vp4.xlx", "bd563s3.boot", "l_1_vp4.d56"
49 },
50 };
51
52 int i, err;
53
54 for (i = 0; i < 4; i++) {
55 char path[32];
56 const struct firmware *fw;
57 if (! fw_files[chip->type][i])
58 continue;
59 sprintf(path, "vx/%s", fw_files[chip->type][i]);
60 if (request_firmware(&fw, path, chip->dev)) {
61 snd_printk(KERN_ERR "vx: can't load firmware %s\n", path);
62 return -ENOENT;
63 }
64 err = chip->ops->load_dsp(chip, i, fw);
65 if (err < 0) {
66 release_firmware(fw);
67 return err;
68 }
69 if (i == 1)
70 chip->chip_status |= VX_STAT_XILINX_LOADED;
71#ifdef CONFIG_PM
72 chip->firmware[i] = fw;
73#else
74 release_firmware(fw);
75#endif
76 }
77
78 /* ok, we reached to the last one */
79 /* create the devices if not built yet */
80 if ((err = snd_vx_pcm_new(chip)) < 0)
81 return err;
82
83 if ((err = snd_vx_mixer_new(chip)) < 0)
84 return err;
85
86 if (chip->ops->add_controls)
87 if ((err = chip->ops->add_controls(chip)) < 0)
88 return err;
89
90 chip->chip_status |= VX_STAT_DEVICE_INIT;
91 chip->chip_status |= VX_STAT_CHIP_INIT;
92
93 return snd_card_register(chip->card);
94}
95
96/* exported */
97void snd_vx_free_firmware(vx_core_t *chip)
98{
99#ifdef CONFIG_PM
100 int i;
101 for (i = 0; i < 4; i++)
102 release_firmware(chip->firmware[i]);
103#endif
104}
105
106#else /* old style firmware loading */
107
108static int vx_hwdep_open(snd_hwdep_t *hw, struct file *file)
109{
110 return 0;
111}
112
113static int vx_hwdep_release(snd_hwdep_t *hw, struct file *file)
114{
115 return 0;
116}
117
118static int vx_hwdep_dsp_status(snd_hwdep_t *hw, snd_hwdep_dsp_status_t *info)
119{
120 static char *type_ids[VX_TYPE_NUMS] = {
121 [VX_TYPE_BOARD] = "vxboard",
122 [VX_TYPE_V2] = "vx222",
123 [VX_TYPE_MIC] = "vx222",
124 [VX_TYPE_VXPOCKET] = "vxpocket",
125 [VX_TYPE_VXP440] = "vxp440",
126 };
127 vx_core_t *vx = hw->private_data;
128
129 snd_assert(type_ids[vx->type], return -EINVAL);
130 strcpy(info->id, type_ids[vx->type]);
131 if (vx_is_pcmcia(vx))
132 info->num_dsps = 4;
133 else
134 info->num_dsps = 3;
135 if (vx->chip_status & VX_STAT_CHIP_INIT)
136 info->chip_ready = 1;
137 info->version = VX_DRIVER_VERSION;
138 return 0;
139}
140
141static void free_fw(const struct firmware *fw)
142{
143 if (fw) {
144 vfree(fw->data);
145 kfree(fw);
146 }
147}
148
149static int vx_hwdep_dsp_load(snd_hwdep_t *hw, snd_hwdep_dsp_image_t *dsp)
150{
151 vx_core_t *vx = hw->private_data;
152 int index, err;
153 struct firmware *fw;
154
155 snd_assert(vx->ops->load_dsp, return -ENXIO);
156
157 fw = kmalloc(sizeof(*fw), GFP_KERNEL);
158 if (! fw) {
159 snd_printk(KERN_ERR "cannot allocate firmware\n");
160 return -ENOMEM;
161 }
162 fw->size = dsp->length;
163 fw->data = vmalloc(fw->size);
164 if (! fw->data) {
165 snd_printk(KERN_ERR "cannot allocate firmware image (length=%d)\n",
166 (int)fw->size);
167 kfree(fw);
168 return -ENOMEM;
169 }
170 if (copy_from_user(fw->data, dsp->image, dsp->length)) {
171 free_fw(fw);
172 return -EFAULT;
173 }
174
175 index = dsp->index;
176 if (! vx_is_pcmcia(vx))
177 index++;
178 err = vx->ops->load_dsp(vx, index, fw);
179 if (err < 0) {
180 free_fw(fw);
181 return err;
182 }
183#ifdef CONFIG_PM
184 vx->firmware[index] = fw;
185#else
186 free_fw(fw);
187#endif
188
189 if (index == 1)
190 vx->chip_status |= VX_STAT_XILINX_LOADED;
191 if (index < 3)
192 return 0;
193
194 /* ok, we reached to the last one */
195 /* create the devices if not built yet */
196 if (! (vx->chip_status & VX_STAT_DEVICE_INIT)) {
197 if ((err = snd_vx_pcm_new(vx)) < 0)
198 return err;
199
200 if ((err = snd_vx_mixer_new(vx)) < 0)
201 return err;
202
203 if (vx->ops->add_controls)
204 if ((err = vx->ops->add_controls(vx)) < 0)
205 return err;
206
207 if ((err = snd_card_register(vx->card)) < 0)
208 return err;
209
210 vx->chip_status |= VX_STAT_DEVICE_INIT;
211 }
212 vx->chip_status |= VX_STAT_CHIP_INIT;
213 return 0;
214}
215
216
217/* exported */
218int snd_vx_setup_firmware(vx_core_t *chip)
219{
220 int err;
221 snd_hwdep_t *hw;
222
223 if ((err = snd_hwdep_new(chip->card, SND_VX_HWDEP_ID, 0, &hw)) < 0)
224 return err;
225
226 hw->iface = SNDRV_HWDEP_IFACE_VX;
227 hw->private_data = chip;
228 hw->ops.open = vx_hwdep_open;
229 hw->ops.release = vx_hwdep_release;
230 hw->ops.dsp_status = vx_hwdep_dsp_status;
231 hw->ops.dsp_load = vx_hwdep_dsp_load;
232 hw->exclusive = 1;
233 sprintf(hw->name, "VX Loader (%s)", chip->card->driver);
234 chip->hwdep = hw;
235
236 return snd_card_register(chip->card);
237}
238
239/* exported */
240void snd_vx_free_firmware(vx_core_t *chip)
241{
242#ifdef CONFIG_PM
243 int i;
244 for (i = 0; i < 4; i++)
245 free_fw(chip->firmware[i]);
246#endif
247}
248
249#endif /* SND_VX_FW_LOADER */
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
new file mode 100644
index 000000000000..f00c88886460
--- /dev/null
+++ b/sound/drivers/vx/vx_mixer.c
@@ -0,0 +1,1000 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * Common mixer part
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <sound/core.h>
25#include <sound/control.h>
26#include <sound/vx_core.h>
27#include "vx_cmd.h"
28
29
30/*
31 * write a codec data (24bit)
32 */
33static void vx_write_codec_reg(vx_core_t *chip, int codec, unsigned int data)
34{
35 unsigned long flags;
36
37 snd_assert(chip->ops->write_codec, return);
38
39 if (chip->chip_status & VX_STAT_IS_STALE)
40 return;
41
42 spin_lock_irqsave(&chip->lock, flags);
43 chip->ops->write_codec(chip, codec, data);
44 spin_unlock_irqrestore(&chip->lock, flags);
45}
46
47/*
48 * Data type used to access the Codec
49 */
50typedef union {
51 u32 l;
52#ifdef SNDRV_BIG_ENDIAN
53 struct w {
54 u16 h;
55 u16 l;
56 } w;
57 struct b {
58 u8 hh;
59 u8 mh;
60 u8 ml;
61 u8 ll;
62 } b;
63#else /* LITTLE_ENDIAN */
64 struct w {
65 u16 l;
66 u16 h;
67 } w;
68 struct b {
69 u8 ll;
70 u8 ml;
71 u8 mh;
72 u8 hh;
73 } b;
74#endif
75} vx_codec_data_t;
76
77#define SET_CDC_DATA_SEL(di,s) ((di).b.mh = (u8) (s))
78#define SET_CDC_DATA_REG(di,r) ((di).b.ml = (u8) (r))
79#define SET_CDC_DATA_VAL(di,d) ((di).b.ll = (u8) (d))
80#define SET_CDC_DATA_INIT(di) ((di).l = 0L, SET_CDC_DATA_SEL(di,XX_CODEC_SELECTOR))
81
82/*
83 * set up codec register and write the value
84 * @codec: the codec id, 0 or 1
85 * @reg: register index
86 * @val: data value
87 */
88static void vx_set_codec_reg(vx_core_t *chip, int codec, int reg, int val)
89{
90 vx_codec_data_t data;
91 /* DAC control register */
92 SET_CDC_DATA_INIT(data);
93 SET_CDC_DATA_REG(data, reg);
94 SET_CDC_DATA_VAL(data, val);
95 vx_write_codec_reg(chip, codec, data.l);
96}
97
98
99/*
100 * vx_set_analog_output_level - set the output attenuation level
101 * @codec: the output codec, 0 or 1. (1 for VXP440 only)
102 * @left: left output level, 0 = mute
103 * @right: right output level
104 */
105static void vx_set_analog_output_level(vx_core_t *chip, int codec, int left, int right)
106{
107 left = chip->hw->output_level_max - left;
108 right = chip->hw->output_level_max - right;
109
110 if (chip->ops->akm_write) {
111 chip->ops->akm_write(chip, XX_CODEC_LEVEL_LEFT_REGISTER, left);
112 chip->ops->akm_write(chip, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
113 } else {
114 /* convert to attenuation level: 0 = 0dB (max), 0xe3 = -113.5 dB (min) */
115 vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_LEFT_REGISTER, left);
116 vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
117 }
118}
119
120
121/*
122 * vx_toggle_dac_mute - mute/unmute DAC
123 * @mute: 0 = unmute, 1 = mute
124 */
125
126#define DAC_ATTEN_MIN 0x08
127#define DAC_ATTEN_MAX 0x38
128
129void vx_toggle_dac_mute(vx_core_t *chip, int mute)
130{
131 unsigned int i;
132 for (i = 0; i < chip->hw->num_codecs; i++) {
133 if (chip->ops->akm_write)
134 chip->ops->akm_write(chip, XX_CODEC_DAC_CONTROL_REGISTER, mute); /* XXX */
135 else
136 vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER,
137 mute ? DAC_ATTEN_MAX : DAC_ATTEN_MIN);
138 }
139}
140
141/*
142 * vx_reset_codec - reset and initialize the codecs
143 */
144void vx_reset_codec(vx_core_t *chip, int cold_reset)
145{
146 unsigned int i;
147 int port = chip->type >= VX_TYPE_VXPOCKET ? 0x75 : 0x65;
148
149 chip->ops->reset_codec(chip);
150
151 /* AKM codecs should be initialized in reset_codec callback */
152 if (! chip->ops->akm_write) {
153 /* initialize old codecs */
154 for (i = 0; i < chip->hw->num_codecs; i++) {
155 /* DAC control register (change level when zero crossing + mute) */
156 vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER, DAC_ATTEN_MAX);
157 /* ADC control register */
158 vx_set_codec_reg(chip, i, XX_CODEC_ADC_CONTROL_REGISTER, 0x00);
159 /* Port mode register */
160 vx_set_codec_reg(chip, i, XX_CODEC_PORT_MODE_REGISTER, port);
161 /* Clock control register */
162 vx_set_codec_reg(chip, i, XX_CODEC_CLOCK_CONTROL_REGISTER, 0x00);
163 }
164 }
165
166 /* mute analog output */
167 for (i = 0; i < chip->hw->num_codecs; i++) {
168 chip->output_level[i][0] = 0;
169 chip->output_level[i][1] = 0;
170 vx_set_analog_output_level(chip, i, 0, 0);
171 }
172}
173
174/*
175 * change the audio input source
176 * @src: the target source (VX_AUDIO_SRC_XXX)
177 */
178static void vx_change_audio_source(vx_core_t *chip, int src)
179{
180 unsigned long flags;
181
182 if (chip->chip_status & VX_STAT_IS_STALE)
183 return;
184
185 spin_lock_irqsave(&chip->lock, flags);
186 chip->ops->change_audio_source(chip, src);
187 spin_unlock_irqrestore(&chip->lock, flags);
188}
189
190
191/*
192 * change the audio source if necessary and possible
193 * returns 1 if the source is actually changed.
194 */
195int vx_sync_audio_source(vx_core_t *chip)
196{
197 if (chip->audio_source_target == chip->audio_source ||
198 chip->pcm_running)
199 return 0;
200 vx_change_audio_source(chip, chip->audio_source_target);
201 chip->audio_source = chip->audio_source_target;
202 return 1;
203}
204
205
206/*
207 * audio level, mute, monitoring
208 */
209struct vx_audio_level {
210 unsigned int has_level: 1;
211 unsigned int has_monitor_level: 1;
212 unsigned int has_mute: 1;
213 unsigned int has_monitor_mute: 1;
214 unsigned int mute;
215 unsigned int monitor_mute;
216 short level;
217 short monitor_level;
218};
219
220static int vx_adjust_audio_level(vx_core_t *chip, int audio, int capture,
221 struct vx_audio_level *info)
222{
223 struct vx_rmh rmh;
224
225 if (chip->chip_status & VX_STAT_IS_STALE)
226 return -EBUSY;
227
228 vx_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
229 if (capture)
230 rmh.Cmd[0] |= COMMAND_RECORD_MASK;
231 /* Add Audio IO mask */
232 rmh.Cmd[1] = 1 << audio;
233 rmh.Cmd[2] = 0;
234 if (info->has_level) {
235 rmh.Cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
236 rmh.Cmd[2] |= info->level;
237 }
238 if (info->has_monitor_level) {
239 rmh.Cmd[0] |= VALID_AUDIO_IO_MONITORING_LEVEL;
240 rmh.Cmd[2] |= ((unsigned int)info->monitor_level << 10);
241 }
242 if (info->has_mute) {
243 rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_LEVEL;
244 if (info->mute)
245 rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_LEVEL;
246 }
247 if (info->has_monitor_mute) {
248 /* validate flag for M2 at least to unmute it */
249 rmh.Cmd[0] |= VALID_AUDIO_IO_MUTE_MONITORING_1 | VALID_AUDIO_IO_MUTE_MONITORING_2;
250 if (info->monitor_mute)
251 rmh.Cmd[2] |= AUDIO_IO_HAS_MUTE_MONITORING_1;
252 }
253
254 return vx_send_msg(chip, &rmh);
255}
256
257
258#if 0 // not used
259static int vx_read_audio_level(vx_core_t *chip, int audio, int capture,
260 struct vx_audio_level *info)
261{
262 int err;
263 struct vx_rmh rmh;
264
265 memset(info, 0, sizeof(*info));
266 vx_init_rmh(&rmh, CMD_GET_AUDIO_LEVELS);
267 if (capture)
268 rmh.Cmd[0] |= COMMAND_RECORD_MASK;
269 /* Add Audio IO mask */
270 rmh.Cmd[1] = 1 << audio;
271 err = vx_send_msg(chip, &rmh);
272 if (err < 0)
273 return err;
274 info.level = rmh.Stat[0] & MASK_DSP_WORD_LEVEL;
275 info.monitor_level = (rmh.Stat[0] >> 10) & MASK_DSP_WORD_LEVEL;
276 info.mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_LEVEL) ? 1 : 0;
277 info.monitor_mute = (rmh.Stat[i] & AUDIO_IO_HAS_MUTE_MONITORING_1) ? 1 : 0;
278 return 0;
279}
280#endif // not used
281
282/*
283 * set the monitoring level and mute state of the given audio
284 * no more static, because must be called from vx_pcm to demute monitoring
285 */
286int vx_set_monitor_level(vx_core_t *chip, int audio, int level, int active)
287{
288 struct vx_audio_level info;
289
290 memset(&info, 0, sizeof(info));
291 info.has_monitor_level = 1;
292 info.monitor_level = level;
293 info.has_monitor_mute = 1;
294 info.monitor_mute = !active;
295 chip->audio_monitor[audio] = level;
296 chip->audio_monitor_active[audio] = active;
297 return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */
298}
299
300
301/*
302 * set the mute status of the given audio
303 */
304static int vx_set_audio_switch(vx_core_t *chip, int audio, int active)
305{
306 struct vx_audio_level info;
307
308 memset(&info, 0, sizeof(info));
309 info.has_mute = 1;
310 info.mute = !active;
311 chip->audio_active[audio] = active;
312 return vx_adjust_audio_level(chip, audio, 0, &info); /* playback only */
313}
314
315/*
316 * set the mute status of the given audio
317 */
318static int vx_set_audio_gain(vx_core_t *chip, int audio, int capture, int level)
319{
320 struct vx_audio_level info;
321
322 memset(&info, 0, sizeof(info));
323 info.has_level = 1;
324 info.level = level;
325 chip->audio_gain[capture][audio] = level;
326 return vx_adjust_audio_level(chip, audio, capture, &info);
327}
328
329/*
330 * reset all audio levels
331 */
332static void vx_reset_audio_levels(vx_core_t *chip)
333{
334 unsigned int i, c;
335 struct vx_audio_level info;
336
337 memset(chip->audio_gain, 0, sizeof(chip->audio_gain));
338 memset(chip->audio_active, 0, sizeof(chip->audio_active));
339 memset(chip->audio_monitor, 0, sizeof(chip->audio_monitor));
340 memset(chip->audio_monitor_active, 0, sizeof(chip->audio_monitor_active));
341
342 for (c = 0; c < 2; c++) {
343 for (i = 0; i < chip->hw->num_ins * 2; i++) {
344 memset(&info, 0, sizeof(info));
345 if (c == 0) {
346 info.has_monitor_level = 1;
347 info.has_mute = 1;
348 info.has_monitor_mute = 1;
349 }
350 info.has_level = 1;
351 info.level = CVAL_0DB; /* default: 0dB */
352 vx_adjust_audio_level(chip, i, c, &info);
353 chip->audio_gain[c][i] = CVAL_0DB;
354 chip->audio_monitor[i] = CVAL_0DB;
355 }
356 }
357}
358
359
360/*
361 * VU, peak meter record
362 */
363
364#define VU_METER_CHANNELS 2
365
366struct vx_vu_meter {
367 int saturated;
368 int vu_level;
369 int peak_level;
370};
371
372/*
373 * get the VU and peak meter values
374 * @audio: the audio index
375 * @capture: 0 = playback, 1 = capture operation
376 * @info: the array of vx_vu_meter records (size = 2).
377 */
378static int vx_get_audio_vu_meter(vx_core_t *chip, int audio, int capture, struct vx_vu_meter *info)
379{
380 struct vx_rmh rmh;
381 int i, err;
382
383 if (chip->chip_status & VX_STAT_IS_STALE)
384 return -EBUSY;
385
386 vx_init_rmh(&rmh, CMD_AUDIO_VU_PIC_METER);
387 rmh.LgStat += 2 * VU_METER_CHANNELS;
388 if (capture)
389 rmh.Cmd[0] |= COMMAND_RECORD_MASK;
390
391 /* Add Audio IO mask */
392 rmh.Cmd[1] = 0;
393 for (i = 0; i < VU_METER_CHANNELS; i++)
394 rmh.Cmd[1] |= 1 << (audio + i);
395 err = vx_send_msg(chip, &rmh);
396 if (err < 0)
397 return err;
398 /* Read response */
399 for (i = 0; i < 2 * VU_METER_CHANNELS; i +=2) {
400 info->saturated = (rmh.Stat[0] & (1 << (audio + i))) ? 1 : 0;
401 info->vu_level = rmh.Stat[i + 1];
402 info->peak_level = rmh.Stat[i + 2];
403 info++;
404 }
405 return 0;
406}
407
408
409/*
410 * control API entries
411 */
412
413/*
414 * output level control
415 */
416static int vx_output_level_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
417{
418 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
419 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
420 uinfo->count = 2;
421 uinfo->value.integer.min = 0;
422 uinfo->value.integer.max = chip->hw->output_level_max;
423 return 0;
424}
425
426static int vx_output_level_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
427{
428 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
429 int codec = kcontrol->id.index;
430 down(&chip->mixer_mutex);
431 ucontrol->value.integer.value[0] = chip->output_level[codec][0];
432 ucontrol->value.integer.value[1] = chip->output_level[codec][1];
433 up(&chip->mixer_mutex);
434 return 0;
435}
436
437static int vx_output_level_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
438{
439 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
440 int codec = kcontrol->id.index;
441 down(&chip->mixer_mutex);
442 if (ucontrol->value.integer.value[0] != chip->output_level[codec][0] ||
443 ucontrol->value.integer.value[1] != chip->output_level[codec][1]) {
444 vx_set_analog_output_level(chip, codec,
445 ucontrol->value.integer.value[0],
446 ucontrol->value.integer.value[1]);
447 chip->output_level[codec][0] = ucontrol->value.integer.value[0];
448 chip->output_level[codec][1] = ucontrol->value.integer.value[1];
449 up(&chip->mixer_mutex);
450 return 1;
451 }
452 up(&chip->mixer_mutex);
453 return 0;
454}
455
456static snd_kcontrol_new_t vx_control_output_level = {
457 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
458 .name = "Master Playback Volume",
459 .info = vx_output_level_info,
460 .get = vx_output_level_get,
461 .put = vx_output_level_put,
462};
463
464/*
465 * audio source select
466 */
467static int vx_audio_src_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
468{
469 static char *texts_mic[3] = {
470 "Digital", "Line", "Mic"
471 };
472 static char *texts_vx2[2] = {
473 "Digital", "Analog"
474 };
475 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
476
477 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
478 uinfo->count = 1;
479 if (chip->type >= VX_TYPE_VXPOCKET) {
480 uinfo->value.enumerated.items = 3;
481 if (uinfo->value.enumerated.item > 2)
482 uinfo->value.enumerated.item = 2;
483 strcpy(uinfo->value.enumerated.name,
484 texts_mic[uinfo->value.enumerated.item]);
485 } else {
486 uinfo->value.enumerated.items = 2;
487 if (uinfo->value.enumerated.item > 1)
488 uinfo->value.enumerated.item = 1;
489 strcpy(uinfo->value.enumerated.name,
490 texts_vx2[uinfo->value.enumerated.item]);
491 }
492 return 0;
493}
494
495static int vx_audio_src_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
496{
497 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
498 ucontrol->value.enumerated.item[0] = chip->audio_source_target;
499 return 0;
500}
501
502static int vx_audio_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
503{
504 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
505 down(&chip->mixer_mutex);
506 if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) {
507 chip->audio_source_target = ucontrol->value.enumerated.item[0];
508 vx_sync_audio_source(chip);
509 up(&chip->mixer_mutex);
510 return 1;
511 }
512 up(&chip->mixer_mutex);
513 return 0;
514}
515
516static snd_kcontrol_new_t vx_control_audio_src = {
517 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
518 .name = "Capture Source",
519 .info = vx_audio_src_info,
520 .get = vx_audio_src_get,
521 .put = vx_audio_src_put,
522};
523
524/*
525 * clock mode selection
526 */
527static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
528{
529 static char *texts[3] = {
530 "Auto", "Internal", "External"
531 };
532
533 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
534 uinfo->count = 1;
535 uinfo->value.enumerated.items = 3;
536 if (uinfo->value.enumerated.item > 2)
537 uinfo->value.enumerated.item = 2;
538 strcpy(uinfo->value.enumerated.name,
539 texts[uinfo->value.enumerated.item]);
540 return 0;
541}
542
543static int vx_clock_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
544{
545 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
546 ucontrol->value.enumerated.item[0] = chip->clock_mode;
547 return 0;
548}
549
550static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
551{
552 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
553 down(&chip->mixer_mutex);
554 if (chip->clock_mode != ucontrol->value.enumerated.item[0]) {
555 chip->clock_mode = ucontrol->value.enumerated.item[0];
556 vx_set_clock(chip, chip->freq);
557 up(&chip->mixer_mutex);
558 return 1;
559 }
560 up(&chip->mixer_mutex);
561 return 0;
562}
563
564static snd_kcontrol_new_t vx_control_clock_mode = {
565 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
566 .name = "Clock Mode",
567 .info = vx_clock_mode_info,
568 .get = vx_clock_mode_get,
569 .put = vx_clock_mode_put,
570};
571
572/*
573 * Audio Gain
574 */
575static int vx_audio_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
576{
577 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
578 uinfo->count = 2;
579 uinfo->value.integer.min = 0;
580 uinfo->value.integer.max = CVAL_MAX;
581 return 0;
582}
583
584static int vx_audio_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
585{
586 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
587 int audio = kcontrol->private_value & 0xff;
588 int capture = (kcontrol->private_value >> 8) & 1;
589
590 down(&chip->mixer_mutex);
591 ucontrol->value.integer.value[0] = chip->audio_gain[capture][audio];
592 ucontrol->value.integer.value[1] = chip->audio_gain[capture][audio+1];
593 up(&chip->mixer_mutex);
594 return 0;
595}
596
597static int vx_audio_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
598{
599 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
600 int audio = kcontrol->private_value & 0xff;
601 int capture = (kcontrol->private_value >> 8) & 1;
602
603 down(&chip->mixer_mutex);
604 if (ucontrol->value.integer.value[0] != chip->audio_gain[capture][audio] ||
605 ucontrol->value.integer.value[1] != chip->audio_gain[capture][audio+1]) {
606 vx_set_audio_gain(chip, audio, capture, ucontrol->value.integer.value[0]);
607 vx_set_audio_gain(chip, audio+1, capture, ucontrol->value.integer.value[1]);
608 up(&chip->mixer_mutex);
609 return 1;
610 }
611 up(&chip->mixer_mutex);
612 return 0;
613}
614
615static int vx_audio_monitor_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
616{
617 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
618 int audio = kcontrol->private_value & 0xff;
619
620 down(&chip->mixer_mutex);
621 ucontrol->value.integer.value[0] = chip->audio_monitor[audio];
622 ucontrol->value.integer.value[1] = chip->audio_monitor[audio+1];
623 up(&chip->mixer_mutex);
624 return 0;
625}
626
627static int vx_audio_monitor_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
628{
629 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
630 int audio = kcontrol->private_value & 0xff;
631
632 down(&chip->mixer_mutex);
633 if (ucontrol->value.integer.value[0] != chip->audio_monitor[audio] ||
634 ucontrol->value.integer.value[1] != chip->audio_monitor[audio+1]) {
635 vx_set_monitor_level(chip, audio, ucontrol->value.integer.value[0],
636 chip->audio_monitor_active[audio]);
637 vx_set_monitor_level(chip, audio+1, ucontrol->value.integer.value[1],
638 chip->audio_monitor_active[audio+1]);
639 up(&chip->mixer_mutex);
640 return 1;
641 }
642 up(&chip->mixer_mutex);
643 return 0;
644}
645
646static int vx_audio_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
647{
648 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
649 uinfo->count = 2;
650 uinfo->value.integer.min = 0;
651 uinfo->value.integer.max = 1;
652 return 0;
653}
654
655static int vx_audio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
656{
657 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
658 int audio = kcontrol->private_value & 0xff;
659
660 down(&chip->mixer_mutex);
661 ucontrol->value.integer.value[0] = chip->audio_active[audio];
662 ucontrol->value.integer.value[1] = chip->audio_active[audio+1];
663 up(&chip->mixer_mutex);
664 return 0;
665}
666
667static int vx_audio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
668{
669 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
670 int audio = kcontrol->private_value & 0xff;
671
672 down(&chip->mixer_mutex);
673 if (ucontrol->value.integer.value[0] != chip->audio_active[audio] ||
674 ucontrol->value.integer.value[1] != chip->audio_active[audio+1]) {
675 vx_set_audio_switch(chip, audio, ucontrol->value.integer.value[0]);
676 vx_set_audio_switch(chip, audio+1, ucontrol->value.integer.value[1]);
677 up(&chip->mixer_mutex);
678 return 1;
679 }
680 up(&chip->mixer_mutex);
681 return 0;
682}
683
684static int vx_monitor_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
685{
686 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
687 int audio = kcontrol->private_value & 0xff;
688
689 down(&chip->mixer_mutex);
690 ucontrol->value.integer.value[0] = chip->audio_monitor_active[audio];
691 ucontrol->value.integer.value[1] = chip->audio_monitor_active[audio+1];
692 up(&chip->mixer_mutex);
693 return 0;
694}
695
696static int vx_monitor_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
697{
698 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
699 int audio = kcontrol->private_value & 0xff;
700
701 down(&chip->mixer_mutex);
702 if (ucontrol->value.integer.value[0] != chip->audio_monitor_active[audio] ||
703 ucontrol->value.integer.value[1] != chip->audio_monitor_active[audio+1]) {
704 vx_set_monitor_level(chip, audio, chip->audio_monitor[audio],
705 ucontrol->value.integer.value[0]);
706 vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1],
707 ucontrol->value.integer.value[1]);
708 up(&chip->mixer_mutex);
709 return 1;
710 }
711 up(&chip->mixer_mutex);
712 return 0;
713}
714
715static snd_kcontrol_new_t vx_control_audio_gain = {
716 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
717 /* name will be filled later */
718 .info = vx_audio_gain_info,
719 .get = vx_audio_gain_get,
720 .put = vx_audio_gain_put
721};
722static snd_kcontrol_new_t vx_control_output_switch = {
723 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
724 .name = "PCM Playback Switch",
725 .info = vx_audio_sw_info,
726 .get = vx_audio_sw_get,
727 .put = vx_audio_sw_put
728};
729static snd_kcontrol_new_t vx_control_monitor_gain = {
730 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
731 .name = "Monitoring Volume",
732 .info = vx_audio_gain_info, /* shared */
733 .get = vx_audio_monitor_get,
734 .put = vx_audio_monitor_put
735};
736static snd_kcontrol_new_t vx_control_monitor_switch = {
737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
738 .name = "Monitoring Switch",
739 .info = vx_audio_sw_info, /* shared */
740 .get = vx_monitor_sw_get,
741 .put = vx_monitor_sw_put
742};
743
744
745/*
746 * IEC958 status bits
747 */
748static int vx_iec958_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
749{
750 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
751 uinfo->count = 1;
752 return 0;
753}
754
755static int vx_iec958_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
756{
757 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
758
759 down(&chip->mixer_mutex);
760 ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff;
761 ucontrol->value.iec958.status[1] = (chip->uer_bits >> 8) & 0xff;
762 ucontrol->value.iec958.status[2] = (chip->uer_bits >> 16) & 0xff;
763 ucontrol->value.iec958.status[3] = (chip->uer_bits >> 24) & 0xff;
764 up(&chip->mixer_mutex);
765 return 0;
766}
767
768static int vx_iec958_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol)
769{
770 ucontrol->value.iec958.status[0] = 0xff;
771 ucontrol->value.iec958.status[1] = 0xff;
772 ucontrol->value.iec958.status[2] = 0xff;
773 ucontrol->value.iec958.status[3] = 0xff;
774 return 0;
775}
776
777static int vx_iec958_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
778{
779 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
780 unsigned int val;
781
782 val = (ucontrol->value.iec958.status[0] << 0) |
783 (ucontrol->value.iec958.status[1] << 8) |
784 (ucontrol->value.iec958.status[2] << 16) |
785 (ucontrol->value.iec958.status[3] << 24);
786 down(&chip->mixer_mutex);
787 if (chip->uer_bits != val) {
788 chip->uer_bits = val;
789 vx_set_iec958_status(chip, val);
790 up(&chip->mixer_mutex);
791 return 1;
792 }
793 up(&chip->mixer_mutex);
794 return 0;
795}
796
797static snd_kcontrol_new_t vx_control_iec958_mask = {
798 .access = SNDRV_CTL_ELEM_ACCESS_READ,
799 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
800 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
801 .info = vx_iec958_info, /* shared */
802 .get = vx_iec958_mask_get,
803};
804
805static snd_kcontrol_new_t vx_control_iec958 = {
806 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
807 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
808 .info = vx_iec958_info,
809 .get = vx_iec958_get,
810 .put = vx_iec958_put
811};
812
813
814/*
815 * VU meter
816 */
817
818#define METER_MAX 0xff
819#define METER_SHIFT 16
820
821static int vx_vu_meter_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
822{
823 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
824 uinfo->count = 2;
825 uinfo->value.integer.min = 0;
826 uinfo->value.integer.max = METER_MAX;
827 return 0;
828}
829
830static int vx_vu_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
831{
832 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
833 struct vx_vu_meter meter[2];
834 int audio = kcontrol->private_value & 0xff;
835 int capture = (kcontrol->private_value >> 8) & 1;
836
837 vx_get_audio_vu_meter(chip, audio, capture, meter);
838 ucontrol->value.integer.value[0] = meter[0].vu_level >> METER_SHIFT;
839 ucontrol->value.integer.value[1] = meter[1].vu_level >> METER_SHIFT;
840 return 0;
841}
842
843static int vx_peak_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
844{
845 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
846 struct vx_vu_meter meter[2];
847 int audio = kcontrol->private_value & 0xff;
848 int capture = (kcontrol->private_value >> 8) & 1;
849
850 vx_get_audio_vu_meter(chip, audio, capture, meter);
851 ucontrol->value.integer.value[0] = meter[0].peak_level >> METER_SHIFT;
852 ucontrol->value.integer.value[1] = meter[1].peak_level >> METER_SHIFT;
853 return 0;
854}
855
856static int vx_saturation_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
857{
858 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
859 uinfo->count = 2;
860 uinfo->value.integer.min = 0;
861 uinfo->value.integer.max = 1;
862 return 0;
863}
864
865static int vx_saturation_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
866{
867 vx_core_t *chip = snd_kcontrol_chip(kcontrol);
868 struct vx_vu_meter meter[2];
869 int audio = kcontrol->private_value & 0xff;
870
871 vx_get_audio_vu_meter(chip, audio, 1, meter); /* capture only */
872 ucontrol->value.integer.value[0] = meter[0].saturated;
873 ucontrol->value.integer.value[1] = meter[1].saturated;
874 return 0;
875}
876
877static snd_kcontrol_new_t vx_control_vu_meter = {
878 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
879 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
880 /* name will be filled later */
881 .info = vx_vu_meter_info,
882 .get = vx_vu_meter_get,
883};
884
885static snd_kcontrol_new_t vx_control_peak_meter = {
886 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
887 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
888 /* name will be filled later */
889 .info = vx_vu_meter_info, /* shared */
890 .get = vx_peak_meter_get,
891};
892
893static snd_kcontrol_new_t vx_control_saturation = {
894 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
895 .name = "Input Saturation",
896 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
897 .info = vx_saturation_info,
898 .get = vx_saturation_get,
899};
900
901
902
903/*
904 *
905 */
906
907int snd_vx_mixer_new(vx_core_t *chip)
908{
909 unsigned int i, c;
910 int err;
911 snd_kcontrol_new_t temp;
912 snd_card_t *card = chip->card;
913 char name[32];
914
915 strcpy(card->mixername, card->driver);
916
917 /* output level controls */
918 for (i = 0; i < chip->hw->num_outs; i++) {
919 temp = vx_control_output_level;
920 temp.index = i;
921 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
922 return err;
923 }
924
925 /* PCM volumes, switches, monitoring */
926 for (i = 0; i < chip->hw->num_outs; i++) {
927 int val = i * 2;
928 temp = vx_control_audio_gain;
929 temp.index = i;
930 temp.name = "PCM Playback Volume";
931 temp.private_value = val;
932 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
933 return err;
934 temp = vx_control_output_switch;
935 temp.index = i;
936 temp.private_value = val;
937 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
938 return err;
939 temp = vx_control_monitor_gain;
940 temp.index = i;
941 temp.private_value = val;
942 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
943 return err;
944 temp = vx_control_monitor_switch;
945 temp.index = i;
946 temp.private_value = val;
947 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
948 return err;
949 }
950 for (i = 0; i < chip->hw->num_outs; i++) {
951 temp = vx_control_audio_gain;
952 temp.index = i;
953 temp.name = "PCM Capture Volume";
954 temp.private_value = (i * 2) | (1 << 8);
955 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
956 return err;
957 }
958
959 /* Audio source */
960 if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0)
961 return err;
962 /* clock mode */
963 if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0)
964 return err;
965 /* IEC958 controls */
966 if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0)
967 return err;
968 if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip))) < 0)
969 return err;
970 /* VU, peak, saturation meters */
971 for (c = 0; c < 2; c++) {
972 static char *dir[2] = { "Output", "Input" };
973 for (i = 0; i < chip->hw->num_ins; i++) {
974 int val = (i * 2) | (c << 8);
975 if (c == 1) {
976 temp = vx_control_saturation;
977 temp.index = i;
978 temp.private_value = val;
979 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
980 return err;
981 }
982 sprintf(name, "%s VU Meter", dir[c]);
983 temp = vx_control_vu_meter;
984 temp.index = i;
985 temp.name = name;
986 temp.private_value = val;
987 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
988 return err;
989 sprintf(name, "%s Peak Meter", dir[c]);
990 temp = vx_control_peak_meter;
991 temp.index = i;
992 temp.name = name;
993 temp.private_value = val;
994 if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0)
995 return err;
996 }
997 }
998 vx_reset_audio_levels(chip);
999 return 0;
1000}
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c
new file mode 100644
index 000000000000..98587176b327
--- /dev/null
+++ b/sound/drivers/vx/vx_pcm.c
@@ -0,0 +1,1312 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * PCM part
5 *
6 * Copyright (c) 2002,2003 by Takashi Iwai <tiwai@suse.de>
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 * STRATEGY
24 * for playback, we send series of "chunks", which size is equal with the
25 * IBL size, typically 126 samples. at each end of chunk, the end-of-buffer
26 * interrupt is notified, and the interrupt handler will feed the next chunk.
27 *
28 * the current position is calculated from the sample count RMH.
29 * pipe->transferred is the counter of data which has been already transferred.
30 * if this counter reaches to the period size, snd_pcm_period_elapsed() will
31 * be issued.
32 *
33 * for capture, the situation is much easier.
34 * to get a low latency response, we'll check the capture streams at each
35 * interrupt (capture stream has no EOB notification). if the pending
36 * data is accumulated to the period size, snd_pcm_period_elapsed() is
37 * called and the pointer is updated.
38 *
39 * the current point of read buffer is kept in pipe->hw_ptr. note that
40 * this is in bytes.
41 *
42 *
43 * TODO
44 * - linked trigger for full-duplex mode.
45 * - scheduled action on the stream.
46 */
47
48#include <sound/driver.h>
49#include <linux/slab.h>
50#include <linux/vmalloc.h>
51#include <linux/delay.h>
52#include <sound/core.h>
53#include <sound/asoundef.h>
54#include <sound/pcm.h>
55#include <sound/vx_core.h>
56#include "vx_cmd.h"
57
58
59/*
60 * we use a vmalloc'ed (sg-)buffer
61 */
62
63/* get the physical page pointer on the given offset */
64static struct page *snd_pcm_get_vmalloc_page(snd_pcm_substream_t *subs, unsigned long offset)
65{
66 void *pageptr = subs->runtime->dma_area + offset;
67 return vmalloc_to_page(pageptr);
68}
69
70/*
71 * allocate a buffer via vmalloc_32().
72 * called from hw_params
73 * NOTE: this may be called not only once per pcm open!
74 */
75static int snd_pcm_alloc_vmalloc_buffer(snd_pcm_substream_t *subs, size_t size)
76{
77 snd_pcm_runtime_t *runtime = subs->runtime;
78 if (runtime->dma_area) {
79 /* already allocated */
80 if (runtime->dma_bytes >= size)
81 return 0; /* already enough large */
82 vfree_nocheck(runtime->dma_area); /* bypass the memory wrapper */
83 }
84 runtime->dma_area = vmalloc_32(size);
85 if (! runtime->dma_area)
86 return -ENOMEM;
87 memset(runtime->dma_area, 0, size);
88 runtime->dma_bytes = size;
89 return 1; /* changed */
90}
91
92/*
93 * free the buffer.
94 * called from hw_free callback
95 * NOTE: this may be called not only once per pcm open!
96 */
97static int snd_pcm_free_vmalloc_buffer(snd_pcm_substream_t *subs)
98{
99 snd_pcm_runtime_t *runtime = subs->runtime;
100 if (runtime->dma_area) {
101 vfree_nocheck(runtime->dma_area); /* bypass the memory wrapper */
102 runtime->dma_area = NULL;
103 }
104 return 0;
105}
106
107
108/*
109 * read three pending pcm bytes via inb()
110 */
111static void vx_pcm_read_per_bytes(vx_core_t *chip, snd_pcm_runtime_t *runtime, vx_pipe_t *pipe)
112{
113 int offset = pipe->hw_ptr;
114 unsigned char *buf = (unsigned char *)(runtime->dma_area + offset);
115 *buf++ = vx_inb(chip, RXH);
116 if (++offset >= pipe->buffer_bytes) {
117 offset = 0;
118 buf = (unsigned char *)runtime->dma_area;
119 }
120 *buf++ = vx_inb(chip, RXM);
121 if (++offset >= pipe->buffer_bytes) {
122 offset = 0;
123 buf = (unsigned char *)runtime->dma_area;
124 }
125 *buf++ = vx_inb(chip, RXL);
126 if (++offset >= pipe->buffer_bytes) {
127 offset = 0;
128 buf = (unsigned char *)runtime->dma_area;
129 }
130 pipe->hw_ptr = offset;
131}
132
133/*
134 * vx_set_pcx_time - convert from the PC time to the RMH status time.
135 * @pc_time: the pointer for the PC-time to set
136 * @dsp_time: the pointer for RMH status time array
137 */
138static void vx_set_pcx_time(vx_core_t *chip, pcx_time_t *pc_time, unsigned int *dsp_time)
139{
140 dsp_time[0] = (unsigned int)((*pc_time) >> 24) & PCX_TIME_HI_MASK;
141 dsp_time[1] = (unsigned int)(*pc_time) & MASK_DSP_WORD;
142}
143
144/*
145 * vx_set_differed_time - set the differed time if specified
146 * @rmh: the rmh record to modify
147 * @pipe: the pipe to be checked
148 *
149 * if the pipe is programmed with the differed time, set the DSP time
150 * on the rmh and changes its command length.
151 *
152 * returns the increase of the command length.
153 */
154static int vx_set_differed_time(vx_core_t *chip, struct vx_rmh *rmh, vx_pipe_t *pipe)
155{
156 /* Update The length added to the RMH command by the timestamp */
157 if (! (pipe->differed_type & DC_DIFFERED_DELAY))
158 return 0;
159
160 /* Set the T bit */
161 rmh->Cmd[0] |= DSP_DIFFERED_COMMAND_MASK;
162
163 /* Time stamp is the 1st following parameter */
164 vx_set_pcx_time(chip, &pipe->pcx_time, &rmh->Cmd[1]);
165
166 /* Add the flags to a notified differed command */
167 if (pipe->differed_type & DC_NOTIFY_DELAY)
168 rmh->Cmd[1] |= NOTIFY_MASK_TIME_HIGH ;
169
170 /* Add the flags to a multiple differed command */
171 if (pipe->differed_type & DC_MULTIPLE_DELAY)
172 rmh->Cmd[1] |= MULTIPLE_MASK_TIME_HIGH;
173
174 /* Add the flags to a stream-time differed command */
175 if (pipe->differed_type & DC_STREAM_TIME_DELAY)
176 rmh->Cmd[1] |= STREAM_MASK_TIME_HIGH;
177
178 rmh->LgCmd += 2;
179 return 2;
180}
181
182/*
183 * vx_set_stream_format - send the stream format command
184 * @pipe: the affected pipe
185 * @data: format bitmask
186 */
187static int vx_set_stream_format(vx_core_t *chip, vx_pipe_t *pipe, unsigned int data)
188{
189 struct vx_rmh rmh;
190
191 vx_init_rmh(&rmh, pipe->is_capture ?
192 CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
193 rmh.Cmd[0] |= pipe->number << FIELD_SIZE;
194
195 /* Command might be longer since we may have to add a timestamp */
196 vx_set_differed_time(chip, &rmh, pipe);
197
198 rmh.Cmd[rmh.LgCmd] = (data & 0xFFFFFF00) >> 8;
199 rmh.Cmd[rmh.LgCmd + 1] = (data & 0xFF) << 16 /*| (datal & 0xFFFF00) >> 8*/;
200 rmh.LgCmd += 2;
201
202 return vx_send_msg(chip, &rmh);
203}
204
205
206/*
207 * vx_set_format - set the format of a pipe
208 * @pipe: the affected pipe
209 * @runtime: pcm runtime instance to be referred
210 *
211 * returns 0 if successful, or a negative error code.
212 */
213static int vx_set_format(vx_core_t *chip, vx_pipe_t *pipe,
214 snd_pcm_runtime_t *runtime)
215{
216 unsigned int header = HEADER_FMT_BASE;
217
218 if (runtime->channels == 1)
219 header |= HEADER_FMT_MONO;
220 if (snd_pcm_format_little_endian(runtime->format))
221 header |= HEADER_FMT_INTEL;
222 if (runtime->rate < 32000 && runtime->rate > 11025)
223 header |= HEADER_FMT_UPTO32;
224 else if (runtime->rate <= 11025)
225 header |= HEADER_FMT_UPTO11;
226
227 switch (snd_pcm_format_physical_width(runtime->format)) {
228 // case 8: break;
229 case 16: header |= HEADER_FMT_16BITS; break;
230 case 24: header |= HEADER_FMT_24BITS; break;
231 default :
232 snd_BUG();
233 return -EINVAL;
234 };
235
236 return vx_set_stream_format(chip, pipe, header);
237}
238
239/*
240 * set / query the IBL size
241 */
242static int vx_set_ibl(vx_core_t *chip, struct vx_ibl_info *info)
243{
244 int err;
245 struct vx_rmh rmh;
246
247 vx_init_rmh(&rmh, CMD_IBL);
248 rmh.Cmd[0] |= info->size & 0x03ffff;
249 err = vx_send_msg(chip, &rmh);
250 if (err < 0)
251 return err;
252 info->size = rmh.Stat[0];
253 info->max_size = rmh.Stat[1];
254 info->min_size = rmh.Stat[2];
255 info->granularity = rmh.Stat[3];
256 snd_printdd(KERN_DEBUG "vx_set_ibl: size = %d, max = %d, min = %d, gran = %d\n",
257 info->size, info->max_size, info->min_size, info->granularity);
258 return 0;
259}
260
261
262/*
263 * vx_get_pipe_state - get the state of a pipe
264 * @pipe: the pipe to be checked
265 * @state: the pointer for the returned state
266 *
267 * checks the state of a given pipe, and stores the state (1 = running,
268 * 0 = paused) on the given pointer.
269 *
270 * called from trigger callback only
271 */
272static int vx_get_pipe_state(vx_core_t *chip, vx_pipe_t *pipe, int *state)
273{
274 int err;
275 struct vx_rmh rmh;
276
277 vx_init_rmh(&rmh, CMD_PIPE_STATE);
278 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
279 err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
280 if (! err)
281 *state = (rmh.Stat[0] & (1 << pipe->number)) ? 1 : 0;
282 return err;
283}
284
285
286/*
287 * vx_query_hbuffer_size - query available h-buffer size in bytes
288 * @pipe: the pipe to be checked
289 *
290 * return the available size on h-buffer in bytes,
291 * or a negative error code.
292 *
293 * NOTE: calling this function always switches to the stream mode.
294 * you'll need to disconnect the host to get back to the
295 * normal mode.
296 */
297static int vx_query_hbuffer_size(vx_core_t *chip, vx_pipe_t *pipe)
298{
299 int result;
300 struct vx_rmh rmh;
301
302 vx_init_rmh(&rmh, CMD_SIZE_HBUFFER);
303 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
304 if (pipe->is_capture)
305 rmh.Cmd[0] |= 0x00000001;
306 result = vx_send_msg(chip, &rmh);
307 if (! result)
308 result = rmh.Stat[0] & 0xffff;
309 return result;
310}
311
312
313/*
314 * vx_pipe_can_start - query whether a pipe is ready for start
315 * @pipe: the pipe to be checked
316 *
317 * return 1 if ready, 0 if not ready, and negative value on error.
318 *
319 * called from trigger callback only
320 */
321static int vx_pipe_can_start(vx_core_t *chip, vx_pipe_t *pipe)
322{
323 int err;
324 struct vx_rmh rmh;
325
326 vx_init_rmh(&rmh, CMD_CAN_START_PIPE);
327 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
328 rmh.Cmd[0] |= 1;
329
330 err = vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
331 if (! err) {
332 if (rmh.Stat[0])
333 err = 1;
334 }
335 return err;
336}
337
338/*
339 * vx_conf_pipe - tell the pipe to stand by and wait for IRQA.
340 * @pipe: the pipe to be configured
341 */
342static int vx_conf_pipe(vx_core_t *chip, vx_pipe_t *pipe)
343{
344 struct vx_rmh rmh;
345
346 vx_init_rmh(&rmh, CMD_CONF_PIPE);
347 if (pipe->is_capture)
348 rmh.Cmd[0] |= COMMAND_RECORD_MASK;
349 rmh.Cmd[1] = 1 << pipe->number;
350 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
351}
352
353/*
354 * vx_send_irqa - trigger IRQA
355 */
356static int vx_send_irqa(vx_core_t *chip)
357{
358 struct vx_rmh rmh;
359
360 vx_init_rmh(&rmh, CMD_SEND_IRQA);
361 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
362}
363
364
365#define MAX_WAIT_FOR_DSP 250
366/*
367 * vx boards do not support inter-card sync, besides
368 * only 126 samples require to be prepared before a pipe can start
369 */
370#define CAN_START_DELAY 2 /* wait 2ms only before asking if the pipe is ready*/
371#define WAIT_STATE_DELAY 2 /* wait 2ms after irqA was requested and check if the pipe state toggled*/
372
373/*
374 * vx_toggle_pipe - start / pause a pipe
375 * @pipe: the pipe to be triggered
376 * @state: start = 1, pause = 0
377 *
378 * called from trigger callback only
379 *
380 */
381static int vx_toggle_pipe(vx_core_t *chip, vx_pipe_t *pipe, int state)
382{
383 int err, i, cur_state;
384
385 /* Check the pipe is not already in the requested state */
386 if (vx_get_pipe_state(chip, pipe, &cur_state) < 0)
387 return -EBADFD;
388 if (state == cur_state)
389 return 0;
390
391 /* If a start is requested, ask the DSP to get prepared
392 * and wait for a positive acknowledge (when there are
393 * enough sound buffer for this pipe)
394 */
395 if (state) {
396 for (i = 0 ; i < MAX_WAIT_FOR_DSP; i++) {
397 err = vx_pipe_can_start(chip, pipe);
398 if (err > 0)
399 break;
400 /* Wait for a few, before asking again
401 * to avoid flooding the DSP with our requests
402 */
403 mdelay(1);
404 }
405 }
406
407 if ((err = vx_conf_pipe(chip, pipe)) < 0)
408 return err;
409
410 if ((err = vx_send_irqa(chip)) < 0)
411 return err;
412
413 /* If it completes successfully, wait for the pipes
414 * reaching the expected state before returning
415 * Check one pipe only (since they are synchronous)
416 */
417 for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
418 err = vx_get_pipe_state(chip, pipe, &cur_state);
419 if (err < 0 || cur_state == state)
420 break;
421 err = -EIO;
422 mdelay(1);
423 }
424 return err < 0 ? -EIO : 0;
425}
426
427
428/*
429 * vx_stop_pipe - stop a pipe
430 * @pipe: the pipe to be stopped
431 *
432 * called from trigger callback only
433 */
434static int vx_stop_pipe(vx_core_t *chip, vx_pipe_t *pipe)
435{
436 struct vx_rmh rmh;
437 vx_init_rmh(&rmh, CMD_STOP_PIPE);
438 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
439 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
440}
441
442
443/*
444 * vx_alloc_pipe - allocate a pipe and initialize the pipe instance
445 * @capture: 0 = playback, 1 = capture operation
446 * @audioid: the audio id to be assigned
447 * @num_audio: number of audio channels
448 * @pipep: the returned pipe instance
449 *
450 * return 0 on success, or a negative error code.
451 */
452static int vx_alloc_pipe(vx_core_t *chip, int capture,
453 int audioid, int num_audio,
454 vx_pipe_t **pipep)
455{
456 int err;
457 vx_pipe_t *pipe;
458 struct vx_rmh rmh;
459 int data_mode;
460
461 *pipep = NULL;
462 vx_init_rmh(&rmh, CMD_RES_PIPE);
463 vx_set_pipe_cmd_params(&rmh, capture, audioid, num_audio);
464#if 0 // NYI
465 if (underrun_skip_sound)
466 rmh.Cmd[0] |= BIT_SKIP_SOUND;
467#endif // NYI
468 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;
469 if (! capture && data_mode)
470 rmh.Cmd[0] |= BIT_DATA_MODE;
471 err = vx_send_msg(chip, &rmh);
472 if (err < 0)
473 return err;
474
475 /* initialize the pipe record */
476 pipe = kcalloc(1, sizeof(*pipe), GFP_KERNEL);
477 if (! pipe) {
478 /* release the pipe */
479 vx_init_rmh(&rmh, CMD_FREE_PIPE);
480 vx_set_pipe_cmd_params(&rmh, capture, audioid, 0);
481 vx_send_msg(chip, &rmh);
482 return -ENOMEM;
483 }
484
485 /* the pipe index should be identical with the audio index */
486 pipe->number = audioid;
487 pipe->is_capture = capture;
488 pipe->channels = num_audio;
489 pipe->differed_type = 0;
490 pipe->pcx_time = 0;
491 pipe->data_mode = data_mode;
492 *pipep = pipe;
493
494 return 0;
495}
496
497
498/*
499 * vx_free_pipe - release a pipe
500 * @pipe: pipe to be released
501 */
502static int vx_free_pipe(vx_core_t *chip, vx_pipe_t *pipe)
503{
504 struct vx_rmh rmh;
505
506 vx_init_rmh(&rmh, CMD_FREE_PIPE);
507 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
508 vx_send_msg(chip, &rmh);
509
510 kfree(pipe);
511 return 0;
512}
513
514
515/*
516 * vx_start_stream - start the stream
517 *
518 * called from trigger callback only
519 */
520static int vx_start_stream(vx_core_t *chip, vx_pipe_t *pipe)
521{
522 struct vx_rmh rmh;
523
524 vx_init_rmh(&rmh, CMD_START_ONE_STREAM);
525 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
526 vx_set_differed_time(chip, &rmh, pipe);
527 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
528}
529
530
531/*
532 * vx_stop_stream - stop the stream
533 *
534 * called from trigger callback only
535 */
536static int vx_stop_stream(vx_core_t *chip, vx_pipe_t *pipe)
537{
538 struct vx_rmh rmh;
539
540 vx_init_rmh(&rmh, CMD_STOP_STREAM);
541 vx_set_stream_cmd_params(&rmh, pipe->is_capture, pipe->number);
542 return vx_send_msg_nolock(chip, &rmh); /* no lock needed for trigger */
543}
544
545
546/*
547 * playback hw information
548 */
549
550static snd_pcm_hardware_t vx_pcm_playback_hw = {
551 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
552 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID |
553 SNDRV_PCM_INFO_RESUME),
554 .formats = /*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
555 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
556 .rate_min = 5000,
557 .rate_max = 48000,
558 .channels_min = 1,
559 .channels_max = 2,
560 .buffer_bytes_max = (128*1024),
561 .period_bytes_min = 126,
562 .period_bytes_max = (128*1024),
563 .periods_min = 2,
564 .periods_max = VX_MAX_PERIODS,
565 .fifo_size = 126,
566};
567
568
569static void vx_pcm_delayed_start(unsigned long arg);
570
571/*
572 * vx_pcm_playback_open - open callback for playback
573 */
574static int vx_pcm_playback_open(snd_pcm_substream_t *subs)
575{
576 snd_pcm_runtime_t *runtime = subs->runtime;
577 vx_core_t *chip = snd_pcm_substream_chip(subs);
578 vx_pipe_t *pipe = NULL;
579 unsigned int audio;
580 int err;
581
582 if (chip->chip_status & VX_STAT_IS_STALE)
583 return -EBUSY;
584
585 audio = subs->pcm->device * 2;
586 snd_assert(audio < chip->audio_outs, return -EINVAL);
587
588 /* playback pipe may have been already allocated for monitoring */
589 pipe = chip->playback_pipes[audio];
590 if (! pipe) {
591 /* not allocated yet */
592 err = vx_alloc_pipe(chip, 0, audio, 2, &pipe); /* stereo playback */
593 if (err < 0)
594 return err;
595 chip->playback_pipes[audio] = pipe;
596 }
597 /* open for playback */
598 pipe->references++;
599
600 pipe->substream = subs;
601 tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
602 chip->playback_pipes[audio] = pipe;
603
604 runtime->hw = vx_pcm_playback_hw;
605 runtime->hw.period_bytes_min = chip->ibl.size;
606 runtime->private_data = pipe;
607
608 /* align to 4 bytes (otherwise will be problematic when 24bit is used) */
609 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
610 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
611
612 return 0;
613}
614
615/*
616 * vx_pcm_playback_close - close callback for playback
617 */
618static int vx_pcm_playback_close(snd_pcm_substream_t *subs)
619{
620 vx_core_t *chip = snd_pcm_substream_chip(subs);
621 vx_pipe_t *pipe;
622
623 if (! subs->runtime->private_data)
624 return -EINVAL;
625
626 pipe = subs->runtime->private_data;
627
628 if (--pipe->references == 0) {
629 chip->playback_pipes[pipe->number] = NULL;
630 vx_free_pipe(chip, pipe);
631 }
632
633 return 0;
634
635}
636
637
638/*
639 * vx_notify_end_of_buffer - send "end-of-buffer" notifier at the given pipe
640 * @pipe: the pipe to notify
641 *
642 * NB: call with a certain lock.
643 */
644static int vx_notify_end_of_buffer(vx_core_t *chip, vx_pipe_t *pipe)
645{
646 int err;
647 struct vx_rmh rmh; /* use a temporary rmh here */
648
649 /* Toggle Dsp Host Interface into Message mode */
650 vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);
651 vx_init_rmh(&rmh, CMD_NOTIFY_END_OF_BUFFER);
652 vx_set_stream_cmd_params(&rmh, 0, pipe->number);
653 err = vx_send_msg_nolock(chip, &rmh);
654 if (err < 0)
655 return err;
656 /* Toggle Dsp Host Interface back to sound transfer mode */
657 vx_send_rih_nolock(chip, IRQ_PAUSE_START_CONNECT);
658 return 0;
659}
660
661/*
662 * vx_pcm_playback_transfer_chunk - transfer a single chunk
663 * @subs: substream
664 * @pipe: the pipe to transfer
665 * @size: chunk size in bytes
666 *
667 * transfer a single buffer chunk. EOB notificaton is added after that.
668 * called from the interrupt handler, too.
669 *
670 * return 0 if ok.
671 */
672static int vx_pcm_playback_transfer_chunk(vx_core_t *chip, snd_pcm_runtime_t *runtime, vx_pipe_t *pipe, int size)
673{
674 int space, err = 0;
675
676 space = vx_query_hbuffer_size(chip, pipe);
677 if (space < 0) {
678 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
679 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
680 snd_printd("error hbuffer\n");
681 return space;
682 }
683 if (space < size) {
684 vx_send_rih(chip, IRQ_CONNECT_STREAM_NEXT);
685 snd_printd("no enough hbuffer space %d\n", space);
686 return -EIO; /* XRUN */
687 }
688
689 /* we don't need irqsave here, because this function
690 * is called from either trigger callback or irq handler
691 */
692 spin_lock(&chip->lock);
693 vx_pseudo_dma_write(chip, runtime, pipe, size);
694 err = vx_notify_end_of_buffer(chip, pipe);
695 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
696 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
697 spin_unlock(&chip->lock);
698 return err;
699}
700
701/*
702 * update the position of the given pipe.
703 * pipe->position is updated and wrapped within the buffer size.
704 * pipe->transferred is updated, too, but the size is not wrapped,
705 * so that the caller can check the total transferred size later
706 * (to call snd_pcm_period_elapsed).
707 */
708static int vx_update_pipe_position(vx_core_t *chip, snd_pcm_runtime_t *runtime, vx_pipe_t *pipe)
709{
710 struct vx_rmh rmh;
711 int err, update;
712 u64 count;
713
714 vx_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);
715 vx_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->number, 0);
716 err = vx_send_msg(chip, &rmh);
717 if (err < 0)
718 return err;
719
720 count = ((u64)(rmh.Stat[0] & 0xfffff) << 24) | (u64)rmh.Stat[1];
721 update = (int)(count - pipe->cur_count);
722 pipe->cur_count = count;
723 pipe->position += update;
724 if (pipe->position >= (int)runtime->buffer_size)
725 pipe->position %= runtime->buffer_size;
726 pipe->transferred += update;
727 return 0;
728}
729
730/*
731 * transfer the pending playback buffer data to DSP
732 * called from interrupt handler
733 */
734static void vx_pcm_playback_transfer(vx_core_t *chip, snd_pcm_substream_t *subs, vx_pipe_t *pipe, int nchunks)
735{
736 int i, err;
737 snd_pcm_runtime_t *runtime = subs->runtime;
738
739 if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
740 return;
741 for (i = 0; i < nchunks; i++) {
742 if ((err = vx_pcm_playback_transfer_chunk(chip, runtime, pipe,
743 chip->ibl.size)) < 0)
744 return;
745 }
746}
747
748/*
749 * update the playback position and call snd_pcm_period_elapsed() if necessary
750 * called from interrupt handler
751 */
752static void vx_pcm_playback_update(vx_core_t *chip, snd_pcm_substream_t *subs, vx_pipe_t *pipe)
753{
754 int err;
755 snd_pcm_runtime_t *runtime = subs->runtime;
756
757 if (pipe->running && ! (chip->chip_status & VX_STAT_IS_STALE)) {
758 if ((err = vx_update_pipe_position(chip, runtime, pipe)) < 0)
759 return;
760 if (pipe->transferred >= (int)runtime->period_size) {
761 pipe->transferred %= runtime->period_size;
762 snd_pcm_period_elapsed(subs);
763 }
764 }
765}
766
767/*
768 * start the stream and pipe.
769 * this function is called from tasklet, which is invoked by the trigger
770 * START callback.
771 */
772static void vx_pcm_delayed_start(unsigned long arg)
773{
774 snd_pcm_substream_t *subs = (snd_pcm_substream_t *)arg;
775 vx_core_t *chip = subs->pcm->private_data;
776 vx_pipe_t *pipe = subs->runtime->private_data;
777 int err;
778
779 /* printk( KERN_DEBUG "DDDD tasklet delayed start jiffies = %ld\n", jiffies);*/
780
781 if ((err = vx_start_stream(chip, pipe)) < 0) {
782 snd_printk(KERN_ERR "vx: cannot start stream\n");
783 return;
784 }
785 if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0) {
786 snd_printk(KERN_ERR "vx: cannot start pipe\n");
787 return;
788 }
789 /* printk( KERN_DEBUG "dddd tasklet delayed start jiffies = %ld \n", jiffies);*/
790}
791
792/*
793 * vx_pcm_playback_trigger - trigger callback for playback
794 */
795static int vx_pcm_trigger(snd_pcm_substream_t *subs, int cmd)
796{
797 vx_core_t *chip = snd_pcm_substream_chip(subs);
798 vx_pipe_t *pipe = subs->runtime->private_data;
799 int err;
800
801 if (chip->chip_status & VX_STAT_IS_STALE)
802 return -EBUSY;
803
804 switch (cmd) {
805 case SNDRV_PCM_TRIGGER_START:
806 case SNDRV_PCM_TRIGGER_RESUME:
807 if (! pipe->is_capture)
808 vx_pcm_playback_transfer(chip, subs, pipe, 2);
809 /* FIXME:
810 * we trigger the pipe using tasklet, so that the interrupts are
811 * issued surely after the trigger is completed.
812 */
813 tasklet_hi_schedule(&pipe->start_tq);
814 chip->pcm_running++;
815 pipe->running = 1;
816 break;
817 case SNDRV_PCM_TRIGGER_STOP:
818 case SNDRV_PCM_TRIGGER_SUSPEND:
819 vx_toggle_pipe(chip, pipe, 0);
820 vx_stop_pipe(chip, pipe);
821 vx_stop_stream(chip, pipe);
822 chip->pcm_running--;
823 pipe->running = 0;
824 break;
825 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
826 if ((err = vx_toggle_pipe(chip, pipe, 0)) < 0)
827 return err;
828 break;
829 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
830 if ((err = vx_toggle_pipe(chip, pipe, 1)) < 0)
831 return err;
832 break;
833 default:
834 return -EINVAL;
835 }
836 return 0;
837}
838
839/*
840 * vx_pcm_playback_pointer - pointer callback for playback
841 */
842static snd_pcm_uframes_t vx_pcm_playback_pointer(snd_pcm_substream_t *subs)
843{
844 snd_pcm_runtime_t *runtime = subs->runtime;
845 vx_pipe_t *pipe = runtime->private_data;
846 return pipe->position;
847}
848
849/*
850 * vx_pcm_hw_params - hw_params callback for playback and capture
851 */
852static int vx_pcm_hw_params(snd_pcm_substream_t *subs,
853 snd_pcm_hw_params_t *hw_params)
854{
855 return snd_pcm_alloc_vmalloc_buffer(subs, params_buffer_bytes(hw_params));
856}
857
858/*
859 * vx_pcm_hw_free - hw_free callback for playback and capture
860 */
861static int vx_pcm_hw_free(snd_pcm_substream_t *subs)
862{
863 return snd_pcm_free_vmalloc_buffer(subs);
864}
865
866/*
867 * vx_pcm_prepare - prepare callback for playback and capture
868 */
869static int vx_pcm_prepare(snd_pcm_substream_t *subs)
870{
871 vx_core_t *chip = snd_pcm_substream_chip(subs);
872 snd_pcm_runtime_t *runtime = subs->runtime;
873 vx_pipe_t *pipe = runtime->private_data;
874 int err, data_mode;
875 // int max_size, nchunks;
876
877 if (chip->chip_status & VX_STAT_IS_STALE)
878 return -EBUSY;
879
880 data_mode = (chip->uer_bits & IEC958_AES0_NONAUDIO) != 0;
881 if (data_mode != pipe->data_mode && ! pipe->is_capture) {
882 /* IEC958 status (raw-mode) was changed */
883 /* we reopen the pipe */
884 struct vx_rmh rmh;
885 snd_printdd(KERN_DEBUG "reopen the pipe with data_mode = %d\n", data_mode);
886 vx_init_rmh(&rmh, CMD_FREE_PIPE);
887 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, 0);
888 if ((err = vx_send_msg(chip, &rmh)) < 0)
889 return err;
890 vx_init_rmh(&rmh, CMD_RES_PIPE);
891 vx_set_pipe_cmd_params(&rmh, 0, pipe->number, pipe->channels);
892 if (data_mode)
893 rmh.Cmd[0] |= BIT_DATA_MODE;
894 if ((err = vx_send_msg(chip, &rmh)) < 0)
895 return err;
896 pipe->data_mode = data_mode;
897 }
898
899 if (chip->pcm_running && chip->freq != runtime->rate) {
900 snd_printk(KERN_ERR "vx: cannot set different clock %d from the current %d\n", runtime->rate, chip->freq);
901 return -EINVAL;
902 }
903 vx_set_clock(chip, runtime->rate);
904
905 if ((err = vx_set_format(chip, pipe, runtime)) < 0)
906 return err;
907
908 if (vx_is_pcmcia(chip)) {
909 pipe->align = 2; /* 16bit word */
910 } else {
911 pipe->align = 4; /* 32bit word */
912 }
913
914 pipe->buffer_bytes = frames_to_bytes(runtime, runtime->buffer_size);
915 pipe->period_bytes = frames_to_bytes(runtime, runtime->period_size);
916 pipe->hw_ptr = 0;
917
918 /* set the timestamp */
919 vx_update_pipe_position(chip, runtime, pipe);
920 /* clear again */
921 pipe->transferred = 0;
922 pipe->position = 0;
923
924 pipe->prepared = 1;
925
926 return 0;
927}
928
929
930/*
931 * operators for PCM playback
932 */
933static snd_pcm_ops_t vx_pcm_playback_ops = {
934 .open = vx_pcm_playback_open,
935 .close = vx_pcm_playback_close,
936 .ioctl = snd_pcm_lib_ioctl,
937 .hw_params = vx_pcm_hw_params,
938 .hw_free = vx_pcm_hw_free,
939 .prepare = vx_pcm_prepare,
940 .trigger = vx_pcm_trigger,
941 .pointer = vx_pcm_playback_pointer,
942 .page = snd_pcm_get_vmalloc_page,
943};
944
945
946/*
947 * playback hw information
948 */
949
950static snd_pcm_hardware_t vx_pcm_capture_hw = {
951 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
952 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_MMAP_VALID |
953 SNDRV_PCM_INFO_RESUME),
954 .formats = /*SNDRV_PCM_FMTBIT_U8 |*/ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
955 .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
956 .rate_min = 5000,
957 .rate_max = 48000,
958 .channels_min = 1,
959 .channels_max = 2,
960 .buffer_bytes_max = (128*1024),
961 .period_bytes_min = 126,
962 .period_bytes_max = (128*1024),
963 .periods_min = 2,
964 .periods_max = VX_MAX_PERIODS,
965 .fifo_size = 126,
966};
967
968
969/*
970 * vx_pcm_capture_open - open callback for capture
971 */
972static int vx_pcm_capture_open(snd_pcm_substream_t *subs)
973{
974 snd_pcm_runtime_t *runtime = subs->runtime;
975 vx_core_t *chip = snd_pcm_substream_chip(subs);
976 vx_pipe_t *pipe;
977 vx_pipe_t *pipe_out_monitoring = NULL;
978 unsigned int audio;
979 int err;
980
981 if (chip->chip_status & VX_STAT_IS_STALE)
982 return -EBUSY;
983
984 audio = subs->pcm->device * 2;
985 snd_assert(audio < chip->audio_ins, return -EINVAL);
986 err = vx_alloc_pipe(chip, 1, audio, 2, &pipe);
987 if (err < 0)
988 return err;
989 pipe->substream = subs;
990 tasklet_init(&pipe->start_tq, vx_pcm_delayed_start, (unsigned long)subs);
991 chip->capture_pipes[audio] = pipe;
992
993 /* check if monitoring is needed */
994 if (chip->audio_monitor_active[audio]) {
995 pipe_out_monitoring = chip->playback_pipes[audio];
996 if (! pipe_out_monitoring) {
997 /* allocate a pipe */
998 err = vx_alloc_pipe(chip, 0, audio, 2, &pipe_out_monitoring);
999 if (err < 0)
1000 return err;
1001 chip->playback_pipes[audio] = pipe_out_monitoring;
1002 }
1003 pipe_out_monitoring->references++;
1004 /*
1005 if an output pipe is available, it's audios still may need to be
1006 unmuted. hence we'll have to call a mixer entry point.
1007 */
1008 vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], chip->audio_monitor_active[audio]);
1009 /* assuming stereo */
1010 vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], chip->audio_monitor_active[audio+1]);
1011 }
1012
1013 pipe->monitoring_pipe = pipe_out_monitoring; /* default value NULL */
1014
1015 runtime->hw = vx_pcm_capture_hw;
1016 runtime->hw.period_bytes_min = chip->ibl.size;
1017 runtime->private_data = pipe;
1018
1019 /* align to 4 bytes (otherwise will be problematic when 24bit is used) */
1020 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
1021 snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
1022
1023 return 0;
1024}
1025
1026/*
1027 * vx_pcm_capture_close - close callback for capture
1028 */
1029static int vx_pcm_capture_close(snd_pcm_substream_t *subs)
1030{
1031 vx_core_t *chip = snd_pcm_substream_chip(subs);
1032 vx_pipe_t *pipe;
1033 vx_pipe_t *pipe_out_monitoring;
1034
1035 if (! subs->runtime->private_data)
1036 return -EINVAL;
1037 pipe = subs->runtime->private_data;
1038 chip->capture_pipes[pipe->number] = NULL;
1039
1040 pipe_out_monitoring = pipe->monitoring_pipe;
1041
1042 /*
1043 if an output pipe is attached to this input,
1044 check if it needs to be released.
1045 */
1046 if (pipe_out_monitoring) {
1047 if (--pipe_out_monitoring->references == 0) {
1048 vx_free_pipe(chip, pipe_out_monitoring);
1049 chip->playback_pipes[pipe->number] = NULL;
1050 pipe->monitoring_pipe = NULL;
1051 }
1052 }
1053
1054 vx_free_pipe(chip, pipe);
1055 return 0;
1056}
1057
1058
1059
1060#define DMA_READ_ALIGN 6 /* hardware alignment for read */
1061
1062/*
1063 * vx_pcm_capture_update - update the capture buffer
1064 */
1065static void vx_pcm_capture_update(vx_core_t *chip, snd_pcm_substream_t *subs, vx_pipe_t *pipe)
1066{
1067 int size, space, count;
1068 snd_pcm_runtime_t *runtime = subs->runtime;
1069
1070 if (! pipe->prepared || (chip->chip_status & VX_STAT_IS_STALE))
1071 return;
1072
1073 size = runtime->buffer_size - snd_pcm_capture_avail(runtime);
1074 if (! size)
1075 return;
1076 size = frames_to_bytes(runtime, size);
1077 space = vx_query_hbuffer_size(chip, pipe);
1078 if (space < 0)
1079 goto _error;
1080 if (size > space)
1081 size = space;
1082 size = (size / 3) * 3; /* align to 3 bytes */
1083 if (size < DMA_READ_ALIGN)
1084 goto _error;
1085
1086 /* keep the last 6 bytes, they will be read after disconnection */
1087 count = size - DMA_READ_ALIGN;
1088 /* read bytes until the current pointer reaches to the aligned position
1089 * for word-transfer
1090 */
1091 while (count > 0) {
1092 if ((pipe->hw_ptr % pipe->align) == 0)
1093 break;
1094 if (vx_wait_for_rx_full(chip) < 0)
1095 goto _error;
1096 vx_pcm_read_per_bytes(chip, runtime, pipe);
1097 count -= 3;
1098 }
1099 if (count > 0) {
1100 /* ok, let's accelerate! */
1101 int align = pipe->align * 3;
1102 space = (count / align) * align;
1103 vx_pseudo_dma_read(chip, runtime, pipe, space);
1104 count -= space;
1105 }
1106 /* read the rest of bytes */
1107 while (count > 0) {
1108 if (vx_wait_for_rx_full(chip) < 0)
1109 goto _error;
1110 vx_pcm_read_per_bytes(chip, runtime, pipe);
1111 count -= 3;
1112 }
1113 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
1114 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
1115 /* read the last pending 6 bytes */
1116 count = DMA_READ_ALIGN;
1117 while (count > 0) {
1118 vx_pcm_read_per_bytes(chip, runtime, pipe);
1119 count -= 3;
1120 }
1121 /* update the position */
1122 pipe->transferred += size;
1123 if (pipe->transferred >= pipe->period_bytes) {
1124 pipe->transferred %= pipe->period_bytes;
1125 snd_pcm_period_elapsed(subs);
1126 }
1127 return;
1128
1129 _error:
1130 /* disconnect the host, SIZE_HBUF command always switches to the stream mode */
1131 vx_send_rih_nolock(chip, IRQ_CONNECT_STREAM_NEXT);
1132 return;
1133}
1134
1135/*
1136 * vx_pcm_capture_pointer - pointer callback for capture
1137 */
1138static snd_pcm_uframes_t vx_pcm_capture_pointer(snd_pcm_substream_t *subs)
1139{
1140 snd_pcm_runtime_t *runtime = subs->runtime;
1141 vx_pipe_t *pipe = runtime->private_data;
1142 return bytes_to_frames(runtime, pipe->hw_ptr);
1143}
1144
1145/*
1146 * operators for PCM capture
1147 */
1148static snd_pcm_ops_t vx_pcm_capture_ops = {
1149 .open = vx_pcm_capture_open,
1150 .close = vx_pcm_capture_close,
1151 .ioctl = snd_pcm_lib_ioctl,
1152 .hw_params = vx_pcm_hw_params,
1153 .hw_free = vx_pcm_hw_free,
1154 .prepare = vx_pcm_prepare,
1155 .trigger = vx_pcm_trigger,
1156 .pointer = vx_pcm_capture_pointer,
1157 .page = snd_pcm_get_vmalloc_page,
1158};
1159
1160
1161/*
1162 * interrupt handler for pcm streams
1163 */
1164void vx_pcm_update_intr(vx_core_t *chip, unsigned int events)
1165{
1166 unsigned int i;
1167 vx_pipe_t *pipe;
1168
1169#define EVENT_MASK (END_OF_BUFFER_EVENTS_PENDING|ASYNC_EVENTS_PENDING)
1170
1171 if (events & EVENT_MASK) {
1172 vx_init_rmh(&chip->irq_rmh, CMD_ASYNC);
1173 if (events & ASYNC_EVENTS_PENDING)
1174 chip->irq_rmh.Cmd[0] |= 0x00000001; /* SEL_ASYNC_EVENTS */
1175 if (events & END_OF_BUFFER_EVENTS_PENDING)
1176 chip->irq_rmh.Cmd[0] |= 0x00000002; /* SEL_END_OF_BUF_EVENTS */
1177
1178 if (vx_send_msg(chip, &chip->irq_rmh) < 0) {
1179 snd_printdd(KERN_ERR "msg send error!!\n");
1180 return;
1181 }
1182
1183 i = 1;
1184 while (i < chip->irq_rmh.LgStat) {
1185 int p, buf, capture, eob;
1186 p = chip->irq_rmh.Stat[i] & MASK_FIRST_FIELD;
1187 capture = (chip->irq_rmh.Stat[i] & 0x400000) ? 1 : 0;
1188 eob = (chip->irq_rmh.Stat[i] & 0x800000) ? 1 : 0;
1189 i++;
1190 if (events & ASYNC_EVENTS_PENDING)
1191 i++;
1192 buf = 1; /* force to transfer */
1193 if (events & END_OF_BUFFER_EVENTS_PENDING) {
1194 if (eob)
1195 buf = chip->irq_rmh.Stat[i];
1196 i++;
1197 }
1198 if (capture)
1199 continue;
1200 snd_assert(p >= 0 && (unsigned int)p < chip->audio_outs,);
1201 pipe = chip->playback_pipes[p];
1202 if (pipe && pipe->substream) {
1203 vx_pcm_playback_update(chip, pipe->substream, pipe);
1204 vx_pcm_playback_transfer(chip, pipe->substream, pipe, buf);
1205 }
1206 }
1207 }
1208
1209 /* update the capture pcm pointers as frequently as possible */
1210 for (i = 0; i < chip->audio_ins; i++) {
1211 pipe = chip->capture_pipes[i];
1212 if (pipe && pipe->substream)
1213 vx_pcm_capture_update(chip, pipe->substream, pipe);
1214 }
1215}
1216
1217
1218/*
1219 * vx_init_audio_io - check the availabe audio i/o and allocate pipe arrays
1220 */
1221static int vx_init_audio_io(vx_core_t *chip)
1222{
1223 struct vx_rmh rmh;
1224 int preferred;
1225
1226 vx_init_rmh(&rmh, CMD_SUPPORTED);
1227 if (vx_send_msg(chip, &rmh) < 0) {
1228 snd_printk(KERN_ERR "vx: cannot get the supported audio data\n");
1229 return -ENXIO;
1230 }
1231
1232 chip->audio_outs = rmh.Stat[0] & MASK_FIRST_FIELD;
1233 chip->audio_ins = (rmh.Stat[0] >> (FIELD_SIZE*2)) & MASK_FIRST_FIELD;
1234 chip->audio_info = rmh.Stat[1];
1235
1236 /* allocate pipes */
1237 chip->playback_pipes = kmalloc(sizeof(vx_pipe_t *) * chip->audio_outs, GFP_KERNEL);
1238 chip->capture_pipes = kmalloc(sizeof(vx_pipe_t *) * chip->audio_ins, GFP_KERNEL);
1239 if (! chip->playback_pipes || ! chip->capture_pipes)
1240 return -ENOMEM;
1241
1242 memset(chip->playback_pipes, 0, sizeof(vx_pipe_t *) * chip->audio_outs);
1243 memset(chip->capture_pipes, 0, sizeof(vx_pipe_t *) * chip->audio_ins);
1244
1245 preferred = chip->ibl.size;
1246 chip->ibl.size = 0;
1247 vx_set_ibl(chip, &chip->ibl); /* query the info */
1248 if (preferred > 0) {
1249 chip->ibl.size = ((preferred + chip->ibl.granularity - 1) / chip->ibl.granularity) * chip->ibl.granularity;
1250 if (chip->ibl.size > chip->ibl.max_size)
1251 chip->ibl.size = chip->ibl.max_size;
1252 } else
1253 chip->ibl.size = chip->ibl.min_size; /* set to the minimum */
1254 vx_set_ibl(chip, &chip->ibl);
1255
1256 return 0;
1257}
1258
1259
1260/*
1261 * free callback for pcm
1262 */
1263static void snd_vx_pcm_free(snd_pcm_t *pcm)
1264{
1265 vx_core_t *chip = pcm->private_data;
1266 chip->pcm[pcm->device] = NULL;
1267 if (chip->playback_pipes) {
1268 kfree(chip->playback_pipes);
1269 chip->playback_pipes = NULL;
1270 }
1271 if (chip->capture_pipes) {
1272 kfree(chip->capture_pipes);
1273 chip->capture_pipes = NULL;
1274 }
1275}
1276
1277/*
1278 * snd_vx_pcm_new - create and initialize a pcm
1279 */
1280int snd_vx_pcm_new(vx_core_t *chip)
1281{
1282 snd_pcm_t *pcm;
1283 unsigned int i;
1284 int err;
1285
1286 if ((err = vx_init_audio_io(chip)) < 0)
1287 return err;
1288
1289 for (i = 0; i < chip->hw->num_codecs; i++) {
1290 unsigned int outs, ins;
1291 outs = chip->audio_outs > i * 2 ? 1 : 0;
1292 ins = chip->audio_ins > i * 2 ? 1 : 0;
1293 if (! outs && ! ins)
1294 break;
1295 err = snd_pcm_new(chip->card, "VX PCM", i,
1296 outs, ins, &pcm);
1297 if (err < 0)
1298 return err;
1299 if (outs)
1300 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vx_pcm_playback_ops);
1301 if (ins)
1302 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops);
1303
1304 pcm->private_data = chip;
1305 pcm->private_free = snd_vx_pcm_free;
1306 pcm->info_flags = 0;
1307 strcpy(pcm->name, chip->card->shortname);
1308 chip->pcm[i] = pcm;
1309 }
1310
1311 return 0;
1312}
diff --git a/sound/drivers/vx/vx_uer.c b/sound/drivers/vx/vx_uer.c
new file mode 100644
index 000000000000..18114713c3b3
--- /dev/null
+++ b/sound/drivers/vx/vx_uer.c
@@ -0,0 +1,321 @@
1/*
2 * Driver for Digigram VX soundcards
3 *
4 * IEC958 stuff
5 *
6 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <linux/delay.h>
25#include <sound/core.h>
26#include <sound/vx_core.h>
27#include "vx_cmd.h"
28
29
30/*
31 * vx_modify_board_clock - tell the board that its clock has been modified
32 * @sync: DSP needs to resynchronize its FIFO
33 */
34static int vx_modify_board_clock(vx_core_t *chip, int sync)
35{
36 struct vx_rmh rmh;
37
38 vx_init_rmh(&rmh, CMD_MODIFY_CLOCK);
39 /* Ask the DSP to resynchronize its FIFO. */
40 if (sync)
41 rmh.Cmd[0] |= CMD_MODIFY_CLOCK_S_BIT;
42 return vx_send_msg(chip, &rmh);
43}
44
45/*
46 * vx_modify_board_inputs - resync audio inputs
47 */
48static int vx_modify_board_inputs(vx_core_t *chip)
49{
50 struct vx_rmh rmh;
51
52 vx_init_rmh(&rmh, CMD_RESYNC_AUDIO_INPUTS);
53 rmh.Cmd[0] |= 1 << 0; /* reference: AUDIO 0 */
54 return vx_send_msg(chip, &rmh);
55}
56
57/*
58 * vx_read_one_cbit - read one bit from UER config
59 * @index: the bit index
60 * returns 0 or 1.
61 */
62static int vx_read_one_cbit(vx_core_t *chip, int index)
63{
64 unsigned long flags;
65 int val;
66 spin_lock_irqsave(&chip->lock, flags);
67 if (chip->type >= VX_TYPE_VXPOCKET) {
68 vx_outb(chip, CSUER, 1); /* read */
69 vx_outb(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
70 val = (vx_inb(chip, RUER) >> 7) & 0x01;
71 } else {
72 vx_outl(chip, CSUER, 1); /* read */
73 vx_outl(chip, RUER, index & XX_UER_CBITS_OFFSET_MASK);
74 val = (vx_inl(chip, RUER) >> 7) & 0x01;
75 }
76 spin_unlock_irqrestore(&chip->lock, flags);
77 return val;
78}
79
80/*
81 * vx_write_one_cbit - write one bit to UER config
82 * @index: the bit index
83 * @val: bit value, 0 or 1
84 */
85static void vx_write_one_cbit(vx_core_t *chip, int index, int val)
86{
87 unsigned long flags;
88 val = !!val; /* 0 or 1 */
89 spin_lock_irqsave(&chip->lock, flags);
90 if (vx_is_pcmcia(chip)) {
91 vx_outb(chip, CSUER, 0); /* write */
92 vx_outb(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
93 } else {
94 vx_outl(chip, CSUER, 0); /* write */
95 vx_outl(chip, RUER, (val << 7) | (index & XX_UER_CBITS_OFFSET_MASK));
96 }
97 spin_unlock_irqrestore(&chip->lock, flags);
98}
99
100/*
101 * vx_read_uer_status - read the current UER status
102 * @mode: pointer to store the UER mode, VX_UER_MODE_XXX
103 *
104 * returns the frequency of UER, or 0 if not sync,
105 * or a negative error code.
106 */
107static int vx_read_uer_status(vx_core_t *chip, int *mode)
108{
109 int val, freq;
110
111 /* Default values */
112 freq = 0;
113
114 /* Read UER status */
115 if (vx_is_pcmcia(chip))
116 val = vx_inb(chip, CSUER);
117 else
118 val = vx_inl(chip, CSUER);
119 if (val < 0)
120 return val;
121 /* If clock is present, read frequency */
122 if (val & VX_SUER_CLOCK_PRESENT_MASK) {
123 switch (val & VX_SUER_FREQ_MASK) {
124 case VX_SUER_FREQ_32KHz_MASK:
125 freq = 32000;
126 break;
127 case VX_SUER_FREQ_44KHz_MASK:
128 freq = 44100;
129 break;
130 case VX_SUER_FREQ_48KHz_MASK:
131 freq = 48000;
132 break;
133 }
134 }
135 if (val & VX_SUER_DATA_PRESENT_MASK)
136 /* bit 0 corresponds to consumer/professional bit */
137 *mode = vx_read_one_cbit(chip, 0) ?
138 VX_UER_MODE_PROFESSIONAL : VX_UER_MODE_CONSUMER;
139 else
140 *mode = VX_UER_MODE_NOT_PRESENT;
141
142 return freq;
143}
144
145
146/*
147 * compute the sample clock value from frequency
148 *
149 * The formula is as follows:
150 *
151 * HexFreq = (dword) ((double) ((double) 28224000 / (double) Frequency))
152 * switch ( HexFreq & 0x00000F00 )
153 * case 0x00000100: ;
154 * case 0x00000200:
155 * case 0x00000300: HexFreq -= 0x00000201 ;
156 * case 0x00000400:
157 * case 0x00000500:
158 * case 0x00000600:
159 * case 0x00000700: HexFreq = (dword) (((double) 28224000 / (double) (Frequency*2)) - 1)
160 * default : HexFreq = (dword) ((double) 28224000 / (double) (Frequency*4)) - 0x000001FF
161 */
162
163static int vx_calc_clock_from_freq(vx_core_t *chip, int freq)
164{
165#define XX_FECH48000 0x0000004B
166#define XX_FECH32000 0x00000171
167#define XX_FECH24000 0x0000024B
168#define XX_FECH16000 0x00000371
169#define XX_FECH12000 0x0000044B
170#define XX_FECH8000 0x00000571
171#define XX_FECH44100 0x0000007F
172#define XX_FECH29400 0x0000016F
173#define XX_FECH22050 0x0000027F
174#define XX_FECH14000 0x000003EF
175#define XX_FECH11025 0x0000047F
176#define XX_FECH7350 0x000005BF
177
178 switch (freq) {
179 case 48000: return XX_FECH48000;
180 case 44100: return XX_FECH44100;
181 case 32000: return XX_FECH32000;
182 case 29400: return XX_FECH29400;
183 case 24000: return XX_FECH24000;
184 case 22050: return XX_FECH22050;
185 case 16000: return XX_FECH16000;
186 case 14000: return XX_FECH14000;
187 case 12000: return XX_FECH12000;
188 case 11025: return XX_FECH11025;
189 case 8000: return XX_FECH8000;
190 case 7350: return XX_FECH7350;
191 default: return freq; /* The value is already correct */
192 }
193}
194
195
196/*
197 * vx_change_clock_source - change the clock source
198 * @source: the new source
199 */
200static void vx_change_clock_source(vx_core_t *chip, int source)
201{
202 unsigned long flags;
203
204 /* we mute DAC to prevent clicks */
205 vx_toggle_dac_mute(chip, 1);
206 spin_lock_irqsave(&chip->lock, flags);
207 chip->ops->set_clock_source(chip, source);
208 chip->clock_source = source;
209 spin_unlock_irqrestore(&chip->lock, flags);
210 /* unmute */
211 vx_toggle_dac_mute(chip, 0);
212}
213
214
215/*
216 * set the internal clock
217 */
218void vx_set_internal_clock(vx_core_t *chip, unsigned int freq)
219{
220 int clock;
221 unsigned long flags;
222 /* Get real clock value */
223 clock = vx_calc_clock_from_freq(chip, freq);
224 snd_printdd(KERN_DEBUG "set internal clock to 0x%x from freq %d\n", clock, freq);
225 spin_lock_irqsave(&chip->lock, flags);
226 if (vx_is_pcmcia(chip)) {
227 vx_outb(chip, HIFREQ, (clock >> 8) & 0x0f);
228 vx_outb(chip, LOFREQ, clock & 0xff);
229 } else {
230 vx_outl(chip, HIFREQ, (clock >> 8) & 0x0f);
231 vx_outl(chip, LOFREQ, clock & 0xff);
232 }
233 spin_unlock_irqrestore(&chip->lock, flags);
234}
235
236
237/*
238 * set the iec958 status bits
239 * @bits: 32-bit status bits
240 */
241void vx_set_iec958_status(vx_core_t *chip, unsigned int bits)
242{
243 int i;
244
245 if (chip->chip_status & VX_STAT_IS_STALE)
246 return;
247
248 for (i = 0; i < 32; i++)
249 vx_write_one_cbit(chip, i, bits & (1 << i));
250}
251
252
253/*
254 * vx_set_clock - change the clock and audio source if necessary
255 */
256int vx_set_clock(vx_core_t *chip, unsigned int freq)
257{
258 int src_changed = 0;
259
260 if (chip->chip_status & VX_STAT_IS_STALE)
261 return 0;
262
263 /* change the audio source if possible */
264 vx_sync_audio_source(chip);
265
266 if (chip->clock_mode == VX_CLOCK_MODE_EXTERNAL ||
267 (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
268 chip->audio_source == VX_AUDIO_SRC_DIGITAL)) {
269 if (chip->clock_source != UER_SYNC) {
270 vx_change_clock_source(chip, UER_SYNC);
271 mdelay(6);
272 src_changed = 1;
273 }
274 } else if (chip->clock_mode == VX_CLOCK_MODE_INTERNAL ||
275 (chip->clock_mode == VX_CLOCK_MODE_AUTO &&
276 chip->audio_source != VX_AUDIO_SRC_DIGITAL)) {
277 if (chip->clock_source != INTERNAL_QUARTZ) {
278 vx_change_clock_source(chip, INTERNAL_QUARTZ);
279 src_changed = 1;
280 }
281 if (chip->freq == freq)
282 return 0;
283 vx_set_internal_clock(chip, freq);
284 if (src_changed)
285 vx_modify_board_inputs(chip);
286 }
287 if (chip->freq == freq)
288 return 0;
289 chip->freq = freq;
290 vx_modify_board_clock(chip, 1);
291 return 0;
292}
293
294
295/*
296 * vx_change_frequency - called from interrupt handler
297 */
298int vx_change_frequency(vx_core_t *chip)
299{
300 int freq;
301
302 if (chip->chip_status & VX_STAT_IS_STALE)
303 return 0;
304
305 if (chip->clock_source == INTERNAL_QUARTZ)
306 return 0;
307 /*
308 * Read the real UER board frequency
309 */
310 freq = vx_read_uer_status(chip, &chip->uer_detected);
311 if (freq < 0)
312 return freq;
313 /*
314 * The frequency computed by the DSP is good and
315 * is different from the previous computed.
316 */
317 if (freq == 48000 || freq == 44100 || freq == 32000)
318 chip->freq_detected = freq;
319
320 return 0;
321}