162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * The driver for the EMU10K1 (SB Live!) based soundcards 462306a36Sopenharmony_ci * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 562306a36Sopenharmony_ci * James Courtier-Dutton <James@superbug.co.uk> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/init.h> 962306a36Sopenharmony_ci#include <linux/pci.h> 1062306a36Sopenharmony_ci#include <linux/time.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <sound/core.h> 1362306a36Sopenharmony_ci#include <sound/emu10k1.h> 1462306a36Sopenharmony_ci#include <sound/initval.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ciMODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 1762306a36Sopenharmony_ciMODULE_DESCRIPTION("EMU10K1"); 1862306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_SND_SEQUENCER) 2162306a36Sopenharmony_ci#define ENABLE_SYNTH 2262306a36Sopenharmony_ci#include <sound/emu10k1_synth.h> 2362306a36Sopenharmony_ci#endif 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 2662306a36Sopenharmony_cistatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 2762306a36Sopenharmony_cistatic bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 2862306a36Sopenharmony_cistatic int extin[SNDRV_CARDS]; 2962306a36Sopenharmony_cistatic int extout[SNDRV_CARDS]; 3062306a36Sopenharmony_cistatic int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4}; 3162306a36Sopenharmony_cistatic int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64}; 3262306a36Sopenharmony_cistatic int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128}; 3362306a36Sopenharmony_cistatic bool enable_ir[SNDRV_CARDS]; 3462306a36Sopenharmony_cistatic uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cimodule_param_array(index, int, NULL, 0444); 3762306a36Sopenharmony_ciMODULE_PARM_DESC(index, "Index value for the EMU10K1 soundcard."); 3862306a36Sopenharmony_cimodule_param_array(id, charp, NULL, 0444); 3962306a36Sopenharmony_ciMODULE_PARM_DESC(id, "ID string for the EMU10K1 soundcard."); 4062306a36Sopenharmony_cimodule_param_array(enable, bool, NULL, 0444); 4162306a36Sopenharmony_ciMODULE_PARM_DESC(enable, "Enable the EMU10K1 soundcard."); 4262306a36Sopenharmony_cimodule_param_array(extin, int, NULL, 0444); 4362306a36Sopenharmony_ciMODULE_PARM_DESC(extin, "Available external inputs for FX8010. Zero=default."); 4462306a36Sopenharmony_cimodule_param_array(extout, int, NULL, 0444); 4562306a36Sopenharmony_ciMODULE_PARM_DESC(extout, "Available external outputs for FX8010. Zero=default."); 4662306a36Sopenharmony_cimodule_param_array(seq_ports, int, NULL, 0444); 4762306a36Sopenharmony_ciMODULE_PARM_DESC(seq_ports, "Allocated sequencer ports for internal synthesizer."); 4862306a36Sopenharmony_cimodule_param_array(max_synth_voices, int, NULL, 0444); 4962306a36Sopenharmony_ciMODULE_PARM_DESC(max_synth_voices, "Maximum number of voices for WaveTable."); 5062306a36Sopenharmony_cimodule_param_array(max_buffer_size, int, NULL, 0444); 5162306a36Sopenharmony_ciMODULE_PARM_DESC(max_buffer_size, "Maximum sample buffer size in MB."); 5262306a36Sopenharmony_cimodule_param_array(enable_ir, bool, NULL, 0444); 5362306a36Sopenharmony_ciMODULE_PARM_DESC(enable_ir, "Enable IR."); 5462306a36Sopenharmony_cimodule_param_array(subsystem, uint, NULL, 0444); 5562306a36Sopenharmony_ciMODULE_PARM_DESC(subsystem, "Force card subsystem model."); 5662306a36Sopenharmony_ci/* 5762306a36Sopenharmony_ci * Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_cistatic const struct pci_device_id snd_emu10k1_ids[] = { 6062306a36Sopenharmony_ci { PCI_VDEVICE(CREATIVE, 0x0002), 0 }, /* EMU10K1 */ 6162306a36Sopenharmony_ci { PCI_VDEVICE(CREATIVE, 0x0004), 1 }, /* Audigy */ 6262306a36Sopenharmony_ci { PCI_VDEVICE(CREATIVE, 0x0008), 1 }, /* Audigy 2 Value SB0400 */ 6362306a36Sopenharmony_ci { 0, } 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, snd_emu10k1_ids); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic int snd_card_emu10k1_probe(struct pci_dev *pci, 6962306a36Sopenharmony_ci const struct pci_device_id *pci_id) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci static int dev; 7262306a36Sopenharmony_ci struct snd_card *card; 7362306a36Sopenharmony_ci struct snd_emu10k1 *emu; 7462306a36Sopenharmony_ci#ifdef ENABLE_SYNTH 7562306a36Sopenharmony_ci struct snd_seq_device *wave = NULL; 7662306a36Sopenharmony_ci#endif 7762306a36Sopenharmony_ci int err; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (dev >= SNDRV_CARDS) 8062306a36Sopenharmony_ci return -ENODEV; 8162306a36Sopenharmony_ci if (!enable[dev]) { 8262306a36Sopenharmony_ci dev++; 8362306a36Sopenharmony_ci return -ENOENT; 8462306a36Sopenharmony_ci } 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE, 8762306a36Sopenharmony_ci sizeof(*emu), &card); 8862306a36Sopenharmony_ci if (err < 0) 8962306a36Sopenharmony_ci return err; 9062306a36Sopenharmony_ci emu = card->private_data; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci if (max_buffer_size[dev] < 32) 9362306a36Sopenharmony_ci max_buffer_size[dev] = 32; 9462306a36Sopenharmony_ci else if (max_buffer_size[dev] > 1024) 9562306a36Sopenharmony_ci max_buffer_size[dev] = 1024; 9662306a36Sopenharmony_ci err = snd_emu10k1_create(card, pci, extin[dev], extout[dev], 9762306a36Sopenharmony_ci (long)max_buffer_size[dev] * 1024 * 1024, 9862306a36Sopenharmony_ci enable_ir[dev], subsystem[dev]); 9962306a36Sopenharmony_ci if (err < 0) 10062306a36Sopenharmony_ci return err; 10162306a36Sopenharmony_ci err = snd_emu10k1_pcm(emu, 0); 10262306a36Sopenharmony_ci if (err < 0) 10362306a36Sopenharmony_ci return err; 10462306a36Sopenharmony_ci if (emu->card_capabilities->ac97_chip) { 10562306a36Sopenharmony_ci err = snd_emu10k1_pcm_mic(emu, 1); 10662306a36Sopenharmony_ci if (err < 0) 10762306a36Sopenharmony_ci return err; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci err = snd_emu10k1_pcm_efx(emu, 2); 11062306a36Sopenharmony_ci if (err < 0) 11162306a36Sopenharmony_ci return err; 11262306a36Sopenharmony_ci /* This stores the periods table. */ 11362306a36Sopenharmony_ci if (emu->card_capabilities->ca0151_chip) { /* P16V */ 11462306a36Sopenharmony_ci emu->p16v_buffer = 11562306a36Sopenharmony_ci snd_devm_alloc_pages(&pci->dev, SNDRV_DMA_TYPE_DEV, 1024); 11662306a36Sopenharmony_ci if (!emu->p16v_buffer) 11762306a36Sopenharmony_ci return -ENOMEM; 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci err = snd_emu10k1_mixer(emu, 0, 3); 12162306a36Sopenharmony_ci if (err < 0) 12262306a36Sopenharmony_ci return err; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci err = snd_emu10k1_timer(emu, 0); 12562306a36Sopenharmony_ci if (err < 0) 12662306a36Sopenharmony_ci return err; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci err = snd_emu10k1_pcm_multi(emu, 3); 12962306a36Sopenharmony_ci if (err < 0) 13062306a36Sopenharmony_ci return err; 13162306a36Sopenharmony_ci if (emu->card_capabilities->ca0151_chip) { /* P16V */ 13262306a36Sopenharmony_ci err = snd_p16v_pcm(emu, 4); 13362306a36Sopenharmony_ci if (err < 0) 13462306a36Sopenharmony_ci return err; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci if (emu->audigy) { 13762306a36Sopenharmony_ci err = snd_emu10k1_audigy_midi(emu); 13862306a36Sopenharmony_ci if (err < 0) 13962306a36Sopenharmony_ci return err; 14062306a36Sopenharmony_ci } else { 14162306a36Sopenharmony_ci err = snd_emu10k1_midi(emu); 14262306a36Sopenharmony_ci if (err < 0) 14362306a36Sopenharmony_ci return err; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci err = snd_emu10k1_fx8010_new(emu, 0); 14662306a36Sopenharmony_ci if (err < 0) 14762306a36Sopenharmony_ci return err; 14862306a36Sopenharmony_ci#ifdef ENABLE_SYNTH 14962306a36Sopenharmony_ci if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_EMU10K1_SYNTH, 15062306a36Sopenharmony_ci sizeof(struct snd_emu10k1_synth_arg), &wave) < 0 || 15162306a36Sopenharmony_ci wave == NULL) { 15262306a36Sopenharmony_ci dev_warn(emu->card->dev, 15362306a36Sopenharmony_ci "can't initialize Emu10k1 wavetable synth\n"); 15462306a36Sopenharmony_ci } else { 15562306a36Sopenharmony_ci struct snd_emu10k1_synth_arg *arg; 15662306a36Sopenharmony_ci arg = SNDRV_SEQ_DEVICE_ARGPTR(wave); 15762306a36Sopenharmony_ci strcpy(wave->name, "Emu-10k1 Synth"); 15862306a36Sopenharmony_ci arg->hwptr = emu; 15962306a36Sopenharmony_ci arg->index = 1; 16062306a36Sopenharmony_ci arg->seq_ports = seq_ports[dev]; 16162306a36Sopenharmony_ci arg->max_voices = max_synth_voices[dev]; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci#endif 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci strscpy(card->driver, emu->card_capabilities->driver, 16662306a36Sopenharmony_ci sizeof(card->driver)); 16762306a36Sopenharmony_ci strscpy(card->shortname, emu->card_capabilities->name, 16862306a36Sopenharmony_ci sizeof(card->shortname)); 16962306a36Sopenharmony_ci snprintf(card->longname, sizeof(card->longname), 17062306a36Sopenharmony_ci "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i", 17162306a36Sopenharmony_ci card->shortname, emu->revision, emu->serial, emu->port, emu->irq); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci err = snd_card_register(card); 17462306a36Sopenharmony_ci if (err < 0) 17562306a36Sopenharmony_ci return err; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci pci_set_drvdata(pci, card); 17862306a36Sopenharmony_ci dev++; 17962306a36Sopenharmony_ci return 0; 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 18362306a36Sopenharmony_cistatic int snd_emu10k1_suspend(struct device *dev) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci struct snd_card *card = dev_get_drvdata(dev); 18662306a36Sopenharmony_ci struct snd_emu10k1 *emu = card->private_data; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci emu->suspend = 1; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci cancel_work_sync(&emu->emu1010.firmware_work); 19362306a36Sopenharmony_ci cancel_work_sync(&emu->emu1010.clock_work); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci snd_ac97_suspend(emu->ac97); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci snd_emu10k1_efx_suspend(emu); 19862306a36Sopenharmony_ci snd_emu10k1_suspend_regs(emu); 19962306a36Sopenharmony_ci if (emu->card_capabilities->ca0151_chip) 20062306a36Sopenharmony_ci snd_p16v_suspend(emu); 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci snd_emu10k1_done(emu); 20362306a36Sopenharmony_ci return 0; 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic int snd_emu10k1_resume(struct device *dev) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci struct snd_card *card = dev_get_drvdata(dev); 20962306a36Sopenharmony_ci struct snd_emu10k1 *emu = card->private_data; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci snd_emu10k1_resume_init(emu); 21262306a36Sopenharmony_ci snd_emu10k1_efx_resume(emu); 21362306a36Sopenharmony_ci snd_ac97_resume(emu->ac97); 21462306a36Sopenharmony_ci snd_emu10k1_resume_regs(emu); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci if (emu->card_capabilities->ca0151_chip) 21762306a36Sopenharmony_ci snd_p16v_resume(emu); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci emu->suspend = 0; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci snd_power_change_state(card, SNDRV_CTL_POWER_D0); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci return 0; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(snd_emu10k1_pm, snd_emu10k1_suspend, snd_emu10k1_resume); 22762306a36Sopenharmony_ci#define SND_EMU10K1_PM_OPS &snd_emu10k1_pm 22862306a36Sopenharmony_ci#else 22962306a36Sopenharmony_ci#define SND_EMU10K1_PM_OPS NULL 23062306a36Sopenharmony_ci#endif /* CONFIG_PM_SLEEP */ 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_cistatic struct pci_driver emu10k1_driver = { 23362306a36Sopenharmony_ci .name = KBUILD_MODNAME, 23462306a36Sopenharmony_ci .id_table = snd_emu10k1_ids, 23562306a36Sopenharmony_ci .probe = snd_card_emu10k1_probe, 23662306a36Sopenharmony_ci .driver = { 23762306a36Sopenharmony_ci .pm = SND_EMU10K1_PM_OPS, 23862306a36Sopenharmony_ci }, 23962306a36Sopenharmony_ci}; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cimodule_pci_driver(emu10k1_driver); 242