537 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>,4 * Hannu Savolainen 1993-1996,5 * Rob Hooft6 * 7 * Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)8 *9 * Most if code is ported from OSS/Lite.10 */11 12#include <sound/opl3.h>13#include <linux/io.h>14#include <linux/delay.h>15#include <linux/module.h>16#include <linux/init.h>17#include <linux/slab.h>18#include <linux/ioport.h>19#include <sound/minors.h>20#include "opl3_voice.h"21 22MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Hannu Savolainen 1993-1996, Rob Hooft");23MODULE_DESCRIPTION("Routines for control of AdLib FM cards (OPL2/OPL3/OPL4 chips)");24MODULE_LICENSE("GPL");25 26static void snd_opl2_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val)27{28 unsigned long flags;29 unsigned long port;30 31 /*32 * The original 2-OP synth requires a quite long delay33 * after writing to a register.34 */35 36 port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port;37 38 spin_lock_irqsave(&opl3->reg_lock, flags);39 40 outb((unsigned char) cmd, port);41 udelay(10);42 43 outb((unsigned char) val, port + 1);44 udelay(30);45 46 spin_unlock_irqrestore(&opl3->reg_lock, flags);47}48 49static void snd_opl3_command(struct snd_opl3 * opl3, unsigned short cmd, unsigned char val)50{51 unsigned long flags;52 unsigned long port;53 54 /*55 * The OPL-3 survives with just two INBs56 * after writing to a register.57 */58 59 port = (cmd & OPL3_RIGHT) ? opl3->r_port : opl3->l_port;60 61 spin_lock_irqsave(&opl3->reg_lock, flags);62 63 outb((unsigned char) cmd, port);64 inb(opl3->l_port);65 inb(opl3->l_port);66 67 outb((unsigned char) val, port + 1);68 inb(opl3->l_port);69 inb(opl3->l_port);70 71 spin_unlock_irqrestore(&opl3->reg_lock, flags);72}73 74static int snd_opl3_detect(struct snd_opl3 * opl3)75{76 /*77 * This function returns 1 if the FM chip is present at the given I/O port78 * The detection algorithm plays with the timer built in the FM chip and79 * looks for a change in the status register.80 *81 * Note! The timers of the FM chip are not connected to AdLib (and compatible)82 * boards.83 *84 * Note2! The chip is initialized if detected.85 */86 87 unsigned char stat1, stat2, signature;88 89 /* Reset timers 1 and 2 */90 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK);91 /* Reset the IRQ of the FM chip */92 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);93 signature = stat1 = inb(opl3->l_port); /* Status register */94 if ((stat1 & 0xe0) != 0x00) { /* Should be 0x00 */95 dev_dbg(opl3->card->dev, "OPL3: stat1 = 0x%x\n", stat1);96 return -ENODEV;97 }98 /* Set timer1 to 0xff */99 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 0xff);100 /* Unmask and start timer 1 */101 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER2_MASK | OPL3_TIMER1_START);102 /* Now we have to delay at least 80us */103 udelay(200);104 /* Read status after timers have expired */105 stat2 = inb(opl3->l_port);106 /* Stop the timers */107 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_TIMER1_MASK | OPL3_TIMER2_MASK);108 /* Reset the IRQ of the FM chip */109 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, OPL3_IRQ_RESET);110 if ((stat2 & 0xe0) != 0xc0) { /* There is no YM3812 */111 dev_dbg(opl3->card->dev, "OPL3: stat2 = 0x%x\n", stat2);112 return -ENODEV;113 }114 115 /* If the toplevel code knows exactly the type of chip, don't try116 to detect it. */117 if (opl3->hardware != OPL3_HW_AUTO)118 return 0;119 120 /* There is a FM chip on this address. Detect the type (OPL2 to OPL4) */121 if (signature == 0x06) { /* OPL2 */122 opl3->hardware = OPL3_HW_OPL2;123 } else {124 /*125 * If we had an OPL4 chip, opl3->hardware would have been set126 * by the OPL4 driver; so we can assume OPL3 here.127 */128 if (snd_BUG_ON(!opl3->r_port))129 return -ENODEV;130 opl3->hardware = OPL3_HW_OPL3;131 }132 return 0;133}134 135/*136 * AdLib timers137 */138 139/*140 * Timer 1 - 80us141 */142 143static int snd_opl3_timer1_start(struct snd_timer * timer)144{145 unsigned long flags;146 unsigned char tmp;147 unsigned int ticks;148 struct snd_opl3 *opl3;149 150 opl3 = snd_timer_chip(timer);151 spin_lock_irqsave(&opl3->timer_lock, flags);152 ticks = timer->sticks;153 tmp = (opl3->timer_enable | OPL3_TIMER1_START) & ~OPL3_TIMER1_MASK;154 opl3->timer_enable = tmp;155 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER1, 256 - ticks); /* timer 1 count */156 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */157 spin_unlock_irqrestore(&opl3->timer_lock, flags);158 return 0;159}160 161static int snd_opl3_timer1_stop(struct snd_timer * timer)162{163 unsigned long flags;164 unsigned char tmp;165 struct snd_opl3 *opl3;166 167 opl3 = snd_timer_chip(timer);168 spin_lock_irqsave(&opl3->timer_lock, flags);169 tmp = (opl3->timer_enable | OPL3_TIMER1_MASK) & ~OPL3_TIMER1_START;170 opl3->timer_enable = tmp;171 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */172 spin_unlock_irqrestore(&opl3->timer_lock, flags);173 return 0;174}175 176/*177 * Timer 2 - 320us178 */179 180static int snd_opl3_timer2_start(struct snd_timer * timer)181{182 unsigned long flags;183 unsigned char tmp;184 unsigned int ticks;185 struct snd_opl3 *opl3;186 187 opl3 = snd_timer_chip(timer);188 spin_lock_irqsave(&opl3->timer_lock, flags);189 ticks = timer->sticks;190 tmp = (opl3->timer_enable | OPL3_TIMER2_START) & ~OPL3_TIMER2_MASK;191 opl3->timer_enable = tmp;192 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER2, 256 - ticks); /* timer 1 count */193 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* enable timer 1 IRQ */194 spin_unlock_irqrestore(&opl3->timer_lock, flags);195 return 0;196}197 198static int snd_opl3_timer2_stop(struct snd_timer * timer)199{200 unsigned long flags;201 unsigned char tmp;202 struct snd_opl3 *opl3;203 204 opl3 = snd_timer_chip(timer);205 spin_lock_irqsave(&opl3->timer_lock, flags);206 tmp = (opl3->timer_enable | OPL3_TIMER2_MASK) & ~OPL3_TIMER2_START;207 opl3->timer_enable = tmp;208 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TIMER_CONTROL, tmp); /* disable timer #1 */209 spin_unlock_irqrestore(&opl3->timer_lock, flags);210 return 0;211}212 213/*214 215 */216 217static const struct snd_timer_hardware snd_opl3_timer1 =218{219 .flags = SNDRV_TIMER_HW_STOP,220 .resolution = 80000,221 .ticks = 256,222 .start = snd_opl3_timer1_start,223 .stop = snd_opl3_timer1_stop,224};225 226static const struct snd_timer_hardware snd_opl3_timer2 =227{228 .flags = SNDRV_TIMER_HW_STOP,229 .resolution = 320000,230 .ticks = 256,231 .start = snd_opl3_timer2_start,232 .stop = snd_opl3_timer2_stop,233};234 235static int snd_opl3_timer1_init(struct snd_opl3 * opl3, int timer_no)236{237 struct snd_timer *timer = NULL;238 struct snd_timer_id tid;239 int err;240 241 tid.dev_class = SNDRV_TIMER_CLASS_CARD;242 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;243 tid.card = opl3->card->number;244 tid.device = timer_no;245 tid.subdevice = 0;246 err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer);247 if (err >= 0) {248 strcpy(timer->name, "AdLib timer #1");249 timer->private_data = opl3;250 timer->hw = snd_opl3_timer1;251 }252 opl3->timer1 = timer;253 return err;254}255 256static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no)257{258 struct snd_timer *timer = NULL;259 struct snd_timer_id tid;260 int err;261 262 tid.dev_class = SNDRV_TIMER_CLASS_CARD;263 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;264 tid.card = opl3->card->number;265 tid.device = timer_no;266 tid.subdevice = 0;267 err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer);268 if (err >= 0) {269 strcpy(timer->name, "AdLib timer #2");270 timer->private_data = opl3;271 timer->hw = snd_opl3_timer2;272 }273 opl3->timer2 = timer;274 return err;275}276 277/*278 279 */280 281void snd_opl3_interrupt(struct snd_hwdep * hw)282{283 unsigned char status;284 struct snd_opl3 *opl3;285 struct snd_timer *timer;286 287 if (hw == NULL)288 return;289 290 opl3 = hw->private_data;291 status = inb(opl3->l_port);292 if (!(status & 0x80))293 return;294 295 if (status & 0x40) {296 timer = opl3->timer1;297 snd_timer_interrupt(timer, timer->sticks);298 }299 if (status & 0x20) {300 timer = opl3->timer2;301 snd_timer_interrupt(timer, timer->sticks);302 }303}304 305EXPORT_SYMBOL(snd_opl3_interrupt);306 307/*308 309 */310 311static int snd_opl3_free(struct snd_opl3 *opl3)312{313 if (snd_BUG_ON(!opl3))314 return -ENXIO;315 if (opl3->private_free)316 opl3->private_free(opl3);317 snd_opl3_clear_patches(opl3);318 release_and_free_resource(opl3->res_l_port);319 release_and_free_resource(opl3->res_r_port);320 kfree(opl3);321 return 0;322}323 324static int snd_opl3_dev_free(struct snd_device *device)325{326 struct snd_opl3 *opl3 = device->device_data;327 return snd_opl3_free(opl3);328}329 330int snd_opl3_new(struct snd_card *card,331 unsigned short hardware,332 struct snd_opl3 **ropl3)333{334 static const struct snd_device_ops ops = {335 .dev_free = snd_opl3_dev_free,336 };337 struct snd_opl3 *opl3;338 int err;339 340 *ropl3 = NULL;341 opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL);342 if (!opl3)343 return -ENOMEM;344 345 opl3->card = card;346 opl3->hardware = hardware;347 spin_lock_init(&opl3->reg_lock);348 spin_lock_init(&opl3->timer_lock);349 350 err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops);351 if (err < 0) {352 snd_opl3_free(opl3);353 return err;354 }355 356 *ropl3 = opl3;357 return 0;358}359 360EXPORT_SYMBOL(snd_opl3_new);361 362int snd_opl3_init(struct snd_opl3 *opl3)363{364 if (! opl3->command) {365 dev_err(opl3->card->dev,366 "snd_opl3_init: command not defined!\n");367 return -EINVAL;368 }369 370 opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);371 /* Melodic mode */372 opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00);373 374 switch (opl3->hardware & OPL3_HW_MASK) {375 case OPL3_HW_OPL2:376 opl3->max_voices = MAX_OPL2_VOICES;377 break;378 case OPL3_HW_OPL3:379 case OPL3_HW_OPL4:380 opl3->max_voices = MAX_OPL3_VOICES;381 /* Enter OPL3 mode */382 opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE);383 }384 return 0;385}386 387EXPORT_SYMBOL(snd_opl3_init);388 389int snd_opl3_create(struct snd_card *card,390 unsigned long l_port,391 unsigned long r_port,392 unsigned short hardware,393 int integrated,394 struct snd_opl3 ** ropl3)395{396 struct snd_opl3 *opl3;397 int err;398 399 *ropl3 = NULL;400 err = snd_opl3_new(card, hardware, &opl3);401 if (err < 0)402 return err;403 if (! integrated) {404 opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)");405 if (!opl3->res_l_port) {406 dev_err(card->dev, "opl3: can't grab left port 0x%lx\n", l_port);407 snd_device_free(card, opl3);408 return -EBUSY;409 }410 if (r_port != 0) {411 opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)");412 if (!opl3->res_r_port) {413 dev_err(card->dev, "opl3: can't grab right port 0x%lx\n", r_port);414 snd_device_free(card, opl3);415 return -EBUSY;416 }417 }418 }419 opl3->l_port = l_port;420 opl3->r_port = r_port;421 422 switch (opl3->hardware) {423 /* some hardware doesn't support timers */424 case OPL3_HW_OPL3_SV:425 case OPL3_HW_OPL3_CS:426 case OPL3_HW_OPL3_FM801:427 opl3->command = &snd_opl3_command;428 break;429 default:430 opl3->command = &snd_opl2_command;431 err = snd_opl3_detect(opl3);432 if (err < 0) {433 dev_dbg(card->dev, "OPL2/3 chip not detected at 0x%lx/0x%lx\n",434 opl3->l_port, opl3->r_port);435 snd_device_free(card, opl3);436 return err;437 }438 /* detect routine returns correct hardware type */439 switch (opl3->hardware & OPL3_HW_MASK) {440 case OPL3_HW_OPL3:441 case OPL3_HW_OPL4:442 opl3->command = &snd_opl3_command;443 }444 }445 446 snd_opl3_init(opl3);447 448 *ropl3 = opl3;449 return 0;450}451 452EXPORT_SYMBOL(snd_opl3_create);453 454int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)455{456 int err;457 458 if (timer1_dev >= 0) {459 err = snd_opl3_timer1_init(opl3, timer1_dev);460 if (err < 0)461 return err;462 }463 if (timer2_dev >= 0) {464 err = snd_opl3_timer2_init(opl3, timer2_dev);465 if (err < 0) {466 snd_device_free(opl3->card, opl3->timer1);467 opl3->timer1 = NULL;468 return err;469 }470 }471 return 0;472}473 474EXPORT_SYMBOL(snd_opl3_timer_new);475 476int snd_opl3_hwdep_new(struct snd_opl3 * opl3,477 int device, int seq_device,478 struct snd_hwdep ** rhwdep)479{480 struct snd_hwdep *hw;481 struct snd_card *card = opl3->card;482 int err;483 484 if (rhwdep)485 *rhwdep = NULL;486 487 /* create hardware dependent device (direct FM) */488 489 err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw);490 if (err < 0) {491 snd_device_free(card, opl3);492 return err;493 }494 hw->private_data = opl3;495 hw->exclusive = 1;496#ifdef CONFIG_SND_OSSEMUL497 if (device == 0)498 hw->oss_type = SNDRV_OSS_DEVICE_TYPE_DMFM;499#endif500 strcpy(hw->name, hw->id);501 switch (opl3->hardware & OPL3_HW_MASK) {502 case OPL3_HW_OPL2:503 strcpy(hw->name, "OPL2 FM");504 hw->iface = SNDRV_HWDEP_IFACE_OPL2;505 break;506 case OPL3_HW_OPL3:507 strcpy(hw->name, "OPL3 FM");508 hw->iface = SNDRV_HWDEP_IFACE_OPL3;509 break;510 case OPL3_HW_OPL4:511 strcpy(hw->name, "OPL4 FM");512 hw->iface = SNDRV_HWDEP_IFACE_OPL4;513 break;514 }515 516 /* operators - only ioctl */517 hw->ops.open = snd_opl3_open;518 hw->ops.ioctl = snd_opl3_ioctl;519 hw->ops.write = snd_opl3_write;520 hw->ops.release = snd_opl3_release;521 522 opl3->hwdep = hw;523 opl3->seq_dev_num = seq_device;524#if IS_ENABLED(CONFIG_SND_SEQUENCER)525 if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,526 sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) {527 strcpy(opl3->seq_dev->name, hw->name);528 *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3;529 }530#endif531 if (rhwdep)532 *rhwdep = hw;533 return 0;534}535 536EXPORT_SYMBOL(snd_opl3_hwdep_new);537