Branch data Line data Source code
1 : : /*
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_display_types.h"
25 : : #include "intel_dpio_phy.h"
26 : : #include "intel_dpll_mgr.h"
27 : :
28 : : /**
29 : : * DOC: Display PLLs
30 : : *
31 : : * Display PLLs used for driving outputs vary by platform. While some have
32 : : * per-pipe or per-encoder dedicated PLLs, others allow the use of any PLL
33 : : * from a pool. In the latter scenario, it is possible that multiple pipes
34 : : * share a PLL if their configurations match.
35 : : *
36 : : * This file provides an abstraction over display PLLs. The function
37 : : * intel_shared_dpll_init() initializes the PLLs for the given platform. The
38 : : * users of a PLL are tracked and that tracking is integrated with the atomic
39 : : * modset interface. During an atomic operation, required PLLs can be reserved
40 : : * for a given CRTC and encoder configuration by calling
41 : : * intel_reserve_shared_dplls() and previously reserved PLLs can be released
42 : : * with intel_release_shared_dplls().
43 : : * Changes to the users are first staged in the atomic state, and then made
44 : : * effective by calling intel_shared_dpll_swap_state() during the atomic
45 : : * commit phase.
46 : : */
47 : :
48 : : static void
49 : 0 : intel_atomic_duplicate_dpll_state(struct drm_i915_private *dev_priv,
50 : : struct intel_shared_dpll_state *shared_dpll)
51 : : {
52 : : enum intel_dpll_id i;
53 : :
54 : : /* Copy shared dpll state */
55 [ # # ]: 0 : for (i = 0; i < dev_priv->num_shared_dpll; i++) {
56 : 0 : struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
57 : :
58 : 0 : shared_dpll[i] = pll->state;
59 : : }
60 : : }
61 : :
62 : : static struct intel_shared_dpll_state *
63 : 0 : intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s)
64 : : {
65 : 0 : struct intel_atomic_state *state = to_intel_atomic_state(s);
66 : :
67 [ # # ]: 0 : WARN_ON(!drm_modeset_is_locked(&s->dev->mode_config.connection_mutex));
68 : :
69 [ # # ]: 0 : if (!state->dpll_set) {
70 : 0 : state->dpll_set = true;
71 : :
72 : 0 : intel_atomic_duplicate_dpll_state(to_i915(s->dev),
73 : 0 : state->shared_dpll);
74 : : }
75 : :
76 : 0 : return state->shared_dpll;
77 : : }
78 : :
79 : : /**
80 : : * intel_get_shared_dpll_by_id - get a DPLL given its id
81 : : * @dev_priv: i915 device instance
82 : : * @id: pll id
83 : : *
84 : : * Returns:
85 : : * A pointer to the DPLL with @id
86 : : */
87 : : struct intel_shared_dpll *
88 : 0 : intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
89 : : enum intel_dpll_id id)
90 : : {
91 : 0 : return &dev_priv->shared_dplls[id];
92 : : }
93 : :
94 : : /**
95 : : * intel_get_shared_dpll_id - get the id of a DPLL
96 : : * @dev_priv: i915 device instance
97 : : * @pll: the DPLL
98 : : *
99 : : * Returns:
100 : : * The id of @pll
101 : : */
102 : : enum intel_dpll_id
103 : 0 : intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
104 : : struct intel_shared_dpll *pll)
105 : : {
106 [ # # # # : 0 : if (WARN_ON(pll < dev_priv->shared_dplls||
# # # # ]
107 : : pll > &dev_priv->shared_dplls[dev_priv->num_shared_dpll]))
108 : : return -1;
109 : :
110 : 0 : return (enum intel_dpll_id) (pll - dev_priv->shared_dplls);
111 : : }
112 : :
113 : : /* For ILK+ */
114 : 0 : void assert_shared_dpll(struct drm_i915_private *dev_priv,
115 : : struct intel_shared_dpll *pll,
116 : : bool state)
117 : : {
118 : 0 : bool cur_state;
119 : 0 : struct intel_dpll_hw_state hw_state;
120 : :
121 [ # # # # : 0 : if (WARN(!pll, "asserting DPLL %s with no DPLL\n", onoff(state)))
# # ]
122 : 0 : return;
123 : :
124 : 0 : cur_state = pll->info->funcs->get_hw_state(dev_priv, pll, &hw_state);
125 [ # # # # : 0 : I915_STATE_WARN(cur_state != state,
# # # # #
# ]
126 : : "%s assertion failure (expected %s, current %s)\n",
127 : : pll->info->name, onoff(state), onoff(cur_state));
128 : : }
129 : :
130 : : /**
131 : : * intel_prepare_shared_dpll - call a dpll's prepare hook
132 : : * @crtc_state: CRTC, and its state, which has a shared dpll
133 : : *
134 : : * This calls the PLL's prepare hook if it has one and if the PLL is not
135 : : * already enabled. The prepare hook is platform specific.
136 : : */
137 : 0 : void intel_prepare_shared_dpll(const struct intel_crtc_state *crtc_state)
138 : : {
139 : 0 : struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
140 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
141 : 0 : struct intel_shared_dpll *pll = crtc_state->shared_dpll;
142 : :
143 [ # # # # ]: 0 : if (WARN_ON(pll == NULL))
144 : : return;
145 : :
146 : 0 : mutex_lock(&dev_priv->dpll_lock);
147 [ # # ]: 0 : WARN_ON(!pll->state.crtc_mask);
148 [ # # ]: 0 : if (!pll->active_mask) {
149 : 0 : DRM_DEBUG_DRIVER("setting up %s\n", pll->info->name);
150 [ # # ]: 0 : WARN_ON(pll->on);
151 : 0 : assert_shared_dpll_disabled(dev_priv, pll);
152 : :
153 : 0 : pll->info->funcs->prepare(dev_priv, pll);
154 : : }
155 : 0 : mutex_unlock(&dev_priv->dpll_lock);
156 : : }
157 : :
158 : : /**
159 : : * intel_enable_shared_dpll - enable a CRTC's shared DPLL
160 : : * @crtc_state: CRTC, and its state, which has a shared DPLL
161 : : *
162 : : * Enable the shared DPLL used by @crtc.
163 : : */
164 : 0 : void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state)
165 : : {
166 : 0 : struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
167 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
168 : 0 : struct intel_shared_dpll *pll = crtc_state->shared_dpll;
169 [ # # ]: 0 : unsigned int crtc_mask = drm_crtc_mask(&crtc->base);
170 : 0 : unsigned int old_mask;
171 : :
172 [ # # # # ]: 0 : if (WARN_ON(pll == NULL))
173 : : return;
174 : :
175 : 0 : mutex_lock(&dev_priv->dpll_lock);
176 : 0 : old_mask = pll->active_mask;
177 : :
178 [ # # # # ]: 0 : if (WARN_ON(!(pll->state.crtc_mask & crtc_mask)) ||
179 [ # # # # ]: 0 : WARN_ON(pll->active_mask & crtc_mask))
180 : 0 : goto out;
181 : :
182 : 0 : pll->active_mask |= crtc_mask;
183 : :
184 : 0 : DRM_DEBUG_KMS("enable %s (active %x, on? %d) for crtc %d\n",
185 : : pll->info->name, pll->active_mask, pll->on,
186 : : crtc->base.base.id);
187 : :
188 [ # # ]: 0 : if (old_mask) {
189 [ # # ]: 0 : WARN_ON(!pll->on);
190 : 0 : assert_shared_dpll_enabled(dev_priv, pll);
191 : 0 : goto out;
192 : : }
193 [ # # ]: 0 : WARN_ON(pll->on);
194 : :
195 : 0 : DRM_DEBUG_KMS("enabling %s\n", pll->info->name);
196 : 0 : pll->info->funcs->enable(dev_priv, pll);
197 : 0 : pll->on = true;
198 : :
199 : 0 : out:
200 : 0 : mutex_unlock(&dev_priv->dpll_lock);
201 : : }
202 : :
203 : : /**
204 : : * intel_disable_shared_dpll - disable a CRTC's shared DPLL
205 : : * @crtc_state: CRTC, and its state, which has a shared DPLL
206 : : *
207 : : * Disable the shared DPLL used by @crtc.
208 : : */
209 : 0 : void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state)
210 : : {
211 : 0 : struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
212 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
213 : 0 : struct intel_shared_dpll *pll = crtc_state->shared_dpll;
214 [ # # ]: 0 : unsigned int crtc_mask = drm_crtc_mask(&crtc->base);
215 : :
216 : : /* PCH only available on ILK+ */
217 [ # # ]: 0 : if (INTEL_GEN(dev_priv) < 5)
218 : : return;
219 : :
220 [ # # ]: 0 : if (pll == NULL)
221 : : return;
222 : :
223 : 0 : mutex_lock(&dev_priv->dpll_lock);
224 [ # # # # ]: 0 : if (WARN_ON(!(pll->active_mask & crtc_mask)))
225 : 0 : goto out;
226 : :
227 : 0 : DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
228 : : pll->info->name, pll->active_mask, pll->on,
229 : : crtc->base.base.id);
230 : :
231 : 0 : assert_shared_dpll_enabled(dev_priv, pll);
232 [ # # ]: 0 : WARN_ON(!pll->on);
233 : :
234 : 0 : pll->active_mask &= ~crtc_mask;
235 [ # # ]: 0 : if (pll->active_mask)
236 : 0 : goto out;
237 : :
238 : 0 : DRM_DEBUG_KMS("disabling %s\n", pll->info->name);
239 : 0 : pll->info->funcs->disable(dev_priv, pll);
240 : 0 : pll->on = false;
241 : :
242 : 0 : out:
243 : 0 : mutex_unlock(&dev_priv->dpll_lock);
244 : : }
245 : :
246 : : static struct intel_shared_dpll *
247 : 0 : intel_find_shared_dpll(struct intel_atomic_state *state,
248 : : const struct intel_crtc *crtc,
249 : : const struct intel_dpll_hw_state *pll_state,
250 : : unsigned long dpll_mask)
251 : : {
252 : 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
253 : 0 : struct intel_shared_dpll *pll, *unused_pll = NULL;
254 : 0 : struct intel_shared_dpll_state *shared_dpll;
255 : 0 : enum intel_dpll_id i;
256 : :
257 : 0 : shared_dpll = intel_atomic_get_shared_dpll_state(&state->base);
258 : :
259 [ # # ]: 0 : WARN_ON(dpll_mask & ~(BIT(I915_NUM_PLLS) - 1));
260 : :
261 [ # # ]: 0 : for_each_set_bit(i, &dpll_mask, I915_NUM_PLLS) {
262 : 0 : pll = &dev_priv->shared_dplls[i];
263 : :
264 : : /* Only want to check enabled timings first */
265 [ # # ]: 0 : if (shared_dpll[i].crtc_mask == 0) {
266 [ # # ]: 0 : if (!unused_pll)
267 : 0 : unused_pll = pll;
268 : 0 : continue;
269 : : }
270 : :
271 : 0 : if (memcmp(pll_state,
272 [ # # ]: 0 : &shared_dpll[i].hw_state,
273 : : sizeof(*pll_state)) == 0) {
274 : 0 : DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
275 : : crtc->base.base.id, crtc->base.name,
276 : : pll->info->name,
277 : : shared_dpll[i].crtc_mask,
278 : : pll->active_mask);
279 : 0 : return pll;
280 : : }
281 : : }
282 : :
283 : : /* Ok no matching timings, maybe there's a free one? */
284 [ # # ]: 0 : if (unused_pll) {
285 : 0 : DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n",
286 : : crtc->base.base.id, crtc->base.name,
287 : : unused_pll->info->name);
288 : 0 : return unused_pll;
289 : : }
290 : :
291 : : return NULL;
292 : : }
293 : :
294 : : static void
295 : : intel_reference_shared_dpll(struct intel_atomic_state *state,
296 : : const struct intel_crtc *crtc,
297 : : const struct intel_shared_dpll *pll,
298 : : const struct intel_dpll_hw_state *pll_state)
299 : : {
300 : : struct intel_shared_dpll_state *shared_dpll;
301 : : const enum intel_dpll_id id = pll->info->id;
302 : :
303 : : shared_dpll = intel_atomic_get_shared_dpll_state(&state->base);
304 : :
305 : : if (shared_dpll[id].crtc_mask == 0)
306 : : shared_dpll[id].hw_state = *pll_state;
307 : :
308 : : DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->info->name,
309 : : pipe_name(crtc->pipe));
310 : :
311 : : shared_dpll[id].crtc_mask |= 1 << crtc->pipe;
312 : : }
313 : :
314 : : static void intel_unreference_shared_dpll(struct intel_atomic_state *state,
315 : : const struct intel_crtc *crtc,
316 : : const struct intel_shared_dpll *pll)
317 : : {
318 : : struct intel_shared_dpll_state *shared_dpll;
319 : :
320 : : shared_dpll = intel_atomic_get_shared_dpll_state(&state->base);
321 : : shared_dpll[pll->info->id].crtc_mask &= ~(1 << crtc->pipe);
322 : : }
323 : :
324 : 0 : static void intel_put_dpll(struct intel_atomic_state *state,
325 : : struct intel_crtc *crtc)
326 : : {
327 [ # # ]: 0 : const struct intel_crtc_state *old_crtc_state =
328 : : intel_atomic_get_old_crtc_state(state, crtc);
329 [ # # ]: 0 : struct intel_crtc_state *new_crtc_state =
330 : : intel_atomic_get_new_crtc_state(state, crtc);
331 : :
332 : 0 : new_crtc_state->shared_dpll = NULL;
333 : :
334 [ # # ]: 0 : if (!old_crtc_state->shared_dpll)
335 : : return;
336 : :
337 : 0 : intel_unreference_shared_dpll(state, crtc, old_crtc_state->shared_dpll);
338 : : }
339 : :
340 : : /**
341 : : * intel_shared_dpll_swap_state - make atomic DPLL configuration effective
342 : : * @state: atomic state
343 : : *
344 : : * This is the dpll version of drm_atomic_helper_swap_state() since the
345 : : * helper does not handle driver-specific global state.
346 : : *
347 : : * For consistency with atomic helpers this function does a complete swap,
348 : : * i.e. it also puts the current state into @state, even though there is no
349 : : * need for that at this moment.
350 : : */
351 : 0 : void intel_shared_dpll_swap_state(struct intel_atomic_state *state)
352 : : {
353 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(state->base.dev);
354 : 0 : struct intel_shared_dpll_state *shared_dpll = state->shared_dpll;
355 : 0 : enum intel_dpll_id i;
356 : :
357 [ # # ]: 0 : if (!state->dpll_set)
358 : : return;
359 : :
360 [ # # ]: 0 : for (i = 0; i < dev_priv->num_shared_dpll; i++) {
361 : 0 : struct intel_shared_dpll *pll =
362 : : &dev_priv->shared_dplls[i];
363 : :
364 : 0 : swap(pll->state, shared_dpll[i]);
365 : : }
366 : : }
367 : :
368 : 0 : static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv,
369 : : struct intel_shared_dpll *pll,
370 : : struct intel_dpll_hw_state *hw_state)
371 : : {
372 : 0 : const enum intel_dpll_id id = pll->info->id;
373 : 0 : intel_wakeref_t wakeref;
374 : 0 : u32 val;
375 : :
376 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv,
377 : : POWER_DOMAIN_DISPLAY_CORE);
378 [ # # ]: 0 : if (!wakeref)
379 : : return false;
380 : :
381 [ # # ]: 0 : val = I915_READ(PCH_DPLL(id));
382 : 0 : hw_state->dpll = val;
383 [ # # ]: 0 : hw_state->fp0 = I915_READ(PCH_FP0(id));
384 [ # # ]: 0 : hw_state->fp1 = I915_READ(PCH_FP1(id));
385 : :
386 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
387 : :
388 : 0 : return val & DPLL_VCO_ENABLE;
389 : : }
390 : :
391 : 0 : static void ibx_pch_dpll_prepare(struct drm_i915_private *dev_priv,
392 : : struct intel_shared_dpll *pll)
393 : : {
394 : 0 : const enum intel_dpll_id id = pll->info->id;
395 : :
396 [ # # ]: 0 : I915_WRITE(PCH_FP0(id), pll->state.hw_state.fp0);
397 [ # # ]: 0 : I915_WRITE(PCH_FP1(id), pll->state.hw_state.fp1);
398 : 0 : }
399 : :
400 : 0 : static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
401 : : {
402 : 0 : u32 val;
403 : 0 : bool enabled;
404 : :
405 [ # # # # : 0 : I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
# # ]
406 : :
407 : 0 : val = I915_READ(PCH_DREF_CONTROL);
408 : 0 : enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
409 : : DREF_SUPERSPREAD_SOURCE_MASK));
410 [ # # # # : 0 : I915_STATE_WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
# # ]
411 : 0 : }
412 : :
413 : 0 : static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv,
414 : : struct intel_shared_dpll *pll)
415 : : {
416 : 0 : const enum intel_dpll_id id = pll->info->id;
417 : :
418 : : /* PCH refclock must be enabled first */
419 : 0 : ibx_assert_pch_refclk_enabled(dev_priv);
420 : :
421 [ # # ]: 0 : I915_WRITE(PCH_DPLL(id), pll->state.hw_state.dpll);
422 : :
423 : : /* Wait for the clocks to stabilize. */
424 : 0 : POSTING_READ(PCH_DPLL(id));
425 : 0 : udelay(150);
426 : :
427 : : /* The pixel multiplier can only be updated once the
428 : : * DPLL is enabled and the clocks are stable.
429 : : *
430 : : * So write it again.
431 : : */
432 : 0 : I915_WRITE(PCH_DPLL(id), pll->state.hw_state.dpll);
433 : 0 : POSTING_READ(PCH_DPLL(id));
434 : 0 : udelay(200);
435 : 0 : }
436 : :
437 : 0 : static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv,
438 : : struct intel_shared_dpll *pll)
439 : : {
440 : 0 : const enum intel_dpll_id id = pll->info->id;
441 : :
442 [ # # ]: 0 : I915_WRITE(PCH_DPLL(id), 0);
443 : 0 : POSTING_READ(PCH_DPLL(id));
444 : 0 : udelay(200);
445 : 0 : }
446 : :
447 : 0 : static bool ibx_get_dpll(struct intel_atomic_state *state,
448 : : struct intel_crtc *crtc,
449 : : struct intel_encoder *encoder)
450 : : {
451 [ # # ]: 0 : struct intel_crtc_state *crtc_state =
452 : : intel_atomic_get_new_crtc_state(state, crtc);
453 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
454 : 0 : struct intel_shared_dpll *pll;
455 : 0 : enum intel_dpll_id i;
456 : :
457 [ # # ]: 0 : if (HAS_PCH_IBX(dev_priv)) {
458 : : /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */
459 : 0 : i = (enum intel_dpll_id) crtc->pipe;
460 : 0 : pll = &dev_priv->shared_dplls[i];
461 : :
462 : 0 : DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
463 : : crtc->base.base.id, crtc->base.name,
464 : : pll->info->name);
465 : : } else {
466 : 0 : pll = intel_find_shared_dpll(state, crtc,
467 : 0 : &crtc_state->dpll_hw_state,
468 : : BIT(DPLL_ID_PCH_PLL_B) |
469 : : BIT(DPLL_ID_PCH_PLL_A));
470 : : }
471 : :
472 [ # # ]: 0 : if (!pll)
473 : : return false;
474 : :
475 : : /* reference the pll */
476 : 0 : intel_reference_shared_dpll(state, crtc,
477 : 0 : pll, &crtc_state->dpll_hw_state);
478 : :
479 : 0 : crtc_state->shared_dpll = pll;
480 : :
481 : 0 : return true;
482 : : }
483 : :
484 : 0 : static void ibx_dump_hw_state(struct drm_i915_private *dev_priv,
485 : : const struct intel_dpll_hw_state *hw_state)
486 : : {
487 : 0 : DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
488 : : "fp0: 0x%x, fp1: 0x%x\n",
489 : : hw_state->dpll,
490 : : hw_state->dpll_md,
491 : : hw_state->fp0,
492 : : hw_state->fp1);
493 : 0 : }
494 : :
495 : : static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = {
496 : : .prepare = ibx_pch_dpll_prepare,
497 : : .enable = ibx_pch_dpll_enable,
498 : : .disable = ibx_pch_dpll_disable,
499 : : .get_hw_state = ibx_pch_dpll_get_hw_state,
500 : : };
501 : :
502 : 0 : static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv,
503 : : struct intel_shared_dpll *pll)
504 : : {
505 : 0 : const enum intel_dpll_id id = pll->info->id;
506 : :
507 : 0 : I915_WRITE(WRPLL_CTL(id), pll->state.hw_state.wrpll);
508 : 0 : POSTING_READ(WRPLL_CTL(id));
509 : 0 : udelay(20);
510 : 0 : }
511 : :
512 : 0 : static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv,
513 : : struct intel_shared_dpll *pll)
514 : : {
515 : 0 : I915_WRITE(SPLL_CTL, pll->state.hw_state.spll);
516 : 0 : POSTING_READ(SPLL_CTL);
517 : 0 : udelay(20);
518 : 0 : }
519 : :
520 : 0 : static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv,
521 : : struct intel_shared_dpll *pll)
522 : : {
523 : 0 : const enum intel_dpll_id id = pll->info->id;
524 : 0 : u32 val;
525 : :
526 : 0 : val = I915_READ(WRPLL_CTL(id));
527 : 0 : I915_WRITE(WRPLL_CTL(id), val & ~WRPLL_PLL_ENABLE);
528 : 0 : POSTING_READ(WRPLL_CTL(id));
529 : :
530 : : /*
531 : : * Try to set up the PCH reference clock once all DPLLs
532 : : * that depend on it have been shut down.
533 : : */
534 [ # # ]: 0 : if (dev_priv->pch_ssc_use & BIT(id))
535 : 0 : intel_init_pch_refclk(dev_priv);
536 : 0 : }
537 : :
538 : 0 : static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv,
539 : : struct intel_shared_dpll *pll)
540 : : {
541 : 0 : enum intel_dpll_id id = pll->info->id;
542 : 0 : u32 val;
543 : :
544 : 0 : val = I915_READ(SPLL_CTL);
545 : 0 : I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE);
546 : 0 : POSTING_READ(SPLL_CTL);
547 : :
548 : : /*
549 : : * Try to set up the PCH reference clock once all DPLLs
550 : : * that depend on it have been shut down.
551 : : */
552 [ # # ]: 0 : if (dev_priv->pch_ssc_use & BIT(id))
553 : 0 : intel_init_pch_refclk(dev_priv);
554 : 0 : }
555 : :
556 : 0 : static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv,
557 : : struct intel_shared_dpll *pll,
558 : : struct intel_dpll_hw_state *hw_state)
559 : : {
560 : 0 : const enum intel_dpll_id id = pll->info->id;
561 : 0 : intel_wakeref_t wakeref;
562 : 0 : u32 val;
563 : :
564 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv,
565 : : POWER_DOMAIN_DISPLAY_CORE);
566 [ # # ]: 0 : if (!wakeref)
567 : : return false;
568 : :
569 : 0 : val = I915_READ(WRPLL_CTL(id));
570 : 0 : hw_state->wrpll = val;
571 : :
572 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
573 : :
574 : 0 : return val & WRPLL_PLL_ENABLE;
575 : : }
576 : :
577 : 0 : static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv,
578 : : struct intel_shared_dpll *pll,
579 : : struct intel_dpll_hw_state *hw_state)
580 : : {
581 : 0 : intel_wakeref_t wakeref;
582 : 0 : u32 val;
583 : :
584 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv,
585 : : POWER_DOMAIN_DISPLAY_CORE);
586 [ # # ]: 0 : if (!wakeref)
587 : : return false;
588 : :
589 : 0 : val = I915_READ(SPLL_CTL);
590 : 0 : hw_state->spll = val;
591 : :
592 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
593 : :
594 : 0 : return val & SPLL_PLL_ENABLE;
595 : : }
596 : :
597 : : #define LC_FREQ 2700
598 : : #define LC_FREQ_2K U64_C(LC_FREQ * 2000)
599 : :
600 : : #define P_MIN 2
601 : : #define P_MAX 64
602 : : #define P_INC 2
603 : :
604 : : /* Constraints for PLL good behavior */
605 : : #define REF_MIN 48
606 : : #define REF_MAX 400
607 : : #define VCO_MIN 2400
608 : : #define VCO_MAX 4800
609 : :
610 : : struct hsw_wrpll_rnp {
611 : : unsigned p, n2, r2;
612 : : };
613 : :
614 : 0 : static unsigned hsw_wrpll_get_budget_for_freq(int clock)
615 : : {
616 : 0 : unsigned budget;
617 : :
618 [ # # # # : 0 : switch (clock) {
# # ]
619 : : case 25175000:
620 : : case 25200000:
621 : : case 27000000:
622 : : case 27027000:
623 : : case 37762500:
624 : : case 37800000:
625 : : case 40500000:
626 : : case 40541000:
627 : : case 54000000:
628 : : case 54054000:
629 : : case 59341000:
630 : : case 59400000:
631 : : case 72000000:
632 : : case 74176000:
633 : : case 74250000:
634 : : case 81000000:
635 : : case 81081000:
636 : : case 89012000:
637 : : case 89100000:
638 : : case 108000000:
639 : : case 108108000:
640 : : case 111264000:
641 : : case 111375000:
642 : : case 148352000:
643 : : case 148500000:
644 : : case 162000000:
645 : : case 162162000:
646 : : case 222525000:
647 : : case 222750000:
648 : : case 296703000:
649 : : case 297000000:
650 : : budget = 0;
651 : : break;
652 : 0 : case 233500000:
653 : : case 245250000:
654 : : case 247750000:
655 : : case 253250000:
656 : : case 298000000:
657 : 0 : budget = 1500;
658 : 0 : break;
659 : 0 : case 169128000:
660 : : case 169500000:
661 : : case 179500000:
662 : : case 202000000:
663 : 0 : budget = 2000;
664 : 0 : break;
665 : 0 : case 256250000:
666 : : case 262500000:
667 : : case 270000000:
668 : : case 272500000:
669 : : case 273750000:
670 : : case 280750000:
671 : : case 281250000:
672 : : case 286000000:
673 : : case 291750000:
674 : 0 : budget = 4000;
675 : 0 : break;
676 : 0 : case 267250000:
677 : : case 268500000:
678 : 0 : budget = 5000;
679 : 0 : break;
680 : 0 : default:
681 : 0 : budget = 1000;
682 : 0 : break;
683 : : }
684 : :
685 : 0 : return budget;
686 : : }
687 : :
688 : 0 : static void hsw_wrpll_update_rnp(u64 freq2k, unsigned int budget,
689 : : unsigned int r2, unsigned int n2,
690 : : unsigned int p,
691 : : struct hsw_wrpll_rnp *best)
692 : : {
693 : 0 : u64 a, b, c, d, diff, diff_best;
694 : :
695 : : /* No best (r,n,p) yet */
696 [ # # ]: 0 : if (best->p == 0) {
697 : 0 : best->p = p;
698 : 0 : best->n2 = n2;
699 : 0 : best->r2 = r2;
700 : 0 : return;
701 : : }
702 : :
703 : : /*
704 : : * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to
705 : : * freq2k.
706 : : *
707 : : * delta = 1e6 *
708 : : * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) /
709 : : * freq2k;
710 : : *
711 : : * and we would like delta <= budget.
712 : : *
713 : : * If the discrepancy is above the PPM-based budget, always prefer to
714 : : * improve upon the previous solution. However, if you're within the
715 : : * budget, try to maximize Ref * VCO, that is N / (P * R^2).
716 : : */
717 : 0 : a = freq2k * budget * p * r2;
718 : 0 : b = freq2k * budget * best->p * best->r2;
719 [ # # ]: 0 : diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2);
720 [ # # ]: 0 : diff_best = abs_diff(freq2k * best->p * best->r2,
721 : : LC_FREQ_2K * best->n2);
722 : 0 : c = 1000000 * diff;
723 : 0 : d = 1000000 * diff_best;
724 : :
725 [ # # ]: 0 : if (a < c && b < d) {
726 : : /* If both are above the budget, pick the closer */
727 [ # # ]: 0 : if (best->p * best->r2 * diff < p * r2 * diff_best) {
728 : 0 : best->p = p;
729 : 0 : best->n2 = n2;
730 : 0 : best->r2 = r2;
731 : : }
732 [ # # ]: 0 : } else if (a >= c && b < d) {
733 : : /* If A is below the threshold but B is above it? Update. */
734 : 0 : best->p = p;
735 : 0 : best->n2 = n2;
736 : 0 : best->r2 = r2;
737 [ # # ]: 0 : } else if (a >= c && b >= d) {
738 : : /* Both are below the limit, so pick the higher n2/(r2*r2) */
739 [ # # ]: 0 : if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) {
740 : 0 : best->p = p;
741 : 0 : best->n2 = n2;
742 : 0 : best->r2 = r2;
743 : : }
744 : : }
745 : : /* Otherwise a < c && b >= d, do nothing */
746 : : }
747 : :
748 : : static void
749 : 0 : hsw_ddi_calculate_wrpll(int clock /* in Hz */,
750 : : unsigned *r2_out, unsigned *n2_out, unsigned *p_out)
751 : : {
752 : 0 : u64 freq2k;
753 : 0 : unsigned p, n2, r2;
754 : 0 : struct hsw_wrpll_rnp best = { 0, 0, 0 };
755 : 0 : unsigned budget;
756 : :
757 : 0 : freq2k = clock / 100;
758 : :
759 : 0 : budget = hsw_wrpll_get_budget_for_freq(clock);
760 : :
761 : : /* Special case handling for 540 pixel clock: bypass WR PLL entirely
762 : : * and directly pass the LC PLL to it. */
763 [ # # ]: 0 : if (freq2k == 5400000) {
764 : 0 : *n2_out = 2;
765 : 0 : *p_out = 1;
766 : 0 : *r2_out = 2;
767 : 0 : return;
768 : : }
769 : :
770 : : /*
771 : : * Ref = LC_FREQ / R, where Ref is the actual reference input seen by
772 : : * the WR PLL.
773 : : *
774 : : * We want R so that REF_MIN <= Ref <= REF_MAX.
775 : : * Injecting R2 = 2 * R gives:
776 : : * REF_MAX * r2 > LC_FREQ * 2 and
777 : : * REF_MIN * r2 < LC_FREQ * 2
778 : : *
779 : : * Which means the desired boundaries for r2 are:
780 : : * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN
781 : : *
782 : : */
783 : 0 : for (r2 = LC_FREQ * 2 / REF_MAX + 1;
784 [ # # ]: 0 : r2 <= LC_FREQ * 2 / REF_MIN;
785 : 0 : r2++) {
786 : :
787 : : /*
788 : : * VCO = N * Ref, that is: VCO = N * LC_FREQ / R
789 : : *
790 : : * Once again we want VCO_MIN <= VCO <= VCO_MAX.
791 : : * Injecting R2 = 2 * R and N2 = 2 * N, we get:
792 : : * VCO_MAX * r2 > n2 * LC_FREQ and
793 : : * VCO_MIN * r2 < n2 * LC_FREQ)
794 : : *
795 : : * Which means the desired boundaries for n2 are:
796 : : * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ
797 : : */
798 : 0 : for (n2 = VCO_MIN * r2 / LC_FREQ + 1;
799 [ # # ]: 0 : n2 <= VCO_MAX * r2 / LC_FREQ;
800 : 0 : n2++) {
801 : :
802 [ # # ]: 0 : for (p = P_MIN; p <= P_MAX; p += P_INC)
803 : 0 : hsw_wrpll_update_rnp(freq2k, budget,
804 : : r2, n2, p, &best);
805 : : }
806 : : }
807 : :
808 : 0 : *n2_out = best.n2;
809 : 0 : *p_out = best.p;
810 : 0 : *r2_out = best.r2;
811 : : }
812 : :
813 : : static struct intel_shared_dpll *
814 : 0 : hsw_ddi_hdmi_get_dpll(struct intel_atomic_state *state,
815 : : struct intel_crtc *crtc)
816 : : {
817 : 0 : struct intel_crtc_state *crtc_state =
818 : : intel_atomic_get_new_crtc_state(state, crtc);
819 : 0 : struct intel_shared_dpll *pll;
820 : 0 : u32 val;
821 : 0 : unsigned int p, n2, r2;
822 : :
823 : 0 : hsw_ddi_calculate_wrpll(crtc_state->port_clock * 1000, &r2, &n2, &p);
824 : :
825 : 0 : val = WRPLL_PLL_ENABLE | WRPLL_REF_LCPLL |
826 : 0 : WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) |
827 : 0 : WRPLL_DIVIDER_POST(p);
828 : :
829 : 0 : crtc_state->dpll_hw_state.wrpll = val;
830 : :
831 : 0 : pll = intel_find_shared_dpll(state, crtc,
832 : 0 : &crtc_state->dpll_hw_state,
833 : : BIT(DPLL_ID_WRPLL2) |
834 : : BIT(DPLL_ID_WRPLL1));
835 : :
836 [ # # ]: 0 : if (!pll)
837 : 0 : return NULL;
838 : :
839 : : return pll;
840 : : }
841 : :
842 : : static struct intel_shared_dpll *
843 : : hsw_ddi_dp_get_dpll(struct intel_crtc_state *crtc_state)
844 : : {
845 : : struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
846 : : struct intel_shared_dpll *pll;
847 : : enum intel_dpll_id pll_id;
848 : : int clock = crtc_state->port_clock;
849 : :
850 : : switch (clock / 2) {
851 : : case 81000:
852 : : pll_id = DPLL_ID_LCPLL_810;
853 : : break;
854 : : case 135000:
855 : : pll_id = DPLL_ID_LCPLL_1350;
856 : : break;
857 : : case 270000:
858 : : pll_id = DPLL_ID_LCPLL_2700;
859 : : break;
860 : : default:
861 : : DRM_DEBUG_KMS("Invalid clock for DP: %d\n", clock);
862 : : return NULL;
863 : : }
864 : :
865 : : pll = intel_get_shared_dpll_by_id(dev_priv, pll_id);
866 : :
867 : : if (!pll)
868 : : return NULL;
869 : :
870 : : return pll;
871 : : }
872 : :
873 : 0 : static bool hsw_get_dpll(struct intel_atomic_state *state,
874 : : struct intel_crtc *crtc,
875 : : struct intel_encoder *encoder)
876 : : {
877 [ # # ]: 0 : struct intel_crtc_state *crtc_state =
878 : : intel_atomic_get_new_crtc_state(state, crtc);
879 : 0 : struct intel_shared_dpll *pll;
880 : :
881 : 0 : memset(&crtc_state->dpll_hw_state, 0,
882 : : sizeof(crtc_state->dpll_hw_state));
883 : :
884 [ # # ]: 0 : if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
885 : 0 : pll = hsw_ddi_hdmi_get_dpll(state, crtc);
886 [ # # ]: 0 : } else if (intel_crtc_has_dp_encoder(crtc_state)) {
887 : 0 : pll = hsw_ddi_dp_get_dpll(crtc_state);
888 [ # # ]: 0 : } else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) {
889 [ # # # # ]: 0 : if (WARN_ON(crtc_state->port_clock / 2 != 135000))
890 : : return false;
891 : :
892 : 0 : crtc_state->dpll_hw_state.spll =
893 : : SPLL_PLL_ENABLE | SPLL_FREQ_1350MHz | SPLL_REF_MUXED_SSC;
894 : :
895 : 0 : pll = intel_find_shared_dpll(state, crtc,
896 : : &crtc_state->dpll_hw_state,
897 : : BIT(DPLL_ID_SPLL));
898 : : } else {
899 : : return false;
900 : : }
901 : :
902 [ # # ]: 0 : if (!pll)
903 : : return false;
904 : :
905 : 0 : intel_reference_shared_dpll(state, crtc,
906 : : pll, &crtc_state->dpll_hw_state);
907 : :
908 : 0 : crtc_state->shared_dpll = pll;
909 : :
910 : 0 : return true;
911 : : }
912 : :
913 : 0 : static void hsw_dump_hw_state(struct drm_i915_private *dev_priv,
914 : : const struct intel_dpll_hw_state *hw_state)
915 : : {
916 : 0 : DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n",
917 : : hw_state->wrpll, hw_state->spll);
918 : 0 : }
919 : :
920 : : static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = {
921 : : .enable = hsw_ddi_wrpll_enable,
922 : : .disable = hsw_ddi_wrpll_disable,
923 : : .get_hw_state = hsw_ddi_wrpll_get_hw_state,
924 : : };
925 : :
926 : : static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = {
927 : : .enable = hsw_ddi_spll_enable,
928 : : .disable = hsw_ddi_spll_disable,
929 : : .get_hw_state = hsw_ddi_spll_get_hw_state,
930 : : };
931 : :
932 : 0 : static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv,
933 : : struct intel_shared_dpll *pll)
934 : : {
935 : 0 : }
936 : :
937 : 0 : static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv,
938 : : struct intel_shared_dpll *pll)
939 : : {
940 : 0 : }
941 : :
942 : 0 : static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv,
943 : : struct intel_shared_dpll *pll,
944 : : struct intel_dpll_hw_state *hw_state)
945 : : {
946 : 0 : return true;
947 : : }
948 : :
949 : : static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = {
950 : : .enable = hsw_ddi_lcpll_enable,
951 : : .disable = hsw_ddi_lcpll_disable,
952 : : .get_hw_state = hsw_ddi_lcpll_get_hw_state,
953 : : };
954 : :
955 : : struct skl_dpll_regs {
956 : : i915_reg_t ctl, cfgcr1, cfgcr2;
957 : : };
958 : :
959 : : /* this array is indexed by the *shared* pll id */
960 : : static const struct skl_dpll_regs skl_dpll_regs[4] = {
961 : : {
962 : : /* DPLL 0 */
963 : : .ctl = LCPLL1_CTL,
964 : : /* DPLL 0 doesn't support HDMI mode */
965 : : },
966 : : {
967 : : /* DPLL 1 */
968 : : .ctl = LCPLL2_CTL,
969 : : .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1),
970 : : .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1),
971 : : },
972 : : {
973 : : /* DPLL 2 */
974 : : .ctl = WRPLL_CTL(0),
975 : : .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2),
976 : : .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2),
977 : : },
978 : : {
979 : : /* DPLL 3 */
980 : : .ctl = WRPLL_CTL(1),
981 : : .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3),
982 : : .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3),
983 : : },
984 : : };
985 : :
986 : : static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv,
987 : : struct intel_shared_dpll *pll)
988 : : {
989 : : const enum intel_dpll_id id = pll->info->id;
990 : : u32 val;
991 : :
992 : : val = I915_READ(DPLL_CTRL1);
993 : :
994 : : val &= ~(DPLL_CTRL1_HDMI_MODE(id) |
995 : : DPLL_CTRL1_SSC(id) |
996 : : DPLL_CTRL1_LINK_RATE_MASK(id));
997 : : val |= pll->state.hw_state.ctrl1 << (id * 6);
998 : :
999 : : I915_WRITE(DPLL_CTRL1, val);
1000 : : POSTING_READ(DPLL_CTRL1);
1001 : : }
1002 : :
1003 : 0 : static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv,
1004 : : struct intel_shared_dpll *pll)
1005 : : {
1006 : 0 : const struct skl_dpll_regs *regs = skl_dpll_regs;
1007 : 0 : const enum intel_dpll_id id = pll->info->id;
1008 : :
1009 : 0 : skl_ddi_pll_write_ctrl1(dev_priv, pll);
1010 : :
1011 : 0 : I915_WRITE(regs[id].cfgcr1, pll->state.hw_state.cfgcr1);
1012 : 0 : I915_WRITE(regs[id].cfgcr2, pll->state.hw_state.cfgcr2);
1013 : 0 : POSTING_READ(regs[id].cfgcr1);
1014 : 0 : POSTING_READ(regs[id].cfgcr2);
1015 : :
1016 : : /* the enable bit is always bit 31 */
1017 : 0 : I915_WRITE(regs[id].ctl,
1018 : : I915_READ(regs[id].ctl) | LCPLL_PLL_ENABLE);
1019 : :
1020 [ # # ]: 0 : if (intel_de_wait_for_set(dev_priv, DPLL_STATUS, DPLL_LOCK(id), 5))
1021 : 0 : DRM_ERROR("DPLL %d not locked\n", id);
1022 : 0 : }
1023 : :
1024 : 0 : static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv,
1025 : : struct intel_shared_dpll *pll)
1026 : : {
1027 : 0 : skl_ddi_pll_write_ctrl1(dev_priv, pll);
1028 : 0 : }
1029 : :
1030 : 0 : static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv,
1031 : : struct intel_shared_dpll *pll)
1032 : : {
1033 : 0 : const struct skl_dpll_regs *regs = skl_dpll_regs;
1034 : 0 : const enum intel_dpll_id id = pll->info->id;
1035 : :
1036 : : /* the enable bit is always bit 31 */
1037 : 0 : I915_WRITE(regs[id].ctl,
1038 : : I915_READ(regs[id].ctl) & ~LCPLL_PLL_ENABLE);
1039 : 0 : POSTING_READ(regs[id].ctl);
1040 : 0 : }
1041 : :
1042 : 0 : static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv,
1043 : : struct intel_shared_dpll *pll)
1044 : : {
1045 : 0 : }
1046 : :
1047 : 0 : static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1048 : : struct intel_shared_dpll *pll,
1049 : : struct intel_dpll_hw_state *hw_state)
1050 : : {
1051 : 0 : u32 val;
1052 : 0 : const struct skl_dpll_regs *regs = skl_dpll_regs;
1053 : 0 : const enum intel_dpll_id id = pll->info->id;
1054 : 0 : intel_wakeref_t wakeref;
1055 : 0 : bool ret;
1056 : :
1057 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv,
1058 : : POWER_DOMAIN_DISPLAY_CORE);
1059 [ # # ]: 0 : if (!wakeref)
1060 : : return false;
1061 : :
1062 : 0 : ret = false;
1063 : :
1064 : 0 : val = I915_READ(regs[id].ctl);
1065 [ # # ]: 0 : if (!(val & LCPLL_PLL_ENABLE))
1066 : 0 : goto out;
1067 : :
1068 : 0 : val = I915_READ(DPLL_CTRL1);
1069 : 0 : hw_state->ctrl1 = (val >> (id * 6)) & 0x3f;
1070 : :
1071 : : /* avoid reading back stale values if HDMI mode is not enabled */
1072 [ # # ]: 0 : if (val & DPLL_CTRL1_HDMI_MODE(id)) {
1073 : 0 : hw_state->cfgcr1 = I915_READ(regs[id].cfgcr1);
1074 : 0 : hw_state->cfgcr2 = I915_READ(regs[id].cfgcr2);
1075 : : }
1076 : : ret = true;
1077 : :
1078 : 0 : out:
1079 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
1080 : :
1081 : 0 : return ret;
1082 : : }
1083 : :
1084 : 0 : static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv,
1085 : : struct intel_shared_dpll *pll,
1086 : : struct intel_dpll_hw_state *hw_state)
1087 : : {
1088 : 0 : const struct skl_dpll_regs *regs = skl_dpll_regs;
1089 : 0 : const enum intel_dpll_id id = pll->info->id;
1090 : 0 : intel_wakeref_t wakeref;
1091 : 0 : u32 val;
1092 : 0 : bool ret;
1093 : :
1094 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv,
1095 : : POWER_DOMAIN_DISPLAY_CORE);
1096 [ # # ]: 0 : if (!wakeref)
1097 : : return false;
1098 : :
1099 : 0 : ret = false;
1100 : :
1101 : : /* DPLL0 is always enabled since it drives CDCLK */
1102 : 0 : val = I915_READ(regs[id].ctl);
1103 [ # # # # ]: 0 : if (WARN_ON(!(val & LCPLL_PLL_ENABLE)))
1104 : 0 : goto out;
1105 : :
1106 : 0 : val = I915_READ(DPLL_CTRL1);
1107 : 0 : hw_state->ctrl1 = (val >> (id * 6)) & 0x3f;
1108 : :
1109 : 0 : ret = true;
1110 : :
1111 : 0 : out:
1112 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
1113 : :
1114 : 0 : return ret;
1115 : : }
1116 : :
1117 : : struct skl_wrpll_context {
1118 : : u64 min_deviation; /* current minimal deviation */
1119 : : u64 central_freq; /* chosen central freq */
1120 : : u64 dco_freq; /* chosen dco freq */
1121 : : unsigned int p; /* chosen divider */
1122 : : };
1123 : :
1124 : 0 : static void skl_wrpll_context_init(struct skl_wrpll_context *ctx)
1125 : : {
1126 : 0 : memset(ctx, 0, sizeof(*ctx));
1127 : :
1128 : 0 : ctx->min_deviation = U64_MAX;
1129 : : }
1130 : :
1131 : : /* DCO freq must be within +1%/-6% of the DCO central freq */
1132 : : #define SKL_DCO_MAX_PDEVIATION 100
1133 : : #define SKL_DCO_MAX_NDEVIATION 600
1134 : :
1135 : 0 : static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx,
1136 : : u64 central_freq,
1137 : : u64 dco_freq,
1138 : : unsigned int divider)
1139 : : {
1140 : 0 : u64 deviation;
1141 : :
1142 [ # # # # ]: 0 : deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq),
1143 : : central_freq);
1144 : :
1145 : : /* positive deviation */
1146 [ # # ]: 0 : if (dco_freq >= central_freq) {
1147 [ # # ]: 0 : if (deviation < SKL_DCO_MAX_PDEVIATION &&
1148 [ # # ]: 0 : deviation < ctx->min_deviation) {
1149 : 0 : ctx->min_deviation = deviation;
1150 : 0 : ctx->central_freq = central_freq;
1151 : 0 : ctx->dco_freq = dco_freq;
1152 : 0 : ctx->p = divider;
1153 : : }
1154 : : /* negative deviation */
1155 [ # # ]: 0 : } else if (deviation < SKL_DCO_MAX_NDEVIATION &&
1156 [ # # ]: 0 : deviation < ctx->min_deviation) {
1157 : 0 : ctx->min_deviation = deviation;
1158 : 0 : ctx->central_freq = central_freq;
1159 : 0 : ctx->dco_freq = dco_freq;
1160 : 0 : ctx->p = divider;
1161 : : }
1162 : 0 : }
1163 : :
1164 : 0 : static void skl_wrpll_get_multipliers(unsigned int p,
1165 : : unsigned int *p0 /* out */,
1166 : : unsigned int *p1 /* out */,
1167 : : unsigned int *p2 /* out */)
1168 : : {
1169 : : /* even dividers */
1170 [ # # ]: 0 : if (p % 2 == 0) {
1171 : 0 : unsigned int half = p / 2;
1172 : :
1173 [ # # ]: 0 : if (half == 1 || half == 2 || half == 3 || half == 5) {
1174 : 0 : *p0 = 2;
1175 : 0 : *p1 = 1;
1176 : 0 : *p2 = half;
1177 [ # # ]: 0 : } else if (half % 2 == 0) {
1178 : 0 : *p0 = 2;
1179 : 0 : *p1 = half / 2;
1180 : 0 : *p2 = 2;
1181 [ # # ]: 0 : } else if (half % 3 == 0) {
1182 : 0 : *p0 = 3;
1183 : 0 : *p1 = half / 3;
1184 : 0 : *p2 = 2;
1185 [ # # ]: 0 : } else if (half % 7 == 0) {
1186 : 0 : *p0 = 7;
1187 : 0 : *p1 = half / 7;
1188 : 0 : *p2 = 2;
1189 : : }
1190 [ # # ]: 0 : } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */
1191 : 0 : *p0 = 3;
1192 : 0 : *p1 = 1;
1193 : 0 : *p2 = p / 3;
1194 [ # # ]: 0 : } else if (p == 5 || p == 7) {
1195 : 0 : *p0 = p;
1196 : 0 : *p1 = 1;
1197 : 0 : *p2 = 1;
1198 [ # # ]: 0 : } else if (p == 15) {
1199 : 0 : *p0 = 3;
1200 : 0 : *p1 = 1;
1201 : 0 : *p2 = 5;
1202 [ # # ]: 0 : } else if (p == 21) {
1203 : 0 : *p0 = 7;
1204 : 0 : *p1 = 1;
1205 : 0 : *p2 = 3;
1206 [ # # ]: 0 : } else if (p == 35) {
1207 : 0 : *p0 = 7;
1208 : 0 : *p1 = 1;
1209 : 0 : *p2 = 5;
1210 : : }
1211 : 0 : }
1212 : :
1213 : : struct skl_wrpll_params {
1214 : : u32 dco_fraction;
1215 : : u32 dco_integer;
1216 : : u32 qdiv_ratio;
1217 : : u32 qdiv_mode;
1218 : : u32 kdiv;
1219 : : u32 pdiv;
1220 : : u32 central_freq;
1221 : : };
1222 : :
1223 : 0 : static void skl_wrpll_params_populate(struct skl_wrpll_params *params,
1224 : : u64 afe_clock,
1225 : : u64 central_freq,
1226 : : u32 p0, u32 p1, u32 p2)
1227 : : {
1228 : 0 : u64 dco_freq;
1229 : :
1230 [ # # # # ]: 0 : switch (central_freq) {
1231 : 0 : case 9600000000ULL:
1232 : 0 : params->central_freq = 0;
1233 : 0 : break;
1234 : 0 : case 9000000000ULL:
1235 : 0 : params->central_freq = 1;
1236 : 0 : break;
1237 : 0 : case 8400000000ULL:
1238 : 0 : params->central_freq = 3;
1239 : : }
1240 : :
1241 [ # # # # : 0 : switch (p0) {
# ]
1242 : 0 : case 1:
1243 : 0 : params->pdiv = 0;
1244 : 0 : break;
1245 : 0 : case 2:
1246 : 0 : params->pdiv = 1;
1247 : 0 : break;
1248 : 0 : case 3:
1249 : 0 : params->pdiv = 2;
1250 : 0 : break;
1251 : 0 : case 7:
1252 : 0 : params->pdiv = 4;
1253 : 0 : break;
1254 : : default:
1255 : 0 : WARN(1, "Incorrect PDiv\n");
1256 : : }
1257 : :
1258 [ # # # # : 0 : switch (p2) {
# ]
1259 : 0 : case 5:
1260 : 0 : params->kdiv = 0;
1261 : 0 : break;
1262 : 0 : case 2:
1263 : 0 : params->kdiv = 1;
1264 : 0 : break;
1265 : 0 : case 3:
1266 : 0 : params->kdiv = 2;
1267 : 0 : break;
1268 : 0 : case 1:
1269 : 0 : params->kdiv = 3;
1270 : 0 : break;
1271 : : default:
1272 : 0 : WARN(1, "Incorrect KDiv\n");
1273 : : }
1274 : :
1275 : 0 : params->qdiv_ratio = p1;
1276 : 0 : params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1;
1277 : :
1278 : 0 : dco_freq = p0 * p1 * p2 * afe_clock;
1279 : :
1280 : : /*
1281 : : * Intermediate values are in Hz.
1282 : : * Divide by MHz to match bsepc
1283 : : */
1284 : 0 : params->dco_integer = div_u64(dco_freq, 24 * MHz(1));
1285 : 0 : params->dco_fraction =
1286 : 0 : div_u64((div_u64(dco_freq, 24) -
1287 : 0 : params->dco_integer * MHz(1)) * 0x8000, MHz(1));
1288 : 0 : }
1289 : :
1290 : : static bool
1291 : 0 : skl_ddi_calculate_wrpll(int clock /* in Hz */,
1292 : : struct skl_wrpll_params *wrpll_params)
1293 : : {
1294 : 0 : u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */
1295 : 0 : u64 dco_central_freq[3] = { 8400000000ULL,
1296 : : 9000000000ULL,
1297 : : 9600000000ULL };
1298 : 0 : static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20,
1299 : : 24, 28, 30, 32, 36, 40, 42, 44,
1300 : : 48, 52, 54, 56, 60, 64, 66, 68,
1301 : : 70, 72, 76, 78, 80, 84, 88, 90,
1302 : : 92, 96, 98 };
1303 : 0 : static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 };
1304 : 0 : static const struct {
1305 : : const int *list;
1306 : : int n_dividers;
1307 : : } dividers[] = {
1308 : : { even_dividers, ARRAY_SIZE(even_dividers) },
1309 : : { odd_dividers, ARRAY_SIZE(odd_dividers) },
1310 : : };
1311 : 0 : struct skl_wrpll_context ctx;
1312 : 0 : unsigned int dco, d, i;
1313 : 0 : unsigned int p0, p1, p2;
1314 : :
1315 : 0 : skl_wrpll_context_init(&ctx);
1316 : :
1317 [ # # ]: 0 : for (d = 0; d < ARRAY_SIZE(dividers); d++) {
1318 [ # # ]: 0 : for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) {
1319 [ # # ]: 0 : for (i = 0; i < dividers[d].n_dividers; i++) {
1320 : 0 : unsigned int p = dividers[d].list[i];
1321 : 0 : u64 dco_freq = p * afe_clock;
1322 : :
1323 : 0 : skl_wrpll_try_divider(&ctx,
1324 : : dco_central_freq[dco],
1325 : : dco_freq,
1326 : : p);
1327 : : /*
1328 : : * Skip the remaining dividers if we're sure to
1329 : : * have found the definitive divider, we can't
1330 : : * improve a 0 deviation.
1331 : : */
1332 [ # # ]: 0 : if (ctx.min_deviation == 0)
1333 : 0 : goto skip_remaining_dividers;
1334 : : }
1335 : : }
1336 : :
1337 : 0 : skip_remaining_dividers:
1338 : : /*
1339 : : * If a solution is found with an even divider, prefer
1340 : : * this one.
1341 : : */
1342 [ # # # # ]: 0 : if (d == 0 && ctx.p)
1343 : : break;
1344 : : }
1345 : :
1346 [ # # ]: 0 : if (!ctx.p) {
1347 : 0 : DRM_DEBUG_DRIVER("No valid divider found for %dHz\n", clock);
1348 : 0 : return false;
1349 : : }
1350 : :
1351 : : /*
1352 : : * gcc incorrectly analyses that these can be used without being
1353 : : * initialized. To be fair, it's hard to guess.
1354 : : */
1355 : 0 : p0 = p1 = p2 = 0;
1356 : 0 : skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2);
1357 : 0 : skl_wrpll_params_populate(wrpll_params, afe_clock, ctx.central_freq,
1358 : : p0, p1, p2);
1359 : :
1360 : 0 : return true;
1361 : : }
1362 : :
1363 : 0 : static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state)
1364 : : {
1365 : 0 : u32 ctrl1, cfgcr1, cfgcr2;
1366 : 0 : struct skl_wrpll_params wrpll_params = { 0, };
1367 : :
1368 : : /*
1369 : : * See comment in intel_dpll_hw_state to understand why we always use 0
1370 : : * as the DPLL id in this function.
1371 : : */
1372 : 0 : ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1373 : :
1374 : 0 : ctrl1 |= DPLL_CTRL1_HDMI_MODE(0);
1375 : :
1376 [ # # ]: 0 : if (!skl_ddi_calculate_wrpll(crtc_state->port_clock * 1000,
1377 : : &wrpll_params))
1378 : : return false;
1379 : :
1380 : 0 : cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE |
1381 : 0 : DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) |
1382 : 0 : wrpll_params.dco_integer;
1383 : :
1384 : 0 : cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) |
1385 : 0 : DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) |
1386 : 0 : DPLL_CFGCR2_KDIV(wrpll_params.kdiv) |
1387 : 0 : DPLL_CFGCR2_PDIV(wrpll_params.pdiv) |
1388 : 0 : wrpll_params.central_freq;
1389 : :
1390 : 0 : memset(&crtc_state->dpll_hw_state, 0,
1391 : : sizeof(crtc_state->dpll_hw_state));
1392 : :
1393 : 0 : crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1394 : 0 : crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
1395 : 0 : crtc_state->dpll_hw_state.cfgcr2 = cfgcr2;
1396 : 0 : return true;
1397 : : }
1398 : :
1399 : : static bool
1400 : 0 : skl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
1401 : : {
1402 : 0 : u32 ctrl1;
1403 : :
1404 : : /*
1405 : : * See comment in intel_dpll_hw_state to understand why we always use 0
1406 : : * as the DPLL id in this function.
1407 : : */
1408 : 0 : ctrl1 = DPLL_CTRL1_OVERRIDE(0);
1409 [ # # # # : 0 : switch (crtc_state->port_clock / 2) {
# # ]
1410 : 0 : case 81000:
1411 : 0 : ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0);
1412 : 0 : break;
1413 : 0 : case 135000:
1414 : 0 : ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0);
1415 : 0 : break;
1416 : : case 270000:
1417 : : ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0);
1418 : : break;
1419 : : /* eDP 1.4 rates */
1420 : 0 : case 162000:
1421 : 0 : ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
1422 : 0 : break;
1423 : 0 : case 108000:
1424 : 0 : ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
1425 : 0 : break;
1426 : 0 : case 216000:
1427 : 0 : ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0);
1428 : 0 : break;
1429 : : }
1430 : :
1431 : 0 : memset(&crtc_state->dpll_hw_state, 0,
1432 : : sizeof(crtc_state->dpll_hw_state));
1433 : :
1434 : 0 : crtc_state->dpll_hw_state.ctrl1 = ctrl1;
1435 : :
1436 : 0 : return true;
1437 : : }
1438 : :
1439 : 0 : static bool skl_get_dpll(struct intel_atomic_state *state,
1440 : : struct intel_crtc *crtc,
1441 : : struct intel_encoder *encoder)
1442 : : {
1443 [ # # ]: 0 : struct intel_crtc_state *crtc_state =
1444 : : intel_atomic_get_new_crtc_state(state, crtc);
1445 : 0 : struct intel_shared_dpll *pll;
1446 : 0 : bool bret;
1447 : :
1448 [ # # ]: 0 : if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
1449 : 0 : bret = skl_ddi_hdmi_pll_dividers(crtc_state);
1450 [ # # ]: 0 : if (!bret) {
1451 : 0 : DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n");
1452 : 0 : return false;
1453 : : }
1454 [ # # ]: 0 : } else if (intel_crtc_has_dp_encoder(crtc_state)) {
1455 : 0 : bret = skl_ddi_dp_set_dpll_hw_state(crtc_state);
1456 [ # # ]: 0 : if (!bret) {
1457 : 0 : DRM_DEBUG_KMS("Could not set DP dpll HW state.\n");
1458 : 0 : return false;
1459 : : }
1460 : : } else {
1461 : : return false;
1462 : : }
1463 : :
1464 [ # # ]: 0 : if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
1465 : 0 : pll = intel_find_shared_dpll(state, crtc,
1466 : 0 : &crtc_state->dpll_hw_state,
1467 : : BIT(DPLL_ID_SKL_DPLL0));
1468 : : else
1469 : 0 : pll = intel_find_shared_dpll(state, crtc,
1470 : 0 : &crtc_state->dpll_hw_state,
1471 : : BIT(DPLL_ID_SKL_DPLL3) |
1472 : : BIT(DPLL_ID_SKL_DPLL2) |
1473 : : BIT(DPLL_ID_SKL_DPLL1));
1474 [ # # ]: 0 : if (!pll)
1475 : : return false;
1476 : :
1477 : 0 : intel_reference_shared_dpll(state, crtc,
1478 : 0 : pll, &crtc_state->dpll_hw_state);
1479 : :
1480 : 0 : crtc_state->shared_dpll = pll;
1481 : :
1482 : 0 : return true;
1483 : : }
1484 : :
1485 : 0 : static void skl_dump_hw_state(struct drm_i915_private *dev_priv,
1486 : : const struct intel_dpll_hw_state *hw_state)
1487 : : {
1488 : 0 : DRM_DEBUG_KMS("dpll_hw_state: "
1489 : : "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n",
1490 : : hw_state->ctrl1,
1491 : : hw_state->cfgcr1,
1492 : : hw_state->cfgcr2);
1493 : 0 : }
1494 : :
1495 : : static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = {
1496 : : .enable = skl_ddi_pll_enable,
1497 : : .disable = skl_ddi_pll_disable,
1498 : : .get_hw_state = skl_ddi_pll_get_hw_state,
1499 : : };
1500 : :
1501 : : static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = {
1502 : : .enable = skl_ddi_dpll0_enable,
1503 : : .disable = skl_ddi_dpll0_disable,
1504 : : .get_hw_state = skl_ddi_dpll0_get_hw_state,
1505 : : };
1506 : :
1507 : 0 : static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
1508 : : struct intel_shared_dpll *pll)
1509 : : {
1510 : 0 : u32 temp;
1511 : 0 : enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
1512 : 0 : enum dpio_phy phy;
1513 : 0 : enum dpio_channel ch;
1514 : :
1515 : 0 : bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
1516 : :
1517 : : /* Non-SSC reference */
1518 : 0 : temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1519 : 0 : temp |= PORT_PLL_REF_SEL;
1520 : 0 : I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1521 : :
1522 [ # # ]: 0 : if (IS_GEMINILAKE(dev_priv)) {
1523 : 0 : temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1524 : 0 : temp |= PORT_PLL_POWER_ENABLE;
1525 : 0 : I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1526 : :
1527 [ # # # # : 0 : if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) &
# # ]
1528 : : PORT_PLL_POWER_STATE), 200))
1529 : 0 : DRM_ERROR("Power state not set for PLL:%d\n", port);
1530 : : }
1531 : :
1532 : : /* Disable 10 bit clock */
1533 : 0 : temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
1534 : 0 : temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1535 : 0 : I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
1536 : :
1537 : : /* Write P1 & P2 */
1538 : 0 : temp = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
1539 : 0 : temp &= ~(PORT_PLL_P1_MASK | PORT_PLL_P2_MASK);
1540 : 0 : temp |= pll->state.hw_state.ebb0;
1541 : 0 : I915_WRITE(BXT_PORT_PLL_EBB_0(phy, ch), temp);
1542 : :
1543 : : /* Write M2 integer */
1544 : 0 : temp = I915_READ(BXT_PORT_PLL(phy, ch, 0));
1545 : 0 : temp &= ~PORT_PLL_M2_MASK;
1546 : 0 : temp |= pll->state.hw_state.pll0;
1547 : 0 : I915_WRITE(BXT_PORT_PLL(phy, ch, 0), temp);
1548 : :
1549 : : /* Write N */
1550 : 0 : temp = I915_READ(BXT_PORT_PLL(phy, ch, 1));
1551 : 0 : temp &= ~PORT_PLL_N_MASK;
1552 : 0 : temp |= pll->state.hw_state.pll1;
1553 : 0 : I915_WRITE(BXT_PORT_PLL(phy, ch, 1), temp);
1554 : :
1555 : : /* Write M2 fraction */
1556 : 0 : temp = I915_READ(BXT_PORT_PLL(phy, ch, 2));
1557 : 0 : temp &= ~PORT_PLL_M2_FRAC_MASK;
1558 : 0 : temp |= pll->state.hw_state.pll2;
1559 : 0 : I915_WRITE(BXT_PORT_PLL(phy, ch, 2), temp);
1560 : :
1561 : : /* Write M2 fraction enable */
1562 : 0 : temp = I915_READ(BXT_PORT_PLL(phy, ch, 3));
1563 : 0 : temp &= ~PORT_PLL_M2_FRAC_ENABLE;
1564 : 0 : temp |= pll->state.hw_state.pll3;
1565 : 0 : I915_WRITE(BXT_PORT_PLL(phy, ch, 3), temp);
1566 : :
1567 : : /* Write coeff */
1568 : 0 : temp = I915_READ(BXT_PORT_PLL(phy, ch, 6));
1569 : 0 : temp &= ~PORT_PLL_PROP_COEFF_MASK;
1570 : 0 : temp &= ~PORT_PLL_INT_COEFF_MASK;
1571 : 0 : temp &= ~PORT_PLL_GAIN_CTL_MASK;
1572 : 0 : temp |= pll->state.hw_state.pll6;
1573 : 0 : I915_WRITE(BXT_PORT_PLL(phy, ch, 6), temp);
1574 : :
1575 : : /* Write calibration val */
1576 : 0 : temp = I915_READ(BXT_PORT_PLL(phy, ch, 8));
1577 : 0 : temp &= ~PORT_PLL_TARGET_CNT_MASK;
1578 : 0 : temp |= pll->state.hw_state.pll8;
1579 : 0 : I915_WRITE(BXT_PORT_PLL(phy, ch, 8), temp);
1580 : :
1581 : 0 : temp = I915_READ(BXT_PORT_PLL(phy, ch, 9));
1582 : 0 : temp &= ~PORT_PLL_LOCK_THRESHOLD_MASK;
1583 : 0 : temp |= pll->state.hw_state.pll9;
1584 : 0 : I915_WRITE(BXT_PORT_PLL(phy, ch, 9), temp);
1585 : :
1586 : 0 : temp = I915_READ(BXT_PORT_PLL(phy, ch, 10));
1587 : 0 : temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H;
1588 : 0 : temp &= ~PORT_PLL_DCO_AMP_MASK;
1589 : 0 : temp |= pll->state.hw_state.pll10;
1590 : 0 : I915_WRITE(BXT_PORT_PLL(phy, ch, 10), temp);
1591 : :
1592 : : /* Recalibrate with new settings */
1593 : 0 : temp = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
1594 : 0 : temp |= PORT_PLL_RECALIBRATE;
1595 : 0 : I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
1596 : 0 : temp &= ~PORT_PLL_10BIT_CLK_ENABLE;
1597 : 0 : temp |= pll->state.hw_state.ebb4;
1598 : 0 : I915_WRITE(BXT_PORT_PLL_EBB_4(phy, ch), temp);
1599 : :
1600 : : /* Enable PLL */
1601 : 0 : temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1602 : 0 : temp |= PORT_PLL_ENABLE;
1603 : 0 : I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1604 : 0 : POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1605 : :
1606 [ # # # # : 0 : if (wait_for_us((I915_READ(BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK),
# # ]
1607 : : 200))
1608 : 0 : DRM_ERROR("PLL %d not locked\n", port);
1609 : :
1610 [ # # ]: 0 : if (IS_GEMINILAKE(dev_priv)) {
1611 : 0 : temp = I915_READ(BXT_PORT_TX_DW5_LN0(phy, ch));
1612 : 0 : temp |= DCC_DELAY_RANGE_2;
1613 : 0 : I915_WRITE(BXT_PORT_TX_DW5_GRP(phy, ch), temp);
1614 : : }
1615 : :
1616 : : /*
1617 : : * While we write to the group register to program all lanes at once we
1618 : : * can read only lane registers and we pick lanes 0/1 for that.
1619 : : */
1620 : 0 : temp = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
1621 : 0 : temp &= ~LANE_STAGGER_MASK;
1622 : 0 : temp &= ~LANESTAGGER_STRAP_OVRD;
1623 : 0 : temp |= pll->state.hw_state.pcsdw12;
1624 : 0 : I915_WRITE(BXT_PORT_PCS_DW12_GRP(phy, ch), temp);
1625 : 0 : }
1626 : :
1627 : 0 : static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv,
1628 : : struct intel_shared_dpll *pll)
1629 : : {
1630 : 0 : enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
1631 : 0 : u32 temp;
1632 : :
1633 : 0 : temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1634 : 0 : temp &= ~PORT_PLL_ENABLE;
1635 : 0 : I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1636 : 0 : POSTING_READ(BXT_PORT_PLL_ENABLE(port));
1637 : :
1638 [ # # ]: 0 : if (IS_GEMINILAKE(dev_priv)) {
1639 : 0 : temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
1640 : 0 : temp &= ~PORT_PLL_POWER_ENABLE;
1641 : 0 : I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
1642 : :
1643 [ # # # # : 0 : if (wait_for_us(!(I915_READ(BXT_PORT_PLL_ENABLE(port)) &
# # ]
1644 : : PORT_PLL_POWER_STATE), 200))
1645 : 0 : DRM_ERROR("Power state not reset for PLL:%d\n", port);
1646 : : }
1647 : 0 : }
1648 : :
1649 : 0 : static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
1650 : : struct intel_shared_dpll *pll,
1651 : : struct intel_dpll_hw_state *hw_state)
1652 : : {
1653 : 0 : enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */
1654 : 0 : intel_wakeref_t wakeref;
1655 : 0 : enum dpio_phy phy;
1656 : 0 : enum dpio_channel ch;
1657 : 0 : u32 val;
1658 : 0 : bool ret;
1659 : :
1660 : 0 : bxt_port_to_phy_channel(dev_priv, port, &phy, &ch);
1661 : :
1662 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv,
1663 : : POWER_DOMAIN_DISPLAY_CORE);
1664 [ # # ]: 0 : if (!wakeref)
1665 : : return false;
1666 : :
1667 : 0 : ret = false;
1668 : :
1669 : 0 : val = I915_READ(BXT_PORT_PLL_ENABLE(port));
1670 [ # # ]: 0 : if (!(val & PORT_PLL_ENABLE))
1671 : 0 : goto out;
1672 : :
1673 : 0 : hw_state->ebb0 = I915_READ(BXT_PORT_PLL_EBB_0(phy, ch));
1674 : 0 : hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK;
1675 : :
1676 : 0 : hw_state->ebb4 = I915_READ(BXT_PORT_PLL_EBB_4(phy, ch));
1677 : 0 : hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE;
1678 : :
1679 : 0 : hw_state->pll0 = I915_READ(BXT_PORT_PLL(phy, ch, 0));
1680 : 0 : hw_state->pll0 &= PORT_PLL_M2_MASK;
1681 : :
1682 : 0 : hw_state->pll1 = I915_READ(BXT_PORT_PLL(phy, ch, 1));
1683 : 0 : hw_state->pll1 &= PORT_PLL_N_MASK;
1684 : :
1685 : 0 : hw_state->pll2 = I915_READ(BXT_PORT_PLL(phy, ch, 2));
1686 : 0 : hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK;
1687 : :
1688 : 0 : hw_state->pll3 = I915_READ(BXT_PORT_PLL(phy, ch, 3));
1689 : 0 : hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE;
1690 : :
1691 : 0 : hw_state->pll6 = I915_READ(BXT_PORT_PLL(phy, ch, 6));
1692 : 0 : hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK |
1693 : : PORT_PLL_INT_COEFF_MASK |
1694 : : PORT_PLL_GAIN_CTL_MASK;
1695 : :
1696 : 0 : hw_state->pll8 = I915_READ(BXT_PORT_PLL(phy, ch, 8));
1697 : 0 : hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK;
1698 : :
1699 : 0 : hw_state->pll9 = I915_READ(BXT_PORT_PLL(phy, ch, 9));
1700 : 0 : hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK;
1701 : :
1702 : 0 : hw_state->pll10 = I915_READ(BXT_PORT_PLL(phy, ch, 10));
1703 : 0 : hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H |
1704 : : PORT_PLL_DCO_AMP_MASK;
1705 : :
1706 : : /*
1707 : : * While we write to the group register to program all lanes at once we
1708 : : * can read only lane registers. We configure all lanes the same way, so
1709 : : * here just read out lanes 0/1 and output a note if lanes 2/3 differ.
1710 : : */
1711 : 0 : hw_state->pcsdw12 = I915_READ(BXT_PORT_PCS_DW12_LN01(phy, ch));
1712 [ # # ]: 0 : if (I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12)
1713 : 0 : DRM_DEBUG_DRIVER("lane stagger config different for lane 01 (%08x) and 23 (%08x)\n",
1714 : : hw_state->pcsdw12,
1715 : : I915_READ(BXT_PORT_PCS_DW12_LN23(phy, ch)));
1716 : 0 : hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD;
1717 : :
1718 : 0 : ret = true;
1719 : :
1720 : 0 : out:
1721 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
1722 : :
1723 : 0 : return ret;
1724 : : }
1725 : :
1726 : : /* bxt clock parameters */
1727 : : struct bxt_clk_div {
1728 : : int clock;
1729 : : u32 p1;
1730 : : u32 p2;
1731 : : u32 m2_int;
1732 : : u32 m2_frac;
1733 : : bool m2_frac_en;
1734 : : u32 n;
1735 : :
1736 : : int vco;
1737 : : };
1738 : :
1739 : : /* pre-calculated values for DP linkrates */
1740 : : static const struct bxt_clk_div bxt_dp_clk_val[] = {
1741 : : {162000, 4, 2, 32, 1677722, 1, 1},
1742 : : {270000, 4, 1, 27, 0, 0, 1},
1743 : : {540000, 2, 1, 27, 0, 0, 1},
1744 : : {216000, 3, 2, 32, 1677722, 1, 1},
1745 : : {243000, 4, 1, 24, 1258291, 1, 1},
1746 : : {324000, 4, 1, 32, 1677722, 1, 1},
1747 : : {432000, 3, 1, 32, 1677722, 1, 1}
1748 : : };
1749 : :
1750 : : static bool
1751 : 0 : bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state,
1752 : : struct bxt_clk_div *clk_div)
1753 : : {
1754 : 0 : struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
1755 : 0 : struct dpll best_clock;
1756 : :
1757 : : /* Calculate HDMI div */
1758 : : /*
1759 : : * FIXME: tie the following calculation into
1760 : : * i9xx_crtc_compute_clock
1761 : : */
1762 [ # # ]: 0 : if (!bxt_find_best_dpll(crtc_state, &best_clock)) {
1763 : 0 : DRM_DEBUG_DRIVER("no PLL dividers found for clock %d pipe %c\n",
1764 : : crtc_state->port_clock,
1765 : : pipe_name(crtc->pipe));
1766 : 0 : return false;
1767 : : }
1768 : :
1769 : 0 : clk_div->p1 = best_clock.p1;
1770 : 0 : clk_div->p2 = best_clock.p2;
1771 [ # # ]: 0 : WARN_ON(best_clock.m1 != 2);
1772 : 0 : clk_div->n = best_clock.n;
1773 : 0 : clk_div->m2_int = best_clock.m2 >> 22;
1774 : 0 : clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1);
1775 : 0 : clk_div->m2_frac_en = clk_div->m2_frac != 0;
1776 : :
1777 : 0 : clk_div->vco = best_clock.vco;
1778 : :
1779 : 0 : return true;
1780 : : }
1781 : :
1782 : : static void bxt_ddi_dp_pll_dividers(struct intel_crtc_state *crtc_state,
1783 : : struct bxt_clk_div *clk_div)
1784 : : {
1785 : : int clock = crtc_state->port_clock;
1786 : : int i;
1787 : :
1788 : : *clk_div = bxt_dp_clk_val[0];
1789 : : for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) {
1790 : : if (bxt_dp_clk_val[i].clock == clock) {
1791 : : *clk_div = bxt_dp_clk_val[i];
1792 : : break;
1793 : : }
1794 : : }
1795 : :
1796 : : clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2;
1797 : : }
1798 : :
1799 : 0 : static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state,
1800 : : const struct bxt_clk_div *clk_div)
1801 : : {
1802 : 0 : struct intel_dpll_hw_state *dpll_hw_state = &crtc_state->dpll_hw_state;
1803 : 0 : int clock = crtc_state->port_clock;
1804 : 0 : int vco = clk_div->vco;
1805 : 0 : u32 prop_coef, int_coef, gain_ctl, targ_cnt;
1806 : 0 : u32 lanestagger;
1807 : :
1808 : 0 : memset(dpll_hw_state, 0, sizeof(*dpll_hw_state));
1809 : :
1810 [ # # ]: 0 : if (vco >= 6200000 && vco <= 6700000) {
1811 : : prop_coef = 4;
1812 : : int_coef = 9;
1813 : : gain_ctl = 3;
1814 : : targ_cnt = 8;
1815 : 0 : } else if ((vco > 5400000 && vco < 6200000) ||
1816 [ # # ]: 0 : (vco >= 4800000 && vco < 5400000)) {
1817 : : prop_coef = 5;
1818 : : int_coef = 11;
1819 : : gain_ctl = 3;
1820 : : targ_cnt = 9;
1821 [ # # ]: 0 : } else if (vco == 5400000) {
1822 : : prop_coef = 3;
1823 : : int_coef = 8;
1824 : : gain_ctl = 1;
1825 : : targ_cnt = 9;
1826 : : } else {
1827 : 0 : DRM_ERROR("Invalid VCO\n");
1828 : 0 : return false;
1829 : : }
1830 : :
1831 [ # # ]: 0 : if (clock > 270000)
1832 : : lanestagger = 0x18;
1833 [ # # ]: 0 : else if (clock > 135000)
1834 : : lanestagger = 0x0d;
1835 [ # # ]: 0 : else if (clock > 67000)
1836 : : lanestagger = 0x07;
1837 [ # # ]: 0 : else if (clock > 33000)
1838 : : lanestagger = 0x04;
1839 : : else
1840 : 0 : lanestagger = 0x02;
1841 : :
1842 : 0 : dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2);
1843 : 0 : dpll_hw_state->pll0 = clk_div->m2_int;
1844 : 0 : dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n);
1845 : 0 : dpll_hw_state->pll2 = clk_div->m2_frac;
1846 : :
1847 [ # # ]: 0 : if (clk_div->m2_frac_en)
1848 : 0 : dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE;
1849 : :
1850 : 0 : dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef);
1851 : 0 : dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl);
1852 : :
1853 : 0 : dpll_hw_state->pll8 = targ_cnt;
1854 : :
1855 : 0 : dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT;
1856 : :
1857 : 0 : dpll_hw_state->pll10 =
1858 : : PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT)
1859 : : | PORT_PLL_DCO_AMP_OVR_EN_H;
1860 : :
1861 : 0 : dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE;
1862 : :
1863 : 0 : dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger;
1864 : :
1865 : 0 : return true;
1866 : : }
1867 : :
1868 : : static bool
1869 : 0 : bxt_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
1870 : : {
1871 : 0 : struct bxt_clk_div clk_div = {};
1872 : :
1873 : 0 : bxt_ddi_dp_pll_dividers(crtc_state, &clk_div);
1874 : :
1875 : 0 : return bxt_ddi_set_dpll_hw_state(crtc_state, &clk_div);
1876 : : }
1877 : :
1878 : : static bool
1879 : 0 : bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
1880 : : {
1881 : 0 : struct bxt_clk_div clk_div = {};
1882 : :
1883 : 0 : bxt_ddi_hdmi_pll_dividers(crtc_state, &clk_div);
1884 : :
1885 : 0 : return bxt_ddi_set_dpll_hw_state(crtc_state, &clk_div);
1886 : : }
1887 : :
1888 : 0 : static bool bxt_get_dpll(struct intel_atomic_state *state,
1889 : : struct intel_crtc *crtc,
1890 : : struct intel_encoder *encoder)
1891 : : {
1892 [ # # ]: 0 : struct intel_crtc_state *crtc_state =
1893 : : intel_atomic_get_new_crtc_state(state, crtc);
1894 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
1895 : 0 : struct intel_shared_dpll *pll;
1896 : 0 : enum intel_dpll_id id;
1897 : :
1898 [ # # # # ]: 0 : if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) &&
1899 : 0 : !bxt_ddi_hdmi_set_dpll_hw_state(crtc_state))
1900 : : return false;
1901 : :
1902 [ # # # # ]: 0 : if (intel_crtc_has_dp_encoder(crtc_state) &&
1903 : 0 : !bxt_ddi_dp_set_dpll_hw_state(crtc_state))
1904 : : return false;
1905 : :
1906 : : /* 1:1 mapping between ports and PLLs */
1907 : 0 : id = (enum intel_dpll_id) encoder->port;
1908 : 0 : pll = intel_get_shared_dpll_by_id(dev_priv, id);
1909 : :
1910 : 0 : DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
1911 : : crtc->base.base.id, crtc->base.name, pll->info->name);
1912 : :
1913 : 0 : intel_reference_shared_dpll(state, crtc,
1914 : 0 : pll, &crtc_state->dpll_hw_state);
1915 : :
1916 : 0 : crtc_state->shared_dpll = pll;
1917 : :
1918 : 0 : return true;
1919 : : }
1920 : :
1921 : 0 : static void bxt_dump_hw_state(struct drm_i915_private *dev_priv,
1922 : : const struct intel_dpll_hw_state *hw_state)
1923 : : {
1924 : 0 : DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x,"
1925 : : "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, "
1926 : : "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n",
1927 : : hw_state->ebb0,
1928 : : hw_state->ebb4,
1929 : : hw_state->pll0,
1930 : : hw_state->pll1,
1931 : : hw_state->pll2,
1932 : : hw_state->pll3,
1933 : : hw_state->pll6,
1934 : : hw_state->pll8,
1935 : : hw_state->pll9,
1936 : : hw_state->pll10,
1937 : : hw_state->pcsdw12);
1938 : 0 : }
1939 : :
1940 : : static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
1941 : : .enable = bxt_ddi_pll_enable,
1942 : : .disable = bxt_ddi_pll_disable,
1943 : : .get_hw_state = bxt_ddi_pll_get_hw_state,
1944 : : };
1945 : :
1946 : : struct intel_dpll_mgr {
1947 : : const struct dpll_info *dpll_info;
1948 : :
1949 : : bool (*get_dplls)(struct intel_atomic_state *state,
1950 : : struct intel_crtc *crtc,
1951 : : struct intel_encoder *encoder);
1952 : : void (*put_dplls)(struct intel_atomic_state *state,
1953 : : struct intel_crtc *crtc);
1954 : : void (*update_active_dpll)(struct intel_atomic_state *state,
1955 : : struct intel_crtc *crtc,
1956 : : struct intel_encoder *encoder);
1957 : : void (*dump_hw_state)(struct drm_i915_private *dev_priv,
1958 : : const struct intel_dpll_hw_state *hw_state);
1959 : : };
1960 : :
1961 : : static const struct dpll_info pch_plls[] = {
1962 : : { "PCH DPLL A", &ibx_pch_dpll_funcs, DPLL_ID_PCH_PLL_A, 0 },
1963 : : { "PCH DPLL B", &ibx_pch_dpll_funcs, DPLL_ID_PCH_PLL_B, 0 },
1964 : : { },
1965 : : };
1966 : :
1967 : : static const struct intel_dpll_mgr pch_pll_mgr = {
1968 : : .dpll_info = pch_plls,
1969 : : .get_dplls = ibx_get_dpll,
1970 : : .put_dplls = intel_put_dpll,
1971 : : .dump_hw_state = ibx_dump_hw_state,
1972 : : };
1973 : :
1974 : : static const struct dpll_info hsw_plls[] = {
1975 : : { "WRPLL 1", &hsw_ddi_wrpll_funcs, DPLL_ID_WRPLL1, 0 },
1976 : : { "WRPLL 2", &hsw_ddi_wrpll_funcs, DPLL_ID_WRPLL2, 0 },
1977 : : { "SPLL", &hsw_ddi_spll_funcs, DPLL_ID_SPLL, 0 },
1978 : : { "LCPLL 810", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_810, INTEL_DPLL_ALWAYS_ON },
1979 : : { "LCPLL 1350", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_1350, INTEL_DPLL_ALWAYS_ON },
1980 : : { "LCPLL 2700", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_2700, INTEL_DPLL_ALWAYS_ON },
1981 : : { },
1982 : : };
1983 : :
1984 : : static const struct intel_dpll_mgr hsw_pll_mgr = {
1985 : : .dpll_info = hsw_plls,
1986 : : .get_dplls = hsw_get_dpll,
1987 : : .put_dplls = intel_put_dpll,
1988 : : .dump_hw_state = hsw_dump_hw_state,
1989 : : };
1990 : :
1991 : : static const struct dpll_info skl_plls[] = {
1992 : : { "DPLL 0", &skl_ddi_dpll0_funcs, DPLL_ID_SKL_DPLL0, INTEL_DPLL_ALWAYS_ON },
1993 : : { "DPLL 1", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 },
1994 : : { "DPLL 2", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 },
1995 : : { "DPLL 3", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL3, 0 },
1996 : : { },
1997 : : };
1998 : :
1999 : : static const struct intel_dpll_mgr skl_pll_mgr = {
2000 : : .dpll_info = skl_plls,
2001 : : .get_dplls = skl_get_dpll,
2002 : : .put_dplls = intel_put_dpll,
2003 : : .dump_hw_state = skl_dump_hw_state,
2004 : : };
2005 : :
2006 : : static const struct dpll_info bxt_plls[] = {
2007 : : { "PORT PLL A", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL0, 0 },
2008 : : { "PORT PLL B", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 },
2009 : : { "PORT PLL C", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 },
2010 : : { },
2011 : : };
2012 : :
2013 : : static const struct intel_dpll_mgr bxt_pll_mgr = {
2014 : : .dpll_info = bxt_plls,
2015 : : .get_dplls = bxt_get_dpll,
2016 : : .put_dplls = intel_put_dpll,
2017 : : .dump_hw_state = bxt_dump_hw_state,
2018 : : };
2019 : :
2020 : 0 : static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv,
2021 : : struct intel_shared_dpll *pll)
2022 : : {
2023 : 0 : const enum intel_dpll_id id = pll->info->id;
2024 : 0 : u32 val;
2025 : :
2026 : : /* 1. Enable DPLL power in DPLL_ENABLE. */
2027 : 0 : val = I915_READ(CNL_DPLL_ENABLE(id));
2028 : 0 : val |= PLL_POWER_ENABLE;
2029 : 0 : I915_WRITE(CNL_DPLL_ENABLE(id), val);
2030 : :
2031 : : /* 2. Wait for DPLL power state enabled in DPLL_ENABLE. */
2032 [ # # ]: 0 : if (intel_de_wait_for_set(dev_priv, CNL_DPLL_ENABLE(id),
2033 : : PLL_POWER_STATE, 5))
2034 : 0 : DRM_ERROR("PLL %d Power not enabled\n", id);
2035 : :
2036 : : /*
2037 : : * 3. Configure DPLL_CFGCR0 to set SSC enable/disable,
2038 : : * select DP mode, and set DP link rate.
2039 : : */
2040 : 0 : val = pll->state.hw_state.cfgcr0;
2041 : 0 : I915_WRITE(CNL_DPLL_CFGCR0(id), val);
2042 : :
2043 : : /* 4. Reab back to ensure writes completed */
2044 : 0 : POSTING_READ(CNL_DPLL_CFGCR0(id));
2045 : :
2046 : : /* 3. Configure DPLL_CFGCR0 */
2047 : : /* Avoid touch CFGCR1 if HDMI mode is not enabled */
2048 [ # # ]: 0 : if (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_HDMI_MODE) {
2049 : 0 : val = pll->state.hw_state.cfgcr1;
2050 : 0 : I915_WRITE(CNL_DPLL_CFGCR1(id), val);
2051 : : /* 4. Reab back to ensure writes completed */
2052 : 0 : POSTING_READ(CNL_DPLL_CFGCR1(id));
2053 : : }
2054 : :
2055 : : /*
2056 : : * 5. If the frequency will result in a change to the voltage
2057 : : * requirement, follow the Display Voltage Frequency Switching
2058 : : * Sequence Before Frequency Change
2059 : : *
2060 : : * Note: DVFS is actually handled via the cdclk code paths,
2061 : : * hence we do nothing here.
2062 : : */
2063 : :
2064 : : /* 6. Enable DPLL in DPLL_ENABLE. */
2065 : 0 : val = I915_READ(CNL_DPLL_ENABLE(id));
2066 : 0 : val |= PLL_ENABLE;
2067 : 0 : I915_WRITE(CNL_DPLL_ENABLE(id), val);
2068 : :
2069 : : /* 7. Wait for PLL lock status in DPLL_ENABLE. */
2070 [ # # ]: 0 : if (intel_de_wait_for_set(dev_priv, CNL_DPLL_ENABLE(id), PLL_LOCK, 5))
2071 : 0 : DRM_ERROR("PLL %d not locked\n", id);
2072 : :
2073 : : /*
2074 : : * 8. If the frequency will result in a change to the voltage
2075 : : * requirement, follow the Display Voltage Frequency Switching
2076 : : * Sequence After Frequency Change
2077 : : *
2078 : : * Note: DVFS is actually handled via the cdclk code paths,
2079 : : * hence we do nothing here.
2080 : : */
2081 : :
2082 : : /*
2083 : : * 9. turn on the clock for the DDI and map the DPLL to the DDI
2084 : : * Done at intel_ddi_clk_select
2085 : : */
2086 : 0 : }
2087 : :
2088 : 0 : static void cnl_ddi_pll_disable(struct drm_i915_private *dev_priv,
2089 : : struct intel_shared_dpll *pll)
2090 : : {
2091 : 0 : const enum intel_dpll_id id = pll->info->id;
2092 : 0 : u32 val;
2093 : :
2094 : : /*
2095 : : * 1. Configure DPCLKA_CFGCR0 to turn off the clock for the DDI.
2096 : : * Done at intel_ddi_post_disable
2097 : : */
2098 : :
2099 : : /*
2100 : : * 2. If the frequency will result in a change to the voltage
2101 : : * requirement, follow the Display Voltage Frequency Switching
2102 : : * Sequence Before Frequency Change
2103 : : *
2104 : : * Note: DVFS is actually handled via the cdclk code paths,
2105 : : * hence we do nothing here.
2106 : : */
2107 : :
2108 : : /* 3. Disable DPLL through DPLL_ENABLE. */
2109 : 0 : val = I915_READ(CNL_DPLL_ENABLE(id));
2110 : 0 : val &= ~PLL_ENABLE;
2111 : 0 : I915_WRITE(CNL_DPLL_ENABLE(id), val);
2112 : :
2113 : : /* 4. Wait for PLL not locked status in DPLL_ENABLE. */
2114 [ # # ]: 0 : if (intel_de_wait_for_clear(dev_priv, CNL_DPLL_ENABLE(id), PLL_LOCK, 5))
2115 : 0 : DRM_ERROR("PLL %d locked\n", id);
2116 : :
2117 : : /*
2118 : : * 5. If the frequency will result in a change to the voltage
2119 : : * requirement, follow the Display Voltage Frequency Switching
2120 : : * Sequence After Frequency Change
2121 : : *
2122 : : * Note: DVFS is actually handled via the cdclk code paths,
2123 : : * hence we do nothing here.
2124 : : */
2125 : :
2126 : : /* 6. Disable DPLL power in DPLL_ENABLE. */
2127 : 0 : val = I915_READ(CNL_DPLL_ENABLE(id));
2128 : 0 : val &= ~PLL_POWER_ENABLE;
2129 : 0 : I915_WRITE(CNL_DPLL_ENABLE(id), val);
2130 : :
2131 : : /* 7. Wait for DPLL power state disabled in DPLL_ENABLE. */
2132 [ # # ]: 0 : if (intel_de_wait_for_clear(dev_priv, CNL_DPLL_ENABLE(id),
2133 : : PLL_POWER_STATE, 5))
2134 : 0 : DRM_ERROR("PLL %d Power not disabled\n", id);
2135 : 0 : }
2136 : :
2137 : 0 : static bool cnl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv,
2138 : : struct intel_shared_dpll *pll,
2139 : : struct intel_dpll_hw_state *hw_state)
2140 : : {
2141 : 0 : const enum intel_dpll_id id = pll->info->id;
2142 : 0 : intel_wakeref_t wakeref;
2143 : 0 : u32 val;
2144 : 0 : bool ret;
2145 : :
2146 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv,
2147 : : POWER_DOMAIN_DISPLAY_CORE);
2148 [ # # ]: 0 : if (!wakeref)
2149 : : return false;
2150 : :
2151 : 0 : ret = false;
2152 : :
2153 : 0 : val = I915_READ(CNL_DPLL_ENABLE(id));
2154 [ # # ]: 0 : if (!(val & PLL_ENABLE))
2155 : 0 : goto out;
2156 : :
2157 : 0 : val = I915_READ(CNL_DPLL_CFGCR0(id));
2158 : 0 : hw_state->cfgcr0 = val;
2159 : :
2160 : : /* avoid reading back stale values if HDMI mode is not enabled */
2161 [ # # ]: 0 : if (val & DPLL_CFGCR0_HDMI_MODE) {
2162 : 0 : hw_state->cfgcr1 = I915_READ(CNL_DPLL_CFGCR1(id));
2163 : : }
2164 : : ret = true;
2165 : :
2166 : 0 : out:
2167 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
2168 : :
2169 : 0 : return ret;
2170 : : }
2171 : :
2172 : 0 : static void cnl_wrpll_get_multipliers(int bestdiv, int *pdiv,
2173 : : int *qdiv, int *kdiv)
2174 : : {
2175 : : /* even dividers */
2176 [ # # ]: 0 : if (bestdiv % 2 == 0) {
2177 [ # # ]: 0 : if (bestdiv == 2) {
2178 : 0 : *pdiv = 2;
2179 : 0 : *qdiv = 1;
2180 : 0 : *kdiv = 1;
2181 [ # # ]: 0 : } else if (bestdiv % 4 == 0) {
2182 : 0 : *pdiv = 2;
2183 : 0 : *qdiv = bestdiv / 4;
2184 : 0 : *kdiv = 2;
2185 [ # # ]: 0 : } else if (bestdiv % 6 == 0) {
2186 : 0 : *pdiv = 3;
2187 : 0 : *qdiv = bestdiv / 6;
2188 : 0 : *kdiv = 2;
2189 [ # # ]: 0 : } else if (bestdiv % 5 == 0) {
2190 : 0 : *pdiv = 5;
2191 : 0 : *qdiv = bestdiv / 10;
2192 : 0 : *kdiv = 2;
2193 [ # # ]: 0 : } else if (bestdiv % 14 == 0) {
2194 : 0 : *pdiv = 7;
2195 : 0 : *qdiv = bestdiv / 14;
2196 : 0 : *kdiv = 2;
2197 : : }
2198 : : } else {
2199 [ # # # # ]: 0 : if (bestdiv == 3 || bestdiv == 5 || bestdiv == 7) {
2200 : 0 : *pdiv = bestdiv;
2201 : 0 : *qdiv = 1;
2202 : 0 : *kdiv = 1;
2203 : : } else { /* 9, 15, 21 */
2204 : 0 : *pdiv = bestdiv / 3;
2205 : 0 : *qdiv = 1;
2206 : 0 : *kdiv = 3;
2207 : : }
2208 : : }
2209 : 0 : }
2210 : :
2211 : 0 : static void cnl_wrpll_params_populate(struct skl_wrpll_params *params,
2212 : : u32 dco_freq, u32 ref_freq,
2213 : : int pdiv, int qdiv, int kdiv)
2214 : : {
2215 : 0 : u32 dco;
2216 : :
2217 [ # # # # ]: 0 : switch (kdiv) {
2218 : 0 : case 1:
2219 : 0 : params->kdiv = 1;
2220 : 0 : break;
2221 : 0 : case 2:
2222 : 0 : params->kdiv = 2;
2223 : 0 : break;
2224 : 0 : case 3:
2225 : 0 : params->kdiv = 4;
2226 : 0 : break;
2227 : : default:
2228 : 0 : WARN(1, "Incorrect KDiv\n");
2229 : : }
2230 : :
2231 [ # # # # : 0 : switch (pdiv) {
# ]
2232 : 0 : case 2:
2233 : 0 : params->pdiv = 1;
2234 : 0 : break;
2235 : 0 : case 3:
2236 : 0 : params->pdiv = 2;
2237 : 0 : break;
2238 : 0 : case 5:
2239 : 0 : params->pdiv = 4;
2240 : 0 : break;
2241 : 0 : case 7:
2242 : 0 : params->pdiv = 8;
2243 : 0 : break;
2244 : : default:
2245 : 0 : WARN(1, "Incorrect PDiv\n");
2246 : : }
2247 : :
2248 [ # # ]: 0 : WARN_ON(kdiv != 2 && qdiv != 1);
2249 : :
2250 : 0 : params->qdiv_ratio = qdiv;
2251 : 0 : params->qdiv_mode = (qdiv == 1) ? 0 : 1;
2252 : :
2253 : 0 : dco = div_u64((u64)dco_freq << 15, ref_freq);
2254 : :
2255 : 0 : params->dco_integer = dco >> 15;
2256 : 0 : params->dco_fraction = dco & 0x7fff;
2257 : 0 : }
2258 : :
2259 : 0 : int cnl_hdmi_pll_ref_clock(struct drm_i915_private *dev_priv)
2260 : : {
2261 : 0 : int ref_clock = dev_priv->cdclk.hw.ref;
2262 : :
2263 : : /*
2264 : : * For ICL+, the spec states: if reference frequency is 38.4,
2265 : : * use 19.2 because the DPLL automatically divides that by 2.
2266 : : */
2267 [ # # # # ]: 0 : if (INTEL_GEN(dev_priv) >= 11 && ref_clock == 38400)
2268 : 0 : ref_clock = 19200;
2269 : :
2270 : 0 : return ref_clock;
2271 : : }
2272 : :
2273 : : static bool
2274 : : cnl_ddi_calculate_wrpll(struct intel_crtc_state *crtc_state,
2275 : : struct skl_wrpll_params *wrpll_params)
2276 : : {
2277 : : struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
2278 : : u32 afe_clock = crtc_state->port_clock * 5;
2279 : : u32 ref_clock;
2280 : : u32 dco_min = 7998000;
2281 : : u32 dco_max = 10000000;
2282 : : u32 dco_mid = (dco_min + dco_max) / 2;
2283 : : static const int dividers[] = { 2, 4, 6, 8, 10, 12, 14, 16,
2284 : : 18, 20, 24, 28, 30, 32, 36, 40,
2285 : : 42, 44, 48, 50, 52, 54, 56, 60,
2286 : : 64, 66, 68, 70, 72, 76, 78, 80,
2287 : : 84, 88, 90, 92, 96, 98, 100, 102,
2288 : : 3, 5, 7, 9, 15, 21 };
2289 : : u32 dco, best_dco = 0, dco_centrality = 0;
2290 : : u32 best_dco_centrality = U32_MAX; /* Spec meaning of 999999 MHz */
2291 : : int d, best_div = 0, pdiv = 0, qdiv = 0, kdiv = 0;
2292 : :
2293 : : for (d = 0; d < ARRAY_SIZE(dividers); d++) {
2294 : : dco = afe_clock * dividers[d];
2295 : :
2296 : : if ((dco <= dco_max) && (dco >= dco_min)) {
2297 : : dco_centrality = abs(dco - dco_mid);
2298 : :
2299 : : if (dco_centrality < best_dco_centrality) {
2300 : : best_dco_centrality = dco_centrality;
2301 : : best_div = dividers[d];
2302 : : best_dco = dco;
2303 : : }
2304 : : }
2305 : : }
2306 : :
2307 : : if (best_div == 0)
2308 : : return false;
2309 : :
2310 : : cnl_wrpll_get_multipliers(best_div, &pdiv, &qdiv, &kdiv);
2311 : :
2312 : : ref_clock = cnl_hdmi_pll_ref_clock(dev_priv);
2313 : :
2314 : : cnl_wrpll_params_populate(wrpll_params, best_dco, ref_clock,
2315 : : pdiv, qdiv, kdiv);
2316 : :
2317 : : return true;
2318 : : }
2319 : :
2320 : 0 : static bool cnl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state)
2321 : : {
2322 : 0 : u32 cfgcr0, cfgcr1;
2323 : 0 : struct skl_wrpll_params wrpll_params = { 0, };
2324 : :
2325 : 0 : cfgcr0 = DPLL_CFGCR0_HDMI_MODE;
2326 : :
2327 [ # # ]: 0 : if (!cnl_ddi_calculate_wrpll(crtc_state, &wrpll_params))
2328 : : return false;
2329 : :
2330 : 0 : cfgcr0 |= DPLL_CFGCR0_DCO_FRACTION(wrpll_params.dco_fraction) |
2331 : 0 : wrpll_params.dco_integer;
2332 : :
2333 : 0 : cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(wrpll_params.qdiv_ratio) |
2334 : 0 : DPLL_CFGCR1_QDIV_MODE(wrpll_params.qdiv_mode) |
2335 : 0 : DPLL_CFGCR1_KDIV(wrpll_params.kdiv) |
2336 : 0 : DPLL_CFGCR1_PDIV(wrpll_params.pdiv) |
2337 : : DPLL_CFGCR1_CENTRAL_FREQ;
2338 : :
2339 : 0 : memset(&crtc_state->dpll_hw_state, 0,
2340 : : sizeof(crtc_state->dpll_hw_state));
2341 : :
2342 : 0 : crtc_state->dpll_hw_state.cfgcr0 = cfgcr0;
2343 : 0 : crtc_state->dpll_hw_state.cfgcr1 = cfgcr1;
2344 : 0 : return true;
2345 : : }
2346 : :
2347 : : static bool
2348 : 0 : cnl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state)
2349 : : {
2350 : 0 : u32 cfgcr0;
2351 : :
2352 : 0 : cfgcr0 = DPLL_CFGCR0_SSC_ENABLE;
2353 : :
2354 [ # # # # : 0 : switch (crtc_state->port_clock / 2) {
# # # # ]
2355 : 0 : case 81000:
2356 : 0 : cfgcr0 |= DPLL_CFGCR0_LINK_RATE_810;
2357 : 0 : break;
2358 : 0 : case 135000:
2359 : 0 : cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1350;
2360 : 0 : break;
2361 : : case 270000:
2362 : : cfgcr0 |= DPLL_CFGCR0_LINK_RATE_2700;
2363 : : break;
2364 : : /* eDP 1.4 rates */
2365 : 0 : case 162000:
2366 : 0 : cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1620;
2367 : 0 : break;
2368 : 0 : case 108000:
2369 : 0 : cfgcr0 |= DPLL_CFGCR0_LINK_RATE_1080;
2370 : 0 : break;
2371 : 0 : case 216000:
2372 : 0 : cfgcr0 |= DPLL_CFGCR0_LINK_RATE_2160;
2373 : 0 : break;
2374 : 0 : case 324000:
2375 : : /* Some SKUs may require elevated I/O voltage to support this */
2376 : 0 : cfgcr0 |= DPLL_CFGCR0_LINK_RATE_3240;
2377 : 0 : break;
2378 : 0 : case 405000:
2379 : : /* Some SKUs may require elevated I/O voltage to support this */
2380 : 0 : cfgcr0 |= DPLL_CFGCR0_LINK_RATE_4050;
2381 : 0 : break;
2382 : : }
2383 : :
2384 : 0 : memset(&crtc_state->dpll_hw_state, 0,
2385 : : sizeof(crtc_state->dpll_hw_state));
2386 : :
2387 : 0 : crtc_state->dpll_hw_state.cfgcr0 = cfgcr0;
2388 : :
2389 : 0 : return true;
2390 : : }
2391 : :
2392 : 0 : static bool cnl_get_dpll(struct intel_atomic_state *state,
2393 : : struct intel_crtc *crtc,
2394 : : struct intel_encoder *encoder)
2395 : : {
2396 [ # # ]: 0 : struct intel_crtc_state *crtc_state =
2397 : : intel_atomic_get_new_crtc_state(state, crtc);
2398 : 0 : struct intel_shared_dpll *pll;
2399 : 0 : bool bret;
2400 : :
2401 [ # # ]: 0 : if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) {
2402 : 0 : bret = cnl_ddi_hdmi_pll_dividers(crtc_state);
2403 [ # # ]: 0 : if (!bret) {
2404 : 0 : DRM_DEBUG_KMS("Could not get HDMI pll dividers.\n");
2405 : 0 : return false;
2406 : : }
2407 [ # # ]: 0 : } else if (intel_crtc_has_dp_encoder(crtc_state)) {
2408 : 0 : bret = cnl_ddi_dp_set_dpll_hw_state(crtc_state);
2409 [ # # ]: 0 : if (!bret) {
2410 : 0 : DRM_DEBUG_KMS("Could not set DP dpll HW state.\n");
2411 : 0 : return false;
2412 : : }
2413 : : } else {
2414 : 0 : DRM_DEBUG_KMS("Skip DPLL setup for output_types 0x%x\n",
2415 : : crtc_state->output_types);
2416 : 0 : return false;
2417 : : }
2418 : :
2419 : 0 : pll = intel_find_shared_dpll(state, crtc,
2420 : 0 : &crtc_state->dpll_hw_state,
2421 : : BIT(DPLL_ID_SKL_DPLL2) |
2422 : : BIT(DPLL_ID_SKL_DPLL1) |
2423 : : BIT(DPLL_ID_SKL_DPLL0));
2424 [ # # ]: 0 : if (!pll) {
2425 : 0 : DRM_DEBUG_KMS("No PLL selected\n");
2426 : 0 : return false;
2427 : : }
2428 : :
2429 : 0 : intel_reference_shared_dpll(state, crtc,
2430 : : pll, &crtc_state->dpll_hw_state);
2431 : :
2432 : 0 : crtc_state->shared_dpll = pll;
2433 : :
2434 : 0 : return true;
2435 : : }
2436 : :
2437 : 0 : static void cnl_dump_hw_state(struct drm_i915_private *dev_priv,
2438 : : const struct intel_dpll_hw_state *hw_state)
2439 : : {
2440 : 0 : DRM_DEBUG_KMS("dpll_hw_state: "
2441 : : "cfgcr0: 0x%x, cfgcr1: 0x%x\n",
2442 : : hw_state->cfgcr0,
2443 : : hw_state->cfgcr1);
2444 : 0 : }
2445 : :
2446 : : static const struct intel_shared_dpll_funcs cnl_ddi_pll_funcs = {
2447 : : .enable = cnl_ddi_pll_enable,
2448 : : .disable = cnl_ddi_pll_disable,
2449 : : .get_hw_state = cnl_ddi_pll_get_hw_state,
2450 : : };
2451 : :
2452 : : static const struct dpll_info cnl_plls[] = {
2453 : : { "DPLL 0", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL0, 0 },
2454 : : { "DPLL 1", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 },
2455 : : { "DPLL 2", &cnl_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 },
2456 : : { },
2457 : : };
2458 : :
2459 : : static const struct intel_dpll_mgr cnl_pll_mgr = {
2460 : : .dpll_info = cnl_plls,
2461 : : .get_dplls = cnl_get_dpll,
2462 : : .put_dplls = intel_put_dpll,
2463 : : .dump_hw_state = cnl_dump_hw_state,
2464 : : };
2465 : :
2466 : : struct icl_combo_pll_params {
2467 : : int clock;
2468 : : struct skl_wrpll_params wrpll;
2469 : : };
2470 : :
2471 : : /*
2472 : : * These values alrea already adjusted: they're the bits we write to the
2473 : : * registers, not the logical values.
2474 : : */
2475 : : static const struct icl_combo_pll_params icl_dp_combo_pll_24MHz_values[] = {
2476 : : { 540000,
2477 : : { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [0]: 5.4 */
2478 : : .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2479 : : { 270000,
2480 : : { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [1]: 2.7 */
2481 : : .pdiv = 0x2 /* 3 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2482 : : { 162000,
2483 : : { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [2]: 1.62 */
2484 : : .pdiv = 0x4 /* 5 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2485 : : { 324000,
2486 : : { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [3]: 3.24 */
2487 : : .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2488 : : { 216000,
2489 : : { .dco_integer = 0x168, .dco_fraction = 0x0000, /* [4]: 2.16 */
2490 : : .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 1, .qdiv_ratio = 2, }, },
2491 : : { 432000,
2492 : : { .dco_integer = 0x168, .dco_fraction = 0x0000, /* [5]: 4.32 */
2493 : : .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2494 : : { 648000,
2495 : : { .dco_integer = 0x195, .dco_fraction = 0x0000, /* [6]: 6.48 */
2496 : : .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2497 : : { 810000,
2498 : : { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [7]: 8.1 */
2499 : : .pdiv = 0x1 /* 2 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2500 : : };
2501 : :
2502 : :
2503 : : /* Also used for 38.4 MHz values. */
2504 : : static const struct icl_combo_pll_params icl_dp_combo_pll_19_2MHz_values[] = {
2505 : : { 540000,
2506 : : { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [0]: 5.4 */
2507 : : .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2508 : : { 270000,
2509 : : { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [1]: 2.7 */
2510 : : .pdiv = 0x2 /* 3 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2511 : : { 162000,
2512 : : { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [2]: 1.62 */
2513 : : .pdiv = 0x4 /* 5 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2514 : : { 324000,
2515 : : { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [3]: 3.24 */
2516 : : .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2517 : : { 216000,
2518 : : { .dco_integer = 0x1C2, .dco_fraction = 0x0000, /* [4]: 2.16 */
2519 : : .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 1, .qdiv_ratio = 2, }, },
2520 : : { 432000,
2521 : : { .dco_integer = 0x1C2, .dco_fraction = 0x0000, /* [5]: 4.32 */
2522 : : .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2523 : : { 648000,
2524 : : { .dco_integer = 0x1FA, .dco_fraction = 0x2000, /* [6]: 6.48 */
2525 : : .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2526 : : { 810000,
2527 : : { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [7]: 8.1 */
2528 : : .pdiv = 0x1 /* 2 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, },
2529 : : };
2530 : :
2531 : : static const struct skl_wrpll_params icl_tbt_pll_24MHz_values = {
2532 : : .dco_integer = 0x151, .dco_fraction = 0x4000,
2533 : : .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0,
2534 : : };
2535 : :
2536 : : static const struct skl_wrpll_params icl_tbt_pll_19_2MHz_values = {
2537 : : .dco_integer = 0x1A5, .dco_fraction = 0x7000,
2538 : : .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0,
2539 : : };
2540 : :
2541 : : static const struct skl_wrpll_params tgl_tbt_pll_19_2MHz_values = {
2542 : : .dco_integer = 0x54, .dco_fraction = 0x3000,
2543 : : /* the following params are unused */
2544 : : .pdiv = 0, .kdiv = 0, .qdiv_mode = 0, .qdiv_ratio = 0,
2545 : : };
2546 : :
2547 : : static const struct skl_wrpll_params tgl_tbt_pll_24MHz_values = {
2548 : : .dco_integer = 0x43, .dco_fraction = 0x4000,
2549 : : /* the following params are unused */
2550 : : .pdiv = 0, .kdiv = 0, .qdiv_mode = 0, .qdiv_ratio = 0,
2551 : : };
2552 : :
2553 : : static bool icl_calc_dp_combo_pll(struct intel_crtc_state *crtc_state,
2554 : : struct skl_wrpll_params *pll_params)
2555 : : {
2556 : : struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
2557 : : const struct icl_combo_pll_params *params =
2558 : : dev_priv->cdclk.hw.ref == 24000 ?
2559 : : icl_dp_combo_pll_24MHz_values :
2560 : : icl_dp_combo_pll_19_2MHz_values;
2561 : : int clock = crtc_state->port_clock;
2562 : : int i;
2563 : :
2564 : : for (i = 0; i < ARRAY_SIZE(icl_dp_combo_pll_24MHz_values); i++) {
2565 : : if (clock == params[i].clock) {
2566 : : *pll_params = params[i].wrpll;
2567 : : return true;
2568 : : }
2569 : : }
2570 : :
2571 : : MISSING_CASE(clock);
2572 : : return false;
2573 : : }
2574 : :
2575 : : static bool icl_calc_tbt_pll(struct intel_crtc_state *crtc_state,
2576 : : struct skl_wrpll_params *pll_params)
2577 : : {
2578 : : struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
2579 : :
2580 : : if (INTEL_GEN(dev_priv) >= 12) {
2581 : : switch (dev_priv->cdclk.hw.ref) {
2582 : : default:
2583 : : MISSING_CASE(dev_priv->cdclk.hw.ref);
2584 : : /* fall-through */
2585 : : case 19200:
2586 : : case 38400:
2587 : : *pll_params = tgl_tbt_pll_19_2MHz_values;
2588 : : break;
2589 : : case 24000:
2590 : : *pll_params = tgl_tbt_pll_24MHz_values;
2591 : : break;
2592 : : }
2593 : : } else {
2594 : : switch (dev_priv->cdclk.hw.ref) {
2595 : : default:
2596 : : MISSING_CASE(dev_priv->cdclk.hw.ref);
2597 : : /* fall-through */
2598 : : case 19200:
2599 : : case 38400:
2600 : : *pll_params = icl_tbt_pll_19_2MHz_values;
2601 : : break;
2602 : : case 24000:
2603 : : *pll_params = icl_tbt_pll_24MHz_values;
2604 : : break;
2605 : : }
2606 : : }
2607 : :
2608 : : return true;
2609 : : }
2610 : :
2611 : : static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
2612 : : struct intel_encoder *encoder,
2613 : : struct intel_dpll_hw_state *pll_state)
2614 : : {
2615 : : struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
2616 : : u32 cfgcr0, cfgcr1;
2617 : : struct skl_wrpll_params pll_params = { 0 };
2618 : : bool ret;
2619 : :
2620 : : if (intel_phy_is_tc(dev_priv, intel_port_to_phy(dev_priv,
2621 : : encoder->port)))
2622 : : ret = icl_calc_tbt_pll(crtc_state, &pll_params);
2623 : : else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) ||
2624 : : intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
2625 : : ret = cnl_ddi_calculate_wrpll(crtc_state, &pll_params);
2626 : : else
2627 : : ret = icl_calc_dp_combo_pll(crtc_state, &pll_params);
2628 : :
2629 : : if (!ret)
2630 : : return false;
2631 : :
2632 : : cfgcr0 = DPLL_CFGCR0_DCO_FRACTION(pll_params.dco_fraction) |
2633 : : pll_params.dco_integer;
2634 : :
2635 : : cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(pll_params.qdiv_ratio) |
2636 : : DPLL_CFGCR1_QDIV_MODE(pll_params.qdiv_mode) |
2637 : : DPLL_CFGCR1_KDIV(pll_params.kdiv) |
2638 : : DPLL_CFGCR1_PDIV(pll_params.pdiv);
2639 : :
2640 : : if (INTEL_GEN(dev_priv) >= 12)
2641 : : cfgcr1 |= TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL;
2642 : : else
2643 : : cfgcr1 |= DPLL_CFGCR1_CENTRAL_FREQ_8400;
2644 : :
2645 : : memset(pll_state, 0, sizeof(*pll_state));
2646 : :
2647 : : pll_state->cfgcr0 = cfgcr0;
2648 : : pll_state->cfgcr1 = cfgcr1;
2649 : :
2650 : : return true;
2651 : : }
2652 : :
2653 : :
2654 : 0 : static enum tc_port icl_pll_id_to_tc_port(enum intel_dpll_id id)
2655 : : {
2656 : 0 : return id - DPLL_ID_ICL_MGPLL1;
2657 : : }
2658 : :
2659 : 0 : enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port)
2660 : : {
2661 : 0 : return tc_port + DPLL_ID_ICL_MGPLL1;
2662 : : }
2663 : :
2664 : 0 : static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc,
2665 : : u32 *target_dco_khz,
2666 : : struct intel_dpll_hw_state *state,
2667 : : bool is_dkl)
2668 : : {
2669 : 0 : u32 dco_min_freq, dco_max_freq;
2670 : 0 : int div1_vals[] = {7, 5, 3, 2};
2671 : 0 : unsigned int i;
2672 : 0 : int div2;
2673 : :
2674 [ # # # # ]: 0 : dco_min_freq = is_dp ? 8100000 : use_ssc ? 8000000 : 7992000;
2675 [ # # ]: 0 : dco_max_freq = is_dp ? 8100000 : 10000000;
2676 : :
2677 [ # # ]: 0 : for (i = 0; i < ARRAY_SIZE(div1_vals); i++) {
2678 : 0 : int div1 = div1_vals[i];
2679 : :
2680 [ # # ]: 0 : for (div2 = 10; div2 > 0; div2--) {
2681 : 0 : int dco = div1 * div2 * clock_khz * 5;
2682 : 0 : int a_divratio, tlinedrv, inputsel;
2683 : 0 : u32 hsdiv;
2684 : :
2685 [ # # ]: 0 : if (dco < dco_min_freq || dco > dco_max_freq)
2686 : 0 : continue;
2687 : :
2688 [ # # ]: 0 : if (div2 >= 2) {
2689 : : /*
2690 : : * Note: a_divratio not matching TGL BSpec
2691 : : * algorithm but matching hardcoded values and
2692 : : * working on HW for DP alt-mode at least
2693 : : */
2694 [ # # ]: 0 : a_divratio = is_dp ? 10 : 5;
2695 [ # # ]: 0 : tlinedrv = is_dkl ? 1 : 2;
2696 : : } else {
2697 : : a_divratio = 5;
2698 : : tlinedrv = 0;
2699 : : }
2700 : 0 : inputsel = is_dp ? 0 : 1;
2701 : :
2702 [ # # # # : 0 : switch (div1) {
# ]
2703 : : default:
2704 : 0 : MISSING_CASE(div1);
2705 : : /* fall through */
2706 : : case 2:
2707 : : hsdiv = MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2;
2708 : : break;
2709 : : case 3:
2710 : : hsdiv = MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_3;
2711 : : break;
2712 : 0 : case 5:
2713 : 0 : hsdiv = MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_5;
2714 : 0 : break;
2715 : 0 : case 7:
2716 : 0 : hsdiv = MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_7;
2717 : 0 : break;
2718 : : }
2719 : :
2720 : 0 : *target_dco_khz = dco;
2721 : :
2722 : 0 : state->mg_refclkin_ctl = MG_REFCLKIN_CTL_OD_2_MUX(1);
2723 : :
2724 : 0 : state->mg_clktop2_coreclkctl1 =
2725 : 0 : MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO(a_divratio);
2726 : :
2727 : 0 : state->mg_clktop2_hsclkctl =
2728 : 0 : MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL(tlinedrv) |
2729 : 0 : MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL(inputsel) |
2730 : 0 : hsdiv |
2731 : 0 : MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO(div2);
2732 : :
2733 : 0 : return true;
2734 : : }
2735 : : }
2736 : :
2737 : : return false;
2738 : : }
2739 : :
2740 : : /*
2741 : : * The specification for this function uses real numbers, so the math had to be
2742 : : * adapted to integer-only calculation, that's why it looks so different.
2743 : : */
2744 : 0 : static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
2745 : : struct intel_dpll_hw_state *pll_state)
2746 : : {
2747 : 0 : struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
2748 : 0 : int refclk_khz = dev_priv->cdclk.hw.ref;
2749 : 0 : int clock = crtc_state->port_clock;
2750 : 0 : u32 dco_khz, m1div, m2div_int, m2div_rem, m2div_frac;
2751 : 0 : u32 iref_ndiv, iref_trim, iref_pulse_w;
2752 : 0 : u32 prop_coeff, int_coeff;
2753 : 0 : u32 tdc_targetcnt, feedfwgain;
2754 : 0 : u64 ssc_stepsize, ssc_steplen, ssc_steplog;
2755 : 0 : u64 tmp;
2756 : 0 : bool use_ssc = false;
2757 : 0 : bool is_dp = !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI);
2758 : 0 : bool is_dkl = INTEL_GEN(dev_priv) >= 12;
2759 : :
2760 : 0 : memset(pll_state, 0, sizeof(*pll_state));
2761 : :
2762 [ # # ]: 0 : if (!icl_mg_pll_find_divisors(clock, is_dp, use_ssc, &dco_khz,
2763 : : pll_state, is_dkl)) {
2764 : 0 : DRM_DEBUG_KMS("Failed to find divisors for clock %d\n", clock);
2765 : 0 : return false;
2766 : : }
2767 : :
2768 : 0 : m1div = 2;
2769 : 0 : m2div_int = dco_khz / (refclk_khz * m1div);
2770 [ # # ]: 0 : if (m2div_int > 255) {
2771 [ # # ]: 0 : if (!is_dkl) {
2772 : 0 : m1div = 4;
2773 : 0 : m2div_int = dco_khz / (refclk_khz * m1div);
2774 : : }
2775 : :
2776 [ # # ]: 0 : if (m2div_int > 255) {
2777 : 0 : DRM_DEBUG_KMS("Failed to find mdiv for clock %d\n",
2778 : : clock);
2779 : 0 : return false;
2780 : : }
2781 : : }
2782 : 0 : m2div_rem = dco_khz % (refclk_khz * m1div);
2783 : :
2784 : 0 : tmp = (u64)m2div_rem * (1 << 22);
2785 : 0 : do_div(tmp, refclk_khz * m1div);
2786 : 0 : m2div_frac = tmp;
2787 : :
2788 [ # # # # ]: 0 : switch (refclk_khz) {
2789 : : case 19200:
2790 : : iref_ndiv = 1;
2791 : : iref_trim = 28;
2792 : : iref_pulse_w = 1;
2793 : : break;
2794 : 0 : case 24000:
2795 : 0 : iref_ndiv = 1;
2796 : 0 : iref_trim = 25;
2797 : 0 : iref_pulse_w = 2;
2798 : 0 : break;
2799 : 0 : case 38400:
2800 : 0 : iref_ndiv = 2;
2801 : 0 : iref_trim = 28;
2802 : 0 : iref_pulse_w = 1;
2803 : 0 : break;
2804 : : default:
2805 : 0 : MISSING_CASE(refclk_khz);
2806 : 0 : return false;
2807 : : }
2808 : :
2809 : : /*
2810 : : * tdc_res = 0.000003
2811 : : * tdc_targetcnt = int(2 / (tdc_res * 8 * 50 * 1.1) / refclk_mhz + 0.5)
2812 : : *
2813 : : * The multiplication by 1000 is due to refclk MHz to KHz conversion. It
2814 : : * was supposed to be a division, but we rearranged the operations of
2815 : : * the formula to avoid early divisions so we don't multiply the
2816 : : * rounding errors.
2817 : : *
2818 : : * 0.000003 * 8 * 50 * 1.1 = 0.00132, also known as 132 / 100000, which
2819 : : * we also rearrange to work with integers.
2820 : : *
2821 : : * The 0.5 transformed to 5 results in a multiplication by 10 and the
2822 : : * last division by 10.
2823 : : */
2824 : 0 : tdc_targetcnt = (2 * 1000 * 100000 * 10 / (132 * refclk_khz) + 5) / 10;
2825 : :
2826 : : /*
2827 : : * Here we divide dco_khz by 10 in order to allow the dividend to fit in
2828 : : * 32 bits. That's not a problem since we round the division down
2829 : : * anyway.
2830 : : */
2831 : 0 : feedfwgain = (use_ssc || m2div_rem > 0) ?
2832 [ # # ]: 0 : m1div * 1000000 * 100 / (dco_khz * 3 / 10) : 0;
2833 : :
2834 [ # # ]: 0 : if (dco_khz >= 9000000) {
2835 : : prop_coeff = 5;
2836 : : int_coeff = 10;
2837 : : } else {
2838 : 0 : prop_coeff = 4;
2839 : 0 : int_coeff = 8;
2840 : : }
2841 : :
2842 : 0 : if (use_ssc) {
2843 : : tmp = mul_u32_u32(dco_khz, 47 * 32);
2844 : : do_div(tmp, refclk_khz * m1div * 10000);
2845 : : ssc_stepsize = tmp;
2846 : :
2847 : : tmp = mul_u32_u32(dco_khz, 1000);
2848 : : ssc_steplen = DIV_ROUND_UP_ULL(tmp, 32 * 2 * 32);
2849 : : } else {
2850 : 0 : ssc_stepsize = 0;
2851 : 0 : ssc_steplen = 0;
2852 : : }
2853 : 0 : ssc_steplog = 4;
2854 : :
2855 : : /* write pll_state calculations */
2856 [ # # ]: 0 : if (is_dkl) {
2857 : 0 : pll_state->mg_pll_div0 = DKL_PLL_DIV0_INTEG_COEFF(int_coeff) |
2858 : 0 : DKL_PLL_DIV0_PROP_COEFF(prop_coeff) |
2859 : 0 : DKL_PLL_DIV0_FBPREDIV(m1div) |
2860 : : DKL_PLL_DIV0_FBDIV_INT(m2div_int);
2861 : :
2862 : 0 : pll_state->mg_pll_div1 = DKL_PLL_DIV1_IREF_TRIM(iref_trim) |
2863 : : DKL_PLL_DIV1_TDC_TARGET_CNT(tdc_targetcnt);
2864 : :
2865 : 0 : pll_state->mg_pll_ssc = DKL_PLL_SSC_IREF_NDIV_RATIO(iref_ndiv) |
2866 : 0 : DKL_PLL_SSC_STEP_LEN(ssc_steplen) |
2867 : : DKL_PLL_SSC_STEP_NUM(ssc_steplog) |
2868 : : (use_ssc ? DKL_PLL_SSC_EN : 0);
2869 : :
2870 [ # # ]: 0 : pll_state->mg_pll_bias = (m2div_frac ? DKL_PLL_BIAS_FRAC_EN_H : 0) |
2871 : 0 : DKL_PLL_BIAS_FBDIV_FRAC(m2div_frac);
2872 : :
2873 : 0 : pll_state->mg_pll_tdc_coldst_bias =
2874 : : DKL_PLL_TDC_SSC_STEP_SIZE(ssc_stepsize) |
2875 : : DKL_PLL_TDC_FEED_FWD_GAIN(feedfwgain);
2876 : :
2877 : : } else {
2878 : 0 : pll_state->mg_pll_div0 =
2879 [ # # ]: 0 : (m2div_rem > 0 ? MG_PLL_DIV0_FRACNEN_H : 0) |
2880 : 0 : MG_PLL_DIV0_FBDIV_FRAC(m2div_frac) |
2881 : : MG_PLL_DIV0_FBDIV_INT(m2div_int);
2882 : :
2883 : 0 : pll_state->mg_pll_div1 =
2884 : 0 : MG_PLL_DIV1_IREF_NDIVRATIO(iref_ndiv) |
2885 : : MG_PLL_DIV1_DITHER_DIV_2 |
2886 : 0 : MG_PLL_DIV1_NDIVRATIO(1) |
2887 : : MG_PLL_DIV1_FBPREDIV(m1div);
2888 : :
2889 : 0 : pll_state->mg_pll_lf =
2890 : 0 : MG_PLL_LF_TDCTARGETCNT(tdc_targetcnt) |
2891 : : MG_PLL_LF_AFCCNTSEL_512 |
2892 : 0 : MG_PLL_LF_GAINCTRL(1) |
2893 : 0 : MG_PLL_LF_INT_COEFF(int_coeff) |
2894 : : MG_PLL_LF_PROP_COEFF(prop_coeff);
2895 : :
2896 : 0 : pll_state->mg_pll_frac_lock =
2897 : : MG_PLL_FRAC_LOCK_TRUELOCK_CRIT_32 |
2898 : : MG_PLL_FRAC_LOCK_EARLYLOCK_CRIT_32 |
2899 : : MG_PLL_FRAC_LOCK_LOCKTHRESH(10) |
2900 : 0 : MG_PLL_FRAC_LOCK_DCODITHEREN |
2901 : : MG_PLL_FRAC_LOCK_FEEDFWRDGAIN(feedfwgain);
2902 [ # # ]: 0 : if (use_ssc || m2div_rem > 0)
2903 : 0 : pll_state->mg_pll_frac_lock |=
2904 : : MG_PLL_FRAC_LOCK_FEEDFWRDCAL_EN;
2905 : :
2906 : 0 : pll_state->mg_pll_ssc =
2907 : : (use_ssc ? MG_PLL_SSC_EN : 0) |
2908 : : MG_PLL_SSC_TYPE(2) |
2909 : : MG_PLL_SSC_STEPLENGTH(ssc_steplen) |
2910 : : MG_PLL_SSC_STEPNUM(ssc_steplog) |
2911 : : MG_PLL_SSC_FLLEN |
2912 : : MG_PLL_SSC_STEPSIZE(ssc_stepsize);
2913 : :
2914 : 0 : pll_state->mg_pll_tdc_coldst_bias =
2915 : : MG_PLL_TDC_COLDST_COLDSTART |
2916 : : MG_PLL_TDC_COLDST_IREFINT_EN |
2917 : 0 : MG_PLL_TDC_COLDST_REFBIAS_START_PULSE_W(iref_pulse_w) |
2918 : 0 : MG_PLL_TDC_TDCOVCCORR_EN |
2919 : : MG_PLL_TDC_TDCSEL(3);
2920 : :
2921 : 0 : pll_state->mg_pll_bias =
2922 : : MG_PLL_BIAS_BIAS_GB_SEL(3) |
2923 : : MG_PLL_BIAS_INIT_DCOAMP(0x3F) |
2924 : : MG_PLL_BIAS_BIAS_BONUS(10) |
2925 : : MG_PLL_BIAS_BIASCAL_EN |
2926 : : MG_PLL_BIAS_CTRIM(12) |
2927 : 0 : MG_PLL_BIAS_VREF_RDAC(4) |
2928 : : MG_PLL_BIAS_IREFTRIM(iref_trim);
2929 : :
2930 [ # # ]: 0 : if (refclk_khz == 38400) {
2931 : 0 : pll_state->mg_pll_tdc_coldst_bias_mask =
2932 : : MG_PLL_TDC_COLDST_COLDSTART;
2933 : 0 : pll_state->mg_pll_bias_mask = 0;
2934 : : } else {
2935 : 0 : pll_state->mg_pll_tdc_coldst_bias_mask = -1U;
2936 : 0 : pll_state->mg_pll_bias_mask = -1U;
2937 : : }
2938 : :
2939 : 0 : pll_state->mg_pll_tdc_coldst_bias &=
2940 : 0 : pll_state->mg_pll_tdc_coldst_bias_mask;
2941 : 0 : pll_state->mg_pll_bias &= pll_state->mg_pll_bias_mask;
2942 : : }
2943 : :
2944 : : return true;
2945 : : }
2946 : :
2947 : : /**
2948 : : * icl_set_active_port_dpll - select the active port DPLL for a given CRTC
2949 : : * @crtc_state: state for the CRTC to select the DPLL for
2950 : : * @port_dpll_id: the active @port_dpll_id to select
2951 : : *
2952 : : * Select the given @port_dpll_id instance from the DPLLs reserved for the
2953 : : * CRTC.
2954 : : */
2955 : 0 : void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state,
2956 : : enum icl_port_dpll_id port_dpll_id)
2957 : : {
2958 : 0 : struct icl_port_dpll *port_dpll =
2959 : : &crtc_state->icl_port_dplls[port_dpll_id];
2960 : :
2961 : 0 : crtc_state->shared_dpll = port_dpll->pll;
2962 : 0 : crtc_state->dpll_hw_state = port_dpll->hw_state;
2963 : 0 : }
2964 : :
2965 : 0 : static void icl_update_active_dpll(struct intel_atomic_state *state,
2966 : : struct intel_crtc *crtc,
2967 : : struct intel_encoder *encoder)
2968 : : {
2969 [ # # ]: 0 : struct intel_crtc_state *crtc_state =
2970 : : intel_atomic_get_new_crtc_state(state, crtc);
2971 : 0 : struct intel_digital_port *primary_port;
2972 : 0 : enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT;
2973 : :
2974 : 0 : primary_port = encoder->type == INTEL_OUTPUT_DP_MST ?
2975 [ # # ]: 0 : enc_to_mst(encoder)->primary :
2976 : : enc_to_dig_port(encoder);
2977 : :
2978 [ # # ]: 0 : if (primary_port &&
2979 [ # # ]: 0 : (primary_port->tc_mode == TC_PORT_DP_ALT ||
2980 : : primary_port->tc_mode == TC_PORT_LEGACY))
2981 : 0 : port_dpll_id = ICL_PORT_DPLL_MG_PHY;
2982 : :
2983 : 0 : icl_set_active_port_dpll(crtc_state, port_dpll_id);
2984 : 0 : }
2985 : :
2986 : 0 : static bool icl_get_combo_phy_dpll(struct intel_atomic_state *state,
2987 : : struct intel_crtc *crtc,
2988 : : struct intel_encoder *encoder)
2989 : : {
2990 : 0 : struct intel_crtc_state *crtc_state =
2991 : : intel_atomic_get_new_crtc_state(state, crtc);
2992 : 0 : struct icl_port_dpll *port_dpll =
2993 : : &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
2994 : 0 : struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
2995 : 0 : enum port port = encoder->port;
2996 : 0 : unsigned long dpll_mask;
2997 : :
2998 [ # # ]: 0 : if (!icl_calc_dpll_state(crtc_state, encoder, &port_dpll->hw_state)) {
2999 : 0 : DRM_DEBUG_KMS("Could not calculate combo PHY PLL state.\n");
3000 : :
3001 : 0 : return false;
3002 : : }
3003 : :
3004 [ # # # # ]: 0 : if (IS_ELKHARTLAKE(dev_priv) && port != PORT_A)
3005 : : dpll_mask =
3006 : : BIT(DPLL_ID_EHL_DPLL4) |
3007 : : BIT(DPLL_ID_ICL_DPLL1) |
3008 : : BIT(DPLL_ID_ICL_DPLL0);
3009 : : else
3010 : 0 : dpll_mask = BIT(DPLL_ID_ICL_DPLL1) | BIT(DPLL_ID_ICL_DPLL0);
3011 : :
3012 : 0 : port_dpll->pll = intel_find_shared_dpll(state, crtc,
3013 : : &port_dpll->hw_state,
3014 : : dpll_mask);
3015 [ # # ]: 0 : if (!port_dpll->pll) {
3016 : 0 : DRM_DEBUG_KMS("No combo PHY PLL found for [ENCODER:%d:%s]\n",
3017 : : encoder->base.base.id, encoder->base.name);
3018 : 0 : return false;
3019 : : }
3020 : :
3021 : 0 : intel_reference_shared_dpll(state, crtc,
3022 : : port_dpll->pll, &port_dpll->hw_state);
3023 : :
3024 : 0 : icl_update_active_dpll(state, crtc, encoder);
3025 : :
3026 : 0 : return true;
3027 : : }
3028 : :
3029 : 0 : static bool icl_get_tc_phy_dplls(struct intel_atomic_state *state,
3030 : : struct intel_crtc *crtc,
3031 : : struct intel_encoder *encoder)
3032 : : {
3033 : 0 : struct drm_i915_private *dev_priv = to_i915(state->base.dev);
3034 : 0 : struct intel_crtc_state *crtc_state =
3035 : : intel_atomic_get_new_crtc_state(state, crtc);
3036 : 0 : struct icl_port_dpll *port_dpll;
3037 : 0 : enum intel_dpll_id dpll_id;
3038 : :
3039 : 0 : port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
3040 [ # # ]: 0 : if (!icl_calc_dpll_state(crtc_state, encoder, &port_dpll->hw_state)) {
3041 : 0 : DRM_DEBUG_KMS("Could not calculate TBT PLL state.\n");
3042 : 0 : return false;
3043 : : }
3044 : :
3045 : 0 : port_dpll->pll = intel_find_shared_dpll(state, crtc,
3046 : : &port_dpll->hw_state,
3047 : : BIT(DPLL_ID_ICL_TBTPLL));
3048 [ # # ]: 0 : if (!port_dpll->pll) {
3049 : 0 : DRM_DEBUG_KMS("No TBT-ALT PLL found\n");
3050 : 0 : return false;
3051 : : }
3052 : 0 : intel_reference_shared_dpll(state, crtc,
3053 : : port_dpll->pll, &port_dpll->hw_state);
3054 : :
3055 : :
3056 : 0 : port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY];
3057 [ # # ]: 0 : if (!icl_calc_mg_pll_state(crtc_state, &port_dpll->hw_state)) {
3058 : 0 : DRM_DEBUG_KMS("Could not calculate MG PHY PLL state.\n");
3059 : 0 : goto err_unreference_tbt_pll;
3060 : : }
3061 : :
3062 : 0 : dpll_id = icl_tc_port_to_pll_id(intel_port_to_tc(dev_priv,
3063 : : encoder->port));
3064 : 0 : port_dpll->pll = intel_find_shared_dpll(state, crtc,
3065 : : &port_dpll->hw_state,
3066 : : BIT(dpll_id));
3067 [ # # ]: 0 : if (!port_dpll->pll) {
3068 : 0 : DRM_DEBUG_KMS("No MG PHY PLL found\n");
3069 : 0 : goto err_unreference_tbt_pll;
3070 : : }
3071 : 0 : intel_reference_shared_dpll(state, crtc,
3072 : : port_dpll->pll, &port_dpll->hw_state);
3073 : :
3074 : 0 : icl_update_active_dpll(state, crtc, encoder);
3075 : :
3076 : 0 : return true;
3077 : :
3078 : 0 : err_unreference_tbt_pll:
3079 : 0 : port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT];
3080 : 0 : intel_unreference_shared_dpll(state, crtc, port_dpll->pll);
3081 : :
3082 : 0 : return false;
3083 : : }
3084 : :
3085 : 0 : static bool icl_get_dplls(struct intel_atomic_state *state,
3086 : : struct intel_crtc *crtc,
3087 : : struct intel_encoder *encoder)
3088 : : {
3089 : 0 : struct drm_i915_private *dev_priv = to_i915(state->base.dev);
3090 : 0 : enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
3091 : :
3092 [ # # ]: 0 : if (intel_phy_is_combo(dev_priv, phy))
3093 : 0 : return icl_get_combo_phy_dpll(state, crtc, encoder);
3094 [ # # ]: 0 : else if (intel_phy_is_tc(dev_priv, phy))
3095 : 0 : return icl_get_tc_phy_dplls(state, crtc, encoder);
3096 : :
3097 : 0 : MISSING_CASE(phy);
3098 : :
3099 : 0 : return false;
3100 : : }
3101 : :
3102 : 0 : static void icl_put_dplls(struct intel_atomic_state *state,
3103 : : struct intel_crtc *crtc)
3104 : : {
3105 : 0 : const struct intel_crtc_state *old_crtc_state =
3106 : : intel_atomic_get_old_crtc_state(state, crtc);
3107 : 0 : struct intel_crtc_state *new_crtc_state =
3108 : : intel_atomic_get_new_crtc_state(state, crtc);
3109 : 0 : enum icl_port_dpll_id id;
3110 : :
3111 : 0 : new_crtc_state->shared_dpll = NULL;
3112 : :
3113 [ # # ]: 0 : for (id = ICL_PORT_DPLL_DEFAULT; id < ICL_PORT_DPLL_COUNT; id++) {
3114 : 0 : const struct icl_port_dpll *old_port_dpll =
3115 : : &old_crtc_state->icl_port_dplls[id];
3116 : 0 : struct icl_port_dpll *new_port_dpll =
3117 : : &new_crtc_state->icl_port_dplls[id];
3118 : :
3119 : 0 : new_port_dpll->pll = NULL;
3120 : :
3121 [ # # ]: 0 : if (!old_port_dpll->pll)
3122 : 0 : continue;
3123 : :
3124 : 0 : intel_unreference_shared_dpll(state, crtc, old_port_dpll->pll);
3125 : : }
3126 : 0 : }
3127 : :
3128 : 0 : static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv,
3129 : : struct intel_shared_dpll *pll,
3130 : : struct intel_dpll_hw_state *hw_state)
3131 : : {
3132 : 0 : const enum intel_dpll_id id = pll->info->id;
3133 : 0 : enum tc_port tc_port = icl_pll_id_to_tc_port(id);
3134 : 0 : intel_wakeref_t wakeref;
3135 : 0 : bool ret = false;
3136 : 0 : u32 val;
3137 : :
3138 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv,
3139 : : POWER_DOMAIN_DISPLAY_CORE);
3140 [ # # ]: 0 : if (!wakeref)
3141 : : return false;
3142 : :
3143 : 0 : val = I915_READ(MG_PLL_ENABLE(tc_port));
3144 [ # # ]: 0 : if (!(val & PLL_ENABLE))
3145 : 0 : goto out;
3146 : :
3147 : 0 : hw_state->mg_refclkin_ctl = I915_READ(MG_REFCLKIN_CTL(tc_port));
3148 : 0 : hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK;
3149 : :
3150 : 0 : hw_state->mg_clktop2_coreclkctl1 =
3151 : 0 : I915_READ(MG_CLKTOP2_CORECLKCTL1(tc_port));
3152 : 0 : hw_state->mg_clktop2_coreclkctl1 &=
3153 : : MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
3154 : :
3155 : 0 : hw_state->mg_clktop2_hsclkctl =
3156 : 0 : I915_READ(MG_CLKTOP2_HSCLKCTL(tc_port));
3157 : 0 : hw_state->mg_clktop2_hsclkctl &=
3158 : : MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
3159 : : MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
3160 : : MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK |
3161 : : MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK;
3162 : :
3163 : 0 : hw_state->mg_pll_div0 = I915_READ(MG_PLL_DIV0(tc_port));
3164 : 0 : hw_state->mg_pll_div1 = I915_READ(MG_PLL_DIV1(tc_port));
3165 : 0 : hw_state->mg_pll_lf = I915_READ(MG_PLL_LF(tc_port));
3166 : 0 : hw_state->mg_pll_frac_lock = I915_READ(MG_PLL_FRAC_LOCK(tc_port));
3167 : 0 : hw_state->mg_pll_ssc = I915_READ(MG_PLL_SSC(tc_port));
3168 : :
3169 : 0 : hw_state->mg_pll_bias = I915_READ(MG_PLL_BIAS(tc_port));
3170 : 0 : hw_state->mg_pll_tdc_coldst_bias =
3171 : 0 : I915_READ(MG_PLL_TDC_COLDST_BIAS(tc_port));
3172 : :
3173 [ # # ]: 0 : if (dev_priv->cdclk.hw.ref == 38400) {
3174 : 0 : hw_state->mg_pll_tdc_coldst_bias_mask = MG_PLL_TDC_COLDST_COLDSTART;
3175 : 0 : hw_state->mg_pll_bias_mask = 0;
3176 : : } else {
3177 : 0 : hw_state->mg_pll_tdc_coldst_bias_mask = -1U;
3178 : 0 : hw_state->mg_pll_bias_mask = -1U;
3179 : : }
3180 : :
3181 : 0 : hw_state->mg_pll_tdc_coldst_bias &= hw_state->mg_pll_tdc_coldst_bias_mask;
3182 : 0 : hw_state->mg_pll_bias &= hw_state->mg_pll_bias_mask;
3183 : :
3184 : 0 : ret = true;
3185 : 0 : out:
3186 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
3187 : 0 : return ret;
3188 : : }
3189 : :
3190 : 0 : static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
3191 : : struct intel_shared_dpll *pll,
3192 : : struct intel_dpll_hw_state *hw_state)
3193 : : {
3194 : 0 : const enum intel_dpll_id id = pll->info->id;
3195 : 0 : enum tc_port tc_port = icl_pll_id_to_tc_port(id);
3196 : 0 : intel_wakeref_t wakeref;
3197 : 0 : bool ret = false;
3198 : 0 : u32 val;
3199 : :
3200 : 0 : wakeref = intel_display_power_get_if_enabled(dev_priv,
3201 : : POWER_DOMAIN_DISPLAY_CORE);
3202 [ # # ]: 0 : if (!wakeref)
3203 : : return false;
3204 : :
3205 : 0 : val = I915_READ(MG_PLL_ENABLE(tc_port));
3206 [ # # ]: 0 : if (!(val & PLL_ENABLE))
3207 : 0 : goto out;
3208 : :
3209 : : /*
3210 : : * All registers read here have the same HIP_INDEX_REG even though
3211 : : * they are on different building blocks
3212 : : */
3213 [ # # ]: 0 : I915_WRITE(HIP_INDEX_REG(tc_port), HIP_INDEX_VAL(tc_port, 0x2));
3214 : :
3215 : 0 : hw_state->mg_refclkin_ctl = I915_READ(DKL_REFCLKIN_CTL(tc_port));
3216 : 0 : hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK;
3217 : :
3218 : 0 : hw_state->mg_clktop2_hsclkctl =
3219 : 0 : I915_READ(DKL_CLKTOP2_HSCLKCTL(tc_port));
3220 : 0 : hw_state->mg_clktop2_hsclkctl &=
3221 : : MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
3222 : : MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
3223 : : MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK |
3224 : : MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK;
3225 : :
3226 : 0 : hw_state->mg_clktop2_coreclkctl1 =
3227 : 0 : I915_READ(DKL_CLKTOP2_CORECLKCTL1(tc_port));
3228 : 0 : hw_state->mg_clktop2_coreclkctl1 &=
3229 : : MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
3230 : :
3231 : 0 : hw_state->mg_pll_div0 = I915_READ(DKL_PLL_DIV0(tc_port));
3232 : 0 : hw_state->mg_pll_div0 &= (DKL_PLL_DIV0_INTEG_COEFF_MASK |
3233 : : DKL_PLL_DIV0_PROP_COEFF_MASK |
3234 : : DKL_PLL_DIV0_FBPREDIV_MASK |
3235 : : DKL_PLL_DIV0_FBDIV_INT_MASK);
3236 : :
3237 : 0 : hw_state->mg_pll_div1 = I915_READ(DKL_PLL_DIV1(tc_port));
3238 : 0 : hw_state->mg_pll_div1 &= (DKL_PLL_DIV1_IREF_TRIM_MASK |
3239 : : DKL_PLL_DIV1_TDC_TARGET_CNT_MASK);
3240 : :
3241 : 0 : hw_state->mg_pll_ssc = I915_READ(DKL_PLL_SSC(tc_port));
3242 : 0 : hw_state->mg_pll_ssc &= (DKL_PLL_SSC_IREF_NDIV_RATIO_MASK |
3243 : : DKL_PLL_SSC_STEP_LEN_MASK |
3244 : : DKL_PLL_SSC_STEP_NUM_MASK |
3245 : : DKL_PLL_SSC_EN);
3246 : :
3247 : 0 : hw_state->mg_pll_bias = I915_READ(DKL_PLL_BIAS(tc_port));
3248 : 0 : hw_state->mg_pll_bias &= (DKL_PLL_BIAS_FRAC_EN_H |
3249 : : DKL_PLL_BIAS_FBDIV_FRAC_MASK);
3250 : :
3251 : 0 : hw_state->mg_pll_tdc_coldst_bias =
3252 : 0 : I915_READ(DKL_PLL_TDC_COLDST_BIAS(tc_port));
3253 : 0 : hw_state->mg_pll_tdc_coldst_bias &= (DKL_PLL_TDC_SSC_STEP_SIZE_MASK |
3254 : : DKL_PLL_TDC_FEED_FWD_GAIN_MASK);
3255 : :
3256 : 0 : ret = true;
3257 : 0 : out:
3258 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
3259 : 0 : return ret;
3260 : : }
3261 : :
3262 : : static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
3263 : : struct intel_shared_dpll *pll,
3264 : : struct intel_dpll_hw_state *hw_state,
3265 : : i915_reg_t enable_reg)
3266 : : {
3267 : : const enum intel_dpll_id id = pll->info->id;
3268 : : intel_wakeref_t wakeref;
3269 : : bool ret = false;
3270 : : u32 val;
3271 : :
3272 : : wakeref = intel_display_power_get_if_enabled(dev_priv,
3273 : : POWER_DOMAIN_DISPLAY_CORE);
3274 : : if (!wakeref)
3275 : : return false;
3276 : :
3277 : : val = I915_READ(enable_reg);
3278 : : if (!(val & PLL_ENABLE))
3279 : : goto out;
3280 : :
3281 : : if (INTEL_GEN(dev_priv) >= 12) {
3282 : : hw_state->cfgcr0 = I915_READ(TGL_DPLL_CFGCR0(id));
3283 : : hw_state->cfgcr1 = I915_READ(TGL_DPLL_CFGCR1(id));
3284 : : } else {
3285 : : if (IS_ELKHARTLAKE(dev_priv) && id == DPLL_ID_EHL_DPLL4) {
3286 : : hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(4));
3287 : : hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(4));
3288 : : } else {
3289 : : hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id));
3290 : : hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id));
3291 : : }
3292 : : }
3293 : :
3294 : : ret = true;
3295 : : out:
3296 : : intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
3297 : : return ret;
3298 : : }
3299 : :
3300 : 0 : static bool combo_pll_get_hw_state(struct drm_i915_private *dev_priv,
3301 : : struct intel_shared_dpll *pll,
3302 : : struct intel_dpll_hw_state *hw_state)
3303 : : {
3304 : 0 : i915_reg_t enable_reg = CNL_DPLL_ENABLE(pll->info->id);
3305 : :
3306 [ # # # # ]: 0 : if (IS_ELKHARTLAKE(dev_priv) &&
3307 : : pll->info->id == DPLL_ID_EHL_DPLL4) {
3308 : 0 : enable_reg = MG_PLL_ENABLE(0);
3309 : : }
3310 : :
3311 : 0 : return icl_pll_get_hw_state(dev_priv, pll, hw_state, enable_reg);
3312 : : }
3313 : :
3314 : 0 : static bool tbt_pll_get_hw_state(struct drm_i915_private *dev_priv,
3315 : : struct intel_shared_dpll *pll,
3316 : : struct intel_dpll_hw_state *hw_state)
3317 : : {
3318 : 0 : return icl_pll_get_hw_state(dev_priv, pll, hw_state, TBT_PLL_ENABLE);
3319 : : }
3320 : :
3321 : 0 : static void icl_dpll_write(struct drm_i915_private *dev_priv,
3322 : : struct intel_shared_dpll *pll)
3323 : : {
3324 : 0 : struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
3325 : 0 : const enum intel_dpll_id id = pll->info->id;
3326 : 0 : i915_reg_t cfgcr0_reg, cfgcr1_reg;
3327 : :
3328 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 12) {
3329 : 0 : cfgcr0_reg = TGL_DPLL_CFGCR0(id);
3330 : 0 : cfgcr1_reg = TGL_DPLL_CFGCR1(id);
3331 : : } else {
3332 [ # # # # ]: 0 : if (IS_ELKHARTLAKE(dev_priv) && id == DPLL_ID_EHL_DPLL4) {
3333 : : cfgcr0_reg = ICL_DPLL_CFGCR0(4);
3334 : : cfgcr1_reg = ICL_DPLL_CFGCR1(4);
3335 : : } else {
3336 : 0 : cfgcr0_reg = ICL_DPLL_CFGCR0(id);
3337 : 0 : cfgcr1_reg = ICL_DPLL_CFGCR1(id);
3338 : : }
3339 : : }
3340 : :
3341 : 0 : I915_WRITE(cfgcr0_reg, hw_state->cfgcr0);
3342 : 0 : I915_WRITE(cfgcr1_reg, hw_state->cfgcr1);
3343 : 0 : POSTING_READ(cfgcr1_reg);
3344 : 0 : }
3345 : :
3346 : 0 : static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
3347 : : struct intel_shared_dpll *pll)
3348 : : {
3349 : 0 : struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
3350 : 0 : enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id);
3351 : 0 : u32 val;
3352 : :
3353 : : /*
3354 : : * Some of the following registers have reserved fields, so program
3355 : : * these with RMW based on a mask. The mask can be fixed or generated
3356 : : * during the calc/readout phase if the mask depends on some other HW
3357 : : * state like refclk, see icl_calc_mg_pll_state().
3358 : : */
3359 : 0 : val = I915_READ(MG_REFCLKIN_CTL(tc_port));
3360 : 0 : val &= ~MG_REFCLKIN_CTL_OD_2_MUX_MASK;
3361 : 0 : val |= hw_state->mg_refclkin_ctl;
3362 : 0 : I915_WRITE(MG_REFCLKIN_CTL(tc_port), val);
3363 : :
3364 : 0 : val = I915_READ(MG_CLKTOP2_CORECLKCTL1(tc_port));
3365 : 0 : val &= ~MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
3366 : 0 : val |= hw_state->mg_clktop2_coreclkctl1;
3367 : 0 : I915_WRITE(MG_CLKTOP2_CORECLKCTL1(tc_port), val);
3368 : :
3369 : 0 : val = I915_READ(MG_CLKTOP2_HSCLKCTL(tc_port));
3370 : 0 : val &= ~(MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
3371 : : MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
3372 : : MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK |
3373 : : MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK);
3374 : 0 : val |= hw_state->mg_clktop2_hsclkctl;
3375 : 0 : I915_WRITE(MG_CLKTOP2_HSCLKCTL(tc_port), val);
3376 : :
3377 : 0 : I915_WRITE(MG_PLL_DIV0(tc_port), hw_state->mg_pll_div0);
3378 : 0 : I915_WRITE(MG_PLL_DIV1(tc_port), hw_state->mg_pll_div1);
3379 : 0 : I915_WRITE(MG_PLL_LF(tc_port), hw_state->mg_pll_lf);
3380 : 0 : I915_WRITE(MG_PLL_FRAC_LOCK(tc_port), hw_state->mg_pll_frac_lock);
3381 : 0 : I915_WRITE(MG_PLL_SSC(tc_port), hw_state->mg_pll_ssc);
3382 : :
3383 : 0 : val = I915_READ(MG_PLL_BIAS(tc_port));
3384 : 0 : val &= ~hw_state->mg_pll_bias_mask;
3385 : 0 : val |= hw_state->mg_pll_bias;
3386 : 0 : I915_WRITE(MG_PLL_BIAS(tc_port), val);
3387 : :
3388 : 0 : val = I915_READ(MG_PLL_TDC_COLDST_BIAS(tc_port));
3389 : 0 : val &= ~hw_state->mg_pll_tdc_coldst_bias_mask;
3390 : 0 : val |= hw_state->mg_pll_tdc_coldst_bias;
3391 : 0 : I915_WRITE(MG_PLL_TDC_COLDST_BIAS(tc_port), val);
3392 : :
3393 : 0 : POSTING_READ(MG_PLL_TDC_COLDST_BIAS(tc_port));
3394 : 0 : }
3395 : :
3396 : 0 : static void dkl_pll_write(struct drm_i915_private *dev_priv,
3397 : : struct intel_shared_dpll *pll)
3398 : : {
3399 : 0 : struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
3400 : 0 : enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id);
3401 : 0 : u32 val;
3402 : :
3403 : : /*
3404 : : * All registers programmed here have the same HIP_INDEX_REG even
3405 : : * though on different building block
3406 : : */
3407 [ # # ]: 0 : I915_WRITE(HIP_INDEX_REG(tc_port), HIP_INDEX_VAL(tc_port, 0x2));
3408 : :
3409 : : /* All the registers are RMW */
3410 : 0 : val = I915_READ(DKL_REFCLKIN_CTL(tc_port));
3411 : 0 : val &= ~MG_REFCLKIN_CTL_OD_2_MUX_MASK;
3412 : 0 : val |= hw_state->mg_refclkin_ctl;
3413 : 0 : I915_WRITE(DKL_REFCLKIN_CTL(tc_port), val);
3414 : :
3415 : 0 : val = I915_READ(DKL_CLKTOP2_CORECLKCTL1(tc_port));
3416 : 0 : val &= ~MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
3417 : 0 : val |= hw_state->mg_clktop2_coreclkctl1;
3418 : 0 : I915_WRITE(DKL_CLKTOP2_CORECLKCTL1(tc_port), val);
3419 : :
3420 : 0 : val = I915_READ(DKL_CLKTOP2_HSCLKCTL(tc_port));
3421 : 0 : val &= ~(MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
3422 : : MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
3423 : : MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK |
3424 : : MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK);
3425 : 0 : val |= hw_state->mg_clktop2_hsclkctl;
3426 : 0 : I915_WRITE(DKL_CLKTOP2_HSCLKCTL(tc_port), val);
3427 : :
3428 : 0 : val = I915_READ(DKL_PLL_DIV0(tc_port));
3429 : 0 : val &= ~(DKL_PLL_DIV0_INTEG_COEFF_MASK |
3430 : : DKL_PLL_DIV0_PROP_COEFF_MASK |
3431 : : DKL_PLL_DIV0_FBPREDIV_MASK |
3432 : : DKL_PLL_DIV0_FBDIV_INT_MASK);
3433 : 0 : val |= hw_state->mg_pll_div0;
3434 : 0 : I915_WRITE(DKL_PLL_DIV0(tc_port), val);
3435 : :
3436 : 0 : val = I915_READ(DKL_PLL_DIV1(tc_port));
3437 : 0 : val &= ~(DKL_PLL_DIV1_IREF_TRIM_MASK |
3438 : : DKL_PLL_DIV1_TDC_TARGET_CNT_MASK);
3439 : 0 : val |= hw_state->mg_pll_div1;
3440 : 0 : I915_WRITE(DKL_PLL_DIV1(tc_port), val);
3441 : :
3442 : 0 : val = I915_READ(DKL_PLL_SSC(tc_port));
3443 : 0 : val &= ~(DKL_PLL_SSC_IREF_NDIV_RATIO_MASK |
3444 : : DKL_PLL_SSC_STEP_LEN_MASK |
3445 : : DKL_PLL_SSC_STEP_NUM_MASK |
3446 : : DKL_PLL_SSC_EN);
3447 : 0 : val |= hw_state->mg_pll_ssc;
3448 : 0 : I915_WRITE(DKL_PLL_SSC(tc_port), val);
3449 : :
3450 : 0 : val = I915_READ(DKL_PLL_BIAS(tc_port));
3451 : 0 : val &= ~(DKL_PLL_BIAS_FRAC_EN_H |
3452 : : DKL_PLL_BIAS_FBDIV_FRAC_MASK);
3453 : 0 : val |= hw_state->mg_pll_bias;
3454 : 0 : I915_WRITE(DKL_PLL_BIAS(tc_port), val);
3455 : :
3456 : 0 : val = I915_READ(DKL_PLL_TDC_COLDST_BIAS(tc_port));
3457 : 0 : val &= ~(DKL_PLL_TDC_SSC_STEP_SIZE_MASK |
3458 : : DKL_PLL_TDC_FEED_FWD_GAIN_MASK);
3459 : 0 : val |= hw_state->mg_pll_tdc_coldst_bias;
3460 : 0 : I915_WRITE(DKL_PLL_TDC_COLDST_BIAS(tc_port), val);
3461 : :
3462 : 0 : POSTING_READ(DKL_PLL_TDC_COLDST_BIAS(tc_port));
3463 : 0 : }
3464 : :
3465 : : static void icl_pll_power_enable(struct drm_i915_private *dev_priv,
3466 : : struct intel_shared_dpll *pll,
3467 : : i915_reg_t enable_reg)
3468 : : {
3469 : : u32 val;
3470 : :
3471 : : val = I915_READ(enable_reg);
3472 : : val |= PLL_POWER_ENABLE;
3473 : : I915_WRITE(enable_reg, val);
3474 : :
3475 : : /*
3476 : : * The spec says we need to "wait" but it also says it should be
3477 : : * immediate.
3478 : : */
3479 : : if (intel_de_wait_for_set(dev_priv, enable_reg, PLL_POWER_STATE, 1))
3480 : : DRM_ERROR("PLL %d Power not enabled\n", pll->info->id);
3481 : : }
3482 : :
3483 : : static void icl_pll_enable(struct drm_i915_private *dev_priv,
3484 : : struct intel_shared_dpll *pll,
3485 : : i915_reg_t enable_reg)
3486 : : {
3487 : : u32 val;
3488 : :
3489 : : val = I915_READ(enable_reg);
3490 : : val |= PLL_ENABLE;
3491 : : I915_WRITE(enable_reg, val);
3492 : :
3493 : : /* Timeout is actually 600us. */
3494 : : if (intel_de_wait_for_set(dev_priv, enable_reg, PLL_LOCK, 1))
3495 : : DRM_ERROR("PLL %d not locked\n", pll->info->id);
3496 : : }
3497 : :
3498 : 0 : static void combo_pll_enable(struct drm_i915_private *dev_priv,
3499 : : struct intel_shared_dpll *pll)
3500 : : {
3501 : 0 : i915_reg_t enable_reg = CNL_DPLL_ENABLE(pll->info->id);
3502 : :
3503 [ # # # # ]: 0 : if (IS_ELKHARTLAKE(dev_priv) &&
3504 : : pll->info->id == DPLL_ID_EHL_DPLL4) {
3505 : 0 : enable_reg = MG_PLL_ENABLE(0);
3506 : :
3507 : : /*
3508 : : * We need to disable DC states when this DPLL is enabled.
3509 : : * This can be done by taking a reference on DPLL4 power
3510 : : * domain.
3511 : : */
3512 : 0 : pll->wakeref = intel_display_power_get(dev_priv,
3513 : : POWER_DOMAIN_DPLL_DC_OFF);
3514 : : }
3515 : :
3516 : 0 : icl_pll_power_enable(dev_priv, pll, enable_reg);
3517 : :
3518 : 0 : icl_dpll_write(dev_priv, pll);
3519 : :
3520 : : /*
3521 : : * DVFS pre sequence would be here, but in our driver the cdclk code
3522 : : * paths should already be setting the appropriate voltage, hence we do
3523 : : * nothing here.
3524 : : */
3525 : :
3526 : 0 : icl_pll_enable(dev_priv, pll, enable_reg);
3527 : :
3528 : : /* DVFS post sequence would be here. See the comment above. */
3529 : 0 : }
3530 : :
3531 : 0 : static void tbt_pll_enable(struct drm_i915_private *dev_priv,
3532 : : struct intel_shared_dpll *pll)
3533 : : {
3534 : 0 : icl_pll_power_enable(dev_priv, pll, TBT_PLL_ENABLE);
3535 : :
3536 : 0 : icl_dpll_write(dev_priv, pll);
3537 : :
3538 : : /*
3539 : : * DVFS pre sequence would be here, but in our driver the cdclk code
3540 : : * paths should already be setting the appropriate voltage, hence we do
3541 : : * nothing here.
3542 : : */
3543 : :
3544 : 0 : icl_pll_enable(dev_priv, pll, TBT_PLL_ENABLE);
3545 : :
3546 : : /* DVFS post sequence would be here. See the comment above. */
3547 : 0 : }
3548 : :
3549 : 0 : static void mg_pll_enable(struct drm_i915_private *dev_priv,
3550 : : struct intel_shared_dpll *pll)
3551 : : {
3552 : 0 : i915_reg_t enable_reg =
3553 : 0 : MG_PLL_ENABLE(icl_pll_id_to_tc_port(pll->info->id));
3554 : :
3555 : 0 : icl_pll_power_enable(dev_priv, pll, enable_reg);
3556 : :
3557 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 12)
3558 : 0 : dkl_pll_write(dev_priv, pll);
3559 : : else
3560 : 0 : icl_mg_pll_write(dev_priv, pll);
3561 : :
3562 : : /*
3563 : : * DVFS pre sequence would be here, but in our driver the cdclk code
3564 : : * paths should already be setting the appropriate voltage, hence we do
3565 : : * nothing here.
3566 : : */
3567 : :
3568 : 0 : icl_pll_enable(dev_priv, pll, enable_reg);
3569 : :
3570 : : /* DVFS post sequence would be here. See the comment above. */
3571 : 0 : }
3572 : :
3573 : : static void icl_pll_disable(struct drm_i915_private *dev_priv,
3574 : : struct intel_shared_dpll *pll,
3575 : : i915_reg_t enable_reg)
3576 : : {
3577 : : u32 val;
3578 : :
3579 : : /* The first steps are done by intel_ddi_post_disable(). */
3580 : :
3581 : : /*
3582 : : * DVFS pre sequence would be here, but in our driver the cdclk code
3583 : : * paths should already be setting the appropriate voltage, hence we do
3584 : : * nothign here.
3585 : : */
3586 : :
3587 : : val = I915_READ(enable_reg);
3588 : : val &= ~PLL_ENABLE;
3589 : : I915_WRITE(enable_reg, val);
3590 : :
3591 : : /* Timeout is actually 1us. */
3592 : : if (intel_de_wait_for_clear(dev_priv, enable_reg, PLL_LOCK, 1))
3593 : : DRM_ERROR("PLL %d locked\n", pll->info->id);
3594 : :
3595 : : /* DVFS post sequence would be here. See the comment above. */
3596 : :
3597 : : val = I915_READ(enable_reg);
3598 : : val &= ~PLL_POWER_ENABLE;
3599 : : I915_WRITE(enable_reg, val);
3600 : :
3601 : : /*
3602 : : * The spec says we need to "wait" but it also says it should be
3603 : : * immediate.
3604 : : */
3605 : : if (intel_de_wait_for_clear(dev_priv, enable_reg, PLL_POWER_STATE, 1))
3606 : : DRM_ERROR("PLL %d Power not disabled\n", pll->info->id);
3607 : : }
3608 : :
3609 : 0 : static void combo_pll_disable(struct drm_i915_private *dev_priv,
3610 : : struct intel_shared_dpll *pll)
3611 : : {
3612 : 0 : i915_reg_t enable_reg = CNL_DPLL_ENABLE(pll->info->id);
3613 : :
3614 [ # # # # ]: 0 : if (IS_ELKHARTLAKE(dev_priv) &&
3615 : : pll->info->id == DPLL_ID_EHL_DPLL4) {
3616 : 0 : enable_reg = MG_PLL_ENABLE(0);
3617 : 0 : icl_pll_disable(dev_priv, pll, enable_reg);
3618 : :
3619 : 0 : intel_display_power_put(dev_priv, POWER_DOMAIN_DPLL_DC_OFF,
3620 : : pll->wakeref);
3621 : 0 : return;
3622 : : }
3623 : :
3624 : 0 : icl_pll_disable(dev_priv, pll, enable_reg);
3625 : : }
3626 : :
3627 : 0 : static void tbt_pll_disable(struct drm_i915_private *dev_priv,
3628 : : struct intel_shared_dpll *pll)
3629 : : {
3630 : 0 : icl_pll_disable(dev_priv, pll, TBT_PLL_ENABLE);
3631 : 0 : }
3632 : :
3633 : 0 : static void mg_pll_disable(struct drm_i915_private *dev_priv,
3634 : : struct intel_shared_dpll *pll)
3635 : : {
3636 : 0 : i915_reg_t enable_reg =
3637 : 0 : MG_PLL_ENABLE(icl_pll_id_to_tc_port(pll->info->id));
3638 : :
3639 : 0 : icl_pll_disable(dev_priv, pll, enable_reg);
3640 : 0 : }
3641 : :
3642 : 0 : static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
3643 : : const struct intel_dpll_hw_state *hw_state)
3644 : : {
3645 : 0 : DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, "
3646 : : "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
3647 : : "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
3648 : : "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
3649 : : "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
3650 : : "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n",
3651 : : hw_state->cfgcr0, hw_state->cfgcr1,
3652 : : hw_state->mg_refclkin_ctl,
3653 : : hw_state->mg_clktop2_coreclkctl1,
3654 : : hw_state->mg_clktop2_hsclkctl,
3655 : : hw_state->mg_pll_div0,
3656 : : hw_state->mg_pll_div1,
3657 : : hw_state->mg_pll_lf,
3658 : : hw_state->mg_pll_frac_lock,
3659 : : hw_state->mg_pll_ssc,
3660 : : hw_state->mg_pll_bias,
3661 : : hw_state->mg_pll_tdc_coldst_bias);
3662 : 0 : }
3663 : :
3664 : : static const struct intel_shared_dpll_funcs combo_pll_funcs = {
3665 : : .enable = combo_pll_enable,
3666 : : .disable = combo_pll_disable,
3667 : : .get_hw_state = combo_pll_get_hw_state,
3668 : : };
3669 : :
3670 : : static const struct intel_shared_dpll_funcs tbt_pll_funcs = {
3671 : : .enable = tbt_pll_enable,
3672 : : .disable = tbt_pll_disable,
3673 : : .get_hw_state = tbt_pll_get_hw_state,
3674 : : };
3675 : :
3676 : : static const struct intel_shared_dpll_funcs mg_pll_funcs = {
3677 : : .enable = mg_pll_enable,
3678 : : .disable = mg_pll_disable,
3679 : : .get_hw_state = mg_pll_get_hw_state,
3680 : : };
3681 : :
3682 : : static const struct dpll_info icl_plls[] = {
3683 : : { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 },
3684 : : { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 },
3685 : : { "TBT PLL", &tbt_pll_funcs, DPLL_ID_ICL_TBTPLL, 0 },
3686 : : { "MG PLL 1", &mg_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
3687 : : { "MG PLL 2", &mg_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
3688 : : { "MG PLL 3", &mg_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
3689 : : { "MG PLL 4", &mg_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
3690 : : { },
3691 : : };
3692 : :
3693 : : static const struct intel_dpll_mgr icl_pll_mgr = {
3694 : : .dpll_info = icl_plls,
3695 : : .get_dplls = icl_get_dplls,
3696 : : .put_dplls = icl_put_dplls,
3697 : : .update_active_dpll = icl_update_active_dpll,
3698 : : .dump_hw_state = icl_dump_hw_state,
3699 : : };
3700 : :
3701 : : static const struct dpll_info ehl_plls[] = {
3702 : : { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 },
3703 : : { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 },
3704 : : { "DPLL 4", &combo_pll_funcs, DPLL_ID_EHL_DPLL4, 0 },
3705 : : { },
3706 : : };
3707 : :
3708 : : static const struct intel_dpll_mgr ehl_pll_mgr = {
3709 : : .dpll_info = ehl_plls,
3710 : : .get_dplls = icl_get_dplls,
3711 : : .put_dplls = icl_put_dplls,
3712 : : .dump_hw_state = icl_dump_hw_state,
3713 : : };
3714 : :
3715 : : static const struct intel_shared_dpll_funcs dkl_pll_funcs = {
3716 : : .enable = mg_pll_enable,
3717 : : .disable = mg_pll_disable,
3718 : : .get_hw_state = dkl_pll_get_hw_state,
3719 : : };
3720 : :
3721 : : static const struct dpll_info tgl_plls[] = {
3722 : : { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 },
3723 : : { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 },
3724 : : { "TBT PLL", &tbt_pll_funcs, DPLL_ID_ICL_TBTPLL, 0 },
3725 : : { "TC PLL 1", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
3726 : : { "TC PLL 2", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
3727 : : { "TC PLL 3", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
3728 : : { "TC PLL 4", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
3729 : : { "TC PLL 5", &dkl_pll_funcs, DPLL_ID_TGL_MGPLL5, 0 },
3730 : : { "TC PLL 6", &dkl_pll_funcs, DPLL_ID_TGL_MGPLL6, 0 },
3731 : : { },
3732 : : };
3733 : :
3734 : : static const struct intel_dpll_mgr tgl_pll_mgr = {
3735 : : .dpll_info = tgl_plls,
3736 : : .get_dplls = icl_get_dplls,
3737 : : .put_dplls = icl_put_dplls,
3738 : : .update_active_dpll = icl_update_active_dpll,
3739 : : .dump_hw_state = icl_dump_hw_state,
3740 : : };
3741 : :
3742 : : /**
3743 : : * intel_shared_dpll_init - Initialize shared DPLLs
3744 : : * @dev: drm device
3745 : : *
3746 : : * Initialize shared DPLLs for @dev.
3747 : : */
3748 : 0 : void intel_shared_dpll_init(struct drm_device *dev)
3749 : : {
3750 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(dev);
3751 : 0 : const struct intel_dpll_mgr *dpll_mgr = NULL;
3752 : 0 : const struct dpll_info *dpll_info;
3753 : 0 : int i;
3754 : :
3755 [ # # ]: 0 : if (INTEL_GEN(dev_priv) >= 12)
3756 : : dpll_mgr = &tgl_pll_mgr;
3757 [ # # ]: 0 : else if (IS_ELKHARTLAKE(dev_priv))
3758 : : dpll_mgr = &ehl_pll_mgr;
3759 [ # # ]: 0 : else if (INTEL_GEN(dev_priv) >= 11)
3760 : : dpll_mgr = &icl_pll_mgr;
3761 [ # # ]: 0 : else if (IS_CANNONLAKE(dev_priv))
3762 : : dpll_mgr = &cnl_pll_mgr;
3763 [ # # # # ]: 0 : else if (IS_GEN9_BC(dev_priv))
3764 : : dpll_mgr = &skl_pll_mgr;
3765 [ # # # # ]: 0 : else if (IS_GEN9_LP(dev_priv))
3766 : : dpll_mgr = &bxt_pll_mgr;
3767 [ # # ]: 0 : else if (HAS_DDI(dev_priv))
3768 : : dpll_mgr = &hsw_pll_mgr;
3769 [ # # ]: 0 : else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
3770 : : dpll_mgr = &pch_pll_mgr;
3771 : :
3772 : 0 : if (!dpll_mgr) {
3773 : 0 : dev_priv->num_shared_dpll = 0;
3774 : 0 : return;
3775 : : }
3776 : :
3777 : 0 : dpll_info = dpll_mgr->dpll_info;
3778 : :
3779 [ # # ]: 0 : for (i = 0; dpll_info[i].name; i++) {
3780 [ # # ]: 0 : WARN_ON(i != dpll_info[i].id);
3781 : 0 : dev_priv->shared_dplls[i].info = &dpll_info[i];
3782 : : }
3783 : :
3784 : 0 : dev_priv->dpll_mgr = dpll_mgr;
3785 : 0 : dev_priv->num_shared_dpll = i;
3786 : 0 : mutex_init(&dev_priv->dpll_lock);
3787 : :
3788 [ # # ]: 0 : BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);
3789 : : }
3790 : :
3791 : : /**
3792 : : * intel_reserve_shared_dplls - reserve DPLLs for CRTC and encoder combination
3793 : : * @state: atomic state
3794 : : * @crtc: CRTC to reserve DPLLs for
3795 : : * @encoder: encoder
3796 : : *
3797 : : * This function reserves all required DPLLs for the given CRTC and encoder
3798 : : * combination in the current atomic commit @state and the new @crtc atomic
3799 : : * state.
3800 : : *
3801 : : * The new configuration in the atomic commit @state is made effective by
3802 : : * calling intel_shared_dpll_swap_state().
3803 : : *
3804 : : * The reserved DPLLs should be released by calling
3805 : : * intel_release_shared_dplls().
3806 : : *
3807 : : * Returns:
3808 : : * True if all required DPLLs were successfully reserved.
3809 : : */
3810 : 0 : bool intel_reserve_shared_dplls(struct intel_atomic_state *state,
3811 : : struct intel_crtc *crtc,
3812 : : struct intel_encoder *encoder)
3813 : : {
3814 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(state->base.dev);
3815 : 0 : const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
3816 : :
3817 [ # # # # ]: 0 : if (WARN_ON(!dpll_mgr))
3818 : : return false;
3819 : :
3820 : 0 : return dpll_mgr->get_dplls(state, crtc, encoder);
3821 : : }
3822 : :
3823 : : /**
3824 : : * intel_release_shared_dplls - end use of DPLLs by CRTC in atomic state
3825 : : * @state: atomic state
3826 : : * @crtc: crtc from which the DPLLs are to be released
3827 : : *
3828 : : * This function releases all DPLLs reserved by intel_reserve_shared_dplls()
3829 : : * from the current atomic commit @state and the old @crtc atomic state.
3830 : : *
3831 : : * The new configuration in the atomic commit @state is made effective by
3832 : : * calling intel_shared_dpll_swap_state().
3833 : : */
3834 : 0 : void intel_release_shared_dplls(struct intel_atomic_state *state,
3835 : : struct intel_crtc *crtc)
3836 : : {
3837 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(state->base.dev);
3838 : 0 : const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
3839 : :
3840 : : /*
3841 : : * FIXME: this function is called for every platform having a
3842 : : * compute_clock hook, even though the platform doesn't yet support
3843 : : * the shared DPLL framework and intel_reserve_shared_dplls() is not
3844 : : * called on those.
3845 : : */
3846 [ # # ]: 0 : if (!dpll_mgr)
3847 : : return;
3848 : :
3849 : 0 : dpll_mgr->put_dplls(state, crtc);
3850 : : }
3851 : :
3852 : : /**
3853 : : * intel_update_active_dpll - update the active DPLL for a CRTC/encoder
3854 : : * @state: atomic state
3855 : : * @crtc: the CRTC for which to update the active DPLL
3856 : : * @encoder: encoder determining the type of port DPLL
3857 : : *
3858 : : * Update the active DPLL for the given @crtc/@encoder in @crtc's atomic state,
3859 : : * from the port DPLLs reserved previously by intel_reserve_shared_dplls(). The
3860 : : * DPLL selected will be based on the current mode of the encoder's port.
3861 : : */
3862 : 0 : void intel_update_active_dpll(struct intel_atomic_state *state,
3863 : : struct intel_crtc *crtc,
3864 : : struct intel_encoder *encoder)
3865 : : {
3866 [ # # ]: 0 : struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
3867 : 0 : const struct intel_dpll_mgr *dpll_mgr = dev_priv->dpll_mgr;
3868 : :
3869 [ # # # # ]: 0 : if (WARN_ON(!dpll_mgr))
3870 : : return;
3871 : :
3872 : 0 : dpll_mgr->update_active_dpll(state, crtc, encoder);
3873 : : }
3874 : :
3875 : : /**
3876 : : * intel_shared_dpll_dump_hw_state - write hw_state to dmesg
3877 : : * @dev_priv: i915 drm device
3878 : : * @hw_state: hw state to be written to the log
3879 : : *
3880 : : * Write the relevant values in @hw_state to dmesg using DRM_DEBUG_KMS.
3881 : : */
3882 : 0 : void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv,
3883 : : const struct intel_dpll_hw_state *hw_state)
3884 : : {
3885 [ # # ]: 0 : if (dev_priv->dpll_mgr) {
3886 : 0 : dev_priv->dpll_mgr->dump_hw_state(dev_priv, hw_state);
3887 : : } else {
3888 : : /* fallback for platforms that don't use the shared dpll
3889 : : * infrastructure
3890 : : */
3891 : 0 : DRM_DEBUG_KMS("dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, "
3892 : : "fp0: 0x%x, fp1: 0x%x\n",
3893 : : hw_state->dpll,
3894 : : hw_state->dpll_md,
3895 : : hw_state->fp0,
3896 : : hw_state->fp1);
3897 : : }
3898 : 0 : }
|