Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 791ddb1e authored by Thierry Reding's avatar Thierry Reding
Browse files

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: default avatarThierry Reding <treding@nvidia.com>
parent 01a5da0c
Loading
Loading
Loading
Loading
+41 −3
Original line number Diff line number Diff line
@@ -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:
+8 −0
Original line number Diff line number Diff line
@@ -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;