Browse Source

Merge branch 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (204 commits)
  agp: intel-agp: do not use PCI resources before pci_enable_device()
  agp: efficeon-agp: do not use PCI resources before pci_enable_device()
  drm: kill BKL from common code
  drm/kms: Simplify setup of the initial I2C encoder config.
  drm,io-mapping: Specify slot to use for atomic mappings
  drm/radeon/kms: only expose underscan on avivo chips
  drm/radeon: add new pci ids
  drm: Cleanup after failing to create master->unique and dev->name
  drm/radeon: tone down overchatty acpi debug messages.
  drm/radeon/kms: enable underscan option for digital connectors
  drm/radeon/kms: fix calculation of h/v scaling factors
  drm/radeon/kms/igp: sideport is AMD only
  drm/radeon/kms: handle the case of no active displays properly in the bandwidth code
  drm: move ttm global code to core drm
  drm/i915: Clear the Ironlake dithering flags when the pipe doesn't want it.
  drm/radeon/kms: make sure HPD is set to NONE on analog-only connectors
  drm/radeon/kms: make sure rio_mem is valid before unmapping it
  drm/agp/i915: trim stolen space to 32M
  drm/i915: Unset cursor if out-of-bounds upon mode change (v4)
  drm/i915: Unreference object not handle on creation
  ...
Linus Torvalds 15 years ago
parent
commit
fc1caf6eaf
100 changed files with 4256 additions and 2781 deletions
  1. 11 11
      drivers/char/agp/efficeon-agp.c
  2. 13 13
      drivers/char/agp/intel-agp.c
  3. 6 0
      drivers/char/agp/intel-agp.h
  4. 76 7
      drivers/char/agp/intel-gtt.c
  5. 6 5
      drivers/gpu/drm/Kconfig
  6. 5 2
      drivers/gpu/drm/Makefile
  7. 1 14
      drivers/gpu/drm/drm_bufs.c
  8. 23 7
      drivers/gpu/drm/drm_crtc.c
  9. 47 24
      drivers/gpu/drm/drm_crtc_helper.c
  10. 9 34
      drivers/gpu/drm/drm_drv.c
  11. 2 2
      drivers/gpu/drm/drm_edid.c
  12. 7 0
      drivers/gpu/drm/drm_encoder_slave.c
  13. 11 12
      drivers/gpu/drm/drm_fops.c
  14. 11 0
      drivers/gpu/drm/drm_gem.c
  15. 15 15
      drivers/gpu/drm/drm_global.c
  16. 17 6
      drivers/gpu/drm/drm_info.c
  17. 106 34
      drivers/gpu/drm/drm_ioctl.c
  18. 20 6
      drivers/gpu/drm/drm_irq.c
  19. 232 127
      drivers/gpu/drm/drm_mm.c
  20. 143 0
      drivers/gpu/drm/drm_pci.c
  21. 122 0
      drivers/gpu/drm/drm_platform.c
  22. 5 87
      drivers/gpu/drm/drm_stub.c
  23. 2 1
      drivers/gpu/drm/drm_sysfs.c
  24. 66 0
      drivers/gpu/drm/drm_trace.h
  25. 4 0
      drivers/gpu/drm/drm_trace_points.c
  26. 13 1
      drivers/gpu/drm/drm_vm.c
  27. 3 0
      drivers/gpu/drm/i2c/Makefile
  28. 20 2
      drivers/gpu/drm/i2c/ch7006_drv.c
  29. 1 1
      drivers/gpu/drm/i2c/ch7006_priv.h
  30. 462 0
      drivers/gpu/drm/i2c/sil164_drv.c
  31. 67 58
      drivers/gpu/drm/i810/i810_dma.c
  32. 1 1
      drivers/gpu/drm/i810/i810_drv.c
  33. 34 31
      drivers/gpu/drm/i810/i810_drv.h
  34. 72 65
      drivers/gpu/drm/i830/i830_dma.c
  35. 1 1
      drivers/gpu/drm/i830/i830_drv.c
  36. 26 23
      drivers/gpu/drm/i830/i830_drv.h
  37. 5 5
      drivers/gpu/drm/i830/i830_irq.c
  38. 17 7
      drivers/gpu/drm/i915/i915_dma.c
  39. 33 33
      drivers/gpu/drm/i915/i915_drv.c
  40. 22 7
      drivers/gpu/drm/i915/i915_drv.h
  41. 114 58
      drivers/gpu/drm/i915/i915_gem.c
  42. 0 2
      drivers/gpu/drm/i915/i915_gem_tiling.c
  43. 31 27
      drivers/gpu/drm/i915/i915_irq.c
  44. 28 28
      drivers/gpu/drm/i915/i915_reg.h
  45. 7 2
      drivers/gpu/drm/i915/i915_suspend.c
  46. 36 0
      drivers/gpu/drm/i915/i915_trace.h
  47. 397 161
      drivers/gpu/drm/i915/intel_display.c
  48. 125 18
      drivers/gpu/drm/i915/intel_dp.c
  49. 8 2
      drivers/gpu/drm/i915/intel_drv.h
  50. 5 4
      drivers/gpu/drm/i915/intel_hdmi.c
  51. 120 211
      drivers/gpu/drm/i915/intel_lvds.c
  52. 9 5
      drivers/gpu/drm/i915/intel_overlay.c
  53. 5 3
      drivers/gpu/drm/i915/intel_sdvo.c
  54. 5 7
      drivers/gpu/drm/i915/intel_tv.c
  55. 45 58
      drivers/gpu/drm/mga/mga_dma.c
  56. 2 2
      drivers/gpu/drm/mga/mga_drv.c
  57. 91 96
      drivers/gpu/drm/mga/mga_drv.h
  58. 4 5
      drivers/gpu/drm/mga/mga_irq.c
  59. 23 24
      drivers/gpu/drm/mga/mga_state.c
  60. 2 2
      drivers/gpu/drm/mga/mga_warp.c
  61. 10 1
      drivers/gpu/drm/nouveau/Kconfig
  62. 3 3
      drivers/gpu/drm/nouveau/Makefile
  63. 37 1
      drivers/gpu/drm/nouveau/nouveau_acpi.c
  64. 490 123
      drivers/gpu/drm/nouveau/nouveau_bios.c
  65. 2 2
      drivers/gpu/drm/nouveau/nouveau_bios.h
  66. 5 6
      drivers/gpu/drm/nouveau/nouveau_bo.c
  67. 2 2
      drivers/gpu/drm/nouveau/nouveau_calc.c
  68. 2 6
      drivers/gpu/drm/nouveau/nouveau_channel.c
  69. 181 223
      drivers/gpu/drm/nouveau/nouveau_connector.c
  70. 5 2
      drivers/gpu/drm/nouveau/nouveau_connector.h
  71. 3 5
      drivers/gpu/drm/nouveau/nouveau_dma.c
  72. 39 2
      drivers/gpu/drm/nouveau/nouveau_dp.c
  73. 18 23
      drivers/gpu/drm/nouveau/nouveau_drv.c
  74. 70 67
      drivers/gpu/drm/nouveau/nouveau_drv.h
  75. 6 4
      drivers/gpu/drm/nouveau/nouveau_encoder.h
  76. 1 1
      drivers/gpu/drm/nouveau/nouveau_fbcon.c
  77. 8 27
      drivers/gpu/drm/nouveau/nouveau_fence.c
  78. 1 10
      drivers/gpu/drm/nouveau/nouveau_gem.c
  79. 0 160
      drivers/gpu/drm/nouveau/nouveau_grctx.c
  80. 42 0
      drivers/gpu/drm/nouveau/nouveau_i2c.c
  81. 3 0
      drivers/gpu/drm/nouveau/nouveau_i2c.h
  82. 67 265
      drivers/gpu/drm/nouveau/nouveau_mem.c
  83. 12 18
      drivers/gpu/drm/nouveau/nouveau_notifier.c
  84. 31 74
      drivers/gpu/drm/nouveau/nouveau_object.c
  85. 60 31
      drivers/gpu/drm/nouveau/nouveau_reg.h
  86. 7 39
      drivers/gpu/drm/nouveau/nouveau_sgdma.c
  87. 137 118
      drivers/gpu/drm/nouveau/nouveau_state.c
  88. 10 10
      drivers/gpu/drm/nouveau/nouveau_ttm.c
  89. 5 0
      drivers/gpu/drm/nouveau/nv04_crtc.c
  90. 35 15
      drivers/gpu/drm/nouveau/nv04_dac.c
  91. 5 7
      drivers/gpu/drm/nouveau/nv04_dfp.c
  92. 53 37
      drivers/gpu/drm/nouveau/nv04_display.c
  93. 8 12
      drivers/gpu/drm/nouveau/nv04_fifo.c
  94. 2 3
      drivers/gpu/drm/nouveau/nv04_graph.c
  95. 7 14
      drivers/gpu/drm/nouveau/nv04_instmem.c
  96. 4 0
      drivers/gpu/drm/nouveau/nv04_mc.c
  97. 39 86
      drivers/gpu/drm/nouveau/nv04_tv.c
  98. 0 10
      drivers/gpu/drm/nouveau/nv10_fifo.c
  99. 2 2
      drivers/gpu/drm/nouveau/nv10_gpio.c
  100. 50 15
      drivers/gpu/drm/nouveau/nv17_tv.c

+ 11 - 11
drivers/char/agp/efficeon-agp.c

@@ -371,6 +371,17 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
 	bridge->dev = pdev;
 	bridge->dev = pdev;
 	bridge->capndx = cap_ptr;
 	bridge->capndx = cap_ptr;
 
 
+	/*
+	* If the device has not been properly setup, the following will catch
+	* the problem and should stop the system from crashing.
+	* 20030610 - hamish@zot.org
+	*/
+	if (pci_enable_device(pdev)) {
+		printk(KERN_ERR PFX "Unable to Enable PCI device\n");
+		agp_put_bridge(bridge);
+		return -ENODEV;
+	}
+
 	/*
 	/*
 	* The following fixes the case where the BIOS has "forgotten" to
 	* The following fixes the case where the BIOS has "forgotten" to
 	* provide an address range for the GART.
 	* provide an address range for the GART.
@@ -385,17 +396,6 @@ static int __devinit agp_efficeon_probe(struct pci_dev *pdev,
 		}
 		}
 	}
 	}
 
 
-	/*
-	* If the device has not been properly setup, the following will catch
-	* the problem and should stop the system from crashing.
-	* 20030610 - hamish@zot.org
-	*/
-	if (pci_enable_device(pdev)) {
-		printk(KERN_ERR PFX "Unable to Enable PCI device\n");
-		agp_put_bridge(bridge);
-		return -ENODEV;
-	}
-
 	/* Fill in the mode register */
 	/* Fill in the mode register */
 	if (cap_ptr) {
 	if (cap_ptr) {
 		pci_read_config_dword(pdev,
 		pci_read_config_dword(pdev,

+ 13 - 13
drivers/char/agp/intel-agp.c

@@ -816,9 +816,9 @@ static const struct intel_driver_description {
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
 	    "HD Graphics", NULL, &intel_i965_driver },
 	    "HD Graphics", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG,
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG,
-	    "Sandybridge", NULL, &intel_i965_driver },
+	    "Sandybridge", NULL, &intel_gen6_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG,
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG,
-	    "Sandybridge", NULL, &intel_i965_driver },
+	    "Sandybridge", NULL, &intel_gen6_driver },
 	{ 0, 0, NULL, NULL, NULL }
 	{ 0, 0, NULL, NULL, NULL }
 };
 };
 
 
@@ -907,6 +907,17 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
 
 
 	dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
 	dev_info(&pdev->dev, "Intel %s Chipset\n", intel_agp_chipsets[i].name);
 
 
+	/*
+	* If the device has not been properly setup, the following will catch
+	* the problem and should stop the system from crashing.
+	* 20030610 - hamish@zot.org
+	*/
+	if (pci_enable_device(pdev)) {
+		dev_err(&pdev->dev, "can't enable PCI device\n");
+		agp_put_bridge(bridge);
+		return -ENODEV;
+	}
+
 	/*
 	/*
 	* The following fixes the case where the BIOS has "forgotten" to
 	* The following fixes the case where the BIOS has "forgotten" to
 	* provide an address range for the GART.
 	* provide an address range for the GART.
@@ -921,17 +932,6 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
 		}
 		}
 	}
 	}
 
 
-	/*
-	* If the device has not been properly setup, the following will catch
-	* the problem and should stop the system from crashing.
-	* 20030610 - hamish@zot.org
-	*/
-	if (pci_enable_device(pdev)) {
-		dev_err(&pdev->dev, "can't enable PCI device\n");
-		agp_put_bridge(bridge);
-		return -ENODEV;
-	}
-
 	/* Fill in the mode register */
 	/* Fill in the mode register */
 	if (cap_ptr) {
 	if (cap_ptr) {
 		pci_read_config_dword(pdev,
 		pci_read_config_dword(pdev,

+ 6 - 0
drivers/char/agp/intel-agp.h

@@ -60,6 +60,12 @@
 #define I810_PTE_LOCAL		0x00000002
 #define I810_PTE_LOCAL		0x00000002
 #define I810_PTE_VALID		0x00000001
 #define I810_PTE_VALID		0x00000001
 #define I830_PTE_SYSTEM_CACHED  0x00000006
 #define I830_PTE_SYSTEM_CACHED  0x00000006
+/* GT PTE cache control fields */
+#define GEN6_PTE_UNCACHED	0x00000002
+#define GEN6_PTE_LLC		0x00000004
+#define GEN6_PTE_LLC_MLC	0x00000006
+#define GEN6_PTE_GFDT		0x00000008
+
 #define I810_SMRAM_MISCC	0x70
 #define I810_SMRAM_MISCC	0x70
 #define I810_GFX_MEM_WIN_SIZE	0x00010000
 #define I810_GFX_MEM_WIN_SIZE	0x00010000
 #define I810_GFX_MEM_WIN_32M	0x00010000
 #define I810_GFX_MEM_WIN_32M	0x00010000

+ 76 - 7
drivers/char/agp/intel-gtt.c

@@ -25,6 +25,10 @@
 #define USE_PCI_DMA_API 1
 #define USE_PCI_DMA_API 1
 #endif
 #endif
 
 
+/* Max amount of stolen space, anything above will be returned to Linux */
+int intel_max_stolen = 32 * 1024 * 1024;
+EXPORT_SYMBOL(intel_max_stolen);
+
 static const struct aper_size_info_fixed intel_i810_sizes[] =
 static const struct aper_size_info_fixed intel_i810_sizes[] =
 {
 {
 	{64, 16384, 4},
 	{64, 16384, 4},
@@ -104,7 +108,7 @@ static int intel_agp_map_memory(struct agp_memory *mem)
 	DBG("try mapping %lu pages\n", (unsigned long)mem->page_count);
 	DBG("try mapping %lu pages\n", (unsigned long)mem->page_count);
 
 
 	if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL))
 	if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL))
-		return -ENOMEM;
+		goto err;
 
 
 	mem->sg_list = sg = st.sgl;
 	mem->sg_list = sg = st.sgl;
 
 
@@ -113,11 +117,14 @@ static int intel_agp_map_memory(struct agp_memory *mem)
 
 
 	mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list,
 	mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list,
 				 mem->page_count, PCI_DMA_BIDIRECTIONAL);
 				 mem->page_count, PCI_DMA_BIDIRECTIONAL);
-	if (unlikely(!mem->num_sg)) {
-		intel_agp_free_sglist(mem);
-		return -ENOMEM;
-	}
+	if (unlikely(!mem->num_sg))
+		goto err;
+
 	return 0;
 	return 0;
+
+err:
+	sg_free_table(&st);
+	return -ENOMEM;
 }
 }
 
 
 static void intel_agp_unmap_memory(struct agp_memory *mem)
 static void intel_agp_unmap_memory(struct agp_memory *mem)
@@ -176,7 +183,7 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
 	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
 	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
 	    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
 	    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
 	{
 	{
-		cache_bits = I830_PTE_SYSTEM_CACHED;
+		cache_bits = GEN6_PTE_LLC_MLC;
 	}
 	}
 
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
@@ -710,7 +717,12 @@ static void intel_i830_init_gtt_entries(void)
 			break;
 			break;
 		}
 		}
 	}
 	}
-	if (gtt_entries > 0) {
+	if (!local && gtt_entries > intel_max_stolen) {
+		dev_info(&agp_bridge->dev->dev,
+			 "detected %dK stolen memory, trimming to %dK\n",
+			 gtt_entries / KB(1), intel_max_stolen / KB(1));
+		gtt_entries = intel_max_stolen / KB(4);
+	} else if (gtt_entries > 0) {
 		dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n",
 		dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n",
 		       gtt_entries / KB(1), local ? "local" : "stolen");
 		       gtt_entries / KB(1), local ? "local" : "stolen");
 		gtt_entries /= KB(4);
 		gtt_entries /= KB(4);
@@ -797,6 +809,10 @@ static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
 
 
 	/* we have to call this as early as possible after the MMIO base address is known */
 	/* we have to call this as early as possible after the MMIO base address is known */
 	intel_i830_init_gtt_entries();
 	intel_i830_init_gtt_entries();
+	if (intel_private.gtt_entries == 0) {
+		iounmap(intel_private.registers);
+		return -ENOMEM;
+	}
 
 
 	agp_bridge->gatt_table = NULL;
 	agp_bridge->gatt_table = NULL;
 
 
@@ -1282,6 +1298,11 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
 
 
 	/* we have to call this as early as possible after the MMIO base address is known */
 	/* we have to call this as early as possible after the MMIO base address is known */
 	intel_i830_init_gtt_entries();
 	intel_i830_init_gtt_entries();
+	if (intel_private.gtt_entries == 0) {
+		iounmap(intel_private.gtt);
+		iounmap(intel_private.registers);
+		return -ENOMEM;
+	}
 
 
 	agp_bridge->gatt_table = NULL;
 	agp_bridge->gatt_table = NULL;
 
 
@@ -1309,6 +1330,16 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
 	return addr | bridge->driver->masks[type].mask;
 	return addr | bridge->driver->masks[type].mask;
 }
 }
 
 
+static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge,
+					    dma_addr_t addr, int type)
+{
+	/* Shift high bits down */
+	addr |= (addr >> 28) & 0xff;
+
+	/* Type checking must be done elsewhere */
+	return addr | bridge->driver->masks[type].mask;
+}
+
 static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
 static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
 {
 {
 	u16 snb_gmch_ctl;
 	u16 snb_gmch_ctl;
@@ -1390,6 +1421,11 @@ static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
 
 
 	/* we have to call this as early as possible after the MMIO base address is known */
 	/* we have to call this as early as possible after the MMIO base address is known */
 	intel_i830_init_gtt_entries();
 	intel_i830_init_gtt_entries();
+	if (intel_private.gtt_entries == 0) {
+		iounmap(intel_private.gtt);
+		iounmap(intel_private.registers);
+		return -ENOMEM;
+	}
 
 
 	agp_bridge->gatt_table = NULL;
 	agp_bridge->gatt_table = NULL;
 
 
@@ -1517,6 +1553,39 @@ static const struct agp_bridge_driver intel_i965_driver = {
 #endif
 #endif
 };
 };
 
 
+static const struct agp_bridge_driver intel_gen6_driver = {
+	.owner			= THIS_MODULE,
+	.aperture_sizes		= intel_i830_sizes,
+	.size_type		= FIXED_APER_SIZE,
+	.num_aperture_sizes	= 4,
+	.needs_scratch_page	= true,
+	.configure		= intel_i9xx_configure,
+	.fetch_size		= intel_i9xx_fetch_size,
+	.cleanup		= intel_i915_cleanup,
+	.mask_memory		= intel_gen6_mask_memory,
+	.masks			= intel_i810_masks,
+	.agp_enable		= intel_i810_agp_enable,
+	.cache_flush		= global_cache_flush,
+	.create_gatt_table	= intel_i965_create_gatt_table,
+	.free_gatt_table	= intel_i830_free_gatt_table,
+	.insert_memory		= intel_i915_insert_entries,
+	.remove_memory		= intel_i915_remove_entries,
+	.alloc_by_type		= intel_i830_alloc_by_type,
+	.free_by_type		= intel_i810_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_alloc_pages        = agp_generic_alloc_pages,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.agp_destroy_pages      = agp_generic_destroy_pages,
+	.agp_type_to_mask_type	= intel_i830_type_to_mask_type,
+	.chipset_flush		= intel_i915_chipset_flush,
+#ifdef USE_PCI_DMA_API
+	.agp_map_page		= intel_agp_map_page,
+	.agp_unmap_page		= intel_agp_unmap_page,
+	.agp_map_memory		= intel_agp_map_memory,
+	.agp_unmap_memory	= intel_agp_unmap_memory,
+#endif
+};
+
 static const struct agp_bridge_driver intel_g33_driver = {
 static const struct agp_bridge_driver intel_g33_driver = {
 	.owner			= THIS_MODULE,
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= intel_i830_sizes,
 	.aperture_sizes		= intel_i830_sizes,

+ 6 - 5
drivers/gpu/drm/Kconfig

@@ -6,7 +6,7 @@
 #
 #
 menuconfig DRM
 menuconfig DRM
 	tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
 	tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
-	depends on (AGP || AGP=n) && PCI && !EMULATED_CMPXCHG && MMU
+	depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && MMU
 	select I2C
 	select I2C
 	select I2C_ALGOBIT
 	select I2C_ALGOBIT
 	select SLOW_WORK
 	select SLOW_WORK
@@ -17,7 +17,7 @@ menuconfig DRM
 	  These modules provide support for synchronization, security, and
 	  These modules provide support for synchronization, security, and
 	  DMA transfers. Please see <http://dri.sourceforge.net/> for more
 	  DMA transfers. Please see <http://dri.sourceforge.net/> for more
 	  details.  You should also select and configure AGP
 	  details.  You should also select and configure AGP
-	  (/dev/agpgart) support.
+	  (/dev/agpgart) support if it is available for your platform.
 
 
 config DRM_KMS_HELPER
 config DRM_KMS_HELPER
 	tristate
 	tristate
@@ -61,6 +61,7 @@ config DRM_RADEON
         select DRM_KMS_HELPER
         select DRM_KMS_HELPER
         select DRM_TTM
         select DRM_TTM
 	select POWER_SUPPLY
 	select POWER_SUPPLY
+	select HWMON
 	help
 	help
 	  Choose this option if you have an ATI Radeon graphics card.  There
 	  Choose this option if you have an ATI Radeon graphics card.  There
 	  are both PCI and AGP versions.  You don't need to choose this to
 	  are both PCI and AGP versions.  You don't need to choose this to
@@ -130,7 +131,7 @@ endchoice
 
 
 config DRM_MGA
 config DRM_MGA
 	tristate "Matrox g200/g400"
 	tristate "Matrox g200/g400"
-	depends on DRM
+	depends on DRM && PCI
 	select FW_LOADER
 	select FW_LOADER
 	help
 	help
 	  Choose this option if you have a Matrox G200, G400 or G450 graphics
 	  Choose this option if you have a Matrox G200, G400 or G450 graphics
@@ -148,14 +149,14 @@ config DRM_SIS
 
 
 config DRM_VIA
 config DRM_VIA
 	tristate "Via unichrome video cards"
 	tristate "Via unichrome video cards"
-	depends on DRM
+	depends on DRM && PCI
 	help
 	help
 	  Choose this option if you have a Via unichrome or compatible video
 	  Choose this option if you have a Via unichrome or compatible video
 	  chipset. If M is selected the module will be called via.
 	  chipset. If M is selected the module will be called via.
 
 
 config DRM_SAVAGE
 config DRM_SAVAGE
 	tristate "Savage video cards"
 	tristate "Savage video cards"
-	depends on DRM
+	depends on DRM && PCI
 	help
 	help
 	  Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
 	  Choose this option if you have a Savage3D/4/SuperSavage/Pro/Twister
 	  chipset. If M is selected the module will be called savage.
 	  chipset. If M is selected the module will be called savage.

+ 5 - 2
drivers/gpu/drm/Makefile

@@ -9,9 +9,10 @@ drm-y       :=	drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
 		drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
 		drm_drv.o drm_fops.o drm_gem.o drm_ioctl.o drm_irq.o \
 		drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
 		drm_lock.o drm_memory.o drm_proc.o drm_stub.o drm_vm.o \
 		drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
 		drm_agpsupport.o drm_scatter.o ati_pcigart.o drm_pci.o \
-		drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
+		drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
-		drm_info.o drm_debugfs.o drm_encoder_slave.o
+		drm_info.o drm_debugfs.o drm_encoder_slave.o \
+		drm_trace_points.o drm_global.o
 
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 
 
@@ -19,6 +20,8 @@ drm_kms_helper-y := drm_fb_helper.o drm_crtc_helper.o drm_dp_i2c_helper.o
 
 
 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
 obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
 
 
+CFLAGS_drm_trace_points.o := -I$(src)
+
 obj-$(CONFIG_DRM)	+= drm.o
 obj-$(CONFIG_DRM)	+= drm.o
 obj-$(CONFIG_DRM_TTM)	+= ttm/
 obj-$(CONFIG_DRM_TTM)	+= ttm/
 obj-$(CONFIG_DRM_TDFX)	+= tdfx/
 obj-$(CONFIG_DRM_TDFX)	+= tdfx/

+ 1 - 14
drivers/gpu/drm/drm_bufs.c

@@ -39,19 +39,6 @@
 #include <asm/shmparam.h>
 #include <asm/shmparam.h>
 #include "drmP.h"
 #include "drmP.h"
 
 
-resource_size_t drm_get_resource_start(struct drm_device *dev, unsigned int resource)
-{
-	return pci_resource_start(dev->pdev, resource);
-}
-EXPORT_SYMBOL(drm_get_resource_start);
-
-resource_size_t drm_get_resource_len(struct drm_device *dev, unsigned int resource)
-{
-	return pci_resource_len(dev->pdev, resource);
-}
-
-EXPORT_SYMBOL(drm_get_resource_len);
-
 static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
 static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
 						  struct drm_local_map *map)
 						  struct drm_local_map *map)
 {
 {
@@ -189,7 +176,7 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
 	switch (map->type) {
 	switch (map->type) {
 	case _DRM_REGISTERS:
 	case _DRM_REGISTERS:
 	case _DRM_FRAME_BUFFER:
 	case _DRM_FRAME_BUFFER:
-#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__)
+#if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__arm__)
 		if (map->offset + (map->size-1) < map->offset ||
 		if (map->offset + (map->size-1) < map->offset ||
 		    map->offset < virt_to_phys(high_memory)) {
 		    map->offset < virt_to_phys(high_memory)) {
 			kfree(map);
 			kfree(map);

+ 23 - 7
drivers/gpu/drm/drm_crtc.c

@@ -80,6 +80,7 @@ static struct drm_prop_enum_list drm_dithering_mode_enum_list[] =
 {
 {
 	{ DRM_MODE_DITHERING_OFF, "Off" },
 	{ DRM_MODE_DITHERING_OFF, "Off" },
 	{ DRM_MODE_DITHERING_ON, "On" },
 	{ DRM_MODE_DITHERING_ON, "On" },
+	{ DRM_MODE_DITHERING_AUTO, "Automatic" },
 };
 };
 
 
 /*
 /*
@@ -1126,7 +1127,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
 		if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
 		if (file_priv->master->minor->type == DRM_MINOR_CONTROL) {
 			list_for_each_entry(crtc, &dev->mode_config.crtc_list,
 			list_for_each_entry(crtc, &dev->mode_config.crtc_list,
 					    head) {
 					    head) {
-				DRM_DEBUG_KMS("CRTC ID is %d\n", crtc->base.id);
+				DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 				if (put_user(crtc->base.id, crtc_id + copied)) {
 				if (put_user(crtc->base.id, crtc_id + copied)) {
 					ret = -EFAULT;
 					ret = -EFAULT;
 					goto out;
 					goto out;
@@ -1154,8 +1155,8 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
 			list_for_each_entry(encoder,
 			list_for_each_entry(encoder,
 					    &dev->mode_config.encoder_list,
 					    &dev->mode_config.encoder_list,
 					    head) {
 					    head) {
-				DRM_DEBUG_KMS("ENCODER ID is %d\n",
-					  encoder->base.id);
+				DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
+						drm_get_encoder_name(encoder));
 				if (put_user(encoder->base.id, encoder_id +
 				if (put_user(encoder->base.id, encoder_id +
 					     copied)) {
 					     copied)) {
 					ret = -EFAULT;
 					ret = -EFAULT;
@@ -1185,8 +1186,9 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
 			list_for_each_entry(connector,
 			list_for_each_entry(connector,
 					    &dev->mode_config.connector_list,
 					    &dev->mode_config.connector_list,
 					    head) {
 					    head) {
-				DRM_DEBUG_KMS("CONNECTOR ID is %d\n",
-					  connector->base.id);
+				DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+					connector->base.id,
+					drm_get_connector_name(connector));
 				if (put_user(connector->base.id,
 				if (put_user(connector->base.id,
 					     connector_id + copied)) {
 					     connector_id + copied)) {
 					ret = -EFAULT;
 					ret = -EFAULT;
@@ -1209,7 +1211,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
 	}
 	}
 	card_res->count_connectors = connector_count;
 	card_res->count_connectors = connector_count;
 
 
-	DRM_DEBUG_KMS("Counted %d %d %d\n", card_res->count_crtcs,
+	DRM_DEBUG_KMS("CRTC[%d] CONNECTORS[%d] ENCODERS[%d]\n", card_res->count_crtcs,
 		  card_res->count_connectors, card_res->count_encoders);
 		  card_res->count_connectors, card_res->count_encoders);
 
 
 out:
 out:
@@ -1312,7 +1314,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
 
 
 	memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
 	memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
 
 
-	DRM_DEBUG_KMS("connector id %d:\n", out_resp->connector_id);
+	DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
 
 
 	mutex_lock(&dev->mode_config.mutex);
 	mutex_lock(&dev->mode_config.mutex);
 
 
@@ -1493,6 +1495,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
 		goto out;
 		goto out;
 	}
 	}
 	crtc = obj_to_crtc(obj);
 	crtc = obj_to_crtc(obj);
+	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
 
 	if (crtc_req->mode_valid) {
 	if (crtc_req->mode_valid) {
 		/* If we have a mode we need a framebuffer. */
 		/* If we have a mode we need a framebuffer. */
@@ -1569,6 +1572,9 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
 				goto out;
 				goto out;
 			}
 			}
 			connector = obj_to_connector(obj);
 			connector = obj_to_connector(obj);
+			DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
+					connector->base.id,
+					drm_get_connector_name(connector));
 
 
 			connector_set[i] = connector;
 			connector_set[i] = connector;
 		}
 		}
@@ -1684,6 +1690,7 @@ int drm_mode_addfb(struct drm_device *dev,
 
 
 	r->fb_id = fb->base.id;
 	r->fb_id = fb->base.id;
 	list_add(&fb->filp_head, &file_priv->fbs);
 	list_add(&fb->filp_head, &file_priv->fbs);
+	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
 
 
 out:
 out:
 	mutex_unlock(&dev->mode_config.mutex);
 	mutex_unlock(&dev->mode_config.mutex);
@@ -2610,6 +2617,15 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
 		goto out;
 		goto out;
 	crtc = obj_to_crtc(obj);
 	crtc = obj_to_crtc(obj);
 
 
+	if (crtc->fb == NULL) {
+		/* The framebuffer is currently unbound, presumably
+		 * due to a hotplug event, that userspace has not
+		 * yet discovered.
+		 */
+		ret = -EBUSY;
+		goto out;
+	}
+
 	if (crtc->funcs->page_flip == NULL)
 	if (crtc->funcs->page_flip == NULL)
 		goto out;
 		goto out;
 
 

+ 47 - 24
drivers/gpu/drm/drm_crtc_helper.c

@@ -86,7 +86,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 	int count = 0;
 	int count = 0;
 	int mode_flags = 0;
 	int mode_flags = 0;
 
 
-	DRM_DEBUG_KMS("%s\n", drm_get_connector_name(connector));
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id,
+			drm_get_connector_name(connector));
 	/* set all modes to the unverified state */
 	/* set all modes to the unverified state */
 	list_for_each_entry_safe(mode, t, &connector->modes, head)
 	list_for_each_entry_safe(mode, t, &connector->modes, head)
 		mode->status = MODE_UNVERIFIED;
 		mode->status = MODE_UNVERIFIED;
@@ -102,8 +103,8 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
 		connector->status = connector->funcs->detect(connector);
 		connector->status = connector->funcs->detect(connector);
 
 
 	if (connector->status == connector_status_disconnected) {
 	if (connector->status == connector_status_disconnected) {
-		DRM_DEBUG_KMS("%s is disconnected\n",
-			  drm_get_connector_name(connector));
+		DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n",
+			connector->base.id, drm_get_connector_name(connector));
 		drm_mode_connector_update_edid_property(connector, NULL);
 		drm_mode_connector_update_edid_property(connector, NULL);
 		goto prune;
 		goto prune;
 	}
 	}
@@ -141,8 +142,8 @@ prune:
 
 
 	drm_mode_sort(&connector->modes);
 	drm_mode_sort(&connector->modes);
 
 
-	DRM_DEBUG_KMS("Probed modes for %s\n",
-				drm_get_connector_name(connector));
+	DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id,
+			drm_get_connector_name(connector));
 	list_for_each_entry_safe(mode, t, &connector->modes, head) {
 	list_for_each_entry_safe(mode, t, &connector->modes, head) {
 		mode->vrefresh = drm_mode_vrefresh(mode);
 		mode->vrefresh = drm_mode_vrefresh(mode);
 
 
@@ -201,6 +202,17 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
 }
 }
 EXPORT_SYMBOL(drm_helper_crtc_in_use);
 EXPORT_SYMBOL(drm_helper_crtc_in_use);
 
 
+static void
+drm_encoder_disable(struct drm_encoder *encoder)
+{
+	struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private;
+
+	if (encoder_funcs->disable)
+		(*encoder_funcs->disable)(encoder);
+	else
+		(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+}
+
 /**
 /**
  * drm_helper_disable_unused_functions - disable unused objects
  * drm_helper_disable_unused_functions - disable unused objects
  * @dev: DRM device
  * @dev: DRM device
@@ -215,7 +227,6 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
 {
 {
 	struct drm_encoder *encoder;
 	struct drm_encoder *encoder;
 	struct drm_connector *connector;
 	struct drm_connector *connector;
-	struct drm_encoder_helper_funcs *encoder_funcs;
 	struct drm_crtc *crtc;
 	struct drm_crtc *crtc;
 
 
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
@@ -226,12 +237,8 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
 	}
 	}
 
 
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		encoder_funcs = encoder->helper_private;
 		if (!drm_helper_encoder_in_use(encoder)) {
 		if (!drm_helper_encoder_in_use(encoder)) {
-			if (encoder_funcs->disable)
-				(*encoder_funcs->disable)(encoder);
-			else
-				(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+			drm_encoder_disable(encoder);
 			/* disconnector encoder from any connector */
 			/* disconnector encoder from any connector */
 			encoder->crtc = NULL;
 			encoder->crtc = NULL;
 		}
 		}
@@ -241,7 +248,10 @@ void drm_helper_disable_unused_functions(struct drm_device *dev)
 		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 		struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
 		crtc->enabled = drm_helper_crtc_in_use(crtc);
 		crtc->enabled = drm_helper_crtc_in_use(crtc);
 		if (!crtc->enabled) {
 		if (!crtc->enabled) {
-			crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
+			if (crtc_funcs->disable)
+				(*crtc_funcs->disable)(crtc);
+			else
+				(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
 			crtc->fb = NULL;
 			crtc->fb = NULL;
 		}
 		}
 	}
 	}
@@ -292,11 +302,11 @@ drm_crtc_prepare_encoders(struct drm_device *dev)
 		encoder_funcs = encoder->helper_private;
 		encoder_funcs = encoder->helper_private;
 		/* Disable unused encoders */
 		/* Disable unused encoders */
 		if (encoder->crtc == NULL)
 		if (encoder->crtc == NULL)
-			(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+			drm_encoder_disable(encoder);
 		/* Disable encoders whose CRTC is about to change */
 		/* Disable encoders whose CRTC is about to change */
 		if (encoder_funcs->get_crtc &&
 		if (encoder_funcs->get_crtc &&
 		    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
 		    encoder->crtc != (*encoder_funcs->get_crtc)(encoder))
-			(*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF);
+			drm_encoder_disable(encoder);
 	}
 	}
 }
 }
 
 
@@ -365,6 +375,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
 	if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) {
 		goto done;
 		goto done;
 	}
 	}
+	DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
 
 
 	/* Prepare the encoders and CRTCs before setting the mode. */
 	/* Prepare the encoders and CRTCs before setting the mode. */
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
@@ -392,8 +403,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 		if (encoder->crtc != crtc)
 		if (encoder->crtc != crtc)
 			continue;
 			continue;
 
 
-		DRM_DEBUG("%s: set mode %s %x\n", drm_get_encoder_name(encoder),
-			 mode->name, mode->base.id);
+		DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n",
+			encoder->base.id, drm_get_encoder_name(encoder),
+			mode->base.id, mode->name);
 		encoder_funcs = encoder->helper_private;
 		encoder_funcs = encoder->helper_private;
 		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 		encoder_funcs->mode_set(encoder, mode, adjusted_mode);
 	}
 	}
@@ -469,10 +481,15 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 
 
 	crtc_funcs = set->crtc->helper_private;
 	crtc_funcs = set->crtc->helper_private;
 
 
-	DRM_DEBUG_KMS("crtc: %p %d fb: %p connectors: %p num_connectors:"
-			" %d (x, y) (%i, %i)\n",
-		  set->crtc, set->crtc->base.id, set->fb, set->connectors,
-		  (int)set->num_connectors, set->x, set->y);
+	if (set->fb) {
+		DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n",
+				set->crtc->base.id, set->fb->base.id,
+				(int)set->num_connectors, set->x, set->y);
+	} else {
+		DRM_DEBUG_KMS("[CRTC:%d] [NOFB] #connectors=%d (x y) (%i %i)\n",
+				set->crtc->base.id, (int)set->num_connectors,
+				set->x, set->y);
+	}
 
 
 	dev = set->crtc->dev;
 	dev = set->crtc->dev;
 
 
@@ -601,8 +618,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 			mode_changed = true;
 			mode_changed = true;
 			connector->encoder->crtc = new_crtc;
 			connector->encoder->crtc = new_crtc;
 		}
 		}
-		DRM_DEBUG_KMS("setting connector %d crtc to %p\n",
-			  connector->base.id, new_crtc);
+		if (new_crtc) {
+			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n",
+				connector->base.id, drm_get_connector_name(connector),
+				new_crtc->base.id);
+		} else {
+			DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n",
+				connector->base.id, drm_get_connector_name(connector));
+		}
 	}
 	}
 
 
 	/* mode_set_base is not a required function */
 	/* mode_set_base is not a required function */
@@ -620,8 +643,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
 			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
 			if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
 						      set->x, set->y,
 						      set->x, set->y,
 						      old_fb)) {
 						      old_fb)) {
-				DRM_ERROR("failed to set mode on crtc %p\n",
-					  set->crtc);
+				DRM_ERROR("failed to set mode on [CRTC:%d]\n",
+					  set->crtc->base.id);
 				ret = -EINVAL;
 				ret = -EINVAL;
 				goto fail;
 				goto fail;
 			}
 			}

+ 9 - 34
drivers/gpu/drm/drm_drv.c

@@ -243,47 +243,20 @@ int drm_lastclose(struct drm_device * dev)
  *
  *
  * Initializes an array of drm_device structures, and attempts to
  * Initializes an array of drm_device structures, and attempts to
  * initialize all available devices, using consecutive minors, registering the
  * initialize all available devices, using consecutive minors, registering the
- * stubs and initializing the AGP device.
+ * stubs and initializing the device.
  *
  *
  * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
  * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
  * after the initialization for driver customization.
  * after the initialization for driver customization.
  */
  */
 int drm_init(struct drm_driver *driver)
 int drm_init(struct drm_driver *driver)
 {
 {
-	struct pci_dev *pdev = NULL;
-	const struct pci_device_id *pid;
-	int i;
-
 	DRM_DEBUG("\n");
 	DRM_DEBUG("\n");
-
 	INIT_LIST_HEAD(&driver->device_list);
 	INIT_LIST_HEAD(&driver->device_list);
 
 
-	if (driver->driver_features & DRIVER_MODESET)
-		return pci_register_driver(&driver->pci_driver);
-
-	/* If not using KMS, fall back to stealth mode manual scanning. */
-	for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
-		pid = &driver->pci_driver.id_table[i];
-
-		/* Loop around setting up a DRM device for each PCI device
-		 * matching our ID and device class.  If we had the internal
-		 * function that pci_get_subsys and pci_get_class used, we'd
-		 * be able to just pass pid in instead of doing a two-stage
-		 * thing.
-		 */
-		pdev = NULL;
-		while ((pdev =
-			pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
-				       pid->subdevice, pdev)) != NULL) {
-			if ((pdev->class & pid->class_mask) != pid->class)
-				continue;
-
-			/* stealth mode requires a manual probe */
-			pci_dev_get(pdev);
-			drm_get_dev(pdev, pid, driver);
-		}
-	}
-	return 0;
+	if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE)
+		return drm_platform_init(driver);
+	else
+		return drm_pci_init(driver);
 }
 }
 
 
 EXPORT_SYMBOL(drm_init);
 EXPORT_SYMBOL(drm_init);
@@ -315,6 +288,7 @@ static int __init drm_core_init(void)
 {
 {
 	int ret = -ENOMEM;
 	int ret = -ENOMEM;
 
 
+	drm_global_init();
 	idr_init(&drm_minors_idr);
 	idr_init(&drm_minors_idr);
 
 
 	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
 	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
@@ -362,6 +336,7 @@ static void __exit drm_core_exit(void)
 
 
 	unregister_chrdev(DRM_MAJOR, "drm");
 	unregister_chrdev(DRM_MAJOR, "drm");
 
 
+	idr_remove_all(&drm_minors_idr);
 	idr_destroy(&drm_minors_idr);
 	idr_destroy(&drm_minors_idr);
 }
 }
 
 
@@ -506,9 +481,9 @@ long drm_ioctl(struct file *filp,
 		if (ioctl->flags & DRM_UNLOCKED)
 		if (ioctl->flags & DRM_UNLOCKED)
 			retcode = func(dev, kdata, file_priv);
 			retcode = func(dev, kdata, file_priv);
 		else {
 		else {
-			lock_kernel();
+			mutex_lock(&drm_global_mutex);
 			retcode = func(dev, kdata, file_priv);
 			retcode = func(dev, kdata, file_priv);
-			unlock_kernel();
+			mutex_unlock(&drm_global_mutex);
 		}
 		}
 
 
 		if (cmd & IOC_OUT) {
 		if (cmd & IOC_OUT) {

+ 2 - 2
drivers/gpu/drm/drm_edid.c

@@ -282,7 +282,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 	return block;
 	return block;
 
 
 carp:
 carp:
-	dev_warn(&connector->dev->pdev->dev, "%s: EDID block %d invalid.\n",
+	dev_warn(connector->dev->dev, "%s: EDID block %d invalid.\n",
 		 drm_get_connector_name(connector), j);
 		 drm_get_connector_name(connector), j);
 
 
 out:
 out:
@@ -1623,7 +1623,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
 		return 0;
 		return 0;
 	}
 	}
 	if (!drm_edid_is_valid(edid)) {
 	if (!drm_edid_is_valid(edid)) {
-		dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
+		dev_warn(connector->dev->dev, "%s: EDID invalid.\n",
 			 drm_get_connector_name(connector));
 			 drm_get_connector_name(connector));
 		return 0;
 		return 0;
 	}
 	}

+ 7 - 0
drivers/gpu/drm/drm_encoder_slave.c

@@ -41,6 +41,9 @@
  * &drm_encoder_slave. The @slave_funcs field will be initialized with
  * &drm_encoder_slave. The @slave_funcs field will be initialized with
  * the hooks provided by the slave driver.
  * the hooks provided by the slave driver.
  *
  *
+ * If @info->platform_data is non-NULL it will be used as the initial
+ * slave config.
+ *
  * Returns 0 on success or a negative errno on failure, in particular,
  * Returns 0 on success or a negative errno on failure, in particular,
  * -ENODEV is returned when no matching driver is found.
  * -ENODEV is returned when no matching driver is found.
  */
  */
@@ -85,6 +88,10 @@ int drm_i2c_encoder_init(struct drm_device *dev,
 	if (err)
 	if (err)
 		goto fail_unregister;
 		goto fail_unregister;
 
 
+	if (info->platform_data)
+		encoder->slave_funcs->set_config(&encoder->base,
+						 info->platform_data);
+
 	return 0;
 	return 0;
 
 
 fail_unregister:
 fail_unregister:

+ 11 - 12
drivers/gpu/drm/drm_fops.c

@@ -39,6 +39,9 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/smp_lock.h>
 
 
+/* from BKL pushdown: note that nothing else serializes idr_find() */
+DEFINE_MUTEX(drm_global_mutex);
+
 static int drm_open_helper(struct inode *inode, struct file *filp,
 static int drm_open_helper(struct inode *inode, struct file *filp,
 			   struct drm_device * dev);
 			   struct drm_device * dev);
 
 
@@ -175,8 +178,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
 
 
 	DRM_DEBUG("\n");
 	DRM_DEBUG("\n");
 
 
-	/* BKL pushdown: note that nothing else serializes idr_find() */
-	lock_kernel();
+	mutex_lock(&drm_global_mutex);
 	minor = idr_find(&drm_minors_idr, minor_id);
 	minor = idr_find(&drm_minors_idr, minor_id);
 	if (!minor)
 	if (!minor)
 		goto out;
 		goto out;
@@ -197,7 +199,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
 	fops_put(old_fops);
 	fops_put(old_fops);
 
 
 out:
 out:
-	unlock_kernel();
+	mutex_unlock(&drm_global_mutex);
 	return err;
 	return err;
 }
 }
 
 
@@ -472,7 +474,7 @@ int drm_release(struct inode *inode, struct file *filp)
 	struct drm_device *dev = file_priv->minor->dev;
 	struct drm_device *dev = file_priv->minor->dev;
 	int retcode = 0;
 	int retcode = 0;
 
 
-	lock_kernel();
+	mutex_lock(&drm_global_mutex);
 
 
 	DRM_DEBUG("open_count = %d\n", dev->open_count);
 	DRM_DEBUG("open_count = %d\n", dev->open_count);
 
 
@@ -573,17 +575,14 @@ int drm_release(struct inode *inode, struct file *filp)
 		if (atomic_read(&dev->ioctl_count)) {
 		if (atomic_read(&dev->ioctl_count)) {
 			DRM_ERROR("Device busy: %d\n",
 			DRM_ERROR("Device busy: %d\n",
 				  atomic_read(&dev->ioctl_count));
 				  atomic_read(&dev->ioctl_count));
-			spin_unlock(&dev->count_lock);
-			unlock_kernel();
-			return -EBUSY;
+			retcode = -EBUSY;
+			goto out;
 		}
 		}
-		spin_unlock(&dev->count_lock);
-		unlock_kernel();
-		return drm_lastclose(dev);
+		retcode = drm_lastclose(dev);
 	}
 	}
+out:
 	spin_unlock(&dev->count_lock);
 	spin_unlock(&dev->count_lock);
-
-	unlock_kernel();
+	mutex_unlock(&drm_global_mutex);
 
 
 	return retcode;
 	return retcode;
 }
 }

+ 11 - 0
drivers/gpu/drm/drm_gem.c

@@ -68,8 +68,18 @@
  * We make up offsets for buffer objects so we can recognize them at
  * We make up offsets for buffer objects so we can recognize them at
  * mmap time.
  * mmap time.
  */
  */
+
+/* pgoff in mmap is an unsigned long, so we need to make sure that
+ * the faked up offset will fit
+ */
+
+#if BITS_PER_LONG == 64
 #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1)
 #define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFFUL >> PAGE_SHIFT) + 1)
 #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16)
 #define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFFUL >> PAGE_SHIFT) * 16)
+#else
+#define DRM_FILE_PAGE_OFFSET_START ((0xFFFFFFFUL >> PAGE_SHIFT) + 1)
+#define DRM_FILE_PAGE_OFFSET_SIZE ((0xFFFFFFFUL >> PAGE_SHIFT) * 16)
+#endif
 
 
 /**
 /**
  * Initialize the GEM device fields
  * Initialize the GEM device fields
@@ -419,6 +429,7 @@ drm_gem_release(struct drm_device *dev, struct drm_file *file_private)
 	idr_for_each(&file_private->object_idr,
 	idr_for_each(&file_private->object_idr,
 		     &drm_gem_object_release_handle, NULL);
 		     &drm_gem_object_release_handle, NULL);
 
 
+	idr_remove_all(&file_private->object_idr);
 	idr_destroy(&file_private->object_idr);
 	idr_destroy(&file_private->object_idr);
 }
 }
 
 

+ 15 - 15
drivers/gpu/drm/ttm/ttm_global.c → drivers/gpu/drm/drm_global.c

@@ -28,45 +28,45 @@
  * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
  * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
  */
  */
 
 
-#include "ttm/ttm_module.h"
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include "drm_global.h"
 
 
-struct ttm_global_item {
+struct drm_global_item {
 	struct mutex mutex;
 	struct mutex mutex;
 	void *object;
 	void *object;
 	int refcount;
 	int refcount;
 };
 };
 
 
-static struct ttm_global_item glob[TTM_GLOBAL_NUM];
+static struct drm_global_item glob[DRM_GLOBAL_NUM];
 
 
-void ttm_global_init(void)
+void drm_global_init(void)
 {
 {
 	int i;
 	int i;
 
 
-	for (i = 0; i < TTM_GLOBAL_NUM; ++i) {
-		struct ttm_global_item *item = &glob[i];
+	for (i = 0; i < DRM_GLOBAL_NUM; ++i) {
+		struct drm_global_item *item = &glob[i];
 		mutex_init(&item->mutex);
 		mutex_init(&item->mutex);
 		item->object = NULL;
 		item->object = NULL;
 		item->refcount = 0;
 		item->refcount = 0;
 	}
 	}
 }
 }
 
 
-void ttm_global_release(void)
+void drm_global_release(void)
 {
 {
 	int i;
 	int i;
-	for (i = 0; i < TTM_GLOBAL_NUM; ++i) {
-		struct ttm_global_item *item = &glob[i];
+	for (i = 0; i < DRM_GLOBAL_NUM; ++i) {
+		struct drm_global_item *item = &glob[i];
 		BUG_ON(item->object != NULL);
 		BUG_ON(item->object != NULL);
 		BUG_ON(item->refcount != 0);
 		BUG_ON(item->refcount != 0);
 	}
 	}
 }
 }
 
 
-int ttm_global_item_ref(struct ttm_global_reference *ref)
+int drm_global_item_ref(struct drm_global_reference *ref)
 {
 {
 	int ret;
 	int ret;
-	struct ttm_global_item *item = &glob[ref->global_type];
+	struct drm_global_item *item = &glob[ref->global_type];
 	void *object;
 	void *object;
 
 
 	mutex_lock(&item->mutex);
 	mutex_lock(&item->mutex);
@@ -93,11 +93,11 @@ out_err:
 	item->object = NULL;
 	item->object = NULL;
 	return ret;
 	return ret;
 }
 }
-EXPORT_SYMBOL(ttm_global_item_ref);
+EXPORT_SYMBOL(drm_global_item_ref);
 
 
-void ttm_global_item_unref(struct ttm_global_reference *ref)
+void drm_global_item_unref(struct drm_global_reference *ref)
 {
 {
-	struct ttm_global_item *item = &glob[ref->global_type];
+	struct drm_global_item *item = &glob[ref->global_type];
 
 
 	mutex_lock(&item->mutex);
 	mutex_lock(&item->mutex);
 	BUG_ON(item->refcount == 0);
 	BUG_ON(item->refcount == 0);
@@ -108,5 +108,5 @@ void ttm_global_item_unref(struct ttm_global_reference *ref)
 	}
 	}
 	mutex_unlock(&item->mutex);
 	mutex_unlock(&item->mutex);
 }
 }
-EXPORT_SYMBOL(ttm_global_item_unref);
+EXPORT_SYMBOL(drm_global_item_unref);
 
 

+ 17 - 6
drivers/gpu/drm/drm_info.c

@@ -51,13 +51,24 @@ int drm_name_info(struct seq_file *m, void *data)
 	if (!master)
 	if (!master)
 		return 0;
 		return 0;
 
 
-	if (master->unique) {
-		seq_printf(m, "%s %s %s\n",
-			   dev->driver->pci_driver.name,
-			   pci_name(dev->pdev), master->unique);
+	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
+		if (master->unique) {
+			seq_printf(m, "%s %s %s\n",
+					dev->driver->platform_device->name,
+					dev_name(dev->dev), master->unique);
+		} else {
+			seq_printf(m, "%s\n",
+				dev->driver->platform_device->name);
+		}
 	} else {
 	} else {
-		seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
-			   pci_name(dev->pdev));
+		if (master->unique) {
+			seq_printf(m, "%s %s %s\n",
+				dev->driver->pci_driver.name,
+				dev_name(dev->dev), master->unique);
+		} else {
+			seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
+				dev_name(dev->dev));
+		}
 	}
 	}
 
 
 	return 0;
 	return 0;

+ 106 - 34
drivers/gpu/drm/drm_ioctl.c

@@ -64,6 +64,19 @@ int drm_getunique(struct drm_device *dev, void *data,
 	return 0;
 	return 0;
 }
 }
 
 
+static void
+drm_unset_busid(struct drm_device *dev,
+		struct drm_master *master)
+{
+	kfree(dev->devname);
+	dev->devname = NULL;
+
+	kfree(master->unique);
+	master->unique = NULL;
+	master->unique_len = 0;
+	master->unique_size = 0;
+}
+
 /**
 /**
  * Set the bus id.
  * Set the bus id.
  *
  *
@@ -94,17 +107,24 @@ int drm_setunique(struct drm_device *dev, void *data,
 	master->unique_len = u->unique_len;
 	master->unique_len = u->unique_len;
 	master->unique_size = u->unique_len + 1;
 	master->unique_size = u->unique_len + 1;
 	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
 	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
-	if (!master->unique)
-		return -ENOMEM;
-	if (copy_from_user(master->unique, u->unique, master->unique_len))
-		return -EFAULT;
+	if (!master->unique) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (copy_from_user(master->unique, u->unique, master->unique_len)) {
+		ret = -EFAULT;
+		goto err;
+	}
 
 
 	master->unique[master->unique_len] = '\0';
 	master->unique[master->unique_len] = '\0';
 
 
 	dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
 	dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
 			       strlen(master->unique) + 2, GFP_KERNEL);
 			       strlen(master->unique) + 2, GFP_KERNEL);
-	if (!dev->devname)
-		return -ENOMEM;
+	if (!dev->devname) {
+		ret = -ENOMEM;
+		goto err;
+	}
 
 
 	sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
 	sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
 		master->unique);
 		master->unique);
@@ -113,53 +133,103 @@ int drm_setunique(struct drm_device *dev, void *data,
 	 * busid.
 	 * busid.
 	 */
 	 */
 	ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
 	ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
-	if (ret != 3)
-		return -EINVAL;
+	if (ret != 3) {
+		ret = -EINVAL;
+		goto err;
+	}
+
 	domain = bus >> 8;
 	domain = bus >> 8;
 	bus &= 0xff;
 	bus &= 0xff;
 
 
 	if ((domain != drm_get_pci_domain(dev)) ||
 	if ((domain != drm_get_pci_domain(dev)) ||
 	    (bus != dev->pdev->bus->number) ||
 	    (bus != dev->pdev->bus->number) ||
 	    (slot != PCI_SLOT(dev->pdev->devfn)) ||
 	    (slot != PCI_SLOT(dev->pdev->devfn)) ||
-	    (func != PCI_FUNC(dev->pdev->devfn)))
-		return -EINVAL;
+	    (func != PCI_FUNC(dev->pdev->devfn))) {
+		ret = -EINVAL;
+		goto err;
+	}
 
 
 	return 0;
 	return 0;
+
+err:
+	drm_unset_busid(dev, master);
+	return ret;
 }
 }
 
 
 static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
 static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
 {
 {
 	struct drm_master *master = file_priv->master;
 	struct drm_master *master = file_priv->master;
-	int len;
+	int len, ret;
 
 
 	if (master->unique != NULL)
 	if (master->unique != NULL)
-		return -EBUSY;
+		drm_unset_busid(dev, master);
 
 
-	master->unique_len = 40;
-	master->unique_size = master->unique_len;
-	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
-	if (master->unique == NULL)
-		return -ENOMEM;
-
-	len = snprintf(master->unique, master->unique_len, "pci:%04x:%02x:%02x.%d",
-		       drm_get_pci_domain(dev),
-		       dev->pdev->bus->number,
-		       PCI_SLOT(dev->pdev->devfn),
-		       PCI_FUNC(dev->pdev->devfn));
-	if (len >= master->unique_len)
-		DRM_ERROR("buffer overflow");
-	else
-		master->unique_len = len;
+	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
+		master->unique_len = 10 + strlen(dev->platformdev->name);
+		master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
 
 
-	dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
-			       master->unique_len + 2, GFP_KERNEL);
-	if (dev->devname == NULL)
-		return -ENOMEM;
+		if (master->unique == NULL)
+			return -ENOMEM;
 
 
-	sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
-		master->unique);
+		len = snprintf(master->unique, master->unique_len,
+			"platform:%s", dev->platformdev->name);
+
+		if (len > master->unique_len) {
+			DRM_ERROR("Unique buffer overflowed\n");
+			ret = -EINVAL;
+			goto err;
+		}
+
+		dev->devname =
+			kmalloc(strlen(dev->platformdev->name) +
+				master->unique_len + 2, GFP_KERNEL);
+
+		if (dev->devname == NULL) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		sprintf(dev->devname, "%s@%s", dev->platformdev->name,
+			master->unique);
+
+	} else {
+		master->unique_len = 40;
+		master->unique_size = master->unique_len;
+		master->unique = kmalloc(master->unique_size, GFP_KERNEL);
+		if (master->unique == NULL)
+			return -ENOMEM;
+
+		len = snprintf(master->unique, master->unique_len,
+			"pci:%04x:%02x:%02x.%d",
+			drm_get_pci_domain(dev),
+			dev->pdev->bus->number,
+			PCI_SLOT(dev->pdev->devfn),
+			PCI_FUNC(dev->pdev->devfn));
+		if (len >= master->unique_len) {
+			DRM_ERROR("buffer overflow");
+			ret = -EINVAL;
+			goto err;
+		} else
+			master->unique_len = len;
+
+		dev->devname =
+			kmalloc(strlen(dev->driver->pci_driver.name) +
+				master->unique_len + 2, GFP_KERNEL);
+
+		if (dev->devname == NULL) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
+			master->unique);
+	}
 
 
 	return 0;
 	return 0;
+
+err:
+	drm_unset_busid(dev, master);
+	return ret;
 }
 }
 
 
 /**
 /**
@@ -323,7 +393,9 @@ int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_pri
 			/*
 			/*
 			 * Version 1.1 includes tying of DRM to specific device
 			 * Version 1.1 includes tying of DRM to specific device
 			 */
 			 */
-			drm_set_busid(dev, file_priv);
+			retcode = drm_set_busid(dev, file_priv);
+			if (retcode)
+				goto done;
 		}
 		}
 	}
 	}
 
 

+ 20 - 6
drivers/gpu/drm/drm_irq.c

@@ -34,6 +34,7 @@
  */
  */
 
 
 #include "drmP.h"
 #include "drmP.h"
+#include "drm_trace.h"
 
 
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -57,6 +58,9 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
 {
 {
 	struct drm_irq_busid *p = data;
 	struct drm_irq_busid *p = data;
 
 
+	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
+		return -EINVAL;
+
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
 		return -EINVAL;
 
 
@@ -211,7 +215,7 @@ int drm_irq_install(struct drm_device *dev)
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	if (dev->pdev->irq == 0)
+	if (drm_dev_to_irq(dev) == 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	mutex_lock(&dev->struct_mutex);
 	mutex_lock(&dev->struct_mutex);
@@ -229,7 +233,7 @@ int drm_irq_install(struct drm_device *dev)
 	dev->irq_enabled = 1;
 	dev->irq_enabled = 1;
 	mutex_unlock(&dev->struct_mutex);
 	mutex_unlock(&dev->struct_mutex);
 
 
-	DRM_DEBUG("irq=%d\n", dev->pdev->irq);
+	DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
 
 
 	/* Before installing handler */
 	/* Before installing handler */
 	dev->driver->irq_preinstall(dev);
 	dev->driver->irq_preinstall(dev);
@@ -302,14 +306,14 @@ int drm_irq_uninstall(struct drm_device * dev)
 	if (!irq_enabled)
 	if (!irq_enabled)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	DRM_DEBUG("irq=%d\n", dev->pdev->irq);
+	DRM_DEBUG("irq=%d\n", drm_dev_to_irq(dev));
 
 
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		vga_client_register(dev->pdev, NULL, NULL, NULL);
 		vga_client_register(dev->pdev, NULL, NULL, NULL);
 
 
 	dev->driver->irq_uninstall(dev);
 	dev->driver->irq_uninstall(dev);
 
 
-	free_irq(dev->pdev->irq, dev);
+	free_irq(drm_dev_to_irq(dev), dev);
 
 
 	return 0;
 	return 0;
 }
 }
@@ -341,7 +345,7 @@ int drm_control(struct drm_device *dev, void *data,
 		if (drm_core_check_feature(dev, DRIVER_MODESET))
 		if (drm_core_check_feature(dev, DRIVER_MODESET))
 			return 0;
 			return 0;
 		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
 		if (dev->if_version < DRM_IF_VERSION(1, 2) &&
-		    ctl->irq != dev->pdev->irq)
+		    ctl->irq != drm_dev_to_irq(dev))
 			return -EINVAL;
 			return -EINVAL;
 		return drm_irq_install(dev);
 		return drm_irq_install(dev);
 	case DRM_UNINST_HANDLER:
 	case DRM_UNINST_HANDLER:
@@ -587,6 +591,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	e->pipe = pipe;
 	e->pipe = pipe;
+	e->base.pid = current->pid;
 	e->event.base.type = DRM_EVENT_VBLANK;
 	e->event.base.type = DRM_EVENT_VBLANK;
 	e->event.base.length = sizeof e->event;
 	e->event.base.length = sizeof e->event;
 	e->event.user_data = vblwait->request.signal;
 	e->event.user_data = vblwait->request.signal;
@@ -614,6 +619,9 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
 	DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
 	DRM_DEBUG("event on vblank count %d, current %d, crtc %d\n",
 		  vblwait->request.sequence, seq, pipe);
 		  vblwait->request.sequence, seq, pipe);
 
 
+	trace_drm_vblank_event_queued(current->pid, pipe,
+				      vblwait->request.sequence);
+
 	e->event.sequence = vblwait->request.sequence;
 	e->event.sequence = vblwait->request.sequence;
 	if ((seq - vblwait->request.sequence) <= (1 << 23)) {
 	if ((seq - vblwait->request.sequence) <= (1 << 23)) {
 		e->event.tv_sec = now.tv_sec;
 		e->event.tv_sec = now.tv_sec;
@@ -621,6 +629,8 @@ static int drm_queue_vblank_event(struct drm_device *dev, int pipe,
 		drm_vblank_put(dev, e->pipe);
 		drm_vblank_put(dev, e->pipe);
 		list_add_tail(&e->base.link, &e->base.file_priv->event_list);
 		list_add_tail(&e->base.link, &e->base.file_priv->event_list);
 		wake_up_interruptible(&e->base.file_priv->event_wait);
 		wake_up_interruptible(&e->base.file_priv->event_wait);
+		trace_drm_vblank_event_delivered(current->pid, pipe,
+						 vblwait->request.sequence);
 	} else {
 	} else {
 		list_add_tail(&e->base.link, &dev->vblank_event_list);
 		list_add_tail(&e->base.link, &dev->vblank_event_list);
 	}
 	}
@@ -651,7 +661,7 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
 	int ret = 0;
 	int ret = 0;
 	unsigned int flags, seq, crtc;
 	unsigned int flags, seq, crtc;
 
 
-	if ((!dev->pdev->irq) || (!dev->irq_enabled))
+	if ((!drm_dev_to_irq(dev)) || (!dev->irq_enabled))
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
 	if (vblwait->request.type & _DRM_VBLANK_SIGNAL)
@@ -751,9 +761,13 @@ void drm_handle_vblank_events(struct drm_device *dev, int crtc)
 		drm_vblank_put(dev, e->pipe);
 		drm_vblank_put(dev, e->pipe);
 		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
 		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
 		wake_up_interruptible(&e->base.file_priv->event_wait);
 		wake_up_interruptible(&e->base.file_priv->event_wait);
+		trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
+						 e->event.sequence);
 	}
 	}
 
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
 	spin_unlock_irqrestore(&dev->event_lock, flags);
+
+	trace_drm_vblank_event(crtc, seq);
 }
 }
 
 
 /**
 /**

+ 232 - 127
drivers/gpu/drm/drm_mm.c

@@ -48,44 +48,14 @@
 
 
 #define MM_UNUSED_TARGET 4
 #define MM_UNUSED_TARGET 4
 
 
-unsigned long drm_mm_tail_space(struct drm_mm *mm)
-{
-	struct list_head *tail_node;
-	struct drm_mm_node *entry;
-
-	tail_node = mm->ml_entry.prev;
-	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
-	if (!entry->free)
-		return 0;
-
-	return entry->size;
-}
-
-int drm_mm_remove_space_from_tail(struct drm_mm *mm, unsigned long size)
-{
-	struct list_head *tail_node;
-	struct drm_mm_node *entry;
-
-	tail_node = mm->ml_entry.prev;
-	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
-	if (!entry->free)
-		return -ENOMEM;
-
-	if (entry->size <= size)
-		return -ENOMEM;
-
-	entry->size -= size;
-	return 0;
-}
-
 static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
 static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
 {
 {
 	struct drm_mm_node *child;
 	struct drm_mm_node *child;
 
 
 	if (atomic)
 	if (atomic)
-		child = kmalloc(sizeof(*child), GFP_ATOMIC);
+		child = kzalloc(sizeof(*child), GFP_ATOMIC);
 	else
 	else
-		child = kmalloc(sizeof(*child), GFP_KERNEL);
+		child = kzalloc(sizeof(*child), GFP_KERNEL);
 
 
 	if (unlikely(child == NULL)) {
 	if (unlikely(child == NULL)) {
 		spin_lock(&mm->unused_lock);
 		spin_lock(&mm->unused_lock);
@@ -94,8 +64,8 @@ static struct drm_mm_node *drm_mm_kmalloc(struct drm_mm *mm, int atomic)
 		else {
 		else {
 			child =
 			child =
 			    list_entry(mm->unused_nodes.next,
 			    list_entry(mm->unused_nodes.next,
-				       struct drm_mm_node, fl_entry);
-			list_del(&child->fl_entry);
+				       struct drm_mm_node, free_stack);
+			list_del(&child->free_stack);
 			--mm->num_unused;
 			--mm->num_unused;
 		}
 		}
 		spin_unlock(&mm->unused_lock);
 		spin_unlock(&mm->unused_lock);
@@ -115,7 +85,7 @@ int drm_mm_pre_get(struct drm_mm *mm)
 	spin_lock(&mm->unused_lock);
 	spin_lock(&mm->unused_lock);
 	while (mm->num_unused < MM_UNUSED_TARGET) {
 	while (mm->num_unused < MM_UNUSED_TARGET) {
 		spin_unlock(&mm->unused_lock);
 		spin_unlock(&mm->unused_lock);
-		node = kmalloc(sizeof(*node), GFP_KERNEL);
+		node = kzalloc(sizeof(*node), GFP_KERNEL);
 		spin_lock(&mm->unused_lock);
 		spin_lock(&mm->unused_lock);
 
 
 		if (unlikely(node == NULL)) {
 		if (unlikely(node == NULL)) {
@@ -124,7 +94,7 @@ int drm_mm_pre_get(struct drm_mm *mm)
 			return ret;
 			return ret;
 		}
 		}
 		++mm->num_unused;
 		++mm->num_unused;
-		list_add_tail(&node->fl_entry, &mm->unused_nodes);
+		list_add_tail(&node->free_stack, &mm->unused_nodes);
 	}
 	}
 	spin_unlock(&mm->unused_lock);
 	spin_unlock(&mm->unused_lock);
 	return 0;
 	return 0;
@@ -146,27 +116,12 @@ static int drm_mm_create_tail_node(struct drm_mm *mm,
 	child->start = start;
 	child->start = start;
 	child->mm = mm;
 	child->mm = mm;
 
 
-	list_add_tail(&child->ml_entry, &mm->ml_entry);
-	list_add_tail(&child->fl_entry, &mm->fl_entry);
+	list_add_tail(&child->node_list, &mm->node_list);
+	list_add_tail(&child->free_stack, &mm->free_stack);
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-int drm_mm_add_space_to_tail(struct drm_mm *mm, unsigned long size, int atomic)
-{
-	struct list_head *tail_node;
-	struct drm_mm_node *entry;
-
-	tail_node = mm->ml_entry.prev;
-	entry = list_entry(tail_node, struct drm_mm_node, ml_entry);
-	if (!entry->free) {
-		return drm_mm_create_tail_node(mm, entry->start + entry->size,
-					       size, atomic);
-	}
-	entry->size += size;
-	return 0;
-}
-
 static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
 static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
 						 unsigned long size,
 						 unsigned long size,
 						 int atomic)
 						 int atomic)
@@ -177,15 +132,14 @@ static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
 	if (unlikely(child == NULL))
 	if (unlikely(child == NULL))
 		return NULL;
 		return NULL;
 
 
-	INIT_LIST_HEAD(&child->fl_entry);
+	INIT_LIST_HEAD(&child->free_stack);
 
 
-	child->free = 0;
 	child->size = size;
 	child->size = size;
 	child->start = parent->start;
 	child->start = parent->start;
 	child->mm = parent->mm;
 	child->mm = parent->mm;
 
 
-	list_add_tail(&child->ml_entry, &parent->ml_entry);
-	INIT_LIST_HEAD(&child->fl_entry);
+	list_add_tail(&child->node_list, &parent->node_list);
+	INIT_LIST_HEAD(&child->free_stack);
 
 
 	parent->size -= size;
 	parent->size -= size;
 	parent->start += size;
 	parent->start += size;
@@ -213,7 +167,7 @@ struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
 	}
 	}
 
 
 	if (node->size == size) {
 	if (node->size == size) {
-		list_del_init(&node->fl_entry);
+		list_del_init(&node->free_stack);
 		node->free = 0;
 		node->free = 0;
 	} else {
 	} else {
 		node = drm_mm_split_at_start(node, size, atomic);
 		node = drm_mm_split_at_start(node, size, atomic);
@@ -251,7 +205,7 @@ struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
 	}
 	}
 
 
 	if (node->size == size) {
 	if (node->size == size) {
-		list_del_init(&node->fl_entry);
+		list_del_init(&node->free_stack);
 		node->free = 0;
 		node->free = 0;
 	} else {
 	} else {
 		node = drm_mm_split_at_start(node, size, atomic);
 		node = drm_mm_split_at_start(node, size, atomic);
@@ -273,16 +227,19 @@ void drm_mm_put_block(struct drm_mm_node *cur)
 {
 {
 
 
 	struct drm_mm *mm = cur->mm;
 	struct drm_mm *mm = cur->mm;
-	struct list_head *cur_head = &cur->ml_entry;
-	struct list_head *root_head = &mm->ml_entry;
+	struct list_head *cur_head = &cur->node_list;
+	struct list_head *root_head = &mm->node_list;
 	struct drm_mm_node *prev_node = NULL;
 	struct drm_mm_node *prev_node = NULL;
 	struct drm_mm_node *next_node;
 	struct drm_mm_node *next_node;
 
 
 	int merged = 0;
 	int merged = 0;
 
 
+	BUG_ON(cur->scanned_block || cur->scanned_prev_free
+				  || cur->scanned_next_free);
+
 	if (cur_head->prev != root_head) {
 	if (cur_head->prev != root_head) {
 		prev_node =
 		prev_node =
-		    list_entry(cur_head->prev, struct drm_mm_node, ml_entry);
+		    list_entry(cur_head->prev, struct drm_mm_node, node_list);
 		if (prev_node->free) {
 		if (prev_node->free) {
 			prev_node->size += cur->size;
 			prev_node->size += cur->size;
 			merged = 1;
 			merged = 1;
@@ -290,15 +247,15 @@ void drm_mm_put_block(struct drm_mm_node *cur)
 	}
 	}
 	if (cur_head->next != root_head) {
 	if (cur_head->next != root_head) {
 		next_node =
 		next_node =
-		    list_entry(cur_head->next, struct drm_mm_node, ml_entry);
+		    list_entry(cur_head->next, struct drm_mm_node, node_list);
 		if (next_node->free) {
 		if (next_node->free) {
 			if (merged) {
 			if (merged) {
 				prev_node->size += next_node->size;
 				prev_node->size += next_node->size;
-				list_del(&next_node->ml_entry);
-				list_del(&next_node->fl_entry);
+				list_del(&next_node->node_list);
+				list_del(&next_node->free_stack);
 				spin_lock(&mm->unused_lock);
 				spin_lock(&mm->unused_lock);
 				if (mm->num_unused < MM_UNUSED_TARGET) {
 				if (mm->num_unused < MM_UNUSED_TARGET) {
-					list_add(&next_node->fl_entry,
+					list_add(&next_node->free_stack,
 						 &mm->unused_nodes);
 						 &mm->unused_nodes);
 					++mm->num_unused;
 					++mm->num_unused;
 				} else
 				} else
@@ -313,12 +270,12 @@ void drm_mm_put_block(struct drm_mm_node *cur)
 	}
 	}
 	if (!merged) {
 	if (!merged) {
 		cur->free = 1;
 		cur->free = 1;
-		list_add(&cur->fl_entry, &mm->fl_entry);
+		list_add(&cur->free_stack, &mm->free_stack);
 	} else {
 	} else {
-		list_del(&cur->ml_entry);
+		list_del(&cur->node_list);
 		spin_lock(&mm->unused_lock);
 		spin_lock(&mm->unused_lock);
 		if (mm->num_unused < MM_UNUSED_TARGET) {
 		if (mm->num_unused < MM_UNUSED_TARGET) {
-			list_add(&cur->fl_entry, &mm->unused_nodes);
+			list_add(&cur->free_stack, &mm->unused_nodes);
 			++mm->num_unused;
 			++mm->num_unused;
 		} else
 		} else
 			kfree(cur);
 			kfree(cur);
@@ -328,40 +285,50 @@ void drm_mm_put_block(struct drm_mm_node *cur)
 
 
 EXPORT_SYMBOL(drm_mm_put_block);
 EXPORT_SYMBOL(drm_mm_put_block);
 
 
+static int check_free_mm_node(struct drm_mm_node *entry, unsigned long size,
+			      unsigned alignment)
+{
+	unsigned wasted = 0;
+
+	if (entry->size < size)
+		return 0;
+
+	if (alignment) {
+		register unsigned tmp = entry->start % alignment;
+		if (tmp)
+			wasted = alignment - tmp;
+	}
+
+	if (entry->size >= size + wasted) {
+		return 1;
+	}
+
+	return 0;
+}
+
 struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
 struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm,
 				       unsigned long size,
 				       unsigned long size,
 				       unsigned alignment, int best_match)
 				       unsigned alignment, int best_match)
 {
 {
-	struct list_head *list;
-	const struct list_head *free_stack = &mm->fl_entry;
 	struct drm_mm_node *entry;
 	struct drm_mm_node *entry;
 	struct drm_mm_node *best;
 	struct drm_mm_node *best;
 	unsigned long best_size;
 	unsigned long best_size;
-	unsigned wasted;
+
+	BUG_ON(mm->scanned_blocks);
 
 
 	best = NULL;
 	best = NULL;
 	best_size = ~0UL;
 	best_size = ~0UL;
 
 
-	list_for_each(list, free_stack) {
-		entry = list_entry(list, struct drm_mm_node, fl_entry);
-		wasted = 0;
-
-		if (entry->size < size)
+	list_for_each_entry(entry, &mm->free_stack, free_stack) {
+		if (!check_free_mm_node(entry, size, alignment))
 			continue;
 			continue;
 
 
-		if (alignment) {
-			register unsigned tmp = entry->start % alignment;
-			if (tmp)
-				wasted += alignment - tmp;
-		}
+		if (!best_match)
+			return entry;
 
 
-		if (entry->size >= size + wasted) {
-			if (!best_match)
-				return entry;
-			if (entry->size < best_size) {
-				best = entry;
-				best_size = entry->size;
-			}
+		if (entry->size < best_size) {
+			best = entry;
+			best_size = entry->size;
 		}
 		}
 	}
 	}
 
 
@@ -376,43 +343,28 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
 						unsigned long end,
 						unsigned long end,
 						int best_match)
 						int best_match)
 {
 {
-	struct list_head *list;
-	const struct list_head *free_stack = &mm->fl_entry;
 	struct drm_mm_node *entry;
 	struct drm_mm_node *entry;
 	struct drm_mm_node *best;
 	struct drm_mm_node *best;
 	unsigned long best_size;
 	unsigned long best_size;
-	unsigned wasted;
+
+	BUG_ON(mm->scanned_blocks);
 
 
 	best = NULL;
 	best = NULL;
 	best_size = ~0UL;
 	best_size = ~0UL;
 
 
-	list_for_each(list, free_stack) {
-		entry = list_entry(list, struct drm_mm_node, fl_entry);
-		wasted = 0;
-
-		if (entry->size < size)
-			continue;
-
+	list_for_each_entry(entry, &mm->free_stack, free_stack) {
 		if (entry->start > end || (entry->start+entry->size) < start)
 		if (entry->start > end || (entry->start+entry->size) < start)
 			continue;
 			continue;
 
 
-		if (entry->start < start)
-			wasted += start - entry->start;
+		if (!check_free_mm_node(entry, size, alignment))
+			continue;
 
 
-		if (alignment) {
-			register unsigned tmp = (entry->start + wasted) % alignment;
-			if (tmp)
-				wasted += alignment - tmp;
-		}
+		if (!best_match)
+			return entry;
 
 
-		if (entry->size >= size + wasted &&
-		    (entry->start + wasted + size) <= end) {
-			if (!best_match)
-				return entry;
-			if (entry->size < best_size) {
-				best = entry;
-				best_size = entry->size;
-			}
+		if (entry->size < best_size) {
+			best = entry;
+			best_size = entry->size;
 		}
 		}
 	}
 	}
 
 
@@ -420,9 +372,161 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm,
 }
 }
 EXPORT_SYMBOL(drm_mm_search_free_in_range);
 EXPORT_SYMBOL(drm_mm_search_free_in_range);
 
 
+/**
+ * Initializa lru scanning.
+ *
+ * This simply sets up the scanning routines with the parameters for the desired
+ * hole.
+ *
+ * Warning: As long as the scan list is non-empty, no other operations than
+ * adding/removing nodes to/from the scan list are allowed.
+ */
+void drm_mm_init_scan(struct drm_mm *mm, unsigned long size,
+		      unsigned alignment)
+{
+	mm->scan_alignment = alignment;
+	mm->scan_size = size;
+	mm->scanned_blocks = 0;
+	mm->scan_hit_start = 0;
+	mm->scan_hit_size = 0;
+}
+EXPORT_SYMBOL(drm_mm_init_scan);
+
+/**
+ * Add a node to the scan list that might be freed to make space for the desired
+ * hole.
+ *
+ * Returns non-zero, if a hole has been found, zero otherwise.
+ */
+int drm_mm_scan_add_block(struct drm_mm_node *node)
+{
+	struct drm_mm *mm = node->mm;
+	struct list_head *prev_free, *next_free;
+	struct drm_mm_node *prev_node, *next_node;
+
+	mm->scanned_blocks++;
+
+	prev_free = next_free = NULL;
+
+	BUG_ON(node->free);
+	node->scanned_block = 1;
+	node->free = 1;
+
+	if (node->node_list.prev != &mm->node_list) {
+		prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
+				       node_list);
+
+		if (prev_node->free) {
+			list_del(&prev_node->node_list);
+
+			node->start = prev_node->start;
+			node->size += prev_node->size;
+
+			prev_node->scanned_prev_free = 1;
+
+			prev_free = &prev_node->free_stack;
+		}
+	}
+
+	if (node->node_list.next != &mm->node_list) {
+		next_node = list_entry(node->node_list.next, struct drm_mm_node,
+				       node_list);
+
+		if (next_node->free) {
+			list_del(&next_node->node_list);
+
+			node->size += next_node->size;
+
+			next_node->scanned_next_free = 1;
+
+			next_free = &next_node->free_stack;
+		}
+	}
+
+	/* The free_stack list is not used for allocated objects, so these two
+	 * pointers can be abused (as long as no allocations in this memory
+	 * manager happens). */
+	node->free_stack.prev = prev_free;
+	node->free_stack.next = next_free;
+
+	if (check_free_mm_node(node, mm->scan_size, mm->scan_alignment)) {
+		mm->scan_hit_start = node->start;
+		mm->scan_hit_size = node->size;
+
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_mm_scan_add_block);
+
+/**
+ * Remove a node from the scan list.
+ *
+ * Nodes _must_ be removed in the exact same order from the scan list as they
+ * have been added, otherwise the internal state of the memory manager will be
+ * corrupted.
+ *
+ * When the scan list is empty, the selected memory nodes can be freed. An
+ * immediatly following drm_mm_search_free with best_match = 0 will then return
+ * the just freed block (because its at the top of the free_stack list).
+ *
+ * Returns one if this block should be evicted, zero otherwise. Will always
+ * return zero when no hole has been found.
+ */
+int drm_mm_scan_remove_block(struct drm_mm_node *node)
+{
+	struct drm_mm *mm = node->mm;
+	struct drm_mm_node *prev_node, *next_node;
+
+	mm->scanned_blocks--;
+
+	BUG_ON(!node->scanned_block);
+	node->scanned_block = 0;
+	node->free = 0;
+
+	prev_node = list_entry(node->free_stack.prev, struct drm_mm_node,
+			       free_stack);
+	next_node = list_entry(node->free_stack.next, struct drm_mm_node,
+			       free_stack);
+
+	if (prev_node) {
+		BUG_ON(!prev_node->scanned_prev_free);
+		prev_node->scanned_prev_free = 0;
+
+		list_add_tail(&prev_node->node_list, &node->node_list);
+
+		node->start = prev_node->start + prev_node->size;
+		node->size -= prev_node->size;
+	}
+
+	if (next_node) {
+		BUG_ON(!next_node->scanned_next_free);
+		next_node->scanned_next_free = 0;
+
+		list_add(&next_node->node_list, &node->node_list);
+
+		node->size -= next_node->size;
+	}
+
+	INIT_LIST_HEAD(&node->free_stack);
+
+	/* Only need to check for containement because start&size for the
+	 * complete resulting free block (not just the desired part) is
+	 * stored. */
+	if (node->start >= mm->scan_hit_start &&
+	    node->start + node->size
+	    		<= mm->scan_hit_start + mm->scan_hit_size) {
+		return 1;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_mm_scan_remove_block);
+
 int drm_mm_clean(struct drm_mm * mm)
 int drm_mm_clean(struct drm_mm * mm)
 {
 {
-	struct list_head *head = &mm->ml_entry;
+	struct list_head *head = &mm->node_list;
 
 
 	return (head->next->next == head);
 	return (head->next->next == head);
 }
 }
@@ -430,10 +534,11 @@ EXPORT_SYMBOL(drm_mm_clean);
 
 
 int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
 {
-	INIT_LIST_HEAD(&mm->ml_entry);
-	INIT_LIST_HEAD(&mm->fl_entry);
+	INIT_LIST_HEAD(&mm->node_list);
+	INIT_LIST_HEAD(&mm->free_stack);
 	INIT_LIST_HEAD(&mm->unused_nodes);
 	INIT_LIST_HEAD(&mm->unused_nodes);
 	mm->num_unused = 0;
 	mm->num_unused = 0;
+	mm->scanned_blocks = 0;
 	spin_lock_init(&mm->unused_lock);
 	spin_lock_init(&mm->unused_lock);
 
 
 	return drm_mm_create_tail_node(mm, start, size, 0);
 	return drm_mm_create_tail_node(mm, start, size, 0);
@@ -442,25 +547,25 @@ EXPORT_SYMBOL(drm_mm_init);
 
 
 void drm_mm_takedown(struct drm_mm * mm)
 void drm_mm_takedown(struct drm_mm * mm)
 {
 {
-	struct list_head *bnode = mm->fl_entry.next;
+	struct list_head *bnode = mm->free_stack.next;
 	struct drm_mm_node *entry;
 	struct drm_mm_node *entry;
 	struct drm_mm_node *next;
 	struct drm_mm_node *next;
 
 
-	entry = list_entry(bnode, struct drm_mm_node, fl_entry);
+	entry = list_entry(bnode, struct drm_mm_node, free_stack);
 
 
-	if (entry->ml_entry.next != &mm->ml_entry ||
-	    entry->fl_entry.next != &mm->fl_entry) {
+	if (entry->node_list.next != &mm->node_list ||
+	    entry->free_stack.next != &mm->free_stack) {
 		DRM_ERROR("Memory manager not clean. Delaying takedown\n");
 		DRM_ERROR("Memory manager not clean. Delaying takedown\n");
 		return;
 		return;
 	}
 	}
 
 
-	list_del(&entry->fl_entry);
-	list_del(&entry->ml_entry);
+	list_del(&entry->free_stack);
+	list_del(&entry->node_list);
 	kfree(entry);
 	kfree(entry);
 
 
 	spin_lock(&mm->unused_lock);
 	spin_lock(&mm->unused_lock);
-	list_for_each_entry_safe(entry, next, &mm->unused_nodes, fl_entry) {
-		list_del(&entry->fl_entry);
+	list_for_each_entry_safe(entry, next, &mm->unused_nodes, free_stack) {
+		list_del(&entry->free_stack);
 		kfree(entry);
 		kfree(entry);
 		--mm->num_unused;
 		--mm->num_unused;
 	}
 	}
@@ -475,7 +580,7 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
 	struct drm_mm_node *entry;
 	struct drm_mm_node *entry;
 	int total_used = 0, total_free = 0, total = 0;
 	int total_used = 0, total_free = 0, total = 0;
 
 
-	list_for_each_entry(entry, &mm->ml_entry, ml_entry) {
+	list_for_each_entry(entry, &mm->node_list, node_list) {
 		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
 		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
 			prefix, entry->start, entry->start + entry->size,
 			prefix, entry->start, entry->start + entry->size,
 			entry->size, entry->free ? "free" : "used");
 			entry->size, entry->free ? "free" : "used");
@@ -496,7 +601,7 @@ int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
 	struct drm_mm_node *entry;
 	struct drm_mm_node *entry;
 	int total_used = 0, total_free = 0, total = 0;
 	int total_used = 0, total_free = 0, total = 0;
 
 
-	list_for_each_entry(entry, &mm->ml_entry, ml_entry) {
+	list_for_each_entry(entry, &mm->node_list, node_list) {
 		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used");
 		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used");
 		total += entry->size;
 		total += entry->size;
 		if (entry->free)
 		if (entry->free)

+ 143 - 0
drivers/gpu/drm/drm_pci.c

@@ -124,4 +124,147 @@ void drm_pci_free(struct drm_device * dev, drm_dma_handle_t * dmah)
 
 
 EXPORT_SYMBOL(drm_pci_free);
 EXPORT_SYMBOL(drm_pci_free);
 
 
+#ifdef CONFIG_PCI
+/**
+ * Register.
+ *
+ * \param pdev - PCI device structure
+ * \param ent entry from the PCI ID table with device type flags
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to gets inter module "drm" information. If we are first
+ * then register the character device and inter module information.
+ * Try and register, if we fail to register, backout previous work.
+ */
+int drm_get_pci_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+		    struct drm_driver *driver)
+{
+	struct drm_device *dev;
+	int ret;
+
+	DRM_DEBUG("\n");
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	ret = pci_enable_device(pdev);
+	if (ret)
+		goto err_g1;
+
+	pci_set_master(pdev);
+
+	dev->pdev = pdev;
+	dev->dev = &pdev->dev;
+
+	dev->pci_device = pdev->device;
+	dev->pci_vendor = pdev->vendor;
+
+#ifdef __alpha__
+	dev->hose = pdev->sysdata;
+#endif
+
+	if ((ret = drm_fill_in_dev(dev, ent, driver))) {
+		printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+		goto err_g2;
+	}
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		pci_set_drvdata(pdev, dev);
+		ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
+		if (ret)
+			goto err_g2;
+	}
+
+	if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
+		goto err_g3;
+
+	if (dev->driver->load) {
+		ret = dev->driver->load(dev, ent->driver_data);
+		if (ret)
+			goto err_g4;
+	}
+
+	/* setup the grouping for the legacy output */
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		ret = drm_mode_group_init_legacy_group(dev,
+						&dev->primary->mode_group);
+		if (ret)
+			goto err_g4;
+	}
+
+	list_add_tail(&dev->driver_item, &driver->device_list);
+
+	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
+		 driver->name, driver->major, driver->minor, driver->patchlevel,
+		 driver->date, pci_name(pdev), dev->primary->index);
+
+	return 0;
+
+err_g4:
+	drm_put_minor(&dev->primary);
+err_g3:
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_put_minor(&dev->control);
+err_g2:
+	pci_disable_device(pdev);
+err_g1:
+	kfree(dev);
+	return ret;
+}
+EXPORT_SYMBOL(drm_get_pci_dev);
+
+/**
+ * PCI device initialization. Called via drm_init at module load time,
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Initializes a drm_device structures,registering the
+ * stubs and initializing the AGP device.
+ *
+ * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
+ * after the initialization for driver customization.
+ */
+int drm_pci_init(struct drm_driver *driver)
+{
+	struct pci_dev *pdev = NULL;
+	const struct pci_device_id *pid;
+	int i;
+
+	if (driver->driver_features & DRIVER_MODESET)
+		return pci_register_driver(&driver->pci_driver);
+
+	/* If not using KMS, fall back to stealth mode manual scanning. */
+	for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
+		pid = &driver->pci_driver.id_table[i];
+
+		/* Loop around setting up a DRM device for each PCI device
+		 * matching our ID and device class.  If we had the internal
+		 * function that pci_get_subsys and pci_get_class used, we'd
+		 * be able to just pass pid in instead of doing a two-stage
+		 * thing.
+		 */
+		pdev = NULL;
+		while ((pdev =
+			pci_get_subsys(pid->vendor, pid->device, pid->subvendor,
+				       pid->subdevice, pdev)) != NULL) {
+			if ((pdev->class & pid->class_mask) != pid->class)
+				continue;
+
+			/* stealth mode requires a manual probe */
+			pci_dev_get(pdev);
+			drm_get_pci_dev(pdev, pid, driver);
+		}
+	}
+	return 0;
+}
+
+#else
+
+int drm_pci_init(struct drm_driver *driver)
+{
+	return -1;
+}
+
+#endif
 /*@}*/
 /*@}*/

+ 122 - 0
drivers/gpu/drm/drm_platform.c

@@ -0,0 +1,122 @@
+/*
+ * Derived from drm_pci.c
+ *
+ * Copyright 2003 José Fonseca.
+ * Copyright 2003 Leif Delgass.
+ * Copyright (c) 2009, Code Aurora Forum.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "drmP.h"
+
+/**
+ * Register.
+ *
+ * \param platdev - Platform device struture
+ * \return zero on success or a negative number on failure.
+ *
+ * Attempt to gets inter module "drm" information. If we are first
+ * then register the character device and inter module information.
+ * Try and register, if we fail to register, backout previous work.
+ */
+
+int drm_get_platform_dev(struct platform_device *platdev,
+			 struct drm_driver *driver)
+{
+	struct drm_device *dev;
+	int ret;
+
+	DRM_DEBUG("\n");
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->platformdev = platdev;
+	dev->dev = &platdev->dev;
+
+	ret = drm_fill_in_dev(dev, NULL, driver);
+
+	if (ret) {
+		printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+		goto err_g1;
+	}
+
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		dev_set_drvdata(&platdev->dev, dev);
+		ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
+		if (ret)
+			goto err_g1;
+	}
+
+	ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY);
+	if (ret)
+		goto err_g2;
+
+	if (dev->driver->load) {
+		ret = dev->driver->load(dev, 0);
+		if (ret)
+			goto err_g3;
+	}
+
+	/* setup the grouping for the legacy output */
+	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+		ret = drm_mode_group_init_legacy_group(dev,
+				&dev->primary->mode_group);
+		if (ret)
+			goto err_g3;
+	}
+
+	list_add_tail(&dev->driver_item, &driver->device_list);
+
+	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+		 driver->name, driver->major, driver->minor, driver->patchlevel,
+		 driver->date, dev->primary->index);
+
+	return 0;
+
+err_g3:
+	drm_put_minor(&dev->primary);
+err_g2:
+	if (drm_core_check_feature(dev, DRIVER_MODESET))
+		drm_put_minor(&dev->control);
+err_g1:
+	kfree(dev);
+	return ret;
+}
+EXPORT_SYMBOL(drm_get_platform_dev);
+
+/**
+ * Platform device initialization. Called via drm_init at module load time,
+ *
+ * \return zero on success or a negative number on failure.
+ *
+ * Initializes a drm_device structures,registering the
+ * stubs
+ *
+ * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
+ * after the initialization for driver customization.
+ */
+
+int drm_platform_init(struct drm_driver *driver)
+{
+	return drm_get_platform_dev(driver->platform_device, driver);
+}

+ 5 - 87
drivers/gpu/drm/drm_stub.c

@@ -156,6 +156,9 @@ static void drm_master_destroy(struct kref *kref)
 		master->unique_len = 0;
 		master->unique_len = 0;
 	}
 	}
 
 
+	kfree(dev->devname);
+	dev->devname = NULL;
+
 	list_for_each_entry_safe(pt, next, &master->magicfree, head) {
 	list_for_each_entry_safe(pt, next, &master->magicfree, head) {
 		list_del(&pt->head);
 		list_del(&pt->head);
 		drm_ht_remove_item(&master->magiclist, &pt->hash_item);
 		drm_ht_remove_item(&master->magiclist, &pt->hash_item);
@@ -224,7 +227,7 @@ int drm_dropmaster_ioctl(struct drm_device *dev, void *data,
 	return 0;
 	return 0;
 }
 }
 
 
-static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
+int drm_fill_in_dev(struct drm_device *dev,
 			   const struct pci_device_id *ent,
 			   const struct pci_device_id *ent,
 			   struct drm_driver *driver)
 			   struct drm_driver *driver)
 {
 {
@@ -245,14 +248,6 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
 
 
 	idr_init(&dev->drw_idr);
 	idr_init(&dev->drw_idr);
 
 
-	dev->pdev = pdev;
-	dev->pci_device = pdev->device;
-	dev->pci_vendor = pdev->vendor;
-
-#ifdef __alpha__
-	dev->hose = pdev->sysdata;
-#endif
-
 	if (drm_ht_create(&dev->map_hash, 12)) {
 	if (drm_ht_create(&dev->map_hash, 12)) {
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
@@ -321,7 +316,7 @@ static int drm_fill_in_dev(struct drm_device * dev, struct pci_dev *pdev,
  * create the proc init entry via proc_init(). This routines assigns
  * create the proc init entry via proc_init(). This routines assigns
  * minor numbers to secondary heads of multi-headed cards
  * minor numbers to secondary heads of multi-headed cards
  */
  */
-static int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
+int drm_get_minor(struct drm_device *dev, struct drm_minor **minor, int type)
 {
 {
 	struct drm_minor *new_minor;
 	struct drm_minor *new_minor;
 	int ret;
 	int ret;
@@ -387,83 +382,6 @@ err_idr:
 	return ret;
 	return ret;
 }
 }
 
 
-/**
- * Register.
- *
- * \param pdev - PCI device structure
- * \param ent entry from the PCI ID table with device type flags
- * \return zero on success or a negative number on failure.
- *
- * Attempt to gets inter module "drm" information. If we are first
- * then register the character device and inter module information.
- * Try and register, if we fail to register, backout previous work.
- */
-int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
-		struct drm_driver *driver)
-{
-	struct drm_device *dev;
-	int ret;
-
-	DRM_DEBUG("\n");
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
-
-	ret = pci_enable_device(pdev);
-	if (ret)
-		goto err_g1;
-
-	pci_set_master(pdev);
-	if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
-		printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
-		goto err_g2;
-	}
-
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		pci_set_drvdata(pdev, dev);
-		ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
-		if (ret)
-			goto err_g2;
-	}
-
-	if ((ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY)))
-		goto err_g3;
-
-	if (dev->driver->load) {
-		ret = dev->driver->load(dev, ent->driver_data);
-		if (ret)
-			goto err_g4;
-	}
-
-        /* setup the grouping for the legacy output */
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
-		if (ret)
-			goto err_g4;
-	}
-
-	list_add_tail(&dev->driver_item, &driver->device_list);
-
-	DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n",
-		 driver->name, driver->major, driver->minor, driver->patchlevel,
-		 driver->date, pci_name(pdev), dev->primary->index);
-
-	return 0;
-
-err_g4:
-	drm_put_minor(&dev->primary);
-err_g3:
-	if (drm_core_check_feature(dev, DRIVER_MODESET))
-		drm_put_minor(&dev->control);
-err_g2:
-	pci_disable_device(pdev);
-err_g1:
-	kfree(dev);
-	return ret;
-}
-EXPORT_SYMBOL(drm_get_dev);
-
 /**
 /**
  * Put a secondary minor number.
  * Put a secondary minor number.
  *
  *

+ 2 - 1
drivers/gpu/drm/drm_sysfs.c

@@ -489,7 +489,8 @@ int drm_sysfs_device_add(struct drm_minor *minor)
 	int err;
 	int err;
 	char *minor_str;
 	char *minor_str;
 
 
-	minor->kdev.parent = &minor->dev->pdev->dev;
+	minor->kdev.parent = minor->dev->dev;
+
 	minor->kdev.class = drm_class;
 	minor->kdev.class = drm_class;
 	minor->kdev.release = drm_sysfs_device_release;
 	minor->kdev.release = drm_sysfs_device_release;
 	minor->kdev.devt = minor->device;
 	minor->kdev.devt = minor->device;

+ 66 - 0
drivers/gpu/drm/drm_trace.h

@@ -0,0 +1,66 @@
+#if !defined(_DRM_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ)
+#define _DRM_TRACE_H_
+
+#include <linux/stringify.h>
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM drm
+#define TRACE_SYSTEM_STRING __stringify(TRACE_SYSTEM)
+#define TRACE_INCLUDE_FILE drm_trace
+
+TRACE_EVENT(drm_vblank_event,
+	    TP_PROTO(int crtc, unsigned int seq),
+	    TP_ARGS(crtc, seq),
+	    TP_STRUCT__entry(
+		    __field(int, crtc)
+		    __field(unsigned int, seq)
+		    ),
+	    TP_fast_assign(
+		    __entry->crtc = crtc;
+		    __entry->seq = seq;
+		    ),
+	    TP_printk("crtc=%d, seq=%d", __entry->crtc, __entry->seq)
+);
+
+TRACE_EVENT(drm_vblank_event_queued,
+	    TP_PROTO(pid_t pid, int crtc, unsigned int seq),
+	    TP_ARGS(pid, crtc, seq),
+	    TP_STRUCT__entry(
+		    __field(pid_t, pid)
+		    __field(int, crtc)
+		    __field(unsigned int, seq)
+		    ),
+	    TP_fast_assign(
+		    __entry->pid = pid;
+		    __entry->crtc = crtc;
+		    __entry->seq = seq;
+		    ),
+	    TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \
+		      __entry->seq)
+);
+
+TRACE_EVENT(drm_vblank_event_delivered,
+	    TP_PROTO(pid_t pid, int crtc, unsigned int seq),
+	    TP_ARGS(pid, crtc, seq),
+	    TP_STRUCT__entry(
+		    __field(pid_t, pid)
+		    __field(int, crtc)
+		    __field(unsigned int, seq)
+		    ),
+	    TP_fast_assign(
+		    __entry->pid = pid;
+		    __entry->crtc = crtc;
+		    __entry->seq = seq;
+		    ),
+	    TP_printk("pid=%d, crtc=%d, seq=%d", __entry->pid, __entry->crtc, \
+		      __entry->seq)
+);
+
+#endif /* _DRM_TRACE_H_ */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>

+ 4 - 0
drivers/gpu/drm/drm_trace_points.c

@@ -0,0 +1,4 @@
+#include "drmP.h"
+
+#define CREATE_TRACE_POINTS
+#include "drm_trace.h"

+ 13 - 1
drivers/gpu/drm/drm_vm.c

@@ -61,7 +61,7 @@ static pgprot_t drm_io_prot(uint32_t map_type, struct vm_area_struct *vma)
 		tmp = pgprot_writecombine(tmp);
 		tmp = pgprot_writecombine(tmp);
 	else
 	else
 		tmp = pgprot_noncached(tmp);
 		tmp = pgprot_noncached(tmp);
-#elif defined(__sparc__)
+#elif defined(__sparc__) || defined(__arm__)
 	tmp = pgprot_noncached(tmp);
 	tmp = pgprot_noncached(tmp);
 #endif
 #endif
 	return tmp;
 	return tmp;
@@ -601,6 +601,7 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 	}
 	}
 
 
 	switch (map->type) {
 	switch (map->type) {
+#if !defined(__arm__)
 	case _DRM_AGP:
 	case _DRM_AGP:
 		if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
 		if (drm_core_has_AGP(dev) && dev->agp->cant_use_aperture) {
 			/*
 			/*
@@ -615,20 +616,31 @@ int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
 			break;
 			break;
 		}
 		}
 		/* fall through to _DRM_FRAME_BUFFER... */
 		/* fall through to _DRM_FRAME_BUFFER... */
+#endif
 	case _DRM_FRAME_BUFFER:
 	case _DRM_FRAME_BUFFER:
 	case _DRM_REGISTERS:
 	case _DRM_REGISTERS:
 		offset = dev->driver->get_reg_ofs(dev);
 		offset = dev->driver->get_reg_ofs(dev);
 		vma->vm_flags |= VM_IO;	/* not in core dump */
 		vma->vm_flags |= VM_IO;	/* not in core dump */
 		vma->vm_page_prot = drm_io_prot(map->type, vma);
 		vma->vm_page_prot = drm_io_prot(map->type, vma);
+#if !defined(__arm__)
 		if (io_remap_pfn_range(vma, vma->vm_start,
 		if (io_remap_pfn_range(vma, vma->vm_start,
 				       (map->offset + offset) >> PAGE_SHIFT,
 				       (map->offset + offset) >> PAGE_SHIFT,
 				       vma->vm_end - vma->vm_start,
 				       vma->vm_end - vma->vm_start,
 				       vma->vm_page_prot))
 				       vma->vm_page_prot))
 			return -EAGAIN;
 			return -EAGAIN;
+#else
+		if (remap_pfn_range(vma, vma->vm_start,
+					(map->offset + offset) >> PAGE_SHIFT,
+					vma->vm_end - vma->vm_start,
+					vma->vm_page_prot))
+			return -EAGAIN;
+#endif
+
 		DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
 		DRM_DEBUG("   Type = %d; start = 0x%lx, end = 0x%lx,"
 			  " offset = 0x%llx\n",
 			  " offset = 0x%llx\n",
 			  map->type,
 			  map->type,
 			  vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset));
 			  vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset));
+
 		vma->vm_ops = &drm_vm_ops;
 		vma->vm_ops = &drm_vm_ops;
 		break;
 		break;
 	case _DRM_CONSISTENT:
 	case _DRM_CONSISTENT:

+ 3 - 0
drivers/gpu/drm/i2c/Makefile

@@ -2,3 +2,6 @@ ccflags-y := -Iinclude/drm
 
 
 ch7006-y := ch7006_drv.o ch7006_mode.o
 ch7006-y := ch7006_drv.o ch7006_mode.o
 obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
 obj-$(CONFIG_DRM_I2C_CH7006) += ch7006.o
+
+sil164-y := sil164_drv.o
+obj-$(CONFIG_DRM_I2C_SIL164) += sil164.o

+ 20 - 2
drivers/gpu/drm/i2c/ch7006_drv.c

@@ -33,7 +33,7 @@ static void ch7006_encoder_set_config(struct drm_encoder *encoder,
 {
 {
 	struct ch7006_priv *priv = to_ch7006_priv(encoder);
 	struct ch7006_priv *priv = to_ch7006_priv(encoder);
 
 
-	priv->params = params;
+	priv->params = *(struct ch7006_encoder_params *)params;
 }
 }
 
 
 static void ch7006_encoder_destroy(struct drm_encoder *encoder)
 static void ch7006_encoder_destroy(struct drm_encoder *encoder)
@@ -114,7 +114,7 @@ static void ch7006_encoder_mode_set(struct drm_encoder *encoder,
 {
 {
 	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
 	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
 	struct ch7006_priv *priv = to_ch7006_priv(encoder);
 	struct ch7006_priv *priv = to_ch7006_priv(encoder);
-	struct ch7006_encoder_params *params = priv->params;
+	struct ch7006_encoder_params *params = &priv->params;
 	struct ch7006_state *state = &priv->state;
 	struct ch7006_state *state = &priv->state;
 	uint8_t *regs = state->regs;
 	uint8_t *regs = state->regs;
 	struct ch7006_mode *mode = priv->mode;
 	struct ch7006_mode *mode = priv->mode;
@@ -428,6 +428,22 @@ static int ch7006_remove(struct i2c_client *client)
 	return 0;
 	return 0;
 }
 }
 
 
+static int ch7006_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	ch7006_dbg(client, "\n");
+
+	return 0;
+}
+
+static int ch7006_resume(struct i2c_client *client)
+{
+	ch7006_dbg(client, "\n");
+
+	ch7006_write(client, 0x3d, 0x0);
+
+	return 0;
+}
+
 static int ch7006_encoder_init(struct i2c_client *client,
 static int ch7006_encoder_init(struct i2c_client *client,
 			       struct drm_device *dev,
 			       struct drm_device *dev,
 			       struct drm_encoder_slave *encoder)
 			       struct drm_encoder_slave *encoder)
@@ -487,6 +503,8 @@ static struct drm_i2c_encoder_driver ch7006_driver = {
 	.i2c_driver = {
 	.i2c_driver = {
 		.probe = ch7006_probe,
 		.probe = ch7006_probe,
 		.remove = ch7006_remove,
 		.remove = ch7006_remove,
+		.suspend = ch7006_suspend,
+		.resume = ch7006_resume,
 
 
 		.driver = {
 		.driver = {
 			.name = "ch7006",
 			.name = "ch7006",

+ 1 - 1
drivers/gpu/drm/i2c/ch7006_priv.h

@@ -77,7 +77,7 @@ struct ch7006_state {
 };
 };
 
 
 struct ch7006_priv {
 struct ch7006_priv {
-	struct ch7006_encoder_params *params;
+	struct ch7006_encoder_params params;
 	struct ch7006_mode *mode;
 	struct ch7006_mode *mode;
 
 
 	struct ch7006_state state;
 	struct ch7006_state state;

+ 462 - 0
drivers/gpu/drm/i2c/sil164_drv.c

@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2010 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#include "drmP.h"
+#include "drm_crtc_helper.h"
+#include "drm_encoder_slave.h"
+#include "i2c/sil164.h"
+
+struct sil164_priv {
+	struct sil164_encoder_params config;
+	struct i2c_client *duallink_slave;
+
+	uint8_t saved_state[0x10];
+	uint8_t saved_slave_state[0x10];
+};
+
+#define to_sil164_priv(x) \
+	((struct sil164_priv *)to_encoder_slave(x)->slave_priv)
+
+#define sil164_dbg(client, format, ...) do {				\
+		if (drm_debug & DRM_UT_KMS)				\
+			dev_printk(KERN_DEBUG, &client->dev,		\
+				   "%s: " format, __func__, ## __VA_ARGS__); \
+	} while (0)
+#define sil164_info(client, format, ...)		\
+	dev_info(&client->dev, format, __VA_ARGS__)
+#define sil164_err(client, format, ...)			\
+	dev_err(&client->dev, format, __VA_ARGS__)
+
+#define SIL164_I2C_ADDR_MASTER			0x38
+#define SIL164_I2C_ADDR_SLAVE			0x39
+
+/* HW register definitions */
+
+#define SIL164_VENDOR_LO			0x0
+#define SIL164_VENDOR_HI			0x1
+#define SIL164_DEVICE_LO			0x2
+#define SIL164_DEVICE_HI			0x3
+#define SIL164_REVISION				0x4
+#define SIL164_FREQ_MIN				0x6
+#define SIL164_FREQ_MAX				0x7
+#define SIL164_CONTROL0				0x8
+#  define SIL164_CONTROL0_POWER_ON		0x01
+#  define SIL164_CONTROL0_EDGE_RISING		0x02
+#  define SIL164_CONTROL0_INPUT_24BIT		0x04
+#  define SIL164_CONTROL0_DUAL_EDGE		0x08
+#  define SIL164_CONTROL0_HSYNC_ON		0x10
+#  define SIL164_CONTROL0_VSYNC_ON		0x20
+#define SIL164_DETECT				0x9
+#  define SIL164_DETECT_INTR_STAT		0x01
+#  define SIL164_DETECT_HOTPLUG_STAT		0x02
+#  define SIL164_DETECT_RECEIVER_STAT		0x04
+#  define SIL164_DETECT_INTR_MODE_RECEIVER	0x00
+#  define SIL164_DETECT_INTR_MODE_HOTPLUG	0x08
+#  define SIL164_DETECT_OUT_MODE_HIGH		0x00
+#  define SIL164_DETECT_OUT_MODE_INTR		0x10
+#  define SIL164_DETECT_OUT_MODE_RECEIVER	0x20
+#  define SIL164_DETECT_OUT_MODE_HOTPLUG	0x30
+#  define SIL164_DETECT_VSWING_STAT		0x80
+#define SIL164_CONTROL1				0xa
+#  define SIL164_CONTROL1_DESKEW_ENABLE		0x10
+#  define SIL164_CONTROL1_DESKEW_INCR_SHIFT	5
+#define SIL164_GPIO				0xb
+#define SIL164_CONTROL2				0xc
+#  define SIL164_CONTROL2_FILTER_ENABLE		0x01
+#  define SIL164_CONTROL2_FILTER_SETTING_SHIFT	1
+#  define SIL164_CONTROL2_DUALLINK_MASTER	0x40
+#  define SIL164_CONTROL2_SYNC_CONT		0x80
+#define SIL164_DUALLINK				0xd
+#  define SIL164_DUALLINK_ENABLE		0x10
+#  define SIL164_DUALLINK_SKEW_SHIFT		5
+#define SIL164_PLLZONE				0xe
+#  define SIL164_PLLZONE_STAT			0x08
+#  define SIL164_PLLZONE_FORCE_ON		0x10
+#  define SIL164_PLLZONE_FORCE_HIGH		0x20
+
+/* HW access functions */
+
+static void
+sil164_write(struct i2c_client *client, uint8_t addr, uint8_t val)
+{
+	uint8_t buf[] = {addr, val};
+	int ret;
+
+	ret = i2c_master_send(client, buf, ARRAY_SIZE(buf));
+	if (ret < 0)
+		sil164_err(client, "Error %d writing to subaddress 0x%x\n",
+			   ret, addr);
+}
+
+static uint8_t
+sil164_read(struct i2c_client *client, uint8_t addr)
+{
+	uint8_t val;
+	int ret;
+
+	ret = i2c_master_send(client, &addr, sizeof(addr));
+	if (ret < 0)
+		goto fail;
+
+	ret = i2c_master_recv(client, &val, sizeof(val));
+	if (ret < 0)
+		goto fail;
+
+	return val;
+
+fail:
+	sil164_err(client, "Error %d reading from subaddress 0x%x\n",
+		   ret, addr);
+	return 0;
+}
+
+static void
+sil164_save_state(struct i2c_client *client, uint8_t *state)
+{
+	int i;
+
+	for (i = 0x8; i <= 0xe; i++)
+		state[i] = sil164_read(client, i);
+}
+
+static void
+sil164_restore_state(struct i2c_client *client, uint8_t *state)
+{
+	int i;
+
+	for (i = 0x8; i <= 0xe; i++)
+		sil164_write(client, i, state[i]);
+}
+
+static void
+sil164_set_power_state(struct i2c_client *client, bool on)
+{
+	uint8_t control0 = sil164_read(client, SIL164_CONTROL0);
+
+	if (on)
+		control0 |= SIL164_CONTROL0_POWER_ON;
+	else
+		control0 &= ~SIL164_CONTROL0_POWER_ON;
+
+	sil164_write(client, SIL164_CONTROL0, control0);
+}
+
+static void
+sil164_init_state(struct i2c_client *client,
+		  struct sil164_encoder_params *config,
+		  bool duallink)
+{
+	sil164_write(client, SIL164_CONTROL0,
+		     SIL164_CONTROL0_HSYNC_ON |
+		     SIL164_CONTROL0_VSYNC_ON |
+		     (config->input_edge ? SIL164_CONTROL0_EDGE_RISING : 0) |
+		     (config->input_width ? SIL164_CONTROL0_INPUT_24BIT : 0) |
+		     (config->input_dual ? SIL164_CONTROL0_DUAL_EDGE : 0));
+
+	sil164_write(client, SIL164_DETECT,
+		     SIL164_DETECT_INTR_STAT |
+		     SIL164_DETECT_OUT_MODE_RECEIVER);
+
+	sil164_write(client, SIL164_CONTROL1,
+		     (config->input_skew ? SIL164_CONTROL1_DESKEW_ENABLE : 0) |
+		     (((config->input_skew + 4) & 0x7)
+		      << SIL164_CONTROL1_DESKEW_INCR_SHIFT));
+
+	sil164_write(client, SIL164_CONTROL2,
+		     SIL164_CONTROL2_SYNC_CONT |
+		     (config->pll_filter ? 0 : SIL164_CONTROL2_FILTER_ENABLE) |
+		     (4 << SIL164_CONTROL2_FILTER_SETTING_SHIFT));
+
+	sil164_write(client, SIL164_PLLZONE, 0);
+
+	if (duallink)
+		sil164_write(client, SIL164_DUALLINK,
+			     SIL164_DUALLINK_ENABLE |
+			     (((config->duallink_skew + 4) & 0x7)
+			      << SIL164_DUALLINK_SKEW_SHIFT));
+	else
+		sil164_write(client, SIL164_DUALLINK, 0);
+}
+
+/* DRM encoder functions */
+
+static void
+sil164_encoder_set_config(struct drm_encoder *encoder, void *params)
+{
+	struct sil164_priv *priv = to_sil164_priv(encoder);
+
+	priv->config = *(struct sil164_encoder_params *)params;
+}
+
+static void
+sil164_encoder_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct sil164_priv *priv = to_sil164_priv(encoder);
+	bool on = (mode == DRM_MODE_DPMS_ON);
+	bool duallink = (on && encoder->crtc->mode.clock > 165000);
+
+	sil164_set_power_state(drm_i2c_encoder_get_client(encoder), on);
+
+	if (priv->duallink_slave)
+		sil164_set_power_state(priv->duallink_slave, duallink);
+}
+
+static void
+sil164_encoder_save(struct drm_encoder *encoder)
+{
+	struct sil164_priv *priv = to_sil164_priv(encoder);
+
+	sil164_save_state(drm_i2c_encoder_get_client(encoder),
+			  priv->saved_state);
+
+	if (priv->duallink_slave)
+		sil164_save_state(priv->duallink_slave,
+				  priv->saved_slave_state);
+}
+
+static void
+sil164_encoder_restore(struct drm_encoder *encoder)
+{
+	struct sil164_priv *priv = to_sil164_priv(encoder);
+
+	sil164_restore_state(drm_i2c_encoder_get_client(encoder),
+			     priv->saved_state);
+
+	if (priv->duallink_slave)
+		sil164_restore_state(priv->duallink_slave,
+				     priv->saved_slave_state);
+}
+
+static bool
+sil164_encoder_mode_fixup(struct drm_encoder *encoder,
+			  struct drm_display_mode *mode,
+			  struct drm_display_mode *adjusted_mode)
+{
+	return true;
+}
+
+static int
+sil164_encoder_mode_valid(struct drm_encoder *encoder,
+			  struct drm_display_mode *mode)
+{
+	struct sil164_priv *priv = to_sil164_priv(encoder);
+
+	if (mode->clock < 32000)
+		return MODE_CLOCK_LOW;
+
+	if (mode->clock > 330000 ||
+	    (mode->clock > 165000 && !priv->duallink_slave))
+		return MODE_CLOCK_HIGH;
+
+	return MODE_OK;
+}
+
+static void
+sil164_encoder_mode_set(struct drm_encoder *encoder,
+			struct drm_display_mode *mode,
+			struct drm_display_mode *adjusted_mode)
+{
+	struct sil164_priv *priv = to_sil164_priv(encoder);
+	bool duallink = adjusted_mode->clock > 165000;
+
+	sil164_init_state(drm_i2c_encoder_get_client(encoder),
+			  &priv->config, duallink);
+
+	if (priv->duallink_slave)
+		sil164_init_state(priv->duallink_slave,
+				  &priv->config, duallink);
+
+	sil164_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
+}
+
+static enum drm_connector_status
+sil164_encoder_detect(struct drm_encoder *encoder,
+		      struct drm_connector *connector)
+{
+	struct i2c_client *client = drm_i2c_encoder_get_client(encoder);
+
+	if (sil164_read(client, SIL164_DETECT) & SIL164_DETECT_HOTPLUG_STAT)
+		return connector_status_connected;
+	else
+		return connector_status_disconnected;
+}
+
+static int
+sil164_encoder_get_modes(struct drm_encoder *encoder,
+			 struct drm_connector *connector)
+{
+	return 0;
+}
+
+static int
+sil164_encoder_create_resources(struct drm_encoder *encoder,
+				struct drm_connector *connector)
+{
+	return 0;
+}
+
+static int
+sil164_encoder_set_property(struct drm_encoder *encoder,
+			    struct drm_connector *connector,
+			    struct drm_property *property,
+			    uint64_t val)
+{
+	return 0;
+}
+
+static void
+sil164_encoder_destroy(struct drm_encoder *encoder)
+{
+	struct sil164_priv *priv = to_sil164_priv(encoder);
+
+	if (priv->duallink_slave)
+		i2c_unregister_device(priv->duallink_slave);
+
+	kfree(priv);
+	drm_i2c_encoder_destroy(encoder);
+}
+
+static struct drm_encoder_slave_funcs sil164_encoder_funcs = {
+	.set_config = sil164_encoder_set_config,
+	.destroy = sil164_encoder_destroy,
+	.dpms = sil164_encoder_dpms,
+	.save = sil164_encoder_save,
+	.restore = sil164_encoder_restore,
+	.mode_fixup = sil164_encoder_mode_fixup,
+	.mode_valid = sil164_encoder_mode_valid,
+	.mode_set = sil164_encoder_mode_set,
+	.detect = sil164_encoder_detect,
+	.get_modes = sil164_encoder_get_modes,
+	.create_resources = sil164_encoder_create_resources,
+	.set_property = sil164_encoder_set_property,
+};
+
+/* I2C driver functions */
+
+static int
+sil164_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+	int vendor = sil164_read(client, SIL164_VENDOR_HI) << 8 |
+		sil164_read(client, SIL164_VENDOR_LO);
+	int device = sil164_read(client, SIL164_DEVICE_HI) << 8 |
+		sil164_read(client, SIL164_DEVICE_LO);
+	int rev = sil164_read(client, SIL164_REVISION);
+
+	if (vendor != 0x1 || device != 0x6) {
+		sil164_dbg(client, "Unknown device %x:%x.%x\n",
+			   vendor, device, rev);
+		return -ENODEV;
+	}
+
+	sil164_info(client, "Detected device %x:%x.%x\n",
+		    vendor, device, rev);
+
+	return 0;
+}
+
+static int
+sil164_remove(struct i2c_client *client)
+{
+	return 0;
+}
+
+static struct i2c_client *
+sil164_detect_slave(struct i2c_client *client)
+{
+	struct i2c_adapter *adap = client->adapter;
+	struct i2c_msg msg = {
+		.addr = SIL164_I2C_ADDR_SLAVE,
+		.len = 0,
+	};
+	const struct i2c_board_info info = {
+		I2C_BOARD_INFO("sil164", SIL164_I2C_ADDR_SLAVE)
+	};
+
+	if (i2c_transfer(adap, &msg, 1) != 1) {
+		sil164_dbg(adap, "No dual-link slave found.");
+		return NULL;
+	}
+
+	return i2c_new_device(adap, &info);
+}
+
+static int
+sil164_encoder_init(struct i2c_client *client,
+		    struct drm_device *dev,
+		    struct drm_encoder_slave *encoder)
+{
+	struct sil164_priv *priv;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	encoder->slave_priv = priv;
+	encoder->slave_funcs = &sil164_encoder_funcs;
+
+	priv->duallink_slave = sil164_detect_slave(client);
+
+	return 0;
+}
+
+static struct i2c_device_id sil164_ids[] = {
+	{ "sil164", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, sil164_ids);
+
+static struct drm_i2c_encoder_driver sil164_driver = {
+	.i2c_driver = {
+		.probe = sil164_probe,
+		.remove = sil164_remove,
+		.driver = {
+			.name = "sil164",
+		},
+		.id_table = sil164_ids,
+	},
+	.encoder_init = sil164_encoder_init,
+};
+
+/* Module initialization */
+
+static int __init
+sil164_init(void)
+{
+	return drm_i2c_encoder_register(THIS_MODULE, &sil164_driver);
+}
+
+static void __exit
+sil164_exit(void)
+{
+	drm_i2c_encoder_unregister(&sil164_driver);
+}
+
+MODULE_AUTHOR("Francisco Jerez <currojerez@riseup.net>");
+MODULE_DESCRIPTION("Silicon Image sil164 TMDS transmitter driver");
+MODULE_LICENSE("GPL and additional rights");
+
+module_init(sil164_init);
+module_exit(sil164_exit);

+ 67 - 58
drivers/gpu/drm/i810/i810_dma.c

@@ -37,6 +37,7 @@
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/pagemap.h>
 
 
 #define I810_BUF_FREE		2
 #define I810_BUF_FREE		2
@@ -60,9 +61,8 @@ static struct drm_buf *i810_freelist_get(struct drm_device * dev)
 		/* In use is already a pointer */
 		/* In use is already a pointer */
 		used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
 		used = cmpxchg(buf_priv->in_use, I810_BUF_FREE,
 			       I810_BUF_CLIENT);
 			       I810_BUF_CLIENT);
-		if (used == I810_BUF_FREE) {
+		if (used == I810_BUF_FREE)
 			return buf;
 			return buf;
-		}
 	}
 	}
 	return NULL;
 	return NULL;
 }
 }
@@ -71,7 +71,7 @@ static struct drm_buf *i810_freelist_get(struct drm_device * dev)
  * yet, the hardware updates in use for us once its on the ring buffer.
  * yet, the hardware updates in use for us once its on the ring buffer.
  */
  */
 
 
-static int i810_freelist_put(struct drm_device * dev, struct drm_buf * buf)
+static int i810_freelist_put(struct drm_device *dev, struct drm_buf *buf)
 {
 {
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	int used;
 	int used;
@@ -121,7 +121,7 @@ static const struct file_operations i810_buffer_fops = {
 	.fasync = drm_fasync,
 	.fasync = drm_fasync,
 };
 };
 
 
-static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
+static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
 {
 {
 	struct drm_device *dev = file_priv->minor->dev;
 	struct drm_device *dev = file_priv->minor->dev;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
@@ -152,7 +152,7 @@ static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
 	return retcode;
 	return retcode;
 }
 }
 
 
-static int i810_unmap_buffer(struct drm_buf * buf)
+static int i810_unmap_buffer(struct drm_buf *buf)
 {
 {
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	int retcode = 0;
 	int retcode = 0;
@@ -172,7 +172,7 @@ static int i810_unmap_buffer(struct drm_buf * buf)
 	return retcode;
 	return retcode;
 }
 }
 
 
-static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
+static int i810_dma_get_buffer(struct drm_device *dev, drm_i810_dma_t *d,
 			       struct drm_file *file_priv)
 			       struct drm_file *file_priv)
 {
 {
 	struct drm_buf *buf;
 	struct drm_buf *buf;
@@ -202,7 +202,7 @@ static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d,
 	return retcode;
 	return retcode;
 }
 }
 
 
-static int i810_dma_cleanup(struct drm_device * dev)
+static int i810_dma_cleanup(struct drm_device *dev)
 {
 {
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
 
 
@@ -218,9 +218,8 @@ static int i810_dma_cleanup(struct drm_device * dev)
 		drm_i810_private_t *dev_priv =
 		drm_i810_private_t *dev_priv =
 		    (drm_i810_private_t *) dev->dev_private;
 		    (drm_i810_private_t *) dev->dev_private;
 
 
-		if (dev_priv->ring.virtual_start) {
+		if (dev_priv->ring.virtual_start)
 			drm_core_ioremapfree(&dev_priv->ring.map, dev);
 			drm_core_ioremapfree(&dev_priv->ring.map, dev);
-		}
 		if (dev_priv->hw_status_page) {
 		if (dev_priv->hw_status_page) {
 			pci_free_consistent(dev->pdev, PAGE_SIZE,
 			pci_free_consistent(dev->pdev, PAGE_SIZE,
 					    dev_priv->hw_status_page,
 					    dev_priv->hw_status_page,
@@ -242,7 +241,7 @@ static int i810_dma_cleanup(struct drm_device * dev)
 	return 0;
 	return 0;
 }
 }
 
 
-static int i810_wait_ring(struct drm_device * dev, int n)
+static int i810_wait_ring(struct drm_device *dev, int n)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
 	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -271,11 +270,11 @@ static int i810_wait_ring(struct drm_device * dev, int n)
 		udelay(1);
 		udelay(1);
 	}
 	}
 
 
-      out_wait_ring:
+out_wait_ring:
 	return iters;
 	return iters;
 }
 }
 
 
-static void i810_kernel_lost_context(struct drm_device * dev)
+static void i810_kernel_lost_context(struct drm_device *dev)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
 	drm_i810_ring_buffer_t *ring = &(dev_priv->ring);
@@ -287,7 +286,7 @@ static void i810_kernel_lost_context(struct drm_device * dev)
 		ring->space += ring->Size;
 		ring->space += ring->Size;
 }
 }
 
 
-static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_priv)
+static int i810_freelist_init(struct drm_device *dev, drm_i810_private_t *dev_priv)
 {
 {
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
 	int my_idx = 24;
 	int my_idx = 24;
@@ -322,9 +321,9 @@ static int i810_freelist_init(struct drm_device * dev, drm_i810_private_t * dev_
 	return 0;
 	return 0;
 }
 }
 
 
-static int i810_dma_initialize(struct drm_device * dev,
-			       drm_i810_private_t * dev_priv,
-			       drm_i810_init_t * init)
+static int i810_dma_initialize(struct drm_device *dev,
+			       drm_i810_private_t *dev_priv,
+			       drm_i810_init_t *init)
 {
 {
 	struct drm_map_list *r_list;
 	struct drm_map_list *r_list;
 	memset(dev_priv, 0, sizeof(drm_i810_private_t));
 	memset(dev_priv, 0, sizeof(drm_i810_private_t));
@@ -462,7 +461,7 @@ static int i810_dma_init(struct drm_device *dev, void *data,
  * Use 'volatile' & local var tmp to force the emitted values to be
  * Use 'volatile' & local var tmp to force the emitted values to be
  * identical to the verified ones.
  * identical to the verified ones.
  */
  */
-static void i810EmitContextVerified(struct drm_device * dev,
+static void i810EmitContextVerified(struct drm_device *dev,
 				    volatile unsigned int *code)
 				    volatile unsigned int *code)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -495,7 +494,7 @@ static void i810EmitContextVerified(struct drm_device * dev,
 	ADVANCE_LP_RING();
 	ADVANCE_LP_RING();
 }
 }
 
 
-static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *code)
+static void i810EmitTexVerified(struct drm_device *dev, volatile unsigned int *code)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	int i, j = 0;
@@ -528,7 +527,7 @@ static void i810EmitTexVerified(struct drm_device * dev, volatile unsigned int *
 
 
 /* Need to do some additional checking when setting the dest buffer.
 /* Need to do some additional checking when setting the dest buffer.
  */
  */
-static void i810EmitDestVerified(struct drm_device * dev,
+static void i810EmitDestVerified(struct drm_device *dev,
 				 volatile unsigned int *code)
 				 volatile unsigned int *code)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -563,7 +562,7 @@ static void i810EmitDestVerified(struct drm_device * dev,
 	ADVANCE_LP_RING();
 	ADVANCE_LP_RING();
 }
 }
 
 
-static void i810EmitState(struct drm_device * dev)
+static void i810EmitState(struct drm_device *dev)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -594,7 +593,7 @@ static void i810EmitState(struct drm_device * dev)
 
 
 /* need to verify
 /* need to verify
  */
  */
-static void i810_dma_dispatch_clear(struct drm_device * dev, int flags,
+static void i810_dma_dispatch_clear(struct drm_device *dev, int flags,
 				    unsigned int clear_color,
 				    unsigned int clear_color,
 				    unsigned int clear_zval)
 				    unsigned int clear_zval)
 {
 {
@@ -669,7 +668,7 @@ static void i810_dma_dispatch_clear(struct drm_device * dev, int flags,
 	}
 	}
 }
 }
 
 
-static void i810_dma_dispatch_swap(struct drm_device * dev)
+static void i810_dma_dispatch_swap(struct drm_device *dev)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_i810_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -715,8 +714,8 @@ static void i810_dma_dispatch_swap(struct drm_device * dev)
 	}
 	}
 }
 }
 
 
-static void i810_dma_dispatch_vertex(struct drm_device * dev,
-				     struct drm_buf * buf, int discard, int used)
+static void i810_dma_dispatch_vertex(struct drm_device *dev,
+				     struct drm_buf *buf, int discard, int used)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
@@ -795,7 +794,7 @@ static void i810_dma_dispatch_vertex(struct drm_device * dev,
 	}
 	}
 }
 }
 
 
-static void i810_dma_dispatch_flip(struct drm_device * dev)
+static void i810_dma_dispatch_flip(struct drm_device *dev)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	int pitch = dev_priv->pitch;
 	int pitch = dev_priv->pitch;
@@ -841,7 +840,7 @@ static void i810_dma_dispatch_flip(struct drm_device * dev)
 
 
 }
 }
 
 
-static void i810_dma_quiescent(struct drm_device * dev)
+static void i810_dma_quiescent(struct drm_device *dev)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
 	RING_LOCALS;
@@ -858,7 +857,7 @@ static void i810_dma_quiescent(struct drm_device * dev)
 	i810_wait_ring(dev, dev_priv->ring.Size - 8);
 	i810_wait_ring(dev, dev_priv->ring.Size - 8);
 }
 }
 
 
-static int i810_flush_queue(struct drm_device * dev)
+static int i810_flush_queue(struct drm_device *dev)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
@@ -891,7 +890,7 @@ static int i810_flush_queue(struct drm_device * dev)
 }
 }
 
 
 /* Must be called with the lock held */
 /* Must be called with the lock held */
-static void i810_reclaim_buffers(struct drm_device * dev,
+static void i810_reclaim_buffers(struct drm_device *dev,
 				 struct drm_file *file_priv)
 				 struct drm_file *file_priv)
 {
 {
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
@@ -969,9 +968,8 @@ static int i810_clear_bufs(struct drm_device *dev, void *data,
 	LOCK_TEST_WITH_RETURN(dev, file_priv);
 	LOCK_TEST_WITH_RETURN(dev, file_priv);
 
 
 	/* GH: Someone's doing nasty things... */
 	/* GH: Someone's doing nasty things... */
-	if (!dev->dev_private) {
+	if (!dev->dev_private)
 		return -EINVAL;
 		return -EINVAL;
-	}
 
 
 	i810_dma_dispatch_clear(dev, clear->flags,
 	i810_dma_dispatch_clear(dev, clear->flags,
 				clear->clear_color, clear->clear_depth);
 				clear->clear_color, clear->clear_depth);
@@ -1039,7 +1037,7 @@ static int i810_docopy(struct drm_device *dev, void *data,
 	return 0;
 	return 0;
 }
 }
 
 
-static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, int used,
+static void i810_dma_dispatch_mc(struct drm_device *dev, struct drm_buf *buf, int used,
 				 unsigned int last_render)
 				 unsigned int last_render)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
@@ -1053,9 +1051,8 @@ static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf,
 	i810_kernel_lost_context(dev);
 	i810_kernel_lost_context(dev);
 
 
 	u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE);
 	u = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_HARDWARE);
-	if (u != I810_BUF_CLIENT) {
+	if (u != I810_BUF_CLIENT)
 		DRM_DEBUG("MC found buffer that isn't mine!\n");
 		DRM_DEBUG("MC found buffer that isn't mine!\n");
-	}
 
 
 	if (used > 4 * 1024)
 	if (used > 4 * 1024)
 		used = 0;
 		used = 0;
@@ -1160,7 +1157,7 @@ static int i810_ov0_flip(struct drm_device *dev, void *data,
 
 
 	LOCK_TEST_WITH_RETURN(dev, file_priv);
 	LOCK_TEST_WITH_RETURN(dev, file_priv);
 
 
-	//Tell the overlay to update
+	/* Tell the overlay to update */
 	I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);
 	I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000);
 
 
 	return 0;
 	return 0;
@@ -1168,7 +1165,7 @@ static int i810_ov0_flip(struct drm_device *dev, void *data,
 
 
 /* Not sure why this isn't set all the time:
 /* Not sure why this isn't set all the time:
  */
  */
-static void i810_do_init_pageflip(struct drm_device * dev)
+static void i810_do_init_pageflip(struct drm_device *dev)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
 
@@ -1178,7 +1175,7 @@ static void i810_do_init_pageflip(struct drm_device * dev)
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 }
 }
 
 
-static int i810_do_cleanup_pageflip(struct drm_device * dev)
+static int i810_do_cleanup_pageflip(struct drm_device *dev)
 {
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
 
@@ -1218,49 +1215,61 @@ int i810_driver_load(struct drm_device *dev, unsigned long flags)
 	return 0;
 	return 0;
 }
 }
 
 
-void i810_driver_lastclose(struct drm_device * dev)
+void i810_driver_lastclose(struct drm_device *dev)
 {
 {
 	i810_dma_cleanup(dev);
 	i810_dma_cleanup(dev);
 }
 }
 
 
-void i810_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
+void i810_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
 {
 {
 	if (dev->dev_private) {
 	if (dev->dev_private) {
 		drm_i810_private_t *dev_priv = dev->dev_private;
 		drm_i810_private_t *dev_priv = dev->dev_private;
-		if (dev_priv->page_flipping) {
+		if (dev_priv->page_flipping)
 			i810_do_cleanup_pageflip(dev);
 			i810_do_cleanup_pageflip(dev);
-		}
 	}
 	}
 }
 }
 
 
-void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
+void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
 					struct drm_file *file_priv)
 					struct drm_file *file_priv)
 {
 {
 	i810_reclaim_buffers(dev, file_priv);
 	i810_reclaim_buffers(dev, file_priv);
 }
 }
 
 
-int i810_driver_dma_quiescent(struct drm_device * dev)
+int i810_driver_dma_quiescent(struct drm_device *dev)
 {
 {
 	i810_dma_quiescent(dev);
 	i810_dma_quiescent(dev);
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * call the drm_ioctl under the big kernel lock because
+ * to lock against the i810_mmap_buffers function.
+ */
+long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+	lock_kernel();
+	ret = drm_ioctl(file, cmd, arg);
+	unlock_kernel();
+	return ret;
+}
+
 struct drm_ioctl_desc i810_ioctls[] = {
 struct drm_ioctl_desc i810_ioctls[] = {
-	DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH)
+	DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
 };
 };
 
 
 int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
 int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
@@ -1276,7 +1285,7 @@ int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
  * \returns
  * \returns
  * A value of 1 is always retured to indictate every i810 is AGP.
  * A value of 1 is always retured to indictate every i810 is AGP.
  */
  */
-int i810_driver_device_is_agp(struct drm_device * dev)
+int i810_driver_device_is_agp(struct drm_device *dev)
 {
 {
 	return 1;
 	return 1;
 }
 }

+ 1 - 1
drivers/gpu/drm/i810/i810_drv.c

@@ -59,7 +59,7 @@ static struct drm_driver driver = {
 		 .owner = THIS_MODULE,
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .open = drm_open,
 		 .release = drm_release,
 		 .release = drm_release,
-		 .unlocked_ioctl = drm_ioctl,
+		 .unlocked_ioctl = i810_ioctl,
 		 .mmap = drm_mmap,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
 		 .fasync = drm_fasync,

+ 34 - 31
drivers/gpu/drm/i810/i810_drv.h

@@ -115,56 +115,59 @@ typedef struct drm_i810_private {
 } drm_i810_private_t;
 } drm_i810_private_t;
 
 
 				/* i810_dma.c */
 				/* i810_dma.c */
-extern int i810_driver_dma_quiescent(struct drm_device * dev);
-extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
+extern int i810_driver_dma_quiescent(struct drm_device *dev);
+extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
 					       struct drm_file *file_priv);
 					       struct drm_file *file_priv);
 extern int i810_driver_load(struct drm_device *, unsigned long flags);
 extern int i810_driver_load(struct drm_device *, unsigned long flags);
-extern void i810_driver_lastclose(struct drm_device * dev);
-extern void i810_driver_preclose(struct drm_device * dev,
+extern void i810_driver_lastclose(struct drm_device *dev);
+extern void i810_driver_preclose(struct drm_device *dev,
 				 struct drm_file *file_priv);
 				 struct drm_file *file_priv);
-extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev,
+extern void i810_driver_reclaim_buffers_locked(struct drm_device *dev,
 					       struct drm_file *file_priv);
 					       struct drm_file *file_priv);
-extern int i810_driver_device_is_agp(struct drm_device * dev);
+extern int i810_driver_device_is_agp(struct drm_device *dev);
 
 
+extern long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 extern struct drm_ioctl_desc i810_ioctls[];
 extern struct drm_ioctl_desc i810_ioctls[];
 extern int i810_max_ioctl;
 extern int i810_max_ioctl;
 
 
 #define I810_BASE(reg)		((unsigned long) \
 #define I810_BASE(reg)		((unsigned long) \
 				dev_priv->mmio_map->handle)
 				dev_priv->mmio_map->handle)
 #define I810_ADDR(reg)		(I810_BASE(reg) + reg)
 #define I810_ADDR(reg)		(I810_BASE(reg) + reg)
-#define I810_DEREF(reg)		*(__volatile__ int *)I810_ADDR(reg)
+#define I810_DEREF(reg)		(*(__volatile__ int *)I810_ADDR(reg))
 #define I810_READ(reg)		I810_DEREF(reg)
 #define I810_READ(reg)		I810_DEREF(reg)
-#define I810_WRITE(reg,val)	do { I810_DEREF(reg) = val; } while (0)
-#define I810_DEREF16(reg)	*(__volatile__ u16 *)I810_ADDR(reg)
+#define I810_WRITE(reg, val)	do { I810_DEREF(reg) = val; } while (0)
+#define I810_DEREF16(reg)	(*(__volatile__ u16 *)I810_ADDR(reg))
 #define I810_READ16(reg)	I810_DEREF16(reg)
 #define I810_READ16(reg)	I810_DEREF16(reg)
-#define I810_WRITE16(reg,val)	do { I810_DEREF16(reg) = val; } while (0)
+#define I810_WRITE16(reg, val)	do { I810_DEREF16(reg) = val; } while (0)
 
 
 #define I810_VERBOSE 0
 #define I810_VERBOSE 0
 #define RING_LOCALS	unsigned int outring, ringmask; \
 #define RING_LOCALS	unsigned int outring, ringmask; \
-                        volatile char *virt;
-
-#define BEGIN_LP_RING(n) do {						\
-	if (I810_VERBOSE)                                               \
-		DRM_DEBUG("BEGIN_LP_RING(%d)\n", n);			\
-	if (dev_priv->ring.space < n*4)					\
-		i810_wait_ring(dev, n*4);				\
-	dev_priv->ring.space -= n*4;					\
-	outring = dev_priv->ring.tail;					\
-	ringmask = dev_priv->ring.tail_mask;				\
-	virt = dev_priv->ring.virtual_start;				\
+			volatile char *virt;
+
+#define BEGIN_LP_RING(n) do {					\
+	if (I810_VERBOSE)					\
+		DRM_DEBUG("BEGIN_LP_RING(%d)\n", n);		\
+	if (dev_priv->ring.space < n*4)				\
+		i810_wait_ring(dev, n*4);			\
+	dev_priv->ring.space -= n*4;				\
+	outring = dev_priv->ring.tail;				\
+	ringmask = dev_priv->ring.tail_mask;			\
+	virt = dev_priv->ring.virtual_start;			\
 } while (0)
 } while (0)
 
 
-#define ADVANCE_LP_RING() do {				        \
-	if (I810_VERBOSE) DRM_DEBUG("ADVANCE_LP_RING\n");	\
+#define ADVANCE_LP_RING() do {					\
+	if (I810_VERBOSE)					\
+		DRM_DEBUG("ADVANCE_LP_RING\n");			\
 	dev_priv->ring.tail = outring;				\
 	dev_priv->ring.tail = outring;				\
-	I810_WRITE(LP_RING + RING_TAIL, outring);	        \
-} while(0)
-
-#define OUT_RING(n) do {				                \
-	if (I810_VERBOSE) DRM_DEBUG("   OUT_RING %x\n", (int)(n));	\
-	*(volatile unsigned int *)(virt + outring) = n;	                \
-	outring += 4;					                \
-	outring &= ringmask;			                        \
+	I810_WRITE(LP_RING + RING_TAIL, outring);		\
+} while (0)
+
+#define OUT_RING(n) do {					\
+	if (I810_VERBOSE)					\
+		DRM_DEBUG("   OUT_RING %x\n", (int)(n));	\
+	*(volatile unsigned int *)(virt + outring) = n;		\
+	outring += 4;						\
+	outring &= ringmask;					\
 } while (0)
 } while (0)
 
 
 #define GFX_OP_USER_INTERRUPT		((0<<29)|(2<<23))
 #define GFX_OP_USER_INTERRUPT		((0<<29)|(2<<23))

+ 72 - 65
drivers/gpu/drm/i830/i830_dma.c

@@ -36,6 +36,7 @@
 #include "i830_drm.h"
 #include "i830_drm.h"
 #include "i830_drv.h"
 #include "i830_drv.h"
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/interrupt.h>	/* For task queue support */
+#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 #include <linux/pagemap.h>
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -62,9 +63,8 @@ static struct drm_buf *i830_freelist_get(struct drm_device * dev)
 		/* In use is already a pointer */
 		/* In use is already a pointer */
 		used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
 		used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
 			       I830_BUF_CLIENT);
 			       I830_BUF_CLIENT);
-		if (used == I830_BUF_FREE) {
+		if (used == I830_BUF_FREE)
 			return buf;
 			return buf;
-		}
 	}
 	}
 	return NULL;
 	return NULL;
 }
 }
@@ -73,7 +73,7 @@ static struct drm_buf *i830_freelist_get(struct drm_device * dev)
  * yet, the hardware updates in use for us once its on the ring buffer.
  * yet, the hardware updates in use for us once its on the ring buffer.
  */
  */
 
 
-static int i830_freelist_put(struct drm_device * dev, struct drm_buf * buf)
+static int i830_freelist_put(struct drm_device *dev, struct drm_buf *buf)
 {
 {
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	int used;
 	int used;
@@ -123,7 +123,7 @@ static const struct file_operations i830_buffer_fops = {
 	.fasync = drm_fasync,
 	.fasync = drm_fasync,
 };
 };
 
 
-static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
+static int i830_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
 {
 {
 	struct drm_device *dev = file_priv->minor->dev;
 	struct drm_device *dev = file_priv->minor->dev;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
@@ -156,7 +156,7 @@ static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv)
 	return retcode;
 	return retcode;
 }
 }
 
 
-static int i830_unmap_buffer(struct drm_buf * buf)
+static int i830_unmap_buffer(struct drm_buf *buf)
 {
 {
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	int retcode = 0;
 	int retcode = 0;
@@ -176,7 +176,7 @@ static int i830_unmap_buffer(struct drm_buf * buf)
 	return retcode;
 	return retcode;
 }
 }
 
 
-static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d,
+static int i830_dma_get_buffer(struct drm_device *dev, drm_i830_dma_t *d,
 			       struct drm_file *file_priv)
 			       struct drm_file *file_priv)
 {
 {
 	struct drm_buf *buf;
 	struct drm_buf *buf;
@@ -206,7 +206,7 @@ static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d,
 	return retcode;
 	return retcode;
 }
 }
 
 
-static int i830_dma_cleanup(struct drm_device * dev)
+static int i830_dma_cleanup(struct drm_device *dev)
 {
 {
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
 
 
@@ -222,9 +222,8 @@ static int i830_dma_cleanup(struct drm_device * dev)
 		drm_i830_private_t *dev_priv =
 		drm_i830_private_t *dev_priv =
 		    (drm_i830_private_t *) dev->dev_private;
 		    (drm_i830_private_t *) dev->dev_private;
 
 
-		if (dev_priv->ring.virtual_start) {
+		if (dev_priv->ring.virtual_start)
 			drm_core_ioremapfree(&dev_priv->ring.map, dev);
 			drm_core_ioremapfree(&dev_priv->ring.map, dev);
-		}
 		if (dev_priv->hw_status_page) {
 		if (dev_priv->hw_status_page) {
 			pci_free_consistent(dev->pdev, PAGE_SIZE,
 			pci_free_consistent(dev->pdev, PAGE_SIZE,
 					    dev_priv->hw_status_page,
 					    dev_priv->hw_status_page,
@@ -246,7 +245,7 @@ static int i830_dma_cleanup(struct drm_device * dev)
 	return 0;
 	return 0;
 }
 }
 
 
-int i830_wait_ring(struct drm_device * dev, int n, const char *caller)
+int i830_wait_ring(struct drm_device *dev, int n, const char *caller)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
 	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -276,11 +275,11 @@ int i830_wait_ring(struct drm_device * dev, int n, const char *caller)
 		dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
 		dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
 	}
 	}
 
 
-      out_wait_ring:
+out_wait_ring:
 	return iters;
 	return iters;
 }
 }
 
 
-static void i830_kernel_lost_context(struct drm_device * dev)
+static void i830_kernel_lost_context(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
 	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
@@ -295,7 +294,7 @@ static void i830_kernel_lost_context(struct drm_device * dev)
 		dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
 		dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
 }
 }
 
 
-static int i830_freelist_init(struct drm_device * dev, drm_i830_private_t * dev_priv)
+static int i830_freelist_init(struct drm_device *dev, drm_i830_private_t *dev_priv)
 {
 {
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
 	int my_idx = 36;
 	int my_idx = 36;
@@ -329,9 +328,9 @@ static int i830_freelist_init(struct drm_device * dev, drm_i830_private_t * dev_
 	return 0;
 	return 0;
 }
 }
 
 
-static int i830_dma_initialize(struct drm_device * dev,
-			       drm_i830_private_t * dev_priv,
-			       drm_i830_init_t * init)
+static int i830_dma_initialize(struct drm_device *dev,
+			       drm_i830_private_t *dev_priv,
+			       drm_i830_init_t *init)
 {
 {
 	struct drm_map_list *r_list;
 	struct drm_map_list *r_list;
 
 
@@ -482,7 +481,7 @@ static int i830_dma_init(struct drm_device *dev, void *data,
 /* Most efficient way to verify state for the i830 is as it is
 /* Most efficient way to verify state for the i830 is as it is
  * emitted.  Non-conformant state is silently dropped.
  * emitted.  Non-conformant state is silently dropped.
  */
  */
-static void i830EmitContextVerified(struct drm_device * dev, unsigned int *code)
+static void i830EmitContextVerified(struct drm_device *dev, unsigned int *code)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	int i, j = 0;
@@ -527,7 +526,7 @@ static void i830EmitContextVerified(struct drm_device * dev, unsigned int *code)
 	ADVANCE_LP_RING();
 	ADVANCE_LP_RING();
 }
 }
 
 
-static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code)
+static void i830EmitTexVerified(struct drm_device *dev, unsigned int *code)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	int i, j = 0;
 	int i, j = 0;
@@ -561,7 +560,7 @@ static void i830EmitTexVerified(struct drm_device * dev, unsigned int *code)
 		printk("rejected packet %x\n", code[0]);
 		printk("rejected packet %x\n", code[0]);
 }
 }
 
 
-static void i830EmitTexBlendVerified(struct drm_device * dev,
+static void i830EmitTexBlendVerified(struct drm_device *dev,
 				     unsigned int *code, unsigned int num)
 				     unsigned int *code, unsigned int num)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
@@ -586,7 +585,7 @@ static void i830EmitTexBlendVerified(struct drm_device * dev,
 	ADVANCE_LP_RING();
 	ADVANCE_LP_RING();
 }
 }
 
 
-static void i830EmitTexPalette(struct drm_device * dev,
+static void i830EmitTexPalette(struct drm_device *dev,
 			       unsigned int *palette, int number, int is_shared)
 			       unsigned int *palette, int number, int is_shared)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
@@ -603,9 +602,8 @@ static void i830EmitTexPalette(struct drm_device * dev,
 	} else {
 	} else {
 		OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
 		OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
 	}
 	}
-	for (i = 0; i < 256; i++) {
+	for (i = 0; i < 256; i++)
 		OUT_RING(palette[i]);
 		OUT_RING(palette[i]);
-	}
 	OUT_RING(0);
 	OUT_RING(0);
 	/* KW:  WHERE IS THE ADVANCE_LP_RING?  This is effectively a noop!
 	/* KW:  WHERE IS THE ADVANCE_LP_RING?  This is effectively a noop!
 	 */
 	 */
@@ -613,7 +611,7 @@ static void i830EmitTexPalette(struct drm_device * dev,
 
 
 /* Need to do some additional checking when setting the dest buffer.
 /* Need to do some additional checking when setting the dest buffer.
  */
  */
-static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code)
+static void i830EmitDestVerified(struct drm_device *dev, unsigned int *code)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	unsigned int tmp;
 	unsigned int tmp;
@@ -674,7 +672,7 @@ static void i830EmitDestVerified(struct drm_device * dev, unsigned int *code)
 	ADVANCE_LP_RING();
 	ADVANCE_LP_RING();
 }
 }
 
 
-static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code)
+static void i830EmitStippleVerified(struct drm_device *dev, unsigned int *code)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
 	RING_LOCALS;
@@ -685,7 +683,7 @@ static void i830EmitStippleVerified(struct drm_device * dev, unsigned int *code)
 	ADVANCE_LP_RING();
 	ADVANCE_LP_RING();
 }
 }
 
 
-static void i830EmitState(struct drm_device * dev)
+static void i830EmitState(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -788,7 +786,7 @@ static void i830EmitState(struct drm_device * dev)
  * Performance monitoring functions
  * Performance monitoring functions
  */
  */
 
 
-static void i830_fill_box(struct drm_device * dev,
+static void i830_fill_box(struct drm_device *dev,
 			  int x, int y, int w, int h, int r, int g, int b)
 			  int x, int y, int w, int h, int r, int g, int b)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
@@ -816,17 +814,16 @@ static void i830_fill_box(struct drm_device * dev,
 	OUT_RING((y << 16) | x);
 	OUT_RING((y << 16) | x);
 	OUT_RING(((y + h) << 16) | (x + w));
 	OUT_RING(((y + h) << 16) | (x + w));
 
 
-	if (dev_priv->current_page == 1) {
+	if (dev_priv->current_page == 1)
 		OUT_RING(dev_priv->front_offset);
 		OUT_RING(dev_priv->front_offset);
-	} else {
+	else
 		OUT_RING(dev_priv->back_offset);
 		OUT_RING(dev_priv->back_offset);
-	}
 
 
 	OUT_RING(color);
 	OUT_RING(color);
 	ADVANCE_LP_RING();
 	ADVANCE_LP_RING();
 }
 }
 
 
-static void i830_cp_performance_boxes(struct drm_device * dev)
+static void i830_cp_performance_boxes(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
 
@@ -871,7 +868,7 @@ static void i830_cp_performance_boxes(struct drm_device * dev)
 	dev_priv->sarea_priv->perf_boxes = 0;
 	dev_priv->sarea_priv->perf_boxes = 0;
 }
 }
 
 
-static void i830_dma_dispatch_clear(struct drm_device * dev, int flags,
+static void i830_dma_dispatch_clear(struct drm_device *dev, int flags,
 				    unsigned int clear_color,
 				    unsigned int clear_color,
 				    unsigned int clear_zval,
 				    unsigned int clear_zval,
 				    unsigned int clear_depthmask)
 				    unsigned int clear_depthmask)
@@ -966,7 +963,7 @@ static void i830_dma_dispatch_clear(struct drm_device * dev, int flags,
 	}
 	}
 }
 }
 
 
-static void i830_dma_dispatch_swap(struct drm_device * dev)
+static void i830_dma_dispatch_swap(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -1036,7 +1033,7 @@ static void i830_dma_dispatch_swap(struct drm_device * dev)
 	}
 	}
 }
 }
 
 
-static void i830_dma_dispatch_flip(struct drm_device * dev)
+static void i830_dma_dispatch_flip(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
 	RING_LOCALS;
@@ -1079,8 +1076,8 @@ static void i830_dma_dispatch_flip(struct drm_device * dev)
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 }
 }
 
 
-static void i830_dma_dispatch_vertex(struct drm_device * dev,
-				     struct drm_buf * buf, int discard, int used)
+static void i830_dma_dispatch_vertex(struct drm_device *dev,
+				     struct drm_buf *buf, int discard, int used)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
@@ -1100,9 +1097,8 @@ static void i830_dma_dispatch_vertex(struct drm_device * dev,
 	if (discard) {
 	if (discard) {
 		u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
 		u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
 			    I830_BUF_HARDWARE);
 			    I830_BUF_HARDWARE);
-		if (u != I830_BUF_CLIENT) {
+		if (u != I830_BUF_CLIENT)
 			DRM_DEBUG("xxxx 2\n");
 			DRM_DEBUG("xxxx 2\n");
-		}
 	}
 	}
 
 
 	if (used > 4 * 1023)
 	if (used > 4 * 1023)
@@ -1191,7 +1187,7 @@ static void i830_dma_dispatch_vertex(struct drm_device * dev,
 	}
 	}
 }
 }
 
 
-static void i830_dma_quiescent(struct drm_device * dev)
+static void i830_dma_quiescent(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
 	RING_LOCALS;
@@ -1208,7 +1204,7 @@ static void i830_dma_quiescent(struct drm_device * dev)
 	i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
 	i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
 }
 }
 
 
-static int i830_flush_queue(struct drm_device * dev)
+static int i830_flush_queue(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
@@ -1241,7 +1237,7 @@ static int i830_flush_queue(struct drm_device * dev)
 }
 }
 
 
 /* Must be called with the lock held */
 /* Must be called with the lock held */
-static void i830_reclaim_buffers(struct drm_device * dev, struct drm_file *file_priv)
+static void i830_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
 {
 {
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
 	int i;
 	int i;
@@ -1316,9 +1312,8 @@ static int i830_clear_bufs(struct drm_device *dev, void *data,
 	LOCK_TEST_WITH_RETURN(dev, file_priv);
 	LOCK_TEST_WITH_RETURN(dev, file_priv);
 
 
 	/* GH: Someone's doing nasty things... */
 	/* GH: Someone's doing nasty things... */
-	if (!dev->dev_private) {
+	if (!dev->dev_private)
 		return -EINVAL;
 		return -EINVAL;
-	}
 
 
 	i830_dma_dispatch_clear(dev, clear->flags,
 	i830_dma_dispatch_clear(dev, clear->flags,
 				clear->clear_color,
 				clear->clear_color,
@@ -1339,7 +1334,7 @@ static int i830_swap_bufs(struct drm_device *dev, void *data,
 
 
 /* Not sure why this isn't set all the time:
 /* Not sure why this isn't set all the time:
  */
  */
-static void i830_do_init_pageflip(struct drm_device * dev)
+static void i830_do_init_pageflip(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
 
@@ -1349,7 +1344,7 @@ static void i830_do_init_pageflip(struct drm_device * dev)
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 }
 }
 
 
-static int i830_do_cleanup_pageflip(struct drm_device * dev)
+static int i830_do_cleanup_pageflip(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
 
@@ -1490,47 +1485,59 @@ int i830_driver_load(struct drm_device *dev, unsigned long flags)
 	return 0;
 	return 0;
 }
 }
 
 
-void i830_driver_lastclose(struct drm_device * dev)
+void i830_driver_lastclose(struct drm_device *dev)
 {
 {
 	i830_dma_cleanup(dev);
 	i830_dma_cleanup(dev);
 }
 }
 
 
-void i830_driver_preclose(struct drm_device * dev, struct drm_file *file_priv)
+void i830_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
 {
 {
 	if (dev->dev_private) {
 	if (dev->dev_private) {
 		drm_i830_private_t *dev_priv = dev->dev_private;
 		drm_i830_private_t *dev_priv = dev->dev_private;
-		if (dev_priv->page_flipping) {
+		if (dev_priv->page_flipping)
 			i830_do_cleanup_pageflip(dev);
 			i830_do_cleanup_pageflip(dev);
-		}
 	}
 	}
 }
 }
 
 
-void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct drm_file *file_priv)
+void i830_driver_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv)
 {
 {
 	i830_reclaim_buffers(dev, file_priv);
 	i830_reclaim_buffers(dev, file_priv);
 }
 }
 
 
-int i830_driver_dma_quiescent(struct drm_device * dev)
+int i830_driver_dma_quiescent(struct drm_device *dev)
 {
 {
 	i830_dma_quiescent(dev);
 	i830_dma_quiescent(dev);
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * call the drm_ioctl under the big kernel lock because
+ * to lock against the i830_mmap_buffers function.
+ */
+long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+	lock_kernel();
+	ret = drm_ioctl(file, cmd, arg);
+	unlock_kernel();
+	return ret;
+}
+
 struct drm_ioctl_desc i830_ioctls[] = {
 struct drm_ioctl_desc i830_ioctls[] = {
-	DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
-	DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH),
-	DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH)
+	DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED),
 };
 };
 
 
 int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
 int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
@@ -1546,7 +1553,7 @@ int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
  * \returns
  * \returns
  * A value of 1 is always retured to indictate every i8xx is AGP.
  * A value of 1 is always retured to indictate every i8xx is AGP.
  */
  */
-int i830_driver_device_is_agp(struct drm_device * dev)
+int i830_driver_device_is_agp(struct drm_device *dev)
 {
 {
 	return 1;
 	return 1;
 }
 }

+ 1 - 1
drivers/gpu/drm/i830/i830_drv.c

@@ -70,7 +70,7 @@ static struct drm_driver driver = {
 		 .owner = THIS_MODULE,
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .open = drm_open,
 		 .release = drm_release,
 		 .release = drm_release,
-		 .unlocked_ioctl = drm_ioctl,
+		 .unlocked_ioctl = i830_ioctl,
 		 .mmap = drm_mmap,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
 		 .fasync = drm_fasync,

+ 26 - 23
drivers/gpu/drm/i830/i830_drv.h

@@ -122,6 +122,7 @@ typedef struct drm_i830_private {
 
 
 } drm_i830_private_t;
 } drm_i830_private_t;
 
 
+long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 extern struct drm_ioctl_desc i830_ioctls[];
 extern struct drm_ioctl_desc i830_ioctls[];
 extern int i830_max_ioctl;
 extern int i830_max_ioctl;
 
 
@@ -132,33 +133,33 @@ extern int i830_irq_wait(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
 			 struct drm_file *file_priv);
 
 
 extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
 extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i830_driver_irq_preinstall(struct drm_device * dev);
-extern void i830_driver_irq_postinstall(struct drm_device * dev);
-extern void i830_driver_irq_uninstall(struct drm_device * dev);
+extern void i830_driver_irq_preinstall(struct drm_device *dev);
+extern void i830_driver_irq_postinstall(struct drm_device *dev);
+extern void i830_driver_irq_uninstall(struct drm_device *dev);
 extern int i830_driver_load(struct drm_device *, unsigned long flags);
 extern int i830_driver_load(struct drm_device *, unsigned long flags);
-extern void i830_driver_preclose(struct drm_device * dev,
+extern void i830_driver_preclose(struct drm_device *dev,
 				 struct drm_file *file_priv);
 				 struct drm_file *file_priv);
-extern void i830_driver_lastclose(struct drm_device * dev);
-extern void i830_driver_reclaim_buffers_locked(struct drm_device * dev,
+extern void i830_driver_lastclose(struct drm_device *dev);
+extern void i830_driver_reclaim_buffers_locked(struct drm_device *dev,
 					       struct drm_file *file_priv);
 					       struct drm_file *file_priv);
-extern int i830_driver_dma_quiescent(struct drm_device * dev);
-extern int i830_driver_device_is_agp(struct drm_device * dev);
+extern int i830_driver_dma_quiescent(struct drm_device *dev);
+extern int i830_driver_device_is_agp(struct drm_device *dev);
 
 
-#define I830_READ(reg)          DRM_READ32(dev_priv->mmio_map, reg)
-#define I830_WRITE(reg,val)     DRM_WRITE32(dev_priv->mmio_map, reg, val)
-#define I830_READ16(reg)        DRM_READ16(dev_priv->mmio_map, reg)
-#define I830_WRITE16(reg,val)   DRM_WRITE16(dev_priv->mmio_map, reg, val)
+#define I830_READ(reg)		DRM_READ32(dev_priv->mmio_map, reg)
+#define I830_WRITE(reg, val)	DRM_WRITE32(dev_priv->mmio_map, reg, val)
+#define I830_READ16(reg)	DRM_READ16(dev_priv->mmio_map, reg)
+#define I830_WRITE16(reg, val)	DRM_WRITE16(dev_priv->mmio_map, reg, val)
 
 
 #define I830_VERBOSE 0
 #define I830_VERBOSE 0
 
 
 #define RING_LOCALS	unsigned int outring, ringmask, outcount; \
 #define RING_LOCALS	unsigned int outring, ringmask, outcount; \
-                        volatile char *virt;
+			volatile char *virt;
 
 
 #define BEGIN_LP_RING(n) do {				\
 #define BEGIN_LP_RING(n) do {				\
 	if (I830_VERBOSE)				\
 	if (I830_VERBOSE)				\
 		printk("BEGIN_LP_RING(%d)\n", (n));	\
 		printk("BEGIN_LP_RING(%d)\n", (n));	\
 	if (dev_priv->ring.space < n*4)			\
 	if (dev_priv->ring.space < n*4)			\
-		i830_wait_ring(dev, n*4, __func__);		\
+		i830_wait_ring(dev, n*4, __func__);	\
 	outcount = 0;					\
 	outcount = 0;					\
 	outring = dev_priv->ring.tail;			\
 	outring = dev_priv->ring.tail;			\
 	ringmask = dev_priv->ring.tail_mask;		\
 	ringmask = dev_priv->ring.tail_mask;		\
@@ -166,21 +167,23 @@ extern int i830_driver_device_is_agp(struct drm_device * dev);
 } while (0)
 } while (0)
 
 
 #define OUT_RING(n) do {					\
 #define OUT_RING(n) do {					\
-	if (I830_VERBOSE) printk("   OUT_RING %x\n", (int)(n));	\
+	if (I830_VERBOSE)					\
+		printk("   OUT_RING %x\n", (int)(n));		\
 	*(volatile unsigned int *)(virt + outring) = n;		\
 	*(volatile unsigned int *)(virt + outring) = n;		\
-        outcount++;						\
+	outcount++;						\
 	outring += 4;						\
 	outring += 4;						\
 	outring &= ringmask;					\
 	outring &= ringmask;					\
 } while (0)
 } while (0)
 
 
-#define ADVANCE_LP_RING() do {						\
-	if (I830_VERBOSE) printk("ADVANCE_LP_RING %x\n", outring);	\
-	dev_priv->ring.tail = outring;					\
-	dev_priv->ring.space -= outcount * 4;				\
-	I830_WRITE(LP_RING + RING_TAIL, outring);			\
-} while(0)
+#define ADVANCE_LP_RING() do {					\
+	if (I830_VERBOSE)					\
+		printk("ADVANCE_LP_RING %x\n", outring);	\
+	dev_priv->ring.tail = outring;				\
+	dev_priv->ring.space -= outcount * 4;			\
+	I830_WRITE(LP_RING + RING_TAIL, outring);		\
+} while (0)
 
 
-extern int i830_wait_ring(struct drm_device * dev, int n, const char *caller);
+extern int i830_wait_ring(struct drm_device *dev, int n, const char *caller);
 
 
 #define GFX_OP_USER_INTERRUPT		((0<<29)|(2<<23))
 #define GFX_OP_USER_INTERRUPT		((0<<29)|(2<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
 #define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))

+ 5 - 5
drivers/gpu/drm/i830/i830_irq.c

@@ -53,7 +53,7 @@ irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 }
 }
 
 
-static int i830_emit_irq(struct drm_device * dev)
+static int i830_emit_irq(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	RING_LOCALS;
 	RING_LOCALS;
@@ -70,7 +70,7 @@ static int i830_emit_irq(struct drm_device * dev)
 	return atomic_read(&dev_priv->irq_emitted);
 	return atomic_read(&dev_priv->irq_emitted);
 }
 }
 
 
-static int i830_wait_irq(struct drm_device * dev, int irq_nr)
+static int i830_wait_irq(struct drm_device *dev, int irq_nr)
 {
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	DECLARE_WAITQUEUE(entry, current);
 	DECLARE_WAITQUEUE(entry, current);
@@ -156,7 +156,7 @@ int i830_irq_wait(struct drm_device *dev, void *data,
 
 
 /* drm_dma.h hooks
 /* drm_dma.h hooks
 */
 */
-void i830_driver_irq_preinstall(struct drm_device * dev)
+void i830_driver_irq_preinstall(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 
 
@@ -168,14 +168,14 @@ void i830_driver_irq_preinstall(struct drm_device * dev)
 	init_waitqueue_head(&dev_priv->irq_queue);
 	init_waitqueue_head(&dev_priv->irq_queue);
 }
 }
 
 
-void i830_driver_irq_postinstall(struct drm_device * dev)
+void i830_driver_irq_postinstall(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 
 
 	I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
 	I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
 }
 }
 
 
-void i830_driver_irq_uninstall(struct drm_device * dev)
+void i830_driver_irq_uninstall(struct drm_device *dev)
 {
 {
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
 	if (!dev_priv)
 	if (!dev_priv)

+ 17 - 7
drivers/gpu/drm/i915/i915_dma.c

@@ -34,12 +34,15 @@
 #include "i915_drm.h"
 #include "i915_drm.h"
 #include "i915_drv.h"
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "i915_trace.h"
+#include <linux/pci.h>
 #include <linux/vgaarb.h>
 #include <linux/vgaarb.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
 #include <linux/pnp.h>
 #include <linux/pnp.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/vga_switcheroo.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 
 
+extern int intel_max_stolen; /* from AGP driver */
+
 /**
 /**
  * Sets up the hardware status page for devices that need a physical address
  * Sets up the hardware status page for devices that need a physical address
  * in the register.
  * in the register.
@@ -1256,7 +1259,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 		drm_mm_put_block(compressed_fb);
 		drm_mm_put_block(compressed_fb);
 	}
 	}
 
 
-	if (!IS_GM45(dev)) {
+	if (!(IS_GM45(dev) || IS_IRONLAKE_M(dev))) {
 		compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096,
 		compressed_llb = drm_mm_search_free(&dev_priv->vram, 4096,
 						    4096, 0);
 						    4096, 0);
 		if (!compressed_llb) {
 		if (!compressed_llb) {
@@ -1282,8 +1285,9 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 
 
 	intel_disable_fbc(dev);
 	intel_disable_fbc(dev);
 	dev_priv->compressed_fb = compressed_fb;
 	dev_priv->compressed_fb = compressed_fb;
-
-	if (IS_GM45(dev)) {
+	if (IS_IRONLAKE_M(dev))
+		I915_WRITE(ILK_DPFC_CB_BASE, compressed_fb->start);
+	else if (IS_GM45(dev)) {
 		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
 		I915_WRITE(DPFC_CB_BASE, compressed_fb->start);
 	} else {
 	} else {
 		I915_WRITE(FBC_CFB_BASE, cfb_base);
 		I915_WRITE(FBC_CFB_BASE, cfb_base);
@@ -1291,7 +1295,7 @@ static void i915_setup_compression(struct drm_device *dev, int size)
 		dev_priv->compressed_llb = compressed_llb;
 		dev_priv->compressed_llb = compressed_llb;
 	}
 	}
 
 
-	DRM_DEBUG("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
+	DRM_DEBUG_KMS("FBC base 0x%08lx, ll base 0x%08lx, size %dM\n", cfb_base,
 		  ll_base, size >> 20);
 		  ll_base, size >> 20);
 }
 }
 
 
@@ -1354,7 +1358,7 @@ static int i915_load_modeset_init(struct drm_device *dev,
 	int fb_bar = IS_I9XX(dev) ? 2 : 0;
 	int fb_bar = IS_I9XX(dev) ? 2 : 0;
 	int ret = 0;
 	int ret = 0;
 
 
-	dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) &
+	dev->mode_config.fb_base = pci_resource_start(dev->pdev, fb_bar) &
 		0xff000000;
 		0xff000000;
 
 
 	/* Basic memrange allocator for stolen space (aka vram) */
 	/* Basic memrange allocator for stolen space (aka vram) */
@@ -2063,8 +2067,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 
 
 	/* Add register map (needed for suspend/resume) */
 	/* Add register map (needed for suspend/resume) */
 	mmio_bar = IS_I9XX(dev) ? 0 : 1;
 	mmio_bar = IS_I9XX(dev) ? 0 : 1;
-	base = drm_get_resource_start(dev, mmio_bar);
-	size = drm_get_resource_len(dev, mmio_bar);
+	base = pci_resource_start(dev->pdev, mmio_bar);
+	size = pci_resource_len(dev->pdev, mmio_bar);
 
 
 	if (i915_get_bridge_dev(dev)) {
 	if (i915_get_bridge_dev(dev)) {
 		ret = -EIO;
 		ret = -EIO;
@@ -2104,6 +2108,12 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 	if (ret)
 	if (ret)
 		goto out_iomapfree;
 		goto out_iomapfree;
 
 
+	if (prealloc_size > intel_max_stolen) {
+		DRM_INFO("detected %dM stolen memory, trimming to %dM\n",
+			 prealloc_size >> 20, intel_max_stolen >> 20);
+		prealloc_size = intel_max_stolen;
+	}
+
 	dev_priv->wq = create_singlethread_workqueue("i915");
 	dev_priv->wq = create_singlethread_workqueue("i915");
 	if (dev_priv->wq == NULL) {
 	if (dev_priv->wq == NULL) {
 		DRM_ERROR("Failed to create our workqueue.\n");
 		DRM_ERROR("Failed to create our workqueue.\n");

+ 33 - 33
drivers/gpu/drm/i915/i915_drv.c

@@ -93,11 +93,11 @@ static const struct intel_device_info intel_i945gm_info = {
 };
 };
 
 
 static const struct intel_device_info intel_i965g_info = {
 static const struct intel_device_info intel_i965g_info = {
-	.is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
+	.is_broadwater = 1, .is_i965g = 1, .is_i9xx = 1, .has_hotplug = 1,
 };
 };
 
 
 static const struct intel_device_info intel_i965gm_info = {
 static const struct intel_device_info intel_i965gm_info = {
-	.is_i965g = 1, .is_mobile = 1, .is_i965gm = 1, .is_i9xx = 1,
+	.is_crestline = 1, .is_i965g = 1, .is_i965gm = 1, .is_i9xx = 1,
 	.is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
 	.is_mobile = 1, .has_fbc = 1, .has_rc6 = 1,
 	.has_hotplug = 1,
 	.has_hotplug = 1,
 };
 };
@@ -114,7 +114,7 @@ static const struct intel_device_info intel_g45_info = {
 };
 };
 
 
 static const struct intel_device_info intel_gm45_info = {
 static const struct intel_device_info intel_gm45_info = {
-	.is_i965g = 1, .is_mobile = 1, .is_g4x = 1, .is_i9xx = 1,
+	.is_i965g = 1, .is_g4x = 1, .is_i9xx = 1,
 	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
 	.is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
 	.has_pipe_cxsr = 1,
 	.has_pipe_cxsr = 1,
 	.has_hotplug = 1,
 	.has_hotplug = 1,
@@ -134,7 +134,7 @@ static const struct intel_device_info intel_ironlake_d_info = {
 
 
 static const struct intel_device_info intel_ironlake_m_info = {
 static const struct intel_device_info intel_ironlake_m_info = {
 	.is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
 	.is_ironlake = 1, .is_mobile = 1, .is_i965g = 1, .is_i9xx = 1,
-	.need_gfx_hws = 1, .has_rc6 = 1,
+	.need_gfx_hws = 1, .has_fbc = 1, .has_rc6 = 1,
 	.has_hotplug = 1,
 	.has_hotplug = 1,
 };
 };
 
 
@@ -148,33 +148,33 @@ static const struct intel_device_info intel_sandybridge_m_info = {
 	.has_hotplug = 1, .is_gen6 = 1,
 	.has_hotplug = 1, .is_gen6 = 1,
 };
 };
 
 
-static const struct pci_device_id pciidlist[] = {
-	INTEL_VGA_DEVICE(0x3577, &intel_i830_info),
-	INTEL_VGA_DEVICE(0x2562, &intel_845g_info),
-	INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),
+static const struct pci_device_id pciidlist[] = {		/* aka */
+	INTEL_VGA_DEVICE(0x3577, &intel_i830_info),		/* I830_M */
+	INTEL_VGA_DEVICE(0x2562, &intel_845g_info),		/* 845_G */
+	INTEL_VGA_DEVICE(0x3582, &intel_i85x_info),		/* I855_GM */
 	INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
 	INTEL_VGA_DEVICE(0x358e, &intel_i85x_info),
-	INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),
-	INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),
-	INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),
-	INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),
-	INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),
-	INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),
-	INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),
-	INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),
-	INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),
-	INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),
-	INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),
-	INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),
-	INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),
-	INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),
-	INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),
-	INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),
-	INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),
-	INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),
-	INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),
-	INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),
-	INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),
-	INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),
+	INTEL_VGA_DEVICE(0x2572, &intel_i865g_info),		/* I865_G */
+	INTEL_VGA_DEVICE(0x2582, &intel_i915g_info),		/* I915_G */
+	INTEL_VGA_DEVICE(0x258a, &intel_i915g_info),		/* E7221_G */
+	INTEL_VGA_DEVICE(0x2592, &intel_i915gm_info),		/* I915_GM */
+	INTEL_VGA_DEVICE(0x2772, &intel_i945g_info),		/* I945_G */
+	INTEL_VGA_DEVICE(0x27a2, &intel_i945gm_info),		/* I945_GM */
+	INTEL_VGA_DEVICE(0x27ae, &intel_i945gm_info),		/* I945_GME */
+	INTEL_VGA_DEVICE(0x2972, &intel_i965g_info),		/* I946_GZ */
+	INTEL_VGA_DEVICE(0x2982, &intel_i965g_info),		/* G35_G */
+	INTEL_VGA_DEVICE(0x2992, &intel_i965g_info),		/* I965_Q */
+	INTEL_VGA_DEVICE(0x29a2, &intel_i965g_info),		/* I965_G */
+	INTEL_VGA_DEVICE(0x29b2, &intel_g33_info),		/* Q35_G */
+	INTEL_VGA_DEVICE(0x29c2, &intel_g33_info),		/* G33_G */
+	INTEL_VGA_DEVICE(0x29d2, &intel_g33_info),		/* Q33_G */
+	INTEL_VGA_DEVICE(0x2a02, &intel_i965gm_info),		/* I965_GM */
+	INTEL_VGA_DEVICE(0x2a12, &intel_i965gm_info),		/* I965_GME */
+	INTEL_VGA_DEVICE(0x2a42, &intel_gm45_info),		/* GM45_G */
+	INTEL_VGA_DEVICE(0x2e02, &intel_g45_info),		/* IGD_E_G */
+	INTEL_VGA_DEVICE(0x2e12, &intel_g45_info),		/* Q45_G */
+	INTEL_VGA_DEVICE(0x2e22, &intel_g45_info),		/* G45_G */
+	INTEL_VGA_DEVICE(0x2e32, &intel_g45_info),		/* G41_G */
+	INTEL_VGA_DEVICE(0x2e42, &intel_g45_info),		/* B43_G */
 	INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
 	INTEL_VGA_DEVICE(0xa001, &intel_pineview_info),
 	INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
 	INTEL_VGA_DEVICE(0xa011, &intel_pineview_info),
 	INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
 	INTEL_VGA_DEVICE(0x0042, &intel_ironlake_d_info),
@@ -340,7 +340,7 @@ int i965_reset(struct drm_device *dev, u8 flags)
 	/*
 	/*
 	 * Clear request list
 	 * Clear request list
 	 */
 	 */
-	i915_gem_retire_requests(dev, &dev_priv->render_ring);
+	i915_gem_retire_requests(dev);
 
 
 	if (need_display)
 	if (need_display)
 		i915_save_display(dev);
 		i915_save_display(dev);
@@ -413,7 +413,7 @@ int i965_reset(struct drm_device *dev, u8 flags)
 static int __devinit
 static int __devinit
 i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 {
-	return drm_get_dev(pdev, ent, &driver);
+	return drm_get_pci_dev(pdev, ent, &driver);
 }
 }
 
 
 static void
 static void
@@ -482,7 +482,7 @@ static int i915_pm_poweroff(struct device *dev)
 	return i915_drm_freeze(drm_dev);
 	return i915_drm_freeze(drm_dev);
 }
 }
 
 
-const struct dev_pm_ops i915_pm_ops = {
+static const struct dev_pm_ops i915_pm_ops = {
      .suspend = i915_pm_suspend,
      .suspend = i915_pm_suspend,
      .resume = i915_pm_resume,
      .resume = i915_pm_resume,
      .freeze = i915_pm_freeze,
      .freeze = i915_pm_freeze,

+ 22 - 7
drivers/gpu/drm/i915/i915_drv.h

@@ -176,7 +176,8 @@ struct drm_i915_display_funcs {
 	int (*get_display_clock_speed)(struct drm_device *dev);
 	int (*get_display_clock_speed)(struct drm_device *dev);
 	int (*get_fifo_size)(struct drm_device *dev, int plane);
 	int (*get_fifo_size)(struct drm_device *dev, int plane);
 	void (*update_wm)(struct drm_device *dev, int planea_clock,
 	void (*update_wm)(struct drm_device *dev, int planea_clock,
-			  int planeb_clock, int sr_hdisplay, int pixel_size);
+			  int planeb_clock, int sr_hdisplay, int sr_htotal,
+			  int pixel_size);
 	/* clock updates for mode set */
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* cursor updates */
 	/* render clock increase/decrease */
 	/* render clock increase/decrease */
@@ -200,6 +201,8 @@ struct intel_device_info {
 	u8 need_gfx_hws : 1;
 	u8 need_gfx_hws : 1;
 	u8 is_g4x : 1;
 	u8 is_g4x : 1;
 	u8 is_pineview : 1;
 	u8 is_pineview : 1;
+	u8 is_broadwater : 1;
+	u8 is_crestline : 1;
 	u8 is_ironlake : 1;
 	u8 is_ironlake : 1;
 	u8 is_gen6 : 1;
 	u8 is_gen6 : 1;
 	u8 has_fbc : 1;
 	u8 has_fbc : 1;
@@ -288,6 +291,8 @@ typedef struct drm_i915_private {
 	struct timer_list hangcheck_timer;
 	struct timer_list hangcheck_timer;
 	int hangcheck_count;
 	int hangcheck_count;
 	uint32_t last_acthd;
 	uint32_t last_acthd;
+	uint32_t last_instdone;
+	uint32_t last_instdone1;
 
 
 	struct drm_mm vram;
 	struct drm_mm vram;
 
 
@@ -546,6 +551,14 @@ typedef struct drm_i915_private {
 		/** LRU list of objects with fence regs on them. */
 		/** LRU list of objects with fence regs on them. */
 		struct list_head fence_list;
 		struct list_head fence_list;
 
 
+		/**
+		 * List of objects currently pending being freed.
+		 *
+		 * These objects are no longer in use, but due to a signal
+		 * we were prevented from freeing them at the appointed time.
+		 */
+		struct list_head deferred_free_list;
+
 		/**
 		/**
 		 * We leave the user IRQ off as much as possible,
 		 * We leave the user IRQ off as much as possible,
 		 * but this means that requests will finish and never
 		 * but this means that requests will finish and never
@@ -677,7 +690,7 @@ struct drm_i915_gem_object {
 	 *
 	 *
 	 * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
 	 * Size: 4 bits for 16 fences + sign (for FENCE_REG_NONE)
 	 */
 	 */
-	int fence_reg : 5;
+	signed int fence_reg : 5;
 
 
 	/**
 	/**
 	 * Used for checking the object doesn't appear more than once
 	 * Used for checking the object doesn't appear more than once
@@ -713,7 +726,7 @@ struct drm_i915_gem_object {
 	 *
 	 *
 	 * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
 	 * In the worst case this is 1 + 1 + 1 + 2*2 = 7. That would fit into 3
 	 * bits with absolutely no headroom. So use 4 bits. */
 	 * bits with absolutely no headroom. So use 4 bits. */
-	int pin_count : 4;
+	unsigned int pin_count : 4;
 #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
 #define DRM_I915_GEM_OBJECT_MAX_PIN_COUNT 0xf
 
 
 	/** AGP memory structure for our GTT binding. */
 	/** AGP memory structure for our GTT binding. */
@@ -743,7 +756,7 @@ struct drm_i915_gem_object {
 	uint32_t stride;
 	uint32_t stride;
 
 
 	/** Record of address bit 17 of each page at last unbind. */
 	/** Record of address bit 17 of each page at last unbind. */
-	long *bit_17;
+	unsigned long *bit_17;
 
 
 	/** AGP mapping type (AGP_USER_MEMORY or AGP_USER_CACHED_MEMORY */
 	/** AGP mapping type (AGP_USER_MEMORY or AGP_USER_CACHED_MEMORY */
 	uint32_t agp_type;
 	uint32_t agp_type;
@@ -955,8 +968,7 @@ uint32_t i915_get_gem_seqno(struct drm_device *dev,
 bool i915_seqno_passed(uint32_t seq1, uint32_t seq2);
 bool i915_seqno_passed(uint32_t seq1, uint32_t seq2);
 int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
 int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
 int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
 int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
-void i915_gem_retire_requests(struct drm_device *dev,
-		 struct intel_ring_buffer *ring);
+void i915_gem_retire_requests(struct drm_device *dev);
 void i915_gem_retire_work_handler(struct work_struct *work);
 void i915_gem_retire_work_handler(struct work_struct *work);
 void i915_gem_clflush_object(struct drm_gem_object *obj);
 void i915_gem_clflush_object(struct drm_gem_object *obj);
 int i915_gem_object_set_domain(struct drm_gem_object *obj,
 int i915_gem_object_set_domain(struct drm_gem_object *obj,
@@ -986,7 +998,7 @@ void i915_gem_free_all_phys_object(struct drm_device *dev);
 int i915_gem_object_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
 int i915_gem_object_get_pages(struct drm_gem_object *obj, gfp_t gfpmask);
 void i915_gem_object_put_pages(struct drm_gem_object *obj);
 void i915_gem_object_put_pages(struct drm_gem_object *obj);
 void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
 void i915_gem_release(struct drm_device * dev, struct drm_file *file_priv);
-void i915_gem_object_flush_write_domain(struct drm_gem_object *obj);
+int i915_gem_object_flush_write_domain(struct drm_gem_object *obj);
 
 
 void i915_gem_shrinker_init(void);
 void i915_gem_shrinker_init(void);
 void i915_gem_shrinker_exit(void);
 void i915_gem_shrinker_exit(void);
@@ -1046,6 +1058,7 @@ extern void intel_modeset_cleanup(struct drm_device *dev);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 extern int intel_modeset_vga_set_state(struct drm_device *dev, bool state);
 extern void i8xx_disable_fbc(struct drm_device *dev);
 extern void i8xx_disable_fbc(struct drm_device *dev);
 extern void g4x_disable_fbc(struct drm_device *dev);
 extern void g4x_disable_fbc(struct drm_device *dev);
+extern void ironlake_disable_fbc(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern void intel_disable_fbc(struct drm_device *dev);
 extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
 extern void intel_enable_fbc(struct drm_crtc *crtc, unsigned long interval);
 extern bool intel_fbc_enabled(struct drm_device *dev);
 extern bool intel_fbc_enabled(struct drm_device *dev);
@@ -1135,6 +1148,8 @@ extern int intel_trans_dp_port_sel (struct drm_crtc *crtc);
 #define IS_I945GM(dev)		(INTEL_INFO(dev)->is_i945gm)
 #define IS_I945GM(dev)		(INTEL_INFO(dev)->is_i945gm)
 #define IS_I965G(dev)		(INTEL_INFO(dev)->is_i965g)
 #define IS_I965G(dev)		(INTEL_INFO(dev)->is_i965g)
 #define IS_I965GM(dev)		(INTEL_INFO(dev)->is_i965gm)
 #define IS_I965GM(dev)		(INTEL_INFO(dev)->is_i965gm)
+#define IS_BROADWATER(dev)	(INTEL_INFO(dev)->is_broadwater)
+#define IS_CRESTLINE(dev)	(INTEL_INFO(dev)->is_crestline)
 #define IS_GM45(dev)		((dev)->pci_device == 0x2A42)
 #define IS_GM45(dev)		((dev)->pci_device == 0x2A42)
 #define IS_G4X(dev)		(INTEL_INFO(dev)->is_g4x)
 #define IS_G4X(dev)		(INTEL_INFO(dev)->is_g4x)
 #define IS_PINEVIEW_G(dev)	((dev)->pci_device == 0xa001)
 #define IS_PINEVIEW_G(dev)	((dev)->pci_device == 0xa001)

+ 114 - 58
drivers/gpu/drm/i915/i915_gem.c

@@ -35,7 +35,7 @@
 #include <linux/swap.h>
 #include <linux/swap.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
 
 
-static void i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
+static int i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_gtt_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
 static void i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj);
 static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj,
 static int i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj,
@@ -53,6 +53,7 @@ static int i915_gem_evict_from_inactive_list(struct drm_device *dev);
 static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
 static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
 				struct drm_i915_gem_pwrite *args,
 				struct drm_i915_gem_pwrite *args,
 				struct drm_file *file_priv);
 				struct drm_file *file_priv);
+static void i915_gem_free_object_tail(struct drm_gem_object *obj);
 
 
 static LIST_HEAD(shrink_list);
 static LIST_HEAD(shrink_list);
 static DEFINE_SPINLOCK(shrink_list_lock);
 static DEFINE_SPINLOCK(shrink_list_lock);
@@ -127,8 +128,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	ret = drm_gem_handle_create(file_priv, obj, &handle);
 	ret = drm_gem_handle_create(file_priv, obj, &handle);
-	drm_gem_object_handle_unreference_unlocked(obj);
-
+	drm_gem_object_unreference_unlocked(obj);
 	if (ret)
 	if (ret)
 		return ret;
 		return ret;
 
 
@@ -496,10 +496,10 @@ fast_user_write(struct io_mapping *mapping,
 	char *vaddr_atomic;
 	char *vaddr_atomic;
 	unsigned long unwritten;
 	unsigned long unwritten;
 
 
-	vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base);
+	vaddr_atomic = io_mapping_map_atomic_wc(mapping, page_base, KM_USER0);
 	unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
 	unwritten = __copy_from_user_inatomic_nocache(vaddr_atomic + page_offset,
 						      user_data, length);
 						      user_data, length);
-	io_mapping_unmap_atomic(vaddr_atomic);
+	io_mapping_unmap_atomic(vaddr_atomic, KM_USER0);
 	if (unwritten)
 	if (unwritten)
 		return -EFAULT;
 		return -EFAULT;
 	return 0;
 	return 0;
@@ -1709,9 +1709,9 @@ i915_get_gem_seqno(struct drm_device *dev,
 /**
 /**
  * This function clears the request list as sequence numbers are passed.
  * This function clears the request list as sequence numbers are passed.
  */
  */
-void
-i915_gem_retire_requests(struct drm_device *dev,
-		struct intel_ring_buffer *ring)
+static void
+i915_gem_retire_requests_ring(struct drm_device *dev,
+			      struct intel_ring_buffer *ring)
 {
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t seqno;
 	uint32_t seqno;
@@ -1750,6 +1750,30 @@ i915_gem_retire_requests(struct drm_device *dev,
 	}
 	}
 }
 }
 
 
+void
+i915_gem_retire_requests(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	if (!list_empty(&dev_priv->mm.deferred_free_list)) {
+	    struct drm_i915_gem_object *obj_priv, *tmp;
+
+	    /* We must be careful that during unbind() we do not
+	     * accidentally infinitely recurse into retire requests.
+	     * Currently:
+	     *   retire -> free -> unbind -> wait -> retire_ring
+	     */
+	    list_for_each_entry_safe(obj_priv, tmp,
+				     &dev_priv->mm.deferred_free_list,
+				     list)
+		    i915_gem_free_object_tail(&obj_priv->base);
+	}
+
+	i915_gem_retire_requests_ring(dev, &dev_priv->render_ring);
+	if (HAS_BSD(dev))
+		i915_gem_retire_requests_ring(dev, &dev_priv->bsd_ring);
+}
+
 void
 void
 i915_gem_retire_work_handler(struct work_struct *work)
 i915_gem_retire_work_handler(struct work_struct *work)
 {
 {
@@ -1761,10 +1785,7 @@ i915_gem_retire_work_handler(struct work_struct *work)
 	dev = dev_priv->dev;
 	dev = dev_priv->dev;
 
 
 	mutex_lock(&dev->struct_mutex);
 	mutex_lock(&dev->struct_mutex);
-	i915_gem_retire_requests(dev, &dev_priv->render_ring);
-
-	if (HAS_BSD(dev))
-		i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
+	i915_gem_retire_requests(dev);
 
 
 	if (!dev_priv->mm.suspended &&
 	if (!dev_priv->mm.suspended &&
 		(!list_empty(&dev_priv->render_ring.request_list) ||
 		(!list_empty(&dev_priv->render_ring.request_list) ||
@@ -1832,7 +1853,7 @@ i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
 	 * a separate wait queue to handle that.
 	 * a separate wait queue to handle that.
 	 */
 	 */
 	if (ret == 0)
 	if (ret == 0)
-		i915_gem_retire_requests(dev, ring);
+		i915_gem_retire_requests_ring(dev, ring);
 
 
 	return ret;
 	return ret;
 }
 }
@@ -1945,11 +1966,12 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
 	 * before we unbind.
 	 * before we unbind.
 	 */
 	 */
 	ret = i915_gem_object_set_to_cpu_domain(obj, 1);
 	ret = i915_gem_object_set_to_cpu_domain(obj, 1);
-	if (ret) {
-		if (ret != -ERESTARTSYS)
-			DRM_ERROR("set_domain failed: %d\n", ret);
+	if (ret == -ERESTARTSYS)
 		return ret;
 		return ret;
-	}
+	/* Continue on if we fail due to EIO, the GPU is hung so we
+	 * should be safe and we need to cleanup or else we might
+	 * cause memory corruption through use-after-free.
+	 */
 
 
 	BUG_ON(obj_priv->active);
 	BUG_ON(obj_priv->active);
 
 
@@ -1985,7 +2007,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
 
 
 	trace_i915_gem_object_unbind(obj);
 	trace_i915_gem_object_unbind(obj);
 
 
-	return 0;
+	return ret;
 }
 }
 
 
 static struct drm_gem_object *
 static struct drm_gem_object *
@@ -2107,10 +2129,7 @@ i915_gem_evict_something(struct drm_device *dev, int min_size)
 	struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
 	struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
 	struct intel_ring_buffer *bsd_ring = &dev_priv->bsd_ring;
 	struct intel_ring_buffer *bsd_ring = &dev_priv->bsd_ring;
 	for (;;) {
 	for (;;) {
-		i915_gem_retire_requests(dev, render_ring);
-
-		if (HAS_BSD(dev))
-			i915_gem_retire_requests(dev, bsd_ring);
+		i915_gem_retire_requests(dev);
 
 
 		/* If there's an inactive buffer available now, grab it
 		/* If there's an inactive buffer available now, grab it
 		 * and be done.
 		 * and be done.
@@ -2583,7 +2602,10 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
 	if (!IS_I965G(dev)) {
 	if (!IS_I965G(dev)) {
 		int ret;
 		int ret;
 
 
-		i915_gem_object_flush_gpu_write_domain(obj);
+		ret = i915_gem_object_flush_gpu_write_domain(obj);
+		if (ret != 0)
+			return ret;
+
 		ret = i915_gem_object_wait_rendering(obj);
 		ret = i915_gem_object_wait_rendering(obj);
 		if (ret != 0)
 		if (ret != 0)
 			return ret;
 			return ret;
@@ -2634,10 +2656,8 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
 	if (free_space != NULL) {
 	if (free_space != NULL) {
 		obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
 		obj_priv->gtt_space = drm_mm_get_block(free_space, obj->size,
 						       alignment);
 						       alignment);
-		if (obj_priv->gtt_space != NULL) {
-			obj_priv->gtt_space->private = obj;
+		if (obj_priv->gtt_space != NULL)
 			obj_priv->gtt_offset = obj_priv->gtt_space->start;
 			obj_priv->gtt_offset = obj_priv->gtt_space->start;
-		}
 	}
 	}
 	if (obj_priv->gtt_space == NULL) {
 	if (obj_priv->gtt_space == NULL) {
 		/* If the gtt is empty and we're still having trouble
 		/* If the gtt is empty and we're still having trouble
@@ -2733,7 +2753,7 @@ i915_gem_clflush_object(struct drm_gem_object *obj)
 }
 }
 
 
 /** Flushes any GPU write domain for the object if it's dirty. */
 /** Flushes any GPU write domain for the object if it's dirty. */
-static void
+static int
 i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
 i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
 {
 {
 	struct drm_device *dev = obj->dev;
 	struct drm_device *dev = obj->dev;
@@ -2741,17 +2761,18 @@ i915_gem_object_flush_gpu_write_domain(struct drm_gem_object *obj)
 	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 
 
 	if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
 	if ((obj->write_domain & I915_GEM_GPU_DOMAINS) == 0)
-		return;
+		return 0;
 
 
 	/* Queue the GPU write cache flushing we need. */
 	/* Queue the GPU write cache flushing we need. */
 	old_write_domain = obj->write_domain;
 	old_write_domain = obj->write_domain;
 	i915_gem_flush(dev, 0, obj->write_domain);
 	i915_gem_flush(dev, 0, obj->write_domain);
-	(void) i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring);
-	BUG_ON(obj->write_domain);
+	if (i915_add_request(dev, NULL, obj->write_domain, obj_priv->ring) == 0)
+		return -ENOMEM;
 
 
 	trace_i915_gem_object_change_domain(obj,
 	trace_i915_gem_object_change_domain(obj,
 					    obj->read_domains,
 					    obj->read_domains,
 					    old_write_domain);
 					    old_write_domain);
+	return 0;
 }
 }
 
 
 /** Flushes the GTT write domain for the object if it's dirty. */
 /** Flushes the GTT write domain for the object if it's dirty. */
@@ -2795,9 +2816,11 @@ i915_gem_object_flush_cpu_write_domain(struct drm_gem_object *obj)
 					    old_write_domain);
 					    old_write_domain);
 }
 }
 
 
-void
+int
 i915_gem_object_flush_write_domain(struct drm_gem_object *obj)
 i915_gem_object_flush_write_domain(struct drm_gem_object *obj)
 {
 {
+	int ret = 0;
+
 	switch (obj->write_domain) {
 	switch (obj->write_domain) {
 	case I915_GEM_DOMAIN_GTT:
 	case I915_GEM_DOMAIN_GTT:
 		i915_gem_object_flush_gtt_write_domain(obj);
 		i915_gem_object_flush_gtt_write_domain(obj);
@@ -2806,9 +2829,11 @@ i915_gem_object_flush_write_domain(struct drm_gem_object *obj)
 		i915_gem_object_flush_cpu_write_domain(obj);
 		i915_gem_object_flush_cpu_write_domain(obj);
 		break;
 		break;
 	default:
 	default:
-		i915_gem_object_flush_gpu_write_domain(obj);
+		ret = i915_gem_object_flush_gpu_write_domain(obj);
 		break;
 		break;
 	}
 	}
+
+	return ret;
 }
 }
 
 
 /**
 /**
@@ -2828,7 +2853,10 @@ i915_gem_object_set_to_gtt_domain(struct drm_gem_object *obj, int write)
 	if (obj_priv->gtt_space == NULL)
 	if (obj_priv->gtt_space == NULL)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	i915_gem_object_flush_gpu_write_domain(obj);
+	ret = i915_gem_object_flush_gpu_write_domain(obj);
+	if (ret != 0)
+		return ret;
+
 	/* Wait on any GPU rendering and flushing to occur. */
 	/* Wait on any GPU rendering and flushing to occur. */
 	ret = i915_gem_object_wait_rendering(obj);
 	ret = i915_gem_object_wait_rendering(obj);
 	if (ret != 0)
 	if (ret != 0)
@@ -2878,7 +2906,9 @@ i915_gem_object_set_to_display_plane(struct drm_gem_object *obj)
 	if (obj_priv->gtt_space == NULL)
 	if (obj_priv->gtt_space == NULL)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	i915_gem_object_flush_gpu_write_domain(obj);
+	ret = i915_gem_object_flush_gpu_write_domain(obj);
+	if (ret)
+		return ret;
 
 
 	/* Wait on any GPU rendering and flushing to occur. */
 	/* Wait on any GPU rendering and flushing to occur. */
 	if (obj_priv->active) {
 	if (obj_priv->active) {
@@ -2926,7 +2956,10 @@ i915_gem_object_set_to_cpu_domain(struct drm_gem_object *obj, int write)
 	uint32_t old_write_domain, old_read_domains;
 	uint32_t old_write_domain, old_read_domains;
 	int ret;
 	int ret;
 
 
-	i915_gem_object_flush_gpu_write_domain(obj);
+	ret = i915_gem_object_flush_gpu_write_domain(obj);
+	if (ret)
+		return ret;
+
 	/* Wait on any GPU rendering and flushing to occur. */
 	/* Wait on any GPU rendering and flushing to occur. */
 	ret = i915_gem_object_wait_rendering(obj);
 	ret = i915_gem_object_wait_rendering(obj);
 	if (ret != 0)
 	if (ret != 0)
@@ -3216,7 +3249,10 @@ i915_gem_object_set_cpu_read_domain_range(struct drm_gem_object *obj,
 	if (offset == 0 && size == obj->size)
 	if (offset == 0 && size == obj->size)
 		return i915_gem_object_set_to_cpu_domain(obj, 0);
 		return i915_gem_object_set_to_cpu_domain(obj, 0);
 
 
-	i915_gem_object_flush_gpu_write_domain(obj);
+	ret = i915_gem_object_flush_gpu_write_domain(obj);
+	if (ret)
+		return ret;
+
 	/* Wait on any GPU rendering and flushing to occur. */
 	/* Wait on any GPU rendering and flushing to occur. */
 	ret = i915_gem_object_wait_rendering(obj);
 	ret = i915_gem_object_wait_rendering(obj);
 	if (ret != 0)
 	if (ret != 0)
@@ -3451,7 +3487,8 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
 		reloc_offset = obj_priv->gtt_offset + reloc->offset;
 		reloc_offset = obj_priv->gtt_offset + reloc->offset;
 		reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
 		reloc_page = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
 						      (reloc_offset &
 						      (reloc_offset &
-						       ~(PAGE_SIZE - 1)));
+						       ~(PAGE_SIZE - 1)),
+						      KM_USER0);
 		reloc_entry = (uint32_t __iomem *)(reloc_page +
 		reloc_entry = (uint32_t __iomem *)(reloc_page +
 						   (reloc_offset & (PAGE_SIZE - 1)));
 						   (reloc_offset & (PAGE_SIZE - 1)));
 		reloc_val = target_obj_priv->gtt_offset + reloc->delta;
 		reloc_val = target_obj_priv->gtt_offset + reloc->delta;
@@ -3462,7 +3499,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
 			  readl(reloc_entry), reloc_val);
 			  readl(reloc_entry), reloc_val);
 #endif
 #endif
 		writel(reloc_val, reloc_entry);
 		writel(reloc_val, reloc_entry);
-		io_mapping_unmap_atomic(reloc_page);
+		io_mapping_unmap_atomic(reloc_page, KM_USER0);
 
 
 		/* The updated presumed offset for this entry will be
 		/* The updated presumed offset for this entry will be
 		 * copied back out to the user.
 		 * copied back out to the user.
@@ -4313,7 +4350,6 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 	struct drm_i915_gem_busy *args = data;
 	struct drm_i915_gem_busy *args = data;
 	struct drm_gem_object *obj;
 	struct drm_gem_object *obj;
 	struct drm_i915_gem_object *obj_priv;
 	struct drm_i915_gem_object *obj_priv;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 
 
 	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
 	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
 	if (obj == NULL) {
 	if (obj == NULL) {
@@ -4328,10 +4364,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data,
 	 * actually unmasked, and our working set ends up being larger than
 	 * actually unmasked, and our working set ends up being larger than
 	 * required.
 	 * required.
 	 */
 	 */
-	i915_gem_retire_requests(dev, &dev_priv->render_ring);
-
-	if (HAS_BSD(dev))
-		i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
+	i915_gem_retire_requests(dev);
 
 
 	obj_priv = to_intel_bo(obj);
 	obj_priv = to_intel_bo(obj);
 	/* Don't count being on the flushing list against the object being
 	/* Don't count being on the flushing list against the object being
@@ -4441,20 +4474,19 @@ int i915_gem_init_object(struct drm_gem_object *obj)
 	return 0;
 	return 0;
 }
 }
 
 
-void i915_gem_free_object(struct drm_gem_object *obj)
+static void i915_gem_free_object_tail(struct drm_gem_object *obj)
 {
 {
 	struct drm_device *dev = obj->dev;
 	struct drm_device *dev = obj->dev;
+	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+	int ret;
 
 
-	trace_i915_gem_object_destroy(obj);
-
-	while (obj_priv->pin_count > 0)
-		i915_gem_object_unpin(obj);
-
-	if (obj_priv->phys_obj)
-		i915_gem_detach_phys_object(dev, obj);
-
-	i915_gem_object_unbind(obj);
+	ret = i915_gem_object_unbind(obj);
+	if (ret == -ERESTARTSYS) {
+		list_move(&obj_priv->list,
+			  &dev_priv->mm.deferred_free_list);
+		return;
+	}
 
 
 	if (obj_priv->mmap_offset)
 	if (obj_priv->mmap_offset)
 		i915_gem_free_mmap_offset(obj);
 		i915_gem_free_mmap_offset(obj);
@@ -4466,6 +4498,22 @@ void i915_gem_free_object(struct drm_gem_object *obj)
 	kfree(obj_priv);
 	kfree(obj_priv);
 }
 }
 
 
+void i915_gem_free_object(struct drm_gem_object *obj)
+{
+	struct drm_device *dev = obj->dev;
+	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+
+	trace_i915_gem_object_destroy(obj);
+
+	while (obj_priv->pin_count > 0)
+		i915_gem_object_unpin(obj);
+
+	if (obj_priv->phys_obj)
+		i915_gem_detach_phys_object(dev, obj);
+
+	i915_gem_free_object_tail(obj);
+}
+
 /** Unbinds all inactive objects. */
 /** Unbinds all inactive objects. */
 static int
 static int
 i915_gem_evict_from_inactive_list(struct drm_device *dev)
 i915_gem_evict_from_inactive_list(struct drm_device *dev)
@@ -4689,9 +4737,19 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 	BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list));
 	BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.request_list));
 	mutex_unlock(&dev->struct_mutex);
 	mutex_unlock(&dev->struct_mutex);
 
 
-	drm_irq_install(dev);
+	ret = drm_irq_install(dev);
+	if (ret)
+		goto cleanup_ringbuffer;
 
 
 	return 0;
 	return 0;
+
+cleanup_ringbuffer:
+	mutex_lock(&dev->struct_mutex);
+	i915_gem_cleanup_ringbuffer(dev);
+	dev_priv->mm.suspended = 1;
+	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
 }
 }
 
 
 int
 int
@@ -4729,6 +4787,7 @@ i915_gem_load(struct drm_device *dev)
 	INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list);
 	INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list);
 	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
 	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
 	INIT_LIST_HEAD(&dev_priv->mm.fence_list);
+	INIT_LIST_HEAD(&dev_priv->mm.deferred_free_list);
 	INIT_LIST_HEAD(&dev_priv->render_ring.active_list);
 	INIT_LIST_HEAD(&dev_priv->render_ring.active_list);
 	INIT_LIST_HEAD(&dev_priv->render_ring.request_list);
 	INIT_LIST_HEAD(&dev_priv->render_ring.request_list);
 	if (HAS_BSD(dev)) {
 	if (HAS_BSD(dev)) {
@@ -5027,10 +5086,7 @@ rescan:
 			continue;
 			continue;
 
 
 		spin_unlock(&shrink_list_lock);
 		spin_unlock(&shrink_list_lock);
-		i915_gem_retire_requests(dev, &dev_priv->render_ring);
-
-		if (HAS_BSD(dev))
-			i915_gem_retire_requests(dev, &dev_priv->bsd_ring);
+		i915_gem_retire_requests(dev);
 
 
 		list_for_each_entry_safe(obj_priv, next_obj,
 		list_for_each_entry_safe(obj_priv, next_obj,
 					 &dev_priv->mm.inactive_list,
 					 &dev_priv->mm.inactive_list,

+ 0 - 2
drivers/gpu/drm/i915/i915_gem_tiling.c

@@ -333,8 +333,6 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
 			i915_gem_release_mmap(obj);
 			i915_gem_release_mmap(obj);
 
 
 		if (ret != 0) {
 		if (ret != 0) {
-			WARN(ret != -ERESTARTSYS,
-			     "failed to reset object for tiling switch");
 			args->tiling_mode = obj_priv->tiling_mode;
 			args->tiling_mode = obj_priv->tiling_mode;
 			args->stride = obj_priv->stride;
 			args->stride = obj_priv->stride;
 			goto err;
 			goto err;

+ 31 - 27
drivers/gpu/drm/i915/i915_irq.c

@@ -171,10 +171,10 @@ void intel_enable_asle (struct drm_device *dev)
 		ironlake_enable_display_irq(dev_priv, DE_GSE);
 		ironlake_enable_display_irq(dev_priv, DE_GSE);
 	else {
 	else {
 		i915_enable_pipestat(dev_priv, 1,
 		i915_enable_pipestat(dev_priv, 1,
-				     I915_LEGACY_BLC_EVENT_ENABLE);
+				     PIPE_LEGACY_BLC_EVENT_ENABLE);
 		if (IS_I965G(dev))
 		if (IS_I965G(dev))
 			i915_enable_pipestat(dev_priv, 0,
 			i915_enable_pipestat(dev_priv, 0,
-					     I915_LEGACY_BLC_EVENT_ENABLE);
+					     PIPE_LEGACY_BLC_EVENT_ENABLE);
 	}
 	}
 }
 }
 
 
@@ -842,7 +842,6 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 	u32 iir, new_iir;
 	u32 iir, new_iir;
 	u32 pipea_stats, pipeb_stats;
 	u32 pipea_stats, pipeb_stats;
 	u32 vblank_status;
 	u32 vblank_status;
-	u32 vblank_enable;
 	int vblank = 0;
 	int vblank = 0;
 	unsigned long irqflags;
 	unsigned long irqflags;
 	int irq_received;
 	int irq_received;
@@ -856,13 +855,10 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 
 
 	iir = I915_READ(IIR);
 	iir = I915_READ(IIR);
 
 
-	if (IS_I965G(dev)) {
-		vblank_status = I915_START_VBLANK_INTERRUPT_STATUS;
-		vblank_enable = PIPE_START_VBLANK_INTERRUPT_ENABLE;
-	} else {
-		vblank_status = I915_VBLANK_INTERRUPT_STATUS;
-		vblank_enable = I915_VBLANK_INTERRUPT_ENABLE;
-	}
+	if (IS_I965G(dev))
+		vblank_status = PIPE_START_VBLANK_INTERRUPT_STATUS;
+	else
+		vblank_status = PIPE_VBLANK_INTERRUPT_STATUS;
 
 
 	for (;;) {
 	for (;;) {
 		irq_received = iir != 0;
 		irq_received = iir != 0;
@@ -966,8 +962,8 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
 				intel_finish_page_flip(dev, 1);
 				intel_finish_page_flip(dev, 1);
 		}
 		}
 
 
-		if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
-		    (pipeb_stats & I915_LEGACY_BLC_EVENT_STATUS) ||
+		if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
+		    (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
 		    (iir & I915_ASLE_INTERRUPT))
 		    (iir & I915_ASLE_INTERRUPT))
 			opregion_asle_intr(dev);
 			opregion_asle_intr(dev);
 
 
@@ -1233,16 +1229,21 @@ void i915_hangcheck_elapsed(unsigned long data)
 {
 {
 	struct drm_device *dev = (struct drm_device *)data;
 	struct drm_device *dev = (struct drm_device *)data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_i915_private_t *dev_priv = dev->dev_private;
-	uint32_t acthd;
+	uint32_t acthd, instdone, instdone1;
 
 
 	/* No reset support on this chip yet. */
 	/* No reset support on this chip yet. */
 	if (IS_GEN6(dev))
 	if (IS_GEN6(dev))
 		return;
 		return;
 
 
-	if (!IS_I965G(dev))
+	if (!IS_I965G(dev)) {
 		acthd = I915_READ(ACTHD);
 		acthd = I915_READ(ACTHD);
-	else
+		instdone = I915_READ(INSTDONE);
+		instdone1 = 0;
+	} else {
 		acthd = I915_READ(ACTHD_I965);
 		acthd = I915_READ(ACTHD_I965);
+		instdone = I915_READ(INSTDONE_I965);
+		instdone1 = I915_READ(INSTDONE1);
+	}
 
 
 	/* If all work is done then ACTHD clearly hasn't advanced. */
 	/* If all work is done then ACTHD clearly hasn't advanced. */
 	if (list_empty(&dev_priv->render_ring.request_list) ||
 	if (list_empty(&dev_priv->render_ring.request_list) ||
@@ -1253,21 +1254,24 @@ void i915_hangcheck_elapsed(unsigned long data)
 		return;
 		return;
 	}
 	}
 
 
-	if (dev_priv->last_acthd == acthd && dev_priv->hangcheck_count > 0) {
-		DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
-		i915_handle_error(dev, true);
-		return;
-	} 
+	if (dev_priv->last_acthd == acthd &&
+	    dev_priv->last_instdone == instdone &&
+	    dev_priv->last_instdone1 == instdone1) {
+		if (dev_priv->hangcheck_count++ > 1) {
+			DRM_ERROR("Hangcheck timer elapsed... GPU hung\n");
+			i915_handle_error(dev, true);
+			return;
+		}
+	} else {
+		dev_priv->hangcheck_count = 0;
+
+		dev_priv->last_acthd = acthd;
+		dev_priv->last_instdone = instdone;
+		dev_priv->last_instdone1 = instdone1;
+	}
 
 
 	/* Reset timer case chip hangs without another request being added */
 	/* Reset timer case chip hangs without another request being added */
 	mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
 	mod_timer(&dev_priv->hangcheck_timer, jiffies + DRM_I915_HANGCHECK_PERIOD);
-
-	if (acthd != dev_priv->last_acthd)
-		dev_priv->hangcheck_count = 0;
-	else
-		dev_priv->hangcheck_count++;
-
-	dev_priv->last_acthd = acthd;
 }
 }
 
 
 /* drm_dma.h hooks
 /* drm_dma.h hooks

+ 28 - 28
drivers/gpu/drm/i915/i915_reg.h

@@ -442,7 +442,7 @@
 #define GEN6_RENDER_IMR		0x20a8
 #define GEN6_RENDER_IMR		0x20a8
 #define   GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT		(1 << 8)
 #define   GEN6_RENDER_CONTEXT_SWITCH_INTERRUPT		(1 << 8)
 #define   GEN6_RENDER_PPGTT_PAGE_FAULT			(1 << 7)
 #define   GEN6_RENDER_PPGTT_PAGE_FAULT			(1 << 7)
-#define   GEN6_RENDER TIMEOUT_COUNTER_EXPIRED		(1 << 6)
+#define   GEN6_RENDER_TIMEOUT_COUNTER_EXPIRED		(1 << 6)
 #define   GEN6_RENDER_L3_PARITY_ERROR			(1 << 5)
 #define   GEN6_RENDER_L3_PARITY_ERROR			(1 << 5)
 #define   GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT	(1 << 4)
 #define   GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT	(1 << 4)
 #define   GEN6_RENDER_COMMAND_PARSER_MASTER_ERROR	(1 << 3)
 #define   GEN6_RENDER_COMMAND_PARSER_MASTER_ERROR	(1 << 3)
@@ -530,6 +530,21 @@
 #define DPFC_CHICKEN		0x3224
 #define DPFC_CHICKEN		0x3224
 #define   DPFC_HT_MODIFY	(1<<31)
 #define   DPFC_HT_MODIFY	(1<<31)
 
 
+/* Framebuffer compression for Ironlake */
+#define ILK_DPFC_CB_BASE	0x43200
+#define ILK_DPFC_CONTROL	0x43208
+/* The bit 28-8 is reserved */
+#define   DPFC_RESERVED		(0x1FFFFF00)
+#define ILK_DPFC_RECOMP_CTL	0x4320c
+#define ILK_DPFC_STATUS		0x43210
+#define ILK_DPFC_FENCE_YOFF	0x43218
+#define ILK_DPFC_CHICKEN	0x43224
+#define ILK_FBC_RT_BASE		0x2128
+#define   ILK_FBC_RT_VALID	(1<<0)
+
+#define ILK_DISPLAY_CHICKEN1	0x42000
+#define   ILK_FBCQ_DIS		(1<<22)
+
 /*
 /*
  * GPIO regs
  * GPIO regs
  */
  */
@@ -595,32 +610,6 @@
 #define   DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK	0x00ff0000 /* i915 */
 #define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW	0x00ff8000 /* Pineview */
 #define   DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW	0x00ff8000 /* Pineview */
 
 
-#define I915_FIFO_UNDERRUN_STATUS		(1UL<<31)
-#define I915_CRC_ERROR_ENABLE			(1UL<<29)
-#define I915_CRC_DONE_ENABLE			(1UL<<28)
-#define I915_GMBUS_EVENT_ENABLE			(1UL<<27)
-#define I915_VSYNC_INTERRUPT_ENABLE		(1UL<<25)
-#define I915_DISPLAY_LINE_COMPARE_ENABLE	(1UL<<24)
-#define I915_DPST_EVENT_ENABLE			(1UL<<23)
-#define I915_LEGACY_BLC_EVENT_ENABLE		(1UL<<22)
-#define I915_ODD_FIELD_INTERRUPT_ENABLE		(1UL<<21)
-#define I915_EVEN_FIELD_INTERRUPT_ENABLE	(1UL<<20)
-#define I915_START_VBLANK_INTERRUPT_ENABLE	(1UL<<18)	/* 965 or later */
-#define I915_VBLANK_INTERRUPT_ENABLE		(1UL<<17)
-#define I915_OVERLAY_UPDATED_ENABLE		(1UL<<16)
-#define I915_CRC_ERROR_INTERRUPT_STATUS		(1UL<<13)
-#define I915_CRC_DONE_INTERRUPT_STATUS		(1UL<<12)
-#define I915_GMBUS_INTERRUPT_STATUS		(1UL<<11)
-#define I915_VSYNC_INTERRUPT_STATUS		(1UL<<9)
-#define I915_DISPLAY_LINE_COMPARE_STATUS	(1UL<<8)
-#define I915_DPST_EVENT_STATUS			(1UL<<7)
-#define I915_LEGACY_BLC_EVENT_STATUS		(1UL<<6)
-#define I915_ODD_FIELD_INTERRUPT_STATUS		(1UL<<5)
-#define I915_EVEN_FIELD_INTERRUPT_STATUS	(1UL<<4)
-#define I915_START_VBLANK_INTERRUPT_STATUS	(1UL<<2)	/* 965 or later */
-#define I915_VBLANK_INTERRUPT_STATUS		(1UL<<1)
-#define I915_OVERLAY_UPDATED_STATUS		(1UL<<0)
-
 #define SRX_INDEX		0x3c4
 #define SRX_INDEX		0x3c4
 #define SRX_DATA		0x3c5
 #define SRX_DATA		0x3c5
 #define SR01			1
 #define SR01			1
@@ -2166,7 +2155,8 @@
 #define I830_FIFO_LINE_SIZE	32
 #define I830_FIFO_LINE_SIZE	32
 
 
 #define G4X_FIFO_SIZE		127
 #define G4X_FIFO_SIZE		127
-#define I945_FIFO_SIZE		127 /* 945 & 965 */
+#define I965_FIFO_SIZE		512
+#define I945_FIFO_SIZE		127
 #define I915_FIFO_SIZE		95
 #define I915_FIFO_SIZE		95
 #define I855GM_FIFO_SIZE	127 /* In cachelines */
 #define I855GM_FIFO_SIZE	127 /* In cachelines */
 #define I830_FIFO_SIZE		95
 #define I830_FIFO_SIZE		95
@@ -2185,6 +2175,9 @@
 #define PINEVIEW_CURSOR_DFT_WM	0
 #define PINEVIEW_CURSOR_DFT_WM	0
 #define PINEVIEW_CURSOR_GUARD_WM	5
 #define PINEVIEW_CURSOR_GUARD_WM	5
 
 
+#define I965_CURSOR_FIFO	64
+#define I965_CURSOR_MAX_WM	32
+#define I965_CURSOR_DFT_WM	8
 
 
 /* define the Watermark register on Ironlake */
 /* define the Watermark register on Ironlake */
 #define WM0_PIPEA_ILK		0x45100
 #define WM0_PIPEA_ILK		0x45100
@@ -2212,6 +2205,9 @@
 #define ILK_DISPLAY_FIFO	128
 #define ILK_DISPLAY_FIFO	128
 #define ILK_DISPLAY_MAXWM	64
 #define ILK_DISPLAY_MAXWM	64
 #define ILK_DISPLAY_DFTWM	8
 #define ILK_DISPLAY_DFTWM	8
+#define ILK_CURSOR_FIFO		32
+#define ILK_CURSOR_MAXWM	16
+#define ILK_CURSOR_DFTWM	8
 
 
 #define ILK_DISPLAY_SR_FIFO	512
 #define ILK_DISPLAY_SR_FIFO	512
 #define ILK_DISPLAY_MAX_SRWM	0x1ff
 #define ILK_DISPLAY_MAX_SRWM	0x1ff
@@ -2510,6 +2506,10 @@
 #define  ILK_VSDPFD_FULL	(1<<21)
 #define  ILK_VSDPFD_FULL	(1<<21)
 #define ILK_DSPCLK_GATE		0x42020
 #define ILK_DSPCLK_GATE		0x42020
 #define  ILK_DPARB_CLK_GATE	(1<<5)
 #define  ILK_DPARB_CLK_GATE	(1<<5)
+/* According to spec this bit 7/8/9 of 0x42020 should be set to enable FBC */
+#define   ILK_CLK_FBC		(1<<7)
+#define   ILK_DPFC_DIS1		(1<<8)
+#define   ILK_DPFC_DIS2		(1<<9)
 
 
 #define DISP_ARB_CTL	0x45000
 #define DISP_ARB_CTL	0x45000
 #define  DISP_TILE_SURFACE_SWIZZLING	(1<<13)
 #define  DISP_TILE_SURFACE_SWIZZLING	(1<<13)

+ 7 - 2
drivers/gpu/drm/i915/i915_suspend.c

@@ -602,7 +602,9 @@ void i915_save_display(struct drm_device *dev)
 
 
 	/* Only save FBC state on the platform that supports FBC */
 	/* Only save FBC state on the platform that supports FBC */
 	if (I915_HAS_FBC(dev)) {
 	if (I915_HAS_FBC(dev)) {
-		if (IS_GM45(dev)) {
+		if (IS_IRONLAKE_M(dev)) {
+			dev_priv->saveDPFC_CB_BASE = I915_READ(ILK_DPFC_CB_BASE);
+		} else if (IS_GM45(dev)) {
 			dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
 			dev_priv->saveDPFC_CB_BASE = I915_READ(DPFC_CB_BASE);
 		} else {
 		} else {
 			dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
 			dev_priv->saveFBC_CFB_BASE = I915_READ(FBC_CFB_BASE);
@@ -706,7 +708,10 @@ void i915_restore_display(struct drm_device *dev)
 
 
 	/* only restore FBC info on the platform that supports FBC*/
 	/* only restore FBC info on the platform that supports FBC*/
 	if (I915_HAS_FBC(dev)) {
 	if (I915_HAS_FBC(dev)) {
-		if (IS_GM45(dev)) {
+		if (IS_IRONLAKE_M(dev)) {
+			ironlake_disable_fbc(dev);
+			I915_WRITE(ILK_DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
+		} else if (IS_GM45(dev)) {
 			g4x_disable_fbc(dev);
 			g4x_disable_fbc(dev);
 			I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
 			I915_WRITE(DPFC_CB_BASE, dev_priv->saveDPFC_CB_BASE);
 		} else {
 		} else {

+ 36 - 0
drivers/gpu/drm/i915/i915_trace.h

@@ -262,6 +262,42 @@ DEFINE_EVENT(i915_ring, i915_ring_wait_end,
 	    TP_ARGS(dev)
 	    TP_ARGS(dev)
 );
 );
 
 
+TRACE_EVENT(i915_flip_request,
+	    TP_PROTO(int plane, struct drm_gem_object *obj),
+
+	    TP_ARGS(plane, obj),
+
+	    TP_STRUCT__entry(
+		    __field(int, plane)
+		    __field(struct drm_gem_object *, obj)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->plane = plane;
+		    __entry->obj = obj;
+		    ),
+
+	    TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj)
+);
+
+TRACE_EVENT(i915_flip_complete,
+	    TP_PROTO(int plane, struct drm_gem_object *obj),
+
+	    TP_ARGS(plane, obj),
+
+	    TP_STRUCT__entry(
+		    __field(int, plane)
+		    __field(struct drm_gem_object *, obj)
+		    ),
+
+	    TP_fast_assign(
+		    __entry->plane = plane;
+		    __entry->obj = obj;
+		    ),
+
+	    TP_printk("plane=%d, obj=%p", __entry->plane, __entry->obj)
+);
+
 #endif /* _I915_TRACE_H_ */
 #endif /* _I915_TRACE_H_ */
 
 
 /* This part must be outside protection */
 /* This part must be outside protection */

File diff suppressed because it is too large
+ 397 - 161
drivers/gpu/drm/i915/intel_display.c


+ 125 - 18
drivers/gpu/drm/i915/intel_dp.c

@@ -43,6 +43,7 @@
 #define DP_LINK_CONFIGURATION_SIZE	9
 #define DP_LINK_CONFIGURATION_SIZE	9
 
 
 #define IS_eDP(i) ((i)->type == INTEL_OUTPUT_EDP)
 #define IS_eDP(i) ((i)->type == INTEL_OUTPUT_EDP)
+#define IS_PCH_eDP(dp_priv) ((dp_priv)->is_pch_edp)
 
 
 struct intel_dp_priv {
 struct intel_dp_priv {
 	uint32_t output_reg;
 	uint32_t output_reg;
@@ -56,6 +57,7 @@ struct intel_dp_priv {
 	struct intel_encoder *intel_encoder;
 	struct intel_encoder *intel_encoder;
 	struct i2c_adapter adapter;
 	struct i2c_adapter adapter;
 	struct i2c_algo_dp_aux_data algo;
 	struct i2c_algo_dp_aux_data algo;
+	bool is_pch_edp;
 };
 };
 
 
 static void
 static void
@@ -128,8 +130,9 @@ intel_dp_link_required(struct drm_device *dev,
 		       struct intel_encoder *intel_encoder, int pixel_clock)
 		       struct intel_encoder *intel_encoder, int pixel_clock)
 {
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
 
 
-	if (IS_eDP(intel_encoder))
+	if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv))
 		return (pixel_clock * dev_priv->edp_bpp) / 8;
 		return (pixel_clock * dev_priv->edp_bpp) / 8;
 	else
 	else
 		return pixel_clock * 3;
 		return pixel_clock * 3;
@@ -147,9 +150,21 @@ intel_dp_mode_valid(struct drm_connector *connector,
 {
 {
 	struct drm_encoder *encoder = intel_attached_encoder(connector);
 	struct drm_encoder *encoder = intel_attached_encoder(connector);
 	struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
 	struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
+	struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
 	int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_encoder));
 	int max_lanes = intel_dp_max_lane_count(intel_encoder);
 	int max_lanes = intel_dp_max_lane_count(intel_encoder);
 
 
+	if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
+	    dev_priv->panel_fixed_mode) {
+		if (mode->hdisplay > dev_priv->panel_fixed_mode->hdisplay)
+			return MODE_PANEL;
+
+		if (mode->vdisplay > dev_priv->panel_fixed_mode->vdisplay)
+			return MODE_PANEL;
+	}
+
 	/* only refuse the mode on non eDP since we have seen some wierd eDP panels
 	/* only refuse the mode on non eDP since we have seen some wierd eDP panels
 	   which are outside spec tolerances but somehow work by magic */
 	   which are outside spec tolerances but somehow work by magic */
 	if (!IS_eDP(intel_encoder) &&
 	if (!IS_eDP(intel_encoder) &&
@@ -508,11 +523,37 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
 {
 {
 	struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
 	struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
 	struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
 	struct intel_dp_priv   *dp_priv = intel_encoder->dev_priv;
+	struct drm_device *dev = encoder->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	int lane_count, clock;
 	int lane_count, clock;
 	int max_lane_count = intel_dp_max_lane_count(intel_encoder);
 	int max_lane_count = intel_dp_max_lane_count(intel_encoder);
 	int max_clock = intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0;
 	int max_clock = intel_dp_max_link_bw(intel_encoder) == DP_LINK_BW_2_7 ? 1 : 0;
 	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
 	static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 };
 
 
+	if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
+	    dev_priv->panel_fixed_mode) {
+		struct drm_display_mode *fixed_mode = dev_priv->panel_fixed_mode;
+
+		adjusted_mode->hdisplay = fixed_mode->hdisplay;
+		adjusted_mode->hsync_start = fixed_mode->hsync_start;
+		adjusted_mode->hsync_end = fixed_mode->hsync_end;
+		adjusted_mode->htotal = fixed_mode->htotal;
+
+		adjusted_mode->vdisplay = fixed_mode->vdisplay;
+		adjusted_mode->vsync_start = fixed_mode->vsync_start;
+		adjusted_mode->vsync_end = fixed_mode->vsync_end;
+		adjusted_mode->vtotal = fixed_mode->vtotal;
+
+		adjusted_mode->clock = fixed_mode->clock;
+		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
+
+		/*
+		 * the mode->clock is used to calculate the Data&Link M/N
+		 * of the pipe. For the eDP the fixed clock should be used.
+		 */
+		mode->clock = dev_priv->panel_fixed_mode->clock;
+	}
+
 	for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
 	for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) {
 		for (clock = 0; clock <= max_clock; clock++) {
 		for (clock = 0; clock <= max_clock; clock++) {
 			int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
 			int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count);
@@ -531,7 +572,7 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		}
 		}
 	}
 	}
 
 
-	if (IS_eDP(intel_encoder)) {
+	if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
 		/* okay we failed just pick the highest */
 		/* okay we failed just pick the highest */
 		dp_priv->lane_count = max_lane_count;
 		dp_priv->lane_count = max_lane_count;
 		dp_priv->link_bw = bws[max_clock];
 		dp_priv->link_bw = bws[max_clock];
@@ -563,14 +604,14 @@ intel_reduce_ratio(uint32_t *num, uint32_t *den)
 }
 }
 
 
 static void
 static void
-intel_dp_compute_m_n(int bytes_per_pixel,
+intel_dp_compute_m_n(int bpp,
 		     int nlanes,
 		     int nlanes,
 		     int pixel_clock,
 		     int pixel_clock,
 		     int link_clock,
 		     int link_clock,
 		     struct intel_dp_m_n *m_n)
 		     struct intel_dp_m_n *m_n)
 {
 {
 	m_n->tu = 64;
 	m_n->tu = 64;
-	m_n->gmch_m = pixel_clock * bytes_per_pixel;
+	m_n->gmch_m = (pixel_clock * bpp) >> 3;
 	m_n->gmch_n = link_clock * nlanes;
 	m_n->gmch_n = link_clock * nlanes;
 	intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
 	intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n);
 	m_n->link_m = pixel_clock;
 	m_n->link_m = pixel_clock;
@@ -578,6 +619,28 @@ intel_dp_compute_m_n(int bytes_per_pixel,
 	intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
 	intel_reduce_ratio(&m_n->link_m, &m_n->link_n);
 }
 }
 
 
+bool intel_pch_has_edp(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_mode_config *mode_config = &dev->mode_config;
+	struct drm_encoder *encoder;
+
+	list_for_each_entry(encoder, &mode_config->encoder_list, head) {
+		struct intel_encoder *intel_encoder;
+		struct intel_dp_priv *dp_priv;
+
+		if (!encoder || encoder->crtc != crtc)
+			continue;
+
+		intel_encoder = enc_to_intel_encoder(encoder);
+		dp_priv = intel_encoder->dev_priv;
+
+		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT)
+			return dp_priv->is_pch_edp;
+	}
+	return false;
+}
+
 void
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode)
 		 struct drm_display_mode *adjusted_mode)
@@ -587,7 +650,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	struct drm_encoder *encoder;
 	struct drm_encoder *encoder;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-	int lane_count = 4;
+	int lane_count = 4, bpp = 24;
 	struct intel_dp_m_n m_n;
 	struct intel_dp_m_n m_n;
 
 
 	/*
 	/*
@@ -605,6 +668,8 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 
 
 		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
 		if (intel_encoder->type == INTEL_OUTPUT_DISPLAYPORT) {
 			lane_count = dp_priv->lane_count;
 			lane_count = dp_priv->lane_count;
+			if (IS_PCH_eDP(dp_priv))
+				bpp = dev_priv->edp_bpp;
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -614,7 +679,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 	 * the number of bytes_per_pixel post-LUT, which we always
 	 * the number of bytes_per_pixel post-LUT, which we always
 	 * set up for 8-bits of R/G/B, or 3 bytes total.
 	 * set up for 8-bits of R/G/B, or 3 bytes total.
 	 */
 	 */
-	intel_dp_compute_m_n(3, lane_count,
+	intel_dp_compute_m_n(bpp, lane_count,
 			     mode->clock, adjusted_mode->clock, &m_n);
 			     mode->clock, adjusted_mode->clock, &m_n);
 
 
 	if (HAS_PCH_SPLIT(dev)) {
 	if (HAS_PCH_SPLIT(dev)) {
@@ -796,7 +861,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
 	if (mode != DRM_MODE_DPMS_ON) {
 	if (mode != DRM_MODE_DPMS_ON) {
 		if (dp_reg & DP_PORT_EN) {
 		if (dp_reg & DP_PORT_EN) {
 			intel_dp_link_down(intel_encoder, dp_priv->DP);
 			intel_dp_link_down(intel_encoder, dp_priv->DP);
-			if (IS_eDP(intel_encoder)) {
+			if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
 				ironlake_edp_backlight_off(dev);
 				ironlake_edp_backlight_off(dev);
 				ironlake_edp_panel_off(dev);
 				ironlake_edp_panel_off(dev);
 			}
 			}
@@ -804,7 +869,7 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode)
 	} else {
 	} else {
 		if (!(dp_reg & DP_PORT_EN)) {
 		if (!(dp_reg & DP_PORT_EN)) {
 			intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
 			intel_dp_link_train(intel_encoder, dp_priv->DP, dp_priv->link_configuration);
-			if (IS_eDP(intel_encoder)) {
+			if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
 				ironlake_edp_panel_on(dev);
 				ironlake_edp_panel_on(dev);
 				ironlake_edp_backlight_on(dev);
 				ironlake_edp_backlight_on(dev);
 			}
 			}
@@ -1340,17 +1405,32 @@ static int intel_dp_get_modes(struct drm_connector *connector)
 	struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
 	struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
 	struct drm_device *dev = intel_encoder->enc.dev;
 	struct drm_device *dev = intel_encoder->enc.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_dp_priv *dp_priv = intel_encoder->dev_priv;
 	int ret;
 	int ret;
 
 
 	/* We should parse the EDID data and find out if it has an audio sink
 	/* We should parse the EDID data and find out if it has an audio sink
 	 */
 	 */
 
 
 	ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
 	ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus);
-	if (ret)
+	if (ret) {
+		if ((IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) &&
+		    !dev_priv->panel_fixed_mode) {
+			struct drm_display_mode *newmode;
+			list_for_each_entry(newmode, &connector->probed_modes,
+					    head) {
+				if (newmode->type & DRM_MODE_TYPE_PREFERRED) {
+					dev_priv->panel_fixed_mode =
+						drm_mode_duplicate(dev, newmode);
+					break;
+				}
+			}
+		}
+
 		return ret;
 		return ret;
+	}
 
 
 	/* if eDP has no EDID, try to use fixed panel mode from VBT */
 	/* if eDP has no EDID, try to use fixed panel mode from VBT */
-	if (IS_eDP(intel_encoder)) {
+	if (IS_eDP(intel_encoder) || IS_PCH_eDP(dp_priv)) {
 		if (dev_priv->panel_fixed_mode != NULL) {
 		if (dev_priv->panel_fixed_mode != NULL) {
 			struct drm_display_mode *mode;
 			struct drm_display_mode *mode;
 			mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
 			mode = drm_mode_duplicate(dev, dev_priv->panel_fixed_mode);
@@ -1435,6 +1515,26 @@ intel_trans_dp_port_sel (struct drm_crtc *crtc)
 	return -1;
 	return -1;
 }
 }
 
 
+/* check the VBT to see whether the eDP is on DP-D port */
+bool intel_dpd_is_edp(struct drm_device *dev)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct child_device_config *p_child;
+	int i;
+
+	if (!dev_priv->child_dev_num)
+		return false;
+
+	for (i = 0; i < dev_priv->child_dev_num; i++) {
+		p_child = dev_priv->child_dev + i;
+
+		if (p_child->dvo_port == PORT_IDPD &&
+		    p_child->device_type == DEVICE_TYPE_eDP)
+			return true;
+	}
+	return false;
+}
+
 void
 void
 intel_dp_init(struct drm_device *dev, int output_reg)
 intel_dp_init(struct drm_device *dev, int output_reg)
 {
 {
@@ -1444,6 +1544,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	struct intel_connector *intel_connector;
 	struct intel_connector *intel_connector;
 	struct intel_dp_priv *dp_priv;
 	struct intel_dp_priv *dp_priv;
 	const char *name = NULL;
 	const char *name = NULL;
+	int type;
 
 
 	intel_encoder = kcalloc(sizeof(struct intel_encoder) +
 	intel_encoder = kcalloc(sizeof(struct intel_encoder) +
 			       sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
 			       sizeof(struct intel_dp_priv), 1, GFP_KERNEL);
@@ -1458,18 +1559,24 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
 
 	dp_priv = (struct intel_dp_priv *)(intel_encoder + 1);
 	dp_priv = (struct intel_dp_priv *)(intel_encoder + 1);
 
 
+	if (HAS_PCH_SPLIT(dev) && (output_reg == PCH_DP_D))
+		if (intel_dpd_is_edp(dev))
+			dp_priv->is_pch_edp = true;
+
+	if (output_reg == DP_A || IS_PCH_eDP(dp_priv)) {
+		type = DRM_MODE_CONNECTOR_eDP;
+		intel_encoder->type = INTEL_OUTPUT_EDP;
+	} else {
+		type = DRM_MODE_CONNECTOR_DisplayPort;
+		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
+	}
+
 	connector = &intel_connector->base;
 	connector = &intel_connector->base;
-	drm_connector_init(dev, connector, &intel_dp_connector_funcs,
-			   DRM_MODE_CONNECTOR_DisplayPort);
+	drm_connector_init(dev, connector, &intel_dp_connector_funcs, type);
 	drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
 	drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs);
 
 
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->polled = DRM_CONNECTOR_POLL_HPD;
 
 
-	if (output_reg == DP_A)
-		intel_encoder->type = INTEL_OUTPUT_EDP;
-	else
-		intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
-
 	if (output_reg == DP_B || output_reg == PCH_DP_B)
 	if (output_reg == DP_B || output_reg == PCH_DP_B)
 		intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
 		intel_encoder->clone_mask = (1 << INTEL_DP_B_CLONE_BIT);
 	else if (output_reg == DP_C || output_reg == PCH_DP_C)
 	else if (output_reg == DP_C || output_reg == PCH_DP_C)
@@ -1528,7 +1635,7 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 	intel_encoder->ddc_bus = &dp_priv->adapter;
 	intel_encoder->ddc_bus = &dp_priv->adapter;
 	intel_encoder->hot_plug = intel_dp_hot_plug;
 	intel_encoder->hot_plug = intel_dp_hot_plug;
 
 
-	if (output_reg == DP_A) {
+	if (output_reg == DP_A || IS_PCH_eDP(dp_priv)) {
 		/* initialize panel mode from VBT if available for eDP */
 		/* initialize panel mode from VBT if available for eDP */
 		if (dev_priv->lfp_lvds_vbt_mode) {
 		if (dev_priv->lfp_lvds_vbt_mode) {
 			dev_priv->panel_fixed_mode =
 			dev_priv->panel_fixed_mode =

+ 8 - 2
drivers/gpu/drm/i915/intel_drv.h

@@ -143,8 +143,6 @@ struct intel_crtc {
 	struct drm_crtc base;
 	struct drm_crtc base;
 	enum pipe pipe;
 	enum pipe pipe;
 	enum plane plane;
 	enum plane plane;
-	struct drm_gem_object *cursor_bo;
-	uint32_t cursor_addr;
 	u8 lut_r[256], lut_g[256], lut_b[256];
 	u8 lut_r[256], lut_g[256], lut_b[256];
 	int dpms_mode;
 	int dpms_mode;
 	bool busy; /* is scanout buffer being updated frequently? */
 	bool busy; /* is scanout buffer being updated frequently? */
@@ -153,6 +151,12 @@ struct intel_crtc {
 	struct intel_overlay *overlay;
 	struct intel_overlay *overlay;
 	struct intel_unpin_work *unpin_work;
 	struct intel_unpin_work *unpin_work;
 	int fdi_lanes;
 	int fdi_lanes;
+
+	struct drm_gem_object *cursor_bo;
+	uint32_t cursor_addr;
+	int16_t cursor_x, cursor_y;
+	int16_t cursor_width, cursor_height;
+	bool cursor_visble;
 };
 };
 
 
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
 #define to_intel_crtc(x) container_of(x, struct intel_crtc, base)
@@ -179,6 +183,8 @@ extern void intel_dp_init(struct drm_device *dev, int dp_reg);
 void
 void
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
 		 struct drm_display_mode *adjusted_mode);
 		 struct drm_display_mode *adjusted_mode);
+extern bool intel_pch_has_edp(struct drm_crtc *crtc);
+extern bool intel_dpd_is_edp(struct drm_device *dev);
 extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
 extern void intel_edp_link_config (struct intel_encoder *, int *, int *);
 
 
 
 

+ 5 - 4
drivers/gpu/drm/i915/intel_hdmi.c

@@ -54,10 +54,11 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder,
 	struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
 	struct intel_hdmi_priv *hdmi_priv = intel_encoder->dev_priv;
 	u32 sdvox;
 	u32 sdvox;
 
 
-	sdvox = SDVO_ENCODING_HDMI |
-		SDVO_BORDER_ENABLE |
-		SDVO_VSYNC_ACTIVE_HIGH |
-		SDVO_HSYNC_ACTIVE_HIGH;
+	sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+		sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
+	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+		sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
 
 
 	if (hdmi_priv->has_hdmi_sink) {
 	if (hdmi_priv->has_hdmi_sink) {
 		sdvox |= SDVO_AUDIO_ENABLE;
 		sdvox |= SDVO_AUDIO_ENABLE;

+ 120 - 211
drivers/gpu/drm/i915/intel_lvds.c

@@ -156,31 +156,73 @@ static int intel_lvds_mode_valid(struct drm_connector *connector,
 	return MODE_OK;
 	return MODE_OK;
 }
 }
 
 
+static void
+centre_horizontally(struct drm_display_mode *mode,
+		    int width)
+{
+	u32 border, sync_pos, blank_width, sync_width;
+
+	/* keep the hsync and hblank widths constant */
+	sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
+	blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
+	sync_pos = (blank_width - sync_width + 1) / 2;
+
+	border = (mode->hdisplay - width + 1) / 2;
+	border += border & 1; /* make the border even */
+
+	mode->crtc_hdisplay = width;
+	mode->crtc_hblank_start = width + border;
+	mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
+
+	mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
+	mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
+}
+
+static void
+centre_vertically(struct drm_display_mode *mode,
+		  int height)
+{
+	u32 border, sync_pos, blank_width, sync_width;
+
+	/* keep the vsync and vblank widths constant */
+	sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
+	blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
+	sync_pos = (blank_width - sync_width + 1) / 2;
+
+	border = (mode->vdisplay - height + 1) / 2;
+
+	mode->crtc_vdisplay = height;
+	mode->crtc_vblank_start = height + border;
+	mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
+
+	mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
+	mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
+}
+
+static inline u32 panel_fitter_scaling(u32 source, u32 target)
+{
+	/*
+	 * Floating point operation is not supported. So the FACTOR
+	 * is defined, which can avoid the floating point computation
+	 * when calculating the panel ratio.
+	 */
+#define ACCURACY 12
+#define FACTOR (1 << ACCURACY)
+	u32 ratio = source * FACTOR / target;
+	return (FACTOR * ratio + FACTOR/2) / FACTOR;
+}
+
 static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode)
 				  struct drm_display_mode *adjusted_mode)
 {
 {
-	/*
-	 * float point operation is not supported . So the PANEL_RATIO_FACTOR
-	 * is defined, which can avoid the float point computation when
-	 * calculating the panel ratio.
-	 */
-#define PANEL_RATIO_FACTOR 8192
 	struct drm_device *dev = encoder->dev;
 	struct drm_device *dev = encoder->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
 	struct drm_encoder *tmp_encoder;
 	struct drm_encoder *tmp_encoder;
 	struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
 	struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder);
 	struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
 	struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv;
-	u32 pfit_control = 0, pfit_pgm_ratios = 0;
-	int left_border = 0, right_border = 0, top_border = 0;
-	int bottom_border = 0;
-	bool border = 0;
-	int panel_ratio, desired_ratio, vert_scale, horiz_scale;
-	int horiz_ratio, vert_ratio;
-	u32 hsync_width, vsync_width;
-	u32 hblank_width, vblank_width;
-	u32 hsync_pos, vsync_pos;
+	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
 
 
 	/* Should never happen!! */
 	/* Should never happen!! */
 	if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
 	if (!IS_I965G(dev) && intel_crtc->pipe == 0) {
@@ -200,27 +242,25 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 	if (dev_priv->panel_fixed_mode == NULL)
 	if (dev_priv->panel_fixed_mode == NULL)
 		return true;
 		return true;
 	/*
 	/*
-	 * If we have timings from the BIOS for the panel, put them in
+	 * We have timings from the BIOS for the panel, put them in
 	 * to the adjusted mode.  The CRTC will be set up for this mode,
 	 * to the adjusted mode.  The CRTC will be set up for this mode,
 	 * with the panel scaling set up to source from the H/VDisplay
 	 * with the panel scaling set up to source from the H/VDisplay
 	 * of the original mode.
 	 * of the original mode.
 	 */
 	 */
-	if (dev_priv->panel_fixed_mode != NULL) {
-		adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay;
-		adjusted_mode->hsync_start =
-			dev_priv->panel_fixed_mode->hsync_start;
-		adjusted_mode->hsync_end =
-			dev_priv->panel_fixed_mode->hsync_end;
-		adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal;
-		adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay;
-		adjusted_mode->vsync_start =
-			dev_priv->panel_fixed_mode->vsync_start;
-		adjusted_mode->vsync_end =
-			dev_priv->panel_fixed_mode->vsync_end;
-		adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal;
-		adjusted_mode->clock = dev_priv->panel_fixed_mode->clock;
-		drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
-	}
+	adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay;
+	adjusted_mode->hsync_start =
+		dev_priv->panel_fixed_mode->hsync_start;
+	adjusted_mode->hsync_end =
+		dev_priv->panel_fixed_mode->hsync_end;
+	adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal;
+	adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay;
+	adjusted_mode->vsync_start =
+		dev_priv->panel_fixed_mode->vsync_start;
+	adjusted_mode->vsync_end =
+		dev_priv->panel_fixed_mode->vsync_end;
+	adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal;
+	adjusted_mode->clock = dev_priv->panel_fixed_mode->clock;
+	drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
 
 
 	/* Make sure pre-965s set dither correctly */
 	/* Make sure pre-965s set dither correctly */
 	if (!IS_I965G(dev)) {
 	if (!IS_I965G(dev)) {
@@ -230,11 +270,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 
 
 	/* Native modes don't need fitting */
 	/* Native modes don't need fitting */
 	if (adjusted_mode->hdisplay == mode->hdisplay &&
 	if (adjusted_mode->hdisplay == mode->hdisplay &&
-			adjusted_mode->vdisplay == mode->vdisplay) {
-		pfit_pgm_ratios = 0;
-		border = 0;
+	    adjusted_mode->vdisplay == mode->vdisplay)
 		goto out;
 		goto out;
-	}
 
 
 	/* full screen scale for now */
 	/* full screen scale for now */
 	if (HAS_PCH_SPLIT(dev))
 	if (HAS_PCH_SPLIT(dev))
@@ -242,25 +279,9 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 
 
 	/* 965+ wants fuzzy fitting */
 	/* 965+ wants fuzzy fitting */
 	if (IS_I965G(dev))
 	if (IS_I965G(dev))
-		pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) |
-					PFIT_FILTER_FUZZY;
-
-	hsync_width = adjusted_mode->crtc_hsync_end -
-					adjusted_mode->crtc_hsync_start;
-	vsync_width = adjusted_mode->crtc_vsync_end -
-					adjusted_mode->crtc_vsync_start;
-	hblank_width = adjusted_mode->crtc_hblank_end -
-					adjusted_mode->crtc_hblank_start;
-	vblank_width = adjusted_mode->crtc_vblank_end -
-					adjusted_mode->crtc_vblank_start;
-	/*
-	 * Deal with panel fitting options. Figure out how to stretch the
-	 * image based on its aspect ratio & the current panel fitting mode.
-	 */
-	panel_ratio = adjusted_mode->hdisplay * PANEL_RATIO_FACTOR /
-				adjusted_mode->vdisplay;
-	desired_ratio = mode->hdisplay * PANEL_RATIO_FACTOR /
-				mode->vdisplay;
+		pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
+				 PFIT_FILTER_FUZZY);
+
 	/*
 	/*
 	 * Enable automatic panel scaling for non-native modes so that they fill
 	 * Enable automatic panel scaling for non-native modes so that they fill
 	 * the screen.  Should be enabled before the pipe is enabled, according
 	 * the screen.  Should be enabled before the pipe is enabled, according
@@ -278,170 +299,63 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 		 * For centered modes, we have to calculate border widths &
 		 * For centered modes, we have to calculate border widths &
 		 * heights and modify the values programmed into the CRTC.
 		 * heights and modify the values programmed into the CRTC.
 		 */
 		 */
-		left_border = (adjusted_mode->hdisplay - mode->hdisplay) / 2;
-		right_border = left_border;
-		if (mode->hdisplay & 1)
-			right_border++;
-		top_border = (adjusted_mode->vdisplay - mode->vdisplay) / 2;
-		bottom_border = top_border;
-		if (mode->vdisplay & 1)
-			bottom_border++;
-		/* Set active & border values */
-		adjusted_mode->crtc_hdisplay = mode->hdisplay;
-		/* Keep the boder be even */
-		if (right_border & 1)
-			right_border++;
-		/* use the border directly instead of border minuse one */
-		adjusted_mode->crtc_hblank_start = mode->hdisplay +
-						right_border;
-		/* keep the blank width constant */
-		adjusted_mode->crtc_hblank_end =
-			adjusted_mode->crtc_hblank_start + hblank_width;
-		/* get the hsync pos relative to hblank start */
-		hsync_pos = (hblank_width - hsync_width) / 2;
-		/* keep the hsync pos be even */
-		if (hsync_pos & 1)
-			hsync_pos++;
-		adjusted_mode->crtc_hsync_start =
-				adjusted_mode->crtc_hblank_start + hsync_pos;
-		/* keep the hsync width constant */
-		adjusted_mode->crtc_hsync_end =
-				adjusted_mode->crtc_hsync_start + hsync_width;
-		adjusted_mode->crtc_vdisplay = mode->vdisplay;
-		/* use the border instead of border minus one */
-		adjusted_mode->crtc_vblank_start = mode->vdisplay +
-						bottom_border;
-		/* keep the vblank width constant */
-		adjusted_mode->crtc_vblank_end =
-				adjusted_mode->crtc_vblank_start + vblank_width;
-		/* get the vsync start postion relative to vblank start */
-		vsync_pos = (vblank_width - vsync_width) / 2;
-		adjusted_mode->crtc_vsync_start =
-				adjusted_mode->crtc_vblank_start + vsync_pos;
-		/* keep the vsync width constant */
-		adjusted_mode->crtc_vsync_end =
-				adjusted_mode->crtc_vsync_start + vsync_width;
-		border = 1;
+		centre_horizontally(adjusted_mode, mode->hdisplay);
+		centre_vertically(adjusted_mode, mode->vdisplay);
+		border = LVDS_BORDER_ENABLE;
 		break;
 		break;
+
 	case DRM_MODE_SCALE_ASPECT:
 	case DRM_MODE_SCALE_ASPECT:
-		/* Scale but preserve the spect ratio */
-		pfit_control |= PFIT_ENABLE;
+		/* Scale but preserve the aspect ratio */
 		if (IS_I965G(dev)) {
 		if (IS_I965G(dev)) {
+			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
+			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
+
+			pfit_control |= PFIT_ENABLE;
 			/* 965+ is easy, it does everything in hw */
 			/* 965+ is easy, it does everything in hw */
-			if (panel_ratio > desired_ratio)
+			if (scaled_width > scaled_height)
 				pfit_control |= PFIT_SCALING_PILLAR;
 				pfit_control |= PFIT_SCALING_PILLAR;
-			else if (panel_ratio < desired_ratio)
+			else if (scaled_width < scaled_height)
 				pfit_control |= PFIT_SCALING_LETTER;
 				pfit_control |= PFIT_SCALING_LETTER;
 			else
 			else
 				pfit_control |= PFIT_SCALING_AUTO;
 				pfit_control |= PFIT_SCALING_AUTO;
 		} else {
 		} else {
+			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
+			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
 			/*
 			/*
 			 * For earlier chips we have to calculate the scaling
 			 * For earlier chips we have to calculate the scaling
 			 * ratio by hand and program it into the
 			 * ratio by hand and program it into the
 			 * PFIT_PGM_RATIO register
 			 * PFIT_PGM_RATIO register
 			 */
 			 */
-			u32 horiz_bits, vert_bits, bits = 12;
-			horiz_ratio = mode->hdisplay * PANEL_RATIO_FACTOR/
-						adjusted_mode->hdisplay;
-			vert_ratio = mode->vdisplay * PANEL_RATIO_FACTOR/
-						adjusted_mode->vdisplay;
-			horiz_scale = adjusted_mode->hdisplay *
-					PANEL_RATIO_FACTOR / mode->hdisplay;
-			vert_scale = adjusted_mode->vdisplay *
-					PANEL_RATIO_FACTOR / mode->vdisplay;
-
-			/* retain aspect ratio */
-			if (panel_ratio > desired_ratio) { /* Pillar */
-				u32 scaled_width;
-				scaled_width = mode->hdisplay * vert_scale /
-						PANEL_RATIO_FACTOR;
-				horiz_ratio = vert_ratio;
-				pfit_control |= (VERT_AUTO_SCALE |
-						 VERT_INTERP_BILINEAR |
-						 HORIZ_INTERP_BILINEAR);
-				/* Pillar will have left/right borders */
-				left_border = (adjusted_mode->hdisplay -
-						scaled_width) / 2;
-				right_border = left_border;
-				if (mode->hdisplay & 1) /* odd resolutions */
-					right_border++;
-				/* keep the border be even */
-				if (right_border & 1)
-					right_border++;
-				adjusted_mode->crtc_hdisplay = scaled_width;
-				/* use border instead of border minus one */
-				adjusted_mode->crtc_hblank_start =
-					scaled_width + right_border;
-				/* keep the hblank width constant */
-				adjusted_mode->crtc_hblank_end =
-					adjusted_mode->crtc_hblank_start +
-							hblank_width;
-				/*
-				 * get the hsync start pos relative to
-				 * hblank start
-				 */
-				hsync_pos = (hblank_width - hsync_width) / 2;
-				/* keep the hsync_pos be even */
-				if (hsync_pos & 1)
-					hsync_pos++;
-				adjusted_mode->crtc_hsync_start =
-					adjusted_mode->crtc_hblank_start +
-							hsync_pos;
-				/* keept hsync width constant */
-				adjusted_mode->crtc_hsync_end =
-					adjusted_mode->crtc_hsync_start +
-							hsync_width;
-				border = 1;
-			} else if (panel_ratio < desired_ratio) { /* letter */
-				u32 scaled_height = mode->vdisplay *
-					horiz_scale / PANEL_RATIO_FACTOR;
-				vert_ratio = horiz_ratio;
-				pfit_control |= (HORIZ_AUTO_SCALE |
-						 VERT_INTERP_BILINEAR |
-						 HORIZ_INTERP_BILINEAR);
-				/* Letterbox will have top/bottom border */
-				top_border = (adjusted_mode->vdisplay -
-					scaled_height) / 2;
-				bottom_border = top_border;
-				if (mode->vdisplay & 1)
-					bottom_border++;
-				adjusted_mode->crtc_vdisplay = scaled_height;
-				/* use border instead of border minus one */
-				adjusted_mode->crtc_vblank_start =
-					scaled_height + bottom_border;
-				/* keep the vblank width constant */
-				adjusted_mode->crtc_vblank_end =
-					adjusted_mode->crtc_vblank_start +
-							vblank_width;
-				/*
-				 * get the vsync start pos relative to
-				 * vblank start
-				 */
-				vsync_pos = (vblank_width - vsync_width) / 2;
-				adjusted_mode->crtc_vsync_start =
-					adjusted_mode->crtc_vblank_start +
-							vsync_pos;
-				/* keep the vsync width constant */
-				adjusted_mode->crtc_vsync_end =
-					adjusted_mode->crtc_vsync_start +
-							vsync_width;
-				border = 1;
-			} else {
-			/* Aspects match, Let hw scale both directions */
-				pfit_control |= (VERT_AUTO_SCALE |
-						 HORIZ_AUTO_SCALE |
+			if (scaled_width > scaled_height) { /* pillar */
+				centre_horizontally(adjusted_mode, scaled_height / mode->vdisplay);
+
+				border = LVDS_BORDER_ENABLE;
+				if (mode->vdisplay != adjusted_mode->vdisplay) {
+					u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
+					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
+							    bits << PFIT_VERT_SCALE_SHIFT);
+					pfit_control |= (PFIT_ENABLE |
+							 VERT_INTERP_BILINEAR |
+							 HORIZ_INTERP_BILINEAR);
+				}
+			} else if (scaled_width < scaled_height) { /* letter */
+				centre_vertically(adjusted_mode, scaled_width / mode->hdisplay);
+
+				border = LVDS_BORDER_ENABLE;
+				if (mode->hdisplay != adjusted_mode->hdisplay) {
+					u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
+					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
+							    bits << PFIT_VERT_SCALE_SHIFT);
+					pfit_control |= (PFIT_ENABLE |
+							 VERT_INTERP_BILINEAR |
+							 HORIZ_INTERP_BILINEAR);
+				}
+			} else
+				/* Aspects match, Let hw scale both directions */
+				pfit_control |= (PFIT_ENABLE |
+						 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
 						 VERT_INTERP_BILINEAR |
 						 VERT_INTERP_BILINEAR |
 						 HORIZ_INTERP_BILINEAR);
 						 HORIZ_INTERP_BILINEAR);
-			}
-			horiz_bits = (1 << bits) * horiz_ratio /
-					PANEL_RATIO_FACTOR;
-			vert_bits = (1 << bits) * vert_ratio /
-					PANEL_RATIO_FACTOR;
-			pfit_pgm_ratios =
-				((vert_bits << PFIT_VERT_SCALE_SHIFT) &
-						PFIT_VERT_SCALE_MASK) |
-				((horiz_bits << PFIT_HORIZ_SCALE_SHIFT) &
-						PFIT_HORIZ_SCALE_MASK);
 		}
 		}
 		break;
 		break;
 
 
@@ -458,6 +372,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 					 VERT_INTERP_BILINEAR |
 					 VERT_INTERP_BILINEAR |
 					 HORIZ_INTERP_BILINEAR);
 					 HORIZ_INTERP_BILINEAR);
 		break;
 		break;
+
 	default:
 	default:
 		break;
 		break;
 	}
 	}
@@ -465,14 +380,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
 out:
 out:
 	lvds_priv->pfit_control = pfit_control;
 	lvds_priv->pfit_control = pfit_control;
 	lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios;
 	lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios;
-	/*
-	 * When there exists the border, it means that the LVDS_BORDR
-	 * should be enabled.
-	 */
-	if (border)
-		dev_priv->lvds_border_bits |= LVDS_BORDER_ENABLE;
-	else
-		dev_priv->lvds_border_bits &= ~(LVDS_BORDER_ENABLE);
+	dev_priv->lvds_border_bits = border;
+
 	/*
 	/*
 	 * XXX: It would be nice to support lower refresh rates on the
 	 * XXX: It would be nice to support lower refresh rates on the
 	 * panels to reduce power consumption, and perhaps match the
 	 * panels to reduce power consumption, and perhaps match the

+ 9 - 5
drivers/gpu/drm/i915/intel_overlay.c

@@ -65,7 +65,7 @@
 #define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
 #define OCMD_YUV_410_PLANAR	(0xe<<10) /* also 411 */
 #define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
 #define OCMD_TVSYNCFLIP_PARITY	(0x1<<9)
 #define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
 #define OCMD_TVSYNCFLIP_ENABLE	(0x1<<7)
-#define OCMD_BUF_TYPE_MASK	(Ox1<<5)
+#define OCMD_BUF_TYPE_MASK	(0x1<<5)
 #define OCMD_BUF_TYPE_FRAME	(0x0<<5)
 #define OCMD_BUF_TYPE_FRAME	(0x0<<5)
 #define OCMD_BUF_TYPE_FIELD	(0x1<<5)
 #define OCMD_BUF_TYPE_FIELD	(0x1<<5)
 #define OCMD_TEST_MODE		(0x1<<4)
 #define OCMD_TEST_MODE		(0x1<<4)
@@ -185,7 +185,8 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over
 
 
 	if (OVERLAY_NONPHYSICAL(overlay->dev)) {
 	if (OVERLAY_NONPHYSICAL(overlay->dev)) {
 		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
 		regs = io_mapping_map_atomic_wc(dev_priv->mm.gtt_mapping,
-				overlay->reg_bo->gtt_offset);
+						overlay->reg_bo->gtt_offset,
+						KM_USER0);
 
 
 		if (!regs) {
 		if (!regs) {
 			DRM_ERROR("failed to map overlay regs in GTT\n");
 			DRM_ERROR("failed to map overlay regs in GTT\n");
@@ -200,7 +201,7 @@ static struct overlay_registers *intel_overlay_map_regs_atomic(struct intel_over
 static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
 static void intel_overlay_unmap_regs_atomic(struct intel_overlay *overlay)
 {
 {
 	if (OVERLAY_NONPHYSICAL(overlay->dev))
 	if (OVERLAY_NONPHYSICAL(overlay->dev))
-		io_mapping_unmap_atomic(overlay->virt_addr);
+		io_mapping_unmap_atomic(overlay->virt_addr, KM_USER0);
 
 
 	overlay->virt_addr = NULL;
 	overlay->virt_addr = NULL;
 
 
@@ -958,7 +959,7 @@ static int check_overlay_src(struct drm_device *dev,
 	    || rec->src_width < N_HORIZ_Y_TAPS*4)
 	    || rec->src_width < N_HORIZ_Y_TAPS*4)
 		return -EINVAL;
 		return -EINVAL;
 
 
-	/* check alingment constrains */
+	/* check alignment constraints */
 	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
 	switch (rec->flags & I915_OVERLAY_TYPE_MASK) {
 		case I915_OVERLAY_RGB:
 		case I915_OVERLAY_RGB:
 			/* not implemented */
 			/* not implemented */
@@ -990,7 +991,10 @@ static int check_overlay_src(struct drm_device *dev,
 		return -EINVAL;
 		return -EINVAL;
 
 
 	/* stride checking */
 	/* stride checking */
-	stride_mask = 63;
+	if (IS_I830(dev) || IS_845G(dev))
+		stride_mask = 255;
+	else
+		stride_mask = 63;
 
 
 	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
 	if (rec->stride_Y & stride_mask || rec->stride_UV & stride_mask)
 		return -EINVAL;
 		return -EINVAL;

+ 5 - 3
drivers/gpu/drm/i915/intel_sdvo.c

@@ -1237,9 +1237,11 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder,
 
 
 	/* Set the SDVO control regs. */
 	/* Set the SDVO control regs. */
 	if (IS_I965G(dev)) {
 	if (IS_I965G(dev)) {
-		sdvox |= SDVO_BORDER_ENABLE |
-			SDVO_VSYNC_ACTIVE_HIGH |
-			SDVO_HSYNC_ACTIVE_HIGH;
+		sdvox |= SDVO_BORDER_ENABLE;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+			sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+			sdvox |= SDVO_HSYNC_ACTIVE_HIGH;
 	} else {
 	} else {
 		sdvox |= I915_READ(sdvo_priv->sdvo_reg);
 		sdvox |= I915_READ(sdvo_priv->sdvo_reg);
 		switch (sdvo_priv->sdvo_reg) {
 		switch (sdvo_priv->sdvo_reg) {

+ 5 - 7
drivers/gpu/drm/i915/intel_tv.c

@@ -476,7 +476,7 @@ static const struct tv_mode tv_modes[] = {
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
 		.vi_end_f1	= 20,		    .vi_end_f2		= 21,
 		.nbr_end	= 240,
 		.nbr_end	= 240,
 
 
-		.burst_ena	= 8,
+		.burst_ena	= true,
 		.hburst_start	= 72,		    .hburst_len		= 34,
 		.hburst_start	= 72,		    .hburst_len		= 34,
 		.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,
 		.vburst_start_f1 = 9,		    .vburst_end_f1	= 240,
 		.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,
 		.vburst_start_f2 = 10,		    .vburst_end_f2	= 240,
@@ -896,8 +896,6 @@ static const struct tv_mode tv_modes[] = {
 	},
 	},
 };
 };
 
 
-#define NUM_TV_MODES sizeof(tv_modes) / sizeof (tv_modes[0])
-
 static void
 static void
 intel_tv_dpms(struct drm_encoder *encoder, int mode)
 intel_tv_dpms(struct drm_encoder *encoder, int mode)
 {
 {
@@ -1512,7 +1510,7 @@ intel_tv_set_property(struct drm_connector *connector, struct drm_property *prop
 		tv_priv->margin[TV_MARGIN_BOTTOM] = val;
 		tv_priv->margin[TV_MARGIN_BOTTOM] = val;
 		changed = true;
 		changed = true;
 	} else if (property == dev->mode_config.tv_mode_property) {
 	} else if (property == dev->mode_config.tv_mode_property) {
-		if (val >= NUM_TV_MODES) {
+		if (val >= ARRAY_SIZE(tv_modes)) {
 			ret = -EINVAL;
 			ret = -EINVAL;
 			goto out;
 			goto out;
 		}
 		}
@@ -1693,13 +1691,13 @@ intel_tv_init(struct drm_device *dev)
 	connector->doublescan_allowed = false;
 	connector->doublescan_allowed = false;
 
 
 	/* Create TV properties then attach current values */
 	/* Create TV properties then attach current values */
-	tv_format_names = kmalloc(sizeof(char *) * NUM_TV_MODES,
+	tv_format_names = kmalloc(sizeof(char *) * ARRAY_SIZE(tv_modes),
 				  GFP_KERNEL);
 				  GFP_KERNEL);
 	if (!tv_format_names)
 	if (!tv_format_names)
 		goto out;
 		goto out;
-	for (i = 0; i < NUM_TV_MODES; i++)
+	for (i = 0; i < ARRAY_SIZE(tv_modes); i++)
 		tv_format_names[i] = tv_modes[i].name;
 		tv_format_names[i] = tv_modes[i].name;
-	drm_mode_create_tv_properties(dev, NUM_TV_MODES, tv_format_names);
+	drm_mode_create_tv_properties(dev, ARRAY_SIZE(tv_modes), tv_format_names);
 
 
 	drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
 	drm_connector_attach_property(connector, dev->mode_config.tv_mode_property,
 				   initial_mode);
 				   initial_mode);

+ 45 - 58
drivers/gpu/drm/mga/mga_dma.c

@@ -52,7 +52,7 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup);
  * Engine control
  * Engine control
  */
  */
 
 
-int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
+int mga_do_wait_for_idle(drm_mga_private_t *dev_priv)
 {
 {
 	u32 status = 0;
 	u32 status = 0;
 	int i;
 	int i;
@@ -74,7 +74,7 @@ int mga_do_wait_for_idle(drm_mga_private_t * dev_priv)
 	return -EBUSY;
 	return -EBUSY;
 }
 }
 
 
-static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
+static int mga_do_dma_reset(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
@@ -102,7 +102,7 @@ static int mga_do_dma_reset(drm_mga_private_t * dev_priv)
  * Primary DMA stream
  * Primary DMA stream
  */
  */
 
 
-void mga_do_dma_flush(drm_mga_private_t * dev_priv)
+void mga_do_dma_flush(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 	u32 head, tail;
 	u32 head, tail;
@@ -142,11 +142,10 @@ void mga_do_dma_flush(drm_mga_private_t * dev_priv)
 
 
 	head = MGA_READ(MGA_PRIMADDRESS);
 	head = MGA_READ(MGA_PRIMADDRESS);
 
 
-	if (head <= tail) {
+	if (head <= tail)
 		primary->space = primary->size - primary->tail;
 		primary->space = primary->size - primary->tail;
-	} else {
+	else
 		primary->space = head - tail;
 		primary->space = head - tail;
-	}
 
 
 	DRM_DEBUG("   head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
 	DRM_DEBUG("   head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
 	DRM_DEBUG("   tail = 0x%06lx\n", (unsigned long)(tail - dev_priv->primary->offset));
 	DRM_DEBUG("   tail = 0x%06lx\n", (unsigned long)(tail - dev_priv->primary->offset));
@@ -158,7 +157,7 @@ void mga_do_dma_flush(drm_mga_private_t * dev_priv)
 	DRM_DEBUG("done.\n");
 	DRM_DEBUG("done.\n");
 }
 }
 
 
-void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
+void mga_do_dma_wrap_start(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 	u32 head, tail;
 	u32 head, tail;
@@ -181,11 +180,10 @@ void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
 
 
 	head = MGA_READ(MGA_PRIMADDRESS);
 	head = MGA_READ(MGA_PRIMADDRESS);
 
 
-	if (head == dev_priv->primary->offset) {
+	if (head == dev_priv->primary->offset)
 		primary->space = primary->size;
 		primary->space = primary->size;
-	} else {
+	else
 		primary->space = head - dev_priv->primary->offset;
 		primary->space = head - dev_priv->primary->offset;
-	}
 
 
 	DRM_DEBUG("   head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
 	DRM_DEBUG("   head = 0x%06lx\n", (unsigned long)(head - dev_priv->primary->offset));
 	DRM_DEBUG("   tail = 0x%06x\n", primary->tail);
 	DRM_DEBUG("   tail = 0x%06x\n", primary->tail);
@@ -199,7 +197,7 @@ void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv)
 	DRM_DEBUG("done.\n");
 	DRM_DEBUG("done.\n");
 }
 }
 
 
-void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
+void mga_do_dma_wrap_end(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -220,11 +218,11 @@ void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv)
  * Freelist management
  * Freelist management
  */
  */
 
 
-#define MGA_BUFFER_USED		~0
+#define MGA_BUFFER_USED		(~0)
 #define MGA_BUFFER_FREE		0
 #define MGA_BUFFER_FREE		0
 
 
 #if MGA_FREELIST_DEBUG
 #if MGA_FREELIST_DEBUG
-static void mga_freelist_print(struct drm_device * dev)
+static void mga_freelist_print(struct drm_device *dev)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_freelist_t *entry;
 	drm_mga_freelist_t *entry;
@@ -245,7 +243,7 @@ static void mga_freelist_print(struct drm_device * dev)
 }
 }
 #endif
 #endif
 
 
-static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_priv)
+static int mga_freelist_init(struct drm_device *dev, drm_mga_private_t *dev_priv)
 {
 {
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_buf *buf;
 	struct drm_buf *buf;
@@ -288,7 +286,7 @@ static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_pr
 	return 0;
 	return 0;
 }
 }
 
 
-static void mga_freelist_cleanup(struct drm_device * dev)
+static void mga_freelist_cleanup(struct drm_device *dev)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_freelist_t *entry;
 	drm_mga_freelist_t *entry;
@@ -308,7 +306,7 @@ static void mga_freelist_cleanup(struct drm_device * dev)
 #if 0
 #if 0
 /* FIXME: Still needed?
 /* FIXME: Still needed?
  */
  */
-static void mga_freelist_reset(struct drm_device * dev)
+static void mga_freelist_reset(struct drm_device *dev)
 {
 {
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_device_dma *dma = dev->dma;
 	struct drm_buf *buf;
 	struct drm_buf *buf;
@@ -356,7 +354,7 @@ static struct drm_buf *mga_freelist_get(struct drm_device * dev)
 	return NULL;
 	return NULL;
 }
 }
 
 
-int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
+int mga_freelist_put(struct drm_device *dev, struct drm_buf *buf)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -391,7 +389,7 @@ int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf)
  * DMA initialization, cleanup
  * DMA initialization, cleanup
  */
  */
 
 
-int mga_driver_load(struct drm_device * dev, unsigned long flags)
+int mga_driver_load(struct drm_device *dev, unsigned long flags)
 {
 {
 	drm_mga_private_t *dev_priv;
 	drm_mga_private_t *dev_priv;
 	int ret;
 	int ret;
@@ -405,8 +403,8 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags)
 	dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
 	dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;
 	dev_priv->chipset = flags;
 	dev_priv->chipset = flags;
 
 
-	dev_priv->mmio_base = drm_get_resource_start(dev, 1);
-	dev_priv->mmio_size = drm_get_resource_len(dev, 1);
+	dev_priv->mmio_base = pci_resource_start(dev->pdev, 1);
+	dev_priv->mmio_size = pci_resource_len(dev->pdev, 1);
 
 
 	dev->counters += 3;
 	dev->counters += 3;
 	dev->types[6] = _DRM_STAT_IRQ;
 	dev->types[6] = _DRM_STAT_IRQ;
@@ -439,8 +437,8 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags)
  *
  *
  * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
  * \sa mga_do_dma_bootstrap, mga_do_pci_dma_bootstrap
  */
  */
-static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
-				    drm_mga_dma_bootstrap_t * dma_bs)
+static int mga_do_agp_dma_bootstrap(struct drm_device *dev,
+				    drm_mga_dma_bootstrap_t *dma_bs)
 {
 {
 	drm_mga_private_t *const dev_priv =
 	drm_mga_private_t *const dev_priv =
 	    (drm_mga_private_t *) dev->dev_private;
 	    (drm_mga_private_t *) dev->dev_private;
@@ -481,11 +479,10 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
 	 */
 	 */
 
 
 	if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
 	if (dev_priv->chipset == MGA_CARD_TYPE_G200) {
-		if (mode.mode & 0x02) {
+		if (mode.mode & 0x02)
 			MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
 			MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_ENABLE);
-		} else {
+		else
 			MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
 			MGA_WRITE(MGA_AGP_PLL, MGA_AGP2XPLL_DISABLE);
-		}
 	}
 	}
 
 
 	/* Allocate and bind AGP memory. */
 	/* Allocate and bind AGP memory. */
@@ -593,8 +590,8 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
 	return 0;
 	return 0;
 }
 }
 #else
 #else
-static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
-				    drm_mga_dma_bootstrap_t * dma_bs)
+static int mga_do_agp_dma_bootstrap(struct drm_device *dev,
+				    drm_mga_dma_bootstrap_t *dma_bs)
 {
 {
 	return -EINVAL;
 	return -EINVAL;
 }
 }
@@ -614,8 +611,8 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
  *
  *
  * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
  * \sa mga_do_dma_bootstrap, mga_do_agp_dma_bootstrap
  */
  */
-static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
-				    drm_mga_dma_bootstrap_t * dma_bs)
+static int mga_do_pci_dma_bootstrap(struct drm_device *dev,
+				    drm_mga_dma_bootstrap_t *dma_bs)
 {
 {
 	drm_mga_private_t *const dev_priv =
 	drm_mga_private_t *const dev_priv =
 	    (drm_mga_private_t *) dev->dev_private;
 	    (drm_mga_private_t *) dev->dev_private;
@@ -678,9 +675,8 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
 		req.size = dma_bs->secondary_bin_size;
 		req.size = dma_bs->secondary_bin_size;
 
 
 		err = drm_addbufs_pci(dev, &req);
 		err = drm_addbufs_pci(dev, &req);
-		if (!err) {
+		if (!err)
 			break;
 			break;
-		}
 	}
 	}
 
 
 	if (bin_count == 0) {
 	if (bin_count == 0) {
@@ -704,8 +700,8 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
 	return 0;
 	return 0;
 }
 }
 
 
-static int mga_do_dma_bootstrap(struct drm_device * dev,
-				drm_mga_dma_bootstrap_t * dma_bs)
+static int mga_do_dma_bootstrap(struct drm_device *dev,
+				drm_mga_dma_bootstrap_t *dma_bs)
 {
 {
 	const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
 	const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
 	int err;
 	int err;
@@ -737,17 +733,15 @@ static int mga_do_dma_bootstrap(struct drm_device * dev,
 	 * carve off portions of it for internal uses.  The remaining memory
 	 * carve off portions of it for internal uses.  The remaining memory
 	 * is returned to user-mode to be used for AGP textures.
 	 * is returned to user-mode to be used for AGP textures.
 	 */
 	 */
-	if (is_agp) {
+	if (is_agp)
 		err = mga_do_agp_dma_bootstrap(dev, dma_bs);
 		err = mga_do_agp_dma_bootstrap(dev, dma_bs);
-	}
 
 
 	/* If we attempted to initialize the card for AGP DMA but failed,
 	/* If we attempted to initialize the card for AGP DMA but failed,
 	 * clean-up any mess that may have been created.
 	 * clean-up any mess that may have been created.
 	 */
 	 */
 
 
-	if (err) {
+	if (err)
 		mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
 		mga_do_cleanup_dma(dev, MINIMAL_CLEANUP);
-	}
 
 
 	/* Not only do we want to try and initialized PCI cards for PCI DMA,
 	/* Not only do we want to try and initialized PCI cards for PCI DMA,
 	 * but we also try to initialized AGP cards that could not be
 	 * but we also try to initialized AGP cards that could not be
@@ -757,9 +751,8 @@ static int mga_do_dma_bootstrap(struct drm_device * dev,
 	 * AGP memory, etc.
 	 * AGP memory, etc.
 	 */
 	 */
 
 
-	if (!is_agp || err) {
+	if (!is_agp || err)
 		err = mga_do_pci_dma_bootstrap(dev, dma_bs);
 		err = mga_do_pci_dma_bootstrap(dev, dma_bs);
-	}
 
 
 	return err;
 	return err;
 }
 }
@@ -792,7 +785,7 @@ int mga_dma_bootstrap(struct drm_device *dev, void *data,
 	return err;
 	return err;
 }
 }
 
 
-static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
+static int mga_do_init_dma(struct drm_device *dev, drm_mga_init_t *init)
 {
 {
 	drm_mga_private_t *dev_priv;
 	drm_mga_private_t *dev_priv;
 	int ret;
 	int ret;
@@ -800,11 +793,10 @@ static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init)
 
 
 	dev_priv = dev->dev_private;
 	dev_priv = dev->dev_private;
 
 
-	if (init->sgram) {
+	if (init->sgram)
 		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
 		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
-	} else {
+	else
 		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
 		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
-	}
 	dev_priv->maccess = init->maccess;
 	dev_priv->maccess = init->maccess;
 
 
 	dev_priv->fb_cpp = init->fb_cpp;
 	dev_priv->fb_cpp = init->fb_cpp;
@@ -975,9 +967,8 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
 				dev_priv->agp_handle = 0;
 				dev_priv->agp_handle = 0;
 			}
 			}
 
 
-			if ((dev->agp != NULL) && dev->agp->acquired) {
+			if ((dev->agp != NULL) && dev->agp->acquired)
 				err = drm_agp_release(dev);
 				err = drm_agp_release(dev);
-			}
 #endif
 #endif
 		}
 		}
 
 
@@ -998,9 +989,8 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup)
 		memset(dev_priv->warp_pipe_phys, 0,
 		memset(dev_priv->warp_pipe_phys, 0,
 		       sizeof(dev_priv->warp_pipe_phys));
 		       sizeof(dev_priv->warp_pipe_phys));
 
 
-		if (dev_priv->head != NULL) {
+		if (dev_priv->head != NULL)
 			mga_freelist_cleanup(dev);
 			mga_freelist_cleanup(dev);
-		}
 	}
 	}
 
 
 	return err;
 	return err;
@@ -1017,9 +1007,8 @@ int mga_dma_init(struct drm_device *dev, void *data,
 	switch (init->func) {
 	switch (init->func) {
 	case MGA_INIT_DMA:
 	case MGA_INIT_DMA:
 		err = mga_do_init_dma(dev, init);
 		err = mga_do_init_dma(dev, init);
-		if (err) {
+		if (err)
 			(void)mga_do_cleanup_dma(dev, FULL_CLEANUP);
 			(void)mga_do_cleanup_dma(dev, FULL_CLEANUP);
-		}
 		return err;
 		return err;
 	case MGA_CLEANUP_DMA:
 	case MGA_CLEANUP_DMA:
 		return mga_do_cleanup_dma(dev, FULL_CLEANUP);
 		return mga_do_cleanup_dma(dev, FULL_CLEANUP);
@@ -1047,9 +1036,8 @@ int mga_dma_flush(struct drm_device *dev, void *data,
 
 
 	WRAP_WAIT_WITH_RETURN(dev_priv);
 	WRAP_WAIT_WITH_RETURN(dev_priv);
 
 
-	if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) {
+	if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL))
 		mga_do_dma_flush(dev_priv);
 		mga_do_dma_flush(dev_priv);
-	}
 
 
 	if (lock->flags & _DRM_LOCK_QUIESCENT) {
 	if (lock->flags & _DRM_LOCK_QUIESCENT) {
 #if MGA_DMA_DEBUG
 #if MGA_DMA_DEBUG
@@ -1079,8 +1067,8 @@ int mga_dma_reset(struct drm_device *dev, void *data,
  * DMA buffer management
  * DMA buffer management
  */
  */
 
 
-static int mga_dma_get_buffers(struct drm_device * dev,
-			       struct drm_file *file_priv, struct drm_dma * d)
+static int mga_dma_get_buffers(struct drm_device *dev,
+			       struct drm_file *file_priv, struct drm_dma *d)
 {
 {
 	struct drm_buf *buf;
 	struct drm_buf *buf;
 	int i;
 	int i;
@@ -1134,9 +1122,8 @@ int mga_dma_buffers(struct drm_device *dev, void *data,
 
 
 	d->granted_count = 0;
 	d->granted_count = 0;
 
 
-	if (d->request_count) {
+	if (d->request_count)
 		ret = mga_dma_get_buffers(dev, file_priv, d);
 		ret = mga_dma_get_buffers(dev, file_priv, d);
-	}
 
 
 	return ret;
 	return ret;
 }
 }
@@ -1144,7 +1131,7 @@ int mga_dma_buffers(struct drm_device *dev, void *data,
 /**
 /**
  * Called just before the module is unloaded.
  * Called just before the module is unloaded.
  */
  */
-int mga_driver_unload(struct drm_device * dev)
+int mga_driver_unload(struct drm_device *dev)
 {
 {
 	kfree(dev->dev_private);
 	kfree(dev->dev_private);
 	dev->dev_private = NULL;
 	dev->dev_private = NULL;
@@ -1155,12 +1142,12 @@ int mga_driver_unload(struct drm_device * dev)
 /**
 /**
  * Called when the last opener of the device is closed.
  * Called when the last opener of the device is closed.
  */
  */
-void mga_driver_lastclose(struct drm_device * dev)
+void mga_driver_lastclose(struct drm_device *dev)
 {
 {
 	mga_do_cleanup_dma(dev, FULL_CLEANUP);
 	mga_do_cleanup_dma(dev, FULL_CLEANUP);
 }
 }
 
 
-int mga_driver_dma_quiescent(struct drm_device * dev)
+int mga_driver_dma_quiescent(struct drm_device *dev)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	return mga_do_wait_for_idle(dev_priv);
 	return mga_do_wait_for_idle(dev_priv);

+ 2 - 2
drivers/gpu/drm/mga/mga_drv.c

@@ -36,7 +36,7 @@
 
 
 #include "drm_pciids.h"
 #include "drm_pciids.h"
 
 
-static int mga_driver_device_is_agp(struct drm_device * dev);
+static int mga_driver_device_is_agp(struct drm_device *dev);
 
 
 static struct pci_device_id pciidlist[] = {
 static struct pci_device_id pciidlist[] = {
 	mga_PCI_IDS
 	mga_PCI_IDS
@@ -119,7 +119,7 @@ MODULE_LICENSE("GPL and additional rights");
  * \returns
  * \returns
  * If the device is a PCI G450, zero is returned.  Otherwise 2 is returned.
  * If the device is a PCI G450, zero is returned.  Otherwise 2 is returned.
  */
  */
-static int mga_driver_device_is_agp(struct drm_device * dev)
+static int mga_driver_device_is_agp(struct drm_device *dev)
 {
 {
 	const struct pci_dev *const pdev = dev->pdev;
 	const struct pci_dev *const pdev = dev->pdev;
 
 

+ 91 - 96
drivers/gpu/drm/mga/mga_drv.h

@@ -164,59 +164,59 @@ extern int mga_dma_reset(struct drm_device *dev, void *data,
 extern int mga_dma_buffers(struct drm_device *dev, void *data,
 extern int mga_dma_buffers(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv);
 			   struct drm_file *file_priv);
 extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
 extern int mga_driver_load(struct drm_device *dev, unsigned long flags);
-extern int mga_driver_unload(struct drm_device * dev);
-extern void mga_driver_lastclose(struct drm_device * dev);
-extern int mga_driver_dma_quiescent(struct drm_device * dev);
+extern int mga_driver_unload(struct drm_device *dev);
+extern void mga_driver_lastclose(struct drm_device *dev);
+extern int mga_driver_dma_quiescent(struct drm_device *dev);
 
 
-extern int mga_do_wait_for_idle(drm_mga_private_t * dev_priv);
+extern int mga_do_wait_for_idle(drm_mga_private_t *dev_priv);
 
 
-extern void mga_do_dma_flush(drm_mga_private_t * dev_priv);
-extern void mga_do_dma_wrap_start(drm_mga_private_t * dev_priv);
-extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
+extern void mga_do_dma_flush(drm_mga_private_t *dev_priv);
+extern void mga_do_dma_wrap_start(drm_mga_private_t *dev_priv);
+extern void mga_do_dma_wrap_end(drm_mga_private_t *dev_priv);
 
 
-extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
+extern int mga_freelist_put(struct drm_device *dev, struct drm_buf *buf);
 
 
 				/* mga_warp.c */
 				/* mga_warp.c */
-extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
-extern int mga_warp_init(drm_mga_private_t * dev_priv);
+extern int mga_warp_install_microcode(drm_mga_private_t *dev_priv);
+extern int mga_warp_init(drm_mga_private_t *dev_priv);
 
 
 				/* mga_irq.c */
 				/* mga_irq.c */
 extern int mga_enable_vblank(struct drm_device *dev, int crtc);
 extern int mga_enable_vblank(struct drm_device *dev, int crtc);
 extern void mga_disable_vblank(struct drm_device *dev, int crtc);
 extern void mga_disable_vblank(struct drm_device *dev, int crtc);
 extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
 extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
-extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
-extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
+extern int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence);
+extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence);
 extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
 extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
-extern void mga_driver_irq_preinstall(struct drm_device * dev);
+extern void mga_driver_irq_preinstall(struct drm_device *dev);
 extern int mga_driver_irq_postinstall(struct drm_device *dev);
 extern int mga_driver_irq_postinstall(struct drm_device *dev);
-extern void mga_driver_irq_uninstall(struct drm_device * dev);
+extern void mga_driver_irq_uninstall(struct drm_device *dev);
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
 extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
 			     unsigned long arg);
 			     unsigned long arg);
 
 
 #define mga_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
 #define mga_flush_write_combine()	DRM_WRITEMEMORYBARRIER()
 
 
 #if defined(__linux__) && defined(__alpha__)
 #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_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_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)
+#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)
+static inline u32 _MGA_READ(u32 *addr)
 {
 {
 	DRM_MEMORYBARRIER();
 	DRM_MEMORYBARRIER();
 	return *(volatile u32 *)addr;
 	return *(volatile u32 *)addr;
 }
 }
 #else
 #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))
+#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
 #endif
 
 
 #define DWGREG0		0x1c00
 #define DWGREG0		0x1c00
@@ -233,40 +233,39 @@ static inline u32 _MGA_READ(u32 * addr)
  * Helper macross...
  * Helper macross...
  */
  */
 
 
-#define MGA_EMIT_STATE( dev_priv, dirty )				\
+#define MGA_EMIT_STATE(dev_priv, dirty)					\
 do {									\
 do {									\
-	if ( (dirty) & ~MGA_UPLOAD_CLIPRECTS ) {			\
-		if ( dev_priv->chipset >= MGA_CARD_TYPE_G400 ) {	\
-			mga_g400_emit_state( dev_priv );		\
-		} else {						\
-			mga_g200_emit_state( dev_priv );		\
-		}							\
+	if ((dirty) & ~MGA_UPLOAD_CLIPRECTS) {				\
+		if (dev_priv->chipset >= MGA_CARD_TYPE_G400)		\
+			mga_g400_emit_state(dev_priv);			\
+		else							\
+			mga_g200_emit_state(dev_priv);			\
 	}								\
 	}								\
 } while (0)
 } while (0)
 
 
-#define WRAP_TEST_WITH_RETURN( dev_priv )				\
+#define WRAP_TEST_WITH_RETURN(dev_priv)					\
 do {									\
 do {									\
-	if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {			\
-		if ( mga_is_idle( dev_priv ) ) {			\
-			mga_do_dma_wrap_end( dev_priv );		\
-		} else if ( dev_priv->prim.space <			\
-			    dev_priv->prim.high_mark ) {		\
-			if ( MGA_DMA_DEBUG )				\
-				DRM_INFO( "wrap...\n");		\
-			return -EBUSY;			\
+	if (test_bit(0, &dev_priv->prim.wrapped)) {			\
+		if (mga_is_idle(dev_priv)) {				\
+			mga_do_dma_wrap_end(dev_priv);			\
+		} else if (dev_priv->prim.space <			\
+			   dev_priv->prim.high_mark) {			\
+			if (MGA_DMA_DEBUG)				\
+				DRM_INFO("wrap...\n");			\
+			return -EBUSY;					\
 		}							\
 		}							\
 	}								\
 	}								\
 } while (0)
 } while (0)
 
 
-#define WRAP_WAIT_WITH_RETURN( dev_priv )				\
+#define WRAP_WAIT_WITH_RETURN(dev_priv)					\
 do {									\
 do {									\
-	if ( test_bit( 0, &dev_priv->prim.wrapped ) ) {			\
-		if ( mga_do_wait_for_idle( dev_priv ) < 0 ) {		\
-			if ( MGA_DMA_DEBUG )				\
-				DRM_INFO( "wrap...\n");		\
-			return -EBUSY;			\
+	if (test_bit(0, &dev_priv->prim.wrapped)) {			\
+		if (mga_do_wait_for_idle(dev_priv) < 0) {		\
+			if (MGA_DMA_DEBUG)				\
+				DRM_INFO("wrap...\n");			\
+			return -EBUSY;					\
 		}							\
 		}							\
-		mga_do_dma_wrap_end( dev_priv );			\
+		mga_do_dma_wrap_end(dev_priv);				\
 	}								\
 	}								\
 } while (0)
 } while (0)
 
 
@@ -280,12 +279,12 @@ do {									\
 
 
 #define DMA_BLOCK_SIZE	(5 * sizeof(u32))
 #define DMA_BLOCK_SIZE	(5 * sizeof(u32))
 
 
-#define BEGIN_DMA( n )							\
+#define BEGIN_DMA(n)							\
 do {									\
 do {									\
-	if ( MGA_VERBOSE ) {						\
-		DRM_INFO( "BEGIN_DMA( %d )\n", (n) );		\
-		DRM_INFO( "   space=0x%x req=0x%Zx\n",			\
-			  dev_priv->prim.space, (n) * DMA_BLOCK_SIZE );	\
+	if (MGA_VERBOSE) {						\
+		DRM_INFO("BEGIN_DMA(%d)\n", (n));			\
+		DRM_INFO("   space=0x%x req=0x%Zx\n",			\
+			 dev_priv->prim.space, (n) * DMA_BLOCK_SIZE);	\
 	}								\
 	}								\
 	prim = dev_priv->prim.start;					\
 	prim = dev_priv->prim.start;					\
 	write = dev_priv->prim.tail;					\
 	write = dev_priv->prim.tail;					\
@@ -293,9 +292,9 @@ do {									\
 
 
 #define BEGIN_DMA_WRAP()						\
 #define BEGIN_DMA_WRAP()						\
 do {									\
 do {									\
-	if ( MGA_VERBOSE ) {						\
-		DRM_INFO( "BEGIN_DMA()\n" );				\
-		DRM_INFO( "   space=0x%x\n", dev_priv->prim.space );	\
+	if (MGA_VERBOSE) {						\
+		DRM_INFO("BEGIN_DMA()\n");				\
+		DRM_INFO("   space=0x%x\n", dev_priv->prim.space);	\
 	}								\
 	}								\
 	prim = dev_priv->prim.start;					\
 	prim = dev_priv->prim.start;					\
 	write = dev_priv->prim.tail;					\
 	write = dev_priv->prim.tail;					\
@@ -304,72 +303,68 @@ do {									\
 #define ADVANCE_DMA()							\
 #define ADVANCE_DMA()							\
 do {									\
 do {									\
 	dev_priv->prim.tail = write;					\
 	dev_priv->prim.tail = write;					\
-	if ( MGA_VERBOSE ) {						\
-		DRM_INFO( "ADVANCE_DMA() tail=0x%05x sp=0x%x\n",	\
-			  write, dev_priv->prim.space );		\
-	}								\
+	if (MGA_VERBOSE)						\
+		DRM_INFO("ADVANCE_DMA() tail=0x%05x sp=0x%x\n",		\
+			 write, dev_priv->prim.space);			\
 } while (0)
 } while (0)
 
 
 #define FLUSH_DMA()							\
 #define FLUSH_DMA()							\
 do {									\
 do {									\
-	if ( 0 ) {							\
-		DRM_INFO( "\n" );					\
-		DRM_INFO( "   tail=0x%06x head=0x%06lx\n",		\
-			  dev_priv->prim.tail,				\
-			  (unsigned long)(MGA_READ(MGA_PRIMADDRESS) -	\
-					  dev_priv->primary->offset));	\
+	if (0) {							\
+		DRM_INFO("\n");						\
+		DRM_INFO("   tail=0x%06x head=0x%06lx\n",		\
+			 dev_priv->prim.tail,				\
+			 (unsigned long)(MGA_READ(MGA_PRIMADDRESS) -	\
+					 dev_priv->primary->offset));	\
 	}								\
 	}								\
-	if ( !test_bit( 0, &dev_priv->prim.wrapped ) ) {		\
-		if ( dev_priv->prim.space <				\
-		     dev_priv->prim.high_mark ) {			\
-			mga_do_dma_wrap_start( dev_priv );		\
-		} else {						\
-			mga_do_dma_flush( dev_priv );			\
-		}							\
+	if (!test_bit(0, &dev_priv->prim.wrapped)) {			\
+		if (dev_priv->prim.space < dev_priv->prim.high_mark)	\
+			mga_do_dma_wrap_start(dev_priv);		\
+		else							\
+			mga_do_dma_flush(dev_priv);			\
 	}								\
 	}								\
 } while (0)
 } while (0)
 
 
 /* Never use this, always use DMA_BLOCK(...) for primary DMA output.
 /* Never use this, always use DMA_BLOCK(...) for primary DMA output.
  */
  */
-#define DMA_WRITE( offset, val )					\
+#define DMA_WRITE(offset, val)						\
 do {									\
 do {									\
-	if ( MGA_VERBOSE ) {						\
-		DRM_INFO( "   DMA_WRITE( 0x%08x ) at 0x%04Zx\n",	\
-			  (u32)(val), write + (offset) * sizeof(u32) );	\
-	}								\
+	if (MGA_VERBOSE)						\
+		DRM_INFO("   DMA_WRITE( 0x%08x ) at 0x%04Zx\n",		\
+			 (u32)(val), write + (offset) * sizeof(u32));	\
 	*(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val;	\
 	*(volatile u32 *)(prim + write + (offset) * sizeof(u32)) = val;	\
 } while (0)
 } while (0)
 
 
-#define DMA_BLOCK( reg0, val0, reg1, val1, reg2, val2, reg3, val3 )	\
+#define DMA_BLOCK(reg0, val0, reg1, val1, reg2, val2, reg3, val3)	\
 do {									\
 do {									\
-	DMA_WRITE( 0, ((DMAREG( reg0 ) << 0) |				\
-		       (DMAREG( reg1 ) << 8) |				\
-		       (DMAREG( reg2 ) << 16) |				\
-		       (DMAREG( reg3 ) << 24)) );			\
-	DMA_WRITE( 1, val0 );						\
-	DMA_WRITE( 2, val1 );						\
-	DMA_WRITE( 3, val2 );						\
-	DMA_WRITE( 4, val3 );						\
+	DMA_WRITE(0, ((DMAREG(reg0) << 0) |				\
+		      (DMAREG(reg1) << 8) |				\
+		      (DMAREG(reg2) << 16) |				\
+		      (DMAREG(reg3) << 24)));				\
+	DMA_WRITE(1, val0);						\
+	DMA_WRITE(2, val1);						\
+	DMA_WRITE(3, val2);						\
+	DMA_WRITE(4, val3);						\
 	write += DMA_BLOCK_SIZE;					\
 	write += DMA_BLOCK_SIZE;					\
 } while (0)
 } while (0)
 
 
 /* Buffer aging via primary DMA stream head pointer.
 /* Buffer aging via primary DMA stream head pointer.
  */
  */
 
 
-#define SET_AGE( age, h, w )						\
+#define SET_AGE(age, h, w)						\
 do {									\
 do {									\
 	(age)->head = h;						\
 	(age)->head = h;						\
 	(age)->wrap = w;						\
 	(age)->wrap = w;						\
 } while (0)
 } while (0)
 
 
-#define TEST_AGE( age, h, w )		( (age)->wrap < w ||		\
-					  ( (age)->wrap == w &&		\
-					    (age)->head < h ) )
+#define TEST_AGE(age, h, w)		((age)->wrap < w ||		\
+					 ((age)->wrap == w &&		\
+					  (age)->head < h))
 
 
-#define AGE_BUFFER( buf_priv )						\
+#define AGE_BUFFER(buf_priv)						\
 do {									\
 do {									\
 	drm_mga_freelist_t *entry = (buf_priv)->list_entry;		\
 	drm_mga_freelist_t *entry = (buf_priv)->list_entry;		\
-	if ( (buf_priv)->dispatched ) {					\
+	if ((buf_priv)->dispatched) {					\
 		entry->age.head = (dev_priv->prim.tail +		\
 		entry->age.head = (dev_priv->prim.tail +		\
 				   dev_priv->primary->offset);		\
 				   dev_priv->primary->offset);		\
 		entry->age.wrap = dev_priv->sarea_priv->last_wrap;	\
 		entry->age.wrap = dev_priv->sarea_priv->last_wrap;	\
@@ -681,7 +676,7 @@ do {									\
 
 
 /* Simple idle test.
 /* Simple idle test.
  */
  */
-static __inline__ int mga_is_idle(drm_mga_private_t * dev_priv)
+static __inline__ int mga_is_idle(drm_mga_private_t *dev_priv)
 {
 {
 	u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
 	u32 status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK;
 	return (status == MGA_ENDPRDMASTS);
 	return (status == MGA_ENDPRDMASTS);

+ 4 - 5
drivers/gpu/drm/mga/mga_irq.c

@@ -76,9 +76,8 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
 		/* In addition to clearing the interrupt-pending bit, we
 		/* In addition to clearing the interrupt-pending bit, we
 		 * have to write to MGA_PRIMEND to re-start the DMA operation.
 		 * have to write to MGA_PRIMEND to re-start the DMA operation.
 		 */
 		 */
-		if ((prim_start & ~0x03) != (prim_end & ~0x03)) {
+		if ((prim_start & ~0x03) != (prim_end & ~0x03))
 			MGA_WRITE(MGA_PRIMEND, prim_end);
 			MGA_WRITE(MGA_PRIMEND, prim_end);
-		}
 
 
 		atomic_inc(&dev_priv->last_fence_retired);
 		atomic_inc(&dev_priv->last_fence_retired);
 		DRM_WAKEUP(&dev_priv->fence_queue);
 		DRM_WAKEUP(&dev_priv->fence_queue);
@@ -120,7 +119,7 @@ void mga_disable_vblank(struct drm_device *dev, int crtc)
 	/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
 	/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
 }
 }
 
 
-int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
+int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence)
 {
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	unsigned int cur_fence;
 	unsigned int cur_fence;
@@ -139,7 +138,7 @@ int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
 	return ret;
 	return ret;
 }
 }
 
 
-void mga_driver_irq_preinstall(struct drm_device * dev)
+void mga_driver_irq_preinstall(struct drm_device *dev)
 {
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 
 
@@ -162,7 +161,7 @@ int mga_driver_irq_postinstall(struct drm_device *dev)
 	return 0;
 	return 0;
 }
 }
 
 
-void mga_driver_irq_uninstall(struct drm_device * dev)
+void mga_driver_irq_uninstall(struct drm_device *dev)
 {
 {
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
 	if (!dev_priv)
 	if (!dev_priv)

+ 23 - 24
drivers/gpu/drm/mga/mga_state.c

@@ -41,8 +41,8 @@
  * DMA hardware state programming functions
  * DMA hardware state programming functions
  */
  */
 
 
-static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
-			       struct drm_clip_rect * box)
+static void mga_emit_clip_rect(drm_mga_private_t *dev_priv,
+			       struct drm_clip_rect *box)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -66,7 +66,7 @@ static void mga_emit_clip_rect(drm_mga_private_t * dev_priv,
 	ADVANCE_DMA();
 	ADVANCE_DMA();
 }
 }
 
 
-static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv)
+static __inline__ void mga_g200_emit_context(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -89,7 +89,7 @@ static __inline__ void mga_g200_emit_context(drm_mga_private_t * dev_priv)
 	ADVANCE_DMA();
 	ADVANCE_DMA();
 }
 }
 
 
-static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv)
+static __inline__ void mga_g400_emit_context(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -116,7 +116,7 @@ static __inline__ void mga_g400_emit_context(drm_mga_private_t * dev_priv)
 	ADVANCE_DMA();
 	ADVANCE_DMA();
 }
 }
 
 
-static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv)
+static __inline__ void mga_g200_emit_tex0(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
@@ -144,7 +144,7 @@ static __inline__ void mga_g200_emit_tex0(drm_mga_private_t * dev_priv)
 	ADVANCE_DMA();
 	ADVANCE_DMA();
 }
 }
 
 
-static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv)
+static __inline__ void mga_g400_emit_tex0(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[0];
@@ -184,7 +184,7 @@ static __inline__ void mga_g400_emit_tex0(drm_mga_private_t * dev_priv)
 	ADVANCE_DMA();
 	ADVANCE_DMA();
 }
 }
 
 
-static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv)
+static __inline__ void mga_g400_emit_tex1(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[1];
@@ -223,7 +223,7 @@ static __inline__ void mga_g400_emit_tex1(drm_mga_private_t * dev_priv)
 	ADVANCE_DMA();
 	ADVANCE_DMA();
 }
 }
 
 
-static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv)
+static __inline__ void mga_g200_emit_pipe(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int pipe = sarea_priv->warp_pipe;
 	unsigned int pipe = sarea_priv->warp_pipe;
@@ -250,7 +250,7 @@ static __inline__ void mga_g200_emit_pipe(drm_mga_private_t * dev_priv)
 	ADVANCE_DMA();
 	ADVANCE_DMA();
 }
 }
 
 
-static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv)
+static __inline__ void mga_g400_emit_pipe(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int pipe = sarea_priv->warp_pipe;
 	unsigned int pipe = sarea_priv->warp_pipe;
@@ -327,7 +327,7 @@ static __inline__ void mga_g400_emit_pipe(drm_mga_private_t * dev_priv)
 	ADVANCE_DMA();
 	ADVANCE_DMA();
 }
 }
 
 
-static void mga_g200_emit_state(drm_mga_private_t * dev_priv)
+static void mga_g200_emit_state(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int dirty = sarea_priv->dirty;
 	unsigned int dirty = sarea_priv->dirty;
@@ -348,7 +348,7 @@ static void mga_g200_emit_state(drm_mga_private_t * dev_priv)
 	}
 	}
 }
 }
 
 
-static void mga_g400_emit_state(drm_mga_private_t * dev_priv)
+static void mga_g400_emit_state(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int dirty = sarea_priv->dirty;
 	unsigned int dirty = sarea_priv->dirty;
@@ -381,7 +381,7 @@ static void mga_g400_emit_state(drm_mga_private_t * dev_priv)
 
 
 /* Disallow all write destinations except the front and backbuffer.
 /* Disallow all write destinations except the front and backbuffer.
  */
  */
-static int mga_verify_context(drm_mga_private_t * dev_priv)
+static int mga_verify_context(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
 	drm_mga_context_regs_t *ctx = &sarea_priv->context_state;
@@ -400,7 +400,7 @@ static int mga_verify_context(drm_mga_private_t * dev_priv)
 
 
 /* Disallow texture reads from PCI space.
 /* Disallow texture reads from PCI space.
  */
  */
-static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
+static int mga_verify_tex(drm_mga_private_t *dev_priv, int unit)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
 	drm_mga_texture_regs_t *tex = &sarea_priv->tex_state[unit];
@@ -417,7 +417,7 @@ static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit)
 	return 0;
 	return 0;
 }
 }
 
 
-static int mga_verify_state(drm_mga_private_t * dev_priv)
+static int mga_verify_state(drm_mga_private_t *dev_priv)
 {
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	unsigned int dirty = sarea_priv->dirty;
 	unsigned int dirty = sarea_priv->dirty;
@@ -446,7 +446,7 @@ static int mga_verify_state(drm_mga_private_t * dev_priv)
 	return (ret == 0);
 	return (ret == 0);
 }
 }
 
 
-static int mga_verify_iload(drm_mga_private_t * dev_priv,
+static int mga_verify_iload(drm_mga_private_t *dev_priv,
 			    unsigned int dstorg, unsigned int length)
 			    unsigned int dstorg, unsigned int length)
 {
 {
 	if (dstorg < dev_priv->texture_offset ||
 	if (dstorg < dev_priv->texture_offset ||
@@ -465,7 +465,7 @@ static int mga_verify_iload(drm_mga_private_t * dev_priv,
 	return 0;
 	return 0;
 }
 }
 
 
-static int mga_verify_blit(drm_mga_private_t * dev_priv,
+static int mga_verify_blit(drm_mga_private_t *dev_priv,
 			   unsigned int srcorg, unsigned int dstorg)
 			   unsigned int srcorg, unsigned int dstorg)
 {
 {
 	if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
 	if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) ||
@@ -480,7 +480,7 @@ static int mga_verify_blit(drm_mga_private_t * dev_priv,
  *
  *
  */
  */
 
 
-static void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * clear)
+static void mga_dma_dispatch_clear(struct drm_device *dev, drm_mga_clear_t *clear)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -568,7 +568,7 @@ static void mga_dma_dispatch_clear(struct drm_device * dev, drm_mga_clear_t * cl
 	FLUSH_DMA();
 	FLUSH_DMA();
 }
 }
 
 
-static void mga_dma_dispatch_swap(struct drm_device * dev)
+static void mga_dma_dispatch_swap(struct drm_device *dev)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -622,7 +622,7 @@ static void mga_dma_dispatch_swap(struct drm_device * dev)
 	DRM_DEBUG("... done.\n");
 	DRM_DEBUG("... done.\n");
 }
 }
 
 
-static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * buf)
+static void mga_dma_dispatch_vertex(struct drm_device *dev, struct drm_buf *buf)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
 	drm_mga_buf_priv_t *buf_priv = buf->dev_private;
@@ -669,7 +669,7 @@ static void mga_dma_dispatch_vertex(struct drm_device * dev, struct drm_buf * bu
 	FLUSH_DMA();
 	FLUSH_DMA();
 }
 }
 
 
-static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * buf,
+static void mga_dma_dispatch_indices(struct drm_device *dev, struct drm_buf *buf,
 				     unsigned int start, unsigned int end)
 				     unsigned int start, unsigned int end)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -718,7 +718,7 @@ static void mga_dma_dispatch_indices(struct drm_device * dev, struct drm_buf * b
 /* This copies a 64 byte aligned agp region to the frambuffer with a
 /* This copies a 64 byte aligned agp region to the frambuffer with a
  * standard blit, the ioctl needs to do checking.
  * standard blit, the ioctl needs to do checking.
  */
  */
-static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf,
+static void mga_dma_dispatch_iload(struct drm_device *dev, struct drm_buf *buf,
 				   unsigned int dstorg, unsigned int length)
 				   unsigned int dstorg, unsigned int length)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -766,7 +766,7 @@ static void mga_dma_dispatch_iload(struct drm_device * dev, struct drm_buf * buf
 	FLUSH_DMA();
 	FLUSH_DMA();
 }
 }
 
 
-static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit)
+static void mga_dma_dispatch_blit(struct drm_device *dev, drm_mga_blit_t *blit)
 {
 {
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_private_t *dev_priv = dev->dev_private;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
@@ -801,9 +801,8 @@ static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit
 		int w = pbox[i].x2 - pbox[i].x1 - 1;
 		int w = pbox[i].x2 - pbox[i].x1 - 1;
 		int start;
 		int start;
 
 
-		if (blit->ydir == -1) {
+		if (blit->ydir == -1)
 			srcy = blit->height - srcy - 1;
 			srcy = blit->height - srcy - 1;
-		}
 
 
 		start = srcy * blit->src_pitch + srcx;
 		start = srcy * blit->src_pitch + srcx;
 
 

+ 2 - 2
drivers/gpu/drm/mga/mga_warp.c

@@ -46,7 +46,7 @@ MODULE_FIRMWARE(FIRMWARE_G400);
 
 
 #define WARP_UCODE_SIZE(size)		ALIGN(size, MGA_WARP_CODE_ALIGN)
 #define WARP_UCODE_SIZE(size)		ALIGN(size, MGA_WARP_CODE_ALIGN)
 
 
-int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
+int mga_warp_install_microcode(drm_mga_private_t *dev_priv)
 {
 {
 	unsigned char *vcbase = dev_priv->warp->handle;
 	unsigned char *vcbase = dev_priv->warp->handle;
 	unsigned long pcbase = dev_priv->warp->offset;
 	unsigned long pcbase = dev_priv->warp->offset;
@@ -133,7 +133,7 @@ out:
 
 
 #define WMISC_EXPECTED		(MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
 #define WMISC_EXPECTED		(MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
 
 
-int mga_warp_init(drm_mga_private_t * dev_priv)
+int mga_warp_init(drm_mga_private_t *dev_priv)
 {
 {
 	u32 wmisc;
 	u32 wmisc;
 
 

+ 10 - 1
drivers/gpu/drm/nouveau/Kconfig

@@ -1,6 +1,6 @@
 config DRM_NOUVEAU
 config DRM_NOUVEAU
 	tristate "Nouveau (nVidia) cards"
 	tristate "Nouveau (nVidia) cards"
-	depends on DRM
+	depends on DRM && PCI
         select FW_LOADER
         select FW_LOADER
 	select DRM_KMS_HELPER
 	select DRM_KMS_HELPER
 	select DRM_TTM
 	select DRM_TTM
@@ -41,4 +41,13 @@ config DRM_I2C_CH7006
 
 
 	  This driver is currently only useful if you're also using
 	  This driver is currently only useful if you're also using
 	  the nouveau driver.
 	  the nouveau driver.
+
+config DRM_I2C_SIL164
+	tristate "Silicon Image sil164 TMDS transmitter"
+	default m if DRM_NOUVEAU
+	help
+	  Support for sil164 and similar single-link (or dual-link
+	  when used in pairs) TMDS transmitters, used in some nVidia
+	  video cards.
+
 endmenu
 endmenu

+ 3 - 3
drivers/gpu/drm/nouveau/Makefile

@@ -9,10 +9,10 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
              nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
              nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \
              nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
              nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \
              nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
              nouveau_display.o nouveau_connector.o nouveau_fbcon.o \
-             nouveau_dp.o nouveau_grctx.o \
+             nouveau_dp.o \
              nv04_timer.o \
              nv04_timer.o \
              nv04_mc.o nv40_mc.o nv50_mc.o \
              nv04_mc.o nv40_mc.o nv50_mc.o \
-             nv04_fb.o nv10_fb.o nv40_fb.o nv50_fb.o \
+             nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o \
              nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
              nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
              nv04_graph.o nv10_graph.o nv20_graph.o \
              nv04_graph.o nv10_graph.o nv20_graph.o \
              nv40_graph.o nv50_graph.o \
              nv40_graph.o nv50_graph.o \
@@ -22,7 +22,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
              nv50_cursor.o nv50_display.o nv50_fbcon.o \
              nv50_cursor.o nv50_display.o nv50_fbcon.o \
              nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
              nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
              nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
              nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \
-             nv17_gpio.o nv50_gpio.o \
+             nv10_gpio.o nv50_gpio.o \
 	     nv50_calc.o
 	     nv50_calc.o
 
 
 nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
 nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o

+ 37 - 1
drivers/gpu/drm/nouveau/nouveau_acpi.c

@@ -3,6 +3,7 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_bus.h>
+#include <acpi/video.h>
 
 
 #include "drmP.h"
 #include "drmP.h"
 #include "drm.h"
 #include "drm.h"
@@ -11,6 +12,7 @@
 #include "nouveau_drv.h"
 #include "nouveau_drv.h"
 #include "nouveau_drm.h"
 #include "nouveau_drm.h"
 #include "nv50_display.h"
 #include "nv50_display.h"
+#include "nouveau_connector.h"
 
 
 #include <linux/vga_switcheroo.h>
 #include <linux/vga_switcheroo.h>
 
 
@@ -42,7 +44,7 @@ static const char nouveau_dsm_muid[] = {
 	0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
 	0xB3, 0x4D, 0x7E, 0x5F, 0xEA, 0x12, 0x9F, 0xD4,
 };
 };
 
 
-static int nouveau_dsm(acpi_handle handle, int func, int arg, int *result)
+static int nouveau_dsm(acpi_handle handle, int func, int arg, uint32_t *result)
 {
 {
 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 	struct acpi_object_list input;
 	struct acpi_object_list input;
@@ -259,3 +261,37 @@ int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len)
 {
 {
 	return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
 	return nouveau_rom_call(nouveau_dsm_priv.rom_handle, bios, offset, len);
 }
 }
+
+int
+nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector)
+{
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct acpi_device *acpidev;
+	acpi_handle handle;
+	int type, ret;
+	void *edid;
+
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_LVDS:
+	case DRM_MODE_CONNECTOR_eDP:
+		type = ACPI_VIDEO_DISPLAY_LCD;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev);
+	if (!handle)
+		return -ENODEV;
+
+	ret = acpi_bus_get_device(handle, &acpidev);
+	if (ret)
+		return -ENODEV;
+
+	ret = acpi_video_get_edid(acpidev, type, -1, &edid);
+	if (ret < 0)
+		return ret;
+
+	nv_connector->edid = edid;
+	return 0;
+}

File diff suppressed because it is too large
+ 490 - 123
drivers/gpu/drm/nouveau/nouveau_bios.c


+ 2 - 2
drivers/gpu/drm/nouveau/nouveau_bios.h

@@ -81,6 +81,7 @@ struct dcb_connector_table_entry {
 	enum dcb_connector_type type;
 	enum dcb_connector_type type;
 	uint8_t index2;
 	uint8_t index2;
 	uint8_t gpio_tag;
 	uint8_t gpio_tag;
+	void *drm;
 };
 };
 
 
 struct dcb_connector_table {
 struct dcb_connector_table {
@@ -117,6 +118,7 @@ struct dcb_entry {
 		struct {
 		struct {
 			struct sor_conf sor;
 			struct sor_conf sor;
 			bool use_straps_for_mode;
 			bool use_straps_for_mode;
+			bool use_acpi_for_edid;
 			bool use_power_scripts;
 			bool use_power_scripts;
 		} lvdsconf;
 		} lvdsconf;
 		struct {
 		struct {
@@ -249,8 +251,6 @@ struct nvbios {
 
 
 	struct {
 	struct {
 		int crtchead;
 		int crtchead;
-		/* these need remembering across suspend */
-		uint32_t saved_nv_pfb_cfg0;
 	} state;
 	} state;
 
 
 	struct {
 	struct {

+ 5 - 6
drivers/gpu/drm/nouveau/nouveau_bo.c

@@ -461,9 +461,9 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
 		return ret;
 		return ret;
 
 
 	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
 	ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
-					evict, no_wait_reserve, no_wait_gpu, new_mem);
-	if (nvbo->channel && nvbo->channel != chan)
-		ret = nouveau_fence_wait(fence, NULL, false, false);
+					evict || (nvbo->channel &&
+						  nvbo->channel != chan),
+					no_wait_reserve, no_wait_gpu, new_mem);
 	nouveau_fence_unref((void *)&fence);
 	nouveau_fence_unref((void *)&fence);
 	return ret;
 	return ret;
 }
 }
@@ -711,8 +711,7 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr,
 		return ret;
 		return ret;
 
 
 	/* Software copy if the card isn't up and running yet. */
 	/* Software copy if the card isn't up and running yet. */
-	if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE ||
-	    !dev_priv->channel) {
+	if (!dev_priv->channel) {
 		ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem);
 		ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem);
 		goto out;
 		goto out;
 	}
 	}
@@ -783,7 +782,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 		break;
 		break;
 	case TTM_PL_VRAM:
 	case TTM_PL_VRAM:
 		mem->bus.offset = mem->mm_node->start << PAGE_SHIFT;
 		mem->bus.offset = mem->mm_node->start << PAGE_SHIFT;
-		mem->bus.base = drm_get_resource_start(dev, 1);
+		mem->bus.base = pci_resource_start(dev->pdev, 1);
 		mem->bus.is_iomem = true;
 		mem->bus.is_iomem = true;
 		break;
 		break;
 	default:
 	default:

+ 2 - 2
drivers/gpu/drm/nouveau/nouveau_calc.c

@@ -200,7 +200,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
 	struct nv_sim_state sim_data;
 	struct nv_sim_state sim_data;
 	int MClk = nouveau_hw_get_clock(dev, MPLL);
 	int MClk = nouveau_hw_get_clock(dev, MPLL);
 	int NVClk = nouveau_hw_get_clock(dev, NVPLL);
 	int NVClk = nouveau_hw_get_clock(dev, NVPLL);
-	uint32_t cfg1 = nvReadFB(dev, NV_PFB_CFG1);
+	uint32_t cfg1 = nvReadFB(dev, NV04_PFB_CFG1);
 
 
 	sim_data.pclk_khz = VClk;
 	sim_data.pclk_khz = VClk;
 	sim_data.mclk_khz = MClk;
 	sim_data.mclk_khz = MClk;
@@ -218,7 +218,7 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp,
 		sim_data.mem_latency = 3;
 		sim_data.mem_latency = 3;
 		sim_data.mem_page_miss = 10;
 		sim_data.mem_page_miss = 10;
 	} else {
 	} else {
-		sim_data.memory_type = nvReadFB(dev, NV_PFB_CFG0) & 0x1;
+		sim_data.memory_type = nvReadFB(dev, NV04_PFB_CFG0) & 0x1;
 		sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
 		sim_data.memory_width = (nvReadEXTDEV(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64;
 		sim_data.mem_latency = cfg1 & 0xf;
 		sim_data.mem_latency = cfg1 & 0xf;
 		sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);
 		sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1);

+ 2 - 6
drivers/gpu/drm/nouveau/nouveau_channel.c

@@ -62,7 +62,8 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
 		 * VRAM.
 		 * VRAM.
 		 */
 		 */
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
-					     drm_get_resource_start(dev, 1),
+					     pci_resource_start(dev->pdev,
+					     1),
 					     dev_priv->fb_available_size,
 					     dev_priv->fb_available_size,
 					     NV_DMA_ACCESS_RO,
 					     NV_DMA_ACCESS_RO,
 					     NV_DMA_TARGET_PCI, &pushbuf);
 					     NV_DMA_TARGET_PCI, &pushbuf);
@@ -257,9 +258,7 @@ nouveau_channel_free(struct nouveau_channel *chan)
 	nouveau_debugfs_channel_fini(chan);
 	nouveau_debugfs_channel_fini(chan);
 
 
 	/* Give outstanding push buffers a chance to complete */
 	/* Give outstanding push buffers a chance to complete */
-	spin_lock_irqsave(&chan->fence.lock, flags);
 	nouveau_fence_update(chan);
 	nouveau_fence_update(chan);
-	spin_unlock_irqrestore(&chan->fence.lock, flags);
 	if (chan->fence.sequence != chan->fence.sequence_ack) {
 	if (chan->fence.sequence != chan->fence.sequence_ack) {
 		struct nouveau_fence *fence = NULL;
 		struct nouveau_fence *fence = NULL;
 
 
@@ -368,8 +367,6 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
 	struct nouveau_channel *chan;
 	struct nouveau_channel *chan;
 	int ret;
 	int ret;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
 	if (dev_priv->engine.graph.accel_blocked)
 	if (dev_priv->engine.graph.accel_blocked)
 		return -ENODEV;
 		return -ENODEV;
 
 
@@ -418,7 +415,6 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
 	struct drm_nouveau_channel_free *cfree = data;
 	struct drm_nouveau_channel_free *cfree = data;
 	struct nouveau_channel *chan;
 	struct nouveau_channel *chan;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan);
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(cfree->channel, file_priv, chan);
 
 
 	nouveau_channel_free(chan);
 	nouveau_channel_free(chan);

+ 181 - 223
drivers/gpu/drm/nouveau/nouveau_connector.c

@@ -102,63 +102,15 @@ nouveau_connector_destroy(struct drm_connector *drm_connector)
 	kfree(drm_connector);
 	kfree(drm_connector);
 }
 }
 
 
-static void
-nouveau_connector_ddc_prepare(struct drm_connector *connector, int *flags)
-{
-	struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
-
-	if (dev_priv->card_type >= NV_50)
-		return;
-
-	*flags = 0;
-	if (NVLockVgaCrtcs(dev_priv->dev, false))
-		*flags |= 1;
-	if (nv_heads_tied(dev_priv->dev))
-		*flags |= 2;
-
-	if (*flags & 2)
-		NVSetOwner(dev_priv->dev, 0); /* necessary? */
-}
-
-static void
-nouveau_connector_ddc_finish(struct drm_connector *connector, int flags)
-{
-	struct drm_nouveau_private *dev_priv = connector->dev->dev_private;
-
-	if (dev_priv->card_type >= NV_50)
-		return;
-
-	if (flags & 2)
-		NVSetOwner(dev_priv->dev, 4);
-	if (flags & 1)
-		NVLockVgaCrtcs(dev_priv->dev, true);
-}
-
 static struct nouveau_i2c_chan *
 static struct nouveau_i2c_chan *
 nouveau_connector_ddc_detect(struct drm_connector *connector,
 nouveau_connector_ddc_detect(struct drm_connector *connector,
 			     struct nouveau_encoder **pnv_encoder)
 			     struct nouveau_encoder **pnv_encoder)
 {
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_device *dev = connector->dev;
-	uint8_t out_buf[] = { 0x0, 0x0}, buf[2];
-	int ret, flags, i;
-
-	struct i2c_msg msgs[] = {
-		{
-			.addr = 0x50,
-			.flags = 0,
-			.len = 1,
-			.buf = out_buf,
-		},
-		{
-			.addr = 0x50,
-			.flags = I2C_M_RD,
-			.len = 1,
-			.buf = buf,
-		}
-	};
+	int i;
 
 
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-		struct nouveau_i2c_chan *i2c = NULL;
+		struct nouveau_i2c_chan *i2c;
 		struct nouveau_encoder *nv_encoder;
 		struct nouveau_encoder *nv_encoder;
 		struct drm_mode_object *obj;
 		struct drm_mode_object *obj;
 		int id;
 		int id;
@@ -171,17 +123,9 @@ nouveau_connector_ddc_detect(struct drm_connector *connector,
 		if (!obj)
 		if (!obj)
 			continue;
 			continue;
 		nv_encoder = nouveau_encoder(obj_to_encoder(obj));
 		nv_encoder = nouveau_encoder(obj_to_encoder(obj));
+		i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
 
 
-		if (nv_encoder->dcb->i2c_index < 0xf)
-			i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
-		if (!i2c)
-			continue;
-
-		nouveau_connector_ddc_prepare(connector, &flags);
-		ret = i2c_transfer(&i2c->adapter, msgs, 2);
-		nouveau_connector_ddc_finish(connector, flags);
-
-		if (ret == 2) {
+		if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) {
 			*pnv_encoder = nv_encoder;
 			*pnv_encoder = nv_encoder;
 			return i2c;
 			return i2c;
 		}
 		}
@@ -234,21 +178,7 @@ nouveau_connector_detect(struct drm_connector *connector)
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_encoder *nv_encoder = NULL;
 	struct nouveau_encoder *nv_encoder = NULL;
 	struct nouveau_i2c_chan *i2c;
 	struct nouveau_i2c_chan *i2c;
-	int type, flags;
-
-	if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS)
-		nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
-	if (nv_encoder && nv_connector->native_mode) {
-		unsigned status = connector_status_connected;
-
-#if defined(CONFIG_ACPI_BUTTON) || \
-	(defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE))
-		if (!nouveau_ignorelid && !acpi_lid_open())
-			status = connector_status_unknown;
-#endif
-		nouveau_connector_set_encoder(connector, nv_encoder);
-		return status;
-	}
+	int type;
 
 
 	/* Cleanup the previous EDID block. */
 	/* Cleanup the previous EDID block. */
 	if (nv_connector->edid) {
 	if (nv_connector->edid) {
@@ -259,9 +189,7 @@ nouveau_connector_detect(struct drm_connector *connector)
 
 
 	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
 	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
 	if (i2c) {
 	if (i2c) {
-		nouveau_connector_ddc_prepare(connector, &flags);
 		nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
 		nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
-		nouveau_connector_ddc_finish(connector, flags);
 		drm_mode_connector_update_edid_property(connector,
 		drm_mode_connector_update_edid_property(connector,
 							nv_connector->edid);
 							nv_connector->edid);
 		if (!nv_connector->edid) {
 		if (!nv_connector->edid) {
@@ -321,6 +249,85 @@ detect_analog:
 	return connector_status_disconnected;
 	return connector_status_disconnected;
 }
 }
 
 
+static enum drm_connector_status
+nouveau_connector_detect_lvds(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
+	struct nouveau_encoder *nv_encoder = NULL;
+	enum drm_connector_status status = connector_status_disconnected;
+
+	/* Cleanup the previous EDID block. */
+	if (nv_connector->edid) {
+		drm_mode_connector_update_edid_property(connector, NULL);
+		kfree(nv_connector->edid);
+		nv_connector->edid = NULL;
+	}
+
+	nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
+	if (!nv_encoder)
+		return connector_status_disconnected;
+
+	/* Try retrieving EDID via DDC */
+	if (!dev_priv->vbios.fp_no_ddc) {
+		status = nouveau_connector_detect(connector);
+		if (status == connector_status_connected)
+			goto out;
+	}
+
+	/* On some laptops (Sony, i'm looking at you) there appears to
+	 * be no direct way of accessing the panel's EDID.  The only
+	 * option available to us appears to be to ask ACPI for help..
+	 *
+	 * It's important this check's before trying straps, one of the
+	 * said manufacturer's laptops are configured in such a way
+	 * the nouveau decides an entry in the VBIOS FP mode table is
+	 * valid - it's not (rh#613284)
+	 */
+	if (nv_encoder->dcb->lvdsconf.use_acpi_for_edid) {
+		if (!nouveau_acpi_edid(dev, connector)) {
+			status = connector_status_connected;
+			goto out;
+		}
+	}
+
+	/* If no EDID found above, and the VBIOS indicates a hardcoded
+	 * modeline is avalilable for the panel, set it as the panel's
+	 * native mode and exit.
+	 */
+	if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc ||
+	    nv_encoder->dcb->lvdsconf.use_straps_for_mode)) {
+		status = connector_status_connected;
+		goto out;
+	}
+
+	/* Still nothing, some VBIOS images have a hardcoded EDID block
+	 * stored for the panel stored in them.
+	 */
+	if (!dev_priv->vbios.fp_no_ddc) {
+		struct edid *edid =
+			(struct edid *)nouveau_bios_embedded_edid(dev);
+		if (edid) {
+			nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
+			*(nv_connector->edid) = *edid;
+			status = connector_status_connected;
+		}
+	}
+
+out:
+#if defined(CONFIG_ACPI_BUTTON) || \
+	(defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE))
+	if (status == connector_status_connected &&
+	    !nouveau_ignorelid && !acpi_lid_open())
+		status = connector_status_unknown;
+#endif
+
+	drm_mode_connector_update_edid_property(connector, nv_connector->edid);
+	nouveau_connector_set_encoder(connector, nv_encoder);
+	return status;
+}
+
 static void
 static void
 nouveau_connector_force(struct drm_connector *connector)
 nouveau_connector_force(struct drm_connector *connector)
 {
 {
@@ -441,7 +448,8 @@ nouveau_connector_native_mode(struct drm_connector *connector)
 	int high_w = 0, high_h = 0, high_v = 0;
 	int high_w = 0, high_h = 0, high_v = 0;
 
 
 	list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
 	list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
-		if (helper->mode_valid(connector, mode) != MODE_OK)
+		if (helper->mode_valid(connector, mode) != MODE_OK ||
+		    (mode->flags & DRM_MODE_FLAG_INTERLACE))
 			continue;
 			continue;
 
 
 		/* Use preferred mode if there is one.. */
 		/* Use preferred mode if there is one.. */
@@ -534,21 +542,27 @@ static int
 nouveau_connector_get_modes(struct drm_connector *connector)
 nouveau_connector_get_modes(struct drm_connector *connector)
 {
 {
 	struct drm_device *dev = connector->dev;
 	struct drm_device *dev = connector->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
 	int ret = 0;
 	int ret = 0;
 
 
-	/* If we're not LVDS, destroy the previous native mode, the attached
-	 * monitor could have changed.
+	/* destroy the native mode, the attached monitor could have changed.
 	 */
 	 */
-	if (nv_connector->dcb->type != DCB_CONNECTOR_LVDS &&
-	    nv_connector->native_mode) {
+	if (nv_connector->native_mode) {
 		drm_mode_destroy(dev, nv_connector->native_mode);
 		drm_mode_destroy(dev, nv_connector->native_mode);
 		nv_connector->native_mode = NULL;
 		nv_connector->native_mode = NULL;
 	}
 	}
 
 
 	if (nv_connector->edid)
 	if (nv_connector->edid)
 		ret = drm_add_edid_modes(connector, nv_connector->edid);
 		ret = drm_add_edid_modes(connector, nv_connector->edid);
+	else
+	if (nv_encoder->dcb->type == OUTPUT_LVDS &&
+	    (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
+	     dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) {
+		nv_connector->native_mode = drm_mode_create(dev);
+		nouveau_bios_fp_mode(dev, nv_connector->native_mode);
+	}
 
 
 	/* Find the native mode if this is a digital panel, if we didn't
 	/* Find the native mode if this is a digital panel, if we didn't
 	 * find any modes through DDC previously add the native mode to
 	 * find any modes through DDC previously add the native mode to
@@ -569,7 +583,8 @@ nouveau_connector_get_modes(struct drm_connector *connector)
 		ret = get_slave_funcs(nv_encoder)->
 		ret = get_slave_funcs(nv_encoder)->
 			get_modes(to_drm_encoder(nv_encoder), connector);
 			get_modes(to_drm_encoder(nv_encoder), connector);
 
 
-	if (nv_encoder->dcb->type == OUTPUT_LVDS)
+	if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS ||
+	    nv_connector->dcb->type == DCB_CONNECTOR_eDP)
 		ret += nouveau_connector_scaler_modes_add(connector);
 		ret += nouveau_connector_scaler_modes_add(connector);
 
 
 	return ret;
 	return ret;
@@ -643,6 +658,44 @@ nouveau_connector_best_encoder(struct drm_connector *connector)
 	return NULL;
 	return NULL;
 }
 }
 
 
+void
+nouveau_connector_set_polling(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
+	bool spare_crtc = false;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
+		spare_crtc |= !crtc->enabled;
+
+	connector->polled = 0;
+
+	switch (connector->connector_type) {
+	case DRM_MODE_CONNECTOR_VGA:
+	case DRM_MODE_CONNECTOR_TV:
+		if (dev_priv->card_type >= NV_50 ||
+		    (nv_gf4_disp_arch(dev) && spare_crtc))
+			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+		break;
+
+	case DRM_MODE_CONNECTOR_DVII:
+	case DRM_MODE_CONNECTOR_DVID:
+	case DRM_MODE_CONNECTOR_HDMIA:
+	case DRM_MODE_CONNECTOR_DisplayPort:
+	case DRM_MODE_CONNECTOR_eDP:
+		if (dev_priv->card_type >= NV_50)
+			connector->polled = DRM_CONNECTOR_POLL_HPD;
+		else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID ||
+			 spare_crtc)
+			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
+		break;
+
+	default:
+		break;
+	}
+}
+
 static const struct drm_connector_helper_funcs
 static const struct drm_connector_helper_funcs
 nouveau_connector_helper_funcs = {
 nouveau_connector_helper_funcs = {
 	.get_modes = nouveau_connector_get_modes,
 	.get_modes = nouveau_connector_get_modes,
@@ -662,148 +715,74 @@ nouveau_connector_funcs = {
 	.force = nouveau_connector_force
 	.force = nouveau_connector_force
 };
 };
 
 
-static int
-nouveau_connector_create_lvds(struct drm_device *dev,
-			      struct drm_connector *connector)
-{
-	struct nouveau_connector *nv_connector = nouveau_connector(connector);
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_i2c_chan *i2c = NULL;
-	struct nouveau_encoder *nv_encoder;
-	struct drm_display_mode native, *mode, *temp;
-	bool dummy, if_is_24bit = false;
-	int ret, flags;
-
-	nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
-	if (!nv_encoder)
-		return -ENODEV;
-
-	ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &if_is_24bit);
-	if (ret) {
-		NV_ERROR(dev, "Error parsing LVDS table, disabling LVDS\n");
-		return ret;
-	}
-	nv_connector->use_dithering = !if_is_24bit;
-
-	/* Firstly try getting EDID over DDC, if allowed and I2C channel
-	 * is available.
-	 */
-	if (!dev_priv->vbios.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
-		i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
-
-	if (i2c) {
-		nouveau_connector_ddc_prepare(connector, &flags);
-		nv_connector->edid = drm_get_edid(connector, &i2c->adapter);
-		nouveau_connector_ddc_finish(connector, flags);
-	}
-
-	/* If no EDID found above, and the VBIOS indicates a hardcoded
-	 * modeline is avalilable for the panel, set it as the panel's
-	 * native mode and exit.
-	 */
-	if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) &&
-	     (nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
-	      dev_priv->vbios.fp_no_ddc)) {
-		nv_connector->native_mode = drm_mode_duplicate(dev, &native);
-		goto out;
-	}
-
-	/* Still nothing, some VBIOS images have a hardcoded EDID block
-	 * stored for the panel stored in them.
-	 */
-	if (!nv_connector->edid && !nv_connector->native_mode &&
-	    !dev_priv->vbios.fp_no_ddc) {
-		struct edid *edid =
-			(struct edid *)nouveau_bios_embedded_edid(dev);
-		if (edid) {
-			nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
-			*(nv_connector->edid) = *edid;
-		}
-	}
-
-	if (!nv_connector->edid)
-		goto out;
-
-	/* We didn't find/use a panel mode from the VBIOS, so parse the EDID
-	 * block and look for the preferred mode there.
-	 */
-	ret = drm_add_edid_modes(connector, nv_connector->edid);
-	if (ret == 0)
-		goto out;
-	nv_connector->detected_encoder = nv_encoder;
-	nv_connector->native_mode = nouveau_connector_native_mode(connector);
-	list_for_each_entry_safe(mode, temp, &connector->probed_modes, head)
-		drm_mode_remove(connector, mode);
-
-out:
-	if (!nv_connector->native_mode) {
-		NV_ERROR(dev, "LVDS present in DCB table, but couldn't "
-			      "determine its native mode.  Disabling.\n");
-		return -ENODEV;
-	}
-
-	drm_mode_connector_update_edid_property(connector, nv_connector->edid);
-	return 0;
-}
+static const struct drm_connector_funcs
+nouveau_connector_funcs_lvds = {
+	.dpms = drm_helper_connector_dpms,
+	.save = NULL,
+	.restore = NULL,
+	.detect = nouveau_connector_detect_lvds,
+	.destroy = nouveau_connector_destroy,
+	.fill_modes = drm_helper_probe_single_connector_modes,
+	.set_property = nouveau_connector_set_property,
+	.force = nouveau_connector_force
+};
 
 
-int
-nouveau_connector_create(struct drm_device *dev,
-			 struct dcb_connector_table_entry *dcb)
+struct drm_connector *
+nouveau_connector_create(struct drm_device *dev, int index)
 {
 {
+	const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_connector *nv_connector = NULL;
 	struct nouveau_connector *nv_connector = NULL;
+	struct dcb_connector_table_entry *dcb = NULL;
 	struct drm_connector *connector;
 	struct drm_connector *connector;
-	struct drm_encoder *encoder;
-	int ret, type;
+	int type, ret = 0;
 
 
 	NV_DEBUG_KMS(dev, "\n");
 	NV_DEBUG_KMS(dev, "\n");
 
 
+	if (index >= dev_priv->vbios.dcb.connector.entries)
+		return ERR_PTR(-EINVAL);
+
+	dcb = &dev_priv->vbios.dcb.connector.entry[index];
+	if (dcb->drm)
+		return dcb->drm;
+
 	switch (dcb->type) {
 	switch (dcb->type) {
-	case DCB_CONNECTOR_NONE:
-		return 0;
 	case DCB_CONNECTOR_VGA:
 	case DCB_CONNECTOR_VGA:
-		NV_INFO(dev, "Detected a VGA connector\n");
 		type = DRM_MODE_CONNECTOR_VGA;
 		type = DRM_MODE_CONNECTOR_VGA;
 		break;
 		break;
 	case DCB_CONNECTOR_TV_0:
 	case DCB_CONNECTOR_TV_0:
 	case DCB_CONNECTOR_TV_1:
 	case DCB_CONNECTOR_TV_1:
 	case DCB_CONNECTOR_TV_3:
 	case DCB_CONNECTOR_TV_3:
-		NV_INFO(dev, "Detected a TV connector\n");
 		type = DRM_MODE_CONNECTOR_TV;
 		type = DRM_MODE_CONNECTOR_TV;
 		break;
 		break;
 	case DCB_CONNECTOR_DVI_I:
 	case DCB_CONNECTOR_DVI_I:
-		NV_INFO(dev, "Detected a DVI-I connector\n");
 		type = DRM_MODE_CONNECTOR_DVII;
 		type = DRM_MODE_CONNECTOR_DVII;
 		break;
 		break;
 	case DCB_CONNECTOR_DVI_D:
 	case DCB_CONNECTOR_DVI_D:
-		NV_INFO(dev, "Detected a DVI-D connector\n");
 		type = DRM_MODE_CONNECTOR_DVID;
 		type = DRM_MODE_CONNECTOR_DVID;
 		break;
 		break;
 	case DCB_CONNECTOR_HDMI_0:
 	case DCB_CONNECTOR_HDMI_0:
 	case DCB_CONNECTOR_HDMI_1:
 	case DCB_CONNECTOR_HDMI_1:
-		NV_INFO(dev, "Detected a HDMI connector\n");
 		type = DRM_MODE_CONNECTOR_HDMIA;
 		type = DRM_MODE_CONNECTOR_HDMIA;
 		break;
 		break;
 	case DCB_CONNECTOR_LVDS:
 	case DCB_CONNECTOR_LVDS:
-		NV_INFO(dev, "Detected a LVDS connector\n");
 		type = DRM_MODE_CONNECTOR_LVDS;
 		type = DRM_MODE_CONNECTOR_LVDS;
+		funcs = &nouveau_connector_funcs_lvds;
 		break;
 		break;
 	case DCB_CONNECTOR_DP:
 	case DCB_CONNECTOR_DP:
-		NV_INFO(dev, "Detected a DisplayPort connector\n");
 		type = DRM_MODE_CONNECTOR_DisplayPort;
 		type = DRM_MODE_CONNECTOR_DisplayPort;
 		break;
 		break;
 	case DCB_CONNECTOR_eDP:
 	case DCB_CONNECTOR_eDP:
-		NV_INFO(dev, "Detected an eDP connector\n");
 		type = DRM_MODE_CONNECTOR_eDP;
 		type = DRM_MODE_CONNECTOR_eDP;
 		break;
 		break;
 	default:
 	default:
 		NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
 		NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
-		return -EINVAL;
+		return ERR_PTR(-EINVAL);
 	}
 	}
 
 
 	nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
 	nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
 	if (!nv_connector)
 	if (!nv_connector)
-		return -ENOMEM;
+		return ERR_PTR(-ENOMEM);
 	nv_connector->dcb = dcb;
 	nv_connector->dcb = dcb;
 	connector = &nv_connector->base;
 	connector = &nv_connector->base;
 
 
@@ -811,27 +790,21 @@ nouveau_connector_create(struct drm_device *dev,
 	connector->interlace_allowed = false;
 	connector->interlace_allowed = false;
 	connector->doublescan_allowed = false;
 	connector->doublescan_allowed = false;
 
 
-	drm_connector_init(dev, connector, &nouveau_connector_funcs, type);
+	drm_connector_init(dev, connector, funcs, type);
 	drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
 	drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
 
 
-	/* attach encoders */
-	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
-		struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-
-		if (nv_encoder->dcb->connector != dcb->index)
-			continue;
-
-		if (get_slave_funcs(nv_encoder))
-			get_slave_funcs(nv_encoder)->create_resources(encoder, connector);
+	/* Check if we need dithering enabled */
+	if (dcb->type == DCB_CONNECTOR_LVDS) {
+		bool dummy, is_24bit = false;
 
 
-		drm_mode_connector_attach_encoder(connector, encoder);
-	}
+		ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit);
+		if (ret) {
+			NV_ERROR(dev, "Error parsing LVDS table, disabling "
+				 "LVDS\n");
+			goto fail;
+		}
 
 
-	if (!connector->encoder_ids[0]) {
-		NV_WARN(dev, "  no encoders, ignoring\n");
-		drm_connector_cleanup(connector);
-		kfree(connector);
-		return 0;
+		nv_connector->use_dithering = !is_24bit;
 	}
 	}
 
 
 	/* Init DVI-I specific properties */
 	/* Init DVI-I specific properties */
@@ -841,12 +814,8 @@ nouveau_connector_create(struct drm_device *dev,
 		drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
 		drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
 	}
 	}
 
 
-	if (dcb->type != DCB_CONNECTOR_LVDS)
-		nv_connector->use_dithering = false;
-
 	switch (dcb->type) {
 	switch (dcb->type) {
 	case DCB_CONNECTOR_VGA:
 	case DCB_CONNECTOR_VGA:
-		connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 		if (dev_priv->card_type >= NV_50) {
 		if (dev_priv->card_type >= NV_50) {
 			drm_connector_attach_property(connector,
 			drm_connector_attach_property(connector,
 					dev->mode_config.scaling_mode_property,
 					dev->mode_config.scaling_mode_property,
@@ -858,17 +827,6 @@ nouveau_connector_create(struct drm_device *dev,
 	case DCB_CONNECTOR_TV_3:
 	case DCB_CONNECTOR_TV_3:
 		nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
 		nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
 		break;
 		break;
-	case DCB_CONNECTOR_DP:
-	case DCB_CONNECTOR_eDP:
-	case DCB_CONNECTOR_HDMI_0:
-	case DCB_CONNECTOR_HDMI_1:
-	case DCB_CONNECTOR_DVI_I:
-	case DCB_CONNECTOR_DVI_D:
-		if (dev_priv->card_type >= NV_50)
-			connector->polled = DRM_CONNECTOR_POLL_HPD;
-		else
-			connector->polled = DRM_CONNECTOR_POLL_CONNECT;
-		/* fall-through */
 	default:
 	default:
 		nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
 		nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
 
 
@@ -882,15 +840,15 @@ nouveau_connector_create(struct drm_device *dev,
 		break;
 		break;
 	}
 	}
 
 
+	nouveau_connector_set_polling(connector);
+
 	drm_sysfs_connector_add(connector);
 	drm_sysfs_connector_add(connector);
+	dcb->drm = connector;
+	return dcb->drm;
 
 
-	if (dcb->type == DCB_CONNECTOR_LVDS) {
-		ret = nouveau_connector_create_lvds(dev, connector);
-		if (ret) {
-			connector->funcs->destroy(connector);
-			return ret;
-		}
-	}
+fail:
+	drm_connector_cleanup(connector);
+	kfree(connector);
+	return ERR_PTR(ret);
 
 
-	return 0;
 }
 }

+ 5 - 2
drivers/gpu/drm/nouveau/nouveau_connector.h

@@ -49,7 +49,10 @@ static inline struct nouveau_connector *nouveau_connector(
 	return container_of(con, struct nouveau_connector, base);
 	return container_of(con, struct nouveau_connector, base);
 }
 }
 
 
-int nouveau_connector_create(struct drm_device *,
-			     struct dcb_connector_table_entry *);
+struct drm_connector *
+nouveau_connector_create(struct drm_device *, int index);
+
+void
+nouveau_connector_set_polling(struct drm_connector *);
 
 
 #endif /* __NOUVEAU_CONNECTOR_H__ */
 #endif /* __NOUVEAU_CONNECTOR_H__ */

+ 3 - 5
drivers/gpu/drm/nouveau/nouveau_dma.c

@@ -92,11 +92,9 @@ nouveau_dma_init(struct nouveau_channel *chan)
 		return ret;
 		return ret;
 
 
 	/* Map M2MF notifier object - fbcon. */
 	/* Map M2MF notifier object - fbcon. */
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		ret = nouveau_bo_map(chan->notifier_bo);
-		if (ret)
-			return ret;
-	}
+	ret = nouveau_bo_map(chan->notifier_bo);
+	if (ret)
+		return ret;
 
 
 	/* Insert NOPS for NOUVEAU_DMA_SKIPS */
 	/* Insert NOPS for NOUVEAU_DMA_SKIPS */
 	ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);
 	ret = RING_SPACE(chan, NOUVEAU_DMA_SKIPS);

+ 39 - 2
drivers/gpu/drm/nouveau/nouveau_dp.c

@@ -23,8 +23,10 @@
  */
  */
 
 
 #include "drmP.h"
 #include "drmP.h"
+
 #include "nouveau_drv.h"
 #include "nouveau_drv.h"
 #include "nouveau_i2c.h"
 #include "nouveau_i2c.h"
+#include "nouveau_connector.h"
 #include "nouveau_encoder.h"
 #include "nouveau_encoder.h"
 
 
 static int
 static int
@@ -270,13 +272,39 @@ bool
 nouveau_dp_link_train(struct drm_encoder *encoder)
 nouveau_dp_link_train(struct drm_encoder *encoder)
 {
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-	uint8_t config[4];
-	uint8_t status[3];
+	struct nouveau_connector *nv_connector;
+	struct bit_displayport_encoder_table *dpe;
+	int dpe_headerlen;
+	uint8_t config[4], status[3];
 	bool cr_done, cr_max_vs, eq_done;
 	bool cr_done, cr_max_vs, eq_done;
 	int ret = 0, i, tries, voltage;
 	int ret = 0, i, tries, voltage;
 
 
 	NV_DEBUG_KMS(dev, "link training!!\n");
 	NV_DEBUG_KMS(dev, "link training!!\n");
+
+	nv_connector = nouveau_encoder_connector_get(nv_encoder);
+	if (!nv_connector)
+		return false;
+
+	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
+	if (!dpe) {
+		NV_ERROR(dev, "SOR-%d: no DP encoder table!\n", nv_encoder->or);
+		return false;
+	}
+
+	/* disable hotplug detect, this flips around on some panels during
+	 * link training.
+	 */
+	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false);
+
+	if (dpe->script0) {
+		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or);
+		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0),
+					    nv_encoder->dcb);
+	}
+
 train:
 train:
 	cr_done = eq_done = false;
 	cr_done = eq_done = false;
 
 
@@ -403,6 +431,15 @@ stop:
 		}
 		}
 	}
 	}
 
 
+	if (dpe->script1) {
+		NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or);
+		nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1),
+					    nv_encoder->dcb);
+	}
+
+	/* re-enable hotplug detect */
+	pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true);
+
 	return eq_done;
 	return eq_done;
 }
 }
 
 

+ 18 - 23
drivers/gpu/drm/nouveau/nouveau_drv.c

@@ -35,10 +35,6 @@
 
 
 #include "drm_pciids.h"
 #include "drm_pciids.h"
 
 
-MODULE_PARM_DESC(ctxfw, "Use external firmware blob for grctx init (NV40)");
-int nouveau_ctxfw = 0;
-module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
-
 MODULE_PARM_DESC(noagp, "Disable AGP");
 MODULE_PARM_DESC(noagp, "Disable AGP");
 int nouveau_noagp;
 int nouveau_noagp;
 module_param_named(noagp, nouveau_noagp, int, 0400);
 module_param_named(noagp, nouveau_noagp, int, 0400);
@@ -56,7 +52,7 @@ int nouveau_vram_pushbuf;
 module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
 module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
 
 
 MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
 MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
-int nouveau_vram_notify = 1;
+int nouveau_vram_notify = 0;
 module_param_named(vram_notify, nouveau_vram_notify, int, 0400);
 module_param_named(vram_notify, nouveau_vram_notify, int, 0400);
 
 
 MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
 MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
@@ -132,7 +128,7 @@ static struct drm_driver driver;
 static int __devinit
 static int __devinit
 nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 {
-	return drm_get_dev(pdev, ent, &driver);
+	return drm_get_pci_dev(pdev, ent, &driver);
 }
 }
 
 
 static void
 static void
@@ -155,9 +151,6 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
 	struct drm_crtc *crtc;
 	struct drm_crtc *crtc;
 	int ret, i;
 	int ret, i;
 
 
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -ENODEV;
-
 	if (pm_state.event == PM_EVENT_PRETHAW)
 	if (pm_state.event == PM_EVENT_PRETHAW)
 		return 0;
 		return 0;
 
 
@@ -257,9 +250,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
 	struct drm_crtc *crtc;
 	struct drm_crtc *crtc;
 	int ret, i;
 	int ret, i;
 
 
-	if (!drm_core_check_feature(dev, DRIVER_MODESET))
-		return -ENODEV;
-
 	nouveau_fbcon_save_disable_accel(dev);
 	nouveau_fbcon_save_disable_accel(dev);
 
 
 	NV_INFO(dev, "We're back, enabling device...\n");
 	NV_INFO(dev, "We're back, enabling device...\n");
@@ -269,6 +259,13 @@ nouveau_pci_resume(struct pci_dev *pdev)
 		return -1;
 		return -1;
 	pci_set_master(dev->pdev);
 	pci_set_master(dev->pdev);
 
 
+	/* Make sure the AGP controller is in a consistent state */
+	if (dev_priv->gart_info.type == NOUVEAU_GART_AGP)
+		nouveau_mem_reset_agp(dev);
+
+	/* Make the CRTCs accessible */
+	engine->display.early_init(dev);
+
 	NV_INFO(dev, "POSTing device...\n");
 	NV_INFO(dev, "POSTing device...\n");
 	ret = nouveau_run_vbios_init(dev);
 	ret = nouveau_run_vbios_init(dev);
 	if (ret)
 	if (ret)
@@ -323,7 +320,6 @@ nouveau_pci_resume(struct pci_dev *pdev)
 
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-		int ret;
 
 
 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
 		if (!ret)
 		if (!ret)
@@ -332,11 +328,7 @@ nouveau_pci_resume(struct pci_dev *pdev)
 			NV_ERROR(dev, "Could not pin/map cursor.\n");
 			NV_ERROR(dev, "Could not pin/map cursor.\n");
 	}
 	}
 
 
-	if (dev_priv->card_type < NV_50) {
-		nv04_display_restore(dev);
-		NVLockVgaCrtcs(dev, false);
-	} else
-		nv50_display_init(dev);
+	engine->display.init(dev);
 
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
@@ -371,7 +363,8 @@ nouveau_pci_resume(struct pci_dev *pdev)
 static struct drm_driver driver = {
 static struct drm_driver driver = {
 	.driver_features =
 	.driver_features =
 		DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
 		DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG |
-		DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM,
+		DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM |
+		DRIVER_MODESET,
 	.load = nouveau_load,
 	.load = nouveau_load,
 	.firstopen = nouveau_firstopen,
 	.firstopen = nouveau_firstopen,
 	.lastclose = nouveau_lastclose,
 	.lastclose = nouveau_lastclose,
@@ -438,16 +431,18 @@ static int __init nouveau_init(void)
 			nouveau_modeset = 1;
 			nouveau_modeset = 1;
 	}
 	}
 
 
-	if (nouveau_modeset == 1) {
-		driver.driver_features |= DRIVER_MODESET;
-		nouveau_register_dsm_handler();
-	}
+	if (!nouveau_modeset)
+		return 0;
 
 
+	nouveau_register_dsm_handler();
 	return drm_init(&driver);
 	return drm_init(&driver);
 }
 }
 
 
 static void __exit nouveau_exit(void)
 static void __exit nouveau_exit(void)
 {
 {
+	if (!nouveau_modeset)
+		return;
+
 	drm_exit(&driver);
 	drm_exit(&driver);
 	nouveau_unregister_dsm_handler();
 	nouveau_unregister_dsm_handler();
 }
 }

+ 70 - 67
drivers/gpu/drm/nouveau/nouveau_drv.h

@@ -123,14 +123,6 @@ nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo)
 	return ioptr;
 	return ioptr;
 }
 }
 
 
-struct mem_block {
-	struct mem_block *next;
-	struct mem_block *prev;
-	uint64_t start;
-	uint64_t size;
-	struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */
-};
-
 enum nouveau_flags {
 enum nouveau_flags {
 	NV_NFORCE   = 0x10000000,
 	NV_NFORCE   = 0x10000000,
 	NV_NFORCE2  = 0x20000000
 	NV_NFORCE2  = 0x20000000
@@ -149,7 +141,7 @@ struct nouveau_gpuobj {
 	struct list_head list;
 	struct list_head list;
 
 
 	struct nouveau_channel *im_channel;
 	struct nouveau_channel *im_channel;
-	struct mem_block *im_pramin;
+	struct drm_mm_node *im_pramin;
 	struct nouveau_bo *im_backing;
 	struct nouveau_bo *im_backing;
 	uint32_t im_backing_start;
 	uint32_t im_backing_start;
 	uint32_t *im_backing_suspend;
 	uint32_t *im_backing_suspend;
@@ -196,7 +188,7 @@ struct nouveau_channel {
 		struct list_head pending;
 		struct list_head pending;
 		uint32_t sequence;
 		uint32_t sequence;
 		uint32_t sequence_ack;
 		uint32_t sequence_ack;
-		uint32_t last_sequence_irq;
+		atomic_t last_sequence_irq;
 	} fence;
 	} fence;
 
 
 	/* DMA push buffer */
 	/* DMA push buffer */
@@ -206,7 +198,7 @@ struct nouveau_channel {
 
 
 	/* Notifier memory */
 	/* Notifier memory */
 	struct nouveau_bo *notifier_bo;
 	struct nouveau_bo *notifier_bo;
-	struct mem_block *notifier_heap;
+	struct drm_mm notifier_heap;
 
 
 	/* PFIFO context */
 	/* PFIFO context */
 	struct nouveau_gpuobj_ref *ramfc;
 	struct nouveau_gpuobj_ref *ramfc;
@@ -224,7 +216,7 @@ struct nouveau_channel {
 
 
 	/* Objects */
 	/* Objects */
 	struct nouveau_gpuobj_ref *ramin; /* Private instmem */
 	struct nouveau_gpuobj_ref *ramin; /* Private instmem */
-	struct mem_block          *ramin_heap; /* Private PRAMIN heap */
+	struct drm_mm              ramin_heap; /* Private PRAMIN heap */
 	struct nouveau_gpuobj_ref *ramht; /* Hash table */
 	struct nouveau_gpuobj_ref *ramht; /* Hash table */
 	struct list_head           ramht_refs; /* Objects referenced by RAMHT */
 	struct list_head           ramht_refs; /* Objects referenced by RAMHT */
 
 
@@ -277,8 +269,7 @@ struct nouveau_instmem_engine {
 	void	(*clear)(struct drm_device *, struct nouveau_gpuobj *);
 	void	(*clear)(struct drm_device *, struct nouveau_gpuobj *);
 	int	(*bind)(struct drm_device *, struct nouveau_gpuobj *);
 	int	(*bind)(struct drm_device *, struct nouveau_gpuobj *);
 	int	(*unbind)(struct drm_device *, struct nouveau_gpuobj *);
 	int	(*unbind)(struct drm_device *, struct nouveau_gpuobj *);
-	void	(*prepare_access)(struct drm_device *, bool write);
-	void	(*finish_access)(struct drm_device *);
+	void	(*flush)(struct drm_device *);
 };
 };
 
 
 struct nouveau_mc_engine {
 struct nouveau_mc_engine {
@@ -303,10 +294,11 @@ struct nouveau_fb_engine {
 };
 };
 
 
 struct nouveau_fifo_engine {
 struct nouveau_fifo_engine {
-	void *priv;
-
 	int  channels;
 	int  channels;
 
 
+	struct nouveau_gpuobj_ref *playlist[2];
+	int cur_playlist;
+
 	int  (*init)(struct drm_device *);
 	int  (*init)(struct drm_device *);
 	void (*takedown)(struct drm_device *);
 	void (*takedown)(struct drm_device *);
 
 
@@ -339,10 +331,11 @@ struct nouveau_pgraph_object_class {
 struct nouveau_pgraph_engine {
 struct nouveau_pgraph_engine {
 	struct nouveau_pgraph_object_class *grclass;
 	struct nouveau_pgraph_object_class *grclass;
 	bool accel_blocked;
 	bool accel_blocked;
-	void *ctxprog;
-	void *ctxvals;
 	int grctx_size;
 	int grctx_size;
 
 
+	/* NV2x/NV3x context table (0x400780) */
+	struct nouveau_gpuobj_ref *ctx_table;
+
 	int  (*init)(struct drm_device *);
 	int  (*init)(struct drm_device *);
 	void (*takedown)(struct drm_device *);
 	void (*takedown)(struct drm_device *);
 
 
@@ -358,6 +351,24 @@ struct nouveau_pgraph_engine {
 				  uint32_t size, uint32_t pitch);
 				  uint32_t size, uint32_t pitch);
 };
 };
 
 
+struct nouveau_display_engine {
+	int (*early_init)(struct drm_device *);
+	void (*late_takedown)(struct drm_device *);
+	int (*create)(struct drm_device *);
+	int (*init)(struct drm_device *);
+	void (*destroy)(struct drm_device *);
+};
+
+struct nouveau_gpio_engine {
+	int  (*init)(struct drm_device *);
+	void (*takedown)(struct drm_device *);
+
+	int  (*get)(struct drm_device *, enum dcb_gpio_tag);
+	int  (*set)(struct drm_device *, enum dcb_gpio_tag, int state);
+
+	void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on);
+};
+
 struct nouveau_engine {
 struct nouveau_engine {
 	struct nouveau_instmem_engine instmem;
 	struct nouveau_instmem_engine instmem;
 	struct nouveau_mc_engine      mc;
 	struct nouveau_mc_engine      mc;
@@ -365,6 +376,8 @@ struct nouveau_engine {
 	struct nouveau_fb_engine      fb;
 	struct nouveau_fb_engine      fb;
 	struct nouveau_pgraph_engine  graph;
 	struct nouveau_pgraph_engine  graph;
 	struct nouveau_fifo_engine    fifo;
 	struct nouveau_fifo_engine    fifo;
+	struct nouveau_display_engine display;
+	struct nouveau_gpio_engine    gpio;
 };
 };
 
 
 struct nouveau_pll_vals {
 struct nouveau_pll_vals {
@@ -500,11 +513,6 @@ enum nouveau_card_type {
 
 
 struct drm_nouveau_private {
 struct drm_nouveau_private {
 	struct drm_device *dev;
 	struct drm_device *dev;
-	enum {
-		NOUVEAU_CARD_INIT_DOWN,
-		NOUVEAU_CARD_INIT_DONE,
-		NOUVEAU_CARD_INIT_FAILED
-	} init_state;
 
 
 	/* the card type, takes NV_* as values */
 	/* the card type, takes NV_* as values */
 	enum nouveau_card_type card_type;
 	enum nouveau_card_type card_type;
@@ -525,7 +533,7 @@ struct drm_nouveau_private {
 	struct list_head vbl_waiting;
 	struct list_head vbl_waiting;
 
 
 	struct {
 	struct {
-		struct ttm_global_reference mem_global_ref;
+		struct drm_global_reference mem_global_ref;
 		struct ttm_bo_global_ref bo_global_ref;
 		struct ttm_bo_global_ref bo_global_ref;
 		struct ttm_bo_device bdev;
 		struct ttm_bo_device bdev;
 		spinlock_t bo_list_lock;
 		spinlock_t bo_list_lock;
@@ -533,8 +541,6 @@ struct drm_nouveau_private {
 		atomic_t validate_sequence;
 		atomic_t validate_sequence;
 	} ttm;
 	} ttm;
 
 
-	struct fb_info *fbdev_info;
-
 	int fifo_alloc_count;
 	int fifo_alloc_count;
 	struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR];
 	struct nouveau_channel *fifos[NOUVEAU_MAX_CHANNEL_NR];
 
 
@@ -595,11 +601,7 @@ struct drm_nouveau_private {
 	struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
 	struct nouveau_gpuobj *vm_vram_pt[NV50_VM_VRAM_NR];
 	int vm_vram_pt_nr;
 	int vm_vram_pt_nr;
 
 
-	struct mem_block *ramin_heap;
-
-	/* context table pointed to be NV_PGRAPH_CHANNEL_CTX_TABLE (0x400780) */
-	uint32_t ctx_table_size;
-	struct nouveau_gpuobj_ref *ctx_table;
+	struct drm_mm ramin_heap;
 
 
 	struct list_head gpuobj_list;
 	struct list_head gpuobj_list;
 
 
@@ -618,6 +620,11 @@ struct drm_nouveau_private {
 	struct backlight_device *backlight;
 	struct backlight_device *backlight;
 
 
 	struct nouveau_channel *evo;
 	struct nouveau_channel *evo;
+	struct {
+		struct dcb_entry *dcb;
+		u16 script;
+		u32 pclk;
+	} evo_irq;
 
 
 	struct {
 	struct {
 		struct dentry *channel_root;
 		struct dentry *channel_root;
@@ -652,14 +659,6 @@ nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pnvbo)
 	return 0;
 	return 0;
 }
 }
 
 
-#define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do {            \
-	struct drm_nouveau_private *nv = dev->dev_private;    \
-	if (nv->init_state != NOUVEAU_CARD_INIT_DONE) {       \
-		NV_ERROR(dev, "called without init\n");       \
-		return -EINVAL;                               \
-	}                                                     \
-} while (0)
-
 #define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do {    \
 #define NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(id, cl, ch) do {    \
 	struct drm_nouveau_private *nv = dev->dev_private;       \
 	struct drm_nouveau_private *nv = dev->dev_private;       \
 	if (!nouveau_channel_owner(dev, (cl), (id))) {           \
 	if (!nouveau_channel_owner(dev, (cl), (id))) {           \
@@ -682,7 +681,6 @@ extern int nouveau_tv_disable;
 extern char *nouveau_tv_norm;
 extern char *nouveau_tv_norm;
 extern int nouveau_reg_debug;
 extern int nouveau_reg_debug;
 extern char *nouveau_vbios;
 extern char *nouveau_vbios;
-extern int nouveau_ctxfw;
 extern int nouveau_ignorelid;
 extern int nouveau_ignorelid;
 extern int nouveau_nofbaccel;
 extern int nouveau_nofbaccel;
 extern int nouveau_noaccel;
 extern int nouveau_noaccel;
@@ -707,17 +705,10 @@ extern bool nouveau_wait_for_idle(struct drm_device *);
 extern int  nouveau_card_init(struct drm_device *);
 extern int  nouveau_card_init(struct drm_device *);
 
 
 /* nouveau_mem.c */
 /* nouveau_mem.c */
-extern int  nouveau_mem_init_heap(struct mem_block **, uint64_t start,
-				 uint64_t size);
-extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *,
-						 uint64_t size, int align2,
-						 struct drm_file *, int tail);
-extern void nouveau_mem_takedown(struct mem_block **heap);
-extern void nouveau_mem_free_block(struct mem_block *);
 extern int  nouveau_mem_detect(struct drm_device *dev);
 extern int  nouveau_mem_detect(struct drm_device *dev);
-extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap);
 extern int  nouveau_mem_init(struct drm_device *);
 extern int  nouveau_mem_init(struct drm_device *);
 extern int  nouveau_mem_init_agp(struct drm_device *);
 extern int  nouveau_mem_init_agp(struct drm_device *);
+extern int  nouveau_mem_reset_agp(struct drm_device *);
 extern void nouveau_mem_close(struct drm_device *);
 extern void nouveau_mem_close(struct drm_device *);
 extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev,
 extern struct nouveau_tile_reg *nv10_mem_set_tiling(struct drm_device *dev,
 						    uint32_t addr,
 						    uint32_t addr,
@@ -857,11 +848,13 @@ void nouveau_register_dsm_handler(void);
 void nouveau_unregister_dsm_handler(void);
 void nouveau_unregister_dsm_handler(void);
 int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
 int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len);
 bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
 bool nouveau_acpi_rom_supported(struct pci_dev *pdev);
+int nouveau_acpi_edid(struct drm_device *, struct drm_connector *);
 #else
 #else
 static inline void nouveau_register_dsm_handler(void) {}
 static inline void nouveau_register_dsm_handler(void) {}
 static inline void nouveau_unregister_dsm_handler(void) {}
 static inline void nouveau_unregister_dsm_handler(void) {}
 static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
 static inline bool nouveau_acpi_rom_supported(struct pci_dev *pdev) { return false; }
 static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
 static inline int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len) { return -EINVAL; }
+static inline int nouveau_acpi_edid(struct drm_device *dev, struct drm_connector *connector) { return -EINVAL; }
 #endif
 #endif
 
 
 /* nouveau_backlight.c */
 /* nouveau_backlight.c */
@@ -924,6 +917,10 @@ extern void nv10_fb_takedown(struct drm_device *);
 extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t,
 extern void nv10_fb_set_region_tiling(struct drm_device *, int, uint32_t,
 				      uint32_t, uint32_t);
 				      uint32_t, uint32_t);
 
 
+/* nv30_fb.c */
+extern int  nv30_fb_init(struct drm_device *);
+extern void nv30_fb_takedown(struct drm_device *);
+
 /* nv40_fb.c */
 /* nv40_fb.c */
 extern int  nv40_fb_init(struct drm_device *);
 extern int  nv40_fb_init(struct drm_device *);
 extern void nv40_fb_takedown(struct drm_device *);
 extern void nv40_fb_takedown(struct drm_device *);
@@ -1035,12 +1032,6 @@ extern int  nv50_graph_unload_context(struct drm_device *);
 extern void nv50_graph_context_switch(struct drm_device *);
 extern void nv50_graph_context_switch(struct drm_device *);
 extern int  nv50_grctx_init(struct nouveau_grctx *);
 extern int  nv50_grctx_init(struct nouveau_grctx *);
 
 
-/* nouveau_grctx.c */
-extern int  nouveau_grctx_prog_load(struct drm_device *);
-extern void nouveau_grctx_vals_load(struct drm_device *,
-				    struct nouveau_gpuobj *);
-extern void nouveau_grctx_fini(struct drm_device *);
-
 /* nv04_instmem.c */
 /* nv04_instmem.c */
 extern int  nv04_instmem_init(struct drm_device *);
 extern int  nv04_instmem_init(struct drm_device *);
 extern void nv04_instmem_takedown(struct drm_device *);
 extern void nv04_instmem_takedown(struct drm_device *);
@@ -1051,8 +1042,7 @@ extern int  nv04_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
 extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
 extern void nv04_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
 extern int  nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
 extern int  nv04_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
 extern int  nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
 extern int  nv04_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
-extern void nv04_instmem_prepare_access(struct drm_device *, bool write);
-extern void nv04_instmem_finish_access(struct drm_device *);
+extern void nv04_instmem_flush(struct drm_device *);
 
 
 /* nv50_instmem.c */
 /* nv50_instmem.c */
 extern int  nv50_instmem_init(struct drm_device *);
 extern int  nv50_instmem_init(struct drm_device *);
@@ -1064,8 +1054,9 @@ extern int  nv50_instmem_populate(struct drm_device *, struct nouveau_gpuobj *,
 extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
 extern void nv50_instmem_clear(struct drm_device *, struct nouveau_gpuobj *);
 extern int  nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
 extern int  nv50_instmem_bind(struct drm_device *, struct nouveau_gpuobj *);
 extern int  nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
 extern int  nv50_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *);
-extern void nv50_instmem_prepare_access(struct drm_device *, bool write);
-extern void nv50_instmem_finish_access(struct drm_device *);
+extern void nv50_instmem_flush(struct drm_device *);
+extern void nv84_instmem_flush(struct drm_device *);
+extern void nv50_vm_flush(struct drm_device *, int engine);
 
 
 /* nv04_mc.c */
 /* nv04_mc.c */
 extern int  nv04_mc_init(struct drm_device *);
 extern int  nv04_mc_init(struct drm_device *);
@@ -1088,13 +1079,14 @@ extern long nouveau_compat_ioctl(struct file *file, unsigned int cmd,
 				 unsigned long arg);
 				 unsigned long arg);
 
 
 /* nv04_dac.c */
 /* nv04_dac.c */
-extern int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry);
+extern int nv04_dac_create(struct drm_connector *, struct dcb_entry *);
 extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
 extern uint32_t nv17_dac_sample_load(struct drm_encoder *encoder);
 extern int nv04_dac_output_offset(struct drm_encoder *encoder);
 extern int nv04_dac_output_offset(struct drm_encoder *encoder);
 extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
 extern void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable);
+extern bool nv04_dac_in_use(struct drm_encoder *encoder);
 
 
 /* nv04_dfp.c */
 /* nv04_dfp.c */
-extern int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry);
+extern int nv04_dfp_create(struct drm_connector *, struct dcb_entry *);
 extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent);
 extern int nv04_dfp_get_bound_head(struct drm_device *dev, struct dcb_entry *dcbent);
 extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent,
 extern void nv04_dfp_bind_head(struct drm_device *dev, struct dcb_entry *dcbent,
 			       int head, bool dl);
 			       int head, bool dl);
@@ -1103,15 +1095,17 @@ extern void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode);
 
 
 /* nv04_tv.c */
 /* nv04_tv.c */
 extern int nv04_tv_identify(struct drm_device *dev, int i2c_index);
 extern int nv04_tv_identify(struct drm_device *dev, int i2c_index);
-extern int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry);
+extern int nv04_tv_create(struct drm_connector *, struct dcb_entry *);
 
 
 /* nv17_tv.c */
 /* nv17_tv.c */
-extern int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry);
+extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *);
 
 
 /* nv04_display.c */
 /* nv04_display.c */
+extern int nv04_display_early_init(struct drm_device *);
+extern void nv04_display_late_takedown(struct drm_device *);
 extern int nv04_display_create(struct drm_device *);
 extern int nv04_display_create(struct drm_device *);
+extern int nv04_display_init(struct drm_device *);
 extern void nv04_display_destroy(struct drm_device *);
 extern void nv04_display_destroy(struct drm_device *);
-extern void nv04_display_restore(struct drm_device *);
 
 
 /* nv04_crtc.c */
 /* nv04_crtc.c */
 extern int nv04_crtc_create(struct drm_device *, int index);
 extern int nv04_crtc_create(struct drm_device *, int index);
@@ -1147,7 +1141,6 @@ extern int nouveau_fence_wait(void *obj, void *arg, bool lazy, bool intr);
 extern int nouveau_fence_flush(void *obj, void *arg);
 extern int nouveau_fence_flush(void *obj, void *arg);
 extern void nouveau_fence_unref(void **obj);
 extern void nouveau_fence_unref(void **obj);
 extern void *nouveau_fence_ref(void *obj);
 extern void *nouveau_fence_ref(void *obj);
-extern void nouveau_fence_handler(struct drm_device *dev, int channel);
 
 
 /* nouveau_gem.c */
 /* nouveau_gem.c */
 extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
 extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
@@ -1167,13 +1160,15 @@ extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
 extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
 extern int nouveau_gem_ioctl_info(struct drm_device *, void *,
 				  struct drm_file *);
 				  struct drm_file *);
 
 
-/* nv17_gpio.c */
-int nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
-int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
+/* nv10_gpio.c */
+int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
+int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
 
 
 /* nv50_gpio.c */
 /* nv50_gpio.c */
+int nv50_gpio_init(struct drm_device *dev);
 int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
 int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag);
 int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
 int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state);
+void nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on);
 
 
 /* nv50_calc. */
 /* nv50_calc. */
 int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk,
 int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk,
@@ -1220,6 +1215,14 @@ static inline void nv_wr32(struct drm_device *dev, unsigned reg, u32 val)
 	iowrite32_native(val, dev_priv->mmio + reg);
 	iowrite32_native(val, dev_priv->mmio + reg);
 }
 }
 
 
+static inline void nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val)
+{
+	u32 tmp = nv_rd32(dev, reg);
+	tmp &= ~mask;
+	tmp |= val;
+	nv_wr32(dev, reg, tmp);
+}
+
 static inline u8 nv_rd08(struct drm_device *dev, unsigned reg)
 static inline u8 nv_rd08(struct drm_device *dev, unsigned reg)
 {
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;

+ 6 - 4
drivers/gpu/drm/nouveau/nouveau_encoder.h

@@ -38,13 +38,15 @@ struct nouveau_encoder {
 	struct dcb_entry *dcb;
 	struct dcb_entry *dcb;
 	int or;
 	int or;
 
 
+	/* different to drm_encoder.crtc, this reflects what's
+	 * actually programmed on the hw, not the proposed crtc */
+	struct drm_crtc *crtc;
+
 	struct drm_display_mode mode;
 	struct drm_display_mode mode;
 	int last_dpms;
 	int last_dpms;
 
 
 	struct nv04_output_reg restore;
 	struct nv04_output_reg restore;
 
 
-	void (*disconnect)(struct nouveau_encoder *encoder);
-
 	union {
 	union {
 		struct {
 		struct {
 			int mc_unknown;
 			int mc_unknown;
@@ -71,8 +73,8 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc)
 
 
 struct nouveau_connector *
 struct nouveau_connector *
 nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
 nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
-int nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry);
-int nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry);
+int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
+int nv50_dac_create(struct drm_connector *, struct dcb_entry *);
 
 
 struct bit_displayport_encoder_table {
 struct bit_displayport_encoder_table {
 	uint32_t match;
 	uint32_t match;

+ 1 - 1
drivers/gpu/drm/nouveau/nouveau_fbcon.c

@@ -333,7 +333,7 @@ nouveau_fbcon_output_poll_changed(struct drm_device *dev)
 	drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper);
 	drm_fb_helper_hotplug_event(&dev_priv->nfbdev->helper);
 }
 }
 
 
-int
+static int
 nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
 nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *nfbdev)
 {
 {
 	struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb;
 	struct nouveau_framebuffer *nouveau_fb = &nfbdev->nouveau_fb;

+ 8 - 27
drivers/gpu/drm/nouveau/nouveau_fence.c

@@ -67,12 +67,13 @@ nouveau_fence_update(struct nouveau_channel *chan)
 	if (USE_REFCNT)
 	if (USE_REFCNT)
 		sequence = nvchan_rd32(chan, 0x48);
 		sequence = nvchan_rd32(chan, 0x48);
 	else
 	else
-		sequence = chan->fence.last_sequence_irq;
+		sequence = atomic_read(&chan->fence.last_sequence_irq);
 
 
 	if (chan->fence.sequence_ack == sequence)
 	if (chan->fence.sequence_ack == sequence)
 		return;
 		return;
 	chan->fence.sequence_ack = sequence;
 	chan->fence.sequence_ack = sequence;
 
 
+	spin_lock(&chan->fence.lock);
 	list_for_each_safe(entry, tmp, &chan->fence.pending) {
 	list_for_each_safe(entry, tmp, &chan->fence.pending) {
 		fence = list_entry(entry, struct nouveau_fence, entry);
 		fence = list_entry(entry, struct nouveau_fence, entry);
 
 
@@ -84,6 +85,7 @@ nouveau_fence_update(struct nouveau_channel *chan)
 		if (sequence == chan->fence.sequence_ack)
 		if (sequence == chan->fence.sequence_ack)
 			break;
 			break;
 	}
 	}
+	spin_unlock(&chan->fence.lock);
 }
 }
 
 
 int
 int
@@ -119,7 +121,6 @@ nouveau_fence_emit(struct nouveau_fence *fence)
 {
 {
 	struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private;
 	struct drm_nouveau_private *dev_priv = fence->channel->dev->dev_private;
 	struct nouveau_channel *chan = fence->channel;
 	struct nouveau_channel *chan = fence->channel;
-	unsigned long flags;
 	int ret;
 	int ret;
 
 
 	ret = RING_SPACE(chan, 2);
 	ret = RING_SPACE(chan, 2);
@@ -127,9 +128,7 @@ nouveau_fence_emit(struct nouveau_fence *fence)
 		return ret;
 		return ret;
 
 
 	if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) {
 	if (unlikely(chan->fence.sequence == chan->fence.sequence_ack - 1)) {
-		spin_lock_irqsave(&chan->fence.lock, flags);
 		nouveau_fence_update(chan);
 		nouveau_fence_update(chan);
-		spin_unlock_irqrestore(&chan->fence.lock, flags);
 
 
 		BUG_ON(chan->fence.sequence ==
 		BUG_ON(chan->fence.sequence ==
 		       chan->fence.sequence_ack - 1);
 		       chan->fence.sequence_ack - 1);
@@ -138,9 +137,9 @@ nouveau_fence_emit(struct nouveau_fence *fence)
 	fence->sequence = ++chan->fence.sequence;
 	fence->sequence = ++chan->fence.sequence;
 
 
 	kref_get(&fence->refcount);
 	kref_get(&fence->refcount);
-	spin_lock_irqsave(&chan->fence.lock, flags);
+	spin_lock(&chan->fence.lock);
 	list_add_tail(&fence->entry, &chan->fence.pending);
 	list_add_tail(&fence->entry, &chan->fence.pending);
-	spin_unlock_irqrestore(&chan->fence.lock, flags);
+	spin_unlock(&chan->fence.lock);
 
 
 	BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1);
 	BEGIN_RING(chan, NvSubSw, USE_REFCNT ? 0x0050 : 0x0150, 1);
 	OUT_RING(chan, fence->sequence);
 	OUT_RING(chan, fence->sequence);
@@ -173,14 +172,11 @@ nouveau_fence_signalled(void *sync_obj, void *sync_arg)
 {
 {
 	struct nouveau_fence *fence = nouveau_fence(sync_obj);
 	struct nouveau_fence *fence = nouveau_fence(sync_obj);
 	struct nouveau_channel *chan = fence->channel;
 	struct nouveau_channel *chan = fence->channel;
-	unsigned long flags;
 
 
 	if (fence->signalled)
 	if (fence->signalled)
 		return true;
 		return true;
 
 
-	spin_lock_irqsave(&chan->fence.lock, flags);
 	nouveau_fence_update(chan);
 	nouveau_fence_update(chan);
-	spin_unlock_irqrestore(&chan->fence.lock, flags);
 	return fence->signalled;
 	return fence->signalled;
 }
 }
 
 
@@ -190,8 +186,6 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
 	unsigned long timeout = jiffies + (3 * DRM_HZ);
 	unsigned long timeout = jiffies + (3 * DRM_HZ);
 	int ret = 0;
 	int ret = 0;
 
 
-	__set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
-
 	while (1) {
 	while (1) {
 		if (nouveau_fence_signalled(sync_obj, sync_arg))
 		if (nouveau_fence_signalled(sync_obj, sync_arg))
 			break;
 			break;
@@ -201,6 +195,8 @@ nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
 			break;
 			break;
 		}
 		}
 
 
+		__set_current_state(intr ? TASK_INTERRUPTIBLE
+			: TASK_UNINTERRUPTIBLE);
 		if (lazy)
 		if (lazy)
 			schedule_timeout(1);
 			schedule_timeout(1);
 
 
@@ -221,27 +217,12 @@ nouveau_fence_flush(void *sync_obj, void *sync_arg)
 	return 0;
 	return 0;
 }
 }
 
 
-void
-nouveau_fence_handler(struct drm_device *dev, int channel)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *chan = NULL;
-
-	if (channel >= 0 && channel < dev_priv->engine.fifo.channels)
-		chan = dev_priv->fifos[channel];
-
-	if (chan) {
-		spin_lock_irq(&chan->fence.lock);
-		nouveau_fence_update(chan);
-		spin_unlock_irq(&chan->fence.lock);
-	}
-}
-
 int
 int
 nouveau_fence_init(struct nouveau_channel *chan)
 nouveau_fence_init(struct nouveau_channel *chan)
 {
 {
 	INIT_LIST_HEAD(&chan->fence.pending);
 	INIT_LIST_HEAD(&chan->fence.pending);
 	spin_lock_init(&chan->fence.lock);
 	spin_lock_init(&chan->fence.lock);
+	atomic_set(&chan->fence.last_sequence_irq, 0);
 	return 0;
 	return 0;
 }
 }
 
 

+ 1 - 10
drivers/gpu/drm/nouveau/nouveau_gem.c

@@ -137,8 +137,6 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data,
 	uint32_t flags = 0;
 	uint32_t flags = 0;
 	int ret = 0;
 	int ret = 0;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
 	if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
 	if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
 		dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
 		dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
 
 
@@ -577,10 +575,9 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
 	struct drm_nouveau_gem_pushbuf_bo *bo;
 	struct drm_nouveau_gem_pushbuf_bo *bo;
 	struct nouveau_channel *chan;
 	struct nouveau_channel *chan;
 	struct validate_op op;
 	struct validate_op op;
-	struct nouveau_fence *fence = 0;
+	struct nouveau_fence *fence = NULL;
 	int i, j, ret = 0, do_reloc = 0;
 	int i, j, ret = 0, do_reloc = 0;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
 
 
 	req->vram_available = dev_priv->fb_aper_free;
 	req->vram_available = dev_priv->fb_aper_free;
@@ -760,8 +757,6 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
 	bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
 	bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT);
 	int ret = -EINVAL;
 	int ret = -EINVAL;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
 	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
 	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
 	if (!gem)
 	if (!gem)
 		return ret;
 		return ret;
@@ -800,8 +795,6 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data,
 	struct nouveau_bo *nvbo;
 	struct nouveau_bo *nvbo;
 	int ret = -EINVAL;
 	int ret = -EINVAL;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
 	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
 	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
 	if (!gem)
 	if (!gem)
 		return ret;
 		return ret;
@@ -827,8 +820,6 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data,
 	struct drm_gem_object *gem;
 	struct drm_gem_object *gem;
 	int ret;
 	int ret;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
 	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
 	gem = drm_gem_object_lookup(dev, file_priv, req->handle);
 	if (!gem)
 	if (!gem)
 		return -EINVAL;
 		return -EINVAL;

+ 0 - 160
drivers/gpu/drm/nouveau/nouveau_grctx.c

@@ -1,160 +0,0 @@
-/*
- * Copyright 2009 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-
-#include <linux/firmware.h>
-#include <linux/slab.h>
-
-#include "drmP.h"
-#include "nouveau_drv.h"
-
-struct nouveau_ctxprog {
-	uint32_t signature;
-	uint8_t  version;
-	uint16_t length;
-	uint32_t data[];
-} __attribute__ ((packed));
-
-struct nouveau_ctxvals {
-	uint32_t signature;
-	uint8_t  version;
-	uint32_t length;
-	struct {
-		uint32_t offset;
-		uint32_t value;
-	} data[];
-} __attribute__ ((packed));
-
-int
-nouveau_grctx_prog_load(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-	const int chipset = dev_priv->chipset;
-	const struct firmware *fw;
-	const struct nouveau_ctxprog *cp;
-	const struct nouveau_ctxvals *cv;
-	char name[32];
-	int ret, i;
-
-	if (pgraph->accel_blocked)
-		return -ENODEV;
-
-	if (!pgraph->ctxprog) {
-		sprintf(name, "nouveau/nv%02x.ctxprog", chipset);
-		ret = request_firmware(&fw, name, &dev->pdev->dev);
-		if (ret) {
-			NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset);
-			return ret;
-		}
-
-		pgraph->ctxprog = kmemdup(fw->data, fw->size, GFP_KERNEL);
-		if (!pgraph->ctxprog) {
-			NV_ERROR(dev, "OOM copying ctxprog\n");
-			release_firmware(fw);
-			return -ENOMEM;
-		}
-
-		cp = pgraph->ctxprog;
-		if (le32_to_cpu(cp->signature) != 0x5043564e ||
-		    cp->version != 0 ||
-		    le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) {
-			NV_ERROR(dev, "ctxprog invalid\n");
-			release_firmware(fw);
-			nouveau_grctx_fini(dev);
-			return -EINVAL;
-		}
-		release_firmware(fw);
-	}
-
-	if (!pgraph->ctxvals) {
-		sprintf(name, "nouveau/nv%02x.ctxvals", chipset);
-		ret = request_firmware(&fw, name, &dev->pdev->dev);
-		if (ret) {
-			NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset);
-			nouveau_grctx_fini(dev);
-			return ret;
-		}
-
-		pgraph->ctxvals = kmemdup(fw->data, fw->size, GFP_KERNEL);
-		if (!pgraph->ctxvals) {
-			NV_ERROR(dev, "OOM copying ctxvals\n");
-			release_firmware(fw);
-			nouveau_grctx_fini(dev);
-			return -ENOMEM;
-		}
-
-		cv = (void *)pgraph->ctxvals;
-		if (le32_to_cpu(cv->signature) != 0x5643564e ||
-		    cv->version != 0 ||
-		    le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) {
-			NV_ERROR(dev, "ctxvals invalid\n");
-			release_firmware(fw);
-			nouveau_grctx_fini(dev);
-			return -EINVAL;
-		}
-		release_firmware(fw);
-	}
-
-	cp = pgraph->ctxprog;
-
-	nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
-	for (i = 0; i < le16_to_cpu(cp->length); i++)
-		nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA,
-			le32_to_cpu(cp->data[i]));
-
-	return 0;
-}
-
-void
-nouveau_grctx_fini(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-
-	if (pgraph->ctxprog) {
-		kfree(pgraph->ctxprog);
-		pgraph->ctxprog = NULL;
-	}
-
-	if (pgraph->ctxvals) {
-		kfree(pgraph->ctxprog);
-		pgraph->ctxvals = NULL;
-	}
-}
-
-void
-nouveau_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-	struct nouveau_ctxvals *cv = pgraph->ctxvals;
-	int i;
-
-	if (!cv)
-		return;
-
-	for (i = 0; i < le32_to_cpu(cv->length); i++)
-		nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset),
-			le32_to_cpu(cv->data[i].value));
-}

+ 42 - 0
drivers/gpu/drm/nouveau/nouveau_i2c.c

@@ -278,3 +278,45 @@ nouveau_i2c_find(struct drm_device *dev, int index)
 	return i2c->chan;
 	return i2c->chan;
 }
 }
 
 
+bool
+nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr)
+{
+	uint8_t buf[] = { 0 };
+	struct i2c_msg msgs[] = {
+		{
+			.addr = addr,
+			.flags = 0,
+			.len = 1,
+			.buf = buf,
+		},
+		{
+			.addr = addr,
+			.flags = I2C_M_RD,
+			.len = 1,
+			.buf = buf,
+		}
+	};
+
+	return i2c_transfer(&i2c->adapter, msgs, 2) == 2;
+}
+
+int
+nouveau_i2c_identify(struct drm_device *dev, const char *what,
+		     struct i2c_board_info *info, int index)
+{
+	struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index);
+	int i;
+
+	NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index);
+
+	for (i = 0; info[i].addr; i++) {
+		if (nouveau_probe_i2c_addr(i2c, info[i].addr)) {
+			NV_INFO(dev, "Detected %s: %s\n", what, info[i].type);
+			return i;
+		}
+	}
+
+	NV_DEBUG(dev, "No devices found.\n");
+
+	return -ENODEV;
+}

+ 3 - 0
drivers/gpu/drm/nouveau/nouveau_i2c.h

@@ -45,6 +45,9 @@ struct nouveau_i2c_chan {
 int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index);
 int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index);
 void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
 void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *);
 struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
 struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index);
+bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr);
+int nouveau_i2c_identify(struct drm_device *dev, const char *what,
+			 struct i2c_board_info *info, int index);
 
 
 int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte,
 int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte,
 			  uint8_t *read_byte);
 			  uint8_t *read_byte);

+ 67 - 265
drivers/gpu/drm/nouveau/nouveau_mem.c

@@ -35,162 +35,6 @@
 #include "drm_sarea.h"
 #include "drm_sarea.h"
 #include "nouveau_drv.h"
 #include "nouveau_drv.h"
 
 
-static struct mem_block *
-split_block(struct mem_block *p, uint64_t start, uint64_t size,
-	    struct drm_file *file_priv)
-{
-	/* Maybe cut off the start of an existing block */
-	if (start > p->start) {
-		struct mem_block *newblock =
-			kmalloc(sizeof(*newblock), GFP_KERNEL);
-		if (!newblock)
-			goto out;
-		newblock->start = start;
-		newblock->size = p->size - (start - p->start);
-		newblock->file_priv = NULL;
-		newblock->next = p->next;
-		newblock->prev = p;
-		p->next->prev = newblock;
-		p->next = newblock;
-		p->size -= newblock->size;
-		p = newblock;
-	}
-
-	/* Maybe cut off the end of an existing block */
-	if (size < p->size) {
-		struct mem_block *newblock =
-			kmalloc(sizeof(*newblock), GFP_KERNEL);
-		if (!newblock)
-			goto out;
-		newblock->start = start + size;
-		newblock->size = p->size - size;
-		newblock->file_priv = NULL;
-		newblock->next = p->next;
-		newblock->prev = p;
-		p->next->prev = newblock;
-		p->next = newblock;
-		p->size = size;
-	}
-
-out:
-	/* Our block is in the middle */
-	p->file_priv = file_priv;
-	return p;
-}
-
-struct mem_block *
-nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size,
-			int align2, struct drm_file *file_priv, int tail)
-{
-	struct mem_block *p;
-	uint64_t mask = (1 << align2) - 1;
-
-	if (!heap)
-		return NULL;
-
-	if (tail) {
-		list_for_each_prev(p, heap) {
-			uint64_t start = ((p->start + p->size) - size) & ~mask;
-
-			if (p->file_priv == NULL && start >= p->start &&
-			    start + size <= p->start + p->size)
-				return split_block(p, start, size, file_priv);
-		}
-	} else {
-		list_for_each(p, heap) {
-			uint64_t start = (p->start + mask) & ~mask;
-
-			if (p->file_priv == NULL &&
-			    start + size <= p->start + p->size)
-				return split_block(p, start, size, file_priv);
-		}
-	}
-
-	return NULL;
-}
-
-void nouveau_mem_free_block(struct mem_block *p)
-{
-	p->file_priv = NULL;
-
-	/* Assumes a single contiguous range.  Needs a special file_priv in
-	 * 'heap' to stop it being subsumed.
-	 */
-	if (p->next->file_priv == NULL) {
-		struct mem_block *q = p->next;
-		p->size += q->size;
-		p->next = q->next;
-		p->next->prev = p;
-		kfree(q);
-	}
-
-	if (p->prev->file_priv == NULL) {
-		struct mem_block *q = p->prev;
-		q->size += p->size;
-		q->next = p->next;
-		q->next->prev = q;
-		kfree(p);
-	}
-}
-
-/* Initialize.  How to check for an uninitialized heap?
- */
-int nouveau_mem_init_heap(struct mem_block **heap, uint64_t start,
-			  uint64_t size)
-{
-	struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL);
-
-	if (!blocks)
-		return -ENOMEM;
-
-	*heap = kmalloc(sizeof(**heap), GFP_KERNEL);
-	if (!*heap) {
-		kfree(blocks);
-		return -ENOMEM;
-	}
-
-	blocks->start = start;
-	blocks->size = size;
-	blocks->file_priv = NULL;
-	blocks->next = blocks->prev = *heap;
-
-	memset(*heap, 0, sizeof(**heap));
-	(*heap)->file_priv = (struct drm_file *) -1;
-	(*heap)->next = (*heap)->prev = blocks;
-	return 0;
-}
-
-/*
- * Free all blocks associated with the releasing file_priv
- */
-void nouveau_mem_release(struct drm_file *file_priv, struct mem_block *heap)
-{
-	struct mem_block *p;
-
-	if (!heap || !heap->next)
-		return;
-
-	list_for_each(p, heap) {
-		if (p->file_priv == file_priv)
-			p->file_priv = NULL;
-	}
-
-	/* Assumes a single contiguous range.  Needs a special file_priv in
-	 * 'heap' to stop it being subsumed.
-	 */
-	list_for_each(p, heap) {
-		while ((p->file_priv == NULL) &&
-					(p->next->file_priv == NULL) &&
-					(p->next != heap)) {
-			struct mem_block *q = p->next;
-			p->size += q->size;
-			p->next = q->next;
-			p->next->prev = p;
-			kfree(q);
-		}
-	}
-}
-
 /*
 /*
  * NV10-NV40 tiling helpers
  * NV10-NV40 tiling helpers
  */
  */
@@ -299,7 +143,6 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
 		phys |= 0x30;
 		phys |= 0x30;
 	}
 	}
 
 
-	dev_priv->engine.instmem.prepare_access(dev, true);
 	while (size) {
 	while (size) {
 		unsigned offset_h = upper_32_bits(phys);
 		unsigned offset_h = upper_32_bits(phys);
 		unsigned offset_l = lower_32_bits(phys);
 		unsigned offset_l = lower_32_bits(phys);
@@ -331,36 +174,12 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size,
 			}
 			}
 		}
 		}
 	}
 	}
-	dev_priv->engine.instmem.finish_access(dev);
-
-	nv_wr32(dev, 0x100c80, 0x00050001);
-	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-		return -EBUSY;
-	}
-
-	nv_wr32(dev, 0x100c80, 0x00000001);
-	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-		return -EBUSY;
-	}
-
-	nv_wr32(dev, 0x100c80, 0x00040001);
-	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-		return -EBUSY;
-	}
-
-	nv_wr32(dev, 0x100c80, 0x00060001);
-	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-		return -EBUSY;
-	}
+	dev_priv->engine.instmem.flush(dev);
 
 
+	nv50_vm_flush(dev, 5);
+	nv50_vm_flush(dev, 0);
+	nv50_vm_flush(dev, 4);
+	nv50_vm_flush(dev, 6);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -374,7 +193,6 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
 	virt -= dev_priv->vm_vram_base;
 	virt -= dev_priv->vm_vram_base;
 	pages = (size >> 16) << 1;
 	pages = (size >> 16) << 1;
 
 
-	dev_priv->engine.instmem.prepare_access(dev, true);
 	while (pages) {
 	while (pages) {
 		pgt = dev_priv->vm_vram_pt[virt >> 29];
 		pgt = dev_priv->vm_vram_pt[virt >> 29];
 		pte = (virt & 0x1ffe0000ULL) >> 15;
 		pte = (virt & 0x1ffe0000ULL) >> 15;
@@ -388,57 +206,19 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size)
 		while (pte < end)
 		while (pte < end)
 			nv_wo32(dev, pgt, pte++, 0);
 			nv_wo32(dev, pgt, pte++, 0);
 	}
 	}
-	dev_priv->engine.instmem.finish_access(dev);
-
-	nv_wr32(dev, 0x100c80, 0x00050001);
-	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-		return;
-	}
-
-	nv_wr32(dev, 0x100c80, 0x00000001);
-	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-		return;
-	}
-
-	nv_wr32(dev, 0x100c80, 0x00040001);
-	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-		return;
-	}
+	dev_priv->engine.instmem.flush(dev);
 
 
-	nv_wr32(dev, 0x100c80, 0x00060001);
-	if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-		NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-		NV_ERROR(dev, "0x100c80 = 0x%08x\n", nv_rd32(dev, 0x100c80));
-	}
+	nv50_vm_flush(dev, 5);
+	nv50_vm_flush(dev, 0);
+	nv50_vm_flush(dev, 4);
+	nv50_vm_flush(dev, 6);
 }
 }
 
 
 /*
 /*
  * Cleanup everything
  * Cleanup everything
  */
  */
-void nouveau_mem_takedown(struct mem_block **heap)
-{
-	struct mem_block *p;
-
-	if (!*heap)
-		return;
-
-	for (p = (*heap)->next; p != *heap;) {
-		struct mem_block *q = p;
-		p = p->next;
-		kfree(q);
-	}
-
-	kfree(*heap);
-	*heap = NULL;
-}
-
-void nouveau_mem_close(struct drm_device *dev)
+void
+nouveau_mem_close(struct drm_device *dev)
 {
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 
@@ -449,8 +229,7 @@ void nouveau_mem_close(struct drm_device *dev)
 
 
 	nouveau_ttm_global_release(dev_priv);
 	nouveau_ttm_global_release(dev_priv);
 
 
-	if (drm_core_has_AGP(dev) && dev->agp &&
-	    drm_core_check_feature(dev, DRIVER_MODESET)) {
+	if (drm_core_has_AGP(dev) && dev->agp) {
 		struct drm_agp_mem *entry, *tempe;
 		struct drm_agp_mem *entry, *tempe;
 
 
 		/* Remove AGP resources, but leave dev->agp
 		/* Remove AGP resources, but leave dev->agp
@@ -471,28 +250,29 @@ void nouveau_mem_close(struct drm_device *dev)
 	}
 	}
 
 
 	if (dev_priv->fb_mtrr) {
 	if (dev_priv->fb_mtrr) {
-		drm_mtrr_del(dev_priv->fb_mtrr, drm_get_resource_start(dev, 1),
-			     drm_get_resource_len(dev, 1), DRM_MTRR_WC);
-		dev_priv->fb_mtrr = 0;
+		drm_mtrr_del(dev_priv->fb_mtrr,
+			     pci_resource_start(dev->pdev, 1),
+			     pci_resource_len(dev->pdev, 1), DRM_MTRR_WC);
+		dev_priv->fb_mtrr = -1;
 	}
 	}
 }
 }
 
 
 static uint32_t
 static uint32_t
 nouveau_mem_detect_nv04(struct drm_device *dev)
 nouveau_mem_detect_nv04(struct drm_device *dev)
 {
 {
-	uint32_t boot0 = nv_rd32(dev, NV03_BOOT_0);
+	uint32_t boot0 = nv_rd32(dev, NV04_PFB_BOOT_0);
 
 
 	if (boot0 & 0x00000100)
 	if (boot0 & 0x00000100)
 		return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024;
 		return (((boot0 >> 12) & 0xf) * 2 + 2) * 1024 * 1024;
 
 
-	switch (boot0 & NV03_BOOT_0_RAM_AMOUNT) {
-	case NV04_BOOT_0_RAM_AMOUNT_32MB:
+	switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
+	case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
 		return 32 * 1024 * 1024;
 		return 32 * 1024 * 1024;
-	case NV04_BOOT_0_RAM_AMOUNT_16MB:
+	case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
 		return 16 * 1024 * 1024;
 		return 16 * 1024 * 1024;
-	case NV04_BOOT_0_RAM_AMOUNT_8MB:
+	case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
 		return 8 * 1024 * 1024;
 		return 8 * 1024 * 1024;
-	case NV04_BOOT_0_RAM_AMOUNT_4MB:
+	case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
 		return 4 * 1024 * 1024;
 		return 4 * 1024 * 1024;
 	}
 	}
 
 
@@ -536,12 +316,18 @@ nouveau_mem_detect(struct drm_device *dev)
 	} else
 	} else
 	if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
 	if (dev_priv->flags & (NV_NFORCE | NV_NFORCE2)) {
 		dev_priv->vram_size = nouveau_mem_detect_nforce(dev);
 		dev_priv->vram_size = nouveau_mem_detect_nforce(dev);
+	} else
+	if (dev_priv->card_type < NV_50) {
+		dev_priv->vram_size  = nv_rd32(dev, NV04_PFB_FIFO_DATA);
+		dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
 	} else {
 	} else {
-		dev_priv->vram_size  = nv_rd32(dev, NV04_FIFO_DATA);
-		dev_priv->vram_size &= NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK;
-		if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac)
+		dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA);
+		dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
+		dev_priv->vram_size &= 0xffffffff00ll;
+		if (dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) {
 			dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
 			dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10);
 			dev_priv->vram_sys_base <<= 12;
 			dev_priv->vram_sys_base <<= 12;
+		}
 	}
 	}
 
 
 	NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
 	NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20));
@@ -555,18 +341,36 @@ nouveau_mem_detect(struct drm_device *dev)
 	return -ENOMEM;
 	return -ENOMEM;
 }
 }
 
 
-#if __OS_HAS_AGP
-static void nouveau_mem_reset_agp(struct drm_device *dev)
+int
+nouveau_mem_reset_agp(struct drm_device *dev)
 {
 {
-	uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable;
+#if __OS_HAS_AGP
+	uint32_t saved_pci_nv_1, pmc_enable;
+	int ret;
+
+	/* First of all, disable fast writes, otherwise if it's
+	 * already enabled in the AGP bridge and we disable the card's
+	 * AGP controller we might be locking ourselves out of it. */
+	if (dev->agp->acquired) {
+		struct drm_agp_info info;
+		struct drm_agp_mode mode;
+
+		ret = drm_agp_info(dev, &info);
+		if (ret)
+			return ret;
+
+		mode.mode = info.mode & ~0x10;
+		ret = drm_agp_enable(dev, mode);
+		if (ret)
+			return ret;
+	}
 
 
 	saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1);
 	saved_pci_nv_1 = nv_rd32(dev, NV04_PBUS_PCI_NV_1);
-	saved_pci_nv_19 = nv_rd32(dev, NV04_PBUS_PCI_NV_19);
 
 
 	/* clear busmaster bit */
 	/* clear busmaster bit */
 	nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4);
 	nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4);
-	/* clear SBA and AGP bits */
-	nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff);
+	/* disable AGP */
+	nv_wr32(dev, NV04_PBUS_PCI_NV_19, 0);
 
 
 	/* power cycle pgraph, if enabled */
 	/* power cycle pgraph, if enabled */
 	pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);
 	pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);
@@ -578,11 +382,12 @@ static void nouveau_mem_reset_agp(struct drm_device *dev)
 	}
 	}
 
 
 	/* and restore (gives effect of resetting AGP) */
 	/* and restore (gives effect of resetting AGP) */
-	nv_wr32(dev, NV04_PBUS_PCI_NV_19, saved_pci_nv_19);
 	nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
 	nv_wr32(dev, NV04_PBUS_PCI_NV_1, saved_pci_nv_1);
-}
 #endif
 #endif
 
 
+	return 0;
+}
+
 int
 int
 nouveau_mem_init_agp(struct drm_device *dev)
 nouveau_mem_init_agp(struct drm_device *dev)
 {
 {
@@ -592,11 +397,6 @@ nouveau_mem_init_agp(struct drm_device *dev)
 	struct drm_agp_mode mode;
 	struct drm_agp_mode mode;
 	int ret;
 	int ret;
 
 
-	if (nouveau_noagp)
-		return 0;
-
-	nouveau_mem_reset_agp(dev);
-
 	if (!dev->agp->acquired) {
 	if (!dev->agp->acquired) {
 		ret = drm_agp_acquire(dev);
 		ret = drm_agp_acquire(dev);
 		if (ret) {
 		if (ret) {
@@ -633,7 +433,7 @@ nouveau_mem_init(struct drm_device *dev)
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	int ret, dma_bits = 32;
 	int ret, dma_bits = 32;
 
 
-	dev_priv->fb_phys = drm_get_resource_start(dev, 1);
+	dev_priv->fb_phys = pci_resource_start(dev->pdev, 1);
 	dev_priv->gart_info.type = NOUVEAU_GART_NONE;
 	dev_priv->gart_info.type = NOUVEAU_GART_NONE;
 
 
 	if (dev_priv->card_type >= NV_50 &&
 	if (dev_priv->card_type >= NV_50 &&
@@ -665,8 +465,9 @@ nouveau_mem_init(struct drm_device *dev)
 
 
 	dev_priv->fb_available_size = dev_priv->vram_size;
 	dev_priv->fb_available_size = dev_priv->vram_size;
 	dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
 	dev_priv->fb_mappable_pages = dev_priv->fb_available_size;
-	if (dev_priv->fb_mappable_pages > drm_get_resource_len(dev, 1))
-		dev_priv->fb_mappable_pages = drm_get_resource_len(dev, 1);
+	if (dev_priv->fb_mappable_pages > pci_resource_len(dev->pdev, 1))
+		dev_priv->fb_mappable_pages =
+			pci_resource_len(dev->pdev, 1);
 	dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
 	dev_priv->fb_mappable_pages >>= PAGE_SHIFT;
 
 
 	/* remove reserved space at end of vram from available amount */
 	/* remove reserved space at end of vram from available amount */
@@ -692,7 +493,8 @@ nouveau_mem_init(struct drm_device *dev)
 
 
 	/* GART */
 	/* GART */
 #if !defined(__powerpc__) && !defined(__ia64__)
 #if !defined(__powerpc__) && !defined(__ia64__)
-	if (drm_device_is_agp(dev) && dev->agp) {
+	if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) {
+		nouveau_mem_reset_agp(dev);
 		ret = nouveau_mem_init_agp(dev);
 		ret = nouveau_mem_init_agp(dev);
 		if (ret)
 		if (ret)
 			NV_ERROR(dev, "Error initialising AGP: %d\n", ret);
 			NV_ERROR(dev, "Error initialising AGP: %d\n", ret);
@@ -718,8 +520,8 @@ nouveau_mem_init(struct drm_device *dev)
 		return ret;
 		return ret;
 	}
 	}
 
 
-	dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1),
-					 drm_get_resource_len(dev, 1),
+	dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1),
+					 pci_resource_len(dev->pdev, 1),
 					 DRM_MTRR_WC);
 					 DRM_MTRR_WC);
 
 
 	return 0;
 	return 0;

+ 12 - 18
drivers/gpu/drm/nouveau/nouveau_notifier.c

@@ -55,7 +55,7 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
 	if (ret)
 	if (ret)
 		goto out_err;
 		goto out_err;
 
 
-	ret = nouveau_mem_init_heap(&chan->notifier_heap, 0, ntfy->bo.mem.size);
+	ret = drm_mm_init(&chan->notifier_heap, 0, ntfy->bo.mem.size);
 	if (ret)
 	if (ret)
 		goto out_err;
 		goto out_err;
 
 
@@ -80,7 +80,7 @@ nouveau_notifier_takedown_channel(struct nouveau_channel *chan)
 	nouveau_bo_unpin(chan->notifier_bo);
 	nouveau_bo_unpin(chan->notifier_bo);
 	mutex_unlock(&dev->struct_mutex);
 	mutex_unlock(&dev->struct_mutex);
 	drm_gem_object_unreference_unlocked(chan->notifier_bo->gem);
 	drm_gem_object_unreference_unlocked(chan->notifier_bo->gem);
-	nouveau_mem_takedown(&chan->notifier_heap);
+	drm_mm_takedown(&chan->notifier_heap);
 }
 }
 
 
 static void
 static void
@@ -90,7 +90,7 @@ nouveau_notifier_gpuobj_dtor(struct drm_device *dev,
 	NV_DEBUG(dev, "\n");
 	NV_DEBUG(dev, "\n");
 
 
 	if (gpuobj->priv)
 	if (gpuobj->priv)
-		nouveau_mem_free_block(gpuobj->priv);
+		drm_mm_put_block(gpuobj->priv);
 }
 }
 
 
 int
 int
@@ -100,18 +100,13 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
 	struct drm_device *dev = chan->dev;
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *nobj = NULL;
 	struct nouveau_gpuobj *nobj = NULL;
-	struct mem_block *mem;
+	struct drm_mm_node *mem;
 	uint32_t offset;
 	uint32_t offset;
 	int target, ret;
 	int target, ret;
 
 
-	if (!chan->notifier_heap) {
-		NV_ERROR(dev, "Channel %d doesn't have a notifier heap!\n",
-			 chan->id);
-		return -EINVAL;
-	}
-
-	mem = nouveau_mem_alloc_block(chan->notifier_heap, size, 0,
-				      (struct drm_file *)-2, 0);
+	mem = drm_mm_search_free(&chan->notifier_heap, size, 0, 0);
+	if (mem)
+		mem = drm_mm_get_block(mem, size, 0);
 	if (!mem) {
 	if (!mem) {
 		NV_ERROR(dev, "Channel %d notifier block full\n", chan->id);
 		NV_ERROR(dev, "Channel %d notifier block full\n", chan->id);
 		return -ENOMEM;
 		return -ENOMEM;
@@ -144,17 +139,17 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
 				     mem->size, NV_DMA_ACCESS_RW, target,
 				     mem->size, NV_DMA_ACCESS_RW, target,
 				     &nobj);
 				     &nobj);
 	if (ret) {
 	if (ret) {
-		nouveau_mem_free_block(mem);
+		drm_mm_put_block(mem);
 		NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret);
 		NV_ERROR(dev, "Error creating notifier ctxdma: %d\n", ret);
 		return ret;
 		return ret;
 	}
 	}
-	nobj->dtor   = nouveau_notifier_gpuobj_dtor;
-	nobj->priv   = mem;
+	nobj->dtor = nouveau_notifier_gpuobj_dtor;
+	nobj->priv = mem;
 
 
 	ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL);
 	ret = nouveau_gpuobj_ref_add(dev, chan, handle, nobj, NULL);
 	if (ret) {
 	if (ret) {
 		nouveau_gpuobj_del(dev, &nobj);
 		nouveau_gpuobj_del(dev, &nobj);
-		nouveau_mem_free_block(mem);
+		drm_mm_put_block(mem);
 		NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret);
 		NV_ERROR(dev, "Error referencing notifier ctxdma: %d\n", ret);
 		return ret;
 		return ret;
 	}
 	}
@@ -170,7 +165,7 @@ nouveau_notifier_offset(struct nouveau_gpuobj *nobj, uint32_t *poffset)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (poffset) {
 	if (poffset) {
-		struct mem_block *mem = nobj->priv;
+		struct drm_mm_node *mem = nobj->priv;
 
 
 		if (*poffset >= mem->size)
 		if (*poffset >= mem->size)
 			return false;
 			return false;
@@ -189,7 +184,6 @@ nouveau_ioctl_notifier_alloc(struct drm_device *dev, void *data,
 	struct nouveau_channel *chan;
 	struct nouveau_channel *chan;
 	int ret;
 	int ret;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan);
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(na->channel, file_priv, chan);
 
 
 	ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset);
 	ret = nouveau_notifier_alloc(chan, na->handle, na->size, &na->offset);

+ 31 - 74
drivers/gpu/drm/nouveau/nouveau_object.c

@@ -132,7 +132,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
 		}
 		}
 	}
 	}
 
 
-	instmem->prepare_access(dev, true);
 	co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
 	co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
 	do {
 	do {
 		if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
 		if (!nouveau_ramht_entry_valid(dev, ramht, co)) {
@@ -143,7 +142,7 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
 			nv_wo32(dev, ramht, (co + 4)/4, ctx);
 			nv_wo32(dev, ramht, (co + 4)/4, ctx);
 
 
 			list_add_tail(&ref->list, &chan->ramht_refs);
 			list_add_tail(&ref->list, &chan->ramht_refs);
-			instmem->finish_access(dev);
+			instmem->flush(dev);
 			return 0;
 			return 0;
 		}
 		}
 		NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n",
 		NV_DEBUG(dev, "collision ch%d 0x%08x: h=0x%08x\n",
@@ -153,7 +152,6 @@ nouveau_ramht_insert(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
 		if (co >= dev_priv->ramht_size)
 		if (co >= dev_priv->ramht_size)
 			co = 0;
 			co = 0;
 	} while (co != ho);
 	} while (co != ho);
-	instmem->finish_access(dev);
 
 
 	NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id);
 	NV_ERROR(dev, "RAMHT space exhausted. ch=%d\n", chan->id);
 	return -ENOMEM;
 	return -ENOMEM;
@@ -173,7 +171,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
 		return;
 		return;
 	}
 	}
 
 
-	instmem->prepare_access(dev, true);
 	co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
 	co = ho = nouveau_ramht_hash_handle(dev, chan->id, ref->handle);
 	do {
 	do {
 		if (nouveau_ramht_entry_valid(dev, ramht, co) &&
 		if (nouveau_ramht_entry_valid(dev, ramht, co) &&
@@ -186,7 +183,7 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
 			nv_wo32(dev, ramht, (co + 4)/4, 0x00000000);
 			nv_wo32(dev, ramht, (co + 4)/4, 0x00000000);
 
 
 			list_del(&ref->list);
 			list_del(&ref->list);
-			instmem->finish_access(dev);
+			instmem->flush(dev);
 			return;
 			return;
 		}
 		}
 
 
@@ -195,7 +192,6 @@ nouveau_ramht_remove(struct drm_device *dev, struct nouveau_gpuobj_ref *ref)
 			co = 0;
 			co = 0;
 	} while (co != ho);
 	} while (co != ho);
 	list_del(&ref->list);
 	list_del(&ref->list);
-	instmem->finish_access(dev);
 
 
 	NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",
 	NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n",
 		 chan->id, ref->handle);
 		 chan->id, ref->handle);
@@ -209,7 +205,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_engine *engine = &dev_priv->engine;
 	struct nouveau_engine *engine = &dev_priv->engine;
 	struct nouveau_gpuobj *gpuobj;
 	struct nouveau_gpuobj *gpuobj;
-	struct mem_block *pramin = NULL;
+	struct drm_mm *pramin = NULL;
 	int ret;
 	int ret;
 
 
 	NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n",
 	NV_DEBUG(dev, "ch%d size=%u align=%d flags=0x%08x\n",
@@ -233,25 +229,12 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
 	 * available.
 	 * available.
 	 */
 	 */
 	if (chan) {
 	if (chan) {
-		if (chan->ramin_heap) {
-			NV_DEBUG(dev, "private heap\n");
-			pramin = chan->ramin_heap;
-		} else
-		if (dev_priv->card_type < NV_50) {
-			NV_DEBUG(dev, "global heap fallback\n");
-			pramin = dev_priv->ramin_heap;
-		}
+		NV_DEBUG(dev, "channel heap\n");
+		pramin = &chan->ramin_heap;
 	} else {
 	} else {
 		NV_DEBUG(dev, "global heap\n");
 		NV_DEBUG(dev, "global heap\n");
-		pramin = dev_priv->ramin_heap;
-	}
-
-	if (!pramin) {
-		NV_ERROR(dev, "No PRAMIN heap!\n");
-		return -EINVAL;
-	}
+		pramin = &dev_priv->ramin_heap;
 
 
-	if (!chan) {
 		ret = engine->instmem.populate(dev, gpuobj, &size);
 		ret = engine->instmem.populate(dev, gpuobj, &size);
 		if (ret) {
 		if (ret) {
 			nouveau_gpuobj_del(dev, &gpuobj);
 			nouveau_gpuobj_del(dev, &gpuobj);
@@ -260,9 +243,10 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
 	}
 	}
 
 
 	/* Allocate a chunk of the PRAMIN aperture */
 	/* Allocate a chunk of the PRAMIN aperture */
-	gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size,
-						    drm_order(align),
-						    (struct drm_file *)-2, 0);
+	gpuobj->im_pramin = drm_mm_search_free(pramin, size, align, 0);
+	if (gpuobj->im_pramin)
+		gpuobj->im_pramin = drm_mm_get_block(gpuobj->im_pramin, size, align);
+
 	if (!gpuobj->im_pramin) {
 	if (!gpuobj->im_pramin) {
 		nouveau_gpuobj_del(dev, &gpuobj);
 		nouveau_gpuobj_del(dev, &gpuobj);
 		return -ENOMEM;
 		return -ENOMEM;
@@ -279,10 +263,9 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan,
 	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
 	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
 		int i;
 		int i;
 
 
-		engine->instmem.prepare_access(dev, true);
 		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
 		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
 			nv_wo32(dev, gpuobj, i/4, 0);
 			nv_wo32(dev, gpuobj, i/4, 0);
-		engine->instmem.finish_access(dev);
+		engine->instmem.flush(dev);
 	}
 	}
 
 
 	*gpuobj_ret = gpuobj;
 	*gpuobj_ret = gpuobj;
@@ -370,10 +353,9 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
 	}
 	}
 
 
 	if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) {
 	if (gpuobj->im_pramin && (gpuobj->flags & NVOBJ_FLAG_ZERO_FREE)) {
-		engine->instmem.prepare_access(dev, true);
 		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
 		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
 			nv_wo32(dev, gpuobj, i/4, 0);
 			nv_wo32(dev, gpuobj, i/4, 0);
-		engine->instmem.finish_access(dev);
+		engine->instmem.flush(dev);
 	}
 	}
 
 
 	if (gpuobj->dtor)
 	if (gpuobj->dtor)
@@ -386,7 +368,7 @@ nouveau_gpuobj_del(struct drm_device *dev, struct nouveau_gpuobj **pgpuobj)
 		if (gpuobj->flags & NVOBJ_FLAG_FAKE)
 		if (gpuobj->flags & NVOBJ_FLAG_FAKE)
 			kfree(gpuobj->im_pramin);
 			kfree(gpuobj->im_pramin);
 		else
 		else
-			nouveau_mem_free_block(gpuobj->im_pramin);
+			drm_mm_put_block(gpuobj->im_pramin);
 	}
 	}
 
 
 	list_del(&gpuobj->list);
 	list_del(&gpuobj->list);
@@ -589,7 +571,7 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
 	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
 	list_add_tail(&gpuobj->list, &dev_priv->gpuobj_list);
 
 
 	if (p_offset != ~0) {
 	if (p_offset != ~0) {
-		gpuobj->im_pramin = kzalloc(sizeof(struct mem_block),
+		gpuobj->im_pramin = kzalloc(sizeof(struct drm_mm_node),
 					    GFP_KERNEL);
 					    GFP_KERNEL);
 		if (!gpuobj->im_pramin) {
 		if (!gpuobj->im_pramin) {
 			nouveau_gpuobj_del(dev, &gpuobj);
 			nouveau_gpuobj_del(dev, &gpuobj);
@@ -605,10 +587,9 @@ nouveau_gpuobj_new_fake(struct drm_device *dev, uint32_t p_offset,
 	}
 	}
 
 
 	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
 	if (gpuobj->flags & NVOBJ_FLAG_ZERO_ALLOC) {
-		dev_priv->engine.instmem.prepare_access(dev, true);
 		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
 		for (i = 0; i < gpuobj->im_pramin->size; i += 4)
 			nv_wo32(dev, gpuobj, i/4, 0);
 			nv_wo32(dev, gpuobj, i/4, 0);
-		dev_priv->engine.instmem.finish_access(dev);
+		dev_priv->engine.instmem.flush(dev);
 	}
 	}
 
 
 	if (pref) {
 	if (pref) {
@@ -696,8 +677,6 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
 		return ret;
 		return ret;
 	}
 	}
 
 
-	instmem->prepare_access(dev, true);
-
 	if (dev_priv->card_type < NV_50) {
 	if (dev_priv->card_type < NV_50) {
 		uint32_t frame, adjust, pte_flags = 0;
 		uint32_t frame, adjust, pte_flags = 0;
 
 
@@ -734,7 +713,7 @@ nouveau_gpuobj_dma_new(struct nouveau_channel *chan, int class,
 		nv_wo32(dev, *gpuobj, 5, flags5);
 		nv_wo32(dev, *gpuobj, 5, flags5);
 	}
 	}
 
 
-	instmem->finish_access(dev);
+	instmem->flush(dev);
 
 
 	(*gpuobj)->engine = NVOBJ_ENGINE_SW;
 	(*gpuobj)->engine = NVOBJ_ENGINE_SW;
 	(*gpuobj)->class  = class;
 	(*gpuobj)->class  = class;
@@ -849,7 +828,6 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
 		return ret;
 		return ret;
 	}
 	}
 
 
-	dev_priv->engine.instmem.prepare_access(dev, true);
 	if (dev_priv->card_type >= NV_50) {
 	if (dev_priv->card_type >= NV_50) {
 		nv_wo32(dev, *gpuobj, 0, class);
 		nv_wo32(dev, *gpuobj, 0, class);
 		nv_wo32(dev, *gpuobj, 5, 0x00010000);
 		nv_wo32(dev, *gpuobj, 5, 0x00010000);
@@ -874,7 +852,7 @@ nouveau_gpuobj_gr_new(struct nouveau_channel *chan, int class,
 			}
 			}
 		}
 		}
 	}
 	}
-	dev_priv->engine.instmem.finish_access(dev);
+	dev_priv->engine.instmem.flush(dev);
 
 
 	(*gpuobj)->engine = NVOBJ_ENGINE_GR;
 	(*gpuobj)->engine = NVOBJ_ENGINE_GR;
 	(*gpuobj)->class  = class;
 	(*gpuobj)->class  = class;
@@ -920,6 +898,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
 	base = 0;
 	base = 0;
 
 
 	/* PGRAPH context */
 	/* PGRAPH context */
+	size += dev_priv->engine.graph.grctx_size;
 
 
 	if (dev_priv->card_type == NV_50) {
 	if (dev_priv->card_type == NV_50) {
 		/* Various fixed table thingos */
 		/* Various fixed table thingos */
@@ -930,12 +909,8 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
 		size += 0x8000;
 		size += 0x8000;
 		/* RAMFC */
 		/* RAMFC */
 		size += 0x1000;
 		size += 0x1000;
-		/* PGRAPH context */
-		size += 0x70000;
 	}
 	}
 
 
-	NV_DEBUG(dev, "ch%d PRAMIN size: 0x%08x bytes, base alloc=0x%08x\n",
-		 chan->id, size, base);
 	ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0,
 	ret = nouveau_gpuobj_new_ref(dev, NULL, NULL, 0, size, 0x1000, 0,
 				     &chan->ramin);
 				     &chan->ramin);
 	if (ret) {
 	if (ret) {
@@ -944,8 +919,7 @@ nouveau_gpuobj_channel_init_pramin(struct nouveau_channel *chan)
 	}
 	}
 	pramin = chan->ramin->gpuobj;
 	pramin = chan->ramin->gpuobj;
 
 
-	ret = nouveau_mem_init_heap(&chan->ramin_heap,
-				    pramin->im_pramin->start + base, size);
+	ret = drm_mm_init(&chan->ramin_heap, pramin->im_pramin->start + base, size);
 	if (ret) {
 	if (ret) {
 		NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);
 		NV_ERROR(dev, "Error creating PRAMIN heap: %d\n", ret);
 		nouveau_gpuobj_ref_del(dev, &chan->ramin);
 		nouveau_gpuobj_ref_del(dev, &chan->ramin);
@@ -969,15 +943,11 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 
 
 	NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
 	NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
 
 
-	/* Reserve a block of PRAMIN for the channel
-	 *XXX: maybe on <NV50 too at some point
-	 */
-	if (0 || dev_priv->card_type == NV_50) {
-		ret = nouveau_gpuobj_channel_init_pramin(chan);
-		if (ret) {
-			NV_ERROR(dev, "init pramin\n");
-			return ret;
-		}
+	/* Allocate a chunk of memory for per-channel object storage */
+	ret = nouveau_gpuobj_channel_init_pramin(chan);
+	if (ret) {
+		NV_ERROR(dev, "init pramin\n");
+		return ret;
 	}
 	}
 
 
 	/* NV50 VM
 	/* NV50 VM
@@ -988,17 +958,13 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 	if (dev_priv->card_type >= NV_50) {
 	if (dev_priv->card_type >= NV_50) {
 		uint32_t vm_offset, pde;
 		uint32_t vm_offset, pde;
 
 
-		instmem->prepare_access(dev, true);
-
 		vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200;
 		vm_offset = (dev_priv->chipset & 0xf0) == 0x50 ? 0x1400 : 0x200;
 		vm_offset += chan->ramin->gpuobj->im_pramin->start;
 		vm_offset += chan->ramin->gpuobj->im_pramin->start;
 
 
 		ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000,
 		ret = nouveau_gpuobj_new_fake(dev, vm_offset, ~0, 0x4000,
 							0, &chan->vm_pd, NULL);
 							0, &chan->vm_pd, NULL);
-		if (ret) {
-			instmem->finish_access(dev);
+		if (ret)
 			return ret;
 			return ret;
-		}
 		for (i = 0; i < 0x4000; i += 8) {
 		for (i = 0; i < 0x4000; i += 8) {
 			nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000);
 			nv_wo32(dev, chan->vm_pd, (i+0)/4, 0x00000000);
 			nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe);
 			nv_wo32(dev, chan->vm_pd, (i+4)/4, 0xdeadcafe);
@@ -1008,10 +974,8 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 		ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
 		ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
 					     dev_priv->gart_info.sg_ctxdma,
 					     dev_priv->gart_info.sg_ctxdma,
 					     &chan->vm_gart_pt);
 					     &chan->vm_gart_pt);
-		if (ret) {
-			instmem->finish_access(dev);
+		if (ret)
 			return ret;
 			return ret;
-		}
 		nv_wo32(dev, chan->vm_pd, pde++,
 		nv_wo32(dev, chan->vm_pd, pde++,
 			    chan->vm_gart_pt->instance | 0x03);
 			    chan->vm_gart_pt->instance | 0x03);
 		nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
 		nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
@@ -1021,17 +985,15 @@ nouveau_gpuobj_channel_init(struct nouveau_channel *chan,
 			ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
 			ret = nouveau_gpuobj_ref_add(dev, NULL, 0,
 						     dev_priv->vm_vram_pt[i],
 						     dev_priv->vm_vram_pt[i],
 						     &chan->vm_vram_pt[i]);
 						     &chan->vm_vram_pt[i]);
-			if (ret) {
-				instmem->finish_access(dev);
+			if (ret)
 				return ret;
 				return ret;
-			}
 
 
 			nv_wo32(dev, chan->vm_pd, pde++,
 			nv_wo32(dev, chan->vm_pd, pde++,
 				    chan->vm_vram_pt[i]->instance | 0x61);
 				    chan->vm_vram_pt[i]->instance | 0x61);
 			nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
 			nv_wo32(dev, chan->vm_pd, pde++, 0x00000000);
 		}
 		}
 
 
-		instmem->finish_access(dev);
+		instmem->flush(dev);
 	}
 	}
 
 
 	/* RAMHT */
 	/* RAMHT */
@@ -1130,8 +1092,8 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan)
 	for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)
 	for (i = 0; i < dev_priv->vm_vram_pt_nr; i++)
 		nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]);
 		nouveau_gpuobj_ref_del(dev, &chan->vm_vram_pt[i]);
 
 
-	if (chan->ramin_heap)
-		nouveau_mem_takedown(&chan->ramin_heap);
+	if (chan->ramin_heap.free_stack.next)
+		drm_mm_takedown(&chan->ramin_heap);
 	if (chan->ramin)
 	if (chan->ramin)
 		nouveau_gpuobj_ref_del(dev, &chan->ramin);
 		nouveau_gpuobj_ref_del(dev, &chan->ramin);
 
 
@@ -1164,10 +1126,8 @@ nouveau_gpuobj_suspend(struct drm_device *dev)
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
 
 
-		dev_priv->engine.instmem.prepare_access(dev, false);
 		for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
 		for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
 			gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i);
 			gpuobj->im_backing_suspend[i] = nv_ro32(dev, gpuobj, i);
-		dev_priv->engine.instmem.finish_access(dev);
 	}
 	}
 
 
 	return 0;
 	return 0;
@@ -1212,10 +1172,9 @@ nouveau_gpuobj_resume(struct drm_device *dev)
 		if (!gpuobj->im_backing_suspend)
 		if (!gpuobj->im_backing_suspend)
 			continue;
 			continue;
 
 
-		dev_priv->engine.instmem.prepare_access(dev, true);
 		for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
 		for (i = 0; i < gpuobj->im_pramin->size / 4; i++)
 			nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]);
 			nv_wo32(dev, gpuobj, i, gpuobj->im_backing_suspend[i]);
-		dev_priv->engine.instmem.finish_access(dev);
+		dev_priv->engine.instmem.flush(dev);
 	}
 	}
 
 
 	nouveau_gpuobj_suspend_cleanup(dev);
 	nouveau_gpuobj_suspend_cleanup(dev);
@@ -1232,7 +1191,6 @@ int nouveau_ioctl_grobj_alloc(struct drm_device *dev, void *data,
 	struct nouveau_channel *chan;
 	struct nouveau_channel *chan;
 	int ret;
 	int ret;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(init->channel, file_priv, chan);
 
 
 	if (init->handle == ~0)
 	if (init->handle == ~0)
@@ -1283,7 +1241,6 @@ int nouveau_ioctl_gpuobj_free(struct drm_device *dev, void *data,
 	struct nouveau_channel *chan;
 	struct nouveau_channel *chan;
 	int ret;
 	int ret;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);
 	NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(objfree->channel, file_priv, chan);
 
 
 	ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref);
 	ret = nouveau_gpuobj_ref_find(chan, objfree->handle, &ref);

+ 60 - 31
drivers/gpu/drm/nouveau/nouveau_reg.h

@@ -1,19 +1,64 @@
 
 
+#define NV04_PFB_BOOT_0						0x00100000
+#	define NV04_PFB_BOOT_0_RAM_AMOUNT			0x00000003
+#	define NV04_PFB_BOOT_0_RAM_AMOUNT_32MB			0x00000000
+#	define NV04_PFB_BOOT_0_RAM_AMOUNT_4MB			0x00000001
+#	define NV04_PFB_BOOT_0_RAM_AMOUNT_8MB			0x00000002
+#	define NV04_PFB_BOOT_0_RAM_AMOUNT_16MB			0x00000003
+#	define NV04_PFB_BOOT_0_RAM_WIDTH_128			0x00000004
+#	define NV04_PFB_BOOT_0_RAM_TYPE				0x00000028
+#	define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_8MBIT		0x00000000
+#	define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT		0x00000008
+#	define NV04_PFB_BOOT_0_RAM_TYPE_SGRAM_16MBIT_4BANK	0x00000010
+#	define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_16MBIT		0x00000018
+#	define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBIT		0x00000020
+#	define NV04_PFB_BOOT_0_RAM_TYPE_SDRAM_64MBITX16		0x00000028
+#	define NV04_PFB_BOOT_0_UMA_ENABLE			0x00000100
+#	define NV04_PFB_BOOT_0_UMA_SIZE				0x0000f000
+#define NV04_PFB_DEBUG_0					0x00100080
+#	define NV04_PFB_DEBUG_0_PAGE_MODE			0x00000001
+#	define NV04_PFB_DEBUG_0_REFRESH_OFF			0x00000010
+#	define NV04_PFB_DEBUG_0_REFRESH_COUNTX64		0x00003f00
+#	define NV04_PFB_DEBUG_0_REFRESH_SLOW_CLK		0x00004000
+#	define NV04_PFB_DEBUG_0_SAFE_MODE			0x00008000
+#	define NV04_PFB_DEBUG_0_ALOM_ENABLE			0x00010000
+#	define NV04_PFB_DEBUG_0_CASOE				0x00100000
+#	define NV04_PFB_DEBUG_0_CKE_INVERT			0x10000000
+#	define NV04_PFB_DEBUG_0_REFINC				0x20000000
+#	define NV04_PFB_DEBUG_0_SAVE_POWER_OFF			0x40000000
+#define NV04_PFB_CFG0						0x00100200
+#	define NV04_PFB_CFG0_SCRAMBLE				0x20000000
+#define NV04_PFB_CFG1						0x00100204
+#define NV04_PFB_FIFO_DATA					0x0010020c
+#	define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK		0xfff00000
+#	define NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_SHIFT		20
+#define NV10_PFB_REFCTRL					0x00100210
+#	define NV10_PFB_REFCTRL_VALID_1				(1 << 31)
+#define NV04_PFB_PAD						0x0010021c
+#	define NV04_PFB_PAD_CKE_NORMAL				(1 << 0)
+#define NV10_PFB_TILE(i)                              (0x00100240 + (i*16))
+#define NV10_PFB_TILE__SIZE					8
+#define NV10_PFB_TLIMIT(i)                            (0x00100244 + (i*16))
+#define NV10_PFB_TSIZE(i)                             (0x00100248 + (i*16))
+#define NV10_PFB_TSTATUS(i)                           (0x0010024c + (i*16))
+#define NV04_PFB_REF						0x001002d0
+#	define NV04_PFB_REF_CMD_REFRESH				(1 << 0)
+#define NV04_PFB_PRE						0x001002d4
+#	define NV04_PFB_PRE_CMD_PRECHARGE			(1 << 0)
+#define NV10_PFB_CLOSE_PAGE2					0x0010033c
+#define NV04_PFB_SCRAMBLE(i)                         (0x00100400 + 4 * (i))
+#define NV40_PFB_TILE(i)                              (0x00100600 + (i*16))
+#define NV40_PFB_TILE__SIZE_0					12
+#define NV40_PFB_TILE__SIZE_1					15
+#define NV40_PFB_TLIMIT(i)                            (0x00100604 + (i*16))
+#define NV40_PFB_TSIZE(i)                             (0x00100608 + (i*16))
+#define NV40_PFB_TSTATUS(i)                           (0x0010060c + (i*16))
+#define NV40_PFB_UNK_800					0x00100800
 
 
-#define NV03_BOOT_0                                        0x00100000
-#    define NV03_BOOT_0_RAM_AMOUNT                         0x00000003
-#    define NV03_BOOT_0_RAM_AMOUNT_8MB                     0x00000000
-#    define NV03_BOOT_0_RAM_AMOUNT_2MB                     0x00000001
-#    define NV03_BOOT_0_RAM_AMOUNT_4MB                     0x00000002
-#    define NV03_BOOT_0_RAM_AMOUNT_8MB_SDRAM               0x00000003
-#    define NV04_BOOT_0_RAM_AMOUNT_32MB                    0x00000000
-#    define NV04_BOOT_0_RAM_AMOUNT_4MB                     0x00000001
-#    define NV04_BOOT_0_RAM_AMOUNT_8MB                     0x00000002
-#    define NV04_BOOT_0_RAM_AMOUNT_16MB                    0x00000003
-
-#define NV04_FIFO_DATA                                     0x0010020c
-#    define NV10_FIFO_DATA_RAM_AMOUNT_MB_MASK              0xfff00000
-#    define NV10_FIFO_DATA_RAM_AMOUNT_MB_SHIFT             20
+#define NV_PEXTDEV_BOOT_0					0x00101000
+#define NV_PEXTDEV_BOOT_0_RAMCFG				0x0000003c
+#	define NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT		(8 << 12)
+#define NV_PEXTDEV_BOOT_3					0x0010100c
 
 
 #define NV_RAMIN                                           0x00700000
 #define NV_RAMIN                                           0x00700000
 
 
@@ -131,23 +176,6 @@
 #define NV04_PTIMER_TIME_1                                 0x00009410
 #define NV04_PTIMER_TIME_1                                 0x00009410
 #define NV04_PTIMER_ALARM_0                                0x00009420
 #define NV04_PTIMER_ALARM_0                                0x00009420
 
 
-#define NV04_PFB_CFG0                                      0x00100200
-#define NV04_PFB_CFG1                                      0x00100204
-#define NV40_PFB_020C                                      0x0010020C
-#define NV10_PFB_TILE(i)                                   (0x00100240 + (i*16))
-#define NV10_PFB_TILE__SIZE                                8
-#define NV10_PFB_TLIMIT(i)                                 (0x00100244 + (i*16))
-#define NV10_PFB_TSIZE(i)                                  (0x00100248 + (i*16))
-#define NV10_PFB_TSTATUS(i)                                (0x0010024C + (i*16))
-#define NV10_PFB_CLOSE_PAGE2                               0x0010033C
-#define NV40_PFB_TILE(i)                                   (0x00100600 + (i*16))
-#define NV40_PFB_TILE__SIZE_0                              12
-#define NV40_PFB_TILE__SIZE_1                              15
-#define NV40_PFB_TLIMIT(i)                                 (0x00100604 + (i*16))
-#define NV40_PFB_TSIZE(i)                                  (0x00100608 + (i*16))
-#define NV40_PFB_TSTATUS(i)                                (0x0010060C + (i*16))
-#define NV40_PFB_UNK_800					0x00100800
-
 #define NV04_PGRAPH_DEBUG_0                                0x00400080
 #define NV04_PGRAPH_DEBUG_0                                0x00400080
 #define NV04_PGRAPH_DEBUG_1                                0x00400084
 #define NV04_PGRAPH_DEBUG_1                                0x00400084
 #define NV04_PGRAPH_DEBUG_2                                0x00400088
 #define NV04_PGRAPH_DEBUG_2                                0x00400088
@@ -814,6 +842,7 @@
 #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE                           0x80000000
 #define NV50_PDISPLAY_SOR_BACKLIGHT_ENABLE                           0x80000000
 #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL                            0x00000fff
 #define NV50_PDISPLAY_SOR_BACKLIGHT_LEVEL                            0x00000fff
 #define NV50_SOR_DP_CTRL(i,l)            (0x0061c10c + (i) * 0x800 + (l) * 0x80)
 #define NV50_SOR_DP_CTRL(i,l)            (0x0061c10c + (i) * 0x800 + (l) * 0x80)
+#define NV50_SOR_DP_CTRL_ENABLED                                     0x00000001
 #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED                      0x00004000
 #define NV50_SOR_DP_CTRL_ENHANCED_FRAME_ENABLED                      0x00004000
 #define NV50_SOR_DP_CTRL_LANE_MASK                                   0x001f0000
 #define NV50_SOR_DP_CTRL_LANE_MASK                                   0x001f0000
 #define NV50_SOR_DP_CTRL_LANE_0_ENABLED                              0x00010000
 #define NV50_SOR_DP_CTRL_LANE_0_ENABLED                              0x00010000

+ 7 - 39
drivers/gpu/drm/nouveau/nouveau_sgdma.c

@@ -97,7 +97,6 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 
 
 	NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start);
 	NV_DEBUG(dev, "pg=0x%lx\n", mem->mm_node->start);
 
 
-	dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
 	pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT);
 	pte = nouveau_sgdma_pte(nvbe->dev, mem->mm_node->start << PAGE_SHIFT);
 	nvbe->pte_start = pte;
 	nvbe->pte_start = pte;
 	for (i = 0; i < nvbe->nr_pages; i++) {
 	for (i = 0; i < nvbe->nr_pages; i++) {
@@ -116,24 +115,11 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 			dma_offset += NV_CTXDMA_PAGE_SIZE;
 			dma_offset += NV_CTXDMA_PAGE_SIZE;
 		}
 		}
 	}
 	}
-	dev_priv->engine.instmem.finish_access(nvbe->dev);
+	dev_priv->engine.instmem.flush(nvbe->dev);
 
 
 	if (dev_priv->card_type == NV_50) {
 	if (dev_priv->card_type == NV_50) {
-		nv_wr32(dev, 0x100c80, 0x00050001);
-		if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-			NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-			NV_ERROR(dev, "0x100c80 = 0x%08x\n",
-						nv_rd32(dev, 0x100c80));
-			return -EBUSY;
-		}
-
-		nv_wr32(dev, 0x100c80, 0x00000001);
-		if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-			NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-			NV_ERROR(dev, "0x100c80 = 0x%08x\n",
-						nv_rd32(dev, 0x100c80));
-			return -EBUSY;
-		}
+		nv50_vm_flush(dev, 5); /* PGRAPH */
+		nv50_vm_flush(dev, 0); /* PFIFO */
 	}
 	}
 
 
 	nvbe->bound = true;
 	nvbe->bound = true;
@@ -154,7 +140,6 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
 	if (!nvbe->bound)
 	if (!nvbe->bound)
 		return 0;
 		return 0;
 
 
-	dev_priv->engine.instmem.prepare_access(nvbe->dev, true);
 	pte = nvbe->pte_start;
 	pte = nvbe->pte_start;
 	for (i = 0; i < nvbe->nr_pages; i++) {
 	for (i = 0; i < nvbe->nr_pages; i++) {
 		dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus;
 		dma_addr_t dma_offset = dev_priv->gart_info.sg_dummy_bus;
@@ -170,24 +155,11 @@ nouveau_sgdma_unbind(struct ttm_backend *be)
 			dma_offset += NV_CTXDMA_PAGE_SIZE;
 			dma_offset += NV_CTXDMA_PAGE_SIZE;
 		}
 		}
 	}
 	}
-	dev_priv->engine.instmem.finish_access(nvbe->dev);
+	dev_priv->engine.instmem.flush(nvbe->dev);
 
 
 	if (dev_priv->card_type == NV_50) {
 	if (dev_priv->card_type == NV_50) {
-		nv_wr32(dev, 0x100c80, 0x00050001);
-		if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-			NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-			NV_ERROR(dev, "0x100c80 = 0x%08x\n",
-						nv_rd32(dev, 0x100c80));
-			return -EBUSY;
-		}
-
-		nv_wr32(dev, 0x100c80, 0x00000001);
-		if (!nv_wait(0x100c80, 0x00000001, 0x00000000)) {
-			NV_ERROR(dev, "timeout: (0x100c80 & 1) == 0 (2)\n");
-			NV_ERROR(dev, "0x100c80 = 0x%08x\n",
-						nv_rd32(dev, 0x100c80));
-			return -EBUSY;
-		}
+		nv50_vm_flush(dev, 5);
+		nv50_vm_flush(dev, 0);
 	}
 	}
 
 
 	nvbe->bound = false;
 	nvbe->bound = false;
@@ -272,7 +244,6 @@ nouveau_sgdma_init(struct drm_device *dev)
 		pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
 		pci_map_page(dev->pdev, dev_priv->gart_info.sg_dummy_page, 0,
 			     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 			     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 
 
-	dev_priv->engine.instmem.prepare_access(dev, true);
 	if (dev_priv->card_type < NV_50) {
 	if (dev_priv->card_type < NV_50) {
 		/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
 		/* Maybe use NV_DMA_TARGET_AGP for PCIE? NVIDIA do this, and
 		 * confirmed to work on c51.  Perhaps means NV_DMA_TARGET_PCIE
 		 * confirmed to work on c51.  Perhaps means NV_DMA_TARGET_PCIE
@@ -294,7 +265,7 @@ nouveau_sgdma_init(struct drm_device *dev)
 			nv_wo32(dev, gpuobj, (i+4)/4, 0);
 			nv_wo32(dev, gpuobj, (i+4)/4, 0);
 		}
 		}
 	}
 	}
-	dev_priv->engine.instmem.finish_access(dev);
+	dev_priv->engine.instmem.flush(dev);
 
 
 	dev_priv->gart_info.type      = NOUVEAU_GART_SGDMA;
 	dev_priv->gart_info.type      = NOUVEAU_GART_SGDMA;
 	dev_priv->gart_info.aper_base = 0;
 	dev_priv->gart_info.aper_base = 0;
@@ -325,14 +296,11 @@ nouveau_sgdma_get_page(struct drm_device *dev, uint32_t offset, uint32_t *page)
 {
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
 	struct nouveau_gpuobj *gpuobj = dev_priv->gart_info.sg_ctxdma;
-	struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem;
 	int pte;
 	int pte;
 
 
 	pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
 	pte = (offset >> NV_CTXDMA_PAGE_SHIFT);
 	if (dev_priv->card_type < NV_50) {
 	if (dev_priv->card_type < NV_50) {
-		instmem->prepare_access(dev, false);
 		*page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
 		*page = nv_ro32(dev, gpuobj, (pte + 2)) & ~NV_CTXDMA_PAGE_MASK;
-		instmem->finish_access(dev);
 		return 0;
 		return 0;
 	}
 	}
 
 

+ 137 - 118
drivers/gpu/drm/nouveau/nouveau_state.c

@@ -38,6 +38,7 @@
 #include "nv50_display.h"
 #include "nv50_display.h"
 
 
 static void nouveau_stub_takedown(struct drm_device *dev) {}
 static void nouveau_stub_takedown(struct drm_device *dev) {}
+static int nouveau_stub_init(struct drm_device *dev) { return 0; }
 
 
 static int nouveau_init_engine_ptrs(struct drm_device *dev)
 static int nouveau_init_engine_ptrs(struct drm_device *dev)
 {
 {
@@ -54,8 +55,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
-		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
-		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.takedown		= nv04_mc_takedown;
 		engine->mc.takedown		= nv04_mc_takedown;
 		engine->timer.init		= nv04_timer_init;
 		engine->timer.init		= nv04_timer_init;
@@ -85,6 +85,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
 		engine->fifo.destroy_context	= nv04_fifo_destroy_context;
 		engine->fifo.load_context	= nv04_fifo_load_context;
 		engine->fifo.load_context	= nv04_fifo_load_context;
 		engine->fifo.unload_context	= nv04_fifo_unload_context;
 		engine->fifo.unload_context	= nv04_fifo_unload_context;
+		engine->display.early_init	= nv04_display_early_init;
+		engine->display.late_takedown	= nv04_display_late_takedown;
+		engine->display.create		= nv04_display_create;
+		engine->display.init		= nv04_display_init;
+		engine->display.destroy		= nv04_display_destroy;
+		engine->gpio.init		= nouveau_stub_init;
+		engine->gpio.takedown		= nouveau_stub_takedown;
+		engine->gpio.get		= NULL;
+		engine->gpio.set		= NULL;
+		engine->gpio.irq_enable		= NULL;
 		break;
 		break;
 	case 0x10:
 	case 0x10:
 		engine->instmem.init		= nv04_instmem_init;
 		engine->instmem.init		= nv04_instmem_init;
@@ -95,8 +105,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
-		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
-		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.takedown		= nv04_mc_takedown;
 		engine->mc.takedown		= nv04_mc_takedown;
 		engine->timer.init		= nv04_timer_init;
 		engine->timer.init		= nv04_timer_init;
@@ -128,6 +137,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
 		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
 		engine->fifo.unload_context	= nv10_fifo_unload_context;
 		engine->fifo.unload_context	= nv10_fifo_unload_context;
+		engine->display.early_init	= nv04_display_early_init;
+		engine->display.late_takedown	= nv04_display_late_takedown;
+		engine->display.create		= nv04_display_create;
+		engine->display.init		= nv04_display_init;
+		engine->display.destroy		= nv04_display_destroy;
+		engine->gpio.init		= nouveau_stub_init;
+		engine->gpio.takedown		= nouveau_stub_takedown;
+		engine->gpio.get		= nv10_gpio_get;
+		engine->gpio.set		= nv10_gpio_set;
+		engine->gpio.irq_enable		= NULL;
 		break;
 		break;
 	case 0x20:
 	case 0x20:
 		engine->instmem.init		= nv04_instmem_init;
 		engine->instmem.init		= nv04_instmem_init;
@@ -138,8 +157,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
-		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
-		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.takedown		= nv04_mc_takedown;
 		engine->mc.takedown		= nv04_mc_takedown;
 		engine->timer.init		= nv04_timer_init;
 		engine->timer.init		= nv04_timer_init;
@@ -171,6 +189,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
 		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
 		engine->fifo.unload_context	= nv10_fifo_unload_context;
 		engine->fifo.unload_context	= nv10_fifo_unload_context;
+		engine->display.early_init	= nv04_display_early_init;
+		engine->display.late_takedown	= nv04_display_late_takedown;
+		engine->display.create		= nv04_display_create;
+		engine->display.init		= nv04_display_init;
+		engine->display.destroy		= nv04_display_destroy;
+		engine->gpio.init		= nouveau_stub_init;
+		engine->gpio.takedown		= nouveau_stub_takedown;
+		engine->gpio.get		= nv10_gpio_get;
+		engine->gpio.set		= nv10_gpio_set;
+		engine->gpio.irq_enable		= NULL;
 		break;
 		break;
 	case 0x30:
 	case 0x30:
 		engine->instmem.init		= nv04_instmem_init;
 		engine->instmem.init		= nv04_instmem_init;
@@ -181,15 +209,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
-		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
-		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.init			= nv04_mc_init;
 		engine->mc.takedown		= nv04_mc_takedown;
 		engine->mc.takedown		= nv04_mc_takedown;
 		engine->timer.init		= nv04_timer_init;
 		engine->timer.init		= nv04_timer_init;
 		engine->timer.read		= nv04_timer_read;
 		engine->timer.read		= nv04_timer_read;
 		engine->timer.takedown		= nv04_timer_takedown;
 		engine->timer.takedown		= nv04_timer_takedown;
-		engine->fb.init			= nv10_fb_init;
-		engine->fb.takedown		= nv10_fb_takedown;
+		engine->fb.init			= nv30_fb_init;
+		engine->fb.takedown		= nv30_fb_takedown;
 		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
 		engine->fb.set_region_tiling	= nv10_fb_set_region_tiling;
 		engine->graph.grclass		= nv30_graph_grclass;
 		engine->graph.grclass		= nv30_graph_grclass;
 		engine->graph.init		= nv30_graph_init;
 		engine->graph.init		= nv30_graph_init;
@@ -214,6 +241,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
 		engine->fifo.destroy_context	= nv10_fifo_destroy_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
 		engine->fifo.load_context	= nv10_fifo_load_context;
 		engine->fifo.unload_context	= nv10_fifo_unload_context;
 		engine->fifo.unload_context	= nv10_fifo_unload_context;
+		engine->display.early_init	= nv04_display_early_init;
+		engine->display.late_takedown	= nv04_display_late_takedown;
+		engine->display.create		= nv04_display_create;
+		engine->display.init		= nv04_display_init;
+		engine->display.destroy		= nv04_display_destroy;
+		engine->gpio.init		= nouveau_stub_init;
+		engine->gpio.takedown		= nouveau_stub_takedown;
+		engine->gpio.get		= nv10_gpio_get;
+		engine->gpio.set		= nv10_gpio_set;
+		engine->gpio.irq_enable		= NULL;
 		break;
 		break;
 	case 0x40:
 	case 0x40:
 	case 0x60:
 	case 0x60:
@@ -225,8 +262,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.clear		= nv04_instmem_clear;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.bind		= nv04_instmem_bind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
 		engine->instmem.unbind		= nv04_instmem_unbind;
-		engine->instmem.prepare_access	= nv04_instmem_prepare_access;
-		engine->instmem.finish_access	= nv04_instmem_finish_access;
+		engine->instmem.flush		= nv04_instmem_flush;
 		engine->mc.init			= nv40_mc_init;
 		engine->mc.init			= nv40_mc_init;
 		engine->mc.takedown		= nv40_mc_takedown;
 		engine->mc.takedown		= nv40_mc_takedown;
 		engine->timer.init		= nv04_timer_init;
 		engine->timer.init		= nv04_timer_init;
@@ -258,6 +294,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->fifo.destroy_context	= nv40_fifo_destroy_context;
 		engine->fifo.destroy_context	= nv40_fifo_destroy_context;
 		engine->fifo.load_context	= nv40_fifo_load_context;
 		engine->fifo.load_context	= nv40_fifo_load_context;
 		engine->fifo.unload_context	= nv40_fifo_unload_context;
 		engine->fifo.unload_context	= nv40_fifo_unload_context;
+		engine->display.early_init	= nv04_display_early_init;
+		engine->display.late_takedown	= nv04_display_late_takedown;
+		engine->display.create		= nv04_display_create;
+		engine->display.init		= nv04_display_init;
+		engine->display.destroy		= nv04_display_destroy;
+		engine->gpio.init		= nouveau_stub_init;
+		engine->gpio.takedown		= nouveau_stub_takedown;
+		engine->gpio.get		= nv10_gpio_get;
+		engine->gpio.set		= nv10_gpio_set;
+		engine->gpio.irq_enable		= NULL;
 		break;
 		break;
 	case 0x50:
 	case 0x50:
 	case 0x80: /* gotta love NVIDIA's consistency.. */
 	case 0x80: /* gotta love NVIDIA's consistency.. */
@@ -271,8 +317,10 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->instmem.clear		= nv50_instmem_clear;
 		engine->instmem.clear		= nv50_instmem_clear;
 		engine->instmem.bind		= nv50_instmem_bind;
 		engine->instmem.bind		= nv50_instmem_bind;
 		engine->instmem.unbind		= nv50_instmem_unbind;
 		engine->instmem.unbind		= nv50_instmem_unbind;
-		engine->instmem.prepare_access	= nv50_instmem_prepare_access;
-		engine->instmem.finish_access	= nv50_instmem_finish_access;
+		if (dev_priv->chipset == 0x50)
+			engine->instmem.flush	= nv50_instmem_flush;
+		else
+			engine->instmem.flush	= nv84_instmem_flush;
 		engine->mc.init			= nv50_mc_init;
 		engine->mc.init			= nv50_mc_init;
 		engine->mc.takedown		= nv50_mc_takedown;
 		engine->mc.takedown		= nv50_mc_takedown;
 		engine->timer.init		= nv04_timer_init;
 		engine->timer.init		= nv04_timer_init;
@@ -300,6 +348,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
 		engine->fifo.destroy_context	= nv50_fifo_destroy_context;
 		engine->fifo.destroy_context	= nv50_fifo_destroy_context;
 		engine->fifo.load_context	= nv50_fifo_load_context;
 		engine->fifo.load_context	= nv50_fifo_load_context;
 		engine->fifo.unload_context	= nv50_fifo_unload_context;
 		engine->fifo.unload_context	= nv50_fifo_unload_context;
+		engine->display.early_init	= nv50_display_early_init;
+		engine->display.late_takedown	= nv50_display_late_takedown;
+		engine->display.create		= nv50_display_create;
+		engine->display.init		= nv50_display_init;
+		engine->display.destroy		= nv50_display_destroy;
+		engine->gpio.init		= nv50_gpio_init;
+		engine->gpio.takedown		= nouveau_stub_takedown;
+		engine->gpio.get		= nv50_gpio_get;
+		engine->gpio.set		= nv50_gpio_set;
+		engine->gpio.irq_enable		= nv50_gpio_irq_enable;
 		break;
 		break;
 	default:
 	default:
 		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
 		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset);
@@ -407,11 +465,6 @@ nouveau_card_init(struct drm_device *dev)
 	struct nouveau_engine *engine;
 	struct nouveau_engine *engine;
 	int ret;
 	int ret;
 
 
-	NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
-
-	if (dev_priv->init_state == NOUVEAU_CARD_INIT_DONE)
-		return 0;
-
 	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
 	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode);
 	vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
 	vga_switcheroo_register_client(dev->pdev, nouveau_switcheroo_set_state,
 				       nouveau_switcheroo_can_switch);
 				       nouveau_switcheroo_can_switch);
@@ -421,15 +474,17 @@ nouveau_card_init(struct drm_device *dev)
 	if (ret)
 	if (ret)
 		goto out;
 		goto out;
 	engine = &dev_priv->engine;
 	engine = &dev_priv->engine;
-	dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
 	spin_lock_init(&dev_priv->context_switch_lock);
 	spin_lock_init(&dev_priv->context_switch_lock);
 
 
+	/* Make the CRTCs and I2C buses accessible */
+	ret = engine->display.early_init(dev);
+	if (ret)
+		goto out;
+
 	/* Parse BIOS tables / Run init tables if card not POSTed */
 	/* Parse BIOS tables / Run init tables if card not POSTed */
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		ret = nouveau_bios_init(dev);
-		if (ret)
-			goto out;
-	}
+	ret = nouveau_bios_init(dev);
+	if (ret)
+		goto out_display_early;
 
 
 	ret = nouveau_mem_detect(dev);
 	ret = nouveau_mem_detect(dev);
 	if (ret)
 	if (ret)
@@ -461,10 +516,15 @@ nouveau_card_init(struct drm_device *dev)
 	if (ret)
 	if (ret)
 		goto out_gpuobj;
 		goto out_gpuobj;
 
 
+	/* PGPIO */
+	ret = engine->gpio.init(dev);
+	if (ret)
+		goto out_mc;
+
 	/* PTIMER */
 	/* PTIMER */
 	ret = engine->timer.init(dev);
 	ret = engine->timer.init(dev);
 	if (ret)
 	if (ret)
-		goto out_mc;
+		goto out_gpio;
 
 
 	/* PFB */
 	/* PFB */
 	ret = engine->fb.init(dev);
 	ret = engine->fb.init(dev);
@@ -485,12 +545,16 @@ nouveau_card_init(struct drm_device *dev)
 			goto out_graph;
 			goto out_graph;
 	}
 	}
 
 
+	ret = engine->display.create(dev);
+	if (ret)
+		goto out_fifo;
+
 	/* this call irq_preinstall, register irq handler and
 	/* this call irq_preinstall, register irq handler and
 	 * call irq_postinstall
 	 * call irq_postinstall
 	 */
 	 */
 	ret = drm_irq_install(dev);
 	ret = drm_irq_install(dev);
 	if (ret)
 	if (ret)
-		goto out_fifo;
+		goto out_display;
 
 
 	ret = drm_vblank_init(dev, 0);
 	ret = drm_vblank_init(dev, 0);
 	if (ret)
 	if (ret)
@@ -504,35 +568,18 @@ nouveau_card_init(struct drm_device *dev)
 			goto out_irq;
 			goto out_irq;
 	}
 	}
 
 
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		if (dev_priv->card_type >= NV_50)
-			ret = nv50_display_create(dev);
-		else
-			ret = nv04_display_create(dev);
-		if (ret)
-			goto out_channel;
-	}
-
 	ret = nouveau_backlight_init(dev);
 	ret = nouveau_backlight_init(dev);
 	if (ret)
 	if (ret)
 		NV_ERROR(dev, "Error %d registering backlight\n", ret);
 		NV_ERROR(dev, "Error %d registering backlight\n", ret);
 
 
-	dev_priv->init_state = NOUVEAU_CARD_INIT_DONE;
-
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		nouveau_fbcon_init(dev);
-		drm_kms_helper_poll_init(dev);
-	}
-
+	nouveau_fbcon_init(dev);
+	drm_kms_helper_poll_init(dev);
 	return 0;
 	return 0;
 
 
-out_channel:
-	if (dev_priv->channel) {
-		nouveau_channel_free(dev_priv->channel);
-		dev_priv->channel = NULL;
-	}
 out_irq:
 out_irq:
 	drm_irq_uninstall(dev);
 	drm_irq_uninstall(dev);
+out_display:
+	engine->display.destroy(dev);
 out_fifo:
 out_fifo:
 	if (!nouveau_noaccel)
 	if (!nouveau_noaccel)
 		engine->fifo.takedown(dev);
 		engine->fifo.takedown(dev);
@@ -543,6 +590,8 @@ out_fb:
 	engine->fb.takedown(dev);
 	engine->fb.takedown(dev);
 out_timer:
 out_timer:
 	engine->timer.takedown(dev);
 	engine->timer.takedown(dev);
+out_gpio:
+	engine->gpio.takedown(dev);
 out_mc:
 out_mc:
 	engine->mc.takedown(dev);
 	engine->mc.takedown(dev);
 out_gpuobj:
 out_gpuobj:
@@ -556,6 +605,8 @@ out_gpuobj_early:
 	nouveau_gpuobj_late_takedown(dev);
 	nouveau_gpuobj_late_takedown(dev);
 out_bios:
 out_bios:
 	nouveau_bios_takedown(dev);
 	nouveau_bios_takedown(dev);
+out_display_early:
+	engine->display.late_takedown(dev);
 out:
 out:
 	vga_client_register(dev->pdev, NULL, NULL, NULL);
 	vga_client_register(dev->pdev, NULL, NULL, NULL);
 	return ret;
 	return ret;
@@ -566,45 +617,39 @@ static void nouveau_card_takedown(struct drm_device *dev)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_engine *engine = &dev_priv->engine;
 	struct nouveau_engine *engine = &dev_priv->engine;
 
 
-	NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state);
-
-	if (dev_priv->init_state != NOUVEAU_CARD_INIT_DOWN) {
-
-		nouveau_backlight_exit(dev);
-
-		if (dev_priv->channel) {
-			nouveau_channel_free(dev_priv->channel);
-			dev_priv->channel = NULL;
-		}
+	nouveau_backlight_exit(dev);
 
 
-		if (!nouveau_noaccel) {
-			engine->fifo.takedown(dev);
-			engine->graph.takedown(dev);
-		}
-		engine->fb.takedown(dev);
-		engine->timer.takedown(dev);
-		engine->mc.takedown(dev);
+	if (dev_priv->channel) {
+		nouveau_channel_free(dev_priv->channel);
+		dev_priv->channel = NULL;
+	}
 
 
-		mutex_lock(&dev->struct_mutex);
-		ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
-		ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
-		mutex_unlock(&dev->struct_mutex);
-		nouveau_sgdma_takedown(dev);
+	if (!nouveau_noaccel) {
+		engine->fifo.takedown(dev);
+		engine->graph.takedown(dev);
+	}
+	engine->fb.takedown(dev);
+	engine->timer.takedown(dev);
+	engine->gpio.takedown(dev);
+	engine->mc.takedown(dev);
+	engine->display.late_takedown(dev);
 
 
-		nouveau_gpuobj_takedown(dev);
-		nouveau_mem_close(dev);
-		engine->instmem.takedown(dev);
+	mutex_lock(&dev->struct_mutex);
+	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
+	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
+	mutex_unlock(&dev->struct_mutex);
+	nouveau_sgdma_takedown(dev);
 
 
-		if (drm_core_check_feature(dev, DRIVER_MODESET))
-			drm_irq_uninstall(dev);
+	nouveau_gpuobj_takedown(dev);
+	nouveau_mem_close(dev);
+	engine->instmem.takedown(dev);
 
 
-		nouveau_gpuobj_late_takedown(dev);
-		nouveau_bios_takedown(dev);
+	drm_irq_uninstall(dev);
 
 
-		vga_client_register(dev->pdev, NULL, NULL, NULL);
+	nouveau_gpuobj_late_takedown(dev);
+	nouveau_bios_takedown(dev);
 
 
-		dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
-	}
+	vga_client_register(dev->pdev, NULL, NULL, NULL);
 }
 }
 
 
 /* here a client dies, release the stuff that was allocated for its
 /* here a client dies, release the stuff that was allocated for its
@@ -691,6 +736,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
 	struct drm_nouveau_private *dev_priv;
 	struct drm_nouveau_private *dev_priv;
 	uint32_t reg0;
 	uint32_t reg0;
 	resource_size_t mmio_start_offs;
 	resource_size_t mmio_start_offs;
+	int ret;
 
 
 	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
 	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL);
 	if (!dev_priv)
 	if (!dev_priv)
@@ -699,7 +745,6 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
 	dev_priv->dev = dev;
 	dev_priv->dev = dev;
 
 
 	dev_priv->flags = flags & NOUVEAU_FLAGS;
 	dev_priv->flags = flags & NOUVEAU_FLAGS;
-	dev_priv->init_state = NOUVEAU_CARD_INIT_DOWN;
 
 
 	NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
 	NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
 		 dev->pci_vendor, dev->pci_device, dev->pdev->class);
 		 dev->pci_vendor, dev->pci_device, dev->pdev->class);
@@ -773,11 +818,9 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
 	NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
 	NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
 		dev_priv->card_type, reg0);
 		dev_priv->card_type, reg0);
 
 
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		int ret = nouveau_remove_conflicting_drivers(dev);
-		if (ret)
-			return ret;
-	}
+	ret = nouveau_remove_conflicting_drivers(dev);
+	if (ret)
+		return ret;
 
 
 	/* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */
 	/* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */
 	if (dev_priv->card_type >= NV_40) {
 	if (dev_priv->card_type >= NV_40) {
@@ -812,46 +855,26 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
 		dev_priv->flags |= NV_NFORCE2;
 		dev_priv->flags |= NV_NFORCE2;
 
 
 	/* For kernel modesetting, init card now and bring up fbcon */
 	/* For kernel modesetting, init card now and bring up fbcon */
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		int ret = nouveau_card_init(dev);
-		if (ret)
-			return ret;
-	}
+	ret = nouveau_card_init(dev);
+	if (ret)
+		return ret;
 
 
 	return 0;
 	return 0;
 }
 }
 
 
-static void nouveau_close(struct drm_device *dev)
-{
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-
-	/* In the case of an error dev_priv may not be allocated yet */
-	if (dev_priv)
-		nouveau_card_takedown(dev);
-}
-
-/* KMS: we need mmio at load time, not when the first drm client opens. */
 void nouveau_lastclose(struct drm_device *dev)
 void nouveau_lastclose(struct drm_device *dev)
 {
 {
-	if (drm_core_check_feature(dev, DRIVER_MODESET))
-		return;
-
-	nouveau_close(dev);
 }
 }
 
 
 int nouveau_unload(struct drm_device *dev)
 int nouveau_unload(struct drm_device *dev)
 {
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_engine *engine = &dev_priv->engine;
 
 
-	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
-		drm_kms_helper_poll_fini(dev);
-		nouveau_fbcon_fini(dev);
-		if (dev_priv->card_type >= NV_50)
-			nv50_display_destroy(dev);
-		else
-			nv04_display_destroy(dev);
-		nouveau_close(dev);
-	}
+	drm_kms_helper_poll_fini(dev);
+	nouveau_fbcon_fini(dev);
+	engine->display.destroy(dev);
+	nouveau_card_takedown(dev);
 
 
 	iounmap(dev_priv->mmio);
 	iounmap(dev_priv->mmio);
 	iounmap(dev_priv->ramin);
 	iounmap(dev_priv->ramin);
@@ -867,8 +890,6 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_getparam *getparam = data;
 	struct drm_nouveau_getparam *getparam = data;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
 	switch (getparam->param) {
 	switch (getparam->param) {
 	case NOUVEAU_GETPARAM_CHIPSET_ID:
 	case NOUVEAU_GETPARAM_CHIPSET_ID:
 		getparam->value = dev_priv->chipset;
 		getparam->value = dev_priv->chipset;
@@ -937,8 +958,6 @@ nouveau_ioctl_setparam(struct drm_device *dev, void *data,
 {
 {
 	struct drm_nouveau_setparam *setparam = data;
 	struct drm_nouveau_setparam *setparam = data;
 
 
-	NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
-
 	switch (setparam->param) {
 	switch (setparam->param) {
 	default:
 	default:
 		NV_ERROR(dev, "unknown parameter %lld\n", setparam->param);
 		NV_ERROR(dev, "unknown parameter %lld\n", setparam->param);

+ 10 - 10
drivers/gpu/drm/nouveau/nouveau_ttm.c

@@ -42,13 +42,13 @@ nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma)
 }
 }
 
 
 static int
 static int
-nouveau_ttm_mem_global_init(struct ttm_global_reference *ref)
+nouveau_ttm_mem_global_init(struct drm_global_reference *ref)
 {
 {
 	return ttm_mem_global_init(ref->object);
 	return ttm_mem_global_init(ref->object);
 }
 }
 
 
 static void
 static void
-nouveau_ttm_mem_global_release(struct ttm_global_reference *ref)
+nouveau_ttm_mem_global_release(struct drm_global_reference *ref)
 {
 {
 	ttm_mem_global_release(ref->object);
 	ttm_mem_global_release(ref->object);
 }
 }
@@ -56,16 +56,16 @@ nouveau_ttm_mem_global_release(struct ttm_global_reference *ref)
 int
 int
 nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv)
 nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv)
 {
 {
-	struct ttm_global_reference *global_ref;
+	struct drm_global_reference *global_ref;
 	int ret;
 	int ret;
 
 
 	global_ref = &dev_priv->ttm.mem_global_ref;
 	global_ref = &dev_priv->ttm.mem_global_ref;
-	global_ref->global_type = TTM_GLOBAL_TTM_MEM;
+	global_ref->global_type = DRM_GLOBAL_TTM_MEM;
 	global_ref->size = sizeof(struct ttm_mem_global);
 	global_ref->size = sizeof(struct ttm_mem_global);
 	global_ref->init = &nouveau_ttm_mem_global_init;
 	global_ref->init = &nouveau_ttm_mem_global_init;
 	global_ref->release = &nouveau_ttm_mem_global_release;
 	global_ref->release = &nouveau_ttm_mem_global_release;
 
 
-	ret = ttm_global_item_ref(global_ref);
+	ret = drm_global_item_ref(global_ref);
 	if (unlikely(ret != 0)) {
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("Failed setting up TTM memory accounting\n");
 		DRM_ERROR("Failed setting up TTM memory accounting\n");
 		dev_priv->ttm.mem_global_ref.release = NULL;
 		dev_priv->ttm.mem_global_ref.release = NULL;
@@ -74,15 +74,15 @@ nouveau_ttm_global_init(struct drm_nouveau_private *dev_priv)
 
 
 	dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object;
 	dev_priv->ttm.bo_global_ref.mem_glob = global_ref->object;
 	global_ref = &dev_priv->ttm.bo_global_ref.ref;
 	global_ref = &dev_priv->ttm.bo_global_ref.ref;
-	global_ref->global_type = TTM_GLOBAL_TTM_BO;
+	global_ref->global_type = DRM_GLOBAL_TTM_BO;
 	global_ref->size = sizeof(struct ttm_bo_global);
 	global_ref->size = sizeof(struct ttm_bo_global);
 	global_ref->init = &ttm_bo_global_init;
 	global_ref->init = &ttm_bo_global_init;
 	global_ref->release = &ttm_bo_global_release;
 	global_ref->release = &ttm_bo_global_release;
 
 
-	ret = ttm_global_item_ref(global_ref);
+	ret = drm_global_item_ref(global_ref);
 	if (unlikely(ret != 0)) {
 	if (unlikely(ret != 0)) {
 		DRM_ERROR("Failed setting up TTM BO subsystem\n");
 		DRM_ERROR("Failed setting up TTM BO subsystem\n");
-		ttm_global_item_unref(&dev_priv->ttm.mem_global_ref);
+		drm_global_item_unref(&dev_priv->ttm.mem_global_ref);
 		dev_priv->ttm.mem_global_ref.release = NULL;
 		dev_priv->ttm.mem_global_ref.release = NULL;
 		return ret;
 		return ret;
 	}
 	}
@@ -96,8 +96,8 @@ nouveau_ttm_global_release(struct drm_nouveau_private *dev_priv)
 	if (dev_priv->ttm.mem_global_ref.release == NULL)
 	if (dev_priv->ttm.mem_global_ref.release == NULL)
 		return;
 		return;
 
 
-	ttm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref);
-	ttm_global_item_unref(&dev_priv->ttm.mem_global_ref);
+	drm_global_item_unref(&dev_priv->ttm.bo_global_ref.ref);
+	drm_global_item_unref(&dev_priv->ttm.mem_global_ref);
 	dev_priv->ttm.mem_global_ref.release = NULL;
 	dev_priv->ttm.mem_global_ref.release = NULL;
 }
 }
 
 

+ 5 - 0
drivers/gpu/drm/nouveau/nv04_crtc.c

@@ -157,6 +157,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
 {
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct drm_device *dev = crtc->dev;
 	struct drm_device *dev = crtc->dev;
+	struct drm_connector *connector;
 	unsigned char seq1 = 0, crtc17 = 0;
 	unsigned char seq1 = 0, crtc17 = 0;
 	unsigned char crtc1A;
 	unsigned char crtc1A;
 
 
@@ -211,6 +212,10 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode)
 	NVVgaSeqReset(dev, nv_crtc->index, false);
 	NVVgaSeqReset(dev, nv_crtc->index, false);
 
 
 	NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
 	NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A);
+
+	/* Update connector polling modes */
+	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
+		nouveau_connector_set_polling(connector);
 }
 }
 
 
 static bool
 static bool

+ 35 - 15
drivers/gpu/drm/nouveau/nv04_dac.c

@@ -220,6 +220,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
 {
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_device *dev = encoder->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
 	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
 	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
 	uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
 	uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder);
 	uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
 	uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput,
@@ -251,22 +252,21 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
 		nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
 		nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf);
 	}
 	}
 
 
-	saved_gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
-	saved_gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
+	saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1);
+	saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0);
 
 
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV);
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV);
+	gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV);
+	gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV);
 
 
 	msleep(4);
 	msleep(4);
 
 
 	saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
 	saved_routput = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
 	head = (saved_routput & 0x100) >> 8;
 	head = (saved_routput & 0x100) >> 8;
-#if 0
-	/* if there's a spare crtc, using it will minimise flicker for the case
-	 * where the in-use crtc is in use by an off-chip tmds encoder */
-	if (xf86_config->crtc[head]->enabled && !xf86_config->crtc[head ^ 1]->enabled)
+
+	/* if there's a spare crtc, using it will minimise flicker */
+	if (!(NVReadVgaCrtc(dev, head, NV_CIO_CRE_RPC1_INDEX) & 0xC0))
 		head ^= 1;
 		head ^= 1;
-#endif
+
 	/* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */
 	/* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */
 	routput = (saved_routput & 0xfffffece) | head << 8;
 	routput = (saved_routput & 0xfffffece) | head << 8;
 
 
@@ -304,8 +304,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
 		nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
 		nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4);
 	nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
 	nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2);
 
 
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
+	gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1);
+	gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0);
 
 
 	return sample;
 	return sample;
 }
 }
@@ -315,9 +315,12 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 {
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_device *dev = encoder->dev;
 	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
 	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
-	uint32_t sample = nv17_dac_sample_load(encoder);
 
 
-	if (sample & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
+	if (nv04_dac_in_use(encoder))
+		return connector_status_disconnected;
+
+	if (nv17_dac_sample_load(encoder) &
+	    NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) {
 		NV_INFO(dev, "Load detected on output %c\n",
 		NV_INFO(dev, "Load detected on output %c\n",
 			'@' + ffs(dcb->or));
 			'@' + ffs(dcb->or));
 		return connector_status_connected;
 		return connector_status_connected;
@@ -330,6 +333,9 @@ static bool nv04_dac_mode_fixup(struct drm_encoder *encoder,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 				struct drm_display_mode *adjusted_mode)
 {
 {
+	if (nv04_dac_in_use(encoder))
+		return false;
+
 	return true;
 	return true;
 }
 }
 
 
@@ -428,6 +434,17 @@ void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable)
 	}
 	}
 }
 }
 
 
+/* Check if the DAC corresponding to 'encoder' is being used by
+ * someone else. */
+bool nv04_dac_in_use(struct drm_encoder *encoder)
+{
+	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
+	struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb;
+
+	return nv_gf4_disp_arch(encoder->dev) &&
+		(dev_priv->dac_users[ffs(dcb->or) - 1] & ~(1 << dcb->index));
+}
+
 static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
 static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)
 {
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_device *dev = encoder->dev;
@@ -501,11 +518,13 @@ static const struct drm_encoder_funcs nv04_dac_funcs = {
 	.destroy = nv04_dac_destroy,
 	.destroy = nv04_dac_destroy,
 };
 };
 
 
-int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
+int
+nv04_dac_create(struct drm_connector *connector, struct dcb_entry *entry)
 {
 {
 	const struct drm_encoder_helper_funcs *helper;
 	const struct drm_encoder_helper_funcs *helper;
-	struct drm_encoder *encoder;
 	struct nouveau_encoder *nv_encoder = NULL;
 	struct nouveau_encoder *nv_encoder = NULL;
+	struct drm_device *dev = connector->dev;
+	struct drm_encoder *encoder;
 
 
 	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
 	nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL);
 	if (!nv_encoder)
 	if (!nv_encoder)
@@ -527,5 +546,6 @@ int nv04_dac_create(struct drm_device *dev, struct dcb_entry *entry)
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_clones = 0;
 	encoder->possible_clones = 0;
 
 
+	drm_mode_connector_attach_encoder(connector, encoder);
 	return 0;
 	return 0;
 }
 }

+ 5 - 7
drivers/gpu/drm/nouveau/nv04_dfp.c

@@ -413,10 +413,6 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)
 	struct dcb_entry *dcbe = nv_encoder->dcb;
 	struct dcb_entry *dcbe = nv_encoder->dcb;
 	int head = nouveau_crtc(encoder->crtc)->index;
 	int head = nouveau_crtc(encoder->crtc)->index;
 
 
-	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n",
-		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base),
-		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));
-
 	if (dcbe->type == OUTPUT_TMDS)
 	if (dcbe->type == OUTPUT_TMDS)
 		run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock);
 		run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock);
 	else if (dcbe->type == OUTPUT_LVDS)
 	else if (dcbe->type == OUTPUT_LVDS)
@@ -584,11 +580,12 @@ static const struct drm_encoder_funcs nv04_dfp_funcs = {
 	.destroy = nv04_dfp_destroy,
 	.destroy = nv04_dfp_destroy,
 };
 };
 
 
-int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
+int
+nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry)
 {
 {
 	const struct drm_encoder_helper_funcs *helper;
 	const struct drm_encoder_helper_funcs *helper;
-	struct drm_encoder *encoder;
 	struct nouveau_encoder *nv_encoder = NULL;
 	struct nouveau_encoder *nv_encoder = NULL;
+	struct drm_encoder *encoder;
 	int type;
 	int type;
 
 
 	switch (entry->type) {
 	switch (entry->type) {
@@ -613,11 +610,12 @@ int nv04_dfp_create(struct drm_device *dev, struct dcb_entry *entry)
 	nv_encoder->dcb = entry;
 	nv_encoder->dcb = entry;
 	nv_encoder->or = ffs(entry->or) - 1;
 	nv_encoder->or = ffs(entry->or) - 1;
 
 
-	drm_encoder_init(dev, encoder, &nv04_dfp_funcs, type);
+	drm_encoder_init(connector->dev, encoder, &nv04_dfp_funcs, type);
 	drm_encoder_helper_add(encoder, helper);
 	drm_encoder_helper_add(encoder, helper);
 
 
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_clones = 0;
 	encoder->possible_clones = 0;
 
 
+	drm_mode_connector_attach_encoder(connector, encoder);
 	return 0;
 	return 0;
 }
 }

+ 53 - 37
drivers/gpu/drm/nouveau/nv04_display.c

@@ -32,8 +32,6 @@
 #include "nouveau_encoder.h"
 #include "nouveau_encoder.h"
 #include "nouveau_connector.h"
 #include "nouveau_connector.h"
 
 
-#define MULTIPLE_ENCODERS(e) (e & (e - 1))
-
 static void
 static void
 nv04_display_store_initial_head_owner(struct drm_device *dev)
 nv04_display_store_initial_head_owner(struct drm_device *dev)
 {
 {
@@ -41,7 +39,7 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
 
 
 	if (dev_priv->chipset != 0x11) {
 	if (dev_priv->chipset != 0x11) {
 		dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44);
 		dev_priv->crtc_owner = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44);
-		goto ownerknown;
+		return;
 	}
 	}
 
 
 	/* reading CR44 is broken on nv11, so we attempt to infer it */
 	/* reading CR44 is broken on nv11, so we attempt to infer it */
@@ -52,8 +50,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
 		bool tvA = false;
 		bool tvA = false;
 		bool tvB = false;
 		bool tvB = false;
 
 
-		NVLockVgaCrtcs(dev, false);
-
 		slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) &
 		slaved_on_B = NVReadVgaCrtc(dev, 1, NV_CIO_CRE_PIXEL_INDEX) &
 									0x80;
 									0x80;
 		if (slaved_on_B)
 		if (slaved_on_B)
@@ -66,8 +62,6 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
 			tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) &
 			tvA = !(NVReadVgaCrtc(dev, 0, NV_CIO_CRE_LCD__INDEX) &
 					MASK(NV_CIO_CRE_LCD_LCD_SELECT));
 					MASK(NV_CIO_CRE_LCD_LCD_SELECT));
 
 
-		NVLockVgaCrtcs(dev, true);
-
 		if (slaved_on_A && !tvA)
 		if (slaved_on_A && !tvA)
 			dev_priv->crtc_owner = 0x0;
 			dev_priv->crtc_owner = 0x0;
 		else if (slaved_on_B && !tvB)
 		else if (slaved_on_B && !tvB)
@@ -79,14 +73,40 @@ nv04_display_store_initial_head_owner(struct drm_device *dev)
 		else
 		else
 			dev_priv->crtc_owner = 0x0;
 			dev_priv->crtc_owner = 0x0;
 	}
 	}
+}
+
+int
+nv04_display_early_init(struct drm_device *dev)
+{
+	/* Make the I2C buses accessible. */
+	if (!nv_gf4_disp_arch(dev)) {
+		uint32_t pmc_enable = nv_rd32(dev, NV03_PMC_ENABLE);
+
+		if (!(pmc_enable & 1))
+			nv_wr32(dev, NV03_PMC_ENABLE, pmc_enable | 1);
+	}
 
 
-ownerknown:
-	NV_INFO(dev, "Initial CRTC_OWNER is %d\n", dev_priv->crtc_owner);
+	/* Unlock the VGA CRTCs. */
+	NVLockVgaCrtcs(dev, false);
+
+	/* Make sure the CRTCs aren't in slaved mode. */
+	if (nv_two_heads(dev)) {
+		nv04_display_store_initial_head_owner(dev);
+		NVSetOwner(dev, 0);
+	}
+
+	return 0;
+}
+
+void
+nv04_display_late_takedown(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+
+	if (nv_two_heads(dev))
+		NVSetOwner(dev, dev_priv->crtc_owner);
 
 
-	/* we need to ensure the heads are not tied henceforth, or reading any
-	 * 8 bit reg on head B will fail
-	 * setting a single arbitrary head solves that */
-	NVSetOwner(dev, 0);
+	NVLockVgaCrtcs(dev, true);
 }
 }
 
 
 int
 int
@@ -94,14 +114,13 @@ nv04_display_create(struct drm_device *dev)
 {
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct dcb_table *dcb = &dev_priv->vbios.dcb;
 	struct dcb_table *dcb = &dev_priv->vbios.dcb;
+	struct drm_connector *connector, *ct;
 	struct drm_encoder *encoder;
 	struct drm_encoder *encoder;
 	struct drm_crtc *crtc;
 	struct drm_crtc *crtc;
 	int i, ret;
 	int i, ret;
 
 
 	NV_DEBUG_KMS(dev, "\n");
 	NV_DEBUG_KMS(dev, "\n");
 
 
-	if (nv_two_heads(dev))
-		nv04_display_store_initial_head_owner(dev);
 	nouveau_hw_save_vga_fonts(dev, 1);
 	nouveau_hw_save_vga_fonts(dev, 1);
 
 
 	drm_mode_config_init(dev);
 	drm_mode_config_init(dev);
@@ -132,19 +151,23 @@ nv04_display_create(struct drm_device *dev)
 	for (i = 0; i < dcb->entries; i++) {
 	for (i = 0; i < dcb->entries; i++) {
 		struct dcb_entry *dcbent = &dcb->entry[i];
 		struct dcb_entry *dcbent = &dcb->entry[i];
 
 
+		connector = nouveau_connector_create(dev, dcbent->connector);
+		if (IS_ERR(connector))
+			continue;
+
 		switch (dcbent->type) {
 		switch (dcbent->type) {
 		case OUTPUT_ANALOG:
 		case OUTPUT_ANALOG:
-			ret = nv04_dac_create(dev, dcbent);
+			ret = nv04_dac_create(connector, dcbent);
 			break;
 			break;
 		case OUTPUT_LVDS:
 		case OUTPUT_LVDS:
 		case OUTPUT_TMDS:
 		case OUTPUT_TMDS:
-			ret = nv04_dfp_create(dev, dcbent);
+			ret = nv04_dfp_create(connector, dcbent);
 			break;
 			break;
 		case OUTPUT_TV:
 		case OUTPUT_TV:
 			if (dcbent->location == DCB_LOC_ON_CHIP)
 			if (dcbent->location == DCB_LOC_ON_CHIP)
-				ret = nv17_tv_create(dev, dcbent);
+				ret = nv17_tv_create(connector, dcbent);
 			else
 			else
-				ret = nv04_tv_create(dev, dcbent);
+				ret = nv04_tv_create(connector, dcbent);
 			break;
 			break;
 		default:
 		default:
 			NV_WARN(dev, "DCB type %d not known\n", dcbent->type);
 			NV_WARN(dev, "DCB type %d not known\n", dcbent->type);
@@ -155,12 +178,16 @@ nv04_display_create(struct drm_device *dev)
 			continue;
 			continue;
 	}
 	}
 
 
-	for (i = 0; i < dcb->connector.entries; i++)
-		nouveau_connector_create(dev, &dcb->connector.entry[i]);
+	list_for_each_entry_safe(connector, ct,
+				 &dev->mode_config.connector_list, head) {
+		if (!connector->encoder_ids[0]) {
+			NV_WARN(dev, "%s has no encoders, removing\n",
+				drm_get_connector_name(connector));
+			connector->funcs->destroy(connector);
+		}
+	}
 
 
 	/* Save previous state */
 	/* Save previous state */
-	NVLockVgaCrtcs(dev, false);
-
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 		crtc->funcs->save(crtc);
 		crtc->funcs->save(crtc);
 
 
@@ -191,8 +218,6 @@ nv04_display_destroy(struct drm_device *dev)
 	}
 	}
 
 
 	/* Restore state */
 	/* Restore state */
-	NVLockVgaCrtcs(dev, false);
-
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 		struct drm_encoder_helper_funcs *func = encoder->helper_private;
 		struct drm_encoder_helper_funcs *func = encoder->helper_private;
 
 
@@ -207,15 +232,12 @@ nv04_display_destroy(struct drm_device *dev)
 	nouveau_hw_save_vga_fonts(dev, 0);
 	nouveau_hw_save_vga_fonts(dev, 0);
 }
 }
 
 
-void
-nv04_display_restore(struct drm_device *dev)
+int
+nv04_display_init(struct drm_device *dev)
 {
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_encoder *encoder;
 	struct drm_encoder *encoder;
 	struct drm_crtc *crtc;
 	struct drm_crtc *crtc;
 
 
-	NVLockVgaCrtcs(dev, false);
-
 	/* meh.. modeset apparently doesn't setup all the regs and depends
 	/* meh.. modeset apparently doesn't setup all the regs and depends
 	 * on pre-existing state, for now load the state of the card *before*
 	 * on pre-existing state, for now load the state of the card *before*
 	 * nouveau was loaded, and then do a modeset.
 	 * nouveau was loaded, and then do a modeset.
@@ -233,12 +255,6 @@ nv04_display_restore(struct drm_device *dev)
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
 		crtc->funcs->restore(crtc);
 		crtc->funcs->restore(crtc);
 
 
-	if (nv_two_heads(dev)) {
-		NV_INFO(dev, "Restoring CRTC_OWNER to %d.\n",
-			dev_priv->crtc_owner);
-		NVSetOwner(dev, dev_priv->crtc_owner);
-	}
-
-	NVLockVgaCrtcs(dev, true);
+	return 0;
 }
 }
 
 

+ 8 - 12
drivers/gpu/drm/nouveau/nv04_fifo.c

@@ -112,6 +112,12 @@ nv04_fifo_channel_id(struct drm_device *dev)
 			NV03_PFIFO_CACHE1_PUSH1_CHID_MASK;
 			NV03_PFIFO_CACHE1_PUSH1_CHID_MASK;
 }
 }
 
 
+#ifdef __BIG_ENDIAN
+#define DMA_FETCH_ENDIANNESS NV_PFIFO_CACHE1_BIG_ENDIAN
+#else
+#define DMA_FETCH_ENDIANNESS 0
+#endif
+
 int
 int
 nv04_fifo_create_context(struct nouveau_channel *chan)
 nv04_fifo_create_context(struct nouveau_channel *chan)
 {
 {
@@ -131,18 +137,13 @@ nv04_fifo_create_context(struct nouveau_channel *chan)
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
 
 
 	/* Setup initial state */
 	/* Setup initial state */
-	dev_priv->engine.instmem.prepare_access(dev, true);
 	RAMFC_WR(DMA_PUT, chan->pushbuf_base);
 	RAMFC_WR(DMA_PUT, chan->pushbuf_base);
 	RAMFC_WR(DMA_GET, chan->pushbuf_base);
 	RAMFC_WR(DMA_GET, chan->pushbuf_base);
 	RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4);
 	RAMFC_WR(DMA_INSTANCE, chan->pushbuf->instance >> 4);
 	RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
 	RAMFC_WR(DMA_FETCH, (NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
 			     NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
 			     NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
 			     NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
 			     NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8 |
-#ifdef __BIG_ENDIAN
-			     NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
-			     0));
-	dev_priv->engine.instmem.finish_access(dev);
+			     DMA_FETCH_ENDIANNESS));
 
 
 	/* enable the fifo dma operation */
 	/* enable the fifo dma operation */
 	nv_wr32(dev, NV04_PFIFO_MODE,
 	nv_wr32(dev, NV04_PFIFO_MODE,
@@ -169,8 +170,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t fc = NV04_RAMFC(chid), tmp;
 	uint32_t fc = NV04_RAMFC(chid), tmp;
 
 
-	dev_priv->engine.instmem.prepare_access(dev, false);
-
 	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
 	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
 	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
 	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
 	tmp = nv_ri32(dev, fc + 8);
 	tmp = nv_ri32(dev, fc + 8);
@@ -181,8 +180,6 @@ nv04_fifo_do_load_context(struct drm_device *dev, int chid)
 	nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20));
 	nv_wr32(dev, NV04_PFIFO_CACHE1_ENGINE, nv_ri32(dev, fc + 20));
 	nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24));
 	nv_wr32(dev, NV04_PFIFO_CACHE1_PULL1, nv_ri32(dev, fc + 24));
 
 
-	dev_priv->engine.instmem.finish_access(dev);
-
 	nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
 }
 }
@@ -223,7 +220,6 @@ nv04_fifo_unload_context(struct drm_device *dev)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	dev_priv->engine.instmem.prepare_access(dev, true);
 	RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
 	RAMFC_WR(DMA_PUT, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
 	RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
 	RAMFC_WR(DMA_GET, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
 	tmp  = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
 	tmp  = nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_DCOUNT) << 16;
@@ -233,7 +229,6 @@ nv04_fifo_unload_context(struct drm_device *dev)
 	RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH));
 	RAMFC_WR(DMA_FETCH, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_FETCH));
 	RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
 	RAMFC_WR(ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_ENGINE));
 	RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
 	RAMFC_WR(PULL1_ENGINE, nv_rd32(dev, NV04_PFIFO_CACHE1_PULL1));
-	dev_priv->engine.instmem.finish_access(dev);
 
 
 	nv04_fifo_do_load_context(dev, pfifo->channels - 1);
 	nv04_fifo_do_load_context(dev, pfifo->channels - 1);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
@@ -297,6 +292,7 @@ nv04_fifo_init(struct drm_device *dev)
 
 
 	nv04_fifo_init_intr(dev);
 	nv04_fifo_init_intr(dev);
 	pfifo->enable(dev);
 	pfifo->enable(dev);
+	pfifo->reassign(dev, true);
 
 
 	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
 	for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
 		if (dev_priv->fifos[i]) {
 		if (dev_priv->fifos[i]) {

+ 2 - 3
drivers/gpu/drm/nouveau/nv04_graph.c

@@ -342,7 +342,7 @@ static uint32_t nv04_graph_ctx_regs[] = {
 };
 };
 
 
 struct graph_state {
 struct graph_state {
-	int nv04[ARRAY_SIZE(nv04_graph_ctx_regs)];
+	uint32_t nv04[ARRAY_SIZE(nv04_graph_ctx_regs)];
 };
 };
 
 
 struct nouveau_channel *
 struct nouveau_channel *
@@ -527,8 +527,7 @@ static int
 nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass,
 nv04_graph_mthd_set_ref(struct nouveau_channel *chan, int grclass,
 			int mthd, uint32_t data)
 			int mthd, uint32_t data)
 {
 {
-	chan->fence.last_sequence_irq = data;
-	nouveau_fence_handler(chan->dev, chan->id);
+	atomic_set(&chan->fence.last_sequence_irq, data);
 	return 0;
 	return 0;
 }
 }
 
 

+ 7 - 14
drivers/gpu/drm/nouveau/nv04_instmem.c

@@ -49,10 +49,8 @@ nv04_instmem_determine_amount(struct drm_device *dev)
 	NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10);
 	NV_DEBUG(dev, "RAMIN size: %dKiB\n", dev_priv->ramin_rsvd_vram >> 10);
 
 
 	/* Clear all of it, except the BIOS image that's in the first 64KiB */
 	/* Clear all of it, except the BIOS image that's in the first 64KiB */
-	dev_priv->engine.instmem.prepare_access(dev, true);
 	for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4)
 	for (i = 64 * 1024; i < dev_priv->ramin_rsvd_vram; i += 4)
 		nv_wi32(dev, i, 0x00000000);
 		nv_wi32(dev, i, 0x00000000);
-	dev_priv->engine.instmem.finish_access(dev);
 }
 }
 
 
 static void
 static void
@@ -106,7 +104,7 @@ int nv04_instmem_init(struct drm_device *dev)
 {
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t offset;
 	uint32_t offset;
-	int ret = 0;
+	int ret;
 
 
 	nv04_instmem_determine_amount(dev);
 	nv04_instmem_determine_amount(dev);
 	nv04_instmem_configure_fixed_tables(dev);
 	nv04_instmem_configure_fixed_tables(dev);
@@ -129,14 +127,14 @@ int nv04_instmem_init(struct drm_device *dev)
 			offset = 0x40000;
 			offset = 0x40000;
 	}
 	}
 
 
-	ret = nouveau_mem_init_heap(&dev_priv->ramin_heap,
-				    offset, dev_priv->ramin_rsvd_vram - offset);
+	ret = drm_mm_init(&dev_priv->ramin_heap, offset,
+			  dev_priv->ramin_rsvd_vram - offset);
 	if (ret) {
 	if (ret) {
-		dev_priv->ramin_heap = NULL;
-		NV_ERROR(dev, "Failed to init RAMIN heap\n");
+		NV_ERROR(dev, "Failed to init RAMIN heap: %d\n", ret);
+		return ret;
 	}
 	}
 
 
-	return ret;
+	return 0;
 }
 }
 
 
 void
 void
@@ -186,12 +184,7 @@ nv04_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj)
 }
 }
 
 
 void
 void
-nv04_instmem_prepare_access(struct drm_device *dev, bool write)
-{
-}
-
-void
-nv04_instmem_finish_access(struct drm_device *dev)
+nv04_instmem_flush(struct drm_device *dev)
 {
 {
 }
 }
 
 

+ 4 - 0
drivers/gpu/drm/nouveau/nv04_mc.c

@@ -11,6 +11,10 @@ nv04_mc_init(struct drm_device *dev)
 	 */
 	 */
 
 
 	nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
 	nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF);
+
+	/* Disable PROM access. */
+	nv_wr32(dev, NV_PBUS_PCI_NV_20, NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED);
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 39 - 86
drivers/gpu/drm/nouveau/nv04_tv.c

@@ -34,69 +34,26 @@
 
 
 #include "i2c/ch7006.h"
 #include "i2c/ch7006.h"
 
 
-static struct {
-	struct i2c_board_info board_info;
-	struct drm_encoder_funcs funcs;
-	struct drm_encoder_helper_funcs hfuncs;
-	void *params;
-
-} nv04_tv_encoder_info[] = {
+static struct i2c_board_info nv04_tv_encoder_info[] = {
 	{
 	{
-		.board_info = { I2C_BOARD_INFO("ch7006", 0x75) },
-		.params = &(struct ch7006_encoder_params) {
+		I2C_BOARD_INFO("ch7006", 0x75),
+		.platform_data = &(struct ch7006_encoder_params) {
 			CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
 			CH7006_FORMAT_RGB24m12I, CH7006_CLOCK_MASTER,
 			0, 0, 0,
 			0, 0, 0,
 			CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
 			CH7006_SYNC_SLAVE, CH7006_SYNC_SEPARATED,
 			CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
 			CH7006_POUT_3_3V, CH7006_ACTIVE_HSYNC
-		},
+		}
 	},
 	},
+	{ }
 };
 };
 
 
-static bool probe_i2c_addr(struct i2c_adapter *adapter, int addr)
-{
-	struct i2c_msg msg = {
-		.addr = addr,
-		.len = 0,
-	};
-
-	return i2c_transfer(adapter, &msg, 1) == 1;
-}
-
 int nv04_tv_identify(struct drm_device *dev, int i2c_index)
 int nv04_tv_identify(struct drm_device *dev, int i2c_index)
 {
 {
-	struct nouveau_i2c_chan *i2c;
-	bool was_locked;
-	int i, ret;
-
-	NV_TRACE(dev, "Probing TV encoders on I2C bus: %d\n", i2c_index);
-
-	i2c = nouveau_i2c_find(dev, i2c_index);
-	if (!i2c)
-		return -ENODEV;
-
-	was_locked = NVLockVgaCrtcs(dev, false);
-
-	for (i = 0; i < ARRAY_SIZE(nv04_tv_encoder_info); i++) {
-		if (probe_i2c_addr(&i2c->adapter,
-				   nv04_tv_encoder_info[i].board_info.addr)) {
-			ret = i;
-			break;
-		}
-	}
-
-	if (i < ARRAY_SIZE(nv04_tv_encoder_info)) {
-		NV_TRACE(dev, "Detected TV encoder: %s\n",
-			 nv04_tv_encoder_info[i].board_info.type);
-
-	} else {
-		NV_TRACE(dev, "No TV encoders found.\n");
-		i = -ENODEV;
-	}
-
-	NVLockVgaCrtcs(dev, was_locked);
-	return i;
+	return nouveau_i2c_identify(dev, "TV encoder",
+				    nv04_tv_encoder_info, i2c_index);
 }
 }
 
 
+
 #define PLLSEL_TV_CRTC1_MASK				\
 #define PLLSEL_TV_CRTC1_MASK				\
 	(NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1		\
 	(NV_PRAMDAC_PLL_COEFF_SELECT_TV_VSCLK1		\
 	 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1)
 	 | NV_PRAMDAC_PLL_COEFF_SELECT_TV_PCLK1)
@@ -214,30 +171,32 @@ static void nv04_tv_commit(struct drm_encoder *encoder)
 
 
 static void nv04_tv_destroy(struct drm_encoder *encoder)
 static void nv04_tv_destroy(struct drm_encoder *encoder)
 {
 {
-	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
-
 	to_encoder_slave(encoder)->slave_funcs->destroy(encoder);
 	to_encoder_slave(encoder)->slave_funcs->destroy(encoder);
 
 
 	drm_encoder_cleanup(encoder);
 	drm_encoder_cleanup(encoder);
 
 
-	kfree(nv_encoder);
+	kfree(encoder->helper_private);
+	kfree(nouveau_encoder(encoder));
 }
 }
 
 
-int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+static const struct drm_encoder_funcs nv04_tv_funcs = {
+	.destroy = nv04_tv_destroy,
+};
+
+int
+nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
 {
 {
 	struct nouveau_encoder *nv_encoder;
 	struct nouveau_encoder *nv_encoder;
 	struct drm_encoder *encoder;
 	struct drm_encoder *encoder;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct i2c_adapter *adap;
-	struct drm_encoder_funcs *funcs = NULL;
-	struct drm_encoder_helper_funcs *hfuncs = NULL;
-	struct drm_encoder_slave_funcs *sfuncs = NULL;
-	int i2c_index = entry->i2c_index;
+	struct drm_device *dev = connector->dev;
+	struct drm_encoder_helper_funcs *hfuncs;
+	struct drm_encoder_slave_funcs *sfuncs;
+	struct nouveau_i2c_chan *i2c =
+		nouveau_i2c_find(dev, entry->i2c_index);
 	int type, ret;
 	int type, ret;
-	bool was_locked;
 
 
 	/* Ensure that we can talk to this encoder */
 	/* Ensure that we can talk to this encoder */
-	type = nv04_tv_identify(dev, i2c_index);
+	type = nv04_tv_identify(dev, entry->i2c_index);
 	if (type < 0)
 	if (type < 0)
 		return type;
 		return type;
 
 
@@ -246,41 +205,32 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
 	if (!nv_encoder)
 	if (!nv_encoder)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
+	hfuncs = kzalloc(sizeof(*hfuncs), GFP_KERNEL);
+	if (!hfuncs) {
+		ret = -ENOMEM;
+		goto fail_free;
+	}
+
 	/* Initialize the common members */
 	/* Initialize the common members */
 	encoder = to_drm_encoder(nv_encoder);
 	encoder = to_drm_encoder(nv_encoder);
 
 
-	funcs = &nv04_tv_encoder_info[type].funcs;
-	hfuncs = &nv04_tv_encoder_info[type].hfuncs;
-
-	drm_encoder_init(dev, encoder, funcs, DRM_MODE_ENCODER_TVDAC);
+	drm_encoder_init(dev, encoder, &nv04_tv_funcs, DRM_MODE_ENCODER_TVDAC);
 	drm_encoder_helper_add(encoder, hfuncs);
 	drm_encoder_helper_add(encoder, hfuncs);
 
 
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_clones = 0;
 	encoder->possible_clones = 0;
-
 	nv_encoder->dcb = entry;
 	nv_encoder->dcb = entry;
 	nv_encoder->or = ffs(entry->or) - 1;
 	nv_encoder->or = ffs(entry->or) - 1;
 
 
 	/* Run the slave-specific initialization */
 	/* Run the slave-specific initialization */
-	adap = &dev_priv->vbios.dcb.i2c[i2c_index].chan->adapter;
-
-	was_locked = NVLockVgaCrtcs(dev, false);
-
-	ret = drm_i2c_encoder_init(encoder->dev, to_encoder_slave(encoder), adap,
-				   &nv04_tv_encoder_info[type].board_info);
-
-	NVLockVgaCrtcs(dev, was_locked);
-
+	ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder),
+				   &i2c->adapter, &nv04_tv_encoder_info[type]);
 	if (ret < 0)
 	if (ret < 0)
-		goto fail;
+		goto fail_cleanup;
 
 
 	/* Fill the function pointers */
 	/* Fill the function pointers */
 	sfuncs = to_encoder_slave(encoder)->slave_funcs;
 	sfuncs = to_encoder_slave(encoder)->slave_funcs;
 
 
-	*funcs = (struct drm_encoder_funcs) {
-		.destroy = nv04_tv_destroy,
-	};
-
 	*hfuncs = (struct drm_encoder_helper_funcs) {
 	*hfuncs = (struct drm_encoder_helper_funcs) {
 		.dpms = nv04_tv_dpms,
 		.dpms = nv04_tv_dpms,
 		.save = sfuncs->save,
 		.save = sfuncs->save,
@@ -292,14 +242,17 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
 		.detect = sfuncs->detect,
 		.detect = sfuncs->detect,
 	};
 	};
 
 
-	/* Set the slave encoder configuration */
-	sfuncs->set_config(encoder, nv04_tv_encoder_info[type].params);
+	/* Attach it to the specified connector. */
+	sfuncs->set_config(encoder, nv04_tv_encoder_info[type].platform_data);
+	sfuncs->create_resources(encoder, connector);
+	drm_mode_connector_attach_encoder(connector, encoder);
 
 
 	return 0;
 	return 0;
 
 
-fail:
+fail_cleanup:
 	drm_encoder_cleanup(encoder);
 	drm_encoder_cleanup(encoder);
-
+	kfree(hfuncs);
+fail_free:
 	kfree(nv_encoder);
 	kfree(nv_encoder);
 	return ret;
 	return ret;
 }
 }

+ 0 - 10
drivers/gpu/drm/nouveau/nv10_fifo.c

@@ -55,7 +55,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan)
 	/* Fill entries that are seen filled in dumps of nvidia driver just
 	/* Fill entries that are seen filled in dumps of nvidia driver just
 	 * after channel's is put into DMA mode
 	 * after channel's is put into DMA mode
 	 */
 	 */
-	dev_priv->engine.instmem.prepare_access(dev, true);
 	nv_wi32(dev, fc +  0, chan->pushbuf_base);
 	nv_wi32(dev, fc +  0, chan->pushbuf_base);
 	nv_wi32(dev, fc +  4, chan->pushbuf_base);
 	nv_wi32(dev, fc +  4, chan->pushbuf_base);
 	nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4);
 	nv_wi32(dev, fc + 12, chan->pushbuf->instance >> 4);
@@ -66,7 +65,6 @@ nv10_fifo_create_context(struct nouveau_channel *chan)
 			      NV_PFIFO_CACHE1_BIG_ENDIAN |
 			      NV_PFIFO_CACHE1_BIG_ENDIAN |
 #endif
 #endif
 			      0);
 			      0);
-	dev_priv->engine.instmem.finish_access(dev);
 
 
 	/* enable the fifo dma operation */
 	/* enable the fifo dma operation */
 	nv_wr32(dev, NV04_PFIFO_MODE,
 	nv_wr32(dev, NV04_PFIFO_MODE,
@@ -91,8 +89,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid)
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	uint32_t fc = NV10_RAMFC(chid), tmp;
 	uint32_t fc = NV10_RAMFC(chid), tmp;
 
 
-	dev_priv->engine.instmem.prepare_access(dev, false);
-
 	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
 	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_PUT, nv_ri32(dev, fc + 0));
 	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
 	nv_wr32(dev, NV04_PFIFO_CACHE1_DMA_GET, nv_ri32(dev, fc + 4));
 	nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8));
 	nv_wr32(dev, NV10_PFIFO_CACHE1_REF_CNT, nv_ri32(dev, fc + 8));
@@ -117,8 +113,6 @@ nv10_fifo_do_load_context(struct drm_device *dev, int chid)
 	nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48));
 	nv_wr32(dev, NV10_PFIFO_CACHE1_DMA_SUBROUTINE, nv_ri32(dev, fc + 48));
 
 
 out:
 out:
-	dev_priv->engine.instmem.finish_access(dev);
-
 	nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_GET, 0);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_PUT, 0);
 }
 }
@@ -155,8 +149,6 @@ nv10_fifo_unload_context(struct drm_device *dev)
 		return 0;
 		return 0;
 	fc = NV10_RAMFC(chid);
 	fc = NV10_RAMFC(chid);
 
 
-	dev_priv->engine.instmem.prepare_access(dev, true);
-
 	nv_wi32(dev, fc +  0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
 	nv_wi32(dev, fc +  0, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_PUT));
 	nv_wi32(dev, fc +  4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
 	nv_wi32(dev, fc +  4, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
 	nv_wi32(dev, fc +  8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT));
 	nv_wi32(dev, fc +  8, nv_rd32(dev, NV10_PFIFO_CACHE1_REF_CNT));
@@ -179,8 +171,6 @@ nv10_fifo_unload_context(struct drm_device *dev)
 	nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
 	nv_wi32(dev, fc + 48, nv_rd32(dev, NV04_PFIFO_CACHE1_DMA_GET));
 
 
 out:
 out:
-	dev_priv->engine.instmem.finish_access(dev);
-
 	nv10_fifo_do_load_context(dev, pfifo->channels - 1);
 	nv10_fifo_do_load_context(dev, pfifo->channels - 1);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
 	nv_wr32(dev, NV03_PFIFO_CACHE1_PUSH1, pfifo->channels - 1);
 	return 0;
 	return 0;

+ 2 - 2
drivers/gpu/drm/nouveau/nv17_gpio.c → drivers/gpu/drm/nouveau/nv10_gpio.c

@@ -55,7 +55,7 @@ get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift,
 }
 }
 
 
 int
 int
-nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
+nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
 {
 {
 	struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
 	struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
 	uint32_t reg, shift, mask, value;
 	uint32_t reg, shift, mask, value;
@@ -72,7 +72,7 @@ nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag)
 }
 }
 
 
 int
 int
-nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
+nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state)
 {
 {
 	struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
 	struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag);
 	uint32_t reg, shift, mask, value;
 	uint32_t reg, shift, mask, value;

+ 50 - 15
drivers/gpu/drm/nouveau/nv17_tv.c

@@ -37,6 +37,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
 {
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_device *dev = encoder->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
 	uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
 	uint32_t testval, regoffset = nv04_dac_output_offset(encoder);
 	uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
 	uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end,
 		fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
 		fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c;
@@ -52,8 +53,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
 	head = (dacclk & 0x100) >> 8;
 	head = (dacclk & 0x100) >> 8;
 
 
 	/* Save the previous state. */
 	/* Save the previous state. */
-	gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1);
-	gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0);
+	gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1);
+	gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0);
 	fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
 	fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL);
 	fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
 	fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START);
 	fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
 	fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END);
@@ -64,8 +65,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
 	ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);
 	ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c);
 
 
 	/* Prepare the DAC for load detection.  */
 	/* Prepare the DAC for load detection.  */
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true);
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true);
+	gpio->set(dev, DCB_GPIO_TVDAC1, true);
+	gpio->set(dev, DCB_GPIO_TVDAC0, true);
 
 
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343);
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047);
@@ -110,12 +111,27 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end);
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start);
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal);
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1);
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0);
+	gpio->set(dev, DCB_GPIO_TVDAC1, gpio1);
+	gpio->set(dev, DCB_GPIO_TVDAC0, gpio0);
 
 
 	return sample;
 	return sample;
 }
 }
 
 
+static bool
+get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask)
+{
+	/* Zotac FX5200 */
+	if (dev->pdev->device == 0x0322 &&
+	    dev->pdev->subsystem_vendor == 0x19da &&
+	    (dev->pdev->subsystem_device == 0x1035 ||
+	     dev->pdev->subsystem_device == 0x2035)) {
+		*pin_mask = 0xc;
+		return false;
+	}
+
+	return true;
+}
+
 static enum drm_connector_status
 static enum drm_connector_status
 nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 {
 {
@@ -124,12 +140,20 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 	struct drm_mode_config *conf = &dev->mode_config;
 	struct drm_mode_config *conf = &dev->mode_config;
 	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder);
 	struct dcb_entry *dcb = tv_enc->base.dcb;
 	struct dcb_entry *dcb = tv_enc->base.dcb;
+	bool reliable = get_tv_detect_quirks(dev, &tv_enc->pin_mask);
 
 
-	if (dev_priv->chipset == 0x42 ||
-	    dev_priv->chipset == 0x43)
-		tv_enc->pin_mask = nv42_tv_sample_load(encoder) >> 28 & 0xe;
-	else
-		tv_enc->pin_mask = nv17_dac_sample_load(encoder) >> 28 & 0xe;
+	if (nv04_dac_in_use(encoder))
+		return connector_status_disconnected;
+
+	if (reliable) {
+		if (dev_priv->chipset == 0x42 ||
+		    dev_priv->chipset == 0x43)
+			tv_enc->pin_mask =
+				nv42_tv_sample_load(encoder) >> 28 & 0xe;
+		else
+			tv_enc->pin_mask =
+				nv17_dac_sample_load(encoder) >> 28 & 0xe;
+	}
 
 
 	switch (tv_enc->pin_mask) {
 	switch (tv_enc->pin_mask) {
 	case 0x2:
 	case 0x2:
@@ -154,7 +178,9 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector)
 					 conf->tv_subconnector_property,
 					 conf->tv_subconnector_property,
 					 tv_enc->subconnector);
 					 tv_enc->subconnector);
 
 
-	if (tv_enc->subconnector) {
+	if (!reliable) {
+		return connector_status_unknown;
+	} else if (tv_enc->subconnector) {
 		NV_INFO(dev, "Load detected on output %c\n",
 		NV_INFO(dev, "Load detected on output %c\n",
 			'@' + ffs(dcb->or));
 			'@' + ffs(dcb->or));
 		return connector_status_connected;
 		return connector_status_connected;
@@ -296,6 +322,9 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
 {
 {
 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 
 
+	if (nv04_dac_in_use(encoder))
+		return false;
+
 	if (tv_norm->kind == CTV_ENC_MODE)
 	if (tv_norm->kind == CTV_ENC_MODE)
 		adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock;
 		adjusted_mode->clock = tv_norm->ctv_enc_mode.mode.clock;
 	else
 	else
@@ -307,6 +336,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder,
 static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode)
 static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode)
 {
 {
 	struct drm_device *dev = encoder->dev;
 	struct drm_device *dev = encoder->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio;
 	struct nv17_tv_state *regs = &to_tv_enc(encoder)->state;
 	struct nv17_tv_state *regs = &to_tv_enc(encoder)->state;
 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
 
 
@@ -331,8 +362,8 @@ static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode)
 
 
 	nv_load_ptv(dev, regs, 200);
 	nv_load_ptv(dev, regs, 200);
 
 
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON);
-	nv17_gpio_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON);
+	gpio->set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON);
+	gpio->set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON);
 
 
 	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
 	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);
 }
 }
@@ -744,8 +775,10 @@ static struct drm_encoder_funcs nv17_tv_funcs = {
 	.destroy = nv17_tv_destroy,
 	.destroy = nv17_tv_destroy,
 };
 };
 
 
-int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
+int
+nv17_tv_create(struct drm_connector *connector, struct dcb_entry *entry)
 {
 {
+	struct drm_device *dev = connector->dev;
 	struct drm_encoder *encoder;
 	struct drm_encoder *encoder;
 	struct nv17_tv_encoder *tv_enc = NULL;
 	struct nv17_tv_encoder *tv_enc = NULL;
 
 
@@ -774,5 +807,7 @@ int nv17_tv_create(struct drm_device *dev, struct dcb_entry *entry)
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_crtcs = entry->heads;
 	encoder->possible_clones = 0;
 	encoder->possible_clones = 0;
 
 
+	nv17_tv_create_resources(encoder, connector);
+	drm_mode_connector_attach_encoder(connector, encoder);
 	return 0;
 	return 0;
 }
 }

Some files were not shown because too many files changed in this diff