PageRenderTime 77ms CodeModel.GetById 36ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/media/platform/qcom/venus/hfi_parser.c

https://github.com/kvaneesh/linux
C | 325 lines | 253 code | 66 blank | 6 comment | 40 complexity | 11ee8806e4990183b54c48c951ee70bd MD5 | raw file
  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 hfi_plat_caps *cap, const void *data,
  13. unsigned int size);
  14. static void init_codecs(struct venus_core *core)
  15. {
  16. struct hfi_plat_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 hfi_plat_caps *caps, unsigned int caps_num,
  32. u32 codecs, u32 domain, func cb, void *data,
  33. unsigned int size)
  34. {
  35. struct hfi_plat_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 hfi_plat_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 hfi_plat_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 hfi_plat_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 hfi_plat_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. core->enc_codecs &= ~HFI_VIDEO_CODEC_HEVC;
  148. }
  149. }
  150. static void parse_max_sessions(struct venus_core *core, const void *data)
  151. {
  152. const struct hfi_max_sessions_supported *sessions = data;
  153. core->max_sessions_supported = sessions->max_sessions;
  154. }
  155. static void parse_codecs_mask(u32 *codecs, u32 *domain, void *data)
  156. {
  157. struct hfi_codec_mask_supported *mask = data;
  158. *codecs = mask->codecs;
  159. *domain = mask->video_domains;
  160. }
  161. static void parser_init(struct venus_inst *inst, u32 *codecs, u32 *domain)
  162. {
  163. if (!inst || !IS_V1(inst->core))
  164. return;
  165. *codecs = inst->hfi_codec;
  166. *domain = inst->session_type;
  167. }
  168. static void parser_fini(struct venus_inst *inst, u32 codecs, u32 domain)
  169. {
  170. struct hfi_plat_caps *caps, *cap;
  171. unsigned int i;
  172. u32 dom;
  173. if (!inst || !IS_V1(inst->core))
  174. return;
  175. caps = inst->core->caps;
  176. dom = inst->session_type;
  177. for (i = 0; i < MAX_CODEC_NUM; i++) {
  178. cap = &caps[i];
  179. if (cap->codec & codecs && cap->domain == dom)
  180. cap->valid = true;
  181. }
  182. }
  183. static int hfi_platform_parser(struct venus_core *core, struct venus_inst *inst)
  184. {
  185. const struct hfi_platform *plat;
  186. const struct hfi_plat_caps *caps = NULL;
  187. u32 enc_codecs, dec_codecs, count = 0;
  188. unsigned int entries;
  189. plat = hfi_platform_get(core->res->hfi_version);
  190. if (!plat)
  191. return -EINVAL;
  192. if (inst)
  193. return 0;
  194. if (plat->codecs)
  195. plat->codecs(&enc_codecs, &dec_codecs, &count);
  196. if (plat->capabilities)
  197. caps = plat->capabilities(&entries);
  198. if (!caps || !entries || !count)
  199. return -EINVAL;
  200. core->enc_codecs = enc_codecs;
  201. core->dec_codecs = dec_codecs;
  202. core->codecs_count = count;
  203. core->max_sessions_supported = MAX_SESSIONS;
  204. memset(core->caps, 0, sizeof(*caps) * MAX_CODEC_NUM);
  205. memcpy(core->caps, caps, sizeof(*caps) * entries);
  206. return 0;
  207. }
  208. u32 hfi_parser(struct venus_core *core, struct venus_inst *inst, void *buf,
  209. u32 size)
  210. {
  211. unsigned int words_count = size >> 2;
  212. u32 *word = buf, *data, codecs = 0, domain = 0;
  213. int ret;
  214. ret = hfi_platform_parser(core, inst);
  215. if (!ret)
  216. return HFI_ERR_NONE;
  217. if (size % 4)
  218. return HFI_ERR_SYS_INSUFFICIENT_RESOURCES;
  219. parser_init(inst, &codecs, &domain);
  220. if (core->res->hfi_version > HFI_VERSION_1XX) {
  221. core->codecs_count = 0;
  222. memset(core->caps, 0, sizeof(core->caps));
  223. }
  224. while (words_count) {
  225. data = word + 1;
  226. switch (*word) {
  227. case HFI_PROPERTY_PARAM_CODEC_SUPPORTED:
  228. parse_codecs(core, data);
  229. init_codecs(core);
  230. break;
  231. case HFI_PROPERTY_PARAM_MAX_SESSIONS_SUPPORTED:
  232. parse_max_sessions(core, data);
  233. break;
  234. case HFI_PROPERTY_PARAM_CODEC_MASK_SUPPORTED:
  235. parse_codecs_mask(&codecs, &domain, data);
  236. break;
  237. case HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
  238. parse_raw_formats(core, codecs, domain, data);
  239. break;
  240. case HFI_PROPERTY_PARAM_CAPABILITY_SUPPORTED:
  241. parse_caps(core, codecs, domain, data);
  242. break;
  243. case HFI_PROPERTY_PARAM_PROFILE_LEVEL_SUPPORTED:
  244. parse_profile_level(core, codecs, domain, data);
  245. break;
  246. case HFI_PROPERTY_PARAM_BUFFER_ALLOC_MODE_SUPPORTED:
  247. parse_alloc_mode(core, codecs, domain, data);
  248. break;
  249. default:
  250. break;
  251. }
  252. word++;
  253. words_count--;
  254. }
  255. if (!core->max_sessions_supported)
  256. core->max_sessions_supported = MAX_SESSIONS;
  257. parser_fini(inst, codecs, domain);
  258. return HFI_ERR_NONE;
  259. }