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