OMAP: DSS2: Taal: Add regulator configuration support
authorTomi Valkeinen <tomi.valkeinen@nokia.com>
Wed, 9 Jun 2010 12:24:46 +0000 (15:24 +0300)
committerTomi Valkeinen <tomi.valkeinen@nokia.com>
Tue, 3 Aug 2010 12:18:49 +0000 (15:18 +0300)
Add support for configuring regulators in the panel specific
configuration data.

Signed-off-by: Jani Nikula <ext-jani.1.nikula@nokia.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
drivers/video/omap2/displays/panel-taal.c

index cbe0214e2f05d33b22826b6a436768455057265f..941f1f208c9e4960176515bdb94d1aff0c9e7cbb 100644 (file)
@@ -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 @@ 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;
@@ -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);
 }