diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 388 | 
1 files changed, 240 insertions, 148 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 397087cf689..d514719f65e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -75,7 +75,7 @@ struct intel_limit {  	intel_range_t   dot, vco, n, m, m1, m2, p, p1;  	intel_p2_t	    p2;  	bool (* find_pll)(const intel_limit_t *, struct drm_crtc *, -			int, int, intel_clock_t *); +			int, int, intel_clock_t *, intel_clock_t *);  };  /* FDI */ @@ -83,17 +83,21 @@ struct intel_limit {  static bool  intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, -		    int target, int refclk, intel_clock_t *best_clock); +		    int target, int refclk, intel_clock_t *match_clock, +		    intel_clock_t *best_clock);  static bool  intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, -			int target, int refclk, intel_clock_t *best_clock); +			int target, int refclk, intel_clock_t *match_clock, +			intel_clock_t *best_clock);  static bool  intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, -		      int target, int refclk, intel_clock_t *best_clock); +		      int target, int refclk, intel_clock_t *match_clock, +		      intel_clock_t *best_clock);  static bool  intel_find_pll_ironlake_dp(const intel_limit_t *, struct drm_crtc *crtc, -			   int target, int refclk, intel_clock_t *best_clock); +			   int target, int refclk, intel_clock_t *match_clock, +			   intel_clock_t *best_clock);  static inline u32 /* units of 100MHz */  intel_fdi_link_freq(struct drm_device *dev) @@ -515,7 +519,8 @@ static bool intel_PLL_is_valid(struct drm_device *dev,  static bool  intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, -		    int target, int refclk, intel_clock_t *best_clock) +		    int target, int refclk, intel_clock_t *match_clock, +		    intel_clock_t *best_clock)  {  	struct drm_device *dev = crtc->dev; @@ -562,6 +567,9 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,  					if (!intel_PLL_is_valid(dev, limit,  								&clock))  						continue; +					if (match_clock && +					    clock.p != match_clock->p) +						continue;  					this_err = abs(clock.dot - target);  					if (this_err < err) { @@ -578,7 +586,8 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,  static bool  intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, -			int target, int refclk, intel_clock_t *best_clock) +			int target, int refclk, intel_clock_t *match_clock, +			intel_clock_t *best_clock)  {  	struct drm_device *dev = crtc->dev;  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -625,6 +634,9 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,  					if (!intel_PLL_is_valid(dev, limit,  								&clock))  						continue; +					if (match_clock && +					    clock.p != match_clock->p) +						continue;  					this_err = abs(clock.dot - target);  					if (this_err < err_most) { @@ -642,7 +654,8 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,  static bool  intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc, -			   int target, int refclk, intel_clock_t *best_clock) +			   int target, int refclk, intel_clock_t *match_clock, +			   intel_clock_t *best_clock)  {  	struct drm_device *dev = crtc->dev;  	intel_clock_t clock; @@ -668,7 +681,8 @@ intel_find_pll_ironlake_dp(const intel_limit_t *limit, struct drm_crtc *crtc,  /* DisplayPort has only two frequencies, 162MHz and 270MHz */  static bool  intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, -		      int target, int refclk, intel_clock_t *best_clock) +		      int target, int refclk, intel_clock_t *match_clock, +		      intel_clock_t *best_clock)  {  	intel_clock_t clock;  	if (target < 200000) { @@ -922,6 +936,10 @@ void assert_pipe(struct drm_i915_private *dev_priv,  	u32 val;  	bool cur_state; +	/* if we need the pipe A quirk it must be always on */ +	if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) +		state = true; +  	reg = PIPECONF(pipe);  	val = I915_READ(reg);  	cur_state = !!(val & PIPECONF_ENABLE); @@ -930,19 +948,24 @@ void assert_pipe(struct drm_i915_private *dev_priv,  	     pipe_name(pipe), state_string(state), state_string(cur_state));  } -static void assert_plane_enabled(struct drm_i915_private *dev_priv, -				 enum plane plane) +static void assert_plane(struct drm_i915_private *dev_priv, +			 enum plane plane, bool state)  {  	int reg;  	u32 val; +	bool cur_state;  	reg = DSPCNTR(plane);  	val = I915_READ(reg); -	WARN(!(val & DISPLAY_PLANE_ENABLE), -	     "plane %c assertion failure, should be active but is disabled\n", -	     plane_name(plane)); +	cur_state = !!(val & DISPLAY_PLANE_ENABLE); +	WARN(cur_state != state, +	     "plane %c assertion failure (expected %s, current %s)\n", +	     plane_name(plane), state_string(state), state_string(cur_state));  } +#define assert_plane_enabled(d, p) assert_plane(d, p, true) +#define assert_plane_disabled(d, p) assert_plane(d, p, false) +  static void assert_planes_disabled(struct drm_i915_private *dev_priv,  				   enum pipe pipe)  { @@ -951,8 +974,14 @@ static void assert_planes_disabled(struct drm_i915_private *dev_priv,  	int cur_pipe;  	/* Planes are fixed to pipes on ILK+ */ -	if (HAS_PCH_SPLIT(dev_priv->dev)) +	if (HAS_PCH_SPLIT(dev_priv->dev)) { +		reg = DSPCNTR(pipe); +		val = I915_READ(reg); +		WARN((val & DISPLAY_PLANE_ENABLE), +		     "plane %c assertion failure, should be disabled but not\n", +		     plane_name(pipe));  		return; +	}  	/* Need to check both planes against the pipe */  	for (i = 0; i < 2; i++) { @@ -1071,7 +1100,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,  {  	u32 val = I915_READ(reg);  	WARN(hdmi_pipe_enabled(dev_priv, val, pipe), -	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n", +	     "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",  	     reg, pipe_name(pipe));  } @@ -1237,7 +1266,8 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,  				    enum pipe pipe)  {  	int reg; -	u32 val; +	u32 val, pipeconf_val; +	struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe];  	/* PCH only available on ILK+ */  	BUG_ON(dev_priv->info->gen < 5); @@ -1251,6 +1281,7 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,  	reg = TRANSCONF(pipe);  	val = I915_READ(reg); +	pipeconf_val = I915_READ(PIPECONF(pipe));  	if (HAS_PCH_IBX(dev_priv->dev)) {  		/* @@ -1258,8 +1289,19 @@ static void intel_enable_transcoder(struct drm_i915_private *dev_priv,  		 * that in pipeconf reg.  		 */  		val &= ~PIPE_BPC_MASK; -		val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK; +		val |= pipeconf_val & PIPE_BPC_MASK;  	} + +	val &= ~TRANS_INTERLACE_MASK; +	if ((pipeconf_val & PIPECONF_INTERLACE_MASK) == PIPECONF_INTERLACED_ILK) +		if (HAS_PCH_IBX(dev_priv->dev) && +		    intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) +			val |= TRANS_LEGACY_INTERLACED_ILK; +		else +			val |= TRANS_INTERLACED; +	else +		val |= TRANS_PROGRESSIVE; +  	I915_WRITE(reg, val | TRANS_ENABLE);  	if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))  		DRM_ERROR("failed to enable transcoder %d\n", pipe); @@ -2012,6 +2054,8 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev,  		ret = i915_gem_object_get_fence(obj, pipelined);  		if (ret)  			goto err_unpin; + +		i915_gem_object_pin_fence(obj);  	}  	dev_priv->mm.interruptible = true; @@ -2024,6 +2068,12 @@ err_interruptible:  	return ret;  } +void intel_unpin_fb_obj(struct drm_i915_gem_object *obj) +{ +	i915_gem_object_unpin_fence(obj); +	i915_gem_object_unpin(obj); +} +  static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,  			     int x, int y)  { @@ -2255,7 +2305,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,  	ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,  					 LEAVE_ATOMIC_MODE_SET);  	if (ret) { -		i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); +		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);  		mutex_unlock(&dev->struct_mutex);  		DRM_ERROR("failed to update base address\n");  		return ret; @@ -2263,7 +2313,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,  	if (old_fb) {  		intel_wait_for_vblank(dev, intel_crtc->pipe); -		i915_gem_object_unpin(to_intel_framebuffer(old_fb)->obj); +		intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);  	}  	mutex_unlock(&dev->struct_mutex); @@ -2936,6 +2986,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)  	I915_WRITE(TRANS_VTOTAL(pipe), I915_READ(VTOTAL(pipe)));  	I915_WRITE(TRANS_VBLANK(pipe), I915_READ(VBLANK(pipe)));  	I915_WRITE(TRANS_VSYNC(pipe),  I915_READ(VSYNC(pipe))); +	I915_WRITE(TRANS_VSYNCSHIFT(pipe),  I915_READ(VSYNCSHIFT(pipe)));  	intel_fdi_normal_train(crtc); @@ -3321,10 +3372,12 @@ static void intel_crtc_disable(struct drm_crtc *crtc)  	struct drm_device *dev = crtc->dev;  	crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); +	assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); +	assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);  	if (crtc->fb) {  		mutex_lock(&dev->struct_mutex); -		i915_gem_object_unpin(to_intel_framebuffer(crtc->fb)->obj); +		intel_unpin_fb_obj(to_intel_framebuffer(crtc->fb)->obj);  		mutex_unlock(&dev->struct_mutex);  	}  } @@ -3398,11 +3451,8 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,  			return false;  	} -	/* XXX some encoders set the crtcinfo, others don't. -	 * Obviously we need some form of conflict resolution here... -	 */ -	if (adjusted_mode->crtc_htotal == 0) -		drm_mode_set_crtcinfo(adjusted_mode, 0); +	/* All interlaced capable intel hw wants timings in frames. */ +	drm_mode_set_crtcinfo(adjusted_mode, 0);  	return true;  } @@ -4521,6 +4571,7 @@ void sandybridge_update_wm(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */ +	u32 val;  	int fbc_wm, plane_wm, cursor_wm;  	unsigned int enabled; @@ -4529,8 +4580,10 @@ void sandybridge_update_wm(struct drm_device *dev)  			    &sandybridge_display_wm_info, latency,  			    &sandybridge_cursor_wm_info, latency,  			    &plane_wm, &cursor_wm)) { -		I915_WRITE(WM0_PIPEA_ILK, -			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); +		val = I915_READ(WM0_PIPEA_ILK); +		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); +		I915_WRITE(WM0_PIPEA_ILK, val | +			   ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));  		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"  			      " plane %d, " "cursor: %d\n",  			      plane_wm, cursor_wm); @@ -4541,8 +4594,10 @@ void sandybridge_update_wm(struct drm_device *dev)  			    &sandybridge_display_wm_info, latency,  			    &sandybridge_cursor_wm_info, latency,  			    &plane_wm, &cursor_wm)) { -		I915_WRITE(WM0_PIPEB_ILK, -			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); +		val = I915_READ(WM0_PIPEB_ILK); +		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); +		I915_WRITE(WM0_PIPEB_ILK, val | +			   ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));  		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"  			      " plane %d, cursor: %d\n",  			      plane_wm, cursor_wm); @@ -4555,8 +4610,10 @@ void sandybridge_update_wm(struct drm_device *dev)  			    &sandybridge_display_wm_info, latency,  			    &sandybridge_cursor_wm_info, latency,  			    &plane_wm, &cursor_wm)) { -		I915_WRITE(WM0_PIPEC_IVB, -			   (plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm); +		val = I915_READ(WM0_PIPEC_IVB); +		val &= ~(WM0_PIPE_PLANE_MASK | WM0_PIPE_CURSOR_MASK); +		I915_WRITE(WM0_PIPEC_IVB, val | +			   ((plane_wm << WM0_PIPE_PLANE_SHIFT) | cursor_wm));  		DRM_DEBUG_KMS("FIFO watermarks For pipe C -"  			      " plane %d, cursor: %d\n",  			      plane_wm, cursor_wm); @@ -4709,6 +4766,7 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */ +	u32 val;  	int sprite_wm, reg;  	int ret; @@ -4735,7 +4793,9 @@ static void sandybridge_update_sprite_wm(struct drm_device *dev, int pipe,  		return;  	} -	I915_WRITE(reg, I915_READ(reg) | (sprite_wm << WM0_PIPE_SPRITE_SHIFT)); +	val = I915_READ(reg); +	val &= ~WM0_PIPE_SPRITE_MASK; +	I915_WRITE(reg, val | (sprite_wm << WM0_PIPE_SPRITE_SHIFT));  	DRM_DEBUG_KMS("sprite watermarks For pipe %d - %d\n", pipe, sprite_wm); @@ -4977,6 +5037,82 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,  	return display_bpc != bpc;  } +static int i9xx_get_refclk(struct drm_crtc *crtc, int num_connectors) +{ +	struct drm_device *dev = crtc->dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	int refclk; + +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && +	    intel_panel_use_ssc(dev_priv) && num_connectors < 2) { +		refclk = dev_priv->lvds_ssc_freq * 1000; +		DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", +			      refclk / 1000); +	} else if (!IS_GEN2(dev)) { +		refclk = 96000; +	} else { +		refclk = 48000; +	} + +	return refclk; +} + +static void i9xx_adjust_sdvo_tv_clock(struct drm_display_mode *adjusted_mode, +				      intel_clock_t *clock) +{ +	/* SDVO TV has fixed PLL values depend on its clock range, +	   this mirrors vbios setting. */ +	if (adjusted_mode->clock >= 100000 +	    && adjusted_mode->clock < 140500) { +		clock->p1 = 2; +		clock->p2 = 10; +		clock->n = 3; +		clock->m1 = 16; +		clock->m2 = 8; +	} else if (adjusted_mode->clock >= 140500 +		   && adjusted_mode->clock <= 200000) { +		clock->p1 = 1; +		clock->p2 = 10; +		clock->n = 6; +		clock->m1 = 12; +		clock->m2 = 8; +	} +} + +static void i9xx_update_pll_dividers(struct drm_crtc *crtc, +				     intel_clock_t *clock, +				     intel_clock_t *reduced_clock) +{ +	struct drm_device *dev = crtc->dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	int pipe = intel_crtc->pipe; +	u32 fp, fp2 = 0; + +	if (IS_PINEVIEW(dev)) { +		fp = (1 << clock->n) << 16 | clock->m1 << 8 | clock->m2; +		if (reduced_clock) +			fp2 = (1 << reduced_clock->n) << 16 | +				reduced_clock->m1 << 8 | reduced_clock->m2; +	} else { +		fp = clock->n << 16 | clock->m1 << 8 | clock->m2; +		if (reduced_clock) +			fp2 = reduced_clock->n << 16 | reduced_clock->m1 << 8 | +				reduced_clock->m2; +	} + +	I915_WRITE(FP0(pipe), fp); + +	intel_crtc->lowfreq_avail = false; +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && +	    reduced_clock && i915_powersave) { +		I915_WRITE(FP1(pipe), fp2); +		intel_crtc->lowfreq_avail = true; +	} else { +		I915_WRITE(FP1(pipe), fp); +	} +} +  static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  			      struct drm_display_mode *mode,  			      struct drm_display_mode *adjusted_mode, @@ -4990,7 +5126,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  	int plane = intel_crtc->plane;  	int refclk, num_connectors = 0;  	intel_clock_t clock, reduced_clock; -	u32 dpll, fp = 0, fp2 = 0, dspcntr, pipeconf; +	u32 dpll, dspcntr, pipeconf, vsyncshift;  	bool ok, has_reduced_clock = false, is_sdvo = false, is_dvo = false;  	bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false;  	struct drm_mode_config *mode_config = &dev->mode_config; @@ -5031,15 +5167,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  		num_connectors++;  	} -	if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) { -		refclk = dev_priv->lvds_ssc_freq * 1000; -		DRM_DEBUG_KMS("using SSC reference clock of %d MHz\n", -			      refclk / 1000); -	} else if (!IS_GEN2(dev)) { -		refclk = 96000; -	} else { -		refclk = 48000; -	} +	refclk = i9xx_get_refclk(crtc, num_connectors);  	/*  	 * Returns a set of divisors for the desired target clock with the given @@ -5047,7 +5175,8 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  	 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.  	 */  	limit = intel_limit(crtc, refclk); -	ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); +	ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL, +			     &clock);  	if (!ok) {  		DRM_ERROR("Couldn't find PLL settings for mode!\n");  		return -EINVAL; @@ -5057,53 +5186,24 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  	intel_crtc_update_cursor(crtc, true);  	if (is_lvds && dev_priv->lvds_downclock_avail) { +		/* +		 * Ensure we match the reduced clock's P to the target clock. +		 * If the clocks don't match, we can't switch the display clock +		 * by using the FP0/FP1. In such case we will disable the LVDS +		 * downclock feature. +		*/  		has_reduced_clock = limit->find_pll(limit, crtc,  						    dev_priv->lvds_downclock,  						    refclk, +						    &clock,  						    &reduced_clock); -		if (has_reduced_clock && (clock.p != reduced_clock.p)) { -			/* -			 * If the different P is found, it means that we can't -			 * switch the display clock by using the FP0/FP1. -			 * In such case we will disable the LVDS downclock -			 * feature. -			 */ -			DRM_DEBUG_KMS("Different P is found for " -				      "LVDS clock/downclock\n"); -			has_reduced_clock = 0; -		} -	} -	/* SDVO TV has fixed PLL values depend on its clock range, -	   this mirrors vbios setting. */ -	if (is_sdvo && is_tv) { -		if (adjusted_mode->clock >= 100000 -		    && adjusted_mode->clock < 140500) { -			clock.p1 = 2; -			clock.p2 = 10; -			clock.n = 3; -			clock.m1 = 16; -			clock.m2 = 8; -		} else if (adjusted_mode->clock >= 140500 -			   && adjusted_mode->clock <= 200000) { -			clock.p1 = 1; -			clock.p2 = 10; -			clock.n = 6; -			clock.m1 = 12; -			clock.m2 = 8; -		}  	} -	if (IS_PINEVIEW(dev)) { -		fp = (1 << clock.n) << 16 | clock.m1 << 8 | clock.m2; -		if (has_reduced_clock) -			fp2 = (1 << reduced_clock.n) << 16 | -				reduced_clock.m1 << 8 | reduced_clock.m2; -	} else { -		fp = clock.n << 16 | clock.m1 << 8 | clock.m2; -		if (has_reduced_clock) -			fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | -				reduced_clock.m2; -	} +	if (is_sdvo && is_tv) +		i9xx_adjust_sdvo_tv_clock(adjusted_mode, &clock); + +	i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ? +				 &reduced_clock : NULL);  	dpll = DPLL_VGA_MODE_DIS; @@ -5177,8 +5277,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  	/* Set up the display plane register */  	dspcntr = DISPPLANE_GAMMA_ENABLE; -	/* Ironlake's plane is forced to pipe, bit 24 is to -	   enable color space conversion */  	if (pipe == 0)  		dspcntr &= ~DISPPLANE_SEL_PIPE_MASK;  	else @@ -5213,7 +5311,6 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');  	drm_mode_debug_printmodeline(mode); -	I915_WRITE(FP0(pipe), fp);  	I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE);  	POSTING_READ(DPLL(pipe)); @@ -5300,34 +5397,32 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  		I915_WRITE(DPLL(pipe), dpll);  	} -	intel_crtc->lowfreq_avail = false; -	if (is_lvds && has_reduced_clock && i915_powersave) { -		I915_WRITE(FP1(pipe), fp2); -		intel_crtc->lowfreq_avail = true; -		if (HAS_PIPE_CXSR(dev)) { +	if (HAS_PIPE_CXSR(dev)) { +		if (intel_crtc->lowfreq_avail) {  			DRM_DEBUG_KMS("enabling CxSR downclocking\n");  			pipeconf |= PIPECONF_CXSR_DOWNCLOCK; -		} -	} else { -		I915_WRITE(FP1(pipe), fp); -		if (HAS_PIPE_CXSR(dev)) { +		} else {  			DRM_DEBUG_KMS("disabling CxSR downclocking\n");  			pipeconf &= ~PIPECONF_CXSR_DOWNCLOCK;  		}  	}  	pipeconf &= ~PIPECONF_INTERLACE_MASK; -	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { +	if (!IS_GEN2(dev) && +	    adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) {  		pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION;  		/* the chip adds 2 halflines automatically */ -		adjusted_mode->crtc_vdisplay -= 1;  		adjusted_mode->crtc_vtotal -= 1; -		adjusted_mode->crtc_vblank_start -= 1;  		adjusted_mode->crtc_vblank_end -= 1; -		adjusted_mode->crtc_vsync_end -= 1; -		adjusted_mode->crtc_vsync_start -= 1; -	} else +		vsyncshift = adjusted_mode->crtc_hsync_start +			     - adjusted_mode->crtc_htotal/2; +	} else {  		pipeconf |= PIPECONF_PROGRESSIVE; +		vsyncshift = 0; +	} + +	if (!IS_GEN3(dev)) +		I915_WRITE(VSYNCSHIFT(pipe), vsyncshift);  	I915_WRITE(HTOTAL(pipe),  		   (adjusted_mode->crtc_hdisplay - 1) | @@ -5593,7 +5688,8 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  	 * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2.  	 */  	limit = intel_limit(crtc, refclk); -	ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, &clock); +	ok = limit->find_pll(limit, crtc, adjusted_mode->clock, refclk, NULL, +			     &clock);  	if (!ok) {  		DRM_ERROR("Couldn't find PLL settings for mode!\n");  		return -EINVAL; @@ -5603,21 +5699,17 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  	intel_crtc_update_cursor(crtc, true);  	if (is_lvds && dev_priv->lvds_downclock_avail) { +		/* +		 * Ensure we match the reduced clock's P to the target clock. +		 * If the clocks don't match, we can't switch the display clock +		 * by using the FP0/FP1. In such case we will disable the LVDS +		 * downclock feature. +		*/  		has_reduced_clock = limit->find_pll(limit, crtc,  						    dev_priv->lvds_downclock,  						    refclk, +						    &clock,  						    &reduced_clock); -		if (has_reduced_clock && (clock.p != reduced_clock.p)) { -			/* -			 * If the different P is found, it means that we can't -			 * switch the display clock by using the FP0/FP1. -			 * In such case we will disable the LVDS downclock -			 * feature. -			 */ -			DRM_DEBUG_KMS("Different P is found for " -				      "LVDS clock/downclock\n"); -			has_reduced_clock = 0; -		}  	}  	/* SDVO TV has fixed PLL values depend on its clock range,  	   this mirrors vbios setting. */ @@ -5914,16 +6006,17 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  	pipeconf &= ~PIPECONF_INTERLACE_MASK;  	if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { -		pipeconf |= PIPECONF_INTERLACE_W_FIELD_INDICATION; +		pipeconf |= PIPECONF_INTERLACED_ILK;  		/* the chip adds 2 halflines automatically */ -		adjusted_mode->crtc_vdisplay -= 1;  		adjusted_mode->crtc_vtotal -= 1; -		adjusted_mode->crtc_vblank_start -= 1;  		adjusted_mode->crtc_vblank_end -= 1; -		adjusted_mode->crtc_vsync_end -= 1; -		adjusted_mode->crtc_vsync_start -= 1; -	} else +		I915_WRITE(VSYNCSHIFT(pipe), +			   adjusted_mode->crtc_hsync_start +			   - adjusted_mode->crtc_htotal/2); +	} else {  		pipeconf |= PIPECONF_PROGRESSIVE; +		I915_WRITE(VSYNCSHIFT(pipe), 0); +	}  	I915_WRITE(HTOTAL(pipe),  		   (adjusted_mode->crtc_hdisplay - 1) | @@ -5966,12 +6059,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  	intel_wait_for_vblank(dev, pipe); -	if (IS_GEN5(dev)) { -		/* enable address swizzle for tiling buffer */ -		temp = I915_READ(DISP_ARB_CTL); -		I915_WRITE(DISP_ARB_CTL, temp | DISP_TILE_SURFACE_SWIZZLING); -	} -  	I915_WRITE(DSPCNTR(plane), dspcntr);  	POSTING_READ(DSPCNTR(plane)); @@ -6086,15 +6173,18 @@ static void ironlake_write_eld(struct drm_connector *connector,  	uint32_t i;  	int len;  	int hdmiw_hdmiedid; +	int aud_config;  	int aud_cntl_st;  	int aud_cntrl_st2;  	if (HAS_PCH_IBX(connector->dev)) {  		hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID_A; +		aud_config = IBX_AUD_CONFIG_A;  		aud_cntl_st = IBX_AUD_CNTL_ST_A;  		aud_cntrl_st2 = IBX_AUD_CNTL_ST2;  	} else {  		hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID_A; +		aud_config = CPT_AUD_CONFIG_A;  		aud_cntl_st = CPT_AUD_CNTL_ST_A;  		aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;  	} @@ -6102,6 +6192,7 @@ static void ironlake_write_eld(struct drm_connector *connector,  	i = to_intel_crtc(crtc)->pipe;  	hdmiw_hdmiedid += i * 0x100;  	aud_cntl_st += i * 0x100; +	aud_config += i * 0x100;  	DRM_DEBUG_DRIVER("ELD on pipe %c\n", pipe_name(i)); @@ -6121,7 +6212,9 @@ static void ironlake_write_eld(struct drm_connector *connector,  	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) {  		DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n");  		eld[5] |= (1 << 2);	/* Conn_Type, 0x1 = DisplayPort */ -	} +		I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ +	} else +		I915_WRITE(aud_config, 0);  	if (intel_eld_uptodate(connector,  			       aud_cntrl_st2, eldv, @@ -6927,9 +7020,7 @@ static void intel_increase_pllclock(struct drm_crtc *crtc)  	if (!HAS_PIPE_CXSR(dev) && (dpll & DISPLAY_RATE_SELECT_FPA1)) {  		DRM_DEBUG_DRIVER("upclocking LVDS\n"); -		/* Unlock panel regs */ -		I915_WRITE(PP_CONTROL, -			   I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS); +		assert_panel_unlocked(dev_priv, pipe);  		dpll &= ~DISPLAY_RATE_SELECT_FPA1;  		I915_WRITE(dpll_reg, dpll); @@ -6938,9 +7029,6 @@ static void intel_increase_pllclock(struct drm_crtc *crtc)  		dpll = I915_READ(dpll_reg);  		if (dpll & DISPLAY_RATE_SELECT_FPA1)  			DRM_DEBUG_DRIVER("failed to upclock LVDS!\n"); - -		/* ...and lock them again */ -		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);  	}  	/* Schedule downclock */ @@ -6970,9 +7058,7 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)  	if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) {  		DRM_DEBUG_DRIVER("downclocking LVDS\n"); -		/* Unlock panel regs */ -		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) | -			   PANEL_UNLOCK_REGS); +		assert_panel_unlocked(dev_priv, pipe);  		dpll |= DISPLAY_RATE_SELECT_FPA1;  		I915_WRITE(dpll_reg, dpll); @@ -6980,9 +7066,6 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)  		dpll = I915_READ(dpll_reg);  		if (!(dpll & DISPLAY_RATE_SELECT_FPA1))  			DRM_DEBUG_DRIVER("failed to downclock LVDS!\n"); - -		/* ...and lock them again */ -		I915_WRITE(PP_CONTROL, I915_READ(PP_CONTROL) & 0x3);  	}  } @@ -7097,7 +7180,7 @@ static void intel_unpin_work_fn(struct work_struct *__work)  		container_of(__work, struct intel_unpin_work, work);  	mutex_lock(&work->dev->struct_mutex); -	i915_gem_object_unpin(work->old_fb_obj); +	intel_unpin_fb_obj(work->old_fb_obj);  	drm_gem_object_unreference(&work->pending_flip_obj->base);  	drm_gem_object_unreference(&work->old_fb_obj->base); @@ -7247,7 +7330,7 @@ static int intel_gen2_queue_flip(struct drm_device *dev,  		 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane));  	OUT_RING(fb->pitches[0]);  	OUT_RING(obj->gtt_offset + offset); -	OUT_RING(MI_NOOP); +	OUT_RING(0); /* aux display base address, unused */  	ADVANCE_LP_RING();  out:  	return ret; @@ -7681,10 +7764,9 @@ static void intel_setup_outputs(struct drm_device *dev)  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_encoder *encoder;  	bool dpd_is_edp = false; -	bool has_lvds = false; +	bool has_lvds; -	if (IS_MOBILE(dev) && !IS_I830(dev)) -		has_lvds = intel_lvds_init(dev); +	has_lvds = intel_lvds_init(dev);  	if (!has_lvds && !HAS_PCH_SPLIT(dev)) {  		/* disable the panel fitter on everything but LVDS */  		I915_WRITE(PFIT_CONTROL, 0); @@ -7840,7 +7922,8 @@ int intel_framebuffer_init(struct drm_device *dev,  	case DRM_FORMAT_VYUY:  		break;  	default: -		DRM_ERROR("unsupported pixel format\n"); +		DRM_DEBUG_KMS("unsupported pixel format %u\n", +				mode_cmd->pixel_format);  		return -EINVAL;  	} @@ -8162,6 +8245,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)  	u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);  	u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);  	u32 pcu_mbox, rc6_mask = 0; +	u32 gtfifodbg;  	int cur_freq, min_freq, max_freq;  	int i; @@ -8173,6 +8257,13 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)  	 */  	I915_WRITE(GEN6_RC_STATE, 0);  	mutex_lock(&dev_priv->dev->struct_mutex); + +	/* Clear the DBG now so we don't confuse earlier errors */ +	if ((gtfifodbg = I915_READ(GTFIFODBG))) { +		DRM_ERROR("GT fifo had a previous error %x\n", gtfifodbg); +		I915_WRITE(GTFIFODBG, gtfifodbg); +	} +  	gen6_gt_force_wake_get(dev_priv);  	/* disable the counters and set deterministic thresholds */ @@ -8959,8 +9050,6 @@ struct intel_quirk {  };  struct intel_quirk intel_quirks[] = { -	/* HP Compaq 2730p needs pipe A force quirk (LP: #291555) */ -	{ 0x2a42, 0x103c, 0x30eb, quirk_pipea_force },  	/* HP Mini needs pipe A force quirk (LP: #322104) */  	{ 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, @@ -9037,6 +9126,9 @@ void intel_modeset_init(struct drm_device *dev)  	dev->mode_config.min_width = 0;  	dev->mode_config.min_height = 0; +	dev->mode_config.preferred_depth = 24; +	dev->mode_config.prefer_shadow = 1; +  	dev->mode_config.funcs = (void *)&intel_mode_funcs;  	intel_init_quirks(dev);  |