1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2018 Linaro Ltd.
5 * Author: Stanimir Varbanov <stanimir.varbanov@linaro.org>
7 #include <linux/bitops.h>
8 #include <linux/kernel.h>
11 #include "hfi_helper.h"
12 #include "hfi_parser.h"
14 typedef void (*func
)(struct venus_caps
*cap
, const void *data
,
17 static void init_codecs(struct venus_core
*core
)
19 struct venus_caps
*caps
= core
->caps
, *cap
;
22 for_each_set_bit(bit
, &core
->dec_codecs
, MAX_CODEC_NUM
) {
23 cap
= &caps
[core
->codecs_count
++];
24 cap
->codec
= BIT(bit
);
25 cap
->domain
= VIDC_SESSION_TYPE_DEC
;
29 for_each_set_bit(bit
, &core
->enc_codecs
, MAX_CODEC_NUM
) {
30 cap
= &caps
[core
->codecs_count
++];
31 cap
->codec
= BIT(bit
);
32 cap
->domain
= VIDC_SESSION_TYPE_ENC
;
37 static void for_each_codec(struct venus_caps
*caps
, unsigned int caps_num
,
38 u32 codecs
, u32 domain
, func cb
, void *data
,
41 struct venus_caps
*cap
;
44 for (i
= 0; i
< caps_num
; i
++) {
46 if (cap
->valid
&& cap
->domain
== domain
)
48 if (cap
->codec
& codecs
&& cap
->domain
== domain
)
54 fill_buf_mode(struct venus_caps
*cap
, const void *data
, unsigned int num
)
56 const u32
*type
= data
;
58 if (*type
== HFI_BUFFER_MODE_DYNAMIC
)
59 cap
->cap_bufs_mode_dynamic
= true;
63 parse_alloc_mode(struct venus_core
*core
, u32 codecs
, u32 domain
, void *data
)
65 struct hfi_buffer_alloc_mode_supported
*mode
= data
;
66 u32 num_entries
= mode
->num_entries
;
69 if (num_entries
> MAX_ALLOC_MODE_ENTRIES
)
74 while (num_entries
--) {
75 if (mode
->buffer_type
== HFI_BUFFER_OUTPUT
||
76 mode
->buffer_type
== HFI_BUFFER_OUTPUT2
)
77 for_each_codec(core
->caps
, ARRAY_SIZE(core
->caps
),
78 codecs
, domain
, fill_buf_mode
, type
, 1);
84 static void fill_profile_level(struct venus_caps
*cap
, const void *data
,
87 const struct hfi_profile_level
*pl
= data
;
89 memcpy(&cap
->pl
[cap
->num_pl
], pl
, num
* sizeof(*pl
));
94 parse_profile_level(struct venus_core
*core
, u32 codecs
, u32 domain
, void *data
)
96 struct hfi_profile_level_supported
*pl
= data
;
97 struct hfi_profile_level
*proflevel
= pl
->profile_level
;
98 struct hfi_profile_level pl_arr
[HFI_MAX_PROFILE_COUNT
] = {};
100 if (pl
->profile_count
> HFI_MAX_PROFILE_COUNT
)
103 memcpy(pl_arr
, proflevel
, pl
->profile_count
* sizeof(*proflevel
));
105 for_each_codec(core
->caps
, ARRAY_SIZE(core
->caps
), codecs
, domain
,
106 fill_profile_level
, pl_arr
, pl
->profile_count
);
110 fill_caps(struct venus_caps
*cap
, const void *data
, unsigned int num
)
112 const struct hfi_capability
*caps
= data
;
114 memcpy(&cap
->caps
[cap
->num_caps
], caps
, num
* sizeof(*caps
));
115 cap
->num_caps
+= num
;
119 parse_caps(struct venus_core
*core
, u32 codecs
, u32 domain
, void *data
)
121 struct hfi_capabilities
*caps
= data
;
122 struct hfi_capability
*cap
= caps
->data
;
123 u32 num_caps
= caps
->num_capabilities
;
124 struct hfi_capability caps_arr
[MAX_CAP_ENTRIES
] = {};
126 if (num_caps
> MAX_CAP_ENTRIES
)
129 memcpy(caps_arr
, cap
, num_caps
* sizeof(*cap
));
131 for_each_codec(core
->caps
, ARRAY_SIZE(core
->caps
), codecs
, domain
,
132 fill_caps
, caps_arr
, num_caps
);
135 static void fill_raw_fmts(struct venus_caps
*cap
, const void *fmts
,
136 unsigned int num_fmts
)
138 const struct raw_formats
*formats
= fmts
;
140 memcpy(&cap
->fmts
[cap
->num_fmts
], formats
, num_fmts
* sizeof(*formats
));
141 cap
->num_fmts
+= num_fmts
;
145 parse_raw_formats(struct venus_core
*core
, u32 codecs
, u32 domain
, void *data
)
147 struct hfi_uncompressed_format_supported
*fmt
= data
;
148 struct hfi_uncompressed_plane_info
*pinfo
= fmt
->plane_info
;
149 struct hfi_uncompressed_plane_constraints
*constr
;
150 struct raw_formats rawfmts
[MAX_FMT_ENTRIES
] = {};
151 u32 entries
= fmt
->format_entries
;
156 num_planes
= pinfo
->num_planes
;
158 rawfmts
[i
].fmt
= pinfo
->format
;
159 rawfmts
[i
].buftype
= fmt
->buffer_type
;
162 if (pinfo
->num_planes
> MAX_PLANES
)
165 pinfo
= (void *)pinfo
+ sizeof(*constr
) * num_planes
+
170 for_each_codec(core
->caps
, ARRAY_SIZE(core
->caps
), codecs
, domain
,
171 fill_raw_fmts
, rawfmts
, i
);
174 static void parse_codecs(struct venus_core
*core
, void *data
)
176 struct hfi_codec_supported
*codecs
= data
;
178 core
->dec_codecs
= codecs
->dec_codecs
;
179 core
->enc_codecs
= codecs
->enc_codecs
;
182 core
->dec_codecs
&= ~HFI_VIDEO_CODEC_HEVC
;
183 core
->dec_codecs
&= ~HFI_VIDEO_CODEC_SPARK
;
187 static void parse_max_sessions(struct venus_core
*core
, const void *data
)
189 const struct hfi_max_sessions_supported
*sessions
= data
;
191 core
->max_sessions_supported
= sessions
->max_sessions
;
194 static void parse_codecs_mask(u32
*codecs
, u32
*domain
, void *data
)
196 struct hfi_codec_mask_supported
*mask
= data
;
198 *codecs
= mask
->codecs
;
199 *domain
= mask
->video_domains
;
202 static void parser_init(struct venus_inst
*inst
, u32
*codecs
, u32
*domain
)
204 if (!inst
|| !IS_V1(inst
->core
))
207 *codecs
= inst
->hfi_codec
;
208 *domain
= inst
->session_type
;
211 static void parser_fini(struct venus_inst
*inst
, u32 codecs
, u32 domain
)
213 struct venus_caps
*caps
, *cap
;
217 if (!inst
|| !IS_V1(inst
->core
))
220 caps
= inst
->core
->caps
;
221 dom
= inst
->session_type
;
223 for (i
= 0; i
< MAX_CODEC_NUM
; i
++) {
225 if (cap
->codec
& codecs
&& cap
->domain
== dom
)
230 u32
hfi_parser(struct venus_core
*core
, struct venus_inst
*inst
, void *buf
,
233 unsigned int words_count
= size
>> 2;
234 u32
*word
= buf
, *data
, codecs
= 0, domain
= 0;
237 return HFI_ERR_SYS_INSUFFICIENT_RESOURCES
;
239 parser_init(inst
, &codecs
, &domain
);
241 while (words_count
) {
245 case HFI_PROPERTY_PARAM_CODEC_SUPPORTED
:
246 parse_codecs(core
, data
);
249 case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED
:
250 parse_max_sessions(core
, data
);
252 case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED
:
253 parse_codecs_mask(&codecs
, &domain
, data
);
255 case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED
:
256 parse_raw_formats(core
, codecs
, domain
, data
);
258 case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED
:
259 parse_caps(core
, codecs
, domain
, data
);
261 case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED
:
262 parse_profile_level(core
, codecs
, domain
, data
);
264 case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED
:
265 parse_alloc_mode(core
, codecs
, domain
, data
);
275 parser_fini(inst
, codecs
, domain
);