464479e493aae1090825a40a8c97571be29d9608
[linux-2.6.git] / arch / arm / mach-tegra / board-whistler-panel.c
1 /*
2  * arch/arm/mach-tegra/board-whistler-panel.c
3  *
4  * Copyright (c) 2010-2012, NVIDIA Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20
21 #include <linux/delay.h>
22 #include <linux/gpio.h>
23 #include <linux/regulator/consumer.h>
24 #include <linux/resource.h>
25 #include <asm/mach-types.h>
26 #include <linux/platform_device.h>
27 #ifdef CONFIG_HAS_EARLYSUSPEND
28 #include <linux/earlysuspend.h>
29 #endif
30 #include <linux/kernel.h>
31 #include <linux/pwm_backlight.h>
32 #include <linux/tegra_pwm_bl.h>
33 #include <linux/nvhost.h>
34 #include <linux/nvmap.h>
35 #include <mach/irqs.h>
36 #include <mach/iomap.h>
37 #include <mach/dc.h>
38 #include <mach/fb.h>
39 #include <mach/gpio-tegra.h>
40
41 #include "devices.h"
42 #include "gpio-names.h"
43 #include "board.h"
44
45 #define whistler_hdmi_hpd       TEGRA_GPIO_PN7
46
47 #ifdef CONFIG_TEGRA_DC
48 static struct regulator *whistler_hdmi_reg = NULL;
49 static struct regulator *whistler_hdmi_pll = NULL;
50 #endif
51
52 /*
53  * In case which_pwm is TEGRA_PWM_PM0,
54  * gpio_conf_to_sfio should be TEGRA_GPIO_PW0: set LCD_CS1_N pin to SFIO
55  * In case which_pwm is TEGRA_PWM_PM1,
56  * gpio_conf_to_sfio should be TEGRA_GPIO_PW1: set LCD_M1 pin to SFIO
57  */
58 static struct platform_tegra_pwm_backlight_data whistler_disp1_backlight_data = {
59         .which_dc = 0,
60         .which_pwm = TEGRA_PWM_PM1,
61         .max_brightness = 256,
62         .dft_brightness = 77,
63         .gpio_conf_to_sfio      = TEGRA_GPIO_PW1,
64         .switch_to_sfio         = &tegra_gpio_disable,
65         .period = 0x1F,
66         .clk_div = 3,
67         .clk_select = 2,
68 };
69
70 static struct platform_device whistler_disp1_backlight_device = {
71         .name   = "tegra-pwm-bl",
72         .id     = -1,
73         .dev    = {
74                 .platform_data = &whistler_disp1_backlight_data,
75         },
76 };
77
78 #ifdef CONFIG_TEGRA_DC
79 static int whistler_hdmi_enable(void)
80 {
81         if (!whistler_hdmi_reg) {
82                 whistler_hdmi_reg = regulator_get(NULL, "avdd_hdmi"); /* LD011 */
83                 if (IS_ERR_OR_NULL(whistler_hdmi_reg)) {
84                         pr_err("hdmi: couldn't get regulator avdd_hdmi\n");
85                         whistler_hdmi_reg = NULL;
86                         return PTR_ERR(whistler_hdmi_reg);
87                 }
88         }
89         regulator_enable(whistler_hdmi_reg);
90
91         if (!whistler_hdmi_pll) {
92                 whistler_hdmi_pll = regulator_get(NULL, "avdd_hdmi_pll"); /* LD06 */
93                 if (IS_ERR_OR_NULL(whistler_hdmi_pll)) {
94                         pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n");
95                         whistler_hdmi_pll = NULL;
96                         regulator_disable(whistler_hdmi_reg);
97                         whistler_hdmi_reg = NULL;
98                         return PTR_ERR(whistler_hdmi_pll);
99                 }
100         }
101         regulator_enable(whistler_hdmi_pll);
102         return 0;
103 }
104
105 static int whistler_hdmi_disable(void)
106 {
107         regulator_disable(whistler_hdmi_reg);
108         regulator_disable(whistler_hdmi_pll);
109         return 0;
110 }
111
112 static struct resource whistler_disp1_resources[] = {
113         {
114                 .name   = "irq",
115                 .start  = INT_DISPLAY_GENERAL,
116                 .end    = INT_DISPLAY_GENERAL,
117                 .flags  = IORESOURCE_IRQ,
118         },
119         {
120                 .name   = "regs",
121                 .start  = TEGRA_DISPLAY_BASE,
122                 .end    = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1,
123                 .flags  = IORESOURCE_MEM,
124         },
125         {
126                 .name   = "fbmem",
127                 .flags  = IORESOURCE_MEM,
128         },
129 };
130
131 static struct resource whistler_disp2_resources[] = {
132         {
133                 .name   = "irq",
134                 .start  = INT_DISPLAY_B_GENERAL,
135                 .end    = INT_DISPLAY_B_GENERAL,
136                 .flags  = IORESOURCE_IRQ,
137         },
138         {
139                 .name   = "regs",
140                 .start  = TEGRA_DISPLAY2_BASE,
141                 .end    = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
142                 .flags  = IORESOURCE_MEM,
143         },
144         {
145                 .name   = "fbmem",
146                 .flags  = IORESOURCE_MEM,
147         },
148         {
149                 .name   = "hdmi_regs",
150                 .start  = TEGRA_HDMI_BASE,
151                 .end    = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
152                 .flags  = IORESOURCE_MEM,
153         },
154 };
155
156 static struct tegra_dc_mode whistler_panel_modes[] = {
157         {
158                 .pclk = 27000000,
159                 .h_ref_to_sync = 4,
160                 .v_ref_to_sync = 2,
161                 .h_sync_width = 10,
162                 .v_sync_width = 3,
163                 .h_back_porch = 20,
164                 .v_back_porch = 3,
165                 .h_active = 800,
166                 .v_active = 480,
167                 .h_front_porch = 70,
168                 .v_front_porch = 3,
169         },
170 };
171
172 static struct tegra_dc_out_pin whistler_dc_out_pins[] = {
173         {
174                 .name   = TEGRA_DC_OUT_PIN_H_SYNC,
175                 .pol    = TEGRA_DC_OUT_PIN_POL_LOW,
176         },
177         {
178                 .name   = TEGRA_DC_OUT_PIN_V_SYNC,
179                 .pol    = TEGRA_DC_OUT_PIN_POL_LOW,
180         },
181         {
182                 .name   = TEGRA_DC_OUT_PIN_PIXEL_CLOCK,
183                 .pol    = TEGRA_DC_OUT_PIN_POL_LOW,
184         },
185 };
186
187 static u8 whistler_dc_out_pin_sel_config[] = {
188         TEGRA_PIN_OUT_CONFIG_SEL_LM1_PM1,
189 };
190
191 static struct tegra_dc_out whistler_disp1_out = {
192         .type           = TEGRA_DC_OUT_RGB,
193
194         .align          = TEGRA_DC_ALIGN_MSB,
195         .order          = TEGRA_DC_ORDER_RED_BLUE,
196
197         .height         = 54, /* mm */
198         .width          = 90, /* mm */
199
200         .modes          = whistler_panel_modes,
201         .n_modes        = ARRAY_SIZE(whistler_panel_modes),
202
203         .out_pins       = whistler_dc_out_pins,
204         .n_out_pins     = ARRAY_SIZE(whistler_dc_out_pins),
205
206         .out_sel_configs   = whistler_dc_out_pin_sel_config,
207         .n_out_sel_configs = ARRAY_SIZE(whistler_dc_out_pin_sel_config),
208 };
209
210 static struct tegra_dc_out whistler_disp2_out = {
211         .type           = TEGRA_DC_OUT_HDMI,
212         .flags          = TEGRA_DC_OUT_HOTPLUG_HIGH,
213
214         .dcc_bus        = 1,
215         .hotplug_gpio   = whistler_hdmi_hpd,
216
217         .max_pixclock   = KHZ2PICOS(148500),
218
219         .align          = TEGRA_DC_ALIGN_MSB,
220         .order          = TEGRA_DC_ORDER_RED_BLUE,
221
222         .enable         = whistler_hdmi_enable,
223         .disable        = whistler_hdmi_disable,
224 };
225
226 static struct tegra_fb_data whistler_fb_data = {
227         .win            = 0,
228         .xres           = 800,
229         .yres           = 480,
230         .bits_per_pixel = 32,
231         .flags          = TEGRA_FB_FLIP_ON_PROBE,
232 };
233
234 static struct tegra_fb_data whistler_hdmi_fb_data = {
235         .win            = 0,
236         .xres           = 800,
237         .yres           = 480,
238         .bits_per_pixel = 32,
239         .flags          = TEGRA_FB_FLIP_ON_PROBE,
240 };
241
242
243 static struct tegra_dc_platform_data whistler_disp1_pdata = {
244         .flags          = TEGRA_DC_FLAG_ENABLED,
245         .default_out    = &whistler_disp1_out,
246         .fb             = &whistler_fb_data,
247 };
248
249 static struct nvhost_device whistler_disp1_device = {
250         .name           = "tegradc",
251         .id             = 0,
252         .resource       = whistler_disp1_resources,
253         .num_resources  = ARRAY_SIZE(whistler_disp1_resources),
254         .dev = {
255                 .platform_data = &whistler_disp1_pdata,
256         },
257 };
258
259 static struct tegra_dc_platform_data whistler_disp2_pdata = {
260         .flags          = 0,
261         .default_out    = &whistler_disp2_out,
262         .fb             = &whistler_hdmi_fb_data,
263 };
264
265 static struct nvhost_device whistler_disp2_device = {
266         .name           = "tegradc",
267         .id             = 1,
268         .resource       = whistler_disp2_resources,
269         .num_resources  = ARRAY_SIZE(whistler_disp2_resources),
270         .dev = {
271                 .platform_data = &whistler_disp2_pdata,
272         },
273 };
274 #endif
275
276 #if defined(CONFIG_TEGRA_NVMAP)
277 static struct nvmap_platform_carveout whistler_carveouts[] = {
278         [0] = NVMAP_HEAP_CARVEOUT_IRAM_INIT,
279         [1] = {
280                 .name           = "generic-0",
281                 .usage_mask     = NVMAP_HEAP_CARVEOUT_GENERIC,
282                 .base           = 0x18C00000,
283                 .size           = SZ_128M - 0xC00000,
284                 .buddy_size     = SZ_32K,
285         },
286 };
287
288 static struct nvmap_platform_data whistler_nvmap_data = {
289         .carveouts      = whistler_carveouts,
290         .nr_carveouts   = ARRAY_SIZE(whistler_carveouts),
291 };
292
293 static struct platform_device whistler_nvmap_device = {
294         .name   = "tegra-nvmap",
295         .id     = -1,
296         .dev    = {
297                 .platform_data = &whistler_nvmap_data,
298         },
299 };
300 #endif
301
302 static struct platform_device *whistler_gfx_devices[] __initdata = {
303 #if defined(CONFIG_TEGRA_NVMAP)
304         &whistler_nvmap_device,
305 #endif
306         &whistler_disp1_backlight_device,
307 };
308
309 #ifdef CONFIG_HAS_EARLYSUSPEND
310 /* put early_suspend/late_resume handlers here for the display in order
311  * to keep the code out of the display driver, keeping it closer to upstream
312  */
313 struct early_suspend whistler_panel_early_suspender;
314
315 static void whistler_panel_early_suspend(struct early_suspend *h)
316 {
317         /* power down LCD, add use a blank screen for HDMI */
318         if (num_registered_fb > 0)
319                 fb_blank(registered_fb[0], FB_BLANK_POWERDOWN);
320         if (num_registered_fb > 1)
321                 fb_blank(registered_fb[1], FB_BLANK_NORMAL);
322
323 #ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
324         cpufreq_store_default_gov();
325         if (cpufreq_change_gov(cpufreq_conservative_gov))
326                 pr_err("Early_suspend: Error changing governor to %s\n",
327                                 cpufreq_conservative_gov);
328 #endif
329 }
330
331 static void whistler_panel_late_resume(struct early_suspend *h)
332 {
333         unsigned i;
334
335 #ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND
336         if (cpufreq_restore_default_gov())
337                 pr_err("Early_suspend: Unable to restore governor\n");
338 #endif
339
340         for (i = 0; i < num_registered_fb; i++)
341                 fb_blank(registered_fb[i], FB_BLANK_UNBLANK);
342 }
343 #endif
344
345 int __init whistler_panel_init(void)
346 {
347         int err;
348         struct resource __maybe_unused *res;
349
350         tegra_gpio_enable(whistler_hdmi_hpd);
351         gpio_request(whistler_hdmi_hpd, "hdmi_hpd");
352         gpio_direction_input(whistler_hdmi_hpd);
353
354 #ifdef CONFIG_HAS_EARLYSUSPEND
355         whistler_panel_early_suspender.suspend = whistler_panel_early_suspend;
356         whistler_panel_early_suspender.resume = whistler_panel_late_resume;
357         whistler_panel_early_suspender.level = EARLY_SUSPEND_LEVEL_DISABLE_FB;
358         register_early_suspend(&whistler_panel_early_suspender);
359 #endif
360
361 #if defined(CONFIG_TEGRA_NVMAP)
362         whistler_carveouts[1].base = tegra_carveout_start;
363         whistler_carveouts[1].size = tegra_carveout_size;
364 #endif
365
366 #ifdef CONFIG_TEGRA_GRHOST
367         err = nvhost_device_register(&tegra_grhost_device);
368         if (err)
369                 return err;
370 #endif
371
372         err = platform_add_devices(whistler_gfx_devices,
373                                    ARRAY_SIZE(whistler_gfx_devices));
374
375 #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
376         res = nvhost_get_resource_byname(&whistler_disp1_device,
377                                          IORESOURCE_MEM, "fbmem");
378         res->start = tegra_fb_start;
379         res->end = tegra_fb_start + tegra_fb_size - 1;
380 #endif
381
382         /* Copy the bootloader fb to the fb. */
383         tegra_move_framebuffer(tegra_fb_start, tegra_bootloader_fb_start,
384                 min(tegra_fb_size, tegra_bootloader_fb_size));
385
386 #if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC)
387         res = nvhost_get_resource_byname(&whistler_disp2_device,
388                                          IORESOURCE_MEM, "fbmem");
389         res->start = tegra_fb2_start;
390         res->end = tegra_fb2_start + tegra_fb2_size - 1;
391
392         if (!err)
393                 err = nvhost_device_register(&whistler_disp1_device);
394
395         if (!err)
396                 err = nvhost_device_register(&whistler_disp2_device);
397 #endif
398
399         return err;
400 }
401