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        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 0
 293        snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status);
 294#endif
 295        if (!(status & 0x80))
 296                return;
 297
 298        if (status & 0x40) {
 299                timer = opl3->timer1;
 300                snd_timer_interrupt(timer, timer->sticks);
 301        }
 302        if (status & 0x20) {
 303                timer = opl3->timer2;
 304                snd_timer_interrupt(timer, timer->sticks);
 305        }
 306}
 307
 308EXPORT_SYMBOL(snd_opl3_interrupt);
 309
 310/*
 311
 312 */
 313
 314static int snd_opl3_free(struct snd_opl3 *opl3)
 315{
 316        if (snd_BUG_ON(!opl3))
 317                return -ENXIO;
 318        if (opl3->private_free)
 319                opl3->private_free(opl3);
 320        snd_opl3_clear_patches(opl3);
 321        release_and_free_resource(opl3->res_l_port);
 322        release_and_free_resource(opl3->res_r_port);
 323        kfree(opl3);
 324        return 0;
 325}
 326
 327static int snd_opl3_dev_free(struct snd_device *device)
 328{
 329        struct snd_opl3 *opl3 = device->device_data;
 330        return snd_opl3_free(opl3);
 331}
 332
 333int snd_opl3_new(struct snd_card *card,
 334                 unsigned short hardware,
 335                 struct snd_opl3 **ropl3)
 336{
 337        static const struct snd_device_ops ops = {
 338                .dev_free = snd_opl3_dev_free,
 339        };
 340        struct snd_opl3 *opl3;
 341        int err;
 342
 343        *ropl3 = NULL;
 344        opl3 = kzalloc(sizeof(*opl3), GFP_KERNEL);
 345        if (!opl3)
 346                return -ENOMEM;
 347
 348        opl3->card = card;
 349        opl3->hardware = hardware;
 350        spin_lock_init(&opl3->reg_lock);
 351        spin_lock_init(&opl3->timer_lock);
 352
 353        err = snd_device_new(card, SNDRV_DEV_CODEC, opl3, &ops);
 354        if (err < 0) {
 355                snd_opl3_free(opl3);
 356                return err;
 357        }
 358
 359        *ropl3 = opl3;
 360        return 0;
 361}
 362
 363EXPORT_SYMBOL(snd_opl3_new);
 364
 365int snd_opl3_init(struct snd_opl3 *opl3)
 366{
 367        if (! opl3->command) {
 368                printk(KERN_ERR "snd_opl3_init: command not defined!\n");
 369                return -EINVAL;
 370        }
 371
 372        opl3->command(opl3, OPL3_LEFT | OPL3_REG_TEST, OPL3_ENABLE_WAVE_SELECT);
 373        /* Melodic mode */
 374        opl3->command(opl3, OPL3_LEFT | OPL3_REG_PERCUSSION, 0x00);
 375
 376        switch (opl3->hardware & OPL3_HW_MASK) {
 377        case OPL3_HW_OPL2:
 378                opl3->max_voices = MAX_OPL2_VOICES;
 379                break;
 380        case OPL3_HW_OPL3:
 381        case OPL3_HW_OPL4:
 382                opl3->max_voices = MAX_OPL3_VOICES;
 383                /* Enter OPL3 mode */
 384                opl3->command(opl3, OPL3_RIGHT | OPL3_REG_MODE, OPL3_OPL3_ENABLE);
 385        }
 386        return 0;
 387}
 388
 389EXPORT_SYMBOL(snd_opl3_init);
 390
 391int snd_opl3_create(struct snd_card *card,
 392                    unsigned long l_port,
 393                    unsigned long r_port,
 394                    unsigned short hardware,
 395                    int integrated,
 396                    struct snd_opl3 ** ropl3)
 397{
 398        struct snd_opl3 *opl3;
 399        int err;
 400
 401        *ropl3 = NULL;
 402        err = snd_opl3_new(card, hardware, &opl3);
 403        if (err < 0)
 404                return err;
 405        if (! integrated) {
 406                opl3->res_l_port = request_region(l_port, 2, "OPL2/3 (left)");
 407                if (!opl3->res_l_port) {
 408                        snd_printk(KERN_ERR "opl3: can't grab left port 0x%lx\n", l_port);
 409                        snd_device_free(card, opl3);
 410                        return -EBUSY;
 411                }
 412                if (r_port != 0) {
 413                        opl3->res_r_port = request_region(r_port, 2, "OPL2/3 (right)");
 414                        if (!opl3->res_r_port) {
 415                                snd_printk(KERN_ERR "opl3: can't grab right port 0x%lx\n", r_port);
 416                                snd_device_free(card, opl3);
 417                                return -EBUSY;
 418                        }
 419                }
 420        }
 421        opl3->l_port = l_port;
 422        opl3->r_port = r_port;
 423
 424        switch (opl3->hardware) {
 425        /* some hardware doesn't support timers */
 426        case OPL3_HW_OPL3_SV:
 427        case OPL3_HW_OPL3_CS:
 428        case OPL3_HW_OPL3_FM801:
 429                opl3->command = &snd_opl3_command;
 430                break;
 431        default:
 432                opl3->command = &snd_opl2_command;
 433                err = snd_opl3_detect(opl3);
 434                if (err < 0) {
 435                        snd_printd("OPL2/3 chip not detected at 0x%lx/0x%lx\n",
 436                                   opl3->l_port, opl3->r_port);
 437                        snd_device_free(card, opl3);
 438                        return err;
 439                }
 440                /* detect routine returns correct hardware type */
 441                switch (opl3->hardware & OPL3_HW_MASK) {
 442                case OPL3_HW_OPL3:
 443                case OPL3_HW_OPL4:
 444                        opl3->command = &snd_opl3_command;
 445                }
 446        }
 447
 448        snd_opl3_init(opl3);
 449
 450        *ropl3 = opl3;
 451        return 0;
 452}
 453
 454EXPORT_SYMBOL(snd_opl3_create);
 455
 456int snd_opl3_timer_new(struct snd_opl3 * opl3, int timer1_dev, int timer2_dev)
 457{
 458        int err;
 459
 460        if (timer1_dev >= 0) {
 461                err = snd_opl3_timer1_init(opl3, timer1_dev);
 462                if (err < 0)
 463                        return err;
 464        }
 465        if (timer2_dev >= 0) {
 466                err = snd_opl3_timer2_init(opl3, timer2_dev);
 467                if (err < 0) {
 468                        snd_device_free(opl3->card, opl3->timer1);
 469                        opl3->timer1 = NULL;
 470                        return err;
 471                }
 472        }
 473        return 0;
 474}
 475
 476EXPORT_SYMBOL(snd_opl3_timer_new);
 477
 478int snd_opl3_hwdep_new(struct snd_opl3 * opl3,
 479                       int device, int seq_device,
 480                       struct snd_hwdep ** rhwdep)
 481{
 482        struct snd_hwdep *hw;
 483        struct snd_card *card = opl3->card;
 484        int err;
 485
 486        if (rhwdep)
 487                *rhwdep = NULL;
 488
 489        /* create hardware dependent device (direct FM) */
 490
 491        err = snd_hwdep_new(card, "OPL2/OPL3", device, &hw);
 492        if (err < 0) {
 493                snd_device_free(card, opl3);
 494                return err;
 495        }
 496        hw->private_data = opl3;
 497        hw->exclusive = 1;
 498#ifdef CONFIG_SND_OSSEMUL
 499        if (device == 0)
 500                hw->oss_type = SNDRV_OSS_DEVICE_TYPE_DMFM;
 501#endif
 502        strcpy(hw->name, hw->id);
 503        switch (opl3->hardware & OPL3_HW_MASK) {
 504        case OPL3_HW_OPL2:
 505                strcpy(hw->name, "OPL2 FM");
 506                hw->iface = SNDRV_HWDEP_IFACE_OPL2;
 507                break;
 508        case OPL3_HW_OPL3:
 509                strcpy(hw->name, "OPL3 FM");
 510                hw->iface = SNDRV_HWDEP_IFACE_OPL3;
 511                break;
 512        case OPL3_HW_OPL4:
 513                strcpy(hw->name, "OPL4 FM");
 514                hw->iface = SNDRV_HWDEP_IFACE_OPL4;
 515                break;
 516        }
 517
 518        /* operators - only ioctl */
 519        hw->ops.open = snd_opl3_open;
 520        hw->ops.ioctl = snd_opl3_ioctl;
 521        hw->ops.write = snd_opl3_write;
 522        hw->ops.release = snd_opl3_release;
 523
 524        opl3->hwdep = hw;
 525        opl3->seq_dev_num = seq_device;
 526#if IS_ENABLED(CONFIG_SND_SEQUENCER)
 527        if (snd_seq_device_new(card, seq_device, SNDRV_SEQ_DEV_ID_OPL3,
 528                               sizeof(struct snd_opl3 *), &opl3->seq_dev) >= 0) {
 529                strcpy(opl3->seq_dev->name, hw->name);
 530                *(struct snd_opl3 **)SNDRV_SEQ_DEVICE_ARGPTR(opl3->seq_dev) = opl3;
 531        }
 532#endif
 533        if (rhwdep)
 534                *rhwdep = hw;
 535        return 0;
 536}
 537
 538EXPORT_SYMBOL(snd_opl3_hwdep_new);
 539