/* * intel_wait_for_pipe_off - wait for pipe to turn off * @dev: drm device * @pipe: pipe to wait for * * After disabling a pipe, we can't wait for vblank in the usual way, * spinning on the vblank interrupt status bit, since we won't actually * see an interrupt when the pipe is disabled. * * On Gen4 and above: * wait for the pipe register state bit to turn off * * Otherwise: * wait for the display line value to settle (it usually * ends up stopping at the start of the next frame). * */ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe) { struct drm_i915_private *dev_priv = dev->dev_private; if (INTEL_INFO(dev)->gen >= 4) { int reg = PIPECONF(pipe); /* Wait for the Pipe State to go off */ if (wait_for((I915_READ(reg) & I965_PIPECONF_ACTIVE) == 0, 100)) fprintf(stderr, "pipe_off wait timed out\n"); } else { u32 last_line; int reg = PIPEDSL(pipe); unsigned long timeout = msecs() + 100; /* Wait for the display line to settle */ do { last_line = I915_READ(reg) & DSL_LINEMASK; mdelay(5); } while (((I915_READ(reg) & DSL_LINEMASK) != last_line) && (timeout> msecs())); if ((msecs()> timeout)) fprintf(stderr, "pipe_off wait timed out\n"); } }
int intel_drrs_configure_dsi_pll(struct intel_dsi *intel_dsi, struct intel_dsi_mnp *intel_dsi_mnp) { struct drm_i915_private *dev_priv = intel_dsi->base.base.dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(intel_dsi->base.base.crtc); struct intel_mipi_drrs_work *work = dev_priv->drrs.mipi_drrs_work; u32 dsi_pll_ctrl, vactive; u32 dsl_offset = PIPEDSL(intel_crtc->pipe), dsl; unsigned long timeout; intel_configure_dsi_pll_reg(dev_priv, intel_dsi_mnp, intel_dsi, true); dsi_pll_ctrl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL); dsi_pll_ctrl &= (~DSI_PLL_VCO_EN); vactive = (I915_READ(VTOTAL(intel_crtc->pipe)) & VERTICAL_ACTIVE_DISPLAY_MASK) + 1; timeout = jiffies + msecs_to_jiffies(50); do { if (atomic_read(&work->abort_wait_loop) == 1) { DRM_DEBUG_KMS("Aborting the pll update\n"); return -EPERM; } dsl = (I915_READ(dsl_offset) & DSL_LINEMASK_GEN3); if (jiffies >= timeout) { DRM_ERROR("Timeout at waiting for Vblank\n"); return -ETIMEDOUT; } } while (dsl <= vactive); mutex_lock(&dev_priv->dpio_lock); /* Toggle the VCO_EN to bring in the new dividers values */ vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_pll_ctrl); dsi_pll_ctrl |= DSI_PLL_VCO_EN; vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_pll_ctrl); mutex_unlock(&dev_priv->dpio_lock); DRM_DEBUG_KMS("PLL Changed between DSL: %d, %d\n", dsl, I915_READ(dsl_offset) & DSL_LINEMASK_GEN3); if (wait_for(I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED, 20)) { DRM_ERROR("DSI PLL lock failed\n"); return -EACCES; } return 0; }