blob: 655a5b382cf96c29f800cd7640a74144c618911f [file] [log] [blame]
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001/*
2 * Copyright © 2006-2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "intel_drv.h"
25
26struct intel_shared_dpll *
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020027intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
28 enum intel_dpll_id id)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020029{
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020030 return &dev_priv->shared_dplls[id];
31}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020032
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020033enum intel_dpll_id
34intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
35 struct intel_shared_dpll *pll)
36{
37 if (WARN_ON(pll < dev_priv->shared_dplls||
38 pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll]))
39 return -1;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020040
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020041 return (enum intel_dpll_id) (pll - dev_priv->shared_dplls);
42}
43
44void
45intel_shared_dpll_config_get(struct intel_shared_dpll_config *config,
46 struct intel_shared_dpll *pll,
47 struct intel_crtc *crtc)
48{
49 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
50 enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
51
52 config[id].crtc_mask |= 1 << crtc->pipe;
53}
54
55void
56intel_shared_dpll_config_put(struct intel_shared_dpll_config *config,
57 struct intel_shared_dpll *pll,
58 struct intel_crtc *crtc)
59{
60 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
61 enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
62
63 config[id].crtc_mask &= ~(1 << crtc->pipe);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020064}
65
66/* For ILK+ */
67void assert_shared_dpll(struct drm_i915_private *dev_priv,
68 struct intel_shared_dpll *pll,
69 bool state)
70{
71 bool cur_state;
72 struct intel_dpll_hw_state hw_state;
73
74 if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
75 return;
76
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +020077 cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020078 I915_STATE_WARN(cur_state != state,
79 "%s assertion failure (expected %s, current %s)\n",
80 pll->name, onoff(state), onoff(cur_state));
81}
82
83void intel_prepare_shared_dpll(struct intel_crtc *crtc)
84{
85 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +010086 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020087 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020088
89 if (WARN_ON(pll == NULL))
90 return;
91
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +010092 mutex_lock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020093 WARN_ON(!pll->config.crtc_mask);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +010094 if (!pll->active_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020095 DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
96 WARN_ON(pll->on);
97 assert_shared_dpll_disabled(dev_priv, pll);
98
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +020099 pll->funcs.mode_set(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200100 }
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100101 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200102}
103
104/**
105 * intel_enable_shared_dpll - enable PCH PLL
106 * @dev_priv: i915 private structure
107 * @pipe: pipe PLL to enable
108 *
109 * The PCH PLL needs to be enabled before the PCH transcoder, since it
110 * drives the transcoder clock.
111 */
112void intel_enable_shared_dpll(struct intel_crtc *crtc)
113{
114 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100115 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200116 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100117 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100118 unsigned old_mask;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200119
120 if (WARN_ON(pll == NULL))
121 return;
122
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100123 mutex_lock(&dev_priv->dpll_lock);
124 old_mask = pll->active_mask;
125
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100126 if (WARN_ON(!(pll->config.crtc_mask & crtc_mask)) ||
127 WARN_ON(pll->active_mask & crtc_mask))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100128 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200129
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100130 pll->active_mask |= crtc_mask;
131
132 DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n",
133 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200134 crtc->base.base.id);
135
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100136 if (old_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200137 WARN_ON(!pll->on);
138 assert_shared_dpll_enabled(dev_priv, pll);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100139 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200140 }
141 WARN_ON(pll->on);
142
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200143 DRM_DEBUG_KMS("enabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200144 pll->funcs.enable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200145 pll->on = true;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100146
147out:
148 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200149}
150
151void intel_disable_shared_dpll(struct intel_crtc *crtc)
152{
153 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100154 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200155 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100156 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200157
158 /* PCH only available on ILK+ */
159 if (INTEL_INFO(dev)->gen < 5)
160 return;
161
162 if (pll == NULL)
163 return;
164
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100165 mutex_lock(&dev_priv->dpll_lock);
Maarten Lankhorsta1475e72016-03-14 09:27:53 +0100166 if (WARN_ON(!(pll->active_mask & crtc_mask)))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100167 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200168
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100169 DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
170 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200171 crtc->base.base.id);
172
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200173 assert_shared_dpll_enabled(dev_priv, pll);
174 WARN_ON(!pll->on);
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100175
176 pll->active_mask &= ~crtc_mask;
177 if (pll->active_mask)
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100178 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200179
180 DRM_DEBUG_KMS("disabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200181 pll->funcs.disable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200182 pll->on = false;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100183
184out:
185 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200186}
187
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200188static struct intel_shared_dpll *
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200189intel_find_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200190 struct intel_crtc_state *crtc_state,
191 enum intel_dpll_id range_min,
192 enum intel_dpll_id range_max)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200193{
Chris Wilsonfac5e232016-07-04 11:34:36 +0100194 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200195 struct intel_shared_dpll *pll;
196 struct intel_shared_dpll_config *shared_dpll;
197 enum intel_dpll_id i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200198
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200199 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
200
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200201 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200202 pll = &dev_priv->shared_dplls[i];
203
204 /* Only want to check enabled timings first */
205 if (shared_dpll[i].crtc_mask == 0)
206 continue;
207
208 if (memcmp(&crtc_state->dpll_hw_state,
209 &shared_dpll[i].hw_state,
210 sizeof(crtc_state->dpll_hw_state)) == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300211 DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
212 crtc->base.base.id, crtc->base.name, pll->name,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200213 shared_dpll[i].crtc_mask,
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100214 pll->active_mask);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200215 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200216 }
217 }
218
219 /* Ok no matching timings, maybe there's a free one? */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200220 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200221 pll = &dev_priv->shared_dplls[i];
222 if (shared_dpll[i].crtc_mask == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300223 DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n",
224 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200225 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200226 }
227 }
228
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200229 return NULL;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200230}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200231
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200232static void
233intel_reference_shared_dpll(struct intel_shared_dpll *pll,
234 struct intel_crtc_state *crtc_state)
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200235{
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200236 struct intel_shared_dpll_config *shared_dpll;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200237 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
238 enum intel_dpll_id i = pll->id;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200239
240 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
241
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200242 if (shared_dpll[i].crtc_mask == 0)
243 shared_dpll[i].hw_state =
244 crtc_state->dpll_hw_state;
245
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200246 crtc_state->shared_dpll = pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200247 DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
248 pipe_name(crtc->pipe));
249
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200250 intel_shared_dpll_config_get(shared_dpll, pll, crtc);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200251}
252
253void intel_shared_dpll_commit(struct drm_atomic_state *state)
254{
255 struct drm_i915_private *dev_priv = to_i915(state->dev);
256 struct intel_shared_dpll_config *shared_dpll;
257 struct intel_shared_dpll *pll;
258 enum intel_dpll_id i;
259
260 if (!to_intel_atomic_state(state)->dpll_set)
261 return;
262
263 shared_dpll = to_intel_atomic_state(state)->shared_dpll;
264 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
265 pll = &dev_priv->shared_dplls[i];
266 pll->config = shared_dpll[i];
267 }
268}
269
270static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
271 struct intel_shared_dpll *pll,
272 struct intel_dpll_hw_state *hw_state)
273{
274 uint32_t val;
275
276 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
277 return false;
278
279 val = I915_READ(PCH_DPLL(pll->id));
280 hw_state->dpll = val;
281 hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
282 hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
283
284 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
285
286 return val & DPLL_VCO_ENABLE;
287}
288
289static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
290 struct intel_shared_dpll *pll)
291{
292 I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
293 I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
294}
295
296static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
297{
298 u32 val;
299 bool enabled;
300
Joonas Lahtinen2d1fe072016-04-07 11:08:05 +0300301 I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200302
303 val = I915_READ(PCH_DREF_CONTROL);
304 enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
305 DREF_SUPERSPREAD_SOURCE_MASK));
306 I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
307}
308
309static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
310 struct intel_shared_dpll *pll)
311{
312 /* PCH refclock must be enabled first */
313 ibx_assert_pch_refclk_enabled(dev_priv);
314
315 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
316
317 /* Wait for the clocks to stabilize. */
318 POSTING_READ(PCH_DPLL(pll->id));
319 udelay(150);
320
321 /* The pixel multiplier can only be updated once the
322 * DPLL is enabled and the clocks are stable.
323 *
324 * So write it again.
325 */
326 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
327 POSTING_READ(PCH_DPLL(pll->id));
328 udelay(200);
329}
330
331static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
332 struct intel_shared_dpll *pll)
333{
Chris Wilson91c8a322016-07-05 10:40:23 +0100334 struct drm_device *dev = &dev_priv->drm;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200335 struct intel_crtc *crtc;
336
337 /* Make sure no transcoder isn't still depending on us. */
338 for_each_intel_crtc(dev, crtc) {
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200339 if (crtc->config->shared_dpll == pll)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200340 assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
341 }
342
343 I915_WRITE(PCH_DPLL(pll->id), 0);
344 POSTING_READ(PCH_DPLL(pll->id));
345 udelay(200);
346}
347
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200348static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200349ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
350 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200351{
352 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
353 struct intel_shared_dpll *pll;
354 enum intel_dpll_id i;
355
356 if (HAS_PCH_IBX(dev_priv)) {
357 /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
358 i = (enum intel_dpll_id) crtc->pipe;
359 pll = &dev_priv->shared_dplls[i];
360
Ville Syrjälä78108b72016-05-27 20:59:19 +0300361 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
362 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200363 } else {
364 pll = intel_find_shared_dpll(crtc, crtc_state,
365 DPLL_ID_PCH_PLL_A,
366 DPLL_ID_PCH_PLL_B);
367 }
368
Ander Conselvan de Oliveirabb143162016-05-20 15:47:06 +0300369 if (!pll)
370 return NULL;
371
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200372 /* reference the pll */
373 intel_reference_shared_dpll(pll, crtc_state);
374
375 return pll;
376}
377
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200378static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
379 .mode_set = ibx_pch_dpll_mode_set,
380 .enable = ibx_pch_dpll_enable,
381 .disable = ibx_pch_dpll_disable,
382 .get_hw_state = ibx_pch_dpll_get_hw_state,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200383};
384
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200385static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
386 struct intel_shared_dpll *pll)
387{
388 I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
389 POSTING_READ(WRPLL_CTL(pll->id));
390 udelay(20);
391}
392
393static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
394 struct intel_shared_dpll *pll)
395{
396 I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
397 POSTING_READ(SPLL_CTL);
398 udelay(20);
399}
400
401static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
402 struct intel_shared_dpll *pll)
403{
404 uint32_t val;
405
406 val = I915_READ(WRPLL_CTL(pll->id));
407 I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
408 POSTING_READ(WRPLL_CTL(pll->id));
409}
410
411static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
412 struct intel_shared_dpll *pll)
413{
414 uint32_t val;
415
416 val = I915_READ(SPLL_CTL);
417 I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
418 POSTING_READ(SPLL_CTL);
419}
420
421static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
422 struct intel_shared_dpll *pll,
423 struct intel_dpll_hw_state *hw_state)
424{
425 uint32_t val;
426
427 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
428 return false;
429
430 val = I915_READ(WRPLL_CTL(pll->id));
431 hw_state->wrpll = val;
432
433 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
434
435 return val & WRPLL_PLL_ENABLE;
436}
437
438static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
439 struct intel_shared_dpll *pll,
440 struct intel_dpll_hw_state *hw_state)
441{
442 uint32_t val;
443
444 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
445 return false;
446
447 val = I915_READ(SPLL_CTL);
448 hw_state->spll = val;
449
450 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
451
452 return val & SPLL_PLL_ENABLE;
453}
454
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200455static uint32_t hsw_pll_to_ddi_pll_sel(struct intel_shared_dpll *pll)
456{
457 switch (pll->id) {
458 case DPLL_ID_WRPLL1:
459 return PORT_CLK_SEL_WRPLL1;
460 case DPLL_ID_WRPLL2:
461 return PORT_CLK_SEL_WRPLL2;
462 case DPLL_ID_SPLL:
463 return PORT_CLK_SEL_SPLL;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200464 case DPLL_ID_LCPLL_810:
465 return PORT_CLK_SEL_LCPLL_810;
466 case DPLL_ID_LCPLL_1350:
467 return PORT_CLK_SEL_LCPLL_1350;
468 case DPLL_ID_LCPLL_2700:
469 return PORT_CLK_SEL_LCPLL_2700;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200470 default:
471 return PORT_CLK_SEL_NONE;
472 }
473}
474
475#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
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200690static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200691hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
692 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200693{
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200694 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200695 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200696 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200697
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200698 memset(&crtc_state->dpll_hw_state, 0,
699 sizeof(crtc_state->dpll_hw_state));
700
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200701 if (encoder->type == INTEL_OUTPUT_HDMI) {
702 uint32_t val;
703 unsigned p, n2, r2;
704
705 hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
706
707 val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
708 WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
709 WRPLL_DIVIDER_POST(p);
710
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200711 crtc_state->dpll_hw_state.wrpll = val;
712
713 pll = intel_find_shared_dpll(crtc, crtc_state,
714 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
715
Ville Syrjäläcca05022016-06-22 21:57:06 +0300716 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200717 encoder->type == INTEL_OUTPUT_DP_MST ||
718 encoder->type == INTEL_OUTPUT_EDP) {
719 enum intel_dpll_id pll_id;
720
721 switch (clock / 2) {
722 case 81000:
723 pll_id = DPLL_ID_LCPLL_810;
724 break;
725 case 135000:
726 pll_id = DPLL_ID_LCPLL_1350;
727 break;
728 case 270000:
729 pll_id = DPLL_ID_LCPLL_2700;
730 break;
731 default:
732 DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
733 return NULL;
734 }
735
736 pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
737
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200738 } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
739 if (WARN_ON(crtc_state->port_clock / 2 != 135000))
740 return NULL;
741
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200742 crtc_state->dpll_hw_state.spll =
743 SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
744
745 pll = intel_find_shared_dpll(crtc, crtc_state,
746 DPLL_ID_SPLL, DPLL_ID_SPLL);
747 } else {
748 return NULL;
749 }
750
751 if (!pll)
752 return NULL;
753
754 crtc_state->ddi_pll_sel = hsw_pll_to_ddi_pll_sel(pll);
755
756 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200757
758 return pll;
759}
760
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200761
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200762static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
763 .enable = hsw_ddi_wrpll_enable,
764 .disable = hsw_ddi_wrpll_disable,
765 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200766};
767
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200768static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
769 .enable = hsw_ddi_spll_enable,
770 .disable = hsw_ddi_spll_disable,
771 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200772};
773
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200774static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
775 struct intel_shared_dpll *pll)
776{
777}
778
779static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
780 struct intel_shared_dpll *pll)
781{
782}
783
784static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
785 struct intel_shared_dpll *pll,
786 struct intel_dpll_hw_state *hw_state)
787{
788 return true;
789}
790
791static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
792 .enable = hsw_ddi_lcpll_enable,
793 .disable = hsw_ddi_lcpll_disable,
794 .get_hw_state = hsw_ddi_lcpll_get_hw_state,
795};
796
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200797struct skl_dpll_regs {
798 i915_reg_t ctl, cfgcr1, cfgcr2;
799};
800
801/* this array is indexed by the *shared* pll id */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200802static const struct skl_dpll_regs skl_dpll_regs[4] = {
803 {
804 /* DPLL 0 */
805 .ctl = LCPLL1_CTL,
806 /* DPLL 0 doesn't support HDMI mode */
807 },
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200808 {
809 /* DPLL 1 */
810 .ctl = LCPLL2_CTL,
811 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
812 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
813 },
814 {
815 /* DPLL 2 */
816 .ctl = WRPLL_CTL(0),
817 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
818 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
819 },
820 {
821 /* DPLL 3 */
822 .ctl = WRPLL_CTL(1),
823 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
824 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
825 },
826};
827
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200828static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
829 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200830{
831 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200832
833 val = I915_READ(DPLL_CTRL1);
834
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200835 val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
836 DPLL_CTRL1_LINK_RATE_MASK(pll->id));
837 val |= pll->config.hw_state.ctrl1 << (pll->id * 6);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200838
839 I915_WRITE(DPLL_CTRL1, val);
840 POSTING_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200841}
842
843static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
844 struct intel_shared_dpll *pll)
845{
846 const struct skl_dpll_regs *regs = skl_dpll_regs;
847
848 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200849
850 I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
851 I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
852 POSTING_READ(regs[pll->id].cfgcr1);
853 POSTING_READ(regs[pll->id].cfgcr2);
854
855 /* the enable bit is always bit 31 */
856 I915_WRITE(regs[pll->id].ctl,
857 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
858
Chris Wilson27bf23a2016-06-30 15:33:12 +0100859 if (intel_wait_for_register(dev_priv,
860 DPLL_STATUS,
861 DPLL_LOCK(pll->id),
862 DPLL_LOCK(pll->id),
863 5))
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200864 DRM_ERROR("DPLL %d not locked\n", pll->id);
865}
866
867static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
868 struct intel_shared_dpll *pll)
869{
870 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200871}
872
873static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
874 struct intel_shared_dpll *pll)
875{
876 const struct skl_dpll_regs *regs = skl_dpll_regs;
877
878 /* the enable bit is always bit 31 */
879 I915_WRITE(regs[pll->id].ctl,
880 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
881 POSTING_READ(regs[pll->id].ctl);
882}
883
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200884static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
885 struct intel_shared_dpll *pll)
886{
887}
888
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200889static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
890 struct intel_shared_dpll *pll,
891 struct intel_dpll_hw_state *hw_state)
892{
893 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200894 const struct skl_dpll_regs *regs = skl_dpll_regs;
895 bool ret;
896
897 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
898 return false;
899
900 ret = false;
901
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200902 val = I915_READ(regs[pll->id].ctl);
903 if (!(val & LCPLL_PLL_ENABLE))
904 goto out;
905
906 val = I915_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200907 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200908
909 /* avoid reading back stale values if HDMI mode is not enabled */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200910 if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200911 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
912 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
913 }
914 ret = true;
915
916out:
917 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
918
919 return ret;
920}
921
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200922static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
923 struct intel_shared_dpll *pll,
924 struct intel_dpll_hw_state *hw_state)
925{
926 uint32_t val;
927 const struct skl_dpll_regs *regs = skl_dpll_regs;
928 bool ret;
929
930 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
931 return false;
932
933 ret = false;
934
935 /* DPLL0 is always enabled since it drives CDCLK */
936 val = I915_READ(regs[pll->id].ctl);
937 if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
938 goto out;
939
940 val = I915_READ(DPLL_CTRL1);
941 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
942
943 ret = true;
944
945out:
946 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
947
948 return ret;
949}
950
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +0200951struct skl_wrpll_context {
952 uint64_t min_deviation; /* current minimal deviation */
953 uint64_t central_freq; /* chosen central freq */
954 uint64_t dco_freq; /* chosen dco freq */
955 unsigned int p; /* chosen divider */
956};
957
958static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
959{
960 memset(ctx, 0, sizeof(*ctx));
961
962 ctx->min_deviation = U64_MAX;
963}
964
965/* DCO freq must be within +1%/-6% of the DCO central freq */
966#define SKL_DCO_MAX_PDEVIATION 100
967#define SKL_DCO_MAX_NDEVIATION 600
968
969static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
970 uint64_t central_freq,
971 uint64_t dco_freq,
972 unsigned int divider)
973{
974 uint64_t deviation;
975
976 deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
977 central_freq);
978
979 /* positive deviation */
980 if (dco_freq >= central_freq) {
981 if (deviation < SKL_DCO_MAX_PDEVIATION &&
982 deviation < ctx->min_deviation) {
983 ctx->min_deviation = deviation;
984 ctx->central_freq = central_freq;
985 ctx->dco_freq = dco_freq;
986 ctx->p = divider;
987 }
988 /* negative deviation */
989 } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
990 deviation < ctx->min_deviation) {
991 ctx->min_deviation = deviation;
992 ctx->central_freq = central_freq;
993 ctx->dco_freq = dco_freq;
994 ctx->p = divider;
995 }
996}
997
998static void skl_wrpll_get_multipliers(unsigned int p,
999 unsigned int *p0 /* out */,
1000 unsigned int *p1 /* out */,
1001 unsigned int *p2 /* out */)
1002{
1003 /* even dividers */
1004 if (p % 2 == 0) {
1005 unsigned int half = p / 2;
1006
1007 if (half == 1 || half == 2 || half == 3 || half == 5) {
1008 *p0 = 2;
1009 *p1 = 1;
1010 *p2 = half;
1011 } else if (half % 2 == 0) {
1012 *p0 = 2;
1013 *p1 = half / 2;
1014 *p2 = 2;
1015 } else if (half % 3 == 0) {
1016 *p0 = 3;
1017 *p1 = half / 3;
1018 *p2 = 2;
1019 } else if (half % 7 == 0) {
1020 *p0 = 7;
1021 *p1 = half / 7;
1022 *p2 = 2;
1023 }
1024 } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
1025 *p0 = 3;
1026 *p1 = 1;
1027 *p2 = p / 3;
1028 } else if (p == 5 || p == 7) {
1029 *p0 = p;
1030 *p1 = 1;
1031 *p2 = 1;
1032 } else if (p == 15) {
1033 *p0 = 3;
1034 *p1 = 1;
1035 *p2 = 5;
1036 } else if (p == 21) {
1037 *p0 = 7;
1038 *p1 = 1;
1039 *p2 = 3;
1040 } else if (p == 35) {
1041 *p0 = 7;
1042 *p1 = 1;
1043 *p2 = 5;
1044 }
1045}
1046
1047struct skl_wrpll_params {
1048 uint32_t dco_fraction;
1049 uint32_t dco_integer;
1050 uint32_t qdiv_ratio;
1051 uint32_t qdiv_mode;
1052 uint32_t kdiv;
1053 uint32_t pdiv;
1054 uint32_t central_freq;
1055};
1056
1057static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
1058 uint64_t afe_clock,
1059 uint64_t central_freq,
1060 uint32_t p0, uint32_t p1, uint32_t p2)
1061{
1062 uint64_t dco_freq;
1063
1064 switch (central_freq) {
1065 case 9600000000ULL:
1066 params->central_freq = 0;
1067 break;
1068 case 9000000000ULL:
1069 params->central_freq = 1;
1070 break;
1071 case 8400000000ULL:
1072 params->central_freq = 3;
1073 }
1074
1075 switch (p0) {
1076 case 1:
1077 params->pdiv = 0;
1078 break;
1079 case 2:
1080 params->pdiv = 1;
1081 break;
1082 case 3:
1083 params->pdiv = 2;
1084 break;
1085 case 7:
1086 params->pdiv = 4;
1087 break;
1088 default:
1089 WARN(1, "Incorrect PDiv\n");
1090 }
1091
1092 switch (p2) {
1093 case 5:
1094 params->kdiv = 0;
1095 break;
1096 case 2:
1097 params->kdiv = 1;
1098 break;
1099 case 3:
1100 params->kdiv = 2;
1101 break;
1102 case 1:
1103 params->kdiv = 3;
1104 break;
1105 default:
1106 WARN(1, "Incorrect KDiv\n");
1107 }
1108
1109 params->qdiv_ratio = p1;
1110 params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1111
1112 dco_freq = p0 * p1 * p2 * afe_clock;
1113
1114 /*
1115 * Intermediate values are in Hz.
1116 * Divide by MHz to match bsepc
1117 */
1118 params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1119 params->dco_fraction =
1120 div_u64((div_u64(dco_freq, 24) -
1121 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1122}
1123
1124static bool
1125skl_ddi_calculate_wrpll(int clock /* in Hz */,
1126 struct skl_wrpll_params *wrpll_params)
1127{
1128 uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1129 uint64_t dco_central_freq[3] = {8400000000ULL,
1130 9000000000ULL,
1131 9600000000ULL};
1132 static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1133 24, 28, 30, 32, 36, 40, 42, 44,
1134 48, 52, 54, 56, 60, 64, 66, 68,
1135 70, 72, 76, 78, 80, 84, 88, 90,
1136 92, 96, 98 };
1137 static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1138 static const struct {
1139 const int *list;
1140 int n_dividers;
1141 } dividers[] = {
1142 { even_dividers, ARRAY_SIZE(even_dividers) },
1143 { odd_dividers, ARRAY_SIZE(odd_dividers) },
1144 };
1145 struct skl_wrpll_context ctx;
1146 unsigned int dco, d, i;
1147 unsigned int p0, p1, p2;
1148
1149 skl_wrpll_context_init(&ctx);
1150
1151 for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1152 for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1153 for (i = 0; i < dividers[d].n_dividers; i++) {
1154 unsigned int p = dividers[d].list[i];
1155 uint64_t dco_freq = p * afe_clock;
1156
1157 skl_wrpll_try_divider(&ctx,
1158 dco_central_freq[dco],
1159 dco_freq,
1160 p);
1161 /*
1162 * Skip the remaining dividers if we're sure to
1163 * have found the definitive divider, we can't
1164 * improve a 0 deviation.
1165 */
1166 if (ctx.min_deviation == 0)
1167 goto skip_remaining_dividers;
1168 }
1169 }
1170
1171skip_remaining_dividers:
1172 /*
1173 * If a solution is found with an even divider, prefer
1174 * this one.
1175 */
1176 if (d == 0 && ctx.p)
1177 break;
1178 }
1179
1180 if (!ctx.p) {
1181 DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1182 return false;
1183 }
1184
1185 /*
1186 * gcc incorrectly analyses that these can be used without being
1187 * initialized. To be fair, it's hard to guess.
1188 */
1189 p0 = p1 = p2 = 0;
1190 skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1191 skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1192 p0, p1, p2);
1193
1194 return true;
1195}
1196
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001197static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001198skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1199 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001200{
1201 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001202 uint32_t ctrl1, cfgcr1, cfgcr2;
1203 int clock = crtc_state->port_clock;
1204
1205 /*
1206 * See comment in intel_dpll_hw_state to understand why we always use 0
1207 * as the DPLL id in this function.
1208 */
1209
1210 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1211
1212 if (encoder->type == INTEL_OUTPUT_HDMI) {
1213 struct skl_wrpll_params wrpll_params = { 0, };
1214
1215 ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
1216
1217 if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
Jani Nikula52e2abb2016-03-16 18:06:58 +02001218 return NULL;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001219
1220 cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1221 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1222 wrpll_params.dco_integer;
1223
1224 cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1225 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1226 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1227 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1228 wrpll_params.central_freq;
Ville Syrjäläcca05022016-06-22 21:57:06 +03001229 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001230 encoder->type == INTEL_OUTPUT_DP_MST ||
1231 encoder->type == INTEL_OUTPUT_EDP) {
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001232 switch (crtc_state->port_clock / 2) {
1233 case 81000:
1234 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1235 break;
1236 case 135000:
1237 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1238 break;
1239 case 270000:
1240 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1241 break;
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001242 /* eDP 1.4 rates */
1243 case 162000:
1244 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
1245 break;
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001246 case 108000:
1247 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
1248 break;
1249 case 216000:
1250 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
1251 break;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001252 }
1253
1254 cfgcr1 = cfgcr2 = 0;
1255 } else {
1256 return NULL;
1257 }
1258
1259 memset(&crtc_state->dpll_hw_state, 0,
1260 sizeof(crtc_state->dpll_hw_state));
1261
1262 crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1263 crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1264 crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001265
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001266 if (encoder->type == INTEL_OUTPUT_EDP)
1267 pll = intel_find_shared_dpll(crtc, crtc_state,
1268 DPLL_ID_SKL_DPLL0,
1269 DPLL_ID_SKL_DPLL0);
1270 else
1271 pll = intel_find_shared_dpll(crtc, crtc_state,
1272 DPLL_ID_SKL_DPLL1,
1273 DPLL_ID_SKL_DPLL3);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001274 if (!pll)
1275 return NULL;
1276
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001277 crtc_state->ddi_pll_sel = pll->id;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001278
1279 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001280
1281 return pll;
1282}
1283
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001284static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1285 .enable = skl_ddi_pll_enable,
1286 .disable = skl_ddi_pll_disable,
1287 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001288};
1289
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001290static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
1291 .enable = skl_ddi_dpll0_enable,
1292 .disable = skl_ddi_dpll0_disable,
1293 .get_hw_state = skl_ddi_dpll0_get_hw_state,
1294};
1295
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001296static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1297 struct intel_shared_dpll *pll)
1298{
1299 uint32_t temp;
1300 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1301
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001302 /* Non-SSC reference */
Dongwon Kimda6110b2016-04-14 15:37:43 -07001303 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1304 temp |= PORT_PLL_REF_SEL;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001305 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1306
1307 /* Disable 10 bit clock */
1308 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
1309 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1310 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1311
1312 /* Write P1 & P2 */
1313 temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
1314 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
1315 temp |= pll->config.hw_state.ebb0;
1316 I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
1317
1318 /* Write M2 integer */
1319 temp = I915_READ(BXT_PORT_PLL(port, 0));
1320 temp &= ~PORT_PLL_M2_MASK;
1321 temp |= pll->config.hw_state.pll0;
1322 I915_WRITE(BXT_PORT_PLL(port, 0), temp);
1323
1324 /* Write N */
1325 temp = I915_READ(BXT_PORT_PLL(port, 1));
1326 temp &= ~PORT_PLL_N_MASK;
1327 temp |= pll->config.hw_state.pll1;
1328 I915_WRITE(BXT_PORT_PLL(port, 1), temp);
1329
1330 /* Write M2 fraction */
1331 temp = I915_READ(BXT_PORT_PLL(port, 2));
1332 temp &= ~PORT_PLL_M2_FRAC_MASK;
1333 temp |= pll->config.hw_state.pll2;
1334 I915_WRITE(BXT_PORT_PLL(port, 2), temp);
1335
1336 /* Write M2 fraction enable */
1337 temp = I915_READ(BXT_PORT_PLL(port, 3));
1338 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
1339 temp |= pll->config.hw_state.pll3;
1340 I915_WRITE(BXT_PORT_PLL(port, 3), temp);
1341
1342 /* Write coeff */
1343 temp = I915_READ(BXT_PORT_PLL(port, 6));
1344 temp &= ~PORT_PLL_PROP_COEFF_MASK;
1345 temp &= ~PORT_PLL_INT_COEFF_MASK;
1346 temp &= ~PORT_PLL_GAIN_CTL_MASK;
1347 temp |= pll->config.hw_state.pll6;
1348 I915_WRITE(BXT_PORT_PLL(port, 6), temp);
1349
1350 /* Write calibration val */
1351 temp = I915_READ(BXT_PORT_PLL(port, 8));
1352 temp &= ~PORT_PLL_TARGET_CNT_MASK;
1353 temp |= pll->config.hw_state.pll8;
1354 I915_WRITE(BXT_PORT_PLL(port, 8), temp);
1355
1356 temp = I915_READ(BXT_PORT_PLL(port, 9));
1357 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
1358 temp |= pll->config.hw_state.pll9;
1359 I915_WRITE(BXT_PORT_PLL(port, 9), temp);
1360
1361 temp = I915_READ(BXT_PORT_PLL(port, 10));
1362 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1363 temp &= ~PORT_PLL_DCO_AMP_MASK;
1364 temp |= pll->config.hw_state.pll10;
1365 I915_WRITE(BXT_PORT_PLL(port, 10), temp);
1366
1367 /* Recalibrate with new settings */
1368 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
1369 temp |= PORT_PLL_RECALIBRATE;
1370 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1371 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1372 temp |= pll->config.hw_state.ebb4;
1373 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1374
1375 /* Enable PLL */
1376 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1377 temp |= PORT_PLL_ENABLE;
1378 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1379 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1380
Imre Deak0b786e42016-06-28 13:37:30 +03001381 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
1382 200))
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001383 DRM_ERROR("PLL %d not locked\n", port);
1384
1385 /*
1386 * While we write to the group register to program all lanes at once we
1387 * can read only lane registers and we pick lanes 0/1 for that.
1388 */
1389 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
1390 temp &= ~LANE_STAGGER_MASK;
1391 temp &= ~LANESTAGGER_STRAP_OVRD;
1392 temp |= pll->config.hw_state.pcsdw12;
1393 I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
1394}
1395
1396static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1397 struct intel_shared_dpll *pll)
1398{
1399 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1400 uint32_t temp;
1401
1402 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1403 temp &= ~PORT_PLL_ENABLE;
1404 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1405 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1406}
1407
1408static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1409 struct intel_shared_dpll *pll,
1410 struct intel_dpll_hw_state *hw_state)
1411{
1412 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1413 uint32_t val;
1414 bool ret;
1415
1416 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1417 return false;
1418
1419 ret = false;
1420
1421 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1422 if (!(val & PORT_PLL_ENABLE))
1423 goto out;
1424
1425 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
1426 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1427
1428 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
1429 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1430
1431 hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
1432 hw_state->pll0 &= PORT_PLL_M2_MASK;
1433
1434 hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
1435 hw_state->pll1 &= PORT_PLL_N_MASK;
1436
1437 hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
1438 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1439
1440 hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
1441 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1442
1443 hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
1444 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1445 PORT_PLL_INT_COEFF_MASK |
1446 PORT_PLL_GAIN_CTL_MASK;
1447
1448 hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
1449 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1450
1451 hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
1452 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1453
1454 hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
1455 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1456 PORT_PLL_DCO_AMP_MASK;
1457
1458 /*
1459 * While we write to the group register to program all lanes at once we
1460 * can read only lane registers. We configure all lanes the same way, so
1461 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1462 */
1463 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
1464 if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
1465 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1466 hw_state->pcsdw12,
1467 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
1468 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1469
1470 ret = true;
1471
1472out:
1473 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1474
1475 return ret;
1476}
1477
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001478/* bxt clock parameters */
1479struct bxt_clk_div {
1480 int clock;
1481 uint32_t p1;
1482 uint32_t p2;
1483 uint32_t m2_int;
1484 uint32_t m2_frac;
1485 bool m2_frac_en;
1486 uint32_t n;
1487};
1488
1489/* pre-calculated values for DP linkrates */
1490static const struct bxt_clk_div bxt_dp_clk_val[] = {
1491 {162000, 4, 2, 32, 1677722, 1, 1},
1492 {270000, 4, 1, 27, 0, 0, 1},
1493 {540000, 2, 1, 27, 0, 0, 1},
1494 {216000, 3, 2, 32, 1677722, 1, 1},
1495 {243000, 4, 1, 24, 1258291, 1, 1},
1496 {324000, 4, 1, 32, 1677722, 1, 1},
1497 {432000, 3, 1, 32, 1677722, 1, 1}
1498};
1499
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001500static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001501bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1502 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001503{
1504 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001505 struct intel_shared_dpll *pll;
1506 enum intel_dpll_id i;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001507 struct intel_digital_port *intel_dig_port;
1508 struct bxt_clk_div clk_div = {0};
1509 int vco = 0;
1510 uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
1511 uint32_t lanestagger;
1512 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001513
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001514 if (encoder->type == INTEL_OUTPUT_HDMI) {
Ander Conselvan de Oliveira9e2c8472016-05-04 12:11:57 +03001515 struct dpll best_clock;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001516
1517 /* Calculate HDMI div */
1518 /*
1519 * FIXME: tie the following calculation into
1520 * i9xx_crtc_compute_clock
1521 */
1522 if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
1523 DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1524 clock, pipe_name(crtc->pipe));
1525 return NULL;
1526 }
1527
1528 clk_div.p1 = best_clock.p1;
1529 clk_div.p2 = best_clock.p2;
1530 WARN_ON(best_clock.m1 != 2);
1531 clk_div.n = best_clock.n;
1532 clk_div.m2_int = best_clock.m2 >> 22;
1533 clk_div.m2_frac = best_clock.m2 & ((1 << 22) - 1);
1534 clk_div.m2_frac_en = clk_div.m2_frac != 0;
1535
1536 vco = best_clock.vco;
Ville Syrjäläcca05022016-06-22 21:57:06 +03001537 } else if (encoder->type == INTEL_OUTPUT_DP ||
Maarten Lankhorsta79e8cc2016-08-09 17:04:00 +02001538 encoder->type == INTEL_OUTPUT_EDP ||
1539 encoder->type == INTEL_OUTPUT_DP_MST) {
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001540 int i;
1541
1542 clk_div = bxt_dp_clk_val[0];
1543 for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1544 if (bxt_dp_clk_val[i].clock == clock) {
1545 clk_div = bxt_dp_clk_val[i];
1546 break;
1547 }
1548 }
1549 vco = clock * 10 / 2 * clk_div.p1 * clk_div.p2;
1550 }
1551
1552 if (vco >= 6200000 && vco <= 6700000) {
1553 prop_coef = 4;
1554 int_coef = 9;
1555 gain_ctl = 3;
1556 targ_cnt = 8;
1557 } else if ((vco > 5400000 && vco < 6200000) ||
1558 (vco >= 4800000 && vco < 5400000)) {
1559 prop_coef = 5;
1560 int_coef = 11;
1561 gain_ctl = 3;
1562 targ_cnt = 9;
1563 } else if (vco == 5400000) {
1564 prop_coef = 3;
1565 int_coef = 8;
1566 gain_ctl = 1;
1567 targ_cnt = 9;
1568 } else {
1569 DRM_ERROR("Invalid VCO\n");
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001570 return NULL;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001571 }
1572
1573 memset(&crtc_state->dpll_hw_state, 0,
1574 sizeof(crtc_state->dpll_hw_state));
1575
1576 if (clock > 270000)
1577 lanestagger = 0x18;
1578 else if (clock > 135000)
1579 lanestagger = 0x0d;
1580 else if (clock > 67000)
1581 lanestagger = 0x07;
1582 else if (clock > 33000)
1583 lanestagger = 0x04;
1584 else
1585 lanestagger = 0x02;
1586
1587 crtc_state->dpll_hw_state.ebb0 =
1588 PORT_PLL_P1(clk_div.p1) | PORT_PLL_P2(clk_div.p2);
1589 crtc_state->dpll_hw_state.pll0 = clk_div.m2_int;
1590 crtc_state->dpll_hw_state.pll1 = PORT_PLL_N(clk_div.n);
1591 crtc_state->dpll_hw_state.pll2 = clk_div.m2_frac;
1592
1593 if (clk_div.m2_frac_en)
1594 crtc_state->dpll_hw_state.pll3 =
1595 PORT_PLL_M2_FRAC_ENABLE;
1596
1597 crtc_state->dpll_hw_state.pll6 =
1598 prop_coef | PORT_PLL_INT_COEFF(int_coef);
1599 crtc_state->dpll_hw_state.pll6 |=
1600 PORT_PLL_GAIN_CTL(gain_ctl);
1601
1602 crtc_state->dpll_hw_state.pll8 = targ_cnt;
1603
1604 crtc_state->dpll_hw_state.pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
1605
1606 crtc_state->dpll_hw_state.pll10 =
1607 PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1608 | PORT_PLL_DCO_AMP_OVR_EN_H;
1609
1610 crtc_state->dpll_hw_state.ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
1611
1612 crtc_state->dpll_hw_state.pcsdw12 =
1613 LANESTAGGER_STRAP_OVRD | lanestagger;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001614
Maarten Lankhorsta79e8cc2016-08-09 17:04:00 +02001615 if (encoder->type == INTEL_OUTPUT_DP_MST) {
1616 struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
1617
1618 intel_dig_port = intel_mst->primary;
1619 } else
1620 intel_dig_port = enc_to_dig_port(&encoder->base);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001621
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001622 /* 1:1 mapping between ports and PLLs */
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001623 i = (enum intel_dpll_id) intel_dig_port->port;
1624 pll = intel_get_shared_dpll_by_id(dev_priv, i);
1625
Ville Syrjälä78108b72016-05-27 20:59:19 +03001626 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
1627 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001628
1629 intel_reference_shared_dpll(pll, crtc_state);
1630
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001631 /* shared DPLL id 0 is DPLL A */
1632 crtc_state->ddi_pll_sel = pll->id;
1633
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001634 return pll;
1635}
1636
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001637static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1638 .enable = bxt_ddi_pll_enable,
1639 .disable = bxt_ddi_pll_disable,
1640 .get_hw_state = bxt_ddi_pll_get_hw_state,
1641};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001642
1643static void intel_ddi_pll_init(struct drm_device *dev)
1644{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001645 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001646
Ville Syrjälä9f7eb312016-05-13 23:41:29 +03001647 if (INTEL_GEN(dev_priv) < 9) {
1648 uint32_t val = I915_READ(LCPLL_CTL);
Ville Syrjäläb2045352016-05-13 23:41:27 +03001649
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001650 /*
1651 * The LCPLL register should be turned on by the BIOS. For now
1652 * let's just check its state and print errors in case
1653 * something is wrong. Don't even try to turn it on.
1654 */
1655
1656 if (val & LCPLL_CD_SOURCE_FCLK)
1657 DRM_ERROR("CDCLK source is not LCPLL\n");
1658
1659 if (val & LCPLL_PLL_DISABLE)
1660 DRM_ERROR("LCPLL is disabled\n");
1661 }
1662}
1663
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001664struct dpll_info {
1665 const char *name;
1666 const int id;
1667 const struct intel_shared_dpll_funcs *funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001668 uint32_t flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001669};
1670
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001671struct intel_dpll_mgr {
1672 const struct dpll_info *dpll_info;
1673
1674 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001675 struct intel_crtc_state *crtc_state,
1676 struct intel_encoder *encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001677};
1678
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001679static const struct dpll_info pch_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001680 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
1681 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
1682 { NULL, -1, NULL, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001683};
1684
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001685static const struct intel_dpll_mgr pch_pll_mgr = {
1686 .dpll_info = pch_plls,
1687 .get_dpll = ibx_get_dpll,
1688};
1689
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001690static const struct dpll_info hsw_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001691 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 },
1692 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 },
1693 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 },
1694 { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1695 { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1696 { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001697 { NULL, -1, NULL, },
1698};
1699
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001700static const struct intel_dpll_mgr hsw_pll_mgr = {
1701 .dpll_info = hsw_plls,
1702 .get_dpll = hsw_get_dpll,
1703};
1704
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001705static const struct dpll_info skl_plls[] = {
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001706 { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
Ville Syrjäläd5aab9d2016-05-11 22:04:33 +03001707 { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
1708 { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
1709 { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001710 { NULL, -1, NULL, },
1711};
1712
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001713static const struct intel_dpll_mgr skl_pll_mgr = {
1714 .dpll_info = skl_plls,
1715 .get_dpll = skl_get_dpll,
1716};
1717
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001718static const struct dpll_info bxt_plls[] = {
Imre Deak08250c42016-03-14 19:55:34 +02001719 { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
1720 { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
1721 { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001722 { NULL, -1, NULL, },
1723};
1724
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001725static const struct intel_dpll_mgr bxt_pll_mgr = {
1726 .dpll_info = bxt_plls,
1727 .get_dpll = bxt_get_dpll,
1728};
1729
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001730void intel_shared_dpll_init(struct drm_device *dev)
1731{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001732 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001733 const struct intel_dpll_mgr *dpll_mgr = NULL;
1734 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001735 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001736
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001737 if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001738 dpll_mgr = &skl_pll_mgr;
Imre Deak08250c42016-03-14 19:55:34 +02001739 else if (IS_BROXTON(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001740 dpll_mgr = &bxt_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001741 else if (HAS_DDI(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001742 dpll_mgr = &hsw_pll_mgr;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001743 else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001744 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001745
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001746 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001747 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001748 return;
1749 }
1750
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001751 dpll_info = dpll_mgr->dpll_info;
1752
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001753 for (i = 0; dpll_info[i].id >= 0; i++) {
1754 WARN_ON(i != dpll_info[i].id);
1755
1756 dev_priv->shared_dplls[i].id = dpll_info[i].id;
1757 dev_priv->shared_dplls[i].name = dpll_info[i].name;
1758 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001759 dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001760 }
1761
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001762 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001763 dev_priv->num_shared_dpll = i;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +01001764 mutex_init(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001765
1766 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001767
1768 /* FIXME: Move this to a more suitable place */
1769 if (HAS_DDI(dev))
1770 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001771}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001772
1773struct intel_shared_dpll *
1774intel_get_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001775 struct intel_crtc_state *crtc_state,
1776 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001777{
1778 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1779 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
1780
1781 if (WARN_ON(!dpll_mgr))
1782 return NULL;
1783
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001784 return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001785}