diff options
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/button-gigabeat-s.c | 74 |
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. */ |
34 | static uint32_t int_btn = BUTTON_NONE; | ||
35 | static bool hold_button = false; | ||
36 | #ifdef BOOTLOADER | 34 | #ifdef BOOTLOADER |
37 | static bool initialized = false; | 35 | static bool initialized = false; |
38 | #else | 36 | #endif |
37 | |||
38 | static int ext_btn = BUTTON_NONE; /* Buttons not on KPP */ | ||
39 | static bool hold_button = false; | ||
40 | #ifndef BOOTLOADER | ||
39 | static bool hold_button_old = false; | 41 | static 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 | ||
43 | static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void) | 46 | /* Scan the keypad port and return the pressed buttons */ |
47 | static 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 | ||
122 | bool button_hold(void) | 108 | bool button_hold(void) |
@@ -129,7 +115,7 @@ bool button_hold(void) | |||
129 | void button_headphone_set(int button) | 115 | void 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 |
232 | void button_close_device(void) | 215 | void 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 */ |