From 570c3438ea78f13fe9979d7a7022f063beecbad1 Mon Sep 17 00:00:00 2001 From: Preetham Chandru Date: Thu, 29 Dec 2011 18:55:34 +0530 Subject: arm: tegra: Enable HDMI for harmony Enabled HDMI support for harmony. Bug: 911662 Change-Id: I50d513dc0705fb64fc3946c1518b60b885d6194e Signed-off-by: Preetham Chandru R Reviewed-on: http://git-master/r/72611 Reviewed-by: Simone Willett Tested-by: Simone Willett --- arch/arm/mach-tegra/board-harmony-panel.c | 137 ++++++++++++++++++++++++++++-- arch/arm/mach-tegra/board-harmony.c | 2 +- 2 files changed, 129 insertions(+), 10 deletions(-) (limited to 'arch') diff --git a/arch/arm/mach-tegra/board-harmony-panel.c b/arch/arm/mach-tegra/board-harmony-panel.c index d0eecfc9917a..4ea6725101ee 100644 --- a/arch/arm/mach-tegra/board-harmony-panel.c +++ b/arch/arm/mach-tegra/board-harmony-panel.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -38,6 +39,7 @@ #define harmony_en_vdd_pnl TEGRA_GPIO_PC6 #define harmony_bl_vdd TEGRA_GPIO_PW0 #define harmony_bl_pwm TEGRA_GPIO_PB4 +#define harmony_hdmi_hpd TEGRA_GPIO_PN7 /* panel power on sequence timing */ #define harmony_pnl_to_lvds_ms 0 @@ -113,6 +115,47 @@ static int harmony_panel_disable(void) return 0; } +static int harmony_set_hdmi_power(bool enable) +{ + static struct { + struct regulator *regulator; + const char *name; + } regs[] = { + { .name = "avdd_hdmi" }, + { .name = "avdd_hdmi_pll" }, + }; + int i; + + for (i = 0; i < ARRAY_SIZE(regs); i++) { + if (!regs[i].regulator) { + regs[i].regulator = regulator_get(NULL, regs[i].name); + + if (IS_ERR(regs[i].regulator)) { + int ret = PTR_ERR(regs[i].regulator); + regs[i].regulator = NULL; + return ret; + } + } + + if (enable) + regulator_enable(regs[i].regulator); + else + regulator_disable(regs[i].regulator); + } + + return 0; +} + +static int harmony_hdmi_enable(void) +{ + return harmony_set_hdmi_power(true); +} + +static int harmony_hdmi_disable(void) +{ + return harmony_set_hdmi_power(false); +} + static struct resource harmony_disp1_resources[] = { { .name = "irq", @@ -132,6 +175,31 @@ static struct resource harmony_disp1_resources[] = { }, }; +static struct resource harmony_disp2_resources[] = { + { + .name = "irq", + .start = INT_DISPLAY_B_GENERAL, + .end = INT_DISPLAY_B_GENERAL, + .flags = IORESOURCE_IRQ, + }, + { + .name = "regs", + .start = TEGRA_DISPLAY2_BASE, + .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "fbmem", + .flags = IORESOURCE_MEM, + }, + { + .name = "hdmi_regs", + .start = TEGRA_HDMI_BASE, + .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + static struct tegra_dc_mode harmony_panel_modes[] = { { .pclk = 42430000, @@ -156,6 +224,13 @@ static struct tegra_fb_data harmony_fb_data = { .flags = TEGRA_FB_FLIP_ON_PROBE, }; +static struct tegra_fb_data harmony_hdmi_fb_data = { + .win = 0, + .xres = 1280, + .yres = 720, + .bits_per_pixel = 16, +}; + static struct tegra_dc_out harmony_disp1_out = { .type = TEGRA_DC_OUT_RGB, @@ -171,12 +246,32 @@ static struct tegra_dc_out harmony_disp1_out = { .disable = harmony_panel_disable, }; +static struct tegra_dc_out harmony_disp2_out = { + .type = TEGRA_DC_OUT_HDMI, + .flags = TEGRA_DC_OUT_HOTPLUG_HIGH, + + .dcc_bus = 1, + .hotplug_gpio = harmony_hdmi_hpd, + + .align = TEGRA_DC_ALIGN_MSB, + .order = TEGRA_DC_ORDER_RED_BLUE, + + .enable = harmony_hdmi_enable, + .disable = harmony_hdmi_disable, +}; + static struct tegra_dc_platform_data harmony_disp1_pdata = { .flags = TEGRA_DC_FLAG_ENABLED, .default_out = &harmony_disp1_out, .fb = &harmony_fb_data, }; +static struct tegra_dc_platform_data harmony_disp2_pdata = { + .flags = 0, + .default_out = &harmony_disp2_out, + .fb = &harmony_hdmi_fb_data, +}; + static struct nvhost_device harmony_disp1_device = { .name = "tegradc", .id = 0, @@ -192,6 +287,16 @@ static int harmony_disp1_check_fb(struct device *dev, struct fb_info *info) return info->device == &harmony_disp1_device.dev; } +static struct nvhost_device harmony_disp2_device = { + .name = "tegradc", + .id = 1, + .resource = harmony_disp2_resources, + .num_resources = ARRAY_SIZE(harmony_disp2_resources), + .dev = { + .platform_data = &harmony_disp2_pdata, + }, +}; + #if defined(CONFIG_TEGRA_NVMAP) static struct nvmap_platform_carveout harmony_carveouts[] = { [0] = NVMAP_HEAP_CARVEOUT_IRAM_INIT, @@ -241,6 +346,10 @@ int __init harmony_panel_init(void) { gpio_direction_output(harmony_lvds_shutdown, 1); tegra_gpio_enable(harmony_lvds_shutdown); + gpio_request(harmony_hdmi_hpd, "hdmi_hpd"); + gpio_direction_input(harmony_hdmi_hpd); + tegra_gpio_enable(harmony_hdmi_hpd); + #if defined(CONFIG_TEGRA_NVMAP) harmony_carveouts[1].base = tegra_carveout_start; harmony_carveouts[1].size = tegra_carveout_size; @@ -256,18 +365,28 @@ int __init harmony_panel_init(void) { if (res) { res->start = tegra_fb_start; res->end = tegra_fb_start + tegra_fb_size - 1; + } - /* Copy the bootloader fb to the fb. */ - if (tegra_bootloader_fb_start) - tegra_move_framebuffer(tegra_fb_start, - tegra_bootloader_fb_start, - min(tegra_fb_size, tegra_bootloader_fb_size)); - - err = nvhost_device_register(&harmony_disp1_device); - if (err) - return err; + res = nvhost_get_resource_byname(&harmony_disp2_device, + IORESOURCE_MEM, "fbmem"); + if (res) { + res->start = tegra_fb2_start; + res->end = tegra_fb2_start + tegra_fb2_size - 1; } + /* Copy the bootloader fb to the fb. */ + if (tegra_bootloader_fb_start) + tegra_move_framebuffer(tegra_fb_start, + tegra_bootloader_fb_start, + min(tegra_fb_size, tegra_bootloader_fb_size)); + err = nvhost_device_register(&harmony_disp1_device); + if (err) + return err; + + err = nvhost_device_register(&harmony_disp2_device); + if (err) + return err; + return 0; } diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index f3f15a1bd3db..27f678a74c4f 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c @@ -507,7 +507,7 @@ void __init tegra_harmony_reserve(void) if (memblock_reserve(0x0, 4096) < 0) pr_warn("Cannot reserve first 4K of memory for safety\n"); - tegra_reserve(SZ_128M, SZ_8M, 0); + tegra_reserve(SZ_128M, SZ_8M, SZ_16M); } MACHINE_START(HARMONY, "harmony") -- cgit v1.2.3