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