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