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

Commit 48c732c0 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: vidc: Add a new governor for vmem"

parents 9dbcac2d df0c439a
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ Optional properties:
    supports hevc decoder = 0x0c000000
    supports hevc_hybrid encoder = 0x10000000
    supports hevc_hybrid decoder = 0x30000000
- qcom,imem-ab-tbl : video core frequency in Hz and corresponding imem ab value
  in kbps. The imem ab value corresponds to the clock frequency at which imem
  should operate for a particular video core frequency.
- qcom,reg-presets : list of offset-value pairs for registers to be written.
  The offsets are from the base offset specified in 'reg'. This is mainly
  used for QoS, VBIF, etc. presets for video.
@@ -153,6 +156,13 @@ Example:
			<72000 133330000 0x0c000000>, /* HEVC decoder VGA 60fps   */
			<36000 133330000 0x0c000000>, /* HEVC VGA 30 fps  */
			<36000 133330000 0x01000414>; /* Legacy encoder VGA 30 fps   */

		qcom,imem-ab-tbl =
			<75000000  1500000>, /* imem clk @ 75 Mhz  */
			<150000000 1500000>, /* imem clk @ 75 Mhz  */
			<355333333 2500000>, /* imem clk @ 170 Mhz */
			<533000000 6000000>; /* imem clk @ 320 Mhz */

		qcom,imem-size = <4096>;
		qcom,firmware-name = "venus";
		qcom,hfi-version = "3xx";
+73 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ module_param(debug, bool, 0644);
enum governor_mode {
	GOVERNOR_DDR,
	GOVERNOR_VMEM,
	GOVERNOR_VMEM_PLUS,
};

struct governor {
@@ -274,6 +275,36 @@ static int __bpp(enum hal_uncompressed_format f)
	}
}

static unsigned long __calculate_vmem_plus_ab(struct vidc_bus_vote_data *d)
{
	unsigned long i = 0, vmem_plus = 0;

	if (!d->imem_ab_tbl || !d->imem_ab_tbl_size) {
		vmem_plus = 1; /* Vote for the min ab value */
		goto exit;
	}

	/* Pick up vmem frequency based on venus core frequency */
	for (i = 0; i < d->imem_ab_tbl_size; i++) {
		if (d->imem_ab_tbl[i].core_freq == d->core_freq) {
			vmem_plus = d->imem_ab_tbl[i].imem_ab;
			break;
		}
	}

	/* Incase we get an unsupported freq throw a warning
	 * and set ab to the minimum value. */
	if (!vmem_plus) {
		vmem_plus = 1;
		dprintk(VIDC_WARN,
			"could not calculate vmem ab value due to core freq mismatch\n");
		WARN_ON(1);
	}

exit:
	return vmem_plus;
}

static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d,
		enum governor_mode gm) {
	/*
@@ -308,6 +339,8 @@ static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d,
			total;
	} ddr, vmem;

	unsigned long ret = 0;

	/* Decoder parameters setup */
	scenario = SCENARIO_WORST;

@@ -573,7 +606,21 @@ static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d,
		__dump(dump, ARRAY_SIZE(dump));
	}

	return kbps(fp_round((gm == GOVERNOR_DDR ? &ddr : &vmem)->total));
	switch (gm) {
	case GOVERNOR_DDR:
		ret = kbps(fp_round(ddr.total));
		break;
	case GOVERNOR_VMEM:
		ret = kbps(fp_round(vmem.total));
		break;
	case GOVERNOR_VMEM_PLUS:
		ret = __calculate_vmem_plus_ab(d);
		break;
	default:
		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
	}

	return ret;
}

static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d,
@@ -620,6 +667,8 @@ static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d,
			original_write, dpb_read, dpb_write, total;
	} ddr, vmem;

	unsigned long ret = 0;

	/* Encoder Parameters setup */
	scenario = SCENARIO_WORST;

@@ -961,7 +1010,21 @@ static unsigned long __calculate_encoder(struct vidc_bus_vote_data *d,
		__dump(dump, ARRAY_SIZE(dump));
	}

	return kbps(fp_round((gm == GOVERNOR_DDR ? &ddr : &vmem)->total));
	switch (gm) {
	case GOVERNOR_DDR:
		ret = kbps(fp_round(ddr.total));
		break;
	case GOVERNOR_VMEM:
		ret = kbps(fp_round(vmem.total));
		break;
	case GOVERNOR_VMEM_PLUS:
		ret = __calculate_vmem_plus_ab(d);
		break;
	default:
		dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
	}

	return ret;
}

static unsigned long __calculate(struct vidc_bus_vote_data *d,
@@ -1046,7 +1109,14 @@ static struct governor governors[] = {
			.event_handler = __event_handler,
		},
	},

	{
		.mode = GOVERNOR_VMEM_PLUS,
		.devfreq_gov = {
			.name = "msm-vidc-vmem+",
			.get_target_freq = __get_target_freq,
			.event_handler = __event_handler,
		},
	},
};

static int __init msm_vidc_bw_gov_init(void)
+11 −1
Original line number Diff line number Diff line
@@ -297,6 +297,7 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core)
	struct hfi_device *hdev;
	struct msm_vidc_inst *inst = NULL;
	struct vidc_bus_vote_data *vote_data = NULL;
	unsigned long core_freq = 0;

	if (!core) {
		dprintk(VIDC_ERR, "%s Invalid args: %p\n", __func__, core);
@@ -322,6 +323,9 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core)
		goto fail_alloc;
	}

	core_freq = call_hfi_op(hdev, get_core_clock_rate,
			hdev->hfi_device_data, 0);

	list_for_each_entry(inst, &core->instances, list) {
		int codec = 0, yuv = 0;

@@ -344,6 +348,12 @@ static int msm_comm_vote_bus(struct msm_vidc_core *core)
			vote_data[i].power_mode = VIDC_POWER_LOW;
		else
			vote_data[i].power_mode = VIDC_POWER_NORMAL;
		if (i == 0) {
			vote_data[i].imem_ab_tbl = core->resources.imem_ab_tbl;
			vote_data[i].imem_ab_tbl_size =
				core->resources.imem_ab_tbl_size;
			vote_data[i].core_freq = core_freq;
		}

		/*
		 * TODO: support for OBP-DBP split mode hasn't been yet
@@ -1984,7 +1994,7 @@ static unsigned long msm_comm_get_clock_rate(struct msm_vidc_core *core)
	}
	hdev = core->device;

	freq = call_hfi_op(hdev, get_core_clock_rate, hdev->hfi_device_data);
	freq = call_hfi_op(hdev, get_core_clock_rate, hdev->hfi_device_data, 1);
	dprintk(VIDC_DBG, "clock freq %ld\n", freq);

	return freq;
+48 −0
Original line number Diff line number Diff line
@@ -69,6 +69,12 @@ static inline void msm_vidc_free_freq_table(
	res->load_freq_tbl = NULL;
}

static inline void msm_vidc_free_imem_ab_table(
		struct msm_vidc_platform_resources *res)
{
	res->imem_ab_tbl = NULL;
}

static inline void msm_vidc_free_reg_table(
			struct msm_vidc_platform_resources *res)
{
@@ -227,6 +233,44 @@ err_qdss_addr_tbl:
	return rc;
}

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

	if (!of_find_property(pdev->dev.of_node, "qcom,imem-ab-tbl", NULL)) {
		/* optional property */
		dprintk(VIDC_DBG, "qcom,imem-freq-tbl not found\n");
		return 0;
	}

	num_elements = get_u32_array_num_elements(pdev, "qcom,imem-ab-tbl");
	num_elements /= (sizeof(*res->imem_ab_tbl) / sizeof(u32));
	if (!num_elements) {
		dprintk(VIDC_ERR, "no elements in imem ab table\n");
		return -EINVAL;
	}

	res->imem_ab_tbl = devm_kzalloc(&pdev->dev, num_elements *
			sizeof(*res->imem_ab_tbl), GFP_KERNEL);
	if (!res->imem_ab_tbl) {
		dprintk(VIDC_ERR, "Failed to alloc imem_ab_tbl\n");
		return -ENOMEM;
	}

	if (of_property_read_u32_array(pdev->dev.of_node,
		"qcom,imem-ab-tbl", (u32 *)res->imem_ab_tbl,
		num_elements * sizeof(*res->imem_ab_tbl) / sizeof(u32))) {
		dprintk(VIDC_ERR, "Failed to read imem_ab_tbl\n");
		msm_vidc_free_imem_ab_table(res);
		return -EINVAL;
	}

	res->imem_ab_tbl_size = num_elements;

	return 0;
}

static int msm_vidc_load_freq_table(struct msm_vidc_platform_resources *res)
{
	int rc = 0;
@@ -630,6 +674,10 @@ int read_platform_resources_from_dt(
		goto err_load_freq_table;
	}

	rc = msm_vidc_load_imem_ab_table(res);
	if (rc)
		dprintk(VIDC_WARN, "Failed to load freq table: %d\n", rc);

	rc = msm_vidc_load_qdss_table(res);
	if (rc)
		dprintk(VIDC_WARN, "Failed to load qdss reg table: %d\n", rc);
+7 −0
Original line number Diff line number Diff line
@@ -26,6 +26,11 @@ struct load_freq_table {
	u32 supported_codecs;
};

struct imem_ab_table {
	u32 core_freq;
	u32 imem_ab;
};

struct reg_value_pair {
	u32 reg;
	u32 value;
@@ -121,6 +126,8 @@ struct msm_vidc_platform_resources {
	uint32_t irq;
	struct load_freq_table *load_freq_tbl;
	uint32_t load_freq_tbl_size;
	struct imem_ab_table *imem_ab_tbl;
	u32 imem_ab_tbl_size;
	struct reg_set reg_set;
	struct addr_set qdss_addr_set;
	struct buffer_usage_set buffer_usage_set;
Loading