xref: /linux/sound/pci/au88x0/au88x0_eq.c (revision 44f57d78)
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 */
919