aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2010-04-12 11:38:44 -0400
committerEric Anholt <eric@anholt.net>2010-04-18 19:57:44 -0400
commit77ffb5979de59efd1a6b280b10d647b09285bee0 (patch)
treea3a2293c9e944900c59d9b56b778d90c4f766f99 /drivers
parent7f8a85698f5c8a981641ec0bdf9926768786db9d (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')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c26
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
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)