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
;
52 case V4L2_PIX_FMT_HEVC
:
53 return HFI_VIDEO_CODEC_HEVC
;
59 int hfi_core_init(struct venus_core
*core
)
63 mutex_lock(&core
->lock
);
65 if (core
->state
>= CORE_INIT
)
68 reinit_completion(&core
->done
);
70 ret
= core
->ops
->core_init(core
);
74 ret
= wait_for_completion_timeout(&core
->done
, TIMEOUT
);
82 if (core
->error
!= HFI_ERR_NONE
) {
87 core
->state
= CORE_INIT
;
89 mutex_unlock(&core
->lock
);
93 int hfi_core_deinit(struct venus_core
*core
, bool blocking
)
97 mutex_lock(&core
->lock
);
99 if (core
->state
== CORE_UNINIT
)
102 empty
= list_empty(&core
->instances
);
104 if (!empty
&& !blocking
) {
110 mutex_unlock(&core
->lock
);
111 wait_var_event(&core
->insts_count
,
112 !atomic_read(&core
->insts_count
));
113 mutex_lock(&core
->lock
);
116 ret
= core
->ops
->core_deinit(core
);
119 core
->state
= CORE_UNINIT
;
122 mutex_unlock(&core
->lock
);
126 int hfi_core_suspend(struct venus_core
*core
)
128 if (core
->state
!= CORE_INIT
)
131 return core
->ops
->suspend(core
);
134 int hfi_core_resume(struct venus_core
*core
, bool force
)
136 if (!force
&& core
->state
!= CORE_INIT
)
139 return core
->ops
->resume(core
);
142 int hfi_core_trigger_ssr(struct venus_core
*core
, u32 type
)
144 return core
->ops
->core_trigger_ssr(core
, type
);
147 int hfi_core_ping(struct venus_core
*core
)
151 mutex_lock(&core
->lock
);
153 ret
= core
->ops
->core_ping(core
, 0xbeef);
157 ret
= wait_for_completion_timeout(&core
->done
, TIMEOUT
);
163 if (core
->error
!= HFI_ERR_NONE
)
166 mutex_unlock(&core
->lock
);
170 static int wait_session_msg(struct venus_inst
*inst
)
174 ret
= wait_for_completion_timeout(&inst
->done
, TIMEOUT
);
178 if (inst
->error
!= HFI_ERR_NONE
)
184 int hfi_session_create(struct venus_inst
*inst
, const struct hfi_inst_ops
*ops
)
186 struct venus_core
*core
= inst
->core
;
191 inst
->state
= INST_UNINIT
;
192 init_completion(&inst
->done
);
195 mutex_lock(&core
->lock
);
196 list_add_tail(&inst
->list
, &core
->instances
);
197 atomic_inc(&core
->insts_count
);
198 mutex_unlock(&core
->lock
);
202 EXPORT_SYMBOL_GPL(hfi_session_create
);
204 int hfi_session_init(struct venus_inst
*inst
, u32 pixfmt
)
206 struct venus_core
*core
= inst
->core
;
207 const struct hfi_ops
*ops
= core
->ops
;
210 inst
->hfi_codec
= to_codec_type(pixfmt
);
211 reinit_completion(&inst
->done
);
213 ret
= ops
->session_init(inst
, inst
->session_type
, inst
->hfi_codec
);
217 ret
= wait_session_msg(inst
);
221 inst
->state
= INST_INIT
;
225 EXPORT_SYMBOL_GPL(hfi_session_init
);
227 void hfi_session_destroy(struct venus_inst
*inst
)
229 struct venus_core
*core
= inst
->core
;
231 mutex_lock(&core
->lock
);
232 list_del_init(&inst
->list
);
233 if (atomic_dec_and_test(&core
->insts_count
))
234 wake_up_var(&core
->insts_count
);
235 mutex_unlock(&core
->lock
);
237 EXPORT_SYMBOL_GPL(hfi_session_destroy
);
239 int hfi_session_deinit(struct venus_inst
*inst
)
241 const struct hfi_ops
*ops
= inst
->core
->ops
;
244 if (inst
->state
== INST_UNINIT
)
247 if (inst
->state
< INST_INIT
)
250 reinit_completion(&inst
->done
);
252 ret
= ops
->session_end(inst
);
256 ret
= wait_session_msg(inst
);
260 inst
->state
= INST_UNINIT
;
264 EXPORT_SYMBOL_GPL(hfi_session_deinit
);
266 int hfi_session_start(struct venus_inst
*inst
)
268 const struct hfi_ops
*ops
= inst
->core
->ops
;
271 if (inst
->state
!= INST_LOAD_RESOURCES
)
274 reinit_completion(&inst
->done
);
276 ret
= ops
->session_start(inst
);
280 ret
= wait_session_msg(inst
);
284 inst
->state
= INST_START
;
289 int hfi_session_stop(struct venus_inst
*inst
)
291 const struct hfi_ops
*ops
= inst
->core
->ops
;
294 if (inst
->state
!= INST_START
)
297 reinit_completion(&inst
->done
);
299 ret
= ops
->session_stop(inst
);
303 ret
= wait_session_msg(inst
);
307 inst
->state
= INST_STOP
;
312 int hfi_session_continue(struct venus_inst
*inst
)
314 struct venus_core
*core
= inst
->core
;
316 if (core
->res
->hfi_version
== HFI_VERSION_1XX
)
319 return core
->ops
->session_continue(inst
);
321 EXPORT_SYMBOL_GPL(hfi_session_continue
);
323 int hfi_session_abort(struct venus_inst
*inst
)
325 const struct hfi_ops
*ops
= inst
->core
->ops
;
328 reinit_completion(&inst
->done
);
330 ret
= ops
->session_abort(inst
);
334 ret
= wait_session_msg(inst
);
341 int hfi_session_load_res(struct venus_inst
*inst
)
343 const struct hfi_ops
*ops
= inst
->core
->ops
;
346 if (inst
->state
!= INST_INIT
)
349 reinit_completion(&inst
->done
);
351 ret
= ops
->session_load_res(inst
);
355 ret
= wait_session_msg(inst
);
359 inst
->state
= INST_LOAD_RESOURCES
;
364 int hfi_session_unload_res(struct venus_inst
*inst
)
366 const struct hfi_ops
*ops
= inst
->core
->ops
;
369 if (inst
->state
!= INST_STOP
)
372 reinit_completion(&inst
->done
);
374 ret
= ops
->session_release_res(inst
);
378 ret
= wait_session_msg(inst
);
382 inst
->state
= INST_RELEASE_RESOURCES
;
387 int hfi_session_flush(struct venus_inst
*inst
)
389 const struct hfi_ops
*ops
= inst
->core
->ops
;
392 reinit_completion(&inst
->done
);
394 ret
= ops
->session_flush(inst
, HFI_FLUSH_ALL
);
398 ret
= wait_session_msg(inst
);
404 EXPORT_SYMBOL_GPL(hfi_session_flush
);
406 int hfi_session_set_buffers(struct venus_inst
*inst
, struct hfi_buffer_desc
*bd
)
408 const struct hfi_ops
*ops
= inst
->core
->ops
;
410 return ops
->session_set_buffers(inst
, bd
);
413 int hfi_session_unset_buffers(struct venus_inst
*inst
,
414 struct hfi_buffer_desc
*bd
)
416 const struct hfi_ops
*ops
= inst
->core
->ops
;
419 reinit_completion(&inst
->done
);
421 ret
= ops
->session_unset_buffers(inst
, bd
);
425 if (!bd
->response_required
)
428 ret
= wait_session_msg(inst
);
435 int hfi_session_get_property(struct venus_inst
*inst
, u32 ptype
,
436 union hfi_get_property
*hprop
)
438 const struct hfi_ops
*ops
= inst
->core
->ops
;
441 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
444 reinit_completion(&inst
->done
);
446 ret
= ops
->session_get_property(inst
, ptype
);
450 ret
= wait_session_msg(inst
);
454 *hprop
= inst
->hprop
;
458 EXPORT_SYMBOL_GPL(hfi_session_get_property
);
460 int hfi_session_set_property(struct venus_inst
*inst
, u32 ptype
, void *pdata
)
462 const struct hfi_ops
*ops
= inst
->core
->ops
;
464 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
467 return ops
->session_set_property(inst
, ptype
, pdata
);
469 EXPORT_SYMBOL_GPL(hfi_session_set_property
);
471 int hfi_session_process_buf(struct venus_inst
*inst
, struct hfi_frame_data
*fd
)
473 const struct hfi_ops
*ops
= inst
->core
->ops
;
475 if (fd
->buffer_type
== HFI_BUFFER_INPUT
)
476 return ops
->session_etb(inst
, fd
);
477 else if (fd
->buffer_type
== HFI_BUFFER_OUTPUT
||
478 fd
->buffer_type
== HFI_BUFFER_OUTPUT2
)
479 return ops
->session_ftb(inst
, fd
);
483 EXPORT_SYMBOL_GPL(hfi_session_process_buf
);
485 irqreturn_t
hfi_isr_thread(int irq
, void *dev_id
)
487 struct venus_core
*core
= dev_id
;
489 return core
->ops
->isr_thread(core
);
492 irqreturn_t
hfi_isr(int irq
, void *dev
)
494 struct venus_core
*core
= dev
;
496 return core
->ops
->isr(core
);
499 int hfi_create(struct venus_core
*core
, const struct hfi_core_ops
*ops
)
506 atomic_set(&core
->insts_count
, 0);
507 core
->core_ops
= ops
;
508 core
->state
= CORE_UNINIT
;
509 init_completion(&core
->done
);
510 pkt_set_version(core
->res
->hfi_version
);
511 ret
= venus_hfi_create(core
);
516 void hfi_destroy(struct venus_core
*core
)
518 venus_hfi_destroy(core
);