summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-12-29 18:20:31 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-12-29 18:20:31 +0000
commit65850011ccf0baff376bf0d352528db2bb06f1a9 (patch)
treeb516c87375b8cee0621f6afe2c28b2421f5d7a15
parente541c98a7e19f22ab62a0adb370ea9f4c922e666 (diff)
downloadrockbox-65850011ccf0baff376bf0d352528db2bb06f1a9.zip
rockbox-65850011ccf0baff376bf0d352528db2bb06f1a9.tar.gz
rockbox-65850011ccf0baff376bf0d352528db2bb06f1a9.tar.bz2
rockbox-65850011ccf0baff376bf0d352528db2bb06f1a9.tar.xz
Gigabeat S: Do simple direct keypad scanning rather than triggering a separate scan interrupt and it all does the same thing but with 1 tick less latency.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28926 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c74
1 files changed, 29 insertions, 45 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c
index ae158b8..90db00d 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c
@@ -31,16 +31,20 @@
/* Most code in here is taken from the Linux BSP provided by Freescale
* Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */
-static uint32_t int_btn = BUTTON_NONE;
-static bool hold_button = false;
#ifdef BOOTLOADER
static bool initialized = false;
-#else
+#endif
+
+static int ext_btn = BUTTON_NONE; /* Buttons not on KPP */
+static bool hold_button = false;
+#ifndef BOOTLOADER
static bool hold_button_old = false;
#endif
+
#define _button_hold() (GPIO3_DR & 0x10)
-static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
+/* Scan the keypad port and return the pressed buttons */
+static int kpp_scan(void)
{
static const struct key_mask_shift
{
@@ -53,19 +57,9 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
{ 0x1f, 7 }, /* BUTTON_VOL_UP...BUTTON_NEXT */
};
- int col;
- /* Power button is handled separately on PMIC, remote read in headphone
- * jack driver. */
-#ifdef HAVE_HEADPHONE_DETECTION
- int button = int_btn & (BUTTON_POWER | BUTTON_REMOTE);
-#else
- int button = int_btn & BUTTON_POWER;
-#endif
-
+ int button = BUTTON_NONE;
int oldlevel = disable_irq_save();
-
- /* 1. Disable both (depress and release) keypad interrupts. */
- KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE);
+ int col;
for (col = 0; col < 3; col++) /* Col */
{
@@ -106,17 +100,9 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
* clear the KPKD synchronizer chain by writing "1" to KDSC register */
KPP_KPSR = KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKR | KPP_KPSR_KPKD;
- /* 10. Re-enable the appropriate keypad interrupt(s) so that the KDIE
- * detects a key hold condition, or the KRIE detects a key-release
- * event. */
- if ((button & ~BUTTON_POWER) != BUTTON_NONE)
- KPP_KPSR |= KPP_KPSR_KRIE;
- else
- KPP_KPSR |= KPP_KPSR_KDIE;
-
- int_btn = button;
-
restore_irq(oldlevel);
+
+ return button;
}
bool button_hold(void)
@@ -129,7 +115,7 @@ bool button_hold(void)
void button_headphone_set(int button)
{
int oldstatus = disable_irq_save();
- int_btn = (int_btn & ~BUTTON_REMOTE) | button;
+ ext_btn = (ext_btn & ~BUTTON_REMOTE) | button;
restore_irq(oldstatus);
}
#endif
@@ -148,19 +134,19 @@ int button_read_device(void)
}
#endif
- /* Enable the keypad interrupt to cause it to fire if a key is down.
- * KPP_HANDLER will clear and disable it after the scan. If no key
- * is depressed then this bit will already be set in waiting for the
- * first key down event. */
- KPP_KPSR |= KPP_KPSR_KDIE;
+ int button = ext_btn;
+
+ /* Check status for key down flag and scan port if so indicated. */
+ if (KPP_KPSR & KPP_KPSR_KPKD)
+ button |= kpp_scan();
#ifdef HAVE_HEADPHONE_DETECTION
/* If hold, ignore any pressed button. Remote has its own hold
* switch, so return state regardless. */
- return hold_button ? (int_btn & BUTTON_REMOTE) : int_btn;
+ return hold_button ? (button & BUTTON_REMOTE) : button;
#else
/* If hold, ignore any pressed button. */
- return hold_button ? BUTTON_NONE : int_btn;
+ return hold_button ? BUTTON_NONE : button;
#endif
}
@@ -170,16 +156,15 @@ void button_power_event(void)
bool pressed =
(mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD1S) == 0;
- /* Prevent KPP_HANDLER from changing things */
int oldlevel = disable_irq_save();
if (pressed)
{
- int_btn |= BUTTON_POWER;
+ ext_btn |= BUTTON_POWER;
}
else
{
- int_btn &= ~BUTTON_POWER;
+ ext_btn &= ~BUTTON_POWER;
}
restore_irq(oldlevel);
@@ -216,9 +201,7 @@ void button_init_device(void)
/* 5. Clear the KPKD Status Flag and Synchronizer chain.
* 6. Set the KDIE control bit bit. */
- KPP_KPSR = KPP_KPSR_KDIE | KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD;
-
- avic_enable_int(INT_KPP, INT_TYPE_IRQ, INT_PRIO_DEFAULT, KPP_HANDLER);
+ KPP_KPSR = KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD;
button_power_event();
mc13783_enable_event(MC13783_ONOFD1_EVENT);
@@ -231,12 +214,13 @@ void button_init_device(void)
#ifdef BUTTON_DRIVER_CLOSE
void button_close_device(void)
{
- int oldlevel = disable_irq_save();
+ if (!initialized)
+ return;
- avic_disable_int(INT_KPP);
- KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE);
- int_btn = BUTTON_NONE;
+ /* Assumes HP detection is not available */
+ initialized = false;
- restore_irq(oldlevel);
+ mc13783_disable_event(MC13783_ONOFD1_EVENT);
+ ext_btn = BUTTON_NONE;
}
#endif /* BUTTON_DRIVER_CLOSE */