1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2017 Linaro Ltd.
6 #include <linux/slab.h>
7 #include <linux/mutex.h>
8 #include <linux/list.h>
9 #include <linux/completion.h>
10 #include <linux/platform_device.h>
11 #include <linux/videodev2.h>
16 #include "hfi_venus.h"
18 #define TIMEOUT msecs_to_jiffies(1000)
20 static u32 to_codec_type(u32 pixfmt)
23 case V4L2_PIX_FMT_H264:
24 case V4L2_PIX_FMT_H264_NO_SC:
25 return HFI_VIDEO_CODEC_H264;
26 case V4L2_PIX_FMT_H263:
27 return HFI_VIDEO_CODEC_H263;
28 case V4L2_PIX_FMT_MPEG1:
29 return HFI_VIDEO_CODEC_MPEG1;
30 case V4L2_PIX_FMT_MPEG2:
31 return HFI_VIDEO_CODEC_MPEG2;
32 case V4L2_PIX_FMT_MPEG4:
33 return HFI_VIDEO_CODEC_MPEG4;
34 case V4L2_PIX_FMT_VC1_ANNEX_G:
35 case V4L2_PIX_FMT_VC1_ANNEX_L:
36 return HFI_VIDEO_CODEC_VC1;
37 case V4L2_PIX_FMT_VP8:
38 return HFI_VIDEO_CODEC_VP8;
39 case V4L2_PIX_FMT_VP9:
40 return HFI_VIDEO_CODEC_VP9;
41 case V4L2_PIX_FMT_XVID:
42 return HFI_VIDEO_CODEC_DIVX;
43 case V4L2_PIX_FMT_HEVC:
44 return HFI_VIDEO_CODEC_HEVC;
50 int hfi_core_init(struct venus_core *core)
54 mutex_lock(&core->lock);
56 if (core->state >= CORE_INIT)
59 reinit_completion(&core->done);
61 ret = core->ops->core_init(core);
65 ret = wait_for_completion_timeout(&core->done, TIMEOUT);
73 if (core->error != HFI_ERR_NONE) {
78 core->state = CORE_INIT;
80 mutex_unlock(&core->lock);
84 int hfi_core_deinit(struct venus_core *core, bool blocking)
88 mutex_lock(&core->lock);
90 if (core->state == CORE_UNINIT)
93 empty = list_empty(&core->instances);
95 if (!empty && !blocking) {
101 mutex_unlock(&core->lock);
102 wait_var_event(&core->insts_count,
103 !atomic_read(&core->insts_count));
104 mutex_lock(&core->lock);
110 ret = core->ops->core_deinit(core);
113 core->state = CORE_UNINIT;
116 mutex_unlock(&core->lock);
120 int hfi_core_suspend(struct venus_core *core)
122 if (core->state != CORE_INIT)
125 return core->ops->suspend(core);
128 int hfi_core_resume(struct venus_core *core, bool force)
130 if (!force && core->state != CORE_INIT)
133 return core->ops->resume(core);
136 int hfi_core_trigger_ssr(struct venus_core *core, u32 type)
138 return core->ops->core_trigger_ssr(core, type);
141 int hfi_core_ping(struct venus_core *core)
145 mutex_lock(&core->lock);
147 ret = core->ops->core_ping(core, 0xbeef);
151 ret = wait_for_completion_timeout(&core->done, TIMEOUT);
157 if (core->error != HFI_ERR_NONE)
160 mutex_unlock(&core->lock);
164 static int wait_session_msg(struct venus_inst *inst)
168 ret = wait_for_completion_timeout(&inst->done, TIMEOUT);
172 if (inst->error != HFI_ERR_NONE)
178 int hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops)
180 struct venus_core *core = inst->core;
187 inst->state = INST_UNINIT;
188 init_completion(&inst->done);
191 mutex_lock(&core->lock);
193 if (test_bit(0, &inst->core->sys_error)) {
198 max = atomic_add_unless(&core->insts_count, 1,
199 core->max_sessions_supported);
203 list_add_tail(&inst->list, &core->instances);
208 mutex_unlock(&core->lock);
212 EXPORT_SYMBOL_GPL(hfi_session_create);
214 int hfi_session_init(struct venus_inst *inst, u32 pixfmt)
216 struct venus_core *core = inst->core;
217 const struct hfi_ops *ops = core->ops;
221 * If core shutdown is in progress or if we are in system
222 * recovery, return an error as during system error recovery
223 * session_init() can't pass successfully
225 mutex_lock(&core->lock);
226 if (!core->ops || test_bit(0, &inst->core->sys_error)) {
227 mutex_unlock(&core->lock);
230 mutex_unlock(&core->lock);
232 if (inst->state != INST_UNINIT)
235 inst->hfi_codec = to_codec_type(pixfmt);
236 reinit_completion(&inst->done);
238 ret = ops->session_init(inst, inst->session_type, inst->hfi_codec);
242 ret = wait_session_msg(inst);
246 inst->state = INST_INIT;
250 EXPORT_SYMBOL_GPL(hfi_session_init);
252 void hfi_session_destroy(struct venus_inst *inst)
254 struct venus_core *core = inst->core;
256 mutex_lock(&core->lock);
257 list_del_init(&inst->list);
258 if (atomic_dec_and_test(&core->insts_count))
259 wake_up_var(&core->insts_count);
260 mutex_unlock(&core->lock);
262 EXPORT_SYMBOL_GPL(hfi_session_destroy);
264 int hfi_session_deinit(struct venus_inst *inst)
266 const struct hfi_ops *ops = inst->core->ops;
269 if (inst->state == INST_UNINIT)
272 if (inst->state < INST_INIT)
275 if (test_bit(0, &inst->core->sys_error))
278 reinit_completion(&inst->done);
280 ret = ops->session_end(inst);
284 ret = wait_session_msg(inst);
289 inst->state = INST_UNINIT;
293 EXPORT_SYMBOL_GPL(hfi_session_deinit);
295 int hfi_session_start(struct venus_inst *inst)
297 const struct hfi_ops *ops = inst->core->ops;
300 if (test_bit(0, &inst->core->sys_error))
303 if (inst->state != INST_LOAD_RESOURCES)
306 reinit_completion(&inst->done);
308 ret = ops->session_start(inst);
312 ret = wait_session_msg(inst);
316 inst->state = INST_START;
320 EXPORT_SYMBOL_GPL(hfi_session_start);
322 int hfi_session_stop(struct venus_inst *inst)
324 const struct hfi_ops *ops = inst->core->ops;
327 if (test_bit(0, &inst->core->sys_error))
330 if (inst->state != INST_START)
333 reinit_completion(&inst->done);
335 ret = ops->session_stop(inst);
339 ret = wait_session_msg(inst);
343 inst->state = INST_STOP;
347 EXPORT_SYMBOL_GPL(hfi_session_stop);
349 int hfi_session_continue(struct venus_inst *inst)
351 struct venus_core *core = inst->core;
353 if (test_bit(0, &inst->core->sys_error))
356 if (core->res->hfi_version == HFI_VERSION_1XX)
359 return core->ops->session_continue(inst);
361 EXPORT_SYMBOL_GPL(hfi_session_continue);
363 int hfi_session_abort(struct venus_inst *inst)
365 const struct hfi_ops *ops = inst->core->ops;
368 if (test_bit(0, &inst->core->sys_error))
371 reinit_completion(&inst->done);
373 ret = ops->session_abort(inst);
377 ret = wait_session_msg(inst);
383 EXPORT_SYMBOL_GPL(hfi_session_abort);
385 int hfi_session_load_res(struct venus_inst *inst)
387 const struct hfi_ops *ops = inst->core->ops;
390 if (test_bit(0, &inst->core->sys_error))
393 if (inst->state != INST_INIT)
396 reinit_completion(&inst->done);
398 ret = ops->session_load_res(inst);
402 ret = wait_session_msg(inst);
406 inst->state = INST_LOAD_RESOURCES;
411 int hfi_session_unload_res(struct venus_inst *inst)
413 const struct hfi_ops *ops = inst->core->ops;
416 if (test_bit(0, &inst->core->sys_error))
419 if (inst->state != INST_STOP)
422 reinit_completion(&inst->done);
424 ret = ops->session_release_res(inst);
428 ret = wait_session_msg(inst);
432 inst->state = INST_RELEASE_RESOURCES;
436 EXPORT_SYMBOL_GPL(hfi_session_unload_res);
438 int hfi_session_flush(struct venus_inst *inst, u32 type, bool block)
440 const struct hfi_ops *ops = inst->core->ops;
443 if (test_bit(0, &inst->core->sys_error))
446 reinit_completion(&inst->done);
448 ret = ops->session_flush(inst, type);
453 ret = wait_session_msg(inst);
460 EXPORT_SYMBOL_GPL(hfi_session_flush);
462 int hfi_session_set_buffers(struct venus_inst *inst, struct hfi_buffer_desc *bd)
464 const struct hfi_ops *ops = inst->core->ops;
466 if (test_bit(0, &inst->core->sys_error))
469 return ops->session_set_buffers(inst, bd);
472 int hfi_session_unset_buffers(struct venus_inst *inst,
473 struct hfi_buffer_desc *bd)
475 const struct hfi_ops *ops = inst->core->ops;
478 if (test_bit(0, &inst->core->sys_error))
481 reinit_completion(&inst->done);
483 ret = ops->session_unset_buffers(inst, bd);
487 if (!bd->response_required)
490 ret = wait_session_msg(inst);
497 int hfi_session_get_property(struct venus_inst *inst, u32 ptype,
498 union hfi_get_property *hprop)
500 const struct hfi_ops *ops = inst->core->ops;
503 if (test_bit(0, &inst->core->sys_error))
506 if (inst->state < INST_INIT || inst->state >= INST_STOP)
509 reinit_completion(&inst->done);
511 ret = ops->session_get_property(inst, ptype);
515 ret = wait_session_msg(inst);
519 *hprop = inst->hprop;
523 EXPORT_SYMBOL_GPL(hfi_session_get_property);
525 int hfi_session_set_property(struct venus_inst *inst, u32 ptype, void *pdata)
527 const struct hfi_ops *ops = inst->core->ops;
529 if (test_bit(0, &inst->core->sys_error))
532 if (inst->state < INST_INIT || inst->state >= INST_STOP)
535 return ops->session_set_property(inst, ptype, pdata);
537 EXPORT_SYMBOL_GPL(hfi_session_set_property);
539 int hfi_session_process_buf(struct venus_inst *inst, struct hfi_frame_data *fd)
541 const struct hfi_ops *ops = inst->core->ops;
543 if (test_bit(0, &inst->core->sys_error))
546 if (fd->buffer_type == HFI_BUFFER_INPUT)
547 return ops->session_etb(inst, fd);
548 else if (fd->buffer_type == HFI_BUFFER_OUTPUT ||
549 fd->buffer_type == HFI_BUFFER_OUTPUT2)
550 return ops->session_ftb(inst, fd);
554 EXPORT_SYMBOL_GPL(hfi_session_process_buf);
556 irqreturn_t hfi_isr_thread(int irq, void *dev_id)
558 struct venus_core *core = dev_id;
560 return core->ops->isr_thread(core);
563 irqreturn_t hfi_isr(int irq, void *dev)
565 struct venus_core *core = dev;
567 return core->ops->isr(core);
570 int hfi_create(struct venus_core *core, const struct hfi_core_ops *ops)
575 atomic_set(&core->insts_count, 0);
576 core->core_ops = ops;
577 core->state = CORE_UNINIT;
578 init_completion(&core->done);
579 pkt_set_version(core->res->hfi_version);
581 return venus_hfi_create(core);
584 void hfi_destroy(struct venus_core *core)
586 venus_hfi_destroy(core);
589 void hfi_reinit(struct venus_core *core)
591 venus_hfi_queues_reinit(core);