summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormattis fjallstrom <mattis@acm.org>2015-04-13 16:13:47 -0700
committermattis fjallstrom <mattis@acm.org>2015-04-13 16:13:47 -0700
commit51f4dba7f9029e25e6b91b3a8b9c6569c21af0cc (patch)
tree317ea024c532133ba7d259e427d9164816e1c2f6
parent26621f86d74d70df0afdb4fc1de819ced3a074f2 (diff)
downloadolio-linux-3.10-51f4dba7f9029e25e6b91b3a8b9c6569c21af0cc.tar.xz
olio-linux-3.10-51f4dba7f9029e25e6b91b3a8b9c6569c21af0cc.zip
Adding basic power management for the backlight and the display panel driver.
Change-Id: Ibe4546e9f7b694f03b5aa6f8b6188f96806c8ad1
-rw-r--r--drivers/leds/leds-lm3530.c46
-rw-r--r--drivers/video/omap2/displays/panel-ili9342.c143
2 files changed, 178 insertions, 11 deletions
diff --git a/drivers/leds/leds-lm3530.c b/drivers/leds/leds-lm3530.c
index c3182fae12e..b9661ea70bb 100644
--- a/drivers/leds/leds-lm3530.c
+++ b/drivers/leds/leds-lm3530.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2015 Olio Devices
* Copyright (C) 2011 ST-Ericsson SA.
* Copyright (C) 2009 Motorola, Inc.
*
@@ -6,7 +7,8 @@
*
* Simple driver for National Semiconductor LM3530 Backlight driver chip
*
- * Author: Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com>
+ * Author: Mattis Fjallstrom <mattis@oliodevices.com>
+ * based on Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com>
* based on leds-lm3530.c by Dan Murphy <D.Murphy@motorola.com>
*/
@@ -487,7 +489,7 @@ static int lm3530_remove(struct i2c_client *client)
}
-/***************************************************************************
+/**
* lm3530_shutdown - make sure brightness is set to 0
*
* The PMIC of the Olio H1 can't provide the power needed by the lm3530,
@@ -504,6 +506,45 @@ static void lm3530_shutdown(struct i2c_client *client)
return;
}
+/**
+ * lm3530_suspend - suspend backlight
+ *
+ * For now, off. Should also save the previous setting.
+ */
+
+static int lm3530_suspend(struct device *dev) {
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+ printk ("OLIO %s:%s Suspending\n", __FILE__, __FUNCTION__);
+
+ lm3530_brightness_set(led_cdev, LED_OFF);
+
+ return 0;
+}
+
+/**
+ * lm3530_resume - reset backlight
+ *
+ * Turn the backlight on again (Does android take care of this for us?)
+ */
+
+static int lm3530_resume(struct device *dev) {
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+
+ printk ("OLIO %s:%s Resuming\n", __FILE__, __FUNCTION__);
+
+ /* lm3530_brightness_set(led_cdev, 100); */
+
+ return 0;
+}
+
+
+/* ---------------------------------------------------------------------- */
+
+static const struct dev_pm_ops lm3530_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(lm3530_suspend, lm3530_resume)
+};
+
static const struct i2c_device_id lm3530_id[] = {
{LM3530_NAME, 0},
{}
@@ -518,6 +559,7 @@ static struct i2c_driver lm3530_i2c_driver = {
.driver = {
.name = LM3530_NAME,
.owner = THIS_MODULE,
+ .pm = &lm3530_pm_ops,
},
};
diff --git a/drivers/video/omap2/displays/panel-ili9342.c b/drivers/video/omap2/displays/panel-ili9342.c
index 37dc5165e9c..afcf05dfa79 100644
--- a/drivers/video/omap2/displays/panel-ili9342.c
+++ b/drivers/video/omap2/displays/panel-ili9342.c
@@ -2,8 +2,9 @@
/*
* Driver for ili9342 display driver
*
- * Copyright (C) 2014 Olio Devices Inc.
+ * Copyright (C) 2014,2015 Olio Devices Inc.
* Author: Evan Wilson <evan@oliodevices.com>
+ * Author: Mattis Fjallstrom <mattis@oliodevices.com>
*
* Adapted from panel-generic-dpi.c, panel-nec-nl8048hl11-01b.c
*
@@ -25,8 +26,17 @@
#include <linux/slab.h>
#include <linux/spi/spi.h>
#include <linux/gpio.h>
+#include <linux/device.h>
+#include <linux/regulator/consumer.h>
+
#include <video/omapdss.h>
+#ifdef OLIODEBUG
+#define oliodebug(...) printk ( __VA_ARGS__ )
+#else
+#define oliodebug(...)
+#endif
+
struct panel_config {
struct omap_video_timings timings;
@@ -250,6 +260,28 @@ static int ili9342_get_recommended_bpp(struct omap_dss_device *dssdev) {
return 24;
}
+/***************************************************************************
+ * suspend & resume
+ *
+ * For now, this is all handled by the SPI driver (see below).
+ * Leaving this functions here should we change our minds.
+ */
+
+static int ili9342_disp_suspend (struct device * dev) {
+
+ return 0;
+}
+
+static int ili9342_disp_resume (struct device * dev) {
+
+ return 0;
+}
+
+static struct dev_pm_ops ili9342_disp_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ili9342_disp_suspend, ili9342_disp_resume)
+};
+
+
static struct omap_dss_driver ili9342_driver = {
.probe = ili9342_panel_probe,
.remove = __exit_p(ili9342_panel_remove),
@@ -266,9 +298,20 @@ static struct omap_dss_driver ili9342_driver = {
.driver = {
.name = "ili9342_panel",
.owner = THIS_MODULE,
+ .pm = &ili9342_disp_pm_ops,
},
};
+/* ====================================================================== */
+
+/* Here follows the SPI driver - it's required by the panel, but the
+ * coupling is rather weak. It registers another driver.
+ */
+
+/* ====================================================================== */
+
+static struct regulator *spi_regulator;
+
static int ili9342_spi_write(struct spi_device *spi, bool cmd, unsigned char val) {
unsigned short buf;
struct spi_message m;
@@ -407,6 +450,20 @@ static inline void ili9342_init_seq(struct spi_device *spi) {
ili9342_write_cmd(spi, 0x29);
}
+
+static inline void init_ili9342_hw (struct spi_device *spi) {
+ struct omap_dss_device *panel = spi->dev.platform_data;
+
+ gpio_set_value(panel->reset_gpio, 1);
+ mdelay(1);
+ gpio_set_value(panel->reset_gpio, 0);
+ mdelay(50);
+ gpio_set_value(panel->reset_gpio, 1);
+ mdelay(120);
+
+ ili9342_init_seq(spi);
+}
+
static inline int init_ili9342_spi(struct spi_device *spi) {
struct omap_dss_device *panel = spi->dev.platform_data;
int reset_gpio;
@@ -433,35 +490,103 @@ static inline int init_ili9342_spi(struct spi_device *spi) {
return -EINVAL;
}
- gpio_set_value(panel->reset_gpio, 1);
- mdelay(1);
- gpio_set_value(panel->reset_gpio, 0);
- mdelay(50);
- gpio_set_value(panel->reset_gpio, 1);
- mdelay(120);
-
- ili9342_init_seq(spi);
+ init_ili9342_hw (spi);
return 0;
}
+
static int ili9342_spi_probe(struct spi_device *spi)
{
+ int err;
+ int ret;
+
+ spi_regulator = devm_regulator_get(&spi->dev, "vdd");
+
+ if (IS_ERR(spi_regulator)) {
+ dev_err(&spi->dev, "regulator get failed\n");
+ err = PTR_ERR(spi_regulator);
+ spi_regulator = NULL;
+ return err;
+ }
+
+ ret = regulator_enable(spi_regulator);
+
+ if (ret) {
+ dev_err(&spi->dev, "Failed to enable vdd: %d\n", ret);
+ return ret;
+ }
+
init_ili9342_spi(spi);
+
return omap_dss_register_driver(&ili9342_driver);
}
static int ili9342_spi_remove(struct spi_device *spi)
{
+ oliodebug ("OLIO %s:%s Removing SPI\n", __FILE__, __FUNCTION__);
+
omap_dss_unregister_driver(&ili9342_driver);
return 0;
}
+static int ili9342_suspend(struct device *dev) {
+ int ret;
+
+ oliodebug ("OLIO %s:%s Suspending SPI for %s\n", __FILE__, __FUNCTION__, dev_name(dev));
+
+ ret = regulator_disable(spi_regulator);
+ if (ret) {
+ dev_err(dev, "Failed to disable vdd:%d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int ili9342_resume(struct device *dev) {
+ int ret;
+
+ /* HACK WARNING: We need an spi_device here. If, as can be assumed,
+ * the device pointer passed in points to a device in an spi_device,
+ * it's the first device in the spi_device struct. In other words,
+ * it's address is the same as the spi_device and a cast should be OK.
+ */
+
+ /* IF, otoh, that's an incorrect assumption ... then this will lead
+ * to horrible crashes. But oh well, you can't win 'em all.
+ */
+
+ struct spi_device * spi = (struct spi_device *) dev;
+
+ oliodebug ("OLIO %s:%s Resuming SPI for %s\n", __FILE__, __FUNCTION__, dev_name(dev));
+
+ ret = regulator_enable(spi_regulator);
+
+ if (ret) {
+ dev_err(&spi->dev, "Failed to enable vdd: %d\n", ret);
+ return ret;
+ }
+
+ init_ili9342_hw (spi);
+
+ return 0;
+}
+
+
+static struct dev_pm_ops ili9342_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ili9342_suspend, ili9342_resume)
+};
+
+
static struct spi_driver ili9342_spi_driver = {
.probe = ili9342_spi_probe,
.remove = ili9342_spi_remove,
.driver = {
.name = "ili9342-spi",
.owner = THIS_MODULE,
+ .pm = &ili9342_pm_ops,
},
};