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/hash.h>
16 #include <linux/list.h>
17 #include <linux/slab.h>
18 #include <media/videobuf2-v4l2.h>
22 #include "hfi_helper.h"
25 static void event_seq_changed(struct venus_core
*core
, struct venus_inst
*inst
,
26 struct hfi_msg_event_notify_pkt
*pkt
)
28 struct hfi_event_data event
= {0};
29 int num_properties_changed
;
30 struct hfi_framesize
*frame_sz
;
31 struct hfi_profile_level
*profile_level
;
35 inst
->error
= HFI_ERR_NONE
;
37 switch (pkt
->event_data1
) {
38 case HFI_EVENT_DATA_SEQUENCE_CHANGED_SUFFICIENT_BUF_RESOURCES
:
39 case HFI_EVENT_DATA_SEQUENCE_CHANGED_INSUFFICIENT_BUF_RESOURCES
:
42 inst
->error
= HFI_ERR_SESSION_INVALID_PARAMETER
;
46 event
.event_type
= pkt
->event_data1
;
48 num_properties_changed
= pkt
->event_data2
;
49 if (!num_properties_changed
) {
50 inst
->error
= HFI_ERR_SESSION_INSUFFICIENT_RESOURCES
;
54 data_ptr
= (u8
*)&pkt
->ext_event_data
[0];
56 ptype
= *((u32
*)data_ptr
);
58 case HFI_PROPERTY_PARAM_FRAME_SIZE
:
59 data_ptr
+= sizeof(u32
);
60 frame_sz
= (struct hfi_framesize
*)data_ptr
;
61 event
.width
= frame_sz
->width
;
62 event
.height
= frame_sz
->height
;
63 data_ptr
+= sizeof(frame_sz
);
65 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT
:
66 data_ptr
+= sizeof(u32
);
67 profile_level
= (struct hfi_profile_level
*)data_ptr
;
68 event
.profile
= profile_level
->profile
;
69 event
.level
= profile_level
->level
;
70 data_ptr
+= sizeof(profile_level
);
75 num_properties_changed
--;
76 } while (num_properties_changed
> 0);
79 inst
->ops
->event_notify(inst
, EVT_SYS_EVENT_CHANGE
, &event
);
82 static void event_release_buffer_ref(struct venus_core
*core
,
83 struct venus_inst
*inst
,
84 struct hfi_msg_event_notify_pkt
*pkt
)
86 struct hfi_event_data event
= {0};
87 struct hfi_msg_event_release_buffer_ref_pkt
*data
;
89 data
= (struct hfi_msg_event_release_buffer_ref_pkt
*)
92 event
.event_type
= HFI_EVENT_RELEASE_BUFFER_REFERENCE
;
93 event
.packet_buffer
= data
->packet_buffer
;
94 event
.extradata_buffer
= data
->extradata_buffer
;
95 event
.tag
= data
->output_tag
;
97 inst
->error
= HFI_ERR_NONE
;
98 inst
->ops
->event_notify(inst
, EVT_SYS_EVENT_CHANGE
, &event
);
101 static void event_sys_error(struct venus_core
*core
, u32 event
,
102 struct hfi_msg_event_notify_pkt
*pkt
)
106 "sys error (session id:%x, data1:%x, data2:%x)\n",
107 pkt
->shdr
.session_id
, pkt
->event_data1
,
110 core
->core_ops
->event_notify(core
, event
);
114 event_session_error(struct venus_core
*core
, struct venus_inst
*inst
,
115 struct hfi_msg_event_notify_pkt
*pkt
)
117 struct device
*dev
= core
->dev
;
119 dev_dbg(dev
, "session error: event id:%x, session id:%x\n",
120 pkt
->event_data1
, pkt
->shdr
.session_id
);
125 switch (pkt
->event_data1
) {
126 /* non fatal session errors */
127 case HFI_ERR_SESSION_INVALID_SCALE_FACTOR
:
128 case HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE
:
129 case HFI_ERR_SESSION_UNSUPPORTED_SETTING
:
130 case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED
:
131 inst
->error
= HFI_ERR_NONE
;
134 dev_err(dev
, "session error: event id:%x (%x), session id:%x\n",
135 pkt
->event_data1
, pkt
->event_data2
,
136 pkt
->shdr
.session_id
);
138 inst
->error
= pkt
->event_data1
;
139 inst
->ops
->event_notify(inst
, EVT_SESSION_ERROR
, NULL
);
144 static void hfi_event_notify(struct venus_core
*core
, struct venus_inst
*inst
,
147 struct hfi_msg_event_notify_pkt
*pkt
= packet
;
152 switch (pkt
->event_id
) {
153 case HFI_EVENT_SYS_ERROR
:
154 event_sys_error(core
, EVT_SYS_ERROR
, pkt
);
156 case HFI_EVENT_SESSION_ERROR
:
157 event_session_error(core
, inst
, pkt
);
159 case HFI_EVENT_SESSION_SEQUENCE_CHANGED
:
160 event_seq_changed(core
, inst
, pkt
);
162 case HFI_EVENT_RELEASE_BUFFER_REFERENCE
:
163 event_release_buffer_ref(core
, inst
, pkt
);
165 case HFI_EVENT_SESSION_PROPERTY_CHANGED
:
172 static void hfi_sys_init_done(struct venus_core
*core
, struct venus_inst
*inst
,
175 struct hfi_msg_sys_init_done_pkt
*pkt
= packet
;
176 u32 rem_bytes
, read_bytes
= 0, num_properties
;
180 error
= pkt
->error_type
;
181 if (error
!= HFI_ERR_NONE
)
184 num_properties
= pkt
->num_properties
;
186 if (!num_properties
) {
187 error
= HFI_ERR_SYS_INVALID_PARAMETER
;
191 rem_bytes
= pkt
->hdr
.size
- sizeof(*pkt
) + sizeof(u32
);
194 /* missing property data */
195 error
= HFI_ERR_SYS_INSUFFICIENT_RESOURCES
;
199 data
= (u8
*)&pkt
->data
[0];
201 if (core
->res
->hfi_version
== HFI_VERSION_3XX
)
204 while (num_properties
&& rem_bytes
>= sizeof(u32
)) {
205 ptype
= *((u32
*)data
);
209 case HFI_PROPERTY_PARAM_CODEC_SUPPORTED
: {
210 struct hfi_codec_supported
*prop
;
212 prop
= (struct hfi_codec_supported
*)data
;
214 if (rem_bytes
< sizeof(*prop
)) {
215 error
= HFI_ERR_SYS_INSUFFICIENT_RESOURCES
;
219 read_bytes
+= sizeof(*prop
) + sizeof(u32
);
220 core
->dec_codecs
= prop
->dec_codecs
;
221 core
->enc_codecs
= prop
->enc_codecs
;
224 case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED
: {
225 struct hfi_max_sessions_supported
*prop
;
227 if (rem_bytes
< sizeof(*prop
)) {
228 error
= HFI_ERR_SYS_INSUFFICIENT_RESOURCES
;
232 prop
= (struct hfi_max_sessions_supported
*)data
;
233 read_bytes
+= sizeof(*prop
) + sizeof(u32
);
234 core
->max_sessions_supported
= prop
->max_sessions
;
238 error
= HFI_ERR_SYS_INVALID_PARAMETER
;
245 rem_bytes
-= read_bytes
;
252 complete(&core
->done
);
256 sys_get_prop_image_version(struct device
*dev
,
257 struct hfi_msg_sys_property_info_pkt
*pkt
)
261 req_bytes
= pkt
->hdr
.size
- sizeof(*pkt
);
263 if (req_bytes
< 128 || !pkt
->data
[1] || pkt
->num_properties
> 1)
267 dev_dbg(dev
, "F/W version: %s\n", (u8
*)&pkt
->data
[1]);
270 static void hfi_sys_property_info(struct venus_core
*core
,
271 struct venus_inst
*inst
, void *packet
)
273 struct hfi_msg_sys_property_info_pkt
*pkt
= packet
;
274 struct device
*dev
= core
->dev
;
276 if (!pkt
->num_properties
) {
277 dev_dbg(dev
, "%s: no properties\n", __func__
);
281 switch (pkt
->data
[0]) {
282 case HFI_PROPERTY_SYS_IMAGE_VERSION
:
283 sys_get_prop_image_version(dev
, pkt
);
286 dev_dbg(dev
, "%s: unknown property data\n", __func__
);
291 static void hfi_sys_rel_resource_done(struct venus_core
*core
,
292 struct venus_inst
*inst
,
295 struct hfi_msg_sys_release_resource_done_pkt
*pkt
= packet
;
297 core
->error
= pkt
->error_type
;
298 complete(&core
->done
);
301 static void hfi_sys_ping_done(struct venus_core
*core
, struct venus_inst
*inst
,
304 struct hfi_msg_sys_ping_ack_pkt
*pkt
= packet
;
306 core
->error
= HFI_ERR_NONE
;
308 if (pkt
->client_data
!= 0xbeef)
309 core
->error
= HFI_ERR_SYS_FATAL
;
311 complete(&core
->done
);
314 static void hfi_sys_idle_done(struct venus_core
*core
, struct venus_inst
*inst
,
317 dev_dbg(core
->dev
, "sys idle\n");
320 static void hfi_sys_pc_prepare_done(struct venus_core
*core
,
321 struct venus_inst
*inst
, void *packet
)
323 struct hfi_msg_sys_pc_prep_done_pkt
*pkt
= packet
;
325 dev_dbg(core
->dev
, "pc prepare done (error %x)\n", pkt
->error_type
);
329 hfi_copy_cap_prop(struct hfi_capability
*in
, struct venus_inst
*inst
)
334 switch (in
->capability_type
) {
335 case HFI_CAPABILITY_FRAME_WIDTH
:
336 inst
->cap_width
= *in
;
338 case HFI_CAPABILITY_FRAME_HEIGHT
:
339 inst
->cap_height
= *in
;
341 case HFI_CAPABILITY_MBS_PER_FRAME
:
342 inst
->cap_mbs_per_frame
= *in
;
344 case HFI_CAPABILITY_MBS_PER_SECOND
:
345 inst
->cap_mbs_per_sec
= *in
;
347 case HFI_CAPABILITY_FRAMERATE
:
348 inst
->cap_framerate
= *in
;
350 case HFI_CAPABILITY_SCALE_X
:
351 inst
->cap_scale_x
= *in
;
353 case HFI_CAPABILITY_SCALE_Y
:
354 inst
->cap_scale_y
= *in
;
356 case HFI_CAPABILITY_BITRATE
:
357 inst
->cap_bitrate
= *in
;
359 case HFI_CAPABILITY_HIER_P_NUM_ENH_LAYERS
:
360 inst
->cap_hier_p
= *in
;
362 case HFI_CAPABILITY_ENC_LTR_COUNT
:
363 inst
->cap_ltr_count
= *in
;
365 case HFI_CAPABILITY_CP_OUTPUT2_THRESH
:
366 inst
->cap_secure_output2_threshold
= *in
;
374 session_get_prop_profile_level(struct hfi_msg_session_property_info_pkt
*pkt
,
375 struct hfi_profile_level
*profile_level
)
377 struct hfi_profile_level
*hfi
;
380 req_bytes
= pkt
->shdr
.hdr
.size
- sizeof(*pkt
);
382 if (!req_bytes
|| req_bytes
% sizeof(struct hfi_profile_level
))
384 return HFI_ERR_SESSION_INVALID_PARAMETER
;
386 hfi
= (struct hfi_profile_level
*)&pkt
->data
[1];
387 profile_level
->profile
= hfi
->profile
;
388 profile_level
->level
= hfi
->level
;
394 session_get_prop_buf_req(struct hfi_msg_session_property_info_pkt
*pkt
,
395 struct hfi_buffer_requirements
*bufreq
)
397 struct hfi_buffer_requirements
*buf_req
;
399 unsigned int idx
= 0;
401 req_bytes
= pkt
->shdr
.hdr
.size
- sizeof(*pkt
);
403 if (!req_bytes
|| req_bytes
% sizeof(*buf_req
) || !pkt
->data
[1])
405 return HFI_ERR_SESSION_INVALID_PARAMETER
;
407 buf_req
= (struct hfi_buffer_requirements
*)&pkt
->data
[1];
409 return HFI_ERR_SESSION_INVALID_PARAMETER
;
412 memcpy(&bufreq
[idx
], buf_req
, sizeof(*bufreq
));
415 if (idx
> HFI_BUFFER_TYPE_MAX
)
416 return HFI_ERR_SESSION_INVALID_PARAMETER
;
418 req_bytes
-= sizeof(struct hfi_buffer_requirements
);
425 static void hfi_session_prop_info(struct venus_core
*core
,
426 struct venus_inst
*inst
, void *packet
)
428 struct hfi_msg_session_property_info_pkt
*pkt
= packet
;
429 struct device
*dev
= core
->dev
;
430 union hfi_get_property
*hprop
= &inst
->hprop
;
431 unsigned int error
= HFI_ERR_NONE
;
433 if (!pkt
->num_properties
) {
434 error
= HFI_ERR_SESSION_INVALID_PARAMETER
;
435 dev_err(dev
, "%s: no properties\n", __func__
);
439 switch (pkt
->data
[0]) {
440 case HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS
:
441 memset(hprop
->bufreq
, 0, sizeof(hprop
->bufreq
));
442 error
= session_get_prop_buf_req(pkt
, hprop
->bufreq
);
444 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT
:
445 memset(&hprop
->profile_level
, 0, sizeof(hprop
->profile_level
));
446 error
= session_get_prop_profile_level(pkt
,
447 &hprop
->profile_level
);
449 case HFI_PROPERTY_CONFIG_VDEC_ENTROPY
:
452 dev_dbg(dev
, "%s: unknown property id:%x\n", __func__
,
459 complete(&inst
->done
);
462 static u32
init_done_read_prop(struct venus_core
*core
, struct venus_inst
*inst
,
463 struct hfi_msg_session_init_done_pkt
*pkt
)
465 struct device
*dev
= core
->dev
;
466 u32 rem_bytes
, num_props
;
467 u32 ptype
, next_offset
= 0;
471 rem_bytes
= pkt
->shdr
.hdr
.size
- sizeof(*pkt
) + sizeof(u32
);
473 dev_err(dev
, "%s: missing property info\n", __func__
);
474 return HFI_ERR_SESSION_INSUFFICIENT_RESOURCES
;
477 err
= pkt
->error_type
;
481 data
= (u8
*)&pkt
->data
[0];
482 num_props
= pkt
->num_properties
;
484 while (err
== HFI_ERR_NONE
&& num_props
&& rem_bytes
>= sizeof(u32
)) {
485 ptype
= *((u32
*)data
);
486 next_offset
= sizeof(u32
);
489 case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED
: {
490 struct hfi_codec_mask_supported
*masks
=
491 (struct hfi_codec_mask_supported
*)
492 (data
+ next_offset
);
494 next_offset
+= sizeof(*masks
);
498 case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED
: {
499 struct hfi_capabilities
*caps
;
500 struct hfi_capability
*cap
;
503 if ((rem_bytes
- next_offset
) < sizeof(*cap
)) {
504 err
= HFI_ERR_SESSION_INVALID_PARAMETER
;
508 caps
= (struct hfi_capabilities
*)(data
+ next_offset
);
510 num_caps
= caps
->num_capabilities
;
511 cap
= &caps
->data
[0];
512 next_offset
+= sizeof(u32
);
515 (rem_bytes
- next_offset
) >= sizeof(u32
)) {
516 hfi_copy_cap_prop(cap
, inst
);
518 next_offset
+= sizeof(*cap
);
524 case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED
: {
525 struct hfi_uncompressed_format_supported
*prop
=
526 (struct hfi_uncompressed_format_supported
*)
527 (data
+ next_offset
);
530 struct hfi_uncompressed_plane_info
*inf
;
532 if ((rem_bytes
- next_offset
) < sizeof(*prop
)) {
533 err
= HFI_ERR_SESSION_INVALID_PARAMETER
;
537 num_fmt_entries
= prop
->format_entries
;
538 next_offset
= sizeof(*prop
) - sizeof(u32
);
539 fmt
= (u8
*)&prop
->format_info
[0];
541 dev_dbg(dev
, "uncomm format support num entries:%u\n",
544 while (num_fmt_entries
) {
545 struct hfi_uncompressed_plane_constraints
*cnts
;
548 inf
= (struct hfi_uncompressed_plane_info
*)fmt
;
550 if ((rem_bytes
- next_offset
) < sizeof(*inf
)) {
551 err
= HFI_ERR_SESSION_INVALID_PARAMETER
;
555 dev_dbg(dev
, "plane info: fmt:%x, planes:%x\n",
556 inf
->format
, inf
->num_planes
);
558 cnts
= &inf
->plane_format
[0];
559 dev_dbg(dev
, "%u %u %u %u\n",
560 cnts
->stride_multiples
,
562 cnts
->min_plane_buffer_height_multiple
,
563 cnts
->buffer_alignment
);
565 bytes_to_skip
= sizeof(*inf
) - sizeof(*cnts
) +
566 inf
->num_planes
* sizeof(*cnts
);
568 fmt
+= bytes_to_skip
;
569 next_offset
+= bytes_to_skip
;
575 case HFI_PROPERTY_PARAM_PROPERTIES_SUPPORTED
: {
576 struct hfi_properties_supported
*prop
=
577 (struct hfi_properties_supported
*)
578 (data
+ next_offset
);
580 next_offset
+= sizeof(*prop
) - sizeof(u32
)
581 + prop
->num_properties
* sizeof(u32
);
585 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED
: {
586 struct hfi_profile_level_supported
*prop
=
587 (struct hfi_profile_level_supported
*)
588 (data
+ next_offset
);
589 struct hfi_profile_level
*pl
;
590 unsigned int prop_count
= 0;
591 unsigned int count
= 0;
594 ptr
= (u8
*)&prop
->profile_level
[0];
595 prop_count
= prop
->profile_count
;
597 if (prop_count
> HFI_MAX_PROFILE_COUNT
)
598 prop_count
= HFI_MAX_PROFILE_COUNT
;
602 pl
= (struct hfi_profile_level
*)ptr
;
604 inst
->pl
[count
].profile
= pl
->profile
;
605 inst
->pl
[count
].level
= pl
->level
;
608 ptr
+= sizeof(*pl
) / sizeof(u32
);
611 inst
->pl_count
= count
;
612 next_offset
+= sizeof(*prop
) - sizeof(*pl
) +
613 prop
->profile_count
* sizeof(*pl
);
618 case HFI_PROPERTY_PARAM_INTERLACE_FORMAT_SUPPORTED
: {
620 sizeof(struct hfi_interlace_format_supported
);
624 case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED
: {
625 struct hfi_nal_stream_format
*nal
=
626 (struct hfi_nal_stream_format
*)
627 (data
+ next_offset
);
628 dev_dbg(dev
, "NAL format: %x\n", nal
->format
);
629 next_offset
+= sizeof(*nal
);
633 case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT
: {
634 next_offset
+= sizeof(u32
);
638 case HFI_PROPERTY_PARAM_MAX_SEQUENCE_HEADER_SIZE
: {
639 u32
*max_seq_sz
= (u32
*)(data
+ next_offset
);
641 dev_dbg(dev
, "max seq header sz: %x\n", *max_seq_sz
);
642 next_offset
+= sizeof(u32
);
646 case HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH
: {
647 next_offset
+= sizeof(struct hfi_intra_refresh
);
651 case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED
: {
652 struct hfi_buffer_alloc_mode_supported
*prop
=
653 (struct hfi_buffer_alloc_mode_supported
*)
654 (data
+ next_offset
);
657 for (i
= 0; i
< prop
->num_entries
; i
++) {
658 if (prop
->buffer_type
== HFI_BUFFER_OUTPUT
||
659 prop
->buffer_type
== HFI_BUFFER_OUTPUT2
) {
660 switch (prop
->data
[i
]) {
661 case HFI_BUFFER_MODE_STATIC
:
662 inst
->cap_bufs_mode_static
= 1;
664 case HFI_BUFFER_MODE_DYNAMIC
:
665 inst
->cap_bufs_mode_dynamic
= 1;
672 next_offset
+= sizeof(*prop
) -
673 sizeof(u32
) + prop
->num_entries
* sizeof(u32
);
678 dev_dbg(dev
, "%s: default case %#x\n", __func__
, ptype
);
682 rem_bytes
-= next_offset
;
689 static void hfi_session_init_done(struct venus_core
*core
,
690 struct venus_inst
*inst
, void *packet
)
692 struct hfi_msg_session_init_done_pkt
*pkt
= packet
;
695 error
= pkt
->error_type
;
696 if (error
!= HFI_ERR_NONE
)
699 if (core
->res
->hfi_version
!= HFI_VERSION_1XX
)
702 error
= init_done_read_prop(core
, inst
, pkt
);
706 complete(&inst
->done
);
709 static void hfi_session_load_res_done(struct venus_core
*core
,
710 struct venus_inst
*inst
, void *packet
)
712 struct hfi_msg_session_load_resources_done_pkt
*pkt
= packet
;
714 inst
->error
= pkt
->error_type
;
715 complete(&inst
->done
);
718 static void hfi_session_flush_done(struct venus_core
*core
,
719 struct venus_inst
*inst
, void *packet
)
721 struct hfi_msg_session_flush_done_pkt
*pkt
= packet
;
723 inst
->error
= pkt
->error_type
;
724 complete(&inst
->done
);
727 static void hfi_session_etb_done(struct venus_core
*core
,
728 struct venus_inst
*inst
, void *packet
)
730 struct hfi_msg_session_empty_buffer_done_pkt
*pkt
= packet
;
732 inst
->error
= pkt
->error_type
;
733 inst
->ops
->buf_done(inst
, HFI_BUFFER_INPUT
, pkt
->input_tag
,
734 pkt
->filled_len
, pkt
->offset
, 0, 0, 0);
737 static void hfi_session_ftb_done(struct venus_core
*core
,
738 struct venus_inst
*inst
, void *packet
)
740 u32 session_type
= inst
->session_type
;
741 u64 timestamp_us
= 0;
742 u32 timestamp_hi
= 0, timestamp_lo
= 0;
744 u32 flags
= 0, hfi_flags
= 0, offset
= 0, filled_len
= 0;
745 u32 pic_type
= 0, buffer_type
= 0, output_tag
= -1;
747 if (session_type
== VIDC_SESSION_TYPE_ENC
) {
748 struct hfi_msg_session_fbd_compressed_pkt
*pkt
= packet
;
750 timestamp_hi
= pkt
->time_stamp_hi
;
751 timestamp_lo
= pkt
->time_stamp_lo
;
752 hfi_flags
= pkt
->flags
;
753 offset
= pkt
->offset
;
754 filled_len
= pkt
->filled_len
;
755 pic_type
= pkt
->picture_type
;
756 output_tag
= pkt
->output_tag
;
757 buffer_type
= HFI_BUFFER_OUTPUT
;
759 error
= pkt
->error_type
;
760 } else if (session_type
== VIDC_SESSION_TYPE_DEC
) {
761 struct hfi_msg_session_fbd_uncompressed_plane0_pkt
*pkt
=
764 timestamp_hi
= pkt
->time_stamp_hi
;
765 timestamp_lo
= pkt
->time_stamp_lo
;
766 hfi_flags
= pkt
->flags
;
767 offset
= pkt
->offset
;
768 filled_len
= pkt
->filled_len
;
769 pic_type
= pkt
->picture_type
;
770 output_tag
= pkt
->output_tag
;
772 if (pkt
->stream_id
== 0)
773 buffer_type
= HFI_BUFFER_OUTPUT
;
774 else if (pkt
->stream_id
== 1)
775 buffer_type
= HFI_BUFFER_OUTPUT2
;
777 error
= pkt
->error_type
;
779 error
= HFI_ERR_SESSION_INVALID_PARAMETER
;
782 if (buffer_type
!= HFI_BUFFER_OUTPUT
)
785 if (hfi_flags
& HFI_BUFFERFLAG_EOS
)
786 flags
|= V4L2_BUF_FLAG_LAST
;
789 case HFI_PICTURE_IDR
:
791 flags
|= V4L2_BUF_FLAG_KEYFRAME
;
794 flags
|= V4L2_BUF_FLAG_PFRAME
;
797 flags
|= V4L2_BUF_FLAG_BFRAME
;
799 case HFI_FRAME_NOTCODED
:
800 case HFI_UNUSED_PICT
:
806 if (!(hfi_flags
& HFI_BUFFERFLAG_TIMESTAMPINVALID
) && filled_len
) {
807 timestamp_us
= timestamp_hi
;
808 timestamp_us
= (timestamp_us
<< 32) | timestamp_lo
;
813 inst
->ops
->buf_done(inst
, buffer_type
, output_tag
, filled_len
,
814 offset
, flags
, hfi_flags
, timestamp_us
);
817 static void hfi_session_start_done(struct venus_core
*core
,
818 struct venus_inst
*inst
, void *packet
)
820 struct hfi_msg_session_start_done_pkt
*pkt
= packet
;
822 inst
->error
= pkt
->error_type
;
823 complete(&inst
->done
);
826 static void hfi_session_stop_done(struct venus_core
*core
,
827 struct venus_inst
*inst
, void *packet
)
829 struct hfi_msg_session_stop_done_pkt
*pkt
= packet
;
831 inst
->error
= pkt
->error_type
;
832 complete(&inst
->done
);
835 static void hfi_session_rel_res_done(struct venus_core
*core
,
836 struct venus_inst
*inst
, void *packet
)
838 struct hfi_msg_session_release_resources_done_pkt
*pkt
= packet
;
840 inst
->error
= pkt
->error_type
;
841 complete(&inst
->done
);
844 static void hfi_session_rel_buf_done(struct venus_core
*core
,
845 struct venus_inst
*inst
, void *packet
)
847 struct hfi_msg_session_release_buffers_done_pkt
*pkt
= packet
;
849 inst
->error
= pkt
->error_type
;
850 complete(&inst
->done
);
853 static void hfi_session_end_done(struct venus_core
*core
,
854 struct venus_inst
*inst
, void *packet
)
856 struct hfi_msg_session_end_done_pkt
*pkt
= packet
;
858 inst
->error
= pkt
->error_type
;
859 complete(&inst
->done
);
862 static void hfi_session_abort_done(struct venus_core
*core
,
863 struct venus_inst
*inst
, void *packet
)
865 struct hfi_msg_sys_session_abort_done_pkt
*pkt
= packet
;
867 inst
->error
= pkt
->error_type
;
868 complete(&inst
->done
);
871 static void hfi_session_get_seq_hdr_done(struct venus_core
*core
,
872 struct venus_inst
*inst
, void *packet
)
874 struct hfi_msg_session_get_sequence_hdr_done_pkt
*pkt
= packet
;
876 inst
->error
= pkt
->error_type
;
877 complete(&inst
->done
);
880 struct hfi_done_handler
{
884 void (*done
)(struct venus_core
*, struct venus_inst
*, void *);
888 static const struct hfi_done_handler handlers
[] = {
889 {.pkt
= HFI_MSG_EVENT_NOTIFY
,
890 .pkt_sz
= sizeof(struct hfi_msg_event_notify_pkt
),
891 .done
= hfi_event_notify
,
893 {.pkt
= HFI_MSG_SYS_INIT
,
894 .pkt_sz
= sizeof(struct hfi_msg_sys_init_done_pkt
),
895 .done
= hfi_sys_init_done
,
898 {.pkt
= HFI_MSG_SYS_PROPERTY_INFO
,
899 .pkt_sz
= sizeof(struct hfi_msg_sys_property_info_pkt
),
900 .done
= hfi_sys_property_info
,
903 {.pkt
= HFI_MSG_SYS_RELEASE_RESOURCE
,
904 .pkt_sz
= sizeof(struct hfi_msg_sys_release_resource_done_pkt
),
905 .done
= hfi_sys_rel_resource_done
,
908 {.pkt
= HFI_MSG_SYS_PING_ACK
,
909 .pkt_sz
= sizeof(struct hfi_msg_sys_ping_ack_pkt
),
910 .done
= hfi_sys_ping_done
,
913 {.pkt
= HFI_MSG_SYS_IDLE
,
914 .pkt_sz
= sizeof(struct hfi_msg_sys_idle_pkt
),
915 .done
= hfi_sys_idle_done
,
918 {.pkt
= HFI_MSG_SYS_PC_PREP
,
919 .pkt_sz
= sizeof(struct hfi_msg_sys_pc_prep_done_pkt
),
920 .done
= hfi_sys_pc_prepare_done
,
923 {.pkt
= HFI_MSG_SYS_SESSION_INIT
,
924 .pkt_sz
= sizeof(struct hfi_msg_session_init_done_pkt
),
925 .done
= hfi_session_init_done
,
927 {.pkt
= HFI_MSG_SYS_SESSION_END
,
928 .pkt_sz
= sizeof(struct hfi_msg_session_end_done_pkt
),
929 .done
= hfi_session_end_done
,
931 {.pkt
= HFI_MSG_SESSION_LOAD_RESOURCES
,
932 .pkt_sz
= sizeof(struct hfi_msg_session_load_resources_done_pkt
),
933 .done
= hfi_session_load_res_done
,
935 {.pkt
= HFI_MSG_SESSION_START
,
936 .pkt_sz
= sizeof(struct hfi_msg_session_start_done_pkt
),
937 .done
= hfi_session_start_done
,
939 {.pkt
= HFI_MSG_SESSION_STOP
,
940 .pkt_sz
= sizeof(struct hfi_msg_session_stop_done_pkt
),
941 .done
= hfi_session_stop_done
,
943 {.pkt
= HFI_MSG_SYS_SESSION_ABORT
,
944 .pkt_sz
= sizeof(struct hfi_msg_sys_session_abort_done_pkt
),
945 .done
= hfi_session_abort_done
,
947 {.pkt
= HFI_MSG_SESSION_EMPTY_BUFFER
,
948 .pkt_sz
= sizeof(struct hfi_msg_session_empty_buffer_done_pkt
),
949 .done
= hfi_session_etb_done
,
951 {.pkt
= HFI_MSG_SESSION_FILL_BUFFER
,
952 .pkt_sz
= sizeof(struct hfi_msg_session_fbd_uncompressed_plane0_pkt
),
953 .pkt_sz2
= sizeof(struct hfi_msg_session_fbd_compressed_pkt
),
954 .done
= hfi_session_ftb_done
,
956 {.pkt
= HFI_MSG_SESSION_FLUSH
,
957 .pkt_sz
= sizeof(struct hfi_msg_session_flush_done_pkt
),
958 .done
= hfi_session_flush_done
,
960 {.pkt
= HFI_MSG_SESSION_PROPERTY_INFO
,
961 .pkt_sz
= sizeof(struct hfi_msg_session_property_info_pkt
),
962 .done
= hfi_session_prop_info
,
964 {.pkt
= HFI_MSG_SESSION_RELEASE_RESOURCES
,
965 .pkt_sz
= sizeof(struct hfi_msg_session_release_resources_done_pkt
),
966 .done
= hfi_session_rel_res_done
,
968 {.pkt
= HFI_MSG_SESSION_GET_SEQUENCE_HEADER
,
969 .pkt_sz
= sizeof(struct hfi_msg_session_get_sequence_hdr_done_pkt
),
970 .done
= hfi_session_get_seq_hdr_done
,
972 {.pkt
= HFI_MSG_SESSION_RELEASE_BUFFERS
,
973 .pkt_sz
= sizeof(struct hfi_msg_session_release_buffers_done_pkt
),
974 .done
= hfi_session_rel_buf_done
,
978 void hfi_process_watchdog_timeout(struct venus_core
*core
)
980 event_sys_error(core
, EVT_SYS_WATCHDOG_TIMEOUT
, NULL
);
983 static struct venus_inst
*to_instance(struct venus_core
*core
, u32 session_id
)
985 struct venus_inst
*inst
;
987 mutex_lock(&core
->lock
);
988 list_for_each_entry(inst
, &core
->instances
, list
)
989 if (hash32_ptr(inst
) == session_id
) {
990 mutex_unlock(&core
->lock
);
993 mutex_unlock(&core
->lock
);
998 u32
hfi_process_msg_packet(struct venus_core
*core
, struct hfi_pkt_hdr
*hdr
)
1000 const struct hfi_done_handler
*handler
;
1001 struct device
*dev
= core
->dev
;
1002 struct venus_inst
*inst
;
1006 for (i
= 0; i
< ARRAY_SIZE(handlers
); i
++) {
1007 handler
= &handlers
[i
];
1008 if (handler
->pkt
!= hdr
->pkt_type
)
1015 return hdr
->pkt_type
;
1017 if (hdr
->size
&& hdr
->size
< handler
->pkt_sz
&&
1018 hdr
->size
< handler
->pkt_sz2
) {
1019 dev_err(dev
, "bad packet size (%d should be %d, pkt type:%x)\n",
1020 hdr
->size
, handler
->pkt_sz
, hdr
->pkt_type
);
1022 return hdr
->pkt_type
;
1025 if (handler
->is_sys_pkt
) {
1028 struct hfi_session_pkt
*pkt
;
1030 pkt
= (struct hfi_session_pkt
*)hdr
;
1031 inst
= to_instance(core
, pkt
->shdr
.session_id
);
1034 dev_warn(dev
, "no valid instance(pkt session_id:%x, pkt:%x)\n",
1035 pkt
->shdr
.session_id
,
1036 handler
? handler
->pkt
: 0);
1039 * Event of type HFI_EVENT_SYS_ERROR will not have any session
1040 * associated with it
1042 if (!inst
&& hdr
->pkt_type
!= HFI_MSG_EVENT_NOTIFY
) {
1043 dev_err(dev
, "got invalid session id:%x\n",
1044 pkt
->shdr
.session_id
);
1045 goto invalid_session
;
1049 handler
->done(core
, inst
, hdr
);
1052 return hdr
->pkt_type
;