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