blob: a90ef34a77857e9d29baff8d65388aaaa7a6b827 [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 *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200338ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
339 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200340{
341 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
342 struct intel_shared_dpll *pll;
343 enum intel_dpll_id i;
344
345 if (HAS_PCH_IBX(dev_priv)) {
346 /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
347 i = (enum intel_dpll_id) crtc->pipe;
348 pll = &dev_priv->shared_dplls[i];
349
350 DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
351 crtc->base.base.id, pll->name);
352 } else {
353 pll = intel_find_shared_dpll(crtc, crtc_state,
354 DPLL_ID_PCH_PLL_A,
355 DPLL_ID_PCH_PLL_B);
356 }
357
358 /* reference the pll */
359 intel_reference_shared_dpll(pll, crtc_state);
360
361 return pll;
362}
363
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200364static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
365 .mode_set = ibx_pch_dpll_mode_set,
366 .enable = ibx_pch_dpll_enable,
367 .disable = ibx_pch_dpll_disable,
368 .get_hw_state = ibx_pch_dpll_get_hw_state,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200369};
370
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200371static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
372 struct intel_shared_dpll *pll)
373{
374 I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
375 POSTING_READ(WRPLL_CTL(pll->id));
376 udelay(20);
377}
378
379static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
380 struct intel_shared_dpll *pll)
381{
382 I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
383 POSTING_READ(SPLL_CTL);
384 udelay(20);
385}
386
387static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
388 struct intel_shared_dpll *pll)
389{
390 uint32_t val;
391
392 val = I915_READ(WRPLL_CTL(pll->id));
393 I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
394 POSTING_READ(WRPLL_CTL(pll->id));
395}
396
397static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
398 struct intel_shared_dpll *pll)
399{
400 uint32_t val;
401
402 val = I915_READ(SPLL_CTL);
403 I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
404 POSTING_READ(SPLL_CTL);
405}
406
407static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
408 struct intel_shared_dpll *pll,
409 struct intel_dpll_hw_state *hw_state)
410{
411 uint32_t val;
412
413 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
414 return false;
415
416 val = I915_READ(WRPLL_CTL(pll->id));
417 hw_state->wrpll = val;
418
419 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
420
421 return val & WRPLL_PLL_ENABLE;
422}
423
424static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
425 struct intel_shared_dpll *pll,
426 struct intel_dpll_hw_state *hw_state)
427{
428 uint32_t val;
429
430 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
431 return false;
432
433 val = I915_READ(SPLL_CTL);
434 hw_state->spll = val;
435
436 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
437
438 return val & SPLL_PLL_ENABLE;
439}
440
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200441static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll)
442{
443 switch (pll->id) {
444 case DPLL_ID_WRPLL1:
445 return PORT_CLK_SEL_WRPLL1;
446 case DPLL_ID_WRPLL2:
447 return PORT_CLK_SEL_WRPLL2;
448 case DPLL_ID_SPLL:
449 return PORT_CLK_SEL_SPLL;
450 default:
451 return PORT_CLK_SEL_NONE;
452 }
453}
454
455#define LC_FREQ 2700
456#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
457
458#define P_MIN 2
459#define P_MAX 64
460#define P_INC 2
461
462/* Constraints for PLL good behavior */
463#define REF_MIN 48
464#define REF_MAX 400
465#define VCO_MIN 2400
466#define VCO_MAX 4800
467
468struct hsw_wrpll_rnp {
469 unsigned p, n2, r2;
470};
471
472static unsigned hsw_wrpll_get_budget_for_freq(int clock)
473{
474 unsigned budget;
475
476 switch (clock) {
477 case 25175000:
478 case 25200000:
479 case 27000000:
480 case 27027000:
481 case 37762500:
482 case 37800000:
483 case 40500000:
484 case 40541000:
485 case 54000000:
486 case 54054000:
487 case 59341000:
488 case 59400000:
489 case 72000000:
490 case 74176000:
491 case 74250000:
492 case 81000000:
493 case 81081000:
494 case 89012000:
495 case 89100000:
496 case 108000000:
497 case 108108000:
498 case 111264000:
499 case 111375000:
500 case 148352000:
501 case 148500000:
502 case 162000000:
503 case 162162000:
504 case 222525000:
505 case 222750000:
506 case 296703000:
507 case 297000000:
508 budget = 0;
509 break;
510 case 233500000:
511 case 245250000:
512 case 247750000:
513 case 253250000:
514 case 298000000:
515 budget = 1500;
516 break;
517 case 169128000:
518 case 169500000:
519 case 179500000:
520 case 202000000:
521 budget = 2000;
522 break;
523 case 256250000:
524 case 262500000:
525 case 270000000:
526 case 272500000:
527 case 273750000:
528 case 280750000:
529 case 281250000:
530 case 286000000:
531 case 291750000:
532 budget = 4000;
533 break;
534 case 267250000:
535 case 268500000:
536 budget = 5000;
537 break;
538 default:
539 budget = 1000;
540 break;
541 }
542
543 return budget;
544}
545
546static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
547 unsigned r2, unsigned n2, unsigned p,
548 struct hsw_wrpll_rnp *best)
549{
550 uint64_t a, b, c, d, diff, diff_best;
551
552 /* No best (r,n,p) yet */
553 if (best->p == 0) {
554 best->p = p;
555 best->n2 = n2;
556 best->r2 = r2;
557 return;
558 }
559
560 /*
561 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
562 * freq2k.
563 *
564 * delta = 1e6 *
565 * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
566 * freq2k;
567 *
568 * and we would like delta <= budget.
569 *
570 * If the discrepancy is above the PPM-based budget, always prefer to
571 * improve upon the previous solution. However, if you're within the
572 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
573 */
574 a = freq2k * budget * p * r2;
575 b = freq2k * budget * best->p * best->r2;
576 diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
577 diff_best = abs_diff(freq2k * best->p * best->r2,
578 LC_FREQ_2K * best->n2);
579 c = 1000000 * diff;
580 d = 1000000 * diff_best;
581
582 if (a < c && b < d) {
583 /* If both are above the budget, pick the closer */
584 if (best->p * best->r2 * diff < p * r2 * diff_best) {
585 best->p = p;
586 best->n2 = n2;
587 best->r2 = r2;
588 }
589 } else if (a >= c && b < d) {
590 /* If A is below the threshold but B is above it? Update. */
591 best->p = p;
592 best->n2 = n2;
593 best->r2 = r2;
594 } else if (a >= c && b >= d) {
595 /* Both are below the limit, so pick the higher n2/(r2*r2) */
596 if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
597 best->p = p;
598 best->n2 = n2;
599 best->r2 = r2;
600 }
601 }
602 /* Otherwise a < c && b >= d, do nothing */
603}
604
605static void
606hsw_ddi_calculate_wrpll(int clock /* in Hz */,
607 unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
608{
609 uint64_t freq2k;
610 unsigned p, n2, r2;
611 struct hsw_wrpll_rnp best = { 0, 0, 0 };
612 unsigned budget;
613
614 freq2k = clock / 100;
615
616 budget = hsw_wrpll_get_budget_for_freq(clock);
617
618 /* Special case handling for 540 pixel clock: bypass WR PLL entirely
619 * and directly pass the LC PLL to it. */
620 if (freq2k == 5400000) {
621 *n2_out = 2;
622 *p_out = 1;
623 *r2_out = 2;
624 return;
625 }
626
627 /*
628 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
629 * the WR PLL.
630 *
631 * We want R so that REF_MIN <= Ref <= REF_MAX.
632 * Injecting R2 = 2 * R gives:
633 * REF_MAX * r2 > LC_FREQ * 2 and
634 * REF_MIN * r2 < LC_FREQ * 2
635 *
636 * Which means the desired boundaries for r2 are:
637 * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
638 *
639 */
640 for (r2 = LC_FREQ * 2 / REF_MAX + 1;
641 r2 <= LC_FREQ * 2 / REF_MIN;
642 r2++) {
643
644 /*
645 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
646 *
647 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
648 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
649 * VCO_MAX * r2 > n2 * LC_FREQ and
650 * VCO_MIN * r2 < n2 * LC_FREQ)
651 *
652 * Which means the desired boundaries for n2 are:
653 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
654 */
655 for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
656 n2 <= VCO_MAX * r2 / LC_FREQ;
657 n2++) {
658
659 for (p = P_MIN; p <= P_MAX; p += P_INC)
660 hsw_wrpll_update_rnp(freq2k, budget,
661 r2, n2, p, &best);
662 }
663 }
664
665 *n2_out = best.n2;
666 *p_out = best.p;
667 *r2_out = best.r2;
668}
669
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200670static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200671hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
672 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200673{
674 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200675 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200676
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200677 if (encoder->type == INTEL_OUTPUT_HDMI) {
678 uint32_t val;
679 unsigned p, n2, r2;
680
681 hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
682
683 val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
684 WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
685 WRPLL_DIVIDER_POST(p);
686
687 memset(&crtc_state->dpll_hw_state, 0,
688 sizeof(crtc_state->dpll_hw_state));
689
690 crtc_state->dpll_hw_state.wrpll = val;
691
692 pll = intel_find_shared_dpll(crtc, crtc_state,
693 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
694
695 } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
696 if (WARN_ON(crtc_state->port_clock / 2 != 135000))
697 return NULL;
698
699 memset(&crtc_state->dpll_hw_state, 0,
700 sizeof(crtc_state->dpll_hw_state));
701
702 crtc_state->dpll_hw_state.spll =
703 SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
704
705 pll = intel_find_shared_dpll(crtc, crtc_state,
706 DPLL_ID_SPLL, DPLL_ID_SPLL);
707 } else {
708 return NULL;
709 }
710
711 if (!pll)
712 return NULL;
713
714 crtc_state->ddi_pll_sel = hsw_pll_to_ddi_pll_sel(pll);
715
716 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200717
718 return pll;
719}
720
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200721
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200722static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
723 .enable = hsw_ddi_wrpll_enable,
724 .disable = hsw_ddi_wrpll_disable,
725 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200726};
727
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200728static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
729 .enable = hsw_ddi_spll_enable,
730 .disable = hsw_ddi_spll_disable,
731 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200732};
733
734struct skl_dpll_regs {
735 i915_reg_t ctl, cfgcr1, cfgcr2;
736};
737
738/* this array is indexed by the *shared* pll id */
739static const struct skl_dpll_regs skl_dpll_regs[3] = {
740 {
741 /* DPLL 1 */
742 .ctl = LCPLL2_CTL,
743 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
744 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
745 },
746 {
747 /* DPLL 2 */
748 .ctl = WRPLL_CTL(0),
749 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
750 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
751 },
752 {
753 /* DPLL 3 */
754 .ctl = WRPLL_CTL(1),
755 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
756 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
757 },
758};
759
760static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
761 struct intel_shared_dpll *pll)
762{
763 uint32_t val;
764 unsigned int dpll;
765 const struct skl_dpll_regs *regs = skl_dpll_regs;
766
767 /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
768 dpll = pll->id + 1;
769
770 val = I915_READ(DPLL_CTRL1);
771
772 val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) | DPLL_CTRL1_SSC(dpll) |
773 DPLL_CTRL1_LINK_RATE_MASK(dpll));
774 val |= pll->config.hw_state.ctrl1 << (dpll * 6);
775
776 I915_WRITE(DPLL_CTRL1, val);
777 POSTING_READ(DPLL_CTRL1);
778
779 I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
780 I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
781 POSTING_READ(regs[pll->id].cfgcr1);
782 POSTING_READ(regs[pll->id].cfgcr2);
783
784 /* the enable bit is always bit 31 */
785 I915_WRITE(regs[pll->id].ctl,
786 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
787
788 if (wait_for(I915_READ(DPLL_STATUS) & DPLL_LOCK(dpll), 5))
789 DRM_ERROR("DPLL %d not locked\n", dpll);
790}
791
792static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
793 struct intel_shared_dpll *pll)
794{
795 const struct skl_dpll_regs *regs = skl_dpll_regs;
796
797 /* the enable bit is always bit 31 */
798 I915_WRITE(regs[pll->id].ctl,
799 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
800 POSTING_READ(regs[pll->id].ctl);
801}
802
803static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
804 struct intel_shared_dpll *pll,
805 struct intel_dpll_hw_state *hw_state)
806{
807 uint32_t val;
808 unsigned int dpll;
809 const struct skl_dpll_regs *regs = skl_dpll_regs;
810 bool ret;
811
812 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
813 return false;
814
815 ret = false;
816
817 /* DPLL0 is not part of the shared DPLLs, so pll->id is 0 for DPLL1 */
818 dpll = pll->id + 1;
819
820 val = I915_READ(regs[pll->id].ctl);
821 if (!(val & LCPLL_PLL_ENABLE))
822 goto out;
823
824 val = I915_READ(DPLL_CTRL1);
825 hw_state->ctrl1 = (val >> (dpll * 6)) & 0x3f;
826
827 /* avoid reading back stale values if HDMI mode is not enabled */
828 if (val & DPLL_CTRL1_HDMI_MODE(dpll)) {
829 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
830 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
831 }
832 ret = true;
833
834out:
835 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
836
837 return ret;
838}
839
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +0200840struct skl_wrpll_context {
841 uint64_t min_deviation; /* current minimal deviation */
842 uint64_t central_freq; /* chosen central freq */
843 uint64_t dco_freq; /* chosen dco freq */
844 unsigned int p; /* chosen divider */
845};
846
847static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
848{
849 memset(ctx, 0, sizeof(*ctx));
850
851 ctx->min_deviation = U64_MAX;
852}
853
854/* DCO freq must be within +1%/-6% of the DCO central freq */
855#define SKL_DCO_MAX_PDEVIATION 100
856#define SKL_DCO_MAX_NDEVIATION 600
857
858static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
859 uint64_t central_freq,
860 uint64_t dco_freq,
861 unsigned int divider)
862{
863 uint64_t deviation;
864
865 deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
866 central_freq);
867
868 /* positive deviation */
869 if (dco_freq >= central_freq) {
870 if (deviation < SKL_DCO_MAX_PDEVIATION &&
871 deviation < ctx->min_deviation) {
872 ctx->min_deviation = deviation;
873 ctx->central_freq = central_freq;
874 ctx->dco_freq = dco_freq;
875 ctx->p = divider;
876 }
877 /* negative deviation */
878 } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
879 deviation < ctx->min_deviation) {
880 ctx->min_deviation = deviation;
881 ctx->central_freq = central_freq;
882 ctx->dco_freq = dco_freq;
883 ctx->p = divider;
884 }
885}
886
887static void skl_wrpll_get_multipliers(unsigned int p,
888 unsigned int *p0 /* out */,
889 unsigned int *p1 /* out */,
890 unsigned int *p2 /* out */)
891{
892 /* even dividers */
893 if (p % 2 == 0) {
894 unsigned int half = p / 2;
895
896 if (half == 1 || half == 2 || half == 3 || half == 5) {
897 *p0 = 2;
898 *p1 = 1;
899 *p2 = half;
900 } else if (half % 2 == 0) {
901 *p0 = 2;
902 *p1 = half / 2;
903 *p2 = 2;
904 } else if (half % 3 == 0) {
905 *p0 = 3;
906 *p1 = half / 3;
907 *p2 = 2;
908 } else if (half % 7 == 0) {
909 *p0 = 7;
910 *p1 = half / 7;
911 *p2 = 2;
912 }
913 } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
914 *p0 = 3;
915 *p1 = 1;
916 *p2 = p / 3;
917 } else if (p == 5 || p == 7) {
918 *p0 = p;
919 *p1 = 1;
920 *p2 = 1;
921 } else if (p == 15) {
922 *p0 = 3;
923 *p1 = 1;
924 *p2 = 5;
925 } else if (p == 21) {
926 *p0 = 7;
927 *p1 = 1;
928 *p2 = 3;
929 } else if (p == 35) {
930 *p0 = 7;
931 *p1 = 1;
932 *p2 = 5;
933 }
934}
935
936struct skl_wrpll_params {
937 uint32_t dco_fraction;
938 uint32_t dco_integer;
939 uint32_t qdiv_ratio;
940 uint32_t qdiv_mode;
941 uint32_t kdiv;
942 uint32_t pdiv;
943 uint32_t central_freq;
944};
945
946static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
947 uint64_t afe_clock,
948 uint64_t central_freq,
949 uint32_t p0, uint32_t p1, uint32_t p2)
950{
951 uint64_t dco_freq;
952
953 switch (central_freq) {
954 case 9600000000ULL:
955 params->central_freq = 0;
956 break;
957 case 9000000000ULL:
958 params->central_freq = 1;
959 break;
960 case 8400000000ULL:
961 params->central_freq = 3;
962 }
963
964 switch (p0) {
965 case 1:
966 params->pdiv = 0;
967 break;
968 case 2:
969 params->pdiv = 1;
970 break;
971 case 3:
972 params->pdiv = 2;
973 break;
974 case 7:
975 params->pdiv = 4;
976 break;
977 default:
978 WARN(1, "Incorrect PDiv\n");
979 }
980
981 switch (p2) {
982 case 5:
983 params->kdiv = 0;
984 break;
985 case 2:
986 params->kdiv = 1;
987 break;
988 case 3:
989 params->kdiv = 2;
990 break;
991 case 1:
992 params->kdiv = 3;
993 break;
994 default:
995 WARN(1, "Incorrect KDiv\n");
996 }
997
998 params->qdiv_ratio = p1;
999 params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1000
1001 dco_freq = p0 * p1 * p2 * afe_clock;
1002
1003 /*
1004 * Intermediate values are in Hz.
1005 * Divide by MHz to match bsepc
1006 */
1007 params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1008 params->dco_fraction =
1009 div_u64((div_u64(dco_freq, 24) -
1010 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1011}
1012
1013static bool
1014skl_ddi_calculate_wrpll(int clock /* in Hz */,
1015 struct skl_wrpll_params *wrpll_params)
1016{
1017 uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1018 uint64_t dco_central_freq[3] = {8400000000ULL,
1019 9000000000ULL,
1020 9600000000ULL};
1021 static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1022 24, 28, 30, 32, 36, 40, 42, 44,
1023 48, 52, 54, 56, 60, 64, 66, 68,
1024 70, 72, 76, 78, 80, 84, 88, 90,
1025 92, 96, 98 };
1026 static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1027 static const struct {
1028 const int *list;
1029 int n_dividers;
1030 } dividers[] = {
1031 { even_dividers, ARRAY_SIZE(even_dividers) },
1032 { odd_dividers, ARRAY_SIZE(odd_dividers) },
1033 };
1034 struct skl_wrpll_context ctx;
1035 unsigned int dco, d, i;
1036 unsigned int p0, p1, p2;
1037
1038 skl_wrpll_context_init(&ctx);
1039
1040 for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1041 for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1042 for (i = 0; i < dividers[d].n_dividers; i++) {
1043 unsigned int p = dividers[d].list[i];
1044 uint64_t dco_freq = p * afe_clock;
1045
1046 skl_wrpll_try_divider(&ctx,
1047 dco_central_freq[dco],
1048 dco_freq,
1049 p);
1050 /*
1051 * Skip the remaining dividers if we're sure to
1052 * have found the definitive divider, we can't
1053 * improve a 0 deviation.
1054 */
1055 if (ctx.min_deviation == 0)
1056 goto skip_remaining_dividers;
1057 }
1058 }
1059
1060skip_remaining_dividers:
1061 /*
1062 * If a solution is found with an even divider, prefer
1063 * this one.
1064 */
1065 if (d == 0 && ctx.p)
1066 break;
1067 }
1068
1069 if (!ctx.p) {
1070 DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1071 return false;
1072 }
1073
1074 /*
1075 * gcc incorrectly analyses that these can be used without being
1076 * initialized. To be fair, it's hard to guess.
1077 */
1078 p0 = p1 = p2 = 0;
1079 skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1080 skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1081 p0, p1, p2);
1082
1083 return true;
1084}
1085
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001086static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001087skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1088 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001089{
1090 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001091 uint32_t ctrl1, cfgcr1, cfgcr2;
1092 int clock = crtc_state->port_clock;
1093
1094 /*
1095 * See comment in intel_dpll_hw_state to understand why we always use 0
1096 * as the DPLL id in this function.
1097 */
1098
1099 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1100
1101 if (encoder->type == INTEL_OUTPUT_HDMI) {
1102 struct skl_wrpll_params wrpll_params = { 0, };
1103
1104 ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
1105
1106 if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
1107 return false;
1108
1109 cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1110 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1111 wrpll_params.dco_integer;
1112
1113 cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1114 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1115 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1116 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1117 wrpll_params.central_freq;
1118 } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
1119 encoder->type == INTEL_OUTPUT_DP_MST) {
1120 switch (crtc_state->port_clock / 2) {
1121 case 81000:
1122 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1123 break;
1124 case 135000:
1125 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1126 break;
1127 case 270000:
1128 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1129 break;
1130 }
1131
1132 cfgcr1 = cfgcr2 = 0;
1133 } else {
1134 return NULL;
1135 }
1136
1137 memset(&crtc_state->dpll_hw_state, 0,
1138 sizeof(crtc_state->dpll_hw_state));
1139
1140 crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1141 crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1142 crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001143
1144 pll = intel_find_shared_dpll(crtc, crtc_state,
1145 DPLL_ID_SKL_DPLL1, DPLL_ID_SKL_DPLL3);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001146 if (!pll)
1147 return NULL;
1148
1149 /* shared DPLL id 0 is DPLL 1 */
1150 crtc_state->ddi_pll_sel = pll->id + 1;
1151
1152 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001153
1154 return pll;
1155}
1156
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001157static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1158 .enable = skl_ddi_pll_enable,
1159 .disable = skl_ddi_pll_disable,
1160 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001161};
1162
1163static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1164 struct intel_shared_dpll *pll)
1165{
1166 uint32_t temp;
1167 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1168
1169 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1170 temp &= ~PORT_PLL_REF_SEL;
1171 /* Non-SSC reference */
1172 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1173
1174 /* Disable 10 bit clock */
1175 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
1176 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1177 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1178
1179 /* Write P1 & P2 */
1180 temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
1181 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
1182 temp |= pll->config.hw_state.ebb0;
1183 I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
1184
1185 /* Write M2 integer */
1186 temp = I915_READ(BXT_PORT_PLL(port, 0));
1187 temp &= ~PORT_PLL_M2_MASK;
1188 temp |= pll->config.hw_state.pll0;
1189 I915_WRITE(BXT_PORT_PLL(port, 0), temp);
1190
1191 /* Write N */
1192 temp = I915_READ(BXT_PORT_PLL(port, 1));
1193 temp &= ~PORT_PLL_N_MASK;
1194 temp |= pll->config.hw_state.pll1;
1195 I915_WRITE(BXT_PORT_PLL(port, 1), temp);
1196
1197 /* Write M2 fraction */
1198 temp = I915_READ(BXT_PORT_PLL(port, 2));
1199 temp &= ~PORT_PLL_M2_FRAC_MASK;
1200 temp |= pll->config.hw_state.pll2;
1201 I915_WRITE(BXT_PORT_PLL(port, 2), temp);
1202
1203 /* Write M2 fraction enable */
1204 temp = I915_READ(BXT_PORT_PLL(port, 3));
1205 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
1206 temp |= pll->config.hw_state.pll3;
1207 I915_WRITE(BXT_PORT_PLL(port, 3), temp);
1208
1209 /* Write coeff */
1210 temp = I915_READ(BXT_PORT_PLL(port, 6));
1211 temp &= ~PORT_PLL_PROP_COEFF_MASK;
1212 temp &= ~PORT_PLL_INT_COEFF_MASK;
1213 temp &= ~PORT_PLL_GAIN_CTL_MASK;
1214 temp |= pll->config.hw_state.pll6;
1215 I915_WRITE(BXT_PORT_PLL(port, 6), temp);
1216
1217 /* Write calibration val */
1218 temp = I915_READ(BXT_PORT_PLL(port, 8));
1219 temp &= ~PORT_PLL_TARGET_CNT_MASK;
1220 temp |= pll->config.hw_state.pll8;
1221 I915_WRITE(BXT_PORT_PLL(port, 8), temp);
1222
1223 temp = I915_READ(BXT_PORT_PLL(port, 9));
1224 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
1225 temp |= pll->config.hw_state.pll9;
1226 I915_WRITE(BXT_PORT_PLL(port, 9), temp);
1227
1228 temp = I915_READ(BXT_PORT_PLL(port, 10));
1229 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1230 temp &= ~PORT_PLL_DCO_AMP_MASK;
1231 temp |= pll->config.hw_state.pll10;
1232 I915_WRITE(BXT_PORT_PLL(port, 10), temp);
1233
1234 /* Recalibrate with new settings */
1235 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
1236 temp |= PORT_PLL_RECALIBRATE;
1237 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1238 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1239 temp |= pll->config.hw_state.ebb4;
1240 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1241
1242 /* Enable PLL */
1243 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1244 temp |= PORT_PLL_ENABLE;
1245 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1246 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1247
1248 if (wait_for_atomic_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1249 PORT_PLL_LOCK), 200))
1250 DRM_ERROR("PLL %d not locked\n", port);
1251
1252 /*
1253 * While we write to the group register to program all lanes at once we
1254 * can read only lane registers and we pick lanes 0/1 for that.
1255 */
1256 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
1257 temp &= ~LANE_STAGGER_MASK;
1258 temp &= ~LANESTAGGER_STRAP_OVRD;
1259 temp |= pll->config.hw_state.pcsdw12;
1260 I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
1261}
1262
1263static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1264 struct intel_shared_dpll *pll)
1265{
1266 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1267 uint32_t temp;
1268
1269 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1270 temp &= ~PORT_PLL_ENABLE;
1271 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1272 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1273}
1274
1275static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1276 struct intel_shared_dpll *pll,
1277 struct intel_dpll_hw_state *hw_state)
1278{
1279 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1280 uint32_t val;
1281 bool ret;
1282
1283 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1284 return false;
1285
1286 ret = false;
1287
1288 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1289 if (!(val & PORT_PLL_ENABLE))
1290 goto out;
1291
1292 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
1293 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1294
1295 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
1296 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1297
1298 hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
1299 hw_state->pll0 &= PORT_PLL_M2_MASK;
1300
1301 hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
1302 hw_state->pll1 &= PORT_PLL_N_MASK;
1303
1304 hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
1305 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1306
1307 hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
1308 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1309
1310 hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
1311 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1312 PORT_PLL_INT_COEFF_MASK |
1313 PORT_PLL_GAIN_CTL_MASK;
1314
1315 hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
1316 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1317
1318 hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
1319 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1320
1321 hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
1322 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1323 PORT_PLL_DCO_AMP_MASK;
1324
1325 /*
1326 * While we write to the group register to program all lanes at once we
1327 * can read only lane registers. We configure all lanes the same way, so
1328 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1329 */
1330 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
1331 if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
1332 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1333 hw_state->pcsdw12,
1334 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
1335 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1336
1337 ret = true;
1338
1339out:
1340 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1341
1342 return ret;
1343}
1344
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001345/* bxt clock parameters */
1346struct bxt_clk_div {
1347 int clock;
1348 uint32_t p1;
1349 uint32_t p2;
1350 uint32_t m2_int;
1351 uint32_t m2_frac;
1352 bool m2_frac_en;
1353 uint32_t n;
1354};
1355
1356/* pre-calculated values for DP linkrates */
1357static const struct bxt_clk_div bxt_dp_clk_val[] = {
1358 {162000, 4, 2, 32, 1677722, 1, 1},
1359 {270000, 4, 1, 27, 0, 0, 1},
1360 {540000, 2, 1, 27, 0, 0, 1},
1361 {216000, 3, 2, 32, 1677722, 1, 1},
1362 {243000, 4, 1, 24, 1258291, 1, 1},
1363 {324000, 4, 1, 32, 1677722, 1, 1},
1364 {432000, 3, 1, 32, 1677722, 1, 1}
1365};
1366
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001367static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001368bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1369 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001370{
1371 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001372 struct intel_shared_dpll *pll;
1373 enum intel_dpll_id i;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001374 struct intel_digital_port *intel_dig_port;
1375 struct bxt_clk_div clk_div = {0};
1376 int vco = 0;
1377 uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
1378 uint32_t lanestagger;
1379 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001380
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001381 if (encoder->type == INTEL_OUTPUT_HDMI) {
1382 intel_clock_t best_clock;
1383
1384 /* Calculate HDMI div */
1385 /*
1386 * FIXME: tie the following calculation into
1387 * i9xx_crtc_compute_clock
1388 */
1389 if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
1390 DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1391 clock, pipe_name(crtc->pipe));
1392 return NULL;
1393 }
1394
1395 clk_div.p1 = best_clock.p1;
1396 clk_div.p2 = best_clock.p2;
1397 WARN_ON(best_clock.m1 != 2);
1398 clk_div.n = best_clock.n;
1399 clk_div.m2_int = best_clock.m2 >> 22;
1400 clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1);
1401 clk_div.m2_frac_en = clk_div.m2_frac != 0;
1402
1403 vco = best_clock.vco;
1404 } else if (encoder->type == INTEL_OUTPUT_DISPLAYPORT ||
1405 encoder->type == INTEL_OUTPUT_EDP) {
1406 int i;
1407
1408 clk_div = bxt_dp_clk_val[0];
1409 for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1410 if (bxt_dp_clk_val[i].clock == clock) {
1411 clk_div = bxt_dp_clk_val[i];
1412 break;
1413 }
1414 }
1415 vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2;
1416 }
1417
1418 if (vco >= 6200000 && vco <= 6700000) {
1419 prop_coef = 4;
1420 int_coef = 9;
1421 gain_ctl = 3;
1422 targ_cnt = 8;
1423 } else if ((vco > 5400000 && vco < 6200000) ||
1424 (vco >= 4800000 && vco < 5400000)) {
1425 prop_coef = 5;
1426 int_coef = 11;
1427 gain_ctl = 3;
1428 targ_cnt = 9;
1429 } else if (vco == 5400000) {
1430 prop_coef = 3;
1431 int_coef = 8;
1432 gain_ctl = 1;
1433 targ_cnt = 9;
1434 } else {
1435 DRM_ERROR("Invalid VCO\n");
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001436 return NULL;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001437 }
1438
1439 memset(&crtc_state->dpll_hw_state, 0,
1440 sizeof(crtc_state->dpll_hw_state));
1441
1442 if (clock > 270000)
1443 lanestagger = 0x18;
1444 else if (clock > 135000)
1445 lanestagger = 0x0d;
1446 else if (clock > 67000)
1447 lanestagger = 0x07;
1448 else if (clock > 33000)
1449 lanestagger = 0x04;
1450 else
1451 lanestagger = 0x02;
1452
1453 crtc_state->dpll_hw_state.ebb0 =
1454 PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2);
1455 crtc_state->dpll_hw_state.pll0 = clk_div.m2_int;
1456 crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n);
1457 crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac;
1458
1459 if (clk_div.m2_frac_en)
1460 crtc_state->dpll_hw_state.pll3 =
1461 PORT_PLL_M2_FRAC_ENABLE;
1462
1463 crtc_state->dpll_hw_state.pll6 =
1464 prop_coef | PORT_PLL_INT_COEFF(int_coef);
1465 crtc_state->dpll_hw_state.pll6 |=
1466 PORT_PLL_GAIN_CTL(gain_ctl);
1467
1468 crtc_state->dpll_hw_state.pll8 = targ_cnt;
1469
1470 crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
1471
1472 crtc_state->dpll_hw_state.pll10 =
1473 PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1474 | PORT_PLL_DCO_AMP_OVR_EN_H;
1475
1476 crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
1477
1478 crtc_state->dpll_hw_state.pcsdw12 =
1479 LANESTAGGER_STRAP_OVRD | lanestagger;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001480
1481 intel_dig_port = enc_to_dig_port(&encoder->base);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001482
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001483 /* 1:1 mapping between ports and PLLs */
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001484 i = (enum intel_dpll_id) intel_dig_port->port;
1485 pll = intel_get_shared_dpll_by_id(dev_priv, i);
1486
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001487 DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
1488 crtc->base.base.id, pll->name);
1489
1490 intel_reference_shared_dpll(pll, crtc_state);
1491
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001492 /* shared DPLL id 0 is DPLL A */
1493 crtc_state->ddi_pll_sel = pll->id;
1494
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001495 return pll;
1496}
1497
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001498static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1499 .enable = bxt_ddi_pll_enable,
1500 .disable = bxt_ddi_pll_disable,
1501 .get_hw_state = bxt_ddi_pll_get_hw_state,
1502};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001503
1504static void intel_ddi_pll_init(struct drm_device *dev)
1505{
1506 struct drm_i915_private *dev_priv = dev->dev_private;
1507 uint32_t val = I915_READ(LCPLL_CTL);
1508
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001509 if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
1510 int cdclk_freq;
1511
1512 cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
1513 dev_priv->skl_boot_cdclk = cdclk_freq;
1514 if (skl_sanitize_cdclk(dev_priv))
1515 DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
1516 if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
1517 DRM_ERROR("LCPLL1 is disabled\n");
1518 } else if (IS_BROXTON(dev)) {
1519 broxton_init_cdclk(dev);
1520 broxton_ddi_phy_init(dev);
1521 } else {
1522 /*
1523 * The LCPLL register should be turned on by the BIOS. For now
1524 * let's just check its state and print errors in case
1525 * something is wrong. Don't even try to turn it on.
1526 */
1527
1528 if (val & LCPLL_CD_SOURCE_FCLK)
1529 DRM_ERROR("CDCLK source is not LCPLL\n");
1530
1531 if (val & LCPLL_PLL_DISABLE)
1532 DRM_ERROR("LCPLL is disabled\n");
1533 }
1534}
1535
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001536struct dpll_info {
1537 const char *name;
1538 const int id;
1539 const struct intel_shared_dpll_funcs *funcs;
1540};
1541
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001542struct intel_dpll_mgr {
1543 const struct dpll_info *dpll_info;
1544
1545 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001546 struct intel_crtc_state *crtc_state,
1547 struct intel_encoder *encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001548};
1549
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001550static const struct dpll_info pch_plls[] = {
1551 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs },
1552 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs },
1553 { NULL, -1, NULL },
1554};
1555
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001556static const struct intel_dpll_mgr pch_pll_mgr = {
1557 .dpll_info = pch_plls,
1558 .get_dpll = ibx_get_dpll,
1559};
1560
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001561static const struct dpll_info hsw_plls[] = {
1562 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs },
1563 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs },
1564 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs },
1565 { NULL, -1, NULL, },
1566};
1567
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001568static const struct intel_dpll_mgr hsw_pll_mgr = {
1569 .dpll_info = hsw_plls,
1570 .get_dpll = hsw_get_dpll,
1571};
1572
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001573static const struct dpll_info skl_plls[] = {
1574 { "DPPL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs },
1575 { "DPPL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs },
1576 { "DPPL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs },
1577 { NULL, -1, NULL, },
1578};
1579
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001580static const struct intel_dpll_mgr skl_pll_mgr = {
1581 .dpll_info = skl_plls,
1582 .get_dpll = skl_get_dpll,
1583};
1584
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001585static const struct dpll_info bxt_plls[] = {
1586 { "PORT PLL A", 0, &bxt_ddi_pll_funcs },
1587 { "PORT PLL B", 1, &bxt_ddi_pll_funcs },
1588 { "PORT PLL C", 2, &bxt_ddi_pll_funcs },
1589 { NULL, -1, NULL, },
1590};
1591
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001592static const struct intel_dpll_mgr bxt_pll_mgr = {
1593 .dpll_info = bxt_plls,
1594 .get_dpll = bxt_get_dpll,
1595};
1596
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001597void intel_shared_dpll_init(struct drm_device *dev)
1598{
1599 struct drm_i915_private *dev_priv = dev->dev_private;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001600 const struct intel_dpll_mgr *dpll_mgr = NULL;
1601 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001602 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001603
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001604 if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001605 dpll_mgr = &skl_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001606 else if IS_BROXTON(dev)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001607 dpll_mgr = &bxt_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001608 else if (HAS_DDI(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001609 dpll_mgr = &hsw_pll_mgr;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001610 else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001611 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001612
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001613 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001614 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001615 return;
1616 }
1617
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001618 dpll_info = dpll_mgr->dpll_info;
1619
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001620 for (i = 0; dpll_info[i].id >= 0; i++) {
1621 WARN_ON(i != dpll_info[i].id);
1622
1623 dev_priv->shared_dplls[i].id = dpll_info[i].id;
1624 dev_priv->shared_dplls[i].name = dpll_info[i].name;
1625 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
1626 }
1627
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001628 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001629 dev_priv->num_shared_dpll = i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001630
1631 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001632
1633 /* FIXME: Move this to a more suitable place */
1634 if (HAS_DDI(dev))
1635 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001636}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001637
1638struct intel_shared_dpll *
1639intel_get_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001640 struct intel_crtc_state *crtc_state,
1641 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001642{
1643 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1644 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
1645
1646 if (WARN_ON(!dpll_mgr))
1647 return NULL;
1648
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001649 return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001650}