23 #include <linux/wait.h>
24 #include <linux/sched.h>
25 #include <linux/slab.h>
27 #include <linux/export.h>
33 #include <asm/uaccess.h>
56 outw((
unsigned short)val, port);
57 spin_unlock_irqrestore(&emu->
reg_lock, flags);
71 spin_unlock_irqrestore(&emu->
reg_lock, flags);
84 outw((
unsigned short)val, port);
85 outw((
unsigned short)(val>>16), port+2);
86 spin_unlock_irqrestore(&emu->
reg_lock, flags);
101 res = low + (
inw(port+2) << 16);
102 spin_unlock_irqrestore(&emu->
reg_lock, flags);
238 static unsigned short init1[128] = {
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,
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,
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,
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,
260 static unsigned short init2[128] = {
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,
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,
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,
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,
282 static unsigned short init3[128] = {
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,
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,
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,
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,
304 static unsigned short init4[128] = {
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,
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,
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,
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,
337 for (i = 0; i <
size; i++, p++)
339 for (i = 0; i <
size; i++, p++)
341 for (i = 0; i <
size; i++, p++)
343 for (i = 0; i <
size; i++, p++)
357 msleep((1024 * 1000) / 44100);
369 #define UNIQUE_ID1 0xa5b9
370 #define UNIQUE_ID2 0x9d53
381 int i,
size, detected_size;
408 snd_emu8000_write_wait(emu);
420 snd_emu8000_read_wait(emu);
431 snd_emu8000_read_wait(emu);
434 detected_size = size + 512 * 1024;
438 if (detected_size == 0) {
439 snd_emu8000_read_wait(emu);
443 detected_size = 512 * 1024;
447 for (i = 0; i < 10000; i++) {
457 snd_printdd(
"EMU8000 [0x%lx]: %d Kb on-board memory detected\n",
458 emu->
port1, detected_size/1024);
500 spin_unlock_irqrestore(&emu->
reg_lock, flags);
565 static unsigned short bass_parm[12][3] = {
566 {0xD26A, 0xD36A, 0x0000},
567 {0xD25B, 0xD35B, 0x0000},
568 {0xD24C, 0xD34C, 0x0000},
569 {0xD23D, 0xD33D, 0x0000},
570 {0xD21F, 0xD31F, 0x0000},
571 {0xC208, 0xC308, 0x0001},
572 {0xC219, 0xC319, 0x0001},
573 {0xC22A, 0xC32A, 0x0001},
574 {0xC24C, 0xC34C, 0x0001},
575 {0xC26E, 0xC36E, 0x0001},
576 {0xC248, 0xC384, 0x0002},
577 {0xC26A, 0xC36A, 0x0002},
580 static unsigned short treble_parm[12][9] = {
581 {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
582 {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
583 {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
584 {0x821E, 0xC23D, 0x031E, 0xC33D, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
585 {0x821E, 0xC21F, 0x031E, 0xC31F, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
586 {0x821E, 0xD208, 0x031E, 0xD308, 0x021E, 0xD208, 0x831E, 0xD308, 0x0002},
587 {0x821E, 0xD208, 0x031E, 0xD308, 0x021D, 0xD219, 0x831D, 0xD319, 0x0002},
588 {0x821E, 0xD208, 0x031E, 0xD308, 0x021C, 0xD22A, 0x831C, 0xD32A, 0x0002},
589 {0x821E, 0xD208, 0x031E, 0xD308, 0x021A, 0xD24C, 0x831A, 0xD34C, 0x0002},
590 {0x821E, 0xD208, 0x031E, 0xD308, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
591 {0x821D, 0xD219, 0x031D, 0xD319, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002},
592 {0x821C, 0xD22A, 0x031C, 0xD32A, 0x0219, 0xD26E, 0x8319, 0xD36E, 0x0002}
606 if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
618 w = bass_parm[bass][2] + treble_parm[treble][8];
631 #define SNDRV_EMU8000_CHORUS_1 0
632 #define SNDRV_EMU8000_CHORUS_2 1
633 #define SNDRV_EMU8000_CHORUS_3 2
634 #define SNDRV_EMU8000_CHORUS_4 3
635 #define SNDRV_EMU8000_CHORUS_FEEDBACK 4
636 #define SNDRV_EMU8000_CHORUS_FLANGER 5
637 #define SNDRV_EMU8000_CHORUS_SHORTDELAY 6
638 #define SNDRV_EMU8000_CHORUS_SHORTDELAY2 7
639 #define SNDRV_EMU8000_CHORUS_PREDEFINED 8
641 #define SNDRV_EMU8000_CHORUS_NUMBERS 32
654 {0xE600, 0x03F6, 0xBC2C ,0x00000000, 0x0000006D},
655 {0xE608, 0x031A, 0xBC6E, 0x00000000, 0x0000017C},
656 {0xE610, 0x031A, 0xBC84, 0x00000000, 0x00000083},
657 {0xE620, 0x0269, 0xBC6E, 0x00000000, 0x0000017C},
658 {0xE680, 0x04D3, 0xBCA6, 0x00000000, 0x0000005B},
659 {0xE6E0, 0x044E, 0xBC37, 0x00000000, 0x00000026},
660 {0xE600, 0x0B06, 0xBC00, 0x0006E000, 0x00000083},
661 {0xE6C0, 0x0B06, 0xBC00, 0x0006E000, 0x00000083},
672 if (len < (
long)
sizeof(rec) ||
copy_from_user(&rec, buf,
sizeof(rec)))
674 chorus_parm[
mode] = rec;
675 chorus_defined[
mode] = 1;
702 #define SNDRV_EMU8000_REVERB_ROOM1 0
703 #define SNDRV_EMU8000_REVERB_ROOM2 1
704 #define SNDRV_EMU8000_REVERB_ROOM3 2
705 #define SNDRV_EMU8000_REVERB_HALL1 3
706 #define SNDRV_EMU8000_REVERB_HALL2 4
707 #define SNDRV_EMU8000_REVERB_PLATE 5
708 #define SNDRV_EMU8000_REVERB_DELAY 6
709 #define SNDRV_EMU8000_REVERB_PANNINGDELAY 7
710 #define SNDRV_EMU8000_REVERB_PREDEFINED 8
712 #define SNDRV_EMU8000_REVERB_NUMBERS 32
724 0xB488, 0xA450, 0x9550, 0x84B5, 0x383A, 0x3EB5, 0x72F4,
725 0x72A4, 0x7254, 0x7204, 0x7204, 0x7204, 0x4416, 0x4516,
726 0xA490, 0xA590, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
727 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
730 0xB488, 0xA458, 0x9558, 0x84B5, 0x383A, 0x3EB5, 0x7284,
731 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
732 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
733 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
736 0xB488, 0xA460, 0x9560, 0x84B5, 0x383A, 0x3EB5, 0x7284,
737 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4416, 0x4516,
738 0xA490, 0xA590, 0x842C, 0x852C, 0x842C, 0x852C, 0x842B,
739 0x852B, 0x842B, 0x852B, 0x842A, 0x852A, 0x842A, 0x852A,
742 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7284,
743 0x7254, 0x7224, 0x7224, 0x7254, 0x7284, 0x4448, 0x4548,
744 0xA440, 0xA540, 0x842B, 0x852B, 0x842B, 0x852B, 0x842A,
745 0x852A, 0x842A, 0x852A, 0x8429, 0x8529, 0x8429, 0x8529,
748 0xB488, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7254,
749 0x7234, 0x7224, 0x7254, 0x7264, 0x7294, 0x44C3, 0x45C3,
750 0xA404, 0xA504, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
751 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
754 0xB4FF, 0xA470, 0x9570, 0x84B5, 0x383A, 0x3EB5, 0x7234,
755 0x7234, 0x7234, 0x7234, 0x7234, 0x7234, 0x4448, 0x4548,
756 0xA440, 0xA540, 0x842A, 0x852A, 0x842A, 0x852A, 0x8429,
757 0x8529, 0x8429, 0x8529, 0x8428, 0x8528, 0x8428, 0x8528,
760 0xB4FF, 0xA470, 0x9500, 0x84B5, 0x333A, 0x39B5, 0x7204,
761 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
762 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
763 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
766 0xB4FF, 0xA490, 0x9590, 0x8474, 0x333A, 0x39B5, 0x7204,
767 0x7204, 0x7204, 0x7204, 0x7204, 0x72F4, 0x4400, 0x4500,
768 0xA4FF, 0xA5FF, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420,
769 0x8520, 0x8420, 0x8520, 0x8420, 0x8520, 0x8420, 0x8520,
774 #define AWE_INIT1(c) EMU8000_CMD(2,c), DATA1
775 #define AWE_INIT2(c) EMU8000_CMD(2,c), DATA2
776 #define AWE_INIT3(c) EMU8000_CMD(3,c), DATA1
777 #define AWE_INIT4(c) EMU8000_CMD(3,c), DATA2
779 static struct reverb_cmd_pair {
781 } reverb_cmds[28] = {
800 if (len < (
long)
sizeof(rec) ||
copy_from_user(&rec, buf,
sizeof(rec)))
802 reverb_parm[
mode] = rec;
803 reverb_defined[
mode] = 1;
816 for (i = 0; i < 28; i++) {
818 if (reverb_cmds[i].port ==
DATA1)
858 val1 = ucontrol->
value.integer.value[0] % 12;
875 .name =
"Synth Tone Control - Bass",
876 .info = mixer_bass_treble_info,
877 .get = mixer_bass_treble_get,
878 .put = mixer_bass_treble_put,
885 .name =
"Synth Tone Control - Treble",
886 .info = mixer_bass_treble_info,
887 .get = mixer_bass_treble_get,
888 .put = mixer_bass_treble_put,
942 .name =
"Chorus Mode",
943 .info = mixer_chorus_reverb_info,
944 .get = mixer_chorus_reverb_get,
945 .put = mixer_chorus_reverb_put,
952 .name =
"Reverb Mode",
953 .info = mixer_chorus_reverb_info,
954 .get = mixer_chorus_reverb_get,
955 .put = mixer_chorus_reverb_put,
986 val1 = ucontrol->
value.integer.value[0] % 256;
1004 .name =
"FM Chorus Depth",
1005 .info = mixer_fm_depth_info,
1006 .get = mixer_fm_depth_get,
1007 .put = mixer_fm_depth_put,
1014 .name =
"FM Reverb Depth",
1015 .info = mixer_fm_depth_info,
1016 .get = mixer_fm_depth_get,
1017 .put = mixer_fm_depth_put,
1023 &mixer_bass_control,
1024 &mixer_treble_control,
1025 &mixer_chorus_mode_control,
1026 &mixer_reverb_mode_control,
1027 &mixer_fm_chorus_depth_control,
1028 &mixer_fm_reverb_depth_control,
1079 return snd_emu8000_free(hw);
1108 hw->
port2 = port + 0x400;
1109 hw->
port3 = port + 0x800;
1114 snd_emu8000_free(hw);
1127 if (snd_emu8000_detect(hw) < 0) {
1128 snd_emu8000_free(hw);
1132 snd_emu8000_init_hw(hw);
1133 if ((err = snd_emu8000_create_mixer(card, hw)) < 0) {
1134 snd_emu8000_free(hw);
1139 snd_emu8000_free(hw);
1142 #if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))