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
17271727 {
17281728 struct tegra_dc *dc = to_tegra_dc(crtc);
17291729 u32 value;
1730+ int err;
17301731
17311732 if (!tegra_dc_idle(dc)) {
17321733 tegra_dc_stop(dc);
@@ -1773,7 +1774,9 @@ static void tegra_crtc_atomic_disable(struct drm_crtc *crtc, · 40 unmodified lines
17731774
17741775 spin_unlock_irq(&crtc->dev->event_lock);
17751776
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);
17771780 }
17781781
17791782 static 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
17831786 struct tegra_dc_state *state = to_dc_state(crtc->state);
17841787 struct tegra_dc *dc = to_tegra_dc(crtc);
17851788 u32 value;
1789+ int err;
17861790
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+ }
17881796
17891797 /* initialize display controller */
17901798 if (dc->syncpt) {
@@ -2012,6 +2020,15 @@ static int tegra_dc_init(struct host1x_client *client) · 221 unmodified lines
20122020 if (!tegra_dc_has_window_groups(dc))
20132021 return 0;
20142022
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+
20152032 dc->syncpt = host1x_syncpt_request(client, flags);
20162033 if (!dc->syncpt)
20172034 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
21212138 return 0;
21222139 }
21232140
2141+static 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+
2162+static 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+
2197+disable_clk:
2198+ clk_disable_unprepare(dc->clk);
2199+put_rpm:
2200+ pm_runtime_put_sync(dev);
2201+ return err;
2202+}
2203+
21242204 static const struct host1x_client_ops dc_client_ops = {
21252205 .init = tegra_dc_init,
21262206 .exit = tegra_dc_exit,
2207+ .suspend = tegra_dc_runtime_suspend,
2208+ .resume = tegra_dc_runtime_resume,
21272209 };
21282210
21292211 static 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
25352617 return 0;
25362618 }
25372619
2538−#ifdef CONFIG_PM
2539−static 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−
2558−static 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−
2588−static const struct dev_pm_ops tegra_dc_pm_ops = {
2589− SET_RUNTIME_PM_OPS(tegra_dc_suspend, tegra_dc_resume, NULL)
2590−};
2591−
25922620 struct platform_driver tegra_dc_driver = {
25932621 .driver = {
25942622 .name = "tegra-dc",
25952623 .of_match_table = tegra_dc_of_match,
2596− .pm = &tegra_dc_pm_ops,
25972624 },
25982625 .probe = tegra_dc_probe,
25992626 .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
588588 /* make sure pads are powered down when not in use */
589589 tegra_dpaux_pad_power_down(dpaux);
590590
591− pm_runtime_put(&pdev->dev);
591+ pm_runtime_put_sync(&pdev->dev);
592592 pm_runtime_disable(&pdev->dev);
593593
594594 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
144144 void tegra_output_exit(struct tegra_output *output);
145145 void tegra_output_find_possible_crtcs(struct tegra_output *output,
146146 struct drm_device *drm);
147+int tegra_output_suspend(struct tegra_output *output);
148+int tegra_output_resume(struct tegra_output *output);
147149
148150 int tegra_output_connector_get_modes(struct drm_connector *connector);
149151 enum 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
840840 dev_err(dsi->dev, "failed to disable MIPI calibration: %d\n",
841841 err);
842842
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);
844846 }
845847
846848 static 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
882884 tegra_dsi_unprepare(dsi);
883885 }
884886
885−static void tegra_dsi_prepare(struct tegra_dsi *dsi)
887+static int tegra_dsi_prepare(struct tegra_dsi *dsi)
886888 {
887889 int err;
888890
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+ }
890896
891897 err = tegra_mipi_enable(dsi->mipi);
892898 if (err < 0)
@@ -899,6 +905,8 @@ static void tegra_dsi_prepare(struct tegra_dsi *dsi) · 6 unmodified lines
899905
900906 if (dsi->slave)
901907 tegra_dsi_prepare(dsi->slave);
908+
909+ return 0;
902910 }
903911
904912 static 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
909917 struct tegra_dsi *dsi = to_dsi(output);
910918 struct tegra_dsi_state *state;
911919 u32 value;
920+ int err;
912921
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+ }
914927
915928 state = tegra_dsi_get_state(dsi);
916929
@@ -1075,9 +1088,89 @@ static int tegra_dsi_exit(struct host1x_client *client) · 158 unmodified lines
10751088 return 0;
10761089 }
10771090
1091+static 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+
1116+static 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+
1158+disable_clk_lp:
1159+ clk_disable_unprepare(dsi->clk_lp);
1160+disable_clk:
1161+ clk_disable_unprepare(dsi->clk);
1162+disable_vdd:
1163+ regulator_disable(dsi->vdd);
1164+put_rpm:
1165+ pm_runtime_put_sync(dev);
1166+ return err;
1167+}
1168+
10781169 static const struct host1x_client_ops dsi_client_ops = {
10791170 .init = tegra_dsi_init,
10801171 .exit = tegra_dsi_exit,
1172+ .suspend = tegra_dsi_runtime_suspend,
1173+ .resume = tegra_dsi_runtime_resume,
10811174 };
10821175
10831176 static 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
15961689 return 0;
15971690 }
15981691
1599−#ifdef CONFIG_PM
1600−static 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−
1623−static 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−
1658−disable_clk_lp:
1659− clk_disable_unprepare(dsi->clk_lp);
1660−disable_clk:
1661− clk_disable_unprepare(dsi->clk);
1662−disable_vdd:
1663− regulator_disable(dsi->vdd);
1664− return err;
1665−}
1666−#endif
1667−
1668−static const struct dev_pm_ops tegra_dsi_pm_ops = {
1669− SET_RUNTIME_PM_OPS(tegra_dsi_suspend, tegra_dsi_resume, NULL)
1670−};
1671−
16721692 static const struct of_device_id tegra_dsi_of_match[] = {
16731693 { .compatible = "nvidia,tegra210-dsi", },
16741694 { .compatible = "nvidia,tegra132-dsi", },
@@ -1682,7 +1702,6 @@ struct platform_driver tegra_dsi_driver = { · 7 unmodified lines
16821702 .driver = {
16831703 .name = "tegra-dsi",
16841704 .of_match_table = tegra_dsi_of_match,
1685− .pm = &tegra_dsi_pm_ops,
16861705 },
16871706 .probe = tegra_dsi_probe,
16881707 .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
11461146 struct tegra_dc *dc = to_tegra_dc(encoder->crtc);
11471147 struct tegra_hdmi *hdmi = to_hdmi(output);
11481148 u32 value;
1149+ int err;
11491150
11501151 /*
11511152 * 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
11711172 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_ENABLE);
11721173 tegra_hdmi_writel(hdmi, 0, HDMI_NV_PDISP_INT_MASK);
11731174
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);
11751178 }
11761179
11771180 static 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
11861189 u32 value;
11871190 int err;
11881191
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+ }
11901197
11911198 /*
11921199 * 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
14891496 return 0;
14901497 }
14911498
1499+static 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+
1519+static 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+
1547+disable_clk:
1548+ clk_disable_unprepare(hdmi->clk);
1549+put_rpm:
1550+ pm_runtime_put_sync(dev);
1551+ return err;
1552+}
1553+
14921554 static const struct host1x_client_ops hdmi_client_ops = {
14931555 .init = tegra_hdmi_init,
14941556 .exit = tegra_hdmi_exit,
1557+ .suspend = tegra_hdmi_runtime_suspend,
1558+ .resume = tegra_hdmi_runtime_resume,
14951559 };
14961560
14971561 static const struct tegra_hdmi_config tegra20_hdmi_config = {
@@ -1699,58 +1763,10 @@ static int tegra_hdmi_remove(struct platform_device *pdev) · 201 unmodified lines
16991763 return 0;
17001764 }
17011765
1702−#ifdef CONFIG_PM
1703−static 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−
1721−static 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−
1745−static const struct dev_pm_ops tegra_hdmi_pm_ops = {
1746− SET_RUNTIME_PM_OPS(tegra_hdmi_suspend, tegra_hdmi_resume, NULL)
1747−};
1748−
17491766 struct platform_driver tegra_hdmi_driver = {
17501767 .driver = {
17511768 .name = "tegra-hdmi",
17521769 .of_match_table = tegra_hdmi_of_match,
1753− .pm = &tegra_hdmi_pm_ops,
17541770 },
17551771 .probe = tegra_hdmi_probe,
17561772 .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
9595
9696 static int tegra_windowgroup_enable(struct tegra_windowgroup *wgrp)
9797 {
98+ int err = 0;
99+
98100 mutex_lock(&wgrp->lock);
99101
100102 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+
102109 reset_control_deassert(wgrp->rst);
103110 }
104111
105112 wgrp->usecount++;
106− mutex_unlock(&wgrp->lock);
107113
108− return 0;
114+unlock:
115+ mutex_unlock(&wgrp->lock);
116+ return err;
109117 }
110118
111119 static void tegra_windowgroup_disable(struct tegra_windowgroup *wgrp)
@@ -121,7 +129,7 @@ static void tegra_windowgroup_disable(struct tegra_windowgroup *wgrp) · 9 unmodified lines
121129 wgrp->index);
122130 }
123131
124− pm_runtime_put(wgrp->parent);
132+ host1x_client_suspend(wgrp->parent);
125133 }
126134
127135 wgrp->usecount--;
@@ -379,6 +387,7 @@ static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, · 251 unmodified lines
379387 struct tegra_plane *p = to_tegra_plane(plane);
380388 struct tegra_dc *dc;
381389 u32 value;
390+ int err;
382391
383392 /* rien ne va plus */
384393 if (!old_state || !old_state->crtc)
@@ -386,6 +395,12 @@ static void tegra_shared_plane_atomic_disable(struct drm_plane *plane, · 1 unmodified line
386395
387396 dc = to_tegra_dc(old_state->crtc);
388397
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+
389404 /*
390405 * XXX Legacy helpers seem to sometimes call ->atomic_disable() even
391406 * 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
394409 if (WARN_ON(p->dc == NULL))
395410 p->dc = dc;
396411
397− pm_runtime_get_sync(dc->dev);
398−
399412 value = tegra_plane_readl(p, DC_WIN_WIN_OPTIONS);
400413 value &= ~WIN_ENABLE;
401414 tegra_plane_writel(p, value, DC_WIN_WIN_OPTIONS);
402415
403416 tegra_dc_remove_shared_plane(dc, p);
404417
405− pm_runtime_put(dc->dev);
418+ host1x_client_suspend(&dc->client);
406419 }
407420
408421 static 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
415428 struct tegra_plane *p = to_tegra_plane(plane);
416429 dma_addr_t base;
417430 u32 value;
431+ int err;
418432
419433 /* rien ne va plus */
420434 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
425439 return;
426440 }
427441
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+ }
429447
430448 tegra_dc_assign_shared_plane(dc, p);
431449
@@ -515,7 +533,7 @@ static void tegra_shared_plane_atomic_update(struct drm_plane *plane, · 83 unmodified lines
515533 value &= ~CONTROL_CSC_ENABLE;
516534 tegra_plane_writel(p, value, DC_WIN_WINDOW_SET_CONTROL);
517535
518− pm_runtime_put(dc->dev);
536+ host1x_client_suspend(&dc->client);
519537 }
520538
521539 static 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
551569 plane->base.index = index;
552570
553571 plane->wgrp = &hub->wgrps[wgrp];
554− plane->wgrp->parent = dc->dev;
572+ plane->wgrp->parent = &dc->client;
555573
556574 p = &plane->base.base;
557575
@@ -656,8 +674,13 @@ int tegra_display_hub_atomic_check(struct drm_device *drm, · 98 unmodified lines
656674 static void tegra_display_hub_update(struct tegra_dc *dc)
657675 {
658676 u32 value;
677+ int err;
659678
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+ }
661684
662685 value = tegra_dc_readl(dc, DC_CMD_IHUB_COMMON_MISC_CTL);
663686 value &= ~LATENCY_EVENT;
@@ -672,7 +695,7 @@ static void tegra_display_hub_update(struct tegra_dc *dc) · 8 unmodified lines
672695 tegra_dc_writel(dc, COMMON_ACTREQ, DC_CMD_STATE_CONTROL);
673696 tegra_dc_readl(dc, DC_CMD_STATE_CONTROL);
674697
675− pm_runtime_put(dc->dev);
698+ host1x_client_suspend(&dc->client);
676699 }
677700
678701 void 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
732755 return 0;
733756 }
734757
758+static 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+
781+static 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+
818+disable_heads:
819+ while (i--)
820+ clk_disable_unprepare(hub->clk_heads[i]);
821+
822+ clk_disable_unprepare(hub->clk_hub);
823+disable_dsc:
824+ clk_disable_unprepare(hub->clk_dsc);
825+disable_disp:
826+ clk_disable_unprepare(hub->clk_disp);
827+put_rpm:
828+ pm_runtime_put_sync(dev);
829+ return err;
830+}
831+
735832 static const struct host1x_client_ops tegra_display_hub_ops = {
736833 .init = tegra_display_hub_init,
737834 .exit = tegra_display_hub_exit,
835+ .suspend = tegra_display_hub_runtime_suspend,
836+ .resume = tegra_display_hub_runtime_resume,
738837 };
739838
740839 static 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
851950 static int tegra_display_hub_remove(struct platform_device *pdev)
852951 {
853952 struct tegra_display_hub *hub = platform_get_drvdata(pdev);
953+ unsigned int i;
854954 int err;
855955
856956 err = host1x_client_unregister(&hub->client);
@@ -859,78 +959,17 @@ static int tegra_display_hub_remove(struct platform_device *pdev) · 2 unmodified lines
859959 err);
860960 }
861961
862− pm_runtime_disable(&pdev->dev);
863−
864− return err;
865−}
866−
867−static 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−
887−static 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;
962+ for (i = 0; i < hub->soc->num_wgrps; i++) {
963+ struct tegra_windowgroup *wgrp = &hub->wgrps[i];
904964
905− for (i = 0; i < hub->num_heads; i++) {
906− err = clk_prepare_enable(hub->clk_heads[i]);
907− if (err < 0)
908− goto disable_heads;
965+ mutex_destroy(&wgrp->lock);
909966 }
910967
911− err = reset_control_deassert(hub->rst);
912− if (err < 0)
913− goto disable_heads;
914−
915− return 0;
916−
917−disable_heads:
918− while (i--)
919− clk_disable_unprepare(hub->clk_heads[i]);
968+ pm_runtime_disable(&pdev->dev);
920969
921− clk_disable_unprepare(hub->clk_hub);
922−disable_dsc:
923− clk_disable_unprepare(hub->clk_dsc);
924−disable_disp:
925− clk_disable_unprepare(hub->clk_disp);
926970 return err;
927971 }
928972
929−static 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−
934973 static const struct tegra_display_hub_soc tegra186_display_hub = {
935974 .num_wgrps = 6,
936975 .supports_dsc = true,
@@ -958,7 +997,6 @@ struct platform_driver tegra_display_hub_driver = { · 21 unmodified lines
958997 .driver = {
959998 .name = "tegra-display-hub",
960999 .of_match_table = tegra_display_hub_of_match,
961− .pm = &tegra_display_hub_pm_ops,
9621000 },
9631001 .probe = tegra_display_hub_probe,
9641002 .remove = tegra_display_hub_remove,
drivers/gpu/drm/tegra/hub.h+1−1
@@ -17,7 +17,7 @@ struct tegra_windowgroup { · 16 unmodified lines
1717 struct mutex lock;
1818
1919 unsigned int index;
20− struct device *parent;
20+ struct host1x_client *parent;
2121 struct reset_control *rst;
2222 };
2323
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
22552255 if (err < 0)
22562256 dev_err(sor->dev, "failed to power off I/O pad: %d\n", err);
22572257
2258− pm_runtime_put(sor->dev);
2258+ host1x_client_suspend(&sor->client);
22592259 }
22602260
22612261 static 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
22762276 mode = &encoder->crtc->state->adjusted_mode;
22772277 pclk = mode->clock * 1000;
22782278
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+ }
22802284
22812285 /* switch to safe parent clock */
22822286 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
27222726 if (output->panel)
27232727 drm_panel_unprepare(output->panel);
27242728
2725− pm_runtime_put(sor->dev);
2729+ host1x_client_suspend(&sor->client);
27262730 }
27272731
27282732 static 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
27422746 mode = &encoder->crtc->state->adjusted_mode;
27432747 info = &output->connector.display_info;
27442748
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+ }
27462754
27472755 /* switch to safe parent clock */
27482756 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
31893197 return 0;
31903198 }
31913199
3200+static 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+
3224+static 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+
3260+release_reset:
3261+ reset_control_release(sor->rst);
3262+disable_clk:
3263+ clk_disable_unprepare(sor->clk);
3264+put_rpm:
3265+ pm_runtime_put_sync(dev);
3266+ return err;
3267+}
3268+
31923269 static const struct host1x_client_ops sor_client_ops = {
31933270 .init = tegra_sor_init,
31943271 .exit = tegra_sor_exit,
3272+ .suspend = tegra_sor_runtime_suspend,
3273+ .resume = tegra_sor_runtime_resume,
31953274 };
31963275
31973276 static const u8 tegra124_sor_xbar_cfg[5] = {
@@ -3842,10 +3921,9 @@ static int tegra_sor_probe(struct platform_device *pdev) · 644 unmodified lines
38423921 if (!sor->clk_pad) {
38433922 char *name;
38443923
3845− err = pm_runtime_get_sync(&pdev->dev);
3924+ err = host1x_client_resume(&sor->client);
38463925 if (err < 0) {
3847− dev_err(&pdev->dev, "failed to get runtime PM: %d\n",
3848− err);
3926+ dev_err(sor->dev, "failed to resume: %d\n", err);
38493927 goto remove;
38503928 }
38513929
@@ -3856,7 +3934,7 @@ static int tegra_sor_probe(struct platform_device *pdev) · 4 unmodified lines
38563934 }
38573935
38583936 sor->clk_pad = tegra_clk_sor_pad_register(sor, name);
3859− pm_runtime_put(&pdev->dev);
3937+ host1x_client_suspend(&sor->client);
38603938 }
38613939
38623940 if (IS_ERR(sor->clk_pad)) {
@@ -3912,61 +3990,6 @@ static int tegra_sor_remove(struct platform_device *pdev) · 49 unmodified lines
39123990 return 0;
39133991 }
39143992
3915−static 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−
3937−static 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−
39703993 static int tegra_sor_suspend(struct device *dev)
39713994 {
39723995 struct tegra_sor *sor = dev_get_drvdata(dev);
@@ -3974,8 +3997,9 @@ static int tegra_sor_suspend(struct device *dev) · 1 unmodified line
39743997
39753998 if (sor->hdmi_supply) {
39763999 err = regulator_disable(sor->hdmi_supply);
3977− if (err < 0)
4000+ if (err < 0) {
39784001 return err;
4002+ }
39794003 }
39804004
39814005 return 0;
@@ -3996,8 +4020,6 @@ static int tegra_sor_resume(struct device *dev) · 14 unmodified lines
39964020 }
39974021
39984022 static const struct dev_pm_ops tegra_sor_pm_ops = {
3999− SET_RUNTIME_PM_OPS(tegra_sor_runtime_suspend, tegra_sor_runtime_resume,
4000− NULL)
40014023 SET_SYSTEM_SLEEP_PM_OPS(tegra_sor_suspend, tegra_sor_resume)
40024024 };
40034025
drivers/gpu/host1x/bus.c+75−0
@@ -710,6 +710,10 @@ int host1x_client_register(struct host1x_client *client) · 709 unmodified lines
710710 struct host1x *host1x;
711711 int err;
712712
713+ INIT_LIST_HEAD(&client->list);
714+ mutex_init(&client->lock);
715+ client->usecount = 0;
716+
713717 mutex_lock(&devices_lock);
714718
715719 list_for_each_entry(host1x, &devices, list) {
@@ -768,3 +772,74 @@ int host1x_client_unregister(struct host1x_client *client) · 52 unmodified lines
768772 return 0;
769773 }
770774 EXPORT_SYMBOL(host1x_client_unregister);
775+
776+int 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+
801+resume:
802+ if (client->usecount == 0)
803+ if (client->ops && client->ops->resume)
804+ client->ops->resume(client);
805+
806+ client->usecount++;
807+unlock:
808+ mutex_unlock(&client->lock);
809+ return err;
810+}
811+EXPORT_SYMBOL(host1x_client_suspend);
812+
813+int 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+
838+suspend:
839+ if (client->parent)
840+ host1x_client_suspend(client->parent);
841+unlock:
842+ mutex_unlock(&client->lock);
843+ return err;
844+}
845+EXPORT_SYMBOL(host1x_client_resume);
include/linux/host1x.h+11−0
@@ -24,10 +24,14 @@ struct iommu_group; · 23 unmodified lines
2424 * struct host1x_client_ops - host1x client operations
2525 * @init: host1x client initialization code
2626 * @exit: host1x client tear down code
27+ * @suspend: host1x client suspend code
28+ * @resume: host1x client resume code
2729 */
2830 struct host1x_client_ops {
2931 int (*init)(struct host1x_client *client);
3032 int (*exit)(struct host1x_client *client);
33+ int (*suspend)(struct host1x_client *client);
34+ int (*resume)(struct host1x_client *client);
3135 };
3236
3337 /**
@@ -55,6 +59,10 @@ struct host1x_client { · 21 unmodified lines
5559
5660 struct host1x_syncpt **syncpts;
5761 unsigned int num_syncpts;
62+
63+ struct host1x_client *parent;
64+ unsigned int usecount;
65+ struct mutex lock;
5866 };
5967
6068 /*
@@ -322,6 +330,9 @@ int host1x_device_exit(struct host1x_device *device); · 261 unmodified lines
322330 int host1x_client_register(struct host1x_client *client);
323331 int host1x_client_unregister(struct host1x_client *client);
324332
333+int host1x_client_suspend(struct host1x_client *client);
334+int host1x_client_resume(struct host1x_client *client);
335+
325336 struct tegra_mipi_device;
326337
327338 struct tegra_mipi_device *tegra_mipi_request(struct device *device);