xref: /openbmc/linux/drivers/gpu/drm/msm/dp/dp_power.c (revision 83c4a4ee)
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 	if (pm_type == DP_CORE_PM)
212 		return dp_power->core_clks_on;
213 
214 	if (pm_type == DP_CTRL_PM)
215 		return dp_power->link_clks_on;
216 
217 	if (pm_type == DP_STREAM_PM)
218 		return dp_power->stream_clks_on;
219 
220 	return 0;
221 }
222 
223 int dp_power_clk_enable(struct dp_power *dp_power,
224 		enum dp_pm_type pm_type, bool enable)
225 {
226 	int rc = 0;
227 	struct dp_power_private *power;
228 
229 	power = container_of(dp_power, struct dp_power_private, dp_power);
230 
231 	if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM &&
232 			pm_type != DP_STREAM_PM) {
233 		DRM_ERROR("unsupported power module: %s\n",
234 				dp_parser_pm_name(pm_type));
235 		return -EINVAL;
236 	}
237 
238 	if (enable) {
239 		if (pm_type == DP_CORE_PM && dp_power->core_clks_on) {
240 			DRM_DEBUG_DP("core clks already enabled\n");
241 			return 0;
242 		}
243 
244 		if (pm_type == DP_CTRL_PM && dp_power->link_clks_on) {
245 			DRM_DEBUG_DP("links clks already enabled\n");
246 			return 0;
247 		}
248 
249 		if (pm_type == DP_STREAM_PM && dp_power->stream_clks_on) {
250 			DRM_DEBUG_DP("pixel clks already enabled\n");
251 			return 0;
252 		}
253 
254 		if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) {
255 			DRM_DEBUG_DP("Enable core clks before link clks\n");
256 
257 			rc = dp_power_clk_set_rate(power, DP_CORE_PM, enable);
258 			if (rc) {
259 				DRM_ERROR("fail to enable clks: %s. err=%d\n",
260 					dp_parser_pm_name(DP_CORE_PM), rc);
261 				return rc;
262 			}
263 			dp_power->core_clks_on = true;
264 		}
265 	}
266 
267 	rc = dp_power_clk_set_rate(power, pm_type, enable);
268 	if (rc) {
269 		DRM_ERROR("failed to '%s' clks for: %s. err=%d\n",
270 			enable ? "enable" : "disable",
271 			dp_parser_pm_name(pm_type), rc);
272 			return rc;
273 	}
274 
275 	if (pm_type == DP_CORE_PM)
276 		dp_power->core_clks_on = enable;
277 	else if (pm_type == DP_STREAM_PM)
278 		dp_power->stream_clks_on = enable;
279 	else
280 		dp_power->link_clks_on = enable;
281 
282 	DRM_DEBUG_DP("%s clocks for %s\n",
283 			enable ? "enable" : "disable",
284 			dp_parser_pm_name(pm_type));
285 	DRM_DEBUG_DP("strem_clks:%s link_clks:%s core_clks:%s\n",
286 		dp_power->stream_clks_on ? "on" : "off",
287 		dp_power->link_clks_on ? "on" : "off",
288 		dp_power->core_clks_on ? "on" : "off");
289 
290 	return 0;
291 }
292 
293 int dp_power_client_init(struct dp_power *dp_power)
294 {
295 	int rc = 0;
296 	struct dp_power_private *power;
297 
298 	if (!dp_power) {
299 		DRM_ERROR("invalid power data\n");
300 		return -EINVAL;
301 	}
302 
303 	power = container_of(dp_power, struct dp_power_private, dp_power);
304 
305 	pm_runtime_enable(&power->pdev->dev);
306 
307 	rc = dp_power_regulator_init(power);
308 	if (rc) {
309 		DRM_ERROR("failed to init regulators %d\n", rc);
310 		goto error;
311 	}
312 
313 	rc = dp_power_clk_init(power);
314 	if (rc) {
315 		DRM_ERROR("failed to init clocks %d\n", rc);
316 		goto error;
317 	}
318 	return 0;
319 
320 error:
321 	pm_runtime_disable(&power->pdev->dev);
322 	return rc;
323 }
324 
325 void dp_power_client_deinit(struct dp_power *dp_power)
326 {
327 	struct dp_power_private *power;
328 
329 	if (!dp_power) {
330 		DRM_ERROR("invalid power data\n");
331 		return;
332 	}
333 
334 	power = container_of(dp_power, struct dp_power_private, dp_power);
335 
336 	dp_power_clk_deinit(power);
337 	pm_runtime_disable(&power->pdev->dev);
338 
339 }
340 
341 int dp_power_init(struct dp_power *dp_power, bool flip)
342 {
343 	int rc = 0;
344 	struct dp_power_private *power = NULL;
345 
346 	if (!dp_power) {
347 		DRM_ERROR("invalid power data\n");
348 		return -EINVAL;
349 	}
350 
351 	power = container_of(dp_power, struct dp_power_private, dp_power);
352 
353 	pm_runtime_get_sync(&power->pdev->dev);
354 	rc = dp_power_regulator_enable(power);
355 	if (rc) {
356 		DRM_ERROR("failed to enable regulators, %d\n", rc);
357 		goto exit;
358 	}
359 
360 	rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
361 	if (rc) {
362 		DRM_ERROR("failed to enable DP core clocks, %d\n", rc);
363 		goto err_clk;
364 	}
365 
366 	return 0;
367 
368 err_clk:
369 	dp_power_regulator_disable(power);
370 exit:
371 	pm_runtime_put_sync(&power->pdev->dev);
372 	return rc;
373 }
374 
375 int dp_power_deinit(struct dp_power *dp_power)
376 {
377 	struct dp_power_private *power;
378 
379 	power = container_of(dp_power, struct dp_power_private, dp_power);
380 
381 	dp_power_clk_enable(dp_power, DP_CORE_PM, false);
382 	dp_power_regulator_disable(power);
383 	pm_runtime_put_sync(&power->pdev->dev);
384 	return 0;
385 }
386 
387 struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser)
388 {
389 	struct dp_power_private *power;
390 	struct dp_power *dp_power;
391 
392 	if (!parser) {
393 		DRM_ERROR("invalid input\n");
394 		return ERR_PTR(-EINVAL);
395 	}
396 
397 	power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL);
398 	if (!power)
399 		return ERR_PTR(-ENOMEM);
400 
401 	power->parser = parser;
402 	power->pdev = parser->pdev;
403 	power->dev = dev;
404 
405 	dp_power = &power->dp_power;
406 
407 	return dp_power;
408 }
409