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