Message ID | 20231207075906.651771-1-andyshrk@163.com |
---|---|
Headers | show |
Series | Add VOP2 support on rk3588 | expand |
Hi Andy, Am Donnerstag, 7. Dezember 2023, 08:59:06 CET schrieb Andy Yan: > From: Andy Yan <andy.yan@rock-chips.com> > > This patch sets aims at enable the VOP2 support on rk3588. > > Main feature of VOP2 on rk3588: > Four video ports: > VP0 Max 4096x2160 > VP1 Max 4096x2160 > VP2 Max 4096x2160 > VP3 Max 2048x1080 > > 4 4K Cluster windows with AFBC/line RGB and AFBC-only YUV support > 4 4K Esmart windows with line RGB/YUV support > > The current version support all the 8 windows with all the suppported > plane format. > > And we don't have a upstreamed encoder/connector(HDMI/DP) for rk3588 > yet, Cristian from collabora is working on adding upstream support for > HDMI on rk3588. > > My current test(1080P/4KP60) is runing with a HDMI driver pick from > downstream bsp kernel. > > A branch based on linux-6.7 rc4 containing all the series and > HDMI driver(not compatible with mainline rk3568 hdmi) picked > from downstream bsp kernel is available [0]. > > [0]https://github.com/andyshrk/linux/commits/rk3588-vop2-upstream-linux-6.7-rc4-2023-12-07 > > Changes in v4: > - fix the POST_BUF_EMPTY irq when set mode > - use full stop at all the description's end. > - address Krzysztof's review about dt-binding in v3 > - keep all VOP2_FEATURE_HAS_xxx macros increase in order. > - address Sascha's review about debugfs > - Add const for rockchip,rk3588-iommu compatible very nice, the error messages on "mode changes" are gone now. Display and even combination with panthor still work of my rk3588-board Tested-by: Heiko Stuebner <heiko@sntech.de>
Hi Andy, Am Donnerstag, 7. Dezember 2023, 09:02:47 CET schrieb Andy Yan: > From: Andy Yan <andy.yan@rock-chips.com> > > Add vop dt node for rk3588. > > Signed-off-by: Andy Yan <andy.yan@rock-chips.com> > --- > > (no changes since v1) > > arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 96 +++++++++++++++++++++++ > 1 file changed, 96 insertions(+) > > diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi > index 7064c0e9179f..a9810ca78dc4 100644 > --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi > +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi > @@ -593,6 +608,87 @@ i2c0: i2c@fd880000 { > status = "disabled"; > }; > > + vop: vop@fdd90000 { > + compatible = "rockchip,rk3588-vop"; > + reg = <0x0 0xfdd90000 0x0 0x4200>, <0x0 0xfdd95000 0x0 0x1000>; > + reg-names = "vop", "gamma_lut"; > + interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH 0>; > + clocks = <&cru ACLK_VOP>, > + <&cru HCLK_VOP>, > + <&cru DCLK_VOP0>, > + <&cru DCLK_VOP1>, > + <&cru DCLK_VOP2>, > + <&cru DCLK_VOP3>, > + <&cru PCLK_VOP_ROOT>; > + clock-names = "aclk", > + "hclk", > + "dclk_vp0", > + "dclk_vp1", > + "dclk_vp2", > + "dclk_vp3", > + "pclk_vop"; > + resets = <&cru SRST_A_VOP>, > + <&cru SRST_H_VOP>, > + <&cru SRST_D_VOP0>, > + <&cru SRST_D_VOP1>, > + <&cru SRST_D_VOP2>, > + <&cru SRST_D_VOP3>; > + reset-names = "axi", > + "ahb", > + "dclk_vp0", > + "dclk_vp1", > + "dclk_vp2", > + "dclk_vp3"; resets and reset-names do not seem to be part of the binding, so should probably be added there. > + iommus = <&vop_mmu>; > + power-domains = <&power RK3588_PD_VOP>; > + rockchip,grf = <&sys_grf>; > + rockchip,vop-grf = <&vop_grf>; > + rockchip,vo1-grf = <&vo1_grf>; > + rockchip,pmu = <&pmu>; > + move this blank line _below_ the status=disabled please. > + status = "disabled"; > + vop_out: ports { > + #address-cells = <1>; > + #size-cells = <0>; > + > + vp0: port@0 { > + #address-cells = <1>; > + #size-cells = <0>; > + reg = <0>; > + }; > + > + vp1: port@1 { > + #address-cells = <1>; > + #size-cells = <0>; > + reg = <1>; > + }; > + > + vp2: port@2 { > + #address-cells = <1>; > + #size-cells = <0>; > + reg = <2>; > + }; > + > + vp3: port@3 { > + #address-cells = <1>; > + #size-cells = <0>; > + reg = <3>; > + }; > + }; > + }; > + > + vop_mmu: iommu@fdd97e00 { > + compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; > + reg = <0x0 0xfdd97e00 0x0 0x100>, <0x0 0xfdd97f00 0x0 0x100>; > + interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH 0>; > + interrupt-names = "vop_mmu"; interrupt-names is not part of the mainline iommu binding, so should be dropped Thanks Heiko
Hi Heiko: On 12/9/23 00:07, Heiko Stübner wrote: > Hi Andy, > > Am Donnerstag, 7. Dezember 2023, 08:59:06 CET schrieb Andy Yan: >> From: Andy Yan <andy.yan@rock-chips.com> >> >> This patch sets aims at enable the VOP2 support on rk3588. >> >> Main feature of VOP2 on rk3588: >> Four video ports: >> VP0 Max 4096x2160 >> VP1 Max 4096x2160 >> VP2 Max 4096x2160 >> VP3 Max 2048x1080 >> >> 4 4K Cluster windows with AFBC/line RGB and AFBC-only YUV support >> 4 4K Esmart windows with line RGB/YUV support >> >> The current version support all the 8 windows with all the suppported >> plane format. >> >> And we don't have a upstreamed encoder/connector(HDMI/DP) for rk3588 >> yet, Cristian from collabora is working on adding upstream support for >> HDMI on rk3588. >> >> My current test(1080P/4KP60) is runing with a HDMI driver pick from >> downstream bsp kernel. >> >> A branch based on linux-6.7 rc4 containing all the series and >> HDMI driver(not compatible with mainline rk3568 hdmi) picked >> from downstream bsp kernel is available [0]. >> >> [0]https://github.com/andyshrk/linux/commits/rk3588-vop2-upstream-linux-6.7-rc4-2023-12-07 >> >> Changes in v4: >> - fix the POST_BUF_EMPTY irq when set mode >> - use full stop at all the description's end. >> - address Krzysztof's review about dt-binding in v3 >> - keep all VOP2_FEATURE_HAS_xxx macros increase in order. >> - address Sascha's review about debugfs >> - Add const for rockchip,rk3588-iommu compatible > > very nice, the error messages on "mode changes" are gone now. > Display and even combination with panthor still work of my rk3588-board > > Tested-by: Heiko Stuebner <heiko@sntech.de> Thanks for your honorable work on this platform, and thanks for you test and review. So can I add your Tested-by for all this series form PATCH 1~16 in next version? > > > > > > _______________________________________________ > Linux-rockchip mailing list > Linux-rockchip@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-rockchip
Hi Heiko: On 12/9/23 00:26, Heiko Stübner wrote: > Hi Andy, > > Am Donnerstag, 7. Dezember 2023, 09:02:47 CET schrieb Andy Yan: >> From: Andy Yan <andy.yan@rock-chips.com> >> >> Add vop dt node for rk3588. >> >> Signed-off-by: Andy Yan <andy.yan@rock-chips.com> >> --- >> >> (no changes since v1) >> >> arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 96 +++++++++++++++++++++++ >> 1 file changed, 96 insertions(+) >> >> diff --git a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi >> index 7064c0e9179f..a9810ca78dc4 100644 >> --- a/arch/arm64/boot/dts/rockchip/rk3588s.dtsi >> +++ b/arch/arm64/boot/dts/rockchip/rk3588s.dtsi >> @@ -593,6 +608,87 @@ i2c0: i2c@fd880000 { >> status = "disabled"; >> }; >> >> + vop: vop@fdd90000 { >> + compatible = "rockchip,rk3588-vop"; >> + reg = <0x0 0xfdd90000 0x0 0x4200>, <0x0 0xfdd95000 0x0 0x1000>; >> + reg-names = "vop", "gamma_lut"; >> + interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH 0>; >> + clocks = <&cru ACLK_VOP>, >> + <&cru HCLK_VOP>, >> + <&cru DCLK_VOP0>, >> + <&cru DCLK_VOP1>, >> + <&cru DCLK_VOP2>, >> + <&cru DCLK_VOP3>, >> + <&cru PCLK_VOP_ROOT>; >> + clock-names = "aclk", >> + "hclk", >> + "dclk_vp0", >> + "dclk_vp1", >> + "dclk_vp2", >> + "dclk_vp3", >> + "pclk_vop"; >> + resets = <&cru SRST_A_VOP>, >> + <&cru SRST_H_VOP>, >> + <&cru SRST_D_VOP0>, >> + <&cru SRST_D_VOP1>, >> + <&cru SRST_D_VOP2>, >> + <&cru SRST_D_VOP3>; >> + reset-names = "axi", >> + "ahb", >> + "dclk_vp0", >> + "dclk_vp1", >> + "dclk_vp2", >> + "dclk_vp3"; > > resets and reset-names do not seem to be part of the binding, so > should probably be added there. I will drop resets and reset-names in next version. > > >> + iommus = <&vop_mmu>; >> + power-domains = <&power RK3588_PD_VOP>; >> + rockchip,grf = <&sys_grf>; >> + rockchip,vop-grf = <&vop_grf>; >> + rockchip,vo1-grf = <&vo1_grf>; >> + rockchip,pmu = <&pmu>; >> + > > move this blank line _below_ the status=disabled please. ok, will do. > >> + status = "disabled"; >> + vop_out: ports { >> + #address-cells = <1>; >> + #size-cells = <0>; >> + >> + vp0: port@0 { >> + #address-cells = <1>; >> + #size-cells = <0>; >> + reg = <0>; >> + }; >> + >> + vp1: port@1 { >> + #address-cells = <1>; >> + #size-cells = <0>; >> + reg = <1>; >> + }; >> + >> + vp2: port@2 { >> + #address-cells = <1>; >> + #size-cells = <0>; >> + reg = <2>; >> + }; >> + >> + vp3: port@3 { >> + #address-cells = <1>; >> + #size-cells = <0>; >> + reg = <3>; >> + }; >> + }; >> + }; >> + >> + vop_mmu: iommu@fdd97e00 { >> + compatible = "rockchip,rk3588-iommu", "rockchip,rk3568-iommu"; >> + reg = <0x0 0xfdd97e00 0x0 0x100>, <0x0 0xfdd97f00 0x0 0x100>; >> + interrupts = <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH 0>; >> + interrupt-names = "vop_mmu"; > > interrupt-names is not part of the mainline iommu binding, so should be dropped will do. > > > Thanks > Heiko > >
On Thu, Dec 07, 2023 at 04:02:22PM +0800, Andy Yan wrote: > From: Andy Yan <andy.yan@rock-chips.com> > > /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 <andy.yan@rock-chips.com> Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de> Sascha > > --- > > Changes in v4: > - check NULL pointer at right place > - fix the index of fb->obj > - drop explicitly cast of void pointer > - make the register dump code as a common function. > > Changes in v3: > - put regs dump info in vop2_data > > drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 256 +++++++++++++++++++ > drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 11 + > drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 191 ++++++++++++++ > 3 files changed, 458 insertions(+) > > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > index 2b996f1a25ad..1cd86b3bde7e 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > @@ -27,6 +27,7 @@ > #include <drm/drm_debugfs.h> > #include <drm/drm_flip_work.h> > #include <drm/drm_framebuffer.h> > +#include <drm/drm_gem_framebuffer_helper.h> > #include <drm/drm_probe_helper.h> > #include <drm/drm_vblank.h> > > @@ -187,6 +188,7 @@ struct vop2 { > */ > u32 registered_num_wins; > > + struct resource *res; > void __iomem *regs; > struct regmap *map; > > @@ -238,6 +240,37 @@ struct vop2 { > > #define vop2_output_if_is_dpi(x) ((x) == ROCKCHIP_VOP2_EP_RGB0) > > + > +/* > + * 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) > @@ -2516,6 +2549,227 @@ 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 ? > + "DISABLED" : 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[i]; > + rk_obj = to_rockchip_obj(obj); > + fb_addr = rk_obj->dma_addr + fb->offsets[i]; > + > + 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, > + const struct vop2_regs_dump *dump, bool active_only) > +{ > + resource_size_t start; > + u32 val; > + int i; > + > + if (dump->en_mask && active_only) { > + 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 < dump->size >> 2; i += 4) { > + 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)))); > + } > +} > + > +static void __vop2_regs_dump(struct seq_file *s, bool active_only) > +{ > + struct drm_info_node *node = s->private; > + struct vop2 *vop2 = node->info_ent->data; > + struct drm_minor *minor = node->minor; > + struct drm_device *drm_dev = minor->dev; > + const struct vop2_regs_dump *dump; > + unsigned int i; > + > + drm_modeset_lock_all(drm_dev); > + if (vop2->enable_count) { > + for (i = 0; i < vop2->data->regs_dump_size; i++) { > + dump = &vop2->data->regs_dump[i]; > + vop2_regs_print(vop2, s, dump, active_only); > + } > + } else { > + seq_printf(s, "VOP disabled\n"); > + } > + drm_modeset_unlock_all(drm_dev); > + > +} > + > +static int vop2_regs_show(struct seq_file *s, void *arg) > +{ > + __vop2_regs_dump(s, false); > + > + return 0; > +} > + > +static int vop2_active_regs_show(struct seq_file *s, void *data) > +{ > + __vop2_regs_dump(s, true); > + > + return 0; > +} > + > +static struct drm_info_list vop2_debugfs_list[] = { > + { "summary", vop2_summary_show, 0, NULL }, > + { "active_regs", vop2_active_regs_show, 0, NULL }, > + { "regs", vop2_regs_show, 0, NULL }, > +}; > + > +static void vop2_debugfs_init(struct vop2 *vop2, struct drm_minor *minor) > +{ > + struct dentry *root; > + unsigned int i; > + > + root = debugfs_create_dir("vop2", minor->debugfs_root); > + if (!IS_ERR(root)) { > + for (i = 0; i < ARRAY_SIZE(vop2_debugfs_list); i++) > + vop2_debugfs_list[i].data = vop2; > + > + drm_debugfs_create_files(vop2_debugfs_list, > + ARRAY_SIZE(vop2_debugfs_list), > + root, minor); > + } > +} > + > +static int vop2_crtc_late_register(struct drm_crtc *crtc) > +{ > + struct vop2_video_port *vp = to_vop2_video_port(crtc); > + struct vop2 *vop2 = vp->vop2; > + > + if (drm_crtc_index(crtc) == 0) > + vop2_debugfs_init(vop2, crtc->dev->primary); > + > + return 0; > +} > + > static struct drm_crtc_state *vop2_crtc_duplicate_state(struct drm_crtc *crtc) > { > struct rockchip_crtc_state *vcstate; > @@ -2565,6 +2819,7 @@ static const struct drm_crtc_funcs vop2_crtc_funcs = { > .atomic_destroy_state = vop2_crtc_destroy_state, > .enable_vblank = vop2_crtc_enable_vblank, > .disable_vblank = vop2_crtc_disable_vblank, > + .late_register = vop2_crtc_late_register, > }; > > static irqreturn_t vop2_isr(int irq, void *data) > @@ -3109,6 +3364,7 @@ static int vop2_bind(struct device *dev, struct device *master, void *data) > return -EINVAL; > } > > + vop2->res = res; > vop2->regs = devm_ioremap_resource(dev, res); > if (IS_ERR(vop2->regs)) > return PTR_ERR(vop2->regs); > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > index 615a16196aff..59cd6b933bfb 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > @@ -122,6 +122,15 @@ enum vop2_win_regs { > VOP2_WIN_MAX_REG, > }; > > +struct vop2_regs_dump { > + const char *name; > + u32 base; > + u32 size; > + u32 en_reg; > + u32 en_val; > + u32 en_mask; > +}; > + > struct vop2_win_data { > const char *name; > unsigned int phys_id; > @@ -160,10 +169,12 @@ struct vop2_data { > u64 feature; > const struct vop2_win_data *win; > const struct vop2_video_port_data *vp; > + const struct vop2_regs_dump *regs_dump; > struct vop_rect max_input; > struct vop_rect max_output; > > unsigned int win_size; > + unsigned int regs_dump_size; > unsigned int soc_id; > }; > > diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > index 48170694ac6b..6fc119034a0e 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > @@ -260,6 +260,88 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { > }, > }; > > +static const struct vop2_regs_dump rk3568_regs_dump[] = { > + { > + .name = "SYS", > + .base = RK3568_REG_CFG_DONE, > + .size = 0x100, > + .en_reg = 0, > + .en_val = 0, > + .en_mask = 0 > + }, { > + .name = "OVL", > + .base = RK3568_OVL_CTRL, > + .size = 0x100, > + .en_reg = 0, > + .en_val = 0, > + .en_mask = 0, > + }, { > + .name = "VP0", > + .base = RK3568_VP0_CTRL_BASE, > + .size = 0x100, > + .en_reg = RK3568_VP_DSP_CTRL, > + .en_val = 0, > + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, > + }, { > + .name = "VP1", > + .base = RK3568_VP1_CTRL_BASE, > + .size = 0x100, > + .en_reg = RK3568_VP_DSP_CTRL, > + .en_val = 0, > + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, > + }, { > + .name = "VP2", > + .base = RK3568_VP2_CTRL_BASE, > + .size = 0x100, > + .en_reg = RK3568_VP_DSP_CTRL, > + .en_val = 0, > + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, > + > + }, { > + .name = "Cluster0", > + .base = RK3568_CLUSTER0_CTRL_BASE, > + .size = 0x110, > + .en_reg = RK3568_CLUSTER_WIN_CTRL0, > + .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + }, { > + .name = "Cluster1", > + .base = RK3568_CLUSTER1_CTRL_BASE, > + .size = 0x110, > + .en_reg = RK3568_CLUSTER_WIN_CTRL0, > + .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + }, { > + .name = "Esmart0", > + .base = RK3568_ESMART0_CTRL_BASE, > + .size = 0xf0, > + .en_reg = RK3568_SMART_REGION0_CTRL, > + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + }, { > + .name = "Esmart1", > + .base = RK3568_ESMART1_CTRL_BASE, > + .size = 0xf0, > + .en_reg = RK3568_SMART_REGION0_CTRL, > + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + }, { > + .name = "Smart0", > + .base = RK3568_SMART0_CTRL_BASE, > + .size = 0xf0, > + .en_reg = RK3568_SMART_REGION0_CTRL, > + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + }, { > + .name = "Smart1", > + .base = RK3568_SMART1_CTRL_BASE, > + .size = 0xf0, > + .en_reg = RK3568_SMART_REGION0_CTRL, > + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + }, > +}; > + > static const struct vop2_video_port_data rk3588_vop_video_ports[] = { > { > .id = 0, > @@ -440,6 +522,109 @@ static const struct vop2_win_data rk3588_vop_win_data[] = { > }, > }; > > +static const struct vop2_regs_dump rk3588_regs_dump[] = { > + { > + .name = "SYS", > + .base = RK3568_REG_CFG_DONE, > + .size = 0x100, > + .en_reg = 0, > + .en_val = 0, > + .en_mask = 0 > + }, { > + .name = "OVL", > + .base = RK3568_OVL_CTRL, > + .size = 0x100, > + .en_reg = 0, > + .en_val = 0, > + .en_mask = 0, > + }, { > + .name = "VP0", > + .base = RK3568_VP0_CTRL_BASE, > + .size = 0x100, > + .en_reg = RK3568_VP_DSP_CTRL, > + .en_val = 0, > + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, > + }, { > + .name = "VP1", > + .base = RK3568_VP1_CTRL_BASE, > + .size = 0x100, > + .en_reg = RK3568_VP_DSP_CTRL, > + .en_val = 0, > + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, > + }, { > + .name = "VP2", > + .base = RK3568_VP2_CTRL_BASE, > + .size = 0x100, > + .en_reg = RK3568_VP_DSP_CTRL, > + .en_val = 0, > + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, > + > + }, { > + .name = "VP3", > + .base = RK3588_VP3_CTRL_BASE, > + .size = 0x100, > + .en_reg = RK3568_VP_DSP_CTRL, > + .en_val = 0, > + .en_mask = RK3568_VP_DSP_CTRL__STANDBY, > + }, { > + .name = "Cluster0", > + .base = RK3568_CLUSTER0_CTRL_BASE, > + .size = 0x110, > + .en_reg = RK3568_CLUSTER_WIN_CTRL0, > + .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + }, { > + .name = "Cluster1", > + .base = RK3568_CLUSTER1_CTRL_BASE, > + .size = 0x110, > + .en_reg = RK3568_CLUSTER_WIN_CTRL0, > + .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + }, { > + .name = "Cluster2", > + .base = RK3588_CLUSTER2_CTRL_BASE, > + .size = 0x110, > + .en_reg = RK3568_CLUSTER_WIN_CTRL0, > + .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + }, { > + .name = "Cluster3", > + .base = RK3588_CLUSTER3_CTRL_BASE, > + .size = 0x110, > + .en_reg = RK3568_CLUSTER_WIN_CTRL0, > + .en_val = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + .en_mask = RK3568_CLUSTER_WIN_CTRL0__WIN0_EN, > + }, { > + .name = "Esmart0", > + .base = RK3568_ESMART0_CTRL_BASE, > + .size = 0xf0, > + .en_reg = RK3568_SMART_REGION0_CTRL, > + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + }, { > + .name = "Esmart1", > + .base = RK3568_ESMART1_CTRL_BASE, > + .size = 0xf0, > + .en_reg = RK3568_SMART_REGION0_CTRL, > + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + }, { > + .name = "Esmart2", > + .base = RK3588_ESMART2_CTRL_BASE, > + .size = 0xf0, > + .en_reg = RK3568_SMART_REGION0_CTRL, > + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + }, { > + .name = "Esmart3", > + .base = RK3588_ESMART3_CTRL_BASE, > + .size = 0xf0, > + .en_reg = RK3568_SMART_REGION0_CTRL, > + .en_val = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + .en_mask = RK3568_SMART_REGION0_CTRL__WIN0_EN, > + }, > +}; > + > static const struct vop2_data rk3566_vop = { > .feature = VOP2_FEATURE_HAS_SYS_GRF, > .nr_vps = 3, > @@ -448,6 +633,8 @@ static const struct vop2_data rk3566_vop = { > .vp = rk3568_vop_video_ports, > .win = rk3568_vop_win_data, > .win_size = ARRAY_SIZE(rk3568_vop_win_data), > + .regs_dump = rk3568_regs_dump, > + .regs_dump_size = ARRAY_SIZE(rk3568_regs_dump), > .soc_id = 3566, > }; > > @@ -459,6 +646,8 @@ static const struct vop2_data rk3568_vop = { > .vp = rk3568_vop_video_ports, > .win = rk3568_vop_win_data, > .win_size = ARRAY_SIZE(rk3568_vop_win_data), > + .regs_dump = rk3568_regs_dump, > + .regs_dump_size = ARRAY_SIZE(rk3568_regs_dump), > .soc_id = 3568, > }; > > @@ -471,6 +660,8 @@ static const struct vop2_data rk3588_vop = { > .vp = rk3588_vop_video_ports, > .win = rk3588_vop_win_data, > .win_size = ARRAY_SIZE(rk3588_vop_win_data), > + .regs_dump = rk3588_regs_dump, > + .regs_dump_size = ARRAY_SIZE(rk3588_regs_dump), > .soc_id = 3588, > }; > > -- > 2.34.1 > > >
On Thu, Dec 07, 2023 at 04:02:10PM +0800, Andy Yan wrote: > From: Andy Yan <andy.yan@rock-chips.com> > > VOP2 has multiple independent video ports with different > feature, so rename VOP_FEATURE_OUTPUT_10BIT to > VOP2_VP_FEATURE_OUTPUT_10BIT for more clearly meaning. > > Signed-off-by: Andy Yan <andy.yan@rock-chips.com> > --- Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de> Sascha > > (no changes since v1) > > drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 2 +- > drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 2 +- > drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 8 ++++---- > 3 files changed, 6 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > index edca7723335f..2b996f1a25ad 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > @@ -1995,7 +1995,7 @@ static void vop2_crtc_atomic_enable(struct drm_crtc *crtc, > return; > > if (vcstate->output_mode == ROCKCHIP_OUT_MODE_AAAA && > - !(vp_data->feature & VOP_FEATURE_OUTPUT_10BIT)) > + !(vp_data->feature & VOP2_VP_FEATURE_OUTPUT_10BIT)) > out_mode = ROCKCHIP_OUT_MODE_P888; > else > out_mode = vcstate->output_mode; > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > index 2763e54350a9..615a16196aff 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > @@ -11,7 +11,7 @@ > #include <drm/drm_modes.h> > #include "rockchip_drm_vop.h" > > -#define VOP_FEATURE_OUTPUT_10BIT BIT(0) > +#define VOP2_VP_FEATURE_OUTPUT_10BIT BIT(0) > > #define VOP2_FEATURE_HAS_SYS_GRF BIT(0) > #define VOP2_FEATURE_HAS_VO0_GRF BIT(1) > diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > index 275d265891db..48170694ac6b 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > +++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c > @@ -136,7 +136,7 @@ static const uint64_t format_modifiers_afbc[] = { > static const struct vop2_video_port_data rk3568_vop_video_ports[] = { > { > .id = 0, > - .feature = VOP_FEATURE_OUTPUT_10BIT, > + .feature = VOP2_VP_FEATURE_OUTPUT_10BIT, > .gamma_lut_len = 1024, > .cubic_lut_len = 9 * 9 * 9, > .max_output = { 4096, 2304 }, > @@ -263,7 +263,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = { > static const struct vop2_video_port_data rk3588_vop_video_ports[] = { > { > .id = 0, > - .feature = VOP_FEATURE_OUTPUT_10BIT, > + .feature = VOP2_VP_FEATURE_OUTPUT_10BIT, > .gamma_lut_len = 1024, > .cubic_lut_len = 9 * 9 * 9, /* 9x9x9 */ > .max_output = { 4096, 2304 }, > @@ -272,7 +272,7 @@ static const struct vop2_video_port_data rk3588_vop_video_ports[] = { > .offset = 0xc00, > }, { > .id = 1, > - .feature = VOP_FEATURE_OUTPUT_10BIT, > + .feature = VOP2_VP_FEATURE_OUTPUT_10BIT, > .gamma_lut_len = 1024, > .cubic_lut_len = 729, /* 9x9x9 */ > .max_output = { 4096, 2304 }, > @@ -280,7 +280,7 @@ static const struct vop2_video_port_data rk3588_vop_video_ports[] = { > .offset = 0xd00, > }, { > .id = 2, > - .feature = VOP_FEATURE_OUTPUT_10BIT, > + .feature = VOP2_VP_FEATURE_OUTPUT_10BIT, > .gamma_lut_len = 1024, > .cubic_lut_len = 17 * 17 * 17, /* 17x17x17 */ > .max_output = { 4096, 2304 }, > -- > 2.34.1 > > >
From: Andy Yan <andy.yan@rock-chips.com> This patch sets aims at enable the VOP2 support on rk3588. Main feature of VOP2 on rk3588: Four video ports: VP0 Max 4096x2160 VP1 Max 4096x2160 VP2 Max 4096x2160 VP3 Max 2048x1080 4 4K Cluster windows with AFBC/line RGB and AFBC-only YUV support 4 4K Esmart windows with line RGB/YUV support The current version support all the 8 windows with all the suppported plane format. And we don't have a upstreamed encoder/connector(HDMI/DP) for rk3588 yet, Cristian from collabora is working on adding upstream support for HDMI on rk3588. My current test(1080P/4KP60) is runing with a HDMI driver pick from downstream bsp kernel. A branch based on linux-6.7 rc4 containing all the series and HDMI driver(not compatible with mainline rk3568 hdmi) picked from downstream bsp kernel is available [0]. [0]https://github.com/andyshrk/linux/commits/rk3588-vop2-upstream-linux-6.7-rc4-2023-12-07 Changes in v4: - fix the POST_BUF_EMPTY irq when set mode - use full stop at all the description's end. - address Krzysztof's review about dt-binding in v3 - keep all VOP2_FEATURE_HAS_xxx macros increase in order. - address Sascha's review about debugfs - Add const for rockchip,rk3588-iommu compatible Changes in v3: - split from the vop2 driver patch - put bool variable yuv_overlay next to other bool variable - define macro for RK3568_OVL_CTRL__YUV_MODE - just write RK3568_OVL_CTRL register once in function vop2_setup_layer_mixer - constrain properties in allOf:if:then - some description updates - change the subject as Krzysztof suggested, and add his ACK - add braces for x in macro vop2_output_if_is_yyy(x) - clear the bits of a mask before setting it in rk3588_set_intf_mux - add more comments. - put regs dump info in vop2_data Changes in v2: - fix errors when running 'make DT_CHECKER_FLAGS=-m dt_binding_check' - split form vop driver patch - add rk3588_ prefix for functions which are rk3588 only - make some calculation as fixed value and keep calculation formula as comment - check return value for some cru calculation functions. - check return value for syscon_regmap_lookup_by_phandle - add NV20/NV30 for esmart plane Andy Yan (17): drm/rockchip: move output interface related definition to rockchip_drm_drv.h Revert "drm/rockchip: vop2: Use regcache_sync() to fix suspend/resume" drm/rockchip: vop2: set half_block_en bit in all mode drm/rockchip: vop2: clear afbc en and transform bit for cluster window at linear mode drm/rockchip: vop2: Add write mask for VP config done drm/rockchip: vop2: Set YUV/RGB overlay mode drm/rockchip: vop2: set bg dly and prescan dly at vop2_post_config drm/rockchip: vop2: rename grf to sys_grf dt-bindings: soc: rockchip: add rk3588 vop/vo syscon dt-bindings: display: vop2: Add rk3588 support dt-bindings: rockchip,vop2: Add more endpoint definition drm/rockchip: vop2: Add support for rk3588 drm/rockchip: vop2: rename VOP_FEATURE_OUTPUT_10BIT to VOP2_VP_FEATURE_OUTPUT_10BIT drm/rockchip: vop2: Add debugfs support dt-bindings: iommu: rockchip: Add Rockchip RK3588 arm64: dts: rockchip: Add vop on rk3588 MAINTAINERS: Add myself as a reviewer for rockchip drm .../display/rockchip/rockchip-vop2.yaml | 100 ++- .../bindings/iommu/rockchip,iommu.yaml | 11 +- .../devicetree/bindings/soc/rockchip/grf.yaml | 2 + MAINTAINERS | 1 + arch/arm64/boot/dts/rockchip/rk3588s.dtsi | 96 +++ .../gpu/drm/rockchip/analogix_dp-rockchip.c | 1 - drivers/gpu/drm/rockchip/cdn-dp-core.c | 1 - .../gpu/drm/rockchip/dw-mipi-dsi-rockchip.c | 1 - drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c | 1 - drivers/gpu/drm/rockchip/inno_hdmi.c | 1 - drivers/gpu/drm/rockchip/rk3066_hdmi.c | 1 - drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 18 + drivers/gpu/drm/rockchip/rockchip_drm_vop.h | 12 +- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 761 +++++++++++++++++- drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 111 ++- drivers/gpu/drm/rockchip/rockchip_lvds.c | 1 - drivers/gpu/drm/rockchip/rockchip_rgb.c | 1 - drivers/gpu/drm/rockchip/rockchip_vop2_reg.c | 414 +++++++++- include/dt-bindings/soc/rockchip,vop2.h | 4 + 19 files changed, 1441 insertions(+), 97 deletions(-)