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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 (snd_hwdep_t *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 (snd_hwdep_t *hw, struct file *file)
474 
475 {
476 	module_put(hw->card->module);
477 	return 0;
478 }
479 
480 int
481 snd_wavefront_fx_ioctl (snd_hwdep_t *sdev, struct file *file,
482 			unsigned int cmd, unsigned long arg)
483 
484 {
485 	snd_card_t *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 }
1020