mirror of https://gitee.com/openkylin/linux.git
drm/i915/bxt: VSwing programming sequence
VSwing programming sequence as specified in the updated BXT BSpec v2: Satheesh's review comments addressed. - clear value before setting into registers - move print statement to bxt function Other changes - since signal level will not be set into DDI_BUF_CTL, the value need not be returned to intel_dp_set_signal_levels(). Making the bxt specific function to return void and setting signal_levels = 0 for bxt inside intel_dp_set_signal_levels() - instead of signal levels, printing vswing level and pre-emphasis level - in case none of the pre-emphasis levels or vswing levels are set, setting default of 400mV + 0dB v3: Satheesh's review comments - Check for mask before printing signal_levels. - Removing redundant register writes - Call intel_prepare_ddi_buffers only for HAS_PCH_SPLIT - Making register write part generic as it will be required for HDMI as well. Re-structure the code to include an array for vswing related values, set signal levels v4: Satheesh's review comments - Rebase over latest renaming patches - use hsw_signal_levels for HAS_DDI Other changes - Modified vswing_sequence() func definition - Rebased on top of register macro definitions v5: Satheesh's review comments - Check ddi translation table size v6: Imre's review comments - removed comments in vswing sequence - added vswing, pre-emphasis prints in intel_dp_set_signal_levels - added comment explaining use of DP vswing values for eDP - initialize n_entries and ddi_transaltion table based on encoder type - create bxt_ddi_buf_trans structure and use decimal values - adding a flag in bxt buffer translation table to indicate def entry v7: (imre) - squash in Vandana's "VSwing register definition", "HDMI VSwing programming", "Re-enable vswing programming", "Fix vswing sequence" patches - use BXT_PORT_* regs directly instead of via a temp var - simplify BXT_PORT_* macro definitions - add code comment why we read lane while write group registers - fix readout of DP_TRAIN_PRE_EMPHASIS in debug message Signed-off-by: Vandana Kannan <vandana.kannan@intel.com> (v6) Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
ce3b7e9bcf
commit
96fb9f9b15
|
@ -1260,6 +1260,21 @@ enum skl_disp_power_wells {
|
|||
_PORT_REF_DW8_A)
|
||||
|
||||
/* BXT PHY PCS registers */
|
||||
#define _PORT_PCS_DW10_LN01_A 0x162428
|
||||
#define _PORT_PCS_DW10_LN01_B 0x6C428
|
||||
#define _PORT_PCS_DW10_LN01_C 0x6C828
|
||||
#define _PORT_PCS_DW10_GRP_A 0x162C28
|
||||
#define _PORT_PCS_DW10_GRP_B 0x6CC28
|
||||
#define _PORT_PCS_DW10_GRP_C 0x6CE28
|
||||
#define BXT_PORT_PCS_DW10_LN01(port) _PORT3(port, _PORT_PCS_DW10_LN01_A, \
|
||||
_PORT_PCS_DW10_LN01_B, \
|
||||
_PORT_PCS_DW10_LN01_C)
|
||||
#define BXT_PORT_PCS_DW10_GRP(port) _PORT3(port, _PORT_PCS_DW10_GRP_A, \
|
||||
_PORT_PCS_DW10_GRP_B, \
|
||||
_PORT_PCS_DW10_GRP_C)
|
||||
#define TX2_SWING_CALC_INIT (1 << 31)
|
||||
#define TX1_SWING_CALC_INIT (1 << 30)
|
||||
|
||||
#define _PORT_PCS_DW12_LN01_A 0x162430
|
||||
#define _PORT_PCS_DW12_LN01_B 0x6C430
|
||||
#define _PORT_PCS_DW12_LN01_C 0x6C830
|
||||
|
@ -1285,6 +1300,52 @@ enum skl_disp_power_wells {
|
|||
#define _BXT_LANE_OFFSET(lane) (((lane) >> 1) * 0x200 + \
|
||||
((lane) & 1) * 0x80)
|
||||
|
||||
#define _PORT_TX_DW2_LN0_A 0x162508
|
||||
#define _PORT_TX_DW2_LN0_B 0x6C508
|
||||
#define _PORT_TX_DW2_LN0_C 0x6C908
|
||||
#define _PORT_TX_DW2_GRP_A 0x162D08
|
||||
#define _PORT_TX_DW2_GRP_B 0x6CD08
|
||||
#define _PORT_TX_DW2_GRP_C 0x6CF08
|
||||
#define BXT_PORT_TX_DW2_GRP(port) _PORT3(port, _PORT_TX_DW2_GRP_A, \
|
||||
_PORT_TX_DW2_GRP_B, \
|
||||
_PORT_TX_DW2_GRP_C)
|
||||
#define BXT_PORT_TX_DW2_LN0(port) _PORT3(port, _PORT_TX_DW2_LN0_A, \
|
||||
_PORT_TX_DW2_LN0_B, \
|
||||
_PORT_TX_DW2_LN0_C)
|
||||
#define MARGIN_000_SHIFT 16
|
||||
#define MARGIN_000 (0xFF << MARGIN_000_SHIFT)
|
||||
#define UNIQ_TRANS_SCALE_SHIFT 8
|
||||
#define UNIQ_TRANS_SCALE (0xFF << UNIQ_TRANS_SCALE_SHIFT)
|
||||
|
||||
#define _PORT_TX_DW3_LN0_A 0x16250C
|
||||
#define _PORT_TX_DW3_LN0_B 0x6C50C
|
||||
#define _PORT_TX_DW3_LN0_C 0x6C90C
|
||||
#define _PORT_TX_DW3_GRP_A 0x162D0C
|
||||
#define _PORT_TX_DW3_GRP_B 0x6CD0C
|
||||
#define _PORT_TX_DW3_GRP_C 0x6CF0C
|
||||
#define BXT_PORT_TX_DW3_GRP(port) _PORT3(port, _PORT_TX_DW3_GRP_A, \
|
||||
_PORT_TX_DW3_GRP_B, \
|
||||
_PORT_TX_DW3_GRP_C)
|
||||
#define BXT_PORT_TX_DW3_LN0(port) _PORT3(port, _PORT_TX_DW3_LN0_A, \
|
||||
_PORT_TX_DW3_LN0_B, \
|
||||
_PORT_TX_DW3_LN0_C)
|
||||
#define UNIQE_TRANGE_EN_METHOD (1 << 27)
|
||||
|
||||
#define _PORT_TX_DW4_LN0_A 0x162510
|
||||
#define _PORT_TX_DW4_LN0_B 0x6C510
|
||||
#define _PORT_TX_DW4_LN0_C 0x6C910
|
||||
#define _PORT_TX_DW4_GRP_A 0x162D10
|
||||
#define _PORT_TX_DW4_GRP_B 0x6CD10
|
||||
#define _PORT_TX_DW4_GRP_C 0x6CF10
|
||||
#define BXT_PORT_TX_DW4_LN0(port) _PORT3(port, _PORT_TX_DW4_LN0_A, \
|
||||
_PORT_TX_DW4_LN0_B, \
|
||||
_PORT_TX_DW4_LN0_C)
|
||||
#define BXT_PORT_TX_DW4_GRP(port) _PORT3(port, _PORT_TX_DW4_GRP_A, \
|
||||
_PORT_TX_DW4_GRP_B, \
|
||||
_PORT_TX_DW4_GRP_C)
|
||||
#define DEEMPH_SHIFT 24
|
||||
#define DE_EMPHASIS (0xFF << DEEMPH_SHIFT)
|
||||
|
||||
#define _PORT_TX_DW14_LN0_A 0x162538
|
||||
#define _PORT_TX_DW14_LN0_B 0x6C538
|
||||
#define _PORT_TX_DW14_LN0_C 0x6C938
|
||||
|
|
|
@ -168,6 +168,48 @@ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = {
|
|||
{ 0x00000018, 0x000000c7 },
|
||||
};
|
||||
|
||||
struct bxt_ddi_buf_trans {
|
||||
u32 margin; /* swing value */
|
||||
u32 scale; /* scale value */
|
||||
u32 enable; /* scale enable */
|
||||
u32 deemphasis;
|
||||
bool default_index; /* true if the entry represents default value */
|
||||
};
|
||||
|
||||
/* BSpec does not define separate vswing/pre-emphasis values for eDP.
|
||||
* Using DP values for eDP as well.
|
||||
*/
|
||||
static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = {
|
||||
/* Idx NT mV diff db */
|
||||
{ 52, 0, 0, 128, true }, /* 0: 400 0 */
|
||||
{ 78, 0, 0, 85, false }, /* 1: 400 3.5 */
|
||||
{ 104, 0, 0, 64, false }, /* 2: 400 6 */
|
||||
{ 154, 0, 0, 43, false }, /* 3: 400 9.5 */
|
||||
{ 77, 0, 0, 128, false }, /* 4: 600 0 */
|
||||
{ 116, 0, 0, 85, false }, /* 5: 600 3.5 */
|
||||
{ 154, 0, 0, 64, false }, /* 6: 600 6 */
|
||||
{ 102, 0, 0, 128, false }, /* 7: 800 0 */
|
||||
{ 154, 0, 0, 85, false }, /* 8: 800 3.5 */
|
||||
{ 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */
|
||||
};
|
||||
|
||||
/* BSpec has 2 recommended values - entries 0 and 8.
|
||||
* Using the entry with higher vswing.
|
||||
*/
|
||||
static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = {
|
||||
/* Idx NT mV diff db */
|
||||
{ 52, 0, 0, 128, false }, /* 0: 400 0 */
|
||||
{ 52, 0, 0, 85, false }, /* 1: 400 3.5 */
|
||||
{ 52, 0, 0, 64, false }, /* 2: 400 6 */
|
||||
{ 42, 0, 0, 43, false }, /* 3: 400 9.5 */
|
||||
{ 77, 0, 0, 128, false }, /* 4: 600 0 */
|
||||
{ 77, 0, 0, 85, false }, /* 5: 600 3.5 */
|
||||
{ 77, 0, 0, 64, false }, /* 6: 600 6 */
|
||||
{ 102, 0, 0, 128, false }, /* 7: 800 0 */
|
||||
{ 102, 0, 0, 85, false }, /* 8: 800 3.5 */
|
||||
{ 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */
|
||||
};
|
||||
|
||||
enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)
|
||||
{
|
||||
struct drm_encoder *encoder = &intel_encoder->base;
|
||||
|
@ -219,7 +261,15 @@ static void intel_prepare_ddi_buffers(struct drm_device *dev,
|
|||
const struct ddi_buf_trans *ddi_translations_hdmi;
|
||||
const struct ddi_buf_trans *ddi_translations;
|
||||
|
||||
if (IS_SKYLAKE(dev)) {
|
||||
if (IS_BROXTON(dev)) {
|
||||
if (!intel_dig_port_supports_hdmi(intel_dig_port))
|
||||
return;
|
||||
|
||||
/* Vswing programming for HDMI */
|
||||
bxt_ddi_vswing_sequence(dev, hdmi_level, port,
|
||||
INTEL_OUTPUT_HDMI);
|
||||
return;
|
||||
} else if (IS_SKYLAKE(dev)) {
|
||||
ddi_translations_fdi = NULL;
|
||||
ddi_translations_dp = skl_ddi_translations_dp;
|
||||
n_dp_entries = ARRAY_SIZE(skl_ddi_translations_dp);
|
||||
|
@ -1695,6 +1745,67 @@ void intel_ddi_disable_pipe_clock(struct intel_crtc *intel_crtc)
|
|||
TRANS_CLK_SEL_DISABLED);
|
||||
}
|
||||
|
||||
void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level,
|
||||
enum port port, int type)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
const struct bxt_ddi_buf_trans *ddi_translations;
|
||||
u32 n_entries, i;
|
||||
uint32_t val;
|
||||
|
||||
if (type == INTEL_OUTPUT_DISPLAYPORT || type == INTEL_OUTPUT_EDP) {
|
||||
n_entries = ARRAY_SIZE(bxt_ddi_translations_dp);
|
||||
ddi_translations = bxt_ddi_translations_dp;
|
||||
} else if (type == INTEL_OUTPUT_HDMI) {
|
||||
n_entries = ARRAY_SIZE(bxt_ddi_translations_hdmi);
|
||||
ddi_translations = bxt_ddi_translations_hdmi;
|
||||
} else {
|
||||
DRM_DEBUG_KMS("Vswing programming not done for encoder %d\n",
|
||||
type);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if default value has to be used */
|
||||
if (level >= n_entries ||
|
||||
(type == INTEL_OUTPUT_HDMI && level == HDMI_LEVEL_SHIFT_UNKNOWN)) {
|
||||
for (i = 0; i < n_entries; i++) {
|
||||
if (ddi_translations[i].default_index) {
|
||||
level = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* While we write to the group register to program all lanes at once we
|
||||
* can read only lane registers and we pick lanes 0/1 for that.
|
||||
*/
|
||||
val = I915_READ(BXT_PORT_PCS_DW10_LN01(port));
|
||||
val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT);
|
||||
I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val);
|
||||
|
||||
val = I915_READ(BXT_PORT_TX_DW2_LN0(port));
|
||||
val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE);
|
||||
val |= ddi_translations[level].margin << MARGIN_000_SHIFT |
|
||||
ddi_translations[level].scale << UNIQ_TRANS_SCALE_SHIFT;
|
||||
I915_WRITE(BXT_PORT_TX_DW2_GRP(port), val);
|
||||
|
||||
val = I915_READ(BXT_PORT_TX_DW3_LN0(port));
|
||||
val &= ~UNIQE_TRANGE_EN_METHOD;
|
||||
if (ddi_translations[level].enable)
|
||||
val |= UNIQE_TRANGE_EN_METHOD;
|
||||
I915_WRITE(BXT_PORT_TX_DW3_GRP(port), val);
|
||||
|
||||
val = I915_READ(BXT_PORT_TX_DW4_LN0(port));
|
||||
val &= ~DE_EMPHASIS;
|
||||
val |= ddi_translations[level].deemphasis << DEEMPH_SHIFT;
|
||||
I915_WRITE(BXT_PORT_TX_DW4_GRP(port), val);
|
||||
|
||||
val = I915_READ(BXT_PORT_PCS_DW10_LN01(port));
|
||||
val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT;
|
||||
I915_WRITE(BXT_PORT_PCS_DW10_GRP(port), val);
|
||||
}
|
||||
|
||||
static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
|
||||
{
|
||||
struct drm_encoder *encoder = &intel_encoder->base;
|
||||
|
@ -1703,6 +1814,7 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
|
|||
struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
|
||||
enum port port = intel_ddi_get_encoder_port(intel_encoder);
|
||||
int type = intel_encoder->type;
|
||||
int hdmi_level;
|
||||
|
||||
if (type == INTEL_OUTPUT_EDP) {
|
||||
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
|
||||
|
@ -1759,6 +1871,12 @@ static void intel_ddi_pre_enable(struct intel_encoder *intel_encoder)
|
|||
} else if (type == INTEL_OUTPUT_HDMI) {
|
||||
struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
|
||||
|
||||
if (IS_BROXTON(dev)) {
|
||||
hdmi_level = dev_priv->vbt.
|
||||
ddi_port_info[port].hdmi_level_shift;
|
||||
bxt_ddi_vswing_sequence(dev, hdmi_level, port,
|
||||
INTEL_OUTPUT_HDMI);
|
||||
}
|
||||
intel_hdmi->set_infoframes(encoder,
|
||||
crtc->config->has_hdmi_sink,
|
||||
&crtc->config->base.adjusted_mode);
|
||||
|
|
|
@ -3409,6 +3409,55 @@ intel_hsw_signal_levels(uint8_t train_set)
|
|||
}
|
||||
}
|
||||
|
||||
static void intel_bxt_signal_levels(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct intel_digital_port *dport = dp_to_dig_port(intel_dp);
|
||||
enum port port = dport->port;
|
||||
struct drm_device *dev = dport->base.base.dev;
|
||||
struct intel_encoder *encoder = &dport->base;
|
||||
uint8_t train_set = intel_dp->train_set[0];
|
||||
uint32_t level = 0;
|
||||
|
||||
int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |
|
||||
DP_TRAIN_PRE_EMPHASIS_MASK);
|
||||
switch (signal_levels) {
|
||||
default:
|
||||
DRM_DEBUG_KMS("Unsupported voltage swing/pre-emph level\n");
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_0:
|
||||
level = 0;
|
||||
break;
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_1:
|
||||
level = 1;
|
||||
break;
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_2:
|
||||
level = 2;
|
||||
break;
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | DP_TRAIN_PRE_EMPH_LEVEL_3:
|
||||
level = 3;
|
||||
break;
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_0:
|
||||
level = 4;
|
||||
break;
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_1:
|
||||
level = 5;
|
||||
break;
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_1 | DP_TRAIN_PRE_EMPH_LEVEL_2:
|
||||
level = 6;
|
||||
break;
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_0:
|
||||
level = 7;
|
||||
break;
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_2 | DP_TRAIN_PRE_EMPH_LEVEL_1:
|
||||
level = 8;
|
||||
break;
|
||||
case DP_TRAIN_VOLTAGE_SWING_LEVEL_3 | DP_TRAIN_PRE_EMPH_LEVEL_0:
|
||||
level = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
bxt_ddi_vswing_sequence(dev, level, port, encoder->type);
|
||||
}
|
||||
|
||||
/* Properly updates "DP" with the correct signal levels. */
|
||||
static void
|
||||
intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
|
||||
|
@ -3419,7 +3468,11 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
|
|||
uint32_t signal_levels, mask;
|
||||
uint8_t train_set = intel_dp->train_set[0];
|
||||
|
||||
if (IS_HASWELL(dev) || IS_BROADWELL(dev) || INTEL_INFO(dev)->gen >= 9) {
|
||||
if (IS_BROXTON(dev)) {
|
||||
signal_levels = 0;
|
||||
intel_bxt_signal_levels(intel_dp);
|
||||
mask = 0;
|
||||
} else if (HAS_DDI(dev)) {
|
||||
signal_levels = intel_hsw_signal_levels(train_set);
|
||||
mask = DDI_BUF_EMP_MASK;
|
||||
} else if (IS_CHERRYVIEW(dev)) {
|
||||
|
@ -3439,7 +3492,14 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP)
|
|||
mask = DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK;
|
||||
}
|
||||
|
||||
DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels);
|
||||
if (mask)
|
||||
DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels);
|
||||
|
||||
DRM_DEBUG_KMS("Using vswing level %d\n",
|
||||
train_set & DP_TRAIN_VOLTAGE_SWING_MASK);
|
||||
DRM_DEBUG_KMS("Using pre-emphasis level %d\n",
|
||||
(train_set & DP_TRAIN_PRE_EMPHASIS_MASK) >>
|
||||
DP_TRAIN_PRE_EMPHASIS_SHIFT);
|
||||
|
||||
*DP = (*DP & ~mask) | signal_levels;
|
||||
}
|
||||
|
|
|
@ -943,6 +943,8 @@ void intel_ddi_init_dp_buf_reg(struct intel_encoder *encoder);
|
|||
void intel_ddi_clock_get(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config);
|
||||
void intel_ddi_set_vc_payload_alloc(struct drm_crtc *crtc, bool state);
|
||||
void bxt_ddi_vswing_sequence(struct drm_device *dev, u32 level,
|
||||
enum port port, int type);
|
||||
|
||||
/* intel_frontbuffer.c */
|
||||
void intel_fb_obj_invalidate(struct drm_i915_gem_object *obj,
|
||||
|
|
Loading…
Reference in New Issue