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