Add i915 AGP support

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Add i915 AGP support

dimitry (Bugzilla)
Here is a patch for -current to add AGP support for the Intel i915
video chipset.  It's adapted from FreeBSD, with some minor changes.
This allows X.org to run on this chipset with the hardware
accelerated i810(4) driver.

I have tested this patch on my ThinkPad X41 notebook, and everything
seems to work correctly.  It should also work for other machines with
this chipset, obviously.  Please let me know if it does.

If needed, I can also post a dmesg and a full X.org logfile.

Cheers,
Dimitry

Index: sys/arch/i386/pci/agp_machdep.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/pci/agp_machdep.c,v
retrieving revision 1.3
diff -u -d -p -r1.3 agp_machdep.c
--- sys/arch/i386/pci/agp_machdep.c 20 Jan 2004 19:30:40 -0000 1.3
+++ sys/arch/i386/pci/agp_machdep.c 11 Jan 2006 19:00:21 -0000
@@ -47,6 +47,8 @@ const struct agp_product agp_products[]
  { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82845G_IGD, agp_i810_attach },
  { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82852GM_AGP, agp_i810_attach },
  { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82865_IGD, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82915G_IV, agp_i810_attach },
+ { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_82915GM_IGD, agp_i810_attach },
  { PCI_VENDOR_INTEL, -1, agp_intel_attach },
  { PCI_VENDOR_SIS, -1, agp_sis_attach },
  { PCI_VENDOR_VIATECH, -1, agp_via_attach },
Index: sys/dev/pci/agp_i810.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/agp_i810.c,v
retrieving revision 1.8
diff -u -d -p -r1.8 agp_i810.c
--- sys/dev/pci/agp_i810.c 22 Mar 2005 18:33:03 -0000 1.8
+++ sys/dev/pci/agp_i810.c 11 Jan 2006 19:00:22 -0000
@@ -53,10 +53,22 @@
 #define READ1(off) bus_space_read_1(isc->bst, isc->bsh, off)
 #define READ4(off) bus_space_read_4(isc->bst, isc->bsh, off)
 #define WRITE4(off,v) bus_space_write_4(isc->bst, isc->bsh, off, v)
+#define WRITEGTT(off,v) bus_space_write_4(isc->gtt_bst, isc->gtt_bsh, off, v)
 
 #define CHIP_I810 0 /* i810/i815 */
 #define CHIP_I830 1 /* i830/i845 */
 #define CHIP_I855 2 /* i852GM/i855GM/i865G */
+#define CHIP_I915 3 /* i915G/i915GM */
+
+#define WRITE_GATT(off,v)   \
+ do {   \
+ if (isc->chiptype == CHIP_I915)   \
+ WRITEGTT((u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, \
+    v);   \
+ else   \
+ WRITE4(AGP_I810_GTT +   \
+    (u_int32_t)((off) >> AGP_PAGE_SHIFT) * 4, v);  \
+ } while (0)
 
 struct agp_i810_softc {
  struct agp_gatt *gatt;
@@ -66,6 +78,8 @@ struct agp_i810_softc {
    for stolen memory */
  bus_space_tag_t bst; /* bus_space tag */
  bus_space_handle_t bsh; /* bus_space handle */
+ bus_space_tag_t gtt_bst; /* GATT bus_space tag */
+ bus_space_handle_t gtt_bsh; /* GATT bus_space handle */
  struct pci_attach_args bridge_pa;
 };
 
@@ -134,15 +148,31 @@ agp_i810_attach(struct vga_pci_softc *sc
  case PCI_PRODUCT_INTEL_82865_IGD:
  isc->chiptype = CHIP_I855;
  break;
+ case PCI_PRODUCT_INTEL_82915G_IV:
+ case PCI_PRODUCT_INTEL_82915GM_IGD:
+ isc->chiptype = CHIP_I915;
+ break;
  }
 
- error = pci_mapreg_map(pa, AGP_I810_MMADR,
+ error = pci_mapreg_map(pa,
+    (isc->chiptype == CHIP_I915) ? AGP_I915_MMADR : AGP_I810_MMADR,
     PCI_MAPREG_TYPE_MEM, 0, &isc->bst, &isc->bsh, NULL, NULL, 0);
  if (error != 0) {
  printf(": can't map mmadr registers\n");
+ agp_generic_detach(sc);
  return (error);
  }
 
+ if (isc->chiptype == CHIP_I915) {
+ error = pci_mapreg_map(pa, AGP_I915_GTTADR, PCI_MAPREG_TYPE_MEM,
+    0, &isc->gtt_bst, &isc->gtt_bsh, NULL, NULL, 0);
+ if (error != 0) {
+ printf(": can't map gatt registers\n");
+ agp_generic_detach(sc);
+ return (error);
+ }
+ }
+
  gatt = malloc(sizeof(struct agp_gatt), M_DEVBUF, M_NOWAIT);
  if (!gatt) {
  agp_generic_detach(sc);
@@ -214,30 +244,42 @@ agp_i810_attach(struct vga_pci_softc *sc
  WRITE4(AGP_I810_PGTBL_CTL, pgtblctl);
 
  gatt->ag_physical = pgtblctl & ~1;
- } else { /* CHIP_I855 */
+ } else if (isc->chiptype == CHIP_I855 || isc->chiptype == CHIP_I915) {
  /* The 855GM automatically initializes the 128k gatt on boot. */
+ u_int32_t stolen;
  pcireg_t reg;
  u_int32_t pgtblctl;
  u_int16_t gcc1;
 
+ if (isc->chiptype == CHIP_I855)
+ stolen = 132;
+ else
+ stolen = 260;
+
  reg = pci_conf_read(isc->bridge_pa.pa_pc,
     isc->bridge_pa.pa_tag, AGP_I855_GCC1);
  gcc1 = (u_int16_t)(reg >> 16);
  switch (gcc1 & AGP_I855_GCC1_GMS) {
  case AGP_I855_GCC1_GMS_STOLEN_1M:
- isc->stolen = (1024 - 132) * 1024 / 4096;
+ isc->stolen = (1024 - stolen) * 1024 / 4096;
  break;
  case AGP_I855_GCC1_GMS_STOLEN_4M:
- isc->stolen = (4096 - 132) * 1024 / 4096;
+ isc->stolen = (4096 - stolen) * 1024 / 4096;
  break;
  case AGP_I855_GCC1_GMS_STOLEN_8M:
- isc->stolen = (8192 - 132) * 1024 / 4096;
+ isc->stolen = (8192 - stolen) * 1024 / 4096;
  break;
  case AGP_I855_GCC1_GMS_STOLEN_16M:
- isc->stolen = (16384 - 132) * 1024 / 4096;
+ isc->stolen = (16384 - stolen) * 1024 / 4096;
  break;
  case AGP_I855_GCC1_GMS_STOLEN_32M:
- isc->stolen = (32768 - 132) * 1024 / 4096;
+ isc->stolen = (32768 - stolen) * 1024 / 4096;
+ break;
+ case AGP_I915_GCC1_GMS_STOLEN_48M:
+ isc->stolen = (49152 - stolen) * 1024 / 4096;
+ break;
+ case AGP_I915_GCC1_GMS_STOLEN_64M:
+ isc->stolen = (65536 - stolen) * 1024 / 4096;
  break;
  default:
  isc->stolen = 0;
@@ -296,9 +338,19 @@ agp_i810_get_aperture(struct vga_pci_sof
  return (64 * 1024 * 1024);
  else
  return (128 * 1024 * 1024);
- } else { /* CHIP_I855 */
+ } else if (isc->chiptype == CHIP_I855) {
  return (128 * 1024 * 1024);
+ } else if (isc->chiptype == CHIP_I915) {
+ reg = pci_conf_read(isc->bridge_pa.pa_pc,
+    isc->bridge_pa.pa_tag, AGP_I915_MSAC);
+ if ((reg & AGP_I915_MSAC_GMASIZE) == AGP_I915_MSAC_GMASIZE_128) {
+ return (128 * 1024 * 1024);
+ } else {
+ return (256 * 1024 * 1024);
+ }
  }
+
+ return 0;
 }
 
 int
@@ -353,11 +405,26 @@ agp_i810_set_aperture(struct vga_pci_sof
  reg |= ((pcireg_t)gcc1) << 16;
  pci_conf_write(isc->bridge_pa.pa_pc,
     isc->bridge_pa.pa_tag, AGP_I830_GCC0, reg);
- } else { /* CHIP_I855 */
+ } else if (isc->chiptype == CHIP_I855) {
  if (aperture != (128 * 1024 * 1024)) {
  printf("agp: bad aperture size %d\n", aperture);
  return (EINVAL);
  }
+ } else if (isc->chiptype == CHIP_I915) {
+ if (aperture != (128 * 1024 * 1024) &&
+    aperture != (256 * 1024 * 1024)) {
+ printf("agp: bad aperture size %d\n", aperture);
+ return (EINVAL);
+ }
+ reg = pci_conf_read(isc->bridge_pa.pa_pc,
+    isc->bridge_pa.pa_tag, AGP_I915_MSAC);
+ reg &= ~AGP_I915_MSAC_GMASIZE;
+ if (aperture == (128 * 1024 * 1024))
+ reg |= AGP_I915_MSAC_GMASIZE_128;
+ else
+ reg |= AGP_I915_MSAC_GMASIZE_256;
+ pci_conf_write(isc->bridge_pa.pa_pc,
+    isc->bridge_pa.pa_tag, AGP_I915_MSAC, reg);
  }
 
  return (0);
@@ -386,8 +453,7 @@ agp_i810_bind_page(struct vga_pci_softc
  }
  }
 
- WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
-    physical | 1);
+ WRITE_GATT(offset, physical | 1);
  return (0);
 }
 
@@ -408,7 +474,7 @@ agp_i810_unbind_page(struct vga_pci_soft
  }
  }
 
- WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4, 0);
+ WRITE_GATT(offset, 0);
  return (0);
 }
 
@@ -449,10 +515,12 @@ agp_i810_alloc_memory(struct vga_pci_sof
  return (NULL);
  } else if (type == 2) {
  /*
- * Bogus mapping of a single page for the hardware cursor.
+ * Bogus mapping of 1 or 4 pages for the hardware cursor.
  */
- if (size != AGP_PAGE_SIZE)
+ if (size != AGP_PAGE_SIZE && size != 4 * AGP_PAGE_SIZE) {
+ printf("agp: trying to map %lu for hw cursor\n", size);
  return (NULL);
+ }
  }
 
  mem = malloc(sizeof *mem, M_DEVBUF, M_WAITOK);
@@ -538,8 +606,7 @@ agp_i810_bind_memory(struct vga_pci_soft
  }
 
  if (mem->am_type == 2) {
- WRITE4(AGP_I810_GTT + (u_int32_t)(offset >> AGP_PAGE_SHIFT) * 4,
-    mem->am_physical | 1);
+ WRITE_GATT(offset, mem->am_physical | 1);
  mem->am_offset = offset;
  mem->am_is_bound = 1;
  return (0);
@@ -566,8 +633,7 @@ agp_i810_unbind_memory(struct vga_pci_so
  u_int32_t i;
 
  if (mem->am_type == 2) {
- WRITE4(AGP_I810_GTT +
-    (u_int32_t)(mem->am_offset >> AGP_PAGE_SHIFT) * 4, 0);
+ WRITE_GATT(mem->am_offset, 0);
  mem->am_offset = 0;
  mem->am_is_bound = 0;
  return (0);
Index: sys/dev/pci/agpreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/agpreg.h,v
retrieving revision 1.3
diff -u -d -p -r1.3 agpreg.h
--- sys/dev/pci/agpreg.h 20 Jan 2004 19:30:41 -0000 1.3
+++ sys/dev/pci/agpreg.h 11 Jan 2006 19:00:22 -0000
@@ -186,4 +186,21 @@
 #define AGP_I855_GCC1_GMS_STOLEN_16M 0x40
 #define AGP_I855_GCC1_GMS_STOLEN_32M 0x50
 
+/*
+ * 915G registers
+ */
+#define AGP_I915_GMADR 0x18
+#define AGP_I915_MMADR 0x10
+#define AGP_I915_GTTADR 0x1C
+#define AGP_I915_GCC1_GMS_STOLEN_48M 0x60
+#define AGP_I915_GCC1_GMS_STOLEN_64M 0x70
+#define AGP_I915_DEVEN 0x54
+#define AGP_I915_DEVEN_D2F0 0x08
+#define AGP_I915_DEVEN_D2F0_ENABLED 0x08
+#define AGP_I915_DEVEN_D2F0_DISABLED 0x00
+#define AGP_I915_MSAC 0x62
+#define AGP_I915_MSAC_GMASIZE 0x02
+#define AGP_I915_MSAC_GMASIZE_128 0x02
+#define AGP_I915_MSAC_GMASIZE_256 0x00
+
 #endif /* !_PCI_AGPREG_H_ */