diff options
| author | Adam Jackson <ajax@redhat.com> | 2010-04-12 11:38:44 -0400 | 
|---|---|---|
| committer | Eric Anholt <eric@anholt.net> | 2010-04-18 16:57:44 -0700 | 
| commit | 77ffb5979de59efd1a6b280b10d647b09285bee0 (patch) | |
| tree | a3a2293c9e944900c59d9b56b778d90c4f766f99 | |
| 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>
| -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 9fdea06f3e7..58668c407f6 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)  	/* enable CPU FDI TX and PCH FDI RX */  	temp = I915_READ(fdi_tx_reg);  	temp |= FDI_TX_ENABLE; -	temp |= FDI_DP_PORT_WIDTH_X4; /* default */ +	temp &= ~(7 << 19); +	temp |= (intel_crtc->fdi_lanes - 1) << 19;  	temp &= ~FDI_LINK_TRAIN_NONE;  	temp |= FDI_LINK_TRAIN_PATTERN_1;  	I915_WRITE(fdi_tx_reg, temp); @@ -1607,7 +1608,8 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)  	/* enable CPU FDI TX and PCH FDI RX */  	temp = I915_READ(fdi_tx_reg);  	temp |= FDI_TX_ENABLE; -	temp |= FDI_DP_PORT_WIDTH_X4; /* default */ +	temp &= ~(7 << 19); +	temp |= (intel_crtc->fdi_lanes - 1) << 19;  	temp &= ~FDI_LINK_TRAIN_NONE;  	temp |= FDI_LINK_TRAIN_PATTERN_1;  	temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; @@ -1769,8 +1771,9 @@ static void ironlake_crtc_dpms(struct drm_crtc *crtc, int mode)  			 */  			temp &= ~(0x7 << 16);  			temp |= (pipe_bpc << 11); -			I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE | -					FDI_DP_PORT_WIDTH_X4); /* default 4 lanes */ +			temp &= ~(7 << 19); +			temp |= (intel_crtc->fdi_lanes - 1) << 19; +			I915_WRITE(fdi_rx_reg, temp | FDI_RX_PLL_ENABLE);  			I915_READ(fdi_rx_reg);  			udelay(200); @@ -3368,7 +3371,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,  	/* FDI link */  	if (HAS_PCH_SPLIT(dev)) { -		int lane, link_bw, bpp; +		int lane = 0, link_bw, bpp;  		/* eDP doesn't require FDI link, so just set DP M/N  		   according to current link config */  		if (is_edp) { @@ -3382,7 +3385,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,  				target_clock = mode->clock;  			else  				target_clock = adjusted_mode->clock; -			lane = 4;  			link_bw = 270000;  		} @@ -3434,6 +3436,18 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,  			bpp = 24;  		} +		if (!lane) { +			/*  +			 * Account for spread spectrum to avoid +			 * oversubscribing the link. Max center spread +			 * is 2.5%; use 5% for safety's sake. +			 */ +			u32 bps = target_clock * bpp * 21 / 20; +			lane = bps / (link_bw * 8) + 1; +		} + +		intel_crtc->fdi_lanes = lane; +  		ironlake_compute_m_n(bpp, lane, target_clock, link_bw, &m_n);  	} diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8a64c154b42..1ee4717f431 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -152,6 +152,7 @@ struct intel_crtc {  	bool lowfreq_avail;  	struct intel_overlay *overlay;  	struct intel_unpin_work *unpin_work; +	int fdi_lanes;  };  #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)  | 
