Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
[pandora-kernel.git] / sound / synth / emux / emux_oss.c
1 /*
2  *  Interface for OSS sequencer emulation
3  *
4  *  Copyright (C) 1999 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  * Changes
21  * 19990227   Steve Ratcliffe   Made separate file and merged in latest
22  *                              midi emulation.
23  */
24
25
26 #ifdef CONFIG_SND_SEQUENCER_OSS
27
28 #include <linux/export.h>
29 #include <asm/uaccess.h>
30 #include <sound/core.h>
31 #include "emux_voice.h"
32 #include <sound/asoundef.h>
33
34 static int snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure);
35 static int snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg);
36 static int snd_emux_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd,
37                                   unsigned long ioarg);
38 static int snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
39                                        const char __user *buf, int offs, int count);
40 static int snd_emux_reset_seq_oss(struct snd_seq_oss_arg *arg);
41 static int snd_emux_event_oss_input(struct snd_seq_event *ev, int direct,
42                                     void *private, int atomic, int hop);
43 static void reset_port_mode(struct snd_emux_port *port, int midi_mode);
44 static void emuspec_control(struct snd_emux *emu, struct snd_emux_port *port,
45                             int cmd, unsigned char *event, int atomic, int hop);
46 static void gusspec_control(struct snd_emux *emu, struct snd_emux_port *port,
47                             int cmd, unsigned char *event, int atomic, int hop);
48 static void fake_event(struct snd_emux *emu, struct snd_emux_port *port,
49                        int ch, int param, int val, int atomic, int hop);
50
51 /* operators */
52 static struct snd_seq_oss_callback oss_callback = {
53         .owner = THIS_MODULE,
54         .open = snd_emux_open_seq_oss,
55         .close = snd_emux_close_seq_oss,
56         .ioctl = snd_emux_ioctl_seq_oss,
57         .load_patch = snd_emux_load_patch_seq_oss,
58         .reset = snd_emux_reset_seq_oss,
59 };
60
61
62 /*
63  * register OSS synth
64  */
65
66 void
67 snd_emux_init_seq_oss(struct snd_emux *emu)
68 {
69         struct snd_seq_oss_reg *arg;
70         struct snd_seq_device *dev;
71
72         if (snd_seq_device_new(emu->card, 0, SNDRV_SEQ_DEV_ID_OSS,
73                                sizeof(struct snd_seq_oss_reg), &dev) < 0)
74                 return;
75
76         emu->oss_synth = dev;
77         strcpy(dev->name, emu->name);
78         arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
79         arg->type = SYNTH_TYPE_SAMPLE;
80         arg->subtype = SAMPLE_TYPE_AWE32;
81         arg->nvoices = emu->max_voices;
82         arg->oper = oss_callback;
83         arg->private_data = emu;
84
85         /* register to OSS synth table */
86         snd_device_register(emu->card, dev);
87 }
88
89
90 /*
91  * unregister
92  */
93 void
94 snd_emux_detach_seq_oss(struct snd_emux *emu)
95 {
96         if (emu->oss_synth) {
97                 snd_device_free(emu->card, emu->oss_synth);
98                 emu->oss_synth = NULL;
99         }
100 }
101
102
103 /* use port number as a unique soundfont client number */
104 #define SF_CLIENT_NO(p) ((p) + 0x1000)
105
106 /*
107  * open port for OSS sequencer
108  */
109 static int
110 snd_emux_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure)
111 {
112         struct snd_emux *emu;
113         struct snd_emux_port *p;
114         struct snd_seq_port_callback callback;
115         char tmpname[64];
116
117         emu = closure;
118         if (snd_BUG_ON(!arg || !emu))
119                 return -ENXIO;
120
121         mutex_lock(&emu->register_mutex);
122
123         if (!snd_emux_inc_count(emu)) {
124                 mutex_unlock(&emu->register_mutex);
125                 return -EFAULT;
126         }
127
128         memset(&callback, 0, sizeof(callback));
129         callback.owner = THIS_MODULE;
130         callback.event_input = snd_emux_event_oss_input;
131
132         sprintf(tmpname, "%s OSS Port", emu->name);
133         p = snd_emux_create_port(emu, tmpname, 32,
134                                  1, &callback);
135         if (p == NULL) {
136                 snd_printk(KERN_ERR "can't create port\n");
137                 snd_emux_dec_count(emu);
138                 mutex_unlock(&emu->register_mutex);
139                 return -ENOMEM;
140         }
141
142         /* fill the argument data */
143         arg->private_data = p;
144         arg->addr.client = p->chset.client;
145         arg->addr.port = p->chset.port;
146         p->oss_arg = arg;
147
148         reset_port_mode(p, arg->seq_mode);
149
150         snd_emux_reset_port(p);
151
152         mutex_unlock(&emu->register_mutex);
153         return 0;
154 }
155
156
157 #define DEFAULT_DRUM_FLAGS      ((1<<9) | (1<<25))
158
159 /*
160  * reset port mode
161  */
162 static void
163 reset_port_mode(struct snd_emux_port *port, int midi_mode)
164 {
165         if (midi_mode) {
166                 port->port_mode = SNDRV_EMUX_PORT_MODE_OSS_MIDI;
167                 port->drum_flags = DEFAULT_DRUM_FLAGS;
168                 port->volume_atten = 0;
169                 port->oss_arg->event_passing = SNDRV_SEQ_OSS_PROCESS_KEYPRESS;
170         } else {
171                 port->port_mode = SNDRV_EMUX_PORT_MODE_OSS_SYNTH;
172                 port->drum_flags = 0;
173                 port->volume_atten = 32;
174                 port->oss_arg->event_passing = SNDRV_SEQ_OSS_PROCESS_EVENTS;
175         }
176 }
177
178
179 /*
180  * close port
181  */
182 static int
183 snd_emux_close_seq_oss(struct snd_seq_oss_arg *arg)
184 {
185         struct snd_emux *emu;
186         struct snd_emux_port *p;
187
188         if (snd_BUG_ON(!arg))
189                 return -ENXIO;
190         p = arg->private_data;
191         if (snd_BUG_ON(!p))
192                 return -ENXIO;
193
194         emu = p->emu;
195         if (snd_BUG_ON(!emu))
196                 return -ENXIO;
197
198         mutex_lock(&emu->register_mutex);
199         snd_emux_sounds_off_all(p);
200         snd_soundfont_close_check(emu->sflist, SF_CLIENT_NO(p->chset.port));
201         snd_seq_event_port_detach(p->chset.client, p->chset.port);
202         snd_emux_dec_count(emu);
203
204         mutex_unlock(&emu->register_mutex);
205         return 0;
206 }
207
208
209 /*
210  * load patch
211  */
212 static int
213 snd_emux_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
214                             const char __user *buf, int offs, int count)
215 {
216         struct snd_emux *emu;
217         struct snd_emux_port *p;
218         int rc;
219
220         if (snd_BUG_ON(!arg))
221                 return -ENXIO;
222         p = arg->private_data;
223         if (snd_BUG_ON(!p))
224                 return -ENXIO;
225
226         emu = p->emu;
227         if (snd_BUG_ON(!emu))
228                 return -ENXIO;
229
230         if (format == GUS_PATCH)
231                 rc = snd_soundfont_load_guspatch(emu->sflist, buf, count,
232                                                  SF_CLIENT_NO(p->chset.port));
233         else if (format == SNDRV_OSS_SOUNDFONT_PATCH) {
234                 struct soundfont_patch_info patch;
235                 if (count < (int)sizeof(patch))
236                         rc = -EINVAL;
237                 if (copy_from_user(&patch, buf, sizeof(patch)))
238                         rc = -EFAULT;
239                 if (patch.type >= SNDRV_SFNT_LOAD_INFO &&
240                     patch.type <= SNDRV_SFNT_PROBE_DATA)
241                         rc = snd_soundfont_load(emu->sflist, buf, count, SF_CLIENT_NO(p->chset.port));
242                 else {
243                         if (emu->ops.load_fx)
244                                 rc = emu->ops.load_fx(emu, patch.type, patch.optarg, buf, count);
245                         else
246                                 rc = -EINVAL;
247                 }
248         } else
249                 rc = 0;
250         return rc;
251 }
252
253
254 /*
255  * ioctl
256  */
257 static int
258 snd_emux_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd, unsigned long ioarg)
259 {
260         struct snd_emux_port *p;
261         struct snd_emux *emu;
262
263         if (snd_BUG_ON(!arg))
264                 return -ENXIO;
265         p = arg->private_data;
266         if (snd_BUG_ON(!p))
267                 return -ENXIO;
268
269         emu = p->emu;
270         if (snd_BUG_ON(!emu))
271                 return -ENXIO;
272
273         switch (cmd) {
274         case SNDCTL_SEQ_RESETSAMPLES:
275                 snd_soundfont_remove_samples(emu->sflist);
276                 return 0;
277                         
278         case SNDCTL_SYNTH_MEMAVL:
279                 if (emu->memhdr)
280                         return snd_util_mem_avail(emu->memhdr);
281                 return 0;
282         }
283
284         return 0;
285 }
286
287
288 /*
289  * reset device
290  */
291 static int
292 snd_emux_reset_seq_oss(struct snd_seq_oss_arg *arg)
293 {
294         struct snd_emux_port *p;
295
296         if (snd_BUG_ON(!arg))
297                 return -ENXIO;
298         p = arg->private_data;
299         if (snd_BUG_ON(!p))
300                 return -ENXIO;
301         snd_emux_reset_port(p);
302         return 0;
303 }
304
305
306 /*
307  * receive raw events: only SEQ_PRIVATE is accepted.
308  */
309 static int
310 snd_emux_event_oss_input(struct snd_seq_event *ev, int direct, void *private_data,
311                          int atomic, int hop)
312 {
313         struct snd_emux *emu;
314         struct snd_emux_port *p;
315         unsigned char cmd, *data;
316
317         p = private_data;
318         if (snd_BUG_ON(!p))
319                 return -EINVAL;
320         emu = p->emu;
321         if (snd_BUG_ON(!emu))
322                 return -EINVAL;
323         if (ev->type != SNDRV_SEQ_EVENT_OSS)
324                 return snd_emux_event_input(ev, direct, private_data, atomic, hop);
325
326         data = ev->data.raw8.d;
327         /* only SEQ_PRIVATE is accepted */
328         if (data[0] != 0xfe)
329                 return 0;
330         cmd = data[2] & _EMUX_OSS_MODE_VALUE_MASK;
331         if (data[2] & _EMUX_OSS_MODE_FLAG)
332                 emuspec_control(emu, p, cmd, data, atomic, hop);
333         else
334                 gusspec_control(emu, p, cmd, data, atomic, hop);
335         return 0;
336 }
337
338
339 /*
340  * OSS/AWE driver specific h/w controls
341  */
342 static void
343 emuspec_control(struct snd_emux *emu, struct snd_emux_port *port, int cmd,
344                 unsigned char *event, int atomic, int hop)
345 {
346         int voice;
347         unsigned short p1;
348         short p2;
349         int i;
350         struct snd_midi_channel *chan;
351
352         voice = event[3];
353         if (voice < 0 || voice >= port->chset.max_channels)
354                 chan = NULL;
355         else
356                 chan = &port->chset.channels[voice];
357
358         p1 = *(unsigned short *) &event[4];
359         p2 = *(short *) &event[6];
360
361         switch (cmd) {
362 #if 0 /* don't do this atomically */
363         case _EMUX_OSS_REMOVE_LAST_SAMPLES:
364                 snd_soundfont_remove_unlocked(emu->sflist);
365                 break;
366 #endif
367         case _EMUX_OSS_SEND_EFFECT:
368                 if (chan)
369                         snd_emux_send_effect_oss(port, chan, p1, p2);
370                 break;
371                 
372         case _EMUX_OSS_TERMINATE_ALL:
373                 snd_emux_terminate_all(emu);
374                 break;
375
376         case _EMUX_OSS_TERMINATE_CHANNEL:
377                 /*snd_emux_mute_channel(emu, chan);*/
378                 break;
379         case _EMUX_OSS_RESET_CHANNEL:
380                 /*snd_emux_channel_init(chset, chan);*/
381                 break;
382
383         case _EMUX_OSS_RELEASE_ALL:
384                 fake_event(emu, port, voice, MIDI_CTL_ALL_NOTES_OFF, 0, atomic, hop);
385                 break;
386         case _EMUX_OSS_NOTEOFF_ALL:
387                 fake_event(emu, port, voice, MIDI_CTL_ALL_SOUNDS_OFF, 0, atomic, hop);
388                 break;
389
390         case _EMUX_OSS_INITIAL_VOLUME:
391                 if (p2) {
392                         port->volume_atten = (short)p1;
393                         snd_emux_update_port(port, SNDRV_EMUX_UPDATE_VOLUME);
394                 }
395                 break;
396
397         case _EMUX_OSS_CHN_PRESSURE:
398                 if (chan) {
399                         chan->midi_pressure = p1;
400                         snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_FMMOD|SNDRV_EMUX_UPDATE_FM2FRQ2);
401                 }
402                 break;
403
404         case _EMUX_OSS_CHANNEL_MODE:
405                 reset_port_mode(port, p1);
406                 snd_emux_reset_port(port);
407                 break;
408
409         case _EMUX_OSS_DRUM_CHANNELS:
410                 port->drum_flags = *(unsigned int*)&event[4];
411                 for (i = 0; i < port->chset.max_channels; i++) {
412                         chan = &port->chset.channels[i];
413                         chan->drum_channel = ((port->drum_flags >> i) & 1) ? 1 : 0;
414                 }
415                 break;
416
417         case _EMUX_OSS_MISC_MODE:
418                 if (p1 < EMUX_MD_END)
419                         port->ctrls[p1] = p2;
420                 break;
421         case _EMUX_OSS_DEBUG_MODE:
422                 break;
423
424         default:
425                 if (emu->ops.oss_ioctl)
426                         emu->ops.oss_ioctl(emu, cmd, p1, p2);
427                 break;
428         }
429 }
430
431 /*
432  * GUS specific h/w controls
433  */
434
435 #include <linux/ultrasound.h>
436
437 static void
438 gusspec_control(struct snd_emux *emu, struct snd_emux_port *port, int cmd,
439                 unsigned char *event, int atomic, int hop)
440 {
441         int voice;
442         unsigned short p1;
443         short p2;
444         int plong;
445         struct snd_midi_channel *chan;
446
447         if (port->port_mode != SNDRV_EMUX_PORT_MODE_OSS_SYNTH)
448                 return;
449         if (cmd == _GUS_NUMVOICES)
450                 return;
451         voice = event[3];
452         if (voice < 0 || voice >= port->chset.max_channels)
453                 return;
454
455         chan = &port->chset.channels[voice];
456
457         p1 = *(unsigned short *) &event[4];
458         p2 = *(short *) &event[6];
459         plong = *(int*) &event[4];
460
461         switch (cmd) {
462         case _GUS_VOICESAMPLE:
463                 chan->midi_program = p1;
464                 return;
465
466         case _GUS_VOICEBALA:
467                 /* 0 to 15 --> 0 to 127 */
468                 chan->control[MIDI_CTL_MSB_PAN] = (int)p1 << 3;
469                 snd_emux_update_channel(port, chan, SNDRV_EMUX_UPDATE_PAN);
470                 return;
471
472         case _GUS_VOICEVOL:
473         case _GUS_VOICEVOL2:
474                 /* not supported yet */
475                 return;
476
477         case _GUS_RAMPRANGE:
478         case _GUS_RAMPRATE:
479         case _GUS_RAMPMODE:
480         case _GUS_RAMPON:
481         case _GUS_RAMPOFF:
482                 /* volume ramping not supported */
483                 return;
484
485         case _GUS_VOLUME_SCALE:
486                 return;
487
488         case _GUS_VOICE_POS:
489 #ifdef SNDRV_EMUX_USE_RAW_EFFECT
490                 snd_emux_send_effect(port, chan, EMUX_FX_SAMPLE_START,
491                                      (short)(plong & 0x7fff),
492                                      EMUX_FX_FLAG_SET);
493                 snd_emux_send_effect(port, chan, EMUX_FX_COARSE_SAMPLE_START,
494                                      (plong >> 15) & 0xffff,
495                                      EMUX_FX_FLAG_SET);
496 #endif
497                 return;
498         }
499 }
500
501
502 /*
503  * send an event to midi emulation
504  */
505 static void
506 fake_event(struct snd_emux *emu, struct snd_emux_port *port, int ch, int param, int val, int atomic, int hop)
507 {
508         struct snd_seq_event ev;
509         memset(&ev, 0, sizeof(ev));
510         ev.type = SNDRV_SEQ_EVENT_CONTROLLER;
511         ev.data.control.channel = ch;
512         ev.data.control.param = param;
513         ev.data.control.value = val;
514         snd_emux_event_input(&ev, 0, port, atomic, hop);
515 }
516
517 #endif /* CONFIG_SND_SEQUENCER_OSS */