diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ddi.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_ddi.c | 440 | 
1 files changed, 228 insertions, 212 deletions
| diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 4079050f9d6c..ca705546a0ab 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -494,103 +494,58 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = {  	{ 0x2, 0x7F, 0x3F, 0x00, 0x00 },	/* 400   400      0.0   */  }; -struct icl_combo_phy_ddi_buf_trans { -	u32 dw2_swing_select; -	u32 dw2_swing_scalar; -	u32 dw4_scaling; -}; - -/* Voltage Swing Programming for VccIO 0.85V for DP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_85V[] = { -				/* Voltage mV  db    */ -	{ 0x2, 0x98, 0x0018 },	/* 400         0.0   */ -	{ 0x2, 0x98, 0x3015 },	/* 400         3.5   */ -	{ 0x2, 0x98, 0x6012 },	/* 400         6.0   */ -	{ 0x2, 0x98, 0x900F },	/* 400         9.5   */ -	{ 0xB, 0x70, 0x0018 },	/* 600         0.0   */ -	{ 0xB, 0x70, 0x3015 },	/* 600         3.5   */ -	{ 0xB, 0x70, 0x6012 },	/* 600         6.0   */ -	{ 0x5, 0x00, 0x0018 },	/* 800         0.0   */ -	{ 0x5, 0x00, 0x3015 },	/* 800         3.5   */ -	{ 0x6, 0x98, 0x0018 },	/* 1200        0.0   */ -}; - -/* FIXME - After table is updated in Bspec */ -/* Voltage Swing Programming for VccIO 0.85V for eDP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_85V[] = { -				/* Voltage mV  db    */ -	{ 0x0, 0x00, 0x00 },	/* 200         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 200         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         6.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 250         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 350         0.0   */ -}; - -/* Voltage Swing Programming for VccIO 0.95V for DP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_95V[] = { -				/* Voltage mV  db    */ -	{ 0x2, 0x98, 0x0018 },	/* 400         0.0   */ -	{ 0x2, 0x98, 0x3015 },	/* 400         3.5   */ -	{ 0x2, 0x98, 0x6012 },	/* 400         6.0   */ -	{ 0x2, 0x98, 0x900F },	/* 400         9.5   */ -	{ 0x4, 0x98, 0x0018 },	/* 600         0.0   */ -	{ 0x4, 0x98, 0x3015 },	/* 600         3.5   */ -	{ 0x4, 0x98, 0x6012 },	/* 600         6.0   */ -	{ 0x5, 0x76, 0x0018 },	/* 800         0.0   */ -	{ 0x5, 0x76, 0x3015 },	/* 800         3.5   */ -	{ 0x6, 0x98, 0x0018 },	/* 1200        0.0   */ +/* icl_combo_phy_ddi_translations */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2[] = { +						/* NT mV Trans mV db    */ +	{ 0xA, 0x35, 0x3F, 0x00, 0x00 },	/* 350   350      0.0   */ +	{ 0xA, 0x4F, 0x37, 0x00, 0x08 },	/* 350   500      3.1   */ +	{ 0xC, 0x71, 0x2F, 0x00, 0x10 },	/* 350   700      6.0   */ +	{ 0x6, 0x7F, 0x2B, 0x00, 0x14 },	/* 350   900      8.2   */ +	{ 0xA, 0x4C, 0x3F, 0x00, 0x00 },	/* 500   500      0.0   */ +	{ 0xC, 0x73, 0x34, 0x00, 0x0B },	/* 500   700      2.9   */ +	{ 0x6, 0x7F, 0x2F, 0x00, 0x10 },	/* 500   900      5.1   */ +	{ 0xC, 0x6C, 0x3C, 0x00, 0x03 },	/* 650   700      0.6   */ +	{ 0x6, 0x7F, 0x35, 0x00, 0x0A },	/* 600   900      3.5   */ +	{ 0x6, 0x7F, 0x3F, 0x00, 0x00 },	/* 900   900      0.0   */  }; -/* FIXME - After table is updated in Bspec */ -/* Voltage Swing Programming for VccIO 0.95V for eDP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_95V[] = { -				/* Voltage mV  db    */ -	{ 0x0, 0x00, 0x00 },	/* 200         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 200         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         6.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 250         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 350         0.0   */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2[] = { +						/* NT mV Trans mV db    */ +	{ 0x0, 0x7F, 0x3F, 0x00, 0x00 },	/* 200   200      0.0   */ +	{ 0x8, 0x7F, 0x38, 0x00, 0x07 },	/* 200   250      1.9   */ +	{ 0x1, 0x7F, 0x33, 0x00, 0x0C },	/* 200   300      3.5   */ +	{ 0x9, 0x7F, 0x31, 0x00, 0x0E },	/* 200   350      4.9   */ +	{ 0x8, 0x7F, 0x3F, 0x00, 0x00 },	/* 250   250      0.0   */ +	{ 0x1, 0x7F, 0x38, 0x00, 0x07 },	/* 250   300      1.6   */ +	{ 0x9, 0x7F, 0x35, 0x00, 0x0A },	/* 250   350      2.9   */ +	{ 0x1, 0x7F, 0x3F, 0x00, 0x00 },	/* 300   300      0.0   */ +	{ 0x9, 0x7F, 0x38, 0x00, 0x07 },	/* 300   350      1.3   */ +	{ 0x9, 0x7F, 0x3F, 0x00, 0x00 },	/* 350   350      0.0   */  }; -/* Voltage Swing Programming for VccIO 1.05V for DP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_1_05V[] = { -				/* Voltage mV  db    */ -	{ 0x2, 0x98, 0x0018 },	/* 400         0.0   */ -	{ 0x2, 0x98, 0x3015 },	/* 400         3.5   */ -	{ 0x2, 0x98, 0x6012 },	/* 400         6.0   */ -	{ 0x2, 0x98, 0x900F },	/* 400         9.5   */ -	{ 0x4, 0x98, 0x0018 },	/* 600         0.0   */ -	{ 0x4, 0x98, 0x3015 },	/* 600         3.5   */ -	{ 0x4, 0x98, 0x6012 },	/* 600         6.0   */ -	{ 0x5, 0x71, 0x0018 },	/* 800         0.0   */ -	{ 0x5, 0x71, 0x3015 },	/* 800         3.5   */ -	{ 0x6, 0x98, 0x0018 },	/* 1200        0.0   */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr3[] = { +						/* NT mV Trans mV db    */ +	{ 0xA, 0x35, 0x3F, 0x00, 0x00 },	/* 350   350      0.0   */ +	{ 0xA, 0x4F, 0x37, 0x00, 0x08 },	/* 350   500      3.1   */ +	{ 0xC, 0x71, 0x2F, 0x00, 0x10 },	/* 350   700      6.0   */ +	{ 0x6, 0x7F, 0x2B, 0x00, 0x14 },	/* 350   900      8.2   */ +	{ 0xA, 0x4C, 0x3F, 0x00, 0x00 },	/* 500   500      0.0   */ +	{ 0xC, 0x73, 0x34, 0x00, 0x0B },	/* 500   700      2.9   */ +	{ 0x6, 0x7F, 0x2F, 0x00, 0x10 },	/* 500   900      5.1   */ +	{ 0xC, 0x6C, 0x3C, 0x00, 0x03 },	/* 650   700      0.6   */ +	{ 0x6, 0x7F, 0x35, 0x00, 0x0A },	/* 600   900      3.5   */ +	{ 0x6, 0x7F, 0x3F, 0x00, 0x00 },	/* 900   900      0.0   */  }; -/* FIXME - After table is updated in Bspec */ -/* Voltage Swing Programming for VccIO 1.05V for eDP */ -static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_1_05V[] = { -				/* Voltage mV  db    */ -	{ 0x0, 0x00, 0x00 },	/* 200         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 200         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 200         6.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 250         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 250         4.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         0.0   */ -	{ 0x0, 0x00, 0x00 },	/* 300         1.5   */ -	{ 0x0, 0x00, 0x00 },	/* 350         0.0   */ +static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi[] = { +						/* NT mV Trans mV db    */ +	{ 0xA, 0x60, 0x3F, 0x00, 0x00 },	/* 450   450      0.0   */ +	{ 0xB, 0x73, 0x36, 0x00, 0x09 },	/* 450   650      3.2   */ +	{ 0x6, 0x7F, 0x31, 0x00, 0x0E },	/* 450   850      5.5   */ +	{ 0xB, 0x73, 0x3F, 0x00, 0x00 },	/* 650   650      0.0   ALS */ +	{ 0x6, 0x7F, 0x37, 0x00, 0x08 },	/* 650   850      2.3   */ +	{ 0x6, 0x7F, 0x3F, 0x00, 0x00 },	/* 850   850      0.0   */ +	{ 0x6, 0x7F, 0x35, 0x00, 0x0A },	/* 600   850      3.0   */  };  struct icl_mg_phy_ddi_buf_trans { @@ -871,43 +826,23 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)  	}  } -static const struct icl_combo_phy_ddi_buf_trans * +static const struct cnl_ddi_buf_trans *  icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port, -			int type, int *n_entries) +			int type, int rate, int *n_entries)  { -	u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK; - -	if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { -		switch (voltage) { -		case VOLTAGE_INFO_0_85V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V); -			return icl_combo_phy_ddi_translations_edp_0_85V; -		case VOLTAGE_INFO_0_95V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V); -			return icl_combo_phy_ddi_translations_edp_0_95V; -		case VOLTAGE_INFO_1_05V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V); -			return icl_combo_phy_ddi_translations_edp_1_05V; -		default: -			MISSING_CASE(voltage); -			return NULL; -		} -	} else { -		switch (voltage) { -		case VOLTAGE_INFO_0_85V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V); -			return icl_combo_phy_ddi_translations_dp_hdmi_0_85V; -		case VOLTAGE_INFO_0_95V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V); -			return icl_combo_phy_ddi_translations_dp_hdmi_0_95V; -		case VOLTAGE_INFO_1_05V: -			*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V); -			return icl_combo_phy_ddi_translations_dp_hdmi_1_05V; -		default: -			MISSING_CASE(voltage); -			return NULL; -		} +	if (type == INTEL_OUTPUT_HDMI) { +		*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi); +		return icl_combo_phy_ddi_translations_hdmi; +	} else if (rate > 540000 && type == INTEL_OUTPUT_EDP) { +		*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3); +		return icl_combo_phy_ddi_translations_edp_hbr3; +	} else if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { +		*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2); +		return icl_combo_phy_ddi_translations_edp_hbr2;  	} + +	*n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2); +	return icl_combo_phy_ddi_translations_dp_hbr2;  }  static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port) @@ -918,8 +853,8 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por  	if (IS_ICELAKE(dev_priv)) {  		if (intel_port_is_combophy(dev_priv, port)) -			icl_get_combo_buf_trans(dev_priv, port, -						INTEL_OUTPUT_HDMI, &n_entries); +			icl_get_combo_buf_trans(dev_priv, port, INTEL_OUTPUT_HDMI, +						0, &n_entries);  		else  			n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);  		default_entry = n_entries - 1; @@ -1039,7 +974,7 @@ static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv,  	DRM_ERROR("Timeout waiting for DDI BUF %c idle bit\n", port_name(port));  } -static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll) +static u32 hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)  {  	switch (pll->info->id) {  	case DPLL_ID_WRPLL1: @@ -1060,8 +995,8 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)  	}  } -static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder, -				       const struct intel_crtc_state *crtc_state) +static u32 icl_pll_to_ddi_clk_sel(struct intel_encoder *encoder, +				  const struct intel_crtc_state *crtc_state)  {  	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;  	int clock = crtc_state->port_clock; @@ -1069,10 +1004,11 @@ static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,  	switch (id) {  	default: +		/* +		 * DPLL_ID_ICL_DPLL0 and DPLL_ID_ICL_DPLL1 should not be used +		 * here, so do warn if this get passed in +		 */  		MISSING_CASE(id); -		/* fall through */ -	case DPLL_ID_ICL_DPLL0: -	case DPLL_ID_ICL_DPLL1:  		return DDI_CLK_SEL_NONE;  	case DPLL_ID_ICL_TBTPLL:  		switch (clock) { @@ -1308,8 +1244,8 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,  			       enum intel_dpll_id pll_id)  {  	i915_reg_t cfgcr1_reg, cfgcr2_reg; -	uint32_t cfgcr1_val, cfgcr2_val; -	uint32_t p0, p1, p2, dco_freq; +	u32 cfgcr1_val, cfgcr2_val; +	u32 p0, p1, p2, dco_freq;  	cfgcr1_reg = DPLL_CFGCR1(pll_id);  	cfgcr2_reg = DPLL_CFGCR2(pll_id); @@ -1361,14 +1297,17 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv,  	dco_freq += (((cfgcr1_val & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9) * 24 *  		1000) / 0x8000; +	if (WARN_ON(p0 == 0 || p1 == 0 || p2 == 0)) +		return 0; +  	return dco_freq / (p0 * p1 * p2 * 5);  }  int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv,  			enum intel_dpll_id pll_id)  { -	uint32_t cfgcr0, cfgcr1; -	uint32_t p0, p1, p2, dco_freq, ref_clock; +	u32 cfgcr0, cfgcr1; +	u32 p0, p1, p2, dco_freq, ref_clock;  	if (INTEL_GEN(dev_priv) >= 11) {  		cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(pll_id)); @@ -1453,16 +1392,17 @@ static int icl_calc_tbt_pll_link(struct drm_i915_private *dev_priv,  static int icl_calc_mg_pll_link(struct drm_i915_private *dev_priv,  				enum port port)  { +	enum tc_port tc_port = intel_port_to_tc(dev_priv, port);  	u32 mg_pll_div0, mg_clktop_hsclkctl;  	u32 m1, m2_int, m2_frac, div1, div2, refclk;  	u64 tmp;  	refclk = dev_priv->cdclk.hw.ref; -	mg_pll_div0 = I915_READ(MG_PLL_DIV0(port)); -	mg_clktop_hsclkctl = I915_READ(MG_CLKTOP2_HSCLKCTL(port)); +	mg_pll_div0 = I915_READ(MG_PLL_DIV0(tc_port)); +	mg_clktop_hsclkctl = I915_READ(MG_CLKTOP2_HSCLKCTL(tc_port)); -	m1 = I915_READ(MG_PLL_DIV1(port)) & MG_PLL_DIV1_FBPREDIV_MASK; +	m1 = I915_READ(MG_PLL_DIV1(tc_port)) & MG_PLL_DIV1_FBPREDIV_MASK;  	m2_int = mg_pll_div0 & MG_PLL_DIV0_FBDIV_INT_MASK;  	m2_frac = (mg_pll_div0 & MG_PLL_DIV0_FRACNEN_H) ?  		  (mg_pll_div0 & MG_PLL_DIV0_FBDIV_FRAC_MASK) >> @@ -1533,7 +1473,7 @@ static void icl_ddi_clock_get(struct intel_encoder *encoder,  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	enum port port = encoder->port;  	int link_clock = 0; -	uint32_t pll_id; +	u32 pll_id;  	pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll);  	if (intel_port_is_combophy(dev_priv, port)) { @@ -1558,7 +1498,7 @@ static void cnl_ddi_clock_get(struct intel_encoder *encoder,  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	int link_clock = 0; -	uint32_t cfgcr0; +	u32 cfgcr0;  	enum intel_dpll_id pll_id;  	pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll); @@ -1612,7 +1552,7 @@ static void skl_ddi_clock_get(struct intel_encoder *encoder,  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	int link_clock = 0; -	uint32_t dpll_ctl1; +	u32 dpll_ctl1;  	enum intel_dpll_id pll_id;  	pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll); @@ -1801,7 +1741,7 @@ void intel_ddi_set_vc_payload_alloc(const struct intel_crtc_state *crtc_state,  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; -	uint32_t temp; +	u32 temp;  	temp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder));  	if (state == true) @@ -1819,7 +1759,7 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state)  	enum pipe pipe = crtc->pipe;  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;  	enum port port = encoder->port; -	uint32_t temp; +	u32 temp;  	/* Enable TRANS_DDI_FUNC_CTL for the pipe to work in HDMI mode */  	temp = TRANS_DDI_FUNC_ENABLE; @@ -1880,7 +1820,7 @@ void intel_ddi_enable_transcoder_func(const struct intel_crtc_state *crtc_state)  			temp |= TRANS_DDI_MODE_SELECT_DVI;  		if (crtc_state->hdmi_scrambling) -			temp |= TRANS_DDI_HDMI_SCRAMBLING_MASK; +			temp |= TRANS_DDI_HDMI_SCRAMBLING;  		if (crtc_state->hdmi_high_tmds_clock_ratio)  			temp |= TRANS_DDI_HIGH_TMDS_CHAR_RATE;  	} else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) { @@ -1903,7 +1843,7 @@ void intel_ddi_disable_transcoder_func(const struct intel_crtc_state *crtc_state  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);  	enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;  	i915_reg_t reg = TRANS_DDI_FUNC_CTL(cpu_transcoder); -	uint32_t val = I915_READ(reg); +	u32 val = I915_READ(reg);  	val &= ~(TRANS_DDI_FUNC_ENABLE | TRANS_DDI_PORT_MASK | TRANS_DDI_DP_VC_PAYLOAD_ALLOC);  	val |= TRANS_DDI_PORT_NONE; @@ -1922,12 +1862,14 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,  {  	struct drm_device *dev = intel_encoder->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev); +	intel_wakeref_t wakeref;  	enum pipe pipe = 0;  	int ret = 0; -	uint32_t tmp; +	u32 tmp; -	if (WARN_ON(!intel_display_power_get_if_enabled(dev_priv, -						intel_encoder->power_domain))) +	wakeref = intel_display_power_get_if_enabled(dev_priv, +						     intel_encoder->power_domain); +	if (WARN_ON(!wakeref))  		return -ENXIO;  	if (WARN_ON(!intel_encoder->get_hw_state(intel_encoder, &pipe))) { @@ -1942,7 +1884,7 @@ int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,  		tmp &= ~TRANS_DDI_HDCP_SIGNALLING;  	I915_WRITE(TRANS_DDI_FUNC_CTL(pipe), tmp);  out: -	intel_display_power_put(dev_priv, intel_encoder->power_domain); +	intel_display_power_put(dev_priv, intel_encoder->power_domain, wakeref);  	return ret;  } @@ -1953,13 +1895,15 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)  	struct intel_encoder *encoder = intel_connector->encoder;  	int type = intel_connector->base.connector_type;  	enum port port = encoder->port; -	enum pipe pipe = 0;  	enum transcoder cpu_transcoder; -	uint32_t tmp; +	intel_wakeref_t wakeref; +	enum pipe pipe = 0; +	u32 tmp;  	bool ret; -	if (!intel_display_power_get_if_enabled(dev_priv, -						encoder->power_domain)) +	wakeref = intel_display_power_get_if_enabled(dev_priv, +						     encoder->power_domain); +	if (!wakeref)  		return false;  	if (!encoder->get_hw_state(encoder, &pipe)) { @@ -2001,7 +1945,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)  	}  out: -	intel_display_power_put(dev_priv, encoder->power_domain); +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);  	return ret;  } @@ -2012,6 +1956,7 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,  	struct drm_device *dev = encoder->base.dev;  	struct drm_i915_private *dev_priv = to_i915(dev);  	enum port port = encoder->port; +	intel_wakeref_t wakeref;  	enum pipe p;  	u32 tmp;  	u8 mst_pipe_mask; @@ -2019,8 +1964,9 @@ static void intel_ddi_get_encoder_pipes(struct intel_encoder *encoder,  	*pipe_mask = 0;  	*is_dp_mst = false; -	if (!intel_display_power_get_if_enabled(dev_priv, -						encoder->power_domain)) +	wakeref = intel_display_power_get_if_enabled(dev_priv, +						     encoder->power_domain); +	if (!wakeref)  		return;  	tmp = I915_READ(DDI_BUF_CTL(port)); @@ -2091,7 +2037,7 @@ out:  				  "(PHY_CTL %08x)\n", port_name(port), tmp);  	} -	intel_display_power_put(dev_priv, encoder->power_domain); +	intel_display_power_put(dev_priv, encoder->power_domain, wakeref);  }  bool intel_ddi_get_hw_state(struct intel_encoder *encoder, @@ -2188,7 +2134,7 @@ void intel_ddi_disable_pipe_clock(const struct intel_crtc_state *crtc_state)  }  static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv, -				enum port port, uint8_t iboost) +				enum port port, u8 iboost)  {  	u32 tmp; @@ -2207,7 +2153,7 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder,  	struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base);  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	enum port port = encoder->port; -	uint8_t iboost; +	u8 iboost;  	if (type == INTEL_OUTPUT_HDMI)  		iboost = dev_priv->vbt.ddi_port_info[port].hdmi_boost_level; @@ -2275,13 +2221,14 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,  u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); +	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);  	enum port port = encoder->port;  	int n_entries;  	if (IS_ICELAKE(dev_priv)) {  		if (intel_port_is_combophy(dev_priv, port))  			icl_get_combo_buf_trans(dev_priv, port, encoder->type, -						&n_entries); +						intel_dp->link_rate, &n_entries);  		else  			n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);  	} else if (IS_CANNONLAKE(dev_priv)) { @@ -2462,14 +2409,15 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,  }  static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv, -					 u32 level, enum port port, int type) +					u32 level, enum port port, int type, +					int rate)  { -	const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL; +	const struct cnl_ddi_buf_trans *ddi_translations = NULL;  	u32 n_entries, val;  	int ln;  	ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type, -						   &n_entries); +						   rate, &n_entries);  	if (!ddi_translations)  		return; @@ -2478,34 +2426,23 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,  		level = n_entries - 1;  	} -	/* Set PORT_TX_DW5 Rterm Sel to 110b. */ +	/* Set PORT_TX_DW5 */  	val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); -	val &= ~RTERM_SELECT_MASK; +	val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK | +		  TAP2_DISABLE | TAP3_DISABLE); +	val |= SCALING_MODE_SEL(0x2);  	val |= RTERM_SELECT(0x6); -	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val); - -	/* Program PORT_TX_DW5 */ -	val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); -	/* Set DisableTap2 and DisableTap3 if MIPI DSI -	 * Clear DisableTap2 and DisableTap3 for all other Ports -	 */ -	if (type == INTEL_OUTPUT_DSI) { -		val |= TAP2_DISABLE; -		val |= TAP3_DISABLE; -	} else { -		val &= ~TAP2_DISABLE; -		val &= ~TAP3_DISABLE; -	} +	val |= TAP3_DISABLE;  	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);  	/* Program PORT_TX_DW2 */  	val = I915_READ(ICL_PORT_TX_DW2_LN0(port));  	val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |  		 RCOMP_SCALAR_MASK); -	val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select); -	val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select); +	val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel); +	val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel);  	/* Program Rcomp scalar for every table entry */ -	val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar); +	val |= RCOMP_SCALAR(0x98);  	I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);  	/* Program PORT_TX_DW4 */ @@ -2514,9 +2451,17 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,  		val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));  		val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |  			 CURSOR_COEFF_MASK); -		val |= ddi_translations[level].dw4_scaling; +		val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1); +		val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2); +		val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);  		I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);  	} + +	/* Program PORT_TX_DW7 */ +	val = I915_READ(ICL_PORT_TX_DW7_LN0(port)); +	val &= ~N_SCALAR_MASK; +	val |= N_SCALAR(ddi_translations[level].dw7_n_scalar); +	I915_WRITE(ICL_PORT_TX_DW7_GRP(port), val);  }  static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder, @@ -2581,7 +2526,7 @@ static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,  	I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);  	/* 5. Program swing and de-emphasis */ -	icl_ddi_combo_vswing_program(dev_priv, level, port, type); +	icl_ddi_combo_vswing_program(dev_priv, level, port, type, rate);  	/* 6. Set training enable to trigger update */  	val = I915_READ(ICL_PORT_TX_DW5_LN0(port)); @@ -2722,7 +2667,7 @@ static void icl_ddi_vswing_sequence(struct intel_encoder *encoder,  		icl_mg_phy_ddi_vswing_sequence(encoder, link_clock, level);  } -static uint32_t translate_signal_level(int signal_levels) +static u32 translate_signal_level(int signal_levels)  {  	int i; @@ -2737,9 +2682,9 @@ static uint32_t translate_signal_level(int signal_levels)  	return 0;  } -static uint32_t intel_ddi_dp_level(struct intel_dp *intel_dp) +static u32 intel_ddi_dp_level(struct intel_dp *intel_dp)  { -	uint8_t train_set = intel_dp->train_set[0]; +	u8 train_set = intel_dp->train_set[0];  	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |  					 DP_TRAIN_PRE_EMPHASIS_MASK); @@ -2764,7 +2709,7 @@ u32 bxt_signal_levels(struct intel_dp *intel_dp)  	return 0;  } -uint32_t ddi_signal_levels(struct intel_dp *intel_dp) +u32 ddi_signal_levels(struct intel_dp *intel_dp)  {  	struct intel_digital_port *dport = dp_to_dig_port(intel_dp);  	struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); @@ -2778,8 +2723,8 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)  }  static inline -uint32_t icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv, -				   enum port port) +u32 icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv, +			      enum port port)  {  	if (intel_port_is_combophy(dev_priv, port)) {  		return ICL_DPCLKA_CFGCR0_DDI_CLK_OFF(port); @@ -2914,7 +2859,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	enum port port = encoder->port; -	uint32_t val; +	u32 val;  	const struct intel_shared_dpll *pll = crtc_state->shared_dpll;  	if (WARN_ON(!pll)) @@ -2925,7 +2870,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,  	if (IS_ICELAKE(dev_priv)) {  		if (!intel_port_is_combophy(dev_priv, port))  			I915_WRITE(DDI_CLK_SEL(port), -				   icl_pll_to_ddi_pll_sel(encoder, crtc_state)); +				   icl_pll_to_ddi_clk_sel(encoder, crtc_state));  	} else if (IS_CANNONLAKE(dev_priv)) {  		/* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */  		val = I915_READ(DPCLKA_CFGCR0); @@ -3349,7 +3294,8 @@ static void intel_ddi_post_disable_dp(struct intel_encoder *encoder,  	intel_edp_panel_vdd_on(intel_dp);  	intel_edp_panel_off(intel_dp); -	intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain); +	intel_display_power_put_unchecked(dev_priv, +					  dig_port->ddi_io_power_domain);  	intel_ddi_clk_disable(encoder);  } @@ -3369,7 +3315,8 @@ static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder,  	intel_disable_ddi_buf(encoder, old_crtc_state); -	intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain); +	intel_display_power_put_unchecked(dev_priv, +					  dig_port->ddi_io_power_domain);  	intel_ddi_clk_disable(encoder); @@ -3411,7 +3358,7 @@ void intel_ddi_fdi_post_disable(struct intel_encoder *encoder,  				const struct drm_connector_state *old_conn_state)  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); -	uint32_t val; +	u32 val;  	/*  	 * Bspec lists this as both step 13 (before DDI_BUF_CTL disable) @@ -3603,6 +3550,26 @@ static void intel_disable_ddi(struct intel_encoder *encoder,  		intel_disable_ddi_dp(encoder, old_crtc_state, old_conn_state);  } +static void intel_ddi_update_pipe_dp(struct intel_encoder *encoder, +				     const struct intel_crtc_state *crtc_state, +				     const struct drm_connector_state *conn_state) +{ +	struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + +	intel_psr_enable(intel_dp, crtc_state); +	intel_edp_drrs_enable(intel_dp, crtc_state); + +	intel_panel_update_backlight(encoder, crtc_state, conn_state); +} + +static void intel_ddi_update_pipe(struct intel_encoder *encoder, +				  const struct intel_crtc_state *crtc_state, +				  const struct drm_connector_state *conn_state) +{ +	if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) +		intel_ddi_update_pipe_dp(encoder, crtc_state, conn_state); +} +  static void intel_ddi_set_fia_lane_count(struct intel_encoder *encoder,  					 const struct intel_crtc_state *pipe_config,  					 enum port port) @@ -3671,8 +3638,8 @@ intel_ddi_post_pll_disable(struct intel_encoder *encoder,  	if (intel_crtc_has_dp_encoder(crtc_state) ||  	    intel_port_is_tc(dev_priv, encoder->port)) -		intel_display_power_put(dev_priv, -					intel_ddi_main_link_aux_domain(dig_port)); +		intel_display_power_put_unchecked(dev_priv, +						  intel_ddi_main_link_aux_domain(dig_port));  }  void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp) @@ -3681,7 +3648,7 @@ void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp)  	struct drm_i915_private *dev_priv =  		to_i915(intel_dig_port->base.base.dev);  	enum port port = intel_dig_port->base.port; -	uint32_t val; +	u32 val;  	bool wait = false;  	if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) { @@ -3793,8 +3760,7 @@ void intel_ddi_get_config(struct intel_encoder *encoder,  		if (intel_dig_port->infoframe_enabled(encoder, pipe_config))  			pipe_config->has_infoframe = true; -		if ((temp & TRANS_DDI_HDMI_SCRAMBLING_MASK) == -			TRANS_DDI_HDMI_SCRAMBLING_MASK) +		if (temp & TRANS_DDI_HDMI_SCRAMBLING)  			pipe_config->hdmi_scrambling = true;  		if (temp & TRANS_DDI_HIGH_TMDS_CHAR_RATE)  			pipe_config->hdmi_high_tmds_clock_ratio = true; @@ -3875,9 +3841,9 @@ intel_ddi_compute_output_type(struct intel_encoder *encoder,  	}  } -static bool intel_ddi_compute_config(struct intel_encoder *encoder, -				     struct intel_crtc_state *pipe_config, -				     struct drm_connector_state *conn_state) +static int intel_ddi_compute_config(struct intel_encoder *encoder, +				    struct intel_crtc_state *pipe_config, +				    struct drm_connector_state *conn_state)  {  	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);  	enum port port = encoder->port; @@ -3901,9 +3867,50 @@ static bool intel_ddi_compute_config(struct intel_encoder *encoder,  } +static void intel_ddi_encoder_suspend(struct intel_encoder *encoder) +{ +	struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); +	struct drm_i915_private *i915 = to_i915(encoder->base.dev); + +	intel_dp_encoder_suspend(encoder); + +	/* +	 * TODO: disconnect also from USB DP alternate mode once we have a +	 * way to handle the modeset restore in that mode during resume +	 * even if the sink has disappeared while being suspended. +	 */ +	if (dig_port->tc_legacy_port) +		icl_tc_phy_disconnect(i915, dig_port); +} + +static void intel_ddi_encoder_reset(struct drm_encoder *drm_encoder) +{ +	struct intel_digital_port *dig_port = enc_to_dig_port(drm_encoder); +	struct drm_i915_private *i915 = to_i915(drm_encoder->dev); + +	if (intel_port_is_tc(i915, dig_port->base.port)) +		intel_digital_port_connected(&dig_port->base); + +	intel_dp_encoder_reset(drm_encoder); +} + +static void intel_ddi_encoder_destroy(struct drm_encoder *encoder) +{ +	struct intel_digital_port *dig_port = enc_to_dig_port(encoder); +	struct drm_i915_private *i915 = to_i915(encoder->dev); + +	intel_dp_encoder_flush_work(encoder); + +	if (intel_port_is_tc(i915, dig_port->base.port)) +		icl_tc_phy_disconnect(i915, dig_port); + +	drm_encoder_cleanup(encoder); +	kfree(dig_port); +} +  static const struct drm_encoder_funcs intel_ddi_funcs = { -	.reset = intel_dp_encoder_reset, -	.destroy = intel_dp_encoder_destroy, +	.reset = intel_ddi_encoder_reset, +	.destroy = intel_ddi_encoder_destroy,  };  static struct intel_connector * @@ -4147,16 +4154,16 @@ intel_ddi_max_lanes(struct intel_digital_port *intel_dport)  void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)  { +	struct ddi_vbt_port_info *port_info = +		&dev_priv->vbt.ddi_port_info[port];  	struct intel_digital_port *intel_dig_port;  	struct intel_encoder *intel_encoder;  	struct drm_encoder *encoder;  	bool init_hdmi, init_dp, init_lspcon = false;  	enum pipe pipe; - -	init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || -		     dev_priv->vbt.ddi_port_info[port].supports_hdmi); -	init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp; +	init_hdmi = port_info->supports_dvi || port_info->supports_hdmi; +	init_dp = port_info->supports_dp;  	if (intel_bios_is_lspcon_present(dev_priv, port)) {  		/* @@ -4195,9 +4202,10 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)  	intel_encoder->pre_enable = intel_ddi_pre_enable;  	intel_encoder->disable = intel_disable_ddi;  	intel_encoder->post_disable = intel_ddi_post_disable; +	intel_encoder->update_pipe = intel_ddi_update_pipe;  	intel_encoder->get_hw_state = intel_ddi_get_hw_state;  	intel_encoder->get_config = intel_ddi_get_config; -	intel_encoder->suspend = intel_dp_encoder_suspend; +	intel_encoder->suspend = intel_ddi_encoder_suspend;  	intel_encoder->get_power_domains = intel_ddi_get_power_domains;  	intel_encoder->type = INTEL_OUTPUT_DDI;  	intel_encoder->power_domain = intel_port_to_power_domain(port); @@ -4216,6 +4224,10 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)  	intel_dig_port->max_lanes = intel_ddi_max_lanes(intel_dig_port);  	intel_dig_port->aux_ch = intel_bios_port_aux_ch(dev_priv, port); +	intel_dig_port->tc_legacy_port = intel_port_is_tc(dev_priv, port) && +					 !port_info->supports_typec_usb && +					 !port_info->supports_tbt; +  	switch (port) {  	case PORT_A:  		intel_dig_port->ddi_io_power_domain = @@ -4274,6 +4286,10 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)  	}  	intel_infoframe_init(intel_dig_port); + +	if (intel_port_is_tc(dev_priv, port)) +		intel_digital_port_connected(intel_encoder); +  	return;  err: | 
