18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/***************************************************************************
38c2ecf20Sopenharmony_ci *            au88x0_eq.c
48c2ecf20Sopenharmony_ci *  Aureal Vortex Hardware EQ control/access.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci *  Sun Jun  8 18:19:19 2003
78c2ecf20Sopenharmony_ci *  2003  Manuel Jander (mjander@users.sourceforge.net)
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci *  02 July 2003: First time something works :)
108c2ecf20Sopenharmony_ci *  November 2003: A3D Bypass code completed but untested.
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci *  TODO:
138c2ecf20Sopenharmony_ci *     - Debug (testing)
148c2ecf20Sopenharmony_ci *     - Test peak visualization support.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci ****************************************************************************/
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci/*
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci/*
228c2ecf20Sopenharmony_ci The Aureal Hardware EQ is found on AU8810 and AU8830 chips only.
238c2ecf20Sopenharmony_ci it has 4 inputs (2 for general mix, 2 for A3D) and 2 outputs (supposed
248c2ecf20Sopenharmony_ci to be routed to the codec).
258c2ecf20Sopenharmony_ci*/
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci#include "au88x0.h"
288c2ecf20Sopenharmony_ci#include "au88x0_eq.h"
298c2ecf20Sopenharmony_ci#include "au88x0_eqdata.c"
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define VORTEX_EQ_BASE	 0x2b000
328c2ecf20Sopenharmony_ci#define VORTEX_EQ_DEST   (VORTEX_EQ_BASE + 0x410)
338c2ecf20Sopenharmony_ci#define VORTEX_EQ_SOURCE (VORTEX_EQ_BASE + 0x430)
348c2ecf20Sopenharmony_ci#define VORTEX_EQ_CTRL   (VORTEX_EQ_BASE + 0x440)
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define VORTEX_BAND_COEFF_SIZE 0x30
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci/* CEqHw.s */
398c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetTimeConsts(vortex_t * vortex, u16 gain, u16 level)
408c2ecf20Sopenharmony_ci{
418c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3c4, gain);
428c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3c8, level);
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic inline u16 sign_invert(u16 a)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	/* -(-32768) -> -32768 so we do -(-32768) -> 32767 to make the result positive */
488c2ecf20Sopenharmony_ci	if (a == (u16)-32768)
498c2ecf20Sopenharmony_ci		return 32767;
508c2ecf20Sopenharmony_ci	else
518c2ecf20Sopenharmony_ci		return -a;
528c2ecf20Sopenharmony_ci}
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetLeftCoefs(vortex_t *vortex, const u16 coefs[])
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
578c2ecf20Sopenharmony_ci	int i = 0, n /*esp2c */;
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	for (n = 0; n < eqhw->this04; n++) {
608c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b000 + n * 0x30, coefs[i + 0]);
618c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b004 + n * 0x30, coefs[i + 1]);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci		if (eqhw->this08 == 0) {
648c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, coefs[i + 2]);
658c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, coefs[i + 3]);
668c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b010 + n * 0x30, coefs[i + 4]);
678c2ecf20Sopenharmony_ci		} else {
688c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b008 + n * 0x30, sign_invert(coefs[2 + i]));
698c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b00c + n * 0x30, sign_invert(coefs[3 + i]));
708c2ecf20Sopenharmony_ci		        hwwrite(vortex->mmio, 0x2b010 + n * 0x30, sign_invert(coefs[4 + i]));
718c2ecf20Sopenharmony_ci		}
728c2ecf20Sopenharmony_ci		i += 5;
738c2ecf20Sopenharmony_ci	}
748c2ecf20Sopenharmony_ci}
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetRightCoefs(vortex_t *vortex, const u16 coefs[])
778c2ecf20Sopenharmony_ci{
788c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
798c2ecf20Sopenharmony_ci	int i = 0, n /*esp2c */;
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	for (n = 0; n < eqhw->this04; n++) {
828c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1e0 + n * 0x30, coefs[0 + i]);
838c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1e4 + n * 0x30, coefs[1 + i]);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci		if (eqhw->this08 == 0) {
868c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, coefs[2 + i]);
878c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, coefs[3 + i]);
888c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, coefs[4 + i]);
898c2ecf20Sopenharmony_ci		} else {
908c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1e8 + n * 0x30, sign_invert(coefs[2 + i]));
918c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1ec + n * 0x30, sign_invert(coefs[3 + i]));
928c2ecf20Sopenharmony_ci			hwwrite(vortex->mmio, 0x2b1f0 + n * 0x30, sign_invert(coefs[4 + i]));
938c2ecf20Sopenharmony_ci		}
948c2ecf20Sopenharmony_ci		i += 5;
958c2ecf20Sopenharmony_ci	}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetLeftStates(vortex_t *vortex, const u16 a[], const u16 b[])
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
1028c2ecf20Sopenharmony_ci	int i = 0, ebx;
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3fc, a[0]);
1058c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b400, a[1]);
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
1088c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b014 + (i * 0xc), b[i]);
1098c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b018 + (i * 0xc), b[1 + i]);
1108c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b01c + (i * 0xc), b[2 + i]);
1118c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b020 + (i * 0xc), b[3 + i]);
1128c2ecf20Sopenharmony_ci		i += 4;
1138c2ecf20Sopenharmony_ci	}
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetRightStates(vortex_t *vortex, const u16 a[], const u16 b[])
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
1198c2ecf20Sopenharmony_ci	int i = 0, ebx;
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b404, a[0]);
1228c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b408, a[1]);
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
1258c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1f4 + (i * 0xc), b[i]);
1268c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1f8 + (i * 0xc), b[1 + i]);
1278c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b1fc + (i * 0xc), b[2 + i]);
1288c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b200 + (i * 0xc), b[3 + i]);
1298c2ecf20Sopenharmony_ci		i += 4;
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci#if 0
1348c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetTimeConsts(vortex_t * vortex, u16 * a, u16 * b)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	*a = hwread(vortex->mmio, 0x2b3c4);
1378c2ecf20Sopenharmony_ci	*b = hwread(vortex->mmio, 0x2b3c8);
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetLeftCoefs(vortex_t * vortex, u16 a[])
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ci}
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetRightCoefs(vortex_t * vortex, u16 a[])
1468c2ecf20Sopenharmony_ci{
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetLeftStates(vortex_t * vortex, u16 * a, u16 b[])
1518c2ecf20Sopenharmony_ci{
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetRightStates(vortex_t * vortex, u16 * a, u16 b[])
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci#endif
1618c2ecf20Sopenharmony_ci/* Mix Gains */
1628c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetBypassGain(vortex_t * vortex, u16 a, u16 b)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
1658c2ecf20Sopenharmony_ci	if (eqhw->this08 == 0) {
1668c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b3d4, a);
1678c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b3ec, b);
1688c2ecf20Sopenharmony_ci	} else {
1698c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b3d4, sign_invert(a));
1708c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b3ec, sign_invert(b));
1718c2ecf20Sopenharmony_ci	}
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetA3DBypassGain(vortex_t * vortex, u16 a, u16 b)
1758c2ecf20Sopenharmony_ci{
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3e0, a);
1788c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3f8, b);
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci#if 0
1828c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetCurrBypassGain(vortex_t * vortex, u16 a, u16 b)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3d0, a);
1868c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3e8, b);
1878c2ecf20Sopenharmony_ci}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetCurrA3DBypassGain(vortex_t * vortex, u16 a, u16 b)
1908c2ecf20Sopenharmony_ci{
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3dc, a);
1938c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3f4, b);
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci#endif
1978c2ecf20Sopenharmony_cistatic void
1988c2ecf20Sopenharmony_civortex_EqHw_SetLeftGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
1998c2ecf20Sopenharmony_ci{
2008c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b02c + (index * 0x30), b);
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistatic void
2048c2ecf20Sopenharmony_civortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetLeftGainsTarget(vortex_t *vortex, const u16 a[])
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
2128c2ecf20Sopenharmony_ci	int ebx;
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
2158c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b02c + ebx * 0x30, a[ebx]);
2168c2ecf20Sopenharmony_ci	}
2178c2ecf20Sopenharmony_ci}
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetRightGainsTarget(vortex_t *vortex, const u16 a[])
2208c2ecf20Sopenharmony_ci{
2218c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
2228c2ecf20Sopenharmony_ci	int ebx;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
2258c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b20c + ebx * 0x30, a[ebx]);
2268c2ecf20Sopenharmony_ci	}
2278c2ecf20Sopenharmony_ci}
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetLeftGainsCurrent(vortex_t *vortex, const u16 a[])
2308c2ecf20Sopenharmony_ci{
2318c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
2328c2ecf20Sopenharmony_ci	int ebx;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
2358c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b028 + ebx * 0x30, a[ebx]);
2368c2ecf20Sopenharmony_ci	}
2378c2ecf20Sopenharmony_ci}
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetRightGainsCurrent(vortex_t *vortex, const u16 a[])
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
2428c2ecf20Sopenharmony_ci	int ebx;
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci	for (ebx = 0; ebx < eqhw->this04; ebx++) {
2458c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b208 + ebx * 0x30, a[ebx]);
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci#if 0
2508c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetLeftGainsTarget(vortex_t * vortex, u16 a[])
2518c2ecf20Sopenharmony_ci{
2528c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
2538c2ecf20Sopenharmony_ci	int ebx = 0;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	if (eqhw->this04 < 0)
2568c2ecf20Sopenharmony_ci		return;
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	do {
2598c2ecf20Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b02c + ebx * 0x30);
2608c2ecf20Sopenharmony_ci		ebx++;
2618c2ecf20Sopenharmony_ci	}
2628c2ecf20Sopenharmony_ci	while (ebx < eqhw->this04);
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetRightGainsTarget(vortex_t * vortex, u16 a[])
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
2688c2ecf20Sopenharmony_ci	int ebx = 0;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	if (eqhw->this04 < 0)
2718c2ecf20Sopenharmony_ci		return;
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	do {
2748c2ecf20Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b20c + ebx * 0x30);
2758c2ecf20Sopenharmony_ci		ebx++;
2768c2ecf20Sopenharmony_ci	}
2778c2ecf20Sopenharmony_ci	while (ebx < eqhw->this04);
2788c2ecf20Sopenharmony_ci}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetLeftGainsCurrent(vortex_t * vortex, u16 a[])
2818c2ecf20Sopenharmony_ci{
2828c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
2838c2ecf20Sopenharmony_ci	int ebx = 0;
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	if (eqhw->this04 < 0)
2868c2ecf20Sopenharmony_ci		return;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	do {
2898c2ecf20Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b028 + ebx * 0x30);
2908c2ecf20Sopenharmony_ci		ebx++;
2918c2ecf20Sopenharmony_ci	}
2928c2ecf20Sopenharmony_ci	while (ebx < eqhw->this04);
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetRightGainsCurrent(vortex_t * vortex, u16 a[])
2968c2ecf20Sopenharmony_ci{
2978c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
2988c2ecf20Sopenharmony_ci	int ebx = 0;
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	if (eqhw->this04 < 0)
3018c2ecf20Sopenharmony_ci		return;
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	do {
3048c2ecf20Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b208 + ebx * 0x30);
3058c2ecf20Sopenharmony_ci		ebx++;
3068c2ecf20Sopenharmony_ci	}
3078c2ecf20Sopenharmony_ci	while (ebx < eqhw->this04);
3088c2ecf20Sopenharmony_ci}
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci#endif
3118c2ecf20Sopenharmony_ci/* EQ band levels settings */
3128c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetLevels(vortex_t *vortex, const u16 peaks[])
3138c2ecf20Sopenharmony_ci{
3148c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
3158c2ecf20Sopenharmony_ci	int i;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	/* set left peaks */
3188c2ecf20Sopenharmony_ci	for (i = 0; i < eqhw->this04; i++) {
3198c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b024 + i * VORTEX_BAND_COEFF_SIZE, peaks[i]);
3208c2ecf20Sopenharmony_ci	}
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3cc, peaks[eqhw->this04]);
3238c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3d8, peaks[eqhw->this04 + 1]);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	/* set right peaks */
3268c2ecf20Sopenharmony_ci	for (i = 0; i < eqhw->this04; i++) {
3278c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, 0x2b204 + i * VORTEX_BAND_COEFF_SIZE,
3288c2ecf20Sopenharmony_ci			peaks[i + (eqhw->this04 + 2)]);
3298c2ecf20Sopenharmony_ci	}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3e4, peaks[2 + (eqhw->this04 * 2)]);
3328c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3f0, peaks[3 + (eqhw->this04 * 2)]);
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci#if 0
3368c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetLevels(vortex_t * vortex, u16 a[])
3378c2ecf20Sopenharmony_ci{
3388c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
3398c2ecf20Sopenharmony_ci	int ebx;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci	if (eqhw->this04 < 0)
3428c2ecf20Sopenharmony_ci		return;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	ebx = 0;
3458c2ecf20Sopenharmony_ci	do {
3468c2ecf20Sopenharmony_ci		a[ebx] = hwread(vortex->mmio, 0x2b024 + ebx * 0x30);
3478c2ecf20Sopenharmony_ci		ebx++;
3488c2ecf20Sopenharmony_ci	}
3498c2ecf20Sopenharmony_ci	while (ebx < eqhw->this04);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	a[eqhw->this04] = hwread(vortex->mmio, 0x2b3cc);
3528c2ecf20Sopenharmony_ci	a[eqhw->this04 + 1] = hwread(vortex->mmio, 0x2b3d8);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	ebx = 0;
3558c2ecf20Sopenharmony_ci	do {
3568c2ecf20Sopenharmony_ci		a[ebx + (eqhw->this04 + 2)] =
3578c2ecf20Sopenharmony_ci		    hwread(vortex->mmio, 0x2b204 + ebx * 0x30);
3588c2ecf20Sopenharmony_ci		ebx++;
3598c2ecf20Sopenharmony_ci	}
3608c2ecf20Sopenharmony_ci	while (ebx < eqhw->this04);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	a[2 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3e4);
3638c2ecf20Sopenharmony_ci	a[3 + (eqhw->this04 * 2)] = hwread(vortex->mmio, 0x2b3f0);
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci#endif
3678c2ecf20Sopenharmony_ci/* Global Control */
3688c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetControlReg(vortex_t * vortex, u32 reg)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b440, reg);
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_cistatic void vortex_EqHw_SetSampleRate(vortex_t * vortex, u32 sr)
3748c2ecf20Sopenharmony_ci{
3758c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b440, ((sr & 0x1f) << 3) | 0xb800);
3768c2ecf20Sopenharmony_ci}
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci#if 0
3798c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetControlReg(vortex_t * vortex, u32 *reg)
3808c2ecf20Sopenharmony_ci{
3818c2ecf20Sopenharmony_ci	*reg = hwread(vortex->mmio, 0x2b440);
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetSampleRate(vortex_t * vortex, u32 *sr)
3858c2ecf20Sopenharmony_ci{
3868c2ecf20Sopenharmony_ci	*sr = (hwread(vortex->mmio, 0x2b440) >> 3) & 0x1f;
3878c2ecf20Sopenharmony_ci}
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci#endif
3908c2ecf20Sopenharmony_cistatic void vortex_EqHw_Enable(vortex_t * vortex)
3918c2ecf20Sopenharmony_ci{
3928c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf001);
3938c2ecf20Sopenharmony_ci}
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_cistatic void vortex_EqHw_Disable(vortex_t * vortex)
3968c2ecf20Sopenharmony_ci{
3978c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, VORTEX_EQ_CTRL, 0xf000);
3988c2ecf20Sopenharmony_ci}
3998c2ecf20Sopenharmony_ci
4008c2ecf20Sopenharmony_ci/* Reset (zero) buffers */
4018c2ecf20Sopenharmony_cistatic void vortex_EqHw_ZeroIO(vortex_t * vortex)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	int i;
4048c2ecf20Sopenharmony_ci	for (i = 0; i < 0x8; i++)
4058c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
4068c2ecf20Sopenharmony_ci	for (i = 0; i < 0x4; i++)
4078c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, VORTEX_EQ_SOURCE + (i << 2), 0x0);
4088c2ecf20Sopenharmony_ci}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_cistatic void vortex_EqHw_ZeroA3DIO(vortex_t * vortex)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	int i;
4138c2ecf20Sopenharmony_ci	for (i = 0; i < 0x4; i++)
4148c2ecf20Sopenharmony_ci		hwwrite(vortex->mmio, VORTEX_EQ_DEST + (i << 2), 0x0);
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_cistatic void vortex_EqHw_ZeroState(vortex_t * vortex)
4188c2ecf20Sopenharmony_ci{
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_ci	vortex_EqHw_SetControlReg(vortex, 0);
4218c2ecf20Sopenharmony_ci	vortex_EqHw_ZeroIO(vortex);
4228c2ecf20Sopenharmony_ci	hwwrite(vortex->mmio, 0x2b3c0, 0);
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	vortex_EqHw_SetTimeConsts(vortex, 0, 0);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsZeros);
4278c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightCoefs(vortex, asEqCoefsZeros);
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_zero);
4308c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_zero);
4318c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_zero);
4328c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_zero);
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	vortex_EqHw_SetBypassGain(vortex, 0, 0);
4358c2ecf20Sopenharmony_ci	//vortex_EqHw_SetCurrBypassGain(vortex, 0, 0);
4368c2ecf20Sopenharmony_ci	vortex_EqHw_SetA3DBypassGain(vortex, 0, 0);
4378c2ecf20Sopenharmony_ci	//vortex_EqHw_SetCurrA3DBypassGain(vortex, 0, 0);
4388c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftStates(vortex, eq_states_zero, asEqOutStateZeros);
4398c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightStates(vortex, eq_states_zero, asEqOutStateZeros);
4408c2ecf20Sopenharmony_ci	vortex_EqHw_SetLevels(vortex, (u16 *) eq_levels);
4418c2ecf20Sopenharmony_ci}
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci/* Program coeficients as pass through */
4448c2ecf20Sopenharmony_cistatic void vortex_EqHw_ProgramPipe(vortex_t * vortex)
4458c2ecf20Sopenharmony_ci{
4468c2ecf20Sopenharmony_ci	vortex_EqHw_SetTimeConsts(vortex, 0, 0);
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftCoefs(vortex, asEqCoefsPipes);
4498c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightCoefs(vortex, asEqCoefsPipes);
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftGainsCurrent(vortex, eq_gains_current);
4528c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightGainsCurrent(vortex, eq_gains_current);
4538c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftGainsTarget(vortex, eq_gains_current);
4548c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightGainsTarget(vortex, eq_gains_current);
4558c2ecf20Sopenharmony_ci}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci/* Program EQ block as 10 band Equalizer */
4588c2ecf20Sopenharmony_cistatic void
4598c2ecf20Sopenharmony_civortex_EqHw_Program10Band(vortex_t * vortex, auxxEqCoeffSet_t * coefset)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci	vortex_EqHw_SetTimeConsts(vortex, 0xc, 0x7fe0);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftCoefs(vortex, coefset->LeftCoefs);
4658c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightCoefs(vortex, coefset->RightCoefs);
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftGainsCurrent(vortex, coefset->LeftGains);
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightGainsTarget(vortex, coefset->RightGains);
4708c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftGainsTarget(vortex, coefset->LeftGains);
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightGainsCurrent(vortex, coefset->RightGains);
4738c2ecf20Sopenharmony_ci}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci/* Read all EQ peaks. (think VU meter) */
4768c2ecf20Sopenharmony_cistatic void vortex_EqHw_GetTenBandLevels(vortex_t * vortex, u16 peaks[])
4778c2ecf20Sopenharmony_ci{
4788c2ecf20Sopenharmony_ci	eqhw_t *eqhw = &(vortex->eq.this04);
4798c2ecf20Sopenharmony_ci	int i;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	if (eqhw->this04 <= 0)
4828c2ecf20Sopenharmony_ci		return;
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci	for (i = 0; i < eqhw->this04; i++)
4858c2ecf20Sopenharmony_ci		peaks[i] = hwread(vortex->mmio, 0x2B024 + i * 0x30);
4868c2ecf20Sopenharmony_ci	for (i = 0; i < eqhw->this04; i++)
4878c2ecf20Sopenharmony_ci		peaks[i + eqhw->this04] =
4888c2ecf20Sopenharmony_ci		    hwread(vortex->mmio, 0x2B204 + i * 0x30);
4898c2ecf20Sopenharmony_ci}
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci/* CEqlzr.s */
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_cistatic int vortex_Eqlzr_GetLeftGain(vortex_t * vortex, u16 index, u16 * gain)
4948c2ecf20Sopenharmony_ci{
4958c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	if (eq->this28) {
4988c2ecf20Sopenharmony_ci		*gain = eq->this130[index];
4998c2ecf20Sopenharmony_ci		return 0;
5008c2ecf20Sopenharmony_ci	}
5018c2ecf20Sopenharmony_ci	return 1;
5028c2ecf20Sopenharmony_ci}
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_cistatic void vortex_Eqlzr_SetLeftGain(vortex_t * vortex, u16 index, u16 gain)
5058c2ecf20Sopenharmony_ci{
5068c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci	if (eq->this28 == 0)
5098c2ecf20Sopenharmony_ci		return;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	eq->this130[index] = gain;
5128c2ecf20Sopenharmony_ci	if (eq->this54)
5138c2ecf20Sopenharmony_ci		return;
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftGainsSingleTarget(vortex, index, gain);
5168c2ecf20Sopenharmony_ci}
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_cistatic int vortex_Eqlzr_GetRightGain(vortex_t * vortex, u16 index, u16 * gain)
5198c2ecf20Sopenharmony_ci{
5208c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	if (eq->this28) {
5238c2ecf20Sopenharmony_ci		*gain = eq->this130[index + eq->this10];
5248c2ecf20Sopenharmony_ci		return 0;
5258c2ecf20Sopenharmony_ci	}
5268c2ecf20Sopenharmony_ci	return 1;
5278c2ecf20Sopenharmony_ci}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_cistatic void vortex_Eqlzr_SetRightGain(vortex_t * vortex, u16 index, u16 gain)
5308c2ecf20Sopenharmony_ci{
5318c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
5328c2ecf20Sopenharmony_ci
5338c2ecf20Sopenharmony_ci	if (eq->this28 == 0)
5348c2ecf20Sopenharmony_ci		return;
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	eq->this130[index + eq->this10] = gain;
5378c2ecf20Sopenharmony_ci	if (eq->this54)
5388c2ecf20Sopenharmony_ci		return;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightGainsSingleTarget(vortex, index, gain);
5418c2ecf20Sopenharmony_ci}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci#if 0
5448c2ecf20Sopenharmony_cistatic int
5458c2ecf20Sopenharmony_civortex_Eqlzr_GetAllBands(vortex_t * vortex, u16 * gains, s32 *cnt)
5468c2ecf20Sopenharmony_ci{
5478c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
5488c2ecf20Sopenharmony_ci	int si = 0;
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci	if (eq->this10 == 0)
5518c2ecf20Sopenharmony_ci		return 1;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci	{
5548c2ecf20Sopenharmony_ci		if (vortex_Eqlzr_GetLeftGain(vortex, si, &gains[si]))
5558c2ecf20Sopenharmony_ci			return 1;
5568c2ecf20Sopenharmony_ci		if (vortex_Eqlzr_GetRightGain
5578c2ecf20Sopenharmony_ci		    (vortex, si, &gains[si + eq->this10]))
5588c2ecf20Sopenharmony_ci			return 1;
5598c2ecf20Sopenharmony_ci		si++;
5608c2ecf20Sopenharmony_ci	}
5618c2ecf20Sopenharmony_ci	while (eq->this10 > si) ;
5628c2ecf20Sopenharmony_ci	*cnt = si * 2;
5638c2ecf20Sopenharmony_ci	return 0;
5648c2ecf20Sopenharmony_ci}
5658c2ecf20Sopenharmony_ci#endif
5668c2ecf20Sopenharmony_cistatic int vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex_t * vortex)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_ci	vortex_EqHw_SetLeftGainsTarget(vortex, eq->this130);
5718c2ecf20Sopenharmony_ci	vortex_EqHw_SetRightGainsTarget(vortex, &(eq->this130[eq->this10]));
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	return 0;
5748c2ecf20Sopenharmony_ci}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_cistatic int
5778c2ecf20Sopenharmony_civortex_Eqlzr_SetAllBands(vortex_t *vortex, const u16 gains[], s32 count)
5788c2ecf20Sopenharmony_ci{
5798c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
5808c2ecf20Sopenharmony_ci	int i;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	if (((eq->this10) * 2 != count) || (eq->this28 == 0))
5838c2ecf20Sopenharmony_ci		return 1;
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci	for (i = 0; i < count; i++) {
5868c2ecf20Sopenharmony_ci		eq->this130[i] = gains[i];
5878c2ecf20Sopenharmony_ci	}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_ci	if (eq->this54)
5908c2ecf20Sopenharmony_ci		return 0;
5918c2ecf20Sopenharmony_ci	return vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_cistatic void
5958c2ecf20Sopenharmony_civortex_Eqlzr_SetA3dBypassGain(vortex_t * vortex, u32 a, u32 b)
5968c2ecf20Sopenharmony_ci{
5978c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
5988c2ecf20Sopenharmony_ci	u32 eax, ebx;
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	eq->this58 = a;
6018c2ecf20Sopenharmony_ci	eq->this5c = b;
6028c2ecf20Sopenharmony_ci	if (eq->this54)
6038c2ecf20Sopenharmony_ci		eax = eq->this0e;
6048c2ecf20Sopenharmony_ci	else
6058c2ecf20Sopenharmony_ci		eax = eq->this0a;
6068c2ecf20Sopenharmony_ci	ebx = (eax * eq->this58) >> 0x10;
6078c2ecf20Sopenharmony_ci	eax = (eax * eq->this5c) >> 0x10;
6088c2ecf20Sopenharmony_ci	vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax);
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_cistatic void vortex_Eqlzr_ProgramA3dBypassGain(vortex_t * vortex)
6128c2ecf20Sopenharmony_ci{
6138c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
6148c2ecf20Sopenharmony_ci	u32 eax, ebx;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	if (eq->this54)
6178c2ecf20Sopenharmony_ci		eax = eq->this0e;
6188c2ecf20Sopenharmony_ci	else
6198c2ecf20Sopenharmony_ci		eax = eq->this0a;
6208c2ecf20Sopenharmony_ci	ebx = (eax * eq->this58) >> 0x10;
6218c2ecf20Sopenharmony_ci	eax = (eax * eq->this5c) >> 0x10;
6228c2ecf20Sopenharmony_ci	vortex_EqHw_SetA3DBypassGain(vortex, ebx, eax);
6238c2ecf20Sopenharmony_ci}
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_cistatic void vortex_Eqlzr_ShutDownA3d(vortex_t * vortex)
6268c2ecf20Sopenharmony_ci{
6278c2ecf20Sopenharmony_ci	if (vortex != NULL)
6288c2ecf20Sopenharmony_ci		vortex_EqHw_ZeroA3DIO(vortex);
6298c2ecf20Sopenharmony_ci}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_cistatic void vortex_Eqlzr_SetBypass(vortex_t * vortex, u32 bp)
6328c2ecf20Sopenharmony_ci{
6338c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	if ((eq->this28) && (bp == 0)) {
6368c2ecf20Sopenharmony_ci		/* EQ enabled */
6378c2ecf20Sopenharmony_ci		vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex);
6388c2ecf20Sopenharmony_ci		vortex_EqHw_SetBypassGain(vortex, eq->this08, eq->this08);
6398c2ecf20Sopenharmony_ci	} else {
6408c2ecf20Sopenharmony_ci		/* EQ disabled. */
6418c2ecf20Sopenharmony_ci		vortex_EqHw_SetLeftGainsTarget(vortex, eq->this14_array);
6428c2ecf20Sopenharmony_ci		vortex_EqHw_SetRightGainsTarget(vortex, eq->this14_array);
6438c2ecf20Sopenharmony_ci		vortex_EqHw_SetBypassGain(vortex, eq->this0c, eq->this0c);
6448c2ecf20Sopenharmony_ci	}
6458c2ecf20Sopenharmony_ci	vortex_Eqlzr_ProgramA3dBypassGain(vortex);
6468c2ecf20Sopenharmony_ci}
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_cistatic void vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex_t * vortex)
6498c2ecf20Sopenharmony_ci{
6508c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	/* Set EQ BiQuad filter coeficients */
6538c2ecf20Sopenharmony_ci	memcpy(&(eq->coefset), &asEqCoefsNormal, sizeof(auxxEqCoeffSet_t));
6548c2ecf20Sopenharmony_ci	/* Set EQ Band gain levels and dump into hardware registers. */
6558c2ecf20Sopenharmony_ci	vortex_Eqlzr_SetAllBands(vortex, eq_gains_normal, eq->this10 * 2);
6568c2ecf20Sopenharmony_ci}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_cistatic int vortex_Eqlzr_GetAllPeaks(vortex_t * vortex, u16 * peaks, int *count)
6598c2ecf20Sopenharmony_ci{
6608c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
6618c2ecf20Sopenharmony_ci
6628c2ecf20Sopenharmony_ci	if (eq->this10 == 0)
6638c2ecf20Sopenharmony_ci		return 1;
6648c2ecf20Sopenharmony_ci	*count = eq->this10 * 2;
6658c2ecf20Sopenharmony_ci	vortex_EqHw_GetTenBandLevels(vortex, peaks);
6668c2ecf20Sopenharmony_ci	return 0;
6678c2ecf20Sopenharmony_ci}
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci#if 0
6708c2ecf20Sopenharmony_cistatic auxxEqCoeffSet_t *vortex_Eqlzr_GetActiveCoefSet(vortex_t * vortex)
6718c2ecf20Sopenharmony_ci{
6728c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	return (&(eq->coefset));
6758c2ecf20Sopenharmony_ci}
6768c2ecf20Sopenharmony_ci#endif
6778c2ecf20Sopenharmony_cistatic void vortex_Eqlzr_init(vortex_t * vortex)
6788c2ecf20Sopenharmony_ci{
6798c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
6808c2ecf20Sopenharmony_ci
6818c2ecf20Sopenharmony_ci	/* Object constructor */
6828c2ecf20Sopenharmony_ci	//eq->this04 = 0;
6838c2ecf20Sopenharmony_ci	eq->this08 = 0;		/* Bypass gain with EQ in use. */
6848c2ecf20Sopenharmony_ci	eq->this0a = 0x5999;
6858c2ecf20Sopenharmony_ci	eq->this0c = 0x5999;	/* Bypass gain with EQ disabled. */
6868c2ecf20Sopenharmony_ci	eq->this0e = 0x5999;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	eq->this10 = 0xa;	/* 10 eq frequency bands. */
6898c2ecf20Sopenharmony_ci	eq->this04.this04 = eq->this10;
6908c2ecf20Sopenharmony_ci	eq->this28 = 0x1;	/* if 1 => Allow read access to this130 (gains) */
6918c2ecf20Sopenharmony_ci	eq->this54 = 0x0;	/* if 1 => Dont Allow access to hardware (gains) */
6928c2ecf20Sopenharmony_ci	eq->this58 = 0xffff;
6938c2ecf20Sopenharmony_ci	eq->this5c = 0xffff;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	/* Set gains. */
6968c2ecf20Sopenharmony_ci	memset(eq->this14_array, 0, sizeof(eq->this14_array));
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_ci	/* Actual init. */
6998c2ecf20Sopenharmony_ci	vortex_EqHw_ZeroState(vortex);
7008c2ecf20Sopenharmony_ci	vortex_EqHw_SetSampleRate(vortex, 0x11);
7018c2ecf20Sopenharmony_ci	vortex_Eqlzr_ReadAndSetActiveCoefSet(vortex);
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	vortex_EqHw_Program10Band(vortex, &(eq->coefset));
7048c2ecf20Sopenharmony_ci	vortex_Eqlzr_SetBypass(vortex, eq->this54);
7058c2ecf20Sopenharmony_ci	vortex_Eqlzr_SetA3dBypassGain(vortex, 0, 0);
7068c2ecf20Sopenharmony_ci	vortex_EqHw_Enable(vortex);
7078c2ecf20Sopenharmony_ci}
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_cistatic void vortex_Eqlzr_shutdown(vortex_t * vortex)
7108c2ecf20Sopenharmony_ci{
7118c2ecf20Sopenharmony_ci	vortex_Eqlzr_ShutDownA3d(vortex);
7128c2ecf20Sopenharmony_ci	vortex_EqHw_ProgramPipe(vortex);
7138c2ecf20Sopenharmony_ci	vortex_EqHw_Disable(vortex);
7148c2ecf20Sopenharmony_ci}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci/* ALSA interface */
7178c2ecf20Sopenharmony_ci
7188c2ecf20Sopenharmony_ci/* Control interface */
7198c2ecf20Sopenharmony_ci#define snd_vortex_eqtoggle_info	snd_ctl_boolean_mono_info
7208c2ecf20Sopenharmony_ci
7218c2ecf20Sopenharmony_cistatic int
7228c2ecf20Sopenharmony_cisnd_vortex_eqtoggle_get(struct snd_kcontrol *kcontrol,
7238c2ecf20Sopenharmony_ci			struct snd_ctl_elem_value *ucontrol)
7248c2ecf20Sopenharmony_ci{
7258c2ecf20Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
7268c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
7278c2ecf20Sopenharmony_ci	//int i = kcontrol->private_value;
7288c2ecf20Sopenharmony_ci
7298c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = eq->this54 ? 0 : 1;
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci	return 0;
7328c2ecf20Sopenharmony_ci}
7338c2ecf20Sopenharmony_ci
7348c2ecf20Sopenharmony_cistatic int
7358c2ecf20Sopenharmony_cisnd_vortex_eqtoggle_put(struct snd_kcontrol *kcontrol,
7368c2ecf20Sopenharmony_ci			struct snd_ctl_elem_value *ucontrol)
7378c2ecf20Sopenharmony_ci{
7388c2ecf20Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
7398c2ecf20Sopenharmony_ci	eqlzr_t *eq = &(vortex->eq);
7408c2ecf20Sopenharmony_ci	//int i = kcontrol->private_value;
7418c2ecf20Sopenharmony_ci
7428c2ecf20Sopenharmony_ci	eq->this54 = ucontrol->value.integer.value[0] ? 0 : 1;
7438c2ecf20Sopenharmony_ci	vortex_Eqlzr_SetBypass(vortex, eq->this54);
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	return 1;		/* Allways changes */
7468c2ecf20Sopenharmony_ci}
7478c2ecf20Sopenharmony_ci
7488c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new vortex_eqtoggle_kcontrol = {
7498c2ecf20Sopenharmony_ci	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7508c2ecf20Sopenharmony_ci	.name = "EQ Enable",
7518c2ecf20Sopenharmony_ci	.index = 0,
7528c2ecf20Sopenharmony_ci	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
7538c2ecf20Sopenharmony_ci	.private_value = 0,
7548c2ecf20Sopenharmony_ci	.info = snd_vortex_eqtoggle_info,
7558c2ecf20Sopenharmony_ci	.get = snd_vortex_eqtoggle_get,
7568c2ecf20Sopenharmony_ci	.put = snd_vortex_eqtoggle_put
7578c2ecf20Sopenharmony_ci};
7588c2ecf20Sopenharmony_ci
7598c2ecf20Sopenharmony_cistatic int
7608c2ecf20Sopenharmony_cisnd_vortex_eq_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
7618c2ecf20Sopenharmony_ci{
7628c2ecf20Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
7638c2ecf20Sopenharmony_ci	uinfo->count = 2;
7648c2ecf20Sopenharmony_ci	uinfo->value.integer.min = 0x0000;
7658c2ecf20Sopenharmony_ci	uinfo->value.integer.max = 0x7fff;
7668c2ecf20Sopenharmony_ci	return 0;
7678c2ecf20Sopenharmony_ci}
7688c2ecf20Sopenharmony_ci
7698c2ecf20Sopenharmony_cistatic int
7708c2ecf20Sopenharmony_cisnd_vortex_eq_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7718c2ecf20Sopenharmony_ci{
7728c2ecf20Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
7738c2ecf20Sopenharmony_ci	int i = kcontrol->private_value;
7748c2ecf20Sopenharmony_ci	u16 gainL = 0, gainR = 0;
7758c2ecf20Sopenharmony_ci
7768c2ecf20Sopenharmony_ci	vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
7778c2ecf20Sopenharmony_ci	vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
7788c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[0] = gainL;
7798c2ecf20Sopenharmony_ci	ucontrol->value.integer.value[1] = gainR;
7808c2ecf20Sopenharmony_ci	return 0;
7818c2ecf20Sopenharmony_ci}
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_cistatic int
7848c2ecf20Sopenharmony_cisnd_vortex_eq_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
7858c2ecf20Sopenharmony_ci{
7868c2ecf20Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
7878c2ecf20Sopenharmony_ci	int changed = 0, i = kcontrol->private_value;
7888c2ecf20Sopenharmony_ci	u16 gainL = 0, gainR = 0;
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_ci	vortex_Eqlzr_GetLeftGain(vortex, i, &gainL);
7918c2ecf20Sopenharmony_ci	vortex_Eqlzr_GetRightGain(vortex, i, &gainR);
7928c2ecf20Sopenharmony_ci
7938c2ecf20Sopenharmony_ci	if (gainL != ucontrol->value.integer.value[0]) {
7948c2ecf20Sopenharmony_ci		vortex_Eqlzr_SetLeftGain(vortex, i,
7958c2ecf20Sopenharmony_ci					 ucontrol->value.integer.value[0]);
7968c2ecf20Sopenharmony_ci		changed = 1;
7978c2ecf20Sopenharmony_ci	}
7988c2ecf20Sopenharmony_ci	if (gainR != ucontrol->value.integer.value[1]) {
7998c2ecf20Sopenharmony_ci		vortex_Eqlzr_SetRightGain(vortex, i,
8008c2ecf20Sopenharmony_ci					  ucontrol->value.integer.value[1]);
8018c2ecf20Sopenharmony_ci		changed = 1;
8028c2ecf20Sopenharmony_ci	}
8038c2ecf20Sopenharmony_ci	return changed;
8048c2ecf20Sopenharmony_ci}
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new vortex_eq_kcontrol = {
8078c2ecf20Sopenharmony_ci	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8088c2ecf20Sopenharmony_ci	.name = "                        .",
8098c2ecf20Sopenharmony_ci	.index = 0,
8108c2ecf20Sopenharmony_ci	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
8118c2ecf20Sopenharmony_ci	.private_value = 0,
8128c2ecf20Sopenharmony_ci	.info = snd_vortex_eq_info,
8138c2ecf20Sopenharmony_ci	.get = snd_vortex_eq_get,
8148c2ecf20Sopenharmony_ci	.put = snd_vortex_eq_put
8158c2ecf20Sopenharmony_ci};
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_cistatic int
8188c2ecf20Sopenharmony_cisnd_vortex_peaks_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
8198c2ecf20Sopenharmony_ci{
8208c2ecf20Sopenharmony_ci	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
8218c2ecf20Sopenharmony_ci	uinfo->count = 20;
8228c2ecf20Sopenharmony_ci	uinfo->value.integer.min = 0x0000;
8238c2ecf20Sopenharmony_ci	uinfo->value.integer.max = 0x7fff;
8248c2ecf20Sopenharmony_ci	return 0;
8258c2ecf20Sopenharmony_ci}
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_cistatic int
8288c2ecf20Sopenharmony_cisnd_vortex_peaks_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
8298c2ecf20Sopenharmony_ci{
8308c2ecf20Sopenharmony_ci	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
8318c2ecf20Sopenharmony_ci	int i, count = 0;
8328c2ecf20Sopenharmony_ci	u16 peaks[20];
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci	vortex_Eqlzr_GetAllPeaks(vortex, peaks, &count);
8358c2ecf20Sopenharmony_ci	if (count != 20) {
8368c2ecf20Sopenharmony_ci		dev_err(vortex->card->dev,
8378c2ecf20Sopenharmony_ci			"peak count error 20 != %d\n", count);
8388c2ecf20Sopenharmony_ci		return -1;
8398c2ecf20Sopenharmony_ci	}
8408c2ecf20Sopenharmony_ci	for (i = 0; i < 20; i++)
8418c2ecf20Sopenharmony_ci		ucontrol->value.integer.value[i] = peaks[i];
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	return 0;
8448c2ecf20Sopenharmony_ci}
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new vortex_levels_kcontrol = {
8478c2ecf20Sopenharmony_ci	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8488c2ecf20Sopenharmony_ci	.name = "EQ Peaks",
8498c2ecf20Sopenharmony_ci	.access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
8508c2ecf20Sopenharmony_ci	.info = snd_vortex_peaks_info,
8518c2ecf20Sopenharmony_ci	.get = snd_vortex_peaks_get,
8528c2ecf20Sopenharmony_ci};
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci/* EQ band gain labels. */
8558c2ecf20Sopenharmony_cistatic const char * const EqBandLabels[10] = {
8568c2ecf20Sopenharmony_ci	"EQ0 31Hz\0",
8578c2ecf20Sopenharmony_ci	"EQ1 63Hz\0",
8588c2ecf20Sopenharmony_ci	"EQ2 125Hz\0",
8598c2ecf20Sopenharmony_ci	"EQ3 250Hz\0",
8608c2ecf20Sopenharmony_ci	"EQ4 500Hz\0",
8618c2ecf20Sopenharmony_ci	"EQ5 1KHz\0",
8628c2ecf20Sopenharmony_ci	"EQ6 2KHz\0",
8638c2ecf20Sopenharmony_ci	"EQ7 4KHz\0",
8648c2ecf20Sopenharmony_ci	"EQ8 8KHz\0",
8658c2ecf20Sopenharmony_ci	"EQ9 16KHz\0",
8668c2ecf20Sopenharmony_ci};
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci/* ALSA driver entry points. Init and exit. */
8698c2ecf20Sopenharmony_cistatic int vortex_eq_init(vortex_t *vortex)
8708c2ecf20Sopenharmony_ci{
8718c2ecf20Sopenharmony_ci	struct snd_kcontrol *kcontrol;
8728c2ecf20Sopenharmony_ci	int err, i;
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_ci	vortex_Eqlzr_init(vortex);
8758c2ecf20Sopenharmony_ci
8768c2ecf20Sopenharmony_ci	if ((kcontrol =
8778c2ecf20Sopenharmony_ci	     snd_ctl_new1(&vortex_eqtoggle_kcontrol, vortex)) == NULL)
8788c2ecf20Sopenharmony_ci		return -ENOMEM;
8798c2ecf20Sopenharmony_ci	kcontrol->private_value = 0;
8808c2ecf20Sopenharmony_ci	if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
8818c2ecf20Sopenharmony_ci		return err;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	/* EQ gain controls */
8848c2ecf20Sopenharmony_ci	for (i = 0; i < 10; i++) {
8858c2ecf20Sopenharmony_ci		if ((kcontrol =
8868c2ecf20Sopenharmony_ci		     snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL)
8878c2ecf20Sopenharmony_ci			return -ENOMEM;
8888c2ecf20Sopenharmony_ci		snprintf(kcontrol->id.name, sizeof(kcontrol->id.name),
8898c2ecf20Sopenharmony_ci			"%s Playback Volume", EqBandLabels[i]);
8908c2ecf20Sopenharmony_ci		kcontrol->private_value = i;
8918c2ecf20Sopenharmony_ci		if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
8928c2ecf20Sopenharmony_ci			return err;
8938c2ecf20Sopenharmony_ci		//vortex->eqctrl[i] = kcontrol;
8948c2ecf20Sopenharmony_ci	}
8958c2ecf20Sopenharmony_ci	/* EQ band levels */
8968c2ecf20Sopenharmony_ci	if ((kcontrol = snd_ctl_new1(&vortex_levels_kcontrol, vortex)) == NULL)
8978c2ecf20Sopenharmony_ci		return -ENOMEM;
8988c2ecf20Sopenharmony_ci	if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
8998c2ecf20Sopenharmony_ci		return err;
9008c2ecf20Sopenharmony_ci
9018c2ecf20Sopenharmony_ci	return 0;
9028c2ecf20Sopenharmony_ci}
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_cistatic int vortex_eq_free(vortex_t * vortex)
9058c2ecf20Sopenharmony_ci{
9068c2ecf20Sopenharmony_ci	/*
9078c2ecf20Sopenharmony_ci	   //FIXME: segfault because vortex->eqctrl[i] == 4
9088c2ecf20Sopenharmony_ci	   int i;
9098c2ecf20Sopenharmony_ci	   for (i=0; i<10; i++) {
9108c2ecf20Sopenharmony_ci	   if (vortex->eqctrl[i])
9118c2ecf20Sopenharmony_ci	   snd_ctl_remove(vortex->card, vortex->eqctrl[i]);
9128c2ecf20Sopenharmony_ci	   }
9138c2ecf20Sopenharmony_ci	 */
9148c2ecf20Sopenharmony_ci	vortex_Eqlzr_shutdown(vortex);
9158c2ecf20Sopenharmony_ci	return 0;
9168c2ecf20Sopenharmony_ci}
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci/* End */
919