1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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
38 #include "backlight.h"
41 #include "powermgmt.h"
43 /* Variable to use for setting button status in interrupt handler */
44 int int_btn
= BUTTON_NONE
;
45 #ifdef HAVE_WHEEL_POSITION
46 static int wheel_position
= -1;
47 static bool send_events
= true;
50 static void handle_scroll_wheel(int new_scroll
, int was_hold
)
52 int wheel_keycode
= BUTTON_NONE
;
53 static int prev_scroll
= -1;
54 static int direction
= 0;
56 static int scroll_state
[4][4] = {
63 if ( prev_scroll
== -1 ) {
64 prev_scroll
= new_scroll
;
66 else if (direction
!= scroll_state
[prev_scroll
][new_scroll
]) {
67 direction
= scroll_state
[prev_scroll
][new_scroll
];
72 reset_poweroff_timer();
73 if (++count
== 6) { /* reduce sensitivity */
75 /* Mini 1st Gen wheel has inverse direction mapping
76 * compared to 1st..3rd Gen wheel. */
79 wheel_keycode
= BUTTON_SCROLL_FWD
;
82 wheel_keycode
= BUTTON_SCROLL_BACK
;
85 /* only happens if we get out of sync */
90 if (wheel_keycode
!= BUTTON_NONE
&& queue_empty(&button_queue
))
91 queue_post(&button_queue
, wheel_keycode
, 0);
92 prev_scroll
= new_scroll
;
95 /* mini 1 only, mini 2G uses iPod 4G code */
96 static int ipod_mini_button_read(void)
98 unsigned char source
, wheel_source
, state
, wheel_state
;
99 static bool was_hold
= false;
100 int btn
= BUTTON_NONE
;
102 /* The ipodlinux source had a udelay(250) here, but testing has shown that
103 it is not needed - tested on mini 1g. */
106 /* get source(s) of interupt */
107 source
= GPIOA_INT_STAT
& 0x3f;
108 wheel_source
= GPIOB_INT_STAT
& 0x30;
110 if (source
== 0 && wheel_source
== 0) {
111 return BUTTON_NONE
; /* not for us */
114 /* get current keypad & wheel status */
115 state
= GPIOA_INPUT_VAL
& 0x3f;
116 wheel_state
= GPIOB_INPUT_VAL
& 0x30;
118 /* toggle interrupt level */
119 GPIOA_INT_LEV
= ~state
;
120 GPIOB_INT_LEV
= ~wheel_state
;
122 /* hold switch causes all outputs to go low */
123 /* we shouldn't interpret these as key presses */
124 if ((state
& 0x20)) {
126 btn
|= BUTTON_SELECT
;
136 if (wheel_source
& 0x30) {
137 handle_scroll_wheel((wheel_state
& 0x30) >> 4, was_hold
);
141 was_hold
= button_hold();
143 /* ack any active interrupts */
145 GPIOA_INT_CLR
= source
;
147 GPIOB_INT_CLR
= wheel_source
;
152 void ipod_mini_button_int(void)
154 CPU_HI_INT_DIS
= GPIO0_MASK
;
155 int_btn
= ipod_mini_button_read();
156 //CPU_INT_EN = 0x40000000;
157 CPU_HI_INT_EN
= GPIO0_MASK
;
160 void button_init_device(void)
163 /* buttons - enable as input */
164 GPIOA_ENABLE
|= 0x3f;
165 GPIOA_OUTPUT_EN
&= ~0x3f;
166 /* scroll wheel- enable as input */
167 GPIOB_ENABLE
|= 0x30; /* port b 4,5 */
168 GPIOB_OUTPUT_EN
&= ~0x30; /* port b 4,5 */
169 /* buttons - set interrupt levels */
170 GPIOA_INT_LEV
= ~(GPIOA_INPUT_VAL
& 0x3f);
171 GPIOA_INT_CLR
= GPIOA_INT_STAT
& 0x3f;
172 /* scroll wheel - set interrupt levels */
173 GPIOB_INT_LEV
= ~(GPIOB_INPUT_VAL
& 0x30);
174 GPIOB_INT_CLR
= GPIOB_INT_STAT
& 0x30;
175 /* enable interrupts */
178 /* unmask interrupt */
179 CPU_INT_EN
= 0x40000000;
180 CPU_HI_INT_EN
= GPIO0_MASK
;
184 * Get button pressed from hardware
186 int button_read_device(void)
188 static bool hold_button
= false;
189 bool hold_button_old
;
192 hold_button_old
= hold_button
;
193 hold_button
= button_hold();
195 if (hold_button
!= hold_button_old
)
196 backlight_hold_changed(hold_button
);
198 /* The int_btn variable is set in the button interrupt handler */
202 bool button_hold(void)
204 return (GPIOA_INPUT_VAL
& 0x20)?false:true;
207 bool headphones_inserted(void)
209 return (GPIOA_INPUT_VAL
& 0x80)?true:false;