ソースを参照

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 <[email protected]>
Sebastian Dang 4 年 前
コミット
fb6421e3e9

+ 4 - 0
Android.mk

@@ -12,6 +12,7 @@ KBUILD_OPTIONS += MODNAME=msm_video
 KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM)
 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
@@ -27,6 +28,9 @@ LOCAL_MODULE_TAGS         := optional
 LOCAL_MODULE_DEBUG_ENABLE := true
 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)
 # BOARD_VENDOR_KERNEL_MODULES += $(LOCAL_MODULE_PATH)/$(LOCAL_MODULE)
 include $(DLKM_DIR)/Build_external_kernelmodule.mk

+ 2 - 0
Kbuild

@@ -2,6 +2,8 @@
 
 include $(VIDEO_ROOT)/config/waipio_video.conf
 
+KBUILD_CPPFLAGS += -DCONFIG_MSM_MMRM=1
+
 LINUXINCLUDE    += -include $(VIDEO_ROOT)/config/waipio_video.h
 
 LINUXINCLUDE    += -I$(VIDEO_ROOT)/driver/vidc/inc \

+ 3 - 0
driver/vidc/inc/msm_vidc_dt.h

@@ -8,6 +8,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/soc/qcom/llcc-qcom.h>
+#include <linux/soc/qcom/msm_mmrm.h>
 
 #include "msm_vidc_internal.h"
 
@@ -133,11 +134,13 @@ struct regulator_set {
 
 struct clock_info {
 	const char *name;
+	u32 clk_id;
 	struct clk *clk;
 	u32 count;
 	bool has_scaling;
 	bool has_mem_retention;
 	u64 prev;
+	struct mmrm_client *mmrm_client;
 };
 
 struct clock_set {

+ 20 - 1
driver/vidc/src/msm_vidc_dt.c

@@ -551,6 +551,7 @@ static int msm_vidc_load_clock_table(struct msm_vidc_core *core)
 	int rc = 0, num_clocks = 0, c = 0;
 	struct platform_device *pdev = core->pdev;
 	struct msm_vidc_dt *dt = core->dt;
+	int *clock_ids = NULL;
 	int *clock_props = NULL;
 	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;
 	}
 
+	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 *
 			sizeof(*clock_props), GFP_KERNEL);
 	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,
 				"clock-names", c, &vc->name);
 
+		vc->clk_id = clock_ids[c];
+
 		if (clock_props[c] & CLOCK_PROP_HAS_SCALING) {
 			vc->has_scaling = true;
 		} else {
@@ -976,4 +995,4 @@ int msm_vidc_init_dt(struct platform_device *pdev)
 		return rc;
 
 	return 0;
-}
+}

+ 12 - 0
driver/vidc/src/msm_vidc_power.c

@@ -20,6 +20,9 @@
 #define MSM_VIDC_MIN_UBWC_COMPRESSION_RATIO (1 << 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)
 {
 	struct msm_vidc_core* core;
@@ -408,6 +411,15 @@ int msm_vidc_set_clocks(struct msm_vidc_inst* inst)
 		__func__, rate, freq, increment, decrement);
 	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);
 	if (rc)
 		return rc;

+ 1 - 1
driver/vidc/src/msm_vidc_probe.c

@@ -492,5 +492,5 @@ static void __exit msm_vidc_exit(void)
 module_init(msm_vidc_init);
 module_exit(msm_vidc_exit);
 
-MODULE_SOFTDEP("pre: subsys-pil-tz");
+MODULE_SOFTDEP("pre: subsys-pil-tz msm-mmrm");
 MODULE_LICENSE("GPL v2");

+ 99 - 4
driver/vidc/src/venus_hfi.c

@@ -572,14 +572,22 @@ static int __set_clk_rate(struct msm_vidc_core *core,
 		struct clock_info *cl, u64 rate)
 {
 	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 */
 	if (rate == cl->prev)
 		return 0;
 
 	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) {
 		d_vpr_e("%s: Failed to set clock rate %llu %s: %d\n",
 			__func__, rate, cl->name, rc);
@@ -1301,6 +1309,83 @@ err_clk_get:
 	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,
 			int reset_index, enum reset_state state)
 {
@@ -1639,6 +1724,13 @@ static int __init_resources(struct msm_vidc_core *core)
 		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++) {
 		rc = __handle_reset_clk(core, i, INIT);
 		if (rc) {
@@ -1662,6 +1754,8 @@ static int __init_resources(struct msm_vidc_core *core)
 
 err_init_reset_clk:
 err_init_bus:
+	__deregister_mmrm(core);
+err_init_mmrm:
 	__deinit_clocks(core);
 err_init_clocks:
 	__deinit_regulators(core);
@@ -1672,6 +1766,7 @@ static void __deinit_resources(struct msm_vidc_core *core)
 {
 	__deinit_subcaches(core);
 	__deinit_bus(core);
+	__deregister_mmrm(core);
 	__deinit_clocks(core);
 	__deinit_regulators(core);
 }
@@ -1954,7 +2049,7 @@ static int __set_subcaches(struct msm_vidc_core *core)
 	rc = __iface_cmdq_write(core, core->packet);
 	if (rc)
 		goto err_fail_set_subacaches;
-		
+
 	venus_hfi_for_each_subcache(core, sinfo) {
 		if (sinfo->isactive) {
 			sinfo->isset = true;
@@ -1963,7 +2058,7 @@ static int __set_subcaches(struct msm_vidc_core *core)
 				sinfo->subcache->slice_size);
 		}
 	}
-	
+
 	core->dt->sys_cache_res_set = true;
 
 	return 0;