linux/sound/drivers/opl3/opl3_lib.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>,
   4 *                   Hannu Savolainen 1993-1996,
   5 *                   Rob Hooft
   6 *                   
   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 delay
  33         * 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 INBs
  56         * 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 port
  78         * The detection algorithm plays with the timer built in the FM chip and
  79         * 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                snd_printd("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                snd_printd("OPL3: stat2 = 0x%x\n", stat2);
 112                return -ENODEV;
 113        }
 114
 115        /* If the toplevel code knows exactly the type of chip, don't try
 116           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 set
 126                 * 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 timers
 137 */
 138
 139/*
 140 *  Timer 1 - 80us
 141 */
 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 - 320us
 178 */
 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        if ((err = snd_timer_new(opl3->card, "AdLib timer #1", &tid, &timer)) >= 0) {
 247                strcpy(timer->name, "AdLib timer #1");
 248                timer->private_data = opl3;
 249                timer->hw = snd_opl3_timer1;
 250        }
 251        opl3->timer1 = timer;
 252        return err;
 253}
 254
 255static int snd_opl3_timer2_init(struct snd_opl3 * opl3, int timer_no)
 256{
 257        struct snd_timer *timer = NULL;
 258        struct snd_timer_id tid;
 259        int err;
 260
 261        tid.dev_class = SNDRV_TIMER_CLASS_CARD;
 262        tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
 263        tid.card = opl3->card->number;
 264        tid.device = timer_no;
 265        tid.subdevice = 0;
 266        if ((err = snd_timer_new(opl3->card, "AdLib timer #2", &tid, &timer)) >= 0) {
 267                strcpy(timer->name, "AdLib timer #2");
 268                timer->private_data = opl3;
 269                timer->hw = snd_opl3_timer2;
 270        }
 271        opl3->timer2 = timer;
 272        return err;
 273}
 274
 275/*
 276
 277 */
 278
 279void snd_opl3_interrupt(struct snd_hwdep * hw)
 280{
 281        unsigned char status;
 282        struct snd_opl3 *opl3;
 283        struct snd_timer *timer;
 284
 285        if (hw == NULL)
 286                return;
 287
 288        opl3 = hw->private_data;
 289        status = inb(opl3->l_port);
 290#if 0
 291        snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status);
 292#endif
 293        if (!(status & 0x80))
 294                return;
 295
 296        if (status & 0x40) {
 297                timer = opl3->timer1;
 298                snd_timer_interrupt(timer, timer->sticks);
 299        }
 300        if (status & 0x20) {
 301                timer = opl3->timer2;
 302                snd_timer_interrupt(timer, timer->sticks);
 303        }
 304}
 305
 306EXPORT_SYMBOL(snd_opl3_interrupt);
 307
 308/*
 309
 310 */
 311
 312static int snd_opl3_free(struct snd_opl3 *opl3)
 313{
 314        if (snd_BUG_ON(!opl3))
 315                return -ENXIO;
 316        if (opl3->private_free)
 317                opl3->private_free(opl3);
 318        snd_opl3_clear_patches(opl3);
 319        release_and_free_resource(opl3->res_l_port);
 320        release_and_free_resource(opl3->res_r_port);
 321        kfree(opl3);
 322        return 0;
 323}
 324
 325static int snd_opl3_dev_free(struct snd_device *device)
 326{
 327        struct snd_opl3 *opl3 = device->device_data;
 328        return snd_opl3_free(opl3);
 329}
 330
 331int snd_opl3_new(struct snd_card *card,
 332                 unsigned short hardware,
 333                 struct snd_opl3 **ropl3)
 334{
 335        static const struct snd_device_ops ops = {
 336                .dev_free = snd_opl3_dev_free,
 337        };
 338        struct snd_opl3 *opl3;
 339        int err;
 340
 341        *ropl3 = NULL;
 342        opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL);
 343        if (!opl3)
 344                return -ENOMEM;
 345
 346        opl3->card = card;
 347        opl3->hardware = hardware;
 348        spin_lock_init(&opl3->reg_lock);
 349        spin_lock_init(&opl3->timer_lock);
 350
 351        if ((err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops)) < 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                printk(KERN_ERR "snd_opl3_init: command not defined!\n");
 366                return -EINVAL;
 367        }
 368
 369        opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
 370        /* Melodic mode */
 371        opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00);
 372
 373        switch (opl3->hardware & OPL3_HW_MASK) {
 374        case OPL3_HW_OPL2:
 375                opl3->max_voices = MAX_OPL2_VOICES;
 376                break;
 377        case OPL3_HW_OPL3:
 378        case OPL3_HW_OPL4:
 379                opl3->max_voices = MAX_OPL3_VOICES;
 380                /* Enter OPL3 mode */
 381                opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE);
 382        }
 383        return 0;
 384}
 385
 386EXPORT_SYMBOL(snd_opl3_init);
 387
 388int snd_opl3_create(struct snd_card *card,
 389                    unsigned long l_port,
 390                    unsigned long r_port,
 391                    unsigned short hardware,
 392                    int integrated,
 393                    struct snd_opl3 ** ropl3)
 394{
 395        struct snd_opl3 *opl3;
 396        int err;
 397
 398        *ropl3 = NULL;
 399        if ((err = snd_opl3_new(card, hardware, &opl3)) < 0)
 400                return err;
 401        if (! integrated) {
 402                if ((opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)")) == NULL) {
 403                        snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port);
 404                        snd_device_free(card, opl3);
 405                        return -EBUSY;
 406                }
 407                if (r_port != 0 &&
 408                    (opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)")) == NULL) {
 409                        snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
 410                        snd_device_free(card, opl3);
 411                        return -EBUSY;
 412                }
 413        }
 414        opl3->l_port = l_port;
 415        opl3->r_port = r_port;
 416
 417        switch (opl3->hardware) {
 418        /* some hardware doesn't support timers */
 419        case OPL3_HW_OPL3_SV:
 420        case OPL3_HW_OPL3_CS:
 421        case OPL3_HW_OPL3_FM801:
 422                opl3->command = &snd_opl3_command;
 423                break;
 424        default:
 425                opl3->command = &snd_opl2_command;
 426                if ((err = snd_opl3_detect(opl3)) < 0) {
 427                        snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n",
 428                                   opl3->l_port, opl3->r_port);
 429                        snd_device_free(card, opl3);
 430                        return err;
 431                }
 432                /* detect routine returns correct hardware type */
 433                switch (opl3->hardware & OPL3_HW_MASK) {
 434                case OPL3_HW_OPL3:
 435                case OPL3_HW_OPL4:
 436                        opl3->command = &snd_opl3_command;
 437                }
 438        }
 439
 440        snd_opl3_init(opl3);
 441
 442        *ropl3 = opl3;
 443        return 0;
 444}
 445
 446EXPORT_SYMBOL(snd_opl3_create);
 447
 448int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
 449{
 450        int err;
 451
 452        if (timer1_dev >= 0)
 453                if ((err = snd_opl3_timer1_init(opl3, timer1_dev)) < 0)
 454                        return err;
 455        if (timer2_dev >= 0) {
 456                if ((err = snd_opl3_timer2_init(opl3, timer2_dev)) < 0) {
 457                        snd_device_free(opl3->card, opl3->timer1);
 458                        opl3->timer1 = NULL;
 459                        return err;
 460                }
 461        }
 462        return 0;
 463}
 464
 465EXPORT_SYMBOL(snd_opl3_timer_new);
 466
 467int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
 468                       int device, int seq_device,
 469                       struct snd_hwdep ** rhwdep)
 470{
 471        struct snd_hwdep *hw;
 472        struct snd_card *card = opl3->card;
 473        int err;
 474
 475        if (rhwdep)
 476                *rhwdep = NULL;
 477
 478        /* create hardware dependent device (direct FM) */
 479
 480        if ((err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw)) < 0) {
 481                snd_device_free(card, opl3);
 482                return err;
 483        }
 484        hw->private_data = opl3;
 485        hw->exclusive = 1;
 486#ifdef CONFIG_SND_OSSEMUL
 487        if (device == 0)
 488                hw->oss_type = SNDRV_OSS_DEVICE_TYPE_DMFM;
 489#endif
 490        strcpy(hw->name, hw->id);
 491        switch (opl3->hardware & OPL3_HW_MASK) {
 492        case OPL3_HW_OPL2:
 493                strcpy(hw->name, "OPL2 FM");
 494                hw->iface = SNDRV_HWDEP_IFACE_OPL2;
 495                break;
 496        case OPL3_HW_OPL3:
 497                strcpy(hw->name, "OPL3 FM");
 498                hw->iface = SNDRV_HWDEP_IFACE_OPL3;
 499                break;
 500        case OPL3_HW_OPL4:
 501                strcpy(hw->name, "OPL4 FM");
 502                hw->iface = SNDRV_HWDEP_IFACE_OPL4;
 503                break;
 504        }
 505
 506        /* operators - only ioctl */
 507        hw->ops.open = snd_opl3_open;
 508        hw->ops.ioctl = snd_opl3_ioctl;
 509        hw->ops.write = snd_opl3_write;
 510        hw->ops.release = snd_opl3_release;
 511
 512        opl3->hwdep = hw;
 513        opl3->seq_dev_num = seq_device;
 514#if IS_ENABLED(CONFIG_SND_SEQUENCER)
 515        if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,
 516                               sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) {
 517                strcpy(opl3->seq_dev->name, hw->name);
 518                *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3;
 519        }
 520#endif
 521        if (rhwdep)
 522                *rhwdep = hw;
 523        return 0;
 524}
 525
 526EXPORT_SYMBOL(snd_opl3_hwdep_new);
 527