A few months ago jcs@ got a sandybridge laptop, he did some work to get
it almost working. I continued this a few months ago in edmonton at
c2k11. Since then kettenis@ who has hardware has made yet more progress.
Now the plan is to get this into the tree, but first some precursors.
This kernel patch is just the very basic bits needed to get sandybridge
working, the extra ringsbuffers (BSD, blit) are not in this patch (I
have half to 2/3 of a diff for that). Nor are the requisit xserver bits.
For now some extra testing is required to make sure these patches don't
break any existing setups so that they can go in and work can progress.
So please mail me and kettenis@ privately if this patch regresses your
inteldrm(4) using hardware. Reports that this does nothing other than
attach for sandybridge right now are not necessary. We know.
Cheers,
-0-
--
It took me fifteen years to discover that I had no talent for writing,
but I couldn't give up because by that time I was too famous.
-- Robert Benchley
diff --git dev/pci/agp_i810.c dev/pci/agp_i810.c
index 41b9189..b62610e 100644
--- dev/pci/agp_i810.c
+++ dev/pci/agp_i810.c
@@ -71,6 +71,7 @@ enum {
CHIP_G4X = 7, /* G4X */
CHIP_PINEVIEW = 8, /* Pineview/Pineview M */
CHIP_IRONLAKE = 9, /* Clarkdale/Arrandale */
+ CHIP_SANDYBRIDGE=10, /* Sandybridge */
};
struct agp_i810_softc {
@@ -183,13 +184,23 @@ agp_i810_get_chiptype(struct pci_attach_args *pa)
case PCI_PRODUCT_INTEL_82G45_IGD_1:
case PCI_PRODUCT_INTEL_82G41_IGD_1:
return (CHIP_G4X);
+ break;
case PCI_PRODUCT_INTEL_PINEVIEW_IGC_1:
case PCI_PRODUCT_INTEL_PINEVIEW_M_IGC_1:
return (CHIP_PINEVIEW);
+ break;
case PCI_PRODUCT_INTEL_CLARKDALE_IGD:
case PCI_PRODUCT_INTEL_ARRANDALE_IGD:
return (CHIP_IRONLAKE);
break;
+ case PCI_PRODUCT_INTEL_CORE2G_GT1:
+ case PCI_PRODUCT_INTEL_CORE2G_M_GT1:
+ case PCI_PRODUCT_INTEL_CORE2G_GT2:
+ case PCI_PRODUCT_INTEL_CORE2G_M_GT2:
+ case PCI_PRODUCT_INTEL_CORE2G_GT2_PLUS:
+ case PCI_PRODUCT_INTEL_CORE2G_M_GT2_PLUS:
+ return (CHIP_SANDYBRIDGE);
+ break;
}
return (CHIP_NONE);
}
@@ -246,6 +257,7 @@ agp_i810_attach(struct device *parent, struct device *self,
void *aux)
case CHIP_I965:
case CHIP_G4X:
case CHIP_IRONLAKE:
+ case CHIP_SANDYBRIDGE:
gmaddr = AGP_I965_GMADR;
mmaddr = AGP_I965_MMADR;
memtype = PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT;
@@ -477,6 +489,85 @@ agp_i810_attach(struct device *parent, struct device
*self, void *aux)
gatt->ag_physical = READ4(AGP_I810_PGTBL_CTL) & ~1;
break;
+ case CHIP_SANDYBRIDGE:
+
+ /* Stolen memory is set up at the beginning of the aperture by
+ * the BIOS, consisting of the GATT followed by 4kb for the
+ * BIOS display.
+ */
+
+ gcc1 = (u_int16_t)pci_conf_read(bpa.pa_pc, bpa.pa_tag,
+ AGP_INTEL_SNB_GMCH_CTRL);
+
+ stolen = 4;
+
+ switch (gcc1 & AGP_INTEL_SNB_GMCH_GMS_STOLEN_MASK) {
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_32M:
+ isc->stolen = (32768 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_64M:
+ isc->stolen = (65536 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_96M:
+ isc->stolen = (98304 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_128M:
+ isc->stolen = (131072 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_160M:
+ isc->stolen = (163840 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_192M:
+ isc->stolen = (196608 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_224M:
+ isc->stolen = (229376 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_256M:
+ isc->stolen = (262144 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_288M:
+ isc->stolen = (294912 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_320M:
+ isc->stolen = (327680 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_352M:
+ isc->stolen = (360448 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_384M:
+ isc->stolen = (393216 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_416M:
+ isc->stolen = (425984 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_448M:
+ isc->stolen = (458752 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_480M:
+ isc->stolen = (491520 - stolen) * 1024 / 4096;
+ break;
+ case AGP_INTEL_SNB_GMCH_GMS_STOLEN_512M:
+ isc->stolen = (524288 - stolen) * 1024 / 4096;
+ break;
+ default:
+ isc->stolen = 0;
+ printf("unknown memory configuration, disabling\n");
+ goto out;
+ }
+
+#ifdef DEBUG
+ if (isc->stolen > 0) {
+ printf(": detected %dk stolen memory",
+ isc->stolen * 4);
+ } else
+ printf(": no preallocated video memory\n");
+#endif
+
+ /* GATT address is already in there, make sure it's enabled */
+ gatt->ag_physical = READ4(AGP_I810_PGTBL_CTL) & ~1;
+ break;
+
default:
printf(": unknown initialisation\n");
return;
@@ -532,6 +623,7 @@ agp_i810_activate(struct device *arg, int act)
break;
case CHIP_G4X:
case CHIP_IRONLAKE:
+ case CHIP_SANDYBRIDGE:
offset = AGP_G4X_GTT;
break;
default:
@@ -833,7 +925,8 @@ intagp_write_gtt(struct agp_i810_softc *isc, bus_size_t
off, paddr_t v)
if (isc->chiptype != CHIP_I810 &&
(off >> AGP_PAGE_SHIFT) < isc->stolen) {
- printf("intagp: binding into stolen memory!\n");
+ printf("intagp: binding into stolen memory! (0x%lx)\n",
+ (off >> AGP_PAGE_SHIFT));
}
if (v != 0) {
@@ -843,7 +936,8 @@ intagp_write_gtt(struct agp_i810_softc *isc, bus_size_t
off, paddr_t v)
isc->chiptype == CHIP_G4X ||
isc->chiptype == CHIP_PINEVIEW ||
isc->chiptype == CHIP_G33 ||
- isc->chiptype == CHIP_IRONLAKE) {
+ isc->chiptype == CHIP_IRONLAKE ||
+ isc->chiptype == CHIP_SANDYBRIDGE) {
pte |= (v & 0x0000000f00000000ULL) >> 28;
}
}
@@ -863,6 +957,7 @@ intagp_write_gtt(struct agp_i810_softc *isc, bus_size_t
off, paddr_t v)
break;
case CHIP_G4X:
case CHIP_IRONLAKE:
+ case CHIP_SANDYBRIDGE:
baseoff = AGP_G4X_GTT;
break;
default:
diff --git dev/pci/agpreg.h dev/pci/agpreg.h
index 4e3af78..47d5748 100644
--- dev/pci/agpreg.h
+++ dev/pci/agpreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD$ */
+/* $OpenBSD: agpreg.h,v 1.12 2008/12/24 05:42:58 oga Exp $ */
/* $NetBSD: agpreg.h,v 1.1 2001/09/10 10:01:02 fvdl Exp $ */
/*-
@@ -275,4 +275,26 @@
#define AGP_INTEL_GMCH_GMS_STOLEN_352M 0xd0
#define AGP_G4X_GTT 0x200000
+/*
+ * Intel Sandybridge registers and values
+ */
+#define AGP_INTEL_SNB_GMCH_CTRL 0x50
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_MASK 0xF8
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_32M (1 << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_64M (2 << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_96M (3 << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_128M (4 << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_160M (5 << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_192M (6 << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_224M (7 << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_256M (8 << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_288M (9 << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_320M (0xa << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_352M (0xb << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_384M (0xc << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_416M (0xd << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_448M (0xe << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_480M (0xf << 3)
+#define AGP_INTEL_SNB_GMCH_GMS_STOLEN_512M (0x10 << 3)
+
#endif /* !_PCI_AGPREG_H_ */
diff --git dev/pci/drm/i915_drv.c dev/pci/drm/i915_drv.c
index edb5f32..ab9cf34 100644
--- dev/pci/drm/i915_drv.c
+++ dev/pci/drm/i915_drv.c
@@ -194,6 +194,7 @@ bus_size_t i915_gem_get_gtt_alignment(struct drm_obj *);
bus_size_t i915_get_fence_size(struct inteldrm_softc *, bus_size_t);
int i915_tiling_ok(struct drm_device *, int, int, int);
int i915_gem_object_fence_offset_ok(struct drm_obj *, int);
+void sandybridge_write_fence_reg(struct inteldrm_fence *);
void i965_write_fence_reg(struct inteldrm_fence *);
void i915_write_fence_reg(struct inteldrm_fence *);
void i830_write_fence_reg(struct inteldrm_fence *);
@@ -272,6 +273,18 @@ const static struct drm_pcidev inteldrm_pciidlist[] = {
CHIP_IRONLAKE|CHIP_IRONLAKE_D|CHIP_I965|CHIP_I9XX|CHIP_HWS},
{PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_ARRANDALE_IGD,
CHIP_IRONLAKE|CHIP_M|CHIP_IRONLAKE_M|CHIP_I965|CHIP_I9XX|CHIP_HWS},
+ {PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE2G_GT1,
+ CHIP_SANDYBRIDGE|CHIP_I965|CHIP_I9XX|CHIP_HWS|CHIP_GEN6},
+ {PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE2G_M_GT1,
+ CHIP_SANDYBRIDGE|CHIP_M|CHIP_I965|CHIP_I9XX|CHIP_HWS|CHIP_GEN6},
+ {PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE2G_GT2,
+ CHIP_SANDYBRIDGE|CHIP_I965|CHIP_I9XX|CHIP_HWS|CHIP_GEN6},
+ {PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE2G_M_GT2,
+ CHIP_SANDYBRIDGE|CHIP_M|CHIP_I965|CHIP_I9XX|CHIP_HWS|CHIP_GEN6},
+ {PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE2G_GT2_PLUS,
+ CHIP_SANDYBRIDGE|CHIP_I965|CHIP_I9XX|CHIP_HWS|CHIP_GEN6},
+ {PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE2G_M_GT2_PLUS,
+ CHIP_SANDYBRIDGE|CHIP_M|CHIP_I965|CHIP_I9XX|CHIP_HWS|CHIP_GEN6},
{0, 0, 0}
};
@@ -434,8 +447,12 @@ inteldrm_attach(struct device *parent, struct device
*self, void *aux)
dev_priv->num_fence_regs = 16;
else
dev_priv->num_fence_regs = 8;
+
/* Initialise fences to zero, else on some macs we'll get corruption */
- if (IS_I965G(dev_priv)) {
+ if (IS_GEN6(dev_priv)) {
+ for (i = 0; i < 16; i++)
+ I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8), 0);
+ } else if (IS_I965G(dev_priv)) {
for (i = 0; i < 16; i++)
I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0);
} else {
@@ -1628,11 +1645,14 @@ i915_add_request(struct inteldrm_softc *dev_priv)
if (dev_priv->mm.next_gem_seqno == 0)
dev_priv->mm.next_gem_seqno++;
- BEGIN_LP_RING(4);
+ if (IS_GEN6(dev_priv))
+ BEGIN_LP_RING(10);
+ else
+ BEGIN_LP_RING(4);
+
OUT_RING(MI_STORE_DWORD_INDEX);
OUT_RING(I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
OUT_RING(seqno);
-
OUT_RING(MI_USER_INTERRUPT);
ADVANCE_LP_RING();
@@ -2130,6 +2150,28 @@ i915_gem_get_gtt_alignment(struct drm_obj *obj)
}
void
+sandybridge_write_fence_reg(struct inteldrm_fence *reg)
+{
+ struct drm_obj *obj = reg->obj;
+ struct drm_device *dev = obj->dev;
+ struct inteldrm_softc *dev_priv = dev->dev_private;
+ struct inteldrm_obj *obj_priv = (struct inteldrm_obj *)obj;
+ int regnum = obj_priv->fence_reg;
+ u_int64_t val;
+
+ val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
+ 0xfffff000) << 32;
+ val |= obj_priv->gtt_offset & 0xfffff000;
+ val |= (uint64_t)((obj_priv->stride / 128) - 1) <<
+ SANDYBRIDGE_FENCE_PITCH_SHIFT;
+ if (obj_priv->tiling_mode == I915_TILING_Y)
+ val |= 1 << I965_FENCE_TILING_Y_SHIFT;
+ val |= I965_FENCE_REG_VALID;
+
+ I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (regnum * 8), val);
+}
+
+void
i965_write_fence_reg(struct inteldrm_fence *reg)
{
struct drm_obj *obj = reg->obj;
@@ -2357,7 +2399,9 @@ again:
reg->obj = obj;
TAILQ_INSERT_TAIL(&dev_priv->mm.fence_list, reg, list);
- if (IS_I965G(dev_priv))
+ if (IS_GEN6(dev_priv))
+ sandybridge_write_fence_reg(reg);
+ else if (IS_I965G(dev_priv))
i965_write_fence_reg(reg);
else if (IS_I9XX(dev_priv))
i915_write_fence_reg(reg);
@@ -2741,6 +2785,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_obj *obj,
int write,
/* Not valid to be called on unbound objects. */
if (obj_priv->dmamap == NULL)
return (EINVAL);
+
/* Wait on any GPU rendering and flushing to occur. */
if ((ret = i915_gem_object_flush_gpu_write_domain(obj, 0,
interruptible, write)) != 0)
@@ -3199,8 +3244,12 @@ i915_dispatch_gem_execbuffer(struct drm_device *dev,
} else {
BEGIN_LP_RING(4);
if (IS_I965G(dev_priv)) {
- OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) |
- MI_BATCH_NON_SECURE_I965);
+ if (IS_GEN6(dev_priv))
+ OUT_RING(MI_BATCH_BUFFER_START |
+ MI_BATCH_NON_SECURE_I965);
+ else
+ OUT_RING(MI_BATCH_BUFFER_START | (2 << 6) |
+ MI_BATCH_NON_SECURE_I965);
OUT_RING(exec_start);
} else {
OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
@@ -4016,8 +4065,13 @@ i915_gem_init_hws(struct inteldrm_softc *dev_priv)
drm_unhold_object(obj);
dev_priv->hws_obj = obj;
memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
- I915_WRITE(HWS_PGA, obj_priv->gtt_offset);
- I915_READ(HWS_PGA); /* posting read */
+ if (IS_GEN6(dev_priv)) {
+ I915_WRITE(HWS_PGA_GEN6, obj_priv->gtt_offset);
+ I915_READ(HWS_PGA_GEN6); /* posting read */
+ } else {
+ I915_WRITE(HWS_PGA, obj_priv->gtt_offset);
+ I915_READ(HWS_PGA); /* posting read */
+ }
DRM_DEBUG("hws offset: 0x%08x\n", obj_priv->gtt_offset);
return 0;
@@ -4042,7 +4096,11 @@ i915_gem_cleanup_hws(struct inteldrm_softc *dev_priv)
dev_priv->hws_obj = NULL;
/* Write high address into HWS_PGA when disabling. */
- I915_WRITE(HWS_PGA, 0x1ffff000);
+ if (IS_GEN6(dev_priv)) {
+ I915_WRITE(HWS_PGA_GEN6, 0x1ffff000);
+ } else {
+ I915_WRITE(HWS_PGA, 0x1ffff000);
+ }
}
int
@@ -4139,7 +4197,10 @@ inteldrm_start_ring(struct inteldrm_softc *dev_priv)
/* Update our cache of the ring state */
inteldrm_update_ring(dev_priv);
- if (IS_I9XX(dev_priv) && !IS_GEN3(dev_priv))
+ if (IS_GEN6(dev_priv))
+ I915_WRITE(MI_MODE | MI_FLUSH_ENABLE << 16 | MI_FLUSH_ENABLE,
+ (VS_TIMER_DISPATCH) << 15 | VS_TIMER_DISPATCH);
+ else if (IS_I9XX(dev_priv) && !IS_GEN3(dev_priv))
I915_WRITE(MI_MODE, (VS_TIMER_DISPATCH) << 15 |
VS_TIMER_DISPATCH);
@@ -4242,7 +4303,7 @@ inteldrm_error(struct inteldrm_softc *dev_priv)
}
printf("render error detected, EIR: %b\n", eir, errbitstr);
- if (IS_IRONLAKE(dev_priv)) {
+ if (IS_IRONLAKE(dev_priv) || IS_GEN6(dev_priv)) {
if (eir & GT_ERROR_PTE) {
dev_priv->mm.wedged = 1;
reset = GDRST_FULL;
@@ -4328,7 +4389,7 @@ inteldrm_error(struct inteldrm_softc *dev_priv)
if (dev_priv->mm.wedged == 0)
DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir);
I915_WRITE(EMR, I915_READ(EMR) | eir);
- if (IS_IRONLAKE(dev_priv)) {
+ if (IS_IRONLAKE(dev_priv) || IS_GEN6(dev_priv)) {
I915_WRITE(GTIIR, GT_MASTER_ERROR);
} else {
I915_WRITE(IIR,
@@ -5075,15 +5136,11 @@ inteldrm_pipe_enabled(struct inteldrm_softc *dev_priv,
int pipe)
{
bus_size_t pipeconf;
-#if 0
- if (IS_IRONLAKE(dev_priv)) {
+ if (IS_IRONLAKE(dev_priv) || IS_GEN6(dev_priv)) {
pipeconf = (pipe ? PCH_DPLL_A : PCH_DPLL_B);
} else {
-#endif
pipeconf = (pipe ? PIPEBCONF : PIPEACONF);
-#if 0
}
-#endif
return ((I915_READ(pipeconf) & PIPEACONF_ENABLE) == PIPEACONF_ENABLE);
}
@@ -5100,7 +5157,7 @@ i915_save_palette(struct inteldrm_softc *dev_priv, enum
pipe pipe)
if (!inteldrm_pipe_enabled(dev_priv, pipe))
return;
- if (IS_IRONLAKE(dev_priv))
+ if (HAS_PCH_SPLIT(dev_priv))
reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
if (pipe == PIPE_A)
@@ -5122,7 +5179,7 @@ i915_restore_palette(struct inteldrm_softc *dev_priv,
enum pipe pipe)
if (!inteldrm_pipe_enabled(dev_priv, pipe))
return;
- if (IS_IRONLAKE(dev_priv))
+ if (HAS_PCH_SPLIT(dev_priv))
reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
if (pipe == PIPE_A)
@@ -5284,7 +5341,7 @@ void
i915_save_modeset_reg(struct inteldrm_softc *dev_priv)
{
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->savePCH_DREF_CONTROL = I915_READ(PCH_DREF_CONTROL);
dev_priv->saveDISP_ARB_CTL = I915_READ(DISP_ARB_CTL);
}
@@ -5292,7 +5349,7 @@ i915_save_modeset_reg(struct inteldrm_softc *dev_priv)
/* Pipe & plane A info */
dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->saveFPA0 = I915_READ(PCH_FPA0);
dev_priv->saveFPA1 = I915_READ(PCH_FPA1);
dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A);
@@ -5301,7 +5358,7 @@ i915_save_modeset_reg(struct inteldrm_softc *dev_priv)
dev_priv->saveFPA1 = I915_READ(FPA1);
dev_priv->saveDPLL_A = I915_READ(DPLL_A);
}
- if (IS_I965G(dev_priv) && !IS_IRONLAKE(dev_priv))
+ if (IS_I965G(dev_priv) && !HAS_PCH_SPLIT(dev_priv))
dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
@@ -5309,7 +5366,7 @@ i915_save_modeset_reg(struct inteldrm_softc *dev_priv)
dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1);
dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1);
dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1);
@@ -5348,7 +5405,7 @@ i915_save_modeset_reg(struct inteldrm_softc *dev_priv)
/* Pipe & plane B info */
dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->saveFPA0 = I915_READ(PCH_FPB0);
dev_priv->saveFPA1 = I915_READ(PCH_FPB1);
dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_B);
@@ -5357,7 +5414,7 @@ i915_save_modeset_reg(struct inteldrm_softc *dev_priv)
dev_priv->saveFPB1 = I915_READ(FPB1);
dev_priv->saveDPLL_B = I915_READ(DPLL_B);
}
- if (IS_I965G(dev_priv) && !IS_IRONLAKE(dev_priv))
+ if (IS_I965G(dev_priv) && (!IS_IRONLAKE(dev_priv) &&
!IS_GEN6(dev_priv)))
dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
@@ -5365,7 +5422,7 @@ i915_save_modeset_reg(struct inteldrm_softc *dev_priv)
dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1);
dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1);
dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1);
@@ -5394,7 +5451,7 @@ i915_save_modeset_reg(struct inteldrm_softc *dev_priv)
dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
- if (IS_I965GM(dev_priv) || IS_GM45(dev_priv)) {
+ if (IS_I965GM(dev_priv) || IS_GM45(dev_priv)) { /* XXX: IS_MOBILE ? */
dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
}
@@ -5408,7 +5465,7 @@ i915_restore_modeset_reg(struct inteldrm_softc *dev_priv)
bus_size_t dpll_a_reg, fpa0_reg, fpa1_reg;
bus_size_t dpll_b_reg, fpb0_reg, fpb1_reg;
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dpll_a_reg = PCH_DPLL_A;
dpll_b_reg = PCH_DPLL_B;
fpa0_reg = PCH_FPA0;
@@ -5424,7 +5481,7 @@ i915_restore_modeset_reg(struct inteldrm_softc *dev_priv)
fpb1_reg = FPB1;
}
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
I915_WRITE(PCH_DREF_CONTROL, dev_priv->savePCH_DREF_CONTROL);
I915_WRITE(DISP_ARB_CTL, dev_priv->saveDISP_ARB_CTL);
}
@@ -5441,7 +5498,7 @@ i915_restore_modeset_reg(struct inteldrm_softc *dev_priv)
/* Actually enable it */
I915_WRITE(dpll_a_reg, dev_priv->saveDPLL_A);
DRM_UDELAY(150);
- if (IS_I965G(dev_priv) && !IS_IRONLAKE(dev_priv))
+ if (IS_I965G(dev_priv) && !HAS_PCH_SPLIT(dev_priv))
I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
DRM_UDELAY(150);
@@ -5452,7 +5509,7 @@ i915_restore_modeset_reg(struct inteldrm_softc *dev_priv)
I915_WRITE(VTOTAL_A, dev_priv->saveVTOTAL_A);
I915_WRITE(VBLANK_A, dev_priv->saveVBLANK_A);
I915_WRITE(VSYNC_A, dev_priv->saveVSYNC_A);
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
@@ -5505,7 +5562,7 @@ i915_restore_modeset_reg(struct inteldrm_softc *dev_priv)
/* Actually enable it */
I915_WRITE(dpll_b_reg, dev_priv->saveDPLL_B);
DRM_UDELAY(150);
- if (IS_I965G(dev_priv) && !IS_IRONLAKE(dev_priv))
+ if (IS_I965G(dev_priv) && !HAS_PCH_SPLIT(dev_priv))
I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
DRM_UDELAY(150);
@@ -5516,7 +5573,7 @@ i915_restore_modeset_reg(struct inteldrm_softc *dev_priv)
I915_WRITE(VTOTAL_B, dev_priv->saveVTOTAL_B);
I915_WRITE(VBLANK_B, dev_priv->saveVBLANK_B);
I915_WRITE(VSYNC_B, dev_priv->saveVSYNC_B);
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
@@ -5579,14 +5636,14 @@ inteldrm_save_display(struct inteldrm_softc *dev_priv)
dev_priv->saveCURSIZE = I915_READ(CURSIZE);
/* CRT state */
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->saveADPA = I915_READ(PCH_ADPA);
} else {
dev_priv->saveADPA = I915_READ(ADPA);
}
/* LVDS state */
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
dev_priv->saveBLC_PWM_CTL = I915_READ(BLC_PWM_PCH_CTL1);
dev_priv->saveBLC_PWM_CTL2 = I915_READ(BLC_PWM_PCH_CTL2);
@@ -5603,9 +5660,11 @@ inteldrm_save_display(struct inteldrm_softc *dev_priv)
if (IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
dev_priv->saveLVDS = I915_READ(LVDS);
}
- if (!IS_I830(dev_priv) && !IS_845G(dev_priv))
+
+ if (!IS_I830(dev_priv) && !IS_845G(dev_priv) &&
!HAS_PCH_SPLIT(dev_priv))
dev_priv->savePFIT_CONTROL = I915_READ(PFIT_CONTROL);
- if (IS_IRONLAKE(dev_priv)) {
+
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
dev_priv->savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
dev_priv->savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
@@ -5631,7 +5690,7 @@ inteldrm_save_display(struct inteldrm_softc *dev_priv)
dev_priv->saveVGA0 = I915_READ(VGA0);
dev_priv->saveVGA1 = I915_READ(VGA1);
dev_priv->saveVGA_PD = I915_READ(VGA_PD);
- if (IS_IRONLAKE(dev_priv))
+ if (HAS_PCH_SPLIT(dev_priv))
dev_priv->saveVGACNTRL = I915_READ(CPU_VGACNTRL);
else
dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
@@ -5661,24 +5720,24 @@ inteldrm_restore_display(struct inteldrm_softc
*dev_priv)
I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
/* CRT state */
- if (IS_IRONLAKE(dev_priv))
+ if (HAS_PCH_SPLIT(dev_priv))
I915_WRITE(PCH_ADPA, dev_priv->saveADPA);
else
I915_WRITE(ADPA, dev_priv->saveADPA);
/* LVDS state */
- if (IS_I965G(dev_priv) && !IS_IRONLAKE(dev_priv))
+ if (IS_I965G(dev_priv) && !HAS_PCH_SPLIT(dev_priv))
I915_WRITE(BLC_PWM_CTL2, dev_priv->saveBLC_PWM_CTL2);
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
I915_WRITE(PCH_LVDS, dev_priv->saveLVDS);
} else if (IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
I915_WRITE(LVDS, dev_priv->saveLVDS);
- if (!IS_I830(dev_priv) && !IS_845G(dev_priv) && !IS_IRONLAKE(dev_priv))
+ if (!IS_I830(dev_priv) && !IS_845G(dev_priv) &&
!HAS_PCH_SPLIT(dev_priv))
I915_WRITE(PFIT_CONTROL, dev_priv->savePFIT_CONTROL);
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL);
I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2);
I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL);
@@ -5712,7 +5771,7 @@ inteldrm_restore_display(struct inteldrm_softc *dev_priv)
}
/* VGA state */
- if (IS_IRONLAKE(dev_priv))
+ if (HAS_PCH_SPLIT(dev_priv))
I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL);
else
I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
@@ -5734,12 +5793,16 @@ inteldrm_save_state(struct inteldrm_softc *dev_priv)
dev_priv->saveLBB = pci_conf_read(dev_priv->pc, dev_priv->tag, LBB);
/* Hardware status page */
- dev_priv->saveHWS = I915_READ(HWS_PGA);
+ if (IS_GEN6(dev_priv)) {
+ dev_priv->saveHWS = I915_READ(HWS_PGA_GEN6);
+ } else {
+ dev_priv->saveHWS = I915_READ(HWS_PGA);
+ }
inteldrm_save_display(dev_priv);
/* Interrupt state */
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->saveDEIER = I915_READ(DEIER);
dev_priv->saveDEIMR = I915_READ(DEIMR);
dev_priv->saveGTIER = I915_READ(GTIER);
@@ -5754,7 +5817,7 @@ inteldrm_save_state(struct inteldrm_softc *dev_priv)
}
/* Clock gating state */
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
dev_priv->saveDSPCLK_GATE_D = I915_READ(PCH_DSPCLK_GATE_D);
dev_priv->saveDSPCLK_GATE = I915_READ(ILK_DSPCLK_GATE);
} else if (IS_G4X(dev_priv)) {
@@ -5794,7 +5857,11 @@ inteldrm_save_state(struct inteldrm_softc *dev_priv)
dev_priv->saveSWF2[i] = I915_READ(SWF30 + (i << 2));
/* Fences */
- if (IS_I965G(dev_priv)) {
+ if (IS_GEN6(dev_priv)) {
+ for (i = 0; i < 16; i++)
+ dev_priv->saveFENCE[i] =
I915_READ64(FENCE_REG_SANDYBRIDGE_0 +
+ (i * 8));
+ } else if (IS_I965G(dev_priv)) {
for (i = 0; i < 16; i++)
dev_priv->saveFENCE[i] = I915_READ64(FENCE_REG_965_0 +
(i * 8));
@@ -5819,10 +5886,16 @@ inteldrm_restore_state(struct inteldrm_softc *dev_priv)
pci_conf_write(dev_priv->pc, dev_priv->tag, LBB, dev_priv->saveLBB);
/* Hardware status page */
- I915_WRITE(HWS_PGA, dev_priv->saveHWS);
+ if (IS_GEN6(dev_priv))
+ I915_WRITE(HWS_PGA_GEN6, dev_priv->saveHWS);
+ else
+ I915_WRITE(HWS_PGA, dev_priv->saveHWS);
/* Fences */
- if (IS_I965G(dev_priv)) {
+ if (IS_GEN6(dev_priv)) {
+ for (i = 0; i < 16; i++)
+ I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 + (i * 8),
dev_priv->saveFENCE[i]);
+ } else if (IS_I965G(dev_priv)) {
for (i = 0; i < 16; i++)
I915_WRITE64(FENCE_REG_965_0 + (i * 8),
dev_priv->saveFENCE[i]);
} else {
@@ -5837,7 +5910,7 @@ inteldrm_restore_state(struct inteldrm_softc *dev_priv)
inteldrm_restore_display(dev_priv);
/* Interrupt state */
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
I915_WRITE(DEIER, dev_priv->saveDEIER);
I915_WRITE(DEIMR, dev_priv->saveDEIMR);
I915_WRITE(GTIER, dev_priv->saveGTIER);
@@ -5850,7 +5923,7 @@ inteldrm_restore_state(struct inteldrm_softc *dev_priv)
}
/* Clock gating state */
- if (IS_IRONLAKE(dev_priv)) {
+ if (HAS_PCH_SPLIT(dev_priv)) {
I915_WRITE(PCH_DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
I915_WRITE(ILK_DSPCLK_GATE, dev_priv->saveDSPCLK_GATE);
} if (IS_G4X(dev_priv)) {
@@ -5951,13 +6024,25 @@ inteldrm_965_reset(struct inteldrm_softc *dev_priv,
u_int8_t flags)
panic("can't restart ring, we're fucked");
/* put the hardware status page back */
- if (I915_NEED_GFX_HWS(dev_priv))
+ if (I915_NEED_GFX_HWS(dev_priv)) {
I915_WRITE(HWS_PGA, ((struct inteldrm_obj *)
dev_priv->hws_obj)->gtt_offset);
- else
+ if (IS_GEN6(dev_priv)) {
+ I915_WRITE(HWS_PGA_GEN6,
+ ((struct inteldrm_obj *)
+ dev_priv->hws_obj)->gtt_offset);
+ } else {
+ I915_WRITE(HWS_PGA, ((struct inteldrm_obj *)
+ dev_priv->hws_obj)->gtt_offset);
+ }
+ } else {
I915_WRITE(HWS_PGA,
dev_priv->hws_dmamem->map->dm_segs[0].ds_addr);
- I915_READ(HWS_PGA); /* posting read */
+ }
+ if (IS_GEN6(dev_priv))
+ I915_READ(HWS_PGA_GEN6); /* posting read */
+ else
+ I915_READ(HWS_PGA); /* posting read */
/* so we remove the handler and can put it back in */
DRM_UNLOCK();
diff --git dev/pci/drm/i915_drv.h dev/pci/drm/i915_drv.h
index 4d8dda0..a03c387 100644
--- dev/pci/drm/i915_drv.h
+++ dev/pci/drm/i915_drv.h
@@ -439,6 +439,7 @@ struct inteldrm_file {
#define CHIP_IRONLAKE 0x200000
#define CHIP_IRONLAKE_D 0x400000
#define CHIP_IRONLAKE_M 0x800000
+#define CHIP_SANDYBRIDGE 0x1000000
/* flags we use in drm_obj's do_flags */
#define I915_ACTIVE 0x0010 /* being used by the gpu. */
@@ -767,6 +768,9 @@ read64(struct inteldrm_softc *dev_priv, bus_size_t off)
#define I965_FENCE_REG_VALID (1<<0)
#define I965_FENCE_MAX_PITCH_VAL 0x0400
+#define FENCE_REG_SANDYBRIDGE_0 0x100000
+#define SANDYBRIDGE_FENCE_PITCH_SHIFT 32
+
/*
* Instruction and interrupt control regs
*/
@@ -801,6 +805,7 @@ read64(struct inteldrm_softc *dev_priv, bus_size_t off)
#define INSTDONE1 0x0207c /* 965+ only */
#define ACTHD_I965 0x02074
#define HWS_PGA 0x02080
+#define HWS_PGA_GEN6 0x04080
#define HWS_ADDRESS_MASK 0xfffff000
#define HWS_START_ADDRESS_SHIFT 4
#define IPEIR 0x02088
@@ -811,6 +816,7 @@ read64(struct inteldrm_softc *dev_priv, bus_size_t off)
#define MI_MODE 0x0209c
#define VS_TIMER_DISPATCH (1 << 6)
+#define MI_FLUSH_ENABLE (1 << 11)
#define SCPD0 0x0209c /* 915+ only */
#define IER 0x020a0
@@ -3051,11 +3057,15 @@ read64(struct inteldrm_softc *dev_priv, bus_size_t off)
#define IS_IRONLAKE_D(dev_priv) ((dev_priv)->flags & CHIP_IRONLAKE_D)
#define IS_IRONLAKE_M(dev_priv) ((dev_priv)->flags & CHIP_IRONLAKE_M)
+#define IS_SANDYBRIDGE(dev_priv) ((dev_priv)->flags & CHIP_SANDYBRIDGE)
+#define IS_SANDYBRIDGE_D(dev_priv) ((dev_priv)->flags & CHIP_SANDYBRIDGE_D)
+#define IS_SANDYBRIDGE_M(dev_priv) ((dev_priv)->flags & CHIP_SANDYBRIDGE_M)
+
#define IS_MOBILE(dev_priv) (dev_priv->flags & CHIP_M)
#define I915_NEED_GFX_HWS(dev_priv) (dev_priv->flags & CHIP_HWS)
-#define HAS_RESET(dev_priv) IS_I965G(dev_priv)
+#define HAS_RESET(dev_priv) IS_I965G(dev_priv) && (!IS_GEN6(dev_priv))
#define IS_GEN2(dev_priv) (dev_priv->flags & CHIP_GEN2)
#define IS_GEN3(dev_priv) (dev_priv->flags & CHIP_GEN3)
diff --git dev/pci/drm/i915_irq.c dev/pci/drm/i915_irq.c
index 1e1183c..4335584 100644
--- dev/pci/drm/i915_irq.c
+++ dev/pci/drm/i915_irq.c
@@ -66,9 +66,15 @@ inline void
ironlake_enable_graphics_irq(struct inteldrm_softc *dev_priv, u_int32_t mask)
{
if ((dev_priv->gt_irq_mask_reg & mask) != 0) {
+ /* XXX imr bullshit */
dev_priv->gt_irq_mask_reg &= ~mask;
- I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
- (void)I915_READ(GTIMR);
+ if (IS_GEN6(dev_priv)) {
+ I915_WRITE(0x20a8, dev_priv->gt_irq_mask_reg);
+ (void)I915_READ(0x20a8);
+ } else {
+ I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
+ (void)I915_READ(GTIMR);
+ }
}
}
@@ -77,8 +83,13 @@ ironlake_disable_graphics_irq(struct inteldrm_softc
*dev_priv, u_int32_t mask)
{
if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
dev_priv->gt_irq_mask_reg |= mask;
- I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
- (void)I915_READ(GTIMR);
+ if (IS_GEN6(dev_priv)) {
+ I915_WRITE(0x20a8, dev_priv->gt_irq_mask_reg);
+ (void)I915_READ(0x20a8);
+ } else {
+ I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
+ (void)I915_READ(GTIMR);
+ }
}
}
@@ -145,7 +156,8 @@ i915_get_vblank_counter(struct drm_device *dev, int pipe)
}
/* GM45 just had to be different... */
- if (IS_GM45(dev_priv) || IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv)) {
+ if (IS_GM45(dev_priv) || IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv) ||
+ IS_GEN6(dev_priv)) {
return (I915_READ(pipe ? PIPEB_FRMCOUNT_GM45 :
PIPEA_FRMCOUNT_GM45));
}
@@ -236,7 +248,7 @@ i915_driver_irq_install(struct drm_device *dev)
struct inteldrm_softc *dev_priv = dev->dev_private;
dev->vblank->vb_max = 0xffffff; /* only 24 bits of frame count */
- if (IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv))
+ if (IS_G4X(dev_priv) || IS_IRONLAKE(dev_priv) || IS_GEN6(dev_priv))
dev->vblank->vb_max = 0xffffffff;
I915_WRITE(HWSTAM, 0xeffe);