static int init_regulators(struct omap_dss_device *dssdev, struct panel_regulator *regulators, int n) { int r, i, v; for (i = 0; i < n; i++) { struct regulator *reg; reg = regulator_get(&dssdev->dev, regulators[i].name); if (IS_ERR(reg)) { dev_err(&dssdev->dev, "failed to get regulator %s\n", regulators[i].name); r = PTR_ERR(reg); goto err; } /* FIXME: better handling of fixed vs. variable regulators */ v = regulator_get_voltage(reg); if (v < regulators[i].min_uV || v > regulators[i].max_uV) { r = regulator_set_voltage(reg, regulators[i].min_uV, regulators[i].max_uV); if (r) { dev_err(&dssdev->dev, "failed to set regulator %s voltage\n", regulators[i].name); regulator_put(reg); goto err; } } r = regulator_enable(reg); if (r) { dev_err(&dssdev->dev, "failed to enable regulator %s\n", regulators[i].name); regulator_put(reg); goto err; } regulators[i].regulator = reg; } return 0; err: free_regulators(regulators, i); return r; }
/* * Performs platform device cleanup */ static void abx500_accessory_cleanup(struct abx500_ad *dd) { dev_dbg(&dd->pdev->dev, "Enter: %s\n", __func__); dd->jack_type = JACK_TYPE_UNSPECIFIED; config_accdetect(dd); gpio_free(dd->pdata->video_ctrl_gpio); input_unregister_device(dd->btn_input_dev); free_regulators(dd); cancel_delayed_work(&dd->detect_work); cancel_delayed_work(&dd->unplug_irq_work); cancel_delayed_work(&dd->init_work); flush_workqueue(dd->irq_work_queue); destroy_workqueue(dd->irq_work_queue); switch_dev_unregister(&dd->ab_switch); kfree(dd); }
/* * gets required regulators. */ static int create_regulators(struct abx500_ad *dd) { int i; int status = 0; for (i = 0; i < dd->no_of_regu_desc; i++) { struct regulator *regu = regulator_get(&dd->pdev->dev, dd->regu_desc[i].name); if (IS_ERR(regu)) { status = PTR_ERR(regu); dev_err(&dd->pdev->dev, "%s: Failed to get supply '%s' (%d).\n", __func__, dd->regu_desc[i].name, status); free_regulators(dd); goto out; } else { dd->regu_desc[i].handle = regu; } } out: return status; }
/* * performs platform device initialization */ static int abx500_accessory_init(struct platform_device *pdev) { int ret; struct abx500_ad *dd = (struct abx500_ad *)pdev->id_entry->driver_data; dev_dbg(&pdev->dev, "Enter: %s\n", __func__); dd->pdev = pdev; dd->pdata = dd->get_platform_data(pdev); if (IS_ERR(dd->pdata)) return PTR_ERR(dd->pdata); if (dd->pdata->video_ctrl_gpio) { ret = gpio_is_valid(dd->pdata->video_ctrl_gpio); if (!ret) { dev_err(&pdev->dev, "%s: Video ctrl GPIO invalid (%d).\n", __func__, dd->pdata->video_ctrl_gpio); return ret; } ret = gpio_request(dd->pdata->video_ctrl_gpio, "Video Control"); if (ret) { dev_err(&pdev->dev, "%s: Get video ctrl GPIO" "failed.\n", __func__); return ret; } } (ret = create_btn_input_dev(dd)); if (ret < 0) { dev_err(&pdev->dev, "%s: create_button_input_dev failed.\n", __func__); goto fail_no_btn_input_dev; } ret = create_regulators(dd); if (ret < 0) { dev_err(&pdev->dev, "%s: failed to create regulators\n", __func__); goto fail_no_regulators; } dd->btn_state = BUTTON_UNK; dd->irq_work_queue = create_singlethread_workqueue("abx500_accdet_wq"); if (!dd->irq_work_queue) { dev_err(&pdev->dev, "%s: Failed to create wq\n", __func__); ret = -ENOMEM; goto fail_no_mem_for_wq; } dd->gpadc = dd->accdet_abx500_gpadc_get(); INIT_DELAYED_WORK(&dd->detect_work, detect_work); INIT_DELAYED_WORK(&dd->unplug_irq_work, unplug_irq_handler_work); INIT_DELAYED_WORK(&dd->init_work, init_work); /* Deferred init/detect since no use for the info early in boot */ queue_delayed_work(dd->irq_work_queue, &dd->init_work, msecs_to_jiffies(INIT_DELAY_MS)); platform_set_drvdata(pdev, dd); /* Android switch interface */ dd->ab_switch.name = "h2w"; ret = switch_dev_register(&dd->ab_switch); if (ret < 0) goto fail_switch; return 0; fail_switch: destroy_workqueue(dd->irq_work_queue); fail_no_mem_for_wq: free_regulators(dd); fail_no_regulators: input_unregister_device(dd->btn_input_dev); fail_no_btn_input_dev: if (dd->pdata->video_ctrl_gpio) gpio_free(dd->pdata->video_ctrl_gpio); return ret; }