diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2012-04-20 12:11:53 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-05-03 05:18:08 -0400 |
commit | ee7b9f93fd96a72e5d09e2b44024c11880873c6b (patch) | |
tree | 81686c6a104dccef07ca2ddd9fa9bc95d7f8676b /drivers/gpu/drm/i915/intel_display.c | |
parent | c2798b19bac2538393fc932bfbe59807a4734b3e (diff) |
drm/i915: manage PCH PLLs separately from pipes
PCH PLLs aren't required for outputs on the CPU, so we shouldn't just
treat them as part of the pipe.
So split the code out and manage PCH PLLs separately, allocating them
when needed or trying to re-use existing PCH PLL setups when the timings
match.
v2: add num_pch_pll field to dev_priv (Daniel)
don't NULL the pch_pll pointer in disable or DPMS will fail (Jesse)
put register offsets in pll struct (Chris)
v3: Decouple enable/disable of PLLs from get/put.
v4: Track temporary PLL disabling during modeset
v5: Tidy PLL initialisation by only checking for num_pch_pll == 0 (Eugeni)
v6: Avoid mishandling allocation failure by embedding the small array of
PLLs into the device struct
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=44309
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> (up to v2)
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> (v3+)
Reviewed-by: Eugeni Dodonov <eugeni.dodonov@intel.com>
Tested-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 271 |
1 files changed, 196 insertions, 75 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 4c844c68ec80..c5f071daa851 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -911,26 +911,28 @@ static void assert_pll(struct drm_i915_private *dev_priv, | |||
911 | 911 | ||
912 | /* For ILK+ */ | 912 | /* For ILK+ */ |
913 | static void assert_pch_pll(struct drm_i915_private *dev_priv, | 913 | static void assert_pch_pll(struct drm_i915_private *dev_priv, |
914 | enum pipe pipe, bool state) | 914 | struct intel_crtc *intel_crtc, bool state) |
915 | { | 915 | { |
916 | int reg; | 916 | int reg; |
917 | u32 val; | 917 | u32 val; |
918 | bool cur_state; | 918 | bool cur_state; |
919 | 919 | ||
920 | if (!intel_crtc->pch_pll) { | ||
921 | WARN(1, "asserting PCH PLL enabled with no PLL\n"); | ||
922 | return; | ||
923 | } | ||
924 | |||
920 | if (HAS_PCH_CPT(dev_priv->dev)) { | 925 | if (HAS_PCH_CPT(dev_priv->dev)) { |
921 | u32 pch_dpll; | 926 | u32 pch_dpll; |
922 | 927 | ||
923 | pch_dpll = I915_READ(PCH_DPLL_SEL); | 928 | pch_dpll = I915_READ(PCH_DPLL_SEL); |
924 | 929 | ||
925 | /* Make sure the selected PLL is enabled to the transcoder */ | 930 | /* Make sure the selected PLL is enabled to the transcoder */ |
926 | WARN(!((pch_dpll >> (4 * pipe)) & 8), | 931 | WARN(!((pch_dpll >> (4 * intel_crtc->pipe)) & 8), |
927 | "transcoder %d PLL not enabled\n", pipe); | 932 | "transcoder %d PLL not enabled\n", intel_crtc->pipe); |
928 | |||
929 | /* Convert the transcoder pipe number to a pll pipe number */ | ||
930 | pipe = (pch_dpll >> (4 * pipe)) & 1; | ||
931 | } | 933 | } |
932 | 934 | ||
933 | reg = PCH_DPLL(pipe); | 935 | reg = intel_crtc->pch_pll->pll_reg; |
934 | val = I915_READ(reg); | 936 | val = I915_READ(reg); |
935 | cur_state = !!(val & DPLL_VCO_ENABLE); | 937 | cur_state = !!(val & DPLL_VCO_ENABLE); |
936 | WARN(cur_state != state, | 938 | WARN(cur_state != state, |
@@ -1306,60 +1308,79 @@ static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) | |||
1306 | * The PCH PLL needs to be enabled before the PCH transcoder, since it | 1308 | * The PCH PLL needs to be enabled before the PCH transcoder, since it |
1307 | * drives the transcoder clock. | 1309 | * drives the transcoder clock. |
1308 | */ | 1310 | */ |
1309 | static void intel_enable_pch_pll(struct drm_i915_private *dev_priv, | 1311 | static void intel_enable_pch_pll(struct intel_crtc *intel_crtc) |
1310 | enum pipe pipe) | ||
1311 | { | 1312 | { |
1313 | struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; | ||
1314 | struct intel_pch_pll *pll = intel_crtc->pch_pll; | ||
1312 | int reg; | 1315 | int reg; |
1313 | u32 val; | 1316 | u32 val; |
1314 | 1317 | ||
1315 | if (pipe > 1) | ||
1316 | return; | ||
1317 | |||
1318 | /* PCH only available on ILK+ */ | 1318 | /* PCH only available on ILK+ */ |
1319 | BUG_ON(dev_priv->info->gen < 5); | 1319 | BUG_ON(dev_priv->info->gen < 5); |
1320 | BUG_ON(pll == NULL); | ||
1321 | BUG_ON(pll->refcount == 0); | ||
1322 | |||
1323 | DRM_DEBUG_KMS("enable PCH PLL %x (active %d, on? %d)for crtc %d\n", | ||
1324 | pll->pll_reg, pll->active, pll->on, | ||
1325 | intel_crtc->base.base.id); | ||
1320 | 1326 | ||
1321 | /* PCH refclock must be enabled first */ | 1327 | /* PCH refclock must be enabled first */ |
1322 | assert_pch_refclk_enabled(dev_priv); | 1328 | assert_pch_refclk_enabled(dev_priv); |
1323 | 1329 | ||
1324 | reg = PCH_DPLL(pipe); | 1330 | if (pll->active++ && pll->on) { |
1331 | assert_pch_pll_enabled(dev_priv, intel_crtc); | ||
1332 | return; | ||
1333 | } | ||
1334 | |||
1335 | DRM_DEBUG_KMS("enabling PCH PLL %x\n", pll->pll_reg); | ||
1336 | |||
1337 | reg = pll->pll_reg; | ||
1325 | val = I915_READ(reg); | 1338 | val = I915_READ(reg); |
1326 | val |= DPLL_VCO_ENABLE; | 1339 | val |= DPLL_VCO_ENABLE; |
1327 | I915_WRITE(reg, val); | 1340 | I915_WRITE(reg, val); |
1328 | POSTING_READ(reg); | 1341 | POSTING_READ(reg); |
1329 | udelay(200); | 1342 | udelay(200); |
1343 | |||
1344 | pll->on = true; | ||
1330 | } | 1345 | } |
1331 | 1346 | ||
1332 | static void intel_disable_pch_pll(struct drm_i915_private *dev_priv, | 1347 | static void intel_disable_pch_pll(struct intel_crtc *intel_crtc) |
1333 | enum pipe pipe) | ||
1334 | { | 1348 | { |
1349 | struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; | ||
1350 | struct intel_pch_pll *pll = intel_crtc->pch_pll; | ||
1335 | int reg; | 1351 | int reg; |
1336 | u32 val, pll_mask = TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL, | 1352 | u32 val; |
1337 | pll_sel = TRANSC_DPLL_ENABLE; | ||
1338 | |||
1339 | if (pipe > 1) | ||
1340 | return; | ||
1341 | 1353 | ||
1342 | /* PCH only available on ILK+ */ | 1354 | /* PCH only available on ILK+ */ |
1343 | BUG_ON(dev_priv->info->gen < 5); | 1355 | BUG_ON(dev_priv->info->gen < 5); |
1356 | if (pll == NULL) | ||
1357 | return; | ||
1344 | 1358 | ||
1345 | /* Make sure transcoder isn't still depending on us */ | 1359 | BUG_ON(pll->refcount == 0); |
1346 | assert_transcoder_disabled(dev_priv, pipe); | ||
1347 | |||
1348 | if (pipe == 0) | ||
1349 | pll_sel |= TRANSC_DPLLA_SEL; | ||
1350 | else if (pipe == 1) | ||
1351 | pll_sel |= TRANSC_DPLLB_SEL; | ||
1352 | 1360 | ||
1361 | DRM_DEBUG_KMS("disable PCH PLL %x (active %d, on? %d) for crtc %d\n", | ||
1362 | pll->pll_reg, pll->active, pll->on, | ||
1363 | intel_crtc->base.base.id); | ||
1353 | 1364 | ||
1354 | if ((I915_READ(PCH_DPLL_SEL) & pll_mask) == pll_sel) | 1365 | BUG_ON(pll->active == 0); |
1366 | if (--pll->active) { | ||
1367 | assert_pch_pll_enabled(dev_priv, intel_crtc); | ||
1355 | return; | 1368 | return; |
1369 | } | ||
1370 | |||
1371 | DRM_DEBUG_KMS("disabling PCH PLL %x\n", pll->pll_reg); | ||
1372 | |||
1373 | /* Make sure transcoder isn't still depending on us */ | ||
1374 | assert_transcoder_disabled(dev_priv, intel_crtc->pipe); | ||
1356 | 1375 | ||
1357 | reg = PCH_DPLL(pipe); | 1376 | reg = pll->pll_reg; |
1358 | val = I915_READ(reg); | 1377 | val = I915_READ(reg); |
1359 | val &= ~DPLL_VCO_ENABLE; | 1378 | val &= ~DPLL_VCO_ENABLE; |
1360 | I915_WRITE(reg, val); | 1379 | I915_WRITE(reg, val); |
1361 | POSTING_READ(reg); | 1380 | POSTING_READ(reg); |
1362 | udelay(200); | 1381 | udelay(200); |
1382 | |||
1383 | pll->on = false; | ||
1363 | } | 1384 | } |
1364 | 1385 | ||
1365 | static void intel_enable_transcoder(struct drm_i915_private *dev_priv, | 1386 | static void intel_enable_transcoder(struct drm_i915_private *dev_priv, |
@@ -1373,7 +1394,7 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv, | |||
1373 | BUG_ON(dev_priv->info->gen < 5); | 1394 | BUG_ON(dev_priv->info->gen < 5); |
1374 | 1395 | ||
1375 | /* Make sure PCH DPLL is enabled */ | 1396 | /* Make sure PCH DPLL is enabled */ |
1376 | assert_pch_pll_enabled(dev_priv, pipe); | 1397 | assert_pch_pll_enabled(dev_priv, to_intel_crtc(crtc)); |
1377 | 1398 | ||
1378 | /* FDI must be feeding us bits for PCH ports */ | 1399 | /* FDI must be feeding us bits for PCH ports */ |
1379 | assert_fdi_tx_enabled(dev_priv, pipe); | 1400 | assert_fdi_tx_enabled(dev_priv, pipe); |
@@ -2578,29 +2599,36 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) | |||
2578 | struct drm_i915_private *dev_priv = dev->dev_private; | 2599 | struct drm_i915_private *dev_priv = dev->dev_private; |
2579 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 2600 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
2580 | int pipe = intel_crtc->pipe; | 2601 | int pipe = intel_crtc->pipe; |
2581 | u32 reg, temp, transc_sel; | 2602 | u32 reg, temp; |
2582 | 2603 | ||
2583 | /* For PCH output, training FDI link */ | 2604 | /* For PCH output, training FDI link */ |
2584 | dev_priv->display.fdi_link_train(crtc); | 2605 | dev_priv->display.fdi_link_train(crtc); |
2585 | 2606 | ||
2586 | intel_enable_pch_pll(dev_priv, pipe); | 2607 | intel_enable_pch_pll(intel_crtc); |
2587 | 2608 | ||
2588 | if (HAS_PCH_CPT(dev)) { | 2609 | if (HAS_PCH_CPT(dev)) { |
2589 | transc_sel = intel_crtc->use_pll_a ? TRANSC_DPLLA_SEL : | 2610 | u32 sel; |
2590 | TRANSC_DPLLB_SEL; | ||
2591 | 2611 | ||
2592 | /* Be sure PCH DPLL SEL is set */ | ||
2593 | temp = I915_READ(PCH_DPLL_SEL); | 2612 | temp = I915_READ(PCH_DPLL_SEL); |
2594 | if (pipe == 0) { | 2613 | switch (pipe) { |
2595 | temp &= ~(TRANSA_DPLLB_SEL); | 2614 | default: |
2596 | temp |= (TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL); | 2615 | case 0: |
2597 | } else if (pipe == 1) { | 2616 | temp |= TRANSA_DPLL_ENABLE; |
2598 | temp &= ~(TRANSB_DPLLB_SEL); | 2617 | sel = TRANSA_DPLLB_SEL; |
2599 | temp |= (TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL); | 2618 | break; |
2600 | } else if (pipe == 2) { | 2619 | case 1: |
2601 | temp &= ~(TRANSC_DPLLB_SEL); | 2620 | temp |= TRANSB_DPLL_ENABLE; |
2602 | temp |= (TRANSC_DPLL_ENABLE | transc_sel); | 2621 | sel = TRANSB_DPLLB_SEL; |
2622 | break; | ||
2623 | case 2: | ||
2624 | temp |= TRANSC_DPLL_ENABLE; | ||
2625 | sel = TRANSC_DPLLB_SEL; | ||
2626 | break; | ||
2603 | } | 2627 | } |
2628 | if (intel_crtc->pch_pll->pll_reg == _PCH_DPLL_B) | ||
2629 | temp |= sel; | ||
2630 | else | ||
2631 | temp &= ~sel; | ||
2604 | I915_WRITE(PCH_DPLL_SEL, temp); | 2632 | I915_WRITE(PCH_DPLL_SEL, temp); |
2605 | } | 2633 | } |
2606 | 2634 | ||
@@ -2658,6 +2686,79 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) | |||
2658 | intel_enable_transcoder(dev_priv, pipe); | 2686 | intel_enable_transcoder(dev_priv, pipe); |
2659 | } | 2687 | } |
2660 | 2688 | ||
2689 | static void intel_put_pch_pll(struct intel_crtc *intel_crtc) | ||
2690 | { | ||
2691 | struct intel_pch_pll *pll = intel_crtc->pch_pll; | ||
2692 | |||
2693 | if (pll == NULL) | ||
2694 | return; | ||
2695 | |||
2696 | if (pll->refcount == 0) { | ||
2697 | WARN(1, "bad PCH PLL refcount\n"); | ||
2698 | return; | ||
2699 | } | ||
2700 | |||
2701 | --pll->refcount; | ||
2702 | intel_crtc->pch_pll = NULL; | ||
2703 | } | ||
2704 | |||
2705 | static struct intel_pch_pll *intel_get_pch_pll(struct intel_crtc *intel_crtc, u32 dpll, u32 fp) | ||
2706 | { | ||
2707 | struct drm_i915_private *dev_priv = intel_crtc->base.dev->dev_private; | ||
2708 | struct intel_pch_pll *pll; | ||
2709 | int i; | ||
2710 | |||
2711 | pll = intel_crtc->pch_pll; | ||
2712 | if (pll) { | ||
2713 | DRM_DEBUG_KMS("CRTC:%d reusing existing PCH PLL %x\n", | ||
2714 | intel_crtc->base.base.id, pll->pll_reg); | ||
2715 | goto prepare; | ||
2716 | } | ||
2717 | |||
2718 | for (i = 0; i < dev_priv->num_pch_pll; i++) { | ||
2719 | pll = &dev_priv->pch_plls[i]; | ||
2720 | |||
2721 | /* Only want to check enabled timings first */ | ||
2722 | if (pll->refcount == 0) | ||
2723 | continue; | ||
2724 | |||
2725 | if (dpll == (I915_READ(pll->pll_reg) & 0x7fffffff) && | ||
2726 | fp == I915_READ(pll->fp0_reg)) { | ||
2727 | DRM_DEBUG_KMS("CRTC:%d sharing existing PCH PLL %x (refcount %d, ative %d)\n", | ||
2728 | intel_crtc->base.base.id, | ||
2729 | pll->pll_reg, pll->refcount, pll->active); | ||
2730 | |||
2731 | goto found; | ||
2732 | } | ||
2733 | } | ||
2734 | |||
2735 | /* Ok no matching timings, maybe there's a free one? */ | ||
2736 | for (i = 0; i < dev_priv->num_pch_pll; i++) { | ||
2737 | pll = &dev_priv->pch_plls[i]; | ||
2738 | if (pll->refcount == 0) { | ||
2739 | DRM_DEBUG_KMS("CRTC:%d allocated PCH PLL %x\n", | ||
2740 | intel_crtc->base.base.id, pll->pll_reg); | ||
2741 | goto found; | ||
2742 | } | ||
2743 | } | ||
2744 | |||
2745 | return NULL; | ||
2746 | |||
2747 | found: | ||
2748 | intel_crtc->pch_pll = pll; | ||
2749 | pll->refcount++; | ||
2750 | DRM_DEBUG_DRIVER("using pll %d for pipe %d\n", i, intel_crtc->pipe); | ||
2751 | prepare: /* separate function? */ | ||
2752 | DRM_DEBUG_DRIVER("switching PLL %x off\n", pll->pll_reg); | ||
2753 | I915_WRITE(pll->fp0_reg, fp); | ||
2754 | I915_WRITE(pll->pll_reg, dpll & ~DPLL_VCO_ENABLE); | ||
2755 | |||
2756 | POSTING_READ(pll->pll_reg); | ||
2757 | udelay(150); | ||
2758 | pll->on = false; | ||
2759 | return pll; | ||
2760 | } | ||
2761 | |||
2661 | void intel_cpt_verify_modeset(struct drm_device *dev, int pipe) | 2762 | void intel_cpt_verify_modeset(struct drm_device *dev, int pipe) |
2662 | { | 2763 | { |
2663 | struct drm_i915_private *dev_priv = dev->dev_private; | 2764 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -2802,8 +2903,7 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) | |||
2802 | } | 2903 | } |
2803 | 2904 | ||
2804 | /* disable PCH DPLL */ | 2905 | /* disable PCH DPLL */ |
2805 | if (!intel_crtc->no_pll) | 2906 | intel_disable_pch_pll(intel_crtc); |
2806 | intel_disable_pch_pll(dev_priv, pipe); | ||
2807 | 2907 | ||
2808 | /* Switch from PCDclk to Rawclk */ | 2908 | /* Switch from PCDclk to Rawclk */ |
2809 | reg = FDI_RX_CTL(pipe); | 2909 | reg = FDI_RX_CTL(pipe); |
@@ -2859,6 +2959,12 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
2859 | } | 2959 | } |
2860 | } | 2960 | } |
2861 | 2961 | ||
2962 | static void ironlake_crtc_off(struct drm_crtc *crtc) | ||
2963 | { | ||
2964 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
2965 | intel_put_pch_pll(intel_crtc); | ||
2966 | } | ||
2967 | |||
2862 | static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) | 2968 | static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) |
2863 | { | 2969 | { |
2864 | if (!enable && intel_crtc->overlay) { | 2970 | if (!enable && intel_crtc->overlay) { |
@@ -2950,6 +3056,10 @@ static void i9xx_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
2950 | } | 3056 | } |
2951 | } | 3057 | } |
2952 | 3058 | ||
3059 | static void i9xx_crtc_off(struct drm_crtc *crtc) | ||
3060 | { | ||
3061 | } | ||
3062 | |||
2953 | /** | 3063 | /** |
2954 | * Sets the power management mode of the pipe and plane. | 3064 | * Sets the power management mode of the pipe and plane. |
2955 | */ | 3065 | */ |
@@ -2997,8 +3107,11 @@ static void intel_crtc_disable(struct drm_crtc *crtc) | |||
2997 | { | 3107 | { |
2998 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | 3108 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; |
2999 | struct drm_device *dev = crtc->dev; | 3109 | struct drm_device *dev = crtc->dev; |
3110 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
3000 | 3111 | ||
3001 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | 3112 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); |
3113 | dev_priv->display.off(crtc); | ||
3114 | |||
3002 | assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); | 3115 | assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); |
3003 | assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); | 3116 | assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); |
3004 | 3117 | ||
@@ -4238,29 +4351,18 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
4238 | DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe); | 4351 | DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe); |
4239 | drm_mode_debug_printmodeline(mode); | 4352 | drm_mode_debug_printmodeline(mode); |
4240 | 4353 | ||
4241 | /* PCH eDP needs FDI, but CPU eDP does not */ | 4354 | /* CPU eDP is the only output that doesn't need a PCH PLL of its own */ |
4242 | if (!intel_crtc->no_pll) { | 4355 | if (!is_cpu_edp) { |
4243 | if (!is_cpu_edp) { | 4356 | struct intel_pch_pll *pll; |
4244 | I915_WRITE(PCH_FP0(pipe), fp); | ||
4245 | I915_WRITE(PCH_DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); | ||
4246 | 4357 | ||
4247 | POSTING_READ(PCH_DPLL(pipe)); | 4358 | pll = intel_get_pch_pll(intel_crtc, dpll, fp); |
4248 | udelay(150); | 4359 | if (pll == NULL) { |
4249 | } | 4360 | DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n", |
4250 | } else { | 4361 | pipe); |
4251 | if (dpll == (I915_READ(PCH_DPLL(0)) & 0x7fffffff) && | ||
4252 | fp == I915_READ(PCH_FP0(0))) { | ||
4253 | intel_crtc->use_pll_a = true; | ||
4254 | DRM_DEBUG_KMS("using pipe a dpll\n"); | ||
4255 | } else if (dpll == (I915_READ(PCH_DPLL(1)) & 0x7fffffff) && | ||
4256 | fp == I915_READ(PCH_FP0(1))) { | ||
4257 | intel_crtc->use_pll_a = false; | ||
4258 | DRM_DEBUG_KMS("using pipe b dpll\n"); | ||
4259 | } else { | ||
4260 | DRM_DEBUG_KMS("no matching PLL configuration for pipe 2\n"); | ||
4261 | return -EINVAL; | 4362 | return -EINVAL; |
4262 | } | 4363 | } |
4263 | } | 4364 | } else |
4365 | intel_put_pch_pll(intel_crtc); | ||
4264 | 4366 | ||
4265 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. | 4367 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. |
4266 | * This is an exception to the general rule that mode_set doesn't turn | 4368 | * This is an exception to the general rule that mode_set doesn't turn |
@@ -4317,11 +4419,11 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
4317 | I915_WRITE(TRANSDPLINK_N1(pipe), 0); | 4419 | I915_WRITE(TRANSDPLINK_N1(pipe), 0); |
4318 | } | 4420 | } |
4319 | 4421 | ||
4320 | if (!intel_crtc->no_pll && (!edp_encoder || is_pch_edp)) { | 4422 | if (intel_crtc->pch_pll) { |
4321 | I915_WRITE(PCH_DPLL(pipe), dpll); | 4423 | I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll); |
4322 | 4424 | ||
4323 | /* Wait for the clocks to stabilize. */ | 4425 | /* Wait for the clocks to stabilize. */ |
4324 | POSTING_READ(PCH_DPLL(pipe)); | 4426 | POSTING_READ(intel_crtc->pch_pll->pll_reg); |
4325 | udelay(150); | 4427 | udelay(150); |
4326 | 4428 | ||
4327 | /* The pixel multiplier can only be updated once the | 4429 | /* The pixel multiplier can only be updated once the |
@@ -4329,20 +4431,20 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, | |||
4329 | * | 4431 | * |
4330 | * So write it again. | 4432 | * So write it again. |
4331 | */ | 4433 | */ |
4332 | I915_WRITE(PCH_DPLL(pipe), dpll); | 4434 | I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll); |
4333 | } | 4435 | } |
4334 | 4436 | ||
4335 | intel_crtc->lowfreq_avail = false; | 4437 | intel_crtc->lowfreq_avail = false; |
4336 | if (!intel_crtc->no_pll) { | 4438 | if (intel_crtc->pch_pll) { |
4337 | if (is_lvds && has_reduced_clock && i915_powersave) { | 4439 | if (is_lvds && has_reduced_clock && i915_powersave) { |
4338 | I915_WRITE(PCH_FP1(pipe), fp2); | 4440 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2); |
4339 | intel_crtc->lowfreq_avail = true; | 4441 | intel_crtc->lowfreq_avail = true; |
4340 | if (HAS_PIPE_CXSR(dev)) { | 4442 | if (HAS_PIPE_CXSR(dev)) { |
4341 | DRM_DEBUG_KMS("enabling CxSR downclocking\n"); | 4443 | DRM_DEBUG_KMS("enabling CxSR downclocking\n"); |
4342 | pipeconf |= PIPECONF_CXSR_DOWNCLOCK; | 4444 | pipeconf |= PIPECONF_CXSR_DOWNCLOCK; |
4343 | } | 4445 | } |
4344 | } else { | 4446 | } else { |
4345 | I915_WRITE(PCH_FP1(pipe), fp); | 4447 | I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp); |
4346 | if (HAS_PIPE_CXSR(dev)) { | 4448 | if (HAS_PIPE_CXSR(dev)) { |
4347 | DRM_DEBUG_KMS("disabling CxSR downclocking\n"); | 4449 | DRM_DEBUG_KMS("disabling CxSR downclocking\n"); |
4348 | pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; | 4450 | pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK; |
@@ -6016,6 +6118,23 @@ static const struct drm_crtc_funcs intel_crtc_funcs = { | |||
6016 | .page_flip = intel_crtc_page_flip, | 6118 | .page_flip = intel_crtc_page_flip, |
6017 | }; | 6119 | }; |
6018 | 6120 | ||
6121 | static void intel_pch_pll_init(struct drm_device *dev) | ||
6122 | { | ||
6123 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
6124 | int i; | ||
6125 | |||
6126 | if (dev_priv->num_pch_pll == 0) { | ||
6127 | DRM_DEBUG_KMS("No PCH PLLs on this hardware, skipping initialisation\n"); | ||
6128 | return; | ||
6129 | } | ||
6130 | |||
6131 | for (i = 0; i < dev_priv->num_pch_pll; i++) { | ||
6132 | dev_priv->pch_plls[i].pll_reg = _PCH_DPLL(i); | ||
6133 | dev_priv->pch_plls[i].fp0_reg = _PCH_FP0(i); | ||
6134 | dev_priv->pch_plls[i].fp1_reg = _PCH_FP1(i); | ||
6135 | } | ||
6136 | } | ||
6137 | |||
6019 | static void intel_crtc_init(struct drm_device *dev, int pipe) | 6138 | static void intel_crtc_init(struct drm_device *dev, int pipe) |
6020 | { | 6139 | { |
6021 | drm_i915_private_t *dev_priv = dev->dev_private; | 6140 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -6053,8 +6172,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) | |||
6053 | intel_crtc->bpp = 24; /* default for pre-Ironlake */ | 6172 | intel_crtc->bpp = 24; /* default for pre-Ironlake */ |
6054 | 6173 | ||
6055 | if (HAS_PCH_SPLIT(dev)) { | 6174 | if (HAS_PCH_SPLIT(dev)) { |
6056 | if (pipe == 2 && IS_IVYBRIDGE(dev)) | ||
6057 | intel_crtc->no_pll = true; | ||
6058 | intel_helper_funcs.prepare = ironlake_crtc_prepare; | 6175 | intel_helper_funcs.prepare = ironlake_crtc_prepare; |
6059 | intel_helper_funcs.commit = ironlake_crtc_commit; | 6176 | intel_helper_funcs.commit = ironlake_crtc_commit; |
6060 | } else { | 6177 | } else { |
@@ -6337,10 +6454,12 @@ static void intel_init_display(struct drm_device *dev) | |||
6337 | if (HAS_PCH_SPLIT(dev)) { | 6454 | if (HAS_PCH_SPLIT(dev)) { |
6338 | dev_priv->display.dpms = ironlake_crtc_dpms; | 6455 | dev_priv->display.dpms = ironlake_crtc_dpms; |
6339 | dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; | 6456 | dev_priv->display.crtc_mode_set = ironlake_crtc_mode_set; |
6457 | dev_priv->display.off = ironlake_crtc_off; | ||
6340 | dev_priv->display.update_plane = ironlake_update_plane; | 6458 | dev_priv->display.update_plane = ironlake_update_plane; |
6341 | } else { | 6459 | } else { |
6342 | dev_priv->display.dpms = i9xx_crtc_dpms; | 6460 | dev_priv->display.dpms = i9xx_crtc_dpms; |
6343 | dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; | 6461 | dev_priv->display.crtc_mode_set = i9xx_crtc_mode_set; |
6462 | dev_priv->display.off = i9xx_crtc_off; | ||
6344 | dev_priv->display.update_plane = i9xx_update_plane; | 6463 | dev_priv->display.update_plane = i9xx_update_plane; |
6345 | } | 6464 | } |
6346 | 6465 | ||
@@ -6603,6 +6722,8 @@ void intel_modeset_init(struct drm_device *dev) | |||
6603 | DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret); | 6722 | DRM_DEBUG_KMS("plane %d init failed: %d\n", i, ret); |
6604 | } | 6723 | } |
6605 | 6724 | ||
6725 | intel_pch_pll_init(dev); | ||
6726 | |||
6606 | /* Just disable it once at startup */ | 6727 | /* Just disable it once at startup */ |
6607 | i915_disable_vga(dev); | 6728 | i915_disable_vga(dev); |
6608 | intel_setup_outputs(dev); | 6729 | intel_setup_outputs(dev); |