drm/sti: add debugfs entries for GDP planes
authorVincent Abriou <vincent.abriou@st.com>
Thu, 4 Feb 2016 10:39:54 +0000 (11:39 +0100)
committerVincent Abriou <vincent.abriou@st.com>
Fri, 26 Feb 2016 09:06:22 +0000 (10:06 +0100)
Signed-off-by: Vincent Abriou <vincent.abriou@st.com>
Reviewed-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
drivers/gpu/drm/sti/sti_gdp.c

index a6fba9cfb0a6bc41a1b9dba6cc6aa984d9342875..8f0e89fbb3f9dc3fd859c7fb957c1b3fb1d08bac 100644 (file)
 #define GDP_ARGB1555    0x06
 #define GDP_ARGB4444    0x07
 
+#define GDP2STR(fmt) { GDP_ ## fmt, #fmt }
+
+static struct gdp_format_to_str {
+       int format;
+       char name[20];
+} gdp_format_to_str[] = {
+               GDP2STR(RGB565),
+               GDP2STR(RGB888),
+               GDP2STR(RGB888_32),
+               GDP2STR(XBGR8888),
+               GDP2STR(ARGB8565),
+               GDP2STR(ARGB8888),
+               GDP2STR(ABGR8888),
+               GDP2STR(ARGB1555),
+               GDP2STR(ARGB4444)
+               };
+
 #define GAM_GDP_CTL_OFFSET      0x00
 #define GAM_GDP_AGC_OFFSET      0x04
 #define GAM_GDP_VPO_OFFSET      0x0C
@@ -119,6 +136,222 @@ static const uint32_t gdp_supported_formats[] = {
        DRM_FORMAT_RGB888,
 };
 
+#define DBGFS_DUMP(reg) seq_printf(s, "\n  %-25s 0x%08X", #reg, \
+                                  readl(gdp->regs + reg ## _OFFSET))
+
+static void gdp_dbg_ctl(struct seq_file *s, int val)
+{
+       int i;
+
+       seq_puts(s, "\tColor:");
+       for (i = 0; i < ARRAY_SIZE(gdp_format_to_str); i++) {
+               if (gdp_format_to_str[i].format == (val & 0x1F)) {
+                       seq_printf(s, gdp_format_to_str[i].name);
+                       break;
+               }
+       }
+       if (i == ARRAY_SIZE(gdp_format_to_str))
+               seq_puts(s, "<UNKNOWN>");
+
+       seq_printf(s, "\tWaitNextVsync:%d", val & WAIT_NEXT_VSYNC ? 1 : 0);
+}
+
+static void gdp_dbg_vpo(struct seq_file *s, int val)
+{
+       seq_printf(s, "\txdo:%4d\tydo:%4d", val & 0xFFFF, (val >> 16) & 0xFFFF);
+}
+
+static void gdp_dbg_vps(struct seq_file *s, int val)
+{
+       seq_printf(s, "\txds:%4d\tyds:%4d", val & 0xFFFF, (val >> 16) & 0xFFFF);
+}
+
+static void gdp_dbg_size(struct seq_file *s, int val)
+{
+       seq_printf(s, "\t%d x %d", val & 0xFFFF, (val >> 16) & 0xFFFF);
+}
+
+static void gdp_dbg_nvn(struct seq_file *s, struct sti_gdp *gdp, int val)
+{
+       void *base = NULL;
+       unsigned int i;
+
+       for (i = 0; i < GDP_NODE_NB_BANK; i++) {
+               if (gdp->node_list[i].top_field_paddr == val) {
+                       base = gdp->node_list[i].top_field;
+                       break;
+               }
+               if (gdp->node_list[i].btm_field_paddr == val) {
+                       base = gdp->node_list[i].btm_field;
+                       break;
+               }
+       }
+
+       if (base)
+               seq_printf(s, "\tVirt @: %p", base);
+}
+
+static void gdp_dbg_ppt(struct seq_file *s, int val)
+{
+       if (val & GAM_GDP_PPT_IGNORE)
+               seq_puts(s, "\tNot displayed on mixer!");
+}
+
+static void gdp_dbg_mst(struct seq_file *s, int val)
+{
+       if (val & 1)
+               seq_puts(s, "\tBUFFER UNDERFLOW!");
+}
+
+static int gdp_dbg_show(struct seq_file *s, void *data)
+{
+       struct drm_info_node *node = s->private;
+       struct sti_gdp *gdp = (struct sti_gdp *)node->info_ent->data;
+       struct drm_device *dev = node->minor->dev;
+       struct drm_plane *drm_plane = &gdp->plane.drm_plane;
+       struct drm_crtc *crtc = drm_plane->crtc;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       seq_printf(s, "%s: (vaddr = 0x%p)",
+                  sti_plane_to_str(&gdp->plane), gdp->regs);
+
+       DBGFS_DUMP(GAM_GDP_CTL);
+       gdp_dbg_ctl(s, readl(gdp->regs + GAM_GDP_CTL_OFFSET));
+       DBGFS_DUMP(GAM_GDP_AGC);
+       DBGFS_DUMP(GAM_GDP_VPO);
+       gdp_dbg_vpo(s, readl(gdp->regs + GAM_GDP_VPO_OFFSET));
+       DBGFS_DUMP(GAM_GDP_VPS);
+       gdp_dbg_vps(s, readl(gdp->regs + GAM_GDP_VPS_OFFSET));
+       DBGFS_DUMP(GAM_GDP_PML);
+       DBGFS_DUMP(GAM_GDP_PMP);
+       DBGFS_DUMP(GAM_GDP_SIZE);
+       gdp_dbg_size(s, readl(gdp->regs + GAM_GDP_SIZE_OFFSET));
+       DBGFS_DUMP(GAM_GDP_NVN);
+       gdp_dbg_nvn(s, gdp, readl(gdp->regs + GAM_GDP_NVN_OFFSET));
+       DBGFS_DUMP(GAM_GDP_KEY1);
+       DBGFS_DUMP(GAM_GDP_KEY2);
+       DBGFS_DUMP(GAM_GDP_PPT);
+       gdp_dbg_ppt(s, readl(gdp->regs + GAM_GDP_PPT_OFFSET));
+       DBGFS_DUMP(GAM_GDP_CML);
+       DBGFS_DUMP(GAM_GDP_MST);
+       gdp_dbg_mst(s, readl(gdp->regs + GAM_GDP_MST_OFFSET));
+
+       seq_puts(s, "\n\n");
+       if (!crtc)
+               seq_puts(s, "  Not connected to any DRM CRTC\n");
+       else
+               seq_printf(s, "  Connected to DRM CRTC #%d (%s)\n",
+                          crtc->base.id, sti_mixer_to_str(to_sti_mixer(crtc)));
+
+       mutex_unlock(&dev->struct_mutex);
+       return 0;
+}
+
+static void gdp_node_dump_node(struct seq_file *s, struct sti_gdp_node *node)
+{
+       seq_printf(s, "\t@:0x%p", node);
+       seq_printf(s, "\n\tCTL  0x%08X", node->gam_gdp_ctl);
+       gdp_dbg_ctl(s, node->gam_gdp_ctl);
+       seq_printf(s, "\n\tAGC  0x%08X", node->gam_gdp_agc);
+       seq_printf(s, "\n\tVPO  0x%08X", node->gam_gdp_vpo);
+       gdp_dbg_vpo(s, node->gam_gdp_vpo);
+       seq_printf(s, "\n\tVPS  0x%08X", node->gam_gdp_vps);
+       gdp_dbg_vps(s, node->gam_gdp_vps);
+       seq_printf(s, "\n\tPML  0x%08X", node->gam_gdp_pml);
+       seq_printf(s, "\n\tPMP  0x%08X", node->gam_gdp_pmp);
+       seq_printf(s, "\n\tSIZE 0x%08X", node->gam_gdp_size);
+       gdp_dbg_size(s, node->gam_gdp_size);
+       seq_printf(s, "\n\tNVN  0x%08X", node->gam_gdp_nvn);
+       seq_printf(s, "\n\tKEY1 0x%08X", node->gam_gdp_key1);
+       seq_printf(s, "\n\tKEY2 0x%08X", node->gam_gdp_key2);
+       seq_printf(s, "\n\tPPT  0x%08X", node->gam_gdp_ppt);
+       gdp_dbg_ppt(s, node->gam_gdp_ppt);
+       seq_printf(s, "\n\tCML  0x%08X", node->gam_gdp_cml);
+       seq_puts(s, "\n");
+}
+
+static int gdp_node_dbg_show(struct seq_file *s, void *arg)
+{
+       struct drm_info_node *node = s->private;
+       struct sti_gdp *gdp = (struct sti_gdp *)node->info_ent->data;
+       struct drm_device *dev = node->minor->dev;
+       unsigned int b;
+       int ret;
+
+       ret = mutex_lock_interruptible(&dev->struct_mutex);
+       if (ret)
+               return ret;
+
+       for (b = 0; b < GDP_NODE_NB_BANK; b++) {
+               seq_printf(s, "\n%s[%d].top", sti_plane_to_str(&gdp->plane), b);
+               gdp_node_dump_node(s, gdp->node_list[b].top_field);
+               seq_printf(s, "\n%s[%d].btm", sti_plane_to_str(&gdp->plane), b);
+               gdp_node_dump_node(s, gdp->node_list[b].btm_field);
+       }
+
+       mutex_unlock(&dev->struct_mutex);
+       return 0;
+}
+
+static struct drm_info_list gdp0_debugfs_files[] = {
+       { "gdp0", gdp_dbg_show, 0, NULL },
+       { "gdp0_node", gdp_node_dbg_show, 0, NULL },
+};
+
+static struct drm_info_list gdp1_debugfs_files[] = {
+       { "gdp1", gdp_dbg_show, 0, NULL },
+       { "gdp1_node", gdp_node_dbg_show, 0, NULL },
+};
+
+static struct drm_info_list gdp2_debugfs_files[] = {
+       { "gdp2", gdp_dbg_show, 0, NULL },
+       { "gdp2_node", gdp_node_dbg_show, 0, NULL },
+};
+
+static struct drm_info_list gdp3_debugfs_files[] = {
+       { "gdp3", gdp_dbg_show, 0, NULL },
+       { "gdp3_node", gdp_node_dbg_show, 0, NULL },
+};
+
+static int gdp_debugfs_init(struct sti_gdp *gdp, struct drm_minor *minor)
+{
+       unsigned int i;
+       struct drm_info_list *gdp_debugfs_files;
+       int nb_files;
+
+       switch (gdp->plane.desc) {
+       case STI_GDP_0:
+               gdp_debugfs_files = gdp0_debugfs_files;
+               nb_files = ARRAY_SIZE(gdp0_debugfs_files);
+               break;
+       case STI_GDP_1:
+               gdp_debugfs_files = gdp1_debugfs_files;
+               nb_files = ARRAY_SIZE(gdp1_debugfs_files);
+               break;
+       case STI_GDP_2:
+               gdp_debugfs_files = gdp2_debugfs_files;
+               nb_files = ARRAY_SIZE(gdp2_debugfs_files);
+               break;
+       case STI_GDP_3:
+               gdp_debugfs_files = gdp3_debugfs_files;
+               nb_files = ARRAY_SIZE(gdp3_debugfs_files);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       for (i = 0; i < nb_files; i++)
+               gdp_debugfs_files[i].data = gdp;
+
+       return drm_debugfs_create_files(gdp_debugfs_files,
+                                       nb_files,
+                                       minor->debugfs_root, minor);
+}
+
 static int sti_gdp_fourcc2format(int fourcc)
 {
        switch (fourcc) {
@@ -684,6 +917,9 @@ struct drm_plane *sti_gdp_create(struct drm_device *drm_dev,
 
        sti_plane_init_property(&gdp->plane, type);
 
+       if (gdp_debugfs_init(gdp, drm_dev->primary))
+               DRM_ERROR("GDP debugfs setup failed\n");
+
        return &gdp->plane.drm_plane;
 
 err: