From 5ed7e6f8424236dd57d83f6ab1282693260969cb Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 22 Jun 2004 14:28:46 +0000 Subject: i915 support Dual Head support for i830, i855, i915. ARGB cursor support (including i810) for all chipsets. --- man/i810.man | 86 ++- src/common.h | 57 +- src/i810.h | 9 +- src/i810_accel.c | 85 +-- src/i810_cursor.c | 83 ++- src/i810_dri.c | 40 +- src/i810_driver.c | 82 ++- src/i810_memory.c | 45 +- src/i810_reg.h | 29 +- src/i830.h | 75 ++- src/i830_accel.c | 146 +++-- src/i830_common.h | 271 +++----- src/i830_cursor.c | 202 +++++- src/i830_dga.c | 9 +- src/i830_dri.c | 577 +++-------------- src/i830_dri.h | 80 +-- src/i830_driver.c | 1810 ++++++++++++++++++++++++++++++++++++++++++++--------- src/i830_memory.c | 392 ++++++++---- src/i830_video.c | 464 ++++++++++---- 19 files changed, 3013 insertions(+), 1529 deletions(-) diff --git a/man/i810.man b/man/i810.man index 1a70c742..c892bb3e 100644 --- a/man/i810.man +++ b/man/i810.man @@ -1,4 +1,4 @@ -.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810.man,v 1.4 2003/07/29 20:59:06 dawes Exp $ +.\" $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i810.man,v 1.5 2003/10/18 02:27:07 dawes Exp $ .\" shorthand for double quote that works everywhere. .ds q \N'34' .TH I810 __drivermansuffix__ __vendorversion__ @@ -14,7 +14,7 @@ i810 \- Intel 8xx integrated graphics chipsets .fi .SH DESCRIPTION .B i810 -is an XFree86 driver for Intel integrated graphics chipsets. +is an __xservername__ driver for Intel integrated graphics chipsets. The driver supports depths 8, 15, 16 and 24. All visual types are supported in depth 8. For the i810/i815 other depths support the TrueColor and DirectColor visuals. For the 830M and later, only the @@ -25,10 +25,10 @@ the 830M and later. .SH SUPPORTED HARDWARE .B i810 supports the i810, i810-DC100, i810e, i815, 830M, 845G, 852GM, 855GM, -and 865G chipsets. +865G and 915G chipsets. .SH CONFIGURATION DETAILS -Please refer to XF86Config(__filemansuffix__) for general configuration +Please refer to __xconfigfile__(__filemansuffix__) for general configuration details. This section only covers configuration details specific to this driver. .PP @@ -50,7 +50,8 @@ DRI is enabled. This amount may be changed with the entry in the config file .B "Device" section. It may be set to any reasonable value up to 64MB for older -chipsets or 128MB for newer chipets. It is advisable to check the XFree86 +chipsets or 128MB for newer chipets. It is advisable to check the +__xservername__ log file to check if any features have been disabled because of insufficient video memory. In particular, DRI support or tiling mode may be disabled with insufficient video memory. Either of these being disabled will @@ -72,7 +73,8 @@ Disable or enable acceleration. Default: acceleration is enabled. .TP .BI "Option \*qSWCursor\*q \*q" boolean \*q Disable or enable software cursor. Default: software cursor is disable -and a hardware cursor is used. +and a hardware cursor is used for configurations where the hardware cursor +is available. .TP .BI "Option \*qColorKey\*q \*q" integer \*q This sets the default pixel value for the YUV video overlay key. @@ -86,7 +88,7 @@ textures. Increasing it can improve 2D performance at the expense of Default: depends on the resolution, depth, and available video memory. The driver attempts to allocate at least enough to hold two DVD-sized YUV buffers by default. The default used for a specific configuration can be found -by examining the XFree86 log file. +by examining the __xservername__ log file. .TP .BI "Option \*qDRI\*q \*q" boolean \*q Disable or enable DRI support. @@ -115,6 +117,13 @@ The following driver .B Options are supported for the 830M and later chipsets: .TP +.BI "Option \*qVBERestore\*q \*q" boolean \*q +Enable or disable the use of VBE save/restore for saving and restoring +the initial text mode. This is disabled by default because it causes +lockups on some platforms. However, there are some cases where it must +enabled for the correct restoration of the initial video mode. If you are +having a problem with that, try enabling this option. Default: Disabled. +.TP .BI "Option \*qVideoKey\*q \*q" integer \*q This is the same as the .B \*qColorKey\*q @@ -124,12 +133,71 @@ other drivers. .BI "Option \*qXVideo\*q \*q" boolean \*q Disable or enable XVideo support. Default: XVideo is enabled for configurations where it is supported. - +.TP +.BI "Option \*qMonitorLayout\*q \*q" anystr \*q +Allow different monitor configurations. e.g. \*qCRT,LFP\*q will +configure a CRT on Pipe A and an LFP on Pipe B. Regardless of the +primary heads' pipe it is always configured as \*q,\*q. +Additionally you can add different configurations such as +\*qCRT+DFP,LFP\*q which would put a digital flat panel and a CRT +on pipe A, and a local flat panel on pipe B. +For single pipe configurations you can just specify the monitors types +on Pipe A, such as \*qCRT+DFP\*q which will enable the CRT and DFP +on Pipe A. +Valid monitors are CRT, LFP, DFP, TV, CRT2, LFP2, DFP2, TV2 and NONE. +NOTE: Some configurations of monitor types may fail, this depends on +the Video BIOS and system configuration. +Default: Not configured, and will use the current head's pipe and monitor. +.TP +.BI "Option \*qClone\*q \*q" boolean \*q +Enable Clone mode on pipe B. This will setup the second head as a complete +mirror of the monitor attached to pipe A. +NOTE: Video overlay functions will not work on the second head in this mode. +If you require this, then use the MonitorLayout above and do (as an example) +\*qCRT+DFP,NONE\*q to configure both a CRT and DFP on Pipe A to achieve +local mirroring and disable the use of this option. +Default: Clone mode on pipe B is disabled. +.TP +.BI "Option \*qCloneRefresh\*q \*q" integer \*q +When the Clone option is specified we can drive the second monitor at a +different refresh rate than the primary. +Default: 60Hz. +.TP +.BI "Option \*qCheckLid\*q \*q" boolean \*q +On mobile platforms it's desirable to monitor the lid status and switch +the outputs accordingly when the lid is opened or closed. By default this +option is on, but may incur a very minor performance penalty as we need +to poll a register on the card to check for this activity. It can be +turned off using this option. This only works with the 830M, 852GM and 855GM +systems. +Default: enabled. +.TP +.BI "Option \*qFlipPrimary\*q \*q" boolean \*q +When using a dual pipe system, it may be preferable to switch the primary +screen to the alternate pipe to display on the other monitor connection. +NOTE: Using this option may cause text mode to be restored incorrectly, +and thus should be used with caution. +Default: disabled. +.TP +.BI "Option \*qDisplayInfo\*q \*q" boolean \*q +It has been found that a certain BIOS call can lockup the Xserver because +of a problem in the Video BIOS. The log file will identify if you are +suffering from this problem and tell you to turn this option off. +Default: enabled +.TP +.BI "Option \*qDevicePresence\*q \*q" boolean \*q +Tell the driver to perform an active detect of the currently connected +monitors. This option is useful if the monitor was not connected when +the machine has booted, but unfortunately it doesn't always work and +is extremely dependent upon the Video BIOS. +Default: disabled .SH "SEE ALSO" -XFree86(1), XF86Config(__filemansuffix__), xf86config(1), Xserver(1), X(__miscmansuffix__) +__xservername__(__appmansuffix__), __xconfigfile__(__filemansuffix__), xorgconfig(__appmansuffix__), Xserver(__appmansuffix__), X(__miscmansuffix__) .SH AUTHORS Authors include: Keith Whitwell, and also Jonathan Bian, Matthew J Sottek, Jeff Hartmann, Mark Vojkovich, Alan Hourihane, H. J. Lu. 830M and 845G support reworked for XFree86 4.3 by David Dawes and Keith Whitwell. 852GM, 855GM, and 865G support added by David Dawes and Keith Whitwell. +915G support added by Alan Hourihane and Keith Whitwell. +Dual Head, Clone and lid status support added by Alan Hourihane. 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 */ diff --git a/src/i810.h b/src/i810.h index 332cd81a..58345abc 100644 --- a/src/i810.h +++ b/src/i810.h @@ -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 * + * Add ARGB HW cursor support: + * Alan Hourihane + * */ #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 * + * Add ARGB HW cursor support: + * Alan Hourihane + * */ /* @@ -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,15 +188,45 @@ 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; } } + /* + * 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 @@ -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 diff --git a/src/i830.h b/src/i830.h index 34b76bb3..d23d31db 100644 --- a/src/i830.h +++ b/src/i830.h @@ -78,6 +78,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * Paulo César Pereira de Andrade . */ +#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 - - Converted to common header format: - Jens Owen - */ +/* $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< * David Dawes * + * Updated for Dual Head capabilities: + * Alan Hourihane + * + * Add ARGB HW cursor support: + * Alan Hourihane + * */ #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 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 * Abraham van der Merwe * David Dawes + * Alan Hourihane */ /* @@ -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,73 +2183,234 @@ 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), + BOOLTOSTRING(((1<>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"); pI830->SWCursor = TRUE; } - /* - * Reduce the maximum videoram available for video modes by the ring buffer, - * minimum scratch space and HW cursor amounts. - */ - if (!pI830->SWCursor) - pScrn->videoRam -= (HWCURSOR_SIZE / 1024); - if (!pI830->XvDisabled) - pScrn->videoRam -= (OVERLAY_SIZE / 1024); - if (!pI830->noAccel) { - pScrn->videoRam -= (PRIMARY_RINGBUFFER_SIZE / 1024); - pScrn->videoRam -= (MIN_SCRATCH_BUFFER_SIZE / 1024); - } - - 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; + /* + * Reduce the maximum videoram available for video modes by the ring buffer, + * minimum scratch space and HW cursor amounts. + */ + 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) { + pScrn->videoRam -= (PRIMARY_RINGBUFFER_SIZE / 1024); + pScrn->videoRam -= (MIN_SCRATCH_BUFFER_SIZE / 1024); } + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Maximum frambuffer space: %d kByte\n", pScrn->videoRam); + + 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) { @@ -1786,18 +2482,6 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) "Will use BIOS call 0x5f05 to set refresh rates for CRTs.\n"); } - /* - * 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,37 +3381,147 @@ 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). */ /* * 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 + 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); - 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(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,13 +4212,15 @@ 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; @@ -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 * David Dawes * + * Updated for Dual Head capabilities: + * Alan Hourihane */ #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 @@ -322,15 +329,6 @@ typedef struct { CARD16 RESERVEDG[0x100 / 2 - N_HORIZ_UV_TAPS * N_PHASES]; } I830OverlayRegRec, *I830OverlayRegPtr; -typedef struct { - CARD32 GAMC5; - CARD32 GAMC4; - CARD32 GAMC3; - CARD32 GAMC2; - CARD32 GAMC1; - CARD32 GAMC0; -} I830OverlayStateRec, *I830OverlayStatePtr; - typedef struct { CARD32 YBuf0offset; CARD32 UBuf0offset; @@ -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); + } + } +} -- cgit v1.2.3