Gigabeat S: Add remote control reading and proper headphone insert detection. We need keymaps! A few were copied straight from Gigabeat F/X just to get things worked out.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19830 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2009-01-23 20:55:17 +00:00
parent 34314b1993
commit 753b7a90e1
6 changed files with 290 additions and 23 deletions

View file

@ -32,9 +32,6 @@
/* Most code in here is taken from the Linux BSP provided by Freescale
* Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. */
#ifdef HAVE_HEADPHONE_DETECTION
static bool headphones_detect = false;
#endif
static uint32_t int_btn = BUTTON_NONE;
static bool hold_button = false;
#ifdef BOOTLOADER
@ -123,6 +120,16 @@ bool button_hold(void)
return _button_hold();
}
#ifdef HAVE_HEADPHONE_DETECTION
/* Headphone driver pushes the data here */
void button_headphone_set(int button)
{
int oldstatus = disable_irq_save();
int_btn = (int_btn & ~BUTTON_REMOTE) | button;
restore_irq(oldstatus);
}
#endif
int button_read_device(void)
{
/* Simple poll of GPIO status */
@ -168,21 +175,6 @@ void button_power_event(void)
restore_irq(oldlevel);
}
#ifdef HAVE_HEADPHONE_DETECTION
/* This is called from the mc13783 interrupt thread */
void headphone_detect_event(void)
{
/* FIXME: Not really the correct method */
headphones_detect =
(mc13783_read(MC13783_INTERRUPT_SENSE1) & MC13783_ONOFD2S) == 0;
}
bool headphones_inserted(void)
{
return headphones_detect;
}
#endif /* HAVE_HEADPHONE_DETECTION */
void button_init_device(void)
{
#ifdef BOOTLOADER
@ -223,8 +215,7 @@ void button_init_device(void)
mc13783_enable_event(MC13783_ONOFD1_EVENT);
#ifdef HAVE_HEADPHONE_DETECTION
headphone_detect_event();
mc13783_enable_event(MC13783_ONOFD2_EVENT);
headphone_init();
#endif
}

View file

@ -37,6 +37,8 @@ int button_read_device(void);
void button_power_event(void);
void headphone_detect_event(void);
bool headphones_inserted(void);
void headphone_init(void);
void button_headphone_set(int button);
/* Toshiba Gigabeat S-specific button codes */
@ -55,9 +57,17 @@ bool headphones_inserted(void);
#define BUTTON_NEXT (1 << 11)
#define BUTTON_POWER (1 << 12) /* Read from PMIC */
#define BUTTON_MAIN (0x1fff)
#define BUTTON_MAIN (0x00001fff)
#define BUTTON_REMOTE 0
/* Remote control buttons */
#define BUTTON_RC_VOL_UP (1 << 13)
#define BUTTON_RC_VOL_DOWN (1 << 14)
#define BUTTON_RC_FF (1 << 15)
#define BUTTON_RC_REW (1 << 16)
#define BUTTON_RC_PLAY (1 << 17)
#define BUTTON_RC_DSP (1 << 18)
#define BUTTON_REMOTE (0x0007e000)
#define POWEROFF_BUTTON BUTTON_POWER
#define POWEROFF_COUNT 10

View file

@ -0,0 +1,201 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (c) 2009 by Michael Sevakis
*
* Driver to handle headphone jack events
*
* 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.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include "kernel.h"
#include "thread.h"
#include "mc13783.h"
#include "mc13783-target.h"
#include "adc.h"
#include "button.h"
static struct wakeup headphone_wakeup;
static unsigned int headphone_thread_id;
static int headphone_stack[160/sizeof(int)]; /* Not much stack needed */
static const char * const headphone_thread_name = "headphone";
static bool headphones_detect = false;
/* Convert ADC reading into a button value. */
static int adc_data_to_button(unsigned int data)
{
int btn = BUTTON_NONE;
if (data < 505)
{
if (data < 252)
{
if (data < 149)
{
if (data >= 64)
{
/* Play/Pause */
btn = BUTTON_RC_PLAY;
}
/* else headphone direct */
}
else
{
/* DSP */
btn = BUTTON_RC_DSP;
}
}
else
{
if (data < 370)
{
/* RW */
btn = BUTTON_RC_REW;
}
else
{
/* FF */
btn = BUTTON_RC_FF;
}
}
}
else
{
if (data < 870)
{
if (data < 675)
{
/* Vol + */
btn = BUTTON_RC_VOL_UP;
}
else
{
/* Vol - */
btn = BUTTON_RC_VOL_DOWN;
}
}
#if 0
else
{
if (data < 951)
{
/* No buttons */
}
else
{
/* Not inserted */
}
}
#endif
}
return btn;
}
static void headphone_thread(void)
{
int headphone_sleep_countdown = 0;
int headphone_wait_timeout = TIMEOUT_BLOCK;
while (1)
{
int rc = wakeup_wait(&headphone_wakeup, headphone_wait_timeout);
unsigned int data = adc_read(ADC_HPREMOTE);
if (rc == OBJ_WAIT_TIMEDOUT)
{
if (headphone_sleep_countdown <= 0)
{
/* Polling ADC */
int btn, btn2;
btn = adc_data_to_button(data);
sleep(HZ/50);
data = adc_read(ADC_HPREMOTE);
btn2 = adc_data_to_button(data);
if (btn != btn2)
{
/* If the buttons dont agree twice in a row, then it's
* none (from meg-fx remote reader). */
btn = BUTTON_NONE;
}
button_headphone_set(btn);
continue;
}
if (--headphone_sleep_countdown == 0)
{
/* Nothing has changed and remote is not present -
* go to sleep. */
headphone_wait_timeout = TIMEOUT_BLOCK;
continue;
}
}
headphones_detect = data <= 951; /* Max remote value */
/* Cancel any buttons if jack readings are unstable. */
button_headphone_set(BUTTON_NONE);
if (data >= 64 && data <= 951)
{
/* Should be a remote control - accelerate */
headphone_wait_timeout = HZ/20-HZ/50;
headphone_sleep_countdown = 0;
}
else if (rc == OBJ_WAIT_SUCCEEDED)
{
/* Got signaled - something is being plugged/unplugged. Set
* countdown until we just give up and go to sleep (~10s). */
headphone_wait_timeout = HZ/2;
headphone_sleep_countdown = 10*2;
}
}
}
/* This is called from the mc13783 interrupt thread */
void headphone_detect_event(void)
{
/* Trigger the thread immediately. */
wakeup_signal(&headphone_wakeup);
}
/* Tell if anything is in the jack. */
bool headphones_inserted(void)
{
return headphones_detect;
}
void headphone_init(void)
{
/* A thread is required to monitor the remote ADC and jack state. */
wakeup_init(&headphone_wakeup);
headphone_thread_id = create_thread(headphone_thread,
headphone_stack,
sizeof(headphone_stack),
0, headphone_thread_name
IF_PRIO(, PRIORITY_REALTIME)
IF_COP(, CPU));
/* Initially poll and then enable PMIC event */
headphone_detect_event();
mc13783_enable_event(MC13783_ONOFD2_EVENT);
}