11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
3c1017a4cSJaroslav Kysela * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
41da177e4SLinus Torvalds * and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
51da177e4SLinus Torvalds * Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Emu8000 synth plug-in routine
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds
101da177e4SLinus Torvalds #include "emu8000_local.h"
111da177e4SLinus Torvalds #include <linux/init.h>
12da155d5bSPaul Gortmaker #include <linux/module.h>
131da177e4SLinus Torvalds #include <sound/initval.h>
141da177e4SLinus Torvalds
151da177e4SLinus Torvalds MODULE_AUTHOR("Takashi Iwai, Steve Ratcliffe");
161da177e4SLinus Torvalds MODULE_DESCRIPTION("Emu8000 synth plug-in routine");
171da177e4SLinus Torvalds MODULE_LICENSE("GPL");
181da177e4SLinus Torvalds
191da177e4SLinus Torvalds /*----------------------------------------------------------------*/
201da177e4SLinus Torvalds
211da177e4SLinus Torvalds /*
221da177e4SLinus Torvalds * create a new hardware dependent device for Emu8000
231da177e4SLinus Torvalds */
snd_emu8000_probe(struct device * _dev)2405662205STakashi Iwai static int snd_emu8000_probe(struct device *_dev)
251da177e4SLinus Torvalds {
2605662205STakashi Iwai struct snd_seq_device *dev = to_seq_dev(_dev);
27029d64b0STakashi Iwai struct snd_emu8000 *hw;
28029d64b0STakashi Iwai struct snd_emux *emu;
291da177e4SLinus Torvalds
30029d64b0STakashi Iwai hw = *(struct snd_emu8000**)SNDRV_SEQ_DEVICE_ARGPTR(dev);
311da177e4SLinus Torvalds if (hw == NULL)
321da177e4SLinus Torvalds return -EINVAL;
331da177e4SLinus Torvalds
341da177e4SLinus Torvalds if (hw->emu)
351da177e4SLinus Torvalds return -EBUSY; /* already exists..? */
361da177e4SLinus Torvalds
371da177e4SLinus Torvalds if (snd_emux_new(&emu) < 0)
381da177e4SLinus Torvalds return -ENOMEM;
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds hw->emu = emu;
411da177e4SLinus Torvalds snd_emu8000_ops_setup(hw);
421da177e4SLinus Torvalds
431da177e4SLinus Torvalds emu->hw = hw;
441da177e4SLinus Torvalds emu->max_voices = EMU8000_DRAM_VOICES;
451da177e4SLinus Torvalds emu->num_ports = hw->seq_ports;
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds if (hw->memhdr) {
4899b359baSTakashi Iwai snd_printk(KERN_ERR "memhdr is already initialized!?\n");
491da177e4SLinus Torvalds snd_util_memhdr_free(hw->memhdr);
501da177e4SLinus Torvalds }
511da177e4SLinus Torvalds hw->memhdr = snd_util_memhdr_new(hw->mem_size);
521da177e4SLinus Torvalds if (hw->memhdr == NULL) {
531da177e4SLinus Torvalds snd_emux_free(emu);
541da177e4SLinus Torvalds hw->emu = NULL;
551da177e4SLinus Torvalds return -ENOMEM;
561da177e4SLinus Torvalds }
571da177e4SLinus Torvalds
581da177e4SLinus Torvalds emu->memhdr = hw->memhdr;
591da177e4SLinus Torvalds emu->midi_ports = hw->seq_ports < 2 ? hw->seq_ports : 2; /* number of virmidi ports */
601da177e4SLinus Torvalds emu->midi_devidx = 1;
611da177e4SLinus Torvalds emu->linear_panning = 1;
621da177e4SLinus Torvalds emu->hwdep_idx = 2; /* FIXED */
631da177e4SLinus Torvalds
641da177e4SLinus Torvalds if (snd_emux_register(emu, dev->card, hw->index, "Emu8000") < 0) {
651da177e4SLinus Torvalds snd_emux_free(emu);
661da177e4SLinus Torvalds snd_util_memhdr_free(hw->memhdr);
671da177e4SLinus Torvalds hw->emu = NULL;
681da177e4SLinus Torvalds hw->memhdr = NULL;
691da177e4SLinus Torvalds return -ENOMEM;
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds
721da177e4SLinus Torvalds if (hw->mem_size > 0)
731da177e4SLinus Torvalds snd_emu8000_pcm_new(dev->card, hw, 1);
741da177e4SLinus Torvalds
751da177e4SLinus Torvalds dev->driver_data = hw;
761da177e4SLinus Torvalds
771da177e4SLinus Torvalds return 0;
781da177e4SLinus Torvalds }
791da177e4SLinus Torvalds
801da177e4SLinus Torvalds
811da177e4SLinus Torvalds /*
821da177e4SLinus Torvalds * free all resources
831da177e4SLinus Torvalds */
snd_emu8000_remove(struct device * _dev)8405662205STakashi Iwai static int snd_emu8000_remove(struct device *_dev)
851da177e4SLinus Torvalds {
8605662205STakashi Iwai struct snd_seq_device *dev = to_seq_dev(_dev);
87029d64b0STakashi Iwai struct snd_emu8000 *hw;
881da177e4SLinus Torvalds
891da177e4SLinus Torvalds if (dev->driver_data == NULL)
901da177e4SLinus Torvalds return 0; /* no synth was allocated actually */
911da177e4SLinus Torvalds
921da177e4SLinus Torvalds hw = dev->driver_data;
931da177e4SLinus Torvalds if (hw->pcm)
941da177e4SLinus Torvalds snd_device_free(dev->card, hw->pcm);
951da177e4SLinus Torvalds snd_emux_free(hw->emu);
961da177e4SLinus Torvalds snd_util_memhdr_free(hw->memhdr);
971da177e4SLinus Torvalds hw->emu = NULL;
981da177e4SLinus Torvalds hw->memhdr = NULL;
991da177e4SLinus Torvalds return 0;
1001da177e4SLinus Torvalds }
1011da177e4SLinus Torvalds
1021da177e4SLinus Torvalds /*
1031da177e4SLinus Torvalds * INIT part
1041da177e4SLinus Torvalds */
1051da177e4SLinus Torvalds
10605662205STakashi Iwai static struct snd_seq_driver emu8000_driver = {
10705662205STakashi Iwai .driver = {
10805662205STakashi Iwai .name = KBUILD_MODNAME,
10905662205STakashi Iwai .probe = snd_emu8000_probe,
11005662205STakashi Iwai .remove = snd_emu8000_remove,
11105662205STakashi Iwai },
11205662205STakashi Iwai .id = SNDRV_SEQ_DEV_ID_EMU8000,
11305662205STakashi Iwai .argsize = sizeof(struct snd_emu8000 *),
1141da177e4SLinus Torvalds };
1151da177e4SLinus Torvalds
11605662205STakashi Iwai module_snd_seq_driver(emu8000_driver);
117