Example #1
0
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;
}