Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  The driver for the Yamaha's DS1/DS1E cards
0004  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
0005  */
0006 
0007 #include <linux/init.h>
0008 #include <linux/pci.h>
0009 #include <linux/time.h>
0010 #include <linux/module.h>
0011 #include <sound/core.h>
0012 #include "ymfpci.h"
0013 #include <sound/mpu401.h>
0014 #include <sound/opl3.h>
0015 #include <sound/initval.h>
0016 
0017 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
0018 MODULE_DESCRIPTION("Yamaha DS-1 PCI");
0019 MODULE_LICENSE("GPL");
0020 
0021 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;  /* Index 0-MAX */
0022 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;   /* ID for this card */
0023 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
0024 static long fm_port[SNDRV_CARDS];
0025 static long mpu_port[SNDRV_CARDS];
0026 #ifdef SUPPORT_JOYSTICK
0027 static long joystick_port[SNDRV_CARDS];
0028 #endif
0029 static bool rear_switch[SNDRV_CARDS];
0030 
0031 module_param_array(index, int, NULL, 0444);
0032 MODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard.");
0033 module_param_array(id, charp, NULL, 0444);
0034 MODULE_PARM_DESC(id, "ID string for the Yamaha DS-1 PCI soundcard.");
0035 module_param_array(enable, bool, NULL, 0444);
0036 MODULE_PARM_DESC(enable, "Enable Yamaha DS-1 soundcard.");
0037 module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
0038 MODULE_PARM_DESC(mpu_port, "MPU-401 Port.");
0039 module_param_hw_array(fm_port, long, ioport, NULL, 0444);
0040 MODULE_PARM_DESC(fm_port, "FM OPL-3 Port.");
0041 #ifdef SUPPORT_JOYSTICK
0042 module_param_hw_array(joystick_port, long, ioport, NULL, 0444);
0043 MODULE_PARM_DESC(joystick_port, "Joystick port address");
0044 #endif
0045 module_param_array(rear_switch, bool, NULL, 0444);
0046 MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch");
0047 
0048 static const struct pci_device_id snd_ymfpci_ids[] = {
0049     { PCI_VDEVICE(YAMAHA, 0x0004), 0, },   /* YMF724 */
0050     { PCI_VDEVICE(YAMAHA, 0x000d), 0, },   /* YMF724F */
0051     { PCI_VDEVICE(YAMAHA, 0x000a), 0, },   /* YMF740 */
0052     { PCI_VDEVICE(YAMAHA, 0x000c), 0, },   /* YMF740C */
0053     { PCI_VDEVICE(YAMAHA, 0x0010), 0, },   /* YMF744 */
0054     { PCI_VDEVICE(YAMAHA, 0x0012), 0, },   /* YMF754 */
0055     { 0, }
0056 };
0057 
0058 MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids);
0059 
0060 #ifdef SUPPORT_JOYSTICK
0061 static int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev,
0062                       int legacy_ctrl, int legacy_ctrl2)
0063 {
0064     struct gameport *gp;
0065     struct resource *r = NULL;
0066     int io_port = joystick_port[dev];
0067 
0068     if (!io_port)
0069         return -ENODEV;
0070 
0071     if (chip->pci->device >= 0x0010) { /* YMF 744/754 */
0072 
0073         if (io_port == 1) {
0074             /* auto-detect */
0075             io_port = pci_resource_start(chip->pci, 2);
0076             if (!io_port)
0077                 return -ENODEV;
0078         }
0079     } else {
0080         if (io_port == 1) {
0081             /* auto-detect */
0082             for (io_port = 0x201; io_port <= 0x205; io_port++) {
0083                 if (io_port == 0x203)
0084                     continue;
0085                 r = request_region(io_port, 1, "YMFPCI gameport");
0086                 if (r)
0087                     break;
0088             }
0089             if (!r) {
0090                 dev_err(chip->card->dev,
0091                     "no gameport ports available\n");
0092                 return -EBUSY;
0093             }
0094         }
0095         switch (io_port) {
0096         case 0x201: legacy_ctrl2 |= 0 << 6; break;
0097         case 0x202: legacy_ctrl2 |= 1 << 6; break;
0098         case 0x204: legacy_ctrl2 |= 2 << 6; break;
0099         case 0x205: legacy_ctrl2 |= 3 << 6; break;
0100         default:
0101             dev_err(chip->card->dev,
0102                 "invalid joystick port %#x", io_port);
0103             return -EINVAL;
0104         }
0105     }
0106 
0107     if (!r) {
0108         r = devm_request_region(&chip->pci->dev, io_port, 1,
0109                     "YMFPCI gameport");
0110         if (!r) {
0111             dev_err(chip->card->dev,
0112                 "joystick port %#x is in use.\n", io_port);
0113             return -EBUSY;
0114         }
0115     }
0116 
0117     chip->gameport = gp = gameport_allocate_port();
0118     if (!gp) {
0119         dev_err(chip->card->dev,
0120             "cannot allocate memory for gameport\n");
0121         return -ENOMEM;
0122     }
0123 
0124 
0125     gameport_set_name(gp, "Yamaha YMF Gameport");
0126     gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
0127     gameport_set_dev_parent(gp, &chip->pci->dev);
0128     gp->io = io_port;
0129 
0130     if (chip->pci->device >= 0x0010) /* YMF 744/754 */
0131         pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port);
0132 
0133     pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, legacy_ctrl | YMFPCI_LEGACY_JPEN);
0134     pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
0135 
0136     gameport_register_port(chip->gameport);
0137 
0138     return 0;
0139 }
0140 
0141 void snd_ymfpci_free_gameport(struct snd_ymfpci *chip)
0142 {
0143     if (chip->gameport) {
0144         gameport_unregister_port(chip->gameport);
0145         chip->gameport = NULL;
0146     }
0147 }
0148 #else
0149 static inline int snd_ymfpci_create_gameport(struct snd_ymfpci *chip, int dev, int l, int l2) { return -ENOSYS; }
0150 void snd_ymfpci_free_gameport(struct snd_ymfpci *chip) { }
0151 #endif /* SUPPORT_JOYSTICK */
0152 
0153 static int snd_card_ymfpci_probe(struct pci_dev *pci,
0154                  const struct pci_device_id *pci_id)
0155 {
0156     static int dev;
0157     struct snd_card *card;
0158     struct resource *fm_res = NULL;
0159     struct resource *mpu_res = NULL;
0160     struct snd_ymfpci *chip;
0161     struct snd_opl3 *opl3;
0162     const char *str, *model;
0163     int err;
0164     u16 legacy_ctrl, legacy_ctrl2, old_legacy_ctrl;
0165 
0166     if (dev >= SNDRV_CARDS)
0167         return -ENODEV;
0168     if (!enable[dev]) {
0169         dev++;
0170         return -ENOENT;
0171     }
0172 
0173     err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
0174                sizeof(*chip), &card);
0175     if (err < 0)
0176         return err;
0177     chip = card->private_data;
0178 
0179     switch (pci_id->device) {
0180     case 0x0004: str = "YMF724";  model = "DS-1"; break;
0181     case 0x000d: str = "YMF724F"; model = "DS-1"; break;
0182     case 0x000a: str = "YMF740";  model = "DS-1L"; break;
0183     case 0x000c: str = "YMF740C"; model = "DS-1L"; break;
0184     case 0x0010: str = "YMF744";  model = "DS-1S"; break;
0185     case 0x0012: str = "YMF754";  model = "DS-1E"; break;
0186     default: model = str = "???"; break;
0187     }
0188 
0189     legacy_ctrl = 0;
0190     legacy_ctrl2 = 0x0800;  /* SBEN = 0, SMOD = 01, LAD = 0 */
0191 
0192     if (pci_id->device >= 0x0010) { /* YMF 744/754 */
0193         if (fm_port[dev] == 1) {
0194             /* auto-detect */
0195             fm_port[dev] = pci_resource_start(pci, 1);
0196         }
0197         if (fm_port[dev] > 0)
0198             fm_res = devm_request_region(&pci->dev, fm_port[dev],
0199                              4, "YMFPCI OPL3");
0200         if (fm_res) {
0201             legacy_ctrl |= YMFPCI_LEGACY_FMEN;
0202             pci_write_config_word(pci, PCIR_DSXG_FMBASE, fm_port[dev]);
0203         }
0204         if (mpu_port[dev] == 1) {
0205             /* auto-detect */
0206             mpu_port[dev] = pci_resource_start(pci, 1) + 0x20;
0207         }
0208         if (mpu_port[dev] > 0)
0209             mpu_res = devm_request_region(&pci->dev, mpu_port[dev],
0210                               2, "YMFPCI MPU401");
0211         if (mpu_res) {
0212             legacy_ctrl |= YMFPCI_LEGACY_MEN;
0213             pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]);
0214         }
0215     } else {
0216         switch (fm_port[dev]) {
0217         case 0x388: legacy_ctrl2 |= 0; break;
0218         case 0x398: legacy_ctrl2 |= 1; break;
0219         case 0x3a0: legacy_ctrl2 |= 2; break;
0220         case 0x3a8: legacy_ctrl2 |= 3; break;
0221         default: fm_port[dev] = 0; break;
0222         }
0223         if (fm_port[dev] > 0)
0224             fm_res = devm_request_region(&pci->dev, fm_port[dev],
0225                              4, "YMFPCI OPL3");
0226         if (fm_res) {
0227             legacy_ctrl |= YMFPCI_LEGACY_FMEN;
0228         } else {
0229             legacy_ctrl2 &= ~YMFPCI_LEGACY2_FMIO;
0230             fm_port[dev] = 0;
0231         }
0232         switch (mpu_port[dev]) {
0233         case 0x330: legacy_ctrl2 |= 0 << 4; break;
0234         case 0x300: legacy_ctrl2 |= 1 << 4; break;
0235         case 0x332: legacy_ctrl2 |= 2 << 4; break;
0236         case 0x334: legacy_ctrl2 |= 3 << 4; break;
0237         default: mpu_port[dev] = 0; break;
0238         }
0239         if (mpu_port[dev] > 0)
0240             mpu_res = devm_request_region(&pci->dev, mpu_port[dev],
0241                               2, "YMFPCI MPU401");
0242         if (mpu_res) {
0243             legacy_ctrl |= YMFPCI_LEGACY_MEN;
0244         } else {
0245             legacy_ctrl2 &= ~YMFPCI_LEGACY2_MPUIO;
0246             mpu_port[dev] = 0;
0247         }
0248     }
0249     if (mpu_res) {
0250         legacy_ctrl |= YMFPCI_LEGACY_MIEN;
0251         legacy_ctrl2 |= YMFPCI_LEGACY2_IMOD;
0252     }
0253     pci_read_config_word(pci, PCIR_DSXG_LEGACY, &old_legacy_ctrl);
0254     pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
0255     pci_write_config_word(pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
0256     err = snd_ymfpci_create(card, pci, old_legacy_ctrl);
0257     if (err  < 0)
0258         return err;
0259 
0260     strcpy(card->driver, str);
0261     sprintf(card->shortname, "Yamaha %s (%s)", model, str);
0262     sprintf(card->longname, "%s at 0x%lx, irq %i",
0263         card->shortname,
0264         chip->reg_area_phys,
0265         chip->irq);
0266     err = snd_ymfpci_pcm(chip, 0);
0267     if (err < 0)
0268         return err;
0269 
0270     err = snd_ymfpci_pcm_spdif(chip, 1);
0271     if (err < 0)
0272         return err;
0273 
0274     err = snd_ymfpci_mixer(chip, rear_switch[dev]);
0275     if (err < 0)
0276         return err;
0277 
0278     if (chip->ac97->ext_id & AC97_EI_SDAC) {
0279         err = snd_ymfpci_pcm_4ch(chip, 2);
0280         if (err < 0)
0281             return err;
0282 
0283         err = snd_ymfpci_pcm2(chip, 3);
0284         if (err < 0)
0285             return err;
0286     }
0287     err = snd_ymfpci_timer(chip, 0);
0288     if (err < 0)
0289         return err;
0290 
0291     if (mpu_res) {
0292         err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
0293                       mpu_port[dev],
0294                       MPU401_INFO_INTEGRATED |
0295                       MPU401_INFO_IRQ_HOOK,
0296                       -1, &chip->rawmidi);
0297         if (err < 0) {
0298             dev_warn(card->dev,
0299                  "cannot initialize MPU401 at 0x%lx, skipping...\n",
0300                  mpu_port[dev]);
0301             legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */
0302             pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
0303         }
0304     }
0305     if (fm_res) {
0306         err = snd_opl3_create(card,
0307                       fm_port[dev],
0308                       fm_port[dev] + 2,
0309                       OPL3_HW_OPL3, 1, &opl3);
0310         if (err < 0) {
0311             dev_warn(card->dev,
0312                  "cannot initialize FM OPL3 at 0x%lx, skipping...\n",
0313                  fm_port[dev]);
0314             legacy_ctrl &= ~YMFPCI_LEGACY_FMEN;
0315             pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
0316         } else {
0317             err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
0318             if (err < 0) {
0319                 dev_err(card->dev, "cannot create opl3 hwdep\n");
0320                 return err;
0321             }
0322         }
0323     }
0324 
0325     snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2);
0326 
0327     err = snd_card_register(card);
0328     if (err < 0)
0329         return err;
0330 
0331     pci_set_drvdata(pci, card);
0332     dev++;
0333     return 0;
0334 }
0335 
0336 static struct pci_driver ymfpci_driver = {
0337     .name = KBUILD_MODNAME,
0338     .id_table = snd_ymfpci_ids,
0339     .probe = snd_card_ymfpci_probe,
0340 #ifdef CONFIG_PM_SLEEP
0341     .driver = {
0342         .pm = &snd_ymfpci_pm,
0343     },
0344 #endif
0345 };
0346 
0347 module_pci_driver(ymfpci_driver);