diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2011-09-14 10:26:17 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2011-09-14 10:26:17 +0000 |
commit | 9b6761b3876f332d775de70502f3b2fece8ec0b0 (patch) | |
tree | 850692ed51f9f92c74b3a78a9d9661e23abc1878 /sys | |
parent | 141c424a9640398369524b63e7975530e95256fc (diff) |
Initial kernel support for sandybridge intel chipsets in intagp and inteldrm.
Far from perfect. Extra (almost essential) features like the extra
ringbuffers are not yet supported (I have half a diff), but this and the
appropriate ddx patches allow modesetting and basic shadow acceleration.
Initial work by jcs@, a few cleanups and bugfixes by me.
Tested by many on all appropriate chipsets. ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/agp_i810.c | 101 | ||||
-rw-r--r-- | sys/dev/pci/agpreg.h | 24 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.c | 197 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.h | 14 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_irq.c | 26 |
5 files changed, 293 insertions, 69 deletions
diff --git a/sys/dev/pci/agp_i810.c b/sys/dev/pci/agp_i810.c index 75071f6a0a3..0c2bc0e97b9 100644 --- a/sys/dev/pci/agp_i810.c +++ b/sys/dev/pci/agp_i810.c @@ -1,4 +1,4 @@ -/* $OpenBSD: agp_i810.c,v 1.69 2010/09/06 15:00:50 oga Exp $ */ +/* $OpenBSD: agp_i810.c,v 1.70 2011/09/14 10:26:16 oga Exp $ */ /*- * Copyright (c) 2000 Doug Rabson @@ -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 a/sys/dev/pci/agpreg.h b/sys/dev/pci/agpreg.h index e8d9281855a..d57fb7c7121 100644 --- a/sys/dev/pci/agpreg.h +++ b/sys/dev/pci/agpreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: agpreg.h,v 1.12 2008/12/24 05:42:58 oga Exp $ */ +/* $OpenBSD: agpreg.h,v 1.13 2011/09/14 10:26:16 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 a/sys/dev/pci/drm/i915_drv.c b/sys/dev/pci/drm/i915_drv.c index f5ba8353926..01a42aa11a7 100644 --- a/sys/dev/pci/drm/i915_drv.c +++ b/sys/dev/pci/drm/i915_drv.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i915_drv.c,v 1.115 2011/07/06 01:50:08 deraadt Exp $ */ +/* $OpenBSD: i915_drv.c,v 1.116 2011/09/14 10:26:16 oga Exp $ */ /* * Copyright (c) 2008-2009 Owain G. Ainsworth <oga@openbsd.org> * @@ -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 a/sys/dev/pci/drm/i915_drv.h b/sys/dev/pci/drm/i915_drv.h index 107e6ce6435..18db31b15cc 100644 --- a/sys/dev/pci/drm/i915_drv.h +++ b/sys/dev/pci/drm/i915_drv.h @@ -1,4 +1,4 @@ -/* $OpenBSD: i915_drv.h,v 1.69 2011/06/02 18:22:00 weerd Exp $ */ +/* $OpenBSD: i915_drv.h,v 1.70 2011/09/14 10:26:16 oga Exp $ */ /* i915_drv.h -- Private header for the I915 driver -*- linux-c -*- */ /* @@ -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 a/sys/dev/pci/drm/i915_irq.c b/sys/dev/pci/drm/i915_irq.c index 2af7e13de17..71e921fcfbb 100644 --- a/sys/dev/pci/drm/i915_irq.c +++ b/sys/dev/pci/drm/i915_irq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: i915_irq.c,v 1.51 2011/06/02 18:22:00 weerd Exp $ */ +/* $OpenBSD: i915_irq.c,v 1.52 2011/09/14 10:26:16 oga Exp $ */ /* i915_irq.c -- IRQ support for the I915 -*- linux-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); |