diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common.h | 57 | ||||
-rw-r--r-- | src/i810.h | 9 | ||||
-rw-r--r-- | src/i810_accel.c | 85 | ||||
-rw-r--r-- | src/i810_cursor.c | 83 | ||||
-rw-r--r-- | src/i810_dri.c | 40 | ||||
-rw-r--r-- | src/i810_driver.c | 82 | ||||
-rw-r--r-- | src/i810_memory.c | 45 | ||||
-rw-r--r-- | src/i810_reg.h | 29 | ||||
-rw-r--r-- | src/i830.h | 75 | ||||
-rw-r--r-- | src/i830_accel.c | 146 | ||||
-rw-r--r-- | src/i830_common.h | 271 | ||||
-rw-r--r-- | src/i830_cursor.c | 202 | ||||
-rw-r--r-- | src/i830_dga.c | 9 | ||||
-rw-r--r-- | src/i830_dri.c | 577 | ||||
-rw-r--r-- | src/i830_dri.h | 80 | ||||
-rw-r--r-- | src/i830_driver.c | 1784 | ||||
-rw-r--r-- | src/i830_memory.c | 392 | ||||
-rw-r--r-- | src/i830_video.c | 464 |
18 files changed, 2923 insertions, 1507 deletions
diff --git a/src/common.h b/src/common.h index 9dbea332..1b98d695 100644 --- a/src/common.h +++ b/src/common.h @@ -27,7 +27,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/common.h,v 1.7 2003/06/18 13:14:17 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/common.h,v 1.9 2003/09/24 02:43:23 dawes Exp $ */ /* * Authors: @@ -79,7 +79,11 @@ extern const char *I810vbeSymbols[]; extern const char *I810ddcSymbols[]; extern const char *I810fbSymbols[]; extern const char *I810xaaSymbols[]; +#ifdef XF86DRI +extern const char *I810driSymbols[]; +extern const char *I810drmSymbols[]; extern const char *I810shadowSymbols[]; +#endif extern void I830DPRINTF_stub(const char *filename, int line, const char *function, const char *fmt, ...); @@ -111,7 +115,8 @@ extern void I830DPRINTF_stub(const char *filename, int line, #define OUT_RING(n) do { \ if (I810_DEBUG & DEBUG_VERBOSE_RING) \ - ErrorF( "OUT_RING %x: %x, (mask %x)\n", outring, n, ringmask); \ + ErrorF( "OUT_RING %lx: %x, (mask %x)\n", \ + (unsigned long)(outring), (unsigned int)(n), ringmask); \ *(volatile unsigned int *)(virt + outring) = n; \ outring += 4; \ outring &= ringmask; \ @@ -119,7 +124,7 @@ extern void I830DPRINTF_stub(const char *filename, int line, #if 1 #define ADVANCE_LP_RING() do { \ - RecPtr->LpRing.tail = outring; \ + RecPtr->LpRing->tail = outring; \ if (outring & 0x07) \ ErrorF("ADVANCE_LP_RING: " \ "outring (0x%x) isn't on a QWord boundary", outring); \ @@ -127,7 +132,7 @@ extern void I830DPRINTF_stub(const char *filename, int line, } while (0) #else #define ADVANCE_LP_RING() { \ - RecPtr->LpRing.tail = outring; \ + RecPtr->LpRing->tail = outring; \ if (outring & 0x07) \ ErrorF("ADVANCE_LP_RING: " \ "outring (0x%x) isn't on a QWord boundary", outring); \ @@ -174,19 +179,19 @@ extern void I830DPRINTF_stub(const char *filename, int line, if ((n) > 2 && (I810_DEBUG&DEBUG_ALWAYS_SYNC)) \ DO_RING_IDLE(); \ needed = (n) * 4; \ - if ((RecPtr->LpRing.tail > RecPtr->LpRing.tail_mask - AVOID_SIZE) || \ - (RecPtr->LpRing.tail + needed) > \ - RecPtr->LpRing.tail_mask - AVOID_SIZE) { \ - needed += RecPtr->LpRing.tail_mask + 1 - RecPtr->LpRing.tail; \ + if ((RecPtr->LpRing->tail > RecPtr->LpRing->tail_mask - AVOID_SIZE) || \ + (RecPtr->LpRing->tail + needed) > \ + RecPtr->LpRing->tail_mask - AVOID_SIZE) { \ + needed += RecPtr->LpRing->tail_mask + 1 - RecPtr->LpRing->tail; \ ErrorF("BEGIN_LP_RING: skipping last 64 bytes of " \ "ring (%d vs %d)\n", needed, (n) * 4); \ } \ - if (RecPtr->LpRing.space < needed) \ + if (RecPtr->LpRing->space < needed) \ WaitRingFunc(pScrn, needed, 0); \ - RecPtr->LpRing.space -= needed; \ - outring = RecPtr->LpRing.tail; \ - ringmask = RecPtr->LpRing.tail_mask; \ - virt = RecPtr->LpRing.virtual_start; \ + RecPtr->LpRing->space -= needed; \ + outring = RecPtr->LpRing->tail; \ + ringmask = RecPtr->LpRing->tail_mask; \ + virt = RecPtr->LpRing->virtual_start; \ while (needed > (n) * 4) { \ ErrorF("BEGIN_LP_RING: putting MI_NOOP at 0x%x (remaining %d)\n", \ outring, needed - (n) * 4); \ @@ -207,12 +212,12 @@ extern void I830DPRINTF_stub(const char *filename, int line, if ((n) > 2 && (I810_DEBUG&DEBUG_ALWAYS_SYNC)) \ DO_RING_IDLE(); \ needed = (n) * 4; \ - if (RecPtr->LpRing.space < needed) \ + if (RecPtr->LpRing->space < needed) \ WaitRingFunc(pScrn, needed, 0); \ - RecPtr->LpRing.space -= needed; \ - outring = RecPtr->LpRing.tail; \ - ringmask = RecPtr->LpRing.tail_mask; \ - virt = RecPtr->LpRing.virtual_start; \ + RecPtr->LpRing->space -= needed; \ + outring = RecPtr->LpRing->tail; \ + ringmask = RecPtr->LpRing->tail_mask; \ + virt = RecPtr->LpRing->virtual_start; \ if (I810_DEBUG & DEBUG_VERBOSE_RING) \ ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME); @@ -227,21 +232,24 @@ extern void I830DPRINTF_stub(const char *filename, int line, #define OUTREG8(addr, val) do { \ *(volatile CARD8 *)(RecPtr->MMIOBase + (addr)) = (val); \ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \ - ErrorF("OUTREG8(0x%x, 0x%x) in %s\n", addr, val, FUNCTION_NAME); \ + ErrorF("OUTREG8(0x%lx, 0x%lx) in %s\n", (unsigned long)(addr), \ + (unsigned long)(val), FUNCTION_NAME); \ } \ } while (0) #define OUTREG16(addr, val) do { \ *(volatile CARD16 *)(RecPtr->MMIOBase + (addr)) = (val); \ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \ - ErrorF("OUTREG16(0x%x, 0x%x) in %s\n", addr, val, FUNCTION_NAME); \ + ErrorF("OUTREG16(0x%lx, 0x%lx) in %s\n", (unsigned long)(addr), \ + (unsigned long)(val), FUNCTION_NAME); \ } \ } while (0) #define OUTREG(addr, val) do { \ *(volatile CARD32 *)(RecPtr->MMIOBase + (addr)) = (val); \ if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \ - ErrorF("OUTREG(0x%x, 0x%x) in %s\n", addr, val, FUNCTION_NAME); \ + ErrorF("OUTREG(0x%lx, 0x%lx) in %s\n", (unsigned long)(addr), \ + (unsigned long)(val), FUNCTION_NAME); \ } \ } while (0) @@ -292,6 +300,11 @@ extern int I810_DEBUG; #define PCI_CHIP_I865_G_BRIDGE 0x2570 #endif +#ifndef PCI_CHIP_I915_G +#define PCI_CHIP_I915_G 0x2582 +#define PCI_CHIP_I915_G_BRIDGE 0x2580 +#endif + #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 || \ pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \ pI810->PciInfo->chipType == PCI_CHIP_I810_E) @@ -300,6 +313,7 @@ extern int I810_DEBUG; #define IS_845G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_845_G) #define IS_I85X(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I855_GM) #define IS_I865G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I865_G) +#define IS_I915G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_G) #define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810)) @@ -312,6 +326,7 @@ extern int I810_DEBUG; #define MIN_SCRATCH_BUFFER_SIZE KB(16) #define MAX_SCRATCH_BUFFER_SIZE KB(64) #define HWCURSOR_SIZE GTT_PAGE_SIZE +#define HWCURSOR_SIZE_ARGB GTT_PAGE_SIZE * 4 #define OVERLAY_SIZE GTT_PAGE_SIZE /* Use a 64x64 HW cursor */ @@ -162,9 +162,13 @@ typedef struct _I810Rec { int auxPitch; int auxPitchBits; + Bool CursorIsARGB; int CursorOffset; unsigned long CursorPhysical; unsigned long CursorStart; + int CursorARGBOffset; + unsigned long CursorARGBPhysical; + unsigned long CursorARGBStart; unsigned long OverlayPhysical; unsigned long OverlayStart; int colorKey; @@ -184,7 +188,7 @@ typedef struct _I810Rec { pciVideoPtr PciInfo; PCITAG PciTag; - I810RingBuffer LpRing; + I810RingBuffer *LpRing; unsigned int BR[20]; int LmFreqSel; @@ -195,6 +199,8 @@ typedef struct _I810Rec { unsigned long DcacheOffset; int HwcursKey; unsigned long HwcursOffset; + int ARGBHwcursKey; + unsigned long ARGBHwcursOffset; int GttBound; @@ -235,6 +241,7 @@ typedef struct _I810Rec { unsigned long backHandle; unsigned long zHandle; unsigned long cursorHandle; + unsigned long cursorARGBHandle; unsigned long xvmcHandle; unsigned long sysmemHandle; Bool agpAcquired; diff --git a/src/i810_accel.c b/src/i810_accel.c index d8467424..ca74f966 100644 --- a/src/i810_accel.c +++ b/src/i810_accel.c @@ -25,7 +25,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c,v 1.19 2003/04/24 18:00:24 eich Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_accel.c,v 1.21 2004/01/02 20:22:17 dawes Exp $ */ /* * Reformatted with GNU indent (2.2.8), using the following options: @@ -48,47 +48,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86_ansic.h" #include "xf86.h" - +#include "xaarop.h" #include "i810.h" -static unsigned int i810Rop[16] = { - 0x00, /* GXclear */ - 0x88, /* GXand */ - 0x44, /* GXandReverse */ - 0xCC, /* GXcopy */ - 0x22, /* GXandInvert */ - 0xAA, /* GXnoop */ - 0x66, /* GXxor */ - 0xEE, /* GXor */ - 0x11, /* GXnor */ - 0x99, /* GXequiv */ - 0x55, /* GXinvert */ - 0xDD, /* GXorReverse */ - 0x33, /* GXcopyInvert */ - 0xBB, /* GXorInverted */ - 0x77, /* GXnand */ - 0xFF /* GXset */ -}; - -static unsigned int i810PatternRop[16] = { - 0x00, /* GXclear */ - 0xA0, /* GXand */ - 0x50, /* GXandReverse */ - 0xF0, /* GXcopy */ - 0x0A, /* GXandInvert */ - 0xAA, /* GXnoop */ - 0x5A, /* GXxor */ - 0xFA, /* GXor */ - 0x05, /* GXnor */ - 0xA5, /* GXequiv */ - 0x55, /* GXinvert */ - 0xF5, /* GXorReverse */ - 0x0F, /* GXcopyInvert */ - 0xAF, /* GXorInverted */ - 0x5F, /* GXnand */ - 0xFF /* GXset */ -}; - static void I810SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty, int fg, int bg, int rop, @@ -130,10 +92,7 @@ I810AccelInit(ScreenPtr pScreen) pI810->bufferOffset = 0; infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS; - /* There is a bit blt bug in 24 bpp. This is a problem, but - * at least without the pixmap cache we can pass the test suite */ - if (pScrn->depth != 24) - infoPtr->Flags |= PIXMAP_CACHE; + infoPtr->Flags |= PIXMAP_CACHE; /* Sync */ @@ -227,7 +186,7 @@ int I810WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) { I810Ptr pI810 = I810PTR(pScrn); - I810RingBuffer *ring = &(pI810->LpRing); + I810RingBuffer *ring = pI810->LpRing; int iters = 0; int start = 0; int now = 0; @@ -316,9 +275,9 @@ I810Sync(ScrnInfoPtr pScrn) ADVANCE_LP_RING(); } - I810WaitLpRing(pScrn, pI810->LpRing.mem.Size - 8, 0); + I810WaitLpRing(pScrn, pI810->LpRing->mem.Size - 8, 0); - pI810->LpRing.space = pI810->LpRing.mem.Size - 8; + pI810->LpRing->space = pI810->LpRing->mem.Size - 8; pI810->nextColorExpandBuf = 0; } @@ -334,7 +293,7 @@ I810SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, /* Color blit, p166 */ pI810->BR[13] = (BR13_SOLID_PATTERN | - (i810PatternRop[rop] << 16) | + (XAAPatternROP[rop] << 16) | (pScrn->displayWidth * pI810->cpp)); pI810->BR[16] = color; } @@ -380,7 +339,7 @@ I810SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, if (xdir == -1) pI810->BR[13] |= BR13_RIGHT_TO_LEFT; - pI810->BR[13] |= i810Rop[rop] << 16; + pI810->BR[13] |= XAACopyROP[rop] << 16; pI810->BR[18] = 0; } @@ -401,9 +360,12 @@ I810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, * This was developed empirically so it may not catch all * cases. */ +#define I810_MWIDTH 8 + if ( !(pI810->BR[13] & BR13_RIGHT_TO_LEFT) && (y2 - y1) < 3 - && (y2 - y1) >= 0 && (x2 - x1) <= (w + 4) && (w > 4)) - w = 4; + && (y2 - y1) >= 0 && (x2 - x1) <= (w + I810_MWIDTH) + && (w > I810_MWIDTH)) + w = I810_MWIDTH; do { if (pI810->BR[13] & BR13_PITCH_SIGN_BIT) { @@ -441,7 +403,10 @@ I810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, break; x2 += w; x1 += w; - w = w_back; + if (w_back > I810_MWIDTH) + w = I810_MWIDTH; + else + w = w_back; } while (1); } @@ -460,9 +425,9 @@ I810SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty, pI810->BR[18] = bg; pI810->BR[19] = fg; pI810->BR[13] = (pScrn->displayWidth * pI810->cpp); - pI810->BR[13] |= i810PatternRop[rop] << 16; + pI810->BR[13] |= XAAPatternROP[rop] << 16; if (bg == -1) - pI810->BR[13] |= BR13_MONO_TRANSPCY; + pI810->BR[13] |= BR13_MONO_PATN_TRANS; } static void @@ -524,7 +489,7 @@ I810SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, fg, bg, rop, planemask); pI810->BR[13] = (pScrn->displayWidth * pI810->cpp); - pI810->BR[13] |= i810Rop[rop] << 16; + pI810->BR[13] |= XAACopyROP[rop] << 16; pI810->BR[13] |= (1 << 27); if (bg == -1) pI810->BR[13] |= BR13_MONO_TRANSPCY; @@ -623,11 +588,11 @@ I810RefreshRing(ScrnInfoPtr pScrn) { I810Ptr pI810 = I810PTR(pScrn); - pI810->LpRing.head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR; - pI810->LpRing.tail = INREG(LP_RING + RING_TAIL); - pI810->LpRing.space = pI810->LpRing.head - (pI810->LpRing.tail + 8); - if (pI810->LpRing.space < 0) - pI810->LpRing.space += pI810->LpRing.mem.Size; + pI810->LpRing->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR; + pI810->LpRing->tail = INREG(LP_RING + RING_TAIL); + pI810->LpRing->space = pI810->LpRing->head - (pI810->LpRing->tail + 8); + if (pI810->LpRing->space < 0) + pI810->LpRing->space += pI810->LpRing->mem.Size; pI810->AccelInfoRec->NeedToSync = TRUE; } diff --git a/src/i810_cursor.c b/src/i810_cursor.c index 26023f3f..23b006d3 100644 --- a/src/i810_cursor.c +++ b/src/i810_cursor.c @@ -25,7 +25,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_cursor.c,v 1.7 2002/10/30 12:52:17 alanh Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810_cursor.c,v 1.6 2002/09/11 00:29:31 dawes Exp $ */ /* * Reformatted with GNU indent (2.2.8), using the following options: @@ -44,6 +44,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Keith Whitwell <keith@tungstengraphics.com> * + * Add ARGB HW cursor support: + * Alan Hourihane <alanh@tungstengraphics.com> + * */ #include "xf86.h" @@ -55,6 +58,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i810.h" +static Bool I810UseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs); +static void I810LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs); static void I810LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src); static void I810ShowCursor(ScrnInfoPtr pScrn); static void I810HideCursor(ScrnInfoPtr pScrn); @@ -90,10 +95,63 @@ I810CursorInit(ScreenPtr pScreen) infoPtr->HideCursor = I810HideCursor; infoPtr->ShowCursor = I810ShowCursor; infoPtr->UseHWCursor = I810UseHWCursor; +#ifdef ARGB_CURSOR + pI810->CursorIsARGB = FALSE; + + if (!pI810->CursorARGBPhysical) { + infoPtr->UseHWCursorARGB = I810UseHWCursorARGB; + infoPtr->LoadCursorARGB = I810LoadCursorARGB; + } +#endif return xf86InitCursor(pScreen, infoPtr); } +#ifdef ARGB_CURSOR +#include "cursorstr.h" + +static Bool I810UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + + if (!pI810->CursorARGBPhysical) + return FALSE; + + if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64) + return TRUE; + + return FALSE; +} + +static void I810LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) +{ + I810Ptr pI810 = I810PTR(pScrn); + CARD32 *pcurs = (CARD32 *) (pI810->FbBase + pI810->CursorStart); + CARD32 *image = (CARD32 *) pCurs->bits->argb; + int x, y, w, h; + +#ifdef ARGB_CURSOR + pI810->CursorIsARGB = TRUE; +#endif + + w = pCurs->bits->width; + h = pCurs->bits->height; + + for (y = 0; y < h; y++) + { + for (x = 0; x < w; x++) + *pcurs++ = *image++; + for (; x < 64; x++) + *pcurs++ = 0; + } + + for (; y < 64; y++) + for (x = 0; x < 64; x++) + *pcurs++ = 0; +} +#endif + static Bool I810UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) { @@ -113,6 +171,10 @@ I810LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) CARD8 *pcurs = (CARD8 *) (pI810->FbBase + pI810->CursorStart); int x, y; +#ifdef ARGB_CURSOR + pI810->CursorIsARGB = FALSE; +#endif + for (y = 0; y < 64; y++) { for (x = 0; x < 64 / 4; x++) { *pcurs++ = *src++; @@ -147,7 +209,10 @@ I810SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) OUTREG8(CURSOR_Y_LO, y & 0xFF); OUTREG8(CURSOR_Y_HI, (((y >> 8) & 0x07) | flag)); - OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical); + if (pI810->CursorIsARGB) + OUTREG(CURSOR_BASEADDR, pI810->CursorARGBPhysical); + else + OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical); } static void @@ -156,8 +221,13 @@ I810ShowCursor(ScrnInfoPtr pScrn) I810Ptr pI810 = I810PTR(pScrn); unsigned char tmp; - OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical); - OUTREG8(CURSOR_CONTROL, CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_3C); + if (pI810->CursorIsARGB) { + OUTREG(CURSOR_BASEADDR, pI810->CursorARGBPhysical); + OUTREG8(CURSOR_CONTROL, CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_ARGB_AX); + } else { + OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical); + OUTREG8(CURSOR_CONTROL, CURSOR_ORIGIN_DISPLAY | CURSOR_MODE_64_3C); + } tmp = INREG8(PIXPIPE_CONFIG_0); tmp |= HW_CURSOR_ENABLE; @@ -181,6 +251,11 @@ I810SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) int tmp; I810Ptr pI810 = I810PTR(pScrn); +#ifdef ARGB_CURSOR + if (pI810->CursorIsARGB) + return; +#endif + tmp = INREG8(PIXPIPE_CONFIG_0); tmp |= EXTENDED_PALETTE; OUTREG8(PIXPIPE_CONFIG_0, tmp); diff --git a/src/i810_dri.c b/src/i810_dri.c index a09ba6b7..0750f3f8 100644 --- a/src/i810_dri.c +++ b/src/i810_dri.c @@ -104,7 +104,7 @@ Bool I810InitDma(ScrnInfoPtr pScrn) { I810Ptr pI810 = I810PTR(pScrn); - I810RingBuffer *ring = &(pI810->LpRing); + I810RingBuffer *ring = pI810->LpRing; I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate; drmI810Init info; @@ -517,6 +517,7 @@ I810DRIScreenInit(ScreenPtr pScreen) memset(&pI810->BackBuffer, 0, sizeof(I810MemRange)); memset(&pI810->DepthBuffer, 0, sizeof(I810MemRange)); pI810->CursorPhysical = 0; + pI810->CursorARGBPhysical = 0; /* Dcache - half the speed of normal ram, but has use as a Z buffer * under the DRI. @@ -590,6 +591,7 @@ I810DRIScreenInit(ScreenPtr pScreen) } sysmem_size -= 4096; /* remove 4k for the hw cursor */ + sysmem_size -= 16384; /* remove 16k for the ARGB hw cursor */ pI810->SysMem.Start = 0; pI810->SysMem.Size = sysmem_size; @@ -771,6 +773,30 @@ I810DRIScreenInit(ScreenPtr pScreen) pI810->CursorPhysical = 0; } + drmAgpAlloc(pI810->drmSubFD, 16384, 2, + (unsigned long *)&pI810->CursorARGBPhysical, &agpHandle); + + pI810->cursorARGBHandle = agpHandle; + + if (agpHandle != DRM_AGP_NO_HANDLE) { + int r; + + if ((r = drmAgpBind(pI810->drmSubFD, agpHandle, tom)) == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] GART: Allocated 16K for ARGB mouse cursor image\n"); + pI810->CursorARGBStart = tom; + tom += 16384; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] GART: ARGB cursor bind failed\n"); + pI810->CursorARGBPhysical = 0; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] GART: ARGB cursor alloc failed\n"); + pI810->CursorARGBPhysical = 0; + } + /* Steal some of the excess cursor space for the overlay regs. */ pI810->OverlayPhysical = pI810->CursorPhysical + 1024; @@ -875,8 +901,8 @@ I810DRIScreenInit(ScreenPtr pScreen) pI810DRI->agp_buffers = pI810->buffer_map; pI810DRI->agp_buf_size = pI810->BufferMem.Size; - if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing.mem.Start, - pI810->LpRing.mem.Size, DRM_AGP, 0, &pI810->ring_map) < 0) { + if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->LpRing->mem.Start, + pI810->LpRing->mem.Size, DRM_AGP, 0, &pI810->ring_map) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(ring_map) failed. Disabling DRI.\n"); DRICloseScreen(pScreen); @@ -966,8 +992,8 @@ I810DRIScreenInit(ScreenPtr pScreen) pI810DRI->backOffset = pI810->BackBuffer.Start; pI810DRI->depthOffset = pI810->DepthBuffer.Start; - pI810DRI->ringOffset = pI810->LpRing.mem.Start; - pI810DRI->ringSize = pI810->LpRing.mem.Size; + pI810DRI->ringOffset = pI810->LpRing->mem.Start; + pI810DRI->ringSize = pI810->LpRing->mem.Size; pI810DRI->auxPitch = pI810->auxPitch; pI810DRI->auxPitchBits = pI810->auxPitchBits; @@ -1511,6 +1537,10 @@ I810DRIEnter(ScrnInfoPtr pScrn) if (drmAgpBind(pI810->drmSubFD, pI810->cursorHandle, pI810->CursorStart) != 0) return FALSE; + if (pI810->cursorARGBHandle != 0) + if (drmAgpBind(pI810->drmSubFD, pI810->cursorARGBHandle, + pI810->CursorARGBStart) != 0) + return FALSE; } return TRUE; } diff --git a/src/i810_driver.c b/src/i810_driver.c index caadc879..92bd7e88 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -44,6 +44,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Keith Whitwell <keith@tungstengraphics.com> * + * Add ARGB HW cursor support: + * Alan Hourihane <alanh@tungstengraphics.com> + * */ /* @@ -69,12 +72,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "micmap.h" #include "fb.h" -#include "regionstr.h" +#include "miscstruct.h" #include "xf86xv.h" #include "Xv.h" #include "vbe.h" #include "i810.h" +#include "i830.h" #ifdef XF86DRI #include "dri.h" @@ -124,6 +128,7 @@ static SymTabRec I810Chipsets[] = { {PCI_CHIP_845_G, "845G"}, {PCI_CHIP_I855_GM, "852GM/855GM"}, {PCI_CHIP_I865_G, "865G"}, + {PCI_CHIP_I915_G, "915G"}, {-1, NULL} }; @@ -138,6 +143,7 @@ static PciChipsets I810PciChipsets[] = { {PCI_CHIP_845_G, PCI_CHIP_845_G, RES_SHARED_VGA}, {PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA}, {PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA}, + {PCI_CHIP_I915_G, PCI_CHIP_I915_G, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED } }; @@ -358,6 +364,8 @@ static XF86ModuleVersionInfo i810VersRec = { XF86ModuleData i810ModuleData = { &i810VersRec, i810Setup, 0 }; +int I830EntityIndex = -1; + static pointer i810Setup(pointer module, pointer opts, int *errmaj, int *errmin) { @@ -467,6 +475,8 @@ static Bool I810Probe(DriverPtr drv, int flags) { int i, numUsed, numDevSections, *usedChips; + I830EntPtr pI830Ent = NULL; + DevUnion *pPriv; GDevPtr *devSections; Bool foundScreen = FALSE; pciVideoPtr *VideoInfo; @@ -542,11 +552,39 @@ I810Probe(DriverPtr drv, int flags) pScrn->Probe = I810Probe; foundScreen = TRUE; switch (pEnt->chipset) { - case PCI_CHIP_I830_M: case PCI_CHIP_845_G: - case PCI_CHIP_I855_GM: case PCI_CHIP_I865_G: I830InitpScrn(pScrn); + break; + case PCI_CHIP_I830_M: + case PCI_CHIP_I855_GM: + case PCI_CHIP_I915_G: + xf86SetEntitySharable(usedChips[i]); + + /* Allocate an entity private if necessary */ + if (I830EntityIndex < 0) + I830EntityIndex = xf86AllocateEntityPrivateIndex(); + + pPriv = xf86GetEntityPrivate(pScrn->entityList[0], + I830EntityIndex); + if (!pPriv->ptr) { + pPriv->ptr = xnfcalloc(sizeof(I830EntRec), 1); + pI830Ent = pPriv->ptr; + pI830Ent->lastInstance = -1; + } else { + pI830Ent = pPriv->ptr; + } + + /* + * Set the entity instance for this instance of the driver. + * For dual head per card, instance 0 is the "master" + * instance, driving the primary head, and instance 1 is + * the "slave". + */ + pI830Ent->lastInstance++; + xf86SetEntityInstanceForScreen(pScrn, + pScrn->entityList[0], pI830Ent->lastInstance); + I830InitpScrn(pScrn); break; #ifndef I830_ONLY default: @@ -1122,7 +1160,7 @@ I810MapMem(ScrnInfoPtr pScrn) if (!pI810->FbBase) return FALSE; - pI810->LpRing.virtual_start = pI810->FbBase + pI810->LpRing.mem.Start; + pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start; return TRUE; } @@ -1486,8 +1524,8 @@ DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, OUTREG(LP_RING + RING_TAIL, 0); OUTREG(LP_RING + RING_HEAD, 0); - pI810->LpRing.head = 0; - pI810->LpRing.tail = 0; + pI810->LpRing->head = 0; + pI810->LpRing->tail = 0; itemp = INREG(LP_RING + RING_START); itemp &= ~(START_ADDR); @@ -1527,12 +1565,12 @@ I810SetRingRegs(ScrnInfoPtr pScrn) itemp = INREG(LP_RING + RING_START); itemp &= ~(START_ADDR); - itemp |= pI810->LpRing.mem.Start; + itemp |= pI810->LpRing->mem.Start; OUTREG(LP_RING + RING_START, itemp); itemp = INREG(LP_RING + RING_LEN); itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK); - itemp |= ((pI810->LpRing.mem.Size - 4096) | RING_NO_REPORT | RING_VALID); + itemp |= ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID); OUTREG(LP_RING + RING_LEN, itemp); } @@ -1728,10 +1766,10 @@ I810SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) /* Setup the ring buffer */ i810Reg->LprbTail = 0; i810Reg->LprbHead = 0; - i810Reg->LprbStart = pI810->LpRing.mem.Start; + i810Reg->LprbStart = pI810->LpRing->mem.Start; if (i810Reg->LprbStart) - i810Reg->LprbLen = ((pI810->LpRing.mem.Size - 4096) | + i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) | RING_NO_REPORT | RING_VALID); else i810Reg->LprbLen = RING_INVALID; @@ -1974,18 +2012,18 @@ I810AllocateFront(ScrnInfoPtr pScrn) pI810->FrontBuffer.Start, pI810->FrontBuffer.Size / 1024, pI810->FrontBuffer.Size); - memset(&(pI810->LpRing), 0, sizeof(I810RingBuffer)); - if (I810AllocLow(&(pI810->LpRing.mem), &(pI810->SysMem), 16 * 4096)) { + memset(pI810->LpRing, 0, sizeof(I810RingBuffer)); + if (I810AllocLow(&(pI810->LpRing->mem), &(pI810->SysMem), 16 * 4096)) { DPRINTF(PFX, "Ring buffer at 0x%.8x (%luk, %lu bytes)\n", - pI810->LpRing.mem.Start, - pI810->LpRing.mem.Size / 1024, pI810->LpRing.mem.Size); - - pI810->LpRing.tail_mask = pI810->LpRing.mem.Size - 1; - pI810->LpRing.virtual_start = pI810->FbBase + pI810->LpRing.mem.Start; - pI810->LpRing.head = 0; - pI810->LpRing.tail = 0; - pI810->LpRing.space = 0; + pI810->LpRing->mem.Start, + pI810->LpRing->mem.Size / 1024, pI810->LpRing->mem.Size); + + pI810->LpRing->tail_mask = pI810->LpRing->mem.Size - 1; + pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start; + pI810->LpRing->head = 0; + pI810->LpRing->tail = 0; + pI810->LpRing->space = 0; } else { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Ring buffer allocation failed\n"); @@ -2114,7 +2152,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); #ifdef XF86DRI - if (pI810->LpRing.mem.Start == 0 && pI810->directRenderingEnabled) { + if (pI810->LpRing->mem.Start == 0 && pI810->directRenderingEnabled) { pI810->directRenderingEnabled = FALSE; driFrom = X_PROBED; I810DRICloseScreen(pScreen); @@ -2138,7 +2176,7 @@ I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } if (!xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) { - if (pI810->LpRing.mem.Size != 0) { + if (pI810->LpRing->mem.Size != 0) { I810SetRingRegs(pScrn); if (!I810AccelInit(pScreen)) { diff --git a/src/i810_memory.c b/src/i810_memory.c index 5efa23a9..749997f4 100644 --- a/src/i810_memory.c +++ b/src/i810_memory.c @@ -149,7 +149,7 @@ I810AllocateGARTMemory(ScrnInfoPtr pScrn) pI810->DcacheKey = key; if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Allocation of %d bytes for DCACHE failed\n", size); + "Allocation of %ld bytes for DCACHE failed\n", size); pI810->DcacheKey = -1; } else { pI810->DcacheMem.Start = tom; @@ -159,7 +159,7 @@ I810AllocateGARTMemory(ScrnInfoPtr pScrn) } } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "No physical memory available for %d bytes of DCACHE\n", + "No physical memory available for %ld bytes of DCACHE\n", size); pI810->DcacheKey = -1; } @@ -188,9 +188,11 @@ I810AllocateGARTMemory(ScrnInfoPtr pScrn) pI810->HwcursKey = key; if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Allocation of %d bytes for HW cursor failed\n", size); + "Allocation of %ld bytes for HW cursor failed\n", size); pI810->HwcursKey = -1; } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Allocated of %ld bytes for HW cursor\n", size); pI810->CursorPhysical = physical; pI810->CursorStart = tom; tom += size; @@ -198,6 +200,34 @@ I810AllocateGARTMemory(ScrnInfoPtr pScrn) } /* + * 16k for the ARGB cursor + */ + + size = 16384; + + if ((key = + xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No physical memory available for ARGB HW cursor\n"); + pI810->ARGBHwcursKey = -1; + pI810->CursorARGBStart = 0; + } else { + pI810->ARGBHwcursOffset = tom; + pI810->ARGBHwcursKey = key; + if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Allocation of %ld bytes for ARGB HW cursor failed\n", size); + pI810->ARGBHwcursKey = -1; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Allocated of %ld bytes for ARGB HW cursor\n", size); + pI810->CursorARGBPhysical = physical; + pI810->CursorARGBStart = tom; + tom += size; + } + } + + /* * Overlay register buffer -- Just like the cursor, the i810 needs a * physical address in system memory from which to upload the overlay * registers. @@ -345,6 +375,11 @@ I810BindGARTMemory(ScrnInfoPtr pScrn) pI810->HwcursOffset)) return FALSE; + if (pI810->ARGBHwcursKey != -1 + && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey, + pI810->ARGBHwcursOffset)) + return FALSE; + pI810->GttBound = 1; } @@ -370,6 +405,10 @@ I810UnbindGARTMemory(ScrnInfoPtr pScrn) && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey)) return FALSE; + if (pI810->ARGBHwcursKey != -1 + && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey)) + return FALSE; + if (!xf86ReleaseGART(pScrn->scrnIndex)) return FALSE; diff --git a/src/i810_reg.h b/src/i810_reg.h index c935982a..eac71ba9 100644 --- a/src/i810_reg.h +++ b/src/i810_reg.h @@ -209,6 +209,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define CURSOR_SIZE_HSHIFT 0 #define CURSOR_SIZE_VSHIFT 12 +#define CURSOR_B_CONTROL 0x700C0 +#define CURSOR_B_BASE 0x700C4 +#define CURSOR_B_POSITION 0x700C8 +#define CURSOR_B_PALETTE0 0x700D0 +#define CURSOR_B_PALETTE1 0x700D4 +#define CURSOR_B_PALETTE2 0x700D8 +#define CURSOR_B_PALETTE3 0x700DC + /* Similar registers exist in Device 0 on the i810 (pp55-65), but I'm * not sure they refer to local (graphics) memory. @@ -358,6 +366,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define FENCE 0x2000 #define FENCE_NR 8 +#define I915G_FENCE_START_MASK 0x0ff00000 + #define I830_FENCE_START_MASK 0x07f80000 #define FENCE_START_MASK 0x03F80000 @@ -372,7 +382,14 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define FENCE_SIZE_16M 0x00000500 #define FENCE_SIZE_32M 0x00000600 #define FENCE_SIZE_64M 0x00000700 -#define FENCE_PITCH_MASK 0x00000070 +#define I915G_FENCE_SIZE_1M 0x00000000 +#define I915G_FENCE_SIZE_2M 0x00000100 +#define I915G_FENCE_SIZE_4M 0x00000200 +#define I915G_FENCE_SIZE_8M 0x00000300 +#define I915G_FENCE_SIZE_16M 0x00000400 +#define I915G_FENCE_SIZE_32M 0x00000500 +#define I915G_FENCE_SIZE_64M 0x00000600 +#define I915G_FENCE_SIZE_128M 0x00000700 #define FENCE_PITCH_1 0x00000000 #define FENCE_PITCH_2 0x00000010 #define FENCE_PITCH_4 0x00000020 @@ -497,6 +514,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define BR13_RIGHT_TO_LEFT 0x40000000 #define BR13_LEFT_TO_RIGHT 0x00000000 #define BR13_MONO_TRANSPCY 0x20000000 +#define BR13_MONO_PATN_TRANS 0x10000000 #define BR13_USE_DYN_DEPTH 0x04000000 #define BR13_DYN_8BPP 0x00000000 #define BR13_DYN_16BPP 0x01000000 @@ -708,6 +726,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define PIPEBCONF 0x71008 #define PIPEBCONF_ENABLE (1<<31) #define PIPEBCONF_DISABLE 0 +#define PIPEBCONF_DOUBLE_WIDE (1<<30) +#define PIPEBCONF_DISABLE 0 #define PIPEBCONF_GAMMA (1<<24) #define PIPEBCONF_PALETTE 0 @@ -747,6 +767,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define DSPBADDR DSPBBASE #define DSPBSTRIDE 0x71188 +#define DSPAPOS 0x7018C /* reserved */ +#define DSPASIZE 0x70190 +#define DSPBPOS 0x7118C +#define DSPBSIZE 0x71190 + /* Various masks for reserved bits, etc. */ #define I830_FWATER1_MASK (~((1<<11)|(1<<10)|(1<<9)| \ (1<<8)|(1<<26)|(1<<25)|(1<<24)|(1<<5)|(1<<4)|(1<<3)| \ @@ -801,6 +826,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define I855_GMCH_GMS_STOLEN_8M (0x3 << 4) #define I855_GMCH_GMS_STOLEN_16M (0x4 << 4) #define I855_GMCH_GMS_STOLEN_32M (0x5 << 4) +#define I915G_GMCH_GMS_STOLEN_48M (0x6 << 4) +#define I915G_GMCH_GMS_STOLEN_64M (0x7 << 4) #define I85X_CAPID 0x44 #define I85X_VARIANT_MASK 0x7 @@ -78,6 +78,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Paulo César Pereira de Andrade <pcpa@conectiva.com.br>. */ +#define PIPE_NONE 0<<0 +#define PIPE_CRT 1<<0 +#define PIPE_TV 1<<1 +#define PIPE_DFP 1<<2 +#define PIPE_LFP 1<<3 +#define PIPE_CRT2 1<<4 +#define PIPE_TV2 1<<5 +#define PIPE_DFP2 1<<6 +#define PIPE_LFP2 1<<7 + typedef struct _VESARec { /* SVGA state */ pointer state, pstate; @@ -87,6 +97,8 @@ typedef struct _VESARec { xf86MonPtr monitor; /* Don't try to set the refresh rate for any modes. */ Bool useDefaultRefresh; + /* display start */ + int x, y; } VESARec, *VESAPtr; @@ -133,13 +145,38 @@ typedef struct { unsigned int Fence[8]; } I830RegRec, *I830RegPtr; +typedef struct { + int lastInstance; + int refCount; + ScrnInfoPtr pScrn_1; + ScrnInfoPtr pScrn_2; + int RingRunning; +#ifdef I830_XV + int XvInUse; +#endif +} I830EntRec, *I830EntPtr; + typedef struct _I830Rec { unsigned char *MMIOBase; unsigned char *FbBase; int cpp; + unsigned int bios_version; + + Bool newPipeSwitch; + + Bool Clone; + int CloneRefresh; + int CloneHDisplay; + int CloneVDisplay; + + I830EntPtr entityPrivate; + int pipe; + int init; + unsigned int bufferOffset; /* for I830SelectBuffer */ BoxRec FbMemBox; + BoxRec FbMemBox2; int CacheLines; /* These are set in PreInit and never changed. */ @@ -156,10 +193,16 @@ typedef struct _I830Rec { unsigned long allocatedMemory; /* Regions allocated either from the above pools, or from agpgart. */ + /* for single and dual head configurations */ I830MemRange FrontBuffer; - I830MemRange CursorMem; - I830RingBuffer LpRing; + I830MemRange FrontBuffer2; I830MemRange Scratch; + I830MemRange Scratch2; + + /* Regions allocated either from the above pools, or from agpgart. */ + I830MemRange *CursorMem; + I830MemRange *CursorMemARGB; + I830RingBuffer *LpRing; #if REMAP_RESERVED I830MemRange Dummy; @@ -167,14 +210,13 @@ typedef struct _I830Rec { #ifdef I830_XV /* For Xvideo */ - I830MemRange OverlayMem; + I830MemRange *OverlayMem; #endif #ifdef XF86DRI I830MemRange BackBuffer; I830MemRange DepthBuffer; I830MemRange TexMem; - I830MemRange BufferMem; I830MemRange ContextMem; int TexGranularity; int drmMinor; @@ -185,10 +227,13 @@ typedef struct _I830Rec { Bool allowPageFlip; Bool disableTiling; - int auxPitch; - int auxPitchBits; + int backPitch; Bool CursorNeedsPhysical; + Bool CursorIsARGB; + + int MonType1; + int MonType2; DGAModePtr DGAModes; int numDGAModes; @@ -221,7 +266,6 @@ typedef struct _I830Rec { XAAInfoRecPtr AccelInfoRec; xf86CursorInfoPtr CursorInfoRec; CloseScreenProcPtr CloseScreen; - ScreenBlockHandlerProcPtr BlockHandler; I830WriteIndexedByteFunc writeControl; I830ReadIndexedByteFunc readControl; @@ -234,7 +278,8 @@ typedef struct _I830Rec { #ifdef I830_XV int colorKey; XF86VideoAdaptorPtr adaptor; - Bool overlayOn; + ScreenBlockHandlerProcPtr BlockHandler; + Bool *overlayOn; #endif Bool directRenderingDisabled; /* DRI disabled in PreInit. */ @@ -272,12 +317,13 @@ typedef struct _I830Rec { CARD32 saveSWF0; CARD32 saveSWF4; - /* Use BIOS call 0x5f64 to explicitly enable displays. */ - Bool enableDisplays; /* Use BIOS call 0x5f05 to set the refresh rate. */ Bool useExtendedRefresh; - int configuredDevices; + Bool checkLid; + int monitorSwitch; + int operatingDevices; + int savedDevices; /* These are indexed by the display types */ Bool displayAttached[NumDisplayTypes]; @@ -293,6 +339,7 @@ typedef struct _I830Rec { int planeEnabled[MAX_DISPLAY_PIPES]; /* Driver phase/state information */ + Bool preinit; Bool starting; Bool closing; Bool suspended; @@ -304,6 +351,9 @@ typedef struct _I830Rec { int SaveGeneration; Bool vbeRestoreWorkaround; Bool displayInfo; + Bool devicePresence; + + OsTimerPtr lidTimer; } I830Rec; #define I830PTR(p) ((I830Ptr)((p)->driverPrivate)) @@ -401,8 +451,7 @@ extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer); #define ALLOCATE_DRY_RUN 0x80000000 /* Chipset registers for VIDEO BIOS memory RW access */ -#define _855_DRAM_RW_CONTROL 0x58 -#define _845_DRAM_RW_CONTROL 0x90 +#define DRAM_RW_CONTROL 0x58 #define DRAM_WRITE 0x33330000 #endif /* _I830_H_ */ diff --git a/src/i830_accel.c b/src/i830_accel.c index 63dce22d..84012fac 100644 --- a/src/i830_accel.c +++ b/src/i830_accel.c @@ -55,53 +55,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "xf86_ansic.h" #include "xf86.h" - +#include "xaarop.h" #include "i830.h" #include "i810_reg.h" -static unsigned int i810Rop[16] = { - 0x00, /* GXclear */ - 0x88, /* GXand */ - 0x44, /* GXandReverse */ - 0xCC, /* GXcopy */ - 0x22, /* GXandInvert */ - 0xAA, /* GXnoop */ - 0x66, /* GXxor */ - 0xEE, /* GXor */ - 0x11, /* GXnor */ - 0x99, /* GXequiv */ - 0x55, /* GXinvert */ - 0xDD, /* GXorReverse */ - 0x33, /* GXcopyInvert */ - 0xBB, /* GXorInverted */ - 0x77, /* GXnand */ - 0xFF /* GXset */ -}; - -static unsigned int i810PatternRop[16] = { - 0x00, /* GXclear */ - 0xA0, /* GXand */ - 0x50, /* GXandReverse */ - 0xF0, /* GXcopy */ - 0x0A, /* GXandInvert */ - 0xAA, /* GXnoop */ - 0x5A, /* GXxor */ - 0xFA, /* GXor */ - 0x05, /* GXnor */ - 0xA5, /* GXequiv */ - 0x55, /* GXinvert */ - 0xF5, /* GXorReverse */ - 0x0F, /* GXcopyInvert */ - 0xAF, /* GXorInverted */ - 0x5F, /* GXnand */ - 0xFF /* GXset */ -}; - int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) { I830Ptr pI830 = I830PTR(pScrn); - I830RingBuffer *ring = &(pI830->LpRing); + I830RingBuffer *ring = pI830->LpRing; int iters = 0; int start = 0; int now = 0; @@ -179,6 +141,8 @@ I830Sync(ScrnInfoPtr pScrn) } #endif + if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning) return; + /* Send a flush instruction and then wait till the ring is empty. * This is stronger than waiting for the blitter to finish as it also * flushes the internal graphics caches. @@ -190,9 +154,9 @@ I830Sync(ScrnInfoPtr pScrn) ADVANCE_LP_RING(); } - I830WaitLpRing(pScrn, pI830->LpRing.mem.Size - 8, 0); + I830WaitLpRing(pScrn, pI830->LpRing->mem.Size - 8, 0); - pI830->LpRing.space = pI830->LpRing.mem.Size - 8; + pI830->LpRing->space = pI830->LpRing->mem.Size - 8; pI830->nextColorExpandBuf = 0; } @@ -223,7 +187,7 @@ I830SelectBuffer(ScrnInfoPtr pScrn, int buffer) #endif default: case I830_SELECT_FRONT: - pI830->bufferOffset = pI830->FrontBuffer.Start; + pI830->bufferOffset = pScrn->fbOffset; break; } @@ -237,11 +201,11 @@ I830RefreshRing(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - pI830->LpRing.head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; - pI830->LpRing.tail = INREG(LP_RING + RING_TAIL); - pI830->LpRing.space = pI830->LpRing.head - (pI830->LpRing.tail + 8); - if (pI830->LpRing.space < 0) - pI830->LpRing.space += pI830->LpRing.mem.Size; + pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; + pI830->LpRing->tail = INREG(LP_RING + RING_TAIL); + pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8); + if (pI830->LpRing->space < 0) + pI830->LpRing->space += pI830->LpRing->mem.Size; if (pI830->AccelInfoRec) pI830->AccelInfoRec->NeedToSync = TRUE; @@ -280,6 +244,7 @@ static void I830SubsequentScanlineImageWriteRect(ScrnInfoPtr pScrn, int skipleft); static void I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno); #endif +static void I830RestoreAccelState(ScrnInfoPtr pScrn); /* The following function sets up the supported acceleration. Call it @@ -292,6 +257,10 @@ I830AccelInit(ScreenPtr pScreen) XAAInfoRecPtr infoPtr; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); + int i; + int width = 0; + int nr_buffers = 0; + unsigned char *ptr = NULL; if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) ErrorF("I830AccelInit\n"); @@ -335,12 +304,26 @@ I830AccelInit(ScreenPtr pScreen) } - if (pI830->Scratch.Size != 0) { - int i; - int width = ((pScrn->displayWidth + 31) & ~31) / 8; - int nr_buffers = pI830->Scratch.Size / width; - unsigned char *ptr = pI830->FbBase + pI830->Scratch.Start; + /* On the primary screen */ + if (pI830->init == 0) { + if (pI830->Scratch.Size != 0) { + width = ((pScrn->displayWidth + 31) & ~31) / 8; + nr_buffers = pI830->Scratch.Size / width; + ptr = pI830->FbBase + pI830->Scratch.Start; + } + } else { + /* On the secondary screen */ + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + if (pI8301->Scratch2.Size != 0) { + width = ((pScrn->displayWidth + 31) & ~31) / 8; + nr_buffers = pI8301->Scratch2.Size / width; + /* We have to use the primary screen's FbBase, as that's where + * we allocated Scratch2, so we get the correct pointer */ + ptr = pI8301->FbBase + pI8301->Scratch2.Start; + } + } + if (nr_buffers) { pI830->NumScanlineColorExpandBuffers = nr_buffers; pI830->ScanlineColorExpandBuffers = (unsigned char **) xnfcalloc(nr_buffers, sizeof(unsigned char *)); @@ -382,6 +365,18 @@ I830AccelInit(ScreenPtr pScreen) #endif } + { + Bool shared_accel = FALSE; + int i; + + for(i = 0; i < pScrn->numEntities; i++) { + if(xf86IsEntityShared(pScrn->entityList[i])) + shared_accel = TRUE; + } + if(shared_accel == TRUE) + infoPtr->RestoreAccelState = I830RestoreAccelState; + } + I830SelectBuffer(pScrn, I830_SELECT_FRONT); return XAAInit(pScreen, infoPtr); @@ -397,7 +392,7 @@ I830SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, ErrorF("I830SetupForFillRectSolid color: %x rop: %x mask: %x\n", color, rop, planemask); - pI830->BR[13] = ((i810PatternRop[rop] << 16) | + pI830->BR[13] = ((XAAPatternROP[rop] << 16) | (pScrn->displayWidth * pI830->cpp)); pI830->BR[16] = color; @@ -453,7 +448,7 @@ I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, xdir, ydir, rop, planemask, transparency_color); pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); - pI830->BR[13] |= i810Rop[rop] << 16; + pI830->BR[13] |= XAACopyROP[rop] << 16; switch (pScrn->bitsPerPixel) { case 8: @@ -519,7 +514,7 @@ I830SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty, pI830->BR[19] = fg; pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); /* In bytes */ - pI830->BR[13] |= i810PatternRop[rop] << 16; + pI830->BR[13] |= XAAPatternROP[rop] << 16; if (bg == -1) pI830->BR[13] |= (1 << 28); @@ -608,7 +603,7 @@ I830SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, /* Fill out register values */ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); - pI830->BR[13] |= i810Rop[rop] << 16; + pI830->BR[13] |= XAACopyROP[rop] << 16; if (bg == -1) pI830->BR[13] |= (1 << 29); @@ -651,8 +646,17 @@ I830SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) { I830Ptr pI830 = I830PTR(pScrn); - pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - - pI830->FbBase); + if (pI830->init == 0) { + pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - + pI830->FbBase); + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + + /* We have to use the primary screen's FbBase, as that's where + * we allocated Scratch2, so we get the correct pointer */ + pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - + pI8301->FbBase); + } if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) ErrorF("I830SubsequentColorExpandScanline %d (addr %x)\n", @@ -697,7 +701,7 @@ I830SetupForScanlineImageWrite(ScrnInfoPtr pScrn, int rop, /* Fill out register values */ pI830->BR[13] = (pScrn->displayWidth * pI830->cpp); - pI830->BR[13] |= i810Rop[rop] << 16; + pI830->BR[13] |= XAACopyROP[rop] << 16; switch (pScrn->bitsPerPixel) { case 8: @@ -734,8 +738,17 @@ I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) { I830Ptr pI830 = I830PTR(pScrn); - pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - - pI830->FbBase); + if (pI830->init == 0) { + pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - + pI830->FbBase); + } else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + + /* We have to use the primary screen's FbBase, as that's where + * we allocated Scratch2, so we get the correct pointer */ + pI830->BR[12] = (pI830->AccelInfoRec->ScanlineColorExpandBuffers[0] - + pI8301->FbBase); + } if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) ErrorF("I830SubsequentImageWriteScanline %d (addr %x)\n", @@ -766,5 +779,14 @@ I830SubsequentImageWriteScanline(ScrnInfoPtr pScrn, int bufno) pI830->BR[9] += pScrn->displayWidth * pI830->cpp; I830GetNextScanlineColorExpandBuffer(pScrn); } +#endif +/* Support for multiscreen */ +static void +I830RestoreAccelState(ScrnInfoPtr pScrn) +{ +#if 0 + /* might be needed, but everything is on a ring, so I don't think so */ + I830Sync(pScrn); #endif +} diff --git a/src/i830_common.h b/src/i830_common.h index 3367bfc1..4328baa9 100644 --- a/src/i830_common.h +++ b/src/i830_common.h @@ -26,184 +26,31 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_common.h,v 1.2 2002/12/10 01:27:05 dawes Exp $ */ - -/* Author: Jeff Hartmann <jhartmann@valinux.com> - - Converted to common header format: - Jens Owen <jens@tungstengraphics.com> - */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_common.h,v 1.1 2002/09/11 00:29:32 dawes Exp $ */ #ifndef _I830_COMMON_H_ #define _I830_COMMON_H_ -/* WARNING: These defines must be the same as what the Xserver uses. - * if you change them, you must change the defines in the Xserver. - */ - -#ifndef _I830_DEFINES_ -#define _I830_DEFINES_ -#define I830_DMA_BUF_ORDER 12 -#define I830_DMA_BUF_SZ (1<<I830_DMA_BUF_ORDER) -#define I830_DMA_BUF_NR 256 -#define I830_NR_SAREA_CLIPRECTS 8 +#define I830_NR_TEX_REGIONS 255 /* maximum due to use of chars for next/prev */ +#define I830_LOG_MIN_TEX_REGION_SIZE 14 -/* Each region is a minimum of 64k, and there are at most 64 of them. - */ -#define I830_NR_TEX_REGIONS 64 -#define I830_LOG_MIN_TEX_REGION_SIZE 16 - -/* if defining I830_ENABLE_4_TEXTURES, do it in i830_3d_reg.h, too */ -#if !defined(I830_ENABLE_4_TEXTURES) -#define I830_TEXTURE_COUNT 2 -#define I830_TEXBLEND_COUNT 2 /* always same as TEXTURE_COUNT? */ -#else /* defined(I830_ENABLE_4_TEXTURES) */ -#define I830_TEXTURE_COUNT 4 -#define I830_TEXBLEND_COUNT 4 /* always same as TEXTURE_COUNT? */ -#endif /* I830_ENABLE_4_TEXTURES */ - -#define I830_TEXBLEND_SIZE 12 /* (4 args + op) * 2 + COLOR_FACTOR */ - -#define I830_UPLOAD_CTX 0x1 -#define I830_UPLOAD_BUFFERS 0x2 -#define I830_UPLOAD_CLIPRECTS 0x4 -#define I830_UPLOAD_TEX0_IMAGE 0x100 /* handled clientside */ -#define I830_UPLOAD_TEX0_CUBE 0x200 /* handled clientside */ -#define I830_UPLOAD_TEX1_IMAGE 0x400 /* handled clientside */ -#define I830_UPLOAD_TEX1_CUBE 0x800 /* handled clientside */ -#define I830_UPLOAD_TEX2_IMAGE 0x1000 /* handled clientside */ -#define I830_UPLOAD_TEX2_CUBE 0x2000 /* handled clientside */ -#define I830_UPLOAD_TEX3_IMAGE 0x4000 /* handled clientside */ -#define I830_UPLOAD_TEX3_CUBE 0x8000 /* handled clientside */ -#define I830_UPLOAD_TEX_N_IMAGE(n) (0x100 << (n * 2)) -#define I830_UPLOAD_TEX_N_CUBE(n) (0x200 << (n * 2)) -#define I830_UPLOAD_TEXIMAGE_MASK 0xff00 -#define I830_UPLOAD_TEX0 0x10000 -#define I830_UPLOAD_TEX1 0x20000 -#define I830_UPLOAD_TEX2 0x40000 -#define I830_UPLOAD_TEX3 0x80000 -#define I830_UPLOAD_TEX_N(n) (0x10000 << (n)) -#define I830_UPLOAD_TEX_MASK 0xf0000 -#define I830_UPLOAD_TEXBLEND0 0x100000 -#define I830_UPLOAD_TEXBLEND1 0x200000 -#define I830_UPLOAD_TEXBLEND2 0x400000 -#define I830_UPLOAD_TEXBLEND3 0x800000 -#define I830_UPLOAD_TEXBLEND_N(n) (0x100000 << (n)) -#define I830_UPLOAD_TEXBLEND_MASK 0xf00000 -#define I830_UPLOAD_TEX_PALETTE_N(n) (0x1000000 << (n)) -#define I830_UPLOAD_TEX_PALETTE_SHARED 0x4000000 -#define I830_UPLOAD_STIPPLE 0x8000000 - -/* Indices into buf.Setup where various bits of state are mirrored per - * context and per buffer. These can be fired at the card as a unit, - * or in a piecewise fashion as required. - */ - -/* Destbuffer state - * - backbuffer linear offset and pitch -- invarient in the current dri - * - zbuffer linear offset and pitch -- also invarient - * - drawing origin in back and depth buffers. - * - * Keep the depth/back buffer state here to acommodate private buffers - * in the future. - */ - -#define I830_DESTREG_CBUFADDR 0 -/* Invarient */ -#define I830_DESTREG_DBUFADDR 1 -#define I830_DESTREG_DV0 2 -#define I830_DESTREG_DV1 3 -#define I830_DESTREG_SENABLE 4 -#define I830_DESTREG_SR0 5 -#define I830_DESTREG_SR1 6 -#define I830_DESTREG_SR2 7 -#define I830_DESTREG_DR0 8 -#define I830_DESTREG_DR1 9 -#define I830_DESTREG_DR2 10 -#define I830_DESTREG_DR3 11 -#define I830_DESTREG_DR4 12 -#define I830_DEST_SETUP_SIZE 13 - -/* Context state - */ -#define I830_CTXREG_STATE1 0 -#define I830_CTXREG_STATE2 1 -#define I830_CTXREG_STATE3 2 -#define I830_CTXREG_STATE4 3 -#define I830_CTXREG_STATE5 4 -#define I830_CTXREG_IALPHAB 5 -#define I830_CTXREG_STENCILTST 6 -#define I830_CTXREG_ENABLES_1 7 -#define I830_CTXREG_ENABLES_2 8 -#define I830_CTXREG_AA 9 -#define I830_CTXREG_FOGCOLOR 10 -#define I830_CTXREG_BLENDCOLR0 11 -#define I830_CTXREG_BLENDCOLR 12 /* Dword 1 of 2 dword command */ -#define I830_CTXREG_VF 13 -#define I830_CTXREG_VF2 14 -#define I830_CTXREG_MCSB0 15 -#define I830_CTXREG_MCSB1 16 -#define I830_CTX_SETUP_SIZE 17 - -/* 1.3: Stipple state - */ -#define I830_STPREG_ST0 0 -#define I830_STPREG_ST1 1 -#define I830_STP_SETUP_SIZE 2 - -/* Texture state (per tex unit) - */ -#define I830_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (6 dwords) */ -#define I830_TEXREG_MI1 1 -#define I830_TEXREG_MI2 2 -#define I830_TEXREG_MI3 3 -#define I830_TEXREG_MI4 4 -#define I830_TEXREG_MI5 5 -#define I830_TEXREG_MF 6 /* GFX_OP_MAP_FILTER */ -#define I830_TEXREG_MLC 7 /* GFX_OP_MAP_LOD_CTL */ -#define I830_TEXREG_MLL 8 /* GFX_OP_MAP_LOD_LIMITS */ -#define I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS */ -#define I830_TEX_SETUP_SIZE 10 - -/* New version. Kernel auto-detects. - */ -#define I830_TEXREG_TM0LI 0 /* load immediate 2 texture map n */ -#define I830_TEXREG_TM0S0 1 -#define I830_TEXREG_TM0S1 2 -#define I830_TEXREG_TM0S2 3 -#define I830_TEXREG_TM0S3 4 -#define I830_TEXREG_TM0S4 5 -#define I830_TEXREG_NOP0 6 /* noop */ -#define I830_TEXREG_NOP1 7 /* noop */ -#define I830_TEXREG_NOP2 8 /* noop */ -#define __I830_TEXREG_MCS 9 /* GFX_OP_MAP_COORD_SETS -- shared */ -#define __I830_TEX_SETUP_SIZE 10 - - -#define I830_FRONT 0x1 -#define I830_BACK 0x2 -#define I830_DEPTH 0x4 /* Driver specific DRM command indices * NOTE: these are not OS specific, but they are driver specific */ #define DRM_I830_INIT 0x00 -#define DRM_I830_VERTEX 0x01 -#define DRM_I830_CLEAR 0x02 -#define DRM_I830_FLUSH 0x03 -#define DRM_I830_GETAGE 0x04 -#define DRM_I830_GETBUF 0x05 -#define DRM_I830_SWAP 0x06 -#define DRM_I830_COPY 0x07 -#define DRM_I830_DOCOPY 0x08 -#define DRM_I830_FLIP 0x09 -#define DRM_I830_IRQ_EMIT 0x0a -#define DRM_I830_IRQ_WAIT 0x0b -#define DRM_I830_GETPARAM 0x0c -#define DRM_I830_SETPARAM 0x0d - -#endif /* _I830_DEFINES_ */ +#define DRM_I830_FLUSH 0x01 +#define DRM_I830_FLIP 0x02 +#define DRM_I830_BATCHBUFFER 0x03 +#define DRM_I830_IRQ_EMIT 0x04 +#define DRM_I830_IRQ_WAIT 0x05 +#define DRM_I830_GETPARAM 0x06 +#define DRM_I830_SETPARAM 0x07 +#define DRM_I830_ALLOC 0x08 +#define DRM_I830_FREE 0x09 +#define DRM_I830_INIT_HEAP 0x0a +#define DRM_I830_CMDBUFFER 0x0b typedef struct { enum { @@ -211,7 +58,6 @@ typedef struct { I830_CLEANUP_DMA = 0x02 } func; unsigned int mmio_offset; - unsigned int buffers_offset; int sarea_priv_offset; unsigned int ring_start; unsigned int ring_end; @@ -226,63 +72,88 @@ typedef struct { unsigned int back_pitch; unsigned int depth_pitch; unsigned int cpp; + unsigned int chipset; } drmI830Init; typedef struct { - int clear_color; - int clear_depth; - int flags; - unsigned int clear_colormask; - unsigned int clear_depthmask; -} drmI830Clear; - -/* These may be placeholders if we have more cliprects than - * I830_NR_SAREA_CLIPRECTS. In that case, the client sets discard to - * false, indicating that the buffer will be dispatched again with a - * new set of cliprects. + drmTextureRegion texList[I830_NR_TEX_REGIONS+1]; + int last_upload; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int ctxOwner; /* last context to upload state */ + int texAge; + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; + int pf_current_page; /* which buffer is being displayed? */ + int perf_boxes; /* performance boxes to be displayed */ +} drmI830Sarea; + +/* Flags for perf_boxes */ -typedef struct { - int idx; /* buffer index */ - int used; /* nr bytes in use */ - int discard; /* client is finished with the buffer? */ -} drmI830Vertex; +#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */ +#define I830_BOX_FLIP 0x2 /* populated by kernel */ +#define I830_BOX_WAIT 0x4 /* populated by kernel & client */ +#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */ +#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */ -typedef struct { - int idx; /* buffer index */ - int used; /* nr bytes in use */ - void *address; /* Address to copy from */ -} drmI830Copy; typedef struct { - void *virtual; - int request_idx; - int request_size; - int granted; -} drmI830DMA; + int start; /* agp offset */ + int used; /* nr bytes in use */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO*/ + int num_cliprects; /* mulitpass with multiple cliprects? */ + drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */ +} drmI830BatchBuffer; + -typedef struct drm_i830_irq_emit { +typedef struct { int *irq_seq; } drmI830IrqEmit; -typedef struct drm_i830_irq_wait { +typedef struct { int irq_seq; } drmI830IrqWait; -typedef struct drm_i830_getparam { +typedef struct { int param; int *value; } drmI830GetParam; -#define I830_PARAM_IRQ_ACTIVE 1 +#define I830_PARAM_IRQ_ACTIVE 1 +#define I830_PARAM_LAST_ENQUEUE 2 +#define I830_PARAM_LAST_DEQUEUE 3 - -typedef struct drm_i830_setparam { +typedef struct { int param; int value; } drmI830SetParam; #define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1 +#define I830_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 + + +/* A memory manager for regions of shared memory: + */ +#define I830_MEM_REGION_AGP 1 +typedef struct { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or agp */ +} drmI830MemAlloc; + +typedef struct { + int region; + int region_offset; +} drmI830MemFree; + +typedef struct { + int region; + int size; + int start; +} drmI830MemInitHeap; #endif /* _I830_DRM_H_ */ diff --git a/src/i830_cursor.c b/src/i830_cursor.c index ef9a81ee..d59c19dd 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -26,7 +26,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_cursor.c,v 1.7 2003/06/18 13:14:17 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_cursor.c,v 1.6 2002/12/18 15:49:01 dawes Exp $ */ /* * Reformatted with GNU indent (2.2.8), using the following options: @@ -46,6 +46,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Keith Whitwell <keith@tungstengraphics.com> * David Dawes <dawes@xfree86.org> * + * Updated for Dual Head capabilities: + * Alan Hourihane <alanh@tungstengraphics.com> + * + * Add ARGB HW cursor support: + * Alan Hourihane <alanh@tungstengraphics.com> + * */ #include "xf86.h" @@ -63,6 +69,10 @@ static void I830HideCursor(ScrnInfoPtr pScrn); static void I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fb); static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y); static Bool I830UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs); +#ifdef ARGB_CURSOR +static void I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs); +static Bool I830UseHWCursorARGB(ScreenPtr pScrn, CursorPtr pCurs); +#endif void I830InitHWCursor(ScrnInfoPtr pScrn) @@ -71,24 +81,28 @@ I830InitHWCursor(ScrnInfoPtr pScrn) CARD32 temp; DPRINTF(PFX, "I830InitHWCursor\n"); - /* Initialise the HW cursor registers, leaving the cursor hidden. */ - if (IS_MOBILE(pI830)) { + if (IS_MOBILE(pI830) || IS_I915G(pI830)) { temp = INREG(CURSOR_A_CONTROL); temp &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE | MCURSOR_MEM_TYPE_LOCAL | MCURSOR_PIPE_SELECT); temp |= CURSOR_MODE_DISABLE; - /* - * XXX Should enable cursor B when both pipes are enabled. - * For now, give pipe A preference. - */ - if (pI830->pipeEnabled[0]) - temp |= MCURSOR_PIPE_A; - else if (pI830->pipeEnabled[1]) - temp |= MCURSOR_PIPE_B; + temp |= (pI830->pipe << 28); /* Need to set control, then address. */ OUTREG(CURSOR_A_CONTROL, temp); - OUTREG(CURSOR_A_BASE, pI830->CursorMem.Physical); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + if (pI830->Clone) { + temp &= ~MCURSOR_PIPE_SELECT; + temp |= (!pI830->pipe << 28); + OUTREG(CURSOR_B_CONTROL, temp); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } } else { temp = INREG(CURSOR_CONTROL); temp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE | @@ -97,7 +111,10 @@ I830InitHWCursor(ScrnInfoPtr pScrn) /* This initialises the format and leave the cursor disabled. */ OUTREG(CURSOR_CONTROL, temp); /* Need to set address and size after disabling. */ - OUTREG(CURSOR_BASEADDR, pI830->CursorMem.Start); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start); temp = ((I810_CURSOR_X & CURSOR_SIZE_MASK) << CURSOR_SIZE_HSHIFT) | ((I810_CURSOR_Y & CURSOR_SIZE_MASK) << CURSOR_SIZE_VSHIFT); OUTREG(CURSOR_SIZE, temp); @@ -134,7 +151,17 @@ I830CursorInit(ScreenPtr pScreen) infoPtr->ShowCursor = I830ShowCursor; infoPtr->UseHWCursor = I830UseHWCursor; - if (pI830->CursorNeedsPhysical && !pI830->CursorMem.Physical) +#ifdef ARGB_CURSOR + pI830->CursorIsARGB = FALSE; + + if (pI830->CursorMemARGB->Start) { + /* Use ARGB if we were able to allocate the 16kb needed */ + infoPtr->UseHWCursorARGB = I830UseHWCursorARGB; + infoPtr->LoadCursorARGB = I830LoadCursorARGB; + } +#endif + + if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) return FALSE; I830HideCursor(pScrn); @@ -149,7 +176,7 @@ I830UseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) I830Ptr pI830 = I830PTR(pScrn); DPRINTF(PFX, "I830UseHWCursor\n"); - if (pI830->CursorNeedsPhysical && !pI830->CursorMem.Physical) + if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) return FALSE; return TRUE; @@ -159,10 +186,15 @@ static void I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) { I830Ptr pI830 = I830PTR(pScrn); - CARD8 *pcurs = (CARD8 *) (pI830->FbBase + pI830->CursorMem.Start); + CARD8 *pcurs = (CARD8 *) (pI830->FbBase + pI830->CursorMem->Start); int x, y; DPRINTF(PFX, "I830LoadCursorImage\n"); + +#ifdef ARGB_CURSOR + pI830->CursorIsARGB = FALSE; +#endif + for (y = 0; y < 64; y++) { for (x = 0; x < 64 / 4; x++) { *pcurs++ = *src++; @@ -170,6 +202,59 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) } } +#ifdef ARGB_CURSOR +#include "cursorstr.h" + +static Bool I830UseHWCursorARGB (ScreenPtr pScreen, CursorPtr pCurs) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + + DPRINTF(PFX, "I830UseHWCursorARGB\n"); + if (pScrn->bitsPerPixel == 8) + return FALSE; + + if (pI830->CursorNeedsPhysical && !pI830->CursorMemARGB->Physical) + return FALSE; + + if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64) + return TRUE; + + return FALSE; +} + +static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs) +{ + I830Ptr pI830 = I830PTR(pScrn); + CARD32 *dst = (CARD32 *) (pI830->FbBase + pI830->CursorMemARGB->Start); + CARD32 *image = (CARD32 *)pCurs->bits->argb; + int x, y, w, h; + + DPRINTF(PFX, "I830LoadCursorARGB\n"); + + if (!image) + return; /* XXX can't happen */ + +#ifdef ARGB_CURSOR + pI830->CursorIsARGB = TRUE; +#endif + + w = pCurs->bits->width; + h = pCurs->bits->height; + + for(y = 0; y < h; y++) { + for(x = 0; x < w; x++) + *dst++ = *image++; + for(; x < 64; x++) + *dst++ = 0; + } + + for(; y < 64; y++) { + for(x = 0; x < 64; x++) + *dst++ = 0; + } +} +#endif static void I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) @@ -207,6 +292,8 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); OUTREG(CURSOR_A_POSITION, temp); + if (pI830->Clone) + OUTREG(CURSOR_B_POSITION, temp); if (pI830->cursorOn) { if (hide) @@ -215,6 +302,20 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) pI830->CursorInfoRec->ShowCursor(pScrn); pI830->cursorOn = TRUE; } + + /* have to upload the base for the new position */ + if (IS_I915G(pI830)) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + if (pI830->Clone) { + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } + } } static void @@ -225,22 +326,51 @@ I830ShowCursor(ScrnInfoPtr pScrn) DPRINTF(PFX, "I830ShowCursor\n"); DPRINTF(PFX, - "Value of CursorMem.Physical is %x, " - " Value of CursorMem.Start is %x ", - pI830->CursorMem.Physical, pI830->CursorMem.Start); + "Value of CursorMem->Physical is %x, " + " Value of CursorMem->Start is %x ", + pI830->CursorMem->Physical, pI830->CursorMem->Start); + DPRINTF(PFX, + "Value of CursorMemARGB->Physical is %x, " + " Value of CursorMemARGB->Start is %x ", + pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start); pI830->cursorOn = TRUE; - if (IS_MOBILE(pI830)) { + if (IS_MOBILE(pI830) || IS_I915G(pI830)) { temp = INREG(CURSOR_A_CONTROL); - temp &= ~CURSOR_MODE; - temp |= CURSOR_MODE_64_4C_AX; + temp &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT); + if (pI830->CursorIsARGB) + temp |= CURSOR_MODE_64_ARGB_AX; + else + temp |= CURSOR_MODE_64_4C_AX; + temp |= (pI830->pipe << 28); /* Connect to correct pipe */ /* Need to set mode, then address. */ OUTREG(CURSOR_A_CONTROL, temp); - OUTREG(CURSOR_A_BASE, pI830->CursorMem.Physical); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + if (pI830->Clone) { + temp &= ~MCURSOR_PIPE_SELECT; + temp |= (!pI830->pipe << 28); + OUTREG(CURSOR_B_CONTROL, temp); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } } else { temp = INREG(CURSOR_CONTROL); + temp &= ~(CURSOR_FORMAT_MASK); temp |= CURSOR_ENABLE; + if (pI830->CursorIsARGB) + temp |= CURSOR_FORMAT_ARGB; + else + temp |= CURSOR_FORMAT_3C; OUTREG(CURSOR_CONTROL, temp); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_BASEADDR, pI830->CursorMemARGB->Start); + else + OUTREG(CURSOR_BASEADDR, pI830->CursorMem->Start); } } @@ -253,13 +383,23 @@ I830HideCursor(ScrnInfoPtr pScrn) DPRINTF(PFX, "I830HideCursor\n"); pI830->cursorOn = FALSE; - if (IS_MOBILE(pI830)) { + if (IS_MOBILE(pI830) || IS_I915G(pI830)) { temp = INREG(CURSOR_A_CONTROL); temp &= ~CURSOR_MODE; temp |= CURSOR_MODE_DISABLE; OUTREG(CURSOR_A_CONTROL, temp); /* This is needed to flush the above change. */ - OUTREG(CURSOR_A_BASE, pI830->CursorMem.Physical); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_A_BASE, pI830->CursorMem->Physical); + if (pI830->Clone) { + OUTREG(CURSOR_B_CONTROL, temp); + if (pI830->CursorIsARGB) + OUTREG(CURSOR_B_BASE, pI830->CursorMemARGB->Physical); + else + OUTREG(CURSOR_B_BASE, pI830->CursorMem->Physical); + } } else { temp = INREG(CURSOR_CONTROL); temp &= ~CURSOR_ENABLE; @@ -272,10 +412,22 @@ I830SetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) { I830Ptr pI830 = I830PTR(pScrn); +#ifdef ARGB_CURSOR + /* Don't recolour cursors set with SetCursorARGB. */ + if (pI830->CursorIsARGB) + return; +#endif + DPRINTF(PFX, "I830SetCursorColors\n"); OUTREG(CURSOR_A_PALETTE0, bg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE1, fg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE2, fg & 0x00ffffff); OUTREG(CURSOR_A_PALETTE3, bg & 0x00ffffff); + if (pI830->Clone) { + OUTREG(CURSOR_B_PALETTE0, bg & 0x00ffffff); + OUTREG(CURSOR_B_PALETTE1, fg & 0x00ffffff); + OUTREG(CURSOR_B_PALETTE2, fg & 0x00ffffff); + OUTREG(CURSOR_B_PALETTE3, bg & 0x00ffffff); + } } diff --git a/src/i830_dga.c b/src/i830_dga.c index bb4c103a..b1416598 100644 --- a/src/i830_dga.c +++ b/src/i830_dga.c @@ -34,7 +34,7 @@ * with <TAB> characters expanded at 8-column intervals. */ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dga.c,v 1.3 2003/02/26 04:11:23 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dga.c,v 1.2 2002/11/05 02:01:18 dawes Exp $ */ #include "xf86.h" #include "xf86_OSproc.h" @@ -281,7 +281,12 @@ I830_OpenFramebuffer(ScrnInfoPtr pScrn, *name = NULL; /* no special device */ *mem = (unsigned char *)(pI830->LinearAddr + pScrn->fbOffset); - *size = pI830->FrontBuffer.Size; + if (pI830->init == 0) + *size = pI830->FrontBuffer.Size; + else { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + *size = pI8301->FrontBuffer2.Size; + } *offset = 0; *flags = DGA_NEED_ROOT; diff --git a/src/i830_dri.c b/src/i830_dri.c index 9ed9bb79..9e236f98 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -73,10 +73,9 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "i830.h" #include "i830_dri.h" -#include "i830_3d_reg.h" -static char I830KernelDriverName[] = "i830"; -static char I830ClientDriverName[] = "i830"; +static char I830KernelDriverName[] = "i915"; +static char I830ClientDriverName[] = "i915"; static Bool I830InitVisualConfigs(ScreenPtr pScreen); static Bool I830CreateContext(ScreenPtr pScreen, VisualPtr visual, @@ -128,7 +127,7 @@ static Bool I830InitDma(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - I830RingBuffer *ring = &(pI830->LpRing); + I830RingBuffer *ring = pI830->LpRing; I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; drmI830Init info; @@ -140,7 +139,6 @@ I830InitDma(ScrnInfoPtr pScrn) info.ring_size = ring->mem.Size; info.mmio_offset = (unsigned int)pI830DRI->regs; - info.buffers_offset = (unsigned int)pI830->buffer_map; info.sarea_priv_offset = sizeof(XF86DRISAREARec); @@ -149,10 +147,9 @@ I830InitDma(ScrnInfoPtr pScrn) info.depth_offset = pI830->DepthBuffer.Start; info.w = pScrn->virtualX; info.h = pScrn->virtualY; - info.pitch = pI830->auxPitch; - info.pitch_bits = pI830->auxPitchBits; - info.back_pitch = pI830->auxPitch; - info.depth_pitch = pI830->auxPitch; + info.pitch = pI830->backPitch; + info.back_pitch = pI830->backPitch; + info.depth_pitch = pI830->backPitch; info.cpp = pI830->cpp; if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT, @@ -241,6 +238,7 @@ I830InitVisualConfigs(ScreenPtr pScreen) pConfigs[i].redSize = 5; pConfigs[i].greenSize = 6; pConfigs[i].blueSize = 5; + pConfigs[i].alphaSize = 0; pConfigs[i].redMask = 0x0000F800; pConfigs[i].greenMask = 0x000007E0; pConfigs[i].blueMask = 0x0000001F; @@ -270,10 +268,10 @@ I830InitVisualConfigs(ScreenPtr pScreen) pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (stencil || accum) - pConfigs[i].visualRating = GLX_SLOW_CONFIG; + pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; else - pConfigs[i].visualRating = GLX_NONE; - pConfigs[i].transparentPixel = GLX_NONE; + pConfigs[i].visualRating = GLX_NONE_EXT; + pConfigs[i].transparentPixel = GLX_NONE_EXT; pConfigs[i].transparentRed = 0; pConfigs[i].transparentGreen = 0; pConfigs[i].transparentBlue = 0; @@ -328,7 +326,7 @@ I830InitVisualConfigs(ScreenPtr pScreen) pConfigs[i].redMask = 0x00FF0000; pConfigs[i].greenMask = 0x0000FF00; pConfigs[i].blueMask = 0x000000FF; - pConfigs[i].alphaMask = 0xFF000000;; + pConfigs[i].alphaMask = 0xFF000000; if (accum) { pConfigs[i].accumRedSize = 16; pConfigs[i].accumGreenSize = 16; @@ -357,11 +355,11 @@ I830InitVisualConfigs(ScreenPtr pScreen) pConfigs[i].auxBuffers = 0; pConfigs[i].level = 0; if (accum) { - pConfigs[i].visualRating = GLX_SLOW_CONFIG; + pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT; } else { - pConfigs[i].visualRating = GLX_NONE; + pConfigs[i].visualRating = GLX_NONE_EXT; } - pConfigs[i].transparentPixel = GLX_NONE; + pConfigs[i].transparentPixel = GLX_NONE_EXT; pConfigs[i].transparentRed = 0; pConfigs[i].transparentGreen = 0; pConfigs[i].transparentBlue = 0; @@ -468,7 +466,7 @@ I830DRIScreenInit(ScreenPtr pScreen) else pDRIInfo->maxDrawableTableEntry = I830_MAX_DRAWABLES; - if (sizeof(XF86DRISAREARec) + sizeof(I830SAREARec) > SAREA_MAX) { + if (sizeof(XF86DRISAREARec) + sizeof(drmI830Sarea) > SAREA_MAX) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] Data does not fit in SAREA\n"); return FALSE; @@ -554,14 +552,14 @@ I830DRIScreenInit(ScreenPtr pScreen) drmFreeVersion(version); } - /* Check the i830 DRM version */ + /* Check the i915 DRM version */ version = drmGetVersion(pI830->drmSubFD); if (version) { - if (version->version_major != 1 || version->version_minor < 3) { + if (version->version_major != 1 || version->version_minor < 1) { /* incompatible drm version */ xf86DrvMsg(pScreen->myNum, X_ERROR, "[dri] %s failed because of a version mismatch.\n" - "[dri] i830.o kernel module version is %d.%d.%d but version 1.3 or greater is needed.\n" + "[dri] i915 kernel module version is %d.%d.%d but version 1.1 or greater is needed.\n" "[dri] Disabling DRI.\n", "I830DRIScreenInit", version->version_major, @@ -584,7 +582,6 @@ I830DRIDoMappings(ScreenPtr pScreen) I830Ptr pI830 = I830PTR(pScrn); DRIInfoPtr pDRIInfo = pI830->pDRIInfo; I830DRIPtr pI830DRI = pDRIInfo->devPrivate; - int bufs; DPRINTF(PFX, "I830DRIDoMappings\n"); pI830DRI->regsSize = I830_REG_SIZE; @@ -601,8 +598,7 @@ I830DRIDoMappings(ScreenPtr pScreen) * The tile setup is now initiated from I830BIOSScreenInit(). */ - pI830->auxPitch = pScrn->displayWidth; - pI830->auxPitchBits = 0; + pI830->backPitch = pScrn->displayWidth; pI830DRI->backbufferSize = pI830->BackBuffer.Size; @@ -631,24 +627,10 @@ I830DRIDoMappings(ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Depth Buffer = 0x%08lx\n", pI830DRI->depthbuffer); - if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)pI830->BufferMem.Start + pI830->LinearAddr, - pI830->BufferMem.Size, DRM_AGP, 0, - &pI830->buffer_map) < 0) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[drm] drmAddMap(buffer_map) failed. Disabling DRI\n"); - DRICloseScreen(pScreen); - return FALSE; - } - xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] DMA Buffers = 0x%08lx\n", - pI830->buffer_map); - - pI830DRI->agp_buffers = pI830->buffer_map; - pI830DRI->agp_buf_size = pI830->BufferMem.Size; if (drmAddMap(pI830->drmSubFD, - (drm_handle_t)pI830->LpRing.mem.Start + pI830->LinearAddr, - pI830->LpRing.mem.Size, DRM_AGP, 0, + (drm_handle_t)pI830->LpRing->mem.Start + pI830->LinearAddr, + pI830->LpRing->mem.Size, DRM_AGP, 0, &pI830->ring_map) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(ring_map) failed. Disabling DRI\n"); @@ -673,20 +655,6 @@ I830DRIDoMappings(ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] textures = 0x%08lx\n", pI830DRI->textures); - if ((bufs = drmAddBufs(pI830->drmSubFD, - I830_DMA_BUF_NR, - I830_DMA_BUF_SZ, - DRM_AGP_BUFFER, pI830DRI->agp_buffers)) <= 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] failure adding %d %d byte DMA buffers\n", - I830_DMA_BUF_NR, I830_DMA_BUF_SZ); - DRICloseScreen(pScreen); - return FALSE; - } - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] added %d %d byte DMA buffers\n", bufs, I830_DMA_BUF_SZ); - I830InitDma(pScrn); if (pI830->PciInfo->chipType != PCI_CHIP_845_G && @@ -695,7 +663,7 @@ I830DRIDoMappings(ScreenPtr pScreen) } /* Okay now initialize the dma engine */ - if (!pI830DRI->irq) { + { pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD, ((pciConfigPtr) pI830-> PciInfo->thisCard)->busnum, @@ -703,20 +671,42 @@ I830DRIDoMappings(ScreenPtr pScreen) PciInfo->thisCard)->devnum, ((pciConfigPtr) pI830-> PciInfo->thisCard)->funcnum); -#if 1 - if ((drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] failure adding irq handler, there is a device already using that irq\n" - "[drm] Consider rearranging your PCI cards\n"); + + if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failure adding irq handler\n"); + pI830DRI->irq = 0; DRICloseScreen(pScreen); return FALSE; } -#endif + else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] dma control initialized, using IRQ %d\n", + pI830DRI->irq); + } + + /* Start up the simple memory manager for agp space */ + { + drmI830MemInitHeap drmHeap; + drmHeap.region = I830_MEM_REGION_AGP; + drmHeap.start = 0; + drmHeap.size = pI830DRI->textureSize; + + if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT_HEAP, + &drmHeap, sizeof(drmHeap))) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] Failed to initialized agp heap manager\n"); + } else { + xf86DrvMsg(pScreen->myNum, X_INFO, + "[drm] Initialized kernel agp heap manager, %d\n", + pI830DRI->textureSize); + + I830SetParam(pScrn, I830_SETPARAM_TEX_LRU_LOG_GRANULARITY, + pI830->TexGranularity); + } } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "[drm] dma control initialized, using IRQ %d\n", pI830DRI->irq); pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; pI830DRI->deviceID = pI830->PciInfo->chipType; @@ -726,7 +716,7 @@ I830DRIDoMappings(ScreenPtr pScreen) pI830DRI->cpp = pI830->cpp; pI830DRI->fbOffset = pI830->FrontBuffer.Start; - pI830DRI->fbStride = pI830->auxPitch; + pI830DRI->fbStride = pI830->backPitch; pI830DRI->bitsPerPixel = pScrn->bitsPerPixel; @@ -735,11 +725,8 @@ I830DRIDoMappings(ScreenPtr pScreen) pI830DRI->backOffset = pI830->BackBuffer.Start; pI830DRI->depthOffset = pI830->DepthBuffer.Start; - pI830DRI->ringOffset = pI830->LpRing.mem.Start; - pI830DRI->ringSize = pI830->LpRing.mem.Size; - - pI830DRI->auxPitch = pI830->auxPitch; - pI830DRI->auxPitchBits = pI830->auxPitchBits; + pI830DRI->backPitch = pI830->backPitch; + pI830DRI->depthPitch = pI830->backPitch; pI830DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); if (!(I830InitVisualConfigs(pScreen))) { @@ -804,7 +791,7 @@ I830DestroyContext(ScreenPtr pScreen, drm_context_t hwContext, Bool I830DRIFinishScreenInit(ScreenPtr pScreen) { - I830SAREARec *sPriv = (I830SAREARec *) DRIGetSAREAPrivate(pScreen); + drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); @@ -814,7 +801,7 @@ I830DRIFinishScreenInit(ScreenPtr pScreen) /* Have shadow run only while there is 3d active. */ - if (pI830->allowPageFlip && pI830->drmMinor >= 3) { + if (pI830->allowPageFlip && pI830->drmMinor >= 1) { shadowSetup(pScreen); shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0); } @@ -832,9 +819,6 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - if (!pScrn->vtSema) - return; - if (syncType == DRI_3D_SYNC && oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -842,6 +826,8 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, if (I810_DEBUG & DEBUG_VERBOSE_DRI) ErrorF("i830DRISwapContext (in)\n"); + if (!pScrn->vtSema) + return; pI830->LockHeld = 1; I830RefreshRing(pScrn); } else if (syncType == DRI_2D_SYNC && @@ -1057,445 +1043,26 @@ I830DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, pI830->AccelInfoRec->NeedToSync = TRUE; } -/* Completely Initialize the first context */ +/* Initialize the first context */ void I830EmitInvarientState(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); - I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; - CARD32 ctx_addr, temp; + CARD32 ctx_addr; - BEGIN_LP_RING(128-2); ctx_addr = pI830->ContextMem.Start; /* Align to a 2k boundry */ ctx_addr = ((ctx_addr + 2048 - 1) / 2048) * 2048; - OUT_RING(MI_SET_CONTEXT); - OUT_RING(ctx_addr | - CTXT_NO_RESTORE | - CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE); - - OUT_RING(STATE3D_AA_CMD | - AA_LINE_ECAAR_WIDTH_ENABLE | - AA_LINE_ECAAR_WIDTH_1_0 | - AA_LINE_REGION_WIDTH_ENABLE | - AA_LINE_REGION_WIDTH_1_0 | AA_LINE_DISABLE); - - OUT_RING(STATE3D_BUF_INFO_CMD); - OUT_RING(BUF_3D_ID_COLOR_BACK | - BUF_3D_USE_FENCE | - BUF_3D_PITCH((pI830->cpp * pScrn->displayWidth) / 4)); - OUT_RING(BUF_3D_ADDR(pI830DRI->backOffset)); - - OUT_RING(STATE3D_BUF_INFO_CMD); - OUT_RING(BUF_3D_ID_DEPTH | - BUF_3D_USE_FENCE | - BUF_3D_PITCH((pI830->cpp * pScrn->displayWidth) / 4)); - OUT_RING(BUF_3D_ADDR(pI830DRI->depthOffset)); - - OUT_RING(STATE3D_COLOR_FACTOR); - OUT_RING(0); - - OUT_RING(STATE3D_COLOR_FACTOR_CMD(0)); - OUT_RING(0); - - OUT_RING(STATE3D_COLOR_FACTOR_CMD(1)); - OUT_RING(0); - - OUT_RING(STATE3D_COLOR_FACTOR_CMD(2)); - OUT_RING(0); - - OUT_RING(STATE3D_COLOR_FACTOR_CMD(3)); - OUT_RING(0); - - OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD); - OUT_RING(0); - - OUT_RING(STATE3D_DFLT_DIFFUSE_CMD); - OUT_RING(0); - - OUT_RING(STATE3D_DFLT_SPEC_CMD); - OUT_RING(0); - - OUT_RING(STATE3D_DFLT_Z_CMD); - OUT_RING(0); - - switch (pScrn->bitsPerPixel) { - case 15: - temp = DEPTH_FRMT_16_FIXED | COLR_BUF_RGB555; - break; - case 16: - temp = DEPTH_FRMT_16_FIXED | COLR_BUF_RGB565; - break; - case 32: - temp = DEPTH_FRMT_24_FIXED_8_OTHER | COLR_BUF_ARGB8888; - break; - default: - temp = DEPTH_FRMT_16_FIXED | COLR_BUF_RGB565; - break; + { + BEGIN_LP_RING(2); + OUT_RING(MI_SET_CONTEXT); + OUT_RING(ctx_addr | + CTXT_NO_RESTORE | + CTXT_PALETTE_SAVE_DISABLE | CTXT_PALETTE_RESTORE_DISABLE); + ADVANCE_LP_RING(); } - - OUT_RING(STATE3D_DST_BUF_VARS_CMD); - OUT_RING(DSTORG_HORT_BIAS(0x8) | - DSTORG_VERT_BIAS(0x8) | DEPTH_IS_Z | temp); - - OUT_RING(STATE3D_DRAW_RECT_CMD); - OUT_RING(DRAW_RECT_DIS_DEPTH_OFS); - OUT_RING(0); - OUT_RING((pI830DRI->height << 16) | pI830DRI->width); - OUT_RING(0); - - OUT_RING(STATE3D_ENABLES_1_CMD | - DISABLE_LOGIC_OP | - DISABLE_STENCIL_TEST | - DISABLE_DEPTH_BIAS | - DISABLE_SPEC_ADD | - I830_DISABLE_FOG | - DISABLE_ALPHA_TEST | DISABLE_COLOR_BLEND | DISABLE_DEPTH_TEST); - - OUT_RING(STATE3D_ENABLES_2_CMD | - DISABLE_STENCIL_WRITE | - ENABLE_TEX_CACHE | - ENABLE_DITHER | - ENABLE_COLOR_MASK | ENABLE_COLOR_WRITE | ENABLE_DEPTH_WRITE); - - OUT_RING(STATE3D_FOG_COLOR_CMD | - FOG_COLOR_RED(0) | FOG_COLOR_GREEN(0) | FOG_COLOR_BLUE(0)); - - OUT_RING(STATE3D_FOG_MODE); - OUT_RING(FOG_MODE_VERTEX | - ENABLE_FOG_CONST | ENABLE_FOG_SOURCE | ENABLE_FOG_DENSITY); - OUT_RING(0); - OUT_RING(0); - - OUT_RING(STATE3D_INDPT_ALPHA_BLEND_CMD | - DISABLE_INDPT_ALPHA_BLEND | - ENABLE_ALPHA_BLENDFUNC | - ABLENDFUNC_ADD | - ENABLE_SRC_ABLEND_FACTOR | - SRC_ABLEND_FACT(BLENDFACT_ONE) | - ENABLE_DST_ABLEND_FACTOR | SRC_ABLEND_FACT(BLENDFACT_ZERO)); - - /* I need to come back to texture state */ - OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(0) | - TEXPIPE_COLOR | - TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE); - OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(1) | - TEXPIPE_COLOR | - TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE); - OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(2) | - TEXPIPE_COLOR | - TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE); - OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(3) | - TEXPIPE_COLOR | - TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE); - - OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(0) | - TEXPIPE_ALPHA | - TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE); - OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(1) | - TEXPIPE_ALPHA | - TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE); - OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(2) | - TEXPIPE_ALPHA | - TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE); - OUT_RING(STATE3D_MAP_BLEND_ARG_CMD(3) | - TEXPIPE_ALPHA | - TEXBLEND_ARG1 | TEXBLENDARG_MODIFY_PARMS | TEXBLENDARG_DIFFUSE); - - OUT_RING(STATE3D_MAP_BLEND_OP_CMD(0) | - TEXPIPE_COLOR | - ENABLE_TEXOUTPUT_WRT_SEL | - TEXOP_OUTPUT_CURRENT | - DISABLE_TEX_CNTRL_STAGE | - TEXOP_SCALE_1X | - TEXOP_MODIFY_PARMS | TEXOP_LAST_STAGE | TEXBLENDOP_ARG1); - OUT_RING(STATE3D_MAP_BLEND_OP_CMD(0) | - TEXPIPE_ALPHA | - ENABLE_TEXOUTPUT_WRT_SEL | - TEXOP_OUTPUT_CURRENT | - TEXOP_SCALE_1X | TEXOP_MODIFY_PARMS | TEXBLENDOP_ARG1); - - OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD); - OUT_RING(TEXBIND_SET3(TEXCOORDSRC_DEFAULT) | - TEXBIND_SET2(TEXCOORDSRC_DEFAULT) | - TEXBIND_SET1(TEXCOORDSRC_DEFAULT) | - TEXBIND_SET0(TEXCOORDSRC_DEFAULT)); - - OUT_RING(STATE3D_MAP_COORD_SET_CMD | - MAP_UNIT(0) | - TEXCOORDS_ARE_IN_TEXELUNITS | - TEXCOORDTYPE_CARTESIAN | - ENABLE_ADDR_V_CNTL | - ENABLE_ADDR_U_CNTL | - TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) | - TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP)); - OUT_RING(STATE3D_MAP_COORD_SET_CMD | - MAP_UNIT(1) | - TEXCOORDS_ARE_IN_TEXELUNITS | - TEXCOORDTYPE_CARTESIAN | - ENABLE_ADDR_V_CNTL | - ENABLE_ADDR_U_CNTL | - TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) | - TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP)); - OUT_RING(STATE3D_MAP_COORD_SET_CMD | - MAP_UNIT(2) | - TEXCOORDS_ARE_IN_TEXELUNITS | - TEXCOORDTYPE_CARTESIAN | - ENABLE_ADDR_V_CNTL | - ENABLE_ADDR_U_CNTL | - TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) | - TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP)); - OUT_RING(STATE3D_MAP_COORD_SET_CMD | - MAP_UNIT(3) | - TEXCOORDS_ARE_IN_TEXELUNITS | - TEXCOORDTYPE_CARTESIAN | - ENABLE_ADDR_V_CNTL | - ENABLE_ADDR_U_CNTL | - TEXCOORD_ADDR_V_MODE(TEXCOORDMODE_CLAMP) | - TEXCOORD_ADDR_U_MODE(TEXCOORDMODE_CLAMP)); - - OUT_RING(STATE3D_MAP_TEX_STREAM_CMD | - MAP_UNIT(0) | - DISABLE_TEX_STREAM_BUMP | - ENABLE_TEX_STREAM_COORD_SET | - TEX_STREAM_COORD_SET(0) | - ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(0)); - OUT_RING(STATE3D_MAP_TEX_STREAM_CMD | - MAP_UNIT(1) | - DISABLE_TEX_STREAM_BUMP | - ENABLE_TEX_STREAM_COORD_SET | - TEX_STREAM_COORD_SET(1) | - ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(1)); - OUT_RING(STATE3D_MAP_TEX_STREAM_CMD | - MAP_UNIT(2) | - DISABLE_TEX_STREAM_BUMP | - ENABLE_TEX_STREAM_COORD_SET | - TEX_STREAM_COORD_SET(2) | - ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(2)); - OUT_RING(STATE3D_MAP_TEX_STREAM_CMD | - MAP_UNIT(3) | - DISABLE_TEX_STREAM_BUMP | - ENABLE_TEX_STREAM_COORD_SET | - TEX_STREAM_COORD_SET(3) | - ENABLE_TEX_STREAM_MAP_IDX | TEX_STREAM_MAP_IDX(3)); - -#if 0 - OUT_RING(STATE3D_MAP_FILTER_CMD | - MAP_UNIT(0) | - ENABLE_CHROMA_KEY_PARAMS | - ENABLE_MIP_MODE_FILTER | - MIPFILTER_NEAREST | - ENABLE_MAG_MODE_FILTER | - ENABLE_MIN_MODE_FILTER | - MAG_FILTER(FILTER_NEAREST) | MIN_FILTER(FILTER_NEAREST)); - OUT_RING(STATE3D_MAP_FILTER_CMD | - MAP_UNIT(1) | - ENABLE_CHROMA_KEY_PARAMS | - ENABLE_MIP_MODE_FILTER | - MIPFILTER_NEAREST | - ENABLE_MAG_MODE_FILTER | - ENABLE_MIN_MODE_FILTER | - MAG_FILTER(FILTER_NEAREST) | MIN_FILTER(FILTER_NEAREST)); - OUT_RING(STATE3D_MAP_FILTER_CMD | - MAP_UNIT(2) | - ENABLE_CHROMA_KEY_PARAMS | - ENABLE_MIP_MODE_FILTER | - MIPFILTER_NEAREST | - ENABLE_MAG_MODE_FILTER | - ENABLE_MIN_MODE_FILTER | - MAG_FILTER(FILTER_NEAREST) | MIN_FILTER(FILTER_NEAREST)); - OUT_RING(STATE3D_MAP_FILTER_CMD | - MAP_UNIT(3) | - ENABLE_CHROMA_KEY_PARAMS | - ENABLE_MIP_MODE_FILTER | - MIPFILTER_NEAREST | - ENABLE_MAG_MODE_FILTER | - ENABLE_MIN_MODE_FILTER | - MAG_FILTER(FILTER_NEAREST) | MIN_FILTER(FILTER_NEAREST)); - - OUT_RING(STATE3D_MAP_INFO_COLR_CMD); - OUT_RING(MAP_INFO_TEX(0) | - MAPSURF_32BIT | - MT_32BIT_ARGB8888 | - MAP_INFO_OUTMUX_F0F1F2F3 | - MAP_INFO_VERTLINESTRIDEOFS_0 | - MAP_INFO_FORMAT_2D | MAP_INFO_USE_FENCE); - OUT_RING(MAP_INFO_HEIGHT(0) | MAP_INFO_WIDTH(0)); - OUT_RING(MAP_INFO_BASEADDR(pI830->TexMem.Start)); - OUT_RING(MAP_INFO_DWORD_PITCH(31)); - OUT_RING(MAP_INFO_DFLT_COLR(0)); - - OUT_RING(STATE3D_MAP_INFO_COLR_CMD); - OUT_RING(MAP_INFO_TEX(1) | - MAPSURF_32BIT | - MT_32BIT_ARGB8888 | - MAP_INFO_OUTMUX_F0F1F2F3 | - MAP_INFO_VERTLINESTRIDEOFS_0 | - MAP_INFO_FORMAT_2D | MAP_INFO_USE_FENCE); - OUT_RING(MAP_INFO_HEIGHT(0) | MAP_INFO_WIDTH(0)); - OUT_RING(MAP_INFO_BASEADDR(pI830->TexMem.Start)); - OUT_RING(MAP_INFO_DWORD_PITCH(31)); - OUT_RING(MAP_INFO_DFLT_COLR(0)); - - OUT_RING(STATE3D_MAP_INFO_COLR_CMD); - OUT_RING(MAP_INFO_TEX(2) | - MAPSURF_32BIT | - MT_32BIT_ARGB8888 | - MAP_INFO_OUTMUX_F0F1F2F3 | - MAP_INFO_VERTLINESTRIDEOFS_0 | - MAP_INFO_FORMAT_2D | MAP_INFO_USE_FENCE); - OUT_RING(MAP_INFO_HEIGHT(0) | MAP_INFO_WIDTH(0)); - OUT_RING(MAP_INFO_BASEADDR(pI830->TexMem.Start)); - OUT_RING(MAP_INFO_DWORD_PITCH(31)); - OUT_RING(MAP_INFO_DFLT_COLR(0)); - - OUT_RING(STATE3D_MAP_INFO_COLR_CMD); - OUT_RING(MAP_INFO_TEX(3) | - MAPSURF_32BIT | - MT_32BIT_ARGB8888 | - MAP_INFO_OUTMUX_F0F1F2F3 | - MAP_INFO_VERTLINESTRIDEOFS_0 | - MAP_INFO_FORMAT_2D | MAP_INFO_USE_FENCE); - OUT_RING(MAP_INFO_HEIGHT(0) | MAP_INFO_WIDTH(0)); - OUT_RING(MAP_INFO_BASEADDR(pI830->TexMem.Start)); - OUT_RING(MAP_INFO_DWORD_PITCH(31)); - OUT_RING(MAP_INFO_DFLT_COLR(0)); - - OUT_RING(STATE3D_MAP_LOD_CNTL_CMD | - MAP_UNIT(0) | ENABLE_TEXLOD_BIAS | MAP_LOD_BIAS(0)); - OUT_RING(STATE3D_MAP_LOD_CNTL_CMD | - MAP_UNIT(1) | ENABLE_TEXLOD_BIAS | MAP_LOD_BIAS(0)); - OUT_RING(STATE3D_MAP_LOD_CNTL_CMD | - MAP_UNIT(2) | ENABLE_TEXLOD_BIAS | MAP_LOD_BIAS(0)); - OUT_RING(STATE3D_MAP_LOD_CNTL_CMD | - MAP_UNIT(3) | ENABLE_TEXLOD_BIAS | MAP_LOD_BIAS(0)); - - OUT_RING(STATE3D_MAP_LOD_LIMITS_CMD | - MAP_UNIT(0) | - ENABLE_MAX_MIP_LVL | - ENABLE_MIN_MIP_LVL | LOD_MAX(0) | LOD_MIN(0)); - OUT_RING(STATE3D_MAP_LOD_LIMITS_CMD | - MAP_UNIT(1) | - ENABLE_MAX_MIP_LVL | - ENABLE_MIN_MIP_LVL | LOD_MAX(0) | LOD_MIN(0)); - OUT_RING(STATE3D_MAP_LOD_LIMITS_CMD | - MAP_UNIT(2) | - ENABLE_MAX_MIP_LVL | - ENABLE_MIN_MIP_LVL | LOD_MAX(0) | LOD_MIN(0)); - OUT_RING(STATE3D_MAP_LOD_LIMITS_CMD | - MAP_UNIT(3) | - ENABLE_MAX_MIP_LVL | - ENABLE_MIN_MIP_LVL | LOD_MAX(0) | LOD_MIN(0)); -#endif - - OUT_RING(STATE3D_MAP_COORD_TRANSFORM); - OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(0)); - OUT_RING(STATE3D_MAP_COORD_TRANSFORM); - OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(1)); - OUT_RING(STATE3D_MAP_COORD_TRANSFORM); - OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(2)); - OUT_RING(STATE3D_MAP_COORD_TRANSFORM); - OUT_RING(DISABLE_TEX_TRANSFORM | TEXTURE_SET(3)); - - /* End texture state */ - - OUT_RING(STATE3D_MODES_1_CMD | - ENABLE_COLR_BLND_FUNC | - BLENDFUNC_ADD | - ENABLE_SRC_BLND_FACTOR | - ENABLE_DST_BLND_FACTOR | - SRC_BLND_FACT(BLENDFACT_ONE) | DST_BLND_FACT(BLENDFACT_ZERO)); - - OUT_RING(STATE3D_MODES_2_CMD | - ENABLE_GLOBAL_DEPTH_BIAS | - GLOBAL_DEPTH_BIAS(0) | - ENABLE_ALPHA_TEST_FUNC | - ALPHA_TEST_FUNC(COMPAREFUNC_ALWAYS) | ALPHA_REF_VALUE(0)); - - OUT_RING(STATE3D_MODES_3_CMD | - ENABLE_DEPTH_TEST_FUNC | - DEPTH_TEST_FUNC(COMPAREFUNC_LESS) | - ENABLE_ALPHA_SHADE_MODE | - ALPHA_SHADE_MODE(SHADE_MODE_LINEAR) | - ENABLE_FOG_SHADE_MODE | - FOG_SHADE_MODE(SHADE_MODE_LINEAR) | - ENABLE_SPEC_SHADE_MODE | - SPEC_SHADE_MODE(SHADE_MODE_LINEAR) | - ENABLE_COLOR_SHADE_MODE | - COLOR_SHADE_MODE(SHADE_MODE_LINEAR) | - ENABLE_CULL_MODE | CULLMODE_NONE); - - OUT_RING(STATE3D_MODES_4_CMD | - ENABLE_LOGIC_OP_FUNC | - LOGIC_OP_FUNC(LOGICOP_COPY) | - ENABLE_STENCIL_TEST_MASK | - STENCIL_TEST_MASK(0xff) | - ENABLE_STENCIL_WRITE_MASK | STENCIL_WRITE_MASK(0xff)); - - OUT_RING(STATE3D_MODES_5_CMD | - ENABLE_SPRITE_POINT_TEX | - SPRITE_POINT_TEX_OFF | - FLUSH_RENDER_CACHE | - FLUSH_TEXTURE_CACHE | - ENABLE_FIXED_LINE_WIDTH | - FIXED_LINE_WIDTH(0x2) | - ENABLE_FIXED_POINT_WIDTH | FIXED_POINT_WIDTH(1)); - - OUT_RING(STATE3D_RASTER_RULES_CMD | - ENABLE_POINT_RASTER_RULE | - OGL_POINT_RASTER_RULE | - ENABLE_LINE_STRIP_PROVOKE_VRTX | - ENABLE_TRI_FAN_PROVOKE_VRTX | - ENABLE_TRI_STRIP_PROVOKE_VRTX | - LINE_STRIP_PROVOKE_VRTX(1) | - TRI_FAN_PROVOKE_VRTX(2) | TRI_STRIP_PROVOKE_VRTX(2)); - - OUT_RING(STATE3D_SCISSOR_ENABLE_CMD | DISABLE_SCISSOR_RECT); - - OUT_RING(STATE3D_SCISSOR_RECT_0_CMD); - OUT_RING(0); - OUT_RING(0); - - OUT_RING(STATE3D_STENCIL_TEST_CMD | - ENABLE_STENCIL_PARMS | - STENCIL_FAIL_OP(STENCILOP_KEEP) | - STENCIL_PASS_DEPTH_FAIL_OP(STENCILOP_KEEP) | - STENCIL_PASS_DEPTH_PASS_OP(STENCILOP_KEEP) | - ENABLE_STENCIL_TEST_FUNC | - STENCIL_TEST_FUNC(COMPAREFUNC_ALWAYS) | - ENABLE_STENCIL_REF_VALUE | STENCIL_REF_VALUE(0)); - - OUT_RING(STATE3D_VERTEX_FORMAT_CMD | - VRTX_TEX_COORD_COUNT(1) | - VRTX_HAS_SPEC | - VRTX_HAS_DIFFUSE | - VRTX_HAS_XYZW); - - OUT_RING(STATE3D_VERTEX_FORMAT_2_CMD | - VRTX_TEX_SET_0_FMT(TEXCOORDFMT_2D) | - VRTX_TEX_SET_1_FMT(TEXCOORDFMT_2D) | - VRTX_TEX_SET_2_FMT(TEXCOORDFMT_2D) | - VRTX_TEX_SET_3_FMT(TEXCOORDFMT_2D) | - VRTX_TEX_SET_4_FMT(TEXCOORDFMT_2D) | - VRTX_TEX_SET_5_FMT(TEXCOORDFMT_2D) | - VRTX_TEX_SET_6_FMT(TEXCOORDFMT_2D) | - VRTX_TEX_SET_7_FMT(TEXCOORDFMT_2D)); - - OUT_RING(STATE3D_VERTEX_TRANSFORM); - OUT_RING(DISABLE_VIEWPORT_TRANSFORM | DISABLE_PERSPECTIVE_DIVIDE); - - OUT_RING(STATE3D_W_STATE_CMD); - OUT_RING(MAGIC_W_STATE_DWORD1); - OUT_RING(0x3f800000 /* 1.0 in IEEE float */ ); - -#define GFX_OP_STIPPLE ((0x3<<29)|(0x1d<<24)|(0x83<<16)) - - OUT_RING(GFX_OP_STIPPLE); - OUT_RING(0); - - ADVANCE_LP_RING(); } /* Fullscreen hooks. The DRI fullscreen mode can probably be removed @@ -1551,7 +1118,7 @@ I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf) RegionPtr damage = &pBuf->damage; int i, num = REGION_NUM_RECTS(damage); BoxPtr pbox = REGION_RECTS(damage); - I830SAREARec *pSAREAPriv = DRIGetSAREAPrivate(pScreen); + drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen); int cmd, br13; /* Don't want to do this when no 3d is active and pages are @@ -1591,7 +1158,7 @@ I830EnablePageFlip(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - I830SAREARec *pSAREAPriv = DRIGetSAREAPrivate(pScreen); + drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen); pSAREAPriv->pf_enabled = pI830->allowPageFlip; pSAREAPriv->pf_active = 0; @@ -1625,7 +1192,7 @@ I830EnablePageFlip(ScreenPtr pScreen) static void I830DisablePageFlip(ScreenPtr pScreen) { - I830SAREARec *pSAREAPriv = DRIGetSAREAPrivate(pScreen); + drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen); pSAREAPriv->pf_active = 0; } @@ -1666,7 +1233,7 @@ I830DRITransitionTo2d(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - I830SAREARec *sPriv = (I830SAREARec *) DRIGetSAREAPrivate(pScreen); + drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen); /* Try flipping back to the front page if necessary */ if (sPriv->pf_current_page == 1) diff --git a/src/i830_dri.h b/src/i830_dri.h index 684d7e32..aef93a8b 100644 --- a/src/i830_dri.h +++ b/src/i830_dri.h @@ -38,24 +38,19 @@ typedef struct _I830DRIRec { int mem; int cpp; int bitsPerPixel; + int fbOffset; int fbStride; int backOffset; - int depthOffset; + int backPitch; - int auxPitch; - int auxPitchBits; + int depthOffset; + int depthPitch; int logTextureGranularity; int textureOffset; - /* For non-dma direct rendering. - */ - int ringOffset; - int ringSize; - - drmBufMapPtr drmBufs; int irq; int sarea_priv_offset; } I830DRIRec, *I830DRIPtr; @@ -70,72 +65,5 @@ typedef struct { int dummy; } I830DRIContextRec, *I830DRIContextPtr; -/* Warning: If you change the SAREA structure you must change the kernel - * structure as well */ - -typedef struct _I830SAREA { - unsigned int ContextState[I830_CTX_SETUP_SIZE]; - unsigned int BufferState[I830_DEST_SETUP_SIZE]; - unsigned int TexState[I830_TEXTURE_COUNT][I830_TEX_SETUP_SIZE]; - unsigned int TexBlendState[I830_TEXBLEND_COUNT][I830_TEXBLEND_SIZE]; - unsigned int TexBlendStateWordsUsed[I830_TEXBLEND_COUNT]; - unsigned int Palette[2][256]; - unsigned int dirty; - - unsigned int nbox; - drm_clip_rect_t boxes[I830_NR_SAREA_CLIPRECTS]; - - /* Maintain an LRU of contiguous regions of texture space. If - * you think you own a region of texture memory, and it has an - * age different to the one you set, then you are mistaken and - * it has been stolen by another client. If global texAge - * hasn't changed, there is no need to walk the list. - * - * These regions can be used as a proxy for the fine-grained - * texture information of other clients - by maintaining them - * in the same lru which is used to age their own textures, - * clients have an approximate lru for the whole of global - * texture space, and can make informed decisions as to which - * areas to kick out. There is no need to choose whether to - * kick out your own texture or someone else's - simply eject - * them all in LRU order. - */ - - drmTextureRegion texList[I830_NR_TEX_REGIONS + 1]; - /* Last elt is sentinal */ - int texAge; /* last time texture was uploaded */ - int last_enqueue; /* last time a buffer was enqueued */ - int last_dispatch; /* age of the most recently dispatched buffer */ - int last_quiescent; /* */ - int ctxOwner; /* last context to upload state */ - - int vertex_prim; - - int pf_enabled; /* is pageflipping allowed? */ - int pf_active; /* is pageflipping active right now? */ - int pf_current_page; /* which buffer is being displayed? */ - - int perf_boxes; /* performance boxes to be displayed */ - - /* Here's the state for texunits 2,3: - */ - unsigned int TexState2[I830_TEX_SETUP_SIZE]; - unsigned int TexBlendState2[I830_TEXBLEND_SIZE]; - unsigned int TexBlendStateWordsUsed2; - - unsigned int TexState3[I830_TEX_SETUP_SIZE]; - unsigned int TexBlendState3[I830_TEXBLEND_SIZE]; - unsigned int TexBlendStateWordsUsed3; - - unsigned int StippleState[I830_STP_SETUP_SIZE]; -} I830SAREARec, *I830SAREAPtr; - -/* Flags for perf_boxes - */ -#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */ -#define I830_BOX_FLIP 0x2 /* populated by kernel */ -#define I830_BOX_WAIT 0x4 /* populated by kernel & client */ -#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */ -#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */ #endif diff --git a/src/i830_driver.c b/src/i830_driver.c index 5f5c36d6..458feb28 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c,v 1.36 2003/09/03 15:32:26 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_driver.c,v 1.50 2004/02/20 00:06:00 alanh Exp $ */ /************************************************************************** Copyright 2001 VA Linux Systems Inc., Fremont, California. @@ -44,6 +44,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: Jeff Hartmann <jhartmann@valinux.com> * Abraham van der Merwe <abraham@2d3d.co.za> * David Dawes <dawes@xfree86.org> + * Alan Hourihane <alanh@tungstengraphics.com> */ /* @@ -126,17 +127,24 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * * 08/2002 Keith Whitwell * - Fix DRI initialisation. - */ -/* + * + * * 08/2002 Alan Hourihane and David Dawes * - Add XVideo support. - */ -/* + * + * * 10/2002 David Dawes * - Add Intel(R) 865G support. + * + * + * 01/2004 Alan Hourihane + * - Add Intel(R) 915G support. + * - Add Dual Head and Clone capabilities. + * - Add lid status checking + * - Fix Xvideo with high-res LFP's + * - Add ARGB HW cursor support */ - #ifndef PRINT_MODE_INFO #define PRINT_MODE_INFO 0 #endif @@ -154,7 +162,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "micmap.h" #include "fb.h" -#include "regionstr.h" +#include "miscstruct.h" #include "xf86xv.h" #include "Xv.h" #include "vbe.h" @@ -176,6 +184,7 @@ static SymTabRec I830BIOSChipsets[] = { {PCI_CHIP_845_G, "845G"}, {PCI_CHIP_I855_GM, "852GM/855GM"}, {PCI_CHIP_I865_G, "865G"}, + {PCI_CHIP_I915_G, "915G"}, {-1, NULL} }; @@ -184,6 +193,7 @@ static PciChipsets I830BIOSPciChipsets[] = { {PCI_CHIP_845_G, PCI_CHIP_845_G, RES_SHARED_VGA}, {PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA}, {PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA}, + {PCI_CHIP_I915_G, PCI_CHIP_I915_G, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED} }; @@ -202,8 +212,14 @@ typedef enum { OPTION_XVIDEO, OPTION_VIDEO_KEY, OPTION_COLOR_KEY, - OPTION_STRETCH, - OPTION_CENTER + OPTION_VBE_RESTORE, + OPTION_DISPLAY_INFO, + OPTION_DEVICE_PRESENCE, + OPTION_MONITOR_LAYOUT, + OPTION_CLONE, + OPTION_CLONE_REFRESH, + OPTION_CHECKLID, + OPTION_FLIP_PRIMARY } I830Opts; static OptionInfoRec I830BIOSOptions[] = { @@ -215,8 +231,14 @@ static OptionInfoRec I830BIOSOptions[] = { {OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, TRUE}, {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, {OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE}, - {OPTION_STRETCH, "Stretch", OPTV_BOOLEAN, {0}, FALSE}, - {OPTION_CENTER, "Center", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_VBE_RESTORE, "VBERestore", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_DISPLAY_INFO,"DisplayInfo", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_DEVICE_PRESENCE,"DevicePresence",OPTV_BOOLEAN,{0}, FALSE}, + {OPTION_MONITOR_LAYOUT, "MonitorLayout", OPTV_ANYSTR,{0}, FALSE}, + {OPTION_CLONE, "Clone", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_CLONE_REFRESH,"CloneRefresh",OPTV_INTEGER, {0}, FALSE}, + {OPTION_CHECKLID, "CheckLid", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_FLIP_PRIMARY,"FlipPrimary", OPTV_BOOLEAN, {0}, FALSE}, {-1, NULL, OPTV_NONE, {0}, FALSE} }; /* *INDENT-ON* */ @@ -229,6 +251,11 @@ static Bool I830BIOSSaveScreen(ScreenPtr pScreen, int unblack); static Bool I830BIOSEnterVT(int scrnIndex, int flags); static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock *block); +static CARD32 I830LidTimer(OsTimerPtr timer, CARD32 now, pointer arg); +static Bool SetPipeAccess(ScrnInfoPtr pScrn); +static Bool IsPrimary(ScrnInfoPtr pScrn); + +extern int I830EntityIndex; #ifdef I830DEBUG @@ -386,6 +413,8 @@ GetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh, int *availRefresh) if (mode & 0x100) return 0; + SetPipeAccess(pScrn); + pVbe->pInt10->num = 0x10; pVbe->pInt10->ax = 0x5f05; pVbe->pInt10->bx = (mode & 0xff) | 0x100; @@ -552,34 +581,103 @@ GetDisplayDevices(ScrnInfoPtr pScrn) return -1; } +/* This is needed for SetDisplayDevices to work correctly on I915G + * and possibly later Video BIOS builds around 3272 (but not sure here). + * So enable for all chipsets now as it has no bad side effects, apart + * from slightly longer startup time. + */ +#define I915G_WORKAROUND + static Bool SetDisplayDevices(ScrnInfoPtr pScrn, int devices) { I830Ptr pI830 = I830PTR(pScrn); vbeInfoPtr pVbe = pI830->pVbe; CARD32 temp; +#ifdef I915G_WORKAROUND + int getmode; + int mode; + switch (pScrn->depth) { + case 8: + mode = 0x30; + break; + case 15: + mode = 0x40; + break; + case 16: + mode = 0x41; + break; + case 24: + mode = 0x50; + break; + default: + mode = 0x30; + break; + } + mode |= (1 << 15) | (1 << 14); +#endif DPRINTF(PFX, "SetDisplayDevices: devices 0x%x\n", devices); +#ifdef I915G_WORKAROUND + if (pI830->bios_version >= 3272) { + VBEGetVBEMode(pVbe, &getmode); + I830VESASetVBEMode(pScrn, mode, NULL); + } +#endif + pVbe->pInt10->num = 0x10; pVbe->pInt10->ax = 0x5f64; pVbe->pInt10->bx = 0x1; pVbe->pInt10->cx = devices; xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); - if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) + if (Check5fStatus(pScrn, 0x5f64, pVbe->pInt10->ax)) { +#ifdef I915G_WORKAROUND + if (pI830->bios_version >= 3272) + I830VESASetVBEMode(pScrn, getmode, NULL); +#endif return TRUE; - else { - ErrorF("Writing config directly to SWF0\n"); - temp = INREG(SWF0); - OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff)); - ErrorF("SetDisplayDevices failed. devices is 0x%x instead of 0x%x\n", - GetDisplayDevices(pScrn), devices); - return FALSE; } + +#ifdef I915G_WORKAROUND + if (pI830->bios_version >= 3272) + I830VESASetVBEMode(pScrn, getmode, NULL); +#endif + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "SetDisplayDevices call failed, writing config directly to SWF0.\n"); + temp = INREG(SWF0); + OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff)); + + if (GetDisplayDevices(pScrn) != devices) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "SetDisplayDevices failed with devices 0x%x instead of 0x%x\n", + GetDisplayDevices(pScrn), devices); + + return FALSE; +} + +static Bool +GetBIOSVersion(ScrnInfoPtr pScrn, unsigned int *version) +{ + vbeInfoPtr pVbe = I830PTR(pScrn)->pVbe; + + DPRINTF(PFX, "GetBIOSVersion\n"); + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x5f01; + + xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); + if (Check5fStatus(pScrn, 0x5f01, pVbe->pInt10->ax)) { + *version = pVbe->pInt10->bx; + return TRUE; + } + + *version = 0; + return FALSE; } -#if 0 static Bool GetDevicePresence(ScrnInfoPtr pScrn, Bool *required, int *attached, int *encoderPresent) @@ -604,7 +702,6 @@ GetDevicePresence(ScrnInfoPtr pScrn, Bool *required, int *attached, } else return FALSE; } -#endif static Bool GetDisplayInfo(ScrnInfoPtr pScrn, int device, Bool *attached, Bool *present, @@ -663,8 +760,10 @@ static const char *displayDevices[] = { "TV", "DFP (digital flat panel)", "LFP (local flat panel)", + "CRT2 (second CRT)", "TV2 (second TV)", "DFP2 (second digital flat panel)", + "LFP2 (second local flat panel)", NULL }; @@ -672,7 +771,7 @@ static const char * DeviceToString(int device) { static int savedDevice = -1; - static int bit = 0; + int bit = 0; const char *name; if (device == -1) { @@ -704,7 +803,7 @@ PrintDisplayDeviceInfo(ScrnInfoPtr pScrn) DPRINTF(PFX, "PrintDisplayDeviceInfo\n"); - displays = pI830->configuredDevices; + displays = pI830->operatingDevices; if (displays == -1) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No active display devices.\n"); @@ -758,7 +857,7 @@ GetPipeSizes(ScrnInfoPtr pScrn) for (n = 0; n < pI830->availablePipes; n++) { - pipe = (pI830->configuredDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK; + pipe = (pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK; pI830->pipeDisplaySize[n].x1 = pI830->pipeDisplaySize[n].y1 = 0; pI830->pipeDisplaySize[n].x2 = pI830->pipeDisplaySize[n].y2 = 4096; for (i = 0; i < NumKnownDisplayTypes; i++) { @@ -790,47 +889,38 @@ I830DetectDisplayDevice(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); int pipe, n; DisplayType i; - - for (i = 0; i < NumKnownDisplayTypes; i++) { - if (GetDisplayInfo(pScrn, 1 << i, &pI830->displayAttached[i], + + /* This seems to lockup some Dell BIOS'. So it's on option to turn on */ + if (pI830->displayInfo) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Broken BIOSes cause the system to hang here.\n" + "\t If you encounter this problem please add \n" + "\t\t Option \"DisplayInfo\" \"FALSE\"\n" + "\t to the Device section of your XF86Config file.\n"); + for (i = 0; i < NumKnownDisplayTypes; i++) { + if (GetDisplayInfo(pScrn, 1 << i, &pI830->displayAttached[i], &pI830->displayPresent[i], &pI830->displaySize[i].x2, &pI830->displaySize[i].y2)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display Info: %s: attached: %s, present: %s, size: " "(%d,%d)\n", displayDevices[i], BOOLTOSTRING(pI830->displayAttached[i]), BOOLTOSTRING(pI830->displayPresent[i]), pI830->displaySize[i].x2, pI830->displaySize[i].y2); + } } } - pI830->configuredDevices = GetDisplayDevices(pScrn); - if (pI830->configuredDevices == -1) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Failed to detect active display devices\n"); - return FALSE; - } - /* Check for active devices connected to each display pipe. */ for (n = 0; n < pI830->availablePipes; n++) { - pipe = ((pI830->configuredDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK); + pipe = ((pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK); if (pipe) { pI830->pipeEnabled[n] = TRUE; } } GetPipeSizes(pScrn); - PrintDisplayDeviceInfo(pScrn); - -#if 0 - /* A quick hack to change the set of enabled devices. */ - enabledDevices = PIPE_CRT_ACTIVE; - if (!SetDisplayDevices(pScrn, enabledDevices)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to switch to configured display devices\n"); - } -#endif return TRUE; } @@ -842,40 +932,51 @@ I830DetectMemory(ScrnInfoPtr pScrn) PCITAG bridge; CARD16 gmch_ctrl; int memsize = 0; + int range; bridge = pciTag(0, 0, 0); /* This is always the host bridge */ gmch_ctrl = pciReadWord(bridge, I830_GMCH_CTRL); - if (IS_I85X(pI830) || IS_I865G(pI830)) - { + /* We need to reduce the stolen size, by the GTT and the popup. + * The GTT varying according the the FbMapSize and the popup is 4KB */ + range = (pI830->FbMapSize / (1024*1024)) + 4; + + if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830)) { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: - memsize = MB(1) - KB(132); + memsize = MB(1) - KB(range); break; case I855_GMCH_GMS_STOLEN_4M: - memsize = MB(4) - KB(132); + memsize = MB(4) - KB(range); break; case I855_GMCH_GMS_STOLEN_8M: - memsize = MB(8) - KB(132); + memsize = MB(8) - KB(range); break; case I855_GMCH_GMS_STOLEN_16M: - memsize = MB(16) - KB(132); + memsize = MB(16) - KB(range); break; case I855_GMCH_GMS_STOLEN_32M: - memsize = MB(32) - KB(132); + memsize = MB(32) - KB(range); + break; + case I915G_GMCH_GMS_STOLEN_48M: + if (IS_I915G(pI830)) + memsize = MB(48) - KB(range); + break; + case I915G_GMCH_GMS_STOLEN_64M: + if (IS_I915G(pI830)) + memsize = MB(64) - KB(range); break; } - } else - { + } else { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { case I830_GMCH_GMS_STOLEN_512: - memsize = KB(512) - KB(132); + memsize = KB(512) - KB(range); break; case I830_GMCH_GMS_STOLEN_1024: - memsize = MB(1) - KB(132); + memsize = MB(1) - KB(range); break; case I830_GMCH_GMS_STOLEN_8192: - memsize = MB(8) - KB(132); + memsize = MB(8) - KB(range); break; case I830_GMCH_GMS_LOCAL: memsize = 0; @@ -931,7 +1032,8 @@ I830MapMem(ScrnInfoPtr pScrn) if (!pI830->FbBase) return FALSE; - pI830->LpRing.virtual_start = pI830->FbBase + pI830->LpRing.mem.Start; + if (IsPrimary(pScrn)) + pI830->LpRing->virtual_start = pI830->FbBase + pI830->LpRing->mem.Start; return TRUE; } @@ -1063,6 +1165,93 @@ SaveBIOSMemSize(ScrnInfoPtr pScrn) return FALSE; } +/* + * TweakMemorySize() tweaks the BIOS image to set the correct size. + * Original implementation by Christian Zietz in a stand-alone tool. + */ +static CARD32 +TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize) +{ +#define SIZE 0x10000 +#define IDOFFSET (-23) + const char *MAGICstring = "Total time for VGA POST:"; + const int len = strlen(MAGICstring); + I830Ptr pI830 = I830PTR(pScrn); + char *position; + char *biosAddr; + CARD32 oldsize; + CARD32 oldpermission; + CARD32 ret = 0; + int i,j = 0; + PCITAG tag =pciTag(0,0,0); + + if(!pI830->PciInfo + || !(pI830->PciInfo->chipType == PCI_CHIP_I855_GM + || pI830->PciInfo->chipType == PCI_CHIP_I865_G)) + return 0; + + if (!pI830->pVbe) + return 0; + + biosAddr = xf86int10Addr(pI830->pVbe->pInt10, + pI830->pVbe->pInt10->BIOSseg << 4); + + if (!pI830->BIOSMemSizeLoc) { + + if (!pI830->preinit) + return 0; + + /* Search for MAGIC string */ + for (i = 0; i < SIZE; i++) { + if (biosAddr[i] == MAGICstring[j]) { + if (++j == len) + break; + } else { + i -= j; + j = 0; + } + } + if (j < len) return 0; + + pI830->BIOSMemSizeLoc = (i - j + 1 + IDOFFSET); + } + + position = biosAddr + pI830->BIOSMemSizeLoc; + oldsize = *(CARD32 *)position; + ret = oldsize - (3 << 16); + + /* verify that register really contains current size */ + if (pI830->preinit && ((oldsize) >> 16) - 3 != pI830->vbeInfo->TotalMemory) + return 0; + + oldpermission = pciReadLong(tag, DRAM_RW_CONTROL); + pciWriteLong(tag, DRAM_RW_CONTROL, 0x33330000); + + *(CARD32 *)position = newsize + (3 << 16); + if (pI830->preinit) { + /* reinitialize VBE for new size */ + VBEFreeVBEInfo(pI830->vbeInfo); + vbeFree(pI830->pVbe); + pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); + pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); + + /* verify that change was successful */ + if (pI830->vbeInfo->TotalMemory * 64 * 1024 != pI830->newBIOSMemSize) { + ret = 0; + *(CARD32 *)position = oldsize; + } else { + pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Tweak BIOS image to %d kB VideoRAM\n", + (int)(pI830->BIOSMemorySize / 1024)); + } + } + + pciWriteLong(tag, DRAM_RW_CONTROL, oldpermission); + + return ret; +} + static void RestoreBIOSMemSize(ScrnInfoPtr pScrn) { @@ -1071,6 +1260,9 @@ RestoreBIOSMemSize(ScrnInfoPtr pScrn) DPRINTF(PFX, "RestoreBIOSMemSize\n"); + if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize)) + return; + if (!pI830->overrideBIOSMemSize) return; @@ -1093,7 +1285,7 @@ static void SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize) { I830Ptr pI830 = I830PTR(pScrn); - CARD32 swf1; + unsigned long swf1; Bool mapped; DPRINTF(PFX, "SetBIOSMemSize: %d kB\n", newSize / 1024); @@ -1109,7 +1301,7 @@ SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize) #endif if ((IS_I830(pI830) || IS_845G(pI830)) && pI830->useSWF1) { - CARD32 newSWF1; + unsigned long newSWF1; /* Need MMIO access here. */ mapped = (pI830->MMIOBase != NULL); @@ -1122,10 +1314,10 @@ SetBIOSMemSize(ScrnInfoPtr pScrn, int newSize) newSWF1 = 8; swf1 = INREG(SWF1); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Before: SWF1 is 0x%08x\n", swf1); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Before: SWF1 is 0x%08lx\n", swf1); swf1 &= ~0x0f; swf1 |= (newSWF1 & 0x0f); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "After: SWF1 is 0x%08x\n", swf1); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "After: SWF1 is 0x%08lx\n", swf1); OUTREG(SWF1, swf1); if (!mapped) I830UnmapMMIO(pScrn); @@ -1151,7 +1343,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, DPRINTF(PFX, "I830LoadPalette: numColors: %d\n", numColors); pI830 = I830PTR(pScrn); - if (pI830->pipeEnabled[0]) { + if (pI830->pipe == 0) { /* It seems that an initial read is needed. */ temp = INREG(PALETTE_A); for (i = 0; i < numColors; i++) { @@ -1163,7 +1355,7 @@ I830LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, OUTREG(PALETTE_A + index * 4, val); } } - if (pI830->pipeEnabled[1]) { + if (pI830->pipe == 1) { /* It seems that an initial read is needed. */ temp = INREG(PALETTE_B); for (i = 0; i < numColors; i++) { @@ -1182,6 +1374,28 @@ PreInitCleanup(ScrnInfoPtr pScrn) { I830Ptr pI830 = I830PTR(pScrn); + if (IsPrimary(pScrn) && pI830->LpRing) { + xfree(pI830->LpRing); + pI830->LpRing = NULL; + } + if (IsPrimary(pScrn) && pI830->CursorMem) { + xfree(pI830->CursorMem); + pI830->CursorMem = NULL; + } + if (IsPrimary(pScrn) && pI830->CursorMemARGB) { + xfree(pI830->CursorMemARGB); + pI830->CursorMemARGB = NULL; + } + if (IsPrimary(pScrn) && pI830->OverlayMem) { + xfree(pI830->OverlayMem); + pI830->OverlayMem = NULL; + } + if (IsPrimary(pScrn) && pI830->overlayOn) { + xfree(pI830->overlayOn); + pI830->overlayOn = NULL; + } + if (!IsPrimary(pScrn) && pI830->entityPrivate) + pI830->entityPrivate->pScrn_2 = NULL; RestoreBIOSMemSize(pScrn); if (pI830->swfSaved) { OUTREG(SWF0, pI830->saveSWF0); @@ -1192,6 +1406,90 @@ PreInitCleanup(ScrnInfoPtr pScrn) I830BIOSFreeRec(pScrn); } +static int +GetBIOSPipe(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + vbeInfoPtr pVbe = pI830->pVbe; + int pipe; + + DPRINTF(PFX, "GetBIOSPipe:\n"); + + /* single pipe machines should always return Pipe A */ + if (pI830->availablePipes == 1) return 0; + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x5f1c; + pVbe->pInt10->bx = 0x100; + + xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); + if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) { + if (pI830->newPipeSwitch) { + pipe = ((pVbe->pInt10->bx & 0x0001)); + } else { + pipe = ((pVbe->pInt10->cx & 0x0100) >> 8); + } + return pipe; + } + + return -1; +} + +static Bool +SetBIOSPipe(ScrnInfoPtr pScrn, int pipe) +{ + I830Ptr pI830 = I830PTR(pScrn); + vbeInfoPtr pVbe = pI830->pVbe; + + DPRINTF(PFX, "SetBIOSPipe: pipe 0x%x\n", pipe); + + /* single pipe machines should always return TRUE */ + if (pI830->availablePipes == 1) return TRUE; + + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x5f1c; + if (pI830->newPipeSwitch) { + pVbe->pInt10->bx = pipe; + pVbe->pInt10->cx = 0; + } else { + pVbe->pInt10->bx = 0x0; + pVbe->pInt10->cx = pipe << 8; + } + + xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); + if (Check5fStatus(pScrn, 0x5f1c, pVbe->pInt10->ax)) + return TRUE; + + return FALSE; +} + +static Bool +SetPipeAccess(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + /* Don't try messing with the pipe, unless we're dual head */ + if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) { + if (!SetBIOSPipe(pScrn, pI830->pipe)) + return FALSE; + } + + return TRUE; +} + +static Bool +IsPrimary(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (pI830->init == 0) return TRUE; + else return FALSE; + } + + return TRUE; +} + static Bool I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) { @@ -1199,14 +1497,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) I830Ptr pI830; MessageType from; rgb defaultWeight = { 0, 0, 0 }; - vbeInfoPtr pVbe; EntityInfoPtr pEnt; + I830EntPtr pI830Ent = NULL; int mem, memsize; int flags24; int i, n; + char *s; pointer pDDCModule, pVBEModule; Bool enable; const char *chipname; + unsigned int ver; + char v[5]; if (pScrn->numEntities != 1) return FALSE; @@ -1233,7 +1534,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; xf86LoaderReqSymLists(I810vgahwSymbols, NULL); - /* Allocate a vgaHWRec */ if (!vgaHWGetHWRec(pScrn)) return FALSE; @@ -1243,6 +1543,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; pI830 = I830PTR(pScrn); + pI830->SaveGeneration = -1; pI830->pEnt = pEnt; if (pI830->pEnt->location.type != BUS_PCI) @@ -1252,10 +1553,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->PciTag = pciTag(pI830->PciInfo->bus, pI830->PciInfo->device, pI830->PciInfo->func); + /* Allocate an entity private if necessary */ + if (xf86IsEntityShared(pScrn->entityList[0])) { + pI830Ent = xf86GetEntityPrivate(pScrn->entityList[0], + I830EntityIndex)->ptr; + pI830->entityPrivate = pI830Ent; + } else + pI830->entityPrivate = NULL; + if (xf86RegisterResources(pI830->pEnt->index, 0, ResNone)) { PreInitCleanup(pScrn); return FALSE; - } pScrn->racMemFlags = RAC_FB | RAC_COLORMAP; @@ -1290,6 +1598,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) hwp = VGAHWPTR(pScrn); pI830->cpp = pScrn->bitsPerPixel / 8; + pI830->preinit = TRUE; + /* Process the options */ xf86CollectOptions(pScrn, NULL); if (!(pI830->Options = xalloc(sizeof(I830BIOSOptions)))) @@ -1340,6 +1650,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) case PCI_CHIP_I865_G: chipname = "865G"; break; + case PCI_CHIP_I915_G: + chipname = "915G"; + break; default: chipname = "unknown chipset"; break; @@ -1347,9 +1660,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Integrated Graphics Chipset: Intel(R) %s\n", chipname); - pVbe = pI830->pVbe; - - pI830->vbeInfo = VBEGetVBEInfo(pVbe); + pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); /* Set the Chipset and ChipRev, allowing config file entries to override. */ if (pI830->pEnt->device->chipset && *pI830->pEnt->device->chipset) { @@ -1379,7 +1690,10 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->LinearAddr = pI830->pEnt->device->MemBase; from = X_CONFIG; } else { - if (pI830->PciInfo->memBase[1] != 0) { + if (IS_I915G(pI830)) { + pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xF0000000; + from = X_PROBED; + } else if (pI830->PciInfo->memBase[1] != 0) { /* XXX Check mask. */ pI830->LinearAddr = pI830->PciInfo->memBase[0] & 0xFF000000; from = X_PROBED; @@ -1398,7 +1712,10 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MMIOAddr = pI830->pEnt->device->IOBase; from = X_CONFIG; } else { - if (pI830->PciInfo->memBase[1]) { + if (IS_I915G(pI830)) { + pI830->MMIOAddr = pI830->PciInfo->memBase[0] & 0xFFF80000; + from = X_PROBED; + } else if (pI830->PciInfo->memBase[1]) { pI830->MMIOAddr = pI830->PciInfo->memBase[1] & 0xFFF80000; from = X_PROBED; } else { @@ -1437,14 +1754,43 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) { pI830->FbMapSize = 0x8000000; } else { - pI830->FbMapSize = 0x4000000; + pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */ } + } else { + if (IS_I915G(pI830)) { + if (pI830->PciInfo->memBase[2] & 0x08000000) + pI830->FbMapSize = 0x8000000; /* 128MB aperture */ + else + pI830->FbMapSize = 0x10000000; /* 256MB aperture */ + } else + /* 128MB aperture for later chips */ + pI830->FbMapSize = 0x8000000; } - else { - /* 128MB aperture for later chips */ - pI830->FbMapSize = 0x8000000; + + + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (xf86IsPrimInitDone(pScrn->entityList[0])) { + pI830->init = 1; + + if (!pI830Ent->pScrn_1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to setup second head due to primary head failure.\n"); + return FALSE; + } + + } else { + xf86SetPrimInitDone(pScrn->entityList[0]); + pI830->init = 0; + } } + if (IS_MOBILE(pI830) || IS_I915G(pI830)) + pI830->availablePipes = 2; + else + pI830->availablePipes = 1; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n", + pI830->availablePipes, pI830->availablePipes > 1 ? "s" : ""); + /* * Get the pre-allocated (stolen) memory size. */ @@ -1455,15 +1801,21 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) /* Sanity check: compare with what the BIOS thinks. */ if (pI830->vbeInfo->TotalMemory != pI830->StolenMemory.Size / 1024 / 64) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Detected stolen memory (%d kB) doesn't match what the BIOS" + "Detected stolen memory (%ld kB) doesn't match what the BIOS" " reports (%d kB)\n", ROUND_DOWN_TO(pI830->StolenMemory.Size / 1024, 64), pI830->vbeInfo->TotalMemory * 64); } /* Find the maximum amount of agpgart memory available. */ - mem = I830CheckAvailableMemory(pScrn); - pI830->StolenOnly = FALSE; + if (IsPrimary(pScrn)) { + mem = I830CheckAvailableMemory(pScrn); + pI830->StolenOnly = FALSE; + } else { + /* videoRam isn't used on the second head, but faked */ + mem = pI830->entityPrivate->pScrn_1->videoRam; + pI830->StolenOnly = TRUE; + } if (mem <= 0) { if (pI830->StolenMemory.Size <= 0) { @@ -1507,6 +1859,154 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } #endif + pI830->MonType1 = PIPE_NONE; + pI830->MonType2 = PIPE_NONE; + + if ((s = xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT)) && + IsPrimary(pScrn)) { + char *Mon1; + char *Mon2; + char *sub; + + Mon1 = strtok(s, ","); + Mon2 = strtok(NULL, ","); + + if (Mon1) { + sub = strtok(Mon1, "+"); + do { + if (strcmp(sub, "NONE") == 0) + pI830->MonType1 |= PIPE_NONE; + else if (strcmp(sub, "CRT") == 0) + pI830->MonType1 |= PIPE_CRT; + else if (strcmp(sub, "TV") == 0) + pI830->MonType1 |= PIPE_TV; + else if (strcmp(sub, "DFP") == 0) + pI830->MonType1 |= PIPE_DFP; + else if (strcmp(sub, "LFP") == 0) + pI830->MonType1 |= PIPE_LFP; + else if (strcmp(sub, "CRT2") == 0) + pI830->MonType1 |= PIPE_CRT2; + else if (strcmp(sub, "TV2") == 0) + pI830->MonType1 |= PIPE_TV2; + else if (strcmp(sub, "DFP2") == 0) + pI830->MonType1 |= PIPE_DFP2; + else if (strcmp(sub, "LFP2") == 0) + pI830->MonType1 |= PIPE_LFP2; + else + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for Pipe A\n"); + + sub = strtok(NULL, "+"); + } while (sub); + } + + if (Mon2) { + sub = strtok(Mon2, "+"); + do { + if (strcmp(sub, "NONE") == 0) + pI830->MonType2 |= PIPE_NONE; + else if (strcmp(sub, "CRT") == 0) + pI830->MonType2 |= PIPE_CRT; + else if (strcmp(sub, "TV") == 0) + pI830->MonType2 |= PIPE_TV; + else if (strcmp(sub, "DFP") == 0) + pI830->MonType2 |= PIPE_DFP; + else if (strcmp(sub, "LFP") == 0) + pI830->MonType2 |= PIPE_LFP; + else if (strcmp(sub, "CRT2") == 0) + pI830->MonType2 |= PIPE_CRT2; + else if (strcmp(sub, "TV2") == 0) + pI830->MonType2 |= PIPE_TV2; + else if (strcmp(sub, "DFP2") == 0) + pI830->MonType2 |= PIPE_DFP2; + else if (strcmp(sub, "LFP2") == 0) + pI830->MonType2 |= PIPE_LFP2; + else + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Invalid Monitor type specified for Pipe B\n"); + + sub = strtok(NULL, "+"); + } while (sub); + } + + if (pI830->availablePipes == 1 && pI830->MonType2 != PIPE_NONE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Monitor 2 cannot be specified on single pipe devices\n"); + return FALSE; + } + + if (pI830->MonType1 == PIPE_NONE && pI830->MonType2 == PIPE_NONE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Monitor 1 and 2 cannot be type NONE\n"); + return FALSE; + } + } + + if (xf86ReturnOptValBool(pI830->Options, OPTION_CLONE, FALSE)) { + if (pI830->availablePipes == 1) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't enable Clone Mode because this is a single pipe device\n"); + PreInitCleanup(pScrn); + return FALSE; + } + if (pI830->entityPrivate) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Can't enable Clone Mode because second head is configured\n"); + PreInitCleanup(pScrn); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Clone Mode\n"); + pI830->CloneRefresh = 60; /* default to 60Hz */ + if (xf86GetOptValInteger(pI830->Options, OPTION_CLONE_REFRESH, + &(pI830->CloneRefresh))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Clone Monitor Refresh Rate %d\n", + pI830->CloneRefresh); + } + if (pI830->CloneRefresh < 60 || pI830->CloneRefresh > 120) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Bad Clone Refresh Rate\n"); + PreInitCleanup(pScrn); + return FALSE; + } + pI830->Clone = TRUE; + } + + if ((pI830->entityPrivate && IsPrimary(pScrn)) || pI830->Clone) { + if ((!xf86GetOptValString(pI830->Options, OPTION_MONITOR_LAYOUT))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "You must have a MonitorLayout " + "defined for use in a DualHead or Clone setup.\n"); + PreInitCleanup(pScrn); + return FALSE; + } + + if (pI830->MonType1 == PIPE_NONE || pI830->MonType2 == PIPE_NONE) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Monitor 1 or Monitor 2 " + "cannot be type NONE in Dual or Clone setup.\n"); + PreInitCleanup(pScrn); + return FALSE; + } + } + + /* + * Let's setup the mobile systems to check the lid status + */ + if (IS_MOBILE(pI830)) { + pI830->checkLid = TRUE; + + if (!xf86ReturnOptValBool(pI830->Options, OPTION_CHECKLID, TRUE)) { + pI830->checkLid = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Checking Lid status disabled\n"); + } else + if (pI830->entityPrivate && !IsPrimary(pScrn) && + !I830PTR(pI830->entityPrivate->pScrn_1)->checkLid) { + /* If checklid is off, on the primary head, then + * turn it off on the secondary*/ + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Checking Lid status disabled\n"); + pI830->checkLid = FALSE; + } else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Checking Lid status enabled\n"); + } else + pI830->checkLid = FALSE; + /* * The "VideoRam" config file parameter specifies the total amount of * memory that will be used/allocated. When agpgart support isn't @@ -1520,6 +2020,10 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * amount is higher, default to it rounded up to the nearest MB. This * guarantees that by default there will be at least some run-time * space for things that need a physical address. + * But, we double the amounts when dual head is enabled, and therefore + * for 2D-only we use 16384KB, and 3D we use 65536KB. The VideoRAM + * for the second head is never used, as the primary head does the + * allocation. */ if (!pI830->pEnt->device->videoRam) { from = X_DEFAULT; @@ -1529,6 +2033,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) else #endif pScrn->videoRam = I830_DEFAULT_VIDEOMEM_2D; + + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (IsPrimary(pScrn)) + pScrn->videoRam *= 2; + else + pScrn->videoRam = I830_MAXIMUM_VBIOS_MEM; + } + if (pI830->StolenMemory.Size / 1024 > pScrn->videoRam) pScrn->videoRam = ROUND_TO(pI830->StolenMemory.Size / 1024, 1024); } else { @@ -1559,7 +2071,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) "VideoRam reduced to %d kByte (limited to aperture size)\n", pScrn->videoRam); } - + if (mem > 0) { /* * If the reserved (BIOS accessible) memory is less than the desired @@ -1579,20 +2091,18 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) */ /* Try to keep HW cursor and Overlay amounts separate from this. */ - int reserve = (HWCURSOR_SIZE + OVERLAY_SIZE) / 1024; + int reserve = (HWCURSOR_SIZE + HWCURSOR_SIZE_ARGB + OVERLAY_SIZE) / 1024; if (pScrn->videoRam - reserve >= I830_MAXIMUM_VBIOS_MEM) pI830->newBIOSMemSize = KB(I830_MAXIMUM_VBIOS_MEM); else pI830->newBIOSMemSize = KB(ROUND_DOWN_TO(pScrn->videoRam - reserve, 64)); - if (pI830->vbeInfo->TotalMemory * 64 < pI830->newBIOSMemSize / 1024) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Will attempt to tell the BIOS that there is " "%d kB VideoRAM\n", pI830->newBIOSMemSize / 1024); - if (SaveBIOSMemSize(pScrn)) { pI830->overrideBIOSMemSize = TRUE; SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); @@ -1600,14 +2110,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) VBEFreeVBEInfo(pI830->vbeInfo); vbeFree(pI830->pVbe); pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); - pVbe = pI830->pVbe; - pI830->vbeInfo = VBEGetVBEInfo(pVbe); + pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); pI830->BIOSMemorySize = KB(pI830->vbeInfo->TotalMemory * 64); xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS now sees %d kB VideoRAM\n", + "BIOS now sees %ld kB VideoRAM\n", pI830->BIOSMemorySize / 1024); - } else { + } else + if ((pI830->saveBIOSMemSize = + TweakMemorySize(pScrn, pI830->newBIOSMemSize)) != 0) + pI830->overrideBIOSMemSize = TRUE; + else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS view of memory size can't be changed " "(this is not an error).\n"); @@ -1615,9 +2128,11 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } } - xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Pre-allocated VideoRAM: %d kByte\n", + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Pre-allocated VideoRAM: %ld kByte\n", pI830->StolenMemory.Size / 1024); - xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", pScrn->videoRam); + xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n", + pScrn->videoRam); pI830->TotalVideoRam = KB(pScrn->videoRam); /* @@ -1668,20 +2183,203 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } #endif + /* + * If the driver can do gamma correction, it should call xf86SetGamma() here. + */ + + { + Gamma zeros = { 0.0, 0.0, 0.0 }; + + if (!xf86SetGamma(pScrn, zeros)) { + PreInitCleanup(pScrn); + return FALSE; + } + } + + GetBIOSVersion(pScrn, &ver); + + v[0] = (ver & 0xff000000) >> 24; + v[1] = (ver & 0x00ff0000) >> 16; + v[2] = (ver & 0x0000ff00) >> 8; + v[3] = (ver & 0x000000ff) >> 0; + + pI830->bios_version = atoi(v); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS Build: %d\n",pI830->bios_version); + + /* BIOS build 3062 changed the pipe switching functionality */ + if (pI830->availablePipes == 2 && pI830->bios_version >= 3062) { + pI830->newPipeSwitch = TRUE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using new Pipe switch code\n"); + } else + pI830->newPipeSwitch = FALSE; + + pI830->devicePresence = FALSE; + from = X_DEFAULT; + if (xf86ReturnOptValBool(pI830->Options, OPTION_DEVICE_PRESENCE, FALSE)) { + pI830->devicePresence = TRUE; + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Device Presence: %s.\n", + pI830->devicePresence ? "enabled" : "disabled"); + + /* This performs an active detect of the currently attached monitors + * or, at least it's meant to..... alas it doesn't seem to always work. + */ + if (pI830->devicePresence) { + int req, att, enc; + GetDevicePresence(pScrn, &req, &att, &enc); + for (i = 0; i < NumDisplayTypes; i++) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Display Presence: %s: attached: %s, encoder: %s\n", + displayDevices[i], + BOOLTOSTRING(((1<<i) & att)>>i), + BOOLTOSTRING(((1<<i) & enc)>>i)); + } + } + + /* Save old configuration of detected devices */ + pI830->savedDevices = GetDisplayDevices(pScrn); + + if (IsPrimary(pScrn)) { + pI830->pipe = GetBIOSPipe(pScrn); + + if (xf86ReturnOptValBool(pI830->Options, OPTION_FLIP_PRIMARY, FALSE)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Primary flipping enabled\n"); + pI830->pipe = !pI830->pipe; + } + + /* If the monitors aren't setup, read from the current config */ + if (pI830->MonType1 == PIPE_NONE) + pI830->MonType1 = pI830->savedDevices & 0xff; + if (pI830->MonType2 == PIPE_NONE) + pI830->MonType2 = (pI830->savedDevices & 0xff00) >> 8; + + pI830->operatingDevices = (pI830->MonType2 << 8) | pI830->MonType1; + + if (!xf86IsEntityShared(pScrn->entityList[0]) && !pI830->Clone) { + /* If we're not dual head or clone, turn off the second head, + * if monitorlayout is also specified. */ + + if (pI830->pipe == 0) + pI830->operatingDevices = pI830->MonType1; + else + pI830->operatingDevices = pI830->MonType2 << 8; + + if (pI830->operatingDevices & 0xFF00) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Primary Pipe is %s, switching off second monitor (0x%x)\n", + pI830->pipe ? "B" : "A", pI830->operatingDevices); + } + } else { + I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1); + pI830->operatingDevices = pI8301->operatingDevices; + } + + /* Buggy BIOS 3066 is known to cause this, so turn this off */ + if (pI830->bios_version == 3066) { + pI830->displayInfo = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Detected Broken Video BIOS, turning off displayInfo.\n"); + } else + pI830->displayInfo = TRUE; + from = X_DEFAULT; + if (!xf86ReturnOptValBool(pI830->Options, OPTION_DISPLAY_INFO, TRUE)) { + pI830->displayInfo = FALSE; + from = X_CONFIG; + } + if (xf86ReturnOptValBool(pI830->Options, OPTION_DISPLAY_INFO, FALSE)) { + pI830->displayInfo = TRUE; + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "Display Info: %s.\n", + pI830->displayInfo ? "enabled" : "disabled"); + + if (!I830DetectDisplayDevice(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't detect display devices.\n"); + PreInitCleanup(pScrn); + return FALSE; + } + + if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to switch to monitor configuration (0x%x)\n", + pI830->operatingDevices); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Please check the devices specified in your MonitorLayout\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "is configured correctly.\n"); + PreInitCleanup(pScrn); + return FALSE; + } + + PrintDisplayDeviceInfo(pScrn); + + if (xf86IsEntityShared(pScrn->entityList[0])) { + if (!IsPrimary(pScrn)) { + I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1); + + pI830Ent->pScrn_2 = pScrn; + pI830->pipe = !pI8301->pipe; + + /* This could be made to work with a little more fiddling */ + pI830->directRenderingDisabled = TRUE; + + xf86DrvMsg(pScrn->scrnIndex, from, "Secondary head is using Pipe %s\n", + pI830->pipe ? "B" : "A"); + } else { + pI830Ent->pScrn_1 = pScrn; + pI830Ent->pScrn_2 = NULL; + + xf86DrvMsg(pScrn->scrnIndex, from, "Primary head is using Pipe %s\n", + pI830->pipe ? "B" : "A"); + } + } else { + xf86DrvMsg(pScrn->scrnIndex, from, "Display is using Pipe %s\n", + pI830->pipe ? "B" : "A"); + } + + /* Alloc our pointers for the primary head */ + if (IsPrimary(pScrn)) { + pI830->LpRing = xalloc(sizeof(I830RingBuffer)); + pI830->CursorMem = xalloc(sizeof(I830MemRange)); + pI830->CursorMemARGB = xalloc(sizeof(I830MemRange)); + pI830->OverlayMem = xalloc(sizeof(I830MemRange)); + pI830->overlayOn = xalloc(sizeof(Bool)); + if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB || + !pI830->OverlayMem || !pI830->overlayOn) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not allocate primary data structures.\n"); + PreInitCleanup(pScrn); + return FALSE; + } + *pI830->overlayOn = FALSE; + if (pI830->entityPrivate) + pI830->entityPrivate->XvInUse = -1; + } + /* Check if the HW cursor needs physical address. */ - if (IS_MOBILE(pI830)) + if (IS_MOBILE(pI830) || IS_I915G(pI830)) pI830->CursorNeedsPhysical = TRUE; else pI830->CursorNeedsPhysical = FALSE; - /* Force ring buffer to be in low memory for the 845G. */ - if (IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830)) + /* Force ring buffer to be in low memory for the 845G and later. */ + if (IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830)) pI830->NeedRingBufferLow = TRUE; /* * XXX If we knew the pre-initialised GTT format for certain, we could * probably figure out the physical address even in the StolenOnly case. */ + if (!IsPrimary(pScrn)) { + I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1); + if (!pI8301->SWCursor) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Using HW Cursor because it's enabled on primary head.\n"); + pI830->SWCursor = FALSE; + } + } else if (pI830->StolenOnly && pI830->CursorNeedsPhysical && !pI830->SWCursor) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "HW Cursor disabled because it needs agpgart memory.\n"); @@ -1692,8 +2390,10 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * Reduce the maximum videoram available for video modes by the ring buffer, * minimum scratch space and HW cursor amounts. */ - if (!pI830->SWCursor) + if (!pI830->SWCursor) { pScrn->videoRam -= (HWCURSOR_SIZE / 1024); + pScrn->videoRam -= (HWCURSOR_SIZE_ARGB / 1024); + } if (!pI830->XvDisabled) pScrn->videoRam -= (OVERLAY_SIZE / 1024); if (!pI830->noAccel) { @@ -1704,37 +2404,13 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Maximum frambuffer space: %d kByte\n", pScrn->videoRam); - /* - * If the driver can do gamma correction, it should call xf86SetGamma() here. - */ - - { - Gamma zeros = { 0.0, 0.0, 0.0 }; - - if (!xf86SetGamma(pScrn, zeros)) - return FALSE; - } - - if (IS_MOBILE(pI830)) - pI830->availablePipes = 2; - else - pI830->availablePipes = 1; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%d display pipe%s available.\n", - pI830->availablePipes, pI830->availablePipes > 1 ? "s" : ""); - - if (!I830DetectDisplayDevice(pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Couldn't detect display devices.\n"); - PreInitCleanup(pScrn); - return FALSE; - } - + SetPipeAccess(pScrn); if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) { PreInitCleanup(pScrn); return FALSE; } - if ((pI830->vesa->monitor = vbeDoEDID(pVbe, pDDCModule)) != NULL) { + if ((pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule)) != NULL) { xf86PrintEDID(pI830->vesa->monitor); } if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) @@ -1763,22 +2439,42 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } #endif - for (i = 0; i < pI830->availablePipes; i++) { + pI830->useExtendedRefresh = FALSE; + + if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) { int pipe = - (pI830->configuredDevices >> PIPE_SHIFT(i)) & PIPE_ACTIVE_MASK; + (pI830->operatingDevices >> PIPE_SHIFT(pI830->pipe)) & PIPE_ACTIVE_MASK; if (pipe & ~PIPE_CRT_ACTIVE) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "A non-CRT device is attached to pipe %c.\n" "\tNo refresh rate overrides will be attempted.\n", - PIPE_NAME(i)); + PIPE_NAME(pI830->pipe)); pI830->vesa->useDefaultRefresh = TRUE; } /* * Some desktop platforms might not have 0x5f05, so useExtendedRefresh * would need to be set to FALSE for those cases. */ - if (!pI830->vesa->useDefaultRefresh) + if (!pI830->vesa->useDefaultRefresh) pI830->useExtendedRefresh = TRUE; + } else { + for (i = 0; i < pI830->availablePipes; i++) { + int pipe = + (pI830->operatingDevices >> PIPE_SHIFT(i)) & PIPE_ACTIVE_MASK; + if (pipe & ~PIPE_CRT_ACTIVE) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "A non-CRT device is attached to pipe %c.\n" + "\tNo refresh rate overrides will be attempted.\n", + PIPE_NAME(i)); + pI830->vesa->useDefaultRefresh = TRUE; + } + /* + * Some desktop platforms might not have 0x5f05, so useExtendedRefresh + * would need to be set to FALSE for those cases. + */ + if (!pI830->vesa->useDefaultRefresh) + pI830->useExtendedRefresh = TRUE; + } } if (pI830->useExtendedRefresh) { @@ -1787,18 +2483,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } /* - * Calling 0x5f64 can reset the refresh rate, so only do this when - * using 0x5f05, or when not overriding the default refresh rate. - * Also, 0x5f64 doesn't work correctly in i830 platforms. - */ - pI830->enableDisplays = !IS_I830(pI830) && pI830->useExtendedRefresh; - - if (pI830->enableDisplays) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use BIOS call 0x5f64 to enable displays.\n"); - } - - /* * Limit videoram available for mode selection to what the video * BIOS can see. */ @@ -1814,7 +2498,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * functions. For that reason it's important to set only * V_MODETYPE_VGA in the flags for VBEGetModePool(). */ - pScrn->modePool = VBEGetModePool(pScrn, pVbe, pI830->vbeInfo, + pScrn->modePool = VBEGetModePool(pScrn, pI830->pVbe, pI830->vbeInfo, V_MODETYPE_VGA); if (!pScrn->modePool) { @@ -1824,6 +2508,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } + SetPipeAccess(pScrn); VBESetModeNames(pScrn->modePool); /* @@ -1835,6 +2520,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) /* XXX Need to get relevant modes and virtual parameters. */ /* Do the mode validation without regard to special scanline pitches. */ + SetPipeAccess(pScrn); n = VBEValidateModes(pScrn, NULL, pScrn->display->modes, NULL, NULL, 0, MAX_DISPLAY_PITCH, 1, 0, MAX_DISPLAY_HEIGHT, @@ -1856,17 +2542,17 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) PreInitCleanup(pScrn); return FALSE; } - #ifndef USE_PITCHES #define USE_PITCHES 1 #endif + pI830->disableTiling = FALSE; /* * If DRI is potentially usable, check if there is enough memory available * for it, and if there's also enough to allow tiling to be enabled. */ #if defined(XF86DRI) - if (!pI830->directRenderingDisabled) { + if (IsPrimary(pScrn) && !pI830->directRenderingDisabled) { int savedDisplayWidth = pScrn->displayWidth; int memNeeded = 0; /* Good pitches to allow tiling. Don't care about pitches < 256. */ @@ -1920,7 +2606,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Allocation with DRI tiling enabled would " "exceed the\n" - "\tmemory aperture size (%d kB) by %d kB.\n" + "\tmemory aperture size (%ld kB) by %ld kB.\n" "\tReduce VideoRam amount to avoid this!\n", pI830->FbMapSize / 1024, -pI830->MemoryAperture.Size / 1024); @@ -1944,6 +2630,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * Tiling can't be enabled. Check if there's enough memory for DRI * without tiling. */ + pI830->disableTiling = TRUE; I830ResetAllocations(pScrn, 0); if (I830Allocate2DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_INITIAL) && I830Allocate3DMemory(pScrn, ALLOCATE_DRY_RUN | ALLOC_NO_TILING)) { @@ -1959,7 +2646,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Allocation with DRI enabled would " "exceed the\n" - "\tmemory aperture size (%d kB) by %d kB.\n" + "\tmemory aperture size (%ld kB) by %ld kB.\n" "\tReduce VideoRam amount to avoid this!\n", pI830->FbMapSize / 1024, -pI830->MemoryAperture.Size / 1024); @@ -1975,6 +2662,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } #endif + SetPipeAccess(pScrn); VBEPrintModes(pScrn); if (!pI830->vesa->useDefaultRefresh) { @@ -1985,7 +2673,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * This only works for VBE 3.0 and later. Also, we only do this * if there are no non-CRT devices attached. */ - VBESetModeParameters(pScrn, pVbe); + SetPipeAccess(pScrn); + VBESetModeParameters(pScrn, pI830->pVbe); } /* PreInit shouldn't leave any state changes, so restore this. */ @@ -1996,7 +2685,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) OUTREG(SWF0, pI830->saveSWF0); OUTREG(SWF4, pI830->saveSWF4); } - I830UnmapMMIO(pScrn); /* Set display resolution */ xf86SetDpi(pScrn, 0, 0); @@ -2025,15 +2713,40 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86LoaderReqSymLists(I810ramdacSymbols, NULL); } + if (!SetDisplayDevices(pScrn, pI830->savedDevices)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to switch to saved display devices, continuing.\n"); + } + + I830UnmapMMIO(pScrn); + /* We won't be using the VGA access after the probe. */ I830SetMMIOAccess(pI830); xf86SetOperatingState(resVgaIo, pI830->pEnt->index, ResUnusedOpr); xf86SetOperatingState(resVgaMem, pI830->pEnt->index, ResDisableOpr); VBEFreeVBEInfo(pI830->vbeInfo); - vbeFree(pVbe); + vbeFree(pI830->pVbe); + /* Use the VBE mode restore workaround by default. */ + pI830->vbeRestoreWorkaround = TRUE; + from = X_DEFAULT; + if (xf86ReturnOptValBool(pI830->Options, OPTION_VBE_RESTORE, FALSE)) { + pI830->vbeRestoreWorkaround = FALSE; + from = X_CONFIG; + } + xf86DrvMsg(pScrn->scrnIndex, from, "VBE Restore workaround: %s.\n", + pI830->vbeRestoreWorkaround ? "enabled" : "disabled"); + #if defined(XF86DRI) + /* Load the dri module if requested. */ + if (xf86ReturnOptValBool(pI830->Options, OPTION_DRI, FALSE) && + !pI830->directRenderingDisabled) { + if (xf86LoadSubModule(pScrn, "dri")) { + xf86LoaderReqSymLists(I810driSymbols, I810drmSymbols, NULL); + } + } + if (!pI830->directRenderingDisabled) { if (!xf86LoadSubModule(pScrn, "shadow")) { PreInitCleanup(pScrn); @@ -2043,6 +2756,8 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } #endif + pI830->preinit = FALSE; + return TRUE; } @@ -2057,32 +2772,35 @@ CheckInheritedState(ScrnInfoPtr pScrn) int errors = 0, fatal = 0; unsigned long temp, head, tail; + if (!IsPrimary(pScrn)) return TRUE; + /* Check first for page table errors */ temp = INREG(PGE_ERR); if (temp != 0) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08x\n", temp); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "PGTBL_ER is 0x%08lx\n", temp); errors++; } temp = INREG(PGETBL_CTL); if (!(temp & 1)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "PGTBL_CTL (0x%08x) indicates GTT is disabled\n", temp); + "PGTBL_CTL (0x%08lx) indicates GTT is disabled\n", temp); errors++; } temp = INREG(LP_RING + RING_LEN); if (temp & 1) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "PRB0_CTL (0x%08x) indicates ring buffer enabled\n", temp); + "PRB0_CTL (0x%08lx) indicates ring buffer enabled\n", temp); errors++; } head = INREG(LP_RING + RING_HEAD); tail = INREG(LP_RING + RING_TAIL); if ((tail & I830_TAIL_MASK) != (head & I830_HEAD_MASK)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "PRB0_HEAD (0x%08x) and PRB0_TAIL (0x%08x) indicate " + "PRB0_HEAD (0x%08lx) and PRB0_TAIL (0x%08lx) indicate " "ring buffer not flushed\n", head, tail); errors++; } + #if 0 if (errors) I830PrintErrorState(pScrn); @@ -2109,6 +2827,11 @@ ResetState(ScrnInfoPtr pScrn, Bool flush) DPRINTF(PFX, "ResetState: flush is %s\n", BOOLTOSTRING(flush)); + if (!IsPrimary(pScrn)) return; + + if (pI830->entityPrivate) + pI830->entityPrivate->RingRunning = 0; + /* Reset the fence registers to 0 */ for (i = 0; i < 8; i++) OUTREG(FENCE + i * 4, 0); @@ -2139,6 +2862,8 @@ SetFenceRegs(ScrnInfoPtr pScrn) DPRINTF(PFX, "SetFenceRegs\n"); + if (!IsPrimary(pScrn)) return; + for (i = 0; i < 8; i++) { OUTREG(FENCE + i * 4, pI830->ModeReg.Fence[i]); if (I810_DEBUG & DEBUG_VERBOSE_VGA) @@ -2157,29 +2882,34 @@ SetRingRegs(ScrnInfoPtr pScrn) if (pI830->noAccel) return; + if (!IsPrimary(pScrn)) return; + + if (pI830->entityPrivate) + pI830->entityPrivate->RingRunning = 1; + OUTREG(LP_RING + RING_LEN, 0); OUTREG(LP_RING + RING_TAIL, 0); OUTREG(LP_RING + RING_HEAD, 0); - if ((pI830->LpRing.mem.Start & I830_RING_START_MASK) != - pI830->LpRing.mem.Start) { + if ((pI830->LpRing->mem.Start & I830_RING_START_MASK) != + pI830->LpRing->mem.Start) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "I830SetRingRegs: Ring buffer start (%x) violates its " - "mask (%x)\n", pI830->LpRing.mem.Start, I830_RING_START_MASK); + "I830SetRingRegs: Ring buffer start (%lx) violates its " + "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK); } /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = pI830->LpRing.mem.Start & I830_RING_START_MASK; + itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK; OUTREG(LP_RING + RING_START, itemp); - if (((pI830->LpRing.mem.Size - 4096) & I830_RING_NR_PAGES) != - pI830->LpRing.mem.Size - 4096) { + if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) != + pI830->LpRing->mem.Size - 4096) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "I830SetRingRegs: Ring buffer size - 4096 (%x) violates its " - "mask (%x)\n", pI830->LpRing.mem.Size - 4096, + "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its " + "mask (%x)\n", pI830->LpRing->mem.Size - 4096, I830_RING_NR_PAGES); } /* Don't care about the old value. Reserved bits must be zero anyway. */ - itemp = (pI830->LpRing.mem.Size - 4096) & I830_RING_NR_PAGES; + itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES; itemp |= (RING_NO_REPORT | RING_VALID); OUTREG(LP_RING + RING_LEN, itemp); I830RefreshRing(pScrn); @@ -2215,7 +2945,10 @@ SaveHWState(ScrnInfoPtr pScrn) DPRINTF(PFX, "SaveHWState\n"); + SetPipeAccess(pScrn); + pVesa = pI830->vesa; + /* Make sure we save at least this information in case of failure. */ VBEGetVBEMode(pVbe, &pVesa->stateMode); modeInfo = VBEGetModeInfo(pVbe, pVesa->stateMode); @@ -2230,21 +2963,18 @@ SaveHWState(ScrnInfoPtr pScrn) vgaHWUnlock(hwp); vgaHWSave(pScrn, vgaReg, VGA_SR_FONTS); -#ifndef I845G_VBE_WORKAROUND -#define I845G_VBE_WORKAROUND 1 -#endif - pVesa = pI830->vesa; - /* This save/restore method doesn't work for 845G BIOS */ /* - * XXX If it's fixed in production versions, this could be removed. - * + * This save/restore method doesn't work for 845G BIOS, or for some + * other platforms. Enable it in all cases. + */ + /* * KW: This may have been because of the behaviour I've found on my * board: The 'save' command actually modifies the interrupt * registers, turning off the irq & breaking the kernel module * behaviour. */ - if (!I845G_VBE_WORKAROUND || !IS_845G(pI830)) { + if (!pI830->vbeRestoreWorkaround) { CARD16 imr = INREG16(IMR); CARD16 ier = INREG16(IER); CARD16 hwstam = INREG16(HWSTAM); @@ -2269,6 +2999,8 @@ SaveHWState(ScrnInfoPtr pScrn) return FALSE; } + VBEGetDisplayStart(pVbe, &pVesa->x, &pVesa->y); + return TRUE; } @@ -2350,6 +3082,8 @@ RestoreHWState(ScrnInfoPtr pScrn) if (pVesa->savedPal) VBESetGetPaletteData(pVbe, TRUE, 0, 256, pVesa->savedPal, FALSE, TRUE); + VBESetDisplayStart(pVbe, pVesa->x, pVesa->y, TRUE); + vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS); vgaHWLock(hwp); return TRUE; @@ -2359,12 +3093,92 @@ RestoreHWState(ScrnInfoPtr pScrn) #define USE_VBE 1 #endif +static void I830SetCloneVBERefresh(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block, int refresh) +{ + I830Ptr pI830 = I830PTR(pScrn); + DisplayModePtr p = NULL; + int RefreshRate; + int clock; + + /* Search for our mode and get a refresh to match */ + for (p = pScrn->monitor->Modes; p != NULL; p = p->next) { + if ((p->HDisplay != pI830->CloneHDisplay) || + (p->VDisplay != pI830->CloneVDisplay) || + (p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) + continue; + RefreshRate = ((double)(p->Clock * 1000) / + (double)(p->HTotal * p->VTotal)) * 100; + /* we could probably do better here that 2Hz boundaries */ + if (RefreshRate > (refresh - 200) && RefreshRate < (refresh + 200)) { + block->HorizontalTotal = p->HTotal; + block->HorizontalSyncStart = p->HSyncStart; + block->HorizontalSyncEnd = p->HSyncEnd; + block->VerticalTotal = p->VTotal; + block->VerticalSyncStart = p->VSyncStart; + block->VerticalSyncEnd = p->VSyncEnd; + block->Flags = ((p->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | + ((p->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); + block->PixelClock = p->Clock * 1000; + /* XXX May not have this. */ + clock = VBEGetPixelClock(pI830->pVbe, mode, block->PixelClock); +#ifdef DEBUG + ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n", + (double)data->block->PixelClock / 1000000.0, + (double)clock / 1000000.0); +#endif + if (clock) + block->PixelClock = clock; + block->RefreshRate = ((double)(block->PixelClock) / + (double)(p->HTotal * p->VTotal)) * 100; + return; + } + } +} + static Bool I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) { I830Ptr pI830 = I830PTR(pScrn); DPRINTF(PFX, "Setting mode 0x%.8x\n", mode); + + if (pI830->Clone && !pI830->preinit) { + VbeCRTCInfoBlock newblock; + int Mon; + + if (!pI830->pipe) + Mon = pI830->MonType2; + else + Mon = pI830->MonType1; + + SetBIOSPipe(pScrn, !pI830->pipe); + + /* The reason for this code is if we've not got a CRT on this pipe, then + * make sure we're using a 60Hz refresh */ + if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && + (mode & (1 << 11)) && block) { + /* we'll call 5F05 to set the refresh later.... */ + if (Mon != PIPE_CRT) + VBESetVBEMode(pI830->pVbe, mode, NULL); + else + VBESetVBEMode(pI830->pVbe, mode, block); + } else { + if (Mon != PIPE_CRT) + /* Set clone head to 60Hz because we ain't got a CRT on it */ + I830SetCloneVBERefresh(pScrn, mode, &newblock, 6000); + else + /* Set clone head to specified clone refresh rate */ + I830SetCloneVBERefresh(pScrn, mode, &newblock, pI830->CloneRefresh * 100); + if (newblock.RefreshRate == 0) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to setup clone head mode resolution and refresh.\n"); + else + VBESetVBEMode(pI830->pVbe, mode, &newblock); + } + } + + SetPipeAccess(pScrn); + #if USE_VBE return VBESetVBEMode(pI830->pVbe, mode, block); #else @@ -2388,7 +3202,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) { I830Ptr pI830 = I830PTR(pScrn); vbeInfoPtr pVbe = pI830->pVbe; - VbeModeInfoData *data; + VbeModeInfoData *data = (VbeModeInfoData *) pMode->Private; int mode, i; CARD32 planeA, planeB, temp; int refresh = 60; @@ -2398,8 +3212,6 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) DPRINTF(PFX, "I830VESASetMode\n"); - data = (VbeModeInfoData *) pMode->Private; - /* Always Enable Linear Addressing */ mode = data->mode | (1 << 15) | (1 << 14); @@ -2411,6 +3223,26 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } #endif + /* + * Do this early to find out if we can support it or not.... + * Test if the extendedRefresh BIOS function is supported. + */ + if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && + (mode & (1 << 11)) && data && data->data && data->block) { + SetPipeAccess(pScrn); + if (!SetRefreshRate(pScrn, mode, 60)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "BIOS call 0x5f05 not supported, " + "setting refresh with VBE 3 method.\n"); + pI830->useExtendedRefresh = FALSE; + } + } + + if (pI830->Clone) { + pI830->CloneHDisplay = pMode->HDisplay; + pI830->CloneVDisplay = pMode->VDisplay; + } + #ifndef MODESWITCH_RESET_STATE #define MODESWITCH_RESET_STATE 0 #endif @@ -2444,37 +3276,58 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) * memory than it's aware of. We check for this later, and set it * explicitly if necessary. */ - if (data->data->XResolution != pScrn->displayWidth) + if (data->data->XResolution != pScrn->displayWidth) { + if (pI830->Clone) { + SetBIOSPipe(pScrn, !pI830->pipe); + VBESetLogicalScanline(pVbe, pScrn->displayWidth); + } + SetPipeAccess(pScrn); VBESetLogicalScanline(pVbe, pScrn->displayWidth); + } - if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) + if (pScrn->bitsPerPixel >= 8 && pI830->vbeInfo->Capabilities[0] & 0x01) { + if (pI830->Clone) { + SetBIOSPipe(pScrn, !pI830->pipe); + VBESetGetDACPaletteFormat(pVbe, 8); + } + SetPipeAccess(pScrn); VBESetGetDACPaletteFormat(pVbe, 8); + } /* - * XXX This location of this isn't correct. - * - * Turn on the configured displays. This has the effect of resetting - * the default refresh rates to values that the configured displays - * can handle. This seems to be the safest way to make sure that this - * happens. When it's safe to set higher values, we do that after this. - * - * Note: When a DFP is connected to an 830, this causes the mode setting - * to be trashed. So, we don't do it on the 830. - * - * XXX Need to test an 830 with a LFP. + * When it's OK to set better than default refresh rates, set them here. */ - if (pI830->enableDisplays) { - if (!SetDisplayDevices(pScrn, pI830->configuredDevices)) { + if (pI830->Clone) { + int Mon; + if (!pI830->pipe) + Mon = pI830->MonType2; + else + Mon = pI830->MonType1; + SetBIOSPipe(pScrn, !pI830->pipe); + if (pI830->CloneRefresh && (Mon == PIPE_CRT)) { + if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && + (mode & (1 << 11)) && data && data->data && data->block) { + refresh = SetRefreshRate(pScrn, mode, pI830->CloneRefresh); + if (!refresh) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to set refresh rate to %dHz on Clone head.\n", + pI830->CloneRefresh); + else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Set refresh rate to %dHz on Clone head.\n", + pI830->CloneRefresh); + } else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use VBE3 method to set refresh on Clone head.\n"); + } else { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Failed to switch to configured display devices\n"); + "Not attempting to override default refresh on non-CRT clone head\n"); } } - /* - * When it's OK to set better than default refresh rates, set them here. - */ if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && (mode & (1 << 11)) && data && data->data && data->block) { + SetPipeAccess(pScrn); refresh = SetRefreshRate(pScrn, mode, data->block->RefreshRate / 100); if (!refresh) { refresh = 60; @@ -2484,7 +3337,6 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } } - /* XXX Fix plane A with pipe A, and plane B with pipe B. */ planeA = INREG(DSPACNTR); planeB = INREG(DSPBCNTR); @@ -2492,10 +3344,20 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) pI830->planeEnabled[0] = ((planeA & DISPLAY_PLANE_ENABLE) != 0); pI830->planeEnabled[1] = ((planeB & DISPLAY_PLANE_ENABLE) != 0); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is %s.\n", - pI830->planeEnabled[0] ? "enabled" : "disabled"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is %s.\n", - pI830->planeEnabled[1] ? "enabled" : "disabled"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is %s and connected to %s.\n", + pI830->planeEnabled[0] ? "enabled" : "disabled", + planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); + if (pI830->availablePipes == 2) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is %s and connected to %s.\n", + pI830->planeEnabled[1] ? "enabled" : "disabled", + planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); + + if (xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone) { + pI830->planeEnabled[0] = 1; + pI830->pipeEnabled[0] = 1; + pI830->planeEnabled[1] = 1; + pI830->pipeEnabled[1] = 1; + } /* * Sometimes it seems that no display planes are enabled at this point. @@ -2503,7 +3365,7 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) * For others choose plane A. */ if (!pI830->planeEnabled[0] && !pI830->planeEnabled[1]) { - if (IS_MOBILE(pI830)) { + if (pI830->availablePipes == 2) { if ((pI830->pipeEnabled[0] && ((planeA & DISPPLANE_SEL_PIPE_MASK) == DISPPLANE_SEL_PIPE_A)) || (pI830->pipeEnabled[1] && @@ -2519,23 +3381,37 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) } else { pI830->planeEnabled[0] = TRUE; } - if (pI830->planeEnabled[0]) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n"); - planeA |= DISPLAY_PLANE_ENABLE; - OUTREG(DSPACNTR, planeA); - /* flush the change. */ - temp = INREG(DSPABASE); - OUTREG(DSPABASE, temp); - } - if (pI830->planeEnabled[1]) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane B.\n"); - planeB |= DISPLAY_PLANE_ENABLE; - OUTREG(DSPBCNTR, planeB); - /* flush the change. */ - temp = INREG(DSPBADDR); - OUTREG(DSPBADDR, temp); - } } + if (pI830->planeEnabled[0]) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane A.\n"); + planeA |= DISPLAY_PLANE_ENABLE; + planeA &= ~DISPPLANE_SEL_PIPE_MASK; + planeA |= DISPPLANE_SEL_PIPE_A; + OUTREG(DSPACNTR, planeA); + /* flush the change. */ + temp = INREG(DSPABASE); + OUTREG(DSPABASE, temp); + } + if (pI830->planeEnabled[1]) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling plane B.\n"); + planeB |= DISPLAY_PLANE_ENABLE; + planeB &= ~DISPPLANE_SEL_PIPE_MASK; + planeB |= DISPPLANE_SEL_PIPE_B; + OUTREG(DSPBCNTR, planeB); + /* flush the change. */ + temp = INREG(DSPBADDR); + OUTREG(DSPBADDR, temp); + } + + planeA = INREG(DSPACNTR); + planeB = INREG(DSPBCNTR); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane A is now %s and connected to %s.\n", + pI830->planeEnabled[0] ? "enabled" : "disabled", + planeA & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); + if (pI830->availablePipes == 2) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Display plane B is now %s and connected to %s.\n", + pI830->planeEnabled[1] ? "enabled" : "disabled", + planeB & DISPPLANE_SEL_PIPE_MASK ? "Pipe B" : "Pipe A"); /* XXX Plane C is ignored for now (overlay). */ @@ -2543,13 +3419,109 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) * Print out the PIPEACONF and PIPEBCONF registers. */ temp = INREG(PIPEACONF); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08x\n", temp); - if (IS_MOBILE(pI830)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEACONF is 0x%08lx\n", temp); + if (pI830->availablePipes == 2) { temp = INREG(PIPEBCONF); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08x\n", temp); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "PIPEBCONF is 0x%08lx\n", temp); + } + + if (xf86IsEntityShared(pScrn->entityList[0])) { + /* Clean this up !! */ + if (IsPrimary(pScrn)) { + CARD32 stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; + CARD32 basereg = !pI830->pipe ? DSPABASE : DSPBBASE; + CARD32 sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE; + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + + temp = INREG(stridereg); + if (temp / pI8301->cpp != pI830->entityPrivate->pScrn_1->displayWidth) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe), + (int)(temp / pI8301->cpp), pI830->entityPrivate->pScrn_1->displayWidth); + OUTREG(stridereg, pI830->entityPrivate->pScrn_1->displayWidth * pI8301->cpp); + } + OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); + /* Trigger update */ + temp = INREG(basereg); + OUTREG(basereg, temp); + + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) { + I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); + stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; + basereg = pI830->pipe ? DSPABASE : DSPBBASE; + sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE; + + temp = INREG(stridereg); + if (temp / pI8302->cpp != pI830->entityPrivate->pScrn_2->displayWidth) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe), + (int)(temp / pI8302->cpp), pI830->entityPrivate->pScrn_2->displayWidth); + OUTREG(stridereg, pI830->entityPrivate->pScrn_2->displayWidth * pI8302->cpp); + } + OUTREG(sizereg, (pI830->entityPrivate->pScrn_2->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_2->currentMode->VDisplay - 1) << 16)); + /* Trigger update */ + temp = INREG(basereg); + OUTREG(basereg, temp); + } + } else { + CARD32 stridereg = pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; + CARD32 basereg = pI830->pipe ? DSPABASE : DSPBBASE; + CARD32 sizereg = pI830->pipe ? DSPASIZE : DSPBSIZE; + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + I830Ptr pI8302 = I830PTR(pI830->entityPrivate->pScrn_2); + + temp = INREG(stridereg); + if (temp / pI8301->cpp != pI830->entityPrivate->pScrn_1->displayWidth) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(pI830->pipe), + (int)(temp / pI8301->cpp), pI830->entityPrivate->pScrn_1->displayWidth); + OUTREG(stridereg, pI830->entityPrivate->pScrn_1->displayWidth * pI8301->cpp); + } + OUTREG(sizereg, (pI830->entityPrivate->pScrn_1->currentMode->HDisplay - 1) | ((pI830->entityPrivate->pScrn_1->currentMode->VDisplay - 1) << 16)); + /* Trigger update */ + temp = INREG(basereg); + OUTREG(basereg, temp); + + stridereg = !pI830->pipe ? DSPASTRIDE : DSPBSTRIDE; + basereg = !pI830->pipe ? DSPABASE : DSPBBASE; + sizereg = !pI830->pipe ? DSPASIZE : DSPBSIZE; + + temp = INREG(stridereg); + if (temp / pI8302->cpp != pI830->entityPrivate->pScrn_2->displayWidth) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(!pI830->pipe), + (int)(temp / pI8302->cpp), pI830->entityPrivate->pScrn_2->displayWidth); + OUTREG(stridereg, pI830->entityPrivate->pScrn_2->displayWidth * pI8302->cpp); + } + OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); + /* Trigger update */ + temp = INREG(basereg); + OUTREG(basereg, temp); + } + } else { + for (i = 0; i < pI830->availablePipes; i++) { + CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE; + CARD32 basereg = i ? DSPBBASE : DSPABASE; + CARD32 sizereg = i ? DSPBSIZE : DSPASIZE; + + if (!pI830->planeEnabled[i]) + continue; + + temp = INREG(stridereg); + if (temp / pI830->cpp != pScrn->displayWidth) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i), + (int)(temp / pI830->cpp), pScrn->displayWidth); + OUTREG(stridereg, pScrn->displayWidth * pI830->cpp); + } + OUTREG(sizereg, (pMode->HDisplay - 1) | ((pMode->VDisplay - 1) << 16)); + /* Trigger update */ + temp = INREG(basereg); + OUTREG(basereg, temp); + } } -#if PRINT_MODE_INFO +#if 0 /* Print out some CRTC/display information. */ temp = INREG(HTOTAL_A); ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff, @@ -2578,26 +3550,44 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) ErrorF("Plane A start offset is %d\n", temp); temp = INREG(DSPASTRIDE); ErrorF("Plane A stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp); -#endif - - for (i = 0; i < MAX_DISPLAY_PIPES; i++) { - CARD32 stridereg = i ? DSPBSTRIDE : DSPASTRIDE; - CARD32 basereg = i ? DSPBBASE : DSPABASE; - - if (!pI830->planeEnabled[i]) - continue; + temp = INREG(DSPAPOS); + ErrorF("Plane A position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); + temp = INREG(DSPASIZE); + ErrorF("Plane A size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); - temp = INREG(stridereg); - if (temp / pI830->cpp != pScrn->displayWidth) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Correcting plane %c stride (%d -> %d)\n", PIPE_NAME(i), - temp / pI830->cpp, pScrn->displayWidth); - OUTREG(stridereg, pScrn->displayWidth * pI830->cpp); - /* Trigger update */ - temp = INREG(basereg); - OUTREG(basereg, temp); - } - } + /* Print out some CRTC/display information. */ + temp = INREG(HTOTAL_B); + ErrorF("Horiz active: %d, Horiz total: %d\n", temp & 0x7ff, + (temp >> 16) & 0xfff); + temp = INREG(HBLANK_B); + ErrorF("Horiz blank start: %d, Horiz blank end: %d\n", temp & 0xfff, + (temp >> 16) & 0xfff); + temp = INREG(HSYNC_B); + ErrorF("Horiz sync start: %d, Horiz sync end: %d\n", temp & 0xfff, + (temp >> 16) & 0xfff); + temp = INREG(VTOTAL_B); + ErrorF("Vert active: %d, Vert total: %d\n", temp & 0x7ff, + (temp >> 16) & 0xfff); + temp = INREG(VBLANK_B); + ErrorF("Vert blank start: %d, Vert blank end: %d\n", temp & 0xfff, + (temp >> 16) & 0xfff); + temp = INREG(VSYNC_B); + ErrorF("Vert sync start: %d, Vert sync end: %d\n", temp & 0xfff, + (temp >> 16) & 0xfff); + temp = INREG(PIPEBSRC); + ErrorF("Image size: %dx%d (%dx%d)\n", + (temp >> 16) & 0x7ff, temp & 0x7ff, + (((temp >> 16) & 0x7ff) + 1), ((temp & 0x7ff) + 1)); + ErrorF("Pixel multiply is %d\n", (planeA >> 20) & 0x3); + temp = INREG(DSPBBASE); + ErrorF("Plane B start offset is %d\n", temp); + temp = INREG(DSPBSTRIDE); + ErrorF("Plane B stride is %d bytes (%d pixels)\n", temp, temp / pI830->cpp); + temp = INREG(DSPBPOS); + ErrorF("Plane B position %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); + temp = INREG(DSPBSIZE); + ErrorF("Plane B size %d %d\n", temp & 0xffff, (temp & 0xffff0000) >> 16); +#endif xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Mode bandwidth is %d Mpixel/s\n", pMode->HDisplay * pMode->VDisplay * refresh / 1000000); @@ -2646,6 +3636,8 @@ InitRegisterRec(ScrnInfoPtr pScrn) I830RegPtr i830Reg = &pI830->ModeReg; int i; + if (!IsPrimary(pScrn)) return; + for (i = 0; i < 8; i++) i830Reg->Fence[i] = 0; } @@ -2874,6 +3866,8 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) vgaHWPtr hwp; I830Ptr pI830; VisualPtr visual; + I830EntPtr pI830Ent = NULL; + I830Ptr pI8301 = NULL; #ifdef XF86DRI Bool driDisabled; #endif @@ -2882,14 +3876,63 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830 = I830PTR(pScrn); hwp = VGAHWPTR(pScrn); + if (xf86IsEntityShared(pScrn->entityList[0])) { + pI830Ent = pI830->entityPrivate; + pI8301 = I830PTR(pI830Ent->pScrn_1); + + /* PreInit failed on the second head, so make sure we turn it off */ + if (IsPrimary(pScrn) && !pI830->entityPrivate->pScrn_2) { + if (pI830->pipe == 0) { + pI830->operatingDevices &= 0xFF; + } else { + pI830->operatingDevices &= 0xFF00; + } + } + } + pI830->starting = TRUE; + /* Alloc our pointers for the primary head */ + if (IsPrimary(pScrn)) { + if (!pI830->LpRing) + pI830->LpRing = xalloc(sizeof(I830RingBuffer)); + if (!pI830->CursorMem) + pI830->CursorMem = xalloc(sizeof(I830MemRange)); + if (!pI830->CursorMemARGB) + pI830->CursorMemARGB = xalloc(sizeof(I830MemRange)); + if (!pI830->OverlayMem) + pI830->OverlayMem = xalloc(sizeof(I830MemRange)); + if (!pI830->overlayOn) + pI830->overlayOn = xalloc(sizeof(Bool)); + if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB || + !pI830->OverlayMem || !pI830->overlayOn) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not allocate primary data structures.\n"); + return FALSE; + } + *pI830->overlayOn = FALSE; + if (pI830->entityPrivate) + pI830->entityPrivate->XvInUse = -1; + } + + if (xf86IsEntityShared(pScrn->entityList[0])) { + /* Make our second head point to the first heads structures */ + if (!IsPrimary(pScrn)) { + pI830->LpRing = pI8301->LpRing; + pI830->CursorMem = pI8301->CursorMem; + pI830->CursorMemARGB = pI8301->CursorMemARGB; + pI830->OverlayMem = pI8301->OverlayMem; + pI830->overlayOn = pI8301->overlayOn; + } + } + /* * If we're changing the BIOS's view of the video memory size, do that * first, then re-initialise the VBE information. */ pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); - SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); + if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize)) + SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); if (!pI830->pVbe) return FALSE; pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); @@ -2913,6 +3956,12 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef I830_XV pI830->XvEnabled = !pI830->XvDisabled; if (pI830->XvEnabled) { + if (!IsPrimary(pScrn)) { + if (!pI8301->XvEnabled || pI830->noAccel) { + pI830->XvEnabled = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled.\n"); + } + } else if (pI830->noAccel || pI830->StolenOnly) { xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Xv is disabled because it " "needs 2D accel and AGPGART.\n"); @@ -2923,12 +3972,15 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pI830->XvEnabled = FALSE; #endif - I830ResetAllocations(pScrn, 0); + if (IsPrimary(pScrn)) { + I830ResetAllocations(pScrn, 0); - I830Allocate2DMemory(pScrn, ALLOC_INITIAL); + if (!I830Allocate2DMemory(pScrn, ALLOC_INITIAL)) + return FALSE; + } if (!pI830->noAccel) { - if (pI830->LpRing.mem.Size == 0) { + if (pI830->LpRing->mem.Size == 0) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling acceleration because the ring buffer " "allocation failed.\n"); @@ -2937,7 +3989,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } if (!pI830->SWCursor) { - if (pI830->CursorMem.Size == 0) { + if (pI830->CursorMem->Size == 0) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling HW cursor because the cursor memory " "allocation failed.\n"); @@ -2952,7 +4004,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) "needs 2D acceleration.\n"); pI830->XvEnabled = FALSE; } - if (pI830->OverlayMem.Physical == 0) { + if (pI830->OverlayMem->Physical == 0) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling Xv because the overlay register buffer " "allocation failed.\n"); @@ -2988,9 +4040,13 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (pI830->directRenderingEnabled) pI830->directRenderingEnabled = I830DRIScreenInit(pScreen); - if (pI830->directRenderingEnabled) - if (!(pI830->directRenderingEnabled = I830Allocate3DMemory(pScrn, 0))) + if (pI830->directRenderingEnabled) { + pI830->directRenderingEnabled = + I830Allocate3DMemory(pScrn, + pI830->disableTiling ? ALLOC_NO_TILING : 0); + if (!pI830->directRenderingEnabled) I830DRICloseScreen(pScreen); + } #else pI830->directRenderingEnabled = FALSE; @@ -3000,15 +4056,17 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) * After the 3D allocations have been done, see if there's any free space * that can be added to the framebuffer allocation. */ - I830Allocate2DMemory(pScrn, 0); + if (IsPrimary(pScrn)) { + I830Allocate2DMemory(pScrn, 0); - DPRINTF(PFX, "assert(if(!I830DoPoolAllocation(pScrn, pI830->StolenPool)))\n"); - if (!I830DoPoolAllocation(pScrn, &(pI830->StolenPool))) - return FALSE; + DPRINTF(PFX, "assert(if(!I830DoPoolAllocation(pScrn, pI830->StolenPool)))\n"); + if (!I830DoPoolAllocation(pScrn, &(pI830->StolenPool))) + return FALSE; - DPRINTF(PFX, "assert( if(!I830FixupOffsets(pScrn)) )\n"); - if (!I830FixupOffsets(pScrn)) - return FALSE; + DPRINTF(PFX, "assert( if(!I830FixupOffsets(pScrn)) )\n"); + if (!I830FixupOffsets(pScrn)) + return FALSE; + } #ifdef XF86DRI if (pI830->directRenderingEnabled) { @@ -3022,7 +4080,13 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) return FALSE; pScrn->memPhysBase = (unsigned long)pI830->FbBase; - pScrn->fbOffset = pI830->FrontBuffer.Start; + + if (IsPrimary(pScrn)) { + pScrn->fbOffset = pI830->FrontBuffer.Start; + } else { + I830Ptr pI8301 = I830PTR(pI830Ent->pScrn_1); + pScrn->fbOffset = pI8301->FrontBuffer2.Start; + } pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth; pI830->yoffset = (pScrn->fbOffset / pI830->cpp) / pScrn->displayWidth; @@ -3037,6 +4101,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) memset(&pI830->SavedReg, 0, sizeof(pI830->SavedReg)); DPRINTF(PFX, "assert( if(!I830BIOSEnterVT(scrnIndex, 0)) )\n"); + if (!I830BIOSEnterVT(scrnIndex, 0)) return FALSE; @@ -3066,16 +4131,22 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); -#if 1 I830DGAInit(pScreen); -#endif DPRINTF(PFX, "assert( if(!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) )\n"); - if (!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + if (IsPrimary(pScrn)) { + if (!xf86InitFBManager(pScreen, &(pI830->FbMemBox))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to init memory manager\n"); - return FALSE; + return FALSE; + } + } else { + if (!xf86InitFBManager(pScreen, &(pI8301->FbMemBox2))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to init memory manager\n"); + return FALSE; + } } if (!pI830->noAccel) { @@ -3141,14 +4212,16 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) pScreen->SaveScreen = I830BIOSSaveScreen; pI830->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = I830BIOSCloseScreen; + + if (pI830->checkLid) + pI830->lidTimer = TimerSet(NULL, 0, 1000, I830LidTimer, pScrn); if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); -#if 0 + #ifdef I830DEBUG I830_dump_registers(pScrn); #endif -#endif pI830->starting = FALSE; pI830->closing = FALSE; @@ -3170,7 +4243,44 @@ I830BIOSAdjustFrame(int scrnIndex, int x, int y, int flags) DPRINTF(PFX, "I830BIOSAdjustFrame: y = %d (+ %d), x = %d (+ %d)\n", x, pI830->xoffset, y, pI830->yoffset); - VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE); + /* The i830M just happens to have some problems programming offsets via + * this VESA BIOS call. Especially in dual head configurations which + * have high resolutions which cause the DSP{A,B}BASE registers to be + * programmed incorrectly. Thus, it warrants bypassing the BIOS for i830M + * and hitting the DSP{A,B}BASE registers directly. + * + * We could probably do this for other platforms too, but we don't + * know what else the Video BIOS may do when calling it. It seems safe + * though for i830M during testing...... + * + * Also note, calling the Video BIOS version first and then fixing the + * registers fail on i830M and eventually cause a lockup of the hardware + * in my testing. + */ + + if (pI830->Clone) { + if (!IS_I830(pI830)) { + SetBIOSPipe(pScrn, !pI830->pipe); + VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE); + } else { + if (!pI830->pipe == 0) { + OUTREG(DSPABASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } else { + OUTREG(DSPBBASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } + } + } + + if (!IS_I830(pI830)) { + SetPipeAccess(pScrn); + VBESetDisplayStart(pVbe, x + pI830->xoffset, y + pI830->yoffset, TRUE); + } else { + if (pI830->pipe == 0) { + OUTREG(DSPABASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } else { + OUTREG(DSPBBASE, pScrn->fbOffset + ((y * pScrn->displayWidth + x) * pI830->cpp)); + } + } } static void @@ -3217,6 +4327,13 @@ I830BIOSLeaveVT(int scrnIndex, int flags) DPRINTF(PFX, "Leave VT\n"); + if (!IsPrimary(pScrn)) { + I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1); + if (!pI8301->GttBound) { + return; + } + } + #ifdef XF86DRI if (pI830->directRenderingOpen) { DPRINTF(PFX, "calling dri lock\n"); @@ -3230,10 +4347,22 @@ I830BIOSLeaveVT(int scrnIndex, int flags) SaveHWOperatingState(pScrn); #endif + if (IsPrimary(pScrn)) { + if (!SetDisplayDevices(pScrn, pI830->savedDevices)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to switch back to original display devices (0x%x)\n", + pI830->savedDevices); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Successfully set original devices\n"); + } + } + ResetState(pScrn, TRUE); RestoreHWState(pScrn); RestoreBIOSMemSize(pScrn); - I830UnbindGARTMemory(pScrn); + if (IsPrimary(pScrn)) + I830UnbindGARTMemory(pScrn); if (pI830->AccelInfoRec) pI830->AccelInfoRec->NeedToSync = FALSE; } @@ -3246,22 +4375,34 @@ I830BIOSEnterVT(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); - static int SaveGeneration = -1; DPRINTF(PFX, "Enter VT\n"); - if (!I830BindGARTMemory(pScrn)) - return FALSE; + if (IsPrimary(pScrn)) { + if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to switch to configured display devices\n"); + return FALSE; + } + } + + /* Setup for checking lid status */ + pI830->monitorSwitch = INREG(SWF0) & 0x0000FFFF; + + if (IsPrimary(pScrn)) + if (!I830BindGARTMemory(pScrn)) + return FALSE; CheckInheritedState(pScrn); - SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); + if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize)) + SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); /* * Only save state once per server generation since that's what most * drivers do. Could change this to save state at each VT enter. */ - if (SaveGeneration != serverGeneration) { - SaveGeneration = serverGeneration; + if (pI830->SaveGeneration != serverGeneration) { + pI830->SaveGeneration = serverGeneration; SaveHWState(pScrn); } ResetState(pScrn, FALSE); @@ -3331,7 +4472,8 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) #define BINDUNBIND 0 #endif #if BINDUNBIND - I830UnbindGARTMemory(pScrn); + if (IsPrimary(pScrn)) + I830UnbindGARTMemory(pScrn); #endif #ifdef I830_XV /* Give the video overlay code a chance to see the new mode. */ @@ -3344,7 +4486,8 @@ I830BIOSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) I830VideoSwitchModeAfter(pScrn, mode); #endif #if BINDUNBIND - I830BindGARTMemory(pScrn); + if (IsPrimary(pScrn)) + I830BindGARTMemory(pScrn); #endif return ret; @@ -3361,7 +4504,7 @@ I830BIOSSaveScreen(ScreenPtr pScreen, int mode) DPRINTF(PFX, "I830BIOSSaveScreen: %d, on is %s\n", mode, BOOLTOSTRING(on)); if (pScrn->vtSema) { - for (i = 0; i < MAX_DISPLAY_PIPES; i++) { + for (i = 0; i < pI830->availablePipes; i++) { if (i == 0) { ctrl = DSPACNTR; base = DSPABASE; @@ -3401,6 +4544,34 @@ I830DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, I830Ptr pI830 = I830PTR(pScrn); vbeInfoPtr pVbe = pI830->pVbe; + if (pI830->Clone) { + SetBIOSPipe(pScrn, !pI830->pipe); + if (xf86LoaderCheckSymbol("VBEDPMSSet")) { + VBEDPMSSet(pVbe, PowerManagementMode); + } else { + pVbe->pInt10->num = 0x10; + pVbe->pInt10->ax = 0x4f10; + pVbe->pInt10->bx = 0x01; + + switch (PowerManagementMode) { + case DPMSModeOn: + break; + case DPMSModeStandby: + pVbe->pInt10->bx |= 0x0100; + break; + case DPMSModeSuspend: + pVbe->pInt10->bx |= 0x0200; + break; + case DPMSModeOff: + pVbe->pInt10->bx |= 0x0400; + break; + } + xf86ExecX86int10_wrapper(pVbe->pInt10, pScrn); + } + } + + SetPipeAccess(pScrn); + if (xf86LoaderCheckSymbol("VBEDPMSSet")) { VBEDPMSSet(pVbe, PowerManagementMode); } else { @@ -3465,7 +4636,23 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen) pI830->CursorInfoRec = 0; } - xf86GARTCloseScreen(scrnIndex); + if (IsPrimary(pScrn)) { + xf86GARTCloseScreen(scrnIndex); + + xfree(pI830->LpRing); + pI830->LpRing = NULL; + xfree(pI830->CursorMem); + pI830->CursorMem = NULL; + xfree(pI830->CursorMemARGB); + pI830->CursorMemARGB = NULL; + xfree(pI830->OverlayMem); + pI830->OverlayMem = NULL; + xfree(pI830->overlayOn); + pI830->overlayOn = NULL; + } + + if (pI830->lidTimer) + TimerCancel(pI830->lidTimer); pScrn->vtSema = FALSE; pI830->closing = FALSE; @@ -3473,7 +4660,7 @@ I830BIOSCloseScreen(int scrnIndex, ScreenPtr pScreen) return (*pScreen->CloseScreen) (scrnIndex, pScreen); } -static int +static ModeStatus I830ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) { if (mode->Flags & V_INTERLACE) { @@ -3546,6 +4733,65 @@ I830PMEvent(int scrnIndex, pmEvent event, Bool undo) return TRUE; } +static CARD32 +I830LidTimer(OsTimerPtr timer, CARD32 now, pointer arg) +{ + ScrnInfoPtr pScrn = (ScrnInfoPtr) arg; + I830Ptr pI830 = I830PTR(pScrn); + + if (pScrn->vtSema) { + /* Check for monitor lid being closed/opened and act accordingly */ + int temp = INREG(SWF0) & 0x0000FFFF; + + if (pI830->monitorSwitch != temp) { + int conf = pI830->operatingDevices; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Detected possible lid operation, fixing up.\n"); + if ((temp & 0x0808) == 0x0000) { + /* LFP (PIPE A or B) GOING OFF - PROBABLE LID CLOSURE */ + conf = pI830->operatingDevices & 0xF7F7; +#if 0 + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Lid is being closed.\n"); +#endif + } else { +#if 0 + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Lid is being opened.\n"); +#endif + } + + /* If we've defined our own monitors, then get them and set them + * up when switching in single head mode, no effect in dual heads + * NOTE: This assumes that the LCD is always on Pipe B..... */ + conf |= pI830->MonType1; + if (IsPrimary(pScrn)) { + if (!SetDisplayDevices(pScrn, conf)) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch " + "to configured display devices during lid operation.\n"); + } + pI830->monitorSwitch = conf; + + /* Now, when we're single head, make sure we switch pipes */ + if (!(xf86IsEntityShared(pScrn->entityList[0]) || pI830->Clone)) { + if ((temp & 0xFF00) == 0x0000) + pI830->pipe = 0; + if ((temp & 0x00FF) == 0x0000) + pI830->pipe = 1; + } + I830BIOSSwitchMode(pScrn->pScreen->myNum, pScrn->currentMode, 0); + I830BIOSAdjustFrame(pScrn->pScreen->myNum, pScrn->frameX0, pScrn->frameY0, 0); + + /* Everything should be o.k. now, so make sure the HW cursor is + * on the correct pipe */ + if (pI830->CursorInfoRec && !pI830->SWCursor && pI830->cursorOn) { + pI830->CursorInfoRec->ShowCursor(pScrn); + pI830->cursorOn = TRUE; + } + } + } + + return 1000; +} + void I830InitpScrn(ScrnInfoPtr pScrn) { diff --git a/src/i830_memory.c b/src/i830_memory.c index d3e52501..04e8deee 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -1,4 +1,4 @@ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_memory.c,v 1.7 2003/06/18 13:14:19 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_memory.c,v 1.9 2003/09/24 03:16:54 dawes Exp $ */ /************************************************************************** Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. @@ -46,6 +46,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Keith Whitwell <keith@tungstengraphics.com> * David Dawes <dawes@xfree86.org> * + * Updated for Dual Head capabilities: + * Alan Hourihane <alanh@tungstengraphics.com> */ #include "xf86.h" @@ -255,8 +257,8 @@ AllocateRingBuffer(ScrnInfoPtr pScrn, int flags) const char *s = dryrun ? "[dryrun] " : ""; /* Clear ring buffer info */ - memset(&(pI830->LpRing), 0, sizeof(pI830->LpRing)); - pI830->LpRing.mem.Key = -1; + memset(pI830->LpRing, 0, sizeof(I830RingBuffer)); + pI830->LpRing->mem.Key = -1; if (pI830->noAccel) return TRUE; @@ -268,7 +270,7 @@ AllocateRingBuffer(ScrnInfoPtr pScrn, int flags) else flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP; - alloced = I830AllocVidMem(pScrn, &(pI830->LpRing.mem), + alloced = I830AllocVidMem(pScrn, &(pI830->LpRing->mem), &(pI830->StolenPool), size, GTT_PAGE_SIZE, flags); if (alloced < size) { @@ -279,9 +281,9 @@ AllocateRingBuffer(ScrnInfoPtr pScrn, int flags) return FALSE; } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %d kB for the ring buffer at 0x%x\n", s, - alloced / 1024, pI830->LpRing.mem.Start); - pI830->LpRing.tail_mask = pI830->LpRing.mem.Size - 1; + "%sAllocated %ld kB for the ring buffer at 0x%lx\n", s, + alloced / 1024, pI830->LpRing->mem.Start); + pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1; return TRUE; } @@ -299,8 +301,8 @@ AllocateOverlay(ScrnInfoPtr pScrn, int flags) const char *s = dryrun ? "[dryrun] " : ""; /* Clear overlay info */ - memset(&(pI830->OverlayMem), 0, sizeof(pI830->OverlayMem)); - pI830->OverlayMem.Key = -1; + memset(pI830->OverlayMem, 0, sizeof(I830MemRange)); + pI830->OverlayMem->Key = -1; if (!pI830->XvEnabled) return TRUE; @@ -317,7 +319,7 @@ AllocateOverlay(ScrnInfoPtr pScrn, int flags) else flags |= FROM_ANYWHERE | ALLOCATE_AT_TOP | NEED_PHYSICAL_ADDR; - alloced = I830AllocVidMem(pScrn, &(pI830->OverlayMem), + alloced = I830AllocVidMem(pScrn, pI830->OverlayMem, &(pI830->StolenPool), size, GTT_PAGE_SIZE, flags); /* @@ -335,10 +337,10 @@ AllocateOverlay(ScrnInfoPtr pScrn, int flags) /* This failure isn't fatal. */ } else { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %d kB for Overlay registers at 0x%x " - "(0x%08x).\n", s, - alloced / 1024, pI830->OverlayMem.Start, - pI830->OverlayMem.Physical); + "%sAllocated %ld kB for Overlay registers at 0x%lx " + "(0x%08lx).\n", s, + alloced / 1024, pI830->OverlayMem->Start, + pI830->OverlayMem->Physical); } return TRUE; } @@ -433,6 +435,97 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) if (pI830->NeedRingBufferLow) AllocateRingBuffer(pScrn, flags | FORCE_LOW); + /* Unfortunately this doesn't run on the DRY_RUN pass because our + * second head hasn't been created yet..... */ + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) { + I830EntPtr pI830Ent = pI830->entityPrivate; + I830Ptr pI8302 = I830PTR(pI830Ent->pScrn_2); + + /* Clear everything first. */ + memset(&(pI830->FbMemBox2), 0, sizeof(pI830->FbMemBox2)); + memset(&(pI830->FrontBuffer2), 0, sizeof(pI830->FrontBuffer2)); + pI830->FrontBuffer2.Key = -1; + + pI830->FbMemBox2.x1 = 0; + pI830->FbMemBox2.x2 = pI830Ent->pScrn_2->displayWidth; + pI830->FbMemBox2.y1 = 0; + pI830->FbMemBox2.y2 = pI830Ent->pScrn_2->virtualY; + + /* + * Calculate how much framebuffer memory to allocate. For the + * initial allocation, calculate a reasonable minimum. This is + * enough for the virtual screen size, plus some pixmap cache + * space. + */ + + lineSize = pI830Ent->pScrn_2->displayWidth * pI8302->cpp; + minspace = lineSize * pI830Ent->pScrn_2->virtualY; + avail = pI830Ent->pScrn_2->videoRam * 1024; + maxCacheLines = (avail - minspace) / lineSize; + /* This shouldn't happen. */ + if (maxCacheLines < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Internal Error: " + "maxCacheLines < 0 in I830Allocate2DMemory()\n"); + maxCacheLines = 0; + } + if (maxCacheLines > (MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY)) + maxCacheLines = MAX_DISPLAY_HEIGHT - pI830Ent->pScrn_2->virtualY; + + if (pI8302->CacheLines >= 0) { + cacheLines = pI8302->CacheLines; + } else { +#if 1 + /* Make sure there is enough for two DVD sized YUV buffers */ + cacheLines = (pI830Ent->pScrn_2->depth == 24) ? 256 : 384; + if (pI830Ent->pScrn_2->displayWidth <= 1024) + cacheLines *= 2; +#else + /* + * Make sure there is enough for two DVD sized YUV buffers. + * Make that 1.5MB, which is around what was allocated with + * the old algorithm + */ + cacheLines = (MB(1) + KB(512)) / pI8302->cpp / pI830Ent->pScrn_2->displayWidth; +#endif + } + if (cacheLines > maxCacheLines) + cacheLines = maxCacheLines; + + pI830->FbMemBox2.y2 += cacheLines; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocating at least %d scanlines for pixmap cache\n", + s, cacheLines); + + tileable = !(flags & ALLOC_NO_TILING) && pI8302->allowPageFlip && + IsTileable(pI830Ent->pScrn_2->displayWidth * pI8302->cpp); + if (tileable) { + align = KB(512); + alignflags = ALIGN_BOTH_ENDS; + } else { + align = KB(64); + alignflags = 0; + } + + size = lineSize * (pI830Ent->pScrn_2->virtualY + cacheLines); + size = ROUND_TO_PAGE(size); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sSecondary framebuffer allocation size: %ld kByte\n", s, + size / 1024); + alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer2), + &(pI830->StolenPool), size, align, + flags | alignflags | + FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pI830Ent->pScrn_2->scrnIndex, X_ERROR, + "Failed to allocate secondary framebuffer.\n"); + } + return FALSE; + } + } + /* Clear everything first. */ memset(&(pI830->FbMemBox), 0, sizeof(pI830->FbMemBox)); memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer)); @@ -503,7 +596,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) size = lineSize * (pScrn->virtualY + cacheLines); size = ROUND_TO_PAGE(size); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sInitial framebuffer allocation size: %d kByte\n", s, + "%sInitial framebuffer allocation size: %ld kByte\n", s, size / 1024); alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer), &(pI830->StolenPool), size, align, @@ -511,8 +604,8 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) FROM_ANYWHERE | ALLOCATE_AT_BOTTOM); if (alloced < size) { if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate framebuffer.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate " + "framebuffer. Is your VideoRAM set too low ??\n"); } return FALSE; } @@ -547,7 +640,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error in I830Allocate2DMemory():\n\t" "Framebuffer isn't the last allocation at the bottom" - " of StolenPool\n\t(%x != %x).\n", + " of StolenPool\n\t(%lx != %lx).\n", pI830->FrontBuffer.End, pI830->StolenPool.Free.Start); return FALSE; @@ -564,10 +657,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) pI830->StolenPool.Free.Size += pI830->FrontBuffer.Size; pI830->StolenPool.Free.Start -= pI830->FrontBuffer.Size; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sUpdated framebuffer allocation size from %d " - "to %d kByte\n", s, oldsize / 1024, maxFb / 1024); + "%sUpdated framebuffer allocation size from %ld " + "to %ld kByte\n", s, oldsize / 1024, maxFb / 1024); xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sUpdated pixmap cache from %d scanlines to %d " + "%sUpdated pixmap cache from %ld scanlines to %ld " "scanlines\n", s, oldsize / lineSize - pScrn->virtualY, maxFb / lineSize - pScrn->virtualY); @@ -610,8 +703,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) #endif /* Clear cursor info */ - memset(&(pI830->CursorMem), 0, sizeof(pI830->CursorMem)); - pI830->CursorMem.Key = -1; + memset(pI830->CursorMem, 0, sizeof(I830MemRange)); + pI830->CursorMem->Key = -1; + memset(pI830->CursorMemARGB, 0, sizeof(I830MemRange)); + pI830->CursorMemARGB->Key = -1; if (!pI830->SWCursor) { int cursFlags = 0; @@ -626,7 +721,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) if (pI830->CursorNeedsPhysical) cursFlags |= NEED_PHYSICAL_ADDR; - alloced = I830AllocVidMem(pScrn, &(pI830->CursorMem), + alloced = I830AllocVidMem(pScrn, pI830->CursorMem, &(pI830->StolenPool), size, GTT_PAGE_SIZE, flags | cursFlags); if (alloced < size) { @@ -636,10 +731,32 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) } } else { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %d kB for HW cursor at 0x%x", s, - alloced / 1024, pI830->CursorMem.Start); + "%sAllocated %ld kB for HW cursor at 0x%lx", s, + alloced / 1024, pI830->CursorMem->Start); if (pI830->CursorNeedsPhysical) - xf86ErrorFVerb(verbosity, " (0x%08x)", pI830->CursorMem.Physical); + xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMem->Physical); + xf86ErrorFVerb(verbosity, "\n"); + } + + size = HWCURSOR_SIZE_ARGB; + cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP; + if (pI830->CursorNeedsPhysical) + cursFlags |= NEED_PHYSICAL_ADDR; + + alloced = I830AllocVidMem(pScrn, pI830->CursorMemARGB, + &(pI830->StolenPool), size, + GTT_PAGE_SIZE, flags | cursFlags); + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate HW (ARGB) cursor space.\n"); + } + } else { + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s, + alloced / 1024, pI830->CursorMemARGB->Start); + if (pI830->CursorNeedsPhysical) + xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMemARGB->Physical); xf86ErrorFVerb(verbosity, "\n"); } } @@ -652,8 +769,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) AllocateRingBuffer(pScrn, flags); /* Clear scratch info */ - memset(&(pI830->Scratch), 0, sizeof(pI830->Scratch)); + memset(&(pI830->Scratch), 0, sizeof(I830MemRange)); pI830->Scratch.Key = -1; + memset(&(pI830->Scratch2), 0, sizeof(I830MemRange)); + pI830->Scratch2.Key = -1; if (!pI830->noAccel) { size = MAX_SCRATCH_BUFFER_SIZE; @@ -675,8 +794,35 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags) return FALSE; } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %d kB for the scratch buffer at 0x%x\n", s, + "%sAllocated %ld kB for the scratch buffer at 0x%lx\n", s, alloced / 1024, pI830->Scratch.Start); + + /* Let's allocate another scratch buffer for the second head */ + /* Again, this code won't execute on the dry run pass */ + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) { + size = MAX_SCRATCH_BUFFER_SIZE; + alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2), + &(pI830->StolenPool), + size, GTT_PAGE_SIZE, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); + if (alloced < size) { + size = MIN_SCRATCH_BUFFER_SIZE; + alloced = I830AllocVidMem(pScrn, &(pI830->Scratch2), + &(pI830->StolenPool), size, + GTT_PAGE_SIZE, + flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); + } + if (alloced < size) { + if (!dryrun) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to allocate second scratch buffer space\n"); + } + return FALSE; + } + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, + "%sAllocated %ld kB for the second scratch buffer at 0x%lx\n", s, + alloced / 1024, pI830->Scratch2.Start); + } } return TRUE; } @@ -806,7 +952,7 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) return FALSE; } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %d kB for the back buffer at 0x%x.\n", s, + "%sAllocated %ld kB for the back buffer at 0x%lx.\n", s, alloced / 1024, pI830->BackBuffer.Start); /* Depth Buffer -- same size as the back buffer */ @@ -844,7 +990,7 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) return FALSE; } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %d kB for the depth buffer at 0x%x.\n", s, + "%sAllocated %ld kB for the depth buffer at 0x%lx.\n", s, alloced / 1024, pI830->DepthBuffer.Start); /* Space for logical context. 32k is fine for right now. */ @@ -865,36 +1011,6 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) "%sAllocated %d kB for the logical context at 0x%x.\n", s, alloced / 1024, pI830->ContextMem.Start); - /* - * Space for DMA buffers, only if there's enough free for at least 1MB - * of texture space. - */ - memset(&(pI830->BufferMem), 0, sizeof(pI830->BufferMem)); - pI830->BufferMem.Key = -1; - /* This should already be a page multiple */ - size = I830_DMA_BUF_NR * I830_DMA_BUF_SZ; - if (dryrun || (GetFreeSpace(pScrn) >= size + MB(1))) { - alloced = I830AllocVidMem(pScrn, &(pI830->BufferMem), - &(pI830->StolenPool), size, - GTT_PAGE_SIZE, - flags | FROM_ANYWHERE | ALLOCATE_AT_TOP); - if (alloced < size) { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Failed to allocate DMA buffer space.\n"); - } - return FALSE; - } - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %d kB for the DMA buffers at 0x%x.\n", s, - alloced / 1024, pI830->BufferMem.Start); - } else { - if (!dryrun) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Not enough free space for DMA buffers.\n"); - } - return FALSE; - } /* Allocate the remaining space for textures. */ memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem)); @@ -912,7 +1028,8 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) if (size < KB(512)) { if (!dryrun) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Less than %d kBytes for texture space.\n", size / 1024); + "Less than 512 kBytes for texture space (real %ld kBytes).\n", + size / 1024); } return FALSE; } @@ -927,7 +1044,7 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags) return FALSE; } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity, - "%sAllocated %d kB for textures at 0x%x\n", s, + "%sAllocated %ld kB for textures at 0x%lx\n", s, alloced / 1024, pI830->TexMem.Start); return TRUE; @@ -1052,7 +1169,7 @@ FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem) } #endif xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "%p: Memory at offset 0x%08x, size %d kBytes\n", mem, + "%p: Memory at offset 0x%08lx, size %ld kBytes\n", (void *)mem, mem->Start, mem->Size / 1024); return TRUE; } @@ -1065,13 +1182,18 @@ I830FixupOffsets(ScrnInfoPtr pScrn) DPRINTF(PFX, "I830FixupOffsets\n"); topOfMem = pI830->StolenPool.Total.End; + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) + FixOffset(pScrn, &(pI830->FrontBuffer2)); FixOffset(pScrn, &(pI830->FrontBuffer)); - FixOffset(pScrn, &(pI830->CursorMem)); - FixOffset(pScrn, &(pI830->LpRing.mem)); + FixOffset(pScrn, pI830->CursorMem); + FixOffset(pScrn, pI830->CursorMemARGB); + FixOffset(pScrn, &(pI830->LpRing->mem)); FixOffset(pScrn, &(pI830->Scratch)); + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) + FixOffset(pScrn, &(pI830->Scratch2)); #ifdef I830_XV if (pI830->XvEnabled) { - FixOffset(pScrn, &(pI830->OverlayMem)); + FixOffset(pScrn, pI830->OverlayMem); } #endif #ifdef XF86DRI @@ -1079,7 +1201,6 @@ I830FixupOffsets(ScrnInfoPtr pScrn) FixOffset(pScrn, &(pI830->BackBuffer)); FixOffset(pScrn, &(pI830->DepthBuffer)); FixOffset(pScrn, &(pI830->ContextMem)); - FixOffset(pScrn, &(pI830->BufferMem)); FixOffset(pScrn, &(pI830->TexMem)); } #endif @@ -1102,6 +1223,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, I830RegPtr i830Reg = &pI830->ModeReg; CARD32 val; CARD32 fence_mask = 0; + unsigned int fence_pitch; DPRINTF(PFX, "SetFence: %d, 0x%08x, %d, %d kByte\n", nr, start, pitch, size / 1024); @@ -1114,12 +1236,15 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, i830Reg->Fence[nr] = 0; - fence_mask = ~I830_FENCE_START_MASK; + if (IS_I915G(pI830)) + fence_mask = ~I915G_FENCE_START_MASK; + else + fence_mask = ~I830_FENCE_START_MASK; if (start & fence_mask) { xf86DrvMsg(X_WARNING, pScrn->scrnIndex, - "SetFence: %d: start (0x%08x) is not 512k aligned\n", - nr, start); + "SetFence: %d: start (0x%08x) is not %s aligned\n", + nr, start, (IS_I915G(pI830)) ? "1MB" : "512k"); return; } @@ -1139,38 +1264,73 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, val = (start | FENCE_X_MAJOR | FENCE_VALID); - switch (size) { - case KB(512): - val |= FENCE_SIZE_512K; - break; - case MB(1): - val |= FENCE_SIZE_1M; - break; - case MB(2): - val |= FENCE_SIZE_2M; - break; - case MB(4): - val |= FENCE_SIZE_4M; - break; - case MB(8): - val |= FENCE_SIZE_8M; - break; - case MB(16): - val |= FENCE_SIZE_16M; - break; - case MB(32): - val |= FENCE_SIZE_32M; - break; - case MB(64): - val |= FENCE_SIZE_64M; - break; - default: - xf86DrvMsg(X_WARNING, pScrn->scrnIndex, + if (IS_I915G(pI830)) { + switch (size) { + case MB(1): + val |= I915G_FENCE_SIZE_1M; + break; + case MB(2): + val |= I915G_FENCE_SIZE_2M; + break; + case MB(4): + val |= I915G_FENCE_SIZE_4M; + break; + case MB(8): + val |= I915G_FENCE_SIZE_8M; + break; + case MB(16): + val |= I915G_FENCE_SIZE_16M; + break; + case MB(32): + val |= I915G_FENCE_SIZE_32M; + break; + case MB(64): + val |= I915G_FENCE_SIZE_64M; + break; + default: + xf86DrvMsg(X_WARNING, pScrn->scrnIndex, "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); - return; + return; + } + } else { + switch (size) { + case KB(512): + val |= FENCE_SIZE_512K; + break; + case MB(1): + val |= FENCE_SIZE_1M; + break; + case MB(2): + val |= FENCE_SIZE_2M; + break; + case MB(4): + val |= FENCE_SIZE_4M; + break; + case MB(8): + val |= FENCE_SIZE_8M; + break; + case MB(16): + val |= FENCE_SIZE_16M; + break; + case MB(32): + val |= FENCE_SIZE_32M; + break; + case MB(64): + val |= FENCE_SIZE_64M; + break; + default: + xf86DrvMsg(X_WARNING, pScrn->scrnIndex, + "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024); + return; + } } - switch (pitch / 128) { + if (IS_I915G(pI830)) + fence_pitch = pitch / 512; + else + fence_pitch = pitch / 128; + + switch (fence_pitch) { case 1: val |= FENCE_PITCH_1; break; @@ -1337,16 +1497,24 @@ I830BindGARTMemory(ScrnInfoPtr pScrn) if (!BindMemRange(pScrn, &(pI830->StolenPool.Allocated))) return FALSE; + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) + if (!BindMemRange(pScrn, &(pI830->FrontBuffer2))) + return FALSE; if (!BindMemRange(pScrn, &(pI830->FrontBuffer))) return FALSE; - if (!BindMemRange(pScrn, &(pI830->CursorMem))) + if (!BindMemRange(pScrn, pI830->CursorMem)) + return FALSE; + if (!BindMemRange(pScrn, pI830->CursorMemARGB)) return FALSE; - if (!BindMemRange(pScrn, &(pI830->LpRing.mem))) + if (!BindMemRange(pScrn, &(pI830->LpRing->mem))) return FALSE; if (!BindMemRange(pScrn, &(pI830->Scratch))) return FALSE; + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) + if (!BindMemRange(pScrn, &(pI830->Scratch2))) + return FALSE; #ifdef I830_XV - if (!BindMemRange(pScrn, &(pI830->OverlayMem))) + if (!BindMemRange(pScrn, pI830->OverlayMem)) return FALSE; #endif #ifdef XF86DRI @@ -1357,8 +1525,6 @@ I830BindGARTMemory(ScrnInfoPtr pScrn) return FALSE; if (!BindMemRange(pScrn, &(pI830->ContextMem))) return FALSE; - if (!BindMemRange(pScrn, &(pI830->BufferMem))) - return FALSE; if (!BindMemRange(pScrn, &(pI830->TexMem))) return FALSE; } @@ -1403,16 +1569,24 @@ I830UnbindGARTMemory(ScrnInfoPtr pScrn) if (!UnbindMemRange(pScrn, &(pI830->StolenPool.Allocated))) return FALSE; + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) + if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer2))) + return FALSE; if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer))) return FALSE; - if (!UnbindMemRange(pScrn, &(pI830->CursorMem))) + if (!UnbindMemRange(pScrn, pI830->CursorMem)) + return FALSE; + if (!UnbindMemRange(pScrn, pI830->CursorMemARGB)) return FALSE; - if (!UnbindMemRange(pScrn, &(pI830->LpRing.mem))) + if (!UnbindMemRange(pScrn, &(pI830->LpRing->mem))) return FALSE; if (!UnbindMemRange(pScrn, &(pI830->Scratch))) return FALSE; + if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2) + if (!UnbindMemRange(pScrn, &(pI830->Scratch2))) + return FALSE; #ifdef I830_XV - if (!UnbindMemRange(pScrn, &(pI830->OverlayMem))) + if (!UnbindMemRange(pScrn, pI830->OverlayMem)) return FALSE; #endif #ifdef XF86DRI @@ -1423,8 +1597,6 @@ I830UnbindGARTMemory(ScrnInfoPtr pScrn) return FALSE; if (!UnbindMemRange(pScrn, &(pI830->ContextMem))) return FALSE; - if (!UnbindMemRange(pScrn, &(pI830->BufferMem))) - return FALSE; if (!UnbindMemRange(pScrn, &(pI830->TexMem))) return FALSE; } diff --git a/src/i830_video.c b/src/i830_video.c index 3d7b0349..31be8a64 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -24,7 +24,7 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **************************************************************************/ -/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_video.c,v 1.8 2003/06/18 13:14:19 dawes Exp $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_video.c,v 1.11tsi Exp $ */ /* * Reformatted with GNU indent (2.2.8), using the following options: @@ -111,6 +111,7 @@ static void I830BlockHandler(int, pointer, pointer, pointer); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) static Atom xvBrightness, xvContrast, xvColorKey; +static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; #define IMAGE_MAX_WIDTH 1440 #define IMAGE_MAX_HEIGHT 1080 @@ -138,36 +139,36 @@ Edummy(const char *dummy, ...) BEGIN_LP_RING(6); \ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE); \ OUT_RING(MI_NOOP); \ - if (!pI830->overlayOn) { \ + if (!*pI830->overlayOn) { \ OUT_RING(MI_NOOP); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_ON); \ ErrorF("Overlay goes from off to on\n"); \ - pI830->overlayOn = TRUE; \ + *pI830->overlayOn = TRUE; \ } else { \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_CONTINUE); \ } \ - OUT_RING(pI830->OverlayMem.Physical | 1); \ + OUT_RING(pI830->OverlayMem->Physical | 1); \ ADVANCE_LP_RING(); \ ErrorF("OVERLAY_UPDATE\n"); \ } while(0) #define OVERLAY_OFF \ do { \ - if (pI830->overlayOn) { \ + if (*pI830->overlayOn) { \ BEGIN_LP_RING(8); \ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_FLIP_OFF); \ - OUT_RING(pI830->OverlayMem.Physical); \ + OUT_RING(pI830->OverlayMem->Physical); \ OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); \ OUT_RING(MI_NOOP); \ ADVANCE_LP_RING(); \ - pI830->overlayOn = FALSE; \ + *pI830->overlayOn = FALSE; \ ErrorF("Overlay goes from on to off\n"); \ ErrorF("OVERLAY_OFF\n"); \ } \ @@ -250,12 +251,18 @@ static XF86VideoFormatRec Formats[NUM_FORMATS] = { {15, TrueColor}, {16, TrueColor}, {24, TrueColor} }; -#define NUM_ATTRIBUTES 3 +#define NUM_ATTRIBUTES 9 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, {XvSettable | XvGettable, -128, 127, "XV_BRIGHTNESS"}, - {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"} + {XvSettable | XvGettable, 0, 255, "XV_CONTRAST"}, + {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA0"}, + {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA1"}, + {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"}, + {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"}, + {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"}, + {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"} }; #define NUM_IMAGES 4 @@ -323,15 +330,6 @@ typedef struct { } I830OverlayRegRec, *I830OverlayRegPtr; typedef struct { - CARD32 GAMC5; - CARD32 GAMC4; - CARD32 GAMC3; - CARD32 GAMC2; - CARD32 GAMC1; - CARD32 GAMC0; -} I830OverlayStateRec, *I830OverlayStatePtr; - -typedef struct { CARD32 YBuf0offset; CARD32 UBuf0offset; CARD32 VBuf0offset; @@ -348,20 +346,27 @@ typedef struct { RegionRec clip; CARD32 colorKey; + CARD32 gamma0; + CARD32 gamma1; + CARD32 gamma2; + CARD32 gamma3; + CARD32 gamma4; + CARD32 gamma5; + CARD32 videoStatus; Time offTime; Time freeTime; FBLinearPtr linear; - I830OverlayStateRec hwstate; - - Bool refreshOK; - int maxRate; + Bool overlayOK; + int oneLineMode; + int scaleRatio; } I830PortPrivRec, *I830PortPrivPtr; #define GET_PORT_PRIVATE(pScrn) \ (I830PortPrivPtr)((I830PTR(pScrn))->adaptor->pPortPrivates[0].ptr) +#if VIDEO_DEBUG static void CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size) { @@ -380,6 +385,7 @@ CompareOverlay(I830Ptr pI830, CARD32 * overlay, int size) if (!bad) ErrorF("CompareOverlay: no differences\n"); } +#endif void I830InitVideo(ScreenPtr pScreen) @@ -442,11 +448,10 @@ I830ResetVideo(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start); - I830OverlayStatePtr hwstate = &(pPriv->hwstate); + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); DPRINTF(PFX, "I830ResetVideo: base: %p, offset: 0x%08x, obase: %p\n", - pI830->FbBase, pI830->OverlayMem.Start, overlay); + pI830->FbBase, pI830->OverlayMem->Start, overlay); /* * Default to maximum image size in YV12 */ @@ -461,7 +466,7 @@ I830ResetVideo(ScrnInfoPtr pScrn) overlay->SWIDTH = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 16); overlay->SWIDTHSW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12); overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15); - overlay->OCLRC0 = 0x01000000; /* brightness: 0 contrast: 1.0 */ + overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); overlay->OCLRC1 = 0x00000080; /* saturation: bypass */ overlay->AWINPOS = 0; overlay->AWINSZ = 0; @@ -495,25 +500,16 @@ I830ResetVideo(ScrnInfoPtr pScrn) overlay->OCONFIG = CC_OUT_8BIT; /* - * Select which pipe the overlay is enabled on. Give preference to - * pipe A. + * Select which pipe the overlay is enabled on. */ - if (pI830->pipeEnabled[0]) + overlay->OCONFIG &= ~OVERLAY_PIPE_MASK; + if (pI830->pipe == 0) overlay->OCONFIG |= OVERLAY_PIPE_A; - else if (pI830->pipeEnabled[1]) + else overlay->OCONFIG |= OVERLAY_PIPE_B; overlay->OCMD = YUV_420; - /* setup hwstate */ - /* Default gamma correction values. */ - hwstate->GAMC5 = 0xc0c0c0; - hwstate->GAMC4 = 0x808080; - hwstate->GAMC3 = 0x404040; - hwstate->GAMC2 = 0x202020; - hwstate->GAMC1 = 0x101010; - hwstate->GAMC0 = 0x080808; - #if 0 /* * XXX DUMP REGISTER CODE !!! @@ -526,34 +522,56 @@ I830ResetVideo(ScrnInfoPtr pScrn) ErrorF("0x%x 0x%08x\n", i, INREG(i)); } #endif +} - OUTREG(OGAMC5, hwstate->GAMC5); - OUTREG(OGAMC4, hwstate->GAMC4); - OUTREG(OGAMC3, hwstate->GAMC3); - OUTREG(OGAMC2, hwstate->GAMC2); - OUTREG(OGAMC1, hwstate->GAMC1); - OUTREG(OGAMC0, hwstate->GAMC0); +#define PFIT_CONTROLS 0x61230 +#define PFIT_AUTOVSCALE_MASK 0x200 +#define PFIT_ON_MASK 0x80000000 +#define PFIT_AUTOSCALE_RATIO 0x61238 +#define PFIT_PROGRAMMED_SCALE_RATIO 0x61234 +static void +I830SetOneLineModeRatio(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; + CARD32 panelFitControl = INREG(PFIT_CONTROLS); + int vertScale; + + pPriv->scaleRatio = 0x10000; + + if (panelFitControl & PFIT_ON_MASK) { + if (panelFitControl & PFIT_AUTOVSCALE_MASK) { + vertScale = INREG(PFIT_AUTOSCALE_RATIO) >> 16; + } else { + vertScale = INREG(PFIT_PROGRAMMED_SCALE_RATIO) >> 16; + } + + if (vertScale != 0) + pPriv->scaleRatio = ((double) 0x10000 / (double)vertScale) * 0x10000; + + pPriv->oneLineMode = TRUE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Enabling Xvideo one-line mode\n"); + } + + if (pPriv->scaleRatio == 0x10000) + pPriv->oneLineMode = FALSE; } -/* - * Each chipset has a limit on the pixel rate that the video overlay can - * be used for. Enabling the overlay above that limit can result in a - * lockup. These two functions check the pixel rate for the new mode - * and turn the overlay off before switching to the new mode if it exceeds - * the limit, or turn it back on if the new mode is below the limit. - */ +static void +I830UpdateGamma(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; -/* - * Approximate pixel rate limits for the video overlay. - * The rate is calculated based on the mode resolution and refresh rate. - */ -#define I830_OVERLAY_RATE 79 /* 1024x768@85, 1280x1024@60 */ -#define I845_OVERLAY_RATE 120 /* 1280x1024@85, 1600x1200@60 */ -#define I852_OVERLAY_RATE 79 /* 1024x768@85, 1280x1024@60 */ -#define I855_OVERLAY_RATE 120 /* 1280x1024@85, 1600x1200@60 */ -#define I865_OVERLAY_RATE 170 /* 1600x1200@85, 1920x1440@60 */ -#define DEFAULT_OVERLAY_RATE 120 + OUTREG(OGAMC5, pPriv->gamma5); + OUTREG(OGAMC4, pPriv->gamma4); + OUTREG(OGAMC3, pPriv->gamma3); + OUTREG(OGAMC2, pPriv->gamma2); + OUTREG(OGAMC1, pPriv->gamma1); + OUTREG(OGAMC0, pPriv->gamma0); +} static XF86VideoAdaptorPtr I830SetupImageVideo(ScreenPtr pScreen) @@ -571,7 +589,7 @@ I830SetupImageVideo(ScreenPtr pScreen) adapt->type = XvWindowMask | XvInputMask | XvImageMask; adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; - adapt->name = "Intel(R) 830M/845G/852GM/855GM/865G Video Overlay"; + adapt->name = "Intel(R) 830M/845G/852GM/855GM/865G/915G Video Overlay"; adapt->nEncodings = 1; adapt->pEncodings = DummyEncoding; adapt->nFormats = NUM_FORMATS; @@ -584,7 +602,10 @@ I830SetupImageVideo(ScreenPtr pScreen) adapt->pPortPrivates[0].ptr = (pointer) (pPriv); adapt->pAttributes = Attributes; adapt->nImages = NUM_IMAGES; - adapt->nAttributes = NUM_ATTRIBUTES; + if (IS_I915G(pI830)) + adapt->nAttributes = 9; /* has gamma */ + else + adapt->nAttributes = 3; adapt->pImages = Images; adapt->PutVideo = NULL; adapt->PutStill = NULL; @@ -603,39 +624,29 @@ I830SetupImageVideo(ScreenPtr pScreen) pPriv->contrast = 64; pPriv->linear = NULL; pPriv->currentBuf = 0; - - switch (pI830->PciInfo->chipType) { - case PCI_CHIP_I830_M: - pPriv->maxRate = I830_OVERLAY_RATE; - break; - case PCI_CHIP_845_G: - pPriv->maxRate = I845_OVERLAY_RATE; - break; - case PCI_CHIP_I855_GM: - switch (pI830->variant) { - case I852_GM: - case I852_GME: - pPriv->maxRate = I852_OVERLAY_RATE; - break; - default: - pPriv->maxRate = I855_OVERLAY_RATE; - break; - } - break; - case PCI_CHIP_I865_G: - pPriv->maxRate = I865_OVERLAY_RATE; - break; - default: - pPriv->maxRate = DEFAULT_OVERLAY_RATE; - break; - } + pPriv->gamma5 = 0xc0c0c0; + pPriv->gamma4 = 0x808080; + pPriv->gamma3 = 0x404040; + pPriv->gamma2 = 0x202020; + pPriv->gamma1 = 0x101010; + pPriv->gamma0 = 0x080808; /* gotta uninit this someplace */ REGION_INIT(pScreen, &pPriv->clip, NullBox, 0); pI830->adaptor = adapt; - /* Initialise pPriv->refreshOK */ + /* With LFP's we need to detect whether we're in One Line Mode, which + * essentially means a resolution greater than 1024x768, and fix up + * the scaler accordingly. */ + pPriv->scaleRatio = 0x10000; + pPriv->oneLineMode = FALSE; + + /* + * Initialise pPriv->overlayOK. Set it to TRUE here so that a warning will + * be generated if I830VideoSwitchModeAfter() sets it to FALSE. + */ + pPriv->overlayOK = TRUE; I830VideoSwitchModeAfter(pScrn, pScrn->currentMode); pI830->BlockHandler = pScreen->BlockHandler; @@ -644,12 +655,50 @@ I830SetupImageVideo(ScreenPtr pScreen) xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvContrast = MAKE_ATOM("XV_CONTRAST"); xvColorKey = MAKE_ATOM("XV_COLORKEY"); + if (IS_I915G(pI830)) { + xvGamma0 = MAKE_ATOM("XV_GAMMA0"); + xvGamma1 = MAKE_ATOM("XV_GAMMA1"); + xvGamma2 = MAKE_ATOM("XV_GAMMA2"); + xvGamma3 = MAKE_ATOM("XV_GAMMA3"); + xvGamma4 = MAKE_ATOM("XV_GAMMA4"); + xvGamma5 = MAKE_ATOM("XV_GAMMA5"); + } I830ResetVideo(pScrn); + I830UpdateGamma(pScrn); + return adapt; } +static Bool +RegionsEqual(RegionPtr A, RegionPtr B) +{ + int *dataA, *dataB; + int num; + + num = REGION_NUM_RECTS(A); + if (num != REGION_NUM_RECTS(B)) + return FALSE; + + if ((A->extents.x1 != B->extents.x1) || + (A->extents.x2 != B->extents.x2) || + (A->extents.y1 != B->extents.y1) || (A->extents.y2 != B->extents.y2)) + return FALSE; + + dataA = (int *)REGION_RECTS(A); + dataB = (int *)REGION_RECTS(B); + + while (num--) { + if ((dataA[0] != dataB[0]) || (dataA[1] != dataB[1])) + return FALSE; + dataA += 2; + dataB += 2; + } + + return TRUE; +} + static void I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) { @@ -657,7 +706,7 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) I830Ptr pI830 = I830PTR(pScrn); I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); DPRINTF(PFX, "I830StopVideo\n"); @@ -669,6 +718,9 @@ I830StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) OVERLAY_UPDATE; OVERLAY_OFF; + + if (pI830->entityPrivate) + pI830->entityPrivate->XvInUse = -1; } if (pPriv->linear) { xf86FreeOffscreenLinear(pPriv->linear); @@ -691,22 +743,66 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv = (I830PortPrivPtr) data; I830Ptr pI830 = I830PTR(pScrn); I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); if (attribute == xvBrightness) { if ((value < -128) || (value > 127)) return BadValue; pPriv->brightness = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - if (pPriv->refreshOK) + if (pPriv->overlayOK) OVERLAY_UPDATE; } else if (attribute == xvContrast) { if ((value < 0) || (value > 255)) return BadValue; pPriv->contrast = value; overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); - if (pPriv->refreshOK) + if (pPriv->overlayOK) OVERLAY_UPDATE; + } else if (attribute == xvGamma0 && (IS_I915G(pI830))) { + /* Avoid video anomalies, so set gamma registers when overlay is off */ + /* We also clamp the values if they are outside the ranges */ + if (!*pI830->overlayOn) { + pPriv->gamma0 = value; + if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) + pPriv->gamma1 = pPriv->gamma0 + 0x7d; + } else + return BadRequest; + } else if (attribute == xvGamma1 && (IS_I915G(pI830))) { + if (!*pI830->overlayOn) { + pPriv->gamma1 = value; + if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) + pPriv->gamma0 = pPriv->gamma1 - 0x7d; + } else + return BadRequest; + } else if (attribute == xvGamma2 && (IS_I915G(pI830))) { + if (!*pI830->overlayOn) { + pPriv->gamma2 = value; + if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) + pPriv->gamma3 = pPriv->gamma2 + 0x7d; + } else + return BadRequest; + } else if (attribute == xvGamma3 && (IS_I915G(pI830))) { + if (!*pI830->overlayOn) { + pPriv->gamma3 = value; + if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) + pPriv->gamma2 = pPriv->gamma3 - 0x7d; + } else + return BadRequest; + } else if (attribute == xvGamma4 && (IS_I915G(pI830))) { + if (!*pI830->overlayOn) { + pPriv->gamma4 = value; + if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) + pPriv->gamma5 = pPriv->gamma4 + 0x7d; + } else + return BadRequest; + } else if (attribute == xvGamma5 && (IS_I915G(pI830))) { + if (!*pI830->overlayOn) { + pPriv->gamma5 = value; + if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) + pPriv->gamma4 = pPriv->gamma5 - 0x7d; + } else + return BadRequest; } else if (attribute == xvColorKey) { pPriv->colorKey = value; switch (pScrn->depth) { @@ -720,12 +816,22 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->DCLRKV = pPriv->colorKey; break; } - if (pPriv->refreshOK) + if (pPriv->overlayOK) OVERLAY_UPDATE; REGION_EMPTY(pScrn->pScreen, &pPriv->clip); } else return BadMatch; + /* We've already confirmed that the overlay is off, ready for updating */ + if ((attribute == xvGamma0 || + attribute == xvGamma1 || + attribute == xvGamma2 || + attribute == xvGamma3 || + attribute == xvGamma4 || + attribute == xvGamma5) && (IS_I915G(pI830))) { + I830UpdateGamma(pScrn); + } + return Success; } @@ -733,12 +839,25 @@ static int I830GetPortAttribute(ScrnInfoPtr pScrn, Atom attribute, INT32 * value, pointer data) { + I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = (I830PortPrivPtr) data; if (attribute == xvBrightness) { *value = pPriv->brightness; } else if (attribute == xvContrast) { *value = pPriv->contrast; + } else if (attribute == xvGamma0 && (IS_I915G(pI830))) { + *value = pPriv->gamma0; + } else if (attribute == xvGamma1 && (IS_I915G(pI830))) { + *value = pPriv->gamma1; + } else if (attribute == xvGamma2 && (IS_I915G(pI830))) { + *value = pPriv->gamma2; + } else if (attribute == xvGamma3 && (IS_I915G(pI830))) { + *value = pPriv->gamma3; + } else if (attribute == xvGamma4 && (IS_I915G(pI830))) { + *value = pPriv->gamma4; + } else if (attribute == xvGamma5 && (IS_I915G(pI830))) { + *value = pPriv->gamma5; } else if (attribute == xvColorKey) { *value = pPriv->colorKey; } else @@ -985,7 +1104,7 @@ UpdateCoeff(int taps, double fCutoff, Bool isHoriz, Bool isY, coeffPtr pCoeff) SetCoeffRegs(&coeffs[i][tap2Fix], mantSize + 2, pCoeff, pos); else SetCoeffRegs(&coeffs[i][tap2Fix], mantSize, pCoeff, pos); - + sum = 0.0; for (j = 0; j < taps; j++) sum += coeffs[i][j]; @@ -1004,16 +1123,22 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = pI830->adaptor->pPortPrivates[0].ptr; I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); unsigned int swidth; DPRINTF(PFX, "I830DisplayVideo: %dx%d (pitch %d)\n", width, height, dstPitch); - if (!pPriv->refreshOK) + if (!pPriv->overlayOK) return; +#if VIDEO_DEBUG CompareOverlay(pI830, (CARD32 *) overlay, 0x100); +#endif + + /* When in dual head with different bpp setups we need to refresh the + * color key, so let's reset the video parameters and refresh here */ + I830ResetVideo(pScrn); switch (id) { case FOURCC_YV12: @@ -1049,15 +1174,27 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, overlay->SHEIGHT = height | ((height / 2) << 16); + if (pPriv->oneLineMode) { + /* change the coordinates with panel fitting active */ + dstBox->y1 = (((dstBox->y1 - 1) * pPriv->scaleRatio) >> 16) + 1; + dstBox->y2 = ((dstBox->y2 * pPriv->scaleRatio) >> 16) + 1; + + /* Now, alter the height, so we scale to the correct size */ + drw_h = dstBox->y2 - dstBox->y1; + if (drw_h < height) drw_h = height; + } + overlay->DWINPOS = (dstBox->y1 << 16) | dstBox->x1; + overlay->DWINSZ = ((dstBox->y2 - dstBox->y1) << 16) | (dstBox->x2 - dstBox->x1); /* buffer locations */ overlay->OBUF_0Y = pPriv->YBuf0offset; - overlay->OBUF_1Y = pPriv->YBuf1offset; overlay->OBUF_0U = pPriv->UBuf0offset; overlay->OBUF_0V = pPriv->VBuf0offset; + + overlay->OBUF_1Y = pPriv->YBuf1offset; overlay->OBUF_1U = pPriv->UBuf1offset; overlay->OBUF_1V = pPriv->VBuf1offset; @@ -1147,7 +1284,7 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, scaleChanged = TRUE; overlay->YRGBSCALE = newval; } - + newval = (xscaleIntUV << 16) | ((xscaleFractUV & 0xFFF) << 3) | ((yscaleFractUV & 0xFFF) << 20); if (newval != overlay->UVSCALE) { @@ -1162,14 +1299,14 @@ I830DisplayVideo(ScrnInfoPtr pScrn, int id, short width, short height, } /* Recalculate coefficients if the scaling changed. */ - + /* * Only Horizontal coefficients so far. */ if (scaleChanged) { double fCutoffY; double fCutoffUV; - + fCutoffY = xscaleFract / 4096.0; fCutoffUV = xscaleFractUV / 4096.0; @@ -1248,8 +1385,13 @@ I830AllocateMemory(ScrnInfoPtr pScrn, FBLinearPtr linear, int size) { ScreenPtr pScreen; FBLinearPtr new_linear; + int bytespp = pScrn->bitsPerPixel >> 3; DPRINTF(PFX, "I830AllocateMemory\n"); + + /* convert size in bytes into number of pixels */ + size = (size + bytespp - 1) / bytespp; + if (linear) { if (linear->size >= size) return linear; @@ -1304,6 +1446,19 @@ I830PutImage(ScrnInfoPtr pScrn, "width %d, height %d\n", src_x, src_y, src_w, src_h, drw_x, drw_y, drw_w, drw_h, width, height); + if (pI830->entityPrivate) { + if (pI830->entityPrivate->XvInUse != -1 && + pI830->entityPrivate->XvInUse != pI830->pipe) { + if (!noPanoramiXExtension) { + return Success; /* faked for trying to share it */ + } else { + return BadAlloc; + } + } + + pI830->entityPrivate->XvInUse = pI830->pipe; + } + /* Clip */ x1 = src_x; x2 = src_x + src_w; @@ -1404,12 +1559,8 @@ I830PutImage(ScrnInfoPtr pScrn, } /* update cliplist */ - /* - * XXX Always draw the key. LinDVD seems to fill the window background - * with a colour different from the key. This works around that. - */ - if (1 || !REGION_EQUAL(pScreen, &pPriv->clip, clipBoxes)) { - REGION_COPY(pScreen, &pPriv->clip, clipBoxes); + if (!RegionsEqual(&pPriv->clip, clipBoxes)) { + REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); xf86XVFillKeyHelper(pScreen, pPriv->colorKey, clipBoxes); } @@ -1503,7 +1654,7 @@ I830BlockHandler(int i, I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); pScreen->BlockHandler = pI830->BlockHandler; @@ -1524,6 +1675,9 @@ I830BlockHandler(int i, pPriv->videoStatus = FREE_TIMER; pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + + if (pI830->entityPrivate) + pI830->entityPrivate->XvInUse = -1; } } else { /* FREE_TIMER */ if (pPriv->freeTime < currentTime.milliseconds) { @@ -1614,7 +1768,7 @@ I830StopSurface(XF86SurfacePtr surface) I830Ptr pI830 = I830PTR(pScrn); I830OverlayRegPtr overlay = - (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem.Start); + (I830OverlayRegPtr) (pI830->FbBase + pI830->OverlayMem->Start); overlay->OCMD &= ~OVERLAY_ENABLE; @@ -1622,6 +1776,9 @@ I830StopSurface(XF86SurfacePtr surface) OVERLAY_OFF; + if (pI830->entityPrivate) + pI830->entityPrivate->XvInUse = -1; + pPriv->isOn = FALSE; } @@ -1668,12 +1825,25 @@ I830DisplaySurface(XF86SurfacePtr surface, ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pI830Priv = GET_PORT_PRIVATE(pScrn); - INT32 x1, y1, x2, y2; INT32 loops = 0; BoxRec dstBox; DPRINTF(PFX, "I830DisplaySurface\n"); + + if (pI830->entityPrivate) { + if (pI830->entityPrivate->XvInUse != -1 && + pI830->entityPrivate->XvInUse != pI830->pipe) { + if (!noPanoramiXExtension) { + return Success; /* faked for trying to share it */ + } else { + return BadAlloc; + } + } + + pI830->entityPrivate->XvInUse = pI830->pipe; + } + x1 = src_x; x2 = src_x + src_w; y1 = src_y; @@ -1718,8 +1888,6 @@ I830DisplaySurface(XF86SurfacePtr surface, else pI830Priv->currentBuf = 0; - I830ResetVideo(pScrn); - I830DisplayVideo(pScrn, surface->id, surface->width, surface->height, surface->pitches[0], x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); @@ -1769,7 +1937,6 @@ void I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode) { I830PortPrivPtr pPriv; - int pixrate; if (!I830PTR(pScrn)->adaptor) { return; @@ -1782,31 +1949,72 @@ I830VideoSwitchModeBefore(ScrnInfoPtr pScrn, DisplayModePtr mode) return; } - pixrate = mode->HDisplay * mode->VDisplay * mode->VRefresh; - if (pixrate > pPriv->maxRate && pPriv->refreshOK) { - I830StopVideo(pScrn, pPriv, TRUE); - pPriv->refreshOK = FALSE; - } + /* We stop the video when mode switching, just so we don't lockup + * the engine. The overlayOK will determine whether we can re-enable + * with the current video on completion of the mode switch. + */ + I830StopVideo(pScrn, pPriv, TRUE); + + pPriv->oneLineMode = FALSE; } void I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) { + I830Ptr pI830 = I830PTR(pScrn); I830PortPrivPtr pPriv; - int pixrate; + int size, hsize, vsize, active; - if (!I830PTR(pScrn)->adaptor) { + if (!pI830->adaptor) { return; } pPriv = GET_PORT_PRIVATE(pScrn); if (!pPriv) return; - /* If this isn't initialised, assume 60Hz. */ - if (mode->VRefresh == 0) - mode->VRefresh = 60; + if (pI830->pipe == 0) { + if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling XVideo output because Pipe A is in double-wide mode.\n"); + pPriv->overlayOK = FALSE; + } else if (!pPriv->overlayOK) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Re-enabling XVideo output because Pipe A is now in single-wide mode.\n"); + pPriv->overlayOK = TRUE; + } + } - pixrate = (mode->HDisplay * mode->VDisplay * mode->VRefresh) / 1000000; - pPriv->refreshOK = (pixrate <= pPriv->maxRate); -} + if (pI830->pipe == 1) { + if (INREG(PIPEBCONF) & PIPEBCONF_DOUBLE_WIDE) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Disabling XVideo output because Pipe B is in double-wide mode.\n"); + pPriv->overlayOK = FALSE; + } else if (!pPriv->overlayOK) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Re-enabling XVideo output because Pipe B is now in single-wide mode.\n"); + pPriv->overlayOK = TRUE; + } + } + /* Check we are on pipe B and have an LFP connected */ + if ((pI830->pipe == 1) && (pI830->operatingDevices & (PIPE_LFP << 8))) { + size = INREG(PIPEBSRC); + hsize = (size >> 16) & 0x7FF; + vsize = size & 0x7FF; + active = INREG(VTOTAL_B) & 0x7FF; + + if (vsize < active && hsize > 1024) + I830SetOneLineModeRatio(pScrn); + + if (pPriv->scaleRatio & 0xFFFE0000) { + /* Possible bogus ratio, using in-accurate fallback */ + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Bogus panel fit register, Xvideo positioning may not be accurate.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Using fallback ratio - was 0x%x, now 0x%x\n", pPriv->scaleRatio, (int)(((float)active * 65536)/(float)vsize)); + + + pPriv->scaleRatio = (int)(((float)active * 65536) / (float)vsize); + } + } +} |