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 = msm_dss_get_clk(dev, core->clk_config, core->num_clk);
39 DRM_ERROR("failed to get %s clk. err=%d\n",
40 dp_parser_pm_name(DP_CORE_PM), rc);
44 rc = msm_dss_get_clk(dev, ctrl->clk_config, ctrl->num_clk);
46 DRM_ERROR("failed to get %s clk. err=%d\n",
47 dp_parser_pm_name(DP_CTRL_PM), rc);
48 msm_dss_put_clk(core->clk_config, core->num_clk);
52 rc = msm_dss_get_clk(dev, stream->clk_config, stream->num_clk);
54 DRM_ERROR("failed to get %s clk. err=%d\n",
55 dp_parser_pm_name(DP_CTRL_PM), rc);
56 msm_dss_put_clk(core->clk_config, core->num_clk);
63 static int dp_power_clk_deinit(struct dp_power_private *power)
65 struct dss_module_power *core, *ctrl, *stream;
67 core = &power->parser->mp[DP_CORE_PM];
68 ctrl = &power->parser->mp[DP_CTRL_PM];
69 stream = &power->parser->mp[DP_STREAM_PM];
71 if (!core || !ctrl || !stream) {
72 DRM_ERROR("invalid power_data\n");
76 msm_dss_put_clk(ctrl->clk_config, ctrl->num_clk);
77 msm_dss_put_clk(core->clk_config, core->num_clk);
78 msm_dss_put_clk(stream->clk_config, stream->num_clk);
82 static int dp_power_clk_set_link_rate(struct dp_power_private *power,
83 struct dss_clk *clk_arry, int num_clk, int enable)
88 for (i = 0; i < num_clk; i++) {
89 if (clk_arry[i].clk) {
90 if (clk_arry[i].type == DSS_CLK_PCLK) {
92 rate = clk_arry[i].rate;
96 rc = dev_pm_opp_set_rate(power->dev, rate);
106 static int dp_power_clk_set_rate(struct dp_power_private *power,
107 enum dp_pm_type module, bool enable)
110 struct dss_module_power *mp = &power->parser->mp[module];
112 if (module == DP_CTRL_PM) {
113 rc = dp_power_clk_set_link_rate(power, mp->clk_config, mp->num_clk, enable);
115 DRM_ERROR("failed to set link clks rate\n");
121 rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
123 DRM_ERROR("failed to set clks rate\n");
129 rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
131 DRM_ERROR("failed to %d clks, err: %d\n", enable, rc);
138 int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type)
140 struct dp_power_private *power;
142 power = container_of(dp_power, struct dp_power_private, dp_power);
144 drm_dbg_dp(power->drm_dev,
145 "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n",
146 dp_power->core_clks_on, dp_power->link_clks_on, dp_power->stream_clks_on);
148 if (pm_type == DP_CORE_PM)
149 return dp_power->core_clks_on;
151 if (pm_type == DP_CTRL_PM)
152 return dp_power->link_clks_on;
154 if (pm_type == DP_STREAM_PM)
155 return dp_power->stream_clks_on;
160 int dp_power_clk_enable(struct dp_power *dp_power,
161 enum dp_pm_type pm_type, bool enable)
164 struct dp_power_private *power;
166 power = container_of(dp_power, struct dp_power_private, dp_power);
168 if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM &&
169 pm_type != DP_STREAM_PM) {
170 DRM_ERROR("unsupported power module: %s\n",
171 dp_parser_pm_name(pm_type));
176 if (pm_type == DP_CORE_PM && dp_power->core_clks_on) {
177 drm_dbg_dp(power->drm_dev,
178 "core clks already enabled\n");
182 if (pm_type == DP_CTRL_PM && dp_power->link_clks_on) {
183 drm_dbg_dp(power->drm_dev,
184 "links clks already enabled\n");
188 if (pm_type == DP_STREAM_PM && dp_power->stream_clks_on) {
189 drm_dbg_dp(power->drm_dev,
190 "pixel clks already enabled\n");
194 if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) {
195 drm_dbg_dp(power->drm_dev,
196 "Enable core clks before link clks\n");
198 rc = dp_power_clk_set_rate(power, DP_CORE_PM, enable);
200 DRM_ERROR("fail to enable clks: %s. err=%d\n",
201 dp_parser_pm_name(DP_CORE_PM), rc);
204 dp_power->core_clks_on = true;
208 rc = dp_power_clk_set_rate(power, pm_type, enable);
210 DRM_ERROR("failed to '%s' clks for: %s. err=%d\n",
211 enable ? "enable" : "disable",
212 dp_parser_pm_name(pm_type), rc);
216 if (pm_type == DP_CORE_PM)
217 dp_power->core_clks_on = enable;
218 else if (pm_type == DP_STREAM_PM)
219 dp_power->stream_clks_on = enable;
221 dp_power->link_clks_on = enable;
223 drm_dbg_dp(power->drm_dev, "%s clocks for %s\n",
224 enable ? "enable" : "disable",
225 dp_parser_pm_name(pm_type));
226 drm_dbg_dp(power->drm_dev,
227 "strem_clks:%s link_clks:%s core_clks:%s\n",
228 dp_power->stream_clks_on ? "on" : "off",
229 dp_power->link_clks_on ? "on" : "off",
230 dp_power->core_clks_on ? "on" : "off");
235 int dp_power_client_init(struct dp_power *dp_power)
238 struct dp_power_private *power;
241 DRM_ERROR("invalid power data\n");
245 power = container_of(dp_power, struct dp_power_private, dp_power);
247 pm_runtime_enable(&power->pdev->dev);
249 rc = dp_power_clk_init(power);
251 DRM_ERROR("failed to init clocks %d\n", rc);
256 void dp_power_client_deinit(struct dp_power *dp_power)
258 struct dp_power_private *power;
261 DRM_ERROR("invalid power data\n");
265 power = container_of(dp_power, struct dp_power_private, dp_power);
267 dp_power_clk_deinit(power);
268 pm_runtime_disable(&power->pdev->dev);
272 int dp_power_init(struct dp_power *dp_power, bool flip)
275 struct dp_power_private *power = NULL;
278 DRM_ERROR("invalid power data\n");
282 power = container_of(dp_power, struct dp_power_private, dp_power);
284 pm_runtime_get_sync(&power->pdev->dev);
286 rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
288 DRM_ERROR("failed to enable DP core clocks, %d\n", rc);
295 pm_runtime_put_sync(&power->pdev->dev);
299 int dp_power_deinit(struct dp_power *dp_power)
301 struct dp_power_private *power;
303 power = container_of(dp_power, struct dp_power_private, dp_power);
305 dp_power_clk_enable(dp_power, DP_CORE_PM, false);
306 pm_runtime_put_sync(&power->pdev->dev);
310 struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser)
312 struct dp_power_private *power;
313 struct dp_power *dp_power;
316 DRM_ERROR("invalid input\n");
317 return ERR_PTR(-EINVAL);
320 power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL);
322 return ERR_PTR(-ENOMEM);
324 power->parser = parser;
325 power->pdev = parser->pdev;
328 dp_power = &power->dp_power;