static int othc_configure_hsed(struct pm8058_othc *dd, struct platform_device *pd) { int rc, i; 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("%s: Unable to register switch device \n", __func__); return rc; } ipd = input_allocate_device(); if (ipd == NULL) { pr_err("%s: Unable to allocate memory \n", __func__); 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) { pr_err("%s: othc resource:IRQ_IR absent \n", __func__); rc = -ENXIO; goto fail_othc_config; } if (dd->othc_irq_sw < 0) { pr_err("%s: othc resource:IRQ_SW absent\n", __func__); rc = -ENXIO; goto fail_othc_config; } ipd->name = "pmic8058_othc"; ipd->phys = "pmic8058_othc/input0"; ipd->dev.parent = &pd->dev; dd->othc_ipd = ipd; dd->othc_sw_state = false; dd->othc_ir_state = false; dd->switch_debounce_ms = hsed_config->switch_debounce_ms; dd->othc_support_n_switch = hsed_config->othc_support_n_switch; if (dd->othc_support_n_switch == true) { pr_debug("%s: OTHC 'n' switch supported\n", __func__); if (!hsed_config->switch_config || !hsed_config->switch_config->switch_info) { rc = -EINVAL; pr_err("%s: Switch pdata absent!\n", __func__); goto fail_othc_config; } dd->switch_config = hsed_config->switch_config; for (i = 0; i < dd->switch_config->num_keys; i++) { input_set_capability(ipd, EV_KEY, dd->switch_config->switch_info[i].key_code); } } else input_set_capability(ipd, EV_KEY, KEY_MEDIA); input_set_capability(ipd, EV_SW, SW_HEADPHONE_INSERT); input_set_drvdata(ipd, dd); spin_lock_init(&dd->lock); rc = pm8058_configure_othc(dd); if (rc < 0) goto fail_othc_config; rc = input_register_device(ipd); if (rc) { pr_err("%s: Unable to register OTHC device \n", __func__); goto fail_othc_config; } /* Check if the headset is already inserted during boot up */ rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_ir); if (rc < 0) { pr_err("%s: Unable to get headset status at boot\n", __func__); goto fail_ir_irq; } if (rc) { pr_debug("%s: Headset inserted during boot up\n", __func__); /* Headset present */ dd->othc_ir_state = true; switch_set_state(&dd->othc_sdev, 1); input_report_switch(dd->othc_ipd, SW_HEADPHONE_INSERT, 1); input_sync(dd->othc_ipd); } hrtimer_init(&dd->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); dd->timer.function = pm8058_othc_timer; 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("%s: Unable to request pm8058_othc_ir IRQ\n", __func__); goto fail_ir_irq; } /* This irq is used only for NO type headset */ 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("%s: Unable to request pm8058_othc_sw IRQ\n", __func__); goto fail_sw_irq; } device_init_wakeup(&pd->dev, hsed_config->othc_wakeup); INIT_WORK(&dd->headset_work, headset_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_othc_config: input_free_device(ipd); fail_input_alloc: switch_dev_unregister(&dd->othc_sdev); return rc; }
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("%s: Unable to register switch device \n", __func__); return rc; } ipd = input_allocate_device(); if (ipd == NULL) { pr_err("%s: Unable to allocate memory \n", __func__); 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) { pr_err("%s: othc resource:IRQ_IR absent \n", __func__); rc = -ENXIO; goto fail_othc_config; } if (hsed_config->othc_headset == OTHC_HEADSET_NO) { if (dd->othc_irq_sw < 0) { pr_err("%s: othc resource:IRQ_SW absent\n", __func__); rc = -ENXIO; goto fail_othc_config; } } ipd->name = "pmic8058_othc"; ipd->phys = "pmic8058_othc/input0"; ipd->dev.parent = &pd->dev; input_set_capability(ipd, EV_SW, SW_HEADPHONE_INSERT); input_set_capability(ipd, EV_KEY, KEY_MEDIA); input_set_drvdata(ipd, dd); dd->othc_ipd = ipd; dd->othc_sw_state = false; dd->othc_ir_state = false; if (hsed_config->othc_headset == OTHC_HEADSET_NC) { /* Check if NC specific pdata is present */ if (!hsed_config->othc_nc_gpio_setup || !hsed_config->othc_nc_gpio) { pr_err("%s: NC headset pdata missing \n", __func__); rc = -EINVAL; goto fail_othc_config; } } rc = pm8058_configure_othc(dd); if (rc < 0) goto fail_othc_config; rc = input_register_device(ipd); if (rc) { pr_err("%s: Unable to register OTHC device \n", __func__); goto fail_othc_config; } /* Check if the headset is already inserted during boot up */ rc = pm8058_irq_get_rt_status(dd->pm_chip, dd->othc_irq_ir); if (rc < 0) { pr_err("%s: Unable to get headset status at boot\n", __func__); goto fail_ir_irq; } if (rc) { pr_debug("%s: Headset inserted during boot up\n", __func__); /* Headset present */ dd->othc_ir_state = true; switch_set_state(&dd->othc_sdev, 1); input_report_switch(dd->othc_ipd, SW_HEADPHONE_INSERT, 1); input_sync(dd->othc_ipd); } rc = request_irq(dd->othc_irq_ir, pm8058_nc_ir, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "pm8058_othc_ir", dd); if (rc < 0) { pr_err("%s: Unable to request pm8058_othc_ir IRQ\n", __func__); goto fail_ir_irq; } if (hsed_config->othc_headset == OTHC_HEADSET_NO) { /* This irq is used only for NO type headset */ rc = request_irq(dd->othc_irq_sw, pm8058_no_sw, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "pm8058_othc_sw", dd); if (rc < 0) { pr_err("%s: Unable to request pm8058_othc_sw IRQ \n", __func__); goto fail_sw_irq; } } else { /* NC type of headset use GPIO for IR */ rc = hsed_config->othc_nc_gpio_setup(); if (rc < 0) { pr_err("%s: Unable to setup gpio for NC type \n", __func__); goto fail_sw_irq; } } device_init_wakeup(&pd->dev, hsed_config->othc_wakeup); 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_othc_config: input_free_device(ipd); fail_input_alloc: switch_dev_unregister(&dd->othc_sdev); return rc; }