static irqreturn_t headset_button_irq_handler(int irq, void *dev) { struct _headset_gpio *hgp = dev; int det_status; wake_lock_timeout(&hgp->gpio_wakelock,HZ*4); del_timer(&hgp->gpio_timer); det_status = headset_gpio_get_value(hgp->gpio); pr_debug("%s : %s %s\n", __func__, hgp->desc, hgp->active ? "active" : "inactive"); if(det_status != 1){ hgp->active = 1; headset_gpio_set_irq_type(hgp->irq, hgp->irq_type_inactive); mod_timer(&hgp->gpio_timer, jiffies + msecs_to_jiffies(100)); } else { hgp->active = 0; headset_gpio_set_irq_type(hgp->irq, hgp->irq_type_active); mod_timer(&hgp->gpio_timer,jiffies + msecs_to_jiffies(100)); } return IRQ_HANDLED; }
/* add for control of external mic bias - ffkaka */ static void headset_mic_bias_control(int mode) { int gpio_value; gpio_value=headset_gpio_get_value(HEADSET_MICBIAS_GPIO); //pr_info("[headset] before gpio_value=0x%08x \n",gpio_value); if(mode){ if(gpio_value == 0x00){ gpio_direction_output(HEADSET_MICBIAS_GPIO,1); pr_info("[headset] Enable Headset MIC BIAS!!!\n"); } else pr_info("[headset] MIC BIAS was already enabled!!!\n"); //sprd_codec_auxmic_bias_control(1); } else{ if(gpio_value == 0x01){ gpio_direction_output(HEADSET_MICBIAS_GPIO,0); pr_info("[headset] Disable Headset MIC BIAS!!!\n"); } else pr_info("[headset] MIC BIAS was already disabled!!!\n"); //sprd_codec_auxmic_bias_control(0); } }
static enum hrtimer_restart headset_gpio_timer_func(struct hrtimer *timer) { enum hrtimer_restart restart = HRTIMER_RESTART; struct _headset_gpio *hgp = container_of(timer, struct _headset_gpio, timer); int active = hgp->active_low ^ headset_gpio_get_value(hgp->gpio); /* hgp->active */ int green_ch = (!active && &hgp->parent->detect == hgp); if (active != hgp->active) { pr_info("The value %s mismatch [%d:%d] at %dms!\n", hgp->desc, active, hgp->active, hgp->holded); hgp->holded = 0; } pr_debug("%s : %s %s green_ch[%d], holed=%d, debounce_sw=%d\n", __func__, hgp->desc, active ? "active" : "inactive", green_ch, hgp->holded, hgp->debounce_sw); hgp->holded += HEADSET_GPIO_DEBOUNCE_SW_SAMPLE_PERIOD; if (hgp->holded >= hgp->debounce_sw || green_ch) { if (hgp->holded == hgp->debounce_sw || \ hgp->holded == hgp->timeout_ms || \ green_ch) { pr_debug("call headset gpio handler\n"); restart = hgp->callback(active, hgp); } else pr_debug("gpio <%d> has kept active for %d ms\n", hgp->gpio, hgp->holded); } if (restart == HRTIMER_RESTART) hrtimer_forward_now(timer, ktime_set(HEADSET_GPIO_DEBOUNCE_SW_SAMPLE_PERIOD / 1000, (HEADSET_GPIO_DEBOUNCE_SW_SAMPLE_PERIOD % 1000) * 1000000)); /* repeat timer */ return restart; }
static void headset_detect_gpio_work(struct work_struct *work) { struct _headset_gpio *hgp = container_of(work, struct _headset_gpio, gpio_work); int com_detect = headset_gpio_get_value(HEADSET_COM_DETECT_GPIO); if (hgp->active) { /* Active=1 plug in case - ffkaka */ if(com_detect == 1){ pr_info("[headset] Fake hs detection interrupt!!! com_detect[%d]\n",com_detect); det_cnt=0; headset_gpio_set_irq_type(hgp->irq, hgp->irq_type_active); return; } if(det_cnt < HEADSET_DET_RETRY_CNT){ det_cnt++; mod_timer(&hgp->gpio_timer,jiffies + msecs_to_jiffies(75)); return; } headset_hs_detect_mode(hgp); if (hgp->parent->headphone) { switch_set_state(&hgp->parent->sdev, BIT_HEADSET_NO_MIC); /* add for control of external mic bias REV0.1 - ffkaka */ headset_mic_bias_control(0); pr_info("[headset] headphone plug in\n"); } else { switch_set_state(&hgp->parent->sdev, BIT_HEADSET_MIC); pr_info("[headset] headset plug in\n"); headset_gpio_set_irq_type(hgp->parent->button.irq, hgp->parent->button.irq_type_active); headset_gpio_irq_enable(1, &hgp->parent->button); } } else { /* Active=0 unplug case - ffkaka */ headset_gpio_irq_enable(0, &hgp->parent->button); /* add for control of external mic bias REV0.1 - ffkaka */ headset_mic_bias_control(0); if (hgp->parent->headphone){ hgp->parent->headphone = 0; pr_info("[headset] headphone unplugged\n"); } else pr_info("[headset] headset unplugged\n"); switch_set_state(&hgp->parent->sdev, BIT_HEADSET_OUT); } det_cnt=0; }
static irqreturn_t headset_gpio_irq_handler(int irq, void *dev) { struct _headset_gpio *hgp = dev; hrtimer_cancel(&hgp->timer); hgp->active = hgp->active_low ^ headset_gpio_get_value(hgp->gpio); headset_gpio_set_irq_type(hgp->irq, hgp->active ? hgp->irq_type_inactive : hgp->irq_type_active); pr_debug("%s : %s %s\n", __func__, hgp->desc, hgp->active ? "active" : "inactive"); hgp->holded = 0; hrtimer_start(&hgp->timer, ktime_set(HEADSET_GPIO_DEBOUNCE_SW_SAMPLE_PERIOD / 1000, (HEADSET_GPIO_DEBOUNCE_SW_SAMPLE_PERIOD % 1000) * 1000000), HRTIMER_MODE_REL); return IRQ_HANDLED; }
/* gnd detect sys fs - ffkaka */ static ssize_t headset_gnd_detect_show(struct device *dev, struct device_attribute *attr,char *buf) { return sprintf(buf,"GND DET= %d\n",headset_gpio_get_value(HEADSET_COM_DETECT_GPIO)); }