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 EMU10K1 WaveTable synth
0006  */
0007 
0008 #include "emu10k1_synth_local.h"
0009 #include <linux/init.h>
0010 #include <linux/module.h>
0011 
0012 MODULE_AUTHOR("Takashi Iwai");
0013 MODULE_DESCRIPTION("Routines for control of EMU10K1 WaveTable synth");
0014 MODULE_LICENSE("GPL");
0015 
0016 /*
0017  * create a new hardware dependent device for Emu10k1
0018  */
0019 static int snd_emu10k1_synth_probe(struct device *_dev)
0020 {
0021     struct snd_seq_device *dev = to_seq_dev(_dev);
0022     struct snd_emux *emux;
0023     struct snd_emu10k1 *hw;
0024     struct snd_emu10k1_synth_arg *arg;
0025     unsigned long flags;
0026 
0027     arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
0028     if (arg == NULL)
0029         return -EINVAL;
0030 
0031     if (arg->seq_ports <= 0)
0032         return 0; /* nothing */
0033     if (arg->max_voices < 1)
0034         arg->max_voices = 1;
0035     else if (arg->max_voices > 64)
0036         arg->max_voices = 64;
0037 
0038     if (snd_emux_new(&emux) < 0)
0039         return -ENOMEM;
0040 
0041     snd_emu10k1_ops_setup(emux);
0042     hw = arg->hwptr;
0043     emux->hw = hw;
0044     emux->max_voices = arg->max_voices;
0045     emux->num_ports = arg->seq_ports;
0046     emux->pitch_shift = -501;
0047     emux->memhdr = hw->memhdr;
0048     /* maximum two ports */
0049     emux->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2;
0050     /* audigy has two external midis */
0051     emux->midi_devidx = hw->audigy ? 2 : 1;
0052     emux->linear_panning = 0;
0053     emux->hwdep_idx = 2; /* FIXED */
0054 
0055     if (snd_emux_register(emux, dev->card, arg->index, "Emu10k1") < 0) {
0056         snd_emux_free(emux);
0057         return -ENOMEM;
0058     }
0059 
0060     spin_lock_irqsave(&hw->voice_lock, flags);
0061     hw->synth = emux;
0062     hw->get_synth_voice = snd_emu10k1_synth_get_voice;
0063     spin_unlock_irqrestore(&hw->voice_lock, flags);
0064 
0065     dev->driver_data = emux;
0066 
0067     return 0;
0068 }
0069 
0070 static int snd_emu10k1_synth_remove(struct device *_dev)
0071 {
0072     struct snd_seq_device *dev = to_seq_dev(_dev);
0073     struct snd_emux *emux;
0074     struct snd_emu10k1 *hw;
0075     unsigned long flags;
0076 
0077     if (dev->driver_data == NULL)
0078         return 0; /* not registered actually */
0079 
0080     emux = dev->driver_data;
0081 
0082     hw = emux->hw;
0083     spin_lock_irqsave(&hw->voice_lock, flags);
0084     hw->synth = NULL;
0085     hw->get_synth_voice = NULL;
0086     spin_unlock_irqrestore(&hw->voice_lock, flags);
0087 
0088     snd_emux_free(emux);
0089     return 0;
0090 }
0091 
0092 /*
0093  *  INIT part
0094  */
0095 
0096 static struct snd_seq_driver emu10k1_synth_driver = {
0097     .driver = {
0098         .name = KBUILD_MODNAME,
0099         .probe = snd_emu10k1_synth_probe,
0100         .remove = snd_emu10k1_synth_remove,
0101     },
0102     .id = SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
0103     .argsize = sizeof(struct snd_emu10k1_synth_arg),
0104 };
0105 
0106 module_snd_seq_driver(emu10k1_synth_driver);