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