diff options
Diffstat (limited to 'drivers/gpu/drm/i915/i915_drv.c')
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 206 | 
1 files changed, 137 insertions, 69 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index e9b57893db2..9ebe895c17d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -121,9 +121,7 @@ MODULE_PARM_DESC(i915_enable_ppgtt,  unsigned int i915_preliminary_hw_support __read_mostly = 0;  module_param_named(preliminary_hw_support, i915_preliminary_hw_support, int, 0600);  MODULE_PARM_DESC(preliminary_hw_support, -		"Enable preliminary hardware support. " -		"Enable Haswell and ValleyView Support. " -		"(default: false)"); +		"Enable preliminary hardware support. (default: false)");  int i915_disable_power_well __read_mostly = 0;  module_param_named(disable_power_well, i915_disable_power_well, int, 0600); @@ -142,75 +140,85 @@ extern int intel_agp_enabled;  	.subdevice = PCI_ANY_ID,		\  	.driver_data = (unsigned long) info } +#define INTEL_QUANTA_VGA_DEVICE(info) {		\ +	.class = PCI_BASE_CLASS_DISPLAY << 16,	\ +	.class_mask = 0xff0000,			\ +	.vendor = 0x8086,			\ +	.device = 0x16a,			\ +	.subvendor = 0x152d,			\ +	.subdevice = 0x8990,			\ +	.driver_data = (unsigned long) info } + +  static const struct intel_device_info intel_i830_info = { -	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, +	.gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2,  	.has_overlay = 1, .overlay_needs_physical = 1,  };  static const struct intel_device_info intel_845g_info = { -	.gen = 2, +	.gen = 2, .num_pipes = 1,  	.has_overlay = 1, .overlay_needs_physical = 1,  };  static const struct intel_device_info intel_i85x_info = { -	.gen = 2, .is_i85x = 1, .is_mobile = 1, +	.gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2,  	.cursor_needs_physical = 1,  	.has_overlay = 1, .overlay_needs_physical = 1,  };  static const struct intel_device_info intel_i865g_info = { -	.gen = 2, +	.gen = 2, .num_pipes = 1,  	.has_overlay = 1, .overlay_needs_physical = 1,  };  static const struct intel_device_info intel_i915g_info = { -	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, +	.gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2,  	.has_overlay = 1, .overlay_needs_physical = 1,  };  static const struct intel_device_info intel_i915gm_info = { -	.gen = 3, .is_mobile = 1, +	.gen = 3, .is_mobile = 1, .num_pipes = 2,  	.cursor_needs_physical = 1,  	.has_overlay = 1, .overlay_needs_physical = 1,  	.supports_tv = 1,  };  static const struct intel_device_info intel_i945g_info = { -	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, +	.gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2,  	.has_overlay = 1, .overlay_needs_physical = 1,  };  static const struct intel_device_info intel_i945gm_info = { -	.gen = 3, .is_i945gm = 1, .is_mobile = 1, +	.gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2,  	.has_hotplug = 1, .cursor_needs_physical = 1,  	.has_overlay = 1, .overlay_needs_physical = 1,  	.supports_tv = 1,  };  static const struct intel_device_info intel_i965g_info = { -	.gen = 4, .is_broadwater = 1, +	.gen = 4, .is_broadwater = 1, .num_pipes = 2,  	.has_hotplug = 1,  	.has_overlay = 1,  };  static const struct intel_device_info intel_i965gm_info = { -	.gen = 4, .is_crestline = 1, +	.gen = 4, .is_crestline = 1, .num_pipes = 2,  	.is_mobile = 1, .has_fbc = 1, .has_hotplug = 1,  	.has_overlay = 1,  	.supports_tv = 1,  };  static const struct intel_device_info intel_g33_info = { -	.gen = 3, .is_g33 = 1, +	.gen = 3, .is_g33 = 1, .num_pipes = 2,  	.need_gfx_hws = 1, .has_hotplug = 1,  	.has_overlay = 1,  };  static const struct intel_device_info intel_g45_info = { -	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, +	.gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2,  	.has_pipe_cxsr = 1, .has_hotplug = 1,  	.has_bsd_ring = 1,  };  static const struct intel_device_info intel_gm45_info = { -	.gen = 4, .is_g4x = 1, +	.gen = 4, .is_g4x = 1, .num_pipes = 2,  	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1,  	.has_pipe_cxsr = 1, .has_hotplug = 1,  	.supports_tv = 1, @@ -218,26 +226,26 @@ static const struct intel_device_info intel_gm45_info = {  };  static const struct intel_device_info intel_pineview_info = { -	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, +	.gen = 3, .is_g33 = 1, .is_pineview = 1, .is_mobile = 1, .num_pipes = 2,  	.need_gfx_hws = 1, .has_hotplug = 1,  	.has_overlay = 1,  };  static const struct intel_device_info intel_ironlake_d_info = { -	.gen = 5, +	.gen = 5, .num_pipes = 2,  	.need_gfx_hws = 1, .has_hotplug = 1,  	.has_bsd_ring = 1,  };  static const struct intel_device_info intel_ironlake_m_info = { -	.gen = 5, .is_mobile = 1, +	.gen = 5, .is_mobile = 1, .num_pipes = 2,  	.need_gfx_hws = 1, .has_hotplug = 1,  	.has_fbc = 1,  	.has_bsd_ring = 1,  };  static const struct intel_device_info intel_sandybridge_d_info = { -	.gen = 6, +	.gen = 6, .num_pipes = 2,  	.need_gfx_hws = 1, .has_hotplug = 1,  	.has_bsd_ring = 1,  	.has_blt_ring = 1, @@ -246,7 +254,7 @@ static const struct intel_device_info intel_sandybridge_d_info = {  };  static const struct intel_device_info intel_sandybridge_m_info = { -	.gen = 6, .is_mobile = 1, +	.gen = 6, .is_mobile = 1, .num_pipes = 2,  	.need_gfx_hws = 1, .has_hotplug = 1,  	.has_fbc = 1,  	.has_bsd_ring = 1, @@ -255,61 +263,57 @@ static const struct intel_device_info intel_sandybridge_m_info = {  	.has_force_wake = 1,  }; +#define GEN7_FEATURES  \ +	.gen = 7, .num_pipes = 3, \ +	.need_gfx_hws = 1, .has_hotplug = 1, \ +	.has_bsd_ring = 1, \ +	.has_blt_ring = 1, \ +	.has_llc = 1, \ +	.has_force_wake = 1 +  static const struct intel_device_info intel_ivybridge_d_info = { -	.is_ivybridge = 1, .gen = 7, -	.need_gfx_hws = 1, .has_hotplug = 1, -	.has_bsd_ring = 1, -	.has_blt_ring = 1, -	.has_llc = 1, -	.has_force_wake = 1, +	GEN7_FEATURES, +	.is_ivybridge = 1,  };  static const struct intel_device_info intel_ivybridge_m_info = { -	.is_ivybridge = 1, .gen = 7, .is_mobile = 1, -	.need_gfx_hws = 1, .has_hotplug = 1, -	.has_fbc = 0,	/* FBC is not enabled on Ivybridge mobile yet */ -	.has_bsd_ring = 1, -	.has_blt_ring = 1, -	.has_llc = 1, -	.has_force_wake = 1, +	GEN7_FEATURES, +	.is_ivybridge = 1, +	.is_mobile = 1, +}; + +static const struct intel_device_info intel_ivybridge_q_info = { +	GEN7_FEATURES, +	.is_ivybridge = 1, +	.num_pipes = 0, /* legal, last one wins */  };  static const struct intel_device_info intel_valleyview_m_info = { -	.gen = 7, .is_mobile = 1, -	.need_gfx_hws = 1, .has_hotplug = 1, -	.has_fbc = 0, -	.has_bsd_ring = 1, -	.has_blt_ring = 1, +	GEN7_FEATURES, +	.is_mobile = 1, +	.num_pipes = 2,  	.is_valleyview = 1,  	.display_mmio_offset = VLV_DISPLAY_BASE, +	.has_llc = 0, /* legal, last one wins */  };  static const struct intel_device_info intel_valleyview_d_info = { -	.gen = 7, -	.need_gfx_hws = 1, .has_hotplug = 1, -	.has_fbc = 0, -	.has_bsd_ring = 1, -	.has_blt_ring = 1, +	GEN7_FEATURES, +	.num_pipes = 2,  	.is_valleyview = 1,  	.display_mmio_offset = VLV_DISPLAY_BASE, +	.has_llc = 0, /* legal, last one wins */  };  static const struct intel_device_info intel_haswell_d_info = { -	.is_haswell = 1, .gen = 7, -	.need_gfx_hws = 1, .has_hotplug = 1, -	.has_bsd_ring = 1, -	.has_blt_ring = 1, -	.has_llc = 1, -	.has_force_wake = 1, +	GEN7_FEATURES, +	.is_haswell = 1,  };  static const struct intel_device_info intel_haswell_m_info = { -	.is_haswell = 1, .gen = 7, .is_mobile = 1, -	.need_gfx_hws = 1, .has_hotplug = 1, -	.has_bsd_ring = 1, -	.has_blt_ring = 1, -	.has_llc = 1, -	.has_force_wake = 1, +	GEN7_FEATURES, +	.is_haswell = 1, +	.is_mobile = 1,  };  static const struct pci_device_id pciidlist[] = {		/* aka */ @@ -356,6 +360,7 @@ static const struct pci_device_id pciidlist[] = {		/* aka */  	INTEL_VGA_DEVICE(0x0152, &intel_ivybridge_d_info), /* GT1 desktop */  	INTEL_VGA_DEVICE(0x0162, &intel_ivybridge_d_info), /* GT2 desktop */  	INTEL_VGA_DEVICE(0x015a, &intel_ivybridge_d_info), /* GT1 server */ +	INTEL_QUANTA_VGA_DEVICE(&intel_ivybridge_q_info), /* Quanta transcode */  	INTEL_VGA_DEVICE(0x016a, &intel_ivybridge_d_info), /* GT2 server */  	INTEL_VGA_DEVICE(0x0402, &intel_haswell_d_info), /* GT1 desktop */  	INTEL_VGA_DEVICE(0x0412, &intel_haswell_d_info), /* GT2 desktop */ @@ -394,6 +399,9 @@ static const struct pci_device_id pciidlist[] = {		/* aka */  	INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */  	INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */  	INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), +	INTEL_VGA_DEVICE(0x0f31, &intel_valleyview_m_info), +	INTEL_VGA_DEVICE(0x0f32, &intel_valleyview_m_info), +	INTEL_VGA_DEVICE(0x0f33, &intel_valleyview_m_info),  	INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info),  	INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info),  	{0, 0, 0} @@ -408,6 +416,15 @@ void intel_detect_pch(struct drm_device *dev)  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct pci_dev *pch; +	/* In all current cases, num_pipes is equivalent to the PCH_NOP setting +	 * (which really amounts to a PCH but no South Display). +	 */ +	if (INTEL_INFO(dev)->num_pipes == 0) { +		dev_priv->pch_type = PCH_NOP; +		dev_priv->num_pch_pll = 0; +		return; +	} +  	/*  	 * The reason to probe ISA bridge instead of Dev31:Fun0 is to  	 * make graphics device passthrough work easy for VMM, that only @@ -442,11 +459,13 @@ void intel_detect_pch(struct drm_device *dev)  				dev_priv->num_pch_pll = 0;  				DRM_DEBUG_KMS("Found LynxPoint PCH\n");  				WARN_ON(!IS_HASWELL(dev)); +				WARN_ON(IS_ULT(dev));  			} else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) {  				dev_priv->pch_type = PCH_LPT;  				dev_priv->num_pch_pll = 0;  				DRM_DEBUG_KMS("Found LynxPoint LP PCH\n");  				WARN_ON(!IS_HASWELL(dev)); +				WARN_ON(!IS_ULT(dev));  			}  			BUG_ON(dev_priv->num_pch_pll > I915_NUM_PLLS);  		} @@ -474,6 +493,7 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)  static int i915_drm_freeze(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; +	struct drm_crtc *crtc;  	/* ignore lid events during suspend */  	mutex_lock(&dev_priv->modeset_restore_lock); @@ -497,10 +517,14 @@ static int i915_drm_freeze(struct drm_device *dev)  		cancel_delayed_work_sync(&dev_priv->rps.delayed_resume_work); -		intel_modeset_disable(dev); -  		drm_irq_uninstall(dev);  		dev_priv->enable_hotplug_processing = false; +		/* +		 * Disable CRTCs directly since we want to preserve sw state +		 * for _thaw. +		 */ +		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) +			dev_priv->display.crtc_disable(crtc);  	}  	i915_save_state(dev); @@ -556,6 +580,24 @@ void intel_console_resume(struct work_struct *work)  	console_unlock();  } +static void intel_resume_hotplug(struct drm_device *dev) +{ +	struct drm_mode_config *mode_config = &dev->mode_config; +	struct intel_encoder *encoder; + +	mutex_lock(&mode_config->mutex); +	DRM_DEBUG_KMS("running encoder hotplug functions\n"); + +	list_for_each_entry(encoder, &mode_config->encoder_list, base.head) +		if (encoder->hot_plug) +			encoder->hot_plug(encoder); + +	mutex_unlock(&mode_config->mutex); + +	/* Just fire off a uevent and let userspace tell us what to do */ +	drm_helper_hpd_irq_event(dev); +} +  static int __i915_drm_thaw(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -578,7 +620,10 @@ static int __i915_drm_thaw(struct drm_device *dev)  		drm_irq_install(dev);  		intel_modeset_init_hw(dev); -		intel_modeset_setup_hw_state(dev, false); + +		drm_modeset_lock_all(dev); +		intel_modeset_setup_hw_state(dev, true); +		drm_modeset_unlock_all(dev);  		/*  		 * ... but also need to make sure that hotplug processing @@ -588,6 +633,8 @@ static int __i915_drm_thaw(struct drm_device *dev)  		 * */  		intel_hpd_init(dev);  		dev_priv->enable_hotplug_processing = true; +		/* Config may have changed between suspend and resume */ +		intel_resume_hotplug(dev);  	}  	intel_opregion_init(dev); @@ -732,6 +779,7 @@ static int ironlake_do_reset(struct drm_device *dev)  	int ret;  	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR); +	gdrst &= ~GRDOM_MASK;  	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,  		   gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);  	ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500); @@ -740,6 +788,7 @@ static int ironlake_do_reset(struct drm_device *dev)  	/* We can't reset render&media without also resetting display ... */  	gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR); +	gdrst &= ~GRDOM_MASK;  	I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,  		   gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);  	return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500); @@ -803,7 +852,7 @@ int intel_gpu_reset(struct drm_device *dev)  	/* Also reset the gpu hangman. */  	if (dev_priv->gpu_error.stop_rings) { -		DRM_DEBUG("Simulated gpu hang, resetting stop_rings\n"); +		DRM_INFO("Simulated gpu hang, resetting stop_rings\n");  		dev_priv->gpu_error.stop_rings = 0;  		if (ret == -ENODEV) {  			DRM_ERROR("Reset not implemented, but ignoring " @@ -882,7 +931,11 @@ int i915_reset(struct drm_device *dev)  			ring->init(ring);  		i915_gem_context_init(dev); -		i915_gem_init_ppgtt(dev); +		if (dev_priv->mm.aliasing_ppgtt) { +			ret = dev_priv->mm.aliasing_ppgtt->enable(dev); +			if (ret) +				i915_gem_cleanup_aliasing_ppgtt(dev); +		}  		/*  		 * It would make sense to re-init all the other hw state, at @@ -1147,6 +1200,27 @@ ilk_dummy_write(struct drm_i915_private *dev_priv)  	I915_WRITE_NOTRACE(MI_MODE, 0);  } +static void +hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg) +{ +	if (IS_HASWELL(dev_priv->dev) && +	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) { +		DRM_ERROR("Unknown unclaimed register before writing to %x\n", +			  reg); +		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM); +	} +} + +static void +hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg) +{ +	if (IS_HASWELL(dev_priv->dev) && +	    (I915_READ_NOTRACE(FPGA_DBG) & FPGA_DBG_RM_NOCLAIM)) { +		DRM_ERROR("Unclaimed write to %x\n", reg); +		I915_WRITE_NOTRACE(FPGA_DBG, FPGA_DBG_RM_NOCLAIM); +	} +} +  #define __i915_read(x, y) \  u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \  	u##x val = 0; \ @@ -1183,18 +1257,12 @@ void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \  	} \  	if (IS_GEN5(dev_priv->dev)) \  		ilk_dummy_write(dev_priv); \ -	if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \ -		DRM_ERROR("Unknown unclaimed register before writing to %x\n", reg); \ -		I915_WRITE_NOTRACE(GEN7_ERR_INT, ERR_INT_MMIO_UNCLAIMED); \ -	} \ +	hsw_unclaimed_reg_clear(dev_priv, reg); \  	write##y(val, dev_priv->regs + reg); \  	if (unlikely(__fifo_ret)) { \  		gen6_gt_check_fifodbg(dev_priv); \  	} \ -	if (IS_HASWELL(dev_priv->dev) && (I915_READ_NOTRACE(GEN7_ERR_INT) & ERR_INT_MMIO_UNCLAIMED)) { \ -		DRM_ERROR("Unclaimed write to %x\n", reg); \ -		writel(ERR_INT_MMIO_UNCLAIMED, dev_priv->regs + GEN7_ERR_INT);	\ -	} \ +	hsw_unclaimed_reg_check(dev_priv, reg); \  }  __i915_write(8, b)  __i915_write(16, w)  |