Configure Gigabeat S with EABI compiler by default. Implement the INIT section that...
[kugel-rb.git] / firmware / target / arm / imx31 / gigabeat-s / headphone-gigabeat-s.c
blob0f8cb67a9df9e3d3b831eb63c4af18938fd1c612
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (c) 2009 by Michael Sevakis
12 * Driver to handle headphone jack events
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
22 ****************************************************************************/
23 #include "config.h"
24 #include "system.h"
25 #include "kernel.h"
26 #include "thread.h"
27 #include "mc13783.h"
28 #include "mc13783-target.h"
29 #include "adc.h"
30 #include "button.h"
32 static struct wakeup headphone_wakeup;
33 static unsigned int headphone_thread_id;
34 static int headphone_stack[200/sizeof(int)]; /* Not much stack needed */
35 static const char * const headphone_thread_name = "headphone";
36 static bool headphones_detect = false;
38 /* Convert ADC reading into a button value. */
39 static int adc_data_to_button(unsigned int data)
41 int btn = BUTTON_NONE;
43 if (data < 505)
45 if (data < 252)
47 if (data < 149)
49 if (data >= 64)
51 /* Play/Pause */
52 btn = BUTTON_RC_PLAY;
54 /* else headphone direct */
56 else
58 /* DSP */
59 btn = BUTTON_RC_DSP;
62 else
64 if (data < 370)
66 /* RW */
67 btn = BUTTON_RC_REW;
69 else
71 /* FF */
72 btn = BUTTON_RC_FF;
76 else
78 if (data < 870)
80 if (data < 675)
82 /* Vol + */
83 btn = BUTTON_RC_VOL_UP;
85 else
87 /* Vol - */
88 btn = BUTTON_RC_VOL_DOWN;
91 #if 0
92 else
95 if (data < 951)
97 /* No buttons */
99 else
101 /* Not inserted */
105 #endif
108 return btn;
111 static void headphone_thread(void)
113 int headphone_sleep_countdown = 0;
114 int headphone_wait_timeout = TIMEOUT_BLOCK;
116 while (1)
118 int rc = wakeup_wait(&headphone_wakeup, headphone_wait_timeout);
119 unsigned int data = adc_read(ADC_HPREMOTE);
121 if (rc == OBJ_WAIT_TIMEDOUT)
123 if (headphone_sleep_countdown <= 0)
125 /* Polling ADC */
126 int btn, btn2;
128 btn = adc_data_to_button(data);
129 sleep(HZ/50);
130 data = adc_read(ADC_HPREMOTE);
131 btn2 = adc_data_to_button(data);
133 if (btn != btn2)
135 /* If the buttons dont agree twice in a row, then it's
136 * none (from meg-fx remote reader). */
137 btn = BUTTON_NONE;
140 button_headphone_set(btn);
141 continue;
144 if (--headphone_sleep_countdown == 0)
146 /* Nothing has changed and remote is not present -
147 * go to sleep. */
148 headphone_wait_timeout = TIMEOUT_BLOCK;
149 continue;
153 headphones_detect = data <= 951; /* Max remote value */
155 /* Cancel any buttons if jack readings are unstable. */
156 button_headphone_set(BUTTON_NONE);
158 if (data >= 64 && data <= 951)
160 /* Should be a remote control - accelerate */
161 headphone_wait_timeout = HZ/20-HZ/50;
162 headphone_sleep_countdown = 0;
164 else if (rc == OBJ_WAIT_SUCCEEDED)
166 /* Got signaled - something is being plugged/unplugged. Set
167 * countdown until we just give up and go to sleep (~10s). */
168 headphone_wait_timeout = HZ/2;
169 headphone_sleep_countdown = 10*2;
174 /* This is called from the mc13783 interrupt thread */
175 void headphone_detect_event(void)
177 /* Trigger the thread immediately. */
178 wakeup_signal(&headphone_wakeup);
181 /* Tell if anything is in the jack. */
182 bool headphones_inserted(void)
184 return headphones_detect;
187 void INIT_ATTR headphone_init(void)
189 /* A thread is required to monitor the remote ADC and jack state. */
190 wakeup_init(&headphone_wakeup);
191 headphone_thread_id = create_thread(headphone_thread,
192 headphone_stack,
193 sizeof(headphone_stack),
194 0, headphone_thread_name
195 IF_PRIO(, PRIORITY_REALTIME)
196 IF_COP(, CPU));
198 /* Initially poll and then enable PMIC event */
199 headphone_detect_event();
200 mc13783_enable_event(MC13783_ONOFD2_EVENT);