blob: 6fc32cf2b83d0c1bb479285dd74cc043122222c1 [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 +0200455#define LC_FREQ 2700
456#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
457
458#define P_MIN 2
459#define P_MAX 64
460#define P_INC 2
461
462/* Constraints for PLL good behavior */
463#define REF_MIN 48
464#define REF_MAX 400
465#define VCO_MIN 2400
466#define VCO_MAX 4800
467
468struct hsw_wrpll_rnp {
469 unsigned p, n2, r2;
470};
471
472static unsigned hsw_wrpll_get_budget_for_freq(int clock)
473{
474 unsigned budget;
475
476 switch (clock) {
477 case 25175000:
478 case 25200000:
479 case 27000000:
480 case 27027000:
481 case 37762500:
482 case 37800000:
483 case 40500000:
484 case 40541000:
485 case 54000000:
486 case 54054000:
487 case 59341000:
488 case 59400000:
489 case 72000000:
490 case 74176000:
491 case 74250000:
492 case 81000000:
493 case 81081000:
494 case 89012000:
495 case 89100000:
496 case 108000000:
497 case 108108000:
498 case 111264000:
499 case 111375000:
500 case 148352000:
501 case 148500000:
502 case 162000000:
503 case 162162000:
504 case 222525000:
505 case 222750000:
506 case 296703000:
507 case 297000000:
508 budget = 0;
509 break;
510 case 233500000:
511 case 245250000:
512 case 247750000:
513 case 253250000:
514 case 298000000:
515 budget = 1500;
516 break;
517 case 169128000:
518 case 169500000:
519 case 179500000:
520 case 202000000:
521 budget = 2000;
522 break;
523 case 256250000:
524 case 262500000:
525 case 270000000:
526 case 272500000:
527 case 273750000:
528 case 280750000:
529 case 281250000:
530 case 286000000:
531 case 291750000:
532 budget = 4000;
533 break;
534 case 267250000:
535 case 268500000:
536 budget = 5000;
537 break;
538 default:
539 budget = 1000;
540 break;
541 }
542
543 return budget;
544}
545
546static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
547 unsigned r2, unsigned n2, unsigned p,
548 struct hsw_wrpll_rnp *best)
549{
550 uint64_t a, b, c, d, diff, diff_best;
551
552 /* No best (r,n,p) yet */
553 if (best->p == 0) {
554 best->p = p;
555 best->n2 = n2;
556 best->r2 = r2;
557 return;
558 }
559
560 /*
561 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
562 * freq2k.
563 *
564 * delta = 1e6 *
565 * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
566 * freq2k;
567 *
568 * and we would like delta <= budget.
569 *
570 * If the discrepancy is above the PPM-based budget, always prefer to
571 * improve upon the previous solution. However, if you're within the
572 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
573 */
574 a = freq2k * budget * p * r2;
575 b = freq2k * budget * best->p * best->r2;
576 diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
577 diff_best = abs_diff(freq2k * best->p * best->r2,
578 LC_FREQ_2K * best->n2);
579 c = 1000000 * diff;
580 d = 1000000 * diff_best;
581
582 if (a < c && b < d) {
583 /* If both are above the budget, pick the closer */
584 if (best->p * best->r2 * diff < p * r2 * diff_best) {
585 best->p = p;
586 best->n2 = n2;
587 best->r2 = r2;
588 }
589 } else if (a >= c && b < d) {
590 /* If A is below the threshold but B is above it? Update. */
591 best->p = p;
592 best->n2 = n2;
593 best->r2 = r2;
594 } else if (a >= c && b >= d) {
595 /* Both are below the limit, so pick the higher n2/(r2*r2) */
596 if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
597 best->p = p;
598 best->n2 = n2;
599 best->r2 = r2;
600 }
601 }
602 /* Otherwise a < c && b >= d, do nothing */
603}
604
605static void
606hsw_ddi_calculate_wrpll(int clock /* in Hz */,
607 unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
608{
609 uint64_t freq2k;
610 unsigned p, n2, r2;
611 struct hsw_wrpll_rnp best = { 0, 0, 0 };
612 unsigned budget;
613
614 freq2k = clock / 100;
615
616 budget = hsw_wrpll_get_budget_for_freq(clock);
617
618 /* Special case handling for 540 pixel clock: bypass WR PLL entirely
619 * and directly pass the LC PLL to it. */
620 if (freq2k == 5400000) {
621 *n2_out = 2;
622 *p_out = 1;
623 *r2_out = 2;
624 return;
625 }
626
627 /*
628 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
629 * the WR PLL.
630 *
631 * We want R so that REF_MIN <= Ref <= REF_MAX.
632 * Injecting R2 = 2 * R gives:
633 * REF_MAX * r2 > LC_FREQ * 2 and
634 * REF_MIN * r2 < LC_FREQ * 2
635 *
636 * Which means the desired boundaries for r2 are:
637 * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
638 *
639 */
640 for (r2 = LC_FREQ * 2 / REF_MAX + 1;
641 r2 <= LC_FREQ * 2 / REF_MIN;
642 r2++) {
643
644 /*
645 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
646 *
647 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
648 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
649 * VCO_MAX * r2 > n2 * LC_FREQ and
650 * VCO_MIN * r2 < n2 * LC_FREQ)
651 *
652 * Which means the desired boundaries for n2 are:
653 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
654 */
655 for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
656 n2 <= VCO_MAX * r2 / LC_FREQ;
657 n2++) {
658
659 for (p = P_MIN; p <= P_MAX; p += P_INC)
660 hsw_wrpll_update_rnp(freq2k, budget,
661 r2, n2, p, &best);
662 }
663 }
664
665 *n2_out = best.n2;
666 *p_out = best.p;
667 *r2_out = best.r2;
668}
669
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200670static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200671hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
672 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200673{
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200674 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200675 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200676 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200677
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200678 memset(&crtc_state->dpll_hw_state, 0,
679 sizeof(crtc_state->dpll_hw_state));
680
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200681 if (encoder->type == INTEL_OUTPUT_HDMI) {
682 uint32_t val;
683 unsigned p, n2, r2;
684
685 hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
686
687 val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
688 WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
689 WRPLL_DIVIDER_POST(p);
690
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200691 crtc_state->dpll_hw_state.wrpll = val;
692
693 pll = intel_find_shared_dpll(crtc, crtc_state,
694 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
695
Ville Syrjäläcca05022016-06-22 21:57:06 +0300696 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200697 encoder->type == INTEL_OUTPUT_DP_MST ||
698 encoder->type == INTEL_OUTPUT_EDP) {
699 enum intel_dpll_id pll_id;
700
701 switch (clock / 2) {
702 case 81000:
703 pll_id = DPLL_ID_LCPLL_810;
704 break;
705 case 135000:
706 pll_id = DPLL_ID_LCPLL_1350;
707 break;
708 case 270000:
709 pll_id = DPLL_ID_LCPLL_2700;
710 break;
711 default:
712 DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
713 return NULL;
714 }
715
716 pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
717
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200718 } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
719 if (WARN_ON(crtc_state->port_clock / 2 != 135000))
720 return NULL;
721
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200722 crtc_state->dpll_hw_state.spll =
723 SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
724
725 pll = intel_find_shared_dpll(crtc, crtc_state,
726 DPLL_ID_SPLL, DPLL_ID_SPLL);
727 } else {
728 return NULL;
729 }
730
731 if (!pll)
732 return NULL;
733
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200734 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200735
736 return pll;
737}
738
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200739
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200740static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
741 .enable = hsw_ddi_wrpll_enable,
742 .disable = hsw_ddi_wrpll_disable,
743 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200744};
745
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200746static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
747 .enable = hsw_ddi_spll_enable,
748 .disable = hsw_ddi_spll_disable,
749 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200750};
751
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200752static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
753 struct intel_shared_dpll *pll)
754{
755}
756
757static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
758 struct intel_shared_dpll *pll)
759{
760}
761
762static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
763 struct intel_shared_dpll *pll,
764 struct intel_dpll_hw_state *hw_state)
765{
766 return true;
767}
768
769static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
770 .enable = hsw_ddi_lcpll_enable,
771 .disable = hsw_ddi_lcpll_disable,
772 .get_hw_state = hsw_ddi_lcpll_get_hw_state,
773};
774
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200775struct skl_dpll_regs {
776 i915_reg_t ctl, cfgcr1, cfgcr2;
777};
778
779/* this array is indexed by the *shared* pll id */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200780static const struct skl_dpll_regs skl_dpll_regs[4] = {
781 {
782 /* DPLL 0 */
783 .ctl = LCPLL1_CTL,
784 /* DPLL 0 doesn't support HDMI mode */
785 },
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200786 {
787 /* DPLL 1 */
788 .ctl = LCPLL2_CTL,
789 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
790 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
791 },
792 {
793 /* DPLL 2 */
794 .ctl = WRPLL_CTL(0),
795 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
796 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
797 },
798 {
799 /* DPLL 3 */
800 .ctl = WRPLL_CTL(1),
801 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
802 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
803 },
804};
805
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200806static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
807 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200808{
809 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200810
811 val = I915_READ(DPLL_CTRL1);
812
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200813 val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
814 DPLL_CTRL1_LINK_RATE_MASK(pll->id));
815 val |= pll->config.hw_state.ctrl1 << (pll->id * 6);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200816
817 I915_WRITE(DPLL_CTRL1, val);
818 POSTING_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200819}
820
821static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
822 struct intel_shared_dpll *pll)
823{
824 const struct skl_dpll_regs *regs = skl_dpll_regs;
825
826 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200827
828 I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
829 I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
830 POSTING_READ(regs[pll->id].cfgcr1);
831 POSTING_READ(regs[pll->id].cfgcr2);
832
833 /* the enable bit is always bit 31 */
834 I915_WRITE(regs[pll->id].ctl,
835 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
836
Chris Wilson27bf23a2016-06-30 15:33:12 +0100837 if (intel_wait_for_register(dev_priv,
838 DPLL_STATUS,
839 DPLL_LOCK(pll->id),
840 DPLL_LOCK(pll->id),
841 5))
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200842 DRM_ERROR("DPLL %d not locked\n", pll->id);
843}
844
845static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
846 struct intel_shared_dpll *pll)
847{
848 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200849}
850
851static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
852 struct intel_shared_dpll *pll)
853{
854 const struct skl_dpll_regs *regs = skl_dpll_regs;
855
856 /* the enable bit is always bit 31 */
857 I915_WRITE(regs[pll->id].ctl,
858 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
859 POSTING_READ(regs[pll->id].ctl);
860}
861
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200862static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
863 struct intel_shared_dpll *pll)
864{
865}
866
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200867static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
868 struct intel_shared_dpll *pll,
869 struct intel_dpll_hw_state *hw_state)
870{
871 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200872 const struct skl_dpll_regs *regs = skl_dpll_regs;
873 bool ret;
874
875 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
876 return false;
877
878 ret = false;
879
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200880 val = I915_READ(regs[pll->id].ctl);
881 if (!(val & LCPLL_PLL_ENABLE))
882 goto out;
883
884 val = I915_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200885 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200886
887 /* avoid reading back stale values if HDMI mode is not enabled */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200888 if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200889 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
890 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
891 }
892 ret = true;
893
894out:
895 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
896
897 return ret;
898}
899
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200900static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
901 struct intel_shared_dpll *pll,
902 struct intel_dpll_hw_state *hw_state)
903{
904 uint32_t val;
905 const struct skl_dpll_regs *regs = skl_dpll_regs;
906 bool ret;
907
908 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
909 return false;
910
911 ret = false;
912
913 /* DPLL0 is always enabled since it drives CDCLK */
914 val = I915_READ(regs[pll->id].ctl);
915 if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
916 goto out;
917
918 val = I915_READ(DPLL_CTRL1);
919 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
920
921 ret = true;
922
923out:
924 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
925
926 return ret;
927}
928
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +0200929struct skl_wrpll_context {
930 uint64_t min_deviation; /* current minimal deviation */
931 uint64_t central_freq; /* chosen central freq */
932 uint64_t dco_freq; /* chosen dco freq */
933 unsigned int p; /* chosen divider */
934};
935
936static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
937{
938 memset(ctx, 0, sizeof(*ctx));
939
940 ctx->min_deviation = U64_MAX;
941}
942
943/* DCO freq must be within +1%/-6% of the DCO central freq */
944#define SKL_DCO_MAX_PDEVIATION 100
945#define SKL_DCO_MAX_NDEVIATION 600
946
947static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
948 uint64_t central_freq,
949 uint64_t dco_freq,
950 unsigned int divider)
951{
952 uint64_t deviation;
953
954 deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
955 central_freq);
956
957 /* positive deviation */
958 if (dco_freq >= central_freq) {
959 if (deviation < SKL_DCO_MAX_PDEVIATION &&
960 deviation < ctx->min_deviation) {
961 ctx->min_deviation = deviation;
962 ctx->central_freq = central_freq;
963 ctx->dco_freq = dco_freq;
964 ctx->p = divider;
965 }
966 /* negative deviation */
967 } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
968 deviation < ctx->min_deviation) {
969 ctx->min_deviation = deviation;
970 ctx->central_freq = central_freq;
971 ctx->dco_freq = dco_freq;
972 ctx->p = divider;
973 }
974}
975
976static void skl_wrpll_get_multipliers(unsigned int p,
977 unsigned int *p0 /* out */,
978 unsigned int *p1 /* out */,
979 unsigned int *p2 /* out */)
980{
981 /* even dividers */
982 if (p % 2 == 0) {
983 unsigned int half = p / 2;
984
985 if (half == 1 || half == 2 || half == 3 || half == 5) {
986 *p0 = 2;
987 *p1 = 1;
988 *p2 = half;
989 } else if (half % 2 == 0) {
990 *p0 = 2;
991 *p1 = half / 2;
992 *p2 = 2;
993 } else if (half % 3 == 0) {
994 *p0 = 3;
995 *p1 = half / 3;
996 *p2 = 2;
997 } else if (half % 7 == 0) {
998 *p0 = 7;
999 *p1 = half / 7;
1000 *p2 = 2;
1001 }
1002 } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
1003 *p0 = 3;
1004 *p1 = 1;
1005 *p2 = p / 3;
1006 } else if (p == 5 || p == 7) {
1007 *p0 = p;
1008 *p1 = 1;
1009 *p2 = 1;
1010 } else if (p == 15) {
1011 *p0 = 3;
1012 *p1 = 1;
1013 *p2 = 5;
1014 } else if (p == 21) {
1015 *p0 = 7;
1016 *p1 = 1;
1017 *p2 = 3;
1018 } else if (p == 35) {
1019 *p0 = 7;
1020 *p1 = 1;
1021 *p2 = 5;
1022 }
1023}
1024
1025struct skl_wrpll_params {
1026 uint32_t dco_fraction;
1027 uint32_t dco_integer;
1028 uint32_t qdiv_ratio;
1029 uint32_t qdiv_mode;
1030 uint32_t kdiv;
1031 uint32_t pdiv;
1032 uint32_t central_freq;
1033};
1034
1035static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
1036 uint64_t afe_clock,
1037 uint64_t central_freq,
1038 uint32_t p0, uint32_t p1, uint32_t p2)
1039{
1040 uint64_t dco_freq;
1041
1042 switch (central_freq) {
1043 case 9600000000ULL:
1044 params->central_freq = 0;
1045 break;
1046 case 9000000000ULL:
1047 params->central_freq = 1;
1048 break;
1049 case 8400000000ULL:
1050 params->central_freq = 3;
1051 }
1052
1053 switch (p0) {
1054 case 1:
1055 params->pdiv = 0;
1056 break;
1057 case 2:
1058 params->pdiv = 1;
1059 break;
1060 case 3:
1061 params->pdiv = 2;
1062 break;
1063 case 7:
1064 params->pdiv = 4;
1065 break;
1066 default:
1067 WARN(1, "Incorrect PDiv\n");
1068 }
1069
1070 switch (p2) {
1071 case 5:
1072 params->kdiv = 0;
1073 break;
1074 case 2:
1075 params->kdiv = 1;
1076 break;
1077 case 3:
1078 params->kdiv = 2;
1079 break;
1080 case 1:
1081 params->kdiv = 3;
1082 break;
1083 default:
1084 WARN(1, "Incorrect KDiv\n");
1085 }
1086
1087 params->qdiv_ratio = p1;
1088 params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1089
1090 dco_freq = p0 * p1 * p2 * afe_clock;
1091
1092 /*
1093 * Intermediate values are in Hz.
1094 * Divide by MHz to match bsepc
1095 */
1096 params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1097 params->dco_fraction =
1098 div_u64((div_u64(dco_freq, 24) -
1099 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1100}
1101
1102static bool
1103skl_ddi_calculate_wrpll(int clock /* in Hz */,
1104 struct skl_wrpll_params *wrpll_params)
1105{
1106 uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1107 uint64_t dco_central_freq[3] = {8400000000ULL,
1108 9000000000ULL,
1109 9600000000ULL};
1110 static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1111 24, 28, 30, 32, 36, 40, 42, 44,
1112 48, 52, 54, 56, 60, 64, 66, 68,
1113 70, 72, 76, 78, 80, 84, 88, 90,
1114 92, 96, 98 };
1115 static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1116 static const struct {
1117 const int *list;
1118 int n_dividers;
1119 } dividers[] = {
1120 { even_dividers, ARRAY_SIZE(even_dividers) },
1121 { odd_dividers, ARRAY_SIZE(odd_dividers) },
1122 };
1123 struct skl_wrpll_context ctx;
1124 unsigned int dco, d, i;
1125 unsigned int p0, p1, p2;
1126
1127 skl_wrpll_context_init(&ctx);
1128
1129 for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1130 for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1131 for (i = 0; i < dividers[d].n_dividers; i++) {
1132 unsigned int p = dividers[d].list[i];
1133 uint64_t dco_freq = p * afe_clock;
1134
1135 skl_wrpll_try_divider(&ctx,
1136 dco_central_freq[dco],
1137 dco_freq,
1138 p);
1139 /*
1140 * Skip the remaining dividers if we're sure to
1141 * have found the definitive divider, we can't
1142 * improve a 0 deviation.
1143 */
1144 if (ctx.min_deviation == 0)
1145 goto skip_remaining_dividers;
1146 }
1147 }
1148
1149skip_remaining_dividers:
1150 /*
1151 * If a solution is found with an even divider, prefer
1152 * this one.
1153 */
1154 if (d == 0 && ctx.p)
1155 break;
1156 }
1157
1158 if (!ctx.p) {
1159 DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1160 return false;
1161 }
1162
1163 /*
1164 * gcc incorrectly analyses that these can be used without being
1165 * initialized. To be fair, it's hard to guess.
1166 */
1167 p0 = p1 = p2 = 0;
1168 skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1169 skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1170 p0, p1, p2);
1171
1172 return true;
1173}
1174
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001175static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001176skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1177 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001178{
1179 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001180 uint32_t ctrl1, cfgcr1, cfgcr2;
1181 int clock = crtc_state->port_clock;
1182
1183 /*
1184 * See comment in intel_dpll_hw_state to understand why we always use 0
1185 * as the DPLL id in this function.
1186 */
1187
1188 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1189
1190 if (encoder->type == INTEL_OUTPUT_HDMI) {
1191 struct skl_wrpll_params wrpll_params = { 0, };
1192
1193 ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
1194
1195 if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
Jani Nikula52e2abb2016-03-16 18:06:58 +02001196 return NULL;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001197
1198 cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1199 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1200 wrpll_params.dco_integer;
1201
1202 cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1203 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1204 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1205 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1206 wrpll_params.central_freq;
Ville Syrjäläcca05022016-06-22 21:57:06 +03001207 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001208 encoder->type == INTEL_OUTPUT_DP_MST ||
1209 encoder->type == INTEL_OUTPUT_EDP) {
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001210 switch (crtc_state->port_clock / 2) {
1211 case 81000:
1212 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1213 break;
1214 case 135000:
1215 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1216 break;
1217 case 270000:
1218 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1219 break;
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001220 /* eDP 1.4 rates */
1221 case 162000:
1222 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
1223 break;
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001224 case 108000:
1225 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
1226 break;
1227 case 216000:
1228 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
1229 break;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001230 }
1231
1232 cfgcr1 = cfgcr2 = 0;
1233 } else {
1234 return NULL;
1235 }
1236
1237 memset(&crtc_state->dpll_hw_state, 0,
1238 sizeof(crtc_state->dpll_hw_state));
1239
1240 crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1241 crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1242 crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001243
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001244 if (encoder->type == INTEL_OUTPUT_EDP)
1245 pll = intel_find_shared_dpll(crtc, crtc_state,
1246 DPLL_ID_SKL_DPLL0,
1247 DPLL_ID_SKL_DPLL0);
1248 else
1249 pll = intel_find_shared_dpll(crtc, crtc_state,
1250 DPLL_ID_SKL_DPLL1,
1251 DPLL_ID_SKL_DPLL3);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001252 if (!pll)
1253 return NULL;
1254
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001255 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001256
1257 return pll;
1258}
1259
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001260static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1261 .enable = skl_ddi_pll_enable,
1262 .disable = skl_ddi_pll_disable,
1263 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001264};
1265
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001266static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
1267 .enable = skl_ddi_dpll0_enable,
1268 .disable = skl_ddi_dpll0_disable,
1269 .get_hw_state = skl_ddi_dpll0_get_hw_state,
1270};
1271
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001272static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1273 struct intel_shared_dpll *pll)
1274{
1275 uint32_t temp;
1276 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1277
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001278 /* Non-SSC reference */
Dongwon Kimda6110b2016-04-14 15:37:43 -07001279 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1280 temp |= PORT_PLL_REF_SEL;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001281 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1282
1283 /* Disable 10 bit clock */
1284 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
1285 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1286 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1287
1288 /* Write P1 & P2 */
1289 temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
1290 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
1291 temp |= pll->config.hw_state.ebb0;
1292 I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
1293
1294 /* Write M2 integer */
1295 temp = I915_READ(BXT_PORT_PLL(port, 0));
1296 temp &= ~PORT_PLL_M2_MASK;
1297 temp |= pll->config.hw_state.pll0;
1298 I915_WRITE(BXT_PORT_PLL(port, 0), temp);
1299
1300 /* Write N */
1301 temp = I915_READ(BXT_PORT_PLL(port, 1));
1302 temp &= ~PORT_PLL_N_MASK;
1303 temp |= pll->config.hw_state.pll1;
1304 I915_WRITE(BXT_PORT_PLL(port, 1), temp);
1305
1306 /* Write M2 fraction */
1307 temp = I915_READ(BXT_PORT_PLL(port, 2));
1308 temp &= ~PORT_PLL_M2_FRAC_MASK;
1309 temp |= pll->config.hw_state.pll2;
1310 I915_WRITE(BXT_PORT_PLL(port, 2), temp);
1311
1312 /* Write M2 fraction enable */
1313 temp = I915_READ(BXT_PORT_PLL(port, 3));
1314 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
1315 temp |= pll->config.hw_state.pll3;
1316 I915_WRITE(BXT_PORT_PLL(port, 3), temp);
1317
1318 /* Write coeff */
1319 temp = I915_READ(BXT_PORT_PLL(port, 6));
1320 temp &= ~PORT_PLL_PROP_COEFF_MASK;
1321 temp &= ~PORT_PLL_INT_COEFF_MASK;
1322 temp &= ~PORT_PLL_GAIN_CTL_MASK;
1323 temp |= pll->config.hw_state.pll6;
1324 I915_WRITE(BXT_PORT_PLL(port, 6), temp);
1325
1326 /* Write calibration val */
1327 temp = I915_READ(BXT_PORT_PLL(port, 8));
1328 temp &= ~PORT_PLL_TARGET_CNT_MASK;
1329 temp |= pll->config.hw_state.pll8;
1330 I915_WRITE(BXT_PORT_PLL(port, 8), temp);
1331
1332 temp = I915_READ(BXT_PORT_PLL(port, 9));
1333 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
1334 temp |= pll->config.hw_state.pll9;
1335 I915_WRITE(BXT_PORT_PLL(port, 9), temp);
1336
1337 temp = I915_READ(BXT_PORT_PLL(port, 10));
1338 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1339 temp &= ~PORT_PLL_DCO_AMP_MASK;
1340 temp |= pll->config.hw_state.pll10;
1341 I915_WRITE(BXT_PORT_PLL(port, 10), temp);
1342
1343 /* Recalibrate with new settings */
1344 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
1345 temp |= PORT_PLL_RECALIBRATE;
1346 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1347 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1348 temp |= pll->config.hw_state.ebb4;
1349 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1350
1351 /* Enable PLL */
1352 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1353 temp |= PORT_PLL_ENABLE;
1354 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1355 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1356
Imre Deak0b786e42016-06-28 13:37:30 +03001357 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
1358 200))
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001359 DRM_ERROR("PLL %d not locked\n", port);
1360
1361 /*
1362 * While we write to the group register to program all lanes at once we
1363 * can read only lane registers and we pick lanes 0/1 for that.
1364 */
1365 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
1366 temp &= ~LANE_STAGGER_MASK;
1367 temp &= ~LANESTAGGER_STRAP_OVRD;
1368 temp |= pll->config.hw_state.pcsdw12;
1369 I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
1370}
1371
1372static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1373 struct intel_shared_dpll *pll)
1374{
1375 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1376 uint32_t temp;
1377
1378 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1379 temp &= ~PORT_PLL_ENABLE;
1380 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1381 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1382}
1383
1384static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1385 struct intel_shared_dpll *pll,
1386 struct intel_dpll_hw_state *hw_state)
1387{
1388 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1389 uint32_t val;
1390 bool ret;
1391
1392 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1393 return false;
1394
1395 ret = false;
1396
1397 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1398 if (!(val & PORT_PLL_ENABLE))
1399 goto out;
1400
1401 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
1402 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1403
1404 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
1405 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1406
1407 hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
1408 hw_state->pll0 &= PORT_PLL_M2_MASK;
1409
1410 hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
1411 hw_state->pll1 &= PORT_PLL_N_MASK;
1412
1413 hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
1414 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1415
1416 hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
1417 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1418
1419 hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
1420 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1421 PORT_PLL_INT_COEFF_MASK |
1422 PORT_PLL_GAIN_CTL_MASK;
1423
1424 hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
1425 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1426
1427 hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
1428 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1429
1430 hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
1431 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1432 PORT_PLL_DCO_AMP_MASK;
1433
1434 /*
1435 * While we write to the group register to program all lanes at once we
1436 * can read only lane registers. We configure all lanes the same way, so
1437 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1438 */
1439 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
1440 if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
1441 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1442 hw_state->pcsdw12,
1443 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
1444 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1445
1446 ret = true;
1447
1448out:
1449 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1450
1451 return ret;
1452}
1453
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001454/* bxt clock parameters */
1455struct bxt_clk_div {
1456 int clock;
1457 uint32_t p1;
1458 uint32_t p2;
1459 uint32_t m2_int;
1460 uint32_t m2_frac;
1461 bool m2_frac_en;
1462 uint32_t n;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001463
1464 int vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001465};
1466
1467/* pre-calculated values for DP linkrates */
1468static const struct bxt_clk_div bxt_dp_clk_val[] = {
1469 {162000, 4, 2, 32, 1677722, 1, 1},
1470 {270000, 4, 1, 27, 0, 0, 1},
1471 {540000, 2, 1, 27, 0, 0, 1},
1472 {216000, 3, 2, 32, 1677722, 1, 1},
1473 {243000, 4, 1, 24, 1258291, 1, 1},
1474 {324000, 4, 1, 32, 1677722, 1, 1},
1475 {432000, 3, 1, 32, 1677722, 1, 1}
1476};
1477
Durgadoss Ra277ca72016-09-01 15:08:09 -07001478static bool
1479bxt_ddi_hdmi_pll_dividers(struct intel_crtc *intel_crtc,
1480 struct intel_crtc_state *crtc_state, int clock,
1481 struct bxt_clk_div *clk_div)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001482{
Durgadoss Ra277ca72016-09-01 15:08:09 -07001483 struct dpll best_clock;
1484
1485 /* Calculate HDMI div */
1486 /*
1487 * FIXME: tie the following calculation into
1488 * i9xx_crtc_compute_clock
1489 */
1490 if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
1491 DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1492 clock, pipe_name(intel_crtc->pipe));
1493 return false;
1494 }
1495
1496 clk_div->p1 = best_clock.p1;
1497 clk_div->p2 = best_clock.p2;
1498 WARN_ON(best_clock.m1 != 2);
1499 clk_div->n = best_clock.n;
1500 clk_div->m2_int = best_clock.m2 >> 22;
1501 clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
1502 clk_div->m2_frac_en = clk_div->m2_frac != 0;
1503
1504 clk_div->vco = best_clock.vco;
1505
1506 return true;
1507}
1508
1509static void bxt_ddi_dp_pll_dividers(int clock, struct bxt_clk_div *clk_div)
1510{
1511 int i;
1512
1513 *clk_div = bxt_dp_clk_val[0];
1514 for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1515 if (bxt_dp_clk_val[i].clock == clock) {
1516 *clk_div = bxt_dp_clk_val[i];
1517 break;
1518 }
1519 }
1520
1521 clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
1522}
1523
1524static bool bxt_ddi_set_dpll_hw_state(int clock,
1525 struct bxt_clk_div *clk_div,
1526 struct intel_dpll_hw_state *dpll_hw_state)
1527{
1528 int vco = clk_div->vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001529 uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
1530 uint32_t lanestagger;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001531
1532 if (vco >= 6200000 && vco <= 6700000) {
1533 prop_coef = 4;
1534 int_coef = 9;
1535 gain_ctl = 3;
1536 targ_cnt = 8;
1537 } else if ((vco > 5400000 && vco < 6200000) ||
1538 (vco >= 4800000 && vco < 5400000)) {
1539 prop_coef = 5;
1540 int_coef = 11;
1541 gain_ctl = 3;
1542 targ_cnt = 9;
1543 } else if (vco == 5400000) {
1544 prop_coef = 3;
1545 int_coef = 8;
1546 gain_ctl = 1;
1547 targ_cnt = 9;
1548 } else {
1549 DRM_ERROR("Invalid VCO\n");
Durgadoss Ra277ca72016-09-01 15:08:09 -07001550 return false;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001551 }
1552
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001553 if (clock > 270000)
1554 lanestagger = 0x18;
1555 else if (clock > 135000)
1556 lanestagger = 0x0d;
1557 else if (clock > 67000)
1558 lanestagger = 0x07;
1559 else if (clock > 33000)
1560 lanestagger = 0x04;
1561 else
1562 lanestagger = 0x02;
1563
Durgadoss Ra277ca72016-09-01 15:08:09 -07001564 dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
1565 dpll_hw_state->pll0 = clk_div->m2_int;
1566 dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
1567 dpll_hw_state->pll2 = clk_div->m2_frac;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001568
Durgadoss Ra277ca72016-09-01 15:08:09 -07001569 if (clk_div->m2_frac_en)
1570 dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001571
Durgadoss Ra277ca72016-09-01 15:08:09 -07001572 dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
1573 dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001574
Durgadoss Ra277ca72016-09-01 15:08:09 -07001575 dpll_hw_state->pll8 = targ_cnt;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001576
Durgadoss Ra277ca72016-09-01 15:08:09 -07001577 dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001578
Durgadoss Ra277ca72016-09-01 15:08:09 -07001579 dpll_hw_state->pll10 =
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001580 PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1581 | PORT_PLL_DCO_AMP_OVR_EN_H;
1582
Durgadoss Ra277ca72016-09-01 15:08:09 -07001583 dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001584
Durgadoss Ra277ca72016-09-01 15:08:09 -07001585 dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger;
1586
1587 return true;
1588}
1589
1590bool bxt_ddi_dp_set_dpll_hw_state(int clock,
1591 struct intel_dpll_hw_state *dpll_hw_state)
1592{
1593 struct bxt_clk_div clk_div = {0};
1594
1595 bxt_ddi_dp_pll_dividers(clock, &clk_div);
1596
1597 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1598}
1599
1600static struct intel_shared_dpll *
1601bxt_get_dpll(struct intel_crtc *crtc,
1602 struct intel_crtc_state *crtc_state,
1603 struct intel_encoder *encoder)
1604{
1605 struct bxt_clk_div clk_div = {0};
1606 struct intel_dpll_hw_state dpll_hw_state = {0};
1607 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1608 struct intel_digital_port *intel_dig_port;
1609 struct intel_shared_dpll *pll;
1610 int i, clock = crtc_state->port_clock;
1611
1612 if (encoder->type == INTEL_OUTPUT_HDMI
1613 && !bxt_ddi_hdmi_pll_dividers(crtc, crtc_state,
1614 clock, &clk_div))
1615 return false;
1616
1617 if ((encoder->type == INTEL_OUTPUT_DP ||
1618 encoder->type == INTEL_OUTPUT_EDP) &&
1619 !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
1620 return false;
1621
1622 memset(&crtc_state->dpll_hw_state, 0,
1623 sizeof(crtc_state->dpll_hw_state));
1624
1625 crtc_state->dpll_hw_state = dpll_hw_state;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001626
Maarten Lankhorsta79e8cc2016-08-09 17:04:00 +02001627 if (encoder->type == INTEL_OUTPUT_DP_MST) {
1628 struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
1629
1630 intel_dig_port = intel_mst->primary;
1631 } else
1632 intel_dig_port = enc_to_dig_port(&encoder->base);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001633
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001634 /* 1:1 mapping between ports and PLLs */
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001635 i = (enum intel_dpll_id) intel_dig_port->port;
1636 pll = intel_get_shared_dpll_by_id(dev_priv, i);
1637
Ville Syrjälä78108b72016-05-27 20:59:19 +03001638 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
1639 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001640
1641 intel_reference_shared_dpll(pll, crtc_state);
1642
1643 return pll;
1644}
1645
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001646static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1647 .enable = bxt_ddi_pll_enable,
1648 .disable = bxt_ddi_pll_disable,
1649 .get_hw_state = bxt_ddi_pll_get_hw_state,
1650};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001651
1652static void intel_ddi_pll_init(struct drm_device *dev)
1653{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001654 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001655
Ville Syrjälä9f7eb312016-05-13 23:41:29 +03001656 if (INTEL_GEN(dev_priv) < 9) {
1657 uint32_t val = I915_READ(LCPLL_CTL);
Ville Syrjäläb2045352016-05-13 23:41:27 +03001658
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001659 /*
1660 * The LCPLL register should be turned on by the BIOS. For now
1661 * let's just check its state and print errors in case
1662 * something is wrong. Don't even try to turn it on.
1663 */
1664
1665 if (val & LCPLL_CD_SOURCE_FCLK)
1666 DRM_ERROR("CDCLK source is not LCPLL\n");
1667
1668 if (val & LCPLL_PLL_DISABLE)
1669 DRM_ERROR("LCPLL is disabled\n");
1670 }
1671}
1672
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001673struct dpll_info {
1674 const char *name;
1675 const int id;
1676 const struct intel_shared_dpll_funcs *funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001677 uint32_t flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001678};
1679
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001680struct intel_dpll_mgr {
1681 const struct dpll_info *dpll_info;
1682
1683 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001684 struct intel_crtc_state *crtc_state,
1685 struct intel_encoder *encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001686};
1687
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001688static const struct dpll_info pch_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001689 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
1690 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
1691 { NULL, -1, NULL, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001692};
1693
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001694static const struct intel_dpll_mgr pch_pll_mgr = {
1695 .dpll_info = pch_plls,
1696 .get_dpll = ibx_get_dpll,
1697};
1698
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001699static const struct dpll_info hsw_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001700 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 },
1701 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 },
1702 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 },
1703 { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1704 { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1705 { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001706 { NULL, -1, NULL, },
1707};
1708
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001709static const struct intel_dpll_mgr hsw_pll_mgr = {
1710 .dpll_info = hsw_plls,
1711 .get_dpll = hsw_get_dpll,
1712};
1713
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001714static const struct dpll_info skl_plls[] = {
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001715 { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
Ville Syrjäläd5aab9d2016-05-11 22:04:33 +03001716 { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
1717 { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
1718 { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001719 { NULL, -1, NULL, },
1720};
1721
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001722static const struct intel_dpll_mgr skl_pll_mgr = {
1723 .dpll_info = skl_plls,
1724 .get_dpll = skl_get_dpll,
1725};
1726
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001727static const struct dpll_info bxt_plls[] = {
Imre Deak08250c42016-03-14 19:55:34 +02001728 { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
1729 { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
1730 { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001731 { NULL, -1, NULL, },
1732};
1733
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001734static const struct intel_dpll_mgr bxt_pll_mgr = {
1735 .dpll_info = bxt_plls,
1736 .get_dpll = bxt_get_dpll,
1737};
1738
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001739void intel_shared_dpll_init(struct drm_device *dev)
1740{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001741 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001742 const struct intel_dpll_mgr *dpll_mgr = NULL;
1743 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001744 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001745
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001746 if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001747 dpll_mgr = &skl_pll_mgr;
Imre Deak08250c42016-03-14 19:55:34 +02001748 else if (IS_BROXTON(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001749 dpll_mgr = &bxt_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001750 else if (HAS_DDI(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001751 dpll_mgr = &hsw_pll_mgr;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001752 else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001753 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001754
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001755 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001756 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001757 return;
1758 }
1759
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001760 dpll_info = dpll_mgr->dpll_info;
1761
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001762 for (i = 0; dpll_info[i].id >= 0; i++) {
1763 WARN_ON(i != dpll_info[i].id);
1764
1765 dev_priv->shared_dplls[i].id = dpll_info[i].id;
1766 dev_priv->shared_dplls[i].name = dpll_info[i].name;
1767 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001768 dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001769 }
1770
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001771 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001772 dev_priv->num_shared_dpll = i;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +01001773 mutex_init(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001774
1775 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001776
1777 /* FIXME: Move this to a more suitable place */
1778 if (HAS_DDI(dev))
1779 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001780}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001781
1782struct intel_shared_dpll *
1783intel_get_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001784 struct intel_crtc_state *crtc_state,
1785 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001786{
1787 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1788 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
1789
1790 if (WARN_ON(!dpll_mgr))
1791 return NULL;
1792
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001793 return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001794}