summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2009-01-23 20:55:17 +0000
committerMichael Sevakis <jethead71@rockbox.org>2009-01-23 20:55:17 +0000
commit753b7a90e192dbfd1b268a78e200c103dcca80da (patch)
treef5b6526fe72e1e2203663d69ac9b34368daedffb /firmware/target/arm/imx31
parent34314b1993c0744922754fab1206413441367aea (diff)
Gigabeat S: Add remote control reading and proper headphone insert detection. We need keymaps! A few were copied straight from Gigabeat F/X just to get things worked out.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19830 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/target/arm/imx31')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-imx31.c31
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-target.h14
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c201
3 files changed, 224 insertions, 22 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
index 587e66e0bc..dec0aa108f 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
@@ -32,9 +32,6 @@
/* Most code in here is taken from the Linux BSP provided by Freescale
* Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */
-#ifdef HAVE_HEADPHONE_DETECTION
-static bool headphones_detect = false;
-#endif
static uint32_t int_btn = BUTTON_NONE;
static bool hold_button = false;
#ifdef BOOTLOADER
@@ -123,6 +120,16 @@ bool button_hold(void)
return _button_hold();
}
+#ifdef HAVE_HEADPHONE_DETECTION
+/* Headphone driver pushes the data here */
+void button_headphone_set(int button)
+{
+ int oldstatus = disable_irq_save();
+ int_btn = (int_btn & ~BUTTON_REMOTE) | button;
+ restore_irq(oldstatus);
+}
+#endif
+
int button_read_device(void)
{
/* Simple poll of GPIO status */
@@ -168,21 +175,6 @@ void button_power_event(void)
restore_irq(oldlevel);
}
-#ifdef HAVE_HEADPHONE_DETECTION
-/* This is called from the mc13783 interrupt thread */
-void headphone_detect_event(void)
-{
- /* FIXME: Not really the correct method */
- headphones_detect =
- (mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD2S) == 0;
-}
-
-bool headphones_inserted(void)
-{
- return headphones_detect;
-}
-#endif /* HAVE_HEADPHONE_DETECTION */
-
void button_init_device(void)
{
#ifdef BOOTLOADER
@@ -223,8 +215,7 @@ void button_init_device(void)
mc13783_enable_event(MC13783_ONOFD1_EVENT);
#ifdef HAVE_HEADPHONE_DETECTION
- headphone_detect_event();
- mc13783_enable_event(MC13783_ONOFD2_EVENT);
+ headphone_init();
#endif
}
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-target.h b/firmware/target/arm/imx31/gigabeat-s/button-target.h
index 754694eee5..d970e9983c 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-target.h
+++ b/firmware/target/arm/imx31/gigabeat-s/button-target.h
@@ -37,6 +37,8 @@ int button_read_device(void);
void button_power_event(void);
void headphone_detect_event(void);
bool headphones_inserted(void);
+void headphone_init(void);
+void button_headphone_set(int button);
/* Toshiba Gigabeat S-specific button codes */
@@ -55,9 +57,17 @@ bool headphones_inserted(void);
#define BUTTON_NEXT (1 << 11)
#define BUTTON_POWER (1 << 12) /* Read from PMIC */
-#define BUTTON_MAIN (0x1fff)
+#define BUTTON_MAIN (0x00001fff)
-#define BUTTON_REMOTE 0
+/* Remote control buttons */
+#define BUTTON_RC_VOL_UP (1 << 13)
+#define BUTTON_RC_VOL_DOWN (1 << 14)
+#define BUTTON_RC_FF (1 << 15)
+#define BUTTON_RC_REW (1 << 16)
+#define BUTTON_RC_PLAY (1 << 17)
+#define BUTTON_RC_DSP (1 << 18)
+
+#define BUTTON_REMOTE (0x0007e000)
#define POWEROFF_BUTTON BUTTON_POWER
#define POWEROFF_COUNT 10
diff --git a/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c
new file mode 100644
index 0000000000..6043d00bf5
--- /dev/null
+++ b/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c
@@ -0,0 +1,201 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2009 by Michael Sevakis
+ *
+ * Driver to handle headphone jack events
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include "system.h"
+#include "kernel.h"
+#include "thread.h"
+#include "mc13783.h"
+#include "mc13783-target.h"
+#include "adc.h"
+#include "button.h"
+
+static struct wakeup headphone_wakeup;
+static unsigned int headphone_thread_id;
+static int headphone_stack[160/sizeof(int)]; /* Not much stack needed */
+static const char * const headphone_thread_name = "headphone";
+static bool headphones_detect = false;
+
+/* Convert ADC reading into a button value. */
+static int adc_data_to_button(unsigned int data)
+{
+ int btn = BUTTON_NONE;
+
+ if (data < 505)
+ {
+ if (data < 252)
+ {
+ if (data < 149)
+ {
+ if (data >= 64)
+ {
+ /* Play/Pause */
+ btn = BUTTON_RC_PLAY;
+ }
+ /* else headphone direct */
+ }
+ else
+ {
+ /* DSP */
+ btn = BUTTON_RC_DSP;
+ }
+ }
+ else
+ {
+ if (data < 370)
+ {
+ /* RW */
+ btn = BUTTON_RC_REW;
+ }
+ else
+ {
+ /* FF */
+ btn = BUTTON_RC_FF;
+ }
+ }
+ }
+ else
+ {
+ if (data < 870)
+ {
+ if (data < 675)
+ {
+ /* Vol + */
+ btn = BUTTON_RC_VOL_UP;
+ }
+ else
+ {
+ /* Vol - */
+ btn = BUTTON_RC_VOL_DOWN;
+ }
+ }
+#if 0
+ else
+ {
+
+ if (data < 951)
+ {
+ /* No buttons */
+ }
+ else
+ {
+ /* Not inserted */
+
+ }
+ }
+#endif
+ }
+
+ return btn;
+}
+
+static void headphone_thread(void)
+{
+ int headphone_sleep_countdown = 0;
+ int headphone_wait_timeout = TIMEOUT_BLOCK;
+
+ while (1)
+ {
+ int rc = wakeup_wait(&headphone_wakeup, headphone_wait_timeout);
+ unsigned int data = adc_read(ADC_HPREMOTE);
+
+ if (rc == OBJ_WAIT_TIMEDOUT)
+ {
+ if (headphone_sleep_countdown <= 0)
+ {
+ /* Polling ADC */
+ int btn, btn2;
+
+ btn = adc_data_to_button(data);
+ sleep(HZ/50);
+ data = adc_read(ADC_HPREMOTE);
+ btn2 = adc_data_to_button(data);
+
+ if (btn != btn2)
+ {
+ /* If the buttons dont agree twice in a row, then it's
+ * none (from meg-fx remote reader). */
+ btn = BUTTON_NONE;
+ }
+
+ button_headphone_set(btn);
+ continue;
+ }
+
+ if (--headphone_sleep_countdown == 0)
+ {
+ /* Nothing has changed and remote is not present -
+ * go to sleep. */
+ headphone_wait_timeout = TIMEOUT_BLOCK;
+ continue;
+ }
+ }
+
+ headphones_detect = data <= 951; /* Max remote value */
+
+ /* Cancel any buttons if jack readings are unstable. */
+ button_headphone_set(BUTTON_NONE);
+
+ if (data >= 64 && data <= 951)
+ {
+ /* Should be a remote control - accelerate */
+ headphone_wait_timeout = HZ/20-HZ/50;
+ headphone_sleep_countdown = 0;
+ }
+ else if (rc == OBJ_WAIT_SUCCEEDED)
+ {
+ /* Got signaled - something is being plugged/unplugged. Set
+ * countdown until we just give up and go to sleep (~10s). */
+ headphone_wait_timeout = HZ/2;
+ headphone_sleep_countdown = 10*2;
+ }
+ }
+}
+
+/* This is called from the mc13783 interrupt thread */
+void headphone_detect_event(void)
+{
+ /* Trigger the thread immediately. */
+ wakeup_signal(&headphone_wakeup);
+}
+
+/* Tell if anything is in the jack. */
+bool headphones_inserted(void)
+{
+ return headphones_detect;
+}
+
+void headphone_init(void)
+{
+ /* A thread is required to monitor the remote ADC and jack state. */
+ wakeup_init(&headphone_wakeup);
+ headphone_thread_id = create_thread(headphone_thread,
+ headphone_stack,
+ sizeof(headphone_stack),
+ 0, headphone_thread_name
+ IF_PRIO(, PRIORITY_REALTIME)
+ IF_COP(, CPU));
+
+ /* Initially poll and then enable PMIC event */
+ headphone_detect_event();
+ mc13783_enable_event(MC13783_ONOFD2_EVENT);
+}