Received: by 2002:a05:7412:419a:b0:f3:1519:9f41 with SMTP id i26csp2920626rdh; Mon, 27 Nov 2023 02:14:22 -0800 (PST) X-Google-Smtp-Source: AGHT+IGmBevK+jEeMy09lnq10+wxh0eZiN46qBpRx9gMDUVI4CxxgaygEdlr89c4FJwXTJ0rG+vF X-Received: by 2002:a17:90b:3a82:b0:285:d32c:670f with SMTP id om2-20020a17090b3a8200b00285d32c670fmr2829575pjb.10.1701080062126; Mon, 27 Nov 2023 02:14:22 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1701080062; cv=none; d=google.com; s=arc-20160816; b=rCdZG6OkasLHoEilehVlDtmhCVSAkl6hnjlj3TtvImx0ppKSexXcK4Umjnp8HSjP4m XLD8GSFO/3KH2LA22I5Jh6H2L9zXY4uW4yz2IlNxVRDzxy1Sh87nT3ggVPDUOlU57KIw w/G23F2H1K7CtoKXk8ySNBhMf/H1r4eL7UgSfxWoptkliiMx4Lfo6E634j7WH8GCtlwa tb1J328BHif+qgqbGoAx0AscRIIoabkqEgVvIZCsyzLZAIaJ3Kmb0kSH4pQ7iqLRl2zQ W8EpCLMJgzsgYRPNz1L8wfQUMEBxB3dR1ZG4z9NJwZbgO2o2ZNdpgaUd7SYrqK0j0XkR zucA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date; bh=ryFpz4GrZV3I7mLBSmUJLna3Dnig15iziVvWig1EYKY=; fh=g17TTV3IAh7upqWYUv7HGC34+Nx1v9H4Zz+OCPOH6/U=; b=fG2UzaEcehIN59YHZljHyi++oO7ffgjF7Xwc/5mbiBgjzLt7dgpilbrdQvBDfQl0qs nCe1JTB+L8kuichywKGBffkddcjtB++NQ2JueV+BoxwTXsKRJswE+A4K6OL/9Fvq4Al9 kAB4DfmmbHl2XElnbT6k0HScB2QTHkYMHzE81237PY+RdjXFGOw+sUfs3zVmqxvA7dG8 95ppmWidkxRoY6KFJ+Zirq0/2/Huhy/fvqBh0/G0poglclvx406FtAEB0VjyqDztYcBP KYpAWbFNaT4x/JGLkg+1a402EqYZ6A8MTS4gaoJ3IIGLK7socvG6yJyTdv3B2pqUlygN tbLg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:5 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from groat.vger.email (groat.vger.email. [2620:137:e000::3:5]) by mx.google.com with ESMTPS id g6-20020a17090a300600b00283a5548126si9039177pjb.98.2023.11.27.02.14.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 27 Nov 2023 02:14:22 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:5 as permitted sender) client-ip=2620:137:e000::3:5; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:5 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by groat.vger.email (Postfix) with ESMTP id 0133D807500D; Mon, 27 Nov 2023 02:14:16 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at groat.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232841AbjK0KNx (ORCPT + 99 others); Mon, 27 Nov 2023 05:13:53 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42650 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232789AbjK0KNr (ORCPT ); Mon, 27 Nov 2023 05:13:47 -0500 Received: from metis.whiteo.stw.pengutronix.de (metis.whiteo.stw.pengutronix.de [IPv6:2a0a:edc0:2:b01:1d::104]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DB992E1 for ; Mon, 27 Nov 2023 02:13:51 -0800 (PST) Received: from drehscheibe.grey.stw.pengutronix.de ([2a0a:edc0:0:c01:1d::a2]) by metis.whiteo.stw.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1r7YcY-0008C0-6K; Mon, 27 Nov 2023 11:13:42 +0100 Received: from [2a0a:edc0:2:b01:1d::c0] (helo=ptx.whiteo.stw.pengutronix.de) by drehscheibe.grey.stw.pengutronix.de with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1r7YcU-00Bv3P-0I; Mon, 27 Nov 2023 11:13:38 +0100 Received: from sha by ptx.whiteo.stw.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1r7YcT-0044Za-TW; Mon, 27 Nov 2023 11:13:37 +0100 Date: Mon, 27 Nov 2023 11:13:37 +0100 From: Sascha Hauer To: Andy Yan Cc: heiko@sntech.de, hjc@rock-chips.com, dri-devel@lists.freedesktop.org, linux-rockchip@lists.infradead.org, linux-kernel@vger.kernel.org, krzysztof.kozlowski+dt@linaro.org, robh+dt@kernel.org, devicetree@vger.kernel.org, sebastian.reichel@collabora.com, kever.yang@rock-chips.com, chris.obbard@collabora.com, Andy Yan Subject: Re: [PATCH v2 11/12] drm/rockchip: vop2: Add debugfs support Message-ID: <20231127101337.GU3359458@pengutronix.de> References: <20231122125316.3454268-1-andyshrk@163.com> <20231122125601.3455031-1-andyshrk@163.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20231122125601.3455031-1-andyshrk@163.com> X-Sent-From: Pengutronix Hildesheim X-URL: http://www.pengutronix.de/ X-Accept-Language: de,en X-Accept-Content-Type: text/plain User-Agent: Mutt/1.10.1 (2018-07-13) X-SA-Exim-Connect-IP: 2a0a:edc0:0:c01:1d::a2 X-SA-Exim-Mail-From: sha@pengutronix.de X-SA-Exim-Scanned: No (on metis.whiteo.stw.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org X-Spam-Status: No, score=-0.8 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on groat.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (groat.vger.email [0.0.0.0]); Mon, 27 Nov 2023 02:14:17 -0800 (PST) On Wed, Nov 22, 2023 at 08:56:01PM +0800, Andy Yan wrote: > From: Andy Yan > > /sys/kernel/debug/dri/vop2/summary: dump vop display state > /sys/kernel/debug/dri/vop2/regs: dump whole vop registers > /sys/kernel/debug/dri/vop2/active_regs: only dump the registers of > activated modules > > Signed-off-by: Andy Yan > --- > > (no changes since v1) > > drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 399 +++++++++++++++++++ > 1 file changed, 399 insertions(+) > > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > index 9eecbe1f71f9..4a2342209c15 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > @@ -27,6 +27,7 @@ > #include > #include > #include > +#include > #include > #include > > @@ -187,6 +188,7 @@ struct vop2 { > */ > u32 registered_num_wins; > > + struct resource *res; > void __iomem *regs; > struct regmap *map; > > @@ -228,6 +230,44 @@ struct vop2 { > #define vop2_output_if_is_lvds(x) (x == ROCKCHIP_VOP2_EP_LVDS0 || x == ROCKCHIP_VOP2_EP_LVDS1) > #define vop2_output_if_is_dpi(x) (x == ROCKCHIP_VOP2_EP_RGB0) > > +struct vop2_regs_dump { > + const char *name; > + u32 base; > + u32 en_reg; > + u32 en_val; > + u32 en_mask; > +}; > + > +/* > + * bus-format types. > + */ > +struct drm_bus_format_enum_list { > + int type; > + const char *name; > +}; > + > +static const struct drm_bus_format_enum_list drm_bus_format_enum_list[] = { > + { DRM_MODE_CONNECTOR_Unknown, "Unknown" }, > + { MEDIA_BUS_FMT_RGB565_1X16, "RGB565_1X16" }, > + { MEDIA_BUS_FMT_RGB666_1X18, "RGB666_1X18" }, > + { MEDIA_BUS_FMT_RGB666_1X24_CPADHI, "RGB666_1X24_CPADHI" }, > + { MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, "RGB666_1X7X3_SPWG" }, > + { MEDIA_BUS_FMT_YUV8_1X24, "YUV8_1X24" }, > + { MEDIA_BUS_FMT_UYYVYY8_0_5X24, "UYYVYY8_0_5X24" }, > + { MEDIA_BUS_FMT_YUV10_1X30, "YUV10_1X30" }, > + { MEDIA_BUS_FMT_UYYVYY10_0_5X30, "UYYVYY10_0_5X30" }, > + { MEDIA_BUS_FMT_RGB888_3X8, "RGB888_3X8" }, > + { MEDIA_BUS_FMT_RGB888_1X24, "RGB888_1X24" }, > + { MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, "RGB888_1X7X4_SPWG" }, > + { MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, "RGB888_1X7X4_JEIDA" }, > + { MEDIA_BUS_FMT_UYVY8_2X8, "UYVY8_2X8" }, > + { MEDIA_BUS_FMT_YUYV8_1X16, "YUYV8_1X16" }, > + { MEDIA_BUS_FMT_UYVY8_1X16, "UYVY8_1X16" }, > + { MEDIA_BUS_FMT_RGB101010_1X30, "RGB101010_1X30" }, > + { MEDIA_BUS_FMT_YUYV10_1X20, "YUYV10_1X20" }, > +}; > +static DRM_ENUM_NAME_FN(drm_get_bus_format_name, drm_bus_format_enum_list) > + > static const struct regmap_config vop2_regmap_config; > > static struct vop2_video_port *to_vop2_video_port(struct drm_crtc *crtc) > @@ -2487,6 +2527,363 @@ static const struct drm_crtc_helper_funcs vop2_crtc_helper_funcs = { > .atomic_disable = vop2_crtc_atomic_disable, > }; > > +static void vop2_dump_connector_on_crtc(struct drm_crtc *crtc, struct seq_file *s) > +{ > + struct drm_connector_list_iter conn_iter; > + struct drm_connector *connector; > + > + drm_connector_list_iter_begin(crtc->dev, &conn_iter); > + drm_for_each_connector_iter(connector, &conn_iter) { > + if (crtc->state->connector_mask & drm_connector_mask(connector)) > + seq_printf(s, " Connector: %s\n", connector->name); > + > + } > + drm_connector_list_iter_end(&conn_iter); > +} > + > +static int vop2_plane_state_dump(struct seq_file *s, struct drm_plane *plane) > +{ > + struct vop2_win *win = to_vop2_win(plane); > + struct drm_plane_state *pstate = plane->state; > + struct drm_rect *src, *dst; > + struct drm_framebuffer *fb; > + struct drm_gem_object *obj; > + struct rockchip_gem_object *rk_obj; > + bool xmirror; > + bool ymirror; > + bool rotate_270; > + bool rotate_90; > + dma_addr_t fb_addr; > + int i; > + > + seq_printf(s, " %s: %s\n", win->data->name, pstate->crtc ? "ACTIVE" : "DISABLED"); > + if (!pstate || !pstate->fb) > + return 0; > + > + fb = pstate->fb; > + src = &pstate->src; > + dst = &pstate->dst; > + xmirror = pstate->rotation & DRM_MODE_REFLECT_X ? true : false; > + ymirror = pstate->rotation & DRM_MODE_REFLECT_Y ? true : false; > + rotate_270 = pstate->rotation & DRM_MODE_ROTATE_270; > + rotate_90 = pstate->rotation & DRM_MODE_ROTATE_90; > + > + seq_printf(s, "\twin_id: %d\n", win->win_id); > + > + seq_printf(s, "\tformat: %p4cc%s glb_alpha[0x%x]\n", > + &fb->format->format, > + drm_is_afbc(fb->modifier) ? "[AFBC]" : "", > + pstate->alpha >> 8); > + seq_printf(s, "\trotate: xmirror: %d ymirror: %d rotate_90: %d rotate_270: %d\n", > + xmirror, ymirror, rotate_90, rotate_270); > + seq_printf(s, "\tzpos: %d\n", pstate->normalized_zpos); > + seq_printf(s, "\tsrc: pos[%d, %d] rect[%d x %d]\n", src->x1 >> 16, > + src->y1 >> 16, drm_rect_width(src) >> 16, > + drm_rect_height(src) >> 16); > + seq_printf(s, "\tdst: pos[%d, %d] rect[%d x %d]\n", dst->x1, dst->y1, > + drm_rect_width(dst), drm_rect_height(dst)); > + > + for (i = 0; i < fb->format->num_planes; i++) { > + obj = fb->obj[0]; > + rk_obj = to_rockchip_obj(obj); > + fb_addr = rk_obj->dma_addr + fb->offsets[0]; > + > + seq_printf(s, "\tbuf[%d]: addr: %pad pitch: %d offset: %d\n", > + i, &fb_addr, fb->pitches[i], fb->offsets[i]); > + } > + > + return 0; > +} > + > +static int vop2_crtc_state_dump(struct drm_crtc *crtc, struct seq_file *s) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct drm_crtc_state *cstate = crtc->state; > + struct rockchip_crtc_state *vcstate; > + struct drm_display_mode *mode; > + struct drm_plane *plane; > + bool interlaced; > + > + seq_printf(s, "Video Port%d: %s\n", vp->id, !cstate ? > + "DISABLED" : cstate->active ? "ACTIVE" : "DISABLED"); > + > + if (!cstate || !cstate->active) > + return 0; > + > + mode = &crtc->state->adjusted_mode; > + vcstate = to_rockchip_crtc_state(cstate); > + interlaced = !!(mode->flags & DRM_MODE_FLAG_INTERLACE); > + > + vop2_dump_connector_on_crtc(crtc, s); > + seq_printf(s, "\tbus_format[%x]: %s\n", vcstate->bus_format, > + drm_get_bus_format_name(vcstate->bus_format)); > + seq_printf(s, "\toutput_mode[%x]", vcstate->output_mode); > + seq_printf(s, " color_space[%d]\n", vcstate->color_space); > + seq_printf(s, " Display mode: %dx%d%s%d\n", > + mode->hdisplay, mode->vdisplay, interlaced ? "i" : "p", > + drm_mode_vrefresh(mode)); > + seq_printf(s, "\tclk[%d] real_clk[%d] type[%x] flag[%x]\n", > + mode->clock, mode->crtc_clock, mode->type, mode->flags); > + seq_printf(s, "\tH: %d %d %d %d\n", mode->hdisplay, mode->hsync_start, > + mode->hsync_end, mode->htotal); > + seq_printf(s, "\tV: %d %d %d %d\n", mode->vdisplay, mode->vsync_start, > + mode->vsync_end, mode->vtotal); > + > + drm_atomic_crtc_for_each_plane(plane, crtc) { > + vop2_plane_state_dump(s, plane); > + } > + > + return 0; > +} > + > +static int vop2_summary_show(struct seq_file *s, void *data) > +{ > + struct drm_info_node *node = s->private; > + struct drm_minor *minor = node->minor; > + struct drm_device *drm_dev = minor->dev; > + struct drm_crtc *crtc; > + > + drm_modeset_lock_all(drm_dev); > + drm_for_each_crtc(crtc, drm_dev) { > + vop2_crtc_state_dump(crtc, s); > + } > + drm_modeset_unlock_all(drm_dev); > + > + return 0; > +} > + > +static void vop2_regs_print(struct vop2 *vop2, struct seq_file *s, struct vop2_regs_dump *dump) > +{ > + resource_size_t start; > + const int reg_num = 0x110 / 4; If I'm not mistaken this prints a register space of 0x110 bytes. Shouldn't it be 0x100 bytes instead? Also, are all these register spaces really have the same size? Does it make sense to add the size to struct vop2_regs_dump? > + u32 val; > + int i; > + > + if (dump->en_mask) { > + val = vop2_readl(vop2, dump->base + dump->en_reg); > + if ((val & dump->en_mask) != dump->en_val) > + return; > + } > + seq_printf(s, "\n%s:\n", dump->name); > + > + start = vop2->res->start + dump->base; > + for (i = 0; i < reg_num;) { > + seq_printf(s, "%08x: %08x %08x %08x %08x\n", (u32)start + i * 4, > + vop2_readl(vop2, dump->base + (4 * i)), > + vop2_readl(vop2, dump->base + (4 * (i + 1))), > + vop2_readl(vop2, dump->base + (4 * (i + 2))), > + vop2_readl(vop2, dump->base + (4 * (i + 3)))); > + i += 4; > + } > + > +} > + > +static int vop2_regs_show(struct seq_file *s, void *arg) > +{ > + struct drm_info_node *node = s->private; > + struct vop2 *vop2 = (struct vop2 *)node->info_ent->data; > + struct drm_minor *minor = node->minor; > + struct drm_device *drm_dev = minor->dev; > + > + struct vop2_regs_dump dump; > + > + drm_modeset_lock_all(drm_dev); > + > + if (vop2->enable_count) { > + dump.en_mask = 0; > + > + dump.name = "SYS"; > + dump.base = RK3568_REG_CFG_DONE; > + vop2_regs_print(vop2, s, &dump); Can you create a statically initialized array of struct vop2_regs_dump and iterate over it? You would need an additional present_in_soc_xy flag in struct vop2_regs_dump, but other than that I don't see a problem and the result might look better. For the windows it might also be an option to iterate over vop2->data->win instead. This array already contains the register base addresses and window names. > +static int vop2_active_regs_show(struct seq_file *s, void *data) > +{ > + struct drm_info_node *node = s->private; > + struct vop2 *vop2 = (struct vop2 *)node->info_ent->data; > + struct drm_minor *minor = node->minor; > + struct drm_device *drm_dev = minor->dev; > + > + struct vop2_regs_dump dump; > + > + drm_modeset_lock_all(drm_dev); > + if (vop2->enable_count) { > + dump.en_mask = 0; > + > + dump.name = "SYS"; > + dump.base = RK3568_REG_CFG_DONE; > + vop2_regs_print(vop2, s, &dump); Not sure if we really need an additional debugfs entry to print only the active entities, but if we do then we could avoid a bit of code duplication by adding creating a common register dump function called from vop2_regs_show() and vop2_active_regs_show() which takes an additional ignore_disabled argument. Sascha -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |