18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/clk.h> 98c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 108c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 118c2ecf20Sopenharmony_ci#include "dp_power.h" 128c2ecf20Sopenharmony_ci#include "msm_drv.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistruct dp_power_private { 158c2ecf20Sopenharmony_ci struct dp_parser *parser; 168c2ecf20Sopenharmony_ci struct platform_device *pdev; 178c2ecf20Sopenharmony_ci struct clk *link_clk_src; 188c2ecf20Sopenharmony_ci struct clk *pixel_provider; 198c2ecf20Sopenharmony_ci struct clk *link_provider; 208c2ecf20Sopenharmony_ci struct regulator_bulk_data supplies[DP_DEV_REGULATOR_MAX]; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci struct dp_power dp_power; 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic void dp_power_regulator_disable(struct dp_power_private *power) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci struct regulator_bulk_data *s = power->supplies; 288c2ecf20Sopenharmony_ci const struct dp_reg_entry *regs = power->parser->regulator_cfg->regs; 298c2ecf20Sopenharmony_ci int num = power->parser->regulator_cfg->num; 308c2ecf20Sopenharmony_ci int i; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci DBG(""); 338c2ecf20Sopenharmony_ci for (i = num - 1; i >= 0; i--) 348c2ecf20Sopenharmony_ci if (regs[i].disable_load >= 0) 358c2ecf20Sopenharmony_ci regulator_set_load(s[i].consumer, 368c2ecf20Sopenharmony_ci regs[i].disable_load); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci regulator_bulk_disable(num, s); 398c2ecf20Sopenharmony_ci} 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic int dp_power_regulator_enable(struct dp_power_private *power) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci struct regulator_bulk_data *s = power->supplies; 448c2ecf20Sopenharmony_ci const struct dp_reg_entry *regs = power->parser->regulator_cfg->regs; 458c2ecf20Sopenharmony_ci int num = power->parser->regulator_cfg->num; 468c2ecf20Sopenharmony_ci int ret, i; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci DBG(""); 498c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 508c2ecf20Sopenharmony_ci if (regs[i].enable_load >= 0) { 518c2ecf20Sopenharmony_ci ret = regulator_set_load(s[i].consumer, 528c2ecf20Sopenharmony_ci regs[i].enable_load); 538c2ecf20Sopenharmony_ci if (ret < 0) { 548c2ecf20Sopenharmony_ci pr_err("regulator %d set op mode failed, %d\n", 558c2ecf20Sopenharmony_ci i, ret); 568c2ecf20Sopenharmony_ci goto fail; 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci ret = regulator_bulk_enable(num, s); 628c2ecf20Sopenharmony_ci if (ret < 0) { 638c2ecf20Sopenharmony_ci pr_err("regulator enable failed, %d\n", ret); 648c2ecf20Sopenharmony_ci goto fail; 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci return 0; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cifail: 708c2ecf20Sopenharmony_ci for (i--; i >= 0; i--) 718c2ecf20Sopenharmony_ci regulator_set_load(s[i].consumer, regs[i].disable_load); 728c2ecf20Sopenharmony_ci return ret; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int dp_power_regulator_init(struct dp_power_private *power) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct regulator_bulk_data *s = power->supplies; 788c2ecf20Sopenharmony_ci const struct dp_reg_entry *regs = power->parser->regulator_cfg->regs; 798c2ecf20Sopenharmony_ci struct platform_device *pdev = power->pdev; 808c2ecf20Sopenharmony_ci int num = power->parser->regulator_cfg->num; 818c2ecf20Sopenharmony_ci int i, ret; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) 848c2ecf20Sopenharmony_ci s[i].supply = regs[i].name; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci ret = devm_regulator_bulk_get(&pdev->dev, num, s); 878c2ecf20Sopenharmony_ci if (ret < 0) { 888c2ecf20Sopenharmony_ci pr_err("%s: failed to init regulator, ret=%d\n", 898c2ecf20Sopenharmony_ci __func__, ret); 908c2ecf20Sopenharmony_ci return ret; 918c2ecf20Sopenharmony_ci } 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci return 0; 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic int dp_power_clk_init(struct dp_power_private *power) 978c2ecf20Sopenharmony_ci{ 988c2ecf20Sopenharmony_ci int rc = 0; 998c2ecf20Sopenharmony_ci struct dss_module_power *core, *ctrl, *stream; 1008c2ecf20Sopenharmony_ci struct device *dev = &power->pdev->dev; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci core = &power->parser->mp[DP_CORE_PM]; 1038c2ecf20Sopenharmony_ci ctrl = &power->parser->mp[DP_CTRL_PM]; 1048c2ecf20Sopenharmony_ci stream = &power->parser->mp[DP_STREAM_PM]; 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci rc = msm_dss_get_clk(dev, core->clk_config, core->num_clk); 1078c2ecf20Sopenharmony_ci if (rc) { 1088c2ecf20Sopenharmony_ci DRM_ERROR("failed to get %s clk. err=%d\n", 1098c2ecf20Sopenharmony_ci dp_parser_pm_name(DP_CORE_PM), rc); 1108c2ecf20Sopenharmony_ci return rc; 1118c2ecf20Sopenharmony_ci } 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci rc = msm_dss_get_clk(dev, ctrl->clk_config, ctrl->num_clk); 1148c2ecf20Sopenharmony_ci if (rc) { 1158c2ecf20Sopenharmony_ci DRM_ERROR("failed to get %s clk. err=%d\n", 1168c2ecf20Sopenharmony_ci dp_parser_pm_name(DP_CTRL_PM), rc); 1178c2ecf20Sopenharmony_ci msm_dss_put_clk(core->clk_config, core->num_clk); 1188c2ecf20Sopenharmony_ci return -ENODEV; 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci rc = msm_dss_get_clk(dev, stream->clk_config, stream->num_clk); 1228c2ecf20Sopenharmony_ci if (rc) { 1238c2ecf20Sopenharmony_ci DRM_ERROR("failed to get %s clk. err=%d\n", 1248c2ecf20Sopenharmony_ci dp_parser_pm_name(DP_CTRL_PM), rc); 1258c2ecf20Sopenharmony_ci msm_dss_put_clk(core->clk_config, core->num_clk); 1268c2ecf20Sopenharmony_ci return -ENODEV; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci return 0; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic int dp_power_clk_deinit(struct dp_power_private *power) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci struct dss_module_power *core, *ctrl, *stream; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci core = &power->parser->mp[DP_CORE_PM]; 1378c2ecf20Sopenharmony_ci ctrl = &power->parser->mp[DP_CTRL_PM]; 1388c2ecf20Sopenharmony_ci stream = &power->parser->mp[DP_STREAM_PM]; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci if (!core || !ctrl || !stream) { 1418c2ecf20Sopenharmony_ci DRM_ERROR("invalid power_data\n"); 1428c2ecf20Sopenharmony_ci return -EINVAL; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci msm_dss_put_clk(ctrl->clk_config, ctrl->num_clk); 1468c2ecf20Sopenharmony_ci msm_dss_put_clk(core->clk_config, core->num_clk); 1478c2ecf20Sopenharmony_ci msm_dss_put_clk(stream->clk_config, stream->num_clk); 1488c2ecf20Sopenharmony_ci return 0; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic int dp_power_clk_set_rate(struct dp_power_private *power, 1528c2ecf20Sopenharmony_ci enum dp_pm_type module, bool enable) 1538c2ecf20Sopenharmony_ci{ 1548c2ecf20Sopenharmony_ci int rc = 0; 1558c2ecf20Sopenharmony_ci struct dss_module_power *mp = &power->parser->mp[module]; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (enable) { 1588c2ecf20Sopenharmony_ci rc = msm_dss_clk_set_rate(mp->clk_config, mp->num_clk); 1598c2ecf20Sopenharmony_ci if (rc) { 1608c2ecf20Sopenharmony_ci DRM_ERROR("failed to set clks rate.\n"); 1618c2ecf20Sopenharmony_ci return rc; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable); 1668c2ecf20Sopenharmony_ci if (rc) { 1678c2ecf20Sopenharmony_ci DRM_ERROR("failed to %d clks, err: %d\n", enable, rc); 1688c2ecf20Sopenharmony_ci return rc; 1698c2ecf20Sopenharmony_ci } 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci return 0; 1728c2ecf20Sopenharmony_ci} 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ciint dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci if (pm_type == DP_CORE_PM) 1778c2ecf20Sopenharmony_ci return dp_power->core_clks_on; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci if (pm_type == DP_CTRL_PM) 1808c2ecf20Sopenharmony_ci return dp_power->link_clks_on; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (pm_type == DP_STREAM_PM) 1838c2ecf20Sopenharmony_ci return dp_power->stream_clks_on; 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci return 0; 1868c2ecf20Sopenharmony_ci} 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ciint dp_power_clk_enable(struct dp_power *dp_power, 1898c2ecf20Sopenharmony_ci enum dp_pm_type pm_type, bool enable) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci int rc = 0; 1928c2ecf20Sopenharmony_ci struct dp_power_private *power; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci power = container_of(dp_power, struct dp_power_private, dp_power); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM && 1978c2ecf20Sopenharmony_ci pm_type != DP_STREAM_PM) { 1988c2ecf20Sopenharmony_ci DRM_ERROR("unsupported power module: %s\n", 1998c2ecf20Sopenharmony_ci dp_parser_pm_name(pm_type)); 2008c2ecf20Sopenharmony_ci return -EINVAL; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci if (enable) { 2048c2ecf20Sopenharmony_ci if (pm_type == DP_CORE_PM && dp_power->core_clks_on) { 2058c2ecf20Sopenharmony_ci DRM_DEBUG_DP("core clks already enabled\n"); 2068c2ecf20Sopenharmony_ci return 0; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci if (pm_type == DP_CTRL_PM && dp_power->link_clks_on) { 2108c2ecf20Sopenharmony_ci DRM_DEBUG_DP("links clks already enabled\n"); 2118c2ecf20Sopenharmony_ci return 0; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if (pm_type == DP_STREAM_PM && dp_power->stream_clks_on) { 2158c2ecf20Sopenharmony_ci DRM_DEBUG_DP("pixel clks already enabled\n"); 2168c2ecf20Sopenharmony_ci return 0; 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) { 2208c2ecf20Sopenharmony_ci DRM_DEBUG_DP("Enable core clks before link clks\n"); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci rc = dp_power_clk_set_rate(power, DP_CORE_PM, enable); 2238c2ecf20Sopenharmony_ci if (rc) { 2248c2ecf20Sopenharmony_ci DRM_ERROR("fail to enable clks: %s. err=%d\n", 2258c2ecf20Sopenharmony_ci dp_parser_pm_name(DP_CORE_PM), rc); 2268c2ecf20Sopenharmony_ci return rc; 2278c2ecf20Sopenharmony_ci } 2288c2ecf20Sopenharmony_ci dp_power->core_clks_on = true; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci rc = dp_power_clk_set_rate(power, pm_type, enable); 2338c2ecf20Sopenharmony_ci if (rc) { 2348c2ecf20Sopenharmony_ci DRM_ERROR("failed to '%s' clks for: %s. err=%d\n", 2358c2ecf20Sopenharmony_ci enable ? "enable" : "disable", 2368c2ecf20Sopenharmony_ci dp_parser_pm_name(pm_type), rc); 2378c2ecf20Sopenharmony_ci return rc; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci if (pm_type == DP_CORE_PM) 2418c2ecf20Sopenharmony_ci dp_power->core_clks_on = enable; 2428c2ecf20Sopenharmony_ci else if (pm_type == DP_STREAM_PM) 2438c2ecf20Sopenharmony_ci dp_power->stream_clks_on = enable; 2448c2ecf20Sopenharmony_ci else 2458c2ecf20Sopenharmony_ci dp_power->link_clks_on = enable; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci DRM_DEBUG_DP("%s clocks for %s\n", 2488c2ecf20Sopenharmony_ci enable ? "enable" : "disable", 2498c2ecf20Sopenharmony_ci dp_parser_pm_name(pm_type)); 2508c2ecf20Sopenharmony_ci DRM_DEBUG_DP("strem_clks:%s link_clks:%s core_clks:%s\n", 2518c2ecf20Sopenharmony_ci dp_power->stream_clks_on ? "on" : "off", 2528c2ecf20Sopenharmony_ci dp_power->link_clks_on ? "on" : "off", 2538c2ecf20Sopenharmony_ci dp_power->core_clks_on ? "on" : "off"); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci return 0; 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ciint dp_power_client_init(struct dp_power *dp_power) 2598c2ecf20Sopenharmony_ci{ 2608c2ecf20Sopenharmony_ci int rc = 0; 2618c2ecf20Sopenharmony_ci struct dp_power_private *power; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (!dp_power) { 2648c2ecf20Sopenharmony_ci DRM_ERROR("invalid power data\n"); 2658c2ecf20Sopenharmony_ci return -EINVAL; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci power = container_of(dp_power, struct dp_power_private, dp_power); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci pm_runtime_enable(&power->pdev->dev); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci rc = dp_power_regulator_init(power); 2738c2ecf20Sopenharmony_ci if (rc) { 2748c2ecf20Sopenharmony_ci DRM_ERROR("failed to init regulators %d\n", rc); 2758c2ecf20Sopenharmony_ci goto error; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci rc = dp_power_clk_init(power); 2798c2ecf20Sopenharmony_ci if (rc) { 2808c2ecf20Sopenharmony_ci DRM_ERROR("failed to init clocks %d\n", rc); 2818c2ecf20Sopenharmony_ci goto error; 2828c2ecf20Sopenharmony_ci } 2838c2ecf20Sopenharmony_ci return 0; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_cierror: 2868c2ecf20Sopenharmony_ci pm_runtime_disable(&power->pdev->dev); 2878c2ecf20Sopenharmony_ci return rc; 2888c2ecf20Sopenharmony_ci} 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_civoid dp_power_client_deinit(struct dp_power *dp_power) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci struct dp_power_private *power; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci if (!dp_power) { 2958c2ecf20Sopenharmony_ci DRM_ERROR("invalid power data\n"); 2968c2ecf20Sopenharmony_ci return; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci power = container_of(dp_power, struct dp_power_private, dp_power); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci dp_power_clk_deinit(power); 3028c2ecf20Sopenharmony_ci pm_runtime_disable(&power->pdev->dev); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ciint dp_power_init(struct dp_power *dp_power, bool flip) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci int rc = 0; 3098c2ecf20Sopenharmony_ci struct dp_power_private *power = NULL; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci if (!dp_power) { 3128c2ecf20Sopenharmony_ci DRM_ERROR("invalid power data\n"); 3138c2ecf20Sopenharmony_ci return -EINVAL; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci power = container_of(dp_power, struct dp_power_private, dp_power); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci pm_runtime_get_sync(&power->pdev->dev); 3198c2ecf20Sopenharmony_ci rc = dp_power_regulator_enable(power); 3208c2ecf20Sopenharmony_ci if (rc) { 3218c2ecf20Sopenharmony_ci DRM_ERROR("failed to enable regulators, %d\n", rc); 3228c2ecf20Sopenharmony_ci goto exit; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true); 3268c2ecf20Sopenharmony_ci if (rc) { 3278c2ecf20Sopenharmony_ci DRM_ERROR("failed to enable DP core clocks, %d\n", rc); 3288c2ecf20Sopenharmony_ci goto err_clk; 3298c2ecf20Sopenharmony_ci } 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci return 0; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cierr_clk: 3348c2ecf20Sopenharmony_ci dp_power_regulator_disable(power); 3358c2ecf20Sopenharmony_ciexit: 3368c2ecf20Sopenharmony_ci pm_runtime_put_sync(&power->pdev->dev); 3378c2ecf20Sopenharmony_ci return rc; 3388c2ecf20Sopenharmony_ci} 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ciint dp_power_deinit(struct dp_power *dp_power) 3418c2ecf20Sopenharmony_ci{ 3428c2ecf20Sopenharmony_ci struct dp_power_private *power; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci power = container_of(dp_power, struct dp_power_private, dp_power); 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci dp_power_clk_enable(dp_power, DP_CORE_PM, false); 3478c2ecf20Sopenharmony_ci dp_power_regulator_disable(power); 3488c2ecf20Sopenharmony_ci pm_runtime_put_sync(&power->pdev->dev); 3498c2ecf20Sopenharmony_ci return 0; 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistruct dp_power *dp_power_get(struct dp_parser *parser) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci struct dp_power_private *power; 3558c2ecf20Sopenharmony_ci struct dp_power *dp_power; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci if (!parser) { 3588c2ecf20Sopenharmony_ci DRM_ERROR("invalid input\n"); 3598c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL); 3638c2ecf20Sopenharmony_ci if (!power) 3648c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_ci power->parser = parser; 3678c2ecf20Sopenharmony_ci power->pdev = parser->pdev; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci dp_power = &power->dp_power; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci return dp_power; 3728c2ecf20Sopenharmony_ci} 373