static void detect_work_f(struct work_struct *work)
{
	int rc;
	struct pm8058_othc *dd =
		container_of(work, struct pm8058_othc, detect_work.work);

	if (dd->othc_ir_state) {
		/* inserted */
		rc = pm8058_accessory_report(dd, 1);
		if (rc)
			pr_err("Accessory could not be detected\n");
	} else {
		/* removed */
		rc = pm8058_accessory_report(dd, 0);
		if (rc)
			pr_err("Accessory could not be detected\n");
		/* Clear existing switch state */
		dd->othc_sw_state = false;
	}
	enable_irq(dd->othc_irq_ir);
}
static int
othc_configure_hsed(struct pm8058_othc *dd, struct platform_device *pd)
{
	int rc;
	struct input_dev *ipd;
	struct pmic8058_othc_config_pdata *pdata = pd->dev.platform_data;
	struct othc_hsed_config *hsed_config = pdata->hsed_config;

	dd->othc_sdev.name = "h2w";
	dd->othc_sdev.print_name = othc_headset_print_name;

	rc = switch_dev_register(&dd->othc_sdev);
	if (rc) {
		pr_err("Unable to register switch device\n");
		return rc;
	}

	ipd = input_allocate_device();
	if (ipd == NULL) {
		pr_err("Unable to allocate memory\n");
		rc = -ENOMEM;
		goto fail_input_alloc;
	}

	/* Get the IRQ for Headset Insert-remove and Switch-press */
	dd->othc_irq_sw = platform_get_irq(pd, 0);
	dd->othc_irq_ir = platform_get_irq(pd, 1);
	if (dd->othc_irq_ir < 0 || dd->othc_irq_sw < 0) {
		pr_err("othc resource:IRQs absent\n");
		rc = -ENXIO;
		goto fail_micbias_config;
	}

	if (pdata->hsed_name != NULL)
		ipd->name = pdata->hsed_name;
	else
		ipd->name = "pmic8058_othc";

	ipd->phys = "pmic8058_othc/input0";
	ipd->dev.parent = &pd->dev;

	dd->othc_ipd = ipd;
	dd->othc_sw_state = false;
	dd->switch_debounce_ms = hsed_config->switch_debounce_ms;
	dd->othc_support_n_switch = hsed_config->othc_support_n_switch;
	dd->accessory_support = pdata->hsed_config->accessories_support;
	dd->detection_delay_ms = pdata->hsed_config->detection_delay_ms;

	if (dd->othc_support_n_switch == true)
		dd->switch_config = hsed_config->switch_config;

	if (dd->accessory_support == true) {
		dd->accessory_info = pdata->hsed_config->accessories;
		dd->num_accessories = pdata->hsed_config->othc_num_accessories;
		dd->accessories_adc_support =
				pdata->hsed_config->accessories_adc_support;
		dd->accessories_adc_channel =
				pdata->hsed_config->accessories_adc_channel;
		dd->video_out_gpio = pdata->hsed_config->video_out_gpio;
	}

	/* Configure the MIC_BIAS line for headset detection */
	rc = pm8058_configure_micbias(dd);
	if (rc < 0)
		goto fail_micbias_config;

	/* Configure for the switch events */
	rc = pm8058_configure_switch(dd);
	if (rc < 0)
		goto fail_micbias_config;

	/* Configure the accessory */
	if (dd->accessory_support == true) {
		rc = pm8058_configure_accessory(dd);
		if (rc < 0)
			goto fail_micbias_config;
	}

	input_set_drvdata(ipd, dd);
	spin_lock_init(&dd->lock);

	rc = input_register_device(ipd);
	if (rc) {
		pr_err("Unable to register OTHC device\n");
		goto fail_micbias_config;
	}

	hrtimer_init(&dd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	dd->timer.function = pm8058_othc_timer;

	/* Request the HEADSET IR interrupt */
	rc = request_threaded_irq(dd->othc_irq_ir, NULL, pm8058_nc_ir,
		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_DISABLED,
				"pm8058_othc_ir", dd);
	if (rc < 0) {
		pr_err("Unable to request pm8058_othc_ir IRQ\n");
		goto fail_ir_irq;
	}

	/* Request the  SWITCH press/release interrupt */
	rc = request_threaded_irq(dd->othc_irq_sw, NULL, pm8058_no_sw,
	IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_DISABLED,
			"pm8058_othc_sw", dd);
	if (rc < 0) {
		pr_err("Unable to request pm8058_othc_sw IRQ\n");
		goto fail_sw_irq;
	}

	/* Check if the accessory is already inserted during boot up */
	rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_ir);
	if (rc < 0) {
		pr_err("Unable to get accessory status at boot\n");
		goto fail_ir_irq;
	}
	if (rc) {
		pr_debug("Accessory inserted during boot up\n");
		/* process the data and report the inserted accessory */
		rc = pm8058_accessory_report(dd, 1);
		if (rc)
			pr_debug("Unabele to detect accessory at boot up\n");
	}

	device_init_wakeup(&pd->dev,
			hsed_config->hsed_bias_config->othc_wakeup);

	INIT_DELAYED_WORK(&dd->detect_work, detect_work_f);

	if (dd->othc_support_n_switch == true)
		INIT_WORK(&dd->switch_work, switch_work_f);

	return 0;

fail_sw_irq:
	free_irq(dd->othc_irq_ir, dd);
fail_ir_irq:
	input_unregister_device(ipd);
	dd->othc_ipd = NULL;
fail_micbias_config:
	input_free_device(ipd);
fail_input_alloc:
	switch_dev_unregister(&dd->othc_sdev);
	return rc;
}