aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Zanoni <paulo.r.zanoni@intel.com>2018-04-27 19:14:36 -0400
committerPaulo Zanoni <paulo.r.zanoni@intel.com>2018-05-07 19:42:47 -0400
commitc27e917e2bda748777b7927d7cb7c911bc2027c8 (patch)
tree3759abb6b3ee2f6aaa468c76b06267dbdc9a30d9
parent13e1592f7379422c8d45ccd9c8c8a4698c97b39b (diff)
drm/i915/icl: add basic support for the ICL clocks
This commit introduces the definitions for the ICL clocks and adds the basic functions to the shared DPLL framework. It adds code for the Enable and Disable sequences for some PLLs, but it does not have the code to compute the actual PLL values, which are marked as TODO comments and should be introduced as separate commits. Special thanks to James Ausmus for investigating and fixing a bug with the placement of icl_unmap_plls_to_ports() function. v2: - Rebase around dpll_lock changes. v3: - The spec now says what the timeouts should be. - Touch DPCLKA_CFGCR0_ICL at the appropriate time so we don't freeze the machine. - Checkpatch found a white space problem. - Small adjustments before upstreaming. v4: - Move the ICL checks out of the *map_plls_to_ports() functions (James) - Add extra encoder check (James) - Call icl_unmap_plls_to_ports() later (James) v5: - Rebase after the pll struct changes. v6: - Properly make the unmap function based on encoders_post_disable() with regarding to checks and iterators. - Address checkpatch comment on "min = max = x()". Cc: James Ausmus <james.ausmus@intel.com> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: James Ausmus <james.ausmus@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180427231436.9353-1-paulo.r.zanoni@intel.com
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c22
-rw-r--r--drivers/gpu/drm/i915/intel_ddi.c98
-rw-r--r--drivers/gpu/drm/i915/intel_display.c16
-rw-r--r--drivers/gpu/drm/i915/intel_dpll_mgr.c313
-rw-r--r--drivers/gpu/drm/i915/intel_dpll_mgr.h41
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h6
6 files changed, 491 insertions, 5 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 85911bc0b703..13e7b9e4a6e6 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3368,6 +3368,28 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
3368 seq_printf(m, " fp0: 0x%08x\n", pll->state.hw_state.fp0); 3368 seq_printf(m, " fp0: 0x%08x\n", pll->state.hw_state.fp0);
3369 seq_printf(m, " fp1: 0x%08x\n", pll->state.hw_state.fp1); 3369 seq_printf(m, " fp1: 0x%08x\n", pll->state.hw_state.fp1);
3370 seq_printf(m, " wrpll: 0x%08x\n", pll->state.hw_state.wrpll); 3370 seq_printf(m, " wrpll: 0x%08x\n", pll->state.hw_state.wrpll);
3371 seq_printf(m, " cfgcr0: 0x%08x\n", pll->state.hw_state.cfgcr0);
3372 seq_printf(m, " cfgcr1: 0x%08x\n", pll->state.hw_state.cfgcr1);
3373 seq_printf(m, " mg_refclkin_ctl: 0x%08x\n",
3374 pll->state.hw_state.mg_refclkin_ctl);
3375 seq_printf(m, " mg_clktop2_coreclkctl1: 0x%08x\n",
3376 pll->state.hw_state.mg_clktop2_coreclkctl1);
3377 seq_printf(m, " mg_clktop2_hsclkctl: 0x%08x\n",
3378 pll->state.hw_state.mg_clktop2_hsclkctl);
3379 seq_printf(m, " mg_pll_div0: 0x%08x\n",
3380 pll->state.hw_state.mg_pll_div0);
3381 seq_printf(m, " mg_pll_div1: 0x%08x\n",
3382 pll->state.hw_state.mg_pll_div1);
3383 seq_printf(m, " mg_pll_lf: 0x%08x\n",
3384 pll->state.hw_state.mg_pll_lf);
3385 seq_printf(m, " mg_pll_frac_lock: 0x%08x\n",
3386 pll->state.hw_state.mg_pll_frac_lock);
3387 seq_printf(m, " mg_pll_ssc: 0x%08x\n",
3388 pll->state.hw_state.mg_pll_ssc);
3389 seq_printf(m, " mg_pll_bias: 0x%08x\n",
3390 pll->state.hw_state.mg_pll_bias);
3391 seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n",
3392 pll->state.hw_state.mg_pll_tdc_coldst_bias);
3371 } 3393 }
3372 drm_modeset_unlock_all(dev); 3394 drm_modeset_unlock_all(dev);
3373 3395
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c
index 8225d223f452..b98ac0541f19 100644
--- a/drivers/gpu/drm/i915/intel_ddi.c
+++ b/drivers/gpu/drm/i915/intel_ddi.c
@@ -1052,6 +1052,25 @@ static uint32_t hsw_pll_to_ddi_pll_sel(const struct intel_shared_dpll *pll)
1052 } 1052 }
1053} 1053}
1054 1054
1055static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
1056 const struct intel_shared_dpll *pll)
1057{
1058 const enum intel_dpll_id id = pll->info->id;
1059
1060 switch (id) {
1061 default:
1062 MISSING_CASE(id);
1063 case DPLL_ID_ICL_DPLL0:
1064 case DPLL_ID_ICL_DPLL1:
1065 return DDI_CLK_SEL_NONE;
1066 case DPLL_ID_ICL_MGPLL1:
1067 case DPLL_ID_ICL_MGPLL2:
1068 case DPLL_ID_ICL_MGPLL3:
1069 case DPLL_ID_ICL_MGPLL4:
1070 return DDI_CLK_SEL_MG;
1071 }
1072}
1073
1055/* Starting with Haswell, different DDI ports can work in FDI mode for 1074/* Starting with Haswell, different DDI ports can work in FDI mode for
1056 * connection to the PCH-located connectors. For this, it is necessary to train 1075 * connection to the PCH-located connectors. For this, it is necessary to train
1057 * both the DDI port and PCH receiver for the desired DDI buffer settings. 1076 * both the DDI port and PCH receiver for the desired DDI buffer settings.
@@ -2421,6 +2440,69 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp)
2421 return DDI_BUF_TRANS_SELECT(level); 2440 return DDI_BUF_TRANS_SELECT(level);
2422} 2441}
2423 2442
2443void icl_map_plls_to_ports(struct drm_crtc *crtc,
2444 struct intel_crtc_state *crtc_state,
2445 struct drm_atomic_state *old_state)
2446{
2447 struct intel_shared_dpll *pll = crtc_state->shared_dpll;
2448 struct drm_i915_private *dev_priv = to_i915(crtc->dev);
2449 struct drm_connector_state *conn_state;
2450 struct drm_connector *conn;
2451 int i;
2452
2453 for_each_new_connector_in_state(old_state, conn, conn_state, i) {
2454 struct intel_encoder *encoder =
2455 to_intel_encoder(conn_state->best_encoder);
2456 enum port port = encoder->port;
2457 uint32_t val;
2458
2459 if (conn_state->crtc != crtc)
2460 continue;
2461
2462 mutex_lock(&dev_priv->dpll_lock);
2463
2464 val = I915_READ(DPCLKA_CFGCR0_ICL);
2465 WARN_ON((val & DPCLKA_CFGCR0_DDI_CLK_OFF(port)) == 0);
2466
2467 if (port == PORT_A || port == PORT_B) {
2468 val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
2469 val |= DPCLKA_CFGCR0_DDI_CLK_SEL(pll->info->id, port);
2470 I915_WRITE(DPCLKA_CFGCR0_ICL, val);
2471 POSTING_READ(DPCLKA_CFGCR0_ICL);
2472 }
2473
2474 val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port);
2475 I915_WRITE(DPCLKA_CFGCR0_ICL, val);
2476
2477 mutex_unlock(&dev_priv->dpll_lock);
2478 }
2479}
2480
2481void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
2482 struct intel_crtc_state *crtc_state,
2483 struct drm_atomic_state *old_state)
2484{
2485 struct drm_i915_private *dev_priv = to_i915(crtc->dev);
2486 struct drm_connector_state *old_conn_state;
2487 struct drm_connector *conn;
2488 int i;
2489
2490 for_each_old_connector_in_state(old_state, conn, old_conn_state, i) {
2491 struct intel_encoder *encoder =
2492 to_intel_encoder(old_conn_state->best_encoder);
2493 enum port port = encoder->port;
2494
2495 if (old_conn_state->crtc != crtc)
2496 continue;
2497
2498 mutex_lock(&dev_priv->dpll_lock);
2499 I915_WRITE(DPCLKA_CFGCR0_ICL,
2500 I915_READ(DPCLKA_CFGCR0_ICL) |
2501 DPCLKA_CFGCR0_DDI_CLK_OFF(port));
2502 mutex_unlock(&dev_priv->dpll_lock);
2503 }
2504}
2505
2424static void intel_ddi_clk_select(struct intel_encoder *encoder, 2506static void intel_ddi_clk_select(struct intel_encoder *encoder,
2425 const struct intel_shared_dpll *pll) 2507 const struct intel_shared_dpll *pll)
2426{ 2508{
@@ -2433,7 +2515,11 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder,
2433 2515
2434 mutex_lock(&dev_priv->dpll_lock); 2516 mutex_lock(&dev_priv->dpll_lock);
2435 2517
2436 if (IS_CANNONLAKE(dev_priv)) { 2518 if (IS_ICELAKE(dev_priv)) {
2519 if (port >= PORT_C)
2520 I915_WRITE(DDI_CLK_SEL(port),
2521 icl_pll_to_ddi_pll_sel(encoder, pll));
2522 } else if (IS_CANNONLAKE(dev_priv)) {
2437 /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */ 2523 /* Configure DPCLKA_CFGCR0 to map the DPLL to the DDI. */
2438 val = I915_READ(DPCLKA_CFGCR0); 2524 val = I915_READ(DPCLKA_CFGCR0);
2439 val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port); 2525 val &= ~DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port);
@@ -2471,14 +2557,18 @@ static void intel_ddi_clk_disable(struct intel_encoder *encoder)
2471 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); 2557 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
2472 enum port port = encoder->port; 2558 enum port port = encoder->port;
2473 2559
2474 if (IS_CANNONLAKE(dev_priv)) 2560 if (IS_ICELAKE(dev_priv)) {
2561 if (port >= PORT_C)
2562 I915_WRITE(DDI_CLK_SEL(port), DDI_CLK_SEL_NONE);
2563 } else if (IS_CANNONLAKE(dev_priv)) {
2475 I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) | 2564 I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) |
2476 DPCLKA_CFGCR0_DDI_CLK_OFF(port)); 2565 DPCLKA_CFGCR0_DDI_CLK_OFF(port));
2477 else if (IS_GEN9_BC(dev_priv)) 2566 } else if (IS_GEN9_BC(dev_priv)) {
2478 I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) | 2567 I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) |
2479 DPLL_CTRL2_DDI_CLK_OFF(port)); 2568 DPLL_CTRL2_DDI_CLK_OFF(port));
2480 else if (INTEL_GEN(dev_priv) < 9) 2569 } else if (INTEL_GEN(dev_priv) < 9) {
2481 I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); 2570 I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE);
2571 }
2482} 2572}
2483 2573
2484static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, 2574static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder,
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 3fd249c05e4e..cdfe0951d171 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -5559,6 +5559,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config,
5559 if (intel_crtc->config->shared_dpll) 5559 if (intel_crtc->config->shared_dpll)
5560 intel_enable_shared_dpll(intel_crtc); 5560 intel_enable_shared_dpll(intel_crtc);
5561 5561
5562 if (INTEL_GEN(dev_priv) >= 11)
5563 icl_map_plls_to_ports(crtc, pipe_config, old_state);
5564
5562 if (intel_crtc_has_dp_encoder(intel_crtc->config)) 5565 if (intel_crtc_has_dp_encoder(intel_crtc->config))
5563 intel_dp_set_m_n(intel_crtc, M1_N1); 5566 intel_dp_set_m_n(intel_crtc, M1_N1);
5564 5567
@@ -5756,6 +5759,9 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state,
5756 intel_ddi_disable_pipe_clock(intel_crtc->config); 5759 intel_ddi_disable_pipe_clock(intel_crtc->config);
5757 5760
5758 intel_encoders_post_disable(crtc, old_crtc_state, old_state); 5761 intel_encoders_post_disable(crtc, old_crtc_state, old_state);
5762
5763 if (INTEL_GEN(dev_priv) >= 11)
5764 icl_unmap_plls_to_ports(crtc, old_crtc_state, old_state);
5759} 5765}
5760 5766
5761static void i9xx_pfit_enable(struct intel_crtc *crtc) 5767static void i9xx_pfit_enable(struct intel_crtc *crtc)
@@ -11386,6 +11392,16 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv,
11386 PIPE_CONF_CHECK_X(dpll_hw_state.pll9); 11392 PIPE_CONF_CHECK_X(dpll_hw_state.pll9);
11387 PIPE_CONF_CHECK_X(dpll_hw_state.pll10); 11393 PIPE_CONF_CHECK_X(dpll_hw_state.pll10);
11388 PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12); 11394 PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12);
11395 PIPE_CONF_CHECK_X(dpll_hw_state.mg_refclkin_ctl);
11396 PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_coreclkctl1);
11397 PIPE_CONF_CHECK_X(dpll_hw_state.mg_clktop2_hsclkctl);
11398 PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div0);
11399 PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_div1);
11400 PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_lf);
11401 PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_frac_lock);
11402 PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_ssc);
11403 PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_bias);
11404 PIPE_CONF_CHECK_X(dpll_hw_state.mg_pll_tdc_coldst_bias);
11389 11405
11390 PIPE_CONF_CHECK_X(dsi_pll.ctrl); 11406 PIPE_CONF_CHECK_X(dsi_pll.ctrl);
11391 PIPE_CONF_CHECK_X(dsi_pll.div); 11407 PIPE_CONF_CHECK_X(dsi_pll.div);
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index d5e114e9660b..14f5414ceab2 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -2399,6 +2399,315 @@ static const struct intel_dpll_mgr cnl_pll_mgr = {
2399 .dump_hw_state = cnl_dump_hw_state, 2399 .dump_hw_state = cnl_dump_hw_state,
2400}; 2400};
2401 2401
2402static bool icl_calc_dpll_state(struct intel_crtc_state *crtc_state,
2403 struct intel_encoder *encoder, int clock,
2404 struct intel_dpll_hw_state *pll_state)
2405{
2406 /* TODO */
2407 return true;
2408}
2409
2410static enum port icl_mg_pll_id_to_port(enum intel_dpll_id id)
2411{
2412 return id - DPLL_ID_ICL_MGPLL1 + PORT_C;
2413}
2414
2415static enum intel_dpll_id icl_port_to_mg_pll_id(enum port port)
2416{
2417 return port - PORT_C + DPLL_ID_ICL_MGPLL1;
2418}
2419
2420static bool icl_calc_mg_pll_state(struct intel_crtc_state *crtc_state,
2421 struct intel_encoder *encoder, int clock,
2422 struct intel_dpll_hw_state *pll_state)
2423{
2424 /* TODO */
2425 return true;
2426}
2427
2428static struct intel_shared_dpll *
2429icl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
2430 struct intel_encoder *encoder)
2431{
2432 struct intel_shared_dpll *pll;
2433 struct intel_dpll_hw_state pll_state = {};
2434 enum port port = encoder->port;
2435 enum intel_dpll_id min, max;
2436 int clock = crtc_state->port_clock;
2437 bool ret;
2438
2439 switch (port) {
2440 case PORT_A:
2441 case PORT_B:
2442 min = DPLL_ID_ICL_DPLL0;
2443 max = DPLL_ID_ICL_DPLL1;
2444 ret = icl_calc_dpll_state(crtc_state, encoder, clock,
2445 &pll_state);
2446 break;
2447 case PORT_C:
2448 case PORT_D:
2449 case PORT_E:
2450 case PORT_F:
2451 min = icl_port_to_mg_pll_id(port);
2452 max = min;
2453 ret = icl_calc_mg_pll_state(crtc_state, encoder, clock,
2454 &pll_state);
2455 break;
2456 default:
2457 MISSING_CASE(port);
2458 return NULL;
2459 }
2460
2461 if (!ret) {
2462 DRM_DEBUG_KMS("Could not calculate PLL state.\n");
2463 return NULL;
2464 }
2465
2466 crtc_state->dpll_hw_state = pll_state;
2467
2468 pll = intel_find_shared_dpll(crtc, crtc_state, min, max);
2469 if (!pll) {
2470 DRM_DEBUG_KMS("No PLL selected\n");
2471 return NULL;
2472 }
2473
2474 intel_reference_shared_dpll(pll, crtc_state);
2475
2476 return pll;
2477}
2478
2479static i915_reg_t icl_pll_id_to_enable_reg(enum intel_dpll_id id)
2480{
2481 switch (id) {
2482 default:
2483 MISSING_CASE(id);
2484 case DPLL_ID_ICL_DPLL0:
2485 case DPLL_ID_ICL_DPLL1:
2486 return CNL_DPLL_ENABLE(id);
2487 case DPLL_ID_ICL_MGPLL1:
2488 case DPLL_ID_ICL_MGPLL2:
2489 case DPLL_ID_ICL_MGPLL3:
2490 case DPLL_ID_ICL_MGPLL4:
2491 return MG_PLL_ENABLE(icl_mg_pll_id_to_port(id));
2492 }
2493}
2494
2495static bool icl_pll_get_hw_state(struct drm_i915_private *dev_priv,
2496 struct intel_shared_dpll *pll,
2497 struct intel_dpll_hw_state *hw_state)
2498{
2499 const enum intel_dpll_id id = pll->info->id;
2500 uint32_t val;
2501 enum port port;
2502 bool ret = false;
2503
2504 if (!intel_display_power_get_if_enabled(dev_priv, POWER_DOMAIN_PLLS))
2505 return false;
2506
2507 val = I915_READ(icl_pll_id_to_enable_reg(id));
2508 if (!(val & PLL_ENABLE))
2509 goto out;
2510
2511 switch (id) {
2512 case DPLL_ID_ICL_DPLL0:
2513 case DPLL_ID_ICL_DPLL1:
2514 hw_state->cfgcr0 = I915_READ(ICL_DPLL_CFGCR0(id));
2515 hw_state->cfgcr1 = I915_READ(ICL_DPLL_CFGCR1(id));
2516 break;
2517 case DPLL_ID_ICL_MGPLL1:
2518 case DPLL_ID_ICL_MGPLL2:
2519 case DPLL_ID_ICL_MGPLL3:
2520 case DPLL_ID_ICL_MGPLL4:
2521 port = icl_mg_pll_id_to_port(id);
2522 hw_state->mg_refclkin_ctl = I915_READ(MG_REFCLKIN_CTL(port));
2523 hw_state->mg_clktop2_coreclkctl1 =
2524 I915_READ(MG_CLKTOP2_CORECLKCTL1(port));
2525 hw_state->mg_clktop2_hsclkctl =
2526 I915_READ(MG_CLKTOP2_HSCLKCTL(port));
2527 hw_state->mg_pll_div0 = I915_READ(MG_PLL_DIV0(port));
2528 hw_state->mg_pll_div1 = I915_READ(MG_PLL_DIV1(port));
2529 hw_state->mg_pll_lf = I915_READ(MG_PLL_LF(port));
2530 hw_state->mg_pll_frac_lock = I915_READ(MG_PLL_FRAC_LOCK(port));
2531 hw_state->mg_pll_ssc = I915_READ(MG_PLL_SSC(port));
2532 hw_state->mg_pll_bias = I915_READ(MG_PLL_BIAS(port));
2533 hw_state->mg_pll_tdc_coldst_bias =
2534 I915_READ(MG_PLL_TDC_COLDST_BIAS(port));
2535 break;
2536 default:
2537 MISSING_CASE(id);
2538 }
2539
2540 ret = true;
2541out:
2542 intel_display_power_put(dev_priv, POWER_DOMAIN_PLLS);
2543 return ret;
2544}
2545
2546static void icl_dpll_write(struct drm_i915_private *dev_priv,
2547 struct intel_shared_dpll *pll)
2548{
2549 struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
2550 const enum intel_dpll_id id = pll->info->id;
2551
2552 I915_WRITE(ICL_DPLL_CFGCR0(id), hw_state->cfgcr0);
2553 I915_WRITE(ICL_DPLL_CFGCR1(id), hw_state->cfgcr1);
2554 POSTING_READ(ICL_DPLL_CFGCR1(id));
2555}
2556
2557static void icl_mg_pll_write(struct drm_i915_private *dev_priv,
2558 struct intel_shared_dpll *pll)
2559{
2560 struct intel_dpll_hw_state *hw_state = &pll->state.hw_state;
2561 enum port port = icl_mg_pll_id_to_port(pll->info->id);
2562
2563 I915_WRITE(MG_REFCLKIN_CTL(port), hw_state->mg_refclkin_ctl);
2564 I915_WRITE(MG_CLKTOP2_CORECLKCTL1(port),
2565 hw_state->mg_clktop2_coreclkctl1);
2566 I915_WRITE(MG_CLKTOP2_HSCLKCTL(port), hw_state->mg_clktop2_hsclkctl);
2567 I915_WRITE(MG_PLL_DIV0(port), hw_state->mg_pll_div0);
2568 I915_WRITE(MG_PLL_DIV1(port), hw_state->mg_pll_div1);
2569 I915_WRITE(MG_PLL_LF(port), hw_state->mg_pll_lf);
2570 I915_WRITE(MG_PLL_FRAC_LOCK(port), hw_state->mg_pll_frac_lock);
2571 I915_WRITE(MG_PLL_SSC(port), hw_state->mg_pll_ssc);
2572 I915_WRITE(MG_PLL_BIAS(port), hw_state->mg_pll_bias);
2573 I915_WRITE(MG_PLL_TDC_COLDST_BIAS(port),
2574 hw_state->mg_pll_tdc_coldst_bias);
2575 POSTING_READ(MG_PLL_TDC_COLDST_BIAS(port));
2576}
2577
2578static void icl_pll_enable(struct drm_i915_private *dev_priv,
2579 struct intel_shared_dpll *pll)
2580{
2581 const enum intel_dpll_id id = pll->info->id;
2582 i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
2583 uint32_t val;
2584
2585 val = I915_READ(enable_reg);
2586 val |= PLL_POWER_ENABLE;
2587 I915_WRITE(enable_reg, val);
2588
2589 /*
2590 * The spec says we need to "wait" but it also says it should be
2591 * immediate.
2592 */
2593 if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE,
2594 PLL_POWER_STATE, 1))
2595 DRM_ERROR("PLL %d Power not enabled\n", id);
2596
2597 switch (id) {
2598 case DPLL_ID_ICL_DPLL0:
2599 case DPLL_ID_ICL_DPLL1:
2600 icl_dpll_write(dev_priv, pll);
2601 break;
2602 case DPLL_ID_ICL_MGPLL1:
2603 case DPLL_ID_ICL_MGPLL2:
2604 case DPLL_ID_ICL_MGPLL3:
2605 case DPLL_ID_ICL_MGPLL4:
2606 icl_mg_pll_write(dev_priv, pll);
2607 break;
2608 default:
2609 MISSING_CASE(id);
2610 }
2611
2612 /*
2613 * DVFS pre sequence would be here, but in our driver the cdclk code
2614 * paths should already be setting the appropriate voltage, hence we do
2615 * nothign here.
2616 */
2617
2618 val = I915_READ(enable_reg);
2619 val |= PLL_ENABLE;
2620 I915_WRITE(enable_reg, val);
2621
2622 if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, PLL_LOCK,
2623 1)) /* 600us actually. */
2624 DRM_ERROR("PLL %d not locked\n", id);
2625
2626 /* DVFS post sequence would be here. See the comment above. */
2627}
2628
2629static void icl_pll_disable(struct drm_i915_private *dev_priv,
2630 struct intel_shared_dpll *pll)
2631{
2632 const enum intel_dpll_id id = pll->info->id;
2633 i915_reg_t enable_reg = icl_pll_id_to_enable_reg(id);
2634 uint32_t val;
2635
2636 /* The first steps are done by intel_ddi_post_disable(). */
2637
2638 /*
2639 * DVFS pre sequence would be here, but in our driver the cdclk code
2640 * paths should already be setting the appropriate voltage, hence we do
2641 * nothign here.
2642 */
2643
2644 val = I915_READ(enable_reg);
2645 val &= ~PLL_ENABLE;
2646 I915_WRITE(enable_reg, val);
2647
2648 /* Timeout is actually 1us. */
2649 if (intel_wait_for_register(dev_priv, enable_reg, PLL_LOCK, 0, 1))
2650 DRM_ERROR("PLL %d locked\n", id);
2651
2652 /* DVFS post sequence would be here. See the comment above. */
2653
2654 val = I915_READ(enable_reg);
2655 val &= ~PLL_POWER_ENABLE;
2656 I915_WRITE(enable_reg, val);
2657
2658 /*
2659 * The spec says we need to "wait" but it also says it should be
2660 * immediate.
2661 */
2662 if (intel_wait_for_register(dev_priv, enable_reg, PLL_POWER_STATE, 0,
2663 1))
2664 DRM_ERROR("PLL %d Power not disabled\n", id);
2665}
2666
2667static void icl_dump_hw_state(struct drm_i915_private *dev_priv,
2668 struct intel_dpll_hw_state *hw_state)
2669{
2670 DRM_DEBUG_KMS("dpll_hw_state: cfgcr0: 0x%x, cfgcr1: 0x%x, "
2671 "mg_refclkin_ctl: 0x%x, hg_clktop2_coreclkctl1: 0x%x, "
2672 "mg_clktop2_hsclkctl: 0x%x, mg_pll_div0: 0x%x, "
2673 "mg_pll_div2: 0x%x, mg_pll_lf: 0x%x, "
2674 "mg_pll_frac_lock: 0x%x, mg_pll_ssc: 0x%x, "
2675 "mg_pll_bias: 0x%x, mg_pll_tdc_coldst_bias: 0x%x\n",
2676 hw_state->cfgcr0, hw_state->cfgcr1,
2677 hw_state->mg_refclkin_ctl,
2678 hw_state->mg_clktop2_coreclkctl1,
2679 hw_state->mg_clktop2_hsclkctl,
2680 hw_state->mg_pll_div0,
2681 hw_state->mg_pll_div1,
2682 hw_state->mg_pll_lf,
2683 hw_state->mg_pll_frac_lock,
2684 hw_state->mg_pll_ssc,
2685 hw_state->mg_pll_bias,
2686 hw_state->mg_pll_tdc_coldst_bias);
2687}
2688
2689static const struct intel_shared_dpll_funcs icl_pll_funcs = {
2690 .enable = icl_pll_enable,
2691 .disable = icl_pll_disable,
2692 .get_hw_state = icl_pll_get_hw_state,
2693};
2694
2695static const struct dpll_info icl_plls[] = {
2696 { "DPLL 0", &icl_pll_funcs, DPLL_ID_ICL_DPLL0, 0 },
2697 { "DPLL 1", &icl_pll_funcs, DPLL_ID_ICL_DPLL1, 0 },
2698 { "MG PLL 1", &icl_pll_funcs, DPLL_ID_ICL_MGPLL1, 0 },
2699 { "MG PLL 2", &icl_pll_funcs, DPLL_ID_ICL_MGPLL2, 0 },
2700 { "MG PLL 3", &icl_pll_funcs, DPLL_ID_ICL_MGPLL3, 0 },
2701 { "MG PLL 4", &icl_pll_funcs, DPLL_ID_ICL_MGPLL4, 0 },
2702 { },
2703};
2704
2705static const struct intel_dpll_mgr icl_pll_mgr = {
2706 .dpll_info = icl_plls,
2707 .get_dpll = icl_get_dpll,
2708 .dump_hw_state = icl_dump_hw_state,
2709};
2710
2402/** 2711/**
2403 * intel_shared_dpll_init - Initialize shared DPLLs 2712 * intel_shared_dpll_init - Initialize shared DPLLs
2404 * @dev: drm device 2713 * @dev: drm device
@@ -2412,7 +2721,9 @@ void intel_shared_dpll_init(struct drm_device *dev)
2412 const struct dpll_info *dpll_info; 2721 const struct dpll_info *dpll_info;
2413 int i; 2722 int i;
2414 2723
2415 if (IS_CANNONLAKE(dev_priv)) 2724 if (IS_ICELAKE(dev_priv))
2725 dpll_mgr = &icl_pll_mgr;
2726 else if (IS_CANNONLAKE(dev_priv))
2416 dpll_mgr = &cnl_pll_mgr; 2727 dpll_mgr = &cnl_pll_mgr;
2417 else if (IS_GEN9_BC(dev_priv)) 2728 else if (IS_GEN9_BC(dev_priv))
2418 dpll_mgr = &skl_pll_mgr; 2729 dpll_mgr = &skl_pll_mgr;
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.h b/drivers/gpu/drm/i915/intel_dpll_mgr.h
index 4febfaa90bde..7a0cd564a9ee 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.h
@@ -103,6 +103,32 @@ enum intel_dpll_id {
103 * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3 103 * @DPLL_ID_SKL_DPLL3: SKL and later DPLL3
104 */ 104 */
105 DPLL_ID_SKL_DPLL3 = 3, 105 DPLL_ID_SKL_DPLL3 = 3,
106
107
108 /**
109 * @DPLL_ID_ICL_DPLL0: ICL combo PHY DPLL0
110 */
111 DPLL_ID_ICL_DPLL0 = 0,
112 /**
113 * @DPLL_ID_ICL_DPLL1: ICL combo PHY DPLL1
114 */
115 DPLL_ID_ICL_DPLL1 = 1,
116 /**
117 * @DPLL_ID_ICL_MGPLL1: ICL MG PLL 1 port 1 (C)
118 */
119 DPLL_ID_ICL_MGPLL1 = 2,
120 /**
121 * @DPLL_ID_ICL_MGPLL2: ICL MG PLL 1 port 2 (D)
122 */
123 DPLL_ID_ICL_MGPLL2 = 3,
124 /**
125 * @DPLL_ID_ICL_MGPLL3: ICL MG PLL 1 port 3 (E)
126 */
127 DPLL_ID_ICL_MGPLL3 = 4,
128 /**
129 * @DPLL_ID_ICL_MGPLL4: ICL MG PLL 1 port 4 (F)
130 */
131 DPLL_ID_ICL_MGPLL4 = 5,
106}; 132};
107#define I915_NUM_PLLS 6 133#define I915_NUM_PLLS 6
108 134
@@ -135,6 +161,21 @@ struct intel_dpll_hw_state {
135 /* bxt */ 161 /* bxt */
136 uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10, 162 uint32_t ebb0, ebb4, pll0, pll1, pll2, pll3, pll6, pll8, pll9, pll10,
137 pcsdw12; 163 pcsdw12;
164
165 /*
166 * ICL uses the following, already defined:
167 * uint32_t cfgcr0, cfgcr1;
168 */
169 uint32_t mg_refclkin_ctl;
170 uint32_t mg_clktop2_coreclkctl1;
171 uint32_t mg_clktop2_hsclkctl;
172 uint32_t mg_pll_div0;
173 uint32_t mg_pll_div1;
174 uint32_t mg_pll_lf;
175 uint32_t mg_pll_frac_lock;
176 uint32_t mg_pll_ssc;
177 uint32_t mg_pll_bias;
178 uint32_t mg_pll_tdc_coldst_bias;
138}; 179};
139 180
140/** 181/**
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 11a1932cde6e..52337f487ebc 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1409,6 +1409,12 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp);
1409u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder); 1409u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder);
1410int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder, 1410int intel_ddi_toggle_hdcp_signalling(struct intel_encoder *intel_encoder,
1411 bool enable); 1411 bool enable);
1412void icl_map_plls_to_ports(struct drm_crtc *crtc,
1413 struct intel_crtc_state *crtc_state,
1414 struct drm_atomic_state *old_state);
1415void icl_unmap_plls_to_ports(struct drm_crtc *crtc,
1416 struct intel_crtc_state *crtc_state,
1417 struct drm_atomic_state *old_state);
1412 1418
1413unsigned int intel_fb_align_height(const struct drm_framebuffer *fb, 1419unsigned int intel_fb_align_height(const struct drm_framebuffer *fb,
1414 int plane, unsigned int height); 1420 int plane, unsigned int height);