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