diff options
author | Adam Jackson <ajax@redhat.com> | 2010-04-12 11:38:44 -0400 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2010-04-18 19:57:44 -0400 |
commit | 77ffb5979de59efd1a6b280b10d647b09285bee0 (patch) | |
tree | a3a2293c9e944900c59d9b56b778d90c4f766f99 /drivers/gpu | |
parent | 7f8a85698f5c8a981641ec0bdf9926768786db9d (diff) |
drm/i915/pch: Use minimal number of FDI lanes (v2)
This should be a small power savings. Tested on Lenovo T410 (Ironlake), LVDS
VGA and DisplayPort, up to 1920x1200R.
v2: Add Sandybridge support, fix obvious math error.
Acked-by: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 |
2 files changed, 21 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9fdea06f3e73..58668c407f61 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1507,7 +1507,8 @@ static void ironlake_fdi_link_train(struct drm_crtc *crtc) | |||
1507 | /* enable CPU FDI TX and PCH FDI RX */ | 1507 | /* enable CPU FDI TX and PCH FDI RX */ |
1508 | temp = I915_READ(fdi_tx_reg); | 1508 | temp = I915_READ(fdi_tx_reg); |
1509 | temp |= FDI_TX_ENABLE; | 1509 | temp |= FDI_TX_ENABLE; |
1510 | temp |= FDI_DP_PORT_WIDTH_X4; /* default */ | 1510 | temp &= ~(7 << 19); |
1511 | temp |= (intel_crtc->fdi_lanes - 1) << 19; | ||
1511 | temp &= ~FDI_LINK_TRAIN_NONE; | 1512 | temp &= ~FDI_LINK_TRAIN_NONE; |
1512 | temp |= FDI_LINK_TRAIN_PATTERN_1; | 1513 | temp |= FDI_LINK_TRAIN_PATTERN_1; |
1513 | I915_WRITE(fdi_tx_reg, temp); | 1514 | I915_WRITE(fdi_tx_reg, temp); |
@@ -1607,7 +1608,8 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) | |||
1607 | /* enable CPU FDI TX and PCH FDI RX */ | 1608 | /* enable CPU FDI TX and PCH FDI RX */ |
1608 | temp = I915_READ(fdi_tx_reg); | 1609 | temp = I915_READ(fdi_tx_reg); |
1609 | temp |= FDI_TX_ENABLE; | 1610 | temp |= FDI_TX_ENABLE; |
1610 | temp |= FDI_DP_PORT_WIDTH_X4; /* default */ | 1611 | temp &= ~(7 << 19); |
1612 | temp |= (intel_crtc->fdi_lanes - 1) << 19; | ||
1611 | temp &= ~FDI_LINK_TRAIN_NONE; | 1613 | temp &= ~FDI_LINK_TRAIN_NONE; |
1612 | temp |= FDI_LINK_TRAIN_PATTERN_1; | 1614 | temp |= FDI_LINK_TRAIN_PATTERN_1; |
1613 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; | 1615 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; |
@@ -1769,8 +1771,9 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
1769 | */ | 1771 | */ |
1770 | temp &= ~(0x7 << 16); | 1772 | temp &= ~(0x7 << 16); |
1771 | temp |= (pipe_bpc << 11); | 1773 | temp |= (pipe_bpc << 11); |
1772 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE | | 1774 | temp &= ~(7 << 19); |
1773 | FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */ | 1775 | temp |= (intel_crtc->fdi_lanes - 1) << 19; |
1776 | I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE); | ||
1774 | I915_READ(fdi_rx_reg); | 1777 | I915_READ(fdi_rx_reg); |
1775 | udelay(200); | 1778 | udelay(200); |
1776 | 1779 | ||
@@ -3368,7 +3371,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3368 | 3371 | ||
3369 | /* FDI link */ | 3372 | /* FDI link */ |
3370 | if (HAS_PCH_SPLIT(dev)) { | 3373 | if (HAS_PCH_SPLIT(dev)) { |
3371 | int lane, link_bw, bpp; | 3374 | int lane = 0, link_bw, bpp; |
3372 | /* eDP doesn't require FDI link, so just set DP M/N | 3375 | /* eDP doesn't require FDI link, so just set DP M/N |
3373 | according to current link config */ | 3376 | according to current link config */ |
3374 | if (is_edp) { | 3377 | if (is_edp) { |
@@ -3382,7 +3385,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3382 | target_clock = mode->clock; | 3385 | target_clock = mode->clock; |
3383 | else | 3386 | else |
3384 | target_clock = adjusted_mode->clock; | 3387 | target_clock = adjusted_mode->clock; |
3385 | lane = 4; | ||
3386 | link_bw = 270000; | 3388 | link_bw = 270000; |
3387 | } | 3389 | } |
3388 | 3390 | ||
@@ -3434,6 +3436,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
3434 | bpp = 24; | 3436 | bpp = 24; |
3435 | } | 3437 | } |
3436 | 3438 | ||
3439 | if (!lane) { | ||
3440 | /* | ||
3441 | * Account for spread spectrum to avoid | ||
3442 | * oversubscribing the link. Max center spread | ||
3443 | * is 2.5%; use 5% for safety's sake. | ||
3444 | */ | ||
3445 | u32 bps = target_clock * bpp * 21 / 20; | ||
3446 | lane = bps / (link_bw * 8) + 1; | ||
3447 | } | ||
3448 | |||
3449 | intel_crtc->fdi_lanes = lane; | ||
3450 | |||
3437 | ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); | 3451 | ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n); |
3438 | } | 3452 | } |
3439 | 3453 | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8a64c154b42c..1ee4717f431f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -152,6 +152,7 @@ struct intel_crtc { | |||
152 | bool lowfreq_avail; | 152 | bool lowfreq_avail; |
153 | struct intel_overlay *overlay; | 153 | struct intel_overlay *overlay; |
154 | struct intel_unpin_work *unpin_work; | 154 | struct intel_unpin_work *unpin_work; |
155 | int fdi_lanes; | ||
155 | }; | 156 | }; |
156 | 157 | ||
157 | #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) | 158 | #define to_intel_crtc(x) container_of(x, struct intel_crtc, base) |