linux/sound/isa/sb/emu8000.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   4 *     and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
   5 *  Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
   6 *
   7 *  Routines for control of EMU8000 chip
   8 */
   9
  10#include <linux/wait.h>
  11#include <linux/sched/signal.h>
  12#include <linux/slab.h>
  13#include <linux/ioport.h>
  14#include <linux/export.h>
  15#include <linux/delay.h>
  16#include <linux/io.h>
  17#include <sound/core.h>
  18#include <sound/emu8000.h>
  19#include <sound/emu8000_reg.h>
  20#include <linux/uaccess.h>
  21#include <linux/init.h>
  22#include <sound/control.h>
  23#include <sound/initval.h>
  24
  25/*
  26 * emu8000 register controls
  27 */
  28
  29/*
  30 * The following routines read and write registers on the emu8000.  They
  31 * should always be called via the EMU8000*READ/WRITE macros and never
  32 * directly.  The macros handle the port number and command word.
  33 */
  34/* Write a word */
  35void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
  36{
  37        unsigned long flags;
  38        spin_lock_irqsave(&emu->reg_lock, flags);
  39        if (reg != emu->last_reg) {
  40                outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
  41                emu->last_reg = reg;
  42        }
  43        outw((unsigned short)val, port); /* Send data */
  44        spin_unlock_irqrestore(&emu->reg_lock, flags);
  45}
  46
  47/* Read a word */
  48unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
  49{
  50        unsigned short res;
  51        unsigned long flags;
  52        spin_lock_irqsave(&emu->reg_lock, flags);
  53        if (reg != emu->last_reg) {
  54                outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
  55                emu->last_reg = reg;
  56        }
  57        res = inw(port);        /* Read data */
  58        spin_unlock_irqrestore(&emu->reg_lock, flags);
  59        return res;
  60}
  61
  62/* Write a double word */
  63void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
  64{
  65        unsigned long flags;
  66        spin_lock_irqsave(&emu->reg_lock, flags);
  67        if (reg != emu->last_reg) {
  68                outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
  69                emu->last_reg = reg;
  70        }
  71        outw((unsigned short)val, port); /* Send low word of data */
  72        outw((unsigned short)(val>>16), port+2); /* Send high word of data */
  73        spin_unlock_irqrestore(&emu->reg_lock, flags);
  74}
  75
  76/* Read a double word */
  77unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
  78{
  79        unsigned short low;
  80        unsigned int res;
  81        unsigned long flags;
  82        spin_lock_irqsave(&emu->reg_lock, flags);
  83        if (reg != emu->last_reg) {
  84                outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
  85                emu->last_reg = reg;
  86        }
  87        low = inw(port);        /* Read low word of data */
  88        res = low + (inw(port+2) << 16);
  89        spin_unlock_irqrestore(&emu->reg_lock, flags);
  90        return res;
  91}
  92
  93/*
  94 * Set up / close a channel to be used for DMA.
  95 */
  96/*exported*/ void
  97snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
  98{
  99        unsigned right_bit = (mode & EMU8000_RAM_RIGHT) ? 0x01000000 : 0;
 100        mode &= EMU8000_RAM_MODE_MASK;
 101        if (mode == EMU8000_RAM_CLOSE) {
 102                EMU8000_CCCA_WRITE(emu, ch, 0);
 103                EMU8000_DCYSUSV_WRITE(emu, ch, 0x807F);
 104                return;
 105        }
 106        EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
 107        EMU8000_VTFT_WRITE(emu, ch, 0);
 108        EMU8000_CVCF_WRITE(emu, ch, 0);
 109        EMU8000_PTRX_WRITE(emu, ch, 0x40000000);
 110        EMU8000_CPF_WRITE(emu, ch, 0x40000000);
 111        EMU8000_PSST_WRITE(emu, ch, 0);
 112        EMU8000_CSL_WRITE(emu, ch, 0);
 113        if (mode == EMU8000_RAM_WRITE) /* DMA write */
 114                EMU8000_CCCA_WRITE(emu, ch, 0x06000000 | right_bit);
 115        else       /* DMA read */
 116                EMU8000_CCCA_WRITE(emu, ch, 0x04000000 | right_bit);
 117}
 118
 119/*
 120 */
 121static void
 122snd_emu8000_read_wait(struct snd_emu8000 *emu)
 123{
 124        while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
 125                schedule_timeout_interruptible(1);
 126                if (signal_pending(current))
 127                        break;
 128        }
 129}
 130
 131/*
 132 */
 133static void
 134snd_emu8000_write_wait(struct snd_emu8000 *emu)
 135{
 136        while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
 137                schedule_timeout_interruptible(1);
 138                if (signal_pending(current))
 139                        break;
 140        }
 141}
 142
 143/*
 144 * detect a card at the given port
 145 */
 146static int
 147snd_emu8000_detect(struct snd_emu8000 *emu)
 148{
 149        /* Initialise */
 150        EMU8000_HWCF1_WRITE(emu, 0x0059);
 151        EMU8000_HWCF2_WRITE(emu, 0x0020);
 152        EMU8000_HWCF3_WRITE(emu, 0x0000);
 153        /* Check for a recognisable emu8000 */
 154        /*
 155        if ((EMU8000_U1_READ(emu) & 0x000f) != 0x000c)
 156                return -ENODEV;
 157                */
 158        if ((EMU8000_HWCF1_READ(emu) & 0x007e) != 0x0058)
 159                return -ENODEV;
 160        if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003)
 161                return -ENODEV;
 162
 163        snd_printdd("EMU8000 [0x%lx]: Synth chip found\n",
 164                    emu->port1);
 165        return 0;
 166}
 167
 168
 169/*
 170 * intiailize audio channels
 171 */
 172static void
 173init_audio(struct snd_emu8000 *emu)
 174{
 175        int ch;
 176
 177        /* turn off envelope engines */
 178        for (ch = 0; ch < EMU8000_CHANNELS; ch++)
 179                EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
 180  
 181        /* reset all other parameters to zero */
 182        for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
 183                EMU8000_ENVVOL_WRITE(emu, ch, 0);
 184                EMU8000_ENVVAL_WRITE(emu, ch, 0);
 185                EMU8000_DCYSUS_WRITE(emu, ch, 0);
 186                EMU8000_ATKHLDV_WRITE(emu, ch, 0);
 187                EMU8000_LFO1VAL_WRITE(emu, ch, 0);
 188                EMU8000_ATKHLD_WRITE(emu, ch, 0);
 189                EMU8000_LFO2VAL_WRITE(emu, ch, 0);
 190                EMU8000_IP_WRITE(emu, ch, 0);
 191                EMU8000_IFATN_WRITE(emu, ch, 0);
 192                EMU8000_PEFE_WRITE(emu, ch, 0);
 193                EMU8000_FMMOD_WRITE(emu, ch, 0);
 194                EMU8000_TREMFRQ_WRITE(emu, ch, 0);
 195                EMU8000_FM2FRQ2_WRITE(emu, ch, 0);
 196                EMU8000_PTRX_WRITE(emu, ch, 0);
 197                EMU8000_VTFT_WRITE(emu, ch, 0);
 198                EMU8000_PSST_WRITE(emu, ch, 0);
 199                EMU8000_CSL_WRITE(emu, ch, 0);
 200                EMU8000_CCCA_WRITE(emu, ch, 0);
 201        }
 202
 203        for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
 204                EMU8000_CPF_WRITE(emu, ch, 0);
 205                EMU8000_CVCF_WRITE(emu, ch, 0);
 206        }
 207}
 208
 209
 210/*
 211 * initialize DMA address
 212 */
 213static void
 214init_dma(struct snd_emu8000 *emu)
 215{
 216        EMU8000_SMALR_WRITE(emu, 0);
 217        EMU8000_SMARR_WRITE(emu, 0);
 218        EMU8000_SMALW_WRITE(emu, 0);
 219        EMU8000_SMARW_WRITE(emu, 0);
 220}
 221
 222/*
 223 * initialization arrays; from ADIP
 224 */
 225static unsigned short init1[128] = {
 226        0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
 227        0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
 228        0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
 229        0x33ff, 0x0c30,  0x37ff, 0x0d30, 0x3bff, 0x0e30,  0x3fff, 0x0f30,
 230
 231        0x43ff, 0x0030,  0x47ff, 0x0130, 0x4bff, 0x0230,  0x4fff, 0x0330,
 232        0x53ff, 0x0430,  0x57ff, 0x0530, 0x5bff, 0x0630,  0x5fff, 0x0730,
 233        0x63ff, 0x0830,  0x67ff, 0x0930, 0x6bff, 0x0a30,  0x6fff, 0x0b30,
 234        0x73ff, 0x0c30,  0x77ff, 0x0d30, 0x7bff, 0x0e30,  0x7fff, 0x0f30,
 235
 236        0x83ff, 0x0030,  0x87ff, 0x0130, 0x8bff, 0x0230,  0x8fff, 0x0330,
 237        0x93ff, 0x0430,  0x97ff, 0x0530, 0x9bff, 0x0630,  0x9fff, 0x0730,
 238        0xa3ff, 0x0830,  0xa7ff, 0x0930, 0xabff, 0x0a30,  0xafff, 0x0b30,
 239        0xb3ff, 0x0c30,  0xb7ff, 0x0d30, 0xbbff, 0x0e30,  0xbfff, 0x0f30,
 240
 241        0xc3ff, 0x0030,  0xc7ff, 0x0130, 0xcbff, 0x0230,  0xcfff, 0x0330,
 242        0xd3ff, 0x0430,  0xd7ff, 0x0530, 0xdbff, 0x0630,  0xdfff, 0x0730,
 243        0xe3ff, 0x0830,  0xe7ff, 0x0930, 0xebff, 0x0a30,  0xefff, 0x0b30,
 244        0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
 245};
 246
 247static unsigned short init2[128] = {
 248        0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
 249        0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
 250        0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
 251        0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
 252
 253        0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
 254        0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
 255        0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
 256        0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
 257
 258        0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
 259        0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
 260        0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
 261        0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
 262
 263        0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
 264        0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
 265        0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
 266        0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
 267};
 268
 269static unsigned short init3[128] = {
 270        0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
 271        0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
 272        0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
 273        0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
 274
 275        0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
 276        0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
 277        0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
 278        0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
 279
 280        0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
 281        0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
 282        0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
 283        0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
 284
 285        0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
 286        0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
 287        0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
 288        0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
 289};
 290
 291static unsigned short init4[128] = {
 292        0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
 293        0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
 294        0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
 295        0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
 296
 297        0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
 298        0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
 299        0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
 300        0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
 301
 302        0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
 303        0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
 304        0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
 305        0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
 306
 307        0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
 308        0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
 309        0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
 310        0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
 311};
 312
 313/* send an initialization array
 314 * Taken from the oss driver, not obvious from the doc how this
 315 * is meant to work
 316 */
 317static void
 318send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
 319{
 320        int i;
 321        unsigned short *p;
 322
 323        p = data;
 324        for (i = 0; i < size; i++, p++)
 325                EMU8000_INIT1_WRITE(emu, i, *p);
 326        for (i = 0; i < size; i++, p++)
 327                EMU8000_INIT2_WRITE(emu, i, *p);
 328        for (i = 0; i < size; i++, p++)
 329                EMU8000_INIT3_WRITE(emu, i, *p);
 330        for (i = 0; i < size; i++, p++)
 331                EMU8000_INIT4_WRITE(emu, i, *p);
 332}
 333
 334
 335/*
 336 * Send initialization arrays to start up, this just follows the
 337 * initialisation sequence in the adip.
 338 */
 339static void
 340init_arrays(struct snd_emu8000 *emu)
 341{
 342        send_array(emu, init1, ARRAY_SIZE(init1)/4);
 343
 344        msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */
 345        send_array(emu, init2, ARRAY_SIZE(init2)/4);
 346        send_array(emu, init3, ARRAY_SIZE(init3)/4);
 347
 348        EMU8000_HWCF4_WRITE(emu, 0);
 349        EMU8000_HWCF5_WRITE(emu, 0x83);
 350        EMU8000_HWCF6_WRITE(emu, 0x8000);
 351
 352        send_array(emu, init4, ARRAY_SIZE(init4)/4);
 353}
 354
 355
 356#define UNIQUE_ID1      0xa5b9
 357#define UNIQUE_ID2      0x9d53
 358
 359/*
 360 * Size the onboard memory.
 361 * This is written so as not to need arbitrary delays after the write. It
 362 * seems that the only way to do this is to use the one channel and keep
 363 * reallocating between read and write.
 364 */
 365static void
 366size_dram(struct snd_emu8000 *emu)
 367{
 368        int i, size;
 369
 370        if (emu->dram_checked)
 371                return;
 372
 373        size = 0;
 374
 375        /* write out a magic number */
 376        snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);
 377        snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ);
 378        EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET);
 379        EMU8000_SMLD_WRITE(emu, UNIQUE_ID1);
 380        snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */
 381        snd_emu8000_write_wait(emu);
 382
 383        /*
 384         * Detect first 512 KiB.  If a write succeeds at the beginning of a
 385         * 512 KiB page we assume that the whole page is there.
 386         */
 387        EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
 388        EMU8000_SMLD_READ(emu); /* discard stale data  */
 389        if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
 390                goto skip_detect;   /* No RAM */
 391        snd_emu8000_read_wait(emu);
 392
 393        for (size = 512 * 1024; size < EMU8000_MAX_DRAM; size += 512 * 1024) {
 394
 395                /* Write a unique data on the test address.
 396                 * if the address is out of range, the data is written on
 397                 * 0x200000(=EMU8000_DRAM_OFFSET).  Then the id word is
 398                 * changed by this data.
 399                 */
 400                /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/
 401                EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
 402                EMU8000_SMLD_WRITE(emu, UNIQUE_ID2);
 403                snd_emu8000_write_wait(emu);
 404
 405                /*
 406                 * read the data on the just written DRAM address
 407                 * if not the same then we have reached the end of ram.
 408                 */
 409                /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/
 410                EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
 411                /*snd_emu8000_read_wait(emu);*/
 412                EMU8000_SMLD_READ(emu); /* discard stale data  */
 413                if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
 414                        break; /* no memory at this address */
 415                snd_emu8000_read_wait(emu);
 416
 417                /*
 418                 * If it is the same it could be that the address just
 419                 * wraps back to the beginning; so check to see if the
 420                 * initial value has been overwritten.
 421                 */
 422                EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
 423                EMU8000_SMLD_READ(emu); /* discard stale data  */
 424                if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
 425                        break; /* we must have wrapped around */
 426                snd_emu8000_read_wait(emu);
 427
 428                /* Otherwise, it's valid memory. */
 429        }
 430
 431skip_detect:
 432        /* wait until FULL bit in SMAxW register is false */
 433        for (i = 0; i < 10000; i++) {
 434                if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0)
 435                        break;
 436                schedule_timeout_interruptible(1);
 437                if (signal_pending(current))
 438                        break;
 439        }
 440        snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE);
 441        snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE);
 442
 443        pr_info("EMU8000 [0x%lx]: %d KiB on-board DRAM detected\n",
 444                    emu->port1, size/1024);
 445
 446        emu->mem_size = size;
 447        emu->dram_checked = 1;
 448}
 449
 450
 451/*
 452 * Initiailise the FM section.  You have to do this to use sample RAM
 453 * and therefore lose 2 voices.
 454 */
 455/*exported*/ void
 456snd_emu8000_init_fm(struct snd_emu8000 *emu)
 457{
 458        unsigned long flags;
 459
 460        /* Initialize the last two channels for DRAM refresh and producing
 461           the reverb and chorus effects for Yamaha OPL-3 synthesizer */
 462
 463        /* 31: FM left channel, 0xffffe0-0xffffe8 */
 464        EMU8000_DCYSUSV_WRITE(emu, 30, 0x80);
 465        EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */
 466        EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24));
 467        EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8));
 468        EMU8000_CPF_WRITE(emu, 30, 0);
 469        EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3);
 470
 471        /* 32: FM right channel, 0xfffff0-0xfffff8 */
 472        EMU8000_DCYSUSV_WRITE(emu, 31, 0x80);
 473        EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */
 474        EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24));
 475        EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8));
 476        EMU8000_CPF_WRITE(emu, 31, 0x8000);
 477        EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3);
 478
 479        snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0);
 480
 481        spin_lock_irqsave(&emu->reg_lock, flags);
 482        while (!(inw(EMU8000_PTR(emu)) & 0x1000))
 483                ;
 484        while ((inw(EMU8000_PTR(emu)) & 0x1000))
 485                ;
 486        spin_unlock_irqrestore(&emu->reg_lock, flags);
 487        snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828);
 488        /* this is really odd part.. */
 489        outb(0x3C, EMU8000_PTR(emu));
 490        outb(0, EMU8000_DATA1(emu));
 491
 492        /* skew volume & cutoff */
 493        EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF);
 494        EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF);
 495}
 496
 497
 498/*
 499 * The main initialization routine.
 500 */
 501static void
 502snd_emu8000_init_hw(struct snd_emu8000 *emu)
 503{
 504        int i;
 505
 506        emu->last_reg = 0xffff; /* reset the last register index */
 507
 508        /* initialize hardware configuration */
 509        EMU8000_HWCF1_WRITE(emu, 0x0059);
 510        EMU8000_HWCF2_WRITE(emu, 0x0020);
 511
 512        /* disable audio; this seems to reduce a clicking noise a bit.. */
 513        EMU8000_HWCF3_WRITE(emu, 0);
 514
 515        /* initialize audio channels */
 516        init_audio(emu);
 517
 518        /* initialize DMA */
 519        init_dma(emu);
 520
 521        /* initialize init arrays */
 522        init_arrays(emu);
 523
 524        /*
 525         * Initialize the FM section of the AWE32, this is needed
 526         * for DRAM refresh as well
 527         */
 528        snd_emu8000_init_fm(emu);
 529
 530        /* terminate all voices */
 531        for (i = 0; i < EMU8000_DRAM_VOICES; i++)
 532                EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F);
 533        
 534        /* check DRAM memory size */
 535        size_dram(emu);
 536
 537        /* enable audio */
 538        EMU8000_HWCF3_WRITE(emu, 0x4);
 539
 540        /* set equzlier, chorus and reverb modes */
 541        snd_emu8000_update_equalizer(emu);
 542        snd_emu8000_update_chorus_mode(emu);
 543        snd_emu8000_update_reverb_mode(emu);
 544}
 545
 546
 547/*----------------------------------------------------------------
 548 * Bass/Treble Equalizer
 549 *----------------------------------------------------------------*/
 550
 551static unsigned short bass_parm[12][3] = {
 552        {0xD26A, 0xD36A, 0x0000}, /* -12 dB */
 553        {0xD25B, 0xD35B, 0x0000}, /*  -8 */
 554        {0xD24C, 0xD34C, 0x0000}, /*  -6 */
 555        {0xD23D, 0xD33D, 0x0000}, /*  -4 */
 556        {0xD21F, 0xD31F, 0x0000}, /*  -2 */
 557        {0xC208, 0xC308, 0x0001}, /*   0 (HW default) */
 558        {0xC219, 0xC319, 0x0001}, /*  +2 */
 559        {0xC22A, 0xC32A, 0x0001}, /*  +4 */
 560        {0xC24C, 0xC34C, 0x0001}, /*  +6 */
 561        {0xC26E, 0xC36E, 0x0001}, /*  +8 */
 562        {0xC248, 0xC384, 0x0002}, /* +10 */
 563        {0xC26A, 0xC36A, 0x0002}, /* +12 dB */
 564};
 565
 566static unsigned short treble_parm[12][9] = {
 567        {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
 568        {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 569        {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 570        {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 571        {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 572        {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
 573        {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
 574        {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
 575        {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
 576        {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
 577        {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
 578        {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}  /* +12 dB */
 579};
 580
 581
 582/*
 583 * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
 584 */
 585/*exported*/ void
 586snd_emu8000_update_equalizer(struct snd_emu8000 *emu)
 587{
 588        unsigned short w;
 589        int bass = emu->bass_level;
 590        int treble = emu->treble_level;
 591
 592        if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
 593                return;
 594        EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]);
 595        EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]);
 596        EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]);
 597        EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]);
 598        EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]);
 599        EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]);
 600        EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]);
 601        EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]);
 602        EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]);
 603        EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]);
 604        w = bass_parm[bass][2] + treble_parm[treble][8];
 605        EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262));
 606        EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362));
 607}
 608
 609
 610/*----------------------------------------------------------------
 611 * Chorus mode control
 612 *----------------------------------------------------------------*/
 613
 614/*
 615 * chorus mode parameters
 616 */
 617#define SNDRV_EMU8000_CHORUS_1          0
 618#define SNDRV_EMU8000_CHORUS_2          1
 619#define SNDRV_EMU8000_CHORUS_3          2
 620#define SNDRV_EMU8000_CHORUS_4          3
 621#define SNDRV_EMU8000_CHORUS_FEEDBACK   4
 622#define SNDRV_EMU8000_CHORUS_FLANGER    5
 623#define SNDRV_EMU8000_CHORUS_SHORTDELAY 6
 624#define SNDRV_EMU8000_CHORUS_SHORTDELAY2        7
 625#define SNDRV_EMU8000_CHORUS_PREDEFINED 8
 626/* user can define chorus modes up to 32 */
 627#define SNDRV_EMU8000_CHORUS_NUMBERS    32
 628
 629struct soundfont_chorus_fx {
 630        unsigned short feedback;        /* feedback level (0xE600-0xE6FF) */
 631        unsigned short delay_offset;    /* delay (0-0x0DA3) [1/44100 sec] */
 632        unsigned short lfo_depth;       /* LFO depth (0xBC00-0xBCFF) */
 633        unsigned int delay;     /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
 634        unsigned int lfo_freq;          /* LFO freq LFO freq (0-0xFFFFFFFF) */
 635};
 636
 637/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
 638static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
 639static struct soundfont_chorus_fx chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
 640        {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
 641        {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
 642        {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
 643        {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
 644        {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
 645        {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
 646        {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */
 647        {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */
 648};
 649
 650/*exported*/ int
 651snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
 652{
 653        struct soundfont_chorus_fx rec;
 654        if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) {
 655                snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode);
 656                return -EINVAL;
 657        }
 658        if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
 659                return -EFAULT;
 660        chorus_parm[mode] = rec;
 661        chorus_defined[mode] = 1;
 662        return 0;
 663}
 664
 665/*exported*/ void
 666snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu)
 667{
 668        int effect = emu->chorus_mode;
 669        if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS ||
 670            (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect]))
 671                return;
 672        EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback);
 673        EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset);
 674        EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth);
 675        EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay);
 676        EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq);
 677        EMU8000_HWCF6_WRITE(emu, 0x8000);
 678        EMU8000_HWCF7_WRITE(emu, 0x0000);
 679}
 680
 681/*----------------------------------------------------------------
 682 * Reverb mode control
 683 *----------------------------------------------------------------*/
 684
 685/*
 686 * reverb mode parameters
 687 */
 688#define SNDRV_EMU8000_REVERB_ROOM1      0
 689#define SNDRV_EMU8000_REVERB_ROOM2      1
 690#define SNDRV_EMU8000_REVERB_ROOM3      2
 691#define SNDRV_EMU8000_REVERB_HALL1      3
 692#define SNDRV_EMU8000_REVERB_HALL2      4
 693#define SNDRV_EMU8000_REVERB_PLATE      5
 694#define SNDRV_EMU8000_REVERB_DELAY      6
 695#define SNDRV_EMU8000_REVERB_PANNINGDELAY 7
 696#define SNDRV_EMU8000_REVERB_PREDEFINED 8
 697/* user can define reverb modes up to 32 */
 698#define SNDRV_EMU8000_REVERB_NUMBERS    32
 699
 700struct soundfont_reverb_fx {
 701        unsigned short parms[28];
 702};
 703
 704/* reverb mode settings; write the following 28 data of 16 bit length
 705 *   on the corresponding ports in the reverb_cmds array
 706 */
 707static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
 708static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
 709{{  /* room 1 */
 710        0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
 711        0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
 712        0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 713        0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 714}},
 715{{  /* room 2 */
 716        0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
 717        0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
 718        0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 719        0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 720}},
 721{{  /* room 3 */
 722        0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
 723        0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
 724        0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
 725        0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
 726}},
 727{{  /* hall 1 */
 728        0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
 729        0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
 730        0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
 731        0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
 732}},
 733{{  /* hall 2 */
 734        0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
 735        0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
 736        0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 737        0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 738}},
 739{{  /* plate */
 740        0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
 741        0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
 742        0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 743        0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 744}},
 745{{  /* delay */
 746        0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
 747        0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
 748        0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
 749        0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
 750}},
 751{{  /* panning delay */
 752        0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
 753        0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
 754        0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
 755        0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
 756}},
 757};
 758
 759enum { DATA1, DATA2 };
 760#define AWE_INIT1(c)    EMU8000_CMD(2,c), DATA1
 761#define AWE_INIT2(c)    EMU8000_CMD(2,c), DATA2
 762#define AWE_INIT3(c)    EMU8000_CMD(3,c), DATA1
 763#define AWE_INIT4(c)    EMU8000_CMD(3,c), DATA2
 764
 765static struct reverb_cmd_pair {
 766        unsigned short cmd, port;
 767} reverb_cmds[28] = {
 768  {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
 769  {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
 770  {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
 771  {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
 772  {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
 773  {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
 774  {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
 775};
 776
 777/*exported*/ int
 778snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
 779{
 780        struct soundfont_reverb_fx rec;
 781
 782        if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) {
 783                snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode);
 784                return -EINVAL;
 785        }
 786        if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
 787                return -EFAULT;
 788        reverb_parm[mode] = rec;
 789        reverb_defined[mode] = 1;
 790        return 0;
 791}
 792
 793/*exported*/ void
 794snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu)
 795{
 796        int effect = emu->reverb_mode;
 797        int i;
 798
 799        if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS ||
 800            (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect]))
 801                return;
 802        for (i = 0; i < 28; i++) {
 803                int port;
 804                if (reverb_cmds[i].port == DATA1)
 805                        port = EMU8000_DATA1(emu);
 806                else
 807                        port = EMU8000_DATA2(emu);
 808                snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]);
 809        }
 810}
 811
 812
 813/*----------------------------------------------------------------
 814 * mixer interface
 815 *----------------------------------------------------------------*/
 816
 817/*
 818 * bass/treble
 819 */
 820static int mixer_bass_treble_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 821{
 822        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 823        uinfo->count = 1;
 824        uinfo->value.integer.min = 0;
 825        uinfo->value.integer.max = 11;
 826        return 0;
 827}
 828
 829static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 830{
 831        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 832        
 833        ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level;
 834        return 0;
 835}
 836
 837static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 838{
 839        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 840        unsigned long flags;
 841        int change;
 842        unsigned short val1;
 843        
 844        val1 = ucontrol->value.integer.value[0] % 12;
 845        spin_lock_irqsave(&emu->control_lock, flags);
 846        if (kcontrol->private_value) {
 847                change = val1 != emu->treble_level;
 848                emu->treble_level = val1;
 849        } else {
 850                change = val1 != emu->bass_level;
 851                emu->bass_level = val1;
 852        }
 853        spin_unlock_irqrestore(&emu->control_lock, flags);
 854        snd_emu8000_update_equalizer(emu);
 855        return change;
 856}
 857
 858static struct snd_kcontrol_new mixer_bass_control =
 859{
 860        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 861        .name = "Synth Tone Control - Bass",
 862        .info = mixer_bass_treble_info,
 863        .get = mixer_bass_treble_get,
 864        .put = mixer_bass_treble_put,
 865        .private_value = 0,
 866};
 867
 868static struct snd_kcontrol_new mixer_treble_control =
 869{
 870        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 871        .name = "Synth Tone Control - Treble",
 872        .info = mixer_bass_treble_info,
 873        .get = mixer_bass_treble_get,
 874        .put = mixer_bass_treble_put,
 875        .private_value = 1,
 876};
 877
 878/*
 879 * chorus/reverb mode
 880 */
 881static int mixer_chorus_reverb_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 882{
 883        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 884        uinfo->count = 1;
 885        uinfo->value.integer.min = 0;
 886        uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1);
 887        return 0;
 888}
 889
 890static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 891{
 892        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 893        
 894        ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode;
 895        return 0;
 896}
 897
 898static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 899{
 900        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 901        unsigned long flags;
 902        int change;
 903        unsigned short val1;
 904        
 905        spin_lock_irqsave(&emu->control_lock, flags);
 906        if (kcontrol->private_value) {
 907                val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS;
 908                change = val1 != emu->chorus_mode;
 909                emu->chorus_mode = val1;
 910        } else {
 911                val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS;
 912                change = val1 != emu->reverb_mode;
 913                emu->reverb_mode = val1;
 914        }
 915        spin_unlock_irqrestore(&emu->control_lock, flags);
 916        if (change) {
 917                if (kcontrol->private_value)
 918                        snd_emu8000_update_chorus_mode(emu);
 919                else
 920                        snd_emu8000_update_reverb_mode(emu);
 921        }
 922        return change;
 923}
 924
 925static struct snd_kcontrol_new mixer_chorus_mode_control =
 926{
 927        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 928        .name = "Chorus Mode",
 929        .info = mixer_chorus_reverb_info,
 930        .get = mixer_chorus_reverb_get,
 931        .put = mixer_chorus_reverb_put,
 932        .private_value = 1,
 933};
 934
 935static struct snd_kcontrol_new mixer_reverb_mode_control =
 936{
 937        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 938        .name = "Reverb Mode",
 939        .info = mixer_chorus_reverb_info,
 940        .get = mixer_chorus_reverb_get,
 941        .put = mixer_chorus_reverb_put,
 942        .private_value = 0,
 943};
 944
 945/*
 946 * FM OPL3 chorus/reverb depth
 947 */
 948static int mixer_fm_depth_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 949{
 950        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 951        uinfo->count = 1;
 952        uinfo->value.integer.min = 0;
 953        uinfo->value.integer.max = 255;
 954        return 0;
 955}
 956
 957static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 958{
 959        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 960        
 961        ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth;
 962        return 0;
 963}
 964
 965static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 966{
 967        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 968        unsigned long flags;
 969        int change;
 970        unsigned short val1;
 971        
 972        val1 = ucontrol->value.integer.value[0] % 256;
 973        spin_lock_irqsave(&emu->control_lock, flags);
 974        if (kcontrol->private_value) {
 975                change = val1 != emu->fm_chorus_depth;
 976                emu->fm_chorus_depth = val1;
 977        } else {
 978                change = val1 != emu->fm_reverb_depth;
 979                emu->fm_reverb_depth = val1;
 980        }
 981        spin_unlock_irqrestore(&emu->control_lock, flags);
 982        if (change)
 983                snd_emu8000_init_fm(emu);
 984        return change;
 985}
 986
 987static struct snd_kcontrol_new mixer_fm_chorus_depth_control =
 988{
 989        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 990        .name = "FM Chorus Depth",
 991        .info = mixer_fm_depth_info,
 992        .get = mixer_fm_depth_get,
 993        .put = mixer_fm_depth_put,
 994        .private_value = 1,
 995};
 996
 997static struct snd_kcontrol_new mixer_fm_reverb_depth_control =
 998{
 999        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1000        .name = "FM Reverb Depth",
1001        .info = mixer_fm_depth_info,
1002        .get = mixer_fm_depth_get,
1003        .put = mixer_fm_depth_put,
1004        .private_value = 0,
1005};
1006
1007
1008static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
1009        &mixer_bass_control,
1010        &mixer_treble_control,
1011        &mixer_chorus_mode_control,
1012        &mixer_reverb_mode_control,
1013        &mixer_fm_chorus_depth_control,
1014        &mixer_fm_reverb_depth_control,
1015};
1016
1017/*
1018 * create and attach mixer elements for WaveTable treble/bass controls
1019 */
1020static int
1021snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
1022{
1023        int i, err = 0;
1024
1025        if (snd_BUG_ON(!emu || !card))
1026                return -EINVAL;
1027
1028        spin_lock_init(&emu->control_lock);
1029
1030        memset(emu->controls, 0, sizeof(emu->controls));
1031        for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1032                if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0)
1033                        goto __error;
1034        }
1035        return 0;
1036
1037__error:
1038        for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1039                down_write(&card->controls_rwsem);
1040                if (emu->controls[i])
1041                        snd_ctl_remove(card, emu->controls[i]);
1042                up_write(&card->controls_rwsem);
1043        }
1044        return err;
1045}
1046
1047
1048/*
1049 * free resources
1050 */
1051static int snd_emu8000_free(struct snd_emu8000 *hw)
1052{
1053        release_and_free_resource(hw->res_port1);
1054        release_and_free_resource(hw->res_port2);
1055        release_and_free_resource(hw->res_port3);
1056        kfree(hw);
1057        return 0;
1058}
1059
1060/*
1061 */
1062static int snd_emu8000_dev_free(struct snd_device *device)
1063{
1064        struct snd_emu8000 *hw = device->device_data;
1065        return snd_emu8000_free(hw);
1066}
1067
1068/*
1069 * initialize and register emu8000 synth device.
1070 */
1071int
1072snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
1073                struct snd_seq_device **awe_ret)
1074{
1075        struct snd_seq_device *awe;
1076        struct snd_emu8000 *hw;
1077        int err;
1078        static struct snd_device_ops ops = {
1079                .dev_free = snd_emu8000_dev_free,
1080        };
1081
1082        if (awe_ret)
1083                *awe_ret = NULL;
1084
1085        if (seq_ports <= 0)
1086                return 0;
1087
1088        hw = kzalloc(sizeof(*hw), GFP_KERNEL);
1089        if (hw == NULL)
1090                return -ENOMEM;
1091        spin_lock_init(&hw->reg_lock);
1092        hw->index = index;
1093        hw->port1 = port;
1094        hw->port2 = port + 0x400;
1095        hw->port3 = port + 0x800;
1096        if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) ||
1097            !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) ||
1098            !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) {
1099                snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
1100                snd_emu8000_free(hw);
1101                return -EBUSY;
1102        }
1103        hw->mem_size = 0;
1104        hw->card = card;
1105        hw->seq_ports = seq_ports;
1106        hw->bass_level = 5;
1107        hw->treble_level = 9;
1108        hw->chorus_mode = 2;
1109        hw->reverb_mode = 4;
1110        hw->fm_chorus_depth = 0;
1111        hw->fm_reverb_depth = 0;
1112
1113        if (snd_emu8000_detect(hw) < 0) {
1114                snd_emu8000_free(hw);
1115                return -ENODEV;
1116        }
1117
1118        snd_emu8000_init_hw(hw);
1119        if ((err = snd_emu8000_create_mixer(card, hw)) < 0) {
1120                snd_emu8000_free(hw);
1121                return err;
1122        }
1123        
1124        if ((err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops)) < 0) {
1125                snd_emu8000_free(hw);
1126                return err;
1127        }
1128#if IS_ENABLED(CONFIG_SND_SEQUENCER)
1129        if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
1130                               sizeof(struct snd_emu8000*), &awe) >= 0) {
1131                strcpy(awe->name, "EMU-8000");
1132                *(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
1133        }
1134#else
1135        awe = NULL;
1136#endif
1137        if (awe_ret)
1138                *awe_ret = awe;
1139
1140        return 0;
1141}
1142
1143
1144/*
1145 * exported stuff
1146 */
1147
1148EXPORT_SYMBOL(snd_emu8000_poke);
1149EXPORT_SYMBOL(snd_emu8000_peek);
1150EXPORT_SYMBOL(snd_emu8000_poke_dw);
1151EXPORT_SYMBOL(snd_emu8000_peek_dw);
1152EXPORT_SYMBOL(snd_emu8000_dma_chan);
1153EXPORT_SYMBOL(snd_emu8000_init_fm);
1154EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
1155EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
1156EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
1157EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
1158EXPORT_SYMBOL(snd_emu8000_update_equalizer);
1159