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 */
vortex_EqHw_SetTimeConsts(vortex_t * vortex,u16 gain,u16 level)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
sign_invert(u16 a)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
vortex_EqHw_SetLeftCoefs(vortex_t * vortex,u16 coefs[])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
vortex_EqHw_SetRightCoefs(vortex_t * vortex,u16 coefs[])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
vortex_EqHw_SetLeftStates(vortex_t * vortex,u16 a[],u16 b[])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
vortex_EqHw_SetRightStates(vortex_t * vortex,u16 a[],u16 b[])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 */
vortex_EqHw_SetBypassGain(vortex_t * vortex,u16 a,u16 b)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
vortex_EqHw_SetA3DBypassGain(vortex_t * vortex,u16 a,u16 b)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
vortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex,u16 index,u16 b)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
vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex,u16 index,u16 b)204 vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
205 {
206 hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
207 }
208
vortex_EqHw_SetLeftGainsTarget(vortex_t * vortex,u16 a[])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
vortex_EqHw_SetRightGainsTarget(vortex_t * vortex,u16 a[])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
vortex_EqHw_SetLeftGainsCurrent(vortex_t * vortex,u16 a[])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
vortex_EqHw_SetRightGainsCurrent(vortex_t * vortex,u16 a[])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 */
vortex_EqHw_SetLevels(vortex_t * vortex,u16 peaks[])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 */
vortex_EqHw_SetControlReg(vortex_t * vortex,u32 reg)368 static void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg)
369 {
370 hwwrite(vortex->mmio, 0x2b440, reg);
371 }
372
vortex_EqHw_SetSampleRate(vortex_t * vortex,u32 sr)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
vortex_EqHw_Enable(vortex_t * vortex)390 static void vortex_EqHw_Enable(vortex_t * vortex)
391 {
392 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
393 }
394
vortex_EqHw_Disable(vortex_t * vortex)395 static void vortex_EqHw_Disable(vortex_t * vortex)
396 {
397 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
398 }
399
400 /* Reset (zero) buffers */
vortex_EqHw_ZeroIO(vortex_t * vortex)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
vortex_EqHw_ZeroA3DIO(vortex_t * vortex)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
vortex_EqHw_ZeroState(vortex_t * vortex)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 */
vortex_EqHw_ProgramPipe(vortex_t * vortex)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
vortex_EqHw_Program10Band(vortex_t * vortex,auxxEqCoeffSet_t * coefset)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) */
vortex_EqHw_GetTenBandLevels(vortex_t * vortex,u16 peaks[])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
vortex_Eqlzr_GetLeftGain(vortex_t * vortex,u16 index,u16 * gain)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
vortex_Eqlzr_SetLeftGain(vortex_t * vortex,u16 index,u16 gain)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
vortex_Eqlzr_GetRightGain(vortex_t * vortex,u16 index,u16 * gain)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
vortex_Eqlzr_SetRightGain(vortex_t * vortex,u16 index,u16 gain)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
vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex_t * vortex)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
vortex_Eqlzr_SetAllBands(vortex_t * vortex,u16 gains[],s32 count)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
vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex,u32 a,u32 b)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
vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex)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
vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)625 static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
626 {
627 if (vortex != NULL)
628 vortex_EqHw_ZeroA3DIO(vortex);
629 }
630
vortex_Eqlzr_SetBypass(vortex_t * vortex,u32 bp)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
vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex_t * vortex)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
vortex_Eqlzr_GetAllPeaks(vortex_t * vortex,u16 * peaks,int * count)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
vortex_Eqlzr_init(vortex_t * vortex)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
vortex_Eqlzr_shutdown(vortex_t * vortex)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
snd_vortex_eqtoggle_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)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
snd_vortex_eqtoggle_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)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
snd_vortex_eq_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)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
snd_vortex_eq_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)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
snd_vortex_eq_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)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
snd_vortex_peaks_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)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
snd_vortex_peaks_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)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. */
vortex_eq_init(vortex_t * vortex)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
vortex_eq_free(vortex_t * vortex)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