1c349dbc7Sjsg /* 2c349dbc7Sjsg * Copyright © 2006-2016 Intel Corporation 3c349dbc7Sjsg * 4c349dbc7Sjsg * Permission is hereby granted, free of charge, to any person obtaining a 5c349dbc7Sjsg * copy of this software and associated documentation files (the "Software"), 6c349dbc7Sjsg * to deal in the Software without restriction, including without limitation 7c349dbc7Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8c349dbc7Sjsg * and/or sell copies of the Software, and to permit persons to whom the 9c349dbc7Sjsg * Software is furnished to do so, subject to the following conditions: 10c349dbc7Sjsg * 11c349dbc7Sjsg * The above copyright notice and this permission notice (including the next 12c349dbc7Sjsg * paragraph) shall be included in all copies or substantial portions of the 13c349dbc7Sjsg * Software. 14c349dbc7Sjsg * 15c349dbc7Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16c349dbc7Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17c349dbc7Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18c349dbc7Sjsg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19c349dbc7Sjsg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20c349dbc7Sjsg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21c349dbc7Sjsg * DEALINGS IN THE SOFTWARE. 22c349dbc7Sjsg */ 23c349dbc7Sjsg 24f005ef32Sjsg #include <linux/math.h> 251bb76ff1Sjsg #include <linux/string_helpers.h> 261bb76ff1Sjsg 27f005ef32Sjsg #include "i915_reg.h" 285ca02815Sjsg #include "intel_de.h" 29c349dbc7Sjsg #include "intel_display_types.h" 301bb76ff1Sjsg #include "intel_dkl_phy.h" 31f005ef32Sjsg #include "intel_dkl_phy_regs.h" 32c349dbc7Sjsg #include "intel_dpio_phy.h" 335ca02815Sjsg #include "intel_dpll.h" 34c349dbc7Sjsg #include "intel_dpll_mgr.h" 35f005ef32Sjsg #include "intel_hti.h" 36f005ef32Sjsg #include "intel_mg_phy_regs.h" 371bb76ff1Sjsg #include "intel_pch_refclk.h" 381bb76ff1Sjsg #include "intel_tc.h" 39c349dbc7Sjsg 40c349dbc7Sjsg /** 41c349dbc7Sjsg * DOC: Display PLLs 42c349dbc7Sjsg * 43c349dbc7Sjsg * Display PLLs used for driving outputs vary by platform. While some have 44c349dbc7Sjsg * per-pipe or per-encoder dedicated PLLs, others allow the use of any PLL 45c349dbc7Sjsg * from a pool. In the latter scenario, it is possible that multiple pipes 46c349dbc7Sjsg * share a PLL if their configurations match. 47c349dbc7Sjsg * 48c349dbc7Sjsg * This file provides an abstraction over display PLLs. The function 49c349dbc7Sjsg * intel_shared_dpll_init() initializes the PLLs for the given platform. The 50c349dbc7Sjsg * users of a PLL are tracked and that tracking is integrated with the atomic 51c349dbc7Sjsg * modset interface. During an atomic operation, required PLLs can be reserved 52c349dbc7Sjsg * for a given CRTC and encoder configuration by calling 53c349dbc7Sjsg * intel_reserve_shared_dplls() and previously reserved PLLs can be released 54c349dbc7Sjsg * with intel_release_shared_dplls(). 55c349dbc7Sjsg * Changes to the users are first staged in the atomic state, and then made 56c349dbc7Sjsg * effective by calling intel_shared_dpll_swap_state() during the atomic 57c349dbc7Sjsg * commit phase. 58c349dbc7Sjsg */ 59c349dbc7Sjsg 601bb76ff1Sjsg /* platform specific hooks for managing DPLLs */ 611bb76ff1Sjsg struct intel_shared_dpll_funcs { 621bb76ff1Sjsg /* 631bb76ff1Sjsg * Hook for enabling the pll, called from intel_enable_shared_dpll() if 641bb76ff1Sjsg * the pll is not already enabled. 651bb76ff1Sjsg */ 661bb76ff1Sjsg void (*enable)(struct drm_i915_private *i915, 671bb76ff1Sjsg struct intel_shared_dpll *pll); 681bb76ff1Sjsg 691bb76ff1Sjsg /* 701bb76ff1Sjsg * Hook for disabling the pll, called from intel_disable_shared_dpll() 711bb76ff1Sjsg * only when it is safe to disable the pll, i.e., there are no more 721bb76ff1Sjsg * tracked users for it. 731bb76ff1Sjsg */ 741bb76ff1Sjsg void (*disable)(struct drm_i915_private *i915, 751bb76ff1Sjsg struct intel_shared_dpll *pll); 761bb76ff1Sjsg 771bb76ff1Sjsg /* 781bb76ff1Sjsg * Hook for reading the values currently programmed to the DPLL 791bb76ff1Sjsg * registers. This is used for initial hw state readout and state 801bb76ff1Sjsg * verification after a mode set. 811bb76ff1Sjsg */ 821bb76ff1Sjsg bool (*get_hw_state)(struct drm_i915_private *i915, 831bb76ff1Sjsg struct intel_shared_dpll *pll, 841bb76ff1Sjsg struct intel_dpll_hw_state *hw_state); 851bb76ff1Sjsg 861bb76ff1Sjsg /* 871bb76ff1Sjsg * Hook for calculating the pll's output frequency based on its passed 881bb76ff1Sjsg * in state. 891bb76ff1Sjsg */ 901bb76ff1Sjsg int (*get_freq)(struct drm_i915_private *i915, 911bb76ff1Sjsg const struct intel_shared_dpll *pll, 921bb76ff1Sjsg const struct intel_dpll_hw_state *pll_state); 931bb76ff1Sjsg }; 941bb76ff1Sjsg 95c349dbc7Sjsg struct intel_dpll_mgr { 96c349dbc7Sjsg const struct dpll_info *dpll_info; 97c349dbc7Sjsg 981bb76ff1Sjsg int (*compute_dplls)(struct intel_atomic_state *state, 991bb76ff1Sjsg struct intel_crtc *crtc, 1001bb76ff1Sjsg struct intel_encoder *encoder); 1011bb76ff1Sjsg int (*get_dplls)(struct intel_atomic_state *state, 102c349dbc7Sjsg struct intel_crtc *crtc, 103c349dbc7Sjsg struct intel_encoder *encoder); 104c349dbc7Sjsg void (*put_dplls)(struct intel_atomic_state *state, 105c349dbc7Sjsg struct intel_crtc *crtc); 106c349dbc7Sjsg void (*update_active_dpll)(struct intel_atomic_state *state, 107c349dbc7Sjsg struct intel_crtc *crtc, 108c349dbc7Sjsg struct intel_encoder *encoder); 109c349dbc7Sjsg void (*update_ref_clks)(struct drm_i915_private *i915); 110c349dbc7Sjsg void (*dump_hw_state)(struct drm_i915_private *dev_priv, 111c349dbc7Sjsg const struct intel_dpll_hw_state *hw_state); 112c349dbc7Sjsg }; 113c349dbc7Sjsg 114c349dbc7Sjsg static void 115c349dbc7Sjsg intel_atomic_duplicate_dpll_state(struct drm_i915_private *dev_priv, 116c349dbc7Sjsg struct intel_shared_dpll_state *shared_dpll) 117c349dbc7Sjsg { 118c349dbc7Sjsg enum intel_dpll_id i; 119c349dbc7Sjsg 120c349dbc7Sjsg /* Copy shared dpll state */ 1211bb76ff1Sjsg for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) { 1221bb76ff1Sjsg struct intel_shared_dpll *pll = &dev_priv->display.dpll.shared_dplls[i]; 123c349dbc7Sjsg 124c349dbc7Sjsg shared_dpll[i] = pll->state; 125c349dbc7Sjsg } 126c349dbc7Sjsg } 127c349dbc7Sjsg 128c349dbc7Sjsg static struct intel_shared_dpll_state * 129c349dbc7Sjsg intel_atomic_get_shared_dpll_state(struct drm_atomic_state *s) 130c349dbc7Sjsg { 131c349dbc7Sjsg struct intel_atomic_state *state = to_intel_atomic_state(s); 132c349dbc7Sjsg 133ad8b1aafSjsg drm_WARN_ON(s->dev, !drm_modeset_is_locked(&s->dev->mode_config.connection_mutex)); 134c349dbc7Sjsg 135c349dbc7Sjsg if (!state->dpll_set) { 136c349dbc7Sjsg state->dpll_set = true; 137c349dbc7Sjsg 138c349dbc7Sjsg intel_atomic_duplicate_dpll_state(to_i915(s->dev), 139c349dbc7Sjsg state->shared_dpll); 140c349dbc7Sjsg } 141c349dbc7Sjsg 142c349dbc7Sjsg return state->shared_dpll; 143c349dbc7Sjsg } 144c349dbc7Sjsg 145c349dbc7Sjsg /** 146c349dbc7Sjsg * intel_get_shared_dpll_by_id - get a DPLL given its id 147c349dbc7Sjsg * @dev_priv: i915 device instance 148c349dbc7Sjsg * @id: pll id 149c349dbc7Sjsg * 150c349dbc7Sjsg * Returns: 151c349dbc7Sjsg * A pointer to the DPLL with @id 152c349dbc7Sjsg */ 153c349dbc7Sjsg struct intel_shared_dpll * 154c349dbc7Sjsg intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv, 155c349dbc7Sjsg enum intel_dpll_id id) 156c349dbc7Sjsg { 1571bb76ff1Sjsg return &dev_priv->display.dpll.shared_dplls[id]; 158c349dbc7Sjsg } 159c349dbc7Sjsg 160c349dbc7Sjsg /* For ILK+ */ 161c349dbc7Sjsg void assert_shared_dpll(struct drm_i915_private *dev_priv, 162c349dbc7Sjsg struct intel_shared_dpll *pll, 163c349dbc7Sjsg bool state) 164c349dbc7Sjsg { 165c349dbc7Sjsg bool cur_state; 166c349dbc7Sjsg struct intel_dpll_hw_state hw_state; 167c349dbc7Sjsg 168c349dbc7Sjsg if (drm_WARN(&dev_priv->drm, !pll, 1691bb76ff1Sjsg "asserting DPLL %s with no DPLL\n", str_on_off(state))) 170c349dbc7Sjsg return; 171c349dbc7Sjsg 1725ca02815Sjsg cur_state = intel_dpll_get_hw_state(dev_priv, pll, &hw_state); 173f005ef32Sjsg I915_STATE_WARN(dev_priv, cur_state != state, 174c349dbc7Sjsg "%s assertion failure (expected %s, current %s)\n", 1751bb76ff1Sjsg pll->info->name, str_on_off(state), 1761bb76ff1Sjsg str_on_off(cur_state)); 177c349dbc7Sjsg } 178c349dbc7Sjsg 1795ca02815Sjsg static enum tc_port icl_pll_id_to_tc_port(enum intel_dpll_id id) 1805ca02815Sjsg { 1815ca02815Sjsg return TC_PORT_1 + id - DPLL_ID_ICL_MGPLL1; 1825ca02815Sjsg } 1835ca02815Sjsg 1845ca02815Sjsg enum intel_dpll_id icl_tc_port_to_pll_id(enum tc_port tc_port) 1855ca02815Sjsg { 1865ca02815Sjsg return tc_port - TC_PORT_1 + DPLL_ID_ICL_MGPLL1; 1875ca02815Sjsg } 1885ca02815Sjsg 189ad8b1aafSjsg static i915_reg_t 190ad8b1aafSjsg intel_combo_pll_enable_reg(struct drm_i915_private *i915, 191ad8b1aafSjsg struct intel_shared_dpll *pll) 192ad8b1aafSjsg { 1935ca02815Sjsg if (IS_DG1(i915)) 1945ca02815Sjsg return DG1_DPLL_ENABLE(pll->info->id); 195f005ef32Sjsg else if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) && 196f005ef32Sjsg (pll->info->id == DPLL_ID_EHL_DPLL4)) 197ad8b1aafSjsg return MG_PLL_ENABLE(0); 198ad8b1aafSjsg 1995ca02815Sjsg return ICL_DPLL_ENABLE(pll->info->id); 200ad8b1aafSjsg } 2015ca02815Sjsg 2025ca02815Sjsg static i915_reg_t 2035ca02815Sjsg intel_tc_pll_enable_reg(struct drm_i915_private *i915, 2045ca02815Sjsg struct intel_shared_dpll *pll) 2055ca02815Sjsg { 2065ca02815Sjsg const enum intel_dpll_id id = pll->info->id; 2075ca02815Sjsg enum tc_port tc_port = icl_pll_id_to_tc_port(id); 2085ca02815Sjsg 2095ca02815Sjsg if (IS_ALDERLAKE_P(i915)) 2105ca02815Sjsg return ADLP_PORTTC_PLL_ENABLE(tc_port); 2115ca02815Sjsg 2125ca02815Sjsg return MG_PLL_ENABLE(tc_port); 2135ca02815Sjsg } 2145ca02815Sjsg 215c349dbc7Sjsg /** 216c349dbc7Sjsg * intel_enable_shared_dpll - enable a CRTC's shared DPLL 217c349dbc7Sjsg * @crtc_state: CRTC, and its state, which has a shared DPLL 218c349dbc7Sjsg * 219c349dbc7Sjsg * Enable the shared DPLL used by @crtc. 220c349dbc7Sjsg */ 221c349dbc7Sjsg void intel_enable_shared_dpll(const struct intel_crtc_state *crtc_state) 222c349dbc7Sjsg { 223c349dbc7Sjsg struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 224c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 225c349dbc7Sjsg struct intel_shared_dpll *pll = crtc_state->shared_dpll; 2265ca02815Sjsg unsigned int pipe_mask = BIT(crtc->pipe); 227c349dbc7Sjsg unsigned int old_mask; 228c349dbc7Sjsg 229c349dbc7Sjsg if (drm_WARN_ON(&dev_priv->drm, pll == NULL)) 230c349dbc7Sjsg return; 231c349dbc7Sjsg 2321bb76ff1Sjsg mutex_lock(&dev_priv->display.dpll.lock); 233c349dbc7Sjsg old_mask = pll->active_mask; 234c349dbc7Sjsg 2355ca02815Sjsg if (drm_WARN_ON(&dev_priv->drm, !(pll->state.pipe_mask & pipe_mask)) || 2365ca02815Sjsg drm_WARN_ON(&dev_priv->drm, pll->active_mask & pipe_mask)) 237c349dbc7Sjsg goto out; 238c349dbc7Sjsg 2395ca02815Sjsg pll->active_mask |= pipe_mask; 240c349dbc7Sjsg 241c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, 2425ca02815Sjsg "enable %s (active 0x%x, on? %d) for [CRTC:%d:%s]\n", 243c349dbc7Sjsg pll->info->name, pll->active_mask, pll->on, 2445ca02815Sjsg crtc->base.base.id, crtc->base.name); 245c349dbc7Sjsg 246c349dbc7Sjsg if (old_mask) { 247c349dbc7Sjsg drm_WARN_ON(&dev_priv->drm, !pll->on); 248c349dbc7Sjsg assert_shared_dpll_enabled(dev_priv, pll); 249c349dbc7Sjsg goto out; 250c349dbc7Sjsg } 251c349dbc7Sjsg drm_WARN_ON(&dev_priv->drm, pll->on); 252c349dbc7Sjsg 253c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, "enabling %s\n", pll->info->name); 254c349dbc7Sjsg pll->info->funcs->enable(dev_priv, pll); 255c349dbc7Sjsg pll->on = true; 256c349dbc7Sjsg 257c349dbc7Sjsg out: 2581bb76ff1Sjsg mutex_unlock(&dev_priv->display.dpll.lock); 259c349dbc7Sjsg } 260c349dbc7Sjsg 261c349dbc7Sjsg /** 262c349dbc7Sjsg * intel_disable_shared_dpll - disable a CRTC's shared DPLL 263c349dbc7Sjsg * @crtc_state: CRTC, and its state, which has a shared DPLL 264c349dbc7Sjsg * 265c349dbc7Sjsg * Disable the shared DPLL used by @crtc. 266c349dbc7Sjsg */ 267c349dbc7Sjsg void intel_disable_shared_dpll(const struct intel_crtc_state *crtc_state) 268c349dbc7Sjsg { 269c349dbc7Sjsg struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 270c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 271c349dbc7Sjsg struct intel_shared_dpll *pll = crtc_state->shared_dpll; 2725ca02815Sjsg unsigned int pipe_mask = BIT(crtc->pipe); 273c349dbc7Sjsg 274c349dbc7Sjsg /* PCH only available on ILK+ */ 2755ca02815Sjsg if (DISPLAY_VER(dev_priv) < 5) 276c349dbc7Sjsg return; 277c349dbc7Sjsg 278c349dbc7Sjsg if (pll == NULL) 279c349dbc7Sjsg return; 280c349dbc7Sjsg 2811bb76ff1Sjsg mutex_lock(&dev_priv->display.dpll.lock); 2825ca02815Sjsg if (drm_WARN(&dev_priv->drm, !(pll->active_mask & pipe_mask), 2835ca02815Sjsg "%s not used by [CRTC:%d:%s]\n", pll->info->name, 2845ca02815Sjsg crtc->base.base.id, crtc->base.name)) 285c349dbc7Sjsg goto out; 286c349dbc7Sjsg 287c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, 2885ca02815Sjsg "disable %s (active 0x%x, on? %d) for [CRTC:%d:%s]\n", 289c349dbc7Sjsg pll->info->name, pll->active_mask, pll->on, 2905ca02815Sjsg crtc->base.base.id, crtc->base.name); 291c349dbc7Sjsg 292c349dbc7Sjsg assert_shared_dpll_enabled(dev_priv, pll); 293c349dbc7Sjsg drm_WARN_ON(&dev_priv->drm, !pll->on); 294c349dbc7Sjsg 2955ca02815Sjsg pll->active_mask &= ~pipe_mask; 296c349dbc7Sjsg if (pll->active_mask) 297c349dbc7Sjsg goto out; 298c349dbc7Sjsg 299c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, "disabling %s\n", pll->info->name); 300c349dbc7Sjsg pll->info->funcs->disable(dev_priv, pll); 301c349dbc7Sjsg pll->on = false; 302c349dbc7Sjsg 303c349dbc7Sjsg out: 3041bb76ff1Sjsg mutex_unlock(&dev_priv->display.dpll.lock); 305c349dbc7Sjsg } 306c349dbc7Sjsg 307c349dbc7Sjsg static struct intel_shared_dpll * 308c349dbc7Sjsg intel_find_shared_dpll(struct intel_atomic_state *state, 309c349dbc7Sjsg const struct intel_crtc *crtc, 310c349dbc7Sjsg const struct intel_dpll_hw_state *pll_state, 311c349dbc7Sjsg unsigned long dpll_mask) 312c349dbc7Sjsg { 313c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 314c349dbc7Sjsg struct intel_shared_dpll *pll, *unused_pll = NULL; 315c349dbc7Sjsg struct intel_shared_dpll_state *shared_dpll; 316c349dbc7Sjsg enum intel_dpll_id i; 317c349dbc7Sjsg 318c349dbc7Sjsg shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); 319c349dbc7Sjsg 320c349dbc7Sjsg drm_WARN_ON(&dev_priv->drm, dpll_mask & ~(BIT(I915_NUM_PLLS) - 1)); 321c349dbc7Sjsg 322c349dbc7Sjsg for_each_set_bit(i, &dpll_mask, I915_NUM_PLLS) { 3231bb76ff1Sjsg pll = &dev_priv->display.dpll.shared_dplls[i]; 324c349dbc7Sjsg 325c349dbc7Sjsg /* Only want to check enabled timings first */ 3265ca02815Sjsg if (shared_dpll[i].pipe_mask == 0) { 327c349dbc7Sjsg if (!unused_pll) 328c349dbc7Sjsg unused_pll = pll; 329c349dbc7Sjsg continue; 330c349dbc7Sjsg } 331c349dbc7Sjsg 332c349dbc7Sjsg if (memcmp(pll_state, 333c349dbc7Sjsg &shared_dpll[i].hw_state, 334c349dbc7Sjsg sizeof(*pll_state)) == 0) { 335c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, 3365ca02815Sjsg "[CRTC:%d:%s] sharing existing %s (pipe mask 0x%x, active 0x%x)\n", 337c349dbc7Sjsg crtc->base.base.id, crtc->base.name, 338c349dbc7Sjsg pll->info->name, 3395ca02815Sjsg shared_dpll[i].pipe_mask, 340c349dbc7Sjsg pll->active_mask); 341c349dbc7Sjsg return pll; 342c349dbc7Sjsg } 343c349dbc7Sjsg } 344c349dbc7Sjsg 345c349dbc7Sjsg /* Ok no matching timings, maybe there's a free one? */ 346c349dbc7Sjsg if (unused_pll) { 347c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] allocated %s\n", 348c349dbc7Sjsg crtc->base.base.id, crtc->base.name, 349c349dbc7Sjsg unused_pll->info->name); 350c349dbc7Sjsg return unused_pll; 351c349dbc7Sjsg } 352c349dbc7Sjsg 353c349dbc7Sjsg return NULL; 354c349dbc7Sjsg } 355c349dbc7Sjsg 356f005ef32Sjsg /** 357f005ef32Sjsg * intel_reference_shared_dpll_crtc - Get a DPLL reference for a CRTC 358f005ef32Sjsg * @crtc: CRTC on which behalf the reference is taken 359f005ef32Sjsg * @pll: DPLL for which the reference is taken 360f005ef32Sjsg * @shared_dpll_state: the DPLL atomic state in which the reference is tracked 361f005ef32Sjsg * 362f005ef32Sjsg * Take a reference for @pll tracking the use of it by @crtc. 363f005ef32Sjsg */ 364f005ef32Sjsg static void 365f005ef32Sjsg intel_reference_shared_dpll_crtc(const struct intel_crtc *crtc, 366f005ef32Sjsg const struct intel_shared_dpll *pll, 367f005ef32Sjsg struct intel_shared_dpll_state *shared_dpll_state) 368f005ef32Sjsg { 369f005ef32Sjsg struct drm_i915_private *i915 = to_i915(crtc->base.dev); 370f005ef32Sjsg 371f005ef32Sjsg drm_WARN_ON(&i915->drm, (shared_dpll_state->pipe_mask & BIT(crtc->pipe)) != 0); 372f005ef32Sjsg 373f005ef32Sjsg shared_dpll_state->pipe_mask |= BIT(crtc->pipe); 374f005ef32Sjsg 375f005ef32Sjsg drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] reserving %s\n", 376f005ef32Sjsg crtc->base.base.id, crtc->base.name, pll->info->name); 377f005ef32Sjsg } 378f005ef32Sjsg 379c349dbc7Sjsg static void 380c349dbc7Sjsg intel_reference_shared_dpll(struct intel_atomic_state *state, 381c349dbc7Sjsg const struct intel_crtc *crtc, 382c349dbc7Sjsg const struct intel_shared_dpll *pll, 383c349dbc7Sjsg const struct intel_dpll_hw_state *pll_state) 384c349dbc7Sjsg { 385c349dbc7Sjsg struct intel_shared_dpll_state *shared_dpll; 386c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 387c349dbc7Sjsg 388c349dbc7Sjsg shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); 389c349dbc7Sjsg 3905ca02815Sjsg if (shared_dpll[id].pipe_mask == 0) 391c349dbc7Sjsg shared_dpll[id].hw_state = *pll_state; 392c349dbc7Sjsg 393f005ef32Sjsg intel_reference_shared_dpll_crtc(crtc, pll, &shared_dpll[id]); 394f005ef32Sjsg } 395c349dbc7Sjsg 396f005ef32Sjsg /** 397f005ef32Sjsg * intel_unreference_shared_dpll_crtc - Drop a DPLL reference for a CRTC 398f005ef32Sjsg * @crtc: CRTC on which behalf the reference is dropped 399f005ef32Sjsg * @pll: DPLL for which the reference is dropped 400f005ef32Sjsg * @shared_dpll_state: the DPLL atomic state in which the reference is tracked 401f005ef32Sjsg * 402f005ef32Sjsg * Drop a reference for @pll tracking the end of use of it by @crtc. 403f005ef32Sjsg */ 404f005ef32Sjsg void 405f005ef32Sjsg intel_unreference_shared_dpll_crtc(const struct intel_crtc *crtc, 406f005ef32Sjsg const struct intel_shared_dpll *pll, 407f005ef32Sjsg struct intel_shared_dpll_state *shared_dpll_state) 408f005ef32Sjsg { 409f005ef32Sjsg struct drm_i915_private *i915 = to_i915(crtc->base.dev); 410f005ef32Sjsg 411f005ef32Sjsg drm_WARN_ON(&i915->drm, (shared_dpll_state->pipe_mask & BIT(crtc->pipe)) == 0); 412f005ef32Sjsg 413f005ef32Sjsg shared_dpll_state->pipe_mask &= ~BIT(crtc->pipe); 414f005ef32Sjsg 415f005ef32Sjsg drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] releasing %s\n", 416f005ef32Sjsg crtc->base.base.id, crtc->base.name, pll->info->name); 417c349dbc7Sjsg } 418c349dbc7Sjsg 419c349dbc7Sjsg static void intel_unreference_shared_dpll(struct intel_atomic_state *state, 420c349dbc7Sjsg const struct intel_crtc *crtc, 421c349dbc7Sjsg const struct intel_shared_dpll *pll) 422c349dbc7Sjsg { 423c349dbc7Sjsg struct intel_shared_dpll_state *shared_dpll; 424f005ef32Sjsg const enum intel_dpll_id id = pll->info->id; 425c349dbc7Sjsg 426c349dbc7Sjsg shared_dpll = intel_atomic_get_shared_dpll_state(&state->base); 427f005ef32Sjsg 428f005ef32Sjsg intel_unreference_shared_dpll_crtc(crtc, pll, &shared_dpll[id]); 429c349dbc7Sjsg } 430c349dbc7Sjsg 431c349dbc7Sjsg static void intel_put_dpll(struct intel_atomic_state *state, 432c349dbc7Sjsg struct intel_crtc *crtc) 433c349dbc7Sjsg { 434c349dbc7Sjsg const struct intel_crtc_state *old_crtc_state = 435c349dbc7Sjsg intel_atomic_get_old_crtc_state(state, crtc); 436c349dbc7Sjsg struct intel_crtc_state *new_crtc_state = 437c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 438c349dbc7Sjsg 439c349dbc7Sjsg new_crtc_state->shared_dpll = NULL; 440c349dbc7Sjsg 441c349dbc7Sjsg if (!old_crtc_state->shared_dpll) 442c349dbc7Sjsg return; 443c349dbc7Sjsg 444c349dbc7Sjsg intel_unreference_shared_dpll(state, crtc, old_crtc_state->shared_dpll); 445c349dbc7Sjsg } 446c349dbc7Sjsg 447c349dbc7Sjsg /** 448c349dbc7Sjsg * intel_shared_dpll_swap_state - make atomic DPLL configuration effective 449c349dbc7Sjsg * @state: atomic state 450c349dbc7Sjsg * 451c349dbc7Sjsg * This is the dpll version of drm_atomic_helper_swap_state() since the 452c349dbc7Sjsg * helper does not handle driver-specific global state. 453c349dbc7Sjsg * 454c349dbc7Sjsg * For consistency with atomic helpers this function does a complete swap, 455c349dbc7Sjsg * i.e. it also puts the current state into @state, even though there is no 456c349dbc7Sjsg * need for that at this moment. 457c349dbc7Sjsg */ 458c349dbc7Sjsg void intel_shared_dpll_swap_state(struct intel_atomic_state *state) 459c349dbc7Sjsg { 460c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(state->base.dev); 461c349dbc7Sjsg struct intel_shared_dpll_state *shared_dpll = state->shared_dpll; 462c349dbc7Sjsg enum intel_dpll_id i; 463c349dbc7Sjsg 464c349dbc7Sjsg if (!state->dpll_set) 465c349dbc7Sjsg return; 466c349dbc7Sjsg 4671bb76ff1Sjsg for (i = 0; i < dev_priv->display.dpll.num_shared_dpll; i++) { 468c349dbc7Sjsg struct intel_shared_dpll *pll = 4691bb76ff1Sjsg &dev_priv->display.dpll.shared_dplls[i]; 470c349dbc7Sjsg 471c349dbc7Sjsg swap(pll->state, shared_dpll[i]); 472c349dbc7Sjsg } 473c349dbc7Sjsg } 474c349dbc7Sjsg 475c349dbc7Sjsg static bool ibx_pch_dpll_get_hw_state(struct drm_i915_private *dev_priv, 476c349dbc7Sjsg struct intel_shared_dpll *pll, 477c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 478c349dbc7Sjsg { 479c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 480c349dbc7Sjsg intel_wakeref_t wakeref; 481c349dbc7Sjsg u32 val; 482c349dbc7Sjsg 483c349dbc7Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, 484c349dbc7Sjsg POWER_DOMAIN_DISPLAY_CORE); 485c349dbc7Sjsg if (!wakeref) 486c349dbc7Sjsg return false; 487c349dbc7Sjsg 488c349dbc7Sjsg val = intel_de_read(dev_priv, PCH_DPLL(id)); 489c349dbc7Sjsg hw_state->dpll = val; 490c349dbc7Sjsg hw_state->fp0 = intel_de_read(dev_priv, PCH_FP0(id)); 491c349dbc7Sjsg hw_state->fp1 = intel_de_read(dev_priv, PCH_FP1(id)); 492c349dbc7Sjsg 493c349dbc7Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); 494c349dbc7Sjsg 495c349dbc7Sjsg return val & DPLL_VCO_ENABLE; 496c349dbc7Sjsg } 497c349dbc7Sjsg 498c349dbc7Sjsg static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv) 499c349dbc7Sjsg { 500c349dbc7Sjsg u32 val; 501c349dbc7Sjsg bool enabled; 502c349dbc7Sjsg 503c349dbc7Sjsg val = intel_de_read(dev_priv, PCH_DREF_CONTROL); 504c349dbc7Sjsg enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK | 505c349dbc7Sjsg DREF_SUPERSPREAD_SOURCE_MASK)); 506f005ef32Sjsg I915_STATE_WARN(dev_priv, !enabled, 507f005ef32Sjsg "PCH refclk assertion failure, should be active but is disabled\n"); 508c349dbc7Sjsg } 509c349dbc7Sjsg 510c349dbc7Sjsg static void ibx_pch_dpll_enable(struct drm_i915_private *dev_priv, 511c349dbc7Sjsg struct intel_shared_dpll *pll) 512c349dbc7Sjsg { 513c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 514c349dbc7Sjsg 515c349dbc7Sjsg /* PCH refclock must be enabled first */ 516c349dbc7Sjsg ibx_assert_pch_refclk_enabled(dev_priv); 517c349dbc7Sjsg 5181bb76ff1Sjsg intel_de_write(dev_priv, PCH_FP0(id), pll->state.hw_state.fp0); 5191bb76ff1Sjsg intel_de_write(dev_priv, PCH_FP1(id), pll->state.hw_state.fp1); 5201bb76ff1Sjsg 521c349dbc7Sjsg intel_de_write(dev_priv, PCH_DPLL(id), pll->state.hw_state.dpll); 522c349dbc7Sjsg 523c349dbc7Sjsg /* Wait for the clocks to stabilize. */ 524c349dbc7Sjsg intel_de_posting_read(dev_priv, PCH_DPLL(id)); 525c349dbc7Sjsg udelay(150); 526c349dbc7Sjsg 527c349dbc7Sjsg /* The pixel multiplier can only be updated once the 528c349dbc7Sjsg * DPLL is enabled and the clocks are stable. 529c349dbc7Sjsg * 530c349dbc7Sjsg * So write it again. 531c349dbc7Sjsg */ 532c349dbc7Sjsg intel_de_write(dev_priv, PCH_DPLL(id), pll->state.hw_state.dpll); 533c349dbc7Sjsg intel_de_posting_read(dev_priv, PCH_DPLL(id)); 534c349dbc7Sjsg udelay(200); 535c349dbc7Sjsg } 536c349dbc7Sjsg 537c349dbc7Sjsg static void ibx_pch_dpll_disable(struct drm_i915_private *dev_priv, 538c349dbc7Sjsg struct intel_shared_dpll *pll) 539c349dbc7Sjsg { 540c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 541c349dbc7Sjsg 542c349dbc7Sjsg intel_de_write(dev_priv, PCH_DPLL(id), 0); 543c349dbc7Sjsg intel_de_posting_read(dev_priv, PCH_DPLL(id)); 544c349dbc7Sjsg udelay(200); 545c349dbc7Sjsg } 546c349dbc7Sjsg 5471bb76ff1Sjsg static int ibx_compute_dpll(struct intel_atomic_state *state, 5481bb76ff1Sjsg struct intel_crtc *crtc, 5491bb76ff1Sjsg struct intel_encoder *encoder) 5501bb76ff1Sjsg { 5511bb76ff1Sjsg return 0; 5521bb76ff1Sjsg } 5531bb76ff1Sjsg 5541bb76ff1Sjsg static int ibx_get_dpll(struct intel_atomic_state *state, 555c349dbc7Sjsg struct intel_crtc *crtc, 556c349dbc7Sjsg struct intel_encoder *encoder) 557c349dbc7Sjsg { 558c349dbc7Sjsg struct intel_crtc_state *crtc_state = 559c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 560c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 561c349dbc7Sjsg struct intel_shared_dpll *pll; 562c349dbc7Sjsg enum intel_dpll_id i; 563c349dbc7Sjsg 564c349dbc7Sjsg if (HAS_PCH_IBX(dev_priv)) { 565c349dbc7Sjsg /* Ironlake PCH has a fixed PLL->PCH pipe mapping. */ 566c349dbc7Sjsg i = (enum intel_dpll_id) crtc->pipe; 5671bb76ff1Sjsg pll = &dev_priv->display.dpll.shared_dplls[i]; 568c349dbc7Sjsg 569c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, 570c349dbc7Sjsg "[CRTC:%d:%s] using pre-allocated %s\n", 571c349dbc7Sjsg crtc->base.base.id, crtc->base.name, 572c349dbc7Sjsg pll->info->name); 573c349dbc7Sjsg } else { 574c349dbc7Sjsg pll = intel_find_shared_dpll(state, crtc, 575c349dbc7Sjsg &crtc_state->dpll_hw_state, 576c349dbc7Sjsg BIT(DPLL_ID_PCH_PLL_B) | 577c349dbc7Sjsg BIT(DPLL_ID_PCH_PLL_A)); 578c349dbc7Sjsg } 579c349dbc7Sjsg 580c349dbc7Sjsg if (!pll) 5811bb76ff1Sjsg return -EINVAL; 582c349dbc7Sjsg 583c349dbc7Sjsg /* reference the pll */ 584c349dbc7Sjsg intel_reference_shared_dpll(state, crtc, 585c349dbc7Sjsg pll, &crtc_state->dpll_hw_state); 586c349dbc7Sjsg 587c349dbc7Sjsg crtc_state->shared_dpll = pll; 588c349dbc7Sjsg 5891bb76ff1Sjsg return 0; 590c349dbc7Sjsg } 591c349dbc7Sjsg 592c349dbc7Sjsg static void ibx_dump_hw_state(struct drm_i915_private *dev_priv, 593c349dbc7Sjsg const struct intel_dpll_hw_state *hw_state) 594c349dbc7Sjsg { 595c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, 596c349dbc7Sjsg "dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, " 597c349dbc7Sjsg "fp0: 0x%x, fp1: 0x%x\n", 598c349dbc7Sjsg hw_state->dpll, 599c349dbc7Sjsg hw_state->dpll_md, 600c349dbc7Sjsg hw_state->fp0, 601c349dbc7Sjsg hw_state->fp1); 602c349dbc7Sjsg } 603c349dbc7Sjsg 604c349dbc7Sjsg static const struct intel_shared_dpll_funcs ibx_pch_dpll_funcs = { 605c349dbc7Sjsg .enable = ibx_pch_dpll_enable, 606c349dbc7Sjsg .disable = ibx_pch_dpll_disable, 607c349dbc7Sjsg .get_hw_state = ibx_pch_dpll_get_hw_state, 608c349dbc7Sjsg }; 609c349dbc7Sjsg 610c349dbc7Sjsg static const struct dpll_info pch_plls[] = { 611c349dbc7Sjsg { "PCH DPLL A", &ibx_pch_dpll_funcs, DPLL_ID_PCH_PLL_A, 0 }, 612c349dbc7Sjsg { "PCH DPLL B", &ibx_pch_dpll_funcs, DPLL_ID_PCH_PLL_B, 0 }, 613c349dbc7Sjsg { }, 614c349dbc7Sjsg }; 615c349dbc7Sjsg 616c349dbc7Sjsg static const struct intel_dpll_mgr pch_pll_mgr = { 617c349dbc7Sjsg .dpll_info = pch_plls, 6181bb76ff1Sjsg .compute_dplls = ibx_compute_dpll, 619c349dbc7Sjsg .get_dplls = ibx_get_dpll, 620c349dbc7Sjsg .put_dplls = intel_put_dpll, 621c349dbc7Sjsg .dump_hw_state = ibx_dump_hw_state, 622c349dbc7Sjsg }; 623c349dbc7Sjsg 624c349dbc7Sjsg static void hsw_ddi_wrpll_enable(struct drm_i915_private *dev_priv, 625c349dbc7Sjsg struct intel_shared_dpll *pll) 626c349dbc7Sjsg { 627c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 628c349dbc7Sjsg 629c349dbc7Sjsg intel_de_write(dev_priv, WRPLL_CTL(id), pll->state.hw_state.wrpll); 630c349dbc7Sjsg intel_de_posting_read(dev_priv, WRPLL_CTL(id)); 631c349dbc7Sjsg udelay(20); 632c349dbc7Sjsg } 633c349dbc7Sjsg 634c349dbc7Sjsg static void hsw_ddi_spll_enable(struct drm_i915_private *dev_priv, 635c349dbc7Sjsg struct intel_shared_dpll *pll) 636c349dbc7Sjsg { 637c349dbc7Sjsg intel_de_write(dev_priv, SPLL_CTL, pll->state.hw_state.spll); 638c349dbc7Sjsg intel_de_posting_read(dev_priv, SPLL_CTL); 639c349dbc7Sjsg udelay(20); 640c349dbc7Sjsg } 641c349dbc7Sjsg 642c349dbc7Sjsg static void hsw_ddi_wrpll_disable(struct drm_i915_private *dev_priv, 643c349dbc7Sjsg struct intel_shared_dpll *pll) 644c349dbc7Sjsg { 645c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 646c349dbc7Sjsg 647f005ef32Sjsg intel_de_rmw(dev_priv, WRPLL_CTL(id), WRPLL_PLL_ENABLE, 0); 648c349dbc7Sjsg intel_de_posting_read(dev_priv, WRPLL_CTL(id)); 649c349dbc7Sjsg 650c349dbc7Sjsg /* 651c349dbc7Sjsg * Try to set up the PCH reference clock once all DPLLs 652c349dbc7Sjsg * that depend on it have been shut down. 653c349dbc7Sjsg */ 654f005ef32Sjsg if (dev_priv->display.dpll.pch_ssc_use & BIT(id)) 655c349dbc7Sjsg intel_init_pch_refclk(dev_priv); 656c349dbc7Sjsg } 657c349dbc7Sjsg 658c349dbc7Sjsg static void hsw_ddi_spll_disable(struct drm_i915_private *dev_priv, 659c349dbc7Sjsg struct intel_shared_dpll *pll) 660c349dbc7Sjsg { 661c349dbc7Sjsg enum intel_dpll_id id = pll->info->id; 662c349dbc7Sjsg 663f005ef32Sjsg intel_de_rmw(dev_priv, SPLL_CTL, SPLL_PLL_ENABLE, 0); 664c349dbc7Sjsg intel_de_posting_read(dev_priv, SPLL_CTL); 665c349dbc7Sjsg 666c349dbc7Sjsg /* 667c349dbc7Sjsg * Try to set up the PCH reference clock once all DPLLs 668c349dbc7Sjsg * that depend on it have been shut down. 669c349dbc7Sjsg */ 670f005ef32Sjsg if (dev_priv->display.dpll.pch_ssc_use & BIT(id)) 671c349dbc7Sjsg intel_init_pch_refclk(dev_priv); 672c349dbc7Sjsg } 673c349dbc7Sjsg 674c349dbc7Sjsg static bool hsw_ddi_wrpll_get_hw_state(struct drm_i915_private *dev_priv, 675c349dbc7Sjsg struct intel_shared_dpll *pll, 676c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 677c349dbc7Sjsg { 678c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 679c349dbc7Sjsg intel_wakeref_t wakeref; 680c349dbc7Sjsg u32 val; 681c349dbc7Sjsg 682c349dbc7Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, 683c349dbc7Sjsg POWER_DOMAIN_DISPLAY_CORE); 684c349dbc7Sjsg if (!wakeref) 685c349dbc7Sjsg return false; 686c349dbc7Sjsg 687c349dbc7Sjsg val = intel_de_read(dev_priv, WRPLL_CTL(id)); 688c349dbc7Sjsg hw_state->wrpll = val; 689c349dbc7Sjsg 690c349dbc7Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); 691c349dbc7Sjsg 692c349dbc7Sjsg return val & WRPLL_PLL_ENABLE; 693c349dbc7Sjsg } 694c349dbc7Sjsg 695c349dbc7Sjsg static bool hsw_ddi_spll_get_hw_state(struct drm_i915_private *dev_priv, 696c349dbc7Sjsg struct intel_shared_dpll *pll, 697c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 698c349dbc7Sjsg { 699c349dbc7Sjsg intel_wakeref_t wakeref; 700c349dbc7Sjsg u32 val; 701c349dbc7Sjsg 702c349dbc7Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, 703c349dbc7Sjsg POWER_DOMAIN_DISPLAY_CORE); 704c349dbc7Sjsg if (!wakeref) 705c349dbc7Sjsg return false; 706c349dbc7Sjsg 707c349dbc7Sjsg val = intel_de_read(dev_priv, SPLL_CTL); 708c349dbc7Sjsg hw_state->spll = val; 709c349dbc7Sjsg 710c349dbc7Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); 711c349dbc7Sjsg 712c349dbc7Sjsg return val & SPLL_PLL_ENABLE; 713c349dbc7Sjsg } 714c349dbc7Sjsg 715c349dbc7Sjsg #define LC_FREQ 2700 716c349dbc7Sjsg #define LC_FREQ_2K U64_C(LC_FREQ * 2000) 717c349dbc7Sjsg 718c349dbc7Sjsg #define P_MIN 2 719c349dbc7Sjsg #define P_MAX 64 720c349dbc7Sjsg #define P_INC 2 721c349dbc7Sjsg 722c349dbc7Sjsg /* Constraints for PLL good behavior */ 723c349dbc7Sjsg #define REF_MIN 48 724c349dbc7Sjsg #define REF_MAX 400 725c349dbc7Sjsg #define VCO_MIN 2400 726c349dbc7Sjsg #define VCO_MAX 4800 727c349dbc7Sjsg 728c349dbc7Sjsg struct hsw_wrpll_rnp { 729c349dbc7Sjsg unsigned p, n2, r2; 730c349dbc7Sjsg }; 731c349dbc7Sjsg 732c349dbc7Sjsg static unsigned hsw_wrpll_get_budget_for_freq(int clock) 733c349dbc7Sjsg { 734c349dbc7Sjsg switch (clock) { 735c349dbc7Sjsg case 25175000: 736c349dbc7Sjsg case 25200000: 737c349dbc7Sjsg case 27000000: 738c349dbc7Sjsg case 27027000: 739c349dbc7Sjsg case 37762500: 740c349dbc7Sjsg case 37800000: 741c349dbc7Sjsg case 40500000: 742c349dbc7Sjsg case 40541000: 743c349dbc7Sjsg case 54000000: 744c349dbc7Sjsg case 54054000: 745c349dbc7Sjsg case 59341000: 746c349dbc7Sjsg case 59400000: 747c349dbc7Sjsg case 72000000: 748c349dbc7Sjsg case 74176000: 749c349dbc7Sjsg case 74250000: 750c349dbc7Sjsg case 81000000: 751c349dbc7Sjsg case 81081000: 752c349dbc7Sjsg case 89012000: 753c349dbc7Sjsg case 89100000: 754c349dbc7Sjsg case 108000000: 755c349dbc7Sjsg case 108108000: 756c349dbc7Sjsg case 111264000: 757c349dbc7Sjsg case 111375000: 758c349dbc7Sjsg case 148352000: 759c349dbc7Sjsg case 148500000: 760c349dbc7Sjsg case 162000000: 761c349dbc7Sjsg case 162162000: 762c349dbc7Sjsg case 222525000: 763c349dbc7Sjsg case 222750000: 764c349dbc7Sjsg case 296703000: 765c349dbc7Sjsg case 297000000: 766f005ef32Sjsg return 0; 767c349dbc7Sjsg case 233500000: 768c349dbc7Sjsg case 245250000: 769c349dbc7Sjsg case 247750000: 770c349dbc7Sjsg case 253250000: 771c349dbc7Sjsg case 298000000: 772f005ef32Sjsg return 1500; 773c349dbc7Sjsg case 169128000: 774c349dbc7Sjsg case 169500000: 775c349dbc7Sjsg case 179500000: 776c349dbc7Sjsg case 202000000: 777f005ef32Sjsg return 2000; 778c349dbc7Sjsg case 256250000: 779c349dbc7Sjsg case 262500000: 780c349dbc7Sjsg case 270000000: 781c349dbc7Sjsg case 272500000: 782c349dbc7Sjsg case 273750000: 783c349dbc7Sjsg case 280750000: 784c349dbc7Sjsg case 281250000: 785c349dbc7Sjsg case 286000000: 786c349dbc7Sjsg case 291750000: 787f005ef32Sjsg return 4000; 788c349dbc7Sjsg case 267250000: 789c349dbc7Sjsg case 268500000: 790f005ef32Sjsg return 5000; 791c349dbc7Sjsg default: 792f005ef32Sjsg return 1000; 793c349dbc7Sjsg } 794c349dbc7Sjsg } 795c349dbc7Sjsg 796c349dbc7Sjsg static void hsw_wrpll_update_rnp(u64 freq2k, unsigned int budget, 797c349dbc7Sjsg unsigned int r2, unsigned int n2, 798c349dbc7Sjsg unsigned int p, 799c349dbc7Sjsg struct hsw_wrpll_rnp *best) 800c349dbc7Sjsg { 801c349dbc7Sjsg u64 a, b, c, d, diff, diff_best; 802c349dbc7Sjsg 803c349dbc7Sjsg /* No best (r,n,p) yet */ 804c349dbc7Sjsg if (best->p == 0) { 805c349dbc7Sjsg best->p = p; 806c349dbc7Sjsg best->n2 = n2; 807c349dbc7Sjsg best->r2 = r2; 808c349dbc7Sjsg return; 809c349dbc7Sjsg } 810c349dbc7Sjsg 811c349dbc7Sjsg /* 812c349dbc7Sjsg * Output clock is (LC_FREQ_2K / 2000) * N / (P * R), which compares to 813c349dbc7Sjsg * freq2k. 814c349dbc7Sjsg * 815c349dbc7Sjsg * delta = 1e6 * 816c349dbc7Sjsg * abs(freq2k - (LC_FREQ_2K * n2/(p * r2))) / 817c349dbc7Sjsg * freq2k; 818c349dbc7Sjsg * 819c349dbc7Sjsg * and we would like delta <= budget. 820c349dbc7Sjsg * 821c349dbc7Sjsg * If the discrepancy is above the PPM-based budget, always prefer to 822c349dbc7Sjsg * improve upon the previous solution. However, if you're within the 823c349dbc7Sjsg * budget, try to maximize Ref * VCO, that is N / (P * R^2). 824c349dbc7Sjsg */ 825c349dbc7Sjsg a = freq2k * budget * p * r2; 826c349dbc7Sjsg b = freq2k * budget * best->p * best->r2; 827c349dbc7Sjsg diff = abs_diff(freq2k * p * r2, LC_FREQ_2K * n2); 828c349dbc7Sjsg diff_best = abs_diff(freq2k * best->p * best->r2, 829c349dbc7Sjsg LC_FREQ_2K * best->n2); 830c349dbc7Sjsg c = 1000000 * diff; 831c349dbc7Sjsg d = 1000000 * diff_best; 832c349dbc7Sjsg 833c349dbc7Sjsg if (a < c && b < d) { 834c349dbc7Sjsg /* If both are above the budget, pick the closer */ 835c349dbc7Sjsg if (best->p * best->r2 * diff < p * r2 * diff_best) { 836c349dbc7Sjsg best->p = p; 837c349dbc7Sjsg best->n2 = n2; 838c349dbc7Sjsg best->r2 = r2; 839c349dbc7Sjsg } 840c349dbc7Sjsg } else if (a >= c && b < d) { 841c349dbc7Sjsg /* If A is below the threshold but B is above it? Update. */ 842c349dbc7Sjsg best->p = p; 843c349dbc7Sjsg best->n2 = n2; 844c349dbc7Sjsg best->r2 = r2; 845c349dbc7Sjsg } else if (a >= c && b >= d) { 846c349dbc7Sjsg /* Both are below the limit, so pick the higher n2/(r2*r2) */ 847c349dbc7Sjsg if (n2 * best->r2 * best->r2 > best->n2 * r2 * r2) { 848c349dbc7Sjsg best->p = p; 849c349dbc7Sjsg best->n2 = n2; 850c349dbc7Sjsg best->r2 = r2; 851c349dbc7Sjsg } 852c349dbc7Sjsg } 853c349dbc7Sjsg /* Otherwise a < c && b >= d, do nothing */ 854c349dbc7Sjsg } 855c349dbc7Sjsg 856c349dbc7Sjsg static void 857c349dbc7Sjsg hsw_ddi_calculate_wrpll(int clock /* in Hz */, 858c349dbc7Sjsg unsigned *r2_out, unsigned *n2_out, unsigned *p_out) 859c349dbc7Sjsg { 860c349dbc7Sjsg u64 freq2k; 861c349dbc7Sjsg unsigned p, n2, r2; 8621bb76ff1Sjsg struct hsw_wrpll_rnp best = {}; 863c349dbc7Sjsg unsigned budget; 864c349dbc7Sjsg 865c349dbc7Sjsg freq2k = clock / 100; 866c349dbc7Sjsg 867c349dbc7Sjsg budget = hsw_wrpll_get_budget_for_freq(clock); 868c349dbc7Sjsg 869c349dbc7Sjsg /* Special case handling for 540 pixel clock: bypass WR PLL entirely 870c349dbc7Sjsg * and directly pass the LC PLL to it. */ 871c349dbc7Sjsg if (freq2k == 5400000) { 872c349dbc7Sjsg *n2_out = 2; 873c349dbc7Sjsg *p_out = 1; 874c349dbc7Sjsg *r2_out = 2; 875c349dbc7Sjsg return; 876c349dbc7Sjsg } 877c349dbc7Sjsg 878c349dbc7Sjsg /* 879c349dbc7Sjsg * Ref = LC_FREQ / R, where Ref is the actual reference input seen by 880c349dbc7Sjsg * the WR PLL. 881c349dbc7Sjsg * 882c349dbc7Sjsg * We want R so that REF_MIN <= Ref <= REF_MAX. 883c349dbc7Sjsg * Injecting R2 = 2 * R gives: 884c349dbc7Sjsg * REF_MAX * r2 > LC_FREQ * 2 and 885c349dbc7Sjsg * REF_MIN * r2 < LC_FREQ * 2 886c349dbc7Sjsg * 887c349dbc7Sjsg * Which means the desired boundaries for r2 are: 888c349dbc7Sjsg * LC_FREQ * 2 / REF_MAX < r2 < LC_FREQ * 2 / REF_MIN 889c349dbc7Sjsg * 890c349dbc7Sjsg */ 891c349dbc7Sjsg for (r2 = LC_FREQ * 2 / REF_MAX + 1; 892c349dbc7Sjsg r2 <= LC_FREQ * 2 / REF_MIN; 893c349dbc7Sjsg r2++) { 894c349dbc7Sjsg 895c349dbc7Sjsg /* 896c349dbc7Sjsg * VCO = N * Ref, that is: VCO = N * LC_FREQ / R 897c349dbc7Sjsg * 898c349dbc7Sjsg * Once again we want VCO_MIN <= VCO <= VCO_MAX. 899c349dbc7Sjsg * Injecting R2 = 2 * R and N2 = 2 * N, we get: 900c349dbc7Sjsg * VCO_MAX * r2 > n2 * LC_FREQ and 901c349dbc7Sjsg * VCO_MIN * r2 < n2 * LC_FREQ) 902c349dbc7Sjsg * 903c349dbc7Sjsg * Which means the desired boundaries for n2 are: 904c349dbc7Sjsg * VCO_MIN * r2 / LC_FREQ < n2 < VCO_MAX * r2 / LC_FREQ 905c349dbc7Sjsg */ 906c349dbc7Sjsg for (n2 = VCO_MIN * r2 / LC_FREQ + 1; 907c349dbc7Sjsg n2 <= VCO_MAX * r2 / LC_FREQ; 908c349dbc7Sjsg n2++) { 909c349dbc7Sjsg 910c349dbc7Sjsg for (p = P_MIN; p <= P_MAX; p += P_INC) 911c349dbc7Sjsg hsw_wrpll_update_rnp(freq2k, budget, 912c349dbc7Sjsg r2, n2, p, &best); 913c349dbc7Sjsg } 914c349dbc7Sjsg } 915c349dbc7Sjsg 916c349dbc7Sjsg *n2_out = best.n2; 917c349dbc7Sjsg *p_out = best.p; 918c349dbc7Sjsg *r2_out = best.r2; 919c349dbc7Sjsg } 920c349dbc7Sjsg 921c349dbc7Sjsg static int hsw_ddi_wrpll_get_freq(struct drm_i915_private *dev_priv, 9225ca02815Sjsg const struct intel_shared_dpll *pll, 9235ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 924c349dbc7Sjsg { 925c349dbc7Sjsg int refclk; 926c349dbc7Sjsg int n, p, r; 9275ca02815Sjsg u32 wrpll = pll_state->wrpll; 928c349dbc7Sjsg 929c349dbc7Sjsg switch (wrpll & WRPLL_REF_MASK) { 930c349dbc7Sjsg case WRPLL_REF_SPECIAL_HSW: 931c349dbc7Sjsg /* Muxed-SSC for BDW, non-SSC for non-ULT HSW. */ 932f005ef32Sjsg if (IS_HASWELL(dev_priv) && !IS_HASWELL_ULT(dev_priv)) { 9331bb76ff1Sjsg refclk = dev_priv->display.dpll.ref_clks.nssc; 934c349dbc7Sjsg break; 935c349dbc7Sjsg } 936ad8b1aafSjsg fallthrough; 937c349dbc7Sjsg case WRPLL_REF_PCH_SSC: 938c349dbc7Sjsg /* 939c349dbc7Sjsg * We could calculate spread here, but our checking 940c349dbc7Sjsg * code only cares about 5% accuracy, and spread is a max of 941c349dbc7Sjsg * 0.5% downspread. 942c349dbc7Sjsg */ 9431bb76ff1Sjsg refclk = dev_priv->display.dpll.ref_clks.ssc; 944c349dbc7Sjsg break; 945c349dbc7Sjsg case WRPLL_REF_LCPLL: 946c349dbc7Sjsg refclk = 2700000; 947c349dbc7Sjsg break; 948c349dbc7Sjsg default: 949c349dbc7Sjsg MISSING_CASE(wrpll); 950c349dbc7Sjsg return 0; 951c349dbc7Sjsg } 952c349dbc7Sjsg 953c349dbc7Sjsg r = wrpll & WRPLL_DIVIDER_REF_MASK; 954c349dbc7Sjsg p = (wrpll & WRPLL_DIVIDER_POST_MASK) >> WRPLL_DIVIDER_POST_SHIFT; 955c349dbc7Sjsg n = (wrpll & WRPLL_DIVIDER_FB_MASK) >> WRPLL_DIVIDER_FB_SHIFT; 956c349dbc7Sjsg 957c349dbc7Sjsg /* Convert to KHz, p & r have a fixed point portion */ 958c349dbc7Sjsg return (refclk * n / 10) / (p * r) * 2; 959c349dbc7Sjsg } 960c349dbc7Sjsg 9611bb76ff1Sjsg static int 9621bb76ff1Sjsg hsw_ddi_wrpll_compute_dpll(struct intel_atomic_state *state, 9631bb76ff1Sjsg struct intel_crtc *crtc) 9641bb76ff1Sjsg { 9651bb76ff1Sjsg struct drm_i915_private *i915 = to_i915(state->base.dev); 9661bb76ff1Sjsg struct intel_crtc_state *crtc_state = 9671bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc); 9681bb76ff1Sjsg unsigned int p, n2, r2; 9691bb76ff1Sjsg 9701bb76ff1Sjsg hsw_ddi_calculate_wrpll(crtc_state->port_clock * 1000, &r2, &n2, &p); 9711bb76ff1Sjsg 9721bb76ff1Sjsg crtc_state->dpll_hw_state.wrpll = 9731bb76ff1Sjsg WRPLL_PLL_ENABLE | WRPLL_REF_LCPLL | 9741bb76ff1Sjsg WRPLL_DIVIDER_REFERENCE(r2) | WRPLL_DIVIDER_FEEDBACK(n2) | 9751bb76ff1Sjsg WRPLL_DIVIDER_POST(p); 9761bb76ff1Sjsg 9771bb76ff1Sjsg crtc_state->port_clock = hsw_ddi_wrpll_get_freq(i915, NULL, 9781bb76ff1Sjsg &crtc_state->dpll_hw_state); 9791bb76ff1Sjsg 9801bb76ff1Sjsg return 0; 9811bb76ff1Sjsg } 9821bb76ff1Sjsg 9831bb76ff1Sjsg static struct intel_shared_dpll * 9841bb76ff1Sjsg hsw_ddi_wrpll_get_dpll(struct intel_atomic_state *state, 9851bb76ff1Sjsg struct intel_crtc *crtc) 9861bb76ff1Sjsg { 9871bb76ff1Sjsg struct intel_crtc_state *crtc_state = 9881bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc); 9891bb76ff1Sjsg 9901bb76ff1Sjsg return intel_find_shared_dpll(state, crtc, 9911bb76ff1Sjsg &crtc_state->dpll_hw_state, 9921bb76ff1Sjsg BIT(DPLL_ID_WRPLL2) | 9931bb76ff1Sjsg BIT(DPLL_ID_WRPLL1)); 9941bb76ff1Sjsg } 9951bb76ff1Sjsg 9961bb76ff1Sjsg static int 9971bb76ff1Sjsg hsw_ddi_lcpll_compute_dpll(struct intel_crtc_state *crtc_state) 9981bb76ff1Sjsg { 9991bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); 10001bb76ff1Sjsg int clock = crtc_state->port_clock; 10011bb76ff1Sjsg 10021bb76ff1Sjsg switch (clock / 2) { 10031bb76ff1Sjsg case 81000: 10041bb76ff1Sjsg case 135000: 10051bb76ff1Sjsg case 270000: 10061bb76ff1Sjsg return 0; 10071bb76ff1Sjsg default: 10081bb76ff1Sjsg drm_dbg_kms(&dev_priv->drm, "Invalid clock for DP: %d\n", 10091bb76ff1Sjsg clock); 10101bb76ff1Sjsg return -EINVAL; 10111bb76ff1Sjsg } 10121bb76ff1Sjsg } 10131bb76ff1Sjsg 1014c349dbc7Sjsg static struct intel_shared_dpll * 1015c349dbc7Sjsg hsw_ddi_lcpll_get_dpll(struct intel_crtc_state *crtc_state) 1016c349dbc7Sjsg { 1017c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); 1018c349dbc7Sjsg struct intel_shared_dpll *pll; 1019c349dbc7Sjsg enum intel_dpll_id pll_id; 1020c349dbc7Sjsg int clock = crtc_state->port_clock; 1021c349dbc7Sjsg 1022c349dbc7Sjsg switch (clock / 2) { 1023c349dbc7Sjsg case 81000: 1024c349dbc7Sjsg pll_id = DPLL_ID_LCPLL_810; 1025c349dbc7Sjsg break; 1026c349dbc7Sjsg case 135000: 1027c349dbc7Sjsg pll_id = DPLL_ID_LCPLL_1350; 1028c349dbc7Sjsg break; 1029c349dbc7Sjsg case 270000: 1030c349dbc7Sjsg pll_id = DPLL_ID_LCPLL_2700; 1031c349dbc7Sjsg break; 1032c349dbc7Sjsg default: 10331bb76ff1Sjsg MISSING_CASE(clock / 2); 1034c349dbc7Sjsg return NULL; 1035c349dbc7Sjsg } 1036c349dbc7Sjsg 1037c349dbc7Sjsg pll = intel_get_shared_dpll_by_id(dev_priv, pll_id); 1038c349dbc7Sjsg 1039c349dbc7Sjsg if (!pll) 1040c349dbc7Sjsg return NULL; 1041c349dbc7Sjsg 1042c349dbc7Sjsg return pll; 1043c349dbc7Sjsg } 1044c349dbc7Sjsg 1045c349dbc7Sjsg static int hsw_ddi_lcpll_get_freq(struct drm_i915_private *i915, 10465ca02815Sjsg const struct intel_shared_dpll *pll, 10475ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 1048c349dbc7Sjsg { 1049c349dbc7Sjsg int link_clock = 0; 1050c349dbc7Sjsg 1051c349dbc7Sjsg switch (pll->info->id) { 1052c349dbc7Sjsg case DPLL_ID_LCPLL_810: 1053c349dbc7Sjsg link_clock = 81000; 1054c349dbc7Sjsg break; 1055c349dbc7Sjsg case DPLL_ID_LCPLL_1350: 1056c349dbc7Sjsg link_clock = 135000; 1057c349dbc7Sjsg break; 1058c349dbc7Sjsg case DPLL_ID_LCPLL_2700: 1059c349dbc7Sjsg link_clock = 270000; 1060c349dbc7Sjsg break; 1061c349dbc7Sjsg default: 1062c349dbc7Sjsg drm_WARN(&i915->drm, 1, "bad port clock sel\n"); 1063c349dbc7Sjsg break; 1064c349dbc7Sjsg } 1065c349dbc7Sjsg 1066c349dbc7Sjsg return link_clock * 2; 1067c349dbc7Sjsg } 1068c349dbc7Sjsg 10691bb76ff1Sjsg static int 10701bb76ff1Sjsg hsw_ddi_spll_compute_dpll(struct intel_atomic_state *state, 1071c349dbc7Sjsg struct intel_crtc *crtc) 1072c349dbc7Sjsg { 1073c349dbc7Sjsg struct intel_crtc_state *crtc_state = 1074c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 1075c349dbc7Sjsg 1076ad8b1aafSjsg if (drm_WARN_ON(crtc->base.dev, crtc_state->port_clock / 2 != 135000)) 10771bb76ff1Sjsg return -EINVAL; 1078c349dbc7Sjsg 10791bb76ff1Sjsg crtc_state->dpll_hw_state.spll = 10801bb76ff1Sjsg SPLL_PLL_ENABLE | SPLL_FREQ_1350MHz | SPLL_REF_MUXED_SSC; 10811bb76ff1Sjsg 10821bb76ff1Sjsg return 0; 10831bb76ff1Sjsg } 10841bb76ff1Sjsg 10851bb76ff1Sjsg static struct intel_shared_dpll * 10861bb76ff1Sjsg hsw_ddi_spll_get_dpll(struct intel_atomic_state *state, 10871bb76ff1Sjsg struct intel_crtc *crtc) 10881bb76ff1Sjsg { 10891bb76ff1Sjsg struct intel_crtc_state *crtc_state = 10901bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc); 1091c349dbc7Sjsg 1092c349dbc7Sjsg return intel_find_shared_dpll(state, crtc, &crtc_state->dpll_hw_state, 1093c349dbc7Sjsg BIT(DPLL_ID_SPLL)); 1094c349dbc7Sjsg } 1095c349dbc7Sjsg 1096c349dbc7Sjsg static int hsw_ddi_spll_get_freq(struct drm_i915_private *i915, 10975ca02815Sjsg const struct intel_shared_dpll *pll, 10985ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 1099c349dbc7Sjsg { 1100c349dbc7Sjsg int link_clock = 0; 1101c349dbc7Sjsg 11025ca02815Sjsg switch (pll_state->spll & SPLL_FREQ_MASK) { 1103c349dbc7Sjsg case SPLL_FREQ_810MHz: 1104c349dbc7Sjsg link_clock = 81000; 1105c349dbc7Sjsg break; 1106c349dbc7Sjsg case SPLL_FREQ_1350MHz: 1107c349dbc7Sjsg link_clock = 135000; 1108c349dbc7Sjsg break; 1109c349dbc7Sjsg case SPLL_FREQ_2700MHz: 1110c349dbc7Sjsg link_clock = 270000; 1111c349dbc7Sjsg break; 1112c349dbc7Sjsg default: 1113c349dbc7Sjsg drm_WARN(&i915->drm, 1, "bad spll freq\n"); 1114c349dbc7Sjsg break; 1115c349dbc7Sjsg } 1116c349dbc7Sjsg 1117c349dbc7Sjsg return link_clock * 2; 1118c349dbc7Sjsg } 1119c349dbc7Sjsg 11201bb76ff1Sjsg static int hsw_compute_dpll(struct intel_atomic_state *state, 1121c349dbc7Sjsg struct intel_crtc *crtc, 1122c349dbc7Sjsg struct intel_encoder *encoder) 1123c349dbc7Sjsg { 1124c349dbc7Sjsg struct intel_crtc_state *crtc_state = 1125c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 1126c349dbc7Sjsg 11271bb76ff1Sjsg if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) 11281bb76ff1Sjsg return hsw_ddi_wrpll_compute_dpll(state, crtc); 11291bb76ff1Sjsg else if (intel_crtc_has_dp_encoder(crtc_state)) 11301bb76ff1Sjsg return hsw_ddi_lcpll_compute_dpll(crtc_state); 11311bb76ff1Sjsg else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) 11321bb76ff1Sjsg return hsw_ddi_spll_compute_dpll(state, crtc); 11331bb76ff1Sjsg else 11341bb76ff1Sjsg return -EINVAL; 11351bb76ff1Sjsg } 11361bb76ff1Sjsg 11371bb76ff1Sjsg static int hsw_get_dpll(struct intel_atomic_state *state, 11381bb76ff1Sjsg struct intel_crtc *crtc, 11391bb76ff1Sjsg struct intel_encoder *encoder) 11401bb76ff1Sjsg { 11411bb76ff1Sjsg struct intel_crtc_state *crtc_state = 11421bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc); 11431bb76ff1Sjsg struct intel_shared_dpll *pll = NULL; 1144c349dbc7Sjsg 1145c349dbc7Sjsg if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) 1146c349dbc7Sjsg pll = hsw_ddi_wrpll_get_dpll(state, crtc); 1147c349dbc7Sjsg else if (intel_crtc_has_dp_encoder(crtc_state)) 1148c349dbc7Sjsg pll = hsw_ddi_lcpll_get_dpll(crtc_state); 1149c349dbc7Sjsg else if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) 1150c349dbc7Sjsg pll = hsw_ddi_spll_get_dpll(state, crtc); 1151c349dbc7Sjsg 1152c349dbc7Sjsg if (!pll) 11531bb76ff1Sjsg return -EINVAL; 1154c349dbc7Sjsg 1155c349dbc7Sjsg intel_reference_shared_dpll(state, crtc, 1156c349dbc7Sjsg pll, &crtc_state->dpll_hw_state); 1157c349dbc7Sjsg 1158c349dbc7Sjsg crtc_state->shared_dpll = pll; 1159c349dbc7Sjsg 11601bb76ff1Sjsg return 0; 1161c349dbc7Sjsg } 1162c349dbc7Sjsg 1163c349dbc7Sjsg static void hsw_update_dpll_ref_clks(struct drm_i915_private *i915) 1164c349dbc7Sjsg { 11651bb76ff1Sjsg i915->display.dpll.ref_clks.ssc = 135000; 1166c349dbc7Sjsg /* Non-SSC is only used on non-ULT HSW. */ 1167c349dbc7Sjsg if (intel_de_read(i915, FUSE_STRAP3) & HSW_REF_CLK_SELECT) 11681bb76ff1Sjsg i915->display.dpll.ref_clks.nssc = 24000; 1169c349dbc7Sjsg else 11701bb76ff1Sjsg i915->display.dpll.ref_clks.nssc = 135000; 1171c349dbc7Sjsg } 1172c349dbc7Sjsg 1173c349dbc7Sjsg static void hsw_dump_hw_state(struct drm_i915_private *dev_priv, 1174c349dbc7Sjsg const struct intel_dpll_hw_state *hw_state) 1175c349dbc7Sjsg { 1176c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, "dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", 1177c349dbc7Sjsg hw_state->wrpll, hw_state->spll); 1178c349dbc7Sjsg } 1179c349dbc7Sjsg 1180c349dbc7Sjsg static const struct intel_shared_dpll_funcs hsw_ddi_wrpll_funcs = { 1181c349dbc7Sjsg .enable = hsw_ddi_wrpll_enable, 1182c349dbc7Sjsg .disable = hsw_ddi_wrpll_disable, 1183c349dbc7Sjsg .get_hw_state = hsw_ddi_wrpll_get_hw_state, 1184c349dbc7Sjsg .get_freq = hsw_ddi_wrpll_get_freq, 1185c349dbc7Sjsg }; 1186c349dbc7Sjsg 1187c349dbc7Sjsg static const struct intel_shared_dpll_funcs hsw_ddi_spll_funcs = { 1188c349dbc7Sjsg .enable = hsw_ddi_spll_enable, 1189c349dbc7Sjsg .disable = hsw_ddi_spll_disable, 1190c349dbc7Sjsg .get_hw_state = hsw_ddi_spll_get_hw_state, 1191c349dbc7Sjsg .get_freq = hsw_ddi_spll_get_freq, 1192c349dbc7Sjsg }; 1193c349dbc7Sjsg 1194c349dbc7Sjsg static void hsw_ddi_lcpll_enable(struct drm_i915_private *dev_priv, 1195c349dbc7Sjsg struct intel_shared_dpll *pll) 1196c349dbc7Sjsg { 1197c349dbc7Sjsg } 1198c349dbc7Sjsg 1199c349dbc7Sjsg static void hsw_ddi_lcpll_disable(struct drm_i915_private *dev_priv, 1200c349dbc7Sjsg struct intel_shared_dpll *pll) 1201c349dbc7Sjsg { 1202c349dbc7Sjsg } 1203c349dbc7Sjsg 1204c349dbc7Sjsg static bool hsw_ddi_lcpll_get_hw_state(struct drm_i915_private *dev_priv, 1205c349dbc7Sjsg struct intel_shared_dpll *pll, 1206c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 1207c349dbc7Sjsg { 1208c349dbc7Sjsg return true; 1209c349dbc7Sjsg } 1210c349dbc7Sjsg 1211c349dbc7Sjsg static const struct intel_shared_dpll_funcs hsw_ddi_lcpll_funcs = { 1212c349dbc7Sjsg .enable = hsw_ddi_lcpll_enable, 1213c349dbc7Sjsg .disable = hsw_ddi_lcpll_disable, 1214c349dbc7Sjsg .get_hw_state = hsw_ddi_lcpll_get_hw_state, 1215c349dbc7Sjsg .get_freq = hsw_ddi_lcpll_get_freq, 1216c349dbc7Sjsg }; 1217c349dbc7Sjsg 1218c349dbc7Sjsg static const struct dpll_info hsw_plls[] = { 1219c349dbc7Sjsg { "WRPLL 1", &hsw_ddi_wrpll_funcs, DPLL_ID_WRPLL1, 0 }, 1220c349dbc7Sjsg { "WRPLL 2", &hsw_ddi_wrpll_funcs, DPLL_ID_WRPLL2, 0 }, 1221c349dbc7Sjsg { "SPLL", &hsw_ddi_spll_funcs, DPLL_ID_SPLL, 0 }, 1222c349dbc7Sjsg { "LCPLL 810", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_810, INTEL_DPLL_ALWAYS_ON }, 1223c349dbc7Sjsg { "LCPLL 1350", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_1350, INTEL_DPLL_ALWAYS_ON }, 1224c349dbc7Sjsg { "LCPLL 2700", &hsw_ddi_lcpll_funcs, DPLL_ID_LCPLL_2700, INTEL_DPLL_ALWAYS_ON }, 1225c349dbc7Sjsg { }, 1226c349dbc7Sjsg }; 1227c349dbc7Sjsg 1228c349dbc7Sjsg static const struct intel_dpll_mgr hsw_pll_mgr = { 1229c349dbc7Sjsg .dpll_info = hsw_plls, 12301bb76ff1Sjsg .compute_dplls = hsw_compute_dpll, 1231c349dbc7Sjsg .get_dplls = hsw_get_dpll, 1232c349dbc7Sjsg .put_dplls = intel_put_dpll, 1233c349dbc7Sjsg .update_ref_clks = hsw_update_dpll_ref_clks, 1234c349dbc7Sjsg .dump_hw_state = hsw_dump_hw_state, 1235c349dbc7Sjsg }; 1236c349dbc7Sjsg 1237c349dbc7Sjsg struct skl_dpll_regs { 1238c349dbc7Sjsg i915_reg_t ctl, cfgcr1, cfgcr2; 1239c349dbc7Sjsg }; 1240c349dbc7Sjsg 1241c349dbc7Sjsg /* this array is indexed by the *shared* pll id */ 1242c349dbc7Sjsg static const struct skl_dpll_regs skl_dpll_regs[4] = { 1243c349dbc7Sjsg { 1244c349dbc7Sjsg /* DPLL 0 */ 1245c349dbc7Sjsg .ctl = LCPLL1_CTL, 1246c349dbc7Sjsg /* DPLL 0 doesn't support HDMI mode */ 1247c349dbc7Sjsg }, 1248c349dbc7Sjsg { 1249c349dbc7Sjsg /* DPLL 1 */ 1250c349dbc7Sjsg .ctl = LCPLL2_CTL, 1251c349dbc7Sjsg .cfgcr1 = DPLL_CFGCR1(SKL_DPLL1), 1252c349dbc7Sjsg .cfgcr2 = DPLL_CFGCR2(SKL_DPLL1), 1253c349dbc7Sjsg }, 1254c349dbc7Sjsg { 1255c349dbc7Sjsg /* DPLL 2 */ 1256c349dbc7Sjsg .ctl = WRPLL_CTL(0), 1257c349dbc7Sjsg .cfgcr1 = DPLL_CFGCR1(SKL_DPLL2), 1258c349dbc7Sjsg .cfgcr2 = DPLL_CFGCR2(SKL_DPLL2), 1259c349dbc7Sjsg }, 1260c349dbc7Sjsg { 1261c349dbc7Sjsg /* DPLL 3 */ 1262c349dbc7Sjsg .ctl = WRPLL_CTL(1), 1263c349dbc7Sjsg .cfgcr1 = DPLL_CFGCR1(SKL_DPLL3), 1264c349dbc7Sjsg .cfgcr2 = DPLL_CFGCR2(SKL_DPLL3), 1265c349dbc7Sjsg }, 1266c349dbc7Sjsg }; 1267c349dbc7Sjsg 1268c349dbc7Sjsg static void skl_ddi_pll_write_ctrl1(struct drm_i915_private *dev_priv, 1269c349dbc7Sjsg struct intel_shared_dpll *pll) 1270c349dbc7Sjsg { 1271c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 1272c349dbc7Sjsg 1273f005ef32Sjsg intel_de_rmw(dev_priv, DPLL_CTRL1, 1274f005ef32Sjsg DPLL_CTRL1_HDMI_MODE(id) | DPLL_CTRL1_SSC(id) | DPLL_CTRL1_LINK_RATE_MASK(id), 1275f005ef32Sjsg pll->state.hw_state.ctrl1 << (id * 6)); 1276c349dbc7Sjsg intel_de_posting_read(dev_priv, DPLL_CTRL1); 1277c349dbc7Sjsg } 1278c349dbc7Sjsg 1279c349dbc7Sjsg static void skl_ddi_pll_enable(struct drm_i915_private *dev_priv, 1280c349dbc7Sjsg struct intel_shared_dpll *pll) 1281c349dbc7Sjsg { 1282c349dbc7Sjsg const struct skl_dpll_regs *regs = skl_dpll_regs; 1283c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 1284c349dbc7Sjsg 1285c349dbc7Sjsg skl_ddi_pll_write_ctrl1(dev_priv, pll); 1286c349dbc7Sjsg 1287c349dbc7Sjsg intel_de_write(dev_priv, regs[id].cfgcr1, pll->state.hw_state.cfgcr1); 1288c349dbc7Sjsg intel_de_write(dev_priv, regs[id].cfgcr2, pll->state.hw_state.cfgcr2); 1289c349dbc7Sjsg intel_de_posting_read(dev_priv, regs[id].cfgcr1); 1290c349dbc7Sjsg intel_de_posting_read(dev_priv, regs[id].cfgcr2); 1291c349dbc7Sjsg 1292c349dbc7Sjsg /* the enable bit is always bit 31 */ 1293f005ef32Sjsg intel_de_rmw(dev_priv, regs[id].ctl, 0, LCPLL_PLL_ENABLE); 1294c349dbc7Sjsg 1295c349dbc7Sjsg if (intel_de_wait_for_set(dev_priv, DPLL_STATUS, DPLL_LOCK(id), 5)) 1296c349dbc7Sjsg drm_err(&dev_priv->drm, "DPLL %d not locked\n", id); 1297c349dbc7Sjsg } 1298c349dbc7Sjsg 1299c349dbc7Sjsg static void skl_ddi_dpll0_enable(struct drm_i915_private *dev_priv, 1300c349dbc7Sjsg struct intel_shared_dpll *pll) 1301c349dbc7Sjsg { 1302c349dbc7Sjsg skl_ddi_pll_write_ctrl1(dev_priv, pll); 1303c349dbc7Sjsg } 1304c349dbc7Sjsg 1305c349dbc7Sjsg static void skl_ddi_pll_disable(struct drm_i915_private *dev_priv, 1306c349dbc7Sjsg struct intel_shared_dpll *pll) 1307c349dbc7Sjsg { 1308c349dbc7Sjsg const struct skl_dpll_regs *regs = skl_dpll_regs; 1309c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 1310c349dbc7Sjsg 1311c349dbc7Sjsg /* the enable bit is always bit 31 */ 1312f005ef32Sjsg intel_de_rmw(dev_priv, regs[id].ctl, LCPLL_PLL_ENABLE, 0); 1313c349dbc7Sjsg intel_de_posting_read(dev_priv, regs[id].ctl); 1314c349dbc7Sjsg } 1315c349dbc7Sjsg 1316c349dbc7Sjsg static void skl_ddi_dpll0_disable(struct drm_i915_private *dev_priv, 1317c349dbc7Sjsg struct intel_shared_dpll *pll) 1318c349dbc7Sjsg { 1319c349dbc7Sjsg } 1320c349dbc7Sjsg 1321c349dbc7Sjsg static bool skl_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, 1322c349dbc7Sjsg struct intel_shared_dpll *pll, 1323c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 1324c349dbc7Sjsg { 1325c349dbc7Sjsg u32 val; 1326c349dbc7Sjsg const struct skl_dpll_regs *regs = skl_dpll_regs; 1327c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 1328c349dbc7Sjsg intel_wakeref_t wakeref; 1329c349dbc7Sjsg bool ret; 1330c349dbc7Sjsg 1331c349dbc7Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, 1332c349dbc7Sjsg POWER_DOMAIN_DISPLAY_CORE); 1333c349dbc7Sjsg if (!wakeref) 1334c349dbc7Sjsg return false; 1335c349dbc7Sjsg 1336c349dbc7Sjsg ret = false; 1337c349dbc7Sjsg 1338c349dbc7Sjsg val = intel_de_read(dev_priv, regs[id].ctl); 1339c349dbc7Sjsg if (!(val & LCPLL_PLL_ENABLE)) 1340c349dbc7Sjsg goto out; 1341c349dbc7Sjsg 1342c349dbc7Sjsg val = intel_de_read(dev_priv, DPLL_CTRL1); 1343c349dbc7Sjsg hw_state->ctrl1 = (val >> (id * 6)) & 0x3f; 1344c349dbc7Sjsg 1345c349dbc7Sjsg /* avoid reading back stale values if HDMI mode is not enabled */ 1346c349dbc7Sjsg if (val & DPLL_CTRL1_HDMI_MODE(id)) { 1347c349dbc7Sjsg hw_state->cfgcr1 = intel_de_read(dev_priv, regs[id].cfgcr1); 1348c349dbc7Sjsg hw_state->cfgcr2 = intel_de_read(dev_priv, regs[id].cfgcr2); 1349c349dbc7Sjsg } 1350c349dbc7Sjsg ret = true; 1351c349dbc7Sjsg 1352c349dbc7Sjsg out: 1353c349dbc7Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); 1354c349dbc7Sjsg 1355c349dbc7Sjsg return ret; 1356c349dbc7Sjsg } 1357c349dbc7Sjsg 1358c349dbc7Sjsg static bool skl_ddi_dpll0_get_hw_state(struct drm_i915_private *dev_priv, 1359c349dbc7Sjsg struct intel_shared_dpll *pll, 1360c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 1361c349dbc7Sjsg { 1362c349dbc7Sjsg const struct skl_dpll_regs *regs = skl_dpll_regs; 1363c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 1364c349dbc7Sjsg intel_wakeref_t wakeref; 1365c349dbc7Sjsg u32 val; 1366c349dbc7Sjsg bool ret; 1367c349dbc7Sjsg 1368c349dbc7Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, 1369c349dbc7Sjsg POWER_DOMAIN_DISPLAY_CORE); 1370c349dbc7Sjsg if (!wakeref) 1371c349dbc7Sjsg return false; 1372c349dbc7Sjsg 1373c349dbc7Sjsg ret = false; 1374c349dbc7Sjsg 1375c349dbc7Sjsg /* DPLL0 is always enabled since it drives CDCLK */ 1376c349dbc7Sjsg val = intel_de_read(dev_priv, regs[id].ctl); 1377c349dbc7Sjsg if (drm_WARN_ON(&dev_priv->drm, !(val & LCPLL_PLL_ENABLE))) 1378c349dbc7Sjsg goto out; 1379c349dbc7Sjsg 1380c349dbc7Sjsg val = intel_de_read(dev_priv, DPLL_CTRL1); 1381c349dbc7Sjsg hw_state->ctrl1 = (val >> (id * 6)) & 0x3f; 1382c349dbc7Sjsg 1383c349dbc7Sjsg ret = true; 1384c349dbc7Sjsg 1385c349dbc7Sjsg out: 1386c349dbc7Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); 1387c349dbc7Sjsg 1388c349dbc7Sjsg return ret; 1389c349dbc7Sjsg } 1390c349dbc7Sjsg 1391c349dbc7Sjsg struct skl_wrpll_context { 1392c349dbc7Sjsg u64 min_deviation; /* current minimal deviation */ 1393c349dbc7Sjsg u64 central_freq; /* chosen central freq */ 1394c349dbc7Sjsg u64 dco_freq; /* chosen dco freq */ 1395c349dbc7Sjsg unsigned int p; /* chosen divider */ 1396c349dbc7Sjsg }; 1397c349dbc7Sjsg 1398c349dbc7Sjsg /* DCO freq must be within +1%/-6% of the DCO central freq */ 1399c349dbc7Sjsg #define SKL_DCO_MAX_PDEVIATION 100 1400c349dbc7Sjsg #define SKL_DCO_MAX_NDEVIATION 600 1401c349dbc7Sjsg 1402c349dbc7Sjsg static void skl_wrpll_try_divider(struct skl_wrpll_context *ctx, 1403c349dbc7Sjsg u64 central_freq, 1404c349dbc7Sjsg u64 dco_freq, 1405c349dbc7Sjsg unsigned int divider) 1406c349dbc7Sjsg { 1407c349dbc7Sjsg u64 deviation; 1408c349dbc7Sjsg 1409c349dbc7Sjsg deviation = div64_u64(10000 * abs_diff(dco_freq, central_freq), 1410c349dbc7Sjsg central_freq); 1411c349dbc7Sjsg 1412c349dbc7Sjsg /* positive deviation */ 1413c349dbc7Sjsg if (dco_freq >= central_freq) { 1414c349dbc7Sjsg if (deviation < SKL_DCO_MAX_PDEVIATION && 1415c349dbc7Sjsg deviation < ctx->min_deviation) { 1416c349dbc7Sjsg ctx->min_deviation = deviation; 1417c349dbc7Sjsg ctx->central_freq = central_freq; 1418c349dbc7Sjsg ctx->dco_freq = dco_freq; 1419c349dbc7Sjsg ctx->p = divider; 1420c349dbc7Sjsg } 1421c349dbc7Sjsg /* negative deviation */ 1422c349dbc7Sjsg } else if (deviation < SKL_DCO_MAX_NDEVIATION && 1423c349dbc7Sjsg deviation < ctx->min_deviation) { 1424c349dbc7Sjsg ctx->min_deviation = deviation; 1425c349dbc7Sjsg ctx->central_freq = central_freq; 1426c349dbc7Sjsg ctx->dco_freq = dco_freq; 1427c349dbc7Sjsg ctx->p = divider; 1428c349dbc7Sjsg } 1429c349dbc7Sjsg } 1430c349dbc7Sjsg 1431c349dbc7Sjsg static void skl_wrpll_get_multipliers(unsigned int p, 1432c349dbc7Sjsg unsigned int *p0 /* out */, 1433c349dbc7Sjsg unsigned int *p1 /* out */, 1434c349dbc7Sjsg unsigned int *p2 /* out */) 1435c349dbc7Sjsg { 1436c349dbc7Sjsg /* even dividers */ 1437c349dbc7Sjsg if (p % 2 == 0) { 1438c349dbc7Sjsg unsigned int half = p / 2; 1439c349dbc7Sjsg 1440c349dbc7Sjsg if (half == 1 || half == 2 || half == 3 || half == 5) { 1441c349dbc7Sjsg *p0 = 2; 1442c349dbc7Sjsg *p1 = 1; 1443c349dbc7Sjsg *p2 = half; 1444c349dbc7Sjsg } else if (half % 2 == 0) { 1445c349dbc7Sjsg *p0 = 2; 1446c349dbc7Sjsg *p1 = half / 2; 1447c349dbc7Sjsg *p2 = 2; 1448c349dbc7Sjsg } else if (half % 3 == 0) { 1449c349dbc7Sjsg *p0 = 3; 1450c349dbc7Sjsg *p1 = half / 3; 1451c349dbc7Sjsg *p2 = 2; 1452c349dbc7Sjsg } else if (half % 7 == 0) { 1453c349dbc7Sjsg *p0 = 7; 1454c349dbc7Sjsg *p1 = half / 7; 1455c349dbc7Sjsg *p2 = 2; 1456c349dbc7Sjsg } 1457c349dbc7Sjsg } else if (p == 3 || p == 9) { /* 3, 5, 7, 9, 15, 21, 35 */ 1458c349dbc7Sjsg *p0 = 3; 1459c349dbc7Sjsg *p1 = 1; 1460c349dbc7Sjsg *p2 = p / 3; 1461c349dbc7Sjsg } else if (p == 5 || p == 7) { 1462c349dbc7Sjsg *p0 = p; 1463c349dbc7Sjsg *p1 = 1; 1464c349dbc7Sjsg *p2 = 1; 1465c349dbc7Sjsg } else if (p == 15) { 1466c349dbc7Sjsg *p0 = 3; 1467c349dbc7Sjsg *p1 = 1; 1468c349dbc7Sjsg *p2 = 5; 1469c349dbc7Sjsg } else if (p == 21) { 1470c349dbc7Sjsg *p0 = 7; 1471c349dbc7Sjsg *p1 = 1; 1472c349dbc7Sjsg *p2 = 3; 1473c349dbc7Sjsg } else if (p == 35) { 1474c349dbc7Sjsg *p0 = 7; 1475c349dbc7Sjsg *p1 = 1; 1476c349dbc7Sjsg *p2 = 5; 1477c349dbc7Sjsg } 1478c349dbc7Sjsg } 1479c349dbc7Sjsg 1480c349dbc7Sjsg struct skl_wrpll_params { 1481c349dbc7Sjsg u32 dco_fraction; 1482c349dbc7Sjsg u32 dco_integer; 1483c349dbc7Sjsg u32 qdiv_ratio; 1484c349dbc7Sjsg u32 qdiv_mode; 1485c349dbc7Sjsg u32 kdiv; 1486c349dbc7Sjsg u32 pdiv; 1487c349dbc7Sjsg u32 central_freq; 1488c349dbc7Sjsg }; 1489c349dbc7Sjsg 1490c349dbc7Sjsg static void skl_wrpll_params_populate(struct skl_wrpll_params *params, 1491c349dbc7Sjsg u64 afe_clock, 1492c349dbc7Sjsg int ref_clock, 1493c349dbc7Sjsg u64 central_freq, 1494c349dbc7Sjsg u32 p0, u32 p1, u32 p2) 1495c349dbc7Sjsg { 1496c349dbc7Sjsg u64 dco_freq; 1497c349dbc7Sjsg 1498c349dbc7Sjsg switch (central_freq) { 1499c349dbc7Sjsg case 9600000000ULL: 1500c349dbc7Sjsg params->central_freq = 0; 1501c349dbc7Sjsg break; 1502c349dbc7Sjsg case 9000000000ULL: 1503c349dbc7Sjsg params->central_freq = 1; 1504c349dbc7Sjsg break; 1505c349dbc7Sjsg case 8400000000ULL: 1506c349dbc7Sjsg params->central_freq = 3; 1507c349dbc7Sjsg } 1508c349dbc7Sjsg 1509c349dbc7Sjsg switch (p0) { 1510c349dbc7Sjsg case 1: 1511c349dbc7Sjsg params->pdiv = 0; 1512c349dbc7Sjsg break; 1513c349dbc7Sjsg case 2: 1514c349dbc7Sjsg params->pdiv = 1; 1515c349dbc7Sjsg break; 1516c349dbc7Sjsg case 3: 1517c349dbc7Sjsg params->pdiv = 2; 1518c349dbc7Sjsg break; 1519c349dbc7Sjsg case 7: 1520c349dbc7Sjsg params->pdiv = 4; 1521c349dbc7Sjsg break; 1522c349dbc7Sjsg default: 1523c349dbc7Sjsg WARN(1, "Incorrect PDiv\n"); 1524c349dbc7Sjsg } 1525c349dbc7Sjsg 1526c349dbc7Sjsg switch (p2) { 1527c349dbc7Sjsg case 5: 1528c349dbc7Sjsg params->kdiv = 0; 1529c349dbc7Sjsg break; 1530c349dbc7Sjsg case 2: 1531c349dbc7Sjsg params->kdiv = 1; 1532c349dbc7Sjsg break; 1533c349dbc7Sjsg case 3: 1534c349dbc7Sjsg params->kdiv = 2; 1535c349dbc7Sjsg break; 1536c349dbc7Sjsg case 1: 1537c349dbc7Sjsg params->kdiv = 3; 1538c349dbc7Sjsg break; 1539c349dbc7Sjsg default: 1540c349dbc7Sjsg WARN(1, "Incorrect KDiv\n"); 1541c349dbc7Sjsg } 1542c349dbc7Sjsg 1543c349dbc7Sjsg params->qdiv_ratio = p1; 1544c349dbc7Sjsg params->qdiv_mode = (params->qdiv_ratio == 1) ? 0 : 1; 1545c349dbc7Sjsg 1546c349dbc7Sjsg dco_freq = p0 * p1 * p2 * afe_clock; 1547c349dbc7Sjsg 1548c349dbc7Sjsg /* 1549c349dbc7Sjsg * Intermediate values are in Hz. 1550c349dbc7Sjsg * Divide by MHz to match bsepc 1551c349dbc7Sjsg */ 1552c349dbc7Sjsg params->dco_integer = div_u64(dco_freq, ref_clock * KHz(1)); 1553c349dbc7Sjsg params->dco_fraction = 1554c349dbc7Sjsg div_u64((div_u64(dco_freq, ref_clock / KHz(1)) - 1555c349dbc7Sjsg params->dco_integer * MHz(1)) * 0x8000, MHz(1)); 1556c349dbc7Sjsg } 1557c349dbc7Sjsg 15581bb76ff1Sjsg static int 1559*8e8fc6d2Sjsg skl_ddi_calculate_wrpll(int clock, 1560c349dbc7Sjsg int ref_clock, 1561c349dbc7Sjsg struct skl_wrpll_params *wrpll_params) 1562c349dbc7Sjsg { 15631bb76ff1Sjsg static const u64 dco_central_freq[3] = { 8400000000ULL, 1564c349dbc7Sjsg 9000000000ULL, 1565c349dbc7Sjsg 9600000000ULL }; 15661bb76ff1Sjsg static const u8 even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, 1567c349dbc7Sjsg 24, 28, 30, 32, 36, 40, 42, 44, 1568c349dbc7Sjsg 48, 52, 54, 56, 60, 64, 66, 68, 1569c349dbc7Sjsg 70, 72, 76, 78, 80, 84, 88, 90, 1570c349dbc7Sjsg 92, 96, 98 }; 15711bb76ff1Sjsg static const u8 odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 }; 1572c349dbc7Sjsg static const struct { 15731bb76ff1Sjsg const u8 *list; 1574c349dbc7Sjsg int n_dividers; 1575c349dbc7Sjsg } dividers[] = { 1576c349dbc7Sjsg { even_dividers, ARRAY_SIZE(even_dividers) }, 1577c349dbc7Sjsg { odd_dividers, ARRAY_SIZE(odd_dividers) }, 1578c349dbc7Sjsg }; 15791bb76ff1Sjsg struct skl_wrpll_context ctx = { 15801bb76ff1Sjsg .min_deviation = U64_MAX, 15811bb76ff1Sjsg }; 1582c349dbc7Sjsg unsigned int dco, d, i; 1583c349dbc7Sjsg unsigned int p0, p1, p2; 1584*8e8fc6d2Sjsg u64 afe_clock = (u64)clock * 1000 * 5; /* AFE Clock is 5x Pixel clock, in Hz */ 1585c349dbc7Sjsg 1586c349dbc7Sjsg for (d = 0; d < ARRAY_SIZE(dividers); d++) { 1587c349dbc7Sjsg for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) { 1588c349dbc7Sjsg for (i = 0; i < dividers[d].n_dividers; i++) { 1589c349dbc7Sjsg unsigned int p = dividers[d].list[i]; 1590c349dbc7Sjsg u64 dco_freq = p * afe_clock; 1591c349dbc7Sjsg 1592c349dbc7Sjsg skl_wrpll_try_divider(&ctx, 1593c349dbc7Sjsg dco_central_freq[dco], 1594c349dbc7Sjsg dco_freq, 1595c349dbc7Sjsg p); 1596c349dbc7Sjsg /* 1597c349dbc7Sjsg * Skip the remaining dividers if we're sure to 1598c349dbc7Sjsg * have found the definitive divider, we can't 1599c349dbc7Sjsg * improve a 0 deviation. 1600c349dbc7Sjsg */ 1601c349dbc7Sjsg if (ctx.min_deviation == 0) 1602c349dbc7Sjsg goto skip_remaining_dividers; 1603c349dbc7Sjsg } 1604c349dbc7Sjsg } 1605c349dbc7Sjsg 1606c349dbc7Sjsg skip_remaining_dividers: 1607c349dbc7Sjsg /* 1608c349dbc7Sjsg * If a solution is found with an even divider, prefer 1609c349dbc7Sjsg * this one. 1610c349dbc7Sjsg */ 1611c349dbc7Sjsg if (d == 0 && ctx.p) 1612c349dbc7Sjsg break; 1613c349dbc7Sjsg } 1614c349dbc7Sjsg 16151bb76ff1Sjsg if (!ctx.p) 16161bb76ff1Sjsg return -EINVAL; 1617c349dbc7Sjsg 1618c349dbc7Sjsg /* 1619c349dbc7Sjsg * gcc incorrectly analyses that these can be used without being 1620c349dbc7Sjsg * initialized. To be fair, it's hard to guess. 1621c349dbc7Sjsg */ 1622c349dbc7Sjsg p0 = p1 = p2 = 0; 1623c349dbc7Sjsg skl_wrpll_get_multipliers(ctx.p, &p0, &p1, &p2); 1624c349dbc7Sjsg skl_wrpll_params_populate(wrpll_params, afe_clock, ref_clock, 1625c349dbc7Sjsg ctx.central_freq, p0, p1, p2); 1626c349dbc7Sjsg 16271bb76ff1Sjsg return 0; 1628c349dbc7Sjsg } 1629c349dbc7Sjsg 1630c349dbc7Sjsg static int skl_ddi_wrpll_get_freq(struct drm_i915_private *i915, 16315ca02815Sjsg const struct intel_shared_dpll *pll, 16325ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 1633c349dbc7Sjsg { 16341bb76ff1Sjsg int ref_clock = i915->display.dpll.ref_clks.nssc; 1635c349dbc7Sjsg u32 p0, p1, p2, dco_freq; 1636c349dbc7Sjsg 1637c349dbc7Sjsg p0 = pll_state->cfgcr2 & DPLL_CFGCR2_PDIV_MASK; 1638c349dbc7Sjsg p2 = pll_state->cfgcr2 & DPLL_CFGCR2_KDIV_MASK; 1639c349dbc7Sjsg 1640c349dbc7Sjsg if (pll_state->cfgcr2 & DPLL_CFGCR2_QDIV_MODE(1)) 1641c349dbc7Sjsg p1 = (pll_state->cfgcr2 & DPLL_CFGCR2_QDIV_RATIO_MASK) >> 8; 1642c349dbc7Sjsg else 1643c349dbc7Sjsg p1 = 1; 1644c349dbc7Sjsg 1645c349dbc7Sjsg 1646c349dbc7Sjsg switch (p0) { 1647c349dbc7Sjsg case DPLL_CFGCR2_PDIV_1: 1648c349dbc7Sjsg p0 = 1; 1649c349dbc7Sjsg break; 1650c349dbc7Sjsg case DPLL_CFGCR2_PDIV_2: 1651c349dbc7Sjsg p0 = 2; 1652c349dbc7Sjsg break; 1653c349dbc7Sjsg case DPLL_CFGCR2_PDIV_3: 1654c349dbc7Sjsg p0 = 3; 1655c349dbc7Sjsg break; 16565ca02815Sjsg case DPLL_CFGCR2_PDIV_7_INVALID: 16575ca02815Sjsg /* 16585ca02815Sjsg * Incorrect ASUS-Z170M BIOS setting, the HW seems to ignore bit#0, 16595ca02815Sjsg * handling it the same way as PDIV_7. 16605ca02815Sjsg */ 16615ca02815Sjsg drm_dbg_kms(&i915->drm, "Invalid WRPLL PDIV divider value, fixing it.\n"); 16625ca02815Sjsg fallthrough; 1663c349dbc7Sjsg case DPLL_CFGCR2_PDIV_7: 1664c349dbc7Sjsg p0 = 7; 1665c349dbc7Sjsg break; 16665ca02815Sjsg default: 16675ca02815Sjsg MISSING_CASE(p0); 16685ca02815Sjsg return 0; 1669c349dbc7Sjsg } 1670c349dbc7Sjsg 1671c349dbc7Sjsg switch (p2) { 1672c349dbc7Sjsg case DPLL_CFGCR2_KDIV_5: 1673c349dbc7Sjsg p2 = 5; 1674c349dbc7Sjsg break; 1675c349dbc7Sjsg case DPLL_CFGCR2_KDIV_2: 1676c349dbc7Sjsg p2 = 2; 1677c349dbc7Sjsg break; 1678c349dbc7Sjsg case DPLL_CFGCR2_KDIV_3: 1679c349dbc7Sjsg p2 = 3; 1680c349dbc7Sjsg break; 1681c349dbc7Sjsg case DPLL_CFGCR2_KDIV_1: 1682c349dbc7Sjsg p2 = 1; 1683c349dbc7Sjsg break; 16845ca02815Sjsg default: 16855ca02815Sjsg MISSING_CASE(p2); 16865ca02815Sjsg return 0; 1687c349dbc7Sjsg } 1688c349dbc7Sjsg 1689c349dbc7Sjsg dco_freq = (pll_state->cfgcr1 & DPLL_CFGCR1_DCO_INTEGER_MASK) * 1690c349dbc7Sjsg ref_clock; 1691c349dbc7Sjsg 1692c349dbc7Sjsg dco_freq += ((pll_state->cfgcr1 & DPLL_CFGCR1_DCO_FRACTION_MASK) >> 9) * 1693c349dbc7Sjsg ref_clock / 0x8000; 1694c349dbc7Sjsg 1695ad8b1aafSjsg if (drm_WARN_ON(&i915->drm, p0 == 0 || p1 == 0 || p2 == 0)) 1696c349dbc7Sjsg return 0; 1697c349dbc7Sjsg 1698c349dbc7Sjsg return dco_freq / (p0 * p1 * p2 * 5); 1699c349dbc7Sjsg } 1700c349dbc7Sjsg 17011bb76ff1Sjsg static int skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state) 17021bb76ff1Sjsg { 17031bb76ff1Sjsg struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 17041bb76ff1Sjsg struct skl_wrpll_params wrpll_params = {}; 17051bb76ff1Sjsg u32 ctrl1, cfgcr1, cfgcr2; 17061bb76ff1Sjsg int ret; 17071bb76ff1Sjsg 17081bb76ff1Sjsg /* 17091bb76ff1Sjsg * See comment in intel_dpll_hw_state to understand why we always use 0 17101bb76ff1Sjsg * as the DPLL id in this function. 17111bb76ff1Sjsg */ 17121bb76ff1Sjsg ctrl1 = DPLL_CTRL1_OVERRIDE(0); 17131bb76ff1Sjsg 17141bb76ff1Sjsg ctrl1 |= DPLL_CTRL1_HDMI_MODE(0); 17151bb76ff1Sjsg 1716*8e8fc6d2Sjsg ret = skl_ddi_calculate_wrpll(crtc_state->port_clock, 17171bb76ff1Sjsg i915->display.dpll.ref_clks.nssc, &wrpll_params); 17181bb76ff1Sjsg if (ret) 17191bb76ff1Sjsg return ret; 17201bb76ff1Sjsg 17211bb76ff1Sjsg cfgcr1 = DPLL_CFGCR1_FREQ_ENABLE | 17221bb76ff1Sjsg DPLL_CFGCR1_DCO_FRACTION(wrpll_params.dco_fraction) | 17231bb76ff1Sjsg wrpll_params.dco_integer; 17241bb76ff1Sjsg 17251bb76ff1Sjsg cfgcr2 = DPLL_CFGCR2_QDIV_RATIO(wrpll_params.qdiv_ratio) | 17261bb76ff1Sjsg DPLL_CFGCR2_QDIV_MODE(wrpll_params.qdiv_mode) | 17271bb76ff1Sjsg DPLL_CFGCR2_KDIV(wrpll_params.kdiv) | 17281bb76ff1Sjsg DPLL_CFGCR2_PDIV(wrpll_params.pdiv) | 17291bb76ff1Sjsg wrpll_params.central_freq; 17301bb76ff1Sjsg 17311bb76ff1Sjsg crtc_state->dpll_hw_state.ctrl1 = ctrl1; 17321bb76ff1Sjsg crtc_state->dpll_hw_state.cfgcr1 = cfgcr1; 17331bb76ff1Sjsg crtc_state->dpll_hw_state.cfgcr2 = cfgcr2; 17341bb76ff1Sjsg 17351bb76ff1Sjsg crtc_state->port_clock = skl_ddi_wrpll_get_freq(i915, NULL, 17361bb76ff1Sjsg &crtc_state->dpll_hw_state); 17371bb76ff1Sjsg 17381bb76ff1Sjsg return 0; 17391bb76ff1Sjsg } 17401bb76ff1Sjsg 17411bb76ff1Sjsg static int 1742c349dbc7Sjsg skl_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) 1743c349dbc7Sjsg { 1744c349dbc7Sjsg u32 ctrl1; 1745c349dbc7Sjsg 1746c349dbc7Sjsg /* 1747c349dbc7Sjsg * See comment in intel_dpll_hw_state to understand why we always use 0 1748c349dbc7Sjsg * as the DPLL id in this function. 1749c349dbc7Sjsg */ 1750c349dbc7Sjsg ctrl1 = DPLL_CTRL1_OVERRIDE(0); 1751c349dbc7Sjsg switch (crtc_state->port_clock / 2) { 1752c349dbc7Sjsg case 81000: 1753c349dbc7Sjsg ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, 0); 1754c349dbc7Sjsg break; 1755c349dbc7Sjsg case 135000: 1756c349dbc7Sjsg ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, 0); 1757c349dbc7Sjsg break; 1758c349dbc7Sjsg case 270000: 1759c349dbc7Sjsg ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, 0); 1760c349dbc7Sjsg break; 1761c349dbc7Sjsg /* eDP 1.4 rates */ 1762c349dbc7Sjsg case 162000: 1763c349dbc7Sjsg ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0); 1764c349dbc7Sjsg break; 1765c349dbc7Sjsg case 108000: 1766c349dbc7Sjsg ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0); 1767c349dbc7Sjsg break; 1768c349dbc7Sjsg case 216000: 1769c349dbc7Sjsg ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, 0); 1770c349dbc7Sjsg break; 1771c349dbc7Sjsg } 1772c349dbc7Sjsg 1773c349dbc7Sjsg crtc_state->dpll_hw_state.ctrl1 = ctrl1; 1774c349dbc7Sjsg 17751bb76ff1Sjsg return 0; 1776c349dbc7Sjsg } 1777c349dbc7Sjsg 1778c349dbc7Sjsg static int skl_ddi_lcpll_get_freq(struct drm_i915_private *i915, 17795ca02815Sjsg const struct intel_shared_dpll *pll, 17805ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 1781c349dbc7Sjsg { 1782c349dbc7Sjsg int link_clock = 0; 1783c349dbc7Sjsg 17845ca02815Sjsg switch ((pll_state->ctrl1 & DPLL_CTRL1_LINK_RATE_MASK(0)) >> 1785c349dbc7Sjsg DPLL_CTRL1_LINK_RATE_SHIFT(0)) { 1786c349dbc7Sjsg case DPLL_CTRL1_LINK_RATE_810: 1787c349dbc7Sjsg link_clock = 81000; 1788c349dbc7Sjsg break; 1789c349dbc7Sjsg case DPLL_CTRL1_LINK_RATE_1080: 1790c349dbc7Sjsg link_clock = 108000; 1791c349dbc7Sjsg break; 1792c349dbc7Sjsg case DPLL_CTRL1_LINK_RATE_1350: 1793c349dbc7Sjsg link_clock = 135000; 1794c349dbc7Sjsg break; 1795c349dbc7Sjsg case DPLL_CTRL1_LINK_RATE_1620: 1796c349dbc7Sjsg link_clock = 162000; 1797c349dbc7Sjsg break; 1798c349dbc7Sjsg case DPLL_CTRL1_LINK_RATE_2160: 1799c349dbc7Sjsg link_clock = 216000; 1800c349dbc7Sjsg break; 1801c349dbc7Sjsg case DPLL_CTRL1_LINK_RATE_2700: 1802c349dbc7Sjsg link_clock = 270000; 1803c349dbc7Sjsg break; 1804c349dbc7Sjsg default: 1805c349dbc7Sjsg drm_WARN(&i915->drm, 1, "Unsupported link rate\n"); 1806c349dbc7Sjsg break; 1807c349dbc7Sjsg } 1808c349dbc7Sjsg 1809c349dbc7Sjsg return link_clock * 2; 1810c349dbc7Sjsg } 1811c349dbc7Sjsg 18121bb76ff1Sjsg static int skl_compute_dpll(struct intel_atomic_state *state, 1813c349dbc7Sjsg struct intel_crtc *crtc, 1814c349dbc7Sjsg struct intel_encoder *encoder) 1815c349dbc7Sjsg { 1816c349dbc7Sjsg struct intel_crtc_state *crtc_state = 1817c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 1818c349dbc7Sjsg 18191bb76ff1Sjsg if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) 18201bb76ff1Sjsg return skl_ddi_hdmi_pll_dividers(crtc_state); 18211bb76ff1Sjsg else if (intel_crtc_has_dp_encoder(crtc_state)) 18221bb76ff1Sjsg return skl_ddi_dp_set_dpll_hw_state(crtc_state); 18231bb76ff1Sjsg else 18241bb76ff1Sjsg return -EINVAL; 1825c349dbc7Sjsg } 18261bb76ff1Sjsg 18271bb76ff1Sjsg static int skl_get_dpll(struct intel_atomic_state *state, 18281bb76ff1Sjsg struct intel_crtc *crtc, 18291bb76ff1Sjsg struct intel_encoder *encoder) 18301bb76ff1Sjsg { 18311bb76ff1Sjsg struct intel_crtc_state *crtc_state = 18321bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc); 18331bb76ff1Sjsg struct intel_shared_dpll *pll; 1834c349dbc7Sjsg 1835c349dbc7Sjsg if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP)) 1836c349dbc7Sjsg pll = intel_find_shared_dpll(state, crtc, 1837c349dbc7Sjsg &crtc_state->dpll_hw_state, 1838c349dbc7Sjsg BIT(DPLL_ID_SKL_DPLL0)); 1839c349dbc7Sjsg else 1840c349dbc7Sjsg pll = intel_find_shared_dpll(state, crtc, 1841c349dbc7Sjsg &crtc_state->dpll_hw_state, 1842c349dbc7Sjsg BIT(DPLL_ID_SKL_DPLL3) | 1843c349dbc7Sjsg BIT(DPLL_ID_SKL_DPLL2) | 1844c349dbc7Sjsg BIT(DPLL_ID_SKL_DPLL1)); 1845c349dbc7Sjsg if (!pll) 18461bb76ff1Sjsg return -EINVAL; 1847c349dbc7Sjsg 1848c349dbc7Sjsg intel_reference_shared_dpll(state, crtc, 1849c349dbc7Sjsg pll, &crtc_state->dpll_hw_state); 1850c349dbc7Sjsg 1851c349dbc7Sjsg crtc_state->shared_dpll = pll; 1852c349dbc7Sjsg 18531bb76ff1Sjsg return 0; 1854c349dbc7Sjsg } 1855c349dbc7Sjsg 1856c349dbc7Sjsg static int skl_ddi_pll_get_freq(struct drm_i915_private *i915, 18575ca02815Sjsg const struct intel_shared_dpll *pll, 18585ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 1859c349dbc7Sjsg { 1860c349dbc7Sjsg /* 1861c349dbc7Sjsg * ctrl1 register is already shifted for each pll, just use 0 to get 1862c349dbc7Sjsg * the internal shift for each field 1863c349dbc7Sjsg */ 18645ca02815Sjsg if (pll_state->ctrl1 & DPLL_CTRL1_HDMI_MODE(0)) 18655ca02815Sjsg return skl_ddi_wrpll_get_freq(i915, pll, pll_state); 1866c349dbc7Sjsg else 18675ca02815Sjsg return skl_ddi_lcpll_get_freq(i915, pll, pll_state); 1868c349dbc7Sjsg } 1869c349dbc7Sjsg 1870c349dbc7Sjsg static void skl_update_dpll_ref_clks(struct drm_i915_private *i915) 1871c349dbc7Sjsg { 1872c349dbc7Sjsg /* No SSC ref */ 18731bb76ff1Sjsg i915->display.dpll.ref_clks.nssc = i915->display.cdclk.hw.ref; 1874c349dbc7Sjsg } 1875c349dbc7Sjsg 1876c349dbc7Sjsg static void skl_dump_hw_state(struct drm_i915_private *dev_priv, 1877c349dbc7Sjsg const struct intel_dpll_hw_state *hw_state) 1878c349dbc7Sjsg { 1879c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, "dpll_hw_state: " 1880c349dbc7Sjsg "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n", 1881c349dbc7Sjsg hw_state->ctrl1, 1882c349dbc7Sjsg hw_state->cfgcr1, 1883c349dbc7Sjsg hw_state->cfgcr2); 1884c349dbc7Sjsg } 1885c349dbc7Sjsg 1886c349dbc7Sjsg static const struct intel_shared_dpll_funcs skl_ddi_pll_funcs = { 1887c349dbc7Sjsg .enable = skl_ddi_pll_enable, 1888c349dbc7Sjsg .disable = skl_ddi_pll_disable, 1889c349dbc7Sjsg .get_hw_state = skl_ddi_pll_get_hw_state, 1890c349dbc7Sjsg .get_freq = skl_ddi_pll_get_freq, 1891c349dbc7Sjsg }; 1892c349dbc7Sjsg 1893c349dbc7Sjsg static const struct intel_shared_dpll_funcs skl_ddi_dpll0_funcs = { 1894c349dbc7Sjsg .enable = skl_ddi_dpll0_enable, 1895c349dbc7Sjsg .disable = skl_ddi_dpll0_disable, 1896c349dbc7Sjsg .get_hw_state = skl_ddi_dpll0_get_hw_state, 1897c349dbc7Sjsg .get_freq = skl_ddi_pll_get_freq, 1898c349dbc7Sjsg }; 1899c349dbc7Sjsg 1900c349dbc7Sjsg static const struct dpll_info skl_plls[] = { 1901c349dbc7Sjsg { "DPLL 0", &skl_ddi_dpll0_funcs, DPLL_ID_SKL_DPLL0, INTEL_DPLL_ALWAYS_ON }, 1902c349dbc7Sjsg { "DPLL 1", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 }, 1903c349dbc7Sjsg { "DPLL 2", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 }, 1904c349dbc7Sjsg { "DPLL 3", &skl_ddi_pll_funcs, DPLL_ID_SKL_DPLL3, 0 }, 1905c349dbc7Sjsg { }, 1906c349dbc7Sjsg }; 1907c349dbc7Sjsg 1908c349dbc7Sjsg static const struct intel_dpll_mgr skl_pll_mgr = { 1909c349dbc7Sjsg .dpll_info = skl_plls, 19101bb76ff1Sjsg .compute_dplls = skl_compute_dpll, 1911c349dbc7Sjsg .get_dplls = skl_get_dpll, 1912c349dbc7Sjsg .put_dplls = intel_put_dpll, 1913c349dbc7Sjsg .update_ref_clks = skl_update_dpll_ref_clks, 1914c349dbc7Sjsg .dump_hw_state = skl_dump_hw_state, 1915c349dbc7Sjsg }; 1916c349dbc7Sjsg 1917c349dbc7Sjsg static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, 1918c349dbc7Sjsg struct intel_shared_dpll *pll) 1919c349dbc7Sjsg { 1920c349dbc7Sjsg u32 temp; 1921c349dbc7Sjsg enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ 1922c349dbc7Sjsg enum dpio_phy phy; 1923c349dbc7Sjsg enum dpio_channel ch; 1924c349dbc7Sjsg 1925c349dbc7Sjsg bxt_port_to_phy_channel(dev_priv, port, &phy, &ch); 1926c349dbc7Sjsg 1927c349dbc7Sjsg /* Non-SSC reference */ 1928f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port), 0, PORT_PLL_REF_SEL); 1929c349dbc7Sjsg 1930c349dbc7Sjsg if (IS_GEMINILAKE(dev_priv)) { 1931f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port), 1932f005ef32Sjsg 0, PORT_PLL_POWER_ENABLE); 1933c349dbc7Sjsg 1934c349dbc7Sjsg if (wait_for_us((intel_de_read(dev_priv, BXT_PORT_PLL_ENABLE(port)) & 1935c349dbc7Sjsg PORT_PLL_POWER_STATE), 200)) 1936c349dbc7Sjsg drm_err(&dev_priv->drm, 1937c349dbc7Sjsg "Power state not set for PLL:%d\n", port); 1938c349dbc7Sjsg } 1939c349dbc7Sjsg 1940c349dbc7Sjsg /* Disable 10 bit clock */ 1941f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch), 1942f005ef32Sjsg PORT_PLL_10BIT_CLK_ENABLE, 0); 1943c349dbc7Sjsg 1944c349dbc7Sjsg /* Write P1 & P2 */ 1945f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL_EBB_0(phy, ch), 1946f005ef32Sjsg PORT_PLL_P1_MASK | PORT_PLL_P2_MASK, pll->state.hw_state.ebb0); 1947c349dbc7Sjsg 1948c349dbc7Sjsg /* Write M2 integer */ 1949f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 0), 1950f005ef32Sjsg PORT_PLL_M2_INT_MASK, pll->state.hw_state.pll0); 1951c349dbc7Sjsg 1952c349dbc7Sjsg /* Write N */ 1953f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 1), 1954f005ef32Sjsg PORT_PLL_N_MASK, pll->state.hw_state.pll1); 1955c349dbc7Sjsg 1956c349dbc7Sjsg /* Write M2 fraction */ 1957f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 2), 1958f005ef32Sjsg PORT_PLL_M2_FRAC_MASK, pll->state.hw_state.pll2); 1959c349dbc7Sjsg 1960c349dbc7Sjsg /* Write M2 fraction enable */ 1961f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 3), 1962f005ef32Sjsg PORT_PLL_M2_FRAC_ENABLE, pll->state.hw_state.pll3); 1963c349dbc7Sjsg 1964c349dbc7Sjsg /* Write coeff */ 1965c349dbc7Sjsg temp = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 6)); 1966c349dbc7Sjsg temp &= ~PORT_PLL_PROP_COEFF_MASK; 1967c349dbc7Sjsg temp &= ~PORT_PLL_INT_COEFF_MASK; 1968c349dbc7Sjsg temp &= ~PORT_PLL_GAIN_CTL_MASK; 1969c349dbc7Sjsg temp |= pll->state.hw_state.pll6; 1970c349dbc7Sjsg intel_de_write(dev_priv, BXT_PORT_PLL(phy, ch, 6), temp); 1971c349dbc7Sjsg 1972c349dbc7Sjsg /* Write calibration val */ 1973f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 8), 1974f005ef32Sjsg PORT_PLL_TARGET_CNT_MASK, pll->state.hw_state.pll8); 1975c349dbc7Sjsg 1976f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL(phy, ch, 9), 1977f005ef32Sjsg PORT_PLL_LOCK_THRESHOLD_MASK, pll->state.hw_state.pll9); 1978c349dbc7Sjsg 1979c349dbc7Sjsg temp = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 10)); 1980c349dbc7Sjsg temp &= ~PORT_PLL_DCO_AMP_OVR_EN_H; 1981c349dbc7Sjsg temp &= ~PORT_PLL_DCO_AMP_MASK; 1982c349dbc7Sjsg temp |= pll->state.hw_state.pll10; 1983c349dbc7Sjsg intel_de_write(dev_priv, BXT_PORT_PLL(phy, ch, 10), temp); 1984c349dbc7Sjsg 1985c349dbc7Sjsg /* Recalibrate with new settings */ 1986c349dbc7Sjsg temp = intel_de_read(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch)); 1987c349dbc7Sjsg temp |= PORT_PLL_RECALIBRATE; 1988c349dbc7Sjsg intel_de_write(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch), temp); 1989c349dbc7Sjsg temp &= ~PORT_PLL_10BIT_CLK_ENABLE; 1990c349dbc7Sjsg temp |= pll->state.hw_state.ebb4; 1991c349dbc7Sjsg intel_de_write(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch), temp); 1992c349dbc7Sjsg 1993c349dbc7Sjsg /* Enable PLL */ 1994f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port), 0, PORT_PLL_ENABLE); 1995c349dbc7Sjsg intel_de_posting_read(dev_priv, BXT_PORT_PLL_ENABLE(port)); 1996c349dbc7Sjsg 1997c349dbc7Sjsg if (wait_for_us((intel_de_read(dev_priv, BXT_PORT_PLL_ENABLE(port)) & PORT_PLL_LOCK), 1998c349dbc7Sjsg 200)) 1999c349dbc7Sjsg drm_err(&dev_priv->drm, "PLL %d not locked\n", port); 2000c349dbc7Sjsg 2001c349dbc7Sjsg if (IS_GEMINILAKE(dev_priv)) { 2002c349dbc7Sjsg temp = intel_de_read(dev_priv, BXT_PORT_TX_DW5_LN0(phy, ch)); 2003c349dbc7Sjsg temp |= DCC_DELAY_RANGE_2; 2004c349dbc7Sjsg intel_de_write(dev_priv, BXT_PORT_TX_DW5_GRP(phy, ch), temp); 2005c349dbc7Sjsg } 2006c349dbc7Sjsg 2007c349dbc7Sjsg /* 2008c349dbc7Sjsg * While we write to the group register to program all lanes at once we 2009c349dbc7Sjsg * can read only lane registers and we pick lanes 0/1 for that. 2010c349dbc7Sjsg */ 2011c349dbc7Sjsg temp = intel_de_read(dev_priv, BXT_PORT_PCS_DW12_LN01(phy, ch)); 2012c349dbc7Sjsg temp &= ~LANE_STAGGER_MASK; 2013c349dbc7Sjsg temp &= ~LANESTAGGER_STRAP_OVRD; 2014c349dbc7Sjsg temp |= pll->state.hw_state.pcsdw12; 2015c349dbc7Sjsg intel_de_write(dev_priv, BXT_PORT_PCS_DW12_GRP(phy, ch), temp); 2016c349dbc7Sjsg } 2017c349dbc7Sjsg 2018c349dbc7Sjsg static void bxt_ddi_pll_disable(struct drm_i915_private *dev_priv, 2019c349dbc7Sjsg struct intel_shared_dpll *pll) 2020c349dbc7Sjsg { 2021c349dbc7Sjsg enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ 2022c349dbc7Sjsg 2023f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port), PORT_PLL_ENABLE, 0); 2024c349dbc7Sjsg intel_de_posting_read(dev_priv, BXT_PORT_PLL_ENABLE(port)); 2025c349dbc7Sjsg 2026c349dbc7Sjsg if (IS_GEMINILAKE(dev_priv)) { 2027f005ef32Sjsg intel_de_rmw(dev_priv, BXT_PORT_PLL_ENABLE(port), 2028f005ef32Sjsg PORT_PLL_POWER_ENABLE, 0); 2029c349dbc7Sjsg 2030c349dbc7Sjsg if (wait_for_us(!(intel_de_read(dev_priv, BXT_PORT_PLL_ENABLE(port)) & 2031c349dbc7Sjsg PORT_PLL_POWER_STATE), 200)) 2032c349dbc7Sjsg drm_err(&dev_priv->drm, 2033c349dbc7Sjsg "Power state not reset for PLL:%d\n", port); 2034c349dbc7Sjsg } 2035c349dbc7Sjsg } 2036c349dbc7Sjsg 2037c349dbc7Sjsg static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, 2038c349dbc7Sjsg struct intel_shared_dpll *pll, 2039c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 2040c349dbc7Sjsg { 2041c349dbc7Sjsg enum port port = (enum port)pll->info->id; /* 1:1 port->PLL mapping */ 2042c349dbc7Sjsg intel_wakeref_t wakeref; 2043c349dbc7Sjsg enum dpio_phy phy; 2044c349dbc7Sjsg enum dpio_channel ch; 2045c349dbc7Sjsg u32 val; 2046c349dbc7Sjsg bool ret; 2047c349dbc7Sjsg 2048c349dbc7Sjsg bxt_port_to_phy_channel(dev_priv, port, &phy, &ch); 2049c349dbc7Sjsg 2050c349dbc7Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, 2051c349dbc7Sjsg POWER_DOMAIN_DISPLAY_CORE); 2052c349dbc7Sjsg if (!wakeref) 2053c349dbc7Sjsg return false; 2054c349dbc7Sjsg 2055c349dbc7Sjsg ret = false; 2056c349dbc7Sjsg 2057c349dbc7Sjsg val = intel_de_read(dev_priv, BXT_PORT_PLL_ENABLE(port)); 2058c349dbc7Sjsg if (!(val & PORT_PLL_ENABLE)) 2059c349dbc7Sjsg goto out; 2060c349dbc7Sjsg 2061c349dbc7Sjsg hw_state->ebb0 = intel_de_read(dev_priv, BXT_PORT_PLL_EBB_0(phy, ch)); 2062c349dbc7Sjsg hw_state->ebb0 &= PORT_PLL_P1_MASK | PORT_PLL_P2_MASK; 2063c349dbc7Sjsg 2064c349dbc7Sjsg hw_state->ebb4 = intel_de_read(dev_priv, BXT_PORT_PLL_EBB_4(phy, ch)); 2065c349dbc7Sjsg hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE; 2066c349dbc7Sjsg 2067c349dbc7Sjsg hw_state->pll0 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 0)); 20681bb76ff1Sjsg hw_state->pll0 &= PORT_PLL_M2_INT_MASK; 2069c349dbc7Sjsg 2070c349dbc7Sjsg hw_state->pll1 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 1)); 2071c349dbc7Sjsg hw_state->pll1 &= PORT_PLL_N_MASK; 2072c349dbc7Sjsg 2073c349dbc7Sjsg hw_state->pll2 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 2)); 2074c349dbc7Sjsg hw_state->pll2 &= PORT_PLL_M2_FRAC_MASK; 2075c349dbc7Sjsg 2076c349dbc7Sjsg hw_state->pll3 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 3)); 2077c349dbc7Sjsg hw_state->pll3 &= PORT_PLL_M2_FRAC_ENABLE; 2078c349dbc7Sjsg 2079c349dbc7Sjsg hw_state->pll6 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 6)); 2080c349dbc7Sjsg hw_state->pll6 &= PORT_PLL_PROP_COEFF_MASK | 2081c349dbc7Sjsg PORT_PLL_INT_COEFF_MASK | 2082c349dbc7Sjsg PORT_PLL_GAIN_CTL_MASK; 2083c349dbc7Sjsg 2084c349dbc7Sjsg hw_state->pll8 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 8)); 2085c349dbc7Sjsg hw_state->pll8 &= PORT_PLL_TARGET_CNT_MASK; 2086c349dbc7Sjsg 2087c349dbc7Sjsg hw_state->pll9 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 9)); 2088c349dbc7Sjsg hw_state->pll9 &= PORT_PLL_LOCK_THRESHOLD_MASK; 2089c349dbc7Sjsg 2090c349dbc7Sjsg hw_state->pll10 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 10)); 2091c349dbc7Sjsg hw_state->pll10 &= PORT_PLL_DCO_AMP_OVR_EN_H | 2092c349dbc7Sjsg PORT_PLL_DCO_AMP_MASK; 2093c349dbc7Sjsg 2094c349dbc7Sjsg /* 2095c349dbc7Sjsg * While we write to the group register to program all lanes at once we 2096c349dbc7Sjsg * can read only lane registers. We configure all lanes the same way, so 2097c349dbc7Sjsg * here just read out lanes 0/1 and output a note if lanes 2/3 differ. 2098c349dbc7Sjsg */ 2099c349dbc7Sjsg hw_state->pcsdw12 = intel_de_read(dev_priv, 2100c349dbc7Sjsg BXT_PORT_PCS_DW12_LN01(phy, ch)); 2101c349dbc7Sjsg if (intel_de_read(dev_priv, BXT_PORT_PCS_DW12_LN23(phy, ch)) != hw_state->pcsdw12) 2102c349dbc7Sjsg drm_dbg(&dev_priv->drm, 2103c349dbc7Sjsg "lane stagger config different for lane 01 (%08x) and 23 (%08x)\n", 2104c349dbc7Sjsg hw_state->pcsdw12, 2105c349dbc7Sjsg intel_de_read(dev_priv, 2106c349dbc7Sjsg BXT_PORT_PCS_DW12_LN23(phy, ch))); 2107c349dbc7Sjsg hw_state->pcsdw12 &= LANE_STAGGER_MASK | LANESTAGGER_STRAP_OVRD; 2108c349dbc7Sjsg 2109c349dbc7Sjsg ret = true; 2110c349dbc7Sjsg 2111c349dbc7Sjsg out: 2112c349dbc7Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); 2113c349dbc7Sjsg 2114c349dbc7Sjsg return ret; 2115c349dbc7Sjsg } 2116c349dbc7Sjsg 2117c349dbc7Sjsg /* pre-calculated values for DP linkrates */ 21181bb76ff1Sjsg static const struct dpll bxt_dp_clk_val[] = { 21191bb76ff1Sjsg /* m2 is .22 binary fixed point */ 21201bb76ff1Sjsg { .dot = 162000, .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ }, 21211bb76ff1Sjsg { .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ }, 21221bb76ff1Sjsg { .dot = 540000, .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ }, 21231bb76ff1Sjsg { .dot = 216000, .p1 = 3, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ }, 21241bb76ff1Sjsg { .dot = 243000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6133333 /* 24.3 */ }, 21251bb76ff1Sjsg { .dot = 324000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ }, 21261bb76ff1Sjsg { .dot = 432000, .p1 = 3, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ }, 2127c349dbc7Sjsg }; 2128c349dbc7Sjsg 21291bb76ff1Sjsg static int 2130c349dbc7Sjsg bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state, 21311bb76ff1Sjsg struct dpll *clk_div) 2132c349dbc7Sjsg { 2133c349dbc7Sjsg struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 2134c349dbc7Sjsg 2135c349dbc7Sjsg /* Calculate HDMI div */ 2136c349dbc7Sjsg /* 2137c349dbc7Sjsg * FIXME: tie the following calculation into 2138c349dbc7Sjsg * i9xx_crtc_compute_clock 2139c349dbc7Sjsg */ 21401bb76ff1Sjsg if (!bxt_find_best_dpll(crtc_state, clk_div)) 21411bb76ff1Sjsg return -EINVAL; 2142c349dbc7Sjsg 21431bb76ff1Sjsg drm_WARN_ON(&i915->drm, clk_div->m1 != 2); 2144c349dbc7Sjsg 21451bb76ff1Sjsg return 0; 2146c349dbc7Sjsg } 2147c349dbc7Sjsg 2148c349dbc7Sjsg static void bxt_ddi_dp_pll_dividers(struct intel_crtc_state *crtc_state, 21491bb76ff1Sjsg struct dpll *clk_div) 2150c349dbc7Sjsg { 21511bb76ff1Sjsg struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 2152c349dbc7Sjsg int i; 2153c349dbc7Sjsg 2154c349dbc7Sjsg *clk_div = bxt_dp_clk_val[0]; 2155c349dbc7Sjsg for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) { 21561bb76ff1Sjsg if (crtc_state->port_clock == bxt_dp_clk_val[i].dot) { 2157c349dbc7Sjsg *clk_div = bxt_dp_clk_val[i]; 2158c349dbc7Sjsg break; 2159c349dbc7Sjsg } 2160c349dbc7Sjsg } 2161c349dbc7Sjsg 21621bb76ff1Sjsg chv_calc_dpll_params(i915->display.dpll.ref_clks.nssc, clk_div); 21631bb76ff1Sjsg 21641bb76ff1Sjsg drm_WARN_ON(&i915->drm, clk_div->vco == 0 || 21651bb76ff1Sjsg clk_div->dot != crtc_state->port_clock); 2166c349dbc7Sjsg } 2167c349dbc7Sjsg 21681bb76ff1Sjsg static int bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, 21691bb76ff1Sjsg const struct dpll *clk_div) 2170c349dbc7Sjsg { 2171c349dbc7Sjsg struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 2172c349dbc7Sjsg struct intel_dpll_hw_state *dpll_hw_state = &crtc_state->dpll_hw_state; 2173c349dbc7Sjsg int clock = crtc_state->port_clock; 2174c349dbc7Sjsg int vco = clk_div->vco; 2175c349dbc7Sjsg u32 prop_coef, int_coef, gain_ctl, targ_cnt; 2176c349dbc7Sjsg u32 lanestagger; 2177c349dbc7Sjsg 2178c349dbc7Sjsg if (vco >= 6200000 && vco <= 6700000) { 2179c349dbc7Sjsg prop_coef = 4; 2180c349dbc7Sjsg int_coef = 9; 2181c349dbc7Sjsg gain_ctl = 3; 2182c349dbc7Sjsg targ_cnt = 8; 2183c349dbc7Sjsg } else if ((vco > 5400000 && vco < 6200000) || 2184c349dbc7Sjsg (vco >= 4800000 && vco < 5400000)) { 2185c349dbc7Sjsg prop_coef = 5; 2186c349dbc7Sjsg int_coef = 11; 2187c349dbc7Sjsg gain_ctl = 3; 2188c349dbc7Sjsg targ_cnt = 9; 2189c349dbc7Sjsg } else if (vco == 5400000) { 2190c349dbc7Sjsg prop_coef = 3; 2191c349dbc7Sjsg int_coef = 8; 2192c349dbc7Sjsg gain_ctl = 1; 2193c349dbc7Sjsg targ_cnt = 9; 2194c349dbc7Sjsg } else { 2195c349dbc7Sjsg drm_err(&i915->drm, "Invalid VCO\n"); 21961bb76ff1Sjsg return -EINVAL; 2197c349dbc7Sjsg } 2198c349dbc7Sjsg 2199c349dbc7Sjsg if (clock > 270000) 2200c349dbc7Sjsg lanestagger = 0x18; 2201c349dbc7Sjsg else if (clock > 135000) 2202c349dbc7Sjsg lanestagger = 0x0d; 2203c349dbc7Sjsg else if (clock > 67000) 2204c349dbc7Sjsg lanestagger = 0x07; 2205c349dbc7Sjsg else if (clock > 33000) 2206c349dbc7Sjsg lanestagger = 0x04; 2207c349dbc7Sjsg else 2208c349dbc7Sjsg lanestagger = 0x02; 2209c349dbc7Sjsg 2210c349dbc7Sjsg dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2); 22111bb76ff1Sjsg dpll_hw_state->pll0 = PORT_PLL_M2_INT(clk_div->m2 >> 22); 2212c349dbc7Sjsg dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n); 22131bb76ff1Sjsg dpll_hw_state->pll2 = PORT_PLL_M2_FRAC(clk_div->m2 & 0x3fffff); 2214c349dbc7Sjsg 22151bb76ff1Sjsg if (clk_div->m2 & 0x3fffff) 2216c349dbc7Sjsg dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE; 2217c349dbc7Sjsg 22181bb76ff1Sjsg dpll_hw_state->pll6 = PORT_PLL_PROP_COEFF(prop_coef) | 22191bb76ff1Sjsg PORT_PLL_INT_COEFF(int_coef) | 22201bb76ff1Sjsg PORT_PLL_GAIN_CTL(gain_ctl); 2221c349dbc7Sjsg 22221bb76ff1Sjsg dpll_hw_state->pll8 = PORT_PLL_TARGET_CNT(targ_cnt); 2223c349dbc7Sjsg 22241bb76ff1Sjsg dpll_hw_state->pll9 = PORT_PLL_LOCK_THRESHOLD(5); 2225c349dbc7Sjsg 22261bb76ff1Sjsg dpll_hw_state->pll10 = PORT_PLL_DCO_AMP(15) | 22271bb76ff1Sjsg PORT_PLL_DCO_AMP_OVR_EN_H; 2228c349dbc7Sjsg 2229c349dbc7Sjsg dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE; 2230c349dbc7Sjsg 2231c349dbc7Sjsg dpll_hw_state->pcsdw12 = LANESTAGGER_STRAP_OVRD | lanestagger; 2232c349dbc7Sjsg 22331bb76ff1Sjsg return 0; 2234c349dbc7Sjsg } 2235c349dbc7Sjsg 2236c349dbc7Sjsg static int bxt_ddi_pll_get_freq(struct drm_i915_private *i915, 22375ca02815Sjsg const struct intel_shared_dpll *pll, 22385ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 2239c349dbc7Sjsg { 2240c349dbc7Sjsg struct dpll clock; 2241c349dbc7Sjsg 2242c349dbc7Sjsg clock.m1 = 2; 22431bb76ff1Sjsg clock.m2 = REG_FIELD_GET(PORT_PLL_M2_INT_MASK, pll_state->pll0) << 22; 2244c349dbc7Sjsg if (pll_state->pll3 & PORT_PLL_M2_FRAC_ENABLE) 22451bb76ff1Sjsg clock.m2 |= REG_FIELD_GET(PORT_PLL_M2_FRAC_MASK, pll_state->pll2); 22461bb76ff1Sjsg clock.n = REG_FIELD_GET(PORT_PLL_N_MASK, pll_state->pll1); 22471bb76ff1Sjsg clock.p1 = REG_FIELD_GET(PORT_PLL_P1_MASK, pll_state->ebb0); 22481bb76ff1Sjsg clock.p2 = REG_FIELD_GET(PORT_PLL_P2_MASK, pll_state->ebb0); 2249c349dbc7Sjsg 22501bb76ff1Sjsg return chv_calc_dpll_params(i915->display.dpll.ref_clks.nssc, &clock); 2251c349dbc7Sjsg } 2252c349dbc7Sjsg 22531bb76ff1Sjsg static int 22541bb76ff1Sjsg bxt_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) 22551bb76ff1Sjsg { 22561bb76ff1Sjsg struct dpll clk_div = {}; 22571bb76ff1Sjsg 22581bb76ff1Sjsg bxt_ddi_dp_pll_dividers(crtc_state, &clk_div); 22591bb76ff1Sjsg 22601bb76ff1Sjsg return bxt_ddi_set_dpll_hw_state(crtc_state, &clk_div); 22611bb76ff1Sjsg } 22621bb76ff1Sjsg 22631bb76ff1Sjsg static int 22641bb76ff1Sjsg bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc_state *crtc_state) 22651bb76ff1Sjsg { 22661bb76ff1Sjsg struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 22671bb76ff1Sjsg struct dpll clk_div = {}; 22681bb76ff1Sjsg int ret; 22691bb76ff1Sjsg 22701bb76ff1Sjsg bxt_ddi_hdmi_pll_dividers(crtc_state, &clk_div); 22711bb76ff1Sjsg 22721bb76ff1Sjsg ret = bxt_ddi_set_dpll_hw_state(crtc_state, &clk_div); 22731bb76ff1Sjsg if (ret) 22741bb76ff1Sjsg return ret; 22751bb76ff1Sjsg 22761bb76ff1Sjsg crtc_state->port_clock = bxt_ddi_pll_get_freq(i915, NULL, 22771bb76ff1Sjsg &crtc_state->dpll_hw_state); 22781bb76ff1Sjsg 22791bb76ff1Sjsg return 0; 22801bb76ff1Sjsg } 22811bb76ff1Sjsg 22821bb76ff1Sjsg static int bxt_compute_dpll(struct intel_atomic_state *state, 22831bb76ff1Sjsg struct intel_crtc *crtc, 22841bb76ff1Sjsg struct intel_encoder *encoder) 22851bb76ff1Sjsg { 22861bb76ff1Sjsg struct intel_crtc_state *crtc_state = 22871bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc); 22881bb76ff1Sjsg 22891bb76ff1Sjsg if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) 22901bb76ff1Sjsg return bxt_ddi_hdmi_set_dpll_hw_state(crtc_state); 22911bb76ff1Sjsg else if (intel_crtc_has_dp_encoder(crtc_state)) 22921bb76ff1Sjsg return bxt_ddi_dp_set_dpll_hw_state(crtc_state); 22931bb76ff1Sjsg else 22941bb76ff1Sjsg return -EINVAL; 22951bb76ff1Sjsg } 22961bb76ff1Sjsg 22971bb76ff1Sjsg static int bxt_get_dpll(struct intel_atomic_state *state, 2298c349dbc7Sjsg struct intel_crtc *crtc, 2299c349dbc7Sjsg struct intel_encoder *encoder) 2300c349dbc7Sjsg { 2301c349dbc7Sjsg struct intel_crtc_state *crtc_state = 2302c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 2303c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 2304c349dbc7Sjsg struct intel_shared_dpll *pll; 2305c349dbc7Sjsg enum intel_dpll_id id; 2306c349dbc7Sjsg 2307c349dbc7Sjsg /* 1:1 mapping between ports and PLLs */ 2308c349dbc7Sjsg id = (enum intel_dpll_id) encoder->port; 2309c349dbc7Sjsg pll = intel_get_shared_dpll_by_id(dev_priv, id); 2310c349dbc7Sjsg 2311c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] using pre-allocated %s\n", 2312c349dbc7Sjsg crtc->base.base.id, crtc->base.name, pll->info->name); 2313c349dbc7Sjsg 2314c349dbc7Sjsg intel_reference_shared_dpll(state, crtc, 2315c349dbc7Sjsg pll, &crtc_state->dpll_hw_state); 2316c349dbc7Sjsg 2317c349dbc7Sjsg crtc_state->shared_dpll = pll; 2318c349dbc7Sjsg 23191bb76ff1Sjsg return 0; 2320c349dbc7Sjsg } 2321c349dbc7Sjsg 2322c349dbc7Sjsg static void bxt_update_dpll_ref_clks(struct drm_i915_private *i915) 2323c349dbc7Sjsg { 23241bb76ff1Sjsg i915->display.dpll.ref_clks.ssc = 100000; 23251bb76ff1Sjsg i915->display.dpll.ref_clks.nssc = 100000; 2326c349dbc7Sjsg /* DSI non-SSC ref 19.2MHz */ 2327c349dbc7Sjsg } 2328c349dbc7Sjsg 2329c349dbc7Sjsg static void bxt_dump_hw_state(struct drm_i915_private *dev_priv, 2330c349dbc7Sjsg const struct intel_dpll_hw_state *hw_state) 2331c349dbc7Sjsg { 2332c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, "dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x," 2333c349dbc7Sjsg "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, " 2334c349dbc7Sjsg "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n", 2335c349dbc7Sjsg hw_state->ebb0, 2336c349dbc7Sjsg hw_state->ebb4, 2337c349dbc7Sjsg hw_state->pll0, 2338c349dbc7Sjsg hw_state->pll1, 2339c349dbc7Sjsg hw_state->pll2, 2340c349dbc7Sjsg hw_state->pll3, 2341c349dbc7Sjsg hw_state->pll6, 2342c349dbc7Sjsg hw_state->pll8, 2343c349dbc7Sjsg hw_state->pll9, 2344c349dbc7Sjsg hw_state->pll10, 2345c349dbc7Sjsg hw_state->pcsdw12); 2346c349dbc7Sjsg } 2347c349dbc7Sjsg 2348c349dbc7Sjsg static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = { 2349c349dbc7Sjsg .enable = bxt_ddi_pll_enable, 2350c349dbc7Sjsg .disable = bxt_ddi_pll_disable, 2351c349dbc7Sjsg .get_hw_state = bxt_ddi_pll_get_hw_state, 2352c349dbc7Sjsg .get_freq = bxt_ddi_pll_get_freq, 2353c349dbc7Sjsg }; 2354c349dbc7Sjsg 2355c349dbc7Sjsg static const struct dpll_info bxt_plls[] = { 2356c349dbc7Sjsg { "PORT PLL A", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL0, 0 }, 2357c349dbc7Sjsg { "PORT PLL B", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL1, 0 }, 2358c349dbc7Sjsg { "PORT PLL C", &bxt_ddi_pll_funcs, DPLL_ID_SKL_DPLL2, 0 }, 2359c349dbc7Sjsg { }, 2360c349dbc7Sjsg }; 2361c349dbc7Sjsg 2362c349dbc7Sjsg static const struct intel_dpll_mgr bxt_pll_mgr = { 2363c349dbc7Sjsg .dpll_info = bxt_plls, 23641bb76ff1Sjsg .compute_dplls = bxt_compute_dpll, 2365c349dbc7Sjsg .get_dplls = bxt_get_dpll, 2366c349dbc7Sjsg .put_dplls = intel_put_dpll, 2367c349dbc7Sjsg .update_ref_clks = bxt_update_dpll_ref_clks, 2368c349dbc7Sjsg .dump_hw_state = bxt_dump_hw_state, 2369c349dbc7Sjsg }; 2370c349dbc7Sjsg 23715ca02815Sjsg static void icl_wrpll_get_multipliers(int bestdiv, int *pdiv, 2372c349dbc7Sjsg int *qdiv, int *kdiv) 2373c349dbc7Sjsg { 2374c349dbc7Sjsg /* even dividers */ 2375c349dbc7Sjsg if (bestdiv % 2 == 0) { 2376c349dbc7Sjsg if (bestdiv == 2) { 2377c349dbc7Sjsg *pdiv = 2; 2378c349dbc7Sjsg *qdiv = 1; 2379c349dbc7Sjsg *kdiv = 1; 2380c349dbc7Sjsg } else if (bestdiv % 4 == 0) { 2381c349dbc7Sjsg *pdiv = 2; 2382c349dbc7Sjsg *qdiv = bestdiv / 4; 2383c349dbc7Sjsg *kdiv = 2; 2384c349dbc7Sjsg } else if (bestdiv % 6 == 0) { 2385c349dbc7Sjsg *pdiv = 3; 2386c349dbc7Sjsg *qdiv = bestdiv / 6; 2387c349dbc7Sjsg *kdiv = 2; 2388c349dbc7Sjsg } else if (bestdiv % 5 == 0) { 2389c349dbc7Sjsg *pdiv = 5; 2390c349dbc7Sjsg *qdiv = bestdiv / 10; 2391c349dbc7Sjsg *kdiv = 2; 2392c349dbc7Sjsg } else if (bestdiv % 14 == 0) { 2393c349dbc7Sjsg *pdiv = 7; 2394c349dbc7Sjsg *qdiv = bestdiv / 14; 2395c349dbc7Sjsg *kdiv = 2; 2396c349dbc7Sjsg } 2397c349dbc7Sjsg } else { 2398c349dbc7Sjsg if (bestdiv == 3 || bestdiv == 5 || bestdiv == 7) { 2399c349dbc7Sjsg *pdiv = bestdiv; 2400c349dbc7Sjsg *qdiv = 1; 2401c349dbc7Sjsg *kdiv = 1; 2402c349dbc7Sjsg } else { /* 9, 15, 21 */ 2403c349dbc7Sjsg *pdiv = bestdiv / 3; 2404c349dbc7Sjsg *qdiv = 1; 2405c349dbc7Sjsg *kdiv = 3; 2406c349dbc7Sjsg } 2407c349dbc7Sjsg } 2408c349dbc7Sjsg } 2409c349dbc7Sjsg 24105ca02815Sjsg static void icl_wrpll_params_populate(struct skl_wrpll_params *params, 2411c349dbc7Sjsg u32 dco_freq, u32 ref_freq, 2412c349dbc7Sjsg int pdiv, int qdiv, int kdiv) 2413c349dbc7Sjsg { 2414c349dbc7Sjsg u32 dco; 2415c349dbc7Sjsg 2416c349dbc7Sjsg switch (kdiv) { 2417c349dbc7Sjsg case 1: 2418c349dbc7Sjsg params->kdiv = 1; 2419c349dbc7Sjsg break; 2420c349dbc7Sjsg case 2: 2421c349dbc7Sjsg params->kdiv = 2; 2422c349dbc7Sjsg break; 2423c349dbc7Sjsg case 3: 2424c349dbc7Sjsg params->kdiv = 4; 2425c349dbc7Sjsg break; 2426c349dbc7Sjsg default: 2427c349dbc7Sjsg WARN(1, "Incorrect KDiv\n"); 2428c349dbc7Sjsg } 2429c349dbc7Sjsg 2430c349dbc7Sjsg switch (pdiv) { 2431c349dbc7Sjsg case 2: 2432c349dbc7Sjsg params->pdiv = 1; 2433c349dbc7Sjsg break; 2434c349dbc7Sjsg case 3: 2435c349dbc7Sjsg params->pdiv = 2; 2436c349dbc7Sjsg break; 2437c349dbc7Sjsg case 5: 2438c349dbc7Sjsg params->pdiv = 4; 2439c349dbc7Sjsg break; 2440c349dbc7Sjsg case 7: 2441c349dbc7Sjsg params->pdiv = 8; 2442c349dbc7Sjsg break; 2443c349dbc7Sjsg default: 2444c349dbc7Sjsg WARN(1, "Incorrect PDiv\n"); 2445c349dbc7Sjsg } 2446c349dbc7Sjsg 2447c349dbc7Sjsg WARN_ON(kdiv != 2 && qdiv != 1); 2448c349dbc7Sjsg 2449c349dbc7Sjsg params->qdiv_ratio = qdiv; 2450c349dbc7Sjsg params->qdiv_mode = (qdiv == 1) ? 0 : 1; 2451c349dbc7Sjsg 2452c349dbc7Sjsg dco = div_u64((u64)dco_freq << 15, ref_freq); 2453c349dbc7Sjsg 2454c349dbc7Sjsg params->dco_integer = dco >> 15; 2455c349dbc7Sjsg params->dco_fraction = dco & 0x7fff; 2456c349dbc7Sjsg } 2457c349dbc7Sjsg 2458ad8b1aafSjsg /* 2459e8d47841Sjsg * Display WA #22010492432: ehl, tgl, adl-s, adl-p 2460ad8b1aafSjsg * Program half of the nominal DCO divider fraction value. 2461ad8b1aafSjsg */ 2462ad8b1aafSjsg static bool 24635ca02815Sjsg ehl_combo_pll_div_frac_wa_needed(struct drm_i915_private *i915) 2464ad8b1aafSjsg { 2465ac407e1eSjsg return ((IS_ELKHARTLAKE(i915) && 2466f005ef32Sjsg IS_DISPLAY_STEP(i915, STEP_B0, STEP_FOREVER)) || 2467e8d47841Sjsg IS_TIGERLAKE(i915) || IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) && 24681bb76ff1Sjsg i915->display.dpll.ref_clks.nssc == 38400; 2469ad8b1aafSjsg } 2470ad8b1aafSjsg 2471c349dbc7Sjsg struct icl_combo_pll_params { 2472c349dbc7Sjsg int clock; 2473c349dbc7Sjsg struct skl_wrpll_params wrpll; 2474c349dbc7Sjsg }; 2475c349dbc7Sjsg 2476c349dbc7Sjsg /* 2477c349dbc7Sjsg * These values alrea already adjusted: they're the bits we write to the 2478c349dbc7Sjsg * registers, not the logical values. 2479c349dbc7Sjsg */ 2480c349dbc7Sjsg static const struct icl_combo_pll_params icl_dp_combo_pll_24MHz_values[] = { 2481c349dbc7Sjsg { 540000, 2482c349dbc7Sjsg { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [0]: 5.4 */ 2483c349dbc7Sjsg .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2484c349dbc7Sjsg { 270000, 2485c349dbc7Sjsg { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [1]: 2.7 */ 2486c349dbc7Sjsg .pdiv = 0x2 /* 3 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2487c349dbc7Sjsg { 162000, 2488c349dbc7Sjsg { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [2]: 1.62 */ 2489c349dbc7Sjsg .pdiv = 0x4 /* 5 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2490c349dbc7Sjsg { 324000, 2491c349dbc7Sjsg { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [3]: 3.24 */ 2492c349dbc7Sjsg .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2493c349dbc7Sjsg { 216000, 2494c349dbc7Sjsg { .dco_integer = 0x168, .dco_fraction = 0x0000, /* [4]: 2.16 */ 2495c349dbc7Sjsg .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 1, .qdiv_ratio = 2, }, }, 2496c349dbc7Sjsg { 432000, 2497c349dbc7Sjsg { .dco_integer = 0x168, .dco_fraction = 0x0000, /* [5]: 4.32 */ 2498c349dbc7Sjsg .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2499c349dbc7Sjsg { 648000, 2500c349dbc7Sjsg { .dco_integer = 0x195, .dco_fraction = 0x0000, /* [6]: 6.48 */ 2501c349dbc7Sjsg .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2502c349dbc7Sjsg { 810000, 2503c349dbc7Sjsg { .dco_integer = 0x151, .dco_fraction = 0x4000, /* [7]: 8.1 */ 2504c349dbc7Sjsg .pdiv = 0x1 /* 2 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2505c349dbc7Sjsg }; 2506c349dbc7Sjsg 2507c349dbc7Sjsg 2508c349dbc7Sjsg /* Also used for 38.4 MHz values. */ 2509c349dbc7Sjsg static const struct icl_combo_pll_params icl_dp_combo_pll_19_2MHz_values[] = { 2510c349dbc7Sjsg { 540000, 2511c349dbc7Sjsg { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [0]: 5.4 */ 2512c349dbc7Sjsg .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2513c349dbc7Sjsg { 270000, 2514c349dbc7Sjsg { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [1]: 2.7 */ 2515c349dbc7Sjsg .pdiv = 0x2 /* 3 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2516c349dbc7Sjsg { 162000, 2517c349dbc7Sjsg { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [2]: 1.62 */ 2518c349dbc7Sjsg .pdiv = 0x4 /* 5 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2519c349dbc7Sjsg { 324000, 2520c349dbc7Sjsg { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [3]: 3.24 */ 2521c349dbc7Sjsg .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2522c349dbc7Sjsg { 216000, 2523c349dbc7Sjsg { .dco_integer = 0x1C2, .dco_fraction = 0x0000, /* [4]: 2.16 */ 2524c349dbc7Sjsg .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 1, .qdiv_ratio = 2, }, }, 2525c349dbc7Sjsg { 432000, 2526c349dbc7Sjsg { .dco_integer = 0x1C2, .dco_fraction = 0x0000, /* [5]: 4.32 */ 2527c349dbc7Sjsg .pdiv = 0x1 /* 2 */, .kdiv = 2, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2528c349dbc7Sjsg { 648000, 2529c349dbc7Sjsg { .dco_integer = 0x1FA, .dco_fraction = 0x2000, /* [6]: 6.48 */ 2530c349dbc7Sjsg .pdiv = 0x2 /* 3 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2531c349dbc7Sjsg { 810000, 2532c349dbc7Sjsg { .dco_integer = 0x1A5, .dco_fraction = 0x7000, /* [7]: 8.1 */ 2533c349dbc7Sjsg .pdiv = 0x1 /* 2 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, }, }, 2534c349dbc7Sjsg }; 2535c349dbc7Sjsg 2536c349dbc7Sjsg static const struct skl_wrpll_params icl_tbt_pll_24MHz_values = { 2537c349dbc7Sjsg .dco_integer = 0x151, .dco_fraction = 0x4000, 2538c349dbc7Sjsg .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, 2539c349dbc7Sjsg }; 2540c349dbc7Sjsg 2541c349dbc7Sjsg static const struct skl_wrpll_params icl_tbt_pll_19_2MHz_values = { 2542c349dbc7Sjsg .dco_integer = 0x1A5, .dco_fraction = 0x7000, 2543c349dbc7Sjsg .pdiv = 0x4 /* 5 */, .kdiv = 1, .qdiv_mode = 0, .qdiv_ratio = 0, 2544c349dbc7Sjsg }; 2545c349dbc7Sjsg 2546c349dbc7Sjsg static const struct skl_wrpll_params tgl_tbt_pll_19_2MHz_values = { 2547c349dbc7Sjsg .dco_integer = 0x54, .dco_fraction = 0x3000, 2548c349dbc7Sjsg /* the following params are unused */ 2549c349dbc7Sjsg .pdiv = 0, .kdiv = 0, .qdiv_mode = 0, .qdiv_ratio = 0, 2550c349dbc7Sjsg }; 2551c349dbc7Sjsg 2552c349dbc7Sjsg static const struct skl_wrpll_params tgl_tbt_pll_24MHz_values = { 2553c349dbc7Sjsg .dco_integer = 0x43, .dco_fraction = 0x4000, 2554c349dbc7Sjsg /* the following params are unused */ 2555c349dbc7Sjsg }; 2556c349dbc7Sjsg 25571bb76ff1Sjsg static int icl_calc_dp_combo_pll(struct intel_crtc_state *crtc_state, 2558c349dbc7Sjsg struct skl_wrpll_params *pll_params) 2559c349dbc7Sjsg { 2560c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); 2561c349dbc7Sjsg const struct icl_combo_pll_params *params = 25621bb76ff1Sjsg dev_priv->display.dpll.ref_clks.nssc == 24000 ? 2563c349dbc7Sjsg icl_dp_combo_pll_24MHz_values : 2564c349dbc7Sjsg icl_dp_combo_pll_19_2MHz_values; 2565c349dbc7Sjsg int clock = crtc_state->port_clock; 2566c349dbc7Sjsg int i; 2567c349dbc7Sjsg 2568c349dbc7Sjsg for (i = 0; i < ARRAY_SIZE(icl_dp_combo_pll_24MHz_values); i++) { 2569c349dbc7Sjsg if (clock == params[i].clock) { 2570c349dbc7Sjsg *pll_params = params[i].wrpll; 25711bb76ff1Sjsg return 0; 2572c349dbc7Sjsg } 2573c349dbc7Sjsg } 2574c349dbc7Sjsg 2575c349dbc7Sjsg MISSING_CASE(clock); 25761bb76ff1Sjsg return -EINVAL; 2577c349dbc7Sjsg } 2578c349dbc7Sjsg 25791bb76ff1Sjsg static int icl_calc_tbt_pll(struct intel_crtc_state *crtc_state, 2580c349dbc7Sjsg struct skl_wrpll_params *pll_params) 2581c349dbc7Sjsg { 2582c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); 2583c349dbc7Sjsg 25845ca02815Sjsg if (DISPLAY_VER(dev_priv) >= 12) { 25851bb76ff1Sjsg switch (dev_priv->display.dpll.ref_clks.nssc) { 2586c349dbc7Sjsg default: 25871bb76ff1Sjsg MISSING_CASE(dev_priv->display.dpll.ref_clks.nssc); 2588ad8b1aafSjsg fallthrough; 2589c349dbc7Sjsg case 19200: 2590c349dbc7Sjsg case 38400: 2591c349dbc7Sjsg *pll_params = tgl_tbt_pll_19_2MHz_values; 2592c349dbc7Sjsg break; 2593c349dbc7Sjsg case 24000: 2594c349dbc7Sjsg *pll_params = tgl_tbt_pll_24MHz_values; 2595c349dbc7Sjsg break; 2596c349dbc7Sjsg } 2597c349dbc7Sjsg } else { 25981bb76ff1Sjsg switch (dev_priv->display.dpll.ref_clks.nssc) { 2599c349dbc7Sjsg default: 26001bb76ff1Sjsg MISSING_CASE(dev_priv->display.dpll.ref_clks.nssc); 2601ad8b1aafSjsg fallthrough; 2602c349dbc7Sjsg case 19200: 2603c349dbc7Sjsg case 38400: 2604c349dbc7Sjsg *pll_params = icl_tbt_pll_19_2MHz_values; 2605c349dbc7Sjsg break; 2606c349dbc7Sjsg case 24000: 2607c349dbc7Sjsg *pll_params = icl_tbt_pll_24MHz_values; 2608c349dbc7Sjsg break; 2609c349dbc7Sjsg } 2610c349dbc7Sjsg } 2611c349dbc7Sjsg 26121bb76ff1Sjsg return 0; 2613c349dbc7Sjsg } 2614c349dbc7Sjsg 2615c349dbc7Sjsg static int icl_ddi_tbt_pll_get_freq(struct drm_i915_private *i915, 26165ca02815Sjsg const struct intel_shared_dpll *pll, 26175ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 2618c349dbc7Sjsg { 2619c349dbc7Sjsg /* 2620c349dbc7Sjsg * The PLL outputs multiple frequencies at the same time, selection is 2621c349dbc7Sjsg * made at DDI clock mux level. 2622c349dbc7Sjsg */ 2623c349dbc7Sjsg drm_WARN_ON(&i915->drm, 1); 2624c349dbc7Sjsg 2625c349dbc7Sjsg return 0; 2626c349dbc7Sjsg } 2627c349dbc7Sjsg 2628c349dbc7Sjsg static int icl_wrpll_ref_clock(struct drm_i915_private *i915) 2629c349dbc7Sjsg { 26301bb76ff1Sjsg int ref_clock = i915->display.dpll.ref_clks.nssc; 2631c349dbc7Sjsg 2632c349dbc7Sjsg /* 2633c349dbc7Sjsg * For ICL+, the spec states: if reference frequency is 38.4, 2634c349dbc7Sjsg * use 19.2 because the DPLL automatically divides that by 2. 2635c349dbc7Sjsg */ 2636c349dbc7Sjsg if (ref_clock == 38400) 2637c349dbc7Sjsg ref_clock = 19200; 2638c349dbc7Sjsg 2639c349dbc7Sjsg return ref_clock; 2640c349dbc7Sjsg } 2641c349dbc7Sjsg 26421bb76ff1Sjsg static int 2643c349dbc7Sjsg icl_calc_wrpll(struct intel_crtc_state *crtc_state, 2644c349dbc7Sjsg struct skl_wrpll_params *wrpll_params) 2645c349dbc7Sjsg { 2646c349dbc7Sjsg struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); 26475ca02815Sjsg int ref_clock = icl_wrpll_ref_clock(i915); 26485ca02815Sjsg u32 afe_clock = crtc_state->port_clock * 5; 26495ca02815Sjsg u32 dco_min = 7998000; 26505ca02815Sjsg u32 dco_max = 10000000; 26515ca02815Sjsg u32 dco_mid = (dco_min + dco_max) / 2; 26525ca02815Sjsg static const int dividers[] = { 2, 4, 6, 8, 10, 12, 14, 16, 26535ca02815Sjsg 18, 20, 24, 28, 30, 32, 36, 40, 26545ca02815Sjsg 42, 44, 48, 50, 52, 54, 56, 60, 26555ca02815Sjsg 64, 66, 68, 70, 72, 76, 78, 80, 26565ca02815Sjsg 84, 88, 90, 92, 96, 98, 100, 102, 26575ca02815Sjsg 3, 5, 7, 9, 15, 21 }; 26585ca02815Sjsg u32 dco, best_dco = 0, dco_centrality = 0; 26595ca02815Sjsg u32 best_dco_centrality = U32_MAX; /* Spec meaning of 999999 MHz */ 26605ca02815Sjsg int d, best_div = 0, pdiv = 0, qdiv = 0, kdiv = 0; 2661c349dbc7Sjsg 26625ca02815Sjsg for (d = 0; d < ARRAY_SIZE(dividers); d++) { 26635ca02815Sjsg dco = afe_clock * dividers[d]; 26645ca02815Sjsg 26655ca02815Sjsg if (dco <= dco_max && dco >= dco_min) { 26665ca02815Sjsg dco_centrality = abs(dco - dco_mid); 26675ca02815Sjsg 26685ca02815Sjsg if (dco_centrality < best_dco_centrality) { 26695ca02815Sjsg best_dco_centrality = dco_centrality; 26705ca02815Sjsg best_div = dividers[d]; 26715ca02815Sjsg best_dco = dco; 26725ca02815Sjsg } 26735ca02815Sjsg } 26745ca02815Sjsg } 26755ca02815Sjsg 26765ca02815Sjsg if (best_div == 0) 26771bb76ff1Sjsg return -EINVAL; 26785ca02815Sjsg 26795ca02815Sjsg icl_wrpll_get_multipliers(best_div, &pdiv, &qdiv, &kdiv); 26805ca02815Sjsg icl_wrpll_params_populate(wrpll_params, best_dco, ref_clock, 26815ca02815Sjsg pdiv, qdiv, kdiv); 26825ca02815Sjsg 26831bb76ff1Sjsg return 0; 2684c349dbc7Sjsg } 2685c349dbc7Sjsg 2686c349dbc7Sjsg static int icl_ddi_combo_pll_get_freq(struct drm_i915_private *i915, 26875ca02815Sjsg const struct intel_shared_dpll *pll, 26885ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 2689c349dbc7Sjsg { 26905ca02815Sjsg int ref_clock = icl_wrpll_ref_clock(i915); 26915ca02815Sjsg u32 dco_fraction; 26925ca02815Sjsg u32 p0, p1, p2, dco_freq; 26935ca02815Sjsg 26945ca02815Sjsg p0 = pll_state->cfgcr1 & DPLL_CFGCR1_PDIV_MASK; 26955ca02815Sjsg p2 = pll_state->cfgcr1 & DPLL_CFGCR1_KDIV_MASK; 26965ca02815Sjsg 26975ca02815Sjsg if (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_MODE(1)) 26985ca02815Sjsg p1 = (pll_state->cfgcr1 & DPLL_CFGCR1_QDIV_RATIO_MASK) >> 26995ca02815Sjsg DPLL_CFGCR1_QDIV_RATIO_SHIFT; 27005ca02815Sjsg else 27015ca02815Sjsg p1 = 1; 27025ca02815Sjsg 27035ca02815Sjsg switch (p0) { 27045ca02815Sjsg case DPLL_CFGCR1_PDIV_2: 27055ca02815Sjsg p0 = 2; 27065ca02815Sjsg break; 27075ca02815Sjsg case DPLL_CFGCR1_PDIV_3: 27085ca02815Sjsg p0 = 3; 27095ca02815Sjsg break; 27105ca02815Sjsg case DPLL_CFGCR1_PDIV_5: 27115ca02815Sjsg p0 = 5; 27125ca02815Sjsg break; 27135ca02815Sjsg case DPLL_CFGCR1_PDIV_7: 27145ca02815Sjsg p0 = 7; 27155ca02815Sjsg break; 27165ca02815Sjsg } 27175ca02815Sjsg 27185ca02815Sjsg switch (p2) { 27195ca02815Sjsg case DPLL_CFGCR1_KDIV_1: 27205ca02815Sjsg p2 = 1; 27215ca02815Sjsg break; 27225ca02815Sjsg case DPLL_CFGCR1_KDIV_2: 27235ca02815Sjsg p2 = 2; 27245ca02815Sjsg break; 27255ca02815Sjsg case DPLL_CFGCR1_KDIV_3: 27265ca02815Sjsg p2 = 3; 27275ca02815Sjsg break; 27285ca02815Sjsg } 27295ca02815Sjsg 27305ca02815Sjsg dco_freq = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) * 27315ca02815Sjsg ref_clock; 27325ca02815Sjsg 27335ca02815Sjsg dco_fraction = (pll_state->cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >> 27345ca02815Sjsg DPLL_CFGCR0_DCO_FRACTION_SHIFT; 27355ca02815Sjsg 27365ca02815Sjsg if (ehl_combo_pll_div_frac_wa_needed(i915)) 27375ca02815Sjsg dco_fraction *= 2; 27385ca02815Sjsg 27395ca02815Sjsg dco_freq += (dco_fraction * ref_clock) / 0x8000; 27405ca02815Sjsg 27415ca02815Sjsg if (drm_WARN_ON(&i915->drm, p0 == 0 || p1 == 0 || p2 == 0)) 27425ca02815Sjsg return 0; 27435ca02815Sjsg 27445ca02815Sjsg return dco_freq / (p0 * p1 * p2 * 5); 2745c349dbc7Sjsg } 2746c349dbc7Sjsg 2747ad8b1aafSjsg static void icl_calc_dpll_state(struct drm_i915_private *i915, 2748ad8b1aafSjsg const struct skl_wrpll_params *pll_params, 2749c349dbc7Sjsg struct intel_dpll_hw_state *pll_state) 2750c349dbc7Sjsg { 2751ad8b1aafSjsg u32 dco_fraction = pll_params->dco_fraction; 2752c349dbc7Sjsg 27535ca02815Sjsg if (ehl_combo_pll_div_frac_wa_needed(i915)) 2754ad8b1aafSjsg dco_fraction = DIV_ROUND_CLOSEST(dco_fraction, 2); 2755c349dbc7Sjsg 2756ad8b1aafSjsg pll_state->cfgcr0 = DPLL_CFGCR0_DCO_FRACTION(dco_fraction) | 2757ad8b1aafSjsg pll_params->dco_integer; 2758ad8b1aafSjsg 2759ad8b1aafSjsg pll_state->cfgcr1 = DPLL_CFGCR1_QDIV_RATIO(pll_params->qdiv_ratio) | 2760ad8b1aafSjsg DPLL_CFGCR1_QDIV_MODE(pll_params->qdiv_mode) | 2761ad8b1aafSjsg DPLL_CFGCR1_KDIV(pll_params->kdiv) | 2762ad8b1aafSjsg DPLL_CFGCR1_PDIV(pll_params->pdiv); 2763ad8b1aafSjsg 27645ca02815Sjsg if (DISPLAY_VER(i915) >= 12) 2765ad8b1aafSjsg pll_state->cfgcr1 |= TGL_DPLL_CFGCR1_CFSELOVRD_NORMAL_XTAL; 2766ad8b1aafSjsg else 2767ad8b1aafSjsg pll_state->cfgcr1 |= DPLL_CFGCR1_CENTRAL_FREQ_8400; 27681bb76ff1Sjsg 27691bb76ff1Sjsg if (i915->display.vbt.override_afc_startup) 27701bb76ff1Sjsg pll_state->div0 = TGL_DPLL0_DIV0_AFC_STARTUP(i915->display.vbt.override_afc_startup_val); 2771c349dbc7Sjsg } 2772c349dbc7Sjsg 27731bb76ff1Sjsg static int icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc, 2774c349dbc7Sjsg u32 *target_dco_khz, 2775c349dbc7Sjsg struct intel_dpll_hw_state *state, 2776c349dbc7Sjsg bool is_dkl) 2777c349dbc7Sjsg { 27781bb76ff1Sjsg static const u8 div1_vals[] = { 7, 5, 3, 2 }; 2779c349dbc7Sjsg u32 dco_min_freq, dco_max_freq; 2780c349dbc7Sjsg unsigned int i; 2781c349dbc7Sjsg int div2; 2782c349dbc7Sjsg 2783c349dbc7Sjsg dco_min_freq = is_dp ? 8100000 : use_ssc ? 8000000 : 7992000; 2784c349dbc7Sjsg dco_max_freq = is_dp ? 8100000 : 10000000; 2785c349dbc7Sjsg 2786c349dbc7Sjsg for (i = 0; i < ARRAY_SIZE(div1_vals); i++) { 2787c349dbc7Sjsg int div1 = div1_vals[i]; 2788c349dbc7Sjsg 2789c349dbc7Sjsg for (div2 = 10; div2 > 0; div2--) { 2790c349dbc7Sjsg int dco = div1 * div2 * clock_khz * 5; 2791c349dbc7Sjsg int a_divratio, tlinedrv, inputsel; 2792c349dbc7Sjsg u32 hsdiv; 2793c349dbc7Sjsg 2794c349dbc7Sjsg if (dco < dco_min_freq || dco > dco_max_freq) 2795c349dbc7Sjsg continue; 2796c349dbc7Sjsg 2797c349dbc7Sjsg if (div2 >= 2) { 2798c349dbc7Sjsg /* 2799c349dbc7Sjsg * Note: a_divratio not matching TGL BSpec 2800c349dbc7Sjsg * algorithm but matching hardcoded values and 2801c349dbc7Sjsg * working on HW for DP alt-mode at least 2802c349dbc7Sjsg */ 2803c349dbc7Sjsg a_divratio = is_dp ? 10 : 5; 2804c349dbc7Sjsg tlinedrv = is_dkl ? 1 : 2; 2805c349dbc7Sjsg } else { 2806c349dbc7Sjsg a_divratio = 5; 2807c349dbc7Sjsg tlinedrv = 0; 2808c349dbc7Sjsg } 2809c349dbc7Sjsg inputsel = is_dp ? 0 : 1; 2810c349dbc7Sjsg 2811c349dbc7Sjsg switch (div1) { 2812c349dbc7Sjsg default: 2813c349dbc7Sjsg MISSING_CASE(div1); 2814ad8b1aafSjsg fallthrough; 2815c349dbc7Sjsg case 2: 2816c349dbc7Sjsg hsdiv = MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2; 2817c349dbc7Sjsg break; 2818c349dbc7Sjsg case 3: 2819c349dbc7Sjsg hsdiv = MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_3; 2820c349dbc7Sjsg break; 2821c349dbc7Sjsg case 5: 2822c349dbc7Sjsg hsdiv = MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_5; 2823c349dbc7Sjsg break; 2824c349dbc7Sjsg case 7: 2825c349dbc7Sjsg hsdiv = MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_7; 2826c349dbc7Sjsg break; 2827c349dbc7Sjsg } 2828c349dbc7Sjsg 2829c349dbc7Sjsg *target_dco_khz = dco; 2830c349dbc7Sjsg 2831c349dbc7Sjsg state->mg_refclkin_ctl = MG_REFCLKIN_CTL_OD_2_MUX(1); 2832c349dbc7Sjsg 2833c349dbc7Sjsg state->mg_clktop2_coreclkctl1 = 2834c349dbc7Sjsg MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO(a_divratio); 2835c349dbc7Sjsg 2836c349dbc7Sjsg state->mg_clktop2_hsclkctl = 2837c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL(tlinedrv) | 2838c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL(inputsel) | 2839c349dbc7Sjsg hsdiv | 2840c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO(div2); 2841c349dbc7Sjsg 28421bb76ff1Sjsg return 0; 2843c349dbc7Sjsg } 2844c349dbc7Sjsg } 2845c349dbc7Sjsg 28461bb76ff1Sjsg return -EINVAL; 2847c349dbc7Sjsg } 2848c349dbc7Sjsg 2849c349dbc7Sjsg /* 2850c349dbc7Sjsg * The specification for this function uses real numbers, so the math had to be 2851c349dbc7Sjsg * adapted to integer-only calculation, that's why it looks so different. 2852c349dbc7Sjsg */ 28531bb76ff1Sjsg static int icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state, 2854c349dbc7Sjsg struct intel_dpll_hw_state *pll_state) 2855c349dbc7Sjsg { 2856c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); 28571bb76ff1Sjsg int refclk_khz = dev_priv->display.dpll.ref_clks.nssc; 2858c349dbc7Sjsg int clock = crtc_state->port_clock; 2859c349dbc7Sjsg u32 dco_khz, m1div, m2div_int, m2div_rem, m2div_frac; 2860c349dbc7Sjsg u32 iref_ndiv, iref_trim, iref_pulse_w; 2861c349dbc7Sjsg u32 prop_coeff, int_coeff; 2862c349dbc7Sjsg u32 tdc_targetcnt, feedfwgain; 2863c349dbc7Sjsg u64 ssc_stepsize, ssc_steplen, ssc_steplog; 2864c349dbc7Sjsg u64 tmp; 2865c349dbc7Sjsg bool use_ssc = false; 2866c349dbc7Sjsg bool is_dp = !intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI); 28675ca02815Sjsg bool is_dkl = DISPLAY_VER(dev_priv) >= 12; 28681bb76ff1Sjsg int ret; 2869c349dbc7Sjsg 28701bb76ff1Sjsg ret = icl_mg_pll_find_divisors(clock, is_dp, use_ssc, &dco_khz, 28711bb76ff1Sjsg pll_state, is_dkl); 28721bb76ff1Sjsg if (ret) 28731bb76ff1Sjsg return ret; 2874c349dbc7Sjsg 2875c349dbc7Sjsg m1div = 2; 2876c349dbc7Sjsg m2div_int = dco_khz / (refclk_khz * m1div); 2877c349dbc7Sjsg if (m2div_int > 255) { 2878c349dbc7Sjsg if (!is_dkl) { 2879c349dbc7Sjsg m1div = 4; 2880c349dbc7Sjsg m2div_int = dco_khz / (refclk_khz * m1div); 2881c349dbc7Sjsg } 2882c349dbc7Sjsg 28831bb76ff1Sjsg if (m2div_int > 255) 28841bb76ff1Sjsg return -EINVAL; 2885c349dbc7Sjsg } 2886c349dbc7Sjsg m2div_rem = dco_khz % (refclk_khz * m1div); 2887c349dbc7Sjsg 2888c349dbc7Sjsg tmp = (u64)m2div_rem * (1 << 22); 2889c349dbc7Sjsg do_div(tmp, refclk_khz * m1div); 2890c349dbc7Sjsg m2div_frac = tmp; 2891c349dbc7Sjsg 2892c349dbc7Sjsg switch (refclk_khz) { 2893c349dbc7Sjsg case 19200: 2894c349dbc7Sjsg iref_ndiv = 1; 2895c349dbc7Sjsg iref_trim = 28; 2896c349dbc7Sjsg iref_pulse_w = 1; 2897c349dbc7Sjsg break; 2898c349dbc7Sjsg case 24000: 2899c349dbc7Sjsg iref_ndiv = 1; 2900c349dbc7Sjsg iref_trim = 25; 2901c349dbc7Sjsg iref_pulse_w = 2; 2902c349dbc7Sjsg break; 2903c349dbc7Sjsg case 38400: 2904c349dbc7Sjsg iref_ndiv = 2; 2905c349dbc7Sjsg iref_trim = 28; 2906c349dbc7Sjsg iref_pulse_w = 1; 2907c349dbc7Sjsg break; 2908c349dbc7Sjsg default: 2909c349dbc7Sjsg MISSING_CASE(refclk_khz); 29101bb76ff1Sjsg return -EINVAL; 2911c349dbc7Sjsg } 2912c349dbc7Sjsg 2913c349dbc7Sjsg /* 2914c349dbc7Sjsg * tdc_res = 0.000003 2915c349dbc7Sjsg * tdc_targetcnt = int(2 / (tdc_res * 8 * 50 * 1.1) / refclk_mhz + 0.5) 2916c349dbc7Sjsg * 2917c349dbc7Sjsg * The multiplication by 1000 is due to refclk MHz to KHz conversion. It 2918c349dbc7Sjsg * was supposed to be a division, but we rearranged the operations of 2919c349dbc7Sjsg * the formula to avoid early divisions so we don't multiply the 2920c349dbc7Sjsg * rounding errors. 2921c349dbc7Sjsg * 2922c349dbc7Sjsg * 0.000003 * 8 * 50 * 1.1 = 0.00132, also known as 132 / 100000, which 2923c349dbc7Sjsg * we also rearrange to work with integers. 2924c349dbc7Sjsg * 2925c349dbc7Sjsg * The 0.5 transformed to 5 results in a multiplication by 10 and the 2926c349dbc7Sjsg * last division by 10. 2927c349dbc7Sjsg */ 2928c349dbc7Sjsg tdc_targetcnt = (2 * 1000 * 100000 * 10 / (132 * refclk_khz) + 5) / 10; 2929c349dbc7Sjsg 2930c349dbc7Sjsg /* 2931c349dbc7Sjsg * Here we divide dco_khz by 10 in order to allow the dividend to fit in 2932c349dbc7Sjsg * 32 bits. That's not a problem since we round the division down 2933c349dbc7Sjsg * anyway. 2934c349dbc7Sjsg */ 2935c349dbc7Sjsg feedfwgain = (use_ssc || m2div_rem > 0) ? 2936c349dbc7Sjsg m1div * 1000000 * 100 / (dco_khz * 3 / 10) : 0; 2937c349dbc7Sjsg 2938c349dbc7Sjsg if (dco_khz >= 9000000) { 2939c349dbc7Sjsg prop_coeff = 5; 2940c349dbc7Sjsg int_coeff = 10; 2941c349dbc7Sjsg } else { 2942c349dbc7Sjsg prop_coeff = 4; 2943c349dbc7Sjsg int_coeff = 8; 2944c349dbc7Sjsg } 2945c349dbc7Sjsg 2946c349dbc7Sjsg if (use_ssc) { 2947c349dbc7Sjsg tmp = mul_u32_u32(dco_khz, 47 * 32); 2948c349dbc7Sjsg do_div(tmp, refclk_khz * m1div * 10000); 2949c349dbc7Sjsg ssc_stepsize = tmp; 2950c349dbc7Sjsg 2951c349dbc7Sjsg tmp = mul_u32_u32(dco_khz, 1000); 2952c349dbc7Sjsg ssc_steplen = DIV_ROUND_UP_ULL(tmp, 32 * 2 * 32); 2953c349dbc7Sjsg } else { 2954c349dbc7Sjsg ssc_stepsize = 0; 2955c349dbc7Sjsg ssc_steplen = 0; 2956c349dbc7Sjsg } 2957c349dbc7Sjsg ssc_steplog = 4; 2958c349dbc7Sjsg 2959c349dbc7Sjsg /* write pll_state calculations */ 2960c349dbc7Sjsg if (is_dkl) { 2961c349dbc7Sjsg pll_state->mg_pll_div0 = DKL_PLL_DIV0_INTEG_COEFF(int_coeff) | 2962c349dbc7Sjsg DKL_PLL_DIV0_PROP_COEFF(prop_coeff) | 2963c349dbc7Sjsg DKL_PLL_DIV0_FBPREDIV(m1div) | 2964c349dbc7Sjsg DKL_PLL_DIV0_FBDIV_INT(m2div_int); 29651bb76ff1Sjsg if (dev_priv->display.vbt.override_afc_startup) { 29661bb76ff1Sjsg u8 val = dev_priv->display.vbt.override_afc_startup_val; 29671bb76ff1Sjsg 29681bb76ff1Sjsg pll_state->mg_pll_div0 |= DKL_PLL_DIV0_AFC_STARTUP(val); 29691bb76ff1Sjsg } 2970c349dbc7Sjsg 2971c349dbc7Sjsg pll_state->mg_pll_div1 = DKL_PLL_DIV1_IREF_TRIM(iref_trim) | 2972c349dbc7Sjsg DKL_PLL_DIV1_TDC_TARGET_CNT(tdc_targetcnt); 2973c349dbc7Sjsg 2974c349dbc7Sjsg pll_state->mg_pll_ssc = DKL_PLL_SSC_IREF_NDIV_RATIO(iref_ndiv) | 2975c349dbc7Sjsg DKL_PLL_SSC_STEP_LEN(ssc_steplen) | 2976c349dbc7Sjsg DKL_PLL_SSC_STEP_NUM(ssc_steplog) | 2977c349dbc7Sjsg (use_ssc ? DKL_PLL_SSC_EN : 0); 2978c349dbc7Sjsg 2979c349dbc7Sjsg pll_state->mg_pll_bias = (m2div_frac ? DKL_PLL_BIAS_FRAC_EN_H : 0) | 2980c349dbc7Sjsg DKL_PLL_BIAS_FBDIV_FRAC(m2div_frac); 2981c349dbc7Sjsg 2982c349dbc7Sjsg pll_state->mg_pll_tdc_coldst_bias = 2983c349dbc7Sjsg DKL_PLL_TDC_SSC_STEP_SIZE(ssc_stepsize) | 2984c349dbc7Sjsg DKL_PLL_TDC_FEED_FWD_GAIN(feedfwgain); 2985c349dbc7Sjsg 2986c349dbc7Sjsg } else { 2987c349dbc7Sjsg pll_state->mg_pll_div0 = 2988c349dbc7Sjsg (m2div_rem > 0 ? MG_PLL_DIV0_FRACNEN_H : 0) | 2989c349dbc7Sjsg MG_PLL_DIV0_FBDIV_FRAC(m2div_frac) | 2990c349dbc7Sjsg MG_PLL_DIV0_FBDIV_INT(m2div_int); 2991c349dbc7Sjsg 2992c349dbc7Sjsg pll_state->mg_pll_div1 = 2993c349dbc7Sjsg MG_PLL_DIV1_IREF_NDIVRATIO(iref_ndiv) | 2994c349dbc7Sjsg MG_PLL_DIV1_DITHER_DIV_2 | 2995c349dbc7Sjsg MG_PLL_DIV1_NDIVRATIO(1) | 2996c349dbc7Sjsg MG_PLL_DIV1_FBPREDIV(m1div); 2997c349dbc7Sjsg 2998c349dbc7Sjsg pll_state->mg_pll_lf = 2999c349dbc7Sjsg MG_PLL_LF_TDCTARGETCNT(tdc_targetcnt) | 3000c349dbc7Sjsg MG_PLL_LF_AFCCNTSEL_512 | 3001c349dbc7Sjsg MG_PLL_LF_GAINCTRL(1) | 3002c349dbc7Sjsg MG_PLL_LF_INT_COEFF(int_coeff) | 3003c349dbc7Sjsg MG_PLL_LF_PROP_COEFF(prop_coeff); 3004c349dbc7Sjsg 3005c349dbc7Sjsg pll_state->mg_pll_frac_lock = 3006c349dbc7Sjsg MG_PLL_FRAC_LOCK_TRUELOCK_CRIT_32 | 3007c349dbc7Sjsg MG_PLL_FRAC_LOCK_EARLYLOCK_CRIT_32 | 3008c349dbc7Sjsg MG_PLL_FRAC_LOCK_LOCKTHRESH(10) | 3009c349dbc7Sjsg MG_PLL_FRAC_LOCK_DCODITHEREN | 3010c349dbc7Sjsg MG_PLL_FRAC_LOCK_FEEDFWRDGAIN(feedfwgain); 3011c349dbc7Sjsg if (use_ssc || m2div_rem > 0) 3012c349dbc7Sjsg pll_state->mg_pll_frac_lock |= 3013c349dbc7Sjsg MG_PLL_FRAC_LOCK_FEEDFWRDCAL_EN; 3014c349dbc7Sjsg 3015c349dbc7Sjsg pll_state->mg_pll_ssc = 3016c349dbc7Sjsg (use_ssc ? MG_PLL_SSC_EN : 0) | 3017c349dbc7Sjsg MG_PLL_SSC_TYPE(2) | 3018c349dbc7Sjsg MG_PLL_SSC_STEPLENGTH(ssc_steplen) | 3019c349dbc7Sjsg MG_PLL_SSC_STEPNUM(ssc_steplog) | 3020c349dbc7Sjsg MG_PLL_SSC_FLLEN | 3021c349dbc7Sjsg MG_PLL_SSC_STEPSIZE(ssc_stepsize); 3022c349dbc7Sjsg 3023c349dbc7Sjsg pll_state->mg_pll_tdc_coldst_bias = 3024c349dbc7Sjsg MG_PLL_TDC_COLDST_COLDSTART | 3025c349dbc7Sjsg MG_PLL_TDC_COLDST_IREFINT_EN | 3026c349dbc7Sjsg MG_PLL_TDC_COLDST_REFBIAS_START_PULSE_W(iref_pulse_w) | 3027c349dbc7Sjsg MG_PLL_TDC_TDCOVCCORR_EN | 3028c349dbc7Sjsg MG_PLL_TDC_TDCSEL(3); 3029c349dbc7Sjsg 3030c349dbc7Sjsg pll_state->mg_pll_bias = 3031c349dbc7Sjsg MG_PLL_BIAS_BIAS_GB_SEL(3) | 3032c349dbc7Sjsg MG_PLL_BIAS_INIT_DCOAMP(0x3F) | 3033c349dbc7Sjsg MG_PLL_BIAS_BIAS_BONUS(10) | 3034c349dbc7Sjsg MG_PLL_BIAS_BIASCAL_EN | 3035c349dbc7Sjsg MG_PLL_BIAS_CTRIM(12) | 3036c349dbc7Sjsg MG_PLL_BIAS_VREF_RDAC(4) | 3037c349dbc7Sjsg MG_PLL_BIAS_IREFTRIM(iref_trim); 3038c349dbc7Sjsg 3039c349dbc7Sjsg if (refclk_khz == 38400) { 3040c349dbc7Sjsg pll_state->mg_pll_tdc_coldst_bias_mask = 3041c349dbc7Sjsg MG_PLL_TDC_COLDST_COLDSTART; 3042c349dbc7Sjsg pll_state->mg_pll_bias_mask = 0; 3043c349dbc7Sjsg } else { 3044c349dbc7Sjsg pll_state->mg_pll_tdc_coldst_bias_mask = -1U; 3045c349dbc7Sjsg pll_state->mg_pll_bias_mask = -1U; 3046c349dbc7Sjsg } 3047c349dbc7Sjsg 3048c349dbc7Sjsg pll_state->mg_pll_tdc_coldst_bias &= 3049c349dbc7Sjsg pll_state->mg_pll_tdc_coldst_bias_mask; 3050c349dbc7Sjsg pll_state->mg_pll_bias &= pll_state->mg_pll_bias_mask; 3051c349dbc7Sjsg } 3052c349dbc7Sjsg 30531bb76ff1Sjsg return 0; 3054c349dbc7Sjsg } 3055c349dbc7Sjsg 3056c349dbc7Sjsg static int icl_ddi_mg_pll_get_freq(struct drm_i915_private *dev_priv, 30575ca02815Sjsg const struct intel_shared_dpll *pll, 30585ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 3059c349dbc7Sjsg { 3060c349dbc7Sjsg u32 m1, m2_int, m2_frac, div1, div2, ref_clock; 3061c349dbc7Sjsg u64 tmp; 3062c349dbc7Sjsg 30631bb76ff1Sjsg ref_clock = dev_priv->display.dpll.ref_clks.nssc; 3064c349dbc7Sjsg 30655ca02815Sjsg if (DISPLAY_VER(dev_priv) >= 12) { 3066c349dbc7Sjsg m1 = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBPREDIV_MASK; 3067c349dbc7Sjsg m1 = m1 >> DKL_PLL_DIV0_FBPREDIV_SHIFT; 3068c349dbc7Sjsg m2_int = pll_state->mg_pll_div0 & DKL_PLL_DIV0_FBDIV_INT_MASK; 3069c349dbc7Sjsg 3070c349dbc7Sjsg if (pll_state->mg_pll_bias & DKL_PLL_BIAS_FRAC_EN_H) { 3071c349dbc7Sjsg m2_frac = pll_state->mg_pll_bias & 3072c349dbc7Sjsg DKL_PLL_BIAS_FBDIV_FRAC_MASK; 3073c349dbc7Sjsg m2_frac = m2_frac >> DKL_PLL_BIAS_FBDIV_SHIFT; 3074c349dbc7Sjsg } else { 3075c349dbc7Sjsg m2_frac = 0; 3076c349dbc7Sjsg } 3077c349dbc7Sjsg } else { 3078c349dbc7Sjsg m1 = pll_state->mg_pll_div1 & MG_PLL_DIV1_FBPREDIV_MASK; 3079c349dbc7Sjsg m2_int = pll_state->mg_pll_div0 & MG_PLL_DIV0_FBDIV_INT_MASK; 3080c349dbc7Sjsg 3081c349dbc7Sjsg if (pll_state->mg_pll_div0 & MG_PLL_DIV0_FRACNEN_H) { 3082c349dbc7Sjsg m2_frac = pll_state->mg_pll_div0 & 3083c349dbc7Sjsg MG_PLL_DIV0_FBDIV_FRAC_MASK; 3084c349dbc7Sjsg m2_frac = m2_frac >> MG_PLL_DIV0_FBDIV_FRAC_SHIFT; 3085c349dbc7Sjsg } else { 3086c349dbc7Sjsg m2_frac = 0; 3087c349dbc7Sjsg } 3088c349dbc7Sjsg } 3089c349dbc7Sjsg 3090c349dbc7Sjsg switch (pll_state->mg_clktop2_hsclkctl & 3091c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK) { 3092c349dbc7Sjsg case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_2: 3093c349dbc7Sjsg div1 = 2; 3094c349dbc7Sjsg break; 3095c349dbc7Sjsg case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_3: 3096c349dbc7Sjsg div1 = 3; 3097c349dbc7Sjsg break; 3098c349dbc7Sjsg case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_5: 3099c349dbc7Sjsg div1 = 5; 3100c349dbc7Sjsg break; 3101c349dbc7Sjsg case MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_7: 3102c349dbc7Sjsg div1 = 7; 3103c349dbc7Sjsg break; 3104c349dbc7Sjsg default: 3105c349dbc7Sjsg MISSING_CASE(pll_state->mg_clktop2_hsclkctl); 3106c349dbc7Sjsg return 0; 3107c349dbc7Sjsg } 3108c349dbc7Sjsg 3109c349dbc7Sjsg div2 = (pll_state->mg_clktop2_hsclkctl & 3110c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK) >> 3111c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_SHIFT; 3112c349dbc7Sjsg 3113c349dbc7Sjsg /* div2 value of 0 is same as 1 means no div */ 3114c349dbc7Sjsg if (div2 == 0) 3115c349dbc7Sjsg div2 = 1; 3116c349dbc7Sjsg 3117c349dbc7Sjsg /* 3118c349dbc7Sjsg * Adjust the original formula to delay the division by 2^22 in order to 3119c349dbc7Sjsg * minimize possible rounding errors. 3120c349dbc7Sjsg */ 3121c349dbc7Sjsg tmp = (u64)m1 * m2_int * ref_clock + 3122c349dbc7Sjsg (((u64)m1 * m2_frac * ref_clock) >> 22); 3123c349dbc7Sjsg tmp = div_u64(tmp, 5 * div1 * div2); 3124c349dbc7Sjsg 3125c349dbc7Sjsg return tmp; 3126c349dbc7Sjsg } 3127c349dbc7Sjsg 3128c349dbc7Sjsg /** 3129c349dbc7Sjsg * icl_set_active_port_dpll - select the active port DPLL for a given CRTC 3130c349dbc7Sjsg * @crtc_state: state for the CRTC to select the DPLL for 3131c349dbc7Sjsg * @port_dpll_id: the active @port_dpll_id to select 3132c349dbc7Sjsg * 3133c349dbc7Sjsg * Select the given @port_dpll_id instance from the DPLLs reserved for the 3134c349dbc7Sjsg * CRTC. 3135c349dbc7Sjsg */ 3136c349dbc7Sjsg void icl_set_active_port_dpll(struct intel_crtc_state *crtc_state, 3137c349dbc7Sjsg enum icl_port_dpll_id port_dpll_id) 3138c349dbc7Sjsg { 3139c349dbc7Sjsg struct icl_port_dpll *port_dpll = 3140c349dbc7Sjsg &crtc_state->icl_port_dplls[port_dpll_id]; 3141c349dbc7Sjsg 3142c349dbc7Sjsg crtc_state->shared_dpll = port_dpll->pll; 3143c349dbc7Sjsg crtc_state->dpll_hw_state = port_dpll->hw_state; 3144c349dbc7Sjsg } 3145c349dbc7Sjsg 3146c349dbc7Sjsg static void icl_update_active_dpll(struct intel_atomic_state *state, 3147c349dbc7Sjsg struct intel_crtc *crtc, 3148c349dbc7Sjsg struct intel_encoder *encoder) 3149c349dbc7Sjsg { 3150c349dbc7Sjsg struct intel_crtc_state *crtc_state = 3151c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 3152c349dbc7Sjsg struct intel_digital_port *primary_port; 3153c349dbc7Sjsg enum icl_port_dpll_id port_dpll_id = ICL_PORT_DPLL_DEFAULT; 3154c349dbc7Sjsg 3155c349dbc7Sjsg primary_port = encoder->type == INTEL_OUTPUT_DP_MST ? 3156c349dbc7Sjsg enc_to_mst(encoder)->primary : 3157c349dbc7Sjsg enc_to_dig_port(encoder); 3158c349dbc7Sjsg 3159c349dbc7Sjsg if (primary_port && 31601bb76ff1Sjsg (intel_tc_port_in_dp_alt_mode(primary_port) || 31611bb76ff1Sjsg intel_tc_port_in_legacy_mode(primary_port))) 3162c349dbc7Sjsg port_dpll_id = ICL_PORT_DPLL_MG_PHY; 3163c349dbc7Sjsg 3164c349dbc7Sjsg icl_set_active_port_dpll(crtc_state, port_dpll_id); 3165c349dbc7Sjsg } 3166c349dbc7Sjsg 31671bb76ff1Sjsg static int icl_compute_combo_phy_dpll(struct intel_atomic_state *state, 31681bb76ff1Sjsg struct intel_crtc *crtc) 3169c349dbc7Sjsg { 31701bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 3171c349dbc7Sjsg struct intel_crtc_state *crtc_state = 3172c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 3173c349dbc7Sjsg struct icl_port_dpll *port_dpll = 3174c349dbc7Sjsg &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; 31751bb76ff1Sjsg struct skl_wrpll_params pll_params = {}; 3176ad8b1aafSjsg int ret; 3177c349dbc7Sjsg 3178ad8b1aafSjsg if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI) || 3179ad8b1aafSjsg intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) 3180ad8b1aafSjsg ret = icl_calc_wrpll(crtc_state, &pll_params); 3181ad8b1aafSjsg else 3182ad8b1aafSjsg ret = icl_calc_dp_combo_pll(crtc_state, &pll_params); 3183ad8b1aafSjsg 31841bb76ff1Sjsg if (ret) 31851bb76ff1Sjsg return ret; 3186c349dbc7Sjsg 3187ad8b1aafSjsg icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state); 3188ad8b1aafSjsg 31891bb76ff1Sjsg /* this is mainly for the fastset check */ 31901bb76ff1Sjsg icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_DEFAULT); 31911bb76ff1Sjsg 31921bb76ff1Sjsg crtc_state->port_clock = icl_ddi_combo_pll_get_freq(dev_priv, NULL, 31931bb76ff1Sjsg &port_dpll->hw_state); 31941bb76ff1Sjsg 31951bb76ff1Sjsg return 0; 31961bb76ff1Sjsg } 31971bb76ff1Sjsg 31981bb76ff1Sjsg static int icl_get_combo_phy_dpll(struct intel_atomic_state *state, 31991bb76ff1Sjsg struct intel_crtc *crtc, 32001bb76ff1Sjsg struct intel_encoder *encoder) 32011bb76ff1Sjsg { 32021bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 32031bb76ff1Sjsg struct intel_crtc_state *crtc_state = 32041bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc); 32051bb76ff1Sjsg struct icl_port_dpll *port_dpll = 32061bb76ff1Sjsg &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; 32071bb76ff1Sjsg enum port port = encoder->port; 32081bb76ff1Sjsg unsigned long dpll_mask; 32091bb76ff1Sjsg 32105ca02815Sjsg if (IS_ALDERLAKE_S(dev_priv)) { 32115ca02815Sjsg dpll_mask = 32125ca02815Sjsg BIT(DPLL_ID_DG1_DPLL3) | 32135ca02815Sjsg BIT(DPLL_ID_DG1_DPLL2) | 32145ca02815Sjsg BIT(DPLL_ID_ICL_DPLL1) | 32155ca02815Sjsg BIT(DPLL_ID_ICL_DPLL0); 32165ca02815Sjsg } else if (IS_DG1(dev_priv)) { 32175ca02815Sjsg if (port == PORT_D || port == PORT_E) { 32185ca02815Sjsg dpll_mask = 32195ca02815Sjsg BIT(DPLL_ID_DG1_DPLL2) | 32205ca02815Sjsg BIT(DPLL_ID_DG1_DPLL3); 32215ca02815Sjsg } else { 32225ca02815Sjsg dpll_mask = 32235ca02815Sjsg BIT(DPLL_ID_DG1_DPLL0) | 32245ca02815Sjsg BIT(DPLL_ID_DG1_DPLL1); 32255ca02815Sjsg } 32265ca02815Sjsg } else if (IS_ROCKETLAKE(dev_priv)) { 3227c349dbc7Sjsg dpll_mask = 3228c349dbc7Sjsg BIT(DPLL_ID_EHL_DPLL4) | 3229c349dbc7Sjsg BIT(DPLL_ID_ICL_DPLL1) | 3230c349dbc7Sjsg BIT(DPLL_ID_ICL_DPLL0); 3231f005ef32Sjsg } else if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && 3232f005ef32Sjsg port != PORT_A) { 3233ad8b1aafSjsg dpll_mask = 3234ad8b1aafSjsg BIT(DPLL_ID_EHL_DPLL4) | 3235ad8b1aafSjsg BIT(DPLL_ID_ICL_DPLL1) | 3236ad8b1aafSjsg BIT(DPLL_ID_ICL_DPLL0); 3237ad8b1aafSjsg } else { 3238c349dbc7Sjsg dpll_mask = BIT(DPLL_ID_ICL_DPLL1) | BIT(DPLL_ID_ICL_DPLL0); 3239ad8b1aafSjsg } 3240ad8b1aafSjsg 3241ad8b1aafSjsg /* Eliminate DPLLs from consideration if reserved by HTI */ 3242f005ef32Sjsg dpll_mask &= ~intel_hti_dpll_mask(dev_priv); 3243c349dbc7Sjsg 3244c349dbc7Sjsg port_dpll->pll = intel_find_shared_dpll(state, crtc, 3245c349dbc7Sjsg &port_dpll->hw_state, 3246c349dbc7Sjsg dpll_mask); 32471bb76ff1Sjsg if (!port_dpll->pll) 32481bb76ff1Sjsg return -EINVAL; 3249c349dbc7Sjsg 3250c349dbc7Sjsg intel_reference_shared_dpll(state, crtc, 3251c349dbc7Sjsg port_dpll->pll, &port_dpll->hw_state); 3252c349dbc7Sjsg 3253c349dbc7Sjsg icl_update_active_dpll(state, crtc, encoder); 3254c349dbc7Sjsg 32551bb76ff1Sjsg return 0; 3256c349dbc7Sjsg } 3257c349dbc7Sjsg 32581bb76ff1Sjsg static int icl_compute_tc_phy_dplls(struct intel_atomic_state *state, 32591bb76ff1Sjsg struct intel_crtc *crtc) 32601bb76ff1Sjsg { 32611bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(state->base.dev); 32621bb76ff1Sjsg struct intel_crtc_state *crtc_state = 32631bb76ff1Sjsg intel_atomic_get_new_crtc_state(state, crtc); 32641bb76ff1Sjsg struct icl_port_dpll *port_dpll = 32651bb76ff1Sjsg &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; 32661bb76ff1Sjsg struct skl_wrpll_params pll_params = {}; 32671bb76ff1Sjsg int ret; 32681bb76ff1Sjsg 32691bb76ff1Sjsg port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; 32701bb76ff1Sjsg ret = icl_calc_tbt_pll(crtc_state, &pll_params); 32711bb76ff1Sjsg if (ret) 32721bb76ff1Sjsg return ret; 32731bb76ff1Sjsg 32741bb76ff1Sjsg icl_calc_dpll_state(dev_priv, &pll_params, &port_dpll->hw_state); 32751bb76ff1Sjsg 32761bb76ff1Sjsg port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; 32771bb76ff1Sjsg ret = icl_calc_mg_pll_state(crtc_state, &port_dpll->hw_state); 32781bb76ff1Sjsg if (ret) 32791bb76ff1Sjsg return ret; 32801bb76ff1Sjsg 32811bb76ff1Sjsg /* this is mainly for the fastset check */ 32821bb76ff1Sjsg icl_set_active_port_dpll(crtc_state, ICL_PORT_DPLL_MG_PHY); 32831bb76ff1Sjsg 32841bb76ff1Sjsg crtc_state->port_clock = icl_ddi_mg_pll_get_freq(dev_priv, NULL, 32851bb76ff1Sjsg &port_dpll->hw_state); 32861bb76ff1Sjsg 32871bb76ff1Sjsg return 0; 32881bb76ff1Sjsg } 32891bb76ff1Sjsg 32901bb76ff1Sjsg static int icl_get_tc_phy_dplls(struct intel_atomic_state *state, 3291c349dbc7Sjsg struct intel_crtc *crtc, 3292c349dbc7Sjsg struct intel_encoder *encoder) 3293c349dbc7Sjsg { 3294c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(state->base.dev); 3295c349dbc7Sjsg struct intel_crtc_state *crtc_state = 3296c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 32971bb76ff1Sjsg struct icl_port_dpll *port_dpll = 32981bb76ff1Sjsg &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; 3299c349dbc7Sjsg enum intel_dpll_id dpll_id; 33001bb76ff1Sjsg int ret; 3301c349dbc7Sjsg 3302c349dbc7Sjsg port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; 3303c349dbc7Sjsg port_dpll->pll = intel_find_shared_dpll(state, crtc, 3304c349dbc7Sjsg &port_dpll->hw_state, 3305c349dbc7Sjsg BIT(DPLL_ID_ICL_TBTPLL)); 33061bb76ff1Sjsg if (!port_dpll->pll) 33071bb76ff1Sjsg return -EINVAL; 3308c349dbc7Sjsg intel_reference_shared_dpll(state, crtc, 3309c349dbc7Sjsg port_dpll->pll, &port_dpll->hw_state); 3310c349dbc7Sjsg 3311c349dbc7Sjsg 3312c349dbc7Sjsg port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_MG_PHY]; 3313c349dbc7Sjsg dpll_id = icl_tc_port_to_pll_id(intel_port_to_tc(dev_priv, 3314c349dbc7Sjsg encoder->port)); 3315c349dbc7Sjsg port_dpll->pll = intel_find_shared_dpll(state, crtc, 3316c349dbc7Sjsg &port_dpll->hw_state, 3317c349dbc7Sjsg BIT(dpll_id)); 3318c349dbc7Sjsg if (!port_dpll->pll) { 33191bb76ff1Sjsg ret = -EINVAL; 3320c349dbc7Sjsg goto err_unreference_tbt_pll; 3321c349dbc7Sjsg } 3322c349dbc7Sjsg intel_reference_shared_dpll(state, crtc, 3323c349dbc7Sjsg port_dpll->pll, &port_dpll->hw_state); 3324c349dbc7Sjsg 3325c349dbc7Sjsg icl_update_active_dpll(state, crtc, encoder); 3326c349dbc7Sjsg 33271bb76ff1Sjsg return 0; 3328c349dbc7Sjsg 3329c349dbc7Sjsg err_unreference_tbt_pll: 3330c349dbc7Sjsg port_dpll = &crtc_state->icl_port_dplls[ICL_PORT_DPLL_DEFAULT]; 3331c349dbc7Sjsg intel_unreference_shared_dpll(state, crtc, port_dpll->pll); 3332c349dbc7Sjsg 33331bb76ff1Sjsg return ret; 3334c349dbc7Sjsg } 3335c349dbc7Sjsg 33361bb76ff1Sjsg static int icl_compute_dplls(struct intel_atomic_state *state, 33371bb76ff1Sjsg struct intel_crtc *crtc, 33381bb76ff1Sjsg struct intel_encoder *encoder) 33391bb76ff1Sjsg { 33401bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(state->base.dev); 33411bb76ff1Sjsg enum phy phy = intel_port_to_phy(dev_priv, encoder->port); 33421bb76ff1Sjsg 33431bb76ff1Sjsg if (intel_phy_is_combo(dev_priv, phy)) 33441bb76ff1Sjsg return icl_compute_combo_phy_dpll(state, crtc); 33451bb76ff1Sjsg else if (intel_phy_is_tc(dev_priv, phy)) 33461bb76ff1Sjsg return icl_compute_tc_phy_dplls(state, crtc); 33471bb76ff1Sjsg 33481bb76ff1Sjsg MISSING_CASE(phy); 33491bb76ff1Sjsg 33501bb76ff1Sjsg return 0; 33511bb76ff1Sjsg } 33521bb76ff1Sjsg 33531bb76ff1Sjsg static int icl_get_dplls(struct intel_atomic_state *state, 3354c349dbc7Sjsg struct intel_crtc *crtc, 3355c349dbc7Sjsg struct intel_encoder *encoder) 3356c349dbc7Sjsg { 3357c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(state->base.dev); 3358c349dbc7Sjsg enum phy phy = intel_port_to_phy(dev_priv, encoder->port); 3359c349dbc7Sjsg 3360c349dbc7Sjsg if (intel_phy_is_combo(dev_priv, phy)) 3361c349dbc7Sjsg return icl_get_combo_phy_dpll(state, crtc, encoder); 3362c349dbc7Sjsg else if (intel_phy_is_tc(dev_priv, phy)) 3363c349dbc7Sjsg return icl_get_tc_phy_dplls(state, crtc, encoder); 3364c349dbc7Sjsg 3365c349dbc7Sjsg MISSING_CASE(phy); 3366c349dbc7Sjsg 33671bb76ff1Sjsg return -EINVAL; 3368c349dbc7Sjsg } 3369c349dbc7Sjsg 3370c349dbc7Sjsg static void icl_put_dplls(struct intel_atomic_state *state, 3371c349dbc7Sjsg struct intel_crtc *crtc) 3372c349dbc7Sjsg { 3373c349dbc7Sjsg const struct intel_crtc_state *old_crtc_state = 3374c349dbc7Sjsg intel_atomic_get_old_crtc_state(state, crtc); 3375c349dbc7Sjsg struct intel_crtc_state *new_crtc_state = 3376c349dbc7Sjsg intel_atomic_get_new_crtc_state(state, crtc); 3377c349dbc7Sjsg enum icl_port_dpll_id id; 3378c349dbc7Sjsg 3379c349dbc7Sjsg new_crtc_state->shared_dpll = NULL; 3380c349dbc7Sjsg 3381c349dbc7Sjsg for (id = ICL_PORT_DPLL_DEFAULT; id < ICL_PORT_DPLL_COUNT; id++) { 3382c349dbc7Sjsg const struct icl_port_dpll *old_port_dpll = 3383c349dbc7Sjsg &old_crtc_state->icl_port_dplls[id]; 3384c349dbc7Sjsg struct icl_port_dpll *new_port_dpll = 3385c349dbc7Sjsg &new_crtc_state->icl_port_dplls[id]; 3386c349dbc7Sjsg 3387c349dbc7Sjsg new_port_dpll->pll = NULL; 3388c349dbc7Sjsg 3389c349dbc7Sjsg if (!old_port_dpll->pll) 3390c349dbc7Sjsg continue; 3391c349dbc7Sjsg 3392c349dbc7Sjsg intel_unreference_shared_dpll(state, crtc, old_port_dpll->pll); 3393c349dbc7Sjsg } 3394c349dbc7Sjsg } 3395c349dbc7Sjsg 3396c349dbc7Sjsg static bool mg_pll_get_hw_state(struct drm_i915_private *dev_priv, 3397c349dbc7Sjsg struct intel_shared_dpll *pll, 3398c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 3399c349dbc7Sjsg { 3400c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 3401c349dbc7Sjsg enum tc_port tc_port = icl_pll_id_to_tc_port(id); 3402c349dbc7Sjsg intel_wakeref_t wakeref; 3403c349dbc7Sjsg bool ret = false; 3404c349dbc7Sjsg u32 val; 3405c349dbc7Sjsg 34065ca02815Sjsg i915_reg_t enable_reg = intel_tc_pll_enable_reg(dev_priv, pll); 34075ca02815Sjsg 3408c349dbc7Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, 3409c349dbc7Sjsg POWER_DOMAIN_DISPLAY_CORE); 3410c349dbc7Sjsg if (!wakeref) 3411c349dbc7Sjsg return false; 3412c349dbc7Sjsg 34135ca02815Sjsg val = intel_de_read(dev_priv, enable_reg); 3414c349dbc7Sjsg if (!(val & PLL_ENABLE)) 3415c349dbc7Sjsg goto out; 3416c349dbc7Sjsg 3417c349dbc7Sjsg hw_state->mg_refclkin_ctl = intel_de_read(dev_priv, 3418c349dbc7Sjsg MG_REFCLKIN_CTL(tc_port)); 3419c349dbc7Sjsg hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK; 3420c349dbc7Sjsg 3421c349dbc7Sjsg hw_state->mg_clktop2_coreclkctl1 = 3422c349dbc7Sjsg intel_de_read(dev_priv, MG_CLKTOP2_CORECLKCTL1(tc_port)); 3423c349dbc7Sjsg hw_state->mg_clktop2_coreclkctl1 &= 3424c349dbc7Sjsg MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK; 3425c349dbc7Sjsg 3426c349dbc7Sjsg hw_state->mg_clktop2_hsclkctl = 3427c349dbc7Sjsg intel_de_read(dev_priv, MG_CLKTOP2_HSCLKCTL(tc_port)); 3428c349dbc7Sjsg hw_state->mg_clktop2_hsclkctl &= 3429c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK | 3430c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK | 3431c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK | 3432c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK; 3433c349dbc7Sjsg 3434c349dbc7Sjsg hw_state->mg_pll_div0 = intel_de_read(dev_priv, MG_PLL_DIV0(tc_port)); 3435c349dbc7Sjsg hw_state->mg_pll_div1 = intel_de_read(dev_priv, MG_PLL_DIV1(tc_port)); 3436c349dbc7Sjsg hw_state->mg_pll_lf = intel_de_read(dev_priv, MG_PLL_LF(tc_port)); 3437c349dbc7Sjsg hw_state->mg_pll_frac_lock = intel_de_read(dev_priv, 3438c349dbc7Sjsg MG_PLL_FRAC_LOCK(tc_port)); 3439c349dbc7Sjsg hw_state->mg_pll_ssc = intel_de_read(dev_priv, MG_PLL_SSC(tc_port)); 3440c349dbc7Sjsg 3441c349dbc7Sjsg hw_state->mg_pll_bias = intel_de_read(dev_priv, MG_PLL_BIAS(tc_port)); 3442c349dbc7Sjsg hw_state->mg_pll_tdc_coldst_bias = 3443c349dbc7Sjsg intel_de_read(dev_priv, MG_PLL_TDC_COLDST_BIAS(tc_port)); 3444c349dbc7Sjsg 34451bb76ff1Sjsg if (dev_priv->display.dpll.ref_clks.nssc == 38400) { 3446c349dbc7Sjsg hw_state->mg_pll_tdc_coldst_bias_mask = MG_PLL_TDC_COLDST_COLDSTART; 3447c349dbc7Sjsg hw_state->mg_pll_bias_mask = 0; 3448c349dbc7Sjsg } else { 3449c349dbc7Sjsg hw_state->mg_pll_tdc_coldst_bias_mask = -1U; 3450c349dbc7Sjsg hw_state->mg_pll_bias_mask = -1U; 3451c349dbc7Sjsg } 3452c349dbc7Sjsg 3453c349dbc7Sjsg hw_state->mg_pll_tdc_coldst_bias &= hw_state->mg_pll_tdc_coldst_bias_mask; 3454c349dbc7Sjsg hw_state->mg_pll_bias &= hw_state->mg_pll_bias_mask; 3455c349dbc7Sjsg 3456c349dbc7Sjsg ret = true; 3457c349dbc7Sjsg out: 3458c349dbc7Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); 3459c349dbc7Sjsg return ret; 3460c349dbc7Sjsg } 3461c349dbc7Sjsg 3462c349dbc7Sjsg static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv, 3463c349dbc7Sjsg struct intel_shared_dpll *pll, 3464c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 3465c349dbc7Sjsg { 3466c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 3467c349dbc7Sjsg enum tc_port tc_port = icl_pll_id_to_tc_port(id); 3468c349dbc7Sjsg intel_wakeref_t wakeref; 3469c349dbc7Sjsg bool ret = false; 3470c349dbc7Sjsg u32 val; 3471c349dbc7Sjsg 3472c349dbc7Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, 3473c349dbc7Sjsg POWER_DOMAIN_DISPLAY_CORE); 3474c349dbc7Sjsg if (!wakeref) 3475c349dbc7Sjsg return false; 3476c349dbc7Sjsg 34775ca02815Sjsg val = intel_de_read(dev_priv, intel_tc_pll_enable_reg(dev_priv, pll)); 3478c349dbc7Sjsg if (!(val & PLL_ENABLE)) 3479c349dbc7Sjsg goto out; 3480c349dbc7Sjsg 3481c349dbc7Sjsg /* 3482c349dbc7Sjsg * All registers read here have the same HIP_INDEX_REG even though 3483c349dbc7Sjsg * they are on different building blocks 3484c349dbc7Sjsg */ 34851bb76ff1Sjsg hw_state->mg_refclkin_ctl = intel_dkl_phy_read(dev_priv, 3486f005ef32Sjsg DKL_REFCLKIN_CTL(tc_port)); 3487c349dbc7Sjsg hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK; 3488c349dbc7Sjsg 3489c349dbc7Sjsg hw_state->mg_clktop2_hsclkctl = 3490f005ef32Sjsg intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port)); 3491c349dbc7Sjsg hw_state->mg_clktop2_hsclkctl &= 3492c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK | 3493c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK | 3494c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK | 3495c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK; 3496c349dbc7Sjsg 3497c349dbc7Sjsg hw_state->mg_clktop2_coreclkctl1 = 3498f005ef32Sjsg intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port)); 3499c349dbc7Sjsg hw_state->mg_clktop2_coreclkctl1 &= 3500c349dbc7Sjsg MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK; 3501c349dbc7Sjsg 3502f005ef32Sjsg hw_state->mg_pll_div0 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV0(tc_port)); 35031bb76ff1Sjsg val = DKL_PLL_DIV0_MASK; 35041bb76ff1Sjsg if (dev_priv->display.vbt.override_afc_startup) 35051bb76ff1Sjsg val |= DKL_PLL_DIV0_AFC_STARTUP_MASK; 35061bb76ff1Sjsg hw_state->mg_pll_div0 &= val; 3507c349dbc7Sjsg 3508f005ef32Sjsg hw_state->mg_pll_div1 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port)); 3509c349dbc7Sjsg hw_state->mg_pll_div1 &= (DKL_PLL_DIV1_IREF_TRIM_MASK | 3510c349dbc7Sjsg DKL_PLL_DIV1_TDC_TARGET_CNT_MASK); 3511c349dbc7Sjsg 3512f005ef32Sjsg hw_state->mg_pll_ssc = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port)); 3513c349dbc7Sjsg hw_state->mg_pll_ssc &= (DKL_PLL_SSC_IREF_NDIV_RATIO_MASK | 3514c349dbc7Sjsg DKL_PLL_SSC_STEP_LEN_MASK | 3515c349dbc7Sjsg DKL_PLL_SSC_STEP_NUM_MASK | 3516c349dbc7Sjsg DKL_PLL_SSC_EN); 3517c349dbc7Sjsg 3518f005ef32Sjsg hw_state->mg_pll_bias = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port)); 3519c349dbc7Sjsg hw_state->mg_pll_bias &= (DKL_PLL_BIAS_FRAC_EN_H | 3520c349dbc7Sjsg DKL_PLL_BIAS_FBDIV_FRAC_MASK); 3521c349dbc7Sjsg 3522c349dbc7Sjsg hw_state->mg_pll_tdc_coldst_bias = 3523f005ef32Sjsg intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); 3524c349dbc7Sjsg hw_state->mg_pll_tdc_coldst_bias &= (DKL_PLL_TDC_SSC_STEP_SIZE_MASK | 3525c349dbc7Sjsg DKL_PLL_TDC_FEED_FWD_GAIN_MASK); 3526c349dbc7Sjsg 3527c349dbc7Sjsg ret = true; 3528c349dbc7Sjsg out: 3529c349dbc7Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); 3530c349dbc7Sjsg return ret; 3531c349dbc7Sjsg } 3532c349dbc7Sjsg 3533c349dbc7Sjsg static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv, 3534c349dbc7Sjsg struct intel_shared_dpll *pll, 3535c349dbc7Sjsg struct intel_dpll_hw_state *hw_state, 3536c349dbc7Sjsg i915_reg_t enable_reg) 3537c349dbc7Sjsg { 3538c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 3539c349dbc7Sjsg intel_wakeref_t wakeref; 3540c349dbc7Sjsg bool ret = false; 3541c349dbc7Sjsg u32 val; 3542c349dbc7Sjsg 3543c349dbc7Sjsg wakeref = intel_display_power_get_if_enabled(dev_priv, 3544c349dbc7Sjsg POWER_DOMAIN_DISPLAY_CORE); 3545c349dbc7Sjsg if (!wakeref) 3546c349dbc7Sjsg return false; 3547c349dbc7Sjsg 3548c349dbc7Sjsg val = intel_de_read(dev_priv, enable_reg); 3549c349dbc7Sjsg if (!(val & PLL_ENABLE)) 3550c349dbc7Sjsg goto out; 3551c349dbc7Sjsg 35525ca02815Sjsg if (IS_ALDERLAKE_S(dev_priv)) { 35535ca02815Sjsg hw_state->cfgcr0 = intel_de_read(dev_priv, ADLS_DPLL_CFGCR0(id)); 35545ca02815Sjsg hw_state->cfgcr1 = intel_de_read(dev_priv, ADLS_DPLL_CFGCR1(id)); 35555ca02815Sjsg } else if (IS_DG1(dev_priv)) { 35565ca02815Sjsg hw_state->cfgcr0 = intel_de_read(dev_priv, DG1_DPLL_CFGCR0(id)); 35575ca02815Sjsg hw_state->cfgcr1 = intel_de_read(dev_priv, DG1_DPLL_CFGCR1(id)); 35585ca02815Sjsg } else if (IS_ROCKETLAKE(dev_priv)) { 3559ad8b1aafSjsg hw_state->cfgcr0 = intel_de_read(dev_priv, 3560ad8b1aafSjsg RKL_DPLL_CFGCR0(id)); 3561ad8b1aafSjsg hw_state->cfgcr1 = intel_de_read(dev_priv, 3562ad8b1aafSjsg RKL_DPLL_CFGCR1(id)); 35635ca02815Sjsg } else if (DISPLAY_VER(dev_priv) >= 12) { 3564c349dbc7Sjsg hw_state->cfgcr0 = intel_de_read(dev_priv, 3565c349dbc7Sjsg TGL_DPLL_CFGCR0(id)); 3566c349dbc7Sjsg hw_state->cfgcr1 = intel_de_read(dev_priv, 3567c349dbc7Sjsg TGL_DPLL_CFGCR1(id)); 35681bb76ff1Sjsg if (dev_priv->display.vbt.override_afc_startup) { 35691bb76ff1Sjsg hw_state->div0 = intel_de_read(dev_priv, TGL_DPLL0_DIV0(id)); 35701bb76ff1Sjsg hw_state->div0 &= TGL_DPLL0_DIV0_AFC_STARTUP_MASK; 35711bb76ff1Sjsg } 3572c349dbc7Sjsg } else { 3573f005ef32Sjsg if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && 3574f005ef32Sjsg id == DPLL_ID_EHL_DPLL4) { 3575c349dbc7Sjsg hw_state->cfgcr0 = intel_de_read(dev_priv, 3576c349dbc7Sjsg ICL_DPLL_CFGCR0(4)); 3577c349dbc7Sjsg hw_state->cfgcr1 = intel_de_read(dev_priv, 3578c349dbc7Sjsg ICL_DPLL_CFGCR1(4)); 3579c349dbc7Sjsg } else { 3580c349dbc7Sjsg hw_state->cfgcr0 = intel_de_read(dev_priv, 3581c349dbc7Sjsg ICL_DPLL_CFGCR0(id)); 3582c349dbc7Sjsg hw_state->cfgcr1 = intel_de_read(dev_priv, 3583c349dbc7Sjsg ICL_DPLL_CFGCR1(id)); 3584c349dbc7Sjsg } 3585c349dbc7Sjsg } 3586c349dbc7Sjsg 3587c349dbc7Sjsg ret = true; 3588c349dbc7Sjsg out: 3589c349dbc7Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref); 3590c349dbc7Sjsg return ret; 3591c349dbc7Sjsg } 3592c349dbc7Sjsg 3593c349dbc7Sjsg static bool combo_pll_get_hw_state(struct drm_i915_private *dev_priv, 3594c349dbc7Sjsg struct intel_shared_dpll *pll, 3595c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 3596c349dbc7Sjsg { 3597ad8b1aafSjsg i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll); 3598c349dbc7Sjsg 3599c349dbc7Sjsg return icl_pll_get_hw_state(dev_priv, pll, hw_state, enable_reg); 3600c349dbc7Sjsg } 3601c349dbc7Sjsg 3602c349dbc7Sjsg static bool tbt_pll_get_hw_state(struct drm_i915_private *dev_priv, 3603c349dbc7Sjsg struct intel_shared_dpll *pll, 3604c349dbc7Sjsg struct intel_dpll_hw_state *hw_state) 3605c349dbc7Sjsg { 3606c349dbc7Sjsg return icl_pll_get_hw_state(dev_priv, pll, hw_state, TBT_PLL_ENABLE); 3607c349dbc7Sjsg } 3608c349dbc7Sjsg 3609c349dbc7Sjsg static void icl_dpll_write(struct drm_i915_private *dev_priv, 3610c349dbc7Sjsg struct intel_shared_dpll *pll) 3611c349dbc7Sjsg { 3612c349dbc7Sjsg struct intel_dpll_hw_state *hw_state = &pll->state.hw_state; 3613c349dbc7Sjsg const enum intel_dpll_id id = pll->info->id; 36141bb76ff1Sjsg i915_reg_t cfgcr0_reg, cfgcr1_reg, div0_reg = INVALID_MMIO_REG; 3615c349dbc7Sjsg 36165ca02815Sjsg if (IS_ALDERLAKE_S(dev_priv)) { 36175ca02815Sjsg cfgcr0_reg = ADLS_DPLL_CFGCR0(id); 36185ca02815Sjsg cfgcr1_reg = ADLS_DPLL_CFGCR1(id); 36195ca02815Sjsg } else if (IS_DG1(dev_priv)) { 36205ca02815Sjsg cfgcr0_reg = DG1_DPLL_CFGCR0(id); 36215ca02815Sjsg cfgcr1_reg = DG1_DPLL_CFGCR1(id); 36225ca02815Sjsg } else if (IS_ROCKETLAKE(dev_priv)) { 3623ad8b1aafSjsg cfgcr0_reg = RKL_DPLL_CFGCR0(id); 3624ad8b1aafSjsg cfgcr1_reg = RKL_DPLL_CFGCR1(id); 36255ca02815Sjsg } else if (DISPLAY_VER(dev_priv) >= 12) { 3626c349dbc7Sjsg cfgcr0_reg = TGL_DPLL_CFGCR0(id); 3627c349dbc7Sjsg cfgcr1_reg = TGL_DPLL_CFGCR1(id); 36281bb76ff1Sjsg div0_reg = TGL_DPLL0_DIV0(id); 3629c349dbc7Sjsg } else { 3630f005ef32Sjsg if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && 3631f005ef32Sjsg id == DPLL_ID_EHL_DPLL4) { 3632c349dbc7Sjsg cfgcr0_reg = ICL_DPLL_CFGCR0(4); 3633c349dbc7Sjsg cfgcr1_reg = ICL_DPLL_CFGCR1(4); 3634c349dbc7Sjsg } else { 3635c349dbc7Sjsg cfgcr0_reg = ICL_DPLL_CFGCR0(id); 3636c349dbc7Sjsg cfgcr1_reg = ICL_DPLL_CFGCR1(id); 3637c349dbc7Sjsg } 3638c349dbc7Sjsg } 3639c349dbc7Sjsg 3640c349dbc7Sjsg intel_de_write(dev_priv, cfgcr0_reg, hw_state->cfgcr0); 3641c349dbc7Sjsg intel_de_write(dev_priv, cfgcr1_reg, hw_state->cfgcr1); 36421bb76ff1Sjsg drm_WARN_ON_ONCE(&dev_priv->drm, dev_priv->display.vbt.override_afc_startup && 36431bb76ff1Sjsg !i915_mmio_reg_valid(div0_reg)); 36441bb76ff1Sjsg if (dev_priv->display.vbt.override_afc_startup && 36451bb76ff1Sjsg i915_mmio_reg_valid(div0_reg)) 3646f005ef32Sjsg intel_de_rmw(dev_priv, div0_reg, 3647f005ef32Sjsg TGL_DPLL0_DIV0_AFC_STARTUP_MASK, hw_state->div0); 3648c349dbc7Sjsg intel_de_posting_read(dev_priv, cfgcr1_reg); 3649c349dbc7Sjsg } 3650c349dbc7Sjsg 3651c349dbc7Sjsg static void icl_mg_pll_write(struct drm_i915_private *dev_priv, 3652c349dbc7Sjsg struct intel_shared_dpll *pll) 3653c349dbc7Sjsg { 3654c349dbc7Sjsg struct intel_dpll_hw_state *hw_state = &pll->state.hw_state; 3655c349dbc7Sjsg enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id); 3656c349dbc7Sjsg 3657c349dbc7Sjsg /* 3658c349dbc7Sjsg * Some of the following registers have reserved fields, so program 3659c349dbc7Sjsg * these with RMW based on a mask. The mask can be fixed or generated 3660c349dbc7Sjsg * during the calc/readout phase if the mask depends on some other HW 3661c349dbc7Sjsg * state like refclk, see icl_calc_mg_pll_state(). 3662c349dbc7Sjsg */ 3663f005ef32Sjsg intel_de_rmw(dev_priv, MG_REFCLKIN_CTL(tc_port), 3664f005ef32Sjsg MG_REFCLKIN_CTL_OD_2_MUX_MASK, hw_state->mg_refclkin_ctl); 3665c349dbc7Sjsg 3666f005ef32Sjsg intel_de_rmw(dev_priv, MG_CLKTOP2_CORECLKCTL1(tc_port), 3667f005ef32Sjsg MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK, 3668f005ef32Sjsg hw_state->mg_clktop2_coreclkctl1); 3669c349dbc7Sjsg 3670f005ef32Sjsg intel_de_rmw(dev_priv, MG_CLKTOP2_HSCLKCTL(tc_port), 3671f005ef32Sjsg MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK | 3672c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK | 3673c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK | 3674f005ef32Sjsg MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK, 3675f005ef32Sjsg hw_state->mg_clktop2_hsclkctl); 3676c349dbc7Sjsg 3677c349dbc7Sjsg intel_de_write(dev_priv, MG_PLL_DIV0(tc_port), hw_state->mg_pll_div0); 3678c349dbc7Sjsg intel_de_write(dev_priv, MG_PLL_DIV1(tc_port), hw_state->mg_pll_div1); 3679c349dbc7Sjsg intel_de_write(dev_priv, MG_PLL_LF(tc_port), hw_state->mg_pll_lf); 3680c349dbc7Sjsg intel_de_write(dev_priv, MG_PLL_FRAC_LOCK(tc_port), 3681c349dbc7Sjsg hw_state->mg_pll_frac_lock); 3682c349dbc7Sjsg intel_de_write(dev_priv, MG_PLL_SSC(tc_port), hw_state->mg_pll_ssc); 3683c349dbc7Sjsg 3684f005ef32Sjsg intel_de_rmw(dev_priv, MG_PLL_BIAS(tc_port), 3685f005ef32Sjsg hw_state->mg_pll_bias_mask, hw_state->mg_pll_bias); 3686c349dbc7Sjsg 3687f005ef32Sjsg intel_de_rmw(dev_priv, MG_PLL_TDC_COLDST_BIAS(tc_port), 3688f005ef32Sjsg hw_state->mg_pll_tdc_coldst_bias_mask, 3689f005ef32Sjsg hw_state->mg_pll_tdc_coldst_bias); 3690c349dbc7Sjsg 3691c349dbc7Sjsg intel_de_posting_read(dev_priv, MG_PLL_TDC_COLDST_BIAS(tc_port)); 3692c349dbc7Sjsg } 3693c349dbc7Sjsg 3694c349dbc7Sjsg static void dkl_pll_write(struct drm_i915_private *dev_priv, 3695c349dbc7Sjsg struct intel_shared_dpll *pll) 3696c349dbc7Sjsg { 3697c349dbc7Sjsg struct intel_dpll_hw_state *hw_state = &pll->state.hw_state; 3698c349dbc7Sjsg enum tc_port tc_port = icl_pll_id_to_tc_port(pll->info->id); 3699c349dbc7Sjsg u32 val; 3700c349dbc7Sjsg 3701c349dbc7Sjsg /* 3702c349dbc7Sjsg * All registers programmed here have the same HIP_INDEX_REG even 3703c349dbc7Sjsg * though on different building block 3704c349dbc7Sjsg */ 3705c349dbc7Sjsg /* All the registers are RMW */ 3706f005ef32Sjsg val = intel_dkl_phy_read(dev_priv, DKL_REFCLKIN_CTL(tc_port)); 3707c349dbc7Sjsg val &= ~MG_REFCLKIN_CTL_OD_2_MUX_MASK; 3708c349dbc7Sjsg val |= hw_state->mg_refclkin_ctl; 3709f005ef32Sjsg intel_dkl_phy_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), val); 3710c349dbc7Sjsg 3711f005ef32Sjsg val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port)); 3712c349dbc7Sjsg val &= ~MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK; 3713c349dbc7Sjsg val |= hw_state->mg_clktop2_coreclkctl1; 3714f005ef32Sjsg intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), val); 3715c349dbc7Sjsg 3716f005ef32Sjsg val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port)); 3717c349dbc7Sjsg val &= ~(MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK | 3718c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK | 3719c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK | 3720c349dbc7Sjsg MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK); 3721c349dbc7Sjsg val |= hw_state->mg_clktop2_hsclkctl; 3722f005ef32Sjsg intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), val); 3723c349dbc7Sjsg 37241bb76ff1Sjsg val = DKL_PLL_DIV0_MASK; 37251bb76ff1Sjsg if (dev_priv->display.vbt.override_afc_startup) 37261bb76ff1Sjsg val |= DKL_PLL_DIV0_AFC_STARTUP_MASK; 3727f005ef32Sjsg intel_dkl_phy_rmw(dev_priv, DKL_PLL_DIV0(tc_port), val, 37281bb76ff1Sjsg hw_state->mg_pll_div0); 3729c349dbc7Sjsg 3730f005ef32Sjsg val = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port)); 3731c349dbc7Sjsg val &= ~(DKL_PLL_DIV1_IREF_TRIM_MASK | 3732c349dbc7Sjsg DKL_PLL_DIV1_TDC_TARGET_CNT_MASK); 3733c349dbc7Sjsg val |= hw_state->mg_pll_div1; 3734f005ef32Sjsg intel_dkl_phy_write(dev_priv, DKL_PLL_DIV1(tc_port), val); 3735c349dbc7Sjsg 3736f005ef32Sjsg val = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port)); 3737c349dbc7Sjsg val &= ~(DKL_PLL_SSC_IREF_NDIV_RATIO_MASK | 3738c349dbc7Sjsg DKL_PLL_SSC_STEP_LEN_MASK | 3739c349dbc7Sjsg DKL_PLL_SSC_STEP_NUM_MASK | 3740c349dbc7Sjsg DKL_PLL_SSC_EN); 3741c349dbc7Sjsg val |= hw_state->mg_pll_ssc; 3742f005ef32Sjsg intel_dkl_phy_write(dev_priv, DKL_PLL_SSC(tc_port), val); 3743c349dbc7Sjsg 3744f005ef32Sjsg val = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port)); 3745c349dbc7Sjsg val &= ~(DKL_PLL_BIAS_FRAC_EN_H | 3746c349dbc7Sjsg DKL_PLL_BIAS_FBDIV_FRAC_MASK); 3747c349dbc7Sjsg val |= hw_state->mg_pll_bias; 3748f005ef32Sjsg intel_dkl_phy_write(dev_priv, DKL_PLL_BIAS(tc_port), val); 3749c349dbc7Sjsg 3750f005ef32Sjsg val = intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); 3751c349dbc7Sjsg val &= ~(DKL_PLL_TDC_SSC_STEP_SIZE_MASK | 3752c349dbc7Sjsg DKL_PLL_TDC_FEED_FWD_GAIN_MASK); 3753c349dbc7Sjsg val |= hw_state->mg_pll_tdc_coldst_bias; 3754f005ef32Sjsg intel_dkl_phy_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), val); 3755c349dbc7Sjsg 3756f005ef32Sjsg intel_dkl_phy_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port)); 3757c349dbc7Sjsg } 3758c349dbc7Sjsg 3759c349dbc7Sjsg static void icl_pll_power_enable(struct drm_i915_private *dev_priv, 3760c349dbc7Sjsg struct intel_shared_dpll *pll, 3761c349dbc7Sjsg i915_reg_t enable_reg) 3762c349dbc7Sjsg { 3763f005ef32Sjsg intel_de_rmw(dev_priv, enable_reg, 0, PLL_POWER_ENABLE); 3764c349dbc7Sjsg 3765c349dbc7Sjsg /* 3766c349dbc7Sjsg * The spec says we need to "wait" but it also says it should be 3767c349dbc7Sjsg * immediate. 3768c349dbc7Sjsg */ 3769c349dbc7Sjsg if (intel_de_wait_for_set(dev_priv, enable_reg, PLL_POWER_STATE, 1)) 3770c349dbc7Sjsg drm_err(&dev_priv->drm, "PLL %d Power not enabled\n", 3771c349dbc7Sjsg pll->info->id); 3772c349dbc7Sjsg } 3773c349dbc7Sjsg 3774c349dbc7Sjsg static void icl_pll_enable(struct drm_i915_private *dev_priv, 3775c349dbc7Sjsg struct intel_shared_dpll *pll, 3776c349dbc7Sjsg i915_reg_t enable_reg) 3777c349dbc7Sjsg { 3778f005ef32Sjsg intel_de_rmw(dev_priv, enable_reg, 0, PLL_ENABLE); 3779c349dbc7Sjsg 3780c349dbc7Sjsg /* Timeout is actually 600us. */ 3781c349dbc7Sjsg if (intel_de_wait_for_set(dev_priv, enable_reg, PLL_LOCK, 1)) 3782c349dbc7Sjsg drm_err(&dev_priv->drm, "PLL %d not locked\n", pll->info->id); 3783c349dbc7Sjsg } 3784c349dbc7Sjsg 37855ca02815Sjsg static void adlp_cmtg_clock_gating_wa(struct drm_i915_private *i915, struct intel_shared_dpll *pll) 37865ca02815Sjsg { 37875ca02815Sjsg u32 val; 37885ca02815Sjsg 3789f005ef32Sjsg if (!(IS_ALDERLAKE_P(i915) && IS_DISPLAY_STEP(i915, STEP_A0, STEP_B0)) || 37905ca02815Sjsg pll->info->id != DPLL_ID_ICL_DPLL0) 37915ca02815Sjsg return; 37925ca02815Sjsg /* 37935ca02815Sjsg * Wa_16011069516:adl-p[a0] 37945ca02815Sjsg * 37955ca02815Sjsg * All CMTG regs are unreliable until CMTG clock gating is disabled, 37965ca02815Sjsg * so we can only assume the default TRANS_CMTG_CHICKEN reg value and 37975ca02815Sjsg * sanity check this assumption with a double read, which presumably 37985ca02815Sjsg * returns the correct value even with clock gating on. 37995ca02815Sjsg * 38005ca02815Sjsg * Instead of the usual place for workarounds we apply this one here, 38015ca02815Sjsg * since TRANS_CMTG_CHICKEN is only accessible while DPLL0 is enabled. 38025ca02815Sjsg */ 38035ca02815Sjsg val = intel_de_read(i915, TRANS_CMTG_CHICKEN); 3804f005ef32Sjsg val = intel_de_rmw(i915, TRANS_CMTG_CHICKEN, ~0, DISABLE_DPT_CLK_GATING); 38055ca02815Sjsg if (drm_WARN_ON(&i915->drm, val & ~DISABLE_DPT_CLK_GATING)) 38065ca02815Sjsg drm_dbg_kms(&i915->drm, "Unexpected flags in TRANS_CMTG_CHICKEN: %08x\n", val); 38075ca02815Sjsg } 38085ca02815Sjsg 3809c349dbc7Sjsg static void combo_pll_enable(struct drm_i915_private *dev_priv, 3810c349dbc7Sjsg struct intel_shared_dpll *pll) 3811c349dbc7Sjsg { 3812ad8b1aafSjsg i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll); 3813c349dbc7Sjsg 3814f005ef32Sjsg if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && 3815c349dbc7Sjsg pll->info->id == DPLL_ID_EHL_DPLL4) { 3816c349dbc7Sjsg 3817c349dbc7Sjsg /* 3818c349dbc7Sjsg * We need to disable DC states when this DPLL is enabled. 3819c349dbc7Sjsg * This can be done by taking a reference on DPLL4 power 3820c349dbc7Sjsg * domain. 3821c349dbc7Sjsg */ 3822c349dbc7Sjsg pll->wakeref = intel_display_power_get(dev_priv, 38231bb76ff1Sjsg POWER_DOMAIN_DC_OFF); 3824c349dbc7Sjsg } 3825c349dbc7Sjsg 3826c349dbc7Sjsg icl_pll_power_enable(dev_priv, pll, enable_reg); 3827c349dbc7Sjsg 3828c349dbc7Sjsg icl_dpll_write(dev_priv, pll); 3829c349dbc7Sjsg 3830c349dbc7Sjsg /* 3831c349dbc7Sjsg * DVFS pre sequence would be here, but in our driver the cdclk code 3832c349dbc7Sjsg * paths should already be setting the appropriate voltage, hence we do 3833c349dbc7Sjsg * nothing here. 3834c349dbc7Sjsg */ 3835c349dbc7Sjsg 3836c349dbc7Sjsg icl_pll_enable(dev_priv, pll, enable_reg); 3837c349dbc7Sjsg 38385ca02815Sjsg adlp_cmtg_clock_gating_wa(dev_priv, pll); 38395ca02815Sjsg 3840c349dbc7Sjsg /* DVFS post sequence would be here. See the comment above. */ 3841c349dbc7Sjsg } 3842c349dbc7Sjsg 3843c349dbc7Sjsg static void tbt_pll_enable(struct drm_i915_private *dev_priv, 3844c349dbc7Sjsg struct intel_shared_dpll *pll) 3845c349dbc7Sjsg { 3846c349dbc7Sjsg icl_pll_power_enable(dev_priv, pll, TBT_PLL_ENABLE); 3847c349dbc7Sjsg 3848c349dbc7Sjsg icl_dpll_write(dev_priv, pll); 3849c349dbc7Sjsg 3850c349dbc7Sjsg /* 3851c349dbc7Sjsg * DVFS pre sequence would be here, but in our driver the cdclk code 3852c349dbc7Sjsg * paths should already be setting the appropriate voltage, hence we do 3853c349dbc7Sjsg * nothing here. 3854c349dbc7Sjsg */ 3855c349dbc7Sjsg 3856c349dbc7Sjsg icl_pll_enable(dev_priv, pll, TBT_PLL_ENABLE); 3857c349dbc7Sjsg 3858c349dbc7Sjsg /* DVFS post sequence would be here. See the comment above. */ 3859c349dbc7Sjsg } 3860c349dbc7Sjsg 3861c349dbc7Sjsg static void mg_pll_enable(struct drm_i915_private *dev_priv, 3862c349dbc7Sjsg struct intel_shared_dpll *pll) 3863c349dbc7Sjsg { 38645ca02815Sjsg i915_reg_t enable_reg = intel_tc_pll_enable_reg(dev_priv, pll); 3865c349dbc7Sjsg 3866c349dbc7Sjsg icl_pll_power_enable(dev_priv, pll, enable_reg); 3867c349dbc7Sjsg 38685ca02815Sjsg if (DISPLAY_VER(dev_priv) >= 12) 3869c349dbc7Sjsg dkl_pll_write(dev_priv, pll); 3870c349dbc7Sjsg else 3871c349dbc7Sjsg icl_mg_pll_write(dev_priv, pll); 3872c349dbc7Sjsg 3873c349dbc7Sjsg /* 3874c349dbc7Sjsg * DVFS pre sequence would be here, but in our driver the cdclk code 3875c349dbc7Sjsg * paths should already be setting the appropriate voltage, hence we do 3876c349dbc7Sjsg * nothing here. 3877c349dbc7Sjsg */ 3878c349dbc7Sjsg 3879c349dbc7Sjsg icl_pll_enable(dev_priv, pll, enable_reg); 3880c349dbc7Sjsg 3881c349dbc7Sjsg /* DVFS post sequence would be here. See the comment above. */ 3882c349dbc7Sjsg } 3883c349dbc7Sjsg 3884c349dbc7Sjsg static void icl_pll_disable(struct drm_i915_private *dev_priv, 3885c349dbc7Sjsg struct intel_shared_dpll *pll, 3886c349dbc7Sjsg i915_reg_t enable_reg) 3887c349dbc7Sjsg { 3888c349dbc7Sjsg /* The first steps are done by intel_ddi_post_disable(). */ 3889c349dbc7Sjsg 3890c349dbc7Sjsg /* 3891c349dbc7Sjsg * DVFS pre sequence would be here, but in our driver the cdclk code 3892c349dbc7Sjsg * paths should already be setting the appropriate voltage, hence we do 38935ca02815Sjsg * nothing here. 3894c349dbc7Sjsg */ 3895c349dbc7Sjsg 3896f005ef32Sjsg intel_de_rmw(dev_priv, enable_reg, PLL_ENABLE, 0); 3897c349dbc7Sjsg 3898c349dbc7Sjsg /* Timeout is actually 1us. */ 3899c349dbc7Sjsg if (intel_de_wait_for_clear(dev_priv, enable_reg, PLL_LOCK, 1)) 3900c349dbc7Sjsg drm_err(&dev_priv->drm, "PLL %d locked\n", pll->info->id); 3901c349dbc7Sjsg 3902c349dbc7Sjsg /* DVFS post sequence would be here. See the comment above. */ 3903c349dbc7Sjsg 3904f005ef32Sjsg intel_de_rmw(dev_priv, enable_reg, PLL_POWER_ENABLE, 0); 3905c349dbc7Sjsg 3906c349dbc7Sjsg /* 3907c349dbc7Sjsg * The spec says we need to "wait" but it also says it should be 3908c349dbc7Sjsg * immediate. 3909c349dbc7Sjsg */ 3910c349dbc7Sjsg if (intel_de_wait_for_clear(dev_priv, enable_reg, PLL_POWER_STATE, 1)) 3911c349dbc7Sjsg drm_err(&dev_priv->drm, "PLL %d Power not disabled\n", 3912c349dbc7Sjsg pll->info->id); 3913c349dbc7Sjsg } 3914c349dbc7Sjsg 3915c349dbc7Sjsg static void combo_pll_disable(struct drm_i915_private *dev_priv, 3916c349dbc7Sjsg struct intel_shared_dpll *pll) 3917c349dbc7Sjsg { 3918ad8b1aafSjsg i915_reg_t enable_reg = intel_combo_pll_enable_reg(dev_priv, pll); 3919ad8b1aafSjsg 3920ad8b1aafSjsg icl_pll_disable(dev_priv, pll, enable_reg); 3921c349dbc7Sjsg 3922f005ef32Sjsg if ((IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) && 3923ad8b1aafSjsg pll->info->id == DPLL_ID_EHL_DPLL4) 39241bb76ff1Sjsg intel_display_power_put(dev_priv, POWER_DOMAIN_DC_OFF, 3925c349dbc7Sjsg pll->wakeref); 3926c349dbc7Sjsg } 3927c349dbc7Sjsg 3928c349dbc7Sjsg static void tbt_pll_disable(struct drm_i915_private *dev_priv, 3929c349dbc7Sjsg struct intel_shared_dpll *pll) 3930c349dbc7Sjsg { 3931c349dbc7Sjsg icl_pll_disable(dev_priv, pll, TBT_PLL_ENABLE); 3932c349dbc7Sjsg } 3933c349dbc7Sjsg 3934c349dbc7Sjsg static void mg_pll_disable(struct drm_i915_private *dev_priv, 3935c349dbc7Sjsg struct intel_shared_dpll *pll) 3936c349dbc7Sjsg { 39375ca02815Sjsg i915_reg_t enable_reg = intel_tc_pll_enable_reg(dev_priv, pll); 3938c349dbc7Sjsg 3939c349dbc7Sjsg icl_pll_disable(dev_priv, pll, enable_reg); 3940c349dbc7Sjsg } 3941c349dbc7Sjsg 3942c349dbc7Sjsg static void icl_update_dpll_ref_clks(struct drm_i915_private *i915) 3943c349dbc7Sjsg { 3944c349dbc7Sjsg /* No SSC ref */ 39451bb76ff1Sjsg i915->display.dpll.ref_clks.nssc = i915->display.cdclk.hw.ref; 3946c349dbc7Sjsg } 3947c349dbc7Sjsg 3948c349dbc7Sjsg static void icl_dump_hw_state(struct drm_i915_private *dev_priv, 3949c349dbc7Sjsg const struct intel_dpll_hw_state *hw_state) 3950c349dbc7Sjsg { 3951c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, 39521bb76ff1Sjsg "dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, div0: 0x%x, " 3953c349dbc7Sjsg "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, " 3954c349dbc7Sjsg "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, " 3955c349dbc7Sjsg "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, " 3956c349dbc7Sjsg "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, " 3957c349dbc7Sjsg "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n", 3958c349dbc7Sjsg hw_state->cfgcr0, hw_state->cfgcr1, 39591bb76ff1Sjsg hw_state->div0, 3960c349dbc7Sjsg hw_state->mg_refclkin_ctl, 3961c349dbc7Sjsg hw_state->mg_clktop2_coreclkctl1, 3962c349dbc7Sjsg hw_state->mg_clktop2_hsclkctl, 3963c349dbc7Sjsg hw_state->mg_pll_div0, 3964c349dbc7Sjsg hw_state->mg_pll_div1, 3965c349dbc7Sjsg hw_state->mg_pll_lf, 3966c349dbc7Sjsg hw_state->mg_pll_frac_lock, 3967c349dbc7Sjsg hw_state->mg_pll_ssc, 3968c349dbc7Sjsg hw_state->mg_pll_bias, 3969c349dbc7Sjsg hw_state->mg_pll_tdc_coldst_bias); 3970c349dbc7Sjsg } 3971c349dbc7Sjsg 3972c349dbc7Sjsg static const struct intel_shared_dpll_funcs combo_pll_funcs = { 3973c349dbc7Sjsg .enable = combo_pll_enable, 3974c349dbc7Sjsg .disable = combo_pll_disable, 3975c349dbc7Sjsg .get_hw_state = combo_pll_get_hw_state, 3976c349dbc7Sjsg .get_freq = icl_ddi_combo_pll_get_freq, 3977c349dbc7Sjsg }; 3978c349dbc7Sjsg 3979c349dbc7Sjsg static const struct intel_shared_dpll_funcs tbt_pll_funcs = { 3980c349dbc7Sjsg .enable = tbt_pll_enable, 3981c349dbc7Sjsg .disable = tbt_pll_disable, 3982c349dbc7Sjsg .get_hw_state = tbt_pll_get_hw_state, 3983c349dbc7Sjsg .get_freq = icl_ddi_tbt_pll_get_freq, 3984c349dbc7Sjsg }; 3985c349dbc7Sjsg 3986c349dbc7Sjsg static const struct intel_shared_dpll_funcs mg_pll_funcs = { 3987c349dbc7Sjsg .enable = mg_pll_enable, 3988c349dbc7Sjsg .disable = mg_pll_disable, 3989c349dbc7Sjsg .get_hw_state = mg_pll_get_hw_state, 3990c349dbc7Sjsg .get_freq = icl_ddi_mg_pll_get_freq, 3991c349dbc7Sjsg }; 3992c349dbc7Sjsg 3993c349dbc7Sjsg static const struct dpll_info icl_plls[] = { 3994c349dbc7Sjsg { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, 3995c349dbc7Sjsg { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, 3996c349dbc7Sjsg { "TBT PLL", &tbt_pll_funcs, DPLL_ID_ICL_TBTPLL, 0 }, 3997c349dbc7Sjsg { "MG PLL 1", &mg_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 }, 3998c349dbc7Sjsg { "MG PLL 2", &mg_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 }, 3999c349dbc7Sjsg { "MG PLL 3", &mg_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 }, 4000c349dbc7Sjsg { "MG PLL 4", &mg_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 }, 4001c349dbc7Sjsg { }, 4002c349dbc7Sjsg }; 4003c349dbc7Sjsg 4004c349dbc7Sjsg static const struct intel_dpll_mgr icl_pll_mgr = { 4005c349dbc7Sjsg .dpll_info = icl_plls, 40061bb76ff1Sjsg .compute_dplls = icl_compute_dplls, 4007c349dbc7Sjsg .get_dplls = icl_get_dplls, 4008c349dbc7Sjsg .put_dplls = icl_put_dplls, 4009c349dbc7Sjsg .update_active_dpll = icl_update_active_dpll, 4010c349dbc7Sjsg .update_ref_clks = icl_update_dpll_ref_clks, 4011c349dbc7Sjsg .dump_hw_state = icl_dump_hw_state, 4012c349dbc7Sjsg }; 4013c349dbc7Sjsg 4014c349dbc7Sjsg static const struct dpll_info ehl_plls[] = { 4015c349dbc7Sjsg { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, 4016c349dbc7Sjsg { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, 4017c349dbc7Sjsg { "DPLL 4", &combo_pll_funcs, DPLL_ID_EHL_DPLL4, 0 }, 4018c349dbc7Sjsg { }, 4019c349dbc7Sjsg }; 4020c349dbc7Sjsg 4021c349dbc7Sjsg static const struct intel_dpll_mgr ehl_pll_mgr = { 4022c349dbc7Sjsg .dpll_info = ehl_plls, 40231bb76ff1Sjsg .compute_dplls = icl_compute_dplls, 4024c349dbc7Sjsg .get_dplls = icl_get_dplls, 4025c349dbc7Sjsg .put_dplls = icl_put_dplls, 4026c349dbc7Sjsg .update_ref_clks = icl_update_dpll_ref_clks, 4027c349dbc7Sjsg .dump_hw_state = icl_dump_hw_state, 4028c349dbc7Sjsg }; 4029c349dbc7Sjsg 4030c349dbc7Sjsg static const struct intel_shared_dpll_funcs dkl_pll_funcs = { 4031c349dbc7Sjsg .enable = mg_pll_enable, 4032c349dbc7Sjsg .disable = mg_pll_disable, 4033c349dbc7Sjsg .get_hw_state = dkl_pll_get_hw_state, 4034c349dbc7Sjsg .get_freq = icl_ddi_mg_pll_get_freq, 4035c349dbc7Sjsg }; 4036c349dbc7Sjsg 4037c349dbc7Sjsg static const struct dpll_info tgl_plls[] = { 4038c349dbc7Sjsg { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, 4039c349dbc7Sjsg { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, 4040c349dbc7Sjsg { "TBT PLL", &tbt_pll_funcs, DPLL_ID_ICL_TBTPLL, 0 }, 4041c349dbc7Sjsg { "TC PLL 1", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 }, 4042c349dbc7Sjsg { "TC PLL 2", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 }, 4043c349dbc7Sjsg { "TC PLL 3", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 }, 4044c349dbc7Sjsg { "TC PLL 4", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 }, 4045c349dbc7Sjsg { "TC PLL 5", &dkl_pll_funcs, DPLL_ID_TGL_MGPLL5, 0 }, 4046c349dbc7Sjsg { "TC PLL 6", &dkl_pll_funcs, DPLL_ID_TGL_MGPLL6, 0 }, 4047c349dbc7Sjsg { }, 4048c349dbc7Sjsg }; 4049c349dbc7Sjsg 4050c349dbc7Sjsg static const struct intel_dpll_mgr tgl_pll_mgr = { 4051c349dbc7Sjsg .dpll_info = tgl_plls, 40521bb76ff1Sjsg .compute_dplls = icl_compute_dplls, 4053c349dbc7Sjsg .get_dplls = icl_get_dplls, 4054c349dbc7Sjsg .put_dplls = icl_put_dplls, 4055c349dbc7Sjsg .update_active_dpll = icl_update_active_dpll, 4056c349dbc7Sjsg .update_ref_clks = icl_update_dpll_ref_clks, 4057c349dbc7Sjsg .dump_hw_state = icl_dump_hw_state, 4058c349dbc7Sjsg }; 4059c349dbc7Sjsg 4060ad8b1aafSjsg static const struct dpll_info rkl_plls[] = { 4061ad8b1aafSjsg { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, 4062ad8b1aafSjsg { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, 4063ad8b1aafSjsg { "DPLL 4", &combo_pll_funcs, DPLL_ID_EHL_DPLL4, 0 }, 4064ad8b1aafSjsg { }, 4065ad8b1aafSjsg }; 4066ad8b1aafSjsg 4067ad8b1aafSjsg static const struct intel_dpll_mgr rkl_pll_mgr = { 4068ad8b1aafSjsg .dpll_info = rkl_plls, 40691bb76ff1Sjsg .compute_dplls = icl_compute_dplls, 4070ad8b1aafSjsg .get_dplls = icl_get_dplls, 4071ad8b1aafSjsg .put_dplls = icl_put_dplls, 4072ad8b1aafSjsg .update_ref_clks = icl_update_dpll_ref_clks, 4073ad8b1aafSjsg .dump_hw_state = icl_dump_hw_state, 4074ad8b1aafSjsg }; 4075ad8b1aafSjsg 40765ca02815Sjsg static const struct dpll_info dg1_plls[] = { 40775ca02815Sjsg { "DPLL 0", &combo_pll_funcs, DPLL_ID_DG1_DPLL0, 0 }, 40785ca02815Sjsg { "DPLL 1", &combo_pll_funcs, DPLL_ID_DG1_DPLL1, 0 }, 40795ca02815Sjsg { "DPLL 2", &combo_pll_funcs, DPLL_ID_DG1_DPLL2, 0 }, 40805ca02815Sjsg { "DPLL 3", &combo_pll_funcs, DPLL_ID_DG1_DPLL3, 0 }, 40815ca02815Sjsg { }, 40825ca02815Sjsg }; 40835ca02815Sjsg 40845ca02815Sjsg static const struct intel_dpll_mgr dg1_pll_mgr = { 40855ca02815Sjsg .dpll_info = dg1_plls, 40861bb76ff1Sjsg .compute_dplls = icl_compute_dplls, 40875ca02815Sjsg .get_dplls = icl_get_dplls, 40885ca02815Sjsg .put_dplls = icl_put_dplls, 40895ca02815Sjsg .update_ref_clks = icl_update_dpll_ref_clks, 40905ca02815Sjsg .dump_hw_state = icl_dump_hw_state, 40915ca02815Sjsg }; 40925ca02815Sjsg 40935ca02815Sjsg static const struct dpll_info adls_plls[] = { 40945ca02815Sjsg { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, 40955ca02815Sjsg { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, 40965ca02815Sjsg { "DPLL 2", &combo_pll_funcs, DPLL_ID_DG1_DPLL2, 0 }, 40975ca02815Sjsg { "DPLL 3", &combo_pll_funcs, DPLL_ID_DG1_DPLL3, 0 }, 40985ca02815Sjsg { }, 40995ca02815Sjsg }; 41005ca02815Sjsg 41015ca02815Sjsg static const struct intel_dpll_mgr adls_pll_mgr = { 41025ca02815Sjsg .dpll_info = adls_plls, 41031bb76ff1Sjsg .compute_dplls = icl_compute_dplls, 41045ca02815Sjsg .get_dplls = icl_get_dplls, 41055ca02815Sjsg .put_dplls = icl_put_dplls, 41065ca02815Sjsg .update_ref_clks = icl_update_dpll_ref_clks, 41075ca02815Sjsg .dump_hw_state = icl_dump_hw_state, 41085ca02815Sjsg }; 41095ca02815Sjsg 41105ca02815Sjsg static const struct dpll_info adlp_plls[] = { 41115ca02815Sjsg { "DPLL 0", &combo_pll_funcs, DPLL_ID_ICL_DPLL0, 0 }, 41125ca02815Sjsg { "DPLL 1", &combo_pll_funcs, DPLL_ID_ICL_DPLL1, 0 }, 41135ca02815Sjsg { "TBT PLL", &tbt_pll_funcs, DPLL_ID_ICL_TBTPLL, 0 }, 41145ca02815Sjsg { "TC PLL 1", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 }, 41155ca02815Sjsg { "TC PLL 2", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 }, 41165ca02815Sjsg { "TC PLL 3", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 }, 41175ca02815Sjsg { "TC PLL 4", &dkl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 }, 41185ca02815Sjsg { }, 41195ca02815Sjsg }; 41205ca02815Sjsg 41215ca02815Sjsg static const struct intel_dpll_mgr adlp_pll_mgr = { 41225ca02815Sjsg .dpll_info = adlp_plls, 41231bb76ff1Sjsg .compute_dplls = icl_compute_dplls, 41245ca02815Sjsg .get_dplls = icl_get_dplls, 41255ca02815Sjsg .put_dplls = icl_put_dplls, 41265ca02815Sjsg .update_active_dpll = icl_update_active_dpll, 41275ca02815Sjsg .update_ref_clks = icl_update_dpll_ref_clks, 41285ca02815Sjsg .dump_hw_state = icl_dump_hw_state, 41295ca02815Sjsg }; 41305ca02815Sjsg 4131c349dbc7Sjsg /** 4132c349dbc7Sjsg * intel_shared_dpll_init - Initialize shared DPLLs 41331bb76ff1Sjsg * @dev_priv: i915 device 4134c349dbc7Sjsg * 41351bb76ff1Sjsg * Initialize shared DPLLs for @dev_priv. 4136c349dbc7Sjsg */ 41371bb76ff1Sjsg void intel_shared_dpll_init(struct drm_i915_private *dev_priv) 4138c349dbc7Sjsg { 4139c349dbc7Sjsg const struct intel_dpll_mgr *dpll_mgr = NULL; 4140c349dbc7Sjsg const struct dpll_info *dpll_info; 4141c349dbc7Sjsg int i; 4142c349dbc7Sjsg 4143f005ef32Sjsg rw_init(&dev_priv->display.dpll.lock, "dplllk"); 4144f005ef32Sjsg 4145f005ef32Sjsg if (DISPLAY_VER(dev_priv) >= 14 || IS_DG2(dev_priv)) 41465ca02815Sjsg /* No shared DPLLs on DG2; port PLLs are part of the PHY */ 41475ca02815Sjsg dpll_mgr = NULL; 41485ca02815Sjsg else if (IS_ALDERLAKE_P(dev_priv)) 41495ca02815Sjsg dpll_mgr = &adlp_pll_mgr; 41505ca02815Sjsg else if (IS_ALDERLAKE_S(dev_priv)) 41515ca02815Sjsg dpll_mgr = &adls_pll_mgr; 41525ca02815Sjsg else if (IS_DG1(dev_priv)) 41535ca02815Sjsg dpll_mgr = &dg1_pll_mgr; 41545ca02815Sjsg else if (IS_ROCKETLAKE(dev_priv)) 4155ad8b1aafSjsg dpll_mgr = &rkl_pll_mgr; 41565ca02815Sjsg else if (DISPLAY_VER(dev_priv) >= 12) 4157c349dbc7Sjsg dpll_mgr = &tgl_pll_mgr; 4158f005ef32Sjsg else if (IS_JASPERLAKE(dev_priv) || IS_ELKHARTLAKE(dev_priv)) 4159c349dbc7Sjsg dpll_mgr = &ehl_pll_mgr; 41605ca02815Sjsg else if (DISPLAY_VER(dev_priv) >= 11) 4161c349dbc7Sjsg dpll_mgr = &icl_pll_mgr; 41625ca02815Sjsg else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) 4163c349dbc7Sjsg dpll_mgr = &bxt_pll_mgr; 41645ca02815Sjsg else if (DISPLAY_VER(dev_priv) == 9) 41655ca02815Sjsg dpll_mgr = &skl_pll_mgr; 4166c349dbc7Sjsg else if (HAS_DDI(dev_priv)) 4167c349dbc7Sjsg dpll_mgr = &hsw_pll_mgr; 4168c349dbc7Sjsg else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) 4169c349dbc7Sjsg dpll_mgr = &pch_pll_mgr; 4170c349dbc7Sjsg 4171c349dbc7Sjsg if (!dpll_mgr) { 41721bb76ff1Sjsg dev_priv->display.dpll.num_shared_dpll = 0; 4173c349dbc7Sjsg return; 4174c349dbc7Sjsg } 4175c349dbc7Sjsg 4176c349dbc7Sjsg dpll_info = dpll_mgr->dpll_info; 4177c349dbc7Sjsg 4178c349dbc7Sjsg for (i = 0; dpll_info[i].name; i++) { 41791bb76ff1Sjsg if (drm_WARN_ON(&dev_priv->drm, 41801bb76ff1Sjsg i >= ARRAY_SIZE(dev_priv->display.dpll.shared_dplls))) 41811bb76ff1Sjsg break; 41821bb76ff1Sjsg 41831bb76ff1Sjsg drm_WARN_ON(&dev_priv->drm, i != dpll_info[i].id); 41841bb76ff1Sjsg dev_priv->display.dpll.shared_dplls[i].info = &dpll_info[i]; 4185c349dbc7Sjsg } 4186c349dbc7Sjsg 41871bb76ff1Sjsg dev_priv->display.dpll.mgr = dpll_mgr; 41881bb76ff1Sjsg dev_priv->display.dpll.num_shared_dpll = i; 41891bb76ff1Sjsg } 4190c349dbc7Sjsg 41911bb76ff1Sjsg /** 41921bb76ff1Sjsg * intel_compute_shared_dplls - compute DPLL state CRTC and encoder combination 41931bb76ff1Sjsg * @state: atomic state 41941bb76ff1Sjsg * @crtc: CRTC to compute DPLLs for 41951bb76ff1Sjsg * @encoder: encoder 41961bb76ff1Sjsg * 41971bb76ff1Sjsg * This function computes the DPLL state for the given CRTC and encoder. 41981bb76ff1Sjsg * 41991bb76ff1Sjsg * The new configuration in the atomic commit @state is made effective by 42001bb76ff1Sjsg * calling intel_shared_dpll_swap_state(). 42011bb76ff1Sjsg * 42021bb76ff1Sjsg * Returns: 42031bb76ff1Sjsg * 0 on success, negative error code on falure. 42041bb76ff1Sjsg */ 42051bb76ff1Sjsg int intel_compute_shared_dplls(struct intel_atomic_state *state, 42061bb76ff1Sjsg struct intel_crtc *crtc, 42071bb76ff1Sjsg struct intel_encoder *encoder) 42081bb76ff1Sjsg { 42091bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(state->base.dev); 42101bb76ff1Sjsg const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr; 42111bb76ff1Sjsg 42121bb76ff1Sjsg if (drm_WARN_ON(&dev_priv->drm, !dpll_mgr)) 42131bb76ff1Sjsg return -EINVAL; 42141bb76ff1Sjsg 42151bb76ff1Sjsg return dpll_mgr->compute_dplls(state, crtc, encoder); 4216c349dbc7Sjsg } 4217c349dbc7Sjsg 4218c349dbc7Sjsg /** 4219c349dbc7Sjsg * intel_reserve_shared_dplls - reserve DPLLs for CRTC and encoder combination 4220c349dbc7Sjsg * @state: atomic state 4221c349dbc7Sjsg * @crtc: CRTC to reserve DPLLs for 4222c349dbc7Sjsg * @encoder: encoder 4223c349dbc7Sjsg * 4224c349dbc7Sjsg * This function reserves all required DPLLs for the given CRTC and encoder 4225c349dbc7Sjsg * combination in the current atomic commit @state and the new @crtc atomic 4226c349dbc7Sjsg * state. 4227c349dbc7Sjsg * 4228c349dbc7Sjsg * The new configuration in the atomic commit @state is made effective by 4229c349dbc7Sjsg * calling intel_shared_dpll_swap_state(). 4230c349dbc7Sjsg * 4231c349dbc7Sjsg * The reserved DPLLs should be released by calling 4232c349dbc7Sjsg * intel_release_shared_dplls(). 4233c349dbc7Sjsg * 4234c349dbc7Sjsg * Returns: 42351bb76ff1Sjsg * 0 if all required DPLLs were successfully reserved, 42361bb76ff1Sjsg * negative error code otherwise. 4237c349dbc7Sjsg */ 42381bb76ff1Sjsg int intel_reserve_shared_dplls(struct intel_atomic_state *state, 4239c349dbc7Sjsg struct intel_crtc *crtc, 4240c349dbc7Sjsg struct intel_encoder *encoder) 4241c349dbc7Sjsg { 4242c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(state->base.dev); 42431bb76ff1Sjsg const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr; 4244c349dbc7Sjsg 4245c349dbc7Sjsg if (drm_WARN_ON(&dev_priv->drm, !dpll_mgr)) 42461bb76ff1Sjsg return -EINVAL; 4247c349dbc7Sjsg 4248c349dbc7Sjsg return dpll_mgr->get_dplls(state, crtc, encoder); 4249c349dbc7Sjsg } 4250c349dbc7Sjsg 4251c349dbc7Sjsg /** 4252c349dbc7Sjsg * intel_release_shared_dplls - end use of DPLLs by CRTC in atomic state 4253c349dbc7Sjsg * @state: atomic state 4254c349dbc7Sjsg * @crtc: crtc from which the DPLLs are to be released 4255c349dbc7Sjsg * 4256c349dbc7Sjsg * This function releases all DPLLs reserved by intel_reserve_shared_dplls() 4257c349dbc7Sjsg * from the current atomic commit @state and the old @crtc atomic state. 4258c349dbc7Sjsg * 4259c349dbc7Sjsg * The new configuration in the atomic commit @state is made effective by 4260c349dbc7Sjsg * calling intel_shared_dpll_swap_state(). 4261c349dbc7Sjsg */ 4262c349dbc7Sjsg void intel_release_shared_dplls(struct intel_atomic_state *state, 4263c349dbc7Sjsg struct intel_crtc *crtc) 4264c349dbc7Sjsg { 4265c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(state->base.dev); 42661bb76ff1Sjsg const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr; 4267c349dbc7Sjsg 4268c349dbc7Sjsg /* 4269c349dbc7Sjsg * FIXME: this function is called for every platform having a 4270c349dbc7Sjsg * compute_clock hook, even though the platform doesn't yet support 4271c349dbc7Sjsg * the shared DPLL framework and intel_reserve_shared_dplls() is not 4272c349dbc7Sjsg * called on those. 4273c349dbc7Sjsg */ 4274c349dbc7Sjsg if (!dpll_mgr) 4275c349dbc7Sjsg return; 4276c349dbc7Sjsg 4277c349dbc7Sjsg dpll_mgr->put_dplls(state, crtc); 4278c349dbc7Sjsg } 4279c349dbc7Sjsg 4280c349dbc7Sjsg /** 4281c349dbc7Sjsg * intel_update_active_dpll - update the active DPLL for a CRTC/encoder 4282c349dbc7Sjsg * @state: atomic state 4283c349dbc7Sjsg * @crtc: the CRTC for which to update the active DPLL 4284c349dbc7Sjsg * @encoder: encoder determining the type of port DPLL 4285c349dbc7Sjsg * 4286c349dbc7Sjsg * Update the active DPLL for the given @crtc/@encoder in @crtc's atomic state, 4287c349dbc7Sjsg * from the port DPLLs reserved previously by intel_reserve_shared_dplls(). The 4288c349dbc7Sjsg * DPLL selected will be based on the current mode of the encoder's port. 4289c349dbc7Sjsg */ 4290c349dbc7Sjsg void intel_update_active_dpll(struct intel_atomic_state *state, 4291c349dbc7Sjsg struct intel_crtc *crtc, 4292c349dbc7Sjsg struct intel_encoder *encoder) 4293c349dbc7Sjsg { 4294c349dbc7Sjsg struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 42951bb76ff1Sjsg const struct intel_dpll_mgr *dpll_mgr = dev_priv->display.dpll.mgr; 4296c349dbc7Sjsg 4297c349dbc7Sjsg if (drm_WARN_ON(&dev_priv->drm, !dpll_mgr)) 4298c349dbc7Sjsg return; 4299c349dbc7Sjsg 4300c349dbc7Sjsg dpll_mgr->update_active_dpll(state, crtc, encoder); 4301c349dbc7Sjsg } 4302c349dbc7Sjsg 4303c349dbc7Sjsg /** 4304c349dbc7Sjsg * intel_dpll_get_freq - calculate the DPLL's output frequency 4305c349dbc7Sjsg * @i915: i915 device 4306c349dbc7Sjsg * @pll: DPLL for which to calculate the output frequency 43075ca02815Sjsg * @pll_state: DPLL state from which to calculate the output frequency 4308c349dbc7Sjsg * 43095ca02815Sjsg * Return the output frequency corresponding to @pll's passed in @pll_state. 4310c349dbc7Sjsg */ 4311c349dbc7Sjsg int intel_dpll_get_freq(struct drm_i915_private *i915, 43125ca02815Sjsg const struct intel_shared_dpll *pll, 43135ca02815Sjsg const struct intel_dpll_hw_state *pll_state) 4314c349dbc7Sjsg { 4315c349dbc7Sjsg if (drm_WARN_ON(&i915->drm, !pll->info->funcs->get_freq)) 4316c349dbc7Sjsg return 0; 4317c349dbc7Sjsg 43185ca02815Sjsg return pll->info->funcs->get_freq(i915, pll, pll_state); 43195ca02815Sjsg } 43205ca02815Sjsg 43215ca02815Sjsg /** 43225ca02815Sjsg * intel_dpll_get_hw_state - readout the DPLL's hardware state 43235ca02815Sjsg * @i915: i915 device 43245ca02815Sjsg * @pll: DPLL for which to calculate the output frequency 43255ca02815Sjsg * @hw_state: DPLL's hardware state 43265ca02815Sjsg * 43275ca02815Sjsg * Read out @pll's hardware state into @hw_state. 43285ca02815Sjsg */ 43295ca02815Sjsg bool intel_dpll_get_hw_state(struct drm_i915_private *i915, 43305ca02815Sjsg struct intel_shared_dpll *pll, 43315ca02815Sjsg struct intel_dpll_hw_state *hw_state) 43325ca02815Sjsg { 43335ca02815Sjsg return pll->info->funcs->get_hw_state(i915, pll, hw_state); 4334c349dbc7Sjsg } 4335c349dbc7Sjsg 4336c349dbc7Sjsg static void readout_dpll_hw_state(struct drm_i915_private *i915, 4337c349dbc7Sjsg struct intel_shared_dpll *pll) 4338c349dbc7Sjsg { 4339c349dbc7Sjsg struct intel_crtc *crtc; 4340c349dbc7Sjsg 43415ca02815Sjsg pll->on = intel_dpll_get_hw_state(i915, pll, &pll->state.hw_state); 4342c349dbc7Sjsg 4343f005ef32Sjsg if ((IS_JASPERLAKE(i915) || IS_ELKHARTLAKE(i915)) && 4344f005ef32Sjsg pll->on && 4345c349dbc7Sjsg pll->info->id == DPLL_ID_EHL_DPLL4) { 4346c349dbc7Sjsg pll->wakeref = intel_display_power_get(i915, 43471bb76ff1Sjsg POWER_DOMAIN_DC_OFF); 4348c349dbc7Sjsg } 4349c349dbc7Sjsg 43505ca02815Sjsg pll->state.pipe_mask = 0; 4351c349dbc7Sjsg for_each_intel_crtc(&i915->drm, crtc) { 4352c349dbc7Sjsg struct intel_crtc_state *crtc_state = 4353c349dbc7Sjsg to_intel_crtc_state(crtc->base.state); 4354c349dbc7Sjsg 4355c349dbc7Sjsg if (crtc_state->hw.active && crtc_state->shared_dpll == pll) 4356f005ef32Sjsg intel_reference_shared_dpll_crtc(crtc, pll, &pll->state); 4357c349dbc7Sjsg } 43585ca02815Sjsg pll->active_mask = pll->state.pipe_mask; 4359c349dbc7Sjsg 4360c349dbc7Sjsg drm_dbg_kms(&i915->drm, 43615ca02815Sjsg "%s hw state readout: pipe_mask 0x%x, on %i\n", 43625ca02815Sjsg pll->info->name, pll->state.pipe_mask, pll->on); 43635ca02815Sjsg } 43645ca02815Sjsg 43655ca02815Sjsg void intel_dpll_update_ref_clks(struct drm_i915_private *i915) 43665ca02815Sjsg { 43671bb76ff1Sjsg if (i915->display.dpll.mgr && i915->display.dpll.mgr->update_ref_clks) 43681bb76ff1Sjsg i915->display.dpll.mgr->update_ref_clks(i915); 4369c349dbc7Sjsg } 4370c349dbc7Sjsg 4371c349dbc7Sjsg void intel_dpll_readout_hw_state(struct drm_i915_private *i915) 4372c349dbc7Sjsg { 4373c349dbc7Sjsg int i; 4374c349dbc7Sjsg 43751bb76ff1Sjsg for (i = 0; i < i915->display.dpll.num_shared_dpll; i++) 43761bb76ff1Sjsg readout_dpll_hw_state(i915, &i915->display.dpll.shared_dplls[i]); 4377c349dbc7Sjsg } 4378c349dbc7Sjsg 4379c349dbc7Sjsg static void sanitize_dpll_state(struct drm_i915_private *i915, 4380c349dbc7Sjsg struct intel_shared_dpll *pll) 4381c349dbc7Sjsg { 43825ca02815Sjsg if (!pll->on) 43835ca02815Sjsg return; 43845ca02815Sjsg 43855ca02815Sjsg adlp_cmtg_clock_gating_wa(i915, pll); 43865ca02815Sjsg 43875ca02815Sjsg if (pll->active_mask) 4388c349dbc7Sjsg return; 4389c349dbc7Sjsg 4390c349dbc7Sjsg drm_dbg_kms(&i915->drm, 4391c349dbc7Sjsg "%s enabled but not in use, disabling\n", 4392c349dbc7Sjsg pll->info->name); 4393c349dbc7Sjsg 4394c349dbc7Sjsg pll->info->funcs->disable(i915, pll); 4395c349dbc7Sjsg pll->on = false; 4396c349dbc7Sjsg } 4397c349dbc7Sjsg 4398c349dbc7Sjsg void intel_dpll_sanitize_state(struct drm_i915_private *i915) 4399c349dbc7Sjsg { 4400c349dbc7Sjsg int i; 4401c349dbc7Sjsg 44021bb76ff1Sjsg for (i = 0; i < i915->display.dpll.num_shared_dpll; i++) 44031bb76ff1Sjsg sanitize_dpll_state(i915, &i915->display.dpll.shared_dplls[i]); 4404c349dbc7Sjsg } 4405c349dbc7Sjsg 4406c349dbc7Sjsg /** 44075ca02815Sjsg * intel_dpll_dump_hw_state - write hw_state to dmesg 4408c349dbc7Sjsg * @dev_priv: i915 drm device 4409c349dbc7Sjsg * @hw_state: hw state to be written to the log 4410c349dbc7Sjsg * 4411c349dbc7Sjsg * Write the relevant values in @hw_state to dmesg using drm_dbg_kms. 4412c349dbc7Sjsg */ 4413c349dbc7Sjsg void intel_dpll_dump_hw_state(struct drm_i915_private *dev_priv, 4414c349dbc7Sjsg const struct intel_dpll_hw_state *hw_state) 4415c349dbc7Sjsg { 44161bb76ff1Sjsg if (dev_priv->display.dpll.mgr) { 44171bb76ff1Sjsg dev_priv->display.dpll.mgr->dump_hw_state(dev_priv, hw_state); 4418c349dbc7Sjsg } else { 4419c349dbc7Sjsg /* fallback for platforms that don't use the shared dpll 4420c349dbc7Sjsg * infrastructure 4421c349dbc7Sjsg */ 4422c349dbc7Sjsg drm_dbg_kms(&dev_priv->drm, 4423c349dbc7Sjsg "dpll_hw_state: dpll: 0x%x, dpll_md: 0x%x, " 4424c349dbc7Sjsg "fp0: 0x%x, fp1: 0x%x\n", 4425c349dbc7Sjsg hw_state->dpll, 4426c349dbc7Sjsg hw_state->dpll_md, 4427c349dbc7Sjsg hw_state->fp0, 4428c349dbc7Sjsg hw_state->fp1); 4429c349dbc7Sjsg } 4430c349dbc7Sjsg } 44311bb76ff1Sjsg 44321bb76ff1Sjsg static void 44331bb76ff1Sjsg verify_single_dpll_state(struct drm_i915_private *dev_priv, 44341bb76ff1Sjsg struct intel_shared_dpll *pll, 44351bb76ff1Sjsg struct intel_crtc *crtc, 44361bb76ff1Sjsg struct intel_crtc_state *new_crtc_state) 44371bb76ff1Sjsg { 44381bb76ff1Sjsg struct intel_dpll_hw_state dpll_hw_state; 44391bb76ff1Sjsg u8 pipe_mask; 44401bb76ff1Sjsg bool active; 44411bb76ff1Sjsg 44421bb76ff1Sjsg memset(&dpll_hw_state, 0, sizeof(dpll_hw_state)); 44431bb76ff1Sjsg 44441bb76ff1Sjsg drm_dbg_kms(&dev_priv->drm, "%s\n", pll->info->name); 44451bb76ff1Sjsg 44461bb76ff1Sjsg active = intel_dpll_get_hw_state(dev_priv, pll, &dpll_hw_state); 44471bb76ff1Sjsg 44481bb76ff1Sjsg if (!(pll->info->flags & INTEL_DPLL_ALWAYS_ON)) { 4449f005ef32Sjsg I915_STATE_WARN(dev_priv, !pll->on && pll->active_mask, 44501bb76ff1Sjsg "pll in active use but not on in sw tracking\n"); 4451f005ef32Sjsg I915_STATE_WARN(dev_priv, pll->on && !pll->active_mask, 44521bb76ff1Sjsg "pll is on but not used by any active pipe\n"); 4453f005ef32Sjsg I915_STATE_WARN(dev_priv, pll->on != active, 44541bb76ff1Sjsg "pll on state mismatch (expected %i, found %i)\n", 44551bb76ff1Sjsg pll->on, active); 44561bb76ff1Sjsg } 44571bb76ff1Sjsg 44581bb76ff1Sjsg if (!crtc) { 4459f005ef32Sjsg I915_STATE_WARN(dev_priv, 4460f005ef32Sjsg pll->active_mask & ~pll->state.pipe_mask, 44611bb76ff1Sjsg "more active pll users than references: 0x%x vs 0x%x\n", 44621bb76ff1Sjsg pll->active_mask, pll->state.pipe_mask); 44631bb76ff1Sjsg 44641bb76ff1Sjsg return; 44651bb76ff1Sjsg } 44661bb76ff1Sjsg 44671bb76ff1Sjsg pipe_mask = BIT(crtc->pipe); 44681bb76ff1Sjsg 44691bb76ff1Sjsg if (new_crtc_state->hw.active) 4470f005ef32Sjsg I915_STATE_WARN(dev_priv, !(pll->active_mask & pipe_mask), 44711bb76ff1Sjsg "pll active mismatch (expected pipe %c in active mask 0x%x)\n", 44721bb76ff1Sjsg pipe_name(crtc->pipe), pll->active_mask); 44731bb76ff1Sjsg else 4474f005ef32Sjsg I915_STATE_WARN(dev_priv, pll->active_mask & pipe_mask, 44751bb76ff1Sjsg "pll active mismatch (didn't expect pipe %c in active mask 0x%x)\n", 44761bb76ff1Sjsg pipe_name(crtc->pipe), pll->active_mask); 44771bb76ff1Sjsg 4478f005ef32Sjsg I915_STATE_WARN(dev_priv, !(pll->state.pipe_mask & pipe_mask), 44791bb76ff1Sjsg "pll enabled crtcs mismatch (expected 0x%x in 0x%x)\n", 44801bb76ff1Sjsg pipe_mask, pll->state.pipe_mask); 44811bb76ff1Sjsg 4482f005ef32Sjsg I915_STATE_WARN(dev_priv, 4483f005ef32Sjsg pll->on && memcmp(&pll->state.hw_state, &dpll_hw_state, 44841bb76ff1Sjsg sizeof(dpll_hw_state)), 44851bb76ff1Sjsg "pll hw state mismatch\n"); 44861bb76ff1Sjsg } 44871bb76ff1Sjsg 44881bb76ff1Sjsg void intel_shared_dpll_state_verify(struct intel_crtc *crtc, 44891bb76ff1Sjsg struct intel_crtc_state *old_crtc_state, 44901bb76ff1Sjsg struct intel_crtc_state *new_crtc_state) 44911bb76ff1Sjsg { 44921bb76ff1Sjsg struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); 44931bb76ff1Sjsg 44941bb76ff1Sjsg if (new_crtc_state->shared_dpll) 44951bb76ff1Sjsg verify_single_dpll_state(dev_priv, new_crtc_state->shared_dpll, 44961bb76ff1Sjsg crtc, new_crtc_state); 44971bb76ff1Sjsg 44981bb76ff1Sjsg if (old_crtc_state->shared_dpll && 44991bb76ff1Sjsg old_crtc_state->shared_dpll != new_crtc_state->shared_dpll) { 45001bb76ff1Sjsg u8 pipe_mask = BIT(crtc->pipe); 45011bb76ff1Sjsg struct intel_shared_dpll *pll = old_crtc_state->shared_dpll; 45021bb76ff1Sjsg 4503f005ef32Sjsg I915_STATE_WARN(dev_priv, pll->active_mask & pipe_mask, 45041bb76ff1Sjsg "pll active mismatch (didn't expect pipe %c in active mask (0x%x))\n", 45051bb76ff1Sjsg pipe_name(crtc->pipe), pll->active_mask); 4506f005ef32Sjsg I915_STATE_WARN(dev_priv, pll->state.pipe_mask & pipe_mask, 45071bb76ff1Sjsg "pll enabled crtcs mismatch (found %x in enabled mask (0x%x))\n", 45081bb76ff1Sjsg pipe_name(crtc->pipe), pll->state.pipe_mask); 45091bb76ff1Sjsg } 45101bb76ff1Sjsg } 45111bb76ff1Sjsg 45121bb76ff1Sjsg void intel_shared_dpll_verify_disabled(struct drm_i915_private *i915) 45131bb76ff1Sjsg { 45141bb76ff1Sjsg int i; 45151bb76ff1Sjsg 45161bb76ff1Sjsg for (i = 0; i < i915->display.dpll.num_shared_dpll; i++) 45171bb76ff1Sjsg verify_single_dpll_state(i915, &i915->display.dpll.shared_dplls[i], 45181bb76ff1Sjsg NULL, NULL); 45191bb76ff1Sjsg } 4520