9045a4bf193b75d3f8885e2388b511bd43e25ad9
[linux-2.6.git] / sound / pci / au88x0 / au88x0_eq.c
1 /***************************************************************************
2  *            au88x0_eq.c
3  *  Aureal Vortex Hardware EQ control/access.
4  *
5  *  Sun Jun  8 18:19:19 2003
6  *  2003  Manuel Jander (mjander@users.sourceforge.net)
7  *  
8  *  02 July 2003: First time something works :)
9  *  November 2003: A3D Bypass code completed but untested.
10  *
11  *  TODO:
12  *     - Debug (testing)
13  *     - Test peak visualization support.
14  *
15  ****************************************************************************/
16
17 /*
18  *  This program is free software; you can redistribute it and/or modify
19  *  it under the terms of the GNU General Public License as published by
20  *  the Free Software Foundation; either version 2 of the License, or
21  *  (at your option) any later version.
22  *
23  *  This program is distributed in the hope that it will be useful,
24  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
25  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26  *  GNU Library General Public License for more details.
27  *
28  *  You should have received a copy of the GNU General Public License
29  *  along with this program; if not, write to the Free Software
30  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31  */
32
33 /*
34  The Aureal Hardware EQ is found on AU8810 and AU8830 chips only.
35  it has 4 inputs (2 for general mix, 2 for A3D) and 2 outputs (supposed 
36  to be routed to the codec).
37 */
38
39 #include "au88x0.h"
40 #include "au88x0_eq.h"
41 #include "au88x0_eqdata.c"
42
43 #define VORTEX_EQ_BASE   0x2b000
44 #define VORTEX_EQ_DEST   (VORTEX_EQ_BASE + 0x410)
45 #define VORTEX_EQ_SOURCE (VORTEX_EQ_BASE + 0x430)
46 #define VORTEX_EQ_CTRL   (VORTEX_EQ_BASE + 0x440)
47
48 /* CEqHw.s */
49 static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level)
50 {
51         hwwrite(vortex->mmio, 0x2b3c4, gain);
52         hwwrite(vortex->mmio, 0x2b3c8, level);
53 }
54
55 static inline short sign_invert(short a)
56 {
57         /* -(-32768) -> -32768 so we do -(-32768) -> 32767 to make the result positive */
58         if (a == -32768)
59                 return 32767;
60         else
61                 return -a;
62 }
63
64 static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 coefs[])
65 {
66         eqhw_t *eqhw = &(vortex->eq.this04);
67         int i = 0, n /*esp2c */;
68
69         for (n = 0; n < eqhw->this04; n++) {
70                 hwwrite(vortex->mmio, 0x2b000 + n * 0x30, coefs[i + 0]);
71                 hwwrite(vortex->mmio, 0x2b004 + n * 0x30, coefs[i + 1]);
72
73                 if (eqhw->this08 == 0) {
74                         hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2] & 0xffff);
75                         hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3] & 0xffff);
76                         hwwrite(vortex->mmio, 0x2b010 + n * 0x30, coefs[i + 4] & 0xffff);
77                 } else {
78                         hwwrite(vortex->mmio, 0x2b008 + n * 0x30, sign_invert(coefs[2 + i]) & 0xffff);
79                         hwwrite(vortex->mmio, 0x2b00c + n * 0x30, sign_invert(coefs[3 + i]) & 0xffff);
80                         hwwrite(vortex->mmio, 0x2b010 + n * 0x30, sign_invert(coefs[4 + i]) & 0xffff);
81                 }
82                 i += 5;
83         }
84 }
85
86 static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 coefs[])
87 {
88         eqhw_t *eqhw = &(vortex->eq.this04);
89         int i = 0, n /*esp2c */;
90
91         for (n = 0; n < eqhw->this04; n++) {
92                 hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, coefs[0 + i]);
93                 hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, coefs[1 + i]);
94
95                 if (eqhw->this08 == 0) {
96                         hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i] & 0xffff);
97                         hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i] & 0xffff);
98                         hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, coefs[4 + i] & 0xffff);
99                 } else {
100                         hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, sign_invert(coefs[2 + i]) & 0xffff);
101                         hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, sign_invert(coefs[3 + i]) & 0xffff);
102                         hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, sign_invert(coefs[4 + i]) & 0xffff);
103                 }
104                 i += 5;
105         }
106
107 }
108
109 static void vortex_EqHw_SetLeftStates(vortex_t * vortex, u16 a[], u16 b[])
110 {
111         eqhw_t *eqhw = &(vortex->eq.this04);
112         int i = 0, ebx;
113
114         hwwrite(vortex->mmio, 0x2b3fc, a[0]);
115         hwwrite(vortex->mmio, 0x2b400, a[1]);
116
117         for (ebx = 0; ebx < eqhw->this04; ebx++) {
118                 hwwrite(vortex->mmio, 0x2b014 + (i * 0xc), b[i]);
119                 hwwrite(vortex->mmio, 0x2b018 + (i * 0xc), b[1 + i]);
120                 hwwrite(vortex->mmio, 0x2b01c + (i * 0xc), b[2 + i]);
121                 hwwrite(vortex->mmio, 0x2b020 + (i * 0xc), b[3 + i]);
122                 i += 4;
123         }
124 }
125
126 static void vortex_EqHw_SetRightStates(vortex_t * vortex, u16 a[], u16 b[])
127 {
128         eqhw_t *eqhw = &(vortex->eq.this04);
129         int i = 0, ebx;
130
131         hwwrite(vortex->mmio, 0x2b404, a[0]);
132         hwwrite(vortex->mmio, 0x2b408, a[1]);
133
134         for (ebx = 0; ebx < eqhw->this04; ebx++) {
135                 hwwrite(vortex->mmio, 0x2b1f4 + (i * 0xc), b[i]);
136                 hwwrite(vortex->mmio, 0x2b1f8 + (i * 0xc), b[1 + i]);
137                 hwwrite(vortex->mmio, 0x2b1fc + (i * 0xc), b[2 + i]);
138                 hwwrite(vortex->mmio, 0x2b200 + (i * 0xc), b[3 + i]);
139                 i += 4;
140         }
141 }
142
143 #if 0
144 static void vortex_EqHw_GetTimeConsts(vortex_t * vortex, u16 * a, u16 * b)
145 {
146         *a = hwread(vortex->mmio, 0x2b3c4);
147         *b = hwread(vortex->mmio, 0x2b3c8);
148 }
149
150 static void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[])
151 {
152
153 }
154
155 static void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[])
156 {
157
158 }
159
160 static void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[])
161 {
162
163 }
164
165 static void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[])
166 {
167
168 }
169
170 #endif
171 /* Mix Gains */
172 static void vortex_EqHw_SetBypassGain(vortex_t * vortex, u16 a, u16 b)
173 {
174         eqhw_t *eqhw = &(vortex->eq.this04);
175         if (eqhw->this08 == 0) {
176                 hwwrite(vortex->mmio, 0x2b3d4, a);
177                 hwwrite(vortex->mmio, 0x2b3ec, b);
178         } else {
179                 hwwrite(vortex->mmio, 0x2b3d4, sign_invert(a) & 0xffff);
180                 hwwrite(vortex->mmio, 0x2b3ec, sign_invert(b) & 0xffff);
181         }
182 }
183
184 static void vortex_EqHw_SetA3DBypassGain(vortex_t * vortex, u16 a, u16 b)
185 {
186
187         hwwrite(vortex->mmio, 0x2b3e0, a);
188         hwwrite(vortex->mmio, 0x2b3f8, b);
189 }
190
191 #if 0
192 static void vortex_EqHw_SetCurrBypassGain(vortex_t * vortex, u16 a, u16 b)
193 {
194
195         hwwrite(vortex->mmio, 0x2b3d0, a);
196         hwwrite(vortex->mmio, 0x2b3e8, b);
197 }
198
199 static void vortex_EqHw_SetCurrA3DBypassGain(vortex_t * vortex, u16 a, u16 b)
200 {
201
202         hwwrite(vortex->mmio, 0x2b3dc, a);
203         hwwrite(vortex->mmio, 0x2b3f4, b);
204 }
205
206 #endif
207 static void
208 vortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
209 {
210         hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b);
211 }
212
213 static void
214 vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
215 {
216         hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
217 }
218
219 static void vortex_EqHw_SetLeftGainsTarget(vortex_t * vortex, u16 a[])
220 {
221         eqhw_t *eqhw = &(vortex->eq.this04);
222         int ebx;
223
224         for (ebx = 0; ebx < eqhw->this04; ebx++) {
225                 hwwrite(vortex->mmio, 0x2b02c + ebx * 0x30, a[ebx]);
226         }
227 }
228
229 static void vortex_EqHw_SetRightGainsTarget(vortex_t * vortex, u16 a[])
230 {
231         eqhw_t *eqhw = &(vortex->eq.this04);
232         int ebx;
233
234         for (ebx = 0; ebx < eqhw->this04; ebx++) {
235                 hwwrite(vortex->mmio, 0x2b20c + ebx * 0x30, a[ebx]);
236         }
237 }
238
239 static void vortex_EqHw_SetLeftGainsCurrent(vortex_t * vortex, u16 a[])
240 {
241         eqhw_t *eqhw = &(vortex->eq.this04);
242         int ebx;
243
244         for (ebx = 0; ebx < eqhw->this04; ebx++) {
245                 hwwrite(vortex->mmio, 0x2b028 + ebx * 0x30, a[ebx]);
246         }
247 }
248
249 static void vortex_EqHw_SetRightGainsCurrent(vortex_t * vortex, u16 a[])
250 {
251         eqhw_t *eqhw = &(vortex->eq.this04);
252         int ebx;
253
254         for (ebx = 0; ebx < eqhw->this04; ebx++) {
255                 hwwrite(vortex->mmio, 0x2b208 + ebx * 0x30, a[ebx]);
256         }
257 }
258
259 #if 0
260 static void vortex_EqHw_GetLeftGainsTarget(vortex_t * vortex, u16 a[])
261 {
262         eqhw_t *eqhw = &(vortex->eq.this04);
263         int ebx = 0;
264
265         if (eqhw->this04 < 0)
266                 return;
267
268         do {
269                 a[ebx] = hwread(vortex->mmio, 0x2b02c + ebx * 0x30);
270                 ebx++;
271         }
272         while (ebx < eqhw->this04);
273 }
274
275 static void vortex_EqHw_GetRightGainsTarget(vortex_t * vortex, u16 a[])
276 {
277         eqhw_t *eqhw = &(vortex->eq.this04);
278         int ebx = 0;
279
280         if (eqhw->this04 < 0)
281                 return;
282
283         do {
284                 a[ebx] = hwread(vortex->mmio, 0x2b20c + ebx * 0x30);
285                 ebx++;
286         }
287         while (ebx < eqhw->this04);
288 }
289
290 static void vortex_EqHw_GetLeftGainsCurrent(vortex_t * vortex, u16 a[])
291 {
292         eqhw_t *eqhw = &(vortex->eq.this04);
293         int ebx = 0;
294
295         if (eqhw->this04 < 0)
296                 return;
297
298         do {
299                 a[ebx] = hwread(vortex->mmio, 0x2b028 + ebx * 0x30);
300                 ebx++;
301         }
302         while (ebx < eqhw->this04);
303 }
304
305 static void vortex_EqHw_GetRightGainsCurrent(vortex_t * vortex, u16 a[])
306 {
307         eqhw_t *eqhw = &(vortex->eq.this04);
308         int ebx = 0;
309
310         if (eqhw->this04 < 0)
311                 return;
312
313         do {
314                 a[ebx] = hwread(vortex->mmio, 0x2b208 + ebx * 0x30);
315                 ebx++;
316         }
317         while (ebx < eqhw->this04);
318 }
319
320 #endif
321 /* EQ band levels settings */
322 static void vortex_EqHw_SetLevels(vortex_t * vortex, u16 a[])
323 {
324         eqhw_t *eqhw = &(vortex->eq.this04);
325         int ebx;
326
327         for (ebx = 0; ebx < eqhw->this04; ebx++) {
328                 hwwrite(vortex->mmio, 0x2b024 + ebx * 0x30, a[ebx]);
329         }
330
331         hwwrite(vortex->mmio, 0x2b3cc, a[eqhw->this04]);
332         hwwrite(vortex->mmio, 0x2b3d8, a[eqhw->this04 + 1]);
333
334         for (ebx = 0; ebx < eqhw->this04; ebx++) {
335                 hwwrite(vortex->mmio, 0x2b204 + ebx * 0x30,
336                         a[ebx + (eqhw->this04 + 2)]);
337         }
338
339         hwwrite(vortex->mmio, 0x2b3e4, a[2 + (eqhw->this04 * 2)]);
340         hwwrite(vortex->mmio, 0x2b3f0, a[3 + (eqhw->this04 * 2)]);
341 }
342
343 #if 0
344 static void vortex_EqHw_GetLevels(vortex_t * vortex, u16 a[])
345 {
346         eqhw_t *eqhw = &(vortex->eq.this04);
347         int ebx;
348
349         if (eqhw->this04 < 0)
350                 return;
351
352         ebx = 0;
353         do {
354                 a[ebx] = hwread(vortex->mmio, 0x2b024 + ebx * 0x30);
355                 ebx++;
356         }
357         while (ebx < eqhw->this04);
358
359         a[eqhw->this04] = hwread(vortex->mmio, 0x2b3cc);
360         a[eqhw->this04 + 1] = hwread(vortex->mmio, 0x2b3d8);
361
362         ebx = 0;
363         do {
364                 a[ebx + (eqhw->this04 + 2)] =
365                     hwread(vortex->mmio, 0x2b204 + ebx * 0x30);
366                 ebx++;
367         }
368         while (ebx < eqhw->this04);
369
370         a[2 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3e4);
371         a[3 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3f0);
372 }
373
374 #endif
375 /* Global Control */
376 static void vortex_EqHw_SetControlReg(vortex_t * vortex, unsigned long reg)
377 {
378         hwwrite(vortex->mmio, 0x2b440, reg);
379 }
380
381 static void vortex_EqHw_SetSampleRate(vortex_t * vortex, int sr)
382 {
383         hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800);
384 }
385
386 #if 0
387 static void vortex_EqHw_GetControlReg(vortex_t * vortex, unsigned long *reg)
388 {
389         *reg = hwread(vortex->mmio, 0x2b440);
390 }
391
392 static void vortex_EqHw_GetSampleRate(vortex_t * vortex, int *sr)
393 {
394         *sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f;
395 }
396
397 #endif
398 static void vortex_EqHw_Enable(vortex_t * vortex)
399 {
400         hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
401 }
402
403 static void vortex_EqHw_Disable(vortex_t * vortex)
404 {
405         hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
406 }
407
408 /* Reset (zero) buffers */
409 static void vortex_EqHw_ZeroIO(vortex_t * vortex)
410 {
411         int i;
412         for (i = 0; i < 0x8; i++)
413                 hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
414         for (i = 0; i < 0x4; i++)
415                 hwwrite(vortex->mmio, VORTEX_EQ_SOURCE + (i << 2), 0x0);
416 }
417
418 static void vortex_EqHw_ZeroA3DIO(vortex_t * vortex)
419 {
420         int i;
421         for (i = 0; i < 0x4; i++)
422                 hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
423 }
424
425 static void vortex_EqHw_ZeroState(vortex_t * vortex)
426 {
427
428         vortex_EqHw_SetControlReg(vortex, 0);
429         vortex_EqHw_ZeroIO(vortex);
430         hwwrite(vortex->mmio, 0x2b3c0, 0);
431
432         vortex_EqHw_SetTimeConsts(vortex, 0, 0);
433
434         vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsZeros);
435         vortex_EqHw_SetRightCoefs(vortex, asEqCoefsZeros);
436
437         vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_zero);
438         vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_zero);
439         vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_zero);
440         vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_zero);
441
442         vortex_EqHw_SetBypassGain(vortex, 0, 0);
443         //vortex_EqHw_SetCurrBypassGain(vortex, 0, 0);
444         vortex_EqHw_SetA3DBypassGain(vortex, 0, 0);
445         //vortex_EqHw_SetCurrA3DBypassGain(vortex, 0, 0);
446         vortex_EqHw_SetLeftStates(vortex, eq_states_zero, asEqOutStateZeros);
447         vortex_EqHw_SetRightStates(vortex, eq_states_zero, asEqOutStateZeros);
448         vortex_EqHw_SetLevels(vortex, (u16 *) eq_levels);
449 }
450
451 /* Program coeficients as pass through */
452 static void vortex_EqHw_ProgramPipe(vortex_t * vortex)
453 {
454         vortex_EqHw_SetTimeConsts(vortex, 0, 0);
455
456         vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsPipes);
457         vortex_EqHw_SetRightCoefs(vortex, asEqCoefsPipes);
458
459         vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_current);
460         vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_current);
461         vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_current);
462         vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_current);
463 }
464
465 /* Program EQ block as 10 band Equalizer */
466 static void
467 vortex_EqHw_Program10Band(vortex_t * vortex, auxxEqCoeffSet_t * coefset)
468 {
469
470         vortex_EqHw_SetTimeConsts(vortex, 0xc, 0x7fe0);
471
472         vortex_EqHw_SetLeftCoefs(vortex, coefset->LeftCoefs);
473         vortex_EqHw_SetRightCoefs(vortex, coefset->RightCoefs);
474
475         vortex_EqHw_SetLeftGainsCurrent(vortex, coefset->LeftGains);
476
477         vortex_EqHw_SetRightGainsTarget(vortex, coefset->RightGains);
478         vortex_EqHw_SetLeftGainsTarget(vortex, coefset->LeftGains);
479
480         vortex_EqHw_SetRightGainsCurrent(vortex, coefset->RightGains);
481 }
482
483 /* Read all EQ peaks. (think VU meter) */
484 static void vortex_EqHw_GetTenBandLevels(vortex_t * vortex, u16 peaks[])
485 {
486         eqhw_t *eqhw = &(vortex->eq.this04);
487         int i;
488
489         if (eqhw->this04 <= 0)
490                 return;
491
492         for (i = 0; i < eqhw->this04; i++)
493                 peaks[i] = hwread(vortex->mmio, 0x2B024 + i * 0x30);
494         for (i = 0; i < eqhw->this04; i++)
495                 peaks[i + eqhw->this04] =
496                     hwread(vortex->mmio, 0x2B204 + i * 0x30);
497 }
498
499 /* CEqlzr.s */
500
501 static int vortex_Eqlzr_GetLeftGain(vortex_t * vortex, u16 index, u16 * gain)
502 {
503         eqlzr_t *eq = &(vortex->eq);
504
505         if (eq->this28) {
506                 *gain = eq->this130[index];
507                 return 0;
508         }
509         return 1;
510 }
511
512 static void vortex_Eqlzr_SetLeftGain(vortex_t * vortex, u16 index, u16 gain)
513 {
514         eqlzr_t *eq = &(vortex->eq);
515
516         if (eq->this28 == 0)
517                 return;
518
519         eq->this130[index] = gain;
520         if (eq->this54)
521                 return;
522
523         vortex_EqHw_SetLeftGainsSingleTarget(vortex, index, gain);
524 }
525
526 static int vortex_Eqlzr_GetRightGain(vortex_t * vortex, u16 index, u16 * gain)
527 {
528         eqlzr_t *eq = &(vortex->eq);
529
530         if (eq->this28) {
531                 *gain = eq->this130[index + eq->this10];
532                 return 0;
533         }
534         return 1;
535 }
536
537 static void vortex_Eqlzr_SetRightGain(vortex_t * vortex, u16 index, u16 gain)
538 {
539         eqlzr_t *eq = &(vortex->eq);
540
541         if (eq->this28 == 0)
542                 return;
543
544         eq->this130[index + eq->this10] = gain;
545         if (eq->this54)
546                 return;
547
548         vortex_EqHw_SetRightGainsSingleTarget(vortex, index, gain);
549 }
550
551 #if 0
552 static int
553 vortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, unsigned long *cnt)
554 {
555         eqlzr_t *eq = &(vortex->eq);
556         int si = 0;
557
558         if (eq->this10 == 0)
559                 return 1;
560
561         {
562                 if (vortex_Eqlzr_GetLeftGain(vortex, si, &gains[si]))
563                         return 1;
564                 if (vortex_Eqlzr_GetRightGain
565                     (vortex, si, &gains[si + eq->this10]))
566                         return 1;
567                 si++;
568         }
569         while (eq->this10 > si) ;
570         *cnt = si * 2;
571         return 0;
572 }
573 #endif
574 static int vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex_t * vortex)
575 {
576         eqlzr_t *eq = &(vortex->eq);
577
578         vortex_EqHw_SetLeftGainsTarget(vortex, eq->this130);
579         vortex_EqHw_SetRightGainsTarget(vortex, &(eq->this130[eq->this10]));
580
581         return 0;
582 }
583
584 static int
585 vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], unsigned long count)
586 {
587         eqlzr_t *eq = &(vortex->eq);
588         int i;
589
590         if (((eq->this10) * 2 != count) || (eq->this28 == 0))
591                 return 1;
592
593         for (i = 0; i < count; i++) {
594                 eq->this130[i] = gains[i];
595         }
596         
597         if (eq->this54)
598                 return 0;
599         return vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
600 }
601
602 static void
603 vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, unsigned long a,
604                               unsigned long b)
605 {
606         eqlzr_t *eq = &(vortex->eq);
607         int eax, ebx;
608
609         eq->this58 = a;
610         eq->this5c = b;
611         if (eq->this54)
612                 eax = eq->this0e;
613         else
614                 eax = eq->this0a;
615         ebx = (eax * eq->this58) >> 0x10;
616         eax = (eax * eq->this5c) >> 0x10;
617         vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax);
618 }
619
620 static void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex)
621 {
622         eqlzr_t *eq = &(vortex->eq);
623         int eax, ebx;
624
625         if (eq->this54)
626                 eax = eq->this0e;
627         else
628                 eax = eq->this0a;
629         ebx = (eax * eq->this58) >> 0x10;
630         eax = (eax * eq->this5c) >> 0x10;
631         vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax);
632 }
633
634 static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
635 {
636         if (vortex != NULL)
637                 vortex_EqHw_ZeroA3DIO(vortex);
638 }
639
640 static void vortex_Eqlzr_SetBypass(vortex_t * vortex, long bp)
641 {
642         eqlzr_t *eq = &(vortex->eq);
643         
644         if ((eq->this28) && (bp == 0)) {
645                 /* EQ enabled */
646                 vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
647                 vortex_EqHw_SetBypassGain(vortex, eq->this08, eq->this08);
648         } else {
649                 /* EQ disabled. */
650                 vortex_EqHw_SetLeftGainsTarget(vortex, (u16 *) (eq->this14));
651                 vortex_EqHw_SetRightGainsTarget(vortex, (u16 *) (eq->this14));
652                 vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c);
653         }
654         vortex_Eqlzr_ProgramA3dBypassGain(vortex);
655 }
656
657 static void vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex_t * vortex)
658 {
659         eqlzr_t *eq = &(vortex->eq);
660
661         /* Set EQ BiQuad filter coeficients */
662         memcpy(&(eq->coefset), &asEqCoefsNormal, sizeof(auxxEqCoeffSet_t));
663         /* Set EQ Band gain levels and dump into hardware registers. */
664         vortex_Eqlzr_SetAllBands(vortex, eq_gains_normal, eq->this10 * 2);
665 }
666
667 static int vortex_Eqlzr_GetAllPeaks(vortex_t * vortex, u16 * peaks, int *count)
668 {
669         eqlzr_t *eq = &(vortex->eq);
670
671         if (eq->this10 == 0)
672                 return 1;
673         *count = eq->this10 * 2;
674         vortex_EqHw_GetTenBandLevels(vortex, peaks);
675         return 0;
676 }
677
678 #if 0
679 static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
680 {
681         eqlzr_t *eq = &(vortex->eq);
682
683         return (&(eq->coefset));
684 }
685 #endif
686 static void vortex_Eqlzr_init(vortex_t * vortex)
687 {
688         eqlzr_t *eq = &(vortex->eq);
689
690         /* Object constructor */
691         //eq->this04 = 0;
692         eq->this08 = 0;         /* Bypass gain with EQ in use. */
693         eq->this0a = 0x5999;
694         eq->this0c = 0x5999;    /* Bypass gain with EQ disabled. */
695         eq->this0e = 0x5999;
696
697         eq->this10 = 0xa;       /* 10 eq frequency bands. */
698         eq->this04.this04 = eq->this10;
699         eq->this28 = 0x1;       /* if 1 => Allow read access to this130 (gains) */
700         eq->this54 = 0x0;       /* if 1 => Dont Allow access to hardware (gains) */
701         eq->this58 = 0xffff;
702         eq->this5c = 0xffff;
703
704         /* Set gains. */
705         memset(eq->this14, 0, 2 * 10);
706
707         /* Actual init. */
708         vortex_EqHw_ZeroState(vortex);
709         vortex_EqHw_SetSampleRate(vortex, 0x11);
710         vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex);
711
712         vortex_EqHw_Program10Band(vortex, &(eq->coefset));
713         vortex_Eqlzr_SetBypass(vortex, eq->this54);
714         vortex_Eqlzr_SetA3dBypassGain(vortex, 0, 0);
715         vortex_EqHw_Enable(vortex);
716 }
717
718 static void vortex_Eqlzr_shutdown(vortex_t * vortex)
719 {
720         vortex_Eqlzr_ShutDownA3d(vortex);
721         vortex_EqHw_ProgramPipe(vortex);
722         vortex_EqHw_Disable(vortex);
723 }
724
725 /* ALSA interface */
726
727 /* Control interface */
728 static int
729 snd_vortex_eqtoggle_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
730 {
731         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
732         uinfo->count = 1;
733         uinfo->value.integer.min = 0;
734         uinfo->value.integer.max = 1;
735         return 0;
736 }
737
738 static int
739 snd_vortex_eqtoggle_get(snd_kcontrol_t * kcontrol,
740                         snd_ctl_elem_value_t * ucontrol)
741 {
742         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
743         eqlzr_t *eq = &(vortex->eq);
744         //int i = kcontrol->private_value;
745
746         ucontrol->value.integer.value[0] = eq->this54 ? 0 : 1;
747
748         return 0;
749 }
750
751 static int
752 snd_vortex_eqtoggle_put(snd_kcontrol_t * kcontrol,
753                         snd_ctl_elem_value_t * ucontrol)
754 {
755         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
756         eqlzr_t *eq = &(vortex->eq);
757         //int i = kcontrol->private_value;
758
759         eq->this54 = ucontrol->value.integer.value[0] ? 0 : 1;
760         vortex_Eqlzr_SetBypass(vortex, eq->this54);
761
762         return 1;               /* Allways changes */
763 }
764
765 static snd_kcontrol_new_t vortex_eqtoggle_kcontrol __devinitdata = {
766         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
767         .name = "EQ Enable",
768         .index = 0,
769         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
770         .private_value = 0,
771         .info = snd_vortex_eqtoggle_info,
772         .get = snd_vortex_eqtoggle_get,
773         .put = snd_vortex_eqtoggle_put
774 };
775
776 static int
777 snd_vortex_eq_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
778 {
779         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
780         uinfo->count = 2;
781         uinfo->value.integer.min = 0x0000;
782         uinfo->value.integer.max = 0x7fff;
783         return 0;
784 }
785
786 static int
787 snd_vortex_eq_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
788 {
789         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
790         int i = kcontrol->private_value;
791         u16 gainL, gainR;
792
793         vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
794         vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
795         ucontrol->value.integer.value[0] = gainL;
796         ucontrol->value.integer.value[1] = gainR;
797         return 0;
798 }
799
800 static int
801 snd_vortex_eq_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
802 {
803         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
804         int changed = 0, i = kcontrol->private_value;
805         u16 gainL, gainR;
806
807         vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
808         vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
809
810         if (gainL != ucontrol->value.integer.value[0]) {
811                 vortex_Eqlzr_SetLeftGain(vortex, i,
812                                          ucontrol->value.integer.value[0]);
813                 changed = 1;
814         }
815         if (gainR != ucontrol->value.integer.value[1]) {
816                 vortex_Eqlzr_SetRightGain(vortex, i,
817                                           ucontrol->value.integer.value[1]);
818                 changed = 1;
819         }
820         return changed;
821 }
822
823 static snd_kcontrol_new_t vortex_eq_kcontrol __devinitdata = {
824         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
825         .name = "                        .",
826         .index = 0,
827         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
828         .private_value = 0,
829         .info = snd_vortex_eq_info,
830         .get = snd_vortex_eq_get,
831         .put = snd_vortex_eq_put
832 };
833
834 static int
835 snd_vortex_peaks_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
836 {
837         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
838         uinfo->count = 20;
839         uinfo->value.integer.min = 0x0000;
840         uinfo->value.integer.max = 0x7fff;
841         return 0;
842 }
843
844 static int
845 snd_vortex_peaks_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
846 {
847         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
848         int i, count;
849         u16 peaks[20];
850
851         vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count);
852         if (count != 20) {
853                 printk("vortex: peak count error 20 != %d \n", count);
854                 return -1;
855         }
856         for (i = 0; i < 20; i++)
857                 ucontrol->value.integer.value[i] = peaks[i];
858
859         return 0;
860 }
861
862 static snd_kcontrol_new_t vortex_levels_kcontrol __devinitdata = {
863         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
864         .name = "EQ Peaks",
865         .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
866         .info = snd_vortex_peaks_info,
867         .get = snd_vortex_peaks_get,
868 };
869
870 /* EQ band gain labels. */
871 static char *EqBandLabels[10] __devinitdata = {
872         "EQ0 31Hz\0",
873         "EQ1 63Hz\0",
874         "EQ2 125Hz\0",
875         "EQ3 250Hz\0",
876         "EQ4 500Hz\0",
877         "EQ5 1KHz\0",
878         "EQ6 2KHz\0",
879         "EQ7 4KHz\0",
880         "EQ8 8KHz\0",
881         "EQ9 16KHz\0",
882 };
883
884 /* ALSA driver entry points. Init and exit. */
885 static int vortex_eq_init(vortex_t * vortex)
886 {
887         snd_kcontrol_t *kcontrol;
888         int err, i;
889
890         vortex_Eqlzr_init(vortex);
891
892         if ((kcontrol =
893              snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex)) == NULL)
894                 return -ENOMEM;
895         kcontrol->private_value = 0;
896         if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
897                 return err;
898
899         /* EQ gain controls */
900         for (i = 0; i < 10; i++) {
901                 if ((kcontrol =
902                      snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL)
903                         return -ENOMEM;
904                 strcpy(kcontrol->id.name, EqBandLabels[i]);
905                 kcontrol->private_value = i;
906                 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
907                         return err;
908                 //vortex->eqctrl[i] = kcontrol;
909         }
910         /* EQ band levels */
911         if ((kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex)) == NULL)
912                 return -ENOMEM;
913         if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
914                 return err;
915
916         return 0;
917 }
918
919 static int vortex_eq_free(vortex_t * vortex)
920 {
921         /*
922            //FIXME: segfault because vortex->eqctrl[i] == 4
923            int i;
924            for (i=0; i<10; i++) {
925            if (vortex->eqctrl[i])
926            snd_ctl_remove(vortex->card, vortex->eqctrl[i]);
927            }
928          */
929         vortex_Eqlzr_shutdown(vortex);
930         return 0;
931 }
932
933 /* End */