kernel: port brightness settings from rel-st8-l
[linux-3.10.git] / arch / arm / mach-tegra / panel-a-1200-1920-8-0.c
1 /*
2  * arch/arm/mach-tegra/panel-a-1200-1920-8-0.c
3  *
4  * Copyright (c) 2013-2015, NVIDIA CORPORATION.  All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <mach/dc.h>
20 #include <linux/delay.h>
21 #include <linux/gpio.h>
22 #include <linux/regulator/consumer.h>
23 #include "board.h"
24 #include "board-panel.h"
25 #include "devices.h"
26
27 #define DSI_PANEL_RESET         1
28
29 static bool reg_requested;
30 static struct regulator *avdd_lcd_3v3;
31 static struct regulator *vdd_lcd_bl_en;
32 static struct regulator *dvdd_lcd_1v8;
33 static struct device *dc_dev;
34 static u16 en_panel_rst;
35
36 static int dsi_a_1200_1920_8_0_regulator_get(struct device *dev)
37 {
38         int err = 0;
39
40         if (reg_requested)
41                 return 0;
42
43         avdd_lcd_3v3 = regulator_get(dev, "avdd_lcd");
44         if (IS_ERR_OR_NULL(avdd_lcd_3v3)) {
45                 pr_err("avdd_lcd regulator get failed\n");
46                 err = PTR_ERR(avdd_lcd_3v3);
47                 avdd_lcd_3v3 = NULL;
48                 goto fail;
49         }
50
51         dvdd_lcd_1v8 = regulator_get(dev, "dvdd_lcd");
52         if (IS_ERR_OR_NULL(dvdd_lcd_1v8)) {
53                 pr_err("dvdd_lcd_1v8 regulator get failed\n");
54                 err = PTR_ERR(dvdd_lcd_1v8);
55                 dvdd_lcd_1v8 = NULL;
56                 goto fail;
57         }
58
59         vdd_lcd_bl_en = regulator_get(dev, "vdd_lcd_bl_en");
60         if (IS_ERR_OR_NULL(vdd_lcd_bl_en)) {
61                 err = PTR_ERR(vdd_lcd_bl_en);
62                 pr_warn("warning: vdd_lcd_bl_en regulator get failed, err = %d\n", err);
63                 vdd_lcd_bl_en = NULL;
64         }
65
66         reg_requested = true;
67         return 0;
68 fail:
69         return err;
70 }
71
72 static int dsi_a_1200_1920_8_0_enable(struct device *dev)
73 {
74         int err = 0;
75
76         err = dsi_a_1200_1920_8_0_regulator_get(dev);
77         if (err < 0) {
78                 pr_err("dsi regulator get failed\n");
79                 goto fail;
80         }
81
82         err = tegra_panel_gpio_get_dt("a,wuxga-8-0", &panel_of);
83         if (err < 0) {
84                 pr_err("dsi gpio request failed\n");
85                 goto fail;
86         }
87
88         /* If panel rst gpio is specified in device tree,
89          * use that
90          */
91         if (gpio_is_valid(panel_of.panel_gpio[TEGRA_GPIO_RESET]))
92                 en_panel_rst = panel_of.panel_gpio[TEGRA_GPIO_RESET];
93
94         if (avdd_lcd_3v3) {
95                 err = regulator_enable(avdd_lcd_3v3);
96                 if (err < 0) {
97                         pr_err("avdd_lcd regulator enable failed\n");
98                         goto fail;
99                 }
100         }
101
102         if (dvdd_lcd_1v8) {
103                 err = regulator_enable(dvdd_lcd_1v8);
104                 if (err < 0) {
105                         pr_err("dvdd_lcd regulator enable failed\n");
106                         goto fail;
107                 }
108         }
109
110         if (vdd_lcd_bl_en) {
111                 err = regulator_enable(vdd_lcd_bl_en);
112                 if (err < 0) {
113                         pr_err("vdd_lcd_bl_en regulator enable failed\n");
114                         goto fail;
115                 }
116         }
117
118         msleep(20);
119 #if DSI_PANEL_RESET
120         if (!tegra_dc_initialized(dev)) {
121                 gpio_direction_output(en_panel_rst, 1);
122                 usleep_range(1000, 5000);
123                 gpio_set_value(en_panel_rst, 0);
124                 usleep_range(1000, 5000);
125                 gpio_set_value(en_panel_rst, 1);
126                 msleep(20);
127         }
128 #endif
129         dc_dev = dev;
130         return 0;
131 fail:
132         return err;
133 }
134
135 static int dsi_a_1200_1920_8_0_disable(struct device *dev)
136 {
137         if (gpio_is_valid(en_panel_rst)) {
138                 /* Wait for 50ms before triggering panel reset */
139                 msleep(50);
140                 gpio_set_value(en_panel_rst, 0);
141         }
142
143         if (vdd_lcd_bl_en)
144                 regulator_disable(vdd_lcd_bl_en);
145
146         if (avdd_lcd_3v3)
147                 regulator_disable(avdd_lcd_3v3);
148
149         if (dvdd_lcd_1v8)
150                 regulator_disable(dvdd_lcd_1v8);
151
152         dc_dev = NULL;
153         return 0;
154 }
155
156 static int dsi_a_1200_1920_8_0_postsuspend(void)
157 {
158         return 0;
159 }
160
161 static int dsi_a_1200_1920_8_0_bl_notify(struct device *dev, int brightness)
162 {
163         int cur_sd_brightness;
164         struct backlight_device *bl = NULL;
165         struct pwm_bl_data *pb = NULL;
166         bl = (struct backlight_device *)dev_get_drvdata(dev);
167         pb = (struct pwm_bl_data *)dev_get_drvdata(&bl->dev);
168
169         /* apply the non-linear curve adjustment */
170         if (brightness > 255)
171                 pr_info("Error: Brightness > 255!\n");
172         else if (pb->bl_nonlinear)
173                 brightness = pb->bl_nonlinear[brightness];
174
175         if (dc_dev)
176                 nvsd_check_prism_thresh(dc_dev, brightness);
177
178         cur_sd_brightness = atomic_read(&sd_brightness);
179         /* SD brightness is a percentage */
180         brightness = (brightness * cur_sd_brightness) / 255;
181
182         /* Apply any backlight response curve */
183         if (brightness > 255)
184                 pr_info("Error: Brightness > 255!\n");
185         else if (pb->bl_measured)
186                 brightness = pb->bl_measured[brightness];
187
188         return brightness;
189 }
190
191 static int dsi_a_1200_1920_8_0_check_fb(struct device *dev,
192         struct fb_info *info)
193 {
194         struct platform_device *pdev = NULL;
195         pdev = to_platform_device(bus_find_device_by_name(
196                 &platform_bus_type, NULL, "tegradc.0"));
197         return info->device == &pdev->dev;
198 }
199
200 static struct pwm_bl_data_dt_ops dsi_a_1200_1920_8_0_pwm_bl_ops = {
201         .notify = dsi_a_1200_1920_8_0_bl_notify,
202         .check_fb = dsi_a_1200_1920_8_0_check_fb,
203         .blnode_compatible = "a,wuxga-8-0-bl",
204 };
205 struct tegra_panel_ops dsi_a_1200_1920_8_0_ops = {
206         .enable = dsi_a_1200_1920_8_0_enable,
207         .disable = dsi_a_1200_1920_8_0_disable,
208         .postsuspend = dsi_a_1200_1920_8_0_postsuspend,
209         .pwm_bl_ops = &dsi_a_1200_1920_8_0_pwm_bl_ops,
210 };