@@ -24,6 +24,7 @@
#define VIDC_CLKS_NUM_MAX 4
#define VIDC_VCODEC_CLKS_NUM_MAX 2
#define VIDC_PMDOMAINS_NUM_MAX 3
+#define VIDC_RESETS_NUM_MAX 2
extern int venus_fw_debug;
@@ -64,6 +65,8 @@ struct venus_resources {
unsigned int vcodec_pmdomains_num;
const char **opp_pmdomain;
unsigned int vcodec_num;
+ const char * const resets[VIDC_RESETS_NUM_MAX];
+ unsigned int resets_num;
enum hfi_version hfi_version;
u32 max_load;
unsigned int vmem_id;
@@ -130,6 +133,7 @@ struct venus_core {
struct device *pmdomains[VIDC_PMDOMAINS_NUM_MAX];
struct device_link *opp_dl_venus;
struct device *opp_pmdomain;
+ struct reset_control *resets[VIDC_RESETS_NUM_MAX];
struct video_device *vdev_dec;
struct video_device *vdev_enc;
struct v4l2_device v4l2_dev;
@@ -11,6 +11,7 @@
#include <linux/pm_domain.h>
#include <linux/pm_opp.h>
#include <linux/pm_runtime.h>
+#include <linux/reset.h>
#include <linux/types.h>
#include <media/v4l2-mem2mem.h>
@@ -830,6 +831,52 @@ static void vcodec_domains_put(struct venus_core *core)
dev_pm_opp_detach_genpd(core->opp_table);
}
+static int core_resets_reset(struct venus_core *core)
+{
+ const struct venus_resources *res = core->res;
+ unsigned char i;
+ int ret;
+
+ if (!res->resets_num)
+ return 0;
+
+ for (i = 0; i < res->resets_num; i++) {
+ ret = reset_control_assert(core->resets[i]);
+ if (ret)
+ goto err;
+
+ usleep_range(150, 250);
+ ret = reset_control_deassert(core->resets[i]);
+ if (ret)
+ goto err;
+ }
+
+err:
+ return ret;
+}
+
+static int core_resets_get(struct venus_core *core)
+{
+ struct device *dev = core->dev;
+ const struct venus_resources *res = core->res;
+ unsigned char i;
+ int ret;
+
+ if (!res->resets_num)
+ return 0;
+
+ for (i = 0; i < res->resets_num; i++) {
+ core->resets[i] =
+ devm_reset_control_get_exclusive(dev, res->resets[i]);
+ if (IS_ERR(core->resets[i])) {
+ ret = PTR_ERR(core->resets[i]);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int core_get_v4(struct venus_core *core)
{
struct device *dev = core->dev;
@@ -853,6 +900,10 @@ static int core_get_v4(struct venus_core *core)
if (ret)
return ret;
+ ret = core_resets_get(core);
+ if (ret)
+ return ret;
+
if (legacy_binding)
return 0;
@@ -912,6 +963,13 @@ static int core_power_v4(struct venus_core *core, int on)
}
}
+ ret = core_resets_reset(core);
+ if (ret) {
+ if (pmctrl)
+ pm_runtime_put_sync(pmctrl);
+ return ret;
+ }
+
ret = core_clks_enable(core);
if (ret < 0 && pmctrl)
pm_runtime_put_sync(pmctrl);
@@ -922,6 +980,8 @@ static int core_power_v4(struct venus_core *core, int on)
core_clks_disable(core);
+ ret = core_resets_reset(core);
+
if (pmctrl)
pm_runtime_put_sync(pmctrl);
}