linux/sound/pci/emu10k1/emu10k1_synth.c
<<
>>
Prefs
   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
  12MODULE_AUTHOR("Takashi Iwai");
  13MODULE_DESCRIPTION("Routines for control of EMU10K1 WaveTable synth");
  14MODULE_LICENSE("GPL");
  15
  16/*
  17 * create a new hardware dependent device for Emu10k1
  18 */
  19static 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->pitch_shift = -501;
  47        emux->memhdr = hw->memhdr;
  48        /* maximum two ports */
  49        emux->midi_ports = arg->seq_ports < 2 ? arg->seq_ports : 2;
  50        /* audigy has two external midis */
  51        emux->midi_devidx = hw->audigy ? 2 : 1;
  52        emux->linear_panning = 0;
  53        emux->hwdep_idx = 2; /* FIXED */
  54
  55        if (snd_emux_register(emux, dev->card, arg->index, "Emu10k1") < 0) {
  56                snd_emux_free(emux);
  57                return -ENOMEM;
  58        }
  59
  60        spin_lock_irqsave(&hw->voice_lock, flags);
  61        hw->synth = emux;
  62        hw->get_synth_voice = snd_emu10k1_synth_get_voice;
  63        spin_unlock_irqrestore(&hw->voice_lock, flags);
  64
  65        dev->driver_data = emux;
  66
  67        return 0;
  68}
  69
  70static int snd_emu10k1_synth_remove(struct device *_dev)
  71{
  72        struct snd_seq_device *dev = to_seq_dev(_dev);
  73        struct snd_emux *emux;
  74        struct snd_emu10k1 *hw;
  75        unsigned long flags;
  76
  77        if (dev->driver_data == NULL)
  78                return 0; /* not registered actually */
  79
  80        emux = dev->driver_data;
  81
  82        hw = emux->hw;
  83        spin_lock_irqsave(&hw->voice_lock, flags);
  84        hw->synth = NULL;
  85        hw->get_synth_voice = NULL;
  86        spin_unlock_irqrestore(&hw->voice_lock, flags);
  87
  88        snd_emux_free(emux);
  89        return 0;
  90}
  91
  92/*
  93 *  INIT part
  94 */
  95
  96static struct snd_seq_driver emu10k1_synth_driver = {
  97        .driver = {
  98                .name = KBUILD_MODNAME,
  99                .probe = snd_emu10k1_synth_probe,
 100                .remove = snd_emu10k1_synth_remove,
 101        },
 102        .id = SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH,
 103        .argsize = sizeof(struct snd_emu10k1_synth_arg),
 104};
 105
 106module_snd_seq_driver(emu10k1_synth_driver);
 107