2 * arch/arm/mach-tegra/board-ardbeg-panel.c
4 * Copyright (c) 2013, NVIDIA CORPORATION. All rights reserved.
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.
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
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.
20 #include <linux/ioport.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>
32 #include <mach/irqs.h>
37 #include "gpio-names.h"
38 #include "board-ardbeg.h"
39 #include "board-panel.h"
42 #include "tegra12_host1x_devices.h"
45 struct platform_device * __init ardbeg_host1x_init(void)
47 struct platform_device *pdev = NULL;
49 #ifdef CONFIG_TEGRA_GRHOST
50 pdev = tegra12_register_host1x_devices();
53 pr_err("host1x devices registration failed\n");
60 /* hdmi related regulators */
61 static struct regulator *ardbeg_hdmi_reg;
62 static struct regulator *ardbeg_hdmi_pll;
63 static struct regulator *ardbeg_hdmi_vddio;
65 static struct resource ardbeg_disp1_resources[] = {
68 .start = INT_DISPLAY_GENERAL,
69 .end = INT_DISPLAY_GENERAL,
70 .flags = IORESOURCE_IRQ,
74 .start = TEGRA_DISPLAY_BASE,
75 .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE - 1,
76 .flags = IORESOURCE_MEM,
80 .start = 0, /* Filled in by ardbeg_panel_init() */
81 .end = 0, /* Filled in by ardbeg_panel_init() */
82 .flags = IORESOURCE_MEM,
85 .name = "ganged_dsia_regs",
86 .start = 0, /* Filled in the panel file by init_resources() */
87 .end = 0, /* Filled in the panel file by init_resources() */
88 .flags = IORESOURCE_MEM,
91 .name = "ganged_dsib_regs",
92 .start = 0, /* Filled in the panel file by init_resources() */
93 .end = 0, /* Filled in the panel file by init_resources() */
94 .flags = IORESOURCE_MEM,
98 .start = 0, /* Filled in the panel file by init_resources() */
99 .end = 0, /* Filled in the panel file by init_resources() */
100 .flags = IORESOURCE_MEM,
104 .start = TEGRA_MIPI_CAL_BASE,
105 .end = TEGRA_MIPI_CAL_BASE + TEGRA_MIPI_CAL_SIZE - 1,
106 .flags = IORESOURCE_MEM,
110 static struct resource ardbeg_disp1_edp_resources[] = {
113 .start = INT_DISPLAY_GENERAL,
114 .end = INT_DISPLAY_GENERAL,
115 .flags = IORESOURCE_IRQ,
119 .start = TEGRA_DISPLAY_BASE,
120 .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE - 1,
121 .flags = IORESOURCE_MEM,
125 .start = 0, /* Filled in by ardbeg_panel_init() */
126 .end = 0, /* Filled in by ardbeg_panel_init() */
127 .flags = IORESOURCE_MEM,
131 .start = TEGRA_MIPI_CAL_BASE,
132 .end = TEGRA_MIPI_CAL_BASE + TEGRA_MIPI_CAL_SIZE - 1,
133 .flags = IORESOURCE_MEM,
137 .start = TEGRA_SOR_BASE,
138 .end = TEGRA_SOR_BASE + TEGRA_SOR_SIZE - 1,
139 .flags = IORESOURCE_MEM,
143 .start = TEGRA_DPAUX_BASE,
144 .end = TEGRA_DPAUX_BASE + TEGRA_DPAUX_SIZE - 1,
145 .flags = IORESOURCE_MEM,
151 .flags = IORESOURCE_IRQ,
155 static struct resource ardbeg_disp2_resources[] = {
158 .start = INT_DISPLAY_B_GENERAL,
159 .end = INT_DISPLAY_B_GENERAL,
160 .flags = IORESOURCE_IRQ,
164 .start = TEGRA_DISPLAY2_BASE,
165 .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1,
166 .flags = IORESOURCE_MEM,
170 .start = 0, /* Filled in by ardbeg_panel_init() */
171 .end = 0, /* Filled in by ardbeg_panel_init() */
172 .flags = IORESOURCE_MEM,
176 .start = TEGRA_HDMI_BASE,
177 .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1,
178 .flags = IORESOURCE_MEM,
183 static struct tegra_dc_sd_settings sd_settings;
185 static struct tegra_dc_out ardbeg_disp1_out = {
186 .type = TEGRA_DC_OUT_DSI,
187 .sd_settings = &sd_settings,
190 static int ardbeg_hdmi_enable(struct device *dev)
193 if (!ardbeg_hdmi_reg) {
194 ardbeg_hdmi_reg = regulator_get(dev, "avdd_hdmi");
195 if (IS_ERR_OR_NULL(ardbeg_hdmi_reg)) {
196 pr_err("hdmi: couldn't get regulator avdd_hdmi\n");
197 ardbeg_hdmi_reg = NULL;
198 return PTR_ERR(ardbeg_hdmi_reg);
201 ret = regulator_enable(ardbeg_hdmi_reg);
203 pr_err("hdmi: couldn't enable regulator avdd_hdmi\n");
206 if (!ardbeg_hdmi_pll) {
207 ardbeg_hdmi_pll = regulator_get(dev, "avdd_hdmi_pll");
208 if (IS_ERR_OR_NULL(ardbeg_hdmi_pll)) {
209 pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n");
210 ardbeg_hdmi_pll = NULL;
211 regulator_put(ardbeg_hdmi_reg);
212 ardbeg_hdmi_reg = NULL;
213 return PTR_ERR(ardbeg_hdmi_pll);
216 ret = regulator_enable(ardbeg_hdmi_pll);
218 pr_err("hdmi: couldn't enable regulator avdd_hdmi_pll\n");
224 static int ardbeg_hdmi_disable(void)
226 if (ardbeg_hdmi_reg) {
227 regulator_disable(ardbeg_hdmi_reg);
228 regulator_put(ardbeg_hdmi_reg);
229 ardbeg_hdmi_reg = NULL;
232 if (ardbeg_hdmi_pll) {
233 regulator_disable(ardbeg_hdmi_pll);
234 regulator_put(ardbeg_hdmi_pll);
235 ardbeg_hdmi_pll = NULL;
240 static int ardbeg_hdmi_postsuspend(void)
242 if (ardbeg_hdmi_vddio) {
243 regulator_disable(ardbeg_hdmi_vddio);
244 regulator_put(ardbeg_hdmi_vddio);
245 ardbeg_hdmi_vddio = NULL;
250 static int ardbeg_hdmi_hotplug_init(struct device *dev)
252 if (!ardbeg_hdmi_vddio) {
253 ardbeg_hdmi_vddio = regulator_get(dev, "vdd_hdmi_5v0");
254 if (WARN_ON(IS_ERR(ardbeg_hdmi_vddio))) {
255 pr_err("%s: couldn't get regulator vdd_hdmi_5v0: %ld\n",
256 __func__, PTR_ERR(ardbeg_hdmi_vddio));
257 ardbeg_hdmi_vddio = NULL;
259 regulator_enable(ardbeg_hdmi_vddio);
266 struct tmds_config ardbeg_tmds_config[] = {
267 { /* 480p/576p / 25.2MHz/27MHz modes */
271 .pe_current = 0x08080808,
272 .drive_current = 0x2e2e2e2e,
273 .peak_current = 0x00000000,
275 { /* 720p / 74.25MHz modes */
279 .pe_current = 0x08080808,
280 .drive_current = 0x20202020,
281 .peak_current = 0x00000000,
283 { /* 1080p / 148.5MHz modes */
287 .pe_current = 0x08080808,
288 .drive_current = 0x20202020,
289 .peak_current = 0x00000000,
295 .pe_current = 0x08080808,
296 .drive_current = 0x3A353536, /* lane3 needs a slightly lower current */
297 .peak_current = 0x00000000,
301 struct tegra_hdmi_out ardbeg_hdmi_out = {
302 .tmds_config = ardbeg_tmds_config,
303 .n_tmds_config = ARRAY_SIZE(ardbeg_tmds_config),
307 static struct tegra_dc_out ardbeg_disp2_out = {
308 .type = TEGRA_DC_OUT_HDMI,
309 .flags = TEGRA_DC_OUT_HOTPLUG_HIGH,
310 .parent_clk = "pll_d2",
313 .hotplug_gpio = ardbeg_hdmi_hpd,
314 .hdmi_out = &ardbeg_hdmi_out,
316 /* TODO: update max pclk to POR */
317 .max_pixclock = KHZ2PICOS(297000),
319 .align = TEGRA_DC_ALIGN_MSB,
320 .order = TEGRA_DC_ORDER_RED_BLUE,
322 .enable = ardbeg_hdmi_enable,
323 .disable = ardbeg_hdmi_disable,
324 .postsuspend = ardbeg_hdmi_postsuspend,
325 .hotplug_init = ardbeg_hdmi_hotplug_init,
328 static struct tegra_fb_data ardbeg_disp1_fb_data = {
330 .bits_per_pixel = 32,
331 .flags = TEGRA_FB_FLIP_ON_PROBE,
334 static struct tegra_dc_platform_data ardbeg_disp1_pdata = {
335 .flags = TEGRA_DC_FLAG_ENABLED,
336 .default_out = &ardbeg_disp1_out,
337 .fb = &ardbeg_disp1_fb_data,
338 .emc_clk_rate = 204000000,
339 #ifdef CONFIG_TEGRA_DC_CMU
344 static struct tegra_fb_data ardbeg_disp2_fb_data = {
348 .bits_per_pixel = 32,
349 .flags = TEGRA_FB_FLIP_ON_PROBE,
352 static struct tegra_dc_platform_data ardbeg_disp2_pdata = {
353 .flags = TEGRA_DC_FLAG_ENABLED,
354 .default_out = &ardbeg_disp2_out,
355 .fb = &ardbeg_disp2_fb_data,
356 .emc_clk_rate = 300000000,
359 static struct platform_device ardbeg_disp2_device = {
362 .resource = ardbeg_disp2_resources,
363 .num_resources = ARRAY_SIZE(ardbeg_disp2_resources),
365 .platform_data = &ardbeg_disp2_pdata,
369 static struct platform_device ardbeg_disp1_device = {
372 .resource = ardbeg_disp1_resources,
373 .num_resources = ARRAY_SIZE(ardbeg_disp1_resources),
375 .platform_data = &ardbeg_disp1_pdata,
379 static struct nvmap_platform_carveout ardbeg_carveouts[] = {
382 .usage_mask = NVMAP_HEAP_CARVEOUT_IRAM,
383 .base = TEGRA_IRAM_BASE + TEGRA_RESET_HANDLER_SIZE,
384 .size = TEGRA_IRAM_SIZE - TEGRA_RESET_HANDLER_SIZE,
388 .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC,
389 .base = 0, /* Filled in by ardbeg_panel_init() */
390 .size = 0, /* Filled in by ardbeg_panel_init() */
394 .usage_mask = NVMAP_HEAP_CARVEOUT_VPR,
395 .base = 0, /* Filled in by ardbeg_panel_init() */
396 .size = 0, /* Filled in by ardbeg_panel_init() */
400 static struct nvmap_platform_data ardbeg_nvmap_data = {
401 .carveouts = ardbeg_carveouts,
402 .nr_carveouts = ARRAY_SIZE(ardbeg_carveouts),
404 static struct platform_device ardbeg_nvmap_device = {
405 .name = "tegra-nvmap",
408 .platform_data = &ardbeg_nvmap_data,
412 static struct tegra_dc_sd_settings ardbeg_sd_settings = {
413 .enable = 1, /* enabled by default. */
414 .use_auto_pwm = false,
415 .hw_update_delay = 0,
418 .use_vid_luma = false,
419 .phase_in_adjustments = 0,
420 .k_limit_enable = true,
422 .sd_window_enable = false,
423 .soft_clipping_enable = true,
424 /* Low soft clipping threshold to compensate for aggressive k_limit */
425 .soft_clipping_threshold = 128,
426 .smooth_k_enable = false,
428 /* Default video coefficients */
431 /* Immediate backlight changes */
433 /* Gammas: R: 2.2 G: 2.2 B: 2.2 */
439 {138, 150, 164, 178},
440 {193, 208, 224, 241},
457 .sd_brightness = &sd_brightness,
461 static void ardbeg_panel_select(void)
463 struct tegra_panel *panel = NULL;
464 struct board_info board;
467 tegra_get_display_board_info(&board);
469 switch (board.board_id) {
472 panel = &dsi_s_wqxga_10_1;
473 dsi_instance = DSI_INSTANCE_0;
476 panel = &dsi_a_1080p_14_0;
477 dsi_instance = DSI_INSTANCE_0;
480 panel = &dsi_p_wuxga_10_1;
481 dsi_instance = DSI_INSTANCE_0;
484 panel = &dsi_lgd_wxga_7_0;
485 dsi_instance = DSI_INSTANCE_0;
489 panel = &edp_a_1080p_14_0;
490 ardbeg_disp1_out.type = TEGRA_DC_OUT_DP;
491 ardbeg_disp1_device.resource = ardbeg_disp1_edp_resources;
492 ardbeg_disp1_device.num_resources =
493 ARRAY_SIZE(ardbeg_disp1_edp_resources);
496 panel = &lvds_c_1366_14;
497 ardbeg_disp1_out.type = TEGRA_DC_OUT_LVDS;
498 ardbeg_disp1_device.resource = ardbeg_disp1_edp_resources;
499 ardbeg_disp1_device.num_resources =
500 ARRAY_SIZE(ardbeg_disp1_edp_resources);
503 panel = &dsi_p_wuxga_10_1;
504 dsi_instance = DSI_INSTANCE_0;
509 if (panel->init_sd_settings)
510 panel->init_sd_settings(&sd_settings);
512 if (panel->init_dc_out) {
513 panel->init_dc_out(&ardbeg_disp1_out);
514 if (ardbeg_disp1_out.type == TEGRA_DC_OUT_DSI) {
515 ardbeg_disp1_out.dsi->dsi_instance =
517 ardbeg_disp1_out.dsi->dsi_panel_rst_gpio =
519 ardbeg_disp1_out.dsi->dsi_panel_bl_pwm_gpio =
520 DSI_PANEL_BL_PWM_GPIO;
521 ardbeg_disp1_out.dsi->te_gpio = TEGRA_GPIO_PR6;
525 if (panel->init_fb_data)
526 panel->init_fb_data(&ardbeg_disp1_fb_data);
528 if (panel->init_cmu_data)
529 panel->init_cmu_data(&ardbeg_disp1_pdata);
531 if (panel->set_disp_device)
532 panel->set_disp_device(&ardbeg_disp1_device);
534 if (ardbeg_disp1_out.type == TEGRA_DC_OUT_DSI) {
535 tegra_dsi_resources_init(dsi_instance,
536 ardbeg_disp1_resources,
537 ARRAY_SIZE(ardbeg_disp1_resources));
540 if (panel->register_bl_dev)
541 panel->register_bl_dev();
543 if (panel->register_i2c_bridge)
544 panel->register_i2c_bridge();
548 int __init ardbeg_panel_init(void)
551 struct resource __maybe_unused *res;
552 struct platform_device *phost1x = NULL;
554 sd_settings = ardbeg_sd_settings;
556 ardbeg_panel_select();
558 #ifdef CONFIG_TEGRA_NVMAP
559 ardbeg_carveouts[1].base = tegra_carveout_start;
560 ardbeg_carveouts[1].size = tegra_carveout_size;
561 ardbeg_carveouts[2].base = tegra_vpr_start;
562 ardbeg_carveouts[2].size = tegra_vpr_size;
564 err = platform_device_register(&ardbeg_nvmap_device);
566 pr_err("nvmap device registration failed\n");
571 phost1x = ardbeg_host1x_init();
573 pr_err("host1x devices registration failed\n");
577 res = platform_get_resource_byname(&ardbeg_disp1_device,
578 IORESOURCE_MEM, "fbmem");
579 res->start = tegra_fb_start;
580 res->end = tegra_fb_start + tegra_fb_size - 1;
582 /* Copy the bootloader fb to the fb. */
583 if (tegra_bootloader_fb_size)
584 __tegra_move_framebuffer(&ardbeg_nvmap_device,
585 tegra_fb_start, tegra_bootloader_fb_start,
586 min(tegra_fb_size, tegra_bootloader_fb_size));
588 __tegra_clear_framebuffer(&ardbeg_nvmap_device,
589 tegra_fb_start, tegra_fb_size);
591 ardbeg_disp1_device.dev.parent = &phost1x->dev;
592 err = platform_device_register(&ardbeg_disp1_device);
594 pr_err("disp1 device registration failed\n");
598 err = tegra_init_hdmi(&ardbeg_disp2_device, phost1x);
602 #ifdef CONFIG_TEGRA_NVAVP
603 nvavp_device.dev.parent = &phost1x->dev;
604 err = platform_device_register(&nvavp_device);
606 pr_err("nvavp device registration failed\n");