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