aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2014-07-07 09:32:53 -0400
committerThierry Reding <treding@nvidia.com>2014-11-13 10:11:59 -0500
commit9c0127004ff4e891e475d6dfb22ddcbaeca6ec9b (patch)
tree5e9f76155677e00934fe3b990d753d1a29549728 /drivers/gpu/drm/tegra
parentb298e98ef6ab9c4279b427db717a1624ef722751 (diff)
drm/tegra: dc: Add powergate support
Both display controllers are in their own power partition. Currently the driver relies on the assumption that these partitions are on (which is the hardware default). However some bootloaders may disable them, so the driver must make sure to turn them back on to avoid hangs. Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r--drivers/gpu/drm/tegra/dc.c45
-rw-r--r--drivers/gpu/drm/tegra/drm.h1
2 files changed, 43 insertions, 3 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 6553fd238685..4a015232e2e8 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -11,6 +11,8 @@
11#include <linux/debugfs.h> 11#include <linux/debugfs.h>
12#include <linux/reset.h> 12#include <linux/reset.h>
13 13
14#include <soc/tegra/pmc.h>
15
14#include "dc.h" 16#include "dc.h"
15#include "drm.h" 17#include "drm.h"
16#include "gem.h" 18#include "gem.h"
@@ -20,6 +22,7 @@ struct tegra_dc_soc_info {
20 bool supports_cursor; 22 bool supports_cursor;
21 bool supports_block_linear; 23 bool supports_block_linear;
22 unsigned int pitch_align; 24 unsigned int pitch_align;
25 bool has_powergate;
23}; 26};
24 27
25struct tegra_plane { 28struct tegra_plane {
@@ -1357,6 +1360,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
1357 .supports_cursor = false, 1360 .supports_cursor = false,
1358 .supports_block_linear = false, 1361 .supports_block_linear = false,
1359 .pitch_align = 8, 1362 .pitch_align = 8,
1363 .has_powergate = false,
1360}; 1364};
1361 1365
1362static const struct tegra_dc_soc_info tegra30_dc_soc_info = { 1366static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
@@ -1364,6 +1368,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
1364 .supports_cursor = false, 1368 .supports_cursor = false,
1365 .supports_block_linear = false, 1369 .supports_block_linear = false,
1366 .pitch_align = 8, 1370 .pitch_align = 8,
1371 .has_powergate = false,
1367}; 1372};
1368 1373
1369static const struct tegra_dc_soc_info tegra114_dc_soc_info = { 1374static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
@@ -1371,6 +1376,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
1371 .supports_cursor = false, 1376 .supports_cursor = false,
1372 .supports_block_linear = false, 1377 .supports_block_linear = false,
1373 .pitch_align = 64, 1378 .pitch_align = 64,
1379 .has_powergate = true,
1374}; 1380};
1375 1381
1376static const struct tegra_dc_soc_info tegra124_dc_soc_info = { 1382static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -1378,6 +1384,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
1378 .supports_cursor = true, 1384 .supports_cursor = true,
1379 .supports_block_linear = true, 1385 .supports_block_linear = true,
1380 .pitch_align = 64, 1386 .pitch_align = 64,
1387 .has_powergate = true,
1381}; 1388};
1382 1389
1383static const struct of_device_id tegra_dc_of_match[] = { 1390static const struct of_device_id tegra_dc_of_match[] = {
@@ -1385,6 +1392,9 @@ static const struct of_device_id tegra_dc_of_match[] = {
1385 .compatible = "nvidia,tegra124-dc", 1392 .compatible = "nvidia,tegra124-dc",
1386 .data = &tegra124_dc_soc_info, 1393 .data = &tegra124_dc_soc_info,
1387 }, { 1394 }, {
1395 .compatible = "nvidia,tegra114-dc",
1396 .data = &tegra114_dc_soc_info,
1397 }, {
1388 .compatible = "nvidia,tegra30-dc", 1398 .compatible = "nvidia,tegra30-dc",
1389 .data = &tegra30_dc_soc_info, 1399 .data = &tegra30_dc_soc_info,
1390 }, { 1400 }, {
@@ -1467,9 +1477,34 @@ static int tegra_dc_probe(struct platform_device *pdev)
1467 return PTR_ERR(dc->rst); 1477 return PTR_ERR(dc->rst);
1468 } 1478 }
1469 1479
1470 err = clk_prepare_enable(dc->clk); 1480 if (dc->soc->has_powergate) {
1471 if (err < 0) 1481 if (dc->pipe == 0)
1472 return err; 1482 dc->powergate = TEGRA_POWERGATE_DIS;
1483 else
1484 dc->powergate = TEGRA_POWERGATE_DISB;
1485
1486 err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
1487 dc->rst);
1488 if (err < 0) {
1489 dev_err(&pdev->dev, "failed to power partition: %d\n",
1490 err);
1491 return err;
1492 }
1493 } else {
1494 err = clk_prepare_enable(dc->clk);
1495 if (err < 0) {
1496 dev_err(&pdev->dev, "failed to enable clock: %d\n",
1497 err);
1498 return err;
1499 }
1500
1501 err = reset_control_deassert(dc->rst);
1502 if (err < 0) {
1503 dev_err(&pdev->dev, "failed to deassert reset: %d\n",
1504 err);
1505 return err;
1506 }
1507 }
1473 1508
1474 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1509 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1475 dc->regs = devm_ioremap_resource(&pdev->dev, regs); 1510 dc->regs = devm_ioremap_resource(&pdev->dev, regs);
@@ -1523,6 +1558,10 @@ static int tegra_dc_remove(struct platform_device *pdev)
1523 } 1558 }
1524 1559
1525 reset_control_assert(dc->rst); 1560 reset_control_assert(dc->rst);
1561
1562 if (dc->soc->has_powergate)
1563 tegra_powergate_power_off(dc->powergate);
1564
1526 clk_disable_unprepare(dc->clk); 1565 clk_disable_unprepare(dc->clk);
1527 1566
1528 return 0; 1567 return 0;
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index e89c70fa82d5..b994c017971d 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -101,6 +101,7 @@ struct tegra_dc {
101 spinlock_t lock; 101 spinlock_t lock;
102 102
103 struct drm_crtc base; 103 struct drm_crtc base;
104 int powergate;
104 int pipe; 105 int pipe;
105 106
106 struct clk *clk; 107 struct clk *clk;