linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] Qualcomm Venus enablement for SDM630/636/660
@ 2020-09-26 12:54 kholk11
  2020-09-26 12:54 ` [PATCH 1/3] media: venus: pm_helper: Commonize v3/v4 pmdomains and clocks management kholk11
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: kholk11 @ 2020-09-26 12:54 UTC (permalink / raw)
  To: stanimir.varbanov
  Cc: agross, bjorn.andersson, linux-media, kholk11, marijns95,
	konradybcio, martin.botka1, linux-arm-msm, phone-devel,
	linux-kernel

From: AngeloGioacchino Del Regno <kholk11@gmail.com>

In this patch series, I am enabling the Venus video (enc/dec)oding
functionality on SDM630, SDM636, SDM660 and their SDA variants.

To reliably achieve this, commonizing most of the v3/v4 pm_helper
functions (while keeping compatibility with the previous bindings)
seemed to be totally legit, as (almost) the whole logic that's been
introduced in the v4 helpers does actually apply to all (in my knowledge)
of the SoCs that are currently needing the v3 ops to *at least*
optimize the power consumption while using this remote processor.

In the specific case of the SDM630/660 family, this was necessary in
order to correctly bring up the clocks required by the Venus subsystem
without using particular hacks in the clock drivers.
This patch series achieves functional video encoding and decoding on
the SDM630/660 family of SoCs.

The testing was done with the following methodology:
 - Boot the system (libc with GNOME DE on Wayland)
 - Upload a 720p mp4 h264 sample video file [1] on the device
 - Open gnome-terminal and use FFMPEG to transcode:
   1. Software H264 decoder to Venus HW encoder (wow it's so fast!)
   2. Venus HW decoder to Software H264 decoder
 - Download the resulting files on a PC and start playback
   - Playing back both files works

This patch series has been tested against the following devices:
 - Sony Xperia XA2 Ultra (SDM630 Nile Discovery)
 - Sony Xperia 10        (SDM630 Ganges Kirin)

[1] https://dvdloc8.com/clip.php?movieid=12167&clipid=1

AngeloGioacchino Del Regno (3):
  media: venus: pm_helper: Commonize v3/v4 pmdomains and clocks
    management
  media: venus: core: Add sdm660 DT compatible and resource struct
  media: dt-bindings: media: venus: Add sdm660 DT schema

 .../bindings/media/qcom,sdm660-venus.yaml     | 153 +++++
 drivers/media/platform/qcom/venus/core.c      |  68 +++
 .../media/platform/qcom/venus/pm_helpers.c    | 525 +++++++++---------
 3 files changed, 498 insertions(+), 248 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml

-- 
2.28.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/3] media: venus: pm_helper: Commonize v3/v4 pmdomains and clocks management
  2020-09-26 12:54 [PATCH 0/3] Qualcomm Venus enablement for SDM630/636/660 kholk11
@ 2020-09-26 12:54 ` kholk11
  2020-09-26 16:16   ` kernel test robot
  2020-09-26 12:54 ` [PATCH 2/3] media: venus: core: Add sdm660 DT compatible and resource struct kholk11
  2020-09-26 12:54 ` [PATCH 3/3] media: dt-bindings: media: venus: Add sdm660 DT schema kholk11
  2 siblings, 1 reply; 5+ messages in thread
From: kholk11 @ 2020-09-26 12:54 UTC (permalink / raw)
  To: stanimir.varbanov
  Cc: agross, bjorn.andersson, linux-media, kholk11, marijns95,
	konradybcio, martin.botka1, linux-arm-msm, phone-devel,
	linux-kernel

From: AngeloGioacchino Del Regno <kholk11@gmail.com>

Most of the SoCs that are featuring Venus HFI3 also need to scale the
clocks and also need to bringup power domains, very very similarly to
SoCs (like SDM845 and SC7180) featuring HFI4 Venus, which has *yes*
differences, but not in that specific "field".

So, reduce code duplication (most v3 functions are a subset of v4),
achieve better power consumption and slightly simplify the code by
merging the v3 and v4 functions that are responsible for bringing
up and tearing down clocks and pm domains.

While at it, also add a small quirk to the video encoder functions:
since not all SoCs have got two (or more) vcodec instances, it is
incorrect to *always* manage vcodec1_clks (and itsrelative pmdomain)
there.
To get video encoders working fine - and to avoid duplicating clocks
and pmdomains declarations between vcodec0 and 1 - check for the
number of vcodecs and currently assume that:
  1. If Venus has only one vcodec (vcodec_num), then we use vcodec0
     for both video decoder and encoder;
  2. If it has more than one vcodec, then we use vcodec1 for the
     video encoder and vcodec0 for the decoder.

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
---
 .../media/platform/qcom/venus/pm_helpers.c    | 525 +++++++++---------
 1 file changed, 277 insertions(+), 248 deletions(-)

diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c
index 57877eacecf0..fda480b26636 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -130,6 +130,100 @@ static void vcodec_clks_disable(struct venus_core *core, struct clk **clks)
 		clk_disable_unprepare(clks[i]);
 }
 
+static int vcodec_domains_get(struct device *dev)
+{
+	int ret;
+	struct opp_table *opp_table;
+	struct device **opp_virt_dev;
+	struct venus_core *core = dev_get_drvdata(dev);
+	const struct venus_resources *res = core->res;
+	struct device *pd;
+	unsigned int i;
+
+	if (!res->vcodec_pmdomains_num)
+		goto skip_pmdomains;
+
+	for (i = 0; i < res->vcodec_pmdomains_num; i++) {
+		pd = dev_pm_domain_attach_by_name(dev,
+						  res->vcodec_pmdomains[i]);
+		if (IS_ERR(pd))
+			return PTR_ERR(pd);
+		core->pmdomains[i] = pd;
+	}
+
+	core->pd_dl_venus = device_link_add(dev, core->pmdomains[0],
+					    DL_FLAG_PM_RUNTIME |
+					    DL_FLAG_STATELESS |
+					    DL_FLAG_RPM_ACTIVE);
+	if (!core->pd_dl_venus)
+		return -ENODEV;
+
+skip_pmdomains:
+	if (!core->has_opp_table)
+		return 0;
+
+	/* Attach the power domain for setting performance state */
+	opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev);
+	if (IS_ERR(opp_table)) {
+		ret = PTR_ERR(opp_table);
+		goto opp_attach_err;
+	}
+
+	core->opp_pmdomain = *opp_virt_dev;
+	core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain,
+					     DL_FLAG_RPM_ACTIVE |
+					     DL_FLAG_PM_RUNTIME |
+					     DL_FLAG_STATELESS);
+	if (!core->opp_dl_venus) {
+		ret = -ENODEV;
+		goto opp_dl_add_err;
+	}
+
+	return 0;
+
+opp_dl_add_err:
+	dev_pm_domain_detach(core->opp_pmdomain, true);
+opp_attach_err:
+	if (core->pd_dl_venus) {
+		device_link_del(core->pd_dl_venus);
+		for (i = 0; i < res->vcodec_pmdomains_num; i++) {
+			if (IS_ERR_OR_NULL(core->pmdomains[i]))
+				continue;
+			dev_pm_domain_detach(core->pmdomains[i], true);
+		}
+	}
+	return ret;
+}
+
+static void vcodec_domains_put(struct device *dev)
+{
+	struct venus_core *core = dev_get_drvdata(dev);
+	const struct venus_resources *res = core->res;
+	unsigned int i;
+
+	if (!res->vcodec_pmdomains_num)
+		goto skip_pmdomains;
+
+	if (core->pd_dl_venus)
+		device_link_del(core->pd_dl_venus);
+
+	for (i = 0; i < res->vcodec_pmdomains_num; i++) {
+		if (IS_ERR_OR_NULL(core->pmdomains[i]))
+			continue;
+		dev_pm_domain_detach(core->pmdomains[i], true);
+	}
+
+skip_pmdomains:
+	if (!core->has_opp_table)
+		return;
+
+	if (core->opp_dl_venus)
+		device_link_del(core->opp_dl_venus);
+
+	dev_pm_domain_detach(core->opp_pmdomain, true);
+}
+
+
 static u32 load_per_instance(struct venus_inst *inst)
 {
 	u32 mbs;
@@ -308,19 +402,17 @@ vcodec_control_v3(struct venus_core *core, u32 session_type, bool enable)
 		writel(1, ctrl);
 }
 
-static int vdec_get_v3(struct device *dev)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
-
-	return vcodec_clks_get(core, dev, core->vcodec0_clks,
-			       core->res->vcodec0_clks);
-}
-
 static int vdec_power_v3(struct device *dev, int on)
 {
 	struct venus_core *core = dev_get_drvdata(dev);
 	int ret = 0;
 
+	if (!legacy_binding && on == POWER_ON) {
+		ret = pm_runtime_get_sync(core->pmdomains[1]);
+		if (ret < 0)
+			return ret;
+	}
+
 	vcodec_control_v3(core, VIDC_SESSION_TYPE_DEC, true);
 
 	if (on == POWER_ON)
@@ -330,40 +422,202 @@ static int vdec_power_v3(struct device *dev, int on)
 
 	vcodec_control_v3(core, VIDC_SESSION_TYPE_DEC, false);
 
-	return ret;
-}
-
-static int venc_get_v3(struct device *dev)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
+	if (!legacy_binding && on == POWER_OFF) {
+		ret = pm_runtime_put_sync(core->pmdomains[1]);
+		if (ret < 0)
+			return ret;
+	}
 
-	return vcodec_clks_get(core, dev, core->vcodec1_clks,
-			       core->res->vcodec1_clks);
+	return ret;
 }
 
 static int venc_power_v3(struct device *dev, int on)
 {
 	struct venus_core *core = dev_get_drvdata(dev);
-	int ret = 0;
+	const struct venus_resources *res = core->res;
+	struct clk **vcodec_clks;
+	int idx, ret = 0;
+
+	/*
+	 * Some SoCs have got only one vcodec instance and all of them
+	 * have got one global and one pmdomain per instance.
+	 */
+	if (res->vcodec_num > 1) {
+		vcodec_clks = core->vcodec1_clks;
+		idx = 2;
+	} else {
+		vcodec_clks = core->vcodec0_clks;
+		idx = 1;
+	}
+
+	if (!legacy_binding && on == POWER_ON) {
+		ret = pm_runtime_get_sync(core->pmdomains[idx]);
+		if (ret < 0)
+			return ret;
+	}
 
 	vcodec_control_v3(core, VIDC_SESSION_TYPE_ENC, true);
 
 	if (on == POWER_ON)
-		ret = vcodec_clks_enable(core, core->vcodec1_clks);
+		ret = vcodec_clks_enable(core, vcodec_clks);
 	else
-		vcodec_clks_disable(core, core->vcodec1_clks);
+		vcodec_clks_disable(core, vcodec_clks);
 
 	vcodec_control_v3(core, VIDC_SESSION_TYPE_ENC, false);
 
+	if (!legacy_binding && on == POWER_OFF) {
+		ret = pm_runtime_put_sync(core->pmdomains[idx]);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret;
+}
+
+static int core_get_v4(struct device *dev)
+{
+	struct venus_core *core = dev_get_drvdata(dev);
+	const struct venus_resources *res = core->res;
+	int ret;
+
+	ret = core_clks_get(core);
+	if (ret)
+		return ret;
+
+	if (!res->vcodec_pmdomains_num)
+		legacy_binding = true;
+
+	dev_info(dev, "%s legacy binding\n", legacy_binding ? "" : "non");
+
+	ret = vcodec_clks_get(core, dev, core->vcodec0_clks, res->vcodec0_clks);
+	if (ret)
+		return ret;
+
+	if (core->vcodec1_clks) {
+		ret = vcodec_clks_get(core, dev,
+				      core->vcodec1_clks, res->vcodec1_clks);
+		if (ret)
+			return ret;
+	}
+
+	if (legacy_binding)
+		return 0;
+
+	core->opp_table = dev_pm_opp_set_clkname(dev, "core");
+	if (IS_ERR(core->opp_table))
+		return PTR_ERR(core->opp_table);
+
+	if (core->res->opp_pmdomain) {
+		ret = dev_pm_opp_of_add_table(dev);
+		if (!ret) {
+			core->has_opp_table = true;
+		} else if (ret != -ENODEV) {
+			dev_err(dev, "invalid OPP table in device tree\n");
+			dev_pm_opp_put_clkname(core->opp_table);
+			return ret;
+		}
+	}
+
+	ret = vcodec_domains_get(dev);
+	if (ret) {
+		if (core->has_opp_table)
+			dev_pm_opp_of_remove_table(dev);
+		dev_pm_opp_put_clkname(core->opp_table);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void core_put_v4(struct device *dev)
+{
+	struct venus_core *core = dev_get_drvdata(dev);
+
+	if (legacy_binding)
+		return;
+
+	vcodec_domains_put(dev);
+
+	if (core->has_opp_table)
+		dev_pm_opp_of_remove_table(dev);
+	if (core->opp_table)
+		dev_pm_opp_put_clkname(core->opp_table);
+
+}
+
+static int core_power_v4(struct device *dev, int on)
+{
+	struct venus_core *core = dev_get_drvdata(dev);
+	int ret = 0;
+
+	if (on == POWER_ON) {
+		ret = core_clks_enable(core);
+	} else {
+		/* Drop the performance state vote */
+		if (core->opp_pmdomain)
+			dev_pm_opp_set_rate(dev, 0);
+
+		core_clks_disable(core);
+	}
+
 	return ret;
 }
 
+static int vdec_get_v4(struct device *dev)
+{
+	struct venus_core *core = dev_get_drvdata(dev);
+
+	if (!legacy_binding)
+		return 0;
+
+	return vcodec_clks_get(core, dev, core->vcodec0_clks,
+			       core->res->vcodec0_clks);
+}
+
+static void vdec_put_v4(struct device *dev)
+{
+	struct venus_core *core = dev_get_drvdata(dev);
+	unsigned int i;
+
+	if (!legacy_binding)
+		return;
+
+	for (i = 0; i < core->res->vcodec_clks_num; i++)
+		core->vcodec0_clks[i] = NULL;
+}
+
+static int venc_get_v4(struct device *dev)
+{
+	struct venus_core *core = dev_get_drvdata(dev);
+
+	if (!legacy_binding)
+		return 0;
+
+	return vcodec_clks_get(core, dev, core->vcodec1_clks,
+			       core->res->vcodec1_clks);
+}
+
+static void venc_put_v4(struct device *dev)
+{
+	struct venus_core *core = dev_get_drvdata(dev);
+	unsigned int i;
+
+	if (!legacy_binding)
+		return;
+
+	for (i = 0; i < core->res->vcodec_clks_num; i++)
+		core->vcodec1_clks[i] = NULL;
+}
+
 static const struct venus_pm_ops pm_ops_v3 = {
-	.core_get = core_get_v1,
-	.core_power = core_power_v1,
-	.vdec_get = vdec_get_v3,
+	.core_get = core_get_v4,
+	.core_put = core_put_v4,
+	.core_power = core_power_v4,
+	.vdec_get = vdec_get_v4,
+	.vdec_put = vdec_put_v4,
 	.vdec_power = vdec_power_v3,
-	.venc_get = venc_get_v3,
+	.venc_get = venc_get_v4,
+	.venc_put = venc_put_v4,
 	.venc_power = venc_power_v3,
 	.load_scale = load_scale_v1,
 };
@@ -652,29 +906,6 @@ static int coreid_power_v4(struct venus_inst *inst, int on)
 	return ret;
 }
 
-static int vdec_get_v4(struct device *dev)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
-
-	if (!legacy_binding)
-		return 0;
-
-	return vcodec_clks_get(core, dev, core->vcodec0_clks,
-			       core->res->vcodec0_clks);
-}
-
-static void vdec_put_v4(struct device *dev)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
-	unsigned int i;
-
-	if (!legacy_binding)
-		return;
-
-	for (i = 0; i < core->res->vcodec_clks_num; i++)
-		core->vcodec0_clks[i] = NULL;
-}
-
 static int vdec_power_v4(struct device *dev, int on)
 {
 	struct venus_core *core = dev_get_drvdata(dev);
@@ -697,29 +928,6 @@ static int vdec_power_v4(struct device *dev, int on)
 	return ret;
 }
 
-static int venc_get_v4(struct device *dev)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
-
-	if (!legacy_binding)
-		return 0;
-
-	return vcodec_clks_get(core, dev, core->vcodec1_clks,
-			       core->res->vcodec1_clks);
-}
-
-static void venc_put_v4(struct device *dev)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
-	unsigned int i;
-
-	if (!legacy_binding)
-		return;
-
-	for (i = 0; i < core->res->vcodec_clks_num; i++)
-		core->vcodec1_clks[i] = NULL;
-}
-
 static int venc_power_v4(struct device *dev, int on)
 {
 	struct venus_core *core = dev_get_drvdata(dev);
@@ -742,185 +950,6 @@ static int venc_power_v4(struct device *dev, int on)
 	return ret;
 }
 
-static int vcodec_domains_get(struct device *dev)
-{
-	int ret;
-	struct opp_table *opp_table;
-	struct device **opp_virt_dev;
-	struct venus_core *core = dev_get_drvdata(dev);
-	const struct venus_resources *res = core->res;
-	struct device *pd;
-	unsigned int i;
-
-	if (!res->vcodec_pmdomains_num)
-		goto skip_pmdomains;
-
-	for (i = 0; i < res->vcodec_pmdomains_num; i++) {
-		pd = dev_pm_domain_attach_by_name(dev,
-						  res->vcodec_pmdomains[i]);
-		if (IS_ERR(pd))
-			return PTR_ERR(pd);
-		core->pmdomains[i] = pd;
-	}
-
-	core->pd_dl_venus = device_link_add(dev, core->pmdomains[0],
-					    DL_FLAG_PM_RUNTIME |
-					    DL_FLAG_STATELESS |
-					    DL_FLAG_RPM_ACTIVE);
-	if (!core->pd_dl_venus)
-		return -ENODEV;
-
-skip_pmdomains:
-	if (!core->has_opp_table)
-		return 0;
-
-	/* Attach the power domain for setting performance state */
-	opp_table = dev_pm_opp_attach_genpd(dev, res->opp_pmdomain, &opp_virt_dev);
-	if (IS_ERR(opp_table)) {
-		ret = PTR_ERR(opp_table);
-		goto opp_attach_err;
-	}
-
-	core->opp_pmdomain = *opp_virt_dev;
-	core->opp_dl_venus = device_link_add(dev, core->opp_pmdomain,
-					     DL_FLAG_RPM_ACTIVE |
-					     DL_FLAG_PM_RUNTIME |
-					     DL_FLAG_STATELESS);
-	if (!core->opp_dl_venus) {
-		ret = -ENODEV;
-		goto opp_dl_add_err;
-	}
-
-	return 0;
-
-opp_dl_add_err:
-	dev_pm_domain_detach(core->opp_pmdomain, true);
-opp_attach_err:
-	if (core->pd_dl_venus) {
-		device_link_del(core->pd_dl_venus);
-		for (i = 0; i < res->vcodec_pmdomains_num; i++) {
-			if (IS_ERR_OR_NULL(core->pmdomains[i]))
-				continue;
-			dev_pm_domain_detach(core->pmdomains[i], true);
-		}
-	}
-	return ret;
-}
-
-static void vcodec_domains_put(struct device *dev)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
-	const struct venus_resources *res = core->res;
-	unsigned int i;
-
-	if (!res->vcodec_pmdomains_num)
-		goto skip_pmdomains;
-
-	if (core->pd_dl_venus)
-		device_link_del(core->pd_dl_venus);
-
-	for (i = 0; i < res->vcodec_pmdomains_num; i++) {
-		if (IS_ERR_OR_NULL(core->pmdomains[i]))
-			continue;
-		dev_pm_domain_detach(core->pmdomains[i], true);
-	}
-
-skip_pmdomains:
-	if (!core->has_opp_table)
-		return;
-
-	if (core->opp_dl_venus)
-		device_link_del(core->opp_dl_venus);
-
-	dev_pm_domain_detach(core->opp_pmdomain, true);
-}
-
-static int core_get_v4(struct device *dev)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
-	const struct venus_resources *res = core->res;
-	int ret;
-
-	ret = core_clks_get(core);
-	if (ret)
-		return ret;
-
-	if (!res->vcodec_pmdomains_num)
-		legacy_binding = true;
-
-	dev_info(dev, "%s legacy binding\n", legacy_binding ? "" : "non");
-
-	ret = vcodec_clks_get(core, dev, core->vcodec0_clks, res->vcodec0_clks);
-	if (ret)
-		return ret;
-
-	ret = vcodec_clks_get(core, dev, core->vcodec1_clks, res->vcodec1_clks);
-	if (ret)
-		return ret;
-
-	if (legacy_binding)
-		return 0;
-
-	core->opp_table = dev_pm_opp_set_clkname(dev, "core");
-	if (IS_ERR(core->opp_table))
-		return PTR_ERR(core->opp_table);
-
-	if (core->res->opp_pmdomain) {
-		ret = dev_pm_opp_of_add_table(dev);
-		if (!ret) {
-			core->has_opp_table = true;
-		} else if (ret != -ENODEV) {
-			dev_err(dev, "invalid OPP table in device tree\n");
-			dev_pm_opp_put_clkname(core->opp_table);
-			return ret;
-		}
-	}
-
-	ret = vcodec_domains_get(dev);
-	if (ret) {
-		if (core->has_opp_table)
-			dev_pm_opp_of_remove_table(dev);
-		dev_pm_opp_put_clkname(core->opp_table);
-		return ret;
-	}
-
-	return 0;
-}
-
-static void core_put_v4(struct device *dev)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
-
-	if (legacy_binding)
-		return;
-
-	vcodec_domains_put(dev);
-
-	if (core->has_opp_table)
-		dev_pm_opp_of_remove_table(dev);
-	if (core->opp_table)
-		dev_pm_opp_put_clkname(core->opp_table);
-
-}
-
-static int core_power_v4(struct device *dev, int on)
-{
-	struct venus_core *core = dev_get_drvdata(dev);
-	int ret = 0;
-
-	if (on == POWER_ON) {
-		ret = core_clks_enable(core);
-	} else {
-		/* Drop the performance state vote */
-		if (core->opp_pmdomain)
-			dev_pm_opp_set_rate(dev, 0);
-
-		core_clks_disable(core);
-	}
-
-	return ret;
-}
-
 static unsigned long calculate_inst_freq(struct venus_inst *inst,
 					 unsigned long filled_len)
 {
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/3] media: venus: core: Add sdm660 DT compatible and resource struct
  2020-09-26 12:54 [PATCH 0/3] Qualcomm Venus enablement for SDM630/636/660 kholk11
  2020-09-26 12:54 ` [PATCH 1/3] media: venus: pm_helper: Commonize v3/v4 pmdomains and clocks management kholk11
@ 2020-09-26 12:54 ` kholk11
  2020-09-26 12:54 ` [PATCH 3/3] media: dt-bindings: media: venus: Add sdm660 DT schema kholk11
  2 siblings, 0 replies; 5+ messages in thread
From: kholk11 @ 2020-09-26 12:54 UTC (permalink / raw)
  To: stanimir.varbanov
  Cc: agross, bjorn.andersson, linux-media, kholk11, marijns95,
	konradybcio, martin.botka1, linux-arm-msm, phone-devel,
	linux-kernel

From: AngeloGioacchino Del Regno <kholk11@gmail.com>

Add the SDM660 DT compatible and its resource structure, also
including support for the Venus pmdomains, in order to support
the Venus block in SDM630, SDM636, SDM660 and SDA variants.

This SoC features Venus 4.4 (HFI3XX), with one vcodec used for
both encoding and decoding, switched on through two GDSCs.
The core clock for this Venus chip is powered by the RPM VDD_CX
power domain.

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
---
 drivers/media/platform/qcom/venus/core.c | 68 ++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 6103aaf43987..c5fccafcf656 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -539,6 +539,73 @@ static const struct venus_resources sdm845_res_v2 = {
 	.fwname = "qcom/venus-5.2/venus.mdt",
 };
 
+static const struct freq_tbl sdm660_freq_table[] = {
+	{ 0, 518400000 },
+	{ 0, 441600000 },
+	{ 0, 404000000 },
+	{ 0, 320000000 },
+	{ 0, 269330000 },
+	{ 0, 133330000 },
+};
+
+static const struct reg_val sdm660_reg_preset[] = {
+	{ 0x80010, 0x001f001f },
+	{ 0x80018, 0x00000156 },
+	{ 0x8001C, 0x00000156 },
+};
+
+static const struct bw_tbl sdm660_bw_table_enc[] = {
+	{  979200,  1044000, 0, 2446336, 0 },	/* 4k UHD @ 30 */
+	{  864000,   887000, 0, 2108416, 0 },	/* 720p @ 240 */
+	{  489600,   666000, 0, 1207296, 0 },	/* 1080p @ 60 */
+	{  432000,   578000, 0, 1058816, 0 },	/* 720p @ 120 */
+	{  244800,   346000, 0,  616448, 0 },	/* 1080p @ 30 */
+	{  216000,   293000, 0,  534528, 0 },	/* 720p @ 60 */
+	{  108000,   151000, 0,  271360, 0 },	/* 720p @ 30 */
+};
+
+static const struct bw_tbl sdm660_bw_table_dec[] = {
+	{  979200,  2365000, 0, 1892000, 0 },	/* 4k UHD @ 30 */
+	{  864000,  1978000, 0, 1554000, 0 },	/* 720p @ 240 */
+	{  489600,  1133000, 0,  895000, 0 },	/* 1080p @ 60 */
+	{  432000,   994000, 0,  781000, 0 },	/* 720p @ 120 */
+	{  244800,   580000, 0,  460000, 0 },	/* 1080p @ 30 */
+	{  216000,   501000, 0,  301000, 0 },	/* 720p @ 60 */
+	{  108000,   255000, 0,  202000, 0 },	/* 720p @ 30 */
+};
+
+static const struct venus_resources sdm660_res = {
+	.freq_tbl = sdm660_freq_table,
+	.freq_tbl_size = ARRAY_SIZE(sdm660_freq_table),
+	.reg_tbl = sdm660_reg_preset,
+	.reg_tbl_size = ARRAY_SIZE(sdm660_reg_preset),
+	.bw_tbl_enc = sdm660_bw_table_enc,
+	.bw_tbl_enc_size = ARRAY_SIZE(sdm660_bw_table_enc),
+	.bw_tbl_dec = sdm660_bw_table_dec,
+	.bw_tbl_dec_size = ARRAY_SIZE(sdm660_bw_table_dec),
+	.codec_freq_data = sdm845_codec_freq_data,
+	.codec_freq_data_size = ARRAY_SIZE(sdm845_codec_freq_data),
+	.clks = {"core", "iface", "bus_throttle", "bus" },
+	.clks_num = 4,
+	.vcodec0_clks = { "vcodec0_core" },
+	.vcodec_clks_num = 1,
+	.vcodec_pmdomains = { "venus", "vcodec0" },
+	.vcodec_pmdomains_num = 2,
+	.opp_pmdomain = (const char *[]) { "cx", NULL },
+	.vcodec_num = 1,
+	.max_load = 1036800,
+	.hfi_version = HFI_VERSION_3XX,
+	.vmem_id = VIDC_RESOURCE_NONE,
+	.vmem_size = 0,
+	.vmem_addr = 0,
+	.cp_start = 0,
+	.cp_size = 0x79000000,
+	.cp_nonpixel_start = 0x1000000,
+	.cp_nonpixel_size = 0x28000000,
+	.dma_mask = 0xd9000000 - 1,
+	.fwname = "qcom/venus-4.4/venus.mdt",
+};
+
 static const struct freq_tbl sc7180_freq_table[] = {
 	{  0, 500000000 },
 	{  0, 434000000 },
@@ -587,6 +654,7 @@ static const struct venus_resources sc7180_res = {
 static const struct of_device_id venus_dt_match[] = {
 	{ .compatible = "qcom,msm8916-venus", .data = &msm8916_res, },
 	{ .compatible = "qcom,msm8996-venus", .data = &msm8996_res, },
+	{ .compatible = "qcom,sdm660-venus", .data = &sdm660_res, },
 	{ .compatible = "qcom,sdm845-venus", .data = &sdm845_res, },
 	{ .compatible = "qcom,sdm845-venus-v2", .data = &sdm845_res_v2, },
 	{ .compatible = "qcom,sc7180-venus", .data = &sc7180_res, },
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/3] media: dt-bindings: media: venus: Add sdm660 DT schema
  2020-09-26 12:54 [PATCH 0/3] Qualcomm Venus enablement for SDM630/636/660 kholk11
  2020-09-26 12:54 ` [PATCH 1/3] media: venus: pm_helper: Commonize v3/v4 pmdomains and clocks management kholk11
  2020-09-26 12:54 ` [PATCH 2/3] media: venus: core: Add sdm660 DT compatible and resource struct kholk11
@ 2020-09-26 12:54 ` kholk11
  2 siblings, 0 replies; 5+ messages in thread
From: kholk11 @ 2020-09-26 12:54 UTC (permalink / raw)
  To: stanimir.varbanov
  Cc: agross, bjorn.andersson, linux-media, kholk11, marijns95,
	konradybcio, martin.botka1, linux-arm-msm, phone-devel,
	linux-kernel

From: AngeloGioacchino Del Regno <kholk11@gmail.com>

Add new qcom,sdm660-venus DT binding schema.

Signed-off-by: AngeloGioacchino Del Regno <kholk11@gmail.com>
---
 .../bindings/media/qcom,sdm660-venus.yaml     | 153 ++++++++++++++++++
 1 file changed, 153 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml

diff --git a/Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml b/Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml
new file mode 100644
index 000000000000..78c4a4ec4fe3
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/qcom,sdm660-venus.yaml
@@ -0,0 +1,153 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/media/qcom,sdm660-venus.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Qualcomm Venus video encode and decode accelerators
+
+maintainers:
+  - Stanimir Varbanov <stanimir.varbanov@linaro.org>
+
+description: |
+  The Venus IP is a video encode and decode accelerator present
+  on Qualcomm platforms
+
+properties:
+  compatible:
+    const: qcom,sdm660-venus
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  power-domains:
+    maxItems: 1
+
+  clocks:
+    maxItems: 5
+
+  clock-names:
+    items:
+      - const: core
+      - const: iface
+      - const: bus_throttle
+      - const: bus
+      - const: vcodec0_core
+
+  iommus:
+    maxItems: 20
+
+  memory-region:
+    maxItems: 1
+
+  video-decoder:
+    type: object
+
+    properties:
+      compatible:
+        const: venus-decoder
+
+    required:
+      - compatible
+
+    additionalProperties: false
+
+  video-encoder:
+    type: object
+
+    properties:
+      compatible:
+        const: venus-encoder
+
+    required:
+      - compatible
+
+    additionalProperties: false
+
+  video-firmware:
+    type: object
+
+    description: |
+      Firmware subnode is needed when the platform does not
+      have TrustZone.
+
+    properties:
+      iommus:
+        maxItems: 2
+
+    required:
+      - iommus
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - power-domains
+  - power-domain-names
+  - clocks
+  - clock-names
+  - iommus
+  - memory-region
+  - video-decoder
+  - video-encoder
+
+examples:
+  - |
+        #include <dt-bindings/interrupt-controller/arm-gic.h>
+        #include <dt-bindings/clock/qcom,mmcc-sdm660.h>
+        #include <dt-bindings/interconnect/qcom,sdm660.h>
+        #include <dt-bindings/power/qcom-rpmpd.h>
+
+        video-codec@cc00000 {
+                compatible = "qcom,sdm660-venus";
+                reg = <0x0cc00000 0xff000>;
+                interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
+                power-domains = <&mmcc VENUS_GDSC>,
+                                <&mmcc VENUS_CORE0_GDSC>,
+                                <&rpmpd SDM660_VDDCX>;
+                power-domain-names = "venus", "vcodec0", "cx";
+                clocks = <&mmcc VIDEO_CORE_CLK>,
+                         <&mmcc VIDEO_AHB_CLK>,
+                         <&mmcc THROTTLE_VIDEO_AXI_CLK>,
+                         <&mmcc VIDEO_AXI_CLK>,
+                         <&mmcc VIDEO_SUBCORE0_CLK>;
+                clock-names = "core", "iface", "bus_throttle", "bus",
+                              "vcodec0_core";
+                iommus = <&mmss_smmu 0x400>,
+                         <&mmss_smmu 0x401>,
+                         <&mmss_smmu 0x40a>,
+                         <&mmss_smmu 0x407>,
+                         <&mmss_smmu 0x40e>,
+                         <&mmss_smmu 0x40f>,
+                         <&mmss_smmu 0x408>,
+                         <&mmss_smmu 0x409>,
+                         <&mmss_smmu 0x40b>,
+                         <&mmss_smmu 0x40c>,
+                         <&mmss_smmu 0x40d>,
+                         <&mmss_smmu 0x410>,
+                         <&mmss_smmu 0x421>,
+                         <&mmss_smmu 0x428>,
+                         <&mmss_smmu 0x429>,
+                         <&mmss_smmu 0x42b>,
+                         <&mmss_smmu 0x42c>,
+                         <&mmss_smmu 0x42d>,
+                         <&mmss_smmu 0x411>,
+                         <&mmss_smmu 0x431>;
+                memory-region = <&venus_region>;
+
+                interconnects = <&mnoc MASTER_VENUS &bimc SLAVE_EBI>,
+                                <&gnoc MASTER_APSS_PROC &mnoc SLAVE_VENUS_CFG>;
+                interconnect-names = "video-mem", "cpu-cfg";
+
+                video-decoder {
+                        compatible = "venus-decoder";
+                };
+
+                video-encoder {
+                        compatible = "venus-encoder";
+                };
+        };
-- 
2.28.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH 1/3] media: venus: pm_helper: Commonize v3/v4 pmdomains and clocks management
  2020-09-26 12:54 ` [PATCH 1/3] media: venus: pm_helper: Commonize v3/v4 pmdomains and clocks management kholk11
@ 2020-09-26 16:16   ` kernel test robot
  0 siblings, 0 replies; 5+ messages in thread
From: kernel test robot @ 2020-09-26 16:16 UTC (permalink / raw)
  To: kholk11, stanimir.varbanov
  Cc: kbuild-all, clang-built-linux, agross, bjorn.andersson,
	linux-media, kholk11, marijns95, konradybcio, martin.botka1,
	linux-arm-msm, phone-devel

[-- Attachment #1: Type: text/plain, Size: 3639 bytes --]

Hi,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linuxtv-media/master]
[also build test WARNING on next-20200925]
[cannot apply to v5.9-rc6]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/kholk11-gmail-com/Qualcomm-Venus-enablement-for-SDM630-636-660/20200926-205558
base:   git://linuxtv.org/media_tree.git master
config: x86_64-randconfig-a002-20200925 (attached as .config)
compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project a83eb048cb9a75da7a07a9d5318bbdbf54885c87)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/144283cb3c0b5f0dbd7083ea6eec2b5f049ca9c2
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review kholk11-gmail-com/Qualcomm-Venus-enablement-for-SDM630-636-660/20200926-205558
        git checkout 144283cb3c0b5f0dbd7083ea6eec2b5f049ca9c2
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/media/platform/qcom/venus/pm_helpers.c:496:12: warning: address of array 'core->vcodec1_clks' will always evaluate to 'true' [-Wpointer-bool-conversion]
           if (core->vcodec1_clks) {
           ~~  ~~~~~~^~~~~~~~~~~~
   1 warning generated.

vim +496 drivers/media/platform/qcom/venus/pm_helpers.c

   476	
   477	static int core_get_v4(struct device *dev)
   478	{
   479		struct venus_core *core = dev_get_drvdata(dev);
   480		const struct venus_resources *res = core->res;
   481		int ret;
   482	
   483		ret = core_clks_get(core);
   484		if (ret)
   485			return ret;
   486	
   487		if (!res->vcodec_pmdomains_num)
   488			legacy_binding = true;
   489	
   490		dev_info(dev, "%s legacy binding\n", legacy_binding ? "" : "non");
   491	
   492		ret = vcodec_clks_get(core, dev, core->vcodec0_clks, res->vcodec0_clks);
   493		if (ret)
   494			return ret;
   495	
 > 496		if (core->vcodec1_clks) {
   497			ret = vcodec_clks_get(core, dev,
   498					      core->vcodec1_clks, res->vcodec1_clks);
   499			if (ret)
   500				return ret;
   501		}
   502	
   503		if (legacy_binding)
   504			return 0;
   505	
   506		core->opp_table = dev_pm_opp_set_clkname(dev, "core");
   507		if (IS_ERR(core->opp_table))
   508			return PTR_ERR(core->opp_table);
   509	
   510		if (core->res->opp_pmdomain) {
   511			ret = dev_pm_opp_of_add_table(dev);
   512			if (!ret) {
   513				core->has_opp_table = true;
   514			} else if (ret != -ENODEV) {
   515				dev_err(dev, "invalid OPP table in device tree\n");
   516				dev_pm_opp_put_clkname(core->opp_table);
   517				return ret;
   518			}
   519		}
   520	
   521		ret = vcodec_domains_get(dev);
   522		if (ret) {
   523			if (core->has_opp_table)
   524				dev_pm_opp_of_remove_table(dev);
   525			dev_pm_opp_put_clkname(core->opp_table);
   526			return ret;
   527		}
   528	
   529		return 0;
   530	}
   531	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 36979 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-09-26 16:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-26 12:54 [PATCH 0/3] Qualcomm Venus enablement for SDM630/636/660 kholk11
2020-09-26 12:54 ` [PATCH 1/3] media: venus: pm_helper: Commonize v3/v4 pmdomains and clocks management kholk11
2020-09-26 16:16   ` kernel test robot
2020-09-26 12:54 ` [PATCH 2/3] media: venus: core: Add sdm660 DT compatible and resource struct kholk11
2020-09-26 12:54 ` [PATCH 3/3] media: dt-bindings: media: venus: Add sdm660 DT schema kholk11

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).