Merge "msm: vidc: Add support for Cx ipeak limitation"
This commit is contained in:
commit
2caf0b2fcd
4 changed files with 84 additions and 16 deletions
|
@ -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
|
- 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
|
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.
|
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]
|
[Second level nodes]
|
||||||
Context Banks
|
Context Banks
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "msm_vidc_res_parse.h"
|
#include "msm_vidc_res_parse.h"
|
||||||
#include "venus_boot.h"
|
#include "venus_boot.h"
|
||||||
#include "soc/qcom/secure_buffer.h"
|
#include "soc/qcom/secure_buffer.h"
|
||||||
|
#include "soc/qcom/cx_ipeak.h"
|
||||||
|
|
||||||
enum clock_properties {
|
enum clock_properties {
|
||||||
CLOCK_PROP_HAS_SCALING = 1 << 0,
|
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_qdss_addr_table(res);
|
||||||
msm_vidc_free_bus_vectors(res);
|
msm_vidc_free_bus_vectors(res);
|
||||||
msm_vidc_free_buffer_usage_table(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)
|
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,
|
of_property_read_u32(pdev->dev.of_node,
|
||||||
"qcom,max-secure-instances",
|
"qcom,max-secure-instances",
|
||||||
&res->max_secure_inst_count);
|
&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;
|
return rc;
|
||||||
|
|
||||||
|
err_register_cx_ipeak:
|
||||||
err_setup_legacy_cb:
|
err_setup_legacy_cb:
|
||||||
err_load_max_hw_load:
|
err_load_max_hw_load:
|
||||||
msm_vidc_free_allowed_clocks_table(res);
|
msm_vidc_free_allowed_clocks_table(res);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/devfreq.h>
|
#include <linux/devfreq.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <media/msm_vidc.h>
|
#include <media/msm_vidc.h>
|
||||||
|
#include "soc/qcom/cx_ipeak.h"
|
||||||
#define MAX_BUFFER_TYPES 32
|
#define MAX_BUFFER_TYPES 32
|
||||||
|
|
||||||
struct platform_version_table {
|
struct platform_version_table {
|
||||||
|
@ -191,6 +192,8 @@ struct msm_vidc_platform_resources {
|
||||||
uint32_t pm_qos_latency_us;
|
uint32_t pm_qos_latency_us;
|
||||||
uint32_t max_inst_count;
|
uint32_t max_inst_count;
|
||||||
uint32_t max_secure_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)
|
static inline bool is_iommu_present(struct msm_vidc_platform_resources *res)
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <linux/regulator/consumer.h>
|
#include <linux/regulator/consumer.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/workqueue.h>
|
#include <linux/workqueue.h>
|
||||||
|
#include <soc/qcom/cx_ipeak.h>
|
||||||
#include <soc/qcom/scm.h>
|
#include <soc/qcom/scm.h>
|
||||||
#include <soc/qcom/smem.h>
|
#include <soc/qcom/smem.h>
|
||||||
#include <soc/qcom/subsystem_restart.h>
|
#include <soc/qcom/subsystem_restart.h>
|
||||||
|
@ -1385,6 +1386,39 @@ static int __halt_axi(struct venus_hfi_device *device)
|
||||||
return rc;
|
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,
|
static int __scale_clocks_cycles_per_mb(struct venus_hfi_device *device,
|
||||||
struct vidc_clk_scale_data *data, unsigned long instant_bitrate)
|
struct vidc_clk_scale_data *data, unsigned long instant_bitrate)
|
||||||
{
|
{
|
||||||
|
@ -1458,14 +1492,10 @@ get_clock_freq:
|
||||||
if (!cl->has_scaling)
|
if (!cl->has_scaling)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
device->clk_freq = rate;
|
rc = __set_clk_rate(device, cl, rate);
|
||||||
rc = clk_set_rate(cl->clk, rate);
|
if (rc)
|
||||||
if (rc) {
|
|
||||||
dprintk(VIDC_ERR,
|
|
||||||
"%s: Failed to set clock rate %llu %s: %d\n",
|
|
||||||
__func__, rate, cl->name, rc);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
if (!strcmp(cl->name, "core_clk"))
|
if (!strcmp(cl->name, "core_clk"))
|
||||||
device->scaled_rate = rate;
|
device->scaled_rate = rate;
|
||||||
|
|
||||||
|
@ -1506,14 +1536,11 @@ static int __scale_clocks_load(struct venus_hfi_device *device, int load,
|
||||||
load, data,
|
load, data,
|
||||||
instant_bitrate);
|
instant_bitrate);
|
||||||
}
|
}
|
||||||
device->clk_freq = rate;
|
|
||||||
rc = clk_set_rate(cl->clk, rate);
|
rc = __set_clk_rate(device, cl, rate);
|
||||||
if (rc) {
|
if (rc)
|
||||||
dprintk(VIDC_ERR,
|
|
||||||
"Failed to set clock rate %lu %s: %d\n",
|
|
||||||
rate, cl->name, rc);
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(cl->name, "core_clk"))
|
if (!strcmp(cl->name, "core_clk"))
|
||||||
device->scaled_rate = rate;
|
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
|
* it to the lowest frequency possible
|
||||||
*/
|
*/
|
||||||
if (cl->has_scaling)
|
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) {
|
if (cl->has_mem_retention) {
|
||||||
rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_PERIPH);
|
rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_PERIPH);
|
||||||
|
|
Loading…
Add table
Reference in a new issue