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