summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2017-03-02 08:27:02 -0800
committerGerrit - the friendly Code Review server <code-review@localhost>2017-03-02 08:27:02 -0800
commit2caf0b2fcdf4affc8bde725cd89ab8c803ca6c88 (patch)
tree49a15b27997856c06f6ab54a428aad09e422fbc8
parent1543b55dce25849d04ed75138118a73ee6d38714 (diff)
parent4df2249e9d46f7fce54665fa373cedd45c5eb483 (diff)
Merge "msm: vidc: Add support for Cx ipeak limitation"
-rw-r--r--Documentation/devicetree/bindings/media/video/msm-vidc.txt8
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_res_parse.c31
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_resources.h3
-rw-r--r--drivers/media/platform/msm/vidc/venus_hfi.c58
4 files changed, 84 insertions, 16 deletions
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index 6ca0ac31a581..c26e9fb456e3 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -126,7 +126,7 @@ Optional properties:
internal persist1 = 0x400
internal cmd queue = 0x800
- qcom,pm-qos-latency-us = The latency used to vote for QOS power manager. This
-value is typically max(latencies of every cluster at all power levels) + 1
+ value is typically max(latencies of every cluster at all power levels) + 1
- qcom,max-secure-instances = An int containing max number of concurrent secure
instances supported, accounting for venus and system wide limitations like
memory, performance etc.
@@ -135,6 +135,12 @@ value is typically max(latencies of every cluster at all power levels) + 1
- qcom,power-conf = Indicates the value at which or beyond, a video session
is configured in low power mode to have power benefits. Value is defined
interms of HxW of the video session beyond which power benefit is desired.
+- qcom,cx-ipeak-data : phandle of cx_ipeak device node and bit position on
+ the cx register where venus is supposed to vote
+- qcom,clock-freq-threshold : Operating threshold frequency of venus which
+ video driver uses to check against the frequency voted. Whenever venus
+ clock frequency crosses this mark, driver intimates cx ipeak driver on
+ supported targets.
[Second level nodes]
Context Banks
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index 022c776a6096..a65e22c66e30 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -22,6 +22,7 @@
#include "msm_vidc_res_parse.h"
#include "venus_boot.h"
#include "soc/qcom/secure_buffer.h"
+#include "soc/qcom/cx_ipeak.h"
enum clock_properties {
CLOCK_PROP_HAS_SCALING = 1 << 0,
@@ -171,6 +172,8 @@ void msm_vidc_free_platform_resources(
msm_vidc_free_qdss_addr_table(res);
msm_vidc_free_bus_vectors(res);
msm_vidc_free_buffer_usage_table(res);
+ cx_ipeak_unregister(res->cx_ipeak_context);
+ res->cx_ipeak_context = NULL;
}
static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res)
@@ -1133,8 +1136,36 @@ int read_platform_resources_from_dt(
of_property_read_u32(pdev->dev.of_node,
"qcom,max-secure-instances",
&res->max_secure_inst_count);
+
+ res->cx_ipeak_context = cx_ipeak_register(pdev->dev.of_node,
+ "qcom,cx-ipeak-data");
+
+ if (IS_ERR(res->cx_ipeak_context)) {
+ rc = PTR_ERR(res->cx_ipeak_context);
+ if (rc == -EPROBE_DEFER)
+ dprintk(VIDC_INFO,
+ "cx-ipeak register failed. Deferring probe!");
+ else
+ dprintk(VIDC_ERR,
+ "cx-ipeak register failed. rc: %d", rc);
+
+ res->cx_ipeak_context = NULL;
+ goto err_register_cx_ipeak;
+ } else if (res->cx_ipeak_context) {
+ dprintk(VIDC_INFO, "cx-ipeak register successful");
+ } else {
+ dprintk(VIDC_INFO, "cx-ipeak register not implemented");
+ }
+
+ of_property_read_u32(pdev->dev.of_node,
+ "qcom,clock-freq-threshold",
+ &res->clk_freq_threshold);
+ dprintk(VIDC_DBG, "cx ipeak threshold frequency = %u\n",
+ res->clk_freq_threshold);
+
return rc;
+err_register_cx_ipeak:
err_setup_legacy_cb:
err_load_max_hw_load:
msm_vidc_free_allowed_clocks_table(res);
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 03b31d7fd9d1..3a329d989918 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -17,6 +17,7 @@
#include <linux/devfreq.h>
#include <linux/platform_device.h>
#include <media/msm_vidc.h>
+#include "soc/qcom/cx_ipeak.h"
#define MAX_BUFFER_TYPES 32
struct platform_version_table {
@@ -191,6 +192,8 @@ struct msm_vidc_platform_resources {
uint32_t pm_qos_latency_us;
uint32_t max_inst_count;
uint32_t max_secure_inst_count;
+ uint32_t clk_freq_threshold;
+ struct cx_ipeak_client *cx_ipeak_context;
};
static inline bool is_iommu_present(struct msm_vidc_platform_resources *res)
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 777fb52b2201..1b89f5ff9e8d 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -27,6 +27,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include <soc/qcom/cx_ipeak.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/smem.h>
#include <soc/qcom/subsystem_restart.h>
@@ -1385,6 +1386,39 @@ static int __halt_axi(struct venus_hfi_device *device)
return rc;
}
+static int __set_clk_rate(struct venus_hfi_device *device,
+ struct clock_info *cl, u64 rate) {
+ int rc = 0, rc1 = 0;
+ u64 toggle_freq = device->res->clk_freq_threshold;
+ struct cx_ipeak_client *ipeak = device->res->cx_ipeak_context;
+ struct clk *clk = cl->clk;
+
+ if (device->clk_freq < toggle_freq && rate >= toggle_freq) {
+ rc1 = cx_ipeak_update(ipeak, true);
+ dprintk(VIDC_PROF, "Voting up: %d\n", rc);
+ }
+
+ rc = clk_set_rate(clk, rate);
+ if (rc)
+ dprintk(VIDC_ERR,
+ "%s: Failed to set clock rate %llu %s: %d\n",
+ __func__, rate, cl->name, rc);
+
+ if (device->clk_freq >= toggle_freq && rate < toggle_freq) {
+ rc1 = cx_ipeak_update(ipeak, false);
+ dprintk(VIDC_PROF, "Voting down: %d\n", rc);
+ }
+
+ if (rc1)
+ dprintk(VIDC_ERR,
+ "cx_ipeak_update failed! ipeak %pK\n", ipeak);
+
+ if (!rc)
+ device->clk_freq = rate;
+
+ return rc;
+}
+
static int __scale_clocks_cycles_per_mb(struct venus_hfi_device *device,
struct vidc_clk_scale_data *data, unsigned long instant_bitrate)
{
@@ -1458,14 +1492,10 @@ get_clock_freq:
if (!cl->has_scaling)
continue;
- device->clk_freq = rate;
- rc = clk_set_rate(cl->clk, rate);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s: Failed to set clock rate %llu %s: %d\n",
- __func__, rate, cl->name, rc);
+ rc = __set_clk_rate(device, cl, rate);
+ if (rc)
return rc;
- }
+
if (!strcmp(cl->name, "core_clk"))
device->scaled_rate = rate;
@@ -1506,14 +1536,11 @@ static int __scale_clocks_load(struct venus_hfi_device *device, int load,
load, data,
instant_bitrate);
}
- device->clk_freq = rate;
- rc = clk_set_rate(cl->clk, rate);
- if (rc) {
- dprintk(VIDC_ERR,
- "Failed to set clock rate %lu %s: %d\n",
- rate, cl->name, rc);
+
+ rc = __set_clk_rate(device, cl, rate);
+ if (rc)
return rc;
- }
+
if (!strcmp(cl->name, "core_clk"))
device->scaled_rate = rate;
@@ -3794,7 +3821,8 @@ static inline int __prepare_enable_clks(struct venus_hfi_device *device)
* it to the lowest frequency possible
*/
if (cl->has_scaling)
- clk_set_rate(cl->clk, clk_round_rate(cl->clk, 0));
+ __set_clk_rate(device, cl,
+ clk_round_rate(cl->clk, 0));
if (cl->has_mem_retention) {
rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_PERIPH);