Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (C) 2000 Takashi Iwai <tiwai@suse.de>
0004  *
0005  *  Routines for control of EMU WaveTable chip
0006  */
0007 
0008 #include <linux/wait.h>
0009 #include <linux/slab.h>
0010 #include <linux/string.h>
0011 #include <sound/core.h>
0012 #include <sound/emux_synth.h>
0013 #include <linux/init.h>
0014 #include <linux/module.h>
0015 #include "emux_voice.h"
0016 
0017 MODULE_AUTHOR("Takashi Iwai");
0018 MODULE_DESCRIPTION("Routines for control of EMU WaveTable chip");
0019 MODULE_LICENSE("GPL");
0020 
0021 /*
0022  * create a new hardware dependent device for Emu8000/Emu10k1
0023  */
0024 int snd_emux_new(struct snd_emux **remu)
0025 {
0026     struct snd_emux *emu;
0027 
0028     *remu = NULL;
0029     emu = kzalloc(sizeof(*emu), GFP_KERNEL);
0030     if (emu == NULL)
0031         return -ENOMEM;
0032 
0033     spin_lock_init(&emu->voice_lock);
0034     mutex_init(&emu->register_mutex);
0035 
0036     emu->client = -1;
0037 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
0038     emu->oss_synth = NULL;
0039 #endif
0040     emu->max_voices = 0;
0041     emu->use_time = 0;
0042 
0043     timer_setup(&emu->tlist, snd_emux_timer_callback, 0);
0044     emu->timer_active = 0;
0045 
0046     *remu = emu;
0047     return 0;
0048 }
0049 
0050 EXPORT_SYMBOL(snd_emux_new);
0051 
0052 /*
0053  */
0054 static int sf_sample_new(void *private_data, struct snd_sf_sample *sp,
0055                   struct snd_util_memhdr *hdr,
0056                   const void __user *buf, long count)
0057 {
0058     struct snd_emux *emu = private_data;
0059     return emu->ops.sample_new(emu, sp, hdr, buf, count);
0060     
0061 }
0062 
0063 static int sf_sample_free(void *private_data, struct snd_sf_sample *sp,
0064                    struct snd_util_memhdr *hdr)
0065 {
0066     struct snd_emux *emu = private_data;
0067     return emu->ops.sample_free(emu, sp, hdr);
0068     
0069 }
0070 
0071 static void sf_sample_reset(void *private_data)
0072 {
0073     struct snd_emux *emu = private_data;
0074     emu->ops.sample_reset(emu);
0075 }
0076 
0077 int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, char *name)
0078 {
0079     int err;
0080     struct snd_sf_callback sf_cb;
0081 
0082     if (snd_BUG_ON(!emu->hw || emu->max_voices <= 0))
0083         return -EINVAL;
0084     if (snd_BUG_ON(!card || !name))
0085         return -EINVAL;
0086 
0087     emu->card = card;
0088     emu->name = kstrdup(name, GFP_KERNEL);
0089     emu->voices = kcalloc(emu->max_voices, sizeof(struct snd_emux_voice),
0090                   GFP_KERNEL);
0091     if (emu->name == NULL || emu->voices == NULL)
0092         return -ENOMEM;
0093 
0094     /* create soundfont list */
0095     memset(&sf_cb, 0, sizeof(sf_cb));
0096     sf_cb.private_data = emu;
0097     if (emu->ops.sample_new)
0098         sf_cb.sample_new = sf_sample_new;
0099     if (emu->ops.sample_free)
0100         sf_cb.sample_free = sf_sample_free;
0101     if (emu->ops.sample_reset)
0102         sf_cb.sample_reset = sf_sample_reset;
0103     emu->sflist = snd_sf_new(&sf_cb, emu->memhdr);
0104     if (emu->sflist == NULL)
0105         return -ENOMEM;
0106 
0107     err = snd_emux_init_hwdep(emu);
0108     if (err < 0)
0109         return err;
0110 
0111     snd_emux_init_voices(emu);
0112 
0113     snd_emux_init_seq(emu, card, index);
0114 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
0115     snd_emux_init_seq_oss(emu);
0116 #endif
0117     snd_emux_init_virmidi(emu, card);
0118 
0119     snd_emux_proc_init(emu, card, index);
0120     return 0;
0121 }
0122 
0123 EXPORT_SYMBOL(snd_emux_register);
0124 
0125 /*
0126  */
0127 int snd_emux_free(struct snd_emux *emu)
0128 {
0129     unsigned long flags;
0130 
0131     if (! emu)
0132         return -EINVAL;
0133 
0134     spin_lock_irqsave(&emu->voice_lock, flags);
0135     if (emu->timer_active)
0136         del_timer(&emu->tlist);
0137     spin_unlock_irqrestore(&emu->voice_lock, flags);
0138 
0139     snd_emux_proc_free(emu);
0140     snd_emux_delete_virmidi(emu);
0141 #if IS_ENABLED(CONFIG_SND_SEQUENCER_OSS)
0142     snd_emux_detach_seq_oss(emu);
0143 #endif
0144     snd_emux_detach_seq(emu);
0145     snd_emux_delete_hwdep(emu);
0146     snd_sf_free(emu->sflist);
0147     kfree(emu->voices);
0148     kfree(emu->name);
0149     kfree(emu);
0150     return 0;
0151 }
0152 
0153 EXPORT_SYMBOL(snd_emux_free);