aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra/dc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tegra/dc.c')
-rw-r--r--drivers/gpu/drm/tegra/dc.c176
1 files changed, 106 insertions, 70 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 39940f5b7c91..8495bd01b544 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -10,6 +10,7 @@
10#include <linux/clk.h> 10#include <linux/clk.h>
11#include <linux/debugfs.h> 11#include <linux/debugfs.h>
12#include <linux/iommu.h> 12#include <linux/iommu.h>
13#include <linux/pm_runtime.h>
13#include <linux/reset.h> 14#include <linux/reset.h>
14 15
15#include <soc/tegra/pmc.h> 16#include <soc/tegra/pmc.h>
@@ -1216,6 +1217,8 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
1216 1217
1217 tegra_dc_stats_reset(&dc->stats); 1218 tegra_dc_stats_reset(&dc->stats);
1218 drm_crtc_vblank_off(crtc); 1219 drm_crtc_vblank_off(crtc);
1220
1221 pm_runtime_put_sync(dc->dev);
1219} 1222}
1220 1223
1221static void tegra_crtc_enable(struct drm_crtc *crtc) 1224static void tegra_crtc_enable(struct drm_crtc *crtc)
@@ -1225,6 +1228,48 @@ static void tegra_crtc_enable(struct drm_crtc *crtc)
1225 struct tegra_dc *dc = to_tegra_dc(crtc); 1228 struct tegra_dc *dc = to_tegra_dc(crtc);
1226 u32 value; 1229 u32 value;
1227 1230
1231 pm_runtime_get_sync(dc->dev);
1232
1233 /* initialize display controller */
1234 if (dc->syncpt) {
1235 u32 syncpt = host1x_syncpt_id(dc->syncpt);
1236
1237 value = SYNCPT_CNTRL_NO_STALL;
1238 tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
1239
1240 value = SYNCPT_VSYNC_ENABLE | syncpt;
1241 tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);
1242 }
1243
1244 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1245 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1246 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
1247
1248 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1249 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1250 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
1251
1252 /* initialize timer */
1253 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
1254 WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
1255 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
1256
1257 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
1258 WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
1259 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
1260
1261 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1262 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1263 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
1264
1265 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1266 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1267 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1268
1269 if (dc->soc->supports_border_color)
1270 tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR);
1271
1272 /* apply PLL and pixel clock changes */
1228 tegra_dc_commit_state(dc, state); 1273 tegra_dc_commit_state(dc, state);
1229 1274
1230 /* program display mode */ 1275 /* program display mode */
@@ -1685,7 +1730,6 @@ static int tegra_dc_init(struct host1x_client *client)
1685 struct tegra_drm *tegra = drm->dev_private; 1730 struct tegra_drm *tegra = drm->dev_private;
1686 struct drm_plane *primary = NULL; 1731 struct drm_plane *primary = NULL;
1687 struct drm_plane *cursor = NULL; 1732 struct drm_plane *cursor = NULL;
1688 u32 value;
1689 int err; 1733 int err;
1690 1734
1691 dc->syncpt = host1x_syncpt_request(dc->dev, flags); 1735 dc->syncpt = host1x_syncpt_request(dc->dev, flags);
@@ -1755,47 +1799,6 @@ static int tegra_dc_init(struct host1x_client *client)
1755 goto cleanup; 1799 goto cleanup;
1756 } 1800 }
1757 1801
1758 /* initialize display controller */
1759 if (dc->syncpt) {
1760 u32 syncpt = host1x_syncpt_id(dc->syncpt);
1761
1762 value = SYNCPT_CNTRL_NO_STALL;
1763 tegra_dc_writel(dc, value, DC_CMD_GENERAL_INCR_SYNCPT_CNTRL);
1764
1765 value = SYNCPT_VSYNC_ENABLE | syncpt;
1766 tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);
1767 }
1768
1769 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1770 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1771 tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
1772
1773 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1774 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1775 tegra_dc_writel(dc, value, DC_CMD_INT_POLARITY);
1776
1777 /* initialize timer */
1778 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(0x20) |
1779 WINDOW_B_THRESHOLD(0x20) | WINDOW_C_THRESHOLD(0x20);
1780 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY);
1781
1782 value = CURSOR_THRESHOLD(0) | WINDOW_A_THRESHOLD(1) |
1783 WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
1784 tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
1785
1786 value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1787 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1788 tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
1789
1790 value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
1791 WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
1792 tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
1793
1794 if (dc->soc->supports_border_color)
1795 tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR);
1796
1797 tegra_dc_stats_reset(&dc->stats);
1798
1799 return 0; 1802 return 0;
1800 1803
1801cleanup: 1804cleanup:
@@ -1987,33 +1990,15 @@ static int tegra_dc_probe(struct platform_device *pdev)
1987 return PTR_ERR(dc->rst); 1990 return PTR_ERR(dc->rst);
1988 } 1991 }
1989 1992
1993 reset_control_assert(dc->rst);
1994
1990 if (dc->soc->has_powergate) { 1995 if (dc->soc->has_powergate) {
1991 if (dc->pipe == 0) 1996 if (dc->pipe == 0)
1992 dc->powergate = TEGRA_POWERGATE_DIS; 1997 dc->powergate = TEGRA_POWERGATE_DIS;
1993 else 1998 else
1994 dc->powergate = TEGRA_POWERGATE_DISB; 1999 dc->powergate = TEGRA_POWERGATE_DISB;
1995 2000
1996 err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk, 2001 tegra_powergate_power_off(dc->powergate);
1997 dc->rst);
1998 if (err < 0) {
1999 dev_err(&pdev->dev, "failed to power partition: %d\n",
2000 err);
2001 return err;
2002 }
2003 } else {
2004 err = clk_prepare_enable(dc->clk);
2005 if (err < 0) {
2006 dev_err(&pdev->dev, "failed to enable clock: %d\n",
2007 err);
2008 return err;
2009 }
2010
2011 err = reset_control_deassert(dc->rst);
2012 if (err < 0) {
2013 dev_err(&pdev->dev, "failed to deassert reset: %d\n",
2014 err);
2015 return err;
2016 }
2017 } 2002 }
2018 2003
2019 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2004 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2027,16 +2012,19 @@ static int tegra_dc_probe(struct platform_device *pdev)
2027 return -ENXIO; 2012 return -ENXIO;
2028 } 2013 }
2029 2014
2030 INIT_LIST_HEAD(&dc->client.list);
2031 dc->client.ops = &dc_client_ops;
2032 dc->client.dev = &pdev->dev;
2033
2034 err = tegra_dc_rgb_probe(dc); 2015 err = tegra_dc_rgb_probe(dc);
2035 if (err < 0 && err != -ENODEV) { 2016 if (err < 0 && err != -ENODEV) {
2036 dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err); 2017 dev_err(&pdev->dev, "failed to probe RGB output: %d\n", err);
2037 return err; 2018 return err;
2038 } 2019 }
2039 2020
2021 platform_set_drvdata(pdev, dc);
2022 pm_runtime_enable(&pdev->dev);
2023
2024 INIT_LIST_HEAD(&dc->client.list);
2025 dc->client.ops = &dc_client_ops;
2026 dc->client.dev = &pdev->dev;
2027
2040 err = host1x_client_register(&dc->client); 2028 err = host1x_client_register(&dc->client);
2041 if (err < 0) { 2029 if (err < 0) {
2042 dev_err(&pdev->dev, "failed to register host1x client: %d\n", 2030 dev_err(&pdev->dev, "failed to register host1x client: %d\n",
@@ -2044,8 +2032,6 @@ static int tegra_dc_probe(struct platform_device *pdev)
2044 return err; 2032 return err;
2045 } 2033 }
2046 2034
2047 platform_set_drvdata(pdev, dc);
2048
2049 return 0; 2035 return 0;
2050} 2036}
2051 2037
@@ -2067,7 +2053,22 @@ static int tegra_dc_remove(struct platform_device *pdev)
2067 return err; 2053 return err;
2068 } 2054 }
2069 2055
2070 reset_control_assert(dc->rst); 2056 pm_runtime_disable(&pdev->dev);
2057
2058 return 0;
2059}
2060
2061#ifdef CONFIG_PM
2062static int tegra_dc_suspend(struct device *dev)
2063{
2064 struct tegra_dc *dc = dev_get_drvdata(dev);
2065 int err;
2066
2067 err = reset_control_assert(dc->rst);
2068 if (err < 0) {
2069 dev_err(dev, "failed to assert reset: %d\n", err);
2070 return err;
2071 }
2071 2072
2072 if (dc->soc->has_powergate) 2073 if (dc->soc->has_powergate)
2073 tegra_powergate_power_off(dc->powergate); 2074 tegra_powergate_power_off(dc->powergate);
@@ -2077,10 +2078,45 @@ static int tegra_dc_remove(struct platform_device *pdev)
2077 return 0; 2078 return 0;
2078} 2079}
2079 2080
2081static int tegra_dc_resume(struct device *dev)
2082{
2083 struct tegra_dc *dc = dev_get_drvdata(dev);
2084 int err;
2085
2086 if (dc->soc->has_powergate) {
2087 err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
2088 dc->rst);
2089 if (err < 0) {
2090 dev_err(dev, "failed to power partition: %d\n", err);
2091 return err;
2092 }
2093 } else {
2094 err = clk_prepare_enable(dc->clk);
2095 if (err < 0) {
2096 dev_err(dev, "failed to enable clock: %d\n", err);
2097 return err;
2098 }
2099
2100 err = reset_control_deassert(dc->rst);
2101 if (err < 0) {
2102 dev_err(dev, "failed to deassert reset: %d\n", err);
2103 return err;
2104 }
2105 }
2106
2107 return 0;
2108}
2109#endif
2110
2111static const struct dev_pm_ops tegra_dc_pm_ops = {
2112 SET_RUNTIME_PM_OPS(tegra_dc_suspend, tegra_dc_resume, NULL)
2113};
2114
2080struct platform_driver tegra_dc_driver = { 2115struct platform_driver tegra_dc_driver = {
2081 .driver = { 2116 .driver = {
2082 .name = "tegra-dc", 2117 .name = "tegra-dc",
2083 .of_match_table = tegra_dc_of_match, 2118 .of_match_table = tegra_dc_of_match,
2119 .pm = &tegra_dc_pm_ops,
2084 }, 2120 },
2085 .probe = tegra_dc_probe, 2121 .probe = tegra_dc_probe,
2086 .remove = tegra_dc_remove, 2122 .remove = tegra_dc_remove,