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