blob: 79f656ca593daa9b7aef44c2830d5961ad5cda16 [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
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +020026/**
27 * DOC: Display PLLs
28 *
29 * Display PLLs used for driving outputs vary by platform. While some have
30 * per-pipe or per-encoder dedicated PLLs, others allow the use of any PLL
31 * from a pool. In the latter scenario, it is possible that multiple pipes
32 * share a PLL if their configurations match.
33 *
34 * This file provides an abstraction over display PLLs. The function
35 * intel_shared_dpll_init() initializes the PLLs for the given platform. The
36 * users of a PLL are tracked and that tracking is integrated with the atomic
37 * modest interface. During an atomic operation, a PLL can be requested for a
38 * given CRTC and encoder configuration by calling intel_get_shared_dpll() and
39 * a previously used PLL can be released with intel_release_shared_dpll().
40 * Changes to the users are first staged in the atomic state, and then made
41 * effective by calling intel_shared_dpll_swap_state() during the atomic
42 * commit phase.
43 */
44
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020045struct intel_shared_dpll *
Jim Bridef1696602016-09-07 15:47:34 -070046skl_find_link_pll(struct drm_i915_private *dev_priv, int clock)
47{
48 struct intel_shared_dpll *pll = NULL;
49 struct intel_dpll_hw_state dpll_hw_state;
50 enum intel_dpll_id i;
51 bool found = false;
52
53 if (!skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
54 return pll;
55
56 for (i = DPLL_ID_SKL_DPLL1; i <= DPLL_ID_SKL_DPLL3; i++) {
57 pll = &dev_priv->shared_dplls[i];
58
59 /* Only want to check enabled timings first */
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +020060 if (pll->state.crtc_mask == 0)
Jim Bridef1696602016-09-07 15:47:34 -070061 continue;
62
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +020063 if (memcmp(&dpll_hw_state, &pll->state.hw_state,
64 sizeof(pll->state.hw_state)) == 0) {
Jim Bridef1696602016-09-07 15:47:34 -070065 found = true;
66 break;
67 }
68 }
69
70 /* Ok no matching timings, maybe there's a free one? */
71 for (i = DPLL_ID_SKL_DPLL1;
72 ((found == false) && (i <= DPLL_ID_SKL_DPLL3)); i++) {
73 pll = &dev_priv->shared_dplls[i];
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +020074 if (pll->state.crtc_mask == 0) {
75 pll->state.hw_state = dpll_hw_state;
Jim Bridef1696602016-09-07 15:47:34 -070076 break;
77 }
78 }
79
80 return pll;
81}
82
Ander Conselvan de Oliveira8e45ac12016-12-29 17:22:13 +020083static void
84intel_atomic_duplicate_dpll_state(struct drm_i915_private *dev_priv,
85 struct intel_shared_dpll_state *shared_dpll)
86{
87 enum intel_dpll_id i;
88
89 /* Copy shared dpll state */
90 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
91 struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
92
93 shared_dpll[i] = pll->state;
94 }
95}
96
97static struct intel_shared_dpll_state *
98intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s)
99{
100 struct intel_atomic_state *state = to_intel_atomic_state(s);
101
102 WARN_ON(!drm_modeset_is_locked(&s->dev->mode_config.connection_mutex));
103
104 if (!state->dpll_set) {
105 state->dpll_set = true;
106
107 intel_atomic_duplicate_dpll_state(to_i915(s->dev),
108 state->shared_dpll);
109 }
110
111 return state->shared_dpll;
112}
113
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200114/**
115 * intel_get_shared_dpll_by_id - get a DPLL given its id
116 * @dev_priv: i915 device instance
117 * @id: pll id
118 *
119 * Returns:
120 * A pointer to the DPLL with @id
121 */
Jim Bridef1696602016-09-07 15:47:34 -0700122struct intel_shared_dpll *
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200123intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
124 enum intel_dpll_id id)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200125{
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200126 return &dev_priv->shared_dplls[id];
127}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200128
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200129/**
130 * intel_get_shared_dpll_id - get the id of a DPLL
131 * @dev_priv: i915 device instance
132 * @pll: the DPLL
133 *
134 * Returns:
135 * The id of @pll
136 */
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200137enum intel_dpll_id
138intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
139 struct intel_shared_dpll *pll)
140{
141 if (WARN_ON(pll < dev_priv->shared_dplls||
142 pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll]))
143 return -1;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200144
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200145 return (enum intel_dpll_id) (pll - dev_priv->shared_dplls);
146}
147
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200148/* For ILK+ */
149void assert_shared_dpll(struct drm_i915_private *dev_priv,
150 struct intel_shared_dpll *pll,
151 bool state)
152{
153 bool cur_state;
154 struct intel_dpll_hw_state hw_state;
155
156 if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
157 return;
158
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200159 cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200160 I915_STATE_WARN(cur_state != state,
161 "%s assertion failure (expected %s, current %s)\n",
162 pll->name, onoff(state), onoff(cur_state));
163}
164
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200165/**
166 * intel_prepare_shared_dpll - call a dpll's prepare hook
167 * @crtc: CRTC which has a shared dpll
168 *
169 * This calls the PLL's prepare hook if it has one and if the PLL is not
170 * already enabled. The prepare hook is platform specific.
171 */
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200172void intel_prepare_shared_dpll(struct intel_crtc *crtc)
173{
174 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100175 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200176 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200177
178 if (WARN_ON(pll == NULL))
179 return;
180
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100181 mutex_lock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200182 WARN_ON(!pll->state.crtc_mask);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100183 if (!pll->active_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200184 DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
185 WARN_ON(pll->on);
186 assert_shared_dpll_disabled(dev_priv, pll);
187
Ander Conselvan de Oliveiraeac61762016-12-29 17:22:10 +0200188 pll->funcs.prepare(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200189 }
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100190 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200191}
192
193/**
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200194 * intel_enable_shared_dpll - enable a CRTC's shared DPLL
195 * @crtc: CRTC which has a shared DPLL
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200196 *
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200197 * Enable the shared DPLL used by @crtc.
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200198 */
199void intel_enable_shared_dpll(struct intel_crtc *crtc)
200{
201 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100202 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200203 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100204 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100205 unsigned old_mask;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200206
207 if (WARN_ON(pll == NULL))
208 return;
209
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100210 mutex_lock(&dev_priv->dpll_lock);
211 old_mask = pll->active_mask;
212
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200213 if (WARN_ON(!(pll->state.crtc_mask & crtc_mask)) ||
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100214 WARN_ON(pll->active_mask & crtc_mask))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100215 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200216
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100217 pll->active_mask |= crtc_mask;
218
219 DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n",
220 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200221 crtc->base.base.id);
222
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100223 if (old_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200224 WARN_ON(!pll->on);
225 assert_shared_dpll_enabled(dev_priv, pll);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100226 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200227 }
228 WARN_ON(pll->on);
229
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200230 DRM_DEBUG_KMS("enabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200231 pll->funcs.enable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200232 pll->on = true;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100233
234out:
235 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200236}
237
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200238/**
239 * intel_disable_shared_dpll - disable a CRTC's shared DPLL
240 * @crtc: CRTC which has a shared DPLL
241 *
242 * Disable the shared DPLL used by @crtc.
243 */
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200244void intel_disable_shared_dpll(struct intel_crtc *crtc)
245{
Tvrtko Ursulin66478472016-11-16 08:55:40 +0000246 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200247 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100248 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200249
250 /* PCH only available on ILK+ */
Tvrtko Ursulin66478472016-11-16 08:55:40 +0000251 if (INTEL_GEN(dev_priv) < 5)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200252 return;
253
254 if (pll == NULL)
255 return;
256
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100257 mutex_lock(&dev_priv->dpll_lock);
Maarten Lankhorsta1475e72016-03-14 09:27:53 +0100258 if (WARN_ON(!(pll->active_mask & crtc_mask)))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100259 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200260
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100261 DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
262 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200263 crtc->base.base.id);
264
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200265 assert_shared_dpll_enabled(dev_priv, pll);
266 WARN_ON(!pll->on);
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100267
268 pll->active_mask &= ~crtc_mask;
269 if (pll->active_mask)
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100270 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200271
272 DRM_DEBUG_KMS("disabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200273 pll->funcs.disable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200274 pll->on = false;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100275
276out:
277 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200278}
279
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200280static struct intel_shared_dpll *
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200281intel_find_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200282 struct intel_crtc_state *crtc_state,
283 enum intel_dpll_id range_min,
284 enum intel_dpll_id range_max)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200285{
Chris Wilsonfac5e232016-07-04 11:34:36 +0100286 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200287 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200288 struct intel_shared_dpll_state *shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200289 enum intel_dpll_id i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200290
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200291 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
292
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200293 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200294 pll = &dev_priv->shared_dplls[i];
295
296 /* Only want to check enabled timings first */
297 if (shared_dpll[i].crtc_mask == 0)
298 continue;
299
300 if (memcmp(&crtc_state->dpll_hw_state,
301 &shared_dpll[i].hw_state,
302 sizeof(crtc_state->dpll_hw_state)) == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300303 DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
304 crtc->base.base.id, crtc->base.name, pll->name,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200305 shared_dpll[i].crtc_mask,
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100306 pll->active_mask);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200307 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200308 }
309 }
310
311 /* Ok no matching timings, maybe there's a free one? */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200312 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200313 pll = &dev_priv->shared_dplls[i];
314 if (shared_dpll[i].crtc_mask == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300315 DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n",
316 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200317 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200318 }
319 }
320
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200321 return NULL;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200322}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200323
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200324static void
325intel_reference_shared_dpll(struct intel_shared_dpll *pll,
326 struct intel_crtc_state *crtc_state)
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200327{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200328 struct intel_shared_dpll_state *shared_dpll;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200329 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
330 enum intel_dpll_id i = pll->id;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200331
332 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
333
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200334 if (shared_dpll[i].crtc_mask == 0)
335 shared_dpll[i].hw_state =
336 crtc_state->dpll_hw_state;
337
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200338 crtc_state->shared_dpll = pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200339 DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
340 pipe_name(crtc->pipe));
341
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +0200342 shared_dpll[pll->id].crtc_mask |= 1 << crtc->pipe;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200343}
344
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200345/**
346 * intel_shared_dpll_swap_state - make atomic DPLL configuration effective
347 * @state: atomic state
348 *
349 * This is the dpll version of drm_atomic_helper_swap_state() since the
350 * helper does not handle driver-specific global state.
351 *
352 * For consistency with atomic helpers this function does a complete swap,
353 * i.e. it also puts the current state into @state, even though there is no
354 * need for that at this moment.
355 */
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200356void intel_shared_dpll_swap_state(struct drm_atomic_state *state)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200357{
358 struct drm_i915_private *dev_priv = to_i915(state->dev);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200359 struct intel_shared_dpll_state *shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200360 struct intel_shared_dpll *pll;
361 enum intel_dpll_id i;
362
363 if (!to_intel_atomic_state(state)->dpll_set)
364 return;
365
366 shared_dpll = to_intel_atomic_state(state)->shared_dpll;
367 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200368 struct intel_shared_dpll_state tmp;
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200369
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200370 pll = &dev_priv->shared_dplls[i];
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200371
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200372 tmp = pll->state;
373 pll->state = shared_dpll[i];
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200374 shared_dpll[i] = tmp;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200375 }
376}
377
378static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
379 struct intel_shared_dpll *pll,
380 struct intel_dpll_hw_state *hw_state)
381{
382 uint32_t val;
383
384 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
385 return false;
386
387 val = I915_READ(PCH_DPLL(pll->id));
388 hw_state->dpll = val;
389 hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
390 hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
391
392 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
393
394 return val & DPLL_VCO_ENABLE;
395}
396
Ander Conselvan de Oliveiraeac61762016-12-29 17:22:10 +0200397static void ibx_pch_dpll_prepare(struct drm_i915_private *dev_priv,
398 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200399{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200400 I915_WRITE(PCH_FP0(pll->id), pll->state.hw_state.fp0);
401 I915_WRITE(PCH_FP1(pll->id), pll->state.hw_state.fp1);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200402}
403
404static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
405{
406 u32 val;
407 bool enabled;
408
Joonas Lahtinen2d1fe072016-04-07 11:08:05 +0300409 I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200410
411 val = I915_READ(PCH_DREF_CONTROL);
412 enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
413 DREF_SUPERSPREAD_SOURCE_MASK));
414 I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
415}
416
417static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
418 struct intel_shared_dpll *pll)
419{
420 /* PCH refclock must be enabled first */
421 ibx_assert_pch_refclk_enabled(dev_priv);
422
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200423 I915_WRITE(PCH_DPLL(pll->id), pll->state.hw_state.dpll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200424
425 /* Wait for the clocks to stabilize. */
426 POSTING_READ(PCH_DPLL(pll->id));
427 udelay(150);
428
429 /* The pixel multiplier can only be updated once the
430 * DPLL is enabled and the clocks are stable.
431 *
432 * So write it again.
433 */
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200434 I915_WRITE(PCH_DPLL(pll->id), pll->state.hw_state.dpll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200435 POSTING_READ(PCH_DPLL(pll->id));
436 udelay(200);
437}
438
439static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
440 struct intel_shared_dpll *pll)
441{
Chris Wilson91c8a322016-07-05 10:40:23 +0100442 struct drm_device *dev = &dev_priv->drm;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200443 struct intel_crtc *crtc;
444
445 /* Make sure no transcoder isn't still depending on us. */
446 for_each_intel_crtc(dev, crtc) {
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200447 if (crtc->config->shared_dpll == pll)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200448 assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
449 }
450
451 I915_WRITE(PCH_DPLL(pll->id), 0);
452 POSTING_READ(PCH_DPLL(pll->id));
453 udelay(200);
454}
455
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200456static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200457ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
458 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200459{
460 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
461 struct intel_shared_dpll *pll;
462 enum intel_dpll_id i;
463
464 if (HAS_PCH_IBX(dev_priv)) {
465 /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
466 i = (enum intel_dpll_id) crtc->pipe;
467 pll = &dev_priv->shared_dplls[i];
468
Ville Syrjälä78108b72016-05-27 20:59:19 +0300469 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
470 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200471 } else {
472 pll = intel_find_shared_dpll(crtc, crtc_state,
473 DPLL_ID_PCH_PLL_A,
474 DPLL_ID_PCH_PLL_B);
475 }
476
Ander Conselvan de Oliveirabb143162016-05-20 15:47:06 +0300477 if (!pll)
478 return NULL;
479
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200480 /* reference the pll */
481 intel_reference_shared_dpll(pll, crtc_state);
482
483 return pll;
484}
485
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +0200486static void ibx_dump_hw_state(struct drm_i915_private *dev_priv,
487 struct intel_dpll_hw_state *hw_state)
488{
489 DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
490 "fp0: 0x%x, fp1: 0x%x\n",
491 hw_state->dpll,
492 hw_state->dpll_md,
493 hw_state->fp0,
494 hw_state->fp1);
495}
496
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200497static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
Ander Conselvan de Oliveiraeac61762016-12-29 17:22:10 +0200498 .prepare = ibx_pch_dpll_prepare,
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200499 .enable = ibx_pch_dpll_enable,
500 .disable = ibx_pch_dpll_disable,
501 .get_hw_state = ibx_pch_dpll_get_hw_state,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200502};
503
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200504static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
505 struct intel_shared_dpll *pll)
506{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200507 I915_WRITE(WRPLL_CTL(pll->id), pll->state.hw_state.wrpll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200508 POSTING_READ(WRPLL_CTL(pll->id));
509 udelay(20);
510}
511
512static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
513 struct intel_shared_dpll *pll)
514{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200515 I915_WRITE(SPLL_CTL, pll->state.hw_state.spll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200516 POSTING_READ(SPLL_CTL);
517 udelay(20);
518}
519
520static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
521 struct intel_shared_dpll *pll)
522{
523 uint32_t val;
524
525 val = I915_READ(WRPLL_CTL(pll->id));
526 I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
527 POSTING_READ(WRPLL_CTL(pll->id));
528}
529
530static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
531 struct intel_shared_dpll *pll)
532{
533 uint32_t val;
534
535 val = I915_READ(SPLL_CTL);
536 I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
537 POSTING_READ(SPLL_CTL);
538}
539
540static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
541 struct intel_shared_dpll *pll,
542 struct intel_dpll_hw_state *hw_state)
543{
544 uint32_t val;
545
546 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
547 return false;
548
549 val = I915_READ(WRPLL_CTL(pll->id));
550 hw_state->wrpll = val;
551
552 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
553
554 return val & WRPLL_PLL_ENABLE;
555}
556
557static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
558 struct intel_shared_dpll *pll,
559 struct intel_dpll_hw_state *hw_state)
560{
561 uint32_t val;
562
563 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
564 return false;
565
566 val = I915_READ(SPLL_CTL);
567 hw_state->spll = val;
568
569 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
570
571 return val & SPLL_PLL_ENABLE;
572}
573
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200574#define LC_FREQ 2700
575#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
576
577#define P_MIN 2
578#define P_MAX 64
579#define P_INC 2
580
581/* Constraints for PLL good behavior */
582#define REF_MIN 48
583#define REF_MAX 400
584#define VCO_MIN 2400
585#define VCO_MAX 4800
586
587struct hsw_wrpll_rnp {
588 unsigned p, n2, r2;
589};
590
591static unsigned hsw_wrpll_get_budget_for_freq(int clock)
592{
593 unsigned budget;
594
595 switch (clock) {
596 case 25175000:
597 case 25200000:
598 case 27000000:
599 case 27027000:
600 case 37762500:
601 case 37800000:
602 case 40500000:
603 case 40541000:
604 case 54000000:
605 case 54054000:
606 case 59341000:
607 case 59400000:
608 case 72000000:
609 case 74176000:
610 case 74250000:
611 case 81000000:
612 case 81081000:
613 case 89012000:
614 case 89100000:
615 case 108000000:
616 case 108108000:
617 case 111264000:
618 case 111375000:
619 case 148352000:
620 case 148500000:
621 case 162000000:
622 case 162162000:
623 case 222525000:
624 case 222750000:
625 case 296703000:
626 case 297000000:
627 budget = 0;
628 break;
629 case 233500000:
630 case 245250000:
631 case 247750000:
632 case 253250000:
633 case 298000000:
634 budget = 1500;
635 break;
636 case 169128000:
637 case 169500000:
638 case 179500000:
639 case 202000000:
640 budget = 2000;
641 break;
642 case 256250000:
643 case 262500000:
644 case 270000000:
645 case 272500000:
646 case 273750000:
647 case 280750000:
648 case 281250000:
649 case 286000000:
650 case 291750000:
651 budget = 4000;
652 break;
653 case 267250000:
654 case 268500000:
655 budget = 5000;
656 break;
657 default:
658 budget = 1000;
659 break;
660 }
661
662 return budget;
663}
664
665static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
666 unsigned r2, unsigned n2, unsigned p,
667 struct hsw_wrpll_rnp *best)
668{
669 uint64_t a, b, c, d, diff, diff_best;
670
671 /* No best (r,n,p) yet */
672 if (best->p == 0) {
673 best->p = p;
674 best->n2 = n2;
675 best->r2 = r2;
676 return;
677 }
678
679 /*
680 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
681 * freq2k.
682 *
683 * delta = 1e6 *
684 * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
685 * freq2k;
686 *
687 * and we would like delta <= budget.
688 *
689 * If the discrepancy is above the PPM-based budget, always prefer to
690 * improve upon the previous solution. However, if you're within the
691 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
692 */
693 a = freq2k * budget * p * r2;
694 b = freq2k * budget * best->p * best->r2;
695 diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
696 diff_best = abs_diff(freq2k * best->p * best->r2,
697 LC_FREQ_2K * best->n2);
698 c = 1000000 * diff;
699 d = 1000000 * diff_best;
700
701 if (a < c && b < d) {
702 /* If both are above the budget, pick the closer */
703 if (best->p * best->r2 * diff < p * r2 * diff_best) {
704 best->p = p;
705 best->n2 = n2;
706 best->r2 = r2;
707 }
708 } else if (a >= c && b < d) {
709 /* If A is below the threshold but B is above it? Update. */
710 best->p = p;
711 best->n2 = n2;
712 best->r2 = r2;
713 } else if (a >= c && b >= d) {
714 /* Both are below the limit, so pick the higher n2/(r2*r2) */
715 if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
716 best->p = p;
717 best->n2 = n2;
718 best->r2 = r2;
719 }
720 }
721 /* Otherwise a < c && b >= d, do nothing */
722}
723
724static void
725hsw_ddi_calculate_wrpll(int clock /* in Hz */,
726 unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
727{
728 uint64_t freq2k;
729 unsigned p, n2, r2;
730 struct hsw_wrpll_rnp best = { 0, 0, 0 };
731 unsigned budget;
732
733 freq2k = clock / 100;
734
735 budget = hsw_wrpll_get_budget_for_freq(clock);
736
737 /* Special case handling for 540 pixel clock: bypass WR PLL entirely
738 * and directly pass the LC PLL to it. */
739 if (freq2k == 5400000) {
740 *n2_out = 2;
741 *p_out = 1;
742 *r2_out = 2;
743 return;
744 }
745
746 /*
747 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
748 * the WR PLL.
749 *
750 * We want R so that REF_MIN <= Ref <= REF_MAX.
751 * Injecting R2 = 2 * R gives:
752 * REF_MAX * r2 > LC_FREQ * 2 and
753 * REF_MIN * r2 < LC_FREQ * 2
754 *
755 * Which means the desired boundaries for r2 are:
756 * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
757 *
758 */
759 for (r2 = LC_FREQ * 2 / REF_MAX + 1;
760 r2 <= LC_FREQ * 2 / REF_MIN;
761 r2++) {
762
763 /*
764 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
765 *
766 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
767 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
768 * VCO_MAX * r2 > n2 * LC_FREQ and
769 * VCO_MIN * r2 < n2 * LC_FREQ)
770 *
771 * Which means the desired boundaries for n2 are:
772 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
773 */
774 for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
775 n2 <= VCO_MAX * r2 / LC_FREQ;
776 n2++) {
777
778 for (p = P_MIN; p <= P_MAX; p += P_INC)
779 hsw_wrpll_update_rnp(freq2k, budget,
780 r2, n2, p, &best);
781 }
782 }
783
784 *n2_out = best.n2;
785 *p_out = best.p;
786 *r2_out = best.r2;
787}
788
Manasi Navare81b9fd82016-09-01 15:08:11 -0700789static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(int clock,
790 struct intel_crtc *crtc,
791 struct intel_crtc_state *crtc_state)
792{
793 struct intel_shared_dpll *pll;
794 uint32_t val;
795 unsigned int p, n2, r2;
796
797 hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
798
799 val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
800 WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
801 WRPLL_DIVIDER_POST(p);
802
803 crtc_state->dpll_hw_state.wrpll = val;
804
805 pll = intel_find_shared_dpll(crtc, crtc_state,
806 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
807
808 if (!pll)
809 return NULL;
810
811 return pll;
812}
813
814struct intel_shared_dpll *hsw_ddi_dp_get_dpll(struct intel_encoder *encoder,
815 int clock)
816{
817 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
818 struct intel_shared_dpll *pll;
819 enum intel_dpll_id pll_id;
820
821 switch (clock / 2) {
822 case 81000:
823 pll_id = DPLL_ID_LCPLL_810;
824 break;
825 case 135000:
826 pll_id = DPLL_ID_LCPLL_1350;
827 break;
828 case 270000:
829 pll_id = DPLL_ID_LCPLL_2700;
830 break;
831 default:
832 DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
833 return NULL;
834 }
835
836 pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
837
838 if (!pll)
839 return NULL;
840
841 return pll;
842}
843
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200844static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200845hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
846 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200847{
848 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200849 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200850
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200851 memset(&crtc_state->dpll_hw_state, 0,
852 sizeof(crtc_state->dpll_hw_state));
853
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200854 if (encoder->type == INTEL_OUTPUT_HDMI) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700855 pll = hsw_ddi_hdmi_get_dpll(clock, crtc, crtc_state);
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200856
Ville Syrjäläcca05022016-06-22 21:57:06 +0300857 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200858 encoder->type == INTEL_OUTPUT_DP_MST ||
859 encoder->type == INTEL_OUTPUT_EDP) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700860 pll = hsw_ddi_dp_get_dpll(encoder, clock);
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200861
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200862 } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
863 if (WARN_ON(crtc_state->port_clock / 2 != 135000))
864 return NULL;
865
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200866 crtc_state->dpll_hw_state.spll =
867 SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
868
869 pll = intel_find_shared_dpll(crtc, crtc_state,
870 DPLL_ID_SPLL, DPLL_ID_SPLL);
871 } else {
872 return NULL;
873 }
874
875 if (!pll)
876 return NULL;
877
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200878 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200879
880 return pll;
881}
882
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +0200883static void hsw_dump_hw_state(struct drm_i915_private *dev_priv,
884 struct intel_dpll_hw_state *hw_state)
885{
886 DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
887 hw_state->wrpll, hw_state->spll);
888}
889
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200890static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
891 .enable = hsw_ddi_wrpll_enable,
892 .disable = hsw_ddi_wrpll_disable,
893 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200894};
895
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200896static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
897 .enable = hsw_ddi_spll_enable,
898 .disable = hsw_ddi_spll_disable,
899 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200900};
901
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200902static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
903 struct intel_shared_dpll *pll)
904{
905}
906
907static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
908 struct intel_shared_dpll *pll)
909{
910}
911
912static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
913 struct intel_shared_dpll *pll,
914 struct intel_dpll_hw_state *hw_state)
915{
916 return true;
917}
918
919static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
920 .enable = hsw_ddi_lcpll_enable,
921 .disable = hsw_ddi_lcpll_disable,
922 .get_hw_state = hsw_ddi_lcpll_get_hw_state,
923};
924
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200925struct skl_dpll_regs {
926 i915_reg_t ctl, cfgcr1, cfgcr2;
927};
928
929/* this array is indexed by the *shared* pll id */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200930static const struct skl_dpll_regs skl_dpll_regs[4] = {
931 {
932 /* DPLL 0 */
933 .ctl = LCPLL1_CTL,
934 /* DPLL 0 doesn't support HDMI mode */
935 },
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200936 {
937 /* DPLL 1 */
938 .ctl = LCPLL2_CTL,
939 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
940 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
941 },
942 {
943 /* DPLL 2 */
944 .ctl = WRPLL_CTL(0),
945 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
946 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
947 },
948 {
949 /* DPLL 3 */
950 .ctl = WRPLL_CTL(1),
951 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
952 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
953 },
954};
955
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200956static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
957 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200958{
959 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200960
961 val = I915_READ(DPLL_CTRL1);
962
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200963 val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
964 DPLL_CTRL1_LINK_RATE_MASK(pll->id));
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200965 val |= pll->state.hw_state.ctrl1 << (pll->id * 6);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200966
967 I915_WRITE(DPLL_CTRL1, val);
968 POSTING_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200969}
970
971static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
972 struct intel_shared_dpll *pll)
973{
974 const struct skl_dpll_regs *regs = skl_dpll_regs;
975
976 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200977
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200978 I915_WRITE(regs[pll->id].cfgcr1, pll->state.hw_state.cfgcr1);
979 I915_WRITE(regs[pll->id].cfgcr2, pll->state.hw_state.cfgcr2);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200980 POSTING_READ(regs[pll->id].cfgcr1);
981 POSTING_READ(regs[pll->id].cfgcr2);
982
983 /* the enable bit is always bit 31 */
984 I915_WRITE(regs[pll->id].ctl,
985 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
986
Chris Wilson27bf23a2016-06-30 15:33:12 +0100987 if (intel_wait_for_register(dev_priv,
988 DPLL_STATUS,
989 DPLL_LOCK(pll->id),
990 DPLL_LOCK(pll->id),
991 5))
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200992 DRM_ERROR("DPLL %d not locked\n", pll->id);
993}
994
995static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
996 struct intel_shared_dpll *pll)
997{
998 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200999}
1000
1001static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
1002 struct intel_shared_dpll *pll)
1003{
1004 const struct skl_dpll_regs *regs = skl_dpll_regs;
1005
1006 /* the enable bit is always bit 31 */
1007 I915_WRITE(regs[pll->id].ctl,
1008 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
1009 POSTING_READ(regs[pll->id].ctl);
1010}
1011
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001012static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
1013 struct intel_shared_dpll *pll)
1014{
1015}
1016
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001017static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1018 struct intel_shared_dpll *pll,
1019 struct intel_dpll_hw_state *hw_state)
1020{
1021 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001022 const struct skl_dpll_regs *regs = skl_dpll_regs;
1023 bool ret;
1024
1025 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1026 return false;
1027
1028 ret = false;
1029
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001030 val = I915_READ(regs[pll->id].ctl);
1031 if (!(val & LCPLL_PLL_ENABLE))
1032 goto out;
1033
1034 val = I915_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001035 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001036
1037 /* avoid reading back stale values if HDMI mode is not enabled */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001038 if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001039 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
1040 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
1041 }
1042 ret = true;
1043
1044out:
1045 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1046
1047 return ret;
1048}
1049
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001050static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
1051 struct intel_shared_dpll *pll,
1052 struct intel_dpll_hw_state *hw_state)
1053{
1054 uint32_t val;
1055 const struct skl_dpll_regs *regs = skl_dpll_regs;
1056 bool ret;
1057
1058 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1059 return false;
1060
1061 ret = false;
1062
1063 /* DPLL0 is always enabled since it drives CDCLK */
1064 val = I915_READ(regs[pll->id].ctl);
1065 if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
1066 goto out;
1067
1068 val = I915_READ(DPLL_CTRL1);
1069 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
1070
1071 ret = true;
1072
1073out:
1074 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1075
1076 return ret;
1077}
1078
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001079struct skl_wrpll_context {
1080 uint64_t min_deviation; /* current minimal deviation */
1081 uint64_t central_freq; /* chosen central freq */
1082 uint64_t dco_freq; /* chosen dco freq */
1083 unsigned int p; /* chosen divider */
1084};
1085
1086static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
1087{
1088 memset(ctx, 0, sizeof(*ctx));
1089
1090 ctx->min_deviation = U64_MAX;
1091}
1092
1093/* DCO freq must be within +1%/-6% of the DCO central freq */
1094#define SKL_DCO_MAX_PDEVIATION 100
1095#define SKL_DCO_MAX_NDEVIATION 600
1096
1097static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
1098 uint64_t central_freq,
1099 uint64_t dco_freq,
1100 unsigned int divider)
1101{
1102 uint64_t deviation;
1103
1104 deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
1105 central_freq);
1106
1107 /* positive deviation */
1108 if (dco_freq >= central_freq) {
1109 if (deviation < SKL_DCO_MAX_PDEVIATION &&
1110 deviation < ctx->min_deviation) {
1111 ctx->min_deviation = deviation;
1112 ctx->central_freq = central_freq;
1113 ctx->dco_freq = dco_freq;
1114 ctx->p = divider;
1115 }
1116 /* negative deviation */
1117 } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
1118 deviation < ctx->min_deviation) {
1119 ctx->min_deviation = deviation;
1120 ctx->central_freq = central_freq;
1121 ctx->dco_freq = dco_freq;
1122 ctx->p = divider;
1123 }
1124}
1125
1126static void skl_wrpll_get_multipliers(unsigned int p,
1127 unsigned int *p0 /* out */,
1128 unsigned int *p1 /* out */,
1129 unsigned int *p2 /* out */)
1130{
1131 /* even dividers */
1132 if (p % 2 == 0) {
1133 unsigned int half = p / 2;
1134
1135 if (half == 1 || half == 2 || half == 3 || half == 5) {
1136 *p0 = 2;
1137 *p1 = 1;
1138 *p2 = half;
1139 } else if (half % 2 == 0) {
1140 *p0 = 2;
1141 *p1 = half / 2;
1142 *p2 = 2;
1143 } else if (half % 3 == 0) {
1144 *p0 = 3;
1145 *p1 = half / 3;
1146 *p2 = 2;
1147 } else if (half % 7 == 0) {
1148 *p0 = 7;
1149 *p1 = half / 7;
1150 *p2 = 2;
1151 }
1152 } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
1153 *p0 = 3;
1154 *p1 = 1;
1155 *p2 = p / 3;
1156 } else if (p == 5 || p == 7) {
1157 *p0 = p;
1158 *p1 = 1;
1159 *p2 = 1;
1160 } else if (p == 15) {
1161 *p0 = 3;
1162 *p1 = 1;
1163 *p2 = 5;
1164 } else if (p == 21) {
1165 *p0 = 7;
1166 *p1 = 1;
1167 *p2 = 3;
1168 } else if (p == 35) {
1169 *p0 = 7;
1170 *p1 = 1;
1171 *p2 = 5;
1172 }
1173}
1174
1175struct skl_wrpll_params {
1176 uint32_t dco_fraction;
1177 uint32_t dco_integer;
1178 uint32_t qdiv_ratio;
1179 uint32_t qdiv_mode;
1180 uint32_t kdiv;
1181 uint32_t pdiv;
1182 uint32_t central_freq;
1183};
1184
1185static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
1186 uint64_t afe_clock,
1187 uint64_t central_freq,
1188 uint32_t p0, uint32_t p1, uint32_t p2)
1189{
1190 uint64_t dco_freq;
1191
1192 switch (central_freq) {
1193 case 9600000000ULL:
1194 params->central_freq = 0;
1195 break;
1196 case 9000000000ULL:
1197 params->central_freq = 1;
1198 break;
1199 case 8400000000ULL:
1200 params->central_freq = 3;
1201 }
1202
1203 switch (p0) {
1204 case 1:
1205 params->pdiv = 0;
1206 break;
1207 case 2:
1208 params->pdiv = 1;
1209 break;
1210 case 3:
1211 params->pdiv = 2;
1212 break;
1213 case 7:
1214 params->pdiv = 4;
1215 break;
1216 default:
1217 WARN(1, "Incorrect PDiv\n");
1218 }
1219
1220 switch (p2) {
1221 case 5:
1222 params->kdiv = 0;
1223 break;
1224 case 2:
1225 params->kdiv = 1;
1226 break;
1227 case 3:
1228 params->kdiv = 2;
1229 break;
1230 case 1:
1231 params->kdiv = 3;
1232 break;
1233 default:
1234 WARN(1, "Incorrect KDiv\n");
1235 }
1236
1237 params->qdiv_ratio = p1;
1238 params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1239
1240 dco_freq = p0 * p1 * p2 * afe_clock;
1241
1242 /*
1243 * Intermediate values are in Hz.
1244 * Divide by MHz to match bsepc
1245 */
1246 params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1247 params->dco_fraction =
1248 div_u64((div_u64(dco_freq, 24) -
1249 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1250}
1251
1252static bool
1253skl_ddi_calculate_wrpll(int clock /* in Hz */,
1254 struct skl_wrpll_params *wrpll_params)
1255{
1256 uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1257 uint64_t dco_central_freq[3] = {8400000000ULL,
1258 9000000000ULL,
1259 9600000000ULL};
1260 static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1261 24, 28, 30, 32, 36, 40, 42, 44,
1262 48, 52, 54, 56, 60, 64, 66, 68,
1263 70, 72, 76, 78, 80, 84, 88, 90,
1264 92, 96, 98 };
1265 static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1266 static const struct {
1267 const int *list;
1268 int n_dividers;
1269 } dividers[] = {
1270 { even_dividers, ARRAY_SIZE(even_dividers) },
1271 { odd_dividers, ARRAY_SIZE(odd_dividers) },
1272 };
1273 struct skl_wrpll_context ctx;
1274 unsigned int dco, d, i;
1275 unsigned int p0, p1, p2;
1276
1277 skl_wrpll_context_init(&ctx);
1278
1279 for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1280 for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1281 for (i = 0; i < dividers[d].n_dividers; i++) {
1282 unsigned int p = dividers[d].list[i];
1283 uint64_t dco_freq = p * afe_clock;
1284
1285 skl_wrpll_try_divider(&ctx,
1286 dco_central_freq[dco],
1287 dco_freq,
1288 p);
1289 /*
1290 * Skip the remaining dividers if we're sure to
1291 * have found the definitive divider, we can't
1292 * improve a 0 deviation.
1293 */
1294 if (ctx.min_deviation == 0)
1295 goto skip_remaining_dividers;
1296 }
1297 }
1298
1299skip_remaining_dividers:
1300 /*
1301 * If a solution is found with an even divider, prefer
1302 * this one.
1303 */
1304 if (d == 0 && ctx.p)
1305 break;
1306 }
1307
1308 if (!ctx.p) {
1309 DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1310 return false;
1311 }
1312
1313 /*
1314 * gcc incorrectly analyses that these can be used without being
1315 * initialized. To be fair, it's hard to guess.
1316 */
1317 p0 = p1 = p2 = 0;
1318 skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1319 skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1320 p0, p1, p2);
1321
1322 return true;
1323}
1324
Jim Bride9a4edad2016-09-01 15:08:10 -07001325static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
1326 struct intel_crtc_state *crtc_state,
1327 int clock)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001328{
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001329 uint32_t ctrl1, cfgcr1, cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001330 struct skl_wrpll_params wrpll_params = { 0, };
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001331
1332 /*
1333 * See comment in intel_dpll_hw_state to understand why we always use 0
1334 * as the DPLL id in this function.
1335 */
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001336 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1337
Jim Bride9a4edad2016-09-01 15:08:10 -07001338 ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001339
Jim Bride9a4edad2016-09-01 15:08:10 -07001340 if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
1341 return false;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001342
Jim Bride9a4edad2016-09-01 15:08:10 -07001343 cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1344 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1345 wrpll_params.dco_integer;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001346
Jim Bride9a4edad2016-09-01 15:08:10 -07001347 cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1348 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1349 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1350 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1351 wrpll_params.central_freq;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001352
1353 memset(&crtc_state->dpll_hw_state, 0,
1354 sizeof(crtc_state->dpll_hw_state));
1355
1356 crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1357 crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1358 crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001359 return true;
1360}
1361
1362
1363bool skl_ddi_dp_set_dpll_hw_state(int clock,
1364 struct intel_dpll_hw_state *dpll_hw_state)
1365{
1366 uint32_t ctrl1;
1367
1368 /*
1369 * See comment in intel_dpll_hw_state to understand why we always use 0
1370 * as the DPLL id in this function.
1371 */
1372 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1373 switch (clock / 2) {
1374 case 81000:
1375 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1376 break;
1377 case 135000:
1378 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1379 break;
1380 case 270000:
1381 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1382 break;
1383 /* eDP 1.4 rates */
1384 case 162000:
1385 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
1386 break;
1387 case 108000:
1388 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
1389 break;
1390 case 216000:
1391 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
1392 break;
1393 }
1394
1395 dpll_hw_state->ctrl1 = ctrl1;
1396 return true;
1397}
1398
1399static struct intel_shared_dpll *
1400skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1401 struct intel_encoder *encoder)
1402{
1403 struct intel_shared_dpll *pll;
1404 int clock = crtc_state->port_clock;
1405 bool bret;
1406 struct intel_dpll_hw_state dpll_hw_state;
1407
1408 memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
1409
1410 if (encoder->type == INTEL_OUTPUT_HDMI) {
1411 bret = skl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock);
1412 if (!bret) {
1413 DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n");
1414 return NULL;
1415 }
1416 } else if (encoder->type == INTEL_OUTPUT_DP ||
1417 encoder->type == INTEL_OUTPUT_DP_MST ||
1418 encoder->type == INTEL_OUTPUT_EDP) {
1419 bret = skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state);
1420 if (!bret) {
1421 DRM_DEBUG_KMS("Could not set DP dpll HW state.\n");
1422 return NULL;
1423 }
1424 crtc_state->dpll_hw_state = dpll_hw_state;
1425 } else {
1426 return NULL;
1427 }
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001428
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001429 if (encoder->type == INTEL_OUTPUT_EDP)
1430 pll = intel_find_shared_dpll(crtc, crtc_state,
1431 DPLL_ID_SKL_DPLL0,
1432 DPLL_ID_SKL_DPLL0);
1433 else
1434 pll = intel_find_shared_dpll(crtc, crtc_state,
1435 DPLL_ID_SKL_DPLL1,
1436 DPLL_ID_SKL_DPLL3);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001437 if (!pll)
1438 return NULL;
1439
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001440 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001441
1442 return pll;
1443}
1444
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001445static void skl_dump_hw_state(struct drm_i915_private *dev_priv,
1446 struct intel_dpll_hw_state *hw_state)
1447{
1448 DRM_DEBUG_KMS("dpll_hw_state: "
1449 "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
1450 hw_state->ctrl1,
1451 hw_state->cfgcr1,
1452 hw_state->cfgcr2);
1453}
1454
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001455static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1456 .enable = skl_ddi_pll_enable,
1457 .disable = skl_ddi_pll_disable,
1458 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001459};
1460
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001461static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
1462 .enable = skl_ddi_dpll0_enable,
1463 .disable = skl_ddi_dpll0_disable,
1464 .get_hw_state = skl_ddi_dpll0_get_hw_state,
1465};
1466
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001467static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1468 struct intel_shared_dpll *pll)
1469{
1470 uint32_t temp;
1471 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001472 enum dpio_phy phy;
1473 enum dpio_channel ch;
1474
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001475 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001476
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001477 /* Non-SSC reference */
Dongwon Kimda6110b2016-04-14 15:37:43 -07001478 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1479 temp |= PORT_PLL_REF_SEL;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001480 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1481
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001482 if (IS_GEMINILAKE(dev_priv)) {
1483 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1484 temp |= PORT_PLL_POWER_ENABLE;
1485 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1486
1487 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1488 PORT_PLL_POWER_STATE), 200))
1489 DRM_ERROR("Power state not set for PLL:%d\n", port);
1490 }
1491
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001492 /* Disable 10 bit clock */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001493 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001494 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001495 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001496
1497 /* Write P1 & P2 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001498 temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001499 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001500 temp |= pll->state.hw_state.ebb0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001501 I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001502
1503 /* Write M2 integer */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001504 temp = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001505 temp &= ~PORT_PLL_M2_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001506 temp |= pll->state.hw_state.pll0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001507 I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001508
1509 /* Write N */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001510 temp = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001511 temp &= ~PORT_PLL_N_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001512 temp |= pll->state.hw_state.pll1;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001513 I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001514
1515 /* Write M2 fraction */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001516 temp = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001517 temp &= ~PORT_PLL_M2_FRAC_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001518 temp |= pll->state.hw_state.pll2;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001519 I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001520
1521 /* Write M2 fraction enable */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001522 temp = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001523 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001524 temp |= pll->state.hw_state.pll3;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001525 I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001526
1527 /* Write coeff */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001528 temp = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001529 temp &= ~PORT_PLL_PROP_COEFF_MASK;
1530 temp &= ~PORT_PLL_INT_COEFF_MASK;
1531 temp &= ~PORT_PLL_GAIN_CTL_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001532 temp |= pll->state.hw_state.pll6;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001533 I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001534
1535 /* Write calibration val */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001536 temp = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001537 temp &= ~PORT_PLL_TARGET_CNT_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001538 temp |= pll->state.hw_state.pll8;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001539 I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001540
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001541 temp = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001542 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001543 temp |= pll->state.hw_state.pll9;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001544 I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001545
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001546 temp = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001547 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1548 temp &= ~PORT_PLL_DCO_AMP_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001549 temp |= pll->state.hw_state.pll10;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001550 I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001551
1552 /* Recalibrate with new settings */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001553 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001554 temp |= PORT_PLL_RECALIBRATE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001555 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001556 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001557 temp |= pll->state.hw_state.ebb4;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001558 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001559
1560 /* Enable PLL */
1561 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1562 temp |= PORT_PLL_ENABLE;
1563 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1564 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1565
Imre Deak0b786e42016-06-28 13:37:30 +03001566 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
1567 200))
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001568 DRM_ERROR("PLL %d not locked\n", port);
1569
Ander Conselvan de Oliveira51b3ee32016-12-02 10:23:52 +02001570 if (IS_GEMINILAKE(dev_priv)) {
1571 temp = I915_READ(BXT_PORT_TX_DW5_LN0(phy, ch));
1572 temp |= DCC_DELAY_RANGE_2;
1573 I915_WRITE(BXT_PORT_TX_DW5_GRP(phy, ch), temp);
1574 }
1575
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001576 /*
1577 * While we write to the group register to program all lanes at once we
1578 * can read only lane registers and we pick lanes 0/1 for that.
1579 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001580 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001581 temp &= ~LANE_STAGGER_MASK;
1582 temp &= ~LANESTAGGER_STRAP_OVRD;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001583 temp |= pll->state.hw_state.pcsdw12;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001584 I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001585}
1586
1587static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1588 struct intel_shared_dpll *pll)
1589{
1590 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1591 uint32_t temp;
1592
1593 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1594 temp &= ~PORT_PLL_ENABLE;
1595 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1596 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001597
1598 if (IS_GEMINILAKE(dev_priv)) {
1599 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1600 temp &= ~PORT_PLL_POWER_ENABLE;
1601 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1602
1603 if (wait_for_us(!(I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1604 PORT_PLL_POWER_STATE), 200))
1605 DRM_ERROR("Power state not reset for PLL:%d\n", port);
1606 }
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001607}
1608
1609static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1610 struct intel_shared_dpll *pll,
1611 struct intel_dpll_hw_state *hw_state)
1612{
1613 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1614 uint32_t val;
1615 bool ret;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001616 enum dpio_phy phy;
1617 enum dpio_channel ch;
1618
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001619 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001620
1621 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1622 return false;
1623
1624 ret = false;
1625
1626 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1627 if (!(val & PORT_PLL_ENABLE))
1628 goto out;
1629
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001630 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001631 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1632
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001633 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001634 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1635
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001636 hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001637 hw_state->pll0 &= PORT_PLL_M2_MASK;
1638
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001639 hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001640 hw_state->pll1 &= PORT_PLL_N_MASK;
1641
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001642 hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001643 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1644
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001645 hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001646 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1647
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001648 hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001649 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1650 PORT_PLL_INT_COEFF_MASK |
1651 PORT_PLL_GAIN_CTL_MASK;
1652
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001653 hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001654 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1655
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001656 hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001657 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1658
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001659 hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001660 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1661 PORT_PLL_DCO_AMP_MASK;
1662
1663 /*
1664 * While we write to the group register to program all lanes at once we
1665 * can read only lane registers. We configure all lanes the same way, so
1666 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1667 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001668 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
1669 if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001670 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1671 hw_state->pcsdw12,
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001672 I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001673 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1674
1675 ret = true;
1676
1677out:
1678 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1679
1680 return ret;
1681}
1682
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001683/* bxt clock parameters */
1684struct bxt_clk_div {
1685 int clock;
1686 uint32_t p1;
1687 uint32_t p2;
1688 uint32_t m2_int;
1689 uint32_t m2_frac;
1690 bool m2_frac_en;
1691 uint32_t n;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001692
1693 int vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001694};
1695
1696/* pre-calculated values for DP linkrates */
1697static const struct bxt_clk_div bxt_dp_clk_val[] = {
1698 {162000, 4, 2, 32, 1677722, 1, 1},
1699 {270000, 4, 1, 27, 0, 0, 1},
1700 {540000, 2, 1, 27, 0, 0, 1},
1701 {216000, 3, 2, 32, 1677722, 1, 1},
1702 {243000, 4, 1, 24, 1258291, 1, 1},
1703 {324000, 4, 1, 32, 1677722, 1, 1},
1704 {432000, 3, 1, 32, 1677722, 1, 1}
1705};
1706
Durgadoss Ra277ca72016-09-01 15:08:09 -07001707static bool
1708bxt_ddi_hdmi_pll_dividers(struct intel_crtc *intel_crtc,
1709 struct intel_crtc_state *crtc_state, int clock,
1710 struct bxt_clk_div *clk_div)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001711{
Durgadoss Ra277ca72016-09-01 15:08:09 -07001712 struct dpll best_clock;
1713
1714 /* Calculate HDMI div */
1715 /*
1716 * FIXME: tie the following calculation into
1717 * i9xx_crtc_compute_clock
1718 */
1719 if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
1720 DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1721 clock, pipe_name(intel_crtc->pipe));
1722 return false;
1723 }
1724
1725 clk_div->p1 = best_clock.p1;
1726 clk_div->p2 = best_clock.p2;
1727 WARN_ON(best_clock.m1 != 2);
1728 clk_div->n = best_clock.n;
1729 clk_div->m2_int = best_clock.m2 >> 22;
1730 clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
1731 clk_div->m2_frac_en = clk_div->m2_frac != 0;
1732
1733 clk_div->vco = best_clock.vco;
1734
1735 return true;
1736}
1737
1738static void bxt_ddi_dp_pll_dividers(int clock, struct bxt_clk_div *clk_div)
1739{
1740 int i;
1741
1742 *clk_div = bxt_dp_clk_val[0];
1743 for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1744 if (bxt_dp_clk_val[i].clock == clock) {
1745 *clk_div = bxt_dp_clk_val[i];
1746 break;
1747 }
1748 }
1749
1750 clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
1751}
1752
1753static bool bxt_ddi_set_dpll_hw_state(int clock,
1754 struct bxt_clk_div *clk_div,
1755 struct intel_dpll_hw_state *dpll_hw_state)
1756{
1757 int vco = clk_div->vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001758 uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
1759 uint32_t lanestagger;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001760
1761 if (vco >= 6200000 && vco <= 6700000) {
1762 prop_coef = 4;
1763 int_coef = 9;
1764 gain_ctl = 3;
1765 targ_cnt = 8;
1766 } else if ((vco > 5400000 && vco < 6200000) ||
1767 (vco >= 4800000 && vco < 5400000)) {
1768 prop_coef = 5;
1769 int_coef = 11;
1770 gain_ctl = 3;
1771 targ_cnt = 9;
1772 } else if (vco == 5400000) {
1773 prop_coef = 3;
1774 int_coef = 8;
1775 gain_ctl = 1;
1776 targ_cnt = 9;
1777 } else {
1778 DRM_ERROR("Invalid VCO\n");
Durgadoss Ra277ca72016-09-01 15:08:09 -07001779 return false;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001780 }
1781
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001782 if (clock > 270000)
1783 lanestagger = 0x18;
1784 else if (clock > 135000)
1785 lanestagger = 0x0d;
1786 else if (clock > 67000)
1787 lanestagger = 0x07;
1788 else if (clock > 33000)
1789 lanestagger = 0x04;
1790 else
1791 lanestagger = 0x02;
1792
Durgadoss Ra277ca72016-09-01 15:08:09 -07001793 dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
1794 dpll_hw_state->pll0 = clk_div->m2_int;
1795 dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
1796 dpll_hw_state->pll2 = clk_div->m2_frac;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001797
Durgadoss Ra277ca72016-09-01 15:08:09 -07001798 if (clk_div->m2_frac_en)
1799 dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001800
Durgadoss Ra277ca72016-09-01 15:08:09 -07001801 dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
1802 dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001803
Durgadoss Ra277ca72016-09-01 15:08:09 -07001804 dpll_hw_state->pll8 = targ_cnt;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001805
Durgadoss Ra277ca72016-09-01 15:08:09 -07001806 dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001807
Durgadoss Ra277ca72016-09-01 15:08:09 -07001808 dpll_hw_state->pll10 =
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001809 PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1810 | PORT_PLL_DCO_AMP_OVR_EN_H;
1811
Durgadoss Ra277ca72016-09-01 15:08:09 -07001812 dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001813
Durgadoss Ra277ca72016-09-01 15:08:09 -07001814 dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger;
1815
1816 return true;
1817}
1818
1819bool bxt_ddi_dp_set_dpll_hw_state(int clock,
1820 struct intel_dpll_hw_state *dpll_hw_state)
1821{
1822 struct bxt_clk_div clk_div = {0};
1823
1824 bxt_ddi_dp_pll_dividers(clock, &clk_div);
1825
1826 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1827}
1828
Imre Deaka04139c2016-09-26 17:54:31 +03001829static bool
1830bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc *intel_crtc,
1831 struct intel_crtc_state *crtc_state, int clock,
1832 struct intel_dpll_hw_state *dpll_hw_state)
1833{
1834 struct bxt_clk_div clk_div = { };
1835
1836 bxt_ddi_hdmi_pll_dividers(intel_crtc, crtc_state, clock, &clk_div);
1837
1838 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1839}
1840
Durgadoss Ra277ca72016-09-01 15:08:09 -07001841static struct intel_shared_dpll *
1842bxt_get_dpll(struct intel_crtc *crtc,
1843 struct intel_crtc_state *crtc_state,
1844 struct intel_encoder *encoder)
1845{
Imre Deaka04139c2016-09-26 17:54:31 +03001846 struct intel_dpll_hw_state dpll_hw_state = { };
Durgadoss Ra277ca72016-09-01 15:08:09 -07001847 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1848 struct intel_digital_port *intel_dig_port;
1849 struct intel_shared_dpll *pll;
1850 int i, clock = crtc_state->port_clock;
1851
Imre Deaka04139c2016-09-26 17:54:31 +03001852 if (encoder->type == INTEL_OUTPUT_HDMI &&
1853 !bxt_ddi_hdmi_set_dpll_hw_state(crtc, crtc_state, clock,
1854 &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001855 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001856
1857 if ((encoder->type == INTEL_OUTPUT_DP ||
Lee, Shawn C0aab2c72017-02-03 12:32:09 +08001858 encoder->type == INTEL_OUTPUT_EDP ||
1859 encoder->type == INTEL_OUTPUT_DP_MST) &&
Durgadoss Ra277ca72016-09-01 15:08:09 -07001860 !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001861 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001862
1863 memset(&crtc_state->dpll_hw_state, 0,
1864 sizeof(crtc_state->dpll_hw_state));
1865
1866 crtc_state->dpll_hw_state = dpll_hw_state;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001867
Maarten Lankhorsta79e8cc2016-08-09 17:04:00 +02001868 if (encoder->type == INTEL_OUTPUT_DP_MST) {
1869 struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
1870
1871 intel_dig_port = intel_mst->primary;
1872 } else
1873 intel_dig_port = enc_to_dig_port(&encoder->base);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001874
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001875 /* 1:1 mapping between ports and PLLs */
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001876 i = (enum intel_dpll_id) intel_dig_port->port;
1877 pll = intel_get_shared_dpll_by_id(dev_priv, i);
1878
Ville Syrjälä78108b72016-05-27 20:59:19 +03001879 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
1880 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001881
1882 intel_reference_shared_dpll(pll, crtc_state);
1883
1884 return pll;
1885}
1886
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001887static void bxt_dump_hw_state(struct drm_i915_private *dev_priv,
1888 struct intel_dpll_hw_state *hw_state)
1889{
1890 DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
1891 "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, "
1892 "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n",
1893 hw_state->ebb0,
1894 hw_state->ebb4,
1895 hw_state->pll0,
1896 hw_state->pll1,
1897 hw_state->pll2,
1898 hw_state->pll3,
1899 hw_state->pll6,
1900 hw_state->pll8,
1901 hw_state->pll9,
1902 hw_state->pll10,
1903 hw_state->pcsdw12);
1904}
1905
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001906static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1907 .enable = bxt_ddi_pll_enable,
1908 .disable = bxt_ddi_pll_disable,
1909 .get_hw_state = bxt_ddi_pll_get_hw_state,
1910};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001911
1912static void intel_ddi_pll_init(struct drm_device *dev)
1913{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001914 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001915
Ville Syrjälä9f7eb312016-05-13 23:41:29 +03001916 if (INTEL_GEN(dev_priv) < 9) {
1917 uint32_t val = I915_READ(LCPLL_CTL);
Ville Syrjäläb2045352016-05-13 23:41:27 +03001918
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001919 /*
1920 * The LCPLL register should be turned on by the BIOS. For now
1921 * let's just check its state and print errors in case
1922 * something is wrong. Don't even try to turn it on.
1923 */
1924
1925 if (val & LCPLL_CD_SOURCE_FCLK)
1926 DRM_ERROR("CDCLK source is not LCPLL\n");
1927
1928 if (val & LCPLL_PLL_DISABLE)
1929 DRM_ERROR("LCPLL is disabled\n");
1930 }
1931}
1932
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001933struct dpll_info {
1934 const char *name;
1935 const int id;
1936 const struct intel_shared_dpll_funcs *funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001937 uint32_t flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001938};
1939
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001940struct intel_dpll_mgr {
1941 const struct dpll_info *dpll_info;
1942
1943 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001944 struct intel_crtc_state *crtc_state,
1945 struct intel_encoder *encoder);
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001946
1947 void (*dump_hw_state)(struct drm_i915_private *dev_priv,
1948 struct intel_dpll_hw_state *hw_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001949};
1950
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001951static const struct dpll_info pch_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001952 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
1953 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
1954 { NULL, -1, NULL, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001955};
1956
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001957static const struct intel_dpll_mgr pch_pll_mgr = {
1958 .dpll_info = pch_plls,
1959 .get_dpll = ibx_get_dpll,
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001960 .dump_hw_state = ibx_dump_hw_state,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001961};
1962
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001963static const struct dpll_info hsw_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001964 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 },
1965 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 },
1966 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 },
1967 { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1968 { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1969 { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001970 { NULL, -1, NULL, },
1971};
1972
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001973static const struct intel_dpll_mgr hsw_pll_mgr = {
1974 .dpll_info = hsw_plls,
1975 .get_dpll = hsw_get_dpll,
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001976 .dump_hw_state = hsw_dump_hw_state,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001977};
1978
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001979static const struct dpll_info skl_plls[] = {
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001980 { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
Ville Syrjäläd5aab9d2016-05-11 22:04:33 +03001981 { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
1982 { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
1983 { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001984 { NULL, -1, NULL, },
1985};
1986
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001987static const struct intel_dpll_mgr skl_pll_mgr = {
1988 .dpll_info = skl_plls,
1989 .get_dpll = skl_get_dpll,
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001990 .dump_hw_state = skl_dump_hw_state,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001991};
1992
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001993static const struct dpll_info bxt_plls[] = {
Imre Deak08250c42016-03-14 19:55:34 +02001994 { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
1995 { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
1996 { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001997 { NULL, -1, NULL, },
1998};
1999
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002000static const struct intel_dpll_mgr bxt_pll_mgr = {
2001 .dpll_info = bxt_plls,
2002 .get_dpll = bxt_get_dpll,
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02002003 .dump_hw_state = bxt_dump_hw_state,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002004};
2005
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +02002006/**
2007 * intel_shared_dpll_init - Initialize shared DPLLs
2008 * @dev: drm device
2009 *
2010 * Initialize shared DPLLs for @dev.
2011 */
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02002012void intel_shared_dpll_init(struct drm_device *dev)
2013{
Chris Wilsonfac5e232016-07-04 11:34:36 +01002014 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002015 const struct intel_dpll_mgr *dpll_mgr = NULL;
2016 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002017 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02002018
Rodrigo Vivib976dc52017-01-23 10:32:37 -08002019 if (IS_GEN9_BC(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002020 dpll_mgr = &skl_pll_mgr;
Ander Conselvan de Oliveiracc3f90f2016-12-02 10:23:49 +02002021 else if (IS_GEN9_LP(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002022 dpll_mgr = &bxt_pll_mgr;
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01002023 else if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002024 dpll_mgr = &hsw_pll_mgr;
Tvrtko Ursulin6e266952016-10-13 11:02:53 +01002025 else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002026 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002027
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002028 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02002029 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002030 return;
2031 }
2032
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002033 dpll_info = dpll_mgr->dpll_info;
2034
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002035 for (i = 0; dpll_info[i].id >= 0; i++) {
2036 WARN_ON(i != dpll_info[i].id);
2037
2038 dev_priv->shared_dplls[i].id = dpll_info[i].id;
2039 dev_priv->shared_dplls[i].name = dpll_info[i].name;
2040 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02002041 dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002042 }
2043
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002044 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002045 dev_priv->num_shared_dpll = i;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +01002046 mutex_init(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02002047
2048 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002049
2050 /* FIXME: Move this to a more suitable place */
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01002051 if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002052 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02002053}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002054
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +02002055/**
2056 * intel_get_shared_dpll - get a shared DPLL for CRTC and encoder combination
2057 * @crtc: CRTC
2058 * @crtc_state: atomic state for @crtc
2059 * @encoder: encoder
2060 *
2061 * Find an appropriate DPLL for the given CRTC and encoder combination. A
2062 * reference from the @crtc to the returned pll is registered in the atomic
2063 * state. That configuration is made effective by calling
2064 * intel_shared_dpll_swap_state(). The reference should be released by calling
2065 * intel_release_shared_dpll().
2066 *
2067 * Returns:
2068 * A shared DPLL to be used by @crtc and @encoder with the given @crtc_state.
2069 */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002070struct intel_shared_dpll *
2071intel_get_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02002072 struct intel_crtc_state *crtc_state,
2073 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002074{
2075 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2076 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
2077
2078 if (WARN_ON(!dpll_mgr))
2079 return NULL;
2080
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02002081 return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002082}
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002083
2084/**
2085 * intel_release_shared_dpll - end use of DPLL by CRTC in atomic state
2086 * @dpll: dpll in use by @crtc
2087 * @crtc: crtc
2088 * @state: atomic state
2089 *
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +02002090 * This function releases the reference from @crtc to @dpll from the
2091 * atomic @state. The new configuration is made effective by calling
2092 * intel_shared_dpll_swap_state().
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002093 */
2094void intel_release_shared_dpll(struct intel_shared_dpll *dpll,
2095 struct intel_crtc *crtc,
2096 struct drm_atomic_state *state)
2097{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02002098 struct intel_shared_dpll_state *shared_dpll_state;
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002099
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02002100 shared_dpll_state = intel_atomic_get_shared_dpll_state(state);
2101 shared_dpll_state[dpll->id].crtc_mask &= ~(1 << crtc->pipe);
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002102}
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02002103
2104/**
2105 * intel_shared_dpll_dump_hw_state - write hw_state to dmesg
2106 * @dev_priv: i915 drm device
2107 * @hw_state: hw state to be written to the log
2108 *
2109 * Write the relevant values in @hw_state to dmesg using DRM_DEBUG_KMS.
2110 */
2111void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
2112 struct intel_dpll_hw_state *hw_state)
2113{
2114 if (dev_priv->dpll_mgr) {
2115 dev_priv->dpll_mgr->dump_hw_state(dev_priv, hw_state);
2116 } else {
2117 /* fallback for platforms that don't use the shared dpll
2118 * infrastructure
2119 */
2120 DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
2121 "fp0: 0x%x, fp1: 0x%x\n",
2122 hw_state->dpll,
2123 hw_state->dpll_md,
2124 hw_state->fp0,
2125 hw_state->fp1);
2126 }
2127}