summaryrefslogtreecommitdiff
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.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,
157 value_abs /= scale; 157 value_abs /= scale;
158 unit_no++; 158 unit_no++;
159 } 159 }
160 160
161 value = (value < 0) ? -value_abs : value_abs; /* preserve sign */ 161 value = (value < 0) ? -value_abs : value_abs; /* preserve sign */
162 fraction = (fraction * 1000 / scale) / 10; 162 fraction = (fraction * 1000 / scale) / 10;
163 163
164 if (value_abs >= 100 || fraction >= 100 || !unit_no) 164 if (value_abs >= 100 || fraction >= 100 || !unit_no)
165 tbuf[0] = '\0'; 165 tbuf[0] = '\0';
166 else if (value_abs >= 10) 166 else if (value_abs >= 10)
167 snprintf(tbuf, sizeof(tbuf), "%01u", fraction / 10); 167 snprintf(tbuf, sizeof(tbuf), "%01u", fraction / 10);
@@ -521,7 +521,7 @@ void car_adapter_mode_init(void)
521#endif 521#endif
522 522
523#ifdef HAVE_HEADPHONE_DETECTION 523#ifdef HAVE_HEADPHONE_DETECTION
524static void unplug_change(bool inserted) 524static void hp_unplug_change(bool inserted)
525{ 525{
526 static bool headphone_caused_pause = false; 526 static bool headphone_caused_pause = false;
527 527
@@ -553,6 +553,18 @@ static void unplug_change(bool inserted)
553} 553}
554#endif 554#endif
555 555
556#ifdef HAVE_LINEOUT_DETECTION
557static void lo_unplug_change(bool inserted)
558{
559#ifdef HAVE_LINEOUT_POWEROFF
560 lineout_set(inserted);
561#else
562 (void)inserted;
563 audiohw_set_lineout_volume(0,0);
564#endif
565}
566#endif
567
556long default_event_handler_ex(long event, void (*callback)(void *), void *parameter) 568long default_event_handler_ex(long event, void (*callback)(void *), void *parameter)
557{ 569{
558#if CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO) 570#if CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO)
@@ -632,13 +644,22 @@ long default_event_handler_ex(long event, void (*callback)(void *), void *parame
632#endif 644#endif
633#ifdef HAVE_HEADPHONE_DETECTION 645#ifdef HAVE_HEADPHONE_DETECTION
634 case SYS_PHONE_PLUGGED: 646 case SYS_PHONE_PLUGGED:
635 unplug_change(true); 647 hp_unplug_change(true);
636 return SYS_PHONE_PLUGGED; 648 return SYS_PHONE_PLUGGED;
637 649
638 case SYS_PHONE_UNPLUGGED: 650 case SYS_PHONE_UNPLUGGED:
639 unplug_change(false); 651 hp_unplug_change(false);
640 return SYS_PHONE_UNPLUGGED; 652 return SYS_PHONE_UNPLUGGED;
641#endif 653#endif
654#ifdef HAVE_LINEOUT_DETECTION
655 case SYS_LINEOUT_PLUGGED:
656 lo_unplug_change(true);
657 return SYS_LINEOUT_PLUGGED;
658
659 case SYS_LINEOUT_UNPLUGGED:
660 lo_unplug_change(false);
661 return SYS_LINEOUT_UNPLUGGED;
662#endif
642#if CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO) 663#if CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO)
643 /* stop playback if we receive a call */ 664 /* stop playback if we receive a call */
644 case SYS_CALL_INCOMING: 665 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;
59#ifdef HAVE_HEADPHONE_DETECTION 59#ifdef HAVE_HEADPHONE_DETECTION
60static bool phones_present = false; 60static bool phones_present = false;
61#endif 61#endif
62#ifdef HAVE_LINEOUT_DETECTION
63static bool lineout_present = false;
64#endif
62 65
63/* how long until repeat kicks in, in centiseconds */ 66/* how long until repeat kicks in, in centiseconds */
64#define REPEAT_START (30*HZ/100) 67#define REPEAT_START (30*HZ/100)
@@ -94,12 +97,11 @@ static int button_read(void);
94 97
95#ifdef HAVE_TOUCHSCREEN 98#ifdef HAVE_TOUCHSCREEN
96static int last_touchscreen_touch; 99static int last_touchscreen_touch;
97#endif 100#endif
98#if defined(HAVE_HEADPHONE_DETECTION) 101#if defined(HAVE_HEADPHONE_DETECTION)
99static struct timeout hp_detect_timeout; /* Debouncer for headphone plug/unplug */ 102static struct timeout hp_detect_timeout; /* Debouncer for headphone plug/unplug */
100/* This callback can be used for many different functions if needed - 103
101 just check to which object tmo points */ 104static int hp_detect_callback(struct timeout *tmo)
102static int btn_detect_callback(struct timeout *tmo)
103{ 105{
104 /* Try to post only transistions */ 106 /* Try to post only transistions */
105 const long id = tmo->data ? SYS_PHONE_PLUGGED : SYS_PHONE_UNPLUGGED; 107 const long id = tmo->data ? SYS_PHONE_PLUGGED : SYS_PHONE_UNPLUGGED;
@@ -109,6 +111,19 @@ static int btn_detect_callback(struct timeout *tmo)
109} 111}
110#endif 112#endif
111 113
114#if defined(HAVE_LINEOUT_DETECTION)
115static struct timeout lo_detect_timeout; /* Debouncer for lineout plug/unplug */
116
117static int lo_detect_callback(struct timeout *tmo)
118{
119 /* Try to post only transistions */
120 const long id = tmo->data ? SYS_LINEOUT_PLUGGED : SYS_LINEOUT_UNPLUGGED;
121 queue_remove_from_head(&button_queue, id);
122 queue_post(&button_queue, id, 0);
123 return 0;
124}
125#endif
126
112static bool button_try_post(int button, int data) 127static bool button_try_post(int button, int data)
113{ 128{
114#ifdef HAVE_TOUCHSCREEN 129#ifdef HAVE_TOUCHSCREEN
@@ -176,10 +191,19 @@ static void button_tick(void)
176 { 191 {
177 /* Use the autoresetting oneshot to debounce the detection signal */ 192 /* Use the autoresetting oneshot to debounce the detection signal */
178 phones_present = !phones_present; 193 phones_present = !phones_present;
179 timeout_register(&hp_detect_timeout, btn_detect_callback, 194 timeout_register(&hp_detect_timeout, hp_detect_callback,
180 HZ/2, phones_present); 195 HZ/2, phones_present);
181 } 196 }
182#endif 197#endif
198#if defined(HAVE_LINEOUT_DETECTION)
199 if (lineout_inserted() != lineout_present)
200 {
201 /* Use the autoresetting oneshot to debounce the detection signal */
202 lineout_present = !lineout_present;
203 timeout_register(&lo_detect_timeout, lo_detect_callback,
204 HZ/2, lineout_present);
205 }
206#endif
183 207
184 /* Find out if a key has been released */ 208 /* Find out if a key has been released */
185 diff = btn ^ lastbtn; 209 diff = btn ^ lastbtn;
@@ -318,7 +342,7 @@ static void button_tick(void)
318#ifdef HAVE_BACKLIGHT 342#ifdef HAVE_BACKLIGHT
319#ifdef HAVE_REMOTE_LCD 343#ifdef HAVE_REMOTE_LCD
320 if (btn & BUTTON_REMOTE) { 344 if (btn & BUTTON_REMOTE) {
321 if (!remote_filter_first_keypress 345 if (!remote_filter_first_keypress
322 || is_remote_backlight_on(false) 346 || is_remote_backlight_on(false)
323#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES) 347#if defined(IRIVER_H100_SERIES) || defined(IRIVER_H300_SERIES)
324 || (remote_type()==REMOTETYPE_H300_NONLCD) 348 || (remote_type()==REMOTETYPE_H300_NONLCD)
@@ -427,7 +451,7 @@ static void button_queue_wait(struct queue_event *evp, int timeout)
427 #endif 451 #endif
428 button_boost(true); 452 button_boost(true);
429 453
430 break; 454 break;
431 } 455 }
432 456
433 if (button_boosted && TIME_AFTER(current_tick, button_unboost_tick)) 457 if (button_boosted && TIME_AFTER(current_tick, button_unboost_tick))
@@ -462,7 +486,7 @@ long button_get(bool block)
462 486
463long button_get_w_tmo(int ticks) 487long button_get_w_tmo(int ticks)
464{ 488{
465 struct queue_event ev; 489 struct queue_event ev;
466 button_queue_wait(&ev, ticks); 490 button_queue_wait(&ev, ticks);
467 491
468 if (ev.id == SYS_TIMEOUT) 492 if (ev.id == SYS_TIMEOUT)
@@ -496,7 +520,7 @@ void button_init(void)
496 button_read(); 520 button_read();
497 lastbtn = button_read(); 521 lastbtn = button_read();
498#endif 522#endif
499 523
500 reset_poweroff_timer(); 524 reset_poweroff_timer();
501 525
502#ifdef HAVE_LCD_BITMAP 526#ifdef HAVE_LCD_BITMAP
@@ -506,11 +530,11 @@ void button_init(void)
506 filter_first_keypress = false; 530 filter_first_keypress = false;
507#ifdef HAVE_REMOTE_LCD 531#ifdef HAVE_REMOTE_LCD
508 remote_filter_first_keypress = false; 532 remote_filter_first_keypress = false;
509#endif 533#endif
510#endif 534#endif
511#ifdef HAVE_TOUCHSCREEN 535#ifdef HAVE_TOUCHSCREEN
512 last_touchscreen_touch = 0xffff; 536 last_touchscreen_touch = 0xffff;
513#endif 537#endif
514 /* Start polling last */ 538 /* Start polling last */
515 tick_add_task(button_tick); 539 tick_add_task(button_tick);
516} 540}
@@ -647,7 +671,7 @@ static int button_read(void)
647#ifdef HAVE_TOUCHSCREEN 671#ifdef HAVE_TOUCHSCREEN
648 if (btn & BUTTON_TOUCHSCREEN) 672 if (btn & BUTTON_TOUCHSCREEN)
649 last_touchscreen_touch = current_tick; 673 last_touchscreen_touch = current_tick;
650#endif 674#endif
651 /* Filter the button status. It is only accepted if we get the same 675 /* Filter the button status. It is only accepted if we get the same
652 status twice in a row. */ 676 status twice in a row. */
653#ifndef HAVE_TOUCHSCREEN 677#ifndef HAVE_TOUCHSCREEN
@@ -696,8 +720,8 @@ int touchscreen_last_touch(void)
696 * [23:0] Velocity - degree/sec 720 * [23:0] Velocity - degree/sec
697 * 721 *
698 * WHEEL_ACCEL_FACTOR: 722 * WHEEL_ACCEL_FACTOR:
699 * Value in degree/sec -- configurable via settings -- above which 723 * Value in degree/sec -- configurable via settings -- above which
700 * the accelerated scrolling starts. Factor is internally scaled by 724 * the accelerated scrolling starts. Factor is internally scaled by
701 * 1<<16 in respect to the following 32bit integer operations. 725 * 1<<16 in respect to the following 32bit integer operations.
702 */ 726 */
703int button_apply_acceleration(const unsigned int data) 727int 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);
44#ifdef HAS_BUTTON_HOLD 44#ifdef HAS_BUTTON_HOLD
45bool button_hold(void); 45bool button_hold(void);
46#endif 46#endif
47#ifdef HAS_REMOTE_BUTTON_HOLD 47#ifdef HAS_REMOTE_BUTTON_HOLD
48bool remote_button_hold(void); 48bool remote_button_hold(void);
49#endif 49#endif
50 50
@@ -72,6 +72,9 @@ void set_remote_backlight_filter_keypress(bool value);
72#ifdef HAVE_HEADPHONE_DETECTION 72#ifdef HAVE_HEADPHONE_DETECTION
73bool headphones_inserted(void); 73bool headphones_inserted(void);
74#endif 74#endif
75#ifdef HAVE_LINEOUT_DETECTION
76bool lineout_inserted(void);
77#endif
75#ifdef HAVE_WHEEL_POSITION 78#ifdef HAVE_WHEEL_POSITION
76int wheel_status(void); 79int wheel_status(void);
77void wheel_send_events(bool send); 80void 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 @@
73/* Define this if you can detect headphones */ 73/* Define this if you can detect headphones */
74#define HAVE_HEADPHONE_DETECTION 74#define HAVE_HEADPHONE_DETECTION
75 75
76/* Define this if you can detect lineout */
77#define HAVE_LINEOUT_DETECTION
78
76#define CONFIG_KEYPAD XDUOO_X3_PAD 79#define CONFIG_KEYPAD XDUOO_X3_PAD
77 80
78/* Define this if a programmable hotkey is mapped */ 81/* 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 @@
65#define SYS_PHONE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 3) 65#define SYS_PHONE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 3)
66#define SYS_REMOTE_PLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 4) 66#define SYS_REMOTE_PLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 4)
67#define SYS_REMOTE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 5) 67#define SYS_REMOTE_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 5)
68#define SYS_LINEOUT_PLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 6)
69#define SYS_LINEOUT_UNPLUGGED MAKE_SYS_EVENT(SYS_EVENT_CLS_PLUG, 7)
68#define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0) 70#define SYS_CAR_ADAPTER_RESUME MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 0)
69#define SYS_CALL_INCOMING MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 3) 71#define SYS_CALL_INCOMING MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 3)
70#define SYS_CALL_HUNG_UP MAKE_SYS_EVENT(SYS_EVENT_CLS_MISC, 4) 72#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 @@
26#include "pcm_sw_volume.h" 26#include "pcm_sw_volume.h"
27#include "cs4398.h" 27#include "cs4398.h"
28#include "kernel.h" 28#include "kernel.h"
29#include "button.h"
29 30
30#define PIN_CS_RST (32*1+10) 31#define PIN_CS_RST (32*1+10)
31#define PIN_CODEC_PWRON (32*1+13) 32#define PIN_CODEC_PWRON (32*1+13)
@@ -140,7 +141,11 @@ static int vol_tenthdb2hw(const int tdb)
140 } 141 }
141} 142}
142 143
143void audiohw_set_volume(int vol_l, int vol_r) 144#ifdef HAVE_LINEOUT_DETECTION
145static int real_vol_l, real_vol_r;
146#endif
147
148static void jz4760_set_vol(int vol_l, int vol_r)
144{ 149{
145 uint8_t val = cs4398_read_reg(CS4398_REG_MISC) &~ CS4398_FREEZE; 150 uint8_t val = cs4398_read_reg(CS4398_REG_MISC) &~ CS4398_FREEZE;
146 cs4398_write_reg(CS4398_REG_MISC, val | CS4398_FREEZE); 151 cs4398_write_reg(CS4398_REG_MISC, val | CS4398_FREEZE);
@@ -149,14 +154,31 @@ void audiohw_set_volume(int vol_l, int vol_r)
149 cs4398_write_reg(CS4398_REG_MISC, val); 154 cs4398_write_reg(CS4398_REG_MISC, val);
150} 155}
151 156
157void audiohw_set_volume(int vol_l, int vol_r)
158{
159#ifdef HAVE_LINEOUT_DETECTION
160 real_vol_l = vol_l;
161 real_vol_r = vol_r;
162
163 if (lineout_inserted()) {
164 vol_l = 0;
165 vol_r = 0;
166 }
167#endif
168 jz4760_set_vol(vol_l, vol_r);
169}
170
152void audiohw_set_lineout_volume(int vol_l, int vol_r) 171void audiohw_set_lineout_volume(int vol_l, int vol_r)
153{ 172{
154#if 0 /* unused */
155 cs4398_write_reg(CS4398_REG_VOL_A, vol_tenthdb2hw(vol_l));
156 cs4398_write_reg(CS4398_REG_VOL_B, vol_tenthdb2hw(vol_r));
157#else
158 (void)vol_l; 173 (void)vol_l;
159 (void)vol_r; 174 (void)vol_r;
175
176#ifdef HAVE_LINEOUT_DETECTION
177 if (lineout_inserted()) {
178 jz4760_set_vol(0, 0);
179 } else {
180 jz4760_set_vol(real_vol_l, real_vol_r);
181 }
160#endif 182#endif
161} 183}
162 184
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)
53 return (__gpio_get_pin(PIN_PH_DECT) != 0); 53 return (__gpio_get_pin(PIN_PH_DECT) != 0);
54} 54}
55 55
56bool lineout_inserted(void)
57{
58 /* We want to prevent LO being "enabled" if HP is attached
59 to avoid potential eardrum damage */
60 return (__gpio_get_pin(PIN_LO_DECT) == 0) && !headphones_inserted();
61}
62
56void button_init_device(void) 63void button_init_device(void)
57{ 64{
58 key_val = 0xfff; 65 key_val = 0xfff;
@@ -72,11 +79,11 @@ void button_init_device(void)
72 __gpio_set_pin(PIN_CHARGE_CON); /* 0.7 A */ 79 __gpio_set_pin(PIN_CHARGE_CON); /* 0.7 A */
73 __gpio_as_output(PIN_CHARGE_CON); 80 __gpio_as_output(PIN_CHARGE_CON);
74 81
75 __gpio_as_input(PIN_LO_DECT);
76 __gpio_as_input(PIN_PH_DECT); 82 __gpio_as_input(PIN_PH_DECT);
83 __gpio_disable_pull(PIN_PH_DECT);
77 84
85 __gpio_as_input(PIN_LO_DECT);
78 __gpio_disable_pull(PIN_LO_DECT); 86 __gpio_disable_pull(PIN_LO_DECT);
79 __gpio_disable_pull(PIN_PH_DECT);
80} 87}
81 88
82bool button_hold(void) 89bool button_hold(void)