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