Hi Cristian, On Wed Jun 17, 2026 at 8:52 PM CEST, Cristian Ciocaltea wrote: > Assert the AXI reset in the CRTC disable path, and the VP DCLK reset in > the enable path. > > These resets are intended to leave the hardware in a clean state for the > next use, helping recover from exceptions such as IOMMU page faults, as > well as to prevent random display output glitches, such as a blank > image, observed when switching modes that also change the color format, > e.g. from RGB to YUV420 and vice versa. > > For now this seems to affect only the RK3588, hence the resets are > optional and will be provided in the device tree for this SoC only.
Why do you think it only effect RK3588? I reported about my RK3568 test here: https://lore.kernel.org/linux-rockchip/[email protected]/ "I then went on to try LibreELEC's builds. The artifacts I (sometimes) saw, were gone :-D OTOH, I did get several major issues 'in return', like rk_iommu Page fault resulting in a black screen and the only way to 'recover' from it, was a reboot." And I reported some more test results here: https://forum.libreelec.tv/thread/29953-le13-testing-for-rk3288-rk3328-rk3399-rk3566-rk3568-rk3576-rk3588/?postID=204691#post204691 That seems to me a (strong) indication it also affects RK3566/RK3568? Cheers, Diederik > Co-developed-by: Andy Yan <[email protected]> > Signed-off-by: Andy Yan <[email protected]> > Signed-off-by: Cristian Ciocaltea <[email protected]> > --- > drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 35 > ++++++++++++++++++++++++++++ > drivers/gpu/drm/rockchip/rockchip_drm_vop2.h | 4 ++++ > 2 files changed, 39 insertions(+) > > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > index 4cce3e336f5b..2833fb49ad81 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c > @@ -17,6 +17,7 @@ > #include <linux/platform_device.h> > #include <linux/pm_runtime.h> > #include <linux/regmap.h> > +#include <linux/reset.h> > #include <linux/swab.h> > > #include <drm/drm.h> > @@ -860,6 +861,26 @@ static int vop2_core_clks_prepare_enable(struct vop2 > *vop2) > return ret; > } > > +static void vop2_clk_reset(struct vop2 *vop2, struct reset_control *rstc) > +{ > + int ret; > + > + if (!rstc) > + return; > + > + ret = reset_control_assert(rstc); > + if (ret < 0) { > + drm_warn(vop2->drm, "failed to assert reset: %d\n", ret); > + return; > + } > + > + udelay(10); > + > + ret = reset_control_deassert(rstc); > + if (ret < 0) > + drm_err(vop2->drm, "failed to deassert reset: %d\n", ret); > +} > + > static void rk3588_vop2_power_domain_enable_all(struct vop2 *vop2) > { > u32 pd; > @@ -938,6 +959,8 @@ static void vop2_disable(struct vop2 *vop2) > { > rockchip_drm_dma_detach_device(vop2->drm, vop2->dev); > > + vop2_clk_reset(vop2, vop2->axi_rst); > + > pm_runtime_put_sync(vop2->dev); > > regcache_drop_region(vop2->map, 0, vop2_regmap_config.max_register); > @@ -1948,6 +1971,8 @@ static void vop2_crtc_atomic_enable(struct drm_crtc > *crtc, > > vop2_crtc_atomic_try_set_gamma(vop2, vp, crtc, crtc_state); > > + vop2_clk_reset(vop2, vp->dclk_rst); > + > drm_crtc_vblank_on(crtc); > > vop2_unlock(vop2); > @@ -2531,6 +2556,11 @@ static int vop2_create_crtcs(struct vop2 *vop2) > return dev_err_probe(drm->dev, PTR_ERR(vp->dclk), > "failed to get %s\n", dclk_name); > > + vp->dclk_rst = devm_reset_control_get_optional(vop2->dev, > dclk_name); > + if (IS_ERR(vp->dclk_rst)) > + return dev_err_probe(drm->dev, PTR_ERR(vp->dclk_rst), > + "failed to get %s reset\n", > dclk_name); > + > np = of_graph_get_remote_node(dev->of_node, i, -1); > if (!np) { > drm_dbg(vop2->drm, "%s: No remote for vp%d\n", > __func__, i); > @@ -2890,6 +2920,11 @@ static int vop2_bind(struct device *dev, struct device > *master, void *data) > return dev_err_probe(drm->dev, PTR_ERR(vop2->pll_hdmiphy1), > "failed to get pll_hdmiphy1\n"); > > + vop2->axi_rst = devm_reset_control_get_optional(vop2->dev, "axi"); > + if (IS_ERR(vop2->axi_rst)) > + return dev_err_probe(drm->dev, PTR_ERR(vop2->axi_rst), > + "failed to get axi reset\n"); > + > vop2->irq = platform_get_irq(pdev, 0); > if (vop2->irq < 0) > return dev_err_probe(drm->dev, vop2->irq, "cannot find irq for > vop2\n"); > diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > index ffcb39c130aa..14b437d2d088 100644 > --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.h > @@ -165,6 +165,8 @@ enum vop2_win_regs { > VOP2_WIN_MAX_REG, > }; > > +struct reset_control; > + > struct vop2_regs_dump { > const char *name; > u32 base; > @@ -238,6 +240,7 @@ struct vop2_video_port { > struct vop2 *vop2; > struct clk *dclk; > struct clk *dclk_src; > + struct reset_control *dclk_rst; > unsigned int id; > const struct vop2_video_port_data *data; > > @@ -329,6 +332,7 @@ struct vop2 { > struct clk *pclk; > struct clk *pll_hdmiphy0; > struct clk *pll_hdmiphy1; > + struct reset_control *axi_rst; > > /* optional internal rgb encoder */ > struct rockchip_rgb *rgb;
