input: touch: maxim_sti: dvdd_on init val change
[linux-2.6.git] / drivers / video / tegra / of_lcd_device_data / tegratab_lcd_dev_data.c
1 /*
2  * Copyright (c) 2013, NVIDIA CORPORATION, All rights reserved.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/of.h>
17 #include <linux/err.h>
18 #include <linux/device.h>
19 #include <linux/regulator/consumer.h>
20 #include <linux/gpio.h>
21 #include <linux/of_gpio.h>
22 #include <mach/dc.h>
23 #include <linux/delay.h>
24
25 static struct platform_driver tegratab_lcd_devdata_gen_drv;
26 static struct device_node *gp_node;
27
28 /* LCDs list */
29 struct of_tegra_lcd_devdata tegratab_lgd_lcd;
30
31 #define LGD_LCD_REGULATORS_COUNT                3
32
33 #define WORKAROUND_TO_REMOVE_LGD7_T4_TIME       1
34
35 static bool lgd_lcd_reg_requested;
36
37 #if WORKAROUND_TO_REMOVE_LGD7_T4_TIME
38 extern atomic_t touch_dvdd_on;
39 #endif
40
41 static struct regulator *lgd_lcd_regs[LGD_LCD_REGULATORS_COUNT];
42
43 static struct regulator *avdd_lcd_3v3;
44 static struct regulator *vdd_lcd_bl_en;
45 static struct regulator *dvdd_lcd_1v8;
46
47 static struct tegra_dsi_cmd lgd_wxga_7_0_init_cmd[] = {
48         DSI_CMD_SHORT(0x15, 0x01, 0x0),
49         DSI_DLY_MS(20),
50         DSI_CMD_SHORT(0x15, 0xAE, 0x0B),
51         DSI_CMD_SHORT(0x15, 0xEE, 0xEA),
52         DSI_CMD_SHORT(0x15, 0xEF, 0x5F),
53         DSI_CMD_SHORT(0x15, 0xF2, 0x68),
54         DSI_CMD_SHORT(0x15, 0xEE, 0x0),
55         DSI_CMD_SHORT(0x15, 0xEF, 0x0),
56 };
57
58 static struct tegra_dsi_cmd lgd_wxga_7_0_late_resume_cmd[] = {
59         DSI_CMD_SHORT(0x15, 0x10, 0x0),
60         DSI_DLY_MS(120),
61 };
62
63 static struct tegra_dsi_cmd lgd_wxga_7_0_early_suspend_cmd[] = {
64         DSI_CMD_SHORT(0x15, 0x11, 0x0),
65         DSI_DLY_MS(160),
66 };
67
68 static struct tegra_dsi_cmd lgd_wxga_7_0_suspend_cmd[] = {
69         DSI_CMD_SHORT(0x15, 0x11, 0x0),
70         DSI_DLY_MS(160),
71 };
72
73 static int lgd_lcd_regulators_get(struct device *dev)
74 {
75         int err = 0;
76         struct property *prop;
77         const char *regulator;
78         int reg_i = 0;
79
80         if (lgd_lcd_reg_requested)
81                 return 0;
82         of_property_for_each_string(gp_node, "nvidia,regulators",
83                         prop, regulator) {
84                 lgd_lcd_regs[reg_i] =
85                         regulator_get(dev, regulator);
86                 if (IS_ERR_OR_NULL(lgd_lcd_regs[reg_i])) {
87                         err = PTR_ERR(lgd_lcd_regs[reg_i]);
88                         lgd_lcd_regs[reg_i] = NULL;
89                         return err;
90                 } else {
91                         if (reg_i == 0)
92                                 avdd_lcd_3v3 = lgd_lcd_regs[reg_i];
93                         else if (reg_i == 1)
94                                 vdd_lcd_bl_en = lgd_lcd_regs[reg_i];
95                         else if (reg_i == 2)
96                                 dvdd_lcd_1v8 = lgd_lcd_regs[reg_i];
97                         reg_i++;
98                 }
99         }
100         lgd_lcd_reg_requested = true;
101         return 0;
102 }
103
104 static int lgd_wxga_7_0_enable(struct device *dev)
105 {
106         int err = 0;
107
108         err = lgd_lcd_regulators_get(dev);
109         if (err < 0) {
110                 pr_err("lgd lcd regulator get failed\n");
111                 goto fail;
112         }
113 #if WORKAROUND_TO_REMOVE_LGD7_T4_TIME
114         /*
115          * LGD WXGA 7" panel spec requests 1s delay between
116          * "panel 3v3 off" and "3v3 on" if all panel
117          * related power rails (1v8, 3v3) are not turned off.
118
119          * precondition for work around
120          *  - In power off, panel off then touch off.
121          *  - In power on, touch on then panel on.
122
123          * why work around is necessary?
124          *  - Same 1v8 rail is shared by touch and panel.
125          *  - In panel off, 3v3 rail off and 1v8 rail off
126          *    are requested, but 1v8 rail isn't turned off
127          *    in panel off timeframe because of touch module.
128          *    It is possible to get panel on request without
129          *    touch off/on control. In this case, 1S delay
130          *    is necessary per spec. If 1v8 is turned off
131          *    and on by touch module before panel on request,
132          *    then, we don't need 1S delay. If 1v8 is turned
133          *    off in panel on request time, we don't need
134          *    1S delay, either.
135
136          * In device power on, we don't need to obey this
137          * precondition, since there's no power rail off.
138          * This can be accomplished by setting touch_dvdd_on
139          * initial state to true.
140          */
141
142         if ((!atomic_read(&touch_dvdd_on)) &&
143                 regulator_is_enabled(dvdd_lcd_1v8)) {
144                 msleep(1000);
145         }
146         /*
147          * Clean touch_dvdd_on
148          */
149         atomic_set(&touch_dvdd_on, 0);
150 #endif
151
152         if (dvdd_lcd_1v8) {
153                 err = regulator_enable(dvdd_lcd_1v8);
154                 if (err < 0) {
155                         pr_err("%s: dvdd_lcd_1v8 en failed\n", __func__);
156                         goto fail;
157                 }
158         }
159
160         msleep(20); /*Turn on 1.8V, then, AVDD after 20ms */
161
162         if (avdd_lcd_3v3) {
163                 err = regulator_enable(avdd_lcd_3v3);
164                 if (err < 0) {
165                         pr_err("%s: avdd_lcd_3v3 en failed\n", __func__);
166                         goto fail;
167                 }
168         }
169
170         /* VDD to MIPI > 100ms based on the spec.
171          * Driver already take 50ms, so having 50ms delay here.
172          */
173         msleep(50);
174
175         return 0;
176 fail:
177         return err;
178 }
179
180 static int lgd_wxga_7_0_postpoweron(struct device *dev)
181 {
182         int err = 0;
183
184         if (vdd_lcd_bl_en) {
185                 /*If rail is already enabled, we don't need delay*/
186                 /*
187                  * MIPI to VLED > 200ms, based on the spec
188                  * init_cmd cares 20ms delay already.
189                 */
190                 if (!regulator_is_enabled(vdd_lcd_bl_en))
191                         msleep(180);
192
193                 err = regulator_enable(vdd_lcd_bl_en);
194                 if (err < 0) {
195                         pr_err("%s: vdd_lcd_bl_en en failed\n", __func__);
196                         goto fail;
197                 }
198         }
199         return 0;
200 fail:
201         return err;
202 }
203
204 static int lgd_wxga_7_0_disable(void)
205 {
206         msleep(50); /*MIPI off to VDD off needs to be 50~150ms per spec*/
207
208         if (dvdd_lcd_1v8)
209                 regulator_disable(dvdd_lcd_1v8);
210         if (avdd_lcd_3v3)
211                 regulator_disable(avdd_lcd_3v3);
212
213 #if WORKAROUND_TO_REMOVE_LGD7_T4_TIME
214         /*
215          * Clean touch_dvdd_on here.
216          * pre condition for the work around mentions
217          * the sequence in power off is "panel off => touch off".
218          */
219         atomic_set(&touch_dvdd_on, 0);
220 #else
221         msleep(1000); /*LCD panel VDD on needs to be 1000>ms after it's off*/
222 #endif
223         return 0;
224 }
225
226 static int lgd_wxga_7_0_prepoweroff(void)
227 {
228         if (vdd_lcd_bl_en)
229                 regulator_disable(vdd_lcd_bl_en);
230
231         /*
232          * VLED off to MIPI off > 200ms per spec
233          * suspend_cmd cares 160ms delay already.
234          */
235         msleep(40);
236         return 0;
237 }
238
239 static int lgd_wxga_7_0_postsuspend(void)
240 {
241         return 0;
242 }
243
244 static void tegratab_lgd_lcd_devdata(struct of_tegra_lcd_devdata *lcd_dev_data)
245 {
246         lcd_dev_data->enable = lgd_wxga_7_0_enable;
247         lcd_dev_data->disable = lgd_wxga_7_0_disable;
248         lcd_dev_data->postpoweron = lgd_wxga_7_0_postpoweron;
249         lcd_dev_data->postsuspend = lgd_wxga_7_0_postsuspend;
250         lcd_dev_data->prepoweroff = lgd_wxga_7_0_prepoweroff;
251         lcd_dev_data->dsi_init_cmd =
252                 lgd_wxga_7_0_init_cmd;
253         lcd_dev_data->n_init_cmd =
254                 ARRAY_SIZE(lgd_wxga_7_0_init_cmd);
255         lcd_dev_data->dsi_early_suspend_cmd =
256                 lgd_wxga_7_0_early_suspend_cmd;
257         lcd_dev_data->n_early_suspend_cmd =
258                 ARRAY_SIZE(lgd_wxga_7_0_early_suspend_cmd);
259         lcd_dev_data->dsi_late_resume_cmd =
260                 lgd_wxga_7_0_late_resume_cmd;
261         lcd_dev_data->n_late_resume_cmd =
262                 ARRAY_SIZE(lgd_wxga_7_0_late_resume_cmd);
263         lcd_dev_data->dsi_suspend_cmd =
264                 lgd_wxga_7_0_suspend_cmd;
265         lcd_dev_data->n_suspend_cmd =
266                 ARRAY_SIZE(lgd_wxga_7_0_suspend_cmd);
267 }
268
269 static int tegra_lcd_match_in_dc(struct device *dev, void *data)
270 {
271         struct device_node *dn = data;
272
273         return (dev->of_node == dn) ? 1 : 0;
274 }
275
276 struct device *tegratab_lcd_devdata_to_dc(struct device_node *dn)
277 {
278         struct device *dev;
279         dev = driver_find_device(&tegratab_lcd_devdata_gen_drv.driver,
280                 NULL, dn, tegra_lcd_match_in_dc);
281         if (!dev)
282                 return NULL;
283         return dev;
284 }
285
286 static int tegratab_lcd_devdata_gen_probe(struct platform_device *pdev)
287 {
288         struct device *dev = &pdev->dev;
289         struct device_node *np = pdev->dev.of_node;
290         struct of_tegra_lcd_devdata *lcd_devdata;
291
292         gp_node = np;
293
294         lcd_devdata = devm_kzalloc(dev, sizeof(*lcd_devdata), GFP_KERNEL);
295         if (!lcd_devdata)
296                 return -ENOMEM;
297
298
299         if (of_find_compatible_node(NULL, NULL, "lgd,tegratab")) {
300                 tegratab_lgd_lcd_devdata(&tegratab_lgd_lcd);
301                 memcpy(lcd_devdata, &tegratab_lgd_lcd,
302                                 sizeof(struct of_tegra_lcd_devdata));
303         }
304
305         platform_set_drvdata(pdev, lcd_devdata);
306         lcd_devdata_to_dc_set_callback(tegratab_lcd_devdata_to_dc);
307         return 0;
308 }
309
310 static int tegratab_lcd_devdata_gen_remove(struct platform_device *pdev)
311 {
312         return 0;
313 }
314
315 static struct of_device_id tegratab_lcd_of_match[] = {
316         { .compatible = "lgd,tegratab", },
317         { },
318 };
319
320 static struct platform_driver tegratab_lcd_devdata_gen_drv = {
321         .probe = tegratab_lcd_devdata_gen_probe,
322         .remove = tegratab_lcd_devdata_gen_remove,
323         .driver = {
324                 .owner = THIS_MODULE,
325                 .name = "of_tegratab_lcd_devdata_generate",
326                 .of_match_table = tegratab_lcd_of_match,
327         },
328 };
329
330 int __init of_tegratab_lcd_devdata_init(void)
331 {
332         return platform_driver_register(&tegratab_lcd_devdata_gen_drv);
333 }
334
335 void __exit of_tegratab_lcd_devdata_exit(void)
336 {
337         platform_driver_unregister(&tegratab_lcd_devdata_gen_drv);
338 }
339
340 subsys_initcall(of_tegratab_lcd_devdata_init);
341 module_exit(of_tegratab_lcd_devdata_exit);
342 MODULE_DESCRIPTION("tegratab lcd devdata generate driver with device tree info");