Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
[linux-2.6] / sound / isa / wavefront / wavefront_fx.c
1 /*
2  *  Copyright (c) 1998-2002 by Paul Davis <pbd@op.net>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17  */
18
19 #include <sound/driver.h>
20 #include <asm/io.h>
21 #include <linux/init.h>
22 #include <linux/time.h>
23 #include <linux/wait.h>
24 #include <sound/core.h>
25 #include <sound/snd_wavefront.h>
26 #include <sound/initval.h>
27
28 /* Control bits for the Load Control Register
29  */
30
31 #define FX_LSB_TRANSFER 0x01    /* transfer after DSP LSB byte written */
32 #define FX_MSB_TRANSFER 0x02    /* transfer after DSP MSB byte written */
33 #define FX_AUTO_INCR    0x04    /* auto-increment DSP address after transfer */
34
35 /* weird stuff, derived from port I/O tracing with dosemu */
36
37 static unsigned char page_zero[] __initdata = {
38 0x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
39 0x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
40 0x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
41 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
44 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x19,
50 0x01, 0x1a, 0x01, 0x20, 0x01, 0x40, 0x01, 0x17, 0x00, 0x00, 0x01,
51 0x80, 0x01, 0x20, 0x00, 0x10, 0x01, 0xa0, 0x03, 0xd1, 0x00, 0x00,
52 0x01, 0xf2, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf4, 0x02,
53 0xe0, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17,
54 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x00, 0x00,
55 0x40, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x60, 0x00, 0x00,
56 0x00, 0x92, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb3, 0x02,
57 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x40,
58 0x00, 0x80, 0x00, 0xf5, 0x00, 0x20, 0x00, 0x70, 0x00, 0xa0, 0x02,
59 0x11, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
60 0x02, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x17, 0x00, 0x1b, 0x00,
61 0x1d, 0x02, 0xdf
62 };
63
64 static unsigned char page_one[] __initdata = {
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
66 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
67 0x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
68 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x60,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x80, 0x00,
78 0x00, 0x02, 0xfb, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x1b, 0x02, 0xd7,
79 0x00, 0x00, 0x02, 0xf7, 0x03, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00,
80 0x1c, 0x03, 0x3c, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x03, 0xc0,
81 0x00, 0x00, 0x03, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5d, 0x00,
82 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x03, 0xc0,
83 0x00, 0x00, 0x03, 0x9e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03,
84 0xbe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
86 0xdb, 0x00, 0x00, 0x02, 0xdb, 0x00, 0x00, 0x02, 0xe0, 0x00, 0x00,
87 0x02, 0xfb, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x40, 0x02, 0xfb, 0x02,
88 0x60, 0x00, 0x1b
89 };
90
91 static unsigned char page_two[] __initdata = {
92 0xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
93 0x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x07,
98 0x05, 0x05, 0x05, 0x04, 0x07, 0x05, 0x04, 0x07, 0x05, 0x44, 0x46,
99 0x44, 0x46, 0x46, 0x07, 0x05, 0x44, 0x46, 0x05, 0x46, 0x05, 0x46,
100 0x05, 0x46, 0x05, 0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07,
101 0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07, 0x44, 0x05, 0x05,
102 0x05, 0x44, 0x05, 0x05, 0x05, 0x46, 0x05, 0x46, 0x05, 0x46, 0x05,
103 0x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
104 };
105
106 static unsigned char page_three[] __initdata = {
107 0x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
108 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
112 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
113 0xc0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
114 0x60, 0x00, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0x40,
115 0x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
116 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
117 0x00, 0x42, 0x00, 0x40, 0x00, 0x42, 0x00, 0x02, 0x00, 0x02, 0x00,
118 0x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
119 };
120
121 static unsigned char page_four[] __initdata = {
122 0x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
123 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
128 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
129 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, 0x00,
130 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60,
131 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00,
132 0x20, 0x00, 0x22, 0x02, 0x22, 0x02, 0x20, 0x00, 0x60, 0x00, 0x22,
133 0x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
134 };
135
136 static unsigned char page_six[] __initdata = {
137 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
138 0x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
139 0x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
140 0x16, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1c, 0x00,
141 0x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x22, 0x00, 0x00, 0x24,
142 0x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2a, 0x00, 0x00,
143 0x2c, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x32, 0x00,
144 0x00, 0x34, 0x00, 0x00, 0x36, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3a,
145 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x40, 0x00, 0x00,
146 0x42, 0x03, 0x00, 0x44, 0x01, 0x00, 0x46, 0x0a, 0x21, 0x48, 0x0d,
147 0x23, 0x4a, 0x23, 0x1b, 0x4c, 0x37, 0x8f, 0x4e, 0x45, 0x77, 0x50,
148 0x52, 0xe2, 0x52, 0x1c, 0x92, 0x54, 0x1c, 0x52, 0x56, 0x07, 0x00,
149 0x58, 0x2f, 0xc6, 0x5a, 0x0b, 0x00, 0x5c, 0x30, 0x06, 0x5e, 0x17,
150 0x00, 0x60, 0x3d, 0xda, 0x62, 0x29, 0x00, 0x64, 0x3e, 0x41, 0x66,
151 0x39, 0x00, 0x68, 0x4c, 0x48, 0x6a, 0x49, 0x00, 0x6c, 0x4c, 0x6c,
152 0x6e, 0x11, 0xd2, 0x70, 0x16, 0x0c, 0x72, 0x00, 0x00, 0x74, 0x00,
153 0x80, 0x76, 0x0f, 0x00, 0x78, 0x00, 0x80, 0x7a, 0x13, 0x00, 0x7c,
154 0x80, 0x00, 0x7e, 0x80, 0x80
155 };
156
157 static unsigned char page_seven[] __initdata = {
158 0x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
160 0x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
161 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
165 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
166 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
167 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff,
172 0x0f, 0xff, 0x0f, 0xff, 0x02, 0xe9, 0x06, 0x8c, 0x06, 0x8c, 0x0f,
173 0xff, 0x1a, 0x75, 0x0d, 0x8b, 0x04, 0xe9, 0x0b, 0x16, 0x1a, 0x38,
174 0x0d, 0xc8, 0x04, 0x6f, 0x0b, 0x91, 0x0f, 0xff, 0x06, 0x40, 0x06,
175 0x40, 0x02, 0x8f, 0x0f, 0xff, 0x06, 0x62, 0x06, 0x62, 0x02, 0x7b,
176 0x0f, 0xff, 0x06, 0x97, 0x06, 0x97, 0x02, 0x52, 0x0f, 0xff, 0x06,
177 0xf6, 0x06, 0xf6, 0x02, 0x19, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55,
178 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x14,
179 0xda, 0x0d, 0x93, 0x04, 0xda, 0x05, 0x93, 0x14, 0xda, 0x0d, 0x93,
180 0x04, 0xda, 0x05, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x02, 0x00
182 };
183
184 static unsigned char page_zero_v2[] __initdata = {
185 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
186 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
194 };
195
196 static unsigned char page_one_v2[] __initdata = {
197 0x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
206 };
207
208 static unsigned char page_two_v2[] __initdata = {
209 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
213 0x00, 0x00, 0x00, 0x00
214 };
215 static unsigned char page_three_v2[] __initdata = {
216 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
218 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
219 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
220 0x00, 0x00, 0x00, 0x00
221 };
222 static unsigned char page_four_v2[] __initdata = {
223 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
224 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
225 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
226 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
227 0x00, 0x00, 0x00, 0x00
228 };
229
230 static unsigned char page_seven_v2[] __initdata = {
231 0x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
240 };
241
242 static unsigned char mod_v2[] __initdata = {
243 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02,
244 0x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05,
245 0x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0,
246 0x20, 0xb1, 0x20, 0xb2, 0x20, 0xb3, 0x20, 0xb4, 0x20, 0xb5, 0x20,
247 0xb6, 0x20, 0xb7, 0x20, 0xf0, 0x20, 0xf1, 0x20, 0xf2, 0x20, 0xf3,
248 0x20, 0xf4, 0x20, 0xf5, 0x20, 0xf6, 0x20, 0xf7, 0x20, 0x10, 0xff,
249 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0xff, 0x15, 0xff, 0x16,
250 0xff, 0x17, 0xff, 0x20, 0xff, 0x21, 0xff, 0x22, 0xff, 0x23, 0xff,
251 0x24, 0xff, 0x25, 0xff, 0x26, 0xff, 0x27, 0xff, 0x30, 0x00, 0x31,
252 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00,
253 0x37, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44,
254 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x50, 0x00, 0x51, 0x00,
255 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
256 0x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00,
257 0x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x70, 0xc0, 0x71, 0xc0, 0x72,
258 0xc0, 0x73, 0xc0, 0x74, 0xc0, 0x75, 0xc0, 0x76, 0xc0, 0x77, 0xc0,
259 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85,
260 0x00, 0x86, 0x00, 0x87, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00,
261 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0xa0,
262 0x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00,
263 0xa6, 0x00, 0xa7, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
264 0x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xd0, 0x00,
265 0xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6,
266 0x00, 0xd7, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe2, 0x00, 0xe3, 0x00,
267 0xe4, 0x00, 0xe5, 0x00, 0xe6, 0x00, 0xe7, 0x00, 0x01, 0x00, 0x02,
268 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03,
269 0x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
270 0x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
271 };
272 static unsigned char coefficients[] __initdata = {
273 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
274 0x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
275 0x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
276 0x40, 0x02, 0x40, 0x01, 0x41, 0x02, 0x60, 0x07, 0x40, 0x00, 0x00,
277 0x07, 0x41, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, 0x07, 0x4a, 0x00,
278 0x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x20, 0x07, 0x47,
279 0x00, 0x00, 0x07, 0x4a, 0x00, 0x00, 0x07, 0x7c, 0x00, 0x00, 0x07,
280 0x7e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x07, 0x7c, 0x00, 0x00,
281 0x07, 0x7e, 0x00, 0x00, 0x07, 0x44, 0x00, 0x00, 0x00, 0x44, 0x01,
282 0x00, 0x07, 0x44, 0x00, 0x00, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43,
283 0x00, 0x00, 0x00, 0x42, 0x01, 0x1a, 0x00, 0x43, 0x01, 0x20, 0x07,
284 0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00,
285 0x07, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0x40, 0x01, 0x41, 0x02,
286 0x60, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x44,
287 0x0f, 0xff, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07,
288 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x51, 0x06, 0x40,
289 0x07, 0x50, 0x06, 0x40, 0x07, 0x4f, 0x03, 0x81, 0x07, 0x53, 0x1a,
290 0x76, 0x07, 0x54, 0x0d, 0x8b, 0x07, 0x55, 0x04, 0xe9, 0x07, 0x56,
291 0x0b, 0x17, 0x07, 0x57, 0x1a, 0x38, 0x07, 0x58, 0x0d, 0xc9, 0x07,
292 0x59, 0x04, 0x6f, 0x07, 0x5a, 0x0b, 0x91, 0x07, 0x73, 0x14, 0xda,
293 0x07, 0x74, 0x0d, 0x93, 0x07, 0x75, 0x04, 0xd9, 0x07, 0x76, 0x05,
294 0x93, 0x07, 0x77, 0x14, 0xda, 0x07, 0x78, 0x0d, 0x93, 0x07, 0x79,
295 0x04, 0xd9, 0x07, 0x7a, 0x05, 0x93, 0x07, 0x5e, 0x03, 0x68, 0x07,
296 0x5c, 0x04, 0x31, 0x07, 0x5d, 0x04, 0x31, 0x07, 0x62, 0x03, 0x52,
297 0x07, 0x60, 0x04, 0x76, 0x07, 0x61, 0x04, 0x76, 0x07, 0x66, 0x03,
298 0x2e, 0x07, 0x64, 0x04, 0xda, 0x07, 0x65, 0x04, 0xda, 0x07, 0x6a,
299 0x02, 0xf6, 0x07, 0x68, 0x05, 0x62, 0x07, 0x69, 0x05, 0x62, 0x06,
300 0x46, 0x0a, 0x22, 0x06, 0x48, 0x0d, 0x24, 0x06, 0x6e, 0x11, 0xd3,
301 0x06, 0x70, 0x15, 0xcb, 0x06, 0x52, 0x20, 0x93, 0x06, 0x54, 0x20,
302 0x54, 0x06, 0x4a, 0x27, 0x1d, 0x06, 0x58, 0x2f, 0xc8, 0x06, 0x5c,
303 0x30, 0x07, 0x06, 0x4c, 0x37, 0x90, 0x06, 0x60, 0x3d, 0xdb, 0x06,
304 0x64, 0x3e, 0x42, 0x06, 0x4e, 0x45, 0x78, 0x06, 0x68, 0x4c, 0x48,
305 0x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
306 0xba
307 };
308 static unsigned char coefficients2[] __initdata = {
309 0x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
310 0xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
311 0x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
312 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
313 0x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
314 };
315 static unsigned char coefficients3[] __initdata = {
316 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
317 0x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
318 0x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,
319 0x47, 0x01, 0x47, 0x01, 0x70, 0x01, 0x70, 0x01, 0x99, 0x01, 0x99,
320 0x01, 0xc2, 0x01, 0xc2, 0x01, 0xeb, 0x01, 0xeb, 0x02, 0x14, 0x02,
321 0x14, 0x02, 0x3d, 0x02, 0x3d, 0x02, 0x66, 0x02, 0x66, 0x02, 0x8f,
322 0x02, 0x8f, 0x02, 0xb8, 0x02, 0xb8, 0x02, 0xe1, 0x02, 0xe1, 0x03,
323 0x0a, 0x03, 0x0a, 0x03, 0x33, 0x03, 0x33, 0x03, 0x5c, 0x03, 0x5c,
324 0x03, 0x85, 0x03, 0x85, 0x03, 0xae, 0x03, 0xae, 0x03, 0xd7, 0x03,
325 0xd7, 0x04, 0x00, 0x04, 0x00, 0x04, 0x28, 0x04, 0x28, 0x04, 0x51,
326 0x04, 0x51, 0x04, 0x7a, 0x04, 0x7a, 0x04, 0xa3, 0x04, 0xa3, 0x04,
327 0xcc, 0x04, 0xcc, 0x04, 0xf5, 0x04, 0xf5, 0x05, 0x1e, 0x05, 0x1e,
328 0x05, 0x47, 0x05, 0x47, 0x05, 0x70, 0x05, 0x70, 0x05, 0x99, 0x05,
329 0x99, 0x05, 0xc2, 0x05, 0xc2, 0x05, 0xeb, 0x05, 0xeb, 0x06, 0x14,
330 0x06, 0x14, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x66, 0x06, 0x66, 0x06,
331 0x8f, 0x06, 0x8f, 0x06, 0xb8, 0x06, 0xb8, 0x06, 0xe1, 0x06, 0xe1,
332 0x07, 0x0a, 0x07, 0x0a, 0x07, 0x33, 0x07, 0x33, 0x07, 0x5c, 0x07,
333 0x5c, 0x07, 0x85, 0x07, 0x85, 0x07, 0xae, 0x07, 0xae, 0x07, 0xd7,
334 0x07, 0xd7, 0x08, 0x00, 0x08, 0x00, 0x08, 0x28, 0x08, 0x28, 0x08,
335 0x51, 0x08, 0x51, 0x08, 0x7a, 0x08, 0x7a, 0x08, 0xa3, 0x08, 0xa3,
336 0x08, 0xcc, 0x08, 0xcc, 0x08, 0xf5, 0x08, 0xf5, 0x09, 0x1e, 0x09,
337 0x1e, 0x09, 0x47, 0x09, 0x47, 0x09, 0x70, 0x09, 0x70, 0x09, 0x99,
338 0x09, 0x99, 0x09, 0xc2, 0x09, 0xc2, 0x09, 0xeb, 0x09, 0xeb, 0x0a,
339 0x14, 0x0a, 0x14, 0x0a, 0x3d, 0x0a, 0x3d, 0x0a, 0x66, 0x0a, 0x66,
340 0x0a, 0x8f, 0x0a, 0x8f, 0x0a, 0xb8, 0x0a, 0xb8, 0x0a, 0xe1, 0x0a,
341 0xe1, 0x0b, 0x0a, 0x0b, 0x0a, 0x0b, 0x33, 0x0b, 0x33, 0x0b, 0x5c,
342 0x0b, 0x5c, 0x0b, 0x85, 0x0b, 0x85, 0x0b, 0xae, 0x0b, 0xae, 0x0b,
343 0xd7, 0x0b, 0xd7, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x28, 0x0c, 0x28,
344 0x0c, 0x51, 0x0c, 0x51, 0x0c, 0x7a, 0x0c, 0x7a, 0x0c, 0xa3, 0x0c,
345 0xa3, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xf5, 0x0c, 0xf5, 0x0d, 0x1e,
346 0x0d, 0x1e, 0x0d, 0x47, 0x0d, 0x47, 0x0d, 0x70, 0x0d, 0x70, 0x0d,
347 0x99, 0x0d, 0x99, 0x0d, 0xc2, 0x0d, 0xc2, 0x0d, 0xeb, 0x0d, 0xeb,
348 0x0e, 0x14, 0x0e, 0x14, 0x0e, 0x3d, 0x0e, 0x3d, 0x0e, 0x66, 0x0e,
349 0x66, 0x0e, 0x8f, 0x0e, 0x8f, 0x0e, 0xb8, 0x0e, 0xb8, 0x0e, 0xe1,
350 0x0e, 0xe1, 0x0f, 0x0a, 0x0f, 0x0a, 0x0f, 0x33, 0x0f, 0x33, 0x0f,
351 0x5c, 0x0f, 0x5c, 0x0f, 0x85, 0x0f, 0x85, 0x0f, 0xae, 0x0f, 0xae,
352 0x0f, 0xd7, 0x0f, 0xd7, 0x0f, 0xff, 0x0f, 0xff
353 };
354
355 static int
356 wavefront_fx_idle (snd_wavefront_t *dev)
357
358 {
359         int i;
360         unsigned int x = 0x80;
361
362         for (i = 0; i < 1000; i++) {
363                 x = inb (dev->fx_status);
364                 if ((x & 0x80) == 0) {
365                         break;
366                 }
367         }
368
369         if (x & 0x80) {
370                 snd_printk ("FX device never idle.\n");
371                 return 0;
372         }
373
374         return (1);
375 }
376
377 static void
378 wavefront_fx_mute (snd_wavefront_t *dev, int onoff)
379
380 {
381         if (!wavefront_fx_idle(dev)) {
382                 return;
383         }
384
385         outb (onoff ? 0x02 : 0x00, dev->fx_op);
386 }
387
388 static int
389 wavefront_fx_memset (snd_wavefront_t *dev,
390                      int page,
391                      int addr,
392                      int cnt,
393                      unsigned short *data)
394 {
395         if (page < 0 || page > 7) {
396                 snd_printk ("FX memset: "
397                         "page must be >= 0 and <= 7\n");
398                 return -(EINVAL);
399         }
400
401         if (addr < 0 || addr > 0x7f) {
402                 snd_printk ("FX memset: "
403                         "addr must be >= 0 and <= 7f\n");
404                 return -(EINVAL);
405         }
406
407         if (cnt == 1) {
408
409                 outb (FX_LSB_TRANSFER, dev->fx_lcr);
410                 outb (page, dev->fx_dsp_page);
411                 outb (addr, dev->fx_dsp_addr);
412                 outb ((data[0] >> 8), dev->fx_dsp_msb);
413                 outb ((data[0] & 0xff), dev->fx_dsp_lsb);
414
415                 snd_printk ("FX: addr %d:%x set to 0x%x\n",
416                         page, addr, data[0]);
417
418         } else {
419                 int i;
420
421                 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
422                 outb (page, dev->fx_dsp_page);
423                 outb (addr, dev->fx_dsp_addr);
424
425                 for (i = 0; i < cnt; i++) {
426                         outb ((data[i] >> 8), dev->fx_dsp_msb);
427                         outb ((data[i] & 0xff), dev->fx_dsp_lsb);
428                         if (!wavefront_fx_idle (dev)) {
429                                 break;
430                         }
431                 }
432
433                 if (i != cnt) {
434                         snd_printk ("FX memset "
435                                     "(0x%x, 0x%x, 0x%lx, %d) incomplete\n",
436                                     page, addr, (unsigned long) data, cnt);
437                         return -(EIO);
438                 }
439         }
440
441         return 0;
442 }
443
444 int
445 snd_wavefront_fx_detect (snd_wavefront_t *dev)
446
447 {
448         /* This is a crude check, but its the best one I have for now.
449            Certainly on the Maui and the Tropez, wavefront_fx_idle() will
450            report "never idle", which suggests that this test should
451            work OK.
452         */
453
454         if (inb (dev->fx_status) & 0x80) {
455                 snd_printk ("Hmm, probably a Maui or Tropez.\n");
456                 return -1;
457         }
458
459         return 0;
460 }
461
462 int
463 snd_wavefront_fx_open (struct snd_hwdep *hw, struct file *file)
464
465 {
466         if (!try_module_get(hw->card->module))
467                 return -EFAULT;
468         file->private_data = hw;
469         return 0;
470 }
471
472 int 
473 snd_wavefront_fx_release (struct snd_hwdep *hw, struct file *file)
474
475 {
476         module_put(hw->card->module);
477         return 0;
478 }
479
480 int
481 snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
482                         unsigned int cmd, unsigned long arg)
483
484 {
485         struct snd_card *card;
486         snd_wavefront_card_t *acard;
487         snd_wavefront_t *dev;
488         wavefront_fx_info r;
489         unsigned short *page_data = NULL;
490         unsigned short *pd;
491         int err = 0;
492
493         snd_assert(sdev->card != NULL, return -ENODEV);
494         
495         card = sdev->card;
496
497         snd_assert(card->private_data != NULL, return -ENODEV);
498
499         acard = card->private_data;
500         dev = &acard->wavefront;
501
502         if (copy_from_user (&r, (void __user *)arg, sizeof (wavefront_fx_info)))
503                 return -EFAULT;
504
505         switch (r.request) {
506         case WFFX_MUTE:
507                 wavefront_fx_mute (dev, r.data[0]);
508                 return -EIO;
509
510         case WFFX_MEMSET:
511                 if (r.data[2] <= 0) {
512                         snd_printk ("cannot write "
513                                 "<= 0 bytes to FX\n");
514                         return -EIO;
515                 } else if (r.data[2] == 1) {
516                         pd = (unsigned short *) &r.data[3];
517                 } else {
518                         if (r.data[2] > 256) {
519                                 snd_printk ("cannot write "
520                                             "> 512 bytes to FX\n");
521                                 return -EIO;
522                         }
523                         page_data = kmalloc(r.data[2] * sizeof(short), GFP_KERNEL);
524                         if (!page_data)
525                                 return -ENOMEM;
526                         if (copy_from_user (page_data,
527                                             (unsigned char __user *) r.data[3],
528                                             r.data[2] * sizeof(short))) {
529                                 kfree(page_data);
530                                 return -EFAULT;
531                         }
532                         pd = page_data;
533                 }
534
535                 err = wavefront_fx_memset (dev,
536                              r.data[0], /* page */
537                              r.data[1], /* addr */
538                              r.data[2], /* cnt */
539                              pd);
540                 kfree(page_data);
541                 break;
542
543         default:
544                 snd_printk ("FX: ioctl %d not yet supported\n",
545                             r.request);
546                 return -ENOTTY;
547         }
548         return err;
549 }
550
551 /* YSS225 initialization.
552
553    This code was developed using DOSEMU. The Turtle Beach SETUPSND
554    utility was run with I/O tracing in DOSEMU enabled, and a reconstruction
555    of the port I/O done, using the Yamaha faxback document as a guide
556    to add more logic to the code. Its really pretty weird.
557
558    There was an alternative approach of just dumping the whole I/O
559    sequence as a series of port/value pairs and a simple loop
560    that output it. However, I hope that eventually I'll get more
561    control over what this code does, and so I tried to stick with
562    a somewhat "algorithmic" approach.
563 */
564
565
566 int __init
567 snd_wavefront_fx_start (snd_wavefront_t *dev)
568
569 {
570         unsigned int i, j;
571
572         /* Set all bits for all channels on the MOD unit to zero */
573         /* XXX But why do this twice ? */
574
575         for (j = 0; j < 2; j++) {
576                 for (i = 0x10; i <= 0xff; i++) {
577             
578                         if (!wavefront_fx_idle (dev)) {
579                                 return (-1);
580                         }
581             
582                         outb (i, dev->fx_mod_addr);
583                         outb (0x0, dev->fx_mod_data);
584                 }
585         }
586
587         if (!wavefront_fx_idle (dev)) return (-1);
588         outb (0x02, dev->fx_op);                        /* mute on */
589
590         if (!wavefront_fx_idle (dev)) return (-1);
591         outb (0x07, dev->fx_dsp_page);
592         outb (0x44, dev->fx_dsp_addr);
593         outb (0x00, dev->fx_dsp_msb);
594         outb (0x00, dev->fx_dsp_lsb);
595         if (!wavefront_fx_idle (dev)) return (-1);
596         outb (0x07, dev->fx_dsp_page);
597         outb (0x42, dev->fx_dsp_addr);
598         outb (0x00, dev->fx_dsp_msb);
599         outb (0x00, dev->fx_dsp_lsb);
600         if (!wavefront_fx_idle (dev)) return (-1);
601         outb (0x07, dev->fx_dsp_page);
602         outb (0x43, dev->fx_dsp_addr);
603         outb (0x00, dev->fx_dsp_msb);
604         outb (0x00, dev->fx_dsp_lsb);
605         if (!wavefront_fx_idle (dev)) return (-1);
606         outb (0x07, dev->fx_dsp_page);
607         outb (0x7c, dev->fx_dsp_addr);
608         outb (0x00, dev->fx_dsp_msb);
609         outb (0x00, dev->fx_dsp_lsb);
610         if (!wavefront_fx_idle (dev)) return (-1);
611         outb (0x07, dev->fx_dsp_page);
612         outb (0x7e, dev->fx_dsp_addr);
613         outb (0x00, dev->fx_dsp_msb);
614         outb (0x00, dev->fx_dsp_lsb);
615         if (!wavefront_fx_idle (dev)) return (-1);
616         outb (0x07, dev->fx_dsp_page);
617         outb (0x46, dev->fx_dsp_addr);
618         outb (0x00, dev->fx_dsp_msb);
619         outb (0x00, dev->fx_dsp_lsb);
620         if (!wavefront_fx_idle (dev)) return (-1);
621         outb (0x07, dev->fx_dsp_page);
622         outb (0x49, dev->fx_dsp_addr);
623         outb (0x00, dev->fx_dsp_msb);
624         outb (0x00, dev->fx_dsp_lsb);
625         if (!wavefront_fx_idle (dev)) return (-1);
626         outb (0x07, dev->fx_dsp_page);
627         outb (0x47, dev->fx_dsp_addr);
628         outb (0x00, dev->fx_dsp_msb);
629         outb (0x00, dev->fx_dsp_lsb);
630         if (!wavefront_fx_idle (dev)) return (-1);
631         outb (0x07, dev->fx_dsp_page);
632         outb (0x4a, dev->fx_dsp_addr);
633         outb (0x00, dev->fx_dsp_msb);
634         outb (0x00, dev->fx_dsp_lsb);
635
636         /* either because of stupidity by TB's programmers, or because it
637            actually does something, rezero the MOD page.
638         */
639         for (i = 0x10; i <= 0xff; i++) {
640         
641                 if (!wavefront_fx_idle (dev)) {
642                         return (-1);
643                 }
644         
645                 outb (i, dev->fx_mod_addr);
646                 outb (0x0, dev->fx_mod_data);
647         }
648         /* load page zero */
649
650         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
651         outb (0x00, dev->fx_dsp_page);
652         outb (0x00, dev->fx_dsp_addr);
653
654         for (i = 0; i < sizeof (page_zero); i += 2) {
655                 outb (page_zero[i], dev->fx_dsp_msb);
656                 outb (page_zero[i+1], dev->fx_dsp_lsb);
657                 if (!wavefront_fx_idle (dev)) return (-1);
658         }
659
660         /* Now load page one */
661
662         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
663         outb (0x01, dev->fx_dsp_page);
664         outb (0x00, dev->fx_dsp_addr);
665
666         for (i = 0; i < sizeof (page_one); i += 2) {
667                 outb (page_one[i], dev->fx_dsp_msb);
668                 outb (page_one[i+1], dev->fx_dsp_lsb);
669                 if (!wavefront_fx_idle (dev)) return (-1);
670         }
671     
672         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
673         outb (0x02, dev->fx_dsp_page);
674         outb (0x00, dev->fx_dsp_addr);
675
676         for (i = 0; i < sizeof (page_two); i++) {
677                 outb (page_two[i], dev->fx_dsp_lsb);
678                 if (!wavefront_fx_idle (dev)) return (-1);
679         }
680     
681         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
682         outb (0x03, dev->fx_dsp_page);
683         outb (0x00, dev->fx_dsp_addr);
684
685         for (i = 0; i < sizeof (page_three); i++) {
686                 outb (page_three[i], dev->fx_dsp_lsb);
687                 if (!wavefront_fx_idle (dev)) return (-1);
688         }
689     
690         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
691         outb (0x04, dev->fx_dsp_page);
692         outb (0x00, dev->fx_dsp_addr);
693
694         for (i = 0; i < sizeof (page_four); i++) {
695                 outb (page_four[i], dev->fx_dsp_lsb);
696                 if (!wavefront_fx_idle (dev)) return (-1);
697         }
698
699         /* Load memory area (page six) */
700     
701         outb (FX_LSB_TRANSFER, dev->fx_lcr); 
702         outb (0x06, dev->fx_dsp_page); 
703
704         for (i = 0; i < sizeof (page_six); i += 3) {
705                 outb (page_six[i], dev->fx_dsp_addr);
706                 outb (page_six[i+1], dev->fx_dsp_msb);
707                 outb (page_six[i+2], dev->fx_dsp_lsb);
708                 if (!wavefront_fx_idle (dev)) return (-1);
709         }
710     
711         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
712         outb (0x07, dev->fx_dsp_page);
713         outb (0x00, dev->fx_dsp_addr);
714
715         for (i = 0; i < sizeof (page_seven); i += 2) {
716                 outb (page_seven[i], dev->fx_dsp_msb);
717                 outb (page_seven[i+1], dev->fx_dsp_lsb);
718                 if (!wavefront_fx_idle (dev)) return (-1);
719         }
720
721         /* Now setup the MOD area. We do this algorithmically in order to
722            save a little data space. It could be done in the same fashion
723            as the "pages".
724         */
725
726         for (i = 0x00; i <= 0x0f; i++) {
727                 outb (0x01, dev->fx_mod_addr);
728                 outb (i, dev->fx_mod_data);
729                 if (!wavefront_fx_idle (dev)) return (-1);
730                 outb (0x02, dev->fx_mod_addr);
731                 outb (0x00, dev->fx_mod_data);
732                 if (!wavefront_fx_idle (dev)) return (-1);
733         }
734
735         for (i = 0xb0; i <= 0xbf; i++) {
736                 outb (i, dev->fx_mod_addr);
737                 outb (0x20, dev->fx_mod_data);
738                 if (!wavefront_fx_idle (dev)) return (-1);
739         }
740
741         for (i = 0xf0; i <= 0xff; i++) {
742                 outb (i, dev->fx_mod_addr);
743                 outb (0x20, dev->fx_mod_data);
744                 if (!wavefront_fx_idle (dev)) return (-1);
745         }
746
747         for (i = 0x10; i <= 0x1d; i++) {
748                 outb (i, dev->fx_mod_addr);
749                 outb (0xff, dev->fx_mod_data);
750                 if (!wavefront_fx_idle (dev)) return (-1);
751         }
752
753         outb (0x1e, dev->fx_mod_addr);
754         outb (0x40, dev->fx_mod_data);
755         if (!wavefront_fx_idle (dev)) return (-1);
756
757         for (i = 0x1f; i <= 0x2d; i++) {
758                 outb (i, dev->fx_mod_addr);
759                 outb (0xff, dev->fx_mod_data);
760                 if (!wavefront_fx_idle (dev)) return (-1);
761         }
762
763         outb (0x2e, dev->fx_mod_addr);
764         outb (0x00, dev->fx_mod_data);
765         if (!wavefront_fx_idle (dev)) return (-1);
766
767         for (i = 0x2f; i <= 0x3e; i++) {
768                 outb (i, dev->fx_mod_addr);
769                 outb (0x00, dev->fx_mod_data);
770                 if (!wavefront_fx_idle (dev)) return (-1);
771         }
772
773         outb (0x3f, dev->fx_mod_addr);
774         outb (0x20, dev->fx_mod_data);
775         if (!wavefront_fx_idle (dev)) return (-1);
776
777         for (i = 0x40; i <= 0x4d; i++) {
778                 outb (i, dev->fx_mod_addr);
779                 outb (0x00, dev->fx_mod_data);
780                 if (!wavefront_fx_idle (dev)) return (-1);
781         }
782
783         outb (0x4e, dev->fx_mod_addr);
784         outb (0x0e, dev->fx_mod_data);
785         if (!wavefront_fx_idle (dev)) return (-1);
786         outb (0x4f, dev->fx_mod_addr);
787         outb (0x0e, dev->fx_mod_data);
788         if (!wavefront_fx_idle (dev)) return (-1);
789
790
791         for (i = 0x50; i <= 0x6b; i++) {
792                 outb (i, dev->fx_mod_addr);
793                 outb (0x00, dev->fx_mod_data);
794                 if (!wavefront_fx_idle (dev)) return (-1);
795         }
796
797         outb (0x6c, dev->fx_mod_addr);
798         outb (0x40, dev->fx_mod_data);
799         if (!wavefront_fx_idle (dev)) return (-1);
800
801         outb (0x6d, dev->fx_mod_addr);
802         outb (0x00, dev->fx_mod_data);
803         if (!wavefront_fx_idle (dev)) return (-1);
804
805         outb (0x6e, dev->fx_mod_addr);
806         outb (0x40, dev->fx_mod_data);
807         if (!wavefront_fx_idle (dev)) return (-1);
808
809         outb (0x6f, dev->fx_mod_addr);
810         outb (0x40, dev->fx_mod_data);
811         if (!wavefront_fx_idle (dev)) return (-1);
812
813         for (i = 0x70; i <= 0x7f; i++) {
814                 outb (i, dev->fx_mod_addr);
815                 outb (0xc0, dev->fx_mod_data);
816                 if (!wavefront_fx_idle (dev)) return (-1);
817         }
818     
819         for (i = 0x80; i <= 0xaf; i++) {
820                 outb (i, dev->fx_mod_addr);
821                 outb (0x00, dev->fx_mod_data);
822                 if (!wavefront_fx_idle (dev)) return (-1);
823         }
824
825         for (i = 0xc0; i <= 0xdd; i++) {
826                 outb (i, dev->fx_mod_addr);
827                 outb (0x00, dev->fx_mod_data);
828                 if (!wavefront_fx_idle (dev)) return (-1);
829         }
830
831         outb (0xde, dev->fx_mod_addr);
832         outb (0x10, dev->fx_mod_data);
833         if (!wavefront_fx_idle (dev)) return (-1);
834         outb (0xdf, dev->fx_mod_addr);
835         outb (0x10, dev->fx_mod_data);
836         if (!wavefront_fx_idle (dev)) return (-1);
837
838         for (i = 0xe0; i <= 0xef; i++) {
839                 outb (i, dev->fx_mod_addr);
840                 outb (0x00, dev->fx_mod_data);
841                 if (!wavefront_fx_idle (dev)) return (-1);
842         }
843
844         for (i = 0x00; i <= 0x0f; i++) {
845                 outb (0x01, dev->fx_mod_addr);
846                 outb (i, dev->fx_mod_data);
847                 outb (0x02, dev->fx_mod_addr);
848                 outb (0x01, dev->fx_mod_data);
849                 if (!wavefront_fx_idle (dev)) return (-1);
850         }
851
852         outb (0x02, dev->fx_op); /* mute on */
853
854         /* Now set the coefficients and so forth for the programs above */
855
856         for (i = 0; i < sizeof (coefficients); i += 4) {
857                 outb (coefficients[i], dev->fx_dsp_page);
858                 outb (coefficients[i+1], dev->fx_dsp_addr);
859                 outb (coefficients[i+2], dev->fx_dsp_msb);
860                 outb (coefficients[i+3], dev->fx_dsp_lsb);
861                 if (!wavefront_fx_idle (dev)) return (-1);
862         }
863
864         /* Some settings (?) that are too small to bundle into loops */
865
866         if (!wavefront_fx_idle (dev)) return (-1);
867         outb (0x1e, dev->fx_mod_addr);
868         outb (0x14, dev->fx_mod_data);
869         if (!wavefront_fx_idle (dev)) return (-1);
870         outb (0xde, dev->fx_mod_addr);
871         outb (0x20, dev->fx_mod_data);
872         if (!wavefront_fx_idle (dev)) return (-1);
873         outb (0xdf, dev->fx_mod_addr);
874         outb (0x20, dev->fx_mod_data);
875     
876         /* some more coefficients */
877
878         if (!wavefront_fx_idle (dev)) return (-1);
879         outb (0x06, dev->fx_dsp_page);
880         outb (0x78, dev->fx_dsp_addr);
881         outb (0x00, dev->fx_dsp_msb);
882         outb (0x40, dev->fx_dsp_lsb);
883         if (!wavefront_fx_idle (dev)) return (-1);
884         outb (0x07, dev->fx_dsp_page);
885         outb (0x03, dev->fx_dsp_addr);
886         outb (0x0f, dev->fx_dsp_msb);
887         outb (0xff, dev->fx_dsp_lsb);
888         if (!wavefront_fx_idle (dev)) return (-1);
889         outb (0x07, dev->fx_dsp_page);
890         outb (0x0b, dev->fx_dsp_addr);
891         outb (0x0f, dev->fx_dsp_msb);
892         outb (0xff, dev->fx_dsp_lsb);
893         if (!wavefront_fx_idle (dev)) return (-1);
894         outb (0x07, dev->fx_dsp_page);
895         outb (0x02, dev->fx_dsp_addr);
896         outb (0x00, dev->fx_dsp_msb);
897         outb (0x00, dev->fx_dsp_lsb);
898         if (!wavefront_fx_idle (dev)) return (-1);
899         outb (0x07, dev->fx_dsp_page);
900         outb (0x0a, dev->fx_dsp_addr);
901         outb (0x00, dev->fx_dsp_msb);
902         outb (0x00, dev->fx_dsp_lsb);
903         if (!wavefront_fx_idle (dev)) return (-1);
904         outb (0x07, dev->fx_dsp_page);
905         outb (0x46, dev->fx_dsp_addr);
906         outb (0x00, dev->fx_dsp_msb);
907         outb (0x00, dev->fx_dsp_lsb);
908         if (!wavefront_fx_idle (dev)) return (-1);
909         outb (0x07, dev->fx_dsp_page);
910         outb (0x49, dev->fx_dsp_addr);
911         outb (0x00, dev->fx_dsp_msb);
912         outb (0x00, dev->fx_dsp_lsb);
913     
914         /* Now, for some strange reason, lets reload every page
915            and all the coefficients over again. I have *NO* idea
916            why this is done. I do know that no sound is produced
917            is this phase is omitted.
918         */
919
920         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
921         outb (0x00, dev->fx_dsp_page);  
922         outb (0x10, dev->fx_dsp_addr);
923
924         for (i = 0; i < sizeof (page_zero_v2); i += 2) {
925                 outb (page_zero_v2[i], dev->fx_dsp_msb);
926                 outb (page_zero_v2[i+1], dev->fx_dsp_lsb);
927                 if (!wavefront_fx_idle (dev)) return (-1);
928         }
929     
930         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
931         outb (0x01, dev->fx_dsp_page);
932         outb (0x10, dev->fx_dsp_addr);
933
934         for (i = 0; i < sizeof (page_one_v2); i += 2) {
935                 outb (page_one_v2[i], dev->fx_dsp_msb);
936                 outb (page_one_v2[i+1], dev->fx_dsp_lsb);
937                 if (!wavefront_fx_idle (dev)) return (-1);
938         }
939     
940         if (!wavefront_fx_idle (dev)) return (-1);
941         if (!wavefront_fx_idle (dev)) return (-1);
942     
943         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
944         outb (0x02, dev->fx_dsp_page);
945         outb (0x10, dev->fx_dsp_addr);
946
947         for (i = 0; i < sizeof (page_two_v2); i++) {
948                 outb (page_two_v2[i], dev->fx_dsp_lsb);
949                 if (!wavefront_fx_idle (dev)) return (-1);
950         }
951         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
952         outb (0x03, dev->fx_dsp_page);
953         outb (0x10, dev->fx_dsp_addr);
954
955         for (i = 0; i < sizeof (page_three_v2); i++) {
956                 outb (page_three_v2[i], dev->fx_dsp_lsb);
957                 if (!wavefront_fx_idle (dev)) return (-1);
958         }
959     
960         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
961         outb (0x04, dev->fx_dsp_page);
962         outb (0x10, dev->fx_dsp_addr);
963
964         for (i = 0; i < sizeof (page_four_v2); i++) {
965                 outb (page_four_v2[i], dev->fx_dsp_lsb);
966                 if (!wavefront_fx_idle (dev)) return (-1);
967         }
968     
969         outb (FX_LSB_TRANSFER, dev->fx_lcr);
970         outb (0x06, dev->fx_dsp_page);
971
972         /* Page six v.2 is algorithmic */
973     
974         for (i = 0x10; i <= 0x3e; i += 2) {
975                 outb (i, dev->fx_dsp_addr);
976                 outb (0x00, dev->fx_dsp_msb);
977                 outb (0x00, dev->fx_dsp_lsb);
978                 if (!wavefront_fx_idle (dev)) return (-1);
979         }
980
981         outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
982         outb (0x07, dev->fx_dsp_page);
983         outb (0x10, dev->fx_dsp_addr);
984
985         for (i = 0; i < sizeof (page_seven_v2); i += 2) {
986                 outb (page_seven_v2[i], dev->fx_dsp_msb);
987                 outb (page_seven_v2[i+1], dev->fx_dsp_lsb);
988                 if (!wavefront_fx_idle (dev)) return (-1);
989         }
990
991         for (i = 0x00; i < sizeof(mod_v2); i += 2) {
992                 outb (mod_v2[i], dev->fx_mod_addr);
993                 outb (mod_v2[i+1], dev->fx_mod_data);
994                 if (!wavefront_fx_idle (dev)) return (-1);
995         }
996
997         for (i = 0; i < sizeof (coefficients2); i += 4) {
998                 outb (coefficients2[i], dev->fx_dsp_page);
999                 outb (coefficients2[i+1], dev->fx_dsp_addr);
1000                 outb (coefficients2[i+2], dev->fx_dsp_msb);
1001                 outb (coefficients2[i+3], dev->fx_dsp_lsb);
1002                 if (!wavefront_fx_idle (dev)) return (-1);
1003         }
1004
1005         for (i = 0; i < sizeof (coefficients3); i += 2) {
1006                 int x;
1007
1008                 outb (0x07, dev->fx_dsp_page);
1009                 x = (i % 4) ? 0x4e : 0x4c;
1010                 outb (x, dev->fx_dsp_addr);
1011                 outb (coefficients3[i], dev->fx_dsp_msb);
1012                 outb (coefficients3[i+1], dev->fx_dsp_lsb);
1013         }
1014
1015         outb (0x00, dev->fx_op); /* mute off */
1016         if (!wavefront_fx_idle (dev)) return (-1);
1017
1018         return (0);
1019 }