Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7671f3b authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm_vidc: Add support for Cx ipeak limitation"

parents 5e9a3832 0c0cc0a2
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
@@ -122,6 +122,13 @@ static inline void msm_vidc_free_clock_table(
	res->clock_set.count = 0;
}

static inline void msm_vidc_free_cx_ipeak_context(
			struct msm_vidc_platform_resources *res)
{
	cx_ipeak_unregister(res->cx_ipeak_context);
	res->cx_ipeak_context = NULL;
}

void msm_vidc_free_platform_resources(
			struct msm_vidc_platform_resources *res)
{
@@ -132,6 +139,7 @@ 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);
	msm_vidc_free_cx_ipeak_context(res);
}

static int msm_vidc_load_reg_table(struct msm_vidc_platform_resources *res)
@@ -804,6 +812,48 @@ int read_platform_resources_from_drv_data(

}

static int msm_vidc_populate_cx_ipeak_context(
		struct msm_vidc_platform_resources *res)
{
	struct platform_device *pdev = res->pdev;
	int rc = 0;

	if (of_find_property(pdev->dev.of_node,
			"qcom,cx-ipeak-data", NULL)) {
		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_cx_ipeak;
	}

	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_cx_ipeak:
	return rc;
}

int read_platform_resources_from_dt(
		struct msm_vidc_platform_resources *res)
{
@@ -892,8 +942,16 @@ int read_platform_resources_from_dt(
				"Using fw-bias : %pa", &res->firmware_base);
	}

	rc = msm_vidc_populate_cx_ipeak_context(res);
	if (rc) {
		dprintk(VIDC_ERR,
			"Failed to setup cx-ipeak %d\n", rc);
		goto err_register_cx_ipeak;
	}

return rc;

err_register_cx_ipeak:
err_setup_legacy_cb:
	msm_vidc_free_allowed_clocks_table(res);
err_load_allowed_clocks_table:
+3 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/platform_device.h>
#include "msm_vidc.h"
#include <linux/soc/qcom/llcc-qcom.h>
#include "soc/qcom/cx_ipeak.h"

#define MAX_BUFFER_TYPES 32

@@ -200,6 +201,8 @@ struct msm_vidc_platform_resources {
	struct msm_vidc_mem_cdsp mem_cdsp;
	uint32_t vpu_ver;
	uint32_t fw_cycles;
	uint32_t clk_freq_threshold;
	struct cx_ipeak_client *cx_ipeak_context;
};

static inline bool is_iommu_present(struct msm_vidc_platform_resources *res)
+48 −8
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/workqueue.h>
#include <linux/platform_device.h>
#include <linux/soc/qcom/llcc-qcom.h>
#include <soc/qcom/cx_ipeak.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/socinfo.h>
#include <linux/soc/qcom/smem.h>
@@ -1383,6 +1384,49 @@ static enum hal_default_properties venus_hfi_get_default_properties(void *dev)
	return prop;
}

static int __set_clk_rate(struct venus_hfi_device *device,
		struct clock_info *cl, u64 rate)
{
	int rc = 0;
	u64 threshold_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 < threshold_freq && rate >= threshold_freq) {
		rc = cx_ipeak_update(ipeak, true);
		if (rc) {
			dprintk(VIDC_ERR,
				"cx_ipeak_update failed! ipeak %pK\n", ipeak);
			return rc;
		}
		dprintk(VIDC_PROF, "cx_ipeak_update: up, clk freq = %lu\n",
			device->clk_freq);
	}

	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);
		return rc;
	}

	device->clk_freq = rate;

	if (device->clk_freq >= threshold_freq && rate < threshold_freq) {
		rc = cx_ipeak_update(ipeak, false);
		if (rc) {
			dprintk(VIDC_ERR,
				"cx_ipeak_update failed! ipeak %pK\n", ipeak);
			return rc;
		}
		dprintk(VIDC_PROF, "cx_ipeak_update: down, clk freq = %lu\n",
			device->clk_freq);
	}

	return rc;
}

static int __set_clocks(struct venus_hfi_device *device, u32 freq)
{
	struct clock_info *cl;
@@ -1390,14 +1434,9 @@ static int __set_clocks(struct venus_hfi_device *device, u32 freq)

	venus_hfi_for_each_clock(device, cl) {
		if (cl->has_scaling) {/* has_scaling */
			device->clk_freq = freq;
			rc = clk_set_rate(cl->clk, freq);
			if (rc) {
				dprintk(VIDC_ERR,
					"Failed to set clock rate %u %s: %d %s\n",
					freq, cl->name, rc, __func__);
			rc = __set_clk_rate(device, cl, freq);
			if (rc)
				return rc;
			}

			trace_msm_vidc_perf_clock_scale(cl->name, freq);
			dprintk(VIDC_PROF, "Scaling clock %s to %u\n",
@@ -3956,7 +3995,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));

		rc = clk_set_flags(cl->clk, CLKFLAG_RETAIN_PERIPH);
		if (rc) {