hva-debugfs.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /*
  2. * Copyright (C) STMicroelectronics SA 2015
  3. * Authors: Yannick Fertre <yannick.fertre@st.com>
  4. * Hugues Fruchet <hugues.fruchet@st.com>
  5. * License terms: GNU General Public License (GPL), version 2
  6. */
  7. #include <linux/debugfs.h>
  8. #include "hva.h"
  9. #include "hva-hw.h"
  10. static void format_ctx(struct seq_file *s, struct hva_ctx *ctx)
  11. {
  12. struct hva_streaminfo *stream = &ctx->streaminfo;
  13. struct hva_frameinfo *frame = &ctx->frameinfo;
  14. struct hva_controls *ctrls = &ctx->ctrls;
  15. struct hva_ctx_dbg *dbg = &ctx->dbg;
  16. u32 bitrate_mode, aspect, entropy, vui_sar, sei_fp;
  17. seq_printf(s, "|-%s\n |\n", ctx->name);
  18. seq_printf(s, " |-[%sframe info]\n",
  19. ctx->flags & HVA_FLAG_FRAMEINFO ? "" : "default ");
  20. seq_printf(s, " | |- pixel format=%4.4s\n"
  21. " | |- wxh=%dx%d\n"
  22. " | |- wxh (w/ encoder alignment constraint)=%dx%d\n"
  23. " |\n",
  24. (char *)&frame->pixelformat,
  25. frame->width, frame->height,
  26. frame->aligned_width, frame->aligned_height);
  27. seq_printf(s, " |-[%sstream info]\n",
  28. ctx->flags & HVA_FLAG_STREAMINFO ? "" : "default ");
  29. seq_printf(s, " | |- stream format=%4.4s\n"
  30. " | |- wxh=%dx%d\n"
  31. " | |- %s\n"
  32. " | |- %s\n"
  33. " |\n",
  34. (char *)&stream->streamformat,
  35. stream->width, stream->height,
  36. stream->profile, stream->level);
  37. bitrate_mode = V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
  38. aspect = V4L2_CID_MPEG_VIDEO_ASPECT;
  39. seq_puts(s, " |-[parameters]\n");
  40. seq_printf(s, " | |- %s\n"
  41. " | |- bitrate=%d bps\n"
  42. " | |- GOP size=%d\n"
  43. " | |- video aspect=%s\n"
  44. " | |- framerate=%d/%d\n",
  45. v4l2_ctrl_get_menu(bitrate_mode)[ctrls->bitrate_mode],
  46. ctrls->bitrate,
  47. ctrls->gop_size,
  48. v4l2_ctrl_get_menu(aspect)[ctrls->aspect],
  49. ctrls->time_per_frame.denominator,
  50. ctrls->time_per_frame.numerator);
  51. entropy = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
  52. vui_sar = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC;
  53. sei_fp = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE;
  54. if (stream->streamformat == V4L2_PIX_FMT_H264) {
  55. seq_printf(s, " | |- %s entropy mode\n"
  56. " | |- CPB size=%d kB\n"
  57. " | |- DCT8x8 enable=%s\n"
  58. " | |- qpmin=%d\n"
  59. " | |- qpmax=%d\n"
  60. " | |- PAR enable=%s\n"
  61. " | |- PAR id=%s\n"
  62. " | |- SEI frame packing enable=%s\n"
  63. " | |- SEI frame packing type=%s\n",
  64. v4l2_ctrl_get_menu(entropy)[ctrls->entropy_mode],
  65. ctrls->cpb_size,
  66. ctrls->dct8x8 ? "true" : "false",
  67. ctrls->qpmin,
  68. ctrls->qpmax,
  69. ctrls->vui_sar ? "true" : "false",
  70. v4l2_ctrl_get_menu(vui_sar)[ctrls->vui_sar_idc],
  71. ctrls->sei_fp ? "true" : "false",
  72. v4l2_ctrl_get_menu(sei_fp)[ctrls->sei_fp_type]);
  73. }
  74. if (ctx->sys_errors || ctx->encode_errors || ctx->frame_errors) {
  75. seq_puts(s, " |\n |-[errors]\n");
  76. seq_printf(s, " | |- system=%d\n"
  77. " | |- encoding=%d\n"
  78. " | |- frame=%d\n",
  79. ctx->sys_errors,
  80. ctx->encode_errors,
  81. ctx->frame_errors);
  82. }
  83. seq_puts(s, " |\n |-[performances]\n");
  84. seq_printf(s, " | |- frames encoded=%d\n"
  85. " | |- avg HW processing duration (0.1ms)=%d [min=%d, max=%d]\n"
  86. " | |- avg encoding period (0.1ms)=%d [min=%d, max=%d]\n"
  87. " | |- avg fps (0.1Hz)=%d\n"
  88. " | |- max reachable fps (0.1Hz)=%d\n"
  89. " | |- avg bitrate (kbps)=%d [min=%d, max=%d]\n"
  90. " | |- last bitrate (kbps)=%d\n",
  91. dbg->cnt_duration,
  92. dbg->avg_duration,
  93. dbg->min_duration,
  94. dbg->max_duration,
  95. dbg->avg_period,
  96. dbg->min_period,
  97. dbg->max_period,
  98. dbg->avg_fps,
  99. dbg->max_fps,
  100. dbg->avg_bitrate,
  101. dbg->min_bitrate,
  102. dbg->max_bitrate,
  103. dbg->last_bitrate);
  104. }
  105. /*
  106. * performance debug info
  107. */
  108. void hva_dbg_perf_begin(struct hva_ctx *ctx)
  109. {
  110. u64 div;
  111. u32 period;
  112. u32 bitrate;
  113. struct hva_ctx_dbg *dbg = &ctx->dbg;
  114. ktime_t prev = dbg->begin;
  115. dbg->begin = ktime_get();
  116. if (dbg->is_valid_period) {
  117. /* encoding period */
  118. div = (u64)ktime_us_delta(dbg->begin, prev);
  119. do_div(div, 100);
  120. period = (u32)div;
  121. dbg->min_period = min(period, dbg->min_period);
  122. dbg->max_period = max(period, dbg->max_period);
  123. dbg->total_period += period;
  124. dbg->cnt_period++;
  125. /*
  126. * minimum and maximum bitrates are based on the
  127. * encoding period values upon a window of 32 samples
  128. */
  129. dbg->window_duration += period;
  130. dbg->cnt_window++;
  131. if (dbg->cnt_window >= 32) {
  132. /*
  133. * bitrate in kbps = (size * 8 / 1000) /
  134. * (duration / 10000)
  135. * = size * 80 / duration
  136. */
  137. if (dbg->window_duration > 0) {
  138. div = (u64)dbg->window_stream_size * 80;
  139. do_div(div, dbg->window_duration);
  140. bitrate = (u32)div;
  141. dbg->last_bitrate = bitrate;
  142. dbg->min_bitrate = min(bitrate,
  143. dbg->min_bitrate);
  144. dbg->max_bitrate = max(bitrate,
  145. dbg->max_bitrate);
  146. }
  147. dbg->window_stream_size = 0;
  148. dbg->window_duration = 0;
  149. dbg->cnt_window = 0;
  150. }
  151. }
  152. /*
  153. * filter sequences valid for performance:
  154. * - begin/begin (no stream available) is an invalid sequence
  155. * - begin/end is a valid sequence
  156. */
  157. dbg->is_valid_period = false;
  158. }
  159. void hva_dbg_perf_end(struct hva_ctx *ctx, struct hva_stream *stream)
  160. {
  161. struct device *dev = ctx_to_dev(ctx);
  162. u64 div;
  163. u32 duration;
  164. u32 bytesused;
  165. u32 timestamp;
  166. struct hva_ctx_dbg *dbg = &ctx->dbg;
  167. ktime_t end = ktime_get();
  168. /* stream bytesused and timestamp in us */
  169. bytesused = vb2_get_plane_payload(&stream->vbuf.vb2_buf, 0);
  170. div = stream->vbuf.vb2_buf.timestamp;
  171. do_div(div, 1000);
  172. timestamp = (u32)div;
  173. /* encoding duration */
  174. div = (u64)ktime_us_delta(end, dbg->begin);
  175. dev_dbg(dev,
  176. "%s perf stream[%d] dts=%d encoded using %d bytes in %d us",
  177. ctx->name,
  178. stream->vbuf.sequence,
  179. timestamp,
  180. bytesused, (u32)div);
  181. do_div(div, 100);
  182. duration = (u32)div;
  183. dbg->min_duration = min(duration, dbg->min_duration);
  184. dbg->max_duration = max(duration, dbg->max_duration);
  185. dbg->total_duration += duration;
  186. dbg->cnt_duration++;
  187. /*
  188. * the average bitrate is based on the total stream size
  189. * and the total encoding periods
  190. */
  191. dbg->total_stream_size += bytesused;
  192. dbg->window_stream_size += bytesused;
  193. dbg->is_valid_period = true;
  194. }
  195. static void hva_dbg_perf_compute(struct hva_ctx *ctx)
  196. {
  197. u64 div;
  198. struct hva_ctx_dbg *dbg = &ctx->dbg;
  199. if (dbg->cnt_duration > 0) {
  200. div = (u64)dbg->total_duration;
  201. do_div(div, dbg->cnt_duration);
  202. dbg->avg_duration = (u32)div;
  203. } else {
  204. dbg->avg_duration = 0;
  205. }
  206. if (dbg->total_duration > 0) {
  207. div = (u64)dbg->cnt_duration * 100000;
  208. do_div(div, dbg->total_duration);
  209. dbg->max_fps = (u32)div;
  210. } else {
  211. dbg->max_fps = 0;
  212. }
  213. if (dbg->cnt_period > 0) {
  214. div = (u64)dbg->total_period;
  215. do_div(div, dbg->cnt_period);
  216. dbg->avg_period = (u32)div;
  217. } else {
  218. dbg->avg_period = 0;
  219. }
  220. if (dbg->total_period > 0) {
  221. div = (u64)dbg->cnt_period * 100000;
  222. do_div(div, dbg->total_period);
  223. dbg->avg_fps = (u32)div;
  224. } else {
  225. dbg->avg_fps = 0;
  226. }
  227. if (dbg->total_period > 0) {
  228. /*
  229. * bitrate in kbps = (video size * 8 / 1000) /
  230. * (video duration / 10000)
  231. * = video size * 80 / video duration
  232. */
  233. div = (u64)dbg->total_stream_size * 80;
  234. do_div(div, dbg->total_period);
  235. dbg->avg_bitrate = (u32)div;
  236. } else {
  237. dbg->avg_bitrate = 0;
  238. }
  239. }
  240. /*
  241. * device debug info
  242. */
  243. static int hva_dbg_device(struct seq_file *s, void *data)
  244. {
  245. struct hva_dev *hva = s->private;
  246. seq_printf(s, "[%s]\n", hva->v4l2_dev.name);
  247. seq_printf(s, "registered as /dev/video%d\n", hva->vdev->num);
  248. return 0;
  249. }
  250. static int hva_dbg_encoders(struct seq_file *s, void *data)
  251. {
  252. struct hva_dev *hva = s->private;
  253. unsigned int i = 0;
  254. seq_printf(s, "[encoders]\n|- %d registered encoders:\n",
  255. hva->nb_of_encoders);
  256. while (hva->encoders[i]) {
  257. seq_printf(s, "|- %s: %4.4s => %4.4s\n", hva->encoders[i]->name,
  258. (char *)&hva->encoders[i]->pixelformat,
  259. (char *)&hva->encoders[i]->streamformat);
  260. i++;
  261. }
  262. return 0;
  263. }
  264. static int hva_dbg_last(struct seq_file *s, void *data)
  265. {
  266. struct hva_dev *hva = s->private;
  267. struct hva_ctx *last_ctx = &hva->dbg.last_ctx;
  268. if (last_ctx->flags & HVA_FLAG_STREAMINFO) {
  269. seq_puts(s, "[last encoding]\n");
  270. hva_dbg_perf_compute(last_ctx);
  271. format_ctx(s, last_ctx);
  272. } else {
  273. seq_puts(s, "[no information recorded about last encoding]\n");
  274. }
  275. return 0;
  276. }
  277. static int hva_dbg_regs(struct seq_file *s, void *data)
  278. {
  279. struct hva_dev *hva = s->private;
  280. hva_hw_dump_regs(hva, s);
  281. return 0;
  282. }
  283. #define hva_dbg_declare(name) \
  284. static int hva_dbg_##name##_open(struct inode *i, struct file *f) \
  285. { \
  286. return single_open(f, hva_dbg_##name, i->i_private); \
  287. } \
  288. static const struct file_operations hva_dbg_##name##_fops = { \
  289. .open = hva_dbg_##name##_open, \
  290. .read = seq_read, \
  291. .llseek = seq_lseek, \
  292. .release = single_release, \
  293. }
  294. #define hva_dbg_create_entry(name) \
  295. debugfs_create_file(#name, 0444, hva->dbg.debugfs_entry, hva, \
  296. &hva_dbg_##name##_fops)
  297. hva_dbg_declare(device);
  298. hva_dbg_declare(encoders);
  299. hva_dbg_declare(last);
  300. hva_dbg_declare(regs);
  301. void hva_debugfs_create(struct hva_dev *hva)
  302. {
  303. hva->dbg.debugfs_entry = debugfs_create_dir(HVA_NAME, NULL);
  304. if (!hva->dbg.debugfs_entry)
  305. goto err;
  306. if (!hva_dbg_create_entry(device))
  307. goto err;
  308. if (!hva_dbg_create_entry(encoders))
  309. goto err;
  310. if (!hva_dbg_create_entry(last))
  311. goto err;
  312. if (!hva_dbg_create_entry(regs))
  313. goto err;
  314. return;
  315. err:
  316. hva_debugfs_remove(hva);
  317. }
  318. void hva_debugfs_remove(struct hva_dev *hva)
  319. {
  320. debugfs_remove_recursive(hva->dbg.debugfs_entry);
  321. hva->dbg.debugfs_entry = NULL;
  322. }
  323. /*
  324. * context (instance) debug info
  325. */
  326. static int hva_dbg_ctx(struct seq_file *s, void *data)
  327. {
  328. struct hva_ctx *ctx = s->private;
  329. seq_printf(s, "[running encoding %d]\n", ctx->id);
  330. hva_dbg_perf_compute(ctx);
  331. format_ctx(s, ctx);
  332. return 0;
  333. }
  334. hva_dbg_declare(ctx);
  335. void hva_dbg_ctx_create(struct hva_ctx *ctx)
  336. {
  337. struct hva_dev *hva = ctx->hva_dev;
  338. char name[4] = "";
  339. ctx->dbg.min_duration = UINT_MAX;
  340. ctx->dbg.min_period = UINT_MAX;
  341. ctx->dbg.min_bitrate = UINT_MAX;
  342. snprintf(name, sizeof(name), "%d", hva->instance_id);
  343. ctx->dbg.debugfs_entry = debugfs_create_file(name, 0444,
  344. hva->dbg.debugfs_entry,
  345. ctx, &hva_dbg_ctx_fops);
  346. }
  347. void hva_dbg_ctx_remove(struct hva_ctx *ctx)
  348. {
  349. struct hva_dev *hva = ctx->hva_dev;
  350. if (ctx->flags & HVA_FLAG_STREAMINFO)
  351. /* save context before removing */
  352. memcpy(&hva->dbg.last_ctx, ctx, sizeof(*ctx));
  353. debugfs_remove(ctx->dbg.debugfs_entry);
  354. }