2006-10-05 10:58:51 +00:00
|
|
|
/***************************************************************************
|
|
|
|
* __________ __ ___.
|
|
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
|
|
* \/ \/ \/ \/ \/
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Copyright (C) 2002 by Daniel Stenberg
|
|
|
|
*
|
|
|
|
* iPod driver based on code from the ipodlinux project - http://ipodlinux.org
|
|
|
|
* Adapted for Rockbox in December 2005
|
|
|
|
* Original file: linux/arch/armnommu/mach-ipod/keyboard.c
|
|
|
|
* Copyright (c) 2003-2005 Bernard Leach (leachbj@bouncycastle.org)
|
|
|
|
*
|
|
|
|
*
|
2008-06-28 18:10:04 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2006-10-05 10:58:51 +00:00
|
|
|
*
|
|
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
|
|
* KIND, either express or implied.
|
|
|
|
*
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Rockbox button functions
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "config.h"
|
|
|
|
#include "cpu.h"
|
|
|
|
#include "system.h"
|
|
|
|
#include "button.h"
|
|
|
|
#include "kernel.h"
|
|
|
|
#include "backlight.h"
|
|
|
|
#include "serial.h"
|
|
|
|
#include "power.h"
|
|
|
|
#include "powermgmt.h"
|
2012-03-20 22:26:11 +00:00
|
|
|
#ifdef IPOD_NANO2G
|
2010-09-25 21:41:10 +00:00
|
|
|
#include "pmu-target.h"
|
|
|
|
#endif
|
2006-10-05 10:58:51 +00:00
|
|
|
|
2007-11-19 11:05:54 +00:00
|
|
|
#define WHEEL_FAST_OFF_TIMEOUT 250000 /* timeout for acceleration = 250ms */
|
|
|
|
#define WHEEL_REPEAT_TIMEOUT 250000 /* timeout for button repeat = 250ms */
|
2009-09-17 08:24:59 +00:00
|
|
|
#define WHEEL_UNTOUCH_TIMEOUT 150000 /* timeout for untouching wheel = 150ms */
|
2009-10-02 23:04:30 +00:00
|
|
|
|
|
|
|
#ifdef CPU_PP
|
|
|
|
#define CLICKWHEEL_DATA (*(volatile unsigned long*)(0x7000c140))
|
2010-12-12 00:52:02 +00:00
|
|
|
#elif CONFIG_CPU==S5L8701 || CONFIG_CPU==S5L8702
|
|
|
|
#define CLICKWHEEL_DATA WHEELRX
|
2009-10-02 23:04:30 +00:00
|
|
|
#else
|
|
|
|
#error CPU architecture not supported!
|
|
|
|
#endif
|
|
|
|
|
2007-11-19 11:05:54 +00:00
|
|
|
#define WHEELCLICKS_PER_ROTATION 96 /* wheelclicks per full rotation */
|
|
|
|
|
|
|
|
/* This amount of clicks is needed for at least scrolling 1 item. Choose small values
|
|
|
|
* to have high sensitivity but few precision, choose large values to have less
|
|
|
|
* sensitivity and good precision. */
|
2009-10-02 23:04:30 +00:00
|
|
|
#if defined(IPOD_NANO) || defined(IPOD_NANO2G)
|
2007-11-19 11:05:54 +00:00
|
|
|
#define WHEEL_SENSITIVITY 6 /* iPod nano has smaller wheel, lower sensitivity needed */
|
|
|
|
#else
|
|
|
|
#define WHEEL_SENSITIVITY 4 /* default sensitivity */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int old_wheel_value = -1;
|
|
|
|
int new_wheel_value = 0;
|
2011-11-03 23:32:49 +00:00
|
|
|
static int repeat = 0;
|
2007-11-19 11:05:54 +00:00
|
|
|
int wheel_delta = 0;
|
|
|
|
bool wheel_is_touched = false;
|
|
|
|
unsigned int accumulated_wheel_delta = 0;
|
2011-11-03 23:32:49 +00:00
|
|
|
static unsigned int wheel_repeat = 0;
|
2007-11-19 11:05:54 +00:00
|
|
|
unsigned int wheel_velocity = 0;
|
2011-11-03 23:32:49 +00:00
|
|
|
static unsigned long last_wheel_usec = 0;
|
2007-11-19 11:05:54 +00:00
|
|
|
|
2006-10-05 10:58:51 +00:00
|
|
|
/* Variable to use for setting button status in interrupt handler */
|
2011-11-03 23:32:49 +00:00
|
|
|
static int int_btn = BUTTON_NONE;
|
2006-10-05 10:58:51 +00:00
|
|
|
#ifdef HAVE_WHEEL_POSITION
|
|
|
|
static int wheel_position = -1;
|
|
|
|
static bool send_events = true;
|
|
|
|
#endif
|
|
|
|
|
2010-12-12 00:52:02 +00:00
|
|
|
#if CONFIG_CPU==S5L8701 || CONFIG_CPU==S5L8702
|
2011-03-02 08:49:38 +00:00
|
|
|
static struct semaphore button_init_wakeup;
|
2010-10-10 20:52:46 +00:00
|
|
|
#endif
|
|
|
|
|
2009-10-02 23:04:30 +00:00
|
|
|
#ifdef CPU_PP
|
2006-10-05 10:58:51 +00:00
|
|
|
static void opto_i2c_init(void)
|
|
|
|
{
|
2008-02-10 05:39:20 +00:00
|
|
|
DEV_EN |= DEV_OPTO;
|
|
|
|
DEV_RS |= DEV_OPTO;
|
2006-10-05 10:58:51 +00:00
|
|
|
udelay(5);
|
2008-02-10 05:39:20 +00:00
|
|
|
DEV_RS &= ~DEV_OPTO; /* finish reset */
|
|
|
|
DEV_INIT1 |= INIT_BUTTONS; /* enable buttons (needed for "hold"-detection) */
|
2006-10-05 10:58:51 +00:00
|
|
|
|
|
|
|
outl(0xc00a1f00, 0x7000c100);
|
2008-02-10 05:39:20 +00:00
|
|
|
outl(0x01000000, 0x7000c104);
|
2006-10-05 10:58:51 +00:00
|
|
|
}
|
2009-10-02 23:04:30 +00:00
|
|
|
#endif
|
2006-10-05 10:58:51 +00:00
|
|
|
|
|
|
|
static inline int ipod_4g_button_read(void)
|
|
|
|
{
|
|
|
|
int whl = -1;
|
2008-02-10 05:39:20 +00:00
|
|
|
int btn = BUTTON_NONE;
|
2006-10-05 10:58:51 +00:00
|
|
|
|
2009-10-02 23:04:30 +00:00
|
|
|
#ifdef CPU_PP
|
2008-02-10 05:39:20 +00:00
|
|
|
if ((inl(0x7000c104) & 0x04000000) != 0)
|
2007-11-19 11:05:54 +00:00
|
|
|
{
|
2009-10-02 23:04:30 +00:00
|
|
|
#endif
|
|
|
|
unsigned status = CLICKWHEEL_DATA;
|
2006-10-05 10:58:51 +00:00
|
|
|
|
2007-11-19 11:05:54 +00:00
|
|
|
if ((status & 0x800000ff) == 0x8000001a)
|
|
|
|
{
|
2008-02-10 05:39:20 +00:00
|
|
|
if (status & 0x00000100)
|
2006-10-05 10:58:51 +00:00
|
|
|
btn |= BUTTON_SELECT;
|
2008-02-10 05:39:20 +00:00
|
|
|
if (status & 0x00000200)
|
2006-10-05 10:58:51 +00:00
|
|
|
btn |= BUTTON_RIGHT;
|
2008-02-10 05:39:20 +00:00
|
|
|
if (status & 0x00000400)
|
2006-10-05 10:58:51 +00:00
|
|
|
btn |= BUTTON_LEFT;
|
2008-02-10 05:39:20 +00:00
|
|
|
if (status & 0x00000800)
|
2006-10-05 10:58:51 +00:00
|
|
|
btn |= BUTTON_PLAY;
|
2008-02-10 05:39:20 +00:00
|
|
|
if (status & 0x00001000)
|
2006-10-05 10:58:51 +00:00
|
|
|
btn |= BUTTON_MENU;
|
2007-11-19 11:05:54 +00:00
|
|
|
if (status & 0x40000000)
|
|
|
|
{
|
|
|
|
unsigned long usec = USEC_TIMER;
|
|
|
|
|
|
|
|
/* Highest wheel = 0x5F, clockwise increases */
|
|
|
|
new_wheel_value = (status >> 16) & 0x7f;
|
2006-10-05 10:58:51 +00:00
|
|
|
whl = new_wheel_value;
|
2007-11-19 11:05:54 +00:00
|
|
|
|
|
|
|
/* switch on backlight (again), reset power-off timer */
|
2006-10-05 10:58:51 +00:00
|
|
|
backlight_on();
|
2007-01-18 22:10:29 +00:00
|
|
|
reset_poweroff_timer();
|
2007-11-19 11:05:54 +00:00
|
|
|
|
|
|
|
/* Check whether the scrollwheel was untouched by accident or by will. */
|
|
|
|
/* This is needed because wheel may be untoched very shortly during rotation */
|
|
|
|
if ( (!wheel_is_touched) && TIME_AFTER(usec, last_wheel_usec + WHEEL_UNTOUCH_TIMEOUT) )
|
|
|
|
{
|
|
|
|
/* wheel has been really untouched -> reset internal variables */
|
|
|
|
old_wheel_value = -1;
|
|
|
|
wheel_velocity = 0;
|
|
|
|
accumulated_wheel_delta = 0;
|
|
|
|
wheel_repeat = BUTTON_NONE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* wheel was shortly untouched by accident -> leave internal variables */
|
|
|
|
wheel_is_touched = true;
|
|
|
|
}
|
2006-10-05 10:58:51 +00:00
|
|
|
|
2007-11-19 11:05:54 +00:00
|
|
|
if (old_wheel_value >= 0)
|
|
|
|
{
|
2006-10-05 10:58:51 +00:00
|
|
|
/* This is for later = BUTTON_SCROLL_TOUCH;*/
|
2007-11-19 11:05:54 +00:00
|
|
|
wheel_delta = new_wheel_value - old_wheel_value;
|
|
|
|
unsigned int wheel_keycode = BUTTON_NONE;
|
|
|
|
|
|
|
|
/* Taking into account wrapping during transition from highest
|
|
|
|
* to lowest wheel position and back */
|
|
|
|
if (wheel_delta < -WHEELCLICKS_PER_ROTATION/2)
|
|
|
|
wheel_delta += WHEELCLICKS_PER_ROTATION; /* Forward wrapping case */
|
|
|
|
else if (wheel_delta > WHEELCLICKS_PER_ROTATION/2)
|
|
|
|
wheel_delta -= WHEELCLICKS_PER_ROTATION; /* Backward wrapping case */
|
|
|
|
|
|
|
|
/* Getting direction and wheel_keycode from wheel_delta.
|
|
|
|
* Need at least some clicks to be sure to avoid haptic fuzziness */
|
|
|
|
if (wheel_delta >= WHEEL_SENSITIVITY)
|
2006-10-05 10:58:51 +00:00
|
|
|
wheel_keycode = BUTTON_SCROLL_FWD;
|
2007-11-19 11:05:54 +00:00
|
|
|
else if (wheel_delta <= -WHEEL_SENSITIVITY)
|
2006-10-05 10:58:51 +00:00
|
|
|
wheel_keycode = BUTTON_SCROLL_BACK;
|
2007-11-19 11:05:54 +00:00
|
|
|
else
|
|
|
|
wheel_keycode = BUTTON_NONE;
|
|
|
|
|
|
|
|
if (wheel_keycode != BUTTON_NONE)
|
|
|
|
{
|
|
|
|
long v = (usec - last_wheel_usec) & 0x7fffffff;
|
|
|
|
|
|
|
|
/* undo signedness */
|
|
|
|
wheel_delta = (wheel_delta>0) ? wheel_delta : -wheel_delta;
|
|
|
|
|
|
|
|
/* add the current wheel_delta */
|
|
|
|
accumulated_wheel_delta += wheel_delta;
|
|
|
|
|
|
|
|
v = v ? (1000000 * wheel_delta) / v : 0; /* clicks/sec = 1000000 * clicks/usec */
|
|
|
|
v = (v * 360) / WHEELCLICKS_PER_ROTATION; /* conversion to degree/sec */
|
|
|
|
v = (v<0) ? -v : v; /* undo signedness */
|
|
|
|
|
|
|
|
/* some velocity filtering to smooth things out */
|
2010-03-06 15:53:45 +00:00
|
|
|
wheel_velocity = (15 * wheel_velocity + v) / 16;
|
2007-11-19 11:05:54 +00:00
|
|
|
/* limit to 24 bit */
|
|
|
|
wheel_velocity = (wheel_velocity>0xffffff) ? 0xffffff : wheel_velocity;
|
|
|
|
|
|
|
|
/* assume REPEAT = off */
|
|
|
|
repeat = 0;
|
|
|
|
|
|
|
|
/* direction reversals must nullify acceleration and accumulator */
|
|
|
|
if (wheel_keycode != wheel_repeat)
|
|
|
|
{
|
|
|
|
wheel_repeat = wheel_keycode;
|
|
|
|
wheel_velocity = 0;
|
|
|
|
accumulated_wheel_delta = 0;
|
|
|
|
}
|
|
|
|
/* on same direction REPEAT is assumed when new click is within timeout */
|
|
|
|
else if (TIME_BEFORE(usec, last_wheel_usec + WHEEL_REPEAT_TIMEOUT))
|
|
|
|
{
|
|
|
|
repeat = BUTTON_REPEAT;
|
|
|
|
}
|
|
|
|
/* timeout nullifies acceleration and accumulator */
|
|
|
|
if (TIME_AFTER(usec, last_wheel_usec + WHEEL_FAST_OFF_TIMEOUT))
|
|
|
|
{
|
|
|
|
wheel_velocity = 0;
|
|
|
|
accumulated_wheel_delta = 0;
|
|
|
|
}
|
2006-10-05 10:58:51 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_WHEEL_POSITION
|
2007-11-19 11:05:54 +00:00
|
|
|
if (send_events)
|
2006-10-05 10:58:51 +00:00
|
|
|
#endif
|
2007-11-19 11:05:54 +00:00
|
|
|
/* The queue should have no other events when scrolling */
|
|
|
|
if (queue_empty(&button_queue))
|
|
|
|
{
|
|
|
|
/* each WHEEL_SENSITIVITY clicks = scrolling 1 item */
|
|
|
|
accumulated_wheel_delta /= WHEEL_SENSITIVITY;
|
|
|
|
#ifdef HAVE_SCROLLWHEEL
|
|
|
|
/* use data-format for HAVE_SCROLLWHEEL */
|
|
|
|
/* always use acceleration mode (1<<31) */
|
|
|
|
/* always set message post count to (1<<24) for iPod */
|
|
|
|
/* this way the scrolling is always calculated from wheel_velocity */
|
|
|
|
queue_post(&button_queue, wheel_keycode | repeat,
|
|
|
|
(1<<31) | (1 << 24) | wheel_velocity);
|
|
|
|
|
|
|
|
#else
|
|
|
|
queue_post(&button_queue, wheel_keycode | repeat,
|
|
|
|
(accumulated_wheel_delta << 16) | new_wheel_value);
|
|
|
|
#endif
|
|
|
|
accumulated_wheel_delta = 0;
|
|
|
|
}
|
|
|
|
last_wheel_usec = usec;
|
|
|
|
old_wheel_value = new_wheel_value;
|
2006-10-05 10:58:51 +00:00
|
|
|
}
|
|
|
|
}
|
2007-11-19 11:05:54 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* scrollwheel was touched for the first time after finger lifting */
|
|
|
|
old_wheel_value = new_wheel_value;
|
|
|
|
wheel_is_touched = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* In this case the finger was lifted from the scrollwheel. */
|
|
|
|
wheel_is_touched = false;
|
2006-10-05 10:58:51 +00:00
|
|
|
}
|
|
|
|
|
2007-11-19 11:05:54 +00:00
|
|
|
}
|
2010-12-12 00:52:02 +00:00
|
|
|
#if CONFIG_CPU==S5L8701 || CONFIG_CPU==S5L8702
|
2010-10-10 20:52:46 +00:00
|
|
|
else if ((status & 0x8000FFFF) == 0x8000023A)
|
|
|
|
{
|
|
|
|
if (status & 0x00010000)
|
|
|
|
btn |= BUTTON_SELECT;
|
|
|
|
if (status & 0x00020000)
|
|
|
|
btn |= BUTTON_RIGHT;
|
|
|
|
if (status & 0x00040000)
|
|
|
|
btn |= BUTTON_LEFT;
|
|
|
|
if (status & 0x00080000)
|
|
|
|
btn |= BUTTON_PLAY;
|
|
|
|
if (status & 0x00100000)
|
|
|
|
btn |= BUTTON_MENU;
|
2011-03-02 08:49:38 +00:00
|
|
|
semaphore_release(&button_init_wakeup);
|
2010-10-10 20:52:46 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-10-02 23:04:30 +00:00
|
|
|
#ifdef CPU_PP
|
2006-10-05 10:58:51 +00:00
|
|
|
}
|
2009-10-02 23:04:30 +00:00
|
|
|
#endif
|
2006-10-05 10:58:51 +00:00
|
|
|
|
2007-11-19 11:05:54 +00:00
|
|
|
#ifdef HAVE_WHEEL_POSITION
|
2008-02-10 05:39:20 +00:00
|
|
|
/* Save the new absolute wheel position */
|
2006-10-05 10:58:51 +00:00
|
|
|
wheel_position = whl;
|
2007-11-19 11:05:54 +00:00
|
|
|
#endif
|
2006-10-05 10:58:51 +00:00
|
|
|
return btn;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_WHEEL_POSITION
|
|
|
|
int wheel_status(void)
|
|
|
|
{
|
|
|
|
return wheel_position;
|
|
|
|
}
|
|
|
|
|
|
|
|
void wheel_send_events(bool send)
|
|
|
|
{
|
|
|
|
send_events = send;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-10-02 23:04:30 +00:00
|
|
|
#ifdef CPU_PP
|
2006-10-05 10:58:51 +00:00
|
|
|
void ipod_4g_button_int(void)
|
|
|
|
{
|
2008-06-03 05:19:32 +00:00
|
|
|
CPU_HI_INT_DIS = I2C_MASK;
|
2008-02-10 05:39:20 +00:00
|
|
|
|
2009-10-02 23:04:30 +00:00
|
|
|
/* The following delay was 250 in the ipodlinux source, but 50 seems to
|
|
|
|
work fine - tested on Nano, Color/Photo and Video. */
|
|
|
|
udelay(50);
|
|
|
|
|
2006-10-05 10:58:51 +00:00
|
|
|
int_btn = ipod_4g_button_read();
|
2008-02-10 05:39:20 +00:00
|
|
|
|
|
|
|
outl(inl(0x7000c104) | 0x0c000000, 0x7000c104);
|
2006-10-05 10:58:51 +00:00
|
|
|
outl(0x400a1f00, 0x7000c100);
|
|
|
|
|
|
|
|
CPU_HI_INT_EN = I2C_MASK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void button_init_device(void)
|
|
|
|
{
|
|
|
|
opto_i2c_init();
|
2007-11-19 11:05:54 +00:00
|
|
|
|
2006-10-05 10:58:51 +00:00
|
|
|
/* hold button - enable as input */
|
|
|
|
GPIOA_ENABLE |= 0x20;
|
|
|
|
GPIOA_OUTPUT_EN &= ~0x20;
|
2007-11-19 11:05:54 +00:00
|
|
|
|
2006-10-05 10:58:51 +00:00
|
|
|
/* unmask interrupt */
|
2008-02-10 05:39:20 +00:00
|
|
|
CPU_INT_EN = HI_MASK;
|
2006-10-05 10:58:51 +00:00
|
|
|
CPU_HI_INT_EN = I2C_MASK;
|
|
|
|
}
|
|
|
|
|
2009-10-02 23:04:30 +00:00
|
|
|
bool button_hold(void)
|
|
|
|
{
|
|
|
|
return (GPIOA_INPUT_VAL & 0x20)?false:true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool headphones_inserted(void)
|
|
|
|
{
|
|
|
|
return (GPIOA_INPUT_VAL & 0x80)?true:false;
|
|
|
|
}
|
|
|
|
#else
|
2010-12-12 12:40:37 +00:00
|
|
|
void INT_WHEEL(void)
|
2009-10-02 23:04:30 +00:00
|
|
|
{
|
2010-10-10 20:52:46 +00:00
|
|
|
int clickwheel_events = WHEELINT;
|
2009-10-02 23:04:30 +00:00
|
|
|
|
|
|
|
/* Clear interrupts */
|
2010-10-10 20:52:46 +00:00
|
|
|
if (clickwheel_events & 4) WHEELINT = 4;
|
|
|
|
if (clickwheel_events & 2) WHEELINT = 2;
|
|
|
|
if (clickwheel_events & 1) WHEELINT = 1;
|
2009-10-02 23:04:30 +00:00
|
|
|
|
|
|
|
int_btn = ipod_4g_button_read();
|
|
|
|
}
|
|
|
|
|
2011-04-22 21:39:17 +00:00
|
|
|
static void s5l_clickwheel_init(void)
|
2010-10-10 20:52:46 +00:00
|
|
|
{
|
2010-12-12 00:52:02 +00:00
|
|
|
#if CONFIG_CPU==S5L8701
|
2010-10-10 20:52:46 +00:00
|
|
|
PWRCONEXT &= ~1;
|
|
|
|
PCON15 = (PCON15 & ~0xFFFF0000) | 0x22220000;
|
|
|
|
PUNK15 = 0xF0;
|
|
|
|
WHEEL08 = 0x3A980;
|
|
|
|
WHEEL00 = 0x280000;
|
|
|
|
WHEEL10 = 3;
|
|
|
|
PCON10 = (PCON10 & ~0xFF0) | 0x10;
|
|
|
|
PDAT10 |= 2;
|
|
|
|
WHEELTX = 0x8000023A;
|
|
|
|
WHEEL04 |= 1;
|
|
|
|
PDAT10 &= ~2;
|
2010-12-12 00:52:02 +00:00
|
|
|
#elif CONFIG_CPU==S5L8702
|
2012-03-20 22:53:38 +00:00
|
|
|
/* enable and init internal (s5l8702) wheel controller */
|
|
|
|
PWRCON(1) &= ~(1 << 1);
|
2014-08-28 19:15:29 +00:00
|
|
|
PCON(14) = (PCON(14) & ~0xffff0000) | 0x22220000;
|
2012-03-20 22:53:38 +00:00
|
|
|
WHEELINT = 7;
|
|
|
|
WHEEL10 = 1;
|
|
|
|
WHEEL00 = 0x380000;
|
|
|
|
WHEEL08 = 0x20000;
|
|
|
|
WHEELTX = 0x8000023A;
|
|
|
|
WHEEL04 |= 1;
|
2010-12-12 00:52:02 +00:00
|
|
|
#endif
|
2010-10-10 20:52:46 +00:00
|
|
|
}
|
|
|
|
|
2009-10-02 23:04:30 +00:00
|
|
|
void button_init_device(void)
|
|
|
|
{
|
2011-03-02 08:49:38 +00:00
|
|
|
semaphore_init(&button_init_wakeup, 1, 0);
|
2010-12-12 00:52:02 +00:00
|
|
|
#if CONFIG_CPU==S5L8701
|
2009-10-02 23:04:30 +00:00
|
|
|
INTMSK |= (1<<26);
|
2010-12-12 00:52:02 +00:00
|
|
|
#elif CONFIG_CPU==S5L8702
|
2012-03-20 22:26:11 +00:00
|
|
|
/* configure GPIO E2 as pull-up input */
|
|
|
|
PUNB(14) |= (1 << 2);
|
2010-12-12 00:52:02 +00:00
|
|
|
#endif
|
2010-10-10 20:52:46 +00:00
|
|
|
s5l_clickwheel_init();
|
2011-03-02 08:49:38 +00:00
|
|
|
semaphore_wait(&button_init_wakeup, HZ / 10);
|
2009-10-02 23:04:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool button_hold(void)
|
|
|
|
{
|
2010-12-12 11:41:50 +00:00
|
|
|
#if CONFIG_CPU==S5L8701
|
2011-02-10 10:10:27 +00:00
|
|
|
bool value = (PDAT14 & (1 << 6)) == 0;
|
|
|
|
if (value)
|
2011-02-10 19:13:30 +00:00
|
|
|
PCON15 = PCON15 & ~0xffff0000;
|
2011-02-10 10:22:44 +00:00
|
|
|
else PCON15 = (PCON15 & ~0xffff0000) | 0x22220000;
|
2011-02-10 10:10:27 +00:00
|
|
|
return value;
|
2010-12-12 11:41:50 +00:00
|
|
|
#elif CONFIG_CPU==S5L8702
|
2012-03-20 22:26:11 +00:00
|
|
|
return ((PDATE & (1 << 2)) == 0);
|
2010-12-12 11:41:50 +00:00
|
|
|
#endif
|
2009-10-02 23:04:30 +00:00
|
|
|
}
|
2009-10-10 15:37:05 +00:00
|
|
|
|
|
|
|
bool headphones_inserted(void)
|
|
|
|
{
|
2010-12-12 11:41:50 +00:00
|
|
|
#if CONFIG_CPU==S5L8701
|
2010-12-16 19:54:24 +00:00
|
|
|
return ((PDAT14 & (1 << 5)) != 0);
|
2010-12-12 11:41:50 +00:00
|
|
|
#elif CONFIG_CPU==S5L8702
|
2011-01-07 23:08:01 +00:00
|
|
|
return ((PDATA & (1 << 6)) != 0);
|
2010-12-12 11:41:50 +00:00
|
|
|
#endif
|
2009-10-10 15:37:05 +00:00
|
|
|
}
|
2009-10-02 23:04:30 +00:00
|
|
|
#endif
|
|
|
|
|
2006-10-05 10:58:51 +00:00
|
|
|
/*
|
|
|
|
* Get button pressed from hardware
|
|
|
|
*/
|
|
|
|
int button_read_device(void)
|
|
|
|
{
|
|
|
|
static bool hold_button = false;
|
|
|
|
bool hold_button_old;
|
|
|
|
|
|
|
|
/* normal buttons */
|
|
|
|
hold_button_old = hold_button;
|
|
|
|
hold_button = button_hold();
|
|
|
|
|
|
|
|
if (hold_button != hold_button_old)
|
2008-02-10 05:39:20 +00:00
|
|
|
{
|
2010-10-10 20:52:46 +00:00
|
|
|
#ifndef BOOTLOADER
|
2006-10-05 10:58:51 +00:00
|
|
|
backlight_hold_changed(hold_button);
|
2010-10-10 20:52:46 +00:00
|
|
|
#endif
|
2008-02-10 05:39:20 +00:00
|
|
|
|
|
|
|
if (hold_button)
|
|
|
|
{
|
2009-10-02 23:04:30 +00:00
|
|
|
#ifdef CPU_PP
|
2008-02-10 05:39:20 +00:00
|
|
|
/* lock -> disable wheel sensor */
|
|
|
|
DEV_EN &= ~DEV_OPTO;
|
2009-10-12 00:12:02 +00:00
|
|
|
#elif CONFIG_CPU==S5L8701
|
2010-09-25 21:41:10 +00:00
|
|
|
pmu_ldo_power_off(1); /* disable clickwheel power supply */
|
2010-10-10 20:52:46 +00:00
|
|
|
WHEEL00 = 0;
|
|
|
|
WHEEL10 = 0;
|
|
|
|
PWRCONEXT |= 1;
|
2010-12-12 00:52:02 +00:00
|
|
|
#elif CONFIG_CPU==S5L8702
|
2012-03-20 22:26:11 +00:00
|
|
|
/* disable external (CY8C21x34) wheel controller */
|
|
|
|
GPIOCMD = 0xe040e;
|
|
|
|
|
2012-03-20 22:53:38 +00:00
|
|
|
/* disable internal (s5l8702) wheel controller */
|
|
|
|
WHEEL00 = 0;
|
|
|
|
WHEEL10 = 0;
|
|
|
|
PWRCON(1) |= (1 << 1);
|
2009-10-02 23:04:30 +00:00
|
|
|
#endif
|
2008-02-10 05:39:20 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2009-10-02 23:04:30 +00:00
|
|
|
#ifdef CPU_PP
|
2008-02-10 05:39:20 +00:00
|
|
|
/* unlock -> enable wheel sensor */
|
|
|
|
DEV_EN |= DEV_OPTO;
|
2009-07-29 01:57:48 +00:00
|
|
|
opto_i2c_init();
|
2009-10-12 00:12:02 +00:00
|
|
|
#elif CONFIG_CPU==S5L8701
|
2010-09-25 21:41:10 +00:00
|
|
|
pmu_ldo_power_on(1); /* enable clickwheel power supply */
|
2010-10-10 20:52:46 +00:00
|
|
|
s5l_clickwheel_init();
|
2010-12-12 00:52:02 +00:00
|
|
|
#elif CONFIG_CPU==S5L8702
|
2012-03-20 22:26:11 +00:00
|
|
|
s5l_clickwheel_init();
|
2009-10-02 23:04:30 +00:00
|
|
|
#endif
|
2008-02-10 05:39:20 +00:00
|
|
|
}
|
|
|
|
}
|
2006-10-05 10:58:51 +00:00
|
|
|
|
|
|
|
/* The int_btn variable is set in the button interrupt handler */
|
2008-12-25 01:46:16 +00:00
|
|
|
#ifdef IPOD_ACCESSORY_PROTOCOL
|
|
|
|
return int_btn | remote_control_rx();
|
|
|
|
#else
|
2006-10-05 10:58:51 +00:00
|
|
|
return int_btn;
|
2008-12-25 01:46:16 +00:00
|
|
|
#endif
|
2006-10-05 10:58:51 +00:00
|
|
|
}
|