blob: 00ed513532eb2f6c432c02b49b17034ca002fc04 [file] [log] [blame]
Flemmard65053cf2013-04-25 22:36:25 -07001/* drivers/misc/cable_detect.c - cable detect driver
2 *
3 * Copyright (C) 2009 HTC Corporation.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/interrupt.h>
19#include <linux/mfd/pmic8058.h>
20#include <linux/pmic8058-xoadc.h>
21#include <linux/platform_device.h>
22#include <linux/gpio.h>
23#include <mach/board.h>
24
25#ifdef CONFIG_RESET_BY_CABLE_IN
26#include <mach/board_htc.h>
27#endif
28
29#include <mach/cable_detect.h>
30#include <mach/mpp.h>
31#include <linux/switch.h>
32
33#ifdef CONFIG_HTC_HEADSET_MGR
34#include <mach/htc_headset_mgr.h>
35#ifdef CONFIG_HTC_HEADSET_MISC
36#include <mach/htc_headset_misc.h>
37#endif
38#endif
39
40#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
41#include "../video/msm/sii9234/TPI.h"
42#endif
43
44#include "linux/mfd/pm8xxx/pm8921-charger.h"
45
46static int vbus;
47
48static struct switch_dev dock_switch = {
49 .name = "dock",
50};
51
52struct cable_detect_info {
53 spinlock_t lock;
54
55 int vbus_mpp_gpio;
56 int vbus_mpp_irq;
57
58
59 int ad_en_active_state;
60 int ad_en_gpio;
61 int ad_en_irq;
62
63 enum usb_connect_type connect_type;
64
65 int usb_id_pin_gpio;
66 __u8 detect_type;
67 __u8 accessory_type;
68 int idpin_irq;
69 u8 mfg_usb_carkit_enable;
70 u8 mhl_reset_gpio;
71 bool mhl_version_ctrl_flag;
72 struct workqueue_struct *cable_detect_wq;
73 struct delayed_work cable_detect_work;
74 struct delayed_work vbus_detect_work;
75 struct wake_lock vbus_wlock;
76 struct wake_lock cable_detect_wlock;
77 void (*usb_uart_switch)(int);
78 void (*usb_dpdn_switch)(int);
79 struct usb_id_mpp_config_data *mpp_data;
80 void (*config_usb_id_gpios)(bool enable);
81 void (*mhl_1v2_power)(bool enable);
82 int (*is_wireless_charger)(void);
83 u8 cable_redetect;
84 int64_t (*get_adc_cb)(void);
85
86 int ac_9v_gpio;
87 void (*configure_ac_9v_gpio) (int);
88 u8 mhl_internal_3v3;
89
90 int audio_dock_lock;
91 int notify_init;
92} the_cable_info;
93
94
95#ifdef CONFIG_CABLE_DETECT_ACCESSORY
96static int cable_detect_get_adc(void);
97static int second_detect(struct cable_detect_info *pInfo);
98static void usb_id_detect_init(struct cable_detect_info *info);
99#endif
100
101static DEFINE_MUTEX(cable_notify_sem);
102static void send_cable_connect_notify(int cable_type)
103{
104 static struct t_cable_status_notifier *notifier;
105 struct cable_detect_info *pInfo = &the_cable_info;
106
107 mutex_lock(&cable_notify_sem);
108 CABLE_DEBUG("%s: cable_type = %d\n", __func__, cable_type);
109
110 if (cable_type == CONNECT_TYPE_UNKNOWN)
111 cable_type = CONNECT_TYPE_USB;
112
113 if (pInfo->ac_9v_gpio && (cable_type == CONNECT_TYPE_USB
114 || cable_type == CONNECT_TYPE_AC
115 || cable_type == CONNECT_TYPE_MHL_AC)) {
116 if (pInfo->configure_ac_9v_gpio)
117 pInfo->configure_ac_9v_gpio(1);
118
119 mdelay(5);
120 if (gpio_get_value(pInfo->ac_9v_gpio)) {
121 CABLE_INFO("%s detect 9v charger\n", __func__);
122 cable_type = CONNECT_TYPE_9V_AC;
123 }
124
125 if (pInfo->configure_ac_9v_gpio)
126 pInfo->configure_ac_9v_gpio(0);
127 }
128
129 if (cable_type > 0 && pInfo->accessory_type == DOCK_STATE_DMB) {
130 CABLE_INFO("%s: DMB presents. Disabling charge.\n", __func__);
131 cable_type = CONNECT_TYPE_CLEAR;
132 }
133
134 list_for_each_entry(notifier,
135 &g_lh_calbe_detect_notifier_list,
136 cable_notifier_link) {
137 if (notifier->func != NULL) {
138 CABLE_INFO("Send to: %s, type %d\n",
139 notifier->name, cable_type);
140
141
142 notifier->func(cable_type);
143 }
144 }
145 mutex_unlock(&cable_notify_sem);
146}
147
148int cable_detect_register_notifier(struct t_cable_status_notifier *notifier)
149{
150 if (!notifier || !notifier->name || !notifier->func)
151 return -EINVAL;
152
153 mutex_lock(&cable_notify_sem);
154 list_add(&notifier->cable_notifier_link,
155 &g_lh_calbe_detect_notifier_list);
156 if(the_cable_info.notify_init == 1)
157 notifier->func(cable_get_connect_type());
158 mutex_unlock(&cable_notify_sem);
159 return 0;
160}
161
162#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
163static DEFINE_MUTEX(usb_host_notify_sem);
164static void send_usb_host_connect_notify(int cable_in)
165{
166 struct t_usb_host_status_notifier *notifier;
167
168 mutex_lock(&usb_host_notify_sem);
169 list_for_each_entry(notifier,
170 &g_lh_usb_host_detect_notifier_list,
171 usb_host_notifier_link) {
172 if (notifier->func != NULL) {
173 CABLE_INFO("[HostNotify] Send to: %s: %d\n",
174 notifier->name, cable_in);
175
176
177 notifier->func(cable_in);
178 }
179 }
180 mutex_unlock(&usb_host_notify_sem);
181}
182
183int usb_host_detect_register_notifier(struct t_usb_host_status_notifier *notifier)
184{
185 if (!notifier || !notifier->name || !notifier->func)
186 return -EINVAL;
187
188 mutex_lock(&usb_host_notify_sem);
189 list_add(&notifier->usb_host_notifier_link,
190 &g_lh_usb_host_detect_notifier_list);
191 mutex_unlock(&usb_host_notify_sem);
192 return 0;
193}
194#endif
195
196static void check_vbus_in(struct work_struct *w)
197{
198 int vbus_in;
199 int level;
200 struct cable_detect_info *pInfo = container_of(
201 w, struct cable_detect_info, vbus_detect_work.work);
202
203 level = pm8921_is_pwr_src_plugged_in();
204 vbus_in = level;
205 CABLE_INFO("%s: vbus = %d, vbus_in = %d\n", __func__, vbus, vbus_in);
206
207#ifdef CONFIG_RESET_BY_CABLE_IN
208 reset_dflipflop();
209#endif
210
211#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
212 if (pInfo->cable_redetect) {
213 CABLE_INFO("mhl re-detect\n");
214 disable_irq_nosync(pInfo->idpin_irq);
215 queue_delayed_work(pInfo->cable_detect_wq,
216 &pInfo->cable_detect_work, ADC_DELAY);
217 }
218#endif
219
220 if (pInfo->notify_init == 0 && vbus_in == 0 && vbus == 0)
221 send_cable_connect_notify(CONNECT_TYPE_NONE);
222 if (pInfo->notify_init == 0 && vbus == vbus_in)
223 msm_otg_set_vbus_state(vbus_in);
224
225 pInfo->notify_init = 1;
226
227 if (vbus != vbus_in) {
228 vbus = vbus_in;
229
230 if(pInfo->accessory_type == DOCK_STATE_MHL) {
231 CABLE_INFO("%s: usb_uart switch, MHL cable , Do nothing\n", __func__);
232 } else {
233 if (pInfo->usb_uart_switch)
234 pInfo->usb_uart_switch(!vbus);
235 }
236
237 msm_otg_set_vbus_state(vbus_in);
238
239 if (pInfo->ad_en_gpio) {
240 if (vbus) {
241 if (pInfo->ad_en_irq)
242 CABLE_INFO("%s: Enable ad_en_irq ++\n", __func__);
243 enable_irq(pInfo->ad_en_irq);
244 } else {
245 CABLE_INFO("%s: Disable ad_en_irq --\n", __func__);
246 disable_irq_nosync(pInfo->ad_en_irq);
247 }
248 }
249 }
250 wake_unlock(&pInfo->vbus_wlock);
251}
252
253#ifdef CONFIG_CABLE_DETECT_ACCESSORY
254void release_audio_dock_lock(void)
255{
256 int value;
257 struct cable_detect_info *pInfo = &the_cable_info;
258 if(pInfo->audio_dock_lock != 1) {
259 CABLE_INFO("audio_dock_removal fucntion should not be called when audio_dock_lock != 1\n");
260 return;
261 }
262 CABLE_INFO("unlock audio dock lock\n");
263
264 pInfo->audio_dock_lock = 0;
265
266 value = gpio_get_value(pInfo->usb_id_pin_gpio);
267 irq_set_irq_type(pInfo->idpin_irq, value ? IRQF_TRIGGER_HIGH: IRQF_TRIGGER_LOW);
268 enable_irq(pInfo->idpin_irq);
269}
270EXPORT_SYMBOL(release_audio_dock_lock);
271
272static int cable_detect_get_type(struct cable_detect_info *pInfo)
273{
274 int id_pin, adc, type;
275 static int prev_type, stable_count;
276
277 if (stable_count >= ADC_RETRY)
278 stable_count = 0;
279
280 id_pin = gpio_get_value_cansleep(pInfo->usb_id_pin_gpio);
281 if (id_pin == 0 || pInfo->cable_redetect) {
282 CABLE_INFO("%s: id pin low\n", __func__);
283
284
285 adc = cable_detect_get_adc();
286
287 if (adc > -100 && adc < 100)
288 type = second_detect(pInfo);
289 else {
290 if (adc > 150 && adc < 220)
291 type = DOCK_STATE_CAR;
292 else if (adc > 370 && adc < 440)
293 type = DOCK_STATE_USB_HEADSET;
294 else if (adc > 440 && adc < 550)
295 type = DOCK_STATE_DMB;
296 else if (adc > 550 && adc < 900)
297 type = DOCK_STATE_DESK;
298 else
299 type = DOCK_STATE_UNDEFINED;
300 }
301 } else {
302 CABLE_INFO("%s: id pin high\n", __func__);
303 type = DOCK_STATE_UNDOCKED;
304 }
305
306 if (prev_type == type)
307 stable_count++;
308 else
309 stable_count = 0;
310
311 CABLE_INFO("%s prev_type %d, type %d, stable_count %d\n",
312 __func__, prev_type, type, stable_count);
313
314 prev_type = type;
315 return (stable_count >= ADC_RETRY) ? type : -2;
316}
317
318static void cable_detect_handler(struct work_struct *w)
319{
320 struct cable_detect_info *pInfo = container_of(
321 w, struct cable_detect_info, cable_detect_work.work);
322 int value;
323 int accessory_type;
324
325 if (pInfo == NULL)
326 return;
327 if(pInfo->audio_dock_lock == 1) {
328 CABLE_INFO("audio dock lock! skip cable_detect_handler\n");
329 return;
330 }
331#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
332 if (pInfo->mhl_reset_gpio != 0)
333 gpio_set_value_cansleep(pInfo->mhl_reset_gpio, 0);
334#endif
335 if (pInfo->detect_type == CABLE_TYPE_PMIC_ADC) {
336 accessory_type = cable_detect_get_type(pInfo);
337 if (accessory_type == -2) {
338 queue_delayed_work(pInfo->cable_detect_wq,
339 &pInfo->cable_detect_work, ADC_DELAY);
340 return;
341 }
342 } else
343 accessory_type = DOCK_STATE_UNDOCKED;
344
345#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
346 if (pInfo->mhl_reset_gpio != 0)
347 gpio_set_value_cansleep(pInfo->mhl_reset_gpio, 1);
348 CABLE_INFO("[MHL] Enter D3 mode\n");
349
350 if (accessory_type != DOCK_STATE_MHL)
351 D2ToD3();
352#endif
353
354 if (pInfo->accessory_type == DOCK_STATE_AUDIO_DOCK &&
355 accessory_type != DOCK_STATE_UNDEFINED &&
356 accessory_type != DOCK_STATE_UNDOCKED) {
357 CABLE_INFO("bad accessory state. from audio dock to state %d\n",accessory_type);
358 switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
359#ifdef CONFIG_HTC_HEADSET_MGR
360 headset_ext_detect(USB_NO_HEADSET);
361#endif
362 pInfo->accessory_type = DOCK_STATE_UNDOCKED;
363 }
364
365 switch (accessory_type) {
366 case DOCK_STATE_DESK:
367 CABLE_INFO("cradle inserted\n");
368 switch_set_state(&dock_switch, DOCK_STATE_DESK);
369 pInfo->accessory_type = DOCK_STATE_DESK;
370 break;
371 case DOCK_STATE_CAR:
372 CABLE_INFO("Car kit inserted\n");
373 switch_set_state(&dock_switch, DOCK_STATE_CAR);
374 pInfo->accessory_type = DOCK_STATE_CAR;
375 break;
376 case DOCK_STATE_USB_HEADSET:
377 CABLE_INFO("USB headset inserted\n");
378 pInfo->accessory_type = DOCK_STATE_USB_HEADSET;
379 if (pInfo->usb_dpdn_switch)
380 pInfo->usb_dpdn_switch(PATH_USB_AUD);
381#ifdef CONFIG_HTC_HEADSET_MGR
382 headset_ext_detect(USB_AUDIO_OUT);
383#endif
384 break;
385#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
386 case DOCK_STATE_MHL:
387 CABLE_INFO("MHL inserted\n");
388 switch_set_state(&dock_switch, DOCK_STATE_MHL);
389 pInfo->accessory_type = DOCK_STATE_MHL;
390#ifdef CONFIG_INTERNAL_CHARGING_SUPPORT
391 if (!pInfo->mhl_internal_3v3 && !vbus)
392 send_cable_connect_notify(CONNECT_TYPE_INTERNAL);
393
394#endif
395 sii9234_mhl_device_wakeup();
396 break;
397#endif
398#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
399 case DOCK_STATE_USB_HOST:
400 CABLE_INFO("USB Host inserted\n");
401 send_usb_host_connect_notify(1);
402 pInfo->accessory_type = DOCK_STATE_USB_HOST;
403 switch_set_state(&dock_switch, DOCK_STATE_USB_HOST);
404 break;
405#endif
406 case DOCK_STATE_DMB:
407 CABLE_INFO("DMB inserted\n");
408 send_cable_connect_notify(CONNECT_TYPE_CLEAR);
409 switch_set_state(&dock_switch, DOCK_STATE_DMB);
410 pInfo->accessory_type = DOCK_STATE_DMB;
411 break;
412 case DOCK_STATE_AUDIO_DOCK:
413 CABLE_INFO("Audio Dock inserted\n");
414 switch_set_state(&dock_switch, DOCK_STATE_DESK);
415 pInfo->accessory_type = DOCK_STATE_AUDIO_DOCK;
416#if 0
417#ifdef CONFIG_HTC_HEADSET_MGR
418 cable_type_value = usb_get_connect_type();
419 if (cable_type_value == CONNECT_TYPE_UNKNOWN ||
420 cable_type_value == CONNECT_TYPE_USB ||
421 cable_type_value == CONNECT_TYPE_AC) {
422 CABLE_INFO("notify auido driver in cable_detect_handler, cable type %d\n",cable_type_value);
423 pInfo->audio_dock_lock = 1;
424 headset_ext_detect(USB_AUDIO_OUT);
425 return;
426 }
427#endif
428#endif
429 break;
430 case DOCK_STATE_UNDEFINED:
431 case DOCK_STATE_UNDOCKED:
432 switch (pInfo->accessory_type) {
433 case DOCK_STATE_DESK:
434 CABLE_INFO("cradle removed\n");
435 switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
436 pInfo->accessory_type = DOCK_STATE_UNDOCKED;
437 break;
438 case DOCK_STATE_CAR:
439 CABLE_INFO("Car kit removed\n");
440 switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
441 pInfo->accessory_type = DOCK_STATE_UNDOCKED;
442 break;
443 case DOCK_STATE_USB_HEADSET:
444 CABLE_INFO("USB headset removed\n");
445#ifdef CONFIG_HTC_HEADSET_MGR
446 headset_ext_detect(USB_NO_HEADSET);
447#endif
448 if (pInfo->usb_dpdn_switch)
449 pInfo->usb_dpdn_switch(PATH_USB);
450 pInfo->accessory_type = DOCK_STATE_UNDOCKED;
451 break;
452#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
453 case DOCK_STATE_MHL:
454 CABLE_INFO("MHL removed\n");
455 switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
456 sii9234_disableIRQ();
457 break;
458#endif
459#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
460 case DOCK_STATE_USB_HOST:
461 CABLE_INFO("USB host cable removed\n");
462 pInfo->accessory_type = DOCK_STATE_UNDOCKED;
463 send_usb_host_connect_notify(0);
464 switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
465 break;
466#endif
467 case DOCK_STATE_DMB:
468 CABLE_INFO("DMB removed\n");
469 switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
470 pInfo->accessory_type = DOCK_STATE_UNDOCKED;
471 break;
472 case DOCK_STATE_AUDIO_DOCK:
473 CABLE_INFO("Audio Dock removed\n");
474 switch_set_state(&dock_switch, DOCK_STATE_UNDOCKED);
475#ifdef CONFIG_HTC_HEADSET_MGR
476 headset_ext_detect(USB_NO_HEADSET);
477#endif
478 pInfo->accessory_type = DOCK_STATE_UNDOCKED;
479 break;
480 }
481 default :
482 break;
483 }
484
485 value = gpio_get_value_cansleep(pInfo->usb_id_pin_gpio);
486 CABLE_INFO("%s ID pin %d, type %d\n", __func__,
487 value, pInfo->accessory_type);
488#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
489 if (pInfo->accessory_type == DOCK_STATE_MHL)
490 return;
491#endif
492 if (pInfo->accessory_type == DOCK_STATE_UNDOCKED)
493 irq_set_irq_type(pInfo->idpin_irq,
494 value ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
495 else
496 irq_set_irq_type(pInfo->idpin_irq, IRQF_TRIGGER_HIGH);
497
498 enable_irq(pInfo->idpin_irq);
499#if 0
500 wake_unlock(&pInfo->cable_detect_wlock);
501#endif
502}
503
504void set_mfg_usb_carkit_enable(int enable)
505{
506 the_cable_info.mfg_usb_carkit_enable = enable;
507}
508
509int cable_get_accessory_type(void)
510{
511 return the_cable_info.accessory_type;
512}
513
514static int cable_detect_get_adc(void)
515{
516 struct cable_detect_info *pInfo = &the_cable_info;
517
518 return pInfo->get_adc_cb();
519}
520
521int cable_get_usb_id_level(void)
522{
523 struct cable_detect_info *pInfo = &the_cable_info;
524
525 if (pInfo->usb_id_pin_gpio)
526 return gpio_get_value(pInfo->usb_id_pin_gpio);
527 else {
528 printk(KERN_INFO "usb id is not defined\n");
529 return 1;
530 }
531}
532
533static int second_detect(struct cable_detect_info *pInfo)
534{
535 uint32_t adc_value = 0xffffffff;
536 int type;
537
538 if (pInfo->config_usb_id_gpios)
539 pInfo->config_usb_id_gpios(1);
540
541 adc_value = cable_detect_get_adc();
542 CABLE_INFO("[2nd] accessory adc = %d\n", adc_value);
543
544 if ((pInfo->mhl_version_ctrl_flag) || (adc_value >= 776 && adc_value <= 1020))
545#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
546 type = DOCK_STATE_MHL;
547#else
548 type = DOCK_STATE_UNDEFINED;
549#endif
550 else if(adc_value >= 1021 && adc_value <= 1224)
551 type = DOCK_STATE_AUDIO_DOCK;
552 else
553#if (defined(CONFIG_USB_OTG) && defined(CONFIG_USB_OTG_HOST))
554 type = DOCK_STATE_USB_HOST;
555#else
556 type = DOCK_STATE_UNDEFINED;
557#endif
558
559 if (pInfo->config_usb_id_gpios)
560 pInfo->config_usb_id_gpios(0);
561
562 return type;
563}
564
565static int get_usb_id_adc(char *buffer, struct kernel_param *kp)
566{
567 unsigned length = 0;
568 int adc;
569
570 adc = cable_detect_get_adc();
571
572 length += sprintf(buffer, "%d\n", adc);
573
574 return length;
575}
576module_param_call(usb_id_adc, NULL, get_usb_id_adc, NULL, 0664);
577
578static ssize_t dock_status_show(struct device *dev,
579 struct device_attribute *attr, char *buf)
580{
581 struct cable_detect_info *pInfo = &the_cable_info;
582
583 if (pInfo->accessory_type == DOCK_STATE_DESK || pInfo->accessory_type == DOCK_STATE_AUDIO_DOCK)
584 return sprintf(buf, "online\n");
585 else if (pInfo->accessory_type == 3)
586 return sprintf(buf, "online\n");
587 else
588 return sprintf(buf, "offline\n");
589}
590static DEVICE_ATTR(status, S_IRUGO | S_IWUSR, dock_status_show, NULL);
591
592static irqreturn_t usbid_interrupt(int irq, void *data)
593{
594 struct cable_detect_info *pInfo = (struct cable_detect_info *)data;
595
596 disable_irq_nosync(pInfo->idpin_irq);
597
598 CABLE_INFO("usb: id interrupt\n");
599 pInfo->cable_redetect = 0;
600 queue_delayed_work(pInfo->cable_detect_wq,
601 &pInfo->cable_detect_work, ADC_DELAY);
602 wake_lock_timeout(&pInfo->cable_detect_wlock, HZ*2);
603 return IRQ_HANDLED;
604}
605
606static void usb_id_detect_init(struct cable_detect_info *pInfo)
607{
608 int ret;
609 CABLE_INFO("%s: id pin %d\n", __func__,
610 pInfo->usb_id_pin_gpio);
611
612 if (pInfo->usb_id_pin_gpio == 0)
613 return;
614 ret = gpio_request(pInfo->usb_id_pin_gpio, "USBID_GPIO");
615 if (ret) {
616 CABLE_ERR("%s: request id gpio failed\n", __func__);
617 return;
618 }
619
620 if (pInfo->config_usb_id_gpios)
621 pInfo->config_usb_id_gpios(0);
622
623 if (pInfo->idpin_irq == 0)
624 pInfo->idpin_irq = gpio_to_irq(pInfo->usb_id_pin_gpio);
625
626 set_irq_flags(pInfo->idpin_irq, IRQF_VALID | IRQF_NOAUTOEN);
627 ret = request_any_context_irq(pInfo->idpin_irq, usbid_interrupt,
628 IRQF_TRIGGER_LOW, "idpin_irq", pInfo);
629 if (ret < 0) {
630 CABLE_ERR("%s: request_irq failed\n", __func__);
631 return;
632 }
633
634 ret = enable_irq_wake(pInfo->idpin_irq);
635 if (ret < 0) {
636 CABLE_ERR("%s: set_irq_wake failed\n", __func__);
637 goto err;
638 }
639
640 enable_irq(pInfo->idpin_irq);
641 return;
642err:
643 free_irq(pInfo->idpin_irq, 0);
644}
645
646#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
647static void mhl_status_notifier_func(bool isMHL, int charging_type)
648{
649 struct cable_detect_info *pInfo = &the_cable_info;
650 int id_pin = gpio_get_value_cansleep(pInfo->usb_id_pin_gpio);
651 static uint8_t mhl_connected;
652
653 CABLE_INFO("%s: isMHL %d, charging type %d, id_pin %d\n",
654 __func__, isMHL, charging_type, id_pin);
655 if (pInfo->accessory_type != DOCK_STATE_MHL) {
656 CABLE_INFO("%s: accessory is not MHL, type %d\n",
657 __func__, pInfo->accessory_type);
658 return;
659 }
660
661#ifdef CONFIG_HTC_HEADSET_MISC
662 headset_mhl_audio_jack_enable(isMHL);
663#endif
664
665 if (!isMHL) {
666 CABLE_INFO("MHL removed\n");
667 sii9234_disableIRQ();
668
669 if (pInfo->usb_dpdn_switch)
670 pInfo->usb_dpdn_switch(PATH_USB);
671
672 if (pInfo->mhl_1v2_power)
673 pInfo->mhl_1v2_power(0);
674#ifdef CONFIG_INTERNAL_CHARGING_SUPPORT
675 send_cable_connect_notify(CONNECT_TYPE_CLEAR);
676#endif
677#ifdef MHL_REDETECT
678 if (mhl_connected == 0) {
679 CABLE_INFO("MHL re-detect\n");
680 set_irq_type(pInfo->idpin_irq,
681 id_pin ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
682 pInfo->cable_redetect = 1;
683 }
684#endif
685 mhl_connected = 0;
686
687 pInfo->accessory_type = DOCK_STATE_UNDOCKED;
688 sii9234_disableIRQ();
689 enable_irq(pInfo->idpin_irq);
690 return;
691 } else {
692 mhl_connected = 1;
693 set_irq_type(pInfo->idpin_irq,
694 id_pin ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
695#ifdef CONFIG_INTERNAL_CHARGING_SUPPORT
696 if (charging_type == CONNECT_TYPE_INTERNAL)
697 charging_type = CONNECT_TYPE_NONE;
698 send_cable_connect_notify(charging_type);
699#else
700 send_cable_connect_notify(charging_type);
701#endif
702#if 0
703#ifdef CONFIG_INTERNAL_CHARGING_SUPPORT
704 else if (vbus)
705 send_cable_connect_notify(CONNECT_TYPE_USB);
706#endif
707#endif
708 }
709}
710
711static struct t_mhl_status_notifier mhl_status_notifier = {
712 .name = "mhl_detect",
713 .func = mhl_status_notifier_func,
714};
715#endif
716#endif
717
718
719static ssize_t vbus_status_show(struct device *dev,
720 struct device_attribute *attr, char *buf)
721{
722 int level, vbus_in;
723
724 level = pm8921_is_usb_chg_plugged_in();
725 vbus_in = level;
726 CABLE_INFO("%s: vbus state = %d\n", __func__, vbus_in);
727 return sprintf(buf, "%d\n", vbus_in);
728}
729static DEVICE_ATTR(vbus, S_IRUGO | S_IWUSR, vbus_status_show, NULL);
730
731#ifdef CONFIG_CABLE_DETECT_ACCESSORY
732static ssize_t adc_status_show(struct device *dev,
733 struct device_attribute *attr, char *buf)
734{
735 int adc;
736
737 adc = cable_detect_get_adc();
738 CABLE_INFO("%s: ADC = %d\n", __func__, adc);
739 return sprintf(buf, "%d\n", adc);
740}
741static DEVICE_ATTR(adc, S_IRUGO | S_IWUSR, adc_status_show, NULL);
742
743static ssize_t dmb_wakeup_store(struct device *dev,
744 struct device_attribute *attr,
745 const char *buf, size_t count)
746{
747 struct cable_detect_info *pInfo = &the_cable_info;
748 uint32_t wakeup;
749
750 if (pInfo->accessory_type != DOCK_STATE_DMB) {
751 CABLE_INFO("%s: DMB not exist. Do nothing.\n", __func__);
752 return count;
753 }
754
755 sscanf(buf, "%d", &wakeup);
756 CABLE_DEBUG("%s: wakeup = %d\n", __func__, wakeup);
757 if (!!wakeup) {
758 disable_irq_nosync(pInfo->idpin_irq);
759
760 gpio_direction_output(pInfo->usb_id_pin_gpio, 0);
761 msleep(1);
762 gpio_direction_output(pInfo->usb_id_pin_gpio, 1);
763 msleep(10);
764 gpio_direction_output(pInfo->usb_id_pin_gpio, 0);
765 msleep(1);
766
767 gpio_direction_input(pInfo->usb_id_pin_gpio);
768 enable_irq(pInfo->idpin_irq);
769 }
770 CABLE_INFO("%s(parent:%s): request DMB wakeup done.\n",
771 current->comm, current->parent->comm);
772
773 return count;
774}
775
776static DEVICE_ATTR(dmb_wakeup, S_IRUGO | S_IWUSR, NULL, dmb_wakeup_store);
777static ssize_t unlock_audio_dock_lock_store(struct device *dev,
778 struct device_attribute *attr,
779 const char *buf, size_t count)
780{
781 uint32_t unlock;
782
783 sscanf(buf, "%d", &unlock);
784 CABLE_DEBUG("%s: unlock = %d\n", __func__, unlock);
785 if (!!unlock)
786 release_audio_dock_lock();
787
788 return count;
789}
790
791static DEVICE_ATTR(unlock_audio_dock_lock, S_IRUGO | S_IWUSR, NULL, unlock_audio_dock_lock_store);
792
793#endif
794
795int cable_get_connect_type(void)
796{
797 struct cable_detect_info *pInfo = &the_cable_info;
798
799 return pInfo->connect_type;
800}
801
802static irqreturn_t ad_en_irq_handler(int irq, void *data)
803{
804 unsigned long flags;
805 struct cable_detect_info *pInfo = &the_cable_info;
806
807 disable_irq_nosync(pInfo->ad_en_irq);
808 CABLE_INFO("%s: Disable ad_en_irq --\n", __func__);
809 spin_lock_irqsave(&pInfo->lock, flags);
810 queue_delayed_work(pInfo->cable_detect_wq,
811 &pInfo->vbus_detect_work, HZ/10);
812 spin_unlock_irqrestore(&pInfo->lock, flags);
813#if 1
814 wake_lock_timeout(&pInfo->vbus_wlock, HZ*2);
815#endif
816
817 return IRQ_HANDLED;
818}
819
820static int cd_pmic_request_irq(unsigned int gpio, unsigned int *irq,
821 irq_handler_t handler, unsigned long flags,
822 const char *name, unsigned int wake)
823{
824 int ret = 0;
825
826 ret = gpio_request(gpio, name);
827 if (ret < 0)
828 return ret;
829
830 ret = gpio_direction_input(gpio);
831 if (ret < 0) {
832 gpio_free(gpio);
833 return ret;
834 }
835
836 if (!(*irq)) {
837 ret = gpio_to_irq(gpio);
838 if (ret < 0) {
839 gpio_free(gpio);
840 return ret;
841 }
842 *irq = (unsigned int) ret;
843 }
844
845 ret = request_any_context_irq(*irq, handler, flags, name, NULL);
846 if (ret < 0) {
847 gpio_free(gpio);
848 return ret;
849 }
850
851 ret = irq_set_irq_wake(*irq, wake);
852 if (ret < 0) {
853 free_irq(*irq, 0);
854 gpio_free(gpio);
855 return ret;
856 }
857
858 return 1;
859}
860
861static int cable_detect_probe(struct platform_device *pdev)
862{
863 int ret;
864 struct cable_detect_platform_data *pdata = pdev->dev.platform_data;
865 struct cable_detect_info *pInfo = &the_cable_info;
866
867 spin_lock_init(&the_cable_info.lock);
868
869 if (pdata) {
870 pInfo->vbus_mpp_gpio = pdata->vbus_mpp_gpio;
871 pInfo->vbus_mpp_irq = pdata->vbus_mpp_irq;
872 pInfo->ad_en_active_state = pdata->ad_en_active_state;
873 pInfo->ad_en_gpio = pdata->ad_en_gpio;
874 pInfo->ad_en_irq = pdata->ad_en_irq;
875 pInfo->usb_uart_switch = pdata->usb_uart_switch;
876 pInfo->usb_dpdn_switch = pdata->usb_dpdn_switch;
877 if (pInfo->usb_dpdn_switch)
878 pInfo->usb_dpdn_switch(PATH_USB);
879 pInfo->ac_9v_gpio = pdata->ac_9v_gpio;
880 pInfo->configure_ac_9v_gpio = pdata->configure_ac_9v_gpio;
881 pInfo->mhl_internal_3v3 = pdata->mhl_internal_3v3;
882
883#ifdef CONFIG_CABLE_DETECT_ACCESSORY
884 pInfo->detect_type = pdata->detect_type;
885 pInfo->usb_id_pin_gpio = pdata->usb_id_pin_gpio;
886 pInfo->mhl_reset_gpio = pdata->mhl_reset_gpio;
887 pInfo->mpp_data = &pdata->mpp_data;
888 pInfo->config_usb_id_gpios = pdata->config_usb_id_gpios;
889 pInfo->mhl_version_ctrl_flag = pdata->mhl_version_ctrl_flag;
890 pInfo->mhl_1v2_power = pdata->mhl_1v2_power;
891 pInfo->get_adc_cb = pdata->get_adc_cb;
892
893#endif
894
895 if (pdata->is_wireless_charger)
896 pInfo->is_wireless_charger = pdata->is_wireless_charger;
897#ifdef CONFIG_CABLE_DETECT_ACCESSORY
898 INIT_DELAYED_WORK(&pInfo->cable_detect_work, cable_detect_handler);
899#endif
900 INIT_DELAYED_WORK(&pInfo->vbus_detect_work, check_vbus_in);
901
902 pInfo->cable_detect_wq = create_singlethread_workqueue("cable_detect");
903 if (pInfo->cable_detect_wq == 0) {
904 CABLE_ERR("usb: fail to create workqueue\n");
905 return -ENOMEM;
906 }
907
908 if (pdata->vbus_mpp_config)
909 pdata->vbus_mpp_config();
910
911 wake_lock_init(&pInfo->vbus_wlock,
912 WAKE_LOCK_SUSPEND, "vbus_lock");
913
914 wake_lock_init(&pInfo->cable_detect_wlock,
915 WAKE_LOCK_SUSPEND, "cable_detect_lock");
916
917 if (pdata->ad_en_gpio) {
918 ret = cd_pmic_request_irq(pdata->ad_en_gpio,
919 &pdata->ad_en_irq, ad_en_irq_handler,
920 pdata->ad_en_active_state ?
921 IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING,
922 "ad_en_irq", 1);
923 if (ret < 0) {
924 printk("Failed to request PMIC AD_EN IRQ (0x%X)", ret);
925 } else
926 disable_irq(pdata->ad_en_irq);
927 }
928 }
929 if (switch_dev_register(&dock_switch) < 0) {
930 CABLE_ERR("fail to register dock switch!\n");
931 return 0;
932 }
933
934 ret = device_create_file(dock_switch.dev, &dev_attr_vbus);
935 if (ret != 0)
936 CABLE_ERR("dev_attr_vbus failed\n");
937
938#ifdef CONFIG_CABLE_DETECT_ACCESSORY
939 ret = device_create_file(dock_switch.dev, &dev_attr_status);
940 if (ret != 0)
941 CABLE_ERR("dev_attr_status failed\n");
942
943 ret = device_create_file(dock_switch.dev, &dev_attr_adc);
944 if (ret != 0)
945 CABLE_ERR("dev_attr_adc failed\n");
946
947 ret = device_create_file(dock_switch.dev, &dev_attr_dmb_wakeup);
948 if (ret != 0)
949 CABLE_ERR("dev_attr_dmb_wakeup failed\n");
950
951 ret = device_create_file(dock_switch.dev, &dev_attr_unlock_audio_dock_lock);
952 if (ret != 0)
953 CABLE_ERR("dev_attr_unlock_audio_dock_lock failed\n");
954
955 usb_id_detect_init(pInfo);
956#endif
957
958 return 0;
959}
960
961#ifdef CONFIG_KDDI_ADAPTER
962#define VBUS_DEBOUNCE_TIME 500
963#define MSPERIOD(end, start) ktime_to_ms(ktime_sub(end, start))
964#endif
965irqreturn_t cable_detection_vbus_irq_handler(void)
966{
967 unsigned long flags;
968#ifdef CONFIG_KDDI_ADAPTER
969 static int previous_vbus = -1,current_vbus = -1;
970 static int firstdrop = 0;
971 static ktime_t end_ktime;
972 static ktime_t cable_remove_ktime;
973 s64 diff = 0;
974#endif
975 struct cable_detect_info *pInfo = &the_cable_info;
976
977 CABLE_INFO("%s\n", __func__);
978#ifdef CONFIG_KDDI_ADAPTER
979 if (previous_vbus == -1)
980 previous_vbus = current_vbus = pm8921_is_pwr_src_plugged_in();
981 else {
982 current_vbus = pm8921_is_pwr_src_plugged_in();
983 if(previous_vbus == 1 && current_vbus == 0) {
984 cable_remove_ktime = ktime_get();
985 firstdrop = 1;
986 } else if (previous_vbus == 0 && current_vbus == 1 && firstdrop == 1) {
987 end_ktime = ktime_get();
988 diff = MSPERIOD(end_ktime, cable_remove_ktime);
989 printk("=============diff %lld\n",diff);
990 if (diff < VBUS_DEBOUNCE_TIME) {
991 spin_lock_irqsave(&pInfo->lock, flags);
992 __cancel_delayed_work(&pInfo->vbus_detect_work);
993 spin_unlock_irqrestore(&pInfo->lock, flags);
994 previous_vbus = current_vbus;
995 printk("==========cancel pending\n");
996 return IRQ_HANDLED;
997 }
998 }
999 previous_vbus = current_vbus;
1000 }
1001 CABLE_INFO("%s go\n", __func__);
1002#endif
1003
1004 spin_lock_irqsave(&pInfo->lock, flags);
1005#ifdef CONFIG_KDDI_ADAPTER
1006 queue_delayed_work(pInfo->cable_detect_wq,
1007 &pInfo->vbus_detect_work, HZ / 2);
1008#else
1009 queue_delayed_work(pInfo->cable_detect_wq,
1010 &pInfo->vbus_detect_work, HZ/10);
1011#endif
1012 spin_unlock_irqrestore(&pInfo->lock, flags);
1013#if 1
1014 wake_lock_timeout(&pInfo->vbus_wlock, HZ*2);
1015#endif
1016
1017 CABLE_INFO("%s --\n", __func__);
1018 return IRQ_HANDLED;
1019}
1020EXPORT_SYMBOL(cable_detection_vbus_irq_handler);
1021
1022struct platform_driver cable_detect_driver = {
1023 .probe = cable_detect_probe,
1024
1025 .driver = {
1026 .name = "cable_detect",
1027 .owner = THIS_MODULE,
1028 },
1029};
1030
1031static void usb_status_notifier_func(int cable_type)
1032{
1033 struct cable_detect_info*pInfo = &the_cable_info;
1034
1035 CABLE_INFO("%s: cable_type = %d\n", __func__, cable_type);
1036
1037
1038 if(pInfo->audio_dock_lock == 0 && (cable_type == CONNECT_TYPE_USB || cable_type == CONNECT_TYPE_AC || cable_type == CONNECT_TYPE_MHL_AC))
1039 if(pInfo->accessory_type == DOCK_STATE_AUDIO_DOCK) {
1040#ifdef CONFIG_HTC_HEADSET_MGR
1041 CABLE_INFO("notify auido driver in usb_status_notifier_func\n");
1042 pInfo->audio_dock_lock = 1;
1043
1044 cancel_delayed_work_sync(&pInfo->cable_detect_work);
1045 if (pInfo->accessory_type == DOCK_STATE_AUDIO_DOCK)
1046 headset_ext_detect(USB_AUDIO_OUT);
1047 else {
1048 CABLE_INFO("latest accessory type is %d, stop to notify audio dock\n",pInfo->accessory_type);
1049 pInfo->audio_dock_lock = 0;
1050 }
1051#endif
1052 }
1053
1054 if (cable_type > CONNECT_TYPE_NONE) {
1055 if (pInfo->ad_en_gpio) {
1056 if (gpio_get_value(pInfo->ad_en_gpio) ==
1057 pInfo->ad_en_active_state)
1058 cable_type = CONNECT_TYPE_WIRELESS;
1059 } else if (pInfo->is_wireless_charger) {
1060 if (pInfo->is_wireless_charger())
1061 cable_type = CONNECT_TYPE_WIRELESS;
1062 }
1063 }
1064
1065#ifdef CONFIG_FB_MSM_HDMI_MHL_SII9234
1066#ifdef CONFIG_INTERNAL_CHARGING_SUPPORT
1067 if (!pInfo->mhl_internal_3v3 &&
1068 pInfo->accessory_type == DOCK_STATE_MHL) {
1069 CABLE_INFO("%s: MHL detected. Do nothing\n", __func__);
1070 return;
1071 }
1072#endif
1073#endif
1074 pInfo->connect_type = cable_type;
1075 send_cable_connect_notify(cable_type);
1076
1077}
1078
1079static struct t_usb_status_notifier usb_status_notifier = {
1080 .name = "cable_detect",
1081 .func = usb_status_notifier_func,
1082};
1083
1084static int __init cable_detect_init(void)
1085{
1086 vbus = 0;
1087 the_cable_info.connect_type = CONNECT_TYPE_NONE;
1088 htc_usb_register_notifier(&usb_status_notifier);
1089#if (defined(CONFIG_CABLE_DETECT_ACCESSORY) && defined(CONFIG_FB_MSM_HDMI_MHL_SII9234))
1090 mhl_detect_register_notifier(&mhl_status_notifier);
1091#endif
1092 return platform_driver_register(&cable_detect_driver);
1093
1094}
1095
1096static void __exit cable_detect_exit(void)
1097{
1098 platform_driver_unregister(&cable_detect_driver);
1099}
1100
1101MODULE_DESCRIPTION("CABLE_DETECT");
1102MODULE_LICENSE("GPL");
1103
1104module_init(cable_detect_init);
1105module_exit(cable_detect_exit);