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