diff options
| author | Grant Likely <grant.likely@secretlab.ca> | 2012-05-08 11:35:37 -0600 | 
|---|---|---|
| committer | Grant Likely <grant.likely@secretlab.ca> | 2012-05-08 11:35:37 -0600 | 
| commit | 7b96c686223a5c902d6a59c7d178f3904f0ab757 (patch) | |
| tree | fe328ed56ad3719de3cfebad72ef74e34f1ed92b /drivers/gpu/drm/i915/intel_display.c | |
| parent | f141ed65f256ec036c7fba604da6b7c448096ef9 (diff) | |
| parent | d48b97b403d23f6df0b990cee652bdf9a52337a3 (diff) | |
| download | olio-linux-3.10-7b96c686223a5c902d6a59c7d178f3904f0ab757.tar.xz olio-linux-3.10-7b96c686223a5c902d6a59c7d178f3904f0ab757.zip  | |
Merge tag 'v3.4-rc6' into gpio/next
Linux 3.4-rc6
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 130 | 
1 files changed, 95 insertions, 35 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d514719f65e..1b1cf3b3ff5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2245,6 +2245,33 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,  }  static int +intel_finish_fb(struct drm_framebuffer *old_fb) +{ +	struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj; +	struct drm_i915_private *dev_priv = obj->base.dev->dev_private; +	bool was_interruptible = dev_priv->mm.interruptible; +	int ret; + +	wait_event(dev_priv->pending_flip_queue, +		   atomic_read(&dev_priv->mm.wedged) || +		   atomic_read(&obj->pending_flip) == 0); + +	/* Big Hammer, we also need to ensure that any pending +	 * MI_WAIT_FOR_EVENT inside a user batch buffer on the +	 * current scanout is retired before unpinning the old +	 * framebuffer. +	 * +	 * This should only fail upon a hung GPU, in which case we +	 * can safely continue. +	 */ +	dev_priv->mm.interruptible = false; +	ret = i915_gem_object_finish_gpu(obj); +	dev_priv->mm.interruptible = was_interruptible; + +	return ret; +} + +static int  intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,  		    struct drm_framebuffer *old_fb)  { @@ -2282,25 +2309,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,  		return ret;  	} -	if (old_fb) { -		struct drm_i915_private *dev_priv = dev->dev_private; -		struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj; - -		wait_event(dev_priv->pending_flip_queue, -			   atomic_read(&dev_priv->mm.wedged) || -			   atomic_read(&obj->pending_flip) == 0); - -		/* Big Hammer, we also need to ensure that any pending -		 * MI_WAIT_FOR_EVENT inside a user batch buffer on the -		 * current scanout is retired before unpinning the old -		 * framebuffer. -		 * -		 * This should only fail upon a hung GPU, in which case we -		 * can safely continue. -		 */ -		ret = i915_gem_object_finish_gpu(obj); -		(void) ret; -	} +	if (old_fb) +		intel_finish_fb(old_fb);  	ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,  					 LEAVE_ATOMIC_MODE_SET); @@ -3371,6 +3381,23 @@ static void intel_crtc_disable(struct drm_crtc *crtc)  	struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;  	struct drm_device *dev = crtc->dev; +	/* Flush any pending WAITs before we disable the pipe. Note that +	 * we need to drop the struct_mutex in order to acquire it again +	 * during the lowlevel dpms routines around a couple of the +	 * operations. It does not look trivial nor desirable to move +	 * that locking higher. So instead we leave a window for the +	 * submission of further commands on the fb before we can actually +	 * disable it. This race with userspace exists anyway, and we can +	 * only rely on the pipe being disabled by userspace after it +	 * receives the hotplug notification and has flushed any pending +	 * batches. +	 */ +	if (crtc->fb) { +		mutex_lock(&dev->struct_mutex); +		intel_finish_fb(crtc->fb); +		mutex_unlock(&dev->struct_mutex); +	} +  	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); @@ -3451,8 +3478,11 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,  			return false;  	} -	/* All interlaced capable intel hw wants timings in frames. */ -	drm_mode_set_crtcinfo(adjusted_mode, 0); +	/* All interlaced capable intel hw wants timings in frames. Note though +	 * that intel_lvds_mode_fixup does some funny tricks with the crtc +	 * timings, so we need to be careful not to clobber these.*/ +	if (!(adjusted_mode->private_flags & INTEL_MODE_CRTC_TIMINGS_SET)) +		drm_mode_set_crtcinfo(adjusted_mode, 0);  	return true;  } @@ -5539,7 +5569,8 @@ void ironlake_init_pch_refclk(struct drm_device *dev)  		if (intel_panel_use_ssc(dev_priv) && can_ssc) {  			DRM_DEBUG_KMS("Using SSC on panel\n");  			temp |= DREF_SSC1_ENABLE; -		} +		} else +			temp &= ~DREF_SSC1_ENABLE;  		/* Get SSC going before enabling the outputs */  		I915_WRITE(PCH_DREF_CONTROL, temp); @@ -7041,9 +7072,6 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)  	struct drm_device *dev = crtc->dev;  	drm_i915_private_t *dev_priv = dev->dev_private;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); -	int pipe = intel_crtc->pipe; -	int dpll_reg = DPLL(pipe); -	int dpll = I915_READ(dpll_reg);  	if (HAS_PCH_SPLIT(dev))  		return; @@ -7056,10 +7084,15 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)  	 * the manual case.  	 */  	if (!HAS_PIPE_CXSR(dev) && intel_crtc->lowfreq_avail) { +		int pipe = intel_crtc->pipe; +		int dpll_reg = DPLL(pipe); +		u32 dpll; +  		DRM_DEBUG_DRIVER("downclocking LVDS\n");  		assert_panel_unlocked(dev_priv, pipe); +		dpll = I915_READ(dpll_reg);  		dpll |= DISPLAY_RATE_SELECT_FPA1;  		I915_WRITE(dpll_reg, dpll);  		intel_wait_for_vblank(dev, pipe); @@ -7067,7 +7100,6 @@ static void intel_decrease_pllclock(struct drm_crtc *crtc)  		if (!(dpll & DISPLAY_RATE_SELECT_FPA1))  			DRM_DEBUG_DRIVER("failed to downclock LVDS!\n");  	} -  }  /** @@ -7437,7 +7469,13 @@ static int intel_gen6_queue_flip(struct drm_device *dev,  	OUT_RING(fb->pitches[0] | obj->tiling_mode);  	OUT_RING(obj->gtt_offset); -	pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE; +	/* Contrary to the suggestions in the documentation, +	 * "Enable Panel Fitter" does not seem to be required when page +	 * flipping with a non-native mode, and worse causes a normal +	 * modeset to fail. +	 * pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE; +	 */ +	pf = 0;  	pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff;  	OUT_RING(pf | pipesrc);  	ADVANCE_LP_RING(); @@ -7580,6 +7618,12 @@ static void intel_sanitize_modesetting(struct drm_device *dev,  	struct drm_i915_private *dev_priv = dev->dev_private;  	u32 reg, val; +	/* Clear any frame start delays used for debugging left by the BIOS */ +	for_each_pipe(pipe) { +		reg = PIPECONF(pipe); +		I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); +	} +  	if (HAS_PCH_SPLIT(dev))  		return; @@ -8215,7 +8259,7 @@ void intel_init_emon(struct drm_device *dev)  	dev_priv->corr = (lcfuse & LCFUSE_HIV_MASK);  } -static bool intel_enable_rc6(struct drm_device *dev) +static int intel_enable_rc6(struct drm_device *dev)  {  	/*  	 * Respect the kernel parameter if it is set @@ -8233,11 +8277,11 @@ static bool intel_enable_rc6(struct drm_device *dev)  	 * Disable rc6 on Sandybridge  	 */  	if (INTEL_INFO(dev)->gen == 6) { -		DRM_DEBUG_DRIVER("Sandybridge: RC6 disabled\n"); -		return 0; +		DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); +		return INTEL_RC6_ENABLE;  	} -	DRM_DEBUG_DRIVER("RC6 enabled\n"); -	return 1; +	DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); +	return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE);  }  void gen6_enable_rps(struct drm_i915_private *dev_priv) @@ -8247,6 +8291,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)  	u32 pcu_mbox, rc6_mask = 0;  	u32 gtfifodbg;  	int cur_freq, min_freq, max_freq; +	int rc6_mode;  	int i;  	/* Here begins a magic sequence of register writes to enable @@ -8284,9 +8329,20 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv)  	I915_WRITE(GEN6_RC6p_THRESHOLD, 100000);  	I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ -	if (intel_enable_rc6(dev_priv->dev)) -		rc6_mask = GEN6_RC_CTL_RC6_ENABLE | -			((IS_GEN7(dev_priv->dev)) ? GEN6_RC_CTL_RC6p_ENABLE : 0); +	rc6_mode = intel_enable_rc6(dev_priv->dev); +	if (rc6_mode & INTEL_RC6_ENABLE) +		rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; + +	if (rc6_mode & INTEL_RC6p_ENABLE) +		rc6_mask |= GEN6_RC_CTL_RC6p_ENABLE; + +	if (rc6_mode & INTEL_RC6pp_ENABLE) +		rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; + +	DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", +			(rc6_mode & INTEL_RC6_ENABLE) ? "on" : "off", +			(rc6_mode & INTEL_RC6p_ENABLE) ? "on" : "off", +			(rc6_mode & INTEL_RC6pp_ENABLE) ? "on" : "off");  	I915_WRITE(GEN6_RC_CONTROL,  		   rc6_mask | @@ -8510,6 +8566,10 @@ static void gen6_init_clock_gating(struct drm_device *dev)  	I915_WRITE(WM2_LP_ILK, 0);  	I915_WRITE(WM1_LP_ILK, 0); +	I915_WRITE(GEN6_UCGCTL1, +		   I915_READ(GEN6_UCGCTL1) | +		   GEN6_BLBUNIT_CLOCK_GATE_DISABLE); +  	/* According to the BSpec vol1g, bit 12 (RCPBUNIT) clock  	 * gating disable must be set.  Failure to set it results in  	 * flickering pixels due to Z write ordering failures after  |