Commit b70ad01a authored by José Roberto de Souza's avatar José Roberto de Souza
Browse files

drm/i915/display/tgl+: Implement new PLL programming step



A new programming step was added to combo and TC PLL sequences.
If override_AFC_startup is set in VBT, driver should overwrite
AFC_startup value to 0x0 or 0x7 in PLL's div0 register.

The current understating is that only TGL needs this and all other
display 12 and newer platforms will have a older VBT or a newer VBT
with override_AFC_startup set to 0 but in any case there is a
drm_warn_on_once() to let us know if this is not true.

v2:
- specification updated, now AFC can be override to 0x0 or 0x7
- not using a union for div0 (Imre)
- following previous wrong vbt naming: bits instead of bytes (Imre)

BSpec: 49204
BSpec: 20122
BSpec: 49968
BSpec: 71360
Cc: Imre Deak <imre.deak@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: default avatarImre Deak <imre.deak@intel.com>
Signed-off-by: default avatarJosé Roberto de Souza <jose.souza@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220216134059.25348-1-jose.souza@intel.com
parent ed0ccf34
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -596,6 +596,12 @@ parse_general_features(struct drm_i915_private *i915,
	} else {
	} else {
		i915->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
		i915->vbt.orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
	}
	}

	if (bdb->version >= 249 && general->afc_startup_config) {
		i915->vbt.override_afc_startup = true;
		i915->vbt.override_afc_startup_val = general->afc_startup_config == 0x1 ? 0x0 : 0x7;
	}

	drm_dbg_kms(&i915->drm,
	drm_dbg_kms(&i915->drm,
		    "BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
		    "BDB_GENERAL_FEATURES int_tv_support %d int_crt_support %d lvds_use_ssc %d lvds_ssc_freq %d display_clock_mode %d fdi_rx_polarity_inverted %d\n",
		    i915->vbt.int_tv_support,
		    i915->vbt.int_tv_support,
+1 −0
Original line number Original line Diff line number Diff line
@@ -6314,6 +6314,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
		PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
		PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1);
		PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);
		PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2);
		PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0);
		PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0);
		PIPE_CONF_CHECK_X(dpll_hw_state.div0);
		PIPE_CONF_CHECK_X(dpll_hw_state.ebb0);
		PIPE_CONF_CHECK_X(dpll_hw_state.ebb0);
		PIPE_CONF_CHECK_X(dpll_hw_state.ebb4);
		PIPE_CONF_CHECK_X(dpll_hw_state.ebb4);
		PIPE_CONF_CHECK_X(dpll_hw_state.pll0);
		PIPE_CONF_CHECK_X(dpll_hw_state.pll0);
+1 −0
Original line number Original line Diff line number Diff line
@@ -1014,6 +1014,7 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
		seq_printf(m, " wrpll:   0x%08x\n", pll->state.hw_state.wrpll);
		seq_printf(m, " wrpll:   0x%08x\n", pll->state.hw_state.wrpll);
		seq_printf(m, " cfgcr0:  0x%08x\n", pll->state.hw_state.cfgcr0);
		seq_printf(m, " cfgcr0:  0x%08x\n", pll->state.hw_state.cfgcr0);
		seq_printf(m, " cfgcr1:  0x%08x\n", pll->state.hw_state.cfgcr1);
		seq_printf(m, " cfgcr1:  0x%08x\n", pll->state.hw_state.cfgcr1);
		seq_printf(m, " div0:    0x%08x\n", pll->state.hw_state.div0);
		seq_printf(m, " mg_refclkin_ctl:        0x%08x\n",
		seq_printf(m, " mg_refclkin_ctl:        0x%08x\n",
			   pll->state.hw_state.mg_refclkin_ctl);
			   pll->state.hw_state.mg_refclkin_ctl);
		seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
		seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
+31 −13
Original line number Original line Diff line number Diff line
@@ -2748,6 +2748,9 @@ static void icl_calc_dpll_state(struct drm_i915_private *i915,
		pll_state->cfgcr1 |= TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL;
		pll_state->cfgcr1 |= TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL;
	else
	else
		pll_state->cfgcr1 |= DPLL_CFGCR1_CENTRAL_FREQ_8400;
		pll_state->cfgcr1 |= DPLL_CFGCR1_CENTRAL_FREQ_8400;

	if (i915->vbt.override_afc_startup)
		pll_state->div0 = TGL_DPLL0_DIV0_AFC_STARTUP(i915->vbt.override_afc_startup_val);
}
}


static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
@@ -2949,6 +2952,11 @@ static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
					 DKL_PLL_DIV0_PROP_COEFF(prop_coeff) |
					 DKL_PLL_DIV0_PROP_COEFF(prop_coeff) |
					 DKL_PLL_DIV0_FBPREDIV(m1div) |
					 DKL_PLL_DIV0_FBPREDIV(m1div) |
					 DKL_PLL_DIV0_FBDIV_INT(m2div_int);
					 DKL_PLL_DIV0_FBDIV_INT(m2div_int);
		if (dev_priv->vbt.override_afc_startup) {
			u8 val = dev_priv->vbt.override_afc_startup_val;

			pll_state->mg_pll_div0 |= DKL_PLL_DIV0_AFC_STARTUP(val);
		}


		pll_state->mg_pll_div1 = DKL_PLL_DIV1_IREF_TRIM(iref_trim) |
		pll_state->mg_pll_div1 = DKL_PLL_DIV1_IREF_TRIM(iref_trim) |
					 DKL_PLL_DIV1_TDC_TARGET_CNT(tdc_targetcnt);
					 DKL_PLL_DIV1_TDC_TARGET_CNT(tdc_targetcnt);
@@ -3448,10 +3456,10 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
		MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
		MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;


	hw_state->mg_pll_div0 = intel_de_read(dev_priv, DKL_PLL_DIV0(tc_port));
	hw_state->mg_pll_div0 = intel_de_read(dev_priv, DKL_PLL_DIV0(tc_port));
	hw_state->mg_pll_div0 &= (DKL_PLL_DIV0_INTEG_COEFF_MASK |
	val = DKL_PLL_DIV0_MASK;
				  DKL_PLL_DIV0_PROP_COEFF_MASK |
	if (dev_priv->vbt.override_afc_startup)
				  DKL_PLL_DIV0_FBPREDIV_MASK |
		val |= DKL_PLL_DIV0_AFC_STARTUP_MASK;
				  DKL_PLL_DIV0_FBDIV_INT_MASK);
	hw_state->mg_pll_div0 &= val;


	hw_state->mg_pll_div1 = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port));
	hw_state->mg_pll_div1 = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port));
	hw_state->mg_pll_div1 &= (DKL_PLL_DIV1_IREF_TRIM_MASK |
	hw_state->mg_pll_div1 &= (DKL_PLL_DIV1_IREF_TRIM_MASK |
@@ -3513,6 +3521,10 @@ static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
						 TGL_DPLL_CFGCR0(id));
						 TGL_DPLL_CFGCR0(id));
		hw_state->cfgcr1 = intel_de_read(dev_priv,
		hw_state->cfgcr1 = intel_de_read(dev_priv,
						 TGL_DPLL_CFGCR1(id));
						 TGL_DPLL_CFGCR1(id));
		if (dev_priv->vbt.override_afc_startup) {
			hw_state->div0 = intel_de_read(dev_priv, TGL_DPLL0_DIV0(id));
			hw_state->div0 &= TGL_DPLL0_DIV0_AFC_STARTUP_MASK;
		}
	} else {
	} else {
		if (IS_JSL_EHL(dev_priv) && id == DPLL_ID_EHL_DPLL4) {
		if (IS_JSL_EHL(dev_priv) && id == DPLL_ID_EHL_DPLL4) {
			hw_state->cfgcr0 = intel_de_read(dev_priv,
			hw_state->cfgcr0 = intel_de_read(dev_priv,
@@ -3554,7 +3566,7 @@ static void icl_dpll_write(struct drm_i915_private *dev_priv,
{
{
	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
	struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
	const enum intel_dpll_id id = pll->info->id;
	const enum intel_dpll_id id = pll->info->id;
	i915_reg_t cfgcr0_reg, cfgcr1_reg;
	i915_reg_t cfgcr0_reg, cfgcr1_reg, div0_reg = INVALID_MMIO_REG;


	if (IS_ALDERLAKE_S(dev_priv)) {
	if (IS_ALDERLAKE_S(dev_priv)) {
		cfgcr0_reg = ADLS_DPLL_CFGCR0(id);
		cfgcr0_reg = ADLS_DPLL_CFGCR0(id);
@@ -3568,6 +3580,7 @@ static void icl_dpll_write(struct drm_i915_private *dev_priv,
	} else if (DISPLAY_VER(dev_priv) >= 12) {
	} else if (DISPLAY_VER(dev_priv) >= 12) {
		cfgcr0_reg = TGL_DPLL_CFGCR0(id);
		cfgcr0_reg = TGL_DPLL_CFGCR0(id);
		cfgcr1_reg = TGL_DPLL_CFGCR1(id);
		cfgcr1_reg = TGL_DPLL_CFGCR1(id);
		div0_reg = TGL_DPLL0_DIV0(id);
	} else {
	} else {
		if (IS_JSL_EHL(dev_priv) && id == DPLL_ID_EHL_DPLL4) {
		if (IS_JSL_EHL(dev_priv) && id == DPLL_ID_EHL_DPLL4) {
			cfgcr0_reg = ICL_DPLL_CFGCR0(4);
			cfgcr0_reg = ICL_DPLL_CFGCR0(4);
@@ -3580,6 +3593,12 @@ static void icl_dpll_write(struct drm_i915_private *dev_priv,


	intel_de_write(dev_priv, cfgcr0_reg, hw_state->cfgcr0);
	intel_de_write(dev_priv, cfgcr0_reg, hw_state->cfgcr0);
	intel_de_write(dev_priv, cfgcr1_reg, hw_state->cfgcr1);
	intel_de_write(dev_priv, cfgcr1_reg, hw_state->cfgcr1);
	drm_WARN_ON_ONCE(&dev_priv->drm, dev_priv->vbt.override_afc_startup &&
			 !i915_mmio_reg_valid(div0_reg));
	if (dev_priv->vbt.override_afc_startup &&
	    i915_mmio_reg_valid(div0_reg))
		intel_de_rmw(dev_priv, div0_reg, TGL_DPLL0_DIV0_AFC_STARTUP_MASK,
			     hw_state->div0);
	intel_de_posting_read(dev_priv, cfgcr1_reg);
	intel_de_posting_read(dev_priv, cfgcr1_reg);
}
}


@@ -3667,13 +3686,11 @@ static void dkl_pll_write(struct drm_i915_private *dev_priv,
	val |= hw_state->mg_clktop2_hsclkctl;
	val |= hw_state->mg_clktop2_hsclkctl;
	intel_de_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), val);
	intel_de_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), val);


	val = intel_de_read(dev_priv, DKL_PLL_DIV0(tc_port));
	val = DKL_PLL_DIV0_MASK;
	val &= ~(DKL_PLL_DIV0_INTEG_COEFF_MASK |
	if (dev_priv->vbt.override_afc_startup)
		 DKL_PLL_DIV0_PROP_COEFF_MASK |
		val |= DKL_PLL_DIV0_AFC_STARTUP_MASK;
		 DKL_PLL_DIV0_FBPREDIV_MASK |
	intel_de_rmw(dev_priv, DKL_PLL_DIV0(tc_port), val,
		 DKL_PLL_DIV0_FBDIV_INT_MASK);
		     hw_state->mg_pll_div0);
	val |= hw_state->mg_pll_div0;
	intel_de_write(dev_priv, DKL_PLL_DIV0(tc_port), val);


	val = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port));
	val = intel_de_read(dev_priv, DKL_PLL_DIV1(tc_port));
	val &= ~(DKL_PLL_DIV1_IREF_TRIM_MASK |
	val &= ~(DKL_PLL_DIV1_IREF_TRIM_MASK |
@@ -3912,13 +3929,14 @@ static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
			      const struct intel_dpll_hw_state *hw_state)
			      const struct intel_dpll_hw_state *hw_state)
{
{
	drm_dbg_kms(&dev_priv->drm,
	drm_dbg_kms(&dev_priv->drm,
		    "dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, "
		    "dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, div0: 0x%x, "
		    "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
		    "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
		    "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
		    "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
		    "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
		    "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
		    "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
		    "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
		    "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n",
		    "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n",
		    hw_state->cfgcr0, hw_state->cfgcr1,
		    hw_state->cfgcr0, hw_state->cfgcr1,
		    hw_state->div0,
		    hw_state->mg_refclkin_ctl,
		    hw_state->mg_refclkin_ctl,
		    hw_state->mg_clktop2_coreclkctl1,
		    hw_state->mg_clktop2_coreclkctl1,
		    hw_state->mg_clktop2_hsclkctl,
		    hw_state->mg_clktop2_hsclkctl,
+3 −0
Original line number Original line Diff line number Diff line
@@ -208,6 +208,9 @@ struct intel_dpll_hw_state {
	/* icl */
	/* icl */
	u32 cfgcr0;
	u32 cfgcr0;


	/* tgl */
	u32 div0;

	/* bxt */
	/* bxt */
	u32 ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, pcsdw12;
	u32 ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, pcsdw12;


Loading