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:
Sebastian Dang
2021-02-24 09:06:56 -08:00
committed by Gerrit - the friendly Code Review server
parent a1c98e0e2f
commit fb6421e3e9
7 changed files with 141 additions and 6 deletions

View File

@@ -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
View File

@@ -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 \

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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;

View File

@@ -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");

View File

@@ -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);
} }