xref: /openbmc/linux/sound/pci/au88x0/au88x0_eq.c (revision 64c70b1c)
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, u32 reg)
381 {
382 	hwwrite(vortex->mmio, 0x2b440, reg);
383 }
384 
385 static void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 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, u32 *reg)
392 {
393 	*reg = hwread(vortex->mmio, 0x2b440);
394 }
395 
396 static void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *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, s32 *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[], s32 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, u32 a, u32 b)
608 {
609 	eqlzr_t *eq = &(vortex->eq);
610 	u32 eax, ebx;
611 
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);
621 }
622 
623 static void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex)
624 {
625 	eqlzr_t *eq = &(vortex->eq);
626 	u32 eax, ebx;
627 
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);
635 }
636 
637 static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
638 {
639 	if (vortex != NULL)
640 		vortex_EqHw_ZeroA3DIO(vortex);
641 }
642 
643 static void vortex_Eqlzr_SetBypass(vortex_t * vortex, u32 bp)
644 {
645 	eqlzr_t *eq = &(vortex->eq);
646 
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);
656 	}
657 	vortex_Eqlzr_ProgramA3dBypassGain(vortex);
658 }
659 
660 static void vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex_t * vortex)
661 {
662 	eqlzr_t *eq = &(vortex->eq);
663 
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);
668 }
669 
670 static int vortex_Eqlzr_GetAllPeaks(vortex_t * vortex, u16 * peaks, int *count)
671 {
672 	eqlzr_t *eq = &(vortex->eq);
673 
674 	if (eq->this10 == 0)
675 		return 1;
676 	*count = eq->this10 * 2;
677 	vortex_EqHw_GetTenBandLevels(vortex, peaks);
678 	return 0;
679 }
680 
681 #if 0
682 static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
683 {
684 	eqlzr_t *eq = &(vortex->eq);
685 
686 	return (&(eq->coefset));
687 }
688 #endif
689 static void vortex_Eqlzr_init(vortex_t * vortex)
690 {
691 	eqlzr_t *eq = &(vortex->eq);
692 
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;
699 
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;
706 
707 	/* Set gains. */
708 	memset(eq->this14_array, 0, sizeof(eq->this14_array));
709 
710 	/* Actual init. */
711 	vortex_EqHw_ZeroState(vortex);
712 	vortex_EqHw_SetSampleRate(vortex, 0x11);
713 	vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex);
714 
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);
719 }
720 
721 static void vortex_Eqlzr_shutdown(vortex_t * vortex)
722 {
723 	vortex_Eqlzr_ShutDownA3d(vortex);
724 	vortex_EqHw_ProgramPipe(vortex);
725 	vortex_EqHw_Disable(vortex);
726 }
727 
728 /* ALSA interface */
729 
730 /* Control interface */
731 static int
732 snd_vortex_eqtoggle_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
733 {
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;
739 }
740 
741 static int
742 snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol,
743 			struct snd_ctl_elem_value *ucontrol)
744 {
745 	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
746 	eqlzr_t *eq = &(vortex->eq);
747 	//int i = kcontrol->private_value;
748 
749 	ucontrol->value.integer.value[0] = eq->this54 ? 0 : 1;
750 
751 	return 0;
752 }
753 
754 static int
755 snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
756 			struct snd_ctl_elem_value *ucontrol)
757 {
758 	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
759 	eqlzr_t *eq = &(vortex->eq);
760 	//int i = kcontrol->private_value;
761 
762 	eq->this54 = ucontrol->value.integer.value[0] ? 0 : 1;
763 	vortex_Eqlzr_SetBypass(vortex, eq->this54);
764 
765 	return 1;		/* Allways changes */
766 }
767 
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
777 };
778 
779 static int
780 snd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
781 {
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;
787 }
788 
789 static int
790 snd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
791 {
792 	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
793 	int i = kcontrol->private_value;
794 	u16 gainL = 0, gainR = 0;
795 
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;
801 }
802 
803 static int
804 snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
805 {
806 	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
807 	int changed = 0, i = kcontrol->private_value;
808 	u16 gainL = 0, gainR = 0;
809 
810 	vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
811 	vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
812 
813 	if (gainL != ucontrol->value.integer.value[0]) {
814 		vortex_Eqlzr_SetLeftGain(vortex, i,
815 					 ucontrol->value.integer.value[0]);
816 		changed = 1;
817 	}
818 	if (gainR != ucontrol->value.integer.value[1]) {
819 		vortex_Eqlzr_SetRightGain(vortex, i,
820 					  ucontrol->value.integer.value[1]);
821 		changed = 1;
822 	}
823 	return changed;
824 }
825 
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
835 };
836 
837 static int
838 snd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
839 {
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;
845 }
846 
847 static int
848 snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
849 {
850 	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
851 	int i, count = 0;
852 	u16 peaks[20];
853 
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;
858 	}
859 	for (i = 0; i < 20; i++)
860 		ucontrol->value.integer.value[i] = peaks[i];
861 
862 	return 0;
863 }
864 
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,
871 };
872 
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",
885 };
886 
887 /* ALSA driver entry points. Init and exit. */
888 static int __devinit vortex_eq_init(vortex_t * vortex)
889 {
890 	struct snd_kcontrol *kcontrol;
891 	int err, i;
892 
893 	vortex_Eqlzr_init(vortex);
894 
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;
901 
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;
912 	}
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;
918 
919 	return 0;
920 }
921 
922 static int vortex_eq_free(vortex_t * vortex)
923 {
924 	/*
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]);
930 	   }
931 	 */
932 	vortex_Eqlzr_shutdown(vortex);
933 	return 0;
934 }
935 
936 /* End */
937