11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Driver for Trident 4DWave DX/NX & SiS SI7018 Audio PCI soundcard
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Driver was originated by Trident <audio@tridentmicro.com>
61da177e4SLinus Torvalds * Fri Feb 19 15:55:28 MST 1999
71da177e4SLinus Torvalds */
81da177e4SLinus Torvalds
91da177e4SLinus Torvalds #include <linux/init.h>
101da177e4SLinus Torvalds #include <linux/pci.h>
111da177e4SLinus Torvalds #include <linux/time.h>
1265a77217SPaul Gortmaker #include <linux/module.h>
131da177e4SLinus Torvalds #include <sound/core.h>
1481fcb170STakashi Iwai #include "trident.h"
151da177e4SLinus Torvalds #include <sound/initval.h>
161da177e4SLinus Torvalds
17c1017a4cSJaroslav Kysela MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, <audio@tridentmicro.com>");
181da177e4SLinus Torvalds MODULE_DESCRIPTION("Trident 4D-WaveDX/NX & SiS SI7018");
191da177e4SLinus Torvalds MODULE_LICENSE("GPL");
201da177e4SLinus Torvalds
211da177e4SLinus Torvalds static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
221da177e4SLinus Torvalds static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
23a67ff6a5SRusty Russell static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
241da177e4SLinus Torvalds static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 32};
251da177e4SLinus Torvalds static int wavetable_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8192};
261da177e4SLinus Torvalds
271da177e4SLinus Torvalds module_param_array(index, int, NULL, 0444);
281da177e4SLinus Torvalds MODULE_PARM_DESC(index, "Index value for Trident 4DWave PCI soundcard.");
291da177e4SLinus Torvalds module_param_array(id, charp, NULL, 0444);
301da177e4SLinus Torvalds MODULE_PARM_DESC(id, "ID string for Trident 4DWave PCI soundcard.");
311da177e4SLinus Torvalds module_param_array(enable, bool, NULL, 0444);
321da177e4SLinus Torvalds MODULE_PARM_DESC(enable, "Enable Trident 4DWave PCI soundcard.");
331da177e4SLinus Torvalds module_param_array(pcm_channels, int, NULL, 0444);
341da177e4SLinus Torvalds MODULE_PARM_DESC(pcm_channels, "Number of hardware channels assigned for PCM.");
351da177e4SLinus Torvalds module_param_array(wavetable_size, int, NULL, 0444);
361da177e4SLinus Torvalds MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth.");
371da177e4SLinus Torvalds
389baa3c34SBenoit Taine static const struct pci_device_id snd_trident_ids[] = {
39e3183ec9SJon Mason {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
40e3183ec9SJon Mason PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
41e3183ec9SJon Mason {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
42e3183ec9SJon Mason 0, 0, 0},
43e3183ec9SJon Mason {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, 0},
441da177e4SLinus Torvalds { 0, }
451da177e4SLinus Torvalds };
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds MODULE_DEVICE_TABLE(pci, snd_trident_ids);
481da177e4SLinus Torvalds
snd_trident_probe(struct pci_dev * pci,const struct pci_device_id * pci_id)49e23e7a14SBill Pemberton static int snd_trident_probe(struct pci_dev *pci,
501da177e4SLinus Torvalds const struct pci_device_id *pci_id)
511da177e4SLinus Torvalds {
521da177e4SLinus Torvalds static int dev;
53bee1a5beSTakashi Iwai struct snd_card *card;
54bee1a5beSTakashi Iwai struct snd_trident *trident;
551da177e4SLinus Torvalds const char *str;
561da177e4SLinus Torvalds int err, pcm_dev = 0;
571da177e4SLinus Torvalds
581da177e4SLinus Torvalds if (dev >= SNDRV_CARDS)
591da177e4SLinus Torvalds return -ENODEV;
601da177e4SLinus Torvalds if (!enable[dev]) {
611da177e4SLinus Torvalds dev++;
621da177e4SLinus Torvalds return -ENOENT;
631da177e4SLinus Torvalds }
641da177e4SLinus Torvalds
65*5adfd8c2STakashi Iwai err = snd_devm_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
66*5adfd8c2STakashi Iwai sizeof(*trident), &card);
67e58de7baSTakashi Iwai if (err < 0)
68e58de7baSTakashi Iwai return err;
69*5adfd8c2STakashi Iwai trident = card->private_data;
701da177e4SLinus Torvalds
7134b946eeSTakashi Iwai err = snd_trident_create(card, pci,
721da177e4SLinus Torvalds pcm_channels[dev],
731da177e4SLinus Torvalds ((pci->vendor << 16) | pci->device) == TRIDENT_DEVICE_ID_SI7018 ? 1 : 2,
74*5adfd8c2STakashi Iwai wavetable_size[dev]);
75*5adfd8c2STakashi Iwai if (err < 0)
761da177e4SLinus Torvalds return err;
771da177e4SLinus Torvalds
781da177e4SLinus Torvalds switch (trident->device) {
791da177e4SLinus Torvalds case TRIDENT_DEVICE_ID_DX:
801da177e4SLinus Torvalds str = "TRID4DWAVEDX";
811da177e4SLinus Torvalds break;
821da177e4SLinus Torvalds case TRIDENT_DEVICE_ID_NX:
831da177e4SLinus Torvalds str = "TRID4DWAVENX";
841da177e4SLinus Torvalds break;
851da177e4SLinus Torvalds case TRIDENT_DEVICE_ID_SI7018:
861da177e4SLinus Torvalds str = "SI7018";
871da177e4SLinus Torvalds break;
881da177e4SLinus Torvalds default:
891da177e4SLinus Torvalds str = "Unknown";
901da177e4SLinus Torvalds }
911da177e4SLinus Torvalds strcpy(card->driver, str);
921da177e4SLinus Torvalds if (trident->device == TRIDENT_DEVICE_ID_SI7018) {
931da177e4SLinus Torvalds strcpy(card->shortname, "SiS ");
941da177e4SLinus Torvalds } else {
951da177e4SLinus Torvalds strcpy(card->shortname, "Trident ");
961da177e4SLinus Torvalds }
97d6b340d7STakashi Iwai strcat(card->shortname, str);
981da177e4SLinus Torvalds sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d",
991da177e4SLinus Torvalds card->shortname, trident->port, trident->irq);
1001da177e4SLinus Torvalds
10134b946eeSTakashi Iwai err = snd_trident_pcm(trident, pcm_dev++);
102*5adfd8c2STakashi Iwai if (err < 0)
1031da177e4SLinus Torvalds return err;
1041da177e4SLinus Torvalds switch (trident->device) {
1051da177e4SLinus Torvalds case TRIDENT_DEVICE_ID_DX:
1061da177e4SLinus Torvalds case TRIDENT_DEVICE_ID_NX:
10734b946eeSTakashi Iwai err = snd_trident_foldback_pcm(trident, pcm_dev++);
108*5adfd8c2STakashi Iwai if (err < 0)
1091da177e4SLinus Torvalds return err;
1101da177e4SLinus Torvalds break;
1111da177e4SLinus Torvalds }
1121da177e4SLinus Torvalds if (trident->device == TRIDENT_DEVICE_ID_NX || trident->device == TRIDENT_DEVICE_ID_SI7018) {
11334b946eeSTakashi Iwai err = snd_trident_spdif_pcm(trident, pcm_dev++);
114*5adfd8c2STakashi Iwai if (err < 0)
1151da177e4SLinus Torvalds return err;
1161da177e4SLinus Torvalds }
11734b946eeSTakashi Iwai if (trident->device != TRIDENT_DEVICE_ID_SI7018) {
11834b946eeSTakashi Iwai err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
119302e4c2fSTakashi Iwai trident->midi_port,
120dba8b469SClemens Ladisch MPU401_INFO_INTEGRATED |
121dba8b469SClemens Ladisch MPU401_INFO_IRQ_HOOK,
12234b946eeSTakashi Iwai -1, &trident->rmidi);
123*5adfd8c2STakashi Iwai if (err < 0)
1241da177e4SLinus Torvalds return err;
1251da177e4SLinus Torvalds }
1261da177e4SLinus Torvalds
1271da177e4SLinus Torvalds snd_trident_create_gameport(trident);
1281da177e4SLinus Torvalds
12934b946eeSTakashi Iwai err = snd_card_register(card);
130*5adfd8c2STakashi Iwai if (err < 0)
1311da177e4SLinus Torvalds return err;
1321da177e4SLinus Torvalds pci_set_drvdata(pci, card);
1331da177e4SLinus Torvalds dev++;
1341da177e4SLinus Torvalds return 0;
1351da177e4SLinus Torvalds }
1361da177e4SLinus Torvalds
137e9f66d9bSTakashi Iwai static struct pci_driver trident_driver = {
1383733e424STakashi Iwai .name = KBUILD_MODNAME,
1391da177e4SLinus Torvalds .id_table = snd_trident_ids,
1401da177e4SLinus Torvalds .probe = snd_trident_probe,
141c7561cd8STakashi Iwai #ifdef CONFIG_PM_SLEEP
14268cb2b55STakashi Iwai .driver = {
14368cb2b55STakashi Iwai .pm = &snd_trident_pm,
14468cb2b55STakashi Iwai },
145fb0700b4STakashi Iwai #endif
1461da177e4SLinus Torvalds };
1471da177e4SLinus Torvalds
148e9f66d9bSTakashi Iwai module_pci_driver(trident_driver);
149