import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / accdet / mt8127 / accdet.c
CommitLineData
6fa3eb70
S
1#include "accdet.h"
2
3//#include <mach/mt_boot.h>
4#include <cust_eint.h>
5#include <cust_gpio_usage.h>
6#include <mach/mt_gpio.h>
7#include <mach/eint.h>
8
9
10#define SW_WORK_AROUND_ACCDET_REMOTE_BUTTON_ISSUE
11#define DEBUG_THREAD 1
12
13/*----------------------------------------------------------------------
14static variable defination
15----------------------------------------------------------------------*/
16
17#define REGISTER_VALUE(x) (x - 1)
18
19
20static int button_press_debounce = 0x400;
21
22static int debug_enable = 1;
23
24struct headset_mode_settings *cust_headset_settings = NULL;
25
26#define ACCDET_DEBUG(format, args...) do{ \
27 if(debug_enable) \
28 {\
29 printk(KERN_WARNING format,##args);\
30 }\
31}while(0)
32
33static struct switch_dev accdet_data;
34static struct input_dev *kpd_accdet_dev;
35static struct cdev *accdet_cdev;
36static struct class *accdet_class = NULL;
37static struct device *accdet_nor_device = NULL;
38
39static dev_t accdet_devno;
40
41static int pre_status = 0;
42static int pre_state_swctrl = 0;
43static int accdet_status = PLUG_OUT;
44static int cable_type = 0;
45#if defined ACCDET_EINT && defined ACCDET_PIN_RECOGNIZATION
46//add for new feature PIN recognition
47static int cable_pin_recognition = 0;
48static int show_icon_delay = 0;
49#endif
50
51//ALPS443614: EINT trigger during accdet irq flow running, need add sync method
52//between both
53static int eint_accdet_sync_flag = 0;
54
55static s64 long_press_time_ns = 0 ;
56
57static int g_accdet_first = 1;
58static bool IRQ_CLR_FLAG = FALSE;
59static volatile int call_status =0;
60static volatile int button_status = 0;
61
62
63struct wake_lock accdet_suspend_lock;
64struct wake_lock accdet_irq_lock;
65struct wake_lock accdet_key_lock;
66struct wake_lock accdet_timer_lock;
67
68
69static struct work_struct accdet_work;
70static struct workqueue_struct * accdet_workqueue = NULL;
71
72static int long_press_time;
73
74static DEFINE_MUTEX(accdet_eint_irq_sync_mutex);
75
76static inline void clear_accdet_interrupt(void);
77
78#ifdef ACCDET_EINT
79
80#ifndef ACCDET_MULTI_KEY_FEATURE
81static int g_accdet_working_in_suspend =0;
82#endif
83
84static struct work_struct accdet_eint_work;
85static struct workqueue_struct * accdet_eint_workqueue = NULL;
86
87static inline void accdet_init(void);
88
89
90#ifdef ACCDET_LOW_POWER
91
92#include <linux/timer.h>
93#define MICBIAS_DISABLE_TIMER (6 *HZ) //6 seconds
94struct timer_list micbias_timer;
95static void disable_micbias(unsigned long a);
96/* Used to let accdet know if the pin has been fully plugged-in */
97#define EINT_PIN_PLUG_IN (1)
98#define EINT_PIN_PLUG_OUT (0)
99int cur_eint_state = EINT_PIN_PLUG_OUT;
100static struct work_struct accdet_disable_work;
101static struct workqueue_struct * accdet_disable_workqueue = NULL;
102
103#endif
104
105#endif//end ACCDET_EINT
106
107extern S32 pwrap_read( U32 adr, U32 *rdata );
108extern S32 pwrap_write( U32 adr, U32 wdata );
109extern struct headset_mode_settings* get_cust_headset_settings(void);
110extern struct headset_key_custom* get_headset_key_custom_setting(void);
111extern int PMIC_IMM_GetOneChannelValue(int dwChannel, int deCount, int trimd);
112extern struct file_operations *accdet_get_fops(void);//from accdet_drv.c
113extern struct platform_driver accdet_driver_func(void);//from accdet_drv.c
114
115#ifdef DEBUG_THREAD
116extern void accdet_create_attr_func(void); //from accdet_drv.c
117#endif
118static U32 pmic_pwrap_read(U32 addr);
119static void pmic_pwrap_write(U32 addr, unsigned int wdata);
120
121
122/****************************************************************/
123/*** export function **/
124/****************************************************************/
125
126void accdet_detect(void)
127{
128 int ret = 0 ;
129
130 ACCDET_DEBUG("[Accdet]accdet_detect\n");
131
132 accdet_status = PLUG_OUT;
133 ret = queue_work(accdet_workqueue, &accdet_work);
134 if(!ret)
135 {
136 ACCDET_DEBUG("[Accdet]accdet_detect:accdet_work return:%d!\n", ret);
137 }
138
139 return;
140}
141EXPORT_SYMBOL(accdet_detect);
142
143void accdet_state_reset(void)
144{
145
146 ACCDET_DEBUG("[Accdet]accdet_state_reset\n");
147
148 accdet_status = PLUG_OUT;
149 cable_type = NO_DEVICE;
150
151 return;
152}
153EXPORT_SYMBOL(accdet_state_reset);
154
155int accdet_get_cable_type(void)
156{
157 return cable_type;
158}
159void accdet_auxadc_switch(int enable)
160{
161 if (enable) {
162 #ifndef ACCDET_28V_MODE
163 pmic_pwrap_write(ACCDET_RSV, ACCDET_1V9_MODE_ON);
164 ACCDET_DEBUG("ACCDET enable switch in 1.9v mode \n");
165 #else
166 #ifdef CONFIG_MTK_PMIC_MT6397
167 pmic_pwrap_write(0x732, ACCDET_2V8_MODE_ON);
168 #else
169 pmic_pwrap_write(ACCDET_RSV, ACCDET_2V8_MODE_ON);
170 #endif
171 ACCDET_DEBUG("ACCDET enable switch in 2.8v mode \n");
172 #endif
173 }else {
174 #ifndef ACCDET_28V_MODE
175 pmic_pwrap_write(ACCDET_RSV, ACCDET_1V9_MODE_OFF);
176 ACCDET_DEBUG("ACCDET diable switch in 1.9v mode \n");
177 #else
178 #ifdef CONFIG_MTK_PMIC_MT6397
179 pmic_pwrap_write(0x732, 0);
180 #else
181 pmic_pwrap_write(ACCDET_RSV, ACCDET_2V8_MODE_OFF);
182 #endif
183 ACCDET_DEBUG("ACCDET diable switch in 2.8v mode \n");
184 #endif
185 }
186
187}
188
189/****************************************************************/
190/*******static function defination **/
191/****************************************************************/
192// pmic wrap read and write func
193static U32 pmic_pwrap_read(U32 addr)
194{
195
196 U32 val =0;
197 pwrap_read(addr, &val);
198 //ACCDET_DEBUG("[Accdet]wrap write func addr=0x%x, val=0x%x\n", addr, val);
199 return val;
200
201}
202
203static void pmic_pwrap_write(unsigned int addr, unsigned int wdata)
204
205{
206 pwrap_write(addr, wdata);
207 //ACCDET_DEBUG("[Accdet]wrap write func addr=0x%x, wdate=0x%x\n", addr, wdata);
208}
209#ifndef ACCDET_MULTI_KEY_FEATURE
210//detect if remote button is short pressed or long pressed
211static bool is_long_press(void)
212{
213 int current_status = 0;
214 int index = 0;
215 int count = long_press_time / 100;
216 while(index++ < count)
217 {
218 current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0)>>6);
219 if(current_status != 0)
220 {
221 return false;
222 }
223
224 msleep(100);
225 }
226
227 return true;
228}
229#endif
230#ifdef ACCDET_PIN_RECOGNIZATION
231static void headset_standard_judge_message(void)
232{
233 ACCDET_DEBUG("[Accdet]Dear user: You plug in a headset which this phone doesn't support!!\n");
234
235}
236#endif
237
238#ifdef ACCDET_PIN_SWAP
239
240static void accdet_FSA8049_enable(void)
241{
242#ifndef MTK_ALPS_BOX_SUPPORT
243 mt_set_gpio_mode(GPIO_FSA8049_PIN, GPIO_FSA8049_PIN_M_GPIO);
244 mt_set_gpio_dir(GPIO_FSA8049_PIN, GPIO_DIR_OUT);
245 mt_set_gpio_out(GPIO_FSA8049_PIN, GPIO_OUT_ONE);
246#endif
247}
248
249static void accdet_FSA8049_disable(void)
250{
251#ifndef MTK_ALPS_BOX_SUPPORT
252 mt_set_gpio_mode(GPIO_FSA8049_PIN, GPIO_FSA8049_PIN_M_GPIO);
253 mt_set_gpio_dir(GPIO_FSA8049_PIN, GPIO_DIR_OUT);
254 mt_set_gpio_out(GPIO_FSA8049_PIN, GPIO_OUT_ZERO);
255#endif
256}
257
258
259#endif
260static void inline headset_plug_out(void)
261{
262 accdet_status = PLUG_OUT;
263 cable_type = NO_DEVICE;
264 //update the cable_type
265 switch_set_state((struct switch_dev *)&accdet_data, cable_type);
266 ACCDET_DEBUG( " [accdet] set state in cable_type = NO_DEVICE\n");
267
268}
269
270//Accdet only need this func
271static void inline enable_accdet(u32 state_swctrl)
272{
273 // enable ACCDET unit
274 ACCDET_DEBUG("accdet: enable_accdet\n");
275 //enable clock
276 pmic_pwrap_write(TOP_CKPDN_CLR, RG_ACCDET_CLK_CLR);
277
278 pmic_pwrap_write(ACCDET_STATE_SWCTRL, pmic_pwrap_read(ACCDET_STATE_SWCTRL)|state_swctrl);
279 pmic_pwrap_write(ACCDET_CTRL, ACCDET_ENABLE);
280
281
282}
283
284#ifdef ACCDET_EINT
285static void inline disable_accdet(void)
286{
287 int irq_temp = 0;
288 //sync with accdet_irq_handler set clear accdet irq bit to avoid set clear accdet irq bit after disable accdet
289
290 //disable accdet irq
291 pmic_pwrap_write(INT_CON_ACCDET_CLR, RG_ACCDET_IRQ_CLR);
292 clear_accdet_interrupt();
293 udelay(200);
294 mutex_lock(&accdet_eint_irq_sync_mutex);
295 while(pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT)
296 {
297 ACCDET_DEBUG("[Accdet]check_cable_type: Clear interrupt on-going....\n");
298 msleep(5);
299 }
300 irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS);
301 irq_temp = irq_temp & (~IRQ_CLR_BIT);
302 pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp);
303 ACCDET_DEBUG("[Accdet]disable_accdet:Clear interrupt:Done[0x%x]!\n", pmic_pwrap_read(ACCDET_IRQ_STS));
304 mutex_unlock(&accdet_eint_irq_sync_mutex);
305 // disable ACCDET unit
306 ACCDET_DEBUG("accdet: disable_accdet\n");
307 pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL);
308
309 pmic_pwrap_write(ACCDET_CTRL, ACCDET_DISABLE);
310 pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0);
311//disable clock
312 pmic_pwrap_write(TOP_CKPDN_SET, RG_ACCDET_CLK_SET);
313}
314static void disable_micbias(unsigned long a)
315{
316 int ret = 0;
317 ret = queue_work(accdet_disable_workqueue, &accdet_disable_work);
318 if(!ret)
319 {
320 ACCDET_DEBUG("[Accdet]disable_micbias:accdet_work return:%d!\n", ret);
321 }
322}
323static void disable_micbias_callback(struct work_struct *work)
324{
325
326 if(cable_type == HEADSET_NO_MIC) {
327 #ifdef ACCDET_PIN_RECOGNIZATION
328 show_icon_delay = 0;
329 cable_pin_recognition = 0;
330 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition);
331 pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width);
332 pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_thresh);
333 #endif
334 // setting pwm idle;
335 #ifdef ACCDET_MULTI_KEY_FEATURE
336 pmic_pwrap_write(ACCDET_STATE_SWCTRL, pmic_pwrap_read(ACCDET_STATE_SWCTRL)&~ACCDET_SWCTRL_IDLE_EN);
337 #endif
338 #ifdef ACCDET_PIN_SWAP
339 //accdet_FSA8049_disable(); //disable GPIO209 for PIN swap
340 //ACCDET_DEBUG("[Accdet] FSA8049 disable!\n");
341 #endif
342 disable_accdet();
343 ACCDET_DEBUG("[Accdet] more than 5s MICBIAS : Disabled\n");
344 }
345 #ifdef ACCDET_PIN_RECOGNIZATION
346 else if(cable_type == HEADSET_MIC) {
347 pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width);
348 pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_thresh);
349 ACCDET_DEBUG("[Accdet]pin recog after 5s recover micbias polling!\n");
350 }
351 #endif
352}
353
354static void accdet_eint_work_callback(struct work_struct *work)
355{
356#ifndef MTK_ALPS_BOX_SUPPORT
357 //KE under fastly plug in and plug out
358 mt_eint_mask(CUST_EINT_ACCDET_NUM);
359#endif
360
361 if (cur_eint_state == EINT_PIN_PLUG_IN) {
362 ACCDET_DEBUG("[Accdet]EINT func :plug-in\n");
363 mutex_lock(&accdet_eint_irq_sync_mutex);
364 eint_accdet_sync_flag = 1;
365 mutex_unlock(&accdet_eint_irq_sync_mutex);
366 #ifdef ACCDET_LOW_POWER
367 wake_lock_timeout(&accdet_timer_lock, 7*HZ);
368 #endif
369 #ifdef ACCDET_28V_MODE
370 pmic_pwrap_write(ACCDET_RSV, ACCDET_2V8_MODE_OFF);
371 ACCDET_DEBUG("ACCDET use in 2.8V mode!! \n");
372 #endif
373 #ifdef ACCDET_PIN_SWAP
374 pmic_pwrap_write(0x0400, pmic_pwrap_read(0x0400)|(1<<14));
375 msleep(800);
376 accdet_FSA8049_enable(); //enable GPIO209 for PIN swap
377 ACCDET_DEBUG("[Accdet] FSA8049 enable!\n");
378 msleep(250); //PIN swap need ms
379 #endif
380
381 accdet_init();// do set pwm_idle on in accdet_init
382
383 #ifdef ACCDET_PIN_RECOGNIZATION
384 show_icon_delay = 1;
385 //micbias always on during detected PIN recognition
386 pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width);
387 pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_width);
388 ACCDET_DEBUG("[Accdet]pin recog start! micbias always on!\n");
389 #endif
390 //set PWM IDLE on
391 #ifdef ACCDET_MULTI_KEY_FEATURE
392 pmic_pwrap_write(ACCDET_STATE_SWCTRL, (pmic_pwrap_read(ACCDET_STATE_SWCTRL)|ACCDET_SWCTRL_IDLE_EN));
393 #endif
394 //enable ACCDET unit
395 enable_accdet(ACCDET_SWCTRL_EN);
396 } else {
397//EINT_PIN_PLUG_OUT
398//Disable ACCDET
399 ACCDET_DEBUG("[Accdet]EINT func :plug-out\n");
400 mutex_lock(&accdet_eint_irq_sync_mutex);
401 eint_accdet_sync_flag = 0;
402 mutex_unlock(&accdet_eint_irq_sync_mutex);
403
404 #ifdef ACCDET_LOW_POWER
405 del_timer_sync(&micbias_timer);
406 #endif
407 #ifdef ACCDET_PIN_RECOGNIZATION
408 show_icon_delay = 0;
409 cable_pin_recognition = 0;
410 #endif
411 #ifdef ACCDET_PIN_SWAP
412 pmic_pwrap_write(0x0400, pmic_pwrap_read(0x0400)&~(1<<14));
413 accdet_FSA8049_disable(); //disable GPIO209 for PIN swap
414 ACCDET_DEBUG("[Accdet] FSA8049 disable!\n");
415 #endif
416 accdet_auxadc_switch(0);
417 disable_accdet();
418 headset_plug_out();
419 #ifdef ACCDET_28V_MODE
420 pmic_pwrap_write(ACCDET_RSV, ACCDET_1V9_MODE_OFF);
421 ACCDET_DEBUG("ACCDET use in 1.9V mode!! \n");
422 #endif
423
424 }
425 //unmask EINT
426 //msleep(500);
427#ifndef MTK_ALPS_BOX_SUPPORT
428 mt_eint_unmask(CUST_EINT_ACCDET_NUM);
429#endif
430 ACCDET_DEBUG("[Accdet]eint unmask !!!!!!\n");
431
432}
433
434
435static void accdet_eint_func(void)
436{
437 int ret=0;
438 if(cur_eint_state == EINT_PIN_PLUG_IN )
439 {
440#ifndef MTK_ALPS_BOX_SUPPORT
441 /*
442 To trigger EINT when the headset was plugged in
443 We set the polarity back as we initialed.
444 */
445 if (CUST_EINT_ACCDET_TYPE == CUST_EINTF_TRIGGER_HIGH){
446 mt_eint_set_polarity(CUST_EINT_ACCDET_NUM, (1));
447 }else{
448 mt_eint_set_polarity(CUST_EINT_ACCDET_NUM, (0));
449 }
450
451#ifdef ACCDET_SHORT_PLUGOUT_DEBOUNCE
452 mt_eint_set_hw_debounce(CUST_EINT_ACCDET_NUM, CUST_EINT_ACCDET_DEBOUNCE_CN);
453#endif
454
455#endif
456 /* update the eint status */
457 cur_eint_state = EINT_PIN_PLUG_OUT;
458//#ifdef ACCDET_LOW_POWER
459// del_timer_sync(&micbias_timer);
460//#endif
461 }
462 else
463 {
464#ifndef MTK_ALPS_BOX_SUPPORT
465 /*
466 To trigger EINT when the headset was plugged out
467 We set the opposite polarity to what we initialed.
468 */
469 if (CUST_EINT_ACCDET_TYPE == CUST_EINTF_TRIGGER_HIGH){
470 mt_eint_set_polarity(CUST_EINT_ACCDET_NUM, !(1));
471 }else{
472 mt_eint_set_polarity(CUST_EINT_ACCDET_NUM, !(0));
473 }
474 /* update the eint status */
475#ifdef ACCDET_SHORT_PLUGOUT_DEBOUNCE
476 mt_eint_set_hw_debounce(CUST_EINT_ACCDET_NUM, ACCDET_SHORT_PLUGOUT_DEBOUNCE_CN);
477#endif
478#endif
479 cur_eint_state = EINT_PIN_PLUG_IN;
480
481#ifdef ACCDET_LOW_POWER
482 //INIT the timer to disable micbias.
483
484 init_timer(&micbias_timer);
485 micbias_timer.expires = jiffies + MICBIAS_DISABLE_TIMER;
486 micbias_timer.function = &disable_micbias;
487 micbias_timer.data = ((unsigned long) 0 );
488 add_timer(&micbias_timer);
489
490#endif
491 }
492
493 ret = queue_work(accdet_eint_workqueue, &accdet_eint_work);
494 if(!ret)
495 {
496 //ACCDET_DEBUG("[Accdet]accdet_eint_func:accdet_work return:%d!\n", ret);
497 }
498}
499
500
501static inline int accdet_setup_eint(void)
502{
503
504 /*configure to GPIO function, external interrupt*/
505 ACCDET_DEBUG("[Accdet]accdet_setup_eint\n");
506
507#ifndef MTK_ALPS_BOX_SUPPORT
508 mt_set_gpio_mode(GPIO_ACCDET_EINT_PIN, GPIO_ACCDET_EINT_PIN_M_EINT);
509 mt_set_gpio_dir(GPIO_ACCDET_EINT_PIN, GPIO_DIR_IN);
510 mt_set_gpio_pull_enable(GPIO_ACCDET_EINT_PIN, GPIO_PULL_DISABLE); //To disable GPIO PULL.
511
512 mt_eint_set_hw_debounce(CUST_EINT_ACCDET_NUM, CUST_EINT_ACCDET_DEBOUNCE_CN);
513 mt_eint_registration(CUST_EINT_ACCDET_NUM, CUST_EINT_ACCDET_TYPE, accdet_eint_func, 0);
514 ACCDET_DEBUG("[Accdet]accdet set EINT finished, accdet_eint_num=%d, accdet_eint_debounce_en=%d, accdet_eint_polarity=%d\n", CUST_EINT_ACCDET_NUM, CUST_EINT_ACCDET_DEBOUNCE_EN, CUST_EINT_ACCDET_TYPE);
515
516 mt_eint_unmask(CUST_EINT_ACCDET_NUM);
517#endif
518 return 0;
519}
520
521#endif//endif ACCDET_EINT
522
523#ifdef ACCDET_MULTI_KEY_FEATURE
524extern int PMIC_IMM_GetOneChannelValue(int dwChannel, int deCount, int trimd);
525
526#define KEY_SAMPLE_PERIOD (60) //ms
527#ifdef CONFIG_MTK_PMIC_MT6397
528#define MULTIKEY_ADC_CHANNEL (5)
529#else
530#define MULTIKEY_ADC_CHANNEL (8)
531#endif
532
533#define NO_KEY (0x0)
534#define UP_KEY (0x01)
535#define MD_KEY (0x02)
536#define DW_KEY (0x04)
537
538#define SHORT_PRESS (0x0)
539#define LONG_PRESS (0x10)
540#define SHORT_UP ((UP_KEY) | SHORT_PRESS)
541#define SHORT_MD ((MD_KEY) | SHORT_PRESS)
542#define SHORT_DW ((DW_KEY) | SHORT_PRESS)
543#define LONG_UP ((UP_KEY) | LONG_PRESS)
544#define LONG_MD ((MD_KEY) | LONG_PRESS)
545#define LONG_DW ((DW_KEY) | LONG_PRESS)
546
547#define KEYDOWN_FLAG 1
548#define KEYUP_FLAG 0
549//static int g_adcMic_channel_num =0;
550
551
552static DEFINE_MUTEX(accdet_multikey_mutex);
553
554
555
556/*
557
558 MD UP DW
559|---------|-----------|----------|
5600V<=MD< 0.09V<= UP<0.24V<=DW <0.5V
561
562*/
563
564#define DW_KEY_HIGH_THR (500) //0.50v=500000uv
565#define DW_KEY_THR (240) //0.24v=240000uv
566#define UP_KEY_THR (90) //0.09v=90000uv
567#define MD_KEY_THR (0)
568
569static int key_check(int b)
570{
571 //ACCDET_DEBUG("adc_data: %d v\n",b);
572
573 /* 0.24V ~ */
574 ACCDET_DEBUG("accdet: come in key_check!!\n");
575 if((b<DW_KEY_HIGH_THR)&&(b >= DW_KEY_THR))
576 {
577 ACCDET_DEBUG("adc_data: %d mv\n",b);
578 return DW_KEY;
579 }
580 else if ((b < DW_KEY_THR)&& (b >= UP_KEY_THR))
581 {
582 ACCDET_DEBUG("adc_data: %d mv\n",b);
583 return UP_KEY;
584 }
585 else if ((b < UP_KEY_THR) && (b >= MD_KEY_THR))
586 {
587 ACCDET_DEBUG("adc_data: %d mv\n",b);
588 return MD_KEY;
589 }
590 ACCDET_DEBUG("accdet: leave key_check!!\n");
591 return NO_KEY;
592}
593
594static void send_key_event(int keycode,int flag)
595{
596 if(call_status == 0)
597 {
598 switch (keycode)
599 {
600 case DW_KEY:
601 input_report_key(kpd_accdet_dev, KEY_NEXTSONG, flag);
602 input_sync(kpd_accdet_dev);
603 ACCDET_DEBUG("KEY_NEXTSONG %d\n",flag);
604 break;
605 case UP_KEY:
606 input_report_key(kpd_accdet_dev, KEY_PREVIOUSSONG, flag);
607 input_sync(kpd_accdet_dev);
608 ACCDET_DEBUG("KEY_PREVIOUSSONG %d\n",flag);
609 break;
610 }
611 }
612 else
613 {
614 switch (keycode)
615 {
616 case DW_KEY:
617 input_report_key(kpd_accdet_dev, KEY_VOLUMEDOWN, flag);
618 input_sync(kpd_accdet_dev);
619 ACCDET_DEBUG("KEY_VOLUMEDOWN %d\n",flag);
620 break;
621 case UP_KEY:
622 input_report_key(kpd_accdet_dev, KEY_VOLUMEUP, flag);
623 input_sync(kpd_accdet_dev);
624 ACCDET_DEBUG("KEY_VOLUMEUP %d\n",flag);
625 break;
626 }
627 }
628}
629static int multi_key_detection(void)
630{
631 int current_status = 0;
632 int index = 0;
633 int count = long_press_time / (KEY_SAMPLE_PERIOD + 40 ); //ADC delay
634 int m_key = 0;
635 int cur_key = 0;
636 int cali_voltage=0;
637
638 cali_voltage = PMIC_IMM_GetOneChannelValue(MULTIKEY_ADC_CHANNEL,1,1);
639 ACCDET_DEBUG("[Accdet]adc cali_voltage1 = %d mv\n", cali_voltage);
640 m_key = cur_key = key_check(cali_voltage);
641
642 send_key_event(m_key, KEYDOWN_FLAG);
643
644 while(index++ < count)
645 {
646
647 /* Check if the current state has been changed */
648 current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0)>>6);
649 ACCDET_DEBUG("[Accdet]accdet current_status = %d\n", current_status);
650 if(current_status != 0)
651 {
652 send_key_event(m_key, KEYUP_FLAG);
653 return (m_key | SHORT_PRESS);
654 }
655
656 /* Check if the voltage has been changed (press one key and another) */
657 //IMM_GetOneChannelValue(g_adcMic_channel_num, adc_data, &adc_raw);
658 cali_voltage = PMIC_IMM_GetOneChannelValue(MULTIKEY_ADC_CHANNEL,1,1);
659 ACCDET_DEBUG("[Accdet]adc in while loop [%d]= %d mv\n", index, cali_voltage);
660 cur_key = key_check(cali_voltage);
661 if(m_key != cur_key)
662 {
663 send_key_event(m_key, KEYUP_FLAG);
664 ACCDET_DEBUG("[Accdet]accdet press one key and another happen!!\n");
665 return (m_key | SHORT_PRESS);
666 }
667 else
668 {
669 m_key = cur_key;
670 }
671
672 msleep(KEY_SAMPLE_PERIOD);
673 }
674
675 return (m_key | LONG_PRESS);
676}
677
678#endif
679static void accdet_workqueue_func(void)
680{
681 int ret;
682 ret = queue_work(accdet_workqueue, &accdet_work);
683 if(!ret)
684 {
685 ACCDET_DEBUG("[Accdet]accdet_work return:%d!\n", ret);
686 }
687
688}
689
690int accdet_irq_handler(void)
691{
692 int i = 0;
693 if((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT)) {
694 clear_accdet_interrupt();
695 }
696 #ifdef ACCDET_MULTI_KEY_FEATURE
697 if (accdet_status == MIC_BIAS){
698 accdet_auxadc_switch(1);
699 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width));
700 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_width));
701 }
702 #endif
703 accdet_workqueue_func();
704 while(((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) && i<10)) {
705 i++;
706 udelay(200);
707 }
708 return 1;
709}
710
711//clear ACCDET IRQ in accdet register
712static inline void clear_accdet_interrupt(void)
713{
714
715 //it is safe by using polling to adjust when to clear IRQ_CLR_BIT
716 pmic_pwrap_write(ACCDET_IRQ_STS, (IRQ_CLR_BIT));
717 ACCDET_DEBUG("[Accdet]clear_accdet_interrupt: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS));
718}
719
720#ifdef SW_WORK_AROUND_ACCDET_REMOTE_BUTTON_ISSUE
721
722
723#define ACC_ANSWER_CALL 1
724#define ACC_END_CALL 2
725#define ACC_MEDIA_PLAYPAUSE 3
726
727#ifdef ACCDET_MULTI_KEY_FEATURE
728#define ACC_MEDIA_STOP 4
729#define ACC_MEDIA_NEXT 5
730#define ACC_MEDIA_PREVIOUS 6
731#define ACC_VOLUMEUP 7
732#define ACC_VOLUMEDOWN 8
733#endif
734
735static atomic_t send_event_flag = ATOMIC_INIT(0);
736
737static DECLARE_WAIT_QUEUE_HEAD(send_event_wq);
738
739
740static int accdet_key_event=0;
741
742static int sendKeyEvent(void *unuse)
743{
744 while(1)
745 {
746 ACCDET_DEBUG( " accdet:sendKeyEvent wait\n");
747 //wait for signal
748 wait_event_interruptible(send_event_wq, (atomic_read(&send_event_flag) != 0));
749
750 wake_lock_timeout(&accdet_key_lock, 2*HZ); //set the wake lock.
751 ACCDET_DEBUG( " accdet:going to send event %d\n", accdet_key_event);
752
753 if(PLUG_OUT !=accdet_status)
754 {
755 //send key event
756 if(ACC_END_CALL == accdet_key_event)
757 {
758 ACCDET_DEBUG("[Accdet] end call!\n");
759 input_report_key(kpd_accdet_dev, KEY_ENDCALL, 1);
760 input_report_key(kpd_accdet_dev, KEY_ENDCALL, 0);
761 input_sync(kpd_accdet_dev);
762 }
763#ifdef ACCDET_MULTI_KEY_FEATURE
764 if(ACC_MEDIA_PLAYPAUSE == accdet_key_event)
765 {
766 ACCDET_DEBUG("[Accdet] PLAY_PAUSE !\n");
767 input_report_key(kpd_accdet_dev, KEY_PLAYPAUSE, 1);
768 input_report_key(kpd_accdet_dev, KEY_PLAYPAUSE, 0);
769 input_sync(kpd_accdet_dev);
770 }
771// next, previous, volumeup, volumedown send key in multi_key_detection()
772 if(ACC_MEDIA_NEXT == accdet_key_event)
773 {
774 ACCDET_DEBUG("[Accdet] NEXT ..\n");
775
776 }
777 if(ACC_MEDIA_PREVIOUS == accdet_key_event)
778 {
779 ACCDET_DEBUG("[Accdet] PREVIOUS..\n");
780
781 }
782 if(ACC_VOLUMEUP== accdet_key_event)
783 {
784 ACCDET_DEBUG("[Accdet] VOLUMUP ..\n");
785
786 }
787 if(ACC_VOLUMEDOWN== accdet_key_event)
788 {
789 ACCDET_DEBUG("[Accdet] VOLUMDOWN..\n");
790
791 }
792
793#else
794 if(ACC_MEDIA_PLAYPAUSE == accdet_key_event)
795 {
796 ACCDET_DEBUG("[Accdet] PLAY_PAUSE !\n");
797 input_report_key(kpd_accdet_dev, KEY_PLAYPAUSE, 1);
798 input_report_key(kpd_accdet_dev, KEY_PLAYPAUSE, 0);
799 input_sync(kpd_accdet_dev);
800 }
801#endif
802 }
803 atomic_set(&send_event_flag, 0);
804
805 // wake_unlock(&accdet_key_lock); //unlock wake lock
806 }
807 return 0;
808}
809
810static ssize_t notify_sendKeyEvent(int event)
811{
812
813 accdet_key_event = event;
814 atomic_set(&send_event_flag, 1);
815 wake_up(&send_event_wq);
816 ACCDET_DEBUG( " accdet:notify_sendKeyEvent !\n");
817 return 0;
818}
819
820
821#endif
822
823static inline void check_cable_type(void)
824{
825 int current_status = 0;
826 int irq_temp = 0; //for clear IRQ_bit
827 int wait_clear_irq_times = 0;
828#ifdef ACCDET_PIN_RECOGNIZATION
829 int pin_adc_value = 0;
830#define PIN_ADC_CHANNEL 5
831#endif
832
833 current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0)>>6); //A=bit1; B=bit0
834 ACCDET_DEBUG("[Accdet]accdet interrupt happen:[%s]current AB = %d\n",
835 accdet_status_string[accdet_status], current_status);
836
837 button_status = 0;
838 pre_status = accdet_status;
839
840 ACCDET_DEBUG("[Accdet]check_cable_type: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS));
841 IRQ_CLR_FLAG = FALSE;
842 switch(accdet_status)
843 {
844 case PLUG_OUT:
845 #ifdef ACCDET_PIN_RECOGNIZATION
846 pmic_pwrap_write(ACCDET_DEBOUNCE1, cust_headset_settings->debounce1);
847 #endif
848 if(current_status == 0)
849 {
850 #ifdef ACCDET_PIN_RECOGNIZATION
851 //micbias always on during detected PIN recognition
852 pmic_pwrap_write(ACCDET_PWM_WIDTH, cust_headset_settings->pwm_width);
853 pmic_pwrap_write(ACCDET_PWM_THRESH, cust_headset_settings->pwm_width);
854 ACCDET_DEBUG("[Accdet]PIN recognition micbias always on!\n");
855 ACCDET_DEBUG("[Accdet]before adc read, pin_adc_value = %d mv!\n", pin_adc_value);
856 msleep(1000);
857 current_status = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0)>>6); //A=bit1; B=bit0
858 if (current_status == 0 && show_icon_delay != 0)
859 {
860 accdet_auxadc_switch(1);//switch on when need to use auxadc read voltage
861 pin_adc_value = PMIC_IMM_GetOneChannelValue(MULTIKEY_ADC_CHANNEL,1,1);
862 ACCDET_DEBUG("[Accdet]pin_adc_value = %d mv!\n", pin_adc_value);
863 accdet_auxadc_switch(0);
864 if (200 > pin_adc_value && pin_adc_value> 100) //100mv ilegal headset
865 {
866 headset_standard_judge_message();
867 mutex_lock(&accdet_eint_irq_sync_mutex);
868 if(1 == eint_accdet_sync_flag) {
869 cable_type = HEADSET_NO_MIC;
870 accdet_status = HOOK_SWITCH;
871 cable_pin_recognition = 1;
872 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition);
873 }else {
874 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
875 }
876 mutex_unlock(&accdet_eint_irq_sync_mutex);
877 }
878 else
879 {
880 mutex_lock(&accdet_eint_irq_sync_mutex);
881 if(1 == eint_accdet_sync_flag) {
882 cable_type = HEADSET_NO_MIC;
883 accdet_status = HOOK_SWITCH;
884 }else {
885 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
886 }
887 mutex_unlock(&accdet_eint_irq_sync_mutex);
888 }
889 }
890 #else
891 mutex_lock(&accdet_eint_irq_sync_mutex);
892 if(1 == eint_accdet_sync_flag) {
893 cable_type = HEADSET_NO_MIC;
894 accdet_status = HOOK_SWITCH;
895 }else {
896 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
897 }
898 mutex_unlock(&accdet_eint_irq_sync_mutex);
899 #endif
900 }
901 else if(current_status == 1)
902 {
903 mutex_lock(&accdet_eint_irq_sync_mutex);
904 if(1 == eint_accdet_sync_flag) {
905 accdet_status = MIC_BIAS;
906 cable_type = HEADSET_MIC;
907 }else {
908 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
909 }
910 mutex_unlock(&accdet_eint_irq_sync_mutex);
911 //ALPS00038030:reduce the time of remote button pressed during incoming call
912 //solution: reduce hook switch debounce time to 0x400
913 pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce);
914 //recover polling set AB 00-01
915 #ifdef ACCDET_PIN_RECOGNIZATION
916 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width));
917 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh));
918 #endif
919 //#ifdef ACCDET_LOW_POWER
920 //wake_unlock(&accdet_timer_lock);//add for suspend disable accdet more than 5S
921 //#endif
922 }
923 else if(current_status == 3)
924 {
925 ACCDET_DEBUG("[Accdet]PLUG_OUT state not change!\n");
926 #ifdef ACCDET_MULTI_KEY_FEATURE
927 ACCDET_DEBUG("[Accdet] do not send plug out event in plug out\n");
928 #else
929 mutex_lock(&accdet_eint_irq_sync_mutex);
930 if(1 == eint_accdet_sync_flag) {
931 accdet_status = PLUG_OUT;
932 cable_type = NO_DEVICE;
933 }else {
934 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
935 }
936 mutex_unlock(&accdet_eint_irq_sync_mutex);
937 #ifdef ACCDET_EINT
938 disable_accdet();
939 #endif
940 #endif
941 }
942 else
943 {
944 ACCDET_DEBUG("[Accdet]PLUG_OUT can't change to this state!\n");
945 }
946 break;
947
948 case MIC_BIAS:
949 //ALPS00038030:reduce the time of remote button pressed during incoming call
950 //solution: resume hook switch debounce time
951 pmic_pwrap_write(ACCDET_DEBOUNCE0, cust_headset_settings->debounce0);
952
953 if(current_status == 0)
954 {
955
956 mutex_lock(&accdet_eint_irq_sync_mutex);
957 if(1 == eint_accdet_sync_flag) {
958 while((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) && (wait_clear_irq_times<3))
959 {
960 ACCDET_DEBUG("[Accdet]check_cable_type: MIC BIAS clear IRQ on-going1....\n");
961 wait_clear_irq_times++;
962 msleep(5);
963 }
964 irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS);
965 irq_temp = irq_temp & (~IRQ_CLR_BIT);
966 pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp);
967 IRQ_CLR_FLAG = TRUE;
968 accdet_status = HOOK_SWITCH;
969 }else {
970 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
971 }
972 mutex_unlock(&accdet_eint_irq_sync_mutex);
973 button_status = 1;
974 if(button_status)
975 {
976 #ifdef ACCDET_MULTI_KEY_FEATURE
977 int multi_key = NO_KEY;
978 //mdelay(10);
979 //if plug out don't send key
980 mutex_lock(&accdet_eint_irq_sync_mutex);
981 if(1 == eint_accdet_sync_flag) {
982 multi_key = multi_key_detection();
983 }else {
984 ACCDET_DEBUG("[Accdet] multi_key_detection: Headset has plugged out\n");
985 }
986 mutex_unlock(&accdet_eint_irq_sync_mutex);
987 accdet_auxadc_switch(0);
988 //recover pwm frequency and duty
989 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width));
990 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh));
991 switch (multi_key)
992 {
993 case SHORT_UP:
994 ACCDET_DEBUG("[Accdet] Short press up (0x%x)\n", multi_key);
995 if(call_status == 0)
996 {
997 notify_sendKeyEvent(ACC_MEDIA_PREVIOUS);
998 }
999 else
1000 {
1001 notify_sendKeyEvent(ACC_VOLUMEUP);
1002 }
1003 break;
1004 case SHORT_MD:
1005 ACCDET_DEBUG("[Accdet] Short press middle (0x%x)\n", multi_key);
1006 notify_sendKeyEvent(ACC_MEDIA_PLAYPAUSE);
1007 break;
1008 case SHORT_DW:
1009 ACCDET_DEBUG("[Accdet] Short press down (0x%x)\n", multi_key);
1010 if(call_status == 0)
1011 {
1012 notify_sendKeyEvent(ACC_MEDIA_NEXT);
1013 }
1014 else
1015 {
1016 notify_sendKeyEvent(ACC_VOLUMEDOWN);
1017 }
1018 break;
1019 case LONG_UP:
1020 ACCDET_DEBUG("[Accdet] Long press up (0x%x)\n", multi_key);
1021 send_key_event(UP_KEY, KEYUP_FLAG);
1022
1023 break;
1024 case LONG_MD:
1025 ACCDET_DEBUG("[Accdet] Long press middle (0x%x)\n", multi_key);
1026 notify_sendKeyEvent(ACC_END_CALL);
1027 break;
1028 case LONG_DW:
1029 ACCDET_DEBUG("[Accdet] Long press down (0x%x)\n", multi_key);
1030 send_key_event(DW_KEY, KEYUP_FLAG);
1031
1032 break;
1033 default:
1034 ACCDET_DEBUG("[Accdet] unkown key (0x%x)\n", multi_key);
1035 break;
1036 }
1037 #else
1038 if(call_status != 0)
1039 {
1040 if(is_long_press())
1041 {
1042 ACCDET_DEBUG("[Accdet]send long press remote button event %d \n",ACC_END_CALL);
1043 notify_sendKeyEvent(ACC_END_CALL);
1044 } else {
1045 ACCDET_DEBUG("[Accdet]send short press remote button event %d\n",ACC_ANSWER_CALL);
1046 notify_sendKeyEvent(ACC_MEDIA_PLAYPAUSE);
1047 }
1048 }
1049 #endif////end ifdef ACCDET_MULTI_KEY_FEATURE else
1050 }
1051}
1052 else if(current_status == 1)
1053 {
1054 mutex_lock(&accdet_eint_irq_sync_mutex);
1055 if(1 == eint_accdet_sync_flag) {
1056 accdet_status = MIC_BIAS;
1057 cable_type = HEADSET_MIC;
1058 ACCDET_DEBUG("[Accdet]MIC_BIAS state not change!\n");
1059 }else {
1060 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
1061 }
1062 mutex_unlock(&accdet_eint_irq_sync_mutex);
1063 }
1064 else if(current_status == 3)
1065 {
1066 #ifdef ACCDET_MULTI_KEY_FEATURE
1067 ACCDET_DEBUG("[Accdet]do not send plug ou in micbiast\n");
1068 mutex_lock(&accdet_eint_irq_sync_mutex);
1069 if(1 == eint_accdet_sync_flag) {
1070 accdet_status = PLUG_OUT;
1071 }else {
1072 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
1073 }
1074 mutex_unlock(&accdet_eint_irq_sync_mutex);
1075 #else
1076 mutex_lock(&accdet_eint_irq_sync_mutex);
1077 if(1 == eint_accdet_sync_flag) {
1078 accdet_status = PLUG_OUT;
1079 cable_type = NO_DEVICE;
1080 }else {
1081 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
1082 }
1083 mutex_unlock(&accdet_eint_irq_sync_mutex);
1084 #ifdef ACCDET_EINT
1085 disable_accdet();
1086 #endif
1087 #endif
1088 }
1089 else
1090 {
1091 ACCDET_DEBUG("[Accdet]MIC_BIAS can't change to this state!\n");
1092 }
1093 break;
1094
1095 case HOOK_SWITCH:
1096 if(current_status == 0)
1097 {
1098 mutex_lock(&accdet_eint_irq_sync_mutex);
1099 if(1 == eint_accdet_sync_flag) {
1100 //for avoid 01->00 framework of Headset will report press key info for Audio
1101 //cable_type = HEADSET_NO_MIC;
1102 //accdet_status = HOOK_SWITCH;
1103 ACCDET_DEBUG("[Accdet]HOOK_SWITCH state not change!\n");
1104 }else {
1105 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
1106 }
1107 mutex_unlock(&accdet_eint_irq_sync_mutex);
1108 }
1109 else if(current_status == 1)
1110 {
1111 mutex_lock(&accdet_eint_irq_sync_mutex);
1112 if(1 == eint_accdet_sync_flag) {
1113 accdet_status = MIC_BIAS;
1114 cable_type = HEADSET_MIC;
1115 }else {
1116 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
1117 }
1118 mutex_unlock(&accdet_eint_irq_sync_mutex);
1119 #ifdef ACCDET_PIN_RECOGNIZATION
1120 cable_pin_recognition = 0;
1121 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition);
1122 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width));
1123 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh));
1124 #endif
1125 //ALPS00038030:reduce the time of remote button pressed during incoming call
1126 //solution: reduce hook switch debounce time to 0x400
1127 pmic_pwrap_write(ACCDET_DEBOUNCE0, button_press_debounce);
1128 //#ifdef ACCDET_LOW_POWER
1129 //wake_unlock(&accdet_timer_lock);//add for suspend disable accdet more than 5S
1130 //#endif
1131 }
1132 else if(current_status == 3)
1133 {
1134
1135 #ifdef ACCDET_PIN_RECOGNIZATION
1136 cable_pin_recognition = 0;
1137 ACCDET_DEBUG("[Accdet] cable_pin_recognition = %d\n", cable_pin_recognition);
1138 mutex_lock(&accdet_eint_irq_sync_mutex);
1139 if(1 == eint_accdet_sync_flag) {
1140 accdet_status = PLUG_OUT;
1141 }else {
1142 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
1143 }
1144 mutex_unlock(&accdet_eint_irq_sync_mutex);
1145 #endif
1146 #ifdef ACCDET_MULTI_KEY_FEATURE
1147 ACCDET_DEBUG("[Accdet] do not send plug out event in hook switch\n");
1148 mutex_lock(&accdet_eint_irq_sync_mutex);
1149 if(1 == eint_accdet_sync_flag) {
1150 accdet_status = PLUG_OUT;
1151 }else {
1152 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
1153 }
1154 mutex_unlock(&accdet_eint_irq_sync_mutex);
1155 #else
1156 mutex_lock(&accdet_eint_irq_sync_mutex);
1157 if(1 == eint_accdet_sync_flag) {
1158 accdet_status = PLUG_OUT;
1159 cable_type = NO_DEVICE;
1160 }else {
1161 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
1162 }
1163 mutex_unlock(&accdet_eint_irq_sync_mutex);
1164 #ifdef ACCDET_EINT
1165 disable_accdet();
1166 #endif
1167 #endif
1168 }
1169 else
1170 {
1171 ACCDET_DEBUG("[Accdet]HOOK_SWITCH can't change to this state!\n");
1172 }
1173 break;
1174
1175 case STAND_BY:
1176 if(current_status == 3)
1177 {
1178 #ifdef ACCDET_MULTI_KEY_FEATURE
1179 ACCDET_DEBUG("[Accdet]accdet do not send plug out event in stand by!\n");
1180 #else
1181 mutex_lock(&accdet_eint_irq_sync_mutex);
1182 if(1 == eint_accdet_sync_flag) {
1183 accdet_status = PLUG_OUT;
1184 cable_type = NO_DEVICE;
1185 }else {
1186 ACCDET_DEBUG("[Accdet] Headset has plugged out\n");
1187 }
1188 mutex_unlock(&accdet_eint_irq_sync_mutex);
1189 #ifdef ACCDET_EINT
1190 disable_accdet();
1191 #endif
1192 #endif
1193 }
1194 else
1195 {
1196 ACCDET_DEBUG("[Accdet]STAND_BY can't change to this state!\n");
1197 }
1198 break;
1199
1200 default:
1201 ACCDET_DEBUG("[Accdet]check_cable_type: accdet current status error!\n");
1202 break;
1203
1204}
1205
1206 if(!IRQ_CLR_FLAG)
1207 {
1208 mutex_lock(&accdet_eint_irq_sync_mutex);
1209 if(1 == eint_accdet_sync_flag) {
1210 while((pmic_pwrap_read(ACCDET_IRQ_STS) & IRQ_STATUS_BIT) && (wait_clear_irq_times<3))
1211 {
1212 ACCDET_DEBUG("[Accdet]check_cable_type: Clear interrupt on-going2....\n");
1213 wait_clear_irq_times++;
1214 msleep(5);
1215 }
1216 }
1217 irq_temp = pmic_pwrap_read(ACCDET_IRQ_STS);
1218 irq_temp = irq_temp & (~IRQ_CLR_BIT);
1219 pmic_pwrap_write(ACCDET_IRQ_STS, irq_temp);
1220 mutex_unlock(&accdet_eint_irq_sync_mutex);
1221 IRQ_CLR_FLAG = TRUE;
1222 ACCDET_DEBUG("[Accdet]check_cable_type:Clear interrupt:Done[0x%x]!\n", pmic_pwrap_read(ACCDET_IRQ_STS));
1223
1224 }
1225 else
1226 {
1227 IRQ_CLR_FLAG = FALSE;
1228 }
1229
1230 ACCDET_DEBUG("[Accdet]cable type:[%s], status switch:[%s]->[%s]\n",
1231 accdet_report_string[cable_type], accdet_status_string[pre_status],
1232 accdet_status_string[accdet_status]);
1233}
1234static void accdet_work_callback(struct work_struct *work)
1235{
1236
1237 wake_lock(&accdet_irq_lock);
1238 check_cable_type();
1239
1240 mutex_lock(&accdet_eint_irq_sync_mutex);
1241 if(1 == eint_accdet_sync_flag) {
1242 switch_set_state((struct switch_dev *)&accdet_data, cable_type);
1243 }else {
1244 ACCDET_DEBUG("[Accdet] Headset has plugged out don't set accdet state\n");
1245 }
1246 mutex_unlock(&accdet_eint_irq_sync_mutex);
1247 ACCDET_DEBUG( " [accdet] set state in cable_type status\n");
1248
1249 wake_unlock(&accdet_irq_lock);
1250}
1251
1252//ACCDET hardware initial
1253static inline void accdet_init(void)
1254{
1255 ACCDET_DEBUG("[Accdet]accdet hardware init\n");
1256
1257 pmic_pwrap_write(TOP_CKPDN_CLR, RG_ACCDET_CLK_CLR);
1258 ACCDET_DEBUG("[Accdet]accdet TOP_CKPDN=0x%x!\n", pmic_pwrap_read(TOP_CKPDN));
1259 //reset the accdet unit
1260
1261 ACCDET_DEBUG("ACCDET reset : reset start!! \n\r");
1262 pmic_pwrap_write(TOP_RST_ACCDET_SET, ACCDET_RESET_SET);
1263
1264 ACCDET_DEBUG("ACCDET reset function test: reset finished!! \n\r");
1265 pmic_pwrap_write(TOP_RST_ACCDET_CLR, ACCDET_RESET_CLR);
1266
1267 //init pwm frequency and duty
1268 pmic_pwrap_write(ACCDET_PWM_WIDTH, REGISTER_VALUE(cust_headset_settings->pwm_width));
1269 pmic_pwrap_write(ACCDET_PWM_THRESH, REGISTER_VALUE(cust_headset_settings->pwm_thresh));
1270
1271
1272 pwrap_write(ACCDET_STATE_SWCTRL, 0x07);
1273
1274
1275 pmic_pwrap_write(ACCDET_EN_DELAY_NUM,
1276 (cust_headset_settings->fall_delay << 15 | cust_headset_settings->rise_delay));
1277
1278 // init the debounce time
1279 #ifdef ACCDET_PIN_RECOGNIZATION
1280 pmic_pwrap_write(ACCDET_DEBOUNCE0, cust_headset_settings->debounce0);
1281 pmic_pwrap_write(ACCDET_DEBOUNCE1, 0xFFFF);
1282 pmic_pwrap_write(ACCDET_DEBOUNCE3, cust_headset_settings->debounce3);
1283 #else
1284 pmic_pwrap_write(ACCDET_DEBOUNCE0, cust_headset_settings->debounce0);
1285 pmic_pwrap_write(ACCDET_DEBOUNCE1, cust_headset_settings->debounce1);
1286 pmic_pwrap_write(ACCDET_DEBOUNCE3, cust_headset_settings->debounce3);
1287 #endif
1288 pmic_pwrap_write(ACCDET_IRQ_STS, pmic_pwrap_read(ACCDET_IRQ_STS)&(~IRQ_CLR_BIT));
1289 pmic_pwrap_write(INT_CON_ACCDET_SET, RG_ACCDET_IRQ_SET);
1290 #ifdef ACCDET_EINT
1291 // disable ACCDET unit
1292 pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL);
1293 pmic_pwrap_write(ACCDET_CTRL, ACCDET_DISABLE);
1294 pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0x0);
1295 pmic_pwrap_write(TOP_CKPDN_SET, RG_ACCDET_CLK_SET);
1296 #else
1297
1298 // enable ACCDET unit
1299 // pmic_pwrap_write(ACCDET_STATE_SWCTRL, ACCDET_SWCTRL_EN);
1300 pmic_pwrap_write(ACCDET_CTRL, ACCDET_ENABLE);
1301 #endif
1302
1303#ifdef GPIO_FSA8049_PIN
1304 //mt_set_gpio_out(GPIO_FSA8049_PIN, GPIO_OUT_ONE);
1305#endif
1306#ifdef FSA8049_V_POWER
1307 hwPowerOn(FSA8049_V_POWER, VOL_2800, "ACCDET");
1308#endif
1309
1310}
1311/*-----------------------------------sysfs-----------------------------------------*/
1312#if DEBUG_THREAD
1313#ifdef CONFIG_MTK_PMIC_MT6397
1314int dump_register(void)
1315{
1316
1317 int i=0;
1318 for (i=0x0582; i<= 0x05A4; i+=2)
1319 {
1320 ACCDET_DEBUG(" ACCDET_BASE + %x=%x\n",i,pmic_pwrap_read(ACCDET_BASE + i));
1321 }
1322
1323 ACCDET_DEBUG(" TOP_RST_ACCDET =%x\n",pmic_pwrap_read(TOP_RST_ACCDET));// reset register in 6397
1324 ACCDET_DEBUG(" INT_CON_ACCDET =%x\n",pmic_pwrap_read(INT_CON_ACCDET));//INT register in 6397
1325 ACCDET_DEBUG(" TOP_CKPDN =%x\n",pmic_pwrap_read(TOP_CKPDN));// clock register in 6397
1326 ACCDET_DEBUG(" 0x0732 =%x\n",pmic_pwrap_read(0x0732));
1327 ACCDET_DEBUG(" MULTIKEY_ADC_CHANNEL(%x) is %x\n",MULTIKEY_ADC_CHANNEL, PMIC_IMM_GetOneChannelValue(MULTIKEY_ADC_CHANNEL,1,1));
1328 #ifdef ACCDET_PIN_SWAP
1329 //ACCDET_DEBUG(" 0x00004000 =%x\n",pmic_pwrap_read(0x00004000));//VRF28 power for PIN swap feature
1330 #endif
1331 return 0;
1332}
1333#else
1334static int dump_register(void)
1335{
1336 int i=0;
1337 for (i=0x077A; i<= 0x079A; i+=2)
1338 {
1339 ACCDET_DEBUG(" ACCDET_BASE + %x=%x\n",i,pmic_pwrap_read(ACCDET_BASE + i));
1340 }
1341
1342 ACCDET_DEBUG(" TOP_RST_ACCDET =%x\n",pmic_pwrap_read(TOP_RST_ACCDET));// reset register in 6320
1343 ACCDET_DEBUG(" INT_CON_ACCDET =%x\n",pmic_pwrap_read(INT_CON_ACCDET));//INT register in 6320
1344 ACCDET_DEBUG(" TOP_CKPDN =%x\n",pmic_pwrap_read(TOP_CKPDN));// clock register in 6320
1345 #ifdef ACCDET_PIN_SWAP
1346 //ACCDET_DEBUG(" 0x00004000 =%x\n",pmic_pwrap_read(0x00004000));//VRF28 power for PIN swap feature
1347 #endif
1348 return 0;
1349}
1350#endif
1351
1352static ssize_t accdet_store_call_state(struct device_driver *ddri, const char *buf, size_t count)
1353{
1354 if (sscanf(buf, "%u", &call_status) != 1) {
1355 ACCDET_DEBUG("accdet: Invalid values\n");
1356 return -EINVAL;
1357 }
1358
1359 switch(call_status)
1360 {
1361 case CALL_IDLE :
1362 ACCDET_DEBUG("[Accdet]accdet call: Idle state!\n");
1363 break;
1364
1365 case CALL_RINGING :
1366
1367 ACCDET_DEBUG("[Accdet]accdet call: ringing state!\n");
1368 break;
1369
1370 case CALL_ACTIVE :
1371 ACCDET_DEBUG("[Accdet]accdet call: active or hold state!\n");
1372 ACCDET_DEBUG("[Accdet]accdet_ioctl : Button_Status=%d (state:%d)\n", button_status, accdet_data.state);
1373 //return button_status;
1374 break;
1375
1376 default:
1377 ACCDET_DEBUG("[Accdet]accdet call : Invalid values\n");
1378 break;
1379 }
1380 return count;
1381}
1382
1383//#ifdef ACCDET_PIN_RECOGNIZATION
1384
1385static ssize_t show_pin_recognition_state(struct device_driver *ddri, char *buf)
1386{
1387 #ifdef ACCDET_PIN_RECOGNIZATION
1388 ACCDET_DEBUG("ACCDET show_pin_recognition_state = %d\n", cable_pin_recognition);
1389 return sprintf(buf, "%u\n", cable_pin_recognition);
1390 #else
1391 return sprintf(buf, "%u\n", 0);
1392 #endif
1393}
1394
1395static DRIVER_ATTR(accdet_pin_recognition, 0664, show_pin_recognition_state, NULL);
1396static DRIVER_ATTR(accdet_call_state, 0664, NULL, accdet_store_call_state);
1397
1398static int g_start_debug_thread =0;
1399static struct task_struct *thread = NULL;
1400static int g_dump_register=0;
1401static int dbug_thread(void *unused)
1402{
1403 while(g_start_debug_thread)
1404 {
1405 if(g_dump_register)
1406 {
1407 dump_register();
1408 //dump_pmic_register();
1409 }
1410
1411 msleep(500);
1412
1413 }
1414 return 0;
1415}
1416//static ssize_t store_trace_value(struct device_driver *ddri, const char *buf, size_t count)
1417static ssize_t store_accdet_start_debug_thread(struct device_driver *ddri, const char *buf, size_t count)
1418{
1419
1420 unsigned int start_flag;
1421 int error;
1422
1423 if (sscanf(buf, "%u", &start_flag) != 1) {
1424 ACCDET_DEBUG("accdet: Invalid values\n");
1425 return -EINVAL;
1426 }
1427
1428 ACCDET_DEBUG("[Accdet] start flag =%d \n",start_flag);
1429
1430 g_start_debug_thread = start_flag;
1431
1432 if(1 == start_flag)
1433 {
1434 thread = kthread_run(dbug_thread, 0, "ACCDET");
1435 if (IS_ERR(thread))
1436 {
1437 error = PTR_ERR(thread);
1438 ACCDET_DEBUG( " failed to create kernel thread: %d\n", error);
1439 }
1440 }
1441
1442 return count;
1443}
1444static ssize_t store_accdet_set_headset_mode(struct device_driver *ddri, const char *buf, size_t count)
1445{
1446
1447 unsigned int value;
1448 //int error;
1449
1450 if (sscanf(buf, "%u", &value) != 1) {
1451 ACCDET_DEBUG("accdet: Invalid values\n");
1452 return -EINVAL;
1453 }
1454
1455 ACCDET_DEBUG("[Accdet]store_accdet_set_headset_mode value =%d \n",value);
1456
1457 return count;
1458}
1459
1460static ssize_t store_accdet_dump_register(struct device_driver *ddri, const char *buf, size_t count)
1461{
1462 unsigned int value;
1463// int error;
1464
1465 if (sscanf(buf, "%u", &value) != 1)
1466 {
1467 ACCDET_DEBUG("accdet: Invalid values\n");
1468 return -EINVAL;
1469 }
1470
1471 g_dump_register = value;
1472
1473 ACCDET_DEBUG("[Accdet]store_accdet_dump_register value =%d \n",value);
1474
1475 return count;
1476}
1477
1478/*----------------------------------------------------------------------------*/
1479static DRIVER_ATTR(dump_register, S_IWUSR | S_IRUGO, NULL, store_accdet_dump_register);
1480
1481static DRIVER_ATTR(set_headset_mode, S_IWUSR | S_IRUGO, NULL, store_accdet_set_headset_mode);
1482
1483static DRIVER_ATTR(start_debug, S_IWUSR | S_IRUGO, NULL, store_accdet_start_debug_thread);
1484
1485/*----------------------------------------------------------------------------*/
1486static struct driver_attribute *accdet_attr_list[] = {
1487 &driver_attr_start_debug,
1488 &driver_attr_set_headset_mode,
1489 &driver_attr_dump_register,
1490 &driver_attr_accdet_call_state,
1491 //#ifdef ACCDET_PIN_RECOGNIZATION
1492 &driver_attr_accdet_pin_recognition,
1493 //#endif
1494};
1495
1496static int accdet_create_attr(struct device_driver *driver)
1497{
1498 int idx, err = 0;
1499 int num = (int)(sizeof(accdet_attr_list)/sizeof(accdet_attr_list[0]));
1500 if (driver == NULL)
1501 {
1502 return -EINVAL;
1503 }
1504
1505 for(idx = 0; idx < num; idx++)
1506 {
1507 if((err = driver_create_file(driver, accdet_attr_list[idx])))
1508 {
1509 ACCDET_DEBUG("driver_create_file (%s) = %d\n", accdet_attr_list[idx]->attr.name, err);
1510 break;
1511 }
1512 }
1513 return err;
1514}
1515
1516#endif
1517
1518int mt_accdet_probe(void)
1519{
1520 int ret = 0;
1521#ifdef SW_WORK_AROUND_ACCDET_REMOTE_BUTTON_ISSUE
1522 struct task_struct *keyEvent_thread = NULL;
1523 int error=0;
1524#endif
1525#if DEBUG_THREAD
1526 struct platform_driver accdet_driver_hal = accdet_driver_func();
1527#endif
1528
1529 struct headset_key_custom* press_key_time = get_headset_key_custom_setting();
1530
1531 ACCDET_DEBUG("[Accdet]accdet_probe begin!\n");
1532
1533
1534 //------------------------------------------------------------------
1535 // below register accdet as switch class
1536 //------------------------------------------------------------------
1537 accdet_data.name = "h2w";
1538 accdet_data.index = 0;
1539 accdet_data.state = NO_DEVICE;
1540
1541 cust_headset_settings = get_cust_headset_settings();
1542
1543 ret = switch_dev_register(&accdet_data);
1544 if(ret)
1545 {
1546 ACCDET_DEBUG("[Accdet]switch_dev_register returned:%d!\n", ret);
1547 return 1;
1548 }
1549
1550 //------------------------------------------------------------------
1551 // Create normal device for auido use
1552 //------------------------------------------------------------------
1553 ret = alloc_chrdev_region(&accdet_devno, 0, 1, ACCDET_DEVNAME);
1554 if (ret)
1555 {
1556 ACCDET_DEBUG("[Accdet]alloc_chrdev_region: Get Major number error!\n");
1557 }
1558
1559 accdet_cdev = cdev_alloc();
1560 accdet_cdev->owner = THIS_MODULE;
1561 accdet_cdev->ops = accdet_get_fops();
1562 ret = cdev_add(accdet_cdev, accdet_devno, 1);
1563 if(ret)
1564 {
1565 ACCDET_DEBUG("[Accdet]accdet error: cdev_add\n");
1566 }
1567
1568 accdet_class = class_create(THIS_MODULE, ACCDET_DEVNAME);
1569
1570 // if we want auto creat device node, we must call this
1571 accdet_nor_device = device_create(accdet_class, NULL, accdet_devno, NULL, ACCDET_DEVNAME);
1572
1573 //------------------------------------------------------------------
1574 // Create input device
1575 //------------------------------------------------------------------
1576 kpd_accdet_dev = input_allocate_device();
1577 if (!kpd_accdet_dev)
1578 {
1579 ACCDET_DEBUG("[Accdet]kpd_accdet_dev : fail!\n");
1580 return -ENOMEM;
1581 }
1582
1583 //define multi-key keycode
1584 __set_bit(EV_KEY, kpd_accdet_dev->evbit);
1585 __set_bit(KEY_CALL, kpd_accdet_dev->keybit);
1586 __set_bit(KEY_ENDCALL, kpd_accdet_dev->keybit);
1587 __set_bit(KEY_NEXTSONG, kpd_accdet_dev->keybit);
1588 __set_bit(KEY_PREVIOUSSONG, kpd_accdet_dev->keybit);
1589 __set_bit(KEY_PLAYPAUSE, kpd_accdet_dev->keybit);
1590 __set_bit(KEY_STOPCD, kpd_accdet_dev->keybit);
1591 __set_bit(KEY_VOLUMEDOWN, kpd_accdet_dev->keybit);
1592 __set_bit(KEY_VOLUMEUP, kpd_accdet_dev->keybit);
1593
1594 kpd_accdet_dev->id.bustype = BUS_HOST;
1595 kpd_accdet_dev->name = "ACCDET";
1596 if(input_register_device(kpd_accdet_dev))
1597 {
1598 ACCDET_DEBUG("[Accdet]kpd_accdet_dev register : fail!\n");
1599 }else
1600 {
1601 ACCDET_DEBUG("[Accdet]kpd_accdet_dev register : success!!\n");
1602 }
1603 //------------------------------------------------------------------
1604 // Create workqueue
1605 //------------------------------------------------------------------
1606 accdet_workqueue = create_singlethread_workqueue("accdet");
1607 INIT_WORK(&accdet_work, accdet_work_callback);
1608
1609
1610 //------------------------------------------------------------------
1611 // wake lock
1612 //------------------------------------------------------------------
1613 wake_lock_init(&accdet_suspend_lock, WAKE_LOCK_SUSPEND, "accdet wakelock");
1614 wake_lock_init(&accdet_irq_lock, WAKE_LOCK_SUSPEND, "accdet irq wakelock");
1615 wake_lock_init(&accdet_key_lock, WAKE_LOCK_SUSPEND, "accdet key wakelock");
1616 wake_lock_init(&accdet_timer_lock, WAKE_LOCK_SUSPEND, "accdet timer wakelock");
1617#ifdef SW_WORK_AROUND_ACCDET_REMOTE_BUTTON_ISSUE
1618 init_waitqueue_head(&send_event_wq);
1619 //start send key event thread
1620 keyEvent_thread = kthread_run(sendKeyEvent, 0, "keyEvent_send");
1621 if (IS_ERR(keyEvent_thread))
1622 {
1623 error = PTR_ERR(keyEvent_thread);
1624 ACCDET_DEBUG( " failed to create kernel thread: %d\n", error);
1625 }
1626#endif
1627
1628#if DEBUG_THREAD
1629 if((ret = accdet_create_attr(&accdet_driver_hal.driver))!=0)
1630 {
1631 ACCDET_DEBUG("create attribute err = %d\n", ret);
1632
1633 }
1634#endif
1635
1636 long_press_time = press_key_time->headset_long_press_time;
1637
1638 ACCDET_DEBUG("[Accdet]accdet_probe : ACCDET_INIT\n");
1639 if (g_accdet_first == 1)
1640 {
1641 long_press_time_ns = (s64)long_press_time * NSEC_PER_MSEC;
1642
1643 eint_accdet_sync_flag = 1;
1644
1645 //Accdet Hardware Init
1646 pmic_pwrap_write(ACCDET_RSV, ACCDET_1V9_MODE_OFF);
1647 ACCDET_DEBUG("ACCDET use in 1.9V mode!! \n");
1648 accdet_init();
1649#ifndef MTK_ALPS_BOX_SUPPORT
1650 queue_work(accdet_workqueue, &accdet_work); //schedule a work for the first detection
1651#endif
1652 #ifdef ACCDET_EINT
1653
1654 accdet_eint_workqueue = create_singlethread_workqueue("accdet_eint");
1655 INIT_WORK(&accdet_eint_work, accdet_eint_work_callback);
1656 accdet_setup_eint();
1657 accdet_disable_workqueue = create_singlethread_workqueue("accdet_disable");
1658 INIT_WORK(&accdet_disable_work, disable_micbias_callback);
1659
1660 #endif
1661 g_accdet_first = 0;
1662 }
1663
1664 ACCDET_DEBUG("[Accdet]accdet_probe done!\n");
1665//#ifdef ACCDET_PIN_SWAP
1666 //pmic_pwrap_write(0x0400, 0x1000);
1667 //ACCDET_DEBUG("[Accdet]accdet enable VRF28 power!\n");
1668//#endif
1669
1670 return 0;
1671}
1672
1673void mt_accdet_remove(void)
1674{
1675 ACCDET_DEBUG("[Accdet]accdet_remove begin!\n");
1676
1677 //cancel_delayed_work(&accdet_work);
1678 #ifdef ACCDET_EINT
1679 destroy_workqueue(accdet_eint_workqueue);
1680 #endif
1681 destroy_workqueue(accdet_workqueue);
1682 switch_dev_unregister(&accdet_data);
1683 device_del(accdet_nor_device);
1684 class_destroy(accdet_class);
1685 cdev_del(accdet_cdev);
1686 unregister_chrdev_region(accdet_devno,1);
1687 input_unregister_device(kpd_accdet_dev);
1688 ACCDET_DEBUG("[Accdet]accdet_remove Done!\n");
1689
1690}
1691
1692void mt_accdet_suspend(void) // only one suspend mode
1693{
1694
1695//#ifdef ACCDET_PIN_SWAP
1696// pmic_pwrap_write(0x0400, 0x0);
1697// accdet_FSA8049_disable();
1698//#endif
1699
1700#ifdef ACCDET_MULTI_KEY_FEATURE
1701 ACCDET_DEBUG("[Accdet] in suspend1: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS));
1702#else
1703
1704#if 0
1705#ifdef ACCDET_EINT
1706 if(accdet_get_enable_RG()&& call_status == 0)
1707 {
1708 //record accdet status
1709 //ACCDET_DEBUG("[Accdet]accdet_working_in_suspend\n");
1710 printk(KERN_DEBUG "[Accdet]accdet_working_in_suspend\n");
1711 g_accdet_working_in_suspend = 1;
1712 pre_state_swctrl = accdet_get_swctrl();
1713 // disable ACCDET unit
1714 accdet_disable_hal();
1715 //disable_clock
1716 accdet_disable_clk();
1717 }
1718#else
1719 // disable ACCDET unit
1720 if(call_status == 0)
1721 {
1722 pre_state_swctrl = accdet_get_swctrl();
1723 accdet_disable_hal();
1724 //disable_clock
1725 accdet_disable_clk();
1726 }
1727#endif
1728#endif
1729 printk(KERN_DEBUG "[Accdet]accdet_suspend: ACCDET_CTRL=[0x%x], STATE=[0x%x]->[0x%x]\n", pmic_pwrap_read(ACCDET_CTRL), pre_state_swctrl, pmic_pwrap_read(ACCDET_STATE_SWCTRL));
1730#endif
1731}
1732
1733void mt_accdet_resume(void) // wake up
1734{
1735//#ifdef ACCDET_PIN_SWAP
1736// pmic_pwrap_write(0x0400, 0x1000);
1737// accdet_FSA8049_enable();
1738//#endif
1739
1740#ifdef ACCDET_MULTI_KEY_FEATURE
1741 ACCDET_DEBUG("[Accdet] in resume1: ACCDET_IRQ_STS = 0x%x\n", pmic_pwrap_read(ACCDET_IRQ_STS));
1742#else
1743#if 0
1744#ifdef ACCDET_EINT
1745
1746 if(1==g_accdet_working_in_suspend && 0== call_status)
1747 {
1748
1749 //enable_clock
1750 accdet_enable_hal(pre_state_swctrl);
1751 //clear g_accdet_working_in_suspend
1752 g_accdet_working_in_suspend =0;
1753 ACCDET_DEBUG("[Accdet]accdet_resume : recovery accdet register\n");
1754
1755 }
1756#else
1757 if(call_status == 0)
1758 {
1759 accdet_enable_hal(pre_state_swctrl);
1760 }
1761#endif
1762#endif
1763 printk(KERN_DEBUG "[Accdet]accdet_resume: ACCDET_CTRL=[0x%x], STATE_SWCTRL=[0x%x]\n", pmic_pwrap_read(ACCDET_CTRL), pmic_pwrap_read(ACCDET_STATE_SWCTRL));
1764
1765#endif
1766
1767}
1768/**********************************************************************
1769//add for IPO-H need update headset state when resume
1770
1771***********************************************************************/
1772#ifdef ACCDET_PIN_RECOGNIZATION
1773struct timer_list accdet_disable_ipoh_timer;
1774static void mt_accdet_pm_disable(unsigned long a)
1775{
1776 if (cable_type == NO_DEVICE && eint_accdet_sync_flag ==0) {
1777 //disable accdet
1778 pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL);
1779 pmic_pwrap_write(ACCDET_CTRL, ACCDET_DISABLE);
1780 pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0);
1781 //disable clock
1782 pmic_pwrap_write(TOP_CKPDN_SET, RG_ACCDET_CLK_SET);
1783 printk("[Accdet]daccdet_pm_disable: disable!\n");
1784 }
1785 else
1786 {
1787 printk("[Accdet]daccdet_pm_disable: enable!\n");
1788 }
1789}
1790#endif
1791void mt_accdet_pm_restore_noirq(void)
1792{
1793 int current_status_restore = 0;
1794 printk("[Accdet]accdet_pm_restore_noirq start!\n");
1795 //enable accdet
1796 pmic_pwrap_write(ACCDET_STATE_SWCTRL, (pmic_pwrap_read(ACCDET_STATE_SWCTRL)|ACCDET_SWCTRL_IDLE_EN));
1797 // enable ACCDET unit
1798 ACCDET_DEBUG("accdet: enable_accdet\n");
1799 //enable clock
1800 pmic_pwrap_write(TOP_CKPDN_CLR, RG_ACCDET_CLK_CLR);
1801 enable_accdet(ACCDET_SWCTRL_EN);
1802 eint_accdet_sync_flag = 1;
1803 current_status_restore = ((pmic_pwrap_read(ACCDET_STATE_RG) & 0xc0)>>6); //AB
1804
1805 switch (current_status_restore) {
1806 case 0: //AB=0
1807 cable_type = HEADSET_NO_MIC;
1808 accdet_status = HOOK_SWITCH;
1809 break;
1810 case 1: //AB=1
1811 cable_type = HEADSET_MIC;
1812 accdet_status = MIC_BIAS;
1813 break;
1814 case 3: //AB=3
1815 cable_type = NO_DEVICE;
1816 accdet_status = PLUG_OUT;
1817 break;
1818 default:
1819 printk("[Accdet]accdet_pm_restore_noirq: accdet current status error!\n");
1820 break;
1821 }
1822 switch_set_state((struct switch_dev *)&accdet_data, cable_type);
1823 if (cable_type == NO_DEVICE) {
1824 #ifdef ACCDET_PIN_RECOGNIZATION
1825 init_timer(&accdet_disable_ipoh_timer);
1826 accdet_disable_ipoh_timer.expires = jiffies + 3*HZ;
1827 accdet_disable_ipoh_timer.function = &mt_accdet_pm_disable;
1828 accdet_disable_ipoh_timer.data = ((unsigned long) 0 );
1829 add_timer(&accdet_disable_ipoh_timer);
1830 printk("[Accdet]enable! pm timer\n");
1831
1832 #else
1833 //eint_accdet_sync_flag = 0;
1834 //disable accdet
1835 pre_state_swctrl = pmic_pwrap_read(ACCDET_STATE_SWCTRL);
1836 pmic_pwrap_write(ACCDET_CTRL, ACCDET_DISABLE);
1837 pmic_pwrap_write(ACCDET_STATE_SWCTRL, 0);
1838 //disable clock
1839 pmic_pwrap_write(TOP_CKPDN_SET, RG_ACCDET_CLK_SET);
1840 #endif
1841 }
1842
1843}
1844////////////////////////////////////IPO_H end/////////////////////////////////////////////
1845long mt_accdet_unlocked_ioctl(unsigned int cmd, unsigned long arg)
1846{
1847// bool ret = true;
1848
1849 switch(cmd)
1850 {
1851 case ACCDET_INIT :
1852 break;
1853
1854 case SET_CALL_STATE :
1855 call_status = (int)arg;
1856 ACCDET_DEBUG("[Accdet]accdet_ioctl : CALL_STATE=%d \n", call_status);
1857 break;
1858
1859 case GET_BUTTON_STATUS :
1860 ACCDET_DEBUG("[Accdet]accdet_ioctl : Button_Status=%d (state:%d)\n", button_status, accdet_data.state);
1861 return button_status;
1862
1863 default:
1864 ACCDET_DEBUG("[Accdet]accdet_ioctl : default\n");
1865 break;
1866 }
1867 return 0;
1868}
1869