11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The driver for the Yamaha's DS1/DS1E cards 3c1017a4cdb68ae5368fbc9ee42c77f1f5dca8916Jaroslav Kysela * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License as published by 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2 of the License, or 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * (at your option) any later version. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/time.h> 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h> 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sound/core.h> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sound/ymfpci.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sound/mpu401.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sound/opl3.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <sound/initval.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 32c1017a4cdb68ae5368fbc9ee42c77f1f5dca8916Jaroslav KyselaMODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>"); 3322fb2a708d2f390808f20609213fd6a588bf7612Clemens LadischMODULE_DESCRIPTION("Yamaha DS-1 PCI"); 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724}," 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "{Yamaha,YMF724F}," 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "{Yamaha,YMF740}," 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "{Yamaha,YMF740C}," 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "{Yamaha,YMF744}," 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "{Yamaha,YMF754}}"); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long fm_port[SNDRV_CARDS]; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long mpu_port[SNDRV_CARDS]; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SUPPORT_JOYSTICK 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic long joystick_port[SNDRV_CARDS]; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int rear_switch[SNDRV_CARDS]; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(index, int, NULL, 0444); 5322fb2a708d2f390808f20609213fd6a588bf7612Clemens LadischMODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard."); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(id, charp, NULL, 0444); 5522fb2a708d2f390808f20609213fd6a588bf7612Clemens LadischMODULE_PARM_DESC(id, "ID string for the Yamaha DS-1 PCI soundcard."); 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(enable, bool, NULL, 0444); 5722fb2a708d2f390808f20609213fd6a588bf7612Clemens LadischMODULE_PARM_DESC(enable, "Enable Yamaha DS-1 soundcard."); 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(mpu_port, long, NULL, 0444); 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(mpu_port, "MPU-401 Port."); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(fm_port, long, NULL, 0444); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(fm_port, "FM OPL-3 Port."); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SUPPORT_JOYSTICK 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(joystick_port, long, NULL, 0444); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(joystick_port, "Joystick port address"); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(rear_switch, bool, NULL, 0444); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch"); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 69cebe41d4b8f8092359de31e241815fcb4b4dc0beAlexey Dobriyanstatic DEFINE_PCI_DEVICE_TABLE(snd_ymfpci_ids) = { 7028d27aae9432c300857722a917be4065c6d7abffJoe Perches { PCI_VDEVICE(YAMAHA, 0x0004), 0, }, /* YMF724 */ 7128d27aae9432c300857722a917be4065c6d7abffJoe Perches { PCI_VDEVICE(YAMAHA, 0x000d), 0, }, /* YMF724F */ 7228d27aae9432c300857722a917be4065c6d7abffJoe Perches { PCI_VDEVICE(YAMAHA, 0x000a), 0, }, /* YMF740 */ 7328d27aae9432c300857722a917be4065c6d7abffJoe Perches { PCI_VDEVICE(YAMAHA, 0x000c), 0, }, /* YMF740C */ 7428d27aae9432c300857722a917be4065c6d7abffJoe Perches { PCI_VDEVICE(YAMAHA, 0x0010), 0, }, /* YMF744 */ 7528d27aae9432c300857722a917be4065c6d7abffJoe Perches { PCI_VDEVICE(YAMAHA, 0x0012), 0, }, /* YMF754 */ 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 0, } 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DEVICE_TABLE(pci, snd_ymfpci_ids); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef SUPPORT_JOYSTICK 82208a1b4cb5ad97510aa9cbe51d09e55656691cb4Takashi Iwaistatic int __devinit snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int legacy_ctrl, int legacy_ctrl2) 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct gameport *gp; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *r = NULL; 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int io_port = joystick_port[dev]; 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!io_port) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip->pci->device >= 0x0010) { /* YMF 744/754 */ 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (io_port == 1) { 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* auto-detect */ 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(io_port = pci_resource_start(chip->pci, 2))) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (io_port == 1) { 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* auto-detect */ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (io_port = 0x201; io_port <= 0x205; io_port++) { 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (io_port == 0x203) 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((r = request_region(io_port, 1, "YMFPCI gameport")) != NULL) 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!r) { 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "ymfpci: no gameport ports available\n"); 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (io_port) { 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x201: legacy_ctrl2 |= 0 << 6; break; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x202: legacy_ctrl2 |= 1 << 6; break; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x204: legacy_ctrl2 |= 2 << 6; break; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x205: legacy_ctrl2 |= 3 << 6; break; 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "ymfpci: invalid joystick port %#x", io_port); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!r && !(r = request_region(io_port, 1, "YMFPCI gameport"))) { 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "ymfpci: joystick port %#x is in use.\n", io_port); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip->gameport = gp = gameport_allocate_port(); 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!gp) { 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "ymfpci: cannot allocate memory for gameport\n"); 132b1d5776d865951c213a1caaab5d8bf5de7615dbdTakashi Iwai release_and_free_resource(r); 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gameport_set_name(gp, "Yamaha YMF Gameport"); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci)); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gameport_set_dev_parent(gp, &chip->pci->dev); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gp->io = io_port; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gameport_set_port_data(gp, r); 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip->pci->device >= 0x0010) /* YMF 744/754 */ 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, legacy_ctrl | YMFPCI_LEGACY_JPEN); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2); 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gameport_register_port(chip->gameport); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 154208a1b4cb5ad97510aa9cbe51d09e55656691cb4Takashi Iwaivoid snd_ymfpci_free_gameport(struct snd_ymfpci *chip) 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip->gameport) { 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *r = gameport_get_port_data(chip->gameport); 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gameport_unregister_port(chip->gameport); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip->gameport = NULL; 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 162b1d5776d865951c213a1caaab5d8bf5de7615dbdTakashi Iwai release_and_free_resource(r); 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else 166208a1b4cb5ad97510aa9cbe51d09e55656691cb4Takashi Iwaistatic inline int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, int l, int l2) { return -ENOSYS; } 167208a1b4cb5ad97510aa9cbe51d09e55656691cb4Takashi Iwaivoid snd_ymfpci_free_gameport(struct snd_ymfpci *chip) { } 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* SUPPORT_JOYSTICK */ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __devinit snd_card_ymfpci_probe(struct pci_dev *pci, 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct pci_device_id *pci_id) 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds static int dev; 174208a1b4cb5ad97510aa9cbe51d09e55656691cb4Takashi Iwai struct snd_card *card; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *fm_res = NULL; 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct resource *mpu_res = NULL; 177208a1b4cb5ad97510aa9cbe51d09e55656691cb4Takashi Iwai struct snd_ymfpci *chip; 178208a1b4cb5ad97510aa9cbe51d09e55656691cb4Takashi Iwai struct snd_opl3 *opl3; 17922fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch const char *str, *model; 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 legacy_ctrl, legacy_ctrl2, old_legacy_ctrl; 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (dev >= SNDRV_CARDS) 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!enable[dev]) { 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev++; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOENT; 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 190e58de7baf7de11f01a675cbbf6ecc8a2758b9ca5Takashi Iwai err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); 191e58de7baf7de11f01a675cbbf6ecc8a2758b9ca5Takashi Iwai if (err < 0) 192e58de7baf7de11f01a675cbbf6ecc8a2758b9ca5Takashi Iwai return err; 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (pci_id->device) { 19522fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch case 0x0004: str = "YMF724"; model = "DS-1"; break; 19622fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch case 0x000d: str = "YMF724F"; model = "DS-1"; break; 19722fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch case 0x000a: str = "YMF740"; model = "DS-1L"; break; 19822fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch case 0x000c: str = "YMF740C"; model = "DS-1L"; break; 19922fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch case 0x0010: str = "YMF744"; model = "DS-1S"; break; 20022fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch case 0x0012: str = "YMF754"; model = "DS-1E"; break; 20122fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch default: model = str = "???"; break; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl = 0; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl2 = 0x0800; /* SBEN = 0, SMOD = 01, LAD = 0 */ 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (pci_id->device >= 0x0010) { /* YMF 744/754 */ 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fm_port[dev] == 1) { 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* auto-detect */ 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fm_port[dev] = pci_resource_start(pci, 1); 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fm_port[dev] > 0 && 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3")) != NULL) { 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl |= YMFPCI_LEGACY_FMEN; 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(pci, PCIR_DSXG_FMBASE, fm_port[dev]); 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mpu_port[dev] == 1) { 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* auto-detect */ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mpu_port[dev] = pci_resource_start(pci, 1) + 0x20; 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mpu_port[dev] > 0 && 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401")) != NULL) { 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl |= YMFPCI_LEGACY_MEN; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]); 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (fm_port[dev]) { 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x388: legacy_ctrl2 |= 0; break; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x398: legacy_ctrl2 |= 1; break; 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x3a0: legacy_ctrl2 |= 2; break; 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x3a8: legacy_ctrl2 |= 3; break; 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: fm_port[dev] = 0; break; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (fm_port[dev] > 0 && 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (fm_res = request_region(fm_port[dev], 4, "YMFPCI OPL3")) != NULL) { 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl |= YMFPCI_LEGACY_FMEN; 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl2 &= ~YMFPCI_LEGACY2_FMIO; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fm_port[dev] = 0; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (mpu_port[dev]) { 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x330: legacy_ctrl2 |= 0 << 4; break; 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x300: legacy_ctrl2 |= 1 << 4; break; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x332: legacy_ctrl2 |= 2 << 4; break; 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x334: legacy_ctrl2 |= 3 << 4; break; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: mpu_port[dev] = 0; break; 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mpu_port[dev] > 0 && 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds (mpu_res = request_region(mpu_port[dev], 2, "YMFPCI MPU401")) != NULL) { 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl |= YMFPCI_LEGACY_MEN; 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl2 &= ~YMFPCI_LEGACY2_MPUIO; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mpu_port[dev] = 0; 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (mpu_res) { 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl |= YMFPCI_LEGACY_MIEN; 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl2 |= YMFPCI_LEGACY2_IMOD; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_read_config_word(pci, PCIR_DSXG_LEGACY, &old_legacy_ctrl); 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(pci, PCIR_DSXG_ELEGACY, legacy_ctrl2); 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = snd_ymfpci_create(card, pci, 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds old_legacy_ctrl, 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds &chip)) < 0) { 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(card); 267b1d5776d865951c213a1caaab5d8bf5de7615dbdTakashi Iwai release_and_free_resource(mpu_res); 268b1d5776d865951c213a1caaab5d8bf5de7615dbdTakashi Iwai release_and_free_resource(fm_res); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip->fm_res = fm_res; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip->mpu_res = mpu_res; 273ded462356886e5f80f6a20b227f7e5cf7cfc5159Takashi Iwai card->private_data = chip; 274ded462356886e5f80f6a20b227f7e5cf7cfc5159Takashi Iwai 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds strcpy(card->driver, str); 27622fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch sprintf(card->shortname, "Yamaha %s (%s)", model, str); 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sprintf(card->longname, "%s at 0x%lx, irq %i", 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds card->shortname, 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip->reg_area_phys, 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds chip->irq); 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = snd_ymfpci_pcm(chip, 0, NULL)) < 0) { 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(card); 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = snd_ymfpci_pcm_spdif(chip, 1, NULL)) < 0) { 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(card); 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = snd_ymfpci_pcm_4ch(chip, 2, NULL)) < 0) { 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(card); 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = snd_ymfpci_pcm2(chip, 3, NULL)) < 0) { 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(card); 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 297d9301263cce69ee4ef989de5bbe57515ef71a780Glen Masgai if ((err = snd_ymfpci_mixer(chip, rear_switch[dev])) < 0) { 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(card); 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = snd_ymfpci_timer(chip, 0)) < 0) { 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(card); 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip->mpu_res) { 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI, 307302e4c2f9e2b9f07c69649782330a61c60001ac4Takashi Iwai mpu_port[dev], 308302e4c2f9e2b9f07c69649782330a61c60001ac4Takashi Iwai MPU401_INFO_INTEGRATED, 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci->irq, 0, &chip->rawmidi)) < 0) { 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]); 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */ 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (chip->fm_res) { 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = snd_opl3_create(card, 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fm_port[dev], 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds fm_port[dev] + 2, 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds OPL3_HW_OPL3, 1, &opl3)) < 0) { 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "ymfpci: cannot initialize FM OPL3 at 0x%lx, skipping...\n", fm_port[dev]); 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds legacy_ctrl &= ~YMFPCI_LEGACY_FMEN; 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl); 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) { 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(card); 32599b359ba10a582148c6725f428a33ba5356dd993Takashi Iwai snd_printk(KERN_ERR "cannot create opl3 hwdep\n"); 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2); 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = snd_card_register(card)) < 0) { 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(card); 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_drvdata(pci, card); 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev++; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __devexit snd_card_ymfpci_remove(struct pci_dev *pci) 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds snd_card_free(pci_get_drvdata(pci)); 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_set_drvdata(pci, NULL); 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_driver driver = { 34822fb2a708d2f390808f20609213fd6a588bf7612Clemens Ladisch .name = "Yamaha DS-1 PCI", 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = snd_ymfpci_ids, 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = snd_card_ymfpci_probe, 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .remove = __devexit_p(snd_card_ymfpci_remove), 352ded462356886e5f80f6a20b227f7e5cf7cfc5159Takashi Iwai#ifdef CONFIG_PM 353ded462356886e5f80f6a20b227f7e5cf7cfc5159Takashi Iwai .suspend = snd_ymfpci_suspend, 354ded462356886e5f80f6a20b227f7e5cf7cfc5159Takashi Iwai .resume = snd_ymfpci_resume, 355ded462356886e5f80f6a20b227f7e5cf7cfc5159Takashi Iwai#endif 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init alsa_card_ymfpci_init(void) 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 36001d25d460a3b28aab537fab9a0038d1b5832ce28Takashi Iwai return pci_register_driver(&driver); 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit alsa_card_ymfpci_exit(void) 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds pci_unregister_driver(&driver); 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(alsa_card_ymfpci_init) 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(alsa_card_ymfpci_exit) 370