HID: Use menuconfig objects
[pv_ops_mirror.git] / sound / pci / au88x0 / au88x0_eq.c
blob0c86a31c43362c0fb5401c116c815de25cd87b00
1 /***************************************************************************
2 * au88x0_eq.c
3 * Aureal Vortex Hardware EQ control/access.
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.
11 * TODO:
12 * - Debug (testing)
13 * - Test peak visualization support.
15 ****************************************************************************/
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.
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.
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.
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).
39 #include "au88x0.h"
40 #include "au88x0_eq.h"
41 #include "au88x0_eqdata.c"
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)
48 #define VORTEX_BAND_COEFF_SIZE 0x30
50 /* CEqHw.s */
51 static void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level)
53 hwwrite(vortex->mmio, 0x2b3c4, gain);
54 hwwrite(vortex->mmio, 0x2b3c8, level);
57 static inline u16 sign_invert(u16 a)
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;
66 static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 coefs[])
68 eqhw_t *eqhw = &(vortex->eq.this04);
69 int i = 0, n /*esp2c */;
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]);
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]));
84 i += 5;
88 static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 coefs[])
90 eqhw_t *eqhw = &(vortex->eq.this04);
91 int i = 0, n /*esp2c */;
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]);
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]));
106 i += 5;
111 static void vortex_EqHw_SetLeftStates(vortex_t * vortex, u16 a[], u16 b[])
113 eqhw_t *eqhw = &(vortex->eq.this04);
114 int i = 0, ebx;
116 hwwrite(vortex->mmio, 0x2b3fc, a[0]);
117 hwwrite(vortex->mmio, 0x2b400, a[1]);
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;
128 static void vortex_EqHw_SetRightStates(vortex_t * vortex, u16 a[], u16 b[])
130 eqhw_t *eqhw = &(vortex->eq.this04);
131 int i = 0, ebx;
133 hwwrite(vortex->mmio, 0x2b404, a[0]);
134 hwwrite(vortex->mmio, 0x2b408, a[1]);
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;
145 #if 0
146 static void vortex_EqHw_GetTimeConsts(vortex_t * vortex, u16 * a, u16 * b)
148 *a = hwread(vortex->mmio, 0x2b3c4);
149 *b = hwread(vortex->mmio, 0x2b3c8);
152 static void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[])
157 static void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[])
162 static void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[])
167 static void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[])
172 #endif
173 /* Mix Gains */
174 static void vortex_EqHw_SetBypassGain(vortex_t * vortex, u16 a, u16 b)
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));
186 static void vortex_EqHw_SetA3DBypassGain(vortex_t * vortex, u16 a, u16 b)
189 hwwrite(vortex->mmio, 0x2b3e0, a);
190 hwwrite(vortex->mmio, 0x2b3f8, b);
193 #if 0
194 static void vortex_EqHw_SetCurrBypassGain(vortex_t * vortex, u16 a, u16 b)
197 hwwrite(vortex->mmio, 0x2b3d0, a);
198 hwwrite(vortex->mmio, 0x2b3e8, b);
201 static void vortex_EqHw_SetCurrA3DBypassGain(vortex_t * vortex, u16 a, u16 b)
204 hwwrite(vortex->mmio, 0x2b3dc, a);
205 hwwrite(vortex->mmio, 0x2b3f4, b);
208 #endif
209 static void
210 vortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
212 hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b);
215 static void
216 vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
218 hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
221 static void vortex_EqHw_SetLeftGainsTarget(vortex_t * vortex, u16 a[])
223 eqhw_t *eqhw = &(vortex->eq.this04);
224 int ebx;
226 for (ebx = 0; ebx < eqhw->this04; ebx++) {
227 hwwrite(vortex->mmio, 0x2b02c + ebx * 0x30, a[ebx]);
231 static void vortex_EqHw_SetRightGainsTarget(vortex_t * vortex, u16 a[])
233 eqhw_t *eqhw = &(vortex->eq.this04);
234 int ebx;
236 for (ebx = 0; ebx < eqhw->this04; ebx++) {
237 hwwrite(vortex->mmio, 0x2b20c + ebx * 0x30, a[ebx]);
241 static void vortex_EqHw_SetLeftGainsCurrent(vortex_t * vortex, u16 a[])
243 eqhw_t *eqhw = &(vortex->eq.this04);
244 int ebx;
246 for (ebx = 0; ebx < eqhw->this04; ebx++) {
247 hwwrite(vortex->mmio, 0x2b028 + ebx * 0x30, a[ebx]);
251 static void vortex_EqHw_SetRightGainsCurrent(vortex_t * vortex, u16 a[])
253 eqhw_t *eqhw = &(vortex->eq.this04);
254 int ebx;
256 for (ebx = 0; ebx < eqhw->this04; ebx++) {
257 hwwrite(vortex->mmio, 0x2b208 + ebx * 0x30, a[ebx]);
261 #if 0
262 static void vortex_EqHw_GetLeftGainsTarget(vortex_t * vortex, u16 a[])
264 eqhw_t *eqhw = &(vortex->eq.this04);
265 int ebx = 0;
267 if (eqhw->this04 < 0)
268 return;
270 do {
271 a[ebx] = hwread(vortex->mmio, 0x2b02c + ebx * 0x30);
272 ebx++;
274 while (ebx < eqhw->this04);
277 static void vortex_EqHw_GetRightGainsTarget(vortex_t * vortex, u16 a[])
279 eqhw_t *eqhw = &(vortex->eq.this04);
280 int ebx = 0;
282 if (eqhw->this04 < 0)
283 return;
285 do {
286 a[ebx] = hwread(vortex->mmio, 0x2b20c + ebx * 0x30);
287 ebx++;
289 while (ebx < eqhw->this04);
292 static void vortex_EqHw_GetLeftGainsCurrent(vortex_t * vortex, u16 a[])
294 eqhw_t *eqhw = &(vortex->eq.this04);
295 int ebx = 0;
297 if (eqhw->this04 < 0)
298 return;
300 do {
301 a[ebx] = hwread(vortex->mmio, 0x2b028 + ebx * 0x30);
302 ebx++;
304 while (ebx < eqhw->this04);
307 static void vortex_EqHw_GetRightGainsCurrent(vortex_t * vortex, u16 a[])
309 eqhw_t *eqhw = &(vortex->eq.this04);
310 int ebx = 0;
312 if (eqhw->this04 < 0)
313 return;
315 do {
316 a[ebx] = hwread(vortex->mmio, 0x2b208 + ebx * 0x30);
317 ebx++;
319 while (ebx < eqhw->this04);
322 #endif
323 /* EQ band levels settings */
324 static void vortex_EqHw_SetLevels(vortex_t * vortex, u16 peaks[])
326 eqhw_t *eqhw = &(vortex->eq.this04);
327 int i;
329 /* set left peaks */
330 for (i = 0; i < eqhw->this04; i++) {
331 hwwrite(vortex->mmio, 0x2b024 + i * VORTEX_BAND_COEFF_SIZE, peaks[i]);
334 hwwrite(vortex->mmio, 0x2b3cc, peaks[eqhw->this04]);
335 hwwrite(vortex->mmio, 0x2b3d8, peaks[eqhw->this04 + 1]);
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)]);
343 hwwrite(vortex->mmio, 0x2b3e4, peaks[2 + (eqhw->this04 * 2)]);
344 hwwrite(vortex->mmio, 0x2b3f0, peaks[3 + (eqhw->this04 * 2)]);
347 #if 0
348 static void vortex_EqHw_GetLevels(vortex_t * vortex, u16 a[])
350 eqhw_t *eqhw = &(vortex->eq.this04);
351 int ebx;
353 if (eqhw->this04 < 0)
354 return;
356 ebx = 0;
357 do {
358 a[ebx] = hwread(vortex->mmio, 0x2b024 + ebx * 0x30);
359 ebx++;
361 while (ebx < eqhw->this04);
363 a[eqhw->this04] = hwread(vortex->mmio, 0x2b3cc);
364 a[eqhw->this04 + 1] = hwread(vortex->mmio, 0x2b3d8);
366 ebx = 0;
367 do {
368 a[ebx + (eqhw->this04 + 2)] =
369 hwread(vortex->mmio, 0x2b204 + ebx * 0x30);
370 ebx++;
372 while (ebx < eqhw->this04);
374 a[2 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3e4);
375 a[3 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3f0);
378 #endif
379 /* Global Control */
380 static void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg)
382 hwwrite(vortex->mmio, 0x2b440, reg);
385 static void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr)
387 hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800);
390 #if 0
391 static void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg)
393 *reg = hwread(vortex->mmio, 0x2b440);
396 static void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr)
398 *sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f;
401 #endif
402 static void vortex_EqHw_Enable(vortex_t * vortex)
404 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
407 static void vortex_EqHw_Disable(vortex_t * vortex)
409 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
412 /* Reset (zero) buffers */
413 static void vortex_EqHw_ZeroIO(vortex_t * vortex)
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);
422 static void vortex_EqHw_ZeroA3DIO(vortex_t * vortex)
424 int i;
425 for (i = 0; i < 0x4; i++)
426 hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
429 static void vortex_EqHw_ZeroState(vortex_t * vortex)
432 vortex_EqHw_SetControlReg(vortex, 0);
433 vortex_EqHw_ZeroIO(vortex);
434 hwwrite(vortex->mmio, 0x2b3c0, 0);
436 vortex_EqHw_SetTimeConsts(vortex, 0, 0);
438 vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsZeros);
439 vortex_EqHw_SetRightCoefs(vortex, asEqCoefsZeros);
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);
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);
455 /* Program coeficients as pass through */
456 static void vortex_EqHw_ProgramPipe(vortex_t * vortex)
458 vortex_EqHw_SetTimeConsts(vortex, 0, 0);
460 vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsPipes);
461 vortex_EqHw_SetRightCoefs(vortex, asEqCoefsPipes);
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);
469 /* Program EQ block as 10 band Equalizer */
470 static void
471 vortex_EqHw_Program10Band(vortex_t * vortex, auxxEqCoeffSet_t * coefset)
474 vortex_EqHw_SetTimeConsts(vortex, 0xc, 0x7fe0);
476 vortex_EqHw_SetLeftCoefs(vortex, coefset->LeftCoefs);
477 vortex_EqHw_SetRightCoefs(vortex, coefset->RightCoefs);
479 vortex_EqHw_SetLeftGainsCurrent(vortex, coefset->LeftGains);
481 vortex_EqHw_SetRightGainsTarget(vortex, coefset->RightGains);
482 vortex_EqHw_SetLeftGainsTarget(vortex, coefset->LeftGains);
484 vortex_EqHw_SetRightGainsCurrent(vortex, coefset->RightGains);
487 /* Read all EQ peaks. (think VU meter) */
488 static void vortex_EqHw_GetTenBandLevels(vortex_t * vortex, u16 peaks[])
490 eqhw_t *eqhw = &(vortex->eq.this04);
491 int i;
493 if (eqhw->this04 <= 0)
494 return;
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);
503 /* CEqlzr.s */
505 static int vortex_Eqlzr_GetLeftGain(vortex_t * vortex, u16 index, u16 * gain)
507 eqlzr_t *eq = &(vortex->eq);
509 if (eq->this28) {
510 *gain = eq->this130[index];
511 return 0;
513 return 1;
516 static void vortex_Eqlzr_SetLeftGain(vortex_t * vortex, u16 index, u16 gain)
518 eqlzr_t *eq = &(vortex->eq);
520 if (eq->this28 == 0)
521 return;
523 eq->this130[index] = gain;
524 if (eq->this54)
525 return;
527 vortex_EqHw_SetLeftGainsSingleTarget(vortex, index, gain);
530 static int vortex_Eqlzr_GetRightGain(vortex_t * vortex, u16 index, u16 * gain)
532 eqlzr_t *eq = &(vortex->eq);
534 if (eq->this28) {
535 *gain = eq->this130[index + eq->this10];
536 return 0;
538 return 1;
541 static void vortex_Eqlzr_SetRightGain(vortex_t * vortex, u16 index, u16 gain)
543 eqlzr_t *eq = &(vortex->eq);
545 if (eq->this28 == 0)
546 return;
548 eq->this130[index + eq->this10] = gain;
549 if (eq->this54)
550 return;
552 vortex_EqHw_SetRightGainsSingleTarget(vortex, index, gain);
555 #if 0
556 static int
557 vortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, s32 *cnt)
559 eqlzr_t *eq = &(vortex->eq);
560 int si = 0;
562 if (eq->this10 == 0)
563 return 1;
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++;
573 while (eq->this10 > si) ;
574 *cnt = si * 2;
575 return 0;
577 #endif
578 static int vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex_t * vortex)
580 eqlzr_t *eq = &(vortex->eq);
582 vortex_EqHw_SetLeftGainsTarget(vortex, eq->this130);
583 vortex_EqHw_SetRightGainsTarget(vortex, &(eq->this130[eq->this10]));
585 return 0;
588 static int
589 vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], s32 count)
591 eqlzr_t *eq = &(vortex->eq);
592 int i;
594 if (((eq->this10) * 2 != count) || (eq->this28 == 0))
595 return 1;
597 for (i = 0; i < count; i++) {
598 eq->this130[i] = gains[i];
601 if (eq->this54)
602 return 0;
603 return vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
606 static void
607 vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, u32 a, u32 b)
609 eqlzr_t *eq = &(vortex->eq);
610 u32 eax, ebx;
612 eq->this58 = a;
613 eq->this5c = b;
614 if (eq->this54)
615 eax = eq->this0e;
616 else
617 eax = eq->this0a;
618 ebx = (eax * eq->this58) >> 0x10;
619 eax = (eax * eq->this5c) >> 0x10;
620 vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax);
623 static void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex)
625 eqlzr_t *eq = &(vortex->eq);
626 u32 eax, ebx;
628 if (eq->this54)
629 eax = eq->this0e;
630 else
631 eax = eq->this0a;
632 ebx = (eax * eq->this58) >> 0x10;
633 eax = (eax * eq->this5c) >> 0x10;
634 vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax);
637 static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
639 if (vortex != NULL)
640 vortex_EqHw_ZeroA3DIO(vortex);
643 static void vortex_Eqlzr_SetBypass(vortex_t * vortex, u32 bp)
645 eqlzr_t *eq = &(vortex->eq);
647 if ((eq->this28) && (bp == 0)) {
648 /* EQ enabled */
649 vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
650 vortex_EqHw_SetBypassGain(vortex, eq->this08, eq->this08);
651 } else {
652 /* EQ disabled. */
653 vortex_EqHw_SetLeftGainsTarget(vortex, eq->this14_array);
654 vortex_EqHw_SetRightGainsTarget(vortex, eq->this14_array);
655 vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c);
657 vortex_Eqlzr_ProgramA3dBypassGain(vortex);
660 static void vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex_t * vortex)
662 eqlzr_t *eq = &(vortex->eq);
664 /* Set EQ BiQuad filter coeficients */
665 memcpy(&(eq->coefset), &asEqCoefsNormal, sizeof(auxxEqCoeffSet_t));
666 /* Set EQ Band gain levels and dump into hardware registers. */
667 vortex_Eqlzr_SetAllBands(vortex, eq_gains_normal, eq->this10 * 2);
670 static int vortex_Eqlzr_GetAllPeaks(vortex_t * vortex, u16 * peaks, int *count)
672 eqlzr_t *eq = &(vortex->eq);
674 if (eq->this10 == 0)
675 return 1;
676 *count = eq->this10 * 2;
677 vortex_EqHw_GetTenBandLevels(vortex, peaks);
678 return 0;
681 #if 0
682 static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
684 eqlzr_t *eq = &(vortex->eq);
686 return (&(eq->coefset));
688 #endif
689 static void vortex_Eqlzr_init(vortex_t * vortex)
691 eqlzr_t *eq = &(vortex->eq);
693 /* Object constructor */
694 //eq->this04 = 0;
695 eq->this08 = 0; /* Bypass gain with EQ in use. */
696 eq->this0a = 0x5999;
697 eq->this0c = 0x5999; /* Bypass gain with EQ disabled. */
698 eq->this0e = 0x5999;
700 eq->this10 = 0xa; /* 10 eq frequency bands. */
701 eq->this04.this04 = eq->this10;
702 eq->this28 = 0x1; /* if 1 => Allow read access to this130 (gains) */
703 eq->this54 = 0x0; /* if 1 => Dont Allow access to hardware (gains) */
704 eq->this58 = 0xffff;
705 eq->this5c = 0xffff;
707 /* Set gains. */
708 memset(eq->this14_array, 0, sizeof(eq->this14_array));
710 /* Actual init. */
711 vortex_EqHw_ZeroState(vortex);
712 vortex_EqHw_SetSampleRate(vortex, 0x11);
713 vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex);
715 vortex_EqHw_Program10Band(vortex, &(eq->coefset));
716 vortex_Eqlzr_SetBypass(vortex, eq->this54);
717 vortex_Eqlzr_SetA3dBypassGain(vortex, 0, 0);
718 vortex_EqHw_Enable(vortex);
721 static void vortex_Eqlzr_shutdown(vortex_t * vortex)
723 vortex_Eqlzr_ShutDownA3d(vortex);
724 vortex_EqHw_ProgramPipe(vortex);
725 vortex_EqHw_Disable(vortex);
728 /* ALSA interface */
730 /* Control interface */
731 static int
732 snd_vortex_eqtoggle_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
734 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
735 uinfo->count = 1;
736 uinfo->value.integer.min = 0;
737 uinfo->value.integer.max = 1;
738 return 0;
741 static int
742 snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol,
743 struct snd_ctl_elem_value *ucontrol)
745 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
746 eqlzr_t *eq = &(vortex->eq);
747 //int i = kcontrol->private_value;
749 ucontrol->value.integer.value[0] = eq->this54 ? 0 : 1;
751 return 0;
754 static int
755 snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
756 struct snd_ctl_elem_value *ucontrol)
758 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
759 eqlzr_t *eq = &(vortex->eq);
760 //int i = kcontrol->private_value;
762 eq->this54 = ucontrol->value.integer.value[0] ? 0 : 1;
763 vortex_Eqlzr_SetBypass(vortex, eq->this54);
765 return 1; /* Allways changes */
768 static struct snd_kcontrol_new vortex_eqtoggle_kcontrol __devinitdata = {
769 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
770 .name = "EQ Enable",
771 .index = 0,
772 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
773 .private_value = 0,
774 .info = snd_vortex_eqtoggle_info,
775 .get = snd_vortex_eqtoggle_get,
776 .put = snd_vortex_eqtoggle_put
779 static int
780 snd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
782 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
783 uinfo->count = 2;
784 uinfo->value.integer.min = 0x0000;
785 uinfo->value.integer.max = 0x7fff;
786 return 0;
789 static int
790 snd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
792 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
793 int i = kcontrol->private_value;
794 u16 gainL = 0, gainR = 0;
796 vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
797 vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
798 ucontrol->value.integer.value[0] = gainL;
799 ucontrol->value.integer.value[1] = gainR;
800 return 0;
803 static int
804 snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
806 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
807 int changed = 0, i = kcontrol->private_value;
808 u16 gainL = 0, gainR = 0;
810 vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
811 vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
813 if (gainL != ucontrol->value.integer.value[0]) {
814 vortex_Eqlzr_SetLeftGain(vortex, i,
815 ucontrol->value.integer.value[0]);
816 changed = 1;
818 if (gainR != ucontrol->value.integer.value[1]) {
819 vortex_Eqlzr_SetRightGain(vortex, i,
820 ucontrol->value.integer.value[1]);
821 changed = 1;
823 return changed;
826 static struct snd_kcontrol_new vortex_eq_kcontrol __devinitdata = {
827 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
828 .name = " .",
829 .index = 0,
830 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
831 .private_value = 0,
832 .info = snd_vortex_eq_info,
833 .get = snd_vortex_eq_get,
834 .put = snd_vortex_eq_put
837 static int
838 snd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
840 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
841 uinfo->count = 20;
842 uinfo->value.integer.min = 0x0000;
843 uinfo->value.integer.max = 0x7fff;
844 return 0;
847 static int
848 snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
850 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
851 int i, count = 0;
852 u16 peaks[20];
854 vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count);
855 if (count != 20) {
856 printk(KERN_ERR "vortex: peak count error 20 != %d \n", count);
857 return -1;
859 for (i = 0; i < 20; i++)
860 ucontrol->value.integer.value[i] = peaks[i];
862 return 0;
865 static struct snd_kcontrol_new vortex_levels_kcontrol __devinitdata = {
866 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
867 .name = "EQ Peaks",
868 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
869 .info = snd_vortex_peaks_info,
870 .get = snd_vortex_peaks_get,
873 /* EQ band gain labels. */
874 static char *EqBandLabels[10] __devinitdata = {
875 "EQ0 31Hz\0",
876 "EQ1 63Hz\0",
877 "EQ2 125Hz\0",
878 "EQ3 250Hz\0",
879 "EQ4 500Hz\0",
880 "EQ5 1KHz\0",
881 "EQ6 2KHz\0",
882 "EQ7 4KHz\0",
883 "EQ8 8KHz\0",
884 "EQ9 16KHz\0",
887 /* ALSA driver entry points. Init and exit. */
888 static int __devinit vortex_eq_init(vortex_t * vortex)
890 struct snd_kcontrol *kcontrol;
891 int err, i;
893 vortex_Eqlzr_init(vortex);
895 if ((kcontrol =
896 snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex)) == NULL)
897 return -ENOMEM;
898 kcontrol->private_value = 0;
899 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
900 return err;
902 /* EQ gain controls */
903 for (i = 0; i < 10; i++) {
904 if ((kcontrol =
905 snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL)
906 return -ENOMEM;
907 strcpy(kcontrol->id.name, EqBandLabels[i]);
908 kcontrol->private_value = i;
909 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
910 return err;
911 //vortex->eqctrl[i] = kcontrol;
913 /* EQ band levels */
914 if ((kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex)) == NULL)
915 return -ENOMEM;
916 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
917 return err;
919 return 0;
922 static int vortex_eq_free(vortex_t * vortex)
925 //FIXME: segfault because vortex->eqctrl[i] == 4
926 int i;
927 for (i=0; i<10; i++) {
928 if (vortex->eqctrl[i])
929 snd_ctl_remove(vortex->card, vortex->eqctrl[i]);
932 vortex_Eqlzr_shutdown(vortex);
933 return 0;
936 /* End */