xref: /openbmc/linux/drivers/media/platform/qcom/venus/hfi.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
209c2845eSStanimir Varbanov /*
309c2845eSStanimir Varbanov  * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
409c2845eSStanimir Varbanov  * Copyright (C) 2017 Linaro Ltd.
509c2845eSStanimir Varbanov  */
609c2845eSStanimir Varbanov #include <linux/slab.h>
709c2845eSStanimir Varbanov #include <linux/mutex.h>
809c2845eSStanimir Varbanov #include <linux/list.h>
909c2845eSStanimir Varbanov #include <linux/completion.h>
1009c2845eSStanimir Varbanov #include <linux/platform_device.h>
1109c2845eSStanimir Varbanov #include <linux/videodev2.h>
1209c2845eSStanimir Varbanov 
1309c2845eSStanimir Varbanov #include "core.h"
1409c2845eSStanimir Varbanov #include "hfi.h"
1509c2845eSStanimir Varbanov #include "hfi_cmds.h"
1609c2845eSStanimir Varbanov #include "hfi_venus.h"
1709c2845eSStanimir Varbanov 
1809c2845eSStanimir Varbanov #define TIMEOUT		msecs_to_jiffies(1000)
1909c2845eSStanimir Varbanov 
to_codec_type(u32 pixfmt)2009c2845eSStanimir Varbanov static u32 to_codec_type(u32 pixfmt)
2109c2845eSStanimir Varbanov {
2209c2845eSStanimir Varbanov 	switch (pixfmt) {
2309c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_H264:
2409c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_H264_NO_SC:
2509c2845eSStanimir Varbanov 		return HFI_VIDEO_CODEC_H264;
2609c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_H263:
2709c2845eSStanimir Varbanov 		return HFI_VIDEO_CODEC_H263;
2809c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_MPEG1:
2909c2845eSStanimir Varbanov 		return HFI_VIDEO_CODEC_MPEG1;
3009c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_MPEG2:
3109c2845eSStanimir Varbanov 		return HFI_VIDEO_CODEC_MPEG2;
3209c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_MPEG4:
3309c2845eSStanimir Varbanov 		return HFI_VIDEO_CODEC_MPEG4;
3409c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_VC1_ANNEX_G:
3509c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_VC1_ANNEX_L:
3609c2845eSStanimir Varbanov 		return HFI_VIDEO_CODEC_VC1;
3709c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_VP8:
3809c2845eSStanimir Varbanov 		return HFI_VIDEO_CODEC_VP8;
3909c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_VP9:
4009c2845eSStanimir Varbanov 		return HFI_VIDEO_CODEC_VP9;
4109c2845eSStanimir Varbanov 	case V4L2_PIX_FMT_XVID:
4209c2845eSStanimir Varbanov 		return HFI_VIDEO_CODEC_DIVX;
431fb9a605SStanimir Varbanov 	case V4L2_PIX_FMT_HEVC:
441fb9a605SStanimir Varbanov 		return HFI_VIDEO_CODEC_HEVC;
4509c2845eSStanimir Varbanov 	default:
4609c2845eSStanimir Varbanov 		return 0;
4709c2845eSStanimir Varbanov 	}
4809c2845eSStanimir Varbanov }
4909c2845eSStanimir Varbanov 
hfi_core_init(struct venus_core * core)5009c2845eSStanimir Varbanov int hfi_core_init(struct venus_core *core)
5109c2845eSStanimir Varbanov {
5209c2845eSStanimir Varbanov 	int ret = 0;
5309c2845eSStanimir Varbanov 
5409c2845eSStanimir Varbanov 	mutex_lock(&core->lock);
5509c2845eSStanimir Varbanov 
5609c2845eSStanimir Varbanov 	if (core->state >= CORE_INIT)
5709c2845eSStanimir Varbanov 		goto unlock;
5809c2845eSStanimir Varbanov 
5909c2845eSStanimir Varbanov 	reinit_completion(&core->done);
6009c2845eSStanimir Varbanov 
6109c2845eSStanimir Varbanov 	ret = core->ops->core_init(core);
6209c2845eSStanimir Varbanov 	if (ret)
6309c2845eSStanimir Varbanov 		goto unlock;
6409c2845eSStanimir Varbanov 
6509c2845eSStanimir Varbanov 	ret = wait_for_completion_timeout(&core->done, TIMEOUT);
6609c2845eSStanimir Varbanov 	if (!ret) {
6709c2845eSStanimir Varbanov 		ret = -ETIMEDOUT;
6809c2845eSStanimir Varbanov 		goto unlock;
6909c2845eSStanimir Varbanov 	}
7009c2845eSStanimir Varbanov 
7109c2845eSStanimir Varbanov 	ret = 0;
7209c2845eSStanimir Varbanov 
7309c2845eSStanimir Varbanov 	if (core->error != HFI_ERR_NONE) {
7409c2845eSStanimir Varbanov 		ret = -EIO;
7509c2845eSStanimir Varbanov 		goto unlock;
7609c2845eSStanimir Varbanov 	}
7709c2845eSStanimir Varbanov 
7809c2845eSStanimir Varbanov 	core->state = CORE_INIT;
7909c2845eSStanimir Varbanov unlock:
8009c2845eSStanimir Varbanov 	mutex_unlock(&core->lock);
8109c2845eSStanimir Varbanov 	return ret;
8209c2845eSStanimir Varbanov }
8309c2845eSStanimir Varbanov 
hfi_core_deinit(struct venus_core * core,bool blocking)8409c2845eSStanimir Varbanov int hfi_core_deinit(struct venus_core *core, bool blocking)
8509c2845eSStanimir Varbanov {
8609c2845eSStanimir Varbanov 	int ret = 0, empty;
8709c2845eSStanimir Varbanov 
8809c2845eSStanimir Varbanov 	mutex_lock(&core->lock);
8909c2845eSStanimir Varbanov 
9009c2845eSStanimir Varbanov 	if (core->state == CORE_UNINIT)
9109c2845eSStanimir Varbanov 		goto unlock;
9209c2845eSStanimir Varbanov 
9309c2845eSStanimir Varbanov 	empty = list_empty(&core->instances);
9409c2845eSStanimir Varbanov 
9509c2845eSStanimir Varbanov 	if (!empty && !blocking) {
9609c2845eSStanimir Varbanov 		ret = -EBUSY;
9709c2845eSStanimir Varbanov 		goto unlock;
9809c2845eSStanimir Varbanov 	}
9909c2845eSStanimir Varbanov 
10009c2845eSStanimir Varbanov 	if (!empty) {
10109c2845eSStanimir Varbanov 		mutex_unlock(&core->lock);
102f0baa040SPeter Zijlstra 		wait_var_event(&core->insts_count,
103f0baa040SPeter Zijlstra 			       !atomic_read(&core->insts_count));
10409c2845eSStanimir Varbanov 		mutex_lock(&core->lock);
10509c2845eSStanimir Varbanov 	}
10609c2845eSStanimir Varbanov 
10786594f6aSLuca Weiss 	if (!core->ops)
10886594f6aSLuca Weiss 		goto unlock;
10986594f6aSLuca Weiss 
11009c2845eSStanimir Varbanov 	ret = core->ops->core_deinit(core);
11109c2845eSStanimir Varbanov 
11209c2845eSStanimir Varbanov 	if (!ret)
11309c2845eSStanimir Varbanov 		core->state = CORE_UNINIT;
11409c2845eSStanimir Varbanov 
11509c2845eSStanimir Varbanov unlock:
11609c2845eSStanimir Varbanov 	mutex_unlock(&core->lock);
11709c2845eSStanimir Varbanov 	return ret;
11809c2845eSStanimir Varbanov }
11909c2845eSStanimir Varbanov 
hfi_core_suspend(struct venus_core * core)12009c2845eSStanimir Varbanov int hfi_core_suspend(struct venus_core *core)
12109c2845eSStanimir Varbanov {
12209c2845eSStanimir Varbanov 	if (core->state != CORE_INIT)
12309c2845eSStanimir Varbanov 		return 0;
12409c2845eSStanimir Varbanov 
12509c2845eSStanimir Varbanov 	return core->ops->suspend(core);
12609c2845eSStanimir Varbanov }
12709c2845eSStanimir Varbanov 
hfi_core_resume(struct venus_core * core,bool force)12809c2845eSStanimir Varbanov int hfi_core_resume(struct venus_core *core, bool force)
12909c2845eSStanimir Varbanov {
13009c2845eSStanimir Varbanov 	if (!force && core->state != CORE_INIT)
13109c2845eSStanimir Varbanov 		return 0;
13209c2845eSStanimir Varbanov 
13309c2845eSStanimir Varbanov 	return core->ops->resume(core);
13409c2845eSStanimir Varbanov }
13509c2845eSStanimir Varbanov 
hfi_core_trigger_ssr(struct venus_core * core,u32 type)13609c2845eSStanimir Varbanov int hfi_core_trigger_ssr(struct venus_core *core, u32 type)
13709c2845eSStanimir Varbanov {
13809c2845eSStanimir Varbanov 	return core->ops->core_trigger_ssr(core, type);
13909c2845eSStanimir Varbanov }
14009c2845eSStanimir Varbanov 
hfi_core_ping(struct venus_core * core)14109c2845eSStanimir Varbanov int hfi_core_ping(struct venus_core *core)
14209c2845eSStanimir Varbanov {
14309c2845eSStanimir Varbanov 	int ret;
14409c2845eSStanimir Varbanov 
14509c2845eSStanimir Varbanov 	mutex_lock(&core->lock);
14609c2845eSStanimir Varbanov 
14709c2845eSStanimir Varbanov 	ret = core->ops->core_ping(core, 0xbeef);
14809c2845eSStanimir Varbanov 	if (ret)
1498a5aebf1SStanimir Varbanov 		goto unlock;
15009c2845eSStanimir Varbanov 
15109c2845eSStanimir Varbanov 	ret = wait_for_completion_timeout(&core->done, TIMEOUT);
15209c2845eSStanimir Varbanov 	if (!ret) {
15309c2845eSStanimir Varbanov 		ret = -ETIMEDOUT;
15409c2845eSStanimir Varbanov 		goto unlock;
15509c2845eSStanimir Varbanov 	}
15609c2845eSStanimir Varbanov 	ret = 0;
15709c2845eSStanimir Varbanov 	if (core->error != HFI_ERR_NONE)
15809c2845eSStanimir Varbanov 		ret = -ENODEV;
15909c2845eSStanimir Varbanov unlock:
16009c2845eSStanimir Varbanov 	mutex_unlock(&core->lock);
16109c2845eSStanimir Varbanov 	return ret;
16209c2845eSStanimir Varbanov }
16309c2845eSStanimir Varbanov 
wait_session_msg(struct venus_inst * inst)16409c2845eSStanimir Varbanov static int wait_session_msg(struct venus_inst *inst)
16509c2845eSStanimir Varbanov {
16609c2845eSStanimir Varbanov 	int ret;
16709c2845eSStanimir Varbanov 
16809c2845eSStanimir Varbanov 	ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
16909c2845eSStanimir Varbanov 	if (!ret)
17009c2845eSStanimir Varbanov 		return -ETIMEDOUT;
17109c2845eSStanimir Varbanov 
17209c2845eSStanimir Varbanov 	if (inst->error != HFI_ERR_NONE)
17309c2845eSStanimir Varbanov 		return -EIO;
17409c2845eSStanimir Varbanov 
17509c2845eSStanimir Varbanov 	return 0;
17609c2845eSStanimir Varbanov }
17709c2845eSStanimir Varbanov 
hfi_session_create(struct venus_inst * inst,const struct hfi_inst_ops * ops)17809c2845eSStanimir Varbanov int hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops)
17909c2845eSStanimir Varbanov {
18009c2845eSStanimir Varbanov 	struct venus_core *core = inst->core;
18120891170SStanimir Varbanov 	bool max;
18220891170SStanimir Varbanov 	int ret;
18309c2845eSStanimir Varbanov 
18409c2845eSStanimir Varbanov 	if (!ops)
18509c2845eSStanimir Varbanov 		return -EINVAL;
18609c2845eSStanimir Varbanov 
18709c2845eSStanimir Varbanov 	inst->state = INST_UNINIT;
18809c2845eSStanimir Varbanov 	init_completion(&inst->done);
18909c2845eSStanimir Varbanov 	inst->ops = ops;
19009c2845eSStanimir Varbanov 
19109c2845eSStanimir Varbanov 	mutex_lock(&core->lock);
19220891170SStanimir Varbanov 
1933efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error)) {
1943efc5204SStanimir Varbanov 		ret = -EIO;
1953efc5204SStanimir Varbanov 		goto unlock;
1963efc5204SStanimir Varbanov 	}
1973efc5204SStanimir Varbanov 
19820891170SStanimir Varbanov 	max = atomic_add_unless(&core->insts_count, 1,
19920891170SStanimir Varbanov 				core->max_sessions_supported);
20020891170SStanimir Varbanov 	if (!max) {
20120891170SStanimir Varbanov 		ret = -EAGAIN;
20220891170SStanimir Varbanov 	} else {
20309c2845eSStanimir Varbanov 		list_add_tail(&inst->list, &core->instances);
20420891170SStanimir Varbanov 		ret = 0;
20520891170SStanimir Varbanov 	}
20620891170SStanimir Varbanov 
2073efc5204SStanimir Varbanov unlock:
20809c2845eSStanimir Varbanov 	mutex_unlock(&core->lock);
20909c2845eSStanimir Varbanov 
21020891170SStanimir Varbanov 	return ret;
21109c2845eSStanimir Varbanov }
21209c2845eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_create);
21309c2845eSStanimir Varbanov 
hfi_session_init(struct venus_inst * inst,u32 pixfmt)21409c2845eSStanimir Varbanov int hfi_session_init(struct venus_inst *inst, u32 pixfmt)
21509c2845eSStanimir Varbanov {
21609c2845eSStanimir Varbanov 	struct venus_core *core = inst->core;
21709c2845eSStanimir Varbanov 	const struct hfi_ops *ops = core->ops;
21809c2845eSStanimir Varbanov 	int ret;
21909c2845eSStanimir Varbanov 
2209696960fSMansur Alisha Shaik 	/*
2219696960fSMansur Alisha Shaik 	 * If core shutdown is in progress or if we are in system
2229696960fSMansur Alisha Shaik 	 * recovery, return an error as during system error recovery
2239696960fSMansur Alisha Shaik 	 * session_init() can't pass successfully
2249696960fSMansur Alisha Shaik 	 */
2259696960fSMansur Alisha Shaik 	mutex_lock(&core->lock);
226b46ff4ebSStanimir Varbanov 	if (!core->ops || test_bit(0, &inst->core->sys_error)) {
2279696960fSMansur Alisha Shaik 		mutex_unlock(&core->lock);
2289696960fSMansur Alisha Shaik 		return -EIO;
2299696960fSMansur Alisha Shaik 	}
2309696960fSMansur Alisha Shaik 	mutex_unlock(&core->lock);
2319696960fSMansur Alisha Shaik 
232a367b9abSStanimir Varbanov 	if (inst->state != INST_UNINIT)
233e922a33eSStanimir Varbanov 		return -EALREADY;
234a367b9abSStanimir Varbanov 
2351a73374aSStanimir Varbanov 	inst->hfi_codec = to_codec_type(pixfmt);
23609c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
23709c2845eSStanimir Varbanov 
2381a73374aSStanimir Varbanov 	ret = ops->session_init(inst, inst->session_type, inst->hfi_codec);
23909c2845eSStanimir Varbanov 	if (ret)
24009c2845eSStanimir Varbanov 		return ret;
24109c2845eSStanimir Varbanov 
24209c2845eSStanimir Varbanov 	ret = wait_session_msg(inst);
24309c2845eSStanimir Varbanov 	if (ret)
24409c2845eSStanimir Varbanov 		return ret;
24509c2845eSStanimir Varbanov 
24609c2845eSStanimir Varbanov 	inst->state = INST_INIT;
24709c2845eSStanimir Varbanov 
24809c2845eSStanimir Varbanov 	return 0;
24909c2845eSStanimir Varbanov }
25009c2845eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_init);
25109c2845eSStanimir Varbanov 
hfi_session_destroy(struct venus_inst * inst)25209c2845eSStanimir Varbanov void hfi_session_destroy(struct venus_inst *inst)
25309c2845eSStanimir Varbanov {
25409c2845eSStanimir Varbanov 	struct venus_core *core = inst->core;
25509c2845eSStanimir Varbanov 
25609c2845eSStanimir Varbanov 	mutex_lock(&core->lock);
25709c2845eSStanimir Varbanov 	list_del_init(&inst->list);
258f0baa040SPeter Zijlstra 	if (atomic_dec_and_test(&core->insts_count))
259f0baa040SPeter Zijlstra 		wake_up_var(&core->insts_count);
26009c2845eSStanimir Varbanov 	mutex_unlock(&core->lock);
26109c2845eSStanimir Varbanov }
26209c2845eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_destroy);
26309c2845eSStanimir Varbanov 
hfi_session_deinit(struct venus_inst * inst)26409c2845eSStanimir Varbanov int hfi_session_deinit(struct venus_inst *inst)
26509c2845eSStanimir Varbanov {
26609c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
26709c2845eSStanimir Varbanov 	int ret;
26809c2845eSStanimir Varbanov 
26909c2845eSStanimir Varbanov 	if (inst->state == INST_UNINIT)
27009c2845eSStanimir Varbanov 		return 0;
27109c2845eSStanimir Varbanov 
27209c2845eSStanimir Varbanov 	if (inst->state < INST_INIT)
27309c2845eSStanimir Varbanov 		return -EINVAL;
27409c2845eSStanimir Varbanov 
2753efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
2763efc5204SStanimir Varbanov 		goto done;
2773efc5204SStanimir Varbanov 
27809c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
27909c2845eSStanimir Varbanov 
28009c2845eSStanimir Varbanov 	ret = ops->session_end(inst);
28109c2845eSStanimir Varbanov 	if (ret)
28209c2845eSStanimir Varbanov 		return ret;
28309c2845eSStanimir Varbanov 
28409c2845eSStanimir Varbanov 	ret = wait_session_msg(inst);
28509c2845eSStanimir Varbanov 	if (ret)
28609c2845eSStanimir Varbanov 		return ret;
28709c2845eSStanimir Varbanov 
2883efc5204SStanimir Varbanov done:
28909c2845eSStanimir Varbanov 	inst->state = INST_UNINIT;
29009c2845eSStanimir Varbanov 
29109c2845eSStanimir Varbanov 	return 0;
29209c2845eSStanimir Varbanov }
29309c2845eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_deinit);
29409c2845eSStanimir Varbanov 
hfi_session_start(struct venus_inst * inst)29509c2845eSStanimir Varbanov int hfi_session_start(struct venus_inst *inst)
29609c2845eSStanimir Varbanov {
29709c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
29809c2845eSStanimir Varbanov 	int ret;
29909c2845eSStanimir Varbanov 
3003efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
3013efc5204SStanimir Varbanov 		return -EIO;
3023efc5204SStanimir Varbanov 
30309c2845eSStanimir Varbanov 	if (inst->state != INST_LOAD_RESOURCES)
30409c2845eSStanimir Varbanov 		return -EINVAL;
30509c2845eSStanimir Varbanov 
30609c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
30709c2845eSStanimir Varbanov 
30809c2845eSStanimir Varbanov 	ret = ops->session_start(inst);
30909c2845eSStanimir Varbanov 	if (ret)
31009c2845eSStanimir Varbanov 		return ret;
31109c2845eSStanimir Varbanov 
31209c2845eSStanimir Varbanov 	ret = wait_session_msg(inst);
31309c2845eSStanimir Varbanov 	if (ret)
31409c2845eSStanimir Varbanov 		return ret;
31509c2845eSStanimir Varbanov 
31609c2845eSStanimir Varbanov 	inst->state = INST_START;
31709c2845eSStanimir Varbanov 
31809c2845eSStanimir Varbanov 	return 0;
31909c2845eSStanimir Varbanov }
320e42dbe8eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_start);
32109c2845eSStanimir Varbanov 
hfi_session_stop(struct venus_inst * inst)32209c2845eSStanimir Varbanov int hfi_session_stop(struct venus_inst *inst)
32309c2845eSStanimir Varbanov {
32409c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
32509c2845eSStanimir Varbanov 	int ret;
32609c2845eSStanimir Varbanov 
3273efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
3283efc5204SStanimir Varbanov 		return -EIO;
3293efc5204SStanimir Varbanov 
33009c2845eSStanimir Varbanov 	if (inst->state != INST_START)
33109c2845eSStanimir Varbanov 		return -EINVAL;
33209c2845eSStanimir Varbanov 
33309c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
33409c2845eSStanimir Varbanov 
33509c2845eSStanimir Varbanov 	ret = ops->session_stop(inst);
33609c2845eSStanimir Varbanov 	if (ret)
33709c2845eSStanimir Varbanov 		return ret;
33809c2845eSStanimir Varbanov 
33909c2845eSStanimir Varbanov 	ret = wait_session_msg(inst);
34009c2845eSStanimir Varbanov 	if (ret)
34109c2845eSStanimir Varbanov 		return ret;
34209c2845eSStanimir Varbanov 
34309c2845eSStanimir Varbanov 	inst->state = INST_STOP;
34409c2845eSStanimir Varbanov 
34509c2845eSStanimir Varbanov 	return 0;
34609c2845eSStanimir Varbanov }
347e42dbe8eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_stop);
34809c2845eSStanimir Varbanov 
hfi_session_continue(struct venus_inst * inst)34909c2845eSStanimir Varbanov int hfi_session_continue(struct venus_inst *inst)
35009c2845eSStanimir Varbanov {
35109c2845eSStanimir Varbanov 	struct venus_core *core = inst->core;
35209c2845eSStanimir Varbanov 
3533efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
3543efc5204SStanimir Varbanov 		return -EIO;
3553efc5204SStanimir Varbanov 
3562074b9beSStanimir Varbanov 	if (core->res->hfi_version == HFI_VERSION_1XX)
35709c2845eSStanimir Varbanov 		return 0;
35809c2845eSStanimir Varbanov 
35909c2845eSStanimir Varbanov 	return core->ops->session_continue(inst);
36009c2845eSStanimir Varbanov }
36109c2845eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_continue);
36209c2845eSStanimir Varbanov 
hfi_session_abort(struct venus_inst * inst)36309c2845eSStanimir Varbanov int hfi_session_abort(struct venus_inst *inst)
36409c2845eSStanimir Varbanov {
36509c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
36609c2845eSStanimir Varbanov 	int ret;
36709c2845eSStanimir Varbanov 
3683efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
3693efc5204SStanimir Varbanov 		return -EIO;
3703efc5204SStanimir Varbanov 
37109c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
37209c2845eSStanimir Varbanov 
37309c2845eSStanimir Varbanov 	ret = ops->session_abort(inst);
37409c2845eSStanimir Varbanov 	if (ret)
37509c2845eSStanimir Varbanov 		return ret;
37609c2845eSStanimir Varbanov 
37709c2845eSStanimir Varbanov 	ret = wait_session_msg(inst);
37809c2845eSStanimir Varbanov 	if (ret)
37909c2845eSStanimir Varbanov 		return ret;
38009c2845eSStanimir Varbanov 
38109c2845eSStanimir Varbanov 	return 0;
38209c2845eSStanimir Varbanov }
383e42dbe8eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_abort);
38409c2845eSStanimir Varbanov 
hfi_session_load_res(struct venus_inst * inst)38509c2845eSStanimir Varbanov int hfi_session_load_res(struct venus_inst *inst)
38609c2845eSStanimir Varbanov {
38709c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
38809c2845eSStanimir Varbanov 	int ret;
38909c2845eSStanimir Varbanov 
3903efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
3913efc5204SStanimir Varbanov 		return -EIO;
3923efc5204SStanimir Varbanov 
39309c2845eSStanimir Varbanov 	if (inst->state != INST_INIT)
39409c2845eSStanimir Varbanov 		return -EINVAL;
39509c2845eSStanimir Varbanov 
39609c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
39709c2845eSStanimir Varbanov 
39809c2845eSStanimir Varbanov 	ret = ops->session_load_res(inst);
39909c2845eSStanimir Varbanov 	if (ret)
40009c2845eSStanimir Varbanov 		return ret;
40109c2845eSStanimir Varbanov 
40209c2845eSStanimir Varbanov 	ret = wait_session_msg(inst);
40309c2845eSStanimir Varbanov 	if (ret)
40409c2845eSStanimir Varbanov 		return ret;
40509c2845eSStanimir Varbanov 
40609c2845eSStanimir Varbanov 	inst->state = INST_LOAD_RESOURCES;
40709c2845eSStanimir Varbanov 
40809c2845eSStanimir Varbanov 	return 0;
40909c2845eSStanimir Varbanov }
41009c2845eSStanimir Varbanov 
hfi_session_unload_res(struct venus_inst * inst)41109c2845eSStanimir Varbanov int hfi_session_unload_res(struct venus_inst *inst)
41209c2845eSStanimir Varbanov {
41309c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
41409c2845eSStanimir Varbanov 	int ret;
41509c2845eSStanimir Varbanov 
4163efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
4173efc5204SStanimir Varbanov 		return -EIO;
4183efc5204SStanimir Varbanov 
41909c2845eSStanimir Varbanov 	if (inst->state != INST_STOP)
42009c2845eSStanimir Varbanov 		return -EINVAL;
42109c2845eSStanimir Varbanov 
42209c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
42309c2845eSStanimir Varbanov 
42409c2845eSStanimir Varbanov 	ret = ops->session_release_res(inst);
42509c2845eSStanimir Varbanov 	if (ret)
42609c2845eSStanimir Varbanov 		return ret;
42709c2845eSStanimir Varbanov 
42809c2845eSStanimir Varbanov 	ret = wait_session_msg(inst);
42909c2845eSStanimir Varbanov 	if (ret)
43009c2845eSStanimir Varbanov 		return ret;
43109c2845eSStanimir Varbanov 
43209c2845eSStanimir Varbanov 	inst->state = INST_RELEASE_RESOURCES;
43309c2845eSStanimir Varbanov 
43409c2845eSStanimir Varbanov 	return 0;
43509c2845eSStanimir Varbanov }
436e42dbe8eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_unload_res);
43709c2845eSStanimir Varbanov 
hfi_session_flush(struct venus_inst * inst,u32 type,bool block)43885872f86SStanimir Varbanov int hfi_session_flush(struct venus_inst *inst, u32 type, bool block)
43909c2845eSStanimir Varbanov {
44009c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
44109c2845eSStanimir Varbanov 	int ret;
44209c2845eSStanimir Varbanov 
4433efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
4443efc5204SStanimir Varbanov 		return -EIO;
4453efc5204SStanimir Varbanov 
44609c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
44709c2845eSStanimir Varbanov 
44805dea798SStanimir Varbanov 	ret = ops->session_flush(inst, type);
44909c2845eSStanimir Varbanov 	if (ret)
45009c2845eSStanimir Varbanov 		return ret;
45109c2845eSStanimir Varbanov 
45285872f86SStanimir Varbanov 	if (block) {
45309c2845eSStanimir Varbanov 		ret = wait_session_msg(inst);
45409c2845eSStanimir Varbanov 		if (ret)
45509c2845eSStanimir Varbanov 			return ret;
45685872f86SStanimir Varbanov 	}
45709c2845eSStanimir Varbanov 
45809c2845eSStanimir Varbanov 	return 0;
45909c2845eSStanimir Varbanov }
46009c2845eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_flush);
46109c2845eSStanimir Varbanov 
hfi_session_set_buffers(struct venus_inst * inst,struct hfi_buffer_desc * bd)46209c2845eSStanimir Varbanov int hfi_session_set_buffers(struct venus_inst *inst, struct hfi_buffer_desc *bd)
46309c2845eSStanimir Varbanov {
46409c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
46509c2845eSStanimir Varbanov 
4663efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
4673efc5204SStanimir Varbanov 		return -EIO;
4683efc5204SStanimir Varbanov 
46909c2845eSStanimir Varbanov 	return ops->session_set_buffers(inst, bd);
47009c2845eSStanimir Varbanov }
47109c2845eSStanimir Varbanov 
hfi_session_unset_buffers(struct venus_inst * inst,struct hfi_buffer_desc * bd)47209c2845eSStanimir Varbanov int hfi_session_unset_buffers(struct venus_inst *inst,
47309c2845eSStanimir Varbanov 			      struct hfi_buffer_desc *bd)
47409c2845eSStanimir Varbanov {
47509c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
47609c2845eSStanimir Varbanov 	int ret;
47709c2845eSStanimir Varbanov 
4783efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
4793efc5204SStanimir Varbanov 		return -EIO;
4803efc5204SStanimir Varbanov 
48109c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
48209c2845eSStanimir Varbanov 
48309c2845eSStanimir Varbanov 	ret = ops->session_unset_buffers(inst, bd);
48409c2845eSStanimir Varbanov 	if (ret)
48509c2845eSStanimir Varbanov 		return ret;
48609c2845eSStanimir Varbanov 
48709c2845eSStanimir Varbanov 	if (!bd->response_required)
48809c2845eSStanimir Varbanov 		return 0;
48909c2845eSStanimir Varbanov 
49009c2845eSStanimir Varbanov 	ret = wait_session_msg(inst);
49109c2845eSStanimir Varbanov 	if (ret)
49209c2845eSStanimir Varbanov 		return ret;
49309c2845eSStanimir Varbanov 
49409c2845eSStanimir Varbanov 	return 0;
49509c2845eSStanimir Varbanov }
49609c2845eSStanimir Varbanov 
hfi_session_get_property(struct venus_inst * inst,u32 ptype,union hfi_get_property * hprop)49709c2845eSStanimir Varbanov int hfi_session_get_property(struct venus_inst *inst, u32 ptype,
49809c2845eSStanimir Varbanov 			     union hfi_get_property *hprop)
49909c2845eSStanimir Varbanov {
50009c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
50109c2845eSStanimir Varbanov 	int ret;
50209c2845eSStanimir Varbanov 
5033efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
5043efc5204SStanimir Varbanov 		return -EIO;
5053efc5204SStanimir Varbanov 
50609c2845eSStanimir Varbanov 	if (inst->state < INST_INIT || inst->state >= INST_STOP)
50709c2845eSStanimir Varbanov 		return -EINVAL;
50809c2845eSStanimir Varbanov 
50909c2845eSStanimir Varbanov 	reinit_completion(&inst->done);
51009c2845eSStanimir Varbanov 
51109c2845eSStanimir Varbanov 	ret = ops->session_get_property(inst, ptype);
51209c2845eSStanimir Varbanov 	if (ret)
51309c2845eSStanimir Varbanov 		return ret;
51409c2845eSStanimir Varbanov 
51509c2845eSStanimir Varbanov 	ret = wait_session_msg(inst);
51609c2845eSStanimir Varbanov 	if (ret)
51709c2845eSStanimir Varbanov 		return ret;
51809c2845eSStanimir Varbanov 
51909c2845eSStanimir Varbanov 	*hprop = inst->hprop;
52009c2845eSStanimir Varbanov 
52109c2845eSStanimir Varbanov 	return 0;
52209c2845eSStanimir Varbanov }
52309c2845eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_get_property);
52409c2845eSStanimir Varbanov 
hfi_session_set_property(struct venus_inst * inst,u32 ptype,void * pdata)52509c2845eSStanimir Varbanov int hfi_session_set_property(struct venus_inst *inst, u32 ptype, void *pdata)
52609c2845eSStanimir Varbanov {
52709c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
52809c2845eSStanimir Varbanov 
5293efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
5303efc5204SStanimir Varbanov 		return -EIO;
5313efc5204SStanimir Varbanov 
53209c2845eSStanimir Varbanov 	if (inst->state < INST_INIT || inst->state >= INST_STOP)
53309c2845eSStanimir Varbanov 		return -EINVAL;
53409c2845eSStanimir Varbanov 
53509c2845eSStanimir Varbanov 	return ops->session_set_property(inst, ptype, pdata);
53609c2845eSStanimir Varbanov }
53709c2845eSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_set_property);
53809c2845eSStanimir Varbanov 
hfi_session_process_buf(struct venus_inst * inst,struct hfi_frame_data * fd)53909c2845eSStanimir Varbanov int hfi_session_process_buf(struct venus_inst *inst, struct hfi_frame_data *fd)
54009c2845eSStanimir Varbanov {
54109c2845eSStanimir Varbanov 	const struct hfi_ops *ops = inst->core->ops;
54209c2845eSStanimir Varbanov 
5433efc5204SStanimir Varbanov 	if (test_bit(0, &inst->core->sys_error))
5443efc5204SStanimir Varbanov 		return -EIO;
5453efc5204SStanimir Varbanov 
54609c2845eSStanimir Varbanov 	if (fd->buffer_type == HFI_BUFFER_INPUT)
54709c2845eSStanimir Varbanov 		return ops->session_etb(inst, fd);
5485f43f90aSStanimir Varbanov 	else if (fd->buffer_type == HFI_BUFFER_OUTPUT ||
5495f43f90aSStanimir Varbanov 		 fd->buffer_type == HFI_BUFFER_OUTPUT2)
55009c2845eSStanimir Varbanov 		return ops->session_ftb(inst, fd);
55109c2845eSStanimir Varbanov 
55209c2845eSStanimir Varbanov 	return -EINVAL;
55309c2845eSStanimir Varbanov }
554e69b987aSStanimir Varbanov EXPORT_SYMBOL_GPL(hfi_session_process_buf);
55509c2845eSStanimir Varbanov 
hfi_isr_thread(int irq,void * dev_id)55609c2845eSStanimir Varbanov irqreturn_t hfi_isr_thread(int irq, void *dev_id)
55709c2845eSStanimir Varbanov {
55809c2845eSStanimir Varbanov 	struct venus_core *core = dev_id;
55909c2845eSStanimir Varbanov 
56009c2845eSStanimir Varbanov 	return core->ops->isr_thread(core);
56109c2845eSStanimir Varbanov }
56209c2845eSStanimir Varbanov 
hfi_isr(int irq,void * dev)56309c2845eSStanimir Varbanov irqreturn_t hfi_isr(int irq, void *dev)
56409c2845eSStanimir Varbanov {
56509c2845eSStanimir Varbanov 	struct venus_core *core = dev;
56609c2845eSStanimir Varbanov 
56709c2845eSStanimir Varbanov 	return core->ops->isr(core);
56809c2845eSStanimir Varbanov }
56909c2845eSStanimir Varbanov 
hfi_create(struct venus_core * core,const struct hfi_core_ops * ops)57009c2845eSStanimir Varbanov int hfi_create(struct venus_core *core, const struct hfi_core_ops *ops)
57109c2845eSStanimir Varbanov {
57209c2845eSStanimir Varbanov 	if (!ops)
57309c2845eSStanimir Varbanov 		return -EINVAL;
57409c2845eSStanimir Varbanov 
57509c2845eSStanimir Varbanov 	atomic_set(&core->insts_count, 0);
57609c2845eSStanimir Varbanov 	core->core_ops = ops;
57709c2845eSStanimir Varbanov 	core->state = CORE_UNINIT;
57809c2845eSStanimir Varbanov 	init_completion(&core->done);
57909c2845eSStanimir Varbanov 	pkt_set_version(core->res->hfi_version);
58009c2845eSStanimir Varbanov 
581*265f2fc5Sye xingchen 	return venus_hfi_create(core);
58209c2845eSStanimir Varbanov }
58309c2845eSStanimir Varbanov 
hfi_destroy(struct venus_core * core)58409c2845eSStanimir Varbanov void hfi_destroy(struct venus_core *core)
58509c2845eSStanimir Varbanov {
58609c2845eSStanimir Varbanov 	venus_hfi_destroy(core);
58709c2845eSStanimir Varbanov }
58873d513e4SStanimir Varbanov 
hfi_reinit(struct venus_core * core)58973d513e4SStanimir Varbanov void hfi_reinit(struct venus_core *core)
59073d513e4SStanimir Varbanov {
59173d513e4SStanimir Varbanov 	venus_hfi_queues_reinit(core);
59273d513e4SStanimir Varbanov }
593