blob: e7220533ecfc79a46f9ab05f3d54d083216dc16d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/***************************************************************************
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 */
51static 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
57static 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
66static 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
88static 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
111static 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
128static 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
146static 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
152static void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[])
153{
154
155}
156
157static void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[])
158{
159
160}
161
162static void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[])
163{
164
165}
166
167static void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[])
168{
169
170}
171
172#endif
173/* Mix Gains */
174static 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
186static 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
194static 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
201static 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
209static void
210vortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
211{
212 hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b);
213}
214
215static void
216vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
217{
218 hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
219}
220
221static 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
231static 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
241static 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
251static 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
262static 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
277static 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
292static 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
307static 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 */
324static 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
348static 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 */
Takashi Iwai97c67b62006-01-13 17:16:29 +0100380static void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700381{
382 hwwrite(vortex->mmio, 0x2b440, reg);
383}
384
Takashi Iwai97c67b62006-01-13 17:16:29 +0100385static void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386{
387 hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800);
388}
389
390#if 0
Takashi Iwai97c67b62006-01-13 17:16:29 +0100391static void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700392{
393 *reg = hwread(vortex->mmio, 0x2b440);
394}
395
Takashi Iwai97c67b62006-01-13 17:16:29 +0100396static void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397{
398 *sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f;
399}
400
401#endif
402static void vortex_EqHw_Enable(vortex_t * vortex)
403{
404 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
405}
406
407static void vortex_EqHw_Disable(vortex_t * vortex)
408{
409 hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
410}
411
412/* Reset (zero) buffers */
413static 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
422static 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
429static 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 */
456static 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 */
470static void
471vortex_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) */
488static 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
505static 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
516static 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
530static 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
541static 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
556static int
Takashi Iwai97c67b62006-01-13 17:16:29 +0100557vortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, s32 *cnt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558{
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
578static 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
588static int
Takashi Iwai97c67b62006-01-13 17:16:29 +0100589vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], s32 count)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590{
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
606static void
Takashi Iwai97c67b62006-01-13 17:16:29 +0100607vortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, u32 a, u32 b)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608{
609 eqlzr_t *eq = &(vortex->eq);
Takashi Iwai97c67b62006-01-13 17:16:29 +0100610 u32 eax, ebx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611
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
623static void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex)
624{
625 eqlzr_t *eq = &(vortex->eq);
Takashi Iwai97c67b62006-01-13 17:16:29 +0100626 u32 eax, ebx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700627
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
637static void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
638{
639 if (vortex != NULL)
640 vortex_EqHw_ZeroA3DIO(vortex);
641}
642
Takashi Iwai97c67b62006-01-13 17:16:29 +0100643static void vortex_Eqlzr_SetBypass(vortex_t * vortex, u32 bp)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644{
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. */
Takashi Iwai97c67b62006-01-13 17:16:29 +0100653 vortex_EqHw_SetLeftGainsTarget(vortex, eq->this14_array);
654 vortex_EqHw_SetRightGainsTarget(vortex, eq->this14_array);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655 vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c);
656 }
657 vortex_Eqlzr_ProgramA3dBypassGain(vortex);
658}
659
660static 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
670static 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
682static auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
683{
684 eqlzr_t *eq = &(vortex->eq);
685
686 return (&(eq->coefset));
687}
688#endif
689static 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. */
Takashi Iwai97c67b62006-01-13 17:16:29 +0100708 memset(eq->this14_array, 0, sizeof(eq->this14_array));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709
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
721static 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 */
Takashi Iwaia5ce8892007-07-23 15:42:26 +0200731#define snd_vortex_eqtoggle_info snd_ctl_boolean_mono_info
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
733static int
Takashi Iwai2fd16872005-11-17 14:55:19 +0100734snd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol,
735 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736{
737 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
738 eqlzr_t *eq = &(vortex->eq);
739 //int i = kcontrol->private_value;
740
741 ucontrol->value.integer.value[0] = eq->this54 ? 0 : 1;
742
743 return 0;
744}
745
746static int
Takashi Iwai2fd16872005-11-17 14:55:19 +0100747snd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
748 struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749{
750 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
751 eqlzr_t *eq = &(vortex->eq);
752 //int i = kcontrol->private_value;
753
754 eq->this54 = ucontrol->value.integer.value[0] ? 0 : 1;
755 vortex_Eqlzr_SetBypass(vortex, eq->this54);
756
757 return 1; /* Allways changes */
758}
759
Bill Pembertone23e7a12012-12-06 12:35:10 -0500760static struct snd_kcontrol_new vortex_eqtoggle_kcontrol = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
762 .name = "EQ Enable",
763 .index = 0,
764 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
765 .private_value = 0,
766 .info = snd_vortex_eqtoggle_info,
767 .get = snd_vortex_eqtoggle_get,
768 .put = snd_vortex_eqtoggle_put
769};
770
771static int
Takashi Iwai2fd16872005-11-17 14:55:19 +0100772snd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700773{
774 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
775 uinfo->count = 2;
776 uinfo->value.integer.min = 0x0000;
777 uinfo->value.integer.max = 0x7fff;
778 return 0;
779}
780
781static int
Takashi Iwai2fd16872005-11-17 14:55:19 +0100782snd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
784 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
785 int i = kcontrol->private_value;
Takashi Iwai97c67b62006-01-13 17:16:29 +0100786 u16 gainL = 0, gainR = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787
788 vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
789 vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
790 ucontrol->value.integer.value[0] = gainL;
791 ucontrol->value.integer.value[1] = gainR;
792 return 0;
793}
794
795static int
Takashi Iwai2fd16872005-11-17 14:55:19 +0100796snd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797{
798 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
799 int changed = 0, i = kcontrol->private_value;
Takashi Iwai97c67b62006-01-13 17:16:29 +0100800 u16 gainL = 0, gainR = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801
802 vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
803 vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
804
805 if (gainL != ucontrol->value.integer.value[0]) {
806 vortex_Eqlzr_SetLeftGain(vortex, i,
807 ucontrol->value.integer.value[0]);
808 changed = 1;
809 }
810 if (gainR != ucontrol->value.integer.value[1]) {
811 vortex_Eqlzr_SetRightGain(vortex, i,
812 ucontrol->value.integer.value[1]);
813 changed = 1;
814 }
815 return changed;
816}
817
Bill Pembertone23e7a12012-12-06 12:35:10 -0500818static struct snd_kcontrol_new vortex_eq_kcontrol = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
820 .name = " .",
821 .index = 0,
822 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
823 .private_value = 0,
824 .info = snd_vortex_eq_info,
825 .get = snd_vortex_eq_get,
826 .put = snd_vortex_eq_put
827};
828
829static int
Takashi Iwai2fd16872005-11-17 14:55:19 +0100830snd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700831{
832 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
833 uinfo->count = 20;
834 uinfo->value.integer.min = 0x0000;
835 uinfo->value.integer.max = 0x7fff;
836 return 0;
837}
838
839static int
Takashi Iwai2fd16872005-11-17 14:55:19 +0100840snd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700841{
842 vortex_t *vortex = snd_kcontrol_chip(kcontrol);
Takashi Iwai7113d682006-01-16 13:55:48 +0100843 int i, count = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 u16 peaks[20];
845
846 vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count);
847 if (count != 20) {
Takashi Iwai99b359b2005-10-20 18:26:44 +0200848 printk(KERN_ERR "vortex: peak count error 20 != %d \n", count);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 return -1;
850 }
851 for (i = 0; i < 20; i++)
852 ucontrol->value.integer.value[i] = peaks[i];
853
854 return 0;
855}
856
Bill Pembertone23e7a12012-12-06 12:35:10 -0500857static struct snd_kcontrol_new vortex_levels_kcontrol = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700858 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
859 .name = "EQ Peaks",
860 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
861 .info = snd_vortex_peaks_info,
862 .get = snd_vortex_peaks_get,
863};
864
865/* EQ band gain labels. */
Bill Pembertone23e7a12012-12-06 12:35:10 -0500866static char *EqBandLabels[10] = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867 "EQ0 31Hz\0",
868 "EQ1 63Hz\0",
869 "EQ2 125Hz\0",
870 "EQ3 250Hz\0",
871 "EQ4 500Hz\0",
872 "EQ5 1KHz\0",
873 "EQ6 2KHz\0",
874 "EQ7 4KHz\0",
875 "EQ8 8KHz\0",
876 "EQ9 16KHz\0",
877};
878
879/* ALSA driver entry points. Init and exit. */
Bill Pembertone23e7a12012-12-06 12:35:10 -0500880static int vortex_eq_init(vortex_t *vortex)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700881{
Takashi Iwai2fd16872005-11-17 14:55:19 +0100882 struct snd_kcontrol *kcontrol;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883 int err, i;
884
885 vortex_Eqlzr_init(vortex);
886
887 if ((kcontrol =
888 snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex)) == NULL)
889 return -ENOMEM;
890 kcontrol->private_value = 0;
891 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
892 return err;
893
894 /* EQ gain controls */
895 for (i = 0; i < 10; i++) {
896 if ((kcontrol =
897 snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL)
898 return -ENOMEM;
Raymond Yau01cb7022011-02-20 15:55:14 +0800899 snprintf(kcontrol->id.name, sizeof(kcontrol->id.name),
900 "%s Playback Volume", EqBandLabels[i]);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700901 kcontrol->private_value = i;
902 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
903 return err;
904 //vortex->eqctrl[i] = kcontrol;
905 }
906 /* EQ band levels */
907 if ((kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex)) == NULL)
908 return -ENOMEM;
909 if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
910 return err;
911
912 return 0;
913}
914
915static int vortex_eq_free(vortex_t * vortex)
916{
917 /*
918 //FIXME: segfault because vortex->eqctrl[i] == 4
919 int i;
920 for (i=0; i<10; i++) {
921 if (vortex->eqctrl[i])
922 snd_ctl_remove(vortex->card, vortex->eqctrl[i]);
923 }
924 */
925 vortex_Eqlzr_shutdown(vortex);
926 return 0;
927}
928
929/* End */