162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
462306a36Sopenharmony_ci * Copyright (C) 2017 Linaro Ltd.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci#include <linux/slab.h>
762306a36Sopenharmony_ci#include <linux/mutex.h>
862306a36Sopenharmony_ci#include <linux/list.h>
962306a36Sopenharmony_ci#include <linux/completion.h>
1062306a36Sopenharmony_ci#include <linux/platform_device.h>
1162306a36Sopenharmony_ci#include <linux/videodev2.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "core.h"
1462306a36Sopenharmony_ci#include "hfi.h"
1562306a36Sopenharmony_ci#include "hfi_cmds.h"
1662306a36Sopenharmony_ci#include "hfi_venus.h"
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define TIMEOUT		msecs_to_jiffies(1000)
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic u32 to_codec_type(u32 pixfmt)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	switch (pixfmt) {
2362306a36Sopenharmony_ci	case V4L2_PIX_FMT_H264:
2462306a36Sopenharmony_ci	case V4L2_PIX_FMT_H264_NO_SC:
2562306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_H264;
2662306a36Sopenharmony_ci	case V4L2_PIX_FMT_H263:
2762306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_H263;
2862306a36Sopenharmony_ci	case V4L2_PIX_FMT_MPEG1:
2962306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_MPEG1;
3062306a36Sopenharmony_ci	case V4L2_PIX_FMT_MPEG2:
3162306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_MPEG2;
3262306a36Sopenharmony_ci	case V4L2_PIX_FMT_MPEG4:
3362306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_MPEG4;
3462306a36Sopenharmony_ci	case V4L2_PIX_FMT_VC1_ANNEX_G:
3562306a36Sopenharmony_ci	case V4L2_PIX_FMT_VC1_ANNEX_L:
3662306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_VC1;
3762306a36Sopenharmony_ci	case V4L2_PIX_FMT_VP8:
3862306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_VP8;
3962306a36Sopenharmony_ci	case V4L2_PIX_FMT_VP9:
4062306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_VP9;
4162306a36Sopenharmony_ci	case V4L2_PIX_FMT_XVID:
4262306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_DIVX;
4362306a36Sopenharmony_ci	case V4L2_PIX_FMT_HEVC:
4462306a36Sopenharmony_ci		return HFI_VIDEO_CODEC_HEVC;
4562306a36Sopenharmony_ci	default:
4662306a36Sopenharmony_ci		return 0;
4762306a36Sopenharmony_ci	}
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ciint hfi_core_init(struct venus_core *core)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	int ret = 0;
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	mutex_lock(&core->lock);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	if (core->state >= CORE_INIT)
5762306a36Sopenharmony_ci		goto unlock;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	reinit_completion(&core->done);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	ret = core->ops->core_init(core);
6262306a36Sopenharmony_ci	if (ret)
6362306a36Sopenharmony_ci		goto unlock;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	ret = wait_for_completion_timeout(&core->done, TIMEOUT);
6662306a36Sopenharmony_ci	if (!ret) {
6762306a36Sopenharmony_ci		ret = -ETIMEDOUT;
6862306a36Sopenharmony_ci		goto unlock;
6962306a36Sopenharmony_ci	}
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	ret = 0;
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	if (core->error != HFI_ERR_NONE) {
7462306a36Sopenharmony_ci		ret = -EIO;
7562306a36Sopenharmony_ci		goto unlock;
7662306a36Sopenharmony_ci	}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci	core->state = CORE_INIT;
7962306a36Sopenharmony_ciunlock:
8062306a36Sopenharmony_ci	mutex_unlock(&core->lock);
8162306a36Sopenharmony_ci	return ret;
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ciint hfi_core_deinit(struct venus_core *core, bool blocking)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	int ret = 0, empty;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	mutex_lock(&core->lock);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	if (core->state == CORE_UNINIT)
9162306a36Sopenharmony_ci		goto unlock;
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	empty = list_empty(&core->instances);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	if (!empty && !blocking) {
9662306a36Sopenharmony_ci		ret = -EBUSY;
9762306a36Sopenharmony_ci		goto unlock;
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	if (!empty) {
10162306a36Sopenharmony_ci		mutex_unlock(&core->lock);
10262306a36Sopenharmony_ci		wait_var_event(&core->insts_count,
10362306a36Sopenharmony_ci			       !atomic_read(&core->insts_count));
10462306a36Sopenharmony_ci		mutex_lock(&core->lock);
10562306a36Sopenharmony_ci	}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	if (!core->ops)
10862306a36Sopenharmony_ci		goto unlock;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	ret = core->ops->core_deinit(core);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	if (!ret)
11362306a36Sopenharmony_ci		core->state = CORE_UNINIT;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ciunlock:
11662306a36Sopenharmony_ci	mutex_unlock(&core->lock);
11762306a36Sopenharmony_ci	return ret;
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciint hfi_core_suspend(struct venus_core *core)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	if (core->state != CORE_INIT)
12362306a36Sopenharmony_ci		return 0;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	return core->ops->suspend(core);
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ciint hfi_core_resume(struct venus_core *core, bool force)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	if (!force && core->state != CORE_INIT)
13162306a36Sopenharmony_ci		return 0;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	return core->ops->resume(core);
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ciint hfi_core_trigger_ssr(struct venus_core *core, u32 type)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	return core->ops->core_trigger_ssr(core, type);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ciint hfi_core_ping(struct venus_core *core)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	int ret;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	mutex_lock(&core->lock);
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	ret = core->ops->core_ping(core, 0xbeef);
14862306a36Sopenharmony_ci	if (ret)
14962306a36Sopenharmony_ci		goto unlock;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	ret = wait_for_completion_timeout(&core->done, TIMEOUT);
15262306a36Sopenharmony_ci	if (!ret) {
15362306a36Sopenharmony_ci		ret = -ETIMEDOUT;
15462306a36Sopenharmony_ci		goto unlock;
15562306a36Sopenharmony_ci	}
15662306a36Sopenharmony_ci	ret = 0;
15762306a36Sopenharmony_ci	if (core->error != HFI_ERR_NONE)
15862306a36Sopenharmony_ci		ret = -ENODEV;
15962306a36Sopenharmony_ciunlock:
16062306a36Sopenharmony_ci	mutex_unlock(&core->lock);
16162306a36Sopenharmony_ci	return ret;
16262306a36Sopenharmony_ci}
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_cistatic int wait_session_msg(struct venus_inst *inst)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	int ret;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
16962306a36Sopenharmony_ci	if (!ret)
17062306a36Sopenharmony_ci		return -ETIMEDOUT;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	if (inst->error != HFI_ERR_NONE)
17362306a36Sopenharmony_ci		return -EIO;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	return 0;
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ciint hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct venus_core *core = inst->core;
18162306a36Sopenharmony_ci	bool max;
18262306a36Sopenharmony_ci	int ret;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	if (!ops)
18562306a36Sopenharmony_ci		return -EINVAL;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	inst->state = INST_UNINIT;
18862306a36Sopenharmony_ci	init_completion(&inst->done);
18962306a36Sopenharmony_ci	inst->ops = ops;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	mutex_lock(&core->lock);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error)) {
19462306a36Sopenharmony_ci		ret = -EIO;
19562306a36Sopenharmony_ci		goto unlock;
19662306a36Sopenharmony_ci	}
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	max = atomic_add_unless(&core->insts_count, 1,
19962306a36Sopenharmony_ci				core->max_sessions_supported);
20062306a36Sopenharmony_ci	if (!max) {
20162306a36Sopenharmony_ci		ret = -EAGAIN;
20262306a36Sopenharmony_ci	} else {
20362306a36Sopenharmony_ci		list_add_tail(&inst->list, &core->instances);
20462306a36Sopenharmony_ci		ret = 0;
20562306a36Sopenharmony_ci	}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ciunlock:
20862306a36Sopenharmony_ci	mutex_unlock(&core->lock);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	return ret;
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_create);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ciint hfi_session_init(struct venus_inst *inst, u32 pixfmt)
21562306a36Sopenharmony_ci{
21662306a36Sopenharmony_ci	struct venus_core *core = inst->core;
21762306a36Sopenharmony_ci	const struct hfi_ops *ops = core->ops;
21862306a36Sopenharmony_ci	int ret;
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	/*
22162306a36Sopenharmony_ci	 * If core shutdown is in progress or if we are in system
22262306a36Sopenharmony_ci	 * recovery, return an error as during system error recovery
22362306a36Sopenharmony_ci	 * session_init() can't pass successfully
22462306a36Sopenharmony_ci	 */
22562306a36Sopenharmony_ci	mutex_lock(&core->lock);
22662306a36Sopenharmony_ci	if (!core->ops || test_bit(0, &inst->core->sys_error)) {
22762306a36Sopenharmony_ci		mutex_unlock(&core->lock);
22862306a36Sopenharmony_ci		return -EIO;
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci	mutex_unlock(&core->lock);
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	if (inst->state != INST_UNINIT)
23362306a36Sopenharmony_ci		return -EALREADY;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	inst->hfi_codec = to_codec_type(pixfmt);
23662306a36Sopenharmony_ci	reinit_completion(&inst->done);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	ret = ops->session_init(inst, inst->session_type, inst->hfi_codec);
23962306a36Sopenharmony_ci	if (ret)
24062306a36Sopenharmony_ci		return ret;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	ret = wait_session_msg(inst);
24362306a36Sopenharmony_ci	if (ret)
24462306a36Sopenharmony_ci		return ret;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	inst->state = INST_INIT;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	return 0;
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_init);
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_civoid hfi_session_destroy(struct venus_inst *inst)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	struct venus_core *core = inst->core;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	mutex_lock(&core->lock);
25762306a36Sopenharmony_ci	list_del_init(&inst->list);
25862306a36Sopenharmony_ci	if (atomic_dec_and_test(&core->insts_count))
25962306a36Sopenharmony_ci		wake_up_var(&core->insts_count);
26062306a36Sopenharmony_ci	mutex_unlock(&core->lock);
26162306a36Sopenharmony_ci}
26262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_destroy);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ciint hfi_session_deinit(struct venus_inst *inst)
26562306a36Sopenharmony_ci{
26662306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
26762306a36Sopenharmony_ci	int ret;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	if (inst->state == INST_UNINIT)
27062306a36Sopenharmony_ci		return 0;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	if (inst->state < INST_INIT)
27362306a36Sopenharmony_ci		return -EINVAL;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
27662306a36Sopenharmony_ci		goto done;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	reinit_completion(&inst->done);
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	ret = ops->session_end(inst);
28162306a36Sopenharmony_ci	if (ret)
28262306a36Sopenharmony_ci		return ret;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	ret = wait_session_msg(inst);
28562306a36Sopenharmony_ci	if (ret)
28662306a36Sopenharmony_ci		return ret;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_cidone:
28962306a36Sopenharmony_ci	inst->state = INST_UNINIT;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	return 0;
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_deinit);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ciint hfi_session_start(struct venus_inst *inst)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
29862306a36Sopenharmony_ci	int ret;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
30162306a36Sopenharmony_ci		return -EIO;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	if (inst->state != INST_LOAD_RESOURCES)
30462306a36Sopenharmony_ci		return -EINVAL;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	reinit_completion(&inst->done);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	ret = ops->session_start(inst);
30962306a36Sopenharmony_ci	if (ret)
31062306a36Sopenharmony_ci		return ret;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	ret = wait_session_msg(inst);
31362306a36Sopenharmony_ci	if (ret)
31462306a36Sopenharmony_ci		return ret;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	inst->state = INST_START;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	return 0;
31962306a36Sopenharmony_ci}
32062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_start);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ciint hfi_session_stop(struct venus_inst *inst)
32362306a36Sopenharmony_ci{
32462306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
32562306a36Sopenharmony_ci	int ret;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
32862306a36Sopenharmony_ci		return -EIO;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	if (inst->state != INST_START)
33162306a36Sopenharmony_ci		return -EINVAL;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	reinit_completion(&inst->done);
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci	ret = ops->session_stop(inst);
33662306a36Sopenharmony_ci	if (ret)
33762306a36Sopenharmony_ci		return ret;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	ret = wait_session_msg(inst);
34062306a36Sopenharmony_ci	if (ret)
34162306a36Sopenharmony_ci		return ret;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	inst->state = INST_STOP;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	return 0;
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_stop);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ciint hfi_session_continue(struct venus_inst *inst)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	struct venus_core *core = inst->core;
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
35462306a36Sopenharmony_ci		return -EIO;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	if (core->res->hfi_version == HFI_VERSION_1XX)
35762306a36Sopenharmony_ci		return 0;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	return core->ops->session_continue(inst);
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_continue);
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ciint hfi_session_abort(struct venus_inst *inst)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
36662306a36Sopenharmony_ci	int ret;
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
36962306a36Sopenharmony_ci		return -EIO;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	reinit_completion(&inst->done);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	ret = ops->session_abort(inst);
37462306a36Sopenharmony_ci	if (ret)
37562306a36Sopenharmony_ci		return ret;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	ret = wait_session_msg(inst);
37862306a36Sopenharmony_ci	if (ret)
37962306a36Sopenharmony_ci		return ret;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	return 0;
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_abort);
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ciint hfi_session_load_res(struct venus_inst *inst)
38662306a36Sopenharmony_ci{
38762306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
38862306a36Sopenharmony_ci	int ret;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
39162306a36Sopenharmony_ci		return -EIO;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	if (inst->state != INST_INIT)
39462306a36Sopenharmony_ci		return -EINVAL;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	reinit_completion(&inst->done);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	ret = ops->session_load_res(inst);
39962306a36Sopenharmony_ci	if (ret)
40062306a36Sopenharmony_ci		return ret;
40162306a36Sopenharmony_ci
40262306a36Sopenharmony_ci	ret = wait_session_msg(inst);
40362306a36Sopenharmony_ci	if (ret)
40462306a36Sopenharmony_ci		return ret;
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	inst->state = INST_LOAD_RESOURCES;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	return 0;
40962306a36Sopenharmony_ci}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ciint hfi_session_unload_res(struct venus_inst *inst)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
41462306a36Sopenharmony_ci	int ret;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
41762306a36Sopenharmony_ci		return -EIO;
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci	if (inst->state != INST_STOP)
42062306a36Sopenharmony_ci		return -EINVAL;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci	reinit_completion(&inst->done);
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	ret = ops->session_release_res(inst);
42562306a36Sopenharmony_ci	if (ret)
42662306a36Sopenharmony_ci		return ret;
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	ret = wait_session_msg(inst);
42962306a36Sopenharmony_ci	if (ret)
43062306a36Sopenharmony_ci		return ret;
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	inst->state = INST_RELEASE_RESOURCES;
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	return 0;
43562306a36Sopenharmony_ci}
43662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_unload_res);
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ciint hfi_session_flush(struct venus_inst *inst, u32 type, bool block)
43962306a36Sopenharmony_ci{
44062306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
44162306a36Sopenharmony_ci	int ret;
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
44462306a36Sopenharmony_ci		return -EIO;
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	reinit_completion(&inst->done);
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	ret = ops->session_flush(inst, type);
44962306a36Sopenharmony_ci	if (ret)
45062306a36Sopenharmony_ci		return ret;
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	if (block) {
45362306a36Sopenharmony_ci		ret = wait_session_msg(inst);
45462306a36Sopenharmony_ci		if (ret)
45562306a36Sopenharmony_ci			return ret;
45662306a36Sopenharmony_ci	}
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci	return 0;
45962306a36Sopenharmony_ci}
46062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_flush);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ciint hfi_session_set_buffers(struct venus_inst *inst, struct hfi_buffer_desc *bd)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
46762306a36Sopenharmony_ci		return -EIO;
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	return ops->session_set_buffers(inst, bd);
47062306a36Sopenharmony_ci}
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ciint hfi_session_unset_buffers(struct venus_inst *inst,
47362306a36Sopenharmony_ci			      struct hfi_buffer_desc *bd)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
47662306a36Sopenharmony_ci	int ret;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
47962306a36Sopenharmony_ci		return -EIO;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	reinit_completion(&inst->done);
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	ret = ops->session_unset_buffers(inst, bd);
48462306a36Sopenharmony_ci	if (ret)
48562306a36Sopenharmony_ci		return ret;
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	if (!bd->response_required)
48862306a36Sopenharmony_ci		return 0;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	ret = wait_session_msg(inst);
49162306a36Sopenharmony_ci	if (ret)
49262306a36Sopenharmony_ci		return ret;
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	return 0;
49562306a36Sopenharmony_ci}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ciint hfi_session_get_property(struct venus_inst *inst, u32 ptype,
49862306a36Sopenharmony_ci			     union hfi_get_property *hprop)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
50162306a36Sopenharmony_ci	int ret;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
50462306a36Sopenharmony_ci		return -EIO;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	if (inst->state < INST_INIT || inst->state >= INST_STOP)
50762306a36Sopenharmony_ci		return -EINVAL;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	reinit_completion(&inst->done);
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	ret = ops->session_get_property(inst, ptype);
51262306a36Sopenharmony_ci	if (ret)
51362306a36Sopenharmony_ci		return ret;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	ret = wait_session_msg(inst);
51662306a36Sopenharmony_ci	if (ret)
51762306a36Sopenharmony_ci		return ret;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	*hprop = inst->hprop;
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	return 0;
52262306a36Sopenharmony_ci}
52362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_get_property);
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ciint hfi_session_set_property(struct venus_inst *inst, u32 ptype, void *pdata)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
53062306a36Sopenharmony_ci		return -EIO;
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	if (inst->state < INST_INIT || inst->state >= INST_STOP)
53362306a36Sopenharmony_ci		return -EINVAL;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	return ops->session_set_property(inst, ptype, pdata);
53662306a36Sopenharmony_ci}
53762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_set_property);
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ciint hfi_session_process_buf(struct venus_inst *inst, struct hfi_frame_data *fd)
54062306a36Sopenharmony_ci{
54162306a36Sopenharmony_ci	const struct hfi_ops *ops = inst->core->ops;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	if (test_bit(0, &inst->core->sys_error))
54462306a36Sopenharmony_ci		return -EIO;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	if (fd->buffer_type == HFI_BUFFER_INPUT)
54762306a36Sopenharmony_ci		return ops->session_etb(inst, fd);
54862306a36Sopenharmony_ci	else if (fd->buffer_type == HFI_BUFFER_OUTPUT ||
54962306a36Sopenharmony_ci		 fd->buffer_type == HFI_BUFFER_OUTPUT2)
55062306a36Sopenharmony_ci		return ops->session_ftb(inst, fd);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	return -EINVAL;
55362306a36Sopenharmony_ci}
55462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(hfi_session_process_buf);
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ciirqreturn_t hfi_isr_thread(int irq, void *dev_id)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	struct venus_core *core = dev_id;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	return core->ops->isr_thread(core);
56162306a36Sopenharmony_ci}
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ciirqreturn_t hfi_isr(int irq, void *dev)
56462306a36Sopenharmony_ci{
56562306a36Sopenharmony_ci	struct venus_core *core = dev;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	return core->ops->isr(core);
56862306a36Sopenharmony_ci}
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ciint hfi_create(struct venus_core *core, const struct hfi_core_ops *ops)
57162306a36Sopenharmony_ci{
57262306a36Sopenharmony_ci	if (!ops)
57362306a36Sopenharmony_ci		return -EINVAL;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	atomic_set(&core->insts_count, 0);
57662306a36Sopenharmony_ci	core->core_ops = ops;
57762306a36Sopenharmony_ci	core->state = CORE_UNINIT;
57862306a36Sopenharmony_ci	init_completion(&core->done);
57962306a36Sopenharmony_ci	pkt_set_version(core->res->hfi_version);
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	return venus_hfi_create(core);
58262306a36Sopenharmony_ci}
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_civoid hfi_destroy(struct venus_core *core)
58562306a36Sopenharmony_ci{
58662306a36Sopenharmony_ci	venus_hfi_destroy(core);
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_civoid hfi_reinit(struct venus_core *core)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	venus_hfi_queues_reinit(core);
59262306a36Sopenharmony_ci}
593