Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+132 -103
+132 -103
drivers/gpu/drm/tegra/dsi.c
··· 13 13 #include <linux/of.h> 14 14 #include <linux/of_platform.h> 15 15 #include <linux/platform_device.h> 16 + #include <linux/pm_runtime.h> 16 17 #include <linux/reset.h> 17 18 18 19 #include <linux/regulator/consumer.h> ··· 678 677 tegra_dsi_writel(dsi, 0, DSI_GANGED_MODE_CONTROL); 679 678 } 680 679 680 + static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) 681 + { 682 + u32 value; 683 + 684 + value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); 685 + tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0); 686 + 687 + return 0; 688 + } 689 + 690 + static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) 691 + { 692 + u32 value; 693 + 694 + /* 695 + * XXX Is this still needed? The module reset is deasserted right 696 + * before this function is called. 697 + */ 698 + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0); 699 + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); 700 + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); 701 + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); 702 + tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); 703 + 704 + /* start calibration */ 705 + tegra_dsi_pad_enable(dsi); 706 + 707 + value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | 708 + DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | 709 + DSI_PAD_OUT_CLK(0x0); 710 + tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); 711 + 712 + value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | 713 + DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); 714 + tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3); 715 + 716 + return tegra_mipi_calibrate(dsi->mipi); 717 + } 718 + 681 719 static void tegra_dsi_set_timeout(struct tegra_dsi *dsi, unsigned long bclk, 682 720 unsigned int vrefresh) 683 721 { ··· 877 837 878 838 tegra_dsi_disable(dsi); 879 839 880 - return; 840 + pm_runtime_put(dsi->dev); 881 841 } 882 842 883 843 static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) ··· 888 848 struct tegra_dsi *dsi = to_dsi(output); 889 849 struct tegra_dsi_state *state; 890 850 u32 value; 851 + int err; 852 + 853 + pm_runtime_get_sync(dsi->dev); 854 + 855 + err = tegra_dsi_pad_calibrate(dsi); 856 + if (err < 0) 857 + dev_err(dsi->dev, "MIPI calibration failed: %d\n", err); 891 858 892 859 state = tegra_dsi_get_state(dsi); 893 860 ··· 923 876 924 877 if (output->panel) 925 878 drm_panel_enable(output->panel); 926 - 927 - return; 928 879 } 929 880 930 881 static int ··· 1012 967 .atomic_check = tegra_dsi_encoder_atomic_check, 1013 968 }; 1014 969 1015 - static int tegra_dsi_pad_enable(struct tegra_dsi *dsi) 1016 - { 1017 - u32 value; 1018 - 1019 - value = DSI_PAD_CONTROL_VS1_PULLDN(0) | DSI_PAD_CONTROL_VS1_PDIO(0); 1020 - tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_0); 1021 - 1022 - return 0; 1023 - } 1024 - 1025 - static int tegra_dsi_pad_calibrate(struct tegra_dsi *dsi) 1026 - { 1027 - u32 value; 1028 - 1029 - tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_0); 1030 - tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_1); 1031 - tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_2); 1032 - tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_3); 1033 - tegra_dsi_writel(dsi, 0, DSI_PAD_CONTROL_4); 1034 - 1035 - /* start calibration */ 1036 - tegra_dsi_pad_enable(dsi); 1037 - 1038 - value = DSI_PAD_SLEW_UP(0x7) | DSI_PAD_SLEW_DN(0x7) | 1039 - DSI_PAD_LP_UP(0x1) | DSI_PAD_LP_DN(0x1) | 1040 - DSI_PAD_OUT_CLK(0x0); 1041 - tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_2); 1042 - 1043 - value = DSI_PAD_PREEMP_PD_CLK(0x3) | DSI_PAD_PREEMP_PU_CLK(0x3) | 1044 - DSI_PAD_PREEMP_PD(0x03) | DSI_PAD_PREEMP_PU(0x3); 1045 - tegra_dsi_writel(dsi, value, DSI_PAD_CONTROL_3); 1046 - 1047 - return tegra_mipi_calibrate(dsi->mipi); 1048 - } 1049 - 1050 970 static int tegra_dsi_init(struct host1x_client *client) 1051 971 { 1052 972 struct drm_device *drm = dev_get_drvdata(client->parent); 1053 973 struct tegra_dsi *dsi = host1x_client_to_dsi(client); 1054 974 int err; 1055 - 1056 - reset_control_deassert(dsi->rst); 1057 - 1058 - err = tegra_dsi_pad_calibrate(dsi); 1059 - if (err < 0) { 1060 - dev_err(dsi->dev, "MIPI calibration failed: %d\n", err); 1061 - goto reset; 1062 - } 1063 975 1064 976 /* Gangsters must not register their own outputs. */ 1065 977 if (!dsi->master) { ··· 1040 1038 drm_connector_register(&dsi->output.connector); 1041 1039 1042 1040 err = tegra_output_init(drm, &dsi->output); 1043 - if (err < 0) { 1044 - dev_err(client->dev, 1045 - "failed to initialize output: %d\n", 1041 + if (err < 0) 1042 + dev_err(dsi->dev, "failed to initialize output: %d\n", 1046 1043 err); 1047 - goto reset; 1048 - } 1049 1044 1050 1045 dsi->output.encoder.possible_crtcs = 0x3; 1051 1046 } ··· 1054 1055 } 1055 1056 1056 1057 return 0; 1057 - 1058 - reset: 1059 - reset_control_assert(dsi->rst); 1060 - return err; 1061 1058 } 1062 1059 1063 1060 static int tegra_dsi_exit(struct host1x_client *client) ··· 1065 1070 if (IS_ENABLED(CONFIG_DEBUG_FS)) 1066 1071 tegra_dsi_debugfs_exit(dsi); 1067 1072 1068 - reset_control_assert(dsi->rst); 1073 + regulator_disable(dsi->vdd); 1069 1074 1070 1075 return 0; 1071 1076 } ··· 1496 1501 dsi->clk = devm_clk_get(&pdev->dev, NULL); 1497 1502 if (IS_ERR(dsi->clk)) { 1498 1503 dev_err(&pdev->dev, "cannot get DSI clock\n"); 1499 - err = PTR_ERR(dsi->clk); 1500 - goto reset; 1501 - } 1502 - 1503 - err = clk_prepare_enable(dsi->clk); 1504 - if (err < 0) { 1505 - dev_err(&pdev->dev, "cannot enable DSI clock\n"); 1506 - goto reset; 1504 + return PTR_ERR(dsi->clk); 1507 1505 } 1508 1506 1509 1507 dsi->clk_lp = devm_clk_get(&pdev->dev, "lp"); 1510 1508 if (IS_ERR(dsi->clk_lp)) { 1511 1509 dev_err(&pdev->dev, "cannot get low-power clock\n"); 1512 - err = PTR_ERR(dsi->clk_lp); 1513 - goto disable_clk; 1514 - } 1515 - 1516 - err = clk_prepare_enable(dsi->clk_lp); 1517 - if (err < 0) { 1518 - dev_err(&pdev->dev, "cannot enable low-power clock\n"); 1519 - goto disable_clk; 1510 + return PTR_ERR(dsi->clk_lp); 1520 1511 } 1521 1512 1522 1513 dsi->clk_parent = devm_clk_get(&pdev->dev, "parent"); 1523 1514 if (IS_ERR(dsi->clk_parent)) { 1524 1515 dev_err(&pdev->dev, "cannot get parent clock\n"); 1525 - err = PTR_ERR(dsi->clk_parent); 1526 - goto disable_clk_lp; 1516 + return PTR_ERR(dsi->clk_parent); 1527 1517 } 1528 1518 1529 1519 dsi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi"); 1530 1520 if (IS_ERR(dsi->vdd)) { 1531 1521 dev_err(&pdev->dev, "cannot get VDD supply\n"); 1532 - err = PTR_ERR(dsi->vdd); 1533 - goto disable_clk_lp; 1534 - } 1535 - 1536 - err = regulator_enable(dsi->vdd); 1537 - if (err < 0) { 1538 - dev_err(&pdev->dev, "cannot enable VDD supply\n"); 1539 - goto disable_clk_lp; 1522 + return PTR_ERR(dsi->vdd); 1540 1523 } 1541 1524 1542 1525 err = tegra_dsi_setup_clocks(dsi); 1543 1526 if (err < 0) { 1544 1527 dev_err(&pdev->dev, "cannot setup clocks\n"); 1545 - goto disable_vdd; 1528 + return err; 1546 1529 } 1547 1530 1548 1531 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1549 1532 dsi->regs = devm_ioremap_resource(&pdev->dev, regs); 1550 - if (IS_ERR(dsi->regs)) { 1551 - err = PTR_ERR(dsi->regs); 1552 - goto disable_vdd; 1553 - } 1533 + if (IS_ERR(dsi->regs)) 1534 + return PTR_ERR(dsi->regs); 1554 1535 1555 1536 dsi->mipi = tegra_mipi_request(&pdev->dev); 1556 - if (IS_ERR(dsi->mipi)) { 1557 - err = PTR_ERR(dsi->mipi); 1558 - goto disable_vdd; 1559 - } 1537 + if (IS_ERR(dsi->mipi)) 1538 + return PTR_ERR(dsi->mipi); 1560 1539 1561 1540 dsi->host.ops = &tegra_dsi_host_ops; 1562 1541 dsi->host.dev = &pdev->dev; ··· 1540 1571 dev_err(&pdev->dev, "failed to register DSI host: %d\n", err); 1541 1572 goto mipi_free; 1542 1573 } 1574 + 1575 + platform_set_drvdata(pdev, dsi); 1576 + pm_runtime_enable(&pdev->dev); 1543 1577 1544 1578 INIT_LIST_HEAD(&dsi->client.list); 1545 1579 dsi->client.ops = &dsi_client_ops; ··· 1555 1583 goto unregister; 1556 1584 } 1557 1585 1558 - platform_set_drvdata(pdev, dsi); 1559 - 1560 1586 return 0; 1561 1587 1562 1588 unregister: 1563 1589 mipi_dsi_host_unregister(&dsi->host); 1564 1590 mipi_free: 1565 1591 tegra_mipi_free(dsi->mipi); 1566 - disable_vdd: 1567 - regulator_disable(dsi->vdd); 1568 - disable_clk_lp: 1569 - clk_disable_unprepare(dsi->clk_lp); 1570 - disable_clk: 1571 - clk_disable_unprepare(dsi->clk); 1572 - reset: 1573 - reset_control_assert(dsi->rst); 1574 1592 return err; 1575 1593 } 1576 1594 ··· 1568 1606 { 1569 1607 struct tegra_dsi *dsi = platform_get_drvdata(pdev); 1570 1608 int err; 1609 + 1610 + pm_runtime_disable(&pdev->dev); 1571 1611 1572 1612 err = host1x_client_unregister(&dsi->client); 1573 1613 if (err < 0) { ··· 1583 1619 mipi_dsi_host_unregister(&dsi->host); 1584 1620 tegra_mipi_free(dsi->mipi); 1585 1621 1586 - regulator_disable(dsi->vdd); 1622 + return 0; 1623 + } 1624 + 1625 + #ifdef CONFIG_PM 1626 + static int tegra_dsi_suspend(struct device *dev) 1627 + { 1628 + struct tegra_dsi *dsi = dev_get_drvdata(dev); 1629 + int err; 1630 + 1631 + err = reset_control_assert(dsi->rst); 1632 + if (err < 0) { 1633 + dev_err(dev, "failed to assert reset: %d\n", err); 1634 + return err; 1635 + } 1636 + 1637 + usleep_range(1000, 2000); 1638 + 1587 1639 clk_disable_unprepare(dsi->clk_lp); 1588 1640 clk_disable_unprepare(dsi->clk); 1589 - reset_control_assert(dsi->rst); 1641 + 1642 + regulator_disable(dsi->vdd); 1590 1643 1591 1644 return 0; 1592 1645 } 1646 + 1647 + static int tegra_dsi_resume(struct device *dev) 1648 + { 1649 + struct tegra_dsi *dsi = dev_get_drvdata(dev); 1650 + int err; 1651 + 1652 + err = regulator_enable(dsi->vdd); 1653 + if (err < 0) { 1654 + dev_err(dsi->dev, "failed to enable VDD supply: %d\n", err); 1655 + return err; 1656 + } 1657 + 1658 + err = clk_prepare_enable(dsi->clk); 1659 + if (err < 0) { 1660 + dev_err(dev, "cannot enable DSI clock: %d\n", err); 1661 + goto disable_vdd; 1662 + } 1663 + 1664 + err = clk_prepare_enable(dsi->clk_lp); 1665 + if (err < 0) { 1666 + dev_err(dev, "cannot enable low-power clock: %d\n", err); 1667 + goto disable_clk; 1668 + } 1669 + 1670 + usleep_range(1000, 2000); 1671 + 1672 + err = reset_control_deassert(dsi->rst); 1673 + if (err < 0) { 1674 + dev_err(dev, "cannot assert reset: %d\n", err); 1675 + goto disable_clk_lp; 1676 + } 1677 + 1678 + return 0; 1679 + 1680 + disable_clk_lp: 1681 + clk_disable_unprepare(dsi->clk_lp); 1682 + disable_clk: 1683 + clk_disable_unprepare(dsi->clk); 1684 + disable_vdd: 1685 + regulator_disable(dsi->vdd); 1686 + return err; 1687 + } 1688 + #endif 1689 + 1690 + static const struct dev_pm_ops tegra_dsi_pm_ops = { 1691 + SET_RUNTIME_PM_OPS(tegra_dsi_suspend, tegra_dsi_resume, NULL) 1692 + }; 1593 1693 1594 1694 static const struct of_device_id tegra_dsi_of_match[] = { 1595 1695 { .compatible = "nvidia,tegra210-dsi", }, ··· 1668 1640 .driver = { 1669 1641 .name = "tegra-dsi", 1670 1642 .of_match_table = tegra_dsi_of_match, 1643 + .pm = &tegra_dsi_pm_ops, 1671 1644 }, 1672 1645 .probe = tegra_dsi_probe, 1673 1646 .remove = tegra_dsi_remove,