On Fri, May 11, 2018 at 08:19:37PM +0530, Rajesh Yadav wrote:
Now, since dpu_power_handle manages only bus scaling and power enable/disable notifications which are restricted to dpu driver, move dpu_power_handle to dpu folder.
Changes in v2:
- resolved conflict in dpu_unbind
- dropped (Reviewed-by: Sean Paul) due to above change
Reviewed-by: Sean Paul seanpaul@chromium.org
Signed-off-by: Rajesh Yadav ryadav@codeaurora.org
drivers/gpu/drm/msm/Makefile | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 5 +- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 7 +- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 1 - drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 39 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 + drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c | 693 +++++++++++++++++++++++ drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h | 288 ++++++++++ drivers/gpu/drm/msm/dpu_power_handle.c | 693 ----------------------- drivers/gpu/drm/msm/dpu_power_handle.h | 288 ---------- drivers/gpu/drm/msm/msm_drv.c | 9 - drivers/gpu/drm/msm/msm_drv.h | 4 - 14 files changed, 1013 insertions(+), 1020 deletions(-) create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h delete mode 100644 drivers/gpu/drm/msm/dpu_power_handle.c delete mode 100644 drivers/gpu/drm/msm/dpu_power_handle.h
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index d9826c1..f578d5a 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -82,10 +82,10 @@ msm-y := \ disp/dpu1/dpu_rm.o \ disp/dpu1/dpu_vbif.o \ disp/dpu1/dpu_mdss.o \
- disp/dpu1/dpu_power_handle.o \ dpu_dbg.o \ dpu_io_util.o \ dpu_dbg_evtlog.o \
- dpu_power_handle.o \ msm_prop.o \ msm_atomic.o \ msm_debugfs.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c index 5c5cc56..33ab2ac 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c @@ -18,7 +18,6 @@ #include <linux/kthread.h>
#include "dpu_core_irq.h" -#include "dpu_power_handle.h"
/**
- dpu_core_irq_callback_handler - dispatch core interrupts
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c index 2cf3fca..d3a1ed9 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c @@ -257,7 +257,6 @@ static void _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, = dpu_crtc_get_client_type(crtc); struct drm_crtc *tmp_crtc; struct dpu_crtc_state *dpu_cstate;
struct msm_drm_private *priv = kms->dev->dev_private;
drm_for_each_crtc(tmp_crtc, crtc->dev) { if (_dpu_core_perf_crtc_is_power_on(tmp_crtc) &&
@@ -287,7 +286,7 @@ static void _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms,
switch (curr_client_type) { case NRT_CLIENT:
dpu_power_data_bus_set_quota(&priv->phandle, kms->core_client,
DPU_DEBUG("client:%s bus_id=%d ab=%llu ib=%llu\n", "nrt",dpu_power_data_bus_set_quota(&kms->phandle, kms->core_client, DPU_POWER_HANDLE_DATA_BUS_CLIENT_NRT, bus_id, bus_ab_quota, bus_ib_quota);
@@ -295,7 +294,7 @@ static void _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms, break;
case RT_CLIENT:
dpu_power_data_bus_set_quota(&priv->phandle, kms->core_client,
DPU_DEBUG("client:%s bus_id=%d ab=%llu ib=%llu\n", "rt",dpu_power_data_bus_set_quota(&kms->phandle, kms->core_client, DPU_POWER_HANDLE_DATA_BUS_CLIENT_RT, bus_id, bus_ab_quota, bus_ib_quota);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c index e2d2e32..99c5e75 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -598,6 +598,7 @@ static void dpu_crtc_destroy(struct drm_crtc *crtc) _dpu_crtc_destroy_dest_scaler(dpu_crtc);
_dpu_crtc_deinit_events(dpu_crtc);
dpu_crtc->phandle = NULL;
drm_crtc_cleanup(crtc); mutex_destroy(&dpu_crtc->crtc_lock);
@@ -2572,7 +2573,7 @@ static void dpu_crtc_disable(struct drm_crtc *crtc) }
if (dpu_crtc->power_event)
dpu_power_handle_unregister_event(&priv->phandle,
dpu_power_handle_unregister_event(dpu_crtc->phandle, dpu_crtc->power_event);
@@ -2643,7 +2644,7 @@ static void dpu_crtc_enable(struct drm_crtc *crtc, mutex_unlock(&dpu_crtc->crtc_lock);
dpu_crtc->power_event = dpu_power_handle_register_event(
&priv->phandle,
DPU_POWER_EVENT_POST_ENABLE | DPU_POWER_EVENT_POST_DISABLE | DPU_POWER_EVENT_PRE_DISABLE, dpu_crtc_handle_power_event, crtc, dpu_crtc->name);dpu_crtc->phandle,
@@ -3938,6 +3939,8 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane) dpu_cp_crtc_init(crtc); dpu_cp_crtc_install_properties(crtc);
- dpu_crtc->phandle = &kms->phandle;
- DPU_DEBUG("%s: successfully initialized crtc\n", dpu_crtc->name); return crtc;
} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h index 9304058..671d909 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -184,6 +184,7 @@ struct dpu_crtc_event {
- @misr_enable : boolean entry indicates misr enable/disable status.
- @misr_frame_count : misr frame count provided by client
- @misr_data : store misr data before turning off the clocks.
- @phandle: Pointer to power handler
- @power_event : registered power event handle
- @cur_perf : current performance committed to clock/bandwidth driver
- @rp_lock : serialization lock for resource pool
@@ -240,6 +241,7 @@ struct dpu_crtc { u32 misr_frame_count; u32 misr_data[CRTC_DUAL_MIXERS];
struct dpu_power_handle *phandle; struct dpu_power_event *power_event;
struct dpu_core_perf_params cur_perf;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 298a6ef..11ae6cc 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -31,7 +31,6 @@ #include "dpu_hw_ctl.h" #include "dpu_formats.h" #include "dpu_encoder_phys.h" -#include "dpu_power_handle.h" #include "dpu_crtc.h" #include "dpu_trace.h" #include "dpu_core_irq.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index 9c3b220..0598cfb 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -1017,24 +1017,19 @@ static long dpu_kms_round_pixclk(struct msm_kms *kms, unsigned long rate, static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) { struct drm_device *dev;
struct msm_drm_private *priv; int i;
dev = dpu_kms->dev; if (!dev) return;
priv = dev->dev_private;
if (!priv)
return;
if (dpu_kms->hw_intr) dpu_hw_intr_destroy(dpu_kms->hw_intr); dpu_kms->hw_intr = NULL;
if (dpu_kms->power_event) dpu_power_handle_unregister_event(
&priv->phandle, dpu_kms->power_event);
&dpu_kms->phandle, dpu_kms->power_event);
/* safe to call these more than once during shutdown */ _dpu_debugfs_destroy(dpu_kms);
@@ -1067,7 +1062,8 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms) dpu_kms->catalog = NULL;
if (dpu_kms->core_client)
dpu_power_client_destroy(&priv->phandle, dpu_kms->core_client);
dpu_power_client_destroy(&dpu_kms->phandle,
dpu_kms->core_client);
dpu_kms->core_client = NULL;
if (dpu_kms->vbif[VBIF_NRT])
@@ -1624,7 +1620,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms) } #endif
- dpu_kms->core_client = dpu_power_client_create(&priv->phandle, "core");
- dpu_kms->core_client = dpu_power_client_create(&dpu_kms->phandle,
if (IS_ERR_OR_NULL(dpu_kms->core_client)) { rc = PTR_ERR(dpu_kms->core_client); if (!dpu_kms->core_client)"core");
@@ -1721,7 +1718,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms) #endif
rc = dpu_core_perf_init(&dpu_kms->perf, dev, dpu_kms->catalog,
&priv->phandle, _dpu_kms_get_clk(dpu_kms, "core_clk"));
&dpu_kms->phandle,
if (rc) { DPU_ERROR("failed to init perf %d\n", rc); goto perf_err;_dpu_kms_get_clk(dpu_kms, "core_clk"));
@@ -1765,7 +1763,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms) * Handle (re)initializations during power enable */ dpu_kms_handle_power_event(DPU_POWER_EVENT_POST_ENABLE, dpu_kms);
- dpu_kms->power_event = dpu_power_handle_register_event(&priv->phandle,
- dpu_kms->power_event = dpu_power_handle_register_event(
&dpu_kms->phandle, DPU_POWER_EVENT_POST_ENABLE, dpu_kms_handle_power_event, dpu_kms, "kms");
@@ -1841,6 +1840,12 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) goto clk_rate_error; }
ret = dpu_power_resource_init(pdev, &dpu_kms->phandle);
if (ret) {
pr_err("dpu power resource init failed\n");
goto power_init_fail;
}
platform_set_drvdata(pdev, dpu_kms);
msm_kms_init(&dpu_kms->base, &kms_funcs);
@@ -1853,6 +1858,7 @@ static int dpu_bind(struct device *dev, struct device *master, void *data) priv->kms = &dpu_kms->base; return ret;
+power_init_fail: clk_rate_error: msm_dss_put_clk(mp->clk_config, mp->num_clk); clk_get_error: @@ -1867,6 +1873,7 @@ static void dpu_unbind(struct device *dev, struct device *master, void *data) struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct dss_module_power *mp = &dpu_kms->mp;
- dpu_power_resource_deinit(pdev, &dpu_kms->phandle); msm_dss_put_clk(mp->clk_config, mp->num_clk); devm_kfree(&pdev->dev, mp->clk_config); mp->num_clk = 0;
@@ -1897,7 +1904,6 @@ static int dpu_runtime_suspend(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct drm_device *ddev;
struct msm_drm_private *priv; struct dss_module_power *mp = &dpu_kms->mp;
ddev = dpu_kms->dev;
@@ -1905,10 +1911,9 @@ static int dpu_runtime_suspend(struct device *dev) DPU_ERROR("invalid drm_device\n"); goto exit; }
priv = ddev->dev_private;
rc = dpu_power_resource_enable(&priv->phandle,
dpu_kms->core_client, false);
- rc = dpu_power_resource_enable(&dpu_kms->phandle,
if (rc) DPU_ERROR("resource disable failed: %d\n", rc);dpu_kms->core_client, false);
@@ -1926,7 +1931,6 @@ static int dpu_runtime_resume(struct device *dev) struct platform_device *pdev = to_platform_device(dev); struct dpu_kms *dpu_kms = platform_get_drvdata(pdev); struct drm_device *ddev;
struct msm_drm_private *priv; struct dss_module_power *mp = &dpu_kms->mp;
ddev = dpu_kms->dev;
@@ -1934,7 +1938,6 @@ static int dpu_runtime_resume(struct device *dev) DPU_ERROR("invalid drm_device\n"); goto exit; }
priv = ddev->dev_private;
rc = msm_dss_enable_clk(mp->clk_config, mp->num_clk, true); if (rc) {
@@ -1942,8 +1945,8 @@ static int dpu_runtime_resume(struct device *dev) goto exit; }
- rc = dpu_power_resource_enable(&priv->phandle, dpu_kms->core_client,
true);
- rc = dpu_power_resource_enable(&dpu_kms->phandle,
if (rc) DPU_ERROR("resource enable failed: %d\n", rc);dpu_kms->core_client, true);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h index a8255fe..c48ed4e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h @@ -164,6 +164,7 @@ struct dpu_kms { struct dpu_mdss_cfg *catalog;
struct msm_gem_address_space *aspace[MSM_SMMU_DOMAIN_MAX];
- struct dpu_power_handle phandle; struct dpu_power_client *core_client;
#ifdef CONFIG_ION struct ion_client *iclient; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c new file mode 100644 index 0000000..77be106 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c @@ -0,0 +1,693 @@ +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 and
- only version 2 as published by the Free Software Foundation.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- */
+#define pr_fmt(fmt) "[drm:%s:%d]: " fmt, __func__, __LINE__
+#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/string.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/of_platform.h> +#ifdef CONFIG_QCOM_BUS_SCALING +#include <linux/msm-bus.h> +#include <linux/msm-bus-board.h> +#endif +#include <linux/dpu_io_util.h>
+#include "dpu_power_handle.h" +#include "dpu_trace.h"
+static const char *data_bus_name[DPU_POWER_HANDLE_DBUS_ID_MAX] = {
- [DPU_POWER_HANDLE_DBUS_ID_MNOC] = "qcom,dpu-data-bus",
- [DPU_POWER_HANDLE_DBUS_ID_LLCC] = "qcom,dpu-llcc-bus",
- [DPU_POWER_HANDLE_DBUS_ID_EBI] = "qcom,dpu-ebi-bus",
+};
+const char *dpu_power_handle_get_dbus_name(u32 bus_id) +{
- if (bus_id < DPU_POWER_HANDLE_DBUS_ID_MAX)
return data_bus_name[bus_id];
- return NULL;
+}
+static void dpu_power_event_trigger_locked(struct dpu_power_handle *phandle,
u32 event_type)
+{
- struct dpu_power_event *event;
- list_for_each_entry(event, &phandle->event_list, list) {
if (event->event_type & event_type)
event->cb_fnc(event_type, event->usr);
- }
+}
+struct dpu_power_client *dpu_power_client_create(
- struct dpu_power_handle *phandle, char *client_name)
+{
- struct dpu_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 dpu_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 dpu_power_client_destroy(struct dpu_power_handle *phandle,
- struct dpu_power_client *client)
+{
- if (!client || !phandle) {
pr_err("reg bus vote: invalid client handle\n");
- } else if (!client->active) {
pr_err("dpu 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);
- }
+}
+#ifdef CONFIG_QCOM_BUS_SCALING
+#define MAX_AXI_PORT_COUNT 3
+static int _dpu_power_data_bus_set_quota(
struct dpu_power_data_bus_handle *pdbus,
u64 ab_quota_rt, u64 ab_quota_nrt,
u64 ib_quota_rt, u64 ib_quota_nrt)
+{
- int new_uc_idx;
- u64 ab_quota[MAX_AXI_PORT_COUNT] = {0, 0};
- u64 ib_quota[MAX_AXI_PORT_COUNT] = {0, 0};
- int rc;
- if (pdbus->data_bus_hdl < 1) {
pr_err("invalid bus handle %d\n", pdbus->data_bus_hdl);
return -EINVAL;
- }
- pdbus->ab_rt = ab_quota_rt;
- 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,
DPU_POWER_HANDLE_ENABLE_BUS_AB_QUOTA);
ib_quota_rt = max_t(u64, ib_quota_rt,
DPU_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
ab_quota_nrt = max_t(u64, ab_quota_nrt,
DPU_POWER_HANDLE_ENABLE_BUS_AB_QUOTA);
ib_quota_nrt = max_t(u64, ib_quota_nrt,
DPU_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
- } else {
ab_quota_rt = min_t(u64, ab_quota_rt,
DPU_POWER_HANDLE_DISABLE_BUS_AB_QUOTA);
ib_quota_rt = min_t(u64, ib_quota_rt,
DPU_POWER_HANDLE_DISABLE_BUS_IB_QUOTA);
ab_quota_nrt = min_t(u64, ab_quota_nrt,
DPU_POWER_HANDLE_DISABLE_BUS_AB_QUOTA);
ib_quota_nrt = min_t(u64, ib_quota_nrt,
DPU_POWER_HANDLE_DISABLE_BUS_IB_QUOTA);
- }
- if (!ab_quota_rt && !ab_quota_nrt && !ib_quota_rt && !ib_quota_nrt) {
new_uc_idx = 0;
- } else {
int i;
struct msm_bus_vectors *vect = NULL;
struct msm_bus_scale_pdata *bw_table =
pdbus->data_bus_scale_table;
u32 nrt_axi_port_cnt = pdbus->nrt_axi_port_cnt;
u32 total_axi_port_cnt = pdbus->axi_port_cnt;
u32 rt_axi_port_cnt = total_axi_port_cnt - nrt_axi_port_cnt;
if (!bw_table || !total_axi_port_cnt ||
total_axi_port_cnt > MAX_AXI_PORT_COUNT) {
pr_err("invalid input\n");
return -EINVAL;
}
if (pdbus->bus_channels) {
ib_quota_rt = div_u64(ib_quota_rt,
pdbus->bus_channels);
ib_quota_nrt = div_u64(ib_quota_nrt,
pdbus->bus_channels);
}
if (nrt_axi_port_cnt) {
ab_quota_rt = div_u64(ab_quota_rt, rt_axi_port_cnt);
ab_quota_nrt = div_u64(ab_quota_nrt, nrt_axi_port_cnt);
for (i = 0; i < total_axi_port_cnt; i++) {
if (i < rt_axi_port_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_axi_port_cnt);
ib_quota[0] = ib_quota_rt + ib_quota_nrt;
for (i = 1; i < total_axi_port_cnt; i++) {
ab_quota[i] = ab_quota[0];
ib_quota[i] = ib_quota[0];
}
}
new_uc_idx = (pdbus->curr_bw_uc_idx %
(bw_table->num_usecases - 1)) + 1;
for (i = 0; i < total_axi_port_cnt; i++) {
vect = &bw_table->usecase[new_uc_idx].vectors[i];
vect->ab = ab_quota[i];
vect->ib = ib_quota[i];
pr_debug(
"%s uc_idx=%d %s path idx=%d ab=%llu ib=%llu\n",
bw_table->name,
new_uc_idx, (i < rt_axi_port_cnt) ? "rt" : "nrt"
, i, vect->ab, vect->ib);
}
- }
- pdbus->curr_bw_uc_idx = new_uc_idx;
- pdbus->ao_bw_uc_idx = new_uc_idx;
- DPU_ATRACE_BEGIN("msm_bus_scale_req");
- rc = msm_bus_scale_client_update_request(pdbus->data_bus_hdl,
new_uc_idx);
- DPU_ATRACE_END("msm_bus_scale_req");
- return rc;
+}
+int dpu_power_data_bus_set_quota(struct dpu_power_handle *phandle,
struct dpu_power_client *pclient,
int bus_client, u32 bus_id,
u64 ab_quota, u64 ib_quota)
+{
- int rc = 0;
- int i;
- u64 total_ab_rt = 0, total_ib_rt = 0;
- u64 total_ab_nrt = 0, total_ib_nrt = 0;
- struct dpu_power_client *client;
- if (!phandle || !pclient ||
bus_client >= DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX ||
bus_id >= DPU_POWER_HANDLE_DBUS_ID_MAX) {
pr_err("invalid parameters\n");
return -EINVAL;
- }
- mutex_lock(&phandle->phandle_lock);
- pclient->ab[bus_client] = ab_quota;
- pclient->ib[bus_client] = ib_quota;
- trace_dpu_perf_update_bus(bus_client, ab_quota, ib_quota);
- list_for_each_entry(client, &phandle->power_client_clist, list) {
for (i = 0; i < DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX; i++) {
if (i == DPU_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)
rc = _dpu_power_data_bus_set_quota(
&phandle->data_bus_handle[bus_id],
total_ab_rt, total_ab_nrt,
total_ib_rt, total_ib_nrt);
- mutex_unlock(&phandle->phandle_lock);
- return rc;
+}
+static void dpu_power_data_bus_unregister(
struct dpu_power_data_bus_handle *pdbus)
+{
- if (pdbus->data_bus_hdl) {
msm_bus_scale_unregister_client(pdbus->data_bus_hdl);
pdbus->data_bus_hdl = 0;
- }
+}
+static int dpu_power_data_bus_parse(struct platform_device *pdev,
- struct dpu_power_data_bus_handle *pdbus, const char *name)
+{
- struct device_node *node;
- int rc = 0;
- int paths;
- pdbus->bus_channels = 1;
- rc = of_property_read_u32(pdev->dev.of_node,
"qcom,dpu-dram-channels", &pdbus->bus_channels);
- if (rc) {
pr_debug("number of channels property not specified\n");
rc = 0;
- }
- pdbus->nrt_axi_port_cnt = 0;
- rc = of_property_read_u32(pdev->dev.of_node,
"qcom,dpu-num-nrt-paths",
&pdbus->nrt_axi_port_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);
- if (node) {
rc = of_property_read_u32(node,
"qcom,msm-bus,num-paths", &paths);
if (rc) {
pr_err("Error. qcom,msm-bus,num-paths not found\n");
return rc;
}
pdbus->axi_port_cnt = paths;
pdbus->data_bus_scale_table =
msm_bus_pdata_from_node(pdev, node);
if (IS_ERR_OR_NULL(pdbus->data_bus_scale_table)) {
pr_err("reg bus handle parsing failed\n");
rc = PTR_ERR(pdbus->data_bus_scale_table);
if (!pdbus->data_bus_scale_table)
rc = -EINVAL;
goto end;
}
pdbus->data_bus_hdl = msm_bus_scale_register_client(
pdbus->data_bus_scale_table);
if (!pdbus->data_bus_hdl) {
pr_err("data_bus_client register failed\n");
rc = -EINVAL;
goto end;
}
pr_debug("register %s data_bus_hdl=%x\n", name,
pdbus->data_bus_hdl);
- }
+end:
- return rc;
+}
+static int dpu_power_reg_bus_parse(struct platform_device *pdev,
- struct dpu_power_handle *phandle)
+{
- struct device_node *node;
- struct msm_bus_scale_pdata *bus_scale_table;
- int rc = 0;
- node = of_get_child_by_name(pdev->dev.of_node, "qcom,dpu-reg-bus");
- if (node) {
bus_scale_table = msm_bus_pdata_from_node(pdev, node);
if (IS_ERR_OR_NULL(bus_scale_table)) {
pr_err("reg bus handle parsing failed\n");
rc = PTR_ERR(bus_scale_table);
if (!bus_scale_table)
rc = -EINVAL;
goto end;
}
phandle->reg_bus_hdl = msm_bus_scale_register_client(
bus_scale_table);
if (!phandle->reg_bus_hdl) {
pr_err("reg_bus_client register failed\n");
rc = -EINVAL;
goto end;
}
pr_debug("register reg_bus_hdl=%x\n", phandle->reg_bus_hdl);
- }
+end:
- return rc;
+}
+static void dpu_power_reg_bus_unregister(u32 reg_bus_hdl) +{
- if (reg_bus_hdl)
msm_bus_scale_unregister_client(reg_bus_hdl);
+}
+int dpu_power_data_bus_state_update(struct dpu_power_handle *phandle,
bool enable)
+{
- int i;
- if (!phandle) {
pr_err("invalid param\n");
return -EINVAL;
- }
- for (i = DPU_POWER_HANDLE_DBUS_ID_MNOC;
i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++)
phandle->data_bus_handle[i].enable = enable;
- return 0;
+}
+static int dpu_power_data_bus_update(struct dpu_power_data_bus_handle *pdbus,
bool enable)
+{
- int rc = 0;
- pdbus->enable = enable;
- if (pdbus->data_bus_hdl)
rc = _dpu_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 dpu_power_reg_bus_update(u32 reg_bus_hdl, u32 usecase_ndx) +{
- int rc = 0;
- if (reg_bus_hdl)
rc = msm_bus_scale_client_update_request(reg_bus_hdl,
usecase_ndx);
- if (rc)
pr_err("failed to set reg bus vote rc=%d\n", rc);
- return rc;
+} +#else +static int dpu_power_data_bus_parse(struct platform_device *pdev,
struct dpu_power_data_bus_handle *pdbus, const char *name)
+{
- return 0;
+}
+static void dpu_power_data_bus_unregister(
struct dpu_power_data_bus_handle *pdbus)
+{ +}
+int dpu_power_data_bus_set_quota(struct dpu_power_handle *phandle,
struct dpu_power_client *pclient,
int bus_client, u32 bus_id,
u64 ab_quota, u64 ib_quota)
+{
- return 0;
+}
+static int dpu_power_reg_bus_parse(struct platform_device *pdev,
- struct dpu_power_handle *phandle)
+{
- return 0;
+}
+static void dpu_power_reg_bus_unregister(u32 reg_bus_hdl) +{ +}
+static int dpu_power_reg_bus_update(u32 reg_bus_hdl, u32 usecase_ndx) +{
- return 0;
+}
+static int dpu_power_data_bus_update(struct dpu_power_data_bus_handle *pdbus,
bool enable)
+{
- return 0;
+}
+int dpu_power_data_bus_state_update(struct dpu_power_handle *phandle,
bool enable)
+{
- return 0;
+} +#endif
+int dpu_power_resource_init(struct platform_device *pdev,
- struct dpu_power_handle *phandle)
+{
- int rc = 0, i;
- if (!phandle || !pdev) {
pr_err("invalid input param\n");
return -EINVAL;
- }
- phandle->dev = &pdev->dev;
- rc = dpu_power_reg_bus_parse(pdev, phandle);
- if (rc) {
pr_err("register bus parse failed rc=%d\n", rc);
return rc;
- }
- for (i = DPU_POWER_HANDLE_DBUS_ID_MNOC;
i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++) {
rc = dpu_power_data_bus_parse(pdev,
&phandle->data_bus_handle[i],
data_bus_name[i]);
if (rc) {
pr_err("register data bus parse failed id=%d rc=%d\n",
i, rc);
goto data_bus_err;
}
- }
- INIT_LIST_HEAD(&phandle->power_client_clist);
- INIT_LIST_HEAD(&phandle->event_list);
- mutex_init(&phandle->phandle_lock);
- return rc;
+data_bus_err:
- for (i--; i >= 0; i--)
dpu_power_data_bus_unregister(&phandle->data_bus_handle[i]);
- dpu_power_reg_bus_unregister(phandle->reg_bus_hdl);
- return rc;
+}
+void dpu_power_resource_deinit(struct platform_device *pdev,
- struct dpu_power_handle *phandle)
+{
- struct dpu_power_client *curr_client, *next_client;
- struct dpu_power_event *curr_event, *next_event;
- int i;
- if (!phandle || !pdev) {
pr_err("invalid input param\n");
return;
- }
- 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,
&phandle->event_list, list) {
pr_err("event:%d, client:%s still registered\n",
curr_event->event_type,
curr_event->client_name);
curr_event->active = false;
list_del(&curr_event->list);
- }
- mutex_unlock(&phandle->phandle_lock);
- for (i = 0; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++)
dpu_power_data_bus_unregister(&phandle->data_bus_handle[i]);
- dpu_power_reg_bus_unregister(phandle->reg_bus_hdl);
+}
+int dpu_power_resource_enable(struct dpu_power_handle *phandle,
- struct dpu_power_client *pclient, bool enable)
+{
- int rc = 0, i;
- bool changed = false;
- u32 max_usecase_ndx = VOTE_INDEX_DISABLE, prev_usecase_ndx;
- struct dpu_power_client *client;
- if (!phandle || !pclient) {
pr_err("invalid input argument\n");
return -EINVAL;
- }
- mutex_lock(&phandle->phandle_lock);
- 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;
- 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;
- }
- if (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;
- if (enable) {
dpu_power_event_trigger_locked(phandle,
DPU_POWER_EVENT_PRE_ENABLE);
for (i = 0; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++) {
rc = dpu_power_data_bus_update(
&phandle->data_bus_handle[i], enable);
if (rc) {
pr_err("failed to set data bus vote id=%d rc=%d\n",
i, rc);
goto data_bus_hdl_err;
}
}
rc = dpu_power_reg_bus_update(phandle->reg_bus_hdl,
max_usecase_ndx);
if (rc) {
pr_err("failed to set reg bus vote rc=%d\n", rc);
goto reg_bus_hdl_err;
}
dpu_power_event_trigger_locked(phandle,
DPU_POWER_EVENT_POST_ENABLE);
- } else {
dpu_power_event_trigger_locked(phandle,
DPU_POWER_EVENT_PRE_DISABLE);
dpu_power_reg_bus_update(phandle->reg_bus_hdl,
max_usecase_ndx);
for (i = 0 ; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++)
dpu_power_data_bus_update(&phandle->data_bus_handle[i],
enable);
dpu_power_event_trigger_locked(phandle,
DPU_POWER_EVENT_POST_DISABLE);
- }
+end:
- mutex_unlock(&phandle->phandle_lock);
- return rc;
+reg_bus_hdl_err:
- for (i = 0 ; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++)
dpu_power_data_bus_update(&phandle->data_bus_handle[i], 0);
+data_bus_hdl_err:
- phandle->current_usecase_ndx = prev_usecase_ndx;
- mutex_unlock(&phandle->phandle_lock);
- return rc;
+}
+struct dpu_power_event *dpu_power_handle_register_event(
struct dpu_power_handle *phandle,
u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
void *usr, char *client_name)
+{
- struct dpu_power_event *event;
- if (!phandle) {
pr_err("invalid power handle\n");
return ERR_PTR(-EINVAL);
- } else if (!cb_fnc || !event_type) {
pr_err("no callback fnc or event type\n");
return ERR_PTR(-EINVAL);
- }
- event = kzalloc(sizeof(struct dpu_power_event), GFP_KERNEL);
- if (!event)
return ERR_PTR(-ENOMEM);
- event->event_type = event_type;
- event->cb_fnc = cb_fnc;
- event->usr = usr;
- strlcpy(event->client_name, client_name, MAX_CLIENT_NAME_LEN);
- event->active = true;
- mutex_lock(&phandle->phandle_lock);
- list_add(&event->list, &phandle->event_list);
- mutex_unlock(&phandle->phandle_lock);
- return event;
+}
+void dpu_power_handle_unregister_event(
struct dpu_power_handle *phandle,
struct dpu_power_event *event)
+{
- if (!phandle || !event) {
pr_err("invalid phandle or event\n");
- } else if (!event->active) {
pr_err("power handle deinit already done\n");
kfree(event);
- } else {
mutex_lock(&phandle->phandle_lock);
list_del_init(&event->list);
mutex_unlock(&phandle->phandle_lock);
kfree(event);
- }
+} diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h new file mode 100644 index 0000000..9a6d4b9 --- /dev/null +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h @@ -0,0 +1,288 @@ +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 and
- only version 2 as published by the Free Software Foundation.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- */
+#ifndef _DPU_POWER_HANDLE_H_ +#define _DPU_POWER_HANDLE_H_
+#define MAX_CLIENT_NAME_LEN 128
+#define DPU_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 0 +#define DPU_POWER_HANDLE_DISABLE_BUS_AB_QUOTA 0 +#define DPU_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 1600000000 +#define DPU_POWER_HANDLE_DISABLE_BUS_IB_QUOTA 0
+#include <linux/dpu_io_util.h>
+/* event will be triggered before power handler disable */ +#define DPU_POWER_EVENT_PRE_DISABLE 0x1
+/* event will be triggered after power handler disable */ +#define DPU_POWER_EVENT_POST_DISABLE 0x2
+/* event will be triggered before power handler enable */ +#define DPU_POWER_EVENT_PRE_ENABLE 0x4
+/* event will be triggered after power handler enable */ +#define DPU_POWER_EVENT_POST_ENABLE 0x8
+/**
- mdss_bus_vote_type: register bus vote type
- VOTE_INDEX_DISABLE: removes the client vote
- VOTE_INDEX_LOW: keeps the lowest vote for register bus
- VOTE_INDEX_MAX: invalid
- */
+enum mdss_bus_vote_type {
- VOTE_INDEX_DISABLE,
- VOTE_INDEX_LOW,
- VOTE_INDEX_MAX,
+};
+/**
- enum dpu_power_handle_data_bus_client - type of axi bus clients
- @DPU_POWER_HANDLE_DATA_BUS_CLIENT_RT: core real-time bus client
- @DPU_POWER_HANDLE_DATA_BUS_CLIENT_NRT: core non-real-time bus client
- @DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX: maximum number of bus client type
- */
+enum dpu_power_handle_data_bus_client {
- DPU_POWER_HANDLE_DATA_BUS_CLIENT_RT,
- DPU_POWER_HANDLE_DATA_BUS_CLIENT_NRT,
- DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX
+};
+/**
- enum DPU_POWER_HANDLE_DBUS_ID - data bus identifier
- @DPU_POWER_HANDLE_DBUS_ID_MNOC: DPU/MNOC data bus
- @DPU_POWER_HANDLE_DBUS_ID_LLCC: MNOC/LLCC data bus
- @DPU_POWER_HANDLE_DBUS_ID_EBI: LLCC/EBI data bus
- */
+enum DPU_POWER_HANDLE_DBUS_ID {
- DPU_POWER_HANDLE_DBUS_ID_MNOC,
- DPU_POWER_HANDLE_DBUS_ID_LLCC,
- DPU_POWER_HANDLE_DBUS_ID_EBI,
- DPU_POWER_HANDLE_DBUS_ID_MAX,
+};
+/**
- struct dpu_power_client: stores the power client for dpu 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 dpu power handle
- */
+struct dpu_power_client {
- char name[MAX_CLIENT_NAME_LEN];
- short usecase_ndx;
- short refcount;
- u32 id;
- struct list_head list;
- u64 ab[DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
- u64 ib[DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
- bool active;
+};
+/**
- struct dpu_power_data_handle: power handle struct for data bus
- @data_bus_scale_table: pointer to bus scaling table
- @data_bus_hdl: current data bus handle
- @axi_port_cnt: number of rt axi ports
- @nrt_axi_port_cnt: number of nrt axi ports
- @bus_channels: number of memory bus channels
- @curr_bw_uc_idx: current use case index of data bus
- @ao_bw_uc_idx: active only use case index of data bus
- @ab_rt: realtime ab quota
- @ib_rt: realtime ib quota
- @ab_nrt: non-realtime ab quota
- @ib_nrt: non-realtime ib quota
- @enable: true if bus is enabled
- */
+struct dpu_power_data_bus_handle {
- struct msm_bus_scale_pdata *data_bus_scale_table;
- u32 data_bus_hdl;
- u32 axi_port_cnt;
- u32 nrt_axi_port_cnt;
- u32 bus_channels;
- u32 curr_bw_uc_idx;
- u32 ao_bw_uc_idx;
- u64 ab_rt;
- u64 ib_rt;
- u64 ab_nrt;
- u64 ib_nrt;
- bool enable;
+};
+/*
- struct dpu_power_event - local event registration structure
- @client_name: name of the client registering
- @cb_fnc: pointer to desired callback function
- @usr: user pointer to pass to callback event trigger
- @event: refer to DPU_POWER_HANDLE_EVENT_*
- @list: list to attach event master list
- @active: indicates the state of dpu power handle
- */
+struct dpu_power_event {
- char client_name[MAX_CLIENT_NAME_LEN];
- void (*cb_fnc)(u32 event_type, void *usr);
- void *usr;
- u32 event_type;
- struct list_head list;
- bool active;
+};
+/**
- struct dpu_power_handle: power handle main struct
- @client_clist: master list to store all clients
- @phandle_lock: lock to synchronize the enable/disable
- @dev: pointer to device structure
- @usecase_ndx: current usecase index
- @reg_bus_hdl: current register bus handle
- @data_bus_handle: context structure for data bus control
- @event_list: current power handle event list
- */
+struct dpu_power_handle {
- struct list_head power_client_clist;
- struct mutex phandle_lock;
- struct device *dev;
- u32 current_usecase_ndx;
- u32 reg_bus_hdl;
- struct dpu_power_data_bus_handle data_bus_handle
[DPU_POWER_HANDLE_DBUS_ID_MAX];
- struct list_head event_list;
+};
+/**
- dpu_power_resource_init() - initializes the dpu power handle
- @pdev: platform device to search the power resources
- @pdata: power handle to store the power resources
- Return: error code.
- */
+int dpu_power_resource_init(struct platform_device *pdev,
- struct dpu_power_handle *pdata);
+/**
- dpu_power_resource_deinit() - release the dpu power handle
- @pdev: platform device for power resources
- @pdata: power handle containing the resources
- Return: error code.
- */
+void dpu_power_resource_deinit(struct platform_device *pdev,
- struct dpu_power_handle *pdata);
+/**
- dpu_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 dpu_power_client *dpu_power_client_create(struct dpu_power_handle *pdata,
- char *client_name);
+/**
- dpu_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 dpu_power_client_destroy(struct dpu_power_handle *phandle,
- struct dpu_power_client *client);
+/**
- dpu_power_resource_enable() - enable/disable the power resources
- @pdata: power handle containing the resources
- @client: client information to enable/disable its vote
- @enable: boolean request for enable/disable
- Return: error code.
- */
+int dpu_power_resource_enable(struct dpu_power_handle *pdata,
- struct dpu_power_client *pclient, bool enable);
+/**
- dpu_power_data_bus_state_update() - update data bus state
- @pdata: power handle containing the resources
- @enable: take enable vs disable path
- Return: error code.
- */
+int dpu_power_data_bus_state_update(struct dpu_power_handle *phandle,
bool enable);
+/**
- dpu_power_data_bus_set_quota() - set data bus quota for power client
- @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 DPU_POWER_HANDLE_DBUS_ID
- @ab_quota: arbitrated bus bandwidth
- @ib_quota: instantaneous bus bandwidth
- Return: zero if success, or error code otherwise
- */
+int dpu_power_data_bus_set_quota(struct dpu_power_handle *phandle,
struct dpu_power_client *pclient,
int bus_client, u32 bus_id,
u64 ab_quota, u64 ib_quota);
+/**
- dpu_power_data_bus_bandwidth_ctrl() - control data bus bandwidth enable
- @phandle: power handle containing the resources
- @client: client information to bandwidth control
- @enable: true to enable bandwidth for data base
- Return: none
- */
+void dpu_power_data_bus_bandwidth_ctrl(struct dpu_power_handle *phandle,
struct dpu_power_client *pclient, int enable);
+/**
- dpu_power_handle_register_event - register a callback function for an event.
- Clients can register for multiple events with a single register.
- Any block with access to phandle can register for the event
- notification.
- @phandle: power handle containing the resources
- @event_type: event type to register; refer DPU_POWER_HANDLE_EVENT_*
- @cb_fnc: pointer to desired callback function
- @usr: user pointer to pass to callback on event trigger
- Return: event pointer if success, or error code otherwise
- */
+struct dpu_power_event *dpu_power_handle_register_event(
struct dpu_power_handle *phandle,
u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
void *usr, char *client_name);
+/**
- dpu_power_handle_unregister_event - unregister callback for event(s)
- @phandle: power handle containing the resources
- @event: event pointer returned after power handle register
- */
+void dpu_power_handle_unregister_event(struct dpu_power_handle *phandle,
struct dpu_power_event *event);
+/**
- dpu_power_handle_get_dbus_name - get name of given data bus identifier
- @bus_id: data bus identifier
- Return: Pointer to name string if success; NULL otherwise
- */
+const char *dpu_power_handle_get_dbus_name(u32 bus_id);
+#endif /* _DPU_POWER_HANDLE_H_ */ diff --git a/drivers/gpu/drm/msm/dpu_power_handle.c b/drivers/gpu/drm/msm/dpu_power_handle.c deleted file mode 100644 index 77be106..0000000 --- a/drivers/gpu/drm/msm/dpu_power_handle.c +++ /dev/null @@ -1,693 +0,0 @@ -/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 and
- only version 2 as published by the Free Software Foundation.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- */
-#define pr_fmt(fmt) "[drm:%s:%d]: " fmt, __func__, __LINE__
-#include <linux/kernel.h> -#include <linux/of.h> -#include <linux/string.h> -#include <linux/of_address.h> -#include <linux/slab.h> -#include <linux/mutex.h> -#include <linux/of_platform.h> -#ifdef CONFIG_QCOM_BUS_SCALING -#include <linux/msm-bus.h> -#include <linux/msm-bus-board.h> -#endif -#include <linux/dpu_io_util.h>
-#include "dpu_power_handle.h" -#include "dpu_trace.h"
-static const char *data_bus_name[DPU_POWER_HANDLE_DBUS_ID_MAX] = {
- [DPU_POWER_HANDLE_DBUS_ID_MNOC] = "qcom,dpu-data-bus",
- [DPU_POWER_HANDLE_DBUS_ID_LLCC] = "qcom,dpu-llcc-bus",
- [DPU_POWER_HANDLE_DBUS_ID_EBI] = "qcom,dpu-ebi-bus",
-};
-const char *dpu_power_handle_get_dbus_name(u32 bus_id) -{
- if (bus_id < DPU_POWER_HANDLE_DBUS_ID_MAX)
return data_bus_name[bus_id];
- return NULL;
-}
-static void dpu_power_event_trigger_locked(struct dpu_power_handle *phandle,
u32 event_type)
-{
- struct dpu_power_event *event;
- list_for_each_entry(event, &phandle->event_list, list) {
if (event->event_type & event_type)
event->cb_fnc(event_type, event->usr);
- }
-}
-struct dpu_power_client *dpu_power_client_create(
- struct dpu_power_handle *phandle, char *client_name)
-{
- struct dpu_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 dpu_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 dpu_power_client_destroy(struct dpu_power_handle *phandle,
- struct dpu_power_client *client)
-{
- if (!client || !phandle) {
pr_err("reg bus vote: invalid client handle\n");
- } else if (!client->active) {
pr_err("dpu 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);
- }
-}
-#ifdef CONFIG_QCOM_BUS_SCALING
-#define MAX_AXI_PORT_COUNT 3
-static int _dpu_power_data_bus_set_quota(
struct dpu_power_data_bus_handle *pdbus,
u64 ab_quota_rt, u64 ab_quota_nrt,
u64 ib_quota_rt, u64 ib_quota_nrt)
-{
- int new_uc_idx;
- u64 ab_quota[MAX_AXI_PORT_COUNT] = {0, 0};
- u64 ib_quota[MAX_AXI_PORT_COUNT] = {0, 0};
- int rc;
- if (pdbus->data_bus_hdl < 1) {
pr_err("invalid bus handle %d\n", pdbus->data_bus_hdl);
return -EINVAL;
- }
- pdbus->ab_rt = ab_quota_rt;
- 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,
DPU_POWER_HANDLE_ENABLE_BUS_AB_QUOTA);
ib_quota_rt = max_t(u64, ib_quota_rt,
DPU_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
ab_quota_nrt = max_t(u64, ab_quota_nrt,
DPU_POWER_HANDLE_ENABLE_BUS_AB_QUOTA);
ib_quota_nrt = max_t(u64, ib_quota_nrt,
DPU_POWER_HANDLE_ENABLE_BUS_IB_QUOTA);
- } else {
ab_quota_rt = min_t(u64, ab_quota_rt,
DPU_POWER_HANDLE_DISABLE_BUS_AB_QUOTA);
ib_quota_rt = min_t(u64, ib_quota_rt,
DPU_POWER_HANDLE_DISABLE_BUS_IB_QUOTA);
ab_quota_nrt = min_t(u64, ab_quota_nrt,
DPU_POWER_HANDLE_DISABLE_BUS_AB_QUOTA);
ib_quota_nrt = min_t(u64, ib_quota_nrt,
DPU_POWER_HANDLE_DISABLE_BUS_IB_QUOTA);
- }
- if (!ab_quota_rt && !ab_quota_nrt && !ib_quota_rt && !ib_quota_nrt) {
new_uc_idx = 0;
- } else {
int i;
struct msm_bus_vectors *vect = NULL;
struct msm_bus_scale_pdata *bw_table =
pdbus->data_bus_scale_table;
u32 nrt_axi_port_cnt = pdbus->nrt_axi_port_cnt;
u32 total_axi_port_cnt = pdbus->axi_port_cnt;
u32 rt_axi_port_cnt = total_axi_port_cnt - nrt_axi_port_cnt;
if (!bw_table || !total_axi_port_cnt ||
total_axi_port_cnt > MAX_AXI_PORT_COUNT) {
pr_err("invalid input\n");
return -EINVAL;
}
if (pdbus->bus_channels) {
ib_quota_rt = div_u64(ib_quota_rt,
pdbus->bus_channels);
ib_quota_nrt = div_u64(ib_quota_nrt,
pdbus->bus_channels);
}
if (nrt_axi_port_cnt) {
ab_quota_rt = div_u64(ab_quota_rt, rt_axi_port_cnt);
ab_quota_nrt = div_u64(ab_quota_nrt, nrt_axi_port_cnt);
for (i = 0; i < total_axi_port_cnt; i++) {
if (i < rt_axi_port_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_axi_port_cnt);
ib_quota[0] = ib_quota_rt + ib_quota_nrt;
for (i = 1; i < total_axi_port_cnt; i++) {
ab_quota[i] = ab_quota[0];
ib_quota[i] = ib_quota[0];
}
}
new_uc_idx = (pdbus->curr_bw_uc_idx %
(bw_table->num_usecases - 1)) + 1;
for (i = 0; i < total_axi_port_cnt; i++) {
vect = &bw_table->usecase[new_uc_idx].vectors[i];
vect->ab = ab_quota[i];
vect->ib = ib_quota[i];
pr_debug(
"%s uc_idx=%d %s path idx=%d ab=%llu ib=%llu\n",
bw_table->name,
new_uc_idx, (i < rt_axi_port_cnt) ? "rt" : "nrt"
, i, vect->ab, vect->ib);
}
- }
- pdbus->curr_bw_uc_idx = new_uc_idx;
- pdbus->ao_bw_uc_idx = new_uc_idx;
- DPU_ATRACE_BEGIN("msm_bus_scale_req");
- rc = msm_bus_scale_client_update_request(pdbus->data_bus_hdl,
new_uc_idx);
- DPU_ATRACE_END("msm_bus_scale_req");
- return rc;
-}
-int dpu_power_data_bus_set_quota(struct dpu_power_handle *phandle,
struct dpu_power_client *pclient,
int bus_client, u32 bus_id,
u64 ab_quota, u64 ib_quota)
-{
- int rc = 0;
- int i;
- u64 total_ab_rt = 0, total_ib_rt = 0;
- u64 total_ab_nrt = 0, total_ib_nrt = 0;
- struct dpu_power_client *client;
- if (!phandle || !pclient ||
bus_client >= DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX ||
bus_id >= DPU_POWER_HANDLE_DBUS_ID_MAX) {
pr_err("invalid parameters\n");
return -EINVAL;
- }
- mutex_lock(&phandle->phandle_lock);
- pclient->ab[bus_client] = ab_quota;
- pclient->ib[bus_client] = ib_quota;
- trace_dpu_perf_update_bus(bus_client, ab_quota, ib_quota);
- list_for_each_entry(client, &phandle->power_client_clist, list) {
for (i = 0; i < DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX; i++) {
if (i == DPU_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)
rc = _dpu_power_data_bus_set_quota(
&phandle->data_bus_handle[bus_id],
total_ab_rt, total_ab_nrt,
total_ib_rt, total_ib_nrt);
- mutex_unlock(&phandle->phandle_lock);
- return rc;
-}
-static void dpu_power_data_bus_unregister(
struct dpu_power_data_bus_handle *pdbus)
-{
- if (pdbus->data_bus_hdl) {
msm_bus_scale_unregister_client(pdbus->data_bus_hdl);
pdbus->data_bus_hdl = 0;
- }
-}
-static int dpu_power_data_bus_parse(struct platform_device *pdev,
- struct dpu_power_data_bus_handle *pdbus, const char *name)
-{
- struct device_node *node;
- int rc = 0;
- int paths;
- pdbus->bus_channels = 1;
- rc = of_property_read_u32(pdev->dev.of_node,
"qcom,dpu-dram-channels", &pdbus->bus_channels);
- if (rc) {
pr_debug("number of channels property not specified\n");
rc = 0;
- }
- pdbus->nrt_axi_port_cnt = 0;
- rc = of_property_read_u32(pdev->dev.of_node,
"qcom,dpu-num-nrt-paths",
&pdbus->nrt_axi_port_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);
- if (node) {
rc = of_property_read_u32(node,
"qcom,msm-bus,num-paths", &paths);
if (rc) {
pr_err("Error. qcom,msm-bus,num-paths not found\n");
return rc;
}
pdbus->axi_port_cnt = paths;
pdbus->data_bus_scale_table =
msm_bus_pdata_from_node(pdev, node);
if (IS_ERR_OR_NULL(pdbus->data_bus_scale_table)) {
pr_err("reg bus handle parsing failed\n");
rc = PTR_ERR(pdbus->data_bus_scale_table);
if (!pdbus->data_bus_scale_table)
rc = -EINVAL;
goto end;
}
pdbus->data_bus_hdl = msm_bus_scale_register_client(
pdbus->data_bus_scale_table);
if (!pdbus->data_bus_hdl) {
pr_err("data_bus_client register failed\n");
rc = -EINVAL;
goto end;
}
pr_debug("register %s data_bus_hdl=%x\n", name,
pdbus->data_bus_hdl);
- }
-end:
- return rc;
-}
-static int dpu_power_reg_bus_parse(struct platform_device *pdev,
- struct dpu_power_handle *phandle)
-{
- struct device_node *node;
- struct msm_bus_scale_pdata *bus_scale_table;
- int rc = 0;
- node = of_get_child_by_name(pdev->dev.of_node, "qcom,dpu-reg-bus");
- if (node) {
bus_scale_table = msm_bus_pdata_from_node(pdev, node);
if (IS_ERR_OR_NULL(bus_scale_table)) {
pr_err("reg bus handle parsing failed\n");
rc = PTR_ERR(bus_scale_table);
if (!bus_scale_table)
rc = -EINVAL;
goto end;
}
phandle->reg_bus_hdl = msm_bus_scale_register_client(
bus_scale_table);
if (!phandle->reg_bus_hdl) {
pr_err("reg_bus_client register failed\n");
rc = -EINVAL;
goto end;
}
pr_debug("register reg_bus_hdl=%x\n", phandle->reg_bus_hdl);
- }
-end:
- return rc;
-}
-static void dpu_power_reg_bus_unregister(u32 reg_bus_hdl) -{
- if (reg_bus_hdl)
msm_bus_scale_unregister_client(reg_bus_hdl);
-}
-int dpu_power_data_bus_state_update(struct dpu_power_handle *phandle,
bool enable)
-{
- int i;
- if (!phandle) {
pr_err("invalid param\n");
return -EINVAL;
- }
- for (i = DPU_POWER_HANDLE_DBUS_ID_MNOC;
i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++)
phandle->data_bus_handle[i].enable = enable;
- return 0;
-}
-static int dpu_power_data_bus_update(struct dpu_power_data_bus_handle *pdbus,
bool enable)
-{
- int rc = 0;
- pdbus->enable = enable;
- if (pdbus->data_bus_hdl)
rc = _dpu_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 dpu_power_reg_bus_update(u32 reg_bus_hdl, u32 usecase_ndx) -{
- int rc = 0;
- if (reg_bus_hdl)
rc = msm_bus_scale_client_update_request(reg_bus_hdl,
usecase_ndx);
- if (rc)
pr_err("failed to set reg bus vote rc=%d\n", rc);
- return rc;
-} -#else -static int dpu_power_data_bus_parse(struct platform_device *pdev,
struct dpu_power_data_bus_handle *pdbus, const char *name)
-{
- return 0;
-}
-static void dpu_power_data_bus_unregister(
struct dpu_power_data_bus_handle *pdbus)
-{ -}
-int dpu_power_data_bus_set_quota(struct dpu_power_handle *phandle,
struct dpu_power_client *pclient,
int bus_client, u32 bus_id,
u64 ab_quota, u64 ib_quota)
-{
- return 0;
-}
-static int dpu_power_reg_bus_parse(struct platform_device *pdev,
- struct dpu_power_handle *phandle)
-{
- return 0;
-}
-static void dpu_power_reg_bus_unregister(u32 reg_bus_hdl) -{ -}
-static int dpu_power_reg_bus_update(u32 reg_bus_hdl, u32 usecase_ndx) -{
- return 0;
-}
-static int dpu_power_data_bus_update(struct dpu_power_data_bus_handle *pdbus,
bool enable)
-{
- return 0;
-}
-int dpu_power_data_bus_state_update(struct dpu_power_handle *phandle,
bool enable)
-{
- return 0;
-} -#endif
-int dpu_power_resource_init(struct platform_device *pdev,
- struct dpu_power_handle *phandle)
-{
- int rc = 0, i;
- if (!phandle || !pdev) {
pr_err("invalid input param\n");
return -EINVAL;
- }
- phandle->dev = &pdev->dev;
- rc = dpu_power_reg_bus_parse(pdev, phandle);
- if (rc) {
pr_err("register bus parse failed rc=%d\n", rc);
return rc;
- }
- for (i = DPU_POWER_HANDLE_DBUS_ID_MNOC;
i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++) {
rc = dpu_power_data_bus_parse(pdev,
&phandle->data_bus_handle[i],
data_bus_name[i]);
if (rc) {
pr_err("register data bus parse failed id=%d rc=%d\n",
i, rc);
goto data_bus_err;
}
- }
- INIT_LIST_HEAD(&phandle->power_client_clist);
- INIT_LIST_HEAD(&phandle->event_list);
- mutex_init(&phandle->phandle_lock);
- return rc;
-data_bus_err:
- for (i--; i >= 0; i--)
dpu_power_data_bus_unregister(&phandle->data_bus_handle[i]);
- dpu_power_reg_bus_unregister(phandle->reg_bus_hdl);
- return rc;
-}
-void dpu_power_resource_deinit(struct platform_device *pdev,
- struct dpu_power_handle *phandle)
-{
- struct dpu_power_client *curr_client, *next_client;
- struct dpu_power_event *curr_event, *next_event;
- int i;
- if (!phandle || !pdev) {
pr_err("invalid input param\n");
return;
- }
- 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,
&phandle->event_list, list) {
pr_err("event:%d, client:%s still registered\n",
curr_event->event_type,
curr_event->client_name);
curr_event->active = false;
list_del(&curr_event->list);
- }
- mutex_unlock(&phandle->phandle_lock);
- for (i = 0; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++)
dpu_power_data_bus_unregister(&phandle->data_bus_handle[i]);
- dpu_power_reg_bus_unregister(phandle->reg_bus_hdl);
-}
-int dpu_power_resource_enable(struct dpu_power_handle *phandle,
- struct dpu_power_client *pclient, bool enable)
-{
- int rc = 0, i;
- bool changed = false;
- u32 max_usecase_ndx = VOTE_INDEX_DISABLE, prev_usecase_ndx;
- struct dpu_power_client *client;
- if (!phandle || !pclient) {
pr_err("invalid input argument\n");
return -EINVAL;
- }
- mutex_lock(&phandle->phandle_lock);
- 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;
- 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;
- }
- if (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;
- if (enable) {
dpu_power_event_trigger_locked(phandle,
DPU_POWER_EVENT_PRE_ENABLE);
for (i = 0; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++) {
rc = dpu_power_data_bus_update(
&phandle->data_bus_handle[i], enable);
if (rc) {
pr_err("failed to set data bus vote id=%d rc=%d\n",
i, rc);
goto data_bus_hdl_err;
}
}
rc = dpu_power_reg_bus_update(phandle->reg_bus_hdl,
max_usecase_ndx);
if (rc) {
pr_err("failed to set reg bus vote rc=%d\n", rc);
goto reg_bus_hdl_err;
}
dpu_power_event_trigger_locked(phandle,
DPU_POWER_EVENT_POST_ENABLE);
- } else {
dpu_power_event_trigger_locked(phandle,
DPU_POWER_EVENT_PRE_DISABLE);
dpu_power_reg_bus_update(phandle->reg_bus_hdl,
max_usecase_ndx);
for (i = 0 ; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++)
dpu_power_data_bus_update(&phandle->data_bus_handle[i],
enable);
dpu_power_event_trigger_locked(phandle,
DPU_POWER_EVENT_POST_DISABLE);
- }
-end:
- mutex_unlock(&phandle->phandle_lock);
- return rc;
-reg_bus_hdl_err:
- for (i = 0 ; i < DPU_POWER_HANDLE_DBUS_ID_MAX; i++)
dpu_power_data_bus_update(&phandle->data_bus_handle[i], 0);
-data_bus_hdl_err:
- phandle->current_usecase_ndx = prev_usecase_ndx;
- mutex_unlock(&phandle->phandle_lock);
- return rc;
-}
-struct dpu_power_event *dpu_power_handle_register_event(
struct dpu_power_handle *phandle,
u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
void *usr, char *client_name)
-{
- struct dpu_power_event *event;
- if (!phandle) {
pr_err("invalid power handle\n");
return ERR_PTR(-EINVAL);
- } else if (!cb_fnc || !event_type) {
pr_err("no callback fnc or event type\n");
return ERR_PTR(-EINVAL);
- }
- event = kzalloc(sizeof(struct dpu_power_event), GFP_KERNEL);
- if (!event)
return ERR_PTR(-ENOMEM);
- event->event_type = event_type;
- event->cb_fnc = cb_fnc;
- event->usr = usr;
- strlcpy(event->client_name, client_name, MAX_CLIENT_NAME_LEN);
- event->active = true;
- mutex_lock(&phandle->phandle_lock);
- list_add(&event->list, &phandle->event_list);
- mutex_unlock(&phandle->phandle_lock);
- return event;
-}
-void dpu_power_handle_unregister_event(
struct dpu_power_handle *phandle,
struct dpu_power_event *event)
-{
- if (!phandle || !event) {
pr_err("invalid phandle or event\n");
- } else if (!event->active) {
pr_err("power handle deinit already done\n");
kfree(event);
- } else {
mutex_lock(&phandle->phandle_lock);
list_del_init(&event->list);
mutex_unlock(&phandle->phandle_lock);
kfree(event);
- }
-} diff --git a/drivers/gpu/drm/msm/dpu_power_handle.h b/drivers/gpu/drm/msm/dpu_power_handle.h deleted file mode 100644 index 9a6d4b9..0000000 --- a/drivers/gpu/drm/msm/dpu_power_handle.h +++ /dev/null @@ -1,288 +0,0 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 and
- only version 2 as published by the Free Software Foundation.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- */
-#ifndef _DPU_POWER_HANDLE_H_ -#define _DPU_POWER_HANDLE_H_
-#define MAX_CLIENT_NAME_LEN 128
-#define DPU_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 0 -#define DPU_POWER_HANDLE_DISABLE_BUS_AB_QUOTA 0 -#define DPU_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 1600000000 -#define DPU_POWER_HANDLE_DISABLE_BUS_IB_QUOTA 0
-#include <linux/dpu_io_util.h>
-/* event will be triggered before power handler disable */ -#define DPU_POWER_EVENT_PRE_DISABLE 0x1
-/* event will be triggered after power handler disable */ -#define DPU_POWER_EVENT_POST_DISABLE 0x2
-/* event will be triggered before power handler enable */ -#define DPU_POWER_EVENT_PRE_ENABLE 0x4
-/* event will be triggered after power handler enable */ -#define DPU_POWER_EVENT_POST_ENABLE 0x8
-/**
- mdss_bus_vote_type: register bus vote type
- VOTE_INDEX_DISABLE: removes the client vote
- VOTE_INDEX_LOW: keeps the lowest vote for register bus
- VOTE_INDEX_MAX: invalid
- */
-enum mdss_bus_vote_type {
- VOTE_INDEX_DISABLE,
- VOTE_INDEX_LOW,
- VOTE_INDEX_MAX,
-};
-/**
- enum dpu_power_handle_data_bus_client - type of axi bus clients
- @DPU_POWER_HANDLE_DATA_BUS_CLIENT_RT: core real-time bus client
- @DPU_POWER_HANDLE_DATA_BUS_CLIENT_NRT: core non-real-time bus client
- @DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX: maximum number of bus client type
- */
-enum dpu_power_handle_data_bus_client {
- DPU_POWER_HANDLE_DATA_BUS_CLIENT_RT,
- DPU_POWER_HANDLE_DATA_BUS_CLIENT_NRT,
- DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX
-};
-/**
- enum DPU_POWER_HANDLE_DBUS_ID - data bus identifier
- @DPU_POWER_HANDLE_DBUS_ID_MNOC: DPU/MNOC data bus
- @DPU_POWER_HANDLE_DBUS_ID_LLCC: MNOC/LLCC data bus
- @DPU_POWER_HANDLE_DBUS_ID_EBI: LLCC/EBI data bus
- */
-enum DPU_POWER_HANDLE_DBUS_ID {
- DPU_POWER_HANDLE_DBUS_ID_MNOC,
- DPU_POWER_HANDLE_DBUS_ID_LLCC,
- DPU_POWER_HANDLE_DBUS_ID_EBI,
- DPU_POWER_HANDLE_DBUS_ID_MAX,
-};
-/**
- struct dpu_power_client: stores the power client for dpu 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 dpu power handle
- */
-struct dpu_power_client {
- char name[MAX_CLIENT_NAME_LEN];
- short usecase_ndx;
- short refcount;
- u32 id;
- struct list_head list;
- u64 ab[DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
- u64 ib[DPU_POWER_HANDLE_DATA_BUS_CLIENT_MAX];
- bool active;
-};
-/**
- struct dpu_power_data_handle: power handle struct for data bus
- @data_bus_scale_table: pointer to bus scaling table
- @data_bus_hdl: current data bus handle
- @axi_port_cnt: number of rt axi ports
- @nrt_axi_port_cnt: number of nrt axi ports
- @bus_channels: number of memory bus channels
- @curr_bw_uc_idx: current use case index of data bus
- @ao_bw_uc_idx: active only use case index of data bus
- @ab_rt: realtime ab quota
- @ib_rt: realtime ib quota
- @ab_nrt: non-realtime ab quota
- @ib_nrt: non-realtime ib quota
- @enable: true if bus is enabled
- */
-struct dpu_power_data_bus_handle {
- struct msm_bus_scale_pdata *data_bus_scale_table;
- u32 data_bus_hdl;
- u32 axi_port_cnt;
- u32 nrt_axi_port_cnt;
- u32 bus_channels;
- u32 curr_bw_uc_idx;
- u32 ao_bw_uc_idx;
- u64 ab_rt;
- u64 ib_rt;
- u64 ab_nrt;
- u64 ib_nrt;
- bool enable;
-};
-/*
- struct dpu_power_event - local event registration structure
- @client_name: name of the client registering
- @cb_fnc: pointer to desired callback function
- @usr: user pointer to pass to callback event trigger
- @event: refer to DPU_POWER_HANDLE_EVENT_*
- @list: list to attach event master list
- @active: indicates the state of dpu power handle
- */
-struct dpu_power_event {
- char client_name[MAX_CLIENT_NAME_LEN];
- void (*cb_fnc)(u32 event_type, void *usr);
- void *usr;
- u32 event_type;
- struct list_head list;
- bool active;
-};
-/**
- struct dpu_power_handle: power handle main struct
- @client_clist: master list to store all clients
- @phandle_lock: lock to synchronize the enable/disable
- @dev: pointer to device structure
- @usecase_ndx: current usecase index
- @reg_bus_hdl: current register bus handle
- @data_bus_handle: context structure for data bus control
- @event_list: current power handle event list
- */
-struct dpu_power_handle {
- struct list_head power_client_clist;
- struct mutex phandle_lock;
- struct device *dev;
- u32 current_usecase_ndx;
- u32 reg_bus_hdl;
- struct dpu_power_data_bus_handle data_bus_handle
[DPU_POWER_HANDLE_DBUS_ID_MAX];
- struct list_head event_list;
-};
-/**
- dpu_power_resource_init() - initializes the dpu power handle
- @pdev: platform device to search the power resources
- @pdata: power handle to store the power resources
- Return: error code.
- */
-int dpu_power_resource_init(struct platform_device *pdev,
- struct dpu_power_handle *pdata);
-/**
- dpu_power_resource_deinit() - release the dpu power handle
- @pdev: platform device for power resources
- @pdata: power handle containing the resources
- Return: error code.
- */
-void dpu_power_resource_deinit(struct platform_device *pdev,
- struct dpu_power_handle *pdata);
-/**
- dpu_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 dpu_power_client *dpu_power_client_create(struct dpu_power_handle *pdata,
- char *client_name);
-/**
- dpu_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 dpu_power_client_destroy(struct dpu_power_handle *phandle,
- struct dpu_power_client *client);
-/**
- dpu_power_resource_enable() - enable/disable the power resources
- @pdata: power handle containing the resources
- @client: client information to enable/disable its vote
- @enable: boolean request for enable/disable
- Return: error code.
- */
-int dpu_power_resource_enable(struct dpu_power_handle *pdata,
- struct dpu_power_client *pclient, bool enable);
-/**
- dpu_power_data_bus_state_update() - update data bus state
- @pdata: power handle containing the resources
- @enable: take enable vs disable path
- Return: error code.
- */
-int dpu_power_data_bus_state_update(struct dpu_power_handle *phandle,
bool enable);
-/**
- dpu_power_data_bus_set_quota() - set data bus quota for power client
- @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 DPU_POWER_HANDLE_DBUS_ID
- @ab_quota: arbitrated bus bandwidth
- @ib_quota: instantaneous bus bandwidth
- Return: zero if success, or error code otherwise
- */
-int dpu_power_data_bus_set_quota(struct dpu_power_handle *phandle,
struct dpu_power_client *pclient,
int bus_client, u32 bus_id,
u64 ab_quota, u64 ib_quota);
-/**
- dpu_power_data_bus_bandwidth_ctrl() - control data bus bandwidth enable
- @phandle: power handle containing the resources
- @client: client information to bandwidth control
- @enable: true to enable bandwidth for data base
- Return: none
- */
-void dpu_power_data_bus_bandwidth_ctrl(struct dpu_power_handle *phandle,
struct dpu_power_client *pclient, int enable);
-/**
- dpu_power_handle_register_event - register a callback function for an event.
- Clients can register for multiple events with a single register.
- Any block with access to phandle can register for the event
- notification.
- @phandle: power handle containing the resources
- @event_type: event type to register; refer DPU_POWER_HANDLE_EVENT_*
- @cb_fnc: pointer to desired callback function
- @usr: user pointer to pass to callback on event trigger
- Return: event pointer if success, or error code otherwise
- */
-struct dpu_power_event *dpu_power_handle_register_event(
struct dpu_power_handle *phandle,
u32 event_type, void (*cb_fnc)(u32 event_type, void *usr),
void *usr, char *client_name);
-/**
- dpu_power_handle_unregister_event - unregister callback for event(s)
- @phandle: power handle containing the resources
- @event: event pointer returned after power handle register
- */
-void dpu_power_handle_unregister_event(struct dpu_power_handle *phandle,
struct dpu_power_event *event);
-/**
- dpu_power_handle_get_dbus_name - get name of given data bus identifier
- @bus_id: data bus identifier
- Return: Pointer to name string if success; NULL otherwise
- */
-const char *dpu_power_handle_get_dbus_name(u32 bus_id);
-#endif /* _DPU_POWER_HANDLE_H_ */ diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 5c267cd..60b6919 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -340,7 +340,6 @@ static int msm_drm_uninit(struct device *dev) component_unbind_all(dev, ddev);
#ifdef CONFIG_DRM_MSM_DPU
- dpu_power_resource_deinit(pdev, &priv->phandle); dpu_dbg_destroy();
#endif
@@ -519,12 +518,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) drm_mode_config_init(ddev);
#ifdef CONFIG_DRM_MSM_DPU
- ret = dpu_power_resource_init(pdev, &priv->phandle);
- if (ret) {
pr_err("dpu power resource init failed\n");
goto power_init_fail;
- }
- ret = dpu_dbg_init(&pdev->dev); if (ret) { dev_err(dev, "failed to init dpu dbg: %d\n", ret);
@@ -733,8 +726,6 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) #ifdef CONFIG_DRM_MSM_DPU dpu_dbg_destroy(); dbg_init_fail:
- dpu_power_resource_deinit(pdev, &priv->phandle);
-power_init_fail: #endif if (mdss && mdss->funcs) mdss->funcs->destroy(ddev); diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index f9ae96f..27a73a8 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -46,8 +46,6 @@ #include <drm/msm_drm.h> #include <drm/drm_gem.h>
-#include "dpu_power_handle.h"
#define GET_MAJOR_REV(rev) ((rev) >> 28) #define GET_MINOR_REV(rev) (((rev) >> 16) & 0xFFF) #define GET_STEP_REV(rev) ((rev) & 0xFFFF) @@ -375,8 +373,6 @@ struct msm_drm_private {
struct msm_kms *kms;
- struct dpu_power_handle phandle;
- /* subordinate devices, if present: */ struct platform_device *gpu_pdev;
-- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project