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 arbitary 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;
 381
 382        if (emu->dram_checked)
 383                return;
 384
 385        size = 0;
 386
 387        /* write out a magic number */
 388        snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);
 389        snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ);
 390        EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET);
 391        EMU8000_SMLD_WRITE(emu, UNIQUE_ID1);
 392        snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */
 393
 394        while (size < EMU8000_MAX_DRAM) {
 395
 396                size += 512 * 1024;  /* increment 512kbytes */
 397
 398                /* Write a unique data on the test address.
 399                 * if the address is out of range, the data is written on
 400                 * 0x200000(=EMU8000_DRAM_OFFSET).  Then the id word is
 401                 * changed by this data.
 402                 */
 403                /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/
 404                EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
 405                EMU8000_SMLD_WRITE(emu, UNIQUE_ID2);
 406                snd_emu8000_write_wait(emu);
 407
 408                /*
 409                 * read the data on the just written DRAM address
 410                 * if not the same then we have reached the end of ram.
 411                 */
 412                /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/
 413                EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
 414                /*snd_emu8000_read_wait(emu);*/
 415                EMU8000_SMLD_READ(emu); /* discard stale data  */
 416                if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
 417                        break; /* we must have wrapped around */
 418
 419                snd_emu8000_read_wait(emu);
 420
 421                /*
 422                 * If it is the same it could be that the address just
 423                 * wraps back to the beginning; so check to see if the
 424                 * initial value has been overwritten.
 425                 */
 426                EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
 427                EMU8000_SMLD_READ(emu); /* discard stale data  */
 428                if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
 429                        break; /* we must have wrapped around */
 430                snd_emu8000_read_wait(emu);
 431        }
 432
 433        /* wait until FULL bit in SMAxW register is false */
 434        for (i = 0; i < 10000; i++) {
 435                if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0)
 436                        break;
 437                schedule_timeout_interruptible(1);
 438                if (signal_pending(current))
 439                        break;
 440        }
 441        snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE);
 442        snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE);
 443
 444        snd_printdd("EMU8000 [0x%lx]: %d Kb on-board memory detected\n",
 445                    emu->port1, size/1024);
 446
 447        emu->mem_size = size;
 448        emu->dram_checked = 1;
 449}
 450
 451
 452/*
 453 * Initiailise the FM section.  You have to do this to use sample RAM
 454 * and therefore lose 2 voices.
 455 */
 456/*exported*/ void
 457snd_emu8000_init_fm(struct snd_emu8000 *emu)
 458{
 459        unsigned long flags;
 460
 461        /* Initialize the last two channels for DRAM refresh and producing
 462           the reverb and chorus effects for Yamaha OPL-3 synthesizer */
 463
 464        /* 31: FM left channel, 0xffffe0-0xffffe8 */
 465        EMU8000_DCYSUSV_WRITE(emu, 30, 0x80);
 466        EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */
 467        EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24));
 468        EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8));
 469        EMU8000_CPF_WRITE(emu, 30, 0);
 470        EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3);
 471
 472        /* 32: FM right channel, 0xfffff0-0xfffff8 */
 473        EMU8000_DCYSUSV_WRITE(emu, 31, 0x80);
 474        EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */
 475        EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24));
 476        EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8));
 477        EMU8000_CPF_WRITE(emu, 31, 0x8000);
 478        EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3);
 479
 480        snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0);
 481
 482        spin_lock_irqsave(&emu->reg_lock, flags);
 483        while (!(inw(EMU8000_PTR(emu)) & 0x1000))
 484                ;
 485        while ((inw(EMU8000_PTR(emu)) & 0x1000))
 486                ;
 487        spin_unlock_irqrestore(&emu->reg_lock, flags);
 488        snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828);
 489        /* this is really odd part.. */
 490        outb(0x3C, EMU8000_PTR(emu));
 491        outb(0, EMU8000_DATA1(emu));
 492
 493        /* skew volume & cutoff */
 494        EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF);
 495        EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF);
 496}
 497
 498
 499/*
 500 * The main initialization routine.
 501 */
 502static void __devinit
 503snd_emu8000_init_hw(struct snd_emu8000 *emu)
 504{
 505        int i;
 506
 507        emu->last_reg = 0xffff; /* reset the last register index */
 508
 509        /* initialize hardware configuration */
 510        EMU8000_HWCF1_WRITE(emu, 0x0059);
 511        EMU8000_HWCF2_WRITE(emu, 0x0020);
 512
 513        /* disable audio; this seems to reduce a clicking noise a bit.. */
 514        EMU8000_HWCF3_WRITE(emu, 0);
 515
 516        /* initialize audio channels */
 517        init_audio(emu);
 518
 519        /* initialize DMA */
 520        init_dma(emu);
 521
 522        /* initialize init arrays */
 523        init_arrays(emu);
 524
 525        /*
 526         * Initialize the FM section of the AWE32, this is needed
 527         * for DRAM refresh as well
 528         */
 529        snd_emu8000_init_fm(emu);
 530
 531        /* terminate all voices */
 532        for (i = 0; i < EMU8000_DRAM_VOICES; i++)
 533                EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F);
 534        
 535        /* check DRAM memory size */
 536        size_dram(emu);
 537
 538        /* enable audio */
 539        EMU8000_HWCF3_WRITE(emu, 0x4);
 540
 541        /* set equzlier, chorus and reverb modes */
 542        snd_emu8000_update_equalizer(emu);
 543        snd_emu8000_update_chorus_mode(emu);
 544        snd_emu8000_update_reverb_mode(emu);
 545}
 546
 547
 548/*----------------------------------------------------------------
 549 * Bass/Treble Equalizer
 550 *----------------------------------------------------------------*/
 551
 552static unsigned short bass_parm[12][3] = {
 553        {0xD26A, 0xD36A, 0x0000}, /* -12 dB */
 554        {0xD25B, 0xD35B, 0x0000}, /*  -8 */
 555        {0xD24C, 0xD34C, 0x0000}, /*  -6 */
 556        {0xD23D, 0xD33D, 0x0000}, /*  -4 */
 557        {0xD21F, 0xD31F, 0x0000}, /*  -2 */
 558        {0xC208, 0xC308, 0x0001}, /*   0 (HW default) */
 559        {0xC219, 0xC319, 0x0001}, /*  +2 */
 560        {0xC22A, 0xC32A, 0x0001}, /*  +4 */
 561        {0xC24C, 0xC34C, 0x0001}, /*  +6 */
 562        {0xC26E, 0xC36E, 0x0001}, /*  +8 */
 563        {0xC248, 0xC384, 0x0002}, /* +10 */
 564        {0xC26A, 0xC36A, 0x0002}, /* +12 dB */
 565};
 566
 567static unsigned short treble_parm[12][9] = {
 568        {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
 569        {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 570        {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 571        {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 572        {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
 573        {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
 574        {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
 575        {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
 576        {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
 577        {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
 578        {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
 579        {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}  /* +12 dB */
 580};
 581
 582
 583/*
 584 * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
 585 */
 586/*exported*/ void
 587snd_emu8000_update_equalizer(struct snd_emu8000 *emu)
 588{
 589        unsigned short w;
 590        int bass = emu->bass_level;
 591        int treble = emu->treble_level;
 592
 593        if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
 594                return;
 595        EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]);
 596        EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]);
 597        EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]);
 598        EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]);
 599        EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]);
 600        EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]);
 601        EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]);
 602        EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]);
 603        EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]);
 604        EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]);
 605        w = bass_parm[bass][2] + treble_parm[treble][8];
 606        EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262));
 607        EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362));
 608}
 609
 610
 611/*----------------------------------------------------------------
 612 * Chorus mode control
 613 *----------------------------------------------------------------*/
 614
 615/*
 616 * chorus mode parameters
 617 */
 618#define SNDRV_EMU8000_CHORUS_1          0
 619#define SNDRV_EMU8000_CHORUS_2          1
 620#define SNDRV_EMU8000_CHORUS_3          2
 621#define SNDRV_EMU8000_CHORUS_4          3
 622#define SNDRV_EMU8000_CHORUS_FEEDBACK   4
 623#define SNDRV_EMU8000_CHORUS_FLANGER    5
 624#define SNDRV_EMU8000_CHORUS_SHORTDELAY 6
 625#define SNDRV_EMU8000_CHORUS_SHORTDELAY2        7
 626#define SNDRV_EMU8000_CHORUS_PREDEFINED 8
 627/* user can define chorus modes up to 32 */
 628#define SNDRV_EMU8000_CHORUS_NUMBERS    32
 629
 630struct soundfont_chorus_fx {
 631        unsigned short feedback;        /* feedback level (0xE600-0xE6FF) */
 632        unsigned short delay_offset;    /* delay (0-0x0DA3) [1/44100 sec] */
 633        unsigned short lfo_depth;       /* LFO depth (0xBC00-0xBCFF) */
 634        unsigned int delay;     /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
 635        unsigned int lfo_freq;          /* LFO freq LFO freq (0-0xFFFFFFFF) */
 636};
 637
 638/* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
 639static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
 640static struct soundfont_chorus_fx chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
 641        {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
 642        {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
 643        {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
 644        {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
 645        {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
 646        {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
 647        {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */
 648        {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */
 649};
 650
 651/*exported*/ int
 652snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
 653{
 654        struct soundfont_chorus_fx rec;
 655        if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) {
 656                snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode);
 657                return -EINVAL;
 658        }
 659        if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
 660                return -EFAULT;
 661        chorus_parm[mode] = rec;
 662        chorus_defined[mode] = 1;
 663        return 0;
 664}
 665
 666/*exported*/ void
 667snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu)
 668{
 669        int effect = emu->chorus_mode;
 670        if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS ||
 671            (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect]))
 672                return;
 673        EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback);
 674        EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset);
 675        EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth);
 676        EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay);
 677        EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq);
 678        EMU8000_HWCF6_WRITE(emu, 0x8000);
 679        EMU8000_HWCF7_WRITE(emu, 0x0000);
 680}
 681
 682/*----------------------------------------------------------------
 683 * Reverb mode control
 684 *----------------------------------------------------------------*/
 685
 686/*
 687 * reverb mode parameters
 688 */
 689#define SNDRV_EMU8000_REVERB_ROOM1      0
 690#define SNDRV_EMU8000_REVERB_ROOM2      1
 691#define SNDRV_EMU8000_REVERB_ROOM3      2
 692#define SNDRV_EMU8000_REVERB_HALL1      3
 693#define SNDRV_EMU8000_REVERB_HALL2      4
 694#define SNDRV_EMU8000_REVERB_PLATE      5
 695#define SNDRV_EMU8000_REVERB_DELAY      6
 696#define SNDRV_EMU8000_REVERB_PANNINGDELAY 7
 697#define SNDRV_EMU8000_REVERB_PREDEFINED 8
 698/* user can define reverb modes up to 32 */
 699#define SNDRV_EMU8000_REVERB_NUMBERS    32
 700
 701struct soundfont_reverb_fx {
 702        unsigned short parms[28];
 703};
 704
 705/* reverb mode settings; write the following 28 data of 16 bit length
 706 *   on the corresponding ports in the reverb_cmds array
 707 */
 708static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
 709static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
 710{{  /* room 1 */
 711        0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
 712        0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
 713        0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 714        0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 715}},
 716{{  /* room 2 */
 717        0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
 718        0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
 719        0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 720        0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 721}},
 722{{  /* room 3 */
 723        0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
 724        0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
 725        0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
 726        0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
 727}},
 728{{  /* hall 1 */
 729        0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
 730        0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
 731        0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
 732        0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
 733}},
 734{{  /* hall 2 */
 735        0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
 736        0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
 737        0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 738        0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 739}},
 740{{  /* plate */
 741        0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
 742        0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
 743        0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
 744        0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
 745}},
 746{{  /* delay */
 747        0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
 748        0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
 749        0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
 750        0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
 751}},
 752{{  /* panning delay */
 753        0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
 754        0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
 755        0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
 756        0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
 757}},
 758};
 759
 760enum { DATA1, DATA2 };
 761#define AWE_INIT1(c)    EMU8000_CMD(2,c), DATA1
 762#define AWE_INIT2(c)    EMU8000_CMD(2,c), DATA2
 763#define AWE_INIT3(c)    EMU8000_CMD(3,c), DATA1
 764#define AWE_INIT4(c)    EMU8000_CMD(3,c), DATA2
 765
 766static struct reverb_cmd_pair {
 767        unsigned short cmd, port;
 768} reverb_cmds[28] = {
 769  {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
 770  {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
 771  {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
 772  {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
 773  {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
 774  {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
 775  {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
 776};
 777
 778/*exported*/ int
 779snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
 780{
 781        struct soundfont_reverb_fx rec;
 782
 783        if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) {
 784                snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode);
 785                return -EINVAL;
 786        }
 787        if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
 788                return -EFAULT;
 789        reverb_parm[mode] = rec;
 790        reverb_defined[mode] = 1;
 791        return 0;
 792}
 793
 794/*exported*/ void
 795snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu)
 796{
 797        int effect = emu->reverb_mode;
 798        int i;
 799
 800        if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS ||
 801            (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect]))
 802                return;
 803        for (i = 0; i < 28; i++) {
 804                int port;
 805                if (reverb_cmds[i].port == DATA1)
 806                        port = EMU8000_DATA1(emu);
 807                else
 808                        port = EMU8000_DATA2(emu);
 809                snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]);
 810        }
 811}
 812
 813
 814/*----------------------------------------------------------------
 815 * mixer interface
 816 *----------------------------------------------------------------*/
 817
 818/*
 819 * bass/treble
 820 */
 821static int mixer_bass_treble_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 822{
 823        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 824        uinfo->count = 1;
 825        uinfo->value.integer.min = 0;
 826        uinfo->value.integer.max = 11;
 827        return 0;
 828}
 829
 830static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 831{
 832        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 833        
 834        ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level;
 835        return 0;
 836}
 837
 838static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 839{
 840        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 841        unsigned long flags;
 842        int change;
 843        unsigned short val1;
 844        
 845        val1 = ucontrol->value.integer.value[0] % 12;
 846        spin_lock_irqsave(&emu->control_lock, flags);
 847        if (kcontrol->private_value) {
 848                change = val1 != emu->treble_level;
 849                emu->treble_level = val1;
 850        } else {
 851                change = val1 != emu->bass_level;
 852                emu->bass_level = val1;
 853        }
 854        spin_unlock_irqrestore(&emu->control_lock, flags);
 855        snd_emu8000_update_equalizer(emu);
 856        return change;
 857}
 858
 859static struct snd_kcontrol_new mixer_bass_control =
 860{
 861        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 862        .name = "Synth Tone Control - Bass",
 863        .info = mixer_bass_treble_info,
 864        .get = mixer_bass_treble_get,
 865        .put = mixer_bass_treble_put,
 866        .private_value = 0,
 867};
 868
 869static struct snd_kcontrol_new mixer_treble_control =
 870{
 871        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 872        .name = "Synth Tone Control - Treble",
 873        .info = mixer_bass_treble_info,
 874        .get = mixer_bass_treble_get,
 875        .put = mixer_bass_treble_put,
 876        .private_value = 1,
 877};
 878
 879/*
 880 * chorus/reverb mode
 881 */
 882static int mixer_chorus_reverb_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 883{
 884        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 885        uinfo->count = 1;
 886        uinfo->value.integer.min = 0;
 887        uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1);
 888        return 0;
 889}
 890
 891static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 892{
 893        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 894        
 895        ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode;
 896        return 0;
 897}
 898
 899static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 900{
 901        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 902        unsigned long flags;
 903        int change;
 904        unsigned short val1;
 905        
 906        spin_lock_irqsave(&emu->control_lock, flags);
 907        if (kcontrol->private_value) {
 908                val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS;
 909                change = val1 != emu->chorus_mode;
 910                emu->chorus_mode = val1;
 911        } else {
 912                val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS;
 913                change = val1 != emu->reverb_mode;
 914                emu->reverb_mode = val1;
 915        }
 916        spin_unlock_irqrestore(&emu->control_lock, flags);
 917        if (change) {
 918                if (kcontrol->private_value)
 919                        snd_emu8000_update_chorus_mode(emu);
 920                else
 921                        snd_emu8000_update_reverb_mode(emu);
 922        }
 923        return change;
 924}
 925
 926static struct snd_kcontrol_new mixer_chorus_mode_control =
 927{
 928        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 929        .name = "Chorus Mode",
 930        .info = mixer_chorus_reverb_info,
 931        .get = mixer_chorus_reverb_get,
 932        .put = mixer_chorus_reverb_put,
 933        .private_value = 1,
 934};
 935
 936static struct snd_kcontrol_new mixer_reverb_mode_control =
 937{
 938        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 939        .name = "Reverb Mode",
 940        .info = mixer_chorus_reverb_info,
 941        .get = mixer_chorus_reverb_get,
 942        .put = mixer_chorus_reverb_put,
 943        .private_value = 0,
 944};
 945
 946/*
 947 * FM OPL3 chorus/reverb depth
 948 */
 949static int mixer_fm_depth_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
 950{
 951        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 952        uinfo->count = 1;
 953        uinfo->value.integer.min = 0;
 954        uinfo->value.integer.max = 255;
 955        return 0;
 956}
 957
 958static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 959{
 960        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 961        
 962        ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth;
 963        return 0;
 964}
 965
 966static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 967{
 968        struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
 969        unsigned long flags;
 970        int change;
 971        unsigned short val1;
 972        
 973        val1 = ucontrol->value.integer.value[0] % 256;
 974        spin_lock_irqsave(&emu->control_lock, flags);
 975        if (kcontrol->private_value) {
 976                change = val1 != emu->fm_chorus_depth;
 977                emu->fm_chorus_depth = val1;
 978        } else {
 979                change = val1 != emu->fm_reverb_depth;
 980                emu->fm_reverb_depth = val1;
 981        }
 982        spin_unlock_irqrestore(&emu->control_lock, flags);
 983        if (change)
 984                snd_emu8000_init_fm(emu);
 985        return change;
 986}
 987
 988static struct snd_kcontrol_new mixer_fm_chorus_depth_control =
 989{
 990        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 991        .name = "FM Chorus Depth",
 992        .info = mixer_fm_depth_info,
 993        .get = mixer_fm_depth_get,
 994        .put = mixer_fm_depth_put,
 995        .private_value = 1,
 996};
 997
 998static struct snd_kcontrol_new mixer_fm_reverb_depth_control =
 999{
1000        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1001        .name = "FM Reverb Depth",
1002        .info = mixer_fm_depth_info,
1003        .get = mixer_fm_depth_get,
1004        .put = mixer_fm_depth_put,
1005        .private_value = 0,
1006};
1007
1008
1009static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
1010        &mixer_bass_control,
1011        &mixer_treble_control,
1012        &mixer_chorus_mode_control,
1013        &mixer_reverb_mode_control,
1014        &mixer_fm_chorus_depth_control,
1015        &mixer_fm_reverb_depth_control,
1016};
1017
1018/*
1019 * create and attach mixer elements for WaveTable treble/bass controls
1020 */
1021static int __devinit
1022snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
1023{
1024        int i, err = 0;
1025
1026        if (snd_BUG_ON(!emu || !card))
1027                return -EINVAL;
1028
1029        spin_lock_init(&emu->control_lock);
1030
1031        memset(emu->controls, 0, sizeof(emu->controls));
1032        for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1033                if ((err = snd_ctl_add(card, emu->controls[i] = snd_ctl_new1(mixer_defs[i], emu))) < 0)
1034                        goto __error;
1035        }
1036        return 0;
1037
1038__error:
1039        for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1040                down_write(&card->controls_rwsem);
1041                if (emu->controls[i])
1042                        snd_ctl_remove(card, emu->controls[i]);
1043                up_write(&card->controls_rwsem);
1044        }
1045        return err;
1046}
1047
1048
1049/*
1050 * free resources
1051 */
1052static int snd_emu8000_free(struct snd_emu8000 *hw)
1053{
1054        release_and_free_resource(hw->res_port1);
1055        release_and_free_resource(hw->res_port2);
1056        release_and_free_resource(hw->res_port3);
1057        kfree(hw);
1058        return 0;
1059}
1060
1061/*
1062 */
1063static int snd_emu8000_dev_free(struct snd_device *device)
1064{
1065        struct snd_emu8000 *hw = device->device_data;
1066        return snd_emu8000_free(hw);
1067}
1068
1069/*
1070 * initialize and register emu8000 synth device.
1071 */
1072int __devinit
1073snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
1074                struct snd_seq_device **awe_ret)
1075{
1076        struct snd_seq_device *awe;
1077        struct snd_emu8000 *hw;
1078        int err;
1079        static struct snd_device_ops ops = {
1080                .dev_free = snd_emu8000_dev_free,
1081        };
1082
1083        if (awe_ret)
1084                *awe_ret = NULL;
1085
1086        if (seq_ports <= 0)
1087                return 0;
1088
1089        hw = kzalloc(sizeof(*hw), GFP_KERNEL);
1090        if (hw == NULL)
1091                return -ENOMEM;
1092        spin_lock_init(&hw->reg_lock);
1093        hw->index = index;
1094        hw->port1 = port;
1095        hw->port2 = port + 0x400;
1096        hw->port3 = port + 0x800;
1097        if (!(hw->res_port1 = request_region(hw->port1, 4, "Emu8000-1")) ||
1098            !(hw->res_port2 = request_region(hw->port2, 4, "Emu8000-2")) ||
1099            !(hw->res_port3 = request_region(hw->port3, 4, "Emu8000-3"))) {
1100                snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
1101                snd_emu8000_free(hw);
1102                return -EBUSY;
1103        }
1104        hw->mem_size = 0;
1105        hw->card = card;
1106        hw->seq_ports = seq_ports;
1107        hw->bass_level = 5;
1108        hw->treble_level = 9;
1109        hw->chorus_mode = 2;
1110        hw->reverb_mode = 4;
1111        hw->fm_chorus_depth = 0;
1112        hw->fm_reverb_depth = 0;
1113
1114        if (snd_emu8000_detect(hw) < 0) {
1115                snd_emu8000_free(hw);
1116                return -ENODEV;
1117        }
1118
1119        snd_emu8000_init_hw(hw);
1120        if ((err = snd_emu8000_create_mixer(card, hw)) < 0) {
1121                snd_emu8000_free(hw);
1122                return err;
1123        }
1124        
1125        if ((err = snd_device_new(card, SNDRV_DEV_CODEC, hw, &ops)) < 0) {
1126                snd_emu8000_free(hw);
1127                return err;
1128        }
1129#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
1130        if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
1131                               sizeof(struct snd_emu8000*), &awe) >= 0) {
1132                strcpy(awe->name, "EMU-8000");
1133                *(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
1134        }
1135#else
1136        awe = NULL;
1137#endif
1138        if (awe_ret)
1139                *awe_ret = awe;
1140
1141        return 0;
1142}
1143
1144
1145/*
1146 * exported stuff
1147 */
1148
1149EXPORT_SYMBOL(snd_emu8000_poke);
1150EXPORT_SYMBOL(snd_emu8000_peek);
1151EXPORT_SYMBOL(snd_emu8000_poke_dw);
1152EXPORT_SYMBOL(snd_emu8000_peek_dw);
1153EXPORT_SYMBOL(snd_emu8000_dma_chan);
1154EXPORT_SYMBOL(snd_emu8000_init_fm);
1155EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
1156EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
1157EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
1158EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
1159EXPORT_SYMBOL(snd_emu8000_update_equalizer);
1160