diff options
33 files changed, 2584 insertions, 1134 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index c1601e5a8b7..41e398c5688 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -982,6 +982,20 @@ bytes respectively. Such letter suffixes can also be entirely omitted.  	i8k.restricted	[HW] Allow controlling fans only if SYS_ADMIN  			capability is set. +	i915.invert_brightness= +			[DRM] Invert the sense of the variable that is used to +			set the brightness of the panel backlight. Normally a +			brightness value of 0 indicates backlight switched off, +			and the maximum of the brightness value sets the backlight +			to maximum brightness. If this parameter is set to 0 +			(default) and the machine requires it, or this parameter +			is set to 1, a brightness value of 0 sets the backlight +			to maximum brightness, and the maximum of the brightness +			value switches the backlight off. +			-1 -- never invert brightness +			 0 -- machine default +			 1 -- force brightness inversion +  	icn=		[HW,ISDN]  			Format: <io>[,<membase>[,<icn_id>[,<icn_id2>]]] diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 962e75dc478..74c2d9274c5 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -907,6 +907,7 @@ static struct pci_device_id agp_intel_pci_table[] = {  	ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB),  	ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB),  	ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB), +	ID(PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB),  	{ }  }; diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 7ea18a5fe71..c0091753a0d 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -96,6 +96,7 @@  #define G4x_GMCH_SIZE_VT_2M	(G4x_GMCH_SIZE_2M | G4x_GMCH_SIZE_VT_EN)  #define GFX_FLSH_CNTL		0x2170 /* 915+ */ +#define GFX_FLSH_CNTL_VLV	0x101008  #define I810_DRAM_CTL		0x3000  #define I810_DRAM_ROW_0		0x00000001 @@ -235,6 +236,19 @@  #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB		0x0158  /* Server */  #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG		0x015A  #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG		0x016A +#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB		0x0F00 /* VLV1 */ +#define PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG		0x0F30 +#define PCI_DEVICE_ID_INTEL_HASWELL_HB				0x0400 /* Desktop */ +#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG		0x0402 +#define PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG		0x0412 +#define PCI_DEVICE_ID_INTEL_HASWELL_M_HB			0x0404 /* Mobile */ +#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG		0x0406 +#define PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG		0x0416 +#define PCI_DEVICE_ID_INTEL_HASWELL_S_HB			0x0408 /* Server */ +#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG		0x040a +#define PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG		0x041a +#define PCI_DEVICE_ID_INTEL_HASWELL_SDV		0x0c16 /* SDV */ +#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB			0x0c04  int intel_gmch_probe(struct pci_dev *pdev,  			       struct agp_bridge_data *bridge); diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 7f025fb620d..1237e7575c3 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -1179,6 +1179,20 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry,  	writel(addr | pte_flags, intel_private.gtt + entry);  } +static void valleyview_write_entry(dma_addr_t addr, unsigned int entry, +				   unsigned int flags) +{ +	u32 pte_flags; + +	pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; + +	/* gen6 has bit11-4 for physical addr bit39-32 */ +	addr |= (addr >> 28) & 0xff0; +	writel(addr | pte_flags, intel_private.gtt + entry); + +	writel(1, intel_private.registers + GFX_FLSH_CNTL_VLV); +} +  static void gen6_cleanup(void)  {  } @@ -1205,12 +1219,16 @@ static inline int needs_idle_maps(void)  static int i9xx_setup(void)  {  	u32 reg_addr; +	int size = KB(512);  	pci_read_config_dword(intel_private.pcidev, I915_MMADDR, ®_addr);  	reg_addr &= 0xfff80000; -	intel_private.registers = ioremap(reg_addr, 128 * 4096); +	if (INTEL_GTT_GEN >= 7) +		size = MB(2); + +	intel_private.registers = ioremap(reg_addr, size);  	if (!intel_private.registers)  		return -ENOMEM; @@ -1354,6 +1372,15 @@ static const struct intel_gtt_driver sandybridge_gtt_driver = {  	.check_flags = gen6_check_flags,  	.chipset_flush = i9xx_chipset_flush,  }; +static const struct intel_gtt_driver valleyview_gtt_driver = { +	.gen = 7, +	.setup = i9xx_setup, +	.cleanup = gen6_cleanup, +	.write_entry = valleyview_write_entry, +	.dma_mask_size = 40, +	.check_flags = gen6_check_flags, +	.chipset_flush = i9xx_chipset_flush, +};  /* Table to describe Intel GMCH and AGP/PCIE GART drivers.  At least one of   * driver and gmch_driver must be non-null, and find_gmch will determine @@ -1460,6 +1487,22 @@ static const struct intel_gtt_driver_description {  	    "Ivybridge", &sandybridge_gtt_driver },  	{ PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT2_IG,  	    "Ivybridge", &sandybridge_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_VALLEYVIEW_IG, +	    "ValleyView", &valleyview_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT1_IG, +	    "Haswell", &sandybridge_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_D_GT2_IG, +	    "Haswell", &sandybridge_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT1_IG, +	    "Haswell", &sandybridge_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_M_GT2_IG, +	    "Haswell", &sandybridge_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT1_IG, +	    "Haswell", &sandybridge_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_S_GT2_IG, +	    "Haswell", &sandybridge_gtt_driver }, +	{ PCI_DEVICE_ID_INTEL_HASWELL_SDV, +	    "Haswell", &sandybridge_gtt_driver },  	{ 0, NULL, NULL }  }; diff --git a/drivers/gpu/drm/drm_cache.c b/drivers/gpu/drm/drm_cache.c index 4b8653b932f..08758e06147 100644 --- a/drivers/gpu/drm/drm_cache.c +++ b/drivers/gpu/drm/drm_cache.c @@ -98,3 +98,26 @@ drm_clflush_pages(struct page *pages[], unsigned long num_pages)  #endif  }  EXPORT_SYMBOL(drm_clflush_pages); + +void +drm_clflush_virt_range(char *addr, unsigned long length) +{ +#if defined(CONFIG_X86) +	if (cpu_has_clflush) { +		char *end = addr + length; +		mb(); +		for (; addr < end; addr += boot_cpu_data.x86_clflush_size) +			clflush(addr); +		clflush(end - 1); +		mb(); +		return; +	} + +	if (on_each_cpu(drm_clflush_ipi_handler, NULL, 1) != 0) +		printk(KERN_ERR "Timed out waiting for cache flush.\n"); +#else +	printk(KERN_ERR "Architecture has no drm_cache.c support\n"); +	WARN_ON_ONCE(1); +#endif +} +EXPORT_SYMBOL(drm_clflush_virt_range); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index b505b70dba0..967fb928c57 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -468,7 +468,45 @@ static int i915_interrupt_info(struct seq_file *m, void *data)  	if (ret)  		return ret; -	if (!HAS_PCH_SPLIT(dev)) { +	if (IS_VALLEYVIEW(dev)) { +		seq_printf(m, "Display IER:\t%08x\n", +			   I915_READ(VLV_IER)); +		seq_printf(m, "Display IIR:\t%08x\n", +			   I915_READ(VLV_IIR)); +		seq_printf(m, "Display IIR_RW:\t%08x\n", +			   I915_READ(VLV_IIR_RW)); +		seq_printf(m, "Display IMR:\t%08x\n", +			   I915_READ(VLV_IMR)); +		for_each_pipe(pipe) +			seq_printf(m, "Pipe %c stat:\t%08x\n", +				   pipe_name(pipe), +				   I915_READ(PIPESTAT(pipe))); + +		seq_printf(m, "Master IER:\t%08x\n", +			   I915_READ(VLV_MASTER_IER)); + +		seq_printf(m, "Render IER:\t%08x\n", +			   I915_READ(GTIER)); +		seq_printf(m, "Render IIR:\t%08x\n", +			   I915_READ(GTIIR)); +		seq_printf(m, "Render IMR:\t%08x\n", +			   I915_READ(GTIMR)); + +		seq_printf(m, "PM IER:\t\t%08x\n", +			   I915_READ(GEN6_PMIER)); +		seq_printf(m, "PM IIR:\t\t%08x\n", +			   I915_READ(GEN6_PMIIR)); +		seq_printf(m, "PM IMR:\t\t%08x\n", +			   I915_READ(GEN6_PMIMR)); + +		seq_printf(m, "Port hotplug:\t%08x\n", +			   I915_READ(PORT_HOTPLUG_EN)); +		seq_printf(m, "DPFLIPSTAT:\t%08x\n", +			   I915_READ(VLV_DPFLIPSTAT)); +		seq_printf(m, "DPINVGTT:\t%08x\n", +			   I915_READ(DPINVGTT)); + +	} else if (!HAS_PCH_SPLIT(dev)) {  		seq_printf(m, "Interrupt enable:    %08x\n",  			   I915_READ(IER));  		seq_printf(m, "Interrupt identity:  %08x\n", @@ -704,6 +742,7 @@ static void i915_ring_error_state(struct seq_file *m,  				  struct drm_i915_error_state *error,  				  unsigned ring)  { +	BUG_ON(ring >= I915_NUM_RINGS); /* shut up confused gcc */  	seq_printf(m, "%s command stream:\n", ring_str(ring));  	seq_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);  	seq_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]); @@ -718,8 +757,8 @@ static void i915_ring_error_state(struct seq_file *m,  	if (INTEL_INFO(dev)->gen >= 4)  		seq_printf(m, "  INSTPS: 0x%08x\n", error->instps[ring]);  	seq_printf(m, "  INSTPM: 0x%08x\n", error->instpm[ring]); +	seq_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);  	if (INTEL_INFO(dev)->gen >= 6) { -		seq_printf(m, "  FADDR: 0x%08x\n", error->faddr[ring]);  		seq_printf(m, "  FAULT_REG: 0x%08x\n", error->fault_reg[ring]);  		seq_printf(m, "  SYNC_0: 0x%08x\n",  			   error->semaphore_mboxes[ring][0]); @@ -1502,6 +1541,53 @@ static int i915_ppgtt_info(struct seq_file *m, void *data)  	return 0;  } +static int i915_dpio_info(struct seq_file *m, void *data) +{ +	struct drm_info_node *node = (struct drm_info_node *) m->private; +	struct drm_device *dev = node->minor->dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	int ret; + + +	if (!IS_VALLEYVIEW(dev)) { +		seq_printf(m, "unsupported\n"); +		return 0; +	} + +	ret = mutex_lock_interruptible(&dev->mode_config.mutex); +	if (ret) +		return ret; + +	seq_printf(m, "DPIO_CTL: 0x%08x\n", I915_READ(DPIO_CTL)); + +	seq_printf(m, "DPIO_DIV_A: 0x%08x\n", +		   intel_dpio_read(dev_priv, _DPIO_DIV_A)); +	seq_printf(m, "DPIO_DIV_B: 0x%08x\n", +		   intel_dpio_read(dev_priv, _DPIO_DIV_B)); + +	seq_printf(m, "DPIO_REFSFR_A: 0x%08x\n", +		   intel_dpio_read(dev_priv, _DPIO_REFSFR_A)); +	seq_printf(m, "DPIO_REFSFR_B: 0x%08x\n", +		   intel_dpio_read(dev_priv, _DPIO_REFSFR_B)); + +	seq_printf(m, "DPIO_CORE_CLK_A: 0x%08x\n", +		   intel_dpio_read(dev_priv, _DPIO_CORE_CLK_A)); +	seq_printf(m, "DPIO_CORE_CLK_B: 0x%08x\n", +		   intel_dpio_read(dev_priv, _DPIO_CORE_CLK_B)); + +	seq_printf(m, "DPIO_LFP_COEFF_A: 0x%08x\n", +		   intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_A)); +	seq_printf(m, "DPIO_LFP_COEFF_B: 0x%08x\n", +		   intel_dpio_read(dev_priv, _DPIO_LFP_COEFF_B)); + +	seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n", +		   intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE)); + +	mutex_unlock(&dev->mode_config.mutex); + +	return 0; +} +  static ssize_t  i915_wedged_read(struct file *filp,  		 char __user *ubuf, @@ -1836,6 +1922,7 @@ static struct drm_info_list i915_debugfs_list[] = {  	{"i915_gen6_forcewake_count", i915_gen6_forcewake_count_info, 0},  	{"i915_swizzle_info", i915_swizzle_info, 0},  	{"i915_ppgtt_info", i915_ppgtt_info, 0}, +	{"i915_dpio", i915_dpio_info, 0},  };  #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 785f67f963e..652f43f00ef 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -26,6 +26,8 @@   *   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include "drmP.h"  #include "drm.h"  #include "drm_crtc_helper.h" @@ -43,6 +45,7 @@  #include <linux/slab.h>  #include <linux/module.h>  #include <acpi/video.h> +#include <asm/pat.h>  static void i915_write_hws_pga(struct drm_device *dev)  { @@ -787,6 +790,9 @@ static int i915_getparam(struct drm_device *dev, void *data,  	case I915_PARAM_HAS_LLC:  		value = HAS_LLC(dev);  		break; +	case I915_PARAM_HAS_ALIASING_PPGTT: +		value = dev_priv->mm.aliasing_ppgtt ? 1 : 0; +		break;  	default:  		DRM_DEBUG_DRIVER("Unknown parameter %d\n",  				 param->param); @@ -1158,14 +1164,14 @@ static void i915_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_  	struct drm_device *dev = pci_get_drvdata(pdev);  	pm_message_t pmm = { .event = PM_EVENT_SUSPEND };  	if (state == VGA_SWITCHEROO_ON) { -		printk(KERN_INFO "i915: switched on\n"); +		pr_info("switched on\n");  		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;  		/* i915 resume handler doesn't set to D0 */  		pci_set_power_state(dev->pdev, PCI_D0);  		i915_resume(dev);  		dev->switch_power_state = DRM_SWITCH_POWER_ON;  	} else { -		printk(KERN_ERR "i915: switched off\n"); +		pr_err("switched off\n");  		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING;  		i915_suspend(dev, pmm);  		dev->switch_power_state = DRM_SWITCH_POWER_OFF; @@ -1216,10 +1222,8 @@ static int i915_load_gem_init(struct drm_device *dev)  		/* PPGTT pdes are stolen from global gtt ptes, so shrink the  		 * aperture accordingly when using aliasing ppgtt. */  		gtt_size -= I915_PPGTT_PD_ENTRIES*PAGE_SIZE; -		/* For paranoia keep the guard page in between. */ -		gtt_size -= PAGE_SIZE; -		i915_gem_do_init(dev, 0, mappable_size, gtt_size); +		i915_gem_init_global_gtt(dev, 0, mappable_size, gtt_size);  		ret = i915_gem_init_aliasing_ppgtt(dev);  		if (ret) { @@ -1237,7 +1241,8 @@ static int i915_load_gem_init(struct drm_device *dev)  		 * should be enough to keep any prefetching inside of the  		 * aperture.  		 */ -		i915_gem_do_init(dev, 0, mappable_size, gtt_size - PAGE_SIZE); +		i915_gem_init_global_gtt(dev, 0, mappable_size, +					 gtt_size);  	}  	ret = i915_gem_init_hw(dev); @@ -1931,6 +1936,29 @@ ips_ping_for_i915_load(void)  	}  } +static void +i915_mtrr_setup(struct drm_i915_private *dev_priv, unsigned long base, +		unsigned long size) +{ +	dev_priv->mm.gtt_mtrr = -1; + +#if defined(CONFIG_X86_PAT) +	if (cpu_has_pat) +		return; +#endif + +	/* Set up a WC MTRR for non-PAT systems.  This is more common than +	 * one would think, because the kernel disables PAT on first +	 * generation Core chips because WC PAT gets overridden by a UC +	 * MTRR if present.  Even if a UC MTRR isn't present. +	 */ +	dev_priv->mm.gtt_mtrr = mtrr_add(base, size, MTRR_TYPE_WRCOMB, 1); +	if (dev_priv->mm.gtt_mtrr < 0) { +		DRM_INFO("MTRR allocation failed.  Graphics " +			 "performance may suffer.\n"); +	} +} +  /**   * i915_driver_load - setup chip and create an initial config   * @dev: DRM device @@ -1945,8 +1973,16 @@ ips_ping_for_i915_load(void)  int i915_driver_load(struct drm_device *dev, unsigned long flags)  {  	struct drm_i915_private *dev_priv; +	struct intel_device_info *info;  	int ret = 0, mmio_bar; -	uint32_t agp_size; +	uint32_t aperture_size; + +	info = (struct intel_device_info *) flags; + +	/* Refuse to load on gen6+ without kms enabled. */ +	if (info->gen >= 6 && !drm_core_check_feature(dev, DRIVER_MODESET)) +		return -ENODEV; +  	/* i915 has 4 more counters */  	dev->counters += 4; @@ -1961,7 +1997,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	dev->dev_private = (void *)dev_priv;  	dev_priv->dev = dev; -	dev_priv->info = (struct intel_device_info *) flags; +	dev_priv->info = info;  	if (i915_get_bridge_dev(dev)) {  		ret = -EIO; @@ -2000,27 +2036,16 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  		goto out_rmmap;  	} -	agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; +	aperture_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT;  	dev_priv->mm.gtt_mapping = -		io_mapping_create_wc(dev->agp->base, agp_size); +		io_mapping_create_wc(dev->agp->base, aperture_size);  	if (dev_priv->mm.gtt_mapping == NULL) {  		ret = -EIO;  		goto out_rmmap;  	} -	/* Set up a WC MTRR for non-PAT systems.  This is more common than -	 * one would think, because the kernel disables PAT on first -	 * generation Core chips because WC PAT gets overridden by a UC -	 * MTRR if present.  Even if a UC MTRR isn't present. -	 */ -	dev_priv->mm.gtt_mtrr = mtrr_add(dev->agp->base, -					 agp_size, -					 MTRR_TYPE_WRCOMB, 1); -	if (dev_priv->mm.gtt_mtrr < 0) { -		DRM_INFO("MTRR allocation failed.  Graphics " -			 "performance may suffer.\n"); -	} +	i915_mtrr_setup(dev_priv, dev->agp->base, aperture_size);  	/* The i915 workqueue is primarily used for batched retirement of  	 * requests (and thus managing bo) once the task has been completed @@ -2272,7 +2297,7 @@ int i915_driver_open(struct drm_device *dev, struct drm_file *file)   * mode setting case, we want to restore the kernel's initial mode (just   * in case the last client left us in a bad state).   * - * Additionally, in the non-mode setting case, we'll tear down the AGP + * Additionally, in the non-mode setting case, we'll tear down the GTT   * and DMA structures, since the kernel won't be using them, and clea   * up any GEM state.   */ @@ -2350,16 +2375,10 @@ struct drm_ioctl_desc i915_ioctls[] = {  int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); -/** - * Determine if the device really is AGP or not. - * - * All Intel graphics chipsets are treated as AGP, even if they are really - * PCI-e. - * - * \param dev   The device to be tested. - * - * \returns - * A value of 1 is always retured to indictate every i9x5 is AGP. +/* + * This is really ugly: Because old userspace abused the linux agp interface to + * manage the gtt, we need to claim that all intel devices are agp.  For + * otherwise the drm core refuses to initialize the agp support code.   */  int i915_driver_device_is_agp(struct drm_device * dev)  { diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index dfa55e7478f..c33b0a41a73 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -84,6 +84,12 @@ MODULE_PARM_DESC(lvds_downclock,  		"Use panel (LVDS/eDP) downclocking for power savings "  		"(default: false)"); +int i915_lvds_channel_mode __read_mostly; +module_param_named(lvds_channel_mode, i915_lvds_channel_mode, int, 0600); +MODULE_PARM_DESC(lvds_channel_mode, +		 "Specify LVDS channel mode " +		 "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)"); +  int i915_panel_use_ssc __read_mostly = -1;  module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);  MODULE_PARM_DESC(lvds_use_ssc, @@ -93,8 +99,8 @@ MODULE_PARM_DESC(lvds_use_ssc,  int i915_vbt_sdvo_panel_type __read_mostly = -1;  module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);  MODULE_PARM_DESC(vbt_sdvo_panel_type, -		"Override selection of SDVO panel mode in the VBT " -		"(default: auto)"); +		"Override/Ignore selection of SDVO panel mode in the VBT " +		"(-2=ignore, -1=auto [default], index in VBT BIOS table)");  static bool i915_try_reset __read_mostly = true;  module_param_named(reset, i915_try_reset, bool, 0600); @@ -209,6 +215,7 @@ static const struct intel_device_info intel_ironlake_d_info = {  	.gen = 5,  	.need_gfx_hws = 1, .has_hotplug = 1,  	.has_bsd_ring = 1, +	.has_pch_split = 1,  };  static const struct intel_device_info intel_ironlake_m_info = { @@ -216,6 +223,7 @@ static const struct intel_device_info intel_ironlake_m_info = {  	.need_gfx_hws = 1, .has_hotplug = 1,  	.has_fbc = 1,  	.has_bsd_ring = 1, +	.has_pch_split = 1,  };  static const struct intel_device_info intel_sandybridge_d_info = { @@ -224,6 +232,7 @@ static const struct intel_device_info intel_sandybridge_d_info = {  	.has_bsd_ring = 1,  	.has_blt_ring = 1,  	.has_llc = 1, +	.has_pch_split = 1,  };  static const struct intel_device_info intel_sandybridge_m_info = { @@ -233,6 +242,7 @@ static const struct intel_device_info intel_sandybridge_m_info = {  	.has_bsd_ring = 1,  	.has_blt_ring = 1,  	.has_llc = 1, +	.has_pch_split = 1,  };  static const struct intel_device_info intel_ivybridge_d_info = { @@ -241,6 +251,7 @@ static const struct intel_device_info intel_ivybridge_d_info = {  	.has_bsd_ring = 1,  	.has_blt_ring = 1,  	.has_llc = 1, +	.has_pch_split = 1,  };  static const struct intel_device_info intel_ivybridge_m_info = { @@ -250,6 +261,43 @@ static const struct intel_device_info intel_ivybridge_m_info = {  	.has_bsd_ring = 1,  	.has_blt_ring = 1,  	.has_llc = 1, +	.has_pch_split = 1, +}; + +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, +	.is_valleyview = 1, +}; + +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, +	.is_valleyview = 1, +}; + +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_pch_split = 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_pch_split = 1,  };  static const struct pci_device_id pciidlist[] = {		/* aka */ @@ -308,6 +356,7 @@ MODULE_DEVICE_TABLE(pci, pciidlist);  #define INTEL_PCH_IBX_DEVICE_ID_TYPE	0x3b00  #define INTEL_PCH_CPT_DEVICE_ID_TYPE	0x1c00  #define INTEL_PCH_PPT_DEVICE_ID_TYPE	0x1e00 +#define INTEL_PCH_LPT_DEVICE_ID_TYPE	0x8c00  void intel_detect_pch(struct drm_device *dev)  { @@ -336,6 +385,9 @@ void intel_detect_pch(struct drm_device *dev)  				/* PantherPoint is CPT compatible */  				dev_priv->pch_type = PCH_CPT;  				DRM_DEBUG_KMS("Found PatherPoint PCH\n"); +			} else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { +				dev_priv->pch_type = PCH_LPT; +				DRM_DEBUG_KMS("Found LynxPoint PCH\n");  			}  		}  		pci_dev_put(pch); @@ -446,6 +498,31 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)  	return ret;  } +void vlv_force_wake_get(struct drm_i915_private *dev_priv) +{ +	int count; + +	count = 0; + +	/* Already awake? */ +	if ((I915_READ(0x130094) & 0xa1) == 0xa1) +		return; + +	I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffffffff); +	POSTING_READ(FORCEWAKE_VLV); + +	count = 0; +	while (count++ < 50 && (I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0) +		udelay(10); +} + +void vlv_force_wake_put(struct drm_i915_private *dev_priv) +{ +	I915_WRITE_NOTRACE(FORCEWAKE_VLV, 0xffff0000); +	/* FIXME: confirm VLV behavior with Punit folks */ +	POSTING_READ(FORCEWAKE_VLV); +} +  static int i915_drm_freeze(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -993,6 +1070,13 @@ MODULE_AUTHOR(DRIVER_AUTHOR);  MODULE_DESCRIPTION(DRIVER_DESC);  MODULE_LICENSE("GPL and additional rights"); +/* We give fast paths for the really cool registers */ +#define NEEDS_FORCE_WAKE(dev_priv, reg) \ +       (((dev_priv)->info->gen >= 6) && \ +        ((reg) < 0x40000) &&            \ +        ((reg) != FORCEWAKE)) && \ +       (!IS_VALLEYVIEW((dev_priv)->dev)) +  #define __i915_read(x, y) \  u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \  	u##x val = 0; \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5fabc6c31fe..92e496afc6f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -63,6 +63,16 @@ enum plane {  };  #define plane_name(p) ((p) + 'A') +enum port { +	PORT_A = 0, +	PORT_B, +	PORT_C, +	PORT_D, +	PORT_E, +	I915_MAX_PORTS +}; +#define port_name(p) ((p) + 'A') +  #define I915_GEM_GPU_DOMAINS	(~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))  #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) @@ -255,6 +265,9 @@ struct intel_device_info {  	u8 is_broadwater:1;  	u8 is_crestline:1;  	u8 is_ivybridge:1; +	u8 is_valleyview:1; +	u8 has_pch_split:1; +	u8 is_haswell:1;  	u8 has_fbc:1;  	u8 has_pipe_cxsr:1;  	u8 has_hotplug:1; @@ -291,10 +304,12 @@ enum no_fbc_reason {  enum intel_pch {  	PCH_IBX,	/* Ibexpeak PCH */  	PCH_CPT,	/* Cougarpoint PCH */ +	PCH_LPT,	/* Lynxpoint PCH */  };  #define QUIRK_PIPEA_FORCE (1<<0)  #define QUIRK_LVDS_SSC_DISABLE (1<<1) +#define QUIRK_INVERT_BRIGHTNESS (1<<2)  struct intel_fbdev;  struct intel_fbc_work; @@ -302,7 +317,6 @@ struct intel_fbc_work;  struct intel_gmbus {  	struct i2c_adapter adapter;  	bool force_bit; -	bool has_gpio;  	u32 reg0;  	u32 gpio_reg;  	struct i2c_algo_bit_data bit_algo; @@ -326,12 +340,17 @@ typedef struct drm_i915_private {  	/** gt_lock is also taken in irq contexts. */  	struct spinlock gt_lock; -	struct intel_gmbus *gmbus; +	struct intel_gmbus gmbus[GMBUS_NUM_PORTS];  	/** gmbus_mutex protects against concurrent usage of the single hw gmbus  	 * controller on different i2c buses. */  	struct mutex gmbus_mutex; +	/** +	 * Base address of the gmbus and gpio block. +	 */ +	uint32_t gpio_mmio_base; +  	struct pci_dev *bridge_dev;  	struct intel_ring_buffer ring[I915_NUM_RINGS];  	uint32_t next_seqno; @@ -354,6 +373,10 @@ typedef struct drm_i915_private {  	/* protects the irq masks */  	spinlock_t irq_lock; + +	/* DPIO indirect register protection */ +	spinlock_t dpio_lock; +  	/** Cached value of IMR to avoid reads in updating the bitfield */  	u32 pipestat[2];  	u32 irq_mask; @@ -405,6 +428,8 @@ typedef struct drm_i915_private {  	unsigned int lvds_use_ssc:1;  	unsigned int display_clock_mode:1;  	int lvds_ssc_freq; +	unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ +	unsigned int lvds_val; /* used for checking LVDS channel mode */  	struct {  		int rate;  		int lanes; @@ -881,6 +906,7 @@ struct drm_i915_gem_object {  	unsigned int cache_level:2;  	unsigned int has_aliasing_ppgtt_mapping:1; +	unsigned int has_global_gtt_mapping:1;  	struct page **pages; @@ -918,13 +944,6 @@ struct drm_i915_gem_object {  	/** Record of address bit 17 of each page at last unbind. */  	unsigned long *bit_17; - -	/** -	 * If present, while GEM_DOMAIN_CPU is in the read domain this array -	 * flags which individual pages are valid. -	 */ -	uint8_t *page_cpu_valid; -  	/** User space pin count and filp owning the pin */  	uint32_t user_pin_count;  	struct drm_file *pin_filp; @@ -1001,6 +1020,8 @@ struct drm_i915_file_private {  #define IS_IRONLAKE_D(dev)	((dev)->pci_device == 0x0042)  #define IS_IRONLAKE_M(dev)	((dev)->pci_device == 0x0046)  #define IS_IVYBRIDGE(dev)	(INTEL_INFO(dev)->is_ivybridge) +#define IS_VALLEYVIEW(dev)	(INTEL_INFO(dev)->is_valleyview) +#define IS_HASWELL(dev)	(INTEL_INFO(dev)->is_haswell)  #define IS_MOBILE(dev)		(INTEL_INFO(dev)->is_mobile)  /* @@ -1044,10 +1065,11 @@ struct drm_i915_file_private {  #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr)  #define I915_HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) -#define HAS_PCH_SPLIT(dev) (IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) +#define HAS_PCH_SPLIT(dev) (INTEL_INFO(dev)->has_pch_split)  #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5)  #define INTEL_PCH_TYPE(dev) (((struct drm_i915_private *)(dev)->dev_private)->pch_type) +#define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT)  #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT)  #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) @@ -1081,6 +1103,7 @@ extern int i915_panel_ignore_lid __read_mostly;  extern unsigned int i915_powersave __read_mostly;  extern int i915_semaphores __read_mostly;  extern unsigned int i915_lvds_downclock __read_mostly; +extern int i915_lvds_channel_mode __read_mostly;  extern int i915_panel_use_ssc __read_mostly;  extern int i915_vbt_sdvo_panel_type __read_mostly;  extern int i915_enable_rc6 __read_mostly; @@ -1264,10 +1287,6 @@ int __must_check i915_gem_init_hw(struct drm_device *dev);  void i915_gem_init_swizzling(struct drm_device *dev);  void i915_gem_init_ppgtt(struct drm_device *dev);  void i915_gem_cleanup_ringbuffer(struct drm_device *dev); -void i915_gem_do_init(struct drm_device *dev, -		      unsigned long start, -		      unsigned long mappable_end, -		      unsigned long end);  int __must_check i915_gpu_idle(struct drm_device *dev, bool do_retire);  int __must_check i915_gem_idle(struct drm_device *dev);  int __must_check i915_add_request(struct intel_ring_buffer *ring, @@ -1281,6 +1300,8 @@ int __must_check  i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,  				  bool write);  int __must_check +i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write); +int __must_check  i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,  				     u32 alignment,  				     struct intel_ring_buffer *pipelined); @@ -1311,10 +1332,15 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt,  			      struct drm_i915_gem_object *obj);  void i915_gem_restore_gtt_mappings(struct drm_device *dev); -int __must_check i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj); -void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj, +int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj); +void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj,  				enum i915_cache_level cache_level);  void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj); +void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj); +void i915_gem_init_global_gtt(struct drm_device *dev, +			      unsigned long start, +			      unsigned long mappable_end, +			      unsigned long end);  /* i915_gem_evict.c */  int __must_check i915_gem_evict_something(struct drm_device *dev, int min_size, @@ -1357,6 +1383,13 @@ extern int i915_restore_state(struct drm_device *dev);  /* intel_i2c.c */  extern int intel_setup_gmbus(struct drm_device *dev);  extern void intel_teardown_gmbus(struct drm_device *dev); +extern inline bool intel_gmbus_is_port_valid(unsigned port) +{ +	return (port >= GMBUS_PORT_SSC && port <= GMBUS_PORT_DPD); +} + +extern struct i2c_adapter *intel_gmbus_get_adapter( +		struct drm_i915_private *dev_priv, unsigned port);  extern void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed);  extern void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit);  extern inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) @@ -1409,6 +1442,9 @@ extern void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv);  extern void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);  extern void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv); +extern void vlv_force_wake_get(struct drm_i915_private *dev_priv); +extern void vlv_force_wake_put(struct drm_i915_private *dev_priv); +  /* overlay */  #ifdef CONFIG_DEBUG_FS  extern struct intel_overlay_error_state *intel_overlay_capture_error_state(struct drm_device *dev); @@ -1450,12 +1486,6 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv);  void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv);  int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); -/* We give fast paths for the really cool registers */ -#define NEEDS_FORCE_WAKE(dev_priv, reg) \ -	(((dev_priv)->info->gen >= 6) && \ -	 ((reg) < 0x40000) &&		 \ -	 ((reg) != FORCEWAKE)) -  #define __i915_read(x, y) \  	u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 4c65c639f77..b851bd34ca1 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -39,12 +39,6 @@  static __must_check int i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj);  static void i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj);  static void i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj); -static __must_check int i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, -							  bool write); -static __must_check int i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj, -								  uint64_t offset, -								  uint64_t size); -static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj);  static __must_check int i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,  						    unsigned alignment,  						    bool map_and_fenceable); @@ -125,25 +119,6 @@ i915_gem_object_is_inactive(struct drm_i915_gem_object *obj)  	return obj->gtt_space && !obj->active && obj->pin_count == 0;  } -void i915_gem_do_init(struct drm_device *dev, -		      unsigned long start, -		      unsigned long mappable_end, -		      unsigned long end) -{ -	drm_i915_private_t *dev_priv = dev->dev_private; - -	drm_mm_init(&dev_priv->mm.gtt_space, start, end - start); - -	dev_priv->mm.gtt_start = start; -	dev_priv->mm.gtt_mappable_end = mappable_end; -	dev_priv->mm.gtt_end = end; -	dev_priv->mm.gtt_total = end - start; -	dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start; - -	/* Take over this portion of the GTT */ -	intel_gtt_clear_range(start / PAGE_SIZE, (end-start) / PAGE_SIZE); -} -  int  i915_gem_init_ioctl(struct drm_device *dev, void *data,  		    struct drm_file *file) @@ -154,8 +129,13 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data,  	    (args->gtt_end | args->gtt_start) & (PAGE_SIZE - 1))  		return -EINVAL; +	/* GEM with user mode setting was never supported on ilk and later. */ +	if (INTEL_INFO(dev)->gen >= 5) +		return -ENODEV; +  	mutex_lock(&dev->struct_mutex); -	i915_gem_do_init(dev, args->gtt_start, args->gtt_end, args->gtt_end); +	i915_gem_init_global_gtt(dev, args->gtt_start, +				 args->gtt_end, args->gtt_end);  	mutex_unlock(&dev->struct_mutex);  	return 0; @@ -259,66 +239,6 @@ static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)  		obj->tiling_mode != I915_TILING_NONE;  } -/** - * This is the fast shmem pread path, which attempts to copy_from_user directly - * from the backing pages of the object to the user's address space.  On a - * fault, it fails so we can fall back to i915_gem_shmem_pwrite_slow(). - */ -static int -i915_gem_shmem_pread_fast(struct drm_device *dev, -			  struct drm_i915_gem_object *obj, -			  struct drm_i915_gem_pread *args, -			  struct drm_file *file) -{ -	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; -	ssize_t remain; -	loff_t offset; -	char __user *user_data; -	int page_offset, page_length; - -	user_data = (char __user *) (uintptr_t) args->data_ptr; -	remain = args->size; - -	offset = args->offset; - -	while (remain > 0) { -		struct page *page; -		char *vaddr; -		int ret; - -		/* Operation in this page -		 * -		 * page_offset = offset within page -		 * page_length = bytes to copy for this page -		 */ -		page_offset = offset_in_page(offset); -		page_length = remain; -		if ((page_offset + remain) > PAGE_SIZE) -			page_length = PAGE_SIZE - page_offset; - -		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); -		if (IS_ERR(page)) -			return PTR_ERR(page); - -		vaddr = kmap_atomic(page); -		ret = __copy_to_user_inatomic(user_data, -					      vaddr + page_offset, -					      page_length); -		kunmap_atomic(vaddr); - -		mark_page_accessed(page); -		page_cache_release(page); -		if (ret) -			return -EFAULT; - -		remain -= page_length; -		user_data += page_length; -		offset += page_length; -	} - -	return 0; -} -  static inline int  __copy_to_user_swizzled(char __user *cpu_vaddr,  			const char *gpu_vaddr, int gpu_offset, @@ -371,37 +291,121 @@ __copy_from_user_swizzled(char __user *gpu_vaddr, int gpu_offset,  	return 0;  } -/** - * This is the fallback shmem pread path, which allocates temporary storage - * in kernel space to copy_to_user into outside of the struct_mutex, so we - * can copy out of the object's backing pages while holding the struct mutex - * and not take page faults. - */ +/* Per-page copy function for the shmem pread fastpath. + * Flushes invalid cachelines before reading the target if + * needs_clflush is set. */  static int -i915_gem_shmem_pread_slow(struct drm_device *dev, -			  struct drm_i915_gem_object *obj, -			  struct drm_i915_gem_pread *args, -			  struct drm_file *file) +shmem_pread_fast(struct page *page, int shmem_page_offset, int page_length, +		 char __user *user_data, +		 bool page_do_bit17_swizzling, bool needs_clflush) +{ +	char *vaddr; +	int ret; + +	if (unlikely(page_do_bit17_swizzling)) +		return -EINVAL; + +	vaddr = kmap_atomic(page); +	if (needs_clflush) +		drm_clflush_virt_range(vaddr + shmem_page_offset, +				       page_length); +	ret = __copy_to_user_inatomic(user_data, +				      vaddr + shmem_page_offset, +				      page_length); +	kunmap_atomic(vaddr); + +	return ret; +} + +static void +shmem_clflush_swizzled_range(char *addr, unsigned long length, +			     bool swizzled) +{ +	if (unlikely(swizzled)) { +		unsigned long start = (unsigned long) addr; +		unsigned long end = (unsigned long) addr + length; + +		/* For swizzling simply ensure that we always flush both +		 * channels. Lame, but simple and it works. Swizzled +		 * pwrite/pread is far from a hotpath - current userspace +		 * doesn't use it at all. */ +		start = round_down(start, 128); +		end = round_up(end, 128); + +		drm_clflush_virt_range((void *)start, end - start); +	} else { +		drm_clflush_virt_range(addr, length); +	} + +} + +/* Only difference to the fast-path function is that this can handle bit17 + * and uses non-atomic copy and kmap functions. */ +static int +shmem_pread_slow(struct page *page, int shmem_page_offset, int page_length, +		 char __user *user_data, +		 bool page_do_bit17_swizzling, bool needs_clflush) +{ +	char *vaddr; +	int ret; + +	vaddr = kmap(page); +	if (needs_clflush) +		shmem_clflush_swizzled_range(vaddr + shmem_page_offset, +					     page_length, +					     page_do_bit17_swizzling); + +	if (page_do_bit17_swizzling) +		ret = __copy_to_user_swizzled(user_data, +					      vaddr, shmem_page_offset, +					      page_length); +	else +		ret = __copy_to_user(user_data, +				     vaddr + shmem_page_offset, +				     page_length); +	kunmap(page); + +	return ret; +} + +static int +i915_gem_shmem_pread(struct drm_device *dev, +		     struct drm_i915_gem_object *obj, +		     struct drm_i915_gem_pread *args, +		     struct drm_file *file)  {  	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;  	char __user *user_data;  	ssize_t remain;  	loff_t offset; -	int shmem_page_offset, page_length, ret; +	int shmem_page_offset, page_length, ret = 0;  	int obj_do_bit17_swizzling, page_do_bit17_swizzling; +	int hit_slowpath = 0; +	int prefaulted = 0; +	int needs_clflush = 0; +	int release_page;  	user_data = (char __user *) (uintptr_t) args->data_ptr;  	remain = args->size;  	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); -	offset = args->offset; +	if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU)) { +		/* If we're not in the cpu read domain, set ourself into the gtt +		 * read domain and manually flush cachelines (if required). This +		 * optimizes for the case when the gpu will dirty the data +		 * anyway again before the next pread happens. */ +		if (obj->cache_level == I915_CACHE_NONE) +			needs_clflush = 1; +		ret = i915_gem_object_set_to_gtt_domain(obj, false); +		if (ret) +			return ret; +	} -	mutex_unlock(&dev->struct_mutex); +	offset = args->offset;  	while (remain > 0) {  		struct page *page; -		char *vaddr;  		/* Operation in this page  		 * @@ -413,28 +417,51 @@ i915_gem_shmem_pread_slow(struct drm_device *dev,  		if ((shmem_page_offset + page_length) > PAGE_SIZE)  			page_length = PAGE_SIZE - shmem_page_offset; -		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); -		if (IS_ERR(page)) { -			ret = PTR_ERR(page); -			goto out; +		if (obj->pages) { +			page = obj->pages[offset >> PAGE_SHIFT]; +			release_page = 0; +		} else { +			page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); +			if (IS_ERR(page)) { +				ret = PTR_ERR(page); +				goto out; +			} +			release_page = 1;  		}  		page_do_bit17_swizzling = obj_do_bit17_swizzling &&  			(page_to_phys(page) & (1 << 17)) != 0; -		vaddr = kmap(page); -		if (page_do_bit17_swizzling) -			ret = __copy_to_user_swizzled(user_data, -						      vaddr, shmem_page_offset, -						      page_length); -		else -			ret = __copy_to_user(user_data, -					     vaddr + shmem_page_offset, -					     page_length); -		kunmap(page); +		ret = shmem_pread_fast(page, shmem_page_offset, page_length, +				       user_data, page_do_bit17_swizzling, +				       needs_clflush); +		if (ret == 0) +			goto next_page; -		mark_page_accessed(page); +		hit_slowpath = 1; +		page_cache_get(page); +		mutex_unlock(&dev->struct_mutex); + +		if (!prefaulted) { +			ret = fault_in_multipages_writeable(user_data, remain); +			/* Userspace is tricking us, but we've already clobbered +			 * its pages with the prefault and promised to write the +			 * data up to the first fault. Hence ignore any errors +			 * and just continue. */ +			(void)ret; +			prefaulted = 1; +		} + +		ret = shmem_pread_slow(page, shmem_page_offset, page_length, +				       user_data, page_do_bit17_swizzling, +				       needs_clflush); + +		mutex_lock(&dev->struct_mutex);  		page_cache_release(page); +next_page: +		mark_page_accessed(page); +		if (release_page) +			page_cache_release(page);  		if (ret) {  			ret = -EFAULT; @@ -447,10 +474,11 @@ i915_gem_shmem_pread_slow(struct drm_device *dev,  	}  out: -	mutex_lock(&dev->struct_mutex); -	/* Fixup: Kill any reinstated backing storage pages */ -	if (obj->madv == __I915_MADV_PURGED) -		i915_gem_object_truncate(obj); +	if (hit_slowpath) { +		/* Fixup: Kill any reinstated backing storage pages */ +		if (obj->madv == __I915_MADV_PURGED) +			i915_gem_object_truncate(obj); +	}  	return ret;  } @@ -476,11 +504,6 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,  		       args->size))  		return -EFAULT; -	ret = fault_in_pages_writeable((char __user *)(uintptr_t)args->data_ptr, -				       args->size); -	if (ret) -		return -EFAULT; -  	ret = i915_mutex_lock_interruptible(dev);  	if (ret)  		return ret; @@ -500,17 +523,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,  	trace_i915_gem_object_pread(obj, args->offset, args->size); -	ret = i915_gem_object_set_cpu_read_domain_range(obj, -							args->offset, -							args->size); -	if (ret) -		goto out; - -	ret = -EFAULT; -	if (!i915_gem_object_needs_bit17_swizzle(obj)) -		ret = i915_gem_shmem_pread_fast(dev, obj, args, file); -	if (ret == -EFAULT) -		ret = i915_gem_shmem_pread_slow(dev, obj, args, file); +	ret = i915_gem_shmem_pread(dev, obj, args, file);  out:  	drm_gem_object_unreference(&obj->base); @@ -539,30 +552,6 @@ fast_user_write(struct io_mapping *mapping,  	return unwritten;  } -/* Here's the write path which can sleep for - * page faults - */ - -static inline void -slow_kernel_write(struct io_mapping *mapping, -		  loff_t gtt_base, int gtt_offset, -		  struct page *user_page, int user_offset, -		  int length) -{ -	char __iomem *dst_vaddr; -	char *src_vaddr; - -	dst_vaddr = io_mapping_map_wc(mapping, gtt_base); -	src_vaddr = kmap(user_page); - -	memcpy_toio(dst_vaddr + gtt_offset, -		    src_vaddr + user_offset, -		    length); - -	kunmap(user_page); -	io_mapping_unmap(dst_vaddr); -} -  /**   * This is the fast pwrite path, where we copy the data directly from the   * user into the GTT, uncached. @@ -577,7 +566,19 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,  	ssize_t remain;  	loff_t offset, page_base;  	char __user *user_data; -	int page_offset, page_length; +	int page_offset, page_length, ret; + +	ret = i915_gem_object_pin(obj, 0, true); +	if (ret) +		goto out; + +	ret = i915_gem_object_set_to_gtt_domain(obj, true); +	if (ret) +		goto out_unpin; + +	ret = i915_gem_object_put_fence(obj); +	if (ret) +		goto out_unpin;  	user_data = (char __user *) (uintptr_t) args->data_ptr;  	remain = args->size; @@ -602,214 +603,133 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,  		 * retry in the slow path.  		 */  		if (fast_user_write(dev_priv->mm.gtt_mapping, page_base, -				    page_offset, user_data, page_length)) -			return -EFAULT; +				    page_offset, user_data, page_length)) { +			ret = -EFAULT; +			goto out_unpin; +		}  		remain -= page_length;  		user_data += page_length;  		offset += page_length;  	} -	return 0; +out_unpin: +	i915_gem_object_unpin(obj); +out: +	return ret;  } -/** - * This is the fallback GTT pwrite path, which uses get_user_pages to pin - * the memory and maps it using kmap_atomic for copying. - * - * This code resulted in x11perf -rgb10text consuming about 10% more CPU - * than using i915_gem_gtt_pwrite_fast on a G45 (32-bit). - */ +/* Per-page copy function for the shmem pwrite fastpath. + * Flushes invalid cachelines before writing to the target if + * needs_clflush_before is set and flushes out any written cachelines after + * writing if needs_clflush is set. */  static int -i915_gem_gtt_pwrite_slow(struct drm_device *dev, -			 struct drm_i915_gem_object *obj, -			 struct drm_i915_gem_pwrite *args, -			 struct drm_file *file) +shmem_pwrite_fast(struct page *page, int shmem_page_offset, int page_length, +		  char __user *user_data, +		  bool page_do_bit17_swizzling, +		  bool needs_clflush_before, +		  bool needs_clflush_after)  { -	drm_i915_private_t *dev_priv = dev->dev_private; -	ssize_t remain; -	loff_t gtt_page_base, offset; -	loff_t first_data_page, last_data_page, num_pages; -	loff_t pinned_pages, i; -	struct page **user_pages; -	struct mm_struct *mm = current->mm; -	int gtt_page_offset, data_page_offset, data_page_index, page_length; +	char *vaddr;  	int ret; -	uint64_t data_ptr = args->data_ptr; - -	remain = args->size; - -	/* Pin the user pages containing the data.  We can't fault while -	 * holding the struct mutex, and all of the pwrite implementations -	 * want to hold it while dereferencing the user data. -	 */ -	first_data_page = data_ptr / PAGE_SIZE; -	last_data_page = (data_ptr + args->size - 1) / PAGE_SIZE; -	num_pages = last_data_page - first_data_page + 1; - -	user_pages = drm_malloc_ab(num_pages, sizeof(struct page *)); -	if (user_pages == NULL) -		return -ENOMEM; - -	mutex_unlock(&dev->struct_mutex); -	down_read(&mm->mmap_sem); -	pinned_pages = get_user_pages(current, mm, (uintptr_t)args->data_ptr, -				      num_pages, 0, 0, user_pages, NULL); -	up_read(&mm->mmap_sem); -	mutex_lock(&dev->struct_mutex); -	if (pinned_pages < num_pages) { -		ret = -EFAULT; -		goto out_unpin_pages; -	} - -	ret = i915_gem_object_set_to_gtt_domain(obj, true); -	if (ret) -		goto out_unpin_pages; - -	ret = i915_gem_object_put_fence(obj); -	if (ret) -		goto out_unpin_pages; - -	offset = obj->gtt_offset + args->offset; - -	while (remain > 0) { -		/* Operation in this page -		 * -		 * gtt_page_base = page offset within aperture -		 * gtt_page_offset = offset within page in aperture -		 * data_page_index = page number in get_user_pages return -		 * data_page_offset = offset with data_page_index page. -		 * page_length = bytes to copy for this page -		 */ -		gtt_page_base = offset & PAGE_MASK; -		gtt_page_offset = offset_in_page(offset); -		data_page_index = data_ptr / PAGE_SIZE - first_data_page; -		data_page_offset = offset_in_page(data_ptr); -		page_length = remain; -		if ((gtt_page_offset + page_length) > PAGE_SIZE) -			page_length = PAGE_SIZE - gtt_page_offset; -		if ((data_page_offset + page_length) > PAGE_SIZE) -			page_length = PAGE_SIZE - data_page_offset; - -		slow_kernel_write(dev_priv->mm.gtt_mapping, -				  gtt_page_base, gtt_page_offset, -				  user_pages[data_page_index], -				  data_page_offset, -				  page_length); - -		remain -= page_length; -		offset += page_length; -		data_ptr += page_length; -	} +	if (unlikely(page_do_bit17_swizzling)) +		return -EINVAL; -out_unpin_pages: -	for (i = 0; i < pinned_pages; i++) -		page_cache_release(user_pages[i]); -	drm_free_large(user_pages); +	vaddr = kmap_atomic(page); +	if (needs_clflush_before) +		drm_clflush_virt_range(vaddr + shmem_page_offset, +				       page_length); +	ret = __copy_from_user_inatomic_nocache(vaddr + shmem_page_offset, +						user_data, +						page_length); +	if (needs_clflush_after) +		drm_clflush_virt_range(vaddr + shmem_page_offset, +				       page_length); +	kunmap_atomic(vaddr);  	return ret;  } -/** - * This is the fast shmem pwrite path, which attempts to directly - * copy_from_user into the kmapped pages backing the object. - */ +/* Only difference to the fast-path function is that this can handle bit17 + * and uses non-atomic copy and kmap functions. */  static int -i915_gem_shmem_pwrite_fast(struct drm_device *dev, -			   struct drm_i915_gem_object *obj, -			   struct drm_i915_gem_pwrite *args, -			   struct drm_file *file) +shmem_pwrite_slow(struct page *page, int shmem_page_offset, int page_length, +		  char __user *user_data, +		  bool page_do_bit17_swizzling, +		  bool needs_clflush_before, +		  bool needs_clflush_after)  { -	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; -	ssize_t remain; -	loff_t offset; -	char __user *user_data; -	int page_offset, page_length; - -	user_data = (char __user *) (uintptr_t) args->data_ptr; -	remain = args->size; - -	offset = args->offset; -	obj->dirty = 1; - -	while (remain > 0) { -		struct page *page; -		char *vaddr; -		int ret; - -		/* Operation in this page -		 * -		 * page_offset = offset within page -		 * page_length = bytes to copy for this page -		 */ -		page_offset = offset_in_page(offset); -		page_length = remain; -		if ((page_offset + remain) > PAGE_SIZE) -			page_length = PAGE_SIZE - page_offset; - -		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); -		if (IS_ERR(page)) -			return PTR_ERR(page); +	char *vaddr; +	int ret; -		vaddr = kmap_atomic(page); -		ret = __copy_from_user_inatomic(vaddr + page_offset, +	vaddr = kmap(page); +	if (unlikely(needs_clflush_before || page_do_bit17_swizzling)) +		shmem_clflush_swizzled_range(vaddr + shmem_page_offset, +					     page_length, +					     page_do_bit17_swizzling); +	if (page_do_bit17_swizzling) +		ret = __copy_from_user_swizzled(vaddr, shmem_page_offset,  						user_data,  						page_length); -		kunmap_atomic(vaddr); - -		set_page_dirty(page); -		mark_page_accessed(page); -		page_cache_release(page); - -		/* If we get a fault while copying data, then (presumably) our -		 * source page isn't available.  Return the error and we'll -		 * retry in the slow path. -		 */ -		if (ret) -			return -EFAULT; - -		remain -= page_length; -		user_data += page_length; -		offset += page_length; -	} +	else +		ret = __copy_from_user(vaddr + shmem_page_offset, +				       user_data, +				       page_length); +	if (needs_clflush_after) +		shmem_clflush_swizzled_range(vaddr + shmem_page_offset, +					     page_length, +					     page_do_bit17_swizzling); +	kunmap(page); -	return 0; +	return ret;  } -/** - * This is the fallback shmem pwrite path, which uses get_user_pages to pin - * the memory and maps it using kmap_atomic for copying. - * - * This avoids taking mmap_sem for faulting on the user's address while the - * struct_mutex is held. - */  static int -i915_gem_shmem_pwrite_slow(struct drm_device *dev, -			   struct drm_i915_gem_object *obj, -			   struct drm_i915_gem_pwrite *args, -			   struct drm_file *file) +i915_gem_shmem_pwrite(struct drm_device *dev, +		      struct drm_i915_gem_object *obj, +		      struct drm_i915_gem_pwrite *args, +		      struct drm_file *file)  {  	struct address_space *mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;  	ssize_t remain;  	loff_t offset;  	char __user *user_data; -	int shmem_page_offset, page_length, ret; +	int shmem_page_offset, page_length, ret = 0;  	int obj_do_bit17_swizzling, page_do_bit17_swizzling; +	int hit_slowpath = 0; +	int needs_clflush_after = 0; +	int needs_clflush_before = 0; +	int release_page;  	user_data = (char __user *) (uintptr_t) args->data_ptr;  	remain = args->size;  	obj_do_bit17_swizzling = i915_gem_object_needs_bit17_swizzle(obj); +	if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) { +		/* If we're not in the cpu write domain, set ourself into the gtt +		 * write domain and manually flush cachelines (if required). This +		 * optimizes for the case when the gpu will use the data +		 * right away and we therefore have to clflush anyway. */ +		if (obj->cache_level == I915_CACHE_NONE) +			needs_clflush_after = 1; +		ret = i915_gem_object_set_to_gtt_domain(obj, true); +		if (ret) +			return ret; +	} +	/* Same trick applies for invalidate partially written cachelines before +	 * writing.  */ +	if (!(obj->base.read_domains & I915_GEM_DOMAIN_CPU) +	    && obj->cache_level == I915_CACHE_NONE) +		needs_clflush_before = 1; +  	offset = args->offset;  	obj->dirty = 1; -	mutex_unlock(&dev->struct_mutex); -  	while (remain > 0) {  		struct page *page; -		char *vaddr; +		int partial_cacheline_write;  		/* Operation in this page  		 * @@ -822,29 +742,51 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev,  		if ((shmem_page_offset + page_length) > PAGE_SIZE)  			page_length = PAGE_SIZE - shmem_page_offset; -		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); -		if (IS_ERR(page)) { -			ret = PTR_ERR(page); -			goto out; +		/* If we don't overwrite a cacheline completely we need to be +		 * careful to have up-to-date data by first clflushing. Don't +		 * overcomplicate things and flush the entire patch. */ +		partial_cacheline_write = needs_clflush_before && +			((shmem_page_offset | page_length) +				& (boot_cpu_data.x86_clflush_size - 1)); + +		if (obj->pages) { +			page = obj->pages[offset >> PAGE_SHIFT]; +			release_page = 0; +		} else { +			page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); +			if (IS_ERR(page)) { +				ret = PTR_ERR(page); +				goto out; +			} +			release_page = 1;  		}  		page_do_bit17_swizzling = obj_do_bit17_swizzling &&  			(page_to_phys(page) & (1 << 17)) != 0; -		vaddr = kmap(page); -		if (page_do_bit17_swizzling) -			ret = __copy_from_user_swizzled(vaddr, shmem_page_offset, -							user_data, -							page_length); -		else -			ret = __copy_from_user(vaddr + shmem_page_offset, -					       user_data, -					       page_length); -		kunmap(page); +		ret = shmem_pwrite_fast(page, shmem_page_offset, page_length, +					user_data, page_do_bit17_swizzling, +					partial_cacheline_write, +					needs_clflush_after); +		if (ret == 0) +			goto next_page; +		hit_slowpath = 1; +		page_cache_get(page); +		mutex_unlock(&dev->struct_mutex); + +		ret = shmem_pwrite_slow(page, shmem_page_offset, page_length, +					user_data, page_do_bit17_swizzling, +					partial_cacheline_write, +					needs_clflush_after); + +		mutex_lock(&dev->struct_mutex); +		page_cache_release(page); +next_page:  		set_page_dirty(page);  		mark_page_accessed(page); -		page_cache_release(page); +		if (release_page) +			page_cache_release(page);  		if (ret) {  			ret = -EFAULT; @@ -857,17 +799,21 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev,  	}  out: -	mutex_lock(&dev->struct_mutex); -	/* Fixup: Kill any reinstated backing storage pages */ -	if (obj->madv == __I915_MADV_PURGED) -		i915_gem_object_truncate(obj); -	/* and flush dirty cachelines in case the object isn't in the cpu write -	 * domain anymore. */ -	if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) { -		i915_gem_clflush_object(obj); -		intel_gtt_chipset_flush(); +	if (hit_slowpath) { +		/* Fixup: Kill any reinstated backing storage pages */ +		if (obj->madv == __I915_MADV_PURGED) +			i915_gem_object_truncate(obj); +		/* and flush dirty cachelines in case the object isn't in the cpu write +		 * domain anymore. */ +		if (obj->base.write_domain != I915_GEM_DOMAIN_CPU) { +			i915_gem_clflush_object(obj); +			intel_gtt_chipset_flush(); +		}  	} +	if (needs_clflush_after) +		intel_gtt_chipset_flush(); +  	return ret;  } @@ -892,8 +838,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,  		       args->size))  		return -EFAULT; -	ret = fault_in_pages_readable((char __user *)(uintptr_t)args->data_ptr, -				      args->size); +	ret = fault_in_multipages_readable((char __user *)(uintptr_t)args->data_ptr, +					   args->size);  	if (ret)  		return -EFAULT; @@ -916,6 +862,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,  	trace_i915_gem_object_pwrite(obj, args->offset, args->size); +	ret = -EFAULT;  	/* We can only do the GTT pwrite on untiled buffers, as otherwise  	 * it would end up going through the fenced access, and we'll get  	 * different detiling behavior between reading and writing. @@ -928,42 +875,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,  	}  	if (obj->gtt_space && +	    obj->cache_level == I915_CACHE_NONE && +	    obj->map_and_fenceable &&  	    obj->base.write_domain != I915_GEM_DOMAIN_CPU) { -		ret = i915_gem_object_pin(obj, 0, true); -		if (ret) -			goto out; - -		ret = i915_gem_object_set_to_gtt_domain(obj, true); -		if (ret) -			goto out_unpin; - -		ret = i915_gem_object_put_fence(obj); -		if (ret) -			goto out_unpin; -  		ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file); -		if (ret == -EFAULT) -			ret = i915_gem_gtt_pwrite_slow(dev, obj, args, file); - -out_unpin: -		i915_gem_object_unpin(obj); - -		if (ret != -EFAULT) -			goto out; -		/* Fall through to the shmfs paths because the gtt paths might -		 * fail with non-page-backed user pointers (e.g. gtt mappings -		 * when moving data between textures). */ +		/* Note that the gtt paths might fail with non-page-backed user +		 * pointers (e.g. gtt mappings when moving data between +		 * textures). Fallback to the shmem path in that case. */  	} -	ret = i915_gem_object_set_to_cpu_domain(obj, 1); -	if (ret) -		goto out; - -	ret = -EFAULT; -	if (!i915_gem_object_needs_bit17_swizzle(obj)) -		ret = i915_gem_shmem_pwrite_fast(dev, obj, args, file);  	if (ret == -EFAULT) -		ret = i915_gem_shmem_pwrite_slow(dev, obj, args, file); +		ret = i915_gem_shmem_pwrite(dev, obj, args, file);  out:  	drm_gem_object_unreference(&obj->base); @@ -1153,6 +1075,9 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  			goto unlock;  	} +	if (!obj->has_global_gtt_mapping) +		i915_gem_gtt_bind_object(obj, obj->cache_level); +  	if (obj->tiling_mode == I915_TILING_NONE)  		ret = i915_gem_object_put_fence(obj);  	else @@ -1546,6 +1471,9 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)  	inode = obj->base.filp->f_path.dentry->d_inode;  	shmem_truncate_range(inode, 0, (loff_t)-1); +	if (obj->base.map_list.map) +		drm_gem_free_mmap_offset(&obj->base); +  	obj->madv = __I915_MADV_PURGED;  } @@ -1954,6 +1882,8 @@ i915_wait_request(struct intel_ring_buffer *ring,  	if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) {  		if (HAS_PCH_SPLIT(ring->dev))  			ier = I915_READ(DEIER) | I915_READ(GTIER); +		else if (IS_VALLEYVIEW(ring->dev)) +			ier = I915_READ(GTIER) | I915_READ(VLV_IER);  		else  			ier = I915_READ(IER);  		if (!ier) { @@ -2100,11 +2030,13 @@ i915_gem_object_unbind(struct drm_i915_gem_object *obj)  	trace_i915_gem_object_unbind(obj); -	i915_gem_gtt_unbind_object(obj); +	if (obj->has_global_gtt_mapping) +		i915_gem_gtt_unbind_object(obj);  	if (obj->has_aliasing_ppgtt_mapping) {  		i915_ppgtt_unbind_object(dev_priv->mm.aliasing_ppgtt, obj);  		obj->has_aliasing_ppgtt_mapping = 0;  	} +	i915_gem_gtt_finish_object(obj);  	i915_gem_object_put_pages_gtt(obj); @@ -2749,7 +2681,7 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,  		return ret;  	} -	ret = i915_gem_gtt_bind_object(obj); +	ret = i915_gem_gtt_prepare_object(obj);  	if (ret) {  		i915_gem_object_put_pages_gtt(obj);  		drm_mm_put_block(obj->gtt_space); @@ -2761,6 +2693,9 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,  		goto search_free;  	} +	if (!dev_priv->mm.aliasing_ppgtt) +		i915_gem_gtt_bind_object(obj, obj->cache_level); +  	list_add_tail(&obj->gtt_list, &dev_priv->mm.gtt_list);  	list_add_tail(&obj->mm_list, &dev_priv->mm.inactive_list); @@ -2953,7 +2888,8 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,  				return ret;  		} -		i915_gem_gtt_rebind_object(obj, cache_level); +		if (obj->has_global_gtt_mapping) +			i915_gem_gtt_bind_object(obj, cache_level);  		if (obj->has_aliasing_ppgtt_mapping)  			i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,  					       obj, cache_level); @@ -3082,7 +3018,7 @@ i915_gem_object_finish_gpu(struct drm_i915_gem_object *obj)   * This function returns when the move is complete, including waiting on   * flushes to occur.   */ -static int +int  i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)  {  	uint32_t old_write_domain, old_read_domains; @@ -3101,11 +3037,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)  	i915_gem_object_flush_gtt_write_domain(obj); -	/* If we have a partially-valid cache of the object in the CPU, -	 * finish invalidating it and free the per-page flags. -	 */ -	i915_gem_object_set_to_full_cpu_read_domain(obj); -  	old_write_domain = obj->base.write_domain;  	old_read_domains = obj->base.read_domains; @@ -3136,113 +3067,6 @@ i915_gem_object_set_to_cpu_domain(struct drm_i915_gem_object *obj, bool write)  	return 0;  } -/** - * Moves the object from a partially CPU read to a full one. - * - * Note that this only resolves i915_gem_object_set_cpu_read_domain_range(), - * and doesn't handle transitioning from !(read_domains & I915_GEM_DOMAIN_CPU). - */ -static void -i915_gem_object_set_to_full_cpu_read_domain(struct drm_i915_gem_object *obj) -{ -	if (!obj->page_cpu_valid) -		return; - -	/* If we're partially in the CPU read domain, finish moving it in. -	 */ -	if (obj->base.read_domains & I915_GEM_DOMAIN_CPU) { -		int i; - -		for (i = 0; i <= (obj->base.size - 1) / PAGE_SIZE; i++) { -			if (obj->page_cpu_valid[i]) -				continue; -			drm_clflush_pages(obj->pages + i, 1); -		} -	} - -	/* Free the page_cpu_valid mappings which are now stale, whether -	 * or not we've got I915_GEM_DOMAIN_CPU. -	 */ -	kfree(obj->page_cpu_valid); -	obj->page_cpu_valid = NULL; -} - -/** - * Set the CPU read domain on a range of the object. - * - * The object ends up with I915_GEM_DOMAIN_CPU in its read flags although it's - * not entirely valid.  The page_cpu_valid member of the object flags which - * pages have been flushed, and will be respected by - * i915_gem_object_set_to_cpu_domain() if it's called on to get a valid mapping - * of the whole object. - * - * This function returns when the move is complete, including waiting on - * flushes to occur. - */ -static int -i915_gem_object_set_cpu_read_domain_range(struct drm_i915_gem_object *obj, -					  uint64_t offset, uint64_t size) -{ -	uint32_t old_read_domains; -	int i, ret; - -	if (offset == 0 && size == obj->base.size) -		return i915_gem_object_set_to_cpu_domain(obj, 0); - -	ret = i915_gem_object_flush_gpu_write_domain(obj); -	if (ret) -		return ret; - -	ret = i915_gem_object_wait_rendering(obj); -	if (ret) -		return ret; - -	i915_gem_object_flush_gtt_write_domain(obj); - -	/* If we're already fully in the CPU read domain, we're done. */ -	if (obj->page_cpu_valid == NULL && -	    (obj->base.read_domains & I915_GEM_DOMAIN_CPU) != 0) -		return 0; - -	/* Otherwise, create/clear the per-page CPU read domain flag if we're -	 * newly adding I915_GEM_DOMAIN_CPU -	 */ -	if (obj->page_cpu_valid == NULL) { -		obj->page_cpu_valid = kzalloc(obj->base.size / PAGE_SIZE, -					      GFP_KERNEL); -		if (obj->page_cpu_valid == NULL) -			return -ENOMEM; -	} else if ((obj->base.read_domains & I915_GEM_DOMAIN_CPU) == 0) -		memset(obj->page_cpu_valid, 0, obj->base.size / PAGE_SIZE); - -	/* Flush the cache on any pages that are still invalid from the CPU's -	 * perspective. -	 */ -	for (i = offset / PAGE_SIZE; i <= (offset + size - 1) / PAGE_SIZE; -	     i++) { -		if (obj->page_cpu_valid[i]) -			continue; - -		drm_clflush_pages(obj->pages + i, 1); - -		obj->page_cpu_valid[i] = 1; -	} - -	/* It should now be out of any other write domains, and we can update -	 * the domain values for our changes. -	 */ -	BUG_ON((obj->base.write_domain & ~I915_GEM_DOMAIN_CPU) != 0); - -	old_read_domains = obj->base.read_domains; -	obj->base.read_domains |= I915_GEM_DOMAIN_CPU; - -	trace_i915_gem_object_change_domain(obj, -					    old_read_domains, -					    obj->base.write_domain); - -	return 0; -} -  /* Throttle our rendering by waiting until the ring has completed our requests   * emitted over 20 msec ago.   * @@ -3343,6 +3167,9 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,  			return ret;  	} +	if (!obj->has_global_gtt_mapping && map_and_fenceable) +		i915_gem_gtt_bind_object(obj, obj->cache_level); +  	if (obj->pin_count++ == 0) {  		if (!obj->active)  			list_move_tail(&obj->mm_list, @@ -3664,7 +3491,6 @@ static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj)  	drm_gem_object_release(&obj->base);  	i915_gem_info_remove_obj(dev_priv, obj->base.size); -	kfree(obj->page_cpu_valid);  	kfree(obj->bit_17);  	kfree(obj);  } diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index f51a696486c..254e2f6ac4f 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -266,6 +266,12 @@ eb_destroy(struct eb_objects *eb)  	kfree(eb);  } +static inline int use_cpu_reloc(struct drm_i915_gem_object *obj) +{ +	return (obj->base.write_domain == I915_GEM_DOMAIN_CPU || +		obj->cache_level != I915_CACHE_NONE); +} +  static int  i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  				   struct eb_objects *eb, @@ -273,6 +279,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  {  	struct drm_device *dev = obj->base.dev;  	struct drm_gem_object *target_obj; +	struct drm_i915_gem_object *target_i915_obj;  	uint32_t target_offset;  	int ret = -EINVAL; @@ -281,7 +288,8 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  	if (unlikely(target_obj == NULL))  		return -ENOENT; -	target_offset = to_intel_bo(target_obj)->gtt_offset; +	target_i915_obj = to_intel_bo(target_obj); +	target_offset = target_i915_obj->gtt_offset;  	/* The target buffer should have appeared before us in the  	 * exec_object list, so it should have a GTT space bound by now. @@ -352,11 +360,19 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  		return ret;  	} +	/* We can't wait for rendering with pagefaults disabled */ +	if (obj->active && in_atomic()) +		return -EFAULT; +  	reloc->delta += target_offset; -	if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) { +	if (use_cpu_reloc(obj)) {  		uint32_t page_offset = reloc->offset & ~PAGE_MASK;  		char *vaddr; +		ret = i915_gem_object_set_to_cpu_domain(obj, 1); +		if (ret) +			return ret; +  		vaddr = kmap_atomic(obj->pages[reloc->offset >> PAGE_SHIFT]);  		*(uint32_t *)(vaddr + page_offset) = reloc->delta;  		kunmap_atomic(vaddr); @@ -365,10 +381,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  		uint32_t __iomem *reloc_entry;  		void __iomem *reloc_page; -		/* We can't wait for rendering with pagefaults disabled */ -		if (obj->active && in_atomic()) -			return -EFAULT; -  		ret = i915_gem_object_set_to_gtt_domain(obj, 1);  		if (ret)  			return ret; @@ -383,6 +395,16 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  		io_mapping_unmap_atomic(reloc_page);  	} +	/* Sandybridge PPGTT errata: We need a global gtt mapping for MI and +	 * pipe_control writes because the gpu doesn't properly redirect them +	 * through the ppgtt for non_secure batchbuffers. */ +	if (unlikely(IS_GEN6(dev) && +	    reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION && +	    !target_i915_obj->has_global_gtt_mapping)) { +		i915_gem_gtt_bind_object(target_i915_obj, +					 target_i915_obj->cache_level); +	} +  	/* and update the user's relocation entry */  	reloc->presumed_offset = target_offset; @@ -393,30 +415,46 @@ static int  i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,  				    struct eb_objects *eb)  { +#define N_RELOC(x) ((x) / sizeof(struct drm_i915_gem_relocation_entry)) +	struct drm_i915_gem_relocation_entry stack_reloc[N_RELOC(512)];  	struct drm_i915_gem_relocation_entry __user *user_relocs;  	struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; -	int i, ret; +	int remain, ret;  	user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr; -	for (i = 0; i < entry->relocation_count; i++) { -		struct drm_i915_gem_relocation_entry reloc; -		if (__copy_from_user_inatomic(&reloc, -					      user_relocs+i, -					      sizeof(reloc))) +	remain = entry->relocation_count; +	while (remain) { +		struct drm_i915_gem_relocation_entry *r = stack_reloc; +		int count = remain; +		if (count > ARRAY_SIZE(stack_reloc)) +			count = ARRAY_SIZE(stack_reloc); +		remain -= count; + +		if (__copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0])))  			return -EFAULT; -		ret = i915_gem_execbuffer_relocate_entry(obj, eb, &reloc); -		if (ret) -			return ret; +		do { +			u64 offset = r->presumed_offset; -		if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset, -					    &reloc.presumed_offset, -					    sizeof(reloc.presumed_offset))) -			return -EFAULT; +			ret = i915_gem_execbuffer_relocate_entry(obj, eb, r); +			if (ret) +				return ret; + +			if (r->presumed_offset != offset && +			    __copy_to_user_inatomic(&user_relocs->presumed_offset, +						    &r->presumed_offset, +						    sizeof(r->presumed_offset))) { +				return -EFAULT; +			} + +			user_relocs++; +			r++; +		} while (--count);  	}  	return 0; +#undef N_RELOC  }  static int @@ -465,6 +503,13 @@ i915_gem_execbuffer_relocate(struct drm_device *dev,  #define  __EXEC_OBJECT_HAS_FENCE (1<<31)  static int +need_reloc_mappable(struct drm_i915_gem_object *obj) +{ +	struct drm_i915_gem_exec_object2 *entry = obj->exec_entry; +	return entry->relocation_count && !use_cpu_reloc(obj); +} + +static int  pin_and_fence_object(struct drm_i915_gem_object *obj,  		     struct intel_ring_buffer *ring)  { @@ -477,8 +522,7 @@ pin_and_fence_object(struct drm_i915_gem_object *obj,  		has_fenced_gpu_access &&  		entry->flags & EXEC_OBJECT_NEEDS_FENCE &&  		obj->tiling_mode != I915_TILING_NONE; -	need_mappable = -		entry->relocation_count ? true : need_fence; +	need_mappable = need_fence || need_reloc_mappable(obj);  	ret = i915_gem_object_pin(obj, entry->alignment, need_mappable);  	if (ret) @@ -535,8 +579,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,  			has_fenced_gpu_access &&  			entry->flags & EXEC_OBJECT_NEEDS_FENCE &&  			obj->tiling_mode != I915_TILING_NONE; -		need_mappable = -			entry->relocation_count ? true : need_fence; +		need_mappable = need_fence || need_reloc_mappable(obj);  		if (need_mappable)  			list_move(&obj->exec_list, &ordered_objects); @@ -576,8 +619,7 @@ i915_gem_execbuffer_reserve(struct intel_ring_buffer *ring,  				has_fenced_gpu_access &&  				entry->flags & EXEC_OBJECT_NEEDS_FENCE &&  				obj->tiling_mode != I915_TILING_NONE; -			need_mappable = -				entry->relocation_count ? true : need_fence; +			need_mappable = need_fence || need_reloc_mappable(obj);  			if ((entry->alignment && obj->gtt_offset & (entry->alignment - 1)) ||  			    (need_mappable && !obj->map_and_fenceable)) @@ -955,7 +997,7 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,  		if (!access_ok(VERIFY_WRITE, ptr, length))  			return -EFAULT; -		if (fault_in_pages_readable(ptr, length)) +		if (fault_in_multipages_readable(ptr, length))  			return -EFAULT;  	} diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a135c61f411..4fb875de32e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -346,42 +346,28 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)  	list_for_each_entry(obj, &dev_priv->mm.gtt_list, gtt_list) {  		i915_gem_clflush_object(obj); -		i915_gem_gtt_rebind_object(obj, obj->cache_level); +		i915_gem_gtt_bind_object(obj, obj->cache_level);  	}  	intel_gtt_chipset_flush();  } -int i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj) +int i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj)  {  	struct drm_device *dev = obj->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; -	unsigned int agp_type = cache_level_to_agp_type(dev, obj->cache_level); -	int ret; -	if (dev_priv->mm.gtt->needs_dmar) { -		ret = intel_gtt_map_memory(obj->pages, -					   obj->base.size >> PAGE_SHIFT, -					   &obj->sg_list, -					   &obj->num_sg); -		if (ret != 0) -			return ret; - -		intel_gtt_insert_sg_entries(obj->sg_list, -					    obj->num_sg, -					    obj->gtt_space->start >> PAGE_SHIFT, -					    agp_type); -	} else -		intel_gtt_insert_pages(obj->gtt_space->start >> PAGE_SHIFT, -				       obj->base.size >> PAGE_SHIFT, -				       obj->pages, -				       agp_type); - -	return 0; +	if (dev_priv->mm.gtt->needs_dmar) +		return intel_gtt_map_memory(obj->pages, +					    obj->base.size >> PAGE_SHIFT, +					    &obj->sg_list, +					    &obj->num_sg); +	else +		return 0;  } -void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj, -				enum i915_cache_level cache_level) +void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, +			      enum i915_cache_level cache_level)  {  	struct drm_device *dev = obj->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -399,19 +385,26 @@ void i915_gem_gtt_rebind_object(struct drm_i915_gem_object *obj,  				       obj->base.size >> PAGE_SHIFT,  				       obj->pages,  				       agp_type); + +	obj->has_global_gtt_mapping = 1;  }  void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)  { +	intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT, +			      obj->base.size >> PAGE_SHIFT); + +	obj->has_global_gtt_mapping = 0; +} + +void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) +{  	struct drm_device *dev = obj->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private;  	bool interruptible;  	interruptible = do_idling(dev_priv); -	intel_gtt_clear_range(obj->gtt_space->start >> PAGE_SHIFT, -			      obj->base.size >> PAGE_SHIFT); -  	if (obj->sg_list) {  		intel_gtt_unmap_memory(obj->sg_list, obj->num_sg);  		obj->sg_list = NULL; @@ -419,3 +412,23 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj)  	undo_idling(dev_priv, interruptible);  } + +void i915_gem_init_global_gtt(struct drm_device *dev, +			      unsigned long start, +			      unsigned long mappable_end, +			      unsigned long end) +{ +	drm_i915_private_t *dev_priv = dev->dev_private; + +	/* Substract the guard page ... */ +	drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE); + +	dev_priv->mm.gtt_start = start; +	dev_priv->mm.gtt_mappable_end = mappable_end; +	dev_priv->mm.gtt_end = end; +	dev_priv->mm.gtt_total = end - start; +	dev_priv->mm.mappable_gtt_total = min(end, mappable_end) - start; + +	/* ... but ensure that we clear the entire range. */ +	intel_gtt_clear_range(start / PAGE_SIZE, (end-start) / PAGE_SIZE); +} diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index afd4e03e337..febddc2952f 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -26,6 +26,8 @@   *   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/sysrq.h>  #include <linux/slab.h>  #include "drmP.h" @@ -118,6 +120,10 @@ void intel_enable_asle(struct drm_device *dev)  	drm_i915_private_t *dev_priv = dev->dev_private;  	unsigned long irqflags; +	/* FIXME: opregion/asle for VLV */ +	if (IS_VALLEYVIEW(dev)) +		return; +  	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);  	if (HAS_PCH_SPLIT(dev)) @@ -424,6 +430,128 @@ static void gen6_pm_rps_work(struct work_struct *work)  	mutex_unlock(&dev_priv->dev->struct_mutex);  } +static void snb_gt_irq_handler(struct drm_device *dev, +			       struct drm_i915_private *dev_priv, +			       u32 gt_iir) +{ + +	if (gt_iir & (GEN6_RENDER_USER_INTERRUPT | +		      GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT)) +		notify_ring(dev, &dev_priv->ring[RCS]); +	if (gt_iir & GEN6_BSD_USER_INTERRUPT) +		notify_ring(dev, &dev_priv->ring[VCS]); +	if (gt_iir & GEN6_BLITTER_USER_INTERRUPT) +		notify_ring(dev, &dev_priv->ring[BCS]); + +	if (gt_iir & (GT_GEN6_BLT_CS_ERROR_INTERRUPT | +		      GT_GEN6_BSD_CS_ERROR_INTERRUPT | +		      GT_RENDER_CS_ERROR_INTERRUPT)) { +		DRM_ERROR("GT error interrupt 0x%08x\n", gt_iir); +		i915_handle_error(dev, false); +	} +} + +static irqreturn_t valleyview_irq_handler(DRM_IRQ_ARGS) +{ +	struct drm_device *dev = (struct drm_device *) arg; +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	u32 iir, gt_iir, pm_iir; +	irqreturn_t ret = IRQ_NONE; +	unsigned long irqflags; +	int pipe; +	u32 pipe_stats[I915_MAX_PIPES]; +	u32 vblank_status; +	int vblank = 0; +	bool blc_event; + +	atomic_inc(&dev_priv->irq_received); + +	vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS | +		PIPE_VBLANK_INTERRUPT_STATUS; + +	while (true) { +		iir = I915_READ(VLV_IIR); +		gt_iir = I915_READ(GTIIR); +		pm_iir = I915_READ(GEN6_PMIIR); + +		if (gt_iir == 0 && pm_iir == 0 && iir == 0) +			goto out; + +		ret = IRQ_HANDLED; + +		snb_gt_irq_handler(dev, dev_priv, gt_iir); + +		spin_lock_irqsave(&dev_priv->irq_lock, irqflags); +		for_each_pipe(pipe) { +			int reg = PIPESTAT(pipe); +			pipe_stats[pipe] = I915_READ(reg); + +			/* +			 * Clear the PIPE*STAT regs before the IIR +			 */ +			if (pipe_stats[pipe] & 0x8000ffff) { +				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) +					DRM_DEBUG_DRIVER("pipe %c underrun\n", +							 pipe_name(pipe)); +				I915_WRITE(reg, pipe_stats[pipe]); +			} +		} +		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + +		/* Consume port.  Then clear IIR or we'll miss events */ +		if (iir & I915_DISPLAY_PORT_INTERRUPT) { +			u32 hotplug_status = I915_READ(PORT_HOTPLUG_STAT); + +			DRM_DEBUG_DRIVER("hotplug event received, stat 0x%08x\n", +					 hotplug_status); +			if (hotplug_status & dev_priv->hotplug_supported_mask) +				queue_work(dev_priv->wq, +					   &dev_priv->hotplug_work); + +			I915_WRITE(PORT_HOTPLUG_STAT, hotplug_status); +			I915_READ(PORT_HOTPLUG_STAT); +		} + + +		if (iir & I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT) { +			drm_handle_vblank(dev, 0); +			vblank++; +			if (!dev_priv->flip_pending_is_done) { +				intel_finish_page_flip(dev, 0); +			} +		} + +		if (iir & I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT) { +			drm_handle_vblank(dev, 1); +			vblank++; +			if (!dev_priv->flip_pending_is_done) { +				intel_finish_page_flip(dev, 0); +			} +		} + +		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) +			blc_event = true; + +		if (pm_iir & GEN6_PM_DEFERRED_EVENTS) { +			unsigned long flags; +			spin_lock_irqsave(&dev_priv->rps_lock, flags); +			WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); +			dev_priv->pm_iir |= pm_iir; +			I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir); +			POSTING_READ(GEN6_PMIMR); +			spin_unlock_irqrestore(&dev_priv->rps_lock, flags); +			queue_work(dev_priv->wq, &dev_priv->rps_work); +		} + +		I915_WRITE(GTIIR, gt_iir); +		I915_WRITE(GEN6_PMIIR, pm_iir); +		I915_WRITE(VLV_IIR, iir); +	} + +out: +	return ret; +} +  static void pch_irq_handler(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -499,12 +627,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)  				READ_BREADCRUMB(dev_priv);  	} -	if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY)) -		notify_ring(dev, &dev_priv->ring[RCS]); -	if (gt_iir & GT_GEN6_BSD_USER_INTERRUPT) -		notify_ring(dev, &dev_priv->ring[VCS]); -	if (gt_iir & GT_BLT_USER_INTERRUPT) -		notify_ring(dev, &dev_priv->ring[BCS]); +	snb_gt_irq_handler(dev, dev_priv, gt_iir);  	if (de_iir & DE_GSE_IVB)  		intel_opregion_gse_intr(dev); @@ -556,6 +679,16 @@ done:  	return ret;  } +static void ilk_gt_irq_handler(struct drm_device *dev, +			       struct drm_i915_private *dev_priv, +			       u32 gt_iir) +{ +	if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY)) +		notify_ring(dev, &dev_priv->ring[RCS]); +	if (gt_iir & GT_BSD_USER_INTERRUPT) +		notify_ring(dev, &dev_priv->ring[VCS]); +} +  static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)  {  	struct drm_device *dev = (struct drm_device *) arg; @@ -564,13 +697,9 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)  	u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir;  	u32 hotplug_mask;  	struct drm_i915_master_private *master_priv; -	u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT;  	atomic_inc(&dev_priv->irq_received); -	if (IS_GEN6(dev)) -		bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT; -  	/* disable master interrupt before clearing iir  */  	de_ier = I915_READ(DEIER);  	I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); @@ -599,12 +728,10 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)  				READ_BREADCRUMB(dev_priv);  	} -	if (gt_iir & (GT_USER_INTERRUPT | GT_PIPE_NOTIFY)) -		notify_ring(dev, &dev_priv->ring[RCS]); -	if (gt_iir & bsd_usr_interrupt) -		notify_ring(dev, &dev_priv->ring[VCS]); -	if (gt_iir & GT_BLT_USER_INTERRUPT) -		notify_ring(dev, &dev_priv->ring[BCS]); +	if (IS_GEN5(dev)) +		ilk_gt_irq_handler(dev, dev_priv, gt_iir); +	else +		snb_gt_irq_handler(dev, dev_priv, gt_iir);  	if (de_iir & DE_GSE)  		intel_opregion_gse_intr(dev); @@ -727,7 +854,8 @@ i915_error_object_create(struct drm_i915_private *dev_priv,  			goto unwind;  		local_irq_save(flags); -		if (reloc_offset < dev_priv->mm.gtt_mappable_end) { +		if (reloc_offset < dev_priv->mm.gtt_mappable_end && +		    src->has_global_gtt_mapping) {  			void __iomem *s;  			/* Simply ignore tiling or any overlapping fence. @@ -901,7 +1029,6 @@ static void i915_record_ring_state(struct drm_device *dev,  	struct drm_i915_private *dev_priv = dev->dev_private;  	if (INTEL_INFO(dev)->gen >= 6) { -		error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));  		error->fault_reg[ring->id] = I915_READ(RING_FAULT_REG(ring));  		error->semaphore_mboxes[ring->id][0]  			= I915_READ(RING_SYNC_0(ring->mmio_base)); @@ -910,6 +1037,7 @@ static void i915_record_ring_state(struct drm_device *dev,  	}  	if (INTEL_INFO(dev)->gen >= 4) { +		error->faddr[ring->id] = I915_READ(RING_DMA_FADD(ring->mmio_base));  		error->ipeir[ring->id] = I915_READ(RING_IPEIR(ring->mmio_base));  		error->ipehr[ring->id] = I915_READ(RING_IPEHR(ring->mmio_base));  		error->instdone[ring->id] = I915_READ(RING_INSTDONE(ring->mmio_base)); @@ -919,6 +1047,7 @@ static void i915_record_ring_state(struct drm_device *dev,  			error->bbaddr = I915_READ64(BB_ADDR);  		}  	} else { +		error->faddr[ring->id] = I915_READ(DMA_FADD_I8XX);  		error->ipeir[ring->id] = I915_READ(IPEIR);  		error->ipehr[ring->id] = I915_READ(IPEHR);  		error->instdone[ring->id] = I915_READ(INSTDONE); @@ -1103,33 +1232,26 @@ static void i915_report_and_clear_eir(struct drm_device *dev)  	if (!eir)  		return; -	printk(KERN_ERR "render error detected, EIR: 0x%08x\n", -	       eir); +	pr_err("render error detected, EIR: 0x%08x\n", eir);  	if (IS_G4X(dev)) {  		if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {  			u32 ipeir = I915_READ(IPEIR_I965); -			printk(KERN_ERR "  IPEIR: 0x%08x\n", -			       I915_READ(IPEIR_I965)); -			printk(KERN_ERR "  IPEHR: 0x%08x\n", -			       I915_READ(IPEHR_I965)); -			printk(KERN_ERR "  INSTDONE: 0x%08x\n", +			pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR_I965)); +			pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR_I965)); +			pr_err("  INSTDONE: 0x%08x\n",  			       I915_READ(INSTDONE_I965)); -			printk(KERN_ERR "  INSTPS: 0x%08x\n", -			       I915_READ(INSTPS)); -			printk(KERN_ERR "  INSTDONE1: 0x%08x\n", -			       I915_READ(INSTDONE1)); -			printk(KERN_ERR "  ACTHD: 0x%08x\n", -			       I915_READ(ACTHD_I965)); +			pr_err("  INSTPS: 0x%08x\n", I915_READ(INSTPS)); +			pr_err("  INSTDONE1: 0x%08x\n", I915_READ(INSTDONE1)); +			pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));  			I915_WRITE(IPEIR_I965, ipeir);  			POSTING_READ(IPEIR_I965);  		}  		if (eir & GM45_ERROR_PAGE_TABLE) {  			u32 pgtbl_err = I915_READ(PGTBL_ER); -			printk(KERN_ERR "page table error\n"); -			printk(KERN_ERR "  PGTBL_ER: 0x%08x\n", -			       pgtbl_err); +			pr_err("page table error\n"); +			pr_err("  PGTBL_ER: 0x%08x\n", pgtbl_err);  			I915_WRITE(PGTBL_ER, pgtbl_err);  			POSTING_READ(PGTBL_ER);  		} @@ -1138,53 +1260,42 @@ static void i915_report_and_clear_eir(struct drm_device *dev)  	if (!IS_GEN2(dev)) {  		if (eir & I915_ERROR_PAGE_TABLE) {  			u32 pgtbl_err = I915_READ(PGTBL_ER); -			printk(KERN_ERR "page table error\n"); -			printk(KERN_ERR "  PGTBL_ER: 0x%08x\n", -			       pgtbl_err); +			pr_err("page table error\n"); +			pr_err("  PGTBL_ER: 0x%08x\n", pgtbl_err);  			I915_WRITE(PGTBL_ER, pgtbl_err);  			POSTING_READ(PGTBL_ER);  		}  	}  	if (eir & I915_ERROR_MEMORY_REFRESH) { -		printk(KERN_ERR "memory refresh error:\n"); +		pr_err("memory refresh error:\n");  		for_each_pipe(pipe) -			printk(KERN_ERR "pipe %c stat: 0x%08x\n", +			pr_err("pipe %c stat: 0x%08x\n",  			       pipe_name(pipe), I915_READ(PIPESTAT(pipe)));  		/* pipestat has already been acked */  	}  	if (eir & I915_ERROR_INSTRUCTION) { -		printk(KERN_ERR "instruction error\n"); -		printk(KERN_ERR "  INSTPM: 0x%08x\n", -		       I915_READ(INSTPM)); +		pr_err("instruction error\n"); +		pr_err("  INSTPM: 0x%08x\n", I915_READ(INSTPM));  		if (INTEL_INFO(dev)->gen < 4) {  			u32 ipeir = I915_READ(IPEIR); -			printk(KERN_ERR "  IPEIR: 0x%08x\n", -			       I915_READ(IPEIR)); -			printk(KERN_ERR "  IPEHR: 0x%08x\n", -			       I915_READ(IPEHR)); -			printk(KERN_ERR "  INSTDONE: 0x%08x\n", -			       I915_READ(INSTDONE)); -			printk(KERN_ERR "  ACTHD: 0x%08x\n", -			       I915_READ(ACTHD)); +			pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR)); +			pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR)); +			pr_err("  INSTDONE: 0x%08x\n", I915_READ(INSTDONE)); +			pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD));  			I915_WRITE(IPEIR, ipeir);  			POSTING_READ(IPEIR);  		} else {  			u32 ipeir = I915_READ(IPEIR_I965); -			printk(KERN_ERR "  IPEIR: 0x%08x\n", -			       I915_READ(IPEIR_I965)); -			printk(KERN_ERR "  IPEHR: 0x%08x\n", -			       I915_READ(IPEHR_I965)); -			printk(KERN_ERR "  INSTDONE: 0x%08x\n", +			pr_err("  IPEIR: 0x%08x\n", I915_READ(IPEIR_I965)); +			pr_err("  IPEHR: 0x%08x\n", I915_READ(IPEHR_I965)); +			pr_err("  INSTDONE: 0x%08x\n",  			       I915_READ(INSTDONE_I965)); -			printk(KERN_ERR "  INSTPS: 0x%08x\n", -			       I915_READ(INSTPS)); -			printk(KERN_ERR "  INSTDONE1: 0x%08x\n", -			       I915_READ(INSTDONE1)); -			printk(KERN_ERR "  ACTHD: 0x%08x\n", -			       I915_READ(ACTHD_I965)); +			pr_err("  INSTPS: 0x%08x\n", I915_READ(INSTPS)); +			pr_err("  INSTDONE1: 0x%08x\n", I915_READ(INSTDONE1)); +			pr_err("  ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));  			I915_WRITE(IPEIR_I965, ipeir);  			POSTING_READ(IPEIR_I965);  		} @@ -1582,6 +1693,32 @@ static int ivybridge_enable_vblank(struct drm_device *dev, int pipe)  	return 0;  } +static int valleyview_enable_vblank(struct drm_device *dev, int pipe) +{ +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	unsigned long irqflags; +	u32 dpfl, imr; + +	if (!i915_pipe_enabled(dev, pipe)) +		return -EINVAL; + +	spin_lock_irqsave(&dev_priv->irq_lock, irqflags); +	dpfl = I915_READ(VLV_DPFLIPSTAT); +	imr = I915_READ(VLV_IMR); +	if (pipe == 0) { +		dpfl |= PIPEA_VBLANK_INT_EN; +		imr &= ~I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; +	} else { +		dpfl |= PIPEA_VBLANK_INT_EN; +		imr &= ~I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; +	} +	I915_WRITE(VLV_DPFLIPSTAT, dpfl); +	I915_WRITE(VLV_IMR, imr); +	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); + +	return 0; +} +  /* Called from drm generic code, passed 'crtc' which   * we use as a pipe index   */ @@ -1623,6 +1760,28 @@ static void ivybridge_disable_vblank(struct drm_device *dev, int pipe)  	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);  } +static void valleyview_disable_vblank(struct drm_device *dev, int pipe) +{ +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	unsigned long irqflags; +	u32 dpfl, imr; + +	spin_lock_irqsave(&dev_priv->irq_lock, irqflags); +	dpfl = I915_READ(VLV_DPFLIPSTAT); +	imr = I915_READ(VLV_IMR); +	if (pipe == 0) { +		dpfl &= ~PIPEA_VBLANK_INT_EN; +		imr |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT; +	} else { +		dpfl &= ~PIPEB_VBLANK_INT_EN; +		imr |= I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; +	} +	I915_WRITE(VLV_IMR, imr); +	I915_WRITE(VLV_DPFLIPSTAT, dpfl); +	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); +} + +  /* Set the vblank monitor pipe   */  int i915_vblank_pipe_set(struct drm_device *dev, void *data, @@ -1832,6 +1991,41 @@ static void ironlake_irq_preinstall(struct drm_device *dev)  	POSTING_READ(SDEIER);  } +static void valleyview_irq_preinstall(struct drm_device *dev) +{ +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	int pipe; + +	atomic_set(&dev_priv->irq_received, 0); + +	INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func); +	INIT_WORK(&dev_priv->error_work, i915_error_work_func); + +	/* VLV magic */ +	I915_WRITE(VLV_IMR, 0); +	I915_WRITE(RING_IMR(RENDER_RING_BASE), 0); +	I915_WRITE(RING_IMR(GEN6_BSD_RING_BASE), 0); +	I915_WRITE(RING_IMR(BLT_RING_BASE), 0); + +	/* and GT */ +	I915_WRITE(GTIIR, I915_READ(GTIIR)); +	I915_WRITE(GTIIR, I915_READ(GTIIR)); +	I915_WRITE(GTIMR, 0xffffffff); +	I915_WRITE(GTIER, 0x0); +	POSTING_READ(GTIER); + +	I915_WRITE(DPINVGTT, 0xff); + +	I915_WRITE(PORT_HOTPLUG_EN, 0); +	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); +	for_each_pipe(pipe) +		I915_WRITE(PIPESTAT(pipe), 0xffff); +	I915_WRITE(VLV_IIR, 0xffffffff); +	I915_WRITE(VLV_IMR, 0xffffffff); +	I915_WRITE(VLV_IER, 0x0); +	POSTING_READ(VLV_IER); +} +  /*   * Enable digital hotplug on the PCH, and configure the DP short pulse   * duration to 2ms (which is the minimum in the Display Port spec) @@ -1884,8 +2078,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)  	if (IS_GEN6(dev))  		render_irqs =  			GT_USER_INTERRUPT | -			GT_GEN6_BSD_USER_INTERRUPT | -			GT_BLT_USER_INTERRUPT; +			GEN6_BSD_USER_INTERRUPT | +			GEN6_BLITTER_USER_INTERRUPT;  	else  		render_irqs =  			GT_USER_INTERRUPT | @@ -1957,8 +2151,8 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)  	I915_WRITE(GTIIR, I915_READ(GTIIR));  	I915_WRITE(GTIMR, dev_priv->gt_irq_mask); -	render_irqs = GT_USER_INTERRUPT | GT_GEN6_BSD_USER_INTERRUPT | -		GT_BLT_USER_INTERRUPT; +	render_irqs = GT_USER_INTERRUPT | GEN6_BSD_USER_INTERRUPT | +		GEN6_BLITTER_USER_INTERRUPT;  	I915_WRITE(GTIER, render_irqs);  	POSTING_READ(GTIER); @@ -1978,6 +2172,96 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)  	return 0;  } +static int valleyview_irq_postinstall(struct drm_device *dev) +{ +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	u32 render_irqs; +	u32 enable_mask; +	u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); +	u16 msid; + +	enable_mask = I915_DISPLAY_PORT_INTERRUPT; +	enable_mask |= I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT | +		I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT; + +	dev_priv->irq_mask = ~enable_mask; + + +	DRM_INIT_WAITQUEUE(&dev_priv->ring[RCS].irq_queue); +	DRM_INIT_WAITQUEUE(&dev_priv->ring[VCS].irq_queue); +	DRM_INIT_WAITQUEUE(&dev_priv->ring[BCS].irq_queue); + +	dev_priv->pipestat[0] = 0; +	dev_priv->pipestat[1] = 0; + +	dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B; + +	/* Hack for broken MSIs on VLV */ +	pci_write_config_dword(dev_priv->dev->pdev, 0x94, 0xfee00000); +	pci_read_config_word(dev->pdev, 0x98, &msid); +	msid &= 0xff; /* mask out delivery bits */ +	msid |= (1<<14); +	pci_write_config_word(dev_priv->dev->pdev, 0x98, msid); + +	I915_WRITE(VLV_IMR, dev_priv->irq_mask); +	I915_WRITE(VLV_IER, enable_mask); +	I915_WRITE(VLV_IIR, 0xffffffff); +	I915_WRITE(PIPESTAT(0), 0xffff); +	I915_WRITE(PIPESTAT(1), 0xffff); +	POSTING_READ(VLV_IER); + +	I915_WRITE(VLV_IIR, 0xffffffff); +	I915_WRITE(VLV_IIR, 0xffffffff); + +	render_irqs = GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT | +		GT_GEN6_BLT_CS_ERROR_INTERRUPT | +		GT_GEN6_BLT_USER_INTERRUPT | +		GT_GEN6_BSD_USER_INTERRUPT | +		GT_GEN6_BSD_CS_ERROR_INTERRUPT | +		GT_GEN7_L3_PARITY_ERROR_INTERRUPT | +		GT_PIPE_NOTIFY | +		GT_RENDER_CS_ERROR_INTERRUPT | +		GT_SYNC_STATUS | +		GT_USER_INTERRUPT; + +	dev_priv->gt_irq_mask = ~render_irqs; + +	I915_WRITE(GTIIR, I915_READ(GTIIR)); +	I915_WRITE(GTIIR, I915_READ(GTIIR)); +	I915_WRITE(GTIMR, 0); +	I915_WRITE(GTIER, render_irqs); +	POSTING_READ(GTIER); + +	/* ack & enable invalid PTE error interrupts */ +#if 0 /* FIXME: add support to irq handler for checking these bits */ +	I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK); +	I915_WRITE(DPINVGTT, DPINVGTT_EN_MASK); +#endif + +	I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); +#if 0 /* FIXME: check register definitions; some have moved */ +	/* Note HDMI and DP share bits */ +	if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) +		hotplug_en |= HDMIB_HOTPLUG_INT_EN; +	if (dev_priv->hotplug_supported_mask & HDMIC_HOTPLUG_INT_STATUS) +		hotplug_en |= HDMIC_HOTPLUG_INT_EN; +	if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) +		hotplug_en |= HDMID_HOTPLUG_INT_EN; +	if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) +		hotplug_en |= SDVOC_HOTPLUG_INT_EN; +	if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) +		hotplug_en |= SDVOB_HOTPLUG_INT_EN; +	if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { +		hotplug_en |= CRT_HOTPLUG_INT_EN; +		hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50; +	} +#endif + +	I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); + +	return 0; +} +  static void i915_driver_irq_preinstall(struct drm_device * dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -2081,6 +2365,30 @@ static int i915_driver_irq_postinstall(struct drm_device *dev)  	return 0;  } +static void valleyview_irq_uninstall(struct drm_device *dev) +{ +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	int pipe; + +	if (!dev_priv) +		return; + +	dev_priv->vblank_pipe = 0; + +	for_each_pipe(pipe) +		I915_WRITE(PIPESTAT(pipe), 0xffff); + +	I915_WRITE(HWSTAM, 0xffffffff); +	I915_WRITE(PORT_HOTPLUG_EN, 0); +	I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); +	for_each_pipe(pipe) +		I915_WRITE(PIPESTAT(pipe), 0xffff); +	I915_WRITE(VLV_IIR, 0xffffffff); +	I915_WRITE(VLV_IMR, 0xffffffff); +	I915_WRITE(VLV_IER, 0x0); +	POSTING_READ(VLV_IER); +} +  static void ironlake_irq_uninstall(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -2136,7 +2444,8 @@ void intel_irq_init(struct drm_device *dev)  {  	dev->driver->get_vblank_counter = i915_get_vblank_counter;  	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ -	if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { +	if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev) || +	    IS_VALLEYVIEW(dev)) {  		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */  		dev->driver->get_vblank_counter = gm45_get_vblank_counter;  	} @@ -2147,7 +2456,14 @@ void intel_irq_init(struct drm_device *dev)  		dev->driver->get_vblank_timestamp = NULL;  	dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; -	if (IS_IVYBRIDGE(dev)) { +	if (IS_VALLEYVIEW(dev)) { +		dev->driver->irq_handler = valleyview_irq_handler; +		dev->driver->irq_preinstall = valleyview_irq_preinstall; +		dev->driver->irq_postinstall = valleyview_irq_postinstall; +		dev->driver->irq_uninstall = valleyview_irq_uninstall; +		dev->driver->enable_vblank = valleyview_enable_vblank; +		dev->driver->disable_vblank = valleyview_disable_vblank; +	} else if (IS_IVYBRIDGE(dev)) {  		/* Share pre & uninstall handlers with ILK/SNB */  		dev->driver->irq_handler = ivybridge_irq_handler;  		dev->driver->irq_preinstall = ironlake_irq_preinstall; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2abf4eb9403..6924f44a88d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -27,6 +27,8 @@  #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) +#define _PORT(port, a, b) ((a) + (port)*((b)-(a))) +  /*   * The Bridge device's PCI config space has information about the   * fb aperture size and the amount of pre-reserved memory. @@ -301,6 +303,61 @@  #define  DEBUG_RESET_RENDER		(1<<8)  #define  DEBUG_RESET_DISPLAY		(1<<9) +/* + * DPIO - a special bus for various display related registers to hide behind: + *  0x800c: m1, m2, n, p1, p2, k dividers + *  0x8014: REF and SFR select + *  0x8014: N divider, VCO select + *  0x801c/3c: core clock bits + *  0x8048/68: low pass filter coefficients + *  0x8100: fast clock controls + */ +#define DPIO_PKT			0x2100 +#define  DPIO_RID			(0<<24) +#define  DPIO_OP_WRITE			(1<<16) +#define  DPIO_OP_READ			(0<<16) +#define  DPIO_PORTID			(0x12<<8) +#define  DPIO_BYTE			(0xf<<4) +#define  DPIO_BUSY			(1<<0) /* status only */ +#define DPIO_DATA			0x2104 +#define DPIO_REG			0x2108 +#define DPIO_CTL			0x2110 +#define  DPIO_MODSEL1			(1<<3) /* if ref clk b == 27 */ +#define  DPIO_MODSEL0			(1<<2) /* if ref clk a == 27 */ +#define  DPIO_SFR_BYPASS		(1<<1) +#define  DPIO_RESET			(1<<0) + +#define _DPIO_DIV_A			0x800c +#define   DPIO_POST_DIV_SHIFT		(28) /* 3 bits */ +#define   DPIO_K_SHIFT			(24) /* 4 bits */ +#define   DPIO_P1_SHIFT			(21) /* 3 bits */ +#define   DPIO_P2_SHIFT			(16) /* 5 bits */ +#define   DPIO_N_SHIFT			(12) /* 4 bits */ +#define   DPIO_ENABLE_CALIBRATION	(1<<11) +#define   DPIO_M1DIV_SHIFT		(8) /* 3 bits */ +#define   DPIO_M2DIV_MASK		0xff +#define _DPIO_DIV_B			0x802c +#define DPIO_DIV(pipe) _PIPE(pipe, _DPIO_DIV_A, _DPIO_DIV_B) + +#define _DPIO_REFSFR_A			0x8014 +#define   DPIO_REFSEL_OVERRIDE		27 +#define   DPIO_PLL_MODESEL_SHIFT	24 /* 3 bits */ +#define   DPIO_BIAS_CURRENT_CTL_SHIFT	21 /* 3 bits, always 0x7 */ +#define   DPIO_PLL_REFCLK_SEL_SHIFT	16 /* 2 bits */ +#define   DPIO_DRIVER_CTL_SHIFT		12 /* always set to 0x8 */ +#define   DPIO_CLK_BIAS_CTL_SHIFT	8 /* always set to 0x5 */ +#define _DPIO_REFSFR_B			0x8034 +#define DPIO_REFSFR(pipe) _PIPE(pipe, _DPIO_REFSFR_A, _DPIO_REFSFR_B) + +#define _DPIO_CORE_CLK_A		0x801c +#define _DPIO_CORE_CLK_B		0x803c +#define DPIO_CORE_CLK(pipe) _PIPE(pipe, _DPIO_CORE_CLK_A, _DPIO_CORE_CLK_B) + +#define _DPIO_LFP_COEFF_A		0x8048 +#define _DPIO_LFP_COEFF_B		0x8068 +#define DPIO_LFP_COEFF(pipe) _PIPE(pipe, _DPIO_LFP_COEFF_A, _DPIO_LFP_COEFF_B) + +#define DPIO_FASTCLK_DISABLE		0x8100  /*   * Fence registers @@ -417,6 +474,7 @@  #define INSTDONE	0x02090  #define NOPID		0x02094  #define HWSTAM		0x02098 +#define DMA_FADD_I8XX	0x020d0  #define ERROR_GEN6	0x040a0 @@ -455,6 +513,11 @@  #define IIR		0x020a4  #define IMR		0x020a8  #define ISR		0x020ac +#define VLV_IIR_RW	0x182084 +#define VLV_IER		0x1820a0 +#define VLV_IIR		0x1820a4 +#define VLV_IMR		0x1820a8 +#define VLV_ISR		0x1820ac  #define   I915_PIPE_CONTROL_NOTIFY_INTERRUPT		(1<<18)  #define   I915_DISPLAY_PORT_INTERRUPT			(1<<17)  #define   I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT	(1<<15) @@ -578,7 +641,12 @@  #define   ECO_GATING_CX_ONLY	(1<<3)  #define   ECO_FLIP_DONE		(1<<0) -/* GEN6 interrupt control */ +#define CACHE_MODE_1		0x7004 /* IVB+ */ +#define   PIXEL_SUBSPAN_COLLECT_OPT_DISABLE (1<<6) + +/* GEN6 interrupt control + * Note that the per-ring interrupt bits do alias with the global interrupt bits + * in GTIMR. */  #define GEN6_RENDER_HWSTAM	0x2098  #define GEN6_RENDER_IMR		0x20a8  #define   GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT		(1 << 8) @@ -742,9 +810,9 @@  #define   GMBUS_PORT_PANEL	3  #define   GMBUS_PORT_DPC	4 /* HDMIC */  #define   GMBUS_PORT_DPB	5 /* SDVO, HDMIB */ -				  /* 6 reserved */ -#define   GMBUS_PORT_DPD	7 /* HDMID */ -#define   GMBUS_NUM_PORTS       8 +#define   GMBUS_PORT_DPD	6 /* HDMID */ +#define   GMBUS_PORT_RESERVED	7 /* 7 reserved */ +#define   GMBUS_NUM_PORTS	(GMBUS_PORT_DPD - GMBUS_PORT_SSC + 1)  #define GMBUS1			0x5104 /* command/status */  #define   GMBUS_SW_CLR_INT	(1<<31)  #define   GMBUS_SW_RDY		(1<<30) @@ -796,7 +864,9 @@  #define DPLL(pipe) _PIPE(pipe, _DPLL_A, _DPLL_B)  #define   DPLL_VCO_ENABLE		(1 << 31)  #define   DPLL_DVO_HIGH_SPEED		(1 << 30) +#define   DPLL_EXT_BUFFER_ENABLE_VLV	(1 << 30)  #define   DPLL_SYNCLOCK_ENABLE		(1 << 29) +#define   DPLL_REFA_CLK_ENABLE_VLV	(1 << 29)  #define   DPLL_VGA_MODE_DIS		(1 << 28)  #define   DPLLB_MODE_DAC_SERIAL		(1 << 26) /* i915 */  #define   DPLLB_MODE_LVDS		(2 << 26) /* i915 */ @@ -808,6 +878,7 @@  #define   DPLL_P2_CLOCK_DIV_MASK	0x03000000 /* i915 */  #define   DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000 /* i915 */  #define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW	0x00ff8000 /* Pineview */ +#define   DPLL_INTEGRATED_CLOCK_VLV	(1<<13)  #define SRX_INDEX		0x3c4  #define SRX_DATA		0x3c5 @@ -903,6 +974,7 @@  #define   DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0  #define _DPLL_B_MD 0x06020 /* 965+ only */  #define DPLL_MD(pipe) _PIPE(pipe, _DPLL_A_MD, _DPLL_B_MD) +  #define _FPA0	0x06040  #define _FPA1	0x06044  #define _FPB0	0x06048 @@ -1043,6 +1115,9 @@  #define RAMCLK_GATE_D		0x6210		/* CRL only */  #define DEUC			0x6214          /* CRL only */ +#define FW_BLC_SELF_VLV		0x6500 +#define  FW_CSPWRDWNEN		(1<<15) +  /*   * Palette regs   */ @@ -2421,23 +2496,30 @@  #define   PIPECONF_DITHER_TYPE_TEMP (3<<2)  #define _PIPEASTAT		0x70024  #define   PIPE_FIFO_UNDERRUN_STATUS		(1UL<<31) +#define   SPRITE1_FLIPDONE_INT_EN_VLV		(1UL<<30)  #define   PIPE_CRC_ERROR_ENABLE			(1UL<<29)  #define   PIPE_CRC_DONE_ENABLE			(1UL<<28)  #define   PIPE_GMBUS_EVENT_ENABLE		(1UL<<27) +#define   PLANE_FLIP_DONE_INT_EN_VLV		(1UL<<26)  #define   PIPE_HOTPLUG_INTERRUPT_ENABLE		(1UL<<26)  #define   PIPE_VSYNC_INTERRUPT_ENABLE		(1UL<<25)  #define   PIPE_DISPLAY_LINE_COMPARE_ENABLE	(1UL<<24)  #define   PIPE_DPST_EVENT_ENABLE		(1UL<<23) +#define   SPRITE0_FLIP_DONE_INT_EN_VLV		(1UL<<26)  #define   PIPE_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)  #define   PIPE_ODD_FIELD_INTERRUPT_ENABLE	(1UL<<21)  #define   PIPE_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)  #define   PIPE_HOTPLUG_TV_INTERRUPT_ENABLE	(1UL<<18) /* pre-965 */  #define   PIPE_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18) /* 965 or later */  #define   PIPE_VBLANK_INTERRUPT_ENABLE		(1UL<<17) +#define   PIPEA_HBLANK_INT_EN_VLV		(1UL<<16)  #define   PIPE_OVERLAY_UPDATED_ENABLE		(1UL<<16) +#define   SPRITE1_FLIPDONE_INT_STATUS_VLV	(1UL<<15) +#define   SPRITE0_FLIPDONE_INT_STATUS_VLV	(1UL<<15)  #define   PIPE_CRC_ERROR_INTERRUPT_STATUS	(1UL<<13)  #define   PIPE_CRC_DONE_INTERRUPT_STATUS	(1UL<<12)  #define   PIPE_GMBUS_INTERRUPT_STATUS		(1UL<<11) +#define   PLANE_FLIPDONE_INT_STATUS_VLV		(1UL<<10)  #define   PIPE_HOTPLUG_INTERRUPT_STATUS		(1UL<<10)  #define   PIPE_VSYNC_INTERRUPT_STATUS		(1UL<<9)  #define   PIPE_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8) @@ -2462,6 +2544,40 @@  #define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL)  #define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT) +#define VLV_DPFLIPSTAT				0x70028 +#define   PIPEB_LINE_COMPARE_STATUS		(1<<29) +#define   PIPEB_HLINE_INT_EN			(1<<28) +#define   PIPEB_VBLANK_INT_EN			(1<<27) +#define   SPRITED_FLIPDONE_INT_EN		(1<<26) +#define   SPRITEC_FLIPDONE_INT_EN		(1<<25) +#define   PLANEB_FLIPDONE_INT_EN		(1<<24) +#define   PIPEA_LINE_COMPARE_STATUS		(1<<21) +#define   PIPEA_HLINE_INT_EN			(1<<20) +#define   PIPEA_VBLANK_INT_EN			(1<<19) +#define   SPRITEB_FLIPDONE_INT_EN		(1<<18) +#define   SPRITEA_FLIPDONE_INT_EN		(1<<17) +#define   PLANEA_FLIPDONE_INT_EN		(1<<16) + +#define DPINVGTT				0x7002c /* VLV only */ +#define   CURSORB_INVALID_GTT_INT_EN		(1<<23) +#define   CURSORA_INVALID_GTT_INT_EN		(1<<22) +#define   SPRITED_INVALID_GTT_INT_EN		(1<<21) +#define   SPRITEC_INVALID_GTT_INT_EN		(1<<20) +#define   PLANEB_INVALID_GTT_INT_EN		(1<<19) +#define   SPRITEB_INVALID_GTT_INT_EN		(1<<18) +#define   SPRITEA_INVALID_GTT_INT_EN		(1<<17) +#define   PLANEA_INVALID_GTT_INT_EN		(1<<16) +#define   DPINVGTT_EN_MASK			0xff0000 +#define   CURSORB_INVALID_GTT_STATUS		(1<<7) +#define   CURSORA_INVALID_GTT_STATUS		(1<<6) +#define   SPRITED_INVALID_GTT_STATUS		(1<<5) +#define   SPRITEC_INVALID_GTT_STATUS		(1<<4) +#define   PLANEB_INVALID_GTT_STATUS		(1<<3) +#define   SPRITEB_INVALID_GTT_STATUS		(1<<2) +#define   SPRITEA_INVALID_GTT_STATUS		(1<<1) +#define   PLANEA_INVALID_GTT_STATUS		(1<<0) +#define   DPINVGTT_STATUS_MASK			0xff +  #define DSPARB			0x70030  #define   DSPARB_CSTART_MASK	(0x7f << 7)  #define   DSPARB_CSTART_SHIFT	7 @@ -2491,11 +2607,28 @@  #define   DSPFW_HPLL_CURSOR_MASK	(0x3f<<16)  #define   DSPFW_HPLL_SR_MASK		(0x1ff) +/* drain latency register values*/ +#define DRAIN_LATENCY_PRECISION_32	32 +#define DRAIN_LATENCY_PRECISION_16	16 +#define VLV_DDL1			0x70050 +#define DDL_CURSORA_PRECISION_32	(1<<31) +#define DDL_CURSORA_PRECISION_16	(0<<31) +#define DDL_CURSORA_SHIFT		24 +#define DDL_PLANEA_PRECISION_32		(1<<7) +#define DDL_PLANEA_PRECISION_16		(0<<7) +#define VLV_DDL2			0x70054 +#define DDL_CURSORB_PRECISION_32	(1<<31) +#define DDL_CURSORB_PRECISION_16	(0<<31) +#define DDL_CURSORB_SHIFT		24 +#define DDL_PLANEB_PRECISION_32		(1<<7) +#define DDL_PLANEB_PRECISION_16		(0<<7) +  /* FIFO watermark sizes etc */  #define G4X_FIFO_LINE_SIZE	64  #define I915_FIFO_LINE_SIZE	64  #define I830_FIFO_LINE_SIZE	32 +#define VALLEYVIEW_FIFO_SIZE	255  #define G4X_FIFO_SIZE		127  #define I965_FIFO_SIZE		512  #define I945_FIFO_SIZE		127 @@ -2503,6 +2636,7 @@  #define I855GM_FIFO_SIZE	127 /* In cachelines */  #define I830_FIFO_SIZE		95 +#define VALLEYVIEW_MAX_WM	0xff  #define G4X_MAX_WM		0x3f  #define I915_MAX_WM		0x3f @@ -2517,6 +2651,7 @@  #define PINEVIEW_CURSOR_DFT_WM	0  #define PINEVIEW_CURSOR_GUARD_WM	5 +#define VALLEYVIEW_CURSOR_MAX_WM 64  #define I965_CURSOR_FIFO	64  #define I965_CURSOR_MAX_WM	32  #define I965_CURSOR_DFT_WM	8 @@ -3064,18 +3199,28 @@  #define DE_PIPEB_VBLANK_IVB		(1<<5)  #define DE_PIPEA_VBLANK_IVB		(1<<0) +#define VLV_MASTER_IER			0x4400c /* Gunit master IER */ +#define   MASTER_INTERRUPT_ENABLE	(1<<31) +  #define DEISR   0x44000  #define DEIMR   0x44004  #define DEIIR   0x44008  #define DEIER   0x4400c -/* GT interrupt */ -#define GT_PIPE_NOTIFY		(1 << 4) -#define GT_SYNC_STATUS          (1 << 2) -#define GT_USER_INTERRUPT       (1 << 0) -#define GT_BSD_USER_INTERRUPT   (1 << 5) -#define GT_GEN6_BSD_USER_INTERRUPT	(1 << 12) -#define GT_BLT_USER_INTERRUPT	(1 << 22) +/* GT interrupt. + * Note that for gen6+ the ring-specific interrupt bits do alias with the + * corresponding bits in the per-ring interrupt control registers. */ +#define GT_GEN6_BLT_FLUSHDW_NOTIFY_INTERRUPT	(1 << 26) +#define GT_GEN6_BLT_CS_ERROR_INTERRUPT		(1 << 25) +#define GT_GEN6_BLT_USER_INTERRUPT		(1 << 22) +#define GT_GEN6_BSD_CS_ERROR_INTERRUPT		(1 << 15) +#define GT_GEN6_BSD_USER_INTERRUPT		(1 << 12) +#define GT_BSD_USER_INTERRUPT			(1 << 5) /* ilk only */ +#define GT_GEN7_L3_PARITY_ERROR_INTERRUPT	(1 << 5) +#define GT_PIPE_NOTIFY				(1 << 4) +#define GT_RENDER_CS_ERROR_INTERRUPT		(1 << 3) +#define GT_SYNC_STATUS				(1 << 2) +#define GT_USER_INTERRUPT			(1 << 0)  #define GTISR   0x44010  #define GTIMR   0x44014 @@ -3328,6 +3473,21 @@  #define TVIDEO_DIP_DATA(pipe) _PIPE(pipe, _VIDEO_DIP_DATA_A, _VIDEO_DIP_DATA_B)  #define TVIDEO_DIP_GCP(pipe) _PIPE(pipe, _VIDEO_DIP_GCP_A, _VIDEO_DIP_GCP_B) +#define VLV_VIDEO_DIP_CTL_A		0x60220 +#define VLV_VIDEO_DIP_DATA_A		0x60208 +#define VLV_VIDEO_DIP_GDCP_PAYLOAD_A	0x60210 + +#define VLV_VIDEO_DIP_CTL_B		0x61170 +#define VLV_VIDEO_DIP_DATA_B		0x61174 +#define VLV_VIDEO_DIP_GDCP_PAYLOAD_B	0x61178 + +#define VLV_TVIDEO_DIP_CTL(pipe) \ +	 _PIPE(pipe, VLV_VIDEO_DIP_CTL_A, VLV_VIDEO_DIP_CTL_B) +#define VLV_TVIDEO_DIP_DATA(pipe) \ +	 _PIPE(pipe, VLV_VIDEO_DIP_DATA_A, VLV_VIDEO_DIP_DATA_B) +#define VLV_TVIDEO_DIP_GCP(pipe) \ +	_PIPE(pipe, VLV_VIDEO_DIP_GDCP_PAYLOAD_A, VLV_VIDEO_DIP_GDCP_PAYLOAD_B) +  #define _TRANS_HTOTAL_B          0xe1000  #define _TRANS_HBLANK_B          0xe1004  #define _TRANS_HSYNC_B           0xe1008 @@ -3548,6 +3708,7 @@  #define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)  /* or SDVOB */ +#define VLV_HDMIB 0x61140  #define HDMIB   0xe1140  #define  PORT_ENABLE    (1 << 31)  #define  TRANSCODER(pipe)       ((pipe) << 30) @@ -3713,6 +3874,8 @@  #define  EDP_LINK_TRAIN_VOL_EMP_MASK_IVB	(0x3f<<22)  #define  FORCEWAKE				0xA18C +#define  FORCEWAKE_VLV				0x1300b0 +#define  FORCEWAKE_ACK_VLV			0x1300b4  #define  FORCEWAKE_ACK				0x130090  #define  FORCEWAKE_MT				0xa188 /* multi-threaded */  #define  FORCEWAKE_MT_ACK			0x130040 @@ -3866,4 +4029,193 @@  #define   AUD_CONFIG_PIXEL_CLOCK_HDMI		(0xf << 16)  #define   AUD_CONFIG_DISABLE_NCTS		(1 << 3) +/* HSW Power Wells */ +#define HSW_PWR_WELL_CTL1		0x45400		/* BIOS */ +#define HSW_PWR_WELL_CTL2		0x45404		/* Driver */ +#define HSW_PWR_WELL_CTL3		0x45408		/* KVMR */ +#define HSW_PWR_WELL_CTL4		0x4540C		/* Debug */ +#define   HSW_PWR_WELL_ENABLE				(1<<31) +#define   HSW_PWR_WELL_STATE				(1<<30) +#define HSW_PWR_WELL_CTL5		0x45410 +#define   HSW_PWR_WELL_ENABLE_SINGLE_STEP	(1<<31) +#define   HSW_PWR_WELL_PWR_GATE_OVERRIDE	(1<<20) +#define   HSW_PWR_WELL_FORCE_ON				(1<<19) +#define HSW_PWR_WELL_CTL6		0x45414 + +/* Per-pipe DDI Function Control */ +#define PIPE_DDI_FUNC_CTL_A			0x60400 +#define PIPE_DDI_FUNC_CTL_B			0x61400 +#define PIPE_DDI_FUNC_CTL_C			0x62400 +#define PIPE_DDI_FUNC_CTL_EDP		0x6F400 +#define DDI_FUNC_CTL(pipe) _PIPE(pipe, \ +					PIPE_DDI_FUNC_CTL_A, \ +					PIPE_DDI_FUNC_CTL_B) +#define  PIPE_DDI_FUNC_ENABLE		(1<<31) +/* Those bits are ignored by pipe EDP since it can only connect to DDI A */ +#define  PIPE_DDI_PORT_MASK				(0xf<<28) +#define  PIPE_DDI_SELECT_PORT(x)		((x)<<28) +#define  PIPE_DDI_MODE_SELECT_HDMI		(0<<24) +#define  PIPE_DDI_MODE_SELECT_DVI		(1<<24) +#define  PIPE_DDI_MODE_SELECT_DP_SST	(2<<24) +#define  PIPE_DDI_MODE_SELECT_DP_MST	(3<<24) +#define  PIPE_DDI_MODE_SELECT_FDI		(4<<24) +#define  PIPE_DDI_BPC_8					(0<<20) +#define  PIPE_DDI_BPC_10				(1<<20) +#define  PIPE_DDI_BPC_6					(2<<20) +#define  PIPE_DDI_BPC_12				(3<<20) +#define  PIPE_DDI_BFI_ENABLE			(1<<4) +#define  PIPE_DDI_PORT_WIDTH_X1			(0<<1) +#define  PIPE_DDI_PORT_WIDTH_X2			(1<<1) +#define  PIPE_DDI_PORT_WIDTH_X4			(3<<1) + +/* DisplayPort Transport Control */ +#define DP_TP_CTL_A			0x64040 +#define DP_TP_CTL_B			0x64140 +#define DP_TP_CTL(port) _PORT(port, \ +					DP_TP_CTL_A, \ +					DP_TP_CTL_B) +#define  DP_TP_CTL_ENABLE		(1<<31) +#define  DP_TP_CTL_MODE_SST	(0<<27) +#define  DP_TP_CTL_MODE_MST	(1<<27) +#define  DP_TP_CTL_ENHANCED_FRAME_ENABLE	(1<<18) +#define  DP_TP_CTL_FDI_AUTOTRAIN	(1<<15) +#define  DP_TP_CTL_LINK_TRAIN_MASK		(7<<8) +#define  DP_TP_CTL_LINK_TRAIN_PAT1		(0<<8) +#define  DP_TP_CTL_LINK_TRAIN_PAT2		(1<<8) +#define  DP_TP_CTL_LINK_TRAIN_NORMAL	(3<<8) + +/* DisplayPort Transport Status */ +#define DP_TP_STATUS_A			0x64044 +#define DP_TP_STATUS_B			0x64144 +#define DP_TP_STATUS(port) _PORT(port, \ +					DP_TP_STATUS_A, \ +					DP_TP_STATUS_B) +#define  DP_TP_STATUS_AUTOTRAIN_DONE	(1<<12) + +/* DDI Buffer Control */ +#define DDI_BUF_CTL_A				0x64000 +#define DDI_BUF_CTL_B				0x64100 +#define DDI_BUF_CTL(port) _PORT(port, \ +					DDI_BUF_CTL_A, \ +					DDI_BUF_CTL_B) +#define  DDI_BUF_CTL_ENABLE				(1<<31) +#define  DDI_BUF_EMP_400MV_0DB_HSW		(0<<24)   /* Sel0 */ +#define  DDI_BUF_EMP_400MV_3_5DB_HSW	(1<<24)   /* Sel1 */ +#define  DDI_BUF_EMP_400MV_6DB_HSW		(2<<24)   /* Sel2 */ +#define  DDI_BUF_EMP_400MV_9_5DB_HSW	(3<<24)   /* Sel3 */ +#define  DDI_BUF_EMP_600MV_0DB_HSW		(4<<24)   /* Sel4 */ +#define  DDI_BUF_EMP_600MV_3_5DB_HSW	(5<<24)   /* Sel5 */ +#define  DDI_BUF_EMP_600MV_6DB_HSW		(6<<24)   /* Sel6 */ +#define  DDI_BUF_EMP_800MV_0DB_HSW		(7<<24)   /* Sel7 */ +#define  DDI_BUF_EMP_800MV_3_5DB_HSW	(8<<24)   /* Sel8 */ +#define  DDI_BUF_EMP_MASK				(0xf<<24) +#define  DDI_BUF_IS_IDLE				(1<<7) +#define  DDI_PORT_WIDTH_X1				(0<<1) +#define  DDI_PORT_WIDTH_X2				(1<<1) +#define  DDI_PORT_WIDTH_X4				(3<<1) +#define  DDI_INIT_DISPLAY_DETECTED		(1<<0) + +/* DDI Buffer Translations */ +#define DDI_BUF_TRANS_A				0x64E00 +#define DDI_BUF_TRANS_B				0x64E60 +#define DDI_BUF_TRANS(port) _PORT(port, \ +					DDI_BUF_TRANS_A, \ +					DDI_BUF_TRANS_B) + +/* Sideband Interface (SBI) is programmed indirectly, via + * SBI_ADDR, which contains the register offset; and SBI_DATA, + * which contains the payload */ +#define SBI_ADDR				0xC6000 +#define SBI_DATA				0xC6004 +#define SBI_CTL_STAT			0xC6008 +#define  SBI_CTL_OP_CRRD		(0x6<<8) +#define  SBI_CTL_OP_CRWR		(0x7<<8) +#define  SBI_RESPONSE_FAIL		(0x1<<1) +#define  SBI_RESPONSE_SUCCESS	(0x0<<1) +#define  SBI_BUSY				(0x1<<0) +#define  SBI_READY				(0x0<<0) + +/* SBI offsets */ +#define  SBI_SSCDIVINTPHASE6		0x0600 +#define   SBI_SSCDIVINTPHASE_DIVSEL_MASK	((0x7f)<<1) +#define   SBI_SSCDIVINTPHASE_DIVSEL(x)		((x)<<1) +#define   SBI_SSCDIVINTPHASE_INCVAL_MASK	((0x7f)<<8) +#define   SBI_SSCDIVINTPHASE_INCVAL(x)		((x)<<8) +#define   SBI_SSCDIVINTPHASE_DIR(x)			((x)<<15) +#define   SBI_SSCDIVINTPHASE_PROPAGATE		(1<<0) +#define  SBI_SSCCTL					0x020c +#define  SBI_SSCCTL6				0x060C +#define   SBI_SSCCTL_DISABLE		(1<<0) +#define  SBI_SSCAUXDIV6				0x0610 +#define   SBI_SSCAUXDIV_FINALDIV2SEL(x)		((x)<<4) +#define  SBI_DBUFF0					0x2a00 + +/* LPT PIXCLK_GATE */ +#define PIXCLK_GATE				0xC6020 +#define  PIXCLK_GATE_UNGATE		1<<0 +#define  PIXCLK_GATE_GATE		0<<0 + +/* SPLL */ +#define SPLL_CTL				0x46020 +#define  SPLL_PLL_ENABLE		(1<<31) +#define  SPLL_PLL_SCC			(1<<28) +#define  SPLL_PLL_NON_SCC		(2<<28) +#define  SPLL_PLL_FREQ_810MHz	(0<<26) +#define  SPLL_PLL_FREQ_1350MHz	(1<<26) + +/* WRPLL */ +#define WRPLL_CTL1				0x46040 +#define WRPLL_CTL2				0x46060 +#define  WRPLL_PLL_ENABLE				(1<<31) +#define  WRPLL_PLL_SELECT_SSC			(0x01<<28) +#define  WRPLL_PLL_SELECT_NON_SCC		(0x02<<28) +#define  WRPLL_PLL_SELECT_LCPLL_2700	(0x03<<28) + +/* Port clock selection */ +#define PORT_CLK_SEL_A			0x46100 +#define PORT_CLK_SEL_B			0x46104 +#define PORT_CLK_SEL(port) _PORT(port, \ +					PORT_CLK_SEL_A, \ +					PORT_CLK_SEL_B) +#define  PORT_CLK_SEL_LCPLL_2700	(0<<29) +#define  PORT_CLK_SEL_LCPLL_1350	(1<<29) +#define  PORT_CLK_SEL_LCPLL_810		(2<<29) +#define  PORT_CLK_SEL_SPLL			(3<<29) +#define  PORT_CLK_SEL_WRPLL1		(4<<29) +#define  PORT_CLK_SEL_WRPLL2		(5<<29) + +/* Pipe clock selection */ +#define PIPE_CLK_SEL_A			0x46140 +#define PIPE_CLK_SEL_B			0x46144 +#define PIPE_CLK_SEL(pipe) _PIPE(pipe, \ +					PIPE_CLK_SEL_A, \ +					PIPE_CLK_SEL_B) +/* For each pipe, we need to select the corresponding port clock */ +#define  PIPE_CLK_SEL_DISABLED	(0x0<<29) +#define  PIPE_CLK_SEL_PORT(x)	((x+1)<<29) + +/* LCPLL Control */ +#define LCPLL_CTL				0x130040 +#define  LCPLL_PLL_DISABLE		(1<<31) +#define  LCPLL_PLL_LOCK			(1<<30) +#define  LCPLL_CD_CLOCK_DISABLE	(1<<25) +#define  LCPLL_CD2X_CLOCK_DISABLE	(1<<23) + +/* Pipe WM_LINETIME - watermark line time */ +#define PIPE_WM_LINETIME_A		0x45270 +#define PIPE_WM_LINETIME_B		0x45274 +#define PIPE_WM_LINETIME(pipe) _PIPE(pipe, \ +					PIPE_WM_LINETIME_A, \ +					PIPE_WM_LINETIME_A) +#define   PIPE_WM_LINETIME_MASK		(0x1ff) +#define   PIPE_WM_LINETIME_TIME(x)			((x)) +#define   PIPE_WM_LINETIME_IPS_LINETIME_MASK	(0x1ff<<16) +#define   PIPE_WM_LINETIME_IPS_LINETIME(x)		((x)<<16) + +/* SFUSE_STRAP */ +#define SFUSE_STRAP				0xc2014 +#define  SFUSE_STRAP_DDIB_DETECTED	(1<<2) +#define  SFUSE_STRAP_DDIC_DETECTED	(1<<1) +#define  SFUSE_STRAP_DDID_DETECTED	(1<<0) +  #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/intel_acpi.c b/drivers/gpu/drm/i915/intel_acpi.c index bae3edf956a..f152b2a7fc5 100644 --- a/drivers/gpu/drm/i915/intel_acpi.c +++ b/drivers/gpu/drm/i915/intel_acpi.c @@ -182,8 +182,6 @@ static void intel_dsm_platform_mux_info(void)  			DRM_DEBUG_DRIVER("  hpd mux info: %s\n",  			       intel_dsm_mux_type(info->buffer.pointer[3]));  		} -	} else { -		DRM_ERROR("MUX INFO call failed\n");  	}  out: diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index b48fc2a8410..353459362f6 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -174,6 +174,28 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data,  	return (struct lvds_dvo_timing *)(entry + dvo_timing_offset);  } +/* get lvds_fp_timing entry + * this function may return NULL if the corresponding entry is invalid + */ +static const struct lvds_fp_timing * +get_lvds_fp_timing(const struct bdb_header *bdb, +		   const struct bdb_lvds_lfp_data *data, +		   const struct bdb_lvds_lfp_data_ptrs *ptrs, +		   int index) +{ +	size_t data_ofs = (const u8 *)data - (const u8 *)bdb; +	u16 data_size = ((const u16 *)data)[-1]; /* stored in header */ +	size_t ofs; + +	if (index >= ARRAY_SIZE(ptrs->ptr)) +		return NULL; +	ofs = ptrs->ptr[index].fp_timing_offset; +	if (ofs < data_ofs || +	    ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size) +		return NULL; +	return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs); +} +  /* Try to find integrated panel data */  static void  parse_lfp_panel_data(struct drm_i915_private *dev_priv, @@ -183,6 +205,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,  	const struct bdb_lvds_lfp_data *lvds_lfp_data;  	const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;  	const struct lvds_dvo_timing *panel_dvo_timing; +	const struct lvds_fp_timing *fp_timing;  	struct drm_display_mode *panel_fixed_mode;  	int i, downclock; @@ -244,6 +267,19 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,  			      "Normal Clock %dKHz, downclock %dKHz\n",  			      panel_fixed_mode->clock, 10*downclock);  	} + +	fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data, +				       lvds_lfp_data_ptrs, +				       lvds_options->panel_type); +	if (fp_timing) { +		/* check the resolution, just to be sure */ +		if (fp_timing->x_res == panel_fixed_mode->hdisplay && +		    fp_timing->y_res == panel_fixed_mode->vdisplay) { +			dev_priv->bios_lvds_val = fp_timing->lvds_reg_val; +			DRM_DEBUG_KMS("VBT initial LVDS value %x\n", +				      dev_priv->bios_lvds_val); +		} +	}  }  /* Try to find sdvo panel data */ @@ -256,6 +292,11 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,  	int index;  	index = i915_vbt_sdvo_panel_type; +	if (index == -2) { +		DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n"); +		return; +	} +  	if (index == -1) {  		struct bdb_sdvo_lvds_options *sdvo_lvds_options; @@ -332,11 +373,11 @@ parse_general_definitions(struct drm_i915_private *dev_priv,  		if (block_size >= sizeof(*general)) {  			int bus_pin = general->crt_ddc_gmbus_pin;  			DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); -			if (bus_pin >= 1 && bus_pin <= 6) +			if (intel_gmbus_is_port_valid(bus_pin))  				dev_priv->crt_ddc_pin = bus_pin;  		} else {  			DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", -				  block_size); +				      block_size);  		}  	}  } diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 4d3d736a4f5..70b0f1abf14 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -278,9 +278,10 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector)  	if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {  		struct edid *edid;  		bool is_digital = false; +		struct i2c_adapter *i2c; -		edid = drm_get_edid(connector, -			&dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); +		i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); +		edid = drm_get_edid(connector, i2c);  		/*  		 * This may be a DVI-I connector with a shared DDC  		 * link between analog and digital outputs, so we @@ -483,15 +484,16 @@ static int intel_crt_get_modes(struct drm_connector *connector)  	struct drm_device *dev = connector->dev;  	struct drm_i915_private *dev_priv = dev->dev_private;  	int ret; +	struct i2c_adapter *i2c; -	ret = intel_ddc_get_modes(connector, -				 &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); +	i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->crt_ddc_pin); +	ret = intel_ddc_get_modes(connector, i2c);  	if (ret || !IS_G4X(dev))  		return ret;  	/* Try to probe digital port for output in DVI-I -> VGA mode. */ -	return intel_ddc_get_modes(connector, -				   &dev_priv->gmbus[GMBUS_PORT_DPB].adapter); +	i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB); +	return intel_ddc_get_modes(connector, i2c);  }  static int intel_crt_set_property(struct drm_connector *connector, @@ -543,7 +545,7 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = {  static int __init intel_no_crt_dmi_callback(const struct dmi_system_id *id)  { -	DRM_DEBUG_KMS("Skipping CRT initialization for %s\n", id->ident); +	DRM_INFO("Skipping CRT initialization for %s\n", id->ident);  	return 1;  } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 91b35fd1db8..37514a52b05 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -24,6 +24,7 @@   *	Eric Anholt <eric@anholt.net>   */ +#include <linux/dmi.h>  #include <linux/cpufreq.h>  #include <linux/module.h>  #include <linux/input.h> @@ -360,6 +361,110 @@ static const intel_limit_t intel_limits_ironlake_display_port = {  	.find_pll = intel_find_pll_ironlake_dp,  }; +u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg) +{ +	unsigned long flags; +	u32 val = 0; + +	spin_lock_irqsave(&dev_priv->dpio_lock, flags); +	if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) { +		DRM_ERROR("DPIO idle wait timed out\n"); +		goto out_unlock; +	} + +	I915_WRITE(DPIO_REG, reg); +	I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_READ | DPIO_PORTID | +		   DPIO_BYTE); +	if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) { +		DRM_ERROR("DPIO read wait timed out\n"); +		goto out_unlock; +	} +	val = I915_READ(DPIO_DATA); + +out_unlock: +	spin_unlock_irqrestore(&dev_priv->dpio_lock, flags); +	return val; +} + +static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg, +			     u32 val) +{ +	unsigned long flags; + +	spin_lock_irqsave(&dev_priv->dpio_lock, flags); +	if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) { +		DRM_ERROR("DPIO idle wait timed out\n"); +		goto out_unlock; +	} + +	I915_WRITE(DPIO_DATA, val); +	I915_WRITE(DPIO_REG, reg); +	I915_WRITE(DPIO_PKT, DPIO_RID | DPIO_OP_WRITE | DPIO_PORTID | +		   DPIO_BYTE); +	if (wait_for_atomic_us((I915_READ(DPIO_PKT) & DPIO_BUSY) == 0, 100)) +		DRM_ERROR("DPIO write wait timed out\n"); + +out_unlock: +	spin_unlock_irqrestore(&dev_priv->dpio_lock, flags); +} + +static void vlv_init_dpio(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; + +	/* Reset the DPIO config */ +	I915_WRITE(DPIO_CTL, 0); +	POSTING_READ(DPIO_CTL); +	I915_WRITE(DPIO_CTL, 1); +	POSTING_READ(DPIO_CTL); +} + +static int intel_dual_link_lvds_callback(const struct dmi_system_id *id) +{ +	DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident); +	return 1; +} + +static const struct dmi_system_id intel_dual_link_lvds[] = { +	{ +		.callback = intel_dual_link_lvds_callback, +		.ident = "Apple MacBook Pro (Core i5/i7 Series)", +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), +			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"), +		}, +	}, +	{ }	/* terminating entry */ +}; + +static bool is_dual_link_lvds(struct drm_i915_private *dev_priv, +			      unsigned int reg) +{ +	unsigned int val; + +	/* use the module option value if specified */ +	if (i915_lvds_channel_mode > 0) +		return i915_lvds_channel_mode == 2; + +	if (dmi_check_system(intel_dual_link_lvds)) +		return true; + +	if (dev_priv->lvds_val) +		val = dev_priv->lvds_val; +	else { +		/* BIOS should set the proper LVDS register value at boot, but +		 * in reality, it doesn't set the value when the lid is closed; +		 * we need to check "the value to be set" in VBT when LVDS +		 * register is uninitialized. +		 */ +		val = I915_READ(reg); +		if (!(val & ~LVDS_DETECTED)) +			val = dev_priv->bios_lvds_val; +		dev_priv->lvds_val = val; +	} +	return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; +} +  static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,  						int refclk)  { @@ -368,8 +473,7 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,  	const intel_limit_t *limit;  	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { -		if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == -		    LVDS_CLKB_POWER_UP) { +		if (is_dual_link_lvds(dev_priv, PCH_LVDS)) {  			/* LVDS dual channel */  			if (refclk == 100000)  				limit = &intel_limits_ironlake_dual_lvds_100m; @@ -397,8 +501,7 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)  	const intel_limit_t *limit;  	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { -		if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == -		    LVDS_CLKB_POWER_UP) +		if (is_dual_link_lvds(dev_priv, LVDS))  			/* LVDS with dual channel */  			limit = &intel_limits_g4x_dual_channel_lvds;  		else @@ -536,8 +639,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,  		 * reliably set up different single/dual channel state, if we  		 * even can.  		 */ -		if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == -		    LVDS_CLKB_POWER_UP) +		if (is_dual_link_lvds(dev_priv, LVDS))  			clock.p2 = limit->p2.p2_fast;  		else  			clock.p2 = limit->p2.p2_slow; @@ -2537,7 +2639,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);  	int pipe = intel_crtc->pipe; -	u32 reg, temp, i; +	u32 reg, temp, i, retry;  	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit  	   for train result */ @@ -2589,15 +2691,19 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)  		POSTING_READ(reg);  		udelay(500); -		reg = FDI_RX_IIR(pipe); -		temp = I915_READ(reg); -		DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); - -		if (temp & FDI_RX_BIT_LOCK) { -			I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); -			DRM_DEBUG_KMS("FDI train 1 done.\n"); -			break; +		for (retry = 0; retry < 5; retry++) { +			reg = FDI_RX_IIR(pipe); +			temp = I915_READ(reg); +			DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); +			if (temp & FDI_RX_BIT_LOCK) { +				I915_WRITE(reg, temp | FDI_RX_BIT_LOCK); +				DRM_DEBUG_KMS("FDI train 1 done.\n"); +				break; +			} +			udelay(50);  		} +		if (retry < 5) +			break;  	}  	if (i == 4)  		DRM_ERROR("FDI train 1 fail!\n"); @@ -2638,15 +2744,19 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc)  		POSTING_READ(reg);  		udelay(500); -		reg = FDI_RX_IIR(pipe); -		temp = I915_READ(reg); -		DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); - -		if (temp & FDI_RX_SYMBOL_LOCK) { -			I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); -			DRM_DEBUG_KMS("FDI train 2 done.\n"); -			break; +		for (retry = 0; retry < 5; retry++) { +			reg = FDI_RX_IIR(pipe); +			temp = I915_READ(reg); +			DRM_DEBUG_KMS("FDI_RX_IIR 0x%x\n", temp); +			if (temp & FDI_RX_SYMBOL_LOCK) { +				I915_WRITE(reg, temp | FDI_RX_SYMBOL_LOCK); +				DRM_DEBUG_KMS("FDI train 2 done.\n"); +				break; +			} +			udelay(50);  		} +		if (retry < 5) +			break;  	}  	if (i == 4)  		DRM_ERROR("FDI train 2 fail!\n"); @@ -3457,6 +3567,11 @@ static bool intel_crtc_mode_fixup(struct drm_crtc *crtc,  	return true;  } +static int valleyview_get_display_clock_speed(struct drm_device *dev) +{ +	return 400000; /* FIXME */ +} +  static int i945_get_display_clock_speed(struct drm_device *dev)  {  	return 400000; @@ -3606,6 +3721,20 @@ static const struct intel_watermark_params g4x_cursor_wm_info = {  	2,  	G4X_FIFO_LINE_SIZE,  }; +static const struct intel_watermark_params valleyview_wm_info = { +	VALLEYVIEW_FIFO_SIZE, +	VALLEYVIEW_MAX_WM, +	VALLEYVIEW_MAX_WM, +	2, +	G4X_FIFO_LINE_SIZE, +}; +static const struct intel_watermark_params valleyview_cursor_wm_info = { +	I965_CURSOR_FIFO, +	VALLEYVIEW_CURSOR_MAX_WM, +	I965_CURSOR_DFT_WM, +	2, +	G4X_FIFO_LINE_SIZE, +};  static const struct intel_watermark_params i965_cursor_wm_info = {  	I965_CURSOR_FIFO,  	I965_CURSOR_MAX_WM, @@ -4128,8 +4257,134 @@ static bool g4x_compute_srwm(struct drm_device *dev,  			      display, cursor);  } +static bool vlv_compute_drain_latency(struct drm_device *dev, +				     int plane, +				     int *plane_prec_mult, +				     int *plane_dl, +				     int *cursor_prec_mult, +				     int *cursor_dl) +{ +	struct drm_crtc *crtc; +	int clock, pixel_size; +	int entries; + +	crtc = intel_get_crtc_for_plane(dev, plane); +	if (crtc->fb == NULL || !crtc->enabled) +		return false; + +	clock = crtc->mode.clock;	/* VESA DOT Clock */ +	pixel_size = crtc->fb->bits_per_pixel / 8;	/* BPP */ + +	entries = (clock / 1000) * pixel_size; +	*plane_prec_mult = (entries > 256) ? +		DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16; +	*plane_dl = (64 * (*plane_prec_mult) * 4) / ((clock / 1000) * +						     pixel_size); + +	entries = (clock / 1000) * 4;	/* BPP is always 4 for cursor */ +	*cursor_prec_mult = (entries > 256) ? +		DRAIN_LATENCY_PRECISION_32 : DRAIN_LATENCY_PRECISION_16; +	*cursor_dl = (64 * (*cursor_prec_mult) * 4) / ((clock / 1000) * 4); + +	return true; +} + +/* + * Update drain latency registers of memory arbiter + * + * Valleyview SoC has a new memory arbiter and needs drain latency registers + * to be programmed. Each plane has a drain latency multiplier and a drain + * latency value. + */ + +static void vlv_update_drain_latency(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	int planea_prec, planea_dl, planeb_prec, planeb_dl; +	int cursora_prec, cursora_dl, cursorb_prec, cursorb_dl; +	int plane_prec_mult, cursor_prec_mult; /* Precision multiplier is +							either 16 or 32 */ + +	/* For plane A, Cursor A */ +	if (vlv_compute_drain_latency(dev, 0, &plane_prec_mult, &planea_dl, +				      &cursor_prec_mult, &cursora_dl)) { +		cursora_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ? +			DDL_CURSORA_PRECISION_32 : DDL_CURSORA_PRECISION_16; +		planea_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ? +			DDL_PLANEA_PRECISION_32 : DDL_PLANEA_PRECISION_16; + +		I915_WRITE(VLV_DDL1, cursora_prec | +				(cursora_dl << DDL_CURSORA_SHIFT) | +				planea_prec | planea_dl); +	} + +	/* For plane B, Cursor B */ +	if (vlv_compute_drain_latency(dev, 1, &plane_prec_mult, &planeb_dl, +				      &cursor_prec_mult, &cursorb_dl)) { +		cursorb_prec = (cursor_prec_mult == DRAIN_LATENCY_PRECISION_32) ? +			DDL_CURSORB_PRECISION_32 : DDL_CURSORB_PRECISION_16; +		planeb_prec = (plane_prec_mult == DRAIN_LATENCY_PRECISION_32) ? +			DDL_PLANEB_PRECISION_32 : DDL_PLANEB_PRECISION_16; + +		I915_WRITE(VLV_DDL2, cursorb_prec | +				(cursorb_dl << DDL_CURSORB_SHIFT) | +				planeb_prec | planeb_dl); +	} +} +  #define single_plane_enabled(mask) is_power_of_2(mask) +static void valleyview_update_wm(struct drm_device *dev) +{ +	static const int sr_latency_ns = 12000; +	struct drm_i915_private *dev_priv = dev->dev_private; +	int planea_wm, planeb_wm, cursora_wm, cursorb_wm; +	int plane_sr, cursor_sr; +	unsigned int enabled = 0; + +	vlv_update_drain_latency(dev); + +	if (g4x_compute_wm0(dev, 0, +			    &valleyview_wm_info, latency_ns, +			    &valleyview_cursor_wm_info, latency_ns, +			    &planea_wm, &cursora_wm)) +		enabled |= 1; + +	if (g4x_compute_wm0(dev, 1, +			    &valleyview_wm_info, latency_ns, +			    &valleyview_cursor_wm_info, latency_ns, +			    &planeb_wm, &cursorb_wm)) +		enabled |= 2; + +	plane_sr = cursor_sr = 0; +	if (single_plane_enabled(enabled) && +	    g4x_compute_srwm(dev, ffs(enabled) - 1, +			     sr_latency_ns, +			     &valleyview_wm_info, +			     &valleyview_cursor_wm_info, +			     &plane_sr, &cursor_sr)) +		I915_WRITE(FW_BLC_SELF_VLV, FW_CSPWRDWNEN); +	else +		I915_WRITE(FW_BLC_SELF_VLV, +			   I915_READ(FW_BLC_SELF_VLV) & ~FW_CSPWRDWNEN); + +	DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n", +		      planea_wm, cursora_wm, +		      planeb_wm, cursorb_wm, +		      plane_sr, cursor_sr); + +	I915_WRITE(DSPFW1, +		   (plane_sr << DSPFW_SR_SHIFT) | +		   (cursorb_wm << DSPFW_CURSORB_SHIFT) | +		   (planeb_wm << DSPFW_PLANEB_SHIFT) | +		   planea_wm); +	I915_WRITE(DSPFW2, +		   (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) | +		   (cursora_wm << DSPFW_CURSORA_SHIFT)); +	I915_WRITE(DSPFW3, +		   (I915_READ(DSPFW3) | (cursor_sr << DSPFW_CURSOR_SR_SHIFT))); +} +  static void g4x_update_wm(struct drm_device *dev)  {  	static const int sr_latency_ns = 12000; @@ -5113,6 +5368,233 @@ static void i9xx_update_pll_dividers(struct drm_crtc *crtc,  	}  } +static void intel_update_lvds(struct drm_crtc *crtc, intel_clock_t *clock, +			      struct drm_display_mode *adjusted_mode) +{ +	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 temp, lvds_sync = 0; + +	temp = I915_READ(LVDS); +	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; +	if (pipe == 1) { +		temp |= LVDS_PIPEB_SELECT; +	} else { +		temp &= ~LVDS_PIPEB_SELECT; +	} +	/* set the corresponsding LVDS_BORDER bit */ +	temp |= dev_priv->lvds_border_bits; +	/* Set the B0-B3 data pairs corresponding to whether we're going to +	 * set the DPLLs for dual-channel mode or not. +	 */ +	if (clock->p2 == 7) +		temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; +	else +		temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); + +	/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) +	 * appropriately here, but we need to look more thoroughly into how +	 * panels behave in the two modes. +	 */ +	/* set the dithering flag on LVDS as needed */ +	if (INTEL_INFO(dev)->gen >= 4) { +		if (dev_priv->lvds_dither) +			temp |= LVDS_ENABLE_DITHER; +		else +			temp &= ~LVDS_ENABLE_DITHER; +	} +	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) +		lvds_sync |= LVDS_HSYNC_POLARITY; +	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) +		lvds_sync |= LVDS_VSYNC_POLARITY; +	if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY)) +	    != lvds_sync) { +		char flags[2] = "-+"; +		DRM_INFO("Changing LVDS panel from " +			 "(%chsync, %cvsync) to (%chsync, %cvsync)\n", +			 flags[!(temp & LVDS_HSYNC_POLARITY)], +			 flags[!(temp & LVDS_VSYNC_POLARITY)], +			 flags[!(lvds_sync & LVDS_HSYNC_POLARITY)], +			 flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]); +		temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); +		temp |= lvds_sync; +	} +	I915_WRITE(LVDS, temp); +} + +static void i9xx_update_pll(struct drm_crtc *crtc, +			    struct drm_display_mode *mode, +			    struct drm_display_mode *adjusted_mode, +			    intel_clock_t *clock, intel_clock_t *reduced_clock, +			    int num_connectors) +{ +	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 dpll; +	bool is_sdvo; + +	is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) || +		intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI); + +	dpll = DPLL_VGA_MODE_DIS; + +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) +		dpll |= DPLLB_MODE_LVDS; +	else +		dpll |= DPLLB_MODE_DAC_SERIAL; +	if (is_sdvo) { +		int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); +		if (pixel_multiplier > 1) { +			if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) +				dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; +		} +		dpll |= DPLL_DVO_HIGH_SPEED; +	} +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) +		dpll |= DPLL_DVO_HIGH_SPEED; + +	/* compute bitmask from p1 value */ +	if (IS_PINEVIEW(dev)) +		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; +	else { +		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; +		if (IS_G4X(dev) && reduced_clock) +			dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; +	} +	switch (clock->p2) { +	case 5: +		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; +		break; +	case 7: +		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; +		break; +	case 10: +		dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; +		break; +	case 14: +		dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; +		break; +	} +	if (INTEL_INFO(dev)->gen >= 4) +		dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); + +	if (is_sdvo && intel_pipe_has_type(crtc, INTEL_OUTPUT_TVOUT)) +		dpll |= PLL_REF_INPUT_TVCLKINBC; +	else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_TVOUT)) +		/* XXX: just matching BIOS for now */ +		/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */ +		dpll |= 3; +	else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && +		 intel_panel_use_ssc(dev_priv) && num_connectors < 2) +		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; +	else +		dpll |= PLL_REF_INPUT_DREFCLK; + +	dpll |= DPLL_VCO_ENABLE; +	I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); +	POSTING_READ(DPLL(pipe)); +	udelay(150); + +	/* The LVDS pin pair needs to be on before the DPLLs are enabled. +	 * This is an exception to the general rule that mode_set doesn't turn +	 * things on. +	 */ +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) +		intel_update_lvds(crtc, clock, adjusted_mode); + +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT)) +		intel_dp_set_m_n(crtc, mode, adjusted_mode); + +	I915_WRITE(DPLL(pipe), dpll); + +	/* Wait for the clocks to stabilize. */ +	POSTING_READ(DPLL(pipe)); +	udelay(150); + +	if (INTEL_INFO(dev)->gen >= 4) { +		u32 temp = 0; +		if (is_sdvo) { +			temp = intel_mode_get_pixel_multiplier(adjusted_mode); +			if (temp > 1) +				temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; +			else +				temp = 0; +		} +		I915_WRITE(DPLL_MD(pipe), temp); +	} else { +		/* The pixel multiplier can only be updated once the +		 * DPLL is enabled and the clocks are stable. +		 * +		 * So write it again. +		 */ +		I915_WRITE(DPLL(pipe), dpll); +	} +} + +static void i8xx_update_pll(struct drm_crtc *crtc, +			    struct drm_display_mode *adjusted_mode, +			    intel_clock_t *clock, +			    int num_connectors) +{ +	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 dpll; + +	dpll = DPLL_VGA_MODE_DIS; + +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { +		dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; +	} else { +		if (clock->p1 == 2) +			dpll |= PLL_P1_DIVIDE_BY_TWO; +		else +			dpll |= (clock->p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; +		if (clock->p2 == 4) +			dpll |= PLL_P2_DIVIDE_BY_4; +	} + +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_TVOUT)) +		/* XXX: just matching BIOS for now */ +		/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */ +		dpll |= 3; +	else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && +		 intel_panel_use_ssc(dev_priv) && num_connectors < 2) +		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; +	else +		dpll |= PLL_REF_INPUT_DREFCLK; + +	dpll |= DPLL_VCO_ENABLE; +	I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); +	POSTING_READ(DPLL(pipe)); +	udelay(150); + +	I915_WRITE(DPLL(pipe), dpll); + +	/* Wait for the clocks to stabilize. */ +	POSTING_READ(DPLL(pipe)); +	udelay(150); + +	/* The LVDS pin pair needs to be on before the DPLLs are enabled. +	 * This is an exception to the general rule that mode_set doesn't turn +	 * things on. +	 */ +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) +		intel_update_lvds(crtc, clock, adjusted_mode); + +	/* The pixel multiplier can only be updated once the +	 * DPLL is enabled and the clocks are stable. +	 * +	 * So write it again. +	 */ +	I915_WRITE(DPLL(pipe), dpll); +} +  static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  			      struct drm_display_mode *mode,  			      struct drm_display_mode *adjusted_mode, @@ -5126,15 +5608,13 @@ 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, 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; +	u32 dspcntr, pipeconf, vsyncshift; +	bool ok, has_reduced_clock = false, is_sdvo = false; +	bool is_lvds = false, is_tv = false, is_dp = false;  	struct drm_mode_config *mode_config = &dev->mode_config;  	struct intel_encoder *encoder;  	const intel_limit_t *limit;  	int ret; -	u32 temp; -	u32 lvds_sync = 0;  	list_for_each_entry(encoder, &mode_config->encoder_list, base.head) {  		if (encoder->base.crtc != crtc) @@ -5150,15 +5630,9 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  			if (encoder->needs_tv_clock)  				is_tv = true;  			break; -		case INTEL_OUTPUT_DVO: -			is_dvo = true; -			break;  		case INTEL_OUTPUT_TVOUT:  			is_tv = true;  			break; -		case INTEL_OUTPUT_ANALOG: -			is_crt = true; -			break;  		case INTEL_OUTPUT_DISPLAYPORT:  			is_dp = true;  			break; @@ -5205,71 +5679,12 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  	i9xx_update_pll_dividers(crtc, &clock, has_reduced_clock ?  				 &reduced_clock : NULL); -	dpll = DPLL_VGA_MODE_DIS; - -	if (!IS_GEN2(dev)) { -		if (is_lvds) -			dpll |= DPLLB_MODE_LVDS; -		else -			dpll |= DPLLB_MODE_DAC_SERIAL; -		if (is_sdvo) { -			int pixel_multiplier = intel_mode_get_pixel_multiplier(adjusted_mode); -			if (pixel_multiplier > 1) { -				if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) -					dpll |= (pixel_multiplier - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; -			} -			dpll |= DPLL_DVO_HIGH_SPEED; -		} -		if (is_dp) -			dpll |= DPLL_DVO_HIGH_SPEED; - -		/* compute bitmask from p1 value */ -		if (IS_PINEVIEW(dev)) -			dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; -		else { -			dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; -			if (IS_G4X(dev) && has_reduced_clock) -				dpll |= (1 << (reduced_clock.p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; -		} -		switch (clock.p2) { -		case 5: -			dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; -			break; -		case 7: -			dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; -			break; -		case 10: -			dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; -			break; -		case 14: -			dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; -			break; -		} -		if (INTEL_INFO(dev)->gen >= 4) -			dpll |= (6 << PLL_LOAD_PULSE_PHASE_SHIFT); -	} else { -		if (is_lvds) { -			dpll |= (1 << (clock.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; -		} else { -			if (clock.p1 == 2) -				dpll |= PLL_P1_DIVIDE_BY_TWO; -			else -				dpll |= (clock.p1 - 2) << DPLL_FPA01_P1_POST_DIV_SHIFT; -			if (clock.p2 == 4) -				dpll |= PLL_P2_DIVIDE_BY_4; -		} -	} - -	if (is_sdvo && is_tv) -		dpll |= PLL_REF_INPUT_TVCLKINBC; -	else if (is_tv) -		/* XXX: just matching BIOS for now */ -		/*	dpll |= PLL_REF_INPUT_TVCLKINBC; */ -		dpll |= 3; -	else if (is_lvds && intel_panel_use_ssc(dev_priv) && num_connectors < 2) -		dpll |= PLLB_REF_INPUT_SPREADSPECTRUMIN; +	if (IS_GEN2(dev)) +		i8xx_update_pll(crtc, adjusted_mode, &clock, num_connectors);  	else -		dpll |= PLL_REF_INPUT_DREFCLK; +		i9xx_update_pll(crtc, mode, adjusted_mode, &clock, +				has_reduced_clock ? &reduced_clock : NULL, +				num_connectors);  	/* setup pipeconf */  	pipeconf = I915_READ(PIPECONF(pipe)); @@ -5306,97 +5721,9 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  		}  	} -	dpll |= DPLL_VCO_ENABLE; -  	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');  	drm_mode_debug_printmodeline(mode); -	I915_WRITE(DPLL(pipe), dpll & ~DPLL_VCO_ENABLE); - -	POSTING_READ(DPLL(pipe)); -	udelay(150); - -	/* The LVDS pin pair needs to be on before the DPLLs are enabled. -	 * This is an exception to the general rule that mode_set doesn't turn -	 * things on. -	 */ -	if (is_lvds) { -		temp = I915_READ(LVDS); -		temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; -		if (pipe == 1) { -			temp |= LVDS_PIPEB_SELECT; -		} else { -			temp &= ~LVDS_PIPEB_SELECT; -		} -		/* set the corresponsding LVDS_BORDER bit */ -		temp |= dev_priv->lvds_border_bits; -		/* Set the B0-B3 data pairs corresponding to whether we're going to -		 * set the DPLLs for dual-channel mode or not. -		 */ -		if (clock.p2 == 7) -			temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; -		else -			temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); - -		/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) -		 * appropriately here, but we need to look more thoroughly into how -		 * panels behave in the two modes. -		 */ -		/* set the dithering flag on LVDS as needed */ -		if (INTEL_INFO(dev)->gen >= 4) { -			if (dev_priv->lvds_dither) -				temp |= LVDS_ENABLE_DITHER; -			else -				temp &= ~LVDS_ENABLE_DITHER; -		} -		if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) -			lvds_sync |= LVDS_HSYNC_POLARITY; -		if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) -			lvds_sync |= LVDS_VSYNC_POLARITY; -		if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY)) -		    != lvds_sync) { -			char flags[2] = "-+"; -			DRM_INFO("Changing LVDS panel from " -				 "(%chsync, %cvsync) to (%chsync, %cvsync)\n", -				 flags[!(temp & LVDS_HSYNC_POLARITY)], -				 flags[!(temp & LVDS_VSYNC_POLARITY)], -				 flags[!(lvds_sync & LVDS_HSYNC_POLARITY)], -				 flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]); -			temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); -			temp |= lvds_sync; -		} -		I915_WRITE(LVDS, temp); -	} - -	if (is_dp) { -		intel_dp_set_m_n(crtc, mode, adjusted_mode); -	} - -	I915_WRITE(DPLL(pipe), dpll); - -	/* Wait for the clocks to stabilize. */ -	POSTING_READ(DPLL(pipe)); -	udelay(150); - -	if (INTEL_INFO(dev)->gen >= 4) { -		temp = 0; -		if (is_sdvo) { -			temp = intel_mode_get_pixel_multiplier(adjusted_mode); -			if (temp > 1) -				temp = (temp - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT; -			else -				temp = 0; -		} -		I915_WRITE(DPLL_MD(pipe), temp); -	} else { -		/* The pixel multiplier can only be updated once the -		 * DPLL is enabled and the clocks are stable. -		 * -		 * So write it again. -		 */ -		I915_WRITE(DPLL(pipe), dpll); -	} -  	if (HAS_PIPE_CXSR(dev)) {  		if (intel_crtc->lowfreq_avail) {  			DRM_DEBUG_KMS("enabling CxSR downclocking\n"); @@ -7796,7 +8123,7 @@ static void intel_setup_outputs(struct drm_device *dev)  		if (I915_READ(HDMIB) & PORT_DETECTED) {  			/* PCH SDVOB multiplex with HDMIB */ -			found = intel_sdvo_init(dev, PCH_SDVOB); +			found = intel_sdvo_init(dev, PCH_SDVOB, true);  			if (!found)  				intel_hdmi_init(dev, HDMIB);  			if (!found && (I915_READ(PCH_DP_B) & DP_DETECTED)) @@ -7820,7 +8147,7 @@ static void intel_setup_outputs(struct drm_device *dev)  		if (I915_READ(SDVOB) & SDVO_DETECTED) {  			DRM_DEBUG_KMS("probing SDVOB\n"); -			found = intel_sdvo_init(dev, SDVOB); +			found = intel_sdvo_init(dev, SDVOB, true);  			if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) {  				DRM_DEBUG_KMS("probing HDMI on SDVOB\n");  				intel_hdmi_init(dev, SDVOB); @@ -7836,7 +8163,7 @@ static void intel_setup_outputs(struct drm_device *dev)  		if (I915_READ(SDVOB) & SDVO_DETECTED) {  			DRM_DEBUG_KMS("probing SDVOC\n"); -			found = intel_sdvo_init(dev, SDVOC); +			found = intel_sdvo_init(dev, SDVOC, false);  		}  		if (!found && (I915_READ(SDVOC) & SDVO_DETECTED)) { @@ -8617,6 +8944,54 @@ static void ivybridge_init_clock_gating(struct drm_device *dev)  	}  } +static void valleyview_init_clock_gating(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	int pipe; +	uint32_t dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE; + +	I915_WRITE(PCH_DSPCLK_GATE_D, dspclk_gate); + +	I915_WRITE(WM3_LP_ILK, 0); +	I915_WRITE(WM2_LP_ILK, 0); +	I915_WRITE(WM1_LP_ILK, 0); + +	/* According to the spec, bit 13 (RCZUNIT) must be set on IVB. +	 * This implements the WaDisableRCZUnitClockGating workaround. +	 */ +	I915_WRITE(GEN6_UCGCTL2, GEN6_RCZUNIT_CLOCK_GATE_DISABLE); + +	I915_WRITE(ILK_DSPCLK_GATE, IVB_VRHUNIT_CLK_GATE); + +	I915_WRITE(IVB_CHICKEN3, +		   CHICKEN3_DGMG_REQ_OUT_FIX_DISABLE | +		   CHICKEN3_DGMG_DONE_FIX_DISABLE); + +	/* Apply the WaDisableRHWOOptimizationForRenderHang workaround. */ +	I915_WRITE(GEN7_COMMON_SLICE_CHICKEN1, +		   GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC); + +	/* WaApplyL3ControlAndL3ChickenMode requires those two on Ivy Bridge */ +	I915_WRITE(GEN7_L3CNTLREG1, GEN7_WA_FOR_GEN7_L3_CONTROL); +	I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, GEN7_WA_L3_CHICKEN_MODE); + +	/* This is required by WaCatErrorRejectionIssue */ +	I915_WRITE(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG, +		   I915_READ(GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) | +		   GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB); + +	for_each_pipe(pipe) { +		I915_WRITE(DSPCNTR(pipe), +			   I915_READ(DSPCNTR(pipe)) | +			   DISPPLANE_TRICKLE_FEED_DISABLE); +		intel_flush_display_plane(dev_priv, pipe); +	} + +	I915_WRITE(CACHE_MODE_1, I915_READ(CACHE_MODE_1) | +		   (PIXEL_SUBSPAN_COLLECT_OPT_DISABLE << 16) | +		   PIXEL_SUBSPAN_COLLECT_OPT_DISABLE); +} +  static void g4x_init_clock_gating(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -8871,7 +9246,10 @@ static void intel_init_display(struct drm_device *dev)  	}  	/* Returns the core display clock speed */ -	if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev))) +	if (IS_VALLEYVIEW(dev)) +		dev_priv->display.get_display_clock_speed = +			valleyview_get_display_clock_speed; +	else if (IS_I945G(dev) || (IS_G33(dev) && !IS_PINEVIEW_M(dev)))  		dev_priv->display.get_display_clock_speed =  			i945_get_display_clock_speed;  	else if (IS_I915G(dev)) @@ -8966,6 +9344,12 @@ static void intel_init_display(struct drm_device *dev)  			dev_priv->display.write_eld = ironlake_write_eld;  		} else  			dev_priv->display.update_wm = NULL; +	} else if (IS_VALLEYVIEW(dev)) { +		dev_priv->display.update_wm = valleyview_update_wm; +		dev_priv->display.init_clock_gating = +			valleyview_init_clock_gating; +		dev_priv->display.force_wake_get = vlv_force_wake_get; +		dev_priv->display.force_wake_put = vlv_force_wake_put;  	} else if (IS_PINEVIEW(dev)) {  		if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev),  					    dev_priv->is_ddr3, @@ -9049,7 +9433,7 @@ static void quirk_pipea_force(struct drm_device *dev)  	struct drm_i915_private *dev_priv = dev->dev_private;  	dev_priv->quirks |= QUIRK_PIPEA_FORCE; -	DRM_DEBUG_DRIVER("applying pipe a force quirk\n"); +	DRM_INFO("applying pipe a force quirk\n");  }  /* @@ -9059,6 +9443,18 @@ static void quirk_ssc_force_disable(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	dev_priv->quirks |= QUIRK_LVDS_SSC_DISABLE; +	DRM_INFO("applying lvds SSC disable quirk\n"); +} + +/* + * A machine (e.g. Acer Aspire 5734Z) may need to invert the panel backlight + * brightness value + */ +static void quirk_invert_brightness(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	dev_priv->quirks |= QUIRK_INVERT_BRIGHTNESS; +	DRM_INFO("applying inverted panel brightness quirk\n");  }  struct intel_quirk { @@ -9093,6 +9489,9 @@ struct intel_quirk intel_quirks[] = {  	/* Sony Vaio Y cannot use SSC on LVDS */  	{ 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable }, + +	/* Acer Aspire 5734Z must invert backlight brightness */ +	{ 0x2a42, 0x1025, 0x0459, quirk_invert_brightness },  };  static void intel_init_quirks(struct drm_device *dev) @@ -9236,6 +9635,9 @@ void intel_modeset_cleanup(struct drm_device *dev)  	if (IS_IRONLAKE_M(dev))  		ironlake_disable_rc6(dev); +	if (IS_VALLEYVIEW(dev)) +		vlv_init_dpio(dev); +  	mutex_unlock(&dev->struct_mutex);  	/* Disable the irq before mode object teardown, for the irq might diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5a14149b379..79cabf58d87 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -45,6 +45,18 @@  	ret__;								\  }) +#define wait_for_atomic_us(COND, US) ({ \ +	int i, ret__ = -ETIMEDOUT;	\ +	for (i = 0; i < (US); i++) {	\ +		if ((COND)) {		\ +			ret__ = 0;	\ +			break;		\ +		}			\ +		udelay(1);		\ +	}				\ +	ret__;				\ +}) +  #define wait_for(COND, MS) _wait_for(COND, MS, 1)  #define wait_for_atomic(COND, MS) _wait_for(COND, MS, 0) @@ -293,7 +305,8 @@ extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector)  extern void intel_crt_init(struct drm_device *dev);  extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);  void intel_dip_infoframe_csum(struct dip_infoframe *avi_if); -extern bool intel_sdvo_init(struct drm_device *dev, int output_device); +extern bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, +			    bool is_sdvob);  extern void intel_dvo_init(struct drm_device *dev);  extern void intel_tv_init(struct drm_device *dev);  extern void intel_mark_busy(struct drm_device *dev, @@ -419,4 +432,6 @@ extern int intel_sprite_set_colorkey(struct drm_device *dev, void *data,  extern int intel_sprite_get_colorkey(struct drm_device *dev, void *data,  				     struct drm_file *file_priv); +extern u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg); +  #endif /* __INTEL_DRV_H__ */ diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 020a7d7f744..60ba50b956f 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -243,7 +243,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector)  	 * that's not the case.  	 */  	intel_ddc_get_modes(connector, -			    &dev_priv->gmbus[GMBUS_PORT_DPC].adapter); +			    intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPC));  	if (!list_empty(&connector->probed_modes))  		return 1; @@ -375,7 +375,7 @@ void intel_dvo_init(struct drm_device *dev)  		 * special cases, but otherwise default to what's defined  		 * in the spec.  		 */ -		if (dvo->gpio != 0) +		if (intel_gmbus_is_port_valid(dvo->gpio))  			gpio = dvo->gpio;  		else if (dvo->type == INTEL_DVO_CHIP_LVDS)  			gpio = GMBUS_PORT_SSC; @@ -386,7 +386,7 @@ void intel_dvo_init(struct drm_device *dev)  		 * It appears that everything is on GPIOE except for panels  		 * on i830 laptops, which are on GPIOB (DVOA).  		 */ -		i2c = &dev_priv->gmbus[gpio].adapter; +		i2c = intel_gmbus_get_adapter(dev_priv, gpio);  		intel_dvo->dev = *dvo;  		if (!dvo->dev_ops->init(&intel_dvo->dev, i2c)) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index cae3e5f17a4..7de2d3b85b3 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -177,6 +177,37 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder,  	I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags);  } + +static void vlv_write_infoframe(struct drm_encoder *encoder, +				     struct dip_infoframe *frame) +{ +	uint32_t *data = (uint32_t *)frame; +	struct drm_device *dev = encoder->dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct drm_crtc *crtc = encoder->crtc; +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	int reg = VLV_TVIDEO_DIP_CTL(intel_crtc->pipe); +	unsigned i, len = DIP_HEADER_SIZE + frame->len; +	u32 flags, val = I915_READ(reg); + +	intel_wait_for_vblank(dev, intel_crtc->pipe); + +	flags = intel_infoframe_index(frame); + +	val &= ~(VIDEO_DIP_SELECT_MASK | 0xf); /* clear DIP data offset */ + +	I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); + +	for (i = 0; i < len; i += 4) { +		I915_WRITE(VLV_TVIDEO_DIP_DATA(intel_crtc->pipe), *data); +		data++; +	} + +	flags |= intel_infoframe_flags(frame); + +	I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); +} +  static void intel_set_infoframe(struct drm_encoder *encoder,  				struct dip_infoframe *frame)  { @@ -334,7 +365,8 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)  	intel_hdmi->has_hdmi_sink = false;  	intel_hdmi->has_audio = false;  	edid = drm_get_edid(connector, -			    &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); +			    intel_gmbus_get_adapter(dev_priv, +						    intel_hdmi->ddc_bus));  	if (edid) {  		if (edid->input & DRM_EDID_INPUT_DIGITAL) { @@ -367,7 +399,8 @@ static int intel_hdmi_get_modes(struct drm_connector *connector)  	 */  	return intel_ddc_get_modes(connector, -				   &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); +				   intel_gmbus_get_adapter(dev_priv, +							   intel_hdmi->ddc_bus));  }  static bool @@ -379,7 +412,8 @@ intel_hdmi_detect_audio(struct drm_connector *connector)  	bool has_audio = false;  	edid = drm_get_edid(connector, -			    &dev_priv->gmbus[intel_hdmi->ddc_bus].adapter); +			    intel_gmbus_get_adapter(dev_priv, +						    intel_hdmi->ddc_bus));  	if (edid) {  		if (edid->input & DRM_EDID_INPUT_DIGITAL)  			has_audio = drm_detect_monitor_audio(edid); @@ -549,7 +583,11 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)  	if (!HAS_PCH_SPLIT(dev)) {  		intel_hdmi->write_infoframe = i9xx_write_infoframe;  		I915_WRITE(VIDEO_DIP_CTL, 0); -	} else { +	} else if (IS_VALLEYVIEW(dev)) { +		intel_hdmi->write_infoframe = vlv_write_infoframe; +		for_each_pipe(i) +			I915_WRITE(VLV_TVIDEO_DIP_CTL(i), 0); +	}  else {  		intel_hdmi->write_infoframe = ironlake_write_infoframe;  		for_each_pipe(i)  			I915_WRITE(TVIDEO_DIP_CTL(i), 0); diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 601c86e664a..c12db726589 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -35,6 +35,20 @@  #include "i915_drm.h"  #include "i915_drv.h" +struct gmbus_port { +	const char *name; +	int reg; +}; + +static const struct gmbus_port gmbus_ports[] = { +	{ "ssc", GPIOB }, +	{ "vga", GPIOA }, +	{ "panel", GPIOC }, +	{ "dpc", GPIOD }, +	{ "dpb", GPIOE }, +	{ "dpd", GPIOF }, +}; +  /* Intel GPIO access functions */  #define I2C_RISEFALL_TIME 10 @@ -49,10 +63,7 @@ void  intel_i2c_reset(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; -	if (HAS_PCH_SPLIT(dev)) -		I915_WRITE(PCH_GMBUS0, 0); -	else -		I915_WRITE(GMBUS0, 0); +	I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0);  }  static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) @@ -140,65 +151,132 @@ static void set_data(void *data, int state_high)  	POSTING_READ(bus->gpio_reg);  } -static bool +static int +intel_gpio_pre_xfer(struct i2c_adapter *adapter) +{ +	struct intel_gmbus *bus = container_of(adapter, +					       struct intel_gmbus, +					       adapter); +	struct drm_i915_private *dev_priv = bus->dev_priv; + +	intel_i2c_reset(dev_priv->dev); +	intel_i2c_quirk_set(dev_priv, true); +	set_data(bus, 1); +	set_clock(bus, 1); +	udelay(I2C_RISEFALL_TIME); +	return 0; +} + +static void +intel_gpio_post_xfer(struct i2c_adapter *adapter) +{ +	struct intel_gmbus *bus = container_of(adapter, +					       struct intel_gmbus, +					       adapter); +	struct drm_i915_private *dev_priv = bus->dev_priv; + +	set_data(bus, 1); +	set_clock(bus, 1); +	intel_i2c_quirk_set(dev_priv, false); +} + +static void  intel_gpio_setup(struct intel_gmbus *bus, u32 pin)  {  	struct drm_i915_private *dev_priv = bus->dev_priv; -	static const int map_pin_to_reg[] = { -		0, -		GPIOB, -		GPIOA, -		GPIOC, -		GPIOD, -		GPIOE, -		0, -		GPIOF, -	};  	struct i2c_algo_bit_data *algo; -	if (pin >= ARRAY_SIZE(map_pin_to_reg) || !map_pin_to_reg[pin]) -		return false; -  	algo = &bus->bit_algo; -	bus->gpio_reg = map_pin_to_reg[pin]; -	if (HAS_PCH_SPLIT(dev_priv->dev)) -		bus->gpio_reg += PCH_GPIOA - GPIOA; +	/* -1 to map pin pair to gmbus index */ +	bus->gpio_reg = dev_priv->gpio_mmio_base + gmbus_ports[pin - 1].reg;  	bus->adapter.algo_data = algo;  	algo->setsda = set_data;  	algo->setscl = set_clock;  	algo->getsda = get_data;  	algo->getscl = get_clock; +	algo->pre_xfer = intel_gpio_pre_xfer; +	algo->post_xfer = intel_gpio_post_xfer;  	algo->udelay = I2C_RISEFALL_TIME;  	algo->timeout = usecs_to_jiffies(2200);  	algo->data = bus; - -	return true;  }  static int -intel_i2c_quirk_xfer(struct intel_gmbus *bus, -		     struct i2c_msg *msgs, -		     int num) +gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, +		bool last)  { -	struct drm_i915_private *dev_priv = bus->dev_priv; -	int ret; +	int reg_offset = dev_priv->gpio_mmio_base; +	u16 len = msg->len; +	u8 *buf = msg->buf; -	intel_i2c_reset(dev_priv->dev); +	I915_WRITE(GMBUS1 + reg_offset, +		   GMBUS_CYCLE_WAIT | +		   (last ? GMBUS_CYCLE_STOP : 0) | +		   (len << GMBUS_BYTE_COUNT_SHIFT) | +		   (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | +		   GMBUS_SLAVE_READ | GMBUS_SW_RDY); +	POSTING_READ(GMBUS2 + reg_offset); +	do { +		u32 val, loop = 0; -	intel_i2c_quirk_set(dev_priv, true); -	set_data(bus, 1); -	set_clock(bus, 1); -	udelay(I2C_RISEFALL_TIME); +		if (wait_for(I915_READ(GMBUS2 + reg_offset) & +			     (GMBUS_SATOER | GMBUS_HW_RDY), +			     50)) +			return -ETIMEDOUT; +		if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) +			return -ENXIO; -	ret = i2c_bit_algo.master_xfer(&bus->adapter, msgs, num); +		val = I915_READ(GMBUS3 + reg_offset); +		do { +			*buf++ = val & 0xff; +			val >>= 8; +		} while (--len && ++loop < 4); +	} while (len); -	set_data(bus, 1); -	set_clock(bus, 1); -	intel_i2c_quirk_set(dev_priv, false); +	return 0; +} -	return ret; +static int +gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg, +		bool last) +{ +	int reg_offset = dev_priv->gpio_mmio_base; +	u16 len = msg->len; +	u8 *buf = msg->buf; +	u32 val, loop; + +	val = loop = 0; +	do { +		val |= *buf++ << (8 * loop); +	} while (--len && ++loop < 4); + +	I915_WRITE(GMBUS3 + reg_offset, val); +	I915_WRITE(GMBUS1 + reg_offset, +		   GMBUS_CYCLE_WAIT | +		   (last ? GMBUS_CYCLE_STOP : 0) | +		   (msg->len << GMBUS_BYTE_COUNT_SHIFT) | +		   (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | +		   GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); +	POSTING_READ(GMBUS2 + reg_offset); +	while (len) { +		if (wait_for(I915_READ(GMBUS2 + reg_offset) & +			     (GMBUS_SATOER | GMBUS_HW_RDY), +			     50)) +			return -ETIMEDOUT; +		if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) +			return -ENXIO; + +		val = loop = 0; +		do { +			val |= *buf++ << (8 * loop); +		} while (--len && ++loop < 4); + +		I915_WRITE(GMBUS3 + reg_offset, val); +		POSTING_READ(GMBUS2 + reg_offset); +	} +	return 0;  }  static int @@ -215,74 +293,31 @@ gmbus_xfer(struct i2c_adapter *adapter,  	mutex_lock(&dev_priv->gmbus_mutex);  	if (bus->force_bit) { -		ret = intel_i2c_quirk_xfer(bus, msgs, num); +		ret = i2c_bit_algo.master_xfer(adapter, msgs, num);  		goto out;  	} -	reg_offset = HAS_PCH_SPLIT(dev_priv->dev) ? PCH_GMBUS0 - GMBUS0 : 0; +	reg_offset = dev_priv->gpio_mmio_base;  	I915_WRITE(GMBUS0 + reg_offset, bus->reg0);  	for (i = 0; i < num; i++) { -		u16 len = msgs[i].len; -		u8 *buf = msgs[i].buf; +		bool last = i + 1 == num; -		if (msgs[i].flags & I2C_M_RD) { -			I915_WRITE(GMBUS1 + reg_offset, -				   GMBUS_CYCLE_WAIT | -				   (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | -				   (len << GMBUS_BYTE_COUNT_SHIFT) | -				   (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | -				   GMBUS_SLAVE_READ | GMBUS_SW_RDY); -			POSTING_READ(GMBUS2+reg_offset); -			do { -				u32 val, loop = 0; +		if (msgs[i].flags & I2C_M_RD) +			ret = gmbus_xfer_read(dev_priv, &msgs[i], last); +		else +			ret = gmbus_xfer_write(dev_priv, &msgs[i], last); -				if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) -					goto timeout; -				if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) -					goto clear_err; - -				val = I915_READ(GMBUS3 + reg_offset); -				do { -					*buf++ = val & 0xff; -					val >>= 8; -				} while (--len && ++loop < 4); -			} while (len); -		} else { -			u32 val, loop; - -			val = loop = 0; -			do { -				val |= *buf++ << (8 * loop); -			} while (--len && ++loop < 4); - -			I915_WRITE(GMBUS3 + reg_offset, val); -			I915_WRITE(GMBUS1 + reg_offset, -				   GMBUS_CYCLE_WAIT | -				   (i + 1 == num ? GMBUS_CYCLE_STOP : 0) | -				   (msgs[i].len << GMBUS_BYTE_COUNT_SHIFT) | -				   (msgs[i].addr << GMBUS_SLAVE_ADDR_SHIFT) | -				   GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); -			POSTING_READ(GMBUS2+reg_offset); - -			while (len) { -				if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) -					goto timeout; -				if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) -					goto clear_err; - -				val = loop = 0; -				do { -					val |= *buf++ << (8 * loop); -				} while (--len && ++loop < 4); - -				I915_WRITE(GMBUS3 + reg_offset, val); -				POSTING_READ(GMBUS2+reg_offset); -			} -		} +		if (ret == -ETIMEDOUT) +			goto timeout; +		if (ret == -ENXIO) +			goto clear_err; -		if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50)) +		if (!last && +		    wait_for(I915_READ(GMBUS2 + reg_offset) & +			     (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), +			     50))  			goto timeout;  		if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)  			goto clear_err; @@ -304,23 +339,21 @@ done:  	 * till then let it sleep.  	 */  	if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, 10)) -		DRM_INFO("GMBUS timed out waiting for idle\n"); +		DRM_INFO("GMBUS [%s] timed out waiting for idle\n", +			 bus->adapter.name);  	I915_WRITE(GMBUS0 + reg_offset, 0);  	ret = i;  	goto out;  timeout: -	DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", -		 bus->reg0 & 0xff, bus->adapter.name); +	DRM_INFO("GMBUS [%s] timed out, falling back to bit banging on pin %d\n", +		 bus->adapter.name, bus->reg0 & 0xff);  	I915_WRITE(GMBUS0 + reg_offset, 0);  	/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ -	if (!bus->has_gpio) { -		ret = -EIO; -	} else { -		bus->force_bit = true; -		ret = intel_i2c_quirk_xfer(bus, msgs, num); -	} +	bus->force_bit = true; +	ret = i2c_bit_algo.master_xfer(adapter, msgs, num); +  out:  	mutex_unlock(&dev_priv->gmbus_mutex);  	return ret; @@ -346,35 +379,26 @@ static const struct i2c_algorithm gmbus_algorithm = {   */  int intel_setup_gmbus(struct drm_device *dev)  { -	static const char *names[GMBUS_NUM_PORTS] = { -		"disabled", -		"ssc", -		"vga", -		"panel", -		"dpc", -		"dpb", -		"reserved", -		"dpd", -	};  	struct drm_i915_private *dev_priv = dev->dev_private;  	int ret, i; -	dev_priv->gmbus = kcalloc(GMBUS_NUM_PORTS, sizeof(struct intel_gmbus), -				  GFP_KERNEL); -	if (dev_priv->gmbus == NULL) -		return -ENOMEM; +	if (HAS_PCH_SPLIT(dev)) +		dev_priv->gpio_mmio_base = PCH_GPIOA - GPIOA; +	else +		dev_priv->gpio_mmio_base = 0;  	mutex_init(&dev_priv->gmbus_mutex);  	for (i = 0; i < GMBUS_NUM_PORTS; i++) {  		struct intel_gmbus *bus = &dev_priv->gmbus[i]; +		u32 port = i + 1; /* +1 to map gmbus index to pin pair */  		bus->adapter.owner = THIS_MODULE;  		bus->adapter.class = I2C_CLASS_DDC;  		snprintf(bus->adapter.name,  			 sizeof(bus->adapter.name),  			 "i915 gmbus %s", -			 names[i]); +			 gmbus_ports[i].name);  		bus->adapter.dev.parent = &dev->pdev->dev;  		bus->dev_priv = dev_priv; @@ -385,13 +409,9 @@ int intel_setup_gmbus(struct drm_device *dev)  			goto err;  		/* By default use a conservative clock rate */ -		bus->reg0 = i | GMBUS_RATE_100KHZ; - -		bus->has_gpio = intel_gpio_setup(bus, i); +		bus->reg0 = port | GMBUS_RATE_100KHZ; -		/* XXX force bit banging until GMBUS is fully debugged */ -		if (bus->has_gpio && IS_GEN2(dev)) -			bus->force_bit = true; +		intel_gpio_setup(bus, port);  	}  	intel_i2c_reset(dev_priv->dev); @@ -403,11 +423,18 @@ err:  		struct intel_gmbus *bus = &dev_priv->gmbus[i];  		i2c_del_adapter(&bus->adapter);  	} -	kfree(dev_priv->gmbus); -	dev_priv->gmbus = NULL;  	return ret;  } +struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, +					    unsigned port) +{ +	WARN_ON(!intel_gmbus_is_port_valid(port)); +	/* -1 to map pin pair to gmbus index */ +	return (intel_gmbus_is_port_valid(port)) ? +		&dev_priv->gmbus[port - 1].adapter : NULL; +} +  void intel_gmbus_set_speed(struct i2c_adapter *adapter, int speed)  {  	struct intel_gmbus *bus = to_intel_gmbus(adapter); @@ -419,8 +446,7 @@ void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit)  {  	struct intel_gmbus *bus = to_intel_gmbus(adapter); -	if (bus->has_gpio) -		bus->force_bit = force_bit; +	bus->force_bit = force_bit;  }  void intel_teardown_gmbus(struct drm_device *dev) @@ -435,7 +461,4 @@ void intel_teardown_gmbus(struct drm_device *dev)  		struct intel_gmbus *bus = &dev_priv->gmbus[i];  		i2c_del_adapter(&bus->adapter);  	} - -	kfree(dev_priv->gmbus); -	dev_priv->gmbus = NULL;  } diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 95db2e98822..17a4630cec8 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -474,7 +474,7 @@ static int intel_lvds_get_modes(struct drm_connector *connector)  static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)  { -	DRM_DEBUG_KMS("Skipping forced modeset for %s\n", id->ident); +	DRM_INFO("Skipping forced modeset for %s\n", id->ident);  	return 1;  } @@ -622,7 +622,7 @@ static const struct drm_encoder_funcs intel_lvds_enc_funcs = {  static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)  { -	DRM_DEBUG_KMS("Skipping LVDS initialization for %s\n", id->ident); +	DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);  	return 1;  } @@ -845,8 +845,8 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,  		    child->device_type != DEVICE_TYPE_LFP)  			continue; -		if (child->i2c_pin) -		    *i2c_pin = child->i2c_pin; +		if (intel_gmbus_is_port_valid(child->i2c_pin)) +			*i2c_pin = child->i2c_pin;  		/* However, we cannot trust the BIOS writers to populate  		 * the VBT correctly.  Since LVDS requires additional @@ -987,7 +987,8 @@ bool intel_lvds_init(struct drm_device *dev)  	 * preferred mode is the right one.  	 */  	intel_lvds->edid = drm_get_edid(connector, -					&dev_priv->gmbus[pin].adapter); +					intel_gmbus_get_adapter(dev_priv, +								pin));  	if (intel_lvds->edid) {  		if (drm_add_edid_modes(connector,  				       intel_lvds->edid)) { diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index d1928e79d9b..d67ec3a51e4 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -56,7 +56,8 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus)  		}  	}; -	return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2; +	return i2c_transfer(intel_gmbus_get_adapter(dev_priv, ddc_bus), +			    msgs, 2) == 2;  }  /** diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 289140bc83c..34929aeca66 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -25,6 +25,8 @@   *   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +  #include <linux/acpi.h>  #include <linux/acpi_io.h>  #include <acpi/video.h> @@ -355,7 +357,7 @@ static void intel_didl_outputs(struct drm_device *dev)  	}  	if (!acpi_video_bus) { -		printk(KERN_WARNING "No ACPI video bus found\n"); +		pr_warn("No ACPI video bus found\n");  		return;  	} diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 230a141dbea..cad45ff8251 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -28,6 +28,9 @@   *      Chris Wilson <chris@chris-wilson.co.uk>   */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/moduleparam.h>  #include "intel_drv.h"  #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */ @@ -171,7 +174,7 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)  		/* XXX add code here to query mode clock or hardware clock  		 * and program max PWM appropriately.  		 */ -		printk_once(KERN_WARNING "fixme: max PWM is zero.\n"); +		pr_warn_once("fixme: max PWM is zero\n");  		return 1;  	} @@ -191,6 +194,27 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)  	return max;  } +static int i915_panel_invert_brightness; +MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness " +	"(-1 force normal, 0 machine defaults, 1 force inversion), please " +	"report PCI device ID, subsystem vendor and subsystem device ID " +	"to dri-devel@lists.freedesktop.org, if your machine needs it. " +	"It will then be included in an upcoming module version."); +module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600); +static u32 intel_panel_compute_brightness(struct drm_device *dev, u32 val) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; + +	if (i915_panel_invert_brightness < 0) +		return val; + +	if (i915_panel_invert_brightness > 0 || +	    dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) +		return intel_panel_get_max_backlight(dev) - val; + +	return val; +} +  u32 intel_panel_get_backlight(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -211,6 +235,7 @@ u32 intel_panel_get_backlight(struct drm_device *dev)  		}  	} +	val = intel_panel_compute_brightness(dev, val);  	DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);  	return val;  } @@ -228,6 +253,7 @@ static void intel_panel_actually_set_backlight(struct drm_device *dev, u32 level  	u32 tmp;  	DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level); +	level = intel_panel_compute_brightness(dev, level);  	if (HAS_PCH_SPLIT(dev))  		return intel_pch_panel_set_backlight(dev, level); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index e25581a9f60..dfdb613752c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -290,9 +290,9 @@ static int init_ring_common(struct intel_ring_buffer *ring)  			| RING_VALID);  	/* If the head is still not zero, the ring is dead */ -	if ((I915_READ_CTL(ring) & RING_VALID) == 0 || -	    I915_READ_START(ring) != obj->gtt_offset || -	    (I915_READ_HEAD(ring) & HEAD_ADDR) != 0) { +	if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && +		     I915_READ_START(ring) == obj->gtt_offset && +		     (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) {  		DRM_ERROR("%s initialization failed "  				"ctl %08x head %08x tail %08x start %08x\n",  				ring->name, @@ -687,7 +687,7 @@ render_ring_get_irq(struct intel_ring_buffer *ring)  	spin_lock(&ring->irq_lock);  	if (ring->irq_refcount++ == 0) { -		if (HAS_PCH_SPLIT(dev)) +		if (INTEL_INFO(dev)->gen >= 5)  			ironlake_enable_irq(dev_priv,  					    GT_PIPE_NOTIFY | GT_USER_INTERRUPT);  		else @@ -706,7 +706,7 @@ render_ring_put_irq(struct intel_ring_buffer *ring)  	spin_lock(&ring->irq_lock);  	if (--ring->irq_refcount == 0) { -		if (HAS_PCH_SPLIT(dev)) +		if (INTEL_INFO(dev)->gen >= 5)  			ironlake_disable_irq(dev_priv,  					     GT_USER_INTERRUPT |  					     GT_PIPE_NOTIFY); @@ -788,10 +788,11 @@ ring_add_request(struct intel_ring_buffer *ring,  }  static bool -gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) +gen6_ring_get_irq(struct intel_ring_buffer *ring)  {  	struct drm_device *dev = ring->dev;  	drm_i915_private_t *dev_priv = dev->dev_private; +	u32 mask = ring->irq_enable;  	if (!dev->irq_enabled)  	       return false; @@ -803,9 +804,9 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)  	spin_lock(&ring->irq_lock);  	if (ring->irq_refcount++ == 0) { -		ring->irq_mask &= ~rflag; +		ring->irq_mask &= ~mask;  		I915_WRITE_IMR(ring, ring->irq_mask); -		ironlake_enable_irq(dev_priv, gflag); +		ironlake_enable_irq(dev_priv, mask);  	}  	spin_unlock(&ring->irq_lock); @@ -813,16 +814,17 @@ gen6_ring_get_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)  }  static void -gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag) +gen6_ring_put_irq(struct intel_ring_buffer *ring)  {  	struct drm_device *dev = ring->dev;  	drm_i915_private_t *dev_priv = dev->dev_private; +	u32 mask = ring->irq_enable;  	spin_lock(&ring->irq_lock);  	if (--ring->irq_refcount == 0) { -		ring->irq_mask |= rflag; +		ring->irq_mask |= mask;  		I915_WRITE_IMR(ring, ring->irq_mask); -		ironlake_disable_irq(dev_priv, gflag); +		ironlake_disable_irq(dev_priv, mask);  	}  	spin_unlock(&ring->irq_lock); @@ -1361,38 +1363,6 @@ gen6_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,  	return 0;  } -static bool -gen6_render_ring_get_irq(struct intel_ring_buffer *ring) -{ -	return gen6_ring_get_irq(ring, -				 GT_USER_INTERRUPT, -				 GEN6_RENDER_USER_INTERRUPT); -} - -static void -gen6_render_ring_put_irq(struct intel_ring_buffer *ring) -{ -	return gen6_ring_put_irq(ring, -				 GT_USER_INTERRUPT, -				 GEN6_RENDER_USER_INTERRUPT); -} - -static bool -gen6_bsd_ring_get_irq(struct intel_ring_buffer *ring) -{ -	return gen6_ring_get_irq(ring, -				 GT_GEN6_BSD_USER_INTERRUPT, -				 GEN6_BSD_USER_INTERRUPT); -} - -static void -gen6_bsd_ring_put_irq(struct intel_ring_buffer *ring) -{ -	return gen6_ring_put_irq(ring, -				 GT_GEN6_BSD_USER_INTERRUPT, -				 GEN6_BSD_USER_INTERRUPT); -} -  /* ring buffer for Video Codec for Gen6+ */  static const struct intel_ring_buffer gen6_bsd_ring = {  	.name			= "gen6 bsd ring", @@ -1404,8 +1374,9 @@ static const struct intel_ring_buffer gen6_bsd_ring = {  	.flush			= gen6_ring_flush,  	.add_request		= gen6_add_request,  	.get_seqno		= gen6_ring_get_seqno, -	.irq_get		= gen6_bsd_ring_get_irq, -	.irq_put		= gen6_bsd_ring_put_irq, +	.irq_enable		= GEN6_BSD_USER_INTERRUPT, +	.irq_get		= gen6_ring_get_irq, +	.irq_put		= gen6_ring_put_irq,  	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,  	.sync_to		= gen6_bsd_ring_sync_to,  	.semaphore_register	= {MI_SEMAPHORE_SYNC_VR, @@ -1416,22 +1387,6 @@ static const struct intel_ring_buffer gen6_bsd_ring = {  /* Blitter support (SandyBridge+) */ -static bool -blt_ring_get_irq(struct intel_ring_buffer *ring) -{ -	return gen6_ring_get_irq(ring, -				 GT_BLT_USER_INTERRUPT, -				 GEN6_BLITTER_USER_INTERRUPT); -} - -static void -blt_ring_put_irq(struct intel_ring_buffer *ring) -{ -	gen6_ring_put_irq(ring, -			  GT_BLT_USER_INTERRUPT, -			  GEN6_BLITTER_USER_INTERRUPT); -} -  static int blt_ring_flush(struct intel_ring_buffer *ring,  			  u32 invalidate, u32 flush)  { @@ -1463,8 +1418,9 @@ static const struct intel_ring_buffer gen6_blt_ring = {  	.flush			= blt_ring_flush,  	.add_request		= gen6_add_request,  	.get_seqno		= gen6_ring_get_seqno, -	.irq_get		= blt_ring_get_irq, -	.irq_put		= blt_ring_put_irq, +	.irq_get		= gen6_ring_get_irq, +	.irq_put		= gen6_ring_put_irq, +	.irq_enable		= GEN6_BLITTER_USER_INTERRUPT,  	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,  	.sync_to		= gen6_blt_ring_sync_to,  	.semaphore_register	= {MI_SEMAPHORE_SYNC_BR, @@ -1482,8 +1438,9 @@ int intel_init_render_ring_buffer(struct drm_device *dev)  	if (INTEL_INFO(dev)->gen >= 6) {  		ring->add_request = gen6_add_request;  		ring->flush = gen6_render_ring_flush; -		ring->irq_get = gen6_render_ring_get_irq; -		ring->irq_put = gen6_render_ring_put_irq; +		ring->irq_get = gen6_ring_get_irq; +		ring->irq_put = gen6_ring_put_irq; +		ring->irq_enable = GT_USER_INTERRUPT;  		ring->get_seqno = gen6_ring_get_seqno;  	} else if (IS_GEN5(dev)) {  		ring->add_request = pc_render_add_request; @@ -1506,8 +1463,9 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)  	*ring = render_ring;  	if (INTEL_INFO(dev)->gen >= 6) {  		ring->add_request = gen6_add_request; -		ring->irq_get = gen6_render_ring_get_irq; -		ring->irq_put = gen6_render_ring_put_irq; +		ring->irq_get = gen6_ring_get_irq; +		ring->irq_put = gen6_ring_put_irq; +		ring->irq_enable = GT_USER_INTERRUPT;  	} else if (IS_GEN5(dev)) {  		ring->add_request = pc_render_add_request;  		ring->get_seqno = pc_render_get_seqno; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index bc0365b8fa4..3488a5a127d 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -59,6 +59,7 @@ struct  intel_ring_buffer {  	spinlock_t	irq_lock;  	u32		irq_refcount;  	u32		irq_mask; +	u32		irq_enable;		/* IRQs enabled for this ring */  	u32		irq_seqno;		/* last seq seem at irq time */  	u32		trace_irq_seqno;  	u32		waiting_seqno; diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index e36b171c1e7..6898145b44c 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -41,7 +41,7 @@  #define SDVO_TMDS_MASK (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1)  #define SDVO_RGB_MASK  (SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1)  #define SDVO_LVDS_MASK (SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1) -#define SDVO_TV_MASK   (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0) +#define SDVO_TV_MASK   (SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_YPRPB0)  #define SDVO_OUTPUT_MASK (SDVO_TMDS_MASK | SDVO_RGB_MASK | SDVO_LVDS_MASK |\  			SDVO_TV_MASK) @@ -74,7 +74,7 @@ struct intel_sdvo {  	struct i2c_adapter ddc;  	/* Register for the SDVO device: SDVOB or SDVOC */ -	int sdvo_reg; +	uint32_t sdvo_reg;  	/* Active outputs controlled by this SDVO output */  	uint16_t controlled_output; @@ -114,6 +114,9 @@ struct intel_sdvo {  	 */  	bool is_tv; +	/* On different gens SDVOB is at different places. */ +	bool is_sdvob; +  	/* This is for current tv format name */  	int tv_format_index; @@ -403,8 +406,7 @@ static const struct _sdvo_cmd_name {  	SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HBUF_DATA),  }; -#define IS_SDVOB(reg)	(reg == SDVOB || reg == PCH_SDVOB) -#define SDVO_NAME(svdo) (IS_SDVOB((svdo)->sdvo_reg) ? "SDVOB" : "SDVOC") +#define SDVO_NAME(svdo) ((svdo)->is_sdvob ? "SDVOB" : "SDVOC")  static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,  				   const void *args, int args_len) @@ -1252,7 +1254,8 @@ intel_sdvo_get_analog_edid(struct drm_connector *connector)  	struct drm_i915_private *dev_priv = connector->dev->dev_private;  	return drm_get_edid(connector, -			    &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); +			    intel_gmbus_get_adapter(dev_priv, +						    dev_priv->crt_ddc_pin));  }  enum drm_connector_status @@ -1341,8 +1344,7 @@ intel_sdvo_detect(struct drm_connector *connector, bool force)  		return connector_status_unknown;  	/* add 30ms delay when the output type might be TV */ -	if (intel_sdvo->caps.output_flags & -	    (SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_CVBS0)) +	if (intel_sdvo->caps.output_flags & SDVO_TV_MASK)  		mdelay(30);  	if (!intel_sdvo_read_response(intel_sdvo, &response, 2)) @@ -1893,7 +1895,7 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,  {  	struct sdvo_device_mapping *mapping; -	if (IS_SDVOB(reg)) +	if (sdvo->is_sdvob)  		mapping = &(dev_priv->sdvo_mappings[0]);  	else  		mapping = &(dev_priv->sdvo_mappings[1]); @@ -1911,7 +1913,7 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,  	struct sdvo_device_mapping *mapping;  	u8 pin; -	if (IS_SDVOB(reg)) +	if (sdvo->is_sdvob)  		mapping = &dev_priv->sdvo_mappings[0];  	else  		mapping = &dev_priv->sdvo_mappings[1]; @@ -1920,12 +1922,12 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,  	if (mapping->initialized)  		pin = mapping->i2c_pin; -	if (pin < GMBUS_NUM_PORTS) { -		sdvo->i2c = &dev_priv->gmbus[pin].adapter; +	if (intel_gmbus_is_port_valid(pin)) { +		sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin);  		intel_gmbus_set_speed(sdvo->i2c, GMBUS_RATE_1MHZ);  		intel_gmbus_force_bit(sdvo->i2c, true);  	} else { -		sdvo->i2c = &dev_priv->gmbus[GMBUS_PORT_DPB].adapter; +		sdvo->i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB);  	}  } @@ -1936,12 +1938,12 @@ intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo, int device)  }  static u8 -intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg) +intel_sdvo_get_slave_addr(struct drm_device *dev, struct intel_sdvo *sdvo)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct sdvo_device_mapping *my_mapping, *other_mapping; -	if (IS_SDVOB(sdvo_reg)) { +	if (sdvo->is_sdvob) {  		my_mapping = &dev_priv->sdvo_mappings[0];  		other_mapping = &dev_priv->sdvo_mappings[1];  	} else { @@ -1966,7 +1968,7 @@ intel_sdvo_get_slave_addr(struct drm_device *dev, int sdvo_reg)  	/* No SDVO device info is found for another DVO port,  	 * so use mapping assumption we had before BIOS parsing.  	 */ -	if (IS_SDVOB(sdvo_reg)) +	if (sdvo->is_sdvob)  		return 0x70;  	else  		return 0x72; @@ -2191,6 +2193,10 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)  		if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_CVBS0))  			return false; +	if (flags & SDVO_OUTPUT_YPRPB0) +		if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_YPRPB0)) +			return false; +  	if (flags & SDVO_OUTPUT_RGB0)  		if (!intel_sdvo_analog_init(intel_sdvo, 0))  			return false; @@ -2482,7 +2488,7 @@ intel_sdvo_init_ddc_proxy(struct intel_sdvo *sdvo,  	return i2c_add_adapter(&sdvo->ddc) == 0;  } -bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) +bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_encoder *intel_encoder; @@ -2494,7 +2500,8 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)  		return false;  	intel_sdvo->sdvo_reg = sdvo_reg; -	intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, sdvo_reg) >> 1; +	intel_sdvo->is_sdvob = is_sdvob; +	intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1;  	intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg);  	if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev)) {  		kfree(intel_sdvo); @@ -2511,13 +2518,13 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)  		u8 byte;  		if (!intel_sdvo_read_byte(intel_sdvo, i, &byte)) { -			DRM_DEBUG_KMS("No SDVO device found on SDVO%c\n", -				      IS_SDVOB(sdvo_reg) ? 'B' : 'C'); +			DRM_DEBUG_KMS("No SDVO device found on %s\n", +				      SDVO_NAME(intel_sdvo));  			goto err;  		}  	} -	if (IS_SDVOB(sdvo_reg)) +	if (intel_sdvo->is_sdvob)  		dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS;  	else  		dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; @@ -2538,8 +2545,8 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg)  	if (intel_sdvo_output_setup(intel_sdvo,  				    intel_sdvo->caps.output_flags) != true) { -		DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", -			      IS_SDVOB(sdvo_reg) ? 'B' : 'C'); +		DRM_DEBUG_KMS("SDVO output failed to setup on %s\n", +			      SDVO_NAME(intel_sdvo));  		goto err;  	} diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 05f765ef546..ca12c709f3e 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1153,6 +1153,15 @@ intel_tv_detect_type(struct intel_tv *intel_tv,  		   DAC_B_0_7_V |  		   DAC_C_0_7_V); + +	/* +	 * The TV sense state should be cleared to zero on cantiga platform. Otherwise +	 * the TV is misdetected. This is hardware requirement. +	 */ +	if (IS_GM45(dev)) +		tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | +			    TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL); +  	I915_WRITE(TV_CTL, tv_ctl);  	I915_WRITE(TV_DAC, tv_dac);  	POSTING_READ(TV_DAC); diff --git a/include/drm/drmP.h b/include/drm/drmP.h index dd731043fec..10a5f371e65 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -1378,6 +1378,7 @@ extern int drm_remove_magic(struct drm_master *master, drm_magic_t magic);  /* Cache management (drm_cache.c) */  void drm_clflush_pages(struct page *pages[], unsigned long num_pages); +void drm_clflush_virt_range(char *addr, unsigned long length);  				/* Locking IOCTL support (drm_lock.h) */  extern int drm_lock(struct drm_device *dev, void *data, diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index da929bb5b78..f3f82242bf1 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -296,7 +296,8 @@ typedef struct drm_i915_irq_wait {  #define I915_PARAM_HAS_EXEC_CONSTANTS	 14  #define I915_PARAM_HAS_RELAXED_DELTA	 15  #define I915_PARAM_HAS_GEN7_SOL_RESET	 16 -#define I915_PARAM_HAS_LLC     	 17 +#define I915_PARAM_HAS_LLC     	 	 17 +#define I915_PARAM_HAS_ALIASING_PPGTT	 18  typedef struct drm_i915_getparam {  	int param; diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index cfaaa6949b8..c93a9a9bcd3 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -426,7 +426,7 @@ static inline int fault_in_pages_writeable(char __user *uaddr, int size)  		 */  		if (((unsigned long)uaddr & PAGE_MASK) !=  				((unsigned long)end & PAGE_MASK)) -		 	ret = __put_user(0, end); +			ret = __put_user(0, end);  	}  	return ret;  } @@ -445,13 +445,73 @@ static inline int fault_in_pages_readable(const char __user *uaddr, int size)  		if (((unsigned long)uaddr & PAGE_MASK) !=  				((unsigned long)end & PAGE_MASK)) { -		 	ret = __get_user(c, end); +			ret = __get_user(c, end);  			(void)c;  		}  	}  	return ret;  } +/* + * Multipage variants of the above prefault helpers, useful if more than + * PAGE_SIZE of data needs to be prefaulted. These are separate from the above + * functions (which only handle up to PAGE_SIZE) to avoid clobbering the + * filemap.c hotpaths. + */ +static inline int fault_in_multipages_writeable(char __user *uaddr, int size) +{ +	int ret; +	const char __user *end = uaddr + size - 1; + +	if (unlikely(size == 0)) +		return 0; + +	/* +	 * Writing zeroes into userspace here is OK, because we know that if +	 * the zero gets there, we'll be overwriting it. +	 */ +	while (uaddr <= end) { +		ret = __put_user(0, uaddr); +		if (ret != 0) +			return ret; +		uaddr += PAGE_SIZE; +	} + +	/* Check whether the range spilled into the next page. */ +	if (((unsigned long)uaddr & PAGE_MASK) == +			((unsigned long)end & PAGE_MASK)) +		ret = __put_user(0, end); + +	return ret; +} + +static inline int fault_in_multipages_readable(const char __user *uaddr, +					       int size) +{ +	volatile char c; +	int ret; +	const char __user *end = uaddr + size - 1; + +	if (unlikely(size == 0)) +		return 0; + +	while (uaddr <= end) { +		ret = __get_user(c, uaddr); +		if (ret != 0) +			return ret; +		uaddr += PAGE_SIZE; +	} + +	/* Check whether the range spilled into the next page. */ +	if (((unsigned long)uaddr & PAGE_MASK) == +			((unsigned long)end & PAGE_MASK)) { +		ret = __get_user(c, end); +		(void)c; +	} + +	return ret; +} +  int add_to_page_cache_locked(struct page *page, struct address_space *mapping,  				pgoff_t index, gfp_t gfp_mask);  int add_to_page_cache_lru(struct page *page, struct address_space *mapping,  |