11487f786SFrançois Tigeot /* 21487f786SFrançois Tigeot * Copyright © 2014-2016 Intel Corporation 31487f786SFrançois Tigeot * 41487f786SFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 51487f786SFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 61487f786SFrançois Tigeot * to deal in the Software without restriction, including without limitation 71487f786SFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 81487f786SFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 91487f786SFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 101487f786SFrançois Tigeot * 111487f786SFrançois Tigeot * The above copyright notice and this permission notice (including the next 121487f786SFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 131487f786SFrançois Tigeot * Software. 141487f786SFrançois Tigeot * 151487f786SFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 161487f786SFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 171487f786SFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 181487f786SFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 191487f786SFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 201487f786SFrançois Tigeot * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 211487f786SFrançois Tigeot * DEALINGS IN THE SOFTWARE. 221487f786SFrançois Tigeot */ 231487f786SFrançois Tigeot 241487f786SFrançois Tigeot #include "intel_drv.h" 251487f786SFrançois Tigeot 26*4be47400SFrançois Tigeot /** 27*4be47400SFrançois Tigeot * DOC: DPIO 28*4be47400SFrançois Tigeot * 29*4be47400SFrançois Tigeot * VLV, CHV and BXT have slightly peculiar display PHYs for driving DP/HDMI 30*4be47400SFrançois Tigeot * ports. DPIO is the name given to such a display PHY. These PHYs 31*4be47400SFrançois Tigeot * don't follow the standard programming model using direct MMIO 32*4be47400SFrançois Tigeot * registers, and instead their registers must be accessed trough IOSF 33*4be47400SFrançois Tigeot * sideband. VLV has one such PHY for driving ports B and C, and CHV 34*4be47400SFrançois Tigeot * adds another PHY for driving port D. Each PHY responds to specific 35*4be47400SFrançois Tigeot * IOSF-SB port. 36*4be47400SFrançois Tigeot * 37*4be47400SFrançois Tigeot * Each display PHY is made up of one or two channels. Each channel 38*4be47400SFrançois Tigeot * houses a common lane part which contains the PLL and other common 39*4be47400SFrançois Tigeot * logic. CH0 common lane also contains the IOSF-SB logic for the 40*4be47400SFrançois Tigeot * Common Register Interface (CRI) ie. the DPIO registers. CRI clock 41*4be47400SFrançois Tigeot * must be running when any DPIO registers are accessed. 42*4be47400SFrançois Tigeot * 43*4be47400SFrançois Tigeot * In addition to having their own registers, the PHYs are also 44*4be47400SFrançois Tigeot * controlled through some dedicated signals from the display 45*4be47400SFrançois Tigeot * controller. These include PLL reference clock enable, PLL enable, 46*4be47400SFrançois Tigeot * and CRI clock selection, for example. 47*4be47400SFrançois Tigeot * 48*4be47400SFrançois Tigeot * Eeach channel also has two splines (also called data lanes), and 49*4be47400SFrançois Tigeot * each spline is made up of one Physical Access Coding Sub-Layer 50*4be47400SFrançois Tigeot * (PCS) block and two TX lanes. So each channel has two PCS blocks 51*4be47400SFrançois Tigeot * and four TX lanes. The TX lanes are used as DP lanes or TMDS 52*4be47400SFrançois Tigeot * data/clock pairs depending on the output type. 53*4be47400SFrançois Tigeot * 54*4be47400SFrançois Tigeot * Additionally the PHY also contains an AUX lane with AUX blocks 55*4be47400SFrançois Tigeot * for each channel. This is used for DP AUX communication, but 56*4be47400SFrançois Tigeot * this fact isn't really relevant for the driver since AUX is 57*4be47400SFrançois Tigeot * controlled from the display controller side. No DPIO registers 58*4be47400SFrançois Tigeot * need to be accessed during AUX communication, 59*4be47400SFrançois Tigeot * 60*4be47400SFrançois Tigeot * Generally on VLV/CHV the common lane corresponds to the pipe and 61*4be47400SFrançois Tigeot * the spline (PCS/TX) corresponds to the port. 62*4be47400SFrançois Tigeot * 63*4be47400SFrançois Tigeot * For dual channel PHY (VLV/CHV): 64*4be47400SFrançois Tigeot * 65*4be47400SFrançois Tigeot * pipe A == CMN/PLL/REF CH0 66*4be47400SFrançois Tigeot * 67*4be47400SFrançois Tigeot * pipe B == CMN/PLL/REF CH1 68*4be47400SFrançois Tigeot * 69*4be47400SFrançois Tigeot * port B == PCS/TX CH0 70*4be47400SFrançois Tigeot * 71*4be47400SFrançois Tigeot * port C == PCS/TX CH1 72*4be47400SFrançois Tigeot * 73*4be47400SFrançois Tigeot * This is especially important when we cross the streams 74*4be47400SFrançois Tigeot * ie. drive port B with pipe B, or port C with pipe A. 75*4be47400SFrançois Tigeot * 76*4be47400SFrançois Tigeot * For single channel PHY (CHV): 77*4be47400SFrançois Tigeot * 78*4be47400SFrançois Tigeot * pipe C == CMN/PLL/REF CH0 79*4be47400SFrançois Tigeot * 80*4be47400SFrançois Tigeot * port D == PCS/TX CH0 81*4be47400SFrançois Tigeot * 82*4be47400SFrançois Tigeot * On BXT the entire PHY channel corresponds to the port. That means 83*4be47400SFrançois Tigeot * the PLL is also now associated with the port rather than the pipe, 84*4be47400SFrançois Tigeot * and so the clock needs to be routed to the appropriate transcoder. 85*4be47400SFrançois Tigeot * Port A PLL is directly connected to transcoder EDP and port B/C 86*4be47400SFrançois Tigeot * PLLs can be routed to any transcoder A/B/C. 87*4be47400SFrançois Tigeot * 88*4be47400SFrançois Tigeot * Note: DDI0 is digital port B, DD1 is digital port C, and DDI2 is 89*4be47400SFrançois Tigeot * digital port D (CHV) or port A (BXT). :: 90*4be47400SFrançois Tigeot * 91*4be47400SFrançois Tigeot * 92*4be47400SFrançois Tigeot * Dual channel PHY (VLV/CHV/BXT) 93*4be47400SFrançois Tigeot * --------------------------------- 94*4be47400SFrançois Tigeot * | CH0 | CH1 | 95*4be47400SFrançois Tigeot * | CMN/PLL/REF | CMN/PLL/REF | 96*4be47400SFrançois Tigeot * |---------------|---------------| Display PHY 97*4be47400SFrançois Tigeot * | PCS01 | PCS23 | PCS01 | PCS23 | 98*4be47400SFrançois Tigeot * |-------|-------|-------|-------| 99*4be47400SFrançois Tigeot * |TX0|TX1|TX2|TX3|TX0|TX1|TX2|TX3| 100*4be47400SFrançois Tigeot * --------------------------------- 101*4be47400SFrançois Tigeot * | DDI0 | DDI1 | DP/HDMI ports 102*4be47400SFrançois Tigeot * --------------------------------- 103*4be47400SFrançois Tigeot * 104*4be47400SFrançois Tigeot * Single channel PHY (CHV/BXT) 105*4be47400SFrançois Tigeot * ----------------- 106*4be47400SFrançois Tigeot * | CH0 | 107*4be47400SFrançois Tigeot * | CMN/PLL/REF | 108*4be47400SFrançois Tigeot * |---------------| Display PHY 109*4be47400SFrançois Tigeot * | PCS01 | PCS23 | 110*4be47400SFrançois Tigeot * |-------|-------| 111*4be47400SFrançois Tigeot * |TX0|TX1|TX2|TX3| 112*4be47400SFrançois Tigeot * ----------------- 113*4be47400SFrançois Tigeot * | DDI2 | DP/HDMI port 114*4be47400SFrançois Tigeot * ----------------- 115*4be47400SFrançois Tigeot */ 116*4be47400SFrançois Tigeot 117*4be47400SFrançois Tigeot /** 118*4be47400SFrançois Tigeot * struct bxt_ddi_phy_info - Hold info for a broxton DDI phy 119*4be47400SFrançois Tigeot */ 120*4be47400SFrançois Tigeot struct bxt_ddi_phy_info { 121*4be47400SFrançois Tigeot /** 122*4be47400SFrançois Tigeot * @dual_channel: true if this phy has a second channel. 123*4be47400SFrançois Tigeot */ 124*4be47400SFrançois Tigeot bool dual_channel; 125*4be47400SFrançois Tigeot 126*4be47400SFrançois Tigeot /** 127*4be47400SFrançois Tigeot * @rcomp_phy: If -1, indicates this phy has its own rcomp resistor. 128*4be47400SFrançois Tigeot * Otherwise the GRC value will be copied from the phy indicated by 129*4be47400SFrançois Tigeot * this field. 130*4be47400SFrançois Tigeot */ 131*4be47400SFrançois Tigeot enum dpio_phy rcomp_phy; 132*4be47400SFrançois Tigeot 133*4be47400SFrançois Tigeot /** 134*4be47400SFrançois Tigeot * @channel: struct containing per channel information. 135*4be47400SFrançois Tigeot */ 136*4be47400SFrançois Tigeot struct { 137*4be47400SFrançois Tigeot /** 138*4be47400SFrançois Tigeot * @port: which port maps to this channel. 139*4be47400SFrançois Tigeot */ 140*4be47400SFrançois Tigeot enum port port; 141*4be47400SFrançois Tigeot } channel[2]; 142*4be47400SFrançois Tigeot }; 143*4be47400SFrançois Tigeot 144*4be47400SFrançois Tigeot static const struct bxt_ddi_phy_info bxt_ddi_phy_info[] = { 145*4be47400SFrançois Tigeot [DPIO_PHY0] = { 146*4be47400SFrançois Tigeot .dual_channel = true, 147*4be47400SFrançois Tigeot .rcomp_phy = DPIO_PHY1, 148*4be47400SFrançois Tigeot 149*4be47400SFrançois Tigeot .channel = { 150*4be47400SFrançois Tigeot [DPIO_CH0] = { .port = PORT_B }, 151*4be47400SFrançois Tigeot [DPIO_CH1] = { .port = PORT_C }, 152*4be47400SFrançois Tigeot } 153*4be47400SFrançois Tigeot }, 154*4be47400SFrançois Tigeot [DPIO_PHY1] = { 155*4be47400SFrançois Tigeot .dual_channel = false, 156*4be47400SFrançois Tigeot .rcomp_phy = -1, 157*4be47400SFrançois Tigeot 158*4be47400SFrançois Tigeot .channel = { 159*4be47400SFrançois Tigeot [DPIO_CH0] = { .port = PORT_A }, 160*4be47400SFrançois Tigeot } 161*4be47400SFrançois Tigeot }, 162*4be47400SFrançois Tigeot }; 163*4be47400SFrançois Tigeot 164*4be47400SFrançois Tigeot static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info) 165*4be47400SFrançois Tigeot { 166*4be47400SFrançois Tigeot return (phy_info->dual_channel * BIT(phy_info->channel[DPIO_CH1].port)) | 167*4be47400SFrançois Tigeot BIT(phy_info->channel[DPIO_CH0].port); 168*4be47400SFrançois Tigeot } 169*4be47400SFrançois Tigeot 170*4be47400SFrançois Tigeot void bxt_port_to_phy_channel(enum port port, 171*4be47400SFrançois Tigeot enum dpio_phy *phy, enum dpio_channel *ch) 172*4be47400SFrançois Tigeot { 173*4be47400SFrançois Tigeot const struct bxt_ddi_phy_info *phy_info; 174*4be47400SFrançois Tigeot int i; 175*4be47400SFrançois Tigeot 176*4be47400SFrançois Tigeot for (i = 0; i < ARRAY_SIZE(bxt_ddi_phy_info); i++) { 177*4be47400SFrançois Tigeot phy_info = &bxt_ddi_phy_info[i]; 178*4be47400SFrançois Tigeot 179*4be47400SFrançois Tigeot if (port == phy_info->channel[DPIO_CH0].port) { 180*4be47400SFrançois Tigeot *phy = i; 181*4be47400SFrançois Tigeot *ch = DPIO_CH0; 182*4be47400SFrançois Tigeot return; 183*4be47400SFrançois Tigeot } 184*4be47400SFrançois Tigeot 185*4be47400SFrançois Tigeot if (phy_info->dual_channel && 186*4be47400SFrançois Tigeot port == phy_info->channel[DPIO_CH1].port) { 187*4be47400SFrançois Tigeot *phy = i; 188*4be47400SFrançois Tigeot *ch = DPIO_CH1; 189*4be47400SFrançois Tigeot return; 190*4be47400SFrançois Tigeot } 191*4be47400SFrançois Tigeot } 192*4be47400SFrançois Tigeot 193*4be47400SFrançois Tigeot WARN(1, "PHY not found for PORT %c", port_name(port)); 194*4be47400SFrançois Tigeot *phy = DPIO_PHY0; 195*4be47400SFrançois Tigeot *ch = DPIO_CH0; 196*4be47400SFrançois Tigeot } 197*4be47400SFrançois Tigeot 198*4be47400SFrançois Tigeot void bxt_ddi_phy_set_signal_level(struct drm_i915_private *dev_priv, 199*4be47400SFrançois Tigeot enum port port, u32 margin, u32 scale, 200*4be47400SFrançois Tigeot u32 enable, u32 deemphasis) 201*4be47400SFrançois Tigeot { 202*4be47400SFrançois Tigeot u32 val; 203*4be47400SFrançois Tigeot enum dpio_phy phy; 204*4be47400SFrançois Tigeot enum dpio_channel ch; 205*4be47400SFrançois Tigeot 206*4be47400SFrançois Tigeot bxt_port_to_phy_channel(port, &phy, &ch); 207*4be47400SFrançois Tigeot 208*4be47400SFrançois Tigeot /* 209*4be47400SFrançois Tigeot * While we write to the group register to program all lanes at once we 210*4be47400SFrançois Tigeot * can read only lane registers and we pick lanes 0/1 for that. 211*4be47400SFrançois Tigeot */ 212*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch)); 213*4be47400SFrançois Tigeot val &= ~(TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT); 214*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val); 215*4be47400SFrançois Tigeot 216*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_TX_DW2_LN0(phy, ch)); 217*4be47400SFrançois Tigeot val &= ~(MARGIN_000 | UNIQ_TRANS_SCALE); 218*4be47400SFrançois Tigeot val |= margin << MARGIN_000_SHIFT | scale << UNIQ_TRANS_SCALE_SHIFT; 219*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_TX_DW2_GRP(phy, ch), val); 220*4be47400SFrançois Tigeot 221*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_TX_DW3_LN0(phy, ch)); 222*4be47400SFrançois Tigeot val &= ~SCALE_DCOMP_METHOD; 223*4be47400SFrançois Tigeot if (enable) 224*4be47400SFrançois Tigeot val |= SCALE_DCOMP_METHOD; 225*4be47400SFrançois Tigeot 226*4be47400SFrançois Tigeot if ((val & UNIQUE_TRANGE_EN_METHOD) && !(val & SCALE_DCOMP_METHOD)) 227*4be47400SFrançois Tigeot DRM_ERROR("Disabled scaling while ouniqetrangenmethod was set"); 228*4be47400SFrançois Tigeot 229*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_TX_DW3_GRP(phy, ch), val); 230*4be47400SFrançois Tigeot 231*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_TX_DW4_LN0(phy, ch)); 232*4be47400SFrançois Tigeot val &= ~DE_EMPHASIS; 233*4be47400SFrançois Tigeot val |= deemphasis << DEEMPH_SHIFT; 234*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_TX_DW4_GRP(phy, ch), val); 235*4be47400SFrançois Tigeot 236*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_PCS_DW10_LN01(phy, ch)); 237*4be47400SFrançois Tigeot val |= TX2_SWING_CALC_INIT | TX1_SWING_CALC_INIT; 238*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_PCS_DW10_GRP(phy, ch), val); 239*4be47400SFrançois Tigeot } 240*4be47400SFrançois Tigeot 241*4be47400SFrançois Tigeot bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, 242*4be47400SFrançois Tigeot enum dpio_phy phy) 243*4be47400SFrançois Tigeot { 244*4be47400SFrançois Tigeot const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy]; 245*4be47400SFrançois Tigeot enum port port; 246*4be47400SFrançois Tigeot 247*4be47400SFrançois Tigeot if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy))) 248*4be47400SFrançois Tigeot return false; 249*4be47400SFrançois Tigeot 250*4be47400SFrançois Tigeot if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & 251*4be47400SFrançois Tigeot (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) { 252*4be47400SFrançois Tigeot DRM_DEBUG_DRIVER("DDI PHY %d powered, but power hasn't settled\n", 253*4be47400SFrançois Tigeot phy); 254*4be47400SFrançois Tigeot 255*4be47400SFrançois Tigeot return false; 256*4be47400SFrançois Tigeot } 257*4be47400SFrançois Tigeot 258*4be47400SFrançois Tigeot if (phy_info->rcomp_phy == -1 && 259*4be47400SFrançois Tigeot !(I915_READ(BXT_PORT_REF_DW3(phy)) & GRC_DONE)) { 260*4be47400SFrançois Tigeot DRM_DEBUG_DRIVER("DDI PHY %d powered, but GRC isn't done\n", 261*4be47400SFrançois Tigeot phy); 262*4be47400SFrançois Tigeot 263*4be47400SFrançois Tigeot return false; 264*4be47400SFrançois Tigeot } 265*4be47400SFrançois Tigeot 266*4be47400SFrançois Tigeot if (!(I915_READ(BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) { 267*4be47400SFrançois Tigeot DRM_DEBUG_DRIVER("DDI PHY %d powered, but still in reset\n", 268*4be47400SFrançois Tigeot phy); 269*4be47400SFrançois Tigeot 270*4be47400SFrançois Tigeot return false; 271*4be47400SFrançois Tigeot } 272*4be47400SFrançois Tigeot 273*4be47400SFrançois Tigeot for_each_port_masked(port, bxt_phy_port_mask(phy_info)) { 274*4be47400SFrançois Tigeot u32 tmp = I915_READ(BXT_PHY_CTL(port)); 275*4be47400SFrançois Tigeot 276*4be47400SFrançois Tigeot if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) { 277*4be47400SFrançois Tigeot DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane " 278*4be47400SFrançois Tigeot "for port %c powered down " 279*4be47400SFrançois Tigeot "(PHY_CTL %08x)\n", 280*4be47400SFrançois Tigeot phy, port_name(port), tmp); 281*4be47400SFrançois Tigeot 282*4be47400SFrançois Tigeot return false; 283*4be47400SFrançois Tigeot } 284*4be47400SFrançois Tigeot } 285*4be47400SFrançois Tigeot 286*4be47400SFrançois Tigeot return true; 287*4be47400SFrançois Tigeot } 288*4be47400SFrançois Tigeot 289*4be47400SFrançois Tigeot static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy) 290*4be47400SFrançois Tigeot { 291*4be47400SFrançois Tigeot u32 val = I915_READ(BXT_PORT_REF_DW6(phy)); 292*4be47400SFrançois Tigeot 293*4be47400SFrançois Tigeot return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; 294*4be47400SFrançois Tigeot } 295*4be47400SFrançois Tigeot 296*4be47400SFrançois Tigeot static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv, 297*4be47400SFrançois Tigeot enum dpio_phy phy) 298*4be47400SFrançois Tigeot { 299*4be47400SFrançois Tigeot if (intel_wait_for_register(dev_priv, 300*4be47400SFrançois Tigeot BXT_PORT_REF_DW3(phy), 301*4be47400SFrançois Tigeot GRC_DONE, GRC_DONE, 302*4be47400SFrançois Tigeot 10)) 303*4be47400SFrançois Tigeot DRM_ERROR("timeout waiting for PHY%d GRC\n", phy); 304*4be47400SFrançois Tigeot } 305*4be47400SFrançois Tigeot 306*4be47400SFrançois Tigeot static void _bxt_ddi_phy_init(struct drm_i915_private *dev_priv, 307*4be47400SFrançois Tigeot enum dpio_phy phy) 308*4be47400SFrançois Tigeot { 309*4be47400SFrançois Tigeot const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy]; 310*4be47400SFrançois Tigeot u32 val; 311*4be47400SFrançois Tigeot 312*4be47400SFrançois Tigeot if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { 313*4be47400SFrançois Tigeot /* Still read out the GRC value for state verification */ 314*4be47400SFrançois Tigeot if (phy_info->rcomp_phy != -1) 315*4be47400SFrançois Tigeot dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy); 316*4be47400SFrançois Tigeot 317*4be47400SFrançois Tigeot if (bxt_ddi_phy_verify_state(dev_priv, phy)) { 318*4be47400SFrançois Tigeot DRM_DEBUG_DRIVER("DDI PHY %d already enabled, " 319*4be47400SFrançois Tigeot "won't reprogram it\n", phy); 320*4be47400SFrançois Tigeot 321*4be47400SFrançois Tigeot return; 322*4be47400SFrançois Tigeot } 323*4be47400SFrançois Tigeot 324*4be47400SFrançois Tigeot DRM_DEBUG_DRIVER("DDI PHY %d enabled with invalid state, " 325*4be47400SFrançois Tigeot "force reprogramming it\n", phy); 326*4be47400SFrançois Tigeot } 327*4be47400SFrançois Tigeot 328*4be47400SFrançois Tigeot val = I915_READ(BXT_P_CR_GT_DISP_PWRON); 329*4be47400SFrançois Tigeot val |= GT_DISPLAY_POWER_ON(phy); 330*4be47400SFrançois Tigeot I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); 331*4be47400SFrançois Tigeot 332*4be47400SFrançois Tigeot /* 333*4be47400SFrançois Tigeot * The PHY registers start out inaccessible and respond to reads with 334*4be47400SFrançois Tigeot * all 1s. Eventually they become accessible as they power up, then 335*4be47400SFrançois Tigeot * the reserved bit will give the default 0. Poll on the reserved bit 336*4be47400SFrançois Tigeot * becoming 0 to find when the PHY is accessible. 337*4be47400SFrançois Tigeot * HW team confirmed that the time to reach phypowergood status is 338*4be47400SFrançois Tigeot * anywhere between 50 us and 100us. 339*4be47400SFrançois Tigeot */ 340*4be47400SFrançois Tigeot if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & 341*4be47400SFrançois Tigeot (PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) { 342*4be47400SFrançois Tigeot DRM_ERROR("timeout during PHY%d power on\n", phy); 343*4be47400SFrançois Tigeot } 344*4be47400SFrançois Tigeot 345*4be47400SFrançois Tigeot /* Program PLL Rcomp code offset */ 346*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_CL1CM_DW9(phy)); 347*4be47400SFrançois Tigeot val &= ~IREF0RC_OFFSET_MASK; 348*4be47400SFrançois Tigeot val |= 0xE4 << IREF0RC_OFFSET_SHIFT; 349*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val); 350*4be47400SFrançois Tigeot 351*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_CL1CM_DW10(phy)); 352*4be47400SFrançois Tigeot val &= ~IREF1RC_OFFSET_MASK; 353*4be47400SFrançois Tigeot val |= 0xE4 << IREF1RC_OFFSET_SHIFT; 354*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val); 355*4be47400SFrançois Tigeot 356*4be47400SFrançois Tigeot /* Program power gating */ 357*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_CL1CM_DW28(phy)); 358*4be47400SFrançois Tigeot val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | 359*4be47400SFrançois Tigeot SUS_CLK_CONFIG; 360*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val); 361*4be47400SFrançois Tigeot 362*4be47400SFrançois Tigeot if (phy_info->dual_channel) { 363*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_CL2CM_DW6(phy)); 364*4be47400SFrançois Tigeot val |= DW6_OLDO_DYN_PWR_DOWN_EN; 365*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_CL2CM_DW6(phy), val); 366*4be47400SFrançois Tigeot } 367*4be47400SFrançois Tigeot 368*4be47400SFrançois Tigeot if (phy_info->rcomp_phy != -1) { 369*4be47400SFrançois Tigeot uint32_t grc_code; 370*4be47400SFrançois Tigeot /* 371*4be47400SFrançois Tigeot * PHY0 isn't connected to an RCOMP resistor so copy over 372*4be47400SFrançois Tigeot * the corresponding calibrated value from PHY1, and disable 373*4be47400SFrançois Tigeot * the automatic calibration on PHY0. 374*4be47400SFrançois Tigeot */ 375*4be47400SFrançois Tigeot val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, 376*4be47400SFrançois Tigeot phy_info->rcomp_phy); 377*4be47400SFrançois Tigeot grc_code = val << GRC_CODE_FAST_SHIFT | 378*4be47400SFrançois Tigeot val << GRC_CODE_SLOW_SHIFT | 379*4be47400SFrançois Tigeot val; 380*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_REF_DW6(phy), grc_code); 381*4be47400SFrançois Tigeot 382*4be47400SFrançois Tigeot val = I915_READ(BXT_PORT_REF_DW8(phy)); 383*4be47400SFrançois Tigeot val |= GRC_DIS | GRC_RDY_OVRD; 384*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_REF_DW8(phy), val); 385*4be47400SFrançois Tigeot } 386*4be47400SFrançois Tigeot 387*4be47400SFrançois Tigeot val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); 388*4be47400SFrançois Tigeot val |= COMMON_RESET_DIS; 389*4be47400SFrançois Tigeot I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); 390*4be47400SFrançois Tigeot 391*4be47400SFrançois Tigeot if (phy_info->rcomp_phy == -1) 392*4be47400SFrançois Tigeot bxt_phy_wait_grc_done(dev_priv, phy); 393*4be47400SFrançois Tigeot 394*4be47400SFrançois Tigeot } 395*4be47400SFrançois Tigeot 396*4be47400SFrançois Tigeot void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) 397*4be47400SFrançois Tigeot { 398*4be47400SFrançois Tigeot uint32_t val; 399*4be47400SFrançois Tigeot 400*4be47400SFrançois Tigeot val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); 401*4be47400SFrançois Tigeot val &= ~COMMON_RESET_DIS; 402*4be47400SFrançois Tigeot I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); 403*4be47400SFrançois Tigeot 404*4be47400SFrançois Tigeot val = I915_READ(BXT_P_CR_GT_DISP_PWRON); 405*4be47400SFrançois Tigeot val &= ~GT_DISPLAY_POWER_ON(phy); 406*4be47400SFrançois Tigeot I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); 407*4be47400SFrançois Tigeot } 408*4be47400SFrançois Tigeot 409*4be47400SFrançois Tigeot void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) 410*4be47400SFrançois Tigeot { 411*4be47400SFrançois Tigeot const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy]; 412*4be47400SFrançois Tigeot enum dpio_phy rcomp_phy = phy_info->rcomp_phy; 413*4be47400SFrançois Tigeot bool was_enabled; 414*4be47400SFrançois Tigeot 415*4be47400SFrançois Tigeot lockdep_assert_held(&dev_priv->power_domains.lock); 416*4be47400SFrançois Tigeot 417*4be47400SFrançois Tigeot if (rcomp_phy != -1) { 418*4be47400SFrançois Tigeot was_enabled = bxt_ddi_phy_is_enabled(dev_priv, rcomp_phy); 419*4be47400SFrançois Tigeot 420*4be47400SFrançois Tigeot /* 421*4be47400SFrançois Tigeot * We need to copy the GRC calibration value from rcomp_phy, 422*4be47400SFrançois Tigeot * so make sure it's powered up. 423*4be47400SFrançois Tigeot */ 424*4be47400SFrançois Tigeot if (!was_enabled) 425*4be47400SFrançois Tigeot _bxt_ddi_phy_init(dev_priv, rcomp_phy); 426*4be47400SFrançois Tigeot } 427*4be47400SFrançois Tigeot 428*4be47400SFrançois Tigeot _bxt_ddi_phy_init(dev_priv, phy); 429*4be47400SFrançois Tigeot 430*4be47400SFrançois Tigeot if (rcomp_phy != -1 && !was_enabled) 431*4be47400SFrançois Tigeot bxt_ddi_phy_uninit(dev_priv, phy_info->rcomp_phy); 432*4be47400SFrançois Tigeot } 433*4be47400SFrançois Tigeot 434*4be47400SFrançois Tigeot static bool __printf(6, 7) 435*4be47400SFrançois Tigeot __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, 436*4be47400SFrançois Tigeot i915_reg_t reg, u32 mask, u32 expected, 437*4be47400SFrançois Tigeot const char *reg_fmt, ...) 438*4be47400SFrançois Tigeot { 439*4be47400SFrançois Tigeot struct va_format vaf; 440*4be47400SFrançois Tigeot va_list args; 441*4be47400SFrançois Tigeot u32 val; 442*4be47400SFrançois Tigeot 443*4be47400SFrançois Tigeot val = I915_READ(reg); 444*4be47400SFrançois Tigeot if ((val & mask) == expected) 445*4be47400SFrançois Tigeot return true; 446*4be47400SFrançois Tigeot 447*4be47400SFrançois Tigeot va_start(args, reg_fmt); 448*4be47400SFrançois Tigeot vaf.fmt = reg_fmt; 449*4be47400SFrançois Tigeot vaf.va = &args; 450*4be47400SFrançois Tigeot 451*4be47400SFrançois Tigeot DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: " 452*4be47400SFrançois Tigeot "current %08x, expected %08x (mask %08x)\n", 453*4be47400SFrançois Tigeot phy, &vaf, reg.reg, val, (val & ~mask) | expected, 454*4be47400SFrançois Tigeot mask); 455*4be47400SFrançois Tigeot 456*4be47400SFrançois Tigeot va_end(args); 457*4be47400SFrançois Tigeot 458*4be47400SFrançois Tigeot return false; 459*4be47400SFrançois Tigeot } 460*4be47400SFrançois Tigeot 461*4be47400SFrançois Tigeot bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, 462*4be47400SFrançois Tigeot enum dpio_phy phy) 463*4be47400SFrançois Tigeot { 464*4be47400SFrançois Tigeot const struct bxt_ddi_phy_info *phy_info = &bxt_ddi_phy_info[phy]; 465*4be47400SFrançois Tigeot uint32_t mask; 466*4be47400SFrançois Tigeot bool ok; 467*4be47400SFrançois Tigeot 468*4be47400SFrançois Tigeot #define _CHK(reg, mask, exp, fmt, ...) \ 469*4be47400SFrançois Tigeot __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \ 470*4be47400SFrançois Tigeot ## __VA_ARGS__) 471*4be47400SFrançois Tigeot 472*4be47400SFrançois Tigeot if (!bxt_ddi_phy_is_enabled(dev_priv, phy)) 473*4be47400SFrançois Tigeot return false; 474*4be47400SFrançois Tigeot 475*4be47400SFrançois Tigeot ok = true; 476*4be47400SFrançois Tigeot 477*4be47400SFrançois Tigeot /* PLL Rcomp code offset */ 478*4be47400SFrançois Tigeot ok &= _CHK(BXT_PORT_CL1CM_DW9(phy), 479*4be47400SFrançois Tigeot IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT, 480*4be47400SFrançois Tigeot "BXT_PORT_CL1CM_DW9(%d)", phy); 481*4be47400SFrançois Tigeot ok &= _CHK(BXT_PORT_CL1CM_DW10(phy), 482*4be47400SFrançois Tigeot IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT, 483*4be47400SFrançois Tigeot "BXT_PORT_CL1CM_DW10(%d)", phy); 484*4be47400SFrançois Tigeot 485*4be47400SFrançois Tigeot /* Power gating */ 486*4be47400SFrançois Tigeot mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG; 487*4be47400SFrançois Tigeot ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask, 488*4be47400SFrançois Tigeot "BXT_PORT_CL1CM_DW28(%d)", phy); 489*4be47400SFrançois Tigeot 490*4be47400SFrançois Tigeot if (phy_info->dual_channel) 491*4be47400SFrançois Tigeot ok &= _CHK(BXT_PORT_CL2CM_DW6(phy), 492*4be47400SFrançois Tigeot DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN, 493*4be47400SFrançois Tigeot "BXT_PORT_CL2CM_DW6(%d)", phy); 494*4be47400SFrançois Tigeot 495*4be47400SFrançois Tigeot if (phy_info->rcomp_phy != -1) { 496*4be47400SFrançois Tigeot u32 grc_code = dev_priv->bxt_phy_grc; 497*4be47400SFrançois Tigeot 498*4be47400SFrançois Tigeot grc_code = grc_code << GRC_CODE_FAST_SHIFT | 499*4be47400SFrançois Tigeot grc_code << GRC_CODE_SLOW_SHIFT | 500*4be47400SFrançois Tigeot grc_code; 501*4be47400SFrançois Tigeot mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK | 502*4be47400SFrançois Tigeot GRC_CODE_NOM_MASK; 503*4be47400SFrançois Tigeot ok &= _CHK(BXT_PORT_REF_DW6(phy), mask, grc_code, 504*4be47400SFrançois Tigeot "BXT_PORT_REF_DW6(%d)", phy); 505*4be47400SFrançois Tigeot 506*4be47400SFrançois Tigeot mask = GRC_DIS | GRC_RDY_OVRD; 507*4be47400SFrançois Tigeot ok &= _CHK(BXT_PORT_REF_DW8(phy), mask, mask, 508*4be47400SFrançois Tigeot "BXT_PORT_REF_DW8(%d)", phy); 509*4be47400SFrançois Tigeot } 510*4be47400SFrançois Tigeot 511*4be47400SFrançois Tigeot return ok; 512*4be47400SFrançois Tigeot #undef _CHK 513*4be47400SFrançois Tigeot } 514*4be47400SFrançois Tigeot 515*4be47400SFrançois Tigeot uint8_t 516*4be47400SFrançois Tigeot bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, 517*4be47400SFrançois Tigeot uint8_t lane_count) 518*4be47400SFrançois Tigeot { 519*4be47400SFrançois Tigeot switch (lane_count) { 520*4be47400SFrançois Tigeot case 1: 521*4be47400SFrançois Tigeot return 0; 522*4be47400SFrançois Tigeot case 2: 523*4be47400SFrançois Tigeot return BIT(2) | BIT(0); 524*4be47400SFrançois Tigeot case 4: 525*4be47400SFrançois Tigeot return BIT(3) | BIT(2) | BIT(0); 526*4be47400SFrançois Tigeot default: 527*4be47400SFrançois Tigeot MISSING_CASE(lane_count); 528*4be47400SFrançois Tigeot 529*4be47400SFrançois Tigeot return 0; 530*4be47400SFrançois Tigeot } 531*4be47400SFrançois Tigeot } 532*4be47400SFrançois Tigeot 533*4be47400SFrançois Tigeot void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, 534*4be47400SFrançois Tigeot uint8_t lane_lat_optim_mask) 535*4be47400SFrançois Tigeot { 536*4be47400SFrançois Tigeot struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); 537*4be47400SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); 538*4be47400SFrançois Tigeot enum port port = dport->port; 539*4be47400SFrançois Tigeot enum dpio_phy phy; 540*4be47400SFrançois Tigeot enum dpio_channel ch; 541*4be47400SFrançois Tigeot int lane; 542*4be47400SFrançois Tigeot 543*4be47400SFrançois Tigeot bxt_port_to_phy_channel(port, &phy, &ch); 544*4be47400SFrançois Tigeot 545*4be47400SFrançois Tigeot for (lane = 0; lane < 4; lane++) { 546*4be47400SFrançois Tigeot u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane)); 547*4be47400SFrançois Tigeot 548*4be47400SFrançois Tigeot /* 549*4be47400SFrançois Tigeot * Note that on CHV this flag is called UPAR, but has 550*4be47400SFrançois Tigeot * the same function. 551*4be47400SFrançois Tigeot */ 552*4be47400SFrançois Tigeot val &= ~LATENCY_OPTIM; 553*4be47400SFrançois Tigeot if (lane_lat_optim_mask & BIT(lane)) 554*4be47400SFrançois Tigeot val |= LATENCY_OPTIM; 555*4be47400SFrançois Tigeot 556*4be47400SFrançois Tigeot I915_WRITE(BXT_PORT_TX_DW14_LN(phy, ch, lane), val); 557*4be47400SFrançois Tigeot } 558*4be47400SFrançois Tigeot } 559*4be47400SFrançois Tigeot 560*4be47400SFrançois Tigeot uint8_t 561*4be47400SFrançois Tigeot bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) 562*4be47400SFrançois Tigeot { 563*4be47400SFrançois Tigeot struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); 564*4be47400SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); 565*4be47400SFrançois Tigeot enum port port = dport->port; 566*4be47400SFrançois Tigeot enum dpio_phy phy; 567*4be47400SFrançois Tigeot enum dpio_channel ch; 568*4be47400SFrançois Tigeot int lane; 569*4be47400SFrançois Tigeot uint8_t mask; 570*4be47400SFrançois Tigeot 571*4be47400SFrançois Tigeot bxt_port_to_phy_channel(port, &phy, &ch); 572*4be47400SFrançois Tigeot 573*4be47400SFrançois Tigeot mask = 0; 574*4be47400SFrançois Tigeot for (lane = 0; lane < 4; lane++) { 575*4be47400SFrançois Tigeot u32 val = I915_READ(BXT_PORT_TX_DW14_LN(phy, ch, lane)); 576*4be47400SFrançois Tigeot 577*4be47400SFrançois Tigeot if (val & LATENCY_OPTIM) 578*4be47400SFrançois Tigeot mask |= BIT(lane); 579*4be47400SFrançois Tigeot } 580*4be47400SFrançois Tigeot 581*4be47400SFrançois Tigeot return mask; 582*4be47400SFrançois Tigeot } 583*4be47400SFrançois Tigeot 584*4be47400SFrançois Tigeot 5851487f786SFrançois Tigeot void chv_set_phy_signal_level(struct intel_encoder *encoder, 5861487f786SFrançois Tigeot u32 deemph_reg_value, u32 margin_reg_value, 5871487f786SFrançois Tigeot bool uniq_trans_scale) 5881487f786SFrançois Tigeot { 5891487f786SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 5901487f786SFrançois Tigeot struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); 5911487f786SFrançois Tigeot struct intel_crtc *intel_crtc = to_intel_crtc(dport->base.base.crtc); 5921487f786SFrançois Tigeot enum dpio_channel ch = vlv_dport_to_channel(dport); 5931487f786SFrançois Tigeot enum i915_pipe pipe = intel_crtc->pipe; 5941487f786SFrançois Tigeot u32 val; 5951487f786SFrançois Tigeot int i; 5961487f786SFrançois Tigeot 5971487f786SFrançois Tigeot mutex_lock(&dev_priv->sb_lock); 5981487f786SFrançois Tigeot 5991487f786SFrançois Tigeot /* Clear calc init */ 6001487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); 6011487f786SFrançois Tigeot val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); 6021487f786SFrançois Tigeot val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); 6031487f786SFrançois Tigeot val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; 6041487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val); 6051487f786SFrançois Tigeot 6061487f786SFrançois Tigeot if (intel_crtc->config->lane_count > 2) { 6071487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); 6081487f786SFrançois Tigeot val &= ~(DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3); 6091487f786SFrançois Tigeot val &= ~(DPIO_PCS_TX1DEEMP_MASK | DPIO_PCS_TX2DEEMP_MASK); 6101487f786SFrançois Tigeot val |= DPIO_PCS_TX1DEEMP_9P5 | DPIO_PCS_TX2DEEMP_9P5; 6111487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); 6121487f786SFrançois Tigeot } 6131487f786SFrançois Tigeot 6141487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW9(ch)); 6151487f786SFrançois Tigeot val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); 6161487f786SFrançois Tigeot val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; 6171487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW9(ch), val); 6181487f786SFrançois Tigeot 6191487f786SFrançois Tigeot if (intel_crtc->config->lane_count > 2) { 6201487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW9(ch)); 6211487f786SFrançois Tigeot val &= ~(DPIO_PCS_TX1MARGIN_MASK | DPIO_PCS_TX2MARGIN_MASK); 6221487f786SFrançois Tigeot val |= DPIO_PCS_TX1MARGIN_000 | DPIO_PCS_TX2MARGIN_000; 6231487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW9(ch), val); 6241487f786SFrançois Tigeot } 6251487f786SFrançois Tigeot 6261487f786SFrançois Tigeot /* Program swing deemph */ 6271487f786SFrançois Tigeot for (i = 0; i < intel_crtc->config->lane_count; i++) { 6281487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW4(ch, i)); 6291487f786SFrançois Tigeot val &= ~DPIO_SWING_DEEMPH9P5_MASK; 6301487f786SFrançois Tigeot val |= deemph_reg_value << DPIO_SWING_DEEMPH9P5_SHIFT; 6311487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, CHV_TX_DW4(ch, i), val); 6321487f786SFrançois Tigeot } 6331487f786SFrançois Tigeot 6341487f786SFrançois Tigeot /* Program swing margin */ 6351487f786SFrançois Tigeot for (i = 0; i < intel_crtc->config->lane_count; i++) { 6361487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW2(ch, i)); 6371487f786SFrançois Tigeot 6381487f786SFrançois Tigeot val &= ~DPIO_SWING_MARGIN000_MASK; 6391487f786SFrançois Tigeot val |= margin_reg_value << DPIO_SWING_MARGIN000_SHIFT; 6401487f786SFrançois Tigeot 6411487f786SFrançois Tigeot /* 6421487f786SFrançois Tigeot * Supposedly this value shouldn't matter when unique transition 6431487f786SFrançois Tigeot * scale is disabled, but in fact it does matter. Let's just 6441487f786SFrançois Tigeot * always program the same value and hope it's OK. 6451487f786SFrançois Tigeot */ 6461487f786SFrançois Tigeot val &= ~(0xff << DPIO_UNIQ_TRANS_SCALE_SHIFT); 6471487f786SFrançois Tigeot val |= 0x9a << DPIO_UNIQ_TRANS_SCALE_SHIFT; 6481487f786SFrançois Tigeot 6491487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, CHV_TX_DW2(ch, i), val); 6501487f786SFrançois Tigeot } 6511487f786SFrançois Tigeot 6521487f786SFrançois Tigeot /* 6531487f786SFrançois Tigeot * The document said it needs to set bit 27 for ch0 and bit 26 6541487f786SFrançois Tigeot * for ch1. Might be a typo in the doc. 6551487f786SFrançois Tigeot * For now, for this unique transition scale selection, set bit 6561487f786SFrançois Tigeot * 27 for ch0 and ch1. 6571487f786SFrançois Tigeot */ 6581487f786SFrançois Tigeot for (i = 0; i < intel_crtc->config->lane_count; i++) { 6591487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, CHV_TX_DW3(ch, i)); 6601487f786SFrançois Tigeot if (uniq_trans_scale) 6611487f786SFrançois Tigeot val |= DPIO_TX_UNIQ_TRANS_SCALE_EN; 6621487f786SFrançois Tigeot else 6631487f786SFrançois Tigeot val &= ~DPIO_TX_UNIQ_TRANS_SCALE_EN; 6641487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, CHV_TX_DW3(ch, i), val); 6651487f786SFrançois Tigeot } 6661487f786SFrançois Tigeot 6671487f786SFrançois Tigeot /* Start swing calculation */ 6681487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW10(ch)); 6691487f786SFrançois Tigeot val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; 6701487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW10(ch), val); 6711487f786SFrançois Tigeot 6721487f786SFrançois Tigeot if (intel_crtc->config->lane_count > 2) { 6731487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW10(ch)); 6741487f786SFrançois Tigeot val |= DPIO_PCS_SWING_CALC_TX0_TX2 | DPIO_PCS_SWING_CALC_TX1_TX3; 6751487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW10(ch), val); 6761487f786SFrançois Tigeot } 6771487f786SFrançois Tigeot 6781487f786SFrançois Tigeot mutex_unlock(&dev_priv->sb_lock); 6791487f786SFrançois Tigeot 6801487f786SFrançois Tigeot } 6811487f786SFrançois Tigeot 6821487f786SFrançois Tigeot void chv_data_lane_soft_reset(struct intel_encoder *encoder, 6831487f786SFrançois Tigeot bool reset) 6841487f786SFrançois Tigeot { 6851487f786SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 6861487f786SFrançois Tigeot enum dpio_channel ch = vlv_dport_to_channel(enc_to_dig_port(&encoder->base)); 6871487f786SFrançois Tigeot struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); 6881487f786SFrançois Tigeot enum i915_pipe pipe = crtc->pipe; 6891487f786SFrançois Tigeot uint32_t val; 6901487f786SFrançois Tigeot 6911487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW0(ch)); 6921487f786SFrançois Tigeot if (reset) 6931487f786SFrançois Tigeot val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); 6941487f786SFrançois Tigeot else 6951487f786SFrançois Tigeot val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; 6961487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW0(ch), val); 6971487f786SFrançois Tigeot 6981487f786SFrançois Tigeot if (crtc->config->lane_count > 2) { 6991487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW0(ch)); 7001487f786SFrançois Tigeot if (reset) 7011487f786SFrançois Tigeot val &= ~(DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET); 7021487f786SFrançois Tigeot else 7031487f786SFrançois Tigeot val |= DPIO_PCS_TX_LANE2_RESET | DPIO_PCS_TX_LANE1_RESET; 7041487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW0(ch), val); 7051487f786SFrançois Tigeot } 7061487f786SFrançois Tigeot 7071487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW1(ch)); 7081487f786SFrançois Tigeot val |= CHV_PCS_REQ_SOFTRESET_EN; 7091487f786SFrançois Tigeot if (reset) 7101487f786SFrançois Tigeot val &= ~DPIO_PCS_CLK_SOFT_RESET; 7111487f786SFrançois Tigeot else 7121487f786SFrançois Tigeot val |= DPIO_PCS_CLK_SOFT_RESET; 7131487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW1(ch), val); 7141487f786SFrançois Tigeot 7151487f786SFrançois Tigeot if (crtc->config->lane_count > 2) { 7161487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW1(ch)); 7171487f786SFrançois Tigeot val |= CHV_PCS_REQ_SOFTRESET_EN; 7181487f786SFrançois Tigeot if (reset) 7191487f786SFrançois Tigeot val &= ~DPIO_PCS_CLK_SOFT_RESET; 7201487f786SFrançois Tigeot else 7211487f786SFrançois Tigeot val |= DPIO_PCS_CLK_SOFT_RESET; 7221487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW1(ch), val); 7231487f786SFrançois Tigeot } 7241487f786SFrançois Tigeot } 7251487f786SFrançois Tigeot 7261487f786SFrançois Tigeot void chv_phy_pre_pll_enable(struct intel_encoder *encoder) 7271487f786SFrançois Tigeot { 7281487f786SFrançois Tigeot struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); 7291487f786SFrançois Tigeot struct drm_device *dev = encoder->base.dev; 730303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 7311487f786SFrançois Tigeot struct intel_crtc *intel_crtc = 7321487f786SFrançois Tigeot to_intel_crtc(encoder->base.crtc); 7331487f786SFrançois Tigeot enum dpio_channel ch = vlv_dport_to_channel(dport); 7341487f786SFrançois Tigeot enum i915_pipe pipe = intel_crtc->pipe; 7351487f786SFrançois Tigeot unsigned int lane_mask = 7361487f786SFrançois Tigeot intel_dp_unused_lane_mask(intel_crtc->config->lane_count); 7371487f786SFrançois Tigeot u32 val; 7381487f786SFrançois Tigeot 7391487f786SFrançois Tigeot /* 7401487f786SFrançois Tigeot * Must trick the second common lane into life. 7411487f786SFrançois Tigeot * Otherwise we can't even access the PLL. 7421487f786SFrançois Tigeot */ 7431487f786SFrançois Tigeot if (ch == DPIO_CH0 && pipe == PIPE_B) 7441487f786SFrançois Tigeot dport->release_cl2_override = 7451487f786SFrançois Tigeot !chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, true); 7461487f786SFrançois Tigeot 7471487f786SFrançois Tigeot chv_phy_powergate_lanes(encoder, true, lane_mask); 7481487f786SFrançois Tigeot 7491487f786SFrançois Tigeot mutex_lock(&dev_priv->sb_lock); 7501487f786SFrançois Tigeot 7511487f786SFrançois Tigeot /* Assert data lane reset */ 7521487f786SFrançois Tigeot chv_data_lane_soft_reset(encoder, true); 7531487f786SFrançois Tigeot 7541487f786SFrançois Tigeot /* program left/right clock distribution */ 7551487f786SFrançois Tigeot if (pipe != PIPE_B) { 7561487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); 7571487f786SFrançois Tigeot val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); 7581487f786SFrançois Tigeot if (ch == DPIO_CH0) 7591487f786SFrançois Tigeot val |= CHV_BUFLEFTENA1_FORCE; 7601487f786SFrançois Tigeot if (ch == DPIO_CH1) 7611487f786SFrançois Tigeot val |= CHV_BUFRIGHTENA1_FORCE; 7621487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val); 7631487f786SFrançois Tigeot } else { 7641487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1); 7651487f786SFrançois Tigeot val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); 7661487f786SFrançois Tigeot if (ch == DPIO_CH0) 7671487f786SFrançois Tigeot val |= CHV_BUFLEFTENA2_FORCE; 7681487f786SFrançois Tigeot if (ch == DPIO_CH1) 7691487f786SFrançois Tigeot val |= CHV_BUFRIGHTENA2_FORCE; 7701487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val); 7711487f786SFrançois Tigeot } 7721487f786SFrançois Tigeot 7731487f786SFrançois Tigeot /* program clock channel usage */ 7741487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(ch)); 7751487f786SFrançois Tigeot val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE; 7761487f786SFrançois Tigeot if (pipe != PIPE_B) 7771487f786SFrançois Tigeot val &= ~CHV_PCS_USEDCLKCHANNEL; 7781487f786SFrançois Tigeot else 7791487f786SFrançois Tigeot val |= CHV_PCS_USEDCLKCHANNEL; 7801487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW8(ch), val); 7811487f786SFrançois Tigeot 7821487f786SFrançois Tigeot if (intel_crtc->config->lane_count > 2) { 7831487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW8(ch)); 7841487f786SFrançois Tigeot val |= CHV_PCS_USEDCLKCHANNEL_OVRRIDE; 7851487f786SFrançois Tigeot if (pipe != PIPE_B) 7861487f786SFrançois Tigeot val &= ~CHV_PCS_USEDCLKCHANNEL; 7871487f786SFrançois Tigeot else 7881487f786SFrançois Tigeot val |= CHV_PCS_USEDCLKCHANNEL; 7891487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW8(ch), val); 7901487f786SFrançois Tigeot } 7911487f786SFrançois Tigeot 7921487f786SFrançois Tigeot /* 7931487f786SFrançois Tigeot * This a a bit weird since generally CL 7941487f786SFrançois Tigeot * matches the pipe, but here we need to 7951487f786SFrançois Tigeot * pick the CL based on the port. 7961487f786SFrançois Tigeot */ 7971487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, CHV_CMN_DW19(ch)); 7981487f786SFrançois Tigeot if (pipe != PIPE_B) 7991487f786SFrançois Tigeot val &= ~CHV_CMN_USEDCLKCHANNEL; 8001487f786SFrançois Tigeot else 8011487f786SFrançois Tigeot val |= CHV_CMN_USEDCLKCHANNEL; 8021487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, CHV_CMN_DW19(ch), val); 8031487f786SFrançois Tigeot 8041487f786SFrançois Tigeot mutex_unlock(&dev_priv->sb_lock); 8051487f786SFrançois Tigeot } 8061487f786SFrançois Tigeot 8071487f786SFrançois Tigeot void chv_phy_pre_encoder_enable(struct intel_encoder *encoder) 8081487f786SFrançois Tigeot { 8091487f786SFrançois Tigeot struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); 8101487f786SFrançois Tigeot struct intel_digital_port *dport = dp_to_dig_port(intel_dp); 8111487f786SFrançois Tigeot struct drm_device *dev = encoder->base.dev; 812303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 8131487f786SFrançois Tigeot struct intel_crtc *intel_crtc = 8141487f786SFrançois Tigeot to_intel_crtc(encoder->base.crtc); 8151487f786SFrançois Tigeot enum dpio_channel ch = vlv_dport_to_channel(dport); 8161487f786SFrançois Tigeot int pipe = intel_crtc->pipe; 8171487f786SFrançois Tigeot int data, i, stagger; 8181487f786SFrançois Tigeot u32 val; 8191487f786SFrançois Tigeot 8201487f786SFrançois Tigeot mutex_lock(&dev_priv->sb_lock); 8211487f786SFrançois Tigeot 8221487f786SFrançois Tigeot /* allow hardware to manage TX FIFO reset source */ 8231487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch)); 8241487f786SFrançois Tigeot val &= ~DPIO_LANEDESKEW_STRAP_OVRD; 8251487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); 8261487f786SFrançois Tigeot 8271487f786SFrançois Tigeot if (intel_crtc->config->lane_count > 2) { 8281487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); 8291487f786SFrançois Tigeot val &= ~DPIO_LANEDESKEW_STRAP_OVRD; 8301487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); 8311487f786SFrançois Tigeot } 8321487f786SFrançois Tigeot 8331487f786SFrançois Tigeot /* Program Tx lane latency optimal setting*/ 8341487f786SFrançois Tigeot for (i = 0; i < intel_crtc->config->lane_count; i++) { 8351487f786SFrançois Tigeot /* Set the upar bit */ 8361487f786SFrançois Tigeot if (intel_crtc->config->lane_count == 1) 8371487f786SFrançois Tigeot data = 0x0; 8381487f786SFrançois Tigeot else 8391487f786SFrançois Tigeot data = (i == 1) ? 0x0 : 0x1; 8401487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, CHV_TX_DW14(ch, i), 8411487f786SFrançois Tigeot data << DPIO_UPAR_SHIFT); 8421487f786SFrançois Tigeot } 8431487f786SFrançois Tigeot 8441487f786SFrançois Tigeot /* Data lane stagger programming */ 8451487f786SFrançois Tigeot if (intel_crtc->config->port_clock > 270000) 8461487f786SFrançois Tigeot stagger = 0x18; 8471487f786SFrançois Tigeot else if (intel_crtc->config->port_clock > 135000) 8481487f786SFrançois Tigeot stagger = 0xd; 8491487f786SFrançois Tigeot else if (intel_crtc->config->port_clock > 67500) 8501487f786SFrançois Tigeot stagger = 0x7; 8511487f786SFrançois Tigeot else if (intel_crtc->config->port_clock > 33750) 8521487f786SFrançois Tigeot stagger = 0x4; 8531487f786SFrançois Tigeot else 8541487f786SFrançois Tigeot stagger = 0x2; 8551487f786SFrançois Tigeot 8561487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW11(ch)); 8571487f786SFrançois Tigeot val |= DPIO_TX2_STAGGER_MASK(0x1f); 8581487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW11(ch), val); 8591487f786SFrançois Tigeot 8601487f786SFrançois Tigeot if (intel_crtc->config->lane_count > 2) { 8611487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS23_DW11(ch)); 8621487f786SFrançois Tigeot val |= DPIO_TX2_STAGGER_MASK(0x1f); 8631487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW11(ch), val); 8641487f786SFrançois Tigeot } 8651487f786SFrançois Tigeot 8661487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS01_DW12(ch), 8671487f786SFrançois Tigeot DPIO_LANESTAGGER_STRAP(stagger) | 8681487f786SFrançois Tigeot DPIO_LANESTAGGER_STRAP_OVRD | 8691487f786SFrançois Tigeot DPIO_TX1_STAGGER_MASK(0x1f) | 8701487f786SFrançois Tigeot DPIO_TX1_STAGGER_MULT(6) | 8711487f786SFrançois Tigeot DPIO_TX2_STAGGER_MULT(0)); 8721487f786SFrançois Tigeot 8731487f786SFrançois Tigeot if (intel_crtc->config->lane_count > 2) { 8741487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS23_DW12(ch), 8751487f786SFrançois Tigeot DPIO_LANESTAGGER_STRAP(stagger) | 8761487f786SFrançois Tigeot DPIO_LANESTAGGER_STRAP_OVRD | 8771487f786SFrançois Tigeot DPIO_TX1_STAGGER_MASK(0x1f) | 8781487f786SFrançois Tigeot DPIO_TX1_STAGGER_MULT(7) | 8791487f786SFrançois Tigeot DPIO_TX2_STAGGER_MULT(5)); 8801487f786SFrançois Tigeot } 8811487f786SFrançois Tigeot 8821487f786SFrançois Tigeot /* Deassert data lane reset */ 8831487f786SFrançois Tigeot chv_data_lane_soft_reset(encoder, false); 8841487f786SFrançois Tigeot 8851487f786SFrançois Tigeot mutex_unlock(&dev_priv->sb_lock); 8861487f786SFrançois Tigeot } 8871487f786SFrançois Tigeot 8881487f786SFrançois Tigeot void chv_phy_release_cl2_override(struct intel_encoder *encoder) 8891487f786SFrançois Tigeot { 8901487f786SFrançois Tigeot struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); 8911487f786SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 8921487f786SFrançois Tigeot 8931487f786SFrançois Tigeot if (dport->release_cl2_override) { 8941487f786SFrançois Tigeot chv_phy_powergate_ch(dev_priv, DPIO_PHY0, DPIO_CH1, false); 8951487f786SFrançois Tigeot dport->release_cl2_override = false; 8961487f786SFrançois Tigeot } 8971487f786SFrançois Tigeot } 8981487f786SFrançois Tigeot 8991487f786SFrançois Tigeot void chv_phy_post_pll_disable(struct intel_encoder *encoder) 9001487f786SFrançois Tigeot { 9011487f786SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 9021487f786SFrançois Tigeot enum i915_pipe pipe = to_intel_crtc(encoder->base.crtc)->pipe; 9031487f786SFrançois Tigeot u32 val; 9041487f786SFrançois Tigeot 9051487f786SFrançois Tigeot mutex_lock(&dev_priv->sb_lock); 9061487f786SFrançois Tigeot 9071487f786SFrançois Tigeot /* disable left/right clock distribution */ 9081487f786SFrançois Tigeot if (pipe != PIPE_B) { 9091487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW5_CH0); 9101487f786SFrançois Tigeot val &= ~(CHV_BUFLEFTENA1_MASK | CHV_BUFRIGHTENA1_MASK); 9111487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW5_CH0, val); 9121487f786SFrançois Tigeot } else { 9131487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, _CHV_CMN_DW1_CH1); 9141487f786SFrançois Tigeot val &= ~(CHV_BUFLEFTENA2_MASK | CHV_BUFRIGHTENA2_MASK); 9151487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, _CHV_CMN_DW1_CH1, val); 9161487f786SFrançois Tigeot } 9171487f786SFrançois Tigeot 9181487f786SFrançois Tigeot mutex_unlock(&dev_priv->sb_lock); 9191487f786SFrançois Tigeot 9201487f786SFrançois Tigeot /* 9211487f786SFrançois Tigeot * Leave the power down bit cleared for at least one 9221487f786SFrançois Tigeot * lane so that chv_powergate_phy_ch() will power 9231487f786SFrançois Tigeot * on something when the channel is otherwise unused. 9241487f786SFrançois Tigeot * When the port is off and the override is removed 9251487f786SFrançois Tigeot * the lanes power down anyway, so otherwise it doesn't 9261487f786SFrançois Tigeot * really matter what the state of power down bits is 9271487f786SFrançois Tigeot * after this. 9281487f786SFrançois Tigeot */ 9291487f786SFrançois Tigeot chv_phy_powergate_lanes(encoder, false, 0x0); 9301487f786SFrançois Tigeot } 9311487f786SFrançois Tigeot 9321487f786SFrançois Tigeot void vlv_set_phy_signal_level(struct intel_encoder *encoder, 9331487f786SFrançois Tigeot u32 demph_reg_value, u32 preemph_reg_value, 9341487f786SFrançois Tigeot u32 uniqtranscale_reg_value, u32 tx3_demph) 9351487f786SFrançois Tigeot { 9361487f786SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 9371487f786SFrançois Tigeot struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); 9381487f786SFrançois Tigeot struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); 9391487f786SFrançois Tigeot enum dpio_channel port = vlv_dport_to_channel(dport); 9401487f786SFrançois Tigeot int pipe = intel_crtc->pipe; 9411487f786SFrançois Tigeot 9421487f786SFrançois Tigeot mutex_lock(&dev_priv->sb_lock); 9431487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), 0x00000000); 9441487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_TX_DW4(port), demph_reg_value); 9451487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_TX_DW2(port), 9461487f786SFrançois Tigeot uniqtranscale_reg_value); 9471487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_TX_DW3(port), 0x0C782040); 9481487f786SFrançois Tigeot 9491487f786SFrançois Tigeot if (tx3_demph) 9501487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_TX3_DW4(port), tx3_demph); 9511487f786SFrançois Tigeot 9521487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW11(port), 0x00030000); 9531487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW9(port), preemph_reg_value); 9541487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_TX_DW5(port), DPIO_TX_OCALINIT_EN); 9551487f786SFrançois Tigeot mutex_unlock(&dev_priv->sb_lock); 9561487f786SFrançois Tigeot } 9571487f786SFrançois Tigeot 9581487f786SFrançois Tigeot void vlv_phy_pre_pll_enable(struct intel_encoder *encoder) 9591487f786SFrançois Tigeot { 9601487f786SFrançois Tigeot struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); 9611487f786SFrançois Tigeot struct drm_device *dev = encoder->base.dev; 962303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 9631487f786SFrançois Tigeot struct intel_crtc *intel_crtc = 9641487f786SFrançois Tigeot to_intel_crtc(encoder->base.crtc); 9651487f786SFrançois Tigeot enum dpio_channel port = vlv_dport_to_channel(dport); 9661487f786SFrançois Tigeot int pipe = intel_crtc->pipe; 9671487f786SFrançois Tigeot 9681487f786SFrançois Tigeot /* Program Tx lane resets to default */ 9691487f786SFrançois Tigeot mutex_lock(&dev_priv->sb_lock); 9701487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 9711487f786SFrançois Tigeot DPIO_PCS_TX_LANE2_RESET | 9721487f786SFrançois Tigeot DPIO_PCS_TX_LANE1_RESET); 9731487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 9741487f786SFrançois Tigeot DPIO_PCS_CLK_CRI_RXEB_EIOS_EN | 9751487f786SFrançois Tigeot DPIO_PCS_CLK_CRI_RXDIGFILTSG_EN | 9761487f786SFrançois Tigeot (1<<DPIO_PCS_CLK_DATAWIDTH_SHIFT) | 9771487f786SFrançois Tigeot DPIO_PCS_CLK_SOFT_RESET); 9781487f786SFrançois Tigeot 9791487f786SFrançois Tigeot /* Fix up inter-pair skew failure */ 9801487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW12(port), 0x00750f00); 9811487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_TX_DW11(port), 0x00001500); 9821487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_TX_DW14(port), 0x40400000); 9831487f786SFrançois Tigeot mutex_unlock(&dev_priv->sb_lock); 9841487f786SFrançois Tigeot } 9851487f786SFrançois Tigeot 9861487f786SFrançois Tigeot void vlv_phy_pre_encoder_enable(struct intel_encoder *encoder) 9871487f786SFrançois Tigeot { 9881487f786SFrançois Tigeot struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); 9891487f786SFrançois Tigeot struct intel_digital_port *dport = dp_to_dig_port(intel_dp); 9901487f786SFrançois Tigeot struct drm_device *dev = encoder->base.dev; 991303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(dev); 9921487f786SFrançois Tigeot struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); 9931487f786SFrançois Tigeot enum dpio_channel port = vlv_dport_to_channel(dport); 9941487f786SFrançois Tigeot int pipe = intel_crtc->pipe; 9951487f786SFrançois Tigeot u32 val; 9961487f786SFrançois Tigeot 9971487f786SFrançois Tigeot mutex_lock(&dev_priv->sb_lock); 9981487f786SFrançois Tigeot 9991487f786SFrançois Tigeot /* Enable clock channels for this port */ 10001487f786SFrançois Tigeot val = vlv_dpio_read(dev_priv, pipe, VLV_PCS01_DW8(port)); 10011487f786SFrançois Tigeot val = 0; 10021487f786SFrançois Tigeot if (pipe) 10031487f786SFrançois Tigeot val |= (1<<21); 10041487f786SFrançois Tigeot else 10051487f786SFrançois Tigeot val &= ~(1<<21); 10061487f786SFrançois Tigeot val |= 0x001000c4; 10071487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW8(port), val); 10081487f786SFrançois Tigeot 10091487f786SFrançois Tigeot /* Program lane clock */ 10101487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW14(port), 0x00760018); 10111487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW23(port), 0x00400888); 10121487f786SFrançois Tigeot 10131487f786SFrançois Tigeot mutex_unlock(&dev_priv->sb_lock); 10141487f786SFrançois Tigeot } 10151487f786SFrançois Tigeot 10161487f786SFrançois Tigeot void vlv_phy_reset_lanes(struct intel_encoder *encoder) 10171487f786SFrançois Tigeot { 10181487f786SFrançois Tigeot struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); 1019303bf270SFrançois Tigeot struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 10201487f786SFrançois Tigeot struct intel_crtc *intel_crtc = 10211487f786SFrançois Tigeot to_intel_crtc(encoder->base.crtc); 10221487f786SFrançois Tigeot enum dpio_channel port = vlv_dport_to_channel(dport); 10231487f786SFrançois Tigeot int pipe = intel_crtc->pipe; 10241487f786SFrançois Tigeot 10251487f786SFrançois Tigeot mutex_lock(&dev_priv->sb_lock); 10261487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW0(port), 0x00000000); 10271487f786SFrançois Tigeot vlv_dpio_write(dev_priv, pipe, VLV_PCS_DW1(port), 0x00e00060); 10281487f786SFrançois Tigeot mutex_unlock(&dev_priv->sb_lock); 10291487f786SFrançois Tigeot } 1030