]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - drivers/media/platform/qcom/venus/hfi.c
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 inst
->hfi_codec
= to_codec_type(pixfmt
);
202 reinit_completion(&inst
->done
);
204 ret
= ops
->session_init(inst
, inst
->session_type
, inst
->hfi_codec
);
208 ret
= wait_session_msg(inst
);
212 inst
->state
= INST_INIT
;
216 EXPORT_SYMBOL_GPL(hfi_session_init
);
218 void hfi_session_destroy(struct venus_inst
*inst
)
220 struct venus_core
*core
= inst
->core
;
222 mutex_lock(&core
->lock
);
223 list_del_init(&inst
->list
);
224 if (atomic_dec_and_test(&core
->insts_count
))
225 wake_up_var(&core
->insts_count
);
226 mutex_unlock(&core
->lock
);
228 EXPORT_SYMBOL_GPL(hfi_session_destroy
);
230 int hfi_session_deinit(struct venus_inst
*inst
)
232 const struct hfi_ops
*ops
= inst
->core
->ops
;
235 if (inst
->state
== INST_UNINIT
)
238 if (inst
->state
< INST_INIT
)
241 reinit_completion(&inst
->done
);
243 ret
= ops
->session_end(inst
);
247 ret
= wait_session_msg(inst
);
251 inst
->state
= INST_UNINIT
;
255 EXPORT_SYMBOL_GPL(hfi_session_deinit
);
257 int hfi_session_start(struct venus_inst
*inst
)
259 const struct hfi_ops
*ops
= inst
->core
->ops
;
262 if (inst
->state
!= INST_LOAD_RESOURCES
)
265 reinit_completion(&inst
->done
);
267 ret
= ops
->session_start(inst
);
271 ret
= wait_session_msg(inst
);
275 inst
->state
= INST_START
;
280 int hfi_session_stop(struct venus_inst
*inst
)
282 const struct hfi_ops
*ops
= inst
->core
->ops
;
285 if (inst
->state
!= INST_START
)
288 reinit_completion(&inst
->done
);
290 ret
= ops
->session_stop(inst
);
294 ret
= wait_session_msg(inst
);
298 inst
->state
= INST_STOP
;
303 int hfi_session_continue(struct venus_inst
*inst
)
305 struct venus_core
*core
= inst
->core
;
307 if (core
->res
->hfi_version
== HFI_VERSION_1XX
)
310 return core
->ops
->session_continue(inst
);
312 EXPORT_SYMBOL_GPL(hfi_session_continue
);
314 int hfi_session_abort(struct venus_inst
*inst
)
316 const struct hfi_ops
*ops
= inst
->core
->ops
;
319 reinit_completion(&inst
->done
);
321 ret
= ops
->session_abort(inst
);
325 ret
= wait_session_msg(inst
);
332 int hfi_session_load_res(struct venus_inst
*inst
)
334 const struct hfi_ops
*ops
= inst
->core
->ops
;
337 if (inst
->state
!= INST_INIT
)
340 reinit_completion(&inst
->done
);
342 ret
= ops
->session_load_res(inst
);
346 ret
= wait_session_msg(inst
);
350 inst
->state
= INST_LOAD_RESOURCES
;
355 int hfi_session_unload_res(struct venus_inst
*inst
)
357 const struct hfi_ops
*ops
= inst
->core
->ops
;
360 if (inst
->state
!= INST_STOP
)
363 reinit_completion(&inst
->done
);
365 ret
= ops
->session_release_res(inst
);
369 ret
= wait_session_msg(inst
);
373 inst
->state
= INST_RELEASE_RESOURCES
;
378 int hfi_session_flush(struct venus_inst
*inst
)
380 const struct hfi_ops
*ops
= inst
->core
->ops
;
383 reinit_completion(&inst
->done
);
385 ret
= ops
->session_flush(inst
, HFI_FLUSH_ALL
);
389 ret
= wait_session_msg(inst
);
395 EXPORT_SYMBOL_GPL(hfi_session_flush
);
397 int hfi_session_set_buffers(struct venus_inst
*inst
, struct hfi_buffer_desc
*bd
)
399 const struct hfi_ops
*ops
= inst
->core
->ops
;
401 return ops
->session_set_buffers(inst
, bd
);
404 int hfi_session_unset_buffers(struct venus_inst
*inst
,
405 struct hfi_buffer_desc
*bd
)
407 const struct hfi_ops
*ops
= inst
->core
->ops
;
410 reinit_completion(&inst
->done
);
412 ret
= ops
->session_unset_buffers(inst
, bd
);
416 if (!bd
->response_required
)
419 ret
= wait_session_msg(inst
);
426 int hfi_session_get_property(struct venus_inst
*inst
, u32 ptype
,
427 union hfi_get_property
*hprop
)
429 const struct hfi_ops
*ops
= inst
->core
->ops
;
432 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
435 reinit_completion(&inst
->done
);
437 ret
= ops
->session_get_property(inst
, ptype
);
441 ret
= wait_session_msg(inst
);
445 *hprop
= inst
->hprop
;
449 EXPORT_SYMBOL_GPL(hfi_session_get_property
);
451 int hfi_session_set_property(struct venus_inst
*inst
, u32 ptype
, void *pdata
)
453 const struct hfi_ops
*ops
= inst
->core
->ops
;
455 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
458 return ops
->session_set_property(inst
, ptype
, pdata
);
460 EXPORT_SYMBOL_GPL(hfi_session_set_property
);
462 int hfi_session_process_buf(struct venus_inst
*inst
, struct hfi_frame_data
*fd
)
464 const struct hfi_ops
*ops
= inst
->core
->ops
;
466 if (fd
->buffer_type
== HFI_BUFFER_INPUT
)
467 return ops
->session_etb(inst
, fd
);
468 else if (fd
->buffer_type
== HFI_BUFFER_OUTPUT
||
469 fd
->buffer_type
== HFI_BUFFER_OUTPUT2
)
470 return ops
->session_ftb(inst
, fd
);
474 EXPORT_SYMBOL_GPL(hfi_session_process_buf
);
476 irqreturn_t
hfi_isr_thread(int irq
, void *dev_id
)
478 struct venus_core
*core
= dev_id
;
480 return core
->ops
->isr_thread(core
);
483 irqreturn_t
hfi_isr(int irq
, void *dev
)
485 struct venus_core
*core
= dev
;
487 return core
->ops
->isr(core
);
490 int hfi_create(struct venus_core
*core
, const struct hfi_core_ops
*ops
)
497 atomic_set(&core
->insts_count
, 0);
498 core
->core_ops
= ops
;
499 core
->state
= CORE_UNINIT
;
500 init_completion(&core
->done
);
501 pkt_set_version(core
->res
->hfi_version
);
502 ret
= venus_hfi_create(core
);
507 void hfi_destroy(struct venus_core
*core
)
509 venus_hfi_destroy(core
);