Path: blob/master/sound/pci/emu10k1/emu10k1_synth.c
10818 views
/*1* Copyright (C) 2000 Takashi Iwai <[email protected]>2*3* Routines for control of EMU10K1 WaveTable synth4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*/1920#include "emu10k1_synth_local.h"21#include <linux/init.h>2223MODULE_AUTHOR("Takashi Iwai");24MODULE_DESCRIPTION("Routines for control of EMU10K1 WaveTable synth");25MODULE_LICENSE("GPL");2627/*28* create a new hardware dependent device for Emu10k129*/30static int snd_emu10k1_synth_new_device(struct snd_seq_device *dev)31{32struct snd_emux *emux;33struct snd_emu10k1 *hw;34struct snd_emu10k1_synth_arg *arg;35unsigned long flags;3637arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);38if (arg == NULL)39return -EINVAL;4041if (arg->seq_ports <= 0)42return 0; /* nothing */43if (arg->max_voices < 1)44arg->max_voices = 1;45else if (arg->max_voices > 64)46arg->max_voices = 64;4748if (snd_emux_new(&emux) < 0)49return -ENOMEM;5051snd_emu10k1_ops_setup(emux);52hw = arg->hwptr;53emux->hw = hw;54emux->max_voices = arg->max_voices;55emux->num_ports = arg->seq_ports;56emux->pitch_shift = -501;57emux->memhdr = hw->memhdr;58/* maximum two ports */59emux->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2;60/* audigy has two external midis */61emux->midi_devidx = hw->audigy ? 2 : 1;62emux->linear_panning = 0;63emux->hwdep_idx = 2; /* FIXED */6465if (snd_emux_register(emux, dev->card, arg->index, "Emu10k1") < 0) {66snd_emux_free(emux);67return -ENOMEM;68}6970spin_lock_irqsave(&hw->voice_lock, flags);71hw->synth = emux;72hw->get_synth_voice = snd_emu10k1_synth_get_voice;73spin_unlock_irqrestore(&hw->voice_lock, flags);7475dev->driver_data = emux;7677return 0;78}7980static int snd_emu10k1_synth_delete_device(struct snd_seq_device *dev)81{82struct snd_emux *emux;83struct snd_emu10k1 *hw;84unsigned long flags;8586if (dev->driver_data == NULL)87return 0; /* not registered actually */8889emux = dev->driver_data;9091hw = emux->hw;92spin_lock_irqsave(&hw->voice_lock, flags);93hw->synth = NULL;94hw->get_synth_voice = NULL;95spin_unlock_irqrestore(&hw->voice_lock, flags);9697snd_emux_free(emux);98return 0;99}100101/*102* INIT part103*/104105static int __init alsa_emu10k1_synth_init(void)106{107108static struct snd_seq_dev_ops ops = {109snd_emu10k1_synth_new_device,110snd_emu10k1_synth_delete_device,111};112return snd_seq_device_register_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, &ops,113sizeof(struct snd_emu10k1_synth_arg));114}115116static void __exit alsa_emu10k1_synth_exit(void)117{118snd_seq_device_unregister_driver(SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH);119}120121module_init(alsa_emu10k1_synth_init)122module_exit(alsa_emu10k1_synth_exit)123124125