diff options
author | Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> | 2016-10-06 12:22:17 -0400 |
---|---|---|
committer | Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com> | 2016-10-28 05:24:01 -0400 |
commit | 47a6bc61b86657646aea38e837a7f25c68cec7f8 (patch) | |
tree | 43bb3b2206c21059ac45d01ba850983cd1b3a5b5 /drivers/gpu/drm/i915/intel_dpio_phy.c | |
parent | b284eedaf74bdbd262f71a7937ca78f45354173f (diff) |
drm/i915: Move broxton phy code to intel_dpio_phy.c
The phy in broxton is also a dpio phy, similar to cherryview but with
programming through MMIO. So move the code together with the other
similar phys.
Signed-off-by: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Reviewed-by: Imre Deak <imre.deak@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/d611de6d256593cf904172db7ff27f164480c228.1475770848.git-series.ander.conselvan.de.oliveira@intel.com
Diffstat (limited to 'drivers/gpu/drm/i915/intel_dpio_phy.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_dpio_phy.c | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 047f48748944..edf0cfd860c4 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c | |||
@@ -23,6 +23,333 @@ | |||
23 | 23 | ||
24 | #include "intel_drv.h" | 24 | #include "intel_drv.h" |
25 | 25 | ||
26 | bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, | ||
27 | enum dpio_phy phy) | ||
28 | { | ||
29 | enum port port; | ||
30 | |||
31 | if (!(I915_READ(BXT_P_CR_GT_DISP_PWRON) & GT_DISPLAY_POWER_ON(phy))) | ||
32 | return false; | ||
33 | |||
34 | if ((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & | ||
35 | (PHY_POWER_GOOD | PHY_RESERVED)) != PHY_POWER_GOOD) { | ||
36 | DRM_DEBUG_DRIVER("DDI PHY %d powered, but power hasn't settled\n", | ||
37 | phy); | ||
38 | |||
39 | return false; | ||
40 | } | ||
41 | |||
42 | if (phy == DPIO_PHY1 && | ||
43 | !(I915_READ(BXT_PORT_REF_DW3(DPIO_PHY1)) & GRC_DONE)) { | ||
44 | DRM_DEBUG_DRIVER("DDI PHY 1 powered, but GRC isn't done\n"); | ||
45 | |||
46 | return false; | ||
47 | } | ||
48 | |||
49 | if (!(I915_READ(BXT_PHY_CTL_FAMILY(phy)) & COMMON_RESET_DIS)) { | ||
50 | DRM_DEBUG_DRIVER("DDI PHY %d powered, but still in reset\n", | ||
51 | phy); | ||
52 | |||
53 | return false; | ||
54 | } | ||
55 | |||
56 | for_each_port_masked(port, | ||
57 | phy == DPIO_PHY0 ? BIT(PORT_B) | BIT(PORT_C) : | ||
58 | BIT(PORT_A)) { | ||
59 | u32 tmp = I915_READ(BXT_PHY_CTL(port)); | ||
60 | |||
61 | if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) { | ||
62 | DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane " | ||
63 | "for port %c powered down " | ||
64 | "(PHY_CTL %08x)\n", | ||
65 | phy, port_name(port), tmp); | ||
66 | |||
67 | return false; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | return true; | ||
72 | } | ||
73 | |||
74 | static u32 bxt_get_grc(struct drm_i915_private *dev_priv, enum dpio_phy phy) | ||
75 | { | ||
76 | u32 val = I915_READ(BXT_PORT_REF_DW6(phy)); | ||
77 | |||
78 | return (val & GRC_CODE_MASK) >> GRC_CODE_SHIFT; | ||
79 | } | ||
80 | |||
81 | static void bxt_phy_wait_grc_done(struct drm_i915_private *dev_priv, | ||
82 | enum dpio_phy phy) | ||
83 | { | ||
84 | if (intel_wait_for_register(dev_priv, | ||
85 | BXT_PORT_REF_DW3(phy), | ||
86 | GRC_DONE, GRC_DONE, | ||
87 | 10)) | ||
88 | DRM_ERROR("timeout waiting for PHY%d GRC\n", phy); | ||
89 | } | ||
90 | |||
91 | void bxt_ddi_phy_init(struct drm_i915_private *dev_priv, enum dpio_phy phy) | ||
92 | { | ||
93 | u32 val; | ||
94 | |||
95 | if (bxt_ddi_phy_is_enabled(dev_priv, phy)) { | ||
96 | /* Still read out the GRC value for state verification */ | ||
97 | if (phy == DPIO_PHY0) | ||
98 | dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, phy); | ||
99 | |||
100 | if (bxt_ddi_phy_verify_state(dev_priv, phy)) { | ||
101 | DRM_DEBUG_DRIVER("DDI PHY %d already enabled, " | ||
102 | "won't reprogram it\n", phy); | ||
103 | |||
104 | return; | ||
105 | } | ||
106 | |||
107 | DRM_DEBUG_DRIVER("DDI PHY %d enabled with invalid state, " | ||
108 | "force reprogramming it\n", phy); | ||
109 | } | ||
110 | |||
111 | val = I915_READ(BXT_P_CR_GT_DISP_PWRON); | ||
112 | val |= GT_DISPLAY_POWER_ON(phy); | ||
113 | I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); | ||
114 | |||
115 | /* | ||
116 | * The PHY registers start out inaccessible and respond to reads with | ||
117 | * all 1s. Eventually they become accessible as they power up, then | ||
118 | * the reserved bit will give the default 0. Poll on the reserved bit | ||
119 | * becoming 0 to find when the PHY is accessible. | ||
120 | * HW team confirmed that the time to reach phypowergood status is | ||
121 | * anywhere between 50 us and 100us. | ||
122 | */ | ||
123 | if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) & | ||
124 | (PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) { | ||
125 | DRM_ERROR("timeout during PHY%d power on\n", phy); | ||
126 | } | ||
127 | |||
128 | /* Program PLL Rcomp code offset */ | ||
129 | val = I915_READ(BXT_PORT_CL1CM_DW9(phy)); | ||
130 | val &= ~IREF0RC_OFFSET_MASK; | ||
131 | val |= 0xE4 << IREF0RC_OFFSET_SHIFT; | ||
132 | I915_WRITE(BXT_PORT_CL1CM_DW9(phy), val); | ||
133 | |||
134 | val = I915_READ(BXT_PORT_CL1CM_DW10(phy)); | ||
135 | val &= ~IREF1RC_OFFSET_MASK; | ||
136 | val |= 0xE4 << IREF1RC_OFFSET_SHIFT; | ||
137 | I915_WRITE(BXT_PORT_CL1CM_DW10(phy), val); | ||
138 | |||
139 | /* Program power gating */ | ||
140 | val = I915_READ(BXT_PORT_CL1CM_DW28(phy)); | ||
141 | val |= OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | | ||
142 | SUS_CLK_CONFIG; | ||
143 | I915_WRITE(BXT_PORT_CL1CM_DW28(phy), val); | ||
144 | |||
145 | if (phy == DPIO_PHY0) { | ||
146 | val = I915_READ(BXT_PORT_CL2CM_DW6_BC); | ||
147 | val |= DW6_OLDO_DYN_PWR_DOWN_EN; | ||
148 | I915_WRITE(BXT_PORT_CL2CM_DW6_BC, val); | ||
149 | } | ||
150 | |||
151 | val = I915_READ(BXT_PORT_CL1CM_DW30(phy)); | ||
152 | val &= ~OCL2_LDOFUSE_PWR_DIS; | ||
153 | /* | ||
154 | * On PHY1 disable power on the second channel, since no port is | ||
155 | * connected there. On PHY0 both channels have a port, so leave it | ||
156 | * enabled. | ||
157 | * TODO: port C is only connected on BXT-P, so on BXT0/1 we should | ||
158 | * power down the second channel on PHY0 as well. | ||
159 | * | ||
160 | * FIXME: Clarify programming of the following, the register is | ||
161 | * read-only with bit 6 fixed at 0 at least in stepping A. | ||
162 | */ | ||
163 | if (phy == DPIO_PHY1) | ||
164 | val |= OCL2_LDOFUSE_PWR_DIS; | ||
165 | I915_WRITE(BXT_PORT_CL1CM_DW30(phy), val); | ||
166 | |||
167 | if (phy == DPIO_PHY0) { | ||
168 | uint32_t grc_code; | ||
169 | /* | ||
170 | * PHY0 isn't connected to an RCOMP resistor so copy over | ||
171 | * the corresponding calibrated value from PHY1, and disable | ||
172 | * the automatic calibration on PHY0. | ||
173 | */ | ||
174 | val = dev_priv->bxt_phy_grc = bxt_get_grc(dev_priv, DPIO_PHY1); | ||
175 | grc_code = val << GRC_CODE_FAST_SHIFT | | ||
176 | val << GRC_CODE_SLOW_SHIFT | | ||
177 | val; | ||
178 | I915_WRITE(BXT_PORT_REF_DW6(DPIO_PHY0), grc_code); | ||
179 | |||
180 | val = I915_READ(BXT_PORT_REF_DW8(DPIO_PHY0)); | ||
181 | val |= GRC_DIS | GRC_RDY_OVRD; | ||
182 | I915_WRITE(BXT_PORT_REF_DW8(DPIO_PHY0), val); | ||
183 | } | ||
184 | |||
185 | val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); | ||
186 | val |= COMMON_RESET_DIS; | ||
187 | I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); | ||
188 | |||
189 | if (phy == DPIO_PHY1) | ||
190 | bxt_phy_wait_grc_done(dev_priv, DPIO_PHY1); | ||
191 | } | ||
192 | |||
193 | void bxt_ddi_phy_uninit(struct drm_i915_private *dev_priv, enum dpio_phy phy) | ||
194 | { | ||
195 | uint32_t val; | ||
196 | |||
197 | val = I915_READ(BXT_PHY_CTL_FAMILY(phy)); | ||
198 | val &= ~COMMON_RESET_DIS; | ||
199 | I915_WRITE(BXT_PHY_CTL_FAMILY(phy), val); | ||
200 | |||
201 | val = I915_READ(BXT_P_CR_GT_DISP_PWRON); | ||
202 | val &= ~GT_DISPLAY_POWER_ON(phy); | ||
203 | I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val); | ||
204 | } | ||
205 | |||
206 | static bool __printf(6, 7) | ||
207 | __phy_reg_verify_state(struct drm_i915_private *dev_priv, enum dpio_phy phy, | ||
208 | i915_reg_t reg, u32 mask, u32 expected, | ||
209 | const char *reg_fmt, ...) | ||
210 | { | ||
211 | struct va_format vaf; | ||
212 | va_list args; | ||
213 | u32 val; | ||
214 | |||
215 | val = I915_READ(reg); | ||
216 | if ((val & mask) == expected) | ||
217 | return true; | ||
218 | |||
219 | va_start(args, reg_fmt); | ||
220 | vaf.fmt = reg_fmt; | ||
221 | vaf.va = &args; | ||
222 | |||
223 | DRM_DEBUG_DRIVER("DDI PHY %d reg %pV [%08x] state mismatch: " | ||
224 | "current %08x, expected %08x (mask %08x)\n", | ||
225 | phy, &vaf, reg.reg, val, (val & ~mask) | expected, | ||
226 | mask); | ||
227 | |||
228 | va_end(args); | ||
229 | |||
230 | return false; | ||
231 | } | ||
232 | |||
233 | bool bxt_ddi_phy_verify_state(struct drm_i915_private *dev_priv, | ||
234 | enum dpio_phy phy) | ||
235 | { | ||
236 | uint32_t mask; | ||
237 | bool ok; | ||
238 | |||
239 | #define _CHK(reg, mask, exp, fmt, ...) \ | ||
240 | __phy_reg_verify_state(dev_priv, phy, reg, mask, exp, fmt, \ | ||
241 | ## __VA_ARGS__) | ||
242 | |||
243 | if (!bxt_ddi_phy_is_enabled(dev_priv, phy)) | ||
244 | return false; | ||
245 | |||
246 | ok = true; | ||
247 | |||
248 | /* PLL Rcomp code offset */ | ||
249 | ok &= _CHK(BXT_PORT_CL1CM_DW9(phy), | ||
250 | IREF0RC_OFFSET_MASK, 0xe4 << IREF0RC_OFFSET_SHIFT, | ||
251 | "BXT_PORT_CL1CM_DW9(%d)", phy); | ||
252 | ok &= _CHK(BXT_PORT_CL1CM_DW10(phy), | ||
253 | IREF1RC_OFFSET_MASK, 0xe4 << IREF1RC_OFFSET_SHIFT, | ||
254 | "BXT_PORT_CL1CM_DW10(%d)", phy); | ||
255 | |||
256 | /* Power gating */ | ||
257 | mask = OCL1_POWER_DOWN_EN | DW28_OLDO_DYN_PWR_DOWN_EN | SUS_CLK_CONFIG; | ||
258 | ok &= _CHK(BXT_PORT_CL1CM_DW28(phy), mask, mask, | ||
259 | "BXT_PORT_CL1CM_DW28(%d)", phy); | ||
260 | |||
261 | if (phy == DPIO_PHY0) | ||
262 | ok &= _CHK(BXT_PORT_CL2CM_DW6_BC, | ||
263 | DW6_OLDO_DYN_PWR_DOWN_EN, DW6_OLDO_DYN_PWR_DOWN_EN, | ||
264 | "BXT_PORT_CL2CM_DW6_BC"); | ||
265 | |||
266 | /* | ||
267 | * TODO: Verify BXT_PORT_CL1CM_DW30 bit OCL2_LDOFUSE_PWR_DIS, | ||
268 | * at least on stepping A this bit is read-only and fixed at 0. | ||
269 | */ | ||
270 | |||
271 | if (phy == DPIO_PHY0) { | ||
272 | u32 grc_code = dev_priv->bxt_phy_grc; | ||
273 | |||
274 | grc_code = grc_code << GRC_CODE_FAST_SHIFT | | ||
275 | grc_code << GRC_CODE_SLOW_SHIFT | | ||
276 | grc_code; | ||
277 | mask = GRC_CODE_FAST_MASK | GRC_CODE_SLOW_MASK | | ||
278 | GRC_CODE_NOM_MASK; | ||
279 | ok &= _CHK(BXT_PORT_REF_DW6(DPIO_PHY0), mask, grc_code, | ||
280 | "BXT_PORT_REF_DW6(%d)", DPIO_PHY0); | ||
281 | |||
282 | mask = GRC_DIS | GRC_RDY_OVRD; | ||
283 | ok &= _CHK(BXT_PORT_REF_DW8(DPIO_PHY0), mask, mask, | ||
284 | "BXT_PORT_REF_DW8(%d)", DPIO_PHY0); | ||
285 | } | ||
286 | |||
287 | return ok; | ||
288 | #undef _CHK | ||
289 | } | ||
290 | |||
291 | uint8_t | ||
292 | bxt_ddi_phy_calc_lane_lat_optim_mask(struct intel_encoder *encoder, | ||
293 | uint8_t lane_count) | ||
294 | { | ||
295 | switch (lane_count) { | ||
296 | case 1: | ||
297 | return 0; | ||
298 | case 2: | ||
299 | return BIT(2) | BIT(0); | ||
300 | case 4: | ||
301 | return BIT(3) | BIT(2) | BIT(0); | ||
302 | default: | ||
303 | MISSING_CASE(lane_count); | ||
304 | |||
305 | return 0; | ||
306 | } | ||
307 | } | ||
308 | |||
309 | void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder, | ||
310 | uint8_t lane_lat_optim_mask) | ||
311 | { | ||
312 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); | ||
313 | struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); | ||
314 | enum port port = dport->port; | ||
315 | int lane; | ||
316 | |||
317 | for (lane = 0; lane < 4; lane++) { | ||
318 | u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); | ||
319 | |||
320 | /* | ||
321 | * Note that on CHV this flag is called UPAR, but has | ||
322 | * the same function. | ||
323 | */ | ||
324 | val &= ~LATENCY_OPTIM; | ||
325 | if (lane_lat_optim_mask & BIT(lane)) | ||
326 | val |= LATENCY_OPTIM; | ||
327 | |||
328 | I915_WRITE(BXT_PORT_TX_DW14_LN(port, lane), val); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | uint8_t | ||
333 | bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder) | ||
334 | { | ||
335 | struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); | ||
336 | struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); | ||
337 | enum port port = dport->port; | ||
338 | int lane; | ||
339 | uint8_t mask; | ||
340 | |||
341 | mask = 0; | ||
342 | for (lane = 0; lane < 4; lane++) { | ||
343 | u32 val = I915_READ(BXT_PORT_TX_DW14_LN(port, lane)); | ||
344 | |||
345 | if (val & LATENCY_OPTIM) | ||
346 | mask |= BIT(lane); | ||
347 | } | ||
348 | |||
349 | return mask; | ||
350 | } | ||
351 | |||
352 | |||
26 | void chv_set_phy_signal_level(struct intel_encoder *encoder, | 353 | void chv_set_phy_signal_level(struct intel_encoder *encoder, |
27 | u32 deemph_reg_value, u32 margin_reg_value, | 354 | u32 deemph_reg_value, u32 margin_reg_value, |
28 | bool uniq_trans_scale) | 355 | bool uniq_trans_scale) |