static void sec_jack_det_work_func(struct work_struct *work) { struct sec_jack_info *hi = container_of(work, struct sec_jack_info, det_work); struct sec_jack_platform_data *pdata = hi->pdata; int time_left_ms = DET_CHECK_TIME_MS; pr_debug(MODULE_NAME "%s\n", __func__); /* threaded irq can sleep */ wake_lock_timeout(&hi->det_wake_lock, WAKE_LOCK_TIME); #ifdef CONFIG_MACH_JAGUAR if ((hi->cur_jack_type == SEC_HEADSET_4POLE) && sendkey_irq_progress) { pr_info(MODULE_NAME "%s / 120ms Delay\n", __func__); usleep_range(120000, 120000); } else { pr_info(MODULE_NAME "%s / No Delay\n", __func__); sendkey_irq_progress = false; } #endif /* debounce headset jack. don't try to determine the type of * headset until the detect state is true for a while. */ while (time_left_ms > 0) { if (!pdata->get_det_jack_state()) { /* jack not detected. */ handle_jack_not_inserted(hi); return; } usleep_range(10000, 10000); time_left_ms -= 10; } #if defined(CONFIG_SAMSUNG_JACK_GNDLDET) /* G plus L Detection */ if (!hi->pdata->get_l_jack_state()) return; #endif /* set mic bias to enable adc */ pdata->set_micbias_state(true); /* to reduce noise in earjack when attaching */ /* msleep(200); */ /* jack presence was detected the whole time, figure out which type */ determine_jack_type(hi); return; }
static void sec_jack_det_work_func(struct work_struct *work) { struct sec_jack_info *hi = container_of(work, struct sec_jack_info, det_work); struct sec_jack_platform_data *pdata = hi->pdata; int time_left_ms = DET_CHECK_TIME_MS; int jack_state = 0; pr_debug(MODULE_NAME "%s\n", __func__); /* threaded irq can sleep */ wake_lock_timeout(&hi->det_wake_lock, WAKE_LOCK_TIME); /* debounce headset jack. don't try to determine the type of * headset until the detect state is true for a while. */ while (time_left_ms > 0) { jack_state = pdata->get_det_jack_state(); if (!jack_state) { pr_err("%s : err det jack state %d\n", __func__, jack_state); /* jack not detected. */ handle_jack_not_inserted(hi); return; } usleep_range(10000, 10000); time_left_ms -= 10; } /* set mic bias to enable adc */ pdata->set_micbias_state(true); /* to reduce noise in earjack when attaching */ /* msleep(200); */ /* jack presence was detected the whole time, figure out which type */ determine_jack_type(hi); return; }
static void determine_jack_type(struct sec_jack_info *hi) { struct sec_jack_zone *zones = hi->pdata->zones; struct sec_jack_platform_data *pd = hi->pdata; int size = hi->pdata->num_zones; int count[MAX_ZONE_LIMIT] = {0}; int adc; int i; struct adc_queue *adc_q = init_adc_queue(); #if defined (CONFIG_MACH_MELIUS_CHN_CTC) if (nv_hw_revision > 7 || nv_hw_revision < 2) zones = pd->zones_rev08; #elif defined (CONFIG_MACH_SERRANO_ATT) || defined(CONFIG_MACH_SERRANO_VZW) || defined(CONFIG_MACH_SERRANO_USC) || defined(CONFIG_MACH_SERRANO_LRA) if (system_rev > 2) zones = pd->zones_rev03; #endif while (pd->get_det_jack_state()) { #ifdef CONFIG_SAMSUNG_JACK_ADC_SCALE3 adc = pd->get_ear_adc_value(); #else adc = pd->get_adc_value(); #endif if (adc < 0) break; add_adc_queue(adc_q, adc); /* determine the type of headset based on the * adc value. An adc value can fall in various * ranges or zones. Within some ranges, the type * can be returned immediately. Within others, the * value is considered unstable and we need to sample * a few more types (up to the limit determined by * the range) before we return the type for that range. */ for (i = 0; i < size; i++) { if (adc <= zones[i].adc_high) { if (++count[i] > zones[i].check_count) { print_adc_queue(adc_q); pr_debug(MODULE_NAME "determine_jack_type %d, %d, %d\n", zones[i].adc_high, count[i], zones[i].check_count); #if defined(CONFIG_SAMSUNG_JACK_GNDLDET) /* G plus L Detection */ if (!hi->pdata->get_gnd_jack_state()) { pr_err("%s : err 2nd det jack state\n", __func__); handle_jack_not_inserted(hi); recheck_jack = false; return; } #else if (recheck_jack == true && i == 3) { pr_err(MODULE_NAME "something wrong connectoin!\n"); handle_jack_not_inserted(hi); recheck_jack = false; return; } #endif sec_jack_set_type(hi, zones[i].jack_type); /* mic_bias remains enabled * in race condition. */ if (hi->cur_jack_type != SEC_HEADSET_4POLE) { pd->set_micbias_state(false); pr_info(MODULE_NAME "forced mic_bias disable\n"); } recheck_jack = false; return; } #if defined CONFIG_MACH_GOLDEN msleep(zones[i].delay_ms); #else usleep_range(zones[i].delay_ms*1000, zones[i].delay_ms*1000); #endif break; } } } /* jack removed before detection complete */ recheck_jack = false; pr_err("%s : err det jack state\n", __func__); print_adc_queue(adc_q); handle_jack_not_inserted(hi); }
static void determine_jack_type(struct sec_jack_info *hi) { struct sec_jack_zone *zones = hi->pdata->zones; int size = hi->pdata->num_zones; int count[MAX_ZONE_LIMIT] = {0}; int adc; int i; while (hi->pdata->get_det_jack_state()) { adc = hi->pdata->get_adc_value(); pr_info(MODULE_NAME "determine_jack_type adc = %d\n", adc); /* determine the type of headset based on the * adc value. An adc value can fall in various * ranges or zones. Within some ranges, the type * can be returned immediately. Within others, the * value is considered unstable and we need to sample * a few more types (up to the limit determined by * the range) before we return the type for that range. */ for (i = 0; i < size; i++) { if (adc <= zones[i].adc_high) { if (++count[i] > zones[i].check_count) { pr_debug(MODULE_NAME "determine_jack_type %d, %d, %d\n", zones[i].adc_high, count[i], zones[i].check_count); #ifndef CONFIG_MACH_JAGUAR if (recheck_jack == true && i == 3) { #else if (recheck_jack == true && i == 5) { #endif pr_err(MODULE_NAME "something wrong connectoin!\n"); handle_jack_not_inserted(hi); recheck_jack = false; return; } sec_jack_set_type(hi, zones[i].jack_type); /* mic_bias remains enabled * in race condition. */ if (hi->cur_jack_type != SEC_HEADSET_4POLE) { hi->pdata->set_micbias_state(false); pr_info(MODULE_NAME "forced mic_bias disable\n"); } recheck_jack = false; return; } msleep(zones[i].delay_ms); break; } } } /* jack removed before detection complete */ recheck_jack = false; handle_jack_not_inserted(hi); } #ifdef SUPPORT_PBA static ssize_t key_state_onoff_show(struct device *dev, struct device_attribute *attr, char *buf) { struct sec_jack_info *hi = dev_get_drvdata(dev); #ifdef CONFIG_MACH_JAGUAR struct sec_jack_platform_data *pdata = hi->pdata; #endif int value = 0; #ifdef CONFIG_MACH_JAGUAR int send_key_state = 0; #endif #ifndef CONFIG_MACH_JAGUAR if (hi->send_key_pressed != true) value = 0; else value = 1; #else send_key_state = pdata->get_send_key_state(); pr_info(MODULE_NAME "%s : cur_jack_type=%d, send_key_state=%d.\n", __func__, hi->cur_jack_type, send_key_state); if ((hi->cur_jack_type != SEC_HEADSET_4POLE) || (send_key_state != true)) value = 0; else value = 1; #endif return sprintf(buf, "%d\n", value); } static DEVICE_ATTR(key_state, 0664 , key_state_onoff_show, NULL); static ssize_t earjack_state_onoff_show(struct device *dev, struct device_attribute *attr, char *buf) { struct sec_jack_info *hi = dev_get_drvdata(dev); int value = 0; if (hi->cur_jack_type == SEC_HEADSET_4POLE) value = 1; else value = 0; return sprintf(buf, "%d\n", value); } static DEVICE_ATTR(state, 0664 , earjack_state_onoff_show, NULL); static ssize_t select_jack_show(struct device *dev, struct device_attribute *attr, char *buf) { pr_info("%s : operate nothing\n", __func__); return 0; }