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