[v2,20/21] OMAP: DSS2: Taal: Add regulator configuration support
diff mbox

Message ID ca115745068df8138dcc09052fb0e6868986fabe.1272621452.git.ext-jani.1.nikula@nokia.com
State New, archived
Delegated to: Tomi Valkeinen
Headers show

Commit Message

Jani Nikula May 3, 2010, 6:18 a.m. UTC
None

Patch
diff mbox

diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c
index e209713..07832c4 100644
--- a/drivers/video/omap2/displays/panel-taal.c
+++ b/drivers/video/omap2/displays/panel-taal.c
@@ -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");
@@ -715,6 +793,8 @@  err_gpio:
 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;
@@ -747,6 +827,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);
 }