0001
0002
0003
0004
0005
0006
0007
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
0027
0028
0029
0030
0031
0032
0033
0034
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));
0041 emu->last_reg = reg;
0042 }
0043 outw((unsigned short)val, port);
0044 spin_unlock_irqrestore(&emu->reg_lock, flags);
0045 }
0046
0047
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));
0055 emu->last_reg = reg;
0056 }
0057 res = inw(port);
0058 spin_unlock_irqrestore(&emu->reg_lock, flags);
0059 return res;
0060 }
0061
0062
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));
0069 emu->last_reg = reg;
0070 }
0071 outw((unsigned short)val, port);
0072 outw((unsigned short)(val>>16), port+2);
0073 spin_unlock_irqrestore(&emu->reg_lock, flags);
0074 }
0075
0076
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));
0085 emu->last_reg = reg;
0086 }
0087 low = inw(port);
0088 res = low + (inw(port+2) << 16);
0089 spin_unlock_irqrestore(&emu->reg_lock, flags);
0090 return res;
0091 }
0092
0093
0094
0095
0096 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)
0114 EMU8000_CCCA_WRITE(emu, ch, 0x06000000 | right_bit);
0115 else
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
0145
0146 static int
0147 snd_emu8000_detect(struct snd_emu8000 *emu)
0148 {
0149
0150 EMU8000_HWCF1_WRITE(emu, 0x0059);
0151 EMU8000_HWCF2_WRITE(emu, 0x0020);
0152 EMU8000_HWCF3_WRITE(emu, 0x0000);
0153
0154
0155
0156
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
0171
0172 static void
0173 init_audio(struct snd_emu8000 *emu)
0174 {
0175 int ch;
0176
0177
0178 for (ch = 0; ch < EMU8000_CHANNELS; ch++)
0179 EMU8000_DCYSUSV_WRITE(emu, ch, 0x80);
0180
0181
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
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
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
0314
0315
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
0337
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);
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
0361
0362
0363
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
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);
0381 snd_emu8000_write_wait(emu);
0382
0383
0384
0385
0386
0387 EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
0388 EMU8000_SMLD_READ(emu);
0389 if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
0390 goto skip_detect;
0391 snd_emu8000_read_wait(emu);
0392
0393 for (size = 512 * 1024; size < EMU8000_MAX_DRAM; size += 512 * 1024) {
0394
0395
0396
0397
0398
0399
0400
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
0407
0408
0409
0410 EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET + (size>>1));
0411
0412 EMU8000_SMLD_READ(emu);
0413 if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2)
0414 break;
0415 snd_emu8000_read_wait(emu);
0416
0417
0418
0419
0420
0421
0422 EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET);
0423 EMU8000_SMLD_READ(emu);
0424 if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1)
0425 break;
0426 snd_emu8000_read_wait(emu);
0427
0428
0429 }
0430
0431 skip_detect:
0432
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
0453
0454
0455 void
0456 snd_emu8000_init_fm(struct snd_emu8000 *emu)
0457 {
0458 unsigned long flags;
0459
0460
0461
0462
0463
0464 EMU8000_DCYSUSV_WRITE(emu, 30, 0x80);
0465 EMU8000_PSST_WRITE(emu, 30, 0xFFFFFFE0);
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
0472 EMU8000_DCYSUSV_WRITE(emu, 31, 0x80);
0473 EMU8000_PSST_WRITE(emu, 31, 0x00FFFFF0);
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
0489 outb(0x3C, EMU8000_PTR(emu));
0490 outb(0, EMU8000_DATA1(emu));
0491
0492
0493 EMU8000_VTFT_WRITE(emu, 30, 0x8000FFFF);
0494 EMU8000_VTFT_WRITE(emu, 31, 0x8000FFFF);
0495 }
0496
0497
0498
0499
0500
0501 static void
0502 snd_emu8000_init_hw(struct snd_emu8000 *emu)
0503 {
0504 int i;
0505
0506 emu->last_reg = 0xffff;
0507
0508
0509 EMU8000_HWCF1_WRITE(emu, 0x0059);
0510 EMU8000_HWCF2_WRITE(emu, 0x0020);
0511
0512
0513 EMU8000_HWCF3_WRITE(emu, 0);
0514
0515
0516 init_audio(emu);
0517
0518
0519 init_dma(emu);
0520
0521
0522 init_arrays(emu);
0523
0524
0525
0526
0527
0528 snd_emu8000_init_fm(emu);
0529
0530
0531 for (i = 0; i < EMU8000_DRAM_VOICES; i++)
0532 EMU8000_DCYSUSV_WRITE(emu, 0, 0x807F);
0533
0534
0535 size_dram(emu);
0536
0537
0538 EMU8000_HWCF3_WRITE(emu, 0x4);
0539
0540
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
0549
0550
0551 static const unsigned short bass_parm[12][3] = {
0552 {0xD26A, 0xD36A, 0x0000},
0553 {0xD25B, 0xD35B, 0x0000},
0554 {0xD24C, 0xD34C, 0x0000},
0555 {0xD23D, 0xD33D, 0x0000},
0556 {0xD21F, 0xD31F, 0x0000},
0557 {0xC208, 0xC308, 0x0001},
0558 {0xC219, 0xC319, 0x0001},
0559 {0xC22A, 0xC32A, 0x0001},
0560 {0xC24C, 0xC34C, 0x0001},
0561 {0xC26E, 0xC36E, 0x0001},
0562 {0xC248, 0xC384, 0x0002},
0563 {0xC26A, 0xC36A, 0x0002},
0564 };
0565
0566 static const unsigned short treble_parm[12][9] = {
0567 {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
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},
0577 {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
0578 {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}
0579 };
0580
0581
0582
0583
0584
0585 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
0612
0613
0614
0615
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
0627 #define SNDRV_EMU8000_CHORUS_NUMBERS 32
0628
0629 struct soundfont_chorus_fx {
0630 unsigned short feedback;
0631 unsigned short delay_offset;
0632 unsigned short lfo_depth;
0633 unsigned int delay;
0634 unsigned int lfo_freq;
0635 };
0636
0637
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},
0641 {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C},
0642 {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083},
0643 {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C},
0644 {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B},
0645 {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026},
0646 {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083},
0647 {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083},
0648 };
0649
0650 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 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
0683
0684
0685
0686
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
0698 #define SNDRV_EMU8000_REVERB_NUMBERS 32
0699
0700 struct soundfont_reverb_fx {
0701 unsigned short parms[28];
0702 };
0703
0704
0705
0706
0707 static char reverb_defined[SNDRV_EMU8000_CHORUS_NUMBERS];
0708 static struct soundfont_reverb_fx reverb_parm[SNDRV_EMU8000_REVERB_NUMBERS] = {
0709 {{
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 {{
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 {{
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 {{
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 {{
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 {{
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 {{
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 {{
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 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 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
0815
0816
0817
0818
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
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
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
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
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
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);