blob: 44c3c7056f3fd5b95bdefa4fa20ca5dd1f80dea3 [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 Oliveira2edd6442016-03-08 17:46:21 +0200455static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
Ander Conselvan de Oliveiraeac61762016-12-29 17:22:10 +0200456 .prepare = ibx_pch_dpll_prepare,
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200457 .enable = ibx_pch_dpll_enable,
458 .disable = ibx_pch_dpll_disable,
459 .get_hw_state = ibx_pch_dpll_get_hw_state,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200460};
461
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200462static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
463 struct intel_shared_dpll *pll)
464{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200465 I915_WRITE(WRPLL_CTL(pll->id), pll->state.hw_state.wrpll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200466 POSTING_READ(WRPLL_CTL(pll->id));
467 udelay(20);
468}
469
470static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
471 struct intel_shared_dpll *pll)
472{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200473 I915_WRITE(SPLL_CTL, pll->state.hw_state.spll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200474 POSTING_READ(SPLL_CTL);
475 udelay(20);
476}
477
478static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
479 struct intel_shared_dpll *pll)
480{
481 uint32_t val;
482
483 val = I915_READ(WRPLL_CTL(pll->id));
484 I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
485 POSTING_READ(WRPLL_CTL(pll->id));
486}
487
488static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
489 struct intel_shared_dpll *pll)
490{
491 uint32_t val;
492
493 val = I915_READ(SPLL_CTL);
494 I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
495 POSTING_READ(SPLL_CTL);
496}
497
498static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
499 struct intel_shared_dpll *pll,
500 struct intel_dpll_hw_state *hw_state)
501{
502 uint32_t val;
503
504 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
505 return false;
506
507 val = I915_READ(WRPLL_CTL(pll->id));
508 hw_state->wrpll = val;
509
510 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
511
512 return val & WRPLL_PLL_ENABLE;
513}
514
515static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
516 struct intel_shared_dpll *pll,
517 struct intel_dpll_hw_state *hw_state)
518{
519 uint32_t val;
520
521 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
522 return false;
523
524 val = I915_READ(SPLL_CTL);
525 hw_state->spll = val;
526
527 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
528
529 return val & SPLL_PLL_ENABLE;
530}
531
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200532#define LC_FREQ 2700
533#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
534
535#define P_MIN 2
536#define P_MAX 64
537#define P_INC 2
538
539/* Constraints for PLL good behavior */
540#define REF_MIN 48
541#define REF_MAX 400
542#define VCO_MIN 2400
543#define VCO_MAX 4800
544
545struct hsw_wrpll_rnp {
546 unsigned p, n2, r2;
547};
548
549static unsigned hsw_wrpll_get_budget_for_freq(int clock)
550{
551 unsigned budget;
552
553 switch (clock) {
554 case 25175000:
555 case 25200000:
556 case 27000000:
557 case 27027000:
558 case 37762500:
559 case 37800000:
560 case 40500000:
561 case 40541000:
562 case 54000000:
563 case 54054000:
564 case 59341000:
565 case 59400000:
566 case 72000000:
567 case 74176000:
568 case 74250000:
569 case 81000000:
570 case 81081000:
571 case 89012000:
572 case 89100000:
573 case 108000000:
574 case 108108000:
575 case 111264000:
576 case 111375000:
577 case 148352000:
578 case 148500000:
579 case 162000000:
580 case 162162000:
581 case 222525000:
582 case 222750000:
583 case 296703000:
584 case 297000000:
585 budget = 0;
586 break;
587 case 233500000:
588 case 245250000:
589 case 247750000:
590 case 253250000:
591 case 298000000:
592 budget = 1500;
593 break;
594 case 169128000:
595 case 169500000:
596 case 179500000:
597 case 202000000:
598 budget = 2000;
599 break;
600 case 256250000:
601 case 262500000:
602 case 270000000:
603 case 272500000:
604 case 273750000:
605 case 280750000:
606 case 281250000:
607 case 286000000:
608 case 291750000:
609 budget = 4000;
610 break;
611 case 267250000:
612 case 268500000:
613 budget = 5000;
614 break;
615 default:
616 budget = 1000;
617 break;
618 }
619
620 return budget;
621}
622
623static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
624 unsigned r2, unsigned n2, unsigned p,
625 struct hsw_wrpll_rnp *best)
626{
627 uint64_t a, b, c, d, diff, diff_best;
628
629 /* No best (r,n,p) yet */
630 if (best->p == 0) {
631 best->p = p;
632 best->n2 = n2;
633 best->r2 = r2;
634 return;
635 }
636
637 /*
638 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
639 * freq2k.
640 *
641 * delta = 1e6 *
642 * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
643 * freq2k;
644 *
645 * and we would like delta <= budget.
646 *
647 * If the discrepancy is above the PPM-based budget, always prefer to
648 * improve upon the previous solution. However, if you're within the
649 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
650 */
651 a = freq2k * budget * p * r2;
652 b = freq2k * budget * best->p * best->r2;
653 diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
654 diff_best = abs_diff(freq2k * best->p * best->r2,
655 LC_FREQ_2K * best->n2);
656 c = 1000000 * diff;
657 d = 1000000 * diff_best;
658
659 if (a < c && b < d) {
660 /* If both are above the budget, pick the closer */
661 if (best->p * best->r2 * diff < p * r2 * diff_best) {
662 best->p = p;
663 best->n2 = n2;
664 best->r2 = r2;
665 }
666 } else if (a >= c && b < d) {
667 /* If A is below the threshold but B is above it? Update. */
668 best->p = p;
669 best->n2 = n2;
670 best->r2 = r2;
671 } else if (a >= c && b >= d) {
672 /* Both are below the limit, so pick the higher n2/(r2*r2) */
673 if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
674 best->p = p;
675 best->n2 = n2;
676 best->r2 = r2;
677 }
678 }
679 /* Otherwise a < c && b >= d, do nothing */
680}
681
682static void
683hsw_ddi_calculate_wrpll(int clock /* in Hz */,
684 unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
685{
686 uint64_t freq2k;
687 unsigned p, n2, r2;
688 struct hsw_wrpll_rnp best = { 0, 0, 0 };
689 unsigned budget;
690
691 freq2k = clock / 100;
692
693 budget = hsw_wrpll_get_budget_for_freq(clock);
694
695 /* Special case handling for 540 pixel clock: bypass WR PLL entirely
696 * and directly pass the LC PLL to it. */
697 if (freq2k == 5400000) {
698 *n2_out = 2;
699 *p_out = 1;
700 *r2_out = 2;
701 return;
702 }
703
704 /*
705 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
706 * the WR PLL.
707 *
708 * We want R so that REF_MIN <= Ref <= REF_MAX.
709 * Injecting R2 = 2 * R gives:
710 * REF_MAX * r2 > LC_FREQ * 2 and
711 * REF_MIN * r2 < LC_FREQ * 2
712 *
713 * Which means the desired boundaries for r2 are:
714 * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
715 *
716 */
717 for (r2 = LC_FREQ * 2 / REF_MAX + 1;
718 r2 <= LC_FREQ * 2 / REF_MIN;
719 r2++) {
720
721 /*
722 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
723 *
724 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
725 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
726 * VCO_MAX * r2 > n2 * LC_FREQ and
727 * VCO_MIN * r2 < n2 * LC_FREQ)
728 *
729 * Which means the desired boundaries for n2 are:
730 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
731 */
732 for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
733 n2 <= VCO_MAX * r2 / LC_FREQ;
734 n2++) {
735
736 for (p = P_MIN; p <= P_MAX; p += P_INC)
737 hsw_wrpll_update_rnp(freq2k, budget,
738 r2, n2, p, &best);
739 }
740 }
741
742 *n2_out = best.n2;
743 *p_out = best.p;
744 *r2_out = best.r2;
745}
746
Manasi Navare81b9fd82016-09-01 15:08:11 -0700747static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(int clock,
748 struct intel_crtc *crtc,
749 struct intel_crtc_state *crtc_state)
750{
751 struct intel_shared_dpll *pll;
752 uint32_t val;
753 unsigned int p, n2, r2;
754
755 hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
756
757 val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
758 WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
759 WRPLL_DIVIDER_POST(p);
760
761 crtc_state->dpll_hw_state.wrpll = val;
762
763 pll = intel_find_shared_dpll(crtc, crtc_state,
764 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
765
766 if (!pll)
767 return NULL;
768
769 return pll;
770}
771
772struct intel_shared_dpll *hsw_ddi_dp_get_dpll(struct intel_encoder *encoder,
773 int clock)
774{
775 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
776 struct intel_shared_dpll *pll;
777 enum intel_dpll_id pll_id;
778
779 switch (clock / 2) {
780 case 81000:
781 pll_id = DPLL_ID_LCPLL_810;
782 break;
783 case 135000:
784 pll_id = DPLL_ID_LCPLL_1350;
785 break;
786 case 270000:
787 pll_id = DPLL_ID_LCPLL_2700;
788 break;
789 default:
790 DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
791 return NULL;
792 }
793
794 pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
795
796 if (!pll)
797 return NULL;
798
799 return pll;
800}
801
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200802static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200803hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
804 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200805{
806 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200807 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200808
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200809 memset(&crtc_state->dpll_hw_state, 0,
810 sizeof(crtc_state->dpll_hw_state));
811
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200812 if (encoder->type == INTEL_OUTPUT_HDMI) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700813 pll = hsw_ddi_hdmi_get_dpll(clock, crtc, crtc_state);
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200814
Ville Syrjäläcca05022016-06-22 21:57:06 +0300815 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200816 encoder->type == INTEL_OUTPUT_DP_MST ||
817 encoder->type == INTEL_OUTPUT_EDP) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700818 pll = hsw_ddi_dp_get_dpll(encoder, clock);
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200819
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200820 } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
821 if (WARN_ON(crtc_state->port_clock / 2 != 135000))
822 return NULL;
823
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200824 crtc_state->dpll_hw_state.spll =
825 SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
826
827 pll = intel_find_shared_dpll(crtc, crtc_state,
828 DPLL_ID_SPLL, DPLL_ID_SPLL);
829 } else {
830 return NULL;
831 }
832
833 if (!pll)
834 return NULL;
835
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200836 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200837
838 return pll;
839}
840
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200841static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
842 .enable = hsw_ddi_wrpll_enable,
843 .disable = hsw_ddi_wrpll_disable,
844 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200845};
846
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200847static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
848 .enable = hsw_ddi_spll_enable,
849 .disable = hsw_ddi_spll_disable,
850 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200851};
852
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200853static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
854 struct intel_shared_dpll *pll)
855{
856}
857
858static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
859 struct intel_shared_dpll *pll)
860{
861}
862
863static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
864 struct intel_shared_dpll *pll,
865 struct intel_dpll_hw_state *hw_state)
866{
867 return true;
868}
869
870static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
871 .enable = hsw_ddi_lcpll_enable,
872 .disable = hsw_ddi_lcpll_disable,
873 .get_hw_state = hsw_ddi_lcpll_get_hw_state,
874};
875
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200876struct skl_dpll_regs {
877 i915_reg_t ctl, cfgcr1, cfgcr2;
878};
879
880/* this array is indexed by the *shared* pll id */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200881static const struct skl_dpll_regs skl_dpll_regs[4] = {
882 {
883 /* DPLL 0 */
884 .ctl = LCPLL1_CTL,
885 /* DPLL 0 doesn't support HDMI mode */
886 },
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200887 {
888 /* DPLL 1 */
889 .ctl = LCPLL2_CTL,
890 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
891 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
892 },
893 {
894 /* DPLL 2 */
895 .ctl = WRPLL_CTL(0),
896 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
897 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
898 },
899 {
900 /* DPLL 3 */
901 .ctl = WRPLL_CTL(1),
902 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
903 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
904 },
905};
906
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200907static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
908 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200909{
910 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200911
912 val = I915_READ(DPLL_CTRL1);
913
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200914 val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
915 DPLL_CTRL1_LINK_RATE_MASK(pll->id));
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200916 val |= pll->state.hw_state.ctrl1 << (pll->id * 6);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200917
918 I915_WRITE(DPLL_CTRL1, val);
919 POSTING_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200920}
921
922static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
923 struct intel_shared_dpll *pll)
924{
925 const struct skl_dpll_regs *regs = skl_dpll_regs;
926
927 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200928
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +0200929 I915_WRITE(regs[pll->id].cfgcr1, pll->state.hw_state.cfgcr1);
930 I915_WRITE(regs[pll->id].cfgcr2, pll->state.hw_state.cfgcr2);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200931 POSTING_READ(regs[pll->id].cfgcr1);
932 POSTING_READ(regs[pll->id].cfgcr2);
933
934 /* the enable bit is always bit 31 */
935 I915_WRITE(regs[pll->id].ctl,
936 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
937
Chris Wilson27bf23a2016-06-30 15:33:12 +0100938 if (intel_wait_for_register(dev_priv,
939 DPLL_STATUS,
940 DPLL_LOCK(pll->id),
941 DPLL_LOCK(pll->id),
942 5))
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200943 DRM_ERROR("DPLL %d not locked\n", pll->id);
944}
945
946static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
947 struct intel_shared_dpll *pll)
948{
949 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200950}
951
952static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
953 struct intel_shared_dpll *pll)
954{
955 const struct skl_dpll_regs *regs = skl_dpll_regs;
956
957 /* the enable bit is always bit 31 */
958 I915_WRITE(regs[pll->id].ctl,
959 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
960 POSTING_READ(regs[pll->id].ctl);
961}
962
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200963static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
964 struct intel_shared_dpll *pll)
965{
966}
967
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200968static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
969 struct intel_shared_dpll *pll,
970 struct intel_dpll_hw_state *hw_state)
971{
972 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200973 const struct skl_dpll_regs *regs = skl_dpll_regs;
974 bool ret;
975
976 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
977 return false;
978
979 ret = false;
980
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200981 val = I915_READ(regs[pll->id].ctl);
982 if (!(val & LCPLL_PLL_ENABLE))
983 goto out;
984
985 val = I915_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200986 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200987
988 /* avoid reading back stale values if HDMI mode is not enabled */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200989 if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200990 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
991 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
992 }
993 ret = true;
994
995out:
996 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
997
998 return ret;
999}
1000
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001001static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
1002 struct intel_shared_dpll *pll,
1003 struct intel_dpll_hw_state *hw_state)
1004{
1005 uint32_t val;
1006 const struct skl_dpll_regs *regs = skl_dpll_regs;
1007 bool ret;
1008
1009 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1010 return false;
1011
1012 ret = false;
1013
1014 /* DPLL0 is always enabled since it drives CDCLK */
1015 val = I915_READ(regs[pll->id].ctl);
1016 if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
1017 goto out;
1018
1019 val = I915_READ(DPLL_CTRL1);
1020 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
1021
1022 ret = true;
1023
1024out:
1025 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1026
1027 return ret;
1028}
1029
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001030struct skl_wrpll_context {
1031 uint64_t min_deviation; /* current minimal deviation */
1032 uint64_t central_freq; /* chosen central freq */
1033 uint64_t dco_freq; /* chosen dco freq */
1034 unsigned int p; /* chosen divider */
1035};
1036
1037static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
1038{
1039 memset(ctx, 0, sizeof(*ctx));
1040
1041 ctx->min_deviation = U64_MAX;
1042}
1043
1044/* DCO freq must be within +1%/-6% of the DCO central freq */
1045#define SKL_DCO_MAX_PDEVIATION 100
1046#define SKL_DCO_MAX_NDEVIATION 600
1047
1048static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
1049 uint64_t central_freq,
1050 uint64_t dco_freq,
1051 unsigned int divider)
1052{
1053 uint64_t deviation;
1054
1055 deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
1056 central_freq);
1057
1058 /* positive deviation */
1059 if (dco_freq >= central_freq) {
1060 if (deviation < SKL_DCO_MAX_PDEVIATION &&
1061 deviation < ctx->min_deviation) {
1062 ctx->min_deviation = deviation;
1063 ctx->central_freq = central_freq;
1064 ctx->dco_freq = dco_freq;
1065 ctx->p = divider;
1066 }
1067 /* negative deviation */
1068 } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
1069 deviation < ctx->min_deviation) {
1070 ctx->min_deviation = deviation;
1071 ctx->central_freq = central_freq;
1072 ctx->dco_freq = dco_freq;
1073 ctx->p = divider;
1074 }
1075}
1076
1077static void skl_wrpll_get_multipliers(unsigned int p,
1078 unsigned int *p0 /* out */,
1079 unsigned int *p1 /* out */,
1080 unsigned int *p2 /* out */)
1081{
1082 /* even dividers */
1083 if (p % 2 == 0) {
1084 unsigned int half = p / 2;
1085
1086 if (half == 1 || half == 2 || half == 3 || half == 5) {
1087 *p0 = 2;
1088 *p1 = 1;
1089 *p2 = half;
1090 } else if (half % 2 == 0) {
1091 *p0 = 2;
1092 *p1 = half / 2;
1093 *p2 = 2;
1094 } else if (half % 3 == 0) {
1095 *p0 = 3;
1096 *p1 = half / 3;
1097 *p2 = 2;
1098 } else if (half % 7 == 0) {
1099 *p0 = 7;
1100 *p1 = half / 7;
1101 *p2 = 2;
1102 }
1103 } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
1104 *p0 = 3;
1105 *p1 = 1;
1106 *p2 = p / 3;
1107 } else if (p == 5 || p == 7) {
1108 *p0 = p;
1109 *p1 = 1;
1110 *p2 = 1;
1111 } else if (p == 15) {
1112 *p0 = 3;
1113 *p1 = 1;
1114 *p2 = 5;
1115 } else if (p == 21) {
1116 *p0 = 7;
1117 *p1 = 1;
1118 *p2 = 3;
1119 } else if (p == 35) {
1120 *p0 = 7;
1121 *p1 = 1;
1122 *p2 = 5;
1123 }
1124}
1125
1126struct skl_wrpll_params {
1127 uint32_t dco_fraction;
1128 uint32_t dco_integer;
1129 uint32_t qdiv_ratio;
1130 uint32_t qdiv_mode;
1131 uint32_t kdiv;
1132 uint32_t pdiv;
1133 uint32_t central_freq;
1134};
1135
1136static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
1137 uint64_t afe_clock,
1138 uint64_t central_freq,
1139 uint32_t p0, uint32_t p1, uint32_t p2)
1140{
1141 uint64_t dco_freq;
1142
1143 switch (central_freq) {
1144 case 9600000000ULL:
1145 params->central_freq = 0;
1146 break;
1147 case 9000000000ULL:
1148 params->central_freq = 1;
1149 break;
1150 case 8400000000ULL:
1151 params->central_freq = 3;
1152 }
1153
1154 switch (p0) {
1155 case 1:
1156 params->pdiv = 0;
1157 break;
1158 case 2:
1159 params->pdiv = 1;
1160 break;
1161 case 3:
1162 params->pdiv = 2;
1163 break;
1164 case 7:
1165 params->pdiv = 4;
1166 break;
1167 default:
1168 WARN(1, "Incorrect PDiv\n");
1169 }
1170
1171 switch (p2) {
1172 case 5:
1173 params->kdiv = 0;
1174 break;
1175 case 2:
1176 params->kdiv = 1;
1177 break;
1178 case 3:
1179 params->kdiv = 2;
1180 break;
1181 case 1:
1182 params->kdiv = 3;
1183 break;
1184 default:
1185 WARN(1, "Incorrect KDiv\n");
1186 }
1187
1188 params->qdiv_ratio = p1;
1189 params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1190
1191 dco_freq = p0 * p1 * p2 * afe_clock;
1192
1193 /*
1194 * Intermediate values are in Hz.
1195 * Divide by MHz to match bsepc
1196 */
1197 params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1198 params->dco_fraction =
1199 div_u64((div_u64(dco_freq, 24) -
1200 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1201}
1202
1203static bool
1204skl_ddi_calculate_wrpll(int clock /* in Hz */,
1205 struct skl_wrpll_params *wrpll_params)
1206{
1207 uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1208 uint64_t dco_central_freq[3] = {8400000000ULL,
1209 9000000000ULL,
1210 9600000000ULL};
1211 static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1212 24, 28, 30, 32, 36, 40, 42, 44,
1213 48, 52, 54, 56, 60, 64, 66, 68,
1214 70, 72, 76, 78, 80, 84, 88, 90,
1215 92, 96, 98 };
1216 static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1217 static const struct {
1218 const int *list;
1219 int n_dividers;
1220 } dividers[] = {
1221 { even_dividers, ARRAY_SIZE(even_dividers) },
1222 { odd_dividers, ARRAY_SIZE(odd_dividers) },
1223 };
1224 struct skl_wrpll_context ctx;
1225 unsigned int dco, d, i;
1226 unsigned int p0, p1, p2;
1227
1228 skl_wrpll_context_init(&ctx);
1229
1230 for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1231 for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1232 for (i = 0; i < dividers[d].n_dividers; i++) {
1233 unsigned int p = dividers[d].list[i];
1234 uint64_t dco_freq = p * afe_clock;
1235
1236 skl_wrpll_try_divider(&ctx,
1237 dco_central_freq[dco],
1238 dco_freq,
1239 p);
1240 /*
1241 * Skip the remaining dividers if we're sure to
1242 * have found the definitive divider, we can't
1243 * improve a 0 deviation.
1244 */
1245 if (ctx.min_deviation == 0)
1246 goto skip_remaining_dividers;
1247 }
1248 }
1249
1250skip_remaining_dividers:
1251 /*
1252 * If a solution is found with an even divider, prefer
1253 * this one.
1254 */
1255 if (d == 0 && ctx.p)
1256 break;
1257 }
1258
1259 if (!ctx.p) {
1260 DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1261 return false;
1262 }
1263
1264 /*
1265 * gcc incorrectly analyses that these can be used without being
1266 * initialized. To be fair, it's hard to guess.
1267 */
1268 p0 = p1 = p2 = 0;
1269 skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1270 skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1271 p0, p1, p2);
1272
1273 return true;
1274}
1275
Jim Bride9a4edad2016-09-01 15:08:10 -07001276static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
1277 struct intel_crtc_state *crtc_state,
1278 int clock)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001279{
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001280 uint32_t ctrl1, cfgcr1, cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001281 struct skl_wrpll_params wrpll_params = { 0, };
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001282
1283 /*
1284 * See comment in intel_dpll_hw_state to understand why we always use 0
1285 * as the DPLL id in this function.
1286 */
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001287 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1288
Jim Bride9a4edad2016-09-01 15:08:10 -07001289 ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001290
Jim Bride9a4edad2016-09-01 15:08:10 -07001291 if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
1292 return false;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001293
Jim Bride9a4edad2016-09-01 15:08:10 -07001294 cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1295 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1296 wrpll_params.dco_integer;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001297
Jim Bride9a4edad2016-09-01 15:08:10 -07001298 cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1299 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1300 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1301 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1302 wrpll_params.central_freq;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001303
1304 memset(&crtc_state->dpll_hw_state, 0,
1305 sizeof(crtc_state->dpll_hw_state));
1306
1307 crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1308 crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1309 crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001310 return true;
1311}
1312
1313
1314bool skl_ddi_dp_set_dpll_hw_state(int clock,
1315 struct intel_dpll_hw_state *dpll_hw_state)
1316{
1317 uint32_t ctrl1;
1318
1319 /*
1320 * See comment in intel_dpll_hw_state to understand why we always use 0
1321 * as the DPLL id in this function.
1322 */
1323 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1324 switch (clock / 2) {
1325 case 81000:
1326 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1327 break;
1328 case 135000:
1329 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1330 break;
1331 case 270000:
1332 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1333 break;
1334 /* eDP 1.4 rates */
1335 case 162000:
1336 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
1337 break;
1338 case 108000:
1339 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
1340 break;
1341 case 216000:
1342 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
1343 break;
1344 }
1345
1346 dpll_hw_state->ctrl1 = ctrl1;
1347 return true;
1348}
1349
1350static struct intel_shared_dpll *
1351skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1352 struct intel_encoder *encoder)
1353{
1354 struct intel_shared_dpll *pll;
1355 int clock = crtc_state->port_clock;
1356 bool bret;
1357 struct intel_dpll_hw_state dpll_hw_state;
1358
1359 memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
1360
1361 if (encoder->type == INTEL_OUTPUT_HDMI) {
1362 bret = skl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock);
1363 if (!bret) {
1364 DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n");
1365 return NULL;
1366 }
1367 } else if (encoder->type == INTEL_OUTPUT_DP ||
1368 encoder->type == INTEL_OUTPUT_DP_MST ||
1369 encoder->type == INTEL_OUTPUT_EDP) {
1370 bret = skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state);
1371 if (!bret) {
1372 DRM_DEBUG_KMS("Could not set DP dpll HW state.\n");
1373 return NULL;
1374 }
1375 crtc_state->dpll_hw_state = dpll_hw_state;
1376 } else {
1377 return NULL;
1378 }
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001379
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001380 if (encoder->type == INTEL_OUTPUT_EDP)
1381 pll = intel_find_shared_dpll(crtc, crtc_state,
1382 DPLL_ID_SKL_DPLL0,
1383 DPLL_ID_SKL_DPLL0);
1384 else
1385 pll = intel_find_shared_dpll(crtc, crtc_state,
1386 DPLL_ID_SKL_DPLL1,
1387 DPLL_ID_SKL_DPLL3);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001388 if (!pll)
1389 return NULL;
1390
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001391 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001392
1393 return pll;
1394}
1395
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001396static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1397 .enable = skl_ddi_pll_enable,
1398 .disable = skl_ddi_pll_disable,
1399 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001400};
1401
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001402static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
1403 .enable = skl_ddi_dpll0_enable,
1404 .disable = skl_ddi_dpll0_disable,
1405 .get_hw_state = skl_ddi_dpll0_get_hw_state,
1406};
1407
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001408static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1409 struct intel_shared_dpll *pll)
1410{
1411 uint32_t temp;
1412 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001413 enum dpio_phy phy;
1414 enum dpio_channel ch;
1415
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001416 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001417
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001418 /* Non-SSC reference */
Dongwon Kimda6110b2016-04-14 15:37:43 -07001419 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1420 temp |= PORT_PLL_REF_SEL;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001421 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1422
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001423 if (IS_GEMINILAKE(dev_priv)) {
1424 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1425 temp |= PORT_PLL_POWER_ENABLE;
1426 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1427
1428 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1429 PORT_PLL_POWER_STATE), 200))
1430 DRM_ERROR("Power state not set for PLL:%d\n", port);
1431 }
1432
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001433 /* Disable 10 bit clock */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001434 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001435 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001436 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001437
1438 /* Write P1 & P2 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001439 temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001440 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001441 temp |= pll->state.hw_state.ebb0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001442 I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001443
1444 /* Write M2 integer */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001445 temp = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001446 temp &= ~PORT_PLL_M2_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001447 temp |= pll->state.hw_state.pll0;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001448 I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001449
1450 /* Write N */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001451 temp = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001452 temp &= ~PORT_PLL_N_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001453 temp |= pll->state.hw_state.pll1;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001454 I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001455
1456 /* Write M2 fraction */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001457 temp = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001458 temp &= ~PORT_PLL_M2_FRAC_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001459 temp |= pll->state.hw_state.pll2;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001460 I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001461
1462 /* Write M2 fraction enable */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001463 temp = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001464 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001465 temp |= pll->state.hw_state.pll3;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001466 I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001467
1468 /* Write coeff */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001469 temp = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001470 temp &= ~PORT_PLL_PROP_COEFF_MASK;
1471 temp &= ~PORT_PLL_INT_COEFF_MASK;
1472 temp &= ~PORT_PLL_GAIN_CTL_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001473 temp |= pll->state.hw_state.pll6;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001474 I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001475
1476 /* Write calibration val */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001477 temp = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001478 temp &= ~PORT_PLL_TARGET_CNT_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001479 temp |= pll->state.hw_state.pll8;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001480 I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001481
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001482 temp = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001483 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001484 temp |= pll->state.hw_state.pll9;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001485 I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001486
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001487 temp = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001488 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1489 temp &= ~PORT_PLL_DCO_AMP_MASK;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001490 temp |= pll->state.hw_state.pll10;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001491 I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001492
1493 /* Recalibrate with new settings */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001494 temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001495 temp |= PORT_PLL_RECALIBRATE;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001496 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001497 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001498 temp |= pll->state.hw_state.ebb4;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001499 I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001500
1501 /* Enable PLL */
1502 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1503 temp |= PORT_PLL_ENABLE;
1504 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1505 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1506
Imre Deak0b786e42016-06-28 13:37:30 +03001507 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
1508 200))
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001509 DRM_ERROR("PLL %d not locked\n", port);
1510
Ander Conselvan de Oliveira51b3ee32016-12-02 10:23:52 +02001511 if (IS_GEMINILAKE(dev_priv)) {
1512 temp = I915_READ(BXT_PORT_TX_DW5_LN0(phy, ch));
1513 temp |= DCC_DELAY_RANGE_2;
1514 I915_WRITE(BXT_PORT_TX_DW5_GRP(phy, ch), temp);
1515 }
1516
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001517 /*
1518 * While we write to the group register to program all lanes at once we
1519 * can read only lane registers and we pick lanes 0/1 for that.
1520 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001521 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001522 temp &= ~LANE_STAGGER_MASK;
1523 temp &= ~LANESTAGGER_STRAP_OVRD;
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02001524 temp |= pll->state.hw_state.pcsdw12;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001525 I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001526}
1527
1528static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1529 struct intel_shared_dpll *pll)
1530{
1531 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1532 uint32_t temp;
1533
1534 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1535 temp &= ~PORT_PLL_ENABLE;
1536 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1537 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
Madhav Chauhanf7044dd2016-12-02 10:23:53 +02001538
1539 if (IS_GEMINILAKE(dev_priv)) {
1540 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1541 temp &= ~PORT_PLL_POWER_ENABLE;
1542 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1543
1544 if (wait_for_us(!(I915_READ(BXT_PORT_PLL_ENABLE(port)) &
1545 PORT_PLL_POWER_STATE), 200))
1546 DRM_ERROR("Power state not reset for PLL:%d\n", port);
1547 }
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001548}
1549
1550static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1551 struct intel_shared_dpll *pll,
1552 struct intel_dpll_hw_state *hw_state)
1553{
1554 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1555 uint32_t val;
1556 bool ret;
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001557 enum dpio_phy phy;
1558 enum dpio_channel ch;
1559
Ander Conselvan de Oliveira0a116ce2016-12-02 10:23:51 +02001560 bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001561
1562 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1563 return false;
1564
1565 ret = false;
1566
1567 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1568 if (!(val & PORT_PLL_ENABLE))
1569 goto out;
1570
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001571 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001572 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1573
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001574 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001575 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1576
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001577 hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001578 hw_state->pll0 &= PORT_PLL_M2_MASK;
1579
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001580 hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001581 hw_state->pll1 &= PORT_PLL_N_MASK;
1582
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001583 hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001584 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1585
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001586 hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001587 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1588
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001589 hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001590 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1591 PORT_PLL_INT_COEFF_MASK |
1592 PORT_PLL_GAIN_CTL_MASK;
1593
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001594 hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001595 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1596
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001597 hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001598 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1599
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001600 hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001601 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1602 PORT_PLL_DCO_AMP_MASK;
1603
1604 /*
1605 * While we write to the group register to program all lanes at once we
1606 * can read only lane registers. We configure all lanes the same way, so
1607 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1608 */
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001609 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
1610 if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001611 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1612 hw_state->pcsdw12,
Ander Conselvan de Oliveiraed378922016-10-19 10:59:00 +03001613 I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)));
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001614 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1615
1616 ret = true;
1617
1618out:
1619 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1620
1621 return ret;
1622}
1623
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001624/* bxt clock parameters */
1625struct bxt_clk_div {
1626 int clock;
1627 uint32_t p1;
1628 uint32_t p2;
1629 uint32_t m2_int;
1630 uint32_t m2_frac;
1631 bool m2_frac_en;
1632 uint32_t n;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001633
1634 int vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001635};
1636
1637/* pre-calculated values for DP linkrates */
1638static const struct bxt_clk_div bxt_dp_clk_val[] = {
1639 {162000, 4, 2, 32, 1677722, 1, 1},
1640 {270000, 4, 1, 27, 0, 0, 1},
1641 {540000, 2, 1, 27, 0, 0, 1},
1642 {216000, 3, 2, 32, 1677722, 1, 1},
1643 {243000, 4, 1, 24, 1258291, 1, 1},
1644 {324000, 4, 1, 32, 1677722, 1, 1},
1645 {432000, 3, 1, 32, 1677722, 1, 1}
1646};
1647
Durgadoss Ra277ca72016-09-01 15:08:09 -07001648static bool
1649bxt_ddi_hdmi_pll_dividers(struct intel_crtc *intel_crtc,
1650 struct intel_crtc_state *crtc_state, int clock,
1651 struct bxt_clk_div *clk_div)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001652{
Durgadoss Ra277ca72016-09-01 15:08:09 -07001653 struct dpll best_clock;
1654
1655 /* Calculate HDMI div */
1656 /*
1657 * FIXME: tie the following calculation into
1658 * i9xx_crtc_compute_clock
1659 */
1660 if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
1661 DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1662 clock, pipe_name(intel_crtc->pipe));
1663 return false;
1664 }
1665
1666 clk_div->p1 = best_clock.p1;
1667 clk_div->p2 = best_clock.p2;
1668 WARN_ON(best_clock.m1 != 2);
1669 clk_div->n = best_clock.n;
1670 clk_div->m2_int = best_clock.m2 >> 22;
1671 clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
1672 clk_div->m2_frac_en = clk_div->m2_frac != 0;
1673
1674 clk_div->vco = best_clock.vco;
1675
1676 return true;
1677}
1678
1679static void bxt_ddi_dp_pll_dividers(int clock, struct bxt_clk_div *clk_div)
1680{
1681 int i;
1682
1683 *clk_div = bxt_dp_clk_val[0];
1684 for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1685 if (bxt_dp_clk_val[i].clock == clock) {
1686 *clk_div = bxt_dp_clk_val[i];
1687 break;
1688 }
1689 }
1690
1691 clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
1692}
1693
1694static bool bxt_ddi_set_dpll_hw_state(int clock,
1695 struct bxt_clk_div *clk_div,
1696 struct intel_dpll_hw_state *dpll_hw_state)
1697{
1698 int vco = clk_div->vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001699 uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
1700 uint32_t lanestagger;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001701
1702 if (vco >= 6200000 && vco <= 6700000) {
1703 prop_coef = 4;
1704 int_coef = 9;
1705 gain_ctl = 3;
1706 targ_cnt = 8;
1707 } else if ((vco > 5400000 && vco < 6200000) ||
1708 (vco >= 4800000 && vco < 5400000)) {
1709 prop_coef = 5;
1710 int_coef = 11;
1711 gain_ctl = 3;
1712 targ_cnt = 9;
1713 } else if (vco == 5400000) {
1714 prop_coef = 3;
1715 int_coef = 8;
1716 gain_ctl = 1;
1717 targ_cnt = 9;
1718 } else {
1719 DRM_ERROR("Invalid VCO\n");
Durgadoss Ra277ca72016-09-01 15:08:09 -07001720 return false;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001721 }
1722
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001723 if (clock > 270000)
1724 lanestagger = 0x18;
1725 else if (clock > 135000)
1726 lanestagger = 0x0d;
1727 else if (clock > 67000)
1728 lanestagger = 0x07;
1729 else if (clock > 33000)
1730 lanestagger = 0x04;
1731 else
1732 lanestagger = 0x02;
1733
Durgadoss Ra277ca72016-09-01 15:08:09 -07001734 dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
1735 dpll_hw_state->pll0 = clk_div->m2_int;
1736 dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
1737 dpll_hw_state->pll2 = clk_div->m2_frac;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001738
Durgadoss Ra277ca72016-09-01 15:08:09 -07001739 if (clk_div->m2_frac_en)
1740 dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001741
Durgadoss Ra277ca72016-09-01 15:08:09 -07001742 dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
1743 dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001744
Durgadoss Ra277ca72016-09-01 15:08:09 -07001745 dpll_hw_state->pll8 = targ_cnt;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001746
Durgadoss Ra277ca72016-09-01 15:08:09 -07001747 dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001748
Durgadoss Ra277ca72016-09-01 15:08:09 -07001749 dpll_hw_state->pll10 =
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001750 PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1751 | PORT_PLL_DCO_AMP_OVR_EN_H;
1752
Durgadoss Ra277ca72016-09-01 15:08:09 -07001753 dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001754
Durgadoss Ra277ca72016-09-01 15:08:09 -07001755 dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger;
1756
1757 return true;
1758}
1759
1760bool bxt_ddi_dp_set_dpll_hw_state(int clock,
1761 struct intel_dpll_hw_state *dpll_hw_state)
1762{
1763 struct bxt_clk_div clk_div = {0};
1764
1765 bxt_ddi_dp_pll_dividers(clock, &clk_div);
1766
1767 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1768}
1769
Imre Deaka04139c2016-09-26 17:54:31 +03001770static bool
1771bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc *intel_crtc,
1772 struct intel_crtc_state *crtc_state, int clock,
1773 struct intel_dpll_hw_state *dpll_hw_state)
1774{
1775 struct bxt_clk_div clk_div = { };
1776
1777 bxt_ddi_hdmi_pll_dividers(intel_crtc, crtc_state, clock, &clk_div);
1778
1779 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1780}
1781
Durgadoss Ra277ca72016-09-01 15:08:09 -07001782static struct intel_shared_dpll *
1783bxt_get_dpll(struct intel_crtc *crtc,
1784 struct intel_crtc_state *crtc_state,
1785 struct intel_encoder *encoder)
1786{
Imre Deaka04139c2016-09-26 17:54:31 +03001787 struct intel_dpll_hw_state dpll_hw_state = { };
Durgadoss Ra277ca72016-09-01 15:08:09 -07001788 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1789 struct intel_digital_port *intel_dig_port;
1790 struct intel_shared_dpll *pll;
1791 int i, clock = crtc_state->port_clock;
1792
Imre Deaka04139c2016-09-26 17:54:31 +03001793 if (encoder->type == INTEL_OUTPUT_HDMI &&
1794 !bxt_ddi_hdmi_set_dpll_hw_state(crtc, crtc_state, clock,
1795 &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001796 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001797
1798 if ((encoder->type == INTEL_OUTPUT_DP ||
1799 encoder->type == INTEL_OUTPUT_EDP) &&
1800 !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001801 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001802
1803 memset(&crtc_state->dpll_hw_state, 0,
1804 sizeof(crtc_state->dpll_hw_state));
1805
1806 crtc_state->dpll_hw_state = dpll_hw_state;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001807
Maarten Lankhorsta79e8cc2016-08-09 17:04:00 +02001808 if (encoder->type == INTEL_OUTPUT_DP_MST) {
1809 struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
1810
1811 intel_dig_port = intel_mst->primary;
1812 } else
1813 intel_dig_port = enc_to_dig_port(&encoder->base);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001814
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001815 /* 1:1 mapping between ports and PLLs */
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001816 i = (enum intel_dpll_id) intel_dig_port->port;
1817 pll = intel_get_shared_dpll_by_id(dev_priv, i);
1818
Ville Syrjälä78108b72016-05-27 20:59:19 +03001819 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
1820 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001821
1822 intel_reference_shared_dpll(pll, crtc_state);
1823
1824 return pll;
1825}
1826
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001827static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1828 .enable = bxt_ddi_pll_enable,
1829 .disable = bxt_ddi_pll_disable,
1830 .get_hw_state = bxt_ddi_pll_get_hw_state,
1831};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001832
1833static void intel_ddi_pll_init(struct drm_device *dev)
1834{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001835 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001836
Ville Syrjälä9f7eb312016-05-13 23:41:29 +03001837 if (INTEL_GEN(dev_priv) < 9) {
1838 uint32_t val = I915_READ(LCPLL_CTL);
Ville Syrjäläb2045352016-05-13 23:41:27 +03001839
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001840 /*
1841 * The LCPLL register should be turned on by the BIOS. For now
1842 * let's just check its state and print errors in case
1843 * something is wrong. Don't even try to turn it on.
1844 */
1845
1846 if (val & LCPLL_CD_SOURCE_FCLK)
1847 DRM_ERROR("CDCLK source is not LCPLL\n");
1848
1849 if (val & LCPLL_PLL_DISABLE)
1850 DRM_ERROR("LCPLL is disabled\n");
1851 }
1852}
1853
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001854struct dpll_info {
1855 const char *name;
1856 const int id;
1857 const struct intel_shared_dpll_funcs *funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001858 uint32_t flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001859};
1860
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001861struct intel_dpll_mgr {
1862 const struct dpll_info *dpll_info;
1863
1864 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001865 struct intel_crtc_state *crtc_state,
1866 struct intel_encoder *encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001867};
1868
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001869static const struct dpll_info pch_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001870 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
1871 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
1872 { NULL, -1, NULL, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001873};
1874
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001875static const struct intel_dpll_mgr pch_pll_mgr = {
1876 .dpll_info = pch_plls,
1877 .get_dpll = ibx_get_dpll,
1878};
1879
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001880static const struct dpll_info hsw_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001881 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 },
1882 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 },
1883 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 },
1884 { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1885 { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1886 { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001887 { NULL, -1, NULL, },
1888};
1889
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001890static const struct intel_dpll_mgr hsw_pll_mgr = {
1891 .dpll_info = hsw_plls,
1892 .get_dpll = hsw_get_dpll,
1893};
1894
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001895static const struct dpll_info skl_plls[] = {
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001896 { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
Ville Syrjäläd5aab9d2016-05-11 22:04:33 +03001897 { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
1898 { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
1899 { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001900 { NULL, -1, NULL, },
1901};
1902
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001903static const struct intel_dpll_mgr skl_pll_mgr = {
1904 .dpll_info = skl_plls,
1905 .get_dpll = skl_get_dpll,
1906};
1907
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001908static const struct dpll_info bxt_plls[] = {
Imre Deak08250c42016-03-14 19:55:34 +02001909 { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
1910 { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
1911 { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001912 { NULL, -1, NULL, },
1913};
1914
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001915static const struct intel_dpll_mgr bxt_pll_mgr = {
1916 .dpll_info = bxt_plls,
1917 .get_dpll = bxt_get_dpll,
1918};
1919
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +02001920/**
1921 * intel_shared_dpll_init - Initialize shared DPLLs
1922 * @dev: drm device
1923 *
1924 * Initialize shared DPLLs for @dev.
1925 */
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001926void intel_shared_dpll_init(struct drm_device *dev)
1927{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001928 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001929 const struct intel_dpll_mgr *dpll_mgr = NULL;
1930 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001931 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001932
Tvrtko Ursulin08537232016-10-13 11:03:02 +01001933 if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001934 dpll_mgr = &skl_pll_mgr;
Ander Conselvan de Oliveiracc3f90f2016-12-02 10:23:49 +02001935 else if (IS_GEN9_LP(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001936 dpll_mgr = &bxt_pll_mgr;
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01001937 else if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001938 dpll_mgr = &hsw_pll_mgr;
Tvrtko Ursulin6e266952016-10-13 11:02:53 +01001939 else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001940 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001941
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001942 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001943 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001944 return;
1945 }
1946
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001947 dpll_info = dpll_mgr->dpll_info;
1948
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001949 for (i = 0; dpll_info[i].id >= 0; i++) {
1950 WARN_ON(i != dpll_info[i].id);
1951
1952 dev_priv->shared_dplls[i].id = dpll_info[i].id;
1953 dev_priv->shared_dplls[i].name = dpll_info[i].name;
1954 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001955 dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001956 }
1957
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001958 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001959 dev_priv->num_shared_dpll = i;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +01001960 mutex_init(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001961
1962 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001963
1964 /* FIXME: Move this to a more suitable place */
Tvrtko Ursulin4f8036a2016-10-13 11:02:52 +01001965 if (HAS_DDI(dev_priv))
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001966 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001967}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001968
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +02001969/**
1970 * intel_get_shared_dpll - get a shared DPLL for CRTC and encoder combination
1971 * @crtc: CRTC
1972 * @crtc_state: atomic state for @crtc
1973 * @encoder: encoder
1974 *
1975 * Find an appropriate DPLL for the given CRTC and encoder combination. A
1976 * reference from the @crtc to the returned pll is registered in the atomic
1977 * state. That configuration is made effective by calling
1978 * intel_shared_dpll_swap_state(). The reference should be released by calling
1979 * intel_release_shared_dpll().
1980 *
1981 * Returns:
1982 * A shared DPLL to be used by @crtc and @encoder with the given @crtc_state.
1983 */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001984struct intel_shared_dpll *
1985intel_get_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001986 struct intel_crtc_state *crtc_state,
1987 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001988{
1989 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1990 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
1991
1992 if (WARN_ON(!dpll_mgr))
1993 return NULL;
1994
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001995 return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001996}
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02001997
1998/**
1999 * intel_release_shared_dpll - end use of DPLL by CRTC in atomic state
2000 * @dpll: dpll in use by @crtc
2001 * @crtc: crtc
2002 * @state: atomic state
2003 *
Ander Conselvan de Oliveira294591c2016-12-29 17:22:11 +02002004 * This function releases the reference from @crtc to @dpll from the
2005 * atomic @state. The new configuration is made effective by calling
2006 * intel_shared_dpll_swap_state().
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002007 */
2008void intel_release_shared_dpll(struct intel_shared_dpll *dpll,
2009 struct intel_crtc *crtc,
2010 struct drm_atomic_state *state)
2011{
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02002012 struct intel_shared_dpll_state *shared_dpll_state;
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002013
Ander Conselvan de Oliveira2c42e532016-12-29 17:22:09 +02002014 shared_dpll_state = intel_atomic_get_shared_dpll_state(state);
2015 shared_dpll_state[dpll->id].crtc_mask &= ~(1 << crtc->pipe);
Ander Conselvan de Oliveiraa1c414e2016-12-29 17:22:07 +02002016}