Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[cris-mirror.git] / drivers / media / platform / sti / hva / hva-debugfs.c
blob9f7e8ac875d16bd87a2101fb37f221e3e586317f
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) STMicroelectronics SA 2015
4 * Authors: Yannick Fertre <yannick.fertre@st.com>
5 * Hugues Fruchet <hugues.fruchet@st.com>
6 */
8 #include <linux/debugfs.h>
10 #include "hva.h"
11 #include "hva-hw.h"
13 static void format_ctx(struct seq_file *s, struct hva_ctx *ctx)
15 struct hva_streaminfo *stream = &ctx->streaminfo;
16 struct hva_frameinfo *frame = &ctx->frameinfo;
17 struct hva_controls *ctrls = &ctx->ctrls;
18 struct hva_ctx_dbg *dbg = &ctx->dbg;
19 u32 bitrate_mode, aspect, entropy, vui_sar, sei_fp;
21 seq_printf(s, "|-%s\n |\n", ctx->name);
23 seq_printf(s, " |-[%sframe info]\n",
24 ctx->flags & HVA_FLAG_FRAMEINFO ? "" : "default ");
25 seq_printf(s, " | |- pixel format=%4.4s\n"
26 " | |- wxh=%dx%d\n"
27 " | |- wxh (w/ encoder alignment constraint)=%dx%d\n"
28 " |\n",
29 (char *)&frame->pixelformat,
30 frame->width, frame->height,
31 frame->aligned_width, frame->aligned_height);
33 seq_printf(s, " |-[%sstream info]\n",
34 ctx->flags & HVA_FLAG_STREAMINFO ? "" : "default ");
35 seq_printf(s, " | |- stream format=%4.4s\n"
36 " | |- wxh=%dx%d\n"
37 " | |- %s\n"
38 " | |- %s\n"
39 " |\n",
40 (char *)&stream->streamformat,
41 stream->width, stream->height,
42 stream->profile, stream->level);
44 bitrate_mode = V4L2_CID_MPEG_VIDEO_BITRATE_MODE;
45 aspect = V4L2_CID_MPEG_VIDEO_ASPECT;
46 seq_puts(s, " |-[parameters]\n");
47 seq_printf(s, " | |- %s\n"
48 " | |- bitrate=%d bps\n"
49 " | |- GOP size=%d\n"
50 " | |- video aspect=%s\n"
51 " | |- framerate=%d/%d\n",
52 v4l2_ctrl_get_menu(bitrate_mode)[ctrls->bitrate_mode],
53 ctrls->bitrate,
54 ctrls->gop_size,
55 v4l2_ctrl_get_menu(aspect)[ctrls->aspect],
56 ctrls->time_per_frame.denominator,
57 ctrls->time_per_frame.numerator);
59 entropy = V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE;
60 vui_sar = V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC;
61 sei_fp = V4L2_CID_MPEG_VIDEO_H264_SEI_FP_ARRANGEMENT_TYPE;
62 if (stream->streamformat == V4L2_PIX_FMT_H264) {
63 seq_printf(s, " | |- %s entropy mode\n"
64 " | |- CPB size=%d kB\n"
65 " | |- DCT8x8 enable=%s\n"
66 " | |- qpmin=%d\n"
67 " | |- qpmax=%d\n"
68 " | |- PAR enable=%s\n"
69 " | |- PAR id=%s\n"
70 " | |- SEI frame packing enable=%s\n"
71 " | |- SEI frame packing type=%s\n",
72 v4l2_ctrl_get_menu(entropy)[ctrls->entropy_mode],
73 ctrls->cpb_size,
74 ctrls->dct8x8 ? "true" : "false",
75 ctrls->qpmin,
76 ctrls->qpmax,
77 ctrls->vui_sar ? "true" : "false",
78 v4l2_ctrl_get_menu(vui_sar)[ctrls->vui_sar_idc],
79 ctrls->sei_fp ? "true" : "false",
80 v4l2_ctrl_get_menu(sei_fp)[ctrls->sei_fp_type]);
83 if (ctx->sys_errors || ctx->encode_errors || ctx->frame_errors) {
84 seq_puts(s, " |\n |-[errors]\n");
85 seq_printf(s, " | |- system=%d\n"
86 " | |- encoding=%d\n"
87 " | |- frame=%d\n",
88 ctx->sys_errors,
89 ctx->encode_errors,
90 ctx->frame_errors);
93 seq_puts(s, " |\n |-[performances]\n");
94 seq_printf(s, " | |- frames encoded=%d\n"
95 " | |- avg HW processing duration (0.1ms)=%d [min=%d, max=%d]\n"
96 " | |- avg encoding period (0.1ms)=%d [min=%d, max=%d]\n"
97 " | |- avg fps (0.1Hz)=%d\n"
98 " | |- max reachable fps (0.1Hz)=%d\n"
99 " | |- avg bitrate (kbps)=%d [min=%d, max=%d]\n"
100 " | |- last bitrate (kbps)=%d\n",
101 dbg->cnt_duration,
102 dbg->avg_duration,
103 dbg->min_duration,
104 dbg->max_duration,
105 dbg->avg_period,
106 dbg->min_period,
107 dbg->max_period,
108 dbg->avg_fps,
109 dbg->max_fps,
110 dbg->avg_bitrate,
111 dbg->min_bitrate,
112 dbg->max_bitrate,
113 dbg->last_bitrate);
117 * performance debug info
119 void hva_dbg_perf_begin(struct hva_ctx *ctx)
121 u64 div;
122 u32 period;
123 u32 bitrate;
124 struct hva_ctx_dbg *dbg = &ctx->dbg;
125 ktime_t prev = dbg->begin;
127 dbg->begin = ktime_get();
129 if (dbg->is_valid_period) {
130 /* encoding period */
131 div = (u64)ktime_us_delta(dbg->begin, prev);
132 do_div(div, 100);
133 period = (u32)div;
134 dbg->min_period = min(period, dbg->min_period);
135 dbg->max_period = max(period, dbg->max_period);
136 dbg->total_period += period;
137 dbg->cnt_period++;
140 * minimum and maximum bitrates are based on the
141 * encoding period values upon a window of 32 samples
143 dbg->window_duration += period;
144 dbg->cnt_window++;
145 if (dbg->cnt_window >= 32) {
147 * bitrate in kbps = (size * 8 / 1000) /
148 * (duration / 10000)
149 * = size * 80 / duration
151 if (dbg->window_duration > 0) {
152 div = (u64)dbg->window_stream_size * 80;
153 do_div(div, dbg->window_duration);
154 bitrate = (u32)div;
155 dbg->last_bitrate = bitrate;
156 dbg->min_bitrate = min(bitrate,
157 dbg->min_bitrate);
158 dbg->max_bitrate = max(bitrate,
159 dbg->max_bitrate);
161 dbg->window_stream_size = 0;
162 dbg->window_duration = 0;
163 dbg->cnt_window = 0;
168 * filter sequences valid for performance:
169 * - begin/begin (no stream available) is an invalid sequence
170 * - begin/end is a valid sequence
172 dbg->is_valid_period = false;
175 void hva_dbg_perf_end(struct hva_ctx *ctx, struct hva_stream *stream)
177 struct device *dev = ctx_to_dev(ctx);
178 u64 div;
179 u32 duration;
180 u32 bytesused;
181 u32 timestamp;
182 struct hva_ctx_dbg *dbg = &ctx->dbg;
183 ktime_t end = ktime_get();
185 /* stream bytesused and timestamp in us */
186 bytesused = vb2_get_plane_payload(&stream->vbuf.vb2_buf, 0);
187 div = stream->vbuf.vb2_buf.timestamp;
188 do_div(div, 1000);
189 timestamp = (u32)div;
191 /* encoding duration */
192 div = (u64)ktime_us_delta(end, dbg->begin);
194 dev_dbg(dev,
195 "%s perf stream[%d] dts=%d encoded using %d bytes in %d us",
196 ctx->name,
197 stream->vbuf.sequence,
198 timestamp,
199 bytesused, (u32)div);
201 do_div(div, 100);
202 duration = (u32)div;
204 dbg->min_duration = min(duration, dbg->min_duration);
205 dbg->max_duration = max(duration, dbg->max_duration);
206 dbg->total_duration += duration;
207 dbg->cnt_duration++;
210 * the average bitrate is based on the total stream size
211 * and the total encoding periods
213 dbg->total_stream_size += bytesused;
214 dbg->window_stream_size += bytesused;
216 dbg->is_valid_period = true;
219 static void hva_dbg_perf_compute(struct hva_ctx *ctx)
221 u64 div;
222 struct hva_ctx_dbg *dbg = &ctx->dbg;
224 if (dbg->cnt_duration > 0) {
225 div = (u64)dbg->total_duration;
226 do_div(div, dbg->cnt_duration);
227 dbg->avg_duration = (u32)div;
228 } else {
229 dbg->avg_duration = 0;
232 if (dbg->total_duration > 0) {
233 div = (u64)dbg->cnt_duration * 100000;
234 do_div(div, dbg->total_duration);
235 dbg->max_fps = (u32)div;
236 } else {
237 dbg->max_fps = 0;
240 if (dbg->cnt_period > 0) {
241 div = (u64)dbg->total_period;
242 do_div(div, dbg->cnt_period);
243 dbg->avg_period = (u32)div;
244 } else {
245 dbg->avg_period = 0;
248 if (dbg->total_period > 0) {
249 div = (u64)dbg->cnt_period * 100000;
250 do_div(div, dbg->total_period);
251 dbg->avg_fps = (u32)div;
252 } else {
253 dbg->avg_fps = 0;
256 if (dbg->total_period > 0) {
258 * bitrate in kbps = (video size * 8 / 1000) /
259 * (video duration / 10000)
260 * = video size * 80 / video duration
262 div = (u64)dbg->total_stream_size * 80;
263 do_div(div, dbg->total_period);
264 dbg->avg_bitrate = (u32)div;
265 } else {
266 dbg->avg_bitrate = 0;
271 * device debug info
274 static int hva_dbg_device(struct seq_file *s, void *data)
276 struct hva_dev *hva = s->private;
278 seq_printf(s, "[%s]\n", hva->v4l2_dev.name);
279 seq_printf(s, "registered as /dev/video%d\n", hva->vdev->num);
281 return 0;
284 static int hva_dbg_encoders(struct seq_file *s, void *data)
286 struct hva_dev *hva = s->private;
287 unsigned int i = 0;
289 seq_printf(s, "[encoders]\n|- %d registered encoders:\n",
290 hva->nb_of_encoders);
292 while (hva->encoders[i]) {
293 seq_printf(s, "|- %s: %4.4s => %4.4s\n", hva->encoders[i]->name,
294 (char *)&hva->encoders[i]->pixelformat,
295 (char *)&hva->encoders[i]->streamformat);
296 i++;
299 return 0;
302 static int hva_dbg_last(struct seq_file *s, void *data)
304 struct hva_dev *hva = s->private;
305 struct hva_ctx *last_ctx = &hva->dbg.last_ctx;
307 if (last_ctx->flags & HVA_FLAG_STREAMINFO) {
308 seq_puts(s, "[last encoding]\n");
310 hva_dbg_perf_compute(last_ctx);
311 format_ctx(s, last_ctx);
312 } else {
313 seq_puts(s, "[no information recorded about last encoding]\n");
316 return 0;
319 static int hva_dbg_regs(struct seq_file *s, void *data)
321 struct hva_dev *hva = s->private;
323 hva_hw_dump_regs(hva, s);
325 return 0;
328 #define hva_dbg_declare(name) \
329 static int hva_dbg_##name##_open(struct inode *i, struct file *f) \
331 return single_open(f, hva_dbg_##name, i->i_private); \
333 static const struct file_operations hva_dbg_##name##_fops = { \
334 .open = hva_dbg_##name##_open, \
335 .read = seq_read, \
336 .llseek = seq_lseek, \
337 .release = single_release, \
340 #define hva_dbg_create_entry(name) \
341 debugfs_create_file(#name, 0444, hva->dbg.debugfs_entry, hva, \
342 &hva_dbg_##name##_fops)
344 hva_dbg_declare(device);
345 hva_dbg_declare(encoders);
346 hva_dbg_declare(last);
347 hva_dbg_declare(regs);
349 void hva_debugfs_create(struct hva_dev *hva)
351 hva->dbg.debugfs_entry = debugfs_create_dir(HVA_NAME, NULL);
352 if (!hva->dbg.debugfs_entry)
353 goto err;
355 if (!hva_dbg_create_entry(device))
356 goto err;
358 if (!hva_dbg_create_entry(encoders))
359 goto err;
361 if (!hva_dbg_create_entry(last))
362 goto err;
364 if (!hva_dbg_create_entry(regs))
365 goto err;
367 return;
369 err:
370 hva_debugfs_remove(hva);
373 void hva_debugfs_remove(struct hva_dev *hva)
375 debugfs_remove_recursive(hva->dbg.debugfs_entry);
376 hva->dbg.debugfs_entry = NULL;
380 * context (instance) debug info
383 static int hva_dbg_ctx(struct seq_file *s, void *data)
385 struct hva_ctx *ctx = s->private;
387 seq_printf(s, "[running encoding %d]\n", ctx->id);
389 hva_dbg_perf_compute(ctx);
390 format_ctx(s, ctx);
392 return 0;
395 hva_dbg_declare(ctx);
397 void hva_dbg_ctx_create(struct hva_ctx *ctx)
399 struct hva_dev *hva = ctx->hva_dev;
400 char name[4] = "";
402 ctx->dbg.min_duration = UINT_MAX;
403 ctx->dbg.min_period = UINT_MAX;
404 ctx->dbg.min_bitrate = UINT_MAX;
406 snprintf(name, sizeof(name), "%d", hva->instance_id);
408 ctx->dbg.debugfs_entry = debugfs_create_file(name, 0444,
409 hva->dbg.debugfs_entry,
410 ctx, &hva_dbg_ctx_fops);
413 void hva_dbg_ctx_remove(struct hva_ctx *ctx)
415 struct hva_dev *hva = ctx->hva_dev;
417 if (ctx->flags & HVA_FLAG_STREAMINFO)
418 /* save context before removing */
419 memcpy(&hva->dbg.last_ctx, ctx, sizeof(*ctx));
421 debugfs_remove(ctx->dbg.debugfs_entry);