blob: 4c4b434b74b9871efc1ab377332d5b4ee5a4d230 [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 */
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +020041 if (pll->state.crtc_mask == 0)
Jim Bridef1696602016-09-07 15:47:34 -070042 continue;
43
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +020044 if (memcmp(&dpll_hw_state, &pll->state.hw_state,
45 sizeof(pll->state.hw_state)) == 0) {
Jim Bridef1696602016-09-07 15:47:34 -070046 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];
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +020055 if (pll->state.crtc_mask == 0) {
56 pll->state.hw_state = dpll_hw_state;
Jim Bridef1696602016-09-07 15:47:34 -070057 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
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020082/* For ILK+ */
83void assert_shared_dpll(struct drm_i915_private *dev_priv,
84 struct intel_shared_dpll *pll,
85 bool state)
86{
87 bool cur_state;
88 struct intel_dpll_hw_state hw_state;
89
90 if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
91 return;
92
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +020093 cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020094 I915_STATE_WARN(cur_state != state,
95 "%s assertion failure (expected %s, current %s)\n",
96 pll->name, onoff(state), onoff(cur_state));
97}
98
99void intel_prepare_shared_dpll(struct intel_crtc *crtc)
100{
101 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100102 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200103 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200104
105 if (WARN_ON(pll == NULL))
106 return;
107
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100108 mutex_lock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200109 WARN_ON(!pll->state.crtc_mask);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100110 if (!pll->active_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200111 DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
112 WARN_ON(pll->on);
113 assert_shared_dpll_disabled(dev_priv, pll);
114
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200115 pll->funcs.mode_set(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200116 }
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100117 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200118}
119
120/**
121 * intel_enable_shared_dpll - enable PCH PLL
122 * @dev_priv: i915 private structure
123 * @pipe: pipe PLL to enable
124 *
125 * The PCH PLL needs to be enabled before the PCH transcoder, since it
126 * drives the transcoder clock.
127 */
128void intel_enable_shared_dpll(struct intel_crtc *crtc)
129{
130 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100131 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200132 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100133 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100134 unsigned old_mask;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200135
136 if (WARN_ON(pll == NULL))
137 return;
138
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100139 mutex_lock(&dev_priv->dpll_lock);
140 old_mask = pll->active_mask;
141
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200142 if (WARN_ON(!(pll->state.crtc_mask & crtc_mask)) ||
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100143 WARN_ON(pll->active_mask & crtc_mask))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100144 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200145
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100146 pll->active_mask |= crtc_mask;
147
148 DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n",
149 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200150 crtc->base.base.id);
151
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100152 if (old_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200153 WARN_ON(!pll->on);
154 assert_shared_dpll_enabled(dev_priv, pll);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100155 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200156 }
157 WARN_ON(pll->on);
158
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200159 DRM_DEBUG_KMS("enabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200160 pll->funcs.enable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200161 pll->on = true;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100162
163out:
164 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200165}
166
167void intel_disable_shared_dpll(struct intel_crtc *crtc)
168{
Tvrtko Ursulin66478472016-11-16 08:55:40 +0000169 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200170 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100171 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200172
173 /* PCH only available on ILK+ */
Tvrtko Ursulin66478472016-11-16 08:55:40 +0000174 if (INTEL_GEN(dev_priv) < 5)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200175 return;
176
177 if (pll == NULL)
178 return;
179
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100180 mutex_lock(&dev_priv->dpll_lock);
Maarten Lankhorsta1475e72016-03-14 09:27:53 +0100181 if (WARN_ON(!(pll->active_mask & crtc_mask)))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100182 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200183
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100184 DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
185 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200186 crtc->base.base.id);
187
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200188 assert_shared_dpll_enabled(dev_priv, pll);
189 WARN_ON(!pll->on);
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100190
191 pll->active_mask &= ~crtc_mask;
192 if (pll->active_mask)
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100193 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200194
195 DRM_DEBUG_KMS("disabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200196 pll->funcs.disable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200197 pll->on = false;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100198
199out:
200 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200201}
202
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200203static struct intel_shared_dpll *
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200204intel_find_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200205 struct intel_crtc_state *crtc_state,
206 enum intel_dpll_id range_min,
207 enum intel_dpll_id range_max)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200208{
Chris Wilsonfac5e232016-07-04 11:34:36 +0100209 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200210 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200211 struct intel_shared_dpll_state *shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200212 enum intel_dpll_id i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200213
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200214 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
215
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200216 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200217 pll = &dev_priv->shared_dplls[i];
218
219 /* Only want to check enabled timings first */
220 if (shared_dpll[i].crtc_mask == 0)
221 continue;
222
223 if (memcmp(&crtc_state->dpll_hw_state,
224 &shared_dpll[i].hw_state,
225 sizeof(crtc_state->dpll_hw_state)) == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300226 DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
227 crtc->base.base.id, crtc->base.name, pll->name,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200228 shared_dpll[i].crtc_mask,
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100229 pll->active_mask);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200230 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200231 }
232 }
233
234 /* Ok no matching timings, maybe there's a free one? */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200235 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200236 pll = &dev_priv->shared_dplls[i];
237 if (shared_dpll[i].crtc_mask == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300238 DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n",
239 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200240 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200241 }
242 }
243
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200244 return NULL;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200245}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200246
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200247static void
248intel_reference_shared_dpll(struct intel_shared_dpll *pll,
249 struct intel_crtc_state *crtc_state)
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200250{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200251 struct intel_shared_dpll_state *shared_dpll;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200252 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
253 enum intel_dpll_id i = pll->id;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200254
255 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
256
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200257 if (shared_dpll[i].crtc_mask == 0)
258 shared_dpll[i].hw_state =
259 crtc_state->dpll_hw_state;
260
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200261 crtc_state->shared_dpll = pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200262 DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
263 pipe_name(crtc->pipe));
264
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +0200265 shared_dpll[pll->id].crtc_mask |= 1 << crtc->pipe;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200266}
267
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200268void intel_shared_dpll_swap_state(struct drm_atomic_state *state)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200269{
270 struct drm_i915_private *dev_priv = to_i915(state->dev);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200271 struct intel_shared_dpll_state *shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200272 struct intel_shared_dpll *pll;
273 enum intel_dpll_id i;
274
275 if (!to_intel_atomic_state(state)->dpll_set)
276 return;
277
278 shared_dpll = to_intel_atomic_state(state)->shared_dpll;
279 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200280 struct intel_shared_dpll_state tmp;
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200281
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200282 pll = &dev_priv->shared_dplls[i];
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200283
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200284 tmp = pll->state;
285 pll->state = shared_dpll[i];
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200286 shared_dpll[i] = tmp;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200287 }
288}
289
290static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
291 struct intel_shared_dpll *pll,
292 struct intel_dpll_hw_state *hw_state)
293{
294 uint32_t val;
295
296 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
297 return false;
298
299 val = I915_READ(PCH_DPLL(pll->id));
300 hw_state->dpll = val;
301 hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
302 hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
303
304 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
305
306 return val & DPLL_VCO_ENABLE;
307}
308
309static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
310 struct intel_shared_dpll *pll)
311{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200312 I915_WRITE(PCH_FP0(pll->id), pll->state.hw_state.fp0);
313 I915_WRITE(PCH_FP1(pll->id), pll->state.hw_state.fp1);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200314}
315
316static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
317{
318 u32 val;
319 bool enabled;
320
Joonas Lahtinen2d1fe072016-04-07 11:08:05 +0300321 I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200322
323 val = I915_READ(PCH_DREF_CONTROL);
324 enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
325 DREF_SUPERSPREAD_SOURCE_MASK));
326 I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
327}
328
329static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
330 struct intel_shared_dpll *pll)
331{
332 /* PCH refclock must be enabled first */
333 ibx_assert_pch_refclk_enabled(dev_priv);
334
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200335 I915_WRITE(PCH_DPLL(pll->id), pll->state.hw_state.dpll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200336
337 /* Wait for the clocks to stabilize. */
338 POSTING_READ(PCH_DPLL(pll->id));
339 udelay(150);
340
341 /* The pixel multiplier can only be updated once the
342 * DPLL is enabled and the clocks are stable.
343 *
344 * So write it again.
345 */
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200346 I915_WRITE(PCH_DPLL(pll->id), pll->state.hw_state.dpll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200347 POSTING_READ(PCH_DPLL(pll->id));
348 udelay(200);
349}
350
351static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
352 struct intel_shared_dpll *pll)
353{
Chris Wilson91c8a322016-07-05 10:40:23 +0100354 struct drm_device *dev = &dev_priv->drm;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200355 struct intel_crtc *crtc;
356
357 /* Make sure no transcoder isn't still depending on us. */
358 for_each_intel_crtc(dev, crtc) {
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200359 if (crtc->config->shared_dpll == pll)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200360 assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
361 }
362
363 I915_WRITE(PCH_DPLL(pll->id), 0);
364 POSTING_READ(PCH_DPLL(pll->id));
365 udelay(200);
366}
367
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200368static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200369ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
370 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200371{
372 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
373 struct intel_shared_dpll *pll;
374 enum intel_dpll_id i;
375
376 if (HAS_PCH_IBX(dev_priv)) {
377 /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
378 i = (enum intel_dpll_id) crtc->pipe;
379 pll = &dev_priv->shared_dplls[i];
380
Ville Syrjälä78108b72016-05-27 20:59:19 +0300381 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
382 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200383 } else {
384 pll = intel_find_shared_dpll(crtc, crtc_state,
385 DPLL_ID_PCH_PLL_A,
386 DPLL_ID_PCH_PLL_B);
387 }
388
Ander Conselvan de Oliveirabb143162016-05-20 15:47:06 +0300389 if (!pll)
390 return NULL;
391
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200392 /* reference the pll */
393 intel_reference_shared_dpll(pll, crtc_state);
394
395 return pll;
396}
397
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200398static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
399 .mode_set = ibx_pch_dpll_mode_set,
400 .enable = ibx_pch_dpll_enable,
401 .disable = ibx_pch_dpll_disable,
402 .get_hw_state = ibx_pch_dpll_get_hw_state,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200403};
404
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200405static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
406 struct intel_shared_dpll *pll)
407{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200408 I915_WRITE(WRPLL_CTL(pll->id), pll->state.hw_state.wrpll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200409 POSTING_READ(WRPLL_CTL(pll->id));
410 udelay(20);
411}
412
413static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
414 struct intel_shared_dpll *pll)
415{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200416 I915_WRITE(SPLL_CTL, pll->state.hw_state.spll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200417 POSTING_READ(SPLL_CTL);
418 udelay(20);
419}
420
421static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
422 struct intel_shared_dpll *pll)
423{
424 uint32_t val;
425
426 val = I915_READ(WRPLL_CTL(pll->id));
427 I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
428 POSTING_READ(WRPLL_CTL(pll->id));
429}
430
431static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
432 struct intel_shared_dpll *pll)
433{
434 uint32_t val;
435
436 val = I915_READ(SPLL_CTL);
437 I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
438 POSTING_READ(SPLL_CTL);
439}
440
441static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
442 struct intel_shared_dpll *pll,
443 struct intel_dpll_hw_state *hw_state)
444{
445 uint32_t val;
446
447 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
448 return false;
449
450 val = I915_READ(WRPLL_CTL(pll->id));
451 hw_state->wrpll = val;
452
453 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
454
455 return val & WRPLL_PLL_ENABLE;
456}
457
458static bool hsw_ddi_spll_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(SPLL_CTL);
468 hw_state->spll = val;
469
470 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
471
472 return val & SPLL_PLL_ENABLE;
473}
474
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200475#define LC_FREQ 2700
476#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
477
478#define P_MIN 2
479#define P_MAX 64
480#define P_INC 2
481
482/* Constraints for PLL good behavior */
483#define REF_MIN 48
484#define REF_MAX 400
485#define VCO_MIN 2400
486#define VCO_MAX 4800
487
488struct hsw_wrpll_rnp {
489 unsigned p, n2, r2;
490};
491
492static unsigned hsw_wrpll_get_budget_for_freq(int clock)
493{
494 unsigned budget;
495
496 switch (clock) {
497 case 25175000:
498 case 25200000:
499 case 27000000:
500 case 27027000:
501 case 37762500:
502 case 37800000:
503 case 40500000:
504 case 40541000:
505 case 54000000:
506 case 54054000:
507 case 59341000:
508 case 59400000:
509 case 72000000:
510 case 74176000:
511 case 74250000:
512 case 81000000:
513 case 81081000:
514 case 89012000:
515 case 89100000:
516 case 108000000:
517 case 108108000:
518 case 111264000:
519 case 111375000:
520 case 148352000:
521 case 148500000:
522 case 162000000:
523 case 162162000:
524 case 222525000:
525 case 222750000:
526 case 296703000:
527 case 297000000:
528 budget = 0;
529 break;
530 case 233500000:
531 case 245250000:
532 case 247750000:
533 case 253250000:
534 case 298000000:
535 budget = 1500;
536 break;
537 case 169128000:
538 case 169500000:
539 case 179500000:
540 case 202000000:
541 budget = 2000;
542 break;
543 case 256250000:
544 case 262500000:
545 case 270000000:
546 case 272500000:
547 case 273750000:
548 case 280750000:
549 case 281250000:
550 case 286000000:
551 case 291750000:
552 budget = 4000;
553 break;
554 case 267250000:
555 case 268500000:
556 budget = 5000;
557 break;
558 default:
559 budget = 1000;
560 break;
561 }
562
563 return budget;
564}
565
566static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
567 unsigned r2, unsigned n2, unsigned p,
568 struct hsw_wrpll_rnp *best)
569{
570 uint64_t a, b, c, d, diff, diff_best;
571
572 /* No best (r,n,p) yet */
573 if (best->p == 0) {
574 best->p = p;
575 best->n2 = n2;
576 best->r2 = r2;
577 return;
578 }
579
580 /*
581 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
582 * freq2k.
583 *
584 * delta = 1e6 *
585 * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
586 * freq2k;
587 *
588 * and we would like delta <= budget.
589 *
590 * If the discrepancy is above the PPM-based budget, always prefer to
591 * improve upon the previous solution. However, if you're within the
592 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
593 */
594 a = freq2k * budget * p * r2;
595 b = freq2k * budget * best->p * best->r2;
596 diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
597 diff_best = abs_diff(freq2k * best->p * best->r2,
598 LC_FREQ_2K * best->n2);
599 c = 1000000 * diff;
600 d = 1000000 * diff_best;
601
602 if (a < c && b < d) {
603 /* If both are above the budget, pick the closer */
604 if (best->p * best->r2 * diff < p * r2 * diff_best) {
605 best->p = p;
606 best->n2 = n2;
607 best->r2 = r2;
608 }
609 } else if (a >= c && b < d) {
610 /* If A is below the threshold but B is above it? Update. */
611 best->p = p;
612 best->n2 = n2;
613 best->r2 = r2;
614 } else if (a >= c && b >= d) {
615 /* Both are below the limit, so pick the higher n2/(r2*r2) */
616 if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
617 best->p = p;
618 best->n2 = n2;
619 best->r2 = r2;
620 }
621 }
622 /* Otherwise a < c && b >= d, do nothing */
623}
624
625static void
626hsw_ddi_calculate_wrpll(int clock /* in Hz */,
627 unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
628{
629 uint64_t freq2k;
630 unsigned p, n2, r2;
631 struct hsw_wrpll_rnp best = { 0, 0, 0 };
632 unsigned budget;
633
634 freq2k = clock / 100;
635
636 budget = hsw_wrpll_get_budget_for_freq(clock);
637
638 /* Special case handling for 540 pixel clock: bypass WR PLL entirely
639 * and directly pass the LC PLL to it. */
640 if (freq2k == 5400000) {
641 *n2_out = 2;
642 *p_out = 1;
643 *r2_out = 2;
644 return;
645 }
646
647 /*
648 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
649 * the WR PLL.
650 *
651 * We want R so that REF_MIN <= Ref <= REF_MAX.
652 * Injecting R2 = 2 * R gives:
653 * REF_MAX * r2 > LC_FREQ * 2 and
654 * REF_MIN * r2 < LC_FREQ * 2
655 *
656 * Which means the desired boundaries for r2 are:
657 * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
658 *
659 */
660 for (r2 = LC_FREQ * 2 / REF_MAX + 1;
661 r2 <= LC_FREQ * 2 / REF_MIN;
662 r2++) {
663
664 /*
665 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
666 *
667 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
668 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
669 * VCO_MAX * r2 > n2 * LC_FREQ and
670 * VCO_MIN * r2 < n2 * LC_FREQ)
671 *
672 * Which means the desired boundaries for n2 are:
673 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
674 */
675 for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
676 n2 <= VCO_MAX * r2 / LC_FREQ;
677 n2++) {
678
679 for (p = P_MIN; p <= P_MAX; p += P_INC)
680 hsw_wrpll_update_rnp(freq2k, budget,
681 r2, n2, p, &best);
682 }
683 }
684
685 *n2_out = best.n2;
686 *p_out = best.p;
687 *r2_out = best.r2;
688}
689
Manasi Navare81b9fd82016-09-01 15:08:11 -0700690static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(int clock,
691 struct intel_crtc *crtc,
692 struct intel_crtc_state *crtc_state)
693{
694 struct intel_shared_dpll *pll;
695 uint32_t val;
696 unsigned int p, n2, r2;
697
698 hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
699
700 val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
701 WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
702 WRPLL_DIVIDER_POST(p);
703
704 crtc_state->dpll_hw_state.wrpll = val;
705
706 pll = intel_find_shared_dpll(crtc, crtc_state,
707 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
708
709 if (!pll)
710 return NULL;
711
712 return pll;
713}
714
715struct intel_shared_dpll *hsw_ddi_dp_get_dpll(struct intel_encoder *encoder,
716 int clock)
717{
718 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
719 struct intel_shared_dpll *pll;
720 enum intel_dpll_id pll_id;
721
722 switch (clock / 2) {
723 case 81000:
724 pll_id = DPLL_ID_LCPLL_810;
725 break;
726 case 135000:
727 pll_id = DPLL_ID_LCPLL_1350;
728 break;
729 case 270000:
730 pll_id = DPLL_ID_LCPLL_2700;
731 break;
732 default:
733 DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
734 return NULL;
735 }
736
737 pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
738
739 if (!pll)
740 return NULL;
741
742 return pll;
743}
744
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200745static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200746hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
747 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200748{
749 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200750 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200751
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200752 memset(&crtc_state->dpll_hw_state, 0,
753 sizeof(crtc_state->dpll_hw_state));
754
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200755 if (encoder->type == INTEL_OUTPUT_HDMI) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700756 pll = hsw_ddi_hdmi_get_dpll(clock, crtc, crtc_state);
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200757
Ville Syrjäläcca05022016-06-22 21:57:06 +0300758 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200759 encoder->type == INTEL_OUTPUT_DP_MST ||
760 encoder->type == INTEL_OUTPUT_EDP) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700761 pll = hsw_ddi_dp_get_dpll(encoder, clock);
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200762
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200763 } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
764 if (WARN_ON(crtc_state->port_clock / 2 != 135000))
765 return NULL;
766
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200767 crtc_state->dpll_hw_state.spll =
768 SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
769
770 pll = intel_find_shared_dpll(crtc, crtc_state,
771 DPLL_ID_SPLL, DPLL_ID_SPLL);
772 } else {
773 return NULL;
774 }
775
776 if (!pll)
777 return NULL;
778
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200779 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200780
781 return pll;
782}
783
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200784static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
785 .enable = hsw_ddi_wrpll_enable,
786 .disable = hsw_ddi_wrpll_disable,
787 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200788};
789
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200790static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
791 .enable = hsw_ddi_spll_enable,
792 .disable = hsw_ddi_spll_disable,
793 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200794};
795
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200796static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
797 struct intel_shared_dpll *pll)
798{
799}
800
801static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
802 struct intel_shared_dpll *pll)
803{
804}
805
806static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
807 struct intel_shared_dpll *pll,
808 struct intel_dpll_hw_state *hw_state)
809{
810 return true;
811}
812
813static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
814 .enable = hsw_ddi_lcpll_enable,
815 .disable = hsw_ddi_lcpll_disable,
816 .get_hw_state = hsw_ddi_lcpll_get_hw_state,
817};
818
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200819struct skl_dpll_regs {
820 i915_reg_t ctl, cfgcr1, cfgcr2;
821};
822
823/* this array is indexed by the *shared* pll id */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200824static const struct skl_dpll_regs skl_dpll_regs[4] = {
825 {
826 /* DPLL 0 */
827 .ctl = LCPLL1_CTL,
828 /* DPLL 0 doesn't support HDMI mode */
829 },
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200830 {
831 /* DPLL 1 */
832 .ctl = LCPLL2_CTL,
833 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
834 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
835 },
836 {
837 /* DPLL 2 */
838 .ctl = WRPLL_CTL(0),
839 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
840 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
841 },
842 {
843 /* DPLL 3 */
844 .ctl = WRPLL_CTL(1),
845 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
846 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
847 },
848};
849
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200850static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
851 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200852{
853 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200854
855 val = I915_READ(DPLL_CTRL1);
856
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200857 val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
858 DPLL_CTRL1_LINK_RATE_MASK(pll->id));
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200859 val |= pll->state.hw_state.ctrl1 << (pll->id * 6);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200860
861 I915_WRITE(DPLL_CTRL1, val);
862 POSTING_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200863}
864
865static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
866 struct intel_shared_dpll *pll)
867{
868 const struct skl_dpll_regs *regs = skl_dpll_regs;
869
870 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200871
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200872 I915_WRITE(regs[pll->id].cfgcr1, pll->state.hw_state.cfgcr1);
873 I915_WRITE(regs[pll->id].cfgcr2, pll->state.hw_state.cfgcr2);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200874 POSTING_READ(regs[pll->id].cfgcr1);
875 POSTING_READ(regs[pll->id].cfgcr2);
876
877 /* the enable bit is always bit 31 */
878 I915_WRITE(regs[pll->id].ctl,
879 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
880
Chris Wilson27bf23a2016-06-30 15:33:12 +0100881 if (intel_wait_for_register(dev_priv,
882 DPLL_STATUS,
883 DPLL_LOCK(pll->id),
884 DPLL_LOCK(pll->id),
885 5))
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200886 DRM_ERROR("DPLL %d not locked\n", pll->id);
887}
888
889static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
890 struct intel_shared_dpll *pll)
891{
892 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200893}
894
895static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
896 struct intel_shared_dpll *pll)
897{
898 const struct skl_dpll_regs *regs = skl_dpll_regs;
899
900 /* the enable bit is always bit 31 */
901 I915_WRITE(regs[pll->id].ctl,
902 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
903 POSTING_READ(regs[pll->id].ctl);
904}
905
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200906static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
907 struct intel_shared_dpll *pll)
908{
909}
910
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200911static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
912 struct intel_shared_dpll *pll,
913 struct intel_dpll_hw_state *hw_state)
914{
915 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200916 const struct skl_dpll_regs *regs = skl_dpll_regs;
917 bool ret;
918
919 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
920 return false;
921
922 ret = false;
923
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200924 val = I915_READ(regs[pll->id].ctl);
925 if (!(val & LCPLL_PLL_ENABLE))
926 goto out;
927
928 val = I915_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200929 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200930
931 /* avoid reading back stale values if HDMI mode is not enabled */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200932 if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200933 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
934 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
935 }
936 ret = true;
937
938out:
939 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
940
941 return ret;
942}
943
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200944static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
945 struct intel_shared_dpll *pll,
946 struct intel_dpll_hw_state *hw_state)
947{
948 uint32_t val;
949 const struct skl_dpll_regs *regs = skl_dpll_regs;
950 bool ret;
951
952 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
953 return false;
954
955 ret = false;
956
957 /* DPLL0 is always enabled since it drives CDCLK */
958 val = I915_READ(regs[pll->id].ctl);
959 if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
960 goto out;
961
962 val = I915_READ(DPLL_CTRL1);
963 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
964
965 ret = true;
966
967out:
968 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
969
970 return ret;
971}
972
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +0200973struct skl_wrpll_context {
974 uint64_t min_deviation; /* current minimal deviation */
975 uint64_t central_freq; /* chosen central freq */
976 uint64_t dco_freq; /* chosen dco freq */
977 unsigned int p; /* chosen divider */
978};
979
980static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
981{
982 memset(ctx, 0, sizeof(*ctx));
983
984 ctx->min_deviation = U64_MAX;
985}
986
987/* DCO freq must be within +1%/-6% of the DCO central freq */
988#define SKL_DCO_MAX_PDEVIATION 100
989#define SKL_DCO_MAX_NDEVIATION 600
990
991static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
992 uint64_t central_freq,
993 uint64_t dco_freq,
994 unsigned int divider)
995{
996 uint64_t deviation;
997
998 deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
999 central_freq);
1000
1001 /* positive deviation */
1002 if (dco_freq >= central_freq) {
1003 if (deviation < SKL_DCO_MAX_PDEVIATION &&
1004 deviation < ctx->min_deviation) {
1005 ctx->min_deviation = deviation;
1006 ctx->central_freq = central_freq;
1007 ctx->dco_freq = dco_freq;
1008 ctx->p = divider;
1009 }
1010 /* negative deviation */
1011 } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
1012 deviation < ctx->min_deviation) {
1013 ctx->min_deviation = deviation;
1014 ctx->central_freq = central_freq;
1015 ctx->dco_freq = dco_freq;
1016 ctx->p = divider;
1017 }
1018}
1019
1020static void skl_wrpll_get_multipliers(unsigned int p,
1021 unsigned int *p0 /* out */,
1022 unsigned int *p1 /* out */,
1023 unsigned int *p2 /* out */)
1024{
1025 /* even dividers */
1026 if (p % 2 == 0) {
1027 unsigned int half = p / 2;
1028
1029 if (half == 1 || half == 2 || half == 3 || half == 5) {
1030 *p0 = 2;
1031 *p1 = 1;
1032 *p2 = half;
1033 } else if (half % 2 == 0) {
1034 *p0 = 2;
1035 *p1 = half / 2;
1036 *p2 = 2;
1037 } else if (half % 3 == 0) {
1038 *p0 = 3;
1039 *p1 = half / 3;
1040 *p2 = 2;
1041 } else if (half % 7 == 0) {
1042 *p0 = 7;
1043 *p1 = half / 7;
1044 *p2 = 2;
1045 }
1046 } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
1047 *p0 = 3;
1048 *p1 = 1;
1049 *p2 = p / 3;
1050 } else if (p == 5 || p == 7) {
1051 *p0 = p;
1052 *p1 = 1;
1053 *p2 = 1;
1054 } else if (p == 15) {
1055 *p0 = 3;
1056 *p1 = 1;
1057 *p2 = 5;
1058 } else if (p == 21) {
1059 *p0 = 7;
1060 *p1 = 1;
1061 *p2 = 3;
1062 } else if (p == 35) {
1063 *p0 = 7;
1064 *p1 = 1;
1065 *p2 = 5;
1066 }
1067}
1068
1069struct skl_wrpll_params {
1070 uint32_t dco_fraction;
1071 uint32_t dco_integer;
1072 uint32_t qdiv_ratio;
1073 uint32_t qdiv_mode;
1074 uint32_t kdiv;
1075 uint32_t pdiv;
1076 uint32_t central_freq;
1077};
1078
1079static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
1080 uint64_t afe_clock,
1081 uint64_t central_freq,
1082 uint32_t p0, uint32_t p1, uint32_t p2)
1083{
1084 uint64_t dco_freq;
1085
1086 switch (central_freq) {
1087 case 9600000000ULL:
1088 params->central_freq = 0;
1089 break;
1090 case 9000000000ULL:
1091 params->central_freq = 1;
1092 break;
1093 case 8400000000ULL:
1094 params->central_freq = 3;
1095 }
1096
1097 switch (p0) {
1098 case 1:
1099 params->pdiv = 0;
1100 break;
1101 case 2:
1102 params->pdiv = 1;
1103 break;
1104 case 3:
1105 params->pdiv = 2;
1106 break;
1107 case 7:
1108 params->pdiv = 4;
1109 break;
1110 default:
1111 WARN(1, "Incorrect PDiv\n");
1112 }
1113
1114 switch (p2) {
1115 case 5:
1116 params->kdiv = 0;
1117 break;
1118 case 2:
1119 params->kdiv = 1;
1120 break;
1121 case 3:
1122 params->kdiv = 2;
1123 break;
1124 case 1:
1125 params->kdiv = 3;
1126 break;
1127 default:
1128 WARN(1, "Incorrect KDiv\n");
1129 }
1130
1131 params->qdiv_ratio = p1;
1132 params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1133
1134 dco_freq = p0 * p1 * p2 * afe_clock;
1135
1136 /*
1137 * Intermediate values are in Hz.
1138 * Divide by MHz to match bsepc
1139 */
1140 params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1141 params->dco_fraction =
1142 div_u64((div_u64(dco_freq, 24) -
1143 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1144}
1145
1146static bool
1147skl_ddi_calculate_wrpll(int clock /* in Hz */,
1148 struct skl_wrpll_params *wrpll_params)
1149{
1150 uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1151 uint64_t dco_central_freq[3] = {8400000000ULL,
1152 9000000000ULL,
1153 9600000000ULL};
1154 static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1155 24, 28, 30, 32, 36, 40, 42, 44,
1156 48, 52, 54, 56, 60, 64, 66, 68,
1157 70, 72, 76, 78, 80, 84, 88, 90,
1158 92, 96, 98 };
1159 static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1160 static const struct {
1161 const int *list;
1162 int n_dividers;
1163 } dividers[] = {
1164 { even_dividers, ARRAY_SIZE(even_dividers) },
1165 { odd_dividers, ARRAY_SIZE(odd_dividers) },
1166 };
1167 struct skl_wrpll_context ctx;
1168 unsigned int dco, d, i;
1169 unsigned int p0, p1, p2;
1170
1171 skl_wrpll_context_init(&ctx);
1172
1173 for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1174 for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1175 for (i = 0; i < dividers[d].n_dividers; i++) {
1176 unsigned int p = dividers[d].list[i];
1177 uint64_t dco_freq = p * afe_clock;
1178
1179 skl_wrpll_try_divider(&ctx,
1180 dco_central_freq[dco],
1181 dco_freq,
1182 p);
1183 /*
1184 * Skip the remaining dividers if we're sure to
1185 * have found the definitive divider, we can't
1186 * improve a 0 deviation.
1187 */
1188 if (ctx.min_deviation == 0)
1189 goto skip_remaining_dividers;
1190 }
1191 }
1192
1193skip_remaining_dividers:
1194 /*
1195 * If a solution is found with an even divider, prefer
1196 * this one.
1197 */
1198 if (d == 0 && ctx.p)
1199 break;
1200 }
1201
1202 if (!ctx.p) {
1203 DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1204 return false;
1205 }
1206
1207 /*
1208 * gcc incorrectly analyses that these can be used without being
1209 * initialized. To be fair, it's hard to guess.
1210 */
1211 p0 = p1 = p2 = 0;
1212 skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1213 skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1214 p0, p1, p2);
1215
1216 return true;
1217}
1218
Jim Bride9a4edad2016-09-01 15:08:10 -07001219static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
1220 struct intel_crtc_state *crtc_state,
1221 int clock)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001222{
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001223 uint32_t ctrl1, cfgcr1, cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001224 struct skl_wrpll_params wrpll_params = { 0, };
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001225
1226 /*
1227 * See comment in intel_dpll_hw_state to understand why we always use 0
1228 * as the DPLL id in this function.
1229 */
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001230 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1231
Jim Bride9a4edad2016-09-01 15:08:10 -07001232 ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001233
Jim Bride9a4edad2016-09-01 15:08:10 -07001234 if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
1235 return false;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001236
Jim Bride9a4edad2016-09-01 15:08:10 -07001237 cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1238 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1239 wrpll_params.dco_integer;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001240
Jim Bride9a4edad2016-09-01 15:08:10 -07001241 cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1242 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1243 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1244 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1245 wrpll_params.central_freq;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001246
1247 memset(&crtc_state->dpll_hw_state, 0,
1248 sizeof(crtc_state->dpll_hw_state));
1249
1250 crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1251 crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1252 crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001253 return true;
1254}
1255
1256
1257bool skl_ddi_dp_set_dpll_hw_state(int clock,
1258 struct intel_dpll_hw_state *dpll_hw_state)
1259{
1260 uint32_t ctrl1;
1261
1262 /*
1263 * See comment in intel_dpll_hw_state to understand why we always use 0
1264 * as the DPLL id in this function.
1265 */
1266 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1267 switch (clock / 2) {
1268 case 81000:
1269 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1270 break;
1271 case 135000:
1272 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1273 break;
1274 case 270000:
1275 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1276 break;
1277 /* eDP 1.4 rates */
1278 case 162000:
1279 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
1280 break;
1281 case 108000:
1282 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
1283 break;
1284 case 216000:
1285 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
1286 break;
1287 }
1288
1289 dpll_hw_state->ctrl1 = ctrl1;
1290 return true;
1291}
1292
1293static struct intel_shared_dpll *
1294skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1295 struct intel_encoder *encoder)
1296{
1297 struct intel_shared_dpll *pll;
1298 int clock = crtc_state->port_clock;
1299 bool bret;
1300 struct intel_dpll_hw_state dpll_hw_state;
1301
1302 memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
1303
1304 if (encoder->type == INTEL_OUTPUT_HDMI) {
1305 bret = skl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock);
1306 if (!bret) {
1307 DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n");
1308 return NULL;
1309 }
1310 } else if (encoder->type == INTEL_OUTPUT_DP ||
1311 encoder->type == INTEL_OUTPUT_DP_MST ||
1312 encoder->type == INTEL_OUTPUT_EDP) {
1313 bret = skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state);
1314 if (!bret) {
1315 DRM_DEBUG_KMS("Could not set DP dpll HW state.\n");
1316 return NULL;
1317 }
1318 crtc_state->dpll_hw_state = dpll_hw_state;
1319 } else {
1320 return NULL;
1321 }
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001322
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001323 if (encoder->type == INTEL_OUTPUT_EDP)
1324 pll = intel_find_shared_dpll(crtc, crtc_state,
1325 DPLL_ID_SKL_DPLL0,
1326 DPLL_ID_SKL_DPLL0);
1327 else
1328 pll = intel_find_shared_dpll(crtc, crtc_state,
1329 DPLL_ID_SKL_DPLL1,
1330 DPLL_ID_SKL_DPLL3);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001331 if (!pll)
1332 return NULL;
1333
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001334 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001335
1336 return pll;
1337}
1338
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001339static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1340 .enable = skl_ddi_pll_enable,
1341 .disable = skl_ddi_pll_disable,
1342 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001343};
1344
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001345static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
1346 .enable = skl_ddi_dpll0_enable,
1347 .disable = skl_ddi_dpll0_disable,
1348 .get_hw_state = skl_ddi_dpll0_get_hw_state,
1349};
1350
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001351static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1352 struct intel_shared_dpll *pll)
1353{
1354 uint32_t temp;
1355 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001356 enum dpio_phy phy;
1357 enum dpio_channel ch;
1358
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001359 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001360
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001361 /* Non-SSC reference */
Dongwon Kimda6110b2016-04-14 15:37:43 -07001362 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1363 temp |= PORT_PLL_REF_SEL;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001364 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1365
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001366 if (IS_GEMINILAKE(dev_priv)) {
1367 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1368 temp |= PORT_PLL_POWER_ENABLE;
1369 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1370
1371 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1372 PORT_PLL_POWER_STATE), 200))
1373 DRM_ERROR("Power state not set for PLL:%d\n", port);
1374 }
1375
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001376 /* Disable 10 bit clock */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001377 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001378 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001379 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001380
1381 /* Write P1 & P2 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001382 temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001383 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001384 temp |= pll->state.hw_state.ebb0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001385 I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001386
1387 /* Write M2 integer */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001388 temp = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001389 temp &= ~PORT_PLL_M2_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001390 temp |= pll->state.hw_state.pll0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001391 I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001392
1393 /* Write N */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001394 temp = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001395 temp &= ~PORT_PLL_N_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001396 temp |= pll->state.hw_state.pll1;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001397 I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001398
1399 /* Write M2 fraction */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001400 temp = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001401 temp &= ~PORT_PLL_M2_FRAC_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001402 temp |= pll->state.hw_state.pll2;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001403 I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001404
1405 /* Write M2 fraction enable */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001406 temp = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001407 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001408 temp |= pll->state.hw_state.pll3;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001409 I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001410
1411 /* Write coeff */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001412 temp = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001413 temp &= ~PORT_PLL_PROP_COEFF_MASK;
1414 temp &= ~PORT_PLL_INT_COEFF_MASK;
1415 temp &= ~PORT_PLL_GAIN_CTL_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001416 temp |= pll->state.hw_state.pll6;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001417 I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001418
1419 /* Write calibration val */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001420 temp = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001421 temp &= ~PORT_PLL_TARGET_CNT_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001422 temp |= pll->state.hw_state.pll8;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001423 I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001424
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001425 temp = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001426 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001427 temp |= pll->state.hw_state.pll9;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001428 I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001429
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001430 temp = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001431 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1432 temp &= ~PORT_PLL_DCO_AMP_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001433 temp |= pll->state.hw_state.pll10;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001434 I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001435
1436 /* Recalibrate with new settings */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001437 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001438 temp |= PORT_PLL_RECALIBRATE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001439 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001440 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001441 temp |= pll->state.hw_state.ebb4;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001442 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001443
1444 /* Enable PLL */
1445 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1446 temp |= PORT_PLL_ENABLE;
1447 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1448 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1449
Imre Deak0b786e42016-06-28 13:37:30 +03001450 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
1451 200))
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001452 DRM_ERROR("PLL %d not locked\n", port);
1453
Ander Conselvan de Oliveira51b3ee32016-12-02 10:23:52 +02001454 if (IS_GEMINILAKE(dev_priv)) {
1455 temp = I915_READ(BXT_PORT_TX_DW5_LN0(phy, ch));
1456 temp |= DCC_DELAY_RANGE_2;
1457 I915_WRITE(BXT_PORT_TX_DW5_GRP(phy, ch), temp);
1458 }
1459
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001460 /*
1461 * While we write to the group register to program all lanes at once we
1462 * can read only lane registers and we pick lanes 0/1 for that.
1463 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001464 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001465 temp &= ~LANE_STAGGER_MASK;
1466 temp &= ~LANESTAGGER_STRAP_OVRD;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001467 temp |= pll->state.hw_state.pcsdw12;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001468 I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001469}
1470
1471static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1472 struct intel_shared_dpll *pll)
1473{
1474 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1475 uint32_t temp;
1476
1477 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1478 temp &= ~PORT_PLL_ENABLE;
1479 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1480 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001481
1482 if (IS_GEMINILAKE(dev_priv)) {
1483 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1484 temp &= ~PORT_PLL_POWER_ENABLE;
1485 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1486
1487 if (wait_for_us(!(I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1488 PORT_PLL_POWER_STATE), 200))
1489 DRM_ERROR("Power state not reset for PLL:%d\n", port);
1490 }
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001491}
1492
1493static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1494 struct intel_shared_dpll *pll,
1495 struct intel_dpll_hw_state *hw_state)
1496{
1497 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1498 uint32_t val;
1499 bool ret;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001500 enum dpio_phy phy;
1501 enum dpio_channel ch;
1502
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001503 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001504
1505 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1506 return false;
1507
1508 ret = false;
1509
1510 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1511 if (!(val & PORT_PLL_ENABLE))
1512 goto out;
1513
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001514 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001515 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1516
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001517 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001518 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1519
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001520 hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001521 hw_state->pll0 &= PORT_PLL_M2_MASK;
1522
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001523 hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001524 hw_state->pll1 &= PORT_PLL_N_MASK;
1525
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001526 hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001527 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1528
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001529 hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001530 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1531
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001532 hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001533 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1534 PORT_PLL_INT_COEFF_MASK |
1535 PORT_PLL_GAIN_CTL_MASK;
1536
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001537 hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001538 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1539
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001540 hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001541 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1542
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001543 hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001544 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1545 PORT_PLL_DCO_AMP_MASK;
1546
1547 /*
1548 * While we write to the group register to program all lanes at once we
1549 * can read only lane registers. We configure all lanes the same way, so
1550 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1551 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001552 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
1553 if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001554 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1555 hw_state->pcsdw12,
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001556 I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001557 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1558
1559 ret = true;
1560
1561out:
1562 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1563
1564 return ret;
1565}
1566
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001567/* bxt clock parameters */
1568struct bxt_clk_div {
1569 int clock;
1570 uint32_t p1;
1571 uint32_t p2;
1572 uint32_t m2_int;
1573 uint32_t m2_frac;
1574 bool m2_frac_en;
1575 uint32_t n;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001576
1577 int vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001578};
1579
1580/* pre-calculated values for DP linkrates */
1581static const struct bxt_clk_div bxt_dp_clk_val[] = {
1582 {162000, 4, 2, 32, 1677722, 1, 1},
1583 {270000, 4, 1, 27, 0, 0, 1},
1584 {540000, 2, 1, 27, 0, 0, 1},
1585 {216000, 3, 2, 32, 1677722, 1, 1},
1586 {243000, 4, 1, 24, 1258291, 1, 1},
1587 {324000, 4, 1, 32, 1677722, 1, 1},
1588 {432000, 3, 1, 32, 1677722, 1, 1}
1589};
1590
Durgadoss Ra277ca72016-09-01 15:08:09 -07001591static bool
1592bxt_ddi_hdmi_pll_dividers(struct intel_crtc *intel_crtc,
1593 struct intel_crtc_state *crtc_state, int clock,
1594 struct bxt_clk_div *clk_div)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001595{
Durgadoss Ra277ca72016-09-01 15:08:09 -07001596 struct dpll best_clock;
1597
1598 /* Calculate HDMI div */
1599 /*
1600 * FIXME: tie the following calculation into
1601 * i9xx_crtc_compute_clock
1602 */
1603 if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
1604 DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1605 clock, pipe_name(intel_crtc->pipe));
1606 return false;
1607 }
1608
1609 clk_div->p1 = best_clock.p1;
1610 clk_div->p2 = best_clock.p2;
1611 WARN_ON(best_clock.m1 != 2);
1612 clk_div->n = best_clock.n;
1613 clk_div->m2_int = best_clock.m2 >> 22;
1614 clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
1615 clk_div->m2_frac_en = clk_div->m2_frac != 0;
1616
1617 clk_div->vco = best_clock.vco;
1618
1619 return true;
1620}
1621
1622static void bxt_ddi_dp_pll_dividers(int clock, struct bxt_clk_div *clk_div)
1623{
1624 int i;
1625
1626 *clk_div = bxt_dp_clk_val[0];
1627 for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1628 if (bxt_dp_clk_val[i].clock == clock) {
1629 *clk_div = bxt_dp_clk_val[i];
1630 break;
1631 }
1632 }
1633
1634 clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
1635}
1636
1637static bool bxt_ddi_set_dpll_hw_state(int clock,
1638 struct bxt_clk_div *clk_div,
1639 struct intel_dpll_hw_state *dpll_hw_state)
1640{
1641 int vco = clk_div->vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001642 uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
1643 uint32_t lanestagger;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001644
1645 if (vco >= 6200000 && vco <= 6700000) {
1646 prop_coef = 4;
1647 int_coef = 9;
1648 gain_ctl = 3;
1649 targ_cnt = 8;
1650 } else if ((vco > 5400000 && vco < 6200000) ||
1651 (vco >= 4800000 && vco < 5400000)) {
1652 prop_coef = 5;
1653 int_coef = 11;
1654 gain_ctl = 3;
1655 targ_cnt = 9;
1656 } else if (vco == 5400000) {
1657 prop_coef = 3;
1658 int_coef = 8;
1659 gain_ctl = 1;
1660 targ_cnt = 9;
1661 } else {
1662 DRM_ERROR("Invalid VCO\n");
Durgadoss Ra277ca72016-09-01 15:08:09 -07001663 return false;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001664 }
1665
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001666 if (clock > 270000)
1667 lanestagger = 0x18;
1668 else if (clock > 135000)
1669 lanestagger = 0x0d;
1670 else if (clock > 67000)
1671 lanestagger = 0x07;
1672 else if (clock > 33000)
1673 lanestagger = 0x04;
1674 else
1675 lanestagger = 0x02;
1676
Durgadoss Ra277ca72016-09-01 15:08:09 -07001677 dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
1678 dpll_hw_state->pll0 = clk_div->m2_int;
1679 dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
1680 dpll_hw_state->pll2 = clk_div->m2_frac;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001681
Durgadoss Ra277ca72016-09-01 15:08:09 -07001682 if (clk_div->m2_frac_en)
1683 dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001684
Durgadoss Ra277ca72016-09-01 15:08:09 -07001685 dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
1686 dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001687
Durgadoss Ra277ca72016-09-01 15:08:09 -07001688 dpll_hw_state->pll8 = targ_cnt;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001689
Durgadoss Ra277ca72016-09-01 15:08:09 -07001690 dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001691
Durgadoss Ra277ca72016-09-01 15:08:09 -07001692 dpll_hw_state->pll10 =
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001693 PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1694 | PORT_PLL_DCO_AMP_OVR_EN_H;
1695
Durgadoss Ra277ca72016-09-01 15:08:09 -07001696 dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001697
Durgadoss Ra277ca72016-09-01 15:08:09 -07001698 dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger;
1699
1700 return true;
1701}
1702
1703bool bxt_ddi_dp_set_dpll_hw_state(int clock,
1704 struct intel_dpll_hw_state *dpll_hw_state)
1705{
1706 struct bxt_clk_div clk_div = {0};
1707
1708 bxt_ddi_dp_pll_dividers(clock, &clk_div);
1709
1710 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1711}
1712
Imre Deaka04139c2016-09-26 17:54:31 +03001713static bool
1714bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc *intel_crtc,
1715 struct intel_crtc_state *crtc_state, int clock,
1716 struct intel_dpll_hw_state *dpll_hw_state)
1717{
1718 struct bxt_clk_div clk_div = { };
1719
1720 bxt_ddi_hdmi_pll_dividers(intel_crtc, crtc_state, clock, &clk_div);
1721
1722 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1723}
1724
Durgadoss Ra277ca72016-09-01 15:08:09 -07001725static struct intel_shared_dpll *
1726bxt_get_dpll(struct intel_crtc *crtc,
1727 struct intel_crtc_state *crtc_state,
1728 struct intel_encoder *encoder)
1729{
Imre Deaka04139c2016-09-26 17:54:31 +03001730 struct intel_dpll_hw_state dpll_hw_state = { };
Durgadoss Ra277ca72016-09-01 15:08:09 -07001731 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1732 struct intel_digital_port *intel_dig_port;
1733 struct intel_shared_dpll *pll;
1734 int i, clock = crtc_state->port_clock;
1735
Imre Deaka04139c2016-09-26 17:54:31 +03001736 if (encoder->type == INTEL_OUTPUT_HDMI &&
1737 !bxt_ddi_hdmi_set_dpll_hw_state(crtc, crtc_state, clock,
1738 &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001739 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001740
1741 if ((encoder->type == INTEL_OUTPUT_DP ||
1742 encoder->type == INTEL_OUTPUT_EDP) &&
1743 !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001744 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001745
1746 memset(&crtc_state->dpll_hw_state, 0,
1747 sizeof(crtc_state->dpll_hw_state));
1748
1749 crtc_state->dpll_hw_state = dpll_hw_state;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001750
Maarten Lankhorsta79e8cc2016-08-09 17:04:00 +02001751 if (encoder->type == INTEL_OUTPUT_DP_MST) {
1752 struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
1753
1754 intel_dig_port = intel_mst->primary;
1755 } else
1756 intel_dig_port = enc_to_dig_port(&encoder->base);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001757
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001758 /* 1:1 mapping between ports and PLLs */
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001759 i = (enum intel_dpll_id) intel_dig_port->port;
1760 pll = intel_get_shared_dpll_by_id(dev_priv, i);
1761
Ville Syrjälä78108b72016-05-27 20:59:19 +03001762 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
1763 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001764
1765 intel_reference_shared_dpll(pll, crtc_state);
1766
1767 return pll;
1768}
1769
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001770static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1771 .enable = bxt_ddi_pll_enable,
1772 .disable = bxt_ddi_pll_disable,
1773 .get_hw_state = bxt_ddi_pll_get_hw_state,
1774};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001775
1776static void intel_ddi_pll_init(struct drm_device *dev)
1777{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001778 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001779
Ville Syrjälä9f7eb312016-05-13 23:41:29 +03001780 if (INTEL_GEN(dev_priv) < 9) {
1781 uint32_t val = I915_READ(LCPLL_CTL);
Ville Syrjäläb2045352016-05-13 23:41:27 +03001782
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001783 /*
1784 * The LCPLL register should be turned on by the BIOS. For now
1785 * let's just check its state and print errors in case
1786 * something is wrong. Don't even try to turn it on.
1787 */
1788
1789 if (val & LCPLL_CD_SOURCE_FCLK)
1790 DRM_ERROR("CDCLK source is not LCPLL\n");
1791
1792 if (val & LCPLL_PLL_DISABLE)
1793 DRM_ERROR("LCPLL is disabled\n");
1794 }
1795}
1796
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001797struct dpll_info {
1798 const char *name;
1799 const int id;
1800 const struct intel_shared_dpll_funcs *funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001801 uint32_t flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001802};
1803
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001804struct intel_dpll_mgr {
1805 const struct dpll_info *dpll_info;
1806
1807 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001808 struct intel_crtc_state *crtc_state,
1809 struct intel_encoder *encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001810};
1811
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001812static const struct dpll_info pch_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001813 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
1814 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
1815 { NULL, -1, NULL, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001816};
1817
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001818static const struct intel_dpll_mgr pch_pll_mgr = {
1819 .dpll_info = pch_plls,
1820 .get_dpll = ibx_get_dpll,
1821};
1822
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001823static const struct dpll_info hsw_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001824 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 },
1825 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 },
1826 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 },
1827 { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1828 { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1829 { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001830 { NULL, -1, NULL, },
1831};
1832
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001833static const struct intel_dpll_mgr hsw_pll_mgr = {
1834 .dpll_info = hsw_plls,
1835 .get_dpll = hsw_get_dpll,
1836};
1837
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001838static const struct dpll_info skl_plls[] = {
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001839 { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
Ville Syrjäläd5aab9d2016-05-11 22:04:33 +03001840 { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
1841 { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
1842 { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001843 { NULL, -1, NULL, },
1844};
1845
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001846static const struct intel_dpll_mgr skl_pll_mgr = {
1847 .dpll_info = skl_plls,
1848 .get_dpll = skl_get_dpll,
1849};
1850
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001851static const struct dpll_info bxt_plls[] = {
Imre Deak08250c42016-03-14 19:55:34 +02001852 { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
1853 { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
1854 { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001855 { NULL, -1, NULL, },
1856};
1857
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001858static const struct intel_dpll_mgr bxt_pll_mgr = {
1859 .dpll_info = bxt_plls,
1860 .get_dpll = bxt_get_dpll,
1861};
1862
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001863void intel_shared_dpll_init(struct drm_device *dev)
1864{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001865 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001866 const struct intel_dpll_mgr *dpll_mgr = NULL;
1867 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001868 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001869
Tvrtko Ursulin08537232016-10-13 11:03:02 +01001870 if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001871 dpll_mgr = &skl_pll_mgr;
Ander Conselvan de Oliveiracc3f90f2016-12-02 10:23:49 +02001872 else if (IS_GEN9_LP(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001873 dpll_mgr = &bxt_pll_mgr;
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01001874 else if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001875 dpll_mgr = &hsw_pll_mgr;
Tvrtko Ursulin6e266952016-10-13 11:02:53 +01001876 else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001877 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001878
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001879 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001880 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001881 return;
1882 }
1883
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001884 dpll_info = dpll_mgr->dpll_info;
1885
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001886 for (i = 0; dpll_info[i].id >= 0; i++) {
1887 WARN_ON(i != dpll_info[i].id);
1888
1889 dev_priv->shared_dplls[i].id = dpll_info[i].id;
1890 dev_priv->shared_dplls[i].name = dpll_info[i].name;
1891 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001892 dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001893 }
1894
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001895 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001896 dev_priv->num_shared_dpll = i;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +01001897 mutex_init(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001898
1899 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001900
1901 /* FIXME: Move this to a more suitable place */
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01001902 if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001903 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001904}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001905
1906struct intel_shared_dpll *
1907intel_get_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001908 struct intel_crtc_state *crtc_state,
1909 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001910{
1911 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1912 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
1913
1914 if (WARN_ON(!dpll_mgr))
1915 return NULL;
1916
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001917 return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001918}
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02001919
1920/**
1921 * intel_release_shared_dpll - end use of DPLL by CRTC in atomic state
1922 * @dpll: dpll in use by @crtc
1923 * @crtc: crtc
1924 * @state: atomic state
1925 *
1926 */
1927void intel_release_shared_dpll(struct intel_shared_dpll *dpll,
1928 struct intel_crtc *crtc,
1929 struct drm_atomic_state *state)
1930{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001931 struct intel_shared_dpll_state *shared_dpll_state;
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02001932
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001933 shared_dpll_state = intel_atomic_get_shared_dpll_state(state);
1934 shared_dpll_state[dpll->id].crtc_mask &= ~(1 << crtc->pipe);
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02001935}