blob: b711407014d21b41d77d290111260811fe390f1e [file] [log] [blame]
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001/*
2 * Copyright © 2006-2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "intel_drv.h"
25
26struct intel_shared_dpll *
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020027intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
28 enum intel_dpll_id id)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020029{
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020030 return &dev_priv->shared_dplls[id];
31}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020032
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020033enum intel_dpll_id
34intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
35 struct intel_shared_dpll *pll)
36{
37 if (WARN_ON(pll < dev_priv->shared_dplls||
38 pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll]))
39 return -1;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020040
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020041 return (enum intel_dpll_id) (pll - dev_priv->shared_dplls);
42}
43
44void
45intel_shared_dpll_config_get(struct intel_shared_dpll_config *config,
46 struct intel_shared_dpll *pll,
47 struct intel_crtc *crtc)
48{
49 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
50 enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
51
52 config[id].crtc_mask |= 1 << crtc->pipe;
53}
54
55void
56intel_shared_dpll_config_put(struct intel_shared_dpll_config *config,
57 struct intel_shared_dpll *pll,
58 struct intel_crtc *crtc)
59{
60 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
61 enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
62
63 config[id].crtc_mask &= ~(1 << crtc->pipe);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020064}
65
66/* For ILK+ */
67void assert_shared_dpll(struct drm_i915_private *dev_priv,
68 struct intel_shared_dpll *pll,
69 bool state)
70{
71 bool cur_state;
72 struct intel_dpll_hw_state hw_state;
73
74 if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
75 return;
76
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +020077 cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020078 I915_STATE_WARN(cur_state != state,
79 "%s assertion failure (expected %s, current %s)\n",
80 pll->name, onoff(state), onoff(cur_state));
81}
82
83void intel_prepare_shared_dpll(struct intel_crtc *crtc)
84{
85 struct drm_device *dev = crtc->base.dev;
86 struct drm_i915_private *dev_priv = dev->dev_private;
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020087 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020088
89 if (WARN_ON(pll == NULL))
90 return;
91
92 WARN_ON(!pll->config.crtc_mask);
93 if (pll->active == 0) {
94 DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
95 WARN_ON(pll->on);
96 assert_shared_dpll_disabled(dev_priv, pll);
97
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +020098 pll->funcs.mode_set(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020099 }
100}
101
102/**
103 * intel_enable_shared_dpll - enable PCH PLL
104 * @dev_priv: i915 private structure
105 * @pipe: pipe PLL to enable
106 *
107 * The PCH PLL needs to be enabled before the PCH transcoder, since it
108 * drives the transcoder clock.
109 */
110void intel_enable_shared_dpll(struct intel_crtc *crtc)
111{
112 struct drm_device *dev = crtc->base.dev;
113 struct drm_i915_private *dev_priv = dev->dev_private;
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200114 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200115
116 if (WARN_ON(pll == NULL))
117 return;
118
119 if (WARN_ON(pll->config.crtc_mask == 0))
120 return;
121
122 DRM_DEBUG_KMS("enable %s (active %d, on? %d) for crtc %d\n",
123 pll->name, pll->active, pll->on,
124 crtc->base.base.id);
125
126 if (pll->active++) {
127 WARN_ON(!pll->on);
128 assert_shared_dpll_enabled(dev_priv, pll);
129 return;
130 }
131 WARN_ON(pll->on);
132
133 intel_display_power_get(dev_priv, POWER_DOMAIN_PLLS);
134
135 DRM_DEBUG_KMS("enabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200136 pll->funcs.enable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200137 pll->on = true;
138}
139
140void intel_disable_shared_dpll(struct intel_crtc *crtc)
141{
142 struct drm_device *dev = crtc->base.dev;
143 struct drm_i915_private *dev_priv = dev->dev_private;
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200144 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200145
146 /* PCH only available on ILK+ */
147 if (INTEL_INFO(dev)->gen < 5)
148 return;
149
150 if (pll == NULL)
151 return;
152
153 if (WARN_ON(!(pll->config.crtc_mask & (1 << drm_crtc_index(&crtc->base)))))
154 return;
155
156 DRM_DEBUG_KMS("disable %s (active %d, on? %d) for crtc %d\n",
157 pll->name, pll->active, pll->on,
158 crtc->base.base.id);
159
160 if (WARN_ON(pll->active == 0)) {
161 assert_shared_dpll_disabled(dev_priv, pll);
162 return;
163 }
164
165 assert_shared_dpll_enabled(dev_priv, pll);
166 WARN_ON(!pll->on);
167 if (--pll->active)
168 return;
169
170 DRM_DEBUG_KMS("disabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200171 pll->funcs.disable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200172 pll->on = false;
173
174 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
175}
176
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200177static struct intel_shared_dpll *
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200178intel_find_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200179 struct intel_crtc_state *crtc_state,
180 enum intel_dpll_id range_min,
181 enum intel_dpll_id range_max)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200182{
183 struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
184 struct intel_shared_dpll *pll;
185 struct intel_shared_dpll_config *shared_dpll;
186 enum intel_dpll_id i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200187
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200188 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
189
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200190 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200191 pll = &dev_priv->shared_dplls[i];
192
193 /* Only want to check enabled timings first */
194 if (shared_dpll[i].crtc_mask == 0)
195 continue;
196
197 if (memcmp(&crtc_state->dpll_hw_state,
198 &shared_dpll[i].hw_state,
199 sizeof(crtc_state->dpll_hw_state)) == 0) {
200 DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, ative %d)\n",
201 crtc->base.base.id, pll->name,
202 shared_dpll[i].crtc_mask,
203 pll->active);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200204 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200205 }
206 }
207
208 /* Ok no matching timings, maybe there's a free one? */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200209 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200210 pll = &dev_priv->shared_dplls[i];
211 if (shared_dpll[i].crtc_mask == 0) {
212 DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
213 crtc->base.base.id, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200214 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200215 }
216 }
217
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200218 return NULL;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200219}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200220
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200221static void
222intel_reference_shared_dpll(struct intel_shared_dpll *pll,
223 struct intel_crtc_state *crtc_state)
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200224{
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200225 struct intel_shared_dpll_config *shared_dpll;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200226 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
227 enum intel_dpll_id i = pll->id;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200228
229 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
230
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200231 if (shared_dpll[i].crtc_mask == 0)
232 shared_dpll[i].hw_state =
233 crtc_state->dpll_hw_state;
234
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200235 crtc_state->shared_dpll = pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200236 DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
237 pipe_name(crtc->pipe));
238
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200239 intel_shared_dpll_config_get(shared_dpll, pll, crtc);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200240}
241
242void intel_shared_dpll_commit(struct drm_atomic_state *state)
243{
244 struct drm_i915_private *dev_priv = to_i915(state->dev);
245 struct intel_shared_dpll_config *shared_dpll;
246 struct intel_shared_dpll *pll;
247 enum intel_dpll_id i;
248
249 if (!to_intel_atomic_state(state)->dpll_set)
250 return;
251
252 shared_dpll = to_intel_atomic_state(state)->shared_dpll;
253 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
254 pll = &dev_priv->shared_dplls[i];
255 pll->config = shared_dpll[i];
256 }
257}
258
259static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
260 struct intel_shared_dpll *pll,
261 struct intel_dpll_hw_state *hw_state)
262{
263 uint32_t val;
264
265 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
266 return false;
267
268 val = I915_READ(PCH_DPLL(pll->id));
269 hw_state->dpll = val;
270 hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
271 hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
272
273 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
274
275 return val & DPLL_VCO_ENABLE;
276}
277
278static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
279 struct intel_shared_dpll *pll)
280{
281 I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
282 I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
283}
284
285static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
286{
287 u32 val;
288 bool enabled;
289
290 I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev)));
291
292 val = I915_READ(PCH_DREF_CONTROL);
293 enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
294 DREF_SUPERSPREAD_SOURCE_MASK));
295 I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
296}
297
298static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
299 struct intel_shared_dpll *pll)
300{
301 /* PCH refclock must be enabled first */
302 ibx_assert_pch_refclk_enabled(dev_priv);
303
304 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
305
306 /* Wait for the clocks to stabilize. */
307 POSTING_READ(PCH_DPLL(pll->id));
308 udelay(150);
309
310 /* The pixel multiplier can only be updated once the
311 * DPLL is enabled and the clocks are stable.
312 *
313 * So write it again.
314 */
315 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
316 POSTING_READ(PCH_DPLL(pll->id));
317 udelay(200);
318}
319
320static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
321 struct intel_shared_dpll *pll)
322{
323 struct drm_device *dev = dev_priv->dev;
324 struct intel_crtc *crtc;
325
326 /* Make sure no transcoder isn't still depending on us. */
327 for_each_intel_crtc(dev, crtc) {
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200328 if (crtc->config->shared_dpll == pll)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200329 assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
330 }
331
332 I915_WRITE(PCH_DPLL(pll->id), 0);
333 POSTING_READ(PCH_DPLL(pll->id));
334 udelay(200);
335}
336
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200337static struct intel_shared_dpll *
338ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state)
339{
340 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
341 struct intel_shared_dpll *pll;
342 enum intel_dpll_id i;
343
344 if (HAS_PCH_IBX(dev_priv)) {
345 /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
346 i = (enum intel_dpll_id) crtc->pipe;
347 pll = &dev_priv->shared_dplls[i];
348
349 DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
350 crtc->base.base.id, pll->name);
351 } else {
352 pll = intel_find_shared_dpll(crtc, crtc_state,
353 DPLL_ID_PCH_PLL_A,
354 DPLL_ID_PCH_PLL_B);
355 }
356
357 /* reference the pll */
358 intel_reference_shared_dpll(pll, crtc_state);
359
360 return pll;
361}
362
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200363static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
364 .mode_set = ibx_pch_dpll_mode_set,
365 .enable = ibx_pch_dpll_enable,
366 .disable = ibx_pch_dpll_disable,
367 .get_hw_state = ibx_pch_dpll_get_hw_state,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200368};
369
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200370static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
371 struct intel_shared_dpll *pll)
372{
373 I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
374 POSTING_READ(WRPLL_CTL(pll->id));
375 udelay(20);
376}
377
378static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
379 struct intel_shared_dpll *pll)
380{
381 I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
382 POSTING_READ(SPLL_CTL);
383 udelay(20);
384}
385
386static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
387 struct intel_shared_dpll *pll)
388{
389 uint32_t val;
390
391 val = I915_READ(WRPLL_CTL(pll->id));
392 I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
393 POSTING_READ(WRPLL_CTL(pll->id));
394}
395
396static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
397 struct intel_shared_dpll *pll)
398{
399 uint32_t val;
400
401 val = I915_READ(SPLL_CTL);
402 I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
403 POSTING_READ(SPLL_CTL);
404}
405
406static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
407 struct intel_shared_dpll *pll,
408 struct intel_dpll_hw_state *hw_state)
409{
410 uint32_t val;
411
412 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
413 return false;
414
415 val = I915_READ(WRPLL_CTL(pll->id));
416 hw_state->wrpll = val;
417
418 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
419
420 return val & WRPLL_PLL_ENABLE;
421}
422
423static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
424 struct intel_shared_dpll *pll,
425 struct intel_dpll_hw_state *hw_state)
426{
427 uint32_t val;
428
429 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
430 return false;
431
432 val = I915_READ(SPLL_CTL);
433 hw_state->spll = val;
434
435 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
436
437 return val & SPLL_PLL_ENABLE;
438}
439
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200440static struct intel_shared_dpll *
441hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state)
442{
443 struct intel_shared_dpll *pll;
444
445 pll = intel_find_shared_dpll(crtc, crtc_state,
446 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
447 if (pll)
448 intel_reference_shared_dpll(pll, crtc_state);
449
450 return pll;
451}
452
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200453
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200454static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
455 .enable = hsw_ddi_wrpll_enable,
456 .disable = hsw_ddi_wrpll_disable,
457 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200458};
459
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200460static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
461 .enable = hsw_ddi_spll_enable,
462 .disable = hsw_ddi_spll_disable,
463 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200464};
465
466struct skl_dpll_regs {
467 i915_reg_t ctl, cfgcr1, cfgcr2;
468};
469
470/* this array is indexed by the *shared* pll id */
471static const struct skl_dpll_regs skl_dpll_regs[3] = {
472 {
473 /* DPLL 1 */
474 .ctl = LCPLL2_CTL,
475 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
476 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
477 },
478 {
479 /* DPLL 2 */
480 .ctl = WRPLL_CTL(0),
481 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
482 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
483 },
484 {
485 /* DPLL 3 */
486 .ctl = WRPLL_CTL(1),
487 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
488 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
489 },
490};
491
492static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
493 struct intel_shared_dpll *pll)
494{
495 uint32_t val;
496 unsigned int dpll;
497 const struct skl_dpll_regs *regs = skl_dpll_regs;
498
499 /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
500 dpll = pll->id + 1;
501
502 val = I915_READ(DPLL_CTRL1);
503
504 val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) |
505 DPLL_CTRL1_LINK_RATE_MASK(dpll));
506 val |= pll->config.hw_state.ctrl1 << (dpll * 6);
507
508 I915_WRITE(DPLL_CTRL1, val);
509 POSTING_READ(DPLL_CTRL1);
510
511 I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
512 I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
513 POSTING_READ(regs[pll->id].cfgcr1);
514 POSTING_READ(regs[pll->id].cfgcr2);
515
516 /* the enable bit is always bit 31 */
517 I915_WRITE(regs[pll->id].ctl,
518 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
519
520 if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5))
521 DRM_ERROR("DPLL %d not locked\n", dpll);
522}
523
524static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
525 struct intel_shared_dpll *pll)
526{
527 const struct skl_dpll_regs *regs = skl_dpll_regs;
528
529 /* the enable bit is always bit 31 */
530 I915_WRITE(regs[pll->id].ctl,
531 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
532 POSTING_READ(regs[pll->id].ctl);
533}
534
535static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
536 struct intel_shared_dpll *pll,
537 struct intel_dpll_hw_state *hw_state)
538{
539 uint32_t val;
540 unsigned int dpll;
541 const struct skl_dpll_regs *regs = skl_dpll_regs;
542 bool ret;
543
544 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
545 return false;
546
547 ret = false;
548
549 /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
550 dpll = pll->id + 1;
551
552 val = I915_READ(regs[pll->id].ctl);
553 if (!(val & LCPLL_PLL_ENABLE))
554 goto out;
555
556 val = I915_READ(DPLL_CTRL1);
557 hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f;
558
559 /* avoid reading back stale values if HDMI mode is not enabled */
560 if (val & DPLL_CTRL1_HDMI_MODE(dpll)) {
561 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
562 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
563 }
564 ret = true;
565
566out:
567 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
568
569 return ret;
570}
571
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200572static struct intel_shared_dpll *
573skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state)
574{
575 struct intel_shared_dpll *pll;
576
577 pll = intel_find_shared_dpll(crtc, crtc_state,
578 DPLL_ID_SKL_DPLL1, DPLL_ID_SKL_DPLL3);
579 if (pll)
580 intel_reference_shared_dpll(pll, crtc_state);
581
582 return pll;
583}
584
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200585static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
586 .enable = skl_ddi_pll_enable,
587 .disable = skl_ddi_pll_disable,
588 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200589};
590
591static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
592 struct intel_shared_dpll *pll)
593{
594 uint32_t temp;
595 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
596
597 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
598 temp &= ~PORT_PLL_REF_SEL;
599 /* Non-SSC reference */
600 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
601
602 /* Disable 10 bit clock */
603 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
604 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
605 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
606
607 /* Write P1 & P2 */
608 temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
609 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
610 temp |= pll->config.hw_state.ebb0;
611 I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
612
613 /* Write M2 integer */
614 temp = I915_READ(BXT_PORT_PLL(port, 0));
615 temp &= ~PORT_PLL_M2_MASK;
616 temp |= pll->config.hw_state.pll0;
617 I915_WRITE(BXT_PORT_PLL(port, 0), temp);
618
619 /* Write N */
620 temp = I915_READ(BXT_PORT_PLL(port, 1));
621 temp &= ~PORT_PLL_N_MASK;
622 temp |= pll->config.hw_state.pll1;
623 I915_WRITE(BXT_PORT_PLL(port, 1), temp);
624
625 /* Write M2 fraction */
626 temp = I915_READ(BXT_PORT_PLL(port, 2));
627 temp &= ~PORT_PLL_M2_FRAC_MASK;
628 temp |= pll->config.hw_state.pll2;
629 I915_WRITE(BXT_PORT_PLL(port, 2), temp);
630
631 /* Write M2 fraction enable */
632 temp = I915_READ(BXT_PORT_PLL(port, 3));
633 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
634 temp |= pll->config.hw_state.pll3;
635 I915_WRITE(BXT_PORT_PLL(port, 3), temp);
636
637 /* Write coeff */
638 temp = I915_READ(BXT_PORT_PLL(port, 6));
639 temp &= ~PORT_PLL_PROP_COEFF_MASK;
640 temp &= ~PORT_PLL_INT_COEFF_MASK;
641 temp &= ~PORT_PLL_GAIN_CTL_MASK;
642 temp |= pll->config.hw_state.pll6;
643 I915_WRITE(BXT_PORT_PLL(port, 6), temp);
644
645 /* Write calibration val */
646 temp = I915_READ(BXT_PORT_PLL(port, 8));
647 temp &= ~PORT_PLL_TARGET_CNT_MASK;
648 temp |= pll->config.hw_state.pll8;
649 I915_WRITE(BXT_PORT_PLL(port, 8), temp);
650
651 temp = I915_READ(BXT_PORT_PLL(port, 9));
652 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
653 temp |= pll->config.hw_state.pll9;
654 I915_WRITE(BXT_PORT_PLL(port, 9), temp);
655
656 temp = I915_READ(BXT_PORT_PLL(port, 10));
657 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
658 temp &= ~PORT_PLL_DCO_AMP_MASK;
659 temp |= pll->config.hw_state.pll10;
660 I915_WRITE(BXT_PORT_PLL(port, 10), temp);
661
662 /* Recalibrate with new settings */
663 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
664 temp |= PORT_PLL_RECALIBRATE;
665 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
666 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
667 temp |= pll->config.hw_state.ebb4;
668 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
669
670 /* Enable PLL */
671 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
672 temp |= PORT_PLL_ENABLE;
673 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
674 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
675
676 if (wait_for_atomic_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
677 PORT_PLL_LOCK), 200))
678 DRM_ERROR("PLL %d not locked\n", port);
679
680 /*
681 * While we write to the group register to program all lanes at once we
682 * can read only lane registers and we pick lanes 0/1 for that.
683 */
684 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
685 temp &= ~LANE_STAGGER_MASK;
686 temp &= ~LANESTAGGER_STRAP_OVRD;
687 temp |= pll->config.hw_state.pcsdw12;
688 I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
689}
690
691static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
692 struct intel_shared_dpll *pll)
693{
694 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
695 uint32_t temp;
696
697 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
698 temp &= ~PORT_PLL_ENABLE;
699 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
700 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
701}
702
703static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
704 struct intel_shared_dpll *pll,
705 struct intel_dpll_hw_state *hw_state)
706{
707 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
708 uint32_t val;
709 bool ret;
710
711 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
712 return false;
713
714 ret = false;
715
716 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
717 if (!(val & PORT_PLL_ENABLE))
718 goto out;
719
720 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
721 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
722
723 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
724 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
725
726 hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
727 hw_state->pll0 &= PORT_PLL_M2_MASK;
728
729 hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
730 hw_state->pll1 &= PORT_PLL_N_MASK;
731
732 hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
733 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
734
735 hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
736 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
737
738 hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
739 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
740 PORT_PLL_INT_COEFF_MASK |
741 PORT_PLL_GAIN_CTL_MASK;
742
743 hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
744 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
745
746 hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
747 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
748
749 hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
750 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
751 PORT_PLL_DCO_AMP_MASK;
752
753 /*
754 * While we write to the group register to program all lanes at once we
755 * can read only lane registers. We configure all lanes the same way, so
756 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
757 */
758 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
759 if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
760 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
761 hw_state->pcsdw12,
762 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
763 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
764
765 ret = true;
766
767out:
768 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
769
770 return ret;
771}
772
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200773static struct intel_shared_dpll *
774bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state)
775{
776 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
777 struct intel_encoder *encoder;
778 struct intel_digital_port *intel_dig_port;
779 struct intel_shared_dpll *pll;
780 enum intel_dpll_id i;
781
782 /* PLL is attached to port in bxt */
783 encoder = intel_ddi_get_crtc_new_encoder(crtc_state);
784 if (WARN_ON(!encoder))
785 return NULL;
786
787 intel_dig_port = enc_to_dig_port(&encoder->base);
788 /* 1:1 mapping between ports and PLLs */
789 i = (enum intel_dpll_id)intel_dig_port->port;
790 pll = &dev_priv->shared_dplls[i];
791 DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
792 crtc->base.base.id, pll->name);
793
794 intel_reference_shared_dpll(pll, crtc_state);
795
796 return pll;
797}
798
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200799static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
800 .enable = bxt_ddi_pll_enable,
801 .disable = bxt_ddi_pll_disable,
802 .get_hw_state = bxt_ddi_pll_get_hw_state,
803};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200804
805static void intel_ddi_pll_init(struct drm_device *dev)
806{
807 struct drm_i915_private *dev_priv = dev->dev_private;
808 uint32_t val = I915_READ(LCPLL_CTL);
809
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200810 if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
811 int cdclk_freq;
812
813 cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
814 dev_priv->skl_boot_cdclk = cdclk_freq;
815 if (skl_sanitize_cdclk(dev_priv))
816 DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
817 if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
818 DRM_ERROR("LCPLL1 is disabled\n");
819 } else if (IS_BROXTON(dev)) {
820 broxton_init_cdclk(dev);
821 broxton_ddi_phy_init(dev);
822 } else {
823 /*
824 * The LCPLL register should be turned on by the BIOS. For now
825 * let's just check its state and print errors in case
826 * something is wrong. Don't even try to turn it on.
827 */
828
829 if (val & LCPLL_CD_SOURCE_FCLK)
830 DRM_ERROR("CDCLK source is not LCPLL\n");
831
832 if (val & LCPLL_PLL_DISABLE)
833 DRM_ERROR("LCPLL is disabled\n");
834 }
835}
836
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200837struct dpll_info {
838 const char *name;
839 const int id;
840 const struct intel_shared_dpll_funcs *funcs;
841};
842
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200843struct intel_dpll_mgr {
844 const struct dpll_info *dpll_info;
845
846 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
847 struct intel_crtc_state *crtc_state);
848};
849
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200850static const struct dpll_info pch_plls[] = {
851 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs },
852 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs },
853 { NULL, -1, NULL },
854};
855
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200856static const struct intel_dpll_mgr pch_pll_mgr = {
857 .dpll_info = pch_plls,
858 .get_dpll = ibx_get_dpll,
859};
860
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200861static const struct dpll_info hsw_plls[] = {
862 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs },
863 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs },
864 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs },
865 { NULL, -1, NULL, },
866};
867
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200868static const struct intel_dpll_mgr hsw_pll_mgr = {
869 .dpll_info = hsw_plls,
870 .get_dpll = hsw_get_dpll,
871};
872
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200873static const struct dpll_info skl_plls[] = {
874 { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs },
875 { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs },
876 { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs },
877 { NULL, -1, NULL, },
878};
879
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200880static const struct intel_dpll_mgr skl_pll_mgr = {
881 .dpll_info = skl_plls,
882 .get_dpll = skl_get_dpll,
883};
884
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200885static const struct dpll_info bxt_plls[] = {
886 { "PORT PLL A", 0, &bxt_ddi_pll_funcs },
887 { "PORT PLL B", 1, &bxt_ddi_pll_funcs },
888 { "PORT PLL C", 2, &bxt_ddi_pll_funcs },
889 { NULL, -1, NULL, },
890};
891
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200892static const struct intel_dpll_mgr bxt_pll_mgr = {
893 .dpll_info = bxt_plls,
894 .get_dpll = bxt_get_dpll,
895};
896
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200897void intel_shared_dpll_init(struct drm_device *dev)
898{
899 struct drm_i915_private *dev_priv = dev->dev_private;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200900 const struct intel_dpll_mgr *dpll_mgr = NULL;
901 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200902 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200903
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200904 if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200905 dpll_mgr = &skl_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200906 else if IS_BROXTON(dev)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200907 dpll_mgr = &bxt_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200908 else if (HAS_DDI(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200909 dpll_mgr = &hsw_pll_mgr;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200910 else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200911 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200912
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200913 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200914 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200915 return;
916 }
917
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200918 dpll_info = dpll_mgr->dpll_info;
919
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200920 for (i = 0; dpll_info[i].id >= 0; i++) {
921 WARN_ON(i != dpll_info[i].id);
922
923 dev_priv->shared_dplls[i].id = dpll_info[i].id;
924 dev_priv->shared_dplls[i].name = dpll_info[i].name;
925 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
926 }
927
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200928 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200929 dev_priv->num_shared_dpll = i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200930
931 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200932
933 /* FIXME: Move this to a more suitable place */
934 if (HAS_DDI(dev))
935 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200936}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200937
938struct intel_shared_dpll *
939intel_get_shared_dpll(struct intel_crtc *crtc,
940 struct intel_crtc_state *crtc_state)
941{
942 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
943 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
944
945 if (WARN_ON(!dpll_mgr))
946 return NULL;
947
948 return dpll_mgr->get_dpll(crtc, crtc_state);
949}