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
);
107 ret
= core
->ops
->core_deinit(core
);
110 core
->state
= CORE_UNINIT
;
113 mutex_unlock(&core
->lock
);
117 int hfi_core_suspend(struct venus_core
*core
)
119 if (core
->state
!= CORE_INIT
)
122 return core
->ops
->suspend(core
);
125 int hfi_core_resume(struct venus_core
*core
, bool force
)
127 if (!force
&& core
->state
!= CORE_INIT
)
130 return core
->ops
->resume(core
);
133 int hfi_core_trigger_ssr(struct venus_core
*core
, u32 type
)
135 return core
->ops
->core_trigger_ssr(core
, type
);
138 int hfi_core_ping(struct venus_core
*core
)
142 mutex_lock(&core
->lock
);
144 ret
= core
->ops
->core_ping(core
, 0xbeef);
148 ret
= wait_for_completion_timeout(&core
->done
, TIMEOUT
);
154 if (core
->error
!= HFI_ERR_NONE
)
157 mutex_unlock(&core
->lock
);
161 static int wait_session_msg(struct venus_inst
*inst
)
165 ret
= wait_for_completion_timeout(&inst
->done
, TIMEOUT
);
169 if (inst
->error
!= HFI_ERR_NONE
)
175 int hfi_session_create(struct venus_inst
*inst
, const struct hfi_inst_ops
*ops
)
177 struct venus_core
*core
= inst
->core
;
182 inst
->state
= INST_UNINIT
;
183 init_completion(&inst
->done
);
186 mutex_lock(&core
->lock
);
187 list_add_tail(&inst
->list
, &core
->instances
);
188 atomic_inc(&core
->insts_count
);
189 mutex_unlock(&core
->lock
);
193 EXPORT_SYMBOL_GPL(hfi_session_create
);
195 int hfi_session_init(struct venus_inst
*inst
, u32 pixfmt
)
197 struct venus_core
*core
= inst
->core
;
198 const struct hfi_ops
*ops
= core
->ops
;
201 if (inst
->state
!= INST_UNINIT
)
204 inst
->hfi_codec
= to_codec_type(pixfmt
);
205 reinit_completion(&inst
->done
);
207 ret
= ops
->session_init(inst
, inst
->session_type
, inst
->hfi_codec
);
211 ret
= wait_session_msg(inst
);
215 inst
->state
= INST_INIT
;
219 EXPORT_SYMBOL_GPL(hfi_session_init
);
221 void hfi_session_destroy(struct venus_inst
*inst
)
223 struct venus_core
*core
= inst
->core
;
225 mutex_lock(&core
->lock
);
226 list_del_init(&inst
->list
);
227 if (atomic_dec_and_test(&core
->insts_count
))
228 wake_up_var(&core
->insts_count
);
229 mutex_unlock(&core
->lock
);
231 EXPORT_SYMBOL_GPL(hfi_session_destroy
);
233 int hfi_session_deinit(struct venus_inst
*inst
)
235 const struct hfi_ops
*ops
= inst
->core
->ops
;
238 if (inst
->state
== INST_UNINIT
)
241 if (inst
->state
< INST_INIT
)
244 reinit_completion(&inst
->done
);
246 ret
= ops
->session_end(inst
);
250 ret
= wait_session_msg(inst
);
254 inst
->state
= INST_UNINIT
;
258 EXPORT_SYMBOL_GPL(hfi_session_deinit
);
260 int hfi_session_start(struct venus_inst
*inst
)
262 const struct hfi_ops
*ops
= inst
->core
->ops
;
265 if (inst
->state
!= INST_LOAD_RESOURCES
)
268 reinit_completion(&inst
->done
);
270 ret
= ops
->session_start(inst
);
274 ret
= wait_session_msg(inst
);
278 inst
->state
= INST_START
;
282 EXPORT_SYMBOL_GPL(hfi_session_start
);
284 int hfi_session_stop(struct venus_inst
*inst
)
286 const struct hfi_ops
*ops
= inst
->core
->ops
;
289 if (inst
->state
!= INST_START
)
292 reinit_completion(&inst
->done
);
294 ret
= ops
->session_stop(inst
);
298 ret
= wait_session_msg(inst
);
302 inst
->state
= INST_STOP
;
306 EXPORT_SYMBOL_GPL(hfi_session_stop
);
308 int hfi_session_continue(struct venus_inst
*inst
)
310 struct venus_core
*core
= inst
->core
;
312 if (core
->res
->hfi_version
== HFI_VERSION_1XX
)
315 return core
->ops
->session_continue(inst
);
317 EXPORT_SYMBOL_GPL(hfi_session_continue
);
319 int hfi_session_abort(struct venus_inst
*inst
)
321 const struct hfi_ops
*ops
= inst
->core
->ops
;
324 reinit_completion(&inst
->done
);
326 ret
= ops
->session_abort(inst
);
330 ret
= wait_session_msg(inst
);
336 EXPORT_SYMBOL_GPL(hfi_session_abort
);
338 int hfi_session_load_res(struct venus_inst
*inst
)
340 const struct hfi_ops
*ops
= inst
->core
->ops
;
343 if (inst
->state
!= INST_INIT
)
346 reinit_completion(&inst
->done
);
348 ret
= ops
->session_load_res(inst
);
352 ret
= wait_session_msg(inst
);
356 inst
->state
= INST_LOAD_RESOURCES
;
361 int hfi_session_unload_res(struct venus_inst
*inst
)
363 const struct hfi_ops
*ops
= inst
->core
->ops
;
366 if (inst
->state
!= INST_STOP
)
369 reinit_completion(&inst
->done
);
371 ret
= ops
->session_release_res(inst
);
375 ret
= wait_session_msg(inst
);
379 inst
->state
= INST_RELEASE_RESOURCES
;
383 EXPORT_SYMBOL_GPL(hfi_session_unload_res
);
385 int hfi_session_flush(struct venus_inst
*inst
, u32 type
)
387 const struct hfi_ops
*ops
= inst
->core
->ops
;
390 reinit_completion(&inst
->done
);
392 ret
= ops
->session_flush(inst
, type
);
396 ret
= wait_session_msg(inst
);
402 EXPORT_SYMBOL_GPL(hfi_session_flush
);
404 int hfi_session_set_buffers(struct venus_inst
*inst
, struct hfi_buffer_desc
*bd
)
406 const struct hfi_ops
*ops
= inst
->core
->ops
;
408 return ops
->session_set_buffers(inst
, bd
);
411 int hfi_session_unset_buffers(struct venus_inst
*inst
,
412 struct hfi_buffer_desc
*bd
)
414 const struct hfi_ops
*ops
= inst
->core
->ops
;
417 reinit_completion(&inst
->done
);
419 ret
= ops
->session_unset_buffers(inst
, bd
);
423 if (!bd
->response_required
)
426 ret
= wait_session_msg(inst
);
433 int hfi_session_get_property(struct venus_inst
*inst
, u32 ptype
,
434 union hfi_get_property
*hprop
)
436 const struct hfi_ops
*ops
= inst
->core
->ops
;
439 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
442 reinit_completion(&inst
->done
);
444 ret
= ops
->session_get_property(inst
, ptype
);
448 ret
= wait_session_msg(inst
);
452 *hprop
= inst
->hprop
;
456 EXPORT_SYMBOL_GPL(hfi_session_get_property
);
458 int hfi_session_set_property(struct venus_inst
*inst
, u32 ptype
, void *pdata
)
460 const struct hfi_ops
*ops
= inst
->core
->ops
;
462 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
465 return ops
->session_set_property(inst
, ptype
, pdata
);
467 EXPORT_SYMBOL_GPL(hfi_session_set_property
);
469 int hfi_session_process_buf(struct venus_inst
*inst
, struct hfi_frame_data
*fd
)
471 const struct hfi_ops
*ops
= inst
->core
->ops
;
473 if (fd
->buffer_type
== HFI_BUFFER_INPUT
)
474 return ops
->session_etb(inst
, fd
);
475 else if (fd
->buffer_type
== HFI_BUFFER_OUTPUT
||
476 fd
->buffer_type
== HFI_BUFFER_OUTPUT2
)
477 return ops
->session_ftb(inst
, fd
);
481 EXPORT_SYMBOL_GPL(hfi_session_process_buf
);
483 irqreturn_t
hfi_isr_thread(int irq
, void *dev_id
)
485 struct venus_core
*core
= dev_id
;
487 return core
->ops
->isr_thread(core
);
490 irqreturn_t
hfi_isr(int irq
, void *dev
)
492 struct venus_core
*core
= dev
;
494 return core
->ops
->isr(core
);
497 int hfi_create(struct venus_core
*core
, const struct hfi_core_ops
*ops
)
504 atomic_set(&core
->insts_count
, 0);
505 core
->core_ops
= ops
;
506 core
->state
= CORE_UNINIT
;
507 init_completion(&core
->done
);
508 pkt_set_version(core
->res
->hfi_version
);
509 ret
= venus_hfi_create(core
);
514 void hfi_destroy(struct venus_core
*core
)
516 venus_hfi_destroy(core
);