From: Mark Yao <mark.yao@rock-chips.com> To: David Airlie <airlied@linux.ie>, Daniel Vetter <daniel@ffwll.ch>, Rob Clark <robdclark@gmail.com>, Philipp Zabel <p.zabel@pengutronix.de>, Daniel Kurtz <djkurtz@chromium.org>, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org Cc: Mark Yao <mark.yao@rock-chips.com> Subject: [PATCH v5] drm/rockchip: vop: power off until vop standby take effect Date: Wed, 4 Feb 2015 13:10:31 +0800 [thread overview] Message-ID: <1423026631-9318-1-git-send-email-mark.yao@rock-chips.com> (raw) Vop standby will take effect at end of current frame, if dsp_hold_valid_irq happen, it means vop standby complete. we must wait standby complete when we want to disable aclk, if not, memory bus maybe dead. Reviewed-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Daniel Kurtz <djkurtz@chromium.org> Signed-off-by: Mark Yao <mark.yao@rock-chips.com> --- Changes in v5: - reuse WARN_ON with if (cond) so that WARN_ON have a chance to output. Changes in v4: - fix comment syntax error Changes in v3: - if vop write vop regs when vop clocks is disabled, WARN_ON maybe have no chance to do crash dump, so reuse BUG_ON. - dsp hold irq only happen when standby bit 0->1 take effect, no need to do completion check. Changes in v2: - use WARN_ON instead of BUG_ON. drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 75 ++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index fb25836..20fa8a1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -89,6 +89,7 @@ struct vop { /* mutex vsync_ work */ struct mutex vsync_mutex; bool vsync_work_pending; + struct completion dsp_hold_completion; const struct vop_data *data; @@ -382,6 +383,36 @@ static bool is_alpha_support(uint32_t format) } } +static void vop_dsp_hold_valid_irq_enable(struct vop *vop) +{ + unsigned long flags; + + if (WARN_ON(!vop->is_enabled)) + return; + + spin_lock_irqsave(&vop->irq_lock, flags); + + vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK, + DSP_HOLD_VALID_INTR_EN(1)); + + spin_unlock_irqrestore(&vop->irq_lock, flags); +} + +static void vop_dsp_hold_valid_irq_disable(struct vop *vop) +{ + unsigned long flags; + + if (WARN_ON(!vop->is_enabled)) + return; + + spin_lock_irqsave(&vop->irq_lock, flags); + + vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK, + DSP_HOLD_VALID_INTR_EN(0)); + + spin_unlock_irqrestore(&vop->irq_lock, flags); +} + static void vop_enable(struct drm_crtc *crtc) { struct vop *vop = to_vop(crtc); @@ -454,26 +485,36 @@ static void vop_disable(struct drm_crtc *crtc) drm_vblank_off(crtc->dev, vop->pipe); - disable_irq(vop->irq); - /* - * TODO: Since standby doesn't take effect until the next vblank, - * when we turn off dclk below, the vop is probably still active. + * Vop standby will take effect at end of current frame, + * if dsp hold valid irq happen, it means standby complete. + * + * we must wait standby complete when we want to disable aclk, + * if not, memory bus maybe dead. */ + reinit_completion(&vop->dsp_hold_completion); + vop_dsp_hold_valid_irq_enable(vop); + spin_lock(&vop->reg_lock); VOP_CTRL_SET(vop, standby, 1); spin_unlock(&vop->reg_lock); + wait_for_completion(&vop->dsp_hold_completion); + + vop_dsp_hold_valid_irq_disable(vop); + + disable_irq(vop->irq); + vop->is_enabled = false; + /* - * disable dclk to stop frame scan, so we can safely detach iommu, + * vop standby complete, so iommu detach is safe. */ - clk_disable(vop->dclk); - rockchip_drm_dma_detach_device(vop->drm_dev, vop->dev); + clk_disable(vop->dclk); clk_disable(vop->aclk); clk_disable(vop->hclk); } @@ -1086,6 +1127,7 @@ static irqreturn_t vop_isr(int irq, void *data) struct vop *vop = data; uint32_t intr0_reg, active_irqs; unsigned long flags; + int ret = IRQ_NONE; /* * INTR_CTRL0 register has interrupt status, enable and clear bits, we @@ -1104,15 +1146,23 @@ static irqreturn_t vop_isr(int irq, void *data) if (!active_irqs) return IRQ_NONE; - /* Only Frame Start Interrupt is enabled; other irqs are spurious. */ - if (!(active_irqs & FS_INTR)) { - DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs); - return IRQ_NONE; + if (active_irqs & DSP_HOLD_VALID_INTR) { + complete(&vop->dsp_hold_completion); + active_irqs &= ~DSP_HOLD_VALID_INTR; + ret = IRQ_HANDLED; } - drm_handle_vblank(vop->drm_dev, vop->pipe); + if (active_irqs & FS_INTR) { + drm_handle_vblank(vop->drm_dev, vop->pipe); + active_irqs &= ~FS_INTR; + ret = (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED; + } - return (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED; + /* Unhandled irqs are spurious. */ + if (active_irqs) + DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs); + + return ret; } static int vop_create_crtc(struct vop *vop) @@ -1194,6 +1244,7 @@ static int vop_create_crtc(struct vop *vop) goto err_cleanup_crtc; } + init_completion(&vop->dsp_hold_completion); crtc->port = port; vop->pipe = drm_crtc_index(crtc); rockchip_register_crtc_funcs(drm_dev, &private_crtc_funcs, vop->pipe); -- 1.7.9.5
WARNING: multiple messages have this Message-ID (diff)
From: Mark Yao <mark.yao@rock-chips.com> To: David Airlie <airlied@linux.ie>, Daniel Vetter <daniel@ffwll.ch>, Rob Clark <robdclark@gmail.com>, Philipp Zabel <p.zabel@pengutronix.de>, Daniel Kurtz <djkurtz@chromium.org>, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-rockchip@lists.infradead.org Cc: Mark Yao <mark.yao@rock-chips.com> Subject: [PATCH v5] drm/rockchip: vop: power off until vop standby take effect Date: Wed, 4 Feb 2015 13:10:31 +0800 [thread overview] Message-ID: <1423026631-9318-1-git-send-email-mark.yao@rock-chips.com> (raw) Vop standby will take effect at end of current frame, if dsp_hold_valid_irq happen, it means vop standby complete. we must wait standby complete when we want to disable aclk, if not, memory bus maybe dead. Reviewed-by: Heiko Stuebner <heiko@sntech.de> Reviewed-by: Daniel Kurtz <djkurtz@chromium.org> Signed-off-by: Mark Yao <mark.yao@rock-chips.com> --- Changes in v5: - reuse WARN_ON with if (cond) so that WARN_ON have a chance to output. Changes in v4: - fix comment syntax error Changes in v3: - if vop write vop regs when vop clocks is disabled, WARN_ON maybe have no chance to do crash dump, so reuse BUG_ON. - dsp hold irq only happen when standby bit 0->1 take effect, no need to do completion check. Changes in v2: - use WARN_ON instead of BUG_ON. drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 75 ++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index fb25836..20fa8a1 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -89,6 +89,7 @@ struct vop { /* mutex vsync_ work */ struct mutex vsync_mutex; bool vsync_work_pending; + struct completion dsp_hold_completion; const struct vop_data *data; @@ -382,6 +383,36 @@ static bool is_alpha_support(uint32_t format) } } +static void vop_dsp_hold_valid_irq_enable(struct vop *vop) +{ + unsigned long flags; + + if (WARN_ON(!vop->is_enabled)) + return; + + spin_lock_irqsave(&vop->irq_lock, flags); + + vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK, + DSP_HOLD_VALID_INTR_EN(1)); + + spin_unlock_irqrestore(&vop->irq_lock, flags); +} + +static void vop_dsp_hold_valid_irq_disable(struct vop *vop) +{ + unsigned long flags; + + if (WARN_ON(!vop->is_enabled)) + return; + + spin_lock_irqsave(&vop->irq_lock, flags); + + vop_mask_write(vop, INTR_CTRL0, DSP_HOLD_VALID_INTR_MASK, + DSP_HOLD_VALID_INTR_EN(0)); + + spin_unlock_irqrestore(&vop->irq_lock, flags); +} + static void vop_enable(struct drm_crtc *crtc) { struct vop *vop = to_vop(crtc); @@ -454,26 +485,36 @@ static void vop_disable(struct drm_crtc *crtc) drm_vblank_off(crtc->dev, vop->pipe); - disable_irq(vop->irq); - /* - * TODO: Since standby doesn't take effect until the next vblank, - * when we turn off dclk below, the vop is probably still active. + * Vop standby will take effect at end of current frame, + * if dsp hold valid irq happen, it means standby complete. + * + * we must wait standby complete when we want to disable aclk, + * if not, memory bus maybe dead. */ + reinit_completion(&vop->dsp_hold_completion); + vop_dsp_hold_valid_irq_enable(vop); + spin_lock(&vop->reg_lock); VOP_CTRL_SET(vop, standby, 1); spin_unlock(&vop->reg_lock); + wait_for_completion(&vop->dsp_hold_completion); + + vop_dsp_hold_valid_irq_disable(vop); + + disable_irq(vop->irq); + vop->is_enabled = false; + /* - * disable dclk to stop frame scan, so we can safely detach iommu, + * vop standby complete, so iommu detach is safe. */ - clk_disable(vop->dclk); - rockchip_drm_dma_detach_device(vop->drm_dev, vop->dev); + clk_disable(vop->dclk); clk_disable(vop->aclk); clk_disable(vop->hclk); } @@ -1086,6 +1127,7 @@ static irqreturn_t vop_isr(int irq, void *data) struct vop *vop = data; uint32_t intr0_reg, active_irqs; unsigned long flags; + int ret = IRQ_NONE; /* * INTR_CTRL0 register has interrupt status, enable and clear bits, we @@ -1104,15 +1146,23 @@ static irqreturn_t vop_isr(int irq, void *data) if (!active_irqs) return IRQ_NONE; - /* Only Frame Start Interrupt is enabled; other irqs are spurious. */ - if (!(active_irqs & FS_INTR)) { - DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs); - return IRQ_NONE; + if (active_irqs & DSP_HOLD_VALID_INTR) { + complete(&vop->dsp_hold_completion); + active_irqs &= ~DSP_HOLD_VALID_INTR; + ret = IRQ_HANDLED; } - drm_handle_vblank(vop->drm_dev, vop->pipe); + if (active_irqs & FS_INTR) { + drm_handle_vblank(vop->drm_dev, vop->pipe); + active_irqs &= ~FS_INTR; + ret = (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED; + } - return (vop->vsync_work_pending) ? IRQ_WAKE_THREAD : IRQ_HANDLED; + /* Unhandled irqs are spurious. */ + if (active_irqs) + DRM_ERROR("Unknown VOP IRQs: %#02x\n", active_irqs); + + return ret; } static int vop_create_crtc(struct vop *vop) @@ -1194,6 +1244,7 @@ static int vop_create_crtc(struct vop *vop) goto err_cleanup_crtc; } + init_completion(&vop->dsp_hold_completion); crtc->port = port; vop->pipe = drm_crtc_index(crtc); rockchip_register_crtc_funcs(drm_dev, &private_crtc_funcs, vop->pipe); -- 1.7.9.5 _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
next reply other threads:[~2015-02-04 5:11 UTC|newest] Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top 2015-02-04 5:10 Mark Yao [this message] 2015-02-04 5:10 ` [PATCH v5] drm/rockchip: vop: power off until vop standby take effect Mark Yao
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1423026631-9318-1-git-send-email-mark.yao@rock-chips.com \ --to=mark.yao@rock-chips.com \ --cc=airlied@linux.ie \ --cc=daniel@ffwll.ch \ --cc=djkurtz@chromium.org \ --cc=dri-devel@lists.freedesktop.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux-rockchip@lists.infradead.org \ --cc=p.zabel@pengutronix.de \ --cc=robdclark@gmail.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.