1/* 2 * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de> 3 * 4 * Routines for control of EMU WaveTable chip 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 21#include <linux/wait.h> 22#include <linux/slab.h> 23#include <linux/string.h> 24#include <sound/core.h> 25#include <sound/emux_synth.h> 26#include <linux/init.h> 27#include <linux/module.h> 28#include "emux_voice.h" 29 30MODULE_AUTHOR("Takashi Iwai"); 31MODULE_DESCRIPTION("Routines for control of EMU WaveTable chip"); 32MODULE_LICENSE("GPL"); 33 34/* 35 * create a new hardware dependent device for Emu8000/Emu10k1 36 */ 37int snd_emux_new(struct snd_emux **remu) 38{ 39 struct snd_emux *emu; 40 41 *remu = NULL; 42 emu = kzalloc(sizeof(*emu), GFP_KERNEL); 43 if (emu == NULL) 44 return -ENOMEM; 45 46 spin_lock_init(&emu->voice_lock); 47 mutex_init(&emu->register_mutex); 48 49 emu->client = -1; 50#ifdef CONFIG_SND_SEQUENCER_OSS 51 emu->oss_synth = NULL; 52#endif 53 emu->max_voices = 0; 54 emu->use_time = 0; 55 56 setup_timer(&emu->tlist, snd_emux_timer_callback, (unsigned long)emu); 57 emu->timer_active = 0; 58 59 *remu = emu; 60 return 0; 61} 62 63EXPORT_SYMBOL(snd_emux_new); 64 65/* 66 */ 67static int sf_sample_new(void *private_data, struct snd_sf_sample *sp, 68 struct snd_util_memhdr *hdr, 69 const void __user *buf, long count) 70{ 71 struct snd_emux *emu = private_data; 72 return emu->ops.sample_new(emu, sp, hdr, buf, count); 73 74} 75 76static int sf_sample_free(void *private_data, struct snd_sf_sample *sp, 77 struct snd_util_memhdr *hdr) 78{ 79 struct snd_emux *emu = private_data; 80 return emu->ops.sample_free(emu, sp, hdr); 81 82} 83 84static void sf_sample_reset(void *private_data) 85{ 86 struct snd_emux *emu = private_data; 87 emu->ops.sample_reset(emu); 88} 89 90int snd_emux_register(struct snd_emux *emu, struct snd_card *card, int index, char *name) 91{ 92 int err; 93 struct snd_sf_callback sf_cb; 94 95 if (snd_BUG_ON(!emu->hw || emu->max_voices <= 0)) 96 return -EINVAL; 97 if (snd_BUG_ON(!card || !name)) 98 return -EINVAL; 99 100 emu->card = card; 101 emu->name = kstrdup(name, GFP_KERNEL); 102 emu->voices = kcalloc(emu->max_voices, sizeof(struct snd_emux_voice), 103 GFP_KERNEL); 104 if (emu->voices == NULL) 105 return -ENOMEM; 106 107 /* create soundfont list */ 108 memset(&sf_cb, 0, sizeof(sf_cb)); 109 sf_cb.private_data = emu; 110 if (emu->ops.sample_new) 111 sf_cb.sample_new = sf_sample_new; 112 if (emu->ops.sample_free) 113 sf_cb.sample_free = sf_sample_free; 114 if (emu->ops.sample_reset) 115 sf_cb.sample_reset = sf_sample_reset; 116 emu->sflist = snd_sf_new(&sf_cb, emu->memhdr); 117 if (emu->sflist == NULL) 118 return -ENOMEM; 119 120 if ((err = snd_emux_init_hwdep(emu)) < 0) 121 return err; 122 123 snd_emux_init_voices(emu); 124 125 snd_emux_init_seq(emu, card, index); 126#ifdef CONFIG_SND_SEQUENCER_OSS 127 snd_emux_init_seq_oss(emu); 128#endif 129 snd_emux_init_virmidi(emu, card); 130 131#ifdef CONFIG_PROC_FS 132 snd_emux_proc_init(emu, card, index); 133#endif 134 return 0; 135} 136 137EXPORT_SYMBOL(snd_emux_register); 138 139/* 140 */ 141int snd_emux_free(struct snd_emux *emu) 142{ 143 unsigned long flags; 144 145 if (! emu) 146 return -EINVAL; 147 148 spin_lock_irqsave(&emu->voice_lock, flags); 149 if (emu->timer_active) 150 del_timer(&emu->tlist); 151 spin_unlock_irqrestore(&emu->voice_lock, flags); 152 153#ifdef CONFIG_PROC_FS 154 snd_emux_proc_free(emu); 155#endif 156 snd_emux_delete_virmidi(emu); 157#ifdef CONFIG_SND_SEQUENCER_OSS 158 snd_emux_detach_seq_oss(emu); 159#endif 160 snd_emux_detach_seq(emu); 161 snd_emux_delete_hwdep(emu); 162 snd_sf_free(emu->sflist); 163 kfree(emu->voices); 164 kfree(emu->name); 165 kfree(emu); 166 return 0; 167} 168 169EXPORT_SYMBOL(snd_emux_free); 170 171 172/* 173 * INIT part 174 */ 175 176static int __init alsa_emux_init(void) 177{ 178 return 0; 179} 180 181static void __exit alsa_emux_exit(void) 182{ 183} 184 185module_init(alsa_emux_init) 186module_exit(alsa_emux_exit) 187