Loading drivers/gpu/drm/tegra/dc.c +41 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -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) { Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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 | Loading @@ -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: Loading drivers/gpu/drm/tegra/drm.h +8 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading
drivers/gpu/drm/tegra/dc.c +41 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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); } Loading Loading @@ -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) { Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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 | Loading @@ -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: Loading
drivers/gpu/drm/tegra/drm.h +8 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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