video: driver: Add mmrm api
Add mmrm apis to driver. Replace clk_set_rate with mmrm client set value. Scale branch clock values. Change-Id: I8ea35b668e4c7d6157c9c4f7120e6a4237cf65de Signed-off-by: Sebastian Dang <sebastiandang@codeaurora.org>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
a1c98e0e2f
commit
fb6421e3e9
@@ -12,6 +12,7 @@ KBUILD_OPTIONS += MODNAME=msm_video
|
|||||||
KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM)
|
KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM)
|
||||||
KBUILD_OPTIONS += $(VIDEO_SELECT)
|
KBUILD_OPTIONS += $(VIDEO_SELECT)
|
||||||
|
|
||||||
|
KBUILD_OPTIONS += KBUILD_EXTRA_SYMBOLS=$(shell pwd)/$(call intermediates-dir-for,DLKM,mmrm-module-symvers)/Module.symvers
|
||||||
###########################################################
|
###########################################################
|
||||||
|
|
||||||
DLKM_DIR := device/qcom/common/dlkm
|
DLKM_DIR := device/qcom/common/dlkm
|
||||||
@@ -27,6 +28,9 @@ LOCAL_MODULE_TAGS := optional
|
|||||||
LOCAL_MODULE_DEBUG_ENABLE := true
|
LOCAL_MODULE_DEBUG_ENABLE := true
|
||||||
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
LOCAL_MODULE_PATH := $(KERNEL_MODULES_OUT)
|
||||||
|
|
||||||
|
LOCAL_REQUIRED_MODULES := mmrm-module-symvers
|
||||||
|
LOCAL_ADDITIONAL_DEPENDENCIES := $(call intermediates-dir-for,DLKM,mmrm-module-symvers)/Module.symvers
|
||||||
|
|
||||||
# Include kp_module.ko in the /vendor/lib/modules (vendor.img)
|
# Include kp_module.ko in the /vendor/lib/modules (vendor.img)
|
||||||
# BOARD_VENDOR_KERNEL_MODULES += $(LOCAL_MODULE_PATH)/$(LOCAL_MODULE)
|
# BOARD_VENDOR_KERNEL_MODULES += $(LOCAL_MODULE_PATH)/$(LOCAL_MODULE)
|
||||||
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
include $(DLKM_DIR)/Build_external_kernelmodule.mk
|
||||||
|
2
Kbuild
2
Kbuild
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
include $(VIDEO_ROOT)/config/waipio_video.conf
|
include $(VIDEO_ROOT)/config/waipio_video.conf
|
||||||
|
|
||||||
|
KBUILD_CPPFLAGS += -DCONFIG_MSM_MMRM=1
|
||||||
|
|
||||||
LINUXINCLUDE += -include $(VIDEO_ROOT)/config/waipio_video.h
|
LINUXINCLUDE += -include $(VIDEO_ROOT)/config/waipio_video.h
|
||||||
|
|
||||||
LINUXINCLUDE += -I$(VIDEO_ROOT)/driver/vidc/inc \
|
LINUXINCLUDE += -I$(VIDEO_ROOT)/driver/vidc/inc \
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/soc/qcom/llcc-qcom.h>
|
#include <linux/soc/qcom/llcc-qcom.h>
|
||||||
|
#include <linux/soc/qcom/msm_mmrm.h>
|
||||||
|
|
||||||
#include "msm_vidc_internal.h"
|
#include "msm_vidc_internal.h"
|
||||||
|
|
||||||
@@ -133,11 +134,13 @@ struct regulator_set {
|
|||||||
|
|
||||||
struct clock_info {
|
struct clock_info {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
u32 clk_id;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
u32 count;
|
u32 count;
|
||||||
bool has_scaling;
|
bool has_scaling;
|
||||||
bool has_mem_retention;
|
bool has_mem_retention;
|
||||||
u64 prev;
|
u64 prev;
|
||||||
|
struct mmrm_client *mmrm_client;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct clock_set {
|
struct clock_set {
|
||||||
|
@@ -551,6 +551,7 @@ static int msm_vidc_load_clock_table(struct msm_vidc_core *core)
|
|||||||
int rc = 0, num_clocks = 0, c = 0;
|
int rc = 0, num_clocks = 0, c = 0;
|
||||||
struct platform_device *pdev = core->pdev;
|
struct platform_device *pdev = core->pdev;
|
||||||
struct msm_vidc_dt *dt = core->dt;
|
struct msm_vidc_dt *dt = core->dt;
|
||||||
|
int *clock_ids = NULL;
|
||||||
int *clock_props = NULL;
|
int *clock_props = NULL;
|
||||||
struct clock_set *clocks = &dt->clock_set;
|
struct clock_set *clocks = &dt->clock_set;
|
||||||
|
|
||||||
@@ -563,6 +564,22 @@ static int msm_vidc_load_clock_table(struct msm_vidc_core *core)
|
|||||||
goto err_load_clk_table_fail;
|
goto err_load_clk_table_fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clock_ids = devm_kzalloc(&pdev->dev, num_clocks *
|
||||||
|
sizeof(*clock_ids), GFP_KERNEL);
|
||||||
|
if (!clock_ids) {
|
||||||
|
d_vpr_e("No memory to read clock ids\n");
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err_load_clk_table_fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = of_property_read_u32_array(pdev->dev.of_node,
|
||||||
|
"clock-ids", clock_ids,
|
||||||
|
num_clocks);
|
||||||
|
if (rc) {
|
||||||
|
d_vpr_e("Failed to read clock ids: %d\n", rc);
|
||||||
|
goto err_load_clk_prop_fail;
|
||||||
|
}
|
||||||
|
|
||||||
clock_props = devm_kzalloc(&pdev->dev, num_clocks *
|
clock_props = devm_kzalloc(&pdev->dev, num_clocks *
|
||||||
sizeof(*clock_props), GFP_KERNEL);
|
sizeof(*clock_props), GFP_KERNEL);
|
||||||
if (!clock_props) {
|
if (!clock_props) {
|
||||||
@@ -596,6 +613,8 @@ static int msm_vidc_load_clock_table(struct msm_vidc_core *core)
|
|||||||
of_property_read_string_index(pdev->dev.of_node,
|
of_property_read_string_index(pdev->dev.of_node,
|
||||||
"clock-names", c, &vc->name);
|
"clock-names", c, &vc->name);
|
||||||
|
|
||||||
|
vc->clk_id = clock_ids[c];
|
||||||
|
|
||||||
if (clock_props[c] & CLOCK_PROP_HAS_SCALING) {
|
if (clock_props[c] & CLOCK_PROP_HAS_SCALING) {
|
||||||
vc->has_scaling = true;
|
vc->has_scaling = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -976,4 +995,4 @@ int msm_vidc_init_dt(struct platform_device *pdev)
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,9 @@
|
|||||||
#define MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO (1 << 16)
|
#define MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO (1 << 16)
|
||||||
#define MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO (5 << 16)
|
#define MSM_VIDC_MAX_UBWC_COMPRESSION_RATIO (5 << 16)
|
||||||
|
|
||||||
|
/* TODO: Move to dtsi OR use source clock instead of branch clock.*/
|
||||||
|
#define MSM_VIDC_CLOCK_SOURCE_SCALING_RATIO 3
|
||||||
|
|
||||||
u64 msm_vidc_max_freq(struct msm_vidc_inst *inst)
|
u64 msm_vidc_max_freq(struct msm_vidc_inst *inst)
|
||||||
{
|
{
|
||||||
struct msm_vidc_core* core;
|
struct msm_vidc_core* core;
|
||||||
@@ -408,6 +411,15 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst)
|
|||||||
__func__, rate, freq, increment, decrement);
|
__func__, rate, freq, increment, decrement);
|
||||||
mutex_unlock(&core->lock);
|
mutex_unlock(&core->lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This conversion is necessary since we are scaling clock values based on
|
||||||
|
* the branch clock. However, mmrm driver expects source clock to be registered
|
||||||
|
* and used for scaling.
|
||||||
|
* TODO: Remove this scaling if using source clock instead of branch clock.
|
||||||
|
*/
|
||||||
|
rate = rate * MSM_VIDC_CLOCK_SOURCE_SCALING_RATIO;
|
||||||
|
i_vpr_h(inst, "%s: scaled clock rate %lu\n", __func__, rate);
|
||||||
|
|
||||||
rc = venus_hfi_scale_clocks(inst, rate);
|
rc = venus_hfi_scale_clocks(inst, rate);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
@@ -492,5 +492,5 @@ static void __exit msm_vidc_exit(void)
|
|||||||
module_init(msm_vidc_init);
|
module_init(msm_vidc_init);
|
||||||
module_exit(msm_vidc_exit);
|
module_exit(msm_vidc_exit);
|
||||||
|
|
||||||
MODULE_SOFTDEP("pre: subsys-pil-tz");
|
MODULE_SOFTDEP("pre: subsys-pil-tz msm-mmrm");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@@ -572,14 +572,22 @@ static int __set_clk_rate(struct msm_vidc_core *core,
|
|||||||
struct clock_info *cl, u64 rate)
|
struct clock_info *cl, u64 rate)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct clk *clk = cl->clk;
|
// struct clk *clk = cl->clk;
|
||||||
|
struct mmrm_client_data client_data;
|
||||||
|
struct mmrm_client *client = cl->mmrm_client;
|
||||||
|
|
||||||
|
/* not registered */
|
||||||
|
if (!client)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/* bail early if requested clk rate is not changed */
|
/* bail early if requested clk rate is not changed */
|
||||||
if (rate == cl->prev)
|
if (rate == cl->prev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
d_vpr_p("Scaling clock %s to %llu, prev %llu\n", cl->name, rate, cl->prev);
|
d_vpr_p("Scaling clock %s to %llu, prev %llu\n", cl->name, rate, cl->prev);
|
||||||
rc = clk_set_rate(clk, rate);
|
/* TODO: Set num_hw_blocks based on encoder or decoder */
|
||||||
|
memset(&client_data, 0, sizeof(client_data));
|
||||||
|
rc = mmrm_client_set_value(client, &client_data, rate);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
d_vpr_e("%s: Failed to set clock rate %llu %s: %d\n",
|
d_vpr_e("%s: Failed to set clock rate %llu %s: %d\n",
|
||||||
__func__, rate, cl->name, rc);
|
__func__, rate, cl->name, rc);
|
||||||
@@ -1301,6 +1309,83 @@ err_clk_get:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __deregister_mmrm(struct msm_vidc_core *core)
|
||||||
|
{
|
||||||
|
struct clock_info *cl;
|
||||||
|
|
||||||
|
venus_hfi_for_each_clock(core, cl) {
|
||||||
|
if (cl->has_scaling && cl->mmrm_client) {
|
||||||
|
mmrm_client_deregister(cl->mmrm_client);
|
||||||
|
cl->mmrm_client = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __register_mmrm(struct msm_vidc_core *core)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct clock_info *cl;
|
||||||
|
|
||||||
|
venus_hfi_for_each_clock(core, cl) {
|
||||||
|
struct mmrm_client_desc desc;
|
||||||
|
char *name = (char *)desc.client_info.desc.name;
|
||||||
|
|
||||||
|
// TODO: set notifier data vals
|
||||||
|
struct mmrm_client_notifier_data notifier_data = {
|
||||||
|
MMRM_CLIENT_RESOURCE_VALUE_CHANGE,
|
||||||
|
{{0, 0}},
|
||||||
|
NULL};
|
||||||
|
|
||||||
|
// TODO: add callback fn
|
||||||
|
desc.notifier_callback_fn = NULL;
|
||||||
|
|
||||||
|
if (!cl->has_scaling)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (IS_ERR_OR_NULL(cl->clk)) {
|
||||||
|
d_vpr_e("%s: Invalid clock: %s\n", __func__, cl->name);
|
||||||
|
rc = PTR_ERR(cl->clk) ? PTR_ERR(cl->clk) : -EINVAL;
|
||||||
|
goto err_register_mmrm;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc.client_type = MMRM_CLIENT_CLOCK;
|
||||||
|
desc.client_info.desc.client_domain = MMRM_CLIENT_DOMAIN_VIDEO;
|
||||||
|
desc.client_info.desc.client_id = cl->clk_id;
|
||||||
|
strlcpy(name, cl->name, sizeof(desc.client_info.desc.name));
|
||||||
|
desc.client_info.desc.clk = cl->clk;
|
||||||
|
desc.priority = MMRM_CLIENT_PRIOR_LOW;
|
||||||
|
desc.pvt_data = notifier_data.pvt_data;
|
||||||
|
|
||||||
|
d_vpr_h("%s: domain(%d) cid(%d) name(%s) clk(%pK)\n",
|
||||||
|
__func__,
|
||||||
|
desc.client_info.desc.client_domain,
|
||||||
|
desc.client_info.desc.client_id,
|
||||||
|
desc.client_info.desc.name,
|
||||||
|
desc.client_info.desc.clk);
|
||||||
|
|
||||||
|
d_vpr_h("%s: type(%d) pri(%d) pvt(%pK) notifier(%pK)\n",
|
||||||
|
__func__,
|
||||||
|
desc.client_type,
|
||||||
|
desc.priority,
|
||||||
|
desc.pvt_data,
|
||||||
|
desc.notifier_callback_fn);
|
||||||
|
|
||||||
|
cl->mmrm_client = mmrm_client_register(&desc);
|
||||||
|
if (!cl->mmrm_client) {
|
||||||
|
d_vpr_e("%s: Failed to register clk(%s): %d\n",
|
||||||
|
__func__, cl->name, rc);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto err_register_mmrm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_register_mmrm:
|
||||||
|
__deregister_mmrm(core);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int __handle_reset_clk(struct msm_vidc_core *core,
|
static int __handle_reset_clk(struct msm_vidc_core *core,
|
||||||
int reset_index, enum reset_state state)
|
int reset_index, enum reset_state state)
|
||||||
{
|
{
|
||||||
@@ -1639,6 +1724,13 @@ static int __init_resources(struct msm_vidc_core *core)
|
|||||||
goto err_init_clocks;
|
goto err_init_clocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = __register_mmrm(core);
|
||||||
|
if (rc) {
|
||||||
|
d_vpr_e("Failed to register mmrm\n");
|
||||||
|
rc = -ENODEV;
|
||||||
|
goto err_init_mmrm;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < core->dt->reset_set.count; i++) {
|
for (i = 0; i < core->dt->reset_set.count; i++) {
|
||||||
rc = __handle_reset_clk(core, i, INIT);
|
rc = __handle_reset_clk(core, i, INIT);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -1662,6 +1754,8 @@ static int __init_resources(struct msm_vidc_core *core)
|
|||||||
|
|
||||||
err_init_reset_clk:
|
err_init_reset_clk:
|
||||||
err_init_bus:
|
err_init_bus:
|
||||||
|
__deregister_mmrm(core);
|
||||||
|
err_init_mmrm:
|
||||||
__deinit_clocks(core);
|
__deinit_clocks(core);
|
||||||
err_init_clocks:
|
err_init_clocks:
|
||||||
__deinit_regulators(core);
|
__deinit_regulators(core);
|
||||||
@@ -1672,6 +1766,7 @@ static void __deinit_resources(struct msm_vidc_core *core)
|
|||||||
{
|
{
|
||||||
__deinit_subcaches(core);
|
__deinit_subcaches(core);
|
||||||
__deinit_bus(core);
|
__deinit_bus(core);
|
||||||
|
__deregister_mmrm(core);
|
||||||
__deinit_clocks(core);
|
__deinit_clocks(core);
|
||||||
__deinit_regulators(core);
|
__deinit_regulators(core);
|
||||||
}
|
}
|
||||||
@@ -1954,7 +2049,7 @@ static int __set_subcaches(struct msm_vidc_core *core)
|
|||||||
rc = __iface_cmdq_write(core, core->packet);
|
rc = __iface_cmdq_write(core, core->packet);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_fail_set_subacaches;
|
goto err_fail_set_subacaches;
|
||||||
|
|
||||||
venus_hfi_for_each_subcache(core, sinfo) {
|
venus_hfi_for_each_subcache(core, sinfo) {
|
||||||
if (sinfo->isactive) {
|
if (sinfo->isactive) {
|
||||||
sinfo->isset = true;
|
sinfo->isset = true;
|
||||||
@@ -1963,7 +2058,7 @@ static int __set_subcaches(struct msm_vidc_core *core)
|
|||||||
sinfo->subcache->slice_size);
|
sinfo->subcache->slice_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
core->dt->sys_cache_res_set = true;
|
core->dt->sys_cache_res_set = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user