From 51ba8b3eee2ccfede2c766494b38b1b3404b95e4 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 10 Oct 2024 13:25:47 -0400 Subject: erosqhosted: Support HW volume control on rev2+ hardware This also adds hwrev info to the debug output. Change-Id: Ia75218cacb8f756a23a77334ea6ab69ac3b20d10 --- firmware/drivers/audio/erosqlinux_codec.c | 81 +++++++++++++++++++++++++--- firmware/target/hosted/agptek/debug-agptek.c | 6 +++ firmware/target/hosted/aigo/power-erosq.c | 26 ++++----- firmware/target/hosted/alsa-controls.h | 2 + 4 files changed, 95 insertions(+), 20 deletions(-) diff --git a/firmware/drivers/audio/erosqlinux_codec.c b/firmware/drivers/audio/erosqlinux_codec.c index 02c35e3c00..d1b3e884d3 100644 --- a/firmware/drivers/audio/erosqlinux_codec.c +++ b/firmware/drivers/audio/erosqlinux_codec.c @@ -53,11 +53,29 @@ BUFFER_BYTES: [4096 524288] TICK_TIME: ALL - Mixer controls: + Mixer controls (v1): numid=1,iface=MIXER,name='Output Port Switch' ; type=INTEGER,access=rw------,values=1,min=0,max=5,step=0 : values=4 + + Mixer controls (v2+): + + numid=3,iface=MIXER,name='ES9018_K2M Digital Filter' + ; type=INTEGER,access=rw------,values=1,min=0,max=4,step=0 + : values=0 + numid=1,iface=MIXER,name='Left Playback Volume' + ; type=INTEGER,access=rw------,values=1,min=0,max=255,step=0 + : values=0 + numid=4,iface=MIXER,name='Output Port Switch' + ; type=INTEGER,access=rw------,values=1,min=0,max=5,step=0 + : values=0 + numid=2,iface=MIXER,name='Right Playback Volume' + ; type=INTEGER,access=rw------,values=1,min=0,max=255,step=0 + : values=0 + numid=5,iface=MIXER,name='isDSD' + ; type=BOOLEAN,access=rw------,values=1 + : values=off */ static int hw_init = 0; @@ -68,6 +86,8 @@ static long int last_ps = -1; static int muted = -1; +extern int hwver; + void audiohw_mute(int mute) { logf("mute %d", mute); @@ -129,6 +149,13 @@ void audiohw_preinit(void) logf("hw preinit"); alsa_controls_init("default"); hw_init = 1; + + /* See if we have hw2 or later */ + if (alsa_controls_find("Left Playback Volume") == -1) + hwver = 1; + else if (hwver == 1) + hwver = 23; + audiohw_mute(false); /* No need to stay muted */ } @@ -154,10 +181,8 @@ void audiohw_set_frequency(int fsel) const int min_pcm = -740; const int max_pcm = 0; -void audiohw_set_volume(int vol_l, int vol_r) +static void audiohw_set_volume_v1(int vol_l, int vol_r) { - logf("hw vol %d %d", vol_l, vol_r); - long l,r; vol_l_hw = vol_l; @@ -180,6 +205,39 @@ void audiohw_set_volume(int vol_l, int vol_r) pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20); } +static void audiohw_set_volume_v2(int vol_l, int vol_r) +{ + long l,r; + + if (lineout_inserted()) { + vol_l_hw = vol_r_hw = global_settings.volume_limit * 10; + } else { + vol_l_hw = -vol_l; + vol_r_hw = -vol_r; + } + + if (!hw_init) + return; + + l = vol_l_hw / 5; + r = vol_l_hw / 5; + + alsa_controls_set_ints("Left Playback Volume", 1, &l); + alsa_controls_set_ints("Right Playback Volume", 1, &r); + + /* Dial back PCM mixer to avoid compression */ + pcm_set_mixer_volume(global_settings.volume_limit / 2, global_settings.volume_limit / 2); +} + +void audiohw_set_volume(int vol_l, int vol_r) +{ + if (hwver >= 2) { + audiohw_set_volume_v2(vol_l, vol_r); + } else { + audiohw_set_volume_v1(vol_l, vol_r); + } +} + void audiohw_set_lineout_volume(int vol_l, int vol_r) { long l,r; @@ -196,7 +254,16 @@ void audiohw_set_lineout_volume(int vol_l, int vol_r) r = vol_r_hw; } - int sw_volume_l = l <= min_pcm ? min_pcm : MIN(l, max_pcm); - int sw_volume_r = r <= min_pcm ? min_pcm : MIN(r, max_pcm); - pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20); + if (hwver >= 2) { + if (hw_init) { + l /= 5; + r /= 5; + alsa_controls_set_ints("Left Playback Volume", 1, &l); + alsa_controls_set_ints("Right Playback Volume", 1, &r); + } + } else { + int sw_volume_l = l <= min_pcm ? min_pcm : MIN(l, max_pcm); + int sw_volume_r = r <= min_pcm ? min_pcm : MIN(r, max_pcm); + pcm_set_mixer_volume(sw_volume_l / 20, sw_volume_r / 20); + } } diff --git a/firmware/target/hosted/agptek/debug-agptek.c b/firmware/target/hosted/agptek/debug-agptek.c index a9b829f7ec..de4bc946bc 100644 --- a/firmware/target/hosted/agptek/debug-agptek.c +++ b/firmware/target/hosted/agptek/debug-agptek.c @@ -37,6 +37,8 @@ static int line = 0; +extern int hwver; + bool dbg_hw_info(void) { int btn = 0; @@ -61,6 +63,10 @@ bool dbg_hw_info(void) lcd_putsf(0, line++, "Boot ver: %s", verstr); } +#ifdef EROS_Q + lcd_putsf(0, line++, "hwver: %d", hwver); +#endif + lcd_putsf(0, line++, "pcm srate: %d", pcm_alsa_get_rate()); lcd_putsf(0, line++, "pcm xruns: %d", pcm_alsa_get_xruns()); #ifdef HAVE_HEADPHONE_DETECTION diff --git a/firmware/target/hosted/aigo/power-erosq.c b/firmware/target/hosted/aigo/power-erosq.c index 664ee144af..7c4515f616 100644 --- a/firmware/target/hosted/aigo/power-erosq.c +++ b/firmware/target/hosted/aigo/power-erosq.c @@ -45,16 +45,16 @@ const char * const sysfs_bat_status[2] = { "/sys/class/power_supply/axp_battery/status", }; -static int hwver = 0; +int hwver = 1; /* Exported */ unsigned int erosq_power_get_battery_voltage(void) { int battery_voltage; - int x = sysfs_get_int(sysfs_bat_voltage[hwver], &battery_voltage); + int x = sysfs_get_int(sysfs_bat_voltage[hwver == 4], &battery_voltage); - if (!x) { - hwver ^= 1; - sysfs_get_int(sysfs_bat_voltage[hwver], &battery_voltage); + if (!x && hwver != 4) { + hwver = 4; + sysfs_get_int(sysfs_bat_voltage[hwver == 4], &battery_voltage); } return battery_voltage/1000; @@ -63,11 +63,11 @@ unsigned int erosq_power_get_battery_voltage(void) unsigned int erosq_power_get_battery_capacity(void) { int battery_capacity; - int x = sysfs_get_int(sysfs_bat_capacity[hwver], &battery_capacity); + int x = sysfs_get_int(sysfs_bat_capacity[hwver == 4], &battery_capacity); - if (!x) { - hwver ^= 1; - sysfs_get_int(sysfs_bat_capacity[hwver], &battery_capacity); + if (!x && hwver != 4) { + hwver = 4; + sysfs_get_int(sysfs_bat_capacity[hwver == 4], &battery_capacity); } return battery_capacity; @@ -81,11 +81,11 @@ bool charging_state(void) { if ((current_tick - last_tick) > HZ/2 ) { char buf[12] = {0}; - int x = sysfs_get_string(sysfs_bat_status[hwver], buf, sizeof(buf)); + int x = sysfs_get_string(sysfs_bat_status[hwver == 4], buf, sizeof(buf)); - if (!x) { - hwver ^= 1; - sysfs_get_string(sysfs_bat_status[hwver], buf, sizeof(buf)); + if (!x && hwver != 4) { + hwver = 4; + sysfs_get_string(sysfs_bat_status[hwver == 4], buf, sizeof(buf)); } last_tick = current_tick; diff --git a/firmware/target/hosted/alsa-controls.h b/firmware/target/hosted/alsa-controls.h index af3e584cd9..b868ef52fb 100644 --- a/firmware/target/hosted/alsa-controls.h +++ b/firmware/target/hosted/alsa-controls.h @@ -36,6 +36,8 @@ void alsa_controls_close(void); /* check wether a control exists */ bool alsa_has_control(const char *name); +/* find a control element ID by name, return -1 of not found or index into array */ +int alsa_controls_find(const char *name); /* find a control element enum index by name, return -1 if not found */ int alsa_controls_find_enum(const char *name, const char *enum_name); /* set a control, potentially supports several values */ -- cgit v1.2.3