Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
0004  *     and (c) 1999 Steve Ratcliffe <steve@parabola.demon.co.uk>
0005  *  Copyright (C) 1999-2000 Takashi Iwai <tiwai@suse.de>
0006  *
0007  *  Routines for control of EMU8000 chip
0008  */
0009 
0010 #include <linux/wait.h>
0011 #include <linux/sched/signal.h>
0012 #include <linux/slab.h>
0013 #include <linux/ioport.h>
0014 #include <linux/export.h>
0015 #include <linux/delay.h>
0016 #include <linux/io.h>
0017 #include <sound/core.h>
0018 #include <sound/emu8000.h>
0019 #include <sound/emu8000_reg.h>
0020 #include <linux/uaccess.h>
0021 #include <linux/init.h>
0022 #include <sound/control.h>
0023 #include <sound/initval.h>
0024 
0025 /*
0026  * emu8000 register controls
0027  */
0028 
0029 /*
0030  * The following routines read and write registers on the emu8000.  They
0031  * should always be called via the EMU8000*READ/WRITE macros and never
0032  * directly.  The macros handle the port number and command word.
0033  */
0034 /* Write a word */
0035 void snd_emu8000_poke(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
0036 {
0037     unsigned long flags;
0038     spin_lock_irqsave(&emu->reg_lock, flags);
0039     if (reg != emu->last_reg) {
0040         outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
0041         emu->last_reg = reg;
0042     }
0043     outw((unsigned short)val, port); /* Send data */
0044     spin_unlock_irqrestore(&emu->reg_lock, flags);
0045 }
0046 
0047 /* Read a word */
0048 unsigned short snd_emu8000_peek(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
0049 {
0050     unsigned short res;
0051     unsigned long flags;
0052     spin_lock_irqsave(&emu->reg_lock, flags);
0053     if (reg != emu->last_reg) {
0054         outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
0055         emu->last_reg = reg;
0056     }
0057     res = inw(port);    /* Read data */
0058     spin_unlock_irqrestore(&emu->reg_lock, flags);
0059     return res;
0060 }
0061 
0062 /* Write a double word */
0063 void snd_emu8000_poke_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg, unsigned int val)
0064 {
0065     unsigned long flags;
0066     spin_lock_irqsave(&emu->reg_lock, flags);
0067     if (reg != emu->last_reg) {
0068         outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
0069         emu->last_reg = reg;
0070     }
0071     outw((unsigned short)val, port); /* Send low word of data */
0072     outw((unsigned short)(val>>16), port+2); /* Send high word of data */
0073     spin_unlock_irqrestore(&emu->reg_lock, flags);
0074 }
0075 
0076 /* Read a double word */
0077 unsigned int snd_emu8000_peek_dw(struct snd_emu8000 *emu, unsigned int port, unsigned int reg)
0078 {
0079     unsigned short low;
0080     unsigned int res;
0081     unsigned long flags;
0082     spin_lock_irqsave(&emu->reg_lock, flags);
0083     if (reg != emu->last_reg) {
0084         outw((unsigned short)reg, EMU8000_PTR(emu)); /* Set register */
0085         emu->last_reg = reg;
0086     }
0087     low = inw(port);    /* Read low word of data */
0088     res = low + (inw(port+2) << 16);
0089     spin_unlock_irqrestore(&emu->reg_lock, flags);
0090     return res;
0091 }
0092 
0093 /*
0094  * Set up / close a channel to be used for DMA.
0095  */
0096 /*exported*/ void
0097 snd_emu8000_dma_chan(struct snd_emu8000 *emu, int ch, int mode)
0098 {
0099     unsigned right_bit = (mode & EMU8000_RAM_RIGHT) ? 0x01000000 : 0;
0100     mode &= EMU8000_RAM_MODE_MASK;
0101     if (mode == EMU8000_RAM_CLOSE) {
0102         EMU8000_CCCA_WRITE(emu, ch, 0);
0103         EMU8000_DCYSUSV_WRITE(emu, ch, 0x807F);
0104         return;
0105     }
0106     EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
0107     EMU8000_VTFT_WRITE(emu, ch, 0);
0108     EMU8000_CVCF_WRITE(emu, ch, 0);
0109     EMU8000_PTRX_WRITE(emu, ch, 0x40000000);
0110     EMU8000_CPF_WRITE(emu, ch, 0x40000000);
0111     EMU8000_PSST_WRITE(emu, ch, 0);
0112     EMU8000_CSL_WRITE(emu, ch, 0);
0113     if (mode == EMU8000_RAM_WRITE) /* DMA write */
0114         EMU8000_CCCA_WRITE(emu, ch, 0x06000000 | right_bit);
0115     else       /* DMA read */
0116         EMU8000_CCCA_WRITE(emu, ch, 0x04000000 | right_bit);
0117 }
0118 
0119 /*
0120  */
0121 static void
0122 snd_emu8000_read_wait(struct snd_emu8000 *emu)
0123 {
0124     while ((EMU8000_SMALR_READ(emu) & 0x80000000) != 0) {
0125         schedule_timeout_interruptible(1);
0126         if (signal_pending(current))
0127             break;
0128     }
0129 }
0130 
0131 /*
0132  */
0133 static void
0134 snd_emu8000_write_wait(struct snd_emu8000 *emu)
0135 {
0136     while ((EMU8000_SMALW_READ(emu) & 0x80000000) != 0) {
0137         schedule_timeout_interruptible(1);
0138         if (signal_pending(current))
0139             break;
0140     }
0141 }
0142 
0143 /*
0144  * detect a card at the given port
0145  */
0146 static int
0147 snd_emu8000_detect(struct snd_emu8000 *emu)
0148 {
0149     /* Initialise */
0150     EMU8000_HWCF1_WRITE(emu, 0x0059);
0151     EMU8000_HWCF2_WRITE(emu, 0x0020);
0152     EMU8000_HWCF3_WRITE(emu, 0x0000);
0153     /* Check for a recognisable emu8000 */
0154     /*
0155     if ((EMU8000_U1_READ(emu) & 0x000f) != 0x000c)
0156         return -ENODEV;
0157         */
0158     if ((EMU8000_HWCF1_READ(emu) & 0x007e) != 0x0058)
0159         return -ENODEV;
0160     if ((EMU8000_HWCF2_READ(emu) & 0x0003) != 0x0003)
0161         return -ENODEV;
0162 
0163     snd_printdd("EMU8000 [0x%lx]: Synth chip found\n",
0164                     emu->port1);
0165     return 0;
0166 }
0167 
0168 
0169 /*
0170  * intiailize audio channels
0171  */
0172 static void
0173 init_audio(struct snd_emu8000 *emu)
0174 {
0175     int ch;
0176 
0177     /* turn off envelope engines */
0178     for (ch = 0; ch < EMU8000_CHANNELS; ch++)
0179         EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
0180   
0181     /* reset all other parameters to zero */
0182     for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
0183         EMU8000_ENVVOL_WRITE(emu, ch, 0);
0184         EMU8000_ENVVAL_WRITE(emu, ch, 0);
0185         EMU8000_DCYSUS_WRITE(emu, ch, 0);
0186         EMU8000_ATKHLDV_WRITE(emu, ch, 0);
0187         EMU8000_LFO1VAL_WRITE(emu, ch, 0);
0188         EMU8000_ATKHLD_WRITE(emu, ch, 0);
0189         EMU8000_LFO2VAL_WRITE(emu, ch, 0);
0190         EMU8000_IP_WRITE(emu, ch, 0);
0191         EMU8000_IFATN_WRITE(emu, ch, 0);
0192         EMU8000_PEFE_WRITE(emu, ch, 0);
0193         EMU8000_FMMOD_WRITE(emu, ch, 0);
0194         EMU8000_TREMFRQ_WRITE(emu, ch, 0);
0195         EMU8000_FM2FRQ2_WRITE(emu, ch, 0);
0196         EMU8000_PTRX_WRITE(emu, ch, 0);
0197         EMU8000_VTFT_WRITE(emu, ch, 0);
0198         EMU8000_PSST_WRITE(emu, ch, 0);
0199         EMU8000_CSL_WRITE(emu, ch, 0);
0200         EMU8000_CCCA_WRITE(emu, ch, 0);
0201     }
0202 
0203     for (ch = 0; ch < EMU8000_CHANNELS; ch++) {
0204         EMU8000_CPF_WRITE(emu, ch, 0);
0205         EMU8000_CVCF_WRITE(emu, ch, 0);
0206     }
0207 }
0208 
0209 
0210 /*
0211  * initialize DMA address
0212  */
0213 static void
0214 init_dma(struct snd_emu8000 *emu)
0215 {
0216     EMU8000_SMALR_WRITE(emu, 0);
0217     EMU8000_SMARR_WRITE(emu, 0);
0218     EMU8000_SMALW_WRITE(emu, 0);
0219     EMU8000_SMARW_WRITE(emu, 0);
0220 }
0221 
0222 /*
0223  * initialization arrays; from ADIP
0224  */
0225 static const unsigned short init1[128] = {
0226     0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
0227     0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
0228     0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
0229     0x33ff, 0x0c30,  0x37ff, 0x0d30, 0x3bff, 0x0e30,  0x3fff, 0x0f30,
0230 
0231     0x43ff, 0x0030,  0x47ff, 0x0130, 0x4bff, 0x0230,  0x4fff, 0x0330,
0232     0x53ff, 0x0430,  0x57ff, 0x0530, 0x5bff, 0x0630,  0x5fff, 0x0730,
0233     0x63ff, 0x0830,  0x67ff, 0x0930, 0x6bff, 0x0a30,  0x6fff, 0x0b30,
0234     0x73ff, 0x0c30,  0x77ff, 0x0d30, 0x7bff, 0x0e30,  0x7fff, 0x0f30,
0235 
0236     0x83ff, 0x0030,  0x87ff, 0x0130, 0x8bff, 0x0230,  0x8fff, 0x0330,
0237     0x93ff, 0x0430,  0x97ff, 0x0530, 0x9bff, 0x0630,  0x9fff, 0x0730,
0238     0xa3ff, 0x0830,  0xa7ff, 0x0930, 0xabff, 0x0a30,  0xafff, 0x0b30,
0239     0xb3ff, 0x0c30,  0xb7ff, 0x0d30, 0xbbff, 0x0e30,  0xbfff, 0x0f30,
0240 
0241     0xc3ff, 0x0030,  0xc7ff, 0x0130, 0xcbff, 0x0230,  0xcfff, 0x0330,
0242     0xd3ff, 0x0430,  0xd7ff, 0x0530, 0xdbff, 0x0630,  0xdfff, 0x0730,
0243     0xe3ff, 0x0830,  0xe7ff, 0x0930, 0xebff, 0x0a30,  0xefff, 0x0b30,
0244     0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
0245 };
0246 
0247 static const unsigned short init2[128] = {
0248     0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
0249     0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
0250     0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
0251     0x33ff, 0x8c30, 0x37ff, 0x8d30, 0x3bff, 0x8e30, 0x3fff, 0x8f30,
0252 
0253     0x43ff, 0x8030, 0x47ff, 0x8130, 0x4bff, 0x8230, 0x4fff, 0x8330,
0254     0x53ff, 0x8430, 0x57ff, 0x8530, 0x5bff, 0x8630, 0x5fff, 0x8730,
0255     0x63ff, 0x8830, 0x67ff, 0x8930, 0x6bff, 0x8a30, 0x6fff, 0x8b30,
0256     0x73ff, 0x8c30, 0x77ff, 0x8d30, 0x7bff, 0x8e30, 0x7fff, 0x8f30,
0257 
0258     0x83ff, 0x8030, 0x87ff, 0x8130, 0x8bff, 0x8230, 0x8fff, 0x8330,
0259     0x93ff, 0x8430, 0x97ff, 0x8530, 0x9bff, 0x8630, 0x9fff, 0x8730,
0260     0xa3ff, 0x8830, 0xa7ff, 0x8930, 0xabff, 0x8a30, 0xafff, 0x8b30,
0261     0xb3ff, 0x8c30, 0xb7ff, 0x8d30, 0xbbff, 0x8e30, 0xbfff, 0x8f30,
0262 
0263     0xc3ff, 0x8030, 0xc7ff, 0x8130, 0xcbff, 0x8230, 0xcfff, 0x8330,
0264     0xd3ff, 0x8430, 0xd7ff, 0x8530, 0xdbff, 0x8630, 0xdfff, 0x8730,
0265     0xe3ff, 0x8830, 0xe7ff, 0x8930, 0xebff, 0x8a30, 0xefff, 0x8b30,
0266     0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
0267 };
0268 
0269 static const unsigned short init3[128] = {
0270     0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
0271     0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
0272     0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
0273     0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x86E7, 0x229E, 0xF224,
0274 
0275     0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x87F6, 0x2C28, 0xF254,
0276     0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x8F02, 0x1341, 0xF264,
0277     0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x8FA9, 0x3EB5, 0xF294,
0278     0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0xC4C3, 0x3EBB, 0xC5C3,
0279 
0280     0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x8671, 0x14FD, 0x8287,
0281     0x3EBC, 0xE610, 0x3EC8, 0x8C7B, 0x031A, 0x87E6, 0x3EC8, 0x86F7,
0282     0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x821F, 0x3ECA, 0x8386,
0283     0x3EC1, 0x8C03, 0x3EC9, 0x831E, 0x3ECA, 0x8C4C, 0x3EBF, 0x8C55,
0284 
0285     0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x8EAD, 0x3EC8, 0xD308,
0286     0x3EC2, 0x8F7E, 0x3ECB, 0x8219, 0x3ECB, 0xD26E, 0x3EC5, 0x831F,
0287     0x3EC6, 0xC308, 0x3EC3, 0xB2FF, 0x3EC9, 0x8265, 0x3EC9, 0x8319,
0288     0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
0289 };
0290 
0291 static const unsigned short init4[128] = {
0292     0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
0293     0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
0294     0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
0295     0x229F, 0x8429, 0x2746, 0x8529, 0x1F1C, 0x06E7, 0x229E, 0x7224,
0296 
0297     0x0DA4, 0x8429, 0x2C29, 0x8529, 0x2745, 0x07F6, 0x2C28, 0x7254,
0298     0x383B, 0x8428, 0x320F, 0x8528, 0x320E, 0x0F02, 0x1341, 0x7264,
0299     0x3EB6, 0x8428, 0x3EB9, 0x8528, 0x383A, 0x0FA9, 0x3EB5, 0x7294,
0300     0x3EB7, 0x8474, 0x3EBA, 0x8575, 0x3EB8, 0x44C3, 0x3EBB, 0x45C3,
0301 
0302     0x0000, 0xA404, 0x0001, 0xA504, 0x141F, 0x0671, 0x14FD, 0x0287,
0303     0x3EBC, 0xE610, 0x3EC8, 0x0C7B, 0x031A, 0x07E6, 0x3EC8, 0x86F7,
0304     0x3EC0, 0x821E, 0x3EBE, 0xD208, 0x3EBD, 0x021F, 0x3ECA, 0x0386,
0305     0x3EC1, 0x0C03, 0x3EC9, 0x031E, 0x3ECA, 0x8C4C, 0x3EBF, 0x0C55,
0306 
0307     0x3EC9, 0xC208, 0x3EC4, 0xBC84, 0x3EC8, 0x0EAD, 0x3EC8, 0xD308,
0308     0x3EC2, 0x8F7E, 0x3ECB, 0x0219, 0x3ECB, 0xD26E, 0x3EC5, 0x031F,
0309     0x3EC6, 0xC308, 0x3EC3, 0x32FF, 0x3EC9, 0x0265, 0x3EC9, 0x8319,
0310     0x1342, 0xD36E, 0x3EC7, 0x33FF, 0x0000, 0x8365, 0x1420, 0x9570,
0311 };
0312 
0313 /* send an initialization array
0314  * Taken from the oss driver, not obvious from the doc how this
0315  * is meant to work
0316  */
0317 static void
0318 send_array(struct snd_emu8000 *emu, const unsigned short *data, int size)
0319 {
0320     int i;
0321     const unsigned short *p;
0322 
0323     p = data;
0324     for (i = 0; i < size; i++, p++)
0325         EMU8000_INIT1_WRITE(emu, i, *p);
0326     for (i = 0; i < size; i++, p++)
0327         EMU8000_INIT2_WRITE(emu, i, *p);
0328     for (i = 0; i < size; i++, p++)
0329         EMU8000_INIT3_WRITE(emu, i, *p);
0330     for (i = 0; i < size; i++, p++)
0331         EMU8000_INIT4_WRITE(emu, i, *p);
0332 }
0333 
0334 
0335 /*
0336  * Send initialization arrays to start up, this just follows the
0337  * initialisation sequence in the adip.
0338  */
0339 static void
0340 init_arrays(struct snd_emu8000 *emu)
0341 {
0342     send_array(emu, init1, ARRAY_SIZE(init1)/4);
0343 
0344     msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */
0345     send_array(emu, init2, ARRAY_SIZE(init2)/4);
0346     send_array(emu, init3, ARRAY_SIZE(init3)/4);
0347 
0348     EMU8000_HWCF4_WRITE(emu, 0);
0349     EMU8000_HWCF5_WRITE(emu, 0x83);
0350     EMU8000_HWCF6_WRITE(emu, 0x8000);
0351 
0352     send_array(emu, init4, ARRAY_SIZE(init4)/4);
0353 }
0354 
0355 
0356 #define UNIQUE_ID1  0xa5b9
0357 #define UNIQUE_ID2  0x9d53
0358 
0359 /*
0360  * Size the onboard memory.
0361  * This is written so as not to need arbitrary delays after the write. It
0362  * seems that the only way to do this is to use the one channel and keep
0363  * reallocating between read and write.
0364  */
0365 static void
0366 size_dram(struct snd_emu8000 *emu)
0367 {
0368     int i, size;
0369 
0370     if (emu->dram_checked)
0371         return;
0372 
0373     size = 0;
0374 
0375     /* write out a magic number */
0376     snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);
0377     snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_READ);
0378     EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET);
0379     EMU8000_SMLD_WRITE(emu, UNIQUE_ID1);
0380     snd_emu8000_init_fm(emu); /* This must really be here and not 2 lines back even */
0381     snd_emu8000_write_wait(emu);
0382 
0383     /*
0384      * Detect first 512 KiB.  If a write succeeds at the beginning of a
0385      * 512 KiB page we assume that the whole page is there.
0386      */
0387     EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
0388     EMU8000_SMLD_READ(emu); /* discard stale data  */
0389     if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
0390         goto skip_detect;   /* No RAM */
0391     snd_emu8000_read_wait(emu);
0392 
0393     for (size = 512 * 1024; size < EMU8000_MAX_DRAM; size += 512 * 1024) {
0394 
0395         /* Write a unique data on the test address.
0396          * if the address is out of range, the data is written on
0397          * 0x200000(=EMU8000_DRAM_OFFSET).  Then the id word is
0398          * changed by this data.
0399          */
0400         /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_WRITE);*/
0401         EMU8000_SMALW_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
0402         EMU8000_SMLD_WRITE(emu, UNIQUE_ID2);
0403         snd_emu8000_write_wait(emu);
0404 
0405         /*
0406          * read the data on the just written DRAM address
0407          * if not the same then we have reached the end of ram.
0408          */
0409         /*snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_READ);*/
0410         EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
0411         /*snd_emu8000_read_wait(emu);*/
0412         EMU8000_SMLD_READ(emu); /* discard stale data  */
0413         if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
0414             break; /* no memory at this address */
0415         snd_emu8000_read_wait(emu);
0416 
0417         /*
0418          * If it is the same it could be that the address just
0419          * wraps back to the beginning; so check to see if the
0420          * initial value has been overwritten.
0421          */
0422         EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
0423         EMU8000_SMLD_READ(emu); /* discard stale data  */
0424         if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
0425             break; /* we must have wrapped around */
0426         snd_emu8000_read_wait(emu);
0427 
0428         /* Otherwise, it's valid memory. */
0429     }
0430 
0431 skip_detect:
0432     /* wait until FULL bit in SMAxW register is false */
0433     for (i = 0; i < 10000; i++) {
0434         if ((EMU8000_SMALW_READ(emu) & 0x80000000) == 0)
0435             break;
0436         schedule_timeout_interruptible(1);
0437         if (signal_pending(current))
0438             break;
0439     }
0440     snd_emu8000_dma_chan(emu, 0, EMU8000_RAM_CLOSE);
0441     snd_emu8000_dma_chan(emu, 1, EMU8000_RAM_CLOSE);
0442 
0443     pr_info("EMU8000 [0x%lx]: %d KiB on-board DRAM detected\n",
0444             emu->port1, size/1024);
0445 
0446     emu->mem_size = size;
0447     emu->dram_checked = 1;
0448 }
0449 
0450 
0451 /*
0452  * Initiailise the FM section.  You have to do this to use sample RAM
0453  * and therefore lose 2 voices.
0454  */
0455 /*exported*/ void
0456 snd_emu8000_init_fm(struct snd_emu8000 *emu)
0457 {
0458     unsigned long flags;
0459 
0460     /* Initialize the last two channels for DRAM refresh and producing
0461        the reverb and chorus effects for Yamaha OPL-3 synthesizer */
0462 
0463     /* 31: FM left channel, 0xffffe0-0xffffe8 */
0464     EMU8000_DCYSUSV_WRITE(emu, 30, 0x80);
0465     EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0); /* full left */
0466     EMU8000_CSL_WRITE(emu, 30, 0x00FFFFE8 | (emu->fm_chorus_depth << 24));
0467     EMU8000_PTRX_WRITE(emu, 30, (emu->fm_reverb_depth << 8));
0468     EMU8000_CPF_WRITE(emu, 30, 0);
0469     EMU8000_CCCA_WRITE(emu, 30, 0x00FFFFE3);
0470 
0471     /* 32: FM right channel, 0xfffff0-0xfffff8 */
0472     EMU8000_DCYSUSV_WRITE(emu, 31, 0x80);
0473     EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0); /* full right */
0474     EMU8000_CSL_WRITE(emu, 31, 0x00FFFFF8 | (emu->fm_chorus_depth << 24));
0475     EMU8000_PTRX_WRITE(emu, 31, (emu->fm_reverb_depth << 8));
0476     EMU8000_CPF_WRITE(emu, 31, 0x8000);
0477     EMU8000_CCCA_WRITE(emu, 31, 0x00FFFFF3);
0478 
0479     snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0);
0480 
0481     spin_lock_irqsave(&emu->reg_lock, flags);
0482     while (!(inw(EMU8000_PTR(emu)) & 0x1000))
0483         ;
0484     while ((inw(EMU8000_PTR(emu)) & 0x1000))
0485         ;
0486     spin_unlock_irqrestore(&emu->reg_lock, flags);
0487     snd_emu8000_poke((emu), EMU8000_DATA0(emu), EMU8000_CMD(1, (30)), 0x4828);
0488     /* this is really odd part.. */
0489     outb(0x3C, EMU8000_PTR(emu));
0490     outb(0, EMU8000_DATA1(emu));
0491 
0492     /* skew volume & cutoff */
0493     EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF);
0494     EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF);
0495 }
0496 
0497 
0498 /*
0499  * The main initialization routine.
0500  */
0501 static void
0502 snd_emu8000_init_hw(struct snd_emu8000 *emu)
0503 {
0504     int i;
0505 
0506     emu->last_reg = 0xffff; /* reset the last register index */
0507 
0508     /* initialize hardware configuration */
0509     EMU8000_HWCF1_WRITE(emu, 0x0059);
0510     EMU8000_HWCF2_WRITE(emu, 0x0020);
0511 
0512     /* disable audio; this seems to reduce a clicking noise a bit.. */
0513     EMU8000_HWCF3_WRITE(emu, 0);
0514 
0515     /* initialize audio channels */
0516     init_audio(emu);
0517 
0518     /* initialize DMA */
0519     init_dma(emu);
0520 
0521     /* initialize init arrays */
0522     init_arrays(emu);
0523 
0524     /*
0525      * Initialize the FM section of the AWE32, this is needed
0526      * for DRAM refresh as well
0527      */
0528     snd_emu8000_init_fm(emu);
0529 
0530     /* terminate all voices */
0531     for (i = 0; i < EMU8000_DRAM_VOICES; i++)
0532         EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F);
0533     
0534     /* check DRAM memory size */
0535     size_dram(emu);
0536 
0537     /* enable audio */
0538     EMU8000_HWCF3_WRITE(emu, 0x4);
0539 
0540     /* set equzlier, chorus and reverb modes */
0541     snd_emu8000_update_equalizer(emu);
0542     snd_emu8000_update_chorus_mode(emu);
0543     snd_emu8000_update_reverb_mode(emu);
0544 }
0545 
0546 
0547 /*----------------------------------------------------------------
0548  * Bass/Treble Equalizer
0549  *----------------------------------------------------------------*/
0550 
0551 static const unsigned short bass_parm[12][3] = {
0552     {0xD26A, 0xD36A, 0x0000}, /* -12 dB */
0553     {0xD25B, 0xD35B, 0x0000}, /*  -8 */
0554     {0xD24C, 0xD34C, 0x0000}, /*  -6 */
0555     {0xD23D, 0xD33D, 0x0000}, /*  -4 */
0556     {0xD21F, 0xD31F, 0x0000}, /*  -2 */
0557     {0xC208, 0xC308, 0x0001}, /*   0 (HW default) */
0558     {0xC219, 0xC319, 0x0001}, /*  +2 */
0559     {0xC22A, 0xC32A, 0x0001}, /*  +4 */
0560     {0xC24C, 0xC34C, 0x0001}, /*  +6 */
0561     {0xC26E, 0xC36E, 0x0001}, /*  +8 */
0562     {0xC248, 0xC384, 0x0002}, /* +10 */
0563     {0xC26A, 0xC36A, 0x0002}, /* +12 dB */
0564 };
0565 
0566 static const unsigned short treble_parm[12][9] = {
0567     {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
0568     {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
0569     {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
0570     {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
0571     {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
0572     {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
0573     {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
0574     {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
0575     {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
0576     {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}, /* +8 (HW default) */
0577     {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
0578     {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}  /* +12 dB */
0579 };
0580 
0581 
0582 /*
0583  * set Emu8000 digital equalizer; from 0 to 11 [-12dB - 12dB]
0584  */
0585 /*exported*/ void
0586 snd_emu8000_update_equalizer(struct snd_emu8000 *emu)
0587 {
0588     unsigned short w;
0589     int bass = emu->bass_level;
0590     int treble = emu->treble_level;
0591 
0592     if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
0593         return;
0594     EMU8000_INIT4_WRITE(emu, 0x01, bass_parm[bass][0]);
0595     EMU8000_INIT4_WRITE(emu, 0x11, bass_parm[bass][1]);
0596     EMU8000_INIT3_WRITE(emu, 0x11, treble_parm[treble][0]);
0597     EMU8000_INIT3_WRITE(emu, 0x13, treble_parm[treble][1]);
0598     EMU8000_INIT3_WRITE(emu, 0x1b, treble_parm[treble][2]);
0599     EMU8000_INIT4_WRITE(emu, 0x07, treble_parm[treble][3]);
0600     EMU8000_INIT4_WRITE(emu, 0x0b, treble_parm[treble][4]);
0601     EMU8000_INIT4_WRITE(emu, 0x0d, treble_parm[treble][5]);
0602     EMU8000_INIT4_WRITE(emu, 0x17, treble_parm[treble][6]);
0603     EMU8000_INIT4_WRITE(emu, 0x19, treble_parm[treble][7]);
0604     w = bass_parm[bass][2] + treble_parm[treble][8];
0605     EMU8000_INIT4_WRITE(emu, 0x15, (unsigned short)(w + 0x0262));
0606     EMU8000_INIT4_WRITE(emu, 0x1d, (unsigned short)(w + 0x8362));
0607 }
0608 
0609 
0610 /*----------------------------------------------------------------
0611  * Chorus mode control
0612  *----------------------------------------------------------------*/
0613 
0614 /*
0615  * chorus mode parameters
0616  */
0617 #define SNDRV_EMU8000_CHORUS_1      0
0618 #define SNDRV_EMU8000_CHORUS_2      1
0619 #define SNDRV_EMU8000_CHORUS_3      2
0620 #define SNDRV_EMU8000_CHORUS_4      3
0621 #define SNDRV_EMU8000_CHORUS_FEEDBACK   4
0622 #define SNDRV_EMU8000_CHORUS_FLANGER    5
0623 #define SNDRV_EMU8000_CHORUS_SHORTDELAY 6
0624 #define SNDRV_EMU8000_CHORUS_SHORTDELAY2    7
0625 #define SNDRV_EMU8000_CHORUS_PREDEFINED 8
0626 /* user can define chorus modes up to 32 */
0627 #define SNDRV_EMU8000_CHORUS_NUMBERS    32
0628 
0629 struct soundfont_chorus_fx {
0630     unsigned short feedback;    /* feedback level (0xE600-0xE6FF) */
0631     unsigned short delay_offset;    /* delay (0-0x0DA3) [1/44100 sec] */
0632     unsigned short lfo_depth;   /* LFO depth (0xBC00-0xBCFF) */
0633     unsigned int delay; /* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
0634     unsigned int lfo_freq;      /* LFO freq LFO freq (0-0xFFFFFFFF) */
0635 };
0636 
0637 /* 5 parameters for each chorus mode; 3 x 16bit, 2 x 32bit */
0638 static char chorus_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
0639 static struct soundfont_chorus_fx chorus_parm[SNDRV_EMU8000_CHORUS_NUMBERS] = {
0640     {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D}, /* chorus 1 */
0641     {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 2 */
0642     {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083}, /* chorus 3 */
0643     {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C}, /* chorus 4 */
0644     {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B}, /* feedback */
0645     {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026}, /* flanger */
0646     {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay */
0647     {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083}, /* short delay + feedback */
0648 };
0649 
0650 /*exported*/ int
0651 snd_emu8000_load_chorus_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
0652 {
0653     struct soundfont_chorus_fx rec;
0654     if (mode < SNDRV_EMU8000_CHORUS_PREDEFINED || mode >= SNDRV_EMU8000_CHORUS_NUMBERS) {
0655         snd_printk(KERN_WARNING "invalid chorus mode %d for uploading\n", mode);
0656         return -EINVAL;
0657     }
0658     if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
0659         return -EFAULT;
0660     chorus_parm[mode] = rec;
0661     chorus_defined[mode] = 1;
0662     return 0;
0663 }
0664 
0665 /*exported*/ void
0666 snd_emu8000_update_chorus_mode(struct snd_emu8000 *emu)
0667 {
0668     int effect = emu->chorus_mode;
0669     if (effect < 0 || effect >= SNDRV_EMU8000_CHORUS_NUMBERS ||
0670         (effect >= SNDRV_EMU8000_CHORUS_PREDEFINED && !chorus_defined[effect]))
0671         return;
0672     EMU8000_INIT3_WRITE(emu, 0x09, chorus_parm[effect].feedback);
0673     EMU8000_INIT3_WRITE(emu, 0x0c, chorus_parm[effect].delay_offset);
0674     EMU8000_INIT4_WRITE(emu, 0x03, chorus_parm[effect].lfo_depth);
0675     EMU8000_HWCF4_WRITE(emu, chorus_parm[effect].delay);
0676     EMU8000_HWCF5_WRITE(emu, chorus_parm[effect].lfo_freq);
0677     EMU8000_HWCF6_WRITE(emu, 0x8000);
0678     EMU8000_HWCF7_WRITE(emu, 0x0000);
0679 }
0680 
0681 /*----------------------------------------------------------------
0682  * Reverb mode control
0683  *----------------------------------------------------------------*/
0684 
0685 /*
0686  * reverb mode parameters
0687  */
0688 #define SNDRV_EMU8000_REVERB_ROOM1  0
0689 #define SNDRV_EMU8000_REVERB_ROOM2  1
0690 #define SNDRV_EMU8000_REVERB_ROOM3  2
0691 #define SNDRV_EMU8000_REVERB_HALL1  3
0692 #define SNDRV_EMU8000_REVERB_HALL2  4
0693 #define SNDRV_EMU8000_REVERB_PLATE  5
0694 #define SNDRV_EMU8000_REVERB_DELAY  6
0695 #define SNDRV_EMU8000_REVERB_PANNINGDELAY 7
0696 #define SNDRV_EMU8000_REVERB_PREDEFINED 8
0697 /* user can define reverb modes up to 32 */
0698 #define SNDRV_EMU8000_REVERB_NUMBERS    32
0699 
0700 struct soundfont_reverb_fx {
0701     unsigned short parms[28];
0702 };
0703 
0704 /* reverb mode settings; write the following 28 data of 16 bit length
0705  *   on the corresponding ports in the reverb_cmds array
0706  */
0707 static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
0708 static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
0709 {{  /* room 1 */
0710     0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
0711     0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
0712     0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
0713     0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
0714 }},
0715 {{  /* room 2 */
0716     0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
0717     0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
0718     0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
0719     0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
0720 }},
0721 {{  /* room 3 */
0722     0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
0723     0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
0724     0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
0725     0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
0726 }},
0727 {{  /* hall 1 */
0728     0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
0729     0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
0730     0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
0731     0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
0732 }},
0733 {{  /* hall 2 */
0734     0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
0735     0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
0736     0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
0737     0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
0738 }},
0739 {{  /* plate */
0740     0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
0741     0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
0742     0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
0743     0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
0744 }},
0745 {{  /* delay */
0746     0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
0747     0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
0748     0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
0749     0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
0750 }},
0751 {{  /* panning delay */
0752     0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
0753     0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
0754     0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
0755     0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
0756 }},
0757 };
0758 
0759 enum { DATA1, DATA2 };
0760 #define AWE_INIT1(c)    EMU8000_CMD(2,c), DATA1
0761 #define AWE_INIT2(c)    EMU8000_CMD(2,c), DATA2
0762 #define AWE_INIT3(c)    EMU8000_CMD(3,c), DATA1
0763 #define AWE_INIT4(c)    EMU8000_CMD(3,c), DATA2
0764 
0765 static struct reverb_cmd_pair {
0766     unsigned short cmd, port;
0767 } reverb_cmds[28] = {
0768   {AWE_INIT1(0x03)}, {AWE_INIT1(0x05)}, {AWE_INIT4(0x1F)}, {AWE_INIT1(0x07)},
0769   {AWE_INIT2(0x14)}, {AWE_INIT2(0x16)}, {AWE_INIT1(0x0F)}, {AWE_INIT1(0x17)},
0770   {AWE_INIT1(0x1F)}, {AWE_INIT2(0x07)}, {AWE_INIT2(0x0F)}, {AWE_INIT2(0x17)},
0771   {AWE_INIT2(0x1D)}, {AWE_INIT2(0x1F)}, {AWE_INIT3(0x01)}, {AWE_INIT3(0x03)},
0772   {AWE_INIT1(0x09)}, {AWE_INIT1(0x0B)}, {AWE_INIT1(0x11)}, {AWE_INIT1(0x13)},
0773   {AWE_INIT1(0x19)}, {AWE_INIT1(0x1B)}, {AWE_INIT2(0x01)}, {AWE_INIT2(0x03)},
0774   {AWE_INIT2(0x09)}, {AWE_INIT2(0x0B)}, {AWE_INIT2(0x11)}, {AWE_INIT2(0x13)},
0775 };
0776 
0777 /*exported*/ int
0778 snd_emu8000_load_reverb_fx(struct snd_emu8000 *emu, int mode, const void __user *buf, long len)
0779 {
0780     struct soundfont_reverb_fx rec;
0781 
0782     if (mode < SNDRV_EMU8000_REVERB_PREDEFINED || mode >= SNDRV_EMU8000_REVERB_NUMBERS) {
0783         snd_printk(KERN_WARNING "invalid reverb mode %d for uploading\n", mode);
0784         return -EINVAL;
0785     }
0786     if (len < (long)sizeof(rec) || copy_from_user(&rec, buf, sizeof(rec)))
0787         return -EFAULT;
0788     reverb_parm[mode] = rec;
0789     reverb_defined[mode] = 1;
0790     return 0;
0791 }
0792 
0793 /*exported*/ void
0794 snd_emu8000_update_reverb_mode(struct snd_emu8000 *emu)
0795 {
0796     int effect = emu->reverb_mode;
0797     int i;
0798 
0799     if (effect < 0 || effect >= SNDRV_EMU8000_REVERB_NUMBERS ||
0800         (effect >= SNDRV_EMU8000_REVERB_PREDEFINED && !reverb_defined[effect]))
0801         return;
0802     for (i = 0; i < 28; i++) {
0803         int port;
0804         if (reverb_cmds[i].port == DATA1)
0805             port = EMU8000_DATA1(emu);
0806         else
0807             port = EMU8000_DATA2(emu);
0808         snd_emu8000_poke(emu, port, reverb_cmds[i].cmd, reverb_parm[effect].parms[i]);
0809     }
0810 }
0811 
0812 
0813 /*----------------------------------------------------------------
0814  * mixer interface
0815  *----------------------------------------------------------------*/
0816 
0817 /*
0818  * bass/treble
0819  */
0820 static int mixer_bass_treble_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0821 {
0822     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0823     uinfo->count = 1;
0824     uinfo->value.integer.min = 0;
0825     uinfo->value.integer.max = 11;
0826     return 0;
0827 }
0828 
0829 static int mixer_bass_treble_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0830 {
0831     struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
0832     
0833     ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->treble_level : emu->bass_level;
0834     return 0;
0835 }
0836 
0837 static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0838 {
0839     struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
0840     unsigned long flags;
0841     int change;
0842     unsigned short val1;
0843     
0844     val1 = ucontrol->value.integer.value[0] % 12;
0845     spin_lock_irqsave(&emu->control_lock, flags);
0846     if (kcontrol->private_value) {
0847         change = val1 != emu->treble_level;
0848         emu->treble_level = val1;
0849     } else {
0850         change = val1 != emu->bass_level;
0851         emu->bass_level = val1;
0852     }
0853     spin_unlock_irqrestore(&emu->control_lock, flags);
0854     snd_emu8000_update_equalizer(emu);
0855     return change;
0856 }
0857 
0858 static const struct snd_kcontrol_new mixer_bass_control =
0859 {
0860     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0861     .name = "Synth Tone Control - Bass",
0862     .info = mixer_bass_treble_info,
0863     .get = mixer_bass_treble_get,
0864     .put = mixer_bass_treble_put,
0865     .private_value = 0,
0866 };
0867 
0868 static const struct snd_kcontrol_new mixer_treble_control =
0869 {
0870     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0871     .name = "Synth Tone Control - Treble",
0872     .info = mixer_bass_treble_info,
0873     .get = mixer_bass_treble_get,
0874     .put = mixer_bass_treble_put,
0875     .private_value = 1,
0876 };
0877 
0878 /*
0879  * chorus/reverb mode
0880  */
0881 static int mixer_chorus_reverb_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0882 {
0883     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0884     uinfo->count = 1;
0885     uinfo->value.integer.min = 0;
0886     uinfo->value.integer.max = kcontrol->private_value ? (SNDRV_EMU8000_CHORUS_NUMBERS-1) : (SNDRV_EMU8000_REVERB_NUMBERS-1);
0887     return 0;
0888 }
0889 
0890 static int mixer_chorus_reverb_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0891 {
0892     struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
0893     
0894     ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->chorus_mode : emu->reverb_mode;
0895     return 0;
0896 }
0897 
0898 static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0899 {
0900     struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
0901     unsigned long flags;
0902     int change;
0903     unsigned short val1;
0904     
0905     spin_lock_irqsave(&emu->control_lock, flags);
0906     if (kcontrol->private_value) {
0907         val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_CHORUS_NUMBERS;
0908         change = val1 != emu->chorus_mode;
0909         emu->chorus_mode = val1;
0910     } else {
0911         val1 = ucontrol->value.integer.value[0] % SNDRV_EMU8000_REVERB_NUMBERS;
0912         change = val1 != emu->reverb_mode;
0913         emu->reverb_mode = val1;
0914     }
0915     spin_unlock_irqrestore(&emu->control_lock, flags);
0916     if (change) {
0917         if (kcontrol->private_value)
0918             snd_emu8000_update_chorus_mode(emu);
0919         else
0920             snd_emu8000_update_reverb_mode(emu);
0921     }
0922     return change;
0923 }
0924 
0925 static const struct snd_kcontrol_new mixer_chorus_mode_control =
0926 {
0927     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0928     .name = "Chorus Mode",
0929     .info = mixer_chorus_reverb_info,
0930     .get = mixer_chorus_reverb_get,
0931     .put = mixer_chorus_reverb_put,
0932     .private_value = 1,
0933 };
0934 
0935 static const struct snd_kcontrol_new mixer_reverb_mode_control =
0936 {
0937     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0938     .name = "Reverb Mode",
0939     .info = mixer_chorus_reverb_info,
0940     .get = mixer_chorus_reverb_get,
0941     .put = mixer_chorus_reverb_put,
0942     .private_value = 0,
0943 };
0944 
0945 /*
0946  * FM OPL3 chorus/reverb depth
0947  */
0948 static int mixer_fm_depth_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
0949 {
0950     uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
0951     uinfo->count = 1;
0952     uinfo->value.integer.min = 0;
0953     uinfo->value.integer.max = 255;
0954     return 0;
0955 }
0956 
0957 static int mixer_fm_depth_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0958 {
0959     struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
0960     
0961     ucontrol->value.integer.value[0] = kcontrol->private_value ? emu->fm_chorus_depth : emu->fm_reverb_depth;
0962     return 0;
0963 }
0964 
0965 static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
0966 {
0967     struct snd_emu8000 *emu = snd_kcontrol_chip(kcontrol);
0968     unsigned long flags;
0969     int change;
0970     unsigned short val1;
0971     
0972     val1 = ucontrol->value.integer.value[0] % 256;
0973     spin_lock_irqsave(&emu->control_lock, flags);
0974     if (kcontrol->private_value) {
0975         change = val1 != emu->fm_chorus_depth;
0976         emu->fm_chorus_depth = val1;
0977     } else {
0978         change = val1 != emu->fm_reverb_depth;
0979         emu->fm_reverb_depth = val1;
0980     }
0981     spin_unlock_irqrestore(&emu->control_lock, flags);
0982     if (change)
0983         snd_emu8000_init_fm(emu);
0984     return change;
0985 }
0986 
0987 static const struct snd_kcontrol_new mixer_fm_chorus_depth_control =
0988 {
0989     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0990     .name = "FM Chorus Depth",
0991     .info = mixer_fm_depth_info,
0992     .get = mixer_fm_depth_get,
0993     .put = mixer_fm_depth_put,
0994     .private_value = 1,
0995 };
0996 
0997 static const struct snd_kcontrol_new mixer_fm_reverb_depth_control =
0998 {
0999     .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1000     .name = "FM Reverb Depth",
1001     .info = mixer_fm_depth_info,
1002     .get = mixer_fm_depth_get,
1003     .put = mixer_fm_depth_put,
1004     .private_value = 0,
1005 };
1006 
1007 
1008 static const struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
1009     &mixer_bass_control,
1010     &mixer_treble_control,
1011     &mixer_chorus_mode_control,
1012     &mixer_reverb_mode_control,
1013     &mixer_fm_chorus_depth_control,
1014     &mixer_fm_reverb_depth_control,
1015 };
1016 
1017 /*
1018  * create and attach mixer elements for WaveTable treble/bass controls
1019  */
1020 static int
1021 snd_emu8000_create_mixer(struct snd_card *card, struct snd_emu8000 *emu)
1022 {
1023     struct snd_kcontrol *kctl;
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         kctl = snd_ctl_new1(mixer_defs[i], emu);
1034         err = snd_ctl_add(card, kctl);
1035         if (err < 0)
1036             goto __error;
1037         emu->controls[i] = kctl;
1038     }
1039     return 0;
1040 
1041 __error:
1042     for (i = 0; i < EMU8000_NUM_CONTROLS; i++) {
1043         down_write(&card->controls_rwsem);
1044         if (emu->controls[i])
1045             snd_ctl_remove(card, emu->controls[i]);
1046         up_write(&card->controls_rwsem);
1047     }
1048     return err;
1049 }
1050 
1051 /*
1052  * initialize and register emu8000 synth device.
1053  */
1054 int
1055 snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
1056         struct snd_seq_device **awe_ret)
1057 {
1058     struct snd_seq_device *awe;
1059     struct snd_emu8000 *hw;
1060     int err;
1061 
1062     if (awe_ret)
1063         *awe_ret = NULL;
1064 
1065     if (seq_ports <= 0)
1066         return 0;
1067 
1068     hw = devm_kzalloc(card->dev, sizeof(*hw), GFP_KERNEL);
1069     if (hw == NULL)
1070         return -ENOMEM;
1071     spin_lock_init(&hw->reg_lock);
1072     hw->index = index;
1073     hw->port1 = port;
1074     hw->port2 = port + 0x400;
1075     hw->port3 = port + 0x800;
1076     if (!devm_request_region(card->dev, hw->port1, 4, "Emu8000-1") ||
1077         !devm_request_region(card->dev, hw->port2, 4, "Emu8000-2") ||
1078         !devm_request_region(card->dev, hw->port3, 4, "Emu8000-3")) {
1079         snd_printk(KERN_ERR "sbawe: can't grab ports 0x%lx, 0x%lx, 0x%lx\n", hw->port1, hw->port2, hw->port3);
1080         return -EBUSY;
1081     }
1082     hw->mem_size = 0;
1083     hw->card = card;
1084     hw->seq_ports = seq_ports;
1085     hw->bass_level = 5;
1086     hw->treble_level = 9;
1087     hw->chorus_mode = 2;
1088     hw->reverb_mode = 4;
1089     hw->fm_chorus_depth = 0;
1090     hw->fm_reverb_depth = 0;
1091 
1092     if (snd_emu8000_detect(hw) < 0)
1093         return -ENODEV;
1094 
1095     snd_emu8000_init_hw(hw);
1096     err = snd_emu8000_create_mixer(card, hw);
1097     if (err < 0)
1098         return err;
1099 #if IS_ENABLED(CONFIG_SND_SEQUENCER)
1100     if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
1101                    sizeof(struct snd_emu8000*), &awe) >= 0) {
1102         strcpy(awe->name, "EMU-8000");
1103         *(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
1104     }
1105 #else
1106     awe = NULL;
1107 #endif
1108     if (awe_ret)
1109         *awe_ret = awe;
1110 
1111     return 0;
1112 }
1113 
1114 
1115 /*
1116  * exported stuff
1117  */
1118 
1119 EXPORT_SYMBOL(snd_emu8000_poke);
1120 EXPORT_SYMBOL(snd_emu8000_peek);
1121 EXPORT_SYMBOL(snd_emu8000_poke_dw);
1122 EXPORT_SYMBOL(snd_emu8000_peek_dw);
1123 EXPORT_SYMBOL(snd_emu8000_dma_chan);
1124 EXPORT_SYMBOL(snd_emu8000_init_fm);
1125 EXPORT_SYMBOL(snd_emu8000_load_chorus_fx);
1126 EXPORT_SYMBOL(snd_emu8000_load_reverb_fx);
1127 EXPORT_SYMBOL(snd_emu8000_update_chorus_mode);
1128 EXPORT_SYMBOL(snd_emu8000_update_reverb_mode);
1129 EXPORT_SYMBOL(snd_emu8000_update_equalizer);