forked from Minki/linux
drm/tegra: dc: Record statistics
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>
This commit is contained in:
parent
01a5da0c10
commit
791ddb1e1c
@ -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:
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user