Commit fb83f72c authored by Ville Syrjälä's avatar Ville Syrjälä
Browse files

drm/i915: Introduce .set_signal_levels() vfunc



Sort out some of the mess between intel_ddi.c intel_dp.c by
introducing a .set_signal_levels() vfunc.

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200420200610.31798-2-ville.syrjala@linux.intel.com


Reviewed-by: default avatarJosé Roberto de Souza <jose.souza@intel.com>
parent eee3f911
Loading
Loading
Loading
Loading
+59 −20
Original line number Diff line number Diff line
@@ -2661,38 +2661,66 @@ static u32 intel_ddi_dp_level(struct intel_dp *intel_dp)
	return translate_signal_level(intel_dp, signal_levels);
}

u32 bxt_signal_levels(struct intel_dp *intel_dp)
static void
tgl_set_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);
	struct intel_encoder *encoder = &dport->base;
	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
	int level = intel_ddi_dp_level(intel_dp);

	if (INTEL_GEN(dev_priv) >= 12)
	tgl_ddi_vswing_sequence(encoder, intel_dp->link_rate,
				level, encoder->type);
	else if (INTEL_GEN(dev_priv) >= 11)
}

static void
icl_set_signal_levels(struct intel_dp *intel_dp)
{
	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
	int level = intel_ddi_dp_level(intel_dp);

	icl_ddi_vswing_sequence(encoder, intel_dp->link_rate,
				level, encoder->type);
	else if (IS_CANNONLAKE(dev_priv))
}

static void
cnl_set_signal_levels(struct intel_dp *intel_dp)
{
	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
	int level = intel_ddi_dp_level(intel_dp);

	cnl_ddi_vswing_sequence(encoder, level, encoder->type);
	else
		bxt_ddi_vswing_sequence(encoder, level, encoder->type);
}

	return 0;
static void
bxt_set_signal_levels(struct intel_dp *intel_dp)
{
	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
	int level = intel_ddi_dp_level(intel_dp);

	bxt_ddi_vswing_sequence(encoder, level, encoder->type);
}

u32 ddi_signal_levels(struct intel_dp *intel_dp)
static void
hsw_set_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);
	struct intel_encoder *encoder = &dport->base;
	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
	int level = intel_ddi_dp_level(intel_dp);
	enum port port = encoder->port;
	u32 signal_levels;

	signal_levels = DDI_BUF_TRANS_SELECT(level);

	drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n",
		    signal_levels);

	intel_dp->DP &= ~DDI_BUF_EMP_MASK;
	intel_dp->DP |= signal_levels;

	if (IS_GEN9_BC(dev_priv))
		skl_ddi_set_iboost(encoder, level, encoder->type);

	return DDI_BUF_TRANS_SELECT(level);
	intel_de_write(dev_priv, DDI_BUF_CTL(port), intel_dp->DP);
	intel_de_posting_read(dev_priv, DDI_BUF_CTL(port));
}

static u32 icl_dpclka_cfgcr0_clk_off(struct drm_i915_private *dev_priv,
@@ -4436,6 +4464,17 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port)
		intel_ddi_prepare_link_retrain;
	intel_dig_port->dp.set_link_train = intel_ddi_set_link_train;

	if (INTEL_GEN(dev_priv) >= 12)
		intel_dig_port->dp.set_signal_levels = tgl_set_signal_levels;
	else if (INTEL_GEN(dev_priv) >= 11)
		intel_dig_port->dp.set_signal_levels = icl_set_signal_levels;
	else if (IS_CANNONLAKE(dev_priv))
		intel_dig_port->dp.set_signal_levels = cnl_set_signal_levels;
	else if (IS_GEN9_LP(dev_priv))
		intel_dig_port->dp.set_signal_levels = bxt_set_signal_levels;
	else
		intel_dig_port->dp.set_signal_levels = hsw_set_signal_levels;

	if (INTEL_GEN(dev_priv) < 12) {
		intel_dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port);
		intel_dig_port->dp.regs.dp_tp_status = DP_TP_STATUS(port);
+1 −0
Original line number Diff line number Diff line
@@ -1368,6 +1368,7 @@ struct intel_dp {
	/* This is called before a link training is starterd */
	void (*prepare_link_retrain)(struct intel_dp *intel_dp);
	void (*set_link_train)(struct intel_dp *intel_dp, u8 dp_train_pat);
	void (*set_signal_levels)(struct intel_dp *intel_dp);

	/* Displayport compliance testing */
	struct intel_dp_compliance compliance;
+89 −57
Original line number Diff line number Diff line
@@ -4013,7 +4013,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, u8 voltage_swing)
	}
}

static u32 vlv_signal_levels(struct intel_dp *intel_dp)
static void vlv_set_signal_levels(struct intel_dp *intel_dp)
{
	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
	unsigned long demph_reg_value, preemph_reg_value,
@@ -4041,7 +4041,7 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp)
			uniqtranscale_reg_value = 0x5598DA3A;
			break;
		default:
			return 0;
			return;
		}
		break;
	case DP_TRAIN_PRE_EMPH_LEVEL_1:
@@ -4060,7 +4060,7 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp)
			uniqtranscale_reg_value = 0x55ADDA3A;
			break;
		default:
			return 0;
			return;
		}
		break;
	case DP_TRAIN_PRE_EMPH_LEVEL_2:
@@ -4075,7 +4075,7 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp)
			uniqtranscale_reg_value = 0x55ADDA3A;
			break;
		default:
			return 0;
			return;
		}
		break;
	case DP_TRAIN_PRE_EMPH_LEVEL_3:
@@ -4086,20 +4086,18 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp)
			uniqtranscale_reg_value = 0x55ADDA3A;
			break;
		default:
			return 0;
			return;
		}
		break;
	default:
		return 0;
		return;
	}

	vlv_set_phy_signal_level(encoder, demph_reg_value, preemph_reg_value,
				 uniqtranscale_reg_value, 0);

	return 0;
}

static u32 chv_signal_levels(struct intel_dp *intel_dp)
static void chv_set_signal_levels(struct intel_dp *intel_dp)
{
	struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
	u32 deemph_reg_value, margin_reg_value;
@@ -4127,7 +4125,7 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp)
			uniq_trans_scale = true;
			break;
		default:
			return 0;
			return;
		}
		break;
	case DP_TRAIN_PRE_EMPH_LEVEL_1:
@@ -4145,7 +4143,7 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp)
			margin_reg_value = 154;
			break;
		default:
			return 0;
			return;
		}
		break;
	case DP_TRAIN_PRE_EMPH_LEVEL_2:
@@ -4159,7 +4157,7 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp)
			margin_reg_value = 154;
			break;
		default:
			return 0;
			return;
		}
		break;
	case DP_TRAIN_PRE_EMPH_LEVEL_3:
@@ -4169,21 +4167,18 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp)
			margin_reg_value = 154;
			break;
		default:
			return 0;
			return;
		}
		break;
	default:
		return 0;
		return;
	}

	chv_set_phy_signal_level(encoder, deemph_reg_value,
				 margin_reg_value, uniq_trans_scale);

	return 0;
}

static u32
g4x_signal_levels(u8 train_set)
static u32 g4x_signal_levels(u8 train_set)
{
	u32 signal_levels = 0;

@@ -4220,12 +4215,31 @@ g4x_signal_levels(u8 train_set)
	return signal_levels;
}

static void
g4x_set_signal_levels(struct intel_dp *intel_dp)
{
	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
	u8 train_set = intel_dp->train_set[0];
	u32 signal_levels;

	signal_levels = g4x_signal_levels(train_set);

	drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n",
		    signal_levels);

	intel_dp->DP &= ~(DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK);
	intel_dp->DP |= signal_levels;

	intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP);
	intel_de_posting_read(dev_priv, intel_dp->output_reg);
}

/* SNB CPU eDP voltage swing and pre-emphasis control */
static u32
snb_cpu_edp_signal_levels(u8 train_set)
static u32 snb_cpu_edp_signal_levels(u8 train_set)
{
	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
	u8 signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
					DP_TRAIN_PRE_EMPHASIS_MASK);

	switch (signal_levels) {
	case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
	case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0:
@@ -4248,12 +4262,31 @@ snb_cpu_edp_signal_levels(u8 train_set)
	}
}

static void
snb_cpu_edp_set_signal_levels(struct intel_dp *intel_dp)
{
	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
	u8 train_set = intel_dp->train_set[0];
	u32 signal_levels;

	signal_levels = snb_cpu_edp_signal_levels(train_set);

	drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n",
		    signal_levels);

	intel_dp->DP &= ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB;
	intel_dp->DP |= signal_levels;

	intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP);
	intel_de_posting_read(dev_priv, intel_dp->output_reg);
}

/* IVB CPU eDP voltage swing and pre-emphasis control */
static u32
ivb_cpu_edp_signal_levels(u8 train_set)
static u32 ivb_cpu_edp_signal_levels(u8 train_set)
{
	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
	u8 signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
					DP_TRAIN_PRE_EMPHASIS_MASK);

	switch (signal_levels) {
	case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
		return EDP_LINK_TRAIN_400MV_0DB_IVB;
@@ -4279,39 +4312,30 @@ ivb_cpu_edp_signal_levels(u8 train_set)
	}
}

void
intel_dp_set_signal_levels(struct intel_dp *intel_dp)
static void
ivb_cpu_edp_set_signal_levels(struct intel_dp *intel_dp)
{
	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
	enum port port = intel_dig_port->base.port;
	u32 signal_levels, mask = 0;
	u8 train_set = intel_dp->train_set[0];
	u32 signal_levels;

	if (IS_GEN9_LP(dev_priv) || INTEL_GEN(dev_priv) >= 10) {
		signal_levels = bxt_signal_levels(intel_dp);
	} else if (HAS_DDI(dev_priv)) {
		signal_levels = ddi_signal_levels(intel_dp);
		mask = DDI_BUF_EMP_MASK;
	} else if (IS_CHERRYVIEW(dev_priv)) {
		signal_levels = chv_signal_levels(intel_dp);
	} else if (IS_VALLEYVIEW(dev_priv)) {
		signal_levels = vlv_signal_levels(intel_dp);
	} else if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {
	signal_levels = ivb_cpu_edp_signal_levels(train_set);
		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB;
	} else if (IS_GEN(dev_priv, 6) && port == PORT_A) {
		signal_levels = snb_cpu_edp_signal_levels(train_set);
		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB;
	} else {
		signal_levels = g4x_signal_levels(train_set);
		mask = DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK;
	}

	if (mask)
	drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n",
		    signal_levels);

	intel_dp->DP &= ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB;
	intel_dp->DP |= signal_levels;

	intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP);
	intel_de_posting_read(dev_priv, intel_dp->output_reg);
}

void intel_dp_set_signal_levels(struct intel_dp *intel_dp)
{
	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
	u8 train_set = intel_dp->train_set[0];

	drm_dbg_kms(&dev_priv->drm, "Using vswing level %d%s\n",
		    train_set & DP_TRAIN_VOLTAGE_SWING_MASK,
		    train_set & DP_TRAIN_MAX_SWING_REACHED ? " (max)" : "");
@@ -4321,10 +4345,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)
		    train_set & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED ?
		    " (max)" : "");

	intel_dp->DP = (intel_dp->DP & ~mask) | signal_levels;

	intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP);
	intel_de_posting_read(dev_priv, intel_dp->output_reg);
	intel_dp->set_signal_levels(intel_dp);
}

void
@@ -8495,6 +8516,17 @@ bool intel_dp_init(struct drm_i915_private *dev_priv,
	else
		intel_dig_port->dp.set_link_train = g4x_set_link_train;

	if (IS_CHERRYVIEW(dev_priv))
		intel_dig_port->dp.set_signal_levels = chv_set_signal_levels;
	else if (IS_VALLEYVIEW(dev_priv))
		intel_dig_port->dp.set_signal_levels = vlv_set_signal_levels;
	else if (IS_IVYBRIDGE(dev_priv) && port == PORT_A)
		intel_dig_port->dp.set_signal_levels = ivb_cpu_edp_set_signal_levels;
	else if (IS_GEN(dev_priv, 6) && port == PORT_A)
		intel_dig_port->dp.set_signal_levels = snb_cpu_edp_set_signal_levels;
	else
		intel_dig_port->dp.set_signal_levels = g4x_set_signal_levels;

	intel_dig_port->dp.output_reg = output_reg;
	intel_dig_port->max_lanes = 4;
	intel_dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port);