コード例 #1
0
static int htc_headset_misc_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct htc_headset_misc_platform_data *pdata = pdev->dev.platform_data;

	HS_LOG("++++++++++++++++++++");

	hi = kzalloc(sizeof(struct htc_headset_misc_info), GFP_KERNEL);
	if (!hi) {
		HS_ERR("Failed to allocate memory for headset info");
		return -ENOMEM;
	}

	hi->pdata.driver_flag = pdata->driver_flag;
	hi->pdata.ext_hpin_gpio = pdata->ext_hpin_gpio;
	hi->pdata.ext_accessory_type = pdata->ext_accessory_type;

	hi->pdata.indicator_power_gpio = pdata->indicator_power_gpio;

	hi->ext_hpin_irq_type = IRQF_TRIGGER_LOW;
	hi->ext_hpin_debounce = HS_JIFFIES_INSERT;
	hi->ext_hpin_enable = 0;

	switch (hi->pdata.ext_accessory_type) {
	case USB_AUDIO_OUT:
		hi->accessory_detect = hs_misc_usb_audio_out_detect;
		break;
	default:
		if (hi->pdata.driver_flag & DRIVER_HS_MISC_EXT_HP_DET) {
			ret = -EINVAL;
			HS_ERR("Unknown accessory type");
			goto err_ext_hpin_accessory_type;
		}
	}

	wake_lock_init(&hi->hs_wake_lock, WAKE_LOCK_SUSPEND, DRIVER_NAME);

	detect_wq = create_workqueue("HS_MISC_DETECT");
	if (detect_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create detect workqueue");
		goto err_create_detect_work_queue;
	}

	hs_misc_register();
	hs_notify_driver_ready(DRIVER_NAME);

	HS_LOG("--------------------");

	return 0;

err_create_detect_work_queue:
err_ext_hpin_accessory_type:
	kfree(hi);

	HS_ERR("Failed to register %s driver", DRIVER_NAME);

	return ret;
}
コード例 #2
0
static void detect_gpio_work_func(struct work_struct *work)
{
	int insert = 0;
	int ret = 0;

	HS_DBG();
	if ((hi->pdata.eng_cfg == HS_EDE_U) || (hi->pdata.eng_cfg == HS_EDE_TD) || (hi->pdata.eng_cfg == HS_BLE))
	{
		aic3008_set_mic_bias(1);
	}
	if ((hi->pdata.eng_cfg == HS_QUO_F_U))
	{
		regulator = regulator_get(NULL, "v_aud_2v85");
		if (IS_ERR_OR_NULL(regulator)) {
			pr_err("htc_headset_gpio_probe:Couldn't get regulator v_aud_2v85\n");
			regulator = NULL;
			return;
		}
		regulator_enable(regulator);
	}

	insert = gpio_get_value(hi->pdata.hpin_gpio) ? 0 : 1;

	if (hi->headset_state == insert)
		return;

	hi->headset_state = insert;
	hs_notify_plug_event(insert);

	if (hi->pdata.key_gpio){
		if(!hi->key_irq){
			ret = gpio_to_irq(hi->pdata.key_gpio);
			if (ret < 0)
				HS_ERR("gpio_to_irq");
			hi->key_irq = (unsigned int) ret;

			ret = request_irq(hi->key_irq, button_irq_handler,
				hi->key_irq_type, "HS_GPIO_BUTTON", NULL);
			if (ret < 0)
				HS_ERR("request irq error;");
			disable_irq_nosync(hi->key_irq);
		}

		if (hi->key_irq){
			if (hi->headset_state == 1){
				ret = irq_set_irq_wake(hi->key_irq, 1);
				if (ret < 0)
					HS_ERR("set irq wake error");
				enable_irq(hi->key_irq);
			}else{
				ret = irq_set_irq_wake(hi->key_irq, 0);
				if (ret < 0)
					HS_ERR("set irq wake error");
				disable_irq_nosync(hi->key_irq);
			}
		}
	}
}
コード例 #3
0
static int htc_headset_8x60_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct htc_headset_8x60_platform_data *pdata = pdev->dev.platform_data;

	HS_LOG("++++++++++++++++++++");

	hi = kzalloc(sizeof(struct htc_headset_8x60_info), GFP_KERNEL);
	if (!hi) {
		HS_ERR("Failed to allocate memory for headset info");
		return -ENOMEM;
	}

	hi->pdata.adc_mpp = pdata->adc_mpp;
	hi->pdata.adc_amux = pdata->adc_amux;

	if (pdata->adc_mic_bias[0] && pdata->adc_mic_bias[1]) {
		memcpy(hi->pdata.adc_mic_bias, pdata->adc_mic_bias,
		       sizeof(hi->pdata.adc_mic_bias));
	} else {
		hi->pdata.adc_mic_bias[0] = HS_DEF_MIC_ADC_15_BIT_MIN;
		hi->pdata.adc_mic_bias[1] = HS_DEF_MIC_ADC_15_BIT_MAX;
	}

	if (pdata->adc_remote[5])
		memcpy(hi->pdata.adc_remote, pdata->adc_remote,
		       sizeof(hi->pdata.adc_remote));

	wake_lock_init(&hi->hs_wake_lock, WAKE_LOCK_SUSPEND, DRIVER_NAME);

	// faux123, no need to have a multi-thread/multi-cpu bound work queue!
	//button_wq = create_workqueue("HS_8X60_BUTTON");
	button_wq = create_singlethread_workqueue("HS_8X60_BUTTON");
	if (button_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create button workqueue");
		goto err_create_button_work_queue;
	}

	hs_8x60_register();
	hs_notify_driver_ready(DRIVER_NAME);

	HS_LOG("--------------------");

	return 0;

err_create_button_work_queue:
	kfree(hi);

	HS_ERR("Failed to register %s driver", DRIVER_NAME);

	return ret;
}
コード例 #4
0
static int hs_pmic_remote_threshold(uint32_t adc)
{
	int i = 0;
	int ret = 0;
	int array_size = 0;
	uint32_t status;
	struct hs_pmic_rpc_request req;
	struct hs_pmic_rpc_reply rep;

	HS_DBG();

	if (!(hi->pdata.driver_flag & DRIVER_HS_PMIC_DYNAMIC_THRESHOLD))
		return 0;

	req.hs_controller = cpu_to_be32(hi->pdata.hs_controller);
	req.hs_switch = cpu_to_be32(hi->pdata.hs_switch);
	req.current_uA = cpu_to_be32(HS_PMIC_HTC_CURRENT_THRESHOLD);

	array_size = sizeof(current_threshold_lut) /
		     sizeof(struct hs_pmic_current_threshold);

	for (i = 0; i < array_size; i++) {
		if (adc >= current_threshold_lut[i].adc_min &&
		    adc <= current_threshold_lut[i].adc_max)
			req.current_uA = cpu_to_be32(current_threshold_lut[i].
						     current_uA);
	}

	ret = msm_rpc_call_reply(endpoint_current,
				 HS_PMIC_RPC_CLIENT_PROC_THRESHOLD,
				 &req, sizeof(req), &rep, sizeof(rep),
				 HS_RPC_TIMEOUT);

	if (ret < 0) {
		HS_ERR("Failed to send remote threshold RPC");
		return 0;
	} else {
		status = be32_to_cpu(rep.status);
		if (status != HS_PMIC_RPC_ERR_SUCCESS) {
			HS_ERR("Failed to set remote threshold");
			return 0;
		}
	}

	HS_LOG("Set remote threshold (%u, %u, %u)", hi->pdata.hs_controller,
	       hi->pdata.hs_switch, be32_to_cpu(req.current_uA));

	return 1;
}
コード例 #5
0
static int htc_headset_1wire_probe(struct platform_device *pdev)
{
	struct htc_headset_1wire_platform_data *pdata = pdev->dev.platform_data;
	HS_LOG("1-wire probe starts");

	hi = kzalloc(sizeof(struct htc_35mm_1wire_info), GFP_KERNEL);
	if (!hi)
		return -ENOMEM;

	hi->pdata.tx_level_shift_en = pdata->tx_level_shift_en;
	hi->pdata.uart_sw = pdata->uart_sw;
	if (pdata->one_wire_remote[5])
		memcpy(hi->pdata.one_wire_remote, pdata->one_wire_remote,
		       sizeof(hi->pdata.one_wire_remote));
	hi->pdata.uart_tx = pdata->uart_tx;
	hi->pdata.uart_rx = pdata->uart_rx;
	hi->pdata.remote_press = pdata->remote_press;
	fp_count = 0;
	strncpy(hi->pdata.onewire_tty_dev, pdata->onewire_tty_dev, 15);
	HS_LOG("1wire tty device %s", hi->pdata.onewire_tty_dev);
	onewire_wq = create_workqueue("ONEWIRE_WQ");
	if (onewire_wq  == NULL) {
		HS_ERR("Failed to create onewire workqueue");
		return 0;
	}
	mutex_init(&hi->mutex_lock);
	hs_1wire_register();
	queue_delayed_work(onewire_wq, &onewire_init_work, msecs_to_jiffies(3000));
	hs_notify_driver_ready(DRIVER_NAME);

	HS_LOG("--------------------");

	return 0;
}
コード例 #6
0
int hs_notify_key_event(int key_code)
{
	struct button_work *work;

	HS_DBG();

	if (hi->hs_35mm_type == HEADSET_UNKNOWN_MIC ||
	    hi->hs_35mm_type == HEADSET_NO_MIC ||
	    hi->h2w_35mm_type == HEADSET_NO_MIC)
		update_mic_status(HS_DEF_MIC_DETECT_COUNT);
	else if (!hs_hpin_stable()) {
		HS_LOG("The HPIN is unstable, SKIP THE BUTTON EVENT.");
		return 1;
	} else {
		work = kzalloc(sizeof(struct button_work), GFP_KERNEL);
		if (!work) {
			HS_ERR("Failed to allocate button memory");
			return 1;
		}
		work->key_code = key_code;
		INIT_DELAYED_WORK(&work->key_work, button_35mm_work_func);
		queue_delayed_work(button_wq, &work->key_work,
				   HS_JIFFIES_BUTTON);
	}

	return 1;
}
コード例 #7
0
ファイル: htc_headset_mgr.c プロジェクト: RuNuH/eViL-sense-3x
int hs_notify_key_event(int key_code)
{
    struct button_work *work;

    HS_DBG();

    if (hi->ext_35mm_status == HTC_35MM_UNKNOWN_MIC ||
            hi->ext_35mm_status == HTC_35MM_NO_MIC ||
            hi->h2w_35mm_status == HTC_35MM_NO_MIC) {
        HS_LOG("MIC re-detection");
        cancel_delayed_work_sync(&mic_detect_work);
        hi->mic_detect_counter = HS_DEF_MIC_DETECT_COUNT;
        queue_delayed_work(detect_wq, &mic_detect_work,
                           HS_JIFFIES_MIC_DETECT);
    } else if (!hs_hpin_stable()) {
        HS_LOG("The HPIN is unstable, SKIP THE BUTTON EVENT.");
        return 1;
    } else {
        work = kzalloc(sizeof(struct button_work), GFP_KERNEL);
        if (!work) {
            HS_ERR("Failed to allocate button memory");
            return 1;
        }
        work->key_code = key_code;
        INIT_DELAYED_WORK(&work->key_work, button_35mm_work_func);
        queue_delayed_work(button_wq, &work->key_work,
                           HS_JIFFIES_BUTTON);
    }

    return 1;
}
コード例 #8
0
void headset_mhl_audio_jack_enable(int enable)
{
	int ret = 0;

	if (!(hi->pdata.driver_flag & DRIVER_HS_MISC_EXT_HP_DET)) {
		HS_LOG("NOT support MHL audio jack");
		return;
	}

	if (enable) {
		HS_LOG("Enable MHL audio jack");
		if (!hi->ext_hpin_enable) {
			hi->ext_hpin_irq_type = IRQF_TRIGGER_LOW;
			ret = hs_misc_request_irq(hi->pdata.ext_hpin_gpio,
					&hi->ext_hpin_irq, ext_hpin_irq_handler,
					hi->ext_hpin_irq_type, "EXT_HP_DET", 1);
			if (ret < 0) {
				HS_ERR("Failed to request EXT_HP_DET IRQ");
				return;
			}
			hi->ext_hpin_enable = 1;
		}
	} else {
		if (hi->ext_hpin_enable) {
			disable_irq(hi->ext_hpin_irq);
			free_irq(hi->ext_hpin_irq, 0);
			gpio_free(hi->pdata.ext_hpin_gpio);
			hi->ext_hpin_irq = 0;
			hi->ext_hpin_enable = 0;
		}
		HS_LOG("Disable MHL audio jack");
	}
}
コード例 #9
0
static int htc_headset_1wire_probe(struct platform_device *pdev)
{
	struct htc_hs_1wire_data *dtinfo;
	struct htc_headset_1wire_platform_data *pdata;
	HS_LOG("++++++++++++++++++++");

	wake_lock_init(&onewire_open_wake_lock, WAKE_LOCK_SUSPEND, "one_wire_headset");
	hi = kzalloc(sizeof(struct htc_35mm_1wire_info), GFP_KERNEL);
	if (!hi)
		return -ENOMEM;

	dtinfo = kzalloc(sizeof(*dtinfo), GFP_KERNEL);
	if (!dtinfo)
		return -ENOMEM;

	if (pdev->dev.of_node) {
		pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
		if (pdata == NULL)
			return -ENOMEM;

		dtinfo->dev = &pdev->dev;
		dtinfo->pdata = pdata;
		hs_1wire_dtwq(dtinfo);

		HS_LOG("==DT parser %s==", dtinfo->parser ? "OK": "FAILED");
	} else {
		HS_LOG("old style\n");
		pdata = pdev->dev.platform_data;
	}

	hi->pdata.tx_level_shift_en = pdata->tx_level_shift_en;
	hi->pdata.uart_sw = pdata->uart_sw;
	if (pdata->one_wire_remote[5])
		memcpy(hi->pdata.one_wire_remote, pdata->one_wire_remote,
		       sizeof(hi->pdata.one_wire_remote));
	hi->pdata.uart_tx = pdata->uart_tx;
	hi->pdata.uart_rx = pdata->uart_rx;
	hi->pdata.remote_press = pdata->remote_press;
	fp = NULL;
	fp_count = 0;
	strncpy(hi->pdata.onewire_tty_dev, pdata->onewire_tty_dev, 15);
	HS_LOG("1wire tty device %s", hi->pdata.onewire_tty_dev);
	onewire_wq = create_workqueue("ONEWIRE_WQ");
	if (onewire_wq  == NULL) {
		HS_ERR("Failed to create onewire workqueue");
		return 0;
	}
	mutex_init(&hi->mutex_lock);
	hs_1wire_register();
	queue_delayed_work(onewire_wq, &onewire_init_work, msecs_to_jiffies(3000));
#ifndef CONFIG_OF
	hs_notify_driver_ready(DRIVER_NAME);
#endif
	HS_LOG("--------------------");

	return 0;
}
コード例 #10
0
ファイル: htc_headset_mgr.c プロジェクト: Ca1ne/Enoch213
int hs_notify_key_event(int key_code)
{
	struct button_work *work;
	int ret;

	HS_DBG();

	if (pre_key_work) {
		ret = cancel_delayed_work_sync(pre_key_work);
		if (ret)
			HS_LOG("Previous key code cancelled");
	}
	if (hi->hs_35mm_type == HEADSET_INDICATOR) {
		HS_LOG("Not support remote control");
		return 1;
	}

	if (hi->hs_35mm_type == HEADSET_UNKNOWN_MIC ||
	    hi->hs_35mm_type == HEADSET_NO_MIC ||
	    hi->h2w_35mm_type == HEADSET_NO_MIC)
		update_mic_status(HS_DEF_MIC_DETECT_COUNT);
	else if (hi->hs_35mm_type == HEADSET_UNSTABLE)
		update_mic_status(0);
	else if (!hs_hpin_stable()) {
		HS_LOG("IGNORE key %d (Unstable HPIN)", key_code);
		return 1;
	} else if (hi->hs_35mm_type == HEADSET_UNPLUG && hi->is_ext_insert == 1) {
		HS_LOG("MIC status is changed from float, re-polling to decide accessory type");
		update_mic_status(HS_DEF_MIC_DETECT_COUNT);
		return 1;
	} else {
		work = kzalloc(sizeof(struct button_work), GFP_KERNEL);
		if (!work) {
			HS_ERR("Failed to allocate button memory");
			return 1;
		}
		work->key_code = key_code;
		INIT_DELAYED_WORK(&work->key_work, button_35mm_work_func);
		pre_key_work = &work->key_work;
		if (hi->pdata.driver_flag & DRIVER_HS_MGR_OLD_AJ) {
			queue_delayed_work(button_wq, &work->key_work,
					   HS_JIFFIES_BUTTON_LONG);
		} else {
			queue_delayed_work(button_wq, &work->key_work,
					   HS_JIFFIES_BUTTON);
		}
	}

	return 1;
}
コード例 #11
0
static int hs_8x60_remote_adc(int *adc)
{
	int ret = 0;

	HS_DBG();

	ret = pm8058_htc_config_mpp_and_adc_read(adc, 1, CHANNEL_ADC_HDSET,
						 hi->pdata.adc_mpp,
						 hi->pdata.adc_amux);
	if (ret)
		HS_ERR("Failed to read remote ADC");
	else
		HS_LOG("Remote ADC %d (0x%X)", *adc, *adc);

	return 1;
}
コード例 #12
0
static int hs_gpio_request_output(unsigned int gpio, const char *name, int value)
{
	int ret = 0;

	HS_DBG();

	ret = gpio_request(gpio, name);
	if (ret < 0)
		HS_LOG("GPIO Already Requested");

	ret = gpio_direction_output(gpio, value);
	if (ret < 0) {
		HS_ERR("gpio_direction_output(gpio);");
		gpio_free(gpio);
		return ret;
	}

	return 1;
}
コード例 #13
0
static int hs_pmic_remote_adc(int *adc)
{
	int ret = 0;
	struct rpc_request_hdr req;
	struct hs_rpc_client_rep_adc rep;

	HS_DBG();

	ret = msm_rpc_call_reply(endpoint_adc, HS_RPC_CLIENT_PROC_ADC,
				 &req, sizeof(req), &rep, sizeof(rep),
				 HS_RPC_TIMEOUT);
	if (ret < 0) {
		HS_ERR("Failed to read remote ADC");
		return 0;
	}

	*adc = (int) be32_to_cpu(rep.adc);
	HS_LOG("Remote ADC %d (0x%X)", *adc, *adc);

	return 1;
}
コード例 #14
0
int register_attributes(void)
{
	int ret = 0;
	hi->pmic_dev = device_create(hi->htc_accessory_class,
				NULL, 0, "%s", "pmic");
	if (unlikely(IS_ERR(hi->pmic_dev))) {
		ret = PTR_ERR(hi->pmic_dev);
		hi->pmic_dev = NULL;
	}

	/*register the attributes */
	ret = device_create_file(hi->pmic_dev, &dev_attr_pmic_headset_adc);
	if (ret)
		goto err_create_pmic_device_file;
	return 0;

err_create_pmic_device_file:
	device_unregister(hi->pmic_dev);
	HS_ERR("Failed to register pmic attribute file");
	return ret;
}
コード例 #15
0
static int htc_headset_mgr_probe(struct platform_device *pdev)
{
	int ret;

	struct htc_headset_mgr_platform_data *pdata = pdev->dev.platform_data;

	HS_LOG("++++++++++++++++++++");

	hi = kzalloc(sizeof(struct htc_headset_mgr_info), GFP_KERNEL);
	if (!hi)
		return -ENOMEM;

	hi->pdata.driver_flag = pdata->driver_flag;
	hi->pdata.headset_devices_num = pdata->headset_devices_num;
	hi->pdata.headset_devices = pdata->headset_devices;
	hi->pdata.headset_config_num = pdata->headset_config_num;
	hi->pdata.headset_config = pdata->headset_config;

	hi->pdata.hptv_det_hp_gpio = pdata->hptv_det_hp_gpio;
	hi->pdata.hptv_det_tv_gpio = pdata->hptv_det_tv_gpio;
	hi->pdata.hptv_sel_gpio = pdata->hptv_sel_gpio;

	hi->pdata.headset_init = pdata->headset_init;
	hi->pdata.headset_power = pdata->headset_power;

	if (hi->pdata.headset_init)
		hi->pdata.headset_init();

	hi->driver_init_seq = 0;

	hi->early_suspend.suspend = htc_headset_mgr_early_suspend;
	hi->early_suspend.resume = htc_headset_mgr_late_resume;
	register_early_suspend(&hi->early_suspend);

	wake_lock_init(&hi->hs_wake_lock, WAKE_LOCK_SUSPEND, DRIVER_NAME);

	hi->hpin_jiffies = jiffies;
	hi->usb_headset.type = USB_NO_HEADSET;
	hi->usb_headset.status = STATUS_DISCONNECTED;

	hi->hs_35mm_type = HEADSET_UNPLUG;
	hi->h2w_35mm_type = HEADSET_UNPLUG;
	hi->is_ext_insert = 0;
	hi->mic_bias_state = 0;
	hi->mic_detect_counter = 0;
	hi->key_level_flag = -1;
	hi->quick_boot_status = 0;

	atomic_set(&hi->btn_state, 0);

	hi->tty_enable_flag = 0;
	hi->fm_flag = 0;
	hi->debug_flag = 0;

	mutex_init(&hi->mutex_lock);

	hi->sdev_h2w.name = "h2w";
	hi->sdev_h2w.print_name = h2w_print_name;

	ret = switch_dev_register(&hi->sdev_h2w);
	if (ret < 0)
		goto err_h2w_switch_dev_register;

	hi->sdev_usb_audio.name = "usb_audio";
	hi->sdev_usb_audio.print_name = usb_audio_print_name;

	ret = switch_dev_register(&hi->sdev_usb_audio);
	if (ret < 0)
		goto err_usb_audio_switch_dev_register;

	detect_wq = create_workqueue("detect");
	if (detect_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create detect workqueue");
		goto err_create_detect_work_queue;
	}

	button_wq = create_workqueue("button");
	if (button_wq  == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create button workqueue");
		goto err_create_button_work_queue;
	}

	hi->input = input_allocate_device();
	if (!hi->input) {
		ret = -ENOMEM;
		goto err_request_input_dev;
	}

	hi->input->name = "h2w headset";
	set_bit(EV_SYN, hi->input->evbit);
	set_bit(EV_KEY, hi->input->evbit);
	set_bit(KEY_END, hi->input->keybit);
	set_bit(KEY_MUTE, hi->input->keybit);
	set_bit(KEY_VOLUMEDOWN, hi->input->keybit);
	set_bit(KEY_VOLUMEUP, hi->input->keybit);
	set_bit(KEY_NEXTSONG, hi->input->keybit);
	set_bit(KEY_PLAYPAUSE, hi->input->keybit);
	set_bit(KEY_PREVIOUSSONG, hi->input->keybit);
	set_bit(KEY_MEDIA, hi->input->keybit);
	set_bit(KEY_SEND, hi->input->keybit);

	ret = input_register_device(hi->input);
	if (ret < 0)
	goto err_register_input_dev;

	ret = register_attributes();
	if (ret)
		goto err_register_attributes;

#ifdef HTC_HEADSET_CONFIG_MSM_RPC
	if (hi->pdata.driver_flag & DRIVER_HS_MGR_RPC_SERVER) {
		/* Create RPC server */
		ret = msm_rpc_create_server(&hs_rpc_server);
		if (ret < 0) {
			HS_ERR("Failed to create RPC server");
			goto err_create_rpc_server;
		}
		HS_LOG("Create RPC server successfully");
	}
#else
	HS_DBG("NOT support RPC (%du, %du)", hs_rpc_server.prog,
	       hs_rpc_server.vers);
#endif

	headset_mgr_init();
	hs_notify_driver_ready(DRIVER_NAME);

	HS_LOG("--------------------");

	return 0;

#ifdef HTC_HEADSET_CONFIG_MSM_RPC
err_create_rpc_server:
#endif

err_register_attributes:
	input_unregister_device(hi->input);

err_register_input_dev:
	input_free_device(hi->input);

err_request_input_dev:
	destroy_workqueue(button_wq);

err_create_button_work_queue:
	destroy_workqueue(detect_wq);

err_create_detect_work_queue:
	switch_dev_unregister(&hi->sdev_usb_audio);

err_usb_audio_switch_dev_register:
	switch_dev_unregister(&hi->sdev_h2w);

err_h2w_switch_dev_register:
	mutex_destroy(&hi->mutex_lock);
	wake_lock_destroy(&hi->hs_wake_lock);
	kfree(hi);

	HS_ERR("Failed to register %s driver", DRIVER_NAME);

	return ret;
}
コード例 #16
0
ファイル: htc_headset_mgr.c プロジェクト: RuNuH/eViL-sense-3x
static int htc_headset_mgr_probe(struct platform_device *pdev)
{
    int ret;

    struct htc_headset_mgr_platform_data *pdata = pdev->dev.platform_data;

    HS_LOG("++++++++++++++++++++");

    hi = kzalloc(sizeof(struct htc_headset_mgr_info), GFP_KERNEL);
    if (!hi)
        return -ENOMEM;

    hi->pdata.driver_flag = pdata->driver_flag;
    hi->pdata.headset_devices_num = pdata->headset_devices_num;
    hi->pdata.headset_devices = pdata->headset_devices;

    hi->driver_init_seq = 0;

    wake_lock_init(&hi->hs_wake_lock, WAKE_LOCK_SUSPEND, DRIVER_NAME);

    hi->hpin_jiffies = jiffies;
    hi->usb_headset.type = USB_NO_HEADSET;
    hi->usb_headset.status = STATUS_DISCONNECTED;

    hi->ext_35mm_status = HTC_35MM_UNPLUG;
    hi->h2w_35mm_status = HTC_35MM_UNPLUG;
    hi->is_ext_insert = 0;
    hi->mic_bias_state = 0;
    hi->mic_detect_counter = 0;
    hi->key_level_flag = -1;

    atomic_set(&hi->btn_state, 0);

    hi->tty_enable_flag = 0;
    hi->fm_flag = 0;
    hi->debug_flag = 0;

    mutex_init(&hi->mutex_lock);

    hi->sdev.name = "h2w";
    hi->sdev.print_name = h2w_print_name;

    ret = switch_dev_register(&hi->sdev);
    if (ret < 0)
        goto err_switch_dev_register;

    detect_wq = create_workqueue("detect");
    if (detect_wq == NULL) {
        ret = -ENOMEM;
        HS_ERR("Failed to create detect workqueue");
        goto err_create_detect_work_queue;
    }

    button_wq = create_workqueue("button");
    if (button_wq  == NULL) {
        ret = -ENOMEM;
        HS_ERR("Failed to create button workqueue");
        goto err_create_button_work_queue;
    }

    hi->input = input_allocate_device();
    if (!hi->input) {
        ret = -ENOMEM;
        goto err_request_input_dev;
    }

    hi->input->name = "h2w headset";
    set_bit(EV_SYN, hi->input->evbit);
    set_bit(EV_KEY, hi->input->evbit);
    set_bit(KEY_END, hi->input->keybit);
    set_bit(KEY_MUTE, hi->input->keybit);
    set_bit(KEY_VOLUMEDOWN, hi->input->keybit);
    set_bit(KEY_VOLUMEUP, hi->input->keybit);
    set_bit(KEY_NEXTSONG, hi->input->keybit);
    set_bit(KEY_PLAYPAUSE, hi->input->keybit);
    set_bit(KEY_PREVIOUSSONG, hi->input->keybit);
    set_bit(KEY_MEDIA, hi->input->keybit);
    set_bit(KEY_SEND, hi->input->keybit);

    ret = input_register_device(hi->input);
    if (ret < 0)
        goto err_register_input_dev;

    ret = register_attributes();
    if (ret)
        goto err_register_attributes;

    if (hi->pdata.driver_flag & DRIVER_HS_MGR_RPC_SERVER) {
        /* Create RPC server */
        ret = msm_rpc_create_server(&hs_rpc_server);
        if (ret < 0) {
            HS_ERR("Failed to create RPC server");
            goto err_create_rpc_server;
        }
        HS_LOG("Create RPC server successfully");
    }

    hs_notify_driver_ready(DRIVER_NAME);

    HS_LOG("--------------------");

    return 0;

err_create_rpc_server:

err_register_attributes:
    input_unregister_device(hi->input);

err_register_input_dev:
    input_free_device(hi->input);

err_request_input_dev:
    destroy_workqueue(button_wq);

err_create_button_work_queue:
    destroy_workqueue(detect_wq);

err_create_detect_work_queue:
    switch_dev_unregister(&hi->sdev);

err_switch_dev_register:
    mutex_destroy(&hi->mutex_lock);
    wake_lock_destroy(&hi->hs_wake_lock);
    kfree(hi);

    HS_ERR("Failed to register %s driver", DRIVER_NAME);

    return ret;
}
コード例 #17
0
static int htc_headset_pmic_probe(struct platform_device *pdev)
{
	int ret = 0;
	uint32_t vers = 0;
	struct htc_headset_pmic_platform_data *pdata = pdev->dev.platform_data;

	HS_LOG("++++++++++++++++++++");

	hi = kzalloc(sizeof(struct htc_35mm_pmic_info), GFP_KERNEL);
	if (!hi)
		return -ENOMEM;

	hi->pdata.driver_flag = pdata->driver_flag;
	hi->pdata.hpin_gpio = pdata->hpin_gpio;
	hi->pdata.hpin_irq = pdata->hpin_irq;
	hi->pdata.key_gpio = pdata->key_gpio;
	hi->pdata.key_irq = pdata->key_irq;
	hi->pdata.key_enable_gpio = pdata->key_enable_gpio;
	hi->pdata.hs_controller = pdata->hs_controller;
	hi->pdata.hs_switch = pdata->hs_switch;
	hi->pdata.adc_mic = pdata->adc_mic;

	if (!hi->pdata.adc_mic)
		hi->pdata.adc_mic = HS_DEF_MIC_ADC_16_BIT_MIN;

	if (pdata->adc_mic_bias[0] && pdata->adc_mic_bias[1]) {
		memcpy(hi->pdata.adc_mic_bias, pdata->adc_mic_bias,
		       sizeof(hi->pdata.adc_mic_bias));
		hi->pdata.adc_mic = hi->pdata.adc_mic_bias[0];
	} else {
		hi->pdata.adc_mic_bias[0] = hi->pdata.adc_mic;
		hi->pdata.adc_mic_bias[1] = HS_DEF_MIC_ADC_16_BIT_MAX;
	}

	if (pdata->adc_remote[5])
		memcpy(hi->pdata.adc_remote, pdata->adc_remote,
		       sizeof(hi->pdata.adc_remote));

	if (pdata->adc_metrico[0] && pdata->adc_metrico[1])
		memcpy(hi->pdata.adc_metrico, pdata->adc_metrico,
		       sizeof(hi->pdata.adc_metrico));

	hi->hpin_irq_type = IRQF_TRIGGER_LOW;
	hi->hpin_debounce = HS_JIFFIES_ZERO;
	hi->key_irq_type = IRQF_TRIGGER_LOW;

	wake_lock_init(&hi->hs_wake_lock, WAKE_LOCK_SUSPEND, DRIVER_NAME);

	detect_wq = create_workqueue("HS_PMIC_DETECT");
	if (detect_wq  == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create detect workqueue");
		goto err_create_detect_work_queue;
	}

	button_wq = create_workqueue("HS_PMIC_BUTTON");
	if (button_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create button workqueue");
		goto err_create_button_work_queue;
	}

	if (hi->pdata.hpin_gpio) {
		ret = hs_pmic_request_irq(hi->pdata.hpin_gpio,
				&hi->pdata.hpin_irq, detect_irq_handler,
				hi->hpin_irq_type, "HS_PMIC_DETECT", 1);
		if (ret < 0) {
			HS_ERR("Failed to request PMIC HPIN IRQ (0x%X)", ret);
			goto err_request_detect_irq;
		}
	}

	if (hi->pdata.key_gpio) {
		ret = hs_pmic_request_irq(hi->pdata.key_gpio,
				&hi->pdata.key_irq, button_irq_handler,
				hi->key_irq_type, "HS_PMIC_BUTTON", 1);
		if (ret < 0) {
			HS_ERR("Failed to request PMIC button IRQ (0x%X)", ret);
			goto err_request_button_irq;
		}
	}

	if (hi->pdata.driver_flag & DRIVER_HS_PMIC_RPC_KEY) {
		/* Register ADC RPC client */
		endpoint_adc = msm_rpc_connect(HS_RPC_CLIENT_PROG,
					       HS_RPC_CLIENT_VERS, 0);
		if (IS_ERR(endpoint_adc)) {
			hi->pdata.driver_flag &= ~DRIVER_HS_PMIC_RPC_KEY;
			HS_LOG("Failed to register ADC RPC client");
		} else
			HS_LOG("Register ADC RPC client successfully");
	}

	if (hi->pdata.driver_flag & DRIVER_HS_PMIC_DYNAMIC_THRESHOLD) {
		/* Register threshold RPC client */
		vers = HS_PMIC_RPC_CLIENT_VERS_3_1;
		endpoint_current = msm_rpc_connect_compatible(
				   HS_PMIC_RPC_CLIENT_PROG, vers, 0);
		if (!endpoint_current) {
			vers = HS_PMIC_RPC_CLIENT_VERS_2_1;
			endpoint_current = msm_rpc_connect(
					   HS_PMIC_RPC_CLIENT_PROG, vers, 0);
		}
		if (!endpoint_current) {
			vers = HS_PMIC_RPC_CLIENT_VERS_1_1;
			endpoint_current = msm_rpc_connect(
					   HS_PMIC_RPC_CLIENT_PROG, vers, 0);
		}
		if (!endpoint_current) {
			vers = HS_PMIC_RPC_CLIENT_VERS;
			endpoint_current = msm_rpc_connect(
					   HS_PMIC_RPC_CLIENT_PROG, vers, 0);
		}
		if (IS_ERR(endpoint_current)) {
			hi->pdata.driver_flag &=
				~DRIVER_HS_PMIC_DYNAMIC_THRESHOLD;
			HS_LOG("Failed to register threshold RPC client");
		} else
			HS_LOG("Register threshold RPC client successfully"
			       " (0x%X)", vers);
	}

	hs_pmic_register();
	hs_notify_driver_ready(DRIVER_NAME);

	HS_LOG("--------------------");

	return 0;

err_request_button_irq:
	if (hi->pdata.hpin_gpio) {
		free_irq(hi->pdata.hpin_irq, 0);
		gpio_free(hi->pdata.hpin_gpio);
	}

err_request_detect_irq:
	destroy_workqueue(button_wq);

err_create_button_work_queue:
	destroy_workqueue(detect_wq);

err_create_detect_work_queue:
	wake_lock_destroy(&hi->hs_wake_lock);
	kfree(hi);

	HS_ERR("Failed to register %s driver", DRIVER_NAME);

	return ret;
}
コード例 #18
0
ファイル: htc_headset_mgr.c プロジェクト: freak007/hox-kernel
static int htc_headset_mgr_probe(struct platform_device *pdev)
{
	int ret,i;

	struct htc_headset_mgr_platform_data *pdata = pdev->dev.platform_data;

	HS_LOG("++++++++++++++++++++");

	hi = kzalloc(sizeof(struct htc_headset_mgr_info), GFP_KERNEL);
	if (!hi)
		return -ENOMEM;

	hi->pdata.eng_cfg = pdata->eng_cfg;
	hi->pdata.driver_flag = pdata->driver_flag;
	hi->pdata.headset_devices_num = pdata->headset_devices_num;
	hi->pdata.headset_devices = pdata->headset_devices;
	hi->pdata.headset_config_num = pdata->headset_config_num;
	hi->pdata.headset_config = pdata->headset_config;
	hi->pdata.headset_config_1wire_num = pdata->headset_config_1wire_num;
	hi->pdata.headset_config_1wire = pdata->headset_config_1wire;
	hi->pdata.tx_1wire_gpio = pdata->tx_1wire_gpio;
	hi->pdata.rx_1wire_gpio = pdata->rx_1wire_gpio;
	hi->pdata.level_1wire_gpio = pdata->level_1wire_gpio;
	hi->pdata.enable_1wire = pdata->enable_1wire;
	strncpy(hi->pdata.dev_1wire, pdata->dev_1wire, UART_DEV_NAME_LEN);

	hi->pdata.hptv_det_hp_gpio = pdata->hptv_det_hp_gpio;
	hi->pdata.hptv_det_tv_gpio = pdata->hptv_det_tv_gpio;
	hi->pdata.hptv_sel_gpio = pdata->hptv_sel_gpio;

	hi->pdata.headset_init = pdata->headset_init;
	hi->pdata.headset_power = pdata->headset_power;

	if (hi->pdata.headset_init)
		hi->pdata.headset_init();

	hi->driver_init_seq = 0;

	hi->early_suspend.suspend = htc_headset_mgr_early_suspend;
	hi->early_suspend.resume = htc_headset_mgr_late_resume;
	register_early_suspend(&hi->early_suspend);

	wake_lock_init(&hi->hs_wake_lock, WAKE_LOCK_SUSPEND, DRIVER_NAME);

	hi->hpin_jiffies = jiffies;
	hi->usb_headset.type = USB_NO_HEADSET;
	hi->usb_headset.status = STATUS_DISCONNECTED;

	hi->detect_type = HEADSET_ADC;
	hi->hs_35mm_type = HEADSET_UNPLUG;
	hi->h2w_35mm_type = HEADSET_UNPLUG;
	hi->is_ext_insert = 0;
	hi->mic_bias_state = 0;
	hi->mic_detect_counter = 0;
	hi->key_level_flag = -1;
	hi->quick_boot_status = 0;

	atomic_set(&hi->btn_state, 0);

	hi->tty_enable_flag = 0;
	hi->fm_flag = 0;
	hi->debug_flag = 0;

	mutex_init(&hi->mutex_lock);

	hi->sdev.name = "h2w";
	hi->sdev.print_name = h2w_print_name;

	for (i=0;i<HS_BUTTON_EVENT_QUEUE;i++){
		key_event[i] = kzalloc(sizeof(struct button_work), GFP_KERNEL);
		if (!key_event[i]) {
			HS_ERR("Failed to allocate button memory");
			return -ENOMEM;
		}
	}
	key_event_flag = -1;

	ret = switch_dev_register(&hi->sdev);
	if (ret < 0)
		goto err_switch_dev_register;

	detect_wq = create_workqueue("detect");
	if (detect_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create detect workqueue");
		goto err_create_detect_work_queue;
	}

	button_wq = create_workqueue("button");
	if (button_wq  == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create button workqueue");
		goto err_create_button_work_queue;
	}

	hi->input = input_allocate_device();
	if (!hi->input) {
		ret = -ENOMEM;
		goto err_request_input_dev;
	}

	hi->input->name = "h2w headset";
	set_bit(EV_SYN, hi->input->evbit);
	set_bit(EV_KEY, hi->input->evbit);
	set_bit(KEY_END, hi->input->keybit);
	set_bit(KEY_MUTE, hi->input->keybit);
	set_bit(KEY_VOLUMEDOWN, hi->input->keybit);
	set_bit(KEY_VOLUMEUP, hi->input->keybit);
	set_bit(KEY_NEXTSONG, hi->input->keybit);
	set_bit(KEY_PLAYPAUSE, hi->input->keybit);
	set_bit(KEY_PREVIOUSSONG, hi->input->keybit);
	set_bit(KEY_MEDIA, hi->input->keybit);
	set_bit(KEY_SEND, hi->input->keybit);

	ret = input_register_device(hi->input);
	if (ret < 0)
	goto err_register_input_dev;

	ret = register_attributes();
	if (ret)
		goto err_register_attributes;

	if (hi->pdata.driver_flag & DRIVER_HS_MGR_RPC_SERVER) {
		/* Create RPC server */
		/* FIXME */
		/* ret = msm_rpc_create_server(&hs_rpc_server); */
		ret = -1;
		if (ret < 0) {
			HS_ERR("Failed to create RPC server");
			goto err_create_rpc_server;
		}
		HS_LOG("Create RPC server successfully");
	}

	headset_mgr_init();
	hs_notify_driver_ready(DRIVER_NAME);

	HS_LOG("--------------------");

	return 0;

err_create_rpc_server:

err_register_attributes:
	input_unregister_device(hi->input);

err_register_input_dev:
	input_free_device(hi->input);

err_request_input_dev:
	destroy_workqueue(button_wq);

err_create_button_work_queue:
	destroy_workqueue(detect_wq);

err_create_detect_work_queue:
	switch_dev_unregister(&hi->sdev);

err_switch_dev_register:
	mutex_destroy(&hi->mutex_lock);
	wake_lock_destroy(&hi->hs_wake_lock);
	kfree(hi);

	HS_ERR("Failed to register %s driver", DRIVER_NAME);

	return ret;
}
コード例 #19
0
static int htc_headset_gpio_probe(struct platform_device *pdev)
{
	int ret;
	struct htc_headset_gpio_platform_data *pdata = pdev->dev.platform_data;

	HS_LOG("++++++++++++++++++++");

	hi = kzalloc(sizeof(struct htc_headset_gpio_info), GFP_KERNEL);
	if (!hi) {
		HS_ERR("Failed to allocate memory for headset info");
		return -ENOMEM;
	}

	if (pdata->config_headset_gpio)
		pdata->config_headset_gpio();

	hi->pdata.eng_cfg = pdata->eng_cfg;
	hi->pdata.hpin_gpio = pdata->hpin_gpio;
	hi->pdata.key_gpio = pdata->key_gpio;
	hi->pdata.key_enable_gpio = pdata->key_enable_gpio;
	hi->pdata.mic_select_gpio = pdata->mic_select_gpio;

	hi->hpin_debounce = HS_JIFFIES_ZERO;
	hi->key_irq_type = IRQF_TRIGGER_LOW;
	hi->headset_state = 0;

	if ((hi->pdata.eng_cfg == HS_QUO_F_U))
	{
		/* HW power connet cable issue */
		/* EVT XB WORKAROUND Only */
		if (PROJECT_PHASE_XB == htc_get_pcbid_info()) {
			HS_ERR("=====FORCED RETURN!!!!!=====");
			return -ENOMEM;
		}
	}

	detect_wq = create_workqueue("HS_GPIO_DETECT");
	if (detect_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create detect workqueue");
		goto err_create_detect_work_queue;
	}

	button_wq = create_workqueue("HS_GPIO_BUTTON");
	if (button_wq == NULL){
		ret = -ENOMEM;
		HS_ERR("Failed to create button workqueue");
		goto err_create_button_work_queue;
	}

	wake_lock_init(&hi->hs_wake_lock, WAKE_LOCK_SUSPEND, DRIVER_NAME);

	if (hi->pdata.hpin_gpio) {
		ret = hs_gpio_request_irq(hi->pdata.hpin_gpio,
				&hi->hpin_irq, detect_irq_handler,
				IRQF_TRIGGER_LOW, "HS_GPIO_DETECT", 1);
		if (ret < 0) {
			HS_ERR("Failed to request GPIO HPIN IRQ (0x%X)", ret);
			goto err_request_detect_irq;
		}
	}

	if (hi->pdata.key_gpio) {
		ret = hs_gpio_request(hi->pdata.key_gpio, "HS_GPIO_BUTTON");
		if (ret < 0)
			HS_ERR("Failed to request GPIO HPIN IRQ (0x%X)", ret);
	}

	hs_gpio_register();
	hs_notify_driver_ready(DRIVER_NAME);

	HS_LOG("--------------------");

	return 0;

err_request_detect_irq:
	wake_lock_destroy(&hi->hs_wake_lock);
	destroy_workqueue(button_wq);

err_create_button_work_queue:
	destroy_workqueue(detect_wq);

err_create_detect_work_queue:
	kfree(hi);

	HS_ERR("Failed to register %s driver", DRIVER_NAME);

	return ret;
}
コード例 #20
0
static int htc_headset_gpio_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct htc_headset_gpio_platform_data *pdata;

	HS_LOG("++++++++++++++++++++");

	hi = kzalloc(sizeof(struct htc_headset_gpio_info), GFP_KERNEL);
	if (!hi) {
		HS_ERR("Failed to allocate memory for headset info");
		return -ENOMEM;
	}

	if (pdev->dev.of_node) {
		pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
		if (pdata == NULL)
			ret = -ENOMEM;
		ret = htc_headset_gpio_parse_dt(&pdev->dev, pdata);
	} else {
		HS_LOG("old style\n");
		pdata = pdev->dev.platform_data;
	}

	if (pdata->config_headset_gpio)
		pdata->config_headset_gpio();

	hi->pdata.uart_gpio       = pdata->uart_gpio;
	hi->pdata.hpin_gpio       = pdata->hpin_gpio;
	hi->pdata.key_gpio        = pdata->key_gpio;
	hi->pdata.key_enable_gpio = pdata->key_enable_gpio;
	hi->pdata.mic_select_gpio = pdata->mic_select_gpio;

	hi->hpin_debounce         = HS_JIFFIES_ZERO;
	hi->key_irq_type          = IRQF_TRIGGER_NONE;
	hi->headset_state         = 0;

	detect_wq = create_workqueue("HS_GPIO_DETECT");
	if (detect_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create detect workqueue");
		goto err_create_detect_work_queue;
	}

	button_wq = create_workqueue("HS_GPIO_BUTTON");
	if (button_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create button workqueue");
		goto err_create_button_work_queue;
	}

	wake_lock_init(&hi->hs_wake_lock, WAKE_LOCK_SUSPEND, DRIVER_NAME);

	if (hi->pdata.uart_gpio) {
			ret = hs_gpio_request_output(hi->pdata.uart_gpio, "HS_GPIO_UART", 0);

		if (ret < 0) {
			HS_ERR("Fail to request GPIO UART(0x%x)", ret);
		}
	}

	if (hi->pdata.hpin_gpio) {
		ret = hs_gpio_request_irq(hi->pdata.hpin_gpio,
				&hi->hpin_irq, detect_irq_handler,
				IRQF_TRIGGER_NONE, "HS_GPIO_DETECT", 1);
		if (ret < 0) {
			HS_ERR("Failed to request GPIO HPIN IRQ (0x%X)", ret);
			goto err_request_detect_irq;
		}
		disable_irq(hi->hpin_irq);
	}

	if (hi->pdata.key_gpio) {
		ret = hs_gpio_request_irq(hi->pdata.key_gpio,
				&hi->key_irq, button_irq_handler,
				hi->key_irq_type, "HS_GPIO_BUTTON", 1);
		if (ret < 0) {
			HS_ERR("Failed to request GPIO button IRQ (0x%X)", ret);
			goto err_request_button_irq;
		}
		disable_irq(hi->key_irq);
	}

	queue_delayed_work(detect_wq, &irq_init_work, HS_JIFFIES_IRQ_INIT);

	hs_gpio_register();
#ifndef CONFIG_OF
	hs_notify_driver_ready(DRIVER_NAME);
#endif
	HS_LOG("--------------------");

	return 0;

err_request_button_irq:
	if (hi->pdata.hpin_gpio) {
		free_irq(hi->hpin_irq, 0);
		gpio_free(hi->pdata.hpin_gpio);
	}

err_request_detect_irq:
	wake_lock_destroy(&hi->hs_wake_lock);
	destroy_workqueue(button_wq);

err_create_button_work_queue:
	destroy_workqueue(detect_wq);

err_create_detect_work_queue:
	kfree(hi);

	HS_ERR("Failed to register %s driver", DRIVER_NAME);

	return ret;
}
コード例 #21
0
static int htc_headset_gpio_probe(struct platform_device *pdev)
{
	int ret;
	struct htc_headset_gpio_platform_data *pdata = pdev->dev.platform_data;

	HS_LOG("++++++++++++++++++++");

	hi = kzalloc(sizeof(struct htc_headset_gpio_info), GFP_KERNEL);
	if (!hi) {
		HS_ERR("Failed to allocate memory for headset info");
		return -ENOMEM;
	}

	if (pdata->config_headset_gpio)
		pdata->config_headset_gpio();

	hi->pdata.hpin_gpio = pdata->hpin_gpio;
	hi->pdata.key_gpio = pdata->key_gpio;
	hi->pdata.key_enable_gpio = pdata->key_enable_gpio;
	hi->pdata.mic_select_gpio = pdata->mic_select_gpio;

	hi->hpin_debounce = HS_JIFFIES_ZERO;
	hi->key_irq_type = IRQF_TRIGGER_LOW;
	hi->headset_state = 0;

	detect_wq = create_workqueue("HS_GPIO_DETECT");
	if (detect_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create detect workqueue");
		goto err_create_detect_work_queue;
	}

	button_wq = create_workqueue("HS_GPIO_BUTTON");
	if (button_wq == NULL) {
		ret = -ENOMEM;
		HS_ERR("Failed to create button workqueue");
		goto err_create_button_work_queue;
	}

	wake_lock_init(&hi->hs_wake_lock, WAKE_LOCK_SUSPEND, DRIVER_NAME);

	if (hi->pdata.hpin_gpio) {
		ret = hs_gpio_request_irq(hi->pdata.hpin_gpio,
				&hi->hpin_irq, detect_irq_handler,
				IRQF_TRIGGER_LOW, "HS_GPIO_DETECT", 1);
		if (ret < 0) {
			HS_ERR("Failed to request GPIO HPIN IRQ (0x%X)", ret);
			goto err_request_detect_irq;
		}
	}

	if (hi->pdata.key_gpio) {
		ret = hs_gpio_request_irq(hi->pdata.key_gpio,
				&hi->key_irq, button_irq_handler,
				hi->key_irq_type, "HS_GPIO_BUTTON", 1);
		if (ret < 0) {
			HS_ERR("Failed to request GPIO button IRQ (0x%X)", ret);
			goto err_request_button_irq;
		}
	}

	hs_gpio_register();
	hs_notify_driver_ready(DRIVER_NAME);

	HS_LOG("--------------------");

	return 0;

err_request_button_irq:
	if (hi->pdata.hpin_gpio) {
		free_irq(hi->hpin_irq, 0);
		gpio_free(hi->pdata.hpin_gpio);
	}

err_request_detect_irq:
	wake_lock_destroy(&hi->hs_wake_lock);
	destroy_workqueue(button_wq);

err_create_button_work_queue:
	destroy_workqueue(detect_wq);

err_create_detect_work_queue:
	kfree(hi);

	HS_ERR("Failed to register %s driver", DRIVER_NAME);

	return ret;
}