xref: /dragonfly/sys/dev/drm/i915/intel_dpio_phy.c (revision 4be47400)
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