]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - sound/pci/au88x0/au88x0_eq.c
Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[mirror_ubuntu-jammy-kernel.git] / sound / pci / au88x0 / au88x0_eq.c
CommitLineData
005fdd53 1// SPDX-License-Identifier: GPL-2.0-or-later
1da177e4
LT
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/*
1da177e4
LT
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 */
39static 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
45static 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
54static 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
76static 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
99static 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
116static 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
134static 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
140static void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[])
141{
142
143}
144
145static void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[])
146{
147
148}
149
150static void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[])
151{
152
153}
154
155static void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[])
156{
157
158}
159
160#endif
161/* Mix Gains */
162static 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
174static 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
182static 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
189static 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
197static void
198vortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
199{
200 hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b);
201}
202
203static void
204vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
205{
206 hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
207}
208
209static 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
219static 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
229static 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
239static 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
250static 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
265static 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
280static 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
295static 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 */
312static 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
336static 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 */
97c67b65 368static void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg)
1da177e4
LT
369{
370 hwwrite(vortex->mmio, 0x2b440, reg);
371}
372
97c67b65 373static void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr)
1da177e4
LT
374{
375 hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800);
376}
377
378#if 0
97c67b65 379static void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg)
1da177e4
LT
380{
381 *reg = hwread(vortex->mmio, 0x2b440);
382}
383
97c67b65 384static void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr)
1da177e4
LT
385{
386 *sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f;
387}
388
389#endif
390static void vortex_EqHw_Enable(vortex_t * vortex)
391{
392 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
393}
394
395static void vortex_EqHw_Disable(vortex_t * vortex)
396{
397 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
398}
399
400/* Reset (zero) buffers */
401static 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
410static 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
417static 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 */
444static 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 */
458static void
459vortex_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) */
476static 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
493static 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
504static 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
518static 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
529static 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
544static int
97c67b65 545vortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, s32 *cnt)
1da177e4
LT
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
566static 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
576static int
97c67b65 577vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], s32 count)
1da177e4
LT
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
594static void
97c67b65 595vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, u32 a, u32 b)
1da177e4
LT
596{
597 eqlzr_t *eq = &(vortex->eq);
97c67b65 598 u32 eax, ebx;
1da177e4
LT
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
611static void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex)
612{
613 eqlzr_t *eq = &(vortex->eq);
97c67b65 614 u32 eax, ebx;
1da177e4
LT
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
625static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
626{
627 if (vortex != NULL)
628 vortex_EqHw_ZeroA3DIO(vortex);
629}
630
97c67b65 631static void vortex_Eqlzr_SetBypass(vortex_t * vortex, u32 bp)
1da177e4
LT
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. */
97c67b65
TI
641 vortex_EqHw_SetLeftGainsTarget(vortex, eq->this14_array);
642 vortex_EqHw_SetRightGainsTarget(vortex, eq->this14_array);
1da177e4
LT
643 vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c);
644 }
645 vortex_Eqlzr_ProgramA3dBypassGain(vortex);
646}
647
648static 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
658static 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
670static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
671{
672 eqlzr_t *eq = &(vortex->eq);
673
674 return (&(eq->coefset));
675}
676#endif
677static 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. */
97c67b65 696 memset(eq->this14_array, 0, sizeof(eq->this14_array));
1da177e4
LT
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
709static 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 */
a5ce8890 719#define snd_vortex_eqtoggle_info snd_ctl_boolean_mono_info
1da177e4
LT
720
721static int
2fd16874
TI
722snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol,
723 struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
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
734static int
2fd16874
TI
735snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
736 struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
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
f3b827e0 748static const struct snd_kcontrol_new vortex_eqtoggle_kcontrol = {
1da177e4
LT
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
759static int
2fd16874 760snd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
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
769static int
2fd16874 770snd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
771{
772 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
773 int i = kcontrol->private_value;
97c67b65 774 u16 gainL = 0, gainR = 0;
1da177e4
LT
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
783static int
2fd16874 784snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
785{
786 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
787 int changed = 0, i = kcontrol->private_value;
97c67b65 788 u16 gainL = 0, gainR = 0;
1da177e4
LT
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
f3b827e0 806static const struct snd_kcontrol_new vortex_eq_kcontrol = {
1da177e4
LT
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
817static int
2fd16874 818snd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1da177e4
LT
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
827static int
2fd16874 828snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
1da177e4
LT
829{
830 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
7113d680 831 int i, count = 0;
1da177e4
LT
832 u16 peaks[20];
833
834 vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count);
835 if (count != 20) {
70c84418
SM
836 dev_err(vortex->card->dev,
837 "peak count error 20 != %d\n", count);
1da177e4
LT
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
f3b827e0 846static const struct snd_kcontrol_new vortex_levels_kcontrol = {
1da177e4
LT
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. */
e23e7a14 855static char *EqBandLabels[10] = {
1da177e4
LT
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. */
e23e7a14 869static int vortex_eq_init(vortex_t *vortex)
1da177e4 870{
2fd16874 871 struct snd_kcontrol *kcontrol;
1da177e4
LT
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;
01cb7021
RY
888 snprintf(kcontrol->id.name, sizeof(kcontrol->id.name),
889 "%s Playback Volume", EqBandLabels[i]);
1da177e4
LT
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
904static 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 */