int intel_configure_dsi_pll(struct intel_dsi *intel_dsi,
		struct drm_display_mode *mode)
{
	struct drm_i915_private *dev_priv =
			intel_dsi->base.base.dev->dev_private;
	int ret;
	struct dsi_mnp dsi_mnp;
	u32 dsi_clk;

	DRM_DEBUG_KMS("\n");

	if (intel_dsi->dsi_clock_freq)
		dsi_clk = intel_dsi->dsi_clock_freq;
	else
		get_dsi_clk(intel_dsi, mode, &dsi_clk);

	ret = dsi_calc_mnp(dsi_clk, &dsi_mnp);
	/*ret = mnp_from_clk_table(dsi_clk, &dsi_mnp);*/

	if (ret != 0)
		return ret;

	dsi_mnp.dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL;

	DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n",
			dsi_mnp.dsi_pll_div, dsi_mnp.dsi_pll_ctrl);

	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0);
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_mnp.dsi_pll_div);
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_mnp.dsi_pll_ctrl);

	return 0;
}
예제 #2
0
void vlv_dsi_pll_enable(struct intel_encoder *encoder,
			const struct intel_crtc_state *config)
{
	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);

	DRM_DEBUG_KMS("\n");

	mutex_lock(&dev_priv->sb_lock);

	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0);
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, config->dsi_pll.div);
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL,
		      config->dsi_pll.ctrl & ~DSI_PLL_VCO_EN);

	/* wait at least 0.5 us after ungating before enabling VCO,
	 * allow hrtimer subsystem optimization by relaxing timing
	 */
	usleep_range(10, 50);

	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, config->dsi_pll.ctrl);

	if (wait_for(vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL) &
						DSI_PLL_LOCK, 20)) {

		mutex_unlock(&dev_priv->sb_lock);
		DRM_ERROR("DSI PLL lock failed\n");
		return;
	}
	mutex_unlock(&dev_priv->sb_lock);

	DRM_DEBUG_KMS("DSI PLL locked\n");
}
static void intel_configure_dsi_pll_reg(struct drm_i915_private *dev_priv,
				struct intel_dsi_mnp *intel_dsi_mnp,
				struct intel_dsi *intel_dsi,
						bool divider_update_only)
{
	u32 dsi_pll_ctrl = 0, dsi_pll_div = 0;

	if (divider_update_only) {
		dsi_pll_ctrl = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
		dsi_pll_ctrl &= ~DSI_PLL_P1_POST_DIV_MASK;
	} else {
		vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, 0);
		dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI0_DSIPLL;
	}

	if (intel_dsi->dual_link)
		dsi_pll_ctrl |= DSI_PLL_CLK_GATE_DSI1_DSIPLL;

	dsi_pll_ctrl |= (1 <<
			(DSI_PLL_P1_POST_DIV_SHIFT + intel_dsi_mnp->p - 2));
	dsi_pll_div = ((intel_dsi_mnp->n - 1) <<
			DSI_PLL_N1_DIV_SHIFT) | intel_dsi_mnp->m;

	DRM_DEBUG_KMS("dsi pll div %08x, ctrl %08x\n",
					dsi_pll_div, dsi_pll_ctrl);

	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_DIVIDER, dsi_pll_div);
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, dsi_pll_ctrl);
}
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;
}
예제 #5
0
static void vlv_cck_modify(struct drm_i915_private *dev_priv, u32 reg, u32 val,
			   u32 mask)
{
	u32 tmp = vlv_cck_read(dev_priv, reg);
	tmp &= ~mask;
	tmp |= val;
	vlv_cck_write(dev_priv, reg, tmp);
}
예제 #6
0
void vlv_dsi_pll_disable(struct intel_encoder *encoder)
{
	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
	u32 tmp;

	DRM_DEBUG_KMS("\n");

	mutex_lock(&dev_priv->sb_lock);

	tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
	tmp &= ~DSI_PLL_VCO_EN;
	tmp |= DSI_PLL_LDO_GATE;
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp);

	mutex_unlock(&dev_priv->sb_lock);
}
int intel_disable_dsi_pll(struct intel_dsi *intel_dsi)
{
	struct drm_i915_private *dev_priv = intel_dsi->base.base.dev->dev_private;
	u32 tmp;

	DRM_DEBUG_KMS("\n");

	mutex_lock(&dev_priv->dpio_lock);
	tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
	tmp &= ~DSI_PLL_VCO_EN;
	tmp |= DSI_PLL_LDO_GATE;
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp);
	if ((I915_READ(PIPECONF(PIPE_A)) & (PIPECONF_ENABLE == 0)) &&
		(I915_READ(PIPECONF(PIPE_B)) & (PIPECONF_ENABLE == 0)))
		I915_WRITE_BITS(_DPLL_A, 0x00000000, DPLL_REFA_CLK_ENABLE_VLV);

	mutex_unlock(&dev_priv->dpio_lock);

	return 0;
}
int intel_enable_dsi_pll(struct intel_dsi *intel_dsi)
{
	struct drm_encoder *encoder = &(intel_dsi->base.base);
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
	struct drm_display_mode *mode = &intel_crtc->config.adjusted_mode;
	struct drm_i915_private *dev_priv =
					intel_dsi->base.base.dev->dev_private;
	u32 tmp;

	DRM_DEBUG_KMS("\n");
	if ((I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED)) {
		DRM_DEBUG_KMS("DSI PLL Already locked\n");
		return 0;
	}

	mutex_lock(&dev_priv->dpio_lock);
	intel_configure_dsi_pll(intel_dsi, mode);

	/* wait at least 0.5 us after ungating before enabling VCO */
	usleep_range(1, 10);

	tmp = vlv_cck_read(dev_priv, CCK_REG_DSI_PLL_CONTROL);
	tmp |= DSI_PLL_VCO_EN;
	/* enable DPLL ref clock */
	I915_WRITE_BITS(_DPLL_A, DPLL_REFA_CLK_ENABLE_VLV,
						DPLL_REFA_CLK_ENABLE_VLV);
	udelay(1000);
	vlv_cck_write(dev_priv, CCK_REG_DSI_PLL_CONTROL, tmp);

	mutex_unlock(&dev_priv->dpio_lock);

	if (wait_for(I915_READ(PIPECONF(PIPE_A)) & PIPECONF_DSI_PLL_LOCKED, 20)) {
		DRM_ERROR("DSI PLL lock failed\n");
		return -1;
	}

	DRM_DEBUG_KMS("DSI PLL locked\n");
	return 0;
}