blob: 57d4271cba2ca9b83659a52bf6be5d9af5239b34 [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 Oliveira294591c2016-12-29 17:22:11 +020083/**
84 * intel_get_shared_dpll_by_id - get a DPLL given its id
85 * @dev_priv: i915 device instance
86 * @id: pll id
87 *
88 * Returns:
89 * A pointer to the DPLL with @id
90 */
Jim Bridef1696602016-09-07 15:47:34 -070091struct intel_shared_dpll *
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020092intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
93 enum intel_dpll_id id)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020094{
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020095 return &dev_priv->shared_dplls[id];
96}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020097
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +020098/**
99 * intel_get_shared_dpll_id - get the id of a DPLL
100 * @dev_priv: i915 device instance
101 * @pll: the DPLL
102 *
103 * Returns:
104 * The id of @pll
105 */
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200106enum intel_dpll_id
107intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
108 struct intel_shared_dpll *pll)
109{
110 if (WARN_ON(pll < dev_priv->shared_dplls||
111 pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll]))
112 return -1;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200113
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200114 return (enum intel_dpll_id) (pll - dev_priv->shared_dplls);
115}
116
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200117/* For ILK+ */
118void assert_shared_dpll(struct drm_i915_private *dev_priv,
119 struct intel_shared_dpll *pll,
120 bool state)
121{
122 bool cur_state;
123 struct intel_dpll_hw_state hw_state;
124
125 if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
126 return;
127
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200128 cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200129 I915_STATE_WARN(cur_state != state,
130 "%s assertion failure (expected %s, current %s)\n",
131 pll->name, onoff(state), onoff(cur_state));
132}
133
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200134/**
135 * intel_prepare_shared_dpll - call a dpll's prepare hook
136 * @crtc: CRTC which has a shared dpll
137 *
138 * This calls the PLL's prepare hook if it has one and if the PLL is not
139 * already enabled. The prepare hook is platform specific.
140 */
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200141void intel_prepare_shared_dpll(struct intel_crtc *crtc)
142{
143 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100144 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200145 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200146
147 if (WARN_ON(pll == NULL))
148 return;
149
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100150 mutex_lock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200151 WARN_ON(!pll->state.crtc_mask);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100152 if (!pll->active_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200153 DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
154 WARN_ON(pll->on);
155 assert_shared_dpll_disabled(dev_priv, pll);
156
Ander Conselvan de Oliveiraeac61762016-12-29 17:22:10 +0200157 pll->funcs.prepare(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200158 }
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100159 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200160}
161
162/**
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200163 * intel_enable_shared_dpll - enable a CRTC's shared DPLL
164 * @crtc: CRTC which has a shared DPLL
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200165 *
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200166 * Enable the shared DPLL used by @crtc.
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200167 */
168void intel_enable_shared_dpll(struct intel_crtc *crtc)
169{
170 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100171 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200172 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100173 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100174 unsigned old_mask;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200175
176 if (WARN_ON(pll == NULL))
177 return;
178
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100179 mutex_lock(&dev_priv->dpll_lock);
180 old_mask = pll->active_mask;
181
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200182 if (WARN_ON(!(pll->state.crtc_mask & crtc_mask)) ||
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100183 WARN_ON(pll->active_mask & crtc_mask))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100184 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200185
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100186 pll->active_mask |= crtc_mask;
187
188 DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n",
189 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200190 crtc->base.base.id);
191
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100192 if (old_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200193 WARN_ON(!pll->on);
194 assert_shared_dpll_enabled(dev_priv, pll);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100195 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200196 }
197 WARN_ON(pll->on);
198
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200199 DRM_DEBUG_KMS("enabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200200 pll->funcs.enable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200201 pll->on = true;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100202
203out:
204 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200205}
206
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200207/**
208 * intel_disable_shared_dpll - disable a CRTC's shared DPLL
209 * @crtc: CRTC which has a shared DPLL
210 *
211 * Disable the shared DPLL used by @crtc.
212 */
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200213void intel_disable_shared_dpll(struct intel_crtc *crtc)
214{
Tvrtko Ursulin66478472016-11-16 08:55:40 +0000215 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200216 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100217 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200218
219 /* PCH only available on ILK+ */
Tvrtko Ursulin66478472016-11-16 08:55:40 +0000220 if (INTEL_GEN(dev_priv) < 5)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200221 return;
222
223 if (pll == NULL)
224 return;
225
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100226 mutex_lock(&dev_priv->dpll_lock);
Maarten Lankhorsta1475e72016-03-14 09:27:53 +0100227 if (WARN_ON(!(pll->active_mask & crtc_mask)))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100228 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200229
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100230 DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
231 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200232 crtc->base.base.id);
233
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200234 assert_shared_dpll_enabled(dev_priv, pll);
235 WARN_ON(!pll->on);
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100236
237 pll->active_mask &= ~crtc_mask;
238 if (pll->active_mask)
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100239 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200240
241 DRM_DEBUG_KMS("disabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200242 pll->funcs.disable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200243 pll->on = false;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100244
245out:
246 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200247}
248
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200249static struct intel_shared_dpll *
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200250intel_find_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200251 struct intel_crtc_state *crtc_state,
252 enum intel_dpll_id range_min,
253 enum intel_dpll_id range_max)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200254{
Chris Wilsonfac5e232016-07-04 11:34:36 +0100255 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200256 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200257 struct intel_shared_dpll_state *shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200258 enum intel_dpll_id i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200259
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200260 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
261
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200262 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200263 pll = &dev_priv->shared_dplls[i];
264
265 /* Only want to check enabled timings first */
266 if (shared_dpll[i].crtc_mask == 0)
267 continue;
268
269 if (memcmp(&crtc_state->dpll_hw_state,
270 &shared_dpll[i].hw_state,
271 sizeof(crtc_state->dpll_hw_state)) == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300272 DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
273 crtc->base.base.id, crtc->base.name, pll->name,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200274 shared_dpll[i].crtc_mask,
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100275 pll->active_mask);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200276 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200277 }
278 }
279
280 /* Ok no matching timings, maybe there's a free one? */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200281 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200282 pll = &dev_priv->shared_dplls[i];
283 if (shared_dpll[i].crtc_mask == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300284 DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n",
285 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200286 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200287 }
288 }
289
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200290 return NULL;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200291}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200292
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200293static void
294intel_reference_shared_dpll(struct intel_shared_dpll *pll,
295 struct intel_crtc_state *crtc_state)
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200296{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200297 struct intel_shared_dpll_state *shared_dpll;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200298 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
299 enum intel_dpll_id i = pll->id;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200300
301 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
302
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200303 if (shared_dpll[i].crtc_mask == 0)
304 shared_dpll[i].hw_state =
305 crtc_state->dpll_hw_state;
306
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200307 crtc_state->shared_dpll = pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200308 DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
309 pipe_name(crtc->pipe));
310
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +0200311 shared_dpll[pll->id].crtc_mask |= 1 << crtc->pipe;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200312}
313
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +0200314/**
315 * intel_shared_dpll_swap_state - make atomic DPLL configuration effective
316 * @state: atomic state
317 *
318 * This is the dpll version of drm_atomic_helper_swap_state() since the
319 * helper does not handle driver-specific global state.
320 *
321 * For consistency with atomic helpers this function does a complete swap,
322 * i.e. it also puts the current state into @state, even though there is no
323 * need for that at this moment.
324 */
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200325void intel_shared_dpll_swap_state(struct drm_atomic_state *state)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200326{
327 struct drm_i915_private *dev_priv = to_i915(state->dev);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200328 struct intel_shared_dpll_state *shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200329 struct intel_shared_dpll *pll;
330 enum intel_dpll_id i;
331
332 if (!to_intel_atomic_state(state)->dpll_set)
333 return;
334
335 shared_dpll = to_intel_atomic_state(state)->shared_dpll;
336 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200337 struct intel_shared_dpll_state tmp;
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200338
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200339 pll = &dev_priv->shared_dplls[i];
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200340
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200341 tmp = pll->state;
342 pll->state = shared_dpll[i];
Ander Conselvan de Oliveira3c0fb582016-12-29 17:22:08 +0200343 shared_dpll[i] = tmp;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200344 }
345}
346
347static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
348 struct intel_shared_dpll *pll,
349 struct intel_dpll_hw_state *hw_state)
350{
351 uint32_t val;
352
353 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
354 return false;
355
356 val = I915_READ(PCH_DPLL(pll->id));
357 hw_state->dpll = val;
358 hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
359 hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
360
361 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
362
363 return val & DPLL_VCO_ENABLE;
364}
365
Ander Conselvan de Oliveiraeac61762016-12-29 17:22:10 +0200366static void ibx_pch_dpll_prepare(struct drm_i915_private *dev_priv,
367 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200368{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200369 I915_WRITE(PCH_FP0(pll->id), pll->state.hw_state.fp0);
370 I915_WRITE(PCH_FP1(pll->id), pll->state.hw_state.fp1);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200371}
372
373static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
374{
375 u32 val;
376 bool enabled;
377
Joonas Lahtinen2d1fe072016-04-07 11:08:05 +0300378 I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200379
380 val = I915_READ(PCH_DREF_CONTROL);
381 enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
382 DREF_SUPERSPREAD_SOURCE_MASK));
383 I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
384}
385
386static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
387 struct intel_shared_dpll *pll)
388{
389 /* PCH refclock must be enabled first */
390 ibx_assert_pch_refclk_enabled(dev_priv);
391
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200392 I915_WRITE(PCH_DPLL(pll->id), pll->state.hw_state.dpll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200393
394 /* Wait for the clocks to stabilize. */
395 POSTING_READ(PCH_DPLL(pll->id));
396 udelay(150);
397
398 /* The pixel multiplier can only be updated once the
399 * DPLL is enabled and the clocks are stable.
400 *
401 * So write it again.
402 */
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200403 I915_WRITE(PCH_DPLL(pll->id), pll->state.hw_state.dpll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200404 POSTING_READ(PCH_DPLL(pll->id));
405 udelay(200);
406}
407
408static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
409 struct intel_shared_dpll *pll)
410{
Chris Wilson91c8a322016-07-05 10:40:23 +0100411 struct drm_device *dev = &dev_priv->drm;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200412 struct intel_crtc *crtc;
413
414 /* Make sure no transcoder isn't still depending on us. */
415 for_each_intel_crtc(dev, crtc) {
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200416 if (crtc->config->shared_dpll == pll)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200417 assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
418 }
419
420 I915_WRITE(PCH_DPLL(pll->id), 0);
421 POSTING_READ(PCH_DPLL(pll->id));
422 udelay(200);
423}
424
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200425static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200426ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
427 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200428{
429 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
430 struct intel_shared_dpll *pll;
431 enum intel_dpll_id i;
432
433 if (HAS_PCH_IBX(dev_priv)) {
434 /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
435 i = (enum intel_dpll_id) crtc->pipe;
436 pll = &dev_priv->shared_dplls[i];
437
Ville Syrjälä78108b72016-05-27 20:59:19 +0300438 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
439 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200440 } else {
441 pll = intel_find_shared_dpll(crtc, crtc_state,
442 DPLL_ID_PCH_PLL_A,
443 DPLL_ID_PCH_PLL_B);
444 }
445
Ander Conselvan de Oliveirabb143162016-05-20 15:47:06 +0300446 if (!pll)
447 return NULL;
448
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200449 /* reference the pll */
450 intel_reference_shared_dpll(pll, crtc_state);
451
452 return pll;
453}
454
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +0200455static void ibx_dump_hw_state(struct drm_i915_private *dev_priv,
456 struct intel_dpll_hw_state *hw_state)
457{
458 DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
459 "fp0: 0x%x, fp1: 0x%x\n",
460 hw_state->dpll,
461 hw_state->dpll_md,
462 hw_state->fp0,
463 hw_state->fp1);
464}
465
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200466static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
Ander Conselvan de Oliveiraeac61762016-12-29 17:22:10 +0200467 .prepare = ibx_pch_dpll_prepare,
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200468 .enable = ibx_pch_dpll_enable,
469 .disable = ibx_pch_dpll_disable,
470 .get_hw_state = ibx_pch_dpll_get_hw_state,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200471};
472
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200473static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
474 struct intel_shared_dpll *pll)
475{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200476 I915_WRITE(WRPLL_CTL(pll->id), pll->state.hw_state.wrpll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200477 POSTING_READ(WRPLL_CTL(pll->id));
478 udelay(20);
479}
480
481static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
482 struct intel_shared_dpll *pll)
483{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200484 I915_WRITE(SPLL_CTL, pll->state.hw_state.spll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200485 POSTING_READ(SPLL_CTL);
486 udelay(20);
487}
488
489static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
490 struct intel_shared_dpll *pll)
491{
492 uint32_t val;
493
494 val = I915_READ(WRPLL_CTL(pll->id));
495 I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
496 POSTING_READ(WRPLL_CTL(pll->id));
497}
498
499static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
500 struct intel_shared_dpll *pll)
501{
502 uint32_t val;
503
504 val = I915_READ(SPLL_CTL);
505 I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
506 POSTING_READ(SPLL_CTL);
507}
508
509static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
510 struct intel_shared_dpll *pll,
511 struct intel_dpll_hw_state *hw_state)
512{
513 uint32_t val;
514
515 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
516 return false;
517
518 val = I915_READ(WRPLL_CTL(pll->id));
519 hw_state->wrpll = val;
520
521 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
522
523 return val & WRPLL_PLL_ENABLE;
524}
525
526static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
527 struct intel_shared_dpll *pll,
528 struct intel_dpll_hw_state *hw_state)
529{
530 uint32_t val;
531
532 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
533 return false;
534
535 val = I915_READ(SPLL_CTL);
536 hw_state->spll = val;
537
538 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
539
540 return val & SPLL_PLL_ENABLE;
541}
542
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200543#define LC_FREQ 2700
544#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
545
546#define P_MIN 2
547#define P_MAX 64
548#define P_INC 2
549
550/* Constraints for PLL good behavior */
551#define REF_MIN 48
552#define REF_MAX 400
553#define VCO_MIN 2400
554#define VCO_MAX 4800
555
556struct hsw_wrpll_rnp {
557 unsigned p, n2, r2;
558};
559
560static unsigned hsw_wrpll_get_budget_for_freq(int clock)
561{
562 unsigned budget;
563
564 switch (clock) {
565 case 25175000:
566 case 25200000:
567 case 27000000:
568 case 27027000:
569 case 37762500:
570 case 37800000:
571 case 40500000:
572 case 40541000:
573 case 54000000:
574 case 54054000:
575 case 59341000:
576 case 59400000:
577 case 72000000:
578 case 74176000:
579 case 74250000:
580 case 81000000:
581 case 81081000:
582 case 89012000:
583 case 89100000:
584 case 108000000:
585 case 108108000:
586 case 111264000:
587 case 111375000:
588 case 148352000:
589 case 148500000:
590 case 162000000:
591 case 162162000:
592 case 222525000:
593 case 222750000:
594 case 296703000:
595 case 297000000:
596 budget = 0;
597 break;
598 case 233500000:
599 case 245250000:
600 case 247750000:
601 case 253250000:
602 case 298000000:
603 budget = 1500;
604 break;
605 case 169128000:
606 case 169500000:
607 case 179500000:
608 case 202000000:
609 budget = 2000;
610 break;
611 case 256250000:
612 case 262500000:
613 case 270000000:
614 case 272500000:
615 case 273750000:
616 case 280750000:
617 case 281250000:
618 case 286000000:
619 case 291750000:
620 budget = 4000;
621 break;
622 case 267250000:
623 case 268500000:
624 budget = 5000;
625 break;
626 default:
627 budget = 1000;
628 break;
629 }
630
631 return budget;
632}
633
634static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
635 unsigned r2, unsigned n2, unsigned p,
636 struct hsw_wrpll_rnp *best)
637{
638 uint64_t a, b, c, d, diff, diff_best;
639
640 /* No best (r,n,p) yet */
641 if (best->p == 0) {
642 best->p = p;
643 best->n2 = n2;
644 best->r2 = r2;
645 return;
646 }
647
648 /*
649 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
650 * freq2k.
651 *
652 * delta = 1e6 *
653 * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
654 * freq2k;
655 *
656 * and we would like delta <= budget.
657 *
658 * If the discrepancy is above the PPM-based budget, always prefer to
659 * improve upon the previous solution. However, if you're within the
660 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
661 */
662 a = freq2k * budget * p * r2;
663 b = freq2k * budget * best->p * best->r2;
664 diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
665 diff_best = abs_diff(freq2k * best->p * best->r2,
666 LC_FREQ_2K * best->n2);
667 c = 1000000 * diff;
668 d = 1000000 * diff_best;
669
670 if (a < c && b < d) {
671 /* If both are above the budget, pick the closer */
672 if (best->p * best->r2 * diff < p * r2 * diff_best) {
673 best->p = p;
674 best->n2 = n2;
675 best->r2 = r2;
676 }
677 } else if (a >= c && b < d) {
678 /* If A is below the threshold but B is above it? Update. */
679 best->p = p;
680 best->n2 = n2;
681 best->r2 = r2;
682 } else if (a >= c && b >= d) {
683 /* Both are below the limit, so pick the higher n2/(r2*r2) */
684 if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
685 best->p = p;
686 best->n2 = n2;
687 best->r2 = r2;
688 }
689 }
690 /* Otherwise a < c && b >= d, do nothing */
691}
692
693static void
694hsw_ddi_calculate_wrpll(int clock /* in Hz */,
695 unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
696{
697 uint64_t freq2k;
698 unsigned p, n2, r2;
699 struct hsw_wrpll_rnp best = { 0, 0, 0 };
700 unsigned budget;
701
702 freq2k = clock / 100;
703
704 budget = hsw_wrpll_get_budget_for_freq(clock);
705
706 /* Special case handling for 540 pixel clock: bypass WR PLL entirely
707 * and directly pass the LC PLL to it. */
708 if (freq2k == 5400000) {
709 *n2_out = 2;
710 *p_out = 1;
711 *r2_out = 2;
712 return;
713 }
714
715 /*
716 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
717 * the WR PLL.
718 *
719 * We want R so that REF_MIN <= Ref <= REF_MAX.
720 * Injecting R2 = 2 * R gives:
721 * REF_MAX * r2 > LC_FREQ * 2 and
722 * REF_MIN * r2 < LC_FREQ * 2
723 *
724 * Which means the desired boundaries for r2 are:
725 * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
726 *
727 */
728 for (r2 = LC_FREQ * 2 / REF_MAX + 1;
729 r2 <= LC_FREQ * 2 / REF_MIN;
730 r2++) {
731
732 /*
733 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
734 *
735 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
736 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
737 * VCO_MAX * r2 > n2 * LC_FREQ and
738 * VCO_MIN * r2 < n2 * LC_FREQ)
739 *
740 * Which means the desired boundaries for n2 are:
741 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
742 */
743 for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
744 n2 <= VCO_MAX * r2 / LC_FREQ;
745 n2++) {
746
747 for (p = P_MIN; p <= P_MAX; p += P_INC)
748 hsw_wrpll_update_rnp(freq2k, budget,
749 r2, n2, p, &best);
750 }
751 }
752
753 *n2_out = best.n2;
754 *p_out = best.p;
755 *r2_out = best.r2;
756}
757
Manasi Navare81b9fd82016-09-01 15:08:11 -0700758static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(int clock,
759 struct intel_crtc *crtc,
760 struct intel_crtc_state *crtc_state)
761{
762 struct intel_shared_dpll *pll;
763 uint32_t val;
764 unsigned int p, n2, r2;
765
766 hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
767
768 val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
769 WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
770 WRPLL_DIVIDER_POST(p);
771
772 crtc_state->dpll_hw_state.wrpll = val;
773
774 pll = intel_find_shared_dpll(crtc, crtc_state,
775 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
776
777 if (!pll)
778 return NULL;
779
780 return pll;
781}
782
783struct intel_shared_dpll *hsw_ddi_dp_get_dpll(struct intel_encoder *encoder,
784 int clock)
785{
786 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
787 struct intel_shared_dpll *pll;
788 enum intel_dpll_id pll_id;
789
790 switch (clock / 2) {
791 case 81000:
792 pll_id = DPLL_ID_LCPLL_810;
793 break;
794 case 135000:
795 pll_id = DPLL_ID_LCPLL_1350;
796 break;
797 case 270000:
798 pll_id = DPLL_ID_LCPLL_2700;
799 break;
800 default:
801 DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
802 return NULL;
803 }
804
805 pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
806
807 if (!pll)
808 return NULL;
809
810 return pll;
811}
812
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200813static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200814hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
815 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200816{
817 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200818 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200819
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200820 memset(&crtc_state->dpll_hw_state, 0,
821 sizeof(crtc_state->dpll_hw_state));
822
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200823 if (encoder->type == INTEL_OUTPUT_HDMI) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700824 pll = hsw_ddi_hdmi_get_dpll(clock, crtc, crtc_state);
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200825
Ville Syrjäläcca05022016-06-22 21:57:06 +0300826 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200827 encoder->type == INTEL_OUTPUT_DP_MST ||
828 encoder->type == INTEL_OUTPUT_EDP) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700829 pll = hsw_ddi_dp_get_dpll(encoder, clock);
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200830
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200831 } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
832 if (WARN_ON(crtc_state->port_clock / 2 != 135000))
833 return NULL;
834
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200835 crtc_state->dpll_hw_state.spll =
836 SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
837
838 pll = intel_find_shared_dpll(crtc, crtc_state,
839 DPLL_ID_SPLL, DPLL_ID_SPLL);
840 } else {
841 return NULL;
842 }
843
844 if (!pll)
845 return NULL;
846
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200847 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200848
849 return pll;
850}
851
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +0200852static void hsw_dump_hw_state(struct drm_i915_private *dev_priv,
853 struct intel_dpll_hw_state *hw_state)
854{
855 DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
856 hw_state->wrpll, hw_state->spll);
857}
858
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200859static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
860 .enable = hsw_ddi_wrpll_enable,
861 .disable = hsw_ddi_wrpll_disable,
862 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200863};
864
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200865static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
866 .enable = hsw_ddi_spll_enable,
867 .disable = hsw_ddi_spll_disable,
868 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200869};
870
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200871static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
872 struct intel_shared_dpll *pll)
873{
874}
875
876static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
877 struct intel_shared_dpll *pll)
878{
879}
880
881static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
882 struct intel_shared_dpll *pll,
883 struct intel_dpll_hw_state *hw_state)
884{
885 return true;
886}
887
888static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
889 .enable = hsw_ddi_lcpll_enable,
890 .disable = hsw_ddi_lcpll_disable,
891 .get_hw_state = hsw_ddi_lcpll_get_hw_state,
892};
893
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200894struct skl_dpll_regs {
895 i915_reg_t ctl, cfgcr1, cfgcr2;
896};
897
898/* this array is indexed by the *shared* pll id */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200899static const struct skl_dpll_regs skl_dpll_regs[4] = {
900 {
901 /* DPLL 0 */
902 .ctl = LCPLL1_CTL,
903 /* DPLL 0 doesn't support HDMI mode */
904 },
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200905 {
906 /* DPLL 1 */
907 .ctl = LCPLL2_CTL,
908 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
909 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
910 },
911 {
912 /* DPLL 2 */
913 .ctl = WRPLL_CTL(0),
914 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
915 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
916 },
917 {
918 /* DPLL 3 */
919 .ctl = WRPLL_CTL(1),
920 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
921 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
922 },
923};
924
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200925static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
926 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200927{
928 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200929
930 val = I915_READ(DPLL_CTRL1);
931
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200932 val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
933 DPLL_CTRL1_LINK_RATE_MASK(pll->id));
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200934 val |= pll->state.hw_state.ctrl1 << (pll->id * 6);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200935
936 I915_WRITE(DPLL_CTRL1, val);
937 POSTING_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200938}
939
940static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
941 struct intel_shared_dpll *pll)
942{
943 const struct skl_dpll_regs *regs = skl_dpll_regs;
944
945 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200946
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200947 I915_WRITE(regs[pll->id].cfgcr1, pll->state.hw_state.cfgcr1);
948 I915_WRITE(regs[pll->id].cfgcr2, pll->state.hw_state.cfgcr2);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200949 POSTING_READ(regs[pll->id].cfgcr1);
950 POSTING_READ(regs[pll->id].cfgcr2);
951
952 /* the enable bit is always bit 31 */
953 I915_WRITE(regs[pll->id].ctl,
954 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
955
Chris Wilson27bf23a2016-06-30 15:33:12 +0100956 if (intel_wait_for_register(dev_priv,
957 DPLL_STATUS,
958 DPLL_LOCK(pll->id),
959 DPLL_LOCK(pll->id),
960 5))
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200961 DRM_ERROR("DPLL %d not locked\n", pll->id);
962}
963
964static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
965 struct intel_shared_dpll *pll)
966{
967 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200968}
969
970static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
971 struct intel_shared_dpll *pll)
972{
973 const struct skl_dpll_regs *regs = skl_dpll_regs;
974
975 /* the enable bit is always bit 31 */
976 I915_WRITE(regs[pll->id].ctl,
977 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
978 POSTING_READ(regs[pll->id].ctl);
979}
980
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200981static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
982 struct intel_shared_dpll *pll)
983{
984}
985
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200986static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
987 struct intel_shared_dpll *pll,
988 struct intel_dpll_hw_state *hw_state)
989{
990 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200991 const struct skl_dpll_regs *regs = skl_dpll_regs;
992 bool ret;
993
994 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
995 return false;
996
997 ret = false;
998
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200999 val = I915_READ(regs[pll->id].ctl);
1000 if (!(val & LCPLL_PLL_ENABLE))
1001 goto out;
1002
1003 val = I915_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001004 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001005
1006 /* avoid reading back stale values if HDMI mode is not enabled */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001007 if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001008 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
1009 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
1010 }
1011 ret = true;
1012
1013out:
1014 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1015
1016 return ret;
1017}
1018
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001019static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
1020 struct intel_shared_dpll *pll,
1021 struct intel_dpll_hw_state *hw_state)
1022{
1023 uint32_t val;
1024 const struct skl_dpll_regs *regs = skl_dpll_regs;
1025 bool ret;
1026
1027 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1028 return false;
1029
1030 ret = false;
1031
1032 /* DPLL0 is always enabled since it drives CDCLK */
1033 val = I915_READ(regs[pll->id].ctl);
1034 if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
1035 goto out;
1036
1037 val = I915_READ(DPLL_CTRL1);
1038 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
1039
1040 ret = true;
1041
1042out:
1043 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1044
1045 return ret;
1046}
1047
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001048struct skl_wrpll_context {
1049 uint64_t min_deviation; /* current minimal deviation */
1050 uint64_t central_freq; /* chosen central freq */
1051 uint64_t dco_freq; /* chosen dco freq */
1052 unsigned int p; /* chosen divider */
1053};
1054
1055static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
1056{
1057 memset(ctx, 0, sizeof(*ctx));
1058
1059 ctx->min_deviation = U64_MAX;
1060}
1061
1062/* DCO freq must be within +1%/-6% of the DCO central freq */
1063#define SKL_DCO_MAX_PDEVIATION 100
1064#define SKL_DCO_MAX_NDEVIATION 600
1065
1066static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
1067 uint64_t central_freq,
1068 uint64_t dco_freq,
1069 unsigned int divider)
1070{
1071 uint64_t deviation;
1072
1073 deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
1074 central_freq);
1075
1076 /* positive deviation */
1077 if (dco_freq >= central_freq) {
1078 if (deviation < SKL_DCO_MAX_PDEVIATION &&
1079 deviation < ctx->min_deviation) {
1080 ctx->min_deviation = deviation;
1081 ctx->central_freq = central_freq;
1082 ctx->dco_freq = dco_freq;
1083 ctx->p = divider;
1084 }
1085 /* negative deviation */
1086 } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
1087 deviation < ctx->min_deviation) {
1088 ctx->min_deviation = deviation;
1089 ctx->central_freq = central_freq;
1090 ctx->dco_freq = dco_freq;
1091 ctx->p = divider;
1092 }
1093}
1094
1095static void skl_wrpll_get_multipliers(unsigned int p,
1096 unsigned int *p0 /* out */,
1097 unsigned int *p1 /* out */,
1098 unsigned int *p2 /* out */)
1099{
1100 /* even dividers */
1101 if (p % 2 == 0) {
1102 unsigned int half = p / 2;
1103
1104 if (half == 1 || half == 2 || half == 3 || half == 5) {
1105 *p0 = 2;
1106 *p1 = 1;
1107 *p2 = half;
1108 } else if (half % 2 == 0) {
1109 *p0 = 2;
1110 *p1 = half / 2;
1111 *p2 = 2;
1112 } else if (half % 3 == 0) {
1113 *p0 = 3;
1114 *p1 = half / 3;
1115 *p2 = 2;
1116 } else if (half % 7 == 0) {
1117 *p0 = 7;
1118 *p1 = half / 7;
1119 *p2 = 2;
1120 }
1121 } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
1122 *p0 = 3;
1123 *p1 = 1;
1124 *p2 = p / 3;
1125 } else if (p == 5 || p == 7) {
1126 *p0 = p;
1127 *p1 = 1;
1128 *p2 = 1;
1129 } else if (p == 15) {
1130 *p0 = 3;
1131 *p1 = 1;
1132 *p2 = 5;
1133 } else if (p == 21) {
1134 *p0 = 7;
1135 *p1 = 1;
1136 *p2 = 3;
1137 } else if (p == 35) {
1138 *p0 = 7;
1139 *p1 = 1;
1140 *p2 = 5;
1141 }
1142}
1143
1144struct skl_wrpll_params {
1145 uint32_t dco_fraction;
1146 uint32_t dco_integer;
1147 uint32_t qdiv_ratio;
1148 uint32_t qdiv_mode;
1149 uint32_t kdiv;
1150 uint32_t pdiv;
1151 uint32_t central_freq;
1152};
1153
1154static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
1155 uint64_t afe_clock,
1156 uint64_t central_freq,
1157 uint32_t p0, uint32_t p1, uint32_t p2)
1158{
1159 uint64_t dco_freq;
1160
1161 switch (central_freq) {
1162 case 9600000000ULL:
1163 params->central_freq = 0;
1164 break;
1165 case 9000000000ULL:
1166 params->central_freq = 1;
1167 break;
1168 case 8400000000ULL:
1169 params->central_freq = 3;
1170 }
1171
1172 switch (p0) {
1173 case 1:
1174 params->pdiv = 0;
1175 break;
1176 case 2:
1177 params->pdiv = 1;
1178 break;
1179 case 3:
1180 params->pdiv = 2;
1181 break;
1182 case 7:
1183 params->pdiv = 4;
1184 break;
1185 default:
1186 WARN(1, "Incorrect PDiv\n");
1187 }
1188
1189 switch (p2) {
1190 case 5:
1191 params->kdiv = 0;
1192 break;
1193 case 2:
1194 params->kdiv = 1;
1195 break;
1196 case 3:
1197 params->kdiv = 2;
1198 break;
1199 case 1:
1200 params->kdiv = 3;
1201 break;
1202 default:
1203 WARN(1, "Incorrect KDiv\n");
1204 }
1205
1206 params->qdiv_ratio = p1;
1207 params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1208
1209 dco_freq = p0 * p1 * p2 * afe_clock;
1210
1211 /*
1212 * Intermediate values are in Hz.
1213 * Divide by MHz to match bsepc
1214 */
1215 params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1216 params->dco_fraction =
1217 div_u64((div_u64(dco_freq, 24) -
1218 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1219}
1220
1221static bool
1222skl_ddi_calculate_wrpll(int clock /* in Hz */,
1223 struct skl_wrpll_params *wrpll_params)
1224{
1225 uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1226 uint64_t dco_central_freq[3] = {8400000000ULL,
1227 9000000000ULL,
1228 9600000000ULL};
1229 static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1230 24, 28, 30, 32, 36, 40, 42, 44,
1231 48, 52, 54, 56, 60, 64, 66, 68,
1232 70, 72, 76, 78, 80, 84, 88, 90,
1233 92, 96, 98 };
1234 static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1235 static const struct {
1236 const int *list;
1237 int n_dividers;
1238 } dividers[] = {
1239 { even_dividers, ARRAY_SIZE(even_dividers) },
1240 { odd_dividers, ARRAY_SIZE(odd_dividers) },
1241 };
1242 struct skl_wrpll_context ctx;
1243 unsigned int dco, d, i;
1244 unsigned int p0, p1, p2;
1245
1246 skl_wrpll_context_init(&ctx);
1247
1248 for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1249 for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1250 for (i = 0; i < dividers[d].n_dividers; i++) {
1251 unsigned int p = dividers[d].list[i];
1252 uint64_t dco_freq = p * afe_clock;
1253
1254 skl_wrpll_try_divider(&ctx,
1255 dco_central_freq[dco],
1256 dco_freq,
1257 p);
1258 /*
1259 * Skip the remaining dividers if we're sure to
1260 * have found the definitive divider, we can't
1261 * improve a 0 deviation.
1262 */
1263 if (ctx.min_deviation == 0)
1264 goto skip_remaining_dividers;
1265 }
1266 }
1267
1268skip_remaining_dividers:
1269 /*
1270 * If a solution is found with an even divider, prefer
1271 * this one.
1272 */
1273 if (d == 0 && ctx.p)
1274 break;
1275 }
1276
1277 if (!ctx.p) {
1278 DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1279 return false;
1280 }
1281
1282 /*
1283 * gcc incorrectly analyses that these can be used without being
1284 * initialized. To be fair, it's hard to guess.
1285 */
1286 p0 = p1 = p2 = 0;
1287 skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1288 skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1289 p0, p1, p2);
1290
1291 return true;
1292}
1293
Jim Bride9a4edad2016-09-01 15:08:10 -07001294static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
1295 struct intel_crtc_state *crtc_state,
1296 int clock)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001297{
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001298 uint32_t ctrl1, cfgcr1, cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001299 struct skl_wrpll_params wrpll_params = { 0, };
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001300
1301 /*
1302 * See comment in intel_dpll_hw_state to understand why we always use 0
1303 * as the DPLL id in this function.
1304 */
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001305 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1306
Jim Bride9a4edad2016-09-01 15:08:10 -07001307 ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001308
Jim Bride9a4edad2016-09-01 15:08:10 -07001309 if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
1310 return false;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001311
Jim Bride9a4edad2016-09-01 15:08:10 -07001312 cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1313 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1314 wrpll_params.dco_integer;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001315
Jim Bride9a4edad2016-09-01 15:08:10 -07001316 cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1317 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1318 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1319 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1320 wrpll_params.central_freq;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001321
1322 memset(&crtc_state->dpll_hw_state, 0,
1323 sizeof(crtc_state->dpll_hw_state));
1324
1325 crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1326 crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1327 crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001328 return true;
1329}
1330
1331
1332bool skl_ddi_dp_set_dpll_hw_state(int clock,
1333 struct intel_dpll_hw_state *dpll_hw_state)
1334{
1335 uint32_t ctrl1;
1336
1337 /*
1338 * See comment in intel_dpll_hw_state to understand why we always use 0
1339 * as the DPLL id in this function.
1340 */
1341 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1342 switch (clock / 2) {
1343 case 81000:
1344 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1345 break;
1346 case 135000:
1347 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1348 break;
1349 case 270000:
1350 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1351 break;
1352 /* eDP 1.4 rates */
1353 case 162000:
1354 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
1355 break;
1356 case 108000:
1357 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
1358 break;
1359 case 216000:
1360 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
1361 break;
1362 }
1363
1364 dpll_hw_state->ctrl1 = ctrl1;
1365 return true;
1366}
1367
1368static struct intel_shared_dpll *
1369skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1370 struct intel_encoder *encoder)
1371{
1372 struct intel_shared_dpll *pll;
1373 int clock = crtc_state->port_clock;
1374 bool bret;
1375 struct intel_dpll_hw_state dpll_hw_state;
1376
1377 memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
1378
1379 if (encoder->type == INTEL_OUTPUT_HDMI) {
1380 bret = skl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock);
1381 if (!bret) {
1382 DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n");
1383 return NULL;
1384 }
1385 } else if (encoder->type == INTEL_OUTPUT_DP ||
1386 encoder->type == INTEL_OUTPUT_DP_MST ||
1387 encoder->type == INTEL_OUTPUT_EDP) {
1388 bret = skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state);
1389 if (!bret) {
1390 DRM_DEBUG_KMS("Could not set DP dpll HW state.\n");
1391 return NULL;
1392 }
1393 crtc_state->dpll_hw_state = dpll_hw_state;
1394 } else {
1395 return NULL;
1396 }
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001397
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001398 if (encoder->type == INTEL_OUTPUT_EDP)
1399 pll = intel_find_shared_dpll(crtc, crtc_state,
1400 DPLL_ID_SKL_DPLL0,
1401 DPLL_ID_SKL_DPLL0);
1402 else
1403 pll = intel_find_shared_dpll(crtc, crtc_state,
1404 DPLL_ID_SKL_DPLL1,
1405 DPLL_ID_SKL_DPLL3);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001406 if (!pll)
1407 return NULL;
1408
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001409 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001410
1411 return pll;
1412}
1413
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001414static void skl_dump_hw_state(struct drm_i915_private *dev_priv,
1415 struct intel_dpll_hw_state *hw_state)
1416{
1417 DRM_DEBUG_KMS("dpll_hw_state: "
1418 "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
1419 hw_state->ctrl1,
1420 hw_state->cfgcr1,
1421 hw_state->cfgcr2);
1422}
1423
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001424static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1425 .enable = skl_ddi_pll_enable,
1426 .disable = skl_ddi_pll_disable,
1427 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001428};
1429
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001430static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
1431 .enable = skl_ddi_dpll0_enable,
1432 .disable = skl_ddi_dpll0_disable,
1433 .get_hw_state = skl_ddi_dpll0_get_hw_state,
1434};
1435
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001436static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1437 struct intel_shared_dpll *pll)
1438{
1439 uint32_t temp;
1440 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001441 enum dpio_phy phy;
1442 enum dpio_channel ch;
1443
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001444 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001445
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001446 /* Non-SSC reference */
Dongwon Kimda6110b2016-04-14 15:37:43 -07001447 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1448 temp |= PORT_PLL_REF_SEL;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001449 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1450
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001451 if (IS_GEMINILAKE(dev_priv)) {
1452 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1453 temp |= PORT_PLL_POWER_ENABLE;
1454 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1455
1456 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1457 PORT_PLL_POWER_STATE), 200))
1458 DRM_ERROR("Power state not set for PLL:%d\n", port);
1459 }
1460
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001461 /* Disable 10 bit clock */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001462 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001463 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001464 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001465
1466 /* Write P1 & P2 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001467 temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001468 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001469 temp |= pll->state.hw_state.ebb0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001470 I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001471
1472 /* Write M2 integer */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001473 temp = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001474 temp &= ~PORT_PLL_M2_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001475 temp |= pll->state.hw_state.pll0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001476 I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001477
1478 /* Write N */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001479 temp = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001480 temp &= ~PORT_PLL_N_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001481 temp |= pll->state.hw_state.pll1;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001482 I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001483
1484 /* Write M2 fraction */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001485 temp = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001486 temp &= ~PORT_PLL_M2_FRAC_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001487 temp |= pll->state.hw_state.pll2;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001488 I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001489
1490 /* Write M2 fraction enable */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001491 temp = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001492 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001493 temp |= pll->state.hw_state.pll3;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001494 I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001495
1496 /* Write coeff */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001497 temp = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001498 temp &= ~PORT_PLL_PROP_COEFF_MASK;
1499 temp &= ~PORT_PLL_INT_COEFF_MASK;
1500 temp &= ~PORT_PLL_GAIN_CTL_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001501 temp |= pll->state.hw_state.pll6;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001502 I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001503
1504 /* Write calibration val */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001505 temp = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001506 temp &= ~PORT_PLL_TARGET_CNT_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001507 temp |= pll->state.hw_state.pll8;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001508 I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001509
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001510 temp = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001511 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001512 temp |= pll->state.hw_state.pll9;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001513 I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001514
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001515 temp = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001516 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1517 temp &= ~PORT_PLL_DCO_AMP_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001518 temp |= pll->state.hw_state.pll10;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001519 I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001520
1521 /* Recalibrate with new settings */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001522 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001523 temp |= PORT_PLL_RECALIBRATE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001524 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001525 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001526 temp |= pll->state.hw_state.ebb4;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001527 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001528
1529 /* Enable PLL */
1530 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1531 temp |= PORT_PLL_ENABLE;
1532 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1533 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1534
Imre Deak0b786e42016-06-28 13:37:30 +03001535 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
1536 200))
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001537 DRM_ERROR("PLL %d not locked\n", port);
1538
Ander Conselvan de Oliveira51b3ee32016-12-02 10:23:52 +02001539 if (IS_GEMINILAKE(dev_priv)) {
1540 temp = I915_READ(BXT_PORT_TX_DW5_LN0(phy, ch));
1541 temp |= DCC_DELAY_RANGE_2;
1542 I915_WRITE(BXT_PORT_TX_DW5_GRP(phy, ch), temp);
1543 }
1544
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001545 /*
1546 * While we write to the group register to program all lanes at once we
1547 * can read only lane registers and we pick lanes 0/1 for that.
1548 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001549 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001550 temp &= ~LANE_STAGGER_MASK;
1551 temp &= ~LANESTAGGER_STRAP_OVRD;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001552 temp |= pll->state.hw_state.pcsdw12;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001553 I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001554}
1555
1556static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1557 struct intel_shared_dpll *pll)
1558{
1559 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1560 uint32_t temp;
1561
1562 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1563 temp &= ~PORT_PLL_ENABLE;
1564 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1565 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001566
1567 if (IS_GEMINILAKE(dev_priv)) {
1568 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1569 temp &= ~PORT_PLL_POWER_ENABLE;
1570 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1571
1572 if (wait_for_us(!(I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1573 PORT_PLL_POWER_STATE), 200))
1574 DRM_ERROR("Power state not reset for PLL:%d\n", port);
1575 }
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001576}
1577
1578static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1579 struct intel_shared_dpll *pll,
1580 struct intel_dpll_hw_state *hw_state)
1581{
1582 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1583 uint32_t val;
1584 bool ret;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001585 enum dpio_phy phy;
1586 enum dpio_channel ch;
1587
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001588 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001589
1590 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1591 return false;
1592
1593 ret = false;
1594
1595 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1596 if (!(val & PORT_PLL_ENABLE))
1597 goto out;
1598
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001599 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001600 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1601
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001602 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001603 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1604
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001605 hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001606 hw_state->pll0 &= PORT_PLL_M2_MASK;
1607
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001608 hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001609 hw_state->pll1 &= PORT_PLL_N_MASK;
1610
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001611 hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001612 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1613
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001614 hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001615 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1616
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001617 hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001618 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1619 PORT_PLL_INT_COEFF_MASK |
1620 PORT_PLL_GAIN_CTL_MASK;
1621
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001622 hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001623 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1624
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001625 hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001626 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1627
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001628 hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001629 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1630 PORT_PLL_DCO_AMP_MASK;
1631
1632 /*
1633 * While we write to the group register to program all lanes at once we
1634 * can read only lane registers. We configure all lanes the same way, so
1635 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1636 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001637 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
1638 if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001639 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1640 hw_state->pcsdw12,
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001641 I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001642 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1643
1644 ret = true;
1645
1646out:
1647 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1648
1649 return ret;
1650}
1651
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001652/* bxt clock parameters */
1653struct bxt_clk_div {
1654 int clock;
1655 uint32_t p1;
1656 uint32_t p2;
1657 uint32_t m2_int;
1658 uint32_t m2_frac;
1659 bool m2_frac_en;
1660 uint32_t n;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001661
1662 int vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001663};
1664
1665/* pre-calculated values for DP linkrates */
1666static const struct bxt_clk_div bxt_dp_clk_val[] = {
1667 {162000, 4, 2, 32, 1677722, 1, 1},
1668 {270000, 4, 1, 27, 0, 0, 1},
1669 {540000, 2, 1, 27, 0, 0, 1},
1670 {216000, 3, 2, 32, 1677722, 1, 1},
1671 {243000, 4, 1, 24, 1258291, 1, 1},
1672 {324000, 4, 1, 32, 1677722, 1, 1},
1673 {432000, 3, 1, 32, 1677722, 1, 1}
1674};
1675
Durgadoss Ra277ca72016-09-01 15:08:09 -07001676static bool
1677bxt_ddi_hdmi_pll_dividers(struct intel_crtc *intel_crtc,
1678 struct intel_crtc_state *crtc_state, int clock,
1679 struct bxt_clk_div *clk_div)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001680{
Durgadoss Ra277ca72016-09-01 15:08:09 -07001681 struct dpll best_clock;
1682
1683 /* Calculate HDMI div */
1684 /*
1685 * FIXME: tie the following calculation into
1686 * i9xx_crtc_compute_clock
1687 */
1688 if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
1689 DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1690 clock, pipe_name(intel_crtc->pipe));
1691 return false;
1692 }
1693
1694 clk_div->p1 = best_clock.p1;
1695 clk_div->p2 = best_clock.p2;
1696 WARN_ON(best_clock.m1 != 2);
1697 clk_div->n = best_clock.n;
1698 clk_div->m2_int = best_clock.m2 >> 22;
1699 clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
1700 clk_div->m2_frac_en = clk_div->m2_frac != 0;
1701
1702 clk_div->vco = best_clock.vco;
1703
1704 return true;
1705}
1706
1707static void bxt_ddi_dp_pll_dividers(int clock, struct bxt_clk_div *clk_div)
1708{
1709 int i;
1710
1711 *clk_div = bxt_dp_clk_val[0];
1712 for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1713 if (bxt_dp_clk_val[i].clock == clock) {
1714 *clk_div = bxt_dp_clk_val[i];
1715 break;
1716 }
1717 }
1718
1719 clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
1720}
1721
1722static bool bxt_ddi_set_dpll_hw_state(int clock,
1723 struct bxt_clk_div *clk_div,
1724 struct intel_dpll_hw_state *dpll_hw_state)
1725{
1726 int vco = clk_div->vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001727 uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
1728 uint32_t lanestagger;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001729
1730 if (vco >= 6200000 && vco <= 6700000) {
1731 prop_coef = 4;
1732 int_coef = 9;
1733 gain_ctl = 3;
1734 targ_cnt = 8;
1735 } else if ((vco > 5400000 && vco < 6200000) ||
1736 (vco >= 4800000 && vco < 5400000)) {
1737 prop_coef = 5;
1738 int_coef = 11;
1739 gain_ctl = 3;
1740 targ_cnt = 9;
1741 } else if (vco == 5400000) {
1742 prop_coef = 3;
1743 int_coef = 8;
1744 gain_ctl = 1;
1745 targ_cnt = 9;
1746 } else {
1747 DRM_ERROR("Invalid VCO\n");
Durgadoss Ra277ca72016-09-01 15:08:09 -07001748 return false;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001749 }
1750
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001751 if (clock > 270000)
1752 lanestagger = 0x18;
1753 else if (clock > 135000)
1754 lanestagger = 0x0d;
1755 else if (clock > 67000)
1756 lanestagger = 0x07;
1757 else if (clock > 33000)
1758 lanestagger = 0x04;
1759 else
1760 lanestagger = 0x02;
1761
Durgadoss Ra277ca72016-09-01 15:08:09 -07001762 dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
1763 dpll_hw_state->pll0 = clk_div->m2_int;
1764 dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
1765 dpll_hw_state->pll2 = clk_div->m2_frac;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001766
Durgadoss Ra277ca72016-09-01 15:08:09 -07001767 if (clk_div->m2_frac_en)
1768 dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001769
Durgadoss Ra277ca72016-09-01 15:08:09 -07001770 dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
1771 dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001772
Durgadoss Ra277ca72016-09-01 15:08:09 -07001773 dpll_hw_state->pll8 = targ_cnt;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001774
Durgadoss Ra277ca72016-09-01 15:08:09 -07001775 dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001776
Durgadoss Ra277ca72016-09-01 15:08:09 -07001777 dpll_hw_state->pll10 =
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001778 PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1779 | PORT_PLL_DCO_AMP_OVR_EN_H;
1780
Durgadoss Ra277ca72016-09-01 15:08:09 -07001781 dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001782
Durgadoss Ra277ca72016-09-01 15:08:09 -07001783 dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger;
1784
1785 return true;
1786}
1787
1788bool bxt_ddi_dp_set_dpll_hw_state(int clock,
1789 struct intel_dpll_hw_state *dpll_hw_state)
1790{
1791 struct bxt_clk_div clk_div = {0};
1792
1793 bxt_ddi_dp_pll_dividers(clock, &clk_div);
1794
1795 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1796}
1797
Imre Deaka04139c2016-09-26 17:54:31 +03001798static bool
1799bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc *intel_crtc,
1800 struct intel_crtc_state *crtc_state, int clock,
1801 struct intel_dpll_hw_state *dpll_hw_state)
1802{
1803 struct bxt_clk_div clk_div = { };
1804
1805 bxt_ddi_hdmi_pll_dividers(intel_crtc, crtc_state, clock, &clk_div);
1806
1807 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1808}
1809
Durgadoss Ra277ca72016-09-01 15:08:09 -07001810static struct intel_shared_dpll *
1811bxt_get_dpll(struct intel_crtc *crtc,
1812 struct intel_crtc_state *crtc_state,
1813 struct intel_encoder *encoder)
1814{
Imre Deaka04139c2016-09-26 17:54:31 +03001815 struct intel_dpll_hw_state dpll_hw_state = { };
Durgadoss Ra277ca72016-09-01 15:08:09 -07001816 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1817 struct intel_digital_port *intel_dig_port;
1818 struct intel_shared_dpll *pll;
1819 int i, clock = crtc_state->port_clock;
1820
Imre Deaka04139c2016-09-26 17:54:31 +03001821 if (encoder->type == INTEL_OUTPUT_HDMI &&
1822 !bxt_ddi_hdmi_set_dpll_hw_state(crtc, crtc_state, clock,
1823 &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001824 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001825
1826 if ((encoder->type == INTEL_OUTPUT_DP ||
1827 encoder->type == INTEL_OUTPUT_EDP) &&
1828 !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001829 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001830
1831 memset(&crtc_state->dpll_hw_state, 0,
1832 sizeof(crtc_state->dpll_hw_state));
1833
1834 crtc_state->dpll_hw_state = dpll_hw_state;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001835
Maarten Lankhorsta79e8cc2016-08-09 17:04:00 +02001836 if (encoder->type == INTEL_OUTPUT_DP_MST) {
1837 struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
1838
1839 intel_dig_port = intel_mst->primary;
1840 } else
1841 intel_dig_port = enc_to_dig_port(&encoder->base);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001842
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001843 /* 1:1 mapping between ports and PLLs */
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001844 i = (enum intel_dpll_id) intel_dig_port->port;
1845 pll = intel_get_shared_dpll_by_id(dev_priv, i);
1846
Ville Syrjälä78108b72016-05-27 20:59:19 +03001847 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
1848 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001849
1850 intel_reference_shared_dpll(pll, crtc_state);
1851
1852 return pll;
1853}
1854
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001855static void bxt_dump_hw_state(struct drm_i915_private *dev_priv,
1856 struct intel_dpll_hw_state *hw_state)
1857{
1858 DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
1859 "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, "
1860 "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n",
1861 hw_state->ebb0,
1862 hw_state->ebb4,
1863 hw_state->pll0,
1864 hw_state->pll1,
1865 hw_state->pll2,
1866 hw_state->pll3,
1867 hw_state->pll6,
1868 hw_state->pll8,
1869 hw_state->pll9,
1870 hw_state->pll10,
1871 hw_state->pcsdw12);
1872}
1873
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001874static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1875 .enable = bxt_ddi_pll_enable,
1876 .disable = bxt_ddi_pll_disable,
1877 .get_hw_state = bxt_ddi_pll_get_hw_state,
1878};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001879
1880static void intel_ddi_pll_init(struct drm_device *dev)
1881{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001882 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001883
Ville Syrjälä9f7eb312016-05-13 23:41:29 +03001884 if (INTEL_GEN(dev_priv) < 9) {
1885 uint32_t val = I915_READ(LCPLL_CTL);
Ville Syrjäläb2045352016-05-13 23:41:27 +03001886
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001887 /*
1888 * The LCPLL register should be turned on by the BIOS. For now
1889 * let's just check its state and print errors in case
1890 * something is wrong. Don't even try to turn it on.
1891 */
1892
1893 if (val & LCPLL_CD_SOURCE_FCLK)
1894 DRM_ERROR("CDCLK source is not LCPLL\n");
1895
1896 if (val & LCPLL_PLL_DISABLE)
1897 DRM_ERROR("LCPLL is disabled\n");
1898 }
1899}
1900
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001901struct dpll_info {
1902 const char *name;
1903 const int id;
1904 const struct intel_shared_dpll_funcs *funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001905 uint32_t flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001906};
1907
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001908struct intel_dpll_mgr {
1909 const struct dpll_info *dpll_info;
1910
1911 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001912 struct intel_crtc_state *crtc_state,
1913 struct intel_encoder *encoder);
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001914
1915 void (*dump_hw_state)(struct drm_i915_private *dev_priv,
1916 struct intel_dpll_hw_state *hw_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001917};
1918
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001919static const struct dpll_info pch_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001920 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
1921 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
1922 { NULL, -1, NULL, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001923};
1924
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001925static const struct intel_dpll_mgr pch_pll_mgr = {
1926 .dpll_info = pch_plls,
1927 .get_dpll = ibx_get_dpll,
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001928 .dump_hw_state = ibx_dump_hw_state,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001929};
1930
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001931static const struct dpll_info hsw_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001932 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 },
1933 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 },
1934 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 },
1935 { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1936 { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1937 { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001938 { NULL, -1, NULL, },
1939};
1940
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001941static const struct intel_dpll_mgr hsw_pll_mgr = {
1942 .dpll_info = hsw_plls,
1943 .get_dpll = hsw_get_dpll,
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001944 .dump_hw_state = hsw_dump_hw_state,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001945};
1946
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001947static const struct dpll_info skl_plls[] = {
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001948 { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
Ville Syrjäläd5aab9d2016-05-11 22:04:33 +03001949 { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
1950 { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
1951 { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001952 { NULL, -1, NULL, },
1953};
1954
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001955static const struct intel_dpll_mgr skl_pll_mgr = {
1956 .dpll_info = skl_plls,
1957 .get_dpll = skl_get_dpll,
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001958 .dump_hw_state = skl_dump_hw_state,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001959};
1960
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001961static const struct dpll_info bxt_plls[] = {
Imre Deak08250c42016-03-14 19:55:34 +02001962 { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
1963 { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
1964 { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001965 { NULL, -1, NULL, },
1966};
1967
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001968static const struct intel_dpll_mgr bxt_pll_mgr = {
1969 .dpll_info = bxt_plls,
1970 .get_dpll = bxt_get_dpll,
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02001971 .dump_hw_state = bxt_dump_hw_state,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001972};
1973
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +02001974/**
1975 * intel_shared_dpll_init - Initialize shared DPLLs
1976 * @dev: drm device
1977 *
1978 * Initialize shared DPLLs for @dev.
1979 */
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001980void intel_shared_dpll_init(struct drm_device *dev)
1981{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001982 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001983 const struct intel_dpll_mgr *dpll_mgr = NULL;
1984 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001985 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001986
Tvrtko Ursulin08537232016-10-13 11:03:02 +01001987 if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001988 dpll_mgr = &skl_pll_mgr;
Ander Conselvan de Oliveiracc3f90f2016-12-02 10:23:49 +02001989 else if (IS_GEN9_LP(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001990 dpll_mgr = &bxt_pll_mgr;
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01001991 else if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001992 dpll_mgr = &hsw_pll_mgr;
Tvrtko Ursulin6e266952016-10-13 11:02:53 +01001993 else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001994 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001995
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001996 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001997 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001998 return;
1999 }
2000
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002001 dpll_info = dpll_mgr->dpll_info;
2002
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002003 for (i = 0; dpll_info[i].id >= 0; i++) {
2004 WARN_ON(i != dpll_info[i].id);
2005
2006 dev_priv->shared_dplls[i].id = dpll_info[i].id;
2007 dev_priv->shared_dplls[i].name = dpll_info[i].name;
2008 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02002009 dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002010 }
2011
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002012 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002013 dev_priv->num_shared_dpll = i;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +01002014 mutex_init(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02002015
2016 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002017
2018 /* FIXME: Move this to a more suitable place */
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01002019 if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02002020 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02002021}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002022
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +02002023/**
2024 * intel_get_shared_dpll - get a shared DPLL for CRTC and encoder combination
2025 * @crtc: CRTC
2026 * @crtc_state: atomic state for @crtc
2027 * @encoder: encoder
2028 *
2029 * Find an appropriate DPLL for the given CRTC and encoder combination. A
2030 * reference from the @crtc to the returned pll is registered in the atomic
2031 * state. That configuration is made effective by calling
2032 * intel_shared_dpll_swap_state(). The reference should be released by calling
2033 * intel_release_shared_dpll().
2034 *
2035 * Returns:
2036 * A shared DPLL to be used by @crtc and @encoder with the given @crtc_state.
2037 */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002038struct intel_shared_dpll *
2039intel_get_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02002040 struct intel_crtc_state *crtc_state,
2041 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002042{
2043 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2044 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
2045
2046 if (WARN_ON(!dpll_mgr))
2047 return NULL;
2048
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02002049 return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02002050}
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002051
2052/**
2053 * intel_release_shared_dpll - end use of DPLL by CRTC in atomic state
2054 * @dpll: dpll in use by @crtc
2055 * @crtc: crtc
2056 * @state: atomic state
2057 *
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +02002058 * This function releases the reference from @crtc to @dpll from the
2059 * atomic @state. The new configuration is made effective by calling
2060 * intel_shared_dpll_swap_state().
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002061 */
2062void intel_release_shared_dpll(struct intel_shared_dpll *dpll,
2063 struct intel_crtc *crtc,
2064 struct drm_atomic_state *state)
2065{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02002066 struct intel_shared_dpll_state *shared_dpll_state;
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002067
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02002068 shared_dpll_state = intel_atomic_get_shared_dpll_state(state);
2069 shared_dpll_state[dpll->id].crtc_mask &= ~(1 << crtc->pipe);
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002070}
Ander Conselvan de Oliveiraf50b79f2016-12-29 17:22:12 +02002071
2072/**
2073 * intel_shared_dpll_dump_hw_state - write hw_state to dmesg
2074 * @dev_priv: i915 drm device
2075 * @hw_state: hw state to be written to the log
2076 *
2077 * Write the relevant values in @hw_state to dmesg using DRM_DEBUG_KMS.
2078 */
2079void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
2080 struct intel_dpll_hw_state *hw_state)
2081{
2082 if (dev_priv->dpll_mgr) {
2083 dev_priv->dpll_mgr->dump_hw_state(dev_priv, hw_state);
2084 } else {
2085 /* fallback for platforms that don't use the shared dpll
2086 * infrastructure
2087 */
2088 DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
2089 "fp0: 0x%x, fp1: 0x%x\n",
2090 hw_state->dpll,
2091 hw_state->dpll_md,
2092 hw_state->fp0,
2093 hw_state->fp1);
2094 }
2095}