1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) STMicroelectronics SA 2014
4 * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics.
7 #include <linux/debugfs.h>
8 #include <linux/pm_runtime.h>
11 #include "bdisp-filter.h"
12 #include "bdisp-reg.h"
14 void bdisp_dbg_perf_begin(struct bdisp_dev
*bdisp
)
16 bdisp
->dbg
.hw_start
= ktime_get();
19 void bdisp_dbg_perf_end(struct bdisp_dev
*bdisp
)
23 time_us
= ktime_us_delta(ktime_get(), bdisp
->dbg
.hw_start
);
25 if (!bdisp
->dbg
.min_duration
)
26 bdisp
->dbg
.min_duration
= time_us
;
28 bdisp
->dbg
.min_duration
= min(time_us
, bdisp
->dbg
.min_duration
);
30 bdisp
->dbg
.last_duration
= time_us
;
31 bdisp
->dbg
.max_duration
= max(time_us
, bdisp
->dbg
.max_duration
);
32 bdisp
->dbg
.tot_duration
+= time_us
;
35 static void bdisp_dbg_dump_ins(struct seq_file
*s
, u32 val
)
37 seq_printf(s
, "INS\t0x%08X\t", val
);
39 switch (val
& BLT_INS_S1_MASK
) {
43 seq_puts(s
, "SRC1=mem - ");
46 seq_puts(s
, "SRC1=ColorFill - ");
49 seq_puts(s
, "SRC1=copy - ");
52 seq_puts(s
, "SRC1=fil - ");
55 seq_puts(s
, "SRC1=??? - ");
59 switch (val
& BLT_INS_S2_MASK
) {
63 seq_puts(s
, "SRC2=mem - ");
66 seq_puts(s
, "SRC2=ColorFill - ");
69 seq_puts(s
, "SRC2=??? - ");
73 if ((val
& BLT_INS_S3_MASK
) == BLT_INS_S3_MEM
)
74 seq_puts(s
, "SRC3=mem - ");
76 if (val
& BLT_INS_IVMX
)
77 seq_puts(s
, "IVMX - ");
78 if (val
& BLT_INS_CLUT
)
79 seq_puts(s
, "CLUT - ");
80 if (val
& BLT_INS_SCALE
)
81 seq_puts(s
, "Scale - ");
82 if (val
& BLT_INS_FLICK
)
83 seq_puts(s
, "Flicker - ");
84 if (val
& BLT_INS_CLIP
)
85 seq_puts(s
, "Clip - ");
86 if (val
& BLT_INS_CKEY
)
87 seq_puts(s
, "ColorKey - ");
88 if (val
& BLT_INS_OVMX
)
89 seq_puts(s
, "OVMX - ");
90 if (val
& BLT_INS_DEI
)
91 seq_puts(s
, "Deint - ");
92 if (val
& BLT_INS_PMASK
)
93 seq_puts(s
, "PlaneMask - ");
94 if (val
& BLT_INS_VC1R
)
95 seq_puts(s
, "VC1R - ");
96 if (val
& BLT_INS_ROTATE
)
97 seq_puts(s
, "Rotate - ");
98 if (val
& BLT_INS_GRAD
)
99 seq_puts(s
, "GradFill - ");
100 if (val
& BLT_INS_AQLOCK
)
101 seq_puts(s
, "AQLock - ");
102 if (val
& BLT_INS_PACE
)
103 seq_puts(s
, "Pace - ");
104 if (val
& BLT_INS_IRQ
)
105 seq_puts(s
, "IRQ - ");
110 static void bdisp_dbg_dump_tty(struct seq_file
*s
, u32 val
)
112 seq_printf(s
, "TTY\t0x%08X\t", val
);
113 seq_printf(s
, "Pitch=%d - ", val
& 0xFFFF);
115 switch ((val
& BLT_TTY_COL_MASK
) >> BLT_TTY_COL_SHIFT
) {
117 seq_puts(s
, "RGB565 - ");
120 seq_puts(s
, "RGB888 - ");
123 seq_puts(s
, "xRGB888 - ");
126 seq_puts(s
, "ARGB8888 - ");
129 seq_puts(s
, "NV12 - ");
132 seq_puts(s
, "YUV420P - ");
135 seq_puts(s
, "ColorFormat ??? - ");
139 if (val
& BLT_TTY_ALPHA_R
)
140 seq_puts(s
, "AlphaRange - ");
141 if (val
& BLT_TTY_CR_NOT_CB
)
142 seq_puts(s
, "CrNotCb - ");
143 if (val
& BLT_TTY_MB
)
144 seq_puts(s
, "MB - ");
145 if (val
& BLT_TTY_HSO
)
146 seq_puts(s
, "HSO inverse - ");
147 if (val
& BLT_TTY_VSO
)
148 seq_puts(s
, "VSO inverse - ");
149 if (val
& BLT_TTY_DITHER
)
150 seq_puts(s
, "Dither - ");
151 if (val
& BLT_TTY_CHROMA
)
152 seq_puts(s
, "Write CHROMA - ");
153 if (val
& BLT_TTY_BIG_END
)
154 seq_puts(s
, "BigEndian - ");
159 static void bdisp_dbg_dump_xy(struct seq_file
*s
, u32 val
, char *name
)
161 seq_printf(s
, "%s\t0x%08X\t", name
, val
);
162 seq_printf(s
, "(%d,%d)\n", val
& 0xFFFF, (val
>> 16));
165 static void bdisp_dbg_dump_sz(struct seq_file
*s
, u32 val
, char *name
)
167 seq_printf(s
, "%s\t0x%08X\t", name
, val
);
168 seq_printf(s
, "%dx%d\n", val
& 0x1FFF, (val
>> 16) & 0x1FFF);
171 static void bdisp_dbg_dump_sty(struct seq_file
*s
,
172 u32 val
, u32 addr
, char *name
)
176 seq_printf(s
, "%s\t0x%08X\t", name
, val
);
178 if (!addr
|| !name
|| (strlen(name
) < 2))
181 s1
= name
[strlen(name
) - 1] == '1';
182 s2
= name
[strlen(name
) - 1] == '2';
183 s3
= name
[strlen(name
) - 1] == '3';
185 seq_printf(s
, "Pitch=%d - ", val
& 0xFFFF);
187 switch ((val
& BLT_TTY_COL_MASK
) >> BLT_TTY_COL_SHIFT
) {
189 seq_puts(s
, "RGB565 - ");
192 seq_puts(s
, "RGB888 - ");
195 seq_puts(s
, "xRGB888 - ");
198 seq_puts(s
, "ARGB888 - ");
201 seq_puts(s
, "NV12 - ");
204 seq_puts(s
, "YUV420P - ");
207 seq_puts(s
, "ColorFormat ??? - ");
211 if ((val
& BLT_TTY_ALPHA_R
) && !s3
)
212 seq_puts(s
, "AlphaRange - ");
213 if ((val
& BLT_S1TY_A1_SUBSET
) && !s3
)
214 seq_puts(s
, "A1SubSet - ");
215 if ((val
& BLT_TTY_MB
) && !s1
)
216 seq_puts(s
, "MB - ");
217 if (val
& BLT_TTY_HSO
)
218 seq_puts(s
, "HSO inverse - ");
219 if (val
& BLT_TTY_VSO
)
220 seq_puts(s
, "VSO inverse - ");
221 if ((val
& BLT_S1TY_CHROMA_EXT
) && (s1
|| s2
))
222 seq_puts(s
, "ChromaExt - ");
223 if ((val
& BLT_S3TY_BLANK_ACC
) && s3
)
224 seq_puts(s
, "Blank Acc - ");
225 if ((val
& BTL_S1TY_SUBBYTE
) && !s3
)
226 seq_puts(s
, "SubByte - ");
227 if ((val
& BLT_S1TY_RGB_EXP
) && !s3
)
228 seq_puts(s
, "RGBExpand - ");
229 if ((val
& BLT_TTY_BIG_END
) && !s3
)
230 seq_puts(s
, "BigEndian - ");
236 static void bdisp_dbg_dump_fctl(struct seq_file
*s
, u32 val
)
238 seq_printf(s
, "FCTL\t0x%08X\t", val
);
240 if ((val
& BLT_FCTL_Y_HV_SCALE
) == BLT_FCTL_Y_HV_SCALE
)
241 seq_puts(s
, "Resize Luma - ");
242 else if ((val
& BLT_FCTL_Y_HV_SCALE
) == BLT_FCTL_Y_HV_SAMPLE
)
243 seq_puts(s
, "Sample Luma - ");
245 if ((val
& BLT_FCTL_HV_SCALE
) == BLT_FCTL_HV_SCALE
)
246 seq_puts(s
, "Resize Chroma");
247 else if ((val
& BLT_FCTL_HV_SCALE
) == BLT_FCTL_HV_SAMPLE
)
248 seq_puts(s
, "Sample Chroma");
253 static void bdisp_dbg_dump_rsf(struct seq_file
*s
, u32 val
, char *name
)
257 seq_printf(s
, "%s\t0x%08X\t", name
, val
);
263 seq_printf(s
, "H: %d(6.10) / scale~%dx0.1 - ", inc
, 1024 * 10 / inc
);
266 seq_printf(s
, "V: %d(6.10) / scale~%dx0.1", inc
, 1024 * 10 / inc
);
272 static void bdisp_dbg_dump_rzi(struct seq_file
*s
, u32 val
, char *name
)
274 seq_printf(s
, "%s\t0x%08X\t", name
, val
);
279 seq_printf(s
, "H: init=%d repeat=%d - ", val
& 0x3FF, (val
>> 12) & 7);
281 seq_printf(s
, "V: init=%d repeat=%d", val
& 0x3FF, (val
>> 12) & 7);
287 static void bdisp_dbg_dump_ivmx(struct seq_file
*s
,
288 u32 c0
, u32 c1
, u32 c2
, u32 c3
)
290 seq_printf(s
, "IVMX0\t0x%08X\n", c0
);
291 seq_printf(s
, "IVMX1\t0x%08X\n", c1
);
292 seq_printf(s
, "IVMX2\t0x%08X\n", c2
);
293 seq_printf(s
, "IVMX3\t0x%08X\t", c3
);
295 if (!c0
&& !c1
&& !c2
&& !c3
) {
300 if ((c0
== bdisp_rgb_to_yuv
[0]) &&
301 (c1
== bdisp_rgb_to_yuv
[1]) &&
302 (c2
== bdisp_rgb_to_yuv
[2]) &&
303 (c3
== bdisp_rgb_to_yuv
[3])) {
304 seq_puts(s
, "RGB to YUV\n");
308 if ((c0
== bdisp_yuv_to_rgb
[0]) &&
309 (c1
== bdisp_yuv_to_rgb
[1]) &&
310 (c2
== bdisp_yuv_to_rgb
[2]) &&
311 (c3
== bdisp_yuv_to_rgb
[3])) {
312 seq_puts(s
, "YUV to RGB\n");
315 seq_puts(s
, "Unknown conversion\n");
318 static int bdisp_dbg_last_nodes(struct seq_file
*s
, void *data
)
320 /* Not dumping all fields, focusing on significant ones */
321 struct bdisp_dev
*bdisp
= s
->private;
322 struct bdisp_node
*node
;
325 if (!bdisp
->dbg
.copy_node
[0]) {
326 seq_puts(s
, "No node built yet\n");
331 node
= bdisp
->dbg
.copy_node
[i
];
334 seq_printf(s
, "--------\nNode %d:\n", i
);
335 seq_puts(s
, "-- General --\n");
336 seq_printf(s
, "NIP\t0x%08X\n", node
->nip
);
337 seq_printf(s
, "CIC\t0x%08X\n", node
->cic
);
338 bdisp_dbg_dump_ins(s
, node
->ins
);
339 seq_printf(s
, "ACK\t0x%08X\n", node
->ack
);
340 seq_puts(s
, "-- Target --\n");
341 seq_printf(s
, "TBA\t0x%08X\n", node
->tba
);
342 bdisp_dbg_dump_tty(s
, node
->tty
);
343 bdisp_dbg_dump_xy(s
, node
->txy
, "TXY");
344 bdisp_dbg_dump_sz(s
, node
->tsz
, "TSZ");
345 /* Color Fill not dumped */
346 seq_puts(s
, "-- Source 1 --\n");
347 seq_printf(s
, "S1BA\t0x%08X\n", node
->s1ba
);
348 bdisp_dbg_dump_sty(s
, node
->s1ty
, node
->s1ba
, "S1TY");
349 bdisp_dbg_dump_xy(s
, node
->s1xy
, "S1XY");
350 seq_puts(s
, "-- Source 2 --\n");
351 seq_printf(s
, "S2BA\t0x%08X\n", node
->s2ba
);
352 bdisp_dbg_dump_sty(s
, node
->s2ty
, node
->s2ba
, "S2TY");
353 bdisp_dbg_dump_xy(s
, node
->s2xy
, "S2XY");
354 bdisp_dbg_dump_sz(s
, node
->s2sz
, "S2SZ");
355 seq_puts(s
, "-- Source 3 --\n");
356 seq_printf(s
, "S3BA\t0x%08X\n", node
->s3ba
);
357 bdisp_dbg_dump_sty(s
, node
->s3ty
, node
->s3ba
, "S3TY");
358 bdisp_dbg_dump_xy(s
, node
->s3xy
, "S3XY");
359 bdisp_dbg_dump_sz(s
, node
->s3sz
, "S3SZ");
360 /* Clipping not dumped */
361 /* CLUT not dumped */
362 seq_puts(s
, "-- Filter & Mask --\n");
363 bdisp_dbg_dump_fctl(s
, node
->fctl
);
365 seq_puts(s
, "-- Chroma Filter --\n");
366 bdisp_dbg_dump_rsf(s
, node
->rsf
, "RSF");
367 bdisp_dbg_dump_rzi(s
, node
->rzi
, "RZI");
368 seq_printf(s
, "HFP\t0x%08X\n", node
->hfp
);
369 seq_printf(s
, "VFP\t0x%08X\n", node
->vfp
);
370 seq_puts(s
, "-- Luma Filter --\n");
371 bdisp_dbg_dump_rsf(s
, node
->y_rsf
, "Y_RSF");
372 bdisp_dbg_dump_rzi(s
, node
->y_rzi
, "Y_RZI");
373 seq_printf(s
, "Y_HFP\t0x%08X\n", node
->y_hfp
);
374 seq_printf(s
, "Y_VFP\t0x%08X\n", node
->y_vfp
);
375 /* Flicker not dumped */
376 /* Color key not dumped */
377 /* Reserved not dumped */
378 /* Static Address & User not dumped */
379 seq_puts(s
, "-- Input Versatile Matrix --\n");
380 bdisp_dbg_dump_ivmx(s
, node
->ivmx0
, node
->ivmx1
,
381 node
->ivmx2
, node
->ivmx3
);
382 /* Output Versatile Matrix not dumped */
383 /* Pace not dumped */
384 /* VC1R & DEI not dumped */
385 /* Gradient Fill not dumped */
386 } while ((++i
< MAX_NB_NODE
) && node
->nip
);
391 static int bdisp_dbg_last_nodes_raw(struct seq_file
*s
, void *data
)
393 struct bdisp_dev
*bdisp
= s
->private;
394 struct bdisp_node
*node
;
398 if (!bdisp
->dbg
.copy_node
[0]) {
399 seq_puts(s
, "No node built yet\n");
404 node
= bdisp
->dbg
.copy_node
[i
];
408 seq_printf(s
, "--------\nNode %d:\n", i
);
410 for (j
= 0; j
< sizeof(struct bdisp_node
) / sizeof(u32
); j
++)
411 seq_printf(s
, "0x%08X\n", *val
++);
412 } while ((++i
< MAX_NB_NODE
) && node
->nip
);
417 static const char *bdisp_fmt_to_str(struct bdisp_frame frame
)
419 switch (frame
.fmt
->pixelformat
) {
420 case V4L2_PIX_FMT_YUV420
:
422 case V4L2_PIX_FMT_NV12
:
423 if (frame
.field
== V4L2_FIELD_INTERLACED
)
424 return "NV12 interlaced";
427 case V4L2_PIX_FMT_RGB565
:
429 case V4L2_PIX_FMT_RGB24
:
431 case V4L2_PIX_FMT_XBGR32
:
433 case V4L2_PIX_FMT_ABGR32
:
440 static int bdisp_dbg_last_request(struct seq_file
*s
, void *data
)
442 struct bdisp_dev
*bdisp
= s
->private;
443 struct bdisp_request
*request
= &bdisp
->dbg
.copy_request
;
444 struct bdisp_frame src
, dst
;
446 if (!request
->nb_req
) {
447 seq_puts(s
, "No request\n");
454 seq_printf(s
, "\nRequest #%d\n", request
->nb_req
);
456 seq_printf(s
, "Format: %s\t\t\t%s\n",
457 bdisp_fmt_to_str(src
), bdisp_fmt_to_str(dst
));
458 seq_printf(s
, "Crop area: %dx%d @ %d,%d ==>\t%dx%d @ %d,%d\n",
459 src
.crop
.width
, src
.crop
.height
,
460 src
.crop
.left
, src
.crop
.top
,
461 dst
.crop
.width
, dst
.crop
.height
,
462 dst
.crop
.left
, dst
.crop
.top
);
463 seq_printf(s
, "Buff size: %dx%d\t\t%dx%d\n\n",
464 src
.width
, src
.height
, dst
.width
, dst
.height
);
467 seq_puts(s
, "Horizontal flip\n\n");
470 seq_puts(s
, "Vertical flip\n\n");
475 #define DUMP(reg) seq_printf(s, #reg " \t0x%08X\n", readl(bdisp->regs + reg))
477 static int bdisp_dbg_regs(struct seq_file
*s
, void *data
)
479 struct bdisp_dev
*bdisp
= s
->private;
483 ret
= pm_runtime_get_sync(bdisp
->dev
);
485 seq_puts(s
, "Cannot wake up IP\n");
489 seq_printf(s
, "Reg @ = 0x%p\n", bdisp
->regs
);
491 seq_puts(s
, "\nStatic:\n");
501 seq_puts(s
, "\nPlugs:\n");
502 DUMP(BLT_PLUGS1_OP2
);
503 DUMP(BLT_PLUGS1_CHZ
);
504 DUMP(BLT_PLUGS1_MSZ
);
505 DUMP(BLT_PLUGS1_PGZ
);
506 DUMP(BLT_PLUGS2_OP2
);
507 DUMP(BLT_PLUGS2_CHZ
);
508 DUMP(BLT_PLUGS2_MSZ
);
509 DUMP(BLT_PLUGS2_PGZ
);
510 DUMP(BLT_PLUGS3_OP2
);
511 DUMP(BLT_PLUGS3_CHZ
);
512 DUMP(BLT_PLUGS3_MSZ
);
513 DUMP(BLT_PLUGS3_PGZ
);
519 seq_puts(s
, "\nNode:\n");
558 seq_puts(s
, "\nFilter:\n");
559 for (i
= 0; i
< BLT_NB_H_COEF
; i
++) {
560 seq_printf(s
, "BLT_HFC%d \t0x%08X\n", i
,
561 readl(bdisp
->regs
+ BLT_HFC_N
+ i
* 4));
563 for (i
= 0; i
< BLT_NB_V_COEF
; i
++) {
564 seq_printf(s
, "BLT_VFC%d \t0x%08X\n", i
,
565 readl(bdisp
->regs
+ BLT_VFC_N
+ i
* 4));
568 seq_puts(s
, "\nLuma filter:\n");
569 for (i
= 0; i
< BLT_NB_H_COEF
; i
++) {
570 seq_printf(s
, "BLT_Y_HFC%d \t0x%08X\n", i
,
571 readl(bdisp
->regs
+ BLT_Y_HFC_N
+ i
* 4));
573 for (i
= 0; i
< BLT_NB_V_COEF
; i
++) {
574 seq_printf(s
, "BLT_Y_VFC%d \t0x%08X\n", i
,
575 readl(bdisp
->regs
+ BLT_Y_VFC_N
+ i
* 4));
578 pm_runtime_put(bdisp
->dev
);
583 #define SECOND 1000000
585 static int bdisp_dbg_perf(struct seq_file
*s
, void *data
)
587 struct bdisp_dev
*bdisp
= s
->private;
588 struct bdisp_request
*request
= &bdisp
->dbg
.copy_request
;
590 int avg_fps
, min_fps
, max_fps
, last_fps
;
592 if (!request
->nb_req
) {
593 seq_puts(s
, "No request\n");
597 avg_time_us
= div64_s64(bdisp
->dbg
.tot_duration
, request
->nb_req
);
598 if (avg_time_us
> SECOND
)
601 avg_fps
= SECOND
/ (s32
)avg_time_us
;
603 if (bdisp
->dbg
.min_duration
> SECOND
)
606 min_fps
= SECOND
/ (s32
)bdisp
->dbg
.min_duration
;
608 if (bdisp
->dbg
.max_duration
> SECOND
)
611 max_fps
= SECOND
/ (s32
)bdisp
->dbg
.max_duration
;
613 if (bdisp
->dbg
.last_duration
> SECOND
)
616 last_fps
= SECOND
/ (s32
)bdisp
->dbg
.last_duration
;
618 seq_printf(s
, "HW processing (%d requests):\n", request
->nb_req
);
619 seq_printf(s
, " Average: %5lld us (%3d fps)\n",
620 avg_time_us
, avg_fps
);
621 seq_printf(s
, " Min-Max: %5lld us (%3d fps) - %5lld us (%3d fps)\n",
622 bdisp
->dbg
.min_duration
, min_fps
,
623 bdisp
->dbg
.max_duration
, max_fps
);
624 seq_printf(s
, " Last: %5lld us (%3d fps)\n",
625 bdisp
->dbg
.last_duration
, last_fps
);
630 #define bdisp_dbg_declare(name) \
631 static int bdisp_dbg_##name##_open(struct inode *i, struct file *f) \
633 return single_open(f, bdisp_dbg_##name, i->i_private); \
635 static const struct file_operations bdisp_dbg_##name##_fops = { \
636 .open = bdisp_dbg_##name##_open, \
638 .llseek = seq_lseek, \
639 .release = single_release, \
642 #define bdisp_dbg_create_entry(name) \
643 debugfs_create_file(#name, S_IRUGO, bdisp->dbg.debugfs_entry, bdisp, \
644 &bdisp_dbg_##name##_fops)
646 bdisp_dbg_declare(regs
);
647 bdisp_dbg_declare(last_nodes
);
648 bdisp_dbg_declare(last_nodes_raw
);
649 bdisp_dbg_declare(last_request
);
650 bdisp_dbg_declare(perf
);
652 int bdisp_debugfs_create(struct bdisp_dev
*bdisp
)
656 snprintf(dirname
, sizeof(dirname
), "%s%d", BDISP_NAME
, bdisp
->id
);
657 bdisp
->dbg
.debugfs_entry
= debugfs_create_dir(dirname
, NULL
);
658 if (!bdisp
->dbg
.debugfs_entry
)
661 if (!bdisp_dbg_create_entry(regs
))
664 if (!bdisp_dbg_create_entry(last_nodes
))
667 if (!bdisp_dbg_create_entry(last_nodes_raw
))
670 if (!bdisp_dbg_create_entry(last_request
))
673 if (!bdisp_dbg_create_entry(perf
))
679 bdisp_debugfs_remove(bdisp
);
683 void bdisp_debugfs_remove(struct bdisp_dev
*bdisp
)
685 debugfs_remove_recursive(bdisp
->dbg
.debugfs_entry
);
686 bdisp
->dbg
.debugfs_entry
= NULL
;