0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
0007
0008 #include <linux/clk.h>
0009 #include <linux/clk-provider.h>
0010 #include <linux/regulator/consumer.h>
0011 #include <linux/pm_opp.h>
0012 #include "dp_power.h"
0013 #include "msm_drv.h"
0014
0015 struct dp_power_private {
0016 struct dp_parser *parser;
0017 struct platform_device *pdev;
0018 struct device *dev;
0019 struct drm_device *drm_dev;
0020 struct clk *link_clk_src;
0021 struct clk *pixel_provider;
0022 struct clk *link_provider;
0023
0024 struct dp_power dp_power;
0025 };
0026
0027 static int dp_power_clk_init(struct dp_power_private *power)
0028 {
0029 int rc = 0;
0030 struct dss_module_power *core, *ctrl, *stream;
0031 struct device *dev = &power->pdev->dev;
0032
0033 core = &power->parser->mp[DP_CORE_PM];
0034 ctrl = &power->parser->mp[DP_CTRL_PM];
0035 stream = &power->parser->mp[DP_STREAM_PM];
0036
0037 rc = devm_clk_bulk_get(dev, core->num_clk, core->clocks);
0038 if (rc) {
0039 DRM_ERROR("failed to get %s clk. err=%d\n",
0040 dp_parser_pm_name(DP_CORE_PM), rc);
0041 return rc;
0042 }
0043
0044 rc = devm_clk_bulk_get(dev, ctrl->num_clk, ctrl->clocks);
0045 if (rc) {
0046 DRM_ERROR("failed to get %s clk. err=%d\n",
0047 dp_parser_pm_name(DP_CTRL_PM), rc);
0048 return -ENODEV;
0049 }
0050
0051 rc = devm_clk_bulk_get(dev, stream->num_clk, stream->clocks);
0052 if (rc) {
0053 DRM_ERROR("failed to get %s clk. err=%d\n",
0054 dp_parser_pm_name(DP_CTRL_PM), rc);
0055 return -ENODEV;
0056 }
0057
0058 return 0;
0059 }
0060
0061 int dp_power_clk_status(struct dp_power *dp_power, enum dp_pm_type pm_type)
0062 {
0063 struct dp_power_private *power;
0064
0065 power = container_of(dp_power, struct dp_power_private, dp_power);
0066
0067 drm_dbg_dp(power->drm_dev,
0068 "core_clk_on=%d link_clk_on=%d stream_clk_on=%d\n",
0069 dp_power->core_clks_on, dp_power->link_clks_on, dp_power->stream_clks_on);
0070
0071 if (pm_type == DP_CORE_PM)
0072 return dp_power->core_clks_on;
0073
0074 if (pm_type == DP_CTRL_PM)
0075 return dp_power->link_clks_on;
0076
0077 if (pm_type == DP_STREAM_PM)
0078 return dp_power->stream_clks_on;
0079
0080 return 0;
0081 }
0082
0083 int dp_power_clk_enable(struct dp_power *dp_power,
0084 enum dp_pm_type pm_type, bool enable)
0085 {
0086 int rc = 0;
0087 struct dp_power_private *power;
0088 struct dss_module_power *mp;
0089
0090 power = container_of(dp_power, struct dp_power_private, dp_power);
0091
0092 if (pm_type != DP_CORE_PM && pm_type != DP_CTRL_PM &&
0093 pm_type != DP_STREAM_PM) {
0094 DRM_ERROR("unsupported power module: %s\n",
0095 dp_parser_pm_name(pm_type));
0096 return -EINVAL;
0097 }
0098
0099 if (enable) {
0100 if (pm_type == DP_CORE_PM && dp_power->core_clks_on) {
0101 drm_dbg_dp(power->drm_dev,
0102 "core clks already enabled\n");
0103 return 0;
0104 }
0105
0106 if (pm_type == DP_CTRL_PM && dp_power->link_clks_on) {
0107 drm_dbg_dp(power->drm_dev,
0108 "links clks already enabled\n");
0109 return 0;
0110 }
0111
0112 if (pm_type == DP_STREAM_PM && dp_power->stream_clks_on) {
0113 drm_dbg_dp(power->drm_dev,
0114 "pixel clks already enabled\n");
0115 return 0;
0116 }
0117
0118 if ((pm_type == DP_CTRL_PM) && (!dp_power->core_clks_on)) {
0119 drm_dbg_dp(power->drm_dev,
0120 "Enable core clks before link clks\n");
0121 mp = &power->parser->mp[DP_CORE_PM];
0122
0123 rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks);
0124 if (rc) {
0125 DRM_ERROR("fail to enable clks: %s. err=%d\n",
0126 dp_parser_pm_name(DP_CORE_PM), rc);
0127 return rc;
0128 }
0129 dp_power->core_clks_on = true;
0130 }
0131 }
0132
0133 mp = &power->parser->mp[pm_type];
0134 if (enable) {
0135 rc = clk_bulk_prepare_enable(mp->num_clk, mp->clocks);
0136 if (rc) {
0137 DRM_ERROR("failed to enable clks, err: %d\n", rc);
0138 return rc;
0139 }
0140 } else {
0141 clk_bulk_disable_unprepare(mp->num_clk, mp->clocks);
0142 }
0143
0144 if (pm_type == DP_CORE_PM)
0145 dp_power->core_clks_on = enable;
0146 else if (pm_type == DP_STREAM_PM)
0147 dp_power->stream_clks_on = enable;
0148 else
0149 dp_power->link_clks_on = enable;
0150
0151 drm_dbg_dp(power->drm_dev, "%s clocks for %s\n",
0152 enable ? "enable" : "disable",
0153 dp_parser_pm_name(pm_type));
0154 drm_dbg_dp(power->drm_dev,
0155 "strem_clks:%s link_clks:%s core_clks:%s\n",
0156 dp_power->stream_clks_on ? "on" : "off",
0157 dp_power->link_clks_on ? "on" : "off",
0158 dp_power->core_clks_on ? "on" : "off");
0159
0160 return 0;
0161 }
0162
0163 int dp_power_client_init(struct dp_power *dp_power)
0164 {
0165 int rc = 0;
0166 struct dp_power_private *power;
0167
0168 if (!dp_power) {
0169 DRM_ERROR("invalid power data\n");
0170 return -EINVAL;
0171 }
0172
0173 power = container_of(dp_power, struct dp_power_private, dp_power);
0174
0175 pm_runtime_enable(&power->pdev->dev);
0176
0177 rc = dp_power_clk_init(power);
0178 if (rc)
0179 DRM_ERROR("failed to init clocks %d\n", rc);
0180
0181 return rc;
0182 }
0183
0184 void dp_power_client_deinit(struct dp_power *dp_power)
0185 {
0186 struct dp_power_private *power;
0187
0188 if (!dp_power) {
0189 DRM_ERROR("invalid power data\n");
0190 return;
0191 }
0192
0193 power = container_of(dp_power, struct dp_power_private, dp_power);
0194
0195 pm_runtime_disable(&power->pdev->dev);
0196 }
0197
0198 int dp_power_init(struct dp_power *dp_power, bool flip)
0199 {
0200 int rc = 0;
0201 struct dp_power_private *power = NULL;
0202
0203 if (!dp_power) {
0204 DRM_ERROR("invalid power data\n");
0205 return -EINVAL;
0206 }
0207
0208 power = container_of(dp_power, struct dp_power_private, dp_power);
0209
0210 pm_runtime_get_sync(&power->pdev->dev);
0211
0212 rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
0213 if (rc) {
0214 DRM_ERROR("failed to enable DP core clocks, %d\n", rc);
0215 goto exit;
0216 }
0217
0218 return 0;
0219
0220 exit:
0221 pm_runtime_put_sync(&power->pdev->dev);
0222 return rc;
0223 }
0224
0225 int dp_power_deinit(struct dp_power *dp_power)
0226 {
0227 struct dp_power_private *power;
0228
0229 power = container_of(dp_power, struct dp_power_private, dp_power);
0230
0231 dp_power_clk_enable(dp_power, DP_CORE_PM, false);
0232 pm_runtime_put_sync(&power->pdev->dev);
0233 return 0;
0234 }
0235
0236 struct dp_power *dp_power_get(struct device *dev, struct dp_parser *parser)
0237 {
0238 struct dp_power_private *power;
0239 struct dp_power *dp_power;
0240
0241 if (!parser) {
0242 DRM_ERROR("invalid input\n");
0243 return ERR_PTR(-EINVAL);
0244 }
0245
0246 power = devm_kzalloc(&parser->pdev->dev, sizeof(*power), GFP_KERNEL);
0247 if (!power)
0248 return ERR_PTR(-ENOMEM);
0249
0250 power->parser = parser;
0251 power->pdev = parser->pdev;
0252 power->dev = dev;
0253
0254 dp_power = &power->dp_power;
0255
0256 return dp_power;
0257 }