diff options
Diffstat (limited to 'drivers/gpu/drm')
54 files changed, 1080 insertions, 554 deletions
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c index 3e257a50bf5..61e1ef90d4e 100644 --- a/drivers/gpu/drm/drm_bufs.c +++ b/drivers/gpu/drm/drm_bufs.c @@ -46,10 +46,11 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,  	list_for_each_entry(entry, &dev->maplist, head) {  		/*  		 * Because the kernel-userspace ABI is fixed at a 32-bit offset -		 * while PCI resources may live above that, we ignore the map -		 * offset for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS. -		 * It is assumed that each driver will have only one resource of -		 * each type. +		 * while PCI resources may live above that, we only compare the +		 * lower 32 bits of the map offset for maps of type +		 * _DRM_FRAMEBUFFER or _DRM_REGISTERS. +		 * It is assumed that if a driver have more than one resource +		 * of each type, the lower 32 bits are different.  		 */  		if (!entry->map ||  		    map->type != entry->map->type || @@ -59,9 +60,12 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,  		case _DRM_SHM:  			if (map->flags != _DRM_CONTAINS_LOCK)  				break; +			return entry;  		case _DRM_REGISTERS:  		case _DRM_FRAME_BUFFER: -			return entry; +			if ((entry->map->offset & 0xffffffff) == +			    (map->offset & 0xffffffff)) +				return entry;  		default: /* Make gcc happy */  			;  		} @@ -183,9 +187,6 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,  			return -EINVAL;  		}  #endif -#ifdef __alpha__ -		map->offset += dev->hose->mem_space->start; -#endif  		/* Some drivers preinitialize some maps, without the X Server  		 * needing to be aware of it.  Therefore, we just return success  		 * when the server tries to create a duplicate map. diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 872747c5a54..82db1850666 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -886,9 +886,6 @@ int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)  	total_objects += dev->mode_config.num_connector;  	total_objects += dev->mode_config.num_encoder; -	if (total_objects == 0) -		return -EINVAL; -  	group->id_list = kzalloc(total_objects * sizeof(uint32_t), GFP_KERNEL);  	if (!group->id_list)  		return -ENOMEM; @@ -1113,7 +1110,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,  	if (card_res->count_fbs >= fb_count) {  		copied = 0;  		fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr; -		list_for_each_entry(fb, &file_priv->fbs, head) { +		list_for_each_entry(fb, &file_priv->fbs, filp_head) {  			if (put_user(fb->base.id, fb_id + copied)) {  				ret = -EFAULT;  				goto out; diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 0a9357c66ff..09292193daf 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -184,9 +184,9 @@ drm_edid_block_valid(u8 *raw_edid)  bad:  	if (raw_edid) { -		DRM_ERROR("Raw EDID:\n"); +		printk(KERN_ERR "Raw EDID:\n");  		print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH); -		printk("\n"); +		printk(KERN_ERR "\n");  	}  	return 0;  } @@ -258,6 +258,17 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,  	return ret == 2 ? 0 : -1;  } +static bool drm_edid_is_zero(u8 *in_edid, int length) +{ +	int i; +	u32 *raw_edid = (u32 *)in_edid; + +	for (i = 0; i < length / 4; i++) +		if (*(raw_edid + i) != 0) +			return false; +	return true; +} +  static u8 *  drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)  { @@ -273,6 +284,10 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)  			goto out;  		if (drm_edid_block_valid(block))  			break; +		if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) { +			connector->null_edid_counter++; +			goto carp; +		}  	}  	if (i == 4)  		goto carp; diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 74e4ff57801..4012fe42346 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -34,6 +34,7 @@  #include <linux/module.h>  #include <linux/mman.h>  #include <linux/pagemap.h> +#include <linux/shmem_fs.h>  #include "drmP.h"  /** @file drm_gem.c diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index d61d185cf04..4a058c7af6c 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -28,6 +28,7 @@   * IN THE SOFTWARE.   */  #include <linux/compat.h> +#include <linux/ratelimit.h>  #include "drmP.h"  #include "drm_core.h" @@ -253,10 +254,10 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,  		return -EFAULT;  	m32.handle = (unsigned long)handle; -	if (m32.handle != (unsigned long)handle && printk_ratelimit()) -		printk(KERN_ERR "compat_drm_addmap truncated handle" -		       " %p for type %d offset %x\n", -		       handle, m32.type, m32.offset); +	if (m32.handle != (unsigned long)handle) +		printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle" +				   " %p for type %d offset %x\n", +				   handle, m32.type, m32.offset);  	if (copy_to_user(argp, &m32, sizeof(m32)))  		return -EFAULT; diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index e1aee4f6a7c..b6a19cb07ca 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -251,7 +251,7 @@ err:  } -int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) +static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)  {  	if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||  	    (p->busnum & 0xff) != dev->pdev->bus->number || @@ -292,6 +292,7 @@ static struct drm_bus drm_pci_bus = {  	.get_name = drm_pci_get_name,  	.set_busid = drm_pci_set_busid,  	.set_unique = drm_pci_set_unique, +	.irq_by_busid = drm_pci_irq_by_busid,  	.agp_init = drm_pci_agp_init,  }; diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 2c3fcbdfd8f..5db96d45fc7 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -526,7 +526,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)  static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev)  {  #ifdef __alpha__ -	return dev->hose->dense_mem_base - dev->hose->mem_space->start; +	return dev->hose->dense_mem_base;  #else  	return 0;  #endif diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 4d46441cbe2..0a893f7400f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1207,13 +1207,17 @@ static int i915_context_status(struct seq_file *m, void *unused)  	if (ret)  		return ret; -	seq_printf(m, "power context "); -	describe_obj(m, dev_priv->pwrctx); -	seq_printf(m, "\n"); +	if (dev_priv->pwrctx) { +		seq_printf(m, "power context "); +		describe_obj(m, dev_priv->pwrctx); +		seq_printf(m, "\n"); +	} -	seq_printf(m, "render context "); -	describe_obj(m, dev_priv->renderctx); -	seq_printf(m, "\n"); +	if (dev_priv->renderctx) { +		seq_printf(m, "render context "); +		describe_obj(m, dev_priv->renderctx); +		seq_printf(m, "\n"); +	}  	mutex_unlock(&dev->mode_config.mutex); diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 0239e9974bf..296fbd66f0e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1266,30 +1266,6 @@ static int i915_load_modeset_init(struct drm_device *dev)  	intel_modeset_gem_init(dev); -	if (IS_IVYBRIDGE(dev)) { -		/* Share pre & uninstall handlers with ILK/SNB */ -		dev->driver->irq_handler = ivybridge_irq_handler; -		dev->driver->irq_preinstall = ironlake_irq_preinstall; -		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; -		dev->driver->irq_postinstall = ironlake_irq_postinstall; -		dev->driver->irq_uninstall = ironlake_irq_uninstall; -		dev->driver->enable_vblank = ironlake_enable_vblank; -		dev->driver->disable_vblank = ironlake_disable_vblank; -	} else { -		dev->driver->irq_preinstall = i915_driver_irq_preinstall; -		dev->driver->irq_postinstall = i915_driver_irq_postinstall; -		dev->driver->irq_uninstall = i915_driver_irq_uninstall; -		dev->driver->irq_handler = i915_driver_irq_handler; -		dev->driver->enable_vblank = i915_enable_vblank; -		dev->driver->disable_vblank = i915_disable_vblank; -	} -  	ret = drm_irq_install(dev);  	if (ret)  		goto cleanup_gem; @@ -1967,7 +1943,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	if (!dev_priv->mm.gtt) {  		DRM_ERROR("Failed to initialize GTT\n");  		ret = -ENODEV; -		goto out_iomapfree; +		goto out_rmmap;  	}  	agp_size = dev_priv->mm.gtt->gtt_mappable_entries << PAGE_SHIFT; @@ -2011,18 +1987,13 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	if (dev_priv->wq == NULL) {  		DRM_ERROR("Failed to create our workqueue.\n");  		ret = -ENOMEM; -		goto out_iomapfree; +		goto out_mtrrfree;  	}  	/* enable GEM by default */  	dev_priv->has_gem = 1; -	dev->driver->get_vblank_counter = i915_get_vblank_counter; -	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ -	if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { -		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ -		dev->driver->get_vblank_counter = gm45_get_vblank_counter; -	} +	intel_irq_init(dev);  	/* Try to make sure MCHBAR is enabled before poking at it */  	intel_setup_mchbar(dev); @@ -2103,13 +2074,21 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  	return 0;  out_gem_unload: +	if (dev_priv->mm.inactive_shrinker.shrink) +		unregister_shrinker(&dev_priv->mm.inactive_shrinker); +  	if (dev->pdev->msi_enabled)  		pci_disable_msi(dev->pdev);  	intel_teardown_gmbus(dev);  	intel_teardown_mchbar(dev);  	destroy_workqueue(dev_priv->wq); -out_iomapfree: +out_mtrrfree: +	if (dev_priv->mm.gtt_mtrr >= 0) { +		mtrr_del(dev_priv->mm.gtt_mtrr, dev->agp->base, +			 dev->agp->agp_info.aper_size * 1024 * 1024); +		dev_priv->mm.gtt_mtrr = -1; +	}  	io_mapping_free(dev_priv->mm.gtt_mapping);  out_rmmap:  	pci_iounmap(dev->pdev, dev_priv->regs); @@ -2182,9 +2161,8 @@ int i915_driver_unload(struct drm_device *dev)  		/* Flush any outstanding unpin_work. */  		flush_workqueue(dev_priv->wq); -		i915_gem_free_all_phys_object(dev); -  		mutex_lock(&dev->struct_mutex); +		i915_gem_free_all_phys_object(dev);  		i915_gem_cleanup_ringbuffer(dev);  		mutex_unlock(&dev->struct_mutex);  		if (I915_HAS_FBC(dev) && i915_powersave) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 0defd427059..eb91e2dd791 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -52,7 +52,7 @@ module_param_named(powersave, i915_powersave, int, 0600);  unsigned int i915_semaphores = 0;  module_param_named(semaphores, i915_semaphores, int, 0600); -unsigned int i915_enable_rc6 = 1; +unsigned int i915_enable_rc6 = 0;  module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);  unsigned int i915_enable_fbc = 0; @@ -577,8 +577,12 @@ int i915_reset(struct drm_device *dev, u8 flags)  	if (get_seconds() - dev_priv->last_gpu_reset < 5) {  		DRM_ERROR("GPU hanging too fast, declaring wedged!\n");  	} else switch (INTEL_INFO(dev)->gen) { +	case 7:  	case 6:  		ret = gen6_do_reset(dev, flags); +		/* If reset with a user forcewake, try to restore */ +		if (atomic_read(&dev_priv->forcewake_count)) +			__gen6_gt_force_wake_get(dev_priv);  		break;  	case 5:  		ret = ironlake_do_reset(dev, flags); @@ -762,14 +766,6 @@ static struct drm_driver driver = {  	.resume = i915_resume,  	.device_is_agp = i915_driver_device_is_agp, -	.enable_vblank = i915_enable_vblank, -	.disable_vblank = i915_disable_vblank, -	.get_vblank_timestamp = i915_get_vblank_timestamp, -	.get_scanout_position = i915_get_crtc_scanoutpos, -	.irq_preinstall = i915_driver_irq_preinstall, -	.irq_postinstall = i915_driver_irq_postinstall, -	.irq_uninstall = i915_driver_irq_uninstall, -	.irq_handler = i915_driver_irq_handler,  	.reclaim_buffers = drm_core_reclaim_buffers,  	.master_create = i915_master_create,  	.master_destroy = i915_master_destroy, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f63ee162f12..ce7914c4c04 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -211,6 +211,9 @@ struct drm_i915_display_funcs {  	void (*fdi_link_train)(struct drm_crtc *crtc);  	void (*init_clock_gating)(struct drm_device *dev);  	void (*init_pch_clock_gating)(struct drm_device *dev); +	int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc, +			  struct drm_framebuffer *fb, +			  struct drm_i915_gem_object *obj);  	/* clock updates for mode set */  	/* cursor updates */  	/* render clock increase/decrease */ @@ -259,6 +262,7 @@ enum intel_pch {  };  #define QUIRK_PIPEA_FORCE (1<<0) +#define QUIRK_LVDS_SSC_DISABLE (1<<1)  struct intel_fbdev; @@ -994,8 +998,6 @@ extern unsigned int i915_enable_fbc;  extern int i915_suspend(struct drm_device *dev, pm_message_t state);  extern int i915_resume(struct drm_device *dev); -extern void i915_save_display(struct drm_device *dev); -extern void i915_restore_display(struct drm_device *dev);  extern int i915_master_create(struct drm_device *dev, struct drm_master *master);  extern void i915_master_destroy(struct drm_device *dev, struct drm_master *master); @@ -1030,33 +1032,12 @@ extern int i915_irq_emit(struct drm_device *dev, void *data,  extern int i915_irq_wait(struct drm_device *dev, void *data,  			 struct drm_file *file_priv); -extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); -extern void i915_driver_irq_preinstall(struct drm_device * dev); -extern int i915_driver_irq_postinstall(struct drm_device *dev); -extern void i915_driver_irq_uninstall(struct drm_device * dev); - -extern irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS); -extern void ironlake_irq_preinstall(struct drm_device *dev); -extern int ironlake_irq_postinstall(struct drm_device *dev); -extern void ironlake_irq_uninstall(struct drm_device *dev); - -extern irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS); -extern void ivybridge_irq_preinstall(struct drm_device *dev); -extern int ivybridge_irq_postinstall(struct drm_device *dev); -extern void ivybridge_irq_uninstall(struct drm_device *dev); +extern void intel_irq_init(struct drm_device *dev);  extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,  				struct drm_file *file_priv);  extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,  				struct drm_file *file_priv); -extern int i915_enable_vblank(struct drm_device *dev, int crtc); -extern void i915_disable_vblank(struct drm_device *dev, int crtc); -extern int ironlake_enable_vblank(struct drm_device *dev, int crtc); -extern void ironlake_disable_vblank(struct drm_device *dev, int crtc); -extern int ivybridge_enable_vblank(struct drm_device *dev, int crtc); -extern void ivybridge_disable_vblank(struct drm_device *dev, int crtc); -extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); -extern u32 gm45_get_vblank_counter(struct drm_device *dev, int crtc);  extern int i915_vblank_swap(struct drm_device *dev, void *data,  			    struct drm_file *file_priv); @@ -1067,13 +1048,6 @@ void  i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask);  void intel_enable_asle (struct drm_device *dev); -int i915_get_vblank_timestamp(struct drm_device *dev, int crtc, -			      int *max_error, -			      struct timeval *vblank_time, -			      unsigned flags); - -int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, -			     int *vpos, int *hpos);  #ifdef CONFIG_DEBUG_FS  extern void i915_destroy_error_state(struct drm_device *dev); @@ -1221,7 +1195,9 @@ void i915_gem_free_all_phys_object(struct drm_device *dev);  void i915_gem_release(struct drm_device *dev, struct drm_file *file);  uint32_t -i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj); +i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev, +				    uint32_t size, +				    int tiling_mode);  /* i915_gem_gtt.c */  void i915_gem_restore_gtt_mappings(struct drm_device *dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 12d32579b95..a087e1bf0c2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -31,6 +31,7 @@  #include "i915_drv.h"  #include "i915_trace.h"  #include "intel_drv.h" +#include <linux/shmem_fs.h>  #include <linux/slab.h>  #include <linux/swap.h>  #include <linux/pci.h> @@ -359,8 +360,7 @@ i915_gem_shmem_pread_fast(struct drm_device *dev,  		if ((page_offset + remain) > PAGE_SIZE)  			page_length = PAGE_SIZE - page_offset; -		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, -					   GFP_HIGHUSER | __GFP_RECLAIMABLE); +		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);  		if (IS_ERR(page))  			return PTR_ERR(page); @@ -463,10 +463,11 @@ i915_gem_shmem_pread_slow(struct drm_device *dev,  		if ((data_page_offset + page_length) > PAGE_SIZE)  			page_length = PAGE_SIZE - data_page_offset; -		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, -					   GFP_HIGHUSER | __GFP_RECLAIMABLE); -		if (IS_ERR(page)) -			return PTR_ERR(page); +		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT); +		if (IS_ERR(page)) { +			ret = PTR_ERR(page); +			goto out; +		}  		if (do_bit17_swizzling) {  			slow_shmem_bit17_copy(page, @@ -795,8 +796,7 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev,  		if ((page_offset + remain) > PAGE_SIZE)  			page_length = PAGE_SIZE - page_offset; -		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, -					   GFP_HIGHUSER | __GFP_RECLAIMABLE); +		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);  		if (IS_ERR(page))  			return PTR_ERR(page); @@ -905,8 +905,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev,  		if ((data_page_offset + page_length) > PAGE_SIZE)  			page_length = PAGE_SIZE - data_page_offset; -		page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT, -					   GFP_HIGHUSER | __GFP_RECLAIMABLE); +		page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);  		if (IS_ERR(page)) {  			ret = PTR_ERR(page);  			goto out; @@ -1217,11 +1216,11 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)  		ret = i915_gem_object_bind_to_gtt(obj, 0, true);  		if (ret)  			goto unlock; -	} -	ret = i915_gem_object_set_to_gtt_domain(obj, write); -	if (ret) -		goto unlock; +		ret = i915_gem_object_set_to_gtt_domain(obj, write); +		if (ret) +			goto unlock; +	}  	if (obj->tiling_mode == I915_TILING_NONE)  		ret = i915_gem_object_put_fence(obj); @@ -1375,25 +1374,24 @@ i915_gem_free_mmap_offset(struct drm_i915_gem_object *obj)  }  static uint32_t -i915_gem_get_gtt_size(struct drm_i915_gem_object *obj) +i915_gem_get_gtt_size(struct drm_device *dev, uint32_t size, int tiling_mode)  { -	struct drm_device *dev = obj->base.dev; -	uint32_t size; +	uint32_t gtt_size;  	if (INTEL_INFO(dev)->gen >= 4 || -	    obj->tiling_mode == I915_TILING_NONE) -		return obj->base.size; +	    tiling_mode == I915_TILING_NONE) +		return size;  	/* Previous chips need a power-of-two fence region when tiling */  	if (INTEL_INFO(dev)->gen == 3) -		size = 1024*1024; +		gtt_size = 1024*1024;  	else -		size = 512*1024; +		gtt_size = 512*1024; -	while (size < obj->base.size) -		size <<= 1; +	while (gtt_size < size) +		gtt_size <<= 1; -	return size; +	return gtt_size;  }  /** @@ -1404,59 +1402,52 @@ i915_gem_get_gtt_size(struct drm_i915_gem_object *obj)   * potential fence register mapping.   */  static uint32_t -i915_gem_get_gtt_alignment(struct drm_i915_gem_object *obj) +i915_gem_get_gtt_alignment(struct drm_device *dev, +			   uint32_t size, +			   int tiling_mode)  { -	struct drm_device *dev = obj->base.dev; -  	/*  	 * Minimum alignment is 4k (GTT page size), but might be greater  	 * if a fence register is needed for the object.  	 */  	if (INTEL_INFO(dev)->gen >= 4 || -	    obj->tiling_mode == I915_TILING_NONE) +	    tiling_mode == I915_TILING_NONE)  		return 4096;  	/*  	 * Previous chips need to be aligned to the size of the smallest  	 * fence register that can contain the object.  	 */ -	return i915_gem_get_gtt_size(obj); +	return i915_gem_get_gtt_size(dev, size, tiling_mode);  }  /**   * i915_gem_get_unfenced_gtt_alignment - return required GTT alignment for an   *					 unfenced object - * @obj: object to check + * @dev: the device + * @size: size of the object + * @tiling_mode: tiling mode of the object   *   * Return the required GTT alignment for an object, only taking into account   * unfenced tiled surface requirements.   */  uint32_t -i915_gem_get_unfenced_gtt_alignment(struct drm_i915_gem_object *obj) +i915_gem_get_unfenced_gtt_alignment(struct drm_device *dev, +				    uint32_t size, +				    int tiling_mode)  { -	struct drm_device *dev = obj->base.dev; -	int tile_height; -  	/*  	 * Minimum alignment is 4k (GTT page size) for sane hw.  	 */  	if (INTEL_INFO(dev)->gen >= 4 || IS_G33(dev) || -	    obj->tiling_mode == I915_TILING_NONE) +	    tiling_mode == I915_TILING_NONE)  		return 4096; -	/* -	 * Older chips need unfenced tiled buffers to be aligned to the left -	 * edge of an even tile row (where tile rows are counted as if the bo is -	 * placed in a fenced gtt region). +	/* Previous hardware however needs to be aligned to a power-of-two +	 * tile height. The simplest method for determining this is to reuse +	 * the power-of-tile object size.  	 */ -	if (IS_GEN2(dev)) -		tile_height = 16; -	else if (obj->tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)) -		tile_height = 32; -	else -		tile_height = 8; - -	return tile_height * obj->stride * 2; +	return i915_gem_get_gtt_size(dev, size, tiling_mode);  }  int @@ -1556,12 +1547,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,  	inode = obj->base.filp->f_path.dentry->d_inode;  	mapping = inode->i_mapping; +	gfpmask |= mapping_gfp_mask(mapping); +  	for (i = 0; i < page_count; i++) { -		page = read_cache_page_gfp(mapping, i, -					   GFP_HIGHUSER | -					   __GFP_COLD | -					   __GFP_RECLAIMABLE | -					   gfpmask); +		page = shmem_read_mapping_page_gfp(mapping, i, gfpmask);  		if (IS_ERR(page))  			goto err_pages; @@ -1699,13 +1688,10 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)  	/* Our goal here is to return as much of the memory as  	 * is possible back to the system as we are called from OOM.  	 * To do this we must instruct the shmfs to drop all of its -	 * backing pages, *now*. Here we mirror the actions taken -	 * when by shmem_delete_inode() to release the backing store. +	 * backing pages, *now*.  	 */  	inode = obj->base.filp->f_path.dentry->d_inode; -	truncate_inode_pages(inode->i_mapping, 0); -	if (inode->i_op->truncate_range) -		inode->i_op->truncate_range(inode, 0, (loff_t)-1); +	shmem_truncate_range(inode, 0, (loff_t)-1);  	obj->madv = __I915_MADV_PURGED;  } @@ -2078,8 +2064,8 @@ i915_wait_request(struct intel_ring_buffer *ring,  		if (!ier) {  			DRM_ERROR("something (likely vbetool) disabled "  				  "interrupts, re-enabling\n"); -			i915_driver_irq_preinstall(ring->dev); -			i915_driver_irq_postinstall(ring->dev); +			ring->dev->driver->irq_preinstall(ring->dev); +			ring->dev->driver->irq_postinstall(ring->dev);  		}  		trace_i915_gem_request_wait_begin(ring, seqno); @@ -2750,9 +2736,16 @@ i915_gem_object_bind_to_gtt(struct drm_i915_gem_object *obj,  		return -EINVAL;  	} -	fence_size = i915_gem_get_gtt_size(obj); -	fence_alignment = i915_gem_get_gtt_alignment(obj); -	unfenced_alignment = i915_gem_get_unfenced_gtt_alignment(obj); +	fence_size = i915_gem_get_gtt_size(dev, +					   obj->base.size, +					   obj->tiling_mode); +	fence_alignment = i915_gem_get_gtt_alignment(dev, +						     obj->base.size, +						     obj->tiling_mode); +	unfenced_alignment = +		i915_gem_get_unfenced_gtt_alignment(dev, +						    obj->base.size, +						    obj->tiling_mode);  	if (alignment == 0)  		alignment = map_and_fenceable ? fence_alignment : @@ -2924,8 +2917,6 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)  	 */  	wmb(); -	i915_gem_release_mmap(obj); -  	old_write_domain = obj->base.write_domain;  	obj->base.write_domain = 0; @@ -3565,6 +3556,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,  {  	struct drm_i915_private *dev_priv = dev->dev_private;  	struct drm_i915_gem_object *obj; +	struct address_space *mapping;  	obj = kzalloc(sizeof(*obj), GFP_KERNEL);  	if (obj == NULL) @@ -3575,6 +3567,9 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,  		return NULL;  	} +	mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping; +	mapping_set_gfp_mask(mapping, GFP_HIGHUSER | __GFP_RECLAIMABLE); +  	i915_gem_info_add_obj(dev_priv, size);  	obj->base.write_domain = I915_GEM_DOMAIN_CPU; @@ -3950,8 +3945,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev,  	page_count = obj->base.size / PAGE_SIZE;  	for (i = 0; i < page_count; i++) { -		struct page *page = read_cache_page_gfp(mapping, i, -							GFP_HIGHUSER | __GFP_RECLAIMABLE); +		struct page *page = shmem_read_mapping_page(mapping, i);  		if (!IS_ERR(page)) {  			char *dst = kmap_atomic(page);  			memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE); @@ -4012,8 +4006,7 @@ i915_gem_attach_phys_object(struct drm_device *dev,  		struct page *page;  		char *dst, *src; -		page = read_cache_page_gfp(mapping, i, -					   GFP_HIGHUSER | __GFP_RECLAIMABLE); +		page = shmem_read_mapping_page(mapping, i);  		if (IS_ERR(page))  			return PTR_ERR(page); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 20a4cc5b818..4934cf84c32 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -187,10 +187,6 @@ i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj,  	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU)  		i915_gem_clflush_object(obj); -	/* blow away mappings if mapped through GTT */ -	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT) -		i915_gem_release_mmap(obj); -  	if (obj->base.pending_write_domain)  		cd->flips |= atomic_read(&obj->pending_flip); diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 82d70fd9e93..99c4faa59d8 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -348,7 +348,9 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,  		/* Rebind if we need a change of alignment */  		if (!obj->map_and_fenceable) {  			u32 unfenced_alignment = -				i915_gem_get_unfenced_gtt_alignment(obj); +				i915_gem_get_unfenced_gtt_alignment(dev, +								    obj->base.size, +								    args->tiling_mode);  			if (obj->gtt_offset & (unfenced_alignment - 1))  				ret = i915_gem_object_unbind(obj);  		} diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b9fafe3b045..3b03f85ea62 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -152,7 +152,7 @@ i915_pipe_enabled(struct drm_device *dev, int pipe)  /* Called from drm generic code, passed a 'crtc', which   * we use as a pipe index   */ -u32 i915_get_vblank_counter(struct drm_device *dev, int pipe) +static u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	unsigned long high_frame; @@ -184,7 +184,7 @@ u32 i915_get_vblank_counter(struct drm_device *dev, int pipe)  	return (high1 << 8) | low;  } -u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe) +static u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	int reg = PIPE_FRMCOUNT_GM45(pipe); @@ -198,7 +198,7 @@ u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)  	return I915_READ(reg);  } -int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe, +static int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,  			     int *vpos, int *hpos)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -264,7 +264,7 @@ int i915_get_crtc_scanoutpos(struct drm_device *dev, int pipe,  	return ret;  } -int i915_get_vblank_timestamp(struct drm_device *dev, int pipe, +static int i915_get_vblank_timestamp(struct drm_device *dev, int pipe,  			      int *max_error,  			      struct timeval *vblank_time,  			      unsigned flags) @@ -462,7 +462,7 @@ static void pch_irq_handler(struct drm_device *dev)  		DRM_DEBUG_DRIVER("PCH transcoder A underrun interrupt\n");  } -irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) +static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS)  {  	struct drm_device *dev = (struct drm_device *) arg;  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -550,7 +550,7 @@ done:  	return ret;  } -irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) +static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS)  {  	struct drm_device *dev = (struct drm_device *) arg;  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1209,7 +1209,7 @@ static void i915_pageflip_stall_check(struct drm_device *dev, int pipe)  	}  } -irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) +static irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)  {  	struct drm_device *dev = (struct drm_device *) arg;  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1454,7 +1454,7 @@ int i915_irq_wait(struct drm_device *dev, void *data,  /* Called from drm generic code, passed 'crtc' which   * we use as a pipe index   */ -int i915_enable_vblank(struct drm_device *dev, int pipe) +static int i915_enable_vblank(struct drm_device *dev, int pipe)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	unsigned long irqflags; @@ -1478,7 +1478,7 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)  	return 0;  } -int ironlake_enable_vblank(struct drm_device *dev, int pipe) +static int ironlake_enable_vblank(struct drm_device *dev, int pipe)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	unsigned long irqflags; @@ -1494,7 +1494,7 @@ int ironlake_enable_vblank(struct drm_device *dev, int pipe)  	return 0;  } -int ivybridge_enable_vblank(struct drm_device *dev, int pipe) +static int ivybridge_enable_vblank(struct drm_device *dev, int pipe)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	unsigned long irqflags; @@ -1513,7 +1513,7 @@ int ivybridge_enable_vblank(struct drm_device *dev, int pipe)  /* Called from drm generic code, passed 'crtc' which   * we use as a pipe index   */ -void i915_disable_vblank(struct drm_device *dev, int pipe) +static void i915_disable_vblank(struct drm_device *dev, int pipe)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	unsigned long irqflags; @@ -1529,7 +1529,7 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)  	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);  } -void ironlake_disable_vblank(struct drm_device *dev, int pipe) +static void ironlake_disable_vblank(struct drm_device *dev, int pipe)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	unsigned long irqflags; @@ -1540,7 +1540,7 @@ void ironlake_disable_vblank(struct drm_device *dev, int pipe)  	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);  } -void ivybridge_disable_vblank(struct drm_device *dev, int pipe) +static void ivybridge_disable_vblank(struct drm_device *dev, int pipe)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	unsigned long irqflags; @@ -1728,7 +1728,7 @@ repeat:  /* drm_dma.h hooks  */ -void ironlake_irq_preinstall(struct drm_device *dev) +static void ironlake_irq_preinstall(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -1740,6 +1740,17 @@ void ironlake_irq_preinstall(struct drm_device *dev)  		INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);  	I915_WRITE(HWSTAM, 0xeffe); +	if (IS_GEN6(dev) || IS_GEN7(dev)) { +		/* Workaround stalls observed on Sandy Bridge GPUs by +		 * making the blitter command streamer generate a +		 * write to the Hardware Status Page for +		 * MI_USER_INTERRUPT.  This appears to serialize the +		 * previous seqno write out before the interrupt +		 * happens. +		 */ +		I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT); +		I915_WRITE(GEN6_BSD_HWSTAM, ~GEN6_BSD_USER_INTERRUPT); +	}  	/* XXX hotplug from PCH */ @@ -1758,7 +1769,7 @@ void ironlake_irq_preinstall(struct drm_device *dev)  	POSTING_READ(SDEIER);  } -int ironlake_irq_postinstall(struct drm_device *dev) +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 */ @@ -1830,7 +1841,7 @@ int ironlake_irq_postinstall(struct drm_device *dev)  	return 0;  } -int ivybridge_irq_postinstall(struct drm_device *dev) +static int ivybridge_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 */ @@ -1880,7 +1891,7 @@ int ivybridge_irq_postinstall(struct drm_device *dev)  	return 0;  } -void i915_driver_irq_preinstall(struct drm_device * dev) +static void i915_driver_irq_preinstall(struct drm_device * dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	int pipe; @@ -1907,7 +1918,7 @@ void i915_driver_irq_preinstall(struct drm_device * dev)   * Must be called after intel_modeset_init or hotplug interrupts won't be   * enabled correctly.   */ -int i915_driver_irq_postinstall(struct drm_device *dev) +static int i915_driver_irq_postinstall(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR; @@ -1983,7 +1994,7 @@ int i915_driver_irq_postinstall(struct drm_device *dev)  	return 0;  } -void ironlake_irq_uninstall(struct drm_device *dev) +static void ironlake_irq_uninstall(struct drm_device *dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -2003,7 +2014,7 @@ void ironlake_irq_uninstall(struct drm_device *dev)  	I915_WRITE(GTIIR, I915_READ(GTIIR));  } -void i915_driver_irq_uninstall(struct drm_device * dev) +static void i915_driver_irq_uninstall(struct drm_device * dev)  {  	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;  	int pipe; @@ -2029,3 +2040,41 @@ void i915_driver_irq_uninstall(struct drm_device * dev)  			   I915_READ(PIPESTAT(pipe)) & 0x8000ffff);  	I915_WRITE(IIR, I915_READ(IIR));  } + +void intel_irq_init(struct drm_device *dev) +{ +	dev->driver->get_vblank_counter = i915_get_vblank_counter; +	dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ +	if (IS_G4X(dev) || IS_GEN5(dev) || IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { +		dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */ +		dev->driver->get_vblank_counter = gm45_get_vblank_counter; +	} + + +	dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; +	dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; + +	if (IS_IVYBRIDGE(dev)) { +		/* Share pre & uninstall handlers with ILK/SNB */ +		dev->driver->irq_handler = ivybridge_irq_handler; +		dev->driver->irq_preinstall = ironlake_irq_preinstall; +		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; +		dev->driver->irq_postinstall = ironlake_irq_postinstall; +		dev->driver->irq_uninstall = ironlake_irq_uninstall; +		dev->driver->enable_vblank = ironlake_enable_vblank; +		dev->driver->disable_vblank = ironlake_disable_vblank; +	} else { +		dev->driver->irq_preinstall = i915_driver_irq_preinstall; +		dev->driver->irq_postinstall = i915_driver_irq_postinstall; +		dev->driver->irq_uninstall = i915_driver_irq_uninstall; +		dev->driver->irq_handler = i915_driver_irq_handler; +		dev->driver->enable_vblank = i915_enable_vblank; +		dev->driver->disable_vblank = i915_disable_vblank; +	} +} diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2f967af8e62..5d5def756c9 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -531,6 +531,7 @@  #define   GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE		0  #define   GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR			(1 << 3) +#define GEN6_BSD_HWSTAM			0x12098  #define GEN6_BSD_IMR			0x120a8  #define   GEN6_BSD_USER_INTERRUPT	(1 << 12) diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 60a94d2b526..5257cfc34c3 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -597,7 +597,7 @@ static void i915_restore_modeset_reg(struct drm_device *dev)  	return;  } -void i915_save_display(struct drm_device *dev) +static void i915_save_display(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -689,7 +689,7 @@ void i915_save_display(struct drm_device *dev)  	i915_save_vga(dev);  } -void i915_restore_display(struct drm_device *dev) +static void i915_restore_display(struct drm_device *dev)  {  	struct drm_i915_private *dev_priv = dev->dev_private; @@ -780,6 +780,7 @@ void i915_restore_display(struct drm_device *dev)  		I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL);  	else  		I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL); +  	I915_WRITE(VGA0, dev_priv->saveVGA0);  	I915_WRITE(VGA1, dev_priv->saveVGA1);  	I915_WRITE(VGA_PD, dev_priv->saveVGA_PD); @@ -796,6 +797,8 @@ int i915_save_state(struct drm_device *dev)  	pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB); +	mutex_lock(&dev->struct_mutex); +  	/* Hardware status page */  	dev_priv->saveHWS = I915_READ(HWS_PGA); @@ -835,6 +838,8 @@ int i915_save_state(struct drm_device *dev)  	for (i = 0; i < 3; i++)  		dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2)); +	mutex_unlock(&dev->struct_mutex); +  	return 0;  } @@ -845,6 +850,8 @@ int i915_restore_state(struct drm_device *dev)  	pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB); +	mutex_lock(&dev->struct_mutex); +  	/* Hardware status page */  	I915_WRITE(HWS_PGA, dev_priv->saveHWS); @@ -862,6 +869,7 @@ int i915_restore_state(struct drm_device *dev)  		I915_WRITE(IER, dev_priv->saveIER);  		I915_WRITE(IMR, dev_priv->saveIMR);  	} +	mutex_unlock(&dev->struct_mutex);  	intel_init_clock_gating(dev); @@ -873,6 +881,8 @@ int i915_restore_state(struct drm_device *dev)  	if (IS_GEN6(dev))  		gen6_enable_rps(dev_priv); +	mutex_lock(&dev->struct_mutex); +  	/* Cache mode state */  	I915_WRITE (CACHE_MODE_0, dev_priv->saveCACHE_MODE_0 | 0xffff0000); @@ -886,6 +896,8 @@ int i915_restore_state(struct drm_device *dev)  	for (i = 0; i < 3; i++)  		I915_WRITE(SWF30 + (i << 2), dev_priv->saveSWF2[i]); +	mutex_unlock(&dev->struct_mutex); +  	intel_i2c_reset(dev);  	return 0; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 81a9059b6a9..0f1c799afea 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4305,7 +4305,8 @@ static void intel_update_watermarks(struct drm_device *dev)  static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)  { -	return dev_priv->lvds_use_ssc && i915_panel_use_ssc; +	return dev_priv->lvds_use_ssc && i915_panel_use_ssc +		&& !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE);  }  static int i9xx_crtc_mode_set(struct drm_crtc *crtc, @@ -4687,6 +4688,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,  	I915_WRITE(DSPCNTR(plane), dspcntr);  	POSTING_READ(DSPCNTR(plane)); +	intel_enable_plane(dev_priv, plane, pipe);  	ret = intel_pipe_set_base(crtc, x, y, old_fb); @@ -5217,8 +5219,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,  	I915_WRITE(DSPCNTR(plane), dspcntr);  	POSTING_READ(DSPCNTR(plane)); -	if (!HAS_PCH_SPLIT(dev)) -		intel_enable_plane(dev_priv, plane, pipe);  	ret = intel_pipe_set_base(crtc, x, y, old_fb); @@ -6262,6 +6262,197 @@ void intel_prepare_page_flip(struct drm_device *dev, int plane)  	spin_unlock_irqrestore(&dev->event_lock, flags);  } +static int intel_gen2_queue_flip(struct drm_device *dev, +				 struct drm_crtc *crtc, +				 struct drm_framebuffer *fb, +				 struct drm_i915_gem_object *obj) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	unsigned long offset; +	u32 flip_mask; +	int ret; + +	ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); +	if (ret) +		goto out; + +	/* Offset into the new buffer for cases of shared fbs between CRTCs */ +	offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; + +	ret = BEGIN_LP_RING(6); +	if (ret) +		goto out; + +	/* Can't queue multiple flips, so wait for the previous +	 * one to finish before executing the next. +	 */ +	if (intel_crtc->plane) +		flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; +	else +		flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; +	OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); +	OUT_RING(MI_NOOP); +	OUT_RING(MI_DISPLAY_FLIP | +		 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +	OUT_RING(fb->pitch); +	OUT_RING(obj->gtt_offset + offset); +	OUT_RING(MI_NOOP); +	ADVANCE_LP_RING(); +out: +	return ret; +} + +static int intel_gen3_queue_flip(struct drm_device *dev, +				 struct drm_crtc *crtc, +				 struct drm_framebuffer *fb, +				 struct drm_i915_gem_object *obj) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	unsigned long offset; +	u32 flip_mask; +	int ret; + +	ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); +	if (ret) +		goto out; + +	/* Offset into the new buffer for cases of shared fbs between CRTCs */ +	offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; + +	ret = BEGIN_LP_RING(6); +	if (ret) +		goto out; + +	if (intel_crtc->plane) +		flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; +	else +		flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; +	OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); +	OUT_RING(MI_NOOP); +	OUT_RING(MI_DISPLAY_FLIP_I915 | +		 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +	OUT_RING(fb->pitch); +	OUT_RING(obj->gtt_offset + offset); +	OUT_RING(MI_NOOP); + +	ADVANCE_LP_RING(); +out: +	return ret; +} + +static int intel_gen4_queue_flip(struct drm_device *dev, +				 struct drm_crtc *crtc, +				 struct drm_framebuffer *fb, +				 struct drm_i915_gem_object *obj) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	uint32_t pf, pipesrc; +	int ret; + +	ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); +	if (ret) +		goto out; + +	ret = BEGIN_LP_RING(4); +	if (ret) +		goto out; + +	/* i965+ uses the linear or tiled offsets from the +	 * Display Registers (which do not change across a page-flip) +	 * so we need only reprogram the base address. +	 */ +	OUT_RING(MI_DISPLAY_FLIP | +		 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +	OUT_RING(fb->pitch); +	OUT_RING(obj->gtt_offset | obj->tiling_mode); + +	/* XXX Enabling the panel-fitter across page-flip is so far +	 * untested on non-native modes, so ignore it for now. +	 * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; +	 */ +	pf = 0; +	pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; +	OUT_RING(pf | pipesrc); +	ADVANCE_LP_RING(); +out: +	return ret; +} + +static int intel_gen6_queue_flip(struct drm_device *dev, +				 struct drm_crtc *crtc, +				 struct drm_framebuffer *fb, +				 struct drm_i915_gem_object *obj) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	uint32_t pf, pipesrc; +	int ret; + +	ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); +	if (ret) +		goto out; + +	ret = BEGIN_LP_RING(4); +	if (ret) +		goto out; + +	OUT_RING(MI_DISPLAY_FLIP | +		 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); +	OUT_RING(fb->pitch | obj->tiling_mode); +	OUT_RING(obj->gtt_offset); + +	pf = I915_READ(PF_CTL(intel_crtc->pipe)) & PF_ENABLE; +	pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; +	OUT_RING(pf | pipesrc); +	ADVANCE_LP_RING(); +out: +	return ret; +} + +/* + * On gen7 we currently use the blit ring because (in early silicon at least) + * the render ring doesn't give us interrpts for page flip completion, which + * means clients will hang after the first flip is queued.  Fortunately the + * blit ring generates interrupts properly, so use it instead. + */ +static int intel_gen7_queue_flip(struct drm_device *dev, +				 struct drm_crtc *crtc, +				 struct drm_framebuffer *fb, +				 struct drm_i915_gem_object *obj) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	struct intel_crtc *intel_crtc = to_intel_crtc(crtc); +	struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; +	int ret; + +	ret = intel_pin_and_fence_fb_obj(dev, obj, ring); +	if (ret) +		goto out; + +	ret = intel_ring_begin(ring, 4); +	if (ret) +		goto out; + +	intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19)); +	intel_ring_emit(ring, (fb->pitch | obj->tiling_mode)); +	intel_ring_emit(ring, (obj->gtt_offset)); +	intel_ring_emit(ring, (MI_NOOP)); +	intel_ring_advance(ring); +out: +	return ret; +} + +static int intel_default_queue_flip(struct drm_device *dev, +				    struct drm_crtc *crtc, +				    struct drm_framebuffer *fb, +				    struct drm_i915_gem_object *obj) +{ +	return -ENODEV; +} +  static int intel_crtc_page_flip(struct drm_crtc *crtc,  				struct drm_framebuffer *fb,  				struct drm_pending_vblank_event *event) @@ -6272,9 +6463,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,  	struct drm_i915_gem_object *obj;  	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);  	struct intel_unpin_work *work; -	unsigned long flags, offset; -	int pipe = intel_crtc->pipe; -	u32 pf, pipesrc; +	unsigned long flags;  	int ret;  	work = kzalloc(sizeof *work, GFP_KERNEL); @@ -6303,9 +6492,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,  	obj = intel_fb->obj;  	mutex_lock(&dev->struct_mutex); -	ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); -	if (ret) -		goto cleanup_work;  	/* Reference the objects for the scheduled work. */  	drm_gem_object_reference(&work->old_fb_obj->base); @@ -6317,91 +6503,18 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,  	if (ret)  		goto cleanup_objs; -	if (IS_GEN3(dev) || IS_GEN2(dev)) { -		u32 flip_mask; - -		/* Can't queue multiple flips, so wait for the previous -		 * one to finish before executing the next. -		 */ -		ret = BEGIN_LP_RING(2); -		if (ret) -			goto cleanup_objs; - -		if (intel_crtc->plane) -			flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; -		else -			flip_mask = MI_WAIT_FOR_PLANE_A_FLIP; -		OUT_RING(MI_WAIT_FOR_EVENT | flip_mask); -		OUT_RING(MI_NOOP); -		ADVANCE_LP_RING(); -	} -  	work->pending_flip_obj = obj;  	work->enable_stall_check = true; -	/* Offset into the new buffer for cases of shared fbs between CRTCs */ -	offset = crtc->y * fb->pitch + crtc->x * fb->bits_per_pixel/8; - -	ret = BEGIN_LP_RING(4); -	if (ret) -		goto cleanup_objs; -  	/* 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); -	switch (INTEL_INFO(dev)->gen) { -	case 2: -		OUT_RING(MI_DISPLAY_FLIP | -			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); -		OUT_RING(fb->pitch); -		OUT_RING(obj->gtt_offset + offset); -		OUT_RING(MI_NOOP); -		break; - -	case 3: -		OUT_RING(MI_DISPLAY_FLIP_I915 | -			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); -		OUT_RING(fb->pitch); -		OUT_RING(obj->gtt_offset + offset); -		OUT_RING(MI_NOOP); -		break; - -	case 4: -	case 5: -		/* i965+ uses the linear or tiled offsets from the -		 * Display Registers (which do not change across a page-flip) -		 * so we need only reprogram the base address. -		 */ -		OUT_RING(MI_DISPLAY_FLIP | -			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); -		OUT_RING(fb->pitch); -		OUT_RING(obj->gtt_offset | obj->tiling_mode); - -		/* XXX Enabling the panel-fitter across page-flip is so far -		 * untested on non-native modes, so ignore it for now. -		 * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE; -		 */ -		pf = 0; -		pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff; -		OUT_RING(pf | pipesrc); -		break; - -	case 6: -	case 7: -		OUT_RING(MI_DISPLAY_FLIP | -			 MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); -		OUT_RING(fb->pitch | obj->tiling_mode); -		OUT_RING(obj->gtt_offset); - -		pf = I915_READ(PF_CTL(pipe)) & PF_ENABLE; -		pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff; -		OUT_RING(pf | pipesrc); -		break; -	} -	ADVANCE_LP_RING(); +	ret = dev_priv->display.queue_flip(dev, crtc, fb, obj); +	if (ret) +		goto cleanup_pending;  	mutex_unlock(&dev->struct_mutex); @@ -6409,10 +6522,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,  	return 0; +cleanup_pending: +	atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip);  cleanup_objs:  	drm_gem_object_unreference(&work->old_fb_obj->base);  	drm_gem_object_unreference(&obj->base); -cleanup_work:  	mutex_unlock(&dev->struct_mutex);  	spin_lock_irqsave(&dev->event_lock, flags); @@ -7657,6 +7771,31 @@ static void intel_init_display(struct drm_device *dev)  		else  			dev_priv->display.get_fifo_size = i830_get_fifo_size;  	} + +	/* Default just returns -ENODEV to indicate unsupported */ +	dev_priv->display.queue_flip = intel_default_queue_flip; + +	switch (INTEL_INFO(dev)->gen) { +	case 2: +		dev_priv->display.queue_flip = intel_gen2_queue_flip; +		break; + +	case 3: +		dev_priv->display.queue_flip = intel_gen3_queue_flip; +		break; + +	case 4: +	case 5: +		dev_priv->display.queue_flip = intel_gen4_queue_flip; +		break; + +	case 6: +		dev_priv->display.queue_flip = intel_gen6_queue_flip; +		break; +	case 7: +		dev_priv->display.queue_flip = intel_gen7_queue_flip; +		break; +	}  }  /* @@ -7672,6 +7811,15 @@ static void quirk_pipea_force (struct drm_device *dev)  	DRM_DEBUG_DRIVER("applying pipe a force quirk\n");  } +/* + * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason + */ +static void quirk_ssc_force_disable(struct drm_device *dev) +{ +	struct drm_i915_private *dev_priv = dev->dev_private; +	dev_priv->quirks |= QUIRK_LVDS_SSC_DISABLE; +} +  struct intel_quirk {  	int device;  	int subsystem_vendor; @@ -7700,6 +7848,9 @@ struct intel_quirk intel_quirks[] = {  	/* 855 & before need to leave pipe A & dpll A up */  	{ 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force },  	{ 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, + +	/* Lenovo U160 cannot use SSC on LVDS */ +	{ 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable },  };  static void intel_init_quirks(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 391b55f1cc7..e2aced6eec4 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -50,7 +50,6 @@ struct intel_dp {  	bool has_audio;  	int force_audio;  	uint32_t color_range; -	int dpms_mode;  	uint8_t link_bw;  	uint8_t lane_count;  	uint8_t dpcd[4]; @@ -138,8 +137,8 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp)  {  	int max_lane_count = 4; -	if (intel_dp->dpcd[0] >= 0x11) { -		max_lane_count = intel_dp->dpcd[2] & 0x1f; +	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) { +		max_lane_count = intel_dp->dpcd[DP_MAX_LANE_COUNT] & 0x1f;  		switch (max_lane_count) {  		case 1: case 2: case 4:  			break; @@ -153,7 +152,7 @@ intel_dp_max_lane_count(struct intel_dp *intel_dp)  static int  intel_dp_max_link_bw(struct intel_dp *intel_dp)  { -	int max_link_bw = intel_dp->dpcd[1]; +	int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];  	switch (max_link_bw) {  	case DP_LINK_BW_1_62: @@ -774,7 +773,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,  	/*  	 * Check for DPCD version > 1.1 and enhanced framing support  	 */ -	if (intel_dp->dpcd[0] >= 0x11 && (intel_dp->dpcd[2] & DP_ENHANCED_FRAME_CAP)) { +	if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 && +	    (intel_dp->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)) {  		intel_dp->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;  		intel_dp->DP |= DP_ENHANCED_FRAMING;  	} @@ -942,11 +942,44 @@ static void ironlake_edp_pll_off(struct drm_encoder *encoder)  	udelay(200);  } +/* If the sink supports it, try to set the power state appropriately */ +static void intel_dp_sink_dpms(struct intel_dp *intel_dp, int mode) +{ +	int ret, i; + +	/* Should have a valid DPCD by this point */ +	if (intel_dp->dpcd[DP_DPCD_REV] < 0x11) +		return; + +	if (mode != DRM_MODE_DPMS_ON) { +		ret = intel_dp_aux_native_write_1(intel_dp, DP_SET_POWER, +						  DP_SET_POWER_D3); +		if (ret != 1) +			DRM_DEBUG_DRIVER("failed to write sink power state\n"); +	} else { +		/* +		 * When turning on, we need to retry for 1ms to give the sink +		 * time to wake up. +		 */ +		for (i = 0; i < 3; i++) { +			ret = intel_dp_aux_native_write_1(intel_dp, +							  DP_SET_POWER, +							  DP_SET_POWER_D0); +			if (ret == 1) +				break; +			msleep(1); +		} +	} +} +  static void intel_dp_prepare(struct drm_encoder *encoder)  {  	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);  	struct drm_device *dev = encoder->dev; +	/* Wake up the sink first */ +	intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); +  	if (is_edp(intel_dp)) {  		ironlake_edp_backlight_off(dev);  		ironlake_edp_panel_off(dev); @@ -990,6 +1023,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)  	if (mode != DRM_MODE_DPMS_ON) {  		if (is_edp(intel_dp))  			ironlake_edp_backlight_off(dev); +		intel_dp_sink_dpms(intel_dp, mode);  		intel_dp_link_down(intel_dp);  		if (is_edp(intel_dp))  			ironlake_edp_panel_off(dev); @@ -998,6 +1032,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)  	} else {  		if (is_edp(intel_dp))  			ironlake_edp_panel_vdd_on(intel_dp); +		intel_dp_sink_dpms(intel_dp, mode);  		if (!(dp_reg & DP_PORT_EN)) {  			intel_dp_start_link_train(intel_dp);  			if (is_edp(intel_dp)) { @@ -1009,7 +1044,31 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)  		if (is_edp(intel_dp))  			ironlake_edp_backlight_on(dev);  	} -	intel_dp->dpms_mode = mode; +} + +/* + * Native read with retry for link status and receiver capability reads for + * cases where the sink may still be asleep. + */ +static bool +intel_dp_aux_native_read_retry(struct intel_dp *intel_dp, uint16_t address, +			       uint8_t *recv, int recv_bytes) +{ +	int ret, i; + +	/* +	 * Sinks are *supposed* to come up within 1ms from an off state, +	 * but we're also supposed to retry 3 times per the spec. +	 */ +	for (i = 0; i < 3; i++) { +		ret = intel_dp_aux_native_read(intel_dp, address, recv, +					       recv_bytes); +		if (ret == recv_bytes) +			return true; +		msleep(1); +	} + +	return false;  }  /* @@ -1019,14 +1078,10 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)  static bool  intel_dp_get_link_status(struct intel_dp *intel_dp)  { -	int ret; - -	ret = intel_dp_aux_native_read(intel_dp, -				       DP_LANE0_1_STATUS, -				       intel_dp->link_status, DP_LINK_STATUS_SIZE); -	if (ret != DP_LINK_STATUS_SIZE) -		return false; -	return true; +	return intel_dp_aux_native_read_retry(intel_dp, +					      DP_LANE0_1_STATUS, +					      intel_dp->link_status, +					      DP_LINK_STATUS_SIZE);  }  static uint8_t @@ -1515,6 +1570,8 @@ intel_dp_link_down(struct intel_dp *intel_dp)  static void  intel_dp_check_link_status(struct intel_dp *intel_dp)  { +	int ret; +  	if (!intel_dp->base.base.crtc)  		return; @@ -1523,6 +1580,15 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)  		return;  	} +	/* Try to read receiver status if the link appears to be up */ +	ret = intel_dp_aux_native_read(intel_dp, +				       0x000, intel_dp->dpcd, +				       sizeof (intel_dp->dpcd)); +	if (ret != sizeof(intel_dp->dpcd)) { +		intel_dp_link_down(intel_dp); +		return; +	} +  	if (!intel_channel_eq_ok(intel_dp)) {  		intel_dp_start_link_train(intel_dp);  		intel_dp_complete_link_train(intel_dp); @@ -1533,6 +1599,7 @@ static enum drm_connector_status  ironlake_dp_detect(struct intel_dp *intel_dp)  {  	enum drm_connector_status status; +	bool ret;  	/* Can't disconnect eDP, but you can close the lid... */  	if (is_edp(intel_dp)) { @@ -1543,13 +1610,11 @@ ironlake_dp_detect(struct intel_dp *intel_dp)  	}  	status = connector_status_disconnected; -	if (intel_dp_aux_native_read(intel_dp, -				     0x000, intel_dp->dpcd, -				     sizeof (intel_dp->dpcd)) -	    == sizeof(intel_dp->dpcd)) { -		if (intel_dp->dpcd[0] != 0) -			status = connector_status_connected; -	} +	ret = intel_dp_aux_native_read_retry(intel_dp, +					     0x000, intel_dp->dpcd, +					     sizeof (intel_dp->dpcd)); +	if (ret && intel_dp->dpcd[DP_DPCD_REV] != 0) +		status = connector_status_connected;  	DRM_DEBUG_KMS("DPCD: %hx%hx%hx%hx\n", intel_dp->dpcd[0],  		      intel_dp->dpcd[1], intel_dp->dpcd[2], intel_dp->dpcd[3]);  	return status; @@ -1586,7 +1651,7 @@ g4x_dp_detect(struct intel_dp *intel_dp)  	if (intel_dp_aux_native_read(intel_dp, 0x000, intel_dp->dpcd,  				     sizeof (intel_dp->dpcd)) == sizeof (intel_dp->dpcd))  	{ -		if (intel_dp->dpcd[0] != 0) +		if (intel_dp->dpcd[DP_DPCD_REV] != 0)  			status = connector_status_connected;  	} @@ -1790,8 +1855,7 @@ intel_dp_hot_plug(struct intel_encoder *intel_encoder)  {  	struct intel_dp *intel_dp = container_of(intel_encoder, struct intel_dp, base); -	if (intel_dp->dpms_mode == DRM_MODE_DPMS_ON) -		intel_dp_check_link_status(intel_dp); +	intel_dp_check_link_status(intel_dp);  }  /* Return which DP Port should be selected for Transcoder DP control */ @@ -1859,7 +1923,6 @@ intel_dp_init(struct drm_device *dev, int output_reg)  		return;  	intel_dp->output_reg = output_reg; -	intel_dp->dpms_mode = -1;  	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);  	if (!intel_connector) { @@ -1954,8 +2017,9 @@ intel_dp_init(struct drm_device *dev, int output_reg)  					       sizeof(intel_dp->dpcd));  		ironlake_edp_panel_vdd_off(intel_dp);  		if (ret == sizeof(intel_dp->dpcd)) { -			if (intel_dp->dpcd[0] >= 0x11) -				dev_priv->no_aux_handshake = intel_dp->dpcd[3] & +			if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11) +				dev_priv->no_aux_handshake = +					intel_dp->dpcd[DP_MAX_DOWNSPREAD] &  					DP_NO_AUX_HANDSHAKE_LINK_TRAINING;  		} else {  			/* if this fails, presume the device is a ghost */ diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index d3b903bce7c..d98cee60b60 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -401,8 +401,7 @@ int intel_setup_gmbus(struct drm_device *dev)  		bus->reg0 = i | GMBUS_RATE_100KHZ;  		/* XXX force bit banging until GMBUS is fully debugged */ -		if (IS_GEN2(dev)) -			bus->force_bit = intel_gpio_create(dev_priv, i); +		bus->force_bit = intel_gpio_create(dev_priv, i);  	}  	intel_i2c_reset(dev_priv->dev); diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index a670c006982..9e2959bc91c 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1409,6 +1409,11 @@ void intel_setup_overlay(struct drm_device *dev)  	overlay = kzalloc(sizeof(struct intel_overlay), GFP_KERNEL);  	if (!overlay)  		return; + +	mutex_lock(&dev->struct_mutex); +	if (WARN_ON(dev_priv->overlay)) +		goto out_free; +  	overlay->dev = dev;  	reg_bo = i915_gem_alloc_object(dev, PAGE_SIZE); @@ -1448,7 +1453,7 @@ void intel_setup_overlay(struct drm_device *dev)  	regs = intel_overlay_map_regs(overlay);  	if (!regs) -		goto out_free_bo; +		goto out_unpin_bo;  	memset(regs, 0, sizeof(struct overlay_registers));  	update_polyphase_filter(regs); @@ -1457,14 +1462,17 @@ void intel_setup_overlay(struct drm_device *dev)  	intel_overlay_unmap_regs(overlay, regs);  	dev_priv->overlay = overlay; +	mutex_unlock(&dev->struct_mutex);  	DRM_INFO("initialized overlay support\n");  	return;  out_unpin_bo: -	i915_gem_object_unpin(reg_bo); +	if (!OVERLAY_NEEDS_PHYSICAL(dev)) +		i915_gem_object_unpin(reg_bo);  out_free_bo:  	drm_gem_object_unreference(®_bo->base);  out_free: +	mutex_unlock(&dev->struct_mutex);  	kfree(overlay);  	return;  } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index c0e0ee63fbf..39ac2b634ae 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -165,7 +165,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);  int __must_check intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n);  static inline int intel_wait_ring_idle(struct intel_ring_buffer *ring)  { -	return intel_wait_ring_buffer(ring, ring->space - 8); +	return intel_wait_ring_buffer(ring, ring->size - 8);  }  int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n); diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h index 1084fa4d261..54558a01969 100644 --- a/drivers/gpu/drm/mga/mga_drv.h +++ b/drivers/gpu/drm/mga/mga_drv.h @@ -195,29 +195,10 @@ extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,  #define mga_flush_write_combine()	DRM_WRITEMEMORYBARRIER() -#if defined(__linux__) && defined(__alpha__) -#define MGA_BASE(reg)		((unsigned long)(dev_priv->mmio->handle)) -#define MGA_ADDR(reg)		(MGA_BASE(reg) + reg) - -#define MGA_DEREF(reg)		(*(volatile u32 *)MGA_ADDR(reg)) -#define MGA_DEREF8(reg)		(*(volatile u8 *)MGA_ADDR(reg)) - -#define MGA_READ(reg)		(_MGA_READ((u32 *)MGA_ADDR(reg))) -#define MGA_READ8(reg)		(_MGA_READ((u8 *)MGA_ADDR(reg))) -#define MGA_WRITE(reg, val)	do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF(reg) = val; } while (0) -#define MGA_WRITE8(reg, val)	do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8(reg) = val; } while (0) - -static inline u32 _MGA_READ(u32 *addr) -{ -	DRM_MEMORYBARRIER(); -	return *(volatile u32 *)addr; -} -#else  #define MGA_READ8(reg)		DRM_READ8(dev_priv->mmio, (reg))  #define MGA_READ(reg)		DRM_READ32(dev_priv->mmio, (reg))  #define MGA_WRITE8(reg, val)	DRM_WRITE8(dev_priv->mmio, (reg), (val))  #define MGA_WRITE(reg, val)	DRM_WRITE32(dev_priv->mmio, (reg), (val)) -#endif  #define DWGREG0		0x1c00  #define DWGREG0_END	0x1dff diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index f0d459bb46e..525744d593c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -262,7 +262,6 @@ static bool nouveau_dsm_detect(void)  		vga_count++;  		retval = nouveau_dsm_pci_probe(pdev); -		printk("ret val is %d\n", retval);  		if (retval & NOUVEAU_DSM_HAS_MUX)  			has_dsm |= 1;  		if (retval & NOUVEAU_DSM_HAS_OPT) diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 4b9f4493c9f..7347075ca5b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -339,11 +339,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)  	int ret;  	if (dev_priv->chipset < 0x84) { -		ret = RING_SPACE(chan, 3); +		ret = RING_SPACE(chan, 4);  		if (ret)  			return ret; -		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2); +		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3); +		OUT_RING  (chan, NvSema);  		OUT_RING  (chan, sema->mem->start);  		OUT_RING  (chan, 1);  	} else @@ -351,10 +352,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)  		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;  		u64 offset = vma->offset + sema->mem->start; -		ret = RING_SPACE(chan, 5); +		ret = RING_SPACE(chan, 7);  		if (ret)  			return ret; +		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); +		OUT_RING  (chan, chan->vram_handle);  		BEGIN_RING(chan, NvSubSw, 0x0010, 4);  		OUT_RING  (chan, upper_32_bits(offset));  		OUT_RING  (chan, lower_32_bits(offset)); @@ -394,11 +397,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)  	int ret;  	if (dev_priv->chipset < 0x84) { -		ret = RING_SPACE(chan, 4); +		ret = RING_SPACE(chan, 5);  		if (ret)  			return ret; -		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); +		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2); +		OUT_RING  (chan, NvSema);  		OUT_RING  (chan, sema->mem->start);  		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1);  		OUT_RING  (chan, 1); @@ -407,10 +411,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)  		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;  		u64 offset = vma->offset + sema->mem->start; -		ret = RING_SPACE(chan, 5); +		ret = RING_SPACE(chan, 7);  		if (ret)  			return ret; +		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); +		OUT_RING  (chan, chan->vram_handle);  		BEGIN_RING(chan, NvSubSw, 0x0010, 4);  		OUT_RING  (chan, upper_32_bits(offset));  		OUT_RING  (chan, lower_32_bits(offset)); @@ -504,22 +510,22 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)  	struct nouveau_gpuobj *obj = NULL;  	int ret; -	if (dev_priv->card_type >= NV_C0) -		goto out_initialised; +	if (dev_priv->card_type < NV_C0) { +		/* Create an NV_SW object for various sync purposes */ +		ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); +		if (ret) +			return ret; -	/* Create an NV_SW object for various sync purposes */ -	ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); -	if (ret) -		return ret; +		ret = RING_SPACE(chan, 2); +		if (ret) +			return ret; -	/* we leave subchannel empty for nvc0 */ -	ret = RING_SPACE(chan, 2); -	if (ret) -		return ret; -	BEGIN_RING(chan, NvSubSw, 0, 1); -	OUT_RING(chan, NvSw); +		BEGIN_RING(chan, NvSubSw, 0, 1); +		OUT_RING  (chan, NvSw); +		FIRE_RING (chan); +	} -	/* Create a DMA object for the shared cross-channel sync area. */ +	/* Setup area of memory shared between all channels for x-chan sync */  	if (USE_SEMA(dev) && dev_priv->chipset < 0x84) {  		struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; @@ -534,23 +540,8 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)  		nouveau_gpuobj_ref(NULL, &obj);  		if (ret)  			return ret; - -		ret = RING_SPACE(chan, 2); -		if (ret) -			return ret; -		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); -		OUT_RING(chan, NvSema); -	} else { -		ret = RING_SPACE(chan, 2); -		if (ret) -			return ret; -		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1); -		OUT_RING  (chan, chan->vram_handle); /* whole VM */  	} -	FIRE_RING(chan); - -out_initialised:  	INIT_LIST_HEAD(&chan->fence.pending);  	spin_lock_init(&chan->fence.lock);  	atomic_set(&chan->fence.last_sequence_irq, 0); diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c index 922fb6b664e..ef9dec0e6f8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -182,6 +182,11 @@ nouveau_perf_init(struct drm_device *dev)  		entries   = perf[2];  	} +	if (entries > NOUVEAU_PM_MAX_LEVEL) { +		NV_DEBUG(dev, "perf table has too many entries - buggy vbios?\n"); +		entries = NOUVEAU_PM_MAX_LEVEL; +	} +  	entry = perf + headerlen;  	for (i = 0; i < entries; i++) {  		struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 80218887e0a..731acea865b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -371,7 +371,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)  		engine->vram.flags_valid	= nv50_vram_flags_valid;  		break;  	case 0xC0: -	case 0xD0:  		engine->instmem.init		= nvc0_instmem_init;  		engine->instmem.takedown	= nvc0_instmem_takedown;  		engine->instmem.suspend		= nvc0_instmem_suspend; @@ -881,8 +880,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)  #ifdef __BIG_ENDIAN  	/* Put the card in BE mode if it's not */ -	if (nv_rd32(dev, NV03_PMC_BOOT_1)) -		nv_wr32(dev, NV03_PMC_BOOT_1, 0x00000001); +	if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001) +		nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001);  	DRM_MEMORYBARRIER();  #endif @@ -923,7 +922,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)  		dev_priv->card_type = NV_50;  		break;  	case 0xc0: -	case 0xd0:  		dev_priv->card_type = NV_C0;  		break;  	default: diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 74a3f687270..08da478ba54 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -409,7 +409,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,  	struct nouveau_channel *evo = dispc->sync;  	int ret; -	ret = RING_SPACE(evo, 24); +	ret = RING_SPACE(evo, chan ? 25 : 27);  	if (unlikely(ret))  		return ret; @@ -458,8 +458,19 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,  	/* queue the flip on the crtc's "display sync" channel */  	BEGIN_RING(evo, 0, 0x0100, 1);  	OUT_RING  (evo, 0xfffe0000); -	BEGIN_RING(evo, 0, 0x0084, 5); -	OUT_RING  (evo, chan ? 0x00000100 : 0x00000010); +	if (chan) { +		BEGIN_RING(evo, 0, 0x0084, 1); +		OUT_RING  (evo, 0x00000100); +	} else { +		BEGIN_RING(evo, 0, 0x0084, 1); +		OUT_RING  (evo, 0x00000010); +		/* allows gamma somehow, PDISP will bitch at you if +		 * you don't wait for vblank before changing this.. +		 */ +		BEGIN_RING(evo, 0, 0x00e0, 1); +		OUT_RING  (evo, 0x40000000); +	} +	BEGIN_RING(evo, 0, 0x0088, 4);  	OUT_RING  (evo, dispc->sem.offset);  	OUT_RING  (evo, 0xf00d0000 | dispc->sem.value);  	OUT_RING  (evo, 0x74b1e000); diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index 49611e2365d..1b50ad8919d 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -1200,6 +1200,7 @@ typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3  #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF   0x10  #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING       0x11  #define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION      0x12 +#define EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP              0x14  // ucConfig  #define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK				0x03 diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 84a69e7fa11..9541995e4b2 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -671,6 +671,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,  								DISPPLL_CONFIG_DUAL_LINK;  					}  				} +				if (radeon_encoder_is_dp_bridge(encoder)) { +					struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); +					struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder); +					args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id; +				} else +					args.v3.sInput.ucExtTransmitterID = 0; +  				atom_execute_table(rdev->mode_info.atom_context,  						   index, (uint32_t *)&args);  				adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10; diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 98ea597bc76..15bd0477a3e 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -88,7 +88,8 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  /* get temperature in millidegrees */  int evergreen_get_temp(struct radeon_device *rdev)  { -	u32 temp, toffset, actual_temp = 0; +	u32 temp, toffset; +	int actual_temp = 0;  	if (rdev->family == CHIP_JUNIPER) {  		toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >> @@ -139,11 +140,17 @@ void evergreen_pm_misc(struct radeon_device *rdev)  	struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;  	if (voltage->type == VOLTAGE_SW) { +		/* 0xff01 is a flag rather then an actual voltage */ +		if (voltage->voltage == 0xff01) +			return;  		if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) {  			radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);  			rdev->pm.current_vddc = voltage->voltage;  			DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);  		} +		/* 0xff01 is a flag rather then an actual voltage */ +		if (voltage->vddci == 0xff01) +			return;  		if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) {  			radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI);  			rdev->pm.current_vddci = voltage->vddci; @@ -978,17 +985,19 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav  {  	save->vga_control[0] = RREG32(D1VGA_CONTROL);  	save->vga_control[1] = RREG32(D2VGA_CONTROL); -	save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); -	save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); -	save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); -	save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL);  	save->vga_render_control = RREG32(VGA_RENDER_CONTROL);  	save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);  	save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);  	save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) { +		save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); +		save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL);  		save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);  		save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); +	} +	if (rdev->num_crtc >= 6) { +		save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); +		save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL);  		save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);  		save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);  	} @@ -997,35 +1006,45 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav  	WREG32(VGA_RENDER_CONTROL, 0);  	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);  	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); +	} +	if (rdev->num_crtc >= 6) {  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);  	}  	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);  	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);  		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +	} +	if (rdev->num_crtc >= 6) {  		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);  		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);  	}  	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);  	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +	} +	if (rdev->num_crtc >= 6) {  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);  	}  	WREG32(D1VGA_CONTROL, 0);  	WREG32(D2VGA_CONTROL, 0); -	WREG32(EVERGREEN_D3VGA_CONTROL, 0); -	WREG32(EVERGREEN_D4VGA_CONTROL, 0); -	WREG32(EVERGREEN_D5VGA_CONTROL, 0); -	WREG32(EVERGREEN_D6VGA_CONTROL, 0); +	if (rdev->num_crtc >= 4) { +		WREG32(EVERGREEN_D3VGA_CONTROL, 0); +		WREG32(EVERGREEN_D4VGA_CONTROL, 0); +	} +	if (rdev->num_crtc >= 6) { +		WREG32(EVERGREEN_D5VGA_CONTROL, 0); +		WREG32(EVERGREEN_D6VGA_CONTROL, 0); +	}  }  void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) @@ -1048,7 +1067,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s  	WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET,  	       (u32)rdev->mc.vram_start); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,  		       upper_32_bits(rdev->mc.vram_start));  		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, @@ -1066,7 +1085,8 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s  		       (u32)rdev->mc.vram_start);  		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,  		       (u32)rdev->mc.vram_start); - +	} +	if (rdev->num_crtc >= 6) {  		WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,  		       upper_32_bits(rdev->mc.vram_start));  		WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, @@ -1094,31 +1114,41 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s  	/* Restore video state */  	WREG32(D1VGA_CONTROL, save->vga_control[0]);  	WREG32(D2VGA_CONTROL, save->vga_control[1]); -	WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); -	WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); -	WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); -	WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); +	if (rdev->num_crtc >= 4) { +		WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); +		WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); +	} +	if (rdev->num_crtc >= 6) { +		WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); +		WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); +	}  	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);  	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); +	} +	if (rdev->num_crtc >= 6) {  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);  	}  	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]);  	WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]);  		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); +	} +	if (rdev->num_crtc >= 6) {  		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]);  		WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]);  	}  	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);  	WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +	} +	if (rdev->num_crtc >= 6) {  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);  		WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);  	} @@ -1970,7 +2000,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)  			gb_backend_map = 0x66442200;  			break;  		case CHIP_JUNIPER: -			gb_backend_map = 0x00006420; +			gb_backend_map = 0x00002200;  			break;  		default:  			gb_backend_map = @@ -2006,9 +2036,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)  		rdev->config.evergreen.tile_config |= (3 << 0);  		break;  	} -	/* num banks is 8 on all fusion asics */ +	/* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */  	if (rdev->flags & RADEON_IS_IGP) -		rdev->config.evergreen.tile_config |= 8 << 4; +		rdev->config.evergreen.tile_config |= 1 << 4;  	else  		rdev->config.evergreen.tile_config |=  			((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; @@ -2241,7 +2271,10 @@ int evergreen_mc_init(struct radeon_device *rdev)  	/* Get VRAM informations */  	rdev->mc.vram_is_ddr = true; -	tmp = RREG32(MC_ARB_RAMCFG); +	if (rdev->flags & RADEON_IS_IGP) +		tmp = RREG32(FUS_MC_ARB_RAMCFG); +	else +		tmp = RREG32(MC_ARB_RAMCFG);  	if (tmp & CHANSIZE_OVERRIDE) {  		chansize = 16;  	} else if (tmp & CHANSIZE_MASK) { @@ -2407,18 +2440,22 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)  	WREG32(GRBM_INT_CNTL, 0);  	WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);  	WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);  		WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +	} +	if (rdev->num_crtc >= 6) {  		WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);  		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);  	}  	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);  	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);  		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); +	} +	if (rdev->num_crtc >= 6) {  		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);  		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);  	} @@ -2537,19 +2574,25 @@ int evergreen_irq_set(struct radeon_device *rdev)  	WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1);  	WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2); -	if (!(rdev->flags & RADEON_IS_IGP)) { +	if (rdev->num_crtc >= 4) {  		WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3);  		WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4); +	} +	if (rdev->num_crtc >= 6) {  		WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5);  		WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);  	}  	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1);  	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2); -	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); -	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); -	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); -	WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); +	if (rdev->num_crtc >= 4) { +		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3); +		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4); +	} +	if (rdev->num_crtc >= 6) { +		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5); +		WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6); +	}  	WREG32(DC_HPD1_INT_CONTROL, hpd1);  	WREG32(DC_HPD2_INT_CONTROL, hpd2); @@ -2573,53 +2616,57 @@ static inline void evergreen_irq_ack(struct radeon_device *rdev)  	rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5);  	rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);  	rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET); -	rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); -	rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); -	rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); -	rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); +	if (rdev->num_crtc >= 4) { +		rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET); +		rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET); +	} +	if (rdev->num_crtc >= 6) { +		rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET); +		rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET); +	}  	if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)  		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);  	if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)  		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -	if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED) -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -	if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED) -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -	if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED) -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -	if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED) -		WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); -  	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)  		WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);  	if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)  		WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK); -  	if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)  		WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK);  	if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)  		WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK); -	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) -		WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); -	if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) -		WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK); - -	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) -		WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK); -	if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) -		WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK); - -	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) -		WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); -	if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) -		WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK); +	if (rdev->num_crtc >= 4) { +		if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED) +			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); +		if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED) +			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); +		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT) +			WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK); +		if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT) +			WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK); +		if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT) +			WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK); +		if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT) +			WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK); +	} -	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) -		WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK); -	if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) -		WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK); +	if (rdev->num_crtc >= 6) { +		if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED) +			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); +		if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED) +			WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR); +		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT) +			WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK); +		if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT) +			WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK); +		if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT) +			WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK); +		if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT) +			WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK); +	}  	if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) {  		tmp = RREG32(DC_HPD1_INT_CONTROL); @@ -2694,28 +2741,25 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev)  int evergreen_irq_process(struct radeon_device *rdev)  { -	u32 wptr = evergreen_get_ih_wptr(rdev); -	u32 rptr = rdev->ih.rptr; +	u32 wptr; +	u32 rptr;  	u32 src_id, src_data;  	u32 ring_index;  	unsigned long flags;  	bool queue_hotplug = false; -	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); -	if (!rdev->ih.enabled) +	if (!rdev->ih.enabled || rdev->shutdown)  		return IRQ_NONE; -	spin_lock_irqsave(&rdev->ih.lock, flags); +	wptr = evergreen_get_ih_wptr(rdev); +	rptr = rdev->ih.rptr; +	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); +	spin_lock_irqsave(&rdev->ih.lock, flags);  	if (rptr == wptr) {  		spin_unlock_irqrestore(&rdev->ih.lock, flags);  		return IRQ_NONE;  	} -	if (rdev->shutdown) { -		spin_unlock_irqrestore(&rdev->ih.lock, flags); -		return IRQ_NONE; -	} -  restart_ih:  	/* display interrupts */  	evergreen_irq_ack(rdev); @@ -2944,7 +2988,7 @@ restart_ih:  			radeon_fence_process(rdev);  			break;  		case 233: /* GUI IDLE */ -			DRM_DEBUG("IH: CP EOP\n"); +			DRM_DEBUG("IH: GUI idle\n");  			rdev->pm.gui_idle = true;  			wake_up(&rdev->irq.idle_queue);  			break; @@ -3230,6 +3274,7 @@ void evergreen_fini(struct radeon_device *rdev)  	r700_cp_fini(rdev);  	r600_irq_fini(rdev);  	radeon_wb_fini(rdev); +	radeon_ib_pool_fini(rdev);  	radeon_irq_kms_fini(rdev);  	evergreen_pcie_gart_fini(rdev);  	radeon_gem_fini(rdev); diff --git a/drivers/gpu/drm/radeon/evergreen_blit_kms.c b/drivers/gpu/drm/radeon/evergreen_blit_kms.c index 57f3bc17b87..2eb251858e7 100644 --- a/drivers/gpu/drm/radeon/evergreen_blit_kms.c +++ b/drivers/gpu/drm/radeon/evergreen_blit_kms.c @@ -252,7 +252,7 @@ draw_auto(struct radeon_device *rdev)  } -/* emits 36 */ +/* emits 39 */  static void  set_default_state(struct radeon_device *rdev)  { @@ -531,6 +531,11 @@ set_default_state(struct radeon_device *rdev)  		radeon_ring_write(rdev, (SQ_DYN_GPR_CNTL_PS_FLUSH_REQ - PACKET3_SET_CONFIG_REG_START) >> 2);  		radeon_ring_write(rdev, 0); +		/* setup LDS */ +		radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1)); +		radeon_ring_write(rdev, (SQ_LDS_RESOURCE_MGMT - PACKET3_SET_CONFIG_REG_START) >> 2); +		radeon_ring_write(rdev, 0x10001000); +  		/* SQ config */  		radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 11));  		radeon_ring_write(rdev, (SQ_CONFIG - PACKET3_SET_CONFIG_REG_START) >> 2); @@ -773,7 +778,7 @@ int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)  	/* calculate number of loops correctly */  	ring_size = num_loops * dwords_per_loop;  	/* set default  + shaders */ -	ring_size += 52; /* shaders + def state */ +	ring_size += 55; /* shaders + def state */  	ring_size += 10; /* fence emit for VB IB */  	ring_size += 5; /* done copy */  	ring_size += 10; /* fence emit for done copy */ diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 1636e344982..b7b2714f0b3 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -466,7 +466,7 @@  #define IH_RB_WPTR_ADDR_LO                                0x3e14  #define IH_CNTL                                           0x3e18  #       define ENABLE_INTR                                (1 << 0) -#       define IH_MC_SWAP(x)                              ((x) << 2) +#       define IH_MC_SWAP(x)                              ((x) << 1)  #       define IH_MC_SWAP_NONE                            0  #       define IH_MC_SWAP_16BIT                           1  #       define IH_MC_SWAP_32BIT                           2 @@ -547,7 +547,7 @@  #       define LB_D5_VBLANK_INTERRUPT                   (1 << 3)  #       define DC_HPD5_INTERRUPT                        (1 << 17)  #       define DC_HPD5_RX_INTERRUPT                     (1 << 18) -#define DISP_INTERRUPT_STATUS_CONTINUE5                 0x6050 +#define DISP_INTERRUPT_STATUS_CONTINUE5                 0x6150  #       define LB_D6_VLINE_INTERRUPT                    (1 << 2)  #       define LB_D6_VBLANK_INTERRUPT                   (1 << 3)  #       define DC_HPD6_INTERRUPT                        (1 << 17) diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 16caafeadf5..559dbd41290 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1581,6 +1581,7 @@ void cayman_fini(struct radeon_device *rdev)  	cayman_cp_fini(rdev);  	r600_irq_fini(rdev);  	radeon_wb_fini(rdev); +	radeon_ib_pool_fini(rdev);  	radeon_irq_kms_fini(rdev);  	cayman_pcie_gart_fini(rdev);  	radeon_gem_fini(rdev); diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 9736746da2d..4672869cdb2 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -320,7 +320,7 @@  #define	CGTS_USER_TCC_DISABLE				0x914C  #define		TCC_DISABLE_MASK				0xFFFF0000  #define		TCC_DISABLE_SHIFT				16 -#define	CGTS_SM_CTRL_REG				0x915C +#define	CGTS_SM_CTRL_REG				0x9150  #define		OVERRIDE				(1 << 21)  #define	TA_CNTL_AUX					0x9508 diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h index 2fef9de7f36..686f9dc5d4b 100644 --- a/drivers/gpu/drm/radeon/r100_track.h +++ b/drivers/gpu/drm/radeon/r100_track.h @@ -63,7 +63,7 @@ struct r100_cs_track {  	unsigned			num_arrays;  	unsigned			max_indx;  	unsigned			color_channel_mask; -	struct r100_cs_track_array	arrays[11]; +	struct r100_cs_track_array	arrays[16];  	struct r100_cs_track_cb 	cb[R300_MAX_CB];  	struct r100_cs_track_cb 	zb;  	struct r100_cs_track_cb 	aa; @@ -146,6 +146,12 @@ static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,  	ib = p->ib->ptr;  	track = (struct r100_cs_track *)p->track;  	c = radeon_get_ib_value(p, idx++) & 0x1F; +	if (c > 16) { +	    DRM_ERROR("Only 16 vertex buffers are allowed %d\n", +		      pkt->opcode); +	    r100_cs_dump_packet(p, pkt); +	    return -EINVAL; +	}  	track->num_arrays = c;  	for (i = 0; i < (c - 1); i+=2, idx+=3) {  		r = r100_cs_packet_next_reloc(p, &reloc); diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index d74d4d71437..bc54b26cb32 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -590,6 +590,9 @@ void r600_pm_misc(struct radeon_device *rdev)  	struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;  	if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { +		/* 0xff01 is a flag rather then an actual voltage */ +		if (voltage->voltage == 0xff01) +			return;  		if (voltage->voltage != rdev->pm.current_vddc) {  			radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);  			rdev->pm.current_vddc = voltage->voltage; @@ -2625,6 +2628,7 @@ void r600_fini(struct radeon_device *rdev)  	r600_cp_fini(rdev);  	r600_irq_fini(rdev);  	radeon_wb_fini(rdev); +	radeon_ib_pool_fini(rdev);  	radeon_irq_kms_fini(rdev);  	r600_pcie_gart_fini(rdev);  	radeon_agp_fini(rdev); @@ -3294,27 +3298,26 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)  int r600_irq_process(struct radeon_device *rdev)  { -	u32 wptr = r600_get_ih_wptr(rdev); -	u32 rptr = rdev->ih.rptr; +	u32 wptr; +	u32 rptr;  	u32 src_id, src_data;  	u32 ring_index;  	unsigned long flags;  	bool queue_hotplug = false; -	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); -	if (!rdev->ih.enabled) +	if (!rdev->ih.enabled || rdev->shutdown)  		return IRQ_NONE; +	wptr = r600_get_ih_wptr(rdev); +	rptr = rdev->ih.rptr; +	DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); +  	spin_lock_irqsave(&rdev->ih.lock, flags);  	if (rptr == wptr) {  		spin_unlock_irqrestore(&rdev->ih.lock, flags);  		return IRQ_NONE;  	} -	if (rdev->shutdown) { -		spin_unlock_irqrestore(&rdev->ih.lock, flags); -		return IRQ_NONE; -	}  restart_ih:  	/* display interrupts */ @@ -3444,7 +3447,7 @@ restart_ih:  			radeon_fence_process(rdev);  			break;  		case 233: /* GUI IDLE */ -			DRM_DEBUG("IH: CP EOP\n"); +			DRM_DEBUG("IH: GUI idle\n");  			rdev->pm.gui_idle = true;  			wake_up(&rdev->irq.idle_queue);  			break; diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index f140a0d5cb5..0245ae6c204 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -536,7 +536,7 @@  #define IH_RB_WPTR_ADDR_LO                                0x3e14  #define IH_CNTL                                           0x3e18  #       define ENABLE_INTR                                (1 << 0) -#       define IH_MC_SWAP(x)                              ((x) << 2) +#       define IH_MC_SWAP(x)                              ((x) << 1)  #       define IH_MC_SWAP_NONE                            0  #       define IH_MC_SWAP_16BIT                           1  #       define IH_MC_SWAP_32BIT                           2 diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ba643b57605..ef0e0e01691 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -165,6 +165,7 @@ struct radeon_clock {  	uint32_t default_sclk;  	uint32_t default_dispclk;  	uint32_t dp_extclk; +	uint32_t max_pixel_clock;  };  /* @@ -178,6 +179,7 @@ void radeon_pm_resume(struct radeon_device *rdev);  void radeon_combios_get_power_modes(struct radeon_device *rdev);  void radeon_atombios_get_power_modes(struct radeon_device *rdev);  void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); +int radeon_atom_get_max_vddc(struct radeon_device *rdev, u16 *voltage);  void rs690_pm_info(struct radeon_device *rdev);  extern int rv6xx_get_temp(struct radeon_device *rdev);  extern int rv770_get_temp(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 9bd162fc9b0..b2449629537 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -938,6 +938,13 @@ static struct radeon_asic cayman_asic = {  int radeon_asic_init(struct radeon_device *rdev)  {  	radeon_register_accessor_init(rdev); + +	/* set the number of crtcs */ +	if (rdev->flags & RADEON_SINGLE_CRTC) +		rdev->num_crtc = 1; +	else +		rdev->num_crtc = 2; +  	switch (rdev->family) {  	case CHIP_R100:  	case CHIP_RV100: @@ -1017,6 +1024,11 @@ int radeon_asic_init(struct radeon_device *rdev)  	case CHIP_JUNIPER:  	case CHIP_CYPRESS:  	case CHIP_HEMLOCK: +		/* set num crtcs */ +		if (rdev->family == CHIP_CEDAR) +			rdev->num_crtc = 4; +		else +			rdev->num_crtc = 6;  		rdev->asic = &evergreen_asic;  		break;  	case CHIP_PALM: @@ -1027,10 +1039,17 @@ int radeon_asic_init(struct radeon_device *rdev)  	case CHIP_BARTS:  	case CHIP_TURKS:  	case CHIP_CAICOS: +		/* set num crtcs */ +		if (rdev->family == CHIP_CAICOS) +			rdev->num_crtc = 4; +		else +			rdev->num_crtc = 6;  		rdev->asic = &btc_asic;  		break;  	case CHIP_CAYMAN:  		rdev->asic = &cayman_asic; +		/* set num crtcs */ +		rdev->num_crtc = 6;  		break;  	default:  		/* FIXME: not supported yet */ @@ -1042,18 +1061,6 @@ int radeon_asic_init(struct radeon_device *rdev)  		rdev->asic->set_memory_clock = NULL;  	} -	/* set the number of crtcs */ -	if (rdev->flags & RADEON_SINGLE_CRTC) -		rdev->num_crtc = 1; -	else { -		if (ASIC_IS_DCE41(rdev)) -			rdev->num_crtc = 2; -		else if (ASIC_IS_DCE4(rdev)) -			rdev->num_crtc = 6; -		else -			rdev->num_crtc = 2; -	} -  	return 0;  } diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 90dfb2b8cf0..bf2b61584cd 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1246,6 +1246,10 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)  		}  		*dcpll = *p1pll; +		rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock); +		if (rdev->clock.max_pixel_clock == 0) +			rdev->clock.max_pixel_clock = 40000; +  		return true;  	} @@ -2316,6 +2320,14 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev,  			le16_to_cpu(clock_info->r600.usVDDC);  	} +	/* patch up vddc if necessary */ +	if (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage == 0xff01) { +		u16 vddc; + +		if (radeon_atom_get_max_vddc(rdev, &vddc) == 0) +			rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc; +	} +  	if (rdev->flags & RADEON_IS_IGP) {  		/* skip invalid modes */  		if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0) @@ -2603,6 +2615,10 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v  	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))  		return; +	/* 0xff01 is a flag rather then an actual voltage */ +	if (voltage_level == 0xff01) +		return; +  	switch (crev) {  	case 1:  		args.v1.ucVoltageType = voltage_type; @@ -2622,7 +2638,35 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v  	atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);  } +int radeon_atom_get_max_vddc(struct radeon_device *rdev, +			     u16 *voltage) +{ +	union set_voltage args; +	int index = GetIndexIntoMasterTable(COMMAND, SetVoltage); +	u8 frev, crev; + +	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) +		return -EINVAL; +	switch (crev) { +	case 1: +		return -EINVAL; +	case 2: +		args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE; +		args.v2.ucVoltageMode = 0; +		args.v2.usVoltageLevel = 0; + +		atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + +		*voltage = le16_to_cpu(args.v2.usVoltageLevel); +		break; +	default: +		DRM_ERROR("Unknown table version %d, %d\n", frev, crev); +		return -EINVAL; +	} + +	return 0; +}  void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)  { diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 1aba85cad1a..229a20f10e2 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -104,7 +104,7 @@ static bool radeon_read_bios(struct radeon_device *rdev)  static bool radeon_atrm_get_bios(struct radeon_device *rdev)  {  	int ret; -	int size = 64 * 1024; +	int size = 256 * 1024;  	int i;  	if (!radeon_atrm_supported(rdev->pdev)) @@ -331,7 +331,7 @@ static bool avivo_read_disabled_bios(struct radeon_device *rdev)  	seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);  	viph_control = RREG32(RADEON_VIPH_CONTROL); -	bus_cntl = RREG32(RADEON_BUS_CNTL); +	bus_cntl = RREG32(RV370_BUS_CNTL);  	d1vga_control = RREG32(AVIVO_D1VGA_CONTROL);  	d2vga_control = RREG32(AVIVO_D2VGA_CONTROL);  	vga_render_control = RREG32(AVIVO_VGA_RENDER_CONTROL); @@ -350,7 +350,7 @@ static bool avivo_read_disabled_bios(struct radeon_device *rdev)  	WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));  	/* enable the rom */ -	WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); +	WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM));  	/* Disable VGA mode */  	WREG32(AVIVO_D1VGA_CONTROL, @@ -367,7 +367,7 @@ static bool avivo_read_disabled_bios(struct radeon_device *rdev)  	/* restore regs */  	WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);  	WREG32(RADEON_VIPH_CONTROL, viph_control); -	WREG32(RADEON_BUS_CNTL, bus_cntl); +	WREG32(RV370_BUS_CNTL, bus_cntl);  	WREG32(AVIVO_D1VGA_CONTROL, d1vga_control);  	WREG32(AVIVO_D2VGA_CONTROL, d2vga_control);  	WREG32(AVIVO_VGA_RENDER_CONTROL, vga_render_control); @@ -390,7 +390,10 @@ static bool legacy_read_disabled_bios(struct radeon_device *rdev)  	seprom_cntl1 = RREG32(RADEON_SEPROM_CNTL1);  	viph_control = RREG32(RADEON_VIPH_CONTROL); -	bus_cntl = RREG32(RADEON_BUS_CNTL); +	if (rdev->flags & RADEON_IS_PCIE) +		bus_cntl = RREG32(RV370_BUS_CNTL); +	else +		bus_cntl = RREG32(RADEON_BUS_CNTL);  	crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL);  	crtc2_gen_cntl = 0;  	crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); @@ -412,7 +415,10 @@ static bool legacy_read_disabled_bios(struct radeon_device *rdev)  	WREG32(RADEON_VIPH_CONTROL, (viph_control & ~RADEON_VIPH_EN));  	/* enable the rom */ -	WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM)); +	if (rdev->flags & RADEON_IS_PCIE) +		WREG32(RV370_BUS_CNTL, (bus_cntl & ~RV370_BUS_BIOS_DIS_ROM)); +	else +		WREG32(RADEON_BUS_CNTL, (bus_cntl & ~RADEON_BUS_BIOS_DIS_ROM));  	/* Turn off mem requests and CRTC for both controllers */  	WREG32(RADEON_CRTC_GEN_CNTL, @@ -439,7 +445,10 @@ static bool legacy_read_disabled_bios(struct radeon_device *rdev)  	/* restore regs */  	WREG32(RADEON_SEPROM_CNTL1, seprom_cntl1);  	WREG32(RADEON_VIPH_CONTROL, viph_control); -	WREG32(RADEON_BUS_CNTL, bus_cntl); +	if (rdev->flags & RADEON_IS_PCIE) +		WREG32(RV370_BUS_CNTL, bus_cntl); +	else +		WREG32(RADEON_BUS_CNTL, bus_cntl);  	WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl);  	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {  		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 5249af8931e..2d48e7a1474 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -117,7 +117,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)  	p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;  	if (p1pll->reference_div < 2)  		p1pll->reference_div = 12; -	p2pll->reference_div = p1pll->reference_div;	 +	p2pll->reference_div = p1pll->reference_div;  	/* These aren't in the device-tree */  	if (rdev->family >= CHIP_R420) { @@ -139,6 +139,8 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)  		p2pll->pll_out_min = 12500;  		p2pll->pll_out_max = 35000;  	} +	/* not sure what the max should be in all cases */ +	rdev->clock.max_pixel_clock = 35000;  	spll->reference_freq = mpll->reference_freq = p1pll->reference_freq;  	spll->reference_div = mpll->reference_div = @@ -151,7 +153,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)  	else  		rdev->clock.default_sclk =  			radeon_legacy_get_engine_clock(rdev); -			 +  	val = of_get_property(dp, "ATY,MCLK", NULL);  	if (val && *val)  		rdev->clock.default_mclk = (*val) / 10; @@ -160,7 +162,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)  			radeon_legacy_get_memory_clock(rdev);  	DRM_INFO("Using device-tree clock info\n"); -	 +  	return true;  }  #else diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 5b991f7c6e2..e4594676a07 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -866,6 +866,11 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)  		rdev->clock.default_sclk = sclk;  		rdev->clock.default_mclk = mclk; +		if (RBIOS32(pll_info + 0x16)) +			rdev->clock.max_pixel_clock = RBIOS32(pll_info + 0x16); +		else +			rdev->clock.max_pixel_clock = 35000; /* might need something asic specific */ +  		return true;  	}  	return false; @@ -1548,10 +1553,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)  			   (rdev->pdev->subsystem_device == 0x4a48)) {  			/* Mac X800 */  			rdev->mode_info.connector_table = CT_MAC_X800; -		} else if ((rdev->pdev->device == 0x4150) && +		} else if ((of_machine_is_compatible("PowerMac7,2") || +			    of_machine_is_compatible("PowerMac7,3")) && +			   (rdev->pdev->device == 0x4150) &&  			   (rdev->pdev->subsystem_vendor == 0x1002) &&  			   (rdev->pdev->subsystem_device == 0x4150)) { -			/* Mac G5 9600 */ +			/* Mac G5 tower 9600 */  			rdev->mode_info.connector_table = CT_MAC_G5_9600;  		} else  #endif /* CONFIG_PPC_PMAC */ diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index ee1dccb3fec..9792d4ffdc8 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -44,12 +44,20 @@ extern void  radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,  			     struct drm_connector *drm_connector); +bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector); +  void radeon_connector_hotplug(struct drm_connector *connector)  {  	struct drm_device *dev = connector->dev;  	struct radeon_device *rdev = dev->dev_private;  	struct radeon_connector *radeon_connector = to_radeon_connector(connector); +	/* bail if the connector does not have hpd pin, e.g., +	 * VGA, TV, etc. +	 */ +	if (radeon_connector->hpd.hpd == RADEON_HPD_NONE) +		return; +  	radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);  	/* powering up/down the eDP panel generates hpd events which @@ -626,8 +634,14 @@ static int radeon_vga_get_modes(struct drm_connector *connector)  static int radeon_vga_mode_valid(struct drm_connector *connector,  				  struct drm_display_mode *mode)  { +	struct drm_device *dev = connector->dev; +	struct radeon_device *rdev = dev->dev_private; +  	/* XXX check mode bandwidth */ -	/* XXX verify against max DAC output frequency */ + +	if ((mode->clock / 10) > rdev->clock.max_pixel_clock) +		return MODE_CLOCK_HIGH; +  	return MODE_OK;  } @@ -830,6 +844,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  		if (!radeon_connector->edid) {  			DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",  					drm_get_connector_name(connector)); +			/* rs690 seems to have a problem with connectors not existing and always +			 * return a block of 0's. If we see this just stop polling on this output */ +			if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) { +				ret = connector_status_disconnected; +				DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector)); +				radeon_connector->ddc_bus = NULL; +			}  		} else {  			radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); @@ -1015,6 +1036,11 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector,  		} else  			return MODE_CLOCK_HIGH;  	} + +	/* check against the max pixel clock */ +	if ((mode->clock / 10) > rdev->clock.max_pixel_clock) +		return MODE_CLOCK_HIGH; +  	return MODE_OK;  } @@ -1052,10 +1078,11 @@ static int radeon_dp_get_modes(struct drm_connector *connector)  {  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);  	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; +	struct drm_encoder *encoder = radeon_best_single_encoder(connector);  	int ret; -	if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { -		struct drm_encoder *encoder; +	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || +	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {  		struct drm_display_mode *mode;  		if (!radeon_dig_connector->edp_on) @@ -1067,7 +1094,6 @@ static int radeon_dp_get_modes(struct drm_connector *connector)  						     ATOM_TRANSMITTER_ACTION_POWER_OFF);  		if (ret > 0) { -			encoder = radeon_best_single_encoder(connector);  			if (encoder) {  				radeon_fixup_lvds_native_mode(encoder, connector);  				/* add scaled modes */ @@ -1091,8 +1117,14 @@ static int radeon_dp_get_modes(struct drm_connector *connector)  			/* add scaled modes */  			radeon_add_common_modes(encoder, connector);  		} -	} else +	} else { +		/* need to setup ddc on the bridge */ +		if (radeon_connector_encoder_is_dp_bridge(connector)) { +			if (encoder) +				radeon_atom_ext_encoder_setup_ddc(encoder); +		}  		ret = radeon_ddc_get_modes(radeon_connector); +	}  	return ret;  } @@ -1176,14 +1208,15 @@ radeon_dp_detect(struct drm_connector *connector, bool force)  	struct radeon_connector *radeon_connector = to_radeon_connector(connector);  	enum drm_connector_status ret = connector_status_disconnected;  	struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; +	struct drm_encoder *encoder = radeon_best_single_encoder(connector);  	if (radeon_connector->edid) {  		kfree(radeon_connector->edid);  		radeon_connector->edid = NULL;  	} -	if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { -		struct drm_encoder *encoder = radeon_best_single_encoder(connector); +	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || +	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {  		if (encoder) {  			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);  			struct drm_display_mode *native_mode = &radeon_encoder->native_mode; @@ -1203,6 +1236,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force)  			atombios_set_edp_panel_power(connector,  						     ATOM_TRANSMITTER_ACTION_POWER_OFF);  	} else { +		/* need to setup ddc on the bridge */ +		if (radeon_connector_encoder_is_dp_bridge(connector)) { +			if (encoder) +				radeon_atom_ext_encoder_setup_ddc(encoder); +		}  		radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);  		if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {  			ret = connector_status_connected; @@ -1217,6 +1255,16 @@ radeon_dp_detect(struct drm_connector *connector, bool force)  					ret = connector_status_connected;  			}  		} + +		if ((ret == connector_status_disconnected) && +		    radeon_connector->dac_load_detect) { +			struct drm_encoder *encoder = radeon_best_single_encoder(connector); +			struct drm_encoder_helper_funcs *encoder_funcs; +			if (encoder) { +				encoder_funcs = encoder->helper_private; +				ret = encoder_funcs->detect(encoder, connector); +			} +		}  	}  	radeon_connector_update_scratch_regs(connector, ret); @@ -1231,7 +1279,8 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,  	/* XXX check mode bandwidth */ -	if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { +	if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) || +	    (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {  		struct drm_encoder *encoder = radeon_best_single_encoder(connector);  		if ((mode->hdisplay < 320) || (mode->vdisplay < 240)) @@ -1241,7 +1290,7 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,  			struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);  			struct drm_display_mode *native_mode = &radeon_encoder->native_mode; -		/* AVIVO hardware supports downscaling modes larger than the panel +			/* AVIVO hardware supports downscaling modes larger than the panel  			 * to the panel size, but I'm not sure this is desirable.  			 */  			if ((mode->hdisplay > native_mode->hdisplay) || @@ -1390,6 +1439,10 @@ radeon_add_atom_connector(struct drm_device *dev,  		default:  			connector->interlace_allowed = true;  			connector->doublescan_allowed = true; +			radeon_connector->dac_load_detect = true; +			drm_connector_attach_property(&radeon_connector->base, +						      rdev->mode_info.load_detect_property, +						      1);  			break;  		case DRM_MODE_CONNECTOR_DVII:  		case DRM_MODE_CONNECTOR_DVID: @@ -1411,6 +1464,12 @@ radeon_add_atom_connector(struct drm_device *dev,  				connector->doublescan_allowed = true;  			else  				connector->doublescan_allowed = false; +			if (connector_type == DRM_MODE_CONNECTOR_DVII) { +				radeon_connector->dac_load_detect = true; +				drm_connector_attach_property(&radeon_connector->base, +							      rdev->mode_info.load_detect_property, +							      1); +			}  			break;  		case DRM_MODE_CONNECTOR_LVDS:  		case DRM_MODE_CONNECTOR_eDP: diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index e680501c78e..7cfaa7e2f3b 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -215,6 +215,8 @@ int radeon_wb_init(struct radeon_device *rdev)  		return r;  	} +	/* clear wb memory */ +	memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE);  	/* disable event_write fences */  	rdev->wb.use_event = false;  	/* disabled via module param */ diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 03f124d626c..b293487e5aa 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -367,7 +367,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,  	}  	if (ASIC_IS_DCE3(rdev) && -	    (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) { +	    ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || +	     radeon_encoder_is_dp_bridge(encoder))) {  		struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);  		radeon_dp_set_link_config(connector, mode);  	} @@ -660,21 +661,16 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)  	if (radeon_encoder_is_dp_bridge(encoder))  		return ATOM_ENCODER_MODE_DP; +	/* DVO is always DVO */ +	if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO) +		return ATOM_ENCODER_MODE_DVO; +  	connector = radeon_get_connector_for_encoder(encoder); -	if (!connector) { -		switch (radeon_encoder->encoder_id) { -		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: -		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: -		case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: -		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: -		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: -			return ATOM_ENCODER_MODE_DVI; -		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: -		case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: -		default: -			return ATOM_ENCODER_MODE_CRT; -		} -	} +	/* if we don't have an active device yet, just use one of +	 * the connectors tied to the encoder. +	 */ +	if (!connector) +		connector = radeon_get_connector_for_encoder_init(encoder);  	radeon_connector = to_radeon_connector(connector);  	switch (connector->connector_type) { @@ -1094,9 +1090,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t  			break;  		} -		if (is_dp) +		if (is_dp) {  			args.v2.acConfig.fCoherentMode = 1; -		else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { +			args.v2.acConfig.fDPConnector = 1; +		} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {  			if (dig->coherent_mode)  				args.v2.acConfig.fCoherentMode = 1;  			if (radeon_encoder->pixel_clock > 165000) @@ -1435,7 +1432,11 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)  	if (is_dig) {  		switch (mode) {  		case DRM_MODE_DPMS_ON: -			atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); +			/* some early dce3.2 boards have a bug in their transmitter control table */ +			if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730)) +				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); +			else +				atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);  			if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {  				struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); @@ -1526,26 +1527,29 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)  	}  	if (ext_encoder) { -		int action; -  		switch (mode) {  		case DRM_MODE_DPMS_ON:  		default: -			if (ASIC_IS_DCE41(rdev)) -				action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT; -			else -				action = ATOM_ENABLE; +			if (ASIC_IS_DCE41(rdev)) { +				atombios_external_encoder_setup(encoder, ext_encoder, +								EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT); +				atombios_external_encoder_setup(encoder, ext_encoder, +								EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF); +			} else +				atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);  			break;  		case DRM_MODE_DPMS_STANDBY:  		case DRM_MODE_DPMS_SUSPEND:  		case DRM_MODE_DPMS_OFF: -			if (ASIC_IS_DCE41(rdev)) -				action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT; -			else -				action = ATOM_DISABLE; +			if (ASIC_IS_DCE41(rdev)) { +				atombios_external_encoder_setup(encoder, ext_encoder, +								EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING); +				atombios_external_encoder_setup(encoder, ext_encoder, +								EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT); +			} else +				atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);  			break;  		} -		atombios_external_encoder_setup(encoder, ext_encoder, action);  	}  	radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false); @@ -2004,6 +2008,65 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec  	return connector_status_disconnected;  } +static enum drm_connector_status +radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector) +{ +	struct drm_device *dev = encoder->dev; +	struct radeon_device *rdev = dev->dev_private; +	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); +	struct radeon_connector *radeon_connector = to_radeon_connector(connector); +	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); +	u32 bios_0_scratch; + +	if (!ASIC_IS_DCE4(rdev)) +		return connector_status_unknown; + +	if (!ext_encoder) +		return connector_status_unknown; + +	if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0) +		return connector_status_unknown; + +	/* load detect on the dp bridge */ +	atombios_external_encoder_setup(encoder, ext_encoder, +					EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION); + +	bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH); + +	DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices); +	if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) { +		if (bios_0_scratch & ATOM_S0_CRT1_MASK) +			return connector_status_connected; +	} +	if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) { +		if (bios_0_scratch & ATOM_S0_CRT2_MASK) +			return connector_status_connected; +	} +	if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) { +		if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A)) +			return connector_status_connected; +	} +	if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) { +		if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A)) +			return connector_status_connected; /* CTV */ +		else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A)) +			return connector_status_connected; /* STV */ +	} +	return connector_status_disconnected; +} + +void +radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder) +{ +	struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder); + +	if (ext_encoder) +		/* ddc_setup on the dp bridge */ +		atombios_external_encoder_setup(encoder, ext_encoder, +						EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP); + +} +  static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)  {  	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); @@ -2167,7 +2230,7 @@ static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {  	.mode_set = radeon_atom_encoder_mode_set,  	.commit = radeon_atom_encoder_commit,  	.disable = radeon_atom_encoder_disable, -	/* no detect for TMDS/LVDS yet */ +	.detect = radeon_atom_dig_detect,  };  static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = { diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 1f822943657..021d2b6b556 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -40,6 +40,35 @@  #include "radeon.h"  #include "radeon_trace.h" +static void radeon_fence_write(struct radeon_device *rdev, u32 seq) +{ +	if (rdev->wb.enabled) { +		u32 scratch_index; +		if (rdev->wb.use_event) +			scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +		else +			scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +		rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);; +	} else +		WREG32(rdev->fence_drv.scratch_reg, seq); +} + +static u32 radeon_fence_read(struct radeon_device *rdev) +{ +	u32 seq; + +	if (rdev->wb.enabled) { +		u32 scratch_index; +		if (rdev->wb.use_event) +			scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +		else +			scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; +		seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); +	} else +		seq = RREG32(rdev->fence_drv.scratch_reg); +	return seq; +} +  int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)  {  	unsigned long irq_flags; @@ -50,12 +79,12 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)  		return 0;  	}  	fence->seq = atomic_add_return(1, &rdev->fence_drv.seq); -	if (!rdev->cp.ready) { +	if (!rdev->cp.ready)  		/* FIXME: cp is not running assume everythings is done right  		 * away  		 */ -		WREG32(rdev->fence_drv.scratch_reg, fence->seq); -	} else +		radeon_fence_write(rdev, fence->seq); +	else  		radeon_fence_ring_emit(rdev, fence);  	trace_radeon_fence_emit(rdev->ddev, fence->seq); @@ -73,15 +102,7 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev)  	bool wake = false;  	unsigned long cjiffies; -	if (rdev->wb.enabled) { -		u32 scratch_index; -		if (rdev->wb.use_event) -			scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; -		else -			scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base; -		seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]); -	} else -		seq = RREG32(rdev->fence_drv.scratch_reg); +	seq = radeon_fence_read(rdev);  	if (seq != rdev->fence_drv.last_seq) {  		rdev->fence_drv.last_seq = seq;  		rdev->fence_drv.last_jiffies = jiffies; @@ -251,7 +272,7 @@ retry:  			r = radeon_gpu_reset(rdev);  			if (r)  				return r; -			WREG32(rdev->fence_drv.scratch_reg, fence->seq); +			radeon_fence_write(rdev, fence->seq);  			rdev->gpu_lockup = false;  		}  		timeout = RADEON_FENCE_JIFFIES_TIMEOUT; @@ -351,7 +372,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev)  		write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);  		return r;  	} -	WREG32(rdev->fence_drv.scratch_reg, 0); +	radeon_fence_write(rdev, 0);  	atomic_set(&rdev->fence_drv.seq, 0);  	INIT_LIST_HEAD(&rdev->fence_drv.created);  	INIT_LIST_HEAD(&rdev->fence_drv.emited); @@ -391,7 +412,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data)  	struct radeon_fence *fence;  	seq_printf(m, "Last signaled fence 0x%08X\n", -		   RREG32(rdev->fence_drv.scratch_reg)); +		   radeon_fence_read(rdev));  	if (!list_empty(&rdev->fence_drv.emited)) {  		   fence = list_entry(rdev->fence_drv.emited.prev,  				      struct radeon_fence, list); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 977a341266b..6df4e3cec0c 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -483,6 +483,8 @@ extern void radeon_atom_encoder_init(struct radeon_device *rdev);  extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,  					   int action, uint8_t lane_num,  					   uint8_t lane_set); +extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); +extern struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder);  extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,  				u8 write_byte, u8 *read_byte); diff --git a/drivers/gpu/drm/radeon/radeon_reg.h b/drivers/gpu/drm/radeon/radeon_reg.h index ec93a75369e..bc44a3d35ec 100644 --- a/drivers/gpu/drm/radeon/radeon_reg.h +++ b/drivers/gpu/drm/radeon/radeon_reg.h @@ -300,6 +300,8 @@  #       define RADEON_BUS_READ_BURST         (1 << 30)  #define RADEON_BUS_CNTL1                    0x0034  #       define RADEON_BUS_WAIT_ON_LOCK_EN    (1 << 4) +#define RV370_BUS_CNTL                      0x004c +#       define RV370_BUS_BIOS_DIS_ROM        (1 << 2)  /* rv370/rv380, rv410, r423/r430/r480, r5xx */  #define RADEON_MSI_REARM_EN		    0x0160  #	define RV370_MSI_REARM_EN	     (1 << 0) diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 6e3b11e5abb..1f5850e473c 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -426,7 +426,7 @@ int rs600_gart_init(struct radeon_device *rdev)  	return radeon_gart_table_vram_alloc(rdev);  } -int rs600_gart_enable(struct radeon_device *rdev) +static int rs600_gart_enable(struct radeon_device *rdev)  {  	u32 tmp;  	int r, i; @@ -440,8 +440,8 @@ int rs600_gart_enable(struct radeon_device *rdev)  		return r;  	radeon_gart_restore(rdev);  	/* Enable bus master */ -	tmp = RREG32(R_00004C_BUS_CNTL) & C_00004C_BUS_MASTER_DIS; -	WREG32(R_00004C_BUS_CNTL, tmp); +	tmp = RREG32(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; +	WREG32(RADEON_BUS_CNTL, tmp);  	/* FIXME: setup default page */  	WREG32_MC(R_000100_MC_PT0_CNTL,  		  (S_000100_EFFECTIVE_L2_CACHE_SIZE(6) | diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index ef8a5babe9f..4de51891aa6 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -105,6 +105,9 @@ void rv770_pm_misc(struct radeon_device *rdev)  	struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;  	if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { +		/* 0xff01 is a flag rather then an actual voltage */ +		if (voltage->voltage == 0xff01) +			return;  		if (voltage->voltage != rdev->pm.current_vddc) {  			radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);  			rdev->pm.current_vddc = voltage->voltage; @@ -572,6 +575,12 @@ static void rv770_program_channel_remap(struct radeon_device *rdev)  	else  		tcp_chan_steer = 0x00fac688; +	/* RV770 CE has special chremap setup */ +	if (rdev->pdev->device == 0x944e) { +		tcp_chan_steer = 0x00b08b08; +		mc_shared_chremap = 0x00b08b08; +	} +  	WREG32(TCP_CHAN_STEER, tcp_chan_steer);  	WREG32(MC_SHARED_CHREMAP, mc_shared_chremap);  } @@ -1359,6 +1368,7 @@ void rv770_fini(struct radeon_device *rdev)  	r700_cp_fini(rdev);  	r600_irq_fini(rdev);  	radeon_wb_fini(rdev); +	radeon_ib_pool_fini(rdev);  	radeon_irq_kms_fini(rdev);  	rv770_pcie_gart_fini(rdev);  	rv770_vram_scratch_fini(rdev); diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index bf5f83ea14f..cb1ee4e0050 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -647,9 +647,6 @@ int savage_driver_firstopen(struct drm_device *dev)  	ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,  			 _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,  			 &dev_priv->aperture); -	if (ret) -		return ret; -  	return ret;  } diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 90e23e0bfad..58c271ebc0f 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -31,6 +31,7 @@  #include <linux/sched.h>  #include <linux/highmem.h>  #include <linux/pagemap.h> +#include <linux/shmem_fs.h>  #include <linux/file.h>  #include <linux/swap.h>  #include <linux/slab.h> @@ -484,7 +485,7 @@ static int ttm_tt_swapin(struct ttm_tt *ttm)  	swap_space = swap_storage->f_path.dentry->d_inode->i_mapping;  	for (i = 0; i < ttm->num_pages; ++i) { -		from_page = read_mapping_page(swap_space, i, NULL); +		from_page = shmem_read_mapping_page(swap_space, i);  		if (IS_ERR(from_page)) {  			ret = PTR_ERR(from_page);  			goto out_err; @@ -557,7 +558,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)  		from_page = ttm->pages[i];  		if (unlikely(from_page == NULL))  			continue; -		to_page = read_mapping_page(swap_space, i, NULL); +		to_page = shmem_read_mapping_page(swap_space, i);  		if (unlikely(IS_ERR(to_page))) {  			ret = PTR_ERR(to_page);  			goto out_err;  |