]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
drm/tegra: dc: Record statistics
authorThierry Reding <treding@nvidia.com>
Tue, 28 Jul 2015 19:27:05 +0000 (21:27 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 13 Aug 2015 11:47:43 +0000 (13:47 +0200)
Record interrupt statistics, such as the number of frames and VBLANKs
received and the number of FIFO underflow and overflows.

Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/gpu/drm/tegra/dc.c
drivers/gpu/drm/tegra/drm.h

index 6347c0f8a9590412814eb40912c4ecee6d47614c..60be70fb89ae4540478b4ee68090288ed7f13acd 100644 (file)
@@ -76,6 +76,14 @@ to_tegra_plane_state(struct drm_plane_state *state)
        return NULL;
 }
 
+static void tegra_dc_stats_reset(struct tegra_dc_stats *stats)
+{
+       stats->frames = 0;
+       stats->vblank = 0;
+       stats->underflow = 0;
+       stats->overflow = 0;
+}
+
 /*
  * Reads the active copy of a register. This takes the dc->lock spinlock to
  * prevent races with the VBLANK processing which also needs access to the
@@ -1129,6 +1137,7 @@ static void tegra_crtc_disable(struct drm_crtc *crtc)
                tegra_dc_writel(dc, value, DC_CMD_DISPLAY_POWER_CONTROL);
        }
 
+       tegra_dc_stats_reset(&dc->stats);
        drm_crtc_vblank_off(crtc);
 }
 
@@ -1326,6 +1335,7 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
                /*
                dev_dbg(dc->dev, "%s(): frame end\n", __func__);
                */
+               dc->stats.frames++;
        }
 
        if (status & VBLANK_INT) {
@@ -1334,12 +1344,21 @@ static irqreturn_t tegra_dc_irq(int irq, void *data)
                */
                drm_crtc_handle_vblank(&dc->base);
                tegra_dc_finish_page_flip(dc);
+               dc->stats.vblank++;
        }
 
        if (status & (WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT)) {
                /*
                dev_dbg(dc->dev, "%s(): underflow\n", __func__);
                */
+               dc->stats.underflow++;
+       }
+
+       if (status & (WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT)) {
+               /*
+               dev_dbg(dc->dev, "%s(): overflow\n", __func__);
+               */
+               dc->stats.overflow++;
        }
 
        return IRQ_HANDLED;
@@ -1593,9 +1612,23 @@ static int tegra_dc_show_crc(struct seq_file *s, void *data)
        return 0;
 }
 
+static int tegra_dc_show_stats(struct seq_file *s, void *data)
+{
+       struct drm_info_node *node = s->private;
+       struct tegra_dc *dc = node->info_ent->data;
+
+       seq_printf(s, "frames: %lu\n", dc->stats.frames);
+       seq_printf(s, "vblank: %lu\n", dc->stats.vblank);
+       seq_printf(s, "underflow: %lu\n", dc->stats.underflow);
+       seq_printf(s, "overflow: %lu\n", dc->stats.overflow);
+
+       return 0;
+}
+
 static struct drm_info_list debugfs_files[] = {
        { "regs", tegra_dc_show_regs, 0, NULL },
        { "crc", tegra_dc_show_crc, 0, NULL },
+       { "stats", tegra_dc_show_stats, 0, NULL },
 };
 
 static int tegra_dc_debugfs_init(struct tegra_dc *dc, struct drm_minor *minor)
@@ -1741,7 +1774,8 @@ static int tegra_dc_init(struct host1x_client *client)
                tegra_dc_writel(dc, value, DC_CMD_CONT_SYNCPT_VSYNC);
        }
 
-       value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT | WIN_A_OF_INT;
+       value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
+               WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
        tegra_dc_writel(dc, value, DC_CMD_INT_TYPE);
 
        value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
@@ -1757,15 +1791,19 @@ static int tegra_dc_init(struct host1x_client *client)
                WINDOW_B_THRESHOLD(1) | WINDOW_C_THRESHOLD(1);
        tegra_dc_writel(dc, value, DC_DISP_DISP_MEM_HIGH_PRIORITY_TIMER);
 
-       value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
+       value = VBLANK_INT | WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
+               WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
        tegra_dc_writel(dc, value, DC_CMD_INT_ENABLE);
 
-       value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT;
+       value = WIN_A_UF_INT | WIN_B_UF_INT | WIN_C_UF_INT |
+               WIN_A_OF_INT | WIN_B_OF_INT | WIN_C_OF_INT;
        tegra_dc_writel(dc, value, DC_CMD_INT_MASK);
 
        if (dc->soc->supports_border_color)
                tegra_dc_writel(dc, 0, DC_DISP_BORDER_COLOR);
 
+       tegra_dc_stats_reset(&dc->stats);
+
        return 0;
 
 cleanup:
index ee66049521c35bcb6351bd07b48a3fe032660152..ec49275ffb247c419a70a2f8aed9cd7d922c46d6 100644 (file)
@@ -105,6 +105,13 @@ int tegra_drm_exit(struct tegra_drm *tegra);
 struct tegra_dc_soc_info;
 struct tegra_output;
 
+struct tegra_dc_stats {
+       unsigned long frames;
+       unsigned long vblank;
+       unsigned long underflow;
+       unsigned long overflow;
+};
+
 struct tegra_dc {
        struct host1x_client client;
        struct host1x_syncpt *syncpt;
@@ -122,6 +129,7 @@ struct tegra_dc {
 
        struct tegra_output *rgb;
 
+       struct tegra_dc_stats stats;
        struct list_head list;
 
        struct drm_info_list *debugfs_files;