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;

}
예제 #2
0
static enum hrtimer_restart report_headset_detect_status(int active, struct _headset_gpio *hgp)
{
	struct regulator *mic_regulator;
	mic_regulator = regulator_get(NULL, REGU_NAME_MIC);
	int adc_value;

	if (active) {
		if (!IS_ERR(mic_regulator)) {
			regulator_set_voltage(mic_regulator, 2800000, 2800000);
			regulator_enable(mic_regulator);
		}
		mdelay(20);

		headset_hook_detect(1);
		hgp->parent->headphone = 0;
		/*hgp->parent->headphone = hgp->parent->button.active_low ^ headset_gpio_get_value(hgp->parent->button.gpio);*/
		adc_value = sci_adc_get_value(ADC_CHANNEL_TEMP, false);

		hgp->parent->headphone = adc_value > 0x05? 0 : 1;

		if (hgp->parent->headphone) {
			switch_set_state(&hgp->parent->sdev, BIT_HEADSET_NO_MIC);
			if (!IS_ERR(mic_regulator))
				regulator_disable(mic_regulator);
			pr_info("headphone plug in\n");
		} else {

			switch_set_state(&hgp->parent->sdev, BIT_HEADSET_MIC);
			pr_info("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 {
		headset_gpio_irq_enable(0, &hgp->parent->button);
		hgp->parent->button.callback(-1, &hgp->parent->button);
		headset_hook_detect(0);
		if (hgp->parent->headphone)
			pr_info("headphone plug out\n");
		else {
			if (!IS_ERR(mic_regulator))
				regulator_disable(mic_regulator);
			pr_info("headset plug out\n");
		}
		switch_set_state(&hgp->parent->sdev, BIT_HEADSET_OUT);
	}
	/* use below code only when gpio irq misses state ? */
	/* headset_gpio_set_irq_type(hgp->irq, active ? hgp->irq_type_inactive : hgp->irq_type_active); */
	return HRTIMER_NORESTART;
}
예제 #3
0
static void __exit headset_exit(void)
{
	struct _headset *ht = &headset;
	headset_gpio_irq_enable(0, &ht->button);
	headset_gpio_irq_enable(0, &ht->detect);
	free_irq(ht->detect.irq, &ht->detect);
	headset_gpio2irq_free(ht->detect.irq, &ht->detect);
	free_irq(ht->button.irq, &ht->button);
	headset_gpio2irq_free(ht->button.irq, &ht->button);
	headset_gpio_free(ht->detect.gpio);
	headset_gpio_free(ht->button.gpio);
	input_free_device(ht->input);
	platform_driver_unregister(&headset_button_driver);
	switch_dev_unregister(&ht->sdev);
}
static void __exit headset_exit(void)
{
	struct _headset *ht = &headset;
	device_remove_file((&ht->sdev)->dev, &dev_attr_estate);
	device_remove_file((&ht->sdev)->dev, &dev_attr_hs_adc);
	headset_gpio_irq_enable(0, &ht->button);
	headset_gpio_irq_enable(0, &ht->detect);
	free_irq(ht->detect.irq, &ht->detect);
	headset_gpio2irq_free(ht->detect.irq, &ht->detect);
	free_irq(ht->button.irq, &ht->button);
	headset_gpio2irq_free(ht->button.irq, &ht->button);
	headset_gpio_free(ht->detect.gpio);
	headset_gpio_free(ht->button.gpio);
	headset_gpio_free(HEADSET_MICBIAS_GPIO); /* add for control of external mic bias - ffkaka */
	headset_gpio_free(HEADSET_COM_DETECT_GPIO); /* com open detect - ffkaka */	
	input_free_device(ht->input);
	platform_driver_unregister(&headset_button_driver);
	switch_dev_unregister(&ht->sdev);
}
static int __init headset_init(void)
{
	int ret, i;
	struct _headset *ht = &headset;
	ret = switch_dev_register(&ht->sdev);
	if (ret < 0) {
		pr_err("switch_dev_register failed!\n");
		return ret;
	}
	platform_driver_register(&headset_button_driver); 
	ht->input = input_allocate_device();
	if (ht->input == NULL) {
		pr_err("switch_dev_register failed!\n");
		goto _switch_dev_register;
	}
	//jinwon.baek 120808 for earloopback switch checking 
	ret = device_create_file((&ht->sdev)->dev, &dev_attr_estate);
	if (ret < 0) {
		pr_err("eswitch_dev_register failed!\n");
		return ret;
	}
	/* Add for manual adc checking - ffkaka */
	ret = device_create_file((&ht->sdev)->dev, &dev_attr_hs_adc);
	if (ret < 0) {
		pr_err("hs_adc_dev_register failed!\n");
		return ret;
	}
	/* gnd detection checking - ffkaka */
	ret = device_create_file((&ht->sdev)->dev, &dev_attr_gnd_detect);
	if (ret < 0) {
		pr_err("gnd_detect_dev_register failed!\n");
		return ret;
	}	

	ht->input->name = "headset-keyboard";
	ht->input->id.bustype = BUS_HOST;
	ht->input->id.vendor = 0x0001;
	ht->input->id.product = 0x0001;
	ht->input->id.version = 0x0100;

	for(i = 0; headset_key_capability[i].key != KEY_RESERVED; i++) {
		__set_bit(headset_key_capability[i].type, ht->input->evbit);
		input_set_capability(ht->input, headset_key_capability[i].type, headset_key_capability[i].key);
	}

	if (input_register_device(ht->input))
		goto _switch_dev_register;

	headset_gpio_init(ht->detect.gpio, ht->detect.desc);
	headset_gpio_init(ht->button.gpio, ht->button.desc);

	/* control of external mic bias - ffkaka */
	ret = gpio_request(HEADSET_MICBIAS_GPIO, "hs_mic_control");
	if (ret)
	{
		pr_info("[headset] hs mic control gpio get fail!!!\n");
		goto _gpio_request;
	}
	gpio_direction_output(HEADSET_MICBIAS_GPIO, 0);	

	/* com open detect - ffkaka */
	ret = gpio_request(HEADSET_COM_DETECT_GPIO,"hs_com_detect");
	if(ret)
	{
		pr_info("[headset] hs_com_detect gpio get fail!!!\n");
		goto _gpio_request;	
	}
	gpio_direction_input(HEADSET_COM_DETECT_GPIO);

	/* adc path enable/disable control(REV0.3) - ffkaka */
	ret = gpio_request(HEADSET_ADC_EN_GPIO,"hs_adc_enable");
	if(ret)
	{
		pr_info("[headset] hs_adc_enable gpio get fail!!!\n");
		goto _gpio_request;	
	}
	gpio_direction_input(HEADSET_ADC_EN_GPIO);
	
	/* ffkaka */

	headset_gpio_debounce(ht->detect.gpio, ht->detect.debounce * 1000);
	headset_gpio_debounce(ht->button.gpio, ht->button.debounce * 1000);
	pr_info("[headset] init headset detection[GPIO=%d] / button[GPIO=%d] \n", ht->detect.gpio, ht->button.gpio);

	HEADSET_DEBOUNCE_ROUND_UP(ht->button.debounce_sw);
	ht->button.parent = ht;
	ht->button.irq = headset_gpio2irq(ht->button.gpio);
	INIT_WORK(&ht->button.gpio_work,headset_button_gpio_work);
	wake_lock_init(&ht->button.gpio_wakelock,WAKE_LOCK_SUSPEND,"hs_button_wakelock");
	init_timer(&ht->button.gpio_timer);
	ht->button.gpio_timer.function = headset_button_timer;
	ht->button.gpio_timer.data = (unsigned long)&ht->button;	
	ht->button.irq_type_active = ht->button.active_low ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
	ht->button.irq_type_inactive = ht->button.active_low ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW;
	ret = request_irq(ht->button.irq, headset_button_irq_handler,
					ht->button.irq_type_active, ht->button.desc, &ht->button);
	if (ret) {
		pr_err("request_irq gpio %d's irq failed!\n", ht->button.gpio);
		goto _gpio_request;
	}
	headset_gpio_irq_enable(0, &ht->button);

	HEADSET_DEBOUNCE_ROUND_UP(ht->detect.debounce_sw);
	ht->detect.parent = ht;
	ht->detect.irq = headset_gpio2irq(ht->detect.gpio);
	INIT_WORK(&ht->detect.gpio_work,headset_detect_gpio_work);
	wake_lock_init(&ht->detect.gpio_wakelock,WAKE_LOCK_SUSPEND,"hs_detect_wakelock");	
	init_timer(&ht->detect.gpio_timer);
	ht->detect.gpio_timer.function = headset_detect_timer;
	ht->detect.gpio_timer.data = (unsigned long)&ht->detect;
	ht->detect.irq_type_active = ht->detect.active_low ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
	ht->detect.irq_type_inactive = ht->detect.active_low ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW;
	ret = request_irq(ht->detect.irq, headset_detect_irq_handler,
					ht->detect.irq_type_active, ht->detect.desc, &ht->detect);
	if (ret) {
		pr_err("request_irq gpio %d's irq failed!\n", ht->detect.gpio);
		goto _headset_button_gpio_irq_handler;
	}
	return 0;
_headset_button_gpio_irq_handler:
	free_irq(ht->button.irq, &ht->button);
	headset_gpio2irq_free(ht->button.irq, &ht->button);
_gpio_request:
	headset_gpio_free(ht->detect.gpio);
	headset_gpio_free(ht->button.gpio);
	headset_gpio_free(HEADSET_MICBIAS_GPIO); /* add for control of external mic bias - ffkaka */
	headset_gpio_free(HEADSET_COM_DETECT_GPIO); /* com open detect - ffkaka */
	input_free_device(ht->input);
_switch_dev_register:
	platform_driver_unregister(&headset_button_driver);
	switch_dev_unregister(&ht->sdev);
	return ret;
}
예제 #6
0
static int __init headset_init(void)
{
	int ret, i;
	struct _headset *ht = &headset;
	pa_regulator = regulator_get(NULL, REGU_NAME_LCDIO);
	regulator_set_voltage(pa_regulator, 2800000, 2800000);

	ret = switch_dev_register(&ht->sdev);
	if (ret < 0) {
		pr_err("switch_dev_register failed!\n");
		return ret;
	}
	platform_driver_register(&headset_button_driver); 
	ht->input = input_allocate_device();
	if (ht->input == NULL) {
		pr_err("switch_dev_register failed!\n");
		goto _switch_dev_register;
	}
	//jinwon.baek 120808 for earloopback switch checking 
	ret = device_create_file((&ht->sdev)->dev, &dev_attr_estate);
	if (ret < 0) {
		pr_err("eswitch_dev_register failed!\n");
		return ret;
	}

	ht->input->name = "headset-keyboard";
	ht->input->id.bustype = BUS_HOST;
	ht->input->id.vendor = 0x0001;
	ht->input->id.product = 0x0001;
	ht->input->id.version = 0x0100;

	for(i = 0; headset_key_capability[i].key != KEY_RESERVED; i++) {
		__set_bit(headset_key_capability[i].type, ht->input->evbit);
		input_set_capability(ht->input, headset_key_capability[i].type, headset_key_capability[i].key);
	}

	if (input_register_device(ht->input))
		goto _switch_dev_register;

	headset_gpio_init(ht->detect.gpio, ht->detect.desc);
	headset_gpio_init(ht->button.gpio, ht->button.desc);

	headset_gpio_debounce(ht->detect.gpio, ht->detect.debounce * 1000);
	headset_gpio_debounce(ht->button.gpio, ht->button.debounce * 1000);

	hrtimer_init(&ht->button.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	ht->button.timer.function = headset_gpio_timer_func;
	HEADSET_DEBOUNCE_ROUND_UP(ht->button.debounce_sw);
	HEADSET_DEBOUNCE_ROUND_UP(ht->button.timeout_ms);
	ht->button.parent = ht;
	ht->button.irq = headset_gpio2irq(ht->button.gpio);
	ht->button.irq_type_active = ht->button.active_low ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
	ht->button.irq_type_inactive = ht->button.active_low ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW;
	ret = request_irq(ht->button.irq, headset_gpio_irq_handler,
					ht->button.irq_type_active, ht->button.desc, &ht->button);
	if (ret) {
		pr_err("request_irq gpio %d's irq failed!\n", ht->button.gpio);
		goto _gpio_request;
	}
	headset_gpio_irq_enable(0, &ht->button);

	hrtimer_init(&ht->detect.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	ht->detect.timer.function = headset_gpio_timer_func;
	HEADSET_DEBOUNCE_ROUND_UP(ht->detect.debounce_sw);
	ht->detect.parent = ht;
	ht->detect.irq = headset_gpio2irq(ht->detect.gpio);
	ht->detect.irq_type_active = ht->detect.active_low ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
	ht->detect.irq_type_inactive = ht->detect.active_low ? IRQF_TRIGGER_HIGH : IRQF_TRIGGER_LOW;
	ret = request_irq(ht->detect.irq, headset_gpio_irq_handler,
					ht->detect.irq_type_active, ht->detect.desc, &ht->detect);
	if (ret) {
		pr_err("request_irq gpio %d's irq failed!\n", ht->detect.gpio);
		goto _headset_button_gpio_irq_handler;
	}
	return 0;
_headset_button_gpio_irq_handler:
	free_irq(ht->button.irq, &ht->button);
	headset_gpio2irq_free(ht->button.irq, &ht->button);
_gpio_request:
	headset_gpio_free(ht->detect.gpio);
	headset_gpio_free(ht->button.gpio);
	input_free_device(ht->input);
_switch_dev_register:
	platform_driver_unregister(&headset_button_driver);
	switch_dev_unregister(&ht->sdev);
	return ret;
}