Fix typo and correct punctuation
[maemo-rb.git] / firmware / target / arm / ipod / button-1g-3g.c
blob6c2a8c059c89c89ca7c882f383333c92c7d6f3f6
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Daniel Stenberg
12 * iPod driver based on code from the ipodlinux project - http://ipodlinux.org
13 * Adapted for Rockbox in December 2005
14 * Original file: linux/arch/armnommu/mach-ipod/keyboard.c
15 * Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
24 * KIND, either express or implied.
26 ****************************************************************************/
29 * Rockbox button functions
32 #include <stdlib.h>
33 #include "config.h"
34 #include "cpu.h"
35 #include "system.h"
36 #include "button.h"
37 #include "kernel.h"
38 #include "backlight.h"
39 #include "serial.h"
40 #include "power.h"
41 #include "powermgmt.h"
42 #include "hwcompat.h"
44 static int int_btn = BUTTON_NONE;
45 #ifdef IPOD_1G2G
46 /* The 1st Gen wheel draws ~12mA when enabled permanently. Therefore
47 * we only enable it for a very short time to check for changes every
48 * tick, and only keep it enabled if there is activity. */
49 #define WHEEL_TIMEOUT (HZ/4)
50 #endif
52 static void handle_scroll_wheel(int new_scroll, int was_hold)
54 int wheel_keycode = BUTTON_NONE;
55 static int prev_scroll = -1;
56 static int direction = 0;
57 static int count = 0;
58 static int scroll_state[4][4] = {
59 {0, 1, -1, 0},
60 {-1, 0, 0, 1},
61 {1, 0, 0, -1},
62 {0, -1, 1, 0}
65 if ( prev_scroll == -1 ) {
66 prev_scroll = new_scroll;
68 else if (direction != scroll_state[prev_scroll][new_scroll]) {
69 direction = scroll_state[prev_scroll][new_scroll];
70 count = 0;
72 else if (!was_hold) {
73 backlight_on();
74 reset_poweroff_timer();
75 if (++count == 6) { /* reduce sensitivity */
76 count = 0;
77 /* 1st..3rd Gen wheel has inverse direction mapping
78 * compared to Mini 1st Gen wheel. */
79 switch (direction) {
80 case 1:
81 wheel_keycode = BUTTON_SCROLL_BACK;
82 break;
83 case -1:
84 wheel_keycode = BUTTON_SCROLL_FWD;
85 break;
86 default:
87 /* only happens if we get out of sync */
88 break;
92 if (wheel_keycode != BUTTON_NONE && queue_empty(&button_queue))
93 queue_post(&button_queue, wheel_keycode, 0);
94 prev_scroll = new_scroll;
97 static int ipod_3g_button_read(void)
99 unsigned char source, state;
100 static bool was_hold = false;
101 int btn = BUTTON_NONE;
103 #ifdef IPOD_3G
104 /* The following delay was 250 in the ipodlinux source,
105 * but 50 seems to work fine. 250 causes the wheel to stop
106 * working when spinning it real fast. */
107 udelay(50);
108 #endif
110 /* get source of interupts */
111 source = GPIOA_INT_STAT;
113 /* get current keypad status */
114 state = GPIOA_INPUT_VAL;
116 /* toggle interrupt level */
117 GPIOA_INT_LEV = ~state;
119 #ifdef IPOD_3G
120 if (was_hold && source == 0x40 && state == 0xbf) {
121 /* ack any active interrupts */
122 GPIOA_INT_CLR = source;
123 return BUTTON_NONE;
125 was_hold = false;
127 if ((state & 0x20) == 0) {
128 /* 3g hold switch is active low */
129 was_hold = true;
130 /* hold switch on 3g causes all outputs to go low */
131 /* we shouldn't interpret these as key presses */
132 GPIOA_INT_CLR = source;
133 return BUTTON_NONE;
135 #elif defined IPOD_1G2G
136 if (state & 0x20) {
137 /* 1g/2g hold switch is active high */
138 GPIOA_INT_CLR = source;
139 return BUTTON_NONE;
141 #endif
142 if ((state & 0x1) == 0) {
143 btn |= BUTTON_RIGHT;
145 if ((state & 0x2) == 0) {
146 btn |= BUTTON_SELECT;
148 if ((state & 0x4) == 0) {
149 btn |= BUTTON_PLAY;
151 if ((state & 0x8) == 0) {
152 btn |= BUTTON_LEFT;
154 if ((state & 0x10) == 0) {
155 btn |= BUTTON_MENU;
158 if (source & 0xc0) {
159 handle_scroll_wheel((state & 0xc0) >> 6, was_hold);
162 /* ack any active interrupts */
163 GPIOA_INT_CLR = source;
165 return btn;
168 void ipod_3g_button_int(void)
170 CPU_INT_DIS = GPIO_MASK;
171 int_btn = ipod_3g_button_read();
172 CPU_INT_EN = GPIO_MASK;
175 void button_init_device(void)
177 GPIOA_ENABLE = 0xff;
178 GPIOA_OUTPUT_EN = 0;
180 GPIOA_INT_LEV = ~GPIOA_INPUT_VAL;
181 GPIOA_INT_CLR = GPIOA_INT_STAT;
183 #ifdef IPOD_1G2G
184 if ((IPOD_HW_REVISION >> 16) == 1)
185 { /* enable scroll wheel */
186 GPIOB_ENABLE |= 0x01;
187 GPIOB_OUTPUT_EN |= 0x01;
188 GPIOB_OUTPUT_VAL |= 0x01;
190 #endif
191 GPIOA_INT_EN = 0xff;
193 CPU_INT_EN = GPIO_MASK;
197 * Get button pressed from hardware
199 int button_read_device(void)
201 static bool hold_button = false;
202 bool hold_button_old;
203 #ifdef IPOD_1G2G
204 static int wheel_timeout = 0;
205 static unsigned char last_wheel_value = 0;
206 unsigned char wheel_value;
208 if ((IPOD_HW_REVISION >> 16) == 1)
210 if (!hold_button && (wheel_timeout == 0))
212 GPIOB_OUTPUT_VAL |= 0x01; /* enable wheel */
213 udelay(50); /* let the voltage settle */
215 wheel_value = GPIOA_INPUT_VAL >> 6;
216 if (wheel_value != last_wheel_value)
218 last_wheel_value = wheel_value;
219 wheel_timeout = WHEEL_TIMEOUT; /* keep wheel enabled */
220 GPIOA_INT_EN = 0xff; /* enable wheel interrupts */
222 if (wheel_timeout)
223 wheel_timeout--;
224 else
226 GPIOA_INT_EN = 0x3f; /* disable wheel interrupts */
227 GPIOB_OUTPUT_VAL &= ~0x01; /* disable wheel */
230 #endif
232 /* normal buttons */
233 hold_button_old = hold_button;
234 hold_button = button_hold();
236 if (hold_button != hold_button_old)
237 backlight_hold_changed(hold_button);
239 return int_btn;
242 bool button_hold(void)
244 #ifdef IPOD_1G2G
245 return (GPIOA_INPUT_VAL & 0x20);
246 #else
247 return !(GPIOA_INPUT_VAL & 0x20);
248 #endif
251 bool headphones_inserted(void)
253 #ifdef IPOD_1G2G
254 if ((IPOD_HW_REVISION >> 16) == 2)
256 /* 2G uses GPIO B bit 0 */
257 return (GPIOB_INPUT_VAL & 0x1)?true:false;
259 else
261 /* 1G has no headphone detection, so fake insertion */
262 return (true);
264 #else
265 /* 3G uses GPIO C bit 0 */
266 return (GPIOC_INPUT_VAL & 0x1)?true:false;
267 #endif