History

drm/tegra: Do not implement runtime PM

The Tegra DRM driver heavily relies on the implementations for runtime suspend/resume to be called at specific times. Unfortunately, there are some cases where that doesn't work. One example is if the user disables runtime PM for a given subdevice. Another example is that the PM core acquires a reference to runtime PM during system sleep, effectively preventing devices from going into low power modes. This is intentional to avoid nasty race conditions, but it also causes system sleep to not function properly on all Tegra systems. Fix this by not implementing runtime PM at all. Instead, a minimal, reference-counted suspend/resume infrastructure is added to the host1x bus. This has the benefit that it can be used regardless of the system power state (or any transitions we might be in), or whether or not the user allows runtime PM. Atomic modesetting guarantees that these functions will end up being called at the right point in time, so the pitfalls for the more generic runtime PM do not apply here.

Thierry Reding committed 6 years ago

Commit fd67e9c1 parent 608f43a10 files · +541 −331Browse files

Unified · Split

10 files
  1. drivers/gpu/drm/tegra/dc.c +84 −57
  2. drivers/gpu/drm/tegra/dpaux.c +1 −1
  3. drivers/gpu/drm/tegra/drm.h +2 −0
  4. drivers/gpu/drm/tegra/dsi.c +97 −78
  5. drivers/gpu/drm/tegra/hdmi.c +66 −50
  6. drivers/gpu/drm/tegra/hub.c +116 −78
  7. drivers/gpu/drm/tegra/hub.h +1 −1
  8. drivers/gpu/drm/tegra/sor.c +88 −66
  9. drivers/gpu/host1x/bus.c +75 −0
  10. include/linux/host1x.h +11 −0
drivers/gpu/drm/tegra/dc.c+84−57
@@ -1727,6 +1727,7 @@ static void tegra_crtc_atomic_disable(struct drm_crtc *crtc, · 1726 unmodified lines
1727{1727{
1728 struct tegra_dc *dc = to_tegra_dc(crtc);1728 struct tegra_dc *dc = to_tegra_dc(crtc);
1729 u32 value;1729 u32 value;
1730 int err;
1730 1731
1731 if (!tegra_dc_idle(dc)) {1732 if (!tegra_dc_idle(dc)) {
1732 tegra_dc_stop(dc);1733 tegra_dc_stop(dc);
@@ -1773,7 +1774,9 @@ static void tegra_crtc_atomic_disable(struct drm_crtc *crtc, · 40 unmodified lines
1773 1774
1774 spin_unlock_irq(&crtc->dev->event_lock);1775 spin_unlock_irq(&crtc->dev->event_lock);
1775 1776
1776 pm_runtime_put_sync(dc->dev);1777 err = host1x_client_suspend(&dc->client);
1778 if (err < 0)
1779 dev_err(dc->dev, "failed to suspend: %d\n", err);
1777}1780}
1778 1781
1779static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,1782static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
@@ -1783,8 +1786,13 @@ static void tegra_crtc_atomic_enable(struct drm_crtc *crtc, · 3 unmodified lines
1783 struct tegra_dc_state *state = to_dc_state(crtc->state);1786 struct tegra_dc_state *state = to_dc_state(crtc->state);
1784 struct tegra_dc *dc = to_tegra_dc(crtc);1787 struct tegra_dc *dc = to_tegra_dc(crtc);
1785 u32 value;1788 u32 value;
1789 int err;
1786 1790
1787 pm_runtime_get_sync(dc->dev);1791 err = host1x_client_resume(&dc->client);
1792 if (err < 0) {
1793 dev_err(dc->dev, "failed to resume: %d\n", err);
1794 return;
1795 }
1788 1796
1789 /* initialize display controller */1797 /* initialize display controller */
1790 if (dc->syncpt) {1798 if (dc->syncpt) {
@@ -2012,6 +2020,15 @@ static int tegra_dc_init(struct host1x_client *client) · 221 unmodified lines
2012 if (!tegra_dc_has_window_groups(dc))2020 if (!tegra_dc_has_window_groups(dc))
2013 return 0;2021 return 0;
2014 2022
2023 /*
2024 * Set the display hub as the host1x client parent for the display
2025 * controller. This is needed for the runtime reference counting that
2026 * ensures the display hub is always powered when any of the display
2027 * controllers are.
2028 */
2029 if (dc->soc->has_nvdisplay)
2030 client->parent = &tegra->hub->client;
2031
2015 dc->syncpt = host1x_syncpt_request(client, flags);2032 dc->syncpt = host1x_syncpt_request(client, flags);
2016 if (!dc->syncpt)2033 if (!dc->syncpt)
2017 dev_warn(dc->dev, "failed to allocate syncpoint\n");2034 dev_warn(dc->dev, "failed to allocate syncpoint\n");
@@ -2121,9 +2138,74 @@ static int tegra_dc_exit(struct host1x_client *client) · 103 unmodified lines
2121 return 0;2138 return 0;
2122}2139}
2123 2140
2141static int tegra_dc_runtime_suspend(struct host1x_client *client)
2142{
2143 struct tegra_dc *dc = host1x_client_to_dc(client);
2144 struct device *dev = client->dev;
2145 int err;
2146
2147 err = reset_control_assert(dc->rst);
2148 if (err < 0) {
2149 dev_err(dev, "failed to assert reset: %d\n", err);
2150 return err;
2151 }
2152
2153 if (dc->soc->has_powergate)
2154 tegra_powergate_power_off(dc->powergate);
2155
2156 clk_disable_unprepare(dc->clk);
2157 pm_runtime_put_sync(dev);
2158
2159 return 0;
2160}
2161
2162static int tegra_dc_runtime_resume(struct host1x_client *client)
2163{
2164 struct tegra_dc *dc = host1x_client_to_dc(client);
2165 struct device *dev = client->dev;
2166 int err;
2167
2168 err = pm_runtime_get_sync(dev);
2169 if (err < 0) {
2170 dev_err(dev, "failed to get runtime PM: %d\n", err);
2171 return err;
2172 }
2173
2174 if (dc->soc->has_powergate) {
2175 err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
2176 dc->rst);
2177 if (err < 0) {
2178 dev_err(dev, "failed to power partition: %d\n", err);
2179 goto put_rpm;
2180 }
2181 } else {
2182 err = clk_prepare_enable(dc->clk);
2183 if (err < 0) {
2184 dev_err(dev, "failed to enable clock: %d\n", err);
2185 goto put_rpm;
2186 }
2187
2188 err = reset_control_deassert(dc->rst);
2189 if (err < 0) {
2190 dev_err(dev, "failed to deassert reset: %d\n", err);
2191 goto disable_clk;
2192 }
2193 }
2194
2195 return 0;
2196
2197disable_clk:
2198 clk_disable_unprepare(dc->clk);
2199put_rpm:
2200 pm_runtime_put_sync(dev);
2201 return err;
2202}
2203
2124static const struct host1x_client_ops dc_client_ops = {2204static const struct host1x_client_ops dc_client_ops = {
2125 .init = tegra_dc_init,2205 .init = tegra_dc_init,
2126 .exit = tegra_dc_exit,2206 .exit = tegra_dc_exit,
2207 .suspend = tegra_dc_runtime_suspend,
2208 .resume = tegra_dc_runtime_resume,
2127};2209};
2128 2210
2129static const struct tegra_dc_soc_info tegra20_dc_soc_info = {2211static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
@@ -2535,65 +2617,10 @@ static int tegra_dc_remove(struct platform_device *pdev) · 405 unmodified lines
2535 return 0;2617 return 0;
2536}2618}
2537 2619
2538#ifdef CONFIG_PM
2539static int tegra_dc_suspend(struct device *dev)
2540{
2541 struct tegra_dc *dc = dev_get_drvdata(dev);
2542 int err;
2543
2544 err = reset_control_assert(dc->rst);
2545 if (err < 0) {
2546 dev_err(dev, "failed to assert reset: %d\n", err);
2547 return err;
2548 }
2549
2550 if (dc->soc->has_powergate)
2551 tegra_powergate_power_off(dc->powergate);
2552
2553 clk_disable_unprepare(dc->clk);
2554
2555 return 0;
2556}
2557
2558static int tegra_dc_resume(struct device *dev)
2559{
2560 struct tegra_dc *dc = dev_get_drvdata(dev);
2561 int err;
2562
2563 if (dc->soc->has_powergate) {
2564 err = tegra_powergate_sequence_power_up(dc->powergate, dc->clk,
2565 dc->rst);
2566 if (err < 0) {
2567 dev_err(dev, "failed to power partition: %d\n", err);
2568 return err;
2569 }
2570 } else {
2571 err = clk_prepare_enable(dc->clk);
2572 if (err < 0) {
2573 dev_err(dev, "failed to enable clock: %d\n", err);
2574 return err;
2575 }
2576
2577 err = reset_control_deassert(dc->rst);
2578 if (err < 0) {
2579 dev_err(dev, "failed to deassert reset: %d\n", err);
2580 return err;
2581 }
2582 }
2583
2584 return 0;
2585}
2586#endif
2587
2588static const struct dev_pm_ops tegra_dc_pm_ops = {
2589 SET_RUNTIME_PM_OPS(tegra_dc_suspend, tegra_dc_resume, NULL)
2590};
2591
2592struct platform_driver tegra_dc_driver = {2620struct platform_driver tegra_dc_driver = {
2593 .driver = {2621 .driver = {
2594 .name = "tegra-dc",2622 .name = "tegra-dc",
2595 .of_match_table = tegra_dc_of_match,2623 .of_match_table = tegra_dc_of_match,
2596 .pm = &tegra_dc_pm_ops,
2597 },2624 },
2598 .probe = tegra_dc_probe,2625 .probe = tegra_dc_probe,
2599 .remove = tegra_dc_remove,2626 .remove = tegra_dc_remove,
drivers/gpu/drm/tegra/dpaux.c+1−1
@@ -588,7 +588,7 @@ static int tegra_dpaux_remove(struct platform_device *pdev) · 587 unmodified lines
588 /* make sure pads are powered down when not in use */588 /* make sure pads are powered down when not in use */
589 tegra_dpaux_pad_power_down(dpaux);589 tegra_dpaux_pad_power_down(dpaux);
590 590
591 pm_runtime_put(&pdev->dev);591 pm_runtime_put_sync(&pdev->dev);
592 pm_runtime_disable(&pdev->dev);592 pm_runtime_disable(&pdev->dev);
593 593
594 drm_dp_aux_unregister(&dpaux->aux);594 drm_dp_aux_unregister(&dpaux->aux);
drivers/gpu/drm/tegra/drm.h+2−0
@@ -144,6 +144,8 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output); · 143 unmodified lines
144void tegra_output_exit(struct tegra_output *output);144void tegra_output_exit(struct tegra_output *output);
145void tegra_output_find_possible_crtcs(struct tegra_output *output,145void tegra_output_find_possible_crtcs(struct tegra_output *output,
146 struct drm_device *drm);146 struct drm_device *drm);
147int tegra_output_suspend(struct tegra_output *output);
148int tegra_output_resume(struct tegra_output *output);
147 149
148int tegra_output_connector_get_modes(struct drm_connector *connector);150int tegra_output_connector_get_modes(struct drm_connector *connector);
149enum drm_connector_status151enum drm_connector_status
drivers/gpu/drm/tegra/dsi.c+97−78
@@ -840,7 +840,9 @@ static void tegra_dsi_unprepare(struct tegra_dsi *dsi) · 839 unmodified lines
840 dev_err(dsi->dev, "failed to disable MIPI calibration: %d\n",840 dev_err(dsi->dev, "failed to disable MIPI calibration: %d\n",
841 err);841 err);
842 842
843 pm_runtime_put(dsi->dev);843 err = host1x_client_suspend(&dsi->client);
844 if (err < 0)
845 dev_err(dsi->dev, "failed to suspend: %d\n", err);
844}846}
845 847
846static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)848static void tegra_dsi_encoder_disable(struct drm_encoder *encoder)
@@ -882,11 +884,15 @@ static void tegra_dsi_encoder_disable(struct drm_encoder *encoder) · 35 unmodified lines
882 tegra_dsi_unprepare(dsi);884 tegra_dsi_unprepare(dsi);
883}885}
884 886
885static void tegra_dsi_prepare(struct tegra_dsi *dsi)887static int tegra_dsi_prepare(struct tegra_dsi *dsi)
886{888{
887 int err;889 int err;
888 890
889 pm_runtime_get_sync(dsi->dev);891 err = host1x_client_resume(&dsi->client);
892 if (err < 0) {
893 dev_err(dsi->dev, "failed to resume: %d\n", err);
894 return err;
895 }
890 896
891 err = tegra_mipi_enable(dsi->mipi);897 err = tegra_mipi_enable(dsi->mipi);
892 if (err < 0)898 if (err < 0)
@@ -899,6 +905,8 @@ static void tegra_dsi_prepare(struct tegra_dsi *dsi) · 6 unmodified lines
899 905
900 if (dsi->slave)906 if (dsi->slave)
901 tegra_dsi_prepare(dsi->slave);907 tegra_dsi_prepare(dsi->slave);
908
909 return 0;
902}910}
903 911
904static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)912static void tegra_dsi_encoder_enable(struct drm_encoder *encoder)
@@ -909,8 +917,13 @@ static void tegra_dsi_encoder_enable(struct drm_encoder *encoder) · 4 unmodified lines
909 struct tegra_dsi *dsi = to_dsi(output);917 struct tegra_dsi *dsi = to_dsi(output);
910 struct tegra_dsi_state *state;918 struct tegra_dsi_state *state;
911 u32 value;919 u32 value;
920 int err;
912 921
913 tegra_dsi_prepare(dsi);922 err = tegra_dsi_prepare(dsi);
923 if (err < 0) {
924 dev_err(dsi->dev, "failed to prepare: %d\n", err);
925 return;
926 }
914 927
915 state = tegra_dsi_get_state(dsi);928 state = tegra_dsi_get_state(dsi);
916 929
@@ -1075,9 +1088,89 @@ static int tegra_dsi_exit(struct host1x_client *client) · 158 unmodified lines
1075 return 0;1088 return 0;
1076}1089}
1077 1090
1091static int tegra_dsi_runtime_suspend(struct host1x_client *client)
1092{
1093 struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1094 struct device *dev = client->dev;
1095 int err;
1096
1097 if (dsi->rst) {
1098 err = reset_control_assert(dsi->rst);
1099 if (err < 0) {
1100 dev_err(dev, "failed to assert reset: %d\n", err);
1101 return err;
1102 }
1103 }
1104
1105 usleep_range(1000, 2000);
1106
1107 clk_disable_unprepare(dsi->clk_lp);
1108 clk_disable_unprepare(dsi->clk);
1109
1110 regulator_disable(dsi->vdd);
1111 pm_runtime_put_sync(dev);
1112
1113 return 0;
1114}
1115
1116static int tegra_dsi_runtime_resume(struct host1x_client *client)
1117{
1118 struct tegra_dsi *dsi = host1x_client_to_dsi(client);
1119 struct device *dev = client->dev;
1120 int err;
1121
1122 err = pm_runtime_get_sync(dev);
1123 if (err < 0) {
1124 dev_err(dev, "failed to get runtime PM: %d\n", err);
1125 return err;
1126 }
1127
1128 err = regulator_enable(dsi->vdd);
1129 if (err < 0) {
1130 dev_err(dev, "failed to enable VDD supply: %d\n", err);
1131 goto put_rpm;
1132 }
1133
1134 err = clk_prepare_enable(dsi->clk);
1135 if (err < 0) {
1136 dev_err(dev, "cannot enable DSI clock: %d\n", err);
1137 goto disable_vdd;
1138 }
1139
1140 err = clk_prepare_enable(dsi->clk_lp);
1141 if (err < 0) {
1142 dev_err(dev, "cannot enable low-power clock: %d\n", err);
1143 goto disable_clk;
1144 }
1145
1146 usleep_range(1000, 2000);
1147
1148 if (dsi->rst) {
1149 err = reset_control_deassert(dsi->rst);
1150 if (err < 0) {
1151 dev_err(dev, "cannot assert reset: %d\n", err);
1152 goto disable_clk_lp;
1153 }
1154 }
1155
1156 return 0;
1157
1158disable_clk_lp:
1159 clk_disable_unprepare(dsi->clk_lp);
1160disable_clk:
1161 clk_disable_unprepare(dsi->clk);
1162disable_vdd:
1163 regulator_disable(dsi->vdd);
1164put_rpm:
1165 pm_runtime_put_sync(dev);
1166 return err;
1167}
1168
1078static const struct host1x_client_ops dsi_client_ops = {1169static const struct host1x_client_ops dsi_client_ops = {
1079 .init = tegra_dsi_init,1170 .init = tegra_dsi_init,
1080 .exit = tegra_dsi_exit,1171 .exit = tegra_dsi_exit,
1172 .suspend = tegra_dsi_runtime_suspend,
1173 .resume = tegra_dsi_runtime_resume,
1081};1174};
1082 1175
1083static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi)1176static int tegra_dsi_setup_clocks(struct tegra_dsi *dsi)
@@ -1596,79 +1689,6 @@ static int tegra_dsi_remove(struct platform_device *pdev) · 512 unmodified lines
1596 return 0;1689 return 0;
1597}1690}
1598 1691
1599#ifdef CONFIG_PM
1600static int tegra_dsi_suspend(struct device *dev)
1601{
1602 struct tegra_dsi *dsi = dev_get_drvdata(dev);
1603 int err;
1604
1605 if (dsi->rst) {
1606 err = reset_control_assert(dsi->rst);
1607 if (err < 0) {
1608 dev_err(dev, "failed to assert reset: %d\n", err);
1609 return err;
1610 }
1611 }
1612
1613 usleep_range(1000, 2000);
1614
1615 clk_disable_unprepare(dsi->clk_lp);
1616 clk_disable_unprepare(dsi->clk);
1617
1618 regulator_disable(dsi->vdd);
1619
1620 return 0;
1621}
1622
1623static int tegra_dsi_resume(struct device *dev)
1624{
1625 struct tegra_dsi *dsi = dev_get_drvdata(dev);
1626 int err;
1627
1628 err = regulator_enable(dsi->vdd);
1629 if (err < 0) {
1630 dev_err(dsi->dev, "failed to enable VDD supply: %d\n", err);
1631 return err;
1632 }
1633
1634 err = clk_prepare_enable(dsi->clk);
1635 if (err < 0) {
1636 dev_err(dev, "cannot enable DSI clock: %d\n", err);
1637 goto disable_vdd;
1638 }
1639
1640 err = clk_prepare_enable(dsi->clk_lp);
1641 if (err < 0) {
1642 dev_err(dev, "cannot enable low-power clock: %d\n", err);
1643 goto disable_clk;
1644 }
1645
1646 usleep_range(1000, 2000);
1647
1648 if (dsi->rst) {
1649 err = reset_control_deassert(dsi->rst);
1650 if (err < 0) {
1651 dev_err(dev, "cannot assert reset: %d\n", err);
1652 goto disable_clk_lp;
1653 }
1654 }
1655
1656 return 0;
1657
1658disable_clk_lp:
1659 clk_disable_unprepare(dsi->clk_lp);
1660disable_clk:
1661 clk_disable_unprepare(dsi->clk);
1662disable_vdd:
1663 regulator_disable(dsi->vdd);
1664 return err;
1665}
1666#endif
1667
1668static const struct dev_pm_ops tegra_dsi_pm_ops = {
1669 SET_RUNTIME_PM_OPS(tegra_dsi_suspend, tegra_dsi_resume, NULL)
1670};
1671
1672static const struct of_device_id tegra_dsi_of_match[] = {1692static const struct of_device_id tegra_dsi_of_match[] = {
1673 { .compatible = "nvidia,tegra210-dsi", },1693 { .compatible = "nvidia,tegra210-dsi", },
1674 { .compatible = "nvidia,tegra132-dsi", },1694 { .compatible = "nvidia,tegra132-dsi", },
@@ -1682,7 +1702,6 @@ struct platform_driver tegra_dsi_driver = { · 7 unmodified lines
1682 .driver = {1702 .driver = {
1683 .name = "tegra-dsi",1703 .name = "tegra-dsi",
1684 .of_match_table = tegra_dsi_of_match,1704 .of_match_table = tegra_dsi_of_match,
1685 .pm = &tegra_dsi_pm_ops,
1686 },1705 },
1687 .probe = tegra_dsi_probe,1706 .probe = tegra_dsi_probe,
1688 .remove = tegra_dsi_remove,1707 .remove = tegra_dsi_remove,
drivers/gpu/drm/tegra/hdmi.c+66−50
@@ -1146,6 +1146,7 @@ static void tegra_hdmi_encoder_disable(struct drm_encoder *encoder) · 1145 unmodified lines
1146 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);1146 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
1147 struct tegra_hdmi *hdmi = to_hdmi(output);1147 struct tegra_hdmi *hdmi = to_hdmi(output);
1148 u32 value;1148 u32 value;
1149 int err;
1149 1150
1150 /*1151 /*
1151 * The following accesses registers of the display controller, so make1152 * The following accesses registers of the display controller, so make
@@ -1171,7 +1172,9 @@ static void tegra_hdmi_encoder_disable(struct drm_encoder *encoder) · 19 unmodified lines
1171 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_ENABLE);1172 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_ENABLE);
1172 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_MASK);1173 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_MASK);
1173 1174
1174 pm_runtime_put(hdmi->dev);1175 err = host1x_client_suspend(&hdmi->client);
1176 if (err < 0)
1177 dev_err(hdmi->dev, "failed to suspend: %d\n", err);
1175}1178}
1176 1179
1177static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder)1180static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder)
@@ -1186,7 +1189,11 @@ static void tegra_hdmi_encoder_enable(struct drm_encoder *encoder) · 8 unmodified lines
1186 u32 value;1189 u32 value;
1187 int err;1190 int err;
1188 1191
1189 pm_runtime_get_sync(hdmi->dev);1192 err = host1x_client_resume(&hdmi->client);
1193 if (err < 0) {
1194 dev_err(hdmi->dev, "failed to resume: %d\n", err);
1195 return;
1196 }
1190 1197
1191 /*1198 /*
1192 * Enable and unmask the HDA codec SCRATCH0 register interrupt. This1199 * Enable and unmask the HDA codec SCRATCH0 register interrupt. This
@@ -1489,9 +1496,66 @@ static int tegra_hdmi_exit(struct host1x_client *client) · 296 unmodified lines
1489 return 0;1496 return 0;
1490}1497}
1491 1498
1499static int tegra_hdmi_runtime_suspend(struct host1x_client *client)
1500{
1501 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1502 struct device *dev = client->dev;
1503 int err;
1504
1505 err = reset_control_assert(hdmi->rst);
1506 if (err < 0) {
1507 dev_err(dev, "failed to assert reset: %d\n", err);
1508 return err;
1509 }
1510
1511 usleep_range(1000, 2000);
1512
1513 clk_disable_unprepare(hdmi->clk);
1514 pm_runtime_put_sync(dev);
1515
1516 return 0;
1517}
1518
1519static int tegra_hdmi_runtime_resume(struct host1x_client *client)
1520{
1521 struct tegra_hdmi *hdmi = host1x_client_to_hdmi(client);
1522 struct device *dev = client->dev;
1523 int err;
1524
1525 err = pm_runtime_get_sync(dev);
1526 if (err < 0) {
1527 dev_err(dev, "failed to get runtime PM: %d\n", err);
1528 return err;
1529 }
1530
1531 err = clk_prepare_enable(hdmi->clk);
1532 if (err < 0) {
1533 dev_err(dev, "failed to enable clock: %d\n", err);
1534 goto put_rpm;
1535 }
1536
1537 usleep_range(1000, 2000);
1538
1539 err = reset_control_deassert(hdmi->rst);
1540 if (err < 0) {
1541 dev_err(dev, "failed to deassert reset: %d\n", err);
1542 goto disable_clk;
1543 }
1544
1545 return 0;
1546
1547disable_clk:
1548 clk_disable_unprepare(hdmi->clk);
1549put_rpm:
1550 pm_runtime_put_sync(dev);
1551 return err;
1552}
1553
1492static const struct host1x_client_ops hdmi_client_ops = {1554static const struct host1x_client_ops hdmi_client_ops = {
1493 .init = tegra_hdmi_init,1555 .init = tegra_hdmi_init,
1494 .exit = tegra_hdmi_exit,1556 .exit = tegra_hdmi_exit,
1557 .suspend = tegra_hdmi_runtime_suspend,
1558 .resume = tegra_hdmi_runtime_resume,
1495};1559};
1496 1560
1497static const struct tegra_hdmi_config tegra20_hdmi_config = {1561static const struct tegra_hdmi_config tegra20_hdmi_config = {
@@ -1699,58 +1763,10 @@ static int tegra_hdmi_remove(struct platform_device *pdev) · 201 unmodified lines
1699 return 0;1763 return 0;
1700}1764}
1701 1765
1702#ifdef CONFIG_PM
1703static int tegra_hdmi_suspend(struct device *dev)
1704{
1705 struct tegra_hdmi *hdmi = dev_get_drvdata(dev);
1706 int err;
1707
1708 err = reset_control_assert(hdmi->rst);
1709 if (err < 0) {
1710 dev_err(dev, "failed to assert reset: %d\n", err);
1711 return err;
1712 }
1713
1714 usleep_range(1000, 2000);
1715
1716 clk_disable_unprepare(hdmi->clk);
1717
1718 return 0;
1719}
1720
1721static int tegra_hdmi_resume(struct device *dev)
1722{
1723 struct tegra_hdmi *hdmi = dev_get_drvdata(dev);
1724 int err;
1725
1726 err = clk_prepare_enable(hdmi->clk);
1727 if (err < 0) {
1728 dev_err(dev, "failed to enable clock: %d\n", err);
1729 return err;
1730 }
1731
1732 usleep_range(1000, 2000);
1733
1734 err = reset_control_deassert(hdmi->rst);
1735 if (err < 0) {
1736 dev_err(dev, "failed to deassert reset: %d\n", err);
1737 clk_disable_unprepare(hdmi->clk);
1738 return err;
1739 }
1740
1741 return 0;
1742}
1743#endif
1744
1745static const struct dev_pm_ops tegra_hdmi_pm_ops = {
1746 SET_RUNTIME_PM_OPS(tegra_hdmi_suspend, tegra_hdmi_resume, NULL)
1747};
1748
1749struct platform_driver tegra_hdmi_driver = {1766struct platform_driver tegra_hdmi_driver = {
1750 .driver = {1767 .driver = {
1751 .name = "tegra-hdmi",1768 .name = "tegra-hdmi",
1752 .of_match_table = tegra_hdmi_of_match,1769 .of_match_table = tegra_hdmi_of_match,
1753 .pm = &tegra_hdmi_pm_ops,
1754 },1770 },
1755 .probe = tegra_hdmi_probe,1771 .probe = tegra_hdmi_probe,
1756 .remove = tegra_hdmi_remove,1772 .remove = tegra_hdmi_remove,
drivers/gpu/drm/tegra/hub.c+116−78
@@ -95,17 +95,25 @@ static inline void tegra_plane_writel(struct tegra_plane *plane, u32 value, · 94 unmodified lines
95 95
96static int tegra_windowgroup_enable(struct tegra_windowgroup *wgrp)96static int tegra_windowgroup_enable(struct tegra_windowgroup *wgrp)
97{97{
98 int err = 0;
99
98 mutex_lock(&wgrp->lock);100 mutex_lock(&wgrp->lock);
99 101
100 if (wgrp->usecount == 0) {102 if (wgrp->usecount == 0) {
101 pm_runtime_get_sync(wgrp->parent);103 err = host1x_client_resume(wgrp->parent);
104 if (err < 0) {
105 dev_err(wgrp->parent->dev, "failed to resume: %d\n", err);
106 goto unlock;
107 }
108
102 reset_control_deassert(wgrp->rst);109 reset_control_deassert(wgrp->rst);
103 }110 }
104 111
105 wgrp->usecount++;112 wgrp->usecount++;
106 mutex_unlock(&wgrp->lock);
107 113
108 return 0;114unlock:
115 mutex_unlock(&wgrp->lock);
116 return err;
109}117}
110 118
111static void tegra_windowgroup_disable(struct tegra_windowgroup *wgrp)119static void tegra_windowgroup_disable(struct tegra_windowgroup *wgrp)
@@ -121,7 +129,7 @@ static void tegra_windowgroup_disable(struct tegra_windowgroup *wgrp) · 9 unmodified lines
121 wgrp->index);129 wgrp->index);
122 }130 }
123 131
124 pm_runtime_put(wgrp->parent);132 host1x_client_suspend(wgrp->parent);
125 }133 }
126 134
127 wgrp->usecount--;135 wgrp->usecount--;
@@ -379,6 +387,7 @@ static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, · 251 unmodified lines
379 struct tegra_plane *p = to_tegra_plane(plane);387 struct tegra_plane *p = to_tegra_plane(plane);
380 struct tegra_dc *dc;388 struct tegra_dc *dc;
381 u32 value;389 u32 value;
390 int err;
382 391
383 /* rien ne va plus */392 /* rien ne va plus */
384 if (!old_state || !old_state->crtc)393 if (!old_state || !old_state->crtc)
@@ -386,6 +395,12 @@ static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, · 1 unmodified line
386 395
387 dc = to_tegra_dc(old_state->crtc);396 dc = to_tegra_dc(old_state->crtc);
388 397
398 err = host1x_client_resume(&dc->client);
399 if (err < 0) {
400 dev_err(dc->dev, "failed to resume: %d\n", err);
401 return;
402 }
403
389 /*404 /*
390 * XXX Legacy helpers seem to sometimes call ->atomic_disable() even405 * XXX Legacy helpers seem to sometimes call ->atomic_disable() even
391 * on planes that are already disabled. Make sure we fallback to the406 * on planes that are already disabled. Make sure we fallback to the
@@ -394,15 +409,13 @@ static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, · 2 unmodified lines
394 if (WARN_ON(p->dc == NULL))409 if (WARN_ON(p->dc == NULL))
395 p->dc = dc;410 p->dc = dc;
396 411
397 pm_runtime_get_sync(dc->dev);
398
399 value = tegra_plane_readl(p, DC_WIN_WIN_OPTIONS);412 value = tegra_plane_readl(p, DC_WIN_WIN_OPTIONS);
400 value &= ~WIN_ENABLE;413 value &= ~WIN_ENABLE;
401 tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS);414 tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS);
402 415
403 tegra_dc_remove_shared_plane(dc, p);416 tegra_dc_remove_shared_plane(dc, p);
404 417
405 pm_runtime_put(dc->dev);418 host1x_client_suspend(&dc->client);
406}419}
407 420
408static void tegra_shared_plane_atomic_update(struct drm_plane *plane,421static void tegra_shared_plane_atomic_update(struct drm_plane *plane,
@@ -415,6 +428,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, · 6 unmodified lines
415 struct tegra_plane *p = to_tegra_plane(plane);428 struct tegra_plane *p = to_tegra_plane(plane);
416 dma_addr_t base;429 dma_addr_t base;
417 u32 value;430 u32 value;
431 int err;
418 432
419 /* rien ne va plus */433 /* rien ne va plus */
420 if (!plane->state->crtc || !plane->state->fb)434 if (!plane->state->crtc || !plane->state->fb)
@@ -425,7 +439,11 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, · 4 unmodified lines
425 return;439 return;
426 }440 }
427 441
428 pm_runtime_get_sync(dc->dev);442 err = host1x_client_resume(&dc->client);
443 if (err < 0) {
444 dev_err(dc->dev, "failed to resume: %d\n", err);
445 return;
446 }
429 447
430 tegra_dc_assign_shared_plane(dc, p);448 tegra_dc_assign_shared_plane(dc, p);
431 449
@@ -515,7 +533,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, · 83 unmodified lines
515 value &= ~CONTROL_CSC_ENABLE;533 value &= ~CONTROL_CSC_ENABLE;
516 tegra_plane_writel(p, value, DC_WIN_WINDOW_SET_CONTROL);534 tegra_plane_writel(p, value, DC_WIN_WINDOW_SET_CONTROL);
517 535
518 pm_runtime_put(dc->dev);536 host1x_client_suspend(&dc->client);
519}537}
520 538
521static const struct drm_plane_helper_funcs tegra_shared_plane_helper_funcs = {539static const struct drm_plane_helper_funcs tegra_shared_plane_helper_funcs = {
@@ -551,7 +569,7 @@ struct drm_plane *tegra_shared_plane_create(struct drm_device *drm, · 29 unmodified lines
551 plane->base.index = index;569 plane->base.index = index;
552 570
553 plane->wgrp = &hub->wgrps[wgrp];571 plane->wgrp = &hub->wgrps[wgrp];
554 plane->wgrp->parent = dc->dev;572 plane->wgrp->parent = &dc->client;
555 573
556 p = &plane->base.base;574 p = &plane->base.base;
557 575
@@ -656,8 +674,13 @@ int tegra_display_hub_atomic_check(struct drm_device *drm, · 98 unmodified lines
656static void tegra_display_hub_update(struct tegra_dc *dc)674static void tegra_display_hub_update(struct tegra_dc *dc)
657{675{
658 u32 value;676 u32 value;
677 int err;
659 678
660 pm_runtime_get_sync(dc->dev);679 err = host1x_client_resume(&dc->client);
680 if (err < 0) {
681 dev_err(dc->dev, "failed to resume: %d\n", err);
682 return;
683 }
661 684
662 value = tegra_dc_readl(dc, DC_CMD_IHUB_COMMON_MISC_CTL);685 value = tegra_dc_readl(dc, DC_CMD_IHUB_COMMON_MISC_CTL);
663 value &= ~LATENCY_EVENT;686 value &= ~LATENCY_EVENT;
@@ -672,7 +695,7 @@ static void tegra_display_hub_update(struct tegra_dc *dc) · 8 unmodified lines
672 tegra_dc_writel(dc, COMMON_ACTREQ, DC_CMD_STATE_CONTROL);695 tegra_dc_writel(dc, COMMON_ACTREQ, DC_CMD_STATE_CONTROL);
673 tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);696 tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
674 697
675 pm_runtime_put(dc->dev);698 host1x_client_suspend(&dc->client);
676}699}
677 700
678void tegra_display_hub_atomic_commit(struct drm_device *drm,701void tegra_display_hub_atomic_commit(struct drm_device *drm,
@@ -732,9 +755,85 @@ static int tegra_display_hub_exit(struct host1x_client *client) · 53 unmodified lines
732 return 0;755 return 0;
733}756}
734 757
758static int tegra_display_hub_runtime_suspend(struct host1x_client *client)
759{
760 struct tegra_display_hub *hub = to_tegra_display_hub(client);
761 struct device *dev = client->dev;
762 unsigned int i = hub->num_heads;
763 int err;
764
765 err = reset_control_assert(hub->rst);
766 if (err < 0)
767 return err;
768
769 while (i--)
770 clk_disable_unprepare(hub->clk_heads[i]);
771
772 clk_disable_unprepare(hub->clk_hub);
773 clk_disable_unprepare(hub->clk_dsc);
774 clk_disable_unprepare(hub->clk_disp);
775
776 pm_runtime_put_sync(dev);
777
778 return 0;
779}
780
781static int tegra_display_hub_runtime_resume(struct host1x_client *client)
782{
783 struct tegra_display_hub *hub = to_tegra_display_hub(client);
784 struct device *dev = client->dev;
785 unsigned int i;
786 int err;
787
788 err = pm_runtime_get_sync(dev);
789 if (err < 0) {
790 dev_err(dev, "failed to get runtime PM: %d\n", err);
791 return err;
792 }
793
794 err = clk_prepare_enable(hub->clk_disp);
795 if (err < 0)
796 goto put_rpm;
797
798 err = clk_prepare_enable(hub->clk_dsc);
799 if (err < 0)
800 goto disable_disp;
801
802 err = clk_prepare_enable(hub->clk_hub);
803 if (err < 0)
804 goto disable_dsc;
805
806 for (i = 0; i < hub->num_heads; i++) {
807 err = clk_prepare_enable(hub->clk_heads[i]);
808 if (err < 0)
809 goto disable_heads;
810 }
811
812 err = reset_control_deassert(hub->rst);
813 if (err < 0)
814 goto disable_heads;
815
816 return 0;
817
818disable_heads:
819 while (i--)
820 clk_disable_unprepare(hub->clk_heads[i]);
821
822 clk_disable_unprepare(hub->clk_hub);
823disable_dsc:
824 clk_disable_unprepare(hub->clk_dsc);
825disable_disp:
826 clk_disable_unprepare(hub->clk_disp);
827put_rpm:
828 pm_runtime_put_sync(dev);
829 return err;
830}
831
735static const struct host1x_client_ops tegra_display_hub_ops = {832static const struct host1x_client_ops tegra_display_hub_ops = {
736 .init = tegra_display_hub_init,833 .init = tegra_display_hub_init,
737 .exit = tegra_display_hub_exit,834 .exit = tegra_display_hub_exit,
835 .suspend = tegra_display_hub_runtime_suspend,
836 .resume = tegra_display_hub_runtime_resume,
738};837};
739 838
740static int tegra_display_hub_probe(struct platform_device *pdev)839static int tegra_display_hub_probe(struct platform_device *pdev)
@@ -851,6 +950,7 @@ static int tegra_display_hub_probe(struct platform_device *pdev) · 110 unmodified lines
851static int tegra_display_hub_remove(struct platform_device *pdev)950static int tegra_display_hub_remove(struct platform_device *pdev)
852{951{
853 struct tegra_display_hub *hub = platform_get_drvdata(pdev);952 struct tegra_display_hub *hub = platform_get_drvdata(pdev);
953 unsigned int i;
854 int err;954 int err;
855 955
856 err = host1x_client_unregister(&hub->client);956 err = host1x_client_unregister(&hub->client);
@@ -859,78 +959,17 @@ static int tegra_display_hub_remove(struct platform_device *pdev) · 2 unmodified lines
859 err);959 err);
860 }960 }
861 961
862 pm_runtime_disable(&pdev->dev);962 for (i = 0; i < hub->soc->num_wgrps; i++) {
863 963 struct tegra_windowgroup *wgrp = &hub->wgrps[i];
864 return err;
865}
866
867static int __maybe_unused tegra_display_hub_suspend(struct device *dev)
868{
869 struct tegra_display_hub *hub = dev_get_drvdata(dev);
870 unsigned int i = hub->num_heads;
871 int err;
872
873 err = reset_control_assert(hub->rst);
874 if (err < 0)
875 return err;
876
877 while (i--)
878 clk_disable_unprepare(hub->clk_heads[i]);
879
880 clk_disable_unprepare(hub->clk_hub);
881 clk_disable_unprepare(hub->clk_dsc);
882 clk_disable_unprepare(hub->clk_disp);
883
884 return 0;
885}
886
887static int __maybe_unused tegra_display_hub_resume(struct device *dev)
888{
889 struct tegra_display_hub *hub = dev_get_drvdata(dev);
890 unsigned int i;
891 int err;
892
893 err = clk_prepare_enable(hub->clk_disp);
894 if (err < 0)
895 return err;
896
897 err = clk_prepare_enable(hub->clk_dsc);
898 if (err < 0)
899 goto disable_disp;
900
901 err = clk_prepare_enable(hub->clk_hub);
902 if (err < 0)
903 goto disable_dsc;
904 964
905 for (i = 0; i < hub->num_heads; i++) {965 mutex_destroy(&wgrp->lock);
906 err = clk_prepare_enable(hub->clk_heads[i]);
907 if (err < 0)
908 goto disable_heads;
909 }966 }
910 967
911 err = reset_control_deassert(hub->rst);968 pm_runtime_disable(&pdev->dev);
912 if (err < 0)
913 goto disable_heads;
914
915 return 0;
916
917disable_heads:
918 while (i--)
919 clk_disable_unprepare(hub->clk_heads[i]);
920 969
921 clk_disable_unprepare(hub->clk_hub);
922disable_dsc:
923 clk_disable_unprepare(hub->clk_dsc);
924disable_disp:
925 clk_disable_unprepare(hub->clk_disp);
926 return err;970 return err;
927}971}
928 972
929static const struct dev_pm_ops tegra_display_hub_pm_ops = {
930 SET_RUNTIME_PM_OPS(tegra_display_hub_suspend,
931 tegra_display_hub_resume, NULL)
932};
933
934static const struct tegra_display_hub_soc tegra186_display_hub = {973static const struct tegra_display_hub_soc tegra186_display_hub = {
935 .num_wgrps = 6,974 .num_wgrps = 6,
936 .supports_dsc = true,975 .supports_dsc = true,
@@ -958,7 +997,6 @@ struct platform_driver tegra_display_hub_driver = { · 21 unmodified lines
958 .driver = {997 .driver = {
959 .name = "tegra-display-hub",998 .name = "tegra-display-hub",
960 .of_match_table = tegra_display_hub_of_match,999 .of_match_table = tegra_display_hub_of_match,
961 .pm = &tegra_display_hub_pm_ops,
962 },1000 },
963 .probe = tegra_display_hub_probe,1001 .probe = tegra_display_hub_probe,
964 .remove = tegra_display_hub_remove,1002 .remove = tegra_display_hub_remove,
drivers/gpu/drm/tegra/hub.h+1−1
@@ -17,7 +17,7 @@ struct tegra_windowgroup { · 16 unmodified lines
17 struct mutex lock;17 struct mutex lock;
18 18
19 unsigned int index;19 unsigned int index;
20 struct device *parent;20 struct host1x_client *parent;
21 struct reset_control *rst;21 struct reset_control *rst;
22};22};
23 23
drivers/gpu/drm/tegra/sor.c+88−66
@@ -2255,7 +2255,7 @@ static void tegra_sor_hdmi_disable(struct drm_encoder *encoder) · 2254 unmodified lines
2255 if (err < 0)2255 if (err < 0)
2256 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);2256 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
2257 2257
2258 pm_runtime_put(sor->dev);2258 host1x_client_suspend(&sor->client);
2259}2259}
2260 2260
2261static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)2261static void tegra_sor_hdmi_enable(struct drm_encoder *encoder)
@@ -2276,7 +2276,11 @@ static void tegra_sor_hdmi_enable(struct drm_encoder *encoder) · 14 unmodified lines
2276 mode = &encoder->crtc->state->adjusted_mode;2276 mode = &encoder->crtc->state->adjusted_mode;
2277 pclk = mode->clock * 1000;2277 pclk = mode->clock * 1000;
2278 2278
2279 pm_runtime_get_sync(sor->dev);2279 err = host1x_client_resume(&sor->client);
2280 if (err < 0) {
2281 dev_err(sor->dev, "failed to resume: %d\n", err);
2282 return;
2283 }
2280 2284
2281 /* switch to safe parent clock */2285 /* switch to safe parent clock */
2282 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);2286 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
@@ -2722,7 +2726,7 @@ static void tegra_sor_dp_disable(struct drm_encoder *encoder) · 439 unmodified lines
2722 if (output->panel)2726 if (output->panel)
2723 drm_panel_unprepare(output->panel);2727 drm_panel_unprepare(output->panel);
2724 2728
2725 pm_runtime_put(sor->dev);2729 host1x_client_suspend(&sor->client);
2726}2730}
2727 2731
2728static void tegra_sor_dp_enable(struct drm_encoder *encoder)2732static void tegra_sor_dp_enable(struct drm_encoder *encoder)
@@ -2742,7 +2746,11 @@ static void tegra_sor_dp_enable(struct drm_encoder *encoder) · 13 unmodified lines
2742 mode = &encoder->crtc->state->adjusted_mode;2746 mode = &encoder->crtc->state->adjusted_mode;
2743 info = &output->connector.display_info;2747 info = &output->connector.display_info;
2744 2748
2745 pm_runtime_get_sync(sor->dev);2749 err = host1x_client_resume(&sor->client);
2750 if (err < 0) {
2751 dev_err(sor->dev, "failed to resume: %d\n", err);
2752 return;
2753 }
2746 2754
2747 /* switch to safe parent clock */2755 /* switch to safe parent clock */
2748 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);2756 err = tegra_sor_set_parent_clock(sor, sor->clk_safe);
@@ -3189,9 +3197,80 @@ static int tegra_sor_exit(struct host1x_client *client) · 440 unmodified lines
3189 return 0;3197 return 0;
3190}3198}
3191 3199
3200static int tegra_sor_runtime_suspend(struct host1x_client *client)
3201{
3202 struct tegra_sor *sor = host1x_client_to_sor(client);
3203 struct device *dev = client->dev;
3204 int err;
3205
3206 if (sor->rst) {
3207 err = reset_control_assert(sor->rst);
3208 if (err < 0) {
3209 dev_err(dev, "failed to assert reset: %d\n", err);
3210 return err;
3211 }
3212
3213 reset_control_release(sor->rst);
3214 }
3215
3216 usleep_range(1000, 2000);
3217
3218 clk_disable_unprepare(sor->clk);
3219 pm_runtime_put_sync(dev);
3220
3221 return 0;
3222}
3223
3224static int tegra_sor_runtime_resume(struct host1x_client *client)
3225{
3226 struct tegra_sor *sor = host1x_client_to_sor(client);
3227 struct device *dev = client->dev;
3228 int err;
3229
3230 err = pm_runtime_get_sync(dev);
3231 if (err < 0) {
3232 dev_err(dev, "failed to get runtime PM: %d\n", err);
3233 return err;
3234 }
3235
3236 err = clk_prepare_enable(sor->clk);
3237 if (err < 0) {
3238 dev_err(dev, "failed to enable clock: %d\n", err);
3239 goto put_rpm;
3240 }
3241
3242 usleep_range(1000, 2000);
3243
3244 if (sor->rst) {
3245 err = reset_control_acquire(sor->rst);
3246 if (err < 0) {
3247 dev_err(dev, "failed to acquire reset: %d\n", err);
3248 goto disable_clk;
3249 }
3250
3251 err = reset_control_deassert(sor->rst);
3252 if (err < 0) {
3253 dev_err(dev, "failed to deassert reset: %d\n", err);
3254 goto release_reset;
3255 }
3256 }
3257
3258 return 0;
3259
3260release_reset:
3261 reset_control_release(sor->rst);
3262disable_clk:
3263 clk_disable_unprepare(sor->clk);
3264put_rpm:
3265 pm_runtime_put_sync(dev);
3266 return err;
3267}
3268
3192static const struct host1x_client_ops sor_client_ops = {3269static const struct host1x_client_ops sor_client_ops = {
3193 .init = tegra_sor_init,3270 .init = tegra_sor_init,
3194 .exit = tegra_sor_exit,3271 .exit = tegra_sor_exit,
3272 .suspend = tegra_sor_runtime_suspend,
3273 .resume = tegra_sor_runtime_resume,
3195};3274};
3196 3275
3197static const u8 tegra124_sor_xbar_cfg[5] = {3276static const u8 tegra124_sor_xbar_cfg[5] = {
@@ -3842,10 +3921,9 @@ static int tegra_sor_probe(struct platform_device *pdev) · 644 unmodified lines
3842 if (!sor->clk_pad) {3921 if (!sor->clk_pad) {
3843 char *name;3922 char *name;
3844 3923
3845 err = pm_runtime_get_sync(&pdev->dev);3924 err = host1x_client_resume(&sor->client);
3846 if (err < 0) {3925 if (err < 0) {
3847 dev_err(&pdev->dev, "failed to get runtime PM: %d\n",3926 dev_err(sor->dev, "failed to resume: %d\n", err);
3848 err);
3849 goto remove;3927 goto remove;
3850 }3928 }
3851 3929
@@ -3856,7 +3934,7 @@ static int tegra_sor_probe(struct platform_device *pdev) · 4 unmodified lines
3856 }3934 }
3857 3935
3858 sor->clk_pad = tegra_clk_sor_pad_register(sor, name);3936 sor->clk_pad = tegra_clk_sor_pad_register(sor, name);
3859 pm_runtime_put(&pdev->dev);3937 host1x_client_suspend(&sor->client);
3860 }3938 }
3861 3939
3862 if (IS_ERR(sor->clk_pad)) {3940 if (IS_ERR(sor->clk_pad)) {
@@ -3912,61 +3990,6 @@ static int tegra_sor_remove(struct platform_device *pdev) · 49 unmodified lines
3912 return 0;3990 return 0;
3913}3991}
3914 3992
3915static int tegra_sor_runtime_suspend(struct device *dev)
3916{
3917 struct tegra_sor *sor = dev_get_drvdata(dev);
3918 int err;
3919
3920 if (sor->rst) {
3921 err = reset_control_assert(sor->rst);
3922 if (err < 0) {
3923 dev_err(dev, "failed to assert reset: %d\n", err);
3924 return err;
3925 }
3926
3927 reset_control_release(sor->rst);
3928 }
3929
3930 usleep_range(1000, 2000);
3931
3932 clk_disable_unprepare(sor->clk);
3933
3934 return 0;
3935}
3936
3937static int tegra_sor_runtime_resume(struct device *dev)
3938{
3939 struct tegra_sor *sor = dev_get_drvdata(dev);
3940 int err;
3941
3942 err = clk_prepare_enable(sor->clk);
3943 if (err < 0) {
3944 dev_err(dev, "failed to enable clock: %d\n", err);
3945 return err;
3946 }
3947
3948 usleep_range(1000, 2000);
3949
3950 if (sor->rst) {
3951 err = reset_control_acquire(sor->rst);
3952 if (err < 0) {
3953 dev_err(dev, "failed to acquire reset: %d\n", err);
3954 clk_disable_unprepare(sor->clk);
3955 return err;
3956 }
3957
3958 err = reset_control_deassert(sor->rst);
3959 if (err < 0) {
3960 dev_err(dev, "failed to deassert reset: %d\n", err);
3961 reset_control_release(sor->rst);
3962 clk_disable_unprepare(sor->clk);
3963 return err;
3964 }
3965 }
3966
3967 return 0;
3968}
3969
3970static int tegra_sor_suspend(struct device *dev)3993static int tegra_sor_suspend(struct device *dev)
3971{3994{
3972 struct tegra_sor *sor = dev_get_drvdata(dev);3995 struct tegra_sor *sor = dev_get_drvdata(dev);
@@ -3974,8 +3997,9 @@ static int tegra_sor_suspend(struct device *dev) · 1 unmodified line
3974 3997
3975 if (sor->hdmi_supply) {3998 if (sor->hdmi_supply) {
3976 err = regulator_disable(sor->hdmi_supply);3999 err = regulator_disable(sor->hdmi_supply);
3977 if (err < 0)4000 if (err < 0) {
3978 return err;4001 return err;
4002 }
3979 }4003 }
3980 4004
3981 return 0;4005 return 0;
@@ -3996,8 +4020,6 @@ static int tegra_sor_resume(struct device *dev) · 14 unmodified lines
3996}4020}
3997 4021
3998static const struct dev_pm_ops tegra_sor_pm_ops = {4022static const struct dev_pm_ops tegra_sor_pm_ops = {
3999 SET_RUNTIME_PM_OPS(tegra_sor_runtime_suspend, tegra_sor_runtime_resume,
4000 NULL)
4001 SET_SYSTEM_SLEEP_PM_OPS(tegra_sor_suspend, tegra_sor_resume)4023 SET_SYSTEM_SLEEP_PM_OPS(tegra_sor_suspend, tegra_sor_resume)
4002};4024};
4003 4025
drivers/gpu/host1x/bus.c+75−0
@@ -710,6 +710,10 @@ int host1x_client_register(struct host1x_client *client) · 709 unmodified lines
710 struct host1x *host1x;710 struct host1x *host1x;
711 int err;711 int err;
712 712
713 INIT_LIST_HEAD(&client->list);
714 mutex_init(&client->lock);
715 client->usecount = 0;
716
713 mutex_lock(&devices_lock);717 mutex_lock(&devices_lock);
714 718
715 list_for_each_entry(host1x, &devices, list) {719 list_for_each_entry(host1x, &devices, list) {
@@ -768,3 +772,74 @@ int host1x_client_unregister(struct host1x_client *client) · 52 unmodified lines
768 return 0;772 return 0;
769}773}
770EXPORT_SYMBOL(host1x_client_unregister);774EXPORT_SYMBOL(host1x_client_unregister);
775
776int host1x_client_suspend(struct host1x_client *client)
777{
778 int err = 0;
779
780 mutex_lock(&client->lock);
781
782 if (client->usecount == 1) {
783 if (client->ops && client->ops->suspend) {
784 err = client->ops->suspend(client);
785 if (err < 0)
786 goto unlock;
787 }
788 }
789
790 client->usecount--;
791 dev_dbg(client->dev, "use count: %u\n", client->usecount);
792
793 if (client->parent) {
794 err = host1x_client_suspend(client->parent);
795 if (err < 0)
796 goto resume;
797 }
798
799 goto unlock;
800
801resume:
802 if (client->usecount == 0)
803 if (client->ops && client->ops->resume)
804 client->ops->resume(client);
805
806 client->usecount++;
807unlock:
808 mutex_unlock(&client->lock);
809 return err;
810}
811EXPORT_SYMBOL(host1x_client_suspend);
812
813int host1x_client_resume(struct host1x_client *client)
814{
815 int err = 0;
816
817 mutex_lock(&client->lock);
818
819 if (client->parent) {
820 err = host1x_client_resume(client->parent);
821 if (err < 0)
822 goto unlock;
823 }
824
825 if (client->usecount == 0) {
826 if (client->ops && client->ops->resume) {
827 err = client->ops->resume(client);
828 if (err < 0)
829 goto suspend;
830 }
831 }
832
833 client->usecount++;
834 dev_dbg(client->dev, "use count: %u\n", client->usecount);
835
836 goto unlock;
837
838suspend:
839 if (client->parent)
840 host1x_client_suspend(client->parent);
841unlock:
842 mutex_unlock(&client->lock);
843 return err;
844}
845EXPORT_SYMBOL(host1x_client_resume);
include/linux/host1x.h+11−0
@@ -24,10 +24,14 @@ struct iommu_group; · 23 unmodified lines
24 * struct host1x_client_ops - host1x client operations24 * struct host1x_client_ops - host1x client operations
25 * @init: host1x client initialization code25 * @init: host1x client initialization code
26 * @exit: host1x client tear down code26 * @exit: host1x client tear down code
27 * @suspend: host1x client suspend code
28 * @resume: host1x client resume code
27 */29 */
28struct host1x_client_ops {30struct host1x_client_ops {
29 int (*init)(struct host1x_client *client);31 int (*init)(struct host1x_client *client);
30 int (*exit)(struct host1x_client *client);32 int (*exit)(struct host1x_client *client);
33 int (*suspend)(struct host1x_client *client);
34 int (*resume)(struct host1x_client *client);
31};35};
32 36
33/**37/**
@@ -55,6 +59,10 @@ struct host1x_client { · 21 unmodified lines
55 59
56 struct host1x_syncpt **syncpts;60 struct host1x_syncpt **syncpts;
57 unsigned int num_syncpts;61 unsigned int num_syncpts;
62
63 struct host1x_client *parent;
64 unsigned int usecount;
65 struct mutex lock;
58};66};
59 67
60/*68/*
@@ -322,6 +330,9 @@ int host1x_device_exit(struct host1x_device *device); · 261 unmodified lines
322int host1x_client_register(struct host1x_client *client);330int host1x_client_register(struct host1x_client *client);
323int host1x_client_unregister(struct host1x_client *client);331int host1x_client_unregister(struct host1x_client *client);
324 332
333int host1x_client_suspend(struct host1x_client *client);
334int host1x_client_resume(struct host1x_client *client);
335
325struct tegra_mipi_device;336struct tegra_mipi_device;
326 337
327struct tegra_mipi_device *tegra_mipi_request(struct device *device);338struct tegra_mipi_device *tegra_mipi_request(struct device *device);