5806fada15a4e5e8108e1310097424eabef152d7
[linux-2.6.git] / arch / arm / mach-tegra / board-cardhu-panel.c
1 /*
2  * arch/arm/mach-tegra/board-cardhu-panel.c
3  *
4  * Copyright (c) 2010, 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/pwm_backlight.h>
28 #include <mach/nvhost.h>
29 #include <mach/nvmap.h>
30 #include <mach/irqs.h>
31 #include <mach/iomap.h>
32 #include <mach/dc.h>
33 #include <mach/fb.h>
34
35 #include "board.h"
36 #include "devices.h"
37 #include "gpio-names.h"
38
39 #define cardhu_lvds_shutdown    TEGRA_GPIO_PL2
40 #define cardhu_bl_enb           TEGRA_GPIO_PH2
41 #define cardhu_hdmi_hpd         TEGRA_GPIO_PN7
42
43 static struct regulator *cardhu_hdmi_reg = NULL;
44 static struct regulator *cardhu_hdmi_pll = NULL;
45 static struct regulator *cardhu_hdmi_vddio = NULL;
46
47 static int cardhu_backlight_init(struct device *dev) {
48         int ret;
49
50         ret = gpio_request(cardhu_bl_enb, "backlight_enb");
51         if (ret < 0)
52                 return ret;
53
54         ret = gpio_direction_output(cardhu_bl_enb, 1);
55         if (ret < 0)
56                 gpio_free(cardhu_bl_enb);
57         else
58                 tegra_gpio_enable(cardhu_bl_enb);
59
60         return ret;
61 };
62
63 static void cardhu_backlight_exit(struct device *dev) {
64         gpio_set_value(cardhu_bl_enb, 0);
65         gpio_free(cardhu_bl_enb);
66         tegra_gpio_disable(cardhu_bl_enb);
67 }
68
69 static int cardhu_backlight_notify(struct device *unused, int brightness)
70 {
71         gpio_set_value(cardhu_bl_enb, !!brightness);
72         return brightness;
73 }
74
75 static struct platform_pwm_backlight_data cardhu_backlight_data = {
76         .pwm_id         = 0,
77         .max_brightness = 255,
78         .dft_brightness = 224,
79         .pwm_period_ns  = 5000000,
80         .init           = cardhu_backlight_init,
81         .exit           = cardhu_backlight_exit,
82         .notify         = cardhu_backlight_notify,
83 };
84
85 static struct platform_device cardhu_backlight_device = {
86         .name   = "pwm-backlight",
87         .id     = -1,
88         .dev    = {
89                 .platform_data = &cardhu_backlight_data,
90         },
91 };
92
93 static int cardhu_panel_enable(void)
94 {
95         static struct regulator *reg = NULL;
96
97         if (reg == NULL) {
98                 reg = regulator_get(NULL, "avdd_lvds");
99                 if (WARN_ON(IS_ERR(reg)))
100                         pr_err("%s: couldn't get regulator avdd_lvds: %ld\n",
101                                __func__, PTR_ERR(reg));
102                 else
103                         regulator_enable(reg);
104         }
105
106         gpio_set_value(cardhu_lvds_shutdown, 1);
107         return 0;
108 }
109
110 static int cardhu_panel_disable(void)
111 {
112         gpio_set_value(cardhu_lvds_shutdown, 0);
113         return 0;
114 }
115
116 static int cardhu_hdmi_enable(void)
117 {
118         int ret;
119         if (!cardhu_hdmi_reg) {
120                 cardhu_hdmi_reg = regulator_get(NULL, "avdd_hdmi");
121                 if (IS_ERR_OR_NULL(cardhu_hdmi_reg)) {
122                         pr_err("hdmi: couldn't get regulator avdd_hdmi\n");
123                         cardhu_hdmi_reg = NULL;
124                         return PTR_ERR(cardhu_hdmi_reg);
125                 }
126         }
127         ret = regulator_enable(cardhu_hdmi_reg);
128         if (ret < 0) {
129                 pr_err("hdmi: couldn't enable regulator avdd_hdmi\n");
130                 return ret;
131         }
132         if (!cardhu_hdmi_pll) {
133                 cardhu_hdmi_pll = regulator_get(NULL, "avdd_hdmi_pll");
134                 if (IS_ERR_OR_NULL(cardhu_hdmi_pll)) {
135                         pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n");
136                         cardhu_hdmi_pll = NULL;
137                         regulator_put(cardhu_hdmi_reg);
138                         cardhu_hdmi_reg = NULL;
139                         return PTR_ERR(cardhu_hdmi_pll);
140                 }
141         }
142         ret = regulator_enable(cardhu_hdmi_pll);
143         if (ret < 0) {
144                 pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n");
145                 return ret;
146         }
147         if (!cardhu_hdmi_vddio) {
148                 cardhu_hdmi_vddio = regulator_get(NULL, "vdd_hdmi_con");
149                 if (IS_ERR_OR_NULL(cardhu_hdmi_vddio)) {
150                         pr_err("hdmi: couldn't get regulator vdd_hdmi_con\n");
151                         cardhu_hdmi_vddio = NULL;
152                         regulator_put(cardhu_hdmi_pll);
153                         cardhu_hdmi_pll = NULL;
154                         regulator_put(cardhu_hdmi_reg);
155                         cardhu_hdmi_reg = NULL;
156
157                         return PTR_ERR(cardhu_hdmi_vddio);
158                 }
159         }
160         ret = regulator_enable(cardhu_hdmi_vddio);
161         if (ret < 0) {
162                 pr_err("hdmi: couldn't enable regulator vdd_hdmi_con\n");
163                 return ret;
164         }
165         return 0;
166 }
167
168 static int cardhu_hdmi_disable(void)
169 {
170
171         regulator_disable(cardhu_hdmi_reg);
172         regulator_put(cardhu_hdmi_reg);
173         cardhu_hdmi_reg = NULL;
174
175         regulator_disable(cardhu_hdmi_pll);
176         regulator_put(cardhu_hdmi_pll);
177         cardhu_hdmi_pll = NULL;
178
179         regulator_disable(cardhu_hdmi_vddio);
180         regulator_put(cardhu_hdmi_vddio);
181         cardhu_hdmi_vddio = NULL;
182         return 0;
183 }
184 static struct resource cardhu_disp1_resources[] = {
185         {
186                 .name   = "irq",
187                 .start  = INT_DISPLAY_GENERAL,
188                 .end    = INT_DISPLAY_GENERAL,
189                 .flags  = IORESOURCE_IRQ,
190         },
191         {
192                 .name   = "regs",
193                 .start  = TEGRA_DISPLAY_BASE,
194                 .end    = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1,
195                 .flags  = IORESOURCE_MEM,
196         },
197         {
198                 .name   = "fbmem",
199                 .start  = 0,    /* Filled in by cardhu_panel_init() */
200                 .end    = 0,    /* Filled in by cardhu_panel_init() */
201                 .flags  = IORESOURCE_MEM,
202         },
203 };
204
205 static struct resource cardhu_disp2_resources[] = {
206         {
207                 .name   = "irq",
208                 .start  = INT_DISPLAY_B_GENERAL,
209                 .end    = INT_DISPLAY_B_GENERAL,
210                 .flags  = IORESOURCE_IRQ,
211         },
212         {
213                 .name   = "regs",
214                 .start  = TEGRA_DISPLAY2_BASE,
215                 .end    = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
216                 .flags  = IORESOURCE_MEM,
217         },
218         {
219                 .name   = "fbmem",
220                 .flags  = IORESOURCE_MEM,
221                 .start  = 0,
222                 .end    = 0,
223         },
224         {
225                 .name   = "hdmi_regs",
226                 .start  = TEGRA_HDMI_BASE,
227                 .end    = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
228                 .flags  = IORESOURCE_MEM,
229         },
230 };
231
232 static struct tegra_dc_mode cardhu_panel_modes[] = {
233         {
234                 /* 1366x768@62.3Hz */
235                 .pclk = 72000000,
236                 .h_ref_to_sync = 4,
237                 .v_ref_to_sync = 2,
238                 .h_sync_width = 32,
239                 .v_sync_width = 5,
240                 .h_back_porch = 20,
241                 .v_back_porch = 12,
242                 .h_active = 1366,
243                 .v_active = 768,
244                 .h_front_porch = 48,
245                 .v_front_porch = 3,
246         },
247 };
248
249 static struct tegra_fb_data cardhu_fb_data = {
250         .win            = 0,
251         .xres           = 1366,
252         .yres           = 768,
253         .bits_per_pixel = 16,
254 };
255
256 static struct tegra_fb_data cardhu_hdmi_fb_data = {
257         .win            = 0,
258         .xres           = 1366,
259         .yres           = 768,
260         .bits_per_pixel = 16,
261 };
262 static struct tegra_dc_out cardhu_disp1_out = {
263         .type           = TEGRA_DC_OUT_RGB,
264
265         .align          = TEGRA_DC_ALIGN_MSB,
266         .order          = TEGRA_DC_ORDER_RED_BLUE,
267
268         .modes          = cardhu_panel_modes,
269         .n_modes        = ARRAY_SIZE(cardhu_panel_modes),
270
271         .enable         = cardhu_panel_enable,
272         .disable        = cardhu_panel_disable,
273 };
274
275 static struct tegra_dc_out cardhu_disp2_out = {
276         .type           = TEGRA_DC_OUT_HDMI,
277         .flags          = TEGRA_DC_OUT_HOTPLUG_HIGH,
278
279         .dcc_bus        = 3,
280         .hotplug_gpio   = cardhu_hdmi_hpd,
281
282         .align          = TEGRA_DC_ALIGN_MSB,
283         .order          = TEGRA_DC_ORDER_RED_BLUE,
284
285         .enable         = cardhu_hdmi_enable,
286         .disable        = cardhu_hdmi_disable,
287 };
288 static struct tegra_dc_platform_data cardhu_disp1_pdata = {
289         .flags          = TEGRA_DC_FLAG_ENABLED,
290         .default_out    = &cardhu_disp1_out,
291         .fb             = &cardhu_fb_data,
292 };
293
294 static struct tegra_dc_platform_data cardhu_disp2_pdata = {
295         .flags          = 0,
296         .default_out    = &cardhu_disp2_out,
297         .fb             = &cardhu_hdmi_fb_data,
298 };
299
300 static struct nvhost_device cardhu_disp1_device = {
301         .name           = "tegradc",
302         .id             = 0,
303         .resource       = cardhu_disp1_resources,
304         .num_resources  = ARRAY_SIZE(cardhu_disp1_resources),
305         .dev = {
306                 .platform_data = &cardhu_disp1_pdata,
307         },
308 };
309
310 static struct nvhost_device cardhu_disp2_device = {
311         .name           = "tegradc",
312         .id             = 1,
313         .resource       = cardhu_disp2_resources,
314         .num_resources  = ARRAY_SIZE(cardhu_disp2_resources),
315         .dev = {
316                 .platform_data = &cardhu_disp2_pdata,
317         },
318 };
319
320 static struct nvmap_platform_carveout cardhu_carveouts[] = {
321         [0] = {
322                 .name           = "iram",
323                 .usage_mask     = NVMAP_HEAP_CARVEOUT_IRAM,
324                 .base           = TEGRA_IRAM_BASE,
325                 .size           = TEGRA_IRAM_SIZE,
326                 .buddy_size     = 0, /* no buddy allocation for IRAM */
327         },
328         [1] = {
329                 .name           = "generic-0",
330                 .usage_mask     = NVMAP_HEAP_CARVEOUT_GENERIC,
331                 .base           = 0,    /* Filled in by cardhu_panel_init() */
332                 .size           = 0,    /* Filled in by cardhu_panel_init() */
333                 .buddy_size     = SZ_32K,
334         },
335 };
336
337 static struct nvmap_platform_data cardhu_nvmap_data = {
338         .carveouts      = cardhu_carveouts,
339         .nr_carveouts   = ARRAY_SIZE(cardhu_carveouts),
340 };
341
342 static struct platform_device cardhu_nvmap_device = {
343         .name   = "tegra-nvmap",
344         .id     = -1,
345         .dev    = {
346                 .platform_data = &cardhu_nvmap_data,
347         },
348 };
349
350 static struct platform_device *cardhu_gfx_devices[] __initdata = {
351         &cardhu_nvmap_device,
352         &tegra_grhost_device,
353         &tegra_pwfm0_device,
354         &cardhu_backlight_device,
355 };
356
357
358 int __init cardhu_panel_init(void)
359 {
360         int err;
361         struct resource *res;
362
363         cardhu_carveouts[1].base = tegra_carveout_start;
364         cardhu_carveouts[1].size = tegra_carveout_size;
365
366         tegra_gpio_enable(cardhu_hdmi_hpd);
367         gpio_request(cardhu_hdmi_hpd, "hdmi_hpd");
368         gpio_direction_input(cardhu_hdmi_hpd);
369         err = platform_add_devices(cardhu_gfx_devices,
370                                 ARRAY_SIZE(cardhu_gfx_devices));
371
372         res = nvhost_get_resource_byname(&cardhu_disp1_device,
373                                          IORESOURCE_MEM, "fbmem");
374         res->start = tegra_fb_start;
375         res->end = tegra_fb_start + tegra_fb_size - 1;
376
377         if (!err)
378                 err = nvhost_device_register(&cardhu_disp1_device);
379
380         res = nvhost_get_resource_byname(&cardhu_disp2_device,
381                                          IORESOURCE_MEM, "fbmem");
382         res->start = tegra_fb2_start;
383         res->end = tegra_fb2_start + tegra_fb2_size - 1;
384         if (!err)
385                 err = nvhost_device_register(&cardhu_disp2_device);
386         return err;
387 }