backlight: lm3528: Add backlight driver for LM3528
Chaitanya Bandi [Tue, 12 Feb 2013 08:59:29 +0000 (13:59 +0530)]
Bug 1216857

Change-Id: I2ec1a393769804d73191d690d8340c30885e16ae
Signed-off-by: Chaitanya Bandi <bandik@nvidia.com>
Reviewed-on: http://git-master/r/199925
(cherry picked from commit 82de53cdad7de223cfefc9b5e33b370bd5c18957)
Reviewed-on: http://git-master/r/204954
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Thomas Cherry <tcherry@nvidia.com>

drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/lm3528_bl.c [new file with mode: 0644]
include/linux/lm3528.h [new file with mode: 0644]

index bd836b2..d071ffa 100644 (file)
@@ -442,6 +442,14 @@ config BACKLIGHT_MAX8831
          If you have a MAX8831 for backlight, say Y to enable the
          backlight driver.
 
+config BACKLIGHT_LM3528
+       tristate "Backlight driver for TI LM3528"
+       depends on I2C=y
+       select REGMAP_I2C
+       help
+         If you have a LM3528 for backlight, say Y to enable the
+         backlight driver.
+
 endif # BACKLIGHT_CLASS_DEVICE
 
 endif # BACKLIGHT_LCD_SUPPORT
index 21820f9..91ec9c6 100644 (file)
@@ -55,3 +55,4 @@ obj-$(CONFIG_BACKLIGHT_TEGRA_PWM)     += tegra_pwm_bl.o
 obj-$(CONFIG_BACKLIGHT_TOSA)           += tosa_bl.o
 obj-$(CONFIG_BACKLIGHT_TPS65217)       += tps65217_bl.o
 obj-$(CONFIG_BACKLIGHT_WM831X)         += wm831x_bl.o
+obj-$(CONFIG_BACKLIGHT_LM3528)         += lm3528_bl.o
diff --git a/drivers/video/backlight/lm3528_bl.c b/drivers/video/backlight/lm3528_bl.c
new file mode 100644 (file)
index 0000000..e377713
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/regulator/consumer.h>
+#include <linux/lm3528.h>
+#include <linux/regmap.h>
+
+#define LM3528_BL_MAX_CURR     0x7F
+
+/* I2C registers */
+#define LM3528_GP              0x10
+#define LM3528_GP_ENM          (1 << 0)
+#define LM3528_GP_ENS          (1 << 1)
+#define LM3528_GP_UNI          (1 << 2)
+#define LM3528_GP_RMP0         (1 << 3)
+#define LM3528_GP_RMP1         (1 << 4)
+#define LM3528_GP_OLED         (1 << 5)
+
+#define        LM3528_BMAIN            0xA0
+#define LM3528_BSUB            0xB0
+#define LM3528_HPG             0x80
+#define LM3528_GPIO            0x81
+#define        LM3528_PGEN0            0x90
+#define        LM3528_PGEN1            0x91
+#define        LM3528_PGEN2            0x92
+#define        LM3528_PGEN3            0x93
+
+struct lm3528_backlight_data {
+       struct device           *lm3528_dev;
+       struct regmap           *regmap;
+       struct i2c_client       *client;
+       struct regulator        *regulator;
+       struct backlight_device *bl;
+       int (*notify)(struct device *dev, int brightness);
+       int                     current_brightness;
+};
+
+enum chips { lm3528 };
+
+static const struct i2c_device_id lm3528_id[] = {
+       { "lm3528_display_bl", lm3528 },
+       {},
+};
+MODULE_DEVICE_TABLE(i2c, lm3528_id);
+
+static const struct regmap_config lm3528_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+};
+
+static int lm3528_backlight_set(struct backlight_device *bl, int brightness)
+{
+       struct lm3528_backlight_data *data = bl_get_data(bl);
+       data->current_brightness = brightness;
+
+       regmap_update_bits(data->regmap, LM3528_GP,
+                               LM3528_GP_ENM | LM3528_GP_UNI,
+                               LM3528_GP_ENM | LM3528_GP_UNI);
+
+       return regmap_write(data->regmap, LM3528_BMAIN, brightness);
+}
+
+static int lm3528_backlight_get_brightness(struct backlight_device *bl)
+{
+       struct lm3528_backlight_data *data = bl_get_data(bl);
+       return data->current_brightness;
+}
+
+static int lm3528_backlight_update_status(struct backlight_device *bl)
+{
+       struct lm3528_backlight_data *data = bl_get_data(bl);
+       int brightness = bl->props.brightness;
+
+       if (data->notify)
+               brightness = data->notify(data->lm3528_dev, brightness);
+
+       return lm3528_backlight_set(bl, brightness);
+}
+
+static const struct backlight_ops lm3528_backlight_ops = {
+       .update_status  = lm3528_backlight_update_status,
+       .get_brightness = lm3528_backlight_get_brightness,
+};
+
+static int lm3528_bl_probe(struct i2c_client *i2c,
+       const struct i2c_device_id *id)
+{
+       struct lm3528_backlight_data *data;
+       struct backlight_device *bl;
+       struct backlight_properties props;
+       struct lm3528_platform_data *pData = i2c->dev.platform_data;
+       int ret;
+
+       data = devm_kzalloc(&i2c->dev, sizeof(*data), GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       data->client = i2c;
+       data->lm3528_dev = &i2c->dev;
+       data->current_brightness = 0;
+       data->notify = pData->notify;
+       data->regulator = regulator_get(data->lm3528_dev, "vin");
+       if (IS_ERR(data->regulator)) {
+               dev_err(&i2c->dev, "%s: failed to get regulator\n", __func__);
+               data->regulator = NULL;
+       } else {
+               regulator_enable(data->regulator);
+       }
+
+       data->regmap = devm_regmap_init_i2c(i2c, &lm3528_regmap_config);
+       if (IS_ERR(data->regmap)) {
+               ret = PTR_ERR(data->regmap);
+               dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
+               return ret;
+       }
+
+       props.type = BACKLIGHT_RAW;
+       props.max_brightness = 255;
+       bl = backlight_device_register(i2c->name, data->lm3528_dev, data,
+                                      &lm3528_backlight_ops, &props);
+       if (IS_ERR(bl)) {
+               dev_err(&i2c->dev, "failed to register backlight\n");
+               return PTR_ERR(bl);
+       }
+
+       data->bl = bl;
+       bl->props.brightness = pData->dft_brightness;
+
+       i2c_set_clientdata(i2c, data);
+       backlight_update_status(bl);
+       return 0;
+}
+
+static int __devexit lm3528_bl_remove(struct i2c_client *cl)
+{
+       struct lm3528_backlight_data *data = i2c_get_clientdata(cl);
+       data->bl->props.brightness = 0;
+       backlight_update_status(data->bl);
+       backlight_device_unregister(data->bl);
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int lm3528_bl_suspend(struct device *dev)
+{
+       struct i2c_client *i2c = to_i2c_client(dev);
+       struct lm3528_backlight_data *data = i2c_get_clientdata(i2c);
+       struct backlight_device *bl = data->bl;
+
+       return lm3528_backlight_set(bl, 0);
+}
+
+static int lm3528_bl_resume(struct device *dev)
+{
+       struct i2c_client *i2c = to_i2c_client(dev);
+       struct lm3528_backlight_data *data = i2c_get_clientdata(i2c);
+       struct backlight_device *bl = data->bl;
+
+       backlight_update_status(bl);
+       return 0;
+}
+
+static const struct dev_pm_ops lm3528_bl_pm_ops = {
+       .suspend        = lm3528_bl_suspend,
+       .resume         = lm3528_bl_resume,
+};
+#endif
+
+static struct i2c_driver lm3528_bl_driver = {
+       .driver = {
+               .name   = "lm3528_display_bl",
+               .owner  = THIS_MODULE,
+#ifdef CONFIG_PM
+               .pm     = &lm3528_bl_pm_ops,
+#endif
+       },
+       .id_table = lm3528_id,
+       .probe  = lm3528_bl_probe,
+       .remove = __devexit_p(lm3528_bl_remove),
+};
+module_i2c_driver(lm3528_bl_driver);
+
+MODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>");
+MODULE_DESCRIPTION("LM3528 Backlight display driver");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/lm3528.h b/include/linux/lm3528.h
new file mode 100644 (file)
index 0000000..59bfdd4
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __LINUX_LM3528_BACKLIGHT_H
+#define __LINUX_LM3528_BACKLIGHT_H
+
+#include <linux/backlight.h>
+
+struct lm3528_platform_data {
+       unsigned int dft_brightness;
+       int (*notify)(struct device *dev, int brightness);
+};
+
+#endif
+