/* * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include "board-panel.h" #include "board.h" #include "iomap.h" atomic_t sd_brightness = ATOMIC_INIT(255); EXPORT_SYMBOL(sd_brightness); void tegra_dsi_resources_init(u8 dsi_instance, struct resource *resources, int n_resources) { int i; for (i = 0; i < n_resources; i++) { struct resource *r = &resources[i]; if (resource_type(r) == IORESOURCE_MEM && !strcmp(r->name, "dsi_regs")) { switch (dsi_instance) { case DSI_INSTANCE_0: r->start = TEGRA_DSI_BASE; r->end = TEGRA_DSI_BASE + TEGRA_DSI_SIZE - 1; break; case DSI_INSTANCE_1: default: r->start = TEGRA_DSIB_BASE; r->end = TEGRA_DSIB_BASE + TEGRA_DSIB_SIZE - 1; break; } } if (resource_type(r) == IORESOURCE_MEM && !strcmp(r->name, "ganged_dsia_regs")) { r->start = TEGRA_DSI_BASE; r->end = TEGRA_DSI_BASE + TEGRA_DSI_SIZE - 1; } if (resource_type(r) == IORESOURCE_MEM && !strcmp(r->name, "ganged_dsib_regs")) { r->start = TEGRA_DSIB_BASE; r->end = TEGRA_DSIB_BASE + TEGRA_DSIB_SIZE - 1; } } } void tegra_dsi_update_init_cmd_gpio_rst( struct tegra_dc_out *dsi_disp1_out) { int i; for (i = 0; i < dsi_disp1_out->dsi->n_init_cmd; i++) { if (dsi_disp1_out->dsi->dsi_init_cmd[i].cmd_type == TEGRA_DSI_GPIO_SET) dsi_disp1_out->dsi->dsi_init_cmd[i].sp_len_dly.gpio = dsi_disp1_out->dsi->dsi_panel_rst_gpio; } } int tegra_panel_reset(struct tegra_panel_of *panel, unsigned int delay_ms) { int gpio = panel->panel_gpio[TEGRA_GPIO_RESET]; if (!gpio_is_valid(gpio)) return -ENOENT; gpio_direction_output(gpio, 1); usleep_range(1000, 5000); gpio_set_value(gpio, 0); usleep_range(1000, 5000); gpio_set_value(gpio, 1); msleep(delay_ms); return 0; } int tegra_panel_gpio_get_dt(const char *comp_str, struct tegra_panel_of *panel) { int cnt = 0; char *label = NULL; const char *node_status; int err = 0; struct device_node *node = of_find_compatible_node(NULL, NULL, comp_str); /* * If gpios are already populated, just return. */ if (panel->panel_gpio_populated) return 0; if (!node) { pr_info("%s panel dt support not available\n", comp_str); err = -ENOENT; goto fail; } of_property_read_string(node, "status", &node_status); if (strcmp(node_status, "okay")) { pr_info("%s panel dt support disabled\n", comp_str); err = -ENOENT; goto fail; } panel->panel_gpio[TEGRA_GPIO_RESET] = of_get_named_gpio(node, "nvidia,dsi-panel-rst-gpio", 0); panel->panel_gpio[TEGRA_GPIO_BL_ENABLE] = of_get_named_gpio(node, "nvidia,dsi-panel-bl-en-gpio", 0); panel->panel_gpio[TEGRA_GPIO_PWM] = of_get_named_gpio(node, "nvidia,dsi-panel-bl-pwm-gpio", 0); for (cnt = 0; cnt < TEGRA_N_GPIO_PANEL; cnt++) { if (gpio_is_valid(panel->panel_gpio[cnt])) { switch (cnt) { case TEGRA_GPIO_RESET: label = "tegra-panel-reset"; break; case TEGRA_GPIO_BL_ENABLE: label = "tegra-panel-bl-enable"; break; case TEGRA_GPIO_PWM: label = "tegra-panel-pwm"; break; default: pr_err("tegra panel no gpio entry\n"); } gpio_request(panel->panel_gpio[cnt], label); } } if (gpio_is_valid(panel->panel_gpio[TEGRA_GPIO_PWM])) gpio_free(panel->panel_gpio[TEGRA_GPIO_PWM]); panel->panel_gpio_populated = true; fail: of_node_put(node); return err; } static void tegra_panel_register_ops(struct tegra_dc_out *dc_out, struct tegra_panel_ops *p_ops) { BUG_ON(!dc_out); if (!p_ops) { /* TODO: register default ops */ } dc_out->enable = p_ops->enable; dc_out->postpoweron = p_ops->postpoweron; dc_out->prepoweroff = p_ops->prepoweroff; dc_out->disable = p_ops->disable; dc_out->hotplug_init = p_ops->hotplug_init; dc_out->postsuspend = p_ops->postsuspend; dc_out->hotplug_report = p_ops->hotplug_report; } struct device_node *tegra_panel_get_dt_node( struct tegra_dc_platform_data *pdata) { struct tegra_dc_out *dc_out = NULL; struct device_node *np_panel = NULL; struct board_info display_board; tegra_get_display_board_info(&display_board); if (pdata) dc_out = pdata->default_out; switch (display_board.board_id) { case BOARD_E1627: case BOARD_E1797: if (pdata && dc_out) tegra_panel_register_ops(dc_out, &dsi_p_wuxga_10_1_ops); np_panel = of_find_compatible_node(NULL, NULL, "p,wuxga-10-1"); break; case BOARD_E1549: if (pdata && dc_out) tegra_panel_register_ops(dc_out, &dsi_lgd_wxga_7_0_ops); np_panel = of_find_compatible_node(NULL, NULL, "lg,wxga-7"); break; case BOARD_E1639: case BOARD_E1813: if (pdata && dc_out) tegra_panel_register_ops(dc_out, &dsi_s_wqxga_10_1_ops); np_panel = of_find_compatible_node(NULL, NULL, "s,wqxga-10-1"); break; default: WARN(1, "Display panel not supported\n"); }; return of_device_is_available(np_panel) ? np_panel : NULL; } #ifdef CONFIG_TEGRA_DC /** * tegra_init_hdmi - initialize and add HDMI device if not disabled by DT */ int tegra_init_hdmi(struct platform_device *pdev, struct platform_device *phost1x) { struct resource __maybe_unused *res; bool enabled = true; int err; #ifdef CONFIG_OF struct device_node *hdmi_node = NULL; hdmi_node = of_find_node_by_path("/host1x/hdmi"); /* disable HDMI if explicitly set that way in the device tree */ enabled = !hdmi_node || of_device_is_available(hdmi_node); #endif if (enabled) { #ifndef CONFIG_TEGRA_HDMI_PRIMARY res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "fbmem"); res->start = tegra_fb2_start; res->end = tegra_fb2_start + tegra_fb2_size - 1; #endif pdev->dev.parent = &phost1x->dev; err = platform_device_register(pdev); if (err) { dev_err(&pdev->dev, "device registration failed\n"); return err; } } return 0; } #else int tegra_init_hdmi(struct platform_device *pdev, struct platform_device *phost1x) { return 0; } #endif