patch-2_6_7-vs1_9_1_12
[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                 /* EQ enabled */
716                 vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
717                 vortex_EqHw_SetBypassGain(vortex, eq->this08, eq->this08);
718         } else {
719                 /* EQ disabled. */
720                 vortex_EqHw_SetLeftGainsTarget(vortex, (u16 *) (eq->this14));
721                 vortex_EqHw_SetRightGainsTarget(vortex, (u16 *) (eq->this14));
722                 vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c);
723         }
724         vortex_Eqlzr_ProgramA3dBypassGain(vortex);
725 }
726
727 static void vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex_t * vortex)
728 {
729         eqlzr_t *eq = &(vortex->eq);
730
731         /* Set EQ BiQuad filter coeficients */
732         memcpy(&(eq->coefset), &asEqCoefsNormal, sizeof(auxxEqCoeffSet_t));
733         /* Set EQ Band gain levels and dump into hardware registers. */
734         vortex_Eqlzr_SetAllBands(vortex, eq_gains_normal, eq->this10 * 2);
735 }
736
737 static int vortex_Eqlzr_GetAllPeaks(vortex_t * vortex, u16 * peaks, int *count)
738 {
739         eqlzr_t *eq = &(vortex->eq);
740
741         if (eq->this10 == 0)
742                 return 1;
743         *count = eq->this10 * 2;
744         vortex_EqHw_GetTenBandLevels(vortex, peaks);
745         return 0;
746 }
747
748 #if 0
749 static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
750 {
751         eqlzr_t *eq = &(vortex->eq);
752
753         return (&(eq->coefset));
754 }
755 #endif
756 static void vortex_Eqlzr_init(vortex_t * vortex)
757 {
758         eqlzr_t *eq = &(vortex->eq);
759
760         /* Object constructor */
761         //eq->this04 = 0;
762         eq->this08 = 0;         /* Bypass gain with EQ in use. */
763         eq->this0a = 0x5999;
764         eq->this0c = 0x5999;    /* Bypass gain with EQ disabled. */
765         eq->this0e = 0x5999;
766
767         eq->this10 = 0xa;       /* 10 eq frequency bands. */
768         eq->this04.this04 = eq->this10;
769         eq->this28 = 0x1;       /* if 1 => Allow read access to this130 (gains) */
770         eq->this54 = 0x0;       /* if 1 => Dont Allow access to hardware (gains) */
771         eq->this58 = 0xffff;
772         eq->this5c = 0xffff;
773
774         /* Set gains. */
775         memset(eq->this14, 0, 2 * 10);
776
777         /* Actual init. */
778         vortex_EqHw_ZeroState(vortex);
779         vortex_EqHw_SetSampleRate(vortex, 0x11);
780         vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex);
781
782         vortex_EqHw_Program10Band(vortex, &(eq->coefset));
783         vortex_Eqlzr_SetBypass(vortex, eq->this54);
784         vortex_Eqlzr_SetA3dBypassGain(vortex, 0, 0);
785         vortex_EqHw_Enable(vortex);
786 }
787
788 static void vortex_Eqlzr_shutdown(vortex_t * vortex)
789 {
790         vortex_Eqlzr_ShutDownA3d(vortex);
791         vortex_EqHw_ProgramPipe(vortex);
792         vortex_EqHw_Disable(vortex);
793 }
794
795 /* ALSA interface */
796
797 /* Control interface */
798 static int
799 snd_vortex_eqtoggle_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
800 {
801         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
802         uinfo->count = 1;
803         uinfo->value.integer.min = 0;
804         uinfo->value.integer.max = 1;
805         return 0;
806 }
807
808 static int
809 snd_vortex_eqtoggle_get(snd_kcontrol_t * kcontrol,
810                         snd_ctl_elem_value_t * ucontrol)
811 {
812         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
813         eqlzr_t *eq = &(vortex->eq);
814         //int i = kcontrol->private_value;
815
816         ucontrol->value.integer.value[0] = eq->this54 ? 0 : 1;
817
818         return 0;
819 }
820
821 static int
822 snd_vortex_eqtoggle_put(snd_kcontrol_t * kcontrol,
823                         snd_ctl_elem_value_t * ucontrol)
824 {
825         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
826         eqlzr_t *eq = &(vortex->eq);
827         //int i = kcontrol->private_value;
828
829         eq->this54 = ucontrol->value.integer.value[0] ? 0 : 1;
830         vortex_Eqlzr_SetBypass(vortex, eq->this54);
831
832         return 1;               /* Allways changes */
833 }
834
835 static snd_kcontrol_new_t vortex_eqtoggle_kcontrol __devinitdata = {
836         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
837         .name = "EQ Enable",
838         .index = 0,
839         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
840         .private_value = 0,
841         .info = snd_vortex_eqtoggle_info,
842         .get = snd_vortex_eqtoggle_get,
843         .put = snd_vortex_eqtoggle_put
844 };
845
846 static int
847 snd_vortex_eq_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
848 {
849         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
850         uinfo->count = 2;
851         uinfo->value.integer.min = 0x0000;
852         uinfo->value.integer.max = 0x7fff;
853         return 0;
854 }
855
856 static int
857 snd_vortex_eq_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
858 {
859         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
860         int i = kcontrol->private_value;
861         u16 gainL, gainR;
862
863         vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
864         vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
865         ucontrol->value.integer.value[0] = gainL;
866         ucontrol->value.integer.value[1] = gainR;
867         return 0;
868 }
869
870 static int
871 snd_vortex_eq_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
872 {
873         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
874         int changed = 0, i = kcontrol->private_value;
875         u16 gainL, gainR;
876
877         vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
878         vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
879
880         if (gainL != ucontrol->value.integer.value[0]) {
881                 vortex_Eqlzr_SetLeftGain(vortex, i,
882                                          ucontrol->value.integer.value[0]);
883                 changed = 1;
884         }
885         if (gainR != ucontrol->value.integer.value[1]) {
886                 vortex_Eqlzr_SetRightGain(vortex, i,
887                                           ucontrol->value.integer.value[1]);
888                 changed = 1;
889         }
890         return changed;
891 }
892
893 static snd_kcontrol_new_t vortex_eq_kcontrol __devinitdata = {
894         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
895         .name = "                        .",
896         .index = 0,
897         .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
898         .private_value = 0,
899         .info = snd_vortex_eq_info,
900         .get = snd_vortex_eq_get,
901         .put = snd_vortex_eq_put
902 };
903
904 static int
905 snd_vortex_peaks_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
906 {
907         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
908         uinfo->count = 20;
909         uinfo->value.integer.min = 0x0000;
910         uinfo->value.integer.max = 0x7fff;
911         return 0;
912 }
913
914 static int
915 snd_vortex_peaks_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
916 {
917         vortex_t *vortex = snd_kcontrol_chip(kcontrol);
918         int i, count;
919         u16 peaks[20];
920
921         vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count);
922         if (count != 20) {
923                 printk("vortex: peak count error 20 != %d \n", count);
924                 return -1;
925         }
926         for (i = 0; i < 20; i++)
927                 ucontrol->value.integer.value[i] = peaks[i];
928
929         return 0;
930 }
931
932 static snd_kcontrol_new_t vortex_levels_kcontrol __devinitdata = {
933         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
934         .name = "EQ Peaks",
935         .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
936         .info = snd_vortex_peaks_info,
937         .get = snd_vortex_peaks_get,
938 };
939
940 /* EQ band gain labels. */
941 static char *EqBandLabels[10] __devinitdata = {
942         "EQ0 31Hz\0",
943         "EQ1 63Hz\0",
944         "EQ2 125Hz\0",
945         "EQ3 250Hz\0",
946         "EQ4 500Hz\0",
947         "EQ5 1KHz\0",
948         "EQ6 2KHz\0",
949         "EQ7 4KHz\0",
950         "EQ8 8KHz\0",
951         "EQ9 16KHz\0",
952 };
953
954 /* ALSA driver entry points. Init and exit. */
955 static int vortex_eq_init(vortex_t * vortex)
956 {
957         snd_kcontrol_t *kcontrol;
958         int err, i;
959
960         vortex_Eqlzr_init(vortex);
961
962         if ((kcontrol =
963              snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex)) == NULL)
964                 return -ENOMEM;
965         kcontrol->private_value = 0;
966         if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
967                 return err;
968
969         /* EQ gain controls */
970         for (i = 0; i < 10; i++) {
971                 if ((kcontrol =
972                      snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL)
973                         return -ENOMEM;
974                 strcpy(kcontrol->id.name, EqBandLabels[i]);
975                 kcontrol->private_value = i;
976                 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
977                         return err;
978                 //vortex->eqctrl[i] = kcontrol;
979         }
980         /* EQ band levels */
981         if ((kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex)) == NULL)
982                 return -ENOMEM;
983         if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
984                 return err;
985
986         return 0;
987 }
988
989 static int vortex_eq_free(vortex_t * vortex)
990 {
991         /*
992            //FIXME: segfault because vortex->eqctrl[i] == 4
993            int i;
994            for (i=0; i<10; i++) {
995            if (vortex->eqctrl[i])
996            snd_ctl_remove(vortex->card, vortex->eqctrl[i]);
997            }
998          */
999         vortex_Eqlzr_shutdown(vortex);
1000         return 0;
1001 }
1002
1003 /* End */