From bf78b43d6527c52ead5407bb19504a66220f171b Mon Sep 17 00:00:00 2001 From: Robert Morell Date: Mon, 29 Aug 2011 17:46:07 -0700 Subject: arm: tegra: Add HDMI support for Harmony This adds the necessary platform data to support HDMI on Harmony devices. Bug 868732 Change-Id: Ia972cd2a9695072563478036a7fd1b9c3fd18135 Reviewed-on: http://git-master/r/49729 Reviewed-by: Robert Morell Tested-by: Robert Morell Reviewed-by: Jonathan Mayo --- arch/arm/mach-tegra/board-harmony-panel.c | 116 ++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/arch/arm/mach-tegra/board-harmony-panel.c b/arch/arm/mach-tegra/board-harmony-panel.c index 1498c44aba4f..5bb70205717d 100644 --- a/arch/arm/mach-tegra/board-harmony-panel.c +++ b/arch/arm/mach-tegra/board-harmony-panel.c @@ -40,6 +40,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 static int harmony_backlight_init(struct device *dev) { @@ -73,6 +74,8 @@ static int harmony_backlight_notify(struct device *unused, int brightness) return brightness; } +static int harmony_disp1_check_fb(struct device *dev, struct fb_info *info); + static struct platform_pwm_backlight_data harmony_backlight_data = { .pwm_id = 0, .max_brightness = 255, @@ -81,6 +84,8 @@ static struct platform_pwm_backlight_data harmony_backlight_data = { .init = harmony_backlight_init, .exit = harmony_backlight_exit, .notify = harmony_backlight_notify, + /* Only toggle backlight on fb blank notifications for disp1 */ + .check_fb = harmony_disp1_check_fb, }; static struct platform_device harmony_backlight_device = { @@ -103,6 +108,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", @@ -124,6 +170,27 @@ 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 = "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, @@ -147,6 +214,13 @@ static struct tegra_fb_data harmony_fb_data = { .bits_per_pixel = 32, }; +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, @@ -160,12 +234,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, @@ -176,6 +270,21 @@ static struct nvhost_device harmony_disp1_device = { }, }; +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, + }, +}; + static struct nvmap_platform_carveout harmony_carveouts[] = { [0] = { .name = "iram", @@ -229,12 +338,19 @@ 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); + err = platform_add_devices(harmony_gfx_devices, ARRAY_SIZE(harmony_gfx_devices)); if (!err) err = nvhost_device_register(&harmony_disp1_device); + if (!err) + err = nvhost_device_register(&harmony_disp2_device); + return err; } -- cgit v1.2.3