/* * Vblank IRQ * * The hardware is a bit tilted: the line stays high after clearing * the vblank IRQ, firing many more interrupts. We counter this * by toggling the IRQ back and forth from firing at vblank and * firing at start of active image, which works around the problem * since those occur strictly in sequence, and we get two IRQs for each * frame, one at start of Vblank (that we make call into the CRTC) and * another one at the start of the image (that we discard).
*/ if (stat & TVE200_INT_V_STATUS) {
val = readl(priv->regs + TVE200_CTRL); /* We have an actual start of vsync */ if (!(val & TVE200_VSTSTYPE_BITS)) {
drm_crtc_handle_vblank(&priv->pipe.crtc); /* Toggle trigger to start of active image */
val |= TVE200_VSTSTYPE_VAI;
} else { /* Toggle trigger back to start of vsync */
val &= ~TVE200_VSTSTYPE_BITS;
}
writel(val, priv->regs + TVE200_CTRL);
} else
dev_err(priv->drm->dev, "stray IRQ %08x\n", stat);
/* Clear the interrupt once done */
writel(stat, priv->regs + TVE200_INT_CLR);
if (fb) {
u32 offset = drm_fb_dma_get_gem_addr(fb, pstate, 0);
/* FB base address must be dword aligned. */ if (offset & 3) {
DRM_DEBUG_KMS("FB not 32-bit aligned\n"); return -EINVAL;
}
/* * There's no pitch register, the mode's hdisplay * controls this.
*/ if (fb->pitches[0] != mode->hdisplay * fb->format->cpp[0]) {
DRM_DEBUG_KMS("can't handle pitches\n"); return -EINVAL;
}
/* * We can't change the FB format in a flicker-free * manner (and only update it during CRTC enable).
*/ if (old_fb && old_fb->format != fb->format)
cstate->mode_changed = true;
}
/* Reset the TVE200 and wait for it to come back online */
writel(TVE200_CTRL_4_RESET, priv->regs + TVE200_CTRL_4); for (retries = 0; retries < 5; retries++) {
usleep_range(30000, 50000); if (readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET) continue; else break;
} if (retries == 5 &&
readl(priv->regs + TVE200_CTRL_4) & TVE200_CTRL_4_RESET) {
dev_err(drm->dev, "can't get hardware out of reset\n"); return;
}
if (fb) { /* For RGB, the Y component is used as base address */
writel(drm_fb_dma_get_gem_addr(fb, pstate, 0),
priv->regs + TVE200_Y_FRAME_BASE_ADDR);
/* For three plane YUV we need two more addresses */ if (fb->format->format == DRM_FORMAT_YUV420) {
writel(drm_fb_dma_get_gem_addr(fb, pstate, 1),
priv->regs + TVE200_U_FRAME_BASE_ADDR);
writel(drm_fb_dma_get_gem_addr(fb, pstate, 2),
priv->regs + TVE200_V_FRAME_BASE_ADDR);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.