EDP: remove old system EDP framework (lm3528 backlight driver)
[linux-3.10.git] / drivers / video / backlight / lm3528_bl.c
1 /*
2  * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms and conditions of the GNU General Public License,
6  * version 2, as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11  * more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  */
16
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/fb.h>
20 #include <linux/backlight.h>
21 #include <linux/slab.h>
22 #include <linux/module.h>
23 #include <linux/i2c.h>
24 #include <linux/err.h>
25 #include <linux/regulator/consumer.h>
26 #include <linux/lm3528.h>
27 #include <linux/regmap.h>
28
29 #define LM3528_BL_MAX_CURR      0x7F
30
31 /* I2C registers */
32 #define LM3528_GP               0x10
33 #define LM3528_GP_ENM           (1 << 0)
34 #define LM3528_GP_ENS           (1 << 1)
35 #define LM3528_GP_UNI           (1 << 2)
36 #define LM3528_GP_RMP0          (1 << 3)
37 #define LM3528_GP_RMP1          (1 << 4)
38 #define LM3528_GP_OLED          (1 << 5)
39
40 #define LM3528_BMAIN            0xA0
41 #define LM3528_BSUB             0xB0
42 #define LM3528_HPG              0x80
43 #define LM3528_GPIO             0x81
44 #define LM3528_PGEN0            0x90
45 #define LM3528_PGEN1            0x91
46 #define LM3528_PGEN2            0x92
47 #define LM3528_PGEN3            0x93
48
49 struct lm3528_backlight_data {
50         struct device           *lm3528_dev;
51         struct regmap           *regmap;
52         struct i2c_client       *client;
53         struct regulator        *regulator;
54         struct backlight_device *bl;
55         bool (*is_powered)(void);
56         int (*notify)(struct device *dev, int brightness);
57         int                     current_brightness;
58 };
59
60 enum chips { lm3528 };
61
62 static const struct i2c_device_id lm3528_id[] = {
63         { "lm3528_display_bl", lm3528 },
64         {},
65 };
66 MODULE_DEVICE_TABLE(i2c, lm3528_id);
67
68 static const struct regmap_config lm3528_regmap_config = {
69         .reg_bits = 8,
70         .val_bits = 8,
71 };
72
73 static int lm3528_backlight_set(struct backlight_device *bl, int brightness)
74 {
75         struct lm3528_backlight_data *data = bl_get_data(bl);
76
77         if (data->is_powered)
78                 if (!data->is_powered()) {
79                         pr_err("%s skipped as panel is not powered\n",
80                                 __func__);
81                         /* do not report error else suspend fails */
82                         return 0;
83                 }
84
85         if (data->notify)
86                 brightness = data->notify(data->lm3528_dev, brightness);
87
88         data->current_brightness = brightness;
89
90         /* normalize the brightness value [0-255] to lm3528 range */
91         brightness = brightness * LM3528_BL_MAX_CURR / 255;
92
93         regmap_update_bits(data->regmap, LM3528_GP,
94                                 LM3528_GP_ENM | LM3528_GP_UNI,
95                                 LM3528_GP_ENM | LM3528_GP_UNI);
96
97         return regmap_write(data->regmap, LM3528_BMAIN, brightness);
98 }
99
100 static int lm3528_backlight_update_status(struct backlight_device *bl)
101 {
102         int brightness = bl->props.brightness;
103         return lm3528_backlight_set(bl, brightness);
104 }
105
106 static int lm3528_backlight_get_brightness(struct backlight_device *bl)
107 {
108         struct lm3528_backlight_data *data = bl_get_data(bl);
109         return data->current_brightness;
110 }
111
112 static const struct backlight_ops lm3528_backlight_ops = {
113         .update_status  = lm3528_backlight_update_status,
114         .get_brightness = lm3528_backlight_get_brightness,
115 };
116
117 static int lm3528_bl_probe(struct i2c_client *i2c,
118         const struct i2c_device_id *id)
119 {
120         struct lm3528_backlight_data *data;
121         struct backlight_device *bl;
122         struct backlight_properties props;
123         struct lm3528_platform_data *pData = i2c->dev.platform_data;
124         int ret;
125
126         data = devm_kzalloc(&i2c->dev, sizeof(*data), GFP_KERNEL);
127         if (data == NULL)
128                 return -ENOMEM;
129
130         data->client = i2c;
131         data->lm3528_dev = &i2c->dev;
132         data->current_brightness = 0;
133         data->notify = pData->notify;
134         data->is_powered = pData->is_powered;
135         data->regulator = regulator_get(data->lm3528_dev, "vin");
136         if (IS_ERR(data->regulator)) {
137                 dev_err(&i2c->dev, "%s: failed to get regulator\n", __func__);
138                 data->regulator = NULL;
139         } else {
140                 regulator_enable(data->regulator);
141         }
142
143         data->regmap = devm_regmap_init_i2c(i2c, &lm3528_regmap_config);
144         if (IS_ERR(data->regmap)) {
145                 ret = PTR_ERR(data->regmap);
146                 dev_err(&i2c->dev, "regmap init failed: %d\n", ret);
147                 return ret;
148         }
149
150         props.type = BACKLIGHT_RAW;
151         props.max_brightness = 255;
152         bl = backlight_device_register(i2c->name, data->lm3528_dev, data,
153                                        &lm3528_backlight_ops, &props);
154         if (IS_ERR(bl)) {
155                 dev_err(&i2c->dev, "failed to register backlight\n");
156                 return PTR_ERR(bl);
157         }
158
159         data->bl = bl;
160         bl->props.brightness = pData->dft_brightness;
161
162         i2c_set_clientdata(i2c, data);
163         backlight_update_status(bl);
164         return 0;
165 }
166
167 static int lm3528_bl_remove(struct i2c_client *cl)
168 {
169         struct lm3528_backlight_data *data = i2c_get_clientdata(cl);
170         data->bl->props.brightness = 0;
171         backlight_update_status(data->bl);
172         backlight_device_unregister(data->bl);
173         return 0;
174 }
175
176 #ifdef CONFIG_PM
177 static int lm3528_bl_suspend(struct device *dev)
178 {
179         struct i2c_client *i2c = to_i2c_client(dev);
180         struct lm3528_backlight_data *data = i2c_get_clientdata(i2c);
181         struct backlight_device *bl = data->bl;
182
183         return lm3528_backlight_set(bl, 0);
184 }
185
186 static int lm3528_bl_resume(struct device *dev)
187 {
188         struct i2c_client *i2c = to_i2c_client(dev);
189         struct lm3528_backlight_data *data = i2c_get_clientdata(i2c);
190         struct backlight_device *bl = data->bl;
191
192         backlight_update_status(bl);
193         return 0;
194 }
195
196 static const struct dev_pm_ops lm3528_bl_pm_ops = {
197         .suspend        = lm3528_bl_suspend,
198         .resume         = lm3528_bl_resume,
199 };
200 #endif
201
202 static struct i2c_driver lm3528_bl_driver = {
203         .driver = {
204                 .name   = "lm3528_display_bl",
205                 .owner  = THIS_MODULE,
206 #ifdef CONFIG_PM
207                 .pm     = &lm3528_bl_pm_ops,
208 #endif
209         },
210         .id_table = lm3528_id,
211         .probe  = lm3528_bl_probe,
212         .remove = lm3528_bl_remove,
213 };
214 module_i2c_driver(lm3528_bl_driver);
215
216 MODULE_AUTHOR("Chaitanya Bandi <bandik@nvidia.com>");
217 MODULE_DESCRIPTION("LM3528 Backlight display driver");
218 MODULE_LICENSE("GPL v2");