summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDana Conrad <dconrad@fastmail.com>2021-07-31 10:15:12 -0500
committerAidan MacDonald <amachronic@protonmail.com>2021-08-07 14:21:47 +0000
commit16b009825608164b17dabd877c78123a667b4981 (patch)
treee7c88e07ddadff4b62802f561e8c9a83c90ae925
parent57293f1fd9d091145059293d88bb15c8749bb596 (diff)
downloadrockbox-16b009825608164b17dabd877c78123a667b4981.tar.gz
rockbox-16b009825608164b17dabd877c78123a667b4981.zip
ErosQ Native: Add DC Offset to PCM data
A small negative offset seems to silence all play/pause clicking on the PCM5102A. Also adding PCM soft muting, and muting the headphone amp when the headphones are detected as removed. This has been tested to not cause any unintended side effects on the line out. Also confirmed the numerical dB values are (approx.) correct. Change-Id: I689d68887c86add9cc5e0ccb0c7de01aaa69b4d9
-rw-r--r--firmware/drivers/audio/eros_qn_codec.c24
-rw-r--r--firmware/export/eros_qn_codec.h3
-rw-r--r--firmware/pcm_sw_volume.c4
3 files changed, 31 insertions, 0 deletions
diff --git a/firmware/drivers/audio/eros_qn_codec.c b/firmware/drivers/audio/eros_qn_codec.c
index 21347f5fca..fdf21d2f9d 100644
--- a/firmware/drivers/audio/eros_qn_codec.c
+++ b/firmware/drivers/audio/eros_qn_codec.c
@@ -26,10 +26,14 @@
#include "audiohw.h"
#include "settings.h"
#include "pcm_sw_volume.h"
+#include "gpio-x1000.h"
static long int vol_l_hw = 0;
static long int vol_r_hw = 0;
+/* internal: mute the headphone amp. 0 - unmuted, 1 - muted */
+void audiohw_mute_hp(int mute);
+
void pcm5102_set_outputs(void)
{
audiohw_set_volume(vol_l_hw, vol_r_hw);
@@ -53,13 +57,33 @@ void audiohw_set_volume(int vol_l, int vol_r)
if (lineout_inserted() && !headphones_inserted())
{
l = r = global_settings.volume_limit * 10;
+
+ /* mute the headphone amp if not plugged in */
+ audiohw_mute_hp(1);
}
else
{
+ /* unmute the headphone amp when plugged in */
+ audiohw_mute_hp(0);
l = vol_l;
r = vol_r;
}
#endif
+ l = l <= PCM5102A_VOLUME_MIN ? PCM_MUTE_LEVEL : l;
+ r = r <= PCM5102A_VOLUME_MIN ? PCM_MUTE_LEVEL : r;
+
pcm_set_master_volume(l, r);
}
+
+void audiohw_mute_hp(int mute)
+{
+ if (mute == 0)
+ {
+ gpio_set_level(GPIO_MAX97220_SHDN, 1);
+ }
+ else
+ {
+ gpio_set_level(GPIO_MAX97220_SHDN, 0);
+ }
+}
diff --git a/firmware/export/eros_qn_codec.h b/firmware/export/eros_qn_codec.h
index 15c745c04b..9c900186a8 100644
--- a/firmware/export/eros_qn_codec.h
+++ b/firmware/export/eros_qn_codec.h
@@ -26,6 +26,9 @@
#define PCM5102A_VOLUME_MIN -740
#define PCM5102A_VOLUME_MAX 0
+/* a small DC offset appears to prevent play/pause clicking */
+#define PCM_DC_OFFSET_VALUE -1
+
AUDIOHW_SETTING(VOLUME, "dB", 0, 1, PCM5102A_VOLUME_MIN/10, PCM5102A_VOLUME_MAX/10, 0)
/* this just calls audiohw_set_volume() with the last (locally) known volume,
diff --git a/firmware/pcm_sw_volume.c b/firmware/pcm_sw_volume.c
index 7322269f44..3593c684af 100644
--- a/firmware/pcm_sw_volume.c
+++ b/firmware/pcm_sw_volume.c
@@ -54,7 +54,11 @@ static typeof (memcpy) *pcm_scaling_fn = NULL;
/* Scale sample by PCM factor */
static inline int32_t pcm_scale_sample(PCM_F_T f, int32_t s)
{
+#if defined(PCM_DC_OFFSET_VALUE)
+ return (f * s + PCM_DC_OFFSET_VALUE) >> PCM_SW_VOLUME_FRACBITS;
+#else
return (f * s) >> PCM_SW_VOLUME_FRACBITS;
+#endif
}
/* Both UNITY, use direct copy */