xref: /openbmc/linux/sound/pci/au88x0/au88x0_eq.c (revision 87c2ce3b)
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 */
938