summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target')
-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 ae158b811d..90db00dcc3 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 @@
31 31
32/* Most code in here is taken from the Linux BSP provided by Freescale 32/* Most code in here is taken from the Linux BSP provided by Freescale
33 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */ 33 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */
34static uint32_t int_btn = BUTTON_NONE;
35static bool hold_button = false;
36#ifdef BOOTLOADER 34#ifdef BOOTLOADER
37static bool initialized = false; 35static bool initialized = false;
38#else 36#endif
37
38static int ext_btn = BUTTON_NONE; /* Buttons not on KPP */
39static bool hold_button = false;
40#ifndef BOOTLOADER
39static bool hold_button_old = false; 41static bool hold_button_old = false;
40#endif 42#endif
43
41#define _button_hold() (GPIO3_DR & 0x10) 44#define _button_hold() (GPIO3_DR & 0x10)
42 45
43static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void) 46/* Scan the keypad port and return the pressed buttons */
47static int kpp_scan(void)
44{ 48{
45 static const struct key_mask_shift 49 static const struct key_mask_shift
46 { 50 {
@@ -53,19 +57,9 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
53 { 0x1f, 7 }, /* BUTTON_VOL_UP...BUTTON_NEXT */ 57 { 0x1f, 7 }, /* BUTTON_VOL_UP...BUTTON_NEXT */
54 }; 58 };
55 59
56 int col; 60 int button = BUTTON_NONE;
57 /* Power button is handled separately on PMIC, remote read in headphone
58 * jack driver. */
59#ifdef HAVE_HEADPHONE_DETECTION
60 int button = int_btn & (BUTTON_POWER | BUTTON_REMOTE);
61#else
62 int button = int_btn & BUTTON_POWER;
63#endif
64
65 int oldlevel = disable_irq_save(); 61 int oldlevel = disable_irq_save();
66 62 int col;
67 /* 1. Disable both (depress and release) keypad interrupts. */
68 KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE);
69 63
70 for (col = 0; col < 3; col++) /* Col */ 64 for (col = 0; col < 3; col++) /* Col */
71 { 65 {
@@ -106,17 +100,9 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
106 * clear the KPKD synchronizer chain by writing "1" to KDSC register */ 100 * clear the KPKD synchronizer chain by writing "1" to KDSC register */
107 KPP_KPSR = KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKR | KPP_KPSR_KPKD; 101 KPP_KPSR = KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKR | KPP_KPSR_KPKD;
108 102
109 /* 10. Re-enable the appropriate keypad interrupt(s) so that the KDIE
110 * detects a key hold condition, or the KRIE detects a key-release
111 * event. */
112 if ((button & ~BUTTON_POWER) != BUTTON_NONE)
113 KPP_KPSR |= KPP_KPSR_KRIE;
114 else
115 KPP_KPSR |= KPP_KPSR_KDIE;
116
117 int_btn = button;
118
119 restore_irq(oldlevel); 103 restore_irq(oldlevel);
104
105 return button;
120} 106}
121 107
122bool button_hold(void) 108bool button_hold(void)
@@ -129,7 +115,7 @@ bool button_hold(void)
129void button_headphone_set(int button) 115void button_headphone_set(int button)
130{ 116{
131 int oldstatus = disable_irq_save(); 117 int oldstatus = disable_irq_save();
132 int_btn = (int_btn & ~BUTTON_REMOTE) | button; 118 ext_btn = (ext_btn & ~BUTTON_REMOTE) | button;
133 restore_irq(oldstatus); 119 restore_irq(oldstatus);
134} 120}
135#endif 121#endif
@@ -148,19 +134,19 @@ int button_read_device(void)
148 } 134 }
149#endif 135#endif
150 136
151 /* Enable the keypad interrupt to cause it to fire if a key is down. 137 int button = ext_btn;
152 * KPP_HANDLER will clear and disable it after the scan. If no key 138
153 * is depressed then this bit will already be set in waiting for the 139 /* Check status for key down flag and scan port if so indicated. */
154 * first key down event. */ 140 if (KPP_KPSR & KPP_KPSR_KPKD)
155 KPP_KPSR |= KPP_KPSR_KDIE; 141 button |= kpp_scan();
156 142
157#ifdef HAVE_HEADPHONE_DETECTION 143#ifdef HAVE_HEADPHONE_DETECTION
158 /* If hold, ignore any pressed button. Remote has its own hold 144 /* If hold, ignore any pressed button. Remote has its own hold
159 * switch, so return state regardless. */ 145 * switch, so return state regardless. */
160 return hold_button ? (int_btn & BUTTON_REMOTE) : int_btn; 146 return hold_button ? (button & BUTTON_REMOTE) : button;
161#else 147#else
162 /* If hold, ignore any pressed button. */ 148 /* If hold, ignore any pressed button. */
163 return hold_button ? BUTTON_NONE : int_btn; 149 return hold_button ? BUTTON_NONE : button;
164#endif 150#endif
165} 151}
166 152
@@ -170,16 +156,15 @@ void button_power_event(void)
170 bool pressed = 156 bool pressed =
171 (mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD1S) == 0; 157 (mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD1S) == 0;
172 158
173 /* Prevent KPP_HANDLER from changing things */
174 int oldlevel = disable_irq_save(); 159 int oldlevel = disable_irq_save();
175 160
176 if (pressed) 161 if (pressed)
177 { 162 {
178 int_btn |= BUTTON_POWER; 163 ext_btn |= BUTTON_POWER;
179 } 164 }
180 else 165 else
181 { 166 {
182 int_btn &= ~BUTTON_POWER; 167 ext_btn &= ~BUTTON_POWER;
183 } 168 }
184 169
185 restore_irq(oldlevel); 170 restore_irq(oldlevel);
@@ -216,9 +201,7 @@ void button_init_device(void)
216 201
217 /* 5. Clear the KPKD Status Flag and Synchronizer chain. 202 /* 5. Clear the KPKD Status Flag and Synchronizer chain.
218 * 6. Set the KDIE control bit bit. */ 203 * 6. Set the KDIE control bit bit. */
219 KPP_KPSR = KPP_KPSR_KDIE | KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD; 204 KPP_KPSR = KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD;
220
221 avic_enable_int(INT_KPP, INT_TYPE_IRQ, INT_PRIO_DEFAULT, KPP_HANDLER);
222 205
223 button_power_event(); 206 button_power_event();
224 mc13783_enable_event(MC13783_ONOFD1_EVENT); 207 mc13783_enable_event(MC13783_ONOFD1_EVENT);
@@ -231,12 +214,13 @@ void button_init_device(void)
231#ifdef BUTTON_DRIVER_CLOSE 214#ifdef BUTTON_DRIVER_CLOSE
232void button_close_device(void) 215void button_close_device(void)
233{ 216{
234 int oldlevel = disable_irq_save(); 217 if (!initialized)
218 return;
235 219
236 avic_disable_int(INT_KPP); 220 /* Assumes HP detection is not available */
237 KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE); 221 initialized = false;
238 int_btn = BUTTON_NONE;
239 222
240 restore_irq(oldlevel); 223 mc13783_disable_event(MC13783_ONOFD1_EVENT);
224 ext_btn = BUTTON_NONE;
241} 225}
242#endif /* BUTTON_DRIVER_CLOSE */ 226#endif /* BUTTON_DRIVER_CLOSE */