GNU Linux-libre 4.14.266-gnu1
[releases.git] / drivers / media / platform / sti / hva / hva-debugfs.c
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
8 #include <linux/debugfs.h>
9
10 #include "hva.h"
11 #include "hva-hw.h"
12
13 static void format_ctx(struct seq_file *s, struct hva_ctx *ctx)
14 {
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;
20
21         seq_printf(s, "|-%s\n  |\n", ctx->name);
22
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);
32
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);
43
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);
58
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]);
81         }
82
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);
91         }
92
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);
114 }
115
116 /*
117  * performance debug info
118  */
119 void hva_dbg_perf_begin(struct hva_ctx *ctx)
120 {
121         u64 div;
122         u32 period;
123         u32 bitrate;
124         struct hva_ctx_dbg *dbg = &ctx->dbg;
125         ktime_t prev = dbg->begin;
126
127         dbg->begin = ktime_get();
128
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++;
138
139                 /*
140                  * minimum and maximum bitrates are based on the
141                  * encoding period values upon a window of 32 samples
142                  */
143                 dbg->window_duration += period;
144                 dbg->cnt_window++;
145                 if (dbg->cnt_window >= 32) {
146                         /*
147                          * bitrate in kbps = (size * 8 / 1000) /
148                          *                   (duration / 10000)
149                          *                 = size * 80 / duration
150                          */
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);
160                         }
161                         dbg->window_stream_size = 0;
162                         dbg->window_duration = 0;
163                         dbg->cnt_window = 0;
164                 }
165         }
166
167         /*
168          * filter sequences valid for performance:
169          * - begin/begin (no stream available) is an invalid sequence
170          * - begin/end is a valid sequence
171          */
172         dbg->is_valid_period = false;
173 }
174
175 void hva_dbg_perf_end(struct hva_ctx *ctx, struct hva_stream *stream)
176 {
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();
184
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;
190
191         /* encoding duration */
192         div = (u64)ktime_us_delta(end, dbg->begin);
193
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);
200
201         do_div(div, 100);
202         duration = (u32)div;
203
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++;
208
209         /*
210          * the average bitrate is based on the total stream size
211          * and the total encoding periods
212          */
213         dbg->total_stream_size += bytesused;
214         dbg->window_stream_size += bytesused;
215
216         dbg->is_valid_period = true;
217 }
218
219 static void hva_dbg_perf_compute(struct hva_ctx *ctx)
220 {
221         u64 div;
222         struct hva_ctx_dbg *dbg = &ctx->dbg;
223
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;
230         }
231
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;
238         }
239
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;
246         }
247
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;
254         }
255
256         if (dbg->total_period > 0) {
257                 /*
258                  * bitrate in kbps = (video size * 8 / 1000) /
259                  *                   (video duration / 10000)
260                  *                 = video size * 80 / video duration
261                  */
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;
267         }
268 }
269
270 /*
271  * device debug info
272  */
273
274 static int hva_dbg_device(struct seq_file *s, void *data)
275 {
276         struct hva_dev *hva = s->private;
277
278         seq_printf(s, "[%s]\n", hva->v4l2_dev.name);
279         seq_printf(s, "registered as /dev/video%d\n", hva->vdev->num);
280
281         return 0;
282 }
283
284 static int hva_dbg_encoders(struct seq_file *s, void *data)
285 {
286         struct hva_dev *hva = s->private;
287         unsigned int i = 0;
288
289         seq_printf(s, "[encoders]\n|- %d registered encoders:\n",
290                    hva->nb_of_encoders);
291
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++;
297         }
298
299         return 0;
300 }
301
302 static int hva_dbg_last(struct seq_file *s, void *data)
303 {
304         struct hva_dev *hva = s->private;
305         struct hva_ctx *last_ctx = &hva->dbg.last_ctx;
306
307         if (last_ctx->flags & HVA_FLAG_STREAMINFO) {
308                 seq_puts(s, "[last encoding]\n");
309
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");
314         }
315
316         return 0;
317 }
318
319 static int hva_dbg_regs(struct seq_file *s, void *data)
320 {
321         struct hva_dev *hva = s->private;
322
323         hva_hw_dump_regs(hva, s);
324
325         return 0;
326 }
327
328 #define hva_dbg_declare(name)                                             \
329         static int hva_dbg_##name##_open(struct inode *i, struct file *f) \
330         {                                                                 \
331                 return single_open(f, hva_dbg_##name, i->i_private);      \
332         }                                                                 \
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,                         \
338         }
339
340 #define hva_dbg_create_entry(name)                                       \
341         debugfs_create_file(#name, 0444, hva->dbg.debugfs_entry, hva, \
342                             &hva_dbg_##name##_fops)
343
344 hva_dbg_declare(device);
345 hva_dbg_declare(encoders);
346 hva_dbg_declare(last);
347 hva_dbg_declare(regs);
348
349 void hva_debugfs_create(struct hva_dev *hva)
350 {
351         hva->dbg.debugfs_entry = debugfs_create_dir(HVA_NAME, NULL);
352         if (!hva->dbg.debugfs_entry)
353                 goto err;
354
355         if (!hva_dbg_create_entry(device))
356                 goto err;
357
358         if (!hva_dbg_create_entry(encoders))
359                 goto err;
360
361         if (!hva_dbg_create_entry(last))
362                 goto err;
363
364         if (!hva_dbg_create_entry(regs))
365                 goto err;
366
367         return;
368
369 err:
370         hva_debugfs_remove(hva);
371 }
372
373 void hva_debugfs_remove(struct hva_dev *hva)
374 {
375         debugfs_remove_recursive(hva->dbg.debugfs_entry);
376         hva->dbg.debugfs_entry = NULL;
377 }
378
379 /*
380  * context (instance) debug info
381  */
382
383 static int hva_dbg_ctx(struct seq_file *s, void *data)
384 {
385         struct hva_ctx *ctx = s->private;
386
387         seq_printf(s, "[running encoding %d]\n", ctx->id);
388
389         hva_dbg_perf_compute(ctx);
390         format_ctx(s, ctx);
391
392         return 0;
393 }
394
395 hva_dbg_declare(ctx);
396
397 void hva_dbg_ctx_create(struct hva_ctx *ctx)
398 {
399         struct hva_dev *hva = ctx->hva_dev;
400         char name[4] = "";
401
402         ctx->dbg.min_duration = UINT_MAX;
403         ctx->dbg.min_period = UINT_MAX;
404         ctx->dbg.min_bitrate = UINT_MAX;
405
406         snprintf(name, sizeof(name), "%d", hva->instance_id);
407
408         ctx->dbg.debugfs_entry = debugfs_create_file(name, 0444,
409                                                      hva->dbg.debugfs_entry,
410                                                      ctx, &hva_dbg_ctx_fops);
411 }
412
413 void hva_dbg_ctx_remove(struct hva_ctx *ctx)
414 {
415         struct hva_dev *hva = ctx->hva_dev;
416
417         if (ctx->flags & HVA_FLAG_STREAMINFO)
418                 /* save context before removing */
419                 memcpy(&hva->dbg.last_ctx, ctx, sizeof(*ctx));
420
421         debugfs_remove(ctx->dbg.debugfs_entry);
422 }