diff options
Diffstat (limited to 'drivers/gpu/drm/i915/display/intel_dpio_phy.c')
-rw-r--r-- | drivers/gpu/drm/i915/display/intel_dpio_phy.c | 537 |
1 files changed, 295 insertions, 242 deletions
diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c index 4ca910874a4f..69f242139420 100644 --- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c @@ -21,6 +21,8 @@ * DEALINGS IN THE SOFTWARE. */ +#include "bxt_dpio_phy_regs.h" +#include "i915_drv.h" #include "i915_reg.h" #include "intel_ddi.h" #include "intel_ddi_buf_trans.h" @@ -29,6 +31,7 @@ #include "intel_display_types.h" #include "intel_dp.h" #include "intel_dpio_phy.h" +#include "vlv_dpio_phy_regs.h" #include "vlv_sideband.h" /** @@ -37,7 +40,7 @@ * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI * ports. DPIO is the name given to such a display PHY. These PHYs * don't follow the standard programming model using direct MMIO - * registers, and instead their registers must be accessed trough IOSF + * registers, and instead their registers must be accessed through IOSF * sideband. VLV has one such PHY for driving ports B and C, and CHV * adds another PHY for driving port D. Each PHY responds to specific * IOSF-SB port. @@ -123,9 +126,9 @@ */ /** - * struct bxt_ddi_phy_info - Hold info for a broxton DDI phy + * struct bxt_dpio_phy_info - Hold info for a broxton DDI phy */ -struct bxt_ddi_phy_info { +struct bxt_dpio_phy_info { /** * @dual_channel: true if this phy has a second channel. */ @@ -161,7 +164,7 @@ struct bxt_ddi_phy_info { } channel[2]; }; -static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = { +static const struct bxt_dpio_phy_info bxt_dpio_phy_info[] = { [DPIO_PHY0] = { .dual_channel = true, .rcomp_phy = DPIO_PHY1, @@ -183,7 +186,7 @@ static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = { }, }; -static const struct bxt_ddi_phy_info glk_ddi_phy_info[] = { +static const struct bxt_dpio_phy_info glk_dpio_phy_info[] = { [DPIO_PHY0] = { .dual_channel = false, .rcomp_phy = DPIO_PHY1, @@ -216,35 +219,35 @@ static const struct bxt_ddi_phy_info glk_ddi_phy_info[] = { }, }; -static const struct bxt_ddi_phy_info * -bxt_get_phy_list(struct drm_i915_private *dev_priv, int *count) +static const struct bxt_dpio_phy_info * +bxt_get_phy_list(struct intel_display *display, int *count) { - if (IS_GEMINILAKE(dev_priv)) { - *count = ARRAY_SIZE(glk_ddi_phy_info); - return glk_ddi_phy_info; + if (display->platform.geminilake) { + *count = ARRAY_SIZE(glk_dpio_phy_info); + return glk_dpio_phy_info; } else { - *count = ARRAY_SIZE(bxt_ddi_phy_info); - return bxt_ddi_phy_info; + *count = ARRAY_SIZE(bxt_dpio_phy_info); + return bxt_dpio_phy_info; } } -static const struct bxt_ddi_phy_info * -bxt_get_phy_info(struct drm_i915_private *dev_priv, enum dpio_phy phy) +static const struct bxt_dpio_phy_info * +bxt_get_phy_info(struct intel_display *display, enum dpio_phy phy) { int count; - const struct bxt_ddi_phy_info *phy_list = - bxt_get_phy_list(dev_priv, &count); + const struct bxt_dpio_phy_info *phy_list = + bxt_get_phy_list(display, &count); return &phy_list[phy]; } -void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port, +void bxt_port_to_phy_channel(struct intel_display *display, enum port port, enum dpio_phy *phy, enum dpio_channel *ch) { - const struct bxt_ddi_phy_info *phy_info, *phys; + const struct bxt_dpio_phy_info *phy_info, *phys; int i, count; - phys = bxt_get_phy_list(dev_priv, &count); + phys = bxt_get_phy_list(display, &count); for (i = 0; i < count; i++) { phy_info = &phys[i]; @@ -263,84 +266,110 @@ void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port, } } - drm_WARN(&dev_priv->drm, 1, "PHY not found for PORT %c", + drm_WARN(display->drm, 1, "PHY not found for PORT %c", port_name(port)); *phy = DPIO_PHY0; *ch = DPIO_CH0; } -void bxt_ddi_phy_set_signal_levels(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state) +/* + * Like intel_de_rmw() but reads from a single per-lane register and + * writes to the group register to write the same value to all the lanes. + */ +static u32 bxt_dpio_phy_rmw_grp(struct intel_display *display, + i915_reg_t reg_single, + i915_reg_t reg_group, + u32 clear, u32 set) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - int level = intel_ddi_level(encoder, crtc_state, 0); + u32 old, val; + + old = intel_de_read(display, reg_single); + val = (old & ~clear) | set; + intel_de_write(display, reg_group, val); + + return old; +} + +void bxt_dpio_phy_set_signal_levels(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state) +{ + struct intel_display *display = to_intel_display(encoder); const struct intel_ddi_buf_trans *trans; enum dpio_channel ch; enum dpio_phy phy; - int n_entries; - u32 val; + int lane, n_entries; trans = encoder->get_buf_trans(encoder, crtc_state, &n_entries); - if (drm_WARN_ON_ONCE(&dev_priv->drm, !trans)) + if (drm_WARN_ON_ONCE(display->drm, !trans)) return; - bxt_port_to_phy_channel(dev_priv, encoder->port, &phy, &ch); + bxt_port_to_phy_channel(display, encoder->port, &phy, &ch); /* * 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 = intel_de_read(dev_priv, BXT_PORT_PCS_DW10_LN01(phy, ch)); - val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); - intel_de_write(dev_priv, BXT_PORT_PCS_DW10_GRP(phy, ch), val); - - val = intel_de_read(dev_priv, BXT_PORT_TX_DW2_LN0(phy, ch)); - val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE); - val |= trans->entries[level].bxt.margin << MARGIN_000_SHIFT | - trans->entries[level].bxt.scale << UNIQ_TRANS_SCALE_SHIFT; - intel_de_write(dev_priv, BXT_PORT_TX_DW2_GRP(phy, ch), val); - - val = intel_de_read(dev_priv, BXT_PORT_TX_DW3_LN0(phy, ch)); - val &= ~SCALE_DCOMP_METHOD; - if (trans->entries[level].bxt.enable) - val |= SCALE_DCOMP_METHOD; - - if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD)) - drm_err(&dev_priv->drm, - "Disabled scaling while ouniqetrangenmethod was set"); - - intel_de_write(dev_priv, BXT_PORT_TX_DW3_GRP(phy, ch), val); - - val = intel_de_read(dev_priv, BXT_PORT_TX_DW4_LN0(phy, ch)); - val &= ~DE_EMPHASIS; - val |= trans->entries[level].bxt.deemphasis << DEEMPH_SHIFT; - intel_de_write(dev_priv, BXT_PORT_TX_DW4_GRP(phy, ch), val); - - val = intel_de_read(dev_priv, BXT_PORT_PCS_DW10_LN01(phy, ch)); - val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT; - intel_de_write(dev_priv, BXT_PORT_PCS_DW10_GRP(phy, ch), val); + bxt_dpio_phy_rmw_grp(display, BXT_PORT_PCS_DW10_LN01(phy, ch), + BXT_PORT_PCS_DW10_GRP(phy, ch), + TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT, 0); + + for (lane = 0; lane < crtc_state->lane_count; lane++) { + int level = intel_ddi_level(encoder, crtc_state, lane); + + intel_de_rmw(display, BXT_PORT_TX_DW2_LN(phy, ch, lane), + MARGIN_000_MASK | UNIQ_TRANS_SCALE_MASK, + MARGIN_000(trans->entries[level].bxt.margin) | + UNIQ_TRANS_SCALE(trans->entries[level].bxt.scale)); + } + + for (lane = 0; lane < crtc_state->lane_count; lane++) { + int level = intel_ddi_level(encoder, crtc_state, lane); + u32 val; + + intel_de_rmw(display, BXT_PORT_TX_DW3_LN(phy, ch, lane), + SCALE_DCOMP_METHOD, + trans->entries[level].bxt.enable ? + SCALE_DCOMP_METHOD : 0); + + val = intel_de_read(display, BXT_PORT_TX_DW3_LN(phy, ch, lane)); + if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD)) + drm_err(display->drm, + "Disabled scaling while ouniqetrangenmethod was set"); + } + + for (lane = 0; lane < crtc_state->lane_count; lane++) { + int level = intel_ddi_level(encoder, crtc_state, lane); + + intel_de_rmw(display, BXT_PORT_TX_DW4_LN(phy, ch, lane), + DE_EMPHASIS_MASK, + DE_EMPHASIS(trans->entries[level].bxt.deemphasis)); + } + + bxt_dpio_phy_rmw_grp(display, BXT_PORT_PCS_DW10_LN01(phy, ch), + BXT_PORT_PCS_DW10_GRP(phy, ch), + 0, TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); } -bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, - enum dpio_phy phy) +bool bxt_dpio_phy_is_enabled(struct intel_display *display, + enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info; + const struct bxt_dpio_phy_info *phy_info; - phy_info = bxt_get_phy_info(dev_priv, phy); + phy_info = bxt_get_phy_info(display, phy); - if (!(intel_de_read(dev_priv, BXT_P_CR_GT_DISP_PWRON) & phy_info->pwron_mask)) + if (!(intel_de_read(display, BXT_P_CR_GT_DISP_PWRON) & phy_info->pwron_mask)) return false; - if ((intel_de_read(dev_priv, BXT_PORT_CL1CM_DW0(phy)) & + if ((intel_de_read(display, BXT_PORT_CL1CM_DW0(phy)) & (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) { - drm_dbg(&dev_priv->drm, + drm_dbg(display->drm, "DDI PHY %d powered, but power hasn't settled\n", phy); return false; } - if (!(intel_de_read(dev_priv, BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) { - drm_dbg(&dev_priv->drm, + if (!(intel_de_read(display, BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) { + drm_dbg(display->drm, "DDI PHY %d powered, but still in reset\n", phy); return false; @@ -349,47 +378,44 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, return true; } -static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy) +static u32 bxt_get_grc(struct intel_display *display, enum dpio_phy phy) { - u32 val = intel_de_read(dev_priv, BXT_PORT_REF_DW6(phy)); + u32 val = intel_de_read(display, BXT_PORT_REF_DW6(phy)); - return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; + return REG_FIELD_GET(GRC_CODE_MASK, val); } -static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv, +static void bxt_phy_wait_grc_done(struct intel_display *display, enum dpio_phy phy) { - if (intel_de_wait_for_set(dev_priv, BXT_PORT_REF_DW3(phy), - GRC_DONE, 10)) - drm_err(&dev_priv->drm, "timeout waiting for PHY%d GRC\n", - phy); + if (intel_de_wait_for_set(display, BXT_PORT_REF_DW3(phy), GRC_DONE, 10)) + drm_err(display->drm, "timeout waiting for PHY%d GRC\n", phy); } -static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, - enum dpio_phy phy) +static void _bxt_dpio_phy_init(struct intel_display *display, enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info; + const struct bxt_dpio_phy_info *phy_info; u32 val; - phy_info = bxt_get_phy_info(dev_priv, phy); + phy_info = bxt_get_phy_info(display, phy); - if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { + if (bxt_dpio_phy_is_enabled(display, phy)) { /* Still read out the GRC value for state verification */ if (phy_info->rcomp_phy != -1) - dev_priv->display.state.bxt_phy_grc = bxt_get_grc(dev_priv, phy); + display->state.bxt_phy_grc = bxt_get_grc(display, phy); - if (bxt_ddi_phy_verify_state(dev_priv, phy)) { - drm_dbg(&dev_priv->drm, "DDI PHY %d already enabled, " + if (bxt_dpio_phy_verify_state(display, phy)) { + drm_dbg(display->drm, "DDI PHY %d already enabled, " "won't reprogram it\n", phy); return; } - drm_dbg(&dev_priv->drm, + drm_dbg(display->drm, "DDI PHY %d enabled with invalid state, " "force reprogramming it\n", phy); } - intel_de_rmw(dev_priv, BXT_P_CR_GT_DISP_PWRON, 0, phy_info->pwron_mask); + intel_de_rmw(display, BXT_P_CR_GT_DISP_PWRON, 0, phy_info->pwron_mask); /* * The PHY registers start out inaccessible and respond to reads with @@ -399,95 +425,91 @@ static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, * The flag should get set in 100us according to the HW team, but * use 1ms due to occasional timeouts observed with that. */ - if (intel_wait_for_register_fw(&dev_priv->uncore, - BXT_PORT_CL1CM_DW0(phy), - PHY_RESERVED | PHY_POWER_GOOD, - PHY_POWER_GOOD, - 1)) - drm_err(&dev_priv->drm, "timeout during PHY%d power on\n", + if (intel_de_wait_fw(display, BXT_PORT_CL1CM_DW0(phy), + PHY_RESERVED | PHY_POWER_GOOD, PHY_POWER_GOOD, 1)) + drm_err(display->drm, "timeout during PHY%d power on\n", phy); /* Program PLL Rcomp code offset */ - intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW9(phy), IREF0RC_OFFSET_MASK, - 0xE4 << IREF0RC_OFFSET_SHIFT); + intel_de_rmw(display, BXT_PORT_CL1CM_DW9(phy), + IREF0RC_OFFSET_MASK, IREF0RC_OFFSET(0xE4)); - intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW10(phy), IREF1RC_OFFSET_MASK, - 0xE4 << IREF1RC_OFFSET_SHIFT); + intel_de_rmw(display, BXT_PORT_CL1CM_DW10(phy), + IREF1RC_OFFSET_MASK, IREF1RC_OFFSET(0xE4)); /* Program power gating */ - intel_de_rmw(dev_priv, BXT_PORT_CL1CM_DW28(phy), 0, + intel_de_rmw(display, BXT_PORT_CL1CM_DW28(phy), 0, OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG); if (phy_info->dual_channel) - intel_de_rmw(dev_priv, BXT_PORT_CL2CM_DW6(phy), 0, + intel_de_rmw(display, BXT_PORT_CL2CM_DW6(phy), 0, DW6_OLDO_DYN_PWR_DOWN_EN); if (phy_info->rcomp_phy != -1) { u32 grc_code; - bxt_phy_wait_grc_done(dev_priv, phy_info->rcomp_phy); + bxt_phy_wait_grc_done(display, phy_info->rcomp_phy); /* * PHY0 isn't connected to an RCOMP resistor so copy over * the corresponding calibrated value from PHY1, and disable * the automatic calibration on PHY0. */ - val = bxt_get_grc(dev_priv, phy_info->rcomp_phy); - dev_priv->display.state.bxt_phy_grc = val; - - grc_code = val << GRC_CODE_FAST_SHIFT | - val << GRC_CODE_SLOW_SHIFT | - val; - intel_de_write(dev_priv, BXT_PORT_REF_DW6(phy), grc_code); - intel_de_rmw(dev_priv, BXT_PORT_REF_DW8(phy), + val = bxt_get_grc(display, phy_info->rcomp_phy); + display->state.bxt_phy_grc = val; + + grc_code = GRC_CODE_FAST(val) | + GRC_CODE_SLOW(val) | + GRC_CODE_NOM(val); + intel_de_write(display, BXT_PORT_REF_DW6(phy), grc_code); + intel_de_rmw(display, BXT_PORT_REF_DW8(phy), 0, GRC_DIS | GRC_RDY_OVRD); } if (phy_info->reset_delay) udelay(phy_info->reset_delay); - intel_de_rmw(dev_priv, BXT_PHY_CTL_FAMILY(phy), 0, COMMON_RESET_DIS); + intel_de_rmw(display, BXT_PHY_CTL_FAMILY(phy), 0, COMMON_RESET_DIS); } -void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) +void bxt_dpio_phy_uninit(struct intel_display *display, enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info; + const struct bxt_dpio_phy_info *phy_info; - phy_info = bxt_get_phy_info(dev_priv, phy); + phy_info = bxt_get_phy_info(display, phy); - intel_de_rmw(dev_priv, BXT_PHY_CTL_FAMILY(phy), COMMON_RESET_DIS, 0); + intel_de_rmw(display, BXT_PHY_CTL_FAMILY(phy), COMMON_RESET_DIS, 0); - intel_de_rmw(dev_priv, BXT_P_CR_GT_DISP_PWRON, phy_info->pwron_mask, 0); + intel_de_rmw(display, BXT_P_CR_GT_DISP_PWRON, phy_info->pwron_mask, 0); } -void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) +void bxt_dpio_phy_init(struct intel_display *display, enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info = - bxt_get_phy_info(dev_priv, phy); + const struct bxt_dpio_phy_info *phy_info = bxt_get_phy_info(display, phy); enum dpio_phy rcomp_phy = phy_info->rcomp_phy; bool was_enabled; - lockdep_assert_held(&dev_priv->display.power.domains.lock); + lockdep_assert_held(&display->power.domains.lock); was_enabled = true; if (rcomp_phy != -1) - was_enabled = bxt_ddi_phy_is_enabled(dev_priv, rcomp_phy); + was_enabled = bxt_dpio_phy_is_enabled(display, rcomp_phy); /* * We need to copy the GRC calibration value from rcomp_phy, * so make sure it's powered up. */ if (!was_enabled) - _bxt_ddi_phy_init(dev_priv, rcomp_phy); + _bxt_dpio_phy_init(display, rcomp_phy); - _bxt_ddi_phy_init(dev_priv, phy); + _bxt_dpio_phy_init(display, phy); if (!was_enabled) - bxt_ddi_phy_uninit(dev_priv, rcomp_phy); + bxt_dpio_phy_uninit(display, rcomp_phy); } static bool __printf(6, 7) -__phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, +__phy_reg_verify_state(struct intel_display *display, enum dpio_phy phy, i915_reg_t reg, u32 mask, u32 expected, const char *reg_fmt, ...) { @@ -495,7 +517,7 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, va_list args; u32 val; - val = intel_de_read(dev_priv, reg); + val = intel_de_read(display, reg); if ((val & mask) == expected) return true; @@ -503,7 +525,7 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, vaf.fmt = reg_fmt; vaf.va = &args; - drm_dbg(&dev_priv->drm, "DDI PHY %d reg %pV [%08x] state mismatch: " + drm_dbg(display->drm, "DDI PHY %d reg %pV [%08x] state mismatch: " "current %08x, expected %08x (mask %08x)\n", phy, &vaf, reg.reg, val, (val & ~mask) | expected, mask); @@ -513,36 +535,36 @@ __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, return false; } -bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, - enum dpio_phy phy) +bool bxt_dpio_phy_verify_state(struct intel_display *display, + enum dpio_phy phy) { - const struct bxt_ddi_phy_info *phy_info; + const struct bxt_dpio_phy_info *phy_info; u32 mask; bool ok; - phy_info = bxt_get_phy_info(dev_priv, phy); + phy_info = bxt_get_phy_info(display, phy); #define _CHK(reg, mask, exp, fmt, ...) \ - __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \ + __phy_reg_verify_state(display, phy, reg, mask, exp, fmt, \ ## __VA_ARGS__) - if (!bxt_ddi_phy_is_enabled(dev_priv, phy)) + if (!bxt_dpio_phy_is_enabled(display, phy)) return false; ok = true; /* PLL Rcomp code offset */ ok &= _CHK(BXT_PORT_CL1CM_DW9(phy), - IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT, - "BXT_PORT_CL1CM_DW9(%d)", phy); + IREF0RC_OFFSET_MASK, IREF0RC_OFFSET(0xe4), + "BXT_PORT_CL1CM_DW9(%d)", phy); ok &= _CHK(BXT_PORT_CL1CM_DW10(phy), - IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT, - "BXT_PORT_CL1CM_DW10(%d)", phy); + IREF1RC_OFFSET_MASK, IREF1RC_OFFSET(0xe4), + "BXT_PORT_CL1CM_DW10(%d)", phy); /* Power gating */ mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG; ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask, - "BXT_PORT_CL1CM_DW28(%d)", phy); + "BXT_PORT_CL1CM_DW28(%d)", phy); if (phy_info->dual_channel) ok &= _CHK(BXT_PORT_CL2CM_DW6(phy), @@ -550,11 +572,11 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, "BXT_PORT_CL2CM_DW6(%d)", phy); if (phy_info->rcomp_phy != -1) { - u32 grc_code = dev_priv->display.state.bxt_phy_grc; + u32 grc_code = display->state.bxt_phy_grc; - grc_code = grc_code << GRC_CODE_FAST_SHIFT | - grc_code << GRC_CODE_SLOW_SHIFT | - grc_code; + grc_code = GRC_CODE_FAST(grc_code) | + GRC_CODE_SLOW(grc_code) | + GRC_CODE_NOM(grc_code); mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK | GRC_CODE_NOM_MASK; ok &= _CHK(BXT_PORT_REF_DW6(phy), mask, grc_code, @@ -562,7 +584,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, mask = GRC_DIS | GRC_RDY_OVRD; ok &= _CHK(BXT_PORT_REF_DW8(phy), mask, mask, - "BXT_PORT_REF_DW8(%d)", phy); + "BXT_PORT_REF_DW8(%d)", phy); } return ok; @@ -570,7 +592,7 @@ bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, } u8 -bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count) +bxt_dpio_phy_calc_lane_lat_optim_mask(u8 lane_count) { switch (lane_count) { case 1: @@ -586,49 +608,43 @@ bxt_ddi_phy_calc_lane_lat_optim_mask(u8 lane_count) } } -void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, - u8 lane_lat_optim_mask) +void bxt_dpio_phy_set_lane_optim_mask(struct intel_encoder *encoder, + u8 lane_lat_optim_mask) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); enum port port = encoder->port; enum dpio_phy phy; enum dpio_channel ch; int lane; - bxt_port_to_phy_channel(dev_priv, port, &phy, &ch); + bxt_port_to_phy_channel(display, port, &phy, &ch); for (lane = 0; lane < 4; lane++) { - u32 val = intel_de_read(dev_priv, - BXT_PORT_TX_DW14_LN(phy, ch, lane)); - /* * Note that on CHV this flag is called UPAR, but has * the same function. */ - val &= ~LATENCY_OPTIM; - if (lane_lat_optim_mask & BIT(lane)) - val |= LATENCY_OPTIM; - - intel_de_write(dev_priv, BXT_PORT_TX_DW14_LN(phy, ch, lane), - val); + intel_de_rmw(display, BXT_PORT_TX_DW14_LN(phy, ch, lane), + LATENCY_OPTIM, + lane_lat_optim_mask & BIT(lane) ? LATENCY_OPTIM : 0); } } u8 -bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) +bxt_dpio_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_display *display = to_intel_display(encoder); enum port port = encoder->port; enum dpio_phy phy; enum dpio_channel ch; int lane; u8 mask; - bxt_port_to_phy_channel(dev_priv, port, &phy, &ch); + bxt_port_to_phy_channel(display, port, &phy, &ch); mask = 0; for (lane = 0; lane < 4; lane++) { - u32 val = intel_de_read(dev_priv, + u32 val = intel_de_read(display, BXT_PORT_TX_DW14_LN(phy, ch, lane)); if (val & LATENCY_OPTIM) @@ -701,9 +717,8 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); - enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); + enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); u32 val; int i; @@ -740,7 +755,7 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, for (i = 0; i < crtc_state->lane_count; i++) { val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW4(ch, i)); val &= ~DPIO_SWING_DEEMPH9P5_MASK; - val |= deemph_reg_value << DPIO_SWING_DEEMPH9P5_SHIFT; + val |= DPIO_SWING_DEEMPH9P5(deemph_reg_value); vlv_dpio_write(dev_priv, phy, CHV_TX_DW4(ch, i), val); } @@ -749,15 +764,15 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, val = vlv_dpio_read(dev_priv, phy, CHV_TX_DW2(ch, i)); val &= ~DPIO_SWING_MARGIN000_MASK; - val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT; + val |= DPIO_SWING_MARGIN000(margin_reg_value); /* * Supposedly this value shouldn't matter when unique transition * scale is disabled, but in fact it does matter. Let's just * always program the same value and hope it's OK. */ - val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT); - val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT; + val &= ~DPIO_UNIQ_TRANS_SCALE_MASK; + val |= DPIO_UNIQ_TRANS_SCALE(0x9a); vlv_dpio_write(dev_priv, phy, CHV_TX_DW2(ch, i), val); } @@ -791,14 +806,14 @@ void chv_set_phy_signal_level(struct intel_encoder *encoder, vlv_dpio_put(dev_priv); } -void chv_data_lane_soft_reset(struct intel_encoder *encoder, - const struct intel_crtc_state *crtc_state, - bool reset) +static void __chv_data_lane_soft_reset(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + bool reset) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum dpio_channel ch = vlv_dig_port_to_channel(enc_to_dig_port(encoder)); - enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); + struct intel_digital_port *dig_port = enc_to_dig_port(encoder); + enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); + enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); u32 val; val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW0(ch)); @@ -836,14 +851,26 @@ void chv_data_lane_soft_reset(struct intel_encoder *encoder, } } +void chv_data_lane_soft_reset(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + bool reset) +{ + struct drm_i915_private *i915 = to_i915(encoder->base.dev); + + vlv_dpio_get(i915); + __chv_data_lane_soft_reset(encoder, crtc_state, reset); + vlv_dpio_put(i915); +} + void chv_phy_pre_pll_enable(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state) { + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); - enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); + enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); enum pipe pipe = crtc->pipe; unsigned int lane_mask = intel_dp_unused_lane_mask(crtc_state->lane_count); @@ -855,50 +882,50 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, */ if (ch == DPIO_CH0 && pipe == PIPE_B) dig_port->release_cl2_override = - !chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true); + !chv_phy_powergate_ch(display, DPIO_PHY0, DPIO_CH1, true); chv_phy_powergate_lanes(encoder, true, lane_mask); vlv_dpio_get(dev_priv); /* Assert data lane reset */ - chv_data_lane_soft_reset(encoder, crtc_state, true); + __chv_data_lane_soft_reset(encoder, crtc_state, true); /* program left/right clock distribution */ if (pipe != PIPE_B) { - val = vlv_dpio_read(dev_priv, phy, _CHV_CMN_DW5_CH0); + val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW5_CH0); val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); if (ch == DPIO_CH0) val |= CHV_BUFLEFTENA1_FORCE; if (ch == DPIO_CH1) val |= CHV_BUFRIGHTENA1_FORCE; - vlv_dpio_write(dev_priv, phy, _CHV_CMN_DW5_CH0, val); + vlv_dpio_write(dev_priv, phy, CHV_CMN_DW5_CH0, val); } else { - val = vlv_dpio_read(dev_priv, phy, _CHV_CMN_DW1_CH1); + val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW1_CH1); val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); if (ch == DPIO_CH0) val |= CHV_BUFLEFTENA2_FORCE; if (ch == DPIO_CH1) val |= CHV_BUFRIGHTENA2_FORCE; - vlv_dpio_write(dev_priv, phy, _CHV_CMN_DW1_CH1, val); + vlv_dpio_write(dev_priv, phy, CHV_CMN_DW1_CH1, val); } /* program clock channel usage */ val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW8(ch)); - val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE; - if (pipe != PIPE_B) - val &= ~CHV_PCS_USEDCLKCHANNEL; + val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; + if (pipe == PIPE_B) + val |= DPIO_PCS_USEDCLKCHANNEL; else - val |= CHV_PCS_USEDCLKCHANNEL; + val &= ~DPIO_PCS_USEDCLKCHANNEL; vlv_dpio_write(dev_priv, phy, VLV_PCS01_DW8(ch), val); if (crtc_state->lane_count > 2) { val = vlv_dpio_read(dev_priv, phy, VLV_PCS23_DW8(ch)); - val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE; - if (pipe != PIPE_B) - val &= ~CHV_PCS_USEDCLKCHANNEL; + val |= DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; + if (pipe == PIPE_B) + val |= DPIO_PCS_USEDCLKCHANNEL; else - val |= CHV_PCS_USEDCLKCHANNEL; + val &= ~DPIO_PCS_USEDCLKCHANNEL; vlv_dpio_write(dev_priv, phy, VLV_PCS23_DW8(ch), val); } @@ -908,10 +935,10 @@ void chv_phy_pre_pll_enable(struct intel_encoder *encoder, * pick the CL based on the port. */ val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW19(ch)); - if (pipe != PIPE_B) - val &= ~CHV_CMN_USEDCLKCHANNEL; - else + if (pipe == PIPE_B) val |= CHV_CMN_USEDCLKCHANNEL; + else + val &= ~CHV_CMN_USEDCLKCHANNEL; vlv_dpio_write(dev_priv, phy, CHV_CMN_DW19(ch), val); vlv_dpio_put(dev_priv); @@ -923,9 +950,8 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); - enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); + enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); int data, i, stagger; u32 val; @@ -946,11 +972,10 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, for (i = 0; i < crtc_state->lane_count; i++) { /* Set the upar bit */ if (crtc_state->lane_count == 1) - data = 0x0; + data = 0; else - data = (i == 1) ? 0x0 : 0x1; - vlv_dpio_write(dev_priv, phy, CHV_TX_DW14(ch, i), - data << DPIO_UPAR_SHIFT); + data = (i == 1) ? 0 : DPIO_UPAR; + vlv_dpio_write(dev_priv, phy, CHV_TX_DW14(ch, i), data); } /* Data lane stagger programming */ @@ -992,18 +1017,18 @@ void chv_phy_pre_encoder_enable(struct intel_encoder *encoder, } /* Deassert data lane reset */ - chv_data_lane_soft_reset(encoder, crtc_state, false); + __chv_data_lane_soft_reset(encoder, crtc_state, false); vlv_dpio_put(dev_priv); } void chv_phy_release_cl2_override(struct intel_encoder *encoder) { + struct intel_display *display = to_intel_display(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); if (dig_port->release_cl2_override) { - chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false); + chv_phy_powergate_ch(display, DPIO_PHY0, DPIO_CH1, false); dig_port->release_cl2_override = false; } } @@ -1012,21 +1037,21 @@ void chv_phy_post_pll_disable(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum dpio_phy phy = vlv_dig_port_to_phy(enc_to_dig_port(encoder)); enum pipe pipe = to_intel_crtc(old_crtc_state->uapi.crtc)->pipe; - enum dpio_phy phy = vlv_pipe_to_phy(pipe); u32 val; vlv_dpio_get(dev_priv); /* disable left/right clock distribution */ if (pipe != PIPE_B) { - val = vlv_dpio_read(dev_priv, phy, _CHV_CMN_DW5_CH0); + val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW5_CH0); val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); - vlv_dpio_write(dev_priv, phy, _CHV_CMN_DW5_CH0, val); + vlv_dpio_write(dev_priv, phy, CHV_CMN_DW5_CH0, val); } else { - val = vlv_dpio_read(dev_priv, phy, _CHV_CMN_DW1_CH1); + val = vlv_dpio_read(dev_priv, phy, CHV_CMN_DW1_CH1); val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); - vlv_dpio_write(dev_priv, phy, _CHV_CMN_DW1_CH1, val); + vlv_dpio_write(dev_priv, phy, CHV_CMN_DW1_CH1, val); } vlv_dpio_put(dev_priv); @@ -1050,24 +1075,23 @@ void vlv_set_phy_signal_level(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum dpio_channel port = vlv_dig_port_to_channel(dig_port); - enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); + enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); + enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); vlv_dpio_get(dev_priv); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW5(port), 0x00000000); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW4(port), demph_reg_value); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW2(port), + vlv_dpio_write(dev_priv, phy, VLV_TX_DW5_GRP(ch), 0x00000000); + vlv_dpio_write(dev_priv, phy, VLV_TX_DW4_GRP(ch), demph_reg_value); + vlv_dpio_write(dev_priv, phy, VLV_TX_DW2_GRP(ch), uniqtranscale_reg_value); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW3(port), 0x0C782040); + vlv_dpio_write(dev_priv, phy, VLV_TX_DW3_GRP(ch), 0x0C782040); if (tx3_demph) - vlv_dpio_write(dev_priv, phy, VLV_TX3_DW4(port), tx3_demph); + vlv_dpio_write(dev_priv, phy, VLV_TX_DW4(ch, 3), tx3_demph); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW11(port), 0x00030000); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW9(port), preemph_reg_value); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN); + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW11_GRP(ch), 0x00030000); + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW9_GRP(ch), preemph_reg_value); + vlv_dpio_write(dev_priv, phy, VLV_TX_DW5_GRP(ch), DPIO_TX_OCALINIT_EN); vlv_dpio_put(dev_priv); } @@ -1077,26 +1101,25 @@ void vlv_phy_pre_pll_enable(struct intel_encoder *encoder, { struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum dpio_channel port = vlv_dig_port_to_channel(dig_port); - enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); + enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); + enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); /* Program Tx lane resets to default */ vlv_dpio_get(dev_priv); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0(port), - DPIO_PCS_TX_LANE2_RESET | - DPIO_PCS_TX_LANE1_RESET); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1(port), - DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | - DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | - (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | - DPIO_PCS_CLK_SOFT_RESET); + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0_GRP(ch), + DPIO_PCS_TX_LANE2_RESET | + DPIO_PCS_TX_LANE1_RESET); + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1_GRP(ch), + DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | + DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | + DPIO_PCS_CLK_DATAWIDTH_8_10 | + DPIO_PCS_CLK_SOFT_RESET); /* Fix up inter-pair skew failure */ - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW12(port), 0x00750f00); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW11(port), 0x00001500); - vlv_dpio_write(dev_priv, phy, VLV_TX_DW14(port), 0x40400000); + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW12_GRP(ch), 0x00750f00); + vlv_dpio_write(dev_priv, phy, VLV_TX_DW11_GRP(ch), 0x00001500); + vlv_dpio_write(dev_priv, phy, VLV_TX_DW14_GRP(ch), 0x40400000); vlv_dpio_put(dev_priv); } @@ -1108,26 +1131,23 @@ void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder, struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - enum dpio_channel port = vlv_dig_port_to_channel(dig_port); + enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); + enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); enum pipe pipe = crtc->pipe; - enum dpio_phy phy = vlv_pipe_to_phy(pipe); u32 val; vlv_dpio_get(dev_priv); /* Enable clock channels for this port */ - val = vlv_dpio_read(dev_priv, phy, VLV_PCS01_DW8(port)); - val = 0; - if (pipe) - val |= (1<<21); - else - val &= ~(1<<21); - val |= 0x001000c4; - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW8(port), val); + val = DPIO_PCS_USEDCLKCHANNEL_OVRRIDE; + if (pipe == PIPE_B) + val |= DPIO_PCS_USEDCLKCHANNEL; + val |= 0xc4; + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW8_GRP(ch), val); /* Program lane clock */ - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW14(port), 0x00760018); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW23(port), 0x00400888); + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW14_GRP(ch), 0x00760018); + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW23_GRP(ch), 0x00400888); vlv_dpio_put(dev_priv); } @@ -1137,12 +1157,45 @@ void vlv_phy_reset_lanes(struct intel_encoder *encoder, { struct intel_digital_port *dig_port = enc_to_dig_port(encoder); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - enum dpio_channel port = vlv_dig_port_to_channel(dig_port); - enum dpio_phy phy = vlv_pipe_to_phy(crtc->pipe); + enum dpio_channel ch = vlv_dig_port_to_channel(dig_port); + enum dpio_phy phy = vlv_dig_port_to_phy(dig_port); vlv_dpio_get(dev_priv); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0(port), 0x00000000); - vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1(port), 0x00e00060); + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW0_GRP(ch), 0x00000000); + vlv_dpio_write(dev_priv, phy, VLV_PCS_DW1_GRP(ch), 0x00e00060); vlv_dpio_put(dev_priv); } + +void vlv_wait_port_ready(struct intel_encoder *encoder, + unsigned int expected_mask) +{ + struct intel_display *display = to_intel_display(encoder); + u32 port_mask; + i915_reg_t dpll_reg; + + switch (encoder->port) { + default: + MISSING_CASE(encoder->port); + fallthrough; + case PORT_B: + port_mask = DPLL_PORTB_READY_MASK; + dpll_reg = DPLL(display, 0); + break; + case PORT_C: + port_mask = DPLL_PORTC_READY_MASK; + dpll_reg = DPLL(display, 0); + expected_mask <<= 4; + break; + case PORT_D: + port_mask = DPLL_PORTD_READY_MASK; + dpll_reg = DPIO_PHY_STATUS; + break; + } + + if (intel_de_wait(display, dpll_reg, port_mask, expected_mask, 1000)) + drm_WARN(display->drm, 1, + "timed out waiting for [ENCODER:%d:%s] port ready: got 0x%x, expected 0x%x\n", + encoder->base.base.id, encoder->base.name, + intel_de_read(display, dpll_reg) & port_mask, + expected_mask); +} |