hfi_parser.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2018 Linaro Ltd.
  4. *
  5. * Author: Stanimir Varbanov <stanimir.varbanov@linaro.org>
  6. */
  7. #include <linux/bitops.h>
  8. #include <linux/kernel.h>
  9. #include "core.h"
  10. #include "hfi_helper.h"
  11. #include "hfi_parser.h"
  12. typedef void (*func)(struct venus_caps *cap, const void *data,
  13. unsigned int size);
  14. static void init_codecs(struct venus_core *core)
  15. {
  16. struct venus_caps *caps = core->caps, *cap;
  17. unsigned long bit;
  18. for_each_set_bit(bit, &core->dec_codecs, MAX_CODEC_NUM) {
  19. cap = &caps[core->codecs_count++];
  20. cap->codec = BIT(bit);
  21. cap->domain = VIDC_SESSION_TYPE_DEC;
  22. cap->valid = false;
  23. }
  24. for_each_set_bit(bit, &core->enc_codecs, MAX_CODEC_NUM) {
  25. cap = &caps[core->codecs_count++];
  26. cap->codec = BIT(bit);
  27. cap->domain = VIDC_SESSION_TYPE_ENC;
  28. cap->valid = false;
  29. }
  30. }
  31. static void for_each_codec(struct venus_caps *caps, unsigned int caps_num,
  32. u32 codecs, u32 domain, func cb, void *data,
  33. unsigned int size)
  34. {
  35. struct venus_caps *cap;
  36. unsigned int i;
  37. for (i = 0; i < caps_num; i++) {
  38. cap = &caps[i];
  39. if (cap->valid && cap->domain == domain)
  40. continue;
  41. if (cap->codec & codecs && cap->domain == domain)
  42. cb(cap, data, size);
  43. }
  44. }
  45. static void
  46. fill_buf_mode(struct venus_caps *cap, const void *data, unsigned int num)
  47. {
  48. const u32 *type = data;
  49. if (*type == HFI_BUFFER_MODE_DYNAMIC)
  50. cap->cap_bufs_mode_dynamic = true;
  51. }
  52. static void
  53. parse_alloc_mode(struct venus_core *core, u32 codecs, u32 domain, void *data)
  54. {
  55. struct hfi_buffer_alloc_mode_supported *mode = data;
  56. u32 num_entries = mode->num_entries;
  57. u32 *type;
  58. if (num_entries > MAX_ALLOC_MODE_ENTRIES)
  59. return;
  60. type = mode->data;
  61. while (num_entries--) {
  62. if (mode->buffer_type == HFI_BUFFER_OUTPUT ||
  63. mode->buffer_type == HFI_BUFFER_OUTPUT2)
  64. for_each_codec(core->caps, ARRAY_SIZE(core->caps),
  65. codecs, domain, fill_buf_mode, type, 1);
  66. type++;
  67. }
  68. }
  69. static void fill_profile_level(struct venus_caps *cap, const void *data,
  70. unsigned int num)
  71. {
  72. const struct hfi_profile_level *pl = data;
  73. memcpy(&cap->pl[cap->num_pl], pl, num * sizeof(*pl));
  74. cap->num_pl += num;
  75. }
  76. static void
  77. parse_profile_level(struct venus_core *core, u32 codecs, u32 domain, void *data)
  78. {
  79. struct hfi_profile_level_supported *pl = data;
  80. struct hfi_profile_level *proflevel = pl->profile_level;
  81. struct hfi_profile_level pl_arr[HFI_MAX_PROFILE_COUNT] = {};
  82. if (pl->profile_count > HFI_MAX_PROFILE_COUNT)
  83. return;
  84. memcpy(pl_arr, proflevel, pl->profile_count * sizeof(*proflevel));
  85. for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain,
  86. fill_profile_level, pl_arr, pl->profile_count);
  87. }
  88. static void
  89. fill_caps(struct venus_caps *cap, const void *data, unsigned int num)
  90. {
  91. const struct hfi_capability *caps = data;
  92. memcpy(&cap->caps[cap->num_caps], caps, num * sizeof(*caps));
  93. cap->num_caps += num;
  94. }
  95. static void
  96. parse_caps(struct venus_core *core, u32 codecs, u32 domain, void *data)
  97. {
  98. struct hfi_capabilities *caps = data;
  99. struct hfi_capability *cap = caps->data;
  100. u32 num_caps = caps->num_capabilities;
  101. struct hfi_capability caps_arr[MAX_CAP_ENTRIES] = {};
  102. if (num_caps > MAX_CAP_ENTRIES)
  103. return;
  104. memcpy(caps_arr, cap, num_caps * sizeof(*cap));
  105. for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain,
  106. fill_caps, caps_arr, num_caps);
  107. }
  108. static void fill_raw_fmts(struct venus_caps *cap, const void *fmts,
  109. unsigned int num_fmts)
  110. {
  111. const struct raw_formats *formats = fmts;
  112. memcpy(&cap->fmts[cap->num_fmts], formats, num_fmts * sizeof(*formats));
  113. cap->num_fmts += num_fmts;
  114. }
  115. static void
  116. parse_raw_formats(struct venus_core *core, u32 codecs, u32 domain, void *data)
  117. {
  118. struct hfi_uncompressed_format_supported *fmt = data;
  119. struct hfi_uncompressed_plane_info *pinfo = fmt->plane_info;
  120. struct hfi_uncompressed_plane_constraints *constr;
  121. struct raw_formats rawfmts[MAX_FMT_ENTRIES] = {};
  122. u32 entries = fmt->format_entries;
  123. unsigned int i = 0;
  124. u32 num_planes;
  125. while (entries) {
  126. num_planes = pinfo->num_planes;
  127. rawfmts[i].fmt = pinfo->format;
  128. rawfmts[i].buftype = fmt->buffer_type;
  129. i++;
  130. if (pinfo->num_planes > MAX_PLANES)
  131. break;
  132. pinfo = (void *)pinfo + sizeof(*constr) * num_planes +
  133. 2 * sizeof(u32);
  134. entries--;
  135. }
  136. for_each_codec(core->caps, ARRAY_SIZE(core->caps), codecs, domain,
  137. fill_raw_fmts, rawfmts, i);
  138. }
  139. static void parse_codecs(struct venus_core *core, void *data)
  140. {
  141. struct hfi_codec_supported *codecs = data;
  142. core->dec_codecs = codecs->dec_codecs;
  143. core->enc_codecs = codecs->enc_codecs;
  144. if (IS_V1(core)) {
  145. core->dec_codecs &= ~HFI_VIDEO_CODEC_HEVC;
  146. core->dec_codecs &= ~HFI_VIDEO_CODEC_SPARK;
  147. }
  148. }
  149. static void parse_max_sessions(struct venus_core *core, const void *data)
  150. {
  151. const struct hfi_max_sessions_supported *sessions = data;
  152. core->max_sessions_supported = sessions->max_sessions;
  153. }
  154. static void parse_codecs_mask(u32 *codecs, u32 *domain, void *data)
  155. {
  156. struct hfi_codec_mask_supported *mask = data;
  157. *codecs = mask->codecs;
  158. *domain = mask->video_domains;
  159. }
  160. static void parser_init(struct venus_inst *inst, u32 *codecs, u32 *domain)
  161. {
  162. if (!inst || !IS_V1(inst->core))
  163. return;
  164. *codecs = inst->hfi_codec;
  165. *domain = inst->session_type;
  166. }
  167. static void parser_fini(struct venus_inst *inst, u32 codecs, u32 domain)
  168. {
  169. struct venus_caps *caps, *cap;
  170. unsigned int i;
  171. u32 dom;
  172. if (!inst || !IS_V1(inst->core))
  173. return;
  174. caps = inst->core->caps;
  175. dom = inst->session_type;
  176. for (i = 0; i < MAX_CODEC_NUM; i++) {
  177. cap = &caps[i];
  178. if (cap->codec & codecs && cap->domain == dom)
  179. cap->valid = true;
  180. }
  181. }
  182. u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf,
  183. u32 size)
  184. {
  185. unsigned int words_count = size >> 2;
  186. u32 *word = buf, *data, codecs = 0, domain = 0;
  187. if (size % 4)
  188. return HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
  189. parser_init(inst, &codecs, &domain);
  190. while (words_count) {
  191. data = word + 1;
  192. switch (*word) {
  193. case HFI_PROPERTY_PARAM_CODEC_SUPPORTED:
  194. parse_codecs(core, data);
  195. init_codecs(core);
  196. break;
  197. case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED:
  198. parse_max_sessions(core, data);
  199. break;
  200. case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED:
  201. parse_codecs_mask(&codecs, &domain, data);
  202. break;
  203. case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
  204. parse_raw_formats(core, codecs, domain, data);
  205. break;
  206. case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED:
  207. parse_caps(core, codecs, domain, data);
  208. break;
  209. case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED:
  210. parse_profile_level(core, codecs, domain, data);
  211. break;
  212. case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED:
  213. parse_alloc_mode(core, codecs, domain, data);
  214. break;
  215. default:
  216. break;
  217. }
  218. word++;
  219. words_count--;
  220. }
  221. parser_fini(inst, codecs, domain);
  222. return HFI_ERR_NONE;
  223. }