linux/drivers/media/platform/sti/bdisp/bdisp-debug.c
<<
>>
Prefs
   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