From 396818f4664a98200569144f760edbd468f4f0c0 Mon Sep 17 00:00:00 2001 From: Mark Yao Date: Thu, 19 Jan 2017 14:19:00 +0800 Subject: [PATCH] drm/rockchip: vop: fix iommu crash when resume Iommu crash with that path: vop_disable: 1, disable all windows and set vop config done 2, vop enter to standy, all windows not works, but their registers are not clean, when you read window's enable bit, may found the window is enable. vop_enable: 1, memcpy(vop->regsbak, vop->regs, len) save current vop registers to vop->regsbak, then you can found window is enable on regsbak. 2, VOP_WIN_SET(vop, win, gate, 1); force enable window gate, but gate and enable is on same hardware register, the means window enable rewrite to vop hardware. then: when some on do vop_config_done but not reconfigure the bad register window, iommu crash. Do register configure before memcpy(vop->regsbak, vop->regs, len) is not safe, after that would be save. Change-Id: I55b7846b1d39901c6b357fe541c9af1729b2c6b9 Signed-off-by: Mark Yao --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 40 ++++++++++----------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 959417b9c8ce..a879bb79cb48 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -793,15 +793,33 @@ static void vop_enable(struct drm_crtc *crtc) VOP_CTRL_SET(vop, global_regdone_en, 1); VOP_CTRL_SET(vop, dsp_blank, 0); + /* + * We need to make sure that all windows are disabled before resume + * the crtc. Otherwise we might try to scan from a destroyed + * buffer later. + */ for (i = 0; i < vop->num_wins; i++) { struct vop_win *win = &vop->win[i]; + if (win->phy->scl && win->phy->scl->ext) { + VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, SCALE_NONE); + VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, SCALE_NONE); + VOP_SCL_SET_EXT(vop, win, cbcr_hor_scl_mode, SCALE_NONE); + VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, SCALE_NONE); + } + VOP_WIN_SET(vop, win, enable, 0); VOP_WIN_SET(vop, win, gate, 1); } + VOP_CTRL_SET(vop, afbdc_en, 0); + vop_cfg_done(vop); + vop->is_enabled = true; spin_lock(&vop->reg_lock); + /* + * enable vop, all the register would take effect when vop exit standby + */ VOP_CTRL_SET(vop, standby, 0); spin_unlock(&vop->reg_lock); @@ -821,28 +839,6 @@ err_disable_hclk: static void vop_crtc_disable(struct drm_crtc *crtc) { struct vop *vop = to_vop(crtc); - int i; - - /* - * We need to make sure that all windows are disabled before we - * disable that crtc. Otherwise we might try to scan from a destroyed - * buffer later. - */ - for (i = 0; i < vop->num_wins; i++) { - struct vop_win *win = &vop->win[i]; - - spin_lock(&vop->reg_lock); - if (win->phy->scl && win->phy->scl->ext) { - VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, SCALE_NONE); - VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, SCALE_NONE); - VOP_SCL_SET_EXT(vop, win, cbcr_hor_scl_mode, SCALE_NONE); - VOP_SCL_SET_EXT(vop, win, cbcr_ver_scl_mode, SCALE_NONE); - } - VOP_WIN_SET(vop, win, enable, 0); - spin_unlock(&vop->reg_lock); - } - VOP_CTRL_SET(vop, afbdc_en, 0); - vop_cfg_done(vop); drm_crtc_vblank_off(crtc); -- 2.34.1