Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c8cd4547 authored by Tomi Valkeinen's avatar Tomi Valkeinen
Browse files

OMAP: DSS2: Taal: Add regulator configuration support



Add support for configuring regulators in the panel specific
configuration data.

Signed-off-by: default avatarJani Nikula <ext-jani.1.nikula@nokia.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@nokia.com>
parent 0f45bddf
Loading
Loading
Loading
Loading
+83 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <linux/gpio.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/regulator/consumer.h>
#include <linux/mutex.h>

#include <plat/display.h>
@@ -68,6 +69,73 @@ static irqreturn_t taal_te_isr(int irq, void *data);
static void taal_te_timeout_work_callback(struct work_struct *work);
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);

struct panel_regulator {
	struct regulator *regulator;
	const char *name;
	int min_uV;
	int max_uV;
};

static void free_regulators(struct panel_regulator *regulators, int n)
{
	int i;

	for (i = 0; i < n; i++) {
		/* disable/put in reverse order */
		regulator_disable(regulators[n - i - 1].regulator);
		regulator_put(regulators[n - i - 1].regulator);
	}
}

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;
}

/**
 * struct panel_config - panel configuration
 * @name: panel name
@@ -75,6 +143,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
 * @timings: panel resolution
 * @sleep: various panel specific delays, passed to msleep() if non-zero
 * @reset_sequence: reset sequence timings, passed to udelay() if non-zero
 * @regulators: array of panel regulators
 * @num_regulators: number of regulators in the array
 */
struct panel_config {
	const char *name;
@@ -93,6 +163,9 @@ struct panel_config {
		unsigned int high;
		unsigned int low;
	} reset_sequence;

	struct panel_regulator *regulators;
	int num_regulators;
};

enum {
@@ -629,6 +702,11 @@ static int taal_probe(struct omap_dss_device *dssdev)

	atomic_set(&td->do_update, 0);

	r = init_regulators(dssdev, panel_config->regulators,
			panel_config->num_regulators);
	if (r)
		goto err_reg;

	td->esd_wq = create_singlethread_workqueue("taal_esd");
	if (td->esd_wq == NULL) {
		dev_err(&dssdev->dev, "can't create ESD workqueue\n");
@@ -714,6 +792,8 @@ static int taal_probe(struct omap_dss_device *dssdev)
err_bl:
	destroy_workqueue(td->esd_wq);
err_wq:
	free_regulators(panel_config->regulators, panel_config->num_regulators);
err_reg:
	kfree(td);
err:
	return r;
@@ -746,6 +826,9 @@ static void taal_remove(struct omap_dss_device *dssdev)
	/* reset, to be sure that the panel is in a valid state */
	taal_hw_reset(dssdev);

	free_regulators(td->panel_config->regulators,
			td->panel_config->num_regulators);

	kfree(td);
}