xref: /openbmc/linux/sound/isa/sb/emu8000_synth.c (revision 1a59d1b8)
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