On Thu, Sep 08, 2011 at 05:25:46AM +0100, Owain Ainsworth wrote:
> 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-
Bah, now without a keyword bit that won't apply.
Index: dev/pci/agp_i810.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/agp_i810.c,v
retrieving revision 1.69
diff -u -p -r1.69 agp_i810.c
--- dev/pci/agp_i810.c 6 Sep 2010 15:00:50 -0000 1.69
+++ dev/pci/agp_i810.c 8 Sep 2011 04:59:19 -0000
@@ -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_
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, s
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, s
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, in
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 *
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->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 *
break;
case CHIP_G4X:
case CHIP_IRONLAKE:
+ case CHIP_SANDYBRIDGE:
baseoff = AGP_G4X_GTT;
break;
default:
Index: dev/pci/agpreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/agpreg.h,v
retrieving revision 1.12
diff -u -p -r1.12 agpreg.h
--- dev/pci/agpreg.h 24 Dec 2008 05:42:58 -0000 1.12
+++ dev/pci/agpreg.h 8 Sep 2011 04:59:27 -0000
@@ -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_ */
Index: dev/pci/drm/i915_drv.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915_drv.c,v
retrieving revision 1.115
diff -u -p -r1.115 i915_drv.c
--- dev/pci/drm/i915_drv.c 6 Jul 2011 01:50:08 -0000 1.115
+++ dev/pci/drm/i915_drv.c 8 Sep 2011 04:59:27 -0000
@@ -194,6 +194,7 @@ bus_size_t i915_gem_get_gtt_alignment(st
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_
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, s
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 *
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_ob
}
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
/* 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_
} 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
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_sof
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_soft
/* 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 *de
}
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 *de
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_so
{
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
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_sof
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_so
/* 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_so
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_so
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_so
/* 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_so
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_so
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_so
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
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
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
/* 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
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
/* 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
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_so
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_so
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_so
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
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
}
/* 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_soft
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_soft
}
/* 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_soft
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_s
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_s
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_s
}
/* 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
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();
Index: dev/pci/drm/i915_drv.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915_drv.h,v
retrieving revision 1.69
diff -u -p -r1.69 i915_drv.h
--- dev/pci/drm/i915_drv.h 2 Jun 2011 18:22:00 -0000 1.69
+++ dev/pci/drm/i915_drv.h 8 Sep 2011 04:59:27 -0000
@@ -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,
#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,
#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,
#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,
#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)
Index: dev/pci/drm/i915_irq.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/drm/i915_irq.c,v
retrieving revision 1.51
diff -u -p -r1.51 i915_irq.c
--- dev/pci/drm/i915_irq.c 2 Jun 2011 18:22:00 -0000 1.51
+++ dev/pci/drm/i915_irq.c 8 Sep 2011 04:59:27 -0000
@@ -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 int
{
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_devic
}
/* 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_devic
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);
--
It is impossible to make anything foolproof because fools are so
ingenious.