2 * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
3 * Copyright (C) 2017 Linaro Ltd.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
15 #include <linux/slab.h>
16 #include <linux/mutex.h>
17 #include <linux/list.h>
18 #include <linux/completion.h>
19 #include <linux/platform_device.h>
20 #include <linux/videodev2.h>
25 #include "hfi_venus.h"
27 #define TIMEOUT msecs_to_jiffies(1000)
29 static u32
to_codec_type(u32 pixfmt
)
32 case V4L2_PIX_FMT_H264
:
33 case V4L2_PIX_FMT_H264_NO_SC
:
34 return HFI_VIDEO_CODEC_H264
;
35 case V4L2_PIX_FMT_H263
:
36 return HFI_VIDEO_CODEC_H263
;
37 case V4L2_PIX_FMT_MPEG1
:
38 return HFI_VIDEO_CODEC_MPEG1
;
39 case V4L2_PIX_FMT_MPEG2
:
40 return HFI_VIDEO_CODEC_MPEG2
;
41 case V4L2_PIX_FMT_MPEG4
:
42 return HFI_VIDEO_CODEC_MPEG4
;
43 case V4L2_PIX_FMT_VC1_ANNEX_G
:
44 case V4L2_PIX_FMT_VC1_ANNEX_L
:
45 return HFI_VIDEO_CODEC_VC1
;
46 case V4L2_PIX_FMT_VP8
:
47 return HFI_VIDEO_CODEC_VP8
;
48 case V4L2_PIX_FMT_VP9
:
49 return HFI_VIDEO_CODEC_VP9
;
50 case V4L2_PIX_FMT_XVID
:
51 return HFI_VIDEO_CODEC_DIVX
;
57 int hfi_core_init(struct venus_core
*core
)
61 mutex_lock(&core
->lock
);
63 if (core
->state
>= CORE_INIT
)
66 reinit_completion(&core
->done
);
68 ret
= core
->ops
->core_init(core
);
72 ret
= wait_for_completion_timeout(&core
->done
, TIMEOUT
);
80 if (core
->error
!= HFI_ERR_NONE
) {
85 core
->state
= CORE_INIT
;
87 mutex_unlock(&core
->lock
);
91 static int core_deinit_wait_atomic_t(atomic_t
*p
)
97 int hfi_core_deinit(struct venus_core
*core
, bool blocking
)
101 mutex_lock(&core
->lock
);
103 if (core
->state
== CORE_UNINIT
)
106 empty
= list_empty(&core
->instances
);
108 if (!empty
&& !blocking
) {
114 mutex_unlock(&core
->lock
);
115 wait_on_atomic_t(&core
->insts_count
, core_deinit_wait_atomic_t
,
116 TASK_UNINTERRUPTIBLE
);
117 mutex_lock(&core
->lock
);
120 ret
= core
->ops
->core_deinit(core
);
123 core
->state
= CORE_UNINIT
;
126 mutex_unlock(&core
->lock
);
130 int hfi_core_suspend(struct venus_core
*core
)
132 if (core
->state
!= CORE_INIT
)
135 return core
->ops
->suspend(core
);
138 int hfi_core_resume(struct venus_core
*core
, bool force
)
140 if (!force
&& core
->state
!= CORE_INIT
)
143 return core
->ops
->resume(core
);
146 int hfi_core_trigger_ssr(struct venus_core
*core
, u32 type
)
148 return core
->ops
->core_trigger_ssr(core
, type
);
151 int hfi_core_ping(struct venus_core
*core
)
155 mutex_lock(&core
->lock
);
157 ret
= core
->ops
->core_ping(core
, 0xbeef);
161 ret
= wait_for_completion_timeout(&core
->done
, TIMEOUT
);
167 if (core
->error
!= HFI_ERR_NONE
)
170 mutex_unlock(&core
->lock
);
174 static int wait_session_msg(struct venus_inst
*inst
)
178 ret
= wait_for_completion_timeout(&inst
->done
, TIMEOUT
);
182 if (inst
->error
!= HFI_ERR_NONE
)
188 int hfi_session_create(struct venus_inst
*inst
, const struct hfi_inst_ops
*ops
)
190 struct venus_core
*core
= inst
->core
;
195 inst
->state
= INST_UNINIT
;
196 init_completion(&inst
->done
);
199 mutex_lock(&core
->lock
);
200 list_add_tail(&inst
->list
, &core
->instances
);
201 atomic_inc(&core
->insts_count
);
202 mutex_unlock(&core
->lock
);
206 EXPORT_SYMBOL_GPL(hfi_session_create
);
208 int hfi_session_init(struct venus_inst
*inst
, u32 pixfmt
)
210 struct venus_core
*core
= inst
->core
;
211 const struct hfi_ops
*ops
= core
->ops
;
215 codec
= to_codec_type(pixfmt
);
216 reinit_completion(&inst
->done
);
218 ret
= ops
->session_init(inst
, inst
->session_type
, codec
);
222 ret
= wait_session_msg(inst
);
226 inst
->state
= INST_INIT
;
230 EXPORT_SYMBOL_GPL(hfi_session_init
);
232 void hfi_session_destroy(struct venus_inst
*inst
)
234 struct venus_core
*core
= inst
->core
;
236 mutex_lock(&core
->lock
);
237 list_del_init(&inst
->list
);
238 atomic_dec(&core
->insts_count
);
239 wake_up_atomic_t(&core
->insts_count
);
240 mutex_unlock(&core
->lock
);
242 EXPORT_SYMBOL_GPL(hfi_session_destroy
);
244 int hfi_session_deinit(struct venus_inst
*inst
)
246 const struct hfi_ops
*ops
= inst
->core
->ops
;
249 if (inst
->state
== INST_UNINIT
)
252 if (inst
->state
< INST_INIT
)
255 reinit_completion(&inst
->done
);
257 ret
= ops
->session_end(inst
);
261 ret
= wait_session_msg(inst
);
265 inst
->state
= INST_UNINIT
;
269 EXPORT_SYMBOL_GPL(hfi_session_deinit
);
271 int hfi_session_start(struct venus_inst
*inst
)
273 const struct hfi_ops
*ops
= inst
->core
->ops
;
276 if (inst
->state
!= INST_LOAD_RESOURCES
)
279 reinit_completion(&inst
->done
);
281 ret
= ops
->session_start(inst
);
285 ret
= wait_session_msg(inst
);
289 inst
->state
= INST_START
;
294 int hfi_session_stop(struct venus_inst
*inst
)
296 const struct hfi_ops
*ops
= inst
->core
->ops
;
299 if (inst
->state
!= INST_START
)
302 reinit_completion(&inst
->done
);
304 ret
= ops
->session_stop(inst
);
308 ret
= wait_session_msg(inst
);
312 inst
->state
= INST_STOP
;
317 int hfi_session_continue(struct venus_inst
*inst
)
319 struct venus_core
*core
= inst
->core
;
321 if (core
->res
->hfi_version
!= HFI_VERSION_3XX
)
324 return core
->ops
->session_continue(inst
);
326 EXPORT_SYMBOL_GPL(hfi_session_continue
);
328 int hfi_session_abort(struct venus_inst
*inst
)
330 const struct hfi_ops
*ops
= inst
->core
->ops
;
333 reinit_completion(&inst
->done
);
335 ret
= ops
->session_abort(inst
);
339 ret
= wait_session_msg(inst
);
346 int hfi_session_load_res(struct venus_inst
*inst
)
348 const struct hfi_ops
*ops
= inst
->core
->ops
;
351 if (inst
->state
!= INST_INIT
)
354 reinit_completion(&inst
->done
);
356 ret
= ops
->session_load_res(inst
);
360 ret
= wait_session_msg(inst
);
364 inst
->state
= INST_LOAD_RESOURCES
;
369 int hfi_session_unload_res(struct venus_inst
*inst
)
371 const struct hfi_ops
*ops
= inst
->core
->ops
;
374 if (inst
->state
!= INST_STOP
)
377 reinit_completion(&inst
->done
);
379 ret
= ops
->session_release_res(inst
);
383 ret
= wait_session_msg(inst
);
387 inst
->state
= INST_RELEASE_RESOURCES
;
392 int hfi_session_flush(struct venus_inst
*inst
)
394 const struct hfi_ops
*ops
= inst
->core
->ops
;
397 reinit_completion(&inst
->done
);
399 ret
= ops
->session_flush(inst
, HFI_FLUSH_ALL
);
403 ret
= wait_session_msg(inst
);
409 EXPORT_SYMBOL_GPL(hfi_session_flush
);
411 int hfi_session_set_buffers(struct venus_inst
*inst
, struct hfi_buffer_desc
*bd
)
413 const struct hfi_ops
*ops
= inst
->core
->ops
;
415 return ops
->session_set_buffers(inst
, bd
);
418 int hfi_session_unset_buffers(struct venus_inst
*inst
,
419 struct hfi_buffer_desc
*bd
)
421 const struct hfi_ops
*ops
= inst
->core
->ops
;
424 reinit_completion(&inst
->done
);
426 ret
= ops
->session_unset_buffers(inst
, bd
);
430 if (!bd
->response_required
)
433 ret
= wait_session_msg(inst
);
440 int hfi_session_get_property(struct venus_inst
*inst
, u32 ptype
,
441 union hfi_get_property
*hprop
)
443 const struct hfi_ops
*ops
= inst
->core
->ops
;
446 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
449 reinit_completion(&inst
->done
);
451 ret
= ops
->session_get_property(inst
, ptype
);
455 ret
= wait_session_msg(inst
);
459 *hprop
= inst
->hprop
;
463 EXPORT_SYMBOL_GPL(hfi_session_get_property
);
465 int hfi_session_set_property(struct venus_inst
*inst
, u32 ptype
, void *pdata
)
467 const struct hfi_ops
*ops
= inst
->core
->ops
;
469 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
472 return ops
->session_set_property(inst
, ptype
, pdata
);
474 EXPORT_SYMBOL_GPL(hfi_session_set_property
);
476 int hfi_session_process_buf(struct venus_inst
*inst
, struct hfi_frame_data
*fd
)
478 const struct hfi_ops
*ops
= inst
->core
->ops
;
480 if (fd
->buffer_type
== HFI_BUFFER_INPUT
)
481 return ops
->session_etb(inst
, fd
);
482 else if (fd
->buffer_type
== HFI_BUFFER_OUTPUT
)
483 return ops
->session_ftb(inst
, fd
);
487 EXPORT_SYMBOL_GPL(hfi_session_process_buf
);
489 irqreturn_t
hfi_isr_thread(int irq
, void *dev_id
)
491 struct venus_core
*core
= dev_id
;
493 return core
->ops
->isr_thread(core
);
496 irqreturn_t
hfi_isr(int irq
, void *dev
)
498 struct venus_core
*core
= dev
;
500 return core
->ops
->isr(core
);
503 int hfi_create(struct venus_core
*core
, const struct hfi_core_ops
*ops
)
510 atomic_set(&core
->insts_count
, 0);
511 core
->core_ops
= ops
;
512 core
->state
= CORE_UNINIT
;
513 init_completion(&core
->done
);
514 pkt_set_version(core
->res
->hfi_version
);
515 ret
= venus_hfi_create(core
);
520 void hfi_destroy(struct venus_core
*core
)
522 venus_hfi_destroy(core
);