aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2015-08-07 10:00:43 -0400
committerThierry Reding <treding@nvidia.com>2016-07-04 05:38:11 -0400
commit5234549b93aa2ada9ee3d628b0e06bf291d97577 (patch)
tree711bb1bd3e0b63901de390cc0a4ec3698b262f3b /drivers/gpu/drm/tegra
parentef8187d752650fe79239c5de9efc906cb7f6b30d (diff)
drm/tegra: hdmi: Implement runtime PM
Use runtime PM to clock-(un)gate and (de)assert reset to the HDMI controller. This ties in nicely with atomic DPMS in that a runtime PM reference is taken before a pipe is enabled and dropped after it has been shut down. Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c135
1 files changed, 88 insertions, 47 deletions
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 529768d977b8..db90ec782f53 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -11,6 +11,7 @@
11#include <linux/debugfs.h> 11#include <linux/debugfs.h>
12#include <linux/gpio.h> 12#include <linux/gpio.h>
13#include <linux/hdmi.h> 13#include <linux/hdmi.h>
14#include <linux/pm_runtime.h>
14#include <linux/regulator/consumer.h> 15#include <linux/regulator/consumer.h>
15#include <linux/reset.h> 16#include <linux/reset.h>
16 17
@@ -641,6 +642,29 @@ static void tegra_hdmi_enable_audio(struct tegra_hdmi *hdmi)
641 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL); 642 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_HDMI_GENERIC_CTRL);
642} 643}
643 644
645static void tegra_hdmi_write_eld(struct tegra_hdmi *hdmi)
646{
647 size_t length = drm_eld_size(hdmi->output.connector.eld), i;
648 u32 value;
649
650 for (i = 0; i < length; i++)
651 tegra_hdmi_writel(hdmi, i << 8 | hdmi->output.connector.eld[i],
652 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
653
654 /*
655 * The HDA codec will always report an ELD buffer size of 96 bytes and
656 * the HDA codec driver will check that each byte read from the buffer
657 * is valid. Therefore every byte must be written, even if no 96 bytes
658 * were parsed from EDID.
659 */
660 for (i = length; i < HDMI_ELD_BUFFER_SIZE; i++)
661 tegra_hdmi_writel(hdmi, i << 8 | 0,
662 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
663
664 value = SOR_AUDIO_HDA_PRESENSE_VALID | SOR_AUDIO_HDA_PRESENSE_PRESENT;
665 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
666}
667
644static inline u32 tegra_hdmi_subpack(const u8 *ptr, size_t size) 668static inline u32 tegra_hdmi_subpack(const u8 *ptr, size_t size)
645{ 669{
646 u32 value = 0; 670 u32 value = 0;
@@ -945,29 +969,11 @@ static void tegra_hdmi_encoder_disable(struct drm_encoder *encoder)
945 tegra_hdmi_disable_avi_infoframe(hdmi); 969 tegra_hdmi_disable_avi_infoframe(hdmi);
946 tegra_hdmi_disable_audio(hdmi); 970 tegra_hdmi_disable_audio(hdmi);
947 } 971 }
948}
949
950static void tegra_hdmi_write_eld(struct tegra_hdmi *hdmi)
951{
952 size_t length = drm_eld_size(hdmi->output.connector.eld), i;
953 u32 value;
954 972
955 for (i = 0; i < length; i++) 973 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_ENABLE);
956 tegra_hdmi_writel(hdmi, i << 8 | hdmi->output.connector.eld[i], 974 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_MASK);
957 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
958
959 /*
960 * The HDA codec will always report an ELD buffer size of 96 bytes and
961 * the HDA codec driver will check that each byte read from the buffer
962 * is valid. Therefore every byte must be written, even if no 96 bytes
963 * were parsed from EDID.
964 */
965 for (i = length; i < HDMI_ELD_BUFFER_SIZE; i++)
966 tegra_hdmi_writel(hdmi, i << 8 | 0,
967 HDMI_NV_PDISP_SOR_AUDIO_HDA_ELD_BUFWR);
968 975
969 value = SOR_AUDIO_HDA_PRESENSE_VALID | SOR_AUDIO_HDA_PRESENSE_PRESENT; 976 pm_runtime_put(hdmi->dev);
970 tegra_hdmi_writel(hdmi, value, HDMI_NV_PDISP_SOR_AUDIO_HDA_PRESENSE);
971} 977}
972 978
973static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder) 979static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder)
@@ -982,6 +988,16 @@ static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder)
982 u32 value; 988 u32 value;
983 int err; 989 int err;
984 990
991 pm_runtime_get_sync(hdmi->dev);
992
993 /*
994 * Enable and unmask the HDA codec SCRATCH0 register interrupt. This
995 * is used for interoperability between the HDA codec driver and the
996 * HDMI driver.
997 */
998 tegra_hdmi_writel(hdmi, INT_CODEC_SCRATCH0, HDMI_NV_PDISP_INT_ENABLE);
999 tegra_hdmi_writel(hdmi, INT_CODEC_SCRATCH0, HDMI_NV_PDISP_INT_MASK);
1000
985 hdmi->pixel_clock = mode->clock * 1000; 1001 hdmi->pixel_clock = mode->clock * 1000;
986 h_sync_width = mode->hsync_end - mode->hsync_start; 1002 h_sync_width = mode->hsync_end - mode->hsync_start;
987 h_back_porch = mode->htotal - mode->hsync_end; 1003 h_back_porch = mode->htotal - mode->hsync_end;
@@ -1507,22 +1523,6 @@ static int tegra_hdmi_init(struct host1x_client *client)
1507 return err; 1523 return err;
1508 } 1524 }
1509 1525
1510 err = clk_prepare_enable(hdmi->clk);
1511 if (err < 0) {
1512 dev_err(hdmi->dev, "failed to enable clock: %d\n", err);
1513 return err;
1514 }
1515
1516 reset_control_deassert(hdmi->rst);
1517
1518 /*
1519 * Enable and unmask the HDA codec SCRATCH0 register interrupt. This
1520 * is used for interoperability between the HDA codec driver and the
1521 * HDMI driver.
1522 */
1523 tegra_hdmi_writel(hdmi, INT_CODEC_SCRATCH0, HDMI_NV_PDISP_INT_ENABLE);
1524 tegra_hdmi_writel(hdmi, INT_CODEC_SCRATCH0, HDMI_NV_PDISP_INT_MASK);
1525
1526 return 0; 1526 return 0;
1527} 1527}
1528 1528
@@ -1530,14 +1530,8 @@ static int tegra_hdmi_exit(struct host1x_client *client)
1530{ 1530{
1531 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client); 1531 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1532 1532
1533 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_MASK);
1534 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_ENABLE);
1535
1536 tegra_output_exit(&hdmi->output); 1533 tegra_output_exit(&hdmi->output);
1537 1534
1538 reset_control_assert(hdmi->rst);
1539 clk_disable_unprepare(hdmi->clk);
1540
1541 regulator_disable(hdmi->vdd); 1535 regulator_disable(hdmi->vdd);
1542 regulator_disable(hdmi->pll); 1536 regulator_disable(hdmi->pll);
1543 regulator_disable(hdmi->hdmi); 1537 regulator_disable(hdmi->hdmi);
@@ -1752,6 +1746,9 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
1752 return err; 1746 return err;
1753 } 1747 }
1754 1748
1749 platform_set_drvdata(pdev, hdmi);
1750 pm_runtime_enable(&pdev->dev);
1751
1755 INIT_LIST_HEAD(&hdmi->client.list); 1752 INIT_LIST_HEAD(&hdmi->client.list);
1756 hdmi->client.ops = &hdmi_client_ops; 1753 hdmi->client.ops = &hdmi_client_ops;
1757 hdmi->client.dev = &pdev->dev; 1754 hdmi->client.dev = &pdev->dev;
@@ -1763,8 +1760,6 @@ static int tegra_hdmi_probe(struct platform_device *pdev)
1763 return err; 1760 return err;
1764 } 1761 }
1765 1762
1766 platform_set_drvdata(pdev, hdmi);
1767
1768 return 0; 1763 return 0;
1769} 1764}
1770 1765
@@ -1773,6 +1768,8 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
1773 struct tegra_hdmi *hdmi = platform_get_drvdata(pdev); 1768 struct tegra_hdmi *hdmi = platform_get_drvdata(pdev);
1774 int err; 1769 int err;
1775 1770
1771 pm_runtime_disable(&pdev->dev);
1772
1776 err = host1x_client_unregister(&hdmi->client); 1773 err = host1x_client_unregister(&hdmi->client);
1777 if (err < 0) { 1774 if (err < 0) {
1778 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 1775 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
@@ -1782,17 +1779,61 @@ static int tegra_hdmi_remove(struct platform_device *pdev)
1782 1779
1783 tegra_output_remove(&hdmi->output); 1780 tegra_output_remove(&hdmi->output);
1784 1781
1785 clk_disable_unprepare(hdmi->clk_parent); 1782 return 0;
1783}
1784
1785#ifdef CONFIG_PM
1786static int tegra_hdmi_suspend(struct device *dev)
1787{
1788 struct tegra_hdmi *hdmi = dev_get_drvdata(dev);
1789 int err;
1790
1791 err = reset_control_assert(hdmi->rst);
1792 if (err < 0) {
1793 dev_err(dev, "failed to assert reset: %d\n", err);
1794 return err;
1795 }
1796
1797 usleep_range(1000, 2000);
1798
1786 clk_disable_unprepare(hdmi->clk); 1799 clk_disable_unprepare(hdmi->clk);
1787 1800
1788 return 0; 1801 return 0;
1789} 1802}
1790 1803
1804static int tegra_hdmi_resume(struct device *dev)
1805{
1806 struct tegra_hdmi *hdmi = dev_get_drvdata(dev);
1807 int err;
1808
1809 err = clk_prepare_enable(hdmi->clk);
1810 if (err < 0) {
1811 dev_err(dev, "failed to enable clock: %d\n", err);
1812 return err;
1813 }
1814
1815 usleep_range(1000, 2000);
1816
1817 err = reset_control_deassert(hdmi->rst);
1818 if (err < 0) {
1819 dev_err(dev, "failed to deassert reset: %d\n", err);
1820 clk_disable_unprepare(hdmi->clk);
1821 return err;
1822 }
1823
1824 return 0;
1825}
1826#endif
1827
1828static const struct dev_pm_ops tegra_hdmi_pm_ops = {
1829 SET_RUNTIME_PM_OPS(tegra_hdmi_suspend, tegra_hdmi_resume, NULL)
1830};
1831
1791struct platform_driver tegra_hdmi_driver = { 1832struct platform_driver tegra_hdmi_driver = {
1792 .driver = { 1833 .driver = {
1793 .name = "tegra-hdmi", 1834 .name = "tegra-hdmi",
1794 .owner = THIS_MODULE,
1795 .of_match_table = tegra_hdmi_of_match, 1835 .of_match_table = tegra_hdmi_of_match,
1836 .pm = &tegra_hdmi_pm_ops,
1796 }, 1837 },
1797 .probe = tegra_hdmi_probe, 1838 .probe = tegra_hdmi_probe,
1798 .remove = tegra_hdmi_remove, 1839 .remove = tegra_hdmi_remove,