blob: 1c59ca50c4309c7f92f28c4bec7d95d2ef18aedc [file] [log] [blame]
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001/*
2 * Copyright © 2006-2016 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include "intel_drv.h"
25
26struct intel_shared_dpll *
Jim Bridef1696602016-09-07 15:47:34 -070027skl_find_link_pll(struct drm_i915_private *dev_priv, int clock)
28{
29 struct intel_shared_dpll *pll = NULL;
30 struct intel_dpll_hw_state dpll_hw_state;
31 enum intel_dpll_id i;
32 bool found = false;
33
34 if (!skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
35 return pll;
36
37 for (i = DPLL_ID_SKL_DPLL1; i <= DPLL_ID_SKL_DPLL3; i++) {
38 pll = &dev_priv->shared_dplls[i];
39
40 /* Only want to check enabled timings first */
41 if (pll->config.crtc_mask == 0)
42 continue;
43
44 if (memcmp(&dpll_hw_state, &pll->config.hw_state,
45 sizeof(pll->config.hw_state)) == 0) {
46 found = true;
47 break;
48 }
49 }
50
51 /* Ok no matching timings, maybe there's a free one? */
52 for (i = DPLL_ID_SKL_DPLL1;
53 ((found == false) && (i <= DPLL_ID_SKL_DPLL3)); i++) {
54 pll = &dev_priv->shared_dplls[i];
55 if (pll->config.crtc_mask == 0) {
56 pll->config.hw_state = dpll_hw_state;
57 break;
58 }
59 }
60
61 return pll;
62}
63
64struct intel_shared_dpll *
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020065intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
66 enum intel_dpll_id id)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020067{
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020068 return &dev_priv->shared_dplls[id];
69}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020070
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020071enum intel_dpll_id
72intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
73 struct intel_shared_dpll *pll)
74{
75 if (WARN_ON(pll < dev_priv->shared_dplls||
76 pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll]))
77 return -1;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +020078
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +020079 return (enum intel_dpll_id) (pll - dev_priv->shared_dplls);
80}
81
82void
83intel_shared_dpll_config_get(struct intel_shared_dpll_config *config,
84 struct intel_shared_dpll *pll,
85 struct intel_crtc *crtc)
86{
87 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
88 enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
89
90 config[id].crtc_mask |= 1 << crtc->pipe;
91}
92
93void
94intel_shared_dpll_config_put(struct intel_shared_dpll_config *config,
95 struct intel_shared_dpll *pll,
96 struct intel_crtc *crtc)
97{
98 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
99 enum intel_dpll_id id = intel_get_shared_dpll_id(dev_priv, pll);
100
101 config[id].crtc_mask &= ~(1 << crtc->pipe);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200102}
103
104/* For ILK+ */
105void assert_shared_dpll(struct drm_i915_private *dev_priv,
106 struct intel_shared_dpll *pll,
107 bool state)
108{
109 bool cur_state;
110 struct intel_dpll_hw_state hw_state;
111
112 if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
113 return;
114
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200115 cur_state = pll->funcs.get_hw_state(dev_priv, pll, &hw_state);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200116 I915_STATE_WARN(cur_state != state,
117 "%s assertion failure (expected %s, current %s)\n",
118 pll->name, onoff(state), onoff(cur_state));
119}
120
121void intel_prepare_shared_dpll(struct intel_crtc *crtc)
122{
123 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100124 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200125 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200126
127 if (WARN_ON(pll == NULL))
128 return;
129
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100130 mutex_lock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200131 WARN_ON(!pll->config.crtc_mask);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100132 if (!pll->active_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200133 DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
134 WARN_ON(pll->on);
135 assert_shared_dpll_disabled(dev_priv, pll);
136
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200137 pll->funcs.mode_set(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200138 }
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100139 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200140}
141
142/**
143 * intel_enable_shared_dpll - enable PCH PLL
144 * @dev_priv: i915 private structure
145 * @pipe: pipe PLL to enable
146 *
147 * The PCH PLL needs to be enabled before the PCH transcoder, since it
148 * drives the transcoder clock.
149 */
150void intel_enable_shared_dpll(struct intel_crtc *crtc)
151{
152 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100153 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200154 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100155 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100156 unsigned old_mask;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200157
158 if (WARN_ON(pll == NULL))
159 return;
160
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100161 mutex_lock(&dev_priv->dpll_lock);
162 old_mask = pll->active_mask;
163
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100164 if (WARN_ON(!(pll->config.crtc_mask & crtc_mask)) ||
165 WARN_ON(pll->active_mask & crtc_mask))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100166 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200167
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100168 pll->active_mask |= crtc_mask;
169
170 DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n",
171 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200172 crtc->base.base.id);
173
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100174 if (old_mask) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200175 WARN_ON(!pll->on);
176 assert_shared_dpll_enabled(dev_priv, pll);
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100177 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200178 }
179 WARN_ON(pll->on);
180
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200181 DRM_DEBUG_KMS("enabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200182 pll->funcs.enable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200183 pll->on = true;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100184
185out:
186 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200187}
188
189void intel_disable_shared_dpll(struct intel_crtc *crtc)
190{
191 struct drm_device *dev = crtc->base.dev;
Chris Wilsonfac5e232016-07-04 11:34:36 +0100192 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200193 struct intel_shared_dpll *pll = crtc->config->shared_dpll;
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100194 unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200195
196 /* PCH only available on ILK+ */
197 if (INTEL_INFO(dev)->gen < 5)
198 return;
199
200 if (pll == NULL)
201 return;
202
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100203 mutex_lock(&dev_priv->dpll_lock);
Maarten Lankhorsta1475e72016-03-14 09:27:53 +0100204 if (WARN_ON(!(pll->active_mask & crtc_mask)))
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100205 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200206
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100207 DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
208 pll->name, pll->active_mask, pll->on,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200209 crtc->base.base.id);
210
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200211 assert_shared_dpll_enabled(dev_priv, pll);
212 WARN_ON(!pll->on);
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100213
214 pll->active_mask &= ~crtc_mask;
215 if (pll->active_mask)
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100216 goto out;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200217
218 DRM_DEBUG_KMS("disabling %s\n", pll->name);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200219 pll->funcs.disable(dev_priv, pll);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200220 pll->on = false;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +0100221
222out:
223 mutex_unlock(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200224}
225
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200226static struct intel_shared_dpll *
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200227intel_find_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200228 struct intel_crtc_state *crtc_state,
229 enum intel_dpll_id range_min,
230 enum intel_dpll_id range_max)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200231{
Chris Wilsonfac5e232016-07-04 11:34:36 +0100232 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200233 struct intel_shared_dpll *pll;
234 struct intel_shared_dpll_config *shared_dpll;
235 enum intel_dpll_id i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200236
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200237 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
238
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200239 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200240 pll = &dev_priv->shared_dplls[i];
241
242 /* Only want to check enabled timings first */
243 if (shared_dpll[i].crtc_mask == 0)
244 continue;
245
246 if (memcmp(&crtc_state->dpll_hw_state,
247 &shared_dpll[i].hw_state,
248 sizeof(crtc_state->dpll_hw_state)) == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300249 DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
250 crtc->base.base.id, crtc->base.name, pll->name,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200251 shared_dpll[i].crtc_mask,
Maarten Lankhorst2dd66ebd2016-03-14 09:27:52 +0100252 pll->active_mask);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200253 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200254 }
255 }
256
257 /* Ok no matching timings, maybe there's a free one? */
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200258 for (i = range_min; i <= range_max; i++) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200259 pll = &dev_priv->shared_dplls[i];
260 if (shared_dpll[i].crtc_mask == 0) {
Ville Syrjälä78108b72016-05-27 20:59:19 +0300261 DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n",
262 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200263 return pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200264 }
265 }
266
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200267 return NULL;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200268}
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200269
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200270static void
271intel_reference_shared_dpll(struct intel_shared_dpll *pll,
272 struct intel_crtc_state *crtc_state)
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200273{
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200274 struct intel_shared_dpll_config *shared_dpll;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200275 struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc);
276 enum intel_dpll_id i = pll->id;
Ander Conselvan de Oliveiraa4780b72016-03-08 17:46:17 +0200277
278 shared_dpll = intel_atomic_get_shared_dpll_state(crtc_state->base.state);
279
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200280 if (shared_dpll[i].crtc_mask == 0)
281 shared_dpll[i].hw_state =
282 crtc_state->dpll_hw_state;
283
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200284 crtc_state->shared_dpll = pll;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200285 DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->name,
286 pipe_name(crtc->pipe));
287
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200288 intel_shared_dpll_config_get(shared_dpll, pll, crtc);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200289}
290
291void intel_shared_dpll_commit(struct drm_atomic_state *state)
292{
293 struct drm_i915_private *dev_priv = to_i915(state->dev);
294 struct intel_shared_dpll_config *shared_dpll;
295 struct intel_shared_dpll *pll;
296 enum intel_dpll_id i;
297
298 if (!to_intel_atomic_state(state)->dpll_set)
299 return;
300
301 shared_dpll = to_intel_atomic_state(state)->shared_dpll;
302 for (i = 0; i < dev_priv->num_shared_dpll; i++) {
303 pll = &dev_priv->shared_dplls[i];
304 pll->config = shared_dpll[i];
305 }
306}
307
308static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
309 struct intel_shared_dpll *pll,
310 struct intel_dpll_hw_state *hw_state)
311{
312 uint32_t val;
313
314 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
315 return false;
316
317 val = I915_READ(PCH_DPLL(pll->id));
318 hw_state->dpll = val;
319 hw_state->fp0 = I915_READ(PCH_FP0(pll->id));
320 hw_state->fp1 = I915_READ(PCH_FP1(pll->id));
321
322 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
323
324 return val & DPLL_VCO_ENABLE;
325}
326
327static void ibx_pch_dpll_mode_set(struct drm_i915_private *dev_priv,
328 struct intel_shared_dpll *pll)
329{
330 I915_WRITE(PCH_FP0(pll->id), pll->config.hw_state.fp0);
331 I915_WRITE(PCH_FP1(pll->id), pll->config.hw_state.fp1);
332}
333
334static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
335{
336 u32 val;
337 bool enabled;
338
Joonas Lahtinen2d1fe072016-04-07 11:08:05 +0300339 I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200340
341 val = I915_READ(PCH_DREF_CONTROL);
342 enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
343 DREF_SUPERSPREAD_SOURCE_MASK));
344 I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
345}
346
347static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
348 struct intel_shared_dpll *pll)
349{
350 /* PCH refclock must be enabled first */
351 ibx_assert_pch_refclk_enabled(dev_priv);
352
353 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
354
355 /* Wait for the clocks to stabilize. */
356 POSTING_READ(PCH_DPLL(pll->id));
357 udelay(150);
358
359 /* The pixel multiplier can only be updated once the
360 * DPLL is enabled and the clocks are stable.
361 *
362 * So write it again.
363 */
364 I915_WRITE(PCH_DPLL(pll->id), pll->config.hw_state.dpll);
365 POSTING_READ(PCH_DPLL(pll->id));
366 udelay(200);
367}
368
369static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
370 struct intel_shared_dpll *pll)
371{
Chris Wilson91c8a322016-07-05 10:40:23 +0100372 struct drm_device *dev = &dev_priv->drm;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200373 struct intel_crtc *crtc;
374
375 /* Make sure no transcoder isn't still depending on us. */
376 for_each_intel_crtc(dev, crtc) {
Ander Conselvan de Oliveira8106ddb2016-03-08 17:46:18 +0200377 if (crtc->config->shared_dpll == pll)
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200378 assert_pch_transcoder_disabled(dev_priv, crtc->pipe);
379 }
380
381 I915_WRITE(PCH_DPLL(pll->id), 0);
382 POSTING_READ(PCH_DPLL(pll->id));
383 udelay(200);
384}
385
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200386static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200387ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
388 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200389{
390 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
391 struct intel_shared_dpll *pll;
392 enum intel_dpll_id i;
393
394 if (HAS_PCH_IBX(dev_priv)) {
395 /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
396 i = (enum intel_dpll_id) crtc->pipe;
397 pll = &dev_priv->shared_dplls[i];
398
Ville Syrjälä78108b72016-05-27 20:59:19 +0300399 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
400 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200401 } else {
402 pll = intel_find_shared_dpll(crtc, crtc_state,
403 DPLL_ID_PCH_PLL_A,
404 DPLL_ID_PCH_PLL_B);
405 }
406
Ander Conselvan de Oliveirabb143162016-05-20 15:47:06 +0300407 if (!pll)
408 return NULL;
409
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200410 /* reference the pll */
411 intel_reference_shared_dpll(pll, crtc_state);
412
413 return pll;
414}
415
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200416static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
417 .mode_set = ibx_pch_dpll_mode_set,
418 .enable = ibx_pch_dpll_enable,
419 .disable = ibx_pch_dpll_disable,
420 .get_hw_state = ibx_pch_dpll_get_hw_state,
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +0200421};
422
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200423static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
424 struct intel_shared_dpll *pll)
425{
426 I915_WRITE(WRPLL_CTL(pll->id), pll->config.hw_state.wrpll);
427 POSTING_READ(WRPLL_CTL(pll->id));
428 udelay(20);
429}
430
431static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
432 struct intel_shared_dpll *pll)
433{
434 I915_WRITE(SPLL_CTL, pll->config.hw_state.spll);
435 POSTING_READ(SPLL_CTL);
436 udelay(20);
437}
438
439static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
440 struct intel_shared_dpll *pll)
441{
442 uint32_t val;
443
444 val = I915_READ(WRPLL_CTL(pll->id));
445 I915_WRITE(WRPLL_CTL(pll->id), val & ~WRPLL_PLL_ENABLE);
446 POSTING_READ(WRPLL_CTL(pll->id));
447}
448
449static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
450 struct intel_shared_dpll *pll)
451{
452 uint32_t val;
453
454 val = I915_READ(SPLL_CTL);
455 I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
456 POSTING_READ(SPLL_CTL);
457}
458
459static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
460 struct intel_shared_dpll *pll,
461 struct intel_dpll_hw_state *hw_state)
462{
463 uint32_t val;
464
465 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
466 return false;
467
468 val = I915_READ(WRPLL_CTL(pll->id));
469 hw_state->wrpll = val;
470
471 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
472
473 return val & WRPLL_PLL_ENABLE;
474}
475
476static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
477 struct intel_shared_dpll *pll,
478 struct intel_dpll_hw_state *hw_state)
479{
480 uint32_t val;
481
482 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
483 return false;
484
485 val = I915_READ(SPLL_CTL);
486 hw_state->spll = val;
487
488 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
489
490 return val & SPLL_PLL_ENABLE;
491}
492
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200493#define LC_FREQ 2700
494#define LC_FREQ_2K U64_C(LC_FREQ * 2000)
495
496#define P_MIN 2
497#define P_MAX 64
498#define P_INC 2
499
500/* Constraints for PLL good behavior */
501#define REF_MIN 48
502#define REF_MAX 400
503#define VCO_MIN 2400
504#define VCO_MAX 4800
505
506struct hsw_wrpll_rnp {
507 unsigned p, n2, r2;
508};
509
510static unsigned hsw_wrpll_get_budget_for_freq(int clock)
511{
512 unsigned budget;
513
514 switch (clock) {
515 case 25175000:
516 case 25200000:
517 case 27000000:
518 case 27027000:
519 case 37762500:
520 case 37800000:
521 case 40500000:
522 case 40541000:
523 case 54000000:
524 case 54054000:
525 case 59341000:
526 case 59400000:
527 case 72000000:
528 case 74176000:
529 case 74250000:
530 case 81000000:
531 case 81081000:
532 case 89012000:
533 case 89100000:
534 case 108000000:
535 case 108108000:
536 case 111264000:
537 case 111375000:
538 case 148352000:
539 case 148500000:
540 case 162000000:
541 case 162162000:
542 case 222525000:
543 case 222750000:
544 case 296703000:
545 case 297000000:
546 budget = 0;
547 break;
548 case 233500000:
549 case 245250000:
550 case 247750000:
551 case 253250000:
552 case 298000000:
553 budget = 1500;
554 break;
555 case 169128000:
556 case 169500000:
557 case 179500000:
558 case 202000000:
559 budget = 2000;
560 break;
561 case 256250000:
562 case 262500000:
563 case 270000000:
564 case 272500000:
565 case 273750000:
566 case 280750000:
567 case 281250000:
568 case 286000000:
569 case 291750000:
570 budget = 4000;
571 break;
572 case 267250000:
573 case 268500000:
574 budget = 5000;
575 break;
576 default:
577 budget = 1000;
578 break;
579 }
580
581 return budget;
582}
583
584static void hsw_wrpll_update_rnp(uint64_t freq2k, unsigned budget,
585 unsigned r2, unsigned n2, unsigned p,
586 struct hsw_wrpll_rnp *best)
587{
588 uint64_t a, b, c, d, diff, diff_best;
589
590 /* No best (r,n,p) yet */
591 if (best->p == 0) {
592 best->p = p;
593 best->n2 = n2;
594 best->r2 = r2;
595 return;
596 }
597
598 /*
599 * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
600 * freq2k.
601 *
602 * delta = 1e6 *
603 * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
604 * freq2k;
605 *
606 * and we would like delta <= budget.
607 *
608 * If the discrepancy is above the PPM-based budget, always prefer to
609 * improve upon the previous solution. However, if you're within the
610 * budget, try to maximize Ref * VCO, that is N / (P * R^2).
611 */
612 a = freq2k * budget * p * r2;
613 b = freq2k * budget * best->p * best->r2;
614 diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
615 diff_best = abs_diff(freq2k * best->p * best->r2,
616 LC_FREQ_2K * best->n2);
617 c = 1000000 * diff;
618 d = 1000000 * diff_best;
619
620 if (a < c && b < d) {
621 /* If both are above the budget, pick the closer */
622 if (best->p * best->r2 * diff < p * r2 * diff_best) {
623 best->p = p;
624 best->n2 = n2;
625 best->r2 = r2;
626 }
627 } else if (a >= c && b < d) {
628 /* If A is below the threshold but B is above it? Update. */
629 best->p = p;
630 best->n2 = n2;
631 best->r2 = r2;
632 } else if (a >= c && b >= d) {
633 /* Both are below the limit, so pick the higher n2/(r2*r2) */
634 if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
635 best->p = p;
636 best->n2 = n2;
637 best->r2 = r2;
638 }
639 }
640 /* Otherwise a < c && b >= d, do nothing */
641}
642
643static void
644hsw_ddi_calculate_wrpll(int clock /* in Hz */,
645 unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
646{
647 uint64_t freq2k;
648 unsigned p, n2, r2;
649 struct hsw_wrpll_rnp best = { 0, 0, 0 };
650 unsigned budget;
651
652 freq2k = clock / 100;
653
654 budget = hsw_wrpll_get_budget_for_freq(clock);
655
656 /* Special case handling for 540 pixel clock: bypass WR PLL entirely
657 * and directly pass the LC PLL to it. */
658 if (freq2k == 5400000) {
659 *n2_out = 2;
660 *p_out = 1;
661 *r2_out = 2;
662 return;
663 }
664
665 /*
666 * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
667 * the WR PLL.
668 *
669 * We want R so that REF_MIN <= Ref <= REF_MAX.
670 * Injecting R2 = 2 * R gives:
671 * REF_MAX * r2 > LC_FREQ * 2 and
672 * REF_MIN * r2 < LC_FREQ * 2
673 *
674 * Which means the desired boundaries for r2 are:
675 * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
676 *
677 */
678 for (r2 = LC_FREQ * 2 / REF_MAX + 1;
679 r2 <= LC_FREQ * 2 / REF_MIN;
680 r2++) {
681
682 /*
683 * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
684 *
685 * Once again we want VCO_MIN <= VCO <= VCO_MAX.
686 * Injecting R2 = 2 * R and N2 = 2 * N, we get:
687 * VCO_MAX * r2 > n2 * LC_FREQ and
688 * VCO_MIN * r2 < n2 * LC_FREQ)
689 *
690 * Which means the desired boundaries for n2 are:
691 * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
692 */
693 for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
694 n2 <= VCO_MAX * r2 / LC_FREQ;
695 n2++) {
696
697 for (p = P_MIN; p <= P_MAX; p += P_INC)
698 hsw_wrpll_update_rnp(freq2k, budget,
699 r2, n2, p, &best);
700 }
701 }
702
703 *n2_out = best.n2;
704 *p_out = best.p;
705 *r2_out = best.r2;
706}
707
Manasi Navare81b9fd82016-09-01 15:08:11 -0700708static struct intel_shared_dpll *hsw_ddi_hdmi_get_dpll(int clock,
709 struct intel_crtc *crtc,
710 struct intel_crtc_state *crtc_state)
711{
712 struct intel_shared_dpll *pll;
713 uint32_t val;
714 unsigned int p, n2, r2;
715
716 hsw_ddi_calculate_wrpll(clock * 1000, &r2, &n2, &p);
717
718 val = WRPLL_PLL_ENABLE | WRPLL_PLL_LCPLL |
719 WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
720 WRPLL_DIVIDER_POST(p);
721
722 crtc_state->dpll_hw_state.wrpll = val;
723
724 pll = intel_find_shared_dpll(crtc, crtc_state,
725 DPLL_ID_WRPLL1, DPLL_ID_WRPLL2);
726
727 if (!pll)
728 return NULL;
729
730 return pll;
731}
732
733struct intel_shared_dpll *hsw_ddi_dp_get_dpll(struct intel_encoder *encoder,
734 int clock)
735{
736 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
737 struct intel_shared_dpll *pll;
738 enum intel_dpll_id pll_id;
739
740 switch (clock / 2) {
741 case 81000:
742 pll_id = DPLL_ID_LCPLL_810;
743 break;
744 case 135000:
745 pll_id = DPLL_ID_LCPLL_1350;
746 break;
747 case 270000:
748 pll_id = DPLL_ID_LCPLL_2700;
749 break;
750 default:
751 DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
752 return NULL;
753 }
754
755 pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
756
757 if (!pll)
758 return NULL;
759
760 return pll;
761}
762
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200763static struct intel_shared_dpll *
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200764hsw_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
765 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200766{
767 struct intel_shared_dpll *pll;
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200768 int clock = crtc_state->port_clock;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200769
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200770 memset(&crtc_state->dpll_hw_state, 0,
771 sizeof(crtc_state->dpll_hw_state));
772
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200773 if (encoder->type == INTEL_OUTPUT_HDMI) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700774 pll = hsw_ddi_hdmi_get_dpll(clock, crtc, crtc_state);
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200775
Ville Syrjäläcca05022016-06-22 21:57:06 +0300776 } else if (encoder->type == INTEL_OUTPUT_DP ||
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200777 encoder->type == INTEL_OUTPUT_DP_MST ||
778 encoder->type == INTEL_OUTPUT_EDP) {
Manasi Navare81b9fd82016-09-01 15:08:11 -0700779 pll = hsw_ddi_dp_get_dpll(encoder, clock);
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200780
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200781 } else if (encoder->type == INTEL_OUTPUT_ANALOG) {
782 if (WARN_ON(crtc_state->port_clock / 2 != 135000))
783 return NULL;
784
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200785 crtc_state->dpll_hw_state.spll =
786 SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
787
788 pll = intel_find_shared_dpll(crtc, crtc_state,
789 DPLL_ID_SPLL, DPLL_ID_SPLL);
790 } else {
791 return NULL;
792 }
793
794 if (!pll)
795 return NULL;
796
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +0200797 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +0200798
799 return pll;
800}
801
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200802static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
803 .enable = hsw_ddi_wrpll_enable,
804 .disable = hsw_ddi_wrpll_disable,
805 .get_hw_state = hsw_ddi_wrpll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200806};
807
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +0200808static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
809 .enable = hsw_ddi_spll_enable,
810 .disable = hsw_ddi_spll_disable,
811 .get_hw_state = hsw_ddi_spll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200812};
813
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +0200814static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
815 struct intel_shared_dpll *pll)
816{
817}
818
819static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
820 struct intel_shared_dpll *pll)
821{
822}
823
824static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
825 struct intel_shared_dpll *pll,
826 struct intel_dpll_hw_state *hw_state)
827{
828 return true;
829}
830
831static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
832 .enable = hsw_ddi_lcpll_enable,
833 .disable = hsw_ddi_lcpll_disable,
834 .get_hw_state = hsw_ddi_lcpll_get_hw_state,
835};
836
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200837struct skl_dpll_regs {
838 i915_reg_t ctl, cfgcr1, cfgcr2;
839};
840
841/* this array is indexed by the *shared* pll id */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200842static const struct skl_dpll_regs skl_dpll_regs[4] = {
843 {
844 /* DPLL 0 */
845 .ctl = LCPLL1_CTL,
846 /* DPLL 0 doesn't support HDMI mode */
847 },
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200848 {
849 /* DPLL 1 */
850 .ctl = LCPLL2_CTL,
851 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
852 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
853 },
854 {
855 /* DPLL 2 */
856 .ctl = WRPLL_CTL(0),
857 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
858 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
859 },
860 {
861 /* DPLL 3 */
862 .ctl = WRPLL_CTL(1),
863 .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
864 .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
865 },
866};
867
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200868static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
869 struct intel_shared_dpll *pll)
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200870{
871 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200872
873 val = I915_READ(DPLL_CTRL1);
874
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200875 val &= ~(DPLL_CTRL1_HDMI_MODE(pll->id) | DPLL_CTRL1_SSC(pll->id) |
876 DPLL_CTRL1_LINK_RATE_MASK(pll->id));
877 val |= pll->config.hw_state.ctrl1 << (pll->id * 6);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200878
879 I915_WRITE(DPLL_CTRL1, val);
880 POSTING_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200881}
882
883static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
884 struct intel_shared_dpll *pll)
885{
886 const struct skl_dpll_regs *regs = skl_dpll_regs;
887
888 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200889
890 I915_WRITE(regs[pll->id].cfgcr1, pll->config.hw_state.cfgcr1);
891 I915_WRITE(regs[pll->id].cfgcr2, pll->config.hw_state.cfgcr2);
892 POSTING_READ(regs[pll->id].cfgcr1);
893 POSTING_READ(regs[pll->id].cfgcr2);
894
895 /* the enable bit is always bit 31 */
896 I915_WRITE(regs[pll->id].ctl,
897 I915_READ(regs[pll->id].ctl) | LCPLL_PLL_ENABLE);
898
Chris Wilson27bf23a2016-06-30 15:33:12 +0100899 if (intel_wait_for_register(dev_priv,
900 DPLL_STATUS,
901 DPLL_LOCK(pll->id),
902 DPLL_LOCK(pll->id),
903 5))
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200904 DRM_ERROR("DPLL %d not locked\n", pll->id);
905}
906
907static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
908 struct intel_shared_dpll *pll)
909{
910 skl_ddi_pll_write_ctrl1(dev_priv, pll);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200911}
912
913static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
914 struct intel_shared_dpll *pll)
915{
916 const struct skl_dpll_regs *regs = skl_dpll_regs;
917
918 /* the enable bit is always bit 31 */
919 I915_WRITE(regs[pll->id].ctl,
920 I915_READ(regs[pll->id].ctl) & ~LCPLL_PLL_ENABLE);
921 POSTING_READ(regs[pll->id].ctl);
922}
923
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200924static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
925 struct intel_shared_dpll *pll)
926{
927}
928
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200929static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
930 struct intel_shared_dpll *pll,
931 struct intel_dpll_hw_state *hw_state)
932{
933 uint32_t val;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200934 const struct skl_dpll_regs *regs = skl_dpll_regs;
935 bool ret;
936
937 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
938 return false;
939
940 ret = false;
941
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200942 val = I915_READ(regs[pll->id].ctl);
943 if (!(val & LCPLL_PLL_ENABLE))
944 goto out;
945
946 val = I915_READ(DPLL_CTRL1);
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200947 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200948
949 /* avoid reading back stale values if HDMI mode is not enabled */
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200950 if (val & DPLL_CTRL1_HDMI_MODE(pll->id)) {
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +0200951 hw_state->cfgcr1 = I915_READ(regs[pll->id].cfgcr1);
952 hw_state->cfgcr2 = I915_READ(regs[pll->id].cfgcr2);
953 }
954 ret = true;
955
956out:
957 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
958
959 return ret;
960}
961
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +0200962static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
963 struct intel_shared_dpll *pll,
964 struct intel_dpll_hw_state *hw_state)
965{
966 uint32_t val;
967 const struct skl_dpll_regs *regs = skl_dpll_regs;
968 bool ret;
969
970 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
971 return false;
972
973 ret = false;
974
975 /* DPLL0 is always enabled since it drives CDCLK */
976 val = I915_READ(regs[pll->id].ctl);
977 if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
978 goto out;
979
980 val = I915_READ(DPLL_CTRL1);
981 hw_state->ctrl1 = (val >> (pll->id * 6)) & 0x3f;
982
983 ret = true;
984
985out:
986 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
987
988 return ret;
989}
990
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +0200991struct skl_wrpll_context {
992 uint64_t min_deviation; /* current minimal deviation */
993 uint64_t central_freq; /* chosen central freq */
994 uint64_t dco_freq; /* chosen dco freq */
995 unsigned int p; /* chosen divider */
996};
997
998static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
999{
1000 memset(ctx, 0, sizeof(*ctx));
1001
1002 ctx->min_deviation = U64_MAX;
1003}
1004
1005/* DCO freq must be within +1%/-6% of the DCO central freq */
1006#define SKL_DCO_MAX_PDEVIATION 100
1007#define SKL_DCO_MAX_NDEVIATION 600
1008
1009static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
1010 uint64_t central_freq,
1011 uint64_t dco_freq,
1012 unsigned int divider)
1013{
1014 uint64_t deviation;
1015
1016 deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
1017 central_freq);
1018
1019 /* positive deviation */
1020 if (dco_freq >= central_freq) {
1021 if (deviation < SKL_DCO_MAX_PDEVIATION &&
1022 deviation < ctx->min_deviation) {
1023 ctx->min_deviation = deviation;
1024 ctx->central_freq = central_freq;
1025 ctx->dco_freq = dco_freq;
1026 ctx->p = divider;
1027 }
1028 /* negative deviation */
1029 } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
1030 deviation < ctx->min_deviation) {
1031 ctx->min_deviation = deviation;
1032 ctx->central_freq = central_freq;
1033 ctx->dco_freq = dco_freq;
1034 ctx->p = divider;
1035 }
1036}
1037
1038static void skl_wrpll_get_multipliers(unsigned int p,
1039 unsigned int *p0 /* out */,
1040 unsigned int *p1 /* out */,
1041 unsigned int *p2 /* out */)
1042{
1043 /* even dividers */
1044 if (p % 2 == 0) {
1045 unsigned int half = p / 2;
1046
1047 if (half == 1 || half == 2 || half == 3 || half == 5) {
1048 *p0 = 2;
1049 *p1 = 1;
1050 *p2 = half;
1051 } else if (half % 2 == 0) {
1052 *p0 = 2;
1053 *p1 = half / 2;
1054 *p2 = 2;
1055 } else if (half % 3 == 0) {
1056 *p0 = 3;
1057 *p1 = half / 3;
1058 *p2 = 2;
1059 } else if (half % 7 == 0) {
1060 *p0 = 7;
1061 *p1 = half / 7;
1062 *p2 = 2;
1063 }
1064 } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
1065 *p0 = 3;
1066 *p1 = 1;
1067 *p2 = p / 3;
1068 } else if (p == 5 || p == 7) {
1069 *p0 = p;
1070 *p1 = 1;
1071 *p2 = 1;
1072 } else if (p == 15) {
1073 *p0 = 3;
1074 *p1 = 1;
1075 *p2 = 5;
1076 } else if (p == 21) {
1077 *p0 = 7;
1078 *p1 = 1;
1079 *p2 = 3;
1080 } else if (p == 35) {
1081 *p0 = 7;
1082 *p1 = 1;
1083 *p2 = 5;
1084 }
1085}
1086
1087struct skl_wrpll_params {
1088 uint32_t dco_fraction;
1089 uint32_t dco_integer;
1090 uint32_t qdiv_ratio;
1091 uint32_t qdiv_mode;
1092 uint32_t kdiv;
1093 uint32_t pdiv;
1094 uint32_t central_freq;
1095};
1096
1097static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
1098 uint64_t afe_clock,
1099 uint64_t central_freq,
1100 uint32_t p0, uint32_t p1, uint32_t p2)
1101{
1102 uint64_t dco_freq;
1103
1104 switch (central_freq) {
1105 case 9600000000ULL:
1106 params->central_freq = 0;
1107 break;
1108 case 9000000000ULL:
1109 params->central_freq = 1;
1110 break;
1111 case 8400000000ULL:
1112 params->central_freq = 3;
1113 }
1114
1115 switch (p0) {
1116 case 1:
1117 params->pdiv = 0;
1118 break;
1119 case 2:
1120 params->pdiv = 1;
1121 break;
1122 case 3:
1123 params->pdiv = 2;
1124 break;
1125 case 7:
1126 params->pdiv = 4;
1127 break;
1128 default:
1129 WARN(1, "Incorrect PDiv\n");
1130 }
1131
1132 switch (p2) {
1133 case 5:
1134 params->kdiv = 0;
1135 break;
1136 case 2:
1137 params->kdiv = 1;
1138 break;
1139 case 3:
1140 params->kdiv = 2;
1141 break;
1142 case 1:
1143 params->kdiv = 3;
1144 break;
1145 default:
1146 WARN(1, "Incorrect KDiv\n");
1147 }
1148
1149 params->qdiv_ratio = p1;
1150 params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1151
1152 dco_freq = p0 * p1 * p2 * afe_clock;
1153
1154 /*
1155 * Intermediate values are in Hz.
1156 * Divide by MHz to match bsepc
1157 */
1158 params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1159 params->dco_fraction =
1160 div_u64((div_u64(dco_freq, 24) -
1161 params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1162}
1163
1164static bool
1165skl_ddi_calculate_wrpll(int clock /* in Hz */,
1166 struct skl_wrpll_params *wrpll_params)
1167{
1168 uint64_t afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1169 uint64_t dco_central_freq[3] = {8400000000ULL,
1170 9000000000ULL,
1171 9600000000ULL};
1172 static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1173 24, 28, 30, 32, 36, 40, 42, 44,
1174 48, 52, 54, 56, 60, 64, 66, 68,
1175 70, 72, 76, 78, 80, 84, 88, 90,
1176 92, 96, 98 };
1177 static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1178 static const struct {
1179 const int *list;
1180 int n_dividers;
1181 } dividers[] = {
1182 { even_dividers, ARRAY_SIZE(even_dividers) },
1183 { odd_dividers, ARRAY_SIZE(odd_dividers) },
1184 };
1185 struct skl_wrpll_context ctx;
1186 unsigned int dco, d, i;
1187 unsigned int p0, p1, p2;
1188
1189 skl_wrpll_context_init(&ctx);
1190
1191 for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1192 for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1193 for (i = 0; i < dividers[d].n_dividers; i++) {
1194 unsigned int p = dividers[d].list[i];
1195 uint64_t dco_freq = p * afe_clock;
1196
1197 skl_wrpll_try_divider(&ctx,
1198 dco_central_freq[dco],
1199 dco_freq,
1200 p);
1201 /*
1202 * Skip the remaining dividers if we're sure to
1203 * have found the definitive divider, we can't
1204 * improve a 0 deviation.
1205 */
1206 if (ctx.min_deviation == 0)
1207 goto skip_remaining_dividers;
1208 }
1209 }
1210
1211skip_remaining_dividers:
1212 /*
1213 * If a solution is found with an even divider, prefer
1214 * this one.
1215 */
1216 if (d == 0 && ctx.p)
1217 break;
1218 }
1219
1220 if (!ctx.p) {
1221 DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1222 return false;
1223 }
1224
1225 /*
1226 * gcc incorrectly analyses that these can be used without being
1227 * initialized. To be fair, it's hard to guess.
1228 */
1229 p0 = p1 = p2 = 0;
1230 skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1231 skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1232 p0, p1, p2);
1233
1234 return true;
1235}
1236
Jim Bride9a4edad2016-09-01 15:08:10 -07001237static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc *crtc,
1238 struct intel_crtc_state *crtc_state,
1239 int clock)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001240{
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001241 uint32_t ctrl1, cfgcr1, cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001242 struct skl_wrpll_params wrpll_params = { 0, };
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001243
1244 /*
1245 * See comment in intel_dpll_hw_state to understand why we always use 0
1246 * as the DPLL id in this function.
1247 */
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001248 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1249
Jim Bride9a4edad2016-09-01 15:08:10 -07001250 ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001251
Jim Bride9a4edad2016-09-01 15:08:10 -07001252 if (!skl_ddi_calculate_wrpll(clock * 1000, &wrpll_params))
1253 return false;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001254
Jim Bride9a4edad2016-09-01 15:08:10 -07001255 cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1256 DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1257 wrpll_params.dco_integer;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001258
Jim Bride9a4edad2016-09-01 15:08:10 -07001259 cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1260 DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1261 DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1262 DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1263 wrpll_params.central_freq;
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001264
1265 memset(&crtc_state->dpll_hw_state, 0,
1266 sizeof(crtc_state->dpll_hw_state));
1267
1268 crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1269 crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1270 crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
Jim Bride9a4edad2016-09-01 15:08:10 -07001271 return true;
1272}
1273
1274
1275bool skl_ddi_dp_set_dpll_hw_state(int clock,
1276 struct intel_dpll_hw_state *dpll_hw_state)
1277{
1278 uint32_t ctrl1;
1279
1280 /*
1281 * See comment in intel_dpll_hw_state to understand why we always use 0
1282 * as the DPLL id in this function.
1283 */
1284 ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1285 switch (clock / 2) {
1286 case 81000:
1287 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1288 break;
1289 case 135000:
1290 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1291 break;
1292 case 270000:
1293 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1294 break;
1295 /* eDP 1.4 rates */
1296 case 162000:
1297 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
1298 break;
1299 case 108000:
1300 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
1301 break;
1302 case 216000:
1303 ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
1304 break;
1305 }
1306
1307 dpll_hw_state->ctrl1 = ctrl1;
1308 return true;
1309}
1310
1311static struct intel_shared_dpll *
1312skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
1313 struct intel_encoder *encoder)
1314{
1315 struct intel_shared_dpll *pll;
1316 int clock = crtc_state->port_clock;
1317 bool bret;
1318 struct intel_dpll_hw_state dpll_hw_state;
1319
1320 memset(&dpll_hw_state, 0, sizeof(dpll_hw_state));
1321
1322 if (encoder->type == INTEL_OUTPUT_HDMI) {
1323 bret = skl_ddi_hdmi_pll_dividers(crtc, crtc_state, clock);
1324 if (!bret) {
1325 DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n");
1326 return NULL;
1327 }
1328 } else if (encoder->type == INTEL_OUTPUT_DP ||
1329 encoder->type == INTEL_OUTPUT_DP_MST ||
1330 encoder->type == INTEL_OUTPUT_EDP) {
1331 bret = skl_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state);
1332 if (!bret) {
1333 DRM_DEBUG_KMS("Could not set DP dpll HW state.\n");
1334 return NULL;
1335 }
1336 crtc_state->dpll_hw_state = dpll_hw_state;
1337 } else {
1338 return NULL;
1339 }
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001340
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001341 if (encoder->type == INTEL_OUTPUT_EDP)
1342 pll = intel_find_shared_dpll(crtc, crtc_state,
1343 DPLL_ID_SKL_DPLL0,
1344 DPLL_ID_SKL_DPLL0);
1345 else
1346 pll = intel_find_shared_dpll(crtc, crtc_state,
1347 DPLL_ID_SKL_DPLL1,
1348 DPLL_ID_SKL_DPLL3);
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001349 if (!pll)
1350 return NULL;
1351
Ander Conselvan de Oliveira304b65c2016-03-08 17:46:24 +02001352 intel_reference_shared_dpll(pll, crtc_state);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001353
1354 return pll;
1355}
1356
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001357static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1358 .enable = skl_ddi_pll_enable,
1359 .disable = skl_ddi_pll_disable,
1360 .get_hw_state = skl_ddi_pll_get_hw_state,
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001361};
1362
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001363static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
1364 .enable = skl_ddi_dpll0_enable,
1365 .disable = skl_ddi_dpll0_disable,
1366 .get_hw_state = skl_ddi_dpll0_get_hw_state,
1367};
1368
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001369static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1370 struct intel_shared_dpll *pll)
1371{
1372 uint32_t temp;
1373 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1374
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001375 /* Non-SSC reference */
Dongwon Kimda6110b2016-04-14 15:37:43 -07001376 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1377 temp |= PORT_PLL_REF_SEL;
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001378 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1379
1380 /* Disable 10 bit clock */
1381 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
1382 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1383 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1384
1385 /* Write P1 & P2 */
1386 temp = I915_READ(BXT_PORT_PLL_EBB_0(port));
1387 temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
1388 temp |= pll->config.hw_state.ebb0;
1389 I915_WRITE(BXT_PORT_PLL_EBB_0(port), temp);
1390
1391 /* Write M2 integer */
1392 temp = I915_READ(BXT_PORT_PLL(port, 0));
1393 temp &= ~PORT_PLL_M2_MASK;
1394 temp |= pll->config.hw_state.pll0;
1395 I915_WRITE(BXT_PORT_PLL(port, 0), temp);
1396
1397 /* Write N */
1398 temp = I915_READ(BXT_PORT_PLL(port, 1));
1399 temp &= ~PORT_PLL_N_MASK;
1400 temp |= pll->config.hw_state.pll1;
1401 I915_WRITE(BXT_PORT_PLL(port, 1), temp);
1402
1403 /* Write M2 fraction */
1404 temp = I915_READ(BXT_PORT_PLL(port, 2));
1405 temp &= ~PORT_PLL_M2_FRAC_MASK;
1406 temp |= pll->config.hw_state.pll2;
1407 I915_WRITE(BXT_PORT_PLL(port, 2), temp);
1408
1409 /* Write M2 fraction enable */
1410 temp = I915_READ(BXT_PORT_PLL(port, 3));
1411 temp &= ~PORT_PLL_M2_FRAC_ENABLE;
1412 temp |= pll->config.hw_state.pll3;
1413 I915_WRITE(BXT_PORT_PLL(port, 3), temp);
1414
1415 /* Write coeff */
1416 temp = I915_READ(BXT_PORT_PLL(port, 6));
1417 temp &= ~PORT_PLL_PROP_COEFF_MASK;
1418 temp &= ~PORT_PLL_INT_COEFF_MASK;
1419 temp &= ~PORT_PLL_GAIN_CTL_MASK;
1420 temp |= pll->config.hw_state.pll6;
1421 I915_WRITE(BXT_PORT_PLL(port, 6), temp);
1422
1423 /* Write calibration val */
1424 temp = I915_READ(BXT_PORT_PLL(port, 8));
1425 temp &= ~PORT_PLL_TARGET_CNT_MASK;
1426 temp |= pll->config.hw_state.pll8;
1427 I915_WRITE(BXT_PORT_PLL(port, 8), temp);
1428
1429 temp = I915_READ(BXT_PORT_PLL(port, 9));
1430 temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
1431 temp |= pll->config.hw_state.pll9;
1432 I915_WRITE(BXT_PORT_PLL(port, 9), temp);
1433
1434 temp = I915_READ(BXT_PORT_PLL(port, 10));
1435 temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1436 temp &= ~PORT_PLL_DCO_AMP_MASK;
1437 temp |= pll->config.hw_state.pll10;
1438 I915_WRITE(BXT_PORT_PLL(port, 10), temp);
1439
1440 /* Recalibrate with new settings */
1441 temp = I915_READ(BXT_PORT_PLL_EBB_4(port));
1442 temp |= PORT_PLL_RECALIBRATE;
1443 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1444 temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1445 temp |= pll->config.hw_state.ebb4;
1446 I915_WRITE(BXT_PORT_PLL_EBB_4(port), temp);
1447
1448 /* Enable PLL */
1449 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1450 temp |= PORT_PLL_ENABLE;
1451 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1452 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1453
Imre Deak0b786e42016-06-28 13:37:30 +03001454 if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
1455 200))
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001456 DRM_ERROR("PLL %d not locked\n", port);
1457
1458 /*
1459 * While we write to the group register to program all lanes at once we
1460 * can read only lane registers and we pick lanes 0/1 for that.
1461 */
1462 temp = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
1463 temp &= ~LANE_STAGGER_MASK;
1464 temp &= ~LANESTAGGER_STRAP_OVRD;
1465 temp |= pll->config.hw_state.pcsdw12;
1466 I915_WRITE(BXT_PORT_PCS_DW12_GRP(port), temp);
1467}
1468
1469static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1470 struct intel_shared_dpll *pll)
1471{
1472 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1473 uint32_t temp;
1474
1475 temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1476 temp &= ~PORT_PLL_ENABLE;
1477 I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1478 POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1479}
1480
1481static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1482 struct intel_shared_dpll *pll,
1483 struct intel_dpll_hw_state *hw_state)
1484{
1485 enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
1486 uint32_t val;
1487 bool ret;
1488
1489 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
1490 return false;
1491
1492 ret = false;
1493
1494 val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1495 if (!(val & PORT_PLL_ENABLE))
1496 goto out;
1497
1498 hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(port));
1499 hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1500
1501 hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(port));
1502 hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1503
1504 hw_state->pll0 = I915_READ(BXT_PORT_PLL(port, 0));
1505 hw_state->pll0 &= PORT_PLL_M2_MASK;
1506
1507 hw_state->pll1 = I915_READ(BXT_PORT_PLL(port, 1));
1508 hw_state->pll1 &= PORT_PLL_N_MASK;
1509
1510 hw_state->pll2 = I915_READ(BXT_PORT_PLL(port, 2));
1511 hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1512
1513 hw_state->pll3 = I915_READ(BXT_PORT_PLL(port, 3));
1514 hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1515
1516 hw_state->pll6 = I915_READ(BXT_PORT_PLL(port, 6));
1517 hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1518 PORT_PLL_INT_COEFF_MASK |
1519 PORT_PLL_GAIN_CTL_MASK;
1520
1521 hw_state->pll8 = I915_READ(BXT_PORT_PLL(port, 8));
1522 hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1523
1524 hw_state->pll9 = I915_READ(BXT_PORT_PLL(port, 9));
1525 hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1526
1527 hw_state->pll10 = I915_READ(BXT_PORT_PLL(port, 10));
1528 hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1529 PORT_PLL_DCO_AMP_MASK;
1530
1531 /*
1532 * While we write to the group register to program all lanes at once we
1533 * can read only lane registers. We configure all lanes the same way, so
1534 * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1535 */
1536 hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(port));
1537 if (I915_READ(BXT_PORT_PCS_DW12_LN23(port)) != hw_state->pcsdw12)
1538 DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1539 hw_state->pcsdw12,
1540 I915_READ(BXT_PORT_PCS_DW12_LN23(port)));
1541 hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1542
1543 ret = true;
1544
1545out:
1546 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
1547
1548 return ret;
1549}
1550
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001551/* bxt clock parameters */
1552struct bxt_clk_div {
1553 int clock;
1554 uint32_t p1;
1555 uint32_t p2;
1556 uint32_t m2_int;
1557 uint32_t m2_frac;
1558 bool m2_frac_en;
1559 uint32_t n;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001560
1561 int vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001562};
1563
1564/* pre-calculated values for DP linkrates */
1565static const struct bxt_clk_div bxt_dp_clk_val[] = {
1566 {162000, 4, 2, 32, 1677722, 1, 1},
1567 {270000, 4, 1, 27, 0, 0, 1},
1568 {540000, 2, 1, 27, 0, 0, 1},
1569 {216000, 3, 2, 32, 1677722, 1, 1},
1570 {243000, 4, 1, 24, 1258291, 1, 1},
1571 {324000, 4, 1, 32, 1677722, 1, 1},
1572 {432000, 3, 1, 32, 1677722, 1, 1}
1573};
1574
Durgadoss Ra277ca72016-09-01 15:08:09 -07001575static bool
1576bxt_ddi_hdmi_pll_dividers(struct intel_crtc *intel_crtc,
1577 struct intel_crtc_state *crtc_state, int clock,
1578 struct bxt_clk_div *clk_div)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001579{
Durgadoss Ra277ca72016-09-01 15:08:09 -07001580 struct dpll best_clock;
1581
1582 /* Calculate HDMI div */
1583 /*
1584 * FIXME: tie the following calculation into
1585 * i9xx_crtc_compute_clock
1586 */
1587 if (!bxt_find_best_dpll(crtc_state, clock, &best_clock)) {
1588 DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1589 clock, pipe_name(intel_crtc->pipe));
1590 return false;
1591 }
1592
1593 clk_div->p1 = best_clock.p1;
1594 clk_div->p2 = best_clock.p2;
1595 WARN_ON(best_clock.m1 != 2);
1596 clk_div->n = best_clock.n;
1597 clk_div->m2_int = best_clock.m2 >> 22;
1598 clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
1599 clk_div->m2_frac_en = clk_div->m2_frac != 0;
1600
1601 clk_div->vco = best_clock.vco;
1602
1603 return true;
1604}
1605
1606static void bxt_ddi_dp_pll_dividers(int clock, struct bxt_clk_div *clk_div)
1607{
1608 int i;
1609
1610 *clk_div = bxt_dp_clk_val[0];
1611 for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1612 if (bxt_dp_clk_val[i].clock == clock) {
1613 *clk_div = bxt_dp_clk_val[i];
1614 break;
1615 }
1616 }
1617
1618 clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
1619}
1620
1621static bool bxt_ddi_set_dpll_hw_state(int clock,
1622 struct bxt_clk_div *clk_div,
1623 struct intel_dpll_hw_state *dpll_hw_state)
1624{
1625 int vco = clk_div->vco;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001626 uint32_t prop_coef, int_coef, gain_ctl, targ_cnt;
1627 uint32_t lanestagger;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001628
1629 if (vco >= 6200000 && vco <= 6700000) {
1630 prop_coef = 4;
1631 int_coef = 9;
1632 gain_ctl = 3;
1633 targ_cnt = 8;
1634 } else if ((vco > 5400000 && vco < 6200000) ||
1635 (vco >= 4800000 && vco < 5400000)) {
1636 prop_coef = 5;
1637 int_coef = 11;
1638 gain_ctl = 3;
1639 targ_cnt = 9;
1640 } else if (vco == 5400000) {
1641 prop_coef = 3;
1642 int_coef = 8;
1643 gain_ctl = 1;
1644 targ_cnt = 9;
1645 } else {
1646 DRM_ERROR("Invalid VCO\n");
Durgadoss Ra277ca72016-09-01 15:08:09 -07001647 return false;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001648 }
1649
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001650 if (clock > 270000)
1651 lanestagger = 0x18;
1652 else if (clock > 135000)
1653 lanestagger = 0x0d;
1654 else if (clock > 67000)
1655 lanestagger = 0x07;
1656 else if (clock > 33000)
1657 lanestagger = 0x04;
1658 else
1659 lanestagger = 0x02;
1660
Durgadoss Ra277ca72016-09-01 15:08:09 -07001661 dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
1662 dpll_hw_state->pll0 = clk_div->m2_int;
1663 dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
1664 dpll_hw_state->pll2 = clk_div->m2_frac;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001665
Durgadoss Ra277ca72016-09-01 15:08:09 -07001666 if (clk_div->m2_frac_en)
1667 dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001668
Durgadoss Ra277ca72016-09-01 15:08:09 -07001669 dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
1670 dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001671
Durgadoss Ra277ca72016-09-01 15:08:09 -07001672 dpll_hw_state->pll8 = targ_cnt;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001673
Durgadoss Ra277ca72016-09-01 15:08:09 -07001674 dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001675
Durgadoss Ra277ca72016-09-01 15:08:09 -07001676 dpll_hw_state->pll10 =
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001677 PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1678 | PORT_PLL_DCO_AMP_OVR_EN_H;
1679
Durgadoss Ra277ca72016-09-01 15:08:09 -07001680 dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001681
Durgadoss Ra277ca72016-09-01 15:08:09 -07001682 dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger;
1683
1684 return true;
1685}
1686
1687bool bxt_ddi_dp_set_dpll_hw_state(int clock,
1688 struct intel_dpll_hw_state *dpll_hw_state)
1689{
1690 struct bxt_clk_div clk_div = {0};
1691
1692 bxt_ddi_dp_pll_dividers(clock, &clk_div);
1693
1694 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1695}
1696
Imre Deaka04139c2016-09-26 17:54:31 +03001697static bool
1698bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc *intel_crtc,
1699 struct intel_crtc_state *crtc_state, int clock,
1700 struct intel_dpll_hw_state *dpll_hw_state)
1701{
1702 struct bxt_clk_div clk_div = { };
1703
1704 bxt_ddi_hdmi_pll_dividers(intel_crtc, crtc_state, clock, &clk_div);
1705
1706 return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state);
1707}
1708
Durgadoss Ra277ca72016-09-01 15:08:09 -07001709static struct intel_shared_dpll *
1710bxt_get_dpll(struct intel_crtc *crtc,
1711 struct intel_crtc_state *crtc_state,
1712 struct intel_encoder *encoder)
1713{
Imre Deaka04139c2016-09-26 17:54:31 +03001714 struct intel_dpll_hw_state dpll_hw_state = { };
Durgadoss Ra277ca72016-09-01 15:08:09 -07001715 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1716 struct intel_digital_port *intel_dig_port;
1717 struct intel_shared_dpll *pll;
1718 int i, clock = crtc_state->port_clock;
1719
Imre Deaka04139c2016-09-26 17:54:31 +03001720 if (encoder->type == INTEL_OUTPUT_HDMI &&
1721 !bxt_ddi_hdmi_set_dpll_hw_state(crtc, crtc_state, clock,
1722 &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001723 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001724
1725 if ((encoder->type == INTEL_OUTPUT_DP ||
1726 encoder->type == INTEL_OUTPUT_EDP) &&
1727 !bxt_ddi_dp_set_dpll_hw_state(clock, &dpll_hw_state))
Jani Nikulabcbfcc32016-09-15 16:28:53 +03001728 return NULL;
Durgadoss Ra277ca72016-09-01 15:08:09 -07001729
1730 memset(&crtc_state->dpll_hw_state, 0,
1731 sizeof(crtc_state->dpll_hw_state));
1732
1733 crtc_state->dpll_hw_state = dpll_hw_state;
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001734
Maarten Lankhorsta79e8cc2016-08-09 17:04:00 +02001735 if (encoder->type == INTEL_OUTPUT_DP_MST) {
1736 struct intel_dp_mst_encoder *intel_mst = enc_to_mst(&encoder->base);
1737
1738 intel_dig_port = intel_mst->primary;
1739 } else
1740 intel_dig_port = enc_to_dig_port(&encoder->base);
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001741
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001742 /* 1:1 mapping between ports and PLLs */
Ander Conselvan de Oliveira34177c22016-03-08 17:46:25 +02001743 i = (enum intel_dpll_id) intel_dig_port->port;
1744 pll = intel_get_shared_dpll_by_id(dev_priv, i);
1745
Ville Syrjälä78108b72016-05-27 20:59:19 +03001746 DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
1747 crtc->base.base.id, crtc->base.name, pll->name);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001748
1749 intel_reference_shared_dpll(pll, crtc_state);
1750
1751 return pll;
1752}
1753
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001754static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1755 .enable = bxt_ddi_pll_enable,
1756 .disable = bxt_ddi_pll_disable,
1757 .get_hw_state = bxt_ddi_pll_get_hw_state,
1758};
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001759
1760static void intel_ddi_pll_init(struct drm_device *dev)
1761{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001762 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001763
Ville Syrjälä9f7eb312016-05-13 23:41:29 +03001764 if (INTEL_GEN(dev_priv) < 9) {
1765 uint32_t val = I915_READ(LCPLL_CTL);
Ville Syrjäläb2045352016-05-13 23:41:27 +03001766
Ander Conselvan de Oliveira55be2f02016-03-08 17:46:16 +02001767 /*
1768 * The LCPLL register should be turned on by the BIOS. For now
1769 * let's just check its state and print errors in case
1770 * something is wrong. Don't even try to turn it on.
1771 */
1772
1773 if (val & LCPLL_CD_SOURCE_FCLK)
1774 DRM_ERROR("CDCLK source is not LCPLL\n");
1775
1776 if (val & LCPLL_PLL_DISABLE)
1777 DRM_ERROR("LCPLL is disabled\n");
1778 }
1779}
1780
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001781struct dpll_info {
1782 const char *name;
1783 const int id;
1784 const struct intel_shared_dpll_funcs *funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001785 uint32_t flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001786};
1787
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001788struct intel_dpll_mgr {
1789 const struct dpll_info *dpll_info;
1790
1791 struct intel_shared_dpll *(*get_dpll)(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001792 struct intel_crtc_state *crtc_state,
1793 struct intel_encoder *encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001794};
1795
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001796static const struct dpll_info pch_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001797 { "PCH DPLL A", DPLL_ID_PCH_PLL_A, &ibx_pch_dpll_funcs, 0 },
1798 { "PCH DPLL B", DPLL_ID_PCH_PLL_B, &ibx_pch_dpll_funcs, 0 },
1799 { NULL, -1, NULL, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001800};
1801
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001802static const struct intel_dpll_mgr pch_pll_mgr = {
1803 .dpll_info = pch_plls,
1804 .get_dpll = ibx_get_dpll,
1805};
1806
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001807static const struct dpll_info hsw_plls[] = {
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001808 { "WRPLL 1", DPLL_ID_WRPLL1, &hsw_ddi_wrpll_funcs, 0 },
1809 { "WRPLL 2", DPLL_ID_WRPLL2, &hsw_ddi_wrpll_funcs, 0 },
1810 { "SPLL", DPLL_ID_SPLL, &hsw_ddi_spll_funcs, 0 },
1811 { "LCPLL 810", DPLL_ID_LCPLL_810, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1812 { "LCPLL 1350", DPLL_ID_LCPLL_1350, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
1813 { "LCPLL 2700", DPLL_ID_LCPLL_2700, &hsw_ddi_lcpll_funcs, INTEL_DPLL_ALWAYS_ON },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001814 { NULL, -1, NULL, },
1815};
1816
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001817static const struct intel_dpll_mgr hsw_pll_mgr = {
1818 .dpll_info = hsw_plls,
1819 .get_dpll = hsw_get_dpll,
1820};
1821
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001822static const struct dpll_info skl_plls[] = {
Ander Conselvan de Oliveiraa3c988e2016-03-08 17:46:27 +02001823 { "DPLL 0", DPLL_ID_SKL_DPLL0, &skl_ddi_dpll0_funcs, INTEL_DPLL_ALWAYS_ON },
Ville Syrjäläd5aab9d2016-05-11 22:04:33 +03001824 { "DPLL 1", DPLL_ID_SKL_DPLL1, &skl_ddi_pll_funcs, 0 },
1825 { "DPLL 2", DPLL_ID_SKL_DPLL2, &skl_ddi_pll_funcs, 0 },
1826 { "DPLL 3", DPLL_ID_SKL_DPLL3, &skl_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001827 { NULL, -1, NULL, },
1828};
1829
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001830static const struct intel_dpll_mgr skl_pll_mgr = {
1831 .dpll_info = skl_plls,
1832 .get_dpll = skl_get_dpll,
1833};
1834
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001835static const struct dpll_info bxt_plls[] = {
Imre Deak08250c42016-03-14 19:55:34 +02001836 { "PORT PLL A", DPLL_ID_SKL_DPLL0, &bxt_ddi_pll_funcs, 0 },
1837 { "PORT PLL B", DPLL_ID_SKL_DPLL1, &bxt_ddi_pll_funcs, 0 },
1838 { "PORT PLL C", DPLL_ID_SKL_DPLL2, &bxt_ddi_pll_funcs, 0 },
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001839 { NULL, -1, NULL, },
1840};
1841
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001842static const struct intel_dpll_mgr bxt_pll_mgr = {
1843 .dpll_info = bxt_plls,
1844 .get_dpll = bxt_get_dpll,
1845};
1846
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001847void intel_shared_dpll_init(struct drm_device *dev)
1848{
Chris Wilsonfac5e232016-07-04 11:34:36 +01001849 struct drm_i915_private *dev_priv = to_i915(dev);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001850 const struct intel_dpll_mgr *dpll_mgr = NULL;
1851 const struct dpll_info *dpll_info;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001852 int i;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001853
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001854 if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001855 dpll_mgr = &skl_pll_mgr;
Imre Deak08250c42016-03-14 19:55:34 +02001856 else if (IS_BROXTON(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001857 dpll_mgr = &bxt_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001858 else if (HAS_DDI(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001859 dpll_mgr = &hsw_pll_mgr;
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001860 else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001861 dpll_mgr = &pch_pll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001862
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001863 if (!dpll_mgr) {
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001864 dev_priv->num_shared_dpll = 0;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001865 return;
1866 }
1867
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001868 dpll_info = dpll_mgr->dpll_info;
1869
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001870 for (i = 0; dpll_info[i].id >= 0; i++) {
1871 WARN_ON(i != dpll_info[i].id);
1872
1873 dev_priv->shared_dplls[i].id = dpll_info[i].id;
1874 dev_priv->shared_dplls[i].name = dpll_info[i].name;
1875 dev_priv->shared_dplls[i].funcs = *dpll_info[i].funcs;
Ander Conselvan de Oliveira9d16da62016-03-08 17:46:26 +02001876 dev_priv->shared_dplls[i].flags = dpll_info[i].flags;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001877 }
1878
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001879 dev_priv->dpll_mgr = dpll_mgr;
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001880 dev_priv->num_shared_dpll = i;
Maarten Lankhorstfbf6d872016-03-23 14:51:12 +01001881 mutex_init(&dev_priv->dpll_lock);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001882
1883 BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
Ander Conselvan de Oliveira2edd6442016-03-08 17:46:21 +02001884
1885 /* FIXME: Move this to a more suitable place */
1886 if (HAS_DDI(dev))
1887 intel_ddi_pll_init(dev);
Ander Conselvan de Oliveira7abd4b32016-03-08 17:46:15 +02001888}
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001889
1890struct intel_shared_dpll *
1891intel_get_shared_dpll(struct intel_crtc *crtc,
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001892 struct intel_crtc_state *crtc_state,
1893 struct intel_encoder *encoder)
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001894{
1895 struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1896 const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
1897
1898 if (WARN_ON(!dpll_mgr))
1899 return NULL;
1900
Ander Conselvan de Oliveiradaedf202016-03-08 17:46:23 +02001901 return dpll_mgr->get_dpll(crtc, crtc_state, encoder);
Ander Conselvan de Oliveiraf9476a62016-03-08 17:46:22 +02001902}