summaryrefslogtreecommitdiff
path: root/firmware/target/arm/ipod/button-clickwheel.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/ipod/button-clickwheel.c')
-rw-r--r--firmware/target/arm/ipod/button-clickwheel.c97
1 files changed, 33 insertions, 64 deletions
diff --git a/firmware/target/arm/ipod/button-clickwheel.c b/firmware/target/arm/ipod/button-clickwheel.c
index f01666a8b8..f8dd818a01 100644
--- a/firmware/target/arm/ipod/button-clickwheel.c
+++ b/firmware/target/arm/ipod/button-clickwheel.c
@@ -73,64 +73,40 @@ int int_btn = BUTTON_NONE;
73 73
74static void opto_i2c_init(void) 74static void opto_i2c_init(void)
75{ 75{
76 int i, curr_value; 76 DEV_EN |= DEV_OPTO;
77 77 DEV_RS |= DEV_OPTO;
78 /* wait for value to settle */
79 i = 1000;
80 curr_value = (inl(0x7000c104) << 16) >> 24;
81 while (i > 0)
82 {
83 int new_value = (inl(0x7000c104) << 16) >> 24;
84
85 if (new_value != curr_value) {
86 i = 10000;
87 curr_value = new_value;
88 }
89 else {
90 i--;
91 }
92 }
93
94 GPIOB_OUTPUT_VAL |= 0x10;
95 DEV_EN |= 0x10000;
96 DEV_RS |= 0x10000;
97 udelay(5); 78 udelay(5);
98 DEV_RS &= ~0x10000; /* finish reset */ 79 DEV_RS &= ~DEV_OPTO; /* finish reset */
80 DEV_INIT1 |= INIT_BUTTONS; /* enable buttons (needed for "hold"-detection) */
99 81
100 outl(0xffffffff, 0x7000c120);
101 outl(0xffffffff, 0x7000c124);
102 outl(0xc00a1f00, 0x7000c100); 82 outl(0xc00a1f00, 0x7000c100);
103 outl(0x1000000, 0x7000c104); 83 outl(0x01000000, 0x7000c104);
104} 84}
105 85
106static inline int ipod_4g_button_read(void) 86static inline int ipod_4g_button_read(void)
107{ 87{
108 int whl = -1; 88 int whl = -1;
89 int btn = BUTTON_NONE;
109 90
110 /* The ipodlinux source had a udelay(250) here, but testing has shown that 91 /* The following delay was 250 in the ipodlinux source, but 50 seems to
111 it is not needed - tested on Nano, Color/Photo and Video. */ 92 work fine - tested on Nano, Color/Photo and Video. */
112 /* udelay(250);*/ 93 udelay(50);
113 94
114 int btn = BUTTON_NONE; 95 if ((inl(0x7000c104) & 0x04000000) != 0)
115 unsigned reg = 0x7000c104;
116 if ((inl(0x7000c104) & 0x4000000) != 0)
117 { 96 {
118 unsigned status = inl(0x7000c140); 97 unsigned status = inl(0x7000c140);
119 98
120 reg = reg + 0x3C; /* 0x7000c140 */
121 outl(0x0, 0x7000c140); /* clear interrupt status? */
122
123 if ((status & 0x800000ff) == 0x8000001a) 99 if ((status & 0x800000ff) == 0x8000001a)
124 { 100 {
125 if (status & 0x100) 101 if (status & 0x00000100)
126 btn |= BUTTON_SELECT; 102 btn |= BUTTON_SELECT;
127 if (status & 0x200) 103 if (status & 0x00000200)
128 btn |= BUTTON_RIGHT; 104 btn |= BUTTON_RIGHT;
129 if (status & 0x400) 105 if (status & 0x00000400)
130 btn |= BUTTON_LEFT; 106 btn |= BUTTON_LEFT;
131 if (status & 0x800) 107 if (status & 0x00000800)
132 btn |= BUTTON_PLAY; 108 btn |= BUTTON_PLAY;
133 if (status & 0x1000) 109 if (status & 0x00001000)
134 btn |= BUTTON_MENU; 110 btn |= BUTTON_MENU;
135 if (status & 0x40000000) 111 if (status & 0x40000000)
136 { 112 {
@@ -263,19 +239,10 @@ static inline int ipod_4g_button_read(void)
263 } 239 }
264 240
265 } 241 }
266 else if (status == 0xffffffff)
267 {
268 opto_i2c_init();
269 }
270 } 242 }
271 243
272 if ((inl(reg) & 0x8000000) != 0)
273 {
274 outl(0xffffffff, 0x7000c120);
275 outl(0xffffffff, 0x7000c124);
276 }
277 /* Save the new absolute wheel position */
278#ifdef HAVE_WHEEL_POSITION 244#ifdef HAVE_WHEEL_POSITION
245 /* Save the new absolute wheel position */
279 wheel_position = whl; 246 wheel_position = whl;
280#endif 247#endif
281 return btn; 248 return btn;
@@ -296,16 +263,12 @@ void wheel_send_events(bool send)
296void ipod_4g_button_int(void) 263void ipod_4g_button_int(void)
297{ 264{
298 CPU_HI_INT_CLR = I2C_MASK; 265 CPU_HI_INT_CLR = I2C_MASK;
299 /* The following delay was 250 in the ipodlinux source, but 50 seems to 266
300 work fine - tested on Nano, Color/Photo and Video. */
301 udelay(50);
302 outl(0x0, 0x7000c140);
303 int_btn = ipod_4g_button_read(); 267 int_btn = ipod_4g_button_read();
304 outl(inl(0x7000c104) | 0xC000000, 0x7000c104); 268
269 outl(inl(0x7000c104) | 0x0c000000, 0x7000c104);
305 outl(0x400a1f00, 0x7000c100); 270 outl(0x400a1f00, 0x7000c100);
306 271
307 GPIOB_OUTPUT_VAL |= 0x10;
308 CPU_INT_EN = 0x40000000;
309 CPU_HI_INT_EN = I2C_MASK; 272 CPU_HI_INT_EN = I2C_MASK;
310} 273}
311 274
@@ -317,15 +280,8 @@ void button_init_device(void)
317 GPIOA_ENABLE |= 0x20; 280 GPIOA_ENABLE |= 0x20;
318 GPIOA_OUTPUT_EN &= ~0x20; 281 GPIOA_OUTPUT_EN &= ~0x20;
319 282
320 /* hold button - set interrupt levels */
321 GPIOA_INT_LEV = ~(GPIOA_INPUT_VAL & 0x20);
322 GPIOA_INT_CLR = GPIOA_INT_STAT & 0x20;
323
324 /* enable interrupts */
325 GPIOA_INT_EN = 0x20;
326
327 /* unmask interrupt */ 283 /* unmask interrupt */
328 CPU_INT_EN = 0x40000000; 284 CPU_INT_EN = HI_MASK;
329 CPU_HI_INT_EN = I2C_MASK; 285 CPU_HI_INT_EN = I2C_MASK;
330} 286}
331 287
@@ -342,7 +298,20 @@ int button_read_device(void)
342 hold_button = button_hold(); 298 hold_button = button_hold();
343 299
344 if (hold_button != hold_button_old) 300 if (hold_button != hold_button_old)
301 {
345 backlight_hold_changed(hold_button); 302 backlight_hold_changed(hold_button);
303
304 if (hold_button)
305 {
306 /* lock -> disable wheel sensor */
307 DEV_EN &= ~DEV_OPTO;
308 }
309 else
310 {
311 /* unlock -> enable wheel sensor */
312 DEV_EN |= DEV_OPTO;
313 }
314 }
346 315
347 /* The int_btn variable is set in the button interrupt handler */ 316 /* The int_btn variable is set in the button interrupt handler */
348 return int_btn; 317 return int_btn;