disp: msm: add runtime_pm ops support in drm driver
Add runtime_pm ops support in drm driver instead of direct sde_power_resource_enable/disable call. It allows drm driver to use runtime pm refcount logic to track the resources instead of custom implementation. The change also removes the NRT_CLIENT support from sde_power_handle code to simplify it further. Change-Id: Ib14692dca5876703d0a230da2512d731b69b8ebb Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
This commit is contained in:
@@ -1213,7 +1213,8 @@ static int dp_init_sub_modules(struct dp_display_private *dp)
|
|||||||
goto error_power;
|
goto error_power;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = dp->power->power_client_init(dp->power, &dp->priv->phandle);
|
rc = dp->power->power_client_init(dp->power, &dp->priv->phandle,
|
||||||
|
dp->dp_display.drm_dev);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("Power client create failed\n");
|
pr_err("Power client create failed\n");
|
||||||
goto error_aux;
|
goto error_aux;
|
||||||
|
@@ -6,6 +6,8 @@
|
|||||||
#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
|
#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <drm/drmP.h>
|
||||||
#include "dp_power.h"
|
#include "dp_power.h"
|
||||||
#include "dp_catalog.h"
|
#include "dp_catalog.h"
|
||||||
|
|
||||||
@@ -20,8 +22,6 @@ struct dp_power_private {
|
|||||||
struct clk *pixel1_parent;
|
struct clk *pixel1_parent;
|
||||||
|
|
||||||
struct dp_power dp_power;
|
struct dp_power dp_power;
|
||||||
struct sde_power_client *dp_core_client;
|
|
||||||
struct sde_power_handle *phandle;
|
|
||||||
|
|
||||||
bool core_clks_on;
|
bool core_clks_on;
|
||||||
bool link_clks_on;
|
bool link_clks_on;
|
||||||
@@ -458,14 +458,13 @@ static int dp_power_config_gpios(struct dp_power_private *power, bool flip,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int dp_power_client_init(struct dp_power *dp_power,
|
static int dp_power_client_init(struct dp_power *dp_power,
|
||||||
struct sde_power_handle *phandle)
|
struct sde_power_handle *phandle, struct drm_device *drm_dev)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct dp_power_private *power;
|
struct dp_power_private *power;
|
||||||
char dp_client_name[DP_CLIENT_NAME_SIZE];
|
|
||||||
|
|
||||||
if (!dp_power) {
|
if (!drm_dev) {
|
||||||
pr_err("invalid power data\n");
|
pr_err("invalid drm_dev\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,20 +481,11 @@ static int dp_power_client_init(struct dp_power *dp_power,
|
|||||||
pr_err("failed to init clocks\n");
|
pr_err("failed to init clocks\n");
|
||||||
goto error_clk;
|
goto error_clk;
|
||||||
}
|
}
|
||||||
|
dp_power->phandle = phandle;
|
||||||
|
dp_power->drm_dev = drm_dev;
|
||||||
|
|
||||||
power->phandle = phandle;
|
|
||||||
snprintf(dp_client_name, DP_CLIENT_NAME_SIZE, "dp_core_client");
|
|
||||||
power->dp_core_client = sde_power_client_create(phandle,
|
|
||||||
dp_client_name);
|
|
||||||
if (IS_ERR_OR_NULL(power->dp_core_client)) {
|
|
||||||
pr_err("[%s] client creation failed for DP\n", dp_client_name);
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto error_client;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_client:
|
|
||||||
dp_power_clk_init(power, false);
|
|
||||||
error_clk:
|
error_clk:
|
||||||
dp_power_regulator_deinit(power);
|
dp_power_regulator_deinit(power);
|
||||||
error_power:
|
error_power:
|
||||||
@@ -513,7 +503,6 @@ static void dp_power_client_deinit(struct dp_power *dp_power)
|
|||||||
|
|
||||||
power = container_of(dp_power, struct dp_power_private, dp_power);
|
power = container_of(dp_power, struct dp_power_private, dp_power);
|
||||||
|
|
||||||
sde_power_client_destroy(power->phandle, power->dp_core_client);
|
|
||||||
dp_power_clk_init(power, false);
|
dp_power_clk_init(power, false);
|
||||||
dp_power_regulator_deinit(power);
|
dp_power_regulator_deinit(power);
|
||||||
}
|
}
|
||||||
@@ -559,7 +548,7 @@ static u64 dp_power_clk_get_rate(struct dp_power *dp_power, char *clk_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
power = container_of(dp_power, struct dp_power_private, dp_power);
|
power = container_of(dp_power, struct dp_power_private, dp_power);
|
||||||
mp = &power->phandle->mp;
|
mp = &dp_power->phandle->mp;
|
||||||
for (i = 0; i < mp->num_clk; i++) {
|
for (i = 0; i < mp->num_clk; i++) {
|
||||||
if (!strcmp(mp->clk_config[i].clk_name, clk_name)) {
|
if (!strcmp(mp->clk_config[i].clk_name, clk_name)) {
|
||||||
rate = clk_get_rate(mp->clk_config[i].clk);
|
rate = clk_get_rate(mp->clk_config[i].clk);
|
||||||
@@ -613,9 +602,8 @@ static int dp_power_init(struct dp_power *dp_power, bool flip)
|
|||||||
goto err_gpio;
|
goto err_gpio;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sde_power_resource_enable(power->phandle,
|
rc = pm_runtime_get_sync(dp_power->drm_dev->dev);
|
||||||
power->dp_core_client, true);
|
if (rc < 0) {
|
||||||
if (rc) {
|
|
||||||
pr_err("Power resource enable failed\n");
|
pr_err("Power resource enable failed\n");
|
||||||
goto err_sde_power;
|
goto err_sde_power;
|
||||||
}
|
}
|
||||||
@@ -629,7 +617,7 @@ static int dp_power_init(struct dp_power *dp_power, bool flip)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_clk:
|
err_clk:
|
||||||
sde_power_resource_enable(power->phandle, power->dp_core_client, false);
|
pm_runtime_put_sync(dp_power->drm_dev->dev);
|
||||||
err_sde_power:
|
err_sde_power:
|
||||||
dp_power_config_gpios(power, flip, false);
|
dp_power_config_gpios(power, flip, false);
|
||||||
err_gpio:
|
err_gpio:
|
||||||
@@ -657,13 +645,8 @@ static int dp_power_deinit(struct dp_power *dp_power)
|
|||||||
dp_power_clk_enable(dp_power, DP_LINK_PM, false);
|
dp_power_clk_enable(dp_power, DP_LINK_PM, false);
|
||||||
|
|
||||||
dp_power_clk_enable(dp_power, DP_CORE_PM, false);
|
dp_power_clk_enable(dp_power, DP_CORE_PM, false);
|
||||||
|
pm_runtime_put_sync(dp_power->drm_dev->dev);
|
||||||
|
|
||||||
rc = sde_power_resource_enable(power->phandle,
|
|
||||||
power->dp_core_client, false);
|
|
||||||
if (rc) {
|
|
||||||
pr_err("Power resource disable failed, rc=%d\n", rc);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
dp_power_config_gpios(power, false, false);
|
dp_power_config_gpios(power, false, false);
|
||||||
dp_power_pinctrl_set(power, false);
|
dp_power_pinctrl_set(power, false);
|
||||||
dp_power_regulator_ctrl(power, false);
|
dp_power_regulator_ctrl(power, false);
|
||||||
|
@@ -19,6 +19,8 @@
|
|||||||
* @clk_get_rate: get the current rate for provided clk_name
|
* @clk_get_rate: get the current rate for provided clk_name
|
||||||
*/
|
*/
|
||||||
struct dp_power {
|
struct dp_power {
|
||||||
|
struct drm_device *drm_dev;
|
||||||
|
struct sde_power_handle *phandle;
|
||||||
int (*init)(struct dp_power *power, bool flip);
|
int (*init)(struct dp_power *power, bool flip);
|
||||||
int (*deinit)(struct dp_power *power);
|
int (*deinit)(struct dp_power *power);
|
||||||
int (*clk_enable)(struct dp_power *power, enum dp_pm_type pm_type,
|
int (*clk_enable)(struct dp_power *power, enum dp_pm_type pm_type,
|
||||||
@@ -26,7 +28,8 @@ struct dp_power {
|
|||||||
int (*set_pixel_clk_parent)(struct dp_power *power, u32 stream_id);
|
int (*set_pixel_clk_parent)(struct dp_power *power, u32 stream_id);
|
||||||
u64 (*clk_get_rate)(struct dp_power *power, char *clk_name);
|
u64 (*clk_get_rate)(struct dp_power *power, char *clk_name);
|
||||||
int (*power_client_init)(struct dp_power *power,
|
int (*power_client_init)(struct dp_power *power,
|
||||||
struct sde_power_handle *phandle);
|
struct sde_power_handle *phandle,
|
||||||
|
struct drm_device *drm_dev);
|
||||||
void (*power_client_deinit)(struct dp_power *power);
|
void (*power_client_deinit)(struct dp_power *power);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include "sde_power_handle.h"
|
#include <drm/drmP.h>
|
||||||
|
|
||||||
#define MAX_STRING_LEN 32
|
#define MAX_STRING_LEN 32
|
||||||
#define MAX_DSI_CTRL 2
|
#define MAX_DSI_CTRL 2
|
||||||
@@ -72,8 +72,7 @@ struct clk_ctrl_cb {
|
|||||||
* @core_mmss_clk: Handle to MMSS core clock.
|
* @core_mmss_clk: Handle to MMSS core clock.
|
||||||
* @bus_clk: Handle to bus clock.
|
* @bus_clk: Handle to bus clock.
|
||||||
* @mnoc_clk: Handle to MMSS NOC clock.
|
* @mnoc_clk: Handle to MMSS NOC clock.
|
||||||
* @dsi_core_client: Pointer to SDE power client
|
* @drm: Pointer to drm device node
|
||||||
* @phandle: Pointer to SDE power handle
|
|
||||||
*/
|
*/
|
||||||
struct dsi_core_clk_info {
|
struct dsi_core_clk_info {
|
||||||
struct clk *mdp_core_clk;
|
struct clk *mdp_core_clk;
|
||||||
@@ -81,8 +80,7 @@ struct dsi_core_clk_info {
|
|||||||
struct clk *core_mmss_clk;
|
struct clk *core_mmss_clk;
|
||||||
struct clk *bus_clk;
|
struct clk *bus_clk;
|
||||||
struct clk *mnoc_clk;
|
struct clk *mnoc_clk;
|
||||||
struct sde_power_client *dsi_core_client;
|
struct drm_device *drm;
|
||||||
struct sde_power_handle *phandle;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/msm-bus.h>
|
#include <linux/msm-bus.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
#include "dsi_clk.h"
|
#include "dsi_clk.h"
|
||||||
|
|
||||||
struct dsi_core_clks {
|
struct dsi_core_clks {
|
||||||
@@ -554,10 +555,9 @@ static int dsi_display_core_clk_enable(struct dsi_core_clks *clks,
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
m_clks = &clks[master_ndx];
|
m_clks = &clks[master_ndx];
|
||||||
rc = sde_power_resource_enable(m_clks->clks.phandle,
|
|
||||||
m_clks->clks.dsi_core_client, true);
|
|
||||||
|
|
||||||
if (rc) {
|
rc = pm_runtime_get_sync(m_clks->clks.drm->dev);
|
||||||
|
if (rc < 0) {
|
||||||
pr_err("Power resource enable failed, rc=%d\n", rc);
|
pr_err("Power resource enable failed, rc=%d\n", rc);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -574,9 +574,8 @@ static int dsi_display_core_clk_enable(struct dsi_core_clks *clks,
|
|||||||
if (!clk || (clk == m_clks))
|
if (!clk || (clk == m_clks))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rc = sde_power_resource_enable(clk->clks.phandle,
|
rc = pm_runtime_get_sync(m_clks->clks.drm->dev);
|
||||||
clk->clks.dsi_core_client, true);
|
if (rc < 0) {
|
||||||
if (rc) {
|
|
||||||
pr_err("Power resource enable failed, rc=%d\n", rc);
|
pr_err("Power resource enable failed, rc=%d\n", rc);
|
||||||
goto error_disable_master;
|
goto error_disable_master;
|
||||||
}
|
}
|
||||||
@@ -584,8 +583,7 @@ static int dsi_display_core_clk_enable(struct dsi_core_clks *clks,
|
|||||||
rc = dsi_core_clk_start(clk);
|
rc = dsi_core_clk_start(clk);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("failed to turn on clocks, rc=%d\n", rc);
|
pr_err("failed to turn on clocks, rc=%d\n", rc);
|
||||||
(void)sde_power_resource_enable(clk->clks.phandle,
|
pm_runtime_put_sync(m_clks->clks.drm->dev);
|
||||||
clk->clks.dsi_core_client, false);
|
|
||||||
goto error_disable_master;
|
goto error_disable_master;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -594,8 +592,7 @@ error_disable_master:
|
|||||||
(void)dsi_core_clk_stop(m_clks);
|
(void)dsi_core_clk_stop(m_clks);
|
||||||
|
|
||||||
error_disable_master_resource:
|
error_disable_master_resource:
|
||||||
(void)sde_power_resource_enable(m_clks->clks.phandle,
|
pm_runtime_put_sync(m_clks->clks.drm->dev);
|
||||||
m_clks->clks.dsi_core_client, false);
|
|
||||||
error:
|
error:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -697,12 +694,7 @@ static int dsi_display_core_clk_disable(struct dsi_core_clks *clks,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sde_power_resource_enable(clk->clks.phandle,
|
pm_runtime_put_sync(m_clks->clks.drm->dev);
|
||||||
clk->clks.dsi_core_client, false);
|
|
||||||
if (rc) {
|
|
||||||
pr_err("Power resource disable failed: %d\n", rc);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = dsi_core_clk_stop(m_clks);
|
rc = dsi_core_clk_stop(m_clks);
|
||||||
@@ -711,10 +703,7 @@ static int dsi_display_core_clk_disable(struct dsi_core_clks *clks,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sde_power_resource_enable(m_clks->clks.phandle,
|
pm_runtime_put_sync(m_clks->clks.drm->dev);
|
||||||
m_clks->clks.dsi_core_client, false);
|
|
||||||
if (rc)
|
|
||||||
pr_err("Power resource disable failed: %d\n", rc);
|
|
||||||
error:
|
error:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@@ -4105,20 +4105,15 @@ int dsi_display_cont_splash_config(void *dsi_display)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&display->display_lock);
|
rc = pm_runtime_get_sync(display->drm_dev->dev);
|
||||||
|
if (rc < 0) {
|
||||||
/* Vote for gdsc required to read register address space */
|
|
||||||
display->cont_splash_client = sde_power_client_create(display->phandle,
|
|
||||||
"cont_splash_client");
|
|
||||||
rc = sde_power_resource_enable(display->phandle,
|
|
||||||
display->cont_splash_client, true);
|
|
||||||
if (rc) {
|
|
||||||
pr_err("failed to vote gdsc for continuous splash, rc=%d\n",
|
pr_err("failed to vote gdsc for continuous splash, rc=%d\n",
|
||||||
rc);
|
rc);
|
||||||
mutex_unlock(&display->display_lock);
|
return rc;
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&display->display_lock);
|
||||||
|
|
||||||
/* Verify whether continuous splash is enabled or not */
|
/* Verify whether continuous splash is enabled or not */
|
||||||
display->is_cont_splash_enabled =
|
display->is_cont_splash_enabled =
|
||||||
dsi_display_get_cont_splash_status(display);
|
dsi_display_get_cont_splash_status(display);
|
||||||
@@ -4172,8 +4167,7 @@ clk_manager_update:
|
|||||||
false);
|
false);
|
||||||
|
|
||||||
splash_disabled:
|
splash_disabled:
|
||||||
(void)sde_power_resource_enable(display->phandle,
|
pm_runtime_put_sync(display->drm_dev->dev);
|
||||||
display->cont_splash_client, false);
|
|
||||||
display->is_cont_splash_enabled = false;
|
display->is_cont_splash_enabled = false;
|
||||||
mutex_unlock(&display->display_lock);
|
mutex_unlock(&display->display_lock);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -4197,11 +4191,7 @@ int dsi_display_splash_res_cleanup(struct dsi_display *display)
|
|||||||
pr_err("[%s] failed to disable DSI link clocks, rc=%d\n",
|
pr_err("[%s] failed to disable DSI link clocks, rc=%d\n",
|
||||||
display->name, rc);
|
display->name, rc);
|
||||||
|
|
||||||
rc = sde_power_resource_enable(display->phandle,
|
pm_runtime_put_sync(display->drm_dev->dev);
|
||||||
display->cont_splash_client, false);
|
|
||||||
if (rc)
|
|
||||||
pr_err("failed to remove vote on gdsc for continuous splash, rc=%d\n",
|
|
||||||
rc);
|
|
||||||
|
|
||||||
display->is_cont_splash_enabled = false;
|
display->is_cont_splash_enabled = false;
|
||||||
/* Update splash status for clock manager */
|
/* Update splash status for clock manager */
|
||||||
@@ -4448,12 +4438,10 @@ static int dsi_display_bind(struct device *dev,
|
|||||||
struct dsi_display *display;
|
struct dsi_display *display;
|
||||||
struct dsi_clk_info info;
|
struct dsi_clk_info info;
|
||||||
struct clk_ctrl_cb clk_cb;
|
struct clk_ctrl_cb clk_cb;
|
||||||
struct msm_drm_private *priv;
|
|
||||||
void *handle = NULL;
|
void *handle = NULL;
|
||||||
struct platform_device *pdev = to_platform_device(dev);
|
struct platform_device *pdev = to_platform_device(dev);
|
||||||
char *client1 = "dsi_clk_client";
|
char *client1 = "dsi_clk_client";
|
||||||
char *client2 = "mdp_event_client";
|
char *client2 = "mdp_event_client";
|
||||||
char dsi_client_name[DSI_CLIENT_NAME_SIZE];
|
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
|
|
||||||
if (!dev || !pdev || !master) {
|
if (!dev || !pdev || !master) {
|
||||||
@@ -4469,7 +4457,6 @@ static int dsi_display_bind(struct device *dev,
|
|||||||
drm, display);
|
drm, display);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
priv = drm->dev_private;
|
|
||||||
if (!display->panel_node)
|
if (!display->panel_node)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -4522,22 +4509,12 @@ static int dsi_display_bind(struct device *dev,
|
|||||||
(&display_ctrl->ctrl->clk_info.lp_link_clks),
|
(&display_ctrl->ctrl->clk_info.lp_link_clks),
|
||||||
sizeof(struct dsi_link_lp_clk_info));
|
sizeof(struct dsi_link_lp_clk_info));
|
||||||
|
|
||||||
info.c_clks[i].phandle = &priv->phandle;
|
info.c_clks[i].drm = drm;
|
||||||
info.bus_handle[i] =
|
info.bus_handle[i] =
|
||||||
display_ctrl->ctrl->axi_bus_info.bus_handle;
|
display_ctrl->ctrl->axi_bus_info.bus_handle;
|
||||||
info.ctrl_index[i] = display_ctrl->ctrl->cell_index;
|
info.ctrl_index[i] = display_ctrl->ctrl->cell_index;
|
||||||
snprintf(dsi_client_name, DSI_CLIENT_NAME_SIZE,
|
|
||||||
"dsi_core_client%u", i);
|
|
||||||
info.c_clks[i].dsi_core_client = sde_power_client_create(
|
|
||||||
info.c_clks[i].phandle, dsi_client_name);
|
|
||||||
if (IS_ERR_OR_NULL(info.c_clks[i].dsi_core_client)) {
|
|
||||||
pr_err("[%s] client creation failed for ctrl[%d]\n",
|
|
||||||
dsi_client_name, i);
|
|
||||||
goto error_ctrl_deinit;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
display->phandle = &priv->phandle;
|
|
||||||
info.pre_clkoff_cb = dsi_pre_clkoff_cb;
|
info.pre_clkoff_cb = dsi_pre_clkoff_cb;
|
||||||
info.pre_clkon_cb = dsi_pre_clkon_cb;
|
info.pre_clkon_cb = dsi_pre_clkon_cb;
|
||||||
info.post_clkoff_cb = dsi_post_clkoff_cb;
|
info.post_clkoff_cb = dsi_post_clkoff_cb;
|
||||||
|
@@ -239,9 +239,6 @@ struct dsi_display {
|
|||||||
struct dsi_bridge *bridge;
|
struct dsi_bridge *bridge;
|
||||||
u32 cmd_engine_refcount;
|
u32 cmd_engine_refcount;
|
||||||
|
|
||||||
struct sde_power_handle *phandle;
|
|
||||||
struct sde_power_client *cont_splash_client;
|
|
||||||
|
|
||||||
void *clk_mngr;
|
void *clk_mngr;
|
||||||
void *dsi_clk_handle;
|
void *dsi_clk_handle;
|
||||||
void *mdp_clk_handle;
|
void *mdp_clk_handle;
|
||||||
|
@@ -401,7 +401,6 @@ static int msm_drm_uninit(struct device *dev)
|
|||||||
sde_dbg_destroy();
|
sde_dbg_destroy();
|
||||||
debugfs_remove_recursive(priv->debug_root);
|
debugfs_remove_recursive(priv->debug_root);
|
||||||
|
|
||||||
sde_power_client_destroy(&priv->phandle, priv->pclient);
|
|
||||||
sde_power_resource_deinit(pdev, &priv->phandle);
|
sde_power_resource_deinit(pdev, &priv->phandle);
|
||||||
|
|
||||||
msm_mdss_destroy(ddev);
|
msm_mdss_destroy(ddev);
|
||||||
@@ -535,11 +534,6 @@ static int msm_component_bind_all(struct device *dev,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int msm_power_enable_wrapper(void *handle, void *client, bool enable)
|
|
||||||
{
|
|
||||||
return sde_power_resource_enable(handle, client, enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_drm_display_thread_create(struct sched_param param,
|
static int msm_drm_display_thread_create(struct sched_param param,
|
||||||
struct msm_drm_private *priv, struct drm_device *ddev,
|
struct msm_drm_private *priv, struct drm_device *ddev,
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
@@ -703,7 +697,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
|
|||||||
struct drm_device *ddev;
|
struct drm_device *ddev;
|
||||||
struct msm_drm_private *priv;
|
struct msm_drm_private *priv;
|
||||||
struct msm_kms *kms = NULL;
|
struct msm_kms *kms = NULL;
|
||||||
struct sde_dbg_power_ctrl dbg_power_ctrl = { 0 };
|
|
||||||
int ret;
|
int ret;
|
||||||
struct sched_param param = { 0 };
|
struct sched_param param = { 0 };
|
||||||
|
|
||||||
@@ -741,17 +734,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
|
|||||||
goto power_init_fail;
|
goto power_init_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->pclient = sde_power_client_create(&priv->phandle, "sde");
|
ret = sde_dbg_init(&pdev->dev);
|
||||||
if (IS_ERR_OR_NULL(priv->pclient)) {
|
|
||||||
pr_err("sde power client create failed\n");
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto power_client_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg_power_ctrl.handle = &priv->phandle;
|
|
||||||
dbg_power_ctrl.client = priv->pclient;
|
|
||||||
dbg_power_ctrl.enable_fn = msm_power_enable_wrapper;
|
|
||||||
ret = sde_dbg_init(&pdev->dev, &dbg_power_ctrl);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(dev, "failed to init sde dbg: %d\n", ret);
|
dev_err(dev, "failed to init sde dbg: %d\n", ret);
|
||||||
goto dbg_init_fail;
|
goto dbg_init_fail;
|
||||||
@@ -851,8 +834,6 @@ fail:
|
|||||||
bind_fail:
|
bind_fail:
|
||||||
sde_dbg_destroy();
|
sde_dbg_destroy();
|
||||||
dbg_init_fail:
|
dbg_init_fail:
|
||||||
sde_power_client_destroy(&priv->phandle, priv->pclient);
|
|
||||||
power_client_fail:
|
|
||||||
sde_power_resource_deinit(pdev, &priv->phandle);
|
sde_power_resource_deinit(pdev, &priv->phandle);
|
||||||
power_init_fail:
|
power_init_fail:
|
||||||
msm_mdss_destroy(ddev);
|
msm_mdss_destroy(ddev);
|
||||||
@@ -927,8 +908,7 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file)
|
|||||||
mutex_lock(&ctx->power_lock);
|
mutex_lock(&ctx->power_lock);
|
||||||
if (ctx->enable_refcnt) {
|
if (ctx->enable_refcnt) {
|
||||||
SDE_EVT32(ctx->enable_refcnt);
|
SDE_EVT32(ctx->enable_refcnt);
|
||||||
sde_power_resource_enable(&priv->phandle,
|
pm_runtime_put_sync(dev->dev);
|
||||||
priv->pclient, false);
|
|
||||||
}
|
}
|
||||||
mutex_unlock(&ctx->power_lock);
|
mutex_unlock(&ctx->power_lock);
|
||||||
|
|
||||||
@@ -1602,10 +1582,12 @@ int msm_ioctl_power_ctrl(struct drm_device *dev, void *data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (vote_req) {
|
if (vote_req) {
|
||||||
rc = sde_power_resource_enable(&priv->phandle,
|
if (power_ctrl->enable)
|
||||||
priv->pclient, power_ctrl->enable);
|
rc = pm_runtime_get_sync(dev->dev);
|
||||||
|
else
|
||||||
|
pm_runtime_put_sync(dev->dev);
|
||||||
|
|
||||||
if (rc)
|
if (rc < 0)
|
||||||
ctx->enable_refcnt = old_cnt;
|
ctx->enable_refcnt = old_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1756,7 +1738,9 @@ static int msm_runtime_suspend(struct device *dev)
|
|||||||
DBG("");
|
DBG("");
|
||||||
|
|
||||||
if (priv->mdss)
|
if (priv->mdss)
|
||||||
return msm_mdss_disable(priv->mdss);
|
msm_mdss_disable(priv->mdss);
|
||||||
|
else
|
||||||
|
sde_power_resource_enable(&priv->phandle, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1765,13 +1749,16 @@ static int msm_runtime_resume(struct device *dev)
|
|||||||
{
|
{
|
||||||
struct drm_device *ddev = dev_get_drvdata(dev);
|
struct drm_device *ddev = dev_get_drvdata(dev);
|
||||||
struct msm_drm_private *priv = ddev->dev_private;
|
struct msm_drm_private *priv = ddev->dev_private;
|
||||||
|
int ret;
|
||||||
|
|
||||||
DBG("");
|
DBG("");
|
||||||
|
|
||||||
if (priv->mdss)
|
if (priv->mdss)
|
||||||
return msm_mdss_enable(priv->mdss);
|
ret = msm_mdss_enable(priv->mdss);
|
||||||
|
else
|
||||||
|
ret = sde_power_resource_enable(&priv->phandle, true);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -560,7 +560,6 @@ struct msm_drm_private {
|
|||||||
struct msm_kms *kms;
|
struct msm_kms *kms;
|
||||||
|
|
||||||
struct sde_power_handle phandle;
|
struct sde_power_handle phandle;
|
||||||
struct sde_power_client *pclient;
|
|
||||||
|
|
||||||
/* subordinate devices, if present: */
|
/* subordinate devices, if present: */
|
||||||
struct platform_device *gpu_pdev;
|
struct platform_device *gpu_pdev;
|
||||||
|
@@ -2193,8 +2193,8 @@ static void sde_cp_notify_ad_event(struct drm_crtc *crtc_drm, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
priv = kms->dev->dev_private;
|
priv = kms->dev->dev_private;
|
||||||
ret = sde_power_resource_enable(&priv->phandle, kms->core_client, true);
|
ret = pm_runtime_get_sync(kms->dev->dev);
|
||||||
if (ret) {
|
if (ret < 0) {
|
||||||
SDE_ERROR("failed to enable power resource %d\n", ret);
|
SDE_ERROR("failed to enable power resource %d\n", ret);
|
||||||
SDE_EVT32(ret, SDE_EVTLOG_ERROR);
|
SDE_EVT32(ret, SDE_EVTLOG_ERROR);
|
||||||
return;
|
return;
|
||||||
@@ -2203,8 +2203,7 @@ static void sde_cp_notify_ad_event(struct drm_crtc *crtc_drm, void *arg)
|
|||||||
hw_dspp->ops.ad_read_intr_resp(hw_dspp, AD4_IN_OUT_BACKLIGHT,
|
hw_dspp->ops.ad_read_intr_resp(hw_dspp, AD4_IN_OUT_BACKLIGHT,
|
||||||
&input_bl, &output_bl);
|
&input_bl, &output_bl);
|
||||||
|
|
||||||
sde_power_resource_enable(&priv->phandle, kms->core_client,
|
pm_runtime_put_sync(kms->dev->dev);
|
||||||
false);
|
|
||||||
if (!input_bl || input_bl < output_bl)
|
if (!input_bl || input_bl < output_bl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -2426,7 +2425,6 @@ static void sde_cp_notify_hist_event(struct drm_crtc *crtc_drm, void *arg)
|
|||||||
struct sde_crtc *crtc;
|
struct sde_crtc *crtc;
|
||||||
struct drm_event event;
|
struct drm_event event;
|
||||||
struct drm_msm_hist *hist_data;
|
struct drm_msm_hist *hist_data;
|
||||||
struct msm_drm_private *priv;
|
|
||||||
struct sde_kms *kms;
|
struct sde_kms *kms;
|
||||||
int ret;
|
int ret;
|
||||||
u32 i;
|
u32 i;
|
||||||
@@ -2451,9 +2449,8 @@ static void sde_cp_notify_hist_event(struct drm_crtc *crtc_drm, void *arg)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv = kms->dev->dev_private;
|
ret = pm_runtime_get_sync(kms->dev->dev);
|
||||||
ret = sde_power_resource_enable(&priv->phandle, kms->core_client, true);
|
if (ret < 0) {
|
||||||
if (ret) {
|
|
||||||
SDE_ERROR("failed to enable power resource %d\n", ret);
|
SDE_ERROR("failed to enable power resource %d\n", ret);
|
||||||
SDE_EVT32(ret, SDE_EVTLOG_ERROR);
|
SDE_EVT32(ret, SDE_EVTLOG_ERROR);
|
||||||
return;
|
return;
|
||||||
@@ -2467,15 +2464,13 @@ static void sde_cp_notify_hist_event(struct drm_crtc *crtc_drm, void *arg)
|
|||||||
if (!hw_dspp || !hw_dspp->ops.read_histogram) {
|
if (!hw_dspp || !hw_dspp->ops.read_histogram) {
|
||||||
DRM_ERROR("invalid dspp %pK or read_histogram func\n",
|
DRM_ERROR("invalid dspp %pK or read_histogram func\n",
|
||||||
hw_dspp);
|
hw_dspp);
|
||||||
sde_power_resource_enable(&priv->phandle,
|
pm_runtime_put_sync(kms->dev->dev);
|
||||||
kms->core_client, false);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hw_dspp->ops.read_histogram(hw_dspp, hist_data);
|
hw_dspp->ops.read_histogram(hw_dspp, hist_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
sde_power_resource_enable(&priv->phandle, kms->core_client,
|
pm_runtime_put_sync(kms->dev->dev);
|
||||||
false);
|
|
||||||
/* send histogram event with blob id */
|
/* send histogram event with blob id */
|
||||||
event.length = sizeof(u32);
|
event.length = sizeof(u32);
|
||||||
event.type = DRM_EVENT_HISTOGRAM;
|
event.type = DRM_EVENT_HISTOGRAM;
|
||||||
|
@@ -441,25 +441,16 @@ void sde_debugfs_core_irq_destroy(struct sde_kms *sde_kms)
|
|||||||
|
|
||||||
void sde_core_irq_preinstall(struct sde_kms *sde_kms)
|
void sde_core_irq_preinstall(struct sde_kms *sde_kms)
|
||||||
{
|
{
|
||||||
struct msm_drm_private *priv;
|
|
||||||
int i;
|
int i;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!sde_kms) {
|
if (!sde_kms || !sde_kms->dev) {
|
||||||
SDE_ERROR("invalid sde_kms\n");
|
SDE_ERROR("invalid sde_kms or dev\n");
|
||||||
return;
|
|
||||||
} else if (!sde_kms->dev) {
|
|
||||||
SDE_ERROR("invalid drm device\n");
|
|
||||||
return;
|
|
||||||
} else if (!sde_kms->dev->dev_private) {
|
|
||||||
SDE_ERROR("invalid device private\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
priv = sde_kms->dev->dev_private;
|
|
||||||
|
|
||||||
rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
|
rc = pm_runtime_get_sync(sde_kms->dev->dev);
|
||||||
true);
|
if (rc < 0) {
|
||||||
if (rc) {
|
|
||||||
SDE_ERROR("failed to enable power resource %d\n", rc);
|
SDE_ERROR("failed to enable power resource %d\n", rc);
|
||||||
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
||||||
return;
|
return;
|
||||||
@@ -467,7 +458,7 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms)
|
|||||||
|
|
||||||
sde_clear_all_irqs(sde_kms);
|
sde_clear_all_irqs(sde_kms);
|
||||||
sde_disable_all_irqs(sde_kms);
|
sde_disable_all_irqs(sde_kms);
|
||||||
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
|
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||||
|
|
||||||
spin_lock_init(&sde_kms->irq_obj.cb_lock);
|
spin_lock_init(&sde_kms->irq_obj.cb_lock);
|
||||||
|
|
||||||
@@ -493,26 +484,17 @@ int sde_core_irq_postinstall(struct sde_kms *sde_kms)
|
|||||||
|
|
||||||
void sde_core_irq_uninstall(struct sde_kms *sde_kms)
|
void sde_core_irq_uninstall(struct sde_kms *sde_kms)
|
||||||
{
|
{
|
||||||
struct msm_drm_private *priv;
|
|
||||||
int i;
|
int i;
|
||||||
int rc;
|
int rc;
|
||||||
unsigned long irq_flags;
|
unsigned long irq_flags;
|
||||||
|
|
||||||
if (!sde_kms) {
|
if (!sde_kms || !sde_kms->dev) {
|
||||||
SDE_ERROR("invalid sde_kms\n");
|
SDE_ERROR("invalid sde_kms or dev\n");
|
||||||
return;
|
|
||||||
} else if (!sde_kms->dev) {
|
|
||||||
SDE_ERROR("invalid drm device\n");
|
|
||||||
return;
|
|
||||||
} else if (!sde_kms->dev->dev_private) {
|
|
||||||
SDE_ERROR("invalid device private\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
priv = sde_kms->dev->dev_private;
|
|
||||||
|
|
||||||
rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
|
rc = pm_runtime_get_sync(sde_kms->dev->dev);
|
||||||
true);
|
if (rc < 0) {
|
||||||
if (rc) {
|
|
||||||
SDE_ERROR("failed to enable power resource %d\n", rc);
|
SDE_ERROR("failed to enable power resource %d\n", rc);
|
||||||
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
||||||
return;
|
return;
|
||||||
@@ -525,7 +507,7 @@ void sde_core_irq_uninstall(struct sde_kms *sde_kms)
|
|||||||
|
|
||||||
sde_clear_all_irqs(sde_kms);
|
sde_clear_all_irqs(sde_kms);
|
||||||
sde_disable_all_irqs(sde_kms);
|
sde_disable_all_irqs(sde_kms);
|
||||||
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
|
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||||
|
|
||||||
spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
|
spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags);
|
||||||
kfree(sde_kms->irq_obj.irq_cb_tbl);
|
kfree(sde_kms->irq_obj.irq_cb_tbl);
|
||||||
|
@@ -638,17 +638,8 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
|
|||||||
|
|
||||||
client_vote = _get_sde_client_type(curr_client_type, &kms->perf);
|
client_vote = _get_sde_client_type(curr_client_type, &kms->perf);
|
||||||
switch (client_vote) {
|
switch (client_vote) {
|
||||||
case NRT_CLIENT:
|
|
||||||
sde_power_data_bus_set_quota(&priv->phandle, kms->core_client,
|
|
||||||
SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT,
|
|
||||||
bus_id, bus_ab_quota, bus_ib_quota);
|
|
||||||
SDE_DEBUG("client:%s bus_id=%d ab=%llu ib=%llu\n", "nrt",
|
|
||||||
bus_id, bus_ab_quota, bus_ib_quota);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RT_CLIENT:
|
case RT_CLIENT:
|
||||||
sde_power_data_bus_set_quota(&priv->phandle, kms->core_client,
|
sde_power_data_bus_set_quota(&priv->phandle,
|
||||||
SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT,
|
|
||||||
bus_id, bus_ab_quota, bus_ib_quota);
|
bus_id, bus_ab_quota, bus_ib_quota);
|
||||||
SDE_DEBUG("client:%s bus_id=%d ab=%llu ib=%llu\n", "rt",
|
SDE_DEBUG("client:%s bus_id=%d ab=%llu ib=%llu\n", "rt",
|
||||||
bus_id, bus_ab_quota, bus_ib_quota);
|
bus_id, bus_ab_quota, bus_ib_quota);
|
||||||
@@ -671,12 +662,6 @@ static void _sde_core_perf_crtc_update_bus(struct sde_kms *kms,
|
|||||||
switch (kms->perf.bw_vote_mode) {
|
switch (kms->perf.bw_vote_mode) {
|
||||||
case DISP_RSC_MODE:
|
case DISP_RSC_MODE:
|
||||||
sde_power_data_bus_set_quota(&priv->phandle,
|
sde_power_data_bus_set_quota(&priv->phandle,
|
||||||
kms->core_client,
|
|
||||||
SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT,
|
|
||||||
bus_id, 0, 0);
|
|
||||||
sde_power_data_bus_set_quota(&priv->phandle,
|
|
||||||
kms->core_client,
|
|
||||||
SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT,
|
|
||||||
bus_id, 0, 0);
|
bus_id, 0, 0);
|
||||||
kms->perf.bw_vote_mode_updated = false;
|
kms->perf.bw_vote_mode_updated = false;
|
||||||
break;
|
break;
|
||||||
@@ -1212,10 +1197,9 @@ int sde_core_perf_init(struct sde_core_perf *perf,
|
|||||||
struct drm_device *dev,
|
struct drm_device *dev,
|
||||||
struct sde_mdss_cfg *catalog,
|
struct sde_mdss_cfg *catalog,
|
||||||
struct sde_power_handle *phandle,
|
struct sde_power_handle *phandle,
|
||||||
struct sde_power_client *pclient,
|
|
||||||
char *clk_name)
|
char *clk_name)
|
||||||
{
|
{
|
||||||
if (!perf || !dev || !catalog || !phandle || !pclient || !clk_name) {
|
if (!perf || !dev || !catalog || !phandle || !clk_name) {
|
||||||
SDE_ERROR("invalid parameters\n");
|
SDE_ERROR("invalid parameters\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -1223,7 +1207,6 @@ int sde_core_perf_init(struct sde_core_perf *perf,
|
|||||||
perf->dev = dev;
|
perf->dev = dev;
|
||||||
perf->catalog = catalog;
|
perf->catalog = catalog;
|
||||||
perf->phandle = phandle;
|
perf->phandle = phandle;
|
||||||
perf->pclient = pclient;
|
|
||||||
perf->clk_name = clk_name;
|
perf->clk_name = clk_name;
|
||||||
perf->sde_rsc_available = is_sde_rsc_available(SDE_RSC_INDEX);
|
perf->sde_rsc_available = is_sde_rsc_available(SDE_RSC_INDEX);
|
||||||
/* set default mode */
|
/* set default mode */
|
||||||
|
@@ -60,7 +60,6 @@ struct sde_core_perf_tune {
|
|||||||
* @debugfs_root: top level debug folder
|
* @debugfs_root: top level debug folder
|
||||||
* @catalog: Pointer to catalog configuration
|
* @catalog: Pointer to catalog configuration
|
||||||
* @phandle: Pointer to power handler
|
* @phandle: Pointer to power handler
|
||||||
* @pclient: Pointer to power client
|
|
||||||
* @clk_name: core clock name
|
* @clk_name: core clock name
|
||||||
* @core_clk: Pointer to core clock structure
|
* @core_clk: Pointer to core clock structure
|
||||||
* @core_clk_rate: current core clock rate
|
* @core_clk_rate: current core clock rate
|
||||||
@@ -81,7 +80,6 @@ struct sde_core_perf {
|
|||||||
struct dentry *debugfs_root;
|
struct dentry *debugfs_root;
|
||||||
struct sde_mdss_cfg *catalog;
|
struct sde_mdss_cfg *catalog;
|
||||||
struct sde_power_handle *phandle;
|
struct sde_power_handle *phandle;
|
||||||
struct sde_power_client *pclient;
|
|
||||||
char *clk_name;
|
char *clk_name;
|
||||||
struct clk *core_clk;
|
struct clk *core_clk;
|
||||||
u64 core_clk_rate;
|
u64 core_clk_rate;
|
||||||
@@ -141,14 +139,12 @@ void sde_core_perf_destroy(struct sde_core_perf *perf);
|
|||||||
* @dev: Pointer to drm device
|
* @dev: Pointer to drm device
|
||||||
* @catalog: Pointer to catalog
|
* @catalog: Pointer to catalog
|
||||||
* @phandle: Pointer to power handle
|
* @phandle: Pointer to power handle
|
||||||
* @pclient: Pointer to power client
|
|
||||||
* @clk_name: core clock name
|
* @clk_name: core clock name
|
||||||
*/
|
*/
|
||||||
int sde_core_perf_init(struct sde_core_perf *perf,
|
int sde_core_perf_init(struct sde_core_perf *perf,
|
||||||
struct drm_device *dev,
|
struct drm_device *dev,
|
||||||
struct sde_mdss_cfg *catalog,
|
struct sde_mdss_cfg *catalog,
|
||||||
struct sde_power_handle *phandle,
|
struct sde_power_handle *phandle,
|
||||||
struct sde_power_client *pclient,
|
|
||||||
char *clk_name);
|
char *clk_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -120,35 +120,6 @@ static inline struct drm_encoder *_sde_crtc_get_encoder(struct drm_crtc *crtc)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int _sde_crtc_power_enable(struct sde_crtc *sde_crtc, bool enable)
|
|
||||||
{
|
|
||||||
struct drm_crtc *crtc;
|
|
||||||
struct msm_drm_private *priv;
|
|
||||||
struct sde_kms *sde_kms;
|
|
||||||
|
|
||||||
if (!sde_crtc) {
|
|
||||||
SDE_ERROR("invalid sde crtc\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
crtc = &sde_crtc->base;
|
|
||||||
if (!crtc->dev || !crtc->dev->dev_private) {
|
|
||||||
SDE_ERROR("invalid drm device\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv = crtc->dev->dev_private;
|
|
||||||
if (!priv->kms) {
|
|
||||||
SDE_ERROR("invalid kms\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sde_kms = to_sde_kms(priv->kms);
|
|
||||||
|
|
||||||
return sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
|
|
||||||
enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_crtc_calc_fps() - Calculates fps value.
|
* sde_crtc_calc_fps() - Calculates fps value.
|
||||||
* @sde_crtc : CRTC structure
|
* @sde_crtc : CRTC structure
|
||||||
@@ -3666,9 +3637,9 @@ static int _sde_crtc_vblank_enable_no_lock(
|
|||||||
|
|
||||||
/* drop lock since power crtc cb may try to re-acquire lock */
|
/* drop lock since power crtc cb may try to re-acquire lock */
|
||||||
mutex_unlock(&sde_crtc->crtc_lock);
|
mutex_unlock(&sde_crtc->crtc_lock);
|
||||||
ret = _sde_crtc_power_enable(sde_crtc, true);
|
ret = pm_runtime_get_sync(crtc->dev->dev);
|
||||||
mutex_lock(&sde_crtc->crtc_lock);
|
mutex_lock(&sde_crtc->crtc_lock);
|
||||||
if (ret)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
|
list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
|
||||||
@@ -3698,7 +3669,7 @@ static int _sde_crtc_vblank_enable_no_lock(
|
|||||||
|
|
||||||
/* drop lock since power crtc cb may try to re-acquire lock */
|
/* drop lock since power crtc cb may try to re-acquire lock */
|
||||||
mutex_unlock(&sde_crtc->crtc_lock);
|
mutex_unlock(&sde_crtc->crtc_lock);
|
||||||
_sde_crtc_power_enable(sde_crtc, false);
|
pm_runtime_put_sync(crtc->dev->dev);
|
||||||
mutex_lock(&sde_crtc->crtc_lock);
|
mutex_lock(&sde_crtc->crtc_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5539,13 +5510,13 @@ static ssize_t _sde_crtc_misr_setup(struct file *file,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _sde_crtc_power_enable(sde_crtc, true);
|
rc = pm_runtime_get_sync(crtc->dev->dev);
|
||||||
if (rc)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
sde_crtc->misr_enable_debugfs = enable;
|
sde_crtc->misr_enable_debugfs = enable;
|
||||||
sde_crtc_misr_setup(crtc, enable, frame_count);
|
sde_crtc_misr_setup(crtc, enable, frame_count);
|
||||||
_sde_crtc_power_enable(sde_crtc, false);
|
pm_runtime_put_sync(crtc->dev->dev);
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
@@ -5573,8 +5544,8 @@ static ssize_t _sde_crtc_misr_read(struct file *file,
|
|||||||
if (!sde_kms)
|
if (!sde_kms)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
rc = _sde_crtc_power_enable(sde_crtc, true);
|
rc = pm_runtime_get_sync(crtc->dev->dev);
|
||||||
if (rc)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (sde_kms_is_secure_session_inprogress(sde_kms)) {
|
if (sde_kms_is_secure_session_inprogress(sde_kms)) {
|
||||||
@@ -5628,7 +5599,7 @@ buff_check:
|
|||||||
*ppos += len; /* increase offset */
|
*ppos += len; /* increase offset */
|
||||||
|
|
||||||
end:
|
end:
|
||||||
_sde_crtc_power_enable(sde_crtc, false);
|
pm_runtime_put_sync(crtc->dev->dev);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6110,7 +6081,6 @@ static int _sde_crtc_event_enable(struct sde_kms *kms,
|
|||||||
{
|
{
|
||||||
struct sde_crtc *crtc = NULL;
|
struct sde_crtc *crtc = NULL;
|
||||||
struct sde_crtc_irq_info *node;
|
struct sde_crtc_irq_info *node;
|
||||||
struct msm_drm_private *priv;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int ret, i = 0;
|
int ret, i = 0;
|
||||||
@@ -6151,13 +6121,10 @@ static int _sde_crtc_event_enable(struct sde_kms *kms,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv = kms->dev->dev_private;
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
if (crtc_drm->enabled) {
|
if (crtc_drm->enabled) {
|
||||||
ret = sde_power_resource_enable(&priv->phandle,
|
ret = pm_runtime_get_sync(crtc_drm->dev->dev);
|
||||||
kms->core_client, true);
|
if (ret < 0) {
|
||||||
if (ret) {
|
|
||||||
SDE_ERROR("failed to enable power resource %d\n", ret);
|
|
||||||
SDE_EVT32(ret, SDE_EVTLOG_ERROR);
|
SDE_EVT32(ret, SDE_EVTLOG_ERROR);
|
||||||
kfree(node);
|
kfree(node);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -6175,8 +6142,7 @@ static int _sde_crtc_event_enable(struct sde_kms *kms,
|
|||||||
}
|
}
|
||||||
mutex_unlock(&crtc->crtc_lock);
|
mutex_unlock(&crtc->crtc_lock);
|
||||||
|
|
||||||
sde_power_resource_enable(&priv->phandle, kms->core_client,
|
pm_runtime_put_sync(crtc_drm->dev->dev);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_event)
|
if (add_event)
|
||||||
@@ -6198,7 +6164,6 @@ static int _sde_crtc_event_disable(struct sde_kms *kms,
|
|||||||
{
|
{
|
||||||
struct sde_crtc *crtc = NULL;
|
struct sde_crtc *crtc = NULL;
|
||||||
struct sde_crtc_irq_info *node = NULL;
|
struct sde_crtc_irq_info *node = NULL;
|
||||||
struct msm_drm_private *priv;
|
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
int ret;
|
int ret;
|
||||||
@@ -6226,9 +6191,8 @@ static int _sde_crtc_event_disable(struct sde_kms *kms,
|
|||||||
kfree(node);
|
kfree(node);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
priv = kms->dev->dev_private;
|
ret = pm_runtime_get_sync(crtc_drm->dev->dev);
|
||||||
ret = sde_power_resource_enable(&priv->phandle, kms->core_client, true);
|
if (ret < 0) {
|
||||||
if (ret) {
|
|
||||||
SDE_ERROR("failed to enable power resource %d\n", ret);
|
SDE_ERROR("failed to enable power resource %d\n", ret);
|
||||||
SDE_EVT32(ret, SDE_EVTLOG_ERROR);
|
SDE_EVT32(ret, SDE_EVTLOG_ERROR);
|
||||||
kfree(node);
|
kfree(node);
|
||||||
@@ -6237,7 +6201,7 @@ static int _sde_crtc_event_disable(struct sde_kms *kms,
|
|||||||
|
|
||||||
ret = node->func(crtc_drm, false, &node->irq);
|
ret = node->func(crtc_drm, false, &node->irq);
|
||||||
kfree(node);
|
kfree(node);
|
||||||
sde_power_resource_enable(&priv->phandle, kms->core_client, false);
|
pm_runtime_put_sync(crtc_drm->dev->dev);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -595,7 +595,7 @@ enum sde_intf_mode sde_crtc_get_intf_mode(struct drm_crtc *crtc);
|
|||||||
u32 sde_crtc_get_fps_mode(struct drm_crtc *crtc);
|
u32 sde_crtc_get_fps_mode(struct drm_crtc *crtc);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_crtc_get_client_type - check the crtc type- rt, nrt, rsc, etc.
|
* sde_crtc_get_client_type - check the crtc type- rt, rsc_rt, etc.
|
||||||
* @crtc: Pointer to crtc
|
* @crtc: Pointer to crtc
|
||||||
*/
|
*/
|
||||||
static inline enum sde_crtc_client_type sde_crtc_get_client_type(
|
static inline enum sde_crtc_client_type sde_crtc_get_client_type(
|
||||||
@@ -605,10 +605,9 @@ static inline enum sde_crtc_client_type sde_crtc_get_client_type(
|
|||||||
crtc ? to_sde_crtc_state(crtc->state) : NULL;
|
crtc ? to_sde_crtc_state(crtc->state) : NULL;
|
||||||
|
|
||||||
if (!cstate)
|
if (!cstate)
|
||||||
return NRT_CLIENT;
|
return RT_CLIENT;
|
||||||
|
|
||||||
return sde_crtc_get_intf_mode(crtc) == INTF_MODE_WB_LINE ? NRT_CLIENT :
|
return cstate->rsc_client ? RT_RSC_CLIENT : RT_CLIENT;
|
||||||
(cstate->rsc_client ? RT_RSC_CLIENT : RT_CLIENT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -417,36 +417,6 @@ int sde_encoder_in_cont_splash(struct drm_encoder *drm_enc)
|
|||||||
sde_enc->cur_master->cont_splash_enabled;
|
sde_enc->cur_master->cont_splash_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int _sde_encoder_power_enable(struct sde_encoder_virt *sde_enc,
|
|
||||||
bool enable)
|
|
||||||
{
|
|
||||||
struct drm_encoder *drm_enc;
|
|
||||||
struct msm_drm_private *priv;
|
|
||||||
struct sde_kms *sde_kms;
|
|
||||||
|
|
||||||
if (!sde_enc) {
|
|
||||||
SDE_ERROR("invalid sde enc\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
drm_enc = &sde_enc->base;
|
|
||||||
if (!drm_enc->dev || !drm_enc->dev->dev_private) {
|
|
||||||
SDE_ERROR("drm device invalid\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv = drm_enc->dev->dev_private;
|
|
||||||
if (!priv->kms) {
|
|
||||||
SDE_ERROR("invalid kms\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sde_kms = to_sde_kms(priv->kms);
|
|
||||||
|
|
||||||
return sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
|
|
||||||
enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sde_encoder_helper_report_irq_timeout(struct sde_encoder_phys *phys_enc,
|
void sde_encoder_helper_report_irq_timeout(struct sde_encoder_phys *phys_enc,
|
||||||
enum sde_intr_idx intr_idx)
|
enum sde_intr_idx intr_idx)
|
||||||
{
|
{
|
||||||
@@ -2082,9 +2052,8 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
|
|||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
/* enable SDE core clks */
|
/* enable SDE core clks */
|
||||||
rc = sde_power_resource_enable(&priv->phandle,
|
rc = pm_runtime_get_sync(drm_enc->dev->dev);
|
||||||
sde_kms->core_client, true);
|
if (rc < 0) {
|
||||||
if (rc) {
|
|
||||||
SDE_ERROR("failed to enable power resource %d\n", rc);
|
SDE_ERROR("failed to enable power resource %d\n", rc);
|
||||||
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -2096,8 +2065,7 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
|
|||||||
true);
|
true);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SDE_ERROR("failed to enable clk control %d\n", rc);
|
SDE_ERROR("failed to enable clk control %d\n", rc);
|
||||||
sde_power_resource_enable(&priv->phandle,
|
pm_runtime_put_sync(drm_enc->dev->dev);
|
||||||
sde_kms->core_client, false);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2118,8 +2086,7 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc,
|
|||||||
sde_connector_clk_ctrl(sde_enc->cur_master->connector, false);
|
sde_connector_clk_ctrl(sde_enc->cur_master->connector, false);
|
||||||
|
|
||||||
/* disable SDE core clks */
|
/* disable SDE core clks */
|
||||||
sde_power_resource_enable(&priv->phandle,
|
pm_runtime_put_sync(drm_enc->dev->dev);
|
||||||
sde_kms->core_client, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3949,7 +3916,6 @@ static void _sde_encoder_kickoff_phys(struct sde_encoder_virt *sde_enc)
|
|||||||
sde_kms = to_sde_kms(priv->kms);
|
sde_kms = to_sde_kms(priv->kms);
|
||||||
if (sde_kms != NULL) {
|
if (sde_kms != NULL) {
|
||||||
sde_power_scale_reg_bus(&priv->phandle,
|
sde_power_scale_reg_bus(&priv->phandle,
|
||||||
sde_kms->core_client,
|
|
||||||
VOTE_INDEX_LOW,
|
VOTE_INDEX_LOW,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
@@ -4350,14 +4316,16 @@ static void sde_encoder_vsync_event_work_handler(struct kthread_work *work)
|
|||||||
bool autorefresh_enabled = false;
|
bool autorefresh_enabled = false;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
ktime_t wakeup_time;
|
ktime_t wakeup_time;
|
||||||
|
struct drm_encoder *drm_enc;
|
||||||
|
|
||||||
if (!sde_enc) {
|
if (!sde_enc) {
|
||||||
SDE_ERROR("invalid sde encoder\n");
|
SDE_ERROR("invalid sde encoder\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _sde_encoder_power_enable(sde_enc, true);
|
drm_enc = &sde_enc->base;
|
||||||
if (rc) {
|
rc = pm_runtime_get_sync(drm_enc->dev->dev);
|
||||||
|
if (rc < 0) {
|
||||||
SDE_ERROR_ENC(sde_enc, "sde enc power enabled failed:%d\n", rc);
|
SDE_ERROR_ENC(sde_enc, "sde enc power enabled failed:%d\n", rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4381,7 +4349,7 @@ static void sde_encoder_vsync_event_work_handler(struct kthread_work *work)
|
|||||||
nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
|
nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
_sde_encoder_power_enable(sde_enc, false);
|
pm_runtime_put_sync(drm_enc->dev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sde_encoder_poll_line_counts(struct drm_encoder *drm_enc)
|
int sde_encoder_poll_line_counts(struct drm_encoder *drm_enc)
|
||||||
@@ -4932,6 +4900,7 @@ static ssize_t _sde_encoder_misr_setup(struct file *file,
|
|||||||
u32 frame_count, enable;
|
u32 frame_count, enable;
|
||||||
struct msm_drm_private *priv = NULL;
|
struct msm_drm_private *priv = NULL;
|
||||||
struct sde_kms *sde_kms = NULL;
|
struct sde_kms *sde_kms = NULL;
|
||||||
|
struct drm_encoder *drm_enc;
|
||||||
|
|
||||||
if (!file || !file->private_data)
|
if (!file || !file->private_data)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -4942,6 +4911,7 @@ static ssize_t _sde_encoder_misr_setup(struct file *file,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
sde_kms = to_sde_kms(priv->kms);
|
sde_kms = to_sde_kms(priv->kms);
|
||||||
|
drm_enc = &sde_enc->base;
|
||||||
|
|
||||||
if (sde_kms_is_secure_session_inprogress(sde_kms)) {
|
if (sde_kms_is_secure_session_inprogress(sde_kms)) {
|
||||||
SDE_DEBUG_ENC(sde_enc, "misr enable/disable not allowed\n");
|
SDE_DEBUG_ENC(sde_enc, "misr enable/disable not allowed\n");
|
||||||
@@ -4957,14 +4927,14 @@ static ssize_t _sde_encoder_misr_setup(struct file *file,
|
|||||||
if (sscanf(buf, "%u %u", &enable, &frame_count) != 2)
|
if (sscanf(buf, "%u %u", &enable, &frame_count) != 2)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
rc = _sde_encoder_power_enable(sde_enc, true);
|
rc = pm_runtime_get_sync(drm_enc->dev->dev);
|
||||||
if (rc)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
sde_enc->misr_enable = enable;
|
sde_enc->misr_enable = enable;
|
||||||
sde_enc->misr_frame_count = frame_count;
|
sde_enc->misr_frame_count = frame_count;
|
||||||
sde_encoder_misr_configure(&sde_enc->base, enable, frame_count);
|
sde_encoder_misr_configure(&sde_enc->base, enable, frame_count);
|
||||||
_sde_encoder_power_enable(sde_enc, false);
|
pm_runtime_put_sync(drm_enc->dev->dev);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4974,6 +4944,7 @@ static ssize_t _sde_encoder_misr_read(struct file *file,
|
|||||||
struct sde_encoder_virt *sde_enc;
|
struct sde_encoder_virt *sde_enc;
|
||||||
struct msm_drm_private *priv = NULL;
|
struct msm_drm_private *priv = NULL;
|
||||||
struct sde_kms *sde_kms = NULL;
|
struct sde_kms *sde_kms = NULL;
|
||||||
|
struct drm_encoder *drm_enc;
|
||||||
int i = 0, len = 0;
|
int i = 0, len = 0;
|
||||||
char buf[MISR_BUFF_SIZE + 1] = {'\0'};
|
char buf[MISR_BUFF_SIZE + 1] = {'\0'};
|
||||||
int rc;
|
int rc;
|
||||||
@@ -4993,9 +4964,10 @@ static ssize_t _sde_encoder_misr_read(struct file *file,
|
|||||||
SDE_DEBUG_ENC(sde_enc, "misr read not allowed\n");
|
SDE_DEBUG_ENC(sde_enc, "misr read not allowed\n");
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
drm_enc = &sde_enc->base;
|
||||||
|
|
||||||
rc = _sde_encoder_power_enable(sde_enc, true);
|
rc = pm_runtime_get_sync(drm_enc->dev->dev);
|
||||||
if (rc)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (!sde_enc->misr_enable) {
|
if (!sde_enc->misr_enable) {
|
||||||
@@ -5045,7 +5017,7 @@ buff_check:
|
|||||||
*ppos += len; /* increase offset */
|
*ppos += len; /* increase offset */
|
||||||
|
|
||||||
end:
|
end:
|
||||||
_sde_encoder_power_enable(sde_enc, false);
|
pm_runtime_put_sync(drm_enc->dev->dev);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -398,14 +398,11 @@ end:
|
|||||||
static int _sde_kms_sui_misr_ctrl(struct sde_kms *sde_kms,
|
static int _sde_kms_sui_misr_ctrl(struct sde_kms *sde_kms,
|
||||||
struct drm_crtc *crtc, bool enable)
|
struct drm_crtc *crtc, bool enable)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = sde_kms->dev;
|
|
||||||
struct msm_drm_private *priv = dev->dev_private;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
ret = sde_power_resource_enable(&priv->phandle,
|
ret = pm_runtime_get_sync(sde_kms->dev->dev);
|
||||||
sde_kms->core_client, true);
|
if (ret < 0) {
|
||||||
if (ret) {
|
|
||||||
SDE_ERROR("failed to enable resource, ret:%d\n", ret);
|
SDE_ERROR("failed to enable resource, ret:%d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -414,16 +411,14 @@ static int _sde_kms_sui_misr_ctrl(struct sde_kms *sde_kms,
|
|||||||
|
|
||||||
ret = _sde_kms_secure_ctrl_xin_clients(sde_kms, crtc, true);
|
ret = _sde_kms_secure_ctrl_xin_clients(sde_kms, crtc, true);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
sde_power_resource_enable(&priv->phandle,
|
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||||
sde_kms->core_client, false);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_sde_kms_secure_ctrl_xin_clients(sde_kms, crtc, false);
|
_sde_kms_secure_ctrl_xin_clients(sde_kms, crtc, false);
|
||||||
sde_crtc_misr_setup(crtc, false, 0);
|
sde_crtc_misr_setup(crtc, false, 0);
|
||||||
sde_power_resource_enable(&priv->phandle,
|
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||||
sde_kms->core_client, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -783,7 +778,7 @@ static void sde_kms_prepare_commit(struct msm_kms *kms,
|
|||||||
struct drm_encoder *encoder;
|
struct drm_encoder *encoder;
|
||||||
struct drm_crtc *crtc;
|
struct drm_crtc *crtc;
|
||||||
struct drm_crtc_state *crtc_state;
|
struct drm_crtc_state *crtc_state;
|
||||||
int i, rc = 0;
|
int i, rc;
|
||||||
|
|
||||||
if (!kms)
|
if (!kms)
|
||||||
return;
|
return;
|
||||||
@@ -795,17 +790,15 @@ static void sde_kms_prepare_commit(struct msm_kms *kms,
|
|||||||
priv = dev->dev_private;
|
priv = dev->dev_private;
|
||||||
|
|
||||||
SDE_ATRACE_BEGIN("prepare_commit");
|
SDE_ATRACE_BEGIN("prepare_commit");
|
||||||
rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
|
rc = pm_runtime_get_sync(sde_kms->dev->dev);
|
||||||
true);
|
if (rc < 0) {
|
||||||
if (rc) {
|
SDE_ERROR("failed to enable power resources %d\n", rc);
|
||||||
SDE_ERROR("failed to enable power resource %d\n", rc);
|
|
||||||
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sde_kms->first_kickoff) {
|
if (sde_kms->first_kickoff) {
|
||||||
sde_power_scale_reg_bus(&priv->phandle, sde_kms->core_client,
|
sde_power_scale_reg_bus(&priv->phandle, VOTE_INDEX_HIGH, false);
|
||||||
VOTE_INDEX_HIGH, false);
|
|
||||||
sde_kms->first_kickoff = false;
|
sde_kms->first_kickoff = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,20 +887,16 @@ static void _sde_kms_release_splash_resource(struct sde_kms *sde_kms,
|
|||||||
SDE_DEBUG("cont_splash handoff done for dpy:%d remaining:%d\n",
|
SDE_DEBUG("cont_splash handoff done for dpy:%d remaining:%d\n",
|
||||||
i, sde_kms->splash_data.num_splash_displays);
|
i, sde_kms->splash_data.num_splash_displays);
|
||||||
memset(splash_display, 0x0, sizeof(struct sde_splash_display));
|
memset(splash_display, 0x0, sizeof(struct sde_splash_display));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove the votes if all displays are done with splash */
|
/* remove the votes if all displays are done with splash */
|
||||||
if (!sde_kms->splash_data.num_splash_displays) {
|
if (!sde_kms->splash_data.num_splash_displays) {
|
||||||
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
||||||
sde_power_data_bus_set_quota(&priv->phandle,
|
sde_power_data_bus_set_quota(&priv->phandle, i,
|
||||||
sde_kms->core_client,
|
|
||||||
SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT, i,
|
|
||||||
SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA,
|
SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA,
|
||||||
SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
|
SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
|
||||||
|
|
||||||
sde_power_resource_enable(&priv->phandle,
|
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||||
sde_kms->core_client, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -930,7 +919,7 @@ static void sde_kms_complete_commit(struct msm_kms *kms,
|
|||||||
return;
|
return;
|
||||||
priv = sde_kms->dev->dev_private;
|
priv = sde_kms->dev->dev_private;
|
||||||
|
|
||||||
if (!sde_kms_power_resource_is_enabled(sde_kms->dev)) {
|
if (sde_kms_power_resource_is_enabled(sde_kms->dev) < 0) {
|
||||||
SDE_ERROR("power resource is not enabled\n");
|
SDE_ERROR("power resource is not enabled\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -959,7 +948,7 @@ static void sde_kms_complete_commit(struct msm_kms *kms,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
|
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||||
|
|
||||||
for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i)
|
for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i)
|
||||||
_sde_kms_release_splash_resource(sde_kms, crtc);
|
_sde_kms_release_splash_resource(sde_kms, crtc);
|
||||||
@@ -1662,10 +1651,6 @@ static void _sde_kms_hw_destroy(struct sde_kms *sde_kms,
|
|||||||
sde_hw_catalog_deinit(sde_kms->catalog);
|
sde_hw_catalog_deinit(sde_kms->catalog);
|
||||||
sde_kms->catalog = NULL;
|
sde_kms->catalog = NULL;
|
||||||
|
|
||||||
if (sde_kms->core_client)
|
|
||||||
sde_power_client_destroy(&priv->phandle, sde_kms->core_client);
|
|
||||||
sde_kms->core_client = NULL;
|
|
||||||
|
|
||||||
if (sde_kms->sid)
|
if (sde_kms->sid)
|
||||||
msm_iounmap(pdev, sde_kms->sid);
|
msm_iounmap(pdev, sde_kms->sid);
|
||||||
sde_kms->sid = NULL;
|
sde_kms->sid = NULL;
|
||||||
@@ -2898,23 +2883,15 @@ static void sde_kms_handle_power_event(u32 event_type, void *usr)
|
|||||||
static int sde_kms_pd_enable(struct generic_pm_domain *genpd)
|
static int sde_kms_pd_enable(struct generic_pm_domain *genpd)
|
||||||
{
|
{
|
||||||
struct sde_kms *sde_kms = genpd_to_sde_kms(genpd);
|
struct sde_kms *sde_kms = genpd_to_sde_kms(genpd);
|
||||||
struct drm_device *dev;
|
int rc = -EINVAL;
|
||||||
struct msm_drm_private *priv;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
SDE_DEBUG("\n");
|
SDE_DEBUG("\n");
|
||||||
|
|
||||||
dev = sde_kms->dev;
|
rc = pm_runtime_get_sync(sde_kms->dev->dev);
|
||||||
if (!dev)
|
if (rc > 0)
|
||||||
return -EINVAL;
|
rc = 0;
|
||||||
|
|
||||||
priv = dev->dev_private;
|
SDE_EVT32(rc, genpd->device_count);
|
||||||
if (!priv)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
SDE_EVT32(genpd->device_count);
|
|
||||||
|
|
||||||
rc = sde_power_resource_enable(&priv->phandle, priv->pclient, true);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -2922,25 +2899,14 @@ static int sde_kms_pd_enable(struct generic_pm_domain *genpd)
|
|||||||
static int sde_kms_pd_disable(struct generic_pm_domain *genpd)
|
static int sde_kms_pd_disable(struct generic_pm_domain *genpd)
|
||||||
{
|
{
|
||||||
struct sde_kms *sde_kms = genpd_to_sde_kms(genpd);
|
struct sde_kms *sde_kms = genpd_to_sde_kms(genpd);
|
||||||
struct drm_device *dev;
|
|
||||||
struct msm_drm_private *priv;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
SDE_DEBUG("\n");
|
SDE_DEBUG("\n");
|
||||||
|
|
||||||
dev = sde_kms->dev;
|
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||||
if (!dev)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
priv = dev->dev_private;
|
|
||||||
if (!priv)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
SDE_EVT32(genpd->device_count);
|
SDE_EVT32(genpd->device_count);
|
||||||
|
|
||||||
rc = sde_power_resource_enable(&priv->phandle, priv->pclient, false);
|
return 0;
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sde_kms_get_splash_data(struct sde_splash_data *data)
|
static int _sde_kms_get_splash_data(struct sde_splash_data *data)
|
||||||
@@ -3155,9 +3121,7 @@ static int _sde_kms_hw_init_blocks(struct sde_kms *sde_kms,
|
|||||||
int i, rc = -EINVAL;
|
int i, rc = -EINVAL;
|
||||||
|
|
||||||
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
||||||
sde_power_data_bus_set_quota(&priv->phandle,
|
sde_power_data_bus_set_quota(&priv->phandle, i,
|
||||||
sde_kms->core_client,
|
|
||||||
SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT, i,
|
|
||||||
SDE_POWER_HANDLE_CONT_SPLASH_BUS_AB_QUOTA,
|
SDE_POWER_HANDLE_CONT_SPLASH_BUS_AB_QUOTA,
|
||||||
SDE_POWER_HANDLE_CONT_SPLASH_BUS_IB_QUOTA);
|
SDE_POWER_HANDLE_CONT_SPLASH_BUS_IB_QUOTA);
|
||||||
|
|
||||||
@@ -3281,7 +3245,7 @@ static int _sde_kms_hw_init_blocks(struct sde_kms *sde_kms,
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = sde_core_perf_init(&sde_kms->perf, dev, sde_kms->catalog,
|
rc = sde_core_perf_init(&sde_kms->perf, dev, sde_kms->catalog,
|
||||||
&priv->phandle, priv->pclient, "core_clk");
|
&priv->phandle, "core_clk");
|
||||||
if (rc) {
|
if (rc) {
|
||||||
SDE_ERROR("failed to init perf %d\n", rc);
|
SDE_ERROR("failed to init perf %d\n", rc);
|
||||||
goto perf_err;
|
goto perf_err;
|
||||||
@@ -3339,23 +3303,12 @@ static int sde_kms_hw_init(struct msm_kms *kms)
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
sde_kms->core_client = sde_power_client_create(&priv->phandle, "core");
|
|
||||||
if (IS_ERR_OR_NULL(sde_kms->core_client)) {
|
|
||||||
rc = PTR_ERR(sde_kms->core_client);
|
|
||||||
if (!sde_kms->core_client)
|
|
||||||
rc = -EINVAL;
|
|
||||||
SDE_ERROR("sde power client create failed: %d\n", rc);
|
|
||||||
sde_kms->core_client = NULL;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = _sde_kms_get_splash_data(&sde_kms->splash_data);
|
rc = _sde_kms_get_splash_data(&sde_kms->splash_data);
|
||||||
if (rc)
|
if (rc)
|
||||||
SDE_DEBUG("sde splash data fetch failed: %d\n", rc);
|
SDE_DEBUG("sde splash data fetch failed: %d\n", rc);
|
||||||
|
|
||||||
rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
|
rc = pm_runtime_get_sync(sde_kms->dev->dev);
|
||||||
true);
|
if (rc < 0) {
|
||||||
if (rc) {
|
|
||||||
SDE_ERROR("resource enable failed: %d\n", rc);
|
SDE_ERROR("resource enable failed: %d\n", rc);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@@ -3391,19 +3344,16 @@ static int sde_kms_hw_init(struct msm_kms *kms)
|
|||||||
SDE_DEBUG("Skipping MDP Resources disable\n");
|
SDE_DEBUG("Skipping MDP Resources disable\n");
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
||||||
sde_power_data_bus_set_quota(&priv->phandle,
|
sde_power_data_bus_set_quota(&priv->phandle, i,
|
||||||
sde_kms->core_client,
|
|
||||||
SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT, i,
|
|
||||||
SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA,
|
SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA,
|
||||||
SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
|
SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
|
||||||
|
|
||||||
sde_power_resource_enable(&priv->phandle,
|
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||||
sde_kms->core_client, false);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
hw_init_err:
|
hw_init_err:
|
||||||
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
|
pm_runtime_put_sync(sde_kms->dev->dev);
|
||||||
error:
|
error:
|
||||||
_sde_kms_hw_destroy(sde_kms, platformdev);
|
_sde_kms_hw_destroy(sde_kms, platformdev);
|
||||||
end:
|
end:
|
||||||
|
@@ -238,8 +238,6 @@ struct sde_kms {
|
|||||||
bool genpd_init;
|
bool genpd_init;
|
||||||
|
|
||||||
struct msm_gem_address_space *aspace[MSM_SMMU_DOMAIN_MAX];
|
struct msm_gem_address_space *aspace[MSM_SMMU_DOMAIN_MAX];
|
||||||
struct sde_power_client *core_client;
|
|
||||||
|
|
||||||
struct sde_power_event *power_event;
|
struct sde_power_event *power_event;
|
||||||
|
|
||||||
/* directory entry for debugfs */
|
/* directory entry for debugfs */
|
||||||
@@ -312,14 +310,10 @@ bool sde_is_custom_client(void);
|
|||||||
*/
|
*/
|
||||||
static inline bool sde_kms_power_resource_is_enabled(struct drm_device *dev)
|
static inline bool sde_kms_power_resource_is_enabled(struct drm_device *dev)
|
||||||
{
|
{
|
||||||
struct msm_drm_private *priv;
|
if (!dev)
|
||||||
|
|
||||||
if (!dev || !dev->dev_private)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
priv = dev->dev_private;
|
return pm_runtime_enabled(dev->dev);
|
||||||
|
|
||||||
return sde_power_resource_is_enabled(&priv->phandle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -550,30 +550,20 @@ void sde_plane_set_revalidate(struct drm_plane *plane, bool enable)
|
|||||||
int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
|
int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
|
||||||
{
|
{
|
||||||
struct sde_plane *psde;
|
struct sde_plane *psde;
|
||||||
struct msm_drm_private *priv;
|
|
||||||
struct sde_kms *sde_kms;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (!plane || !plane->dev) {
|
if (!plane) {
|
||||||
SDE_ERROR("invalid arguments\n");
|
SDE_ERROR("invalid arguments\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv = plane->dev->dev_private;
|
|
||||||
if (!priv || !priv->kms) {
|
|
||||||
SDE_ERROR("invalid KMS reference\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sde_kms = to_sde_kms(priv->kms);
|
|
||||||
psde = to_sde_plane(plane);
|
psde = to_sde_plane(plane);
|
||||||
|
|
||||||
if (!psde->is_rt_pipe)
|
if (!psde->is_rt_pipe)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
rc = sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
|
rc = pm_runtime_get_sync(plane->dev->dev);
|
||||||
true);
|
if (rc < 0) {
|
||||||
if (rc) {
|
|
||||||
SDE_ERROR("failed to enable power resource %d\n", rc);
|
SDE_ERROR("failed to enable power resource %d\n", rc);
|
||||||
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
SDE_EVT32(rc, SDE_EVTLOG_ERROR);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -581,7 +571,7 @@ int sde_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
|
|||||||
|
|
||||||
_sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
|
_sde_plane_set_qos_ctrl(plane, enable, SDE_PLANE_QOS_PANIC_CTRL);
|
||||||
|
|
||||||
sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
|
pm_runtime_put_sync(plane->dev->dev);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2103,28 +2093,6 @@ static int _sde_plane_fetch_halt(struct drm_plane *plane)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline int _sde_plane_power_enable(struct drm_plane *plane, bool enable)
|
|
||||||
{
|
|
||||||
struct msm_drm_private *priv;
|
|
||||||
struct sde_kms *sde_kms;
|
|
||||||
|
|
||||||
if (!plane->dev || !plane->dev->dev_private) {
|
|
||||||
SDE_ERROR("invalid drm device\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv = plane->dev->dev_private;
|
|
||||||
if (!priv->kms) {
|
|
||||||
SDE_ERROR("invalid kms\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sde_kms = to_sde_kms(priv->kms);
|
|
||||||
|
|
||||||
return sde_power_resource_enable(&priv->phandle, sde_kms->core_client,
|
|
||||||
enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sde_plane_cleanup_fb(struct drm_plane *plane,
|
static void sde_plane_cleanup_fb(struct drm_plane *plane,
|
||||||
struct drm_plane_state *old_state)
|
struct drm_plane_state *old_state)
|
||||||
{
|
{
|
||||||
@@ -2149,10 +2117,10 @@ static void sde_plane_cleanup_fb(struct drm_plane *plane,
|
|||||||
psde->pipe - SSPP_VIG0);
|
psde->pipe - SSPP_VIG0);
|
||||||
|
|
||||||
/* halt this plane now */
|
/* halt this plane now */
|
||||||
ret = _sde_plane_power_enable(plane, true);
|
ret = pm_runtime_get_sync(plane->dev->dev);
|
||||||
if (ret) {
|
if (ret < 0) {
|
||||||
SDE_ERROR("power resource enable failed with %d", ret);
|
SDE_ERROR("power resource enable failed with %d", ret);
|
||||||
SDE_EVT32(ret);
|
SDE_EVT32(ret, SDE_EVTLOG_ERROR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2164,7 +2132,7 @@ static void sde_plane_cleanup_fb(struct drm_plane *plane,
|
|||||||
SDE_EVT32(DRMID(plane), psde->pipe - SSPP_VIG0,
|
SDE_EVT32(DRMID(plane), psde->pipe - SSPP_VIG0,
|
||||||
ret, SDE_EVTLOG_ERROR);
|
ret, SDE_EVTLOG_ERROR);
|
||||||
}
|
}
|
||||||
_sde_plane_power_enable(plane, false);
|
pm_runtime_put_sync(plane->dev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace);
|
msm_framebuffer_cleanup(old_state->fb, old_pstate->aspace);
|
||||||
|
@@ -86,23 +86,20 @@ TRACE_EVENT(sde_perf_set_ot,
|
|||||||
)
|
)
|
||||||
|
|
||||||
TRACE_EVENT(sde_perf_update_bus,
|
TRACE_EVENT(sde_perf_update_bus,
|
||||||
TP_PROTO(int client, u32 bus_id, unsigned long long ab_quota,
|
TP_PROTO(u32 bus_id, unsigned long long ab_quota,
|
||||||
unsigned long long ib_quota),
|
unsigned long long ib_quota),
|
||||||
TP_ARGS(client, bus_id, ab_quota, ib_quota),
|
TP_ARGS(bus_id, ab_quota, ib_quota),
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
__field(int, client)
|
|
||||||
__field(u32, bus_id);
|
__field(u32, bus_id);
|
||||||
__field(u64, ab_quota)
|
__field(u64, ab_quota)
|
||||||
__field(u64, ib_quota)
|
__field(u64, ib_quota)
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
__entry->client = client;
|
|
||||||
__entry->bus_id = bus_id;
|
__entry->bus_id = bus_id;
|
||||||
__entry->ab_quota = ab_quota;
|
__entry->ab_quota = ab_quota;
|
||||||
__entry->ib_quota = ib_quota;
|
__entry->ib_quota = ib_quota;
|
||||||
),
|
),
|
||||||
TP_printk("Request client:%d bus_id:%d ab=%llu ib=%llu",
|
TP_printk("Request bus_id:%d ab=%llu ib=%llu",
|
||||||
__entry->client,
|
|
||||||
__entry->bus_id,
|
__entry->bus_id,
|
||||||
__entry->ab_quota,
|
__entry->ab_quota,
|
||||||
__entry->ib_quota)
|
__entry->ib_quota)
|
||||||
|
@@ -13,6 +13,8 @@
|
|||||||
#include <linux/dma-buf.h>
|
#include <linux/dma-buf.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/list_sort.h>
|
#include <linux/list_sort.h>
|
||||||
|
#include <linux/pm.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
#include "sde_dbg.h"
|
#include "sde_dbg.h"
|
||||||
#include "sde/sde_hw_catalog.h"
|
#include "sde/sde_hw_catalog.h"
|
||||||
@@ -196,7 +198,6 @@ struct sde_dbg_regbuf {
|
|||||||
* @reg_base_list: list of register dumping regions
|
* @reg_base_list: list of register dumping regions
|
||||||
* @dev: device pointer
|
* @dev: device pointer
|
||||||
* @mutex: mutex to serialize access to serialze dumps, debugfs access
|
* @mutex: mutex to serialize access to serialze dumps, debugfs access
|
||||||
* @power_ctrl: callback structure for enabling power for reading hw registers
|
|
||||||
* @req_dump_blks: list of blocks requested for dumping
|
* @req_dump_blks: list of blocks requested for dumping
|
||||||
* @panic_on_err: whether to kernel panic after triggering dump via debugfs
|
* @panic_on_err: whether to kernel panic after triggering dump via debugfs
|
||||||
* @dump_work: work struct for deferring register dump work to separate thread
|
* @dump_work: work struct for deferring register dump work to separate thread
|
||||||
@@ -216,7 +217,6 @@ static struct sde_dbg_base {
|
|||||||
struct list_head reg_base_list;
|
struct list_head reg_base_list;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct sde_dbg_power_ctrl power_ctrl;
|
|
||||||
|
|
||||||
struct sde_dbg_reg_base *req_dump_blks[SDE_DBG_BASE_MAX];
|
struct sde_dbg_reg_base *req_dump_blks[SDE_DBG_BASE_MAX];
|
||||||
|
|
||||||
@@ -2825,21 +2825,6 @@ static struct vbif_debug_bus_entry vbif_dbg_bus_msm8998[] = {
|
|||||||
{0x21c, 0x214, 0, 14, 0, 0xc}, /* xin blocks - clock side */
|
{0x21c, 0x214, 0, 14, 0, 0xc}, /* xin blocks - clock side */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* _sde_dbg_enable_power - use callback to turn power on for hw register access
|
|
||||||
* @enable: whether to turn power on or off
|
|
||||||
* Return: zero if success; error code otherwise
|
|
||||||
*/
|
|
||||||
static inline int _sde_dbg_enable_power(int enable)
|
|
||||||
{
|
|
||||||
if (!sde_dbg_base.power_ctrl.enable_fn)
|
|
||||||
return -EINVAL;
|
|
||||||
return sde_dbg_base.power_ctrl.enable_fn(
|
|
||||||
sde_dbg_base.power_ctrl.handle,
|
|
||||||
sde_dbg_base.power_ctrl.client,
|
|
||||||
enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* _sde_dump_reg - helper function for dumping rotator register set content
|
* _sde_dump_reg - helper function for dumping rotator register set content
|
||||||
* @dump_name: register set name
|
* @dump_name: register set name
|
||||||
@@ -2901,8 +2886,8 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!from_isr) {
|
if (!from_isr) {
|
||||||
rc = _sde_dbg_enable_power(true);
|
rc = pm_runtime_get_sync(sde_dbg_base.dev);
|
||||||
if (rc) {
|
if (rc < 0) {
|
||||||
pr_err("failed to enable power %d\n", rc);
|
pr_err("failed to enable power %d\n", rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2933,7 +2918,7 @@ static void _sde_dump_reg(const char *dump_name, u32 reg_dump_flag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!from_isr)
|
if (!from_isr)
|
||||||
_sde_dbg_enable_power(false);
|
pm_runtime_put_sync(sde_dbg_base.dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -3138,8 +3123,8 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _sde_dbg_enable_power(true);
|
rc = pm_runtime_get_sync(sde_dbg_base.dev);
|
||||||
if (rc) {
|
if (rc < 0) {
|
||||||
pr_err("failed to enable power %d\n", rc);
|
pr_err("failed to enable power %d\n", rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3183,7 +3168,7 @@ static void _sde_dbg_dump_sde_dbg_bus(struct sde_dbg_sde_debug_bus *bus)
|
|||||||
head->wr_addr != DBGBUS_DSPP)
|
head->wr_addr != DBGBUS_DSPP)
|
||||||
writel_relaxed(0x0, mem_base + DBGBUS_DSPP);
|
writel_relaxed(0x0, mem_base + DBGBUS_DSPP);
|
||||||
}
|
}
|
||||||
_sde_dbg_enable_power(false);
|
pm_runtime_put_sync(sde_dbg_base.dev);
|
||||||
|
|
||||||
dev_info(sde_dbg_base.dev, "======== end %s dump =========\n",
|
dev_info(sde_dbg_base.dev, "======== end %s dump =========\n",
|
||||||
bus->cmn.name);
|
bus->cmn.name);
|
||||||
@@ -3295,8 +3280,8 @@ static void _sde_dbg_dump_vbif_dbg_bus(struct sde_dbg_vbif_debug_bus *bus)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _sde_dbg_enable_power(true);
|
rc = pm_runtime_get_sync(sde_dbg_base.dev);
|
||||||
if (rc) {
|
if (rc < 0) {
|
||||||
pr_err("failed to enable power %d\n", rc);
|
pr_err("failed to enable power %d\n", rc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -3350,7 +3335,7 @@ static void _sde_dbg_dump_vbif_dbg_bus(struct sde_dbg_vbif_debug_bus *bus)
|
|||||||
dump_addr += (head->block_cnt * head->test_pnt_cnt * 4);
|
dump_addr += (head->block_cnt * head->test_pnt_cnt * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
_sde_dbg_enable_power(false);
|
pm_runtime_put_sync(sde_dbg_base.dev);
|
||||||
|
|
||||||
dev_info(sde_dbg_base.dev, "======== end %s dump =========\n",
|
dev_info(sde_dbg_base.dev, "======== end %s dump =========\n",
|
||||||
bus->cmn.name);
|
bus->cmn.name);
|
||||||
@@ -4234,8 +4219,8 @@ static ssize_t sde_dbg_reg_base_reg_write(struct file *file,
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = _sde_dbg_enable_power(true);
|
rc = pm_runtime_get_sync(sde_dbg_base.dev);
|
||||||
if (rc) {
|
if (rc < 0) {
|
||||||
mutex_unlock(&sde_dbg_base.mutex);
|
mutex_unlock(&sde_dbg_base.mutex);
|
||||||
pr_err("failed to enable power %d\n", rc);
|
pr_err("failed to enable power %d\n", rc);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -4243,7 +4228,7 @@ static ssize_t sde_dbg_reg_base_reg_write(struct file *file,
|
|||||||
|
|
||||||
writel_relaxed(data, dbg->base + off);
|
writel_relaxed(data, dbg->base + off);
|
||||||
|
|
||||||
_sde_dbg_enable_power(false);
|
pm_runtime_put_sync(sde_dbg_base.dev);
|
||||||
|
|
||||||
mutex_unlock(&sde_dbg_base.mutex);
|
mutex_unlock(&sde_dbg_base.mutex);
|
||||||
|
|
||||||
@@ -4301,8 +4286,8 @@ static ssize_t sde_dbg_reg_base_reg_read(struct file *file,
|
|||||||
ptr = dbg->base + dbg->off;
|
ptr = dbg->base + dbg->off;
|
||||||
tot = 0;
|
tot = 0;
|
||||||
|
|
||||||
rc = _sde_dbg_enable_power(true);
|
rc = pm_runtime_get_sync(sde_dbg_base.dev);
|
||||||
if (rc) {
|
if (rc < 0) {
|
||||||
mutex_unlock(&sde_dbg_base.mutex);
|
mutex_unlock(&sde_dbg_base.mutex);
|
||||||
pr_err("failed to enable power %d\n", rc);
|
pr_err("failed to enable power %d\n", rc);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -4324,7 +4309,7 @@ static ssize_t sde_dbg_reg_base_reg_read(struct file *file,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
_sde_dbg_enable_power(false);
|
pm_runtime_put_sync(sde_dbg_base.dev);
|
||||||
|
|
||||||
dbg->buf_len = tot;
|
dbg->buf_len = tot;
|
||||||
}
|
}
|
||||||
@@ -4457,9 +4442,9 @@ void sde_dbg_init_dbg_buses(u32 hwversion)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int sde_dbg_init(struct device *dev, struct sde_dbg_power_ctrl *power_ctrl)
|
int sde_dbg_init(struct device *dev)
|
||||||
{
|
{
|
||||||
if (!dev || !power_ctrl) {
|
if (!dev) {
|
||||||
pr_err("invalid params\n");
|
pr_err("invalid params\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -4467,7 +4452,6 @@ int sde_dbg_init(struct device *dev, struct sde_dbg_power_ctrl *power_ctrl)
|
|||||||
mutex_init(&sde_dbg_base.mutex);
|
mutex_init(&sde_dbg_base.mutex);
|
||||||
INIT_LIST_HEAD(&sde_dbg_base.reg_base_list);
|
INIT_LIST_HEAD(&sde_dbg_base.reg_base_list);
|
||||||
sde_dbg_base.dev = dev;
|
sde_dbg_base.dev = dev;
|
||||||
sde_dbg_base.power_ctrl = *power_ctrl;
|
|
||||||
|
|
||||||
sde_dbg_base.evtlog = sde_evtlog_init();
|
sde_dbg_base.evtlog = sde_evtlog_init();
|
||||||
if (IS_ERR_OR_NULL(sde_dbg_base.evtlog))
|
if (IS_ERR_OR_NULL(sde_dbg_base.evtlog))
|
||||||
|
@@ -213,11 +213,9 @@ void sde_dbg_init_dbg_buses(u32 hwversion);
|
|||||||
/**
|
/**
|
||||||
* sde_dbg_init - initialize global sde debug facilities: evtlog, regdump
|
* sde_dbg_init - initialize global sde debug facilities: evtlog, regdump
|
||||||
* @dev: device handle
|
* @dev: device handle
|
||||||
* @power_ctrl: power control callback structure for enabling clocks
|
|
||||||
* during register dumping
|
|
||||||
* Returns: 0 or -ERROR
|
* Returns: 0 or -ERROR
|
||||||
*/
|
*/
|
||||||
int sde_dbg_init(struct device *dev, struct sde_dbg_power_ctrl *power_ctrl);
|
int sde_dbg_init(struct device *dev);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_dbg_debugfs_register - register entries at the given debugfs dir
|
* sde_dbg_debugfs_register - register entries at the given debugfs dir
|
||||||
|
@@ -77,53 +77,6 @@ static int sde_power_rsc_update(struct sde_power_handle *phandle, bool enable)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sde_power_client *sde_power_client_create(
|
|
||||||
struct sde_power_handle *phandle, char *client_name)
|
|
||||||
{
|
|
||||||
struct sde_power_client *client;
|
|
||||||
static u32 id;
|
|
||||||
|
|
||||||
if (!client_name || !phandle) {
|
|
||||||
pr_err("client name is null or invalid power data\n");
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
}
|
|
||||||
|
|
||||||
client = kzalloc(sizeof(struct sde_power_client), GFP_KERNEL);
|
|
||||||
if (!client)
|
|
||||||
return ERR_PTR(-ENOMEM);
|
|
||||||
|
|
||||||
mutex_lock(&phandle->phandle_lock);
|
|
||||||
strlcpy(client->name, client_name, MAX_CLIENT_NAME_LEN);
|
|
||||||
client->usecase_ndx = VOTE_INDEX_DISABLE;
|
|
||||||
client->id = id;
|
|
||||||
client->active = true;
|
|
||||||
pr_debug("client %s created:%pK id :%d\n", client_name,
|
|
||||||
client, id);
|
|
||||||
id++;
|
|
||||||
list_add(&client->list, &phandle->power_client_clist);
|
|
||||||
mutex_unlock(&phandle->phandle_lock);
|
|
||||||
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sde_power_client_destroy(struct sde_power_handle *phandle,
|
|
||||||
struct sde_power_client *client)
|
|
||||||
{
|
|
||||||
if (!client || !phandle) {
|
|
||||||
pr_err("reg bus vote: invalid client handle\n");
|
|
||||||
} else if (!client->active) {
|
|
||||||
pr_err("sde power deinit already done\n");
|
|
||||||
kfree(client);
|
|
||||||
} else {
|
|
||||||
pr_debug("bus vote client %s destroyed:%pK id:%u\n",
|
|
||||||
client->name, client, client->id);
|
|
||||||
mutex_lock(&phandle->phandle_lock);
|
|
||||||
list_del_init(&client->list);
|
|
||||||
mutex_unlock(&phandle->phandle_lock);
|
|
||||||
kfree(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sde_power_parse_dt_supply(struct platform_device *pdev,
|
static int sde_power_parse_dt_supply(struct platform_device *pdev,
|
||||||
struct dss_module_power *mp)
|
struct dss_module_power *mp)
|
||||||
{
|
{
|
||||||
@@ -330,8 +283,7 @@ clk_err:
|
|||||||
|
|
||||||
static int _sde_power_data_bus_set_quota(
|
static int _sde_power_data_bus_set_quota(
|
||||||
struct sde_power_data_bus_handle *pdbus,
|
struct sde_power_data_bus_handle *pdbus,
|
||||||
u64 ab_quota_rt, u64 ab_quota_nrt,
|
u64 in_ab_quota, u64 in_ib_quota)
|
||||||
u64 ib_quota_rt, u64 ib_quota_nrt)
|
|
||||||
{
|
{
|
||||||
int new_uc_idx;
|
int new_uc_idx;
|
||||||
u64 ab_quota[MAX_AXI_PORT_COUNT] = {0, 0};
|
u64 ab_quota[MAX_AXI_PORT_COUNT] = {0, 0};
|
||||||
@@ -343,42 +295,14 @@ static int _sde_power_data_bus_set_quota(
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdbus->ab_rt = ab_quota_rt;
|
if (!in_ab_quota && !in_ib_quota) {
|
||||||
pdbus->ib_rt = ib_quota_rt;
|
|
||||||
pdbus->ab_nrt = ab_quota_nrt;
|
|
||||||
pdbus->ib_nrt = ib_quota_nrt;
|
|
||||||
|
|
||||||
if (pdbus->enable) {
|
|
||||||
ab_quota_rt = max_t(u64, ab_quota_rt,
|
|
||||||
SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA);
|
|
||||||
ib_quota_rt = max_t(u64, ib_quota_rt,
|
|
||||||
SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
|
|
||||||
ab_quota_nrt = max_t(u64, ab_quota_nrt,
|
|
||||||
SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA);
|
|
||||||
ib_quota_nrt = max_t(u64, ib_quota_nrt,
|
|
||||||
SDE_POWER_HANDLE_ENABLE_NRT_BUS_IB_QUOTA);
|
|
||||||
} else {
|
|
||||||
ab_quota_rt = min_t(u64, ab_quota_rt,
|
|
||||||
SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA);
|
|
||||||
ib_quota_rt = min_t(u64, ib_quota_rt,
|
|
||||||
SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA);
|
|
||||||
ab_quota_nrt = min_t(u64, ab_quota_nrt,
|
|
||||||
SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA);
|
|
||||||
ib_quota_nrt = min_t(u64, ib_quota_nrt,
|
|
||||||
SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ab_quota_rt && !ab_quota_nrt && !ib_quota_rt && !ib_quota_nrt) {
|
|
||||||
new_uc_idx = 0;
|
new_uc_idx = 0;
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
struct msm_bus_vectors *vect = NULL;
|
struct msm_bus_vectors *vect = NULL;
|
||||||
struct msm_bus_scale_pdata *bw_table =
|
struct msm_bus_scale_pdata *bw_table =
|
||||||
pdbus->data_bus_scale_table;
|
pdbus->data_bus_scale_table;
|
||||||
u32 nrt_data_paths_cnt = pdbus->nrt_data_paths_cnt;
|
|
||||||
u32 total_data_paths_cnt = pdbus->data_paths_cnt;
|
u32 total_data_paths_cnt = pdbus->data_paths_cnt;
|
||||||
u32 rt_data_paths_cnt = total_data_paths_cnt -
|
|
||||||
nrt_data_paths_cnt;
|
|
||||||
|
|
||||||
if (!bw_table || !total_data_paths_cnt ||
|
if (!bw_table || !total_data_paths_cnt ||
|
||||||
total_data_paths_cnt > MAX_AXI_PORT_COUNT) {
|
total_data_paths_cnt > MAX_AXI_PORT_COUNT) {
|
||||||
@@ -386,37 +310,13 @@ static int _sde_power_data_bus_set_quota(
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nrt_data_paths_cnt) {
|
ab_quota[0] = div_u64(in_ab_quota, total_data_paths_cnt);
|
||||||
|
ib_quota[0] = div_u64(in_ib_quota, total_data_paths_cnt);
|
||||||
ab_quota_rt = div_u64(ab_quota_rt, rt_data_paths_cnt);
|
|
||||||
ab_quota_nrt = div_u64(ab_quota_nrt,
|
|
||||||
nrt_data_paths_cnt);
|
|
||||||
|
|
||||||
ib_quota_rt = div_u64(ib_quota_rt,
|
|
||||||
rt_data_paths_cnt);
|
|
||||||
ib_quota_nrt = div_u64(ib_quota_nrt,
|
|
||||||
nrt_data_paths_cnt);
|
|
||||||
|
|
||||||
for (i = 0; i < total_data_paths_cnt; i++) {
|
|
||||||
if (i < rt_data_paths_cnt) {
|
|
||||||
ab_quota[i] = ab_quota_rt;
|
|
||||||
ib_quota[i] = ib_quota_rt;
|
|
||||||
} else {
|
|
||||||
ab_quota[i] = ab_quota_nrt;
|
|
||||||
ib_quota[i] = ib_quota_nrt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ab_quota[0] = div_u64(ab_quota_rt + ab_quota_nrt,
|
|
||||||
total_data_paths_cnt);
|
|
||||||
ib_quota[0] = div_u64(ib_quota_rt + ib_quota_nrt,
|
|
||||||
total_data_paths_cnt);
|
|
||||||
|
|
||||||
for (i = 1; i < total_data_paths_cnt; i++) {
|
for (i = 1; i < total_data_paths_cnt; i++) {
|
||||||
ab_quota[i] = ab_quota[0];
|
ab_quota[i] = ab_quota[0];
|
||||||
ib_quota[i] = ib_quota[0];
|
ib_quota[i] = ib_quota[0];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
new_uc_idx = (pdbus->curr_bw_uc_idx %
|
new_uc_idx = (pdbus->curr_bw_uc_idx %
|
||||||
(bw_table->num_usecases - 1)) + 1;
|
(bw_table->num_usecases - 1)) + 1;
|
||||||
@@ -427,14 +327,12 @@ static int _sde_power_data_bus_set_quota(
|
|||||||
vect->ib = ib_quota[i];
|
vect->ib = ib_quota[i];
|
||||||
|
|
||||||
pr_debug(
|
pr_debug(
|
||||||
"%s uc_idx=%d %s path idx=%d ab=%llu ib=%llu\n",
|
"%s uc_idx=%d idx=%d ab=%llu ib=%llu\n",
|
||||||
bw_table->name,
|
bw_table->name, new_uc_idx, i, vect->ab,
|
||||||
new_uc_idx, (i < rt_data_paths_cnt) ?
|
vect->ib);
|
||||||
"rt" : "nrt", i, vect->ab, vect->ib);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pdbus->curr_bw_uc_idx = new_uc_idx;
|
pdbus->curr_bw_uc_idx = new_uc_idx;
|
||||||
pdbus->ao_bw_uc_idx = new_uc_idx;
|
|
||||||
|
|
||||||
SDE_ATRACE_BEGIN("msm_bus_scale_req");
|
SDE_ATRACE_BEGIN("msm_bus_scale_req");
|
||||||
rc = msm_bus_scale_client_update_request(pdbus->data_bus_hdl,
|
rc = msm_bus_scale_client_update_request(pdbus->data_bus_hdl,
|
||||||
@@ -445,46 +343,22 @@ static int _sde_power_data_bus_set_quota(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int sde_power_data_bus_set_quota(struct sde_power_handle *phandle,
|
int sde_power_data_bus_set_quota(struct sde_power_handle *phandle,
|
||||||
struct sde_power_client *pclient,
|
u32 bus_id, u64 ab_quota, u64 ib_quota)
|
||||||
int bus_client, u32 bus_id,
|
|
||||||
u64 ab_quota, u64 ib_quota)
|
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int i;
|
|
||||||
u64 total_ab_rt = 0, total_ib_rt = 0;
|
|
||||||
u64 total_ab_nrt = 0, total_ib_nrt = 0;
|
|
||||||
struct sde_power_client *client;
|
|
||||||
|
|
||||||
if (!phandle || !pclient ||
|
if (!phandle || bus_id >= SDE_POWER_HANDLE_DBUS_ID_MAX) {
|
||||||
bus_client >= SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX ||
|
|
||||||
bus_id >= SDE_POWER_HANDLE_DBUS_ID_MAX) {
|
|
||||||
pr_err("invalid parameters\n");
|
pr_err("invalid parameters\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_lock(&phandle->phandle_lock);
|
mutex_lock(&phandle->phandle_lock);
|
||||||
|
|
||||||
pclient->ab[bus_client] = ab_quota;
|
trace_sde_perf_update_bus(bus_id, ab_quota, ib_quota);
|
||||||
pclient->ib[bus_client] = ib_quota;
|
|
||||||
trace_sde_perf_update_bus(bus_client, bus_id, ab_quota, ib_quota);
|
|
||||||
|
|
||||||
list_for_each_entry(client, &phandle->power_client_clist, list) {
|
|
||||||
for (i = 0; i < SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX; i++) {
|
|
||||||
if (i == SDE_POWER_HANDLE_DATA_BUS_CLIENT_NRT) {
|
|
||||||
total_ab_nrt += client->ab[i];
|
|
||||||
total_ib_nrt += client->ib[i];
|
|
||||||
} else {
|
|
||||||
total_ab_rt += client->ab[i];
|
|
||||||
total_ib_rt = max(total_ib_rt, client->ib[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (phandle->data_bus_handle[bus_id].data_bus_hdl)
|
if (phandle->data_bus_handle[bus_id].data_bus_hdl)
|
||||||
rc = _sde_power_data_bus_set_quota(
|
rc = _sde_power_data_bus_set_quota(
|
||||||
&phandle->data_bus_handle[bus_id],
|
&phandle->data_bus_handle[bus_id], ab_quota, ib_quota);
|
||||||
total_ab_rt, total_ab_nrt,
|
|
||||||
total_ib_rt, total_ib_nrt);
|
|
||||||
|
|
||||||
mutex_unlock(&phandle->phandle_lock);
|
mutex_unlock(&phandle->phandle_lock);
|
||||||
|
|
||||||
@@ -507,35 +381,18 @@ static int sde_power_data_bus_parse(struct platform_device *pdev,
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
int paths;
|
int paths;
|
||||||
|
|
||||||
pdbus->bus_channels = 1;
|
|
||||||
rc = of_property_read_u32(pdev->dev.of_node,
|
|
||||||
"qcom,sde-dram-channels", &pdbus->bus_channels);
|
|
||||||
if (rc) {
|
|
||||||
pr_debug("number of channels property not specified\n");
|
|
||||||
rc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
pdbus->nrt_data_paths_cnt = 0;
|
|
||||||
rc = of_property_read_u32(pdev->dev.of_node,
|
|
||||||
"qcom,sde-num-nrt-paths",
|
|
||||||
&pdbus->nrt_data_paths_cnt);
|
|
||||||
if (rc) {
|
|
||||||
pr_debug("number of axi port property not specified\n");
|
|
||||||
rc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = of_get_child_by_name(pdev->dev.of_node, name);
|
node = of_get_child_by_name(pdev->dev.of_node, name);
|
||||||
if (node) {
|
if (!node)
|
||||||
rc = of_property_read_u32(node,
|
goto end;
|
||||||
"qcom,msm-bus,num-paths", &paths);
|
|
||||||
|
rc = of_property_read_u32(node, "qcom,msm-bus,num-paths", &paths);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("Error. qcom,msm-bus,num-paths not found\n");
|
pr_err("Error. qcom,msm-bus,num-paths not found\n");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
pdbus->data_paths_cnt = paths;
|
pdbus->data_paths_cnt = paths;
|
||||||
|
|
||||||
pdbus->data_bus_scale_table =
|
pdbus->data_bus_scale_table = msm_bus_pdata_from_node(pdev, node);
|
||||||
msm_bus_pdata_from_node(pdev, node);
|
|
||||||
if (IS_ERR_OR_NULL(pdbus->data_bus_scale_table)) {
|
if (IS_ERR_OR_NULL(pdbus->data_bus_scale_table)) {
|
||||||
pr_err("reg bus handle parsing failed\n");
|
pr_err("reg bus handle parsing failed\n");
|
||||||
rc = PTR_ERR(pdbus->data_bus_scale_table);
|
rc = PTR_ERR(pdbus->data_bus_scale_table);
|
||||||
@@ -550,9 +407,7 @@ static int sde_power_data_bus_parse(struct platform_device *pdev,
|
|||||||
rc = -EINVAL;
|
rc = -EINVAL;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
pr_debug("register %s data_bus_hdl=%x\n", name,
|
pr_debug("register %s data_bus_hdl=%x\n", name, pdbus->data_bus_hdl);
|
||||||
pdbus->data_bus_hdl);
|
|
||||||
}
|
|
||||||
|
|
||||||
end:
|
end:
|
||||||
return rc;
|
return rc;
|
||||||
@@ -595,41 +450,6 @@ static void sde_power_reg_bus_unregister(u32 reg_bus_hdl)
|
|||||||
msm_bus_scale_unregister_client(reg_bus_hdl);
|
msm_bus_scale_unregister_client(reg_bus_hdl);
|
||||||
}
|
}
|
||||||
|
|
||||||
int sde_power_data_bus_state_update(struct sde_power_handle *phandle,
|
|
||||||
bool enable)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!phandle) {
|
|
||||||
pr_err("invalid param\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = SDE_POWER_HANDLE_DBUS_ID_MNOC;
|
|
||||||
i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
|
||||||
phandle->data_bus_handle[i].enable = enable;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sde_power_data_bus_update(struct sde_power_data_bus_handle *pdbus,
|
|
||||||
bool enable)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
pdbus->enable = enable;
|
|
||||||
|
|
||||||
if (pdbus->data_bus_hdl)
|
|
||||||
rc = _sde_power_data_bus_set_quota(pdbus, pdbus->ab_rt,
|
|
||||||
pdbus->ab_nrt, pdbus->ib_rt, pdbus->ib_nrt);
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
pr_err("failed to set data bus vote rc=%d enable:%d\n",
|
|
||||||
rc, enable);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int sde_power_reg_bus_update(u32 reg_bus_hdl, u32 usecase_ndx)
|
static int sde_power_reg_bus_update(u32 reg_bus_hdl, u32 usecase_ndx)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -647,6 +467,13 @@ static int sde_power_reg_bus_update(u32 reg_bus_hdl, u32 usecase_ndx)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
static int _sde_power_data_bus_set_quota(
|
||||||
|
struct sde_power_data_bus_handle *pdbus,
|
||||||
|
u64 in_ab_quota, u64 in_ib_quota)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int sde_power_data_bus_parse(struct platform_device *pdev,
|
static int sde_power_data_bus_parse(struct platform_device *pdev,
|
||||||
struct sde_power_data_bus_handle *pdbus, const char *name)
|
struct sde_power_data_bus_handle *pdbus, const char *name)
|
||||||
{
|
{
|
||||||
@@ -659,9 +486,7 @@ static void sde_power_data_bus_unregister(
|
|||||||
}
|
}
|
||||||
|
|
||||||
int sde_power_data_bus_set_quota(struct sde_power_handle *phandle,
|
int sde_power_data_bus_set_quota(struct sde_power_handle *phandle,
|
||||||
struct sde_power_client *pclient,
|
u32 bus_id, u64 ab_quota, u64 ib_quota)
|
||||||
int bus_client, u32 bus_id,
|
|
||||||
u64 ab_quota, u64 ib_quota)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -681,12 +506,6 @@ static int sde_power_reg_bus_update(u32 reg_bus_hdl, u32 usecase_ndx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sde_power_data_bus_update(struct sde_power_data_bus_handle *pdbus,
|
|
||||||
bool enable)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sde_power_data_bus_state_update(struct sde_power_handle *phandle,
|
int sde_power_data_bus_state_update(struct sde_power_handle *phandle,
|
||||||
bool enable)
|
bool enable)
|
||||||
{
|
{
|
||||||
@@ -763,7 +582,6 @@ int sde_power_resource_init(struct platform_device *pdev,
|
|||||||
else
|
else
|
||||||
pr_debug("cx ipeak client parse failed\n");
|
pr_debug("cx ipeak client parse failed\n");
|
||||||
|
|
||||||
INIT_LIST_HEAD(&phandle->power_client_clist);
|
|
||||||
INIT_LIST_HEAD(&phandle->event_list);
|
INIT_LIST_HEAD(&phandle->event_list);
|
||||||
|
|
||||||
phandle->rsc_client = NULL;
|
phandle->rsc_client = NULL;
|
||||||
@@ -797,7 +615,6 @@ void sde_power_resource_deinit(struct platform_device *pdev,
|
|||||||
struct sde_power_handle *phandle)
|
struct sde_power_handle *phandle)
|
||||||
{
|
{
|
||||||
struct dss_module_power *mp;
|
struct dss_module_power *mp;
|
||||||
struct sde_power_client *curr_client, *next_client;
|
|
||||||
struct sde_power_event *curr_event, *next_event;
|
struct sde_power_event *curr_event, *next_event;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -808,15 +625,6 @@ void sde_power_resource_deinit(struct platform_device *pdev,
|
|||||||
mp = &phandle->mp;
|
mp = &phandle->mp;
|
||||||
|
|
||||||
mutex_lock(&phandle->phandle_lock);
|
mutex_lock(&phandle->phandle_lock);
|
||||||
list_for_each_entry_safe(curr_client, next_client,
|
|
||||||
&phandle->power_client_clist, list) {
|
|
||||||
pr_err("cliend:%s-%d still registered with refcount:%d\n",
|
|
||||||
curr_client->name, curr_client->id,
|
|
||||||
curr_client->refcount);
|
|
||||||
curr_client->active = false;
|
|
||||||
list_del(&curr_client->list);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry_safe(curr_event, next_event,
|
list_for_each_entry_safe(curr_event, next_event,
|
||||||
&phandle->event_list, list) {
|
&phandle->event_list, list) {
|
||||||
pr_err("event:%d, client:%s still registered\n",
|
pr_err("event:%d, client:%s still registered\n",
|
||||||
@@ -852,47 +660,22 @@ void sde_power_resource_deinit(struct platform_device *pdev,
|
|||||||
sde_rsc_client_destroy(phandle->rsc_client);
|
sde_rsc_client_destroy(phandle->rsc_client);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int sde_power_scale_reg_bus(struct sde_power_handle *phandle,
|
int sde_power_scale_reg_bus(struct sde_power_handle *phandle,
|
||||||
struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock)
|
u32 usecase_ndx, bool skip_lock)
|
||||||
{
|
{
|
||||||
struct sde_power_client *client;
|
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
u32 max_usecase_ndx = VOTE_INDEX_DISABLE;
|
|
||||||
|
|
||||||
if (!skip_lock) {
|
if (!skip_lock)
|
||||||
mutex_lock(&phandle->phandle_lock);
|
mutex_lock(&phandle->phandle_lock);
|
||||||
|
|
||||||
if (WARN_ON(pclient->refcount == 0)) {
|
pr_debug("%pS: requested:%d\n",
|
||||||
/*
|
__builtin_return_address(0), usecase_ndx);
|
||||||
* This is not expected, clients calling without skip
|
|
||||||
* lock are outside the power resource enable, which
|
|
||||||
* means that they should have enabled the power
|
|
||||||
* resource before trying to scale.
|
|
||||||
*/
|
|
||||||
rc = -EINVAL;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%pS: current idx:%d requested:%d client:%d\n",
|
|
||||||
__builtin_return_address(0), pclient->usecase_ndx,
|
|
||||||
usecase_ndx, pclient->id);
|
|
||||||
|
|
||||||
pclient->usecase_ndx = usecase_ndx;
|
|
||||||
|
|
||||||
list_for_each_entry(client, &phandle->power_client_clist, list) {
|
|
||||||
if (client->usecase_ndx < VOTE_INDEX_MAX &&
|
|
||||||
client->usecase_ndx > max_usecase_ndx)
|
|
||||||
max_usecase_ndx = client->usecase_ndx;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = sde_power_reg_bus_update(phandle->reg_bus_hdl,
|
rc = sde_power_reg_bus_update(phandle->reg_bus_hdl,
|
||||||
max_usecase_ndx);
|
usecase_ndx);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_err("failed to set reg bus vote rc=%d\n", rc);
|
pr_err("failed to set reg bus vote rc=%d\n", rc);
|
||||||
|
|
||||||
exit:
|
|
||||||
if (!skip_lock)
|
if (!skip_lock)
|
||||||
mutex_unlock(&phandle->phandle_lock);
|
mutex_unlock(&phandle->phandle_lock);
|
||||||
|
|
||||||
@@ -914,16 +697,12 @@ static inline bool _resource_changed(u32 current_usecase_ndx,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sde_power_resource_enable(struct sde_power_handle *phandle,
|
int sde_power_resource_enable(struct sde_power_handle *phandle, bool enable)
|
||||||
struct sde_power_client *pclient, bool enable)
|
|
||||||
{
|
{
|
||||||
int rc = 0, i;
|
int rc = 0, i = 0;
|
||||||
bool changed = false;
|
|
||||||
u32 max_usecase_ndx = VOTE_INDEX_DISABLE, prev_usecase_ndx;
|
|
||||||
struct sde_power_client *client;
|
|
||||||
struct dss_module_power *mp;
|
struct dss_module_power *mp;
|
||||||
|
|
||||||
if (!phandle || !pclient) {
|
if (!phandle) {
|
||||||
pr_err("invalid input argument\n");
|
pr_err("invalid input argument\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
@@ -931,42 +710,8 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
|
|||||||
mp = &phandle->mp;
|
mp = &phandle->mp;
|
||||||
|
|
||||||
mutex_lock(&phandle->phandle_lock);
|
mutex_lock(&phandle->phandle_lock);
|
||||||
if (enable)
|
|
||||||
pclient->refcount++;
|
|
||||||
else if (pclient->refcount)
|
|
||||||
pclient->refcount--;
|
|
||||||
|
|
||||||
if (pclient->refcount)
|
pr_debug("enable:%d\n", enable);
|
||||||
pclient->usecase_ndx = VOTE_INDEX_LOW;
|
|
||||||
else
|
|
||||||
pclient->usecase_ndx = VOTE_INDEX_DISABLE;
|
|
||||||
|
|
||||||
list_for_each_entry(client, &phandle->power_client_clist, list) {
|
|
||||||
if (client->usecase_ndx < VOTE_INDEX_MAX &&
|
|
||||||
client->usecase_ndx > max_usecase_ndx)
|
|
||||||
max_usecase_ndx = client->usecase_ndx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if we need to enable/disable the power resource, we won't
|
|
||||||
* only-scale up/down the AHB vote in this API; if a client wants to
|
|
||||||
* bump up the AHB clock above the LOW (default) level, it needs to
|
|
||||||
* call 'sde_power_scale_reg_bus' with the desired vote after the power
|
|
||||||
* resource was enabled.
|
|
||||||
*/
|
|
||||||
if (_resource_changed(phandle->current_usecase_ndx,
|
|
||||||
max_usecase_ndx)) {
|
|
||||||
changed = true;
|
|
||||||
prev_usecase_ndx = phandle->current_usecase_ndx;
|
|
||||||
phandle->current_usecase_ndx = max_usecase_ndx;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%pS: changed=%d current idx=%d request client %s id:%u enable:%d refcount:%d\n",
|
|
||||||
__builtin_return_address(0), changed, max_usecase_ndx,
|
|
||||||
pclient->name, pclient->id, enable, pclient->refcount);
|
|
||||||
|
|
||||||
if (!changed)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
SDE_ATRACE_BEGIN("sde_power_resource_enable");
|
SDE_ATRACE_BEGIN("sde_power_resource_enable");
|
||||||
|
|
||||||
@@ -977,13 +722,16 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
|
|||||||
sde_power_event_trigger_locked(phandle,
|
sde_power_event_trigger_locked(phandle,
|
||||||
SDE_POWER_EVENT_PRE_ENABLE);
|
SDE_POWER_EVENT_PRE_ENABLE);
|
||||||
|
|
||||||
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++) {
|
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX &&
|
||||||
rc = sde_power_data_bus_update(
|
phandle->data_bus_handle[i].data_bus_hdl; i++) {
|
||||||
&phandle->data_bus_handle[i], enable);
|
rc = _sde_power_data_bus_set_quota(
|
||||||
|
&phandle->data_bus_handle[i],
|
||||||
|
SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA,
|
||||||
|
SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("failed to set data bus vote id=%d rc=%d\n",
|
pr_err("failed to set data bus vote id=%d rc=%d\n",
|
||||||
i, rc);
|
i, rc);
|
||||||
goto data_bus_hdl_err;
|
goto vreg_err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
|
rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
|
||||||
@@ -993,8 +741,7 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
|
|||||||
goto vreg_err;
|
goto vreg_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sde_power_scale_reg_bus(phandle, pclient,
|
rc = sde_power_scale_reg_bus(phandle, VOTE_INDEX_LOW, true);
|
||||||
max_usecase_ndx, true);
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("failed to set reg bus vote rc=%d\n", rc);
|
pr_err("failed to set reg bus vote rc=%d\n", rc);
|
||||||
goto reg_bus_hdl_err;
|
goto reg_bus_hdl_err;
|
||||||
@@ -1025,20 +772,21 @@ int sde_power_resource_enable(struct sde_power_handle *phandle,
|
|||||||
|
|
||||||
msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
|
msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
|
||||||
|
|
||||||
sde_power_scale_reg_bus(phandle, pclient,
|
sde_power_scale_reg_bus(phandle, VOTE_INDEX_DISABLE, true);
|
||||||
max_usecase_ndx, true);
|
|
||||||
|
|
||||||
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable);
|
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, enable);
|
||||||
|
|
||||||
for (i = 0 ; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
for (i = SDE_POWER_HANDLE_DBUS_ID_MAX - 1; i >= 0; i--)
|
||||||
sde_power_data_bus_update(&phandle->data_bus_handle[i],
|
if (phandle->data_bus_handle[i].data_bus_hdl)
|
||||||
enable);
|
_sde_power_data_bus_set_quota(
|
||||||
|
&phandle->data_bus_handle[i],
|
||||||
|
SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA,
|
||||||
|
SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA);
|
||||||
|
|
||||||
sde_power_event_trigger_locked(phandle,
|
sde_power_event_trigger_locked(phandle,
|
||||||
SDE_POWER_EVENT_POST_DISABLE);
|
SDE_POWER_EVENT_POST_DISABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
SDE_EVT32_VERBOSE(enable, SDE_EVTLOG_FUNC_EXIT);
|
SDE_EVT32_VERBOSE(enable, SDE_EVTLOG_FUNC_EXIT);
|
||||||
mutex_unlock(&phandle->phandle_lock);
|
mutex_unlock(&phandle->phandle_lock);
|
||||||
SDE_ATRACE_END("sde_power_resource_enable");
|
SDE_ATRACE_END("sde_power_resource_enable");
|
||||||
@@ -1047,29 +795,20 @@ end:
|
|||||||
clk_err:
|
clk_err:
|
||||||
sde_power_rsc_update(phandle, false);
|
sde_power_rsc_update(phandle, false);
|
||||||
rsc_err:
|
rsc_err:
|
||||||
sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx, true);
|
sde_power_scale_reg_bus(phandle, VOTE_INDEX_DISABLE, true);
|
||||||
reg_bus_hdl_err:
|
reg_bus_hdl_err:
|
||||||
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0);
|
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0);
|
||||||
vreg_err:
|
vreg_err:
|
||||||
for (i = 0 ; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
for (i-- ; i >= 0 && phandle->data_bus_handle[i].data_bus_hdl; i--)
|
||||||
sde_power_data_bus_update(&phandle->data_bus_handle[i], 0);
|
_sde_power_data_bus_set_quota(
|
||||||
data_bus_hdl_err:
|
&phandle->data_bus_handle[i],
|
||||||
phandle->current_usecase_ndx = prev_usecase_ndx;
|
SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA,
|
||||||
|
SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA);
|
||||||
mutex_unlock(&phandle->phandle_lock);
|
mutex_unlock(&phandle->phandle_lock);
|
||||||
SDE_ATRACE_END("sde_power_resource_enable");
|
SDE_ATRACE_END("sde_power_resource_enable");
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sde_power_resource_is_enabled(struct sde_power_handle *phandle)
|
|
||||||
{
|
|
||||||
if (!phandle) {
|
|
||||||
pr_err("invalid input argument\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return phandle->current_usecase_ndx != VOTE_INDEX_DISABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sde_cx_ipeak_vote(struct sde_power_handle *phandle, struct dss_clk *clock,
|
int sde_cx_ipeak_vote(struct sde_power_handle *phandle, struct dss_clk *clock,
|
||||||
u64 requested_clk_rate, u64 prev_clk_rate, bool enable_vote)
|
u64 requested_clk_rate, u64 prev_clk_rate, bool enable_vote)
|
||||||
{
|
{
|
||||||
|
@@ -73,38 +73,11 @@ enum SDE_POWER_HANDLE_DBUS_ID {
|
|||||||
SDE_POWER_HANDLE_DBUS_ID_MAX,
|
SDE_POWER_HANDLE_DBUS_ID_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* struct sde_power_client: stores the power client for sde driver
|
|
||||||
* @name: name of the client
|
|
||||||
* @usecase_ndx: current regs bus vote type
|
|
||||||
* @refcount: current refcount if multiple modules are using same
|
|
||||||
* same client for enable/disable. Power module will
|
|
||||||
* aggregate the refcount and vote accordingly for this
|
|
||||||
* client.
|
|
||||||
* @id: assigned during create. helps for debugging.
|
|
||||||
* @list: list to attach power handle master list
|
|
||||||
* @ab: arbitrated bandwidth for each bus client
|
|
||||||
* @ib: instantaneous bandwidth for each bus client
|
|
||||||
* @active: inidcates the state of sde power handle
|
|
||||||
*/
|
|
||||||
struct sde_power_client {
|
|
||||||
char name[MAX_CLIENT_NAME_LEN];
|
|
||||||
short usecase_ndx;
|
|
||||||
short refcount;
|
|
||||||
u32 id;
|
|
||||||
struct list_head list;
|
|
||||||
u64 ab[SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
|
|
||||||
u64 ib[SDE_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
|
|
||||||
bool active;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct sde_power_data_handle: power handle struct for data bus
|
* struct sde_power_data_handle: power handle struct for data bus
|
||||||
* @data_bus_scale_table: pointer to bus scaling table
|
* @data_bus_scale_table: pointer to bus scaling table
|
||||||
* @data_bus_hdl: current data bus handle
|
* @data_bus_hdl: current data bus handle
|
||||||
* @data_paths_cnt: number of rt data path ports
|
* @data_paths_cnt: number of rt data path ports
|
||||||
* @nrt_data_paths_cnt: number of nrt data path ports
|
|
||||||
* @bus_channels: number of memory bus channels
|
|
||||||
* @curr_bw_uc_idx: current use case index of data bus
|
* @curr_bw_uc_idx: current use case index of data bus
|
||||||
* @ao_bw_uc_idx: active only use case index of data bus
|
* @ao_bw_uc_idx: active only use case index of data bus
|
||||||
* @ab_rt: realtime ab quota
|
* @ab_rt: realtime ab quota
|
||||||
@@ -117,8 +90,6 @@ struct sde_power_data_bus_handle {
|
|||||||
struct msm_bus_scale_pdata *data_bus_scale_table;
|
struct msm_bus_scale_pdata *data_bus_scale_table;
|
||||||
u32 data_bus_hdl;
|
u32 data_bus_hdl;
|
||||||
u32 data_paths_cnt;
|
u32 data_paths_cnt;
|
||||||
u32 nrt_data_paths_cnt;
|
|
||||||
u32 bus_channels;
|
|
||||||
u32 curr_bw_uc_idx;
|
u32 curr_bw_uc_idx;
|
||||||
u32 ao_bw_uc_idx;
|
u32 ao_bw_uc_idx;
|
||||||
u64 ab_rt;
|
u64 ab_rt;
|
||||||
@@ -149,7 +120,6 @@ struct sde_power_event {
|
|||||||
/**
|
/**
|
||||||
* struct sde_power_handle: power handle main struct
|
* struct sde_power_handle: power handle main struct
|
||||||
* @mp: module power for clock and regulator
|
* @mp: module power for clock and regulator
|
||||||
* @client_clist: master list to store all clients
|
|
||||||
* @phandle_lock: lock to synchronize the enable/disable
|
* @phandle_lock: lock to synchronize the enable/disable
|
||||||
* @dev: pointer to device structure
|
* @dev: pointer to device structure
|
||||||
* @usecase_ndx: current usecase index
|
* @usecase_ndx: current usecase index
|
||||||
@@ -162,7 +132,6 @@ struct sde_power_event {
|
|||||||
*/
|
*/
|
||||||
struct sde_power_handle {
|
struct sde_power_handle {
|
||||||
struct dss_module_power mp;
|
struct dss_module_power mp;
|
||||||
struct list_head power_client_clist;
|
|
||||||
struct mutex phandle_lock;
|
struct mutex phandle_lock;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
u32 current_usecase_ndx;
|
u32 current_usecase_ndx;
|
||||||
@@ -195,41 +164,18 @@ int sde_power_resource_init(struct platform_device *pdev,
|
|||||||
void sde_power_resource_deinit(struct platform_device *pdev,
|
void sde_power_resource_deinit(struct platform_device *pdev,
|
||||||
struct sde_power_handle *pdata);
|
struct sde_power_handle *pdata);
|
||||||
|
|
||||||
/**
|
|
||||||
* sde_power_client_create() - create the client on power handle
|
|
||||||
* @pdata: power handle containing the resources
|
|
||||||
* @client_name: new client name for registration
|
|
||||||
*
|
|
||||||
* Return: error code.
|
|
||||||
*/
|
|
||||||
struct sde_power_client *sde_power_client_create(struct sde_power_handle *pdata,
|
|
||||||
char *client_name);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sde_power_client_destroy() - destroy the client on power handle
|
|
||||||
* @pdata: power handle containing the resources
|
|
||||||
* @client_name: new client name for registration
|
|
||||||
*
|
|
||||||
* Return: none
|
|
||||||
*/
|
|
||||||
void sde_power_client_destroy(struct sde_power_handle *phandle,
|
|
||||||
struct sde_power_client *client);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_power_resource_enable() - enable/disable the power resources
|
* sde_power_resource_enable() - enable/disable the power resources
|
||||||
* @pdata: power handle containing the resources
|
* @pdata: power handle containing the resources
|
||||||
* @client: client information to enable/disable its vote
|
|
||||||
* @enable: boolean request for enable/disable
|
* @enable: boolean request for enable/disable
|
||||||
*
|
*
|
||||||
* Return: error code.
|
* Return: error code.
|
||||||
*/
|
*/
|
||||||
int sde_power_resource_enable(struct sde_power_handle *pdata,
|
int sde_power_resource_enable(struct sde_power_handle *pdata, bool enable);
|
||||||
struct sde_power_client *pclient, bool enable);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_power_scale_reg_bus() - Scale the registers bus for the specified client
|
* sde_power_scale_reg_bus() - Scale the registers bus for the specified client
|
||||||
* @phandle: power handle containing the resources
|
* @phandle: power handle containing the resources
|
||||||
* @pclient: client information to scale its vote
|
|
||||||
* @usecase_ndx: new use case to scale the reg bus
|
* @usecase_ndx: new use case to scale the reg bus
|
||||||
* @skip_lock: will skip holding the power rsrc mutex during the call, this is
|
* @skip_lock: will skip holding the power rsrc mutex during the call, this is
|
||||||
* for internal callers that already hold this required lock.
|
* for internal callers that already hold this required lock.
|
||||||
@@ -237,15 +183,7 @@ int sde_power_resource_enable(struct sde_power_handle *pdata,
|
|||||||
* Return: error code.
|
* Return: error code.
|
||||||
*/
|
*/
|
||||||
int sde_power_scale_reg_bus(struct sde_power_handle *phandle,
|
int sde_power_scale_reg_bus(struct sde_power_handle *phandle,
|
||||||
struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock);
|
u32 usecase_ndx, bool skip_lock);
|
||||||
|
|
||||||
/**
|
|
||||||
* sde_power_resource_is_enabled() - return true if power resource is enabled
|
|
||||||
* @pdata: power handle containing the resources
|
|
||||||
*
|
|
||||||
* Return: true if enabled; false otherwise
|
|
||||||
*/
|
|
||||||
int sde_power_resource_is_enabled(struct sde_power_handle *pdata);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_power_data_bus_state_update() - update data bus state
|
* sde_power_data_bus_state_update() - update data bus state
|
||||||
@@ -311,8 +249,6 @@ int sde_power_clk_set_flags(struct sde_power_handle *pdata,
|
|||||||
/**
|
/**
|
||||||
* sde_power_data_bus_set_quota() - set data bus quota for power client
|
* sde_power_data_bus_set_quota() - set data bus quota for power client
|
||||||
* @phandle: power handle containing the resources
|
* @phandle: power handle containing the resources
|
||||||
* @client: client information to set quota
|
|
||||||
* @bus_client: real-time or non-real-time bus client
|
|
||||||
* @bus_id: identifier of data bus, see SDE_POWER_HANDLE_DBUS_ID
|
* @bus_id: identifier of data bus, see SDE_POWER_HANDLE_DBUS_ID
|
||||||
* @ab_quota: arbitrated bus bandwidth
|
* @ab_quota: arbitrated bus bandwidth
|
||||||
* @ib_quota: instantaneous bus bandwidth
|
* @ib_quota: instantaneous bus bandwidth
|
||||||
@@ -320,20 +256,17 @@ int sde_power_clk_set_flags(struct sde_power_handle *pdata,
|
|||||||
* Return: zero if success, or error code otherwise
|
* Return: zero if success, or error code otherwise
|
||||||
*/
|
*/
|
||||||
int sde_power_data_bus_set_quota(struct sde_power_handle *phandle,
|
int sde_power_data_bus_set_quota(struct sde_power_handle *phandle,
|
||||||
struct sde_power_client *pclient,
|
u32 bus_id, u64 ab_quota, u64 ib_quota);
|
||||||
int bus_client, u32 bus_id,
|
|
||||||
u64 ab_quota, u64 ib_quota);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_power_data_bus_bandwidth_ctrl() - control data bus bandwidth enable
|
* sde_power_data_bus_bandwidth_ctrl() - control data bus bandwidth enable
|
||||||
* @phandle: power handle containing the resources
|
* @phandle: power handle containing the resources
|
||||||
* @client: client information to bandwidth control
|
|
||||||
* @enable: true to enable bandwidth for data base
|
* @enable: true to enable bandwidth for data base
|
||||||
*
|
*
|
||||||
* Return: none
|
* Return: none
|
||||||
*/
|
*/
|
||||||
void sde_power_data_bus_bandwidth_ctrl(struct sde_power_handle *phandle,
|
void sde_power_data_bus_bandwidth_ctrl(struct sde_power_handle *phandle,
|
||||||
struct sde_power_client *pclient, int enable);
|
int enable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_power_handle_register_event - register a callback function for an event.
|
* sde_power_handle_register_event - register a callback function for an event.
|
||||||
|
162
msm/sde_rsc.c
162
msm/sde_rsc.c
@@ -15,6 +15,7 @@
|
|||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
|
||||||
#include <soc/qcom/rpmh.h>
|
#include <soc/qcom/rpmh.h>
|
||||||
#include <drm/drmP.h>
|
#include <drm/drmP.h>
|
||||||
@@ -277,64 +278,6 @@ enum sde_rsc_state get_sde_rsc_current_state(int rsc_index)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(get_sde_rsc_current_state);
|
EXPORT_SYMBOL(get_sde_rsc_current_state);
|
||||||
|
|
||||||
static int sde_rsc_clk_enable(struct sde_power_handle *phandle,
|
|
||||||
struct sde_power_client *pclient, bool enable)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
struct dss_module_power *mp;
|
|
||||||
|
|
||||||
if (!phandle || !pclient) {
|
|
||||||
pr_err("invalid input argument\n");
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mp = &phandle->mp;
|
|
||||||
|
|
||||||
if (enable)
|
|
||||||
pclient->refcount++;
|
|
||||||
else if (pclient->refcount)
|
|
||||||
pclient->refcount--;
|
|
||||||
|
|
||||||
if (pclient->refcount)
|
|
||||||
pclient->usecase_ndx = VOTE_INDEX_LOW;
|
|
||||||
else
|
|
||||||
pclient->usecase_ndx = VOTE_INDEX_DISABLE;
|
|
||||||
|
|
||||||
if (phandle->current_usecase_ndx == pclient->usecase_ndx)
|
|
||||||
goto end;
|
|
||||||
|
|
||||||
if (enable) {
|
|
||||||
rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
|
|
||||||
enable);
|
|
||||||
if (rc) {
|
|
||||||
pr_err("failed to enable vregs rc=%d\n", rc);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
|
|
||||||
if (rc) {
|
|
||||||
pr_err("clock enable failed rc:%d\n", rc);
|
|
||||||
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
|
|
||||||
!enable);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msm_dss_enable_clk(mp->clk_config, mp->num_clk, enable);
|
|
||||||
|
|
||||||
rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
|
|
||||||
enable);
|
|
||||||
if (rc) {
|
|
||||||
pr_err("failed to disable vregs rc=%d\n", rc);
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
phandle->current_usecase_ndx = pclient->usecase_ndx;
|
|
||||||
|
|
||||||
end:
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 sde_rsc_timer_calculate(struct sde_rsc_priv *rsc,
|
static u32 sde_rsc_timer_calculate(struct sde_rsc_priv *rsc,
|
||||||
struct sde_rsc_cmd_config *cmd_config, enum sde_rsc_state state)
|
struct sde_rsc_cmd_config *cmd_config, enum sde_rsc_state state)
|
||||||
{
|
{
|
||||||
@@ -484,7 +427,7 @@ static int sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
|
|||||||
*/
|
*/
|
||||||
if (rsc->current_state == SDE_RSC_CMD_STATE) {
|
if (rsc->current_state == SDE_RSC_CMD_STATE) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
if (config && rsc->version < SDE_RSC_REV_3)
|
if (config)
|
||||||
goto vsync_wait;
|
goto vsync_wait;
|
||||||
else
|
else
|
||||||
goto end;
|
goto end;
|
||||||
@@ -504,8 +447,7 @@ static int sde_rsc_switch_to_cmd(struct sde_rsc_priv *rsc,
|
|||||||
|
|
||||||
vsync_wait:
|
vsync_wait:
|
||||||
/* indicate wait for vsync for vid to cmd state switch & cfg update */
|
/* indicate wait for vsync for vid to cmd state switch & cfg update */
|
||||||
if (!rc && (rsc->version < SDE_RSC_REV_3) &&
|
if (!rc && (rsc->current_state == SDE_RSC_VID_STATE ||
|
||||||
(rsc->current_state == SDE_RSC_VID_STATE ||
|
|
||||||
rsc->current_state == SDE_RSC_CMD_STATE)) {
|
rsc->current_state == SDE_RSC_CMD_STATE)) {
|
||||||
/* clear VSYNC timestamp for indication when update completes */
|
/* clear VSYNC timestamp for indication when update completes */
|
||||||
if (rsc->hw_ops.hw_vsync)
|
if (rsc->hw_ops.hw_vsync)
|
||||||
@@ -623,7 +565,7 @@ static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
|
|||||||
*/
|
*/
|
||||||
if (rsc->current_state == SDE_RSC_VID_STATE) {
|
if (rsc->current_state == SDE_RSC_VID_STATE) {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
if (config && rsc->version < SDE_RSC_REV_3)
|
if (config)
|
||||||
goto vsync_wait;
|
goto vsync_wait;
|
||||||
else
|
else
|
||||||
goto end;
|
goto end;
|
||||||
@@ -644,8 +586,7 @@ static int sde_rsc_switch_to_vid(struct sde_rsc_priv *rsc,
|
|||||||
|
|
||||||
vsync_wait:
|
vsync_wait:
|
||||||
/* indicate wait for vsync for vid to cmd state switch & cfg update */
|
/* indicate wait for vsync for vid to cmd state switch & cfg update */
|
||||||
if (!rc && (rsc->version < SDE_RSC_REV_3) &&
|
if (!rc && (rsc->current_state == SDE_RSC_VID_STATE ||
|
||||||
(rsc->current_state == SDE_RSC_VID_STATE ||
|
|
||||||
rsc->current_state == SDE_RSC_CMD_STATE)) {
|
rsc->current_state == SDE_RSC_CMD_STATE)) {
|
||||||
/* clear VSYNC timestamp for indication when update completes */
|
/* clear VSYNC timestamp for indication when update completes */
|
||||||
if (rsc->hw_ops.hw_vsync)
|
if (rsc->hw_ops.hw_vsync)
|
||||||
@@ -879,7 +820,7 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
|
|||||||
caller_client->name, state);
|
caller_client->name, state);
|
||||||
|
|
||||||
if (rsc->current_state == SDE_RSC_IDLE_STATE)
|
if (rsc->current_state == SDE_RSC_IDLE_STATE)
|
||||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
|
pm_runtime_get_sync(rsc->dev);
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case SDE_RSC_IDLE_STATE:
|
case SDE_RSC_IDLE_STATE:
|
||||||
@@ -936,7 +877,7 @@ int sde_rsc_client_state_update(struct sde_rsc_client *caller_client,
|
|||||||
|
|
||||||
clk_disable:
|
clk_disable:
|
||||||
if (rsc->current_state == SDE_RSC_IDLE_STATE)
|
if (rsc->current_state == SDE_RSC_IDLE_STATE)
|
||||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
|
pm_runtime_put_sync(rsc->dev);
|
||||||
end:
|
end:
|
||||||
mutex_unlock(&rsc->client_lock);
|
mutex_unlock(&rsc->client_lock);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1013,8 +954,8 @@ int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client,
|
|||||||
rsc->bw_config.ib_vote[i] = rsc->bw_config.new_ib_vote[i];
|
rsc->bw_config.ib_vote[i] = rsc->bw_config.new_ib_vote[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true);
|
rc = pm_runtime_get_sync(rsc->dev);
|
||||||
if (rc)
|
if (rc < 0)
|
||||||
goto clk_enable_fail;
|
goto clk_enable_fail;
|
||||||
|
|
||||||
if (delta_vote) {
|
if (delta_vote) {
|
||||||
@@ -1031,8 +972,6 @@ int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client,
|
|||||||
rpmh_invalidate(rsc->rpmh_dev);
|
rpmh_invalidate(rsc->rpmh_dev);
|
||||||
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
for (i = 0; i < SDE_POWER_HANDLE_DBUS_ID_MAX; i++)
|
||||||
sde_power_data_bus_set_quota(&rsc->phandle,
|
sde_power_data_bus_set_quota(&rsc->phandle,
|
||||||
rsc->pclient,
|
|
||||||
SDE_POWER_HANDLE_DATA_BUS_CLIENT_RT,
|
|
||||||
i, rsc->bw_config.ab_vote[i],
|
i, rsc->bw_config.ab_vote[i],
|
||||||
rsc->bw_config.ib_vote[i]);
|
rsc->bw_config.ib_vote[i]);
|
||||||
rpmh_flush(rsc->rpmh_dev);
|
rpmh_flush(rsc->rpmh_dev);
|
||||||
@@ -1046,7 +985,7 @@ int sde_rsc_client_trigger_vote(struct sde_rsc_client *caller_client,
|
|||||||
rsc->hw_ops.tcs_use_ok(rsc);
|
rsc->hw_ops.tcs_use_ok(rsc);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
|
pm_runtime_put_sync(rsc->dev);
|
||||||
clk_enable_fail:
|
clk_enable_fail:
|
||||||
mutex_unlock(&rsc->client_lock);
|
mutex_unlock(&rsc->client_lock);
|
||||||
|
|
||||||
@@ -1353,8 +1292,7 @@ static void sde_rsc_deinit(struct platform_device *pdev,
|
|||||||
if (!rsc)
|
if (!rsc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (rsc->pclient)
|
pm_runtime_put_sync(rsc->dev);
|
||||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
|
|
||||||
if (rsc->sw_fs_enabled)
|
if (rsc->sw_fs_enabled)
|
||||||
regulator_disable(rsc->fs);
|
regulator_disable(rsc->fs);
|
||||||
if (rsc->fs)
|
if (rsc->fs)
|
||||||
@@ -1363,14 +1301,64 @@ static void sde_rsc_deinit(struct platform_device *pdev,
|
|||||||
msm_dss_iounmap(&rsc->wrapper_io);
|
msm_dss_iounmap(&rsc->wrapper_io);
|
||||||
if (rsc->drv_io.base)
|
if (rsc->drv_io.base)
|
||||||
msm_dss_iounmap(&rsc->drv_io);
|
msm_dss_iounmap(&rsc->drv_io);
|
||||||
if (rsc->pclient)
|
|
||||||
sde_power_client_destroy(&rsc->phandle, rsc->pclient);
|
|
||||||
|
|
||||||
sde_power_resource_deinit(pdev, &rsc->phandle);
|
sde_power_resource_deinit(pdev, &rsc->phandle);
|
||||||
debugfs_remove_recursive(rsc->debugfs_root);
|
debugfs_remove_recursive(rsc->debugfs_root);
|
||||||
kfree(rsc);
|
kfree(rsc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
|
static int sde_rsc_runtime_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct sde_rsc_priv *rsc = dev_get_drvdata(dev);
|
||||||
|
struct dss_module_power *mp;
|
||||||
|
|
||||||
|
if (!rsc) {
|
||||||
|
pr_err("invalid drv data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp = &rsc->phandle.mp;
|
||||||
|
msm_dss_enable_clk(mp->clk_config, mp->num_clk, false);
|
||||||
|
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sde_rsc_runtime_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct sde_rsc_priv *rsc = dev_get_drvdata(dev);
|
||||||
|
struct dss_module_power *mp;
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!rsc) {
|
||||||
|
pr_err("invalid drv data\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp = &rsc->phandle.mp;
|
||||||
|
rc = msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, true);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("failed to enable vregs rc=%d\n", rc);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("clock enable failed rc:%d\n", rc);
|
||||||
|
msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const struct dev_pm_ops sde_rsc_pm_ops = {
|
||||||
|
SET_RUNTIME_PM_OPS(sde_rsc_runtime_suspend,
|
||||||
|
sde_rsc_runtime_resume, NULL)
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_rsc_bind - bind rsc device with controlling device
|
* sde_rsc_bind - bind rsc device with controlling device
|
||||||
* @dev: Pointer to base of platform device
|
* @dev: Pointer to base of platform device
|
||||||
@@ -1464,6 +1452,7 @@ static int sde_rsc_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, rsc);
|
platform_set_drvdata(pdev, rsc);
|
||||||
|
rsc->dev = &pdev->dev;
|
||||||
of_property_read_u32(pdev->dev.of_node, "qcom,sde-rsc-version",
|
of_property_read_u32(pdev->dev.of_node, "qcom,sde-rsc-version",
|
||||||
&rsc->version);
|
&rsc->version);
|
||||||
|
|
||||||
@@ -1492,20 +1481,6 @@ static int sde_rsc_probe(struct platform_device *pdev)
|
|||||||
goto sde_rsc_fail;
|
goto sde_rsc_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
rsc->pclient = sde_power_client_create(&rsc->phandle, "rsc");
|
|
||||||
if (IS_ERR_OR_NULL(rsc->pclient)) {
|
|
||||||
ret = PTR_ERR(rsc->pclient);
|
|
||||||
rsc->pclient = NULL;
|
|
||||||
pr_err("sde rsc:power client create failed ret:%d\n", ret);
|
|
||||||
goto sde_rsc_fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sde rsc should always vote through enable path, sleep vote is
|
|
||||||
* set to "0" by default.
|
|
||||||
*/
|
|
||||||
sde_power_data_bus_state_update(&rsc->phandle, true);
|
|
||||||
|
|
||||||
rsc->rpmh_dev = rpmh_dev[SDE_RSC_INDEX + counter];
|
rsc->rpmh_dev = rpmh_dev[SDE_RSC_INDEX + counter];
|
||||||
if (IS_ERR_OR_NULL(rsc->rpmh_dev)) {
|
if (IS_ERR_OR_NULL(rsc->rpmh_dev)) {
|
||||||
ret = !rsc->rpmh_dev ? -EINVAL : PTR_ERR(rsc->rpmh_dev);
|
ret = !rsc->rpmh_dev ? -EINVAL : PTR_ERR(rsc->rpmh_dev);
|
||||||
@@ -1550,15 +1525,17 @@ static int sde_rsc_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
rsc->sw_fs_enabled = true;
|
rsc->sw_fs_enabled = true;
|
||||||
|
|
||||||
if (sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, true)) {
|
pm_runtime_enable(rsc->dev);
|
||||||
pr_err("failed to enable sde rsc power resources\n");
|
ret = pm_runtime_get_sync(rsc->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("failed to enable sde rsc power resources rc:%d\n", ret);
|
||||||
goto sde_rsc_fail;
|
goto sde_rsc_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sde_rsc_timer_calculate(rsc, NULL, SDE_RSC_IDLE_STATE))
|
if (sde_rsc_timer_calculate(rsc, NULL, SDE_RSC_IDLE_STATE))
|
||||||
goto sde_rsc_fail;
|
goto sde_rsc_fail;
|
||||||
|
|
||||||
sde_rsc_clk_enable(&rsc->phandle, rsc->pclient, false);
|
pm_runtime_put_sync(rsc->dev);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&rsc->client_list);
|
INIT_LIST_HEAD(&rsc->client_list);
|
||||||
INIT_LIST_HEAD(&rsc->event_list);
|
INIT_LIST_HEAD(&rsc->event_list);
|
||||||
@@ -1636,6 +1613,7 @@ static struct platform_driver sde_rsc_platform_driver = {
|
|||||||
.name = "sde_rsc",
|
.name = "sde_rsc",
|
||||||
.of_match_table = dt_match,
|
.of_match_table = dt_match,
|
||||||
.suppress_bind_attrs = true,
|
.suppress_bind_attrs = true,
|
||||||
|
.pm = &sde_rsc_pm_ops,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -141,7 +141,6 @@ struct sde_rsc_bw_config {
|
|||||||
* struct sde_rsc_priv: sde resource state coordinator(rsc) private handle
|
* struct sde_rsc_priv: sde resource state coordinator(rsc) private handle
|
||||||
* @version: rsc sequence version
|
* @version: rsc sequence version
|
||||||
* @phandle: module power handle for clocks
|
* @phandle: module power handle for clocks
|
||||||
* @pclient: module power client of phandle
|
|
||||||
* @fs: "MDSS GDSC" handle
|
* @fs: "MDSS GDSC" handle
|
||||||
* @sw_fs_enabled: track "MDSS GDSC" sw vote during probe
|
* @sw_fs_enabled: track "MDSS GDSC" sw vote during probe
|
||||||
*
|
*
|
||||||
@@ -179,11 +178,11 @@ struct sde_rsc_bw_config {
|
|||||||
* rsc_vsync_wait: Refcount to indicate if we have to wait for the vsync.
|
* rsc_vsync_wait: Refcount to indicate if we have to wait for the vsync.
|
||||||
* rsc_vsync_waitq: Queue to wait for the vsync.
|
* rsc_vsync_waitq: Queue to wait for the vsync.
|
||||||
* bw_config: check sde_rsc_bw_config structure description.
|
* bw_config: check sde_rsc_bw_config structure description.
|
||||||
|
* dev: rsc device node
|
||||||
*/
|
*/
|
||||||
struct sde_rsc_priv {
|
struct sde_rsc_priv {
|
||||||
u32 version;
|
u32 version;
|
||||||
struct sde_power_handle phandle;
|
struct sde_power_handle phandle;
|
||||||
struct sde_power_client *pclient;
|
|
||||||
struct regulator *fs;
|
struct regulator *fs;
|
||||||
bool sw_fs_enabled;
|
bool sw_fs_enabled;
|
||||||
|
|
||||||
@@ -218,6 +217,7 @@ struct sde_rsc_priv {
|
|||||||
wait_queue_head_t rsc_vsync_waitq;
|
wait_queue_head_t rsc_vsync_waitq;
|
||||||
|
|
||||||
struct sde_rsc_bw_config bw_config;
|
struct sde_rsc_bw_config bw_config;
|
||||||
|
struct device *dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user