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 int hfi_core_deinit(struct venus_core
*core
, bool blocking
)
95 mutex_lock(&core
->lock
);
97 if (core
->state
== CORE_UNINIT
)
100 empty
= list_empty(&core
->instances
);
102 if (!empty
&& !blocking
) {
108 mutex_unlock(&core
->lock
);
109 wait_on_atomic_t(&core
->insts_count
, atomic_t_wait
,
110 TASK_UNINTERRUPTIBLE
);
111 mutex_lock(&core
->lock
);
114 ret
= core
->ops
->core_deinit(core
);
117 core
->state
= CORE_UNINIT
;
120 mutex_unlock(&core
->lock
);
124 int hfi_core_suspend(struct venus_core
*core
)
126 if (core
->state
!= CORE_INIT
)
129 return core
->ops
->suspend(core
);
132 int hfi_core_resume(struct venus_core
*core
, bool force
)
134 if (!force
&& core
->state
!= CORE_INIT
)
137 return core
->ops
->resume(core
);
140 int hfi_core_trigger_ssr(struct venus_core
*core
, u32 type
)
142 return core
->ops
->core_trigger_ssr(core
, type
);
145 int hfi_core_ping(struct venus_core
*core
)
149 mutex_lock(&core
->lock
);
151 ret
= core
->ops
->core_ping(core
, 0xbeef);
155 ret
= wait_for_completion_timeout(&core
->done
, TIMEOUT
);
161 if (core
->error
!= HFI_ERR_NONE
)
164 mutex_unlock(&core
->lock
);
168 static int wait_session_msg(struct venus_inst
*inst
)
172 ret
= wait_for_completion_timeout(&inst
->done
, TIMEOUT
);
176 if (inst
->error
!= HFI_ERR_NONE
)
182 int hfi_session_create(struct venus_inst
*inst
, const struct hfi_inst_ops
*ops
)
184 struct venus_core
*core
= inst
->core
;
189 inst
->state
= INST_UNINIT
;
190 init_completion(&inst
->done
);
193 mutex_lock(&core
->lock
);
194 list_add_tail(&inst
->list
, &core
->instances
);
195 atomic_inc(&core
->insts_count
);
196 mutex_unlock(&core
->lock
);
200 EXPORT_SYMBOL_GPL(hfi_session_create
);
202 int hfi_session_init(struct venus_inst
*inst
, u32 pixfmt
)
204 struct venus_core
*core
= inst
->core
;
205 const struct hfi_ops
*ops
= core
->ops
;
209 codec
= to_codec_type(pixfmt
);
210 reinit_completion(&inst
->done
);
212 ret
= ops
->session_init(inst
, inst
->session_type
, codec
);
216 ret
= wait_session_msg(inst
);
220 inst
->state
= INST_INIT
;
224 EXPORT_SYMBOL_GPL(hfi_session_init
);
226 void hfi_session_destroy(struct venus_inst
*inst
)
228 struct venus_core
*core
= inst
->core
;
230 mutex_lock(&core
->lock
);
231 list_del_init(&inst
->list
);
232 atomic_dec(&core
->insts_count
);
233 wake_up_atomic_t(&core
->insts_count
);
234 mutex_unlock(&core
->lock
);
236 EXPORT_SYMBOL_GPL(hfi_session_destroy
);
238 int hfi_session_deinit(struct venus_inst
*inst
)
240 const struct hfi_ops
*ops
= inst
->core
->ops
;
243 if (inst
->state
== INST_UNINIT
)
246 if (inst
->state
< INST_INIT
)
249 reinit_completion(&inst
->done
);
251 ret
= ops
->session_end(inst
);
255 ret
= wait_session_msg(inst
);
259 inst
->state
= INST_UNINIT
;
263 EXPORT_SYMBOL_GPL(hfi_session_deinit
);
265 int hfi_session_start(struct venus_inst
*inst
)
267 const struct hfi_ops
*ops
= inst
->core
->ops
;
270 if (inst
->state
!= INST_LOAD_RESOURCES
)
273 reinit_completion(&inst
->done
);
275 ret
= ops
->session_start(inst
);
279 ret
= wait_session_msg(inst
);
283 inst
->state
= INST_START
;
288 int hfi_session_stop(struct venus_inst
*inst
)
290 const struct hfi_ops
*ops
= inst
->core
->ops
;
293 if (inst
->state
!= INST_START
)
296 reinit_completion(&inst
->done
);
298 ret
= ops
->session_stop(inst
);
302 ret
= wait_session_msg(inst
);
306 inst
->state
= INST_STOP
;
311 int hfi_session_continue(struct venus_inst
*inst
)
313 struct venus_core
*core
= inst
->core
;
315 if (core
->res
->hfi_version
!= HFI_VERSION_3XX
)
318 return core
->ops
->session_continue(inst
);
320 EXPORT_SYMBOL_GPL(hfi_session_continue
);
322 int hfi_session_abort(struct venus_inst
*inst
)
324 const struct hfi_ops
*ops
= inst
->core
->ops
;
327 reinit_completion(&inst
->done
);
329 ret
= ops
->session_abort(inst
);
333 ret
= wait_session_msg(inst
);
340 int hfi_session_load_res(struct venus_inst
*inst
)
342 const struct hfi_ops
*ops
= inst
->core
->ops
;
345 if (inst
->state
!= INST_INIT
)
348 reinit_completion(&inst
->done
);
350 ret
= ops
->session_load_res(inst
);
354 ret
= wait_session_msg(inst
);
358 inst
->state
= INST_LOAD_RESOURCES
;
363 int hfi_session_unload_res(struct venus_inst
*inst
)
365 const struct hfi_ops
*ops
= inst
->core
->ops
;
368 if (inst
->state
!= INST_STOP
)
371 reinit_completion(&inst
->done
);
373 ret
= ops
->session_release_res(inst
);
377 ret
= wait_session_msg(inst
);
381 inst
->state
= INST_RELEASE_RESOURCES
;
386 int hfi_session_flush(struct venus_inst
*inst
)
388 const struct hfi_ops
*ops
= inst
->core
->ops
;
391 reinit_completion(&inst
->done
);
393 ret
= ops
->session_flush(inst
, HFI_FLUSH_ALL
);
397 ret
= wait_session_msg(inst
);
403 EXPORT_SYMBOL_GPL(hfi_session_flush
);
405 int hfi_session_set_buffers(struct venus_inst
*inst
, struct hfi_buffer_desc
*bd
)
407 const struct hfi_ops
*ops
= inst
->core
->ops
;
409 return ops
->session_set_buffers(inst
, bd
);
412 int hfi_session_unset_buffers(struct venus_inst
*inst
,
413 struct hfi_buffer_desc
*bd
)
415 const struct hfi_ops
*ops
= inst
->core
->ops
;
418 reinit_completion(&inst
->done
);
420 ret
= ops
->session_unset_buffers(inst
, bd
);
424 if (!bd
->response_required
)
427 ret
= wait_session_msg(inst
);
434 int hfi_session_get_property(struct venus_inst
*inst
, u32 ptype
,
435 union hfi_get_property
*hprop
)
437 const struct hfi_ops
*ops
= inst
->core
->ops
;
440 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
443 reinit_completion(&inst
->done
);
445 ret
= ops
->session_get_property(inst
, ptype
);
449 ret
= wait_session_msg(inst
);
453 *hprop
= inst
->hprop
;
457 EXPORT_SYMBOL_GPL(hfi_session_get_property
);
459 int hfi_session_set_property(struct venus_inst
*inst
, u32 ptype
, void *pdata
)
461 const struct hfi_ops
*ops
= inst
->core
->ops
;
463 if (inst
->state
< INST_INIT
|| inst
->state
>= INST_STOP
)
466 return ops
->session_set_property(inst
, ptype
, pdata
);
468 EXPORT_SYMBOL_GPL(hfi_session_set_property
);
470 int hfi_session_process_buf(struct venus_inst
*inst
, struct hfi_frame_data
*fd
)
472 const struct hfi_ops
*ops
= inst
->core
->ops
;
474 if (fd
->buffer_type
== HFI_BUFFER_INPUT
)
475 return ops
->session_etb(inst
, fd
);
476 else if (fd
->buffer_type
== HFI_BUFFER_OUTPUT
)
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
);