]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/tegra/dc.c
drm/tegra: dc: Add powergate support
[karo-tx-linux.git] / drivers / gpu / drm / tegra / dc.c
index 6553fd238685e459deb0676114bfd9cac04f7e50..4a015232e2e8238275e838d0536141ec96ea023e 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/debugfs.h>
 #include <linux/reset.h>
 
+#include <soc/tegra/pmc.h>
+
 #include "dc.h"
 #include "drm.h"
 #include "gem.h"
@@ -20,6 +22,7 @@ struct tegra_dc_soc_info {
        bool supports_cursor;
        bool supports_block_linear;
        unsigned int pitch_align;
+       bool has_powergate;
 };
 
 struct tegra_plane {
@@ -1357,6 +1360,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
        .supports_cursor = false,
        .supports_block_linear = false,
        .pitch_align = 8,
+       .has_powergate = false,
 };
 
 static 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 = {
        .supports_cursor = false,
        .supports_block_linear = false,
        .pitch_align = 8,
+       .has_powergate = false,
 };
 
 static 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 = {
        .supports_cursor = false,
        .supports_block_linear = false,
        .pitch_align = 64,
+       .has_powergate = true,
 };
 
 static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
@@ -1378,12 +1384,16 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
        .supports_cursor = true,
        .supports_block_linear = true,
        .pitch_align = 64,
+       .has_powergate = true,
 };
 
 static const struct of_device_id tegra_dc_of_match[] = {
        {
                .compatible = "nvidia,tegra124-dc",
                .data = &tegra124_dc_soc_info,
+       }, {
+               .compatible = "nvidia,tegra114-dc",
+               .data = &tegra114_dc_soc_info,
        }, {
                .compatible = "nvidia,tegra30-dc",
                .data = &tegra30_dc_soc_info,
@@ -1467,9 +1477,34 @@ static int tegra_dc_probe(struct platform_device *pdev)
                return PTR_ERR(dc->rst);
        }
 
-       err = clk_prepare_enable(dc->clk);
-       if (err < 0)
-               return err;
+       if (dc->soc->has_powergate) {
+               if (dc->pipe == 0)
+                       dc->powergate = TEGRA_POWERGATE_DIS;
+               else
+                       dc->powergate = TEGRA_POWERGATE_DISB;
+
+               err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
+                                                       dc->rst);
+               if (err < 0) {
+                       dev_err(&pdev->dev, "failed to power partition: %d\n",
+                               err);
+                       return err;
+               }
+       } else {
+               err = clk_prepare_enable(dc->clk);
+               if (err < 0) {
+                       dev_err(&pdev->dev, "failed to enable clock: %d\n",
+                               err);
+                       return err;
+               }
+
+               err = reset_control_deassert(dc->rst);
+               if (err < 0) {
+                       dev_err(&pdev->dev, "failed to deassert reset: %d\n",
+                               err);
+                       return err;
+               }
+       }
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dc->regs = devm_ioremap_resource(&pdev->dev, regs);
@@ -1523,6 +1558,10 @@ static int tegra_dc_remove(struct platform_device *pdev)
        }
 
        reset_control_assert(dc->rst);
+
+       if (dc->soc->has_powergate)
+               tegra_powergate_power_off(dc->powergate);
+
        clk_disable_unprepare(dc->clk);
 
        return 0;