162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/***************************************************************************
362306a36Sopenharmony_ci *            au88x0_eq.c
462306a36Sopenharmony_ci *  Aureal Vortex Hardware EQ control/access.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci *  Sun Jun  8 18:19:19 2003
762306a36Sopenharmony_ci *  2003  Manuel Jander (mjander@users.sourceforge.net)
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *  02 July 2003: First time something works :)
1062306a36Sopenharmony_ci *  November 2003: A3D Bypass code completed but untested.
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci *  TODO:
1362306a36Sopenharmony_ci *     - Debug (testing)
1462306a36Sopenharmony_ci *     - Test peak visualization support.
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci ****************************************************************************/
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci/*
1962306a36Sopenharmony_ci */
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci/*
2262306a36Sopenharmony_ci The Aureal Hardware EQ is found on AU8810 and AU8830 chips only.
2362306a36Sopenharmony_ci it has 4 inputs (2 for general mix, 2 for A3D) and 2 outputs (supposed
2462306a36Sopenharmony_ci to be routed to the codec).
2562306a36Sopenharmony_ci*/
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include "au88x0.h"
2862306a36Sopenharmony_ci#include "au88x0_eq.h"
2962306a36Sopenharmony_ci#include "au88x0_eqdata.c"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#define VORTEX_EQ_BASE	 0x2b000
3262306a36Sopenharmony_ci#define VORTEX_EQ_DEST   (VORTEX_EQ_BASE + 0x410)
3362306a36Sopenharmony_ci#define VORTEX_EQ_SOURCE (VORTEX_EQ_BASE + 0x430)
3462306a36Sopenharmony_ci#define VORTEX_EQ_CTRL   (VORTEX_EQ_BASE + 0x440)
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci#define VORTEX_BAND_COEFF_SIZE 0x30
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci/* CEqHw.s */
3962306a36Sopenharmony_cistatic void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3c4, gain);
4262306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3c8, level);
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic inline u16 sign_invert(u16 a)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	/* -(-32768) -> -32768 so we do -(-32768) -> 32767 to make the result positive */
4862306a36Sopenharmony_ci	if (a == (u16)-32768)
4962306a36Sopenharmony_ci		return 32767;
5062306a36Sopenharmony_ci	else
5162306a36Sopenharmony_ci		return -a;
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic void vortex_EqHw_SetLeftCoefs(vortex_t *vortex, const u16 coefs[])
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
5762306a36Sopenharmony_ci	int i = 0, n /*esp2c */;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	for (n = 0; n < eqhw->this04; n++) {
6062306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b000 + n * 0x30, coefs[i + 0]);
6162306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b004 + n * 0x30, coefs[i + 1]);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci		if (eqhw->this08 == 0) {
6462306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2]);
6562306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3]);
6662306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b010 + n * 0x30, coefs[i + 4]);
6762306a36Sopenharmony_ci		} else {
6862306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, sign_invert(coefs[2 + i]));
6962306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, sign_invert(coefs[3 + i]));
7062306a36Sopenharmony_ci		        hwwrite(vortex->mmio, 0x2b010 + n * 0x30, sign_invert(coefs[4 + i]));
7162306a36Sopenharmony_ci		}
7262306a36Sopenharmony_ci		i += 5;
7362306a36Sopenharmony_ci	}
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_cistatic void vortex_EqHw_SetRightCoefs(vortex_t *vortex, const u16 coefs[])
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
7962306a36Sopenharmony_ci	int i = 0, n /*esp2c */;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	for (n = 0; n < eqhw->this04; n++) {
8262306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, coefs[0 + i]);
8362306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, coefs[1 + i]);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci		if (eqhw->this08 == 0) {
8662306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i]);
8762306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i]);
8862306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, coefs[4 + i]);
8962306a36Sopenharmony_ci		} else {
9062306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, sign_invert(coefs[2 + i]));
9162306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, sign_invert(coefs[3 + i]));
9262306a36Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, sign_invert(coefs[4 + i]));
9362306a36Sopenharmony_ci		}
9462306a36Sopenharmony_ci		i += 5;
9562306a36Sopenharmony_ci	}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic void vortex_EqHw_SetLeftStates(vortex_t *vortex, const u16 a[], const u16 b[])
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
10262306a36Sopenharmony_ci	int i = 0, ebx;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3fc, a[0]);
10562306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b400, a[1]);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
10862306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b014 + (i * 0xc), b[i]);
10962306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b018 + (i * 0xc), b[1 + i]);
11062306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b01c + (i * 0xc), b[2 + i]);
11162306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b020 + (i * 0xc), b[3 + i]);
11262306a36Sopenharmony_ci		i += 4;
11362306a36Sopenharmony_ci	}
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic void vortex_EqHw_SetRightStates(vortex_t *vortex, const u16 a[], const u16 b[])
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
11962306a36Sopenharmony_ci	int i = 0, ebx;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b404, a[0]);
12262306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b408, a[1]);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
12562306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1f4 + (i * 0xc), b[i]);
12662306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1f8 + (i * 0xc), b[1 + i]);
12762306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1fc + (i * 0xc), b[2 + i]);
12862306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b200 + (i * 0xc), b[3 + i]);
12962306a36Sopenharmony_ci		i += 4;
13062306a36Sopenharmony_ci	}
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci#if 0
13462306a36Sopenharmony_cistatic void vortex_EqHw_GetTimeConsts(vortex_t * vortex, u16 * a, u16 * b)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	*a = hwread(vortex->mmio, 0x2b3c4);
13762306a36Sopenharmony_ci	*b = hwread(vortex->mmio, 0x2b3c8);
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_cistatic void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[])
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistatic void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[])
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistatic void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[])
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[])
15662306a36Sopenharmony_ci{
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci#endif
16162306a36Sopenharmony_ci/* Mix Gains */
16262306a36Sopenharmony_cistatic void vortex_EqHw_SetBypassGain(vortex_t * vortex, u16 a, u16 b)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
16562306a36Sopenharmony_ci	if (eqhw->this08 == 0) {
16662306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b3d4, a);
16762306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b3ec, b);
16862306a36Sopenharmony_ci	} else {
16962306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b3d4, sign_invert(a));
17062306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b3ec, sign_invert(b));
17162306a36Sopenharmony_ci	}
17262306a36Sopenharmony_ci}
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_cistatic void vortex_EqHw_SetA3DBypassGain(vortex_t * vortex, u16 a, u16 b)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3e0, a);
17862306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3f8, b);
17962306a36Sopenharmony_ci}
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci#if 0
18262306a36Sopenharmony_cistatic void vortex_EqHw_SetCurrBypassGain(vortex_t * vortex, u16 a, u16 b)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3d0, a);
18662306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3e8, b);
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_cistatic void vortex_EqHw_SetCurrA3DBypassGain(vortex_t * vortex, u16 a, u16 b)
19062306a36Sopenharmony_ci{
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3dc, a);
19362306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3f4, b);
19462306a36Sopenharmony_ci}
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci#endif
19762306a36Sopenharmony_cistatic void
19862306a36Sopenharmony_civortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b);
20162306a36Sopenharmony_ci}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_cistatic void
20462306a36Sopenharmony_civortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_cistatic void vortex_EqHw_SetLeftGainsTarget(vortex_t *vortex, const u16 a[])
21062306a36Sopenharmony_ci{
21162306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
21262306a36Sopenharmony_ci	int ebx;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
21562306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b02c + ebx * 0x30, a[ebx]);
21662306a36Sopenharmony_ci	}
21762306a36Sopenharmony_ci}
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_cistatic void vortex_EqHw_SetRightGainsTarget(vortex_t *vortex, const u16 a[])
22062306a36Sopenharmony_ci{
22162306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
22262306a36Sopenharmony_ci	int ebx;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
22562306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b20c + ebx * 0x30, a[ebx]);
22662306a36Sopenharmony_ci	}
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic void vortex_EqHw_SetLeftGainsCurrent(vortex_t *vortex, const u16 a[])
23062306a36Sopenharmony_ci{
23162306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
23262306a36Sopenharmony_ci	int ebx;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
23562306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b028 + ebx * 0x30, a[ebx]);
23662306a36Sopenharmony_ci	}
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic void vortex_EqHw_SetRightGainsCurrent(vortex_t *vortex, const u16 a[])
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
24262306a36Sopenharmony_ci	int ebx;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
24562306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b208 + ebx * 0x30, a[ebx]);
24662306a36Sopenharmony_ci	}
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci#if 0
25062306a36Sopenharmony_cistatic void vortex_EqHw_GetLeftGainsTarget(vortex_t * vortex, u16 a[])
25162306a36Sopenharmony_ci{
25262306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
25362306a36Sopenharmony_ci	int ebx = 0;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	if (eqhw->this04 < 0)
25662306a36Sopenharmony_ci		return;
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	do {
25962306a36Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b02c + ebx * 0x30);
26062306a36Sopenharmony_ci		ebx++;
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci	while (ebx < eqhw->this04);
26362306a36Sopenharmony_ci}
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic void vortex_EqHw_GetRightGainsTarget(vortex_t * vortex, u16 a[])
26662306a36Sopenharmony_ci{
26762306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
26862306a36Sopenharmony_ci	int ebx = 0;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	if (eqhw->this04 < 0)
27162306a36Sopenharmony_ci		return;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	do {
27462306a36Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b20c + ebx * 0x30);
27562306a36Sopenharmony_ci		ebx++;
27662306a36Sopenharmony_ci	}
27762306a36Sopenharmony_ci	while (ebx < eqhw->this04);
27862306a36Sopenharmony_ci}
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic void vortex_EqHw_GetLeftGainsCurrent(vortex_t * vortex, u16 a[])
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
28362306a36Sopenharmony_ci	int ebx = 0;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	if (eqhw->this04 < 0)
28662306a36Sopenharmony_ci		return;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	do {
28962306a36Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b028 + ebx * 0x30);
29062306a36Sopenharmony_ci		ebx++;
29162306a36Sopenharmony_ci	}
29262306a36Sopenharmony_ci	while (ebx < eqhw->this04);
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cistatic void vortex_EqHw_GetRightGainsCurrent(vortex_t * vortex, u16 a[])
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
29862306a36Sopenharmony_ci	int ebx = 0;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	if (eqhw->this04 < 0)
30162306a36Sopenharmony_ci		return;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	do {
30462306a36Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b208 + ebx * 0x30);
30562306a36Sopenharmony_ci		ebx++;
30662306a36Sopenharmony_ci	}
30762306a36Sopenharmony_ci	while (ebx < eqhw->this04);
30862306a36Sopenharmony_ci}
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_ci#endif
31162306a36Sopenharmony_ci/* EQ band levels settings */
31262306a36Sopenharmony_cistatic void vortex_EqHw_SetLevels(vortex_t *vortex, const u16 peaks[])
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
31562306a36Sopenharmony_ci	int i;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	/* set left peaks */
31862306a36Sopenharmony_ci	for (i = 0; i < eqhw->this04; i++) {
31962306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b024 + i * VORTEX_BAND_COEFF_SIZE, peaks[i]);
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3cc, peaks[eqhw->this04]);
32362306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3d8, peaks[eqhw->this04 + 1]);
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	/* set right peaks */
32662306a36Sopenharmony_ci	for (i = 0; i < eqhw->this04; i++) {
32762306a36Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b204 + i * VORTEX_BAND_COEFF_SIZE,
32862306a36Sopenharmony_ci			peaks[i + (eqhw->this04 + 2)]);
32962306a36Sopenharmony_ci	}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3e4, peaks[2 + (eqhw->this04 * 2)]);
33262306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3f0, peaks[3 + (eqhw->this04 * 2)]);
33362306a36Sopenharmony_ci}
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci#if 0
33662306a36Sopenharmony_cistatic void vortex_EqHw_GetLevels(vortex_t * vortex, u16 a[])
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
33962306a36Sopenharmony_ci	int ebx;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	if (eqhw->this04 < 0)
34262306a36Sopenharmony_ci		return;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	ebx = 0;
34562306a36Sopenharmony_ci	do {
34662306a36Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b024 + ebx * 0x30);
34762306a36Sopenharmony_ci		ebx++;
34862306a36Sopenharmony_ci	}
34962306a36Sopenharmony_ci	while (ebx < eqhw->this04);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	a[eqhw->this04] = hwread(vortex->mmio, 0x2b3cc);
35262306a36Sopenharmony_ci	a[eqhw->this04 + 1] = hwread(vortex->mmio, 0x2b3d8);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	ebx = 0;
35562306a36Sopenharmony_ci	do {
35662306a36Sopenharmony_ci		a[ebx + (eqhw->this04 + 2)] =
35762306a36Sopenharmony_ci		    hwread(vortex->mmio, 0x2b204 + ebx * 0x30);
35862306a36Sopenharmony_ci		ebx++;
35962306a36Sopenharmony_ci	}
36062306a36Sopenharmony_ci	while (ebx < eqhw->this04);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	a[2 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3e4);
36362306a36Sopenharmony_ci	a[3 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3f0);
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci#endif
36762306a36Sopenharmony_ci/* Global Control */
36862306a36Sopenharmony_cistatic void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg)
36962306a36Sopenharmony_ci{
37062306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b440, reg);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800);
37662306a36Sopenharmony_ci}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci#if 0
37962306a36Sopenharmony_cistatic void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg)
38062306a36Sopenharmony_ci{
38162306a36Sopenharmony_ci	*reg = hwread(vortex->mmio, 0x2b440);
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cistatic void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr)
38562306a36Sopenharmony_ci{
38662306a36Sopenharmony_ci	*sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f;
38762306a36Sopenharmony_ci}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci#endif
39062306a36Sopenharmony_cistatic void vortex_EqHw_Enable(vortex_t * vortex)
39162306a36Sopenharmony_ci{
39262306a36Sopenharmony_ci	hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
39362306a36Sopenharmony_ci}
39462306a36Sopenharmony_ci
39562306a36Sopenharmony_cistatic void vortex_EqHw_Disable(vortex_t * vortex)
39662306a36Sopenharmony_ci{
39762306a36Sopenharmony_ci	hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
39862306a36Sopenharmony_ci}
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci/* Reset (zero) buffers */
40162306a36Sopenharmony_cistatic void vortex_EqHw_ZeroIO(vortex_t * vortex)
40262306a36Sopenharmony_ci{
40362306a36Sopenharmony_ci	int i;
40462306a36Sopenharmony_ci	for (i = 0; i < 0x8; i++)
40562306a36Sopenharmony_ci		hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
40662306a36Sopenharmony_ci	for (i = 0; i < 0x4; i++)
40762306a36Sopenharmony_ci		hwwrite(vortex->mmio, VORTEX_EQ_SOURCE + (i << 2), 0x0);
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic void vortex_EqHw_ZeroA3DIO(vortex_t * vortex)
41162306a36Sopenharmony_ci{
41262306a36Sopenharmony_ci	int i;
41362306a36Sopenharmony_ci	for (i = 0; i < 0x4; i++)
41462306a36Sopenharmony_ci		hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
41562306a36Sopenharmony_ci}
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_cistatic void vortex_EqHw_ZeroState(vortex_t * vortex)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	vortex_EqHw_SetControlReg(vortex, 0);
42162306a36Sopenharmony_ci	vortex_EqHw_ZeroIO(vortex);
42262306a36Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3c0, 0);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	vortex_EqHw_SetTimeConsts(vortex, 0, 0);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsZeros);
42762306a36Sopenharmony_ci	vortex_EqHw_SetRightCoefs(vortex, asEqCoefsZeros);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci	vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_zero);
43062306a36Sopenharmony_ci	vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_zero);
43162306a36Sopenharmony_ci	vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_zero);
43262306a36Sopenharmony_ci	vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_zero);
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	vortex_EqHw_SetBypassGain(vortex, 0, 0);
43562306a36Sopenharmony_ci	//vortex_EqHw_SetCurrBypassGain(vortex, 0, 0);
43662306a36Sopenharmony_ci	vortex_EqHw_SetA3DBypassGain(vortex, 0, 0);
43762306a36Sopenharmony_ci	//vortex_EqHw_SetCurrA3DBypassGain(vortex, 0, 0);
43862306a36Sopenharmony_ci	vortex_EqHw_SetLeftStates(vortex, eq_states_zero, asEqOutStateZeros);
43962306a36Sopenharmony_ci	vortex_EqHw_SetRightStates(vortex, eq_states_zero, asEqOutStateZeros);
44062306a36Sopenharmony_ci	vortex_EqHw_SetLevels(vortex, (u16 *) eq_levels);
44162306a36Sopenharmony_ci}
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci/* Program coeficients as pass through */
44462306a36Sopenharmony_cistatic void vortex_EqHw_ProgramPipe(vortex_t * vortex)
44562306a36Sopenharmony_ci{
44662306a36Sopenharmony_ci	vortex_EqHw_SetTimeConsts(vortex, 0, 0);
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsPipes);
44962306a36Sopenharmony_ci	vortex_EqHw_SetRightCoefs(vortex, asEqCoefsPipes);
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_current);
45262306a36Sopenharmony_ci	vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_current);
45362306a36Sopenharmony_ci	vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_current);
45462306a36Sopenharmony_ci	vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_current);
45562306a36Sopenharmony_ci}
45662306a36Sopenharmony_ci
45762306a36Sopenharmony_ci/* Program EQ block as 10 band Equalizer */
45862306a36Sopenharmony_cistatic void
45962306a36Sopenharmony_civortex_EqHw_Program10Band(vortex_t * vortex, auxxEqCoeffSet_t * coefset)
46062306a36Sopenharmony_ci{
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	vortex_EqHw_SetTimeConsts(vortex, 0xc, 0x7fe0);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	vortex_EqHw_SetLeftCoefs(vortex, coefset->LeftCoefs);
46562306a36Sopenharmony_ci	vortex_EqHw_SetRightCoefs(vortex, coefset->RightCoefs);
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	vortex_EqHw_SetLeftGainsCurrent(vortex, coefset->LeftGains);
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	vortex_EqHw_SetRightGainsTarget(vortex, coefset->RightGains);
47062306a36Sopenharmony_ci	vortex_EqHw_SetLeftGainsTarget(vortex, coefset->LeftGains);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	vortex_EqHw_SetRightGainsCurrent(vortex, coefset->RightGains);
47362306a36Sopenharmony_ci}
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci/* Read all EQ peaks. (think VU meter) */
47662306a36Sopenharmony_cistatic void vortex_EqHw_GetTenBandLevels(vortex_t * vortex, u16 peaks[])
47762306a36Sopenharmony_ci{
47862306a36Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
47962306a36Sopenharmony_ci	int i;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	if (eqhw->this04 <= 0)
48262306a36Sopenharmony_ci		return;
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_ci	for (i = 0; i < eqhw->this04; i++)
48562306a36Sopenharmony_ci		peaks[i] = hwread(vortex->mmio, 0x2B024 + i * 0x30);
48662306a36Sopenharmony_ci	for (i = 0; i < eqhw->this04; i++)
48762306a36Sopenharmony_ci		peaks[i + eqhw->this04] =
48862306a36Sopenharmony_ci		    hwread(vortex->mmio, 0x2B204 + i * 0x30);
48962306a36Sopenharmony_ci}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci/* CEqlzr.s */
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic int vortex_Eqlzr_GetLeftGain(vortex_t * vortex, u16 index, u16 * gain)
49462306a36Sopenharmony_ci{
49562306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	if (eq->this28) {
49862306a36Sopenharmony_ci		*gain = eq->this130[index];
49962306a36Sopenharmony_ci		return 0;
50062306a36Sopenharmony_ci	}
50162306a36Sopenharmony_ci	return 1;
50262306a36Sopenharmony_ci}
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_cistatic void vortex_Eqlzr_SetLeftGain(vortex_t * vortex, u16 index, u16 gain)
50562306a36Sopenharmony_ci{
50662306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	if (eq->this28 == 0)
50962306a36Sopenharmony_ci		return;
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	eq->this130[index] = gain;
51262306a36Sopenharmony_ci	if (eq->this54)
51362306a36Sopenharmony_ci		return;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	vortex_EqHw_SetLeftGainsSingleTarget(vortex, index, gain);
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistatic int vortex_Eqlzr_GetRightGain(vortex_t * vortex, u16 index, u16 * gain)
51962306a36Sopenharmony_ci{
52062306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	if (eq->this28) {
52362306a36Sopenharmony_ci		*gain = eq->this130[index + eq->this10];
52462306a36Sopenharmony_ci		return 0;
52562306a36Sopenharmony_ci	}
52662306a36Sopenharmony_ci	return 1;
52762306a36Sopenharmony_ci}
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_cistatic void vortex_Eqlzr_SetRightGain(vortex_t * vortex, u16 index, u16 gain)
53062306a36Sopenharmony_ci{
53162306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci	if (eq->this28 == 0)
53462306a36Sopenharmony_ci		return;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	eq->this130[index + eq->this10] = gain;
53762306a36Sopenharmony_ci	if (eq->this54)
53862306a36Sopenharmony_ci		return;
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	vortex_EqHw_SetRightGainsSingleTarget(vortex, index, gain);
54162306a36Sopenharmony_ci}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci#if 0
54462306a36Sopenharmony_cistatic int
54562306a36Sopenharmony_civortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, s32 *cnt)
54662306a36Sopenharmony_ci{
54762306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
54862306a36Sopenharmony_ci	int si = 0;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	if (eq->this10 == 0)
55162306a36Sopenharmony_ci		return 1;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	{
55462306a36Sopenharmony_ci		if (vortex_Eqlzr_GetLeftGain(vortex, si, &gains[si]))
55562306a36Sopenharmony_ci			return 1;
55662306a36Sopenharmony_ci		if (vortex_Eqlzr_GetRightGain
55762306a36Sopenharmony_ci		    (vortex, si, &gains[si + eq->this10]))
55862306a36Sopenharmony_ci			return 1;
55962306a36Sopenharmony_ci		si++;
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci	while (eq->this10 > si) ;
56262306a36Sopenharmony_ci	*cnt = si * 2;
56362306a36Sopenharmony_ci	return 0;
56462306a36Sopenharmony_ci}
56562306a36Sopenharmony_ci#endif
56662306a36Sopenharmony_cistatic int vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex_t * vortex)
56762306a36Sopenharmony_ci{
56862306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	vortex_EqHw_SetLeftGainsTarget(vortex, eq->this130);
57162306a36Sopenharmony_ci	vortex_EqHw_SetRightGainsTarget(vortex, &(eq->this130[eq->this10]));
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_ci	return 0;
57462306a36Sopenharmony_ci}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_cistatic int
57762306a36Sopenharmony_civortex_Eqlzr_SetAllBands(vortex_t *vortex, const u16 gains[], s32 count)
57862306a36Sopenharmony_ci{
57962306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
58062306a36Sopenharmony_ci	int i;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	if (((eq->this10) * 2 != count) || (eq->this28 == 0))
58362306a36Sopenharmony_ci		return 1;
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci	for (i = 0; i < count; i++) {
58662306a36Sopenharmony_ci		eq->this130[i] = gains[i];
58762306a36Sopenharmony_ci	}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	if (eq->this54)
59062306a36Sopenharmony_ci		return 0;
59162306a36Sopenharmony_ci	return vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
59262306a36Sopenharmony_ci}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_cistatic void
59562306a36Sopenharmony_civortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, u32 a, u32 b)
59662306a36Sopenharmony_ci{
59762306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
59862306a36Sopenharmony_ci	u32 eax, ebx;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	eq->this58 = a;
60162306a36Sopenharmony_ci	eq->this5c = b;
60262306a36Sopenharmony_ci	if (eq->this54)
60362306a36Sopenharmony_ci		eax = eq->this0e;
60462306a36Sopenharmony_ci	else
60562306a36Sopenharmony_ci		eax = eq->this0a;
60662306a36Sopenharmony_ci	ebx = (eax * eq->this58) >> 0x10;
60762306a36Sopenharmony_ci	eax = (eax * eq->this5c) >> 0x10;
60862306a36Sopenharmony_ci	vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax);
60962306a36Sopenharmony_ci}
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_cistatic void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex)
61262306a36Sopenharmony_ci{
61362306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
61462306a36Sopenharmony_ci	u32 eax, ebx;
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci	if (eq->this54)
61762306a36Sopenharmony_ci		eax = eq->this0e;
61862306a36Sopenharmony_ci	else
61962306a36Sopenharmony_ci		eax = eq->this0a;
62062306a36Sopenharmony_ci	ebx = (eax * eq->this58) >> 0x10;
62162306a36Sopenharmony_ci	eax = (eax * eq->this5c) >> 0x10;
62262306a36Sopenharmony_ci	vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax);
62362306a36Sopenharmony_ci}
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_cistatic void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
62662306a36Sopenharmony_ci{
62762306a36Sopenharmony_ci	if (vortex != NULL)
62862306a36Sopenharmony_ci		vortex_EqHw_ZeroA3DIO(vortex);
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_cistatic void vortex_Eqlzr_SetBypass(vortex_t * vortex, u32 bp)
63262306a36Sopenharmony_ci{
63362306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci	if ((eq->this28) && (bp == 0)) {
63662306a36Sopenharmony_ci		/* EQ enabled */
63762306a36Sopenharmony_ci		vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
63862306a36Sopenharmony_ci		vortex_EqHw_SetBypassGain(vortex, eq->this08, eq->this08);
63962306a36Sopenharmony_ci	} else {
64062306a36Sopenharmony_ci		/* EQ disabled. */
64162306a36Sopenharmony_ci		vortex_EqHw_SetLeftGainsTarget(vortex, eq->this14_array);
64262306a36Sopenharmony_ci		vortex_EqHw_SetRightGainsTarget(vortex, eq->this14_array);
64362306a36Sopenharmony_ci		vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c);
64462306a36Sopenharmony_ci	}
64562306a36Sopenharmony_ci	vortex_Eqlzr_ProgramA3dBypassGain(vortex);
64662306a36Sopenharmony_ci}
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_cistatic void vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex_t * vortex)
64962306a36Sopenharmony_ci{
65062306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	/* Set EQ BiQuad filter coeficients */
65362306a36Sopenharmony_ci	memcpy(&(eq->coefset), &asEqCoefsNormal, sizeof(auxxEqCoeffSet_t));
65462306a36Sopenharmony_ci	/* Set EQ Band gain levels and dump into hardware registers. */
65562306a36Sopenharmony_ci	vortex_Eqlzr_SetAllBands(vortex, eq_gains_normal, eq->this10 * 2);
65662306a36Sopenharmony_ci}
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_cistatic int vortex_Eqlzr_GetAllPeaks(vortex_t * vortex, u16 * peaks, int *count)
65962306a36Sopenharmony_ci{
66062306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	if (eq->this10 == 0)
66362306a36Sopenharmony_ci		return 1;
66462306a36Sopenharmony_ci	*count = eq->this10 * 2;
66562306a36Sopenharmony_ci	vortex_EqHw_GetTenBandLevels(vortex, peaks);
66662306a36Sopenharmony_ci	return 0;
66762306a36Sopenharmony_ci}
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci#if 0
67062306a36Sopenharmony_cistatic auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
67162306a36Sopenharmony_ci{
67262306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	return (&(eq->coefset));
67562306a36Sopenharmony_ci}
67662306a36Sopenharmony_ci#endif
67762306a36Sopenharmony_cistatic void vortex_Eqlzr_init(vortex_t * vortex)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	/* Object constructor */
68262306a36Sopenharmony_ci	//eq->this04 = 0;
68362306a36Sopenharmony_ci	eq->this08 = 0;		/* Bypass gain with EQ in use. */
68462306a36Sopenharmony_ci	eq->this0a = 0x5999;
68562306a36Sopenharmony_ci	eq->this0c = 0x5999;	/* Bypass gain with EQ disabled. */
68662306a36Sopenharmony_ci	eq->this0e = 0x5999;
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	eq->this10 = 0xa;	/* 10 eq frequency bands. */
68962306a36Sopenharmony_ci	eq->this04.this04 = eq->this10;
69062306a36Sopenharmony_ci	eq->this28 = 0x1;	/* if 1 => Allow read access to this130 (gains) */
69162306a36Sopenharmony_ci	eq->this54 = 0x0;	/* if 1 => Dont Allow access to hardware (gains) */
69262306a36Sopenharmony_ci	eq->this58 = 0xffff;
69362306a36Sopenharmony_ci	eq->this5c = 0xffff;
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	/* Set gains. */
69662306a36Sopenharmony_ci	memset(eq->this14_array, 0, sizeof(eq->this14_array));
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	/* Actual init. */
69962306a36Sopenharmony_ci	vortex_EqHw_ZeroState(vortex);
70062306a36Sopenharmony_ci	vortex_EqHw_SetSampleRate(vortex, 0x11);
70162306a36Sopenharmony_ci	vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ci	vortex_EqHw_Program10Band(vortex, &(eq->coefset));
70462306a36Sopenharmony_ci	vortex_Eqlzr_SetBypass(vortex, eq->this54);
70562306a36Sopenharmony_ci	vortex_Eqlzr_SetA3dBypassGain(vortex, 0, 0);
70662306a36Sopenharmony_ci	vortex_EqHw_Enable(vortex);
70762306a36Sopenharmony_ci}
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_cistatic void vortex_Eqlzr_shutdown(vortex_t * vortex)
71062306a36Sopenharmony_ci{
71162306a36Sopenharmony_ci	vortex_Eqlzr_ShutDownA3d(vortex);
71262306a36Sopenharmony_ci	vortex_EqHw_ProgramPipe(vortex);
71362306a36Sopenharmony_ci	vortex_EqHw_Disable(vortex);
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci/* ALSA interface */
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci/* Control interface */
71962306a36Sopenharmony_ci#define snd_vortex_eqtoggle_info	snd_ctl_boolean_mono_info
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_cistatic int
72262306a36Sopenharmony_cisnd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol,
72362306a36Sopenharmony_ci			struct snd_ctl_elem_value *ucontrol)
72462306a36Sopenharmony_ci{
72562306a36Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
72662306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
72762306a36Sopenharmony_ci	//int i = kcontrol->private_value;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = eq->this54 ? 0 : 1;
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	return 0;
73262306a36Sopenharmony_ci}
73362306a36Sopenharmony_ci
73462306a36Sopenharmony_cistatic int
73562306a36Sopenharmony_cisnd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
73662306a36Sopenharmony_ci			struct snd_ctl_elem_value *ucontrol)
73762306a36Sopenharmony_ci{
73862306a36Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
73962306a36Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
74062306a36Sopenharmony_ci	//int i = kcontrol->private_value;
74162306a36Sopenharmony_ci
74262306a36Sopenharmony_ci	eq->this54 = ucontrol->value.integer.value[0] ? 0 : 1;
74362306a36Sopenharmony_ci	vortex_Eqlzr_SetBypass(vortex, eq->this54);
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	return 1;		/* Allways changes */
74662306a36Sopenharmony_ci}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_cistatic const struct snd_kcontrol_new vortex_eqtoggle_kcontrol = {
74962306a36Sopenharmony_ci	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
75062306a36Sopenharmony_ci	.name = "EQ Enable",
75162306a36Sopenharmony_ci	.index = 0,
75262306a36Sopenharmony_ci	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
75362306a36Sopenharmony_ci	.private_value = 0,
75462306a36Sopenharmony_ci	.info = snd_vortex_eqtoggle_info,
75562306a36Sopenharmony_ci	.get = snd_vortex_eqtoggle_get,
75662306a36Sopenharmony_ci	.put = snd_vortex_eqtoggle_put
75762306a36Sopenharmony_ci};
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_cistatic int
76062306a36Sopenharmony_cisnd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
76162306a36Sopenharmony_ci{
76262306a36Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
76362306a36Sopenharmony_ci	uinfo->count = 2;
76462306a36Sopenharmony_ci	uinfo->value.integer.min = 0x0000;
76562306a36Sopenharmony_ci	uinfo->value.integer.max = 0x7fff;
76662306a36Sopenharmony_ci	return 0;
76762306a36Sopenharmony_ci}
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_cistatic int
77062306a36Sopenharmony_cisnd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
77162306a36Sopenharmony_ci{
77262306a36Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
77362306a36Sopenharmony_ci	int i = kcontrol->private_value;
77462306a36Sopenharmony_ci	u16 gainL = 0, gainR = 0;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
77762306a36Sopenharmony_ci	vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
77862306a36Sopenharmony_ci	ucontrol->value.integer.value[0] = gainL;
77962306a36Sopenharmony_ci	ucontrol->value.integer.value[1] = gainR;
78062306a36Sopenharmony_ci	return 0;
78162306a36Sopenharmony_ci}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_cistatic int
78462306a36Sopenharmony_cisnd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
78562306a36Sopenharmony_ci{
78662306a36Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
78762306a36Sopenharmony_ci	int changed = 0, i = kcontrol->private_value;
78862306a36Sopenharmony_ci	u16 gainL = 0, gainR = 0;
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
79162306a36Sopenharmony_ci	vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	if (gainL != ucontrol->value.integer.value[0]) {
79462306a36Sopenharmony_ci		vortex_Eqlzr_SetLeftGain(vortex, i,
79562306a36Sopenharmony_ci					 ucontrol->value.integer.value[0]);
79662306a36Sopenharmony_ci		changed = 1;
79762306a36Sopenharmony_ci	}
79862306a36Sopenharmony_ci	if (gainR != ucontrol->value.integer.value[1]) {
79962306a36Sopenharmony_ci		vortex_Eqlzr_SetRightGain(vortex, i,
80062306a36Sopenharmony_ci					  ucontrol->value.integer.value[1]);
80162306a36Sopenharmony_ci		changed = 1;
80262306a36Sopenharmony_ci	}
80362306a36Sopenharmony_ci	return changed;
80462306a36Sopenharmony_ci}
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_cistatic const struct snd_kcontrol_new vortex_eq_kcontrol = {
80762306a36Sopenharmony_ci	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
80862306a36Sopenharmony_ci	.name = "                        .",
80962306a36Sopenharmony_ci	.index = 0,
81062306a36Sopenharmony_ci	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
81162306a36Sopenharmony_ci	.private_value = 0,
81262306a36Sopenharmony_ci	.info = snd_vortex_eq_info,
81362306a36Sopenharmony_ci	.get = snd_vortex_eq_get,
81462306a36Sopenharmony_ci	.put = snd_vortex_eq_put
81562306a36Sopenharmony_ci};
81662306a36Sopenharmony_ci
81762306a36Sopenharmony_cistatic int
81862306a36Sopenharmony_cisnd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
81962306a36Sopenharmony_ci{
82062306a36Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
82162306a36Sopenharmony_ci	uinfo->count = 20;
82262306a36Sopenharmony_ci	uinfo->value.integer.min = 0x0000;
82362306a36Sopenharmony_ci	uinfo->value.integer.max = 0x7fff;
82462306a36Sopenharmony_ci	return 0;
82562306a36Sopenharmony_ci}
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_cistatic int
82862306a36Sopenharmony_cisnd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
82962306a36Sopenharmony_ci{
83062306a36Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
83162306a36Sopenharmony_ci	int i, count = 0;
83262306a36Sopenharmony_ci	u16 peaks[20];
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count);
83562306a36Sopenharmony_ci	if (count != 20) {
83662306a36Sopenharmony_ci		dev_err(vortex->card->dev,
83762306a36Sopenharmony_ci			"peak count error 20 != %d\n", count);
83862306a36Sopenharmony_ci		return -1;
83962306a36Sopenharmony_ci	}
84062306a36Sopenharmony_ci	for (i = 0; i < 20; i++)
84162306a36Sopenharmony_ci		ucontrol->value.integer.value[i] = peaks[i];
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	return 0;
84462306a36Sopenharmony_ci}
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_cistatic const struct snd_kcontrol_new vortex_levels_kcontrol = {
84762306a36Sopenharmony_ci	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
84862306a36Sopenharmony_ci	.name = "EQ Peaks",
84962306a36Sopenharmony_ci	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
85062306a36Sopenharmony_ci	.info = snd_vortex_peaks_info,
85162306a36Sopenharmony_ci	.get = snd_vortex_peaks_get,
85262306a36Sopenharmony_ci};
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci/* EQ band gain labels. */
85562306a36Sopenharmony_cistatic const char * const EqBandLabels[10] = {
85662306a36Sopenharmony_ci	"EQ0 31Hz\0",
85762306a36Sopenharmony_ci	"EQ1 63Hz\0",
85862306a36Sopenharmony_ci	"EQ2 125Hz\0",
85962306a36Sopenharmony_ci	"EQ3 250Hz\0",
86062306a36Sopenharmony_ci	"EQ4 500Hz\0",
86162306a36Sopenharmony_ci	"EQ5 1KHz\0",
86262306a36Sopenharmony_ci	"EQ6 2KHz\0",
86362306a36Sopenharmony_ci	"EQ7 4KHz\0",
86462306a36Sopenharmony_ci	"EQ8 8KHz\0",
86562306a36Sopenharmony_ci	"EQ9 16KHz\0",
86662306a36Sopenharmony_ci};
86762306a36Sopenharmony_ci
86862306a36Sopenharmony_ci/* ALSA driver entry points. Init and exit. */
86962306a36Sopenharmony_cistatic int vortex_eq_init(vortex_t *vortex)
87062306a36Sopenharmony_ci{
87162306a36Sopenharmony_ci	struct snd_kcontrol *kcontrol;
87262306a36Sopenharmony_ci	int err, i;
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	vortex_Eqlzr_init(vortex);
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	kcontrol = snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex);
87762306a36Sopenharmony_ci	if (!kcontrol)
87862306a36Sopenharmony_ci		return -ENOMEM;
87962306a36Sopenharmony_ci	kcontrol->private_value = 0;
88062306a36Sopenharmony_ci	err = snd_ctl_add(vortex->card, kcontrol);
88162306a36Sopenharmony_ci	if (err < 0)
88262306a36Sopenharmony_ci		return err;
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci	/* EQ gain controls */
88562306a36Sopenharmony_ci	for (i = 0; i < 10; i++) {
88662306a36Sopenharmony_ci		kcontrol = snd_ctl_new1(&vortex_eq_kcontrol, vortex);
88762306a36Sopenharmony_ci		if (!kcontrol)
88862306a36Sopenharmony_ci			return -ENOMEM;
88962306a36Sopenharmony_ci		snprintf(kcontrol->id.name, sizeof(kcontrol->id.name),
89062306a36Sopenharmony_ci			"%s Playback Volume", EqBandLabels[i]);
89162306a36Sopenharmony_ci		kcontrol->private_value = i;
89262306a36Sopenharmony_ci		err = snd_ctl_add(vortex->card, kcontrol);
89362306a36Sopenharmony_ci		if (err < 0)
89462306a36Sopenharmony_ci			return err;
89562306a36Sopenharmony_ci		//vortex->eqctrl[i] = kcontrol;
89662306a36Sopenharmony_ci	}
89762306a36Sopenharmony_ci	/* EQ band levels */
89862306a36Sopenharmony_ci	kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex);
89962306a36Sopenharmony_ci	if (!kcontrol)
90062306a36Sopenharmony_ci		return -ENOMEM;
90162306a36Sopenharmony_ci	err = snd_ctl_add(vortex->card, kcontrol);
90262306a36Sopenharmony_ci	if (err < 0)
90362306a36Sopenharmony_ci		return err;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	return 0;
90662306a36Sopenharmony_ci}
90762306a36Sopenharmony_ci
90862306a36Sopenharmony_cistatic int vortex_eq_free(vortex_t * vortex)
90962306a36Sopenharmony_ci{
91062306a36Sopenharmony_ci	/*
91162306a36Sopenharmony_ci	   //FIXME: segfault because vortex->eqctrl[i] == 4
91262306a36Sopenharmony_ci	   int i;
91362306a36Sopenharmony_ci	   for (i=0; i<10; i++) {
91462306a36Sopenharmony_ci	   if (vortex->eqctrl[i])
91562306a36Sopenharmony_ci	   snd_ctl_remove(vortex->card, vortex->eqctrl[i]);
91662306a36Sopenharmony_ci	   }
91762306a36Sopenharmony_ci	 */
91862306a36Sopenharmony_ci	vortex_Eqlzr_shutdown(vortex);
91962306a36Sopenharmony_ci	return 0;
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci/* End */
923