Commit e008466ba8da8924d3ffba519dfa4257e4f388f8

  • avatar
  • phhusson (Committer)
  • Wed Sep 08 20:32:56 CEST 2010
  • avatar
  • Oliver Welther <o.welther @g…x.de> (Author)
  • Thu Sep 02 12:26:43 CEST 2010
Blackstone: Added auto detection for 3.5mm audio jack
  
3939obj-$(CONFIG_MACH_HTCDIAMOND_CDMA) += board-htcdiamond.o board-htcraphael-navi.o board-htcraphael-panel.o htc_wifi_nvs.o mmc.o msm_vibrator.o msm-gpio-keys.o pmem.o htc_acoustic.o
4040
4141obj-$(CONFIG_MACH_HTCBLACKSTONE) += board-htcblackstone.o board-htcblackstone-panel.o htc_wifi_nvs.o mmc.o pmem.o
42obj-$(CONFIG_MACH_HTCBLACKSTONE) += msm_vibrator.o msm-gpio-keys.o htc_acoustic.o
42obj-$(CONFIG_MACH_HTCBLACKSTONE) += msm_vibrator.o msm-gpio-keys.o htc_acoustic.o htc_headset_mgr.o htc_headset_gpio.o
4343
4444obj-$(CONFIG_MACH_HTCKOVSKY) += board-htckovsky.o board-htckovsky-panel.o htc_wifi_nvs.o mmc.o pmem.o
4545obj-$(CONFIG_MACH_HTCKOVSKY) += msm_vibrator.o msm-gpio-keys.o htc_acoustic.o
  
4141#include <mach/msm_serial_hs.h>
4242#include <mach/vreg.h>
4343#include <mach/htc_battery.h>
44#include <mach/htc_headset_mgr.h>
45#include <mach/htc_headset_gpio.h>
4446
4547#include <mach/gpio.h>
4648#include <mach/io.h>
174174 .id = -1,
175175};
176176
177
178static struct htc_headset_mgr_platform_data htc_headset_mgr_data = {
179};
180
181static struct platform_device htc_headset_mgr = {
182 .name = "HTC_HEADSET_MGR",
183 .id = -1,
184 .dev = {
185 .platform_data = &htc_headset_mgr_data,
186 },
187};
188
189static struct htc_headset_gpio_platform_data htc_headset_gpio_data = {
190 .hpin_gpio = BLAC100_GPIO_HDS_DET,
191 .mic_detect_gpio = RAPH100_EXTMIC_IRQ,
192 .microp_channel = 1,
193 .key_enable_gpio = NULL,
194 .mic_select_gpio = NULL,
195};
196
197static struct platform_device htc_headset_gpio = {
198 .name = "HTC_HEADSET_GPIO",
199 .id = -1,
200 .dev = {
201 .platform_data = &htc_headset_gpio_data,
202 },
203};
204
205
177206static struct platform_device *devices[] __initdata = {
178207 &raphael_rfkill,
179208 &msm_device_smd,
216216#endif
217217 &msm_device_htc_battery,
218218 &blac_snd,
219 &htc_headset_mgr,
220 &htc_headset_gpio,
219221};
220222
221223extern struct sys_timer msm_timer;
  
9292
9393#define RAPH100_CAM1_RST 92
9494#define RAPH100_CAM2_RST 93
95#define RAPH100_NAVI_IRQ 94
95#define BLAC100_GPIO_HDS_DET 94
9696
9797#define RAPH100_LCD_VSYNC 97 /* FIXME! hardcoded */
9898#define RAPH100_LCD_PWR1 98
  
1/*
2 *
3 * /arch/arm/mach-msm/htc_headset_gpio.c
4 *
5 * HTC GPIO headset detection driver.
6 *
7 * Copyright (C) 2010 HTC, Inc.
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/sysdev.h>
22#include <linux/device.h>
23#include <linux/interrupt.h>
24#include <linux/irq.h>
25#include <linux/types.h>
26#include <linux/input.h>
27#include <linux/platform_device.h>
28#include <linux/errno.h>
29#include <linux/err.h>
30#include <linux/hrtimer.h>
31#include <linux/workqueue.h>
32#include <linux/wakelock.h>
33#include <linux/delay.h>
34#include <linux/gpio.h>
35
36#include <mach/htc_headset_mgr.h>
37#include <mach/htc_headset_gpio.h>
38
39#define DRIVER_NAME "HS_GPIO"
40
41/* #define DEBUG */
42
43#ifdef DEBUG
44#define AJ_DBG(fmt, arg...) \
45 printk(KERN_INFO "[Audio Jack] %s " fmt "\r\n", __func__, ## arg)
46#else
47#define AJ_DBG(fmt, arg...) do {} while (0)
48#endif
49
50struct audio_jack_info {
51 unsigned int irq_jack;
52 unsigned int irq_mic;
53 int audio_jack_detect;
54 int key_enable_gpio;
55 int mic_select_gpio;
56 int audio_jack_flag;
57 int mic_detect;
58 int last_pressed_key;
59 int microp_channel;
60
61 struct hrtimer detection_timer;
62 ktime_t debounce_time;
63
64 struct work_struct work;
65 struct work_struct mic_work;
66 spinlock_t spin_lock;
67
68 struct wake_lock audiojack_wake_lock;
69};
70
71static struct audio_jack_info *pjack_info;
72
73static int hs_gpio_get_mic(void)
74{
75 int value;
76 value = !gpio_get_value(pjack_info->mic_detect);
77
78 printk("hs_gpio_get_mic: %d\n", value);
79 return value;
80}
81
82static int hs_enable_key_irq(int status)
83{
84 printk("hs_enable_key_irq: %d\n", status);
85 if(status)
86 enable_irq(pjack_info->irq_mic);
87 else
88 disable_irq(pjack_info->irq_mic);
89 return 0;
90}
91
92void hs_gpio_key_enable(int enable)
93{
94 DBG_MSG();
95
96 if (pjack_info->key_enable_gpio)
97 gpio_set_value(pjack_info->key_enable_gpio, enable);
98}
99
100void hs_gpio_mic_select(int enable)
101{
102 DBG_MSG();
103
104 if (pjack_info->mic_select_gpio)
105 gpio_set_value(pjack_info->mic_select_gpio, enable);
106}
107
108static int get_remote_keycode(int *keycode)
109{
110 uint32_t val;
111 uint32_t btn = 0;
112
113 /*microp_set_adc_req(pjack_info->microp_channel);
114 if (microp_get_remote_adc(&val))
115 {
116 // failed. who know why? ignore
117 *keycode = 0;
118 return 1;
119 }*/
120
121 if((val >= 0) && (val <= 33))
122 {
123 btn = 1;
124 }
125 else if((val >= 38) && (val <= 82))
126 {
127 btn = 2;
128 }
129 else if((val >= 95) && (val <= 200))
130 {
131 btn = 3;
132 }
133 else if(val > 200)
134 {
135 // check previous key
136 if (pjack_info->last_pressed_key)
137 {
138 *keycode = pjack_info->last_pressed_key | 0x80;
139 pjack_info->last_pressed_key = 0;
140 return 0;
141 }
142 *keycode = 0;
143 return 1;
144 }
145
146 pjack_info->last_pressed_key = btn;
147 *keycode = btn;
148 return 0;
149}
150
151static irqreturn_t mic_irq_handler(int irq, void *dev_id)
152{
153 pr_info("MIC IRQ Handler\n");
154 int value1, value2;
155 int retry_limit = 10;
156
157 AJ_DBG("");
158
159 do {
160 value1 = gpio_get_value(pjack_info->mic_detect);
161 set_irq_type(pjack_info->irq_mic, value1 ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
162 value2 = gpio_get_value(pjack_info->mic_detect);
163 } while (value1 != value2 && retry_limit-- > 0);
164
165 AJ_DBG("value2 = %d (%d retries)", value2, (10-retry_limit));
166
167 schedule_work(&pjack_info->mic_work);
168 return IRQ_HANDLED;
169}
170
171static irqreturn_t detect_irq_handler(int irq, void *dev_id)
172{
173 pr_info("DET IRQ Handler\n");
174 int value1, value2;
175 int retry_limit = 10;
176
177 hs_notify_hpin_irq();
178
179 AJ_DBG("");
180
181 do {
182 value1 = gpio_get_value(pjack_info->audio_jack_detect);
183 set_irq_type(pjack_info->irq_jack, value1 ?
184 IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
185 value2 = gpio_get_value(pjack_info->audio_jack_detect);
186 } while (value1 != value2 && retry_limit-- > 0);
187
188 AJ_DBG("value2 = %d (%d retries)", value2, (10-retry_limit));
189
190 if ((pjack_info->audio_jack_flag == 0) ^ value2) {
191 wake_lock_timeout(&pjack_info->audiojack_wake_lock, 4*HZ);
192
193 /* Do the rest of the work in timer context */
194 hrtimer_start(&pjack_info->detection_timer,
195 pjack_info->debounce_time, HRTIMER_MODE_REL);
196 }
197
198 return IRQ_HANDLED;
199}
200
201static enum hrtimer_restart detect_35mm_event_timer_func(struct hrtimer *data)
202{
203 int state;
204
205 AJ_DBG("");
206 state = !gpio_get_value(pjack_info->audio_jack_detect);
207 if (pjack_info->audio_jack_flag != state) {
208 pjack_info->audio_jack_flag = state;
209 schedule_work(&pjack_info->work);
210 }
211
212 return HRTIMER_NORESTART;
213}
214
215static void mic_work_func(struct work_struct *work)
216{
217 pr_info("MIC Schedule Work\n");
218 int keycode = 0;
219
220 printk("mic_intr_work_func\n");
221 if (get_remote_keycode(&keycode) == 0)
222 {
223 printk("keycode %d\n", keycode);
224 htc_35mm_remote_notify_button_status(keycode);
225 }
226 else
227 printk("mic error keycode\n");
228
229}
230
231static void audiojack_work_func(struct work_struct *work)
232{
233 int is_insert;
234 pr_info("DET Schedule Work\n");
235 unsigned long flags = 0;
236
237 spin_lock_irqsave(&pjack_info->spin_lock, flags);
238 is_insert = pjack_info->audio_jack_flag;
239 spin_unlock_irqrestore(&pjack_info->spin_lock, flags);
240
241 htc_35mm_remote_notify_insert_ext_headset(is_insert);
242
243 if (is_insert)
244 pjack_info->debounce_time = ktime_set(0, 200000000);
245 else
246 pjack_info->debounce_time = ktime_set(0, 500000000);
247}
248
249static void hs_gpio_register(void)
250{
251 struct headset_notifier notifier;
252
253 if (pjack_info->mic_select_gpio) {
254 notifier.id = HEADSET_REG_MIC_SELECT;
255 notifier.func = hs_gpio_mic_select;
256 headset_notifier_register(&notifier);
257 }
258
259 if (pjack_info->key_enable_gpio) {
260 notifier.id = HEADSET_REG_KEY_ENABLE;
261 notifier.func = hs_gpio_key_enable;
262 headset_notifier_register(&notifier);
263 }
264
265 if (pjack_info->mic_detect) {
266 notifier.id = HEADSET_REG_MIC_STATUS;
267 notifier.func = hs_gpio_get_mic;
268 headset_notifier_register(&notifier);
269
270 notifier.id = HEADSET_REG_KEY_INT_ENABLE;
271 notifier.func = hs_enable_key_irq;
272 headset_notifier_register(&notifier);
273 }
274}
275
276static int audiojack_probe(struct platform_device *pdev)
277{
278 int ret;
279 struct htc_headset_gpio_platform_data *pdata = pdev->dev.platform_data;
280
281 SYS_MSG("++++++++++++++++++++");
282
283 pjack_info = kzalloc(sizeof(struct audio_jack_info), GFP_KERNEL);
284 if (!pjack_info)
285 return -ENOMEM;
286
287 pjack_info->audio_jack_detect = pdata->hpin_gpio;
288 pjack_info->key_enable_gpio = pdata->key_enable_gpio;
289 pjack_info->mic_select_gpio = pdata->mic_select_gpio;
290 pjack_info->mic_detect = pdata->mic_detect_gpio;
291 pjack_info->microp_channel = pdata->microp_channel;
292 pjack_info->audio_jack_flag = 0;
293 pjack_info->last_pressed_key = 0;
294
295 pjack_info->debounce_time = ktime_set(0, 500000000);
296 hrtimer_init(&pjack_info->detection_timer,
297 CLOCK_MONOTONIC, HRTIMER_MODE_REL);
298 pjack_info->detection_timer.function = detect_35mm_event_timer_func;
299
300 INIT_WORK(&pjack_info->work, audiojack_work_func);
301 INIT_WORK(&pjack_info->mic_work, mic_work_func);
302
303 spin_lock_init(&pjack_info->spin_lock);
304 wake_lock_init(&pjack_info->audiojack_wake_lock,
305 WAKE_LOCK_SUSPEND, "audiojack");
306
307 if (pjack_info->audio_jack_detect) {
308 ret = gpio_request(pjack_info->audio_jack_detect,
309 "3.5mm_detect");
310 if (ret < 0)
311 goto err_request_detect_gpio;
312
313 ret = gpio_direction_input(pjack_info->audio_jack_detect);
314 if (ret < 0)
315 goto err_set_detect_gpio;
316
317 pjack_info->irq_jack =
318 gpio_to_irq(pjack_info->audio_jack_detect);
319 if (pjack_info->irq_jack < 0) {
320 ret = pjack_info->irq_jack;
321 goto err_request_detect_irq;
322 }
323
324 ret = request_irq(pjack_info->irq_jack,
325 detect_irq_handler,
326 IRQF_TRIGGER_LOW, "35mm_headset", NULL);
327 if (ret < 0)
328 goto err_request_detect_irq;
329
330 ret = set_irq_wake(pjack_info->irq_jack, 1);
331 if (ret < 0)
332 goto err_set_irq_wake;
333 pr_info("DET IRQ Registered!");
334 }
335
336
337 if (pjack_info->mic_detect) {
338 ret = gpio_request(pjack_info->mic_detect,
339 "mic_detect");
340 if (ret < 0)
341 goto err_request_detect_gpio;
342
343 ret = gpio_direction_input(pjack_info->mic_detect);
344 if (ret < 0)
345 goto err_set_detect_gpio;
346
347 pjack_info->irq_mic =
348 gpio_to_irq(pjack_info->mic_detect);
349 if (pjack_info->irq_mic < 0) {
350 ret = pjack_info->irq_mic;
351 goto err_request_detect_irq;
352 }
353
354 ret = request_irq(pjack_info->irq_mic,
355 mic_irq_handler, IRQF_DISABLED | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW, "mic_headset", NULL);
356 if (ret < 0)
357 goto err_request_detect_irq;
358
359 disable_irq(pjack_info->irq_mic);
360 pr_info("MIC IRQ Registered!");
361 }
362 hs_gpio_register();
363
364 SYS_MSG("--------------------");
365
366 return 0;
367
368err_set_irq_wake:
369 if (pjack_info->audio_jack_detect)
370 free_irq(pjack_info->irq_jack, 0);
371err_request_detect_irq:
372err_set_detect_gpio:
373 if (pjack_info->audio_jack_detect)
374 gpio_free(pjack_info->audio_jack_detect);
375err_request_detect_gpio:
376 printk(KERN_ERR "Audiojack: Failed in audiojack_probe\n");
377
378 return ret;
379}
380
381static int audiojack_remove(struct platform_device *pdev)
382{
383 if (pjack_info->audio_jack_detect)
384 free_irq(pjack_info->irq_jack, 0);
385
386 if (pjack_info->audio_jack_detect)
387 free_irq(pjack_info->irq_mic, 0);
388
389 if (pjack_info->audio_jack_detect)
390 gpio_free(pjack_info->audio_jack_detect);
391
392 if (pjack_info->audio_jack_detect)
393 gpio_free(pjack_info->mic_detect);
394
395 return 0;
396}
397
398static struct platform_driver audiojack_driver = {
399 .probe = audiojack_probe,
400 .remove = audiojack_remove,
401 .driver = {
402 .name = "HTC_HEADSET_GPIO",
403 .owner = THIS_MODULE,
404 },
405};
406
407static int __init audiojack_init(void)
408{
409 return platform_driver_register(&audiojack_driver);
410}
411
412static void __exit audiojack_exit(void)
413{
414 platform_driver_unregister(&audiojack_driver);
415}
416
417module_init(audiojack_init);
418module_exit(audiojack_exit);
419
420MODULE_DESCRIPTION("HTC GPIO headset detection driver");
421MODULE_LICENSE("GPL");
  
1/*
2 *
3 * /arch/arm/mach-msm/htc_headset_mgr.c
4 *
5 * HTC headset manager driver.
6 *
7 * Copyright (C) 2010 HTC, Inc.
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/sysdev.h>
23#include <linux/fs.h>
24#include <linux/interrupt.h>
25#include <linux/workqueue.h>
26#include <linux/irq.h>
27#include <linux/delay.h>
28#include <linux/types.h>
29#include <linux/platform_device.h>
30#include <linux/mutex.h>
31#include <linux/errno.h>
32#include <linux/err.h>
33#include <linux/hrtimer.h>
34#include <linux/debugfs.h>
35#include <linux/jiffies.h>
36#include <linux/gpio.h>
37
38#include <asm/atomic.h>
39#include <asm/mach-types.h>
40
41#include <mach/board.h>
42#include <mach/vreg.h>
43//#include <mach/atmega_microp.h>
44
45#include <mach/htc_headset_mgr.h>
46
47#define DRIVER_NAME "HS_MGR"
48
49/* #define CONFIG_DEBUG_H2W */
50
51/*Delay 200ms when 11pin device plug in*/
52#define H2W_DETECT_DELAY msecs_to_jiffies(200)
53#define BUTTON_H2W_DELAY msecs_to_jiffies(10)
54
55#define H2WI(fmt, arg...) \
56 printk(KERN_INFO "[H2W] %s " fmt "\r\n", __func__, ## arg)
57#define H2WE(fmt, arg...) \
58 printk(KERN_ERR "[H2W] %s " fmt "\r\n", __func__, ## arg)
59
60#ifdef CONFIG_DEBUG_H2W
61#define H2W_DBG(fmt, arg...) \
62 printk(KERN_INFO "[H2W] %s " fmt "\r\n", __func__, ## arg)
63#else
64#define H2W_DBG(fmt, arg...) do {} while (0)
65#endif
66
67static struct workqueue_struct *detect_wq;
68
69static void insert_35mm_do_work(struct work_struct *work);
70static DECLARE_WORK(insert_35mm_work, insert_35mm_do_work);
71static void remove_35mm_do_work(struct work_struct *work);
72static DECLARE_WORK(remove_35mm_work, remove_35mm_do_work);
73
74static struct workqueue_struct *button_wq;
75
76static void button_35mm_do_work(struct work_struct *w);
77static DECLARE_DELAYED_WORK(button_35mm_work, button_35mm_do_work);
78
79static int hs_mgr_rpc_call(struct msm_rpc_server *server,
80 struct rpc_request_hdr *req, unsigned len);
81
82static struct msm_rpc_server hs_rpc_server = {
83 .prog = HS_RPC_SERVER_PROG,
84 .vers = HS_RPC_SERVER_VERS,
85 .rpc_call = hs_mgr_rpc_call,
86};
87
88struct button_work {
89 struct delayed_work key_work;
90 int key_code;
91};
92
93static struct h2w_info *hi;
94static struct hs_notifier_func hs_mgr_notifier;
95
96void hs_notify_hpin_irq(void)
97{
98 hi->hpin_jiffies = jiffies;
99 SYS_MSG("HPIN IRQ");
100}
101
102int hs_hpin_stable(void)
103{
104 unsigned long last_hpin_jiffies = 0;
105 unsigned long unstable_jiffies = 1.2 * HZ;
106
107 last_hpin_jiffies = hi->hpin_jiffies;
108
109 if (time_before_eq(jiffies, last_hpin_jiffies + unstable_jiffies))
110 return 0;
111
112 return 1;
113}
114
115int headset_notifier_register(struct headset_notifier *notifier)
116{
117 if (!notifier->func) {
118 SYS_MSG("NULL register function");
119 return 0;
120 }
121
122 switch (notifier->id) {
123 case HEADSET_REG_REMOTE_ADC:
124 SYS_MSG("Register REMOTE_ADC notifier");
125 hs_mgr_notifier.remote_adc = notifier->func;
126 break;
127 case HEADSET_REG_RPC_KEY:
128 SYS_MSG("Register RPC_KEY notifier");
129 hs_mgr_notifier.rpc_key = notifier->func;
130 break;
131 case HEADSET_REG_MIC_STATUS:
132 SYS_MSG("Register MIC_STATUS notifier");
133 hs_mgr_notifier.mic_status = notifier->func;
134 break;
135 case HEADSET_REG_MIC_BIAS:
136 SYS_MSG("Register MIC_BIAS notifier");
137 hs_mgr_notifier.mic_bias_enable = notifier->func;
138 break;
139 case HEADSET_REG_MIC_SELECT:
140 SYS_MSG("Register MIC_SELECT notifier");
141 hs_mgr_notifier.mic_select = notifier->func;
142 break;
143 case HEADSET_REG_KEY_INT_ENABLE:
144 SYS_MSG("Register KEY_INT_ENABLE notifier");
145 hs_mgr_notifier.key_int_enable = notifier->func;
146 break;
147 case HEADSET_REG_KEY_ENABLE:
148 SYS_MSG("Register KEY_ENABLE notifier");
149 hs_mgr_notifier.key_enable = notifier->func;
150 break;
151 default:
152 SYS_MSG("Unknown register ID");
153 return 0;
154 }
155
156 return 1;
157}
158
159static int hs_mgr_rpc_call(struct msm_rpc_server *server,
160 struct rpc_request_hdr *req, unsigned len)
161{
162 struct hs_rpc_server_args_key *args_key;
163
164 DBG_MSG("");
165
166 switch (req->procedure) {
167 case HS_RPC_SERVER_PROC_NULL:
168 SYS_MSG("RPC_SERVER_NULL");
169 break;
170 case HS_RPC_SERVER_PROC_KEY:
171 args_key = (struct hs_rpc_server_args_key *)(req + 1);
172 args_key->adc = be32_to_cpu(args_key->adc);
173 SYS_MSG("RPC_SERVER_KEY ADC = %u (0x%X)",
174 args_key->adc, args_key->adc);
175 if (hs_mgr_notifier.rpc_key)
176 hs_mgr_notifier.rpc_key(args_key->adc);
177 else
178 SYS_MSG("RPC_KEY notify function doesn't exist");
179 break;
180 default:
181 SYS_MSG("Unknown RPC procedure");
182 return -EINVAL;
183 }
184
185 return 0;
186}
187
188static ssize_t h2w_print_name(struct switch_dev *sdev, char *buf)
189{
190 return sprintf(buf, "Headset\n");
191}
192
193void button_pressed(int type)
194{
195 printk(KERN_INFO "[H2W] button_pressed %d\n", type);
196 atomic_set(&hi->btn_state, type);
197 input_report_key(hi->input, type, 1);
198 input_sync(hi->input);
199}
200
201void button_released(int type)
202{
203 printk(KERN_INFO "[H2W] button_released %d\n", type);
204 atomic_set(&hi->btn_state, 0);
205 input_report_key(hi->input, type, 0);
206 input_sync(hi->input);
207}
208
209void Headset_button_event(int is_press, int type)
210{
211 if (!hs_hpin_stable()) {
212 H2WI("The HPIN is unstable, SKIP THE BUTTON EVENT.");
213 return;
214 }
215
216 if (!is_press) {
217 if (hi->ignore_btn)
218 hi->ignore_btn = 0;
219 else
220 button_released(type);
221 } else {
222 if (!hi->ignore_btn && !atomic_read(&hi->btn_state))
223 button_pressed(type);
224 }
225}
226
227static void set_35mm_hw_state(int state)
228{
229 if (hi->mic_bias_state != state && hs_mgr_notifier.mic_bias_enable) {
230 hs_mgr_notifier.mic_bias_enable(state);
231 hi->mic_bias_state = state;
232 if (state) /* Wait for MIC bias stable */
233 msleep(HS_DELAY_MIC_BIAS);
234 }
235
236 if (hs_mgr_notifier.mic_select)
237 hs_mgr_notifier.mic_select(state);
238
239 if (hs_mgr_notifier.key_enable)
240 hs_mgr_notifier.key_enable(state);
241
242 if (hs_mgr_notifier.key_int_enable)
243 hs_mgr_notifier.key_int_enable(state);
244}
245
246static void insert_11pin_35mm(int *state)
247{
248 int mic = HEADSET_NO_MIC;
249
250 SYS_MSG("Insert USB 3.5mm headset");
251 set_35mm_hw_state(1);
252
253 if (hs_mgr_notifier.mic_status)
254 mic = hs_mgr_notifier.mic_status();
255
256 if (mic == HEADSET_NO_MIC) {
257 /* without microphone */
258 *state |= BIT_HEADSET_NO_MIC;
259 hi->h2w_35mm_status = HTC_35MM_NO_MIC;
260 printk(KERN_INFO "11pin_3.5mm without microphone\n");
261 } else { /* with microphone */
262 *state |= BIT_HEADSET;
263 hi->h2w_35mm_status = HTC_35MM_MIC;
264 printk(KERN_INFO "11pin_3.5mm with microphone\n");
265 }
266}
267
268static void remove_11pin_35mm(void)
269{
270 SYS_MSG("Remove USB 3.5mm headset");
271
272 set_35mm_hw_state(0);
273
274 if (atomic_read(&hi->btn_state))
275 button_released(atomic_read(&hi->btn_state));
276 hi->h2w_35mm_status = HTC_35MM_UNPLUG;
277}
278
279static void button_35mm_do_work(struct work_struct *w)
280{
281 int key;
282 struct button_work *work;
283
284 work = container_of(w, struct button_work, key_work.work);
285 hi->key_level_flag = work->key_code;
286
287 if (!hi->is_ext_insert && !hi->h2w_35mm_status) {
288 kfree(work);
289 H2WI("3.5mm headset is plugged out, skip report key event");
290 return;
291 }
292
293 if (hi->key_level_flag) {
294 switch (hi->key_level_flag) {
295 case 1:
296 H2WI("3.5mm RC: Play Pressed");
297 key = HS_MGR_KEYCODE_MEDIA;
298 break;
299 case 2:
300 H2WI("3.5mm RC: BACKWARD Pressed");
301 key = HS_MGR_KEYCODE_BACKWARD;
302 break;
303 case 3:
304 H2WI("3.5mm RC: FORWARD Pressed");
305 key = HS_MGR_KEYCODE_FORWARD;
306 break;
307 default:
308 H2WI("3.5mm RC: WRONG Button Pressed");
309 return;
310 }
311 Headset_button_event(1, key);
312 } else { /* key release */
313 if (atomic_read(&hi->btn_state))
314 Headset_button_event(0, atomic_read(&hi->btn_state));
315 else
316 H2WI("3.5mm RC: WRONG Button Release");
317 }
318
319 wake_lock_timeout(&hi->headset_wake_lock, 1.5 * HZ);
320
321 kfree(work);
322}
323
324static void enable_metrico_headset(int enable)
325{
326 if (enable && !hi->metrico_status) {
327#if 0
328 enable_mos_test(1);
329#endif
330 hi->metrico_status = 1;
331 printk(KERN_INFO "Enable metrico headset\n");
332 }
333
334 if (!enable && hi->metrico_status) {
335#if 0
336 enable_mos_test(0);
337#endif
338 hi->metrico_status = 0;
339 printk(KERN_INFO "Disable metrico headset\n");
340 }
341}
342
343static void remove_35mm_do_work(struct work_struct *work)
344{
345 int state;
346
347 wake_lock_timeout(&hi->headset_wake_lock, 2.5 * HZ);
348
349 H2W_DBG("");
350 /*To solve the insert, remove, insert headset problem*/
351 if (time_before_eq(jiffies, hi->insert_jiffies))
352 msleep(800);
353 if (hi->is_ext_insert) {
354 H2WI("Skip 3.5mm headset plug out!!!");
355 return;
356 }
357
358 SYS_MSG("Remove 3.5mm headset");
359 set_35mm_hw_state(0);
360
361 /* For HW Metrico lab test */
362 if (hi->metrico_status)
363 enable_metrico_headset(0);
364
365 if (atomic_read(&hi->btn_state))
366 button_released(atomic_read(&hi->btn_state));
367 hi->ext_35mm_status = HTC_35MM_UNPLUG;
368
369 mutex_lock(&hi->mutex_lock);
370 state = switch_get_state(&hi->sdev);
371
372 if (hi->usb_dev_type == USB_HEADSET) {
373 hi->usb_dev_status = STATUS_CONNECTED_ENABLED;
374 state &= ~(BIT_35MM_HEADSET | BIT_HEADSET);
375 state |= BIT_HEADSET_NO_MIC;
376 switch_set_state(&hi->sdev, state);
377 mutex_unlock(&hi->mutex_lock);
378 } else if (hi->usb_dev_type == H2W_TVOUT) {
379 state &= ~(BIT_HEADSET | BIT_35MM_HEADSET);
380 state |= BIT_HEADSET_NO_MIC;
381 switch_set_state(&hi->sdev, state);
382#if 0
383 } else if (hi->cable_in1 && !gpio_get_value(hi->cable_in1)) {
384 state &= ~BIT_35MM_HEADSET;
385 switch_set_state(&hi->sdev, state);
386 queue_delayed_work(detect_wq, &detect_h2w_work,
387 HS_DELAY_ZERO_JIFFIES);
388#endif
389 } else {
390 state &= ~(BIT_HEADSET | BIT_HEADSET_NO_MIC |
391 BIT_35MM_HEADSET);
392 switch_set_state(&hi->sdev, state);
393 }
394
395 mutex_unlock(&hi->mutex_lock);
396}
397
398static void insert_35mm_do_work(struct work_struct *work)
399{
400 int state;
401 int i, mic1, mic2;
402
403 H2W_DBG("");
404 hi->insert_jiffies = jiffies + HZ;
405
406 wake_lock_timeout(&hi->headset_wake_lock, 1.5 * HZ);
407
408#if 0
409 if (hi->usb_dev_type && hi->is_ext_insert &&
410 hi->usb_dev_type != H2W_TVOUT && hi->usb_dev_type != USB_HEADSET)
411 remove_headset();
412 else if (hi->usb_dev_type == USB_HEADSET)
413 hi->usb_dev_status = STATUS_CONNECTED_DISABLED;
414#endif
415
416 if (hi->usb_dev_type == USB_HEADSET)
417 hi->usb_dev_status = STATUS_CONNECTED_DISABLED;
418
419 if (hi->is_ext_insert) {
420 SYS_MSG("Insert 3.5mm headset");
421 set_35mm_hw_state(1);
422 hi->ignore_btn = 0;
423
424 mic1 = mic2 = HEADSET_NO_MIC;
425 if (hs_mgr_notifier.mic_status) {
426 if (hi->ext_35mm_status == HTC_35MM_NO_MIC ||
427 hi->h2w_35mm_status == HTC_35MM_NO_MIC)
428 for (i = 0; i < 10; i++) {
429 mic1 = hs_mgr_notifier.mic_status();
430 msleep(HS_DELAY_MIC_DETECT);
431 mic2 = hs_mgr_notifier.mic_status();
432 if (mic1 == mic2)
433 break;
434 }
435 else
436 mic1 = mic2 = hs_mgr_notifier.mic_status();
437 }
438
439 /* For HW Metrico lab test */
440 if (mic2 == HEADSET_METRICO && !hi->metrico_status)
441 enable_metrico_headset(1);
442
443 mutex_lock(&hi->mutex_lock);
444 state = switch_get_state(&hi->sdev);
445 state &= ~(BIT_HEADSET | BIT_HEADSET_NO_MIC);
446 if (mic2 == HEADSET_NO_MIC || mic1 != mic2) {
447 state |= BIT_HEADSET_NO_MIC;
448 printk(KERN_INFO "3.5mm_headset without microphone\n");
449 } else {
450 state |= BIT_HEADSET;
451 printk(KERN_INFO "3.5mm_headset with microphone\n");
452 }
453
454 state |= BIT_35MM_HEADSET;
455 switch_set_state(&hi->sdev, state);
456 if (state & BIT_HEADSET_NO_MIC)
457 hi->ext_35mm_status = HTC_35MM_NO_MIC;
458 else
459 hi->ext_35mm_status = HTC_35MM_MIC;
460 mutex_unlock(&hi->mutex_lock);
461 }
462}
463
464int htc_35mm_remote_notify_insert_ext_headset(int insert)
465{
466 if (hi) {
467 mutex_lock(&hi->mutex_lock);
468 hi->is_ext_insert = insert;
469 mutex_unlock(&hi->mutex_lock);
470
471 H2WI(" %d", hi->is_ext_insert);
472 if (!hi->is_ext_insert)
473 queue_work(detect_wq, &remove_35mm_work);
474 else
475 queue_work(detect_wq, &insert_35mm_work);
476 }
477 return 1;
478}
479
480int htc_35mm_remote_notify_microp_ready(void)
481{
482 if (hi) {
483 if (hi->is_ext_insert)
484 queue_work(detect_wq, &insert_35mm_work);
485#if 0
486 if (hi->h2w_35mm_status)
487 insert_headset(NORMAL_HEARPHONE);
488#endif
489 }
490 return 1;
491}
492
493int htc_35mm_remote_notify_button_status(int key_level)
494{
495 struct button_work *work;
496
497 if (hi->ext_35mm_status == HTC_35MM_NO_MIC ||
498 hi->h2w_35mm_status == HTC_35MM_NO_MIC) {
499 SYS_MSG("MIC re-detection");
500 msleep(HS_DELAY_MIC_DETECT);
501 queue_work(detect_wq, &insert_35mm_work);
502 } else if (!hs_hpin_stable()) {
503 H2WI("The HPIN is unstable, SKIP THE BUTTON EVENT.");
504 return 1;
505 } else {
506 work = kzalloc(sizeof(struct button_work), GFP_KERNEL);
507 if (!work) {
508 printk(KERN_INFO "Failed to allocate button memory\n");
509 return 1;
510 }
511 work->key_code = key_level;
512 INIT_DELAYED_WORK(&work->key_work, button_35mm_do_work);
513 queue_delayed_work(button_wq, &work->key_work,
514 HS_JIFFIES_BUTTON);
515 }
516
517 return 1;
518}
519
520static void usb_headset_detect(int type)
521{
522 int state;
523
524 mutex_lock(&hi->mutex_lock);
525 state = switch_get_state(&hi->sdev);
526
527 switch (type) {
528 case NO_DEVICE:
529 if (hi->usb_dev_type == USB_HEADSET) {
530 printk(KERN_INFO "Remove USB headset\n");
531 hi->usb_dev_type = NO_DEVICE;
532 hi->usb_dev_status = STATUS_DISCONNECTED;
533 state &= ~BIT_USB_HEADSET;
534 if (!hi->is_ext_insert)
535 state &= ~BIT_HEADSET_NO_MIC;
536 }
537 break;
538 case USB_HEADSET:
539 printk(KERN_INFO "Insert USB headset\n");
540 hi->usb_dev_type = USB_HEADSET;
541 if (hi->is_ext_insert) {
542 printk(KERN_INFO "Disable USB headset\n");
543 hi->usb_dev_status = STATUS_CONNECTED_DISABLED;
544 state |= BIT_USB_HEADSET;
545 } else {
546 printk(KERN_INFO "Enable USB headset\n");
547 hi->usb_dev_status = STATUS_CONNECTED_ENABLED;
548 state |= (BIT_USB_HEADSET | BIT_HEADSET_NO_MIC);
549 }
550 break;
551 default:
552 printk(KERN_INFO "Unknown headset type\n");
553 }
554
555 switch_set_state(&hi->sdev, state);
556 mutex_unlock(&hi->mutex_lock);
557}
558
559void headset_ext_detect(int type)
560{
561 switch (type) {
562 case NO_DEVICE:
563 if (hi->usb_dev_type == USB_HEADSET)
564 usb_headset_detect(type);
565 break;
566 case USB_HEADSET:
567 usb_headset_detect(type);
568 break;
569 default:
570 printk(KERN_INFO "Unknown headset type\n");
571 }
572}
573
574int switch_send_event(unsigned int bit, int on)
575{
576 unsigned long state;
577
578 mutex_lock(&hi->mutex_lock);
579 state = switch_get_state(&hi->sdev);
580 state &= ~(bit);
581
582 if (on)
583 state |= bit;
584
585 switch_set_state(&hi->sdev, state);
586 mutex_unlock(&hi->mutex_lock);
587 return 0;
588}
589
590static ssize_t tty_flag_show(struct device *dev,
591 struct device_attribute *attr, char *buf)
592{
593 char *s = buf;
594 mutex_lock(&hi->mutex_lock);
595 s += sprintf(s, "%d\n", hi->tty_enable_flag);
596 mutex_unlock(&hi->mutex_lock);
597 return (s - buf);
598}
599
600static ssize_t tty_flag_store(struct device *dev,
601 struct device_attribute *attr, const char *buf, size_t count)
602{
603 int state;
604
605 mutex_lock(&hi->mutex_lock);
606 state = switch_get_state(&hi->sdev);
607 state &= ~(BIT_TTY_FULL | BIT_TTY_VCO | BIT_TTY_HCO);
608
609 if (count == (strlen("enable") + 1) &&
610 strncmp(buf, "enable", strlen("enable")) == 0) {
611 hi->tty_enable_flag = 1;
612 switch_set_state(&hi->sdev, state | BIT_TTY_FULL);
613 mutex_unlock(&hi->mutex_lock);
614 printk(KERN_INFO "Enable TTY FULL\n");
615 return count;
616 }
617 if (count == (strlen("vco_enable") + 1) &&
618 strncmp(buf, "vco_enable", strlen("vco_enable")) == 0) {
619 hi->tty_enable_flag = 2;
620 switch_set_state(&hi->sdev, state | BIT_TTY_VCO);
621 mutex_unlock(&hi->mutex_lock);
622 printk(KERN_INFO "Enable TTY VCO\n");
623 return count;
624 }
625 if (count == (strlen("hco_enable") + 1) &&
626 strncmp(buf, "hco_enable", strlen("hco_enable")) == 0) {
627 hi->tty_enable_flag = 3;
628 switch_set_state(&hi->sdev, state | BIT_TTY_HCO);
629 mutex_unlock(&hi->mutex_lock);
630 printk(KERN_INFO "Enable TTY HCO\n");
631 return count;
632 }
633 if (count == (strlen("disable") + 1) &&
634 strncmp(buf, "disable", strlen("disable")) == 0) {
635 hi->tty_enable_flag = 0;
636 switch_set_state(&hi->sdev, state);
637 mutex_unlock(&hi->mutex_lock);
638 printk(KERN_INFO "Disable TTY\n");
639 return count;
640 }
641 printk(KERN_ERR "tty_enable_flag_store: invalid argument\n");
642 return -EINVAL;
643}
644static DEVICE_ACCESSORY_ATTR(tty, 0666, tty_flag_show, tty_flag_store);
645
646static ssize_t fm_flag_store(struct device *dev,
647 struct device_attribute *attr, const char *buf, size_t count)
648{
649 int state;
650
651 mutex_lock(&hi->mutex_lock);
652 state = switch_get_state(&hi->sdev);
653 state &= ~(BIT_FM_HEADSET | BIT_FM_SPEAKER);
654
655 if (count == (strlen("fm_headset") + 1) &&
656 strncmp(buf, "fm_headset", strlen("fm_headset")) == 0) {
657 hi->fm_flag = 1;
658 state |= BIT_FM_HEADSET;
659 printk(KERN_INFO "Enable FM HEADSET\n");
660 } else if (count == (strlen("fm_speaker") + 1) &&
661 strncmp(buf, "fm_speaker", strlen("fm_speaker")) == 0) {
662 hi->fm_flag = 2;
663 state |= BIT_FM_SPEAKER;
664 printk(KERN_INFO "Enable FM SPEAKER\n");
665 } else if (count == (strlen("disable") + 1) &&
666 strncmp(buf, "disable", strlen("disable")) == 0) {
667 hi->fm_flag = 0 ;
668 printk(KERN_INFO "Disable FM\n");
669 } else {
670 mutex_unlock(&hi->mutex_lock);
671 printk(KERN_ERR "fm_enable_flag_store: invalid argument\n");
672 return -EINVAL;
673 }
674 switch_set_state(&hi->sdev, state);
675 mutex_unlock(&hi->mutex_lock);
676 return count;
677}
678
679static ssize_t fm_flag_show(struct device *dev,
680 struct device_attribute *attr, char *buf)
681{
682 char *s = buf;
683 char *show_str;
684 mutex_lock(&hi->mutex_lock);
685 if (hi->fm_flag == 0)
686 show_str = "disable";
687 if (hi->fm_flag == 1)
688 show_str = "fm_headset";
689 if (hi->fm_flag == 2)
690 show_str = "fm_speaker";
691
692 s += sprintf(s, "%s\n", show_str);
693 mutex_unlock(&hi->mutex_lock);
694 return (s - buf);
695}
696static DEVICE_ACCESSORY_ATTR(fm, 0666, fm_flag_show, fm_flag_store);
697
698static int register_common_headset(struct h2w_info *h2w, int create_attr)
699{
700 int ret = 0;
701 hi = h2w;
702
703 hi->htc_accessory_class = class_create(THIS_MODULE, "htc_accessory");
704 if (IS_ERR(hi->htc_accessory_class)) {
705 ret = PTR_ERR(hi->htc_accessory_class);
706 hi->htc_accessory_class = NULL;
707 goto err_create_class;
708 }
709
710 hi->tty_dev = device_create(hi->htc_accessory_class,
711 NULL, 0, "%s", "tty");
712 if (unlikely(IS_ERR(hi->tty_dev))) {
713 ret = PTR_ERR(hi->tty_dev);
714 hi->tty_dev = NULL;
715 goto err_create_tty_device;
716 }
717
718 /* register the attributes */
719 ret = device_create_file(hi->tty_dev, &dev_attr_tty);
720 if (ret)
721 goto err_create_tty_device_file;
722
723 hi->fm_dev = device_create(hi->htc_accessory_class,
724 NULL, 0, "%s", "fm");
725 if (unlikely(IS_ERR(hi->fm_dev))) {
726 ret = PTR_ERR(hi->fm_dev);
727 hi->fm_dev = NULL;
728 goto err_create_fm_device;
729 }
730
731 /* register the attributes */
732 ret = device_create_file(hi->fm_dev, &dev_attr_fm);
733 if (ret)
734 goto err_create_fm_device_file;
735
736 return 0;
737
738err_create_fm_device_file:
739 device_unregister(hi->fm_dev);
740err_create_fm_device:
741 device_remove_file(hi->tty_dev, &dev_attr_tty);
742err_create_tty_device_file:
743 device_unregister(hi->tty_dev);
744err_create_tty_device:
745 class_destroy(hi->htc_accessory_class);
746err_create_class:
747
748 return ret;
749}
750
751static void unregister_common_headset(struct h2w_info *h2w)
752{
753 hi = h2w;
754 device_remove_file(hi->tty_dev, &dev_attr_tty);
755 device_unregister(hi->tty_dev);
756 device_remove_file(hi->fm_dev, &dev_attr_fm);
757 device_unregister(hi->fm_dev);
758 class_destroy(hi->htc_accessory_class);
759}
760
761static int htc_35mm_probe(struct platform_device *pdev)
762{
763 int ret;
764
765 struct htc_headset_mgr_platform_data *pdata = pdev->dev.platform_data;
766
767 SYS_MSG("++++++++++++++++++++");
768
769 hi = kzalloc(sizeof(struct h2w_info), GFP_KERNEL);
770 if (!hi)
771 return -ENOMEM;
772
773 hi->driver_flag = pdata->driver_flag;
774 hi->hpin_jiffies = jiffies;
775
776 hi->ext_35mm_status = 0;
777 hi->h2w_35mm_status = 0;
778 hi->is_ext_insert = 0;
779 hi->mic_bias_state = 0;
780 hi->key_level_flag = -1;
781
782 atomic_set(&hi->btn_state, 0);
783 hi->ignore_btn = 0;
784 hi->usb_dev_type = NO_DEVICE;
785 hi->tty_enable_flag = 0;
786 hi->fm_flag = 0;
787 hi->mic_switch_flag = 1;
788 hi->rc_flag = 0;
789
790 hi->insert_11pin_35mm = insert_11pin_35mm;
791 hi->remove_11pin_35mm = remove_11pin_35mm;
792
793 mutex_init(&hi->mutex_lock);
794 mutex_init(&hi->mutex_rc_lock);
795
796 wake_lock_init(&hi->headset_wake_lock, WAKE_LOCK_SUSPEND, "headset");
797
798 hi->sdev.name = "h2w";
799 hi->sdev.print_name = h2w_print_name;
800
801 ret = switch_dev_register(&hi->sdev);
802 if (ret < 0)
803 goto err_switch_dev_register;
804
805 detect_wq = create_workqueue("detection");
806 if (detect_wq == NULL) {
807 ret = -ENOMEM;
808 goto err_create_detect_work_queue;
809 }
810 button_wq = create_workqueue("button");
811 if (button_wq == NULL) {
812 ret = -ENOMEM;
813 goto err_create_button_work_queue;
814 }
815
816 hi->input = input_allocate_device();
817 if (!hi->input) {
818 ret = -ENOMEM;
819 goto err_request_input_dev;
820 }
821
822 hi->input->name = "h2w headset";
823 set_bit(EV_SYN, hi->input->evbit);
824 set_bit(EV_KEY, hi->input->evbit);
825 set_bit(KEY_END, hi->input->keybit);
826 set_bit(KEY_MUTE, hi->input->keybit);
827 set_bit(KEY_VOLUMEDOWN, hi->input->keybit);
828 set_bit(KEY_VOLUMEUP, hi->input->keybit);
829 set_bit(KEY_NEXTSONG, hi->input->keybit);
830 set_bit(KEY_PLAYPAUSE, hi->input->keybit);
831 set_bit(KEY_PREVIOUSSONG, hi->input->keybit);
832 set_bit(KEY_MEDIA, hi->input->keybit);
833 set_bit(KEY_SEND, hi->input->keybit);
834
835 ret = input_register_device(hi->input);
836 if (ret < 0)
837 goto err_register_input_dev;
838
839 ret = register_common_headset(hi, 0);
840 if (ret)
841 goto err_register_common_headset;
842
843 if (hi->driver_flag & DRIVER_HS_MGR_RPC_SERVER) {
844 /* Create RPC server */
845 ret = msm_rpc_create_server(&hs_rpc_server);
846 if (ret < 0) {
847 SYS_MSG("Failed to create RPC server");
848 goto err_create_rpc_server;
849 }
850 SYS_MSG("Create RPC server successfully");
851 }
852
853 SYS_MSG("--------------------");
854
855 return 0;
856
857err_create_rpc_server:
858
859err_register_common_headset:
860 input_unregister_device(hi->input);
861
862err_register_input_dev:
863 input_free_device(hi->input);
864
865err_request_input_dev:
866 destroy_workqueue(button_wq);
867
868err_create_button_work_queue:
869 destroy_workqueue(detect_wq);
870
871err_create_detect_work_queue:
872 switch_dev_unregister(&hi->sdev);
873
874err_switch_dev_register:
875
876 printk(KERN_ERR "H2W: Failed to register driver\n");
877
878 return ret;
879}
880
881static int htc_35mm_remove(struct platform_device *pdev)
882{
883 H2W_DBG("");
884
885#if 0
886 if ((switch_get_state(&hi->sdev) &
887 (BIT_HEADSET | BIT_HEADSET_NO_MIC)) != 0)
888 remove_headset();
889#endif
890
891 unregister_common_headset(hi);
892 input_unregister_device(hi->input);
893 destroy_workqueue(detect_wq);
894 destroy_workqueue(button_wq);
895 switch_dev_unregister(&hi->sdev);
896
897 return 0;
898}
899
900static struct platform_driver htc_35mm_driver = {
901 .probe = htc_35mm_probe,
902 .remove = htc_35mm_remove,
903 .driver = {
904 .name = "HTC_HEADSET_MGR",
905 .owner = THIS_MODULE,
906 },
907};
908
909
910static int __init htc_35mm_init(void)
911{
912 H2W_DBG("");
913 return platform_driver_register(&htc_35mm_driver);
914}
915
916static void __exit htc_35mm_exit(void)
917{
918 platform_driver_unregister(&htc_35mm_driver);
919}
920
921module_init(htc_35mm_init);
922module_exit(htc_35mm_exit);
923
924MODULE_DESCRIPTION("HTC headset manager driver");
925MODULE_LICENSE("GPL");
  
1/*
2 *
3 * /arch/arm/mach-msm/include/mach/htc_headset_gpio.h
4 *
5 * HTC GPIO headset detection driver.
6 *
7 * Copyright (C) 2010 HTC, Inc.
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#ifndef HTC_HEADSET_GPIO_H
21#define HTC_HEADSET_GPIO_H
22
23struct htc_headset_gpio_platform_data {
24 unsigned int hpin_gpio;
25 unsigned int mic_detect_gpio;
26 unsigned int key_enable_gpio;
27 unsigned int mic_select_gpio;
28 unsigned int microp_channel;
29};
30
31#endif
  
1/*
2 *
3 * /arch/arm/mach-msm/include/mach/htc_headset_mgr.h
4 *
5 * HTC headset manager driver.
6 *
7 * Copyright (C) 2010 HTC, Inc.
8 *
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 */
19
20#ifndef HTC_HEADSET_MGR_H
21#define HTC_HEADSET_MGR_H
22
23#include <mach/msm_rpcrouter.h>
24
25#include <linux/switch.h>
26#include <linux/input.h>
27#include <linux/wakelock.h>
28
29#define SYS_MSG(fmt, arg...) \
30 printk(KERN_INFO "[" DRIVER_NAME "] (%s) " fmt "\n", __func__, ## arg)
31#if 0
32#define DBG_MSG(fmt, arg...) \
33 printk(KERN_INFO "##### [" DRIVER_NAME "] (%s) " fmt "\n", \
34 __func__, ## arg)
35#else
36#define DBG_MSG(fmt, arg...) {}
37#endif
38
39#define DEVICE_ACCESSORY_ATTR(_name, _mode, _show, _store) \
40 struct device_attribute dev_attr_##_name = \
41 __ATTR(flag, _mode, _show, _store)
42
43#define DRIVER_HS_MGR_RPC_SERVER (1 << 0)
44
45#define HS_DEF_MIC_ADC_10_BIT 200
46#define HS_DEF_MIC_ADC_16_BIT 14894 /* (0.5 / 2.2) * (2 ^ 16) */
47
48#define HS_DELAY_ZERO 0
49#define HS_DELAY_MIC_BIAS 200
50#define HS_DELAY_MIC_DETECT 500
51#define HS_DELAY_INSERT 500
52#define HS_DELAY_REMOVE 200
53#define HS_DELAY_BUTTON 500
54
55#define HS_JIFFIES_ZERO msecs_to_jiffies(HS_DELAY_ZERO)
56#define HS_JIFFIES_MIC_BIAS msecs_to_jiffies(HS_DELAY_MIC_BIAS)
57#define HS_JIFFIES_MIC_DETECT msecs_to_jiffies(HS_DELAY_MIC_DETECT)
58#define HS_JIFFIES_INSERT msecs_to_jiffies(HS_DELAY_INSERT)
59#define HS_JIFFIES_REMOVE msecs_to_jiffies(HS_DELAY_REMOVE)
60#define HS_JIFFIES_BUTTON msecs_to_jiffies(HS_DELAY_BUTTON)
61
62/* Definitions for Headset RPC Server */
63#define HS_RPC_SERVER_PROG 0x30100004
64#define HS_RPC_SERVER_VERS 0x00000000
65#define HS_RPC_SERVER_PROC_NULL 0
66#define HS_RPC_SERVER_PROC_KEY 1
67
68/* Definitions for Headset RPC Client */
69#define HS_RPC_CLIENT_PROG 0x30100005
70#define HS_RPC_CLIENT_VERS 0x00000000
71#define HS_RPC_CLIENT_PROC_NULL 0
72#define HS_RPC_CLIENT_PROC_ADC 1
73
74#define HS_MGR_KEYCODE_END KEY_END /* 107 */
75#define HS_MGR_KEYCODE_MUTE KEY_MUTE /* 113 */
76#define HS_MGR_KEYCODE_VOLDOWN KEY_VOLUMEDOWN /* 114 */
77#define HS_MGR_KEYCODE_VOLUP KEY_VOLUMEUP /* 115 */
78#define HS_MGR_KEYCODE_FORWARD KEY_NEXTSONG /* 163 */
79#define HS_MGR_KEYCODE_PLAY KEY_PLAYPAUSE /* 164 */
80#define HS_MGR_KEYCODE_BACKWARD KEY_PREVIOUSSONG /* 165 */
81#define HS_MGR_KEYCODE_MEDIA KEY_MEDIA /* 226 */
82#define HS_MGR_KEYCODE_SEND KEY_SEND /* 231 */
83
84#define HEADSET_NO_MIC 0
85#define HEADSET_MIC 1
86#define HEADSET_METRICO 2
87
88#define HTC_35MM_UNPLUG 0
89#define HTC_35MM_NO_MIC 1
90#define HTC_35MM_MIC 2
91
92enum {
93 HEADSET_REG_REMOTE_ADC,
94 HEADSET_REG_RPC_KEY,
95 HEADSET_REG_MIC_STATUS,
96 HEADSET_REG_MIC_BIAS,
97 HEADSET_REG_MIC_SELECT,
98 HEADSET_REG_KEY_INT_ENABLE,
99 HEADSET_REG_KEY_ENABLE,
100};
101
102enum {
103 HS_MGR_KEY_INVALID = -1,
104 HS_MGR_KEY_NONE = 0,
105 HS_MGR_KEY_PLAY = 1,
106 HS_MGR_KEY_BACKWARD = 2,
107 HS_MGR_KEY_FORWARD = 3,
108};
109
110struct hs_rpc_server_args_key {
111 uint32_t adc;
112};
113
114struct hs_rpc_client_req_adc {
115 struct rpc_request_hdr hdr;
116};
117
118struct hs_rpc_client_rep_adc {
119 struct rpc_reply_hdr hdr;
120 uint32_t adc;
121};
122
123struct headset_notifier {
124 int id;
125 void *func;
126};
127
128struct hs_notifier_func {
129 int (*remote_adc)(int *);
130 void (*rpc_key)(int);
131 int (*mic_status)(void);
132 int (*mic_bias_enable)(int);
133 void (*mic_select)(int);
134 int (*key_int_enable)(int);
135 void (*key_enable)(int);
136};
137
138struct htc_headset_mgr_platform_data {
139 unsigned int driver_flag;
140
141 int cable_in1;
142 int cable_in2;
143 int h2w_clk;
144 int h2w_data;
145 int debug_uart;
146 int headset_mic_35mm;
147
148 void (*h2w_power)(int);
149 void (*config)(int);
150 void (*set_dat)(int);
151 void (*set_clk)(int);
152 void (*set_dat_dir)(int);
153 void (*set_clk_dir)(int);
154 int (*get_dat)(void);
155 int (*get_clk)(void);
156};
157
158#define BIT_HEADSET (1 << 0)
159#define BIT_HEADSET_NO_MIC (1 << 1)
160#define BIT_TTY_FULL (1 << 2)
161#define BIT_FM_HEADSET (1 << 3)
162#define BIT_FM_SPEAKER (1 << 4)
163#define BIT_TTY_VCO (1 << 5)
164#define BIT_TTY_HCO (1 << 6)
165#define BIT_35MM_HEADSET (1 << 7)
166#define BIT_TV_OUT (1 << 8)
167#define BIT_USB_CRADLE (1 << 9)
168#define BIT_TV_OUT_AUDIO (1 << 10)
169#define BIT_HDMI_CABLE (1 << 11)
170#define BIT_HDMI_AUDIO (1 << 12)
171#define BIT_USB_HEADSET (1 << 13)
172
173enum {
174 STATUS_DISCONNECTED = 0,
175 STATUS_CONNECTED_ENABLED = 1,
176 STATUS_CONNECTED_DISABLED = 2,
177};
178
179enum {
180 H2W_GPIO = 0,
181 H2W_UART1 = 1,
182 H2W_UART3 = 2,
183 H2W_BT = 3
184};
185
186enum {
187 NO_DEVICE = 0,
188 HTC_HEADSET = 1,
189 NORMAL_HEARPHONE = 2,
190 H2W_DEVICE = 3,
191 USB_CRADLE = 4,
192 UART_DEBUG = 5,
193 H2W_TVOUT = 6,
194 USB_HEADSET = 7,
195};
196
197#define RESEND_DELAY (3) /* ms */
198#define MAX_ACK_RESEND_TIMES (6) /* follow spec */
199#define MAX_HOST_RESEND_TIMES (3) /* follow spec */
200#define MAX_HYGEIA_RESEND_TIMES (5)
201
202#define H2W_ASCR_DEVICE_INI (0x01)
203#define H2W_ASCR_ACT_EN (0x02)
204#define H2W_ASCR_PHONE_IN (0x04)
205#define H2W_ASCR_RESET (0x08)
206#define H2W_ASCR_AUDIO_IN (0x10)
207
208#define H2W_LED_OFF (0x0)
209#define H2W_LED_BKL (0x1)
210#define H2W_LED_MTL (0x2)
211
212#define H2W_PhoneIn (0x01)
213#define H2W_MuteLed (0x02)
214
215typedef enum {
216 /* === system group 0x0000~0x00FF === */
217 /* (R) Accessory type register */
218 H2W_SYSTEM = 0x0000,
219 /* (R) Maximum group address */
220 H2W_MAX_GP_ADD = 0x0001,
221 /* (R/W) Accessory system control register0 */
222 H2W_ASCR0 = 0x0002,
223
224 /* === key group 0x0100~0x01FF === */
225 /* (R) Key group maximum sub address */
226 H2W_KEY_MAXADD = 0x0100,
227 /* (R) ASCII key press down flag */
228 H2W_ASCII_DOWN = 0x0101,
229 /* (R) ASCII key release up flag */
230 H2W_ASCII_UP = 0x0102,
231 /* (R) Function key status flag */
232 H2W_FNKEY_UPDOWN = 0x0103,
233 /* (R/W) Key device status */
234 H2W_KD_STATUS = 0x0104,
235
236 /* === led group 0x0200~0x02FF === */
237 /* (R) LED group maximum sub address */
238 H2W_LED_MAXADD = 0x0200,
239 /* (R/W) LED control register0 */
240 H2W_LEDCT0 = 0x0201,
241
242 /* === crdl group 0x0300~0x03FF === */
243 /* (R) Cardle group maximum sub address */
244 H2W_CRDL_MAXADD = 0x0300,
245 /* (R/W) Cardle group function control register0 */
246 H2W_CRDLCT0 = 0x0301,
247
248 /* === car kit group 0x0400~0x04FF === */
249 H2W_CARKIT_MAXADD = 0x0400,
250
251 /* === usb host group 0x0500~0x05FF === */
252 H2W_USBHOST_MAXADD = 0x0500,
253
254 /* === medical group 0x0600~0x06FF === */
255 H2W_MED_MAXADD = 0x0600,
256 H2W_MED_CONTROL = 0x0601,
257 H2W_MED_IN_DATA = 0x0602,
258} H2W_ADDR;
259
260typedef struct H2W_INFO {
261 /* system group */
262 unsigned char CLK_SP;
263 int SLEEP_PR;
264 unsigned char HW_REV;
265 int AUDIO_DEVICE;
266 unsigned char ACC_CLASS;
267 unsigned char MAX_GP_ADD;
268
269 /* key group */
270 int KEY_MAXADD;
271 int ASCII_DOWN;
272 int ASCII_UP;
273 int FNKEY_UPDOWN;
274 int KD_STATUS;
275
276 /* led group */
277 int LED_MAXADD;
278 int LEDCT0;
279
280 /* medical group */
281 int MED_MAXADD;
282 unsigned char AP_ID;
283 unsigned char AP_EN;
284 unsigned char DATA_EN;
285} H2W_INFO;
286
287typedef enum {
288 H2W_500KHz = 1,
289 H2W_250KHz = 2,
290 H2W_166KHz = 3,
291 H2W_125KHz = 4,
292 H2W_100KHz = 5,
293 H2W_83KHz = 6,
294 H2W_71KHz = 7,
295 H2W_62KHz = 8,
296 H2W_55KHz = 9,
297 H2W_50KHz = 10,
298} H2W_SPEED;
299
300struct h2w_info {
301 unsigned int driver_flag;
302
303 unsigned long hpin_jiffies;
304
305 struct class *htc_accessory_class;
306 struct device *tty_dev;
307 struct device *fm_dev;
308 struct device *mic_dev;
309 struct device *mute_dev;
310 struct device *phonein_dev;
311 struct mutex mutex_lock;
312 struct mutex mutex_rc_lock;
313
314 struct switch_dev sdev;
315 struct input_dev *input;
316 unsigned long insert_jiffies;
317
318 int ignore_btn;
319 atomic_t btn_state;
320
321 int tty_enable_flag;
322 int fm_flag;
323 int mic_switch_flag;
324 int rc_flag;
325
326 unsigned int irq;
327 unsigned int irq_btn;
328 unsigned int irq_btn_35mm;
329
330 int cable_in1;
331 int cable_in2;
332 int h2w_clk;
333 int h2w_data;
334 int debug_uart;
335 int headset_mic_35mm;
336
337 /* The variables were used by 35mm headset*/
338 int key_level_flag;
339 int ext_35mm_status;
340 int h2w_35mm_status;
341 int is_ext_insert;
342 int mic_bias_state;
343 int metrico_status; /* For HW Metrico lab test */
344
345 /* The variables are used by USB headset */
346 int usb_dev_type;
347 int usb_dev_status;
348
349 void (*insert_11pin_35mm)(int *);
350 void (*remove_11pin_35mm)(void);
351
352 void (*configure) (int);
353 int (*get_path) (void);
354 void (*h2w_power)(int);
355 void (*set_dat)(int);
356 void (*set_clk)(int);
357 void (*set_dat_dir)(int);
358 void (*set_clk_dir)(int);
359 int (*get_dat)(void);
360 int (*get_clk)(void);
361
362 H2W_INFO h2w_info;
363 H2W_SPEED speed;
364
365 struct wake_lock headset_wake_lock;
366};
367
368int headset_notifier_register(struct headset_notifier *notifier);
369
370void insert_headset(int);
371void remove_headset(void);
372
373void headset_button_event(int is_press, int type);
374void button_pressed(int type);
375void button_released(int type);
376
377void button_h2w_do_work(struct work_struct *w);
378void detect_h2w_do_work(struct work_struct *w);
379
380void headset_ext_detect(int type);
381
382extern int switch_send_event(unsigned int bit, int on);
383
384/* notify the 3.5mm driver of events */
385int htc_35mm_remote_notify_ext_headset_irq(int insert);
386int htc_35mm_remote_notify_insert_ext_headset(int insert);
387int htc_35mm_remote_notify_microp_ready(void);
388int htc_35mm_remote_notify_button_status(int key_level);
389int htc_35mm_remote_notify_irq_enable(int enable);
390
391void hs_notify_hpin_irq(void);
392int hs_hpin_stable(void);
393
394#endif