xref: /openbmc/linux/drivers/gpu/drm/msm/dp/dp_power.c (revision f33ac92f)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
4  */
5 
6 #define pr_fmt(fmt)	"[drm-dp] %s: " fmt, __func__
7 
8 #include <linux/clk.h>
9 #include <linux/clk-provider.h>
10 #include <linux/regulator/consumer.h>
11 #include <linux/pm_opp.h>
12 #include "dp_power.h"
13 #include "msm_drv.h"
14 
15 struct dp_power_private {
16 	struct dp_parser *parser;
17 	struct platform_device *pdev;
18 	struct device *dev;
19 	struct clk *link_clk_src;
20 	struct clk *pixel_provider;
21 	struct clk *link_provider;
22 	struct regulator_bulk_data supplies[DP_DEV_REGULATOR_MAX];
23 
24 	struct dp_power dp_power;
25 };
26 
27 static void dp_power_regulator_disable(struct dp_power_private *power)
28 {
29 	struct regulator_bulk_data *s = power->supplies;
30 	const struct dp_reg_entry *regs = power->parser->regulator_cfg->regs;
31 	int num = power->parser->regulator_cfg->num;
32 	int i;
33 
34 	DBG("");
35 	for (i = num - 1; i >= 0; i--)
36 		if (regs[i].disable_load >= 0)
37 			regulator_set_load(s[i].consumer,
38 					   regs[i].disable_load);
39 
40 	regulator_bulk_disable(num, s);
41 }
42 
43 static int dp_power_regulator_enable(struct dp_power_private *power)
44 {
45 	struct regulator_bulk_data *s = power->supplies;
46 	const struct dp_reg_entry *regs = power->parser->regulator_cfg->regs;
47 	int num = power->parser->regulator_cfg->num;
48 	int ret, i;
49 
50 	DBG("");
51 	for (i = 0; i < num; i++) {
52 		if (regs[i].enable_load >= 0) {
53 			ret = regulator_set_load(s[i].consumer,
54 						 regs[i].enable_load);
55 			if (ret < 0) {
56 				pr_err("regulator %d set op mode failed, %d\n",
57 					i, ret);
58 				goto fail;
59 			}
60 		}
61 	}
62 
63 	ret = regulator_bulk_enable(num, s);
64 	if (ret < 0) {
65 		pr_err("regulator enable failed, %d\n", ret);
66 		goto fail;
67 	}
68 
69 	return 0;
70 
71 fail:
72 	for (i--; i >= 0; i--)
73 		regulator_set_load(s[i].consumer, regs[i].disable_load);
74 	return ret;
75 }
76 
77 static int dp_power_regulator_init(struct dp_power_private *power)
78 {
79 	struct regulator_bulk_data *s = power->supplies;
80 	const struct dp_reg_entry *regs = power->parser->regulator_cfg->regs;
81 	struct platform_device *pdev = power->pdev;
82 	int num = power->parser->regulator_cfg->num;
83 	int i, ret;
84 
85 	for (i = 0; i < num; i++)
86 		s[i].supply = regs[i].name;
87 
88 	ret = devm_regulator_bulk_get(&pdev->dev, num, s);
89 	if (ret < 0) {
90 		pr_err("%s: failed to init regulator, ret=%d\n",
91 						__func__, ret);
92 		return ret;
93 	}
94 
95 	return 0;
96 }
97 
98 static int dp_power_clk_init(struct dp_power_private *power)
99 {
100 	int rc = 0;
101 	struct dss_module_power *core, *ctrl, *stream;
102 	struct device *dev = &power->pdev->dev;
103 
104 	core = &power->parser->mp[DP_CORE_PM];
105 	ctrl = &power->parser->mp[DP_CTRL_PM];
106 	stream = &power->parser->mp[DP_STREAM_PM];
107 
108 	rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk);
109 	if (rc) {
110 		DRM_ERROR("failed to get %s clk. err=%d\n",
111 			dp_parser_pm_name(DP_CORE_PM), rc);
112 		return rc;
113 	}
114 
115 	rc = msm_dss_get_clk(dev, ctrl->clk_config, ctrl->num_clk);
116 	if (rc) {
117 		DRM_ERROR("failed to get %s clk. err=%d\n",
118 			dp_parser_pm_name(DP_CTRL_PM), rc);
119 		msm_dss_put_clk(core->clk_config, core->num_clk);
120 		return -ENODEV;
121 	}
122 
123 	rc = msm_dss_get_clk(dev, stream->clk_config, stream->num_clk);
124 	if (rc) {
125 		DRM_ERROR("failed to get %s clk. err=%d\n",
126 			dp_parser_pm_name(DP_CTRL_PM), rc);
127 		msm_dss_put_clk(core->clk_config, core->num_clk);
128 		return -ENODEV;
129 	}
130 
131 	return 0;
132 }
133 
134 static int dp_power_clk_deinit(struct dp_power_private *power)
135 {
136 	struct dss_module_power *core, *ctrl, *stream;
137 
138 	core = &power->parser->mp[DP_CORE_PM];
139 	ctrl = &power->parser->mp[DP_CTRL_PM];
140 	stream = &power->parser->mp[DP_STREAM_PM];
141 
142 	if (!core || !ctrl || !stream) {
143 		DRM_ERROR("invalid power_data\n");
144 		return -EINVAL;
145 	}
146 
147 	msm_dss_put_clk(ctrl->clk_config, ctrl->num_clk);
148 	msm_dss_put_clk(core->clk_config, core->num_clk);
149 	msm_dss_put_clk(stream->clk_config, stream->num_clk);
150 	return 0;
151 }
152 
153 static int dp_power_clk_set_link_rate(struct dp_power_private *power,
154 			struct dss_clk *clk_arry, int num_clk, int enable)
155 {
156 	u32 rate;
157 	int i, rc = 0;
158 
159 	for (i = 0; i < num_clk; i++) {
160 		if (clk_arry[i].clk) {
161 			if (clk_arry[i].type == DSS_CLK_PCLK) {
162 				if (enable)
163 					rate = clk_arry[i].rate;
164 				else
165 					rate = 0;
166 
167 				rc = dev_pm_opp_set_rate(power->dev, rate);
168 				if (rc)
169 					break;
170 			}
171 
172 		}
173 	}
174 	return rc;
175 }
176 
177 static int dp_power_clk_set_rate(struct dp_power_private *power,
178 		enum dp_pm_type module, bool enable)
179 {
180 	int rc = 0;
181 	struct dss_module_power *mp = &power->parser->mp[module];
182 
183 	if (module == DP_CTRL_PM) {
184 		rc = dp_power_clk_set_link_rate(power, mp->clk_config, mp->num_clk, enable);
185 		if (rc) {
186 			DRM_ERROR("failed to set link clks rate\n");
187 			return rc;
188 		}
189 	} else {
190 
191 		if (enable) {
192 			rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
193 			if (rc) {
194 				DRM_ERROR("failed to set clks rate\n");
195 				return rc;
196 			}
197 		}
198 	}
199 
200 	rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
201 	if (rc) {
202 		DRM_ERROR("failed to %d clks, err: %d\n", enable, rc);
203 		return rc;
204 	}
205 
206 	return 0;
207 }
208 
209 int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type)
210 {
211 	DRM_DEBUG_DP("core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n",
212 		dp_power->core_clks_on, dp_power->link_clks_on, dp_power->stream_clks_on);
213 
214 	if (pm_type == DP_CORE_PM)
215 		return dp_power->core_clks_on;
216 
217 	if (pm_type == DP_CTRL_PM)
218 		return dp_power->link_clks_on;
219 
220 	if (pm_type == DP_STREAM_PM)
221 		return dp_power->stream_clks_on;
222 
223 	return 0;
224 }
225 
226 int dp_power_clk_enable(struct dp_power *dp_power,
227 		enum dp_pm_type pm_type, bool enable)
228 {
229 	int rc = 0;
230 	struct dp_power_private *power;
231 
232 	power = container_of(dp_power, struct dp_power_private, dp_power);
233 
234 	if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM &&
235 			pm_type != DP_STREAM_PM) {
236 		DRM_ERROR("unsupported power module: %s\n",
237 				dp_parser_pm_name(pm_type));
238 		return -EINVAL;
239 	}
240 
241 	if (enable) {
242 		if (pm_type == DP_CORE_PM && dp_power->core_clks_on) {
243 			DRM_DEBUG_DP("core clks already enabled\n");
244 			return 0;
245 		}
246 
247 		if (pm_type == DP_CTRL_PM && dp_power->link_clks_on) {
248 			DRM_DEBUG_DP("links clks already enabled\n");
249 			return 0;
250 		}
251 
252 		if (pm_type == DP_STREAM_PM && dp_power->stream_clks_on) {
253 			DRM_DEBUG_DP("pixel clks already enabled\n");
254 			return 0;
255 		}
256 
257 		if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) {
258 			DRM_DEBUG_DP("Enable core clks before link clks\n");
259 
260 			rc = dp_power_clk_set_rate(power, DP_CORE_PM, enable);
261 			if (rc) {
262 				DRM_ERROR("fail to enable clks: %s. err=%d\n",
263 					dp_parser_pm_name(DP_CORE_PM), rc);
264 				return rc;
265 			}
266 			dp_power->core_clks_on = true;
267 		}
268 	}
269 
270 	rc = dp_power_clk_set_rate(power, pm_type, enable);
271 	if (rc) {
272 		DRM_ERROR("failed to '%s' clks for: %s. err=%d\n",
273 			enable ? "enable" : "disable",
274 			dp_parser_pm_name(pm_type), rc);
275 		return rc;
276 	}
277 
278 	if (pm_type == DP_CORE_PM)
279 		dp_power->core_clks_on = enable;
280 	else if (pm_type == DP_STREAM_PM)
281 		dp_power->stream_clks_on = enable;
282 	else
283 		dp_power->link_clks_on = enable;
284 
285 	DRM_DEBUG_DP("%s clocks for %s\n",
286 			enable ? "enable" : "disable",
287 			dp_parser_pm_name(pm_type));
288 	DRM_DEBUG_DP("strem_clks:%s link_clks:%s core_clks:%s\n",
289 		dp_power->stream_clks_on ? "on" : "off",
290 		dp_power->link_clks_on ? "on" : "off",
291 		dp_power->core_clks_on ? "on" : "off");
292 
293 	return 0;
294 }
295 
296 int dp_power_client_init(struct dp_power *dp_power)
297 {
298 	int rc = 0;
299 	struct dp_power_private *power;
300 
301 	if (!dp_power) {
302 		DRM_ERROR("invalid power data\n");
303 		return -EINVAL;
304 	}
305 
306 	power = container_of(dp_power, struct dp_power_private, dp_power);
307 
308 	pm_runtime_enable(&power->pdev->dev);
309 
310 	rc = dp_power_regulator_init(power);
311 	if (rc) {
312 		DRM_ERROR("failed to init regulators %d\n", rc);
313 		goto error;
314 	}
315 
316 	rc = dp_power_clk_init(power);
317 	if (rc) {
318 		DRM_ERROR("failed to init clocks %d\n", rc);
319 		goto error;
320 	}
321 	return 0;
322 
323 error:
324 	pm_runtime_disable(&power->pdev->dev);
325 	return rc;
326 }
327 
328 void dp_power_client_deinit(struct dp_power *dp_power)
329 {
330 	struct dp_power_private *power;
331 
332 	if (!dp_power) {
333 		DRM_ERROR("invalid power data\n");
334 		return;
335 	}
336 
337 	power = container_of(dp_power, struct dp_power_private, dp_power);
338 
339 	dp_power_clk_deinit(power);
340 	pm_runtime_disable(&power->pdev->dev);
341 
342 }
343 
344 int dp_power_init(struct dp_power *dp_power, bool flip)
345 {
346 	int rc = 0;
347 	struct dp_power_private *power = NULL;
348 
349 	if (!dp_power) {
350 		DRM_ERROR("invalid power data\n");
351 		return -EINVAL;
352 	}
353 
354 	power = container_of(dp_power, struct dp_power_private, dp_power);
355 
356 	pm_runtime_get_sync(&power->pdev->dev);
357 	rc = dp_power_regulator_enable(power);
358 	if (rc) {
359 		DRM_ERROR("failed to enable regulators, %d\n", rc);
360 		goto exit;
361 	}
362 
363 	rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
364 	if (rc) {
365 		DRM_ERROR("failed to enable DP core clocks, %d\n", rc);
366 		goto err_clk;
367 	}
368 
369 	return 0;
370 
371 err_clk:
372 	dp_power_regulator_disable(power);
373 exit:
374 	pm_runtime_put_sync(&power->pdev->dev);
375 	return rc;
376 }
377 
378 int dp_power_deinit(struct dp_power *dp_power)
379 {
380 	struct dp_power_private *power;
381 
382 	power = container_of(dp_power, struct dp_power_private, dp_power);
383 
384 	dp_power_clk_enable(dp_power, DP_CORE_PM, false);
385 	dp_power_regulator_disable(power);
386 	pm_runtime_put_sync(&power->pdev->dev);
387 	return 0;
388 }
389 
390 struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser)
391 {
392 	struct dp_power_private *power;
393 	struct dp_power *dp_power;
394 
395 	if (!parser) {
396 		DRM_ERROR("invalid input\n");
397 		return ERR_PTR(-EINVAL);
398 	}
399 
400 	power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL);
401 	if (!power)
402 		return ERR_PTR(-ENOMEM);
403 
404 	power->parser = parser;
405 	power->pdev = parser->pdev;
406 	power->dev = dev;
407 
408 	dp_power = &power->dp_power;
409 
410 	return dp_power;
411 }
412