1/* 2 * Copyright (C) STMicroelectronics SA 2014 3 * Authors: Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. 4 * License terms: GNU General Public License (GPL), version 2 5 */ 6 7#include <linux/debugfs.h> 8#include <linux/pm_runtime.h> 9 10#include "bdisp.h" 11#include "bdisp-filter.h" 12#include "bdisp-reg.h" 13 14void bdisp_dbg_perf_begin(struct bdisp_dev *bdisp) 15{ 16 bdisp->dbg.hw_start = ktime_get(); 17} 18 19void bdisp_dbg_perf_end(struct bdisp_dev *bdisp) 20{ 21 s64 time_us; 22 23 time_us = ktime_us_delta(ktime_get(), bdisp->dbg.hw_start); 24 25 if (!bdisp->dbg.min_duration) 26 bdisp->dbg.min_duration = time_us; 27 else 28 bdisp->dbg.min_duration = min(time_us, bdisp->dbg.min_duration); 29 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; 33} 34 35static void bdisp_dbg_dump_ins(struct seq_file *s, u32 val) 36{ 37 seq_printf(s, "INS\t0x%08X\t", val); 38 39 switch (val & BLT_INS_S1_MASK) { 40 case BLT_INS_S1_OFF: 41 break; 42 case BLT_INS_S1_MEM: 43 seq_puts(s, "SRC1=mem - "); 44 break; 45 case BLT_INS_S1_CF: 46 seq_puts(s, "SRC1=ColorFill - "); 47 break; 48 case BLT_INS_S1_COPY: 49 seq_puts(s, "SRC1=copy - "); 50 break; 51 case BLT_INS_S1_FILL: 52 seq_puts(s, "SRC1=fil - "); 53 break; 54 default: 55 seq_puts(s, "SRC1=??? - "); 56 break; 57 } 58 59 switch (val & BLT_INS_S2_MASK) { 60 case BLT_INS_S2_OFF: 61 break; 62 case BLT_INS_S2_MEM: 63 seq_puts(s, "SRC2=mem - "); 64 break; 65 case BLT_INS_S2_CF: 66 seq_puts(s, "SRC2=ColorFill - "); 67 break; 68 default: 69 seq_puts(s, "SRC2=??? - "); 70 break; 71 } 72 73 if ((val & BLT_INS_S3_MASK) == BLT_INS_S3_MEM) 74 seq_puts(s, "SRC3=mem - "); 75 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 - "); 106 107 seq_puts(s, "\n"); 108} 109 110static void bdisp_dbg_dump_tty(struct seq_file *s, u32 val) 111{ 112 seq_printf(s, "TTY\t0x%08X\t", val); 113 seq_printf(s, "Pitch=%d - ", val & 0xFFFF); 114 115 switch ((val & BLT_TTY_COL_MASK) >> BLT_TTY_COL_SHIFT) { 116 case BDISP_RGB565: 117 seq_puts(s, "RGB565 - "); 118 break; 119 case BDISP_RGB888: 120 seq_puts(s, "RGB888 - "); 121 break; 122 case BDISP_XRGB8888: 123 seq_puts(s, "xRGB888 - "); 124 break; 125 case BDISP_ARGB8888: 126 seq_puts(s, "ARGB8888 - "); 127 break; 128 case BDISP_NV12: 129 seq_puts(s, "NV12 - "); 130 break; 131 case BDISP_YUV_3B: 132 seq_puts(s, "YUV420P - "); 133 break; 134 default: 135 seq_puts(s, "ColorFormat ??? - "); 136 break; 137 } 138 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 - "); 155 156 seq_puts(s, "\n"); 157} 158 159static void bdisp_dbg_dump_xy(struct seq_file *s, u32 val, char *name) 160{ 161 seq_printf(s, "%s\t0x%08X\t", name, val); 162 seq_printf(s, "(%d,%d)\n", val & 0xFFFF, (val >> 16)); 163} 164 165static void bdisp_dbg_dump_sz(struct seq_file *s, u32 val, char *name) 166{ 167 seq_printf(s, "%s\t0x%08X\t", name, val); 168 seq_printf(s, "%dx%d\n", val & 0x1FFF, (val >> 16) & 0x1FFF); 169} 170 171static void bdisp_dbg_dump_sty(struct seq_file *s, 172 u32 val, u32 addr, char *name) 173{ 174 bool s1, s2, s3; 175 176 seq_printf(s, "%s\t0x%08X\t", name, val); 177 178 if (!addr || !name || (strlen(name) < 2)) 179 goto done; 180 181 s1 = name[strlen(name) - 1] == '1'; 182 s2 = name[strlen(name) - 1] == '2'; 183 s3 = name[strlen(name) - 1] == '3'; 184 185 seq_printf(s, "Pitch=%d - ", val & 0xFFFF); 186 187 switch ((val & BLT_TTY_COL_MASK) >> BLT_TTY_COL_SHIFT) { 188 case BDISP_RGB565: 189 seq_puts(s, "RGB565 - "); 190 break; 191 case BDISP_RGB888: 192 seq_puts(s, "RGB888 - "); 193 break; 194 case BDISP_XRGB8888: 195 seq_puts(s, "xRGB888 - "); 196 break; 197 case BDISP_ARGB8888: 198 seq_puts(s, "ARGB888 - "); 199 break; 200 case BDISP_NV12: 201 seq_puts(s, "NV12 - "); 202 break; 203 case BDISP_YUV_3B: 204 seq_puts(s, "YUV420P - "); 205 break; 206 default: 207 seq_puts(s, "ColorFormat ??? - "); 208 break; 209 } 210 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 - "); 231 232done: 233 seq_puts(s, "\n"); 234} 235 236static void bdisp_dbg_dump_fctl(struct seq_file *s, u32 val) 237{ 238 seq_printf(s, "FCTL\t0x%08X\t", val); 239 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 - "); 244 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"); 249 250 seq_puts(s, "\n"); 251} 252 253static void bdisp_dbg_dump_rsf(struct seq_file *s, u32 val, char *name) 254{ 255 u32 inc; 256 257 seq_printf(s, "%s\t0x%08X\t", name, val); 258 259 if (!val) 260 goto done; 261 262 inc = val & 0xFFFF; 263 seq_printf(s, "H: %d(6.10) / scale~%dx0.1 - ", inc, 1024 * 10 / inc); 264 265 inc = val >> 16; 266 seq_printf(s, "V: %d(6.10) / scale~%dx0.1", inc, 1024 * 10 / inc); 267 268done: 269 seq_puts(s, "\n"); 270} 271 272static void bdisp_dbg_dump_rzi(struct seq_file *s, u32 val, char *name) 273{ 274 seq_printf(s, "%s\t0x%08X\t", name, val); 275 276 if (!val) 277 goto done; 278 279 seq_printf(s, "H: init=%d repeat=%d - ", val & 0x3FF, (val >> 12) & 7); 280 val >>= 16; 281 seq_printf(s, "V: init=%d repeat=%d", val & 0x3FF, (val >> 12) & 7); 282 283done: 284 seq_puts(s, "\n"); 285} 286 287static void bdisp_dbg_dump_ivmx(struct seq_file *s, 288 u32 c0, u32 c1, u32 c2, u32 c3) 289{ 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); 294 295 if (!c0 && !c1 && !c2 && !c3) { 296 seq_puts(s, "\n"); 297 return; 298 } 299 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"); 305 return; 306 } 307 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"); 313 return; 314 } 315 seq_puts(s, "Unknown conversion\n"); 316} 317 318static int bdisp_dbg_last_nodes(struct seq_file *s, void *data) 319{ 320 /* Not dumping all fields, focusing on significant ones */ 321 struct bdisp_dev *bdisp = s->private; 322 struct bdisp_node *node; 323 int i = 0; 324 325 if (!bdisp->dbg.copy_node[0]) { 326 seq_puts(s, "No node built yet\n"); 327 return 0; 328 } 329 330 do { 331 node = bdisp->dbg.copy_node[i]; 332 if (!node) 333 break; 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); 364 /* PMK not dumped */ 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); 387 388 return 0; 389} 390 391static int bdisp_dbg_last_nodes_raw(struct seq_file *s, void *data) 392{ 393 struct bdisp_dev *bdisp = s->private; 394 struct bdisp_node *node; 395 u32 *val; 396 int j, i = 0; 397 398 if (!bdisp->dbg.copy_node[0]) { 399 seq_puts(s, "No node built yet\n"); 400 return 0; 401 } 402 403 do { 404 node = bdisp->dbg.copy_node[i]; 405 if (!node) 406 break; 407 408 seq_printf(s, "--------\nNode %d:\n", i); 409 val = (u32 *)node; 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); 413 414 return 0; 415} 416 417static const char *bdisp_fmt_to_str(struct bdisp_frame frame) 418{ 419 switch (frame.fmt->pixelformat) { 420 case V4L2_PIX_FMT_YUV420: 421 return "YUV420P"; 422 case V4L2_PIX_FMT_NV12: 423 if (frame.field == V4L2_FIELD_INTERLACED) 424 return "NV12 interlaced"; 425 else 426 return "NV12"; 427 case V4L2_PIX_FMT_RGB565: 428 return "RGB16"; 429 case V4L2_PIX_FMT_RGB24: 430 return "RGB24"; 431 case V4L2_PIX_FMT_XBGR32: 432 return "XRGB"; 433 case V4L2_PIX_FMT_ABGR32: 434 return "ARGB"; 435 default: 436 return "????"; 437 } 438} 439 440static int bdisp_dbg_last_request(struct seq_file *s, void *data) 441{ 442 struct bdisp_dev *bdisp = s->private; 443 struct bdisp_request *request = &bdisp->dbg.copy_request; 444 struct bdisp_frame src, dst; 445 446 if (!request->nb_req) { 447 seq_puts(s, "No request\n"); 448 return 0; 449 } 450 451 src = request->src; 452 dst = request->dst; 453 454 seq_printf(s, "\nRequest #%d\n", request->nb_req); 455 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); 465 466 if (request->hflip) 467 seq_puts(s, "Horizontal flip\n\n"); 468 469 if (request->vflip) 470 seq_puts(s, "Vertical flip\n\n"); 471 472 return 0; 473} 474 475#define DUMP(reg) seq_printf(s, #reg " \t0x%08X\n", readl(bdisp->regs + reg)) 476 477static int bdisp_dbg_regs(struct seq_file *s, void *data) 478{ 479 struct bdisp_dev *bdisp = s->private; 480 int ret; 481 unsigned int i; 482 483 ret = pm_runtime_get_sync(bdisp->dev); 484 if (ret < 0) { 485 seq_puts(s, "Cannot wake up IP\n"); 486 return 0; 487 } 488 489 seq_printf(s, "Reg @ = 0x%p\n", bdisp->regs); 490 491 seq_puts(s, "\nStatic:\n"); 492 DUMP(BLT_CTL); 493 DUMP(BLT_ITS); 494 DUMP(BLT_STA1); 495 DUMP(BLT_AQ1_CTL); 496 DUMP(BLT_AQ1_IP); 497 DUMP(BLT_AQ1_LNA); 498 DUMP(BLT_AQ1_STA); 499 DUMP(BLT_ITM0); 500 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); 514 DUMP(BLT_PLUGT_OP2); 515 DUMP(BLT_PLUGT_CHZ); 516 DUMP(BLT_PLUGT_MSZ); 517 DUMP(BLT_PLUGT_PGZ); 518 519 seq_puts(s, "\nNode:\n"); 520 DUMP(BLT_NIP); 521 DUMP(BLT_CIC); 522 DUMP(BLT_INS); 523 DUMP(BLT_ACK); 524 DUMP(BLT_TBA); 525 DUMP(BLT_TTY); 526 DUMP(BLT_TXY); 527 DUMP(BLT_TSZ); 528 DUMP(BLT_S1BA); 529 DUMP(BLT_S1TY); 530 DUMP(BLT_S1XY); 531 DUMP(BLT_S2BA); 532 DUMP(BLT_S2TY); 533 DUMP(BLT_S2XY); 534 DUMP(BLT_S2SZ); 535 DUMP(BLT_S3BA); 536 DUMP(BLT_S3TY); 537 DUMP(BLT_S3XY); 538 DUMP(BLT_S3SZ); 539 DUMP(BLT_FCTL); 540 DUMP(BLT_RSF); 541 DUMP(BLT_RZI); 542 DUMP(BLT_HFP); 543 DUMP(BLT_VFP); 544 DUMP(BLT_Y_RSF); 545 DUMP(BLT_Y_RZI); 546 DUMP(BLT_Y_HFP); 547 DUMP(BLT_Y_VFP); 548 DUMP(BLT_IVMX0); 549 DUMP(BLT_IVMX1); 550 DUMP(BLT_IVMX2); 551 DUMP(BLT_IVMX3); 552 DUMP(BLT_OVMX0); 553 DUMP(BLT_OVMX1); 554 DUMP(BLT_OVMX2); 555 DUMP(BLT_OVMX3); 556 DUMP(BLT_DEI); 557 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)); 562 } 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)); 566 } 567 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)); 572 } 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)); 576 } 577 578 pm_runtime_put(bdisp->dev); 579 580 return 0; 581} 582 583#define SECOND 1000000 584 585static int bdisp_dbg_perf(struct seq_file *s, void *data) 586{ 587 struct bdisp_dev *bdisp = s->private; 588 struct bdisp_request *request = &bdisp->dbg.copy_request; 589 s64 avg_time_us; 590 int avg_fps, min_fps, max_fps, last_fps; 591 592 if (!request->nb_req) { 593 seq_puts(s, "No request\n"); 594 return 0; 595 } 596 597 avg_time_us = div64_s64(bdisp->dbg.tot_duration, request->nb_req); 598 if (avg_time_us > SECOND) 599 avg_fps = 0; 600 else 601 avg_fps = SECOND / (s32)avg_time_us; 602 603 if (bdisp->dbg.min_duration > SECOND) 604 min_fps = 0; 605 else 606 min_fps = SECOND / (s32)bdisp->dbg.min_duration; 607 608 if (bdisp->dbg.max_duration > SECOND) 609 max_fps = 0; 610 else 611 max_fps = SECOND / (s32)bdisp->dbg.max_duration; 612 613 if (bdisp->dbg.last_duration > SECOND) 614 last_fps = 0; 615 else 616 last_fps = SECOND / (s32)bdisp->dbg.last_duration; 617 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); 626 627 return 0; 628} 629 630#define bdisp_dbg_declare(name) \ 631 static int bdisp_dbg_##name##_open(struct inode *i, struct file *f) \ 632 { \ 633 return single_open(f, bdisp_dbg_##name, i->i_private); \ 634 } \ 635 static const struct file_operations bdisp_dbg_##name##_fops = { \ 636 .open = bdisp_dbg_##name##_open, \ 637 .read = seq_read, \ 638 .llseek = seq_lseek, \ 639 .release = single_release, \ 640 } 641 642#define bdisp_dbg_create_entry(name) \ 643 debugfs_create_file(#name, S_IRUGO, bdisp->dbg.debugfs_entry, bdisp, \ 644 &bdisp_dbg_##name##_fops) 645 646bdisp_dbg_declare(regs); 647bdisp_dbg_declare(last_nodes); 648bdisp_dbg_declare(last_nodes_raw); 649bdisp_dbg_declare(last_request); 650bdisp_dbg_declare(perf); 651 652int bdisp_debugfs_create(struct bdisp_dev *bdisp) 653{ 654 char dirname[16]; 655 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) 659 goto err; 660 661 if (!bdisp_dbg_create_entry(regs)) 662 goto err; 663 664 if (!bdisp_dbg_create_entry(last_nodes)) 665 goto err; 666 667 if (!bdisp_dbg_create_entry(last_nodes_raw)) 668 goto err; 669 670 if (!bdisp_dbg_create_entry(last_request)) 671 goto err; 672 673 if (!bdisp_dbg_create_entry(perf)) 674 goto err; 675 676 return 0; 677 678err: 679 bdisp_debugfs_remove(bdisp); 680 return 0; 681} 682 683void bdisp_debugfs_remove(struct bdisp_dev *bdisp) 684{ 685 debugfs_remove_recursive(bdisp->dbg.debugfs_entry); 686 bdisp->dbg.debugfs_entry = NULL; 687} 688