arm: tegra: ardbeg: Support HDMI
[linux-3.10.git] / arch / arm / mach-tegra / board-ardbeg-panel.c
1 /*
2  * arch/arm/mach-tegra/board-ardbeg-panel.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
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 #include <linux/ioport.h>
21 #include <linux/fb.h>
22 #include <linux/nvmap.h>
23 #include <linux/nvhost.h>
24 #include <linux/init.h>
25 #include <linux/delay.h>
26 #include <linux/gpio.h>
27 #include <linux/tegra_pwm_bl.h>
28 #include <linux/regulator/consumer.h>
29 #include <linux/pwm_backlight.h>
30 #include <linux/of.h>
31
32 #include <mach/irqs.h>
33 #include <mach/dc.h>
34
35 #include "board.h"
36 #include "devices.h"
37 #include "gpio-names.h"
38 #include "board-ardbeg.h"
39 #include "board-panel.h"
40 #include "common.h"
41 #include "iomap.h"
42
43 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
44 #include "tegra11_host1x_devices.h"
45 #else
46 #include "tegra12_host1x_devices.h"
47 #endif
48
49 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
50 #define DSI_PANEL_RST_GPIO      TEGRA_GPIO_PH3
51 #define DSI_PANEL_BL_PWM_GPIO   TEGRA_GPIO_PH1
52 #else
53 /* TODO: update gpio for t124 ardbeg */
54 #define DSI_PANEL_RST_GPIO      TEGRA_GPIO_PH3
55 #define DSI_PANEL_BL_PWM_GPIO   TEGRA_GPIO_PH1
56 #endif
57
58 struct platform_device * __init ardbeg_host1x_init(void)
59 {
60         struct platform_device *pdev = NULL;
61
62 #ifdef CONFIG_TEGRA_GRHOST
63         if (!of_have_populated_dt()) {
64 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
65                 pdev = tegra11_register_host1x_devices();
66 #else
67                 pdev = tegra12_register_host1x_devices();
68 #endif
69         } else {
70                 pdev = to_platform_device(bus_find_device_by_name(
71                         &platform_bus_type, NULL, "host1x"));
72         }
73
74         if (!pdev) {
75                 pr_err("host1x devices registration failed\n");
76                 return NULL;
77         }
78 #endif
79         return pdev;
80 }
81
82 #ifdef CONFIG_TEGRA_DC
83
84 /* HDMI Hotplug detection pin */
85 #ifdef CONFIG_ARCH_TEGRA_11x_SOC
86 #define ardbeg_hdmi_hpd TEGRA_GPIO_PN7
87 #else
88 /* TODO: update for t124 ardbeg */
89 #define ardbeg_hdmi_hpd TEGRA_GPIO_PN7
90 #endif
91
92 /* hdmi related regulators */
93 static struct regulator *ardbeg_hdmi_reg;
94 static struct regulator *ardbeg_hdmi_pll;
95 static struct regulator *ardbeg_hdmi_vddio;
96
97 static struct resource ardbeg_disp1_resources[] = {
98         {
99                 .name   = "irq",
100                 .start  = INT_DISPLAY_GENERAL,
101                 .end    = INT_DISPLAY_GENERAL,
102                 .flags  = IORESOURCE_IRQ,
103         },
104         {
105                 .name   = "regs",
106                 .start  = TEGRA_DISPLAY_BASE,
107                 .end    = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE - 1,
108                 .flags  = IORESOURCE_MEM,
109         },
110         {
111                 .name   = "fbmem",
112                 .start  = 0, /* Filled in by ardbeg_panel_init() */
113                 .end    = 0, /* Filled in by ardbeg_panel_init() */
114                 .flags  = IORESOURCE_MEM,
115         },
116         {
117                 .name   = "ganged_dsia_regs",
118                 .start  = 0, /* Filled in the panel file by init_resources() */
119                 .end    = 0, /* Filled in the panel file by init_resources() */
120                 .flags  = IORESOURCE_MEM,
121         },
122         {
123                 .name   = "ganged_dsib_regs",
124                 .start  = 0, /* Filled in the panel file by init_resources() */
125                 .end    = 0, /* Filled in the panel file by init_resources() */
126                 .flags  = IORESOURCE_MEM,
127         },
128         {
129                 .name   = "dsi_regs",
130                 .start  = 0, /* Filled in the panel file by init_resources() */
131                 .end    = 0, /* Filled in the panel file by init_resources() */
132                 .flags  = IORESOURCE_MEM,
133         },
134         {
135                 .name   = "mipi_cal",
136                 .start  = TEGRA_MIPI_CAL_BASE,
137                 .end    = TEGRA_MIPI_CAL_BASE + TEGRA_MIPI_CAL_SIZE - 1,
138                 .flags  = IORESOURCE_MEM,
139         },
140 };
141
142 static struct resource ardbeg_disp2_resources[] = {
143         {
144                 .name   = "irq",
145                 .start  = INT_DISPLAY_B_GENERAL,
146                 .end    = INT_DISPLAY_B_GENERAL,
147                 .flags  = IORESOURCE_IRQ,
148         },
149         {
150                 .name   = "regs",
151                 .start  = TEGRA_DISPLAY2_BASE,
152                 .end    = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
153                 .flags  = IORESOURCE_MEM,
154         },
155         {
156                 .name   = "fbmem",
157                 .start  = 0, /* Filled in by ardbeg_panel_init() */
158                 .end    = 0, /* Filled in by ardbeg_panel_init() */
159                 .flags  = IORESOURCE_MEM,
160         },
161         {
162                 .name   = "hdmi_regs",
163                 .start  = TEGRA_HDMI_BASE,
164                 .end    = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
165                 .flags  = IORESOURCE_MEM,
166         },
167 };
168
169
170 static struct tegra_dc_sd_settings sd_settings;
171
172 static struct tegra_dc_out ardbeg_disp1_out = {
173         .type           = TEGRA_DC_OUT_DSI,
174         .sd_settings    = &sd_settings,
175 };
176
177 static int ardbeg_hdmi_enable(struct device *dev)
178 {
179         int ret;
180         if (!ardbeg_hdmi_reg) {
181                 ardbeg_hdmi_reg = regulator_get(dev, "avdd_hdmi");
182                 if (IS_ERR_OR_NULL(ardbeg_hdmi_reg)) {
183                         pr_err("hdmi: couldn't get regulator avdd_hdmi\n");
184                         ardbeg_hdmi_reg = NULL;
185                         return PTR_ERR(ardbeg_hdmi_reg);
186                 }
187         }
188         ret = regulator_enable(ardbeg_hdmi_reg);
189         if (ret < 0) {
190                 pr_err("hdmi: couldn't enable regulator avdd_hdmi\n");
191                 return ret;
192         }
193         if (!ardbeg_hdmi_pll) {
194                 ardbeg_hdmi_pll = regulator_get(dev, "avdd_hdmi_pll");
195                 if (IS_ERR_OR_NULL(ardbeg_hdmi_pll)) {
196                         pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n");
197                         ardbeg_hdmi_pll = NULL;
198                         regulator_put(ardbeg_hdmi_reg);
199                         ardbeg_hdmi_reg = NULL;
200                         return PTR_ERR(ardbeg_hdmi_pll);
201                 }
202         }
203         ret = regulator_enable(ardbeg_hdmi_pll);
204         if (ret < 0) {
205                 pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n");
206                 return ret;
207         }
208         return 0;
209 }
210
211 static int ardbeg_hdmi_disable(void)
212 {
213         if (ardbeg_hdmi_reg) {
214                 regulator_disable(ardbeg_hdmi_reg);
215                 regulator_put(ardbeg_hdmi_reg);
216                 ardbeg_hdmi_reg = NULL;
217         }
218
219         if (ardbeg_hdmi_pll) {
220                 regulator_disable(ardbeg_hdmi_pll);
221                 regulator_put(ardbeg_hdmi_pll);
222                 ardbeg_hdmi_pll = NULL;
223         }
224         return 0;
225 }
226
227 static int ardbeg_hdmi_postsuspend(void)
228 {
229         if (ardbeg_hdmi_vddio) {
230                 regulator_disable(ardbeg_hdmi_vddio);
231                 regulator_put(ardbeg_hdmi_vddio);
232                 ardbeg_hdmi_vddio = NULL;
233         }
234         return 0;
235 }
236
237 static int ardbeg_hdmi_hotplug_init(struct device *dev)
238 {
239         if (!ardbeg_hdmi_vddio) {
240                 ardbeg_hdmi_vddio = regulator_get(dev, "vdd_hdmi_5v0");
241                 if (WARN_ON(IS_ERR(ardbeg_hdmi_vddio))) {
242                         pr_err("%s: couldn't get regulator vdd_hdmi_5v0: %ld\n",
243                                 __func__, PTR_ERR(ardbeg_hdmi_vddio));
244                                 ardbeg_hdmi_vddio = NULL;
245                 } else {
246                         regulator_enable(ardbeg_hdmi_vddio);
247                 }
248         }
249
250         return 0;
251 }
252
253 static struct tegra_dc_out ardbeg_disp2_out = {
254         .type           = TEGRA_DC_OUT_HDMI,
255         .flags          = TEGRA_DC_OUT_HOTPLUG_HIGH,
256         .parent_clk     = "pll_d2_out0",
257
258         .dcc_bus        = 3,
259         .hotplug_gpio   = ardbeg_hdmi_hpd,
260
261         /* TODO: update max pclk to POR */
262         .max_pixclock   = KHZ2PICOS(297000),
263
264         .align          = TEGRA_DC_ALIGN_MSB,
265         .order          = TEGRA_DC_ORDER_RED_BLUE,
266
267         .enable         = ardbeg_hdmi_enable,
268         .disable        = ardbeg_hdmi_disable,
269         .postsuspend    = ardbeg_hdmi_postsuspend,
270         .hotplug_init   = ardbeg_hdmi_hotplug_init,
271 };
272
273 static struct tegra_fb_data ardbeg_disp1_fb_data = {
274         .win            = 0,
275         .bits_per_pixel = 32,
276         .flags          = TEGRA_FB_FLIP_ON_PROBE,
277 };
278
279 static struct tegra_dc_platform_data ardbeg_disp1_pdata = {
280         .flags          = TEGRA_DC_FLAG_ENABLED,
281         .default_out    = &ardbeg_disp1_out,
282         .fb             = &ardbeg_disp1_fb_data,
283         .emc_clk_rate   = 204000000,
284 #ifdef CONFIG_TEGRA_DC_CMU
285         .cmu_enable     = 1,
286 #endif
287 };
288
289 static struct tegra_fb_data ardbeg_disp2_fb_data = {
290         .win            = 0,
291         .xres           = 1280,
292         .yres           = 720,
293         .bits_per_pixel = 32,
294         .flags          = TEGRA_FB_FLIP_ON_PROBE,
295 };
296
297 static struct tegra_dc_platform_data ardbeg_disp2_pdata = {
298         .flags          = TEGRA_DC_FLAG_ENABLED,
299         .default_out    = &ardbeg_disp2_out,
300         .fb             = &ardbeg_disp2_fb_data,
301         .emc_clk_rate   = 300000000,
302 };
303
304 static struct platform_device ardbeg_disp2_device = {
305         .name           = "tegradc",
306         .id             = 1,
307         .resource       = ardbeg_disp2_resources,
308         .num_resources  = ARRAY_SIZE(ardbeg_disp2_resources),
309         .dev = {
310                 .platform_data = &ardbeg_disp2_pdata,
311         },
312 };
313
314 static struct platform_device ardbeg_disp1_device = {
315         .name           = "tegradc",
316         .id             = 0,
317         .resource       = ardbeg_disp1_resources,
318         .num_resources  = ARRAY_SIZE(ardbeg_disp1_resources),
319         .dev = {
320                 .platform_data = &ardbeg_disp1_pdata,
321         },
322 };
323
324 static struct nvmap_platform_carveout ardbeg_carveouts[] = {
325         [0] = {
326                 .name           = "iram",
327                 .usage_mask     = NVMAP_HEAP_CARVEOUT_IRAM,
328                 .base           = TEGRA_IRAM_BASE + TEGRA_RESET_HANDLER_SIZE,
329                 .size           = TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE,
330                 .buddy_size     = 0, /* no buddy allocation for IRAM */
331         },
332         [1] = {
333                 .name           = "generic-0",
334                 .usage_mask     = NVMAP_HEAP_CARVEOUT_GENERIC,
335                 .base           = 0, /* Filled in by ardbeg_panel_init() */
336                 .size           = 0, /* Filled in by ardbeg_panel_init() */
337                 .buddy_size     = SZ_32K,
338         },
339         [2] = {
340                 .name           = "vpr",
341                 .usage_mask     = NVMAP_HEAP_CARVEOUT_VPR,
342                 .base           = 0, /* Filled in by ardbeg_panel_init() */
343                 .size           = 0, /* Filled in by ardbeg_panel_init() */
344                 .buddy_size     = SZ_32K,
345         },
346 };
347
348 static struct nvmap_platform_data ardbeg_nvmap_data = {
349         .carveouts      = ardbeg_carveouts,
350         .nr_carveouts   = ARRAY_SIZE(ardbeg_carveouts),
351 };
352 static struct platform_device ardbeg_nvmap_device  = {
353         .name   = "tegra-nvmap",
354         .id     = -1,
355         .dev    = {
356                 .platform_data = &ardbeg_nvmap_data,
357         },
358 };
359
360 static struct tegra_dc_sd_settings ardbeg_sd_settings = {
361         .enable = 1, /* enabled by default. */
362         .use_auto_pwm = false,
363         .hw_update_delay = 0,
364         .bin_width = -1,
365         .aggressiveness = 5,
366         .use_vid_luma = false,
367         .phase_in_adjustments = 0,
368         .k_limit_enable = true,
369         .k_limit = 200,
370         .sd_window_enable = false,
371         .soft_clipping_enable = true,
372         /* Low soft clipping threshold to compensate for aggressive k_limit */
373         .soft_clipping_threshold = 128,
374         .smooth_k_enable = false,
375         .smooth_k_incr = 64,
376         /* Default video coefficients */
377         .coeff = {5, 9, 2},
378         .fc = {0, 0},
379         /* Immediate backlight changes */
380         .blp = {1024, 255},
381         /* Gammas: R: 2.2 G: 2.2 B: 2.2 */
382         /* Default BL TF */
383         .bltf = {
384                         {
385                                 {57, 65, 73, 82},
386                                 {92, 103, 114, 125},
387                                 {138, 150, 164, 178},
388                                 {193, 208, 224, 241},
389                         },
390                 },
391         /* Default LUT */
392         .lut = {
393                         {
394                                 {255, 255, 255},
395                                 {199, 199, 199},
396                                 {153, 153, 153},
397                                 {116, 116, 116},
398                                 {85, 85, 85},
399                                 {59, 59, 59},
400                                 {36, 36, 36},
401                                 {17, 17, 17},
402                                 {0, 0, 0},
403                         },
404                 },
405         .sd_brightness = &sd_brightness,
406         .use_vpulse2 = true,
407 };
408
409 static void ardbeg_panel_select(void)
410 {
411         struct tegra_panel *panel = NULL;
412         struct board_info board;
413         u8 dsi_instance;
414
415         tegra_get_display_board_info(&board);
416
417         switch (board.board_id) {
418         case BOARD_E1639:
419                 panel = &dsi_s_wqxga_10_1;
420                 dsi_instance = DSI_INSTANCE_0;
421                 break;
422         case BOARD_PM354:
423                 panel = &dsi_a_1080p_14_0;
424                 dsi_instance = DSI_INSTANCE_0;
425                 break;
426         case BOARD_E1627:
427         /* fall through */
428         default:
429                 panel = &dsi_p_wuxga_10_1;
430                 dsi_instance = DSI_INSTANCE_0;
431                 break;
432         }
433
434         if (panel) {
435                 if (panel->init_sd_settings)
436                         panel->init_sd_settings(&sd_settings);
437
438                 if (panel->init_dc_out) {
439                         panel->init_dc_out(&ardbeg_disp1_out);
440                         ardbeg_disp1_out.dsi->dsi_instance = dsi_instance;
441                         ardbeg_disp1_out.dsi->dsi_panel_rst_gpio =
442                                 DSI_PANEL_RST_GPIO;
443                         ardbeg_disp1_out.dsi->dsi_panel_bl_pwm_gpio =
444                                 DSI_PANEL_BL_PWM_GPIO;
445                 }
446
447                 if (panel->init_fb_data)
448                         panel->init_fb_data(&ardbeg_disp1_fb_data);
449
450                 if (panel->init_cmu_data)
451                         panel->init_cmu_data(&ardbeg_disp1_pdata);
452
453                 if (panel->set_disp_device)
454                         panel->set_disp_device(&ardbeg_disp1_device);
455
456                 tegra_dsi_resources_init(dsi_instance, ardbeg_disp1_resources,
457                         ARRAY_SIZE(ardbeg_disp1_resources));
458
459                 if (panel->register_bl_dev)
460                         panel->register_bl_dev();
461
462                 if (panel->register_i2c_bridge)
463                         panel->register_i2c_bridge();
464         }
465
466 }
467 int __init ardbeg_panel_init(void)
468 {
469         int err = 0;
470         struct resource __maybe_unused *res;
471         struct platform_device *phost1x = NULL;
472
473         sd_settings = ardbeg_sd_settings;
474
475         ardbeg_panel_select();
476
477 #ifdef CONFIG_TEGRA_NVMAP
478         ardbeg_carveouts[1].base = tegra_carveout_start;
479         ardbeg_carveouts[1].size = tegra_carveout_size;
480         ardbeg_carveouts[2].base = tegra_vpr_start;
481         ardbeg_carveouts[2].size = tegra_vpr_size;
482
483         err = platform_device_register(&ardbeg_nvmap_device);
484         if (err) {
485                 pr_err("nvmap device registration failed\n");
486                 return err;
487         }
488 #endif
489
490         phost1x = ardbeg_host1x_init();
491         if (!phost1x) {
492                 pr_err("host1x devices registration failed\n");
493                 return -EINVAL;
494         }
495
496         res = platform_get_resource_byname(&ardbeg_disp1_device,
497                                          IORESOURCE_MEM, "fbmem");
498         res->start = tegra_fb_start;
499         res->end = tegra_fb_start + tegra_fb_size - 1;
500
501         /* Copy the bootloader fb to the fb. */
502         __tegra_move_framebuffer(&ardbeg_nvmap_device,
503                 tegra_fb_start, tegra_bootloader_fb_start,
504                         min(tegra_fb_size, tegra_bootloader_fb_size));
505
506         res = platform_get_resource_byname(&ardbeg_disp2_device,
507                                          IORESOURCE_MEM, "fbmem");
508
509         res->start = tegra_fb2_start;
510         res->end = tegra_fb2_start + tegra_fb2_size - 1;
511
512         ardbeg_disp1_device.dev.parent = &phost1x->dev;
513         err = platform_device_register(&ardbeg_disp1_device);
514         if (err) {
515                 pr_err("disp1 device registration failed\n");
516                 return err;
517         }
518
519         ardbeg_disp2_device.dev.parent = &phost1x->dev;
520         err = platform_device_register(&ardbeg_disp2_device);
521         if (err) {
522                 pr_err("disp2 device registration failed\n");
523                 return err;
524         }
525
526 #ifdef CONFIG_TEGRA_NVAVP
527         nvavp_device.dev.parent = &phost1x->dev;
528         err = platform_device_register(&nvavp_device);
529         if (err) {
530                 pr_err("nvavp device registration failed\n");
531                 return err;
532         }
533 #endif
534         return err;
535 }
536 #else
537 int __init ardbeg_panel_init(void)
538 {
539         if (ardbeg_host1x_init())
540                 return 0;
541         else
542                 return -EINVAL;
543 }
544 #endif