1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2000 Takashi Iwai <tiwai@suse.de> 4 * 5 * Routines for control of EMU10K1 WaveTable synth 6 */ 7 8 #include "emu10k1_synth_local.h" 9 #include <linux/init.h> 10 #include <linux/module.h> 11 12 MODULE_AUTHOR("Takashi Iwai"); 13 MODULE_DESCRIPTION("Routines for control of EMU10K1 WaveTable synth"); 14 MODULE_LICENSE("GPL"); 15 16 /* 17 * create a new hardware dependent device for Emu10k1 18 */ 19 static int snd_emu10k1_synth_probe(struct device *_dev) 20 { 21 struct snd_seq_device *dev = to_seq_dev(_dev); 22 struct snd_emux *emux; 23 struct snd_emu10k1 *hw; 24 struct snd_emu10k1_synth_arg *arg; 25 unsigned long flags; 26 27 arg = SNDRV_SEQ_DEVICE_ARGPTR(dev); 28 if (arg == NULL) 29 return -EINVAL; 30 31 if (arg->seq_ports <= 0) 32 return 0; /* nothing */ 33 if (arg->max_voices < 1) 34 arg->max_voices = 1; 35 else if (arg->max_voices > 64) 36 arg->max_voices = 64; 37 38 if (snd_emux_new(&emux) < 0) 39 return -ENOMEM; 40 41 snd_emu10k1_ops_setup(emux); 42 hw = arg->hwptr; 43 emux->hw = hw; 44 emux->max_voices = arg->max_voices; 45 emux->num_ports = arg->seq_ports; 46 emux->memhdr = hw->memhdr; 47 /* maximum two ports */ 48 emux->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2; 49 /* audigy has two external midis */ 50 emux->midi_devidx = hw->audigy ? 2 : 1; 51 emux->linear_panning = 0; 52 emux->hwdep_idx = 2; /* FIXED */ 53 54 if (snd_emux_register(emux, dev->card, arg->index, "Emu10k1") < 0) { 55 snd_emux_free(emux); 56 return -ENOMEM; 57 } 58 59 spin_lock_irqsave(&hw->voice_lock, flags); 60 hw->synth = emux; 61 hw->get_synth_voice = snd_emu10k1_synth_get_voice; 62 spin_unlock_irqrestore(&hw->voice_lock, flags); 63 64 dev->driver_data = emux; 65 66 return 0; 67 } 68 69 static int snd_emu10k1_synth_remove(struct device *_dev) 70 { 71 struct snd_seq_device *dev = to_seq_dev(_dev); 72 struct snd_emux *emux; 73 struct snd_emu10k1 *hw; 74 unsigned long flags; 75 76 if (dev->driver_data == NULL) 77 return 0; /* not registered actually */ 78 79 emux = dev->driver_data; 80 81 hw = emux->hw; 82 spin_lock_irqsave(&hw->voice_lock, flags); 83 hw->synth = NULL; 84 hw->get_synth_voice = NULL; 85 spin_unlock_irqrestore(&hw->voice_lock, flags); 86 87 snd_emux_free(emux); 88 return 0; 89 } 90 91 /* 92 * INIT part 93 */ 94 95 static struct snd_seq_driver emu10k1_synth_driver = { 96 .driver = { 97 .name = KBUILD_MODNAME, 98 .probe = snd_emu10k1_synth_probe, 99 .remove = snd_emu10k1_synth_remove, 100 }, 101 .id = SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, 102 .argsize = sizeof(struct snd_emu10k1_synth_arg), 103 }; 104 105 module_snd_seq_driver(emu10k1_synth_driver); 106