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