static int Remote_Interrupt_Enable(int en) { int ret =0; struct pm8xxx_mpp_config_data sky_handset_digital_adc = { .type = PM8XXX_MPP_TYPE_D_INPUT, .level = PM8058_MPP_DIG_LEVEL_S3, .control = PM8XXX_MPP_DIN_TO_INT, }; if(en) { ret=gpio_get_value_cansleep(hspd->ear_det); if(ret!=hspd->ear_det_active) { printk("EARJACK_DET %d\n",ret); return -1; } if(hspd->curr_state == MSM_HEADSET && hspd->remote_is_int==0) { #if AT1_BDVER_GE(AT1_WS22) ret = pm8xxx_mpp_config(PM8058_MPP_PM_TO_SYS(XOADC_MPP_3), &sky_handset_digital_adc); if (ret < 0) printk("%s: pm8058_mpp_config_DIG ret=%d\n",__func__, ret); /* ret = pm8058_mpp_config_digital_in(PM8058_MPP_SYS_TO_PM(hspd->remote_det), PM8058_MPP_DIG_LEVEL_S3, PM_MPP_DIN_TO_INT); */ #else gpio_tlmm_config(GPIO_CFG(hspd->remote_det, 0, GPIO_CFG_INPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); #endif enable_irq(gpio_to_irq(hspd->remote_det)); irq_set_irq_wake(gpio_to_irq(hspd->remote_det),1); hspd->remote_is_int = 1; } } else { if(hspd->remote_is_int==1) { irq_set_irq_wake(gpio_to_irq(hspd->remote_det),0); disable_irq(gpio_to_irq(hspd->remote_det)); hspd->remote_is_int = 0; #if AT1_BDVER_E(AT1_WS21) gpio_tlmm_config(GPIO_CFG(hspd->remote_det, 0, GPIO_CFG_INPUT,GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); #endif } } return 0; }
static int __devinit hs_probe(struct platform_device *pdev) { int rc = 0,err; struct input_dev *ipdev; struct pm8xxx_mpp_config_data sky_handset_digital_adc = { .type = PM8XXX_MPP_TYPE_D_INPUT, .level = PM8058_MPP_DIG_LEVEL_S3, .control = PM8XXX_MPP_DIN_TO_INT, }; hs_dbg("hs_probe start!!!\n"); headset_init=0; //sky_hs_3p5pi_jack_ctrl.state=SKY_HS_JACK_STATE_INIT; hs = kzalloc(sizeof(struct msm_headset), GFP_KERNEL); if (!hs) return -ENOMEM; hspd = kzalloc(sizeof(struct msm_headset_platform_data), GFP_KERNEL); if (!hspd) return -ENOMEM; #if 0 hs->sdev.name = "h2w"; #else hs->sdev.name = "hw2"; #endif hs->sdev.print_name = msm_headset_print_name; rc = switch_dev_register(&hs->sdev); if (rc) goto err_switch_dev_register; ipdev = input_allocate_device(); if (!ipdev) { rc = -ENOMEM; goto err_switch_dev; } input_set_drvdata(ipdev, hs); hs->ipdev = ipdev; if (pdev->dev.platform_data) { hs->hs_pdata = pdev->dev.platform_data; hspd = pdev->dev.platform_data; } if (hs->hs_pdata->hs_name) ipdev->name = hs->hs_pdata->hs_name; else ipdev->name = DRIVER_NAME; mutex_init(&headset_adc_lock); INIT_DELAYED_WORK(&earjack_work,earjack_det_func); INIT_DELAYED_WORK(&remotekey_work,remotekey_det_func); wake_lock_init(&headset_wakelock, WAKE_LOCK_SUSPEND, "Headset_wakelock"); ipdev->id.vendor = 0x0001; ipdev->id.product = 1; ipdev->id.version = 1; input_set_capability(ipdev, EV_KEY, KEY_MEDIA); input_set_capability(ipdev, EV_KEY, KEY_VOLUMEUP); input_set_capability(ipdev, EV_KEY, KEY_VOLUMEDOWN); //input_set_capability(ipdev, EV_KEY, KEY_END); input_set_capability(ipdev, EV_SW, SW_HEADPHONE_INSERT); //input_set_capability(ipdev, EV_KEY, KEY_POWER); //input_set_capability(ipdev, EV_KEY, KEY_SEND); rc = input_register_device(ipdev); if (rc) { dev_err(&ipdev->dev, "hs_probe: input_register_device rc=%d\n", rc); goto err_reg_wakelock; } /* Enable runtime PM ops, start in ACTIVE mode */ //rc = pm_runtime_set_active(&pdev->dev); //if (rc < 0) // dev_dbg(&pdev->dev, "unable to set runtime pm state\n"); //pm_runtime_enable(&pdev->dev); platform_set_drvdata(pdev, hs); device_init_wakeup(&pdev->dev,1); hs_jack_l8 = regulator_get(NULL, "8058_l8"); if(IS_ERR(hs_jack_l8)) { printk("regulator l8 get error\n"); goto err_reg_input_dev; } // Added sysfs. (/sys/devices/platform/msm-handset/headset) rc = sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp); if (rc) { dev_err(&ipdev->dev, "hs_probe: sysfs_create_group rc=%d\n", rc); goto err_reg_input_dev; } err = gpio_request(hspd->ear_det, "headset_det"); if(err) { printk("unable to request gpio headset_det err=%d\n",err); goto err_reg_input_dev; } err=gpio_direction_input(hspd->ear_det); if(err) { printk("Unable to set direction headset_det err=%d\n",err); goto err_reg_input_dev; } #if AT1_BDVER_GE(AT1_WS22) gpio_tlmm_config(GPIO_CFG(hspd->ear_det, 0, GPIO_CFG_INPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); #else gpio_tlmm_config(GPIO_CFG(hspd->ear_det, 0, GPIO_CFG_INPUT,GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); #endif //gpio_set_debounce(hspd->ear_det,5); //set_irq_wake(gpio_to_irq(hspd->ear_det),1); err=request_irq(gpio_to_irq(hspd->ear_det), Earjack_Det_handler, IRQF_DISABLED|IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "earjack_det-irq", hs); if (err < 0) { printk("Couldn't acquire ear_det as request_irq()"); goto err_reg_input_dev; } irq_set_irq_wake(gpio_to_irq(hspd->ear_det),1); err = gpio_request(hspd->remote_det, "remote_det"); if(err) { printk("unable to request gpio remote_det err=%d\n",err); goto err_reg_input_dev; } #if AT1_BDVER_GE(AT1_WS22) err = pm8xxx_mpp_config(PM8058_MPP_PM_TO_SYS(XOADC_MPP_3), &sky_handset_digital_adc); if (err < 0) printk("%s: pm8058_mpp_config_DIG ret=%d\n",__func__, err); /* err = pm8058_mpp_config_digital_in(PM8058_MPP_SYS_TO_PM(hspd->remote_det), PM8058_MPP_DIG_LEVEL_S3, PM_MPP_DIN_TO_INT); err |= pm8058_mpp_config_bi_dir(PM8058_MPP_SYS_TO_PM(hspd->remote_det), PM8058_MPP_DIG_LEVEL_S3, PM_MPP_BI_PULLUP_OPEN); */ printk("mpp config %d mpp %d err=%d\n",hspd->remote_det, PM8058_MPP_SYS_TO_PM(hspd->remote_det),err); printk(" remote %d %d\n",gpio_to_irq(hspd->remote_det),PM8058_MPP_IRQ(PM8058_IRQ_BASE,PM8058_MPP_SYS_TO_PM(hspd->remote_det))); err=request_threaded_irq(gpio_to_irq(hspd->remote_det),NULL, Remotekey_Det_handler,IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "remote_det-irq", hs); #else err=gpio_direction_input(hspd->remote_det); if(err) { printk("Unable to set direction remote_det err=%d\n",err); goto err_reg_input_dev; } //gpio_tlmm_config(GPIO_CFG(hspd->remote_det, 0, GPIO_CFG_INPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(hspd->remote_det, 0, GPIO_CFG_INPUT,GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); //gpio_set_debounce(hspd->remote_det,5); err=request_irq(gpio_to_irq(hspd->remote_det), Remotekey_Det_handler, IRQF_DISABLED|IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "remote_det-irq", hs); #endif if (err < 0) { printk("Couldn't acquire remote_det as request_irq()"); goto err_reg_input_dev; } disable_irq(gpio_to_irq(hspd->remote_det)); headset_init=1; // headset init rc=gpio_get_value_cansleep(hspd->ear_det); if(rc==hspd->ear_det_active) { schedule_delayed_work(&earjack_work,msecs_to_jiffies(200)); //schedule_delayed_work(&earjack_work,200); } printk("hs_probe success!!!\n"); return 0; err_reg_input_dev: input_unregister_device(ipdev); err_reg_wakelock: wake_lock_destroy(&headset_wakelock); input_free_device(ipdev); err_switch_dev: switch_dev_unregister(&hs->sdev); err_switch_dev_register: kfree(hspd); kfree(hs); return rc; }
static int Check_ADC_MPP(int *nValue) { int err=0,ret=0,result=0; void *h; struct adc_chan_result adc_chan_result; //long timeout=0; struct completion conv_complete_evt; struct pm8xxx_mpp_config_data sky_handset_analog_adc = { .type = PM8XXX_MPP_TYPE_A_INPUT, .level = PM8XXX_MPP_AIN_AMUX_CH5, .control = PM8XXX_MPP_AOUT_CTRL_DISABLE, }; mutex_lock(&headset_adc_lock); ret=gpio_get_value_cansleep(hspd->ear_det); if(ret!=hspd->ear_det_active) { printk("EARJACK_DET %d\n",ret); mutex_unlock(&headset_adc_lock); return -1; } #if AT1_BDVER_GE(AT1_WS22) if(hspd->curr_state == MSM_HEADSET) { Remote_Interrupt_Enable(0); msleep(1); } #endif //sys_gpio= PM8901_GPIO_PM_TO_SYS(mpp); //err=pm8058_mpp_config_analog_input(XOADC_MPP_3,PM_MPP_AIN_AMUX_CH5, PM_MPP_AOUT_CTL_DISABLE); err = pm8xxx_mpp_config(PM8058_MPP_PM_TO_SYS(XOADC_MPP_3), &sky_handset_analog_adc); if(err) { printk("pm8058_mpp_config_analog_input() err=%d\n",err); mutex_unlock(&headset_adc_lock); return -1; } ret = adc_channel_open(CHANNEL_ADC_HDSET, &h); if(ret) { printk("couldn't open channel %d ret=%d\n",CHANNEL_ADC_HDSET,ret); mutex_unlock(&headset_adc_lock); return -1; } init_completion(&conv_complete_evt); ret = adc_channel_request_conv(h, &conv_complete_evt); if(ret) { printk("couldn't request convert channel %d ret=%d\n",CHANNEL_ADC_HDSET,ret); result=-2; goto check_adc_out; } wait_for_completion(&conv_complete_evt); /* timeout=wait_for_completion_timeout(&conv_complete_evt,msecs_to_jiffies(100)); if(timeout<=0) { printk("headset ADC timeout\n"); result=-3; goto check_adc_out; } */ ret = adc_channel_read_result(h, &adc_chan_result); if(ret) { printk("could't read result channel %d ret=%d\n",CHANNEL_ADC_HDSET,ret); result=-4; goto check_adc_out; } *nValue=(int)adc_chan_result.measurement; check_adc_out: ret = adc_channel_close(h); if(ret) { printk("could't close channel %d ret=%d\n",CHANNEL_ADC_HDSET,ret); mutex_unlock(&headset_adc_lock); return -1; } #if AT1_BDVER_GE(AT1_WS22) if(hspd->curr_state == MSM_HEADSET) { Remote_Interrupt_Enable(1); } #endif //printk("ADC value=%d, physical=%d\n",(int)adc_chan_result.measurement,adc_chan_result.physical); mutex_unlock(&headset_adc_lock); return result; }
static void remotekey_detect_func(struct work_struct * test_remotekey_work) { int key_first=0; int key_second=0; // int key_third=0; struct pm8xxx_mpp_config_data pantech_presto_earjack_remote_adc = { .type = PM8XXX_MPP_TYPE_A_INPUT, .level = PM8XXX_MPP_AIN_AMUX_CH5, .control = PM8XXX_MPP_AOUT_CTRL_DISABLE, }; struct pm8xxx_mpp_config_data pantech_presto_earjack_digital_adc = { .type = PM8XXX_MPP_TYPE_D_INPUT, .level = PM8058_MPP_DIG_LEVEL_S3, .control = PM8XXX_MPP_DIN_TO_INT, }; dbg_func_in(); // car kit if(earjack->car_kit ){ if(EARJACK_INSERTED){ dbg("report KEY_MEDIA input from car_kit"); input_report_key(earjack->ipdev, KEY_MEDIA, earjack->remotekey_pressed); // car kit button down earjack->car_kit = 0; // reset car_kit flag if(REMOTEKEY_RELEASED) { earjack->remotekey_pressed = 0; input_report_key(earjack->ipdev, KEY_MEDIA, earjack->remotekey_pressed); // car kit button up } } input_sync(earjack->ipdev); earjack->car_kit = 0; // reset car_kit flag. enable_irq(gpio_to_irq(REMOTEKEY_DET)); wake_unlock(&remotekey_wake_lock); dbg_func_out(); return ; } // if current state: key not pressed if(!earjack->remotekey_pressed){ dbg("current state: remotekey not pressed, read adc value. \n"); pm8xxx_mpp_config(PM8058_MPP_PM_TO_SYS(2), &pantech_presto_earjack_remote_adc); //pm8058_mpp_config_analog_input(XOADC_MPP_3,PM_MPP_AIN_AMUX_CH5, PM_MPP_AOUT_CTL_DISABLE); // read adc value twice key_first=adc_value_to_key(); key_second=adc_value_to_key(); // after 20ms (adc reading delay) pm8xxx_mpp_config(PM8058_MPP_PM_TO_SYS(2), &pantech_presto_earjack_digital_adc); //pm8058_mpp_config_digital_in(XOADC_MPP_3,PM8058_MPP_DIG_LEVEL_S3, PM_MPP_DIN_TO_INT); // is valid key && earjack inserted if( (key_first==key_second) && EARJACK_INSERTED){ earjack->remotekey_index = key_first; earjack->remotekey_pressed = 1; if (earjack->remotekey_index != 0 && !earjack->car_kit) { input_report_key(earjack->ipdev, remotekey_type[earjack->remotekey_index].key_index, earjack->remotekey_pressed); dbg("remote key: %s : %d->%d \n", remotekey_type[earjack->remotekey_index].key_name, !earjack->remotekey_pressed, earjack->remotekey_pressed); } else if (earjack->car_kit) { schedule_delayed_work(&remotekey_work, 20); // for car kit : delayed work after 200ms for __ TODO return; } // Defense code :key pressed but released during processing key. if(REMOTEKEY_RELEASED){ earjack->remotekey_pressed=0; if (earjack->remotekey_index != 0) input_report_key(earjack->ipdev, remotekey_type[earjack->remotekey_index].key_index, earjack->remotekey_pressed); dbg("remote key: %s : %d->%d \n", remotekey_type[earjack->remotekey_index].key_name, !earjack->remotekey_pressed, earjack->remotekey_pressed); } } // else, ignore key else { dbg("igrnore key.\n"); enable_irq(gpio_to_irq(REMOTEKEY_DET)); wake_unlock(&remotekey_wake_lock); dbg_func_out(); return ; } } // if current state : key pressed else { earjack->remotekey_pressed=0; if (earjack->remotekey_index != 0) input_report_key(earjack->ipdev, remotekey_type[earjack->remotekey_index].key_index, earjack->remotekey_pressed); dbg("remote key: %s : %d->%d \n", remotekey_type[earjack->remotekey_index].key_name, !earjack->remotekey_pressed, earjack->remotekey_pressed); } input_sync(earjack->ipdev); enable_irq(gpio_to_irq(REMOTEKEY_DET)); wake_unlock(&remotekey_wake_lock); dbg_func_out(); return; }
static void earjack_detect_func( struct work_struct *test_earjack) { int err; struct pm8xxx_mpp_config_data pantech_presto_earjack_adc = { .type = PM8XXX_MPP_TYPE_D_INPUT, .level = PM8058_MPP_DIG_LEVEL_S3, .control = PM8XXX_MPP_DIN_TO_INT, }; dbg_func_in(); dbg("currnet earjack->type: "); switch(earjack->type){ case EARJACK_STATE_OFF : { dbg_without_label("EARJACK_STATE_OFF\n"); if(EARJACK_INSERTED){ earjack->type = EARJACK_STATE_CHECK; #if defined(CONFIG_MIC_BIAS_1_8V) #else err=regulator_is_enabled(hs_jack_l8); if(err<=0) err = regulator_enable(hs_jack_l8); #endif //defined(CONFIG_MACH_MSM8X60_PRESTO) pm8xxx_mpp_config(PM8058_MPP_PM_TO_SYS(2), &pantech_presto_earjack_adc); //pm8058_mpp_config_digital_in(XOADC_MPP_3,PM8058_MPP_DIG_LEVEL_S3, PM_MPP_DIN_TO_INT); schedule_delayed_work(&earjack_work, 5); //50ms // return without enable IRQ, wake_unlock. return; } break; } case EARJACK_STATE_CHECK : { dbg_without_label("EARJACK_STATE_CHECK\n"); if(EARJACK_INSERTED) { // 3pole if(!is_4pole_earjack()){ dbg("3pole headset inserted.\n"); earjack->type= EARJACK_STATE_ON_3POLE_CHECK; earjack->mic_on = 0; earjack->hs_on = 1; input_report_switch(earjack->ipdev, SW_HEADPHONE_INSERT,earjack->hs_on); switch_set_state(&earjack->sdev, switch_state()); schedule_delayed_work(&earjack_work, 60); // check if 4pole 600ms // return without enable IRQ, wake_unlock. return; } //4pole else { dbg("4pole headset inserted.\n"); earjack->type= EARJACK_STATE_ON; err=request_threaded_irq(gpio_to_irq(REMOTEKEY_DET),NULL,Remotekey_Det_handler,IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "remote_det-irq", earjack); if(err) dbg("request_threaded_irq failed\n"); earjack->mic_on = 1; earjack->hs_on = 1; input_report_switch(earjack->ipdev, SW_MICROPHONE_INSERT,earjack->mic_on); //TODO: NO USE? input_report_switch(earjack->ipdev, SW_HEADPHONE_INSERT,earjack->hs_on); switch_set_state(&earjack->sdev, switch_state()); } } else // if EARJACK_RELEASED { earjack->type = EARJACK_STATE_OFF; dbg("earjack_type: -> EARJACK_STATE_OFF"); } break; // case EARJACK_STATE_CHECK } case EARJACK_STATE_ON_3POLE_CHECK : { // CHECKING IF 4POLE EARJACK IS INSERTIND? dbg_without_label("EARJACK_STATE_ON_3POLE_CHECK\n"); if(EARJACK_INSERTED){ earjack->type= EARJACK_STATE_ON; if(!is_4pole_earjack()){ dbg("3pole earjack insert.\n"); #if defined(CONFIG_MIC_BIAS_1_8V) #else err=regulator_is_enabled(hs_jack_l8); dbg("regulator_is_enabled(hs_jack_l8) value => %d\n",err); if(err>0) regulator_disable(hs_jack_l8); #endif //defined(CONFIG_MACH_MSM8X60_PRESTO) } else { dbg("4pole earjack insert.\n"); earjack->mic_on =1; input_report_switch(earjack->ipdev, SW_MICROPHONE_INSERT,earjack->mic_on); switch_set_state(&earjack->sdev, switch_state()); err=request_threaded_irq(gpio_to_irq(REMOTEKEY_DET),NULL,Remotekey_Det_handler,IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "remote_det-irq", earjack); if(err) dbg("request_threaded_irq failed\n"); } } else{ #if defined(CONFIG_MIC_BIAS_1_8V) #else err=regulator_is_enabled(hs_jack_l8); dbg("regulator_is_enabled(hs_jack_l8) value => %d\n",err); if(err>0) regulator_disable(hs_jack_l8); #endif// defined(CONFIG_MACH_MSM8X60_PRESTO) earjack->type = EARJACK_STATE_OFF; earjack->hs_on=0; input_report_switch(earjack->ipdev, SW_HEADPHONE_INSERT,earjack->hs_on); switch_set_state(&earjack->sdev, switch_state()); } break; } case EARJACK_STATE_ON: { dbg_without_label("EARJACK_STATE_ON\n"); if(EARJACK_RELEASED){ earjack->type = EARJACK_STATE_OFF; // if 4pole if (earjack->mic_on) { earjack->mic_on = 0; input_report_switch(earjack->ipdev, SW_MICROPHONE_INSERT,earjack->mic_on); // free remote key irq and turn off mic power. free_irq(gpio_to_irq(REMOTEKEY_DET), earjack); #if defined(CONFIG_MIC_BIAS_1_8V) #else err=regulator_is_enabled(hs_jack_l8); dbg("regulator_is_enabled(hs_jack_l8) value => %d\n",err); if(err>0){ regulator_disable(hs_jack_l8); } #endif //defined(CONFIG_MACH_MSM8X60_PRESTO) // release remote key if pressed if(earjack->remotekey_pressed){ earjack->remotekey_pressed = 0; if (earjack->remotekey_index != 0) input_report_key(earjack->ipdev, remotekey_type[earjack->remotekey_index].key_index, earjack->remotekey_pressed); dbg("remote key: %s : %d->%d \n", remotekey_type[earjack->remotekey_index].key_name, !earjack->remotekey_pressed, earjack->remotekey_pressed); input_sync(earjack->ipdev); } dbg("earjack_release \n"); } earjack->hs_on = 0; input_report_switch(earjack->ipdev, SW_HEADPHONE_INSERT,earjack->hs_on); switch_set_state(&earjack->sdev, switch_state()); } break; } default : dbg("earjack_detect_func default.\n"); } enable_irq_detect(); //enable_irq(gpio_to_irq(EARJACK_DET)); wake_unlock(&earjack_wake_lock); dbg_func_out(); return; }