ANDROID: drm: kirin: remove wait for VACTIVE IRQ

For each display cycle, the Kirin960 display IP will generate a VACTIVE
interrupt followed by a VBLANK. During a FBIOPAN ioctl, the driver will then
wait for the first one to then wait for the second one. This is an issue when
the CPU load is too low: the wait_event() function might trigger a transition
to a deep sleep state and then, waking up from that state will take too much
time to catch the VBLANK interrupt on time, the difference between those two
interrupts being only 60 us.

  * Ideal case:                   ACT                VBL
                                   +                  +
                                   v                  v
                    ---> wait(ACT) +------> wait(VBL) +-->

  * Our case:                     ACT VBL        ACT VBL
                                   +   +          +   +
                                   v   v          v   v
                    ---> wait(ACT) +------> wait(VBL) +-->

The wait for VACTIVE IRQ can safely be removed: there is no hardware access
performed between the VACTIVE and the VBLANK IRQs.

This behavior has been introduced from 4.11 with the following patch:

    a3fbb53f4 drm/atomic: Wait for vblank whenever a plane is added to state.

Signed-off-by: Vincent Donnefort <vincent.donnefort@arm.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Bug: 146450171
Change-Id: I66e276c08f04257135c3d05483ce70c58d5070b6
This commit is contained in:
Vincent Donnefort 2019-03-26 13:29:55 -07:00 committed by Todd Kjos
parent 4dd668f97d
commit d586305741

View File

@ -74,9 +74,6 @@ struct dpe_hw_ctx {
bool power_on;
int irq;
wait_queue_head_t vactive0_end_wq;
u32 vactive0_end_flag;
struct drm_crtc *crtc;
u32 hdisplay;
@ -274,7 +271,7 @@ static void dpe_interrupt_unmask(struct dpe_hw_ctx *ctx)
writel(unmask, base + GLB_CPU_PDP_INT_MSK);
unmask = ~0;
unmask &= ~(BIT_VSYNC | BIT_VACTIVE0_END | BIT_LDI_UNFLOW);
unmask &= ~(BIT_VSYNC | BIT_LDI_UNFLOW);
writel(unmask, base + DPE_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK);
}
@ -765,36 +762,6 @@ const struct drm_crtc_funcs dpe_crtc_funcs = {
.disable_vblank = dpe_disable_vblank,
};
static int dpe_wait_for_complete(struct dpe_hw_ctx *ctx)
{
int ret = 0;
u32 times = 0;
u32 prev_vactive0_end = ctx->vactive0_end_flag;
REDO:
ret = wait_event_interruptible_timeout(ctx->vactive0_end_wq,
(prev_vactive0_end !=
ctx->vactive0_end_flag),
msecs_to_jiffies(300));
if (ret == -ERESTARTSYS) {
if (times < 50) {
times++;
mdelay(10);
goto REDO;
}
}
if (ret <= 0) {
DRM_ERROR("wait_for vactive0_end_flag timeout! ret=%d.\n", ret);
ret = -ETIMEDOUT;
} else {
ret = 0;
}
return ret;
}
static void dpe_unflow_handler(struct dpe_hw_ctx *ctx)
{
void __iomem *base = ctx->base;
@ -983,7 +950,6 @@ static void dpe_update_channel(struct kirin_plane *kplane,
dpe_unflow_handler(ctx);
dpe_enable_ldi(ctx);
dpe_wait_for_complete(ctx);
}
static void dpe_plane_atomic_update(struct drm_plane *plane,
@ -1088,11 +1054,6 @@ static irqreturn_t dpe_irq_handler(int irq, void *data)
isr_s2 &= ~(readl(base + DPE_LDI0_OFFSET + LDI_CPU_ITF_INT_MSK));
isr_s2_dpp &= ~(readl(base + DPE_DPP_OFFSET + DPP_INT_MSK));
if (isr_s2 & BIT_VACTIVE0_END) {
ctx->vactive0_end_flag++;
wake_up_interruptible_all(&ctx->vactive0_end_wq);
}
if (isr_s2 & BIT_VSYNC)
drm_crtc_handle_vblank(crtc);
@ -1193,9 +1154,6 @@ static void *dpe_hw_ctx_alloc(struct platform_device *pdev,
disable_irq(ctx->irq);
ctx->vactive0_end_flag = 0;
init_waitqueue_head(&ctx->vactive0_end_wq);
return ctx;
}