summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/imx31/gigabeat-s/button-imx31.c')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/button-imx31.c123
1 files changed, 67 insertions, 56 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
index 746883d010..ad1e2b7e49 100644
--- a/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
+++ b/firmware/target/arm/imx31/gigabeat-s/button-imx31.c
@@ -26,6 +26,7 @@
26#include "backlight-target.h" 26#include "backlight-target.h"
27#include "avic-imx31.h" 27#include "avic-imx31.h"
28#include "clkctl-imx31.h" 28#include "clkctl-imx31.h"
29#include "mc13783.h"
29 30
30/* Most code in here is taken from the Linux BSP provided by Freescale 31/* Most code in here is taken from the Linux BSP provided by Freescale
31 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */ 32 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */
@@ -119,56 +120,6 @@ static __attribute__((interrupt("IRQ"))) void KPP_HANDLER(void)
119 int_btn = button; 120 int_btn = button;
120} 121}
121 122
122void button_init_device(void)
123{
124#ifdef BOOTLOADER
125 /* Can be called more than once in the bootloader */
126 if (initialized)
127 return;
128
129 initialized = true;
130#endif
131
132 /* Enable keypad clock */
133 imx31_clkctl_module_clock_gating(CG_KPP, CGM_ON_ALL);
134
135 /* 1. Enable number of rows in keypad (KPCR[4:0])
136 *
137 * Configure the rows/cols in KPP
138 * LSB nybble in KPP is for 5 rows
139 * MSB nybble in KPP is for 3 cols */
140 KPP_KPCR |= 0x1f;
141
142 /* 2. Write 0's to KPDR[10:8] */
143 KPP_KPDR &= ~(0x7 << 8);
144
145 /* 3. Configure the keypad columns as open-drain (KPCR[10:8]). */
146 KPP_KPCR |= (0x7 << 8);
147
148 /* 4. Configure columns as output, rows as input (KDDR[10:8,4:0]) */
149 KPP_KDDR = (KPP_KDDR | (0x7 << 8)) & ~0x1f;
150
151 /* 5. Clear the KPKD Status Flag and Synchronizer chain.
152 * 6. Set the KDIE control bit bit. */
153 KPP_KPSR = KPP_KPSR_KDIE | KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD;
154
155 /* KPP IRQ at priority 3 */
156 avic_enable_int(KPP, IRQ, 3, KPP_HANDLER);
157}
158
159#ifdef BUTTON_DRIVER_CLOSE
160void button_close_device(void)
161{
162 int oldlevel = disable_irq_save();
163
164 avic_disable_int(KPP);
165 KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE);
166 int_btn = BUTTON_NONE;
167
168 restore_irq(oldlevel);
169}
170#endif /* BUTTON_DRIVER_CLOSE */
171
172bool button_hold(void) 123bool button_hold(void)
173{ 124{
174 return _button_hold(); 125 return _button_hold();
@@ -199,8 +150,11 @@ int button_read_device(void)
199} 150}
200 151
201/* This is called from the mc13783 interrupt thread */ 152/* This is called from the mc13783 interrupt thread */
202void button_power_set_state(bool pressed) 153void button_power_event(void)
203{ 154{
155 bool pressed =
156 (mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD1S) == 0;
157
204 /* Prevent KPP_HANDLER from changing things */ 158 /* Prevent KPP_HANDLER from changing things */
205 int oldlevel = disable_irq_save(); 159 int oldlevel = disable_irq_save();
206 160
@@ -218,16 +172,73 @@ void button_power_set_state(bool pressed)
218 172
219#ifdef HAVE_HEADPHONE_DETECTION 173#ifdef HAVE_HEADPHONE_DETECTION
220/* This is called from the mc13783 interrupt thread */ 174/* This is called from the mc13783 interrupt thread */
221void set_headphones_inserted(bool inserted) 175void headphone_detect_event(void)
222{ 176{
223 headphones_detect = inserted; 177 /* FIXME: Not really the correct method */
178 headphones_detect =
179 (mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD2S) == 0;
224} 180}
225 181
226/* This is called from the mc13783 interrupt thread */
227/* TODO: Just do a post to the button queue directly - implement the
228 * appropriate variant in the driver. */
229bool headphones_inserted(void) 182bool headphones_inserted(void)
230{ 183{
231 return headphones_detect; 184 return headphones_detect;
232} 185}
233#endif /* HAVE_HEADPHONE_DETECTION */ 186#endif /* HAVE_HEADPHONE_DETECTION */
187
188void button_init_device(void)
189{
190#ifdef BOOTLOADER
191 /* Can be called more than once in the bootloader */
192 if (initialized)
193 return;
194
195 initialized = true;
196#endif
197
198 /* Enable keypad clock */
199 imx31_clkctl_module_clock_gating(CG_KPP, CGM_ON_ALL);
200
201 /* 1. Enable number of rows in keypad (KPCR[4:0])
202 *
203 * Configure the rows/cols in KPP
204 * LSB nybble in KPP is for 5 rows
205 * MSB nybble in KPP is for 3 cols */
206 KPP_KPCR |= 0x1f;
207
208 /* 2. Write 0's to KPDR[10:8] */
209 KPP_KPDR &= ~(0x7 << 8);
210
211 /* 3. Configure the keypad columns as open-drain (KPCR[10:8]). */
212 KPP_KPCR |= (0x7 << 8);
213
214 /* 4. Configure columns as output, rows as input (KDDR[10:8,4:0]) */
215 KPP_KDDR = (KPP_KDDR | (0x7 << 8)) & ~0x1f;
216
217 /* 5. Clear the KPKD Status Flag and Synchronizer chain.
218 * 6. Set the KDIE control bit bit. */
219 KPP_KPSR = KPP_KPSR_KDIE | KPP_KPSR_KRSS | KPP_KPSR_KDSC | KPP_KPSR_KPKD;
220
221 /* KPP IRQ at priority 3 */
222 avic_enable_int(KPP, IRQ, 3, KPP_HANDLER);
223
224 button_power_event();
225 mc13783_enable_event(MC13783_ONOFD1_EVENT);
226
227#ifdef HAVE_HEADPHONE_DETECTION
228 headphone_detect_event();
229 mc13783_enable_event(MC13783_ONOFD2_EVENT);
230#endif
231}
232
233#ifdef BUTTON_DRIVER_CLOSE
234void button_close_device(void)
235{
236 int oldlevel = disable_irq_save();
237
238 avic_disable_int(KPP);
239 KPP_KPSR &= ~(KPP_KPSR_KRIE | KPP_KPSR_KDIE);
240 int_btn = BUTTON_NONE;
241
242 restore_irq(oldlevel);
243}
244#endif /* BUTTON_DRIVER_CLOSE */