1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
6 #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
9 #include <linux/clk-provider.h>
10 #include <linux/regulator/consumer.h>
11 #include <linux/pm_opp.h>
15 struct dp_power_private {
16 struct dp_parser *parser;
17 struct platform_device *pdev;
19 struct drm_device *drm_dev;
20 struct clk *link_clk_src;
21 struct clk *pixel_provider;
22 struct clk *link_provider;
24 struct dp_power dp_power;
27 static int dp_power_clk_init(struct dp_power_private *power)
30 struct dss_module_power *core, *ctrl, *stream;
31 struct device *dev = &power->pdev->dev;
33 core = &power->parser->mp[DP_CORE_PM];
34 ctrl = &power->parser->mp[DP_CTRL_PM];
35 stream = &power->parser->mp[DP_STREAM_PM];
37 rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks);
39 DRM_ERROR("failed to get %s clk. err=%d\n",
40 dp_parser_pm_name(DP_CORE_PM), rc);
44 rc = devm_clk_bulk_get(dev, ctrl->num_clk, ctrl->clocks);
46 DRM_ERROR("failed to get %s clk. err=%d\n",
47 dp_parser_pm_name(DP_CTRL_PM), rc);
51 rc = devm_clk_bulk_get(dev, stream->num_clk, stream->clocks);
53 DRM_ERROR("failed to get %s clk. err=%d\n",
54 dp_parser_pm_name(DP_CTRL_PM), rc);
61 int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type)
63 struct dp_power_private *power;
65 power = container_of(dp_power, struct dp_power_private, dp_power);
67 drm_dbg_dp(power->drm_dev,
68 "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n",
69 dp_power->core_clks_on, dp_power->link_clks_on, dp_power->stream_clks_on);
71 if (pm_type == DP_CORE_PM)
72 return dp_power->core_clks_on;
74 if (pm_type == DP_CTRL_PM)
75 return dp_power->link_clks_on;
77 if (pm_type == DP_STREAM_PM)
78 return dp_power->stream_clks_on;
83 int dp_power_clk_enable(struct dp_power *dp_power,
84 enum dp_pm_type pm_type, bool enable)
87 struct dp_power_private *power;
88 struct dss_module_power *mp;
90 power = container_of(dp_power, struct dp_power_private, dp_power);
92 if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM &&
93 pm_type != DP_STREAM_PM) {
94 DRM_ERROR("unsupported power module: %s\n",
95 dp_parser_pm_name(pm_type));
100 if (pm_type == DP_CORE_PM && dp_power->core_clks_on) {
101 drm_dbg_dp(power->drm_dev,
102 "core clks already enabled\n");
106 if (pm_type == DP_CTRL_PM && dp_power->link_clks_on) {
107 drm_dbg_dp(power->drm_dev,
108 "links clks already enabled\n");
112 if (pm_type == DP_STREAM_PM && dp_power->stream_clks_on) {
113 drm_dbg_dp(power->drm_dev,
114 "pixel clks already enabled\n");
118 if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) {
119 drm_dbg_dp(power->drm_dev,
120 "Enable core clks before link clks\n");
121 mp = &power->parser->mp[DP_CORE_PM];
123 rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks);
125 DRM_ERROR("fail to enable clks: %s. err=%d\n",
126 dp_parser_pm_name(DP_CORE_PM), rc);
129 dp_power->core_clks_on = true;
133 mp = &power->parser->mp[pm_type];
135 rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks);
137 DRM_ERROR("failed to enable clks, err: %d\n", rc);
141 clk_bulk_disable_unprepare(mp->num_clk, mp->clocks);
144 if (pm_type == DP_CORE_PM)
145 dp_power->core_clks_on = enable;
146 else if (pm_type == DP_STREAM_PM)
147 dp_power->stream_clks_on = enable;
149 dp_power->link_clks_on = enable;
151 drm_dbg_dp(power->drm_dev, "%s clocks for %s\n",
152 enable ? "enable" : "disable",
153 dp_parser_pm_name(pm_type));
154 drm_dbg_dp(power->drm_dev,
155 "strem_clks:%s link_clks:%s core_clks:%s\n",
156 dp_power->stream_clks_on ? "on" : "off",
157 dp_power->link_clks_on ? "on" : "off",
158 dp_power->core_clks_on ? "on" : "off");
163 int dp_power_client_init(struct dp_power *dp_power)
166 struct dp_power_private *power;
169 DRM_ERROR("invalid power data\n");
173 power = container_of(dp_power, struct dp_power_private, dp_power);
175 pm_runtime_enable(&power->pdev->dev);
177 rc = dp_power_clk_init(power);
179 DRM_ERROR("failed to init clocks %d\n", rc);
184 void dp_power_client_deinit(struct dp_power *dp_power)
186 struct dp_power_private *power;
189 DRM_ERROR("invalid power data\n");
193 power = container_of(dp_power, struct dp_power_private, dp_power);
195 pm_runtime_disable(&power->pdev->dev);
198 int dp_power_init(struct dp_power *dp_power, bool flip)
201 struct dp_power_private *power = NULL;
204 DRM_ERROR("invalid power data\n");
208 power = container_of(dp_power, struct dp_power_private, dp_power);
210 pm_runtime_get_sync(&power->pdev->dev);
212 rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
214 DRM_ERROR("failed to enable DP core clocks, %d\n", rc);
221 pm_runtime_put_sync(&power->pdev->dev);
225 int dp_power_deinit(struct dp_power *dp_power)
227 struct dp_power_private *power;
229 power = container_of(dp_power, struct dp_power_private, dp_power);
231 dp_power_clk_enable(dp_power, DP_CORE_PM, false);
232 pm_runtime_put_sync(&power->pdev->dev);
236 struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser)
238 struct dp_power_private *power;
239 struct dp_power *dp_power;
242 DRM_ERROR("invalid input\n");
243 return ERR_PTR(-EINVAL);
246 power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL);
248 return ERR_PTR(-ENOMEM);
250 power->parser = parser;
251 power->pdev = parser->pdev;
254 dp_power = &power->dp_power;