aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra/dsi.c
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2015-08-07 03:29:54 -0400
committerThierry Reding <treding@nvidia.com>2016-07-04 05:37:00 -0400
commitef8187d752650fe79239c5de9efc906cb7f6b30d (patch)
tree7f704924cb03f038f04462000dad4bc41afe4366 /drivers/gpu/drm/tegra/dsi.c
parent33a8eb8d40ee7fc07f23a407607bdbaa46893b2d (diff)
drm/tegra: dsi: Implement runtime PM
Use runtime PM to clock-(un)gate, (de)assert reset and control power to the DSI 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/dsi.c')
-rw-r--r--drivers/gpu/drm/tegra/dsi.c235
1 files changed, 132 insertions, 103 deletions
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index d1239ebc190f..7e75215a9de4 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -13,6 +13,7 @@
13#include <linux/of.h> 13#include <linux/of.h>
14#include <linux/of_platform.h> 14#include <linux/of_platform.h>
15#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/pm_runtime.h>
16#include <linux/reset.h> 17#include <linux/reset.h>
17 18
18#include <linux/regulator/consumer.h> 19#include <linux/regulator/consumer.h>
@@ -677,6 +678,45 @@ static void tegra_dsi_ganged_disable(struct tegra_dsi *dsi)
677 tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); 678 tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL);
678} 679}
679 680
681static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
682{
683 u32 value;
684
685 value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
686 tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
687
688 return 0;
689}
690
691static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
692{
693 u32 value;
694
695 /*
696 * XXX Is this still needed? The module reset is deasserted right
697 * before this function is called.
698 */
699 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
700 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
701 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
702 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
703 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
704
705 /* start calibration */
706 tegra_dsi_pad_enable(dsi);
707
708 value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
709 DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
710 DSI_PAD_OUT_CLK(0x0);
711 tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
712
713 value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
714 DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
715 tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
716
717 return tegra_mipi_calibrate(dsi->mipi);
718}
719
680static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk, 720static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk,
681 unsigned int vrefresh) 721 unsigned int vrefresh)
682{ 722{
@@ -837,7 +877,7 @@ static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
837 877
838 tegra_dsi_disable(dsi); 878 tegra_dsi_disable(dsi);
839 879
840 return; 880 pm_runtime_put(dsi->dev);
841} 881}
842 882
843static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) 883static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
@@ -848,6 +888,13 @@ static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
848 struct tegra_dsi *dsi = to_dsi(output); 888 struct tegra_dsi *dsi = to_dsi(output);
849 struct tegra_dsi_state *state; 889 struct tegra_dsi_state *state;
850 u32 value; 890 u32 value;
891 int err;
892
893 pm_runtime_get_sync(dsi->dev);
894
895 err = tegra_dsi_pad_calibrate(dsi);
896 if (err < 0)
897 dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
851 898
852 state = tegra_dsi_get_state(dsi); 899 state = tegra_dsi_get_state(dsi);
853 900
@@ -876,8 +923,6 @@ static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
876 923
877 if (output->panel) 924 if (output->panel)
878 drm_panel_enable(output->panel); 925 drm_panel_enable(output->panel);
879
880 return;
881} 926}
882 927
883static int 928static int
@@ -967,55 +1012,12 @@ static const struct drm_encoder_helper_funcs tegra_dsi_encoder_helper_funcs = {
967 .atomic_check = tegra_dsi_encoder_atomic_check, 1012 .atomic_check = tegra_dsi_encoder_atomic_check,
968}; 1013};
969 1014
970static int tegra_dsi_pad_enable(struct tegra_dsi *dsi)
971{
972 u32 value;
973
974 value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0);
975 tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0);
976
977 return 0;
978}
979
980static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi)
981{
982 u32 value;
983
984 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0);
985 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1);
986 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2);
987 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3);
988 tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4);
989
990 /* start calibration */
991 tegra_dsi_pad_enable(dsi);
992
993 value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) |
994 DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) |
995 DSI_PAD_OUT_CLK(0x0);
996 tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2);
997
998 value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) |
999 DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3);
1000 tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3);
1001
1002 return tegra_mipi_calibrate(dsi->mipi);
1003}
1004
1005static int tegra_dsi_init(struct host1x_client *client) 1015static int tegra_dsi_init(struct host1x_client *client)
1006{ 1016{
1007 struct drm_device *drm = dev_get_drvdata(client->parent); 1017 struct drm_device *drm = dev_get_drvdata(client->parent);
1008 struct tegra_dsi *dsi = host1x_client_to_dsi(client); 1018 struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1009 int err; 1019 int err;
1010 1020
1011 reset_control_deassert(dsi->rst);
1012
1013 err = tegra_dsi_pad_calibrate(dsi);
1014 if (err < 0) {
1015 dev_err(dsi->dev, "MIPI calibration failed: %d\n", err);
1016 goto reset;
1017 }
1018
1019 /* Gangsters must not register their own outputs. */ 1021 /* Gangsters must not register their own outputs. */
1020 if (!dsi->master) { 1022 if (!dsi->master) {
1021 dsi->output.dev = client->dev; 1023 dsi->output.dev = client->dev;
@@ -1038,12 +1040,9 @@ static int tegra_dsi_init(struct host1x_client *client)
1038 drm_connector_register(&dsi->output.connector); 1040 drm_connector_register(&dsi->output.connector);
1039 1041
1040 err = tegra_output_init(drm, &dsi->output); 1042 err = tegra_output_init(drm, &dsi->output);
1041 if (err < 0) { 1043 if (err < 0)
1042 dev_err(client->dev, 1044 dev_err(dsi->dev, "failed to initialize output: %d\n",
1043 "failed to initialize output: %d\n",
1044 err); 1045 err);
1045 goto reset;
1046 }
1047 1046
1048 dsi->output.encoder.possible_crtcs = 0x3; 1047 dsi->output.encoder.possible_crtcs = 0x3;
1049 } 1048 }
@@ -1055,10 +1054,6 @@ static int tegra_dsi_init(struct host1x_client *client)
1055 } 1054 }
1056 1055
1057 return 0; 1056 return 0;
1058
1059reset:
1060 reset_control_assert(dsi->rst);
1061 return err;
1062} 1057}
1063 1058
1064static int tegra_dsi_exit(struct host1x_client *client) 1059static int tegra_dsi_exit(struct host1x_client *client)
@@ -1070,7 +1065,7 @@ static int tegra_dsi_exit(struct host1x_client *client)
1070 if (IS_ENABLED(CONFIG_DEBUG_FS)) 1065 if (IS_ENABLED(CONFIG_DEBUG_FS))
1071 tegra_dsi_debugfs_exit(dsi); 1066 tegra_dsi_debugfs_exit(dsi);
1072 1067
1073 reset_control_assert(dsi->rst); 1068 regulator_disable(dsi->vdd);
1074 1069
1075 return 0; 1070 return 0;
1076} 1071}
@@ -1501,67 +1496,41 @@ static int tegra_dsi_probe(struct platform_device *pdev)
1501 dsi->clk = devm_clk_get(&pdev->dev, NULL); 1496 dsi->clk = devm_clk_get(&pdev->dev, NULL);
1502 if (IS_ERR(dsi->clk)) { 1497 if (IS_ERR(dsi->clk)) {
1503 dev_err(&pdev->dev, "cannot get DSI clock\n"); 1498 dev_err(&pdev->dev, "cannot get DSI clock\n");
1504 err = PTR_ERR(dsi->clk); 1499 return PTR_ERR(dsi->clk);
1505 goto reset;
1506 }
1507
1508 err = clk_prepare_enable(dsi->clk);
1509 if (err < 0) {
1510 dev_err(&pdev->dev, "cannot enable DSI clock\n");
1511 goto reset;
1512 } 1500 }
1513 1501
1514 dsi->clk_lp = devm_clk_get(&pdev->dev, "lp"); 1502 dsi->clk_lp = devm_clk_get(&pdev->dev, "lp");
1515 if (IS_ERR(dsi->clk_lp)) { 1503 if (IS_ERR(dsi->clk_lp)) {
1516 dev_err(&pdev->dev, "cannot get low-power clock\n"); 1504 dev_err(&pdev->dev, "cannot get low-power clock\n");
1517 err = PTR_ERR(dsi->clk_lp); 1505 return PTR_ERR(dsi->clk_lp);
1518 goto disable_clk;
1519 }
1520
1521 err = clk_prepare_enable(dsi->clk_lp);
1522 if (err < 0) {
1523 dev_err(&pdev->dev, "cannot enable low-power clock\n");
1524 goto disable_clk;
1525 } 1506 }
1526 1507
1527 dsi->clk_parent = devm_clk_get(&pdev->dev, "parent"); 1508 dsi->clk_parent = devm_clk_get(&pdev->dev, "parent");
1528 if (IS_ERR(dsi->clk_parent)) { 1509 if (IS_ERR(dsi->clk_parent)) {
1529 dev_err(&pdev->dev, "cannot get parent clock\n"); 1510 dev_err(&pdev->dev, "cannot get parent clock\n");
1530 err = PTR_ERR(dsi->clk_parent); 1511 return PTR_ERR(dsi->clk_parent);
1531 goto disable_clk_lp;
1532 } 1512 }
1533 1513
1534 dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi"); 1514 dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
1535 if (IS_ERR(dsi->vdd)) { 1515 if (IS_ERR(dsi->vdd)) {
1536 dev_err(&pdev->dev, "cannot get VDD supply\n"); 1516 dev_err(&pdev->dev, "cannot get VDD supply\n");
1537 err = PTR_ERR(dsi->vdd); 1517 return PTR_ERR(dsi->vdd);
1538 goto disable_clk_lp;
1539 }
1540
1541 err = regulator_enable(dsi->vdd);
1542 if (err < 0) {
1543 dev_err(&pdev->dev, "cannot enable VDD supply\n");
1544 goto disable_clk_lp;
1545 } 1518 }
1546 1519
1547 err = tegra_dsi_setup_clocks(dsi); 1520 err = tegra_dsi_setup_clocks(dsi);
1548 if (err < 0) { 1521 if (err < 0) {
1549 dev_err(&pdev->dev, "cannot setup clocks\n"); 1522 dev_err(&pdev->dev, "cannot setup clocks\n");
1550 goto disable_vdd; 1523 return err;
1551 } 1524 }
1552 1525
1553 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1526 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1554 dsi->regs = devm_ioremap_resource(&pdev->dev, regs); 1527 dsi->regs = devm_ioremap_resource(&pdev->dev, regs);
1555 if (IS_ERR(dsi->regs)) { 1528 if (IS_ERR(dsi->regs))
1556 err = PTR_ERR(dsi->regs); 1529 return PTR_ERR(dsi->regs);
1557 goto disable_vdd;
1558 }
1559 1530
1560 dsi->mipi = tegra_mipi_request(&pdev->dev); 1531 dsi->mipi = tegra_mipi_request(&pdev->dev);
1561 if (IS_ERR(dsi->mipi)) { 1532 if (IS_ERR(dsi->mipi))
1562 err = PTR_ERR(dsi->mipi); 1533 return PTR_ERR(dsi->mipi);
1563 goto disable_vdd;
1564 }
1565 1534
1566 dsi->host.ops = &tegra_dsi_host_ops; 1535 dsi->host.ops = &tegra_dsi_host_ops;
1567 dsi->host.dev = &pdev->dev; 1536 dsi->host.dev = &pdev->dev;
@@ -1572,6 +1541,9 @@ static int tegra_dsi_probe(struct platform_device *pdev)
1572 goto mipi_free; 1541 goto mipi_free;
1573 } 1542 }
1574 1543
1544 platform_set_drvdata(pdev, dsi);
1545 pm_runtime_enable(&pdev->dev);
1546
1575 INIT_LIST_HEAD(&dsi->client.list); 1547 INIT_LIST_HEAD(&dsi->client.list);
1576 dsi->client.ops = &dsi_client_ops; 1548 dsi->client.ops = &dsi_client_ops;
1577 dsi->client.dev = &pdev->dev; 1549 dsi->client.dev = &pdev->dev;
@@ -1583,22 +1555,12 @@ static int tegra_dsi_probe(struct platform_device *pdev)
1583 goto unregister; 1555 goto unregister;
1584 } 1556 }
1585 1557
1586 platform_set_drvdata(pdev, dsi);
1587
1588 return 0; 1558 return 0;
1589 1559
1590unregister: 1560unregister:
1591 mipi_dsi_host_unregister(&dsi->host); 1561 mipi_dsi_host_unregister(&dsi->host);
1592mipi_free: 1562mipi_free:
1593 tegra_mipi_free(dsi->mipi); 1563 tegra_mipi_free(dsi->mipi);
1594disable_vdd:
1595 regulator_disable(dsi->vdd);
1596disable_clk_lp:
1597 clk_disable_unprepare(dsi->clk_lp);
1598disable_clk:
1599 clk_disable_unprepare(dsi->clk);
1600reset:
1601 reset_control_assert(dsi->rst);
1602 return err; 1564 return err;
1603} 1565}
1604 1566
@@ -1607,6 +1569,8 @@ static int tegra_dsi_remove(struct platform_device *pdev)
1607 struct tegra_dsi *dsi = platform_get_drvdata(pdev); 1569 struct tegra_dsi *dsi = platform_get_drvdata(pdev);
1608 int err; 1570 int err;
1609 1571
1572 pm_runtime_disable(&pdev->dev);
1573
1610 err = host1x_client_unregister(&dsi->client); 1574 err = host1x_client_unregister(&dsi->client);
1611 if (err < 0) { 1575 if (err < 0) {
1612 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n", 1576 dev_err(&pdev->dev, "failed to unregister host1x client: %d\n",
@@ -1619,14 +1583,78 @@ static int tegra_dsi_remove(struct platform_device *pdev)
1619 mipi_dsi_host_unregister(&dsi->host); 1583 mipi_dsi_host_unregister(&dsi->host);
1620 tegra_mipi_free(dsi->mipi); 1584 tegra_mipi_free(dsi->mipi);
1621 1585
1622 regulator_disable(dsi->vdd); 1586 return 0;
1587}
1588
1589#ifdef CONFIG_PM
1590static int tegra_dsi_suspend(struct device *dev)
1591{
1592 struct tegra_dsi *dsi = dev_get_drvdata(dev);
1593 int err;
1594
1595 err = reset_control_assert(dsi->rst);
1596 if (err < 0) {
1597 dev_err(dev, "failed to assert reset: %d\n", err);
1598 return err;
1599 }
1600
1601 usleep_range(1000, 2000);
1602
1623 clk_disable_unprepare(dsi->clk_lp); 1603 clk_disable_unprepare(dsi->clk_lp);
1624 clk_disable_unprepare(dsi->clk); 1604 clk_disable_unprepare(dsi->clk);
1625 reset_control_assert(dsi->rst); 1605
1606 regulator_disable(dsi->vdd);
1626 1607
1627 return 0; 1608 return 0;
1628} 1609}
1629 1610
1611static int tegra_dsi_resume(struct device *dev)
1612{
1613 struct tegra_dsi *dsi = dev_get_drvdata(dev);
1614 int err;
1615
1616 err = regulator_enable(dsi->vdd);
1617 if (err < 0) {
1618 dev_err(dsi->dev, "failed to enable VDD supply: %d\n", err);
1619 return err;
1620 }
1621
1622 err = clk_prepare_enable(dsi->clk);
1623 if (err < 0) {
1624 dev_err(dev, "cannot enable DSI clock: %d\n", err);
1625 goto disable_vdd;
1626 }
1627
1628 err = clk_prepare_enable(dsi->clk_lp);
1629 if (err < 0) {
1630 dev_err(dev, "cannot enable low-power clock: %d\n", err);
1631 goto disable_clk;
1632 }
1633
1634 usleep_range(1000, 2000);
1635
1636 err = reset_control_deassert(dsi->rst);
1637 if (err < 0) {
1638 dev_err(dev, "cannot assert reset: %d\n", err);
1639 goto disable_clk_lp;
1640 }
1641
1642 return 0;
1643
1644disable_clk_lp:
1645 clk_disable_unprepare(dsi->clk_lp);
1646disable_clk:
1647 clk_disable_unprepare(dsi->clk);
1648disable_vdd:
1649 regulator_disable(dsi->vdd);
1650 return err;
1651}
1652#endif
1653
1654static const struct dev_pm_ops tegra_dsi_pm_ops = {
1655 SET_RUNTIME_PM_OPS(tegra_dsi_suspend, tegra_dsi_resume, NULL)
1656};
1657
1630static const struct of_device_id tegra_dsi_of_match[] = { 1658static const struct of_device_id tegra_dsi_of_match[] = {
1631 { .compatible = "nvidia,tegra210-dsi", }, 1659 { .compatible = "nvidia,tegra210-dsi", },
1632 { .compatible = "nvidia,tegra132-dsi", }, 1660 { .compatible = "nvidia,tegra132-dsi", },
@@ -1640,6 +1668,7 @@ struct platform_driver tegra_dsi_driver = {
1640 .driver = { 1668 .driver = {
1641 .name = "tegra-dsi", 1669 .name = "tegra-dsi",
1642 .of_match_table = tegra_dsi_of_match, 1670 .of_match_table = tegra_dsi_of_match,
1671 .pm = &tegra_dsi_pm_ops,
1643 }, 1672 },
1644 .probe = tegra_dsi_probe, 1673 .probe = tegra_dsi_probe,
1645 .remove = tegra_dsi_remove, 1674 .remove = tegra_dsi_remove,