ARM: DT: Add DT entry for PWMs and Backlight
[linux-3.10.git] / arch / arm / mach-tegra / panel-c-lvds-1366-14.c
1 /*
2  * arch/arm/mach-tegra/panel-c-lvds-1366-4.c
3  *
4  * Copyright (c) 2013, 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/tegra_pwm_bl.h>
23 #include <linux/regulator/consumer.h>
24 #include <linux/pwm_backlight.h>
25 #include <linux/max8831_backlight.h>
26 #include <linux/leds.h>
27 #include <linux/ioport.h>
28 #include "board.h"
29 #include "board-panel.h"
30 #include "devices.h"
31 #include "gpio-names.h"
32 #include "tegra12_host1x_devices.h"
33
34 #define DC_CTRL_MODE    TEGRA_DC_OUT_CONTINUOUS_MODE
35
36 #define LVDS_PANEL_BL_PWM       TEGRA_GPIO_PH1
37
38 static bool reg_requested;
39 static bool gpio_requested;
40 static struct platform_device *disp_device;
41
42 static struct regulator *vdd_lcd_bl;
43 static struct regulator *vdd_lcd_bl_en;
44 static struct regulator *avdd_lcd;
45 static struct regulator *vdd_ds_1v8;
46 static struct regulator *dvdd_lcd_1v8;
47
48 static tegra_dc_bl_output lvds_c_1366_14_bl_output_measured = {
49         /*  TODO: linear backlight calibration */
50         0,   1,   2,   3,   4,   5,   6,   7,
51         8,   9,  10,  11,  12,  13,  14,  15,
52         16,  17,  18,  19,  20,  21,  22,  23,
53         24,  25,  26,  27,  28,  29,  30,  31,
54         32,  33,  34,  35,  36,  37,  38,  39,
55         40,  41,  42,  43,  44,  45,  46,  47,
56         48,  49,  50,  51,  52,  53,  54,  55,
57         56,  57,  58,  59,  60,  61,  62,  63,
58         64,  65,  66,  67,  68,  69,  70,  71,
59         72,  73,  74,  75,  76,  77,  78,  79,
60         80,  81,  82,  83,  84,  85,  86,  87,
61         88,  89,  90,  91,  92,  93,  94,  95,
62         96,  97,  98,  99, 100, 101, 102, 103,
63         104, 105, 106, 107, 108, 109, 110, 111,
64         112, 113, 114, 115, 116, 117, 118, 119,
65         120, 121, 122, 123, 124, 125, 126, 127,
66         128, 129, 130, 131, 132, 133, 134, 135,
67         136, 137, 138, 139, 140, 141, 142, 143,
68         144, 145, 146, 147, 148, 149, 150, 151,
69         152, 153, 154, 155, 156, 157, 158, 159,
70         160, 161, 162, 163, 164, 165, 166, 167,
71         168, 169, 170, 171, 172, 173, 174, 175,
72         176, 177, 178, 179, 180, 181, 182, 183,
73         184, 185, 186, 187, 188, 189, 190, 191,
74         192, 193, 194, 195, 196, 197, 198, 199,
75         200, 201, 202, 203, 204, 205, 206, 207,
76         208, 209, 210, 211, 212, 213, 214, 215,
77         216, 217, 218, 219, 220, 221, 222, 223,
78         224, 225, 226, 227, 228, 229, 230, 231,
79         232, 233, 234, 235, 236, 237, 238, 239,
80         240, 241, 242, 243, 244, 245, 246, 247,
81         248, 249, 250, 251, 252, 253, 254, 255
82 };
83
84 static int laguna_lvds_regulator_get(struct device *dev)
85 {
86         int err = 0;
87
88         if (reg_requested)
89                 return 0;
90
91         vdd_ds_1v8 = regulator_get(dev, "vdd_ds_1v8");
92         if (IS_ERR_OR_NULL(vdd_ds_1v8)) {
93                 pr_err("vdd_ds_1v8 regulator get failed\n");
94                 err = PTR_ERR(vdd_ds_1v8);
95                 vdd_ds_1v8 = NULL;
96                 goto fail;
97         }
98
99         vdd_lcd_bl = regulator_get(dev, "vdd_lcd_bl");
100         if (IS_ERR_OR_NULL(vdd_lcd_bl)) {
101                 pr_err("vdd_lcd_bl regulator get failed\n");
102                 err = PTR_ERR(vdd_lcd_bl);
103                 vdd_lcd_bl = NULL;
104                 goto fail;
105         }
106
107         vdd_lcd_bl_en = regulator_get(dev, "vdd_lcd_bl_en");
108         if (IS_ERR_OR_NULL(vdd_lcd_bl_en)) {
109                 pr_err("vdd_lcd_bl_en regulator get failed\n");
110                 err = PTR_ERR(vdd_lcd_bl_en);
111                 vdd_lcd_bl_en = NULL;
112                 goto fail;
113         }
114
115         avdd_lcd = regulator_get(dev, "avdd_lcd");
116         if (IS_ERR_OR_NULL(avdd_lcd)) {
117                 pr_err("avdd_lcd regulator get failed\n");
118                 err = PTR_ERR(avdd_lcd);
119                 avdd_lcd = NULL;
120                 goto fail;
121         }
122
123         dvdd_lcd_1v8 = regulator_get(dev, "dvdd_lcd");
124         if (IS_ERR_OR_NULL(dvdd_lcd_1v8)) {
125                 pr_err("dvdd_lcd regulator get failed\n");
126                 err = PTR_ERR(dvdd_lcd_1v8);
127                 dvdd_lcd_1v8 = NULL;
128                 goto fail;
129         }
130
131         reg_requested = true;
132         return 0;
133 fail:
134         return err;
135 }
136
137 static int laguna_lvds_gpio_get(void)
138 {
139         int err = 0;
140
141         if (gpio_requested)
142                 return 0;
143
144         err = gpio_request(LVDS_PANEL_BL_PWM, "panel pwm");
145         if (err < 0) {
146                 pr_err("panel pwm gpio request failed\n");
147                 goto fail;
148         }
149         gpio_free(LVDS_PANEL_BL_PWM);
150
151         gpio_requested = true;
152         return 0;
153 fail:
154         return err;
155 }
156
157 static int lvds_c_1366_14_enable(struct device *dev)
158 {
159         int err = 0;
160
161         err = laguna_lvds_regulator_get(dev);
162         if (err < 0) {
163                 pr_err("lvds regulator get failed\n");
164                 goto fail;
165         }
166
167         err = laguna_lvds_gpio_get();
168         if (err < 0) {
169                 pr_err("lvds gpio request failed\n");
170                 goto fail;
171         }
172
173         if (vdd_lcd_bl) {
174                 err = regulator_enable(vdd_lcd_bl);
175                 if (err < 0) {
176                         pr_err("vdd_lcd_bl regulator enable failed\n");
177                         goto fail;
178                 }
179         }
180
181         msleep(20);
182
183         if (vdd_ds_1v8) {
184                 err = regulator_enable(vdd_ds_1v8);
185                 if (err < 0) {
186                         pr_err("vdd_ds_1v8 regulator enable failed\n");
187                         goto fail;
188                 }
189         }
190
191         if (avdd_lcd) {
192                 err = regulator_enable(avdd_lcd);
193                 if (err < 0) {
194                         pr_err("avdd_lcd regulator enable failed\n");
195                         goto fail;
196                 }
197         }
198
199         msleep(10);
200
201         if (vdd_lcd_bl_en) {
202                 err = regulator_enable(vdd_lcd_bl_en);
203                 if (err < 0) {
204                         pr_err("vdd_lcd_bl_en regulator enable failed\n");
205                         goto fail;
206                 }
207         }
208
209         if (dvdd_lcd_1v8) {
210                 err = regulator_enable(dvdd_lcd_1v8);
211                 if (err < 0) {
212                         pr_err("dvdd_lcd_1v8 regulator enable failed\n");
213                         goto fail;
214                 }
215         }
216
217         return 0;
218 fail:
219         return err;
220 }
221
222 static int lvds_c_1366_14_disable(void)
223 {
224         if (vdd_lcd_bl_en)
225                 regulator_disable(vdd_lcd_bl_en);
226
227         msleep(10);
228
229         if (avdd_lcd)
230                 regulator_disable(avdd_lcd);
231
232         if (vdd_ds_1v8)
233                 regulator_disable(vdd_ds_1v8);
234
235         msleep(10);
236
237         if (vdd_lcd_bl)
238                 regulator_disable(vdd_lcd_bl);
239
240         msleep(500);
241
242         return 0;
243 }
244
245 static int lvds_c_1366_14_postsuspend(void)
246 {
247         return 0;
248 }
249
250 static struct tegra_dc_out_pin lvds_out_pins[] = {
251         {
252                 .name   = TEGRA_DC_OUT_PIN_H_SYNC,
253                 .pol    = TEGRA_DC_OUT_PIN_POL_LOW,
254         },
255         {
256                 .name   = TEGRA_DC_OUT_PIN_V_SYNC,
257                 .pol    = TEGRA_DC_OUT_PIN_POL_LOW,
258         },
259         {
260                 .name   = TEGRA_DC_OUT_PIN_PIXEL_CLOCK,
261                 .pol    = TEGRA_DC_OUT_PIN_POL_LOW,
262         },
263         {
264                 .name   = TEGRA_DC_OUT_PIN_DATA_ENABLE,
265                 .pol    = TEGRA_DC_OUT_PIN_POL_HIGH,
266         },
267 };
268
269 static struct tegra_dc_mode lvds_c_1366_14_modes[] = {
270         {
271                 .pclk = 74720100, /* 1366 x 768 @ 60hz */
272                 .h_ref_to_sync = 1,
273                 .v_ref_to_sync = 1,
274                 .h_sync_width = 45,
275                 .v_sync_width = 7,
276                 .h_back_porch = 113,
277                 .v_back_porch = 21,
278                 .h_active = 1366,
279                 .v_active = 768,
280                 .h_front_porch = 68,
281                 .v_front_porch = 4,
282         },
283 };
284
285 static int lvds_c_1366_14_bl_notify(struct device *unused, int brightness)
286 {
287         int cur_sd_brightness = atomic_read(&sd_brightness);
288
289         /* SD brightness is a percentage */
290         brightness = (brightness * cur_sd_brightness) / 255;
291
292         /* Apply any backlight response curve */
293         if (brightness > 255)
294                 pr_info("Error: Brightness > 255!\n");
295         else
296                 brightness = lvds_c_1366_14_bl_output_measured[brightness];
297
298         return brightness;
299 }
300
301 static int lvds_c_1366_14_check_fb(struct device *dev, struct fb_info *info)
302 {
303         return info->device == &disp_device->dev;
304 }
305
306 static struct platform_pwm_backlight_data lvds_c_1366_14_bl_data = {
307         .pwm_id         = 1,
308         .max_brightness = 255,
309         .dft_brightness = 224,
310         .pwm_period_ns  = 1000000,
311         .pwm_gpio       = TEGRA_GPIO_INVALID,
312         .notify         = lvds_c_1366_14_bl_notify,
313         /* Only toggle backlight on fb blank notifications for disp1 */
314         .check_fb       = lvds_c_1366_14_check_fb,
315 };
316
317 static struct platform_device __maybe_unused
318                 lvds_c_1366_14_bl_device = {
319         .name   = "pwm-backlight",
320         .id     = -1,
321         .dev    = {
322                 .platform_data = &lvds_c_1366_14_bl_data,
323         },
324 };
325
326 static struct platform_device __maybe_unused
327                         *lvds_c_1366_14_bl_devices[] __initdata = {
328         &tegra_pwfm_device,
329         &lvds_c_1366_14_bl_device,
330 };
331
332 static int  __init __lvds_c_1366_14_register_bl_dev(void)
333 {
334         int err = 0;
335         err = platform_add_devices(lvds_c_1366_14_bl_devices,
336                                 ARRAY_SIZE(lvds_c_1366_14_bl_devices));
337         if (err) {
338                 pr_err("disp1 bl device registration failed");
339                 return err;
340         }
341         return err;
342 }
343
344 static int  __init lvds_c_1366_14_register_bl_dev(void)
345 {
346         int err = 0;
347         if (!of_have_populated_dt())
348                 err = __lvds_c_1366_14_register_bl_dev();
349         return 0;
350 }
351
352 static void lvds_c_1366_14_set_disp_device(
353         struct platform_device *laguna_display_device)
354 {
355         disp_device = laguna_display_device;
356 }
357
358 static void lvds_c_1366_14_dc_out_init(struct tegra_dc_out *dc)
359 {
360         dc->align = TEGRA_DC_ALIGN_MSB,
361         dc->order = TEGRA_DC_ORDER_RED_BLUE,
362         dc->flags = DC_CTRL_MODE;
363         dc->modes = lvds_c_1366_14_modes;
364         dc->n_modes = ARRAY_SIZE(lvds_c_1366_14_modes);
365         dc->out_pins = lvds_out_pins,
366         dc->n_out_pins = ARRAY_SIZE(lvds_out_pins),
367         dc->depth = 18,
368         dc->parent_clk = "pll_d_out0";
369         dc->enable = lvds_c_1366_14_enable;
370         dc->disable = lvds_c_1366_14_disable;
371         dc->postsuspend = lvds_c_1366_14_postsuspend,
372         dc->width = 309;
373         dc->height = 174;
374 }
375
376 static void lvds_c_1366_14_fb_data_init(struct tegra_fb_data *fb)
377 {
378         fb->xres = lvds_c_1366_14_modes[0].h_active;
379         fb->yres = lvds_c_1366_14_modes[0].v_active;
380 }
381
382 static void
383 lvds_c_1366_14_sd_settings_init(struct tegra_dc_sd_settings *settings)
384 {
385         settings->bl_device_name = "pwm-backlight";
386 }
387
388 struct tegra_panel __initdata lvds_c_1366_14 = {
389         .init_sd_settings = lvds_c_1366_14_sd_settings_init,
390         .init_dc_out = lvds_c_1366_14_dc_out_init,
391         .init_fb_data = lvds_c_1366_14_fb_data_init,
392         .register_bl_dev = lvds_c_1366_14_register_bl_dev,
393         .set_disp_device = lvds_c_1366_14_set_disp_device,
394 };
395 EXPORT_SYMBOL(lvds_c_1366_14);
396