提交 7ad14a29 编写于 作者: S Sonika Jindal 提交者: Daniel Vetter

drm/i915/skl: Add support for edp1.4 low vswing

Based upon vbt's vswing preemph settings value select the appropriate
translations for edp.

v2: Incorporating bspec changes for vswing and preemph levels, adding edp
translation table. Removed HSW from selection 9 which is specific to skl and
correcting the returning of level2 from max pre emph (Damien)

v3: Rebasing on top of renaming patches. Adding level(3,0) since level(2,2) as
mentioned in bspec is invalid as per edp spec. Also changed the determining of
size of the table selected (Satheesh).

v4: Adding level 3 in max voltage selection if low vswing is selected (Satheesh)

v5: Add a comment stating that skl_ddi_translations_edp is for eDP 1.4
    low vswing panels.

v6: Updating recommended DDI translation table for edp 1.4

Reviewed-by: Satheeshakrishna M <satheeshakrishna.m@intel.com> (v4)
Reviewed-by: Damien Lespiau <damien.lespiau@intel.com> (v6)
Signed-off-by: NSonika Jindal <sonika.jindal@intel.com>
Signed-off-by: NDamien Lespiau <damien.lespiau@intel.com>
Signed-off-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
上级 9a57f5bb
...@@ -139,6 +139,21 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = { ...@@ -139,6 +139,21 @@ static const struct ddi_buf_trans skl_ddi_translations_dp[] = {
{ 0x00004014, 0x00000087 }, { 0x00004014, 0x00000087 },
}; };
/* eDP 1.4 low vswing translation parameters */
static const struct ddi_buf_trans skl_ddi_translations_edp[] = {
{ 0x00000018, 0x000000a8 },
{ 0x00002016, 0x000000ab },
{ 0x00006012, 0x000000a2 },
{ 0x00008010, 0x00000088 },
{ 0x00000018, 0x000000ab },
{ 0x00004014, 0x000000a2 },
{ 0x00006012, 0x000000a6 },
{ 0x00000018, 0x000000a2 },
{ 0x00005013, 0x0000009c },
{ 0x00000018, 0x00000088 },
};
static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = {
/* Idx NT mV T mV db */ /* Idx NT mV T mV db */
{ 0x00000018, 0x000000a0 }, /* 0: 400 400 0 */ { 0x00000018, 0x000000a0 }, /* 0: 400 400 0 */
...@@ -187,7 +202,8 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ...@@ -187,7 +202,8 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg; u32 reg;
int i, n_hdmi_entries, hdmi_800mV_0dB; int i, n_hdmi_entries, n_dp_entries, n_edp_entries, hdmi_800mV_0dB,
size;
int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; int hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift;
const struct ddi_buf_trans *ddi_translations_fdi; const struct ddi_buf_trans *ddi_translations_fdi;
const struct ddi_buf_trans *ddi_translations_dp; const struct ddi_buf_trans *ddi_translations_dp;
...@@ -198,7 +214,15 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ...@@ -198,7 +214,15 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
if (IS_SKYLAKE(dev)) { if (IS_SKYLAKE(dev)) {
ddi_translations_fdi = NULL; ddi_translations_fdi = NULL;
ddi_translations_dp = skl_ddi_translations_dp; ddi_translations_dp = skl_ddi_translations_dp;
ddi_translations_edp = skl_ddi_translations_dp; n_dp_entries = ARRAY_SIZE(skl_ddi_translations_dp);
if (dev_priv->vbt.edp_low_vswing) {
ddi_translations_edp = skl_ddi_translations_edp;
n_edp_entries = ARRAY_SIZE(skl_ddi_translations_edp);
} else {
ddi_translations_edp = skl_ddi_translations_dp;
n_edp_entries = ARRAY_SIZE(skl_ddi_translations_dp);
}
ddi_translations_hdmi = skl_ddi_translations_hdmi; ddi_translations_hdmi = skl_ddi_translations_hdmi;
n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi); n_hdmi_entries = ARRAY_SIZE(skl_ddi_translations_hdmi);
hdmi_800mV_0dB = 7; hdmi_800mV_0dB = 7;
...@@ -207,6 +231,8 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ...@@ -207,6 +231,8 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
ddi_translations_dp = bdw_ddi_translations_dp; ddi_translations_dp = bdw_ddi_translations_dp;
ddi_translations_edp = bdw_ddi_translations_edp; ddi_translations_edp = bdw_ddi_translations_edp;
ddi_translations_hdmi = bdw_ddi_translations_hdmi; ddi_translations_hdmi = bdw_ddi_translations_hdmi;
n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_edp);
n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp);
n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
hdmi_800mV_0dB = 7; hdmi_800mV_0dB = 7;
} else if (IS_HASWELL(dev)) { } else if (IS_HASWELL(dev)) {
...@@ -214,6 +240,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ...@@ -214,6 +240,7 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
ddi_translations_dp = hsw_ddi_translations_dp; ddi_translations_dp = hsw_ddi_translations_dp;
ddi_translations_edp = hsw_ddi_translations_dp; ddi_translations_edp = hsw_ddi_translations_dp;
ddi_translations_hdmi = hsw_ddi_translations_hdmi; ddi_translations_hdmi = hsw_ddi_translations_hdmi;
n_dp_entries = n_edp_entries = ARRAY_SIZE(hsw_ddi_translations_dp);
n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi);
hdmi_800mV_0dB = 6; hdmi_800mV_0dB = 6;
} else { } else {
...@@ -222,6 +249,8 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ...@@ -222,6 +249,8 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
ddi_translations_fdi = bdw_ddi_translations_fdi; ddi_translations_fdi = bdw_ddi_translations_fdi;
ddi_translations_dp = bdw_ddi_translations_dp; ddi_translations_dp = bdw_ddi_translations_dp;
ddi_translations_hdmi = bdw_ddi_translations_hdmi; ddi_translations_hdmi = bdw_ddi_translations_hdmi;
n_edp_entries = ARRAY_SIZE(bdw_ddi_translations_edp);
n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp);
n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi);
hdmi_800mV_0dB = 7; hdmi_800mV_0dB = 7;
} }
...@@ -229,29 +258,34 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port) ...@@ -229,29 +258,34 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port)
switch (port) { switch (port) {
case PORT_A: case PORT_A:
ddi_translations = ddi_translations_edp; ddi_translations = ddi_translations_edp;
size = n_edp_entries;
break; break;
case PORT_B: case PORT_B:
case PORT_C: case PORT_C:
ddi_translations = ddi_translations_dp; ddi_translations = ddi_translations_dp;
size = n_dp_entries;
break; break;
case PORT_D: case PORT_D:
if (intel_dp_is_edp(dev, PORT_D)) if (intel_dp_is_edp(dev, PORT_D)) {
ddi_translations = ddi_translations_edp; ddi_translations = ddi_translations_edp;
else size = n_edp_entries;
} else {
ddi_translations = ddi_translations_dp; ddi_translations = ddi_translations_dp;
size = n_dp_entries;
}
break; break;
case PORT_E: case PORT_E:
if (ddi_translations_fdi) if (ddi_translations_fdi)
ddi_translations = ddi_translations_fdi; ddi_translations = ddi_translations_fdi;
else else
ddi_translations = ddi_translations_dp; ddi_translations = ddi_translations_dp;
size = n_dp_entries;
break; break;
default: default:
BUG(); BUG();
} }
for (i = 0, reg = DDI_BUF_TRANS(port); for (i = 0, reg = DDI_BUF_TRANS(port); i < size; i++) {
i < ARRAY_SIZE(hsw_ddi_translations_fdi); i++) {
I915_WRITE(reg, ddi_translations[i].trans1); I915_WRITE(reg, ddi_translations[i].trans1);
reg += 4; reg += 4;
I915_WRITE(reg, ddi_translations[i].trans2); I915_WRITE(reg, ddi_translations[i].trans2);
......
...@@ -2691,11 +2691,14 @@ static uint8_t ...@@ -2691,11 +2691,14 @@ static uint8_t
intel_dp_voltage_max(struct intel_dp *intel_dp) intel_dp_voltage_max(struct intel_dp *intel_dp)
{ {
struct drm_device *dev = intel_dp_to_dev(intel_dp); struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct drm_i915_private *dev_priv = dev->dev_private;
enum port port = dp_to_dig_port(intel_dp)->port; enum port port = dp_to_dig_port(intel_dp)->port;
if (INTEL_INFO(dev)->gen >= 9) if (INTEL_INFO(dev)->gen >= 9) {
if (dev_priv->vbt.edp_low_vswing && port == PORT_A)
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
else if (IS_VALLEYVIEW(dev)) } else if (IS_VALLEYVIEW(dev))
return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; return DP_TRAIN_VOLTAGE_SWING_LEVEL_3;
else if (IS_GEN7(dev) && port == PORT_A) else if (IS_GEN7(dev) && port == PORT_A)
return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; return DP_TRAIN_VOLTAGE_SWING_LEVEL_2;
...@@ -2719,6 +2722,8 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) ...@@ -2719,6 +2722,8 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing)
return DP_TRAIN_PRE_EMPH_LEVEL_2; return DP_TRAIN_PRE_EMPH_LEVEL_2;
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2: case DP_TRAIN_VOLTAGE_SWING_LEVEL_2:
return DP_TRAIN_PRE_EMPH_LEVEL_1; return DP_TRAIN_PRE_EMPH_LEVEL_1;
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3:
return DP_TRAIN_PRE_EMPH_LEVEL_0;
default: default:
return DP_TRAIN_PRE_EMPH_LEVEL_0; return DP_TRAIN_PRE_EMPH_LEVEL_0;
} }
...@@ -3201,6 +3206,9 @@ intel_hsw_signal_levels(uint8_t train_set) ...@@ -3201,6 +3206,9 @@ intel_hsw_signal_levels(uint8_t train_set)
return DDI_BUF_TRANS_SELECT(7); return DDI_BUF_TRANS_SELECT(7);
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1: case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1:
return DDI_BUF_TRANS_SELECT(8); return DDI_BUF_TRANS_SELECT(8);
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0:
return DDI_BUF_TRANS_SELECT(9);
default: default:
DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:" DRM_DEBUG_KMS("Unsupported voltage swing/pre-emphasis level:"
"0x%x\n", signal_levels); "0x%x\n", signal_levels);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册