static void hook_once_work(struct work_struct *work) { int ret,val; #ifdef CONFIG_SND_SOC_WM8994 wm8994_headset_mic_detect(true); #endif #if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224) rt3261_headset_mic_detect(true); #endif #ifdef CONFIG_SND_SOC_RT5631_PHONE rt5631_headset_mic_detect(true); #endif ret = iio_read_channel_raw(headset_info->chan, &val); if (ret < 0) { pr_err("read hook_once_work adc channel() error: %d\n", ret); } else DBG("hook_once_work read adc value: %d\n",val); if(val >= 0 && val < HOOK_LEVEL_LOW) { headset_info->isMic= 0;//No microphone #ifdef CONFIG_SND_SOC_WM8994 wm8994_headset_mic_detect(false); #endif #if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224) rt3261_headset_mic_detect(false); #endif #ifdef CONFIG_SND_SOC_RT5631_PHONE rt5631_headset_mic_detect(false); #endif } else if(val >= HOOK_LEVEL_HIGH) { headset_info->isMic = 1;//have mic schedule_delayed_work(&headset_info->hook_work,msecs_to_jiffies(100)); } headset_info->cur_headset_status = headset_info->isMic ? BIT_HEADSET:BIT_HEADSET_NO_MIC; switch_set_state(&headset_info->sdev, headset_info->cur_headset_status); DBG("%s notice android headset status = %d\n",__func__,headset_info->cur_headset_status); }
//1 static irqreturn_t headset_interrupt(int irq, void *dev_id) { struct rk_headset_pdata *pdata = headset_info->pdata; static unsigned int old_status = 0; int i,level = 0; disable_irq_nosync(headset_info->irq[HEADSET]); if(headset_info->heatset_irq_working == BUSY || headset_info->heatset_irq_working == WAIT) return IRQ_HANDLED; DBG("In the headset_interrupt\n"); headset_info->heatset_irq_working = BUSY; msleep(150); for(i=0; i<3; i++) { level = gpio_get_value(pdata->headset_gpio); if(level < 0) { printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,pdata->headset_gpio,i); msleep(1); continue; } else break; } if(level < 0) { printk("%s:get pin level err!\n",__FUNCTION__); goto out; } else printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,pdata->headset_gpio,i); old_status = headset_info->headset_status; switch(pdata->headset_insert_type) { case HEADSET_IN_HIGH: if(level > 0) headset_info->headset_status = HEADSET_IN; else if(level == 0) headset_info->headset_status = HEADSET_OUT; break; case HEADSET_IN_LOW: if(level == 0) headset_info->headset_status = HEADSET_IN; else if(level > 0) headset_info->headset_status = HEADSET_OUT; break; default: DBG("---- ERROR: on headset headset_insert_type error -----\n"); break; } if(old_status == headset_info->headset_status) { DBG("Read Headset IO level old status == now status =%d\n",headset_info->headset_status); goto out; } DBG("(headset in is %s)headset status is %s\n", pdata->headset_insert_type?"high level":"low level", headset_info->headset_status?"in":"out"); if(headset_info->headset_status == HEADSET_IN) { if(pdata->chan != 0) { //detect Hook key schedule_delayed_work(&headset_info->h_delayed_work[HOOK],msecs_to_jiffies(200)); } else { headset_info->isMic= 0;//No microphone headset_info->cur_headset_status = BIT_HEADSET_NO_MIC; switch_set_state(&headset_info->sdev, headset_info->cur_headset_status); DBG("headset notice android headset status = %d\n",headset_info->cur_headset_status); } if(pdata->headset_insert_type == HEADSET_IN_HIGH) irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_FALLING); else irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_RISING); } else if(headset_info->headset_status == HEADSET_OUT) { headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC); cancel_delayed_work(&headset_info->hook_work); if(headset_info->isMic) { headset_info->hook_status = HOOK_UP; #ifdef CONFIG_SND_SOC_WM8994 //rt5625_headset_mic_detect(false); wm8994_headset_mic_detect(false); #endif #if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224) rt3261_headset_mic_detect(false); #endif #ifdef CONFIG_SND_SOC_RT5631_PHONE rt5631_headset_mic_detect(false); #endif } if(pdata->headset_insert_type == HEADSET_IN_HIGH) irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_RISING); else irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_FALLING); switch_set_state(&headset_info->sdev, headset_info->cur_headset_status); DBG("headset notice android headset status = %d\n",headset_info->cur_headset_status); } // rk_send_wakeup_key(); out: headset_info->heatset_irq_working = IDLE; enable_irq(headset_info->irq[HEADSET]); return IRQ_HANDLED; }
//1 static irqreturn_t headset_interrupt(int irq, void *dev_id) { struct rk_headset_pdata *pdata = headset_info->pdata; static unsigned int old_status = 0; int i,level = 0; int adc_value = 0; wake_lock(&headset_info->headset_on_wake); if(headset_info->heatset_irq_working == BUSY || headset_info->heatset_irq_working == WAIT) return IRQ_HANDLED; DBG("In the headset_interrupt for read headset level wake_lock headset_on_wake\n"); headset_info->heatset_irq_working = BUSY; msleep(150); for(i=0; i<3; i++) { level = gpio_get_value(pdata->Headset_gpio); if(level < 0) { printk("%s:get pin level again,pin=%d,i=%d\n",__FUNCTION__,pdata->Headset_gpio,i); msleep(1); continue; } else break; } if(level < 0) { printk("%s:get pin level err!\n",__FUNCTION__); goto out; } old_status = headset_info->headset_status; switch(pdata->headset_in_type) { case HEADSET_IN_HIGH: if(level > 0) headset_info->headset_status = HEADSET_IN; else if(level == 0) headset_info->headset_status = HEADSET_OUT; break; case HEADSET_IN_LOW: if(level == 0) headset_info->headset_status = HEADSET_IN; else if(level > 0) headset_info->headset_status = HEADSET_OUT; break; default: DBG("---- ERROR: on headset headset_in_type error -----\n"); break; } if(old_status == headset_info->headset_status) { DBG("Read Headset IO level old status == now status\n"); goto out; } DBG("(headset in is %s)headset status is %s\n", pdata->headset_in_type?"high level":"low level", headset_info->headset_status?"in":"out"); if(headset_info->headset_status == HEADSET_IN) { #if 0 while(1) { if(adc_sync_read(headset_info->client) > HOOK_DEFAULT_VAL || adc_sync_read(headset_info->client) < 0) { printk("headset is showly inside\n"); } else break; msleep(50); if(pdata->headset_in_type == HEADSET_IN_HIGH) old_status = headset_info->headset_status = gpio_get_value(pdata->Headset_gpio)?HEADSET_IN:HEADSET_OUT; else old_status = headset_info->headset_status = gpio_get_value(pdata->Headset_gpio)?HEADSET_OUT:HEADSET_IN; if(headset_info->headset_status == HEADSET_OUT) goto out1; msleep(5); } #endif if(pdata->Hook_adc_chn>=0 && 3>=pdata->Hook_adc_chn) { // wait for find Hook key //#ifdef CONFIG_SND_SOC_RT5625 CHECK_AGAIN: //headset_info->isMic = rt5625_headset_mic_detect(true); #ifdef CONFIG_SND_SOC_WM8994 wm8994_headset_mic_detect(true); #endif #if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224) rt3261_headset_mic_detect(true); #endif #ifdef CONFIG_SND_SOC_RT5631_PHONE rt5631_headset_mic_detect(true); #endif //mdelay(400); adc_value = adc_sync_read(headset_info->client); if(adc_value >= 0 && adc_value < HOOK_LEVEL_LOW) { headset_info->isMic= 0;//No microphone #ifdef CONFIG_SND_SOC_WM8994 wm8994_headset_mic_detect(false); #endif #if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224) rt3261_headset_mic_detect(false); #endif #ifdef CONFIG_SND_SOC_RT5631_PHONE rt5631_headset_mic_detect(false); #endif } else if(adc_value >= HOOK_LEVEL_HIGH) headset_info->isMic = 1;//have mic if(headset_info->isMic < 0) { printk("codec is error\n"); headset_info->heatset_irq_working = WAIT; if(pdata->headset_in_type == HEADSET_IN_HIGH) irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_LOW|IRQF_ONESHOT); else irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_HIGH|IRQF_ONESHOT); schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(0)); wake_unlock(&headset_info->headset_on_wake); return IRQ_HANDLED; } //adc_value = adc_sync_read(headset_info->client); printk("headset adc value = %d\n",adc_value); if(headset_info->isMic) { if(adc_value > HOOK_DEFAULT_VAL || adc_value < HOOK_LEVEL_HIGH) goto CHECK_AGAIN; mod_timer(&headset_info->hook_timer, jiffies + msecs_to_jiffies(1000)); } //#endif headset_info->cur_headset_status = headset_info->isMic ? BIT_HEADSET:BIT_HEADSET_NO_MIC; } else { headset_info->isMic= 0;//No microphone headset_info->cur_headset_status = BIT_HEADSET_NO_MIC; } printk("headset->isMic = %d\n",headset_info->isMic); if(pdata->headset_in_type == HEADSET_IN_HIGH) irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_FALLING); else irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_RISING); } else if(headset_info->headset_status == HEADSET_OUT) { headset_info->cur_headset_status = ~(BIT_HEADSET|BIT_HEADSET_NO_MIC); del_timer(&headset_info->hook_timer); if(headset_info->isMic) { headset_info->hook_status = HOOK_UP; #ifdef CONFIG_SND_SOC_WM8994 //rt5625_headset_mic_detect(false); wm8994_headset_mic_detect(false); #endif #if defined (CONFIG_SND_SOC_RT3261) || defined (CONFIG_SND_SOC_RT3224) rt3261_headset_mic_detect(false); #endif #ifdef CONFIG_SND_SOC_RT5631_PHONE rt5631_headset_mic_detect(false); #endif } if(pdata->headset_in_type == HEADSET_IN_HIGH) irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_RISING); else irq_set_irq_type(headset_info->irq[HEADSET],IRQF_TRIGGER_FALLING); } rk28_send_wakeup_key(); switch_set_state(&headset_info->sdev, headset_info->cur_headset_status); DBG("headset notice android headset status = %d\n",headset_info->cur_headset_status); // schedule_delayed_work(&headset_info->h_delayed_work[HEADSET], msecs_to_jiffies(0)); out: headset_info->heatset_irq_working = IDLE; wake_unlock(&headset_info->headset_on_wake); return IRQ_HANDLED; }