summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2019-01-03 20:46:54 -0500
committerSolomon Peachy <pizza@shaftnet.org>2019-01-04 23:52:42 +0100
commitd24edc605b9b52d3610efbb9cf691c437ea00746 (patch)
treebd8e6119e4611c6ff83bd316816e0b9534d84deb
parent100f4338deea5239423a0b8974784939d520385c (diff)
downloadrockbox-d24edc605b9b52d3610efbb9cf691c437ea00746.tar.gz
rockbox-d24edc605b9b52d3610efbb9cf691c437ea00746.tar.bz2
rockbox-d24edc605b9b52d3610efbb9cf691c437ea00746.zip
Add HAVE_LINEOUT_DETECTION and associated logic
This allows targets to automatically switch audio settings when the line out is plugged/unplugged. Only hooked up on the xDuoo X3, but there are other potential users. Change-Id: Ic46a329bc955cca2e2ad0335ca16295eab24ad59
-rw-r--r--apps/misc.c31
-rw-r--r--firmware/drivers/button.c52
-rw-r--r--firmware/export/button.h5
-rw-r--r--firmware/export/config/xduoox3.h3
-rw-r--r--firmware/kernel/include/queue.h2
-rw-r--r--firmware/target/mips/ingenic_jz47xx/codec-jz4760.c32
-rw-r--r--firmware/target/mips/ingenic_jz47xx/xduoo_x3/sadc-xduoo_x3.c11
7 files changed, 109 insertions, 27 deletions
diff --git a/apps/misc.c b/apps/misc.c
index 90865859cf..2106d11164 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -157,11 +157,11 @@ char *output_dyn_value(char *buf,
value_abs /= scale;
unit_no++;
}
-
+
value = (value < 0) ? -value_abs : value_abs; /* preserve sign */
fraction = (fraction * 1000 / scale) / 10;
- if (value_abs >= 100 || fraction >= 100 || !unit_no)
+ if (value_abs >= 100 || fraction >= 100 || !unit_no)
tbuf[0] = '\0';
else if (value_abs >= 10)
snprintf(tbuf, sizeof(tbuf), "%01u", fraction / 10);
@@ -521,7 +521,7 @@ void car_adapter_mode_init(void)
#endif
#ifdef HAVE_HEADPHONE_DETECTION
-static void unplug_change(bool inserted)
+static void hp_unplug_change(bool inserted)
{
static bool headphone_caused_pause = false;
@@ -553,6 +553,18 @@ static void unplug_change(bool inserted)
}
#endif
+#ifdef HAVE_LINEOUT_DETECTION
+static void lo_unplug_change(bool inserted)
+{
+#ifdef HAVE_LINEOUT_POWEROFF
+ lineout_set(inserted);
+#else
+ (void)inserted;
+ audiohw_set_lineout_volume(0,0);
+#endif
+}
+#endif
+
long default_event_handler_ex(long event, void (*callback)(void *), void *parameter)
{
#if CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO)
@@ -632,13 +644,22 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
#endif
#ifdef HAVE_HEADPHONE_DETECTION
case SYS_PHONE_PLUGGED:
- unplug_change(true);
+ hp_unplug_change(true);
return SYS_PHONE_PLUGGED;
case SYS_PHONE_UNPLUGGED:
- unplug_change(false);
+ hp_unplug_change(false);
return SYS_PHONE_UNPLUGGED;
#endif
+#ifdef HAVE_LINEOUT_DETECTION
+ case SYS_LINEOUT_PLUGGED:
+ lo_unplug_change(true);
+ return SYS_LINEOUT_PLUGGED;
+
+ case SYS_LINEOUT_UNPLUGGED:
+ lo_unplug_change(false);
+ return SYS_LINEOUT_UNPLUGGED;
+#endif
#if CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO)
/* stop playback if we receive a call */
case SYS_CALL_INCOMING:
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c
index 64668b4ebf..608fe7e33a 100644
--- a/firmware/drivers/button.c
+++ b/firmware/drivers/button.c
@@ -59,6 +59,9 @@ static bool remote_filter_first_keypress;
#ifdef HAVE_HEADPHONE_DETECTION
static bool phones_present = false;
#endif
+#ifdef HAVE_LINEOUT_DETECTION
+static bool lineout_present = false;
+#endif
/* how long until repeat kicks in, in centiseconds */
#define REPEAT_START (30*HZ/100)
@@ -94,12 +97,11 @@ static int button_read(void);
#ifdef HAVE_TOUCHSCREEN
static int last_touchscreen_touch;
-#endif
+#endif
#if defined(HAVE_HEADPHONE_DETECTION)
static struct timeout hp_detect_timeout; /* Debouncer for headphone plug/unplug */
-/* This callback can be used for many different functions if needed -
- just check to which object tmo points */
-static int btn_detect_callback(struct timeout *tmo)
+
+static int hp_detect_callback(struct timeout *tmo)
{
/* Try to post only transistions */
const long id = tmo->data ? SYS_PHONE_PLUGGED : SYS_PHONE_UNPLUGGED;
@@ -109,6 +111,19 @@ static int btn_detect_callback(struct timeout *tmo)
}
#endif
+#if defined(HAVE_LINEOUT_DETECTION)
+static struct timeout lo_detect_timeout; /* Debouncer for lineout plug/unplug */
+
+static int lo_detect_callback(struct timeout *tmo)
+{
+ /* Try to post only transistions */
+ const long id = tmo->data ? SYS_LINEOUT_PLUGGED : SYS_LINEOUT_UNPLUGGED;
+ queue_remove_from_head(&button_queue, id);
+ queue_post(&button_queue, id, 0);
+ return 0;
+}
+#endif
+
static bool button_try_post(int button, int data)
{
#ifdef HAVE_TOUCHSCREEN
@@ -176,10 +191,19 @@ static void button_tick(void)
{
/* Use the autoresetting oneshot to debounce the detection signal */
phones_present = !phones_present;
- timeout_register(&hp_detect_timeout, btn_detect_callback,
+ timeout_register(&hp_detect_timeout, hp_detect_callback,
HZ/2, phones_present);
}
#endif
+#if defined(HAVE_LINEOUT_DETECTION)
+ if (lineout_inserted() != lineout_present)
+ {
+ /* Use the autoresetting oneshot to debounce the detection signal */
+ lineout_present = !lineout_present;
+ timeout_register(&lo_detect_timeout, lo_detect_callback,
+ HZ/2, lineout_present);
+ }
+#endif
/* Find out if a key has been released */
diff = btn ^ lastbtn;
@@ -318,7 +342,7 @@ static void button_tick(void)
#ifdef HAVE_BACKLIGHT
#ifdef HAVE_REMOTE_LCD
if (btn & BUTTON_REMOTE) {
- if (!remote_filter_first_keypress
+ if (!remote_filter_first_keypress
|| is_remote_backlight_on(false)
#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
|| (remote_type()==REMOTETYPE_H300_NONLCD)
@@ -427,7 +451,7 @@ static void button_queue_wait(struct queue_event *evp, int timeout)
#endif
button_boost(true);
- break;
+ break;
}
if (button_boosted && TIME_AFTER(current_tick, button_unboost_tick))
@@ -462,7 +486,7 @@ long button_get(bool block)
long button_get_w_tmo(int ticks)
{
- struct queue_event ev;
+ struct queue_event ev;
button_queue_wait(&ev, ticks);
if (ev.id == SYS_TIMEOUT)
@@ -496,7 +520,7 @@ void button_init(void)
button_read();
lastbtn = button_read();
#endif
-
+
reset_poweroff_timer();
#ifdef HAVE_LCD_BITMAP
@@ -506,11 +530,11 @@ void button_init(void)
filter_first_keypress = false;
#ifdef HAVE_REMOTE_LCD
remote_filter_first_keypress = false;
-#endif
+#endif
#endif
#ifdef HAVE_TOUCHSCREEN
last_touchscreen_touch = 0xffff;
-#endif
+#endif
/* Start polling last */
tick_add_task(button_tick);
}
@@ -647,7 +671,7 @@ static int button_read(void)
#ifdef HAVE_TOUCHSCREEN
if (btn & BUTTON_TOUCHSCREEN)
last_touchscreen_touch = current_tick;
-#endif
+#endif
/* Filter the button status. It is only accepted if we get the same
status twice in a row. */
#ifndef HAVE_TOUCHSCREEN
@@ -696,8 +720,8 @@ int touchscreen_last_touch(void)
* [23:0] Velocity - degree/sec
*
* WHEEL_ACCEL_FACTOR:
- * Value in degree/sec -- configurable via settings -- above which
- * the accelerated scrolling starts. Factor is internally scaled by
+ * Value in degree/sec -- configurable via settings -- above which
+ * the accelerated scrolling starts. Factor is internally scaled by
* 1<<16 in respect to the following 32bit integer operations.
*/
int button_apply_acceleration(const unsigned int data)
diff --git a/firmware/export/button.h b/firmware/export/button.h
index 7109c00f97..d9732ebe8b 100644
--- a/firmware/export/button.h
+++ b/firmware/export/button.h
@@ -44,7 +44,7 @@ int button_read_device(void);
#ifdef HAS_BUTTON_HOLD
bool button_hold(void);
#endif
-#ifdef HAS_REMOTE_BUTTON_HOLD
+#ifdef HAS_REMOTE_BUTTON_HOLD
bool remote_button_hold(void);
#endif
@@ -72,6 +72,9 @@ void set_remote_backlight_filter_keypress(bool value);
#ifdef HAVE_HEADPHONE_DETECTION
bool headphones_inserted(void);
#endif
+#ifdef HAVE_LINEOUT_DETECTION
+bool lineout_inserted(void);
+#endif
#ifdef HAVE_WHEEL_POSITION
int wheel_status(void);
void wheel_send_events(bool send);
diff --git a/firmware/export/config/xduoox3.h b/firmware/export/config/xduoox3.h
index d4d6f2ee2f..b2c8930531 100644
--- a/firmware/export/config/xduoox3.h
+++ b/firmware/export/config/xduoox3.h
@@ -73,6 +73,9 @@
/* Define this if you can detect headphones */
#define HAVE_HEADPHONE_DETECTION
+/* Define this if you can detect lineout */
+#define HAVE_LINEOUT_DETECTION
+
#define CONFIG_KEYPAD XDUOO_X3_PAD
/* Define this if a programmable hotkey is mapped */
diff --git a/firmware/kernel/include/queue.h b/firmware/kernel/include/queue.h
index afee4c90ff..515a7e43a8 100644
--- a/firmware/kernel/include/queue.h
+++ b/firmware/kernel/include/queue.h
@@ -65,6 +65,8 @@
#define SYS_PHONE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 3)
#define SYS_REMOTE_PLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 4)
#define SYS_REMOTE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 5)
+#define SYS_LINEOUT_PLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 6)
+#define SYS_LINEOUT_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 7)
#define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0)
#define SYS_CALL_INCOMING MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 3)
#define SYS_CALL_HUNG_UP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 4)
diff --git a/firmware/target/mips/ingenic_jz47xx/codec-jz4760.c b/firmware/target/mips/ingenic_jz47xx/codec-jz4760.c
index 09d4858b34..a2de80a914 100644
--- a/firmware/target/mips/ingenic_jz47xx/codec-jz4760.c
+++ b/firmware/target/mips/ingenic_jz47xx/codec-jz4760.c
@@ -26,6 +26,7 @@
#include "pcm_sw_volume.h"
#include "cs4398.h"
#include "kernel.h"
+#include "button.h"
#define PIN_CS_RST (32*1+10)
#define PIN_CODEC_PWRON (32*1+13)
@@ -140,7 +141,11 @@ static int vol_tenthdb2hw(const int tdb)
}
}
-void audiohw_set_volume(int vol_l, int vol_r)
+#ifdef HAVE_LINEOUT_DETECTION
+static int real_vol_l, real_vol_r;
+#endif
+
+static void jz4760_set_vol(int vol_l, int vol_r)
{
uint8_t val = cs4398_read_reg(CS4398_REG_MISC) &~ CS4398_FREEZE;
cs4398_write_reg(CS4398_REG_MISC, val | CS4398_FREEZE);
@@ -149,14 +154,31 @@ void audiohw_set_volume(int vol_l, int vol_r)
cs4398_write_reg(CS4398_REG_MISC, val);
}
+void audiohw_set_volume(int vol_l, int vol_r)
+{
+#ifdef HAVE_LINEOUT_DETECTION
+ real_vol_l = vol_l;
+ real_vol_r = vol_r;
+
+ if (lineout_inserted()) {
+ vol_l = 0;
+ vol_r = 0;
+ }
+#endif
+ jz4760_set_vol(vol_l, vol_r);
+}
+
void audiohw_set_lineout_volume(int vol_l, int vol_r)
{
-#if 0 /* unused */
- cs4398_write_reg(CS4398_REG_VOL_A, vol_tenthdb2hw(vol_l));
- cs4398_write_reg(CS4398_REG_VOL_B, vol_tenthdb2hw(vol_r));
-#else
(void)vol_l;
(void)vol_r;
+
+#ifdef HAVE_LINEOUT_DETECTION
+ if (lineout_inserted()) {
+ jz4760_set_vol(0, 0);
+ } else {
+ jz4760_set_vol(real_vol_l, real_vol_r);
+ }
#endif
}
diff --git a/firmware/target/mips/ingenic_jz47xx/xduoo_x3/sadc-xduoo_x3.c b/firmware/target/mips/ingenic_jz47xx/xduoo_x3/sadc-xduoo_x3.c
index be02167a5d..d227255b8a 100644
--- a/firmware/target/mips/ingenic_jz47xx/xduoo_x3/sadc-xduoo_x3.c
+++ b/firmware/target/mips/ingenic_jz47xx/xduoo_x3/sadc-xduoo_x3.c
@@ -53,6 +53,13 @@ bool headphones_inserted(void)
return (__gpio_get_pin(PIN_PH_DECT) != 0);
}
+bool lineout_inserted(void)
+{
+ /* We want to prevent LO being "enabled" if HP is attached
+ to avoid potential eardrum damage */
+ return (__gpio_get_pin(PIN_LO_DECT) == 0) && !headphones_inserted();
+}
+
void button_init_device(void)
{
key_val = 0xfff;
@@ -72,11 +79,11 @@ void button_init_device(void)
__gpio_set_pin(PIN_CHARGE_CON); /* 0.7 A */
__gpio_as_output(PIN_CHARGE_CON);
- __gpio_as_input(PIN_LO_DECT);
__gpio_as_input(PIN_PH_DECT);
+ __gpio_disable_pull(PIN_PH_DECT);
+ __gpio_as_input(PIN_LO_DECT);
__gpio_disable_pull(PIN_LO_DECT);
- __gpio_disable_pull(PIN_PH_DECT);
}
bool button_hold(void)