media: venus: pm_helpers: Switch domains to back and forth to hwmode

The power domains the venus codec uses are GDSCs which also support HW
control. This means that when the HW control bit is set, the GDSC state
is under HW control and its enable/disbale state is unknown to genpd.
This allows a finer grained controlled as the HW knows best when to
disable/enable the GDSC. At the moment, the venus codec seems to only
work when GDSC is in HW-controlled mode. We would want to switch to
SW-controlled mode when we control the power bit and read the status
of the codec, but we obviously can't do that as the encoding/decoding
will break. If we do try to go through setting up the power control bits
and reading the status, while the GDSC is in HW-controlled mode, it
might be disabled by the HW from under the driver leaving it hanging.
On the other hand, this is how GDSCs that support HW control were
handled until recently and it wasn't a problem. This might've worked
until now because maybe the venus firmware was both expecting the
HW-controlled mode to be enable and it was never allowing the GDSC
to be disabled. Needs further investigation.

Not-Signed-off-by: Abel Vesa <abel.vesa@linaro.org>
diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c
index 990a151..8b80cd3 100644
--- a/drivers/media/platform/qcom/venus/core.c
+++ b/drivers/media/platform/qcom/venus/core.c
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/types.h>
+#include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
 #include <media/videobuf2-v4l2.h>
 #include <media/v4l2-mem2mem.h>
diff --git a/drivers/media/platform/qcom/venus/pm_helpers.c b/drivers/media/platform/qcom/venus/pm_helpers.c
index 48c9084..6ede5e9 100644
--- a/drivers/media/platform/qcom/venus/pm_helpers.c
+++ b/drivers/media/platform/qcom/venus/pm_helpers.c
@@ -455,6 +455,10 @@
 		if (ret)
 			return ret;
 
+		ret = dev_pm_genpd_set_hwmode(core->pmdomains[1], false);
+		if (ret)
+			return ret;
+
 		ret = pm_runtime_put_sync(core->pmdomains[1]);
 		if (ret < 0)
 			return ret;
@@ -471,6 +475,10 @@
 		if (ret)
 			return ret;
 
+		ret = dev_pm_genpd_set_hwmode(core->pmdomains[2], false);
+		if (ret)
+			return ret;
+
 		ret = pm_runtime_put_sync(core->pmdomains[2]);
 		if (ret < 0)
 			return ret;
@@ -488,6 +496,10 @@
 		if (ret < 0)
 			return ret;
 
+		ret = dev_pm_genpd_set_hwmode(core->pmdomains[1], true);
+		if (ret)
+			return ret;
+
 		ret = vcodec_control_v4(core, VIDC_CORE_ID_1, true);
 		if (ret)
 			return ret;
@@ -506,6 +518,10 @@
 		if (ret < 0)
 			return ret;
 
+		ret = dev_pm_genpd_set_hwmode(core->pmdomains[2], true);
+		if (ret)
+			return ret;
+
 		ret = vcodec_control_v4(core, VIDC_CORE_ID_2, true);
 		if (ret)
 			return ret;