From 1e2a9a651c26b7526530428b248132e02624bb84 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 8 Apr 2021 23:58:49 -0400 Subject: [PATCH] erosq: Switch to 32-bit PCM output, and do volume scaling in driver Should improve audio output quality, especially at lower volumes. Change-Id: I31c38f05fe4b554b092511f0fe7aaad9f346f6c5 --- firmware/drivers/audio/erosqlinux_codec.c | 19 +++++++++++-------- firmware/export/config/aigoerosq.h | 3 +-- firmware/export/erosqlinux_codec.h | 2 +- firmware/target/hosted/pcm-alsa.c | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/firmware/drivers/audio/erosqlinux_codec.c b/firmware/drivers/audio/erosqlinux_codec.c index b1c5aa0c4f..58104a61e6 100644 --- a/firmware/drivers/audio/erosqlinux_codec.c +++ b/firmware/drivers/audio/erosqlinux_codec.c @@ -169,6 +169,10 @@ void audiohw_set_frequency(int fsel) (void)fsel; } +/* min/max for pcm volume */ +const int min_pcm = -430; +const int max_pcm = 0; + void audiohw_set_volume(int vol_l, int vol_r) { logf("hw vol %d %d", vol_l, vol_r); @@ -179,7 +183,7 @@ void audiohw_set_volume(int vol_l, int vol_r) vol_r_hw = vol_r; if (lineout_inserted()) { - /* On the EROS Q/K hardware, line out is _very_ hot + /* On the EROS Q/K hardware, full scale line out is _very_ hot at ~5.8Vpp. As the hardware provides no way to reduce output gain, we have to back off on the PCM signal to avoid blowing out the signal. @@ -190,10 +194,9 @@ void audiohw_set_volume(int vol_l, int vol_r) r = vol_r_hw; } - /* SW volume for <= 1.0 gain, HW at unity, < -740 == MUTE */ - int sw_volume_l = l <= -740 ? PCM_MUTE_LEVEL : MIN(l, 0); - int sw_volume_r = r <= -740 ? PCM_MUTE_LEVEL : MIN(r, 0); - pcm_set_master_volume(sw_volume_l, sw_volume_r); + 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 / 10, sw_volume_r / 10); } void audiohw_set_lineout_volume(int vol_l, int vol_r) @@ -212,7 +215,7 @@ void audiohw_set_lineout_volume(int vol_l, int vol_r) r = vol_r_hw; } - int sw_volume_l = l <= -740 ? PCM_MUTE_LEVEL : MIN(l, 0); - int sw_volume_r = r <= -740 ? PCM_MUTE_LEVEL : MIN(r, 0); - pcm_set_master_volume(sw_volume_l, sw_volume_r); + 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 / 10, sw_volume_r / 10); } diff --git a/firmware/export/config/aigoerosq.h b/firmware/export/config/aigoerosq.h index 6ae8ad049f..2d0f7a0cdf 100644 --- a/firmware/export/config/aigoerosq.h +++ b/firmware/export/config/aigoerosq.h @@ -36,8 +36,7 @@ /* Audio codec */ #define HAVE_EROSQ_LINUX_CODEC -/* Rockbox has to handle the volume level */ -#define HAVE_SW_VOLUME_CONTROL +#define HAVE_ALSA_32BIT /* We don't have hardware controls */ #define HAVE_SW_TONE_CONTROLS diff --git a/firmware/export/erosqlinux_codec.h b/firmware/export/erosqlinux_codec.h index 1dd9b7e6c6..c337bb78c7 100644 --- a/firmware/export/erosqlinux_codec.h +++ b/firmware/export/erosqlinux_codec.h @@ -3,7 +3,7 @@ #define AUDIOHW_CAPS (LINEOUT_CAP) -AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -74, 6, -25) +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -43, 0, -20) //#define AUDIOHW_NEEDS_INITIAL_UNMUTE diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c index 16f82bad5c..81c0a19a45 100644 --- a/firmware/target/hosted/pcm-alsa.c +++ b/firmware/target/hosted/pcm-alsa.c @@ -277,7 +277,7 @@ static int dig_vol_mult_r = 2 << 16; /* multiplicative factor to apply to each s void pcm_set_mixer_volume(int vol_db_l, int vol_db_r) { if(vol_db_l > 0 || vol_db_r > 0 || vol_db_l < -43 || vol_db_r < -43) - panicf("invalid pcm alsa volume"); + panicf("invalid pcm alsa volume %d %d", vol_db_l, vol_db_r); if(format != SND_PCM_FORMAT_S32_LE) panicf("this function assumes 32-bit sample size"); vol_db_l += 48; /* -42dB .. 0dB => 5dB .. 48dB */