Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 65c25aad authored by Eric Anholt's avatar Eric Anholt Committed by Dave Jones
Browse files

[AGPGART] Intel 965 Express support.



From: Alan Hourihane <alanh@tungstengraphics.com>
From: Eric Anholt <eric@anholt.net>
Signed-off-by: default avatarDave Jones <davej@redhat.com>
parent 115b384c
Loading
Loading
Loading
Loading
+152 −11
Original line number Diff line number Diff line
@@ -2,14 +2,6 @@
 * Intel AGPGART routines.
 */

/*
 * Intel(R) 855GM/852GM and 865G support added by David Dawes
 * <dawes@tungstengraphics.com>.
 *
 * Intel(R) 915G/915GM support added by Alan Hourihane
 * <alanh@tungstengraphics.com>.
 */

#include <linux/module.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -17,6 +9,21 @@
#include <linux/agp_backend.h>
#include "agp.h"

#define PCI_DEVICE_ID_INTEL_82946GZ_HB      0x2970
#define PCI_DEVICE_ID_INTEL_82946GZ_IG      0x2972
#define PCI_DEVICE_ID_INTEL_82965G_1_HB     0x2980
#define PCI_DEVICE_ID_INTEL_82965G_1_IG     0x2982
#define PCI_DEVICE_ID_INTEL_82965Q_HB       0x2990
#define PCI_DEVICE_ID_INTEL_82965Q_IG       0x2992
#define PCI_DEVICE_ID_INTEL_82965G_HB       0x29A0
#define PCI_DEVICE_ID_INTEL_82965G_IG       0x29A2

#define IS_I965 (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82946GZ_HB || \
                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_1_HB || \
                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965Q_HB || \
                 agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82965G_HB)


/* Intel 815 register */
#define INTEL_815_APCONT	0x51
#define INTEL_815_ATTBASE_MASK	~0x1FFFFFFF
@@ -40,6 +47,8 @@
#define I915_GMCH_GMS_STOLEN_48M	(0x6 << 4)
#define I915_GMCH_GMS_STOLEN_64M	(0x7 << 4)

/* Intel 965G registers */
#define I965_MSAC 0x62

/* Intel 7505 registers */
#define INTEL_I7505_APSIZE	0x74
@@ -354,6 +363,7 @@ static struct aper_size_info_fixed intel_i830_sizes[] =
	/* The 64M mode still requires a 128k gatt */
	{64, 16384, 5},
	{256, 65536, 6},
	{512, 131072, 7},
};

static struct _intel_i830_private {
@@ -377,6 +387,10 @@ static void intel_i830_init_gtt_entries(void)
	/* We obtain the size of the GTT, which is also stored (for some
	 * reason) at the top of stolen memory. Then we add 4KB to that
	 * for the video BIOS popup, which is also stored in there. */

	if (IS_I965)
		size = 512 + 4;
	else
		size = agp_bridge->driver->fetch_size() + 4;

	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
@@ -423,7 +437,7 @@ static void intel_i830_init_gtt_entries(void)
			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB)
			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965 )
				gtt_entries = MB(48) - KB(size);
			else
				gtt_entries = 0;
@@ -433,7 +447,7 @@ static void intel_i830_init_gtt_entries(void)
			if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB ||
			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB)
			    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945GM_HB || IS_I965)
				gtt_entries = MB(64) - KB(size);
			else
				gtt_entries = 0;
@@ -791,6 +805,77 @@ static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)

	return 0;
}
static int intel_i965_fetch_size(void)
{
       struct aper_size_info_fixed *values;
       u32 offset = 0;
       u8 temp;

#define I965_512MB_ADDRESS_MASK (3<<1)

       values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);

       pci_read_config_byte(intel_i830_private.i830_dev, I965_MSAC, &temp);
       temp &= I965_512MB_ADDRESS_MASK;
       switch (temp) {
       case 0x00:
               offset = 0; /* 128MB */
               break;
       case 0x06:
               offset = 3; /* 512MB */
               break;
       default:
       case 0x02:
               offset = 2; /* 256MB */
               break;
       }

       agp_bridge->previous_size = agp_bridge->current_size = (void *)(values + offset);

       return values[offset].size;
}

/* The intel i965 automatically initializes the agp aperture during POST.
+ * Use the memory already set aside for in the GTT.
+ */
static int intel_i965_create_gatt_table(struct agp_bridge_data *bridge)
{
       int page_order;
       struct aper_size_info_fixed *size;
       int num_entries;
       u32 temp;

       size = agp_bridge->current_size;
       page_order = size->page_order;
       num_entries = size->num_entries;
       agp_bridge->gatt_table_real = NULL;

       pci_read_config_dword(intel_i830_private.i830_dev, I915_MMADDR, &temp);

       temp &= 0xfff00000;
       intel_i830_private.gtt = ioremap((temp + (512 * 1024)) , 512 * 1024);

       if (!intel_i830_private.gtt)
               return -ENOMEM;


       intel_i830_private.registers = ioremap(temp,128 * 4096);
       if (!intel_i830_private.registers)
               return -ENOMEM;

       temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
       global_cache_flush();   /* FIXME: ? */

       /* we have to call this as early as possible after the MMIO base address is known */
       intel_i830_init_gtt_entries();

       agp_bridge->gatt_table = NULL;

       agp_bridge->gatt_bus_addr = temp;

       return 0;
}


static int intel_fetch_size(void)
{
@@ -1489,6 +1574,29 @@ static struct agp_bridge_driver intel_915_driver = {
	.agp_destroy_page	= agp_generic_destroy_page,
};

static struct agp_bridge_driver intel_i965_driver = {
       .owner                  = THIS_MODULE,
       .aperture_sizes         = intel_i830_sizes,
       .size_type              = FIXED_APER_SIZE,
       .num_aperture_sizes     = 4,
       .needs_scratch_page     = TRUE,
       .configure              = intel_i915_configure,
       .fetch_size             = intel_i965_fetch_size,
       .cleanup                = intel_i915_cleanup,
       .tlb_flush              = intel_i810_tlbflush,
       .mask_memory            = intel_i810_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_destroy_page       = agp_generic_destroy_page,
};

static struct agp_bridge_driver intel_7505_driver = {
	.owner			= THIS_MODULE,
@@ -1684,6 +1792,35 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
			bridge->driver = &intel_845_driver;
		name = "945GM";
		break;
	case PCI_DEVICE_ID_INTEL_82946GZ_HB:
		if (find_i830(PCI_DEVICE_ID_INTEL_82946GZ_IG))
			bridge->driver = &intel_i965_driver;
		else
			bridge->driver = &intel_845_driver;
		name = "946GZ";
		break;
	case PCI_DEVICE_ID_INTEL_82965G_1_HB:
		if (find_i830(PCI_DEVICE_ID_INTEL_82965G_1_IG))
			bridge->driver = &intel_i965_driver;
		else
			bridge->driver = &intel_845_driver;
		name = "965G";
		break;
	case PCI_DEVICE_ID_INTEL_82965Q_HB:
		if (find_i830(PCI_DEVICE_ID_INTEL_82965Q_IG))
			bridge->driver = &intel_i965_driver;
		else
			bridge->driver = &intel_845_driver;
		name = "965Q";
		break;
	case PCI_DEVICE_ID_INTEL_82965G_HB:
		if (find_i830(PCI_DEVICE_ID_INTEL_82965G_IG))
			bridge->driver = &intel_i965_driver;
		else
			bridge->driver = &intel_845_driver;
		name = "965G";
		break;

	case PCI_DEVICE_ID_INTEL_7505_0:
		bridge->driver = &intel_7505_driver;
		name = "E7505";
@@ -1827,6 +1964,10 @@ static struct pci_device_id agp_intel_pci_table[] = {
	ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
	ID(PCI_DEVICE_ID_INTEL_82945G_HB),
	ID(PCI_DEVICE_ID_INTEL_82945GM_HB),
	ID(PCI_DEVICE_ID_INTEL_82946GZ_HB),
	ID(PCI_DEVICE_ID_INTEL_82965G_1_HB),
	ID(PCI_DEVICE_ID_INTEL_82965Q_HB),
	ID(PCI_DEVICE_ID_INTEL_82965G_HB),
	{ }
};