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