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

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.comReviewed-by: default avatarJosé Roberto de Souza <jose.souza@intel.com>
parent eee3f911
...@@ -2661,38 +2661,66 @@ static u32 intel_ddi_dp_level(struct intel_dp *intel_dp) ...@@ -2661,38 +2661,66 @@ static u32 intel_ddi_dp_level(struct intel_dp *intel_dp)
return translate_signal_level(intel_dp, signal_levels); 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 intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev);
struct intel_encoder *encoder = &dport->base;
int level = intel_ddi_dp_level(intel_dp); int level = intel_ddi_dp_level(intel_dp);
if (INTEL_GEN(dev_priv) >= 12)
tgl_ddi_vswing_sequence(encoder, intel_dp->link_rate, tgl_ddi_vswing_sequence(encoder, intel_dp->link_rate,
level, encoder->type); 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, icl_ddi_vswing_sequence(encoder, intel_dp->link_rate,
level, encoder->type); 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); 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 intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_encoder *encoder = &dport->base;
int level = intel_ddi_dp_level(intel_dp); 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)) if (IS_GEN9_BC(dev_priv))
skl_ddi_set_iboost(encoder, level, encoder->type); 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, 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) ...@@ -4436,6 +4464,17 @@ intel_ddi_init_dp_connector(struct intel_digital_port *intel_dig_port)
intel_ddi_prepare_link_retrain; intel_ddi_prepare_link_retrain;
intel_dig_port->dp.set_link_train = intel_ddi_set_link_train; 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) { 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_ctl = DP_TP_CTL(port);
intel_dig_port->dp.regs.dp_tp_status = DP_TP_STATUS(port); intel_dig_port->dp.regs.dp_tp_status = DP_TP_STATUS(port);
......
...@@ -1368,6 +1368,7 @@ struct intel_dp { ...@@ -1368,6 +1368,7 @@ struct intel_dp {
/* This is called before a link training is starterd */ /* This is called before a link training is starterd */
void (*prepare_link_retrain)(struct intel_dp *intel_dp); void (*prepare_link_retrain)(struct intel_dp *intel_dp);
void (*set_link_train)(struct intel_dp *intel_dp, u8 dp_train_pat); 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 */ /* Displayport compliance testing */
struct intel_dp_compliance compliance; struct intel_dp_compliance compliance;
......
...@@ -4013,7 +4013,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, u8 voltage_swing) ...@@ -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; struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
unsigned long demph_reg_value, preemph_reg_value, unsigned long demph_reg_value, preemph_reg_value,
...@@ -4041,7 +4041,7 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp) ...@@ -4041,7 +4041,7 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp)
uniqtranscale_reg_value = 0x5598DA3A; uniqtranscale_reg_value = 0x5598DA3A;
break; break;
default: default:
return 0; return;
} }
break; break;
case DP_TRAIN_PRE_EMPH_LEVEL_1: case DP_TRAIN_PRE_EMPH_LEVEL_1:
...@@ -4060,7 +4060,7 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp) ...@@ -4060,7 +4060,7 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp)
uniqtranscale_reg_value = 0x55ADDA3A; uniqtranscale_reg_value = 0x55ADDA3A;
break; break;
default: default:
return 0; return;
} }
break; break;
case DP_TRAIN_PRE_EMPH_LEVEL_2: case DP_TRAIN_PRE_EMPH_LEVEL_2:
...@@ -4075,7 +4075,7 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp) ...@@ -4075,7 +4075,7 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp)
uniqtranscale_reg_value = 0x55ADDA3A; uniqtranscale_reg_value = 0x55ADDA3A;
break; break;
default: default:
return 0; return;
} }
break; break;
case DP_TRAIN_PRE_EMPH_LEVEL_3: case DP_TRAIN_PRE_EMPH_LEVEL_3:
...@@ -4086,20 +4086,18 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp) ...@@ -4086,20 +4086,18 @@ static u32 vlv_signal_levels(struct intel_dp *intel_dp)
uniqtranscale_reg_value = 0x55ADDA3A; uniqtranscale_reg_value = 0x55ADDA3A;
break; break;
default: default:
return 0; return;
} }
break; break;
default: default:
return 0; return;
} }
vlv_set_phy_signal_level(encoder, demph_reg_value, preemph_reg_value, vlv_set_phy_signal_level(encoder, demph_reg_value, preemph_reg_value,
uniqtranscale_reg_value, 0); 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; struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
u32 deemph_reg_value, margin_reg_value; u32 deemph_reg_value, margin_reg_value;
...@@ -4127,7 +4125,7 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp) ...@@ -4127,7 +4125,7 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp)
uniq_trans_scale = true; uniq_trans_scale = true;
break; break;
default: default:
return 0; return;
} }
break; break;
case DP_TRAIN_PRE_EMPH_LEVEL_1: case DP_TRAIN_PRE_EMPH_LEVEL_1:
...@@ -4145,7 +4143,7 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp) ...@@ -4145,7 +4143,7 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp)
margin_reg_value = 154; margin_reg_value = 154;
break; break;
default: default:
return 0; return;
} }
break; break;
case DP_TRAIN_PRE_EMPH_LEVEL_2: case DP_TRAIN_PRE_EMPH_LEVEL_2:
...@@ -4159,7 +4157,7 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp) ...@@ -4159,7 +4157,7 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp)
margin_reg_value = 154; margin_reg_value = 154;
break; break;
default: default:
return 0; return;
} }
break; break;
case DP_TRAIN_PRE_EMPH_LEVEL_3: case DP_TRAIN_PRE_EMPH_LEVEL_3:
...@@ -4169,21 +4167,18 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp) ...@@ -4169,21 +4167,18 @@ static u32 chv_signal_levels(struct intel_dp *intel_dp)
margin_reg_value = 154; margin_reg_value = 154;
break; break;
default: default:
return 0; return;
} }
break; break;
default: default:
return 0; return;
} }
chv_set_phy_signal_level(encoder, deemph_reg_value, chv_set_phy_signal_level(encoder, deemph_reg_value,
margin_reg_value, uniq_trans_scale); margin_reg_value, uniq_trans_scale);
return 0;
} }
static u32 static u32 g4x_signal_levels(u8 train_set)
g4x_signal_levels(u8 train_set)
{ {
u32 signal_levels = 0; u32 signal_levels = 0;
...@@ -4220,12 +4215,31 @@ g4x_signal_levels(u8 train_set) ...@@ -4220,12 +4215,31 @@ g4x_signal_levels(u8 train_set)
return signal_levels; 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 */ /* SNB CPU eDP voltage swing and pre-emphasis control */
static u32 static u32 snb_cpu_edp_signal_levels(u8 train_set)
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); DP_TRAIN_PRE_EMPHASIS_MASK);
switch (signal_levels) { switch (signal_levels) {
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: 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: 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) ...@@ -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 */ /* IVB CPU eDP voltage swing and pre-emphasis control */
static u32 static u32 ivb_cpu_edp_signal_levels(u8 train_set)
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); DP_TRAIN_PRE_EMPHASIS_MASK);
switch (signal_levels) { switch (signal_levels) {
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0: case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
return EDP_LINK_TRAIN_400MV_0DB_IVB; return EDP_LINK_TRAIN_400MV_0DB_IVB;
...@@ -4279,39 +4312,30 @@ ivb_cpu_edp_signal_levels(u8 train_set) ...@@ -4279,39 +4312,30 @@ ivb_cpu_edp_signal_levels(u8 train_set)
} }
} }
void static void
intel_dp_set_signal_levels(struct intel_dp *intel_dp) ivb_cpu_edp_set_signal_levels(struct intel_dp *intel_dp)
{ {
struct drm_i915_private *dev_priv = dp_to_i915(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]; 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); 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", drm_dbg_kms(&dev_priv->drm, "Using signal levels %08x\n",
signal_levels); 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", drm_dbg_kms(&dev_priv->drm, "Using vswing level %d%s\n",
train_set & DP_TRAIN_VOLTAGE_SWING_MASK, train_set & DP_TRAIN_VOLTAGE_SWING_MASK,
train_set & DP_TRAIN_MAX_SWING_REACHED ? " (max)" : ""); train_set & DP_TRAIN_MAX_SWING_REACHED ? " (max)" : "");
...@@ -4321,10 +4345,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp) ...@@ -4321,10 +4345,7 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp)
train_set & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED ? train_set & DP_TRAIN_MAX_PRE_EMPHASIS_REACHED ?
" (max)" : ""); " (max)" : "");
intel_dp->DP = (intel_dp->DP & ~mask) | signal_levels; intel_dp->set_signal_levels(intel_dp);
intel_de_write(dev_priv, intel_dp->output_reg, intel_dp->DP);
intel_de_posting_read(dev_priv, intel_dp->output_reg);
} }
void void
...@@ -8495,6 +8516,17 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, ...@@ -8495,6 +8516,17 @@ bool intel_dp_init(struct drm_i915_private *dev_priv,
else else
intel_dig_port->dp.set_link_train = g4x_set_link_train; 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->dp.output_reg = output_reg;
intel_dig_port->max_lanes = 4; intel_dig_port->max_lanes = 4;
intel_dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port); intel_dig_port->dp.regs.dp_tp_ctl = DP_TP_CTL(port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment