From b030bf5885dc5e018dd38eacbb294f1321f2b400 Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 1 Oct 2020 14:06:48 -0400 Subject: xduoox3ii/x20: Proper lineout detection and volume mangling. hotplugging hp and lineout works, without blowing out eardrums. Change-Id: I2df5c7a618bb2d1d77d416548d45dff9cfc619db --- apps/playback.c | 4 -- firmware/drivers/audio/xduoolinux_codec.c | 68 +++++++++++++++++++++++----- firmware/export/audiohw.h | 4 -- firmware/export/config/xduoox20.h | 2 +- firmware/export/config/xduoox3.h | 3 -- firmware/export/config/xduoox3ii.h | 2 +- firmware/export/xduoolinux_codec.h | 5 +- firmware/target/hosted/agptek/debug-agptek.c | 7 +++ firmware/target/hosted/alsa-controls.c | 10 ++-- firmware/target/hosted/xduoo/button-xduoo.c | 23 +++------- 10 files changed, 80 insertions(+), 48 deletions(-) diff --git a/apps/playback.c b/apps/playback.c index c7cfef018a..31aed2abe1 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -3851,10 +3851,6 @@ static void audio_change_frequency_callback(unsigned short id, void *data) static bool starting_playback = false; struct mp3entry *id3; -#ifdef AUDIOHW_HAVE_SET_OUTPUT - audiohw_set_output(); -#endif - switch (id) { case PLAYBACK_EVENT_START_PLAYBACK: diff --git a/firmware/drivers/audio/xduoolinux_codec.c b/firmware/drivers/audio/xduoolinux_codec.c index eedde1d667..f8de0bf78d 100644 --- a/firmware/drivers/audio/xduoolinux_codec.c +++ b/firmware/drivers/audio/xduoolinux_codec.c @@ -24,6 +24,7 @@ #include "config.h" #include "audio.h" #include "audiohw.h" +#include "button.h" #include "system.h" #include "kernel.h" #include "panic.h" @@ -32,6 +33,7 @@ #include "pcm-alsa.h" static int fd_hw; +static int inited = 0; static long int vol_l_hw = 255; static long int vol_r_hw = 255; @@ -72,34 +74,45 @@ void audiohw_mute(int mute) } } -void audiohw_set_output(void) -{ +int xduoo_get_outputs(void){ long int ps = 2; // headset int status = 0; + if (!inited) return ps; + const char * const sysfs_lo_switch = "/sys/class/switch/lineout/state"; const char * const sysfs_hs_switch = "/sys/class/switch/headset/state"; #if defined(XDUOO_X20) const char * const sysfs_bal_switch = "/sys/class/switch/balance/state"; #endif - sysfs_get_int(sysfs_lo_switch, &status); - if (status) ps = 1; // lineout - sysfs_get_int(sysfs_hs_switch, &status); if (status) ps = 2; // headset + sysfs_get_int(sysfs_lo_switch, &status); + if (status) ps = 1; // lineout + #if defined(XDUOO_X20) sysfs_get_int(sysfs_bal_switch, &status); if (status) ps = 3; // balance #endif + xduoo_set_output(ps); + + return ps; +} + +void xduoo_set_output(int ps) +{ + if (!inited) return; + if (last_ps != ps) { /* Output port switch */ last_ps = ps; alsa_controls_set_ints("Output Port Switch", 1, &last_ps); + audiohw_set_volume(vol_l_hw, vol_r_hw); } } @@ -107,15 +120,17 @@ void audiohw_preinit(void) { alsa_controls_init(); hw_open(); + inited = 1; } void audiohw_postinit(void) { - audiohw_set_output(); + xduoo_set_output(xduoo_get_outputs()); } void audiohw_close(void) { + inited = 0; hw_close(); alsa_controls_close(); } @@ -127,16 +142,45 @@ void audiohw_set_frequency(int fsel) void audiohw_set_volume(int vol_l, int vol_r) { - vol_l_hw = -vol_l/5; - vol_r_hw = -vol_r/5; - - alsa_controls_set_ints("Left Playback Volume", 1, &vol_l_hw); - alsa_controls_set_ints("Right Playback Volume", 1, &vol_r_hw); + long l,r; + + vol_l_hw = vol_l; + vol_r_hw = vol_r; + + if (lineout_inserted()) { + l = 0; + r = 0; + } else { + l = -vol_l/5; + r = -vol_r/5; + } + + alsa_controls_set_ints("Left Playback Volume", 1, &l); + alsa_controls_set_ints("Right Playback Volume", 1, &r); +} + +void audiohw_set_lineout_volume(int vol_l, int vol_r) +{ + long l,r; + + (void)vol_l; + (void)vol_r; + + if (lineout_inserted()) { + l = 0; + r = 0; + } else { + l = -vol_l_hw/5; + r = -vol_r_hw/5; + } + + alsa_controls_set_ints("Left Playback Volume", 1, &l); + alsa_controls_set_ints("Right Playback Volume", 1, &r); } void audiohw_set_filter_roll_off(int value) { - /* 0 = Sharp; + /* 0 = Sharp; 1 = Slow; 2 = Short Sharp 3 = Short Slow */ diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index 34a253e893..31be0555f8 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -452,10 +452,6 @@ void audiohw_set_volume(int vol_l, int vol_r); void audiohw_set_lineout_volume(int vol_l, int vol_r); #endif -#ifdef AUDIOHW_HAVE_SET_OUTPUT -void audiohw_set_output(void); -#endif - #ifndef AUDIOHW_HAVE_CLIPPING #if defined(AUDIOHW_HAVE_BASS) || defined(AUDIOHW_HAVE_TREBLE) \ || defined(AUDIOHW_HAVE_EQ) diff --git a/firmware/export/config/xduoox20.h b/firmware/export/config/xduoox20.h index 28a19baaae..b90ebceb04 100644 --- a/firmware/export/config/xduoox20.h +++ b/firmware/export/config/xduoox20.h @@ -67,6 +67,7 @@ #define PLUGIN_BUFFER_SIZE 0x100000 #define HAVE_HEADPHONE_DETECTION +#define HAVE_LINEOUT_DETECTION /* KeyPad configuration for plugins */ #define CONFIG_KEYPAD XDUOO_X20_PAD @@ -81,7 +82,6 @@ /* We have usb power and can detect usb but it is handled by Linux */ #define HAVE_USB_POWER -#define AUDIOHW_HAVE_SET_OUTPUT #endif #define CONFIG_BATTERY_MEASURE PERCENTAGE_MEASURE diff --git a/firmware/export/config/xduoox3.h b/firmware/export/config/xduoox3.h index 4c2cc47fc9..484e52d151 100644 --- a/firmware/export/config/xduoox3.h +++ b/firmware/export/config/xduoox3.h @@ -85,9 +85,6 @@ /* Define this if a programmable hotkey is mapped */ #define HAVE_HOTKEY - - - #ifndef BOOTLOADER /* define this if you have a real-time clock */ #define CONFIG_RTC RTC_JZ4760 diff --git a/firmware/export/config/xduoox3ii.h b/firmware/export/config/xduoox3ii.h index 02e8a57909..9ad7b5884b 100644 --- a/firmware/export/config/xduoox3ii.h +++ b/firmware/export/config/xduoox3ii.h @@ -67,6 +67,7 @@ #define PLUGIN_BUFFER_SIZE 0x100000 #define HAVE_HEADPHONE_DETECTION +#define HAVE_LINEOUT_DETECTION /* KeyPad configuration for plugins */ #define CONFIG_KEYPAD XDUOO_X3II_PAD @@ -81,7 +82,6 @@ /* We have usb power and can detect usb but it is handled by Linux */ #define HAVE_USB_POWER -#define AUDIOHW_HAVE_SET_OUTPUT #endif #define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE diff --git a/firmware/export/xduoolinux_codec.h b/firmware/export/xduoolinux_codec.h index ea0b2988f1..a46976d386 100644 --- a/firmware/export/xduoolinux_codec.h +++ b/firmware/export/xduoolinux_codec.h @@ -1,10 +1,11 @@ #ifndef __XDUOOLINUX_CODEC__ #define __XDUOOLINUX_CODEC__ -#define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP) +#define AUDIOHW_CAPS (LINEOUT_CAP | FILTER_ROLL_OFF_CAP) AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -127, 0, -30) AUDIOHW_SETTING(FILTER_ROLL_OFF, "", 0, 1, 0, 4, 0) #endif void audiohw_mute(int mute); -void audiohw_set_output(void); +void xduoo_set_output(int ps); +int xduoo_get_outputs(void); diff --git a/firmware/target/hosted/agptek/debug-agptek.c b/firmware/target/hosted/agptek/debug-agptek.c index b4fcb4246b..7f794a7073 100644 --- a/firmware/target/hosted/agptek/debug-agptek.c +++ b/firmware/target/hosted/agptek/debug-agptek.c @@ -41,6 +41,13 @@ bool dbg_hw_info(void) line = 0; lcd_putsf(0, line++, "pcm srate: %d", pcm_alsa_get_rate()); +#ifdef HAVE_HEADPHONE_DETECTION + lcd_putsf(0, line++, "hp: %d", headphones_inserted()); +#endif +#ifdef HAVE_LINEOUT_DETECTION + lcd_putsf(0, line++, "lo: %d", lineout_inserted()); +#endif + btn = button_read_device(); lcd_update(); diff --git a/firmware/target/hosted/alsa-controls.c b/firmware/target/hosted/alsa-controls.c index 19de7aea44..f4914aa216 100644 --- a/firmware/target/hosted/alsa-controls.c +++ b/firmware/target/hosted/alsa-controls.c @@ -1,10 +1,10 @@ /*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ + * \/ \/ \/ \/ \/ * * Copyright (C) 2016 Amaury Pouly * diff --git a/firmware/target/hosted/xduoo/button-xduoo.c b/firmware/target/hosted/xduoo/button-xduoo.c index 9fd1392b89..03bb7bbfc9 100644 --- a/firmware/target/hosted/xduoo/button-xduoo.c +++ b/firmware/target/hosted/xduoo/button-xduoo.c @@ -166,25 +166,16 @@ int button_read_device(void) bool headphones_inserted(void) { - int status = 0; - const char * const sysfs_lo_switch = "/sys/class/switch/lineout/state"; - const char * const sysfs_hs_switch = "/sys/class/switch/headset/state"; -#ifdef XDUOO_X20 - const char * const sysfs_bal_switch = "/sys/class/switch/balance/state"; -#endif - - sysfs_get_int(sysfs_lo_switch, &status); - if (status) return true; + int ps = xduoo_get_outputs(); - sysfs_get_int(sysfs_hs_switch, &status); - if (status) return true; + return (ps == 2 || ps == 3); +} -#ifdef XDUOO_X20 - sysfs_get_int(sysfs_bal_switch, &status); - if (status) return true; -#endif +bool lineout_inserted(void) +{ + int ps = xduoo_get_outputs(); - return false; + return (ps == 1); } void button_close_device(void) -- cgit v1.2.3