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