blob: 97f7cc9b58eeddac5a082eeb9373730e92b5499a [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 *
Jim Bridef1696602016-09-07 15:47:34 -070027skl_find_link_pll(struct drm_i915_private *dev_priv, int clock)
28{
29 struct intel_shared_dpll *pll = NULL;
30 struct intel_dpll_hw_state dpll_hw_state;
31 enum intel_dpll_id i;
32 bool found = false;
33
34 if (!skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
35 return pll;
36
37 for (i = DPLL_ID_SKL_DPLL1; i <= DPLL_ID_SKL_DPLL3; i++) {
38 pll = &dev_priv->shared_dplls[i];
39
40 /* Only want to check enabled timings first */
41 if (pll->config.crtc_mask == 0)
42 continue;
43
44 if (memcmp(&dpll_hw_state, &pll->config.hw_state,
45 sizeof(pll->config.hw_state)) == 0) {
46 found = true;
47 break;
48 }
49 }
50
51 /* Ok no matching timings, maybe there's a free one? */
52 for (i = DPLL_ID_SKL_DPLL1;
53 ((found == false) && (i <= DPLL_ID_SKL_DPLL3)); i++) {
54 pll = &dev_priv->shared_dplls[i];
55 if (pll->config.crtc_mask == 0) {
56 pll->config.hw_state = dpll_hw_state;
57 break;
58 }
59 }
60
61 return pll;
62}
63
64struct intel_shared_dpll *
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020065intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
66 enum intel_dpll_id id)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020067{
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020068 return &dev_priv->shared_dplls[id];
69}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020070
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020071enum intel_dpll_id
72intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
73 struct intel_shared_dpll *pll)
74{
75 if (WARN_ON(pll < dev_priv->shared_dplls||
76 pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll]))
77 return -1;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020078
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020079 return (enum intel_dpll_id) (pll - dev_priv->shared_dplls);
80}
81
82void
83intel_shared_dpll_config_get(struct intel_shared_dpll_config *config,
84 struct intel_shared_dpll *pll,
85 struct intel_crtc *crtc)
86{
87 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
88 enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
89
90 config[id].crtc_mask |= 1 << crtc->pipe;
91}
92
93void
94intel_shared_dpll_config_put(struct intel_shared_dpll_config *config,
95 struct intel_shared_dpll *pll,
96 struct intel_crtc *crtc)
97{
98 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
99 enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
100
101 config[id].crtc_mask &= ~(1 << crtc->pipe);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200102}
103
104/* For ILK+ */
105void assert_shared_dpll(struct drm_i915_private *dev_priv,
106 struct intel_shared_dpll *pll,
107 bool state)
108{
109 bool cur_state;
110 struct intel_dpll_hw_state hw_state;
111
112 if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
113 return;
114
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200115 cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200116 I915_STATE_WARN(cur_state != state,
117 "%s assertion failure (expected %s, current %s)\n",
118 pll->name, onoff(state), onoff(cur_state));
119}
120
121void intel_prepare_shared_dpll(struct intel_crtc *crtc)
122{
123 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100124 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200125 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200126
127 if (WARN_ON(pll == NULL))
128 return;
129
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100130 mutex_lock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200131 WARN_ON(!pll->config.crtc_mask);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100132 if (!pll->active_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200133 DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
134 WARN_ON(pll->on);
135 assert_shared_dpll_disabled(dev_priv, pll);
136
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200137 pll->funcs.mode_set(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200138 }
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100139 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200140}
141
142/**
143 * intel_enable_shared_dpll - enable PCH PLL
144 * @dev_priv: i915 private structure
145 * @pipe: pipe PLL to enable
146 *
147 * The PCH PLL needs to be enabled before the PCH transcoder, since it
148 * drives the transcoder clock.
149 */
150void intel_enable_shared_dpll(struct intel_crtc *crtc)
151{
152 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100153 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200154 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100155 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100156 unsigned old_mask;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200157
158 if (WARN_ON(pll == NULL))
159 return;
160
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100161 mutex_lock(&dev_priv->dpll_lock);
162 old_mask = pll->active_mask;
163
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100164 if (WARN_ON(!(pll->config.crtc_mask & crtc_mask)) ||
165 WARN_ON(pll->active_mask & crtc_mask))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100166 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200167
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100168 pll->active_mask |= crtc_mask;
169
170 DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n",
171 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200172 crtc->base.base.id);
173
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100174 if (old_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200175 WARN_ON(!pll->on);
176 assert_shared_dpll_enabled(dev_priv, pll);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100177 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200178 }
179 WARN_ON(pll->on);
180
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200181 DRM_DEBUG_KMS("enabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200182 pll->funcs.enable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200183 pll->on = true;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100184
185out:
186 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200187}
188
189void intel_disable_shared_dpll(struct intel_crtc *crtc)
190{
Tvrtko Ursulin66478472016-11-16 08:55:40 +0000191 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200192 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100193 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200194
195 /* PCH only available on ILK+ */
Tvrtko Ursulin66478472016-11-16 08:55:40 +0000196 if (INTEL_GEN(dev_priv) < 5)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200197 return;
198
199 if (pll == NULL)
200 return;
201
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100202 mutex_lock(&dev_priv->dpll_lock);
Maarten Lankhorsta1475e72016-03-14 09:27:53 +0100203 if (WARN_ON(!(pll->active_mask & crtc_mask)))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100204 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200205
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100206 DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
207 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200208 crtc->base.base.id);
209
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200210 assert_shared_dpll_enabled(dev_priv, pll);
211 WARN_ON(!pll->on);
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100212
213 pll->active_mask &= ~crtc_mask;
214 if (pll->active_mask)
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100215 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200216
217 DRM_DEBUG_KMS("disabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200218 pll->funcs.disable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200219 pll->on = false;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100220
221out:
222 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200223}
224
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200225static struct intel_shared_dpll *
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200226intel_find_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200227 struct intel_crtc_state *crtc_state,
228 enum intel_dpll_id range_min,
229 enum intel_dpll_id range_max)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200230{
Chris Wilsonfac5e232016-07-04 11:34:36 +0100231 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200232 struct intel_shared_dpll *pll;
233 struct intel_shared_dpll_config *shared_dpll;
234 enum intel_dpll_id i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200235
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200236 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
237
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200238 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200239 pll = &dev_priv->shared_dplls[i];
240
241 /* Only want to check enabled timings first */
242 if (shared_dpll[i].crtc_mask == 0)
243 continue;
244
245 if (memcmp(&crtc_state->dpll_hw_state,
246 &shared_dpll[i].hw_state,
247 sizeof(crtc_state->dpll_hw_state)) == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300248 DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
249 crtc->base.base.id, crtc->base.name, pll->name,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200250 shared_dpll[i].crtc_mask,
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100251 pll->active_mask);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200252 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200253 }
254 }
255
256 /* Ok no matching timings, maybe there's a free one? */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200257 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200258 pll = &dev_priv->shared_dplls[i];
259 if (shared_dpll[i].crtc_mask == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300260 DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n",
261 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200262 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200263 }
264 }
265
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200266 return NULL;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200267}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200268
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200269static void
270intel_reference_shared_dpll(struct intel_shared_dpll *pll,
271 struct intel_crtc_state *crtc_state)
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200272{
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200273 struct intel_shared_dpll_config *shared_dpll;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200274 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
275 enum intel_dpll_id i = pll->id;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200276
277 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
278
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200279 if (shared_dpll[i].crtc_mask == 0)
280 shared_dpll[i].hw_state =
281 crtc_state->dpll_hw_state;
282
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200283 crtc_state->shared_dpll = pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200284 DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
285 pipe_name(crtc->pipe));
286
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200287 intel_shared_dpll_config_get(shared_dpll, pll, crtc);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200288}
289
290void intel_shared_dpll_commit(struct drm_atomic_state *state)
291{
292 struct drm_i915_private *dev_priv = to_i915(state->dev);
293 struct intel_shared_dpll_config *shared_dpll;
294 struct intel_shared_dpll *pll;
295 enum intel_dpll_id i;
296
297 if (!to_intel_atomic_state(state)->dpll_set)
298 return;
299
300 shared_dpll = to_intel_atomic_state(state)->shared_dpll;
301 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
302 pll = &dev_priv->shared_dplls[i];
303 pll->config = shared_dpll[i];
304 }
305}
306
307static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
308 struct intel_shared_dpll *pll,
309 struct intel_dpll_hw_state *hw_state)
310{
311 uint32_t val;
312
313 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
314 return false;
315
316 val = I915_READ(PCH_DPLL(pll->id));
317 hw_state->dpll = val;
318 hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
319 hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
320
321 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
322
323 return val & DPLL_VCO_ENABLE;
324}
325
326static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
327 struct intel_shared_dpll *pll)
328{
329 I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
330 I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
331}
332
333static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
334{
335 u32 val;
336 bool enabled;
337
Joonas Lahtinen2d1fe072016-04-07 11:08:05 +0300338 I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200339
340 val = I915_READ(PCH_DREF_CONTROL);
341 enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
342 DREF_SUPERSPREAD_SOURCE_MASK));
343 I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
344}
345
346static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
347 struct intel_shared_dpll *pll)
348{
349 /* PCH refclock must be enabled first */
350 ibx_assert_pch_refclk_enabled(dev_priv);
351
352 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
353
354 /* Wait for the clocks to stabilize. */
355 POSTING_READ(PCH_DPLL(pll->id));
356 udelay(150);
357
358 /* The pixel multiplier can only be updated once the
359 * DPLL is enabled and the clocks are stable.
360 *
361 * So write it again.
362 */
363 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
364 POSTING_READ(PCH_DPLL(pll->id));
365 udelay(200);
366}
367
368static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
369 struct intel_shared_dpll *pll)
370{
Chris Wilson91c8a322016-07-05 10:40:23 +0100371 struct drm_device *dev = &dev_priv->drm;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200372 struct intel_crtc *crtc;
373
374 /* Make sure no transcoder isn't still depending on us. */
375 for_each_intel_crtc(dev, crtc) {
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200376 if (crtc->config->shared_dpll == pll)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200377 assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
378 }
379
380 I915_WRITE(PCH_DPLL(pll->id), 0);
381 POSTING_READ(PCH_DPLL(pll->id));
382 udelay(200);
383}
384
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200385static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200386ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
387 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200388{
389 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
390 struct intel_shared_dpll *pll;
391 enum intel_dpll_id i;
392
393 if (HAS_PCH_IBX(dev_priv)) {
394 /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
395 i = (enum intel_dpll_id) crtc->pipe;
396 pll = &dev_priv->shared_dplls[i];
397
Ville Syrjälä78108b72016-05-27 20:59:19 +0300398 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
399 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200400 } else {
401 pll = intel_find_shared_dpll(crtc, crtc_state,
402 DPLL_ID_PCH_PLL_A,
403 DPLL_ID_PCH_PLL_B);
404 }
405
Ander Conselvan de Oliveirabb143162016-05-20 15:47:06 +0300406 if (!pll)
407 return NULL;
408
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200409 /* reference the pll */
410 intel_reference_shared_dpll(pll, crtc_state);
411
412 return pll;
413}
414
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200415static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
416 .mode_set = ibx_pch_dpll_mode_set,
417 .enable = ibx_pch_dpll_enable,
418 .disable = ibx_pch_dpll_disable,
419 .get_hw_state = ibx_pch_dpll_get_hw_state,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200420};
421
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200422static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
423 struct intel_shared_dpll *pll)
424{
425 I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
426 POSTING_READ(WRPLL_CTL(pll->id));
427 udelay(20);
428}
429
430static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
431 struct intel_shared_dpll *pll)
432{
433 I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
434 POSTING_READ(SPLL_CTL);
435 udelay(20);
436}
437
438static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
439 struct intel_shared_dpll *pll)
440{
441 uint32_t val;
442
443 val = I915_READ(WRPLL_CTL(pll->id));
444 I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
445 POSTING_READ(WRPLL_CTL(pll->id));
446}
447
448static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
449 struct intel_shared_dpll *pll)
450{
451 uint32_t val;
452
453 val = I915_READ(SPLL_CTL);
454 I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
455 POSTING_READ(SPLL_CTL);
456}
457
458static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
459 struct intel_shared_dpll *pll,
460 struct intel_dpll_hw_state *hw_state)
461{
462 uint32_t val;
463
464 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
465 return false;
466
467 val = I915_READ(WRPLL_CTL(pll->id));
468 hw_state->wrpll = val;
469
470 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
471
472 return val & WRPLL_PLL_ENABLE;
473}
474
475static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
476 struct intel_shared_dpll *pll,
477 struct intel_dpll_hw_state *hw_state)
478{
479 uint32_t val;
480
481 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
482 return false;
483
484 val = I915_READ(SPLL_CTL);
485 hw_state->spll = val;
486
487 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
488
489 return val & SPLL_PLL_ENABLE;
490}
491
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200492#define LC_FREQ 2700
493#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
494
495#define P_MIN 2
496#define P_MAX 64
497#define P_INC 2
498
499/* Constraints for PLL good behavior */
500#define REF_MIN 48
501#define REF_MAX 400
502#define VCO_MIN 2400
503#define VCO_MAX 4800
504
505struct hsw_wrpll_rnp {
506 unsigned p, n2, r2;
507};
508
509static unsigned hsw_wrpll_get_budget_for_freq(int clock)
510{
511 unsigned budget;
512
513 switch (clock) {
514 case 25175000:
515 case 25200000:
516 case 27000000:
517 case 27027000:
518 case 37762500:
519 case 37800000:
520 case 40500000:
521 case 40541000:
522 case 54000000:
523 case 54054000:
524 case 59341000:
525 case 59400000:
526 case 72000000:
527 case 74176000:
528 case 74250000:
529 case 81000000:
530 case 81081000:
531 case 89012000:
532 case 89100000:
533 case 108000000:
534 case 108108000:
535 case 111264000:
536 case 111375000:
537 case 148352000:
538 case 148500000:
539 case 162000000:
540 case 162162000:
541 case 222525000:
542 case 222750000:
543 case 296703000:
544 case 297000000:
545 budget = 0;
546 break;
547 case 233500000:
548 case 245250000:
549 case 247750000:
550 case 253250000:
551 case 298000000:
552 budget = 1500;
553 break;
554 case 169128000:
555 case 169500000:
556 case 179500000:
557 case 202000000:
558 budget = 2000;
559 break;
560 case 256250000:
561 case 262500000:
562 case 270000000:
563 case 272500000:
564 case 273750000:
565 case 280750000:
566 case 281250000:
567 case 286000000:
568 case 291750000:
569 budget = 4000;
570 break;
571 case 267250000:
572 case 268500000:
573 budget = 5000;
574 break;
575 default:
576 budget = 1000;
577 break;
578 }
579
580 return budget;
581}
582
583static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
584 unsigned r2, unsigned n2, unsigned p,
585 struct hsw_wrpll_rnp *best)
586{
587 uint64_t a, b, c, d, diff, diff_best;
588
589 /* No best (r,n,p) yet */
590 if (best->p == 0) {
591 best->p = p;
592 best->n2 = n2;
593 best->r2 = r2;
594 return;
595 }
596
597 /*
598 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
599 * freq2k.
600 *
601 * delta = 1e6 *
602 * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
603 * freq2k;
604 *
605 * and we would like delta <= budget.
606 *
607 * If the discrepancy is above the PPM-based budget, always prefer to
608 * improve upon the previous solution. However, if you're within the
609 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
610 */
611 a = freq2k * budget * p * r2;
612 b = freq2k * budget * best->p * best->r2;
613 diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
614 diff_best = abs_diff(freq2k * best->p * best->r2,
615 LC_FREQ_2K * best->n2);
616 c = 1000000 * diff;
617 d = 1000000 * diff_best;
618
619 if (a < c && b < d) {
620 /* If both are above the budget, pick the closer */
621 if (best->p * best->r2 * diff < p * r2 * diff_best) {
622 best->p = p;
623 best->n2 = n2;
624 best->r2 = r2;
625 }
626 } else if (a >= c && b < d) {
627 /* If A is below the threshold but B is above it? Update. */
628 best->p = p;
629 best->n2 = n2;
630 best->r2 = r2;
631 } else if (a >= c && b >= d) {
632 /* Both are below the limit, so pick the higher n2/(r2*r2) */
633 if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
634 best->p = p;
635 best->n2 = n2;
636 best->r2 = r2;
637 }
638 }
639 /* Otherwise a < c && b >= d, do nothing */
640}
641
642static void
643hsw_ddi_calculate_wrpll(int clock /* in Hz */,
644 unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
645{
646 uint64_t freq2k;
647 unsigned p, n2, r2;
648 struct hsw_wrpll_rnp best = { 0, 0, 0 };
649 unsigned budget;
650
651 freq2k = clock / 100;
652
653 budget = hsw_wrpll_get_budget_for_freq(clock);
654
655 /* Special case handling for 540 pixel clock: bypass WR PLL entirely
656 * and directly pass the LC PLL to it. */
657 if (freq2k == 5400000) {
658 *n2_out = 2;
659 *p_out = 1;
660 *r2_out = 2;
661 return;
662 }
663
664 /*
665 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
666 * the WR PLL.
667 *
668 * We want R so that REF_MIN <= Ref <= REF_MAX.
669 * Injecting R2 = 2 * R gives:
670 * REF_MAX * r2 > LC_FREQ * 2 and
671 * REF_MIN * r2 < LC_FREQ * 2
672 *
673 * Which means the desired boundaries for r2 are:
674 * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
675 *
676 */
677 for (r2 = LC_FREQ * 2 / REF_MAX + 1;
678 r2 <= LC_FREQ * 2 / REF_MIN;
679 r2++) {
680
681 /*
682 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
683 *
684 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
685 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
686 * VCO_MAX * r2 > n2 * LC_FREQ and
687 * VCO_MIN * r2 < n2 * LC_FREQ)
688 *
689 * Which means the desired boundaries for n2 are:
690 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
691 */
692 for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
693 n2 <= VCO_MAX * r2 / LC_FREQ;
694 n2++) {
695
696 for (p = P_MIN; p <= P_MAX; p += P_INC)
697 hsw_wrpll_update_rnp(freq2k, budget,
698 r2, n2, p, &best);
699 }
700 }
701
702 *n2_out = best.n2;
703 *p_out = best.p;
704 *r2_out = best.r2;
705}
706
Manasi Navare81b9fd82016-09-01 15:08:11 -0700707static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(int clock,
708 struct intel_crtc *crtc,
709 struct intel_crtc_state *crtc_state)
710{
711 struct intel_shared_dpll *pll;
712 uint32_t val;
713 unsigned int p, n2, r2;
714
715 hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
716
717 val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
718 WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
719 WRPLL_DIVIDER_POST(p);
720
721 crtc_state->dpll_hw_state.wrpll = val;
722
723 pll = intel_find_shared_dpll(crtc, crtc_state,
724 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
725
726 if (!pll)
727 return NULL;
728
729 return pll;
730}
731
732struct intel_shared_dpll *hsw_ddi_dp_get_dpll(struct intel_encoder *encoder,
733 int clock)
734{
735 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
736 struct intel_shared_dpll *pll;
737 enum intel_dpll_id pll_id;
738
739 switch (clock / 2) {
740 case 81000:
741 pll_id = DPLL_ID_LCPLL_810;
742 break;
743 case 135000:
744 pll_id = DPLL_ID_LCPLL_1350;
745 break;
746 case 270000:
747 pll_id = DPLL_ID_LCPLL_2700;
748 break;
749 default:
750 DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
751 return NULL;
752 }
753
754 pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
755
756 if (!pll)
757 return NULL;
758
759 return pll;
760}
761
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200762static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200763hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
764 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200765{
766 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200767 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200768
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200769 memset(&crtc_state->dpll_hw_state, 0,
770 sizeof(crtc_state->dpll_hw_state));
771
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200772 if (encoder->type == INTEL_OUTPUT_HDMI) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700773 pll = hsw_ddi_hdmi_get_dpll(clock, crtc, crtc_state);
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200774
Ville Syrjäläcca05022016-06-22 21:57:06 +0300775 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200776 encoder->type == INTEL_OUTPUT_DP_MST ||
777 encoder->type == INTEL_OUTPUT_EDP) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700778 pll = hsw_ddi_dp_get_dpll(encoder, clock);
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200779
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200780 } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
781 if (WARN_ON(crtc_state->port_clock / 2 != 135000))
782 return NULL;
783
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200784 crtc_state->dpll_hw_state.spll =
785 SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
786
787 pll = intel_find_shared_dpll(crtc, crtc_state,
788 DPLL_ID_SPLL, DPLL_ID_SPLL);
789 } else {
790 return NULL;
791 }
792
793 if (!pll)
794 return NULL;
795
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200796 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200797
798 return pll;
799}
800
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200801static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
802 .enable = hsw_ddi_wrpll_enable,
803 .disable = hsw_ddi_wrpll_disable,
804 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200805};
806
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200807static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
808 .enable = hsw_ddi_spll_enable,
809 .disable = hsw_ddi_spll_disable,
810 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200811};
812
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200813static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
814 struct intel_shared_dpll *pll)
815{
816}
817
818static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
819 struct intel_shared_dpll *pll)
820{
821}
822
823static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
824 struct intel_shared_dpll *pll,
825 struct intel_dpll_hw_state *hw_state)
826{
827 return true;
828}
829
830static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
831 .enable = hsw_ddi_lcpll_enable,
832 .disable = hsw_ddi_lcpll_disable,
833 .get_hw_state = hsw_ddi_lcpll_get_hw_state,
834};
835
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200836struct skl_dpll_regs {
837 i915_reg_t ctl, cfgcr1, cfgcr2;
838};
839
840/* this array is indexed by the *shared* pll id */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200841static const struct skl_dpll_regs skl_dpll_regs[4] = {
842 {
843 /* DPLL 0 */
844 .ctl = LCPLL1_CTL,
845 /* DPLL 0 doesn't support HDMI mode */
846 },
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200847 {
848 /* DPLL 1 */
849 .ctl = LCPLL2_CTL,
850 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
851 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
852 },
853 {
854 /* DPLL 2 */
855 .ctl = WRPLL_CTL(0),
856 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
857 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
858 },
859 {
860 /* DPLL 3 */
861 .ctl = WRPLL_CTL(1),
862 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
863 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
864 },
865};
866
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200867static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
868 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200869{
870 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200871
872 val = I915_READ(DPLL_CTRL1);
873
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200874 val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
875 DPLL_CTRL1_LINK_RATE_MASK(pll->id));
876 val |= pll->config.hw_state.ctrl1 << (pll->id * 6);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200877
878 I915_WRITE(DPLL_CTRL1, val);
879 POSTING_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200880}
881
882static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
883 struct intel_shared_dpll *pll)
884{
885 const struct skl_dpll_regs *regs = skl_dpll_regs;
886
887 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200888
889 I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
890 I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
891 POSTING_READ(regs[pll->id].cfgcr1);
892 POSTING_READ(regs[pll->id].cfgcr2);
893
894 /* the enable bit is always bit 31 */
895 I915_WRITE(regs[pll->id].ctl,
896 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
897
Chris Wilson27bf23a2016-06-30 15:33:12 +0100898 if (intel_wait_for_register(dev_priv,
899 DPLL_STATUS,
900 DPLL_LOCK(pll->id),
901 DPLL_LOCK(pll->id),
902 5))
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200903 DRM_ERROR("DPLL %d not locked\n", pll->id);
904}
905
906static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
907 struct intel_shared_dpll *pll)
908{
909 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200910}
911
912static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
913 struct intel_shared_dpll *pll)
914{
915 const struct skl_dpll_regs *regs = skl_dpll_regs;
916
917 /* the enable bit is always bit 31 */
918 I915_WRITE(regs[pll->id].ctl,
919 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
920 POSTING_READ(regs[pll->id].ctl);
921}
922
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200923static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
924 struct intel_shared_dpll *pll)
925{
926}
927
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200928static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
929 struct intel_shared_dpll *pll,
930 struct intel_dpll_hw_state *hw_state)
931{
932 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200933 const struct skl_dpll_regs *regs = skl_dpll_regs;
934 bool ret;
935
936 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
937 return false;
938
939 ret = false;
940
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200941 val = I915_READ(regs[pll->id].ctl);
942 if (!(val & LCPLL_PLL_ENABLE))
943 goto out;
944
945 val = I915_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200946 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200947
948 /* avoid reading back stale values if HDMI mode is not enabled */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200949 if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200950 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
951 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
952 }
953 ret = true;
954
955out:
956 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
957
958 return ret;
959}
960
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200961static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
962 struct intel_shared_dpll *pll,
963 struct intel_dpll_hw_state *hw_state)
964{
965 uint32_t val;
966 const struct skl_dpll_regs *regs = skl_dpll_regs;
967 bool ret;
968
969 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
970 return false;
971
972 ret = false;
973
974 /* DPLL0 is always enabled since it drives CDCLK */
975 val = I915_READ(regs[pll->id].ctl);
976 if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
977 goto out;
978
979 val = I915_READ(DPLL_CTRL1);
980 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
981
982 ret = true;
983
984out:
985 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
986
987 return ret;
988}
989
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +0200990struct skl_wrpll_context {
991 uint64_t min_deviation; /* current minimal deviation */
992 uint64_t central_freq; /* chosen central freq */
993 uint64_t dco_freq; /* chosen dco freq */
994 unsigned int p; /* chosen divider */
995};
996
997static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
998{
999 memset(ctx, 0, sizeof(*ctx));
1000
1001 ctx->min_deviation = U64_MAX;
1002}
1003
1004/* DCO freq must be within +1%/-6% of the DCO central freq */
1005#define SKL_DCO_MAX_PDEVIATION 100
1006#define SKL_DCO_MAX_NDEVIATION 600
1007
1008static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
1009 uint64_t central_freq,
1010 uint64_t dco_freq,
1011 unsigned int divider)
1012{
1013 uint64_t deviation;
1014
1015 deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
1016 central_freq);
1017
1018 /* positive deviation */
1019 if (dco_freq >= central_freq) {
1020 if (deviation < SKL_DCO_MAX_PDEVIATION &&
1021 deviation < ctx->min_deviation) {
1022 ctx->min_deviation = deviation;
1023 ctx->central_freq = central_freq;
1024 ctx->dco_freq = dco_freq;
1025 ctx->p = divider;
1026 }
1027 /* negative deviation */
1028 } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
1029 deviation < ctx->min_deviation) {
1030 ctx->min_deviation = deviation;
1031 ctx->central_freq = central_freq;
1032 ctx->dco_freq = dco_freq;
1033 ctx->p = divider;
1034 }
1035}
1036
1037static void skl_wrpll_get_multipliers(unsigned int p,
1038 unsigned int *p0 /* out */,
1039 unsigned int *p1 /* out */,
1040 unsigned int *p2 /* out */)
1041{
1042 /* even dividers */
1043 if (p % 2 == 0) {
1044 unsigned int half = p / 2;
1045
1046 if (half == 1 || half == 2 || half == 3 || half == 5) {
1047 *p0 = 2;
1048 *p1 = 1;
1049 *p2 = half;
1050 } else if (half % 2 == 0) {
1051 *p0 = 2;
1052 *p1 = half / 2;
1053 *p2 = 2;
1054 } else if (half % 3 == 0) {
1055 *p0 = 3;
1056 *p1 = half / 3;
1057 *p2 = 2;
1058 } else if (half % 7 == 0) {
1059 *p0 = 7;
1060 *p1 = half / 7;
1061 *p2 = 2;
1062 }
1063 } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
1064 *p0 = 3;
1065 *p1 = 1;
1066 *p2 = p / 3;
1067 } else if (p == 5 || p == 7) {
1068 *p0 = p;
1069 *p1 = 1;
1070 *p2 = 1;
1071 } else if (p == 15) {
1072 *p0 = 3;
1073 *p1 = 1;
1074 *p2 = 5;
1075 } else if (p == 21) {
1076 *p0 = 7;
1077 *p1 = 1;
1078 *p2 = 3;
1079 } else if (p == 35) {
1080 *p0 = 7;
1081 *p1 = 1;
1082 *p2 = 5;
1083 }
1084}
1085
1086struct skl_wrpll_params {
1087 uint32_t dco_fraction;
1088 uint32_t dco_integer;
1089 uint32_t qdiv_ratio;
1090 uint32_t qdiv_mode;
1091 uint32_t kdiv;
1092 uint32_t pdiv;
1093 uint32_t central_freq;
1094};
1095
1096static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
1097 uint64_t afe_clock,
1098 uint64_t central_freq,
1099 uint32_t p0, uint32_t p1, uint32_t p2)
1100{
1101 uint64_t dco_freq;
1102
1103 switch (central_freq) {
1104 case 9600000000ULL:
1105 params->central_freq = 0;
1106 break;
1107 case 9000000000ULL:
1108 params->central_freq = 1;
1109 break;
1110 case 8400000000ULL:
1111 params->central_freq = 3;
1112 }
1113
1114 switch (p0) {
1115 case 1:
1116 params->pdiv = 0;
1117 break;
1118 case 2:
1119 params->pdiv = 1;
1120 break;
1121 case 3:
1122 params->pdiv = 2;
1123 break;
1124 case 7:
1125 params->pdiv = 4;
1126 break;
1127 default:
1128 WARN(1, "Incorrect PDiv\n");
1129 }
1130
1131 switch (p2) {
1132 case 5:
1133 params->kdiv = 0;
1134 break;
1135 case 2:
1136 params->kdiv = 1;
1137 break;
1138 case 3:
1139 params->kdiv = 2;
1140 break;
1141 case 1:
1142 params->kdiv = 3;
1143 break;
1144 default:
1145 WARN(1, "Incorrect KDiv\n");
1146 }
1147
1148 params->qdiv_ratio = p1;
1149 params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1150
1151 dco_freq = p0 * p1 * p2 * afe_clock;
1152
1153 /*
1154 * Intermediate values are in Hz.
1155 * Divide by MHz to match bsepc
1156 */
1157 params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1158 params->dco_fraction =
1159 div_u64((div_u64(dco_freq, 24) -
1160 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1161}
1162
1163static bool
1164skl_ddi_calculate_wrpll(int clock /* in Hz */,
1165 struct skl_wrpll_params *wrpll_params)
1166{
1167 uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1168 uint64_t dco_central_freq[3] = {8400000000ULL,
1169 9000000000ULL,
1170 9600000000ULL};
1171 static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1172 24, 28, 30, 32, 36, 40, 42, 44,
1173 48, 52, 54, 56, 60, 64, 66, 68,
1174 70, 72, 76, 78, 80, 84, 88, 90,
1175 92, 96, 98 };
1176 static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1177 static const struct {
1178 const int *list;
1179 int n_dividers;
1180 } dividers[] = {
1181 { even_dividers, ARRAY_SIZE(even_dividers) },
1182 { odd_dividers, ARRAY_SIZE(odd_dividers) },
1183 };
1184 struct skl_wrpll_context ctx;
1185 unsigned int dco, d, i;
1186 unsigned int p0, p1, p2;
1187
1188 skl_wrpll_context_init(&ctx);
1189
1190 for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1191 for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1192 for (i = 0; i < dividers[d].n_dividers; i++) {
1193 unsigned int p = dividers[d].list[i];
1194 uint64_t dco_freq = p * afe_clock;
1195
1196 skl_wrpll_try_divider(&ctx,
1197 dco_central_freq[dco],
1198 dco_freq,
1199 p);
1200 /*
1201 * Skip the remaining dividers if we're sure to
1202 * have found the definitive divider, we can't
1203 * improve a 0 deviation.
1204 */
1205 if (ctx.min_deviation == 0)
1206 goto skip_remaining_dividers;
1207 }
1208 }
1209
1210skip_remaining_dividers:
1211 /*
1212 * If a solution is found with an even divider, prefer
1213 * this one.
1214 */
1215 if (d == 0 && ctx.p)
1216 break;
1217 }
1218
1219 if (!ctx.p) {
1220 DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1221 return false;
1222 }
1223
1224 /*
1225 * gcc incorrectly analyses that these can be used without being
1226 * initialized. To be fair, it's hard to guess.
1227 */
1228 p0 = p1 = p2 = 0;
1229 skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1230 skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1231 p0, p1, p2);
1232
1233 return true;
1234}
1235
Jim Bride9a4edad2016-09-01 15:08:10 -07001236static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
1237 struct intel_crtc_state *crtc_state,
1238 int clock)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001239{
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001240 uint32_t ctrl1, cfgcr1, cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001241 struct skl_wrpll_params wrpll_params = { 0, };
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001242
1243 /*
1244 * See comment in intel_dpll_hw_state to understand why we always use 0
1245 * as the DPLL id in this function.
1246 */
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001247 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1248
Jim Bride9a4edad2016-09-01 15:08:10 -07001249 ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001250
Jim Bride9a4edad2016-09-01 15:08:10 -07001251 if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
1252 return false;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001253
Jim Bride9a4edad2016-09-01 15:08:10 -07001254 cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1255 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1256 wrpll_params.dco_integer;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001257
Jim Bride9a4edad2016-09-01 15:08:10 -07001258 cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1259 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1260 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1261 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1262 wrpll_params.central_freq;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001263
1264 memset(&crtc_state->dpll_hw_state, 0,
1265 sizeof(crtc_state->dpll_hw_state));
1266
1267 crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1268 crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1269 crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001270 return true;
1271}
1272
1273
1274bool skl_ddi_dp_set_dpll_hw_state(int clock,
1275 struct intel_dpll_hw_state *dpll_hw_state)
1276{
1277 uint32_t ctrl1;
1278
1279 /*
1280 * See comment in intel_dpll_hw_state to understand why we always use 0
1281 * as the DPLL id in this function.
1282 */
1283 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1284 switch (clock / 2) {
1285 case 81000:
1286 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1287 break;
1288 case 135000:
1289 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1290 break;
1291 case 270000:
1292 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1293 break;
1294 /* eDP 1.4 rates */
1295 case 162000:
1296 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
1297 break;
1298 case 108000:
1299 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
1300 break;
1301 case 216000:
1302 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
1303 break;
1304 }
1305
1306 dpll_hw_state->ctrl1 = ctrl1;
1307 return true;
1308}
1309
1310static struct intel_shared_dpll *
1311skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1312 struct intel_encoder *encoder)
1313{
1314 struct intel_shared_dpll *pll;
1315 int clock = crtc_state->port_clock;
1316 bool bret;
1317 struct intel_dpll_hw_state dpll_hw_state;
1318
1319 memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
1320
1321 if (encoder->type == INTEL_OUTPUT_HDMI) {
1322 bret = skl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock);
1323 if (!bret) {
1324 DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n");
1325 return NULL;
1326 }
1327 } else if (encoder->type == INTEL_OUTPUT_DP ||
1328 encoder->type == INTEL_OUTPUT_DP_MST ||
1329 encoder->type == INTEL_OUTPUT_EDP) {
1330 bret = skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state);
1331 if (!bret) {
1332 DRM_DEBUG_KMS("Could not set DP dpll HW state.\n");
1333 return NULL;
1334 }
1335 crtc_state->dpll_hw_state = dpll_hw_state;
1336 } else {
1337 return NULL;
1338 }
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001339
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001340 if (encoder->type == INTEL_OUTPUT_EDP)
1341 pll = intel_find_shared_dpll(crtc, crtc_state,
1342 DPLL_ID_SKL_DPLL0,
1343 DPLL_ID_SKL_DPLL0);
1344 else
1345 pll = intel_find_shared_dpll(crtc, crtc_state,
1346 DPLL_ID_SKL_DPLL1,
1347 DPLL_ID_SKL_DPLL3);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001348 if (!pll)
1349 return NULL;
1350
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001351 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001352
1353 return pll;
1354}
1355
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001356static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1357 .enable = skl_ddi_pll_enable,
1358 .disable = skl_ddi_pll_disable,
1359 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001360};
1361
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001362static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
1363 .enable = skl_ddi_dpll0_enable,
1364 .disable = skl_ddi_dpll0_disable,
1365 .get_hw_state = skl_ddi_dpll0_get_hw_state,
1366};
1367
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001368static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1369 struct intel_shared_dpll *pll)
1370{
1371 uint32_t temp;
1372 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001373 enum dpio_phy phy;
1374 enum dpio_channel ch;
1375
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001376 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001377
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001378 /* Non-SSC reference */
Dongwon Kimda6110b2016-04-14 15:37:43 -07001379 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1380 temp |= PORT_PLL_REF_SEL;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001381 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1382
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001383 if (IS_GEMINILAKE(dev_priv)) {
1384 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1385 temp |= PORT_PLL_POWER_ENABLE;
1386 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1387
1388 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1389 PORT_PLL_POWER_STATE), 200))
1390 DRM_ERROR("Power state not set for PLL:%d\n", port);
1391 }
1392
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001393 /* Disable 10 bit clock */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001394 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001395 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001396 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001397
1398 /* Write P1 & P2 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001399 temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001400 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
1401 temp |= pll->config.hw_state.ebb0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001402 I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001403
1404 /* Write M2 integer */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001405 temp = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001406 temp &= ~PORT_PLL_M2_MASK;
1407 temp |= pll->config.hw_state.pll0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001408 I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001409
1410 /* Write N */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001411 temp = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001412 temp &= ~PORT_PLL_N_MASK;
1413 temp |= pll->config.hw_state.pll1;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001414 I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001415
1416 /* Write M2 fraction */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001417 temp = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001418 temp &= ~PORT_PLL_M2_FRAC_MASK;
1419 temp |= pll->config.hw_state.pll2;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001420 I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001421
1422 /* Write M2 fraction enable */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001423 temp = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001424 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
1425 temp |= pll->config.hw_state.pll3;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001426 I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001427
1428 /* Write coeff */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001429 temp = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001430 temp &= ~PORT_PLL_PROP_COEFF_MASK;
1431 temp &= ~PORT_PLL_INT_COEFF_MASK;
1432 temp &= ~PORT_PLL_GAIN_CTL_MASK;
1433 temp |= pll->config.hw_state.pll6;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001434 I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001435
1436 /* Write calibration val */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001437 temp = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001438 temp &= ~PORT_PLL_TARGET_CNT_MASK;
1439 temp |= pll->config.hw_state.pll8;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001440 I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001441
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001442 temp = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001443 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
1444 temp |= pll->config.hw_state.pll9;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001445 I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001446
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001447 temp = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001448 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1449 temp &= ~PORT_PLL_DCO_AMP_MASK;
1450 temp |= pll->config.hw_state.pll10;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001451 I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001452
1453 /* Recalibrate with new settings */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001454 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001455 temp |= PORT_PLL_RECALIBRATE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001456 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001457 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1458 temp |= pll->config.hw_state.ebb4;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001459 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001460
1461 /* Enable PLL */
1462 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1463 temp |= PORT_PLL_ENABLE;
1464 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1465 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1466
Imre Deak0b786e42016-06-28 13:37:30 +03001467 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
1468 200))
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001469 DRM_ERROR("PLL %d not locked\n", port);
1470
Ander Conselvan de Oliveira51b3ee32016-12-02 10:23:52 +02001471 if (IS_GEMINILAKE(dev_priv)) {
1472 temp = I915_READ(BXT_PORT_TX_DW5_LN0(phy, ch));
1473 temp |= DCC_DELAY_RANGE_2;
1474 I915_WRITE(BXT_PORT_TX_DW5_GRP(phy, ch), temp);
1475 }
1476
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001477 /*
1478 * While we write to the group register to program all lanes at once we
1479 * can read only lane registers and we pick lanes 0/1 for that.
1480 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001481 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001482 temp &= ~LANE_STAGGER_MASK;
1483 temp &= ~LANESTAGGER_STRAP_OVRD;
1484 temp |= pll->config.hw_state.pcsdw12;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001485 I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001486}
1487
1488static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1489 struct intel_shared_dpll *pll)
1490{
1491 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1492 uint32_t temp;
1493
1494 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1495 temp &= ~PORT_PLL_ENABLE;
1496 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1497 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001498
1499 if (IS_GEMINILAKE(dev_priv)) {
1500 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1501 temp &= ~PORT_PLL_POWER_ENABLE;
1502 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1503
1504 if (wait_for_us(!(I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1505 PORT_PLL_POWER_STATE), 200))
1506 DRM_ERROR("Power state not reset for PLL:%d\n", port);
1507 }
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001508}
1509
1510static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1511 struct intel_shared_dpll *pll,
1512 struct intel_dpll_hw_state *hw_state)
1513{
1514 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1515 uint32_t val;
1516 bool ret;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001517 enum dpio_phy phy;
1518 enum dpio_channel ch;
1519
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001520 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001521
1522 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1523 return false;
1524
1525 ret = false;
1526
1527 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1528 if (!(val & PORT_PLL_ENABLE))
1529 goto out;
1530
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001531 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001532 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1533
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001534 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001535 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1536
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001537 hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001538 hw_state->pll0 &= PORT_PLL_M2_MASK;
1539
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001540 hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001541 hw_state->pll1 &= PORT_PLL_N_MASK;
1542
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001543 hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001544 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1545
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001546 hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001547 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1548
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001549 hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001550 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1551 PORT_PLL_INT_COEFF_MASK |
1552 PORT_PLL_GAIN_CTL_MASK;
1553
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001554 hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001555 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1556
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001557 hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001558 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1559
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001560 hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001561 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1562 PORT_PLL_DCO_AMP_MASK;
1563
1564 /*
1565 * While we write to the group register to program all lanes at once we
1566 * can read only lane registers. We configure all lanes the same way, so
1567 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1568 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001569 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
1570 if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001571 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1572 hw_state->pcsdw12,
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001573 I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001574 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1575
1576 ret = true;
1577
1578out:
1579 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1580
1581 return ret;
1582}
1583
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001584/* bxt clock parameters */
1585struct bxt_clk_div {
1586 int clock;
1587 uint32_t p1;
1588 uint32_t p2;
1589 uint32_t m2_int;
1590 uint32_t m2_frac;
1591 bool m2_frac_en;
1592 uint32_t n;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001593
1594 int vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001595};
1596
1597/* pre-calculated values for DP linkrates */
1598static const struct bxt_clk_div bxt_dp_clk_val[] = {
1599 {162000, 4, 2, 32, 1677722, 1, 1},
1600 {270000, 4, 1, 27, 0, 0, 1},
1601 {540000, 2, 1, 27, 0, 0, 1},
1602 {216000, 3, 2, 32, 1677722, 1, 1},
1603 {243000, 4, 1, 24, 1258291, 1, 1},
1604 {324000, 4, 1, 32, 1677722, 1, 1},
1605 {432000, 3, 1, 32, 1677722, 1, 1}
1606};
1607
Durgadoss Ra277ca72016-09-01 15:08:09 -07001608static bool
1609bxt_ddi_hdmi_pll_dividers(struct intel_crtc *intel_crtc,
1610 struct intel_crtc_state *crtc_state, int clock,
1611 struct bxt_clk_div *clk_div)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001612{
Durgadoss Ra277ca72016-09-01 15:08:09 -07001613 struct dpll best_clock;
1614
1615 /* Calculate HDMI div */
1616 /*
1617 * FIXME: tie the following calculation into
1618 * i9xx_crtc_compute_clock
1619 */
1620 if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
1621 DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1622 clock, pipe_name(intel_crtc->pipe));
1623 return false;
1624 }
1625
1626 clk_div->p1 = best_clock.p1;
1627 clk_div->p2 = best_clock.p2;
1628 WARN_ON(best_clock.m1 != 2);
1629 clk_div->n = best_clock.n;
1630 clk_div->m2_int = best_clock.m2 >> 22;
1631 clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
1632 clk_div->m2_frac_en = clk_div->m2_frac != 0;
1633
1634 clk_div->vco = best_clock.vco;
1635
1636 return true;
1637}
1638
1639static void bxt_ddi_dp_pll_dividers(int clock, struct bxt_clk_div *clk_div)
1640{
1641 int i;
1642
1643 *clk_div = bxt_dp_clk_val[0];
1644 for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1645 if (bxt_dp_clk_val[i].clock == clock) {
1646 *clk_div = bxt_dp_clk_val[i];
1647 break;
1648 }
1649 }
1650
1651 clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
1652}
1653
1654static bool bxt_ddi_set_dpll_hw_state(int clock,
1655 struct bxt_clk_div *clk_div,
1656 struct intel_dpll_hw_state *dpll_hw_state)
1657{
1658 int vco = clk_div->vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001659 uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
1660 uint32_t lanestagger;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001661
1662 if (vco >= 6200000 && vco <= 6700000) {
1663 prop_coef = 4;
1664 int_coef = 9;
1665 gain_ctl = 3;
1666 targ_cnt = 8;
1667 } else if ((vco > 5400000 && vco < 6200000) ||
1668 (vco >= 4800000 && vco < 5400000)) {
1669 prop_coef = 5;
1670 int_coef = 11;
1671 gain_ctl = 3;
1672 targ_cnt = 9;
1673 } else if (vco == 5400000) {
1674 prop_coef = 3;
1675 int_coef = 8;
1676 gain_ctl = 1;
1677 targ_cnt = 9;
1678 } else {
1679 DRM_ERROR("Invalid VCO\n");
Durgadoss Ra277ca72016-09-01 15:08:09 -07001680 return false;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001681 }
1682
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001683 if (clock > 270000)
1684 lanestagger = 0x18;
1685 else if (clock > 135000)
1686 lanestagger = 0x0d;
1687 else if (clock > 67000)
1688 lanestagger = 0x07;
1689 else if (clock > 33000)
1690 lanestagger = 0x04;
1691 else
1692 lanestagger = 0x02;
1693
Durgadoss Ra277ca72016-09-01 15:08:09 -07001694 dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
1695 dpll_hw_state->pll0 = clk_div->m2_int;
1696 dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
1697 dpll_hw_state->pll2 = clk_div->m2_frac;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001698
Durgadoss Ra277ca72016-09-01 15:08:09 -07001699 if (clk_div->m2_frac_en)
1700 dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001701
Durgadoss Ra277ca72016-09-01 15:08:09 -07001702 dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
1703 dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001704
Durgadoss Ra277ca72016-09-01 15:08:09 -07001705 dpll_hw_state->pll8 = targ_cnt;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001706
Durgadoss Ra277ca72016-09-01 15:08:09 -07001707 dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001708
Durgadoss Ra277ca72016-09-01 15:08:09 -07001709 dpll_hw_state->pll10 =
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001710 PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1711 | PORT_PLL_DCO_AMP_OVR_EN_H;
1712
Durgadoss Ra277ca72016-09-01 15:08:09 -07001713 dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001714
Durgadoss Ra277ca72016-09-01 15:08:09 -07001715 dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger;
1716
1717 return true;
1718}
1719
1720bool bxt_ddi_dp_set_dpll_hw_state(int clock,
1721 struct intel_dpll_hw_state *dpll_hw_state)
1722{
1723 struct bxt_clk_div clk_div = {0};
1724
1725 bxt_ddi_dp_pll_dividers(clock, &clk_div);
1726
1727 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1728}
1729
Imre Deaka04139c2016-09-26 17:54:31 +03001730static bool
1731bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc *intel_crtc,
1732 struct intel_crtc_state *crtc_state, int clock,
1733 struct intel_dpll_hw_state *dpll_hw_state)
1734{
1735 struct bxt_clk_div clk_div = { };
1736
1737 bxt_ddi_hdmi_pll_dividers(intel_crtc, crtc_state, clock, &clk_div);
1738
1739 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1740}
1741
Durgadoss Ra277ca72016-09-01 15:08:09 -07001742static struct intel_shared_dpll *
1743bxt_get_dpll(struct intel_crtc *crtc,
1744 struct intel_crtc_state *crtc_state,
1745 struct intel_encoder *encoder)
1746{
Imre Deaka04139c2016-09-26 17:54:31 +03001747 struct intel_dpll_hw_state dpll_hw_state = { };
Durgadoss Ra277ca72016-09-01 15:08:09 -07001748 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1749 struct intel_digital_port *intel_dig_port;
1750 struct intel_shared_dpll *pll;
1751 int i, clock = crtc_state->port_clock;
1752
Imre Deaka04139c2016-09-26 17:54:31 +03001753 if (encoder->type == INTEL_OUTPUT_HDMI &&
1754 !bxt_ddi_hdmi_set_dpll_hw_state(crtc, crtc_state, clock,
1755 &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001756 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001757
1758 if ((encoder->type == INTEL_OUTPUT_DP ||
1759 encoder->type == INTEL_OUTPUT_EDP) &&
1760 !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001761 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001762
1763 memset(&crtc_state->dpll_hw_state, 0,
1764 sizeof(crtc_state->dpll_hw_state));
1765
1766 crtc_state->dpll_hw_state = dpll_hw_state;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001767
Maarten Lankhorsta79e8cc2016-08-09 17:04:00 +02001768 if (encoder->type == INTEL_OUTPUT_DP_MST) {
1769 struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
1770
1771 intel_dig_port = intel_mst->primary;
1772 } else
1773 intel_dig_port = enc_to_dig_port(&encoder->base);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001774
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001775 /* 1:1 mapping between ports and PLLs */
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001776 i = (enum intel_dpll_id) intel_dig_port->port;
1777 pll = intel_get_shared_dpll_by_id(dev_priv, i);
1778
Ville Syrjälä78108b72016-05-27 20:59:19 +03001779 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
1780 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001781
1782 intel_reference_shared_dpll(pll, crtc_state);
1783
1784 return pll;
1785}
1786
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001787static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1788 .enable = bxt_ddi_pll_enable,
1789 .disable = bxt_ddi_pll_disable,
1790 .get_hw_state = bxt_ddi_pll_get_hw_state,
1791};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001792
1793static void intel_ddi_pll_init(struct drm_device *dev)
1794{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001795 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001796
Ville Syrjälä9f7eb312016-05-13 23:41:29 +03001797 if (INTEL_GEN(dev_priv) < 9) {
1798 uint32_t val = I915_READ(LCPLL_CTL);
Ville Syrjäläb2045352016-05-13 23:41:27 +03001799
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001800 /*
1801 * The LCPLL register should be turned on by the BIOS. For now
1802 * let's just check its state and print errors in case
1803 * something is wrong. Don't even try to turn it on.
1804 */
1805
1806 if (val & LCPLL_CD_SOURCE_FCLK)
1807 DRM_ERROR("CDCLK source is not LCPLL\n");
1808
1809 if (val & LCPLL_PLL_DISABLE)
1810 DRM_ERROR("LCPLL is disabled\n");
1811 }
1812}
1813
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001814struct dpll_info {
1815 const char *name;
1816 const int id;
1817 const struct intel_shared_dpll_funcs *funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001818 uint32_t flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001819};
1820
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001821struct intel_dpll_mgr {
1822 const struct dpll_info *dpll_info;
1823
1824 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001825 struct intel_crtc_state *crtc_state,
1826 struct intel_encoder *encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001827};
1828
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001829static const struct dpll_info pch_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001830 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
1831 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
1832 { NULL, -1, NULL, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001833};
1834
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001835static const struct intel_dpll_mgr pch_pll_mgr = {
1836 .dpll_info = pch_plls,
1837 .get_dpll = ibx_get_dpll,
1838};
1839
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001840static const struct dpll_info hsw_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001841 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 },
1842 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 },
1843 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 },
1844 { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1845 { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1846 { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001847 { NULL, -1, NULL, },
1848};
1849
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001850static const struct intel_dpll_mgr hsw_pll_mgr = {
1851 .dpll_info = hsw_plls,
1852 .get_dpll = hsw_get_dpll,
1853};
1854
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001855static const struct dpll_info skl_plls[] = {
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001856 { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
Ville Syrjäläd5aab9d2016-05-11 22:04:33 +03001857 { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
1858 { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
1859 { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001860 { NULL, -1, NULL, },
1861};
1862
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001863static const struct intel_dpll_mgr skl_pll_mgr = {
1864 .dpll_info = skl_plls,
1865 .get_dpll = skl_get_dpll,
1866};
1867
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001868static const struct dpll_info bxt_plls[] = {
Imre Deak08250c42016-03-14 19:55:34 +02001869 { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
1870 { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
1871 { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001872 { NULL, -1, NULL, },
1873};
1874
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001875static const struct intel_dpll_mgr bxt_pll_mgr = {
1876 .dpll_info = bxt_plls,
1877 .get_dpll = bxt_get_dpll,
1878};
1879
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001880void intel_shared_dpll_init(struct drm_device *dev)
1881{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001882 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001883 const struct intel_dpll_mgr *dpll_mgr = NULL;
1884 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001885 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001886
Tvrtko Ursulin08537232016-10-13 11:03:02 +01001887 if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001888 dpll_mgr = &skl_pll_mgr;
Ander Conselvan de Oliveiracc3f90f2016-12-02 10:23:49 +02001889 else if (IS_GEN9_LP(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001890 dpll_mgr = &bxt_pll_mgr;
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01001891 else if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001892 dpll_mgr = &hsw_pll_mgr;
Tvrtko Ursulin6e266952016-10-13 11:02:53 +01001893 else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001894 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001895
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001896 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001897 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001898 return;
1899 }
1900
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001901 dpll_info = dpll_mgr->dpll_info;
1902
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001903 for (i = 0; dpll_info[i].id >= 0; i++) {
1904 WARN_ON(i != dpll_info[i].id);
1905
1906 dev_priv->shared_dplls[i].id = dpll_info[i].id;
1907 dev_priv->shared_dplls[i].name = dpll_info[i].name;
1908 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001909 dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001910 }
1911
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001912 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001913 dev_priv->num_shared_dpll = i;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +01001914 mutex_init(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001915
1916 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001917
1918 /* FIXME: Move this to a more suitable place */
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01001919 if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001920 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001921}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001922
1923struct intel_shared_dpll *
1924intel_get_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001925 struct intel_crtc_state *crtc_state,
1926 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001927{
1928 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1929 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
1930
1931 if (WARN_ON(!dpll_mgr))
1932 return NULL;
1933
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001934 return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001935}