diff options
Diffstat (limited to 'drivers')
30 files changed, 1531 insertions, 1108 deletions
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index dbd901e94ea..c8d9dcb15db 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -602,7 +602,6 @@ static int intel_gtt_init(void)  		iounmap(intel_private.registers);  		return -ENOMEM;  	} -	intel_private.base.gtt = intel_private.gtt;  	global_cache_flush();   /* FIXME: ? */ diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 2bf9670ba29..86272f04b82 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -102,20 +102,6 @@ int drm_mm_pre_get(struct drm_mm *mm)  }  EXPORT_SYMBOL(drm_mm_pre_get); -static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node) -{ -	return hole_node->start + hole_node->size; -} - -static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node) -{ -	struct drm_mm_node *next_node = -		list_entry(hole_node->node_list.next, struct drm_mm_node, -			   node_list); - -	return next_node->start; -} -  static void drm_mm_insert_helper(struct drm_mm_node *hole_node,  				 struct drm_mm_node *node,  				 unsigned long size, unsigned alignment, @@ -127,7 +113,7 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,  	unsigned long adj_start = hole_start;  	unsigned long adj_end = hole_end; -	BUG_ON(!hole_node->hole_follows || node->allocated); +	BUG_ON(node->allocated);  	if (mm->color_adjust)  		mm->color_adjust(hole_node, color, &adj_start, &adj_end); @@ -155,12 +141,57 @@ static void drm_mm_insert_helper(struct drm_mm_node *hole_node,  	BUG_ON(node->start + node->size > adj_end);  	node->hole_follows = 0; -	if (node->start + node->size < hole_end) { +	if (__drm_mm_hole_node_start(node) < hole_end) {  		list_add(&node->hole_stack, &mm->hole_stack);  		node->hole_follows = 1;  	}  } +struct drm_mm_node *drm_mm_create_block(struct drm_mm *mm, +					unsigned long start, +					unsigned long size, +					bool atomic) +{ +	struct drm_mm_node *hole, *node; +	unsigned long end = start + size; +	unsigned long hole_start; +	unsigned long hole_end; + +	drm_mm_for_each_hole(hole, mm, hole_start, hole_end) { +		if (hole_start > start || hole_end < end) +			continue; + +		node = drm_mm_kmalloc(mm, atomic); +		if (unlikely(node == NULL)) +			return NULL; + +		node->start = start; +		node->size = size; +		node->mm = mm; +		node->allocated = 1; + +		INIT_LIST_HEAD(&node->hole_stack); +		list_add(&node->node_list, &hole->node_list); + +		if (start == hole_start) { +			hole->hole_follows = 0; +			list_del_init(&hole->hole_stack); +		} + +		node->hole_follows = 0; +		if (end != hole_end) { +			list_add(&node->hole_stack, &mm->hole_stack); +			node->hole_follows = 1; +		} + +		return node; +	} + +	WARN(1, "no hole found for block 0x%lx + 0x%lx\n", start, size); +	return NULL; +} +EXPORT_SYMBOL(drm_mm_create_block); +  struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,  					     unsigned long size,  					     unsigned alignment, @@ -251,7 +282,7 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,  	BUG_ON(node->start + node->size > end);  	node->hole_follows = 0; -	if (node->start + node->size < hole_end) { +	if (__drm_mm_hole_node_start(node) < hole_end) {  		list_add(&node->hole_stack, &mm->hole_stack);  		node->hole_follows = 1;  	} @@ -325,12 +356,13 @@ void drm_mm_remove_node(struct drm_mm_node *node)  	    list_entry(node->node_list.prev, struct drm_mm_node, node_list);  	if (node->hole_follows) { -		BUG_ON(drm_mm_hole_node_start(node) -				== drm_mm_hole_node_end(node)); +		BUG_ON(__drm_mm_hole_node_start(node) == +		       __drm_mm_hole_node_end(node));  		list_del(&node->hole_stack);  	} else -		BUG_ON(drm_mm_hole_node_start(node) -				!= drm_mm_hole_node_end(node)); +		BUG_ON(__drm_mm_hole_node_start(node) != +		       __drm_mm_hole_node_end(node)); +  	if (!prev_node->hole_follows) {  		prev_node->hole_follows = 1; @@ -388,6 +420,8 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,  {  	struct drm_mm_node *entry;  	struct drm_mm_node *best; +	unsigned long adj_start; +	unsigned long adj_end;  	unsigned long best_size;  	BUG_ON(mm->scanned_blocks); @@ -395,17 +429,13 @@ struct drm_mm_node *drm_mm_search_free_generic(const struct drm_mm *mm,  	best = NULL;  	best_size = ~0UL; -	list_for_each_entry(entry, &mm->hole_stack, hole_stack) { -		unsigned long adj_start = drm_mm_hole_node_start(entry); -		unsigned long adj_end = drm_mm_hole_node_end(entry); - +	drm_mm_for_each_hole(entry, mm, adj_start, adj_end) {  		if (mm->color_adjust) {  			mm->color_adjust(entry, color, &adj_start, &adj_end);  			if (adj_end <= adj_start)  				continue;  		} -		BUG_ON(!entry->hole_follows);  		if (!check_free_hole(adj_start, adj_end, size, alignment))  			continue; @@ -432,6 +462,8 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,  {  	struct drm_mm_node *entry;  	struct drm_mm_node *best; +	unsigned long adj_start; +	unsigned long adj_end;  	unsigned long best_size;  	BUG_ON(mm->scanned_blocks); @@ -439,13 +471,11 @@ struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,  	best = NULL;  	best_size = ~0UL; -	list_for_each_entry(entry, &mm->hole_stack, hole_stack) { -		unsigned long adj_start = drm_mm_hole_node_start(entry) < start ? -			start : drm_mm_hole_node_start(entry); -		unsigned long adj_end = drm_mm_hole_node_end(entry) > end ? -			end : drm_mm_hole_node_end(entry); - -		BUG_ON(!entry->hole_follows); +	drm_mm_for_each_hole(entry, mm, adj_start, adj_end) { +		if (adj_start < start) +			adj_start = start; +		if (adj_end > end) +			adj_end = end;  		if (mm->color_adjust) {  			mm->color_adjust(entry, color, &adj_start, &adj_end); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e6a11ca85ea..f7d88e99ebf 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -102,7 +102,7 @@ static const char *cache_level_str(int type)  static void  describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)  { -	seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d %d%s%s%s", +	seq_printf(m, "%p: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s",  		   &obj->base,  		   get_pin_flag(obj),  		   get_tiling_flag(obj), @@ -124,6 +124,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)  	if (obj->gtt_space != NULL)  		seq_printf(m, " (gtt offset: %08x, size: %08x)",  			   obj->gtt_offset, (unsigned int)obj->gtt_space->size); +	if (obj->stolen) +		seq_printf(m, " (stolen: %08lx)", obj->stolen->start);  	if (obj->pin_mappable || obj->fault_mappable) {  		char s[3], *t = s;  		if (obj->pin_mappable) @@ -387,7 +389,7 @@ static void i915_ring_seqno_info(struct seq_file *m,  				 struct intel_ring_buffer *ring)  {  	if (ring->get_seqno) { -		seq_printf(m, "Current sequence (%s): %d\n", +		seq_printf(m, "Current sequence (%s): %u\n",  			   ring->name, ring->get_seqno(ring, false));  	}  } @@ -544,11 +546,11 @@ static int i915_hws_info(struct seq_file *m, void *data)  	struct drm_device *dev = node->minor->dev;  	drm_i915_private_t *dev_priv = dev->dev_private;  	struct intel_ring_buffer *ring; -	const volatile u32 __iomem *hws; +	const u32 *hws;  	int i;  	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data]; -	hws = (volatile u32 __iomem *)ring->status_page.page_addr; +	hws = ring->status_page.page_addr;  	if (hws == NULL)  		return 0; @@ -608,7 +610,7 @@ static void print_error_buffers(struct seq_file *m,  	seq_printf(m, "%s [%d]:\n", name, count);  	while (count--) { -		seq_printf(m, "  %08x %8u %04x %04x %x %x%s%s%s%s%s%s%s", +		seq_printf(m, "  %08x %8u %02x %02x %x %x%s%s%s%s%s%s%s",  			   err->gtt_offset,  			   err->size,  			   err->read_domains, @@ -841,6 +843,77 @@ static const struct file_operations i915_error_state_fops = {  	.release = i915_error_state_release,  }; +static ssize_t +i915_next_seqno_read(struct file *filp, +		 char __user *ubuf, +		 size_t max, +		 loff_t *ppos) +{ +	struct drm_device *dev = filp->private_data; +	drm_i915_private_t *dev_priv = dev->dev_private; +	char buf[80]; +	int len; +	int ret; + +	ret = mutex_lock_interruptible(&dev->struct_mutex); +	if (ret) +		return ret; + +	len = snprintf(buf, sizeof(buf), +		       "next_seqno :  0x%x\n", +		       dev_priv->next_seqno); + +	mutex_unlock(&dev->struct_mutex); + +	if (len > sizeof(buf)) +		len = sizeof(buf); + +	return simple_read_from_buffer(ubuf, max, ppos, buf, len); +} + +static ssize_t +i915_next_seqno_write(struct file *filp, +		      const char __user *ubuf, +		      size_t cnt, +		      loff_t *ppos) +{ +	struct drm_device *dev = filp->private_data; +	char buf[20]; +	u32 val = 1; +	int ret; + +	if (cnt > 0) { +		if (cnt > sizeof(buf) - 1) +			return -EINVAL; + +		if (copy_from_user(buf, ubuf, cnt)) +			return -EFAULT; +		buf[cnt] = 0; + +		ret = kstrtouint(buf, 0, &val); +		if (ret < 0) +			return ret; +	} + +	ret = mutex_lock_interruptible(&dev->struct_mutex); +	if (ret) +		return ret; + +	ret = i915_gem_set_seqno(dev, val); + +	mutex_unlock(&dev->struct_mutex); + +	return ret ?: cnt; +} + +static const struct file_operations i915_next_seqno_fops = { +	.owner = THIS_MODULE, +	.open = simple_open, +	.read = i915_next_seqno_read, +	.write = i915_next_seqno_write, +	.llseek = default_llseek, +}; +  static int i915_rstdby_delays(struct seq_file *m, void *unused)  {  	struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -1551,7 +1624,7 @@ static int i915_dpio_info(struct seq_file *m, void *data)  		return 0;  	} -	ret = mutex_lock_interruptible(&dev->mode_config.mutex); +	ret = mutex_lock_interruptible(&dev_priv->dpio_lock);  	if (ret)  		return ret; @@ -1580,7 +1653,7 @@ static int i915_dpio_info(struct seq_file *m, void *data)  	seq_printf(m, "DPIO_FASTCLK_DISABLE: 0x%08x\n",  		   intel_dpio_read(dev_priv, DPIO_FASTCLK_DISABLE)); -	mutex_unlock(&dev->mode_config.mutex); +	mutex_unlock(&dev_priv->dpio_lock);  	return 0;  } @@ -2105,6 +2178,12 @@ int i915_debugfs_init(struct drm_minor *minor)  	if (ret)  		return ret; +	ret = i915_debugfs_create(minor->debugfs_root, minor, +				 "i915_next_seqno", +				 &i915_next_seqno_fops); +	if (ret) +		return ret; +  	return drm_debugfs_create_files(i915_debugfs_list,  					I915_DEBUGFS_ENTRIES,  					minor->debugfs_root, minor); @@ -2128,6 +2207,8 @@ void i915_debugfs_cleanup(struct drm_minor *minor)  				 1, minor);  	drm_debugfs_remove_files((struct drm_info_list *) &i915_error_state_fops,  				 1, minor); +	drm_debugfs_remove_files((struct drm_info_list *) &i915_next_seqno_fops, +				 1, minor);  }  #endif /* CONFIG_DEBUG_FS */ diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 99daa896105..6d8a1dc7493 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1297,19 +1297,21 @@ static int i915_load_modeset_init(struct drm_device *dev)  	if (ret)  		goto cleanup_vga_switcheroo; +	ret = drm_irq_install(dev); +	if (ret) +		goto cleanup_gem_stolen; + +	/* Important: The output setup functions called by modeset_init need +	 * working irqs for e.g. gmbus and dp aux transfers. */  	intel_modeset_init(dev);  	ret = i915_gem_init(dev);  	if (ret) -		goto cleanup_gem_stolen; - -	intel_modeset_gem_init(dev); +		goto cleanup_irq;  	INIT_WORK(&dev_priv->console_resume_work, intel_console_resume); -	ret = drm_irq_install(dev); -	if (ret) -		goto cleanup_gem; +	intel_modeset_gem_init(dev);  	/* Always safe in the mode setting case. */  	/* FIXME: do pre/post-mode set stuff in core KMS code */ @@ -1317,7 +1319,25 @@ static int i915_load_modeset_init(struct drm_device *dev)  	ret = intel_fbdev_init(dev);  	if (ret) -		goto cleanup_irq; +		goto cleanup_gem; + +	/* Only enable hotplug handling once the fbdev is fully set up. */ +	intel_hpd_init(dev); + +	/* +	 * Some ports require correctly set-up hpd registers for detection to +	 * work properly (leading to ghost connected connector status), e.g. VGA +	 * on gm45.  Hence we can only set up the initial fbdev config after hpd +	 * irqs are fully enabled. Now we should scan for the initial config +	 * only once hotplug handling is enabled, but due to screwed-up locking +	 * around kms/fbdev init we can't protect the fdbev initial config +	 * scanning against hotplug events. Hence do this first and ignore the +	 * tiny window where we will loose hotplug notifactions. +	 */ +	intel_fbdev_initial_config(dev); + +	/* Only enable hotplug handling once the fbdev is fully set up. */ +	dev_priv->enable_hotplug_processing = true;  	drm_kms_helper_poll_init(dev); @@ -1326,13 +1346,13 @@ static int i915_load_modeset_init(struct drm_device *dev)  	return 0; -cleanup_irq: -	drm_irq_uninstall(dev);  cleanup_gem:  	mutex_lock(&dev->struct_mutex);  	i915_gem_cleanup_ringbuffer(dev);  	mutex_unlock(&dev->struct_mutex);  	i915_gem_cleanup_aliasing_ppgtt(dev); +cleanup_irq: +	drm_irq_uninstall(dev);  cleanup_gem_stolen:  	i915_gem_cleanup_stolen(dev);  cleanup_vga_switcheroo: @@ -1582,7 +1602,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	spin_lock_init(&dev_priv->irq_lock);  	spin_lock_init(&dev_priv->error_lock);  	spin_lock_init(&dev_priv->rps.lock); -	spin_lock_init(&dev_priv->dpio_lock); +	mutex_init(&dev_priv->dpio_lock);  	mutex_init(&dev_priv->rps.hw_lock); @@ -1614,9 +1634,6 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	intel_opregion_init(dev);  	acpi_video_register(); -	setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, -		    (unsigned long) dev); -  	if (IS_GEN5(dev))  		intel_gpu_ips_init(dev_priv); @@ -1723,9 +1740,6 @@ int i915_driver_unload(struct drm_device *dev)  		mutex_unlock(&dev->struct_mutex);  		i915_gem_cleanup_aliasing_ppgtt(dev);  		i915_gem_cleanup_stolen(dev); -		drm_mm_takedown(&dev_priv->mm.stolen); - -		intel_cleanup_overlay(dev);  		if (!I915_NEED_GFX_HWS(dev))  			i915_free_hws(dev); @@ -1738,6 +1752,10 @@ int i915_driver_unload(struct drm_device *dev)  	intel_teardown_mchbar(dev);  	destroy_workqueue(dev_priv->wq); +	pm_qos_remove_request(&dev_priv->pm_qos); + +	if (dev_priv->slab) +		kmem_cache_destroy(dev_priv->slab);  	pci_dev_put(dev_priv->bridge_dev);  	kfree(dev->dev_private); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 117265840b1..c8cbc32fe8d 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -565,6 +565,7 @@ static int __i915_drm_thaw(struct drm_device *dev)  		intel_modeset_init_hw(dev);  		intel_modeset_setup_hw_state(dev, false);  		drm_irq_install(dev); +		intel_hpd_init(dev);  	}  	intel_opregion_init(dev); @@ -870,6 +871,7 @@ int i915_reset(struct drm_device *dev)  		drm_irq_uninstall(dev);  		drm_irq_install(dev); +		intel_hpd_init(dev);  	} else {  		mutex_unlock(&dev->struct_mutex);  	} diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ed305957557..b1b1b7350ca 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -30,6 +30,8 @@  #ifndef _I915_DRV_H_  #define _I915_DRV_H_ +#include <uapi/drm/i915_drm.h> +  #include "i915_reg.h"  #include "intel_bios.h"  #include "intel_ringbuffer.h" @@ -40,6 +42,7 @@  #include <linux/backlight.h>  #include <linux/intel-iommu.h>  #include <linux/kref.h> +#include <linux/pm_qos.h>  /* General customization:   */ @@ -83,7 +86,12 @@ enum port {  };  #define port_name(p) ((p) + 'A') -#define I915_GEM_GPU_DOMAINS	(~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT)) +#define I915_GEM_GPU_DOMAINS \ +	(I915_GEM_DOMAIN_RENDER | \ +	 I915_GEM_DOMAIN_SAMPLER | \ +	 I915_GEM_DOMAIN_COMMAND | \ +	 I915_GEM_DOMAIN_INSTRUCTION | \ +	 I915_GEM_DOMAIN_VERTEX)  #define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++) @@ -101,6 +109,19 @@ struct intel_pch_pll {  };  #define I915_NUM_PLLS 2 +/* Used by dp and fdi links */ +struct intel_link_m_n { +	uint32_t	tu; +	uint32_t	gmch_m; +	uint32_t	gmch_n; +	uint32_t	link_m; +	uint32_t	link_n; +}; + +void intel_link_compute_m_n(int bpp, int nlanes, +			    int pixel_clock, int link_clock, +			    struct intel_link_m_n *m_n); +  struct intel_ddi_plls {  	int spll_refcount;  	int wrpll1_refcount; @@ -276,6 +297,7 @@ struct drm_i915_display_funcs {  			  struct drm_i915_gem_object *obj);  	int (*update_plane)(struct drm_crtc *crtc, struct drm_framebuffer *fb,  			    int x, int y); +	void (*hpd_irq_setup)(struct drm_device *dev);  	/* clock updates for mode set */  	/* cursor updates */  	/* render clock increase/decrease */ @@ -577,6 +599,9 @@ struct intel_gen6_power_mgmt {  	struct mutex hw_lock;  }; +/* defined intel_pm.c */ +extern spinlock_t mchdev_lock; +  struct intel_ilk_power_mgmt {  	u8 cur_delay;  	u8 min_delay; @@ -619,6 +644,7 @@ struct intel_l3_parity {  typedef struct drm_i915_private {  	struct drm_device *dev; +	struct kmem_cache *slab;  	const struct intel_device_info *info; @@ -633,10 +659,11 @@ typedef struct drm_i915_private {  	/** forcewake_count is protected by gt_lock */  	unsigned forcewake_count;  	/** gt_lock is also taken in irq contexts. */ -	struct spinlock gt_lock; +	spinlock_t gt_lock;  	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; @@ -646,9 +673,11 @@ typedef struct drm_i915_private {  	 */  	uint32_t gpio_mmio_base; +	wait_queue_head_t gmbus_wait_queue; +  	struct pci_dev *bridge_dev;  	struct intel_ring_buffer ring[I915_NUM_RINGS]; -	uint32_t next_seqno; +	uint32_t last_seqno, next_seqno;  	drm_dma_handle_t *status_page_dmah;  	struct resource mch_res; @@ -658,8 +687,11 @@ typedef struct drm_i915_private {  	/* protects the irq masks */  	spinlock_t irq_lock; +	/* To control wakeup latency, e.g. for irq-driven dp aux transfers. */ +	struct pm_qos_request pm_qos; +  	/* DPIO indirect register protection */ -	spinlock_t dpio_lock; +	struct mutex dpio_lock;  	/** Cached value of IMR to avoid reads in updating the bitfield */  	u32 pipestat[2]; @@ -669,6 +701,7 @@ typedef struct drm_i915_private {  	u32 hotplug_supported_mask;  	struct work_struct hotplug_work; +	bool enable_hotplug_processing;  	int num_pipe;  	int num_pch_pll; @@ -710,7 +743,6 @@ typedef struct drm_i915_private {  	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; @@ -771,6 +803,10 @@ typedef struct drm_i915_private {  		unsigned long gtt_start;  		unsigned long gtt_mappable_end;  		unsigned long gtt_end; +		unsigned long stolen_base; /* limited to low memory (32-bit) */ + +		/** "Graphics Stolen Memory" holds the global PTEs */ +		void __iomem *gsm;  		struct io_mapping *gtt_mapping;  		phys_addr_t gtt_base_addr; @@ -943,6 +979,8 @@ enum i915_cache_level {  	I915_CACHE_LLC_MLC, /* gen6+, in docs at least! */  }; +#define I915_GTT_RESERVED ((struct drm_mm_node *)0x1) +  struct drm_i915_gem_object_ops {  	/* Interface between the GEM object and its backing storage.  	 * get_pages() is called once prior to the use of the associated set @@ -968,6 +1006,8 @@ struct drm_i915_gem_object {  	/** Current space allocated to this object in the GTT, if any. */  	struct drm_mm_node *gtt_space; +	/** Stolen memory for this object, instead of being backed by shmem. */ +	struct drm_mm_node *stolen;  	struct list_head gtt_list;  	/** This object's place on the active/inactive lists */ @@ -1138,7 +1178,7 @@ struct drm_i915_gem_request {  struct drm_i915_file_private {  	struct { -		struct spinlock lock; +		spinlock_t lock;  		struct list_head request_list;  	} mm;  	struct idr context_idr; @@ -1224,6 +1264,8 @@ struct drm_i915_file_private {  #define HAS_PIPE_CONTROL(dev) (INTEL_INFO(dev)->gen >= 5) +#define HAS_DDI(dev)		(IS_HASWELL(dev)) +  #define INTEL_PCH_DEVICE_ID_MASK		0xff00  #define INTEL_PCH_IBX_DEVICE_ID_TYPE		0x3b00  #define INTEL_PCH_CPT_DEVICE_ID_TYPE		0x1c00 @@ -1320,6 +1362,7 @@ void i915_hangcheck_elapsed(unsigned long data);  void i915_handle_error(struct drm_device *dev, bool wedged);  extern void intel_irq_init(struct drm_device *dev); +extern void intel_hpd_init(struct drm_device *dev);  extern void intel_gt_init(struct drm_device *dev);  extern void intel_gt_reset(struct drm_device *dev); @@ -1388,12 +1431,15 @@ int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,  int i915_gem_wait_ioctl(struct drm_device *dev, void *data,  			struct drm_file *file_priv);  void i915_gem_load(struct drm_device *dev); +void *i915_gem_object_alloc(struct drm_device *dev); +void i915_gem_object_free(struct drm_i915_gem_object *obj);  int i915_gem_init_object(struct drm_gem_object *obj);  void i915_gem_object_init(struct drm_i915_gem_object *obj,  			 const struct drm_i915_gem_object_ops *ops);  struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,  						  size_t size);  void i915_gem_free_object(struct drm_gem_object *obj); +  int __must_check i915_gem_object_pin(struct drm_i915_gem_object *obj,  				     uint32_t alignment,  				     bool map_and_fenceable, @@ -1451,8 +1497,8 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)  	return (int32_t)(seq1 - seq2) >= 0;  } -extern int i915_gem_get_seqno(struct drm_device *dev, u32 *seqno); - +int __must_check i915_gem_get_seqno(struct drm_device *dev, u32 *seqno); +int __must_check i915_gem_set_seqno(struct drm_device *dev, u32 seqno);  int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj);  int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj); @@ -1559,10 +1605,9 @@ 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); +void i915_gem_init_global_gtt(struct drm_device *dev); +void i915_gem_setup_global_gtt(struct drm_device *dev, unsigned long start, +			       unsigned long mappable_end, unsigned long end);  int i915_gem_gtt_init(struct drm_device *dev);  void i915_gem_gtt_fini(struct drm_device *dev);  static inline void i915_gem_chipset_flush(struct drm_device *dev) @@ -1582,9 +1627,22 @@ int i915_gem_evict_everything(struct drm_device *dev);  /* i915_gem_stolen.c */  int i915_gem_init_stolen(struct drm_device *dev); +int i915_gem_stolen_setup_compression(struct drm_device *dev, int size); +void i915_gem_stolen_cleanup_compression(struct drm_device *dev);  void i915_gem_cleanup_stolen(struct drm_device *dev); +struct drm_i915_gem_object * +i915_gem_object_create_stolen(struct drm_device *dev, u32 size); +void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj);  /* i915_gem_tiling.c */ +inline static bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) +{ +	drm_i915_private_t *dev_priv = obj->base.dev->dev_private; + +	return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 && +		obj->tiling_mode != I915_TILING_NONE; +} +  void i915_gem_detect_bit_6_swizzle(struct drm_device *dev);  void i915_gem_object_do_bit_17_swizzle(struct drm_i915_gem_object *obj);  void i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index da3c82e301b..e6cc020ea32 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -163,8 +163,8 @@ i915_gem_init_ioctl(struct drm_device *dev, void *data,  		return -ENODEV;  	mutex_lock(&dev->struct_mutex); -	i915_gem_init_global_gtt(dev, args->gtt_start, -				 args->gtt_end, args->gtt_end); +	i915_gem_setup_global_gtt(dev, args->gtt_start, args->gtt_end, +				  args->gtt_end);  	mutex_unlock(&dev->struct_mutex);  	return 0; @@ -192,6 +192,18 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,  	return 0;  } +void *i915_gem_object_alloc(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	return kmem_cache_alloc(dev_priv->slab, GFP_KERNEL | __GFP_ZERO); +} + +void i915_gem_object_free(struct drm_i915_gem_object *obj) +{ +	struct drm_i915_private *dev_priv = obj->base.dev->dev_private; +	kmem_cache_free(dev_priv->slab, obj); +} +  static int  i915_gem_create(struct drm_file *file,  		struct drm_device *dev, @@ -215,7 +227,7 @@ i915_gem_create(struct drm_file *file,  	if (ret) {  		drm_gem_object_release(&obj->base);  		i915_gem_info_remove_obj(dev->dev_private, obj->base.size); -		kfree(obj); +		i915_gem_object_free(obj);  		return ret;  	} @@ -259,14 +271,6 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,  			       args->size, &args->handle);  } -static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) -{ -	drm_i915_private_t *dev_priv = obj->base.dev->dev_private; - -	return dev_priv->mm.bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 && -		obj->tiling_mode != I915_TILING_NONE; -} -  static inline int  __copy_to_user_swizzled(char __user *cpu_vaddr,  			const char *gpu_vaddr, int gpu_offset, @@ -407,7 +411,6 @@ i915_gem_shmem_pread(struct drm_device *dev,  	loff_t offset;  	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;  	struct scatterlist *sg; @@ -469,7 +472,6 @@ i915_gem_shmem_pread(struct drm_device *dev,  		if (ret == 0)  			goto next_page; -		hit_slowpath = 1;  		mutex_unlock(&dev->struct_mutex);  		if (!prefaulted) { @@ -502,12 +504,6 @@ next_page:  out:  	i915_gem_object_unpin_pages(obj); -	if (hit_slowpath) { -		/* Fixup: Kill any reinstated backing storage pages */ -		if (obj->madv == __I915_MADV_PURGED) -			i915_gem_object_truncate(obj); -	} -  	return ret;  } @@ -838,12 +834,13 @@ out:  	i915_gem_object_unpin_pages(obj);  	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) { +		/* +		 * Fixup: Flush cpu caches in case we didn't flush the dirty +		 * cachelines in-line while writing and the object moved +		 * out of the cpu write domain while we've dropped the lock. +		 */ +		if (!needs_clflush_after && +		    obj->base.write_domain != I915_GEM_DOMAIN_CPU) {  			i915_gem_clflush_object(obj);  			i915_gem_chipset_flush(dev);  		} @@ -1344,6 +1341,12 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  	trace_i915_gem_object_fault(obj, page_offset, true, write); +	/* Access to snoopable pages through the GTT is incoherent. */ +	if (obj->cache_level != I915_CACHE_NONE && !HAS_LLC(dev)) { +		ret = -EINVAL; +		goto unlock; +	} +  	/* Now bind it into the GTT if needed */  	ret = i915_gem_object_pin(obj, 0, true, false);  	if (ret) @@ -1933,30 +1936,24 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)  }  static int -i915_gem_handle_seqno_wrap(struct drm_device *dev) +i915_gem_init_seqno(struct drm_device *dev, u32 seqno)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_ring_buffer *ring;  	int ret, i, j; -	/* The hardware uses various monotonic 32-bit counters, if we -	 * detect that they will wraparound we need to idle the GPU -	 * and reset those counters. -	 */ -	ret = 0; +	/* Carefully retire all requests without writing to the rings */  	for_each_ring(ring, dev_priv, i) { -		for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++) -			ret |= ring->sync_seqno[j] != 0; +		ret = intel_ring_idle(ring); +		if (ret) +			return ret;  	} -	if (ret == 0) -		return ret; - -	ret = i915_gpu_idle(dev); -	if (ret) -		return ret; -  	i915_gem_retire_requests(dev); + +	/* Finally reset hw state */  	for_each_ring(ring, dev_priv, i) { +		intel_ring_init_seqno(ring, seqno); +  		for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++)  			ring->sync_seqno[j] = 0;  	} @@ -1964,6 +1961,32 @@ i915_gem_handle_seqno_wrap(struct drm_device *dev)  	return 0;  } +int i915_gem_set_seqno(struct drm_device *dev, u32 seqno) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	int ret; + +	if (seqno == 0) +		return -EINVAL; + +	/* HWS page needs to be set less than what we +	 * will inject to ring +	 */ +	ret = i915_gem_init_seqno(dev, seqno - 1); +	if (ret) +		return ret; + +	/* Carefully set the last_seqno value so that wrap +	 * detection still works +	 */ +	dev_priv->next_seqno = seqno; +	dev_priv->last_seqno = seqno - 1; +	if (dev_priv->last_seqno == 0) +		dev_priv->last_seqno--; + +	return 0; +} +  int  i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)  { @@ -1971,14 +1994,14 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)  	/* reserve 0 for non-seqno */  	if (dev_priv->next_seqno == 0) { -		int ret = i915_gem_handle_seqno_wrap(dev); +		int ret = i915_gem_init_seqno(dev, 0);  		if (ret)  			return ret;  		dev_priv->next_seqno = 1;  	} -	*seqno = dev_priv->next_seqno++; +	*seqno = dev_priv->last_seqno = dev_priv->next_seqno++;  	return 0;  } @@ -2648,7 +2671,7 @@ static void i915_gem_write_fence(struct drm_device *dev, int reg,  	case 4: i965_write_fence_reg(dev, reg, obj); break;  	case 3: i915_write_fence_reg(dev, reg, obj); break;  	case 2: i830_write_fence_reg(dev, reg, obj); break; -	default: break; +	default: BUG();  	}  } @@ -2823,7 +2846,7 @@ static bool i915_gem_valid_gtt_space(struct drm_device *dev,  	/* On non-LLC machines we have to be careful when putting differing  	 * types of snoopable memory together to avoid the prefetcher -	 * crossing memory domains and dieing. +	 * crossing memory domains and dying.  	 */  	if (HAS_LLC(dev))  		return true; @@ -3698,14 +3721,14 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,  {  	struct drm_i915_gem_object *obj;  	struct address_space *mapping; -	u32 mask; +	gfp_t mask; -	obj = kzalloc(sizeof(*obj), GFP_KERNEL); +	obj = i915_gem_object_alloc(dev);  	if (obj == NULL)  		return NULL;  	if (drm_gem_object_init(dev, &obj->base, size) != 0) { -		kfree(obj); +		i915_gem_object_free(obj);  		return NULL;  	} @@ -3777,6 +3800,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)  	obj->pages_pin_count = 0;  	i915_gem_object_put_pages(obj);  	i915_gem_object_free_mmap_offset(obj); +	i915_gem_object_release_stolen(obj);  	BUG_ON(obj->pages); @@ -3787,7 +3811,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)  	i915_gem_info_remove_obj(dev_priv, obj->base.size);  	kfree(obj->bit_17); -	kfree(obj); +	i915_gem_object_free(obj);  }  int @@ -3883,8 +3907,10 @@ void i915_gem_init_swizzling(struct drm_device *dev)  	I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL);  	if (IS_GEN6(dev))  		I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB)); -	else +	else if (IS_GEN7(dev))  		I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB)); +	else +		BUG();  }  static bool @@ -3919,6 +3945,8 @@ i915_gem_init_hw(struct drm_device *dev)  	i915_gem_init_swizzling(dev); +	dev_priv->next_seqno = dev_priv->last_seqno = (u32)~0 - 0x1000; +  	ret = intel_init_render_ring_buffer(dev);  	if (ret)  		return ret; @@ -3935,8 +3963,6 @@ i915_gem_init_hw(struct drm_device *dev)  			goto cleanup_bsd_ring;  	} -	dev_priv->next_seqno = 1; -  	/*  	 * XXX: There was some w/a described somewhere suggesting loading  	 * contexts before PPGTT. @@ -3953,58 +3979,13 @@ cleanup_render_ring:  	return ret;  } -static bool -intel_enable_ppgtt(struct drm_device *dev) -{ -	if (i915_enable_ppgtt >= 0) -		return i915_enable_ppgtt; - -#ifdef CONFIG_INTEL_IOMMU -	/* Disable ppgtt on SNB if VT-d is on. */ -	if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) -		return false; -#endif - -	return true; -} -  int i915_gem_init(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; -	unsigned long gtt_size, mappable_size;  	int ret; -	gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT; -	mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; -  	mutex_lock(&dev->struct_mutex); -	if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(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; - -		i915_gem_init_global_gtt(dev, 0, mappable_size, gtt_size); - -		ret = i915_gem_init_aliasing_ppgtt(dev); -		if (ret) { -			mutex_unlock(&dev->struct_mutex); -			return ret; -		} -	} else { -		/* Let GEM Manage all of the aperture. -		 * -		 * However, leave one page at the end still bound to the scratch -		 * page.  There are a number of places where the hardware -		 * apparently prefetches past the end of the object, and we've -		 * seen multiple hangs with the GPU head pointer stuck in a -		 * batchbuffer bound at the last page of the aperture.  One page -		 * should be enough to keep any prefetching inside of the -		 * aperture. -		 */ -		i915_gem_init_global_gtt(dev, 0, mappable_size, -					 gtt_size); -	} - +	i915_gem_init_global_gtt(dev);  	ret = i915_gem_init_hw(dev);  	mutex_unlock(&dev->struct_mutex);  	if (ret) { @@ -4105,8 +4086,14 @@ init_ring_lists(struct intel_ring_buffer *ring)  void  i915_gem_load(struct drm_device *dev)  { -	int i;  	drm_i915_private_t *dev_priv = dev->dev_private; +	int i; + +	dev_priv->slab = +		kmem_cache_create("i915_gem_object", +				  sizeof(struct drm_i915_gem_object), 0, +				  SLAB_HWCACHE_ALIGN, +				  NULL);  	INIT_LIST_HEAD(&dev_priv->mm.active_list);  	INIT_LIST_HEAD(&dev_priv->mm.inactive_list); diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index abeaafef6d7..6a5af682862 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -281,8 +281,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,  	if (IS_ERR(attach))  		return ERR_CAST(attach); - -	obj = kzalloc(sizeof(*obj), GFP_KERNEL); +	obj = i915_gem_object_alloc(dev);  	if (obj == NULL) {  		ret = -ENOMEM;  		goto fail_detach; @@ -290,7 +289,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,  	ret = drm_gem_private_object_init(dev, &obj->base, dma_buf->size);  	if (ret) { -		kfree(obj); +		i915_gem_object_free(obj);  		goto fail_detach;  	} diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d6a994a0739..163bb52bd3b 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -150,17 +150,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj,  			  reloc->write_domain);  		return ret;  	} -	if (unlikely(reloc->write_domain && target_obj->pending_write_domain && -		     reloc->write_domain != target_obj->pending_write_domain)) { -		DRM_DEBUG("Write domain conflict: " -			  "obj %p target %d offset %d " -			  "new %08x old %08x\n", -			  obj, reloc->target_handle, -			  (int) reloc->offset, -			  reloc->write_domain, -			  target_obj->pending_write_domain); -		return ret; -	}  	target_obj->pending_read_domains |= reloc->read_domains;  	target_obj->pending_write_domain |= reloc->write_domain; @@ -602,44 +591,11 @@ err:  }  static int -i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips) -{ -	u32 plane, flip_mask; -	int ret; - -	/* Check for any pending flips. As we only maintain a flip queue depth -	 * of 1, we can simply insert a WAIT for the next display flip prior -	 * to executing the batch and avoid stalling the CPU. -	 */ - -	for (plane = 0; flips >> plane; plane++) { -		if (((flips >> plane) & 1) == 0) -			continue; - -		if (plane) -			flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; -		else -			flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; - -		ret = intel_ring_begin(ring, 2); -		if (ret) -			return ret; - -		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask); -		intel_ring_emit(ring, MI_NOOP); -		intel_ring_advance(ring); -	} - -	return 0; -} - -static int  i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,  				struct list_head *objects)  {  	struct drm_i915_gem_object *obj;  	uint32_t flush_domains = 0; -	uint32_t flips = 0;  	int ret;  	list_for_each_entry(obj, objects, exec_list) { @@ -650,18 +606,9 @@ i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,  		if (obj->base.write_domain & I915_GEM_DOMAIN_CPU)  			i915_gem_clflush_object(obj); -		if (obj->base.pending_write_domain) -			flips |= atomic_read(&obj->pending_flip); -  		flush_domains |= obj->base.write_domain;  	} -	if (flips) { -		ret = i915_gem_execbuffer_wait_for_flips(ring, flips); -		if (ret) -			return ret; -	} -  	if (flush_domains & I915_GEM_DOMAIN_CPU)  		i915_gem_chipset_flush(ring->dev); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 2c150dee78a..a4af0f79e97 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -282,7 +282,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev)  	uint32_t pd_offset;  	struct intel_ring_buffer *ring;  	struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; -	uint32_t __iomem *pd_addr; +	gtt_pte_t __iomem *pd_addr;  	uint32_t pd_entry;  	int i; @@ -290,7 +290,7 @@ void i915_gem_init_ppgtt(struct drm_device *dev)  		return; -	pd_addr = dev_priv->mm.gtt->gtt + ppgtt->pd_offset/sizeof(uint32_t); +	pd_addr = (gtt_pte_t __iomem*)dev_priv->mm.gsm + ppgtt->pd_offset/sizeof(gtt_pte_t);  	for (i = 0; i < ppgtt->num_pd_entries; i++) {  		dma_addr_t pt_addr; @@ -367,7 +367,7 @@ static void i915_ggtt_clear_range(struct drm_device *dev,  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	gtt_pte_t scratch_pte; -	gtt_pte_t __iomem *gtt_base = dev_priv->mm.gtt->gtt + first_entry; +	gtt_pte_t __iomem *gtt_base = (gtt_pte_t __iomem *) dev_priv->mm.gsm + first_entry;  	const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry;  	int i; @@ -432,7 +432,8 @@ static void gen6_ggtt_bind_object(struct drm_i915_gem_object *obj,  	struct scatterlist *sg = st->sgl;  	const int first_entry = obj->gtt_space->start >> PAGE_SHIFT;  	const int max_entries = dev_priv->mm.gtt->gtt_total_entries - first_entry; -	gtt_pte_t __iomem *gtt_entries = dev_priv->mm.gtt->gtt + first_entry; +	gtt_pte_t __iomem *gtt_entries = +		(gtt_pte_t __iomem *)dev_priv->mm.gsm + first_entry;  	int unused, i = 0;  	unsigned int len, m = 0;  	dma_addr_t addr; @@ -525,26 +526,103 @@ static void i915_gtt_color_adjust(struct drm_mm_node *node,  	}  } -void i915_gem_init_global_gtt(struct drm_device *dev, -			      unsigned long start, -			      unsigned long mappable_end, -			      unsigned long end) +void i915_gem_setup_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; +	struct drm_mm_node *entry; +	struct drm_i915_gem_object *obj; +	unsigned long hole_start, hole_end; -	/* Substract the guard page ... */ +	/* Subtract the guard page ... */  	drm_mm_init(&dev_priv->mm.gtt_space, start, end - start - PAGE_SIZE);  	if (!HAS_LLC(dev))  		dev_priv->mm.gtt_space.color_adjust = i915_gtt_color_adjust; +	/* Mark any preallocated objects as occupied */ +	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) { +		DRM_DEBUG_KMS("reserving preallocated space: %x + %zx\n", +			      obj->gtt_offset, obj->base.size); + +		BUG_ON(obj->gtt_space != I915_GTT_RESERVED); +		obj->gtt_space = drm_mm_create_block(&dev_priv->mm.gtt_space, +						     obj->gtt_offset, +						     obj->base.size, +						     false); +		obj->has_global_gtt_mapping = 1; +	} +  	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. */ -	i915_ggtt_clear_range(dev, start / PAGE_SIZE, (end-start) / PAGE_SIZE); +	/* Clear any non-preallocated blocks */ +	drm_mm_for_each_hole(entry, &dev_priv->mm.gtt_space, +			     hole_start, hole_end) { +		DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", +			      hole_start, hole_end); +		i915_ggtt_clear_range(dev, +				      hole_start / PAGE_SIZE, +				      (hole_end-hole_start) / PAGE_SIZE); +	} + +	/* And finally clear the reserved guard page */ +	i915_ggtt_clear_range(dev, end / PAGE_SIZE - 1, 1); +} + +static bool +intel_enable_ppgtt(struct drm_device *dev) +{ +	if (i915_enable_ppgtt >= 0) +		return i915_enable_ppgtt; + +#ifdef CONFIG_INTEL_IOMMU +	/* Disable ppgtt on SNB if VT-d is on. */ +	if (INTEL_INFO(dev)->gen == 6 && intel_iommu_gfx_mapped) +		return false; +#endif + +	return true; +} + +void i915_gem_init_global_gtt(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	unsigned long gtt_size, mappable_size; +	int ret; + +	gtt_size = dev_priv->mm.gtt->gtt_total_entries << PAGE_SHIFT; +	mappable_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; + +	if (intel_enable_ppgtt(dev) && HAS_ALIASING_PPGTT(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; + +		i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size); + +		ret = i915_gem_init_aliasing_ppgtt(dev); +		if (ret) { +			mutex_unlock(&dev->struct_mutex); +			return; +		} +	} else { +		/* Let GEM Manage all of the aperture. +		 * +		 * However, leave one page at the end still bound to the scratch +		 * page.  There are a number of places where the hardware +		 * apparently prefetches past the end of the object, and we've +		 * seen multiple hangs with the GPU head pointer stuck in a +		 * batchbuffer bound at the last page of the aperture.  One page +		 * should be enough to keep any prefetching inside of the +		 * aperture. +		 */ +		i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size); +	}  }  static int setup_scratch_page(struct drm_device *dev) @@ -674,9 +752,9 @@ int i915_gem_gtt_init(struct drm_device *dev)  		goto err_out;  	} -	dev_priv->mm.gtt->gtt = ioremap_wc(gtt_bus_addr, -					   dev_priv->mm.gtt->gtt_total_entries * sizeof(gtt_pte_t)); -	if (!dev_priv->mm.gtt->gtt) { +	dev_priv->mm.gsm = ioremap_wc(gtt_bus_addr, +				      dev_priv->mm.gtt->gtt_total_entries * sizeof(gtt_pte_t)); +	if (!dev_priv->mm.gsm) {  		DRM_ERROR("Failed to map the gtt page table\n");  		teardown_scratch_page(dev);  		ret = -ENOMEM; @@ -700,7 +778,7 @@ err_out:  void i915_gem_gtt_fini(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; -	iounmap(dev_priv->mm.gtt->gtt); +	iounmap(dev_priv->mm.gsm);  	teardown_scratch_page(dev);  	if (INTEL_INFO(dev)->gen < 6)  		intel_gmch_remove(); diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 8e91083b126..f21ae17e298 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -42,85 +42,73 @@   * for is a boon.   */ -#define PTE_ADDRESS_MASK		0xfffff000 -#define PTE_ADDRESS_MASK_HIGH		0x000000f0 /* i915+ */ -#define PTE_MAPPING_TYPE_UNCACHED	(0 << 1) -#define PTE_MAPPING_TYPE_DCACHE		(1 << 1) /* i830 only */ -#define PTE_MAPPING_TYPE_CACHED		(3 << 1) -#define PTE_MAPPING_TYPE_MASK		(3 << 1) -#define PTE_VALID			(1 << 0) - -/** - * i915_stolen_to_phys - take an offset into stolen memory and turn it into - *                       a physical one - * @dev: drm device - * @offset: address to translate - * - * Some chip functions require allocations from stolen space and need the - * physical address of the memory in question. - */ -static unsigned long i915_stolen_to_phys(struct drm_device *dev, u32 offset) +static unsigned long i915_stolen_to_physical(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct pci_dev *pdev = dev_priv->bridge_dev;  	u32 base; -#if 0  	/* On the machines I have tested the Graphics Base of Stolen Memory -	 * is unreliable, so compute the base by subtracting the stolen memory -	 * from the Top of Low Usable DRAM which is where the BIOS places -	 * the graphics stolen memory. +	 * is unreliable, so on those compute the base by subtracting the +	 * stolen memory from the Top of Low Usable DRAM which is where the +	 * BIOS places the graphics stolen memory. +	 * +	 * On gen2, the layout is slightly different with the Graphics Segment +	 * immediately following Top of Memory (or Top of Usable DRAM). Note +	 * it appears that TOUD is only reported by 865g, so we just use the +	 * top of memory as determined by the e820 probe. +	 * +	 * XXX gen2 requires an unavailable symbol and 945gm fails with +	 * its value of TOLUD.  	 */ -	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) { -		/* top 32bits are reserved = 0 */ +	base = 0; +	if (INTEL_INFO(dev)->gen >= 6) { +		/* Read Base Data of Stolen Memory Register (BDSM) directly. +		 * Note that there is also a MCHBAR miror at 0x1080c0 or +		 * we could use device 2:0x5c instead. +		*/ +		pci_read_config_dword(pdev, 0xB0, &base); +		base &= ~4095; /* lower bits used for locking register */ +	} else if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) { +		/* Read Graphics Base of Stolen Memory directly */  		pci_read_config_dword(pdev, 0xA4, &base); -	} else { -		/* XXX presume 8xx is the same as i915 */ -		pci_bus_read_config_dword(pdev->bus, 2, 0x5C, &base); -	} -#else -	if (INTEL_INFO(dev)->gen > 3 || IS_G33(dev)) { -		u16 val; -		pci_read_config_word(pdev, 0xb0, &val); -		base = val >> 4 << 20; -	} else { +#if 0 +	} else if (IS_GEN3(dev)) {  		u8 val; +		/* Stolen is immediately below Top of Low Usable DRAM */  		pci_read_config_byte(pdev, 0x9c, &val);  		base = val >> 3 << 27; -	} -	base -= dev_priv->mm.gtt->stolen_size; +		base -= dev_priv->mm.gtt->stolen_size; +	} else { +		/* Stolen is immediately above Top of Memory */ +		base = max_low_pfn_mapped << PAGE_SHIFT;  #endif +	} -	return base + offset; -} - -static void i915_warn_stolen(struct drm_device *dev) -{ -	DRM_INFO("not enough stolen space for compressed buffer, disabling\n"); -	DRM_INFO("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n"); +	return base;  } -static void i915_setup_compression(struct drm_device *dev, int size) +static int i915_setup_compression(struct drm_device *dev, int size)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct drm_mm_node *compressed_fb, *uninitialized_var(compressed_llb); -	unsigned long cfb_base; -	unsigned long ll_base = 0; - -	/* Just in case the BIOS is doing something questionable. */ -	intel_disable_fbc(dev); -	compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0); +	/* Try to over-allocate to reduce reallocations and fragmentation */ +	compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, +					   size <<= 1, 4096, 0); +	if (!compressed_fb) +		compressed_fb = drm_mm_search_free(&dev_priv->mm.stolen, +						   size >>= 1, 4096, 0);  	if (compressed_fb)  		compressed_fb = drm_mm_get_block(compressed_fb, size, 4096);  	if (!compressed_fb)  		goto err; -	cfb_base = i915_stolen_to_phys(dev, compressed_fb->start); -	if (!cfb_base) -		goto err_fb; - -	if (!(IS_GM45(dev) || HAS_PCH_SPLIT(dev))) { +	if (HAS_PCH_SPLIT(dev)) +		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start); +	else if (IS_GM45(dev)) { +		I915_WRITE(DPFC_CB_BASE, compressed_fb->start); +	} else {  		compressed_llb = drm_mm_search_free(&dev_priv->mm.stolen,  						    4096, 4096, 0);  		if (compressed_llb) @@ -129,73 +117,206 @@ static void i915_setup_compression(struct drm_device *dev, int size)  		if (!compressed_llb)  			goto err_fb; -		ll_base = i915_stolen_to_phys(dev, compressed_llb->start); -		if (!ll_base) -			goto err_llb; +		dev_priv->compressed_llb = compressed_llb; + +		I915_WRITE(FBC_CFB_BASE, +			   dev_priv->mm.stolen_base + compressed_fb->start); +		I915_WRITE(FBC_LL_BASE, +			   dev_priv->mm.stolen_base + compressed_llb->start);  	} +	dev_priv->compressed_fb = compressed_fb;  	dev_priv->cfb_size = size; -	dev_priv->compressed_fb = compressed_fb; -	if (HAS_PCH_SPLIT(dev)) -		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start); -	else if (IS_GM45(dev)) { -		I915_WRITE(DPFC_CB_BASE, compressed_fb->start); -	} else { -		I915_WRITE(FBC_CFB_BASE, cfb_base); -		I915_WRITE(FBC_LL_BASE, ll_base); -		dev_priv->compressed_llb = compressed_llb; -	} +	DRM_DEBUG_KMS("reserved %d bytes of contiguous stolen space for FBC\n", +		      size); -	DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", -		      cfb_base, ll_base, size >> 20); -	return; +	return 0; -err_llb: -	drm_mm_put_block(compressed_llb);  err_fb:  	drm_mm_put_block(compressed_fb);  err: -	dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; -	i915_warn_stolen(dev); +	return -ENOSPC;  } -static void i915_cleanup_compression(struct drm_device *dev) +int i915_gem_stolen_setup_compression(struct drm_device *dev, int size)  {  	struct drm_i915_private *dev_priv = dev->dev_private; -	drm_mm_put_block(dev_priv->compressed_fb); +	if (dev_priv->mm.stolen_base == 0) +		return -ENODEV; + +	if (size < dev_priv->cfb_size) +		return 0; + +	/* Release any current block */ +	i915_gem_stolen_cleanup_compression(dev); + +	return i915_setup_compression(dev, size); +} + +void i915_gem_stolen_cleanup_compression(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; + +	if (dev_priv->cfb_size == 0) +		return; + +	if (dev_priv->compressed_fb) +		drm_mm_put_block(dev_priv->compressed_fb); +  	if (dev_priv->compressed_llb)  		drm_mm_put_block(dev_priv->compressed_llb); + +	dev_priv->cfb_size = 0;  }  void i915_gem_cleanup_stolen(struct drm_device *dev)  { -	if (I915_HAS_FBC(dev) && i915_powersave) -		i915_cleanup_compression(dev); +	struct drm_i915_private *dev_priv = dev->dev_private; + +	i915_gem_stolen_cleanup_compression(dev); +	drm_mm_takedown(&dev_priv->mm.stolen);  }  int i915_gem_init_stolen(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; -	unsigned long prealloc_size = dev_priv->mm.gtt->stolen_size; + +	dev_priv->mm.stolen_base = i915_stolen_to_physical(dev); +	if (dev_priv->mm.stolen_base == 0) +		return 0; + +	DRM_DEBUG_KMS("found %d bytes of stolen memory at %08lx\n", +		      dev_priv->mm.gtt->stolen_size, dev_priv->mm.stolen_base);  	/* Basic memrange allocator for stolen space */ -	drm_mm_init(&dev_priv->mm.stolen, 0, prealloc_size); +	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->mm.gtt->stolen_size); + +	return 0; +} -	/* Try to set up FBC with a reasonable compressed buffer size */ -	if (I915_HAS_FBC(dev) && i915_powersave) { -		int cfb_size; +static struct sg_table * +i915_pages_create_for_stolen(struct drm_device *dev, +			     u32 offset, u32 size) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct sg_table *st; +	struct scatterlist *sg; + +	DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size); +	BUG_ON(offset > dev_priv->mm.gtt->stolen_size - size); -		/* Leave 1M for line length buffer & misc. */ +	/* We hide that we have no struct page backing our stolen object +	 * by wrapping the contiguous physical allocation with a fake +	 * dma mapping in a single scatterlist. +	 */ + +	st = kmalloc(sizeof(*st), GFP_KERNEL); +	if (st == NULL) +		return NULL; -		/* Try to get a 32M buffer... */ -		if (prealloc_size > (36*1024*1024)) -			cfb_size = 32*1024*1024; -		else /* fall back to 7/8 of the stolen space */ -			cfb_size = prealloc_size * 7 / 8; -		i915_setup_compression(dev, cfb_size); +	if (sg_alloc_table(st, 1, GFP_KERNEL)) { +		kfree(st); +		return NULL;  	} -	return 0; +	sg = st->sgl; +	sg->offset = offset; +	sg->length = size; + +	sg_dma_address(sg) = (dma_addr_t)dev_priv->mm.stolen_base + offset; +	sg_dma_len(sg) = size; + +	return st; +} + +static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj) +{ +	BUG(); +	return -EINVAL; +} + +static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj) +{ +	/* Should only be called during free */ +	sg_free_table(obj->pages); +	kfree(obj->pages); +} + +static const struct drm_i915_gem_object_ops i915_gem_object_stolen_ops = { +	.get_pages = i915_gem_object_get_pages_stolen, +	.put_pages = i915_gem_object_put_pages_stolen, +}; + +static struct drm_i915_gem_object * +_i915_gem_object_create_stolen(struct drm_device *dev, +			       struct drm_mm_node *stolen) +{ +	struct drm_i915_gem_object *obj; + +	obj = i915_gem_object_alloc(dev); +	if (obj == NULL) +		return NULL; + +	if (drm_gem_private_object_init(dev, &obj->base, stolen->size)) +		goto cleanup; + +	i915_gem_object_init(obj, &i915_gem_object_stolen_ops); + +	obj->pages = i915_pages_create_for_stolen(dev, +						  stolen->start, stolen->size); +	if (obj->pages == NULL) +		goto cleanup; + +	obj->has_dma_mapping = true; +	obj->pages_pin_count = 1; +	obj->stolen = stolen; + +	obj->base.write_domain = I915_GEM_DOMAIN_GTT; +	obj->base.read_domains = I915_GEM_DOMAIN_GTT; +	obj->cache_level = I915_CACHE_NONE; + +	return obj; + +cleanup: +	i915_gem_object_free(obj); +	return NULL; +} + +struct drm_i915_gem_object * +i915_gem_object_create_stolen(struct drm_device *dev, u32 size) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct drm_i915_gem_object *obj; +	struct drm_mm_node *stolen; + +	if (dev_priv->mm.stolen_base == 0) +		return NULL; + +	DRM_DEBUG_KMS("creating stolen object: size=%x\n", size); +	if (size == 0) +		return NULL; + +	stolen = drm_mm_search_free(&dev_priv->mm.stolen, size, 4096, 0); +	if (stolen) +		stolen = drm_mm_get_block(stolen, size, 4096); +	if (stolen == NULL) +		return NULL; + +	obj = _i915_gem_object_create_stolen(dev, stolen); +	if (obj) +		return obj; + +	drm_mm_put_block(stolen); +	return NULL; +} + +void +i915_gem_object_release_stolen(struct drm_i915_gem_object *obj) +{ +	if (obj->stolen) { +		drm_mm_put_block(obj->stolen); +		obj->stolen = NULL; +	}  } diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index cedbfd7b3df..65f1d4f3f77 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -396,6 +396,18 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,  	/* we have to maintain this existing ABI... */  	args->stride = obj->stride;  	args->tiling_mode = obj->tiling_mode; + +	/* Try to preallocate memory required to save swizzling on put-pages */ +	if (i915_gem_object_needs_bit17_swizzle(obj)) { +		if (obj->bit_17 == NULL) { +			obj->bit_17 = kmalloc(BITS_TO_LONGS(obj->base.size >> PAGE_SHIFT) * +					      sizeof(long), GFP_KERNEL); +		} +	} else { +		kfree(obj->bit_17); +		obj->bit_17 = NULL; +	} +  	drm_gem_object_unreference(&obj->base);  	mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2220dec3e5d..6689a61b02a 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -287,6 +287,10 @@ static void i915_hotplug_work_func(struct work_struct *work)  	struct drm_mode_config *mode_config = &dev->mode_config;  	struct intel_encoder *encoder; +	/* HPD irq before everything is fully set up. */ +	if (!dev_priv->enable_hotplug_processing) +		return; +  	mutex_lock(&mode_config->mutex);  	DRM_DEBUG_KMS("running encoder hotplug functions\n"); @@ -300,9 +304,6 @@ static void i915_hotplug_work_func(struct work_struct *work)  	drm_helper_hpd_irq_event(dev);  } -/* defined intel_pm.c */ -extern spinlock_t mchdev_lock; -  static void ironlake_handle_rps_change(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = dev->dev_private; @@ -524,6 +525,20 @@ static void gen6_queue_rps_work(struct drm_i915_private *dev_priv,  	queue_work(dev_priv->wq, &dev_priv->rps.work);  } +static void gmbus_irq_handler(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = (drm_i915_private_t *) dev->dev_private; + +	wake_up_all(&dev_priv->gmbus_wait_queue); +} + +static void dp_aux_irq_handler(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = (drm_i915_private_t *) dev->dev_private; + +	wake_up_all(&dev_priv->gmbus_wait_queue); +} +  static irqreturn_t valleyview_irq_handler(int irq, void *arg)  {  	struct drm_device *dev = (struct drm_device *) arg; @@ -533,7 +548,6 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)  	unsigned long irqflags;  	int pipe;  	u32 pipe_stats[I915_MAX_PIPES]; -	bool blc_event;  	atomic_inc(&dev_priv->irq_received); @@ -590,8 +604,8 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)  			I915_READ(PORT_HOTPLUG_STAT);  		} -		if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) -			blc_event = true; +		if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) +			gmbus_irq_handler(dev);  		if (pm_iir & GEN6_PM_DEFERRED_EVENTS)  			gen6_queue_rps_work(dev_priv, pm_iir); @@ -618,8 +632,11 @@ static void ibx_irq_handler(struct drm_device *dev, u32 pch_iir)  				 (pch_iir & SDE_AUDIO_POWER_MASK) >>  				 SDE_AUDIO_POWER_SHIFT); +	if (pch_iir & SDE_AUX_MASK) +		dp_aux_irq_handler(dev); +  	if (pch_iir & SDE_GMBUS) -		DRM_DEBUG_DRIVER("PCH GMBUS interrupt\n"); +		gmbus_irq_handler(dev);  	if (pch_iir & SDE_AUDIO_HDCP_MASK)  		DRM_DEBUG_DRIVER("PCH HDCP audio interrupt\n"); @@ -662,10 +679,10 @@ static void cpt_irq_handler(struct drm_device *dev, u32 pch_iir)  				 SDE_AUDIO_POWER_SHIFT_CPT);  	if (pch_iir & SDE_AUX_MASK_CPT) -		DRM_DEBUG_DRIVER("AUX channel interrupt\n"); +		dp_aux_irq_handler(dev);  	if (pch_iir & SDE_GMBUS_CPT) -		DRM_DEBUG_DRIVER("PCH GMBUS interrupt\n"); +		gmbus_irq_handler(dev);  	if (pch_iir & SDE_AUDIO_CP_REQ_CPT)  		DRM_DEBUG_DRIVER("Audio CP request interrupt\n"); @@ -703,6 +720,9 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg)  	de_iir = I915_READ(DEIIR);  	if (de_iir) { +		if (de_iir & DE_AUX_CHANNEL_A_IVB) +			dp_aux_irq_handler(dev); +  		if (de_iir & DE_GSE_IVB)  			intel_opregion_gse_intr(dev); @@ -758,7 +778,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)  	struct drm_device *dev = (struct drm_device *) arg;  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	int ret = IRQ_NONE; -	u32 de_iir, gt_iir, de_ier, pch_iir, pm_iir; +	u32 de_iir, gt_iir, de_ier, pm_iir;  	atomic_inc(&dev_priv->irq_received); @@ -769,11 +789,9 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)  	de_iir = I915_READ(DEIIR);  	gt_iir = I915_READ(GTIIR); -	pch_iir = I915_READ(SDEIIR);  	pm_iir = I915_READ(GEN6_PMIIR); -	if (de_iir == 0 && gt_iir == 0 && pch_iir == 0 && -	    (!IS_GEN6(dev) || pm_iir == 0)) +	if (de_iir == 0 && gt_iir == 0 && (!IS_GEN6(dev) || pm_iir == 0))  		goto done;  	ret = IRQ_HANDLED; @@ -783,6 +801,9 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)  	else  		snb_gt_irq_handler(dev, dev_priv, gt_iir); +	if (de_iir & DE_AUX_CHANNEL_A) +		dp_aux_irq_handler(dev); +  	if (de_iir & DE_GSE)  		intel_opregion_gse_intr(dev); @@ -804,10 +825,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)  	/* check event from PCH */  	if (de_iir & DE_PCH_EVENT) { +		u32 pch_iir = I915_READ(SDEIIR); +  		if (HAS_PCH_CPT(dev))  			cpt_irq_handler(dev, pch_iir);  		else  			ibx_irq_handler(dev, pch_iir); + +		/* should clear PCH hotplug event before clear CPU irq */ +		I915_WRITE(SDEIIR, pch_iir);  	}  	if (IS_GEN5(dev) &&  de_iir & DE_PCU_EVENT) @@ -816,8 +842,6 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg)  	if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS)  		gen6_queue_rps_work(dev_priv, pm_iir); -	/* should clear PCH hotplug event before clear CPU irq */ -	I915_WRITE(SDEIIR, pch_iir);  	I915_WRITE(GTIIR, gt_iir);  	I915_WRITE(DEIIR, de_iir);  	I915_WRITE(GEN6_PMIIR, pm_iir); @@ -928,6 +952,14 @@ i915_error_object_create(struct drm_i915_private *dev_priv,  						     reloc_offset);  			memcpy_fromio(d, s, PAGE_SIZE);  			io_mapping_unmap_atomic(s); +		} else if (src->stolen) { +			unsigned long offset; + +			offset = dev_priv->mm.stolen_base; +			offset += src->stolen->start; +			offset += i << PAGE_SHIFT; + +			memcpy_fromio(d, (void __iomem *) offset, PAGE_SIZE);  		} else {  			struct page *page;  			void *s; @@ -1074,6 +1106,8 @@ static void i915_gem_record_fences(struct drm_device *dev,  			error->fence[i] = I915_READ(FENCE_REG_830_0 + (i * 4));  		break; +	default: +		BUG();  	}  } @@ -1854,7 +1888,8 @@ static int ironlake_irq_postinstall(struct drm_device *dev)  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	/* enable kind of interrupts always enabled */  	u32 display_mask = DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | -			   DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE; +			   DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE | +			   DE_AUX_CHANNEL_A;  	u32 render_irqs;  	u32 hotplug_mask; @@ -1888,12 +1923,15 @@ static int ironlake_irq_postinstall(struct drm_device *dev)  		hotplug_mask = (SDE_CRT_HOTPLUG_CPT |  				SDE_PORTB_HOTPLUG_CPT |  				SDE_PORTC_HOTPLUG_CPT | -				SDE_PORTD_HOTPLUG_CPT); +				SDE_PORTD_HOTPLUG_CPT | +				SDE_GMBUS_CPT | +				SDE_AUX_MASK_CPT);  	} else {  		hotplug_mask = (SDE_CRT_HOTPLUG |  				SDE_PORTB_HOTPLUG |  				SDE_PORTC_HOTPLUG |  				SDE_PORTD_HOTPLUG | +				SDE_GMBUS |  				SDE_AUX_MASK);  	} @@ -1924,7 +1962,8 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)  		DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | DE_PCH_EVENT_IVB |  		DE_PLANEC_FLIP_DONE_IVB |  		DE_PLANEB_FLIP_DONE_IVB | -		DE_PLANEA_FLIP_DONE_IVB; +		DE_PLANEA_FLIP_DONE_IVB | +		DE_AUX_CHANNEL_A_IVB;  	u32 render_irqs;  	u32 hotplug_mask; @@ -1953,7 +1992,9 @@ static int ivybridge_irq_postinstall(struct drm_device *dev)  	hotplug_mask = (SDE_CRT_HOTPLUG_CPT |  			SDE_PORTB_HOTPLUG_CPT |  			SDE_PORTC_HOTPLUG_CPT | -			SDE_PORTD_HOTPLUG_CPT); +			SDE_PORTD_HOTPLUG_CPT | +			SDE_GMBUS_CPT | +			SDE_AUX_MASK_CPT);  	dev_priv->pch_irq_mask = ~hotplug_mask;  	I915_WRITE(SDEIIR, I915_READ(SDEIIR)); @@ -1970,7 +2011,6 @@ static int valleyview_irq_postinstall(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	u32 enable_mask; -	u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN);  	u32 pipestat_enable = PLANE_FLIP_DONE_INT_EN_VLV;  	u32 render_irqs;  	u16 msid; @@ -1999,6 +2039,9 @@ static int valleyview_irq_postinstall(struct drm_device *dev)  	msid |= (1<<14);  	pci_write_config_word(dev_priv->dev->pdev, 0x98, msid); +	I915_WRITE(PORT_HOTPLUG_EN, 0); +	POSTING_READ(PORT_HOTPLUG_EN); +  	I915_WRITE(VLV_IMR, dev_priv->irq_mask);  	I915_WRITE(VLV_IER, enable_mask);  	I915_WRITE(VLV_IIR, 0xffffffff); @@ -2007,6 +2050,7 @@ static int valleyview_irq_postinstall(struct drm_device *dev)  	POSTING_READ(VLV_IER);  	i915_enable_pipestat(dev_priv, 0, pipestat_enable); +	i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE);  	i915_enable_pipestat(dev_priv, 1, pipestat_enable);  	I915_WRITE(VLV_IIR, 0xffffffff); @@ -2027,6 +2071,15 @@ static int valleyview_irq_postinstall(struct drm_device *dev)  #endif  	I915_WRITE(VLV_MASTER_IER, MASTER_INTERRUPT_ENABLE); + +	return 0; +} + +static void valleyview_hpd_irq_setup(struct drm_device *dev) +{ +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); +  	/* Note HDMI and DP share bits */  	if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)  		hotplug_en |= HDMIB_HOTPLUG_INT_EN; @@ -2044,8 +2097,6 @@ static int valleyview_irq_postinstall(struct drm_device *dev)  	}  	I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); - -	return 0;  }  static void valleyview_irq_uninstall(struct drm_device *dev) @@ -2275,6 +2326,9 @@ static int i915_irq_postinstall(struct drm_device *dev)  		I915_USER_INTERRUPT;  	if (I915_HAS_HOTPLUG(dev)) { +		I915_WRITE(PORT_HOTPLUG_EN, 0); +		POSTING_READ(PORT_HOTPLUG_EN); +  		/* Enable in IER... */  		enable_mask |= I915_DISPLAY_PORT_INTERRUPT;  		/* and unmask in IMR */ @@ -2285,8 +2339,18 @@ static int i915_irq_postinstall(struct drm_device *dev)  	I915_WRITE(IER, enable_mask);  	POSTING_READ(IER); +	intel_opregion_enable_asle(dev); + +	return 0; +} + +static void i915_hpd_irq_setup(struct drm_device *dev) +{ +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	u32 hotplug_en; +  	if (I915_HAS_HOTPLUG(dev)) { -		u32 hotplug_en = I915_READ(PORT_HOTPLUG_EN); +		hotplug_en = I915_READ(PORT_HOTPLUG_EN);  		if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS)  			hotplug_en |= HDMIB_HOTPLUG_INT_EN; @@ -2307,10 +2371,6 @@ static int i915_irq_postinstall(struct drm_device *dev)  		I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);  	} - -	intel_opregion_enable_asle(dev); - -	return 0;  }  static irqreturn_t i915_irq_handler(int irq, void *arg) @@ -2470,7 +2530,6 @@ static void i965_irq_preinstall(struct drm_device * dev)  static int i965_irq_postinstall(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; -	u32 hotplug_en;  	u32 enable_mask;  	u32 error_mask; @@ -2491,6 +2550,7 @@ static int i965_irq_postinstall(struct drm_device *dev)  	dev_priv->pipestat[0] = 0;  	dev_priv->pipestat[1] = 0; +	i915_enable_pipestat(dev_priv, 0, PIPE_GMBUS_EVENT_ENABLE);  	/*  	 * Enable some error detection, note the instruction error mask @@ -2511,6 +2571,19 @@ static int i965_irq_postinstall(struct drm_device *dev)  	I915_WRITE(IER, enable_mask);  	POSTING_READ(IER); +	I915_WRITE(PORT_HOTPLUG_EN, 0); +	POSTING_READ(PORT_HOTPLUG_EN); + +	intel_opregion_enable_asle(dev); + +	return 0; +} + +static void i965_hpd_irq_setup(struct drm_device *dev) +{ +	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; +	u32 hotplug_en; +  	/* Note HDMI and DP share hotplug bits */  	hotplug_en = 0;  	if (dev_priv->hotplug_supported_mask & HDMIB_HOTPLUG_INT_STATUS) @@ -2545,10 +2618,6 @@ static int i965_irq_postinstall(struct drm_device *dev)  	/* Ignore TV since it's buggy */  	I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); - -	intel_opregion_enable_asle(dev); - -	return 0;  }  static irqreturn_t i965_irq_handler(int irq, void *arg) @@ -2644,6 +2713,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)  		if (blc_event || (iir & I915_ASLE_INTERRUPT))  			intel_opregion_asle_intr(dev); +		if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) +			gmbus_irq_handler(dev); +  		/* With MSI, interrupts are only generated when iir  		 * transitions from zero to nonzero.  If another bit got  		 * set while we were handling the existing iir bits, then @@ -2699,6 +2771,11 @@ void intel_irq_init(struct drm_device *dev)  	INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work);  	INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); +	setup_timer(&dev_priv->hangcheck_timer, i915_hangcheck_elapsed, +		    (unsigned long) dev); + +	pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); +  	dev->driver->get_vblank_counter = i915_get_vblank_counter;  	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */  	if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) { @@ -2719,7 +2796,8 @@ void intel_irq_init(struct drm_device *dev)  		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)) { +		dev_priv->display.hpd_irq_setup = valleyview_hpd_irq_setup; +	} else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) {  		/* Share pre & uninstall handlers with ILK/SNB */  		dev->driver->irq_handler = ivybridge_irq_handler;  		dev->driver->irq_preinstall = ironlake_irq_preinstall; @@ -2727,14 +2805,6 @@ void intel_irq_init(struct drm_device *dev)  		dev->driver->irq_uninstall = ironlake_irq_uninstall;  		dev->driver->enable_vblank = ivybridge_enable_vblank;  		dev->driver->disable_vblank = ivybridge_disable_vblank; -	} else if (IS_HASWELL(dev)) { -		/* Share interrupts handling with IVB */ -		dev->driver->irq_handler = ivybridge_irq_handler; -		dev->driver->irq_preinstall = ironlake_irq_preinstall; -		dev->driver->irq_postinstall = ivybridge_irq_postinstall; -		dev->driver->irq_uninstall = ironlake_irq_uninstall; -		dev->driver->enable_vblank = ivybridge_enable_vblank; -		dev->driver->disable_vblank = ivybridge_disable_vblank;  	} else if (HAS_PCH_SPLIT(dev)) {  		dev->driver->irq_handler = ironlake_irq_handler;  		dev->driver->irq_preinstall = ironlake_irq_preinstall; @@ -2753,13 +2823,23 @@ void intel_irq_init(struct drm_device *dev)  			dev->driver->irq_postinstall = i915_irq_postinstall;  			dev->driver->irq_uninstall = i915_irq_uninstall;  			dev->driver->irq_handler = i915_irq_handler; +			dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup;  		} else {  			dev->driver->irq_preinstall = i965_irq_preinstall;  			dev->driver->irq_postinstall = i965_irq_postinstall;  			dev->driver->irq_uninstall = i965_irq_uninstall;  			dev->driver->irq_handler = i965_irq_handler; +			dev_priv->display.hpd_irq_setup = i965_hpd_irq_setup;  		}  		dev->driver->enable_vblank = i915_enable_vblank;  		dev->driver->disable_vblank = i915_disable_vblank;  	}  } + +void intel_hpd_init(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; + +	if (dev_priv->display.hpd_irq_setup) +		dev_priv->display.hpd_irq_setup(dev); +} diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 186ee5c85b5..3b039f4268e 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -142,6 +142,7 @@  #define   VGA_MSR_CGA_MODE (1<<0)  #define VGA_SR_INDEX 0x3c4 +#define SR01			1  #define VGA_SR_DATA 0x3c5  #define VGA_AR_INDEX 0x3c0 @@ -940,23 +941,6 @@  #define   DPLL_LOCK_VLV			(1<<15)  #define   DPLL_INTEGRATED_CLOCK_VLV	(1<<13) -#define SRX_INDEX		0x3c4 -#define SRX_DATA		0x3c5 -#define SR01			1 -#define SR01_SCREEN_OFF		(1<<5) - -#define PPCR			0x61204 -#define PPCR_ON			(1<<0) - -#define DVOB			0x61140 -#define DVOB_ON			(1<<31) -#define DVOC			0x61160 -#define DVOC_ON			(1<<31) -#define LVDS			0x61180 -#define LVDS_ON			(1<<31) - -/* Scratch pad debug 0 reg: - */  #define   DPLL_FPA01_P1_POST_DIV_MASK_I830	0x001f0000  /*   * The i830 generation, in LVDS mode, defines P1 as the bit number set within @@ -1893,8 +1877,6 @@  #define   PFIT_SCALING_PILLAR	(2 << 26)  #define   PFIT_SCALING_LETTER	(3 << 26)  #define PFIT_PGM_RATIOS	0x61234 -#define   PFIT_VERT_SCALE_MASK			0xfff00000 -#define   PFIT_HORIZ_SCALE_MASK			0x0000fff0  /* Pre-965 */  #define		PFIT_VERT_SCALE_SHIFT		20  #define		PFIT_VERT_SCALE_MASK		0xfff00000 @@ -2668,11 +2650,11 @@  #define   PIPECONF_INTERLACED_DBL_ILK		(4 << 21) /* ilk/snb only */  #define   PIPECONF_PFIT_PF_INTERLACED_DBL_ILK	(5 << 21) /* ilk/snb only */  #define   PIPECONF_CXSR_DOWNCLOCK	(1<<16) -#define   PIPECONF_BPP_MASK	(0x000000e0) -#define   PIPECONF_BPP_8	(0<<5) -#define   PIPECONF_BPP_10	(1<<5) -#define   PIPECONF_BPP_6	(2<<5) -#define   PIPECONF_BPP_12	(3<<5) +#define   PIPECONF_BPC_MASK	(0x7 << 5) +#define   PIPECONF_8BPC		(0<<5) +#define   PIPECONF_10BPC	(1<<5) +#define   PIPECONF_6BPC		(2<<5) +#define   PIPECONF_12BPC	(3<<5)  #define   PIPECONF_DITHER_EN	(1<<4)  #define   PIPECONF_DITHER_TYPE_MASK (0x0000000c)  #define   PIPECONF_DITHER_TYPE_SP (0<<2) @@ -2716,11 +2698,6 @@  #define   PIPE_START_VBLANK_INTERRUPT_STATUS	(1UL<<2) /* 965 or later */  #define   PIPE_VBLANK_INTERRUPT_STATUS		(1UL<<1)  #define   PIPE_OVERLAY_UPDATED_STATUS		(1UL<<0) -#define   PIPE_BPC_MASK				(7 << 5) /* Ironlake */ -#define   PIPE_8BPC				(0 << 5) -#define   PIPE_10BPC				(1 << 5) -#define   PIPE_6BPC				(2 << 5) -#define   PIPE_12BPC				(3 << 5)  #define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC)  #define PIPECONF(tran) _TRANSCODER(tran, _PIPEACONF, _PIPEBCONF) @@ -3578,27 +3555,30 @@  #define PORTD_PULSE_DURATION_6ms        (2 << 18)  #define PORTD_PULSE_DURATION_100ms      (3 << 18)  #define PORTD_PULSE_DURATION_MASK	(3 << 18) -#define PORTD_HOTPLUG_NO_DETECT         (0) -#define PORTD_HOTPLUG_SHORT_DETECT      (1 << 16) -#define PORTD_HOTPLUG_LONG_DETECT       (1 << 17) +#define PORTD_HOTPLUG_STATUS_MASK	(0x3 << 16) +#define  PORTD_HOTPLUG_NO_DETECT	(0 << 16) +#define  PORTD_HOTPLUG_SHORT_DETECT	(1 << 16) +#define  PORTD_HOTPLUG_LONG_DETECT	(2 << 16)  #define PORTC_HOTPLUG_ENABLE            (1 << 12)  #define PORTC_PULSE_DURATION_2ms        (0)  #define PORTC_PULSE_DURATION_4_5ms      (1 << 10)  #define PORTC_PULSE_DURATION_6ms        (2 << 10)  #define PORTC_PULSE_DURATION_100ms      (3 << 10)  #define PORTC_PULSE_DURATION_MASK	(3 << 10) -#define PORTC_HOTPLUG_NO_DETECT         (0) -#define PORTC_HOTPLUG_SHORT_DETECT      (1 << 8) -#define PORTC_HOTPLUG_LONG_DETECT       (1 << 9) +#define PORTC_HOTPLUG_STATUS_MASK	(0x3 << 8) +#define  PORTC_HOTPLUG_NO_DETECT	(0 << 8) +#define  PORTC_HOTPLUG_SHORT_DETECT	(1 << 8) +#define  PORTC_HOTPLUG_LONG_DETECT	(2 << 8)  #define PORTB_HOTPLUG_ENABLE            (1 << 4)  #define PORTB_PULSE_DURATION_2ms        (0)  #define PORTB_PULSE_DURATION_4_5ms      (1 << 2)  #define PORTB_PULSE_DURATION_6ms        (2 << 2)  #define PORTB_PULSE_DURATION_100ms      (3 << 2)  #define PORTB_PULSE_DURATION_MASK	(3 << 2) -#define PORTB_HOTPLUG_NO_DETECT         (0) -#define PORTB_HOTPLUG_SHORT_DETECT      (1 << 0) -#define PORTB_HOTPLUG_LONG_DETECT       (1 << 1) +#define PORTB_HOTPLUG_STATUS_MASK	(0x3 << 0) +#define  PORTB_HOTPLUG_NO_DETECT	(0 << 0) +#define  PORTB_HOTPLUG_SHORT_DETECT	(1 << 0) +#define  PORTB_HOTPLUG_LONG_DETECT	(2 << 0)  #define PCH_GPIOA               0xc5010  #define PCH_GPIOB               0xc5014 @@ -3817,8 +3797,6 @@  #define  TRANS_FSYNC_DELAY_HB2  (1<<27)  #define  TRANS_FSYNC_DELAY_HB3  (2<<27)  #define  TRANS_FSYNC_DELAY_HB4  (3<<27) -#define  TRANS_DP_AUDIO_ONLY    (1<<26) -#define  TRANS_DP_VIDEO_AUDIO   (0<<26)  #define  TRANS_INTERLACE_MASK   (7<<21)  #define  TRANS_PROGRESSIVE      (0<<21)  #define  TRANS_INTERLACED       (3<<21) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 9293878ec7e..71a5ebad14f 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -776,7 +776,7 @@ void intel_crt_init(struct drm_device *dev)  	crt->base.disable = intel_disable_crt;  	crt->base.enable = intel_enable_crt; -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		crt->base.get_hw_state = intel_ddi_get_hw_state;  	else  		crt->base.get_hw_state = intel_crt_get_hw_state; diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 4bad0f72401..2e904a5cd6c 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -84,7 +84,8 @@ static enum port intel_ddi_get_encoder_port(struct intel_encoder *intel_encoder)   * in either FDI or DP modes only, as HDMI connections will work with both   * of those   */ -void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, bool use_fdi_mode) +static void intel_prepare_ddi_buffers(struct drm_device *dev, enum port port, +				      bool use_fdi_mode)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	u32 reg; @@ -114,16 +115,17 @@ void intel_prepare_ddi(struct drm_device *dev)  {  	int port; -	if (IS_HASWELL(dev)) { -		for (port = PORT_A; port < PORT_E; port++) -			intel_prepare_ddi_buffers(dev, port, false); +	if (!HAS_DDI(dev)) +		return; -		/* DDI E is the suggested one to work in FDI mode, so program is as such by -		 * default. It will have to be re-programmed in case a digital DP output -		 * will be detected on it -		 */ -		intel_prepare_ddi_buffers(dev, PORT_E, true); -	} +	for (port = PORT_A; port < PORT_E; port++) +		intel_prepare_ddi_buffers(dev, port, false); + +	/* DDI E is the suggested one to work in FDI mode, so program is as such +	 * by default. It will have to be re-programmed in case a digital DP +	 * output will be detected on it +	 */ +	intel_prepare_ddi_buffers(dev, PORT_E, true);  }  static const long hsw_ddi_buf_ctl_values[] = { @@ -1069,7 +1071,7 @@ bool intel_ddi_connector_get_hw_state(struct intel_connector *intel_connector)  	if (port == PORT_A)  		cpu_transcoder = TRANSCODER_EDP;  	else -		cpu_transcoder = pipe; +		cpu_transcoder = (enum transcoder) pipe;  	tmp = I915_READ(TRANS_DDI_FUNC_CTL(cpu_transcoder)); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a9fb046b94a..8c36a11a9a5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -416,13 +416,11 @@ static const intel_limit_t intel_limits_vlv_dp = {  u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)  { -	unsigned long flags; -	u32 val = 0; +	WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); -	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; +		return 0;  	}  	I915_WRITE(DPIO_REG, reg); @@ -430,24 +428,20 @@ u32 intel_dpio_read(struct drm_i915_private *dev_priv, int reg)  		   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; +		return 0;  	} -	val = I915_READ(DPIO_DATA); -out_unlock: -	spin_unlock_irqrestore(&dev_priv->dpio_lock, flags); -	return val; +	return I915_READ(DPIO_DATA);  }  static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,  			     u32 val)  { -	unsigned long flags; +	WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); -	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; +		return;  	}  	I915_WRITE(DPIO_DATA, val); @@ -456,9 +450,6 @@ static void intel_dpio_write(struct drm_i915_private *dev_priv, int reg,  		   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) @@ -472,61 +463,14 @@ static void vlv_init_dpio(struct drm_device *dev)  	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_PIPE_MASK | 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)  {  	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = dev->dev_private;  	const intel_limit_t *limit;  	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { -		if (is_dual_link_lvds(dev_priv, PCH_LVDS)) { +		if (intel_is_dual_link_lvds(dev)) {  			/* LVDS dual channel */  			if (refclk == 100000)  				limit = &intel_limits_ironlake_dual_lvds_100m; @@ -550,11 +494,10 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc,  static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc)  {  	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = dev->dev_private;  	const intel_limit_t *limit;  	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { -		if (is_dual_link_lvds(dev_priv, LVDS)) +		if (intel_is_dual_link_lvds(dev))  			/* LVDS with dual channel */  			limit = &intel_limits_g4x_dual_channel_lvds;  		else @@ -686,19 +629,16 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,  {  	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = dev->dev_private;  	intel_clock_t clock;  	int err = target; -	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && -	    (I915_READ(LVDS)) != 0) { +	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {  		/* -		 * For LVDS, if the panel is on, just rely on its current -		 * settings for dual-channel.  We haven't figured out how to -		 * reliably set up different single/dual channel state, if we -		 * even can. +		 * For LVDS just rely on its current settings for dual-channel. +		 * We haven't figured out how to reliably set up different +		 * single/dual channel state, if we even can.  		 */ -		if (is_dual_link_lvds(dev_priv, LVDS)) +		if (intel_is_dual_link_lvds(dev))  			clock.p2 = limit->p2.p2_fast;  		else  			clock.p2 = limit->p2.p2_slow; @@ -751,7 +691,6 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,  			intel_clock_t *best_clock)  {  	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = dev->dev_private;  	intel_clock_t clock;  	int max_n;  	bool found; @@ -766,8 +705,7 @@ intel_g4x_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc,  			lvds_reg = PCH_LVDS;  		else  			lvds_reg = LVDS; -		if ((I915_READ(lvds_reg) & LVDS_CLKB_POWER_MASK) == -		    LVDS_CLKB_POWER_UP) +		if (intel_is_dual_link_lvds(dev))  			clock.p2 = limit->p2.p2_fast;  		else  			clock.p2 = limit->p2.p2_slow; @@ -1047,6 +985,51 @@ void intel_wait_for_pipe_off(struct drm_device *dev, int pipe)  	}  } +/* + * ibx_digital_port_connected - is the specified port connected? + * @dev_priv: i915 private structure + * @port: the port to test + * + * Returns true if @port is connected, false otherwise. + */ +bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, +				struct intel_digital_port *port) +{ +	u32 bit; + +	if (HAS_PCH_IBX(dev_priv->dev)) { +		switch(port->port) { +		case PORT_B: +			bit = SDE_PORTB_HOTPLUG; +			break; +		case PORT_C: +			bit = SDE_PORTC_HOTPLUG; +			break; +		case PORT_D: +			bit = SDE_PORTD_HOTPLUG; +			break; +		default: +			return true; +		} +	} else { +		switch(port->port) { +		case PORT_B: +			bit = SDE_PORTB_HOTPLUG_CPT; +			break; +		case PORT_C: +			bit = SDE_PORTC_HOTPLUG_CPT; +			break; +		case PORT_D: +			bit = SDE_PORTD_HOTPLUG_CPT; +			break; +		default: +			return true; +		} +	} + +	return I915_READ(SDEISR) & bit; +} +  static const char *state_string(bool enabled)  {  	return enabled ? "on" : "off"; @@ -1125,8 +1108,8 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv,  	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,  								      pipe); -	if (IS_HASWELL(dev_priv->dev)) { -		/* On Haswell, DDI is used instead of FDI_TX_CTL */ +	if (HAS_DDI(dev_priv->dev)) { +		/* DDI does not have a specific FDI_TX register */  		reg = TRANS_DDI_FUNC_CTL(cpu_transcoder);  		val = I915_READ(reg);  		cur_state = !!(val & TRANS_DDI_FUNC_ENABLE); @@ -1170,7 +1153,7 @@ static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,  		return;  	/* On Haswell, DDI ports are responsible for the FDI PLL setup */ -	if (IS_HASWELL(dev_priv->dev)) +	if (HAS_DDI(dev_priv->dev))  		return;  	reg = FDI_TX_CTL(pipe); @@ -1509,13 +1492,14 @@ static void  intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,  		enum intel_sbi_destination destination)  { -	unsigned long flags;  	u32 tmp; -	spin_lock_irqsave(&dev_priv->dpio_lock, flags); -	if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, 100)) { +	WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); + +	if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, +				100)) {  		DRM_ERROR("timeout waiting for SBI to become ready\n"); -		goto out_unlock; +		return;  	}  	I915_WRITE(SBI_ADDR, (reg << 16)); @@ -1530,24 +1514,21 @@ intel_sbi_write(struct drm_i915_private *dev_priv, u16 reg, u32 value,  	if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,  				100)) {  		DRM_ERROR("timeout waiting for SBI to complete write transaction\n"); -		goto out_unlock; +		return;  	} - -out_unlock: -	spin_unlock_irqrestore(&dev_priv->dpio_lock, flags);  }  static u32  intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,  	       enum intel_sbi_destination destination)  { -	unsigned long flags;  	u32 value = 0; +	WARN_ON(!mutex_is_locked(&dev_priv->dpio_lock)); -	spin_lock_irqsave(&dev_priv->dpio_lock, flags); -	if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, 100)) { +	if (wait_for((I915_READ(SBI_CTL_STAT) & SBI_BUSY) == 0, +				100)) {  		DRM_ERROR("timeout waiting for SBI to become ready\n"); -		goto out_unlock; +		return 0;  	}  	I915_WRITE(SBI_ADDR, (reg << 16)); @@ -1561,14 +1542,10 @@ intel_sbi_read(struct drm_i915_private *dev_priv, u16 reg,  	if (wait_for((I915_READ(SBI_CTL_STAT) & (SBI_BUSY | SBI_RESPONSE_FAIL)) == 0,  				100)) {  		DRM_ERROR("timeout waiting for SBI to complete read transaction\n"); -		goto out_unlock; +		return 0;  	} -	value = I915_READ(SBI_DATA); - -out_unlock: -	spin_unlock_irqrestore(&dev_priv->dpio_lock, flags); -	return value; +	return I915_READ(SBI_DATA);  }  /** @@ -1700,8 +1677,8 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv,  		 * make the BPC in transcoder be consistent with  		 * that in pipeconf reg.  		 */ -		val &= ~PIPE_BPC_MASK; -		val |= pipeconf_val & PIPE_BPC_MASK; +		val &= ~PIPECONF_BPC_MASK; +		val |= pipeconf_val & PIPECONF_BPC_MASK;  	}  	val &= ~TRANS_INTERLACE_MASK; @@ -1728,7 +1705,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv,  	BUG_ON(dev_priv->info->gen < 5);  	/* FDI must be feeding us bits for PCH ports */ -	assert_fdi_tx_enabled(dev_priv, cpu_transcoder); +	assert_fdi_tx_enabled(dev_priv, (enum pipe) cpu_transcoder);  	assert_fdi_rx_enabled(dev_priv, TRANSCODER_A);  	/* Workaround: set timing override bit. */ @@ -1816,11 +1793,11 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,  {  	enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv,  								      pipe); -	enum transcoder pch_transcoder; +	enum pipe pch_transcoder;  	int reg;  	u32 val; -	if (IS_HASWELL(dev_priv->dev)) +	if (HAS_PCH_LPT(dev_priv->dev))  		pch_transcoder = TRANSCODER_A;  	else  		pch_transcoder = pipe; @@ -1836,7 +1813,8 @@ static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,  		if (pch_port) {  			/* if driving the PCH, we need FDI enabled */  			assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder); -			assert_fdi_tx_pll_enabled(dev_priv, cpu_transcoder); +			assert_fdi_tx_pll_enabled(dev_priv, +						  (enum pipe) cpu_transcoder);  		}  		/* FIXME: assert CPU port conditions for SNB+ */  	} @@ -2350,43 +2328,6 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,  	return 0;  } -static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock) -{ -	struct drm_device *dev = crtc->dev; -	struct drm_i915_private *dev_priv = dev->dev_private; -	u32 dpa_ctl; - -	DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", clock); -	dpa_ctl = I915_READ(DP_A); -	dpa_ctl &= ~DP_PLL_FREQ_MASK; - -	if (clock < 200000) { -		u32 temp; -		dpa_ctl |= DP_PLL_FREQ_160MHZ; -		/* workaround for 160Mhz: -		   1) program 0x4600c bits 15:0 = 0x8124 -		   2) program 0x46010 bit 0 = 1 -		   3) program 0x46034 bit 24 = 1 -		   4) program 0x64000 bit 14 = 1 -		   */ -		temp = I915_READ(0x4600c); -		temp &= 0xffff0000; -		I915_WRITE(0x4600c, temp | 0x8124); - -		temp = I915_READ(0x46010); -		I915_WRITE(0x46010, temp | 1); - -		temp = I915_READ(0x46034); -		I915_WRITE(0x46034, temp | (1 << 24)); -	} else { -		dpa_ctl |= DP_PLL_FREQ_270MHZ; -	} -	I915_WRITE(DP_A, dpa_ctl); - -	POSTING_READ(DP_A); -	udelay(500); -} -  static void intel_fdi_normal_train(struct drm_crtc *crtc)  {  	struct drm_device *dev = crtc->dev; @@ -2815,7 +2756,7 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)  	temp = I915_READ(reg);  	temp &= ~((0x7 << 19) | (0x7 << 16));  	temp |= (intel_crtc->fdi_lanes - 1) << 19; -	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; +	temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;  	I915_WRITE(reg, temp | FDI_RX_PLL_ENABLE);  	POSTING_READ(reg); @@ -2828,18 +2769,14 @@ static void ironlake_fdi_pll_enable(struct intel_crtc *intel_crtc)  	POSTING_READ(reg);  	udelay(200); -	/* On Haswell, the PLL configuration for ports and pipes is handled -	 * separately, as part of DDI setup */ -	if (!IS_HASWELL(dev)) { -		/* Enable CPU FDI TX PLL, always on for Ironlake */ -		reg = FDI_TX_CTL(pipe); -		temp = I915_READ(reg); -		if ((temp & FDI_TX_PLL_ENABLE) == 0) { -			I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE); +	/* Enable CPU FDI TX PLL, always on for Ironlake */ +	reg = FDI_TX_CTL(pipe); +	temp = I915_READ(reg); +	if ((temp & FDI_TX_PLL_ENABLE) == 0) { +		I915_WRITE(reg, temp | FDI_TX_PLL_ENABLE); -			POSTING_READ(reg); -			udelay(100); -		} +		POSTING_READ(reg); +		udelay(100);  	}  } @@ -2889,7 +2826,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)  	reg = FDI_RX_CTL(pipe);  	temp = I915_READ(reg);  	temp &= ~(0x7 << 16); -	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; +	temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;  	I915_WRITE(reg, temp & ~FDI_RX_ENABLE);  	POSTING_READ(reg); @@ -2918,7 +2855,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc)  	}  	/* BPC in FDI rx is consistent with that in PIPECONF */  	temp &= ~(0x07 << 16); -	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11; +	temp |= (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) << 11;  	I915_WRITE(reg, temp);  	POSTING_READ(reg); @@ -2992,6 +2929,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)  	u32 divsel, phaseinc, auxdiv, phasedir = 0;  	u32 temp; +	mutex_lock(&dev_priv->dpio_lock); +  	/* It is necessary to ungate the pixclk gate prior to programming  	 * the divisors, and gate it back when it is done.  	 */ @@ -3066,6 +3005,8 @@ static void lpt_program_iclkip(struct drm_crtc *crtc)  	udelay(24);  	I915_WRITE(PIXCLK_GATE, PIXCLK_GATE_UNGATE); + +	mutex_unlock(&dev_priv->dpio_lock);  }  /* @@ -3146,7 +3087,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc)  	if (HAS_PCH_CPT(dev) &&  	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||  	     intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))) { -		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) >> 5; +		u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5;  		reg = TRANS_DP_CTL(pipe);  		temp = I915_READ(reg);  		temp &= ~(TRANS_DP_PORT_SEL_MASK | @@ -3623,7 +3564,7 @@ static void haswell_crtc_off(struct drm_crtc *crtc)  	/* Stop saying we're using TRANSCODER_EDP because some other CRTC might  	 * start using it. */ -	intel_crtc->cpu_transcoder = intel_crtc->pipe; +	intel_crtc->cpu_transcoder = (enum transcoder) intel_crtc->pipe;  	intel_ddi_put_crtc_pll(crtc);  } @@ -4012,16 +3953,8 @@ static int i830_get_display_clock_speed(struct drm_device *dev)  	return 133000;  } -struct fdi_m_n { -	u32        tu; -	u32        gmch_m; -	u32        gmch_n; -	u32        link_m; -	u32        link_n; -}; -  static void -fdi_reduce_ratio(u32 *num, u32 *den) +intel_reduce_ratio(uint32_t *num, uint32_t *den)  {  	while (*num > 0xffffff || *den > 0xffffff) {  		*num >>= 1; @@ -4029,20 +3962,18 @@ fdi_reduce_ratio(u32 *num, u32 *den)  	}  } -static void -ironlake_compute_m_n(int bits_per_pixel, int nlanes, int pixel_clock, -		     int link_clock, struct fdi_m_n *m_n) +void +intel_link_compute_m_n(int bits_per_pixel, int nlanes, +		       int pixel_clock, int link_clock, +		       struct intel_link_m_n *m_n)  { -	m_n->tu = 64; /* default size */ - -	/* BUG_ON(pixel_clock > INT_MAX / 36); */ +	m_n->tu = 64;  	m_n->gmch_m = bits_per_pixel * pixel_clock;  	m_n->gmch_n = link_clock * nlanes * 8; -	fdi_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); - +	intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);  	m_n->link_m = pixel_clock;  	m_n->link_n = link_clock; -	fdi_reduce_ratio(&m_n->link_m, &m_n->link_n); +	intel_reduce_ratio(&m_n->link_m, &m_n->link_n);  }  static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) @@ -4289,51 +4220,6 @@ 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; - -	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; -	} -	temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); -	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) -		temp |= LVDS_HSYNC_POLARITY; -	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) -		temp |= LVDS_VSYNC_POLARITY; -	I915_WRITE(LVDS, temp); -} -  static void vlv_update_pll(struct drm_crtc *crtc,  			   struct drm_display_mode *mode,  			   struct drm_display_mode *adjusted_mode, @@ -4349,6 +4235,8 @@ static void vlv_update_pll(struct drm_crtc *crtc,  	bool is_sdvo;  	u32 temp; +	mutex_lock(&dev_priv->dpio_lock); +  	is_sdvo = intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ||  		intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI); @@ -4432,6 +4320,8 @@ static void vlv_update_pll(struct drm_crtc *crtc,  			temp |= (1 << 21);  		intel_dpio_write(dev_priv, DPIO_DATA_CHANNEL2, temp);  	} + +	mutex_unlock(&dev_priv->dpio_lock);  }  static void i9xx_update_pll(struct drm_crtc *crtc, @@ -4443,6 +4333,7 @@ static void i9xx_update_pll(struct drm_crtc *crtc,  	struct drm_device *dev = crtc->dev;  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	struct intel_encoder *encoder;  	int pipe = intel_crtc->pipe;  	u32 dpll;  	bool is_sdvo; @@ -4511,12 +4402,9 @@ static void i9xx_update_pll(struct drm_crtc *crtc,  	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); +	for_each_encoder_on_crtc(dev, crtc, encoder) +		if (encoder->pre_pll_enable) +			encoder->pre_pll_enable(encoder);  	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))  		intel_dp_set_m_n(crtc, mode, adjusted_mode); @@ -4555,6 +4443,7 @@ static void i8xx_update_pll(struct drm_crtc *crtc,  	struct drm_device *dev = crtc->dev;  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	struct intel_encoder *encoder;  	int pipe = intel_crtc->pipe;  	u32 dpll; @@ -4588,12 +4477,9 @@ static void i8xx_update_pll(struct drm_crtc *crtc,  	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); +	for_each_encoder_on_crtc(dev, crtc, encoder) +		if (encoder->pre_pll_enable) +			encoder->pre_pll_enable(encoder);  	I915_WRITE(DPLL(pipe), dpll); @@ -4783,10 +4669,10 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  	}  	/* default to 8bpc */ -	pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN); +	pipeconf &= ~(PIPECONF_BPC_MASK | PIPECONF_DITHER_EN);  	if (is_dp) {  		if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { -			pipeconf |= PIPECONF_BPP_6 | +			pipeconf |= PIPECONF_6BPC |  				    PIPECONF_DITHER_EN |  				    PIPECONF_DITHER_TYPE_SP;  		} @@ -4794,7 +4680,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  	if (IS_VALLEYVIEW(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) {  		if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { -			pipeconf |= PIPECONF_BPP_6 | +			pipeconf |= PIPECONF_6BPC |  					PIPECONF_ENABLE |  					I965_PIPECONF_ACTIVE;  		} @@ -5177,19 +5063,19 @@ static void ironlake_set_pipeconf(struct drm_crtc *crtc,  	val = I915_READ(PIPECONF(pipe)); -	val &= ~PIPE_BPC_MASK; +	val &= ~PIPECONF_BPC_MASK;  	switch (intel_crtc->bpp) {  	case 18: -		val |= PIPE_6BPC; +		val |= PIPECONF_6BPC;  		break;  	case 24: -		val |= PIPE_8BPC; +		val |= PIPECONF_8BPC;  		break;  	case 30: -		val |= PIPE_10BPC; +		val |= PIPECONF_10BPC;  		break;  	case 36: -		val |= PIPE_12BPC; +		val |= PIPECONF_12BPC;  		break;  	default:  		/* Case prevented by intel_choose_pipe_bpp_dither. */ @@ -5400,7 +5286,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc,  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);  	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;  	struct intel_encoder *intel_encoder, *edp_encoder = NULL; -	struct fdi_m_n m_n = {0}; +	struct intel_link_m_n m_n = {0};  	int target_clock, pixel_multiplier, lane, link_bw;  	bool is_dp = false, is_cpu_edp = false; @@ -5452,8 +5338,7 @@ static void ironlake_set_m_n(struct drm_crtc *crtc,  	if (pixel_multiplier > 1)  		link_bw *= pixel_multiplier; -	ironlake_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw, -			     &m_n); +	intel_link_compute_m_n(intel_crtc->bpp, lane, target_clock, link_bw, &m_n);  	I915_WRITE(PIPE_DATA_M1(cpu_transcoder), TU_SIZE(m_n.tu) | m_n.gmch_m);  	I915_WRITE(PIPE_DATA_N1(cpu_transcoder), m_n.gmch_n); @@ -5506,7 +5391,7 @@ static uint32_t ironlake_compute_dpll(struct intel_crtc *intel_crtc,  	if (is_lvds) {  		if ((intel_panel_use_ssc(dev_priv) &&  		     dev_priv->lvds_ssc_freq == 100) || -		    (I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP) +		    intel_is_dual_link_lvds(dev))  			factor = 25;  	} else if (is_sdvo && is_tv)  		factor = 20; @@ -5581,7 +5466,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  	bool ok, has_reduced_clock = false;  	bool is_lvds = false, is_dp = false, is_cpu_edp = false;  	struct intel_encoder *encoder; -	u32 temp;  	int ret;  	bool dither, fdi_config_ok; @@ -5645,54 +5529,12 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  	} else  		intel_put_pch_pll(intel_crtc); -	/* 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(PCH_LVDS); -		temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; -		if (HAS_PCH_CPT(dev)) { -			temp &= ~PORT_TRANS_SEL_MASK; -			temp |= PORT_TRANS_SEL_CPT(pipe); -		} else { -			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. -		 */ -		temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); -		if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) -			temp |= LVDS_HSYNC_POLARITY; -		if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) -			temp |= LVDS_VSYNC_POLARITY; -		I915_WRITE(PCH_LVDS, temp); -	} - -	if (is_dp && !is_cpu_edp) { +	if (is_dp && !is_cpu_edp)  		intel_dp_set_m_n(crtc, mode, adjusted_mode); -	} else { -		/* For non-DP output, clear any trans DP clock recovery setting.*/ -		I915_WRITE(TRANSDATA_M1(pipe), 0); -		I915_WRITE(TRANSDATA_N1(pipe), 0); -		I915_WRITE(TRANSDPLINK_M1(pipe), 0); -		I915_WRITE(TRANSDPLINK_N1(pipe), 0); -	} + +	for_each_encoder_on_crtc(dev, crtc, encoder) +		if (encoder->pre_pll_enable) +			encoder->pre_pll_enable(encoder);  	if (intel_crtc->pch_pll) {  		I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll); @@ -5727,9 +5569,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  	fdi_config_ok = ironlake_check_fdi_lanes(intel_crtc); -	if (is_cpu_edp) -		ironlake_set_pll_edp(crtc, adjusted_mode->clock); -  	ironlake_set_pipeconf(crtc, adjusted_mode, dither);  	intel_wait_for_vblank(dev, pipe); @@ -5759,20 +5598,13 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,  	int pipe = intel_crtc->pipe;  	int plane = intel_crtc->plane;  	int num_connectors = 0; -	intel_clock_t clock, reduced_clock; -	u32 dpll = 0, fp = 0, fp2 = 0; -	bool ok, has_reduced_clock = false; -	bool is_lvds = false, is_dp = false, is_cpu_edp = false; +	bool is_dp = false, is_cpu_edp = false;  	struct intel_encoder *encoder; -	u32 temp;  	int ret;  	bool dither;  	for_each_encoder_on_crtc(dev, crtc, encoder) {  		switch (encoder->type) { -		case INTEL_OUTPUT_LVDS: -			is_lvds = true; -			break;  		case INTEL_OUTPUT_DISPLAYPORT:  			is_dp = true;  			break; @@ -5806,143 +5638,26 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,  	if (!intel_ddi_pll_mode_set(crtc, adjusted_mode->clock))  		return -EINVAL; -	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { -		ok = ironlake_compute_clocks(crtc, adjusted_mode, &clock, -					     &has_reduced_clock, -					     &reduced_clock); -		if (!ok) { -			DRM_ERROR("Couldn't find PLL settings for mode!\n"); -			return -EINVAL; -		} -	} -  	/* Ensure that the cursor is valid for the new mode before changing... */  	intel_crtc_update_cursor(crtc, true);  	/* determine panel color depth */  	dither = intel_choose_pipe_bpp_dither(crtc, fb, &intel_crtc->bpp,  					      adjusted_mode); -	if (is_lvds && dev_priv->lvds_dither) -		dither = true;  	DRM_DEBUG_KMS("Mode for pipe %d:\n", pipe);  	drm_mode_debug_printmodeline(mode); -	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { -		fp = clock.n << 16 | clock.m1 << 8 | clock.m2; -		if (has_reduced_clock) -			fp2 = reduced_clock.n << 16 | reduced_clock.m1 << 8 | -			      reduced_clock.m2; - -		dpll = ironlake_compute_dpll(intel_crtc, adjusted_mode, &clock, -					     fp); - -		/* CPU eDP is the only output that doesn't need a PCH PLL of its -		 * own on pre-Haswell/LPT generation */ -		if (!is_cpu_edp) { -			struct intel_pch_pll *pll; - -			pll = intel_get_pch_pll(intel_crtc, dpll, fp); -			if (pll == NULL) { -				DRM_DEBUG_DRIVER("failed to find PLL for pipe %d\n", -						 pipe); -				return -EINVAL; -			} -		} else -			intel_put_pch_pll(intel_crtc); - -		/* 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(PCH_LVDS); -			temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; -			if (HAS_PCH_CPT(dev)) { -				temp &= ~PORT_TRANS_SEL_MASK; -				temp |= PORT_TRANS_SEL_CPT(pipe); -			} else { -				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. -			 */ -			temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); -			if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) -				temp |= LVDS_HSYNC_POLARITY; -			if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) -				temp |= LVDS_VSYNC_POLARITY; -			I915_WRITE(PCH_LVDS, temp); -		} -	} - -	if (is_dp && !is_cpu_edp) { +	if (is_dp && !is_cpu_edp)  		intel_dp_set_m_n(crtc, mode, adjusted_mode); -	} else { -		if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { -			/* For non-DP output, clear any trans DP clock recovery -			 * setting.*/ -			I915_WRITE(TRANSDATA_M1(pipe), 0); -			I915_WRITE(TRANSDATA_N1(pipe), 0); -			I915_WRITE(TRANSDPLINK_M1(pipe), 0); -			I915_WRITE(TRANSDPLINK_N1(pipe), 0); -		} -	}  	intel_crtc->lowfreq_avail = false; -	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { -		if (intel_crtc->pch_pll) { -			I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll); - -			/* Wait for the clocks to stabilize. */ -			POSTING_READ(intel_crtc->pch_pll->pll_reg); -			udelay(150); - -			/* The pixel multiplier can only be updated once the -			 * DPLL is enabled and the clocks are stable. -			 * -			 * So write it again. -			 */ -			I915_WRITE(intel_crtc->pch_pll->pll_reg, dpll); -		} - -		if (intel_crtc->pch_pll) { -			if (is_lvds && has_reduced_clock && i915_powersave) { -				I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp2); -				intel_crtc->lowfreq_avail = true; -			} else { -				I915_WRITE(intel_crtc->pch_pll->fp1_reg, fp); -			} -		} -	}  	intel_set_pipe_timings(intel_crtc, mode, adjusted_mode);  	if (!is_dp || is_cpu_edp)  		ironlake_set_m_n(crtc, mode, adjusted_mode); -	if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) -		if (is_cpu_edp) -			ironlake_set_pll_edp(crtc, adjusted_mode->clock); -  	haswell_set_pipeconf(crtc, adjusted_mode, dither);  	/* Set up the display plane register */ @@ -6759,7 +6474,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,  		return false;  	} -	if (!intel_set_mode(crtc, mode, 0, 0, fb)) { +	if (intel_set_mode(crtc, mode, 0, 0, fb)) {  		DRM_DEBUG_KMS("failed to set mode on load-detect pipe\n");  		if (old->release_fb)  			old->release_fb->funcs->destroy(old->release_fb); @@ -7109,8 +6824,6 @@ static void do_intel_finish_page_flip(struct drm_device *dev,  	obj = work->old_fb_obj; -	atomic_clear_mask(1 << intel_crtc->plane, -			  &obj->pending_flip.counter);  	wake_up(&dev_priv->pending_flip_queue);  	queue_work(dev_priv->wq, &work->work); @@ -7474,10 +7187,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,  	work->enable_stall_check = true; -	/* Block clients from rendering to the new back buffer until -	 * the flip occurs and the object is no longer visible. -	 */ -	atomic_add(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);  	atomic_inc(&intel_crtc->unpin_work_count);  	ret = dev_priv->display.queue_flip(dev, crtc, fb, obj); @@ -7494,7 +7203,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,  cleanup_pending:  	atomic_dec(&intel_crtc->unpin_work_count); -	atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);  	drm_gem_object_unreference(&work->old_fb_obj->base);  	drm_gem_object_unreference(&obj->base);  	mutex_unlock(&dev->struct_mutex); @@ -7904,16 +7612,21 @@ intel_modeset_check_state(struct drm_device *dev)  	}  } -bool intel_set_mode(struct drm_crtc *crtc, -		    struct drm_display_mode *mode, -		    int x, int y, struct drm_framebuffer *fb) +int intel_set_mode(struct drm_crtc *crtc, +		   struct drm_display_mode *mode, +		   int x, int y, struct drm_framebuffer *fb)  {  	struct drm_device *dev = crtc->dev;  	drm_i915_private_t *dev_priv = dev->dev_private; -	struct drm_display_mode *adjusted_mode, saved_mode, saved_hwmode; +	struct drm_display_mode *adjusted_mode, *saved_mode, *saved_hwmode;  	struct intel_crtc *intel_crtc;  	unsigned disable_pipes, prepare_pipes, modeset_pipes; -	bool ret = true; +	int ret = 0; + +	saved_mode = kmalloc(2 * sizeof(*saved_mode), GFP_KERNEL); +	if (!saved_mode) +		return -ENOMEM; +	saved_hwmode = saved_mode + 1;  	intel_modeset_affected_pipes(crtc, &modeset_pipes,  				     &prepare_pipes, &disable_pipes); @@ -7924,8 +7637,8 @@ bool intel_set_mode(struct drm_crtc *crtc,  	for_each_intel_crtc_masked(dev, disable_pipes, intel_crtc)  		intel_crtc_disable(&intel_crtc->base); -	saved_hwmode = crtc->hwmode; -	saved_mode = crtc->mode; +	*saved_hwmode = crtc->hwmode; +	*saved_mode = crtc->mode;  	/* Hack: Because we don't (yet) support global modeset on multiple  	 * crtcs, we don't keep track of the new mode for more than one crtc. @@ -7936,7 +7649,8 @@ bool intel_set_mode(struct drm_crtc *crtc,  	if (modeset_pipes) {  		adjusted_mode = intel_modeset_adjusted_mode(crtc, mode);  		if (IS_ERR(adjusted_mode)) { -			return false; +			ret = PTR_ERR(adjusted_mode); +			goto out;  		}  	} @@ -7962,11 +7676,11 @@ bool intel_set_mode(struct drm_crtc *crtc,  	 * on the DPLL.  	 */  	for_each_intel_crtc_masked(dev, modeset_pipes, intel_crtc) { -		ret = !intel_crtc_mode_set(&intel_crtc->base, -					   mode, adjusted_mode, -					   x, y, fb); -		if (!ret) -		    goto done; +		ret = intel_crtc_mode_set(&intel_crtc->base, +					  mode, adjusted_mode, +					  x, y, fb); +		if (ret) +			goto done;  	}  	/* Now enable the clocks, plane, pipe, and connectors that we set up. */ @@ -7987,16 +7701,23 @@ bool intel_set_mode(struct drm_crtc *crtc,  	/* FIXME: add subpixel order */  done:  	drm_mode_destroy(dev, adjusted_mode); -	if (!ret && crtc->enabled) { -		crtc->hwmode = saved_hwmode; -		crtc->mode = saved_mode; +	if (ret && crtc->enabled) { +		crtc->hwmode = *saved_hwmode; +		crtc->mode = *saved_mode;  	} else {  		intel_modeset_check_state(dev);  	} +out: +	kfree(saved_mode);  	return ret;  } +void intel_crtc_restore_mode(struct drm_crtc *crtc) +{ +	intel_set_mode(crtc, &crtc->mode, crtc->x, crtc->y, crtc->fb); +} +  #undef for_each_intel_crtc_masked  static void intel_set_config_free(struct intel_set_config *config) @@ -8262,11 +7983,11 @@ static int intel_crtc_set_config(struct drm_mode_set *set)  			drm_mode_debug_printmodeline(set->mode);  		} -		if (!intel_set_mode(set->crtc, set->mode, -				    set->x, set->y, set->fb)) { -			DRM_ERROR("failed to set mode on [CRTC:%d]\n", -				  set->crtc->base.id); -			ret = -EINVAL; +		ret = intel_set_mode(set->crtc, set->mode, +				     set->x, set->y, set->fb); +		if (ret) { +			DRM_ERROR("failed to set mode on [CRTC:%d], err = %d\n", +				  set->crtc->base.id, ret);  			goto fail;  		}  	} else if (config->fb_changed) { @@ -8283,8 +8004,8 @@ fail:  	/* Try to restore the config */  	if (config->mode_changed && -	    !intel_set_mode(save_set.crtc, save_set.mode, -			    save_set.x, save_set.y, save_set.fb)) +	    intel_set_mode(save_set.crtc, save_set.mode, +			   save_set.x, save_set.y, save_set.fb))  		DRM_ERROR("failed to restore config after modeset failure\n");  out_config: @@ -8303,7 +8024,7 @@ static const struct drm_crtc_funcs intel_crtc_funcs = {  static void intel_cpu_pll_init(struct drm_device *dev)  { -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		intel_ddi_pll_init(dev);  } @@ -8439,11 +8160,10 @@ static void intel_setup_outputs(struct drm_device *dev)  		I915_WRITE(PFIT_CONTROL, 0);  	} -	if (!(IS_HASWELL(dev) && -	      (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES))) +	if (!(HAS_DDI(dev) && (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES)))  		intel_crt_init(dev); -	if (IS_HASWELL(dev)) { +	if (HAS_DDI(dev)) {  		int found;  		/* Haswell uses DDI functions to detect digital outputs */ @@ -8686,7 +8406,7 @@ static void intel_init_display(struct drm_device *dev)  	struct drm_i915_private *dev_priv = dev->dev_private;  	/* We always want a DPMS function */ -	if (IS_HASWELL(dev)) { +	if (HAS_DDI(dev)) {  		dev_priv->display.crtc_mode_set = haswell_crtc_mode_set;  		dev_priv->display.crtc_enable = haswell_crtc_enable;  		dev_priv->display.crtc_disable = haswell_crtc_disable; @@ -8748,8 +8468,7 @@ static void intel_init_display(struct drm_device *dev)  		} else if (IS_HASWELL(dev)) {  			dev_priv->display.fdi_link_train = hsw_fdi_link_train;  			dev_priv->display.write_eld = haswell_write_eld; -		} else -			dev_priv->display.update_wm = NULL; +		}  	} else if (IS_G4X(dev)) {  		dev_priv->display.write_eld = g4x_write_eld;  	} @@ -8982,6 +8701,9 @@ void intel_modeset_init(struct drm_device *dev)  	/* Just disable it once at startup */  	i915_disable_vga(dev);  	intel_setup_outputs(dev); + +	/* Just in case the BIOS is doing something questionable. */ +	intel_disable_fbc(dev);  }  static void @@ -9192,7 +8914,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,  	struct intel_encoder *encoder;  	struct intel_connector *connector; -	if (IS_HASWELL(dev)) { +	if (HAS_DDI(dev)) {  		tmp = I915_READ(TRANS_DDI_FUNC_CTL(TRANSCODER_EDP));  		if (tmp & TRANS_DDI_FUNC_ENABLE) { @@ -9233,7 +8955,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,  			      crtc->active ? "enabled" : "disabled");  	} -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		intel_ddi_setup_hw_pll_state(dev);  	list_for_each_entry(encoder, &dev->mode_config.encoder_list, @@ -9284,9 +9006,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,  	if (force_restore) {  		for_each_pipe(pipe) { -			crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); -			intel_set_mode(&crtc->base, &crtc->base.mode, -				       crtc->base.x, crtc->base.y, crtc->base.fb); +			intel_crtc_restore_mode(dev_priv->pipe_to_crtc_mapping[pipe]);  		}  		i915_redisable_vga(dev); @@ -9350,6 +9070,8 @@ void intel_modeset_cleanup(struct drm_device *dev)  	flush_scheduled_work();  	drm_mode_config_cleanup(dev); + +	intel_cleanup_overlay(dev);  }  /* diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b63d55318a..5f12eb2d0fb 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -148,15 +148,6 @@ intel_dp_max_link_bw(struct intel_dp *intel_dp)  	return max_link_bw;  } -static int -intel_dp_link_clock(uint8_t link_bw) -{ -	if (link_bw == DP_LINK_BW_2_7) -		return 270000; -	else -		return 162000; -} -  /*   * The units on the numbers in the next two are... bizarre.  Examples will   * make it clearer; this one parallels an example in the eDP spec. @@ -191,7 +182,8 @@ intel_dp_adjust_dithering(struct intel_dp *intel_dp,  			  struct drm_display_mode *mode,  			  bool adjust_mode)  { -	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_dp)); +	int max_link_clock = +		drm_dp_bw_code_to_link_rate(intel_dp_max_link_bw(intel_dp));  	int max_lanes = drm_dp_max_lane_count(intel_dp->dpcd);  	int max_rate, mode_rate; @@ -330,6 +322,48 @@ intel_dp_check_edp(struct intel_dp *intel_dp)  	}  } +static uint32_t +intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) +{ +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); +	struct drm_device *dev = intel_dig_port->base.base.dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	uint32_t ch_ctl = intel_dp->output_reg + 0x10; +	uint32_t status; +	bool done; + +	if (IS_HASWELL(dev)) { +		switch (intel_dig_port->port) { +		case PORT_A: +			ch_ctl = DPA_AUX_CH_CTL; +			break; +		case PORT_B: +			ch_ctl = PCH_DPB_AUX_CH_CTL; +			break; +		case PORT_C: +			ch_ctl = PCH_DPC_AUX_CH_CTL; +			break; +		case PORT_D: +			ch_ctl = PCH_DPD_AUX_CH_CTL; +			break; +		default: +			BUG(); +		} +	} + +#define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) +	if (has_aux_irq) +		done = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10); +	else +		done = wait_for_atomic(C, 10) == 0; +	if (!done) +		DRM_ERROR("dp aux hw did not signal timeout (has irq: %i)!\n", +			  has_aux_irq); +#undef C + +	return status; +} +  static int  intel_dp_aux_ch(struct intel_dp *intel_dp,  		uint8_t *send, int send_bytes, @@ -341,11 +375,17 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	struct drm_i915_private *dev_priv = dev->dev_private;  	uint32_t ch_ctl = output_reg + 0x10;  	uint32_t ch_data = ch_ctl + 4; -	int i; -	int recv_bytes; +	int i, ret, recv_bytes;  	uint32_t status;  	uint32_t aux_clock_divider;  	int try, precharge; +	bool has_aux_irq = INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev); + +	/* dp aux is extremely sensitive to irq latency, hence request the +	 * lowest possible wakeup latency and so prevent the cpu from going into +	 * deep sleep states. +	 */ +	pm_qos_update_request(&dev_priv->pm_qos, 0);  	if (IS_HASWELL(dev)) {  		switch (intel_dig_port->port) { @@ -379,7 +419,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	 * clock divider.  	 */  	if (is_cpu_edp(intel_dp)) { -		if (IS_HASWELL(dev)) +		if (HAS_DDI(dev))  			aux_clock_divider = intel_ddi_get_cdclk_freq(dev_priv) >> 1;  		else if (IS_VALLEYVIEW(dev))  			aux_clock_divider = 100; @@ -399,7 +439,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	/* Try to wait for any previous AUX channel activity */  	for (try = 0; try < 3; try++) { -		status = I915_READ(ch_ctl); +		status = I915_READ_NOTRACE(ch_ctl);  		if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)  			break;  		msleep(1); @@ -408,7 +448,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	if (try == 3) {  		WARN(1, "dp_aux_ch not started status 0x%08x\n",  		     I915_READ(ch_ctl)); -		return -EBUSY; +		ret = -EBUSY; +		goto out;  	}  	/* Must try at least 3 times according to DP spec */ @@ -421,6 +462,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  		/* Send the command and wait for it to complete */  		I915_WRITE(ch_ctl,  			   DP_AUX_CH_CTL_SEND_BUSY | +			   (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) |  			   DP_AUX_CH_CTL_TIME_OUT_400us |  			   (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |  			   (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | @@ -428,12 +470,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  			   DP_AUX_CH_CTL_DONE |  			   DP_AUX_CH_CTL_TIME_OUT_ERROR |  			   DP_AUX_CH_CTL_RECEIVE_ERROR); -		for (;;) { -			status = I915_READ(ch_ctl); -			if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) -				break; -			udelay(100); -		} + +		status = intel_dp_aux_wait_done(intel_dp, has_aux_irq);  		/* Clear done status and any errors */  		I915_WRITE(ch_ctl, @@ -451,7 +489,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	if ((status & DP_AUX_CH_CTL_DONE) == 0) {  		DRM_ERROR("dp_aux_ch not done status 0x%08x\n", status); -		return -EBUSY; +		ret = -EBUSY; +		goto out;  	}  	/* Check for timeout or receive error. @@ -459,14 +498,16 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  	 */  	if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {  		DRM_ERROR("dp_aux_ch receive error status 0x%08x\n", status); -		return -EIO; +		ret = -EIO; +		goto out;  	}  	/* Timeouts occur when the device isn't connected, so they're  	 * "normal" -- don't fill the kernel log with these */  	if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {  		DRM_DEBUG_KMS("dp_aux_ch timeout status 0x%08x\n", status); -		return -ETIMEDOUT; +		ret = -ETIMEDOUT; +		goto out;  	}  	/* Unload any bytes sent back from the other side */ @@ -479,7 +520,11 @@ intel_dp_aux_ch(struct intel_dp *intel_dp,  		unpack_aux(I915_READ(ch_data + i),  			   recv + i, recv_bytes - i); -	return recv_bytes; +	ret = recv_bytes; +out: +	pm_qos_update_request(&dev_priv->pm_qos, PM_QOS_DEFAULT_VALUE); + +	return ret;  }  /* Write data to the aux channel in native mode */ @@ -722,12 +767,15 @@ intel_dp_mode_fixup(struct drm_encoder *encoder,  	for (clock = 0; clock <= max_clock; clock++) {  		for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { -			int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); +			int link_bw_clock = +				drm_dp_bw_code_to_link_rate(bws[clock]); +			int link_avail = intel_dp_max_data_rate(link_bw_clock, +								lane_count);  			if (mode_rate <= link_avail) {  				intel_dp->link_bw = bws[clock];  				intel_dp->lane_count = lane_count; -				adjusted_mode->clock = intel_dp_link_clock(intel_dp->link_bw); +				adjusted_mode->clock = link_bw_clock;  				DRM_DEBUG_KMS("DP link bw %02x lane "  						"count %d clock %d bpp %d\n",  				       intel_dp->link_bw, intel_dp->lane_count, @@ -742,39 +790,6 @@ intel_dp_mode_fixup(struct drm_encoder *encoder,  	return false;  } -struct intel_dp_m_n { -	uint32_t	tu; -	uint32_t	gmch_m; -	uint32_t	gmch_n; -	uint32_t	link_m; -	uint32_t	link_n; -}; - -static void -intel_reduce_ratio(uint32_t *num, uint32_t *den) -{ -	while (*num > 0xffffff || *den > 0xffffff) { -		*num >>= 1; -		*den >>= 1; -	} -} - -static void -intel_dp_compute_m_n(int bpp, -		     int nlanes, -		     int pixel_clock, -		     int link_clock, -		     struct intel_dp_m_n *m_n) -{ -	m_n->tu = 64; -	m_n->gmch_m = (pixel_clock * bpp) >> 3; -	m_n->gmch_n = link_clock * nlanes; -	intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); -	m_n->link_m = pixel_clock; -	m_n->link_n = link_clock; -	intel_reduce_ratio(&m_n->link_m, &m_n->link_n); -} -  void  intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,  		 struct drm_display_mode *adjusted_mode) @@ -785,7 +800,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);  	int lane_count = 4; -	struct intel_dp_m_n m_n; +	struct intel_link_m_n m_n;  	int pipe = intel_crtc->pipe;  	enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; @@ -808,8 +823,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,  	 * the number of bytes_per_pixel post-LUT, which we always  	 * set up for 8-bits of R/G/B, or 3 bytes total.  	 */ -	intel_dp_compute_m_n(intel_crtc->bpp, lane_count, -			     mode->clock, adjusted_mode->clock, &m_n); +	intel_link_compute_m_n(intel_crtc->bpp, lane_count, +			       mode->clock, adjusted_mode->clock, &m_n);  	if (IS_HASWELL(dev)) {  		I915_WRITE(PIPE_DATA_M1(cpu_transcoder), @@ -851,6 +866,32 @@ void intel_dp_init_link_config(struct intel_dp *intel_dp)  	}  } +static void ironlake_set_pll_edp(struct drm_crtc *crtc, int clock) +{ +	struct drm_device *dev = crtc->dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	u32 dpa_ctl; + +	DRM_DEBUG_KMS("eDP PLL enable for clock %d\n", clock); +	dpa_ctl = I915_READ(DP_A); +	dpa_ctl &= ~DP_PLL_FREQ_MASK; + +	if (clock < 200000) { +		/* For a long time we've carried around a ILK-DevA w/a for the +		 * 160MHz clock. If we're really unlucky, it's still required. +		 */ +		DRM_DEBUG_KMS("160MHz cpu eDP clock, might need ilk devA w/a\n"); +		dpa_ctl |= DP_PLL_FREQ_160MHZ; +	} else { +		dpa_ctl |= DP_PLL_FREQ_270MHZ; +	} + +	I915_WRITE(DP_A, dpa_ctl); + +	POSTING_READ(DP_A); +	udelay(500); +} +  static void  intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  		  struct drm_display_mode *adjusted_mode) @@ -950,6 +991,9 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  	} else {  		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;  	} + +	if (is_cpu_edp(intel_dp)) +		ironlake_set_pll_edp(crtc, adjusted_mode->clock);  }  #define IDLE_ON_MASK		(PP_ON | 0 	  | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK) @@ -1543,7 +1587,7 @@ intel_get_adjust_train(struct intel_dp *intel_dp, uint8_t link_status[DP_LINK_ST  }  static uint32_t -intel_dp_signal_levels(uint8_t train_set) +intel_gen4_signal_levels(uint8_t train_set)  {  	uint32_t	signal_levels = 0; @@ -1641,7 +1685,7 @@ intel_gen7_edp_signal_levels(uint8_t train_set)  /* Gen7.5's (HSW) DP voltage swing and pre-emphasis control */  static uint32_t -intel_dp_signal_levels_hsw(uint8_t train_set) +intel_hsw_signal_levels(uint8_t train_set)  {  	int signal_levels = train_set & (DP_TRAIN_VOLTAGE_SWING_MASK |  					 DP_TRAIN_PRE_EMPHASIS_MASK); @@ -1673,6 +1717,34 @@ intel_dp_signal_levels_hsw(uint8_t train_set)  	}  } +/* Properly updates "DP" with the correct signal levels. */ +static void +intel_dp_set_signal_levels(struct intel_dp *intel_dp, uint32_t *DP) +{ +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); +	struct drm_device *dev = intel_dig_port->base.base.dev; +	uint32_t signal_levels, mask; +	uint8_t train_set = intel_dp->train_set[0]; + +	if (IS_HASWELL(dev)) { +		signal_levels = intel_hsw_signal_levels(train_set); +		mask = DDI_BUF_EMP_MASK; +	} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { +		signal_levels = intel_gen7_edp_signal_levels(train_set); +		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; +	} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { +		signal_levels = intel_gen6_edp_signal_levels(train_set); +		mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB; +	} else { +		signal_levels = intel_gen4_signal_levels(train_set); +		mask = DP_VOLTAGE_MASK | DP_PRE_EMPHASIS_MASK; +	} + +	DRM_DEBUG_KMS("Using signal levels %08x\n", signal_levels); + +	*DP = (*DP & ~mask) | signal_levels; +} +  static bool  intel_dp_set_link_train(struct intel_dp *intel_dp,  			uint32_t dp_reg_value, @@ -1791,7 +1863,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  	int voltage_tries, loop_tries;  	uint32_t DP = intel_dp->DP; -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		intel_ddi_prepare_link_retrain(encoder);  	/* Write the link configuration data */ @@ -1809,24 +1881,8 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  	for (;;) {  		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */  		uint8_t	    link_status[DP_LINK_STATUS_SIZE]; -		uint32_t    signal_levels; -		if (IS_HASWELL(dev)) { -			signal_levels = intel_dp_signal_levels_hsw( -							intel_dp->train_set[0]); -			DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels; -		} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { -			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; -		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { -			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; -		} else { -			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; -		} -		DRM_DEBUG_KMS("training pattern 1 signal levels %08x\n", -			      signal_levels); +		intel_dp_set_signal_levels(intel_dp, &DP);  		/* Set training pattern 1 */  		if (!intel_dp_set_link_train(intel_dp, DP, @@ -1882,7 +1938,6 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)  void  intel_dp_complete_link_train(struct intel_dp *intel_dp)  { -	struct drm_device *dev = intel_dp_to_dev(intel_dp);  	bool channel_eq = false;  	int tries, cr_tries;  	uint32_t DP = intel_dp->DP; @@ -1892,8 +1947,6 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  	cr_tries = 0;  	channel_eq = false;  	for (;;) { -		/* Use intel_dp->train_set[0] to set the voltage and pre emphasis values */ -		uint32_t    signal_levels;  		uint8_t	    link_status[DP_LINK_STATUS_SIZE];  		if (cr_tries > 5) { @@ -1902,19 +1955,7 @@ intel_dp_complete_link_train(struct intel_dp *intel_dp)  			break;  		} -		if (IS_HASWELL(dev)) { -			signal_levels = intel_dp_signal_levels_hsw(intel_dp->train_set[0]); -			DP = (DP & ~DDI_BUF_EMP_MASK) | signal_levels; -		} else if (IS_GEN7(dev) && is_cpu_edp(intel_dp) && !IS_VALLEYVIEW(dev)) { -			signal_levels = intel_gen7_edp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_IVB) | signal_levels; -		} else if (IS_GEN6(dev) && is_cpu_edp(intel_dp)) { -			signal_levels = intel_gen6_edp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~EDP_LINK_TRAIN_VOL_EMP_MASK_SNB) | signal_levels; -		} else { -			signal_levels = intel_dp_signal_levels(intel_dp->train_set[0]); -			DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; -		} +		intel_dp_set_signal_levels(intel_dp, &DP);  		/* channel eq pattern */  		if (!intel_dp_set_link_train(intel_dp, DP, @@ -1964,6 +2005,8 @@ intel_dp_link_down(struct intel_dp *intel_dp)  	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	struct drm_device *dev = intel_dig_port->base.base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_crtc *intel_crtc = +		to_intel_crtc(intel_dig_port->base.base.crtc);  	uint32_t DP = intel_dp->DP;  	/* @@ -1981,7 +2024,7 @@ intel_dp_link_down(struct intel_dp *intel_dp)  	 *   intel_ddi_prepare_link_retrain will take care of redoing the link  	 *   train.  	 */ -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		return;  	if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)) @@ -1998,7 +2041,8 @@ intel_dp_link_down(struct intel_dp *intel_dp)  	}  	POSTING_READ(intel_dp->output_reg); -	msleep(17); +	/* We don't really know why we're doing this */ +	intel_wait_for_vblank(dev, intel_crtc->pipe);  	if (HAS_PCH_IBX(dev) &&  	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) { @@ -2018,19 +2062,14 @@ intel_dp_link_down(struct intel_dp *intel_dp)  		/* Changes to enable or select take place the vblank  		 * after being written.  		 */ -		if (crtc == NULL) { -			/* We can arrive here never having been attached -			 * to a CRTC, for instance, due to inheriting -			 * random state from the BIOS. -			 * -			 * If the pipe is not running, play safe and -			 * wait for the clocks to stabilise before -			 * continuing. -			 */ +		if (WARN_ON(crtc == NULL)) { +			/* We should never try to disable a port without a crtc +			 * attached. For paranoia keep the code around for a +			 * bit. */  			POSTING_READ(intel_dp->output_reg);  			msleep(50);  		} else -			intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe); +			intel_wait_for_vblank(dev, intel_crtc->pipe);  	}  	DP &= ~DP_AUDIO_OUTPUT_ENABLE; @@ -2042,10 +2081,16 @@ intel_dp_link_down(struct intel_dp *intel_dp)  static bool  intel_dp_get_dpcd(struct intel_dp *intel_dp)  { +	char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3]; +  	if (intel_dp_aux_native_read_retry(intel_dp, 0x000, intel_dp->dpcd,  					   sizeof(intel_dp->dpcd)) == 0)  		return false; /* aux transfer failed */ +	hex_dump_to_buffer(intel_dp->dpcd, sizeof(intel_dp->dpcd), +			   32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false); +	DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump); +  	if (intel_dp->dpcd[DP_DPCD_REV] == 0)  		return false; /* DPCD not present */ @@ -2206,6 +2251,8 @@ static enum drm_connector_status  ironlake_dp_detect(struct intel_dp *intel_dp)  {  	struct drm_device *dev = intel_dp_to_dev(intel_dp); +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);  	enum drm_connector_status status;  	/* Can't disconnect eDP, but you can close the lid... */ @@ -2216,6 +2263,9 @@ ironlake_dp_detect(struct intel_dp *intel_dp)  		return status;  	} +	if (!ibx_digital_port_connected(dev_priv, intel_dig_port)) +		return connector_status_disconnected; +  	return intel_dp_detect_dpcd(intel_dp);  } @@ -2290,13 +2340,6 @@ intel_dp_get_edid_modes(struct drm_connector *connector, struct i2c_adapter *ada  	return intel_ddc_get_modes(connector, adapter);  } - -/** - * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. - * - * \return true if DP port is connected. - * \return false if DP port is disconnected. - */  static enum drm_connector_status  intel_dp_detect(struct drm_connector *connector, bool force)  { @@ -2306,7 +2349,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)  	struct drm_device *dev = connector->dev;  	enum drm_connector_status status;  	struct edid *edid = NULL; -	char dpcd_hex_dump[sizeof(intel_dp->dpcd) * 3];  	intel_dp->has_audio = false; @@ -2315,10 +2357,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)  	else  		status = g4x_dp_detect(intel_dp); -	hex_dump_to_buffer(intel_dp->dpcd, sizeof(intel_dp->dpcd), -			   32, 1, dpcd_hex_dump, sizeof(dpcd_hex_dump), false); -	DRM_DEBUG_KMS("DPCD: %s\n", dpcd_hex_dump); -  	if (status != connector_status_connected)  		return status; @@ -2445,11 +2483,8 @@ intel_dp_set_property(struct drm_connector *connector,  	return -EINVAL;  done: -	if (intel_encoder->base.crtc) { -		struct drm_crtc *crtc = intel_encoder->base.crtc; -		intel_set_mode(crtc, &crtc->mode, -			       crtc->x, crtc->y, crtc->fb); -	} +	if (intel_encoder->base.crtc) +		intel_crtc_restore_mode(intel_encoder->base.crtc);  	return 0;  } @@ -2742,7 +2777,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,  	intel_connector_attach_encoder(intel_connector, intel_encoder);  	drm_sysfs_connector_add(connector); -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;  	else  		intel_connector->get_hw_state = intel_connector_get_hw_state; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 8a1bd4a3ad0..54a034c8206 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -153,6 +153,7 @@ struct intel_encoder {  	bool cloneable;  	bool connectors_active;  	void (*hot_plug)(struct intel_encoder *); +	void (*pre_pll_enable)(struct intel_encoder *);  	void (*pre_enable)(struct intel_encoder *);  	void (*enable)(struct intel_encoder *);  	void (*disable)(struct intel_encoder *); @@ -443,6 +444,7 @@ extern void intel_mark_idle(struct drm_device *dev);  extern void intel_mark_fb_busy(struct drm_i915_gem_object *obj);  extern void intel_mark_fb_idle(struct drm_i915_gem_object *obj);  extern bool intel_lvds_init(struct drm_device *dev); +extern bool intel_is_dual_link_lvds(struct drm_device *dev);  extern void intel_dp_init(struct drm_device *dev, int output_reg,  			  enum port port);  extern void intel_dp_init_connector(struct intel_digital_port *intel_dig_port, @@ -502,9 +504,10 @@ struct intel_set_config {  	bool mode_changed;  }; -extern bool intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, -			   int x, int y, struct drm_framebuffer *old_fb); +extern int intel_set_mode(struct drm_crtc *crtc, struct drm_display_mode *mode, +			  int x, int y, struct drm_framebuffer *old_fb);  extern void intel_modeset_disable(struct drm_device *dev); +extern void intel_crtc_restore_mode(struct drm_crtc *crtc);  extern void intel_crtc_load_lut(struct drm_crtc *crtc);  extern void intel_crtc_update_dpms(struct drm_crtc *crtc);  extern void intel_encoder_noop(struct drm_encoder *encoder); @@ -546,6 +549,9 @@ hdmi_to_dig_port(struct intel_hdmi *intel_hdmi)  	return container_of(intel_hdmi, struct intel_digital_port, hdmi);  } +bool ibx_digital_port_connected(struct drm_i915_private *dev_priv, +				struct intel_digital_port *port); +  extern void intel_connector_attach_encoder(struct intel_connector *connector,  					   struct intel_encoder *encoder);  extern struct drm_encoder *intel_best_encoder(struct drm_connector *connector); @@ -589,6 +595,7 @@ extern int intel_framebuffer_init(struct drm_device *dev,  				  struct drm_mode_fb_cmd2 *mode_cmd,  				  struct drm_i915_gem_object *obj);  extern int intel_fbdev_init(struct drm_device *dev); +extern void intel_fbdev_initial_config(struct drm_device *dev);  extern void intel_fbdev_fini(struct drm_device *dev);  extern void intel_fbdev_set_suspend(struct drm_device *dev, int state);  extern void intel_prepare_page_flip(struct drm_device *dev, int plane); diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 7b30b5c2c4e..71d55801c0d 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -83,7 +83,9 @@ static int intelfb_create(struct intel_fbdev *ifbdev,  	size = mode_cmd.pitches[0] * mode_cmd.height;  	size = ALIGN(size, PAGE_SIZE); -	obj = i915_gem_alloc_object(dev, size); +	obj = i915_gem_object_create_stolen(dev, size); +	if (obj == NULL) +		obj = i915_gem_alloc_object(dev, size);  	if (!obj) {  		DRM_ERROR("failed to allocate framebuffer\n");  		ret = -ENOMEM; @@ -153,6 +155,13 @@ static int intelfb_create(struct intel_fbdev *ifbdev,  	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);  	drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); +	/* If the object is shmemfs backed, it will have given us zeroed pages. +	 * If the object is stolen however, it will be full of whatever +	 * garbage was left in there. +	 */ +	if (ifbdev->ifb.obj->stolen) +		memset_io(info->screen_base, 0, info->screen_size); +  	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */  	DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", @@ -241,10 +250,18 @@ int intel_fbdev_init(struct drm_device *dev)  	}  	drm_fb_helper_single_add_all_connectors(&ifbdev->helper); -	drm_fb_helper_initial_config(&ifbdev->helper, 32); +  	return 0;  } +void intel_fbdev_initial_config(struct drm_device *dev) +{ +	drm_i915_private_t *dev_priv = dev->dev_private; + +	/* Due to peculiar init order wrt to hpd handling this is separate. */ +	drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 32); +} +  void intel_fbdev_fini(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2ee9821b9d9..6387f9b0df9 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -48,7 +48,7 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi)  	struct drm_i915_private *dev_priv = dev->dev_private;  	uint32_t enabled_bits; -	enabled_bits = IS_HASWELL(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; +	enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE;  	WARN(I915_READ(intel_hdmi->sdvox_reg) & enabled_bits,  	     "HDMI port enabled, expecting disabled\n"); @@ -793,16 +793,21 @@ static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi)  static enum drm_connector_status  intel_hdmi_detect(struct drm_connector *connector, bool force)  { +	struct drm_device *dev = connector->dev;  	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);  	struct intel_digital_port *intel_dig_port =  		hdmi_to_dig_port(intel_hdmi);  	struct intel_encoder *intel_encoder = &intel_dig_port->base; -	struct drm_i915_private *dev_priv = connector->dev->dev_private; +	struct drm_i915_private *dev_priv = dev->dev_private;  	struct edid *edid;  	enum drm_connector_status status = connector_status_disconnected; -	if (IS_G4X(connector->dev) && !g4x_hdmi_connected(intel_hdmi)) + +	if (IS_G4X(dev) && !g4x_hdmi_connected(intel_hdmi))  		return status; +	else if (HAS_PCH_SPLIT(dev) && +		 !ibx_digital_port_connected(dev_priv, intel_dig_port)) +		 return status;  	intel_hdmi->has_hdmi_sink = false;  	intel_hdmi->has_audio = false; @@ -912,11 +917,8 @@ intel_hdmi_set_property(struct drm_connector *connector,  	return -EINVAL;  done: -	if (intel_dig_port->base.base.crtc) { -		struct drm_crtc *crtc = intel_dig_port->base.base.crtc; -		intel_set_mode(crtc, &crtc->mode, -			       crtc->x, crtc->y, crtc->fb); -	} +	if (intel_dig_port->base.base.crtc) +		intel_crtc_restore_mode(intel_dig_port->base.base.crtc);  	return 0;  } @@ -1013,7 +1015,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,  		intel_hdmi->set_infoframes = cpt_set_infoframes;  	} -	if (IS_HASWELL(dev)) +	if (HAS_DDI(dev))  		intel_connector->get_hw_state = intel_ddi_connector_get_hw_state;  	else  		intel_connector->get_hw_state = intel_connector_get_hw_state; diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 3ef5af15b81..7f090417096 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -63,6 +63,7 @@ intel_i2c_reset(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	I915_WRITE(dev_priv->gpio_mmio_base + GMBUS0, 0); +	I915_WRITE(dev_priv->gpio_mmio_base + GMBUS4, 0);  }  static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) @@ -202,6 +203,68 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin)  	algo->data = bus;  } +#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 4) +static int +gmbus_wait_hw_status(struct drm_i915_private *dev_priv, +		     u32 gmbus2_status, +		     u32 gmbus4_irq_en) +{ +	int i; +	int reg_offset = dev_priv->gpio_mmio_base; +	u32 gmbus2 = 0; +	DEFINE_WAIT(wait); + +	/* Important: The hw handles only the first bit, so set only one! Since +	 * we also need to check for NAKs besides the hw ready/idle signal, we +	 * need to wake up periodically and check that ourselves. */ +	I915_WRITE(GMBUS4 + reg_offset, gmbus4_irq_en); + +	for (i = 0; i < msecs_to_jiffies(50) + 1; i++) { +		prepare_to_wait(&dev_priv->gmbus_wait_queue, &wait, +				TASK_UNINTERRUPTIBLE); + +		gmbus2 = I915_READ_NOTRACE(GMBUS2 + reg_offset); +		if (gmbus2 & (GMBUS_SATOER | gmbus2_status)) +			break; + +		schedule_timeout(1); +	} +	finish_wait(&dev_priv->gmbus_wait_queue, &wait); + +	I915_WRITE(GMBUS4 + reg_offset, 0); + +	if (gmbus2 & GMBUS_SATOER) +		return -ENXIO; +	if (gmbus2 & gmbus2_status) +		return 0; +	return -ETIMEDOUT; +} + +static int +gmbus_wait_idle(struct drm_i915_private *dev_priv) +{ +	int ret; +	int reg_offset = dev_priv->gpio_mmio_base; + +#define C ((I915_READ_NOTRACE(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0) + +	if (!HAS_GMBUS_IRQ(dev_priv->dev)) +		return wait_for(C, 10); + +	/* Important: The hw handles only the first bit, so set only one! */ +	I915_WRITE(GMBUS4 + reg_offset, GMBUS_IDLE_EN); + +	ret = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10); + +	I915_WRITE(GMBUS4 + reg_offset, 0); + +	if (ret) +		return 0; +	else +		return -ETIMEDOUT; +#undef C +} +  static int  gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,  		u32 gmbus1_index) @@ -219,15 +282,11 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,  	while (len) {  		int ret;  		u32 val, loop = 0; -		u32 gmbus2; -		ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & -			       (GMBUS_SATOER | GMBUS_HW_RDY), -			       50); +		ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY, +					   GMBUS_HW_RDY_EN);  		if (ret) -			return -ETIMEDOUT; -		if (gmbus2 & GMBUS_SATOER) -			return -ENXIO; +			return ret;  		val = I915_READ(GMBUS3 + reg_offset);  		do { @@ -261,7 +320,6 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)  		   GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);  	while (len) {  		int ret; -		u32 gmbus2;  		val = loop = 0;  		do { @@ -270,13 +328,10 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)  		I915_WRITE(GMBUS3 + reg_offset, val); -		ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & -			       (GMBUS_SATOER | GMBUS_HW_RDY), -			       50); +		ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_RDY, +					   GMBUS_HW_RDY_EN);  		if (ret) -			return -ETIMEDOUT; -		if (gmbus2 & GMBUS_SATOER) -			return -ENXIO; +			return ret;  	}  	return 0;  } @@ -345,8 +400,6 @@ gmbus_xfer(struct i2c_adapter *adapter,  	I915_WRITE(GMBUS0 + reg_offset, bus->reg0);  	for (i = 0; i < num; i++) { -		u32 gmbus2; -  		if (gmbus_is_index_read(msgs, i, num)) {  			ret = gmbus_xfer_index_read(dev_priv, &msgs[i]);  			i += 1;  /* set i to the index of the read xfer */ @@ -361,13 +414,12 @@ gmbus_xfer(struct i2c_adapter *adapter,  		if (ret == -ENXIO)  			goto clear_err; -		ret = wait_for((gmbus2 = I915_READ(GMBUS2 + reg_offset)) & -			       (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), -			       50); +		ret = gmbus_wait_hw_status(dev_priv, GMBUS_HW_WAIT_PHASE, +					   GMBUS_HW_WAIT_EN); +		if (ret == -ENXIO) +			goto clear_err;  		if (ret)  			goto timeout; -		if (gmbus2 & GMBUS_SATOER) -			goto clear_err;  	}  	/* Generate a STOP condition on the bus. Note that gmbus can't generata @@ -380,8 +432,7 @@ gmbus_xfer(struct i2c_adapter *adapter,  	 * We will re-enable it at the start of the next xfer,  	 * till then let it sleep.  	 */ -	if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, -		     10)) { +	if (gmbus_wait_idle(dev_priv)) {  		DRM_DEBUG_KMS("GMBUS [%s] timed out waiting for idle\n",  			 adapter->name);  		ret = -ETIMEDOUT; @@ -405,8 +456,7 @@ clear_err:  	 * it's slow responding and only answers on the 2nd retry.  	 */  	ret = -ENXIO; -	if (wait_for((I915_READ(GMBUS2 + reg_offset) & GMBUS_ACTIVE) == 0, -		     10)) { +	if (gmbus_wait_idle(dev_priv)) {  		DRM_DEBUG_KMS("GMBUS [%s] timed out after NAK\n",  			      adapter->name);  		ret = -ETIMEDOUT; @@ -469,6 +519,7 @@ int intel_setup_gmbus(struct drm_device *dev)  		dev_priv->gpio_mmio_base = 0;  	mutex_init(&dev_priv->gmbus_mutex); +	init_waitqueue_head(&dev_priv->gmbus_wait_queue);  	for (i = 0; i < GMBUS_NUM_PORTS; i++) {  		struct intel_gmbus *bus = &dev_priv->gmbus[i]; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b9a660a5367..8c61876dbe9 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -52,6 +52,8 @@ struct intel_lvds_encoder {  	u32 pfit_control;  	u32 pfit_pgm_ratios;  	bool pfit_dirty; +	bool is_dual_link; +	u32 reg;  	struct intel_lvds_connector *attached_connector;  }; @@ -71,15 +73,10 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,  {  	struct drm_device *dev = encoder->base.dev;  	struct drm_i915_private *dev_priv = dev->dev_private; -	u32 lvds_reg, tmp; - -	if (HAS_PCH_SPLIT(dev)) { -		lvds_reg = PCH_LVDS; -	} else { -		lvds_reg = LVDS; -	} +	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); +	u32 tmp; -	tmp = I915_READ(lvds_reg); +	tmp = I915_READ(lvds_encoder->reg);  	if (!(tmp & LVDS_PORT_EN))  		return false; @@ -92,6 +89,68 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,  	return true;  } +/* 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. + */ +static void intel_pre_pll_enable_lvds(struct intel_encoder *encoder) +{ +	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base); +	struct drm_device *dev = encoder->base.dev; +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); +	struct drm_display_mode *fixed_mode = +		lvds_encoder->attached_connector->base.panel.fixed_mode; +	int pipe = intel_crtc->pipe; +	u32 temp; + +	temp = I915_READ(lvds_encoder->reg); +	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; + +	if (HAS_PCH_CPT(dev)) { +		temp &= ~PORT_TRANS_SEL_MASK; +		temp |= PORT_TRANS_SEL_CPT(pipe); +	} else { +		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 (lvds_encoder->is_dual_link) +		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, note that there is no +	 * special lvds dither control bit on pch-split platforms, dithering is +	 * only controlled through the PIPECONF reg. */ +	if (INTEL_INFO(dev)->gen == 4) { +		if (dev_priv->lvds_dither) +			temp |= LVDS_ENABLE_DITHER; +		else +			temp &= ~LVDS_ENABLE_DITHER; +	} +	temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY); +	if (fixed_mode->flags & DRM_MODE_FLAG_NHSYNC) +		temp |= LVDS_HSYNC_POLARITY; +	if (fixed_mode->flags & DRM_MODE_FLAG_NVSYNC) +		temp |= LVDS_VSYNC_POLARITY; + +	I915_WRITE(lvds_encoder->reg, temp); +} +  /**   * Sets the power state for the panel.   */ @@ -101,19 +160,17 @@ static void intel_enable_lvds(struct intel_encoder *encoder)  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);  	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);  	struct drm_i915_private *dev_priv = dev->dev_private; -	u32 ctl_reg, lvds_reg, stat_reg; +	u32 ctl_reg, stat_reg;  	if (HAS_PCH_SPLIT(dev)) {  		ctl_reg = PCH_PP_CONTROL; -		lvds_reg = PCH_LVDS;  		stat_reg = PCH_PP_STATUS;  	} else {  		ctl_reg = PP_CONTROL; -		lvds_reg = LVDS;  		stat_reg = PP_STATUS;  	} -	I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN); +	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);  	if (lvds_encoder->pfit_dirty) {  		/* @@ -132,7 +189,7 @@ static void intel_enable_lvds(struct intel_encoder *encoder)  	}  	I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON); -	POSTING_READ(lvds_reg); +	POSTING_READ(lvds_encoder->reg);  	if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000))  		DRM_ERROR("timed out waiting for panel to power on\n"); @@ -144,15 +201,13 @@ static void intel_disable_lvds(struct intel_encoder *encoder)  	struct drm_device *dev = encoder->base.dev;  	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);  	struct drm_i915_private *dev_priv = dev->dev_private; -	u32 ctl_reg, lvds_reg, stat_reg; +	u32 ctl_reg, stat_reg;  	if (HAS_PCH_SPLIT(dev)) {  		ctl_reg = PCH_PP_CONTROL; -		lvds_reg = PCH_LVDS;  		stat_reg = PCH_PP_STATUS;  	} else {  		ctl_reg = PP_CONTROL; -		lvds_reg = LVDS;  		stat_reg = PP_STATUS;  	} @@ -167,8 +222,8 @@ static void intel_disable_lvds(struct intel_encoder *encoder)  		lvds_encoder->pfit_dirty = true;  	} -	I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); -	POSTING_READ(lvds_reg); +	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN); +	POSTING_READ(lvds_encoder->reg);  }  static int intel_lvds_mode_valid(struct drm_connector *connector, @@ -591,8 +646,7 @@ static int intel_lvds_set_property(struct drm_connector *connector,  			 * If the CRTC is enabled, the display will be changed  			 * according to the new panel fitting mode.  			 */ -			intel_set_mode(crtc, &crtc->mode, -				       crtc->x, crtc->y, crtc->fb); +			intel_crtc_restore_mode(crtc);  		}  	} @@ -903,6 +957,66 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev,  	return false;  } +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 */ +}; + +bool intel_is_dual_link_lvds(struct drm_device *dev) +{ +	struct intel_encoder *encoder; +	struct intel_lvds_encoder *lvds_encoder; + +	list_for_each_entry(encoder, &dev->mode_config.encoder_list, +			    base.head) { +		if (encoder->type == INTEL_OUTPUT_LVDS) { +			lvds_encoder = to_lvds_encoder(&encoder->base); + +			return lvds_encoder->is_dual_link; +		} +	} + +	return false; +} + +static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) +{ +	struct drm_device *dev = lvds_encoder->base.base.dev; +	unsigned int val; +	struct drm_i915_private *dev_priv = dev->dev_private; + +	/* 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; + +	/* 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(lvds_encoder->reg); +	if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED))) +		val = dev_priv->bios_lvds_val; + +	return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; +} +  static bool intel_lvds_supported(struct drm_device *dev)  {  	/* With the introduction of the PCH we gained a dedicated @@ -988,6 +1102,7 @@ bool intel_lvds_init(struct drm_device *dev)  			 DRM_MODE_ENCODER_LVDS);  	intel_encoder->enable = intel_enable_lvds; +	intel_encoder->pre_pll_enable = intel_pre_pll_enable_lvds;  	intel_encoder->disable = intel_disable_lvds;  	intel_encoder->get_hw_state = intel_lvds_get_hw_state;  	intel_connector->get_hw_state = intel_connector_get_hw_state; @@ -1009,6 +1124,12 @@ bool intel_lvds_init(struct drm_device *dev)  	connector->interlace_allowed = false;  	connector->doublescan_allowed = false; +	if (HAS_PCH_SPLIT(dev)) { +		lvds_encoder->reg = PCH_LVDS; +	} else { +		lvds_encoder->reg = LVDS; +	} +  	/* create the scaling mode property */  	drm_mode_create_scaling_mode_property(dev);  	drm_object_attach_property(&connector->base, @@ -1109,6 +1230,10 @@ bool intel_lvds_init(struct drm_device *dev)  		goto failed;  out: +	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder); +	DRM_DEBUG_KMS("detected %s-link lvds configuration\n", +		      lvds_encoder->is_dual_link ? "dual" : "single"); +  	/*  	 * Unlock registers and just  	 * leave them unlocked diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index b00f1c83adc..49249bb9748 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -28,7 +28,6 @@  #include <linux/fb.h>  #include <drm/drm_edid.h>  #include <drm/drmP.h> -#include <drm/drm_edid.h>  #include "intel_drv.h"  #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index d7bc817f51a..fabe0acf808 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1333,8 +1333,10 @@ void intel_setup_overlay(struct drm_device *dev)  	overlay->dev = dev; -	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); -	if (!reg_bo) +	reg_bo = i915_gem_object_create_stolen(dev, PAGE_SIZE); +	if (reg_bo == NULL) +		reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); +	if (reg_bo == NULL)  		goto out_free;  	overlay->reg_bo = reg_bo; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e6f54ffab3b..5a8a72c5a89 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -440,12 +440,6 @@ void intel_update_fbc(struct drm_device *dev)  		dev_priv->no_fbc_reason = FBC_MODULE_PARAM;  		goto out_disable;  	} -	if (intel_fb->obj->base.size > dev_priv->cfb_size) { -		DRM_DEBUG_KMS("framebuffer too large, disabling " -			      "compression\n"); -		dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; -		goto out_disable; -	}  	if ((crtc->mode.flags & DRM_MODE_FLAG_INTERLACE) ||  	    (crtc->mode.flags & DRM_MODE_FLAG_DBLSCAN)) {  		DRM_DEBUG_KMS("mode incompatible with compression, " @@ -479,6 +473,14 @@ void intel_update_fbc(struct drm_device *dev)  	if (in_dbg_master())  		goto out_disable; +	if (i915_gem_stolen_setup_compression(dev, intel_fb->obj->base.size)) { +		DRM_INFO("not enough stolen space for compressed buffer (need %zd bytes), disabling\n", intel_fb->obj->base.size); +		DRM_INFO("hint: you may be able to increase stolen memory size in the BIOS to avoid this\n"); +		DRM_DEBUG_KMS("framebuffer too large, disabling compression\n"); +		dev_priv->no_fbc_reason = FBC_STOLEN_TOO_SMALL; +		goto out_disable; +	} +  	/* If the scanout has not changed, don't modify the FBC settings.  	 * Note that we make the fundamental assumption that the fb->obj  	 * cannot be unpinned (and have its GTT offset and fence revoked) @@ -526,6 +528,7 @@ out_disable:  		DRM_DEBUG_KMS("unsupported config, disabling FBC\n");  		intel_disable_fbc(dev);  	} +	i915_gem_stolen_cleanup_compression(dev);  }  static void i915_pineview_get_mem_freq(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index ae253e04c39..59e02691baf 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -601,6 +601,13 @@ gen6_add_request(struct intel_ring_buffer *ring)  	return 0;  } +static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev, +					      u32 seqno) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	return dev_priv->last_seqno < seqno; +} +  /**   * intel_ring_sync - sync the waiter to the signaller on seqno   * @@ -631,11 +638,20 @@ gen6_ring_sync(struct intel_ring_buffer *waiter,  	if (ret)  		return ret; -	intel_ring_emit(waiter, -			dw1 | signaller->semaphore_register[waiter->id]); -	intel_ring_emit(waiter, seqno); -	intel_ring_emit(waiter, 0); -	intel_ring_emit(waiter, MI_NOOP); +	/* If seqno wrap happened, omit the wait with no-ops */ +	if (likely(!i915_gem_has_seqno_wrapped(waiter->dev, seqno))) { +		intel_ring_emit(waiter, +				dw1 | +				signaller->semaphore_register[waiter->id]); +		intel_ring_emit(waiter, seqno); +		intel_ring_emit(waiter, 0); +		intel_ring_emit(waiter, MI_NOOP); +	} else { +		intel_ring_emit(waiter, MI_NOOP); +		intel_ring_emit(waiter, MI_NOOP); +		intel_ring_emit(waiter, MI_NOOP); +		intel_ring_emit(waiter, MI_NOOP); +	}  	intel_ring_advance(waiter);  	return 0; @@ -716,6 +732,12 @@ ring_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)  	return intel_read_status_page(ring, I915_GEM_HWS_INDEX);  } +static void +ring_set_seqno(struct intel_ring_buffer *ring, u32 seqno) +{ +	intel_write_status_page(ring, I915_GEM_HWS_INDEX, seqno); +} +  static u32  pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)  { @@ -723,6 +745,13 @@ pc_render_get_seqno(struct intel_ring_buffer *ring, bool lazy_coherency)  	return pc->cpu_page[0];  } +static void +pc_render_set_seqno(struct intel_ring_buffer *ring, u32 seqno) +{ +	struct pipe_control *pc = ring->private; +	pc->cpu_page[0] = seqno; +} +  static bool  gen5_ring_get_irq(struct intel_ring_buffer *ring)  { @@ -1152,7 +1181,11 @@ static int intel_init_ring_buffer(struct drm_device *dev,  			return ret;  	} -	obj = i915_gem_alloc_object(dev, ring->size); +	obj = NULL; +	if (!HAS_LLC(dev)) +		obj = i915_gem_object_create_stolen(dev, ring->size); +	if (obj == NULL) +		obj = i915_gem_alloc_object(dev, ring->size);  	if (obj == NULL) {  		DRM_ERROR("Failed to allocate ringbuffer\n");  		ret = -ENOMEM; @@ -1190,6 +1223,8 @@ static int intel_init_ring_buffer(struct drm_device *dev,  	if (IS_I830(ring->dev) || IS_845G(ring->dev))  		ring->effective_size -= 128; +	intel_ring_init_seqno(ring, dev_priv->last_seqno); +  	return 0;  err_unmap: @@ -1398,11 +1433,31 @@ intel_ring_alloc_seqno(struct intel_ring_buffer *ring)  	return i915_gem_get_seqno(ring->dev, &ring->outstanding_lazy_request);  } +static int __intel_ring_begin(struct intel_ring_buffer *ring, +			      int bytes) +{ +	int ret; + +	if (unlikely(ring->tail + bytes > ring->effective_size)) { +		ret = intel_wrap_ring_buffer(ring); +		if (unlikely(ret)) +			return ret; +	} + +	if (unlikely(ring->space < bytes)) { +		ret = ring_wait_for_space(ring, bytes); +		if (unlikely(ret)) +			return ret; +	} + +	ring->space -= bytes; +	return 0; +} +  int intel_ring_begin(struct intel_ring_buffer *ring,  		     int num_dwords)  {  	drm_i915_private_t *dev_priv = ring->dev->dev_private; -	int n = 4*num_dwords;  	int ret;  	ret = i915_gem_check_wedge(dev_priv, dev_priv->mm.interruptible); @@ -1414,20 +1469,21 @@ int intel_ring_begin(struct intel_ring_buffer *ring,  	if (ret)  		return ret; -	if (unlikely(ring->tail + n > ring->effective_size)) { -		ret = intel_wrap_ring_buffer(ring); -		if (unlikely(ret)) -			return ret; -	} +	return __intel_ring_begin(ring, num_dwords * sizeof(uint32_t)); +} -	if (unlikely(ring->space < n)) { -		ret = ring_wait_for_space(ring, n); -		if (unlikely(ret)) -			return ret; +void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno) +{ +	struct drm_i915_private *dev_priv = ring->dev->dev_private; + +	BUG_ON(ring->outstanding_lazy_request); + +	if (INTEL_INFO(ring->dev)->gen >= 6) { +		I915_WRITE(RING_SYNC_0(ring->mmio_base), 0); +		I915_WRITE(RING_SYNC_1(ring->mmio_base), 0);  	} -	ring->space -= n; -	return 0; +	ring->set_seqno(ring, seqno);  }  void intel_ring_advance(struct intel_ring_buffer *ring) @@ -1592,6 +1648,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)  		ring->irq_put = gen6_ring_put_irq;  		ring->irq_enable_mask = GT_USER_INTERRUPT;  		ring->get_seqno = gen6_ring_get_seqno; +		ring->set_seqno = ring_set_seqno;  		ring->sync_to = gen6_ring_sync;  		ring->semaphore_register[0] = MI_SEMAPHORE_SYNC_INVALID;  		ring->semaphore_register[1] = MI_SEMAPHORE_SYNC_RV; @@ -1602,6 +1659,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)  		ring->add_request = pc_render_add_request;  		ring->flush = gen4_render_ring_flush;  		ring->get_seqno = pc_render_get_seqno; +		ring->set_seqno = pc_render_set_seqno;  		ring->irq_get = gen5_ring_get_irq;  		ring->irq_put = gen5_ring_put_irq;  		ring->irq_enable_mask = GT_USER_INTERRUPT | GT_PIPE_NOTIFY; @@ -1612,6 +1670,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)  		else  			ring->flush = gen4_render_ring_flush;  		ring->get_seqno = ring_get_seqno; +		ring->set_seqno = ring_set_seqno;  		if (IS_GEN2(dev)) {  			ring->irq_get = i8xx_ring_get_irq;  			ring->irq_put = i8xx_ring_put_irq; @@ -1683,6 +1742,7 @@ int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size)  	else  		ring->flush = gen4_render_ring_flush;  	ring->get_seqno = ring_get_seqno; +	ring->set_seqno = ring_set_seqno;  	if (IS_GEN2(dev)) {  		ring->irq_get = i8xx_ring_get_irq;  		ring->irq_put = i8xx_ring_put_irq; @@ -1743,6 +1803,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)  		ring->flush = gen6_ring_flush;  		ring->add_request = gen6_add_request;  		ring->get_seqno = gen6_ring_get_seqno; +		ring->set_seqno = ring_set_seqno;  		ring->irq_enable_mask = GEN6_BSD_USER_INTERRUPT;  		ring->irq_get = gen6_ring_get_irq;  		ring->irq_put = gen6_ring_put_irq; @@ -1758,6 +1819,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)  		ring->flush = bsd_ring_flush;  		ring->add_request = i9xx_add_request;  		ring->get_seqno = ring_get_seqno; +		ring->set_seqno = ring_set_seqno;  		if (IS_GEN5(dev)) {  			ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;  			ring->irq_get = gen5_ring_get_irq; @@ -1787,6 +1849,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)  	ring->flush = blt_ring_flush;  	ring->add_request = gen6_add_request;  	ring->get_seqno = gen6_ring_get_seqno; +	ring->set_seqno = ring_set_seqno;  	ring->irq_enable_mask = GEN6_BLITTER_USER_INTERRUPT;  	ring->irq_get = gen6_ring_get_irq;  	ring->irq_put = gen6_ring_put_irq; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 6af87cd0572..d66208c2c48 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -90,6 +90,8 @@ struct  intel_ring_buffer {  	 */  	u32		(*get_seqno)(struct intel_ring_buffer *ring,  				     bool lazy_coherency); +	void		(*set_seqno)(struct intel_ring_buffer *ring, +				     u32 seqno);  	int		(*dispatch_execbuffer)(struct intel_ring_buffer *ring,  					       u32 offset, u32 length,  					       unsigned flags); @@ -178,6 +180,13 @@ intel_read_status_page(struct intel_ring_buffer *ring,  	return ring->status_page.page_addr[reg];  } +static inline void +intel_write_status_page(struct intel_ring_buffer *ring, +			int reg, u32 value) +{ +	ring->status_page.page_addr[reg] = value; +} +  /**   * Reads a dword out of the status page, which is written to from the command   * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or @@ -208,7 +217,7 @@ static inline void intel_ring_emit(struct intel_ring_buffer *ring,  }  void intel_ring_advance(struct intel_ring_buffer *ring);  int __must_check intel_ring_idle(struct intel_ring_buffer *ring); - +void intel_ring_init_seqno(struct intel_ring_buffer *ring, u32 seqno);  int intel_ring_flush_all_caches(struct intel_ring_buffer *ring);  int intel_ring_invalidate_all_caches(struct intel_ring_buffer *ring); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index c275bf0fa36..153377bed66 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1997,11 +1997,8 @@ set_value:  done: -	if (intel_sdvo->base.base.crtc) { -		struct drm_crtc *crtc = intel_sdvo->base.base.crtc; -		intel_set_mode(crtc, &crtc->mode, -			       crtc->x, crtc->y, crtc->fb); -	} +	if (intel_sdvo->base.base.crtc) +		intel_crtc_restore_mode(intel_sdvo->base.base.crtc);  	return 0;  #undef CHECK_PROPERTY diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index ea93520c127..984a113c5d1 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1479,8 +1479,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop  	}  	if (changed && crtc) -		intel_set_mode(crtc, &crtc->mode, -			       crtc->x, crtc->y, crtc->fb); +		intel_crtc_restore_mode(crtc);  out:  	return ret;  }  |