drm/msm/dp: delete vdda regulator related functions from eDP/DP controller
[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
24         struct dp_power dp_power;
25 };
26
27 static int dp_power_clk_init(struct dp_power_private *power)
28 {
29         int rc = 0;
30         struct dss_module_power *core, *ctrl, *stream;
31         struct device *dev = &power->pdev->dev;
32
33         core = &power->parser->mp[DP_CORE_PM];
34         ctrl = &power->parser->mp[DP_CTRL_PM];
35         stream = &power->parser->mp[DP_STREAM_PM];
36
37         rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk);
38         if (rc) {
39                 DRM_ERROR("failed to get %s clk. err=%d\n",
40                         dp_parser_pm_name(DP_CORE_PM), rc);
41                 return rc;
42         }
43
44         rc = msm_dss_get_clk(dev, ctrl->clk_config, ctrl->num_clk);
45         if (rc) {
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);
49                 return -ENODEV;
50         }
51
52         rc = msm_dss_get_clk(dev, stream->clk_config, stream->num_clk);
53         if (rc) {
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);
57                 return -ENODEV;
58         }
59
60         return 0;
61 }
62
63 static int dp_power_clk_deinit(struct dp_power_private *power)
64 {
65         struct dss_module_power *core, *ctrl, *stream;
66
67         core = &power->parser->mp[DP_CORE_PM];
68         ctrl = &power->parser->mp[DP_CTRL_PM];
69         stream = &power->parser->mp[DP_STREAM_PM];
70
71         if (!core || !ctrl || !stream) {
72                 DRM_ERROR("invalid power_data\n");
73                 return -EINVAL;
74         }
75
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);
79         return 0;
80 }
81
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)
84 {
85         u32 rate;
86         int i, rc = 0;
87
88         for (i = 0; i < num_clk; i++) {
89                 if (clk_arry[i].clk) {
90                         if (clk_arry[i].type == DSS_CLK_PCLK) {
91                                 if (enable)
92                                         rate = clk_arry[i].rate;
93                                 else
94                                         rate = 0;
95
96                                 rc = dev_pm_opp_set_rate(power->dev, rate);
97                                 if (rc)
98                                         break;
99                         }
100
101                 }
102         }
103         return rc;
104 }
105
106 static int dp_power_clk_set_rate(struct dp_power_private *power,
107                 enum dp_pm_type module, bool enable)
108 {
109         int rc = 0;
110         struct dss_module_power *mp = &power->parser->mp[module];
111
112         if (module == DP_CTRL_PM) {
113                 rc = dp_power_clk_set_link_rate(power, mp->clk_config, mp->num_clk, enable);
114                 if (rc) {
115                         DRM_ERROR("failed to set link clks rate\n");
116                         return rc;
117                 }
118         } else {
119
120                 if (enable) {
121                         rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk);
122                         if (rc) {
123                                 DRM_ERROR("failed to set clks rate\n");
124                                 return rc;
125                         }
126                 }
127         }
128
129         rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
130         if (rc) {
131                 DRM_ERROR("failed to %d clks, err: %d\n", enable, rc);
132                 return rc;
133         }
134
135         return 0;
136 }
137
138 int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type)
139 {
140         struct dp_power_private *power;
141
142         power = container_of(dp_power, struct dp_power_private, dp_power);
143
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);
147
148         if (pm_type == DP_CORE_PM)
149                 return dp_power->core_clks_on;
150
151         if (pm_type == DP_CTRL_PM)
152                 return dp_power->link_clks_on;
153
154         if (pm_type == DP_STREAM_PM)
155                 return dp_power->stream_clks_on;
156
157         return 0;
158 }
159
160 int dp_power_clk_enable(struct dp_power *dp_power,
161                 enum dp_pm_type pm_type, bool enable)
162 {
163         int rc = 0;
164         struct dp_power_private *power;
165
166         power = container_of(dp_power, struct dp_power_private, dp_power);
167
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));
172                 return -EINVAL;
173         }
174
175         if (enable) {
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");
179                         return 0;
180                 }
181
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");
185                         return 0;
186                 }
187
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");
191                         return 0;
192                 }
193
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");
197
198                         rc = dp_power_clk_set_rate(power, DP_CORE_PM, enable);
199                         if (rc) {
200                                 DRM_ERROR("fail to enable clks: %s. err=%d\n",
201                                         dp_parser_pm_name(DP_CORE_PM), rc);
202                                 return rc;
203                         }
204                         dp_power->core_clks_on = true;
205                 }
206         }
207
208         rc = dp_power_clk_set_rate(power, pm_type, enable);
209         if (rc) {
210                 DRM_ERROR("failed to '%s' clks for: %s. err=%d\n",
211                         enable ? "enable" : "disable",
212                         dp_parser_pm_name(pm_type), rc);
213                 return rc;
214         }
215
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;
220         else
221                 dp_power->link_clks_on = enable;
222
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");
231
232         return 0;
233 }
234
235 int dp_power_client_init(struct dp_power *dp_power)
236 {
237         int rc = 0;
238         struct dp_power_private *power;
239
240         if (!dp_power) {
241                 DRM_ERROR("invalid power data\n");
242                 return -EINVAL;
243         }
244
245         power = container_of(dp_power, struct dp_power_private, dp_power);
246
247         pm_runtime_enable(&power->pdev->dev);
248
249         rc = dp_power_clk_init(power);
250         if (rc)
251                 DRM_ERROR("failed to init clocks %d\n", rc);
252
253         return rc;
254 }
255
256 void dp_power_client_deinit(struct dp_power *dp_power)
257 {
258         struct dp_power_private *power;
259
260         if (!dp_power) {
261                 DRM_ERROR("invalid power data\n");
262                 return;
263         }
264
265         power = container_of(dp_power, struct dp_power_private, dp_power);
266
267         dp_power_clk_deinit(power);
268         pm_runtime_disable(&power->pdev->dev);
269
270 }
271
272 int dp_power_init(struct dp_power *dp_power, bool flip)
273 {
274         int rc = 0;
275         struct dp_power_private *power = NULL;
276
277         if (!dp_power) {
278                 DRM_ERROR("invalid power data\n");
279                 return -EINVAL;
280         }
281
282         power = container_of(dp_power, struct dp_power_private, dp_power);
283
284         pm_runtime_get_sync(&power->pdev->dev);
285
286         rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
287         if (rc) {
288                 DRM_ERROR("failed to enable DP core clocks, %d\n", rc);
289                 goto exit;
290         }
291
292         return 0;
293
294 exit:
295         pm_runtime_put_sync(&power->pdev->dev);
296         return rc;
297 }
298
299 int dp_power_deinit(struct dp_power *dp_power)
300 {
301         struct dp_power_private *power;
302
303         power = container_of(dp_power, struct dp_power_private, dp_power);
304
305         dp_power_clk_enable(dp_power, DP_CORE_PM, false);
306         pm_runtime_put_sync(&power->pdev->dev);
307         return 0;
308 }
309
310 struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser)
311 {
312         struct dp_power_private *power;
313         struct dp_power *dp_power;
314
315         if (!parser) {
316                 DRM_ERROR("invalid input\n");
317                 return ERR_PTR(-EINVAL);
318         }
319
320         power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL);
321         if (!power)
322                 return ERR_PTR(-ENOMEM);
323
324         power->parser = parser;
325         power->pdev = parser->pdev;
326         power->dev = dev;
327
328         dp_power = &power->dp_power;
329
330         return dp_power;
331 }