diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-06-20 12:52:10 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-06-25 13:18:01 +0100 |
commit | 797d173a9af12055ba2609293182b616dd673ef4 (patch) | |
tree | 0bc73734fa5e5bb1e57715d448bc7a6da88aba5a /src/legacy/i810 | |
parent | cd61531a78b9a2cbdd6019199c43258f83e6e2ce (diff) |
i810: Move into a legacy directory.
The driver is still built but is no longer under active development so
move it and supporting files to a new directory.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/legacy/i810')
-rw-r--r-- | src/legacy/i810/Makefile.am | 33 | ||||
-rw-r--r-- | src/legacy/i810/i810.h | 335 | ||||
-rw-r--r-- | src/legacy/i810/i810_accel.c | 617 | ||||
-rw-r--r-- | src/legacy/i810/i810_common.h | 323 | ||||
-rw-r--r-- | src/legacy/i810/i810_cursor.c | 266 | ||||
-rw-r--r-- | src/legacy/i810/i810_dga.c | 258 | ||||
-rw-r--r-- | src/legacy/i810/i810_dri.c | 1544 | ||||
-rw-r--r-- | src/legacy/i810/i810_dri.h | 131 | ||||
-rw-r--r-- | src/legacy/i810/i810_driver.c | 2121 | ||||
-rw-r--r-- | src/legacy/i810/i810_hwmc.c | 419 | ||||
-rw-r--r-- | src/legacy/i810/i810_io.c | 133 | ||||
-rw-r--r-- | src/legacy/i810/i810_memory.c | 428 | ||||
-rw-r--r-- | src/legacy/i810/i810_reg.h | 3194 | ||||
-rw-r--r-- | src/legacy/i810/i810_ring.h | 90 | ||||
-rw-r--r-- | src/legacy/i810/i810_video.c | 1423 | ||||
-rw-r--r-- | src/legacy/i810/i810_wmark.c | 313 | ||||
-rw-r--r-- | src/legacy/i810/xvmc/I810XvMC.c | 4509 | ||||
-rw-r--r-- | src/legacy/i810/xvmc/I810XvMC.h | 366 | ||||
-rw-r--r-- | src/legacy/i810/xvmc/Makefile.am | 11 |
19 files changed, 16514 insertions, 0 deletions
diff --git a/src/legacy/i810/Makefile.am b/src/legacy/i810/Makefile.am new file mode 100644 index 00000000..aab7f512 --- /dev/null +++ b/src/legacy/i810/Makefile.am @@ -0,0 +1,33 @@ +SUBDIRS = xvmc + +noinst_LTLIBRARIES = liblegacy-i810.la + +AM_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ @PCIACCESS_CFLAGS@ -I$(top_srcdir)/src + +liblegacy_i810_la_SOURCES = \ + i810_accel.c \ + i810_common.h \ + i810_cursor.c \ + i810_dga.c \ + i810_driver.c \ + i810.h \ + i810_io.c \ + i810_memory.c \ + i810_reg.h \ + i810_ring.h \ + i810_video.c \ + i810_wmark.c + +if DRI +liblegacy_i810_la_SOURCES +=\ + i810_dri.c \ + i810_dri.h \ + $(NULL) +endif + +if XVMC +liblegacy_i810_la_SOURCES += \ + i810_hwmc.h \ + i810_hwmc.c \ + $(NULL) +endif diff --git a/src/legacy/i810/i810.h b/src/legacy/i810/i810.h new file mode 100644 index 00000000..b39cfff3 --- /dev/null +++ b/src/legacy/i810/i810.h @@ -0,0 +1,335 @@ + +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright © 2002 David Dawes + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * David Dawes <dawes@xfree86.org> + * + */ + +#ifndef _I810_H_ +#define _I810_H_ + +#include <stdint.h> +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "i810_reg.h" +#include "xaa.h" +#include "xf86Cursor.h" +#include "xf86xv.h" +#include "vbe.h" +#include "vgaHW.h" + +#include "xorg-server.h" +#include <pciaccess.h> + +#ifdef XF86DRI +#include "xf86drm.h" +#include "sarea.h" +#define _XF86DRI_SERVER_ +#include "dri.h" +#include "GL/glxint.h" +#include "i810_dri.h" +#endif + +#include "i810_common.h" +#include "i810_ring.h" + +#include "intel_driver.h" + +/* HWMC Surfaces */ +#define I810_MAX_SURFACES 7 +#define I810_MAX_SUBPICTURES 2 +#define I810_TOTAL_SURFACES 9 + +/* Globals */ + +typedef struct _I810Rec *I810Ptr; + +typedef void (*I810WriteIndexedByteFunc)(I810Ptr pI810, IOADDRESS addr, + uint8_t index, uint8_t value); +typedef uint8_t(*I810ReadIndexedByteFunc)(I810Ptr pI810, IOADDRESS addr, + uint8_t index); +typedef void (*I810WriteByteFunc)(I810Ptr pI810, IOADDRESS addr, + uint8_t value); +typedef uint8_t(*I810ReadByteFunc)(I810Ptr pI810, IOADDRESS addr); + +extern void I810SetTiledMemory(ScrnInfoPtr pScrn, int nr, unsigned start, + unsigned pitch, unsigned size); + +typedef struct { + unsigned long Start; + unsigned long End; + unsigned long Size; +} I810MemRange; + +typedef struct { + int tail_mask; + I810MemRange mem; + unsigned char *virtual_start; + int head; + int tail; + int space; +} I810RingBuffer; + +typedef struct { + unsigned char DisplayControl; + unsigned char PixelPipeCfg0; + unsigned char PixelPipeCfg1; + unsigned char PixelPipeCfg2; + unsigned short VideoClk2_M; + unsigned short VideoClk2_N; + unsigned char VideoClk2_DivisorSel; + unsigned char AddressMapping; + unsigned char IOControl; + unsigned char BitBLTControl; + unsigned char ExtVertTotal; + unsigned char ExtVertDispEnd; + unsigned char ExtVertSyncStart; + unsigned char ExtVertBlankStart; + unsigned char ExtHorizTotal; + unsigned char ExtHorizBlank; + unsigned char ExtOffset; + unsigned char InterlaceControl; + unsigned int LMI_FIFO_Watermark; + + unsigned int LprbTail; + unsigned int LprbHead; + unsigned int LprbStart; + unsigned int LprbLen; + + unsigned int Fence[8]; + + unsigned short OverlayActiveStart; + unsigned short OverlayActiveEnd; + +} I810RegRec, *I810RegPtr; + +typedef struct _I810Rec { + unsigned char *MMIOBase; + unsigned char *FbBase; + long FbMapSize; + long DepthOffset; + long BackOffset; + int cpp; + int MaxClock; + + unsigned int bufferOffset; /* for I810SelectBuffer */ + Bool DoneFrontAlloc; + BoxRec FbMemBox; + I810MemRange FrontBuffer; + I810MemRange BackBuffer; + I810MemRange DepthBuffer; + I810MemRange TexMem; + I810MemRange Scratch; + I810MemRange BufferMem; + I810MemRange ContextMem; + I810MemRange MC; + + 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; + unsigned int surfaceAllocation[I810_TOTAL_SURFACES]; + int numSurfaces; + + DGAModePtr DGAModes; + int numDGAModes; + Bool DGAactive; + int DGAViewportStatus; + + int Chipset; + unsigned long LinearAddr; + unsigned long MMIOAddr; + IOADDRESS ioBase; + EntityInfoPtr pEnt; + struct pci_device *PciInfo; + + I810RingBuffer *LpRing; + unsigned int BR[20]; + + int LmFreqSel; + + int VramKey; + unsigned long VramOffset; + int DcacheKey; + unsigned long DcacheOffset; + int HwcursKey; + unsigned long HwcursOffset; + int ARGBHwcursKey; + unsigned long ARGBHwcursOffset; + + int GttBound; + + I810MemRange DcacheMem; + I810MemRange SysMem; + + I810MemRange SavedDcacheMem; + I810MemRange SavedSysMem; + + unsigned char **ScanlineColorExpandBuffers; + int NumScanlineColorExpandBuffers; + int nextColorExpandBuf; + + I810RegRec SavedReg; + I810RegRec ModeReg; + + XAAInfoRecPtr AccelInfoRec; + xf86CursorInfoPtr CursorInfoRec; + CloseScreenProcPtr CloseScreen; + ScreenBlockHandlerProcPtr BlockHandler; + + I810WriteIndexedByteFunc writeControl; + I810ReadIndexedByteFunc readControl; + I810WriteByteFunc writeStandard; + I810ReadByteFunc readStandard; + + Bool directRenderingDisabled; /* DRI disabled in PreInit */ + Bool directRenderingEnabled; /* false if XF86DRI not defined. */ + +#ifdef XF86DRI + int LockHeld; + DRIInfoPtr pDRIInfo; + int drmSubFD; + int numVisualConfigs; + __GLXvisualConfig *pVisualConfigs; + I810ConfigPrivPtr pVisualConfigsPriv; + unsigned long dcacheHandle; + unsigned long backHandle; + unsigned long zHandle; + unsigned long cursorHandle; + unsigned long cursorARGBHandle; + unsigned long xvmcHandle; + unsigned long sysmemHandle; + Bool agpAcquired; + drm_handle_t buffer_map; + drm_handle_t ring_map; + drm_handle_t overlay_map; + drm_handle_t mc_map; + drm_handle_t xvmcContext; +#endif + Bool agpAcquired2d; + + XF86VideoAdaptorPtr adaptor; + OptionInfoPtr Options; + + int configured_device; + + Bool showCache; + Bool noAccel; + Bool allowPageFlip; + Bool have3DWindows; + int drmMinor; +} I810Rec; + +#define I810PTR(p) ((I810Ptr)((p)->driverPrivate)) + +#define I810_SELECT_FRONT 0 +#define I810_SELECT_BACK 1 +#define I810_SELECT_DEPTH 2 + +#ifdef XF86DRI +extern Bool I810DRIScreenInit(ScreenPtr pScreen); +extern void I810DRICloseScreen(ScreenPtr pScreen); +extern Bool I810DRIFinishScreenInit(ScreenPtr pScreen); +extern Bool I810DRILeave(ScrnInfoPtr pScrn); +extern Bool I810DRIEnter(ScrnInfoPtr pScrn); +#endif +extern Bool I810InitDma(ScrnInfoPtr pScrn); +extern Bool I810CleanupDma(ScrnInfoPtr pScrn); + +#define I810PTR(p) ((I810Ptr)((p)->driverPrivate)) +#define I810REGPTR(p) (&(I810PTR(p)->ModeReg)) + +extern Bool I810CursorInit(ScreenPtr pScreen); +extern Bool I810AccelInit(ScreenPtr pScreen); +extern void I810SetPIOAccess(I810Ptr pI810); +extern void I810SetMMIOAccess(I810Ptr pI810); +extern unsigned int I810CalcWatermark(ScrnInfoPtr pScrn, double freq, + Bool dcache); +extern void I810PrintErrorState(ScrnInfoPtr pScrn); +extern int I810WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis); +extern void I810Sync(ScrnInfoPtr pScrn); +extern unsigned long I810LocalToPhysical(ScrnInfoPtr pScrn, + unsigned long local); +extern int I810AllocLow(I810MemRange * result, I810MemRange * pool, + int size); +extern int I810AllocHigh(I810MemRange * result, I810MemRange * pool, + int size); +extern Bool I810AllocateFront(ScrnInfoPtr pScrn); + +extern int I810AllocateGARTMemory(ScrnInfoPtr pScrn); +extern void I810FreeGARTMemory(ScrnInfoPtr pScrn); + +extern Bool I810BindGARTMemory(ScrnInfoPtr pScrn); +extern Bool I810UnbindGARTMemory(ScrnInfoPtr pScrn); + +extern int I810CheckAvailableMemory(ScrnInfoPtr pScrn); + +extern Bool I810SwitchMode(int scrnIndex, DisplayModePtr mode, int flags); +extern void I810AdjustFrame(int scrnIndex, int x, int y, int flags); + +extern void I810SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, + int ydir, int rop, + unsigned int planemask, + int trans_color); +extern void I810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int srcX, + int srcY, int dstX, int dstY, + int w, int h); +extern void I810SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask); +extern void I810SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, + int w, int h); + +extern void I810SelectBuffer(ScrnInfoPtr pScrn, int buffer); + +extern void I810RefreshRing(ScrnInfoPtr pScrn); +extern void I810EmitFlush(ScrnInfoPtr pScrn); +extern void I810EmitInvarientState(ScrnInfoPtr pScrn); + +extern Bool I810DGAInit(ScreenPtr pScreen); + +extern void I810InitVideo(ScreenPtr pScreen); +extern void I810InitMC(ScreenPtr pScreen); + +extern const OptionInfoRec *I810AvailableOptions(int chipid, int busid); + +#endif /* _I810_H_ */ diff --git a/src/legacy/i810/i810_accel.c b/src/legacy/i810/i810_accel.c new file mode 100644 index 00000000..ae4a6544 --- /dev/null +++ b/src/legacy/i810/i810_accel.c @@ -0,0 +1,617 @@ + +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "xf86.h" +#include "xaarop.h" +#include "i810.h" + +static void I810SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, + int pattx, int patty, + int fg, int bg, int rop, + unsigned int planemask); +static void I810SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, + int pattx, int patty, + int x, int y, int w, int h); + +static void I810SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, + int rop, + unsigned int mask); + +static void I810SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr + pScrn, int x, + int y, int w, + int h, + int skipleft); + +static void I810SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno); + +/* The following function sets up the supported acceleration. Call it + * from the FbInit() function in the SVGA driver, or before ScreenInit + * in a monolithic server. + */ +Bool +I810AccelInit(ScreenPtr pScreen) +{ + XAAInfoRecPtr infoPtr; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810AccelInit\n"); + + pI810->AccelInfoRec = infoPtr = XAACreateInfoRec(); + if (!infoPtr) + return FALSE; + + pI810->bufferOffset = 0; + infoPtr->Flags = LINEAR_FRAMEBUFFER | OFFSCREEN_PIXMAPS; + infoPtr->Flags |= PIXMAP_CACHE; + + /* Sync + */ + infoPtr->Sync = I810Sync; + + /* Solid filled rectangles + */ + { + infoPtr->SolidFillFlags = NO_PLANEMASK; + infoPtr->SetupForSolidFill = I810SetupForSolidFill; + infoPtr->SubsequentSolidFillRect = I810SubsequentSolidFillRect; + } + + /* Screen to screen copy + * - the transparency op hangs the blit engine, disable for now. + */ + { + infoPtr->ScreenToScreenCopyFlags = (0 + | NO_PLANEMASK + | NO_TRANSPARENCY | 0); + + infoPtr->SetupForScreenToScreenCopy = I810SetupForScreenToScreenCopy; + infoPtr->SubsequentScreenToScreenCopy = + I810SubsequentScreenToScreenCopy; + } + + /* 8x8 pattern fills + */ + { + infoPtr->SetupForMono8x8PatternFill = I810SetupForMono8x8PatternFill; + infoPtr->SubsequentMono8x8PatternFillRect = + I810SubsequentMono8x8PatternFillRect; + + infoPtr->Mono8x8PatternFillFlags = (HARDWARE_PATTERN_PROGRAMMED_BITS | + HARDWARE_PATTERN_SCREEN_ORIGIN | + BIT_ORDER_IN_BYTE_MSBFIRST | + NO_PLANEMASK | 0); + } + + /* 8x8 color fills - not considered useful for XAA. + */ + + /* Scanline color expansion - Use the same scheme as the 3.3 driver. + * + */ + if (pI810->Scratch.Size != 0) { + int i; + int width = ((pScrn->displayWidth + 31) & ~31) / 8; + int nr_buffers = pI810->Scratch.Size / width; + unsigned char *ptr = pI810->FbBase + pI810->Scratch.Start; + + pI810->NumScanlineColorExpandBuffers = nr_buffers; + pI810->ScanlineColorExpandBuffers = (unsigned char **) + xnfcalloc(nr_buffers, sizeof(unsigned char *)); + + for (i = 0; i < nr_buffers; i++, ptr += width) + pI810->ScanlineColorExpandBuffers[i] = ptr; + + infoPtr->ScanlineCPUToScreenColorExpandFillFlags = (NO_PLANEMASK | + ROP_NEEDS_SOURCE | + BIT_ORDER_IN_BYTE_MSBFIRST + | 0); + + infoPtr->ScanlineColorExpandBuffers = (unsigned char **) + xnfcalloc(1, sizeof(unsigned char *)); + infoPtr->NumScanlineColorExpandBuffers = 1; + + infoPtr->ScanlineColorExpandBuffers[0] = + pI810->ScanlineColorExpandBuffers[0]; + pI810->nextColorExpandBuf = 0; + + infoPtr->SetupForScanlineCPUToScreenColorExpandFill = + I810SetupForScanlineCPUToScreenColorExpandFill; + + infoPtr->SubsequentScanlineCPUToScreenColorExpandFill = + I810SubsequentScanlineCPUToScreenColorExpandFill; + + infoPtr->SubsequentColorExpandScanline = + I810SubsequentColorExpandScanline; + } + + /* Possible todo: Image writes w/ non-GXCOPY rop. + */ + + I810SelectBuffer(pScrn, I810_SELECT_FRONT); + + return XAAInit(pScreen, infoPtr); +} + +int +I810WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis) +{ + I810Ptr pI810 = I810PTR(pScrn); + I810RingBuffer *ring = pI810->LpRing; + int iters = 0; + int start = 0; + int now = 0; + int last_head = 0; + int first = 0; + + /* If your system hasn't moved the head pointer in 2 seconds, I'm going to + * call it crashed. + */ + if (timeout_millis == 0) + timeout_millis = 2000; + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) { + ErrorF("I810WaitLpRing %d\n", n); + first = GetTimeInMillis(); + } + + while (ring->space < n) { + ring->head = INREG(LP_RING + RING_HEAD) & HEAD_ADDR; + ring->space = ring->head - (ring->tail + 8); + + if (ring->space < 0) + ring->space += ring->mem.Size; + + iters++; + now = GetTimeInMillis(); + if (start == 0 || now < start || ring->head != last_head) { + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + if (now > start) + ErrorF("space: %d wanted %d\n", ring->space, n); + start = now; + last_head = ring->head; + } else if (now - start > timeout_millis) { + ErrorF("Error in I810WaitLpRing(), now is %d, start is %d\n", now, + start); + I810PrintErrorState(pScrn); + ErrorF("space: %d wanted %d\n", ring->space, n); +#ifdef XF86DRI + if (pI810->directRenderingEnabled) { + DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); + DRICloseScreen(screenInfo.screens[pScrn->scrnIndex]); + } +#endif + pI810->AccelInfoRec = NULL; /* Stops recursive behavior */ + FatalError("lockup\n"); + } + + DELAY(10000); + } + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) { + now = GetTimeInMillis(); + if (now - first) { + ErrorF("Elapsed %d ms\n", now - first); + ErrorF("space: %d wanted %d\n", ring->space, n); + } + } + + return iters; +} + +void +I810Sync(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC)) + ErrorF("I810Sync\n"); + +#ifdef XF86DRI + /* VT switching tries to do this. + */ + if (!pI810->LockHeld && pI810->directRenderingEnabled) { + return; + } +#endif + + /* 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. + */ + { + BEGIN_LP_RING(2); + OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); + OUT_RING(0); /* pad to quadword */ + ADVANCE_LP_RING(); + } + + I810WaitLpRing(pScrn, pI810->LpRing->mem.Size - 8, 0); + + pI810->LpRing->space = pI810->LpRing->mem.Size - 8; + pI810->nextColorExpandBuf = 0; +} + +void +I810SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, + unsigned int planemask) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810SetupForFillRectSolid color: %x rop: %x mask: %x\n", + color, rop, planemask); + + /* Color blit, p166 */ + pI810->BR[13] = (BR13_SOLID_PATTERN | + (XAAGetPatternROP(rop) << 16) | + (pScrn->displayWidth * pI810->cpp)); + pI810->BR[16] = color; +} + +void +I810SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810SubsequentFillRectSolid %d,%d %dx%d\n", x, y, w, h); + + { + BEGIN_LP_RING(6); + + OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_COLOR_BLT | 0x3); + OUT_RING(pI810->BR[13]); + OUT_RING((h << 16) | (w * pI810->cpp)); + OUT_RING(pI810->bufferOffset + + (y * pScrn->displayWidth + x) * pI810->cpp); + + OUT_RING(pI810->BR[16]); + OUT_RING(0); /* pad to quadword */ + + ADVANCE_LP_RING(); + } +} + +void +I810SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, int rop, + unsigned int planemask, int transparency_color) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810SetupForScreenToScreenCopy %d %d %x %x %d\n", + xdir, ydir, rop, planemask, transparency_color); + + pI810->BR[13] = (pScrn->displayWidth * pI810->cpp); + + if (ydir == -1) + pI810->BR[13] = (-pI810->BR[13]) & 0xFFFF; + if (xdir == -1) + pI810->BR[13] |= BR13_RIGHT_TO_LEFT; + + pI810->BR[13] |= XAAGetCopyROP(rop) << 16; + + pI810->BR[18] = 0; +} + +void +I810SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, + int x2, int y2, int w, int h) +{ + I810Ptr pI810 = I810PTR(pScrn); + int src, dst; + int w_back = w; + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF( "I810SubsequentScreenToScreenCopy %d,%d - %d,%d %dx%d\n", + x1,y1,x2,y2,w,h); + /* + * This works around a bug in the i810 drawing engine. + * 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 + I810_MWIDTH) + && (w > I810_MWIDTH)) + w = I810_MWIDTH; + do { + + if (pI810->BR[13] & BR13_PITCH_SIGN_BIT) { + src = (y1 + h - 1) * pScrn->displayWidth * pI810->cpp; + dst = (y2 + h - 1) * pScrn->displayWidth * pI810->cpp; + } else { + src = y1 * pScrn->displayWidth * pI810->cpp; + dst = y2 * pScrn->displayWidth * pI810->cpp; + } + + if (pI810->BR[13] & BR13_RIGHT_TO_LEFT) { + src += (x1 + w - 1) * pI810->cpp + pI810->cpp - 1; + dst += (x2 + w - 1) * pI810->cpp + pI810->cpp - 1; + } else { + src += x1 * pI810->cpp; + dst += x2 * pI810->cpp; + } + + + /* SRC_COPY_BLT, p169 */ + { + BEGIN_LP_RING(6); + OUT_RING( BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4 ); + OUT_RING( pI810->BR[13]); + + OUT_RING( (h << 16) | (w * pI810->cpp)); + OUT_RING( pI810->bufferOffset + dst); + + OUT_RING( pI810->BR[13] & 0xFFFF); + OUT_RING( pI810->bufferOffset + src); + ADVANCE_LP_RING(); + } + w_back -= w; + if (w_back <= 0) + break; + x2 += w; + x1 += w; + if (w_back > I810_MWIDTH) + w = I810_MWIDTH; + else + w = w_back; + } while (1); +} + +static void +I810SetupForMono8x8PatternFill(ScrnInfoPtr pScrn, int pattx, int patty, + int fg, int bg, int rop, + unsigned int planemask) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810SetupFor8x8PatternColorExpand\n"); + + /* FULL_MONO_PAT_BLT, p176 */ + pI810->BR[0] = (BR00_BITBLT_CLIENT | BR00_OP_MONO_PAT_BLT | 0x9); + pI810->BR[18] = bg; + pI810->BR[19] = fg; + pI810->BR[13] = (pScrn->displayWidth * pI810->cpp); + pI810->BR[13] |= XAAGetPatternROP(rop) << 16; + if (bg == -1) + pI810->BR[13] |= BR13_MONO_PATN_TRANS; +} + +static void +I810SubsequentMono8x8PatternFillRect(ScrnInfoPtr pScrn, int pattx, int patty, + int x, int y, int w, int h) +{ + I810Ptr pI810 = I810PTR(pScrn); + int addr = + pI810->bufferOffset + (y * pScrn->displayWidth + x) * pI810->cpp; + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810Subsequent8x8PatternColorExpand\n"); + + { + BEGIN_LP_RING(12); + OUT_RING(pI810->BR[0] | ((y << 5) & BR00_PAT_VERT_ALIGN)); + OUT_RING(pI810->BR[13]); + OUT_RING((h << 16) | (w * pI810->cpp)); + OUT_RING(addr); + OUT_RING(pI810->BR[13] & 0xFFFF); /* src pitch */ + OUT_RING(addr); /* src addr */ + OUT_RING(0); /* transparency color */ + OUT_RING(pI810->BR[18]); /* bg */ + OUT_RING(pI810->BR[19]); /* fg */ + OUT_RING(pattx); /* pattern data */ + OUT_RING(patty); + OUT_RING(0); + ADVANCE_LP_RING(); + } +} + +static void +I810GetNextScanlineColorExpandBuffer(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + XAAInfoRecPtr infoPtr = pI810->AccelInfoRec; + + if (pI810->nextColorExpandBuf == pI810->NumScanlineColorExpandBuffers) + I810Sync(pScrn); + + infoPtr->ScanlineColorExpandBuffers[0] = + pI810->ScanlineColorExpandBuffers[pI810->nextColorExpandBuf]; + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("using color expand buffer %d\n", pI810->nextColorExpandBuf); + + pI810->nextColorExpandBuf++; +} + +static void +I810SetupForScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int fg, int bg, int rop, + unsigned int planemask) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810SetupForScanlineScreenToScreenColorExpand %d %d %x %x\n", + fg, bg, rop, planemask); + + pI810->BR[13] = (pScrn->displayWidth * pI810->cpp); + pI810->BR[13] |= XAAGetCopyROP(rop) << 16; + pI810->BR[13] |= (1 << 27); + if (bg == -1) + pI810->BR[13] |= BR13_MONO_TRANSPCY; + + pI810->BR[18] = bg; + pI810->BR[19] = fg; + + I810GetNextScanlineColorExpandBuffer(pScrn); +} + +static void +I810SubsequentScanlineCPUToScreenColorExpandFill(ScrnInfoPtr pScrn, + int x, int y, + int w, int h, int skipleft) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810SubsequentScanlineCPUToScreenColorExpandFill " + "%d,%d %dx%x %d\n", x, y, w, h, skipleft); + + pI810->BR[0] = BR00_BITBLT_CLIENT | BR00_OP_MONO_SRC_COPY_BLT | 0x06; + pI810->BR[9] = (pI810->bufferOffset + + (y * pScrn->displayWidth + x) * pI810->cpp); + pI810->BR[14] = ((1 << 16) | (w * pI810->cpp)); + pI810->BR[11] = ((w + 31) / 32) - 1; +} + +static void +I810SubsequentColorExpandScanline(ScrnInfoPtr pScrn, int bufno) +{ + I810Ptr pI810 = I810PTR(pScrn); + + pI810->BR[12] = (pI810->AccelInfoRec->ScanlineColorExpandBuffers[0] - + pI810->FbBase); + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810SubsequentColorExpandScanline %d (addr %x)\n", + bufno, pI810->BR[12]); + + { + BEGIN_LP_RING(8); + OUT_RING(pI810->BR[0]); + OUT_RING(pI810->BR[13]); + OUT_RING(pI810->BR[14]); + OUT_RING(pI810->BR[9]); + OUT_RING(pI810->BR[11]); + OUT_RING(pI810->BR[12]); /* srcaddr */ + OUT_RING(pI810->BR[18]); + OUT_RING(pI810->BR[19]); + ADVANCE_LP_RING(); + } + + /* Advance to next scanline. + */ + pI810->BR[9] += pScrn->displayWidth * pI810->cpp; + I810GetNextScanlineColorExpandBuffer(pScrn); +} + +void +I810EmitFlush(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + BEGIN_LP_RING(2); + OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); + OUT_RING(0); + ADVANCE_LP_RING(); +} + +void +I810SelectBuffer(ScrnInfoPtr pScrn, int buffer) +{ + I810Ptr pI810 = I810PTR(pScrn); + + switch (buffer) { + case I810_SELECT_BACK: + pI810->bufferOffset = pI810->BackBuffer.Start; + break; + case I810_SELECT_DEPTH: + pI810->bufferOffset = pI810->DepthBuffer.Start; + break; + default: + case I810_SELECT_FRONT: + pI810->bufferOffset = pI810->FrontBuffer.Start; + break; + } + + if (I810_DEBUG & DEBUG_VERBOSE_ACCEL) + ErrorF("I810SelectBuffer %d --> offset %x\n", + buffer, pI810->bufferOffset); +} + +void +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; + + if (pI810->AccelInfoRec) + pI810->AccelInfoRec->NeedToSync = TRUE; +} + +/* Emit on gaining VT? + */ +void +I810EmitInvarientState(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + BEGIN_LP_RING(10); + + OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); + OUT_RING(GFX_CMD_CONTEXT_SEL | CS_UPDATE_USE | CS_USE_CTX0); + OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE); + OUT_RING(0); + + OUT_RING(GFX_OP_COLOR_CHROMA_KEY); + OUT_RING(CC1_UPDATE_KILL_WRITE | + CC1_DISABLE_KILL_WRITE | + CC1_UPDATE_COLOR_IDX | + CC1_UPDATE_CHROMA_LOW | CC1_UPDATE_CHROMA_HI | 0); + OUT_RING(0); + OUT_RING(0); + +/* OUT_RING( CMD_OP_Z_BUFFER_INFO ); */ +/* OUT_RING( pI810->DepthBuffer.Start | pI810->auxPitchBits); */ + + ADVANCE_LP_RING(); +} + diff --git a/src/legacy/i810/i810_common.h b/src/legacy/i810/i810_common.h new file mode 100644 index 00000000..ea28f4ab --- /dev/null +++ b/src/legacy/i810/i810_common.h @@ -0,0 +1,323 @@ +/* i810_common.h -- common header definitions for I810 2D/3D/DRM suite + * + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Converted to common header format: + * Jens Owen <jens@tungstengraphics.com> + * + * + */ + +/* WARNING: If you change any of these defines, make sure to change + * the kernel include file as well (i810_drm.h) + */ + +#ifndef _I810_COMMON_H_ +#define _I810_COMMON_H_ + +/* Provide substitutes for gcc's __FUNCTION__ on other compilers */ +#if !defined(__GNUC__) && !defined(__FUNCTION__) +# if defined(__STDC__) && (__STDC_VERSION__>=199901L) /* C99 */ +# define __FUNCTION__ __func__ +# else +# define __FUNCTION__ "" +# endif +#endif + +#define PFX __FILE__,__LINE__,__FUNCTION__ +#define FUNCTION_NAME __FUNCTION__ + +#define KB(x) ((x) * 1024) +#define MB(x) ((x) * KB(1024)) + +/* Using usleep() makes things noticably slow. */ +#if 0 +#define DELAY(x) usleep(x) +#else +#define DELAY(x) do {;} while (0) +#endif + +#define PrintErrorState I810PrintErrorState +#define WaitRingFunc I810WaitLpRing +#define RecPtr pI810 + +static inline void memset_volatile(volatile void *b, int c, size_t len) +{ + int i; + + for (i = 0; i < len; i++) + ((volatile char *)b)[i] = c; +} + +static inline void memcpy_volatile(volatile void *dst, const void *src, + size_t len) +{ + int i; + + for (i = 0; i < len; i++) + ((volatile char *)dst)[i] = ((volatile char *)src)[i]; +} + +/* Memory mapped register access macros */ +#define INREG8(addr) *(volatile uint8_t *)(RecPtr->MMIOBase + (addr)) +#define INREG16(addr) *(volatile uint16_t *)(RecPtr->MMIOBase + (addr)) +#define INREG(addr) *(volatile uint32_t *)(RecPtr->MMIOBase + (addr)) +#define INGTT(addr) *(volatile uint32_t *)(RecPtr->GTTBase + (addr)) +#define POSTING_READ(addr) (void)INREG(addr) + +#define OUTREG8(addr, val) do { \ + *(volatile uint8_t *)(RecPtr->MMIOBase + (addr)) = (val); \ + if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \ + 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 uint16_t *)(RecPtr->MMIOBase + (addr)) = (val); \ + if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \ + 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 uint32_t *)(RecPtr->MMIOBase + (addr)) = (val); \ + if (I810_DEBUG&DEBUG_VERBOSE_OUTREG) { \ + ErrorF("OUTREG(0x%lx, 0x%lx) in %s\n", (unsigned long)(addr), \ + (unsigned long)(val), FUNCTION_NAME); \ + } \ +} while (0) + +/* To remove all debugging, make sure I810_DEBUG is defined as a + * preprocessor symbol, and equal to zero. + */ +#if 1 +#define I810_DEBUG 0 +#endif +#ifndef I810_DEBUG +#warning "Debugging enabled - expect reduced performance" +extern int I810_DEBUG; +#endif + +#define DEBUG_VERBOSE_ACCEL 0x1 +#define DEBUG_VERBOSE_SYNC 0x2 +#define DEBUG_VERBOSE_VGA 0x4 +#define DEBUG_VERBOSE_RING 0x8 +#define DEBUG_VERBOSE_OUTREG 0x10 +#define DEBUG_VERBOSE_MEMORY 0x20 +#define DEBUG_VERBOSE_CURSOR 0x40 +#define DEBUG_ALWAYS_SYNC 0x80 +#define DEBUG_VERBOSE_DRI 0x100 +#define DEBUG_VERBOSE_BIOS 0x200 + +/* Size of the mmio region. + */ +#define I810_REG_SIZE 0x80000 + +#define GTT_PAGE_SIZE KB(4) +#define ROUND_TO(x, y) (((x) + (y) - 1) / (y) * (y)) +#define ROUND_DOWN_TO(x, y) ((x) / (y) * (y)) +#define ROUND_TO_PAGE(x) ROUND_TO((x), GTT_PAGE_SIZE) +#define ROUND_TO_MB(x) ROUND_TO((x), MB(1)) +#define PRIMARY_RINGBUFFER_SIZE KB(128) +#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 + +/* Use a 64x64 HW cursor */ +#define I810_CURSOR_X 64 +#define I810_CURSOR_Y I810_CURSOR_X + +#define PIPE_NAME(n) ('A' + (n)) + +extern struct pci_device * +intel_host_bridge (void); + +/** + * Hints to CreatePixmap to tell the driver how the pixmap is going to be + * used. + * + * Compare to CREATE_PIXMAP_USAGE_* in the server. + */ +enum { + INTEL_CREATE_PIXMAP_TILING_X = 0x10000000, + INTEL_CREATE_PIXMAP_TILING_Y, + INTEL_CREATE_PIXMAP_TILING_NONE, +}; + +#ifndef _I810_DEFINES_ +#define _I810_DEFINES_ +#define I810_USE_BATCH 1 + +#define I810_DMA_BUF_ORDER 12 +#define I810_DMA_BUF_SZ (1<<I810_DMA_BUF_ORDER) +#define I810_DMA_BUF_NR 256 + +#define I810_NR_SAREA_CLIPRECTS 8 + +/* Each region is a minimum of 64k, and there are at most 64 of them. + */ +#define I810_NR_TEX_REGIONS 64 +#define I810_LOG_MIN_TEX_REGION_SIZE 16 + +/* Destbuffer state + * - backbuffer linear offset and pitch -- invarient in the current dri + * - zbuffer linear offset and pitch -- also invarient + * - drawing origin in back and depth buffers. + * + * Keep the depth/back buffer state here to acommodate private buffers + * in the future. + */ +#define I810_DESTREG_DI0 0 /* CMD_OP_DESTBUFFER_INFO (2 dwords) */ +#define I810_DESTREG_DI1 1 +#define I810_DESTREG_DV0 2 /* GFX_OP_DESTBUFFER_VARS (2 dwords) */ +#define I810_DESTREG_DV1 3 +#define I810_DESTREG_DR0 4 /* GFX_OP_DRAWRECT_INFO (4 dwords) */ +#define I810_DESTREG_DR1 5 +#define I810_DESTREG_DR2 6 +#define I810_DESTREG_DR3 7 +#define I810_DESTREG_DR4 8 +#define I810_DEST_SETUP_SIZE 10 + +/* Context state + */ +#define I810_CTXREG_CF0 0 /* GFX_OP_COLOR_FACTOR */ +#define I810_CTXREG_CF1 1 +#define I810_CTXREG_ST0 2 /* GFX_OP_STIPPLE */ +#define I810_CTXREG_ST1 3 +#define I810_CTXREG_VF 4 /* GFX_OP_VERTEX_FMT */ +#define I810_CTXREG_MT 5 /* GFX_OP_MAP_TEXELS */ +#define I810_CTXREG_MC0 6 /* GFX_OP_MAP_COLOR_STAGES - stage 0 */ +#define I810_CTXREG_MC1 7 /* GFX_OP_MAP_COLOR_STAGES - stage 1 */ +#define I810_CTXREG_MC2 8 /* GFX_OP_MAP_COLOR_STAGES - stage 2 */ +#define I810_CTXREG_MA0 9 /* GFX_OP_MAP_ALPHA_STAGES - stage 0 */ +#define I810_CTXREG_MA1 10 /* GFX_OP_MAP_ALPHA_STAGES - stage 1 */ +#define I810_CTXREG_MA2 11 /* GFX_OP_MAP_ALPHA_STAGES - stage 2 */ +#define I810_CTXREG_SDM 12 /* GFX_OP_SRC_DEST_MONO */ +#define I810_CTXREG_FOG 13 /* GFX_OP_FOG_COLOR */ +#define I810_CTXREG_B1 14 /* GFX_OP_BOOL_1 */ +#define I810_CTXREG_B2 15 /* GFX_OP_BOOL_2 */ +#define I810_CTXREG_LCS 16 /* GFX_OP_LINEWIDTH_CULL_SHADE_MODE */ +#define I810_CTXREG_PV 17 /* GFX_OP_PV_RULE -- Invarient! */ +#define I810_CTXREG_ZA 18 /* GFX_OP_ZBIAS_ALPHAFUNC */ +#define I810_CTXREG_AA 19 /* GFX_OP_ANTIALIAS */ +#define I810_CTX_SETUP_SIZE 20 + +/* Texture state (per tex unit) + */ +#define I810_TEXREG_MI0 0 /* GFX_OP_MAP_INFO (4 dwords) */ +#define I810_TEXREG_MI1 1 +#define I810_TEXREG_MI2 2 +#define I810_TEXREG_MI3 3 +#define I810_TEXREG_MF 4 /* GFX_OP_MAP_FILTER */ +#define I810_TEXREG_MLC 5 /* GFX_OP_MAP_LOD_CTL */ +#define I810_TEXREG_MLL 6 /* GFX_OP_MAP_LOD_LIMITS */ +#define I810_TEXREG_MCS 7 /* GFX_OP_MAP_COORD_SETS ??? */ +#define I810_TEX_SETUP_SIZE 8 + +/* Driver specific DRM command indices + * NOTE: these are not OS specific, but they are driver specific + */ +#define DRM_I810_INIT 0x00 +#define DRM_I810_VERTEX 0x01 +#define DRM_I810_CLEAR 0x02 +#define DRM_I810_FLUSH 0x03 +#define DRM_I810_GETAGE 0x04 +#define DRM_I810_GETBUF 0x05 +#define DRM_I810_SWAP 0x06 +#define DRM_I810_COPY 0x07 +#define DRM_I810_DOCOPY 0x08 +#define DRM_I810_OV0INFO 0x09 +#define DRM_I810_FSTATUS 0x0a +#define DRM_I810_OV0FLIP 0x0b +#define DRM_I810_MC 0x0c +#define DRM_I810_RSTATUS 0x0d +#define DRM_I810_FLIP 0x0e + +#endif + +typedef enum _drmI810Initfunc { + I810_INIT_DMA = 0x01, + I810_CLEANUP_DMA = 0x02, + I810_INIT_DMA_1_4 = 0x03 +} drmI810Initfunc; + +typedef struct { + drmI810Initfunc func; + unsigned int mmio_offset; + unsigned int buffers_offset; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int overlay_offset; + unsigned int overlay_physical; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; +} drmI810Init; + +typedef struct { + void *virtual; + int request_idx; + int request_size; + int granted; +} drmI810DMA; + +/* Flags for clear ioctl + */ +#define I810_FRONT 0x1 +#define I810_BACK 0x2 +#define I810_DEPTH 0x4 + +typedef struct { + int clear_color; + int clear_depth; + int flags; +} drmI810Clear; + +typedef struct { + int idx; /* buffer index */ + int used; /* nr bytes in use */ + int discard; /* client is finished with the buffer? */ +} drmI810Vertex; + +/* Flags for vertex ioctl + */ +#define PR_TRIANGLES (0x0<<18) +#define PR_TRISTRIP_0 (0x1<<18) +#define PR_TRISTRIP_1 (0x2<<18) +#define PR_TRIFAN (0x3<<18) +#define PR_POLYGON (0x4<<18) +#define PR_LINES (0x5<<18) +#define PR_LINESTRIP (0x6<<18) +#define PR_RECTS (0x7<<18) +#define PR_MASK (0x7<<18) + +#endif diff --git a/src/legacy/i810/i810_cursor.c b/src/legacy/i810/i810_cursor.c new file mode 100644 index 00000000..898a1364 --- /dev/null +++ b/src/legacy/i810/i810_cursor.c @@ -0,0 +1,266 @@ + +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + * Add ARGB HW cursor support: + * Alan Hourihane <alanh@tungstengraphics.com> + * + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "compiler.h" + +#include "xf86fbman.h" + +#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); +static void I810SetCursorColors(ScrnInfoPtr pScrn, int bg, int fb); +static void I810SetCursorPosition(ScrnInfoPtr pScrn, int x, int y); +static Bool I810UseHWCursor(ScreenPtr pScrn, CursorPtr pCurs); + +Bool +I810CursorInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn; + I810Ptr pI810; + xf86CursorInfoPtr infoPtr; + + pScrn = xf86Screens[pScreen->myNum]; + pI810 = I810PTR(pScrn); + pI810->CursorInfoRec = infoPtr = xf86CreateCursorInfoRec(); + if (!infoPtr) + return FALSE; + + infoPtr->MaxWidth = 64; + infoPtr->MaxHeight = 64; + infoPtr->Flags = (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | + HARDWARE_CURSOR_INVERT_MASK | + HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | 0); + + infoPtr->SetCursorColors = I810SetCursorColors; + infoPtr->SetCursorPosition = I810SetCursorPosition; + infoPtr->LoadCursorImage = I810LoadCursorImage; + 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); + uint32_t *pcurs = (uint32_t *) (pI810->FbBase + pI810->CursorStart); + uint32_t *image = (uint32_t *) 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) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + + if (!pI810->CursorPhysical) + return FALSE; + else + return TRUE; +} + +static void +I810LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) +{ + I810Ptr pI810 = I810PTR(pScrn); + uint8_t *pcurs = (uint8_t *) (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++; + } + } +} + +static void +I810SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) +{ + I810Ptr pI810 = I810PTR(pScrn); + int flag; + + x += pI810->CursorOffset; + + if (x >= 0) + flag = CURSOR_X_POS; + else { + flag = CURSOR_X_NEG; + x = -x; + } + + OUTREG8(CURSOR_X_LO, x & 0xFF); + OUTREG8(CURSOR_X_HI, (((x >> 8) & 0x07) | flag)); + + if (y >= 0) + flag = CURSOR_Y_POS; + else { + flag = CURSOR_Y_NEG; + y = -y; + } + OUTREG8(CURSOR_Y_LO, y & 0xFF); + OUTREG8(CURSOR_Y_HI, (((y >> 8) & 0x07) | flag)); + + if (pI810->CursorIsARGB) + OUTREG(CURSOR_BASEADDR, pI810->CursorARGBPhysical); + else + OUTREG(CURSOR_BASEADDR, pI810->CursorPhysical); +} + +static void +I810ShowCursor(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + unsigned char tmp; + + 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; + OUTREG8(PIXPIPE_CONFIG_0, tmp); +} + +static void +I810HideCursor(ScrnInfoPtr pScrn) +{ + unsigned char tmp; + I810Ptr pI810 = I810PTR(pScrn); + + tmp = INREG8(PIXPIPE_CONFIG_0); + tmp &= ~HW_CURSOR_ENABLE; + OUTREG8(PIXPIPE_CONFIG_0, tmp); +} + +static void +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); + + pI810->writeStandard(pI810, DACMASK, 0xFF); + pI810->writeStandard(pI810, DACWX, 0x04); + + pI810->writeStandard(pI810, DACDATA, (bg & 0x00FF0000) >> 16); + pI810->writeStandard(pI810, DACDATA, (bg & 0x0000FF00) >> 8); + pI810->writeStandard(pI810, DACDATA, (bg & 0x000000FF)); + + pI810->writeStandard(pI810, DACDATA, (fg & 0x00FF0000) >> 16); + pI810->writeStandard(pI810, DACDATA, (fg & 0x0000FF00) >> 8); + pI810->writeStandard(pI810, DACDATA, (fg & 0x000000FF)); + + tmp = INREG8(PIXPIPE_CONFIG_0); + tmp &= ~EXTENDED_PALETTE; + OUTREG8(PIXPIPE_CONFIG_0, tmp); +} diff --git a/src/legacy/i810/i810_dga.c b/src/legacy/i810/i810_dga.c new file mode 100644 index 00000000..d9ddda04 --- /dev/null +++ b/src/legacy/i810/i810_dga.c @@ -0,0 +1,258 @@ +/* + * Copyright 2000 by Alan Hourihane, Sychdyn, North Wales, UK. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Alan Hourihane not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Alan Hourihane makes no representations + * about the suitability of this software for any purpose. It is provided + * "as is" without express or implied warranty. + * + * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + * + * Authors: Alan Hourihane, <alanh@fairlite.demon.co.uk> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Pci.h" +#include "xf86PciInfo.h" +#include "xaa.h" +#include "xaalocal.h" +#include "i810.h" +#include "i810_reg.h" +#include "dgaproc.h" +#include "vgaHW.h" + +static Bool I810_OpenFramebuffer(ScrnInfoPtr, char **, unsigned char **, + int *, int *, int *); +static Bool I810_SetMode(ScrnInfoPtr, DGAModePtr); +static void I810_Sync(ScrnInfoPtr); +static int I810_GetViewport(ScrnInfoPtr); +static void I810_SetViewport(ScrnInfoPtr, int, int, int); +static void I810_FillRect(ScrnInfoPtr, int, int, int, int, unsigned long); +static void I810_BlitRect(ScrnInfoPtr, int, int, int, int, int, int); + +#if 0 +static void I810_BlitTransRect(ScrnInfoPtr, int, int, int, int, int, int, + unsigned long); +#endif + +static +DGAFunctionRec I810DGAFuncs = { + I810_OpenFramebuffer, + NULL, + I810_SetMode, + I810_SetViewport, + I810_GetViewport, + I810_Sync, + I810_FillRect, + I810_BlitRect, +#if 0 + I810_BlitTransRect +#else + NULL +#endif +}; + +Bool +I810DGAInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + DGAModePtr modes = NULL, newmodes = NULL, currentMode; + DisplayModePtr pMode, firstMode; + int Bpp = pScrn->bitsPerPixel >> 3; + int num = 0; + + pMode = firstMode = pScrn->modes; + + while (pMode) { + + newmodes = realloc(modes, (num + 1) * sizeof(DGAModeRec)); + + if (!newmodes) { + free(modes); + return FALSE; + } + modes = newmodes; + + currentMode = modes + num; + num++; + + currentMode->mode = pMode; + currentMode->flags = DGA_CONCURRENT_ACCESS | DGA_PIXMAP_AVAILABLE; + if (!pI810->noAccel) + currentMode->flags |= DGA_FILL_RECT | DGA_BLIT_RECT; + if (pMode->Flags & V_DBLSCAN) + currentMode->flags |= DGA_DOUBLESCAN; + if (pMode->Flags & V_INTERLACE) + currentMode->flags |= DGA_INTERLACED; + currentMode->byteOrder = pScrn->imageByteOrder; + currentMode->depth = pScrn->depth; + currentMode->bitsPerPixel = pScrn->bitsPerPixel; + currentMode->red_mask = pScrn->mask.red; + currentMode->green_mask = pScrn->mask.green; + currentMode->blue_mask = pScrn->mask.blue; + currentMode->visualClass = (Bpp == 1) ? PseudoColor : TrueColor; + currentMode->viewportWidth = pMode->HDisplay; + currentMode->viewportHeight = pMode->VDisplay; + currentMode->xViewportStep = (Bpp == 3) ? 2 : 1; + currentMode->yViewportStep = 1; + currentMode->viewportFlags = DGA_FLIP_RETRACE; + currentMode->offset = 0; + currentMode->address = pI810->FbBase; + + currentMode->bytesPerScanline = ((pScrn->displayWidth * Bpp) + 3) & ~3L; + currentMode->imageWidth = pI810->FbMemBox.x2; + currentMode->imageHeight = pI810->FbMemBox.y2; + currentMode->pixmapWidth = currentMode->imageWidth; + currentMode->pixmapHeight = currentMode->imageHeight; + currentMode->maxViewportX = currentMode->imageWidth - + currentMode->viewportWidth; + /* this might need to get clamped to some maximum */ + currentMode->maxViewportY = currentMode->imageHeight - + currentMode->viewportHeight; + + pMode = pMode->next; + if (pMode == firstMode) + break; + } + + pI810->numDGAModes = num; + pI810->DGAModes = modes; + + return DGAInit(pScreen, &I810DGAFuncs, modes, num); +} + +static DisplayModePtr I810SavedDGAModes[MAXSCREENS]; + +static Bool +I810_SetMode(ScrnInfoPtr pScrn, DGAModePtr pMode) +{ + int index = pScrn->pScreen->myNum; + I810Ptr pI810 = I810PTR(pScrn); + + if (!pMode) { /* restore the original mode */ + if (pI810->DGAactive) { + pScrn->currentMode = I810SavedDGAModes[index]; + pScrn->SwitchMode(index, pScrn->currentMode, 0); + pScrn->AdjustFrame(index, 0, 0, 0); + pI810->DGAactive = FALSE; + } + } else { + if (!pI810->DGAactive) { + I810SavedDGAModes[index] = pScrn->currentMode; + pI810->DGAactive = TRUE; + } + + pScrn->SwitchMode(index, pMode->mode, 0); + } + + return TRUE; +} + +static int +I810_GetViewport(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + return pI810->DGAViewportStatus; +} + +static void +I810_SetViewport(ScrnInfoPtr pScrn, int x, int y, int flags) +{ + I810Ptr pI810 = I810PTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + + pScrn->AdjustFrame(pScrn->pScreen->myNum, x, y, flags); + + /* wait for retrace */ + while ((hwp->readST01(hwp) & 0x08)) ; + while (!(hwp->readST01(hwp) & 0x08)) ; + + pI810->DGAViewportStatus = 0; +} + +static void +I810_FillRect(ScrnInfoPtr pScrn, + int x, int y, int w, int h, unsigned long color) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (pI810->AccelInfoRec) { + (*pI810->AccelInfoRec->SetupForSolidFill) (pScrn, color, GXcopy, ~0); + (*pI810->AccelInfoRec->SubsequentSolidFillRect) (pScrn, x, y, w, h); + SET_SYNC_FLAG(pI810->AccelInfoRec); + } +} + +static void +I810_Sync(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (pI810->AccelInfoRec) { + (*pI810->AccelInfoRec->Sync) (pScrn); + } +} + +static void +I810_BlitRect(ScrnInfoPtr pScrn, + int srcx, int srcy, int w, int h, int dstx, int dsty) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (pI810->AccelInfoRec) { + int xdir = ((srcx < dstx) && (srcy == dsty)) ? -1 : 1; + int ydir = (srcy < dsty) ? -1 : 1; + + (*pI810->AccelInfoRec->SetupForScreenToScreenCopy) (pScrn, xdir, ydir, + GXcopy, ~0, -1); + (*pI810->AccelInfoRec->SubsequentScreenToScreenCopy) (pScrn, srcx, srcy, + dstx, dsty, w, h); + SET_SYNC_FLAG(pI810->AccelInfoRec); + } +} + +#if 0 +static void +I810_BlitTransRect(ScrnInfoPtr pScrn, + int srcx, int srcy, + int w, int h, int dstx, int dsty, unsigned long color) +{ + + /* this one should be separate since the XAA function would + * prohibit usage of ~0 as the key */ +} +#endif + +static Bool +I810_OpenFramebuffer(ScrnInfoPtr pScrn, + char **name, + unsigned char **mem, int *size, int *offset, int *flags) +{ + I810Ptr pI810 = I810PTR(pScrn); + + *name = NULL; /* no special device */ + *mem = (unsigned char *)pI810->LinearAddr; + *size = pI810->FbMapSize; + *offset = 0; + *flags = DGA_NEED_ROOT; + + return TRUE; +} diff --git a/src/legacy/i810/i810_dri.c b/src/legacy/i810/i810_dri.c new file mode 100644 index 00000000..ecb94af1 --- /dev/null +++ b/src/legacy/i810/i810_dri.c @@ -0,0 +1,1544 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86Priv.h" + +#include "xf86PciInfo.h" +#include "xf86Pci.h" + +#include "windowstr.h" +#include "shadow.h" +#include "shadowfb.h" + +#include "GL/glxtokens.h" + +#include "i810.h" +#include "i810_dri.h" + +static char I810KernelDriverName[] = "i810"; +static char I810ClientDriverName[] = "i810"; + +static Bool I810InitVisualConfigs(ScreenPtr pScreen); +static Bool I810CreateContext(ScreenPtr pScreen, VisualPtr visual, + drm_context_t hwContext, void *pVisualConfigPriv, + DRIContextType contextStore); +static void I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext, + DRIContextType contextStore); +static void I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, + DRIContextType readContextType, + void *readContextStore, + DRIContextType writeContextType, + void *writeContextStore); +static void I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index); +static void I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, + RegionPtr prgnSrc, CARD32 index); + + +static void I810EnablePageFlip(ScreenPtr pScreen); +static void I810DisablePageFlip(ScreenPtr pScreen); +static void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen); +static void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen); +static void I810DRITransitionTo3d(ScreenPtr pScreen); +static void I810DRITransitionTo2d(ScreenPtr pScreen); + +static void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox); + +extern void GlxSetVisualConfigs(int nconfigs, + __GLXvisualConfig * configs, + void **configprivs); + +static int i810_pitches[] = { + 512, + 1024, + 2048, + 4096, + 0 +}; + +static int i810_pitch_flags[] = { + 0x0, + 0x1, + 0x2, + 0x3, + 0 +}; + +static unsigned int i810_drm_version = 0; + +Bool +I810CleanupDma(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + drmI810Init info; + + memset(&info, 0, sizeof(drmI810Init)); + info.func = I810_CLEANUP_DMA; + + if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT, + &info, sizeof(drmI810Init))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] I810 Dma Cleanup Failed\n"); + return FALSE; + } + + return TRUE; +} + +Bool +I810InitDma(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + I810RingBuffer *ring = pI810->LpRing; + I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate; + drmI810Init info; + + memset(&info, 0, sizeof(drmI810Init)); + + info.ring_start = ring->mem.Start; + info.ring_end = ring->mem.End; + info.ring_size = ring->mem.Size; + info.mmio_offset = (unsigned int)pI810DRI->regs; + info.buffers_offset = (unsigned int)pI810->buffer_map; + info.sarea_priv_offset = sizeof(XF86DRISAREARec); + + info.front_offset = 0; + info.back_offset = pI810->BackBuffer.Start; + info.depth_offset = pI810->DepthBuffer.Start; + info.overlay_offset = pI810->OverlayStart; + info.overlay_physical = pI810->OverlayPhysical; + info.w = pScrn->virtualX; + info.h = pScrn->virtualY; + info.pitch = pI810->auxPitch; + info.pitch_bits = pI810->auxPitchBits; + + /* We require DRM v1.2 or greater. Since DRM v1.2 broke compatibility + * we created a new v1.4 that supports a new init function. Eventually the + * old init function will go away. If you change the drm interface, make a + * new init type too so that we can detect the new client. + */ + switch(i810_drm_version) { + case ((1<<16) | 0): + case ((1<<16) | 1): + case ((1<<16) | 2): + case ((1<<16) | 3): + /* Use OLD drm < 1.4 init */ + info.func = I810_INIT_DMA; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init PRE v1.4 interface.\n"); + break; + default: + case ((1<<16) | 4): + /* DRM version 1.3 or greater init */ + info.func = I810_INIT_DMA_1_4; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Init v1.4 interface.\n"); + break; + } + + if (drmCommandWrite(pI810->drmSubFD, DRM_I810_INIT, + &info, sizeof(drmI810Init))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] I810 Dma Initialization failed.\n"); + return FALSE; + } + + return TRUE; +} + +static Bool +I810InitVisualConfigs(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + int numConfigs = 0; + __GLXvisualConfig *pConfigs = NULL; + I810ConfigPrivPtr pI810Configs = NULL; + I810ConfigPrivPtr *pI810ConfigPtrs = NULL; + int accum, stencil, db, depth; + int i; + + switch (pScrn->bitsPerPixel) { + case 8: + case 24: + case 32: + break; + case 16: + numConfigs = 8; + + pConfigs = + (__GLXvisualConfig *) calloc(sizeof(__GLXvisualConfig), + numConfigs); + if (!pConfigs) + return FALSE; + + pI810Configs = + (I810ConfigPrivPtr) calloc(sizeof(I810ConfigPrivRec), + numConfigs); + if (!pI810Configs) { + free(pConfigs); + return FALSE; + } + + pI810ConfigPtrs = + (I810ConfigPrivPtr *) calloc(sizeof(I810ConfigPrivPtr), + numConfigs); + if (!pI810ConfigPtrs) { + free(pConfigs); + free(pI810Configs); + return FALSE; + } + + for (i = 0; i < numConfigs; i++) + pI810ConfigPtrs[i] = &pI810Configs[i]; + + i = 0; + depth = 1; + for (accum = 0; accum <= 1; accum++) { + for (stencil = 0; stencil <= 1; stencil++) { + for (db = 1; db >= 0; db--) { + pConfigs[i].vid = -1; + pConfigs[i].class = -1; + pConfigs[i].rgba = TRUE; + 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; + pConfigs[i].alphaMask = 0; + if (accum) { + pConfigs[i].accumRedSize = 16; + pConfigs[i].accumGreenSize = 16; + pConfigs[i].accumBlueSize = 16; + pConfigs[i].accumAlphaSize = 0; + } else { + pConfigs[i].accumRedSize = 0; + pConfigs[i].accumGreenSize = 0; + pConfigs[i].accumBlueSize = 0; + pConfigs[i].accumAlphaSize = 0; + } + pConfigs[i].doubleBuffer = db ? TRUE : FALSE; + pConfigs[i].stereo = FALSE; + pConfigs[i].bufferSize = 16; + if (depth) + pConfigs[i].depthSize = 16; + else + pConfigs[i].depthSize = 0; + if (stencil) + pConfigs[i].stencilSize = 8; + else + pConfigs[i].stencilSize = 0; + pConfigs[i].auxBuffers = 0; + pConfigs[i].level = 0; + if (stencil || accum) + pConfigs[i].visualRating = GLX_SLOW_CONFIG; + else + pConfigs[i].visualRating = GLX_NONE; + pConfigs[i].transparentPixel = GLX_NONE; + pConfigs[i].transparentRed = 0; + pConfigs[i].transparentGreen = 0; + pConfigs[i].transparentBlue = 0; + pConfigs[i].transparentAlpha = 0; + pConfigs[i].transparentIndex = 0; + i++; + } + } + } + assert(i == numConfigs); + break; + } + pI810->numVisualConfigs = numConfigs; + pI810->pVisualConfigs = pConfigs; + pI810->pVisualConfigsPriv = pI810Configs; + GlxSetVisualConfigs(numConfigs, pConfigs, (void **)pI810ConfigPtrs); + return TRUE; +} + +static unsigned int +mylog2(unsigned int n) +{ + unsigned int log2 = 1; + + while (n > 1) + n >>= 1, log2++; + return log2; +} + +Bool +I810DRIScreenInit(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + DRIInfoPtr pDRIInfo; + I810DRIPtr pI810DRI; + unsigned long tom; + drm_handle_t agpHandle; + drm_handle_t dcacheHandle; + int sysmem_size = 0; + int back_size = 0; + unsigned int pitch_idx = 0; + int bufs; + int width = pScrn->displayWidth * pI810->cpp; + int i; + + /* Hardware 3D rendering only implemented for 16bpp */ + /* And it only works for 5:6:5 (Mark) */ + if (pScrn->depth != 16) + return FALSE; + + /* Check that the GLX, DRI, and DRM modules have been loaded by testing + * for known symbols in each module. */ + if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs")) + return FALSE; + if (!xf86LoaderCheckSymbol("drmAvailable")) + return FALSE; + if (!xf86LoaderCheckSymbol("DRIQueryVersion")) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] I810DRIScreenInit failed (libdri.a too old)\n"); + return FALSE; + } + + /* adjust width first */ +#define Elements(x) sizeof(x)/sizeof(*x) + for (pitch_idx = 0; pitch_idx < Elements(i810_pitches); pitch_idx++) + if (width <= i810_pitches[pitch_idx]) + break; + + if (pitch_idx == Elements(i810_pitches)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[dri] Couldn't find depth/back buffer pitch"); + DRICloseScreen(pScreen); + return FALSE; + } else { + /* for tiled memory to work, the buffer needs to have the + * number of lines as a multiple of 16 (the tile size), + * - airlied */ + int lines = (pScrn->virtualY + 15) / 16 * 16; + back_size = i810_pitches[pitch_idx] * lines; + back_size = ((back_size + 4096 - 1) / 4096) * 4096; + } + + pScrn->displayWidth = i810_pitches[pitch_idx] / pI810->cpp; + + /* Check the DRI version */ + { + int major, minor, patch; + + DRIQueryVersion(&major, &minor, &patch); + if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] I810DRIScreenInit failed because of a version mismatch.\n" + "[dri] libdri version is %d.%d.%d bug version %d.%d.x is needed.\n" + "[dri] Disabling DRI.\n", major, minor, patch, + DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION); + return FALSE; + } + } + + pDRIInfo = DRICreateInfoRec(); + if (!pDRIInfo) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] DRICreateInfoRec failed. Disabling DRI.\n"); + return FALSE; + } + +/* pDRIInfo->wrap.ValidateTree = 0; */ +/* pDRIInfo->wrap.PostValidateTree = 0; */ + + pI810->pDRIInfo = pDRIInfo; + pI810->LockHeld = 0; + + pDRIInfo->drmDriverName = I810KernelDriverName; + pDRIInfo->clientDriverName = I810ClientDriverName; + if (xf86LoaderCheckSymbol("DRICreatePCIBusID")) { + pDRIInfo->busIdString = DRICreatePCIBusID(pI810->PciInfo); + } else { + pDRIInfo->busIdString = malloc(64); + sprintf(pDRIInfo->busIdString, "PCI:%d:%d:%d", + ((pI810->PciInfo->domain << 8) | pI810->PciInfo->bus), + pI810->PciInfo->dev, pI810->PciInfo->func + ); + } + pDRIInfo->ddxDriverMajorVersion = I810_MAJOR_VERSION; + pDRIInfo->ddxDriverMinorVersion = I810_MINOR_VERSION; + pDRIInfo->ddxDriverPatchVersion = I810_PATCHLEVEL; + pDRIInfo->frameBufferPhysicalAddress = (pointer) pI810->LinearAddr; + pDRIInfo->frameBufferSize = (((pScrn->displayWidth * + pScrn->virtualY * pI810->cpp) + + 4096 - 1) / 4096) * 4096; + + pDRIInfo->frameBufferStride = pScrn->displayWidth * pI810->cpp; + pDRIInfo->ddxDrawableTableEntry = I810_MAX_DRAWABLES; + + if (SAREA_MAX_DRAWABLES < I810_MAX_DRAWABLES) + pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES; + else + pDRIInfo->maxDrawableTableEntry = I810_MAX_DRAWABLES; + + /* For now the mapping works by using a fixed size defined + * in the SAREA header + */ + if (sizeof(XF86DRISAREARec) + sizeof(I810SAREARec) > SAREA_MAX) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] Data does not fit in SAREA\n"); + return FALSE; + } + pDRIInfo->SAREASize = SAREA_MAX; + + if (!(pI810DRI = (I810DRIPtr) calloc(sizeof(I810DRIRec), 1))) { + DRIDestroyInfoRec(pI810->pDRIInfo); + pI810->pDRIInfo = NULL; + return FALSE; + } + pDRIInfo->devPrivate = pI810DRI; + pDRIInfo->devPrivateSize = sizeof(I810DRIRec); + pDRIInfo->contextSize = sizeof(I810DRIContextRec); + + pDRIInfo->CreateContext = I810CreateContext; + pDRIInfo->DestroyContext = I810DestroyContext; + pDRIInfo->SwapContext = I810DRISwapContext; + pDRIInfo->InitBuffers = I810DRIInitBuffers; + pDRIInfo->MoveBuffers = I810DRIMoveBuffers; + pDRIInfo->bufferRequests = DRI_ALL_WINDOWS; + pDRIInfo->TransitionTo2d = I810DRITransitionTo2d; + pDRIInfo->TransitionTo3d = I810DRITransitionTo3d; + pDRIInfo->TransitionSingleToMulti3D = I810DRITransitionSingleToMulti3d; + pDRIInfo->TransitionMultiToSingle3D = I810DRITransitionMultiToSingle3d; + + pDRIInfo->createDummyCtx = TRUE; + pDRIInfo->createDummyCtxPriv = FALSE; + + /* This adds the framebuffer as a drm map *before* we have asked agp + * to allocate it. Scary stuff, hold on... + */ + if (!DRIScreenInit(pScreen, pDRIInfo, &pI810->drmSubFD)) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] DRIScreenInit failed. Disabling DRI.\n"); + free(pDRIInfo->devPrivate); + pDRIInfo->devPrivate = NULL; + DRIDestroyInfoRec(pI810->pDRIInfo); + pI810->pDRIInfo = NULL; + return FALSE; + } + + /* Check the i810 DRM versioning */ + { + drmVersionPtr version; + + /* Check the DRM lib version. + * drmGetLibVersion was not supported in version 1.0, so check for + * symbol first to avoid possible crash or hang. + */ + if (xf86LoaderCheckSymbol("drmGetLibVersion")) { + version = drmGetLibVersion(pI810->drmSubFD); + } else + { + /* drmlib version 1.0.0 didn't have the drmGetLibVersion + * entry point. Fake it by allocating a version record + * via drmGetVersion and changing it to version 1.0.0 + */ + version = drmGetVersion(pI810->drmSubFD); + version->version_major = 1; + version->version_minor = 0; + version->version_patchlevel = 0; + } + +#define REQ_MAJ 1 +#define REQ_MIN 1 + if (version) { + if (version->version_major != REQ_MAJ || + version->version_minor < REQ_MIN) { + /* incompatible drm library version */ + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] I810DRIScreenInit failed because of a version mismatch.\n" + "[dri] libdrm.a module version is %d.%d.%d but version %d.%d.x is needed.\n" + "[dri] Disabling DRI.\n", + version->version_major, + version->version_minor, version->version_patchlevel, + REQ_MAJ, REQ_MIN); + drmFreeVersion(version); + I810DRICloseScreen(pScreen); + return FALSE; + } + drmFreeVersion(version); + } + + /* Check the i810 DRM version */ + version = drmGetVersion(pI810->drmSubFD); + if (version) { + i810_drm_version = (version->version_major<<16) | + version->version_minor; + if (version->version_major != 1 || version->version_minor < 2) { + /* incompatible drm version */ + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] I810DRIScreenInit failed because of a version mismatch.\n" + "[dri] i810.o kernel module version is %d.%d.%d but version 1.2.0 or greater is needed.\n" + "[dri] Disabling DRI.\n", + version->version_major, + version->version_minor, version->version_patchlevel); + I810DRICloseScreen(pScreen); + drmFreeVersion(version); + return FALSE; + } + pI810->drmMinor = version->version_minor; + drmFreeVersion(version); + } + } + + pI810DRI->regsSize = I810_REG_SIZE; + if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->MMIOAddr, + pI810DRI->regsSize, DRM_REGISTERS, 0, + (drmAddress) &pI810DRI->regs) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[drm] drmAddMap(regs) failed\n"); + DRICloseScreen(pScreen); + return FALSE; + } + xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n", + (int)pI810DRI->regs); + + pI810->backHandle = DRM_AGP_NO_HANDLE; + pI810->zHandle = DRM_AGP_NO_HANDLE; + pI810->cursorHandle = DRM_AGP_NO_HANDLE; + pI810->xvmcHandle = DRM_AGP_NO_HANDLE; + pI810->sysmemHandle = DRM_AGP_NO_HANDLE; + pI810->agpAcquired = FALSE; + pI810->dcacheHandle = DRM_AGP_NO_HANDLE; + + /* Agp Support - Need this just to get the framebuffer. + */ + if (drmAgpAcquire(pI810->drmSubFD) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpAquire failed\n"); + DRICloseScreen(pScreen); + return FALSE; + } + pI810->agpAcquired = TRUE; + + if (drmAgpEnable(pI810->drmSubFD, 0) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] drmAgpEnable failed\n"); + DRICloseScreen(pScreen); + return FALSE; + } + + memset(&pI810->DcacheMem, 0, sizeof(I810MemRange)); + 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. + */ + + drmAgpAlloc(pI810->drmSubFD, 4096 * 1024, 1, NULL, + (drmAddress) &dcacheHandle); + pI810->dcacheHandle = dcacheHandle; + + xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] dcacheHandle : 0x%x\n", + (int)dcacheHandle); + + sysmem_size = pScrn->videoRam * 1024; + if (dcacheHandle != DRM_AGP_NO_HANDLE) { + if (back_size > 4 * 1024 * 1024) { + xf86DrvMsg(pScreen->myNum, X_INFO, + "[dri] Backsize is larger then 4 meg\n"); + sysmem_size = sysmem_size - 2 * back_size; + drmAgpFree(pI810->drmSubFD, dcacheHandle); + pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; + } else { + sysmem_size = sysmem_size - back_size; + } + } else { + sysmem_size = sysmem_size - 2 * back_size; + } + + /* Max size is 48 without XvMC, 41 with 6 surfaces, 40 with 7 surfaces */ + if (pI810->numSurfaces && (pI810->numSurfaces == 6)) { + if (sysmem_size > (pI810->FbMapSize - 7 * 1024 * 1024)) { + sysmem_size = (pI810->FbMapSize - 7 * 1024 * 1024); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "User requested more memory then fits in the agp aperture\n" + "Truncating to %d bytes of memory\n", sysmem_size); + } + } + if (pI810->numSurfaces && (pI810->numSurfaces == 7)) { + if (sysmem_size > (pI810->FbMapSize - 8 * 1024 * 1024)) { + sysmem_size = (pI810->FbMapSize - 8 * 1024 * 1024); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "User requested more memory then fits in the agp aperture\n" + "Truncating to %d bytes of memory\n", sysmem_size); + } + } + + if (sysmem_size > pI810->FbMapSize) { + sysmem_size = pI810->FbMapSize; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[dri] User requested more memory then fits in the agp" + " aperture\n\tTruncating to %d bytes of memory\n", + sysmem_size); + } + + 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; + pI810->SysMem.End = sysmem_size; + tom = sysmem_size; + + pI810->SavedSysMem = pI810->SysMem; + + if (dcacheHandle != DRM_AGP_NO_HANDLE) { + if (drmAgpBind(pI810->drmSubFD, dcacheHandle, pI810->DepthOffset) == 0) { + memset(&pI810->DcacheMem, 0, sizeof(I810MemRange)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] GART: Found 4096K Z buffer memory\n"); + pI810->DcacheMem.Start = pI810->DepthOffset; + pI810->DcacheMem.Size = 1024 * 4096; + pI810->DcacheMem.End = + pI810->DcacheMem.Start + pI810->DcacheMem.Size; + if (!I810AllocLow + (&(pI810->DepthBuffer), &(pI810->DcacheMem), back_size)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] Depth buffer allocation failed\n"); + DRICloseScreen(pScreen); + return FALSE; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] GART: dcache bind failed\n"); + drmAgpFree(pI810->drmSubFD, dcacheHandle); + pI810->dcacheHandle = dcacheHandle = DRM_AGP_NO_HANDLE; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] GART: no dcache memory found\n"); + } + + drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, + (drmAddress) &agpHandle); + pI810->backHandle = agpHandle; + + if (agpHandle != DRM_AGP_NO_HANDLE) { + if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->BackOffset) == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] Bound backbuffer memory\n"); + + pI810->BackBuffer.Start = pI810->BackOffset; + pI810->BackBuffer.Size = back_size; + pI810->BackBuffer.End = (pI810->BackBuffer.Start + + pI810->BackBuffer.Size); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] Unable to bind backbuffer. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[dri] Unable to allocate backbuffer memory. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + + if (dcacheHandle == DRM_AGP_NO_HANDLE) { + drmAgpAlloc(pI810->drmSubFD, back_size, 0, NULL, + (drmAddress) &agpHandle); + + pI810->zHandle = agpHandle; + + if (agpHandle != DRM_AGP_NO_HANDLE) { + if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->DepthOffset) == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] Bound depthbuffer memory\n"); + pI810->DepthBuffer.Start = pI810->DepthOffset; + pI810->DepthBuffer.Size = back_size; + pI810->DepthBuffer.End = (pI810->DepthBuffer.Start + + pI810->DepthBuffer.Size); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] Unable to bind depthbuffer. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] Unable to allocate depthbuffer memory. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + } + + /* Now allocate and bind the agp space. This memory will include the + * regular framebuffer as well as texture memory. + */ + drmAgpAlloc(pI810->drmSubFD, sysmem_size, 0, NULL, + (drmAddress)&agpHandle); + pI810->sysmemHandle = agpHandle; + + if (agpHandle != DRM_AGP_NO_HANDLE) { + if (drmAgpBind(pI810->drmSubFD, agpHandle, 0) == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] Bound System Texture Memory\n"); + } else { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to bind system texture memory. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + } else { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Unable to allocate system texture memory. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + +/* Allocate 7 or 8MB for XvMC this is setup as follows to best use tiled + regions and required surface pitches. (Numbers are adjusted if the + AGP region is only 32MB + For numSurfaces == 6 + 44 - 48MB = 4MB Fence, 8 Tiles wide + 43 - 44MB = 1MB Fence, 8 Tiles wide + 42 - 43MB = 1MB Fence, 4 Tiles wide + 41 - 42MB = 1MB Fence, 4 Tiles wide + For numSurfaces == 7 + 44 - 48MB = 4MB Fence, 8 Tiles wide + 43 - 44MB = 1MB Fence, 8 Tiles wide + 42.5 - 43MB = 0.5MB Fence, 8 Tiles wide + 42 - 42.5MB = 0.5MB Fence, 4 Tiles wide + 40 - 42MB = 2MB Fence, 4 Tiles wide + */ + if (pI810->numSurfaces) { + if (pI810->numSurfaces == 6) { + pI810->MC.Size = 7 * 1024 * 1024; + pI810->MC.Start = pI810->FbMapSize - 7 * 1024 * 1024; + + } + if (pI810->numSurfaces == 7) { + pI810->MC.Size = 8 * 1024 * 1024; + pI810->MC.Start = pI810->FbMapSize - 8 * 1024 * 1024; + } + drmAgpAlloc(pI810->drmSubFD, pI810->MC.Size, 0, NULL, + (drmAddress) &agpHandle); + + pI810->xvmcHandle = agpHandle; + + if (agpHandle != DRM_AGP_NO_HANDLE) { + if (drmAgpBind(pI810->drmSubFD, agpHandle, pI810->MC.Start) == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "GART: Allocated 7MB for HWMC\n"); + pI810->MC.End = pI810->MC.Start + pI810->MC.Size; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC bind failed\n"); + pI810->MC.Start = 0; + pI810->MC.Size = 0; + pI810->MC.End = 0; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "GART: HWMC alloc failed\n"); + pI810->MC.Start = 0; + pI810->MC.Size = 0; + pI810->MC.End = 0; + } + pI810->xvmcContext = 0; + } + + drmAgpAlloc(pI810->drmSubFD, 4096, 2, + (unsigned long *)&pI810->CursorPhysical, + (drmAddress) &agpHandle); + + pI810->cursorHandle = agpHandle; + + if (agpHandle != DRM_AGP_NO_HANDLE) { + tom = sysmem_size; + + if (drmAgpBind(pI810->drmSubFD, agpHandle, tom) == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] GART: Allocated 4K for mouse cursor image\n"); + pI810->CursorStart = tom; + tom += 4096; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] GART: cursor bind failed\n"); + pI810->CursorPhysical = 0; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[agp] GART: cursor alloc failed\n"); + pI810->CursorPhysical = 0; + } + + drmAgpAlloc(pI810->drmSubFD, 16384, 2, + (unsigned long *)&pI810->CursorARGBPhysical, + (drmAddress) &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; + pI810->OverlayStart = pI810->CursorStart + 1024; + + I810SetTiledMemory(pScrn, 1, + pI810->DepthBuffer.Start, + i810_pitches[pitch_idx], 8 * 1024 * 1024); + + I810SetTiledMemory(pScrn, 2, + pI810->BackBuffer.Start, + i810_pitches[pitch_idx], 8 * 1024 * 1024); + + /* These are for HWMC surfaces */ + if (pI810->numSurfaces == 6) { + I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 1024 * 1024); + + I810SetTiledMemory(pScrn, 4, + pI810->MC.Start + 1024 * 1024, 512, 1024 * 1024); + + I810SetTiledMemory(pScrn, 5, + pI810->MC.Start + 1024 * 1024 * 2, + 1024, 1024 * 1024); + + I810SetTiledMemory(pScrn, 6, + pI810->MC.Start + 1024 * 1024 * 3, + 1024, 4 * 1024 * 1024); + } + if (pI810->numSurfaces == 7) { + I810SetTiledMemory(pScrn, 3, pI810->MC.Start, 512, 2 * 1024 * 1024); + + I810SetTiledMemory(pScrn, 4, + pI810->MC.Start + 2 * 1024 * 1024, 512, 512 * 1024); + + I810SetTiledMemory(pScrn, 5, + pI810->MC.Start + 2 * 1024 * 1024 + 512 * 1024, + 1024, 512 * 1024); + + I810SetTiledMemory(pScrn, 6, + pI810->MC.Start + 3 * 1024 * 1024, + 1024, 1 * 1024 * 1024); + + I810SetTiledMemory(pScrn, 7, + pI810->MC.Start + 4 * 1024 * 1024, + 1024, 4 * 1024 * 1024); + + } + + pI810->auxPitch = i810_pitches[pitch_idx]; + pI810->auxPitchBits = i810_pitch_flags[pitch_idx]; + pI810->SavedDcacheMem = pI810->DcacheMem; + pI810DRI->backbufferSize = pI810->BackBuffer.Size; + + if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BackBuffer.Start, + pI810->BackBuffer.Size, DRM_AGP, 0, + (drmAddress) &pI810DRI->backbuffer) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] drmAddMap(backbuffer) failed. Disabling DRI\n"); + DRICloseScreen(pScreen); + return FALSE; + } + + pI810DRI->depthbufferSize = pI810->DepthBuffer.Size; + if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->DepthBuffer.Start, + pI810->DepthBuffer.Size, DRM_AGP, 0, + (drmAddress) &pI810DRI->depthbuffer) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] drmAddMap(depthbuffer) failed. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + + /* Allocate FrontBuffer etc. */ + if (!I810AllocateFront(pScrn)) { + DRICloseScreen(pScreen); + return FALSE; + } + + /* Allocate buffer memory */ + I810AllocHigh(&(pI810->BufferMem), &(pI810->SysMem), + I810_DMA_BUF_NR * I810_DMA_BUF_SZ); + + xf86DrvMsg(pScreen->myNum, X_INFO, "[dri] Buffer map : %lx\n", + pI810->BufferMem.Start); + + if (pI810->BufferMem.Start == 0 || + pI810->BufferMem.End - pI810->BufferMem.Start > + I810_DMA_BUF_NR * I810_DMA_BUF_SZ) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] Not enough memory for dma buffers. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->BufferMem.Start, + pI810->BufferMem.Size, DRM_AGP, 0, + (drmAddress) &pI810->buffer_map) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] drmAddMap(buffer_map) failed. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + + 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, + (drmAddress) &pI810->ring_map) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] drmAddMap(ring_map) failed. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + + /* Use the rest of memory for textures. */ + pI810DRI->textureSize = pI810->SysMem.Size; + + i = mylog2(pI810DRI->textureSize / I810_NR_TEX_REGIONS); + + if (i < I810_LOG_MIN_TEX_REGION_SIZE) + i = I810_LOG_MIN_TEX_REGION_SIZE; + + pI810DRI->logTextureGranularity = i; + pI810DRI->textureSize = (pI810DRI->textureSize >> i) << i; /* truncate */ + + if (pI810DRI->textureSize < 512 * 1024) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] Less then 512k memory left for textures. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + + I810AllocLow(&(pI810->TexMem), &(pI810->SysMem), pI810DRI->textureSize); + + if (drmAddMap(pI810->drmSubFD, (drm_handle_t) pI810->TexMem.Start, + pI810->TexMem.Size, DRM_AGP, 0, + (drmAddress) &pI810DRI->textures) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[drm] drmAddMap(textures) failed. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + + if ((bufs = drmAddBufs(pI810->drmSubFD, + I810_DMA_BUF_NR, + I810_DMA_BUF_SZ, + DRM_AGP_BUFFER, pI810->BufferMem.Start)) <= 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] failure adding %d %d byte DMA buffers. Disabling DRI.\n", + I810_DMA_BUF_NR, I810_DMA_BUF_SZ); + DRICloseScreen(pScreen); + return FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] added %d %d byte DMA buffers\n", bufs, I810_DMA_BUF_SZ); + + I810InitDma(pScrn); + + /* Okay now initialize the dma engine */ + + if (!pI810DRI->irq) { + pI810DRI->irq = drmGetInterruptFromBusID(pI810->drmSubFD, + ((pI810->PciInfo->domain << 8) | + pI810->PciInfo->bus), + pI810->PciInfo->dev, + pI810->PciInfo->func + ); + if ((drmCtlInstHandler(pI810->drmSubFD, pI810DRI->irq)) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] failure adding irq handler, there is a device " + "already using that irq\n Consider rearranging your " + "PCI cards. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] dma control initialized, using IRQ %d\n", pI810DRI->irq); + + pI810DRI->deviceID = DEVICE_ID(pI810->PciInfo); + pI810DRI->width = pScrn->virtualX; + pI810DRI->height = pScrn->virtualY; + pI810DRI->mem = pScrn->videoRam * 1024; + pI810DRI->cpp = pI810->cpp; + + pI810DRI->fbOffset = pI810->FrontBuffer.Start; + pI810DRI->fbStride = pI810->auxPitch; + + pI810DRI->bitsPerPixel = pScrn->bitsPerPixel; + + pI810DRI->textureOffset = pI810->TexMem.Start; + + pI810DRI->backOffset = pI810->BackBuffer.Start; + pI810DRI->depthOffset = pI810->DepthBuffer.Start; + + pI810DRI->ringOffset = pI810->LpRing->mem.Start; + pI810DRI->ringSize = pI810->LpRing->mem.Size; + + pI810DRI->auxPitch = pI810->auxPitch; + pI810DRI->auxPitchBits = pI810->auxPitchBits; + pI810DRI->sarea_priv_offset = sizeof(XF86DRISAREARec); + + if (!(I810InitVisualConfigs(pScreen))) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[dri] I810InitVisualConfigs failed. Disabling DRI.\n"); + DRICloseScreen(pScreen); + return FALSE; + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[dri] visual configs initialized.\n"); + pI810->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT; + + return TRUE; +} + +void +I810DRICloseScreen(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + I810DRIPtr pI810DRI = (I810DRIPtr) pI810->pDRIInfo->devPrivate; + + if (pI810DRI->irq) { + drmCtlUninstHandler(pI810->drmSubFD); + pI810DRI->irq = 0; + } + + I810CleanupDma(pScrn); + + if (pI810->dcacheHandle!=DRM_AGP_NO_HANDLE) + drmAgpFree(pI810->drmSubFD, pI810->dcacheHandle); + if (pI810->backHandle!=DRM_AGP_NO_HANDLE) + drmAgpFree(pI810->drmSubFD, pI810->backHandle); + if (pI810->zHandle!=DRM_AGP_NO_HANDLE) + drmAgpFree(pI810->drmSubFD, pI810->zHandle); + if (pI810->cursorHandle!=DRM_AGP_NO_HANDLE) + drmAgpFree(pI810->drmSubFD, pI810->cursorHandle); + if (pI810->xvmcHandle!=DRM_AGP_NO_HANDLE) + drmAgpFree(pI810->drmSubFD, pI810->xvmcHandle); + if (pI810->sysmemHandle!=DRM_AGP_NO_HANDLE) + drmAgpFree(pI810->drmSubFD, pI810->sysmemHandle); + + if (pI810->agpAcquired == TRUE) + drmAgpRelease(pI810->drmSubFD); + + pI810->backHandle = DRM_AGP_NO_HANDLE; + pI810->zHandle = DRM_AGP_NO_HANDLE; + pI810->cursorHandle = DRM_AGP_NO_HANDLE; + pI810->xvmcHandle = DRM_AGP_NO_HANDLE; + pI810->sysmemHandle = DRM_AGP_NO_HANDLE; + pI810->agpAcquired = FALSE; + pI810->dcacheHandle = DRM_AGP_NO_HANDLE; + + DRICloseScreen(pScreen); + + if (pI810->pDRIInfo) { + if (pI810->pDRIInfo->devPrivate) { + free(pI810->pDRIInfo->devPrivate); + pI810->pDRIInfo->devPrivate = NULL; + } + DRIDestroyInfoRec(pI810->pDRIInfo); + pI810->pDRIInfo = NULL; + } + if (pI810->pVisualConfigs) + free(pI810->pVisualConfigs); + if (pI810->pVisualConfigsPriv) + free(pI810->pVisualConfigsPriv); +} + +static Bool +I810CreateContext(ScreenPtr pScreen, VisualPtr visual, + drm_context_t hwContext, void *pVisualConfigPriv, + DRIContextType contextStore) +{ + return TRUE; +} + +static void +I810DestroyContext(ScreenPtr pScreen, drm_context_t hwContext, + DRIContextType contextStore) +{ +} + +Bool +I810DRIFinishScreenInit(ScreenPtr pScreen) +{ + I810SAREARec *sPriv = (I810SAREARec *) DRIGetSAREAPrivate(pScreen); + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr info = I810PTR(pScrn); + + memset(sPriv, 0, sizeof(sPriv)); + + /* Have shadow run only while there is 3d active. + */ + if (info->allowPageFlip && info->drmMinor >= 3) { + ShadowFBInit( pScreen, I810DRIRefreshArea ); + } + else + info->allowPageFlip = 0; + return DRIFinishScreenInit(pScreen); +} + +void +I810DRISwapContext(ScreenPtr pScreen, DRISyncType syncType, + DRIContextType oldContextType, void *oldContext, + DRIContextType newContextType, void *newContext) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + + if (syncType == DRI_3D_SYNC && + oldContextType == DRI_2D_CONTEXT && newContextType == DRI_2D_CONTEXT) { + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("I810DRISwapContext (in)\n"); + + if (!pScrn->vtSema) + return; + pI810->LockHeld = 1; + I810RefreshRing(pScrn); + } else if (syncType == DRI_2D_SYNC && + oldContextType == DRI_NO_CONTEXT && + newContextType == DRI_2D_CONTEXT) { + pI810->LockHeld = 0; + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("I810DRISwapContext (out)\n"); + } else if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("I810DRISwapContext (other)\n"); +} + +static void +I810DRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + BoxPtr pbox = REGION_RECTS(prgn); + int nbox = REGION_NUM_RECTS(prgn); + + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("I810DRIInitBuffers\n"); + + I810SetupForSolidFill(pScrn, 0, GXcopy, -1); + while (nbox--) { + I810SelectBuffer(pScrn, I810_SELECT_BACK); + I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + pbox++; + } + + /* Clear the depth buffer - uses 0xffff rather than 0. + */ + pbox = REGION_RECTS(prgn); + nbox = REGION_NUM_RECTS(prgn); + I810SelectBuffer(pScrn, I810_SELECT_DEPTH); + I810SetupForSolidFill(pScrn, 0xffff, GXcopy, -1); + while (nbox--) { + I810SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1, + pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); + pbox++; + } + I810SelectBuffer(pScrn, I810_SELECT_FRONT); + + if (pI810->AccelInfoRec) + pI810->AccelInfoRec->NeedToSync = TRUE; +} + +/* This routine is a modified form of XAADoBitBlt with the calls to + * ScreenToScreenBitBlt built in. My routine has the prgnSrc as source + * instead of destination. My origin is upside down so the ydir cases + * are reversed. + * + * KW: can you believe that this is called even when a 2d window moves? + */ +static void +I810DRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg, + RegionPtr prgnSrc, CARD32 index) +{ + ScreenPtr pScreen = pParent->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + BoxPtr pboxTmp, pboxNext, pboxBase; + DDXPointPtr pptTmp, pptNew2 = NULL; + int xdir, ydir; + + int screenwidth = pScrn->virtualX; + int screenheight = pScrn->virtualY; + + BoxPtr pbox = REGION_RECTS(prgnSrc); + int nbox = REGION_NUM_RECTS(prgnSrc); + + BoxPtr pboxNew1 = NULL; + BoxPtr pboxNew2 = NULL; + DDXPointPtr pptNew1 = NULL; + DDXPointPtr pptSrc = &ptOldOrg; + + int dx = pParent->drawable.x - ptOldOrg.x; + int dy = pParent->drawable.y - ptOldOrg.y; + + /* If the copy will overlap in Y, reverse the order */ + if (dy > 0) { + ydir = -1; + + if (nbox > 1) { + /* Keep ordering in each band, reverse order of bands */ + pboxNew1 = (BoxPtr) malloc(sizeof(BoxRec) * nbox); + if (!pboxNew1) + return; + pptNew1 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox); + if (!pptNew1) { + free(pboxNew1); + return; + } + pboxBase = pboxNext = pbox + nbox - 1; + while (pboxBase >= pbox) { + while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1)) + pboxNext--; + pboxTmp = pboxNext + 1; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp <= pboxBase) { + *pboxNew1++ = *pboxTmp++; + *pptNew1++ = *pptTmp++; + } + pboxBase = pboxNext; + } + pboxNew1 -= nbox; + pbox = pboxNew1; + pptNew1 -= nbox; + pptSrc = pptNew1; + } + } else { + /* No changes required */ + ydir = 1; + } + + /* If the regions will overlap in X, reverse the order */ + if (dx > 0) { + xdir = -1; + + if (nbox > 1) { + /*reverse orderof rects in each band */ + pboxNew2 = (BoxPtr) malloc(sizeof(BoxRec) * nbox); + pptNew2 = (DDXPointPtr) malloc(sizeof(DDXPointRec) * nbox); + if (!pboxNew2 || !pptNew2) { + if (pptNew2) + free(pptNew2); + if (pboxNew2) + free(pboxNew2); + if (pboxNew1) { + free(pptNew1); + free(pboxNew1); + } + return; + } + pboxBase = pboxNext = pbox; + while (pboxBase < pbox + nbox) { + while ((pboxNext < pbox + nbox) && (pboxNext->y1 == pboxBase->y1)) + pboxNext++; + pboxTmp = pboxNext; + pptTmp = pptSrc + (pboxTmp - pbox); + while (pboxTmp != pboxBase) { + *pboxNew2++ = *--pboxTmp; + *pptNew2++ = *--pptTmp; + } + pboxBase = pboxNext; + } + pboxNew2 -= nbox; + pbox = pboxNew2; + pptNew2 -= nbox; + pptSrc = pptNew2; + } + } else { + /* No changes are needed */ + xdir = 1; + } + + /* SelectBuffer isn't really a good concept for the i810. + */ + I810EmitFlush(pScrn); + I810SetupForScreenToScreenCopy(pScrn, xdir, ydir, GXcopy, -1, -1); + for (; nbox--; pbox++) { + + int x1 = pbox->x1; + int y1 = pbox->y1; + int destx = x1 + dx; + int desty = y1 + dy; + int w = pbox->x2 - x1 + 1; + int h = pbox->y2 - y1 + 1; + + if (destx < 0) + x1 -= destx, w += destx, destx = 0; + if (desty < 0) + y1 -= desty, h += desty, desty = 0; + if (destx + w > screenwidth) + w = screenwidth - destx; + if (desty + h > screenheight) + h = screenheight - desty; + if (w <= 0) + continue; + if (h <= 0) + continue; + + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("MoveBuffers %d,%d %dx%d dx: %d dy: %d\n", + x1, y1, w, h, dx, dy); + + I810SelectBuffer(pScrn, I810_SELECT_BACK); + I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); + I810SelectBuffer(pScrn, I810_SELECT_DEPTH); + I810SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h); + } + I810SelectBuffer(pScrn, I810_SELECT_FRONT); + I810EmitFlush(pScrn); + + if (pboxNew2) { + free(pptNew2); + free(pboxNew2); + } + if (pboxNew1) { + free(pptNew1); + free(pboxNew1); + } + + if (pI810->AccelInfoRec) + pI810->AccelInfoRec->NeedToSync = TRUE; +} + + +/* Use the miext/shadow module to maintain a list of dirty rectangles. + * These are blitted to the back buffer to keep both buffers clean + * during page-flipping when the 3d application isn't fullscreen. + * + * Unlike most use of the shadow code, both buffers are in video memory. + * + * An alternative to this would be to organize for all on-screen drawing + * operations to be duplicated for the two buffers. That might be + * faster, but seems like a lot more work... + */ + + +/* This should be done *before* XAA syncs or fires its buffer. + * Otherwise will have to fire it again??? + */ +static void I810DRIRefreshArea(ScrnInfoPtr pScrn, int num, BoxPtr pbox) +{ + I810Ptr pI810 = I810PTR(pScrn); + int i; + I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + unsigned int br13; + int cpp=2; + + + /* Don't want to do this when no 3d is active and pages are + * right-way-round + */ + if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0) + return; + + br13 = (pI810->auxPitch) | (0xcc << 16); + + for (i = 0 ; i < num ; i++, pbox++) { + unsigned int w = min(pbox->y2, pScrn->virtualY-1) - max(pbox->y1, 0) + 1; + unsigned int h = min(pbox->x2, pScrn->virtualX-1) - max(pbox->x1, 0) + 1; + unsigned int dst = max(pbox->x1, 0)*cpp + (max(pbox->y1, 0)*pI810->auxPitch); + + BEGIN_LP_RING(6); + + OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4); + OUT_RING(br13); + OUT_RING( (h<<16) | (w*cpp) ); + OUT_RING(pI810->BackBuffer.Start + dst); + OUT_RING(br13 & 0xffff); + OUT_RING(dst); + + ADVANCE_LP_RING(); + } + +} + +static void I810EnablePageFlip(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + int cpp=2; + pSAREAPriv->pf_enabled = pI810->allowPageFlip; + pSAREAPriv->pf_active = 0; + + if (pI810->allowPageFlip) { + unsigned int br13 = pI810->auxPitch | (0xcc << 16); + + BEGIN_LP_RING(6); + + OUT_RING(BR00_BITBLT_CLIENT | BR00_OP_SRC_COPY_BLT | 0x4); + OUT_RING(br13); + OUT_RING((pScrn->virtualY << 16) | (pScrn->virtualX*cpp)); + OUT_RING(pI810->BackBuffer.Start); + OUT_RING(br13 & 0xFFFF); + OUT_RING(0); + ADVANCE_LP_RING(); + + pSAREAPriv->pf_active = 1; + } + +} + +static void I810DisablePageFlip(ScreenPtr pScreen) +{ + I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + pSAREAPriv->pf_active=0; +} + +static void I810DRITransitionSingleToMulti3d(ScreenPtr pScreen) +{ + /* Tell the clients not to pageflip. How? + * -- Field in sarea, plus bumping the window counters. + * -- DRM needs to cope with Front-to-Back swapbuffers. + */ + I810DisablePageFlip(pScreen); +} + +static void I810DRITransitionMultiToSingle3d(ScreenPtr pScreen) +{ + /* Let the remaining 3d app start page flipping again */ + I810EnablePageFlip(pScreen); +} + +static void I810DRITransitionTo3d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + + I810EnablePageFlip(pScreen); + pI810->have3DWindows = 1; +} + +static void I810DRITransitionTo2d(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + I810SAREAPtr pSAREAPriv = DRIGetSAREAPrivate(pScreen); + + /* Try flipping back to the front page if necessary */ + if (pSAREAPriv->pf_current_page == 1) + drmCommandNone(pI810->drmSubFD, DRM_I810_FLIP); + + /* Shut down shadowing if we've made it back to the front page */ + if (pSAREAPriv->pf_current_page == 0) { + I810DisablePageFlip(pScreen); + } + pI810->have3DWindows = 0; +} + +Bool +I810DRILeave(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (pI810->directRenderingEnabled) { + if (pI810->dcacheHandle != 0) + if (drmAgpUnbind(pI810->drmSubFD, pI810->dcacheHandle) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); + return FALSE; + } + if (pI810->backHandle != 0) + if (drmAgpUnbind(pI810->drmSubFD, pI810->backHandle) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); + return FALSE; + } + if (pI810->zHandle != 0) + if (drmAgpUnbind(pI810->drmSubFD, pI810->zHandle) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); + return FALSE; + } + if (pI810->sysmemHandle != 0) + if (drmAgpUnbind(pI810->drmSubFD, pI810->sysmemHandle) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); + return FALSE; + } + if (pI810->xvmcHandle != 0) + if (drmAgpUnbind(pI810->drmSubFD, pI810->xvmcHandle) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); + return FALSE; + } + if (pI810->cursorHandle != 0) + if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorHandle) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); + return FALSE; + } + if (pI810->cursorARGBHandle != 0) + if (drmAgpUnbind(pI810->drmSubFD, pI810->cursorARGBHandle) != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"%s\n",strerror(errno)); + return FALSE; + } + if (pI810->agpAcquired == TRUE) + drmAgpRelease(pI810->drmSubFD); + pI810->agpAcquired = FALSE; + } + return TRUE; +} + +Bool +I810DRIEnter(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (pI810->directRenderingEnabled) { + + if (pI810->agpAcquired == FALSE) + drmAgpAcquire(pI810->drmSubFD); + pI810->agpAcquired = TRUE; + if (pI810->dcacheHandle != 0) + if (drmAgpBind(pI810->drmSubFD, pI810->dcacheHandle, + pI810->DepthOffset) != 0) + return FALSE; + if (pI810->backHandle != 0) + if (drmAgpBind(pI810->drmSubFD, pI810->backHandle, + pI810->BackOffset) != 0) + return FALSE; + if (pI810->zHandle != 0) + if (drmAgpBind(pI810->drmSubFD, pI810->zHandle, + pI810->DepthOffset) != 0) + return FALSE; + if (pI810->sysmemHandle != 0) + if (drmAgpBind(pI810->drmSubFD, pI810->sysmemHandle, 0) != 0) + return FALSE; + if (pI810->xvmcHandle != 0) + if (drmAgpBind(pI810->drmSubFD, pI810->xvmcHandle, + pI810->MC.Start) != 0) + return FALSE; + if (pI810->cursorHandle != 0) + 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/legacy/i810/i810_dri.h b/src/legacy/i810/i810_dri.h new file mode 100644 index 00000000..16b6f087 --- /dev/null +++ b/src/legacy/i810/i810_dri.h @@ -0,0 +1,131 @@ + +#ifndef _I810_DRI_ +#define _I810_DRI_ + +#include "xf86drm.h" +#include "i810_common.h" + +#define I810_MAX_DRAWABLES 256 + +#define I810_MAJOR_VERSION 1 +#define I810_MINOR_VERSION 7 +#define I810_PATCHLEVEL 4 + +typedef struct { + drm_handle_t regs; + drmSize regsSize; + + drmSize backbufferSize; + drm_handle_t backbuffer; + + drmSize depthbufferSize; + drm_handle_t depthbuffer; + + drm_handle_t textures; + int textureSize; + + drm_handle_t agp_buffers; + drmSize agp_buf_size; + + int deviceID; + int width; + int height; + int mem; + int cpp; + int bitsPerPixel; + int fbOffset; + int fbStride; + + int backOffset; + int depthOffset; + + int auxPitch; + int auxPitchBits; + + int logTextureGranularity; + int textureOffset; + + /* For non-dma direct rendering. + */ + int ringOffset; + int ringSize; + + drmBufMapPtr drmBufs; + int irq; + unsigned int sarea_priv_offset; + +} I810DRIRec, *I810DRIPtr; + +/* WARNING: Do not change the SAREA structure without changing the kernel + * as well */ + +#define I810_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */ +#define I810_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */ +#define I810_UPLOAD_CTX 0x4 +#define I810_UPLOAD_BUFFERS 0x8 +#define I810_UPLOAD_TEX0 0x10 +#define I810_UPLOAD_TEX1 0x20 +#define I810_UPLOAD_CLIPRECTS 0x40 + +typedef struct { + unsigned char next, prev; /* indices to form a circular LRU */ + unsigned char in_use; /* owned by a client, or free? */ + int age; /* tracked by clients to update local LRU's */ +} I810TexRegionRec, *I810TexRegionPtr; + +typedef struct { + unsigned int ContextState[I810_CTX_SETUP_SIZE]; + unsigned int BufferState[I810_DEST_SETUP_SIZE]; + unsigned int TexState[2][I810_TEX_SETUP_SIZE]; + unsigned int dirty; + + unsigned int nbox; + drm_clip_rect_t boxes[I810_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[I810_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? */ + + +} I810SAREARec, *I810SAREAPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} I810ConfigPrivRec, *I810ConfigPrivPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} I810DRIContextRec, *I810DRIContextPtr; + +#endif diff --git a/src/legacy/i810/i810_driver.c b/src/legacy/i810/i810_driver.c new file mode 100644 index 00000000..3fc9d044 --- /dev/null +++ b/src/legacy/i810/i810_driver.c @@ -0,0 +1,2121 @@ + +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + * Add ARGB HW cursor support: + * Alan Hourihane <alanh@tungstengraphics.com> + * + */ + +/* + * This server does not support these XFree86 4.0 features yet + * shadowFb (if requested or acceleration is off) + * Overlay planes + * DGA + */ + +#include <math.h> +#include <string.h> +#include <unistd.h> + +/* + * These are X and server generic header files. + */ +#include "xf86.h" +#include "xf86_OSproc.h" +#include "xf86cmap.h" + +#include "compiler.h" +#include "mibstore.h" +#include "vgaHW.h" +#include "mipointer.h" +#include "micmap.h" + +#include "fb.h" +#include "miscstruct.h" +#include "xf86xv.h" +#include <X11/extensions/Xv.h> +#include "vbe.h" + +#include "i810.h" + +#ifdef XF86DRI +#include "dri.h" +#endif + +#include "../legacy.h" + +static Bool I810PreInit(ScrnInfoPtr pScrn, int flags); +static Bool I810ScreenInit(int Index, ScreenPtr pScreen, int argc, + char **argv); +static Bool I810EnterVT(int scrnIndex, int flags); +static void I810LeaveVT(int scrnIndex, int flags); +static Bool I810CloseScreen(int scrnIndex, ScreenPtr pScreen); +static Bool I810SaveScreen(ScreenPtr pScreen, Bool unblank); +static void I810FreeScreen(int scrnIndex, int flags); +static void I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, + int PowerManagermentMode, + int flags); +static ModeStatus I810ValidMode(int scrnIndex, DisplayModePtr mode, + Bool verbose, int flags); + +typedef enum { + OPTION_NOACCEL, + OPTION_SW_CURSOR, + OPTION_COLOR_KEY, + OPTION_CACHE_LINES, + OPTION_DAC_6BIT, + OPTION_DRI, + OPTION_NO_DDC, + OPTION_SHOW_CACHE, + OPTION_XVMC_SURFACES, + OPTION_PAGEFLIP +} I810Opts; + +static const OptionInfoRec I810Options[] = { + {OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE}, + {OPTION_CACHE_LINES, "CacheLines", OPTV_INTEGER, {0}, FALSE}, + {OPTION_DAC_6BIT, "Dac6Bit", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_NO_DDC, "NoDDC", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_SHOW_CACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE}, + {OPTION_XVMC_SURFACES, "XvMCSurfaces", OPTV_INTEGER, {0}, FALSE}, + {OPTION_PAGEFLIP, "PageFlip", OPTV_BOOLEAN, {0}, FALSE}, + {-1, NULL, OPTV_NONE, {0}, FALSE} +}; +/* *INDENT-ON* */ + +#ifndef I810_DEBUG +int I810_DEBUG = (0 +/* | DEBUG_ALWAYS_SYNC */ +/* | DEBUG_VERBOSE_ACCEL */ +/* | DEBUG_VERBOSE_SYNC */ +/* | DEBUG_VERBOSE_VGA */ +/* | DEBUG_VERBOSE_RING */ +/* | DEBUG_VERBOSE_OUTREG */ +/* | DEBUG_VERBOSE_MEMORY */ +/* | DEBUG_VERBOSE_CURSOR */ + ); +#endif + +#ifdef XF86DRI +static int i810_pitches[] = { + 512, + 1024, + 2048, + 4096, + 0 +}; +#endif + +int I830EntityIndex = -1; + +/* + * I810GetRec and I810FreeRec -- + * + * Private data for the driver is stored in the screen structure. + * These two functions create and destroy that private data. + * + */ +static Bool +I810GetRec(ScrnInfoPtr pScrn) +{ + if (pScrn->driverPrivate) + return TRUE; + + pScrn->driverPrivate = xnfcalloc(sizeof(I810Rec), 1); + return TRUE; +} + +static void +I810FreeRec(ScrnInfoPtr pScrn) +{ + if (!pScrn) + return; + if (!pScrn->driverPrivate) + return; + free(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; +} + +struct pci_device * +intel_host_bridge (void) +{ + static const struct pci_slot_match bridge_match = { + 0, 0, 0, PCI_MATCH_ANY, 0 + }; + struct pci_device_iterator *slot_iterator; + struct pci_device *bridge; + + slot_iterator = pci_slot_match_iterator_create (&bridge_match); + bridge = pci_device_next (slot_iterator); + pci_iterator_destroy (slot_iterator); + return bridge; +} + +static void +I810ProbeDDC(ScrnInfoPtr pScrn, int index) +{ + vbeInfoPtr pVbe; + + if (xf86LoadSubModule(pScrn, "vbe")) { + pVbe = VBEInit(NULL, index); + ConfiguredMonitor = vbeDoEDID(pVbe, NULL); + vbeFree(pVbe); + } +} + +static xf86MonPtr +I810DoDDC(ScrnInfoPtr pScrn, int index) +{ + vbeInfoPtr pVbe; + xf86MonPtr MonInfo = NULL; + I810Ptr pI810 = I810PTR(pScrn); + + /* Honour Option "noDDC" */ + if (xf86ReturnOptValBool(pI810->Options, OPTION_NO_DDC, FALSE)) { + return MonInfo; + } + + if (xf86LoadSubModule(pScrn, "vbe") && (pVbe = VBEInit(NULL, index))) { + MonInfo = vbeDoEDID(pVbe, NULL); + xf86PrintEDID(MonInfo); + xf86SetDDCproperties(pScrn, MonInfo); + vbeFree(pVbe); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "this driver cannot do DDC without VBE\n"); + } + + return MonInfo; +} + +/* + * I810PreInit -- + * + * Do initial setup of the board before we know what resolution we will + * be running at. + * + */ +static Bool +I810PreInit(ScrnInfoPtr pScrn, int flags) +{ + vgaHWPtr hwp; + I810Ptr pI810; + ClockRangePtr clockRanges; + int i; + MessageType from; + int flags24; + rgb defaultWeight = { 0, 0, 0 }; + int mem; + Bool enable; + struct intel_chipset chipset; + + if (pScrn->numEntities != 1) + return FALSE; + + /* Allocate driverPrivate */ + if (!I810GetRec(pScrn)) + return FALSE; + + pI810 = I810PTR(pScrn); + + pI810->pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if (pI810->pEnt->location.type != BUS_PCI) + return FALSE; + + if (flags & PROBE_DETECT) { + I810ProbeDDC(pScrn, pI810->pEnt->index); + return TRUE; + } + + /* The vgahw module should be loaded here when needed */ + if (!xf86LoadSubModule(pScrn, "vgahw")) + return FALSE; + + /* Allocate a vgaHWRec */ + if (!vgaHWGetHWRec(pScrn)) + return FALSE; + hwp = VGAHWPTR(pScrn); + pI810->ioBase = hwp->PIOOffset; + + pI810->PciInfo = xf86GetPciInfoForEntity(pI810->pEnt->index); + + /* Set pScrn->monitor */ + pScrn->monitor = pScrn->confScreen->monitor; + + flags24 = Support24bppFb | PreferConvert32to24 | SupportConvert32to24; + if (!xf86SetDepthBpp(pScrn, 16, 0, 16, flags24)) { + return FALSE; + } else { + switch (pScrn->depth) { + case 8: + case 15: + case 16: + case 24: + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given depth (%d) is not supported by i810 driver\n", + pScrn->depth); + return FALSE; + } + } + xf86PrintDepthBpp(pScrn); + + switch (pScrn->bitsPerPixel) { + case 8: + case 16: + case 24: + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Given bpp (%d) is not supported by i810 driver\n", + pScrn->bitsPerPixel); + return FALSE; + } + + if (!xf86SetWeight(pScrn, defaultWeight, defaultWeight)) + return FALSE; + + if (!xf86SetDefaultVisual(pScrn, -1)) + return FALSE; + + /* We use a programmable clock */ + pScrn->progClock = TRUE; + + pI810->cpp = pScrn->bitsPerPixel / 8; + + /* Process the options */ + xf86CollectOptions(pScrn, NULL); + if (!(pI810->Options = malloc(sizeof(I810Options)))) + return FALSE; + memcpy(pI810->Options, I810Options, sizeof(I810Options)); + xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pI810->Options); + + pScrn->rgbBits = 8; + if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE)) + pScrn->rgbBits = 6; + + if (xf86ReturnOptValBool(pI810->Options, OPTION_SHOW_CACHE, FALSE)) + pI810->showCache = TRUE; + else + pI810->showCache = FALSE; + + /* 6-BIT dac isn't reasonable for modes with > 8bpp */ + if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE) && + pScrn->bitsPerPixel > 8) { + OptionInfoPtr ptr; + + ptr = xf86TokenToOptinfo(pI810->Options, OPTION_DAC_6BIT); + ptr->found = FALSE; + } + + if (xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) + pI810->noAccel = TRUE; + + if (!pI810->noAccel) { + if (!xf86LoadSubModule(pScrn, "xaa")) { + I810FreeRec(pScrn); + return FALSE; + } + } + +#ifdef XF86DRI + pI810->directRenderingDisabled = + !xf86ReturnOptValBool(pI810->Options, OPTION_DRI, TRUE); + + if (!pI810->directRenderingDisabled) { + if (pI810->noAccel) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it " + "needs 2D acceleration.\n"); + pI810->directRenderingDisabled=TRUE; + } else if (pScrn->depth!=16) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI is disabled because it " + "runs only at 16-bit depth.\n"); + pI810->directRenderingDisabled=TRUE; + } + } +#endif + + /* Get DDC info from monitor */ + /* after xf86ProcessOptions, + * because it is controlled by options [no]vbe and [no]ddc + */ + I810DoDDC(pScrn, pI810->pEnt->index); + + /* We have to use PIO to probe, because we haven't mapped yet */ + I810SetPIOAccess(pI810); + + intel_detect_chipset(pScrn, pI810->PciInfo, &chipset); + + /* + * Set the Chipset and ChipRev, allowing config file entries to + * override. + */ + if (pI810->pEnt->device->chipset && *pI810->pEnt->device->chipset) { + pScrn->chipset = pI810->pEnt->device->chipset; + from = X_CONFIG; + } else if (pI810->pEnt->device->chipID >= 0) { + pScrn->chipset = (char *)xf86TokenToString(intel_chipsets, + pI810->pEnt->device->chipID); + from = X_CONFIG; + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n", + pI810->pEnt->device->chipID); + } else { + from = X_PROBED; + pScrn->chipset = (char *)xf86TokenToString(intel_chipsets, + DEVICE_ID(pI810->PciInfo)); + } + if (pI810->pEnt->device->chipRev >= 0) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", + pI810->pEnt->device->chipRev); + } + + xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", + (pScrn->chipset != NULL) ? pScrn->chipset : "Unknown i810"); + + pI810->LinearAddr = pI810->PciInfo->regions[0].base_addr; + xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n", + (unsigned long)pI810->LinearAddr); + + pI810->MMIOAddr = pI810->PciInfo->regions[1].base_addr; + xf86DrvMsg(pScrn->scrnIndex, from, "IO registers at addr 0x%lX\n", + (unsigned long)pI810->MMIOAddr); + + /* AGP GART support is required. Don't proceed any further if it isn't + * present. + */ + if (!xf86AgpGARTSupported()) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "AGP GART support is not available. Make sure your kernel has\n" + "\tagpgart support or that the agpgart kernel module is loaded.\n"); + return FALSE; + } + + /* Find out memory bus frequency. + */ + { + uint32_t whtcfg_pamr_drp; + + pci_device_cfg_read_u32(pI810->PciInfo, & whtcfg_pamr_drp, WHTCFG_PAMR_DRP); + + /* Need this for choosing watermarks. + */ + if ((whtcfg_pamr_drp & LM_FREQ_MASK) == LM_FREQ_133) + pI810->LmFreqSel = 133; + else + pI810->LmFreqSel = 100; + } + + /* Default to 4MB framebuffer, which is sufficient for all + * supported 2d resolutions. If the user has specified a different + * size in the XF86Config, use that amount instead. + * + * Changed to 8 Meg so we can have acceleration by default (Mark). + */ + mem = I810CheckAvailableMemory(pScrn); + if (pI810->directRenderingDisabled || mem < 131072) /* < 128 MB */ + pScrn->videoRam = 8192; + else if (mem < 196608) + pScrn->videoRam = 16384; /* < 192 MB */ + else + pScrn->videoRam = 24576; + + from = X_DEFAULT; + + if (pI810->pEnt->device->videoRam) { + pScrn->videoRam = pI810->pEnt->device->videoRam; + from = X_CONFIG; + } + + if (mem > 0 && mem < pScrn->videoRam) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%dk of memory was requested," + " but the\n\t maximum AGP memory available is %dk.\n", + pScrn->videoRam, mem); + from = X_PROBED; + if (mem > (6 * 1024)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Reducing video memory to 4MB\n"); + pScrn->videoRam = 4096; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Less than 6MB of AGP memory" + " is available. Cannot proceed.\n"); + I810FreeRec(pScrn); + return FALSE; + } + } + + xf86DrvMsg(pScrn->scrnIndex, from, + "Will alloc AGP framebuffer: %d kByte\n", pScrn->videoRam); + + /* Calculate Fixed Offsets depending on graphics aperture size */ + { + struct pci_device *bridge = intel_host_bridge (); + uint32_t smram_miscc; + + pci_device_cfg_read_u32 (bridge, & smram_miscc, SMRAM_MISCC); + + if ((smram_miscc & GFX_MEM_WIN_SIZE) == GFX_MEM_WIN_32M) { + pI810->FbMapSize = 0x1000000; + pI810->DepthOffset = 0x1000000; + pI810->BackOffset = 0x1800000; + } else { + pI810->FbMapSize = 0x3000000; + pI810->DepthOffset = 0x3000000; + pI810->BackOffset = 0x3800000; + } + } + + /* + * 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; + } + } + + pI810->MaxClock = 0; + if (pI810->pEnt->device->dacSpeeds[0]) { + switch (pScrn->bitsPerPixel) { + case 8: + pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP8]; + break; + case 16: + pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP16]; + break; + case 24: + pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP24]; + break; + case 32: /* not supported */ + pI810->MaxClock = pI810->pEnt->device->dacSpeeds[DAC_BPP32]; + break; + } + if (!pI810->MaxClock) + pI810->MaxClock = pI810->pEnt->device->dacSpeeds[0]; + } else { + switch (pScrn->bitsPerPixel) { + case 8: + pI810->MaxClock = 203000; + break; + case 16: + pI810->MaxClock = 163000; + break; + case 24: + pI810->MaxClock = 136000; + break; + case 32: /* not supported */ + pI810->MaxClock = 86000; + } + } + clockRanges = xnfcalloc(sizeof(ClockRange), 1); + clockRanges->next = NULL; + /* 9.4MHz appears to be the smallest that works. */ + clockRanges->minClock = 9500; + clockRanges->maxClock = pI810->MaxClock; + clockRanges->clockIndex = -1; + clockRanges->interlaceAllowed = TRUE; + clockRanges->doubleScanAllowed = FALSE; + + i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, + pScrn->display->modes, clockRanges, +#ifndef XF86DRI + 0, 320, 1600, 64 * pScrn->bitsPerPixel, +#else + i810_pitches, 0, 0, 64 * pScrn->bitsPerPixel, +#endif + 200, 1200, + pScrn->display->virtualX, pScrn->display->virtualY, + pScrn->videoRam * 1024, LOOKUP_BEST_REFRESH); + + if (i == -1) { + I810FreeRec(pScrn); + return FALSE; + } + + xf86PruneDriverModes(pScrn); + + if (!i || !pScrn->modes) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); + I810FreeRec(pScrn); + return FALSE; + } + + xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); + + pScrn->currentMode = pScrn->modes; + + xf86PrintModes(pScrn); + + xf86SetDpi(pScrn, 0, 0); + + if (!xf86LoadSubModule(pScrn, "fb")) { + I810FreeRec(pScrn); + return FALSE; + } + + if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) { + if (!xf86LoadSubModule(pScrn, "ramdac")) { + I810FreeRec(pScrn); + return FALSE; + } + } + + if (xf86GetOptValInteger + (pI810->Options, OPTION_COLOR_KEY, &(pI810->colorKey))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "video overlay key set to 0x%x\n", pI810->colorKey); + } else { + pI810->colorKey = (1 << pScrn->offset.red) | + (1 << pScrn->offset.green) | + (((pScrn->mask.blue >> pScrn->offset.blue) - + 1) << pScrn->offset.blue); + } + + pI810->allowPageFlip=FALSE; + enable = xf86ReturnOptValBool(pI810->Options, OPTION_PAGEFLIP, FALSE); + +#ifdef XF86DRI + if (!pI810->directRenderingDisabled) { + pI810->allowPageFlip = enable; + if (pI810->allowPageFlip == TRUE) + { + if (!xf86LoadSubModule(pScrn, "shadowfb")) { + pI810->allowPageFlip = 0; + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't load shadowfb module:\n"); + } + } + + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n", + enable ? "enabled" : "disabled"); + + } +#endif + + if (xf86GetOptValInteger(pI810->Options, OPTION_XVMC_SURFACES, + &(pI810->numSurfaces))) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "%d XvMC Surfaces Requested.\n", + pI810->numSurfaces); + if (pI810->numSurfaces > 7) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Using 7 XvMC Surfaces (Maximum Allowed).\n"); + pI810->numSurfaces = 7; + } + if (pI810->numSurfaces < 6) { + xf86DrvMsg(pScrn->scrnIndex, X_PROBED, + "Using 6 XvMC Surfaces (Minimum Allowed).\n"); + pI810->numSurfaces = 6; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "XvMC is Disabled: use XvMCSurfaces config option to enable.\n"); + pI810->numSurfaces = 0; + } + +#ifdef XF86DRI + /* Load the dri module if requested. */ + if (xf86ReturnOptValBool(pI810->Options, OPTION_DRI, FALSE)) { + xf86LoadSubModule(pScrn, "dri"); + } +#endif + + /* We won't be using the VGA access after the probe */ + I810SetMMIOAccess(pI810); + return TRUE; +} + +static Bool +I810MapMMIO(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + struct pci_device *const device = pI810->PciInfo; + int err; + + err = pci_device_map_range (device, + pI810->MMIOAddr, + I810_REG_SIZE, + PCI_DEV_MAP_FLAG_WRITABLE, + (void **) &pI810->MMIOBase); + if (err) + { + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + "Unable to map mmio BAR. %s (%d)\n", + strerror (err), err); + return FALSE; + } + return TRUE; +} + +static Bool +I810MapMem(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + struct pci_device *const device = pI810->PciInfo; + int err; + + if (!I810MapMMIO(pScrn)) + return FALSE; + + err = pci_device_map_range (device, + pI810->LinearAddr, + pI810->FbMapSize, + PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE, + (void **) &pI810->FbBase); + if (err) + { + xf86DrvMsg (pScrn->scrnIndex, X_ERROR, + "Unable to map frame buffer BAR. %s (%d)\n", + strerror (err), err); + return FALSE; + } + + pI810->LpRing->virtual_start = pI810->FbBase + pI810->LpRing->mem.Start; + + return TRUE; +} + +static void +I810UnmapMMIO(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + pci_device_unmap_range (pI810->PciInfo, pI810->MMIOBase, I810_REG_SIZE); + pI810->MMIOBase = NULL; +} + +static Bool +I810UnmapMem(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + pci_device_unmap_range (pI810->PciInfo, pI810->FbBase, pI810->FbMapSize); + pI810->FbBase = NULL; + I810UnmapMMIO(pScrn); + return TRUE; +} + +/* Famous last words + */ +void +I810PrintErrorState(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + ErrorF("pgetbl_ctl: 0x%lx pgetbl_err: 0x%lx\n", + (unsigned long) INREG(PGETBL_CTL), (unsigned long) INREG(PGE_ERR)); + + ErrorF("ipeir: %lx iphdr: %lx\n", (unsigned long) INREG(IPEIR), + (unsigned long) INREG(IPEHR)); + + ErrorF("LP ring tail: %lx head: %lx len: %lx start %lx\n", + (unsigned long) INREG(LP_RING + RING_TAIL), + (unsigned long) INREG(LP_RING + RING_HEAD) & HEAD_ADDR, + (unsigned long) INREG(LP_RING + RING_LEN), + (unsigned long) INREG(LP_RING + RING_START)); + + ErrorF("eir: %x esr: %x emr: %x\n", + INREG16(EIR), INREG16(ESR), INREG16(EMR)); + + ErrorF("instdone: %x instpm: %x\n", INREG16(INST_DONE), INREG8(INST_PM)); + + ErrorF("memmode: %lx instps: %lx\n", (unsigned long) INREG(MEMMODE), + (unsigned long) INREG(INST_PS)); + + ErrorF("hwstam: %x ier: %x imr: %x iir: %x\n", + INREG16(HWSTAM), INREG16(IER), INREG16(IMR), INREG16(IIR)); +} + +/* + * I810Save -- + * + * This function saves the video state. It reads all of the SVGA registers + * into the vgaI810Rec data structure. There is in general no need to + * mask out bits here - just read the registers. + */ +static void +DoSave(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, + Bool saveFonts) +{ + I810Ptr pI810; + vgaHWPtr hwp; + int i; + + pI810 = I810PTR(pScrn); + hwp = VGAHWPTR(pScrn); + + /* + * This function will handle creating the data structure and filling + * in the generic VGA portion. + */ + if (saveFonts) + vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_FONTS | VGA_SR_CMAP); + else + vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); + + /* + * The port I/O code necessary to read in the extended registers + * into the fields of the vgaI810Rec structure goes here. + */ + i810Reg->IOControl = hwp->readCrtc(hwp, IO_CTNL); + i810Reg->AddressMapping = pI810->readControl(pI810, GRX, ADDRESS_MAPPING); + i810Reg->BitBLTControl = INREG8(BITBLT_CNTL); + i810Reg->VideoClk2_M = INREG16(VCLK2_VCO_M); + i810Reg->VideoClk2_N = INREG16(VCLK2_VCO_N); + i810Reg->VideoClk2_DivisorSel = INREG8(VCLK2_VCO_DIV_SEL); + + i810Reg->ExtVertTotal = hwp->readCrtc(hwp, EXT_VERT_TOTAL); + i810Reg->ExtVertDispEnd = hwp->readCrtc(hwp, EXT_VERT_DISPLAY); + i810Reg->ExtVertSyncStart = hwp->readCrtc(hwp, EXT_VERT_SYNC_START); + i810Reg->ExtVertBlankStart = hwp->readCrtc(hwp, EXT_VERT_BLANK_START); + i810Reg->ExtHorizTotal = hwp->readCrtc(hwp, EXT_HORIZ_TOTAL); + i810Reg->ExtHorizBlank = hwp->readCrtc(hwp, EXT_HORIZ_BLANK); + i810Reg->ExtOffset = hwp->readCrtc(hwp, EXT_OFFSET); + i810Reg->InterlaceControl = hwp->readCrtc(hwp, INTERLACE_CNTL); + + i810Reg->PixelPipeCfg0 = INREG8(PIXPIPE_CONFIG_0); + i810Reg->PixelPipeCfg1 = INREG8(PIXPIPE_CONFIG_1); + i810Reg->PixelPipeCfg2 = INREG8(PIXPIPE_CONFIG_2); + i810Reg->DisplayControl = INREG8(DISPLAY_CNTL); + i810Reg->LMI_FIFO_Watermark = INREG(FWATER_BLC); + + for (i = 0; i < 8; i++) + i810Reg->Fence[i] = INREG(FENCE + i * 4); + + i810Reg->LprbTail = INREG(LP_RING + RING_TAIL); + i810Reg->LprbHead = INREG(LP_RING + RING_HEAD); + i810Reg->LprbStart = INREG(LP_RING + RING_START); + i810Reg->LprbLen = INREG(LP_RING + RING_LEN); + + if ((i810Reg->LprbTail & TAIL_ADDR) != (i810Reg->LprbHead & HEAD_ADDR) && + i810Reg->LprbLen & RING_VALID) { + I810PrintErrorState(pScrn); + FatalError("Active ring not flushed\n"); + } +} + +static void +I810Save(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp; + I810Ptr pI810; + uint32_t temp; + + hwp = VGAHWPTR(pScrn); + pI810 = I810PTR(pScrn); + DoSave(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE); + + temp = INREG(MEMMODE); + temp |= 4; + OUTREG(MEMMODE, temp); +} + +static void +i810PrintMode(vgaRegPtr vgaReg, I810RegPtr mode) +{ + int i; + + ErrorF(" MiscOut: %x\n", vgaReg->MiscOutReg); + + ErrorF("SEQ: "); + for (i = 0; i < vgaReg->numSequencer; i++) { + if ((i & 7) == 0) + ErrorF("\n"); + ErrorF(" %d: %x", i, vgaReg->Sequencer[i]); + } + ErrorF("\n"); + + ErrorF("CRTC: "); + for (i = 0; i < vgaReg->numCRTC; i++) { + if ((i & 3) == 0) + ErrorF("\n"); + ErrorF(" %d: %x", i, vgaReg->CRTC[i]); + } + ErrorF("\n"); + + ErrorF("GFX: "); + for (i = 0; i < vgaReg->numGraphics; i++) { + if ((i & 7) == 0) + ErrorF("\n"); + ErrorF(" %d: %x", i, vgaReg->Graphics[i]); + } + ErrorF("\n"); + + ErrorF("ATTR: "); + for (i = 0; i < vgaReg->numAttribute; i++) { + if ((i & 7) == 0) + ErrorF("\n"); + ErrorF(" %d: %x", i, vgaReg->Attribute[i]); + } + ErrorF("\n"); + + ErrorF(" DisplayControl: %x\n", mode->DisplayControl); + ErrorF(" PixelPipeCfg0: %x\n", mode->PixelPipeCfg0); + ErrorF(" PixelPipeCfg1: %x\n", mode->PixelPipeCfg1); + ErrorF(" PixelPipeCfg2: %x\n", mode->PixelPipeCfg2); + ErrorF(" VideoClk2_M: %x\n", mode->VideoClk2_M); + ErrorF(" VideoClk2_N: %x\n", mode->VideoClk2_N); + ErrorF(" VideoClk2_DivisorSel: %x\n", mode->VideoClk2_DivisorSel); + ErrorF(" AddressMapping: %x\n", mode->AddressMapping); + ErrorF(" IOControl: %x\n", mode->IOControl); + ErrorF(" BitBLTControl: %x\n", mode->BitBLTControl); + ErrorF(" ExtVertTotal: %x\n", mode->ExtVertTotal); + ErrorF(" ExtVertDispEnd: %x\n", mode->ExtVertDispEnd); + ErrorF(" ExtVertSyncStart: %x\n", mode->ExtVertSyncStart); + ErrorF(" ExtVertBlankStart: %x\n", mode->ExtVertBlankStart); + ErrorF(" ExtHorizTotal: %x\n", mode->ExtHorizTotal); + ErrorF(" ExtHorizBlank: %x\n", mode->ExtHorizBlank); + ErrorF(" ExtOffset: %x\n", mode->ExtOffset); + ErrorF(" InterlaceControl: %x\n", mode->InterlaceControl); + ErrorF(" LMI_FIFO_Watermark: %x\n", mode->LMI_FIFO_Watermark); + ErrorF(" LprbTail: %x\n", mode->LprbTail); + ErrorF(" LprbHead: %x\n", mode->LprbHead); + ErrorF(" LprbStart: %x\n", mode->LprbStart); + ErrorF(" LprbLen: %x\n", mode->LprbLen); +} + +static void +DoRestore(ScrnInfoPtr pScrn, vgaRegPtr vgaReg, I810RegPtr i810Reg, + Bool restoreFonts) +{ + I810Ptr pI810; + vgaHWPtr hwp; + unsigned char temp; + unsigned int itemp; + int i; + + pI810 = I810PTR(pScrn); + hwp = VGAHWPTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_VGA) { + ErrorF("Setting mode in I810Restore:\n"); + i810PrintMode(vgaReg, i810Reg); + } + + vgaHWProtect(pScrn, TRUE); + + usleep(50000); + + /* Turn off DRAM Refresh */ + temp = INREG8(DRAM_ROW_CNTL_HI); + temp &= ~DRAM_REFRESH_RATE; + temp |= DRAM_REFRESH_DISABLE; + OUTREG8(DRAM_ROW_CNTL_HI, temp); + + usleep(1000); /* Wait 1 ms */ + + /* Write the M, N and P values */ + OUTREG16(VCLK2_VCO_M, i810Reg->VideoClk2_M); + OUTREG16(VCLK2_VCO_N, i810Reg->VideoClk2_N); + OUTREG8(VCLK2_VCO_DIV_SEL, i810Reg->VideoClk2_DivisorSel); + + /* + * Turn on 8 bit dac mode, if requested. This is needed to make + * sure that vgaHWRestore writes the values into the DAC properly. + * The problem occurs if 8 bit dac mode is requested and the HW is + * in 6 bit dac mode. If this happens, all the values are + * automatically shifted left twice by the HW and incorrect colors + * will be displayed on the screen. The only time this can happen + * is at server startup time and when switching back from a VT. + */ + temp = INREG8(PIXPIPE_CONFIG_0); + temp &= 0x7F; /* Save all but the 8 bit dac mode bit */ + temp |= (i810Reg->PixelPipeCfg0 & DAC_8_BIT); + OUTREG8(PIXPIPE_CONFIG_0, temp); + + /* + * Code to restore any SVGA registers that have been saved/modified + * goes here. Note that it is allowable, and often correct, to + * only modify certain bits in a register by a read/modify/write cycle. + * + * A special case - when using an external clock-setting program, + * this function must not change bits associated with the clock + * selection. This condition can be checked by the condition: + * + * if (i810Reg->std.NoClock >= 0) + * restore clock-select bits. + */ + if (restoreFonts) + vgaHWRestore(pScrn, vgaReg, VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP); + else + vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); + + hwp->writeCrtc(hwp, EXT_VERT_TOTAL, i810Reg->ExtVertTotal); + hwp->writeCrtc(hwp, EXT_VERT_DISPLAY, i810Reg->ExtVertDispEnd); + hwp->writeCrtc(hwp, EXT_VERT_SYNC_START, i810Reg->ExtVertSyncStart); + hwp->writeCrtc(hwp, EXT_VERT_BLANK_START, i810Reg->ExtVertBlankStart); + hwp->writeCrtc(hwp, EXT_HORIZ_TOTAL, i810Reg->ExtHorizTotal); + hwp->writeCrtc(hwp, EXT_HORIZ_BLANK, i810Reg->ExtHorizBlank); + hwp->writeCrtc(hwp, EXT_OFFSET, i810Reg->ExtOffset); + + temp = hwp->readCrtc(hwp, INTERLACE_CNTL); + temp &= ~INTERLACE_ENABLE; + temp |= i810Reg->InterlaceControl; + hwp->writeCrtc(hwp, INTERLACE_CNTL, temp); + + temp = pI810->readControl(pI810, GRX, ADDRESS_MAPPING); + temp &= 0xE0; /* Save reserved bits 7:5 */ + temp |= i810Reg->AddressMapping; + pI810->writeControl(pI810, GRX, ADDRESS_MAPPING, temp); + + /* Setting the OVRACT Register for video overlay */ + { + uint32_t LCD_TV_Control = INREG(LCD_TV_C); + uint32_t TV_HTotal = INREG(LCD_TV_HTOTAL); + uint32_t ActiveStart, ActiveEnd; + + if((LCD_TV_Control & LCD_TV_ENABLE) + && !(LCD_TV_Control & LCD_TV_VGAMOD) + && TV_HTotal) { + ActiveStart = ((TV_HTotal >> 16) & 0xfff) - 31; + ActiveEnd = (TV_HTotal & 0x3ff) - 31; + } else { + ActiveStart = i810Reg->OverlayActiveStart; + ActiveEnd = i810Reg->OverlayActiveEnd; + } + OUTREG(LCD_TV_OVRACT, + (ActiveEnd << 16) | ActiveStart); + } + + /* Turn on DRAM Refresh */ + temp = INREG8(DRAM_ROW_CNTL_HI); + temp &= ~DRAM_REFRESH_RATE; + temp |= DRAM_REFRESH_60HZ; + OUTREG8(DRAM_ROW_CNTL_HI, temp); + + temp = INREG8(BITBLT_CNTL); + temp &= ~COLEXP_MODE; + temp |= i810Reg->BitBLTControl; + OUTREG8(BITBLT_CNTL, temp); + + temp = INREG8(DISPLAY_CNTL); + temp &= ~(VGA_WRAP_MODE | GUI_MODE); + temp |= i810Reg->DisplayControl; + OUTREG8(DISPLAY_CNTL, temp); + + temp = INREG8(PIXPIPE_CONFIG_0); + temp &= 0x64; /* Save reserved bits 6:5,2 */ + temp |= i810Reg->PixelPipeCfg0; + OUTREG8(PIXPIPE_CONFIG_0, temp); + + temp = INREG8(PIXPIPE_CONFIG_2); + temp &= 0xF3; /* Save reserved bits 7:4,1:0 */ + temp |= i810Reg->PixelPipeCfg2; + OUTREG8(PIXPIPE_CONFIG_2, temp); + + temp = INREG8(PIXPIPE_CONFIG_1); + temp &= ~DISPLAY_COLOR_MODE; + temp &= 0xEF; /* Restore the CRT control bit */ + temp |= i810Reg->PixelPipeCfg1; + OUTREG8(PIXPIPE_CONFIG_1, temp); + + OUTREG16(EIR, 0); + + itemp = INREG(FWATER_BLC); + itemp &= ~(LM_BURST_LENGTH | LM_FIFO_WATERMARK | + MM_BURST_LENGTH | MM_FIFO_WATERMARK); + itemp |= i810Reg->LMI_FIFO_Watermark; + OUTREG(FWATER_BLC, itemp); + + for (i = 0; i < 8; i++) { + OUTREG(FENCE + i * 4, i810Reg->Fence[i]); + if (I810_DEBUG & DEBUG_VERBOSE_VGA) + ErrorF("Fence Register : %x\n", i810Reg->Fence[i]); + } + + /* First disable the ring buffer (Need to wait for empty first?, if so + * should probably do it before entering this section) + */ + itemp = INREG(LP_RING + RING_LEN); + itemp &= ~RING_VALID_MASK; + OUTREG(LP_RING + RING_LEN, itemp); + + /* Set up the low priority ring buffer. + */ + OUTREG(LP_RING + RING_TAIL, 0); + OUTREG(LP_RING + RING_HEAD, 0); + + pI810->LpRing->head = 0; + pI810->LpRing->tail = 0; + + itemp = INREG(LP_RING + RING_START); + itemp &= ~(START_ADDR); + itemp |= i810Reg->LprbStart; + OUTREG(LP_RING + RING_START, itemp); + + itemp = INREG(LP_RING + RING_LEN); + itemp &= ~(RING_NR_PAGES | RING_REPORT_MASK | RING_VALID_MASK); + itemp |= i810Reg->LprbLen; + OUTREG(LP_RING + RING_LEN, itemp); + + if (!(vgaReg->Attribute[0x10] & 0x1)) { + usleep(50000); + if (restoreFonts) + vgaHWRestore(pScrn, vgaReg, + VGA_SR_FONTS | VGA_SR_MODE | VGA_SR_CMAP); + else + vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP); + } + + vgaHWProtect(pScrn, FALSE); + + temp = hwp->readCrtc(hwp, IO_CTNL); + temp &= ~(EXTENDED_ATTR_CNTL | EXTENDED_CRTC_CNTL); + temp |= i810Reg->IOControl; + hwp->writeCrtc(hwp, IO_CTNL, temp); +} + +static void +I810SetRingRegs(ScrnInfoPtr pScrn) +{ + unsigned int itemp; + I810Ptr pI810 = I810PTR(pScrn); + + OUTREG(LP_RING + RING_TAIL, 0); + OUTREG(LP_RING + RING_HEAD, 0); + + itemp = INREG(LP_RING + RING_START); + itemp &= ~(START_ADDR); + 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); + OUTREG(LP_RING + RING_LEN, itemp); +} + +static void +I810Restore(ScrnInfoPtr pScrn) +{ + vgaHWPtr hwp; + I810Ptr pI810; + + hwp = VGAHWPTR(pScrn); + pI810 = I810PTR(pScrn); + + DoRestore(pScrn, &hwp->SavedReg, &pI810->SavedReg, TRUE); +} + +/* + * I810CalcVCLK -- + * + * Determine the closest clock frequency to the one requested. + */ + +#define MAX_VCO_FREQ 600.0 +#define TARGET_MAX_N 30 +#define REF_FREQ 24.0 + +#define CALC_VCLK(m,n,p) \ + (double)m / ((double)n * (1 << p)) * 4 * REF_FREQ + +static void +I810CalcVCLK(ScrnInfoPtr pScrn, double freq) +{ + I810Ptr pI810 = I810PTR(pScrn); + I810RegPtr i810Reg = &pI810->ModeReg; + int m, n, p; + double f_out; + double f_err; + double f_vco; + int m_best = 0, n_best = 0, p_best = 0; + double f_target = freq; + double err_max = 0.005; + double err_target = 0.001; + double err_best = 999999.0; + + p_best = p = log(MAX_VCO_FREQ / f_target) / log((double)2); + /* Make sure p is within range. */ + if (p_best > 5) { + p_best = p = 5; + } + + f_vco = f_target * (1 << p); + + n = 2; + do { + n++; + m = f_vco / (REF_FREQ / (double)n) / (double)4.0 + 0.5; + if (m < 3) + m = 3; + f_out = CALC_VCLK(m, n, p); + f_err = 1.0 - (f_target / f_out); + if (fabs(f_err) < err_max) { + m_best = m; + n_best = n; + err_best = f_err; + } + } while ((fabs(f_err) >= err_target) && + ((n <= TARGET_MAX_N) || (fabs(err_best) > err_max))); + + if (fabs(f_err) < err_target) { + m_best = m; + n_best = n; + } + + i810Reg->VideoClk2_M = (m_best - 2) & 0x3FF; + i810Reg->VideoClk2_N = (n_best - 2) & 0x3FF; + i810Reg->VideoClk2_DivisorSel = (p_best << 4); + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "Setting dot clock to %.1f MHz " "[ 0x%x 0x%x 0x%x ] " + "[ %d %d %d ]\n", CALC_VCLK(m_best, n_best, p_best), + i810Reg->VideoClk2_M, i810Reg->VideoClk2_N, + i810Reg->VideoClk2_DivisorSel, m_best, n_best, p_best); +} + +static Bool +I810SetMode(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + I810Ptr pI810 = I810PTR(pScrn); + I810RegPtr i810Reg = &pI810->ModeReg; + vgaRegPtr pVga = &VGAHWPTR(pScrn)->ModeReg; + double dclk = mode->Clock / 1000.0; + + switch (pScrn->bitsPerPixel) { + case 8: + pVga->CRTC[0x13] = pScrn->displayWidth >> 3; + i810Reg->ExtOffset = pScrn->displayWidth >> 11; + i810Reg->PixelPipeCfg1 = DISPLAY_8BPP_MODE; + i810Reg->BitBLTControl = COLEXP_8BPP; + break; + case 16: + if (pScrn->weight.green == 5) { + i810Reg->PixelPipeCfg1 = DISPLAY_15BPP_MODE; + } else { + i810Reg->PixelPipeCfg1 = DISPLAY_16BPP_MODE; + } + pVga->CRTC[0x13] = pScrn->displayWidth >> 2; + i810Reg->ExtOffset = pScrn->displayWidth >> 10; + i810Reg->BitBLTControl = COLEXP_16BPP; + + /* Enable Palette Programming for Direct Color visuals. -jens */ + i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE; + break; + case 24: + pVga->CRTC[0x13] = (pScrn->displayWidth * 3) >> 3; + i810Reg->ExtOffset = (pScrn->displayWidth * 3) >> 11; + + i810Reg->PixelPipeCfg1 = DISPLAY_24BPP_MODE; + i810Reg->BitBLTControl = COLEXP_24BPP; + + /* Enable Palette Programming for Direct Color visuals. -jens */ + i810Reg->PixelPipeCfg2 = DISPLAY_GAMMA_ENABLE; + break; + default: + break; + } + + /* Turn on 8 bit dac if requested */ + if (xf86ReturnOptValBool(pI810->Options, OPTION_DAC_6BIT, FALSE)) + i810Reg->PixelPipeCfg0 = DAC_6_BIT; + else + i810Reg->PixelPipeCfg0 = DAC_8_BIT; + + /* Do not delay CRT Blank: needed for video overlay */ + i810Reg->PixelPipeCfg1 |= 0x10; + + /* Turn on Extended VGA Interpretation */ + i810Reg->IOControl = EXTENDED_CRTC_CNTL; + + /* Turn on linear and page mapping */ + i810Reg->AddressMapping = (LINEAR_MODE_ENABLE | GTT_MEM_MAP_ENABLE); + + /* Turn on GUI mode */ + i810Reg->DisplayControl = HIRES_MODE; + + /* Calculate the extended CRTC regs */ + i810Reg->ExtVertTotal = (mode->CrtcVTotal - 2) >> 8; + i810Reg->ExtVertDispEnd = (mode->CrtcVDisplay - 1) >> 8; + i810Reg->ExtVertSyncStart = mode->CrtcVSyncStart >> 8; + i810Reg->ExtVertBlankStart = mode->CrtcVBlankStart >> 8; + i810Reg->ExtHorizTotal = ((mode->CrtcHTotal >> 3) - 5) >> 8; + i810Reg->ExtHorizBlank = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 6; + + /* + * the KGA fix in vgaHW.c results in the first + * scanline and the first character clock (8 pixels) + * of each scanline thereafter on display with an i810 + * to be blank. Restoring CRTC 3, 5, & 22 to their + * "theoretical" values corrects the problem. KAO. + */ + pVga->CRTC[3] = (((mode->CrtcHBlankEnd >> 3) - 1) & 0x1F) | 0x80; + pVga->CRTC[5] = ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x20) << 2) + | (((mode->CrtcHSyncEnd >> 3)) & 0x1F); + pVga->CRTC[22] = (mode->CrtcVBlankEnd - 1) & 0xFF; + + i810Reg->ExtHorizBlank = vgaHWHBlankKGA(mode, pVga, 7, 0); + vgaHWVBlankKGA(mode, pVga, 8, 0); + + /* + * The following workarounds are needed to get video overlay working + * at 1024x768 and 1280x1024 display resolutions. + */ + if ((mode->CrtcVDisplay == 768) && (i810Reg->ExtVertBlankStart == 3)) { + i810Reg->ExtVertBlankStart = 2; + } + if ((mode->CrtcVDisplay == 1024) && (i810Reg->ExtVertBlankStart == 4)) { + i810Reg->ExtVertBlankStart = 3; + } + + /* OVRACT Register */ + i810Reg->OverlayActiveStart = mode->CrtcHTotal - 32; + i810Reg->OverlayActiveEnd = mode->CrtcHDisplay - 32; + + /* Turn on interlaced mode if necessary */ + if (mode->Flags & V_INTERLACE) { + i810Reg->InterlaceControl = INTERLACE_ENABLE; + i810Reg->ExtVertDispEnd *= 2; + } else + i810Reg->InterlaceControl = INTERLACE_DISABLE; + + /* + * Set the overscan color to 0. + * NOTE: This only affects >8bpp mode. + */ + pVga->Attribute[0x11] = 0; + + /* + * Calculate the VCLK that most closely matches the requested dot + * clock. + */ + I810CalcVCLK(pScrn, dclk); + + /* Since we program the clocks ourselves, always use VCLK2. */ + pVga->MiscOutReg |= 0x0C; + + /* Calculate the FIFO Watermark and Burst Length. */ + i810Reg->LMI_FIFO_Watermark = I810CalcWatermark(pScrn, dclk, FALSE); + + /* Setup the ring buffer */ + i810Reg->LprbTail = 0; + i810Reg->LprbHead = 0; + i810Reg->LprbStart = pI810->LpRing->mem.Start; + + if (i810Reg->LprbStart) + i810Reg->LprbLen = ((pI810->LpRing->mem.Size - 4096) | + RING_NO_REPORT | RING_VALID); + else + i810Reg->LprbLen = RING_INVALID; + + return TRUE; +} + +static Bool +I810ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) +{ + vgaHWPtr hwp; + I810Ptr pI810; + + hwp = VGAHWPTR(pScrn); + pI810 = I810PTR(pScrn); + + vgaHWUnlock(hwp); + + if (!vgaHWInit(pScrn, mode)) + return FALSE; + + pScrn->vtSema = TRUE; + + if (!I810SetMode(pScrn, mode)) + return FALSE; + +#ifdef XF86DRI + if (pI810->directRenderingEnabled) { + DRILock(screenInfo.screens[pScrn->scrnIndex], 0); + pI810->LockHeld = 1; + } +#endif + + DoRestore(pScrn, &hwp->ModeReg, &pI810->ModeReg, FALSE); + +#ifdef XF86DRI + if (pI810->directRenderingEnabled) { + DRIUnlock(screenInfo.screens[pScrn->scrnIndex]); + pI810->LockHeld = 0; + } +#endif + + return TRUE; +} + +static void +I810LoadPalette15(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO * colors, VisualPtr pVisual) +{ + vgaHWPtr hwp; + int i, j, index; + unsigned char r, g, b; + + hwp = VGAHWPTR(pScrn); + + for (i = 0; i < numColors; i++) { + index = indices[i]; + r = colors[index].red; + g = colors[index].green; + b = colors[index].blue; + for (j = 0; j < 8; j++) { + hwp->writeDacWriteAddr(hwp, (index << 3) + j); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + } + } +} + +static void +I810LoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO * colors, VisualPtr pVisual) +{ + vgaHWPtr hwp; + int i, index; + unsigned char r, g, b; + + hwp = VGAHWPTR(pScrn); + + /* Load all four entries in each of the 64 color ranges. -jens */ + for (i = 0; i < numColors; i++) { + index = indices[i / 2]; + r = colors[index].red; + b = colors[index].blue; + index = indices[i]; + g = colors[index].green; + + hwp->writeDacWriteAddr(hwp, index << 2); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + + hwp->writeDacWriteAddr(hwp, (index << 2) + 1); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + + hwp->writeDacWriteAddr(hwp, (index << 2) + 2); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + + hwp->writeDacWriteAddr(hwp, (index << 2) + 3); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + + i++; + index = indices[i]; + g = colors[index].green; + + hwp->writeDacWriteAddr(hwp, index << 2); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + + hwp->writeDacWriteAddr(hwp, (index << 2) + 1); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + + hwp->writeDacWriteAddr(hwp, (index << 2) + 2); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + + hwp->writeDacWriteAddr(hwp, (index << 2) + 3); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + } +} + +static void +I810LoadPalette24(ScrnInfoPtr pScrn, int numColors, int *indices, + LOCO * colors, VisualPtr pVisual) +{ + vgaHWPtr hwp; + int i, index; + unsigned char r, g, b; + + hwp = VGAHWPTR(pScrn); + + for (i = 0; i < numColors; i++) { + index = indices[i]; + r = colors[index].red; + g = colors[index].green; + b = colors[index].blue; + hwp->writeDacWriteAddr(hwp, index); + hwp->writeDacData(hwp, r); + hwp->writeDacData(hwp, g); + hwp->writeDacData(hwp, b); + } +} + +Bool +I810AllocateFront(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + int cache_lines = -1; + + if (pI810->DoneFrontAlloc) + return TRUE; + + memset(&(pI810->FbMemBox), 0, sizeof(BoxRec)); + /* Alloc FrontBuffer/Ring/Accel memory */ + pI810->FbMemBox.x1 = 0; + pI810->FbMemBox.x2 = pScrn->displayWidth; + pI810->FbMemBox.y1 = 0; + pI810->FbMemBox.y2 = pScrn->virtualY; + + xf86GetOptValInteger(pI810->Options, OPTION_CACHE_LINES, &cache_lines); + + if (cache_lines < 0) { + /* make sure there is enough for two DVD sized YUV buffers */ + cache_lines = (pScrn->depth == 24) ? 256 : 384; + if (pScrn->displayWidth <= 1024) + cache_lines *= 2; + } + /* Make sure there's enough space for cache_lines. + * + * Had a bug here where maxCacheLines was computed to be less than 0. + * Not sure why 256 was initially subtracted from videoRam in the + * maxCacheLines calculation, but that was causing a problem + * for configurations that have exactly enough Ram for the framebuffer. + * Common code should catch the case where there isn't enough space for + * framebuffer, we'll just check for no space for cache_lines. -jens + * + */ + { + int maxCacheLines; + + maxCacheLines = (pScrn->videoRam * 1024 / + (pScrn->bitsPerPixel / 8) / + pScrn->displayWidth) - pScrn->virtualY; + if (maxCacheLines < 0) + maxCacheLines = 0; + if (cache_lines > maxCacheLines) + cache_lines = maxCacheLines; + } + pI810->FbMemBox.y2 += cache_lines; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Adding %i scanlines for pixmap caching\n", cache_lines); + + /* Reserve room for the framebuffer and pixcache. Put at the top + * of memory so we can have nice alignment for the tiled regions at + * the start of memory. + */ + + if (!I810AllocLow(&(pI810->FrontBuffer), + &(pI810->SysMem), + ((pI810->FbMemBox.x2 * + pI810->FbMemBox.y2 * pI810->cpp) + 4095) & ~4095)) { + xf86DrvMsg(pScrn->scrnIndex, + X_WARNING, "Framebuffer allocation failed\n"); + return FALSE; + } + + memset(pI810->LpRing, 0, sizeof(I810RingBuffer)); + if (I810AllocLow(&(pI810->LpRing->mem), &(pI810->SysMem), 16 * 4096)) { + 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"); + return (FALSE); + } + + if (I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 64 * 1024) || + I810AllocLow(&pI810->Scratch, &(pI810->SysMem), 16 * 1024)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocated Scratch Memory\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Scratch memory allocation failed\n"); + return (FALSE); + } + + pI810->DoneFrontAlloc = TRUE; + return TRUE; +} + +static Bool +I810ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) +{ + ScrnInfoPtr pScrn; + vgaHWPtr hwp; + I810Ptr pI810; + VisualPtr visual; + + pScrn = xf86Screens[pScreen->myNum]; + pI810 = I810PTR(pScrn); + hwp = VGAHWPTR(pScrn); + + pI810->LpRing = calloc(sizeof(I810RingBuffer),1); + if (!pI810->LpRing) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Could not allocate lpring data structure.\n"); + return FALSE; + } + + miClearVisualTypes(); + + /* Re-implemented Direct Color support, -jens */ + if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth), + pScrn->rgbBits, pScrn->defaultVisual)) + return FALSE; + + if (!miSetPixmapDepths()) + return FALSE; + + { + I810RegPtr i810Reg = &pI810->ModeReg; + int i; + + for (i = 0; i < 8; i++) + i810Reg->Fence[i] = 0; + } + + /* Have to init the DRM earlier than in other drivers to get agp + * memory. Wonder if this is going to be a problem... + */ + +#ifdef XF86DRI + /* + * Setup DRI after visuals have been established, but before fbScreenInit + * is called. fbScreenInit will eventually call into the drivers + * InitGLXVisuals call back. + */ + /* + * pI810->directRenderingDisabled is set once in PreInit. Reinitialise + * pI810->directRenderingEnabled based on it each generation. + */ + pI810->directRenderingEnabled = !pI810->directRenderingDisabled; + + if (pI810->directRenderingEnabled==TRUE) + pI810->directRenderingEnabled = I810DRIScreenInit(pScreen); + +#else + pI810->directRenderingEnabled = FALSE; + if (!I810AllocateGARTMemory(pScrn)) + return FALSE; + if (!I810AllocateFront(pScrn)) + return FALSE; +#endif + + if (!I810MapMem(pScrn)) + return FALSE; + + pScrn->memPhysBase = (unsigned long)pI810->LinearAddr; + pScrn->fbOffset = 0; + + vgaHWSetMmioFuncs(hwp, pI810->MMIOBase, 0); + vgaHWGetIOBase(hwp); + if (!vgaHWMapMem(pScrn)) + return FALSE; + + I810Save(pScrn); + if (!I810ModeInit(pScrn, pScrn->currentMode)) + return FALSE; + + I810SaveScreen(pScreen, FALSE); + I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + + if (!fbScreenInit(pScreen, pI810->FbBase + pScrn->fbOffset, + pScrn->virtualX, pScrn->virtualY, + pScrn->xDpi, pScrn->yDpi, + pScrn->displayWidth, pScrn->bitsPerPixel)) + return FALSE; + + if (pScrn->bitsPerPixel > 8) { + /* Fixup RGB ordering */ + visual = pScreen->visuals + pScreen->numVisuals; + while (--visual >= pScreen->visuals) { + if ((visual->class | DynamicClass) == DirectColor) { + visual->offsetRed = pScrn->offset.red; + visual->offsetGreen = pScrn->offset.green; + visual->offsetBlue = pScrn->offset.blue; + visual->redMask = pScrn->mask.red; + visual->greenMask = pScrn->mask.green; + visual->blueMask = pScrn->mask.blue; + } + } + } + + fbPictureInit(pScreen, NULL, 0); + + xf86SetBlackWhitePixels(pScreen); + +#ifdef XF86DRI + if (pI810->LpRing->mem.Start == 0 && pI810->directRenderingEnabled) { + pI810->directRenderingEnabled = FALSE; + I810DRICloseScreen(pScreen); + } + + if (!pI810->directRenderingEnabled) { + pI810->DoneFrontAlloc = FALSE; + if (!I810AllocateGARTMemory(pScrn)) + return FALSE; + if (!I810AllocateFront(pScrn)) + return FALSE; + } +#endif + +#ifdef XFreeXDGA + I810DGAInit(pScreen); +#endif + + if (!xf86InitFBManager(pScreen, &(pI810->FbMemBox))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to init memory manager\n"); + return FALSE; + } + + if (!xf86ReturnOptValBool(pI810->Options, OPTION_NOACCEL, FALSE)) { + if (pI810->LpRing->mem.Size != 0) { + I810SetRingRegs(pScrn); + + if (!I810AccelInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Hardware acceleration initialization failed\n"); + } else /* PK added 16.02.2004 */ + I810EmitFlush(pScrn); + } + } + + miInitializeBackingStore(pScreen); + xf86SetBackingStore(pScreen); + xf86SetSilkenMouse(pScreen); + + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + if (!xf86ReturnOptValBool(pI810->Options, OPTION_SW_CURSOR, FALSE)) { + if (!I810CursorInit(pScreen)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Hardware cursor initialization failed\n"); + } + } + + if (!miCreateDefColormap(pScreen)) + return FALSE; + + /* Use driver specific palette load routines for Direct Color support. -jens */ + if (pScrn->bitsPerPixel == 16) { + if (pScrn->depth == 15) { + if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette15, NULL, + CMAP_PALETTED_TRUECOLOR | + CMAP_RELOAD_ON_MODE_SWITCH)) + return FALSE; + } else { + if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette16, NULL, + CMAP_PALETTED_TRUECOLOR | + CMAP_RELOAD_ON_MODE_SWITCH)) + return FALSE; + } + } else { + if (!xf86HandleColormaps(pScreen, 256, 8, I810LoadPalette24, NULL, + CMAP_PALETTED_TRUECOLOR | + CMAP_RELOAD_ON_MODE_SWITCH)) + return FALSE; + } + + xf86DPMSInit(pScreen, I810DisplayPowerManagementSet, 0); + + I810InitVideo(pScreen); + +#ifdef XF86DRI + if (pI810->directRenderingEnabled) { + /* Now that mi, fb, drm and others have done their thing, + * complete the DRI setup. + */ + pI810->directRenderingEnabled = I810DRIFinishScreenInit(pScreen); + } +#ifdef XvMCExtension + if ((pI810->directRenderingEnabled) && (pI810->numSurfaces)) { + /* Initialize the hardware motion compensation code */ + I810InitMC(pScreen); + } +#endif +#endif + + if (pI810->directRenderingEnabled) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n"); + } + + pScreen->SaveScreen = I810SaveScreen; + pI810->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = I810CloseScreen; + + if (serverGeneration == 1) + xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); + + return TRUE; +} + +Bool +I810SwitchMode(int scrnIndex, DisplayModePtr mode, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; +#if 0 + I810Ptr pI810 = I810PTR(pScrn); +#endif + if (I810_DEBUG & DEBUG_VERBOSE_CURSOR) + ErrorF("I810SwitchMode %p %x\n", (void *)mode, flags); + +#if 0 +/* + * This has been added to prevent lockups on mode switch by modeling + * it after I810Leave()/I810Enter() but the call to I810DRILeave() + * was missing so it caused the opposite. + * The version below works but it is doubtful it does any good. + * If lockups on mode switch are still seen revisit this code. (EE) + */ + +# ifdef XF86DRI + if (pI810->directRenderingEnabled) { + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("calling dri lock\n"); + DRILock(screenInfo.screens[scrnIndex], 0); + pI810->LockHeld = 1; + } +# endif + if (pI810->AccelInfoRec != NULL) { + I810RefreshRing(pScrn); + I810Sync(pScrn); + pI810->AccelInfoRec->NeedToSync = FALSE; + } + I810Restore(pScrn); + +# ifdef XF86DRI + if (pI810->directRenderingEnabled) { + if (!I810DRILeave(pScrn)) + return FALSE; + if (!I810DRIEnter(pScrn)) + return FALSE; + + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("calling dri unlock\n"); + DRIUnlock(screenInfo.screens[scrnIndex]); + pI810->LockHeld = 0; + } +# endif +#endif + return I810ModeInit(pScrn, mode); +} + +void +I810AdjustFrame(int scrnIndex, int x, int y, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + I810Ptr pI810 = I810PTR(pScrn); + vgaHWPtr hwp = VGAHWPTR(pScrn); + int Base; + +#if 1 + if (pI810->showCache) { + int lastline = pI810->FbMapSize / + ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8); + lastline -= pScrn->currentMode->VDisplay; + if (y > 0) + y += pScrn->currentMode->VDisplay; + if (y > lastline) y = lastline; + } +#endif + Base = (y * pScrn->displayWidth + x) >> 2; + + if (I810_DEBUG & DEBUG_VERBOSE_CURSOR) + ErrorF("I810AdjustFrame %d,%d %x\n", x, y, flags); + + switch (pScrn->bitsPerPixel) { + case 8: + break; + case 16: + Base *= 2; + break; + case 24: + /* KW: Need to do 16-pixel alignment for i810, otherwise you + * get bad watermark problems. Need to fixup the mouse + * pointer positioning to take this into account. + */ + pI810->CursorOffset = (Base & 0x3) * 4; + Base &= ~0x3; + Base *= 3; + break; + case 32: + Base *= 4; + break; + } + + hwp->writeCrtc(hwp, START_ADDR_LO, Base & 0xFF); + hwp->writeCrtc(hwp, START_ADDR_HI, (Base & 0xFF00) >> 8); + hwp->writeCrtc(hwp, EXT_START_ADDR_HI, (Base & 0x3FC00000) >> 22); + hwp->writeCrtc(hwp, EXT_START_ADDR, + ((Base & 0x00eF0000) >> 16 | EXT_START_ADDR_ENABLE)); +} + +/* These functions are usually called with the lock **not held**. + */ +static Bool +I810EnterVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + +#ifdef XF86DRI + I810Ptr pI810 = I810PTR(pScrn); +#endif + + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("\n\nENTER VT\n"); + + if (!I810BindGARTMemory(pScrn)) { + return FALSE; + } +#ifdef XF86DRI + if (!I810DRIEnter(pScrn)) { + return FALSE; + } + if (pI810->directRenderingEnabled) { + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("calling dri unlock\n"); + DRIUnlock(screenInfo.screens[scrnIndex]); + pI810->LockHeld = 0; + } +#endif + + if (!I810ModeInit(pScrn, pScrn->currentMode)) + return FALSE; + I810AdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); + return TRUE; +} + +static void +I810LeaveVT(int scrnIndex, int flags) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + vgaHWPtr hwp = VGAHWPTR(pScrn); + I810Ptr pI810 = I810PTR(pScrn); + + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("\n\n\nLeave VT\n"); + +#ifdef XF86DRI + if (pI810->directRenderingEnabled) { + if (I810_DEBUG & DEBUG_VERBOSE_DRI) + ErrorF("calling dri lock\n"); + DRILock(screenInfo.screens[scrnIndex], 0); + pI810->LockHeld = 1; + } +#endif + + if (pI810->AccelInfoRec != NULL) { + I810RefreshRing(pScrn); + I810Sync(pScrn); + pI810->AccelInfoRec->NeedToSync = FALSE; + } + I810Restore(pScrn); + + if (!I810UnbindGARTMemory(pScrn)) + return; +#ifdef XF86DRI + if (!I810DRILeave(pScrn)) + return; +#endif + + vgaHWLock(hwp); +} + +static Bool +I810CloseScreen(int scrnIndex, ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + vgaHWPtr hwp = VGAHWPTR(pScrn); + I810Ptr pI810 = I810PTR(pScrn); + XAAInfoRecPtr infoPtr = pI810->AccelInfoRec; + + if (pScrn->vtSema == TRUE) { + if (pI810->AccelInfoRec != NULL) { + I810RefreshRing(pScrn); + I810Sync(pScrn); + pI810->AccelInfoRec->NeedToSync = FALSE; + } + I810Restore(pScrn); + vgaHWLock(hwp); + } +#ifdef XF86DRI + if (pI810->directRenderingEnabled) { + I810DRICloseScreen(pScreen); + pI810->directRenderingEnabled = FALSE; + } +#endif + + if (pScrn->vtSema == TRUE) { + I810UnbindGARTMemory(pScrn); + I810Restore(pScrn); + vgaHWLock(hwp); + } + + I810UnmapMem(pScrn); + vgaHWUnmapMem(pScrn); + + if (pI810->ScanlineColorExpandBuffers) { + free(pI810->ScanlineColorExpandBuffers); + pI810->ScanlineColorExpandBuffers = NULL; + } + + if (infoPtr) { + if (infoPtr->ScanlineColorExpandBuffers) + free(infoPtr->ScanlineColorExpandBuffers); + XAADestroyInfoRec(infoPtr); + pI810->AccelInfoRec = NULL; + } + + if (pI810->CursorInfoRec) { + xf86DestroyCursorInfoRec(pI810->CursorInfoRec); + pI810->CursorInfoRec = NULL; + } + + /* Free all allocated video ram. + */ + pI810->SysMem = pI810->SavedSysMem; + pI810->DcacheMem = pI810->SavedDcacheMem; + pI810->DoneFrontAlloc = FALSE; + + /* Need to actually close the gart fd, or the unbound memory will just sit + * around. Will prevent the Xserver from recycling. + */ + xf86GARTCloseScreen(scrnIndex); + + free(pI810->LpRing); + pI810->LpRing = NULL; + + pScrn->vtSema = FALSE; + pScreen->CloseScreen = pI810->CloseScreen; + return (*pScreen->CloseScreen) (scrnIndex, pScreen); +} + +static void +I810FreeScreen(int scrnIndex, int flags) +{ + I810FreeRec(xf86Screens[scrnIndex]); + if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) + vgaHWFreeHWRec(xf86Screens[scrnIndex]); +} + +static ModeStatus +I810ValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) +{ + if (mode->Flags & V_INTERLACE) { + if (verbose) { + xf86DrvMsg(scrnIndex, X_PROBED, + "Removing interlaced mode \"%s\"\n", mode->name); + } + return MODE_BAD; + } + return MODE_OK; +} + +static Bool +I810SaveScreen(ScreenPtr pScreen, Bool unblack) +{ + return vgaHWSaveScreen(pScreen, unblack); +} + +static void +I810DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, + int flags) +{ + I810Ptr pI810; + unsigned char SEQ01 = 0; + int DPMSSyncSelect = 0; + + pI810 = I810PTR(pScrn); + switch (PowerManagementMode) { + case DPMSModeOn: + /* Screen: On; HSync: On, VSync: On */ + SEQ01 = 0x00; + DPMSSyncSelect = HSYNC_ON | VSYNC_ON; + break; + case DPMSModeStandby: + /* Screen: Off; HSync: Off, VSync: On */ + SEQ01 = 0x20; + DPMSSyncSelect = HSYNC_OFF | VSYNC_ON; + break; + case DPMSModeSuspend: + /* Screen: Off; HSync: On, VSync: Off */ + SEQ01 = 0x20; + DPMSSyncSelect = HSYNC_ON | VSYNC_OFF; + break; + case DPMSModeOff: + /* Screen: Off; HSync: Off, VSync: Off */ + SEQ01 = 0x20; + DPMSSyncSelect = HSYNC_OFF | VSYNC_OFF; + break; + } + + /* Turn the screen on/off */ + SEQ01 |= pI810->readControl(pI810, SRX, 0x01) & ~0x20; + pI810->writeControl(pI810, SRX, 0x01, SEQ01); + + /* Set the DPMS mode */ + OUTREG8(DPMS_SYNC_SELECT, DPMSSyncSelect); +} + +const OptionInfoRec * +lg_i810_available_options(int chipid, int busid) +{ + return I810Options; +} + + +void lg_i810_init(ScrnInfoPtr scrn) +{ + scrn->PreInit = I810PreInit; + scrn->ScreenInit = I810ScreenInit; + scrn->SwitchMode = I810SwitchMode; + scrn->AdjustFrame = I810AdjustFrame; + scrn->EnterVT = I810EnterVT; + scrn->LeaveVT = I810LeaveVT; + scrn->FreeScreen = I810FreeScreen; + scrn->ValidMode = I810ValidMode; +} diff --git a/src/legacy/i810/i810_hwmc.c b/src/legacy/i810/i810_hwmc.c new file mode 100644 index 00000000..724e1bea --- /dev/null +++ b/src/legacy/i810/i810_hwmc.c @@ -0,0 +1,419 @@ +/*************************************************************************** + +Copyright 2000 Intel Corporation. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * i810_hwmc.c: i810 HWMC Driver + * + * Authors: + * Matt Sottek <matthew.j.sottek@intel.com> + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "i810.h" +#include "i810_dri.h" + +#include "xf86xv.h" +#include "xf86xvmc.h" +#include <X11/extensions/Xv.h> +#include <X11/extensions/XvMC.h> +#include "xaa.h" +#include "xaalocal.h" +#include "dixstruct.h" +#include "fourcc.h" + +int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext, + int *num_priv, long **priv ); +void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext); + +int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf, + int *num_priv, long **priv ); +void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf); + +int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf, + int *num_priv, long **priv ); +void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSurf); + + +typedef struct { + drm_context_t drmcontext; + unsigned int fbBase; + unsigned int OverlayOffset; + unsigned int OverlaySize; + unsigned int SurfacesOffset; + unsigned int SurfacesSize; + char busIdString[10]; + char pad[2]; +} I810XvMCCreateContextRec; + + +static int yv12_subpicture_index_list[2] = +{ + FOURCC_IA44, + FOURCC_AI44 +}; + +static XF86MCImageIDList yv12_subpicture_list = +{ + 2, + yv12_subpicture_index_list +}; + +static XF86MCSurfaceInfoRec i810_YV12_mpg2_surface = +{ + FOURCC_YV12, + XVMC_CHROMA_FORMAT_420, + 0, + 720, + 576, + 720, + 576, + XVMC_MPEG_2, + XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING | + XVMC_INTRA_UNSIGNED, + &yv12_subpicture_list +}; + +static XF86MCSurfaceInfoRec i810_YV12_mpg1_surface = +{ + FOURCC_YV12, + XVMC_CHROMA_FORMAT_420, + 0, + 720, + 576, + 720, + 576, + XVMC_MPEG_1, + XVMC_OVERLAID_SURFACE | XVMC_SUBPICTURE_INDEPENDENT_SCALING | + XVMC_INTRA_UNSIGNED, + &yv12_subpicture_list +}; + +static XF86MCSurfaceInfoPtr ppSI[2] = +{ + (XF86MCSurfaceInfoPtr)&i810_YV12_mpg2_surface, + (XF86MCSurfaceInfoPtr)&i810_YV12_mpg1_surface +}; + +/* List of subpicture types that we support */ +static XF86ImageRec ia44_subpicture = XVIMAGE_IA44; +static XF86ImageRec ai44_subpicture = XVIMAGE_AI44; + +static XF86ImagePtr i810_subpicture_list[2] = +{ + (XF86ImagePtr)&ia44_subpicture, + (XF86ImagePtr)&ai44_subpicture +}; + +/* Fill in the device dependent adaptor record. + * This is named "I810 Video Overlay" because this code falls under the + * XV extenstion, the name must match or it won't be used. + * + * Surface and Subpicture - see above + * Function pointers to functions below + */ +static XF86MCAdaptorRec pAdapt = +{ + "I810 Video Overlay", /* name */ + 2, /* num_surfaces */ + ppSI, /* surfaces */ + 2, /* num_subpictures */ + i810_subpicture_list, /* subpictures */ + (xf86XvMCCreateContextProcPtr)I810XvMCCreateContext, + (xf86XvMCDestroyContextProcPtr)I810XvMCDestroyContext, + (xf86XvMCCreateSurfaceProcPtr)I810XvMCCreateSurface, + (xf86XvMCDestroySurfaceProcPtr)I810XvMCDestroySurface, + (xf86XvMCCreateSubpictureProcPtr)I810XvMCCreateSubpicture, + (xf86XvMCDestroySubpictureProcPtr)I810XvMCDestroySubpicture +}; + +static XF86MCAdaptorPtr ppAdapt[1] = +{ + (XF86MCAdaptorPtr)&pAdapt +}; + +/************************************************************************** + * + * I810InitMC + * + * Initialize the hardware motion compenstation extention for this + * hardware. The initialization routines want the address of the pointers + * to the structures, not the address of the structures. This means we + * allocate (or create static?) the pointer memory and pass that + * address. This seems a little convoluted. + * + * We need to allocate memory for the device depended adaptor record. + * This is what holds the pointers to all our device functions. + * + * We need to map the overlay registers into the drm. + * + * We need to map the surfaces into the drm. + * + * Inputs: + * Screen pointer + * + * Outputs: + * None, this calls the device independent screen initialization + * function. + * + * Revisions: + * + **************************************************************************/ +void I810InitMC(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + int i; + + /* Clear the Surface Allocation */ + for(i=0; i<I810_MAX_SURFACES; i++) { + pI810->surfaceAllocation[i] = 0; + } + + /* Cursor is at a page boundary, Overlay regs are not, don't forget */ + if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->CursorStart, + 4096, DRM_AGP, 0, (drmAddress) &pI810->overlay_map) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(overlay) failed\n"); + return; + } + if (drmAddMap(pI810->drmSubFD, (drm_handle_t)pI810->MC.Start, + pI810->MC.Size, DRM_AGP, 0, (drmAddress) &pI810->mc_map) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "drmAddMap(MC) failed\n"); + return; + } + xf86XvMCScreenInit(pScreen, 1, ppAdapt); +} + +/************************************************************************** + * + * I810XvMCCreateContext + * + * Some info about the private data: + * + * Set *num_priv to the number of 32bit words that make up the size of + * of the data that priv will point to. + * + * *priv = (long *) calloc (elements, sizeof(element)) + * *num_priv = (elements * sizeof(element)) >> 2; + * + **************************************************************************/ + +int I810XvMCCreateContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext, + int *num_priv, long **priv ) +{ + I810Ptr pI810 = I810PTR(pScrn); + DRIInfoPtr pDRIInfo = pI810->pDRIInfo; + I810XvMCCreateContextRec *contextRec; + + + if(!pI810->directRenderingEnabled) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "I810XvMCCreateContext: Cannot use XvMC without DRI!\n"); + return BadAlloc; + } + + /* Context Already in use! */ + if(pI810->xvmcContext) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "I810XvMCCreateContext: 2 XvMC Contexts Attempted, not supported.\n"); + return BadAlloc; + } + + *priv = calloc(1,sizeof(I810XvMCCreateContextRec)); + contextRec = (I810XvMCCreateContextRec *)*priv; + + if(!*priv) { + *num_priv = 0; + return BadAlloc; + } + + *num_priv = sizeof(I810XvMCCreateContextRec) >> 2; + if(drmCreateContext(pI810->drmSubFD, &(contextRec->drmcontext) ) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "I810XvMCCreateContext: Unable to create DRMContext!\n"); + free(*priv); + return BadAlloc; + } + + drmAuthMagic(pI810->drmSubFD, pContext->flags); + + pI810->xvmcContext = contextRec->drmcontext; + contextRec->fbBase = pScrn->memPhysBase; + + /* Overlay Regs are at 1024 offset into the Cursor Space */ + contextRec->OverlayOffset = pI810->CursorStart; + contextRec->OverlaySize = 4096; + + contextRec->SurfacesOffset = pI810->MC.Start; + contextRec->SurfacesSize = pI810->MC.Size; + strncpy (contextRec->busIdString, pDRIInfo->busIdString, 9); + + return Success; +} + + +int I810XvMCCreateSurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf, + int *num_priv, long **priv ) +{ + I810Ptr pI810 = I810PTR(pScrn); + int i; + + *priv = (long *)calloc(2,sizeof(long)); + + if(!*priv) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "I810XvMCCreateSurface: Unable to allocate memory!\n"); + *num_priv = 0; + return BadAlloc; + } + *num_priv = 2; + + /* Surface Arrangement is different based on 6 or 7 Surfaces */ + if(pI810->numSurfaces == 6) { + for(i=0; i<pI810->numSurfaces; i++) { + if(!pI810->surfaceAllocation[i]) { + pI810->surfaceAllocation[i] = pSurf->surface_id; + /* Y data starts at 2MB offset, each surface is 576k */ + (*priv)[0] = (2*1024*1024 + 576*1024 * i); + /* UV data starts at 0 offset, each set is 288k */ + (*priv)[1] = (576*512 * i); + return Success; + } + } + } + if(pI810->numSurfaces == 7) { + for(i=0; i<pI810->numSurfaces; i++) { + if(!pI810->surfaceAllocation[i]) { + pI810->surfaceAllocation[i] = pSurf->surface_id; + /* Y data starts at 2.5MB offset, each surface is 576k */ + (*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i); + /* UV data starts at 0 offset, each set is 288k */ + (*priv)[1] = (576*512 * i); + return Success; + } + } + } + (*priv)[0] = 0; + (*priv)[1] = 0; + return BadAlloc; +} + +int I810XvMCCreateSubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp, + int *num_priv, long **priv ) +{ + I810Ptr pI810 = I810PTR(pScrn); + int i; + + *priv = (long *)calloc(1,sizeof(long)); + + if(!*priv) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "I810XvMCCreateSubpicture: Unable to allocate memory!\n"); + *num_priv = 0; + return BadAlloc; + } + *num_priv = 1; + + if(pI810->numSurfaces == 6) { + for(i=6; i<8; i++) { + if(!pI810->surfaceAllocation[i]) { + pI810->surfaceAllocation[i] = pSubp->subpicture_id; + /* Subpictures are after the Y surfaces in memory */ + (*priv)[0] = (2*1024*1024 + 576*1024 * i); + return Success; + } + } + } + if(pI810->numSurfaces == 7) { + for(i=7; i<9; i++) { + if(!pI810->surfaceAllocation[i]) { + pI810->surfaceAllocation[i] = pSubp->subpicture_id; + /* Subpictures are after the Y surfaces in memory */ + (*priv)[0] = (2*1024*1024 + 512*1024 + 576*1024 * i); + return Success; + } + } + } + + (*priv)[0] = 0; + return BadAlloc; +} + +void I810XvMCDestroyContext (ScrnInfoPtr pScrn, XvMCContextPtr pContext) +{ + I810Ptr pI810 = I810PTR(pScrn); + + drmDestroyContext(pI810->drmSubFD,pI810->xvmcContext); + pI810->xvmcContext = 0; +} + +void I810XvMCDestroySurface (ScrnInfoPtr pScrn, XvMCSurfacePtr pSurf) +{ + I810Ptr pI810 = I810PTR(pScrn); + int i; + + for(i=0; i<I810_MAX_SURFACES; i++) { + if(pI810->surfaceAllocation[i] == pSurf->surface_id) { + pI810->surfaceAllocation[i] = 0; + return; + } + } + return; +} + +void I810XvMCDestroySubpicture (ScrnInfoPtr pScrn, XvMCSubpicturePtr pSubp) +{ + I810Ptr pI810 = I810PTR(pScrn); + int i; + + for(i=pI810->numSurfaces; i<I810_MAX_SURFACES + I810_MAX_SUBPICTURES; i++) { + if(pI810->surfaceAllocation[i] == pSubp->subpicture_id) { + pI810->surfaceAllocation[i] = 0; + return; + } + } + return; +} + + + + + + diff --git a/src/legacy/i810/i810_io.c b/src/legacy/i810/i810_io.c new file mode 100644 index 00000000..a6cf3058 --- /dev/null +++ b/src/legacy/i810/i810_io.c @@ -0,0 +1,133 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Authors: + * Daryll Strauss <daryll@precisioninsight.com> + * + */ + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "compiler.h" + +#ifdef BUILD_FOR_I830 +#include "i830.h" +#define pI810 pI830 +#define I810Ptr I830Ptr +#define I810WriteControlPIO I830WriteControlPIO +#define I810ReadControlPIO I830ReadControlPIO +#define I810WriteStandardPIO I830WriteStandardPIO +#define I810ReadStandardPIO I830ReadStandardPIO +#define I810SetPIOAccess I830SetPIOAccess +#define I810WriteControlMMIO I830WriteControlMMIO +#define I810ReadControlMMIO I830ReadControlMMIO +#define I810WriteStandardMMIO I830WriteStandardMMIO +#define I810ReadStandardMMIO I830ReadStandardMMIO +#define I810SetMMIOAccess I830SetMMIOAccess +#else +#include "i810.h" +#endif + +#define minb(p) *(volatile uint8_t *)(pI810->MMIOBase + (p)) +#define moutb(p,v) *(volatile uint8_t *)(pI810->MMIOBase + (p)) = (v) + +static void +I810WriteControlPIO(I810Ptr pI810, IOADDRESS addr, uint8_t index, uint8_t val) +{ + addr += pI810->ioBase; + outb(addr, index); + outb(addr + 1, val); +} + +static uint8_t +I810ReadControlPIO(I810Ptr pI810, IOADDRESS addr, uint8_t index) +{ + addr += pI810->ioBase; + outb(addr, index); + return inb(addr + 1); +} + +static void +I810WriteStandardPIO(I810Ptr pI810, IOADDRESS addr, uint8_t val) +{ + outb(pI810->ioBase + addr, val); +} + +static uint8_t +I810ReadStandardPIO(I810Ptr pI810, IOADDRESS addr) +{ + return inb(pI810->ioBase + addr); +} + +void +I810SetPIOAccess(I810Ptr pI810) +{ + pI810->writeControl = I810WriteControlPIO; + pI810->readControl = I810ReadControlPIO; + pI810->writeStandard = I810WriteStandardPIO; + pI810->readStandard = I810ReadStandardPIO; +} + +static void +I810WriteControlMMIO(I810Ptr pI810, IOADDRESS addr, uint8_t index, uint8_t val) +{ + moutb(addr, index); + moutb(addr + 1, val); +} + +static uint8_t +I810ReadControlMMIO(I810Ptr pI810, IOADDRESS addr, uint8_t index) +{ + moutb(addr, index); + return minb(addr + 1); +} + +static void +I810WriteStandardMMIO(I810Ptr pI810, IOADDRESS addr, uint8_t val) +{ + moutb(addr, val); +} + +static uint8_t +I810ReadStandardMMIO(I810Ptr pI810, IOADDRESS addr) +{ + return minb(addr); +} + +void +I810SetMMIOAccess(I810Ptr pI810) +{ + pI810->writeControl = I810WriteControlMMIO; + pI810->readControl = I810ReadControlMMIO; + pI810->writeStandard = I810WriteStandardMMIO; + pI810->readStandard = I810ReadStandardMMIO; +} diff --git a/src/legacy/i810/i810_memory.c b/src/legacy/i810/i810_memory.c new file mode 100644 index 00000000..f57ddbe2 --- /dev/null +++ b/src/legacy/i810/i810_memory.c @@ -0,0 +1,428 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * + */ + +#include "xf86.h" +#include "xf86_OSproc.h" + +#include "i810.h" +#include "i810_reg.h" + +int +I810AllocLow(I810MemRange * result, I810MemRange * pool, int size) +{ + if (size > (long)pool->Size) + return 0; + + pool->Size -= size; + result->Size = size; + result->Start = pool->Start; + result->End = pool->Start += size; + + return 1; +} + +int +I810AllocHigh(I810MemRange * result, I810MemRange * pool, int size) +{ + if (size > (long)pool->Size) + return 0; + + pool->Size -= size; + result->Size = size; + result->End = pool->End; + result->Start = pool->End -= size; + + return 1; +} + +int +I810AllocateGARTMemory(ScrnInfoPtr pScrn) +{ + unsigned long size = pScrn->videoRam * 1024; + I810Ptr pI810 = I810PTR(pScrn); + int key; + long tom = 0; + unsigned long physical; + + if (!xf86AgpGARTSupported() || !xf86AcquireGART(pScrn->scrnIndex)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "AGP GART support is either not available or cannot be used.\n" + "\tMake sure your kernel has agpgart support or has the\n" + "\tagpgart module loaded.\n"); + return FALSE; + } + + /* This allows the 2d only Xserver to regen */ + pI810->agpAcquired2d = TRUE; + + /* + * I810/I815 + * + * Treat the gart like video memory - we assume we own all that is + * there, so ignore EBUSY errors. Don't try to remove it on + * failure, either, as other X server may be using it. + */ + + if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL)) == -1) + return FALSE; + + pI810->VramOffset = 0; + pI810->VramKey = key; + + if (!xf86BindGARTMemory(pScrn->scrnIndex, key, 0)) + return FALSE; + + pI810->SysMem.Start = 0; + pI810->SysMem.Size = size; + pI810->SysMem.End = size; + pI810->SavedSysMem = pI810->SysMem; + + tom = pI810->SysMem.End; + + pI810->DcacheMem.Start = 0; + pI810->DcacheMem.End = 0; + pI810->DcacheMem.Size = 0; + pI810->CursorPhysical = 0; + pI810->CursorARGBPhysical = 0; + + /* + * Dcache - half the speed of normal ram, so not really useful for + * a 2d server. Don't bother reporting its presence. This is + * mapped in addition to the requested amount of system ram. + */ + + size = 1024 * 4096; + + /* + * Keep it 512K aligned for the sake of tiled regions. + */ + + tom += 0x7ffff; + tom &= ~0x7ffff; + + if ((key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 1, NULL)) != -1) { + pI810->DcacheOffset = tom; + pI810->DcacheKey = key; + if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Allocation of %ld bytes for DCACHE failed\n", size); + pI810->DcacheKey = -1; + } else { + pI810->DcacheMem.Start = tom; + pI810->DcacheMem.Size = size; + pI810->DcacheMem.End = pI810->DcacheMem.Start + pI810->DcacheMem.Size; + tom = pI810->DcacheMem.End; + } + } else { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No physical memory available for %ld bytes of DCACHE\n", + size); + pI810->DcacheKey = -1; + } + + /* + * Mouse cursor -- The i810 (crazy) needs a physical address in + * system memory from which to upload the cursor. We get this from + * the agpgart module using a special memory type. + */ + + /* + * 4k for the cursor is excessive, I'm going to steal 3k for + * overlay registers later + */ + + size = 4096; + + if ((key = + xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2, &physical)) == -1) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "No physical memory available for HW cursor\n"); + pI810->HwcursKey = -1; + pI810->CursorStart = 0; + } else { + pI810->HwcursOffset = tom; + pI810->HwcursKey = key; + if (!xf86BindGARTMemory(pScrn->scrnIndex, key, tom)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "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 + * registers. + */ + + if (pI810->CursorStart != 0) { + pI810->OverlayPhysical = pI810->CursorPhysical + 1024; + pI810->OverlayStart = pI810->CursorStart + 1024; + } + + pI810->GttBound = 1; + + return TRUE; +} + +/* Tiled memory is good... really, really good... + * + * Need to make it less likely that we miss out on this - probably + * need to move the frontbuffer away from the 'guarenteed' alignment + * of the first memory segment, or perhaps allocate a discontigous + * framebuffer to get more alignment 'sweet spots'. + */ +void +I810SetTiledMemory(ScrnInfoPtr pScrn, int nr, unsigned int start, + unsigned int pitch, unsigned int size) +{ + I810Ptr pI810 = I810PTR(pScrn); + I810RegPtr i810Reg = &pI810->ModeReg; + uint32_t val; + uint32_t fence_mask = 0; + + if (nr < 0 || nr > 7) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%s - fence %d out of range\n", + "I810SetTiledMemory", nr); + return; + } + + i810Reg->Fence[nr] = 0; + + fence_mask = ~FENCE_START_MASK; + + if (start & fence_mask) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: start (%x) is not 512k aligned\n", + "I810SetTiledMemory", nr, start); + return; + } + + if (start % size) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: start (%x) is not size (%x) aligned\n", + "I810SetTiledMemory", nr, start, size); + return; + } + + if (pitch & 127) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: pitch (%x) not a multiple of 128 bytes\n", + "I810SetTiledMemory", nr, pitch); + return; + } + + 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; + default: + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr, + size); + return; + } + + switch (pitch / 128) { + case 1: + val |= FENCE_PITCH_1; + break; + case 2: + val |= FENCE_PITCH_2; + break; + case 4: + val |= FENCE_PITCH_4; + break; + case 8: + val |= FENCE_PITCH_8; + break; + case 16: + val |= FENCE_PITCH_16; + break; + case 32: + val |= FENCE_PITCH_32; + break; + default: + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "%s %d: illegal size (0x%x)\n", "I810SetTiledMemory", nr, + size); + return; + } + + i810Reg->Fence[nr] = val; +} + +Bool +I810BindGARTMemory(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (xf86AgpGARTSupported() && !pI810->directRenderingEnabled + && !pI810->GttBound) { + if (!xf86AcquireGART(pScrn->scrnIndex)) + return FALSE; + + if (pI810->VramKey != -1 + && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->VramKey, + pI810->VramOffset)) + return FALSE; + + if (pI810->DcacheKey != -1 + && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->DcacheKey, + pI810->DcacheOffset)) + return FALSE; + + if (pI810->HwcursKey != -1 + && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey, + pI810->HwcursOffset)) + return FALSE; + + if (pI810->ARGBHwcursKey != -1 + && !xf86BindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey, + pI810->ARGBHwcursOffset)) + return FALSE; + + pI810->GttBound = 1; + } + + return TRUE; +} + +Bool +I810UnbindGARTMemory(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + + if (xf86AgpGARTSupported() && !pI810->directRenderingEnabled + && pI810->GttBound) { + if (pI810->VramKey != -1 + && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->VramKey)) + return FALSE; + + if (pI810->DcacheKey != -1 + && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->DcacheKey)) + return FALSE; + + if (pI810->HwcursKey != -1 + && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->HwcursKey)) + return FALSE; + + if (pI810->ARGBHwcursKey != -1 + && !xf86UnbindGARTMemory(pScrn->scrnIndex, pI810->ARGBHwcursKey)) + return FALSE; + + if (!xf86ReleaseGART(pScrn->scrnIndex)) + return FALSE; + + pI810->GttBound = 0; + } + + return TRUE; +} + +int +I810CheckAvailableMemory(ScrnInfoPtr pScrn) +{ + AgpInfoPtr agpinf; + int maxPages; + + if (!xf86AgpGARTSupported() || + !xf86AcquireGART(pScrn->scrnIndex) || + (agpinf = xf86GetAGPInfo(pScrn->scrnIndex)) == NULL || + !xf86ReleaseGART(pScrn->scrnIndex)) + return -1; + + maxPages = agpinf->totalPages - agpinf->usedPages; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 2, "%s: %dk available\n", + "I810CheckAvailableMemory", maxPages * 4); + + return maxPages * 4; +} diff --git a/src/legacy/i810/i810_reg.h b/src/legacy/i810/i810_reg.h new file mode 100644 index 00000000..2b679346 --- /dev/null +++ b/src/legacy/i810/i810_reg.h @@ -0,0 +1,3194 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/** @file + * Register names and fields for Intel graphics. + */ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + * Eric Anholt <eric@anholt.net> + * + * based on the i740 driver by + * Kevin E. Martin <kevin@precisioninsight.com> + * + * + */ + +#ifndef _I810_REG_H +#define _I810_REG_H + +/* I/O register offsets + */ +#define SRX 0x3C4 /* p208 */ +#define GRX 0x3CE /* p213 */ +#define ARX 0x3C0 /* p224 */ + +/* VGA Color Palette Registers */ +#define DACMASK 0x3C6 /* p232 */ +#define DACSTATE 0x3C7 /* p232 */ +#define DACRX 0x3C7 /* p233 */ +#define DACWX 0x3C8 /* p233 */ +#define DACDATA 0x3C9 /* p233 */ + +/* CRT Controller Registers (CRX) */ +#define START_ADDR_HI 0x0C /* p246 */ +#define START_ADDR_LO 0x0D /* p247 */ +#define VERT_SYNC_END 0x11 /* p249 */ +#define EXT_VERT_TOTAL 0x30 /* p257 */ +#define EXT_VERT_DISPLAY 0x31 /* p258 */ +#define EXT_VERT_SYNC_START 0x32 /* p259 */ +#define EXT_VERT_BLANK_START 0x33 /* p260 */ +#define EXT_HORIZ_TOTAL 0x35 /* p261 */ +#define EXT_HORIZ_BLANK 0x39 /* p261 */ +#define EXT_START_ADDR 0x40 /* p262 */ +#define EXT_START_ADDR_ENABLE 0x80 +#define EXT_OFFSET 0x41 /* p263 */ +#define EXT_START_ADDR_HI 0x42 /* p263 */ +#define INTERLACE_CNTL 0x70 /* p264 */ +#define INTERLACE_ENABLE 0x80 +#define INTERLACE_DISABLE 0x00 + +/* Miscellaneous Output Register + */ +#define MSR_R 0x3CC /* p207 */ +#define MSR_W 0x3C2 /* p207 */ +#define IO_ADDR_SELECT 0x01 + +#define MDA_BASE 0x3B0 /* p207 */ +#define CGA_BASE 0x3D0 /* p207 */ + +/* CR80 - IO Control, p264 + */ +#define IO_CTNL 0x80 +#define EXTENDED_ATTR_CNTL 0x02 +#define EXTENDED_CRTC_CNTL 0x01 + +/* GR10 - Address mapping, p221 + */ +#define ADDRESS_MAPPING 0x10 +#define PAGE_TO_LOCAL_MEM_ENABLE 0x10 +#define GTT_MEM_MAP_ENABLE 0x08 +#define PACKED_MODE_ENABLE 0x04 +#define LINEAR_MODE_ENABLE 0x02 +#define PAGE_MAPPING_ENABLE 0x01 + +#define HOTKEY_VBIOS_SWITCH_BLOCK 0x80 +#define HOTKEY_SWITCH 0x20 +#define HOTKEY_TOGGLE 0x10 + +/* Blitter control, p378 + */ +#define BITBLT_CNTL 0x7000c +#define COLEXP_MODE 0x30 +#define COLEXP_8BPP 0x00 +#define COLEXP_16BPP 0x10 +#define COLEXP_24BPP 0x20 +#define COLEXP_RESERVED 0x30 +#define BITBLT_STATUS 0x01 + +#define CHDECMISC 0x10111 +#define DCC 0x10200 +#define C0DRB0 0x10200 +#define C0DRB1 0x10202 +#define C0DRB2 0x10204 +#define C0DRB3 0x10206 +#define C0DRA01 0x10208 +#define C0DRA23 0x1020a +#define C1DRB0 0x10600 +#define C1DRB1 0x10602 +#define C1DRB2 0x10604 +#define C1DRB3 0x10606 +#define C1DRA01 0x10608 +#define C1DRA23 0x1060a + +/* p375. + */ +#define DISPLAY_CNTL 0x70008 +#define VGA_WRAP_MODE 0x02 +#define VGA_WRAP_AT_256KB 0x00 +#define VGA_NO_WRAP 0x02 +#define GUI_MODE 0x01 +#define STANDARD_VGA_MODE 0x00 +#define HIRES_MODE 0x01 + +/* p375 + */ +#define PIXPIPE_CONFIG_0 0x70009 +#define DAC_8_BIT 0x80 +#define DAC_6_BIT 0x00 +#define HW_CURSOR_ENABLE 0x10 +#define EXTENDED_PALETTE 0x01 + +/* p375 + */ +#define PIXPIPE_CONFIG_1 0x7000a +#define DISPLAY_COLOR_MODE 0x0F +#define DISPLAY_VGA_MODE 0x00 +#define DISPLAY_8BPP_MODE 0x02 +#define DISPLAY_15BPP_MODE 0x04 +#define DISPLAY_16BPP_MODE 0x05 +#define DISPLAY_24BPP_MODE 0x06 +#define DISPLAY_32BPP_MODE 0x07 + +/* p375 + */ +#define PIXPIPE_CONFIG_2 0x7000b +#define DISPLAY_GAMMA_ENABLE 0x08 +#define DISPLAY_GAMMA_DISABLE 0x00 +#define OVERLAY_GAMMA_ENABLE 0x04 +#define OVERLAY_GAMMA_DISABLE 0x00 + + +/* p380 + */ +#define DISPLAY_BASE 0x70020 +#define DISPLAY_BASE_MASK 0x03fffffc + + +/* Cursor control registers, pp383-384 + */ +/* Desktop (845G, 865G) */ +#define CURSOR_CONTROL 0x70080 +#define CURSOR_ENABLE 0x80000000 +#define CURSOR_GAMMA_ENABLE 0x40000000 +#define CURSOR_STRIDE_MASK 0x30000000 +#define CURSOR_FORMAT_SHIFT 24 +#define CURSOR_FORMAT_MASK (0x07 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_2C (0x00 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_3C (0x01 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_4C (0x02 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_ARGB (0x04 << CURSOR_FORMAT_SHIFT) +#define CURSOR_FORMAT_XRGB (0x05 << CURSOR_FORMAT_SHIFT) + +/* Mobile and i810 */ +#define CURSOR_A_CONTROL CURSOR_CONTROL +#define CURSOR_ORIGIN_SCREEN 0x00 /* i810 only */ +#define CURSOR_ORIGIN_DISPLAY 0x1 /* i810 only */ +#define CURSOR_MODE 0x27 +#define CURSOR_MODE_DISABLE 0x00 +#define CURSOR_MODE_32_4C_AX 0x01 /* i810 only */ +#define CURSOR_MODE_64_3C 0x04 +#define CURSOR_MODE_64_4C_AX 0x05 +#define CURSOR_MODE_64_4C 0x06 +#define CURSOR_MODE_64_32B_AX 0x07 +#define CURSOR_MODE_64_ARGB_AX (0x20 | CURSOR_MODE_64_32B_AX) +#define MCURSOR_PIPE_SELECT (1 << 28) +#define MCURSOR_PIPE_A 0x00 +#define MCURSOR_PIPE_B (1 << 28) +#define MCURSOR_GAMMA_ENABLE (1 << 26) +#define MCURSOR_MEM_TYPE_LOCAL (1 << 25) + + +#define CURSOR_BASEADDR 0x70084 +#define CURSOR_A_BASE CURSOR_BASEADDR +#define CURSOR_BASEADDR_MASK 0x1FFFFF00 +#define CURSOR_A_POSITION 0x70088 +#define CURSOR_POS_SIGN 0x8000 +#define CURSOR_POS_MASK 0x007FF +#define CURSOR_X_SHIFT 0 +#define CURSOR_Y_SHIFT 16 +#define CURSOR_X_LO 0x70088 +#define CURSOR_X_HI 0x70089 +#define CURSOR_X_POS 0x00 +#define CURSOR_X_NEG 0x80 +#define CURSOR_Y_LO 0x7008A +#define CURSOR_Y_HI 0x7008B +#define CURSOR_Y_POS 0x00 +#define CURSOR_Y_NEG 0x80 + +#define CURSOR_A_PALETTE0 0x70090 +#define CURSOR_A_PALETTE1 0x70094 +#define CURSOR_A_PALETTE2 0x70098 +#define CURSOR_A_PALETTE3 0x7009C + +#define CURSOR_SIZE 0x700A0 +#define CURSOR_SIZE_MASK 0x3FF +#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. + * + * These details are for the local memory control registers, + * (pp301-310). The test machines are not equiped with local memory, + * so nothing is tested. Only a single row seems to be supported. + */ +#define DRAM_ROW_TYPE 0x3000 +#define DRAM_ROW_0 0x01 +#define DRAM_ROW_0_SDRAM 0x01 +#define DRAM_ROW_0_EMPTY 0x00 +#define DRAM_ROW_CNTL_LO 0x3001 +#define DRAM_PAGE_MODE_CTRL 0x10 +#define DRAM_RAS_TO_CAS_OVRIDE 0x08 +#define DRAM_CAS_LATENCY 0x04 +#define DRAM_RAS_TIMING 0x02 +#define DRAM_RAS_PRECHARGE 0x01 +#define DRAM_ROW_CNTL_HI 0x3002 +#define DRAM_REFRESH_RATE 0x18 +#define DRAM_REFRESH_DISABLE 0x00 +#define DRAM_REFRESH_60HZ 0x08 +#define DRAM_REFRESH_FAST_TEST 0x10 +#define DRAM_REFRESH_RESERVED 0x18 +#define DRAM_SMS 0x07 +#define DRAM_SMS_NORMAL 0x00 +#define DRAM_SMS_NOP_ENABLE 0x01 +#define DRAM_SMS_ABPCE 0x02 +#define DRAM_SMS_MRCE 0x03 +#define DRAM_SMS_CBRCE 0x04 + +/* p307 + */ +#define DPMS_SYNC_SELECT 0x5002 +#define VSYNC_CNTL 0x08 +#define VSYNC_ON 0x00 +#define VSYNC_OFF 0x08 +#define HSYNC_CNTL 0x02 +#define HSYNC_ON 0x00 +#define HSYNC_OFF 0x02 + +#define GPIOA 0x5010 +#define GPIOB 0x5014 +#define GPIOC 0x5018 +#define GPIOD 0x501c +#define GPIOE 0x5020 +#define GPIOF 0x5024 +#define GPIOG 0x5028 +#define GPIOH 0x502c +# define GPIO_CLOCK_DIR_MASK (1 << 0) +# define GPIO_CLOCK_DIR_IN (0 << 1) +# define GPIO_CLOCK_DIR_OUT (1 << 1) +# define GPIO_CLOCK_VAL_MASK (1 << 2) +# define GPIO_CLOCK_VAL_OUT (1 << 3) +# define GPIO_CLOCK_VAL_IN (1 << 4) +# define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) +# define GPIO_DATA_DIR_MASK (1 << 8) +# define GPIO_DATA_DIR_IN (0 << 9) +# define GPIO_DATA_DIR_OUT (1 << 9) +# define GPIO_DATA_VAL_MASK (1 << 10) +# define GPIO_DATA_VAL_OUT (1 << 11) +# define GPIO_DATA_VAL_IN (1 << 12) +# define GPIO_DATA_PULLUP_DISABLE (1 << 13) + +/* GMBus registers for hardware-assisted (non-bitbanging) I2C access */ +#define GMBUS0 0x5100 +#define GMBUS1 0x5104 +#define GMBUS2 0x5108 +#define GMBUS3 0x510c +#define GMBUS4 0x5110 +#define GMBUS5 0x5120 + +/* p317, 319 + */ +#define VCLK2_VCO_M 0x6008 /* treat as 16 bit? (includes msbs) */ +#define VCLK2_VCO_N 0x600a +#define VCLK2_VCO_DIV_SEL 0x6012 + +#define VCLK_DIVISOR_VGA0 0x6000 +#define VCLK_DIVISOR_VGA1 0x6004 +#define VCLK_POST_DIV 0x6010 +/** Selects a post divisor of 4 instead of 2. */ +# define VGA1_PD_P2_DIV_4 (1 << 15) +/** Overrides the p2 post divisor field */ +# define VGA1_PD_P1_DIV_2 (1 << 13) +# define VGA1_PD_P1_SHIFT 8 +/** P1 value is 2 greater than this field */ +# define VGA1_PD_P1_MASK (0x1f << 8) +/** Selects a post divisor of 4 instead of 2. */ +# define VGA0_PD_P2_DIV_4 (1 << 7) +/** Overrides the p2 post divisor field */ +# define VGA0_PD_P1_DIV_2 (1 << 5) +# define VGA0_PD_P1_SHIFT 0 +/** P1 value is 2 greater than this field */ +# define VGA0_PD_P1_MASK (0x1f << 0) + +#define POST_DIV_SELECT 0x70 +#define POST_DIV_1 0x00 +#define POST_DIV_2 0x10 +#define POST_DIV_4 0x20 +#define POST_DIV_8 0x30 +#define POST_DIV_16 0x40 +#define POST_DIV_32 0x50 +#define VCO_LOOP_DIV_BY_4M 0x00 +#define VCO_LOOP_DIV_BY_16M 0x04 + + +/* Instruction Parser Mode Register + * - p281 + * - 2 new bits. + */ +#define INST_PM 0x20c0 +#define AGP_SYNC_PACKET_FLUSH_ENABLE 0x20 /* reserved */ +#define SYNC_PACKET_FLUSH_ENABLE 0x10 +#define TWO_D_INST_DISABLE 0x08 +#define THREE_D_INST_DISABLE 0x04 +#define STATE_VAR_UPDATE_DISABLE 0x02 +#define PAL_STIP_DISABLE 0x01 + + +#define MEMMODE 0x20dc + + +/* Instruction parser error register. p279 + */ +#define IPEIR 0x2088 +#define IPEHR 0x208C + +#define INST_DONE 0x2090 +# define IDCT_DONE (1 << 30) +# define IQ_DONE (1 << 29) +# define PR_DONE (1 << 28) +# define VLD_DONE (1 << 27) +# define IP_DONE (1 << 26) +# define FBC_DONE (1 << 25) +# define BINNER_DONE (1 << 24) +# define SF_DONE (1 << 23) +# define SE_DONE (1 << 22) +# define WM_DONE (1 << 21) +# define IZ_DONE (1 << 20) +# define PERSPECTIVE_INTERP_DONE (1 << 19) +# define DISPATCHER_DONE (1 << 18) +# define PROJECTION_DONE (1 << 17) +# define DEPENDENT_ADDRESS_DONE (1 << 16) +# define QUAD_CACHE_DONE (1 << 15) +# define TEXTURE_FETCH_DONE (1 << 14) +# define TEXTURE_DECOMPRESS_DONE (1 << 13) +# define SAMPLER_CACHE_DONE (1 << 12) +# define FILTER_DONE (1 << 11) +# define BYPASS_FIFO_DONE (1 << 10) +# define PS_DONE (1 << 9) +# define CC_DONE (1 << 8) +# define MAP_FILTER_DONE (1 << 7) +# define MAP_L2_IDLE (1 << 6) +# define RING_2_ENABLE (1 << 2) +# define RING_1_ENABLE (1 << 1) +# define RING_0_ENABLE (1 << 0) + +#define SCPD0 0x209c /* debug */ +#define INST_PS 0x20c4 +#define IPEIR_I965 0x2064 /* i965 */ +#define IPEHR_I965 0x2068 /* i965 */ +#define INST_DONE_I965 0x206c +# define I965_SF_DONE (1 << 23) +# define I965_SE_DONE (1 << 22) +# define I965_WM_DONE (1 << 21) +# define I965_TEXTURE_FETCH_DONE (1 << 14) +# define I965_SAMPLER_CACHE_DONE (1 << 12) +# define I965_FILTER_DONE (1 << 11) +# define I965_PS_DONE (1 << 9) +# define I965_CC_DONE (1 << 8) +# define I965_MAP_FILTER_DONE (1 << 7) +# define I965_MAP_L2_IDLE (1 << 6) +# define I965_CP_DONE (1 << 1) +# define I965_RING_0_ENABLE (1 << 0) +#define INST_PS_I965 0x2070 + +/* Current active ring head address: + */ +#define ACTHD_I965 0x2074 +#define ACTHD 0x20C8 + +/* Current primary/secondary DMA fetch addresses: + */ +#define DMA_FADD_P 0x2078 +#define DMA_FADD_S 0x20d4 +#define INST_DONE_1 0x207c + +#define CACHE_MODE_0 0x2120 +#define CACHE_MODE_1 0x2124 +#define MI_MODE 0x209c +#define MI_DISPLAY_POWER_DOWN 0x20e0 +#define MI_ARB_STATE 0x20e4 +#define MI_RDRET_STATE 0x20fc + +/* Start addresses for each of the primary rings: + */ +#define PR0_STR 0x20f0 +#define PR1_STR 0x20f4 +#define PR2_STR 0x20f8 + +#define WIZ_CTL 0x7c00 +#define WIZ_CTL_SINGLE_SUBSPAN (1<<6) +#define WIZ_CTL_IGNORE_STALLS (1<<5) + +#define SVG_WORK_CTL 0x7408 + +#define TS_CTL 0x7e00 +#define TS_MUX_ERR_CODE (0<<8) +#define TS_MUX_URB_0 (1<<8) +#define TS_MUX_DISPATCH_ID_0 (10<<8) +#define TS_MUX_ERR_CODE_VALID (15<<8) +#define TS_MUX_TID_0 (16<<8) +#define TS_MUX_EUID_0 (18<<8) +#define TS_MUX_FFID_0 (22<<8) +#define TS_MUX_EOT (26<<8) +#define TS_MUX_SIDEBAND_0 (27<<8) +#define TS_SNAP_ALL_CHILD (1<<2) +#define TS_SNAP_ALL_ROOT (1<<1) +#define TS_SNAP_ENABLE (1<<0) + +#define TS_DEBUG_DATA 0x7e0c + +#define TD_CTL 0x8000 +#define TD_CTL2 0x8004 + + +#define ECOSKPD 0x21d0 +#define EXCC 0x2028 + +/* I965 debug regs: + */ +#define IA_VERTICES_COUNT_QW 0x2310 +#define IA_PRIMITIVES_COUNT_QW 0x2318 +#define VS_INVOCATION_COUNT_QW 0x2320 +#define GS_INVOCATION_COUNT_QW 0x2328 +#define GS_PRIMITIVES_COUNT_QW 0x2330 +#define CL_INVOCATION_COUNT_QW 0x2338 +#define CL_PRIMITIVES_COUNT_QW 0x2340 +#define PS_INVOCATION_COUNT_QW 0x2348 +#define PS_DEPTH_COUNT_QW 0x2350 +#define TIMESTAMP_QW 0x2358 +#define CLKCMP_QW 0x2360 + + + + + + +/* General error reporting regs, p296 + */ +#define EIR 0x20B0 +#define EMR 0x20B4 +#define ESR 0x20B8 +# define ERR_VERTEX_MAX (1 << 5) /* lpt/cst */ +# define ERR_PGTBL_ERROR (1 << 4) +# define ERR_DISPLAY_OVERLAY_UNDERRUN (1 << 3) +# define ERR_MAIN_MEMORY_REFRESH (1 << 1) +# define ERR_INSTRUCTION_ERROR (1 << 0) + + +/* Interrupt Control Registers + * - new bits for i810 + * - new register hwstam (mask) + */ +#define HWS_PGA 0x2080 +#define PWRCTXA 0x2088 /* 965GM+ only */ +#define PWRCTX_EN (1<<0) +#define HWSTAM 0x2098 /* p290 */ +#define IER 0x20a0 /* p291 */ +#define IIR 0x20a4 /* p292 */ +#define IMR 0x20a8 /* p293 */ +#define ISR 0x20ac /* p294 */ +#define HW_ERROR 0x8000 +#define SYNC_STATUS_TOGGLE 0x1000 +#define DPY_0_FLIP_PENDING 0x0800 +#define DPY_1_FLIP_PENDING 0x0400 /* not implemented on i810 */ +#define OVL_0_FLIP_PENDING 0x0200 +#define OVL_1_FLIP_PENDING 0x0100 /* not implemented on i810 */ +#define DPY_0_VBLANK 0x0080 +#define DPY_0_EVENT 0x0040 +#define DPY_1_VBLANK 0x0020 /* not implemented on i810 */ +#define DPY_1_EVENT 0x0010 /* not implemented on i810 */ +#define HOST_PORT_EVENT 0x0008 /* */ +#define CAPTURE_EVENT 0x0004 /* */ +#define USER_DEFINED 0x0002 +#define BREAKPOINT 0x0001 + + +#define INTR_RESERVED (0x6000 | \ + DPY_1_FLIP_PENDING | \ + OVL_1_FLIP_PENDING | \ + DPY_1_VBLANK | \ + DPY_1_EVENT | \ + HOST_PORT_EVENT | \ + CAPTURE_EVENT ) + +/* FIFO Watermark and Burst Length Control Register + * + * - different offset and contents on i810 (p299) (fewer bits per field) + * - some overlay fields added + * - what does it all mean? + */ +#define FWATER_BLC 0x20d8 +#define FWATER_BLC2 0x20dc +#define MM_BURST_LENGTH 0x00700000 +#define MM_FIFO_WATERMARK 0x0001F000 +#define LM_BURST_LENGTH 0x00000700 +#define LM_FIFO_WATERMARK 0x0000001F + + +/* Fence/Tiling ranges [0..7] + */ +#define FENCE 0x2000 +#define FENCE_NR 8 + +#define FENCE_NEW 0x3000 +#define FENCE_NEW_NR 16 + +#define FENCE_LINEAR 0 +#define FENCE_XMAJOR 1 +#define FENCE_YMAJOR 2 + +#define I915G_FENCE_START_MASK 0x0ff00000 + +#define I830_FENCE_START_MASK 0x07f80000 + +#define FENCE_START_MASK 0x03F80000 +#define FENCE_X_MAJOR 0x00000000 +#define FENCE_Y_MAJOR 0x00001000 +#define FENCE_SIZE_MASK 0x00000700 +#define FENCE_SIZE_512K 0x00000000 +#define FENCE_SIZE_1M 0x00000100 +#define FENCE_SIZE_2M 0x00000200 +#define FENCE_SIZE_4M 0x00000300 +#define FENCE_SIZE_8M 0x00000400 +#define FENCE_SIZE_16M 0x00000500 +#define FENCE_SIZE_32M 0x00000600 +#define FENCE_SIZE_64M 0x00000700 +#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 I965_FENCE_X_MAJOR 0x00000000 +#define I965_FENCE_Y_MAJOR 0x00000002 +#define FENCE_PITCH_1 0x00000000 +#define FENCE_PITCH_2 0x00000010 +#define FENCE_PITCH_4 0x00000020 +#define FENCE_PITCH_8 0x00000030 +#define FENCE_PITCH_16 0x00000040 +#define FENCE_PITCH_32 0x00000050 +#define FENCE_PITCH_64 0x00000060 +#define FENCE_VALID 0x00000001 + + +/* Registers to control page table, p274 + */ +#define PGETBL_CTL 0x2020 +#define PGETBL_ADDR_MASK 0xFFFFF000 +#define PGETBL_ENABLE_MASK 0x00000001 +#define PGETBL_ENABLED 0x00000001 +/** Added in 965G, this field has the actual size of the global GTT */ +#define PGETBL_SIZE_MASK 0x0000000e +#define PGETBL_SIZE_512KB (0 << 1) +#define PGETBL_SIZE_256KB (1 << 1) +#define PGETBL_SIZE_128KB (2 << 1) +#define PGETBL_SIZE_1MB (3 << 1) +#define PGETBL_SIZE_2MB (4 << 1) +#define PGETBL_SIZE_1_5MB (5 << 1) +#define G33_PGETBL_SIZE_MASK (3 << 8) +#define G33_PGETBL_SIZE_1M (1 << 8) +#define G33_PGETBL_SIZE_2M (2 << 8) + +#define I830_PTE_BASE 0x10000 +#define PTE_ADDRESS_MASK 0xfffff000 +#define PTE_ADDRESS_MASK_HIGH 0x000000f0 /* i915+ */ +#define PTE_MAPPING_TYPE_UNCACHED (0 << 1) +#define PTE_MAPPING_TYPE_DCACHE (1 << 1) /* i830 only */ +#define PTE_MAPPING_TYPE_CACHED (3 << 1) +#define PTE_MAPPING_TYPE_MASK (3 << 1) +#define PTE_VALID (1 << 0) + +/** @defgroup PGE_ERR + * @{ + */ +/** Page table debug register for i845 */ +#define PGE_ERR 0x2024 +#define PGE_ERR_ADDR_MASK 0xFFFFF000 +#define PGE_ERR_ID_MASK 0x00000038 +#define PGE_ERR_CAPTURE 0x00000000 +#define PGE_ERR_OVERLAY 0x00000008 +#define PGE_ERR_DISPLAY 0x00000010 +#define PGE_ERR_HOST 0x00000018 +#define PGE_ERR_RENDER 0x00000020 +#define PGE_ERR_BLITTER 0x00000028 +#define PGE_ERR_MAPPING 0x00000030 +#define PGE_ERR_CMD_PARSER 0x00000038 +#define PGE_ERR_TYPE_MASK 0x00000007 +#define PGE_ERR_INV_TABLE 0x00000000 +#define PGE_ERR_INV_PTE 0x00000001 +#define PGE_ERR_MIXED_TYPES 0x00000002 +#define PGE_ERR_PAGE_MISS 0x00000003 +#define PGE_ERR_ILLEGAL_TRX 0x00000004 +#define PGE_ERR_LOCAL_MEM 0x00000005 +#define PGE_ERR_TILED 0x00000006 +/** @} */ + +/** @defgroup PGTBL_ER + * @{ + */ +/** Page table debug register for i945 */ +# define PGTBL_ER 0x2024 +# define PGTBL_ERR_MT_TILING (1 << 27) +# define PGTBL_ERR_MT_GTT_PTE (1 << 26) +# define PGTBL_ERR_LC_TILING (1 << 25) +# define PGTBL_ERR_LC_GTT_PTE (1 << 24) +# define PGTBL_ERR_BIN_VERTEXDATA_GTT_PTE (1 << 23) +# define PGTBL_ERR_BIN_INSTRUCTION_GTT_PTE (1 << 22) +# define PGTBL_ERR_CS_VERTEXDATA_GTT_PTE (1 << 21) +# define PGTBL_ERR_CS_INSTRUCTION_GTT_PTE (1 << 20) +# define PGTBL_ERR_CS_GTT (1 << 19) +# define PGTBL_ERR_OVERLAY_TILING (1 << 18) +# define PGTBL_ERR_OVERLAY_GTT_PTE (1 << 16) +# define PGTBL_ERR_DISPC_TILING (1 << 14) +# define PGTBL_ERR_DISPC_GTT_PTE (1 << 12) +# define PGTBL_ERR_DISPB_TILING (1 << 10) +# define PGTBL_ERR_DISPB_GTT_PTE (1 << 8) +# define PGTBL_ERR_DISPA_TILING (1 << 6) +# define PGTBL_ERR_DISPA_GTT_PTE (1 << 4) +# define PGTBL_ERR_HOST_PTE_DATA (1 << 1) +# define PGTBL_ERR_HOST_GTT_PTE (1 << 0) +/** @} */ + +/* Ring buffer registers, p277, overview p19 + */ +#define LP_RING 0x2030 +#define HP_RING 0x2040 + +#define RING_TAIL 0x00 +#define TAIL_ADDR 0x000FFFF8 +#define I830_TAIL_MASK 0x001FFFF8 + +#define RING_HEAD 0x04 +#define HEAD_WRAP_COUNT 0xFFE00000 +#define HEAD_WRAP_ONE 0x00200000 +#define HEAD_ADDR 0x001FFFFC +#define I830_HEAD_MASK 0x001FFFFC + +#define RING_START 0x08 +#define START_ADDR 0x03FFFFF8 +#define I830_RING_START_MASK 0xFFFFF000 + +#define RING_LEN 0x0C +#define RING_NR_PAGES 0x001FF000 +#define I830_RING_NR_PAGES 0x001FF000 +#define RING_REPORT_MASK 0x00000006 +#define RING_REPORT_64K 0x00000002 +#define RING_REPORT_128K 0x00000004 +#define RING_NO_REPORT 0x00000000 +#define RING_VALID_MASK 0x00000001 +#define RING_VALID 0x00000001 +#define RING_INVALID 0x00000000 + + + +/* BitBlt Instructions + * + * There are many more masks & ranges yet to add. + */ +#define BR00_BITBLT_CLIENT 0x40000000 +#define BR00_OP_COLOR_BLT 0x10000000 +#define BR00_OP_SRC_COPY_BLT 0x10C00000 +#define BR00_OP_FULL_BLT 0x11400000 +#define BR00_OP_MONO_SRC_BLT 0x11800000 +#define BR00_OP_MONO_SRC_COPY_BLT 0x11000000 +#define BR00_OP_MONO_PAT_BLT 0x11C00000 +#define BR00_OP_MONO_SRC_COPY_IMMEDIATE_BLT (0x61 << 22) +#define BR00_OP_TEXT_IMMEDIATE_BLT 0xc000000 + + +#define BR00_TPCY_DISABLE 0x00000000 +#define BR00_TPCY_ENABLE 0x00000010 + +#define BR00_TPCY_ROP 0x00000000 +#define BR00_TPCY_NO_ROP 0x00000020 +#define BR00_TPCY_EQ 0x00000000 +#define BR00_TPCY_NOT_EQ 0x00000040 + +#define BR00_PAT_MSB_FIRST 0x00000000 /* ? */ + +#define BR00_PAT_VERT_ALIGN 0x000000e0 + +#define BR00_LENGTH 0x0000000F + +#define BR09_DEST_ADDR 0x03FFFFFF + +#define BR11_SOURCE_PITCH 0x00003FFF + +#define BR12_SOURCE_ADDR 0x03FFFFFF + +#define BR13_SOLID_PATTERN 0x80000000 +#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 +#define BR13_DYN_24BPP 0x02000000 +#define BR13_ROP_MASK 0x00FF0000 +#define BR13_DEST_PITCH 0x0000FFFF +#define BR13_PITCH_SIGN_BIT 0x00008000 + +#define BR14_DEST_HEIGHT 0xFFFF0000 +#define BR14_DEST_WIDTH 0x0000FFFF + +#define BR15_PATTERN_ADDR 0x03FFFFFF + +#define BR16_SOLID_PAT_COLOR 0x00FFFFFF +#define BR16_BACKGND_PAT_CLR 0x00FFFFFF + +#define BR17_FGND_PAT_CLR 0x00FFFFFF + +#define BR18_SRC_BGND_CLR 0x00FFFFFF +#define BR19_SRC_FGND_CLR 0x00FFFFFF + + +/* Instruction parser instructions + */ + +#define INST_PARSER_CLIENT 0x00000000 +#define INST_OP_FLUSH 0x02000000 +#define INST_FLUSH_MAP_CACHE 0x00000001 + + +#define GFX_OP_USER_INTERRUPT ((0<<29)|(2<<23)) + + +/* Registers in the i810 host-pci bridge pci config space which affect + * the i810 graphics operations. + */ +#define SMRAM_MISCC 0x70 +#define GMS 0x000000c0 +#define GMS_DISABLE 0x00000000 +#define GMS_ENABLE_BARE 0x00000040 +#define GMS_ENABLE_512K 0x00000080 +#define GMS_ENABLE_1M 0x000000c0 +#define USMM 0x00000030 +#define USMM_DISABLE 0x00000000 +#define USMM_TSEG_ZERO 0x00000010 +#define USMM_TSEG_512K 0x00000020 +#define USMM_TSEG_1M 0x00000030 +#define GFX_MEM_WIN_SIZE 0x00010000 +#define GFX_MEM_WIN_32M 0x00010000 +#define GFX_MEM_WIN_64M 0x00000000 + +/* Overkill? I don't know. Need to figure out top of mem to make the + * SMRAM calculations come out. Linux seems to have problems + * detecting it all on its own, so this seems a reasonable double + * check to any user supplied 'mem=...' boot param. + * + * ... unfortunately this reg doesn't work according to spec on the + * test hardware. + */ +#define WHTCFG_PAMR_DRP 0x50 +#define SYS_DRAM_ROW_0_SHIFT 16 +#define SYS_DRAM_ROW_1_SHIFT 20 +#define DRAM_MASK 0x0f +#define DRAM_VALUE_0 0 +#define DRAM_VALUE_1 8 +/* No 2 value defined */ +#define DRAM_VALUE_3 16 +#define DRAM_VALUE_4 16 +#define DRAM_VALUE_5 24 +#define DRAM_VALUE_6 32 +#define DRAM_VALUE_7 32 +#define DRAM_VALUE_8 48 +#define DRAM_VALUE_9 64 +#define DRAM_VALUE_A 64 +#define DRAM_VALUE_B 96 +#define DRAM_VALUE_C 128 +#define DRAM_VALUE_D 128 +#define DRAM_VALUE_E 192 +#define DRAM_VALUE_F 256 /* nice one, geezer */ +#define LM_FREQ_MASK 0x10 +#define LM_FREQ_133 0x10 +#define LM_FREQ_100 0x00 + + + + +/* These are 3d state registers, but the state is invarient, so we let + * the X server handle it: + */ + + + +/* GFXRENDERSTATE_COLOR_CHROMA_KEY, p135 + */ +#define GFX_OP_COLOR_CHROMA_KEY ((0x3<<29)|(0x1d<<24)|(0x2<<16)|0x1) +#define CC1_UPDATE_KILL_WRITE (1<<28) +#define CC1_ENABLE_KILL_WRITE (1<<27) +#define CC1_DISABLE_KILL_WRITE 0 +#define CC1_UPDATE_COLOR_IDX (1<<26) +#define CC1_UPDATE_CHROMA_LOW (1<<25) +#define CC1_UPDATE_CHROMA_HI (1<<24) +#define CC1_CHROMA_LOW_MASK ((1<<24)-1) +#define CC2_COLOR_IDX_SHIFT 24 +#define CC2_COLOR_IDX_MASK (0xff<<24) +#define CC2_CHROMA_HI_MASK ((1<<24)-1) + + +#define GFX_CMD_CONTEXT_SEL ((0<<29)|(0x5<<23)) +#define CS_UPDATE_LOAD (1<<17) +#define CS_UPDATE_USE (1<<16) +#define CS_UPDATE_LOAD (1<<17) +#define CS_LOAD_CTX0 0 +#define CS_LOAD_CTX1 (1<<8) +#define CS_USE_CTX0 0 +#define CS_USE_CTX1 (1<<0) + +/* I810 LCD/TV registers */ +#define LCD_TV_HTOTAL 0x60000 +#define LCD_TV_C 0x60018 +#define LCD_TV_OVRACT 0x6001C + +#define LCD_TV_ENABLE (1 << 31) +#define LCD_TV_VGAMOD (1 << 28) + +/* I830 CRTC registers */ +#define HTOTAL_A 0x60000 +#define HBLANK_A 0x60004 +#define HSYNC_A 0x60008 +#define VTOTAL_A 0x6000c +#define VBLANK_A 0x60010 +#define VSYNC_A 0x60014 +#define PIPEASRC 0x6001c +#define BCLRPAT_A 0x60020 +#define VSYNCSHIFT_A 0x60028 + +#define HTOTAL_B 0x61000 +#define HBLANK_B 0x61004 +#define HSYNC_B 0x61008 +#define VTOTAL_B 0x6100c +#define VBLANK_B 0x61010 +#define VSYNC_B 0x61014 +#define PIPEBSRC 0x6101c +#define BCLRPAT_B 0x61020 +#define VSYNCSHIFT_B 0x61028 + +#define PP_STATUS 0x61200 +# define PP_ON (1 << 31) +/** + * Indicates that all dependencies of the panel are on: + * + * - PLL enabled + * - pipe enabled + * - LVDS/DVOB/DVOC on + */ +# define PP_READY (1 << 30) +# define PP_SEQUENCE_NONE (0 << 28) +# define PP_SEQUENCE_ON (1 << 28) +# define PP_SEQUENCE_OFF (2 << 28) +# define PP_SEQUENCE_MASK 0x30000000 + +#define PP_CONTROL 0x61204 +# define POWER_DOWN_ON_RESET (1 << 1) +# define POWER_TARGET_ON (1 << 0) + +#define PP_ON_DELAYS 0x61208 +#define PP_OFF_DELAYS 0x6120c +#define PP_DIVISOR 0x61210 + +#define PFIT_CONTROL 0x61230 +# define PFIT_ENABLE (1 << 31) +/* Pre-965 */ +# define VERT_INTERP_DISABLE (0 << 10) +# define VERT_INTERP_BILINEAR (1 << 10) +# define VERT_INTERP_MASK (3 << 10) +# define VERT_AUTO_SCALE (1 << 9) +# define HORIZ_INTERP_DISABLE (0 << 6) +# define HORIZ_INTERP_BILINEAR (1 << 6) +# define HORIZ_INTERP_MASK (3 << 6) +# define HORIZ_AUTO_SCALE (1 << 5) +# define PANEL_8TO6_DITHER_ENABLE (1 << 3) +/* 965+ */ +# define PFIT_PIPE_MASK (3 << 29) +# define PFIT_PIPE_SHIFT 29 +# define PFIT_SCALING_MODE_MASK (7 << 26) +# define PFIT_SCALING_AUTO (0 << 26) +# define PFIT_SCALING_PROGRAMMED (1 << 26) +# define PFIT_SCALING_PILLAR (2 << 26) +# define PFIT_SCALING_LETTER (3 << 26) +# define PFIT_FILTER_SELECT_MASK (3 << 24) +# define PFIT_FILTER_FUZZY (0 << 24) +# define PFIT_FILTER_CRISP (1 << 24) +# define PFIT_FILTER_MEDIAN (2 << 24) + +#define PFIT_PGM_RATIOS 0x61234 +/* Pre-965 */ +# define PFIT_VERT_SCALE_SHIFT 20 +# define PFIT_VERT_SCALE_MASK 0xfff00000 +# define PFIT_HORIZ_SCALE_SHIFT 4 +# define PFIT_HORIZ_SCALE_MASK 0x0000fff0 +/* 965+ */ +# define PFIT_VERT_SCALE_SHIFT_965 16 +# define PFIT_VERT_SCALE_MASK_965 0x1fff0000 +# define PFIT_HORIZ_SCALE_SHIFT_965 0 +# define PFIT_HORIZ_SCALE_MASK_965 0x00001fff + +#define DPLL_A 0x06014 +#define DPLL_B 0x06018 +# define DPLL_VCO_ENABLE (1 << 31) +# define DPLL_DVO_HIGH_SPEED (1 << 30) +# define DPLL_SYNCLOCK_ENABLE (1 << 29) +# define DPLL_VGA_MODE_DIS (1 << 28) +# define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ +# define DPLLB_MODE_LVDS (2 << 26) /* i915 */ +# define DPLL_MODE_MASK (3 << 26) +# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ +# define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ +# define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ +# define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ +# define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ +# define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ +# define DPLL_FPA01_P1_POST_DIV_MASK_IGD 0x00ff8000 /* IGD */ +/** + * The i830 generation, in DAC/serial mode, defines p1 as two plus this + * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set. + */ +# define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 +/** + * The i830 generation, in LVDS mode, defines P1 as the bit number set within + * this field (only one bit may be set). + */ +# define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 +# define DPLL_FPA01_P1_POST_DIV_SHIFT 16 +# define DPLL_FPA01_P1_POST_DIV_SHIFT_IGD 15 +/* IGDNG */ +# define DPLL_FPA0_P1_POST_DIV_SHIFT 16 + +# define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required in DVO non-gang */ +# define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ +# define PLL_REF_INPUT_DREFCLK (0 << 13) +# define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ +# define PLL_REF_INPUT_SUPER_SSC (1 << 13) /* IGDNG: 120M SSC */ +# define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO TVCLKIN */ +# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) +# define PLL_REF_INPUT_MASK (3 << 13) +# define PLL_REF_INPUT_DMICLK (5 << 13) /* IGDNG: DMI refclk */ +# define PLL_LOAD_PULSE_PHASE_SHIFT 9 +/* + * Parallel to Serial Load Pulse phase selection. + * Selects the phase for the 10X DPLL clock for the PCIe + * digital display port. The range is 4 to 13; 10 or more + * is just a flip delay. The default is 6 + */ +# define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) +# define DISPLAY_RATE_SELECT_FPA1 (1 << 8) +/* IGDNG */ +# define PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT 9 +# define PLL_REF_SDVO_HDMI_MULTIPLIER_MASK (7 << 9) +# define PLL_REF_SDVO_HDMI_MULTIPLIER(x) (((x)-1)<< PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT) +# define DPLL_FPA1_P1_POST_DIV_SHIFT 0 +# define DPLL_FPA1_P1_POST_DIV_MASK 0xff + +/** + * SDVO multiplier for 945G/GM. Not used on 965. + * + * \sa DPLL_MD_UDI_MULTIPLIER_MASK + */ +# define SDVO_MULTIPLIER_MASK 0x000000ff +# define SDVO_MULTIPLIER_SHIFT_HIRES 4 +# define SDVO_MULTIPLIER_SHIFT_VGA 0 + +/** @defgroup DPLL_MD + * @{ + */ +/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */ +#define DPLL_A_MD 0x0601c +/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */ +#define DPLL_B_MD 0x06020 +/** + * UDI pixel divider, controlling how many pixels are stuffed into a packet. + * + * Value is pixels minus 1. Must be set to 1 pixel for SDVO. + */ +# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 +# define DPLL_MD_UDI_DIVIDER_SHIFT 24 +/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ +# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 +# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 +/** + * SDVO/UDI pixel multiplier. + * + * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus + * clock rate is 10 times the DPLL clock. At low resolution/refresh rate + * modes, the bus rate would be below the limits, so SDVO allows for stuffing + * dummy bytes in the datastream at an increased clock rate, with both sides of + * the link knowing how many bytes are fill. + * + * So, for a mode with a dotclock of 65Mhz, we would want to double the clock + * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be + * set to 130Mhz, and the SDVO multiplier set to 2x in this register and + * through an SDVO command. + * + * This register field has values of multiplication factor minus 1, with + * a maximum multiplier of 5 for SDVO. + */ +# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 +# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 +/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. + * This best be set to the default value (3) or the CRT won't work. No, + * I don't entirely understand what this does... + */ +# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f +# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 +/** @} */ + +#define DPLL_TEST 0x606c +# define DPLLB_TEST_SDVO_DIV_1 (0 << 22) +# define DPLLB_TEST_SDVO_DIV_2 (1 << 22) +# define DPLLB_TEST_SDVO_DIV_4 (2 << 22) +# define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) +# define DPLLB_TEST_N_BYPASS (1 << 19) +# define DPLLB_TEST_M_BYPASS (1 << 18) +# define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) +# define DPLLA_TEST_N_BYPASS (1 << 3) +# define DPLLA_TEST_M_BYPASS (1 << 2) +# define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) + +#define D_STATE 0x6104 +#define DSPCLK_GATE_D 0x6200 +# define DPUNIT_B_CLOCK_GATE_DISABLE (1 << 30) /* 965 */ +# define VSUNIT_CLOCK_GATE_DISABLE (1 << 29) /* 965 */ +# define VRHUNIT_CLOCK_GATE_DISABLE (1 << 28) /* 965 */ +# define VRDUNIT_CLOCK_GATE_DISABLE (1 << 27) /* 965 */ +# define AUDUNIT_CLOCK_GATE_DISABLE (1 << 26) /* 965 */ +# define DPUNIT_A_CLOCK_GATE_DISABLE (1 << 25) /* 965 */ +# define DPCUNIT_CLOCK_GATE_DISABLE (1 << 24) /* 965 */ +# define TVRUNIT_CLOCK_GATE_DISABLE (1 << 23) /* 915-945 */ +# define TVCUNIT_CLOCK_GATE_DISABLE (1 << 22) /* 915-945 */ +# define TVFUNIT_CLOCK_GATE_DISABLE (1 << 21) /* 915-945 */ +# define TVEUNIT_CLOCK_GATE_DISABLE (1 << 20) /* 915-945 */ +# define DVSUNIT_CLOCK_GATE_DISABLE (1 << 19) /* 915-945 */ +# define DSSUNIT_CLOCK_GATE_DISABLE (1 << 18) /* 915-945 */ +# define DDBUNIT_CLOCK_GATE_DISABLE (1 << 17) /* 915-945 */ +# define DPRUNIT_CLOCK_GATE_DISABLE (1 << 16) /* 915-945 */ +# define DPFUNIT_CLOCK_GATE_DISABLE (1 << 15) /* 915-945 */ +# define DPBMUNIT_CLOCK_GATE_DISABLE (1 << 14) /* 915-945 */ +# define DPLSUNIT_CLOCK_GATE_DISABLE (1 << 13) /* 915-945 */ +# define DPLUNIT_CLOCK_GATE_DISABLE (1 << 12) /* 915-945 */ +# define DPOUNIT_CLOCK_GATE_DISABLE (1 << 11) +# define DPBUNIT_CLOCK_GATE_DISABLE (1 << 10) +# define DCUNIT_CLOCK_GATE_DISABLE (1 << 9) +# define DPUNIT_CLOCK_GATE_DISABLE (1 << 8) +# define VRUNIT_CLOCK_GATE_DISABLE (1 << 7) /* 915+: reserved */ +# define OVHUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 830-865 */ +# define DPIOUNIT_CLOCK_GATE_DISABLE (1 << 6) /* 915-945 */ +# define OVFUNIT_CLOCK_GATE_DISABLE (1 << 5) +# define OVBUNIT_CLOCK_GATE_DISABLE (1 << 4) +/** + * This bit must be set on the 830 to prevent hangs when turning off the + * overlay scaler. + */ +# define OVRUNIT_CLOCK_GATE_DISABLE (1 << 3) +# define OVCUNIT_CLOCK_GATE_DISABLE (1 << 2) +# define OVUUNIT_CLOCK_GATE_DISABLE (1 << 1) +# define ZVUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 830 */ +# define OVLUNIT_CLOCK_GATE_DISABLE (1 << 0) /* 845,865 */ + +#define RENCLK_GATE_D1 0x6204 +# define BLITTER_CLOCK_GATE_DISABLE (1 << 13) /* 945GM only */ +# define MPEG_CLOCK_GATE_DISABLE (1 << 12) /* 945GM only */ +# define PC_FE_CLOCK_GATE_DISABLE (1 << 11) +# define PC_BE_CLOCK_GATE_DISABLE (1 << 10) +# define WINDOWER_CLOCK_GATE_DISABLE (1 << 9) +# define INTERPOLATOR_CLOCK_GATE_DISABLE (1 << 8) +# define COLOR_CALCULATOR_CLOCK_GATE_DISABLE (1 << 7) +# define MOTION_COMP_CLOCK_GATE_DISABLE (1 << 6) +# define MAG_CLOCK_GATE_DISABLE (1 << 5) +/** This bit must be unset on 855,865 */ +# define MECI_CLOCK_GATE_DISABLE (1 << 4) +# define DCMP_CLOCK_GATE_DISABLE (1 << 3) +# define MEC_CLOCK_GATE_DISABLE (1 << 2) +# define MECO_CLOCK_GATE_DISABLE (1 << 1) +/** This bit must be set on 855,865. */ +# define SV_CLOCK_GATE_DISABLE (1 << 0) +# define I915_MPEG_CLOCK_GATE_DISABLE (1 << 16) +# define I915_VLD_IP_PR_CLOCK_GATE_DISABLE (1 << 15) +# define I915_MOTION_COMP_CLOCK_GATE_DISABLE (1 << 14) +# define I915_BD_BF_CLOCK_GATE_DISABLE (1 << 13) +# define I915_SF_SE_CLOCK_GATE_DISABLE (1 << 12) +# define I915_WM_CLOCK_GATE_DISABLE (1 << 11) +# define I915_IZ_CLOCK_GATE_DISABLE (1 << 10) +# define I915_PI_CLOCK_GATE_DISABLE (1 << 9) +# define I915_DI_CLOCK_GATE_DISABLE (1 << 8) +# define I915_SH_SV_CLOCK_GATE_DISABLE (1 << 7) +# define I915_PL_DG_QC_FT_CLOCK_GATE_DISABLE (1 << 6) +# define I915_SC_CLOCK_GATE_DISABLE (1 << 5) +# define I915_FL_CLOCK_GATE_DISABLE (1 << 4) +# define I915_DM_CLOCK_GATE_DISABLE (1 << 3) +# define I915_PS_CLOCK_GATE_DISABLE (1 << 2) +# define I915_CC_CLOCK_GATE_DISABLE (1 << 1) +# define I915_BY_CLOCK_GATE_DISABLE (1 << 0) + +# define I965_RCZ_CLOCK_GATE_DISABLE (1 << 30) +/** This bit must always be set on 965G/965GM */ +# define I965_RCC_CLOCK_GATE_DISABLE (1 << 29) +# define I965_RCPB_CLOCK_GATE_DISABLE (1 << 28) +# define I965_DAP_CLOCK_GATE_DISABLE (1 << 27) +# define I965_ROC_CLOCK_GATE_DISABLE (1 << 26) +# define I965_GW_CLOCK_GATE_DISABLE (1 << 25) +# define I965_TD_CLOCK_GATE_DISABLE (1 << 24) +/** This bit must always be set on 965G */ +# define I965_ISC_CLOCK_GATE_DISABLE (1 << 23) +# define I965_IC_CLOCK_GATE_DISABLE (1 << 22) +# define I965_EU_CLOCK_GATE_DISABLE (1 << 21) +# define I965_IF_CLOCK_GATE_DISABLE (1 << 20) +# define I965_TC_CLOCK_GATE_DISABLE (1 << 19) +# define I965_SO_CLOCK_GATE_DISABLE (1 << 17) +# define I965_FBC_CLOCK_GATE_DISABLE (1 << 16) +# define I965_MARI_CLOCK_GATE_DISABLE (1 << 15) +# define I965_MASF_CLOCK_GATE_DISABLE (1 << 14) +# define I965_MAWB_CLOCK_GATE_DISABLE (1 << 13) +# define I965_EM_CLOCK_GATE_DISABLE (1 << 12) +# define I965_UC_CLOCK_GATE_DISABLE (1 << 11) +# define I965_SI_CLOCK_GATE_DISABLE (1 << 6) +# define I965_MT_CLOCK_GATE_DISABLE (1 << 5) +# define I965_PL_CLOCK_GATE_DISABLE (1 << 4) +# define I965_DG_CLOCK_GATE_DISABLE (1 << 3) +# define I965_QC_CLOCK_GATE_DISABLE (1 << 2) +# define I965_FT_CLOCK_GATE_DISABLE (1 << 1) +# define I965_DM_CLOCK_GATE_DISABLE (1 << 0) + +#define RENCLK_GATE_D2 0x6208 +#define VF_UNIT_CLOCK_GATE_DISABLE (1 << 9) +#define GS_UNIT_CLOCK_GATE_DISABLE (1 << 7) +#define CL_UNIT_CLOCK_GATE_DISABLE (1 << 6) +#define RAMCLK_GATE_D 0x6210 /* CRL only */ +#define DEUC 0x6214 /* CRL only */ + +/* + * This is a PCI config space register to manipulate backlight brightness + * It is used when the BLM_LEGACY_MODE is turned on. When enabled, the first + * byte of this config register sets brightness within the range from + * 0 to 0xff + */ +#define LEGACY_BACKLIGHT_BRIGHTNESS 0xf4 + +#define BLC_PWM_CTL 0x61254 +#define BACKLIGHT_MODULATION_FREQ_SHIFT (17) +#define BACKLIGHT_MODULATION_FREQ_SHIFT2 (16) +/** + * This is the most significant 15 bits of the number of backlight cycles in a + * complete cycle of the modulated backlight control. + * + * The actual value is this field multiplied by two. + */ +#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) +#define BACKLIGHT_MODULATION_FREQ_MASK2 (0xffff << 16) +#define BLM_LEGACY_MODE (1 << 16) + +/** + * This is the number of cycles out of the backlight modulation cycle for which + * the backlight is on. + * + * This field must be no greater than the number of cycles in the complete + * backlight modulation cycle. + */ +#define BACKLIGHT_DUTY_CYCLE_SHIFT (0) +#define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) + +/* On 965+ backlight control is in another register */ +#define BLC_PWM_CTL2 0x61250 +#define BLM_LEGACY_MODE2 (1 << 30) + +#define BLM_CTL 0x61260 +#define BLM_THRESHOLD_0 0x61270 +#define BLM_THRESHOLD_1 0x61274 +#define BLM_THRESHOLD_2 0x61278 +#define BLM_THRESHOLD_3 0x6127c +#define BLM_THRESHOLD_4 0x61280 +#define BLM_THRESHOLD_5 0x61284 + +#define BLM_ACCUMULATOR_0 0x61290 +#define BLM_ACCUMULATOR_1 0x61294 +#define BLM_ACCUMULATOR_2 0x61298 +#define BLM_ACCUMULATOR_3 0x6129c +#define BLM_ACCUMULATOR_4 0x612a0 +#define BLM_ACCUMULATOR_5 0x612a4 + +#define FPA0 0x06040 +#define FPA1 0x06044 +#define FPB0 0x06048 +#define FPB1 0x0604c +# define FP_N_DIV_MASK 0x003f0000 +# define FP_N_IGD_DIV_MASK 0x00ff0000 +# define FP_N_DIV_SHIFT 16 +# define FP_M1_DIV_MASK 0x00003f00 +# define FP_M1_DIV_SHIFT 8 +# define FP_M2_DIV_MASK 0x0000003f +# define FP_M2_IGD_DIV_MASK 0x000000ff +# define FP_M2_DIV_SHIFT 0 + +#define PORT_HOTPLUG_EN 0x61110 +# define HDMIB_HOTPLUG_INT_EN (1 << 29) +# define HDMIC_HOTPLUG_INT_EN (1 << 28) +# define HDMID_HOTPLUG_INT_EN (1 << 27) +# define SDVOB_HOTPLUG_INT_EN (1 << 26) +# define SDVOC_HOTPLUG_INT_EN (1 << 25) +# define TV_HOTPLUG_INT_EN (1 << 18) +# define CRT_HOTPLUG_INT_EN (1 << 9) +# define CRT_HOTPLUG_ACTIVATION_PERIOD_32 (0 << 8) +/* must use period 64 on GM45 according to docs */ +# define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) +# define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) +# define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) +# define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) +# define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) +# define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) +# define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) +# define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) +# define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) +# define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) +# define CRT_HOTPLUG_FORCE_DETECT (1 << 3) +# define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) +# define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) +# define CRT_HOTPLUG_MASK (0x3fc) /* Bits 9-2 */ +# define CRT_FORCE_HOTPLUG_MASK 0xfffffe1f + +#define PORT_HOTPLUG_STAT 0x61114 +# define HDMIB_HOTPLUG_INT_STATUS (1 << 29) +# define HDMIC_HOTPLUG_INT_STATUS (1 << 28) +# define HDMID_HOTPLUG_INT_STATUS (1 << 27) +# define CRT_HOTPLUG_INT_STATUS (1 << 11) +# define TV_HOTPLUG_INT_STATUS (1 << 10) +# define CRT_HOTPLUG_MONITOR_MASK (3 << 8) +# define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) +# define CRT_HOTPLUG_MONITOR_MONO (2 << 8) +# define CRT_HOTPLUG_MONITOR_NONE (0 << 8) +# define SDVOC_HOTPLUG_INT_STATUS (1 << 7) +# define SDVOB_HOTPLUG_INT_STATUS (1 << 6) + +#define SDVOB 0x61140 +#define SDVOC 0x61160 +#define SDVO_ENABLE (1 << 31) +#define SDVO_PIPE_B_SELECT (1 << 30) +#define SDVO_STALL_SELECT (1 << 29) +#define SDVO_INTERRUPT_ENABLE (1 << 26) +/** + * 915G/GM SDVO pixel multiplier. + * + * Programmed value is multiplier - 1, up to 5x. + * + * \sa DPLL_MD_UDI_MULTIPLIER_MASK + */ +#define SDVO_PORT_MULTIPLY_MASK (7 << 23) +#define SDVO_PORT_MULTIPLY_SHIFT 23 +#define SDVO_PHASE_SELECT_MASK (15 << 19) +#define SDVO_PHASE_SELECT_DEFAULT (6 << 19) +#define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) +#define SDVOC_GANG_MODE (1 << 16) +#define SDVO_ENCODING_SDVO (0x0 << 10) +#define SDVO_ENCODING_HDMI (0x2 << 10) +/** Requird for HDMI operation */ +#define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) +#define SDVO_COLOR_NOT_FULL_RANGE (1 << 8) +#define SDVO_BORDER_ENABLE (1 << 7) +#define SDVO_AUDIO_ENABLE (1 << 6) +/** New with 965, default is to be set */ +#define SDVO_VSYNC_ACTIVE_HIGH (1 << 4) +/** New with 965, default is to be set */ +#define SDVO_HSYNC_ACTIVE_HIGH (1 << 3) +/** 915/945 only, read-only bit */ +#define SDVOB_PCIE_CONCURRENCY (1 << 3) +#define SDVO_DETECTED (1 << 2) +/* Bits to be preserved when writing */ +#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) +#define SDVOC_PRESERVE_MASK (1 << 17) + +#define UDIB_SVB_SHB_CODES 0x61144 +#define UDIB_SHA_BLANK_CODES 0x61148 +#define UDIB_START_END_FILL_CODES 0x6114c + + +#define SDVOUDI 0x61150 + +#define I830_HTOTAL_MASK 0xfff0000 +#define I830_HACTIVE_MASK 0x7ff + +#define I830_HBLANKEND_MASK 0xfff0000 +#define I830_HBLANKSTART_MASK 0xfff + +#define I830_HSYNCEND_MASK 0xfff0000 +#define I830_HSYNCSTART_MASK 0xfff + +#define I830_VTOTAL_MASK 0xfff0000 +#define I830_VACTIVE_MASK 0x7ff + +#define I830_VBLANKEND_MASK 0xfff0000 +#define I830_VBLANKSTART_MASK 0xfff + +#define I830_VSYNCEND_MASK 0xfff0000 +#define I830_VSYNCSTART_MASK 0xfff + +#define I830_PIPEA_HORZ_MASK 0x7ff0000 +#define I830_PIPEA_VERT_MASK 0x7ff + +#define ADPA 0x61100 +#define ADPA_DAC_ENABLE (1<<31) +#define ADPA_DAC_DISABLE 0 +#define ADPA_PIPE_SELECT_MASK (1<<30) +#define ADPA_PIPE_A_SELECT 0 +#define ADPA_PIPE_B_SELECT (1<<30) +#define ADPA_USE_VGA_HVPOLARITY (1<<15) +#define ADPA_SETS_HVPOLARITY 0 +#define ADPA_VSYNC_CNTL_DISABLE (1<<11) +#define ADPA_VSYNC_CNTL_ENABLE 0 +#define ADPA_HSYNC_CNTL_DISABLE (1<<10) +#define ADPA_HSYNC_CNTL_ENABLE 0 +#define ADPA_VSYNC_ACTIVE_HIGH (1<<4) +#define ADPA_VSYNC_ACTIVE_LOW 0 +#define ADPA_HSYNC_ACTIVE_HIGH (1<<3) +#define ADPA_HSYNC_ACTIVE_LOW 0 + + +#define DVOA 0x61120 +#define DVOB 0x61140 +#define DVOC 0x61160 +#define DVO_ENABLE (1 << 31) +#define DVO_PIPE_B_SELECT (1 << 30) +#define DVO_PIPE_STALL_UNUSED (0 << 28) +#define DVO_PIPE_STALL (1 << 28) +#define DVO_PIPE_STALL_TV (2 << 28) +#define DVO_PIPE_STALL_MASK (3 << 28) +#define DVO_USE_VGA_SYNC (1 << 15) +#define DVO_DATA_ORDER_I740 (0 << 14) +#define DVO_DATA_ORDER_FP (1 << 14) +#define DVO_VSYNC_DISABLE (1 << 11) +#define DVO_HSYNC_DISABLE (1 << 10) +#define DVO_VSYNC_TRISTATE (1 << 9) +#define DVO_HSYNC_TRISTATE (1 << 8) +#define DVO_BORDER_ENABLE (1 << 7) +#define DVO_DATA_ORDER_GBRG (1 << 6) +#define DVO_DATA_ORDER_RGGB (0 << 6) +#define DVO_DATA_ORDER_GBRG_ERRATA (0 << 6) +#define DVO_DATA_ORDER_RGGB_ERRATA (1 << 6) +#define DVO_VSYNC_ACTIVE_HIGH (1 << 4) +#define DVO_HSYNC_ACTIVE_HIGH (1 << 3) +#define DVO_BLANK_ACTIVE_HIGH (1 << 2) +#define DVO_OUTPUT_CSTATE_PIXELS (1 << 1) /* SDG only */ +#define DVO_OUTPUT_SOURCE_SIZE_PIXELS (1 << 0) /* SDG only */ +#define DVO_PRESERVE_MASK (0x7<<24) + +#define DVOA_SRCDIM 0x61124 +#define DVOB_SRCDIM 0x61144 +#define DVOC_SRCDIM 0x61164 +#define DVO_SRCDIM_HORIZONTAL_SHIFT 12 +#define DVO_SRCDIM_VERTICAL_SHIFT 0 + +/** @defgroup LVDS + * @{ + */ +/** + * This register controls the LVDS output enable, pipe selection, and data + * format selection. + * + * All of the clock/data pairs are force powered down by power sequencing. + */ +#define LVDS 0x61180 +/** + * Enables the LVDS port. This bit must be set before DPLLs are enabled, as + * the DPLL semantics change when the LVDS is assigned to that pipe. + */ +# define LVDS_PORT_EN (1 << 31) +/** Selects pipe B for LVDS data. Must be set on pre-965. */ +# define LVDS_PIPEB_SELECT (1 << 30) + +/* on 965, dithering is enabled in this register, not PFIT_CONTROL */ +# define LVDS_DITHER_ENABLE (1 << 25) + +/* + * Selects between .0 and .1 formats: + * + * 0 = 1x18.0, 2x18.0, 1x24.0 or 2x24.0 + * 1 = 1x24.1 or 2x24.1 + */ +# define LVDS_DATA_FORMAT_DOT_ONE (1 << 24) + +/* Using LE instead of HS on second channel control signal */ +# define LVDS_LE_CONTROL_ENABLE (1 << 23) + +/* Using LF instead of VS on second channel control signal */ +# define LVDS_LF_CONTROL_ENABLE (1 << 22) + +/* invert vsync signal polarity */ +# define LVDS_VSYNC_POLARITY_INVERT (1 << 21) + +/* invert hsync signal polarity */ +# define LVDS_HSYNC_POLARITY_INVERT (1 << 20) + +/* invert display enable signal polarity */ +# define LVDS_DE_POLARITY_INVERT (1 << 19) + +/* + * Control signals for second channel, ignored in single channel modes + */ + +/* send DE, HS, VS on second channel */ +# define LVDS_SECOND_CHANNEL_DE_HS_VS (0 << 17) + +# define LVDS_SECOND_CHANNEL_RESERVED (1 << 17) + +/* Send zeros instead of DE, HS, VS on second channel */ +# define LVDS_SECOND_CHANNEL_ZEROS (2 << 17) + +/* Set DE=0, HS=LE, VS=LF on second channel */ +# define LVDS_SECOND_CHANNEL_HS_VS (3 << 17) + +/* + * Send duplicate data for channel reserved bits, otherwise send zeros + */ +# define LVDS_CHANNEL_DUP_RESERVED (1 << 16) + +/* + * Enable border for unscaled (or aspect-scaled) display + */ +# define LVDS_BORDER_ENABLE (1 << 15) + +/* + * Tri-state the LVDS buffers when powered down, otherwise + * they are set to 0V + */ +# define LVDS_POWER_DOWN_TRI_STATE (1 << 10) + +/** + * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per + * pixel. + */ +# define LVDS_A0A2_CLKA_POWER_MASK (3 << 8) +# define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8) +# define LVDS_A0A2_CLKA_POWER_UP (3 << 8) +/** + * Controls the A3 data pair, which contains the additional LSBs for 24 bit + * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be + * on. + */ +# define LVDS_A3_POWER_MASK (3 << 6) +# define LVDS_A3_POWER_DOWN (0 << 6) +# define LVDS_A3_POWER_UP (3 << 6) +/** + * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP + * is set. + */ +# define LVDS_CLKB_POWER_MASK (3 << 4) +# define LVDS_CLKB_POWER_DOWN (0 << 4) +# define LVDS_CLKB_POWER_UP (3 << 4) + +/** + * Controls the B0-B3 data pairs. This must be set to match the DPLL p2 + * setting for whether we are in dual-channel mode. The B3 pair will + * additionally only be powered up when LVDS_A3_POWER_UP is set. + */ +# define LVDS_B0B3_POWER_MASK (3 << 2) +# define LVDS_B0B3_POWER_DOWN (0 << 2) +# define LVDS_B0B3_POWER_UP (3 << 2) + +/** @} */ + +#define DP_B 0x64100 +#define DPB_AUX_CH_CTL 0x64110 +#define DPB_AUX_CH_DATA1 0x64114 +#define DPB_AUX_CH_DATA2 0x64118 +#define DPB_AUX_CH_DATA3 0x6411c +#define DPB_AUX_CH_DATA4 0x64120 +#define DPB_AUX_CH_DATA5 0x64124 + +#define DP_C 0x64200 +#define DPC_AUX_CH_CTL 0x64210 +#define DPC_AUX_CH_DATA1 0x64214 +#define DPC_AUX_CH_DATA2 0x64218 +#define DPC_AUX_CH_DATA3 0x6421c +#define DPC_AUX_CH_DATA4 0x64220 +#define DPC_AUX_CH_DATA5 0x64224 + +#define DP_D 0x64300 +#define DPD_AUX_CH_CTL 0x64310 +#define DPD_AUX_CH_DATA1 0x64314 +#define DPD_AUX_CH_DATA2 0x64318 +#define DPD_AUX_CH_DATA3 0x6431c +#define DPD_AUX_CH_DATA4 0x64320 +#define DPD_AUX_CH_DATA5 0x64324 + +/* + * Two channel clock control. Turn this on if you need clkb for two channel mode + * Overridden by global LVDS power sequencing + */ + +/* clkb off */ +# define LVDS_CLKB_POWER_DOWN (0 << 4) + +/* powered up, but clkb forced to 0 */ +# define LVDS_CLKB_POWER_PARTIAL (1 << 4) + +/* clock B running */ +# define LVDS_CLKB_POWER_UP (3 << 4) + +/* + * Two channel mode B0-B2 control. Sets state when power is on. + * Set to POWER_DOWN in single channel mode, other settings enable + * two channel mode. The CLKB power control controls whether that clock + * is enabled during two channel mode. + * + */ +/* Everything is off, including B3 and CLKB */ +# define LVDS_B_POWER_DOWN (0 << 2) + +/* B0, B1, B2 and data lines forced to 0. timing is active */ +# define LVDS_B_POWER_PARTIAL (1 << 2) + +/* data lines active (both timing and colour) */ +# define LVDS_B_POWER_UP (3 << 2) + +/** @defgroup TV_CTL + * @{ + */ +#define TV_CTL 0x68000 +/** Enables the TV encoder */ +# define TV_ENC_ENABLE (1 << 31) +/** Sources the TV encoder input from pipe B instead of A. */ +# define TV_ENC_PIPEB_SELECT (1 << 30) +/** Outputs composite video (DAC A only) */ +# define TV_ENC_OUTPUT_COMPOSITE (0 << 28) +/** Outputs SVideo video (DAC B/C) */ +# define TV_ENC_OUTPUT_SVIDEO (1 << 28) +/** Outputs Component video (DAC A/B/C) */ +# define TV_ENC_OUTPUT_COMPONENT (2 << 28) +/** Outputs Composite and SVideo (DAC A/B/C) */ +# define TV_ENC_OUTPUT_SVIDEO_COMPOSITE (3 << 28) +# define TV_TRILEVEL_SYNC (1 << 21) +/** Enables slow sync generation (945GM only) */ +# define TV_SLOW_SYNC (1 << 20) +/** Selects 4x oversampling for 480i and 576p */ +# define TV_OVERSAMPLE_4X (0 << 18) +/** Selects 2x oversampling for 720p and 1080i */ +# define TV_OVERSAMPLE_2X (1 << 18) +/** Selects no oversampling for 1080p */ +# define TV_OVERSAMPLE_NONE (2 << 18) +/** Selects 8x oversampling */ +# define TV_OVERSAMPLE_8X (3 << 18) +/** Selects progressive mode rather than interlaced */ +# define TV_PROGRESSIVE (1 << 17) +/** Sets the colorburst to PAL mode. Required for non-M PAL modes. */ +# define TV_PAL_BURST (1 << 16) +/** Field for setting delay of Y compared to C */ +# define TV_YC_SKEW_MASK (7 << 12) +/** Enables a fix for 480p/576p standard definition modes on the 915GM only */ +# define TV_ENC_SDP_FIX (1 << 11) +/** + * Enables a fix for the 915GM only. + * + * Not sure what it does. + */ +# define TV_ENC_C0_FIX (1 << 10) +/** Bits that must be preserved by software */ +# define TV_CTL_SAVE ((1 << 11) | (3 << 9) | (7 << 6) | 0xf) +# define TV_FUSE_STATE_MASK (3 << 4) +/** Read-only state that reports all features enabled */ +# define TV_FUSE_STATE_ENABLED (0 << 4) +/** Read-only state that reports that Macrovision is disabled in hardware*/ +# define TV_FUSE_STATE_NO_MACROVISION (1 << 4) +/** Read-only state that reports that TV-out is disabled in hardware. */ +# define TV_FUSE_STATE_DISABLED (2 << 4) +/** Normal operation */ +# define TV_TEST_MODE_NORMAL (0 << 0) +/** Encoder test pattern 1 - combo pattern */ +# define TV_TEST_MODE_PATTERN_1 (1 << 0) +/** Encoder test pattern 2 - full screen vertical 75% color bars */ +# define TV_TEST_MODE_PATTERN_2 (2 << 0) +/** Encoder test pattern 3 - full screen horizontal 75% color bars */ +# define TV_TEST_MODE_PATTERN_3 (3 << 0) +/** Encoder test pattern 4 - random noise */ +# define TV_TEST_MODE_PATTERN_4 (4 << 0) +/** Encoder test pattern 5 - linear color ramps */ +# define TV_TEST_MODE_PATTERN_5 (5 << 0) +/** + * This test mode forces the DACs to 50% of full output. + * + * This is used for load detection in combination with TVDAC_SENSE_MASK + */ +# define TV_TEST_MODE_MONITOR_DETECT (7 << 0) +# define TV_TEST_MODE_MASK (7 << 0) +/** @} */ + +/** @defgroup TV_DAC + * @{ + */ +#define TV_DAC 0x68004 +/** + * Reports that DAC state change logic has reported change (RO). + * + * This gets cleared when TV_DAC_STATE_EN is cleared +*/ +# define TVDAC_STATE_CHG (1 << 31) +# define TVDAC_SENSE_MASK (7 << 28) +/** Reports that DAC A voltage is above the detect threshold */ +# define TVDAC_A_SENSE (1 << 30) +/** Reports that DAC B voltage is above the detect threshold */ +# define TVDAC_B_SENSE (1 << 29) +/** Reports that DAC C voltage is above the detect threshold */ +# define TVDAC_C_SENSE (1 << 28) +/** + * Enables DAC state detection logic, for load-based TV detection. + * + * The PLL of the chosen pipe (in TV_CTL) must be running, and the encoder set + * to off, for load detection to work. + */ +# define TVDAC_STATE_CHG_EN (1 << 27) +/** Sets the DAC A sense value to high */ +# define TVDAC_A_SENSE_CTL (1 << 26) +/** Sets the DAC B sense value to high */ +# define TVDAC_B_SENSE_CTL (1 << 25) +/** Sets the DAC C sense value to high */ +# define TVDAC_C_SENSE_CTL (1 << 24) +/** Overrides the ENC_ENABLE and DAC voltage levels */ +# define DAC_CTL_OVERRIDE (1 << 7) +/** Sets the slew rate. Must be preserved in software */ +# define ENC_TVDAC_SLEW_FAST (1 << 6) +# define DAC_A_1_3_V (0 << 4) +# define DAC_A_1_1_V (1 << 4) +# define DAC_A_0_7_V (2 << 4) +# define DAC_A_MASK (3 << 4) +# define DAC_B_1_3_V (0 << 2) +# define DAC_B_1_1_V (1 << 2) +# define DAC_B_0_7_V (2 << 2) +# define DAC_B_MASK (3 << 2) +# define DAC_C_1_3_V (0 << 0) +# define DAC_C_1_1_V (1 << 0) +# define DAC_C_0_7_V (2 << 0) +# define DAC_C_MASK (3 << 0) +/** @} */ + +/** + * CSC coefficients are stored in a floating point format with 9 bits of + * mantissa and 2 or 3 bits of exponent. The exponent is represented as 2**-n, + * where 2-bit exponents are unsigned n, and 3-bit exponents are signed n with + * -1 (0x3) being the only legal negative value. + */ +#define TV_CSC_Y 0x68010 +# define TV_RY_MASK 0x07ff0000 +# define TV_RY_SHIFT 16 +# define TV_GY_MASK 0x00000fff +# define TV_GY_SHIFT 0 + +#define TV_CSC_Y2 0x68014 +# define TV_BY_MASK 0x07ff0000 +# define TV_BY_SHIFT 16 +/** + * Y attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AY_MASK 0x000003ff +# define TV_AY_SHIFT 0 + +#define TV_CSC_U 0x68018 +# define TV_RU_MASK 0x07ff0000 +# define TV_RU_SHIFT 16 +# define TV_GU_MASK 0x000007ff +# define TV_GU_SHIFT 0 + +#define TV_CSC_U2 0x6801c +# define TV_BU_MASK 0x07ff0000 +# define TV_BU_SHIFT 16 +/** + * U attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AU_MASK 0x000003ff +# define TV_AU_SHIFT 0 + +#define TV_CSC_V 0x68020 +# define TV_RV_MASK 0x0fff0000 +# define TV_RV_SHIFT 16 +# define TV_GV_MASK 0x000007ff +# define TV_GV_SHIFT 0 + +#define TV_CSC_V2 0x68024 +# define TV_BV_MASK 0x07ff0000 +# define TV_BV_SHIFT 16 +/** + * V attenuation for component video. + * + * Stored in 1.9 fixed point. + */ +# define TV_AV_MASK 0x000007ff +# define TV_AV_SHIFT 0 + +/** @defgroup TV_CSC_KNOBS + * @{ + */ +#define TV_CLR_KNOBS 0x68028 +/** 2s-complement brightness adjustment */ +# define TV_BRIGHTNESS_MASK 0xff000000 +# define TV_BRIGHTNESS_SHIFT 24 +/** Contrast adjustment, as a 2.6 unsigned floating point number */ +# define TV_CONTRAST_MASK 0x00ff0000 +# define TV_CONTRAST_SHIFT 16 +/** Saturation adjustment, as a 2.6 unsigned floating point number */ +# define TV_SATURATION_MASK 0x0000ff00 +# define TV_SATURATION_SHIFT 8 +/** Hue adjustment, as an integer phase angle in degrees */ +# define TV_HUE_MASK 0x000000ff +# define TV_HUE_SHIFT 0 +/** @} */ + +/** @defgroup TV_CLR_LEVEL + * @{ + */ +#define TV_CLR_LEVEL 0x6802c +/** Controls the DAC level for black */ +# define TV_BLACK_LEVEL_MASK 0x01ff0000 +# define TV_BLACK_LEVEL_SHIFT 16 +/** Controls the DAC level for blanking */ +# define TV_BLANK_LEVEL_MASK 0x000001ff +# define TV_BLANK_LEVEL_SHIFT 0 +/* @} */ + +/** @defgroup TV_H_CTL_1 + * @{ + */ +#define TV_H_CTL_1 0x68030 +/** Number of pixels in the hsync. */ +# define TV_HSYNC_END_MASK 0x1fff0000 +# define TV_HSYNC_END_SHIFT 16 +/** Total number of pixels minus one in the line (display and blanking). */ +# define TV_HTOTAL_MASK 0x00001fff +# define TV_HTOTAL_SHIFT 0 +/** @} */ + +/** @defgroup TV_H_CTL_2 + * @{ + */ +#define TV_H_CTL_2 0x68034 +/** Enables the colorburst (needed for non-component color) */ +# define TV_BURST_ENA (1 << 31) +/** Offset of the colorburst from the start of hsync, in pixels minus one. */ +# define TV_HBURST_START_SHIFT 16 +# define TV_HBURST_START_MASK 0x1fff0000 +/** Length of the colorburst */ +# define TV_HBURST_LEN_SHIFT 0 +# define TV_HBURST_LEN_MASK 0x0001fff +/** @} */ + +/** @defgroup TV_H_CTL_3 + * @{ + */ +#define TV_H_CTL_3 0x68038 +/** End of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_END_SHIFT 16 +# define TV_HBLANK_END_MASK 0x1fff0000 +/** Start of hblank, measured in pixels minus one from start of hsync */ +# define TV_HBLANK_START_SHIFT 0 +# define TV_HBLANK_START_MASK 0x0001fff +/** @} */ + +/** @defgroup TV_V_CTL_1 + * @{ + */ +#define TV_V_CTL_1 0x6803c +/** XXX */ +# define TV_NBR_END_SHIFT 16 +# define TV_NBR_END_MASK 0x07ff0000 +/** XXX */ +# define TV_VI_END_F1_SHIFT 8 +# define TV_VI_END_F1_MASK 0x00003f00 +/** XXX */ +# define TV_VI_END_F2_SHIFT 0 +# define TV_VI_END_F2_MASK 0x0000003f +/** @} */ + +/** @defgroup TV_V_CTL_2 + * @{ + */ +#define TV_V_CTL_2 0x68040 +/** Length of vsync, in half lines */ +# define TV_VSYNC_LEN_MASK 0x07ff0000 +# define TV_VSYNC_LEN_SHIFT 16 +/** Offset of the start of vsync in field 1, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F1_MASK 0x00007f00 +# define TV_VSYNC_START_F1_SHIFT 8 +/** + * Offset of the start of vsync in field 2, measured in one less than the + * number of half lines. + */ +# define TV_VSYNC_START_F2_MASK 0x0000007f +# define TV_VSYNC_START_F2_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_3 + * @{ + */ +#define TV_V_CTL_3 0x68044 +/** Enables generation of the equalization signal */ +# define TV_EQUAL_ENA (1 << 31) +/** Length of vsync, in half lines */ +# define TV_VEQ_LEN_MASK 0x007f0000 +# define TV_VEQ_LEN_SHIFT 16 +/** Offset of the start of equalization in field 1, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F1_MASK 0x0007f00 +# define TV_VEQ_START_F1_SHIFT 8 +/** + * Offset of the start of equalization in field 2, measured in one less than + * the number of half lines. + */ +# define TV_VEQ_START_F2_MASK 0x000007f +# define TV_VEQ_START_F2_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_4 + * @{ + */ +#define TV_V_CTL_4 0x68048 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F1_MASK 0x003f0000 +# define TV_VBURST_START_F1_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F1_MASK 0x000000ff +# define TV_VBURST_END_F1_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_5 + * @{ + */ +#define TV_V_CTL_5 0x6804c +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F2_MASK 0x003f0000 +# define TV_VBURST_START_F2_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F2_MASK 0x000000ff +# define TV_VBURST_END_F2_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_6 + * @{ + */ +#define TV_V_CTL_6 0x68050 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F3_MASK 0x003f0000 +# define TV_VBURST_START_F3_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F3_MASK 0x000000ff +# define TV_VBURST_END_F3_SHIFT 0 +/** @} */ + +/** @defgroup TV_V_CTL_7 + * @{ + */ +#define TV_V_CTL_7 0x68054 +/** + * Offset to start of vertical colorburst, measured in one less than the + * number of lines from vertical start. + */ +# define TV_VBURST_START_F4_MASK 0x003f0000 +# define TV_VBURST_START_F4_SHIFT 16 +/** + * Offset to the end of vertical colorburst, measured in one less than the + * number of lines from the start of NBR. + */ +# define TV_VBURST_END_F4_MASK 0x000000ff +# define TV_VBURST_END_F4_SHIFT 0 +/** @} */ + +/** @defgroup TV_SC_CTL_1 + * @{ + */ +#define TV_SC_CTL_1 0x68060 +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA1_EN (1 << 31) +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA2_EN (1 << 30) +/** Turns on the first subcarrier phase generation DDA */ +# define TV_SC_DDA3_EN (1 << 29) +/** Sets the subcarrier DDA to reset frequency every other field */ +# define TV_SC_RESET_EVERY_2 (0 << 24) +/** Sets the subcarrier DDA to reset frequency every fourth field */ +# define TV_SC_RESET_EVERY_4 (1 << 24) +/** Sets the subcarrier DDA to reset frequency every eighth field */ +# define TV_SC_RESET_EVERY_8 (2 << 24) +/** Sets the subcarrier DDA to never reset the frequency */ +# define TV_SC_RESET_NEVER (3 << 24) +/** Sets the peak amplitude of the colorburst.*/ +# define TV_BURST_LEVEL_MASK 0x00ff0000 +# define TV_BURST_LEVEL_SHIFT 16 +/** Sets the increment of the first subcarrier phase generation DDA */ +# define TV_SCDDA1_INC_MASK 0x00000fff +# define TV_SCDDA1_INC_SHIFT 0 +/** @} */ + +/** @defgroup TV_SC_CTL_2 + * @{ + */ +#define TV_SC_CTL_2 0x68064 +/** Sets the rollover for the second subcarrier phase generation DDA */ +# define TV_SCDDA2_SIZE_MASK 0x7fff0000 +# define TV_SCDDA2_SIZE_SHIFT 16 +/** Sets the increent of the second subcarrier phase generation DDA */ +# define TV_SCDDA2_INC_MASK 0x00007fff +# define TV_SCDDA2_INC_SHIFT 0 +/** @} */ + +/** @defgroup TV_SC_CTL_3 + * @{ + */ +#define TV_SC_CTL_3 0x68068 +/** Sets the rollover for the third subcarrier phase generation DDA */ +# define TV_SCDDA3_SIZE_MASK 0x7fff0000 +# define TV_SCDDA3_SIZE_SHIFT 16 +/** Sets the increent of the third subcarrier phase generation DDA */ +# define TV_SCDDA3_INC_MASK 0x00007fff +# define TV_SCDDA3_INC_SHIFT 0 +/** @} */ + +/** @defgroup TV_WIN_POS + * @{ + */ +#define TV_WIN_POS 0x68070 +/** X coordinate of the display from the start of horizontal active */ +# define TV_XPOS_MASK 0x1fff0000 +# define TV_XPOS_SHIFT 16 +/** Y coordinate of the display from the start of vertical active (NBR) */ +# define TV_YPOS_MASK 0x00000fff +# define TV_YPOS_SHIFT 0 +/** @} */ + +/** @defgroup TV_WIN_SIZE + * @{ + */ +#define TV_WIN_SIZE 0x68074 +/** Horizontal size of the display window, measured in pixels*/ +# define TV_XSIZE_MASK 0x1fff0000 +# define TV_XSIZE_SHIFT 16 +/** + * Vertical size of the display window, measured in pixels. + * + * Must be even for interlaced modes. + */ +# define TV_YSIZE_MASK 0x00000fff +# define TV_YSIZE_SHIFT 0 +/** @} */ + +/** @defgroup TV_FILTER_CTL_1 + * @{ + */ +#define TV_FILTER_CTL_1 0x68080 +/** + * Enables automatic scaling calculation. + * + * If set, the rest of the registers are ignored, and the calculated values can + * be read back from the register. + */ +# define TV_AUTO_SCALE (1 << 31) +/** + * Disables the vertical filter. + * + * This is required on modes more than 1024 pixels wide */ +# define TV_V_FILTER_BYPASS (1 << 29) +/** Enables adaptive vertical filtering */ +# define TV_VADAPT (1 << 28) +# define TV_VADAPT_MODE_MASK (3 << 26) +/** Selects the least adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_LEAST (0 << 26) +/** Selects the moderately adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MODERATE (1 << 26) +/** Selects the most adaptive vertical filtering mode */ +# define TV_VADAPT_MODE_MOST (3 << 26) +/** + * Sets the horizontal scaling factor. + * + * This should be the fractional part of the horizontal scaling factor divided + * by the oversampling rate. TV_HSCALE should be less than 1, and set to: + * + * (src width - 1) / ((oversample * dest width) - 1) + */ +# define TV_HSCALE_FRAC_MASK 0x00003fff +# define TV_HSCALE_FRAC_SHIFT 0 +/** @} */ + +/** @defgroup TV_FILTER_CTL_2 + * @{ + */ +#define TV_FILTER_CTL_2 0x68084 +/** + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / ((interlace * dest height) - 1) + */ +# define TV_VSCALE_INT_MASK 0x00038000 +# define TV_VSCALE_INT_SHIFT 15 +/** + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * \sa TV_VSCALE_INT_MASK + */ +# define TV_VSCALE_FRAC_MASK 0x00007fff +# define TV_VSCALE_FRAC_SHIFT 0 +/** @} */ + +/** @defgroup TV_FILTER_CTL_3 + * @{ + */ +#define TV_FILTER_CTL_3 0x68088 +/** + * Sets the integer part of the 3.15 fixed-point vertical scaling factor. + * + * TV_VSCALE should be (src height - 1) / (1/4 * (dest height - 1)) + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + */ +# define TV_VSCALE_IP_INT_MASK 0x00038000 +# define TV_VSCALE_IP_INT_SHIFT 15 +/** + * Sets the fractional part of the 3.15 fixed-point vertical scaling factor. + * + * For progressive modes, TV_VSCALE_IP_INT should be set to zeroes. + * + * \sa TV_VSCALE_IP_INT_MASK + */ +# define TV_VSCALE_IP_FRAC_MASK 0x00007fff +# define TV_VSCALE_IP_FRAC_SHIFT 0 +/** @} */ + +/** @defgroup TV_CC_CONTROL + * @{ + */ +#define TV_CC_CONTROL 0x68090 +# define TV_CC_ENABLE (1 << 31) +/** + * Specifies which field to send the CC data in. + * + * CC data is usually sent in field 0. + */ +# define TV_CC_FID_MASK (1 << 27) +# define TV_CC_FID_SHIFT 27 +/** Sets the horizontal position of the CC data. Usually 135. */ +# define TV_CC_HOFF_MASK 0x03ff0000 +# define TV_CC_HOFF_SHIFT 16 +/** Sets the vertical position of the CC data. Usually 21 */ +# define TV_CC_LINE_MASK 0x0000003f +# define TV_CC_LINE_SHIFT 0 +/** @} */ + +/** @defgroup TV_CC_DATA + * @{ + */ +#define TV_CC_DATA 0x68094 +# define TV_CC_RDY (1 << 31) +/** Second word of CC data to be transmitted. */ +# define TV_CC_DATA_2_MASK 0x007f0000 +# define TV_CC_DATA_2_SHIFT 16 +/** First word of CC data to be transmitted. */ +# define TV_CC_DATA_1_MASK 0x0000007f +# define TV_CC_DATA_1_SHIFT 0 +/** @} + */ + +/** @{ */ +#define TV_H_LUMA_0 0x68100 +#define TV_H_LUMA_59 0x681ec +#define TV_H_CHROMA_0 0x68200 +#define TV_H_CHROMA_59 0x682ec +#define TV_V_LUMA_0 0x68300 +#define TV_V_LUMA_42 0x683a8 +#define TV_V_CHROMA_0 0x68400 +#define TV_V_CHROMA_42 0x684a8 +/** @} */ + +#define PIPEA_DSL 0x70000 + +#define PIPEACONF 0x70008 +#define PIPEACONF_ENABLE (1<<31) +#define PIPEACONF_DISABLE 0 +#define PIPEACONF_DOUBLE_WIDE (1<<30) +#define I965_PIPECONF_ACTIVE (1<<30) +#define PIPEACONF_SINGLE_WIDE 0 +#define PIPEACONF_PIPE_UNLOCKED 0 +#define PIPEACONF_PIPE_LOCKED (1<<25) +#define PIPEACONF_PALETTE 0 +#define PIPEACONF_GAMMA (1<<24) +/* IGDNG: gamma */ +#define PIPECONF_PALETTE_8BIT (0<<24) +#define PIPECONF_PALETTE_10BIT (1<<24) +#define PIPECONF_PALETTE_12BIT (2<<24) +#define PIPECONF_FORCE_BORDER (1<<25) +#define PIPECONF_PROGRESSIVE (0 << 21) +#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) +#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) +/* IGDNG */ +#define PIPECONF_MSA_TIMING_DELAY (0<<18) /* for eDP */ +#define PIPECONF_NO_DYNAMIC_RATE_CHANGE (0 << 16) +#define PIPECONF_NO_ROTATION (0<<14) +#define PIPECONF_FULL_COLOR_RANGE (0<<13) +#define PIPECONF_CE_COLOR_RANGE (1<<13) +#define PIPECONF_COLOR_SPACE_RGB (0<<11) +#define PIPECONF_COLOR_SPACE_YUV601 (1<<11) +#define PIPECONF_COLOR_SPACE_YUV709 (2<<11) +#define PIPECONF_CONNECT_DEFAULT (0<<9) +#define PIPECONF_8BPP (0<<5) +#define PIPECONF_10BPP (1<<5) +#define PIPECONF_6BPP (2<<5) +#define PIPECONF_12BPP (3<<5) +#define PIPECONF_ENABLE_DITHER (1<<4) +#define PIPECONF_DITHER_SPATIAL (0<<2) +#define PIPECONF_DITHER_ST1 (1<<2) +#define PIPECONF_DITHER_ST2 (2<<2) +#define PIPECONF_DITHER_TEMPORAL (3<<2) + +#define PIPEAGCMAXRED 0x70010 +#define PIPEAGCMAXGREEN 0x70014 +#define PIPEAGCMAXBLUE 0x70018 +#define PIPEASTAT 0x70024 +# define FIFO_UNDERRUN (1 << 31) +# define CRC_ERROR_ENABLE (1 << 29) +# define CRC_DONE_ENABLE (1 << 28) +# define GMBUS_EVENT_ENABLE (1 << 27) +# define VSYNC_INT_ENABLE (1 << 25) +# define DLINE_COMPARE_ENABLE (1 << 24) +# define DPST_EVENT_ENABLE (1 << 23) +# define LBLC_EVENT_ENABLE (1 << 22) +# define OFIELD_INT_ENABLE (1 << 21) +# define EFIELD_INT_ENABLE (1 << 20) +# define SVBLANK_INT_ENABLE (1 << 18) +# define VBLANK_INT_ENABLE (1 << 17) +# define OREG_UPDATE_ENABLE (1 << 16) +# define CRC_ERROR_INT_STATUS (1 << 13) +# define CRC_DONE_INT_STATUS (1 << 12) +# define GMBUS_INT_STATUS (1 << 11) +# define VSYNC_INT_STATUS (1 << 9) +# define DLINE_COMPARE_STATUS (1 << 8) +# define DPST_EVENT_STATUS (1 << 7) +# define LBLC_EVENT_STATUS (1 << 6) +# define OFIELD_INT_STATUS (1 << 5) +# define EFIELD_INT_STATUS (1 << 4) +# define SVBLANK_INT_STATUS (1 << 2) +# define VBLANK_INT_STATUS (1 << 1) +# define OREG_UPDATE_STATUS (1 << 0) + + +#define DSPARB 0x70030 +#define DSPARB_CSTART_SHIFT 7 +#define DSPARB_BSTART_SHIFT 0 +#define DSPARB_BEND_SHIFT 9 /* on 855 */ +#define DSPARB_AEND_SHIFT 0 +#define DSPFW1 0x70034 +#define DSPFW2 0x70038 +#define DSPFW3 0x7003c +/* + * The two pipe frame counter registers are not synchronized, so + * reading a stable value is somewhat tricky. The following code + * should work: + * + * do { + * high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> PIPE_FRAME_HIGH_SHIFT; + * low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >> PIPE_FRAME_LOW_SHIFT); + * high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >> PIPE_FRAME_HIGH_SHIFT); + * } while (high1 != high2); + * frame = (high1 << 8) | low1; + */ +#define PIPEAFRAMEHIGH 0x70040 +#define PIPE_FRAME_HIGH_MASK 0x0000ffff +#define PIPE_FRAME_HIGH_SHIFT 0 +#define PIPEAFRAMEPIXEL 0x70044 +#define PIPE_FRAME_LOW_MASK 0xff000000 +#define PIPE_FRAME_LOW_SHIFT 24 +/* + * Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register + * and is 24 bits wide. + */ +#define PIPE_PIXEL_MASK 0x00ffffff +#define PIPE_PIXEL_SHIFT 0 + +/* + * Computing GMCH M and N values. + * + * GMCH M/N = dot clock * bytes per pixel / ls_clk * # of lanes + * + * ls_clk (we assume) is the DP link clock (1.62 or 2.7 GHz) + * + * The GMCH value is used internally + */ +#define PIPEA_GMCH_DATA_M 0x70050 + +/* Transfer unit size for display port - 1, default is 0x3f (for TU size 64) */ +#define PIPE_GMCH_DATA_M_TU_SIZE_MASK (0x3f << 25) +#define PIPE_GMCH_DATA_M_TU_SIZE_SHIFT 25 + +#define PIPE_GMCH_DATA_M_MASK (0xffffff) + +#define PIPEA_GMCH_DATA_N 0x70054 +#define PIPE_GMCH_DATA_N_MASK (0xffffff) + +/* + * Computing Link M and N values. + * + * Link M / N = pixel_clock / ls_clk + * + * (the DP spec calls pixel_clock the 'strm_clk') + * + * The Link value is transmitted in the Main Stream + * Attributes and VB-ID. + */ + +#define PIPEA_DP_LINK_M 0x70060 +#define PIPEA_DP_LINK_M_MASK (0xffffff) + +#define PIPEA_DP_LINK_N 0x70064 +#define PIPEA_DP_LINK_N_MASK (0xffffff) + +#define PIPEB_DSL 0x71000 + +#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 + +#define PIPEBGCMAXRED 0x71010 +#define PIPEBGCMAXGREEN 0x71014 +#define PIPEBGCMAXBLUE 0x71018 +#define PIPEBSTAT 0x71024 +#define PIPEBFRAMEHIGH 0x71040 +#define PIPEBFRAMEPIXEL 0x71044 + +#define PIPEB_GMCH_DATA_M 0x71050 +#define PIPEB_GMCH_DATA_N 0x71054 +#define PIPEB_DP_LINK_M 0x71060 +#define PIPEB_DP_LINK_N 0x71064 + +#define DSPACNTR 0x70180 +#define DSPBCNTR 0x71180 +#define DISPLAY_PLANE_ENABLE (1<<31) +#define DISPLAY_PLANE_DISABLE 0 +#define DISPLAY_PLANE_TILED (1<<10) +#define DISPPLANE_GAMMA_ENABLE (1<<30) +#define DISPPLANE_GAMMA_DISABLE 0 +#define DISPPLANE_PIXFORMAT_MASK (0xf<<26) +#define DISPPLANE_8BPP (0x2<<26) +#define DISPPLANE_15_16BPP (0x4<<26) +#define DISPPLANE_16BPP (0x5<<26) +#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26) /* IGDNG: BGRX */ +#define DISPPLANE_32BPP (0x7<<26) /* IGDNG: not support */ +/* IGDNG */ +#define DISPPLANE_32BPP_10 (0x8<<26) /* 2:10:10:10 */ +#define DISPPLANE_32BPP_BGRX (0xa<<26) +#define DISPPLANE_64BPP (0xc<<26) +#define DISPPLANE_32BPP_RGBX (0xe<<26) +#define DISPPLANE_STEREO_ENABLE (1<<25) +#define DISPPLANE_STEREO_DISABLE 0 +#define DISPPLANE_SEL_PIPE_MASK (1<<24) +#define DISPPLANE_SEL_PIPE_A 0 /* IGDNG: don't use */ +#define DISPPLANE_SEL_PIPE_B (1<<24) +#define DISPPLANE_NORMAL_RANGE (0<<25) +#define DISPPLANE_EXT_RANGE (1<<25) +/* IGDNG */ +#define DISPPLANE_CSC_BYPASS (0<<24) +#define DISPPLANE_CSC_PASSTHROUGH (1<<24) +#define DISPPLANE_SRC_KEY_ENABLE (1<<22) +#define DISPPLANE_SRC_KEY_DISABLE 0 +#define DISPPLANE_LINE_DOUBLE (1<<20) +#define DISPPLANE_NO_LINE_DOUBLE 0 +#define DISPPLANE_STEREO_POLARITY_FIRST 0 +#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18) +/* plane B only */ +#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15) +#define DISPPLANE_ALPHA_TRANS_DISABLE 0 +#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0 +#define DISPPLANE_SPRITE_ABOVE_OVERLAY (1) +/* IGDNG */ +#define DISPPLANE_X_TILE (1<<10) +#define DISPPLANE_LINEAR (0<<10) + +#define DSPABASE 0x70184 +/* IGDNG */ +#define DSPALINOFF 0x70184 +#define DSPASTRIDE 0x70188 + +#define DSPBBASE 0x71184 +/* IGDNG */ +#define DSPBLINOFF 0x71184 +#define DSPBADDR DSPBBASE +#define DSPBSTRIDE 0x71188 + +#define DSPAKEYVAL 0x70194 +#define DSPAKEYMASK 0x70198 + +#define DSPAPOS 0x7018C /* reserved */ +#define DSPASIZE 0x70190 +#define DSPBPOS 0x7118C +#define DSPBSIZE 0x71190 + +#define DSPASURF 0x7019C +#define DSPATILEOFF 0x701A4 + +#define DSPBSURF 0x7119C +#define DSPBTILEOFF 0x711A4 + +#define VGACNTRL 0x71400 +# define VGA_DISP_DISABLE (1 << 31) +# define VGA_2X_MODE (1 << 30) +# define VGA_PIPE_B_SELECT (1 << 29) + +/* 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)| \ + (1<<2)|(1<<1)|1|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16))) +#define I830_FWATER2_MASK ~(0) + +#define DV0A_RESERVED ((1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<16)|(1<<5)|(1<<1)|1) +#define DV0B_RESERVED ((1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<16)|(1<<5)|(1<<1)|1) +#define VGA0_N_DIVISOR_MASK ((1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)) +#define VGA0_M1_DIVISOR_MASK ((1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)) +#define VGA0_M2_DIVISOR_MASK ((1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1) +#define VGA0_M1M2N_RESERVED ~(VGA0_N_DIVISOR_MASK|VGA0_M1_DIVISOR_MASK|VGA0_M2_DIVISOR_MASK) +#define VGA0_POSTDIV_MASK ((1<<7)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1) +#define VGA1_POSTDIV_MASK ((1<<15)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)) +#define VGA_POSTDIV_RESERVED ~(VGA0_POSTDIV_MASK|VGA1_POSTDIV_MASK|(1<<7)|(1<<15)) +#define DPLLA_POSTDIV_MASK ((1<<23)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)) +#define DPLLA_RESERVED ((1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<22)|(1<<15)|(1<<12)|(1<<11)|(1<<10)|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1) +#define ADPA_RESERVED ((1<<2)|(1<<1)|1|(1<<9)|(1<<8)|(1<<7)|(1<<6)|(1<<5)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<26)|(1<<25)|(1<<24)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)) +#define SUPER_WORD 32 +#define BURST_A_MASK ((1<<11)|(1<<10)|(1<<9)|(1<<8)) +#define BURST_B_MASK ((1<<26)|(1<<25)|(1<<24)) +#define WATER_A_MASK ((1<<5)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|1) +#define WATER_B_MASK ((1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)) +#define WATER_RESERVED ((1<<31)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<23)|(1<<22)|(1<<21)|(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<7)|(1<<6)) +#define PIPEACONF_RESERVED ((1<<29)|(1<<28)|(1<<27)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)|0xffff) +#define PIPEBCONF_RESERVED ((1<<30)|(1<<29)|(1<<28)|(1<<27)|(1<<26)|(1<<25)|(1<<23)|(1<<22)|(1<<21)|(1<<20)|(1<<19)|(1<<18)|(1<<17)|(1<<16)|0xffff) +#define DSPACNTR_RESERVED ((1<<23)|(1<<19)|(1<<17)|(1<<16)|0xffff) +#define DSPBCNTR_RESERVED ((1<<23)|(1<<19)|(1<<17)|(1<<16)|0x7ffe) + +#define I830_GMCH_CTRL 0x52 + +#define I830_GMCH_ENABLED 0x4 +#define I830_GMCH_MEM_MASK 0x1 +#define I830_GMCH_MEM_64M 0x1 +#define I830_GMCH_MEM_128M 0 + +#define I830_GMCH_GMS_MASK 0x70 +#define I830_GMCH_GMS_DISABLED 0x00 +#define I830_GMCH_GMS_LOCAL 0x10 +#define I830_GMCH_GMS_STOLEN_512 0x20 +#define I830_GMCH_GMS_STOLEN_1024 0x30 +#define I830_GMCH_GMS_STOLEN_8192 0x40 + +#define I830_RDRAM_CHANNEL_TYPE 0x03010 +#define I830_RDRAM_ND(x) (((x) & 0x20) >> 5) +#define I830_RDRAM_DDT(x) (((x) & 0x18) >> 3) + +#define I855_GMCH_GMS_MASK (0xF << 4) +#define I855_GMCH_GMS_DISABLED 0x00 +#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4) +#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4) +#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 G33_GMCH_GMS_STOLEN_128M (0x8 << 4) +#define G33_GMCH_GMS_STOLEN_256M (0x9 << 4) +#define INTEL_GMCH_GMS_STOLEN_96M (0xa << 4) +#define INTEL_GMCH_GMS_STOLEN_160M (0xb << 4) +#define INTEL_GMCH_GMS_STOLEN_224M (0xc << 4) +#define INTEL_GMCH_GMS_STOLEN_352M (0xd << 4) + + +#define I915_GCFGC 0xf0 +#define I915_LOW_FREQUENCY_ENABLE (1 << 7) +#define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4) +#define I915_DISPLAY_CLOCK_333_MHZ (4 << 4) +#define I915_DISPLAY_CLOCK_MASK (7 << 4) + +#define I855_HPLLCC 0xc0 +#define I855_CLOCK_CONTROL_MASK (3 << 0) +#define I855_CLOCK_133_200 (0 << 0) +#define I855_CLOCK_100_200 (1 << 0) +#define I855_CLOCK_100_133 (2 << 0) +#define I855_CLOCK_166_250 (3 << 0) + +/* BLT commands */ +#define COLOR_BLT_CMD ((2<<29)|(0x40<<22)|(0x3)) +#define COLOR_BLT_WRITE_ALPHA (1<<21) +#define COLOR_BLT_WRITE_RGB (1<<20) + +#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|(0x4)) +#define XY_COLOR_BLT_WRITE_ALPHA (1<<21) +#define XY_COLOR_BLT_WRITE_RGB (1<<20) +#define XY_COLOR_BLT_TILED (1<<11) + +#define XY_SETUP_CLIP_BLT_CMD ((2<<29)|(3<<22)|1) + +#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6) +#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21) +#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20) +#define XY_SRC_COPY_BLT_SRC_TILED (1<<15) +#define XY_SRC_COPY_BLT_DST_TILED (1<<11) + +#define SRC_COPY_BLT_CMD ((2<<29)|(0x43<<22)|0x4) +#define SRC_COPY_BLT_WRITE_ALPHA (1<<21) +#define SRC_COPY_BLT_WRITE_RGB (1<<20) + +#define XY_PAT_BLT_IMMEDIATE ((2<<29)|(0x72<<22)) + +#define XY_MONO_PAT_BLT_CMD ((0x2<<29)|(0x52<<22)|0x7) +#define XY_MONO_PAT_VERT_SEED ((1<<10)|(1<<9)|(1<<8)) +#define XY_MONO_PAT_HORT_SEED ((1<<14)|(1<<13)|(1<<12)) +#define XY_MONO_PAT_BLT_WRITE_ALPHA (1<<21) +#define XY_MONO_PAT_BLT_WRITE_RGB (1<<20) + +#define XY_MONO_SRC_BLT_CMD ((0x2<<29)|(0x54<<22)|(0x6)) +#define XY_MONO_SRC_BLT_WRITE_ALPHA (1<<21) +#define XY_MONO_SRC_BLT_WRITE_RGB (1<<20) + +#define STATE3D_FOG_MODE ((3<<29)|(0x1d<<24)|(0x89<<16)|2) +#define FOG_MODE_VERTEX (1<<31) + +#define DISABLE_TEX_TRANSFORM (1<<28) +#define TEXTURE_SET(x) (x<<29) + +#define STATE3D_VERTEX_TRANSFORM ((3<<29)|(0x1d<<24)|(0x8b<<16)) +#define DISABLE_VIEWPORT_TRANSFORM (1<<31) +#define DISABLE_PERSPECTIVE_DIVIDE (1<<29) + +#define MI_SET_CONTEXT (0x18<<23) +#define CTXT_NO_RESTORE (1) +#define CTXT_PALETTE_SAVE_DISABLE (1<<3) +#define CTXT_PALETTE_RESTORE_DISABLE (1<<2) + +/* Dword 0 */ +#define MI_VERTEX_BUFFER (0x17<<23) +#define MI_VERTEX_BUFFER_IDX(x) (x<<20) +#define MI_VERTEX_BUFFER_PITCH(x) (x<<13) +#define MI_VERTEX_BUFFER_WIDTH(x) (x<<6) +/* Dword 1 */ +#define MI_VERTEX_BUFFER_DISABLE (1) + +/* Overlay Flip */ +#define MI_OVERLAY_FLIP (0x11<<23) +#define MI_OVERLAY_FLIP_CONTINUE (0<<21) +#define MI_OVERLAY_FLIP_ON (1<<21) +#define MI_OVERLAY_FLIP_OFF (2<<21) + +/* Wait for Events */ +#define MI_WAIT_FOR_EVENT (0x03<<23) +#define MI_WAIT_FOR_PIPEB_SVBLANK (1<<18) +#define MI_WAIT_FOR_PIPEA_SVBLANK (1<<17) +#define MI_WAIT_FOR_OVERLAY_FLIP (1<<16) +#define MI_WAIT_FOR_PIPEB_VBLANK (1<<7) +#define MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW (1<<5) +#define MI_WAIT_FOR_PIPEA_VBLANK (1<<3) +#define MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW (1<<1) + +/* Set the scan line for MI_WAIT_FOR_PIPE?_SCAN_LINE_WINDOW */ +#define MI_LOAD_SCAN_LINES_INCL (0x12<<23) +#define MI_LOAD_SCAN_LINES_DISPLAY_PIPEA (0) +#define MI_LOAD_SCAN_LINES_DISPLAY_PIPEB (0x1<<20) + +/* Flush */ +#define MI_FLUSH (0x04<<23) +#define MI_WRITE_DIRTY_STATE (1<<4) +#define MI_END_SCENE (1<<3) +#define MI_GLOBAL_SNAPSHOT_COUNT_RESET (1<<3) +#define MI_INHIBIT_RENDER_CACHE_FLUSH (1<<2) +#define MI_STATE_INSTRUCTION_CACHE_FLUSH (1<<1) +#define MI_INVALIDATE_MAP_CACHE (1<<0) +/* broadwater flush bits */ +#define BRW_MI_GLOBAL_SNAPSHOT_RESET (1 << 3) + +/* Noop */ +#define MI_NOOP 0x00 +#define MI_NOOP_WRITE_ID (1<<22) +#define MI_NOOP_ID_MASK (1<<22 - 1) + +#define STATE3D_COLOR_FACTOR ((0x3<<29)|(0x1d<<24)|(0x01<<16)) + +/* Batch */ +#define MI_BATCH_BUFFER ((0x30 << 23) | 1) +#define MI_BATCH_BUFFER_START (0x31 << 23) +#define MI_BATCH_BUFFER_END (0xA << 23) +#define MI_BATCH_NON_SECURE (1) +#define MI_BATCH_NON_SECURE_I965 (1 << 8) + +/* STATE3D_FOG_MODE stuff */ +#define ENABLE_FOG_SOURCE (1<<27) +#define ENABLE_FOG_CONST (1<<24) +#define ENABLE_FOG_DENSITY (1<<23) + +#define MAX_DISPLAY_PIPES 2 + +typedef enum { + CrtIndex = 0, + TvIndex, + DfpIndex, + LfpIndex, + Crt2Index, + Tv2Index, + Dfp2Index, + Lfp2Index, + NumDisplayTypes +} DisplayType; + +/* What's connected to the pipes (as reported by the BIOS) */ +#define PIPE_ACTIVE_MASK 0xff +#define PIPE_CRT_ACTIVE (1 << CrtIndex) +#define PIPE_TV_ACTIVE (1 << TvIndex) +#define PIPE_DFP_ACTIVE (1 << DfpIndex) +#define PIPE_LCD_ACTIVE (1 << LfpIndex) +#define PIPE_CRT2_ACTIVE (1 << Crt2Index) +#define PIPE_TV2_ACTIVE (1 << Tv2Index) +#define PIPE_DFP2_ACTIVE (1 << Dfp2Index) +#define PIPE_LCD2_ACTIVE (1 << Lfp2Index) + +#define PIPE_SIZED_DISP_MASK (PIPE_DFP_ACTIVE | \ + PIPE_LCD_ACTIVE | \ + PIPE_DFP2_ACTIVE) + +#define PIPE_A_SHIFT 0 +#define PIPE_B_SHIFT 8 +#define PIPE_SHIFT(n) ((n) == 0 ? \ + PIPE_A_SHIFT : PIPE_B_SHIFT) + +/* + * Some BIOS scratch area registers. The 845 (and 830?) store the amount + * of video memory available to the BIOS in SWF1. + */ + +#define SWF0 0x71410 +#define SWF1 0x71414 +#define SWF2 0x71418 +#define SWF3 0x7141c +#define SWF4 0x71420 +#define SWF5 0x71424 +#define SWF6 0x71428 + +/* + * 855 scratch registers. + */ +#define SWF00 0x70410 +#define SWF01 0x70414 +#define SWF02 0x70418 +#define SWF03 0x7041c +#define SWF04 0x70420 +#define SWF05 0x70424 +#define SWF06 0x70428 + +#define SWF10 SWF0 +#define SWF11 SWF1 +#define SWF12 SWF2 +#define SWF13 SWF3 +#define SWF14 SWF4 +#define SWF15 SWF5 +#define SWF16 SWF6 + +#define SWF30 0x72414 +#define SWF31 0x72418 +#define SWF32 0x7241c + +/* + * Overlay registers. These are overlay registers accessed via MMIO. + * Those loaded via the overlay register page are defined in i830_video.c. + */ +#define OVADD 0x30000 + +#define DOVSTA 0x30008 +#define OC_BUF (0x3<<20) + +#define OGAMC5 0x30010 +#define OGAMC4 0x30014 +#define OGAMC3 0x30018 +#define OGAMC2 0x3001c +#define OGAMC1 0x30020 +#define OGAMC0 0x30024 + + +/* + * Palette registers + */ +#define PALETTE_A 0x0a000 +#define PALETTE_B 0x0a800 + +/* Framebuffer compression */ +#define FBC_CFB_BASE 0x03200 /* 4k page aligned */ +#define FBC_LL_BASE 0x03204 /* 4k page aligned */ +#define FBC_CONTROL 0x03208 +#define FBC_CTL_EN (1<<31) +#define FBC_CTL_PERIODIC (1<<30) +#define FBC_CTL_INTERVAL_SHIFT (16) +#define FBC_CTL_UNCOMPRESSIBLE (1<<14) +#define FBC_CTL_STRIDE_SHIFT (5) +#define FBC_CTL_FENCENO (1<<0) +#define FBC_COMMAND 0x0320c +#define FBC_CMD_COMPRESS (1<<0) +#define FBC_STATUS 0x03210 +#define FBC_STAT_COMPRESSING (1<<31) +#define FBC_STAT_COMPRESSED (1<<30) +#define FBC_STAT_MODIFIED (1<<29) +#define FBC_STAT_CURRENT_LINE (1<<0) +#define FBC_CONTROL2 0x03214 +#define FBC_CTL_FENCE_DBL (0<<4) +#define FBC_CTL_IDLE_IMM (0<<2) +#define FBC_CTL_IDLE_FULL (1<<2) +#define FBC_CTL_IDLE_LINE (2<<2) +#define FBC_CTL_IDLE_DEBUG (3<<2) +#define FBC_CTL_CPU_FENCE (1<<1) +#define FBC_CTL_PLANEA (0<<0) +#define FBC_CTL_PLANEB (1<<0) +#define FBC_FENCE_OFF 0x0321b +#define FBC_MOD_NUM 0x03220 +#define FBC_TAG_DEBUG 0x03300 + +#define FBC_LL_SIZE (1536) +#define FBC_LL_PAD (32) + +/* Framebuffer compression version 2 */ +#define DPFC_CB_BASE 0x3200 +#define DPFC_CONTROL 0x3208 +#define DPFC_CTL_EN (1<<31) +#define DPFC_CTL_PLANEA (0<<30) +#define DPFC_CTL_PLANEB (1<<30) +#define DPFC_CTL_FENCE_EN (1<<29) +#define DPFC_CTL_LIMIT_1X (0<<6) +#define DPFC_CTL_LIMIT_2X (1<<6) +#define DPFC_CTL_LIMIT_4X (2<<6) +#define DPFC_RECOMP_CTL 0x320c +#define DPFC_RECOMP_STALL_EN (1<<27) +#define DPFC_RECOMP_STALL_WM_SHIFT (16) +#define DPFC_RECOMP_STALL_WM_MASK (0x07ff0000) +#define DPFC_RECOMP_TIMER_COUNT_SHIFT (0) +#define DPFC_RECOMP_TIMER_COUNT_MASK (0x0000003f) +#define DPFC_STATUS 0x3210 +#define DPFC_INVAL_SEG_SHIFT (16) +#define DPFC_INVAL_SEG_MASK (0x07ff0000) +#define DPFC_COMP_SEG_SHIFT (0) +#define DPFC_COMP_SEG_MASK (0x000003ff) +#define DPFC_STATUS2 0x3214 +#define DPFC_FENCE_YOFF 0x3218 + +#define PEG_BAND_GAP_DATA 0x14d68 + +#define MCHBAR_RENDER_STANDBY 0x111B8 +#define RENDER_STANDBY_ENABLE (1 << 30) + +/* IGDNG */ + +/* warmup time in us */ +#define WARMUP_PCH_REF_CLK_SSC_MOD 1 +#define WARMUP_PCH_FDI_RECEIVER_PLL 25 +#define WARMUP_PCH_DPLL 50 +#define WARMUP_CPU_DP_PLL 20 +#define WARMUP_CPU_FDI_TRANSMITTER_PLL 10 +#define WARMUP_DMI_LATENCY 20 +#define FDI_TRAIN_PATTERN_1_TIME 0.5 +#define FDI_TRAIN_PATTERN_2_TIME 1.5 +#define FDI_ONE_IDLE_PATTERN_TIME 31 + +#define CPU_VGACNTRL 0x41000 + +#define DIGITAL_PORT_HOTPLUG_CNTRL 0x44030 +#define DIGITAL_PORTA_HOTPLUG_ENABLE (1 << 4) +#define DIGITAL_PORTA_SHORT_PULSE_2MS (0 << 2) +#define DIGITAL_PORTA_SHORT_PULSE_4_5MS (1 << 2) +#define DIGITAL_PORTA_SHORT_PULSE_6MS (2 << 2) +#define DIGITAL_PORTA_SHORT_PULSE_100MS (3 << 2) +#define DIGITAL_PORTA_NO_DETECT (0 << 0) +#define DIGITAL_PORTA_LONG_PULSE_DETECT_MASK (1 << 1) +#define DIGITAL_PORTA_SHORT_PULSE_DETECT_MASK (1 << 0) + +/* refresh rate hardware control */ +#define RR_HW_CTL 0x45300 +#define RR_HW_LOW_POWER_FRAMES_MASK 0xff +#define RR_HW_HIGH_POWER_FRAMES_MASK 0xff00 + +#define FDI_PLL_BIOS_0 0x46000 +#define FDI_PLL_BIOS_1 0x46004 +#define FDI_PLL_BIOS_2 0x46008 +#define DISPLAY_PORT_PLL_BIOS_0 0x4600c +#define DISPLAY_PORT_PLL_BIOS_1 0x46010 +#define DISPLAY_PORT_PLL_BIOS_2 0x46014 + +#define FDI_PLL_FREQ_CTL 0x46030 +#define FDI_PLL_FREQ_CHANGE_REQUEST (1<<24) +#define FDI_PLL_FREQ_LOCK_LIMIT_MASK 0xfff00 +#define FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK 0xff + +#define PIPEA_DATA_M1 0x60030 +#define TU_SIZE(x) (((x)-1) << 25) /* default size 64 */ +#define TU_SIZE_MASK 0x7e000000 +#define PIPEA_DATA_M1_OFFSET 0 +#define PIPEA_DATA_N1 0x60034 +#define PIPEA_DATA_N1_OFFSET 0 + +#define PIPEA_DATA_M2 0x60038 +#define PIPEA_DATA_M2_OFFSET 0 +#define PIPEA_DATA_N2 0x6003c +#define PIPEA_DATA_N2_OFFSET 0 + +#define PIPEA_LINK_M1 0x60040 +#define PIPEA_LINK_M1_OFFSET 0 +#define PIPEA_LINK_N1 0x60044 +#define PIPEA_LINK_N1_OFFSET 0 + +#define PIPEA_LINK_M2 0x60048 +#define PIPEA_LINK_M2_OFFSET 0 +#define PIPEA_LINK_N2 0x6004c +#define PIPEA_LINK_N2_OFFSET 0 + +/* PIPEB timing regs are same start from 0x61000 */ + +#define PIPEB_DATA_M1 0x61030 +#define PIPEB_DATA_M1_OFFSET 0 +#define PIPEB_DATA_N1 0x61034 +#define PIPEB_DATA_N1_OFFSET 0 + +#define PIPEB_DATA_M2 0x61038 +#define PIPEB_DATA_M2_OFFSET 0 +#define PIPEB_DATA_N2 0x6103c +#define PIPEB_DATA_N2_OFFSET 0 + +#define PIPEB_LINK_M1 0x61040 +#define PIPEB_LINK_M1_OFFSET 0 +#define PIPEB_LINK_N1 0x61044 +#define PIPEB_LINK_N1_OFFSET 0 + +#define PIPEB_LINK_M2 0x61048 +#define PIPEB_LINK_M2_OFFSET 0 +#define PIPEB_LINK_N2 0x6104c +#define PIPEB_LINK_N2_OFFSET 0 + +/* PIPECONF for pipe A/B addr is same */ + +/* cusor A is only connected to pipe A, + cursor B is connected to pipe B. Otherwise no change. */ + +/* Plane A/B, DSPACNTR/DSPBCNTR addr not changed */ + +/* CPU panel fitter */ +#define PFA_CTL_1 0x68080 +#define PFB_CTL_1 0x68880 +#define PF_ENABLE (1<<31) + +#define PFA_WIN_POS 0x68070 +#define PFB_WIN_POS 0x68870 +#define PFA_WIN_SIZE 0x68074 +#define PFB_WIN_SIZE 0x68874 + +/* legacy palette */ +#define LGC_PALETTE_A 0x4a000 +#define LGC_PALETTE_B 0x4a800 + +/* interrupts */ +#define DE_MASTER_IRQ_CONTROL (1 << 31) +#define DE_SPRITEB_FLIP_DONE (1 << 29) +#define DE_SPRITEA_FLIP_DONE (1 << 28) +#define DE_PLANEB_FLIP_DONE (1 << 27) +#define DE_PLANEA_FLIP_DONE (1 << 26) +#define DE_PCU_EVENT (1 << 25) +#define DE_GTT_FAULT (1 << 24) +#define DE_POISON (1 << 23) +#define DE_PERFORM_COUNTER (1 << 22) +#define DE_PCH_EVENT (1 << 21) +#define DE_AUX_CHANNEL_A (1 << 20) +#define DE_DP_A_HOTPLUG (1 << 19) +#define DE_GSE (1 << 18) +#define DE_PIPEB_VBLANK (1 << 15) +#define DE_PIPEB_EVEN_FIELD (1 << 14) +#define DE_PIPEB_ODD_FIELD (1 << 13) +#define DE_PIPEB_LINE_COMPARE (1 << 12) +#define DE_PIPEB_VSYNC (1 << 11) +#define DE_PIPEB_FIFO_UNDERRUN (1 << 8) +#define DE_PIPEA_VBLANK (1 << 7) +#define DE_PIPEA_EVEN_FIELD (1 << 6) +#define DE_PIPEA_ODD_FIELD (1 << 5) +#define DE_PIPEA_LINE_COMPARE (1 << 4) +#define DE_PIPEA_VSYNC (1 << 3) +#define DE_PIPEA_FIFO_UNDERRUN (1 << 0) + +#define DEISR 0x44000 +#define DEIMR 0x44004 +#define DEIIR 0x44008 +#define DEIER 0x4400c + +/* GT interrupt */ +#define GT_SYNC_STATUS (1 << 2) +#define GT_USER_INTERRUPT (1 << 0) + +#define GTISR 0x44010 +#define GTIMR 0x44014 +#define GTIIR 0x44018 +#define GTIER 0x4401c + +/* PCH */ + +/* south display engine interrupt */ +#define SDE_CRT_HOTPLUG (1 << 11) +#define SDE_PORTD_HOTPLUG (1 << 10) +#define SDE_PORTC_HOTPLUG (1 << 9) +#define SDE_PORTB_HOTPLUG (1 << 8) +#define SDE_SDVOB_HOTPLUG (1 << 6) + +#define SDEISR 0xc4000 +#define SDEIMR 0xc4004 +#define SDEIIR 0xc4008 +#define SDEIER 0xc400c + +/* digital port hotplug */ +#define PCH_PORT_HOTPLUG 0xc4030 +#define PORTD_HOTPLUG_ENABLE (1 << 20) +#define PORTD_PULSE_DURATION_2ms (0) +#define PORTD_PULSE_DURATION_4_5ms (1 << 18) +#define PORTD_PULSE_DURATION_6ms (2 << 18) +#define PORTD_PULSE_DURATION_100ms (3 << 18) +#define PORTD_HOTPLUG_NO_DETECT (0) +#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16) +#define PORTD_HOTPLUG_LONG_DETECT (1 << 17) +#define PORTC_HOTPLUG_ENABLE (1 << 12) +#define PORTC_PULSE_DURATION_2ms (0) +#define PORTC_PULSE_DURATION_4_5ms (1 << 10) +#define PORTC_PULSE_DURATION_6ms (2 << 10) +#define PORTC_PULSE_DURATION_100ms (3 << 10) +#define PORTC_HOTPLUG_NO_DETECT (0) +#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8) +#define PORTC_HOTPLUG_LONG_DETECT (1 << 9) +#define PORTB_HOTPLUG_ENABLE (1 << 4) +#define PORTB_PULSE_DURATION_2ms (0) +#define PORTB_PULSE_DURATION_4_5ms (1 << 2) +#define PORTB_PULSE_DURATION_6ms (2 << 2) +#define PORTB_PULSE_DURATION_100ms (3 << 2) +#define PORTB_HOTPLUG_NO_DETECT (0) +#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) +#define PORTB_HOTPLUG_LONG_DETECT (1 << 1) + +#define PCH_GPIOA 0xc5010 +#define PCH_GPIOB 0xc5014 +#define PCH_GPIOC 0xc5018 +#define PCH_GPIOD 0xc501c +#define PCH_GPIOE 0xc5020 +#define PCH_GPIOF 0xc5024 +#define PCH_GMBUS0 0xc5100 +#define PCH_GMBUS1 0xc5104 +#define PCH_GMBUS2 0xc5108 +#define PCH_GMBUS3 0xc510c +#define PCH_GMBUS4 0xc5110 +#define PCH_GMBUS5 0xc5120 + +#define PCH_DPLL_A 0xc6014 +#define PCH_DPLL_B 0xc6018 + +#define PCH_FPA0 0xc6040 +#define PCH_FPA1 0xc6044 +#define PCH_FPB0 0xc6048 +#define PCH_FPB1 0xc604c + +#define PCH_DPLL_TEST 0xc606c + +#define PCH_DREF_CONTROL 0xC6200 +#define DREF_CONTROL_MASK 0x7fc3 +#define DREF_CPU_SOURCE_OUTPUT_DISABLE (0<<13) +#define DREF_CPU_SOURCE_OUTPUT_DOWNSPREAD (2<<13) +#define DREF_CPU_SOURCE_OUTPUT_NONSPREAD (3<<13) +#define DREF_SSC_SOURCE_DISABLE (0<<11) +#define DREF_SSC_SOURCE_ENABLE (2<<11) +#define DREF_NONSPREAD_SOURCE_DISABLE (0<<9) +#define DREF_NONSPREAD_SOURCE_ENABLE (2<<9) +#define DREF_SUPERSPREAD_SOURCE_DISABLE (0<<7) +#define DREF_SUPERSPREAD_SOURCE_ENABLE (2<<7) +#define DREF_SSC4_DOWNSPREAD (0<<6) +#define DREF_SSC4_CENTERSPREAD (1<<6) +#define DREF_SSC1_DISABLE (0<<1) +#define DREF_SSC1_ENABLE (1<<1) +#define DREF_SSC4_DISABLE (0) +#define DREF_SSC4_ENABLE (1) + +#define PCH_RAWCLK_FREQ 0xc6204 +#define FDL_TP1_TIMER_SHIFT 12 +#define FDL_TP1_TIMER_MASK (3<<12) +#define FDL_TP2_TIMER_SHIFT 10 +#define FDL_TP2_TIMER_MASK (3<<10) +#define RAWCLK_FREQ_MASK 0x3ff + +#define PCH_DPLL_TMR_CFG 0xc6208 + +#define PCH_SSC4_PARMS 0xc6210 +#define PCH_SSC4_AUX_PARMS 0xc6214 + +/* transcoder */ + +#define TRANS_HTOTAL_A 0xe0000 +#define TRANS_HTOTAL_SHIFT 16 +#define TRANS_HACTIVE_SHIFT 0 +#define TRANS_HBLANK_A 0xe0004 +#define TRANS_HBLANK_END_SHIFT 16 +#define TRANS_HBLANK_START_SHIFT 0 +#define TRANS_HSYNC_A 0xe0008 +#define TRANS_HSYNC_END_SHIFT 16 +#define TRANS_HSYNC_START_SHIFT 0 +#define TRANS_VTOTAL_A 0xe000c +#define TRANS_VTOTAL_SHIFT 16 +#define TRANS_VACTIVE_SHIFT 0 +#define TRANS_VBLANK_A 0xe0010 +#define TRANS_VBLANK_END_SHIFT 16 +#define TRANS_VBLANK_START_SHIFT 0 +#define TRANS_VSYNC_A 0xe0014 +#define TRANS_VSYNC_END_SHIFT 16 +#define TRANS_VSYNC_START_SHIFT 0 + +#define TRANSA_DATA_M1 0xe0030 +#define TRANSA_DATA_N1 0xe0034 +#define TRANSA_DATA_M2 0xe0038 +#define TRANSA_DATA_N2 0xe003c +#define TRANSA_DP_LINK_M1 0xe0040 +#define TRANSA_DP_LINK_N1 0xe0044 +#define TRANSA_DP_LINK_M2 0xe0048 +#define TRANSA_DP_LINK_N2 0xe004c + +#define TRANS_HTOTAL_B 0xe1000 +#define TRANS_HBLANK_B 0xe1004 +#define TRANS_HSYNC_B 0xe1008 +#define TRANS_VTOTAL_B 0xe100c +#define TRANS_VBLANK_B 0xe1010 +#define TRANS_VSYNC_B 0xe1014 + +#define TRANSB_DATA_M1 0xe1030 +#define TRANSB_DATA_N1 0xe1034 +#define TRANSB_DATA_M2 0xe1038 +#define TRANSB_DATA_N2 0xe103c +#define TRANSB_DP_LINK_M1 0xe1040 +#define TRANSB_DP_LINK_N1 0xe1044 +#define TRANSB_DP_LINK_M2 0xe1048 +#define TRANSB_DP_LINK_N2 0xe104c + +#define TRANSACONF 0xf0008 +#define TRANSBCONF 0xf1008 +#define TRANS_DISABLE (0<<31) +#define TRANS_ENABLE (1<<31) +#define TRANS_STATE_MASK (1<<30) +#define TRANS_STATE_DISABLE (0<<30) +#define TRANS_STATE_ENABLE (1<<30) +#define TRANS_FSYNC_DELAY_HB1 (0<<27) +#define TRANS_FSYNC_DELAY_HB2 (1<<27) +#define TRANS_FSYNC_DELAY_HB3 (2<<27) +#define TRANS_FSYNC_DELAY_HB4 (3<<27) +#define TRANS_DP_AUDIO_ONLY (1<<26) +#define TRANS_DP_VIDEO_AUDIO (0<<26) +#define TRANS_PROGRESSIVE (0<<21) +#define TRANS_8BPC (0<<5) +#define TRANS_10BPC (1<<5) +#define TRANS_6BPC (2<<5) +#define TRANS_12BPC (3<<5) + +#define FDI_RXA_CHICKEN 0xc200c +#define FDI_RXB_CHICKEN 0xc2010 +#define FDI_RX_PHASE_SYNC_POINTER_ENABLE (1) + +/* CPU: FDI_TX */ +#define FDI_TXA_CTL 0x60100 +#define FDI_TXB_CTL 0x61100 +#define FDI_TX_DISABLE (0<<31) +#define FDI_TX_ENABLE (1<<31) +#define FDI_LINK_TRAIN_PATTERN_1 (0<<28) +#define FDI_LINK_TRAIN_PATTERN_2 (1<<28) +#define FDI_LINK_TRAIN_PATTERN_IDLE (2<<28) +#define FDI_LINK_TRAIN_NONE (3<<28) +#define FDI_LINK_TRAIN_VOLTAGE_0_4V (0<<25) +#define FDI_LINK_TRAIN_VOLTAGE_0_6V (1<<25) +#define FDI_LINK_TRAIN_VOLTAGE_0_8V (2<<25) +#define FDI_LINK_TRAIN_VOLTAGE_1_2V (3<<25) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_NONE (0<<22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_1_5X (1<<22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_2X (2<<22) +#define FDI_LINK_TRAIN_PRE_EMPHASIS_3X (3<<22) +#define FDI_DP_PORT_WIDTH_X1 (0<<19) +#define FDI_DP_PORT_WIDTH_X2 (1<<19) +#define FDI_DP_PORT_WIDTH_X3 (2<<19) +#define FDI_DP_PORT_WIDTH_X4 (3<<19) +#define FDI_TX_ENHANCE_FRAME_ENABLE (1<<18) +/* IGDNG: hardwired to 1 */ +#define FDI_TX_PLL_ENABLE (1<<14) +/* both Tx and Rx */ +#define FDI_SCRAMBLING_ENABLE (0<<7) +#define FDI_SCRAMBLING_DISABLE (1<<7) + +/* FDI_RX, FDI_X is hard-wired to Transcoder_X */ +#define FDI_RXA_CTL 0xf000c +#define FDI_RXB_CTL 0xf100c +#define FDI_RX_ENABLE (1<<31) +#define FDI_RX_DISABLE (0<<31) +/* train, dp width same as FDI_TX */ +#define FDI_DP_PORT_WIDTH_X8 (7<<19) +#define FDI_8BPC (0<<16) +#define FDI_10BPC (1<<16) +#define FDI_6BPC (2<<16) +#define FDI_12BPC (3<<16) +#define FDI_LINK_REVERSE_OVERWRITE (1<<15) +#define FDI_DMI_LINK_REVERSE_MASK (1<<14) +#define FDI_RX_PLL_ENABLE (1<<13) +#define FDI_FS_ERR_CORRECT_ENABLE (1<<11) +#define FDI_FE_ERR_CORRECT_ENABLE (1<<10) +#define FDI_FS_ERR_REPORT_ENABLE (1<<9) +#define FDI_FE_ERR_REPORT_ENABLE (1<<8) +#define FDI_RX_ENHANCE_FRAME_ENABLE (1<<6) +#define FDI_SEL_RAWCLK (0<<4) +#define FDI_SEL_PCDCLK (1<<4) + +#define FDI_RXA_MISC 0xf0010 +#define FDI_RXB_MISC 0xf1010 +#define FDI_RXA_TUSIZE1 0xf0030 +#define FDI_RXA_TUSIZE2 0xf0038 +#define FDI_RXB_TUSIZE1 0xf1030 +#define FDI_RXB_TUSIZE2 0xf1038 + +/* FDI_RX interrupt register format */ +#define FDI_RX_INTER_LANE_ALIGN (1<<10) +#define FDI_RX_SYMBOL_LOCK (1<<9) /* train 2 */ +#define FDI_RX_BIT_LOCK (1<<8) /* train 1 */ +#define FDI_RX_TRAIN_PATTERN_2_FAIL (1<<7) +#define FDI_RX_FS_CODE_ERR (1<<6) +#define FDI_RX_FE_CODE_ERR (1<<5) +#define FDI_RX_SYMBOL_ERR_RATE_ABOVE (1<<4) +#define FDI_RX_HDCP_LINK_FAIL (1<<3) +#define FDI_RX_PIXEL_FIFO_OVERFLOW (1<<2) +#define FDI_RX_CROSS_CLOCK_OVERFLOW (1<<1) +#define FDI_RX_SYMBOL_QUEUE_OVERFLOW (1<<0) + +#define FDI_RXA_IIR 0xf0014 +#define FDI_RXA_IMR 0xf0018 +#define FDI_RXB_IIR 0xf1014 +#define FDI_RXB_IMR 0xf1018 + +#define FDI_PLL_CTL_1 0xfe000 +#define FDI_PLL_CTL_2 0xfe004 + +/* CRT */ +#define PCH_ADPA 0xe1100 +#define ADPA_TRANS_SELECT_MASK (1<<30) +#define ADPA_TRANS_A_SELECT 0 +#define ADPA_TRANS_B_SELECT (1<<30) +/* HPD is here */ +#define ADPA_CRT_HOTPLUG_MASK 0x03ff0000 /* bit 25-16 */ +#define ADPA_CRT_HOTPLUG_MONITOR_NONE (0<<24) +#define ADPA_CRT_HOTPLUG_MONITOR_MASK (3<<24) +#define ADPA_CRT_HOTPLUG_MONITOR_COLOR (3<<24) +#define ADPA_CRT_HOTPLUG_MONITOR_MONO (2<<24) +#define ADPA_CRT_HOTPLUG_ENABLE (1<<23) +#define ADPA_CRT_HOTPLUG_PERIOD_64 (0<<22) +#define ADPA_CRT_HOTPLUG_PERIOD_128 (1<<22) +#define ADPA_CRT_HOTPLUG_WARMUP_5MS (0<<21) +#define ADPA_CRT_HOTPLUG_WARMUP_10MS (1<<21) +#define ADPA_CRT_HOTPLUG_SAMPLE_2S (0<<20) +#define ADPA_CRT_HOTPLUG_SAMPLE_4S (1<<20) +#define ADPA_CRT_HOTPLUG_VOLTAGE_40 (0<<18) +#define ADPA_CRT_HOTPLUG_VOLTAGE_50 (1<<18) +#define ADPA_CRT_HOTPLUG_VOLTAGE_60 (2<<18) +#define ADPA_CRT_HOTPLUG_VOLTAGE_70 (3<<18) +#define ADPA_CRT_HOTPLUG_VOLREF_325MV (0<<17) +#define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17) +#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) +/* polarity control not changed */ + +/* or SDVOB */ +#define HDMIB 0xe1140 +#define PORT_ENABLE (1 << 31) +#define TRANSCODER_A (0) +#define TRANSCODER_B (1 << 30) +#define COLOR_FORMAT_8bpc (0) +#define COLOR_FORMAT_12bpc (3 << 26) +#define SDVOB_HOTPLUG_ENABLE (1 << 23) +#define SDVO_ENCODING (0) +#define TMDS_ENCODING (2 << 10) +#define NULL_PACKET_VSYNC_ENABLE (1 << 9) +#define SDVOB_BORDER_ENABLE (1 << 7) +#define AUDIO_ENABLE (1 << 6) +#define VSYNC_ACTIVE_HIGH (1 << 4) +#define HSYNC_ACTIVE_HIGH (1 << 3) +#define PORT_DETECTED (1 << 2) + +#define HDMIC 0xe1150 +#define HDMID 0xe1160 +#define PCH_LVDS 0xe1180 + +#define AUD_CONFIG 0x62000 +#define AUD_DEBUG 0x62010 +#define AUD_VID_DID 0x62020 +#define AUD_RID 0x62024 +#define AUD_SUBN_CNT 0x62028 +#define AUD_FUNC_GRP 0x62040 +#define AUD_SUBN_CNT2 0x62044 +#define AUD_GRP_CAP 0x62048 +#define AUD_PWRST 0x6204c +#define AUD_SUPPWR 0x62050 +#define AUD_SID 0x62054 +#define AUD_OUT_CWCAP 0x62070 +#define AUD_OUT_PCMSIZE 0x62074 +#define AUD_OUT_STR 0x62078 +#define AUD_OUT_DIG_CNVT 0x6207c +#define AUD_OUT_CH_STR 0x62080 +#define AUD_OUT_STR_DESC 0x62084 +#define AUD_PINW_CAP 0x620a0 +#define AUD_PIN_CAP 0x620a4 +#define AUD_PINW_CONNLNG 0x620a8 +#define AUD_PINW_CONNLST 0x620ac +#define AUD_PINW_CNTR 0x620b0 +#define AUD_PINW_UNSOLRESP 0x620b8 +#define AUD_CNTL_ST 0x620b4 +#define AUD_PINW_CONFIG 0x620bc +#define AUD_HDMIW_STATUS 0x620d4 +#define AUD_HDMIW_HDMIEDID 0x6210c +#define AUD_HDMIW_INFOFR 0x62118 +#define AUD_CONV_CHCNT 0x62120 +#define AUD_CTS_ENABLE 0x62128 + +#define VIDEO_DIP_CTL 0x61170 + +#endif /* _I810_REG_H */ diff --git a/src/legacy/i810/i810_ring.h b/src/legacy/i810/i810_ring.h new file mode 100644 index 00000000..e6e354fd --- /dev/null +++ b/src/legacy/i810/i810_ring.h @@ -0,0 +1,90 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +Copyright © 2002 David Dawes + +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef _INTEL_RING_H +#define _INTEL_RING_H + +#define OUT_RING(n) do { \ + if (I810_DEBUG & DEBUG_VERBOSE_RING) \ + ErrorF("OUT_RING %lx: %x, (mask %x)\n", \ + (unsigned long)(outring), (unsigned int)(n), ringmask); \ + *(volatile unsigned int *)(virt + outring) = n; \ + outring += 4; ringused += 4; \ + outring &= ringmask; \ +} while (0) + +#define ADVANCE_LP_RING() do { \ + if (ringused > needed) \ + FatalError("%s: ADVANCE_LP_RING: exceeded allocation %d/%d\n ", \ + __FUNCTION__, ringused, needed); \ + else if (ringused < needed) \ + FatalError("%s: ADVANCE_LP_RING: under-used allocation %d/%d\n ", \ + __FUNCTION__, ringused, needed); \ + pI810->LpRing->tail = outring; \ + pI810->LpRing->space -= ringused; \ + if (outring & 0x07) \ + FatalError("%s: ADVANCE_LP_RING: " \ + "outring (0x%x) isn't on a QWord boundary\n", \ + __FUNCTION__, outring); \ + OUTREG(LP_RING + RING_TAIL, outring); \ +} while (0) + +/* + * XXX Note: the head/tail masks are different for 810 and i830. + * If the i810 always sets the higher bits to 0, then this shouldn't be + * a problem. Check this! + */ +#define DO_RING_IDLE() do { \ + int _head; \ + int _tail; \ + do { \ + _head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK; \ + _tail = INREG(LP_RING + RING_TAIL) & I830_TAIL_MASK; \ + DELAY(10); \ + } while (_head != _tail); \ +} while( 0) + +#define BEGIN_LP_RING(n) \ + unsigned int outring, ringmask, ringused = 0; \ + volatile unsigned char *virt; \ + int needed; \ + if ((n) & 1) \ + ErrorF("BEGIN_LP_RING called with odd argument: %d\n", n); \ + if ((n) > 2 && (I810_DEBUG&DEBUG_ALWAYS_SYNC)) \ + DO_RING_IDLE(); \ + needed = (n) * 4; \ + if (pI810->LpRing->space < needed) \ + WaitRingFunc(pScrn, needed, 0); \ + outring = pI810->LpRing->tail; \ + ringmask = pI810->LpRing->tail_mask; \ + virt = pI810->LpRing->virtual_start; \ + if (I810_DEBUG & DEBUG_VERBOSE_RING) \ + ErrorF( "BEGIN_LP_RING %d in %s\n", n, FUNCTION_NAME); + +#endif /* _INTEL_RING_H */ diff --git a/src/legacy/i810/i810_video.c b/src/legacy/i810/i810_video.c new file mode 100644 index 00000000..7e3db8c7 --- /dev/null +++ b/src/legacy/i810/i810_video.c @@ -0,0 +1,1423 @@ +/*************************************************************************** + +Copyright 2000 Intel Corporation. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * i810_video.c: i810 Xv driver. Based on the mga Xv driver by Mark Vojkovich. + * + * Authors: + * Jonathan Bian <jonathan.bian@intel.com> + * Offscreen Images: + * Matt Sottek <matthew.j.sottek@intel.com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> + +#include "xf86.h" +#include "xf86_OSproc.h" +#include "compiler.h" +#include "xf86PciInfo.h" +#include "xf86Pci.h" +#include "xf86fbman.h" +#include "regionstr.h" + +#include "i810.h" +#include "xf86xv.h" +#include <X11/extensions/Xv.h> +#include "xaa.h" +#include "xaalocal.h" +#include "dixstruct.h" +#include "fourcc.h" + +#define OFF_DELAY 250 /* milliseconds */ +#define FREE_DELAY 15000 + +#define OFF_TIMER 0x01 +#define FREE_TIMER 0x02 +#define CLIENT_VIDEO_ON 0x04 + +#define TIMER_MASK (OFF_TIMER | FREE_TIMER) + +static void I810InitOffscreenImages(ScreenPtr); + +static XF86VideoAdaptorPtr I810SetupImageVideo(ScreenPtr); +static void I810StopVideo(ScrnInfoPtr, pointer, Bool); +static int I810SetPortAttribute(ScrnInfoPtr, Atom, INT32, pointer); +static int I810GetPortAttribute(ScrnInfoPtr, Atom ,INT32 *, pointer); +static void I810QueryBestSize(ScrnInfoPtr, Bool, + short, short, short, short, unsigned int *, unsigned int *, pointer); +static int I810PutImage( ScrnInfoPtr, + short, short, short, short, short, short, short, short, + int, unsigned char*, short, short, Bool, RegionPtr, pointer, + DrawablePtr); +static int I810QueryImageAttributes(ScrnInfoPtr, + int, unsigned short *, unsigned short *, int *, int *); + +static void I810BlockHandler(int, pointer, pointer, pointer); + +#define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) + +static Atom xvBrightness, xvContrast, xvColorKey; + +#define IMAGE_MAX_WIDTH 1440 +#define IMAGE_FAST_WIDTH 720 +#define IMAGE_MAX_HEIGHT 1080 +#define Y_BUF_SIZE (IMAGE_MAX_WIDTH * IMAGE_MAX_HEIGHT) + +#define OVERLAY_UPDATE(p) OUTREG(0x30000, p | 0x80000000); + +/* + * OV0CMD - Overlay Command Register + */ +#define VERTICAL_CHROMINANCE_FILTER 0x70000000 +#define VC_SCALING_OFF 0x00000000 +#define VC_LINE_REPLICATION 0x10000000 +#define VC_UP_INTERPOLATION 0x20000000 +#define VC_PIXEL_DROPPING 0x50000000 +#define VC_DOWN_INTERPOLATION 0x60000000 +#define VERTICAL_LUMINANCE_FILTER 0x0E000000 +#define VL_SCALING_OFF 0x00000000 +#define VL_LINE_REPLICATION 0x02000000 +#define VL_UP_INTERPOLATION 0x04000000 +#define VL_PIXEL_DROPPING 0x0A000000 +#define VL_DOWN_INTERPOLATION 0x0C000000 +#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000 +#define HC_SCALING_OFF 0x00000000 +#define HC_LINE_REPLICATION 0x00400000 +#define HC_UP_INTERPOLATION 0x00800000 +#define HC_PIXEL_DROPPING 0x01400000 +#define HC_DOWN_INTERPOLATION 0x01800000 +#define HORIZONTAL_LUMINANCE_FILTER 0x00380000 +#define HL_SCALING_OFF 0x00000000 +#define HL_LINE_REPLICATION 0x00080000 +#define HL_UP_INTERPOLATION 0x00100000 +#define HL_PIXEL_DROPPING 0x00280000 +#define HL_DOWN_INTERPOLATION 0x00300000 + +#define Y_ADJUST 0x00010000 +#define OV_BYTE_ORDER 0x0000C000 +#define UV_SWAP 0x00004000 +#define Y_SWAP 0x00008000 +#define Y_AND_UV_SWAP 0x0000C000 +#define SOURCE_FORMAT 0x00003C00 +#define RGB_555 0x00000800 +#define RGB_565 0x00000C00 +#define YUV_422 0x00002000 +#define YUV_411 0x00002400 +#define YUV_420 0x00003000 +#define YUV_410 0x00003800 +#define BUFFER_AND_FIELD 0x00000006 +#define BUFFER0_FIELD0 0x00000000 +#define BUFFER1_FIELD0 0x00000004 +#define OVERLAY_ENABLE 0x00000001 + +#define UV_VERT_BUF1 0x02 +#define UV_VERT_BUF0 0x04 + +/* + * DOV0STA - Display/Overlay 0 Status Register + */ +#define DOV0STA 0x30008 + +#define MINUV_SCALE 0x1 + +#define RGB16ToColorKey(c) \ + (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) + +#define RGB15ToColorKey(c) \ + (((c & 0x7c00) << 9) | ((c & 0x03E0) << 6) | ((c & 0x001F) << 3)) + +void I810InitVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + XF86VideoAdaptorPtr *adaptors, *newAdaptors = NULL; + XF86VideoAdaptorPtr newAdaptor = NULL; + int num_adaptors; + + if (pScrn->bitsPerPixel != 8) + { + newAdaptor = I810SetupImageVideo(pScreen); + I810InitOffscreenImages(pScreen); + } + + num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); + + if(newAdaptor) { + if(!num_adaptors) { + num_adaptors = 1; + adaptors = &newAdaptor; + } else { + newAdaptors = /* need to free this someplace */ + malloc((num_adaptors + 1) * sizeof(XF86VideoAdaptorPtr*)); + if(newAdaptors) { + memcpy(newAdaptors, adaptors, num_adaptors * + sizeof(XF86VideoAdaptorPtr)); + newAdaptors[num_adaptors] = newAdaptor; + adaptors = newAdaptors; + num_adaptors++; + } + } + } + + if(num_adaptors) + xf86XVScreenInit(pScreen, adaptors, num_adaptors); + + if(newAdaptors) + free(newAdaptors); +} + +/* *INDENT-OFF* */ +/* client libraries expect an encoding */ +static XF86VideoEncodingRec DummyEncoding[1] = +{ + { + 0, + "XV_IMAGE", + IMAGE_MAX_WIDTH, IMAGE_MAX_HEIGHT, + {1, 1} + } +}; + +#define NUM_FORMATS 3 + +static XF86VideoFormatRec Formats[NUM_FORMATS] = +{ + {15, TrueColor}, {16, TrueColor}, {24, TrueColor} +}; + +#define NUM_ATTRIBUTES 3 + +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"} +}; + +#define NUM_IMAGES 6 + +#define I810_RV15 0x35315652 +#define I810_RV16 0x36315652 + +static XF86ImageRec Images[NUM_IMAGES] = +{ + { + I810_RV15, + XvRGB, + LSBFirst, + {'R','V','1','5', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, + 15, 0x7C00, 0x03E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R','V','B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + { + I810_RV16, + XvRGB, + LSBFirst, + {'R','V','1','6', + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, + 16, + XvPacked, + 1, + 16, 0xF800, 0x07E0, 0x001F, + 0, 0, 0, + 0, 0, 0, + 0, 0, 0, + {'R','V','B',0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + XvTopToBottom + }, + XVIMAGE_YUY2, + XVIMAGE_YV12, + XVIMAGE_I420, + XVIMAGE_UYVY +}; +/* *INDENT-ON* */ + +typedef struct { + uint32_t OBUF_0Y; + uint32_t OBUF_1Y; + uint32_t OBUF_0U; + uint32_t OBUF_0V; + uint32_t OBUF_1U; + uint32_t OBUF_1V; + uint32_t OV0STRIDE; + uint32_t YRGB_VPH; + uint32_t UV_VPH; + uint32_t HORZ_PH; + uint32_t INIT_PH; + uint32_t DWINPOS; + uint32_t DWINSZ; + uint32_t SWID; + uint32_t SWIDQW; + uint32_t SHEIGHT; + uint32_t YRGBSCALE; + uint32_t UVSCALE; + uint32_t OV0CLRC0; + uint32_t OV0CLRC1; + uint32_t DCLRKV; + uint32_t DCLRKM; + uint32_t SCLRKVH; + uint32_t SCLRKVL; + uint32_t SCLRKM; + uint32_t OV0CONF; + uint32_t OV0CMD; +} I810OverlayRegRec, *I810OverlayRegPtr; + +typedef struct { + uint32_t YBuf0offset; + uint32_t UBuf0offset; + uint32_t VBuf0offset; + + uint32_t YBuf1offset; + uint32_t UBuf1offset; + uint32_t VBuf1offset; + + unsigned char currentBuf; + + int brightness; + int contrast; + + RegionRec clip; + uint32_t colorKey; + + uint32_t videoStatus; + Time offTime; + Time freeTime; + FBLinearPtr linear; +} I810PortPrivRec, *I810PortPrivPtr; + +#define GET_PORT_PRIVATE(pScrn) \ + (I810PortPrivPtr)((I810PTR(pScrn))->adaptor->pPortPrivates[0].ptr) + +static void I810ResetVideo(ScrnInfoPtr pScrn) +{ + I810Ptr pI810 = I810PTR(pScrn); + I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; + I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); + + /* + * Default to maximum image size in YV12 + */ + + overlay->YRGB_VPH = 0; + overlay->UV_VPH = 0; + overlay->HORZ_PH = 0; + overlay->INIT_PH = 0; + overlay->DWINPOS = 0; + overlay->DWINSZ = (IMAGE_MAX_HEIGHT << 16) | IMAGE_MAX_WIDTH; + overlay->SWID = IMAGE_MAX_WIDTH | (IMAGE_MAX_WIDTH << 15); + overlay->SWIDQW = (IMAGE_MAX_WIDTH >> 3) | (IMAGE_MAX_WIDTH << 12); + overlay->SHEIGHT = IMAGE_MAX_HEIGHT | (IMAGE_MAX_HEIGHT << 15); + overlay->YRGBSCALE = 0x80004000; /* scale factor 1 */ + overlay->UVSCALE = 0x80004000; /* scale factor 1 */ + overlay->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */ + overlay->OV0CLRC1 = 0x80; /* saturation: bypass */ + + /* + * Enable destination color keying + */ + switch(pScrn->depth) { + case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey); + overlay->DCLRKM = 0x80070307; + break; + case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey); + overlay->DCLRKM = 0x80070707; + break; + default: overlay->DCLRKV = pPriv->colorKey; + overlay->DCLRKM = 0x80000000; + break; + } + + overlay->SCLRKVH = 0; + overlay->SCLRKVL = 0; + overlay->SCLRKM = 0; /* source color key disable */ + overlay->OV0CONF = 0; /* two 720 pixel line buffers */ + + overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST | + YUV_420; + + OVERLAY_UPDATE(pI810->OverlayPhysical); +} + + +static XF86VideoAdaptorPtr +I810SetupImageVideo(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I810Ptr pI810 = I810PTR(pScrn); + XF86VideoAdaptorPtr adapt; + I810PortPrivPtr pPriv; + + if(!(adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + + sizeof(I810PortPrivRec) + + sizeof(DevUnion)))) + return NULL; + + adapt->type = XvWindowMask | XvInputMask | XvImageMask; + adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; + adapt->name = "I810 Video Overlay"; + adapt->nEncodings = 1; + adapt->pEncodings = DummyEncoding; + adapt->nFormats = NUM_FORMATS; + adapt->pFormats = Formats; + adapt->nPorts = 1; + adapt->pPortPrivates = (DevUnion*)(&adapt[1]); + + pPriv = (I810PortPrivPtr)(&adapt->pPortPrivates[1]); + + adapt->pPortPrivates[0].ptr = (pointer)(pPriv); + adapt->pAttributes = Attributes; + adapt->nImages = NUM_IMAGES; + adapt->nAttributes = NUM_ATTRIBUTES; + adapt->pImages = Images; + adapt->PutVideo = NULL; + adapt->PutStill = NULL; + adapt->GetVideo = NULL; + adapt->GetStill = NULL; + adapt->StopVideo = I810StopVideo; + adapt->SetPortAttribute = I810SetPortAttribute; + adapt->GetPortAttribute = I810GetPortAttribute; + adapt->QueryBestSize = I810QueryBestSize; + adapt->PutImage = I810PutImage; + adapt->QueryImageAttributes = I810QueryImageAttributes; + + pPriv->colorKey = pI810->colorKey & ((1 << pScrn->depth) - 1); + pPriv->videoStatus = 0; + pPriv->brightness = 0; + pPriv->contrast = 64; + pPriv->linear = NULL; + pPriv->currentBuf = 0; + + /* gotta uninit this someplace */ + REGION_NULL(pScreen, &pPriv->clip); + + pI810->adaptor = adapt; + + pI810->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = I810BlockHandler; + + xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); + xvContrast = MAKE_ATOM("XV_CONTRAST"); + xvColorKey = MAKE_ATOM("XV_COLORKEY"); + + I810ResetVideo(pScrn); + + return adapt; +} + + +/* I810ClipVideo - + + Takes the dst box in standard X BoxRec form (top and left + edges inclusive, bottom and right exclusive). The new dst + box is returned. The source boundaries are given (x1, y1 + inclusive, x2, y2 exclusive) and returned are the new source + boundaries in 16.16 fixed point. +*/ + +static void +I810ClipVideo( + BoxPtr dst, + INT32 *x1, + INT32 *x2, + INT32 *y1, + INT32 *y2, + BoxPtr extents, /* extents of the clip region */ + INT32 width, + INT32 height +){ + INT32 vscale, hscale, delta; + int diff; + + hscale = ((*x2 - *x1) << 16) / (dst->x2 - dst->x1); + vscale = ((*y2 - *y1) << 16) / (dst->y2 - dst->y1); + + *x1 <<= 16; *x2 <<= 16; + *y1 <<= 16; *y2 <<= 16; + + diff = extents->x1 - dst->x1; + if(diff > 0) { + dst->x1 = extents->x1; + *x1 += diff * hscale; + } + diff = dst->x2 - extents->x2; + if(diff > 0) { + dst->x2 = extents->x2; + *x2 -= diff * hscale; + } + diff = extents->y1 - dst->y1; + if(diff > 0) { + dst->y1 = extents->y1; + *y1 += diff * vscale; + } + diff = dst->y2 - extents->y2; + if(diff > 0) { + dst->y2 = extents->y2; + *y2 -= diff * vscale; + } + + if(*x1 < 0) { + diff = (- *x1 + hscale - 1)/ hscale; + dst->x1 += diff; + *x1 += diff * hscale; + } + delta = *x2 - (width << 16); + if(delta > 0) { + diff = (delta + hscale - 1)/ hscale; + dst->x2 -= diff; + *x2 -= diff * hscale; + } + if(*y1 < 0) { + diff = (- *y1 + vscale - 1)/ vscale; + dst->y1 += diff; + *y1 += diff * vscale; + } + delta = *y2 - (height << 16); + if(delta > 0) { + diff = (delta + vscale - 1)/ vscale; + dst->y2 -= diff; + *y2 -= diff * vscale; + } +} + +static void +I810StopVideo(ScrnInfoPtr pScrn, pointer data, Bool shutdown) +{ + I810PortPrivPtr pPriv = (I810PortPrivPtr)data; + I810Ptr pI810 = I810PTR(pScrn); + + I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); + + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + + if(shutdown) { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + overlay->OV0CMD &= 0xFFFFFFFE; + OVERLAY_UPDATE(pI810->OverlayPhysical); + } + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } + pPriv->videoStatus = 0; + } else { + if(pPriv->videoStatus & CLIENT_VIDEO_ON) { + pPriv->videoStatus |= OFF_TIMER; + pPriv->offTime = currentTime.milliseconds + OFF_DELAY; + } + } + +} + +static int +I810SetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value, + pointer data +){ + I810PortPrivPtr pPriv = (I810PortPrivPtr)data; + I810Ptr pI810 = I810PTR(pScrn); + I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); + + if(attribute == xvBrightness) { + if((value < -128) || (value > 127)) + return BadValue; + pPriv->brightness = value; + overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff); + OVERLAY_UPDATE(pI810->OverlayPhysical); + } else + if(attribute == xvContrast) { + if((value < 0) || (value > 255)) + return BadValue; + pPriv->contrast = value; + overlay->OV0CLRC0 = (pPriv->contrast << 8) | (pPriv->brightness & 0xff); + OVERLAY_UPDATE(pI810->OverlayPhysical); + } else + if(attribute == xvColorKey) { + pPriv->colorKey = value; + switch(pScrn->depth) { + case 16: overlay->DCLRKV = RGB16ToColorKey(pPriv->colorKey); + break; + case 15: overlay->DCLRKV = RGB15ToColorKey(pPriv->colorKey); + break; + default: overlay->DCLRKV = pPriv->colorKey; + break; + } + OVERLAY_UPDATE(pI810->OverlayPhysical); + REGION_EMPTY(pScrn->pScreen, &pPriv->clip); + } else return BadMatch; + + return Success; +} + +static int +I810GetPortAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value, + pointer data +){ + I810PortPrivPtr pPriv = (I810PortPrivPtr)data; + + if(attribute == xvBrightness) { + *value = pPriv->brightness; + } else + if(attribute == xvContrast) { + *value = pPriv->contrast; + } else + if(attribute == xvColorKey) { + *value = pPriv->colorKey; + } else return BadMatch; + + return Success; +} + +static void +I810QueryBestSize( + ScrnInfoPtr pScrn, + Bool motion, + short vid_w, short vid_h, + short drw_w, short drw_h, + unsigned int *p_w, unsigned int *p_h, + pointer data +){ + if(vid_w > (drw_w << 1)) drw_w = vid_w >> 1; + if(vid_h > (drw_h << 1)) drw_h = vid_h >> 1; + + *p_w = drw_w; + *p_h = drw_h; +} + + +static void +I810CopyPackedData( + ScrnInfoPtr pScrn, + unsigned char *buf, + int srcPitch, + int dstPitch, + int top, + int left, + int h, + int w + ) +{ + I810Ptr pI810 = I810PTR(pScrn); + I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; + unsigned char *src, *dst; + + src = buf + (top*srcPitch) + (left<<1); + + if (pPriv->currentBuf == 0) + dst = pI810->FbBase + pPriv->YBuf0offset; + else + dst = pI810->FbBase + pPriv->YBuf1offset; + + w <<= 1; + while(h--) { + memcpy(dst, src, w); + src += srcPitch; + dst += dstPitch; + } +} + +static void +I810CopyPlanarData( + ScrnInfoPtr pScrn, + unsigned char *buf, + int srcPitch, + int dstPitch, /* of chroma */ + int srcH, + int top, + int left, + int h, + int w, + int id + ) +{ + I810Ptr pI810 = I810PTR(pScrn); + I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; + int i; + unsigned char *src1, *src2, *src3, *dst1, *dst2, *dst3; + + /* Copy Y data */ + src1 = buf + (top*srcPitch) + left; + if (pPriv->currentBuf == 0) + dst1 = pI810->FbBase + pPriv->YBuf0offset; + else + dst1 = pI810->FbBase + pPriv->YBuf1offset; + + for (i = 0; i < h; i++) { + memcpy(dst1, src1, w); + src1 += srcPitch; + dst1 += dstPitch << 1; + } + + /* Copy V data for YV12, or U data for I420 */ + src2 = buf + (srcH*srcPitch) + ((top*srcPitch)>>2) + (left>>1); + if (pPriv->currentBuf == 0) { + if (id == FOURCC_I420) + dst2 = pI810->FbBase + pPriv->UBuf0offset; + else + dst2 = pI810->FbBase + pPriv->VBuf0offset; + } else { + if (id == FOURCC_I420) + dst2 = pI810->FbBase + pPriv->UBuf1offset; + else + dst2 = pI810->FbBase + pPriv->VBuf1offset; + } + + for (i = 0; i < h/2; i++) { + memcpy(dst2, src2, w/2); + src2 += srcPitch>>1; + dst2 += dstPitch; + } + + /* Copy U data for YV12, or V data for I420 */ + src3 = buf + (srcH*srcPitch) + ((srcH*srcPitch)>>2) + ((top*srcPitch)>>2) + (left>>1); + if (pPriv->currentBuf == 0) { + if (id == FOURCC_I420) + dst3 = pI810->FbBase + pPriv->VBuf0offset; + else + dst3 = pI810->FbBase + pPriv->UBuf0offset; + } else { + if (id == FOURCC_I420) + dst3 = pI810->FbBase + pPriv->VBuf1offset; + else + dst3 = pI810->FbBase + pPriv->UBuf1offset; + } + + for (i = 0; i < h/2; i++) { + memcpy(dst3, src3, w/2); + src3 += srcPitch>>1; + dst3 += dstPitch; + } +} + +static void +I810DisplayVideo( + ScrnInfoPtr pScrn, + int id, + short width, short height, + int dstPitch, /* of chroma for 4:2:0 */ + int x1, int y1, int x2, int y2, + BoxPtr dstBox, + short src_w, short src_h, + short drw_w, short drw_h +){ + I810Ptr pI810 = I810PTR(pScrn); + I810PortPrivPtr pPriv = pI810->adaptor->pPortPrivates[0].ptr; + I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); + int xscaleInt, xscaleFract, yscaleInt, yscaleFract; + int xscaleIntUV = 0, xscaleFractUV = 0, yscaleIntUV = 0, yscaleFractUV = 0; + unsigned int swidth; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + swidth = (width + 7) & ~7; + overlay->SWID = (swidth << 15) | swidth; + overlay->SWIDQW = (swidth << 12) | (swidth >> 3); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + swidth = ((width + 3) & ~3) << 1; + overlay->SWID = swidth; + overlay->SWIDQW = swidth >> 3; + break; + } + + /* wide video formats (>720 pixels) are special */ + if( swidth > IMAGE_FAST_WIDTH ) { + overlay->OV0CONF = 1; /* one 1440 pixel line buffer */ + } else { + overlay->OV0CONF = 0; /* two 720 pixel line buffers */ + } + + overlay->SHEIGHT = height | (height << 15); + 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_1U = pPriv->UBuf1offset; + overlay->OBUF_1V = pPriv->VBuf1offset; + + /* + * Calculate horizontal and vertical scaling factors, default to 1:1 + */ + overlay->YRGBSCALE = 0x80004000; + overlay->UVSCALE = 0x80004000; + + /* + * Initially, YCbCr and Overlay Enable and + * vertical chrominance up interpolation and horozontal chrominance + * up interpolation + */ + overlay->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | Y_ADJUST | + OVERLAY_ENABLE; + + if ((drw_w != src_w) || (drw_h != src_h)) + { + xscaleInt = (src_w / drw_w) & 0x3; + xscaleFract = (src_w << 12) / drw_w; + yscaleInt = (src_h / drw_h) & 0x3; + yscaleFract = (src_h << 12) / drw_h; + + overlay->YRGBSCALE = (xscaleInt << 15) | + ((xscaleFract & 0xFFF) << 3) | + (yscaleInt) | + ((yscaleFract & 0xFFF) << 20); + + if (drw_w > src_w) + { + /* horizontal up-scaling */ + overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER; + overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER; + overlay->OV0CMD |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION); + } + + if (drw_h > src_h) + { + /* vertical up-scaling */ + overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER; + overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER; + overlay->OV0CMD |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION); + } + + if (drw_w < src_w) + { + /* horizontal down-scaling */ + overlay->OV0CMD &= ~HORIZONTAL_CHROMINANCE_FILTER; + overlay->OV0CMD &= ~HORIZONTAL_LUMINANCE_FILTER; + overlay->OV0CMD |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION); + } + + if (drw_h < src_h) + { + /* vertical down-scaling */ + overlay->OV0CMD &= ~VERTICAL_CHROMINANCE_FILTER; + overlay->OV0CMD &= ~VERTICAL_LUMINANCE_FILTER; + overlay->OV0CMD |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION); + } + + /* now calculate the UV scaling factor */ + + if (xscaleFract) + { + xscaleFractUV = xscaleFract >> MINUV_SCALE; + overlay->OV0CMD &= ~HC_DOWN_INTERPOLATION; + overlay->OV0CMD |= HC_UP_INTERPOLATION; + } + + if (xscaleInt) + { + xscaleIntUV = xscaleInt >> MINUV_SCALE; + if (xscaleIntUV) + { + overlay->OV0CMD &= ~HC_UP_INTERPOLATION; + } + } + + if (yscaleFract) + { + yscaleFractUV = yscaleFract >> MINUV_SCALE; + overlay->OV0CMD &= ~VC_DOWN_INTERPOLATION; + overlay->OV0CMD |= VC_UP_INTERPOLATION; + } + + if (yscaleInt) + { + yscaleIntUV = yscaleInt >> MINUV_SCALE; + if (yscaleIntUV) + { + overlay->OV0CMD &= ~VC_UP_INTERPOLATION; + overlay->OV0CMD |= VC_DOWN_INTERPOLATION; + } + } + + overlay->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) | + ((yscaleFractUV & 0xFFF) << 20); + } + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + /* set UV vertical phase to -0.25 */ + overlay->UV_VPH = 0x30003000; + overlay->INIT_PH = UV_VERT_BUF0 | UV_VERT_BUF1; + overlay->OV0STRIDE = (dstPitch << 1) | (dstPitch << 16); + overlay->OV0CMD &= ~SOURCE_FORMAT; + overlay->OV0CMD |= YUV_420; + break; + case I810_RV15: + case I810_RV16: + overlay->UV_VPH = 0; + overlay->INIT_PH = 0; + overlay->OV0STRIDE = dstPitch; + overlay->OV0CMD &= ~SOURCE_FORMAT; + overlay->OV0CMD |= (id==I810_RV15 ? RGB_555 : RGB_565); + overlay->OV0CMD &= ~OV_BYTE_ORDER; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + overlay->UV_VPH = 0; + overlay->INIT_PH = 0; + overlay->OV0STRIDE = dstPitch; + overlay->OV0CMD &= ~SOURCE_FORMAT; + overlay->OV0CMD |= YUV_422; + overlay->OV0CMD &= ~OV_BYTE_ORDER; + if (id == FOURCC_UYVY) + overlay->OV0CMD |= Y_SWAP; + break; + } + + overlay->OV0CMD &= ~BUFFER_AND_FIELD; + if (pPriv->currentBuf == 0) + overlay->OV0CMD |= BUFFER0_FIELD0; + else + overlay->OV0CMD |= BUFFER1_FIELD0; + + OVERLAY_UPDATE(pI810->OverlayPhysical); + +} + +static FBLinearPtr +I810AllocateMemory( + ScrnInfoPtr pScrn, + FBLinearPtr linear, + int size +){ + ScreenPtr pScreen; + FBLinearPtr new_linear; + + if(linear) { + if(linear->size >= size) + return linear; + + if(xf86ResizeOffscreenLinear(linear, size)) + return linear; + + xf86FreeOffscreenLinear(linear); + } + + pScreen = screenInfo.screens[pScrn->scrnIndex]; + + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, + NULL, NULL, NULL); + + if(!new_linear) { + int max_size; + + xf86QueryLargestOffscreenLinear(pScreen, &max_size, 4, + PRIORITY_EXTREME); + + if(max_size < size) return NULL; + + xf86PurgeUnlockedOffscreenAreas(pScreen); + new_linear = xf86AllocateOffscreenLinear(pScreen, size, 4, + NULL, NULL, NULL); + } + + return new_linear; +} + +static int +I810PutImage( + ScrnInfoPtr pScrn, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + int id, unsigned char* buf, + short width, short height, + Bool sync, + RegionPtr clipBoxes, pointer data, + DrawablePtr pDraw +){ + I810Ptr pI810 = I810PTR(pScrn); + I810PortPrivPtr pPriv = (I810PortPrivPtr)data; + INT32 x1, x2, y1, y2; + int srcPitch, dstPitch; + int top, left, npixels, nlines, size, loops; + BoxRec dstBox; + + + /* Clip */ + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, + REGION_EXTENTS(pScrn->pScreen, clipBoxes), width, height); + + if((x1 >= x2) || (y1 >= y2)) + return Success; + /* + * Fix for 4 pixel granularity of AdjustFrame + * unless boarder is clipped by frame + */ + dstBox.x1 -= (pScrn->frameX0 & + ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL)); + dstBox.x2 -= (pScrn->frameX0 & ~0x3); + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + srcPitch = (width + 3) & ~3; + dstPitch = ((width >> 1) + 7) & ~7; /* of chroma */ + size = dstPitch * height * 3; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + srcPitch = (width << 1); + dstPitch = (srcPitch + 7) & ~7; + size = dstPitch * height; + break; + } + + if(!(pPriv->linear = I810AllocateMemory(pScrn, pPriv->linear, + (pScrn->bitsPerPixel == 16) ? size : (size >> 1)))) + return BadAlloc; + + /* fixup pointers */ + pPriv->YBuf0offset = pPriv->linear->offset * pI810->cpp; + pPriv->UBuf0offset = pPriv->YBuf0offset + (dstPitch * 2 * height); + pPriv->VBuf0offset = pPriv->UBuf0offset + (dstPitch * height >> 1); + + pPriv->YBuf1offset = (pPriv->linear->offset * pI810->cpp) + size; + pPriv->UBuf1offset = pPriv->YBuf1offset + (dstPitch * 2 * height); + pPriv->VBuf1offset = pPriv->UBuf1offset + (dstPitch * height >> 1); + + + /* Make sure this buffer isn't in use */ + loops = 0; + while (loops < 1000000) { + if(((INREG(DOV0STA)&0x00100000)>>20) == pPriv->currentBuf) { + break; + } + loops++; + } + if(loops >= 1000000) { + pPriv->currentBuf = !pPriv->currentBuf; + } + + + /* buffer swap */ + if (pPriv->currentBuf == 0) + pPriv->currentBuf = 1; + else + pPriv->currentBuf = 0; + + /* copy data */ + top = y1 >> 16; + left = (x1 >> 16) & ~1; + npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; + + switch(id) { + case FOURCC_YV12: + case FOURCC_I420: + top &= ~1; + nlines = ((((y2 + 0xffff) >> 16) + 1) & ~1) - top; + I810CopyPlanarData(pScrn, buf, srcPitch, dstPitch, height, top, left, + nlines, npixels, id); + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + nlines = ((y2 + 0xffff) >> 16) - top; + I810CopyPackedData(pScrn, buf, srcPitch, dstPitch, top, left, nlines, + npixels); + break; + } + + /* update cliplist */ + if(!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { + REGION_COPY(pScrn->pScreen, &pPriv->clip, clipBoxes); + /* draw these */ + xf86XVFillKeyHelperDrawable(pDraw, pPriv->colorKey, clipBoxes); + } + + I810DisplayVideo(pScrn, id, width, height, dstPitch, + x1, y1, x2, y2, &dstBox, src_w, src_h, drw_w, drw_h); + + pPriv->videoStatus = CLIENT_VIDEO_ON; + + return Success; +} + + +static int +I810QueryImageAttributes( + ScrnInfoPtr pScrn, + int id, + unsigned short *w, unsigned short *h, + int *pitches, int *offsets +){ + int size, tmp; + + if(*w > IMAGE_MAX_WIDTH) *w = IMAGE_MAX_WIDTH; + if(*h > IMAGE_MAX_HEIGHT) *h = IMAGE_MAX_HEIGHT; + + *w = (*w + 1) & ~1; + if(offsets) offsets[0] = 0; + + switch(id) { + /* IA44 is for XvMC only */ + case FOURCC_IA44: + case FOURCC_AI44: + if(pitches) pitches[0] = *w; + size = *w * *h; + break; + case FOURCC_YV12: + case FOURCC_I420: + *h = (*h + 1) & ~1; + size = (*w + 3) & ~3; + if(pitches) pitches[0] = size; + size *= *h; + if(offsets) offsets[1] = size; + tmp = ((*w >> 1) + 3) & ~3; + if(pitches) pitches[1] = pitches[2] = tmp; + tmp *= (*h >> 1); + size += tmp; + if(offsets) offsets[2] = size; + size += tmp; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + size = *w << 1; + if(pitches) pitches[0] = size; + size *= *h; + break; + } + + return size; +} + +static void +I810BlockHandler ( + int i, + pointer blockData, + pointer pTimeout, + pointer pReadmask +){ + ScreenPtr pScreen = screenInfo.screens[i]; + ScrnInfoPtr pScrn = xf86Screens[i]; + I810Ptr pI810 = I810PTR(pScrn); + I810PortPrivPtr pPriv = GET_PORT_PRIVATE(pScrn); + I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); + + pScreen->BlockHandler = pI810->BlockHandler; + + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + pScreen->BlockHandler = I810BlockHandler; + + if(pPriv->videoStatus & TIMER_MASK) { + UpdateCurrentTime(); + if(pPriv->videoStatus & OFF_TIMER) { + if(pPriv->offTime < currentTime.milliseconds) { + /* Turn off the overlay */ + overlay->OV0CMD &= 0xFFFFFFFE; + OVERLAY_UPDATE(pI810->OverlayPhysical); + + pPriv->videoStatus = FREE_TIMER; + pPriv->freeTime = currentTime.milliseconds + FREE_DELAY; + } + } else { /* FREE_TIMER */ + if(pPriv->freeTime < currentTime.milliseconds) { + if(pPriv->linear) { + xf86FreeOffscreenLinear(pPriv->linear); + pPriv->linear = NULL; + } + pPriv->videoStatus = 0; + } + } + } +} + + +/*************************************************************************** + * Offscreen Images + ***************************************************************************/ + +typedef struct { + FBLinearPtr linear; + Bool isOn; +} OffscreenPrivRec, * OffscreenPrivPtr; + +static int +I810AllocateSurface( + ScrnInfoPtr pScrn, + int id, + unsigned short w, + unsigned short h, + XF86SurfacePtr surface +){ + FBLinearPtr linear; + int pitch, size, bpp; + OffscreenPrivPtr pPriv; + I810Ptr pI810 = I810PTR(pScrn); + + if((w > 1024) || (h > 1024)) + return BadAlloc; + + w = (w + 1) & ~1; + pitch = ((w << 1) + 15) & ~15; + bpp = pScrn->bitsPerPixel >> 3; + size = ((pitch * h) + bpp - 1) / bpp; + + if(!(linear = I810AllocateMemory(pScrn, NULL, size))) + return BadAlloc; + + surface->width = w; + surface->height = h; + + if(!(surface->pitches = malloc(sizeof(int)))) { + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(surface->offsets = malloc(sizeof(int)))) { + free(surface->pitches); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + if(!(pPriv = malloc(sizeof(OffscreenPrivRec)))) { + free(surface->pitches); + free(surface->offsets); + xf86FreeOffscreenLinear(linear); + return BadAlloc; + } + + pPriv->linear = linear; + pPriv->isOn = FALSE; + + surface->pScrn = pScrn; + surface->id = id; + surface->pitches[0] = pitch; + surface->offsets[0] = linear->offset * bpp; + surface->devPrivate.ptr = (pointer)pPriv; + + memset(pI810->FbBase + surface->offsets[0],0,size); + + return Success; +} + +static int +I810StopSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + + if(pPriv->isOn) { + I810Ptr pI810 = I810PTR(surface->pScrn); + + I810OverlayRegPtr overlay = (I810OverlayRegPtr) (pI810->FbBase + pI810->OverlayStart); + + overlay->OV0CMD &= 0xFFFFFFFE; + OVERLAY_UPDATE(pI810->OverlayPhysical); + + pPriv->isOn = FALSE; + } + + return Success; +} + + +static int +I810FreeSurface( + XF86SurfacePtr surface +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + + if(pPriv->isOn) { + I810StopSurface(surface); + } + xf86FreeOffscreenLinear(pPriv->linear); + free(surface->pitches); + free(surface->offsets); + free(surface->devPrivate.ptr); + + return Success; +} + +static int +I810GetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 *value +){ + return I810GetPortAttribute(pScrn, attribute, value, NULL); +} + +static int +I810SetSurfaceAttribute( + ScrnInfoPtr pScrn, + Atom attribute, + INT32 value +){ + return I810SetPortAttribute(pScrn, attribute, value, NULL); +} + + +static int +I810DisplaySurface( + XF86SurfacePtr surface, + short src_x, short src_y, + short drw_x, short drw_y, + short src_w, short src_h, + short drw_w, short drw_h, + RegionPtr clipBoxes +){ + OffscreenPrivPtr pPriv = (OffscreenPrivPtr)surface->devPrivate.ptr; + ScrnInfoPtr pScrn = surface->pScrn; + I810Ptr pI810 = I810PTR(pScrn); + I810PortPrivPtr pI810Priv = GET_PORT_PRIVATE(pScrn); + + INT32 x1, y1, x2, y2; + INT32 loops = 0; + BoxRec dstBox; + + x1 = src_x; + x2 = src_x + src_w; + y1 = src_y; + y2 = src_y + src_h; + + dstBox.x1 = drw_x; + dstBox.x2 = drw_x + drw_w; + dstBox.y1 = drw_y; + dstBox.y2 = drw_y + drw_h; + + I810ClipVideo(&dstBox, &x1, &x2, &y1, &y2, + REGION_EXTENTS(screenInfo.screens[0], clipBoxes), + surface->width, surface->height); + + /* + * Fix for 4 pixel granularity of AdjustFrame + * unless boarder is clipped by frame + */ + dstBox.x1 -= (pScrn->frameX0 & + ((dstBox.x1 == pScrn->frameX0) ? ~0x0UL : ~0x3UL)); + dstBox.x2 -= (pScrn->frameX0 & ~0x3); + dstBox.y1 -= pScrn->frameY0; + dstBox.y2 -= pScrn->frameY0; + + /* fixup pointers */ + pI810Priv->YBuf0offset = surface->offsets[0]; + pI810Priv->YBuf1offset = pI810Priv->YBuf0offset; + + /* wait for the last rendered buffer to be flipped in */ + while (((INREG(DOV0STA)&0x00100000)>>20) != pI810Priv->currentBuf) { + if(loops == 200000) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Overlay Lockup\n"); + break; + } + loops++; + } + + /* buffer swap */ + if (pI810Priv->currentBuf == 0) + pI810Priv->currentBuf = 1; + else + pI810Priv->currentBuf = 0; + + I810ResetVideo(pScrn); + + I810DisplayVideo(pScrn, surface->id, surface->width, surface->height, + surface->pitches[0], x1, y1, x2, y2, &dstBox, + src_w, src_h, drw_w, drw_h); + + xf86XVFillKeyHelper(pScrn->pScreen, pI810Priv->colorKey, clipBoxes); + + pPriv->isOn = TRUE; + /* we've prempted the XvImage stream so set its free timer */ + if(pI810Priv->videoStatus & CLIENT_VIDEO_ON) { + REGION_EMPTY(pScrn->pScreen, & pI810Priv->clip); + UpdateCurrentTime(); + pI810Priv->videoStatus = FREE_TIMER; + pI810Priv->freeTime = currentTime.milliseconds + FREE_DELAY; + pScrn->pScreen->BlockHandler = I810BlockHandler; + } + + return Success; +} + + +static void +I810InitOffscreenImages(ScreenPtr pScreen) +{ + XF86OffscreenImagePtr offscreenImages; + + /* need to free this someplace */ + if(!(offscreenImages = malloc(sizeof(XF86OffscreenImageRec)))) { + return; + } + + offscreenImages[0].image = &Images[0]; + offscreenImages[0].flags = VIDEO_OVERLAID_IMAGES | + VIDEO_CLIP_TO_VIEWPORT; + offscreenImages[0].alloc_surface = I810AllocateSurface; + offscreenImages[0].free_surface = I810FreeSurface; + offscreenImages[0].display = I810DisplaySurface; + offscreenImages[0].stop = I810StopSurface; + offscreenImages[0].setAttribute = I810SetSurfaceAttribute; + offscreenImages[0].getAttribute = I810GetSurfaceAttribute; + offscreenImages[0].max_width = 1024; + offscreenImages[0].max_height = 1024; + offscreenImages[0].num_attributes = 1; + offscreenImages[0].attributes = Attributes; + + xf86XVRegisterOffscreenImages(pScreen, offscreenImages, 1); +} + diff --git a/src/legacy/i810/i810_wmark.c b/src/legacy/i810/i810_wmark.c new file mode 100644 index 00000000..71b2a825 --- /dev/null +++ b/src/legacy/i810/i810_wmark.c @@ -0,0 +1,313 @@ +/************************************************************************** + +Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. +All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/* + * Authors: + * Keith Whitwell <keith@tungstengraphics.com> + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xf86.h" +#include "i810.h" + +struct wm_info { + double freq; + unsigned int wm; +}; + +static struct wm_info i810_wm_8_100[] = { + {0, 0x22003000}, + {25.2, 0x22003000}, + {28.0, 0x22003000}, + {31.5, 0x22003000}, + {36.0, 0x22007000}, + {40.0, 0x22007000}, + {45.0, 0x22007000}, + {49.5, 0x22008000}, + {50.0, 0x22008000}, + {56.3, 0x22008000}, + {65.0, 0x22008000}, + {75.0, 0x22008000}, + {78.8, 0x22008000}, + {80.0, 0x22008000}, + {94.0, 0x22008000}, + {96.0, 0x22107000}, + {99.0, 0x22107000}, + {108.0, 0x22107000}, + {121.0, 0x22107000}, + {128.9, 0x22107000}, + {132.0, 0x22109000}, + {135.0, 0x22109000}, + {157.5, 0x2210b000}, + {162.0, 0x2210b000}, + {175.5, 0x2210b000}, + {189.0, 0x2220e000}, + {202.5, 0x2220e000} +}; + +static struct wm_info i810_wm_16_100[] = { + {0, 0x22004000}, + {25.2, 0x22006000}, + {28.0, 0x22006000}, + {31.5, 0x22007000}, + {36.0, 0x22007000}, + {40.0, 0x22007000}, + {45.0, 0x22007000}, + {49.5, 0x22009000}, + {50.0, 0x22009000}, + {56.3, 0x22108000}, + {65.0, 0x2210e000}, + {75.0, 0x2210e000}, + {78.8, 0x2210e000}, + {80.0, 0x22210000}, + {94.5, 0x22210000}, + {96.0, 0x22210000}, + {99.0, 0x22210000}, + {108.0, 0x22210000}, + {121.0, 0x22210000}, + {128.9, 0x22210000}, + {132.0, 0x22314000}, + {135.0, 0x22314000}, + {157.5, 0x22415000}, + {162.0, 0x22416000}, + {175.5, 0x22416000}, + {189.0, 0x22416000}, + {195.0, 0x22416000}, + {202.5, 0x22416000} +}; + +static struct wm_info i810_wm_24_100[] = { + {0, 0x22006000}, + {25.2, 0x22009000}, + {28.0, 0x22009000}, + {31.5, 0x2200a000}, + {36.0, 0x2210c000}, + {40.0, 0x2210c000}, + {45.0, 0x2210c000}, + {49.5, 0x22111000}, + {50.0, 0x22111000}, + {56.3, 0x22111000}, + {65.0, 0x22214000}, + {75.0, 0x22214000}, + {78.8, 0x22215000}, + {80.0, 0x22216000}, + {94.5, 0x22218000}, + {96.0, 0x22418000}, + {99.0, 0x22418000}, + {108.0, 0x22418000}, + {121.0, 0x22418000}, + {128.9, 0x22419000}, + {132.0, 0x22519000}, + {135.0, 0x4441d000}, + {157.5, 0x44419000}, + {162.0, 0x44419000}, + {175.5, 0x44419000}, + {189.0, 0x44419000}, + {195.0, 0x44419000}, + {202.5, 0x44419000} +}; + +#if 0 +/* not used */ +static struct wm_info i810_wm_32_100[] = { + {0, 0x2210b000}, + {60, 0x22415000}, /* 0x314000 works too */ + {80, 0x22419000} /* 0x518000 works too */ +}; +#endif + +static struct wm_info i810_wm_8_133[] = { + {0, 0x22003000}, + {25.2, 0x22003000}, + {28.0, 0x22003000}, + {31.5, 0x22003000}, + {36.0, 0x22007000}, + {40.0, 0x22007000}, + {45.0, 0x22007000}, + {49.5, 0x22008000}, + {50.0, 0x22008000}, + {56.3, 0x22008000}, + {65.0, 0x22008000}, + {75.0, 0x22008000}, + {78.8, 0x22008000}, + {80.0, 0x22008000}, + {94.0, 0x22008000}, + {96.0, 0x22107000}, + {99.0, 0x22107000}, + {108.0, 0x22107000}, + {121.0, 0x22107000}, + {128.9, 0x22107000}, + {132.0, 0x22109000}, + {135.0, 0x22109000}, + {157.5, 0x2210b000}, + {162.0, 0x2210b000}, + {175.5, 0x2210b000}, + {189.0, 0x2220e000}, + {202.5, 0x2220e000} +}; + +static struct wm_info i810_wm_16_133[] = { + {0, 0x22004000}, + {25.2, 0x22006000}, + {28.0, 0x22006000}, + {31.5, 0x22007000}, + {36.0, 0x22007000}, + {40.0, 0x22007000}, + {45.0, 0x22007000}, + {49.5, 0x22009000}, + {50.0, 0x22009000}, + {56.3, 0x22108000}, + {65.0, 0x2210e000}, + {75.0, 0x2210e000}, + {78.8, 0x2210e000}, + {80.0, 0x22210000}, + {94.5, 0x22210000}, + {96.0, 0x22210000}, + {99.0, 0x22210000}, + {108.0, 0x22210000}, + {121.0, 0x22210000}, + {128.9, 0x22210000}, + {132.0, 0x22314000}, + {135.0, 0x22314000}, + {157.5, 0x22415000}, + {162.0, 0x22416000}, + {175.5, 0x22416000}, + {189.0, 0x22416000}, + {195.0, 0x22416000}, + {202.5, 0x22416000} +}; + +static struct wm_info i810_wm_24_133[] = { + {0, 0x22006000}, + {25.2, 0x22009000}, + {28.0, 0x22009000}, + {31.5, 0x2200a000}, + {36.0, 0x2210c000}, + {40.0, 0x2210c000}, + {45.0, 0x2210c000}, + {49.5, 0x22111000}, + {50.0, 0x22111000}, + {56.3, 0x22111000}, + {65.0, 0x22214000}, + {75.0, 0x22214000}, + {78.8, 0x22215000}, + {80.0, 0x22216000}, + {94.5, 0x22218000}, + {96.0, 0x22418000}, + {99.0, 0x22418000}, + {108.0, 0x22418000}, + {121.0, 0x22418000}, + {128.9, 0x22419000}, + {132.0, 0x22519000}, + {135.0, 0x4441d000}, + {157.5, 0x44419000}, + {162.0, 0x44419000}, + {175.5, 0x44419000}, + {189.0, 0x44419000}, + {195.0, 0x44419000}, + {202.5, 0x44419000} +}; + +#define Elements(x) (sizeof(x)/sizeof(*x)) + +/* + * I810CalcFIFO -- + * + * Calculate burst length and FIFO watermark. + */ + +unsigned int +I810CalcWatermark(ScrnInfoPtr pScrn, double freq, Bool dcache) +{ + I810Ptr pI810 = I810PTR(pScrn); + struct wm_info *tab; + int nr; + int i; + + if (pI810->LmFreqSel == 100) { + switch (pScrn->bitsPerPixel) { + case 8: + tab = i810_wm_8_100; + nr = Elements(i810_wm_8_100); + break; + case 16: + tab = i810_wm_16_100; + nr = Elements(i810_wm_16_100); + break; + case 24: + tab = i810_wm_24_100; + nr = Elements(i810_wm_24_100); + break; + default: + return 0; + } + } else { + switch (pScrn->bitsPerPixel) { + case 8: + tab = i810_wm_8_133; + nr = Elements(i810_wm_8_133); + break; + case 16: + tab = i810_wm_16_133; + nr = Elements(i810_wm_16_133); + break; + case 24: + tab = i810_wm_24_133; + nr = Elements(i810_wm_24_133); + break; + default: + return 0; + } + } + + for (i = 0; i < nr && tab[i].freq < freq; i++) ; + + if (i == nr) + i--; + + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 3, + "chose watermark 0x%x: (tab.freq %.1f)\n", + tab[i].wm, tab[i].freq); + + /* None of these values (sourced from intel) have watermarks for + * the dcache memory. Fake it for now by using the same watermark + * for both... + * + * Update: this is probably because dcache isn't real useful as + * framebuffer memory, so intel's drivers don't need watermarks + * for that memory because they never use it to feed the ramdacs. + * We do use it in the fallback mode, so keep the watermarks for + * now. + */ + if (dcache) + return (tab[i].wm & ~0xffffff) | ((tab[i].wm >> 12) & 0xfff); + else + return tab[i].wm; +} diff --git a/src/legacy/i810/xvmc/I810XvMC.c b/src/legacy/i810/xvmc/I810XvMC.c new file mode 100644 index 00000000..0754ff44 --- /dev/null +++ b/src/legacy/i810/xvmc/I810XvMC.c @@ -0,0 +1,4509 @@ +/*************************************************************************** + +Copyright 2001 Intel Corporation. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/************************************************************************* +** File libI810XvMC.c +** +** Authors: +** Matt Sottek <matthew.j.sottek@intel.com> +** Bob Paauwe <bob.j.paauwe@intel.com> +** +** +***************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <signal.h> +#include <fcntl.h> +#include <dirent.h> +#include <string.h> + +#include <sys/ioctl.h> +#include <X11/Xlibint.h> +#include <fourcc.h> +#include <X11/extensions/Xv.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XvMC.h> +#include <X11/extensions/XvMClib.h> +#include "I810XvMC.h" + +static int error_base; +static int event_base; + +/*************************************************************************** +// Function: i810_get_free_buffer +// Description: Allocates a free dma page using kernel ioctls, then +// programs the data into the already allocated dma buffer list. +// Arguments: pI810XvMC private data structure from the current context. +// Notes: We faked the drmMapBufs for the i810's security so now we have +// to insert an allocated page into the correct spot in the faked +// list to keep up appearences. +// Concept for this function was taken from Mesa sources. +// Returns: drmBufPtr containing the information about the allocated page. +***************************************************************************/ +drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC) { + drmI810DMA dma; + drmBufPtr buf; + + dma.granted = 0; + dma.request_size = 4096; + while(!dma.granted) { + if(GET_BUFFER(pI810XvMC, dma) || !dma.granted) + FLUSH(pI810XvMC); + } /* No DMA granted */ + + buf = &(pI810XvMC->dmabufs->list[dma.request_idx]); + buf->idx = dma.request_idx; + buf->used = 0; + buf->total = dma.request_size; + buf->address = (drmAddress)dma.virtual; + return buf; +} + +/*************************************************************************** +// Function: free_privContext +// Description: Free's the private context structure if the reference +// count is 0. +***************************************************************************/ +void i810_free_privContext(i810XvMCContext *pI810XvMC) { + + I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT); + + + pI810XvMC->ref--; + if(!pI810XvMC->ref) { + drmUnmapBufs(pI810XvMC->dmabufs); + drmUnmap(pI810XvMC->overlay.address,pI810XvMC->overlay.size); + drmUnmap(pI810XvMC->surfaces.address,pI810XvMC->surfaces.size); + drmClose(pI810XvMC->fd); + + free(pI810XvMC->dmabufs->list); + free(pI810XvMC); + } + + I810_UNLOCK(pI810XvMC); +} + + +/*************************************************************************** +// Function: XvMCCreateContext +// Description: Create a XvMC context for the given surface parameters. +// Arguments: +// display - Connection to the X server. +// port - XvPortID to use as avertised by the X connection. +// surface_type_id - Unique identifier for the Surface type. +// width - Width of the surfaces. +// height - Height of the surfaces. +// flags - one or more of the following +// XVMC_DIRECT - A direct rendered context is requested. +// +// Notes: surface_type_id and width/height parameters must match those +// returned by XvMCListSurfaceTypes. +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port, + int surface_type_id, int width, int height, int flags, + XvMCContext *context) { + i810XvMCContext *pI810XvMC; + int priv_count; + uint *priv_data; + uint magic; + Status ret; + int major, minor; + + /* Verify Obvious things first */ + if(context == NULL) { + return XvMCBadContext; + } + + if(!(flags & XVMC_DIRECT)) { + /* Indirect */ + printf("Indirect Rendering not supported!\nUsing Direct."); + } + + /* Limit use to root for now */ + if(geteuid()) { + printf("Use of XvMC on i810 is currently limited to root\n"); + return BadAccess; + } + + /* FIXME: Check $DISPLAY for legal values here */ + + context->surface_type_id = surface_type_id; + context->width = (unsigned short)width; + context->height = (unsigned short)height; + context->flags = flags; + context->port = port; + /* + Width, Height, and flags are checked against surface_type_id + and port for validity inside the X server, no need to check + here. + */ + + /* Allocate private Context data */ + context->privData = (void *)malloc(sizeof(i810XvMCContext)); + if(!context->privData) { + printf("Unable to allocate resources for XvMC context.\n"); + return BadAlloc; + } + pI810XvMC = (i810XvMCContext *)context->privData; + + + /* Verify the XvMC extension exists */ + if(! XvMCQueryExtension(display, &event_base, + &error_base)) { + printf("XvMC Extension is not available!\n"); + return BadAlloc; + } + /* Verify XvMC version */ + ret = XvMCQueryVersion(display, &major, &minor); + if(ret) { + printf("XvMCQuery Version Failed, unable to determine protocol version\n"); + } + /* FIXME: Check Major and Minor here */ + + /* Check for drm */ + if(! drmAvailable()) { + printf("Direct Rendering is not avilable on this system!\n"); + return BadAlloc; + } + + /* + Build the Attribute Atoms, and Initialize the ones that exist + in Xv. + */ + pI810XvMC->xv_colorkey = XInternAtom(display,"XV_COLORKEY",0); + if(!pI810XvMC->xv_colorkey) { + return XvBadPort; + } + ret = XvGetPortAttribute(display,port,pI810XvMC->xv_colorkey, + &pI810XvMC->colorkey); + if(ret) { + return ret; + } + pI810XvMC->xv_brightness = XInternAtom(display,"XV_BRIGHTNESS",0); + pI810XvMC->xv_saturation = XInternAtom(display,"XV_SATURATION",0); + pI810XvMC->xv_contrast = XInternAtom(display,"XV_CONTRAST",0); + pI810XvMC->brightness = 0; + pI810XvMC->saturation = 0x80; /* 1.0 in 3.7 format */ + pI810XvMC->contrast = 0x40; /* 1.0 in 3.6 format */ + + /* Open DRI Device */ + if((pI810XvMC->fd = drmOpen("i810",NULL)) < 0) { + printf("DRM Device for i810 could not be opened.\n"); + free(pI810XvMC); + return BadAccess; + } /* !pI810XvMC->fd */ + + /* Get magic number and put it in privData for passing */ + drmGetMagic(pI810XvMC->fd,&magic); + context->flags = (unsigned long)magic; + + /* + Pass control to the X server to create a drm_context_t for us and + validate the with/height and flags. + */ + if((ret = _xvmc_create_context(display, context, &priv_count, &priv_data))) { + printf("Unable to create XvMC Context.\n"); + return ret; + } + + /* + X server returns a structure like this: + drm_context_t + fbBase + OverlayOffset + OverlaySize + SurfacesOffset + SurfacesSize + busIdString = 9 char + 1 + */ + if(priv_count != 9) { + printf("_xvmc_create_context() returned incorrect data size!\n"); + printf("\tExpected 9, got %d\n",priv_count); + _xvmc_destroy_context(display, context); + free(pI810XvMC); + return BadAlloc; + } + pI810XvMC->drmcontext = priv_data[0]; + pI810XvMC->fb_base = priv_data[1]; + pI810XvMC->overlay.offset = priv_data[2] + priv_data[1]; + pI810XvMC->overlay.size = priv_data[3]; + pI810XvMC->surfaces.offset = priv_data[4] + priv_data[1]; + pI810XvMC->surfaces.size = priv_data[5]; + strncpy(pI810XvMC->busIdString,(char *)&priv_data[6],9); + pI810XvMC->busIdString[9] = '\0'; + + /* Must free the private data we were passed from X */ + free(priv_data); + + /* Initialize private context values */ + pI810XvMC->current = 0; + pI810XvMC->lock = 0; + pI810XvMC->last_flip = 0; + pI810XvMC->dual_prime = 0; + + /* + Map dma Buffers: Not really, this would be a drmMapBufs + but due to the i810 security model we have to just create an + empty data structure to fake it. + */ + pI810XvMC->dmabufs = (drmBufMapPtr)malloc(sizeof(drmBufMap)); + if(pI810XvMC->dmabufs == NULL) { + printf("Dma Bufs could not be mapped.\n"); + _xvmc_destroy_context(display, context); + free(pI810XvMC); + return BadAlloc; + } /* pI810XvMC->dmabufs == NULL */ + memset(pI810XvMC->dmabufs, 0, sizeof(drmBufMap)); + pI810XvMC->dmabufs->list = (drmBufPtr)malloc(sizeof(drmBuf) * + I810_DMA_BUF_NR); + if(pI810XvMC->dmabufs->list == NULL) { + printf("Dma Bufs could not be mapped.\n"); + _xvmc_destroy_context(display, context); + free(pI810XvMC); + return BadAlloc; + } /* pI810XvMC->dmabufs->list == NULL */ + memset(pI810XvMC->dmabufs->list, 0, sizeof(drmBuf) * I810_DMA_BUF_NR); + + /* Map the Overlay memory */ + if(drmMap(pI810XvMC->fd,pI810XvMC->overlay.offset, + pI810XvMC->overlay.size,&(pI810XvMC->overlay.address)) < 0) { + printf("Unable to map Overlay at offset 0x%x and size 0x%x\n", + (unsigned int)pI810XvMC->overlay.offset,pI810XvMC->overlay.size); + _xvmc_destroy_context(display, context); + free(pI810XvMC->dmabufs->list); + free(pI810XvMC); + return BadAlloc; + } /* drmMap() < 0 */ + + /* Overlay Regs are offset 1024 into Overlay Map */ + pI810XvMC->oregs = (i810OverlayRec *) + ((unsigned char *)pI810XvMC->overlay.address + 1024); + + /* Map Surfaces */ + if(drmMap(pI810XvMC->fd,pI810XvMC->surfaces.offset, + pI810XvMC->surfaces.size,&(pI810XvMC->surfaces.address)) < 0) { + printf("Unable to map XvMC Surfaces.\n"); + _xvmc_destroy_context(display, context); + free(pI810XvMC->dmabufs->list); + free(pI810XvMC); + return BadAlloc; + } /* drmMap() < 0 */ + + /* + There is a tiny chance that someone was using the overlay and + issued a flip that hasn't finished. To be 100% sure I'll just + take the lock and sleep for the worst case time for a flip. + */ + I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT); + usleep(20000); /* 1/50th Sec for 50hz refresh */ + + /* Set up Overlay regs with Initial Values */ + pI810XvMC->oregs->YRGB_VPH = 0; + pI810XvMC->oregs->UV_VPH = 0; + pI810XvMC->oregs->HORZ_PH = 0; + pI810XvMC->oregs->INIT_PH = 0; + pI810XvMC->oregs->DWINPOS = 0; + pI810XvMC->oregs->DWINSZ = (I810_XVMC_MAXHEIGHT << 16) | + I810_XVMC_MAXWIDTH; + pI810XvMC->oregs->SWID = I810_XVMC_MAXWIDTH | (I810_XVMC_MAXWIDTH << 15); + pI810XvMC->oregs->SWIDQW = (I810_XVMC_MAXWIDTH >> 3) | + (I810_XVMC_MAXWIDTH << 12); + pI810XvMC->oregs->SHEIGHT = I810_XVMC_MAXHEIGHT | + (I810_XVMC_MAXHEIGHT << 15); + pI810XvMC->oregs->YRGBSCALE = 0x80004000; /* scale factor 1 */ + pI810XvMC->oregs->UVSCALE = 0x80004000; /* scale factor 1 */ + pI810XvMC->oregs->OV0CLRC0 = 0x4000; /* brightness: 0 contrast: 1.0 */ + pI810XvMC->oregs->OV0CLRC1 = 0x80; /* saturation: bypass */ + + /* Destination Colorkey Setup */ + pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey); + pI810XvMC->oregs->DCLRKM = 0x80070307; + + + pI810XvMC->oregs->SCLRKVH = 0; + pI810XvMC->oregs->SCLRKVL = 0; + pI810XvMC->oregs->SCLRKM = 0; /* source color key disable */ + pI810XvMC->oregs->OV0CONF = 0; /* two 720 pixel line buffers */ + + pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | + Y_ADJUST | YUV_420; + + pI810XvMC->ref = 1; + + I810_UNLOCK(pI810XvMC); + + return Success; + +} + +/*************************************************************************** +// Function: XvMCDestroyContext +// Description: Destorys the specified context. +// +// Arguments: +// display - Specifies the connection to the server. +// context - The context to be destroyed. +// +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCDestroyContext(Display *display, XvMCContext *context) { + i810XvMCContext *pI810XvMC; + + if(context == NULL) { + return (error_base + XvMCBadContext); + } + if(context->privData == NULL) { + return (error_base + XvMCBadContext); + } + pI810XvMC = (i810XvMCContext *)context->privData; + + /* Turn off the overlay */ + if(pI810XvMC->last_flip) { + I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT); + + /* Make sure last flip is done */ + BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current); + + pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | + Y_ADJUST; + pI810XvMC->current = !pI810XvMC->current; + if(pI810XvMC->current == 1) { + pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0; + } + else { + pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0; + } + OVERLAY_FLIP(pI810XvMC); + pI810XvMC->last_flip++; + + /* Wait for the flip */ + BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current); + + I810_UNLOCK(pI810XvMC); + } + + /* Pass Control to the X server to destroy the drm_context_t */ + _xvmc_destroy_context(display, context); + + i810_free_privContext(pI810XvMC); + context->privData = NULL; + + return Success; +} + + +/*************************************************************************** +// Function: XvMCCreateSurface +***************************************************************************/ +_X_EXPORT Status XvMCCreateSurface( Display *display, XvMCContext *context, + XvMCSurface *surface) { + i810XvMCContext *pI810XvMC; + i810XvMCSurface *pI810Surface; + int priv_count; + uint *priv_data; + Status ret; + + if((surface == NULL) || (context == NULL) || (display == NULL)){ + return BadValue; + } + + pI810XvMC = (i810XvMCContext *)context->privData; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadContext); + } + + + surface->privData = (i810XvMCSurface *)malloc(sizeof(i810XvMCSurface)); + if(!surface->privData) { + return BadAlloc; + } + pI810Surface = (i810XvMCSurface *)surface->privData; + + /* Initialize private values */ + pI810Surface->privContext = pI810XvMC; + pI810Surface->last_render = 0; + pI810Surface->last_flip = 0; + pI810Surface->second_field = 0; + + if((ret = _xvmc_create_surface(display, context, surface, + &priv_count, &priv_data))) { + free(pI810Surface); + printf("Unable to create XvMCSurface.\n"); + return ret; + } + + /* + _xvmc_create_subpicture returns 2 uints with the offset into + the DRM map for the Y surface and UV surface. + */ + if(priv_count != 2) { + printf("_xvmc_create_surface() return incorrect data size.\n"); + printf("Expected 2 got %d\n",priv_count); + free(priv_data); + free(pI810Surface); + return BadAlloc; + } + /* Data == Client Address, offset == Physical address offset */ + pI810Surface->data = pI810XvMC->surfaces.address; + pI810Surface->offset = pI810XvMC->surfaces.offset; + + + /* + i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch + and the Tiler need 512k aligned surfaces, basically we are + stuck with fixed memory with pitch 1024 for Y data. UV = 512. + */ + pI810Surface->pitch = 10; + if((surface->surface_type_id == FOURCC_UYVY) || + (surface->surface_type_id == FOURCC_YUY2)) { + /* This is not implemented server side. */ + pI810Surface->pitch++; + } + + /* + offsets[0,1,2] == Offsets from either data or offset for the Y + U and V surfaces. + */ + pI810Surface->offsets[0] = priv_data[0]; + if(((unsigned long)pI810Surface->data + pI810Surface->offsets[0]) & 4095) { + printf("XvMCCreateSurface: Surface offset 0 is not 4096 aligned\n"); + } + + if((surface->surface_type_id == FOURCC_UYVY) || + (surface->surface_type_id == FOURCC_YUY2)) { + /* Packed surface, not fully implemented */ + pI810Surface->offsets[1] = 0; + pI810Surface->offsets[2] = 0; + } + else { + /* Planar surface */ + pI810Surface->offsets[1] = priv_data[1]; + if(((unsigned long)pI810Surface->data + pI810Surface->offsets[1]) & 2047) { + printf("XvMCCreateSurface: Surface offset 1 is not 2048 aligned\n"); + } + + pI810Surface->offsets[2] = ((unsigned long)pI810Surface->offsets[1] + + (1<<(pI810Surface->pitch - 1)) * 288); + if(((unsigned long)pI810Surface->data + pI810Surface->offsets[2]) & 2047) { + printf("XvMCCreateSurface: Surface offset 2 is not 2048 aligned\n"); + } + + } + + /* Free data returned from xvmc_create_surface */ + free(priv_data); + + /* Clear the surface to 0 */ + memset((void *)((unsigned long)pI810Surface->data + (unsigned long)pI810Surface->offsets[0]), + 0, ((1<<pI810Surface->pitch) * surface->height)); + + switch(surface->surface_type_id) { + case FOURCC_YV12: + case FOURCC_I420: + /* Destination buffer info command */ + pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset + + pI810Surface->offsets[0]) & ~0xfc000fff) | + (pI810Surface->pitch - 9)); + pI810Surface->dbi1u = ((((unsigned int)pI810Surface->offset + + pI810Surface->offsets[1]) & ~0xfc000fff) | + (pI810Surface->pitch - 10)); + pI810Surface->dbi1v = ((((unsigned int)pI810Surface->offset + + pI810Surface->offsets[2]) & ~0xfc000fff) | + (pI810Surface->pitch - 10)); + + /* Destination buffer variables command */ + pI810Surface->dbv1 = (0x8<<20) | (0x8<<16); + /* Map info command */ + pI810Surface->mi1y = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 3); + pI810Surface->mi1u = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4); + pI810Surface->mi1v = (0x1<<24) | (1<<9) | (pI810Surface->pitch - 4); + + pI810Surface->mi2y = (((unsigned int)surface->height - 1)<<16) | + ((unsigned int)surface->width - 1); + pI810Surface->mi2u = (((unsigned int)surface->height - 1)<<15) | + (((unsigned int)surface->width - 1)>>1); + pI810Surface->mi2v = pI810Surface->mi2u; + + pI810Surface->mi3y = ((unsigned int)pI810Surface->offset + + pI810Surface->offsets[0]) & ~0x0000000f; + pI810Surface->mi3u = ((unsigned int)pI810Surface->offset + + pI810Surface->offsets[1]) & ~0x0000000f; + pI810Surface->mi3v = ((unsigned int)pI810Surface->offset + + pI810Surface->offsets[2]) & ~0x0000000f; + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + /* Destination buffer info command */ + pI810Surface->dbi1y = ((((unsigned int)pI810Surface->offset + + pI810Surface->offsets[0]) & ~0xfc000fff) | + (pI810Surface->pitch - 9)); + /* Destination buffer variables command */ + if(surface->surface_type_id == FOURCC_YUY2) { + pI810Surface->dbv1 = 0x5<<8; + pI810Surface->mi1y = 0x5<<24 | pI810Surface->pitch | 0x1<<21; + } + else { + pI810Surface->dbv1 = 0x4<<8; + pI810Surface->mi1y = 0x5<<24 | (pI810Surface->pitch - 3); + } + pI810Surface->mi2y = (((unsigned int)surface->width - 1)<<16) | + ((unsigned int)surface->height - 1); + pI810Surface->mi3y = ((unsigned int)pI810Surface->offset + + pI810Surface->offsets[0]) & ~0xfc000fff; + break; + } + pI810XvMC->ref++; + + return Success; +} + + +/*************************************************************************** +// Function: XvMCDestroySurface +***************************************************************************/ +_X_EXPORT Status XvMCDestroySurface(Display *display, XvMCSurface *surface) { + i810XvMCSurface *pI810Surface; + i810XvMCContext *pI810XvMC; + + if((display == NULL) || (surface == NULL)) { + return BadValue; + } + if(surface->privData == NULL) { + return (error_base + XvMCBadSurface); + } + + pI810Surface = (i810XvMCSurface *)surface->privData; + if(pI810Surface->last_flip) { + XvMCSyncSurface(display,surface); + } + pI810XvMC = (i810XvMCContext *)pI810Surface->privContext; + + _xvmc_destroy_surface(display,surface); + + i810_free_privContext(pI810XvMC); + + free(pI810Surface); + surface->privData = NULL; + return Success; +} + +/*************************************************************************** +// Function: XvMCCreateBlocks +***************************************************************************/ +_X_EXPORT Status XvMCCreateBlocks(Display *display, XvMCContext *context, + unsigned int num_blocks, + XvMCBlockArray *block) { + + if((display == NULL) || (context == NULL) || (num_blocks == 0)) { + return BadValue; + } + + block->blocks = (short *)malloc(num_blocks<<6 * sizeof(short)); + if(block->blocks == NULL) { + return BadAlloc; + } + + block->num_blocks = num_blocks; + block->context_id = context->context_id; + + block->privData = NULL; + + return Success; +} + +/*************************************************************************** +// Function: XvMCDestroyBlocks +***************************************************************************/ +_X_EXPORT Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *block) { + if(display == NULL) { + return BadValue; + } + + free(block->blocks); + block->num_blocks = 0; + block->context_id = 0; + block->privData = NULL; + return Success; +} + +/*************************************************************************** +// Function: XvMCCreateMacroBlocks +***************************************************************************/ +_X_EXPORT Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context, + unsigned int num_blocks, + XvMCMacroBlockArray *blocks) { + + if((display == NULL) || (context == NULL) || (blocks == NULL) || + (num_blocks == 0)) { + return BadValue; + } + memset(blocks,0,sizeof(XvMCMacroBlockArray)); + blocks->context_id = context->context_id; + blocks->privData = NULL; + + blocks->macro_blocks = (XvMCMacroBlock *) + malloc(num_blocks * sizeof(XvMCMacroBlock)); + if(blocks->macro_blocks == NULL) { + return BadAlloc; + } + blocks->num_blocks = num_blocks; + + return Success; +} + +/*************************************************************************** +// Function: XvMCDestroyMacroBlocks +***************************************************************************/ +_X_EXPORT Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *block) { + if((display == NULL) || (block == NULL)) { + return BadValue; + } + if(block->macro_blocks) { + free(block->macro_blocks); + } + block->context_id = 0; + block->num_blocks = 0; + block->privData = NULL; + + return Success; +} + + +/*************************************************************************** +// Function: dp (Debug Print) +// Description: This function prints out in hex i * uint32_t at the address +// supplied. This enables you to print out the dma buffers from +// within the debugger even though they are not in your address space. +***************************************************************************/ +void dp(unsigned int *address, unsigned int i) { + int j; + + printf("DebugPrint:\n"); + for(j=0; j<i; j++) { + printf("0x%8.8x ",address[j]); + if(j && !(j & 7)) { printf("\n");} + } +} + +/*************************************************************************** +// Macro: PACK_* +// Description: Packs 16bit signed data from blocks into either 8bit unsigned +// intra data or 16bit signed correction data, both packed into +// 32 bit integers. +***************************************************************************/ +#define PACK_INTRA_DATA(d,b,n) \ + do { \ + char *dp = (char *)d; \ + char *bp = (char *)b; \ + int counter; \ + for(counter = 0; counter < n; counter++) { \ + *dp++ = *bp; \ + bp += 2; \ + } \ + }while(0); + +#define PACK_CORR_DATA(d,b,n) \ + memcpy(d,b,n); \ + d = (uint *)((unsigned long)d + n); + +#define MARK_CORR_DATA(d,n) \ + do { \ + uint* q = (uint*)((unsigned long)d - n); \ + while((unsigned long)q < (unsigned long)d) { \ + *q++ += 0x00330033; \ + } \ + }while(0); + +#define MARK_INTRA_BLOCK(d) \ + do { \ + int q; \ + for(q=0; q<16; q++) { \ + d[q] += 0x33333333; \ + } \ + }while(0); + +/* + Used for DCT 1 when we need DCT 0. Instead + of reading from one block we read from two and + interlace. +*/ +#define PACK_CORR_DATA_1to0(d,top,bottom) \ + do { \ + short *t = top,*b = bottom; \ + PACK_CORR_DATA(d,t,16); \ + t = (short *)((unsigned long)t + 16); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 16); \ + PACK_CORR_DATA(d,t,16); \ + t = (short *)((unsigned long)t + 16); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 16); \ + PACK_CORR_DATA(d,t,16); \ + t = (short *)((unsigned long)t + 16); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 16); \ + PACK_CORR_DATA(d,t,16); \ + t = (short *)((unsigned long)t + 16); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 16); \ + }while(0); + +/* Used for DCT 0 when we need DCT 1. */ +#define PACK_CORR_DATA_0to1(d,top,bottom) \ + do{ \ + short *t = top,*b = bottom; \ + PACK_CORR_DATA(d,t,16); \ + t = (short *)((unsigned long)t + 32); \ + PACK_CORR_DATA(d,t,16); \ + t = (short *)((unsigned long)t + 32); \ + PACK_CORR_DATA(d,t,16); \ + t = (short *)((unsigned long)t + 32); \ + PACK_CORR_DATA(d,t,16); \ + t = (short *)((unsigned long)t + 32); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 32); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 32); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 32); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 32); \ + }while(0); + +#define PACK_CORR_DATA_SHORT(d,block) \ + do { \ + short *b = block; \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 32); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 32); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 32); \ + PACK_CORR_DATA(d,b,16); \ + b = (short *)((unsigned long)b + 32); \ + }while(0); + +/* Lookup tables to speed common calculations */ +static unsigned int drps_table[] = {2<<6,3<<6}; + +static unsigned int mvfs_table[] = { + 0x12, + 0x1a, + 0x13, + 0x1b +}; + +static unsigned int type_table[] = { + 0x1<<12, /* This is an error so make it Forward motion */ + 0x1<<12, + 0x1<<12, + 0x1<<12, + 0x2<<12, + 0x2<<12, + 0x3<<12, + 0x3<<12, + 0x1<<12, /* Pattern but no Motion, Make motion Forward */ + 0x1<<12, + 0x1<<12, + 0x1<<12, + 0x2<<12, + 0x2<<12, + 0x3<<12, + 0x3<<12 +}; + +static unsigned int y_frame_bytes[] = { + 0,0,0,0,128,128,128,128, + 128,128,128,128,256,256,256,256, + 128,128,128,128,256,256,256,256, + 256,256,256,256,384,384,384,384, + 128,128,128,128,256,256,256,256, + 256,256,256,256,384,384,384,384, + 256,256,256,256,384,384,384,384, + 384,384,384,384,512,512,512,512 +}; + +static unsigned int u_frame_bytes[] = { + 0,0,128,128,0,0,128,128, + 0,0,128,128,0,0,128,128, + 0,0,128,128,0,0,128,128, + 0,0,128,128,0,0,128,128, + 0,0,128,128,0,0,128,128, + 0,0,128,128,0,0,128,128, + 0,0,128,128,0,0,128,128, + 0,0,128,128,0,0,128,128 +}; + +static unsigned int v_frame_bytes[] = { + 0,128,0,128,0,128,0,128, + 0,128,0,128,0,128,0,128, + 0,128,0,128,0,128,0,128, + 0,128,0,128,0,128,0,128, + 0,128,0,128,0,128,0,128, + 0,128,0,128,0,128,0,128, + 0,128,0,128,0,128,0,128, + 0,128,0,128,0,128,0,128 +}; + +static unsigned int y_first_field_bytes[] = { + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 128,128,128,128,128,128,128,128, + 128,128,128,128,128,128,128,128, + 128,128,128,128,128,128,128,128, + 128,128,128,128,128,128,128,128, + 256,256,256,256,256,256,256,256, + 256,256,256,256,256,256,256,256 +}; + +static unsigned int y_second_field_bytes[] = { + 0,0,0,0,128,128,128,128, + 128,128,128,128,256,256,256,256, + 0,0,0,0,128,128,128,128, + 128,128,128,128,256,256,256,256, + 0,0,0,0,128,128,128,128, + 128,128,128,128,256,256,256,256, + 0,0,0,0,128,128,128,128, + 128,128,128,128,256,256,256,256 +}; + +static unsigned int y_dct0_field_bytes[] = { + 0,0,0,0,128,128,128,128, + 128,128,128,128,256,256,256,256, + 128,128,128,128,128,128,128,128, + 256,256,256,256,256,256,256,256, + 128,128,128,128,256,256,256,256, + 128,128,128,128,256,256,256,256, + 256,256,256,256,256,256,256,256, + 256,256,256,256,256,256,256,256 +}; + +static unsigned int y_dct1_frame_bytes[] = { + 0,0,0,0,256,256,256,256, + 256,256,256,256,512,512,512,512, + 256,256,256,256,256,256,256,256, + 512,512,512,512,512,512,512,512, + 256,256,256,256,512,512,512,512, + 256,256,256,256,512,512,512,512, + 512,512,512,512,512,512,512,512, + 512,512,512,512,512,512,512,512 +}; + +static unsigned int u_field_bytes[] = { + 0,0,64,64,0,0,64,64, + 0,0,64,64,0,0,64,64, + 0,0,64,64,0,0,64,64, + 0,0,64,64,0,0,64,64, + 0,0,64,64,0,0,64,64, + 0,0,64,64,0,0,64,64, + 0,0,64,64,0,0,64,64, + 0,0,64,64,0,0,64,64 +}; + +static unsigned int v_field_bytes[] = { + 0,64,0,64,0,64,0,64, + 0,64,0,64,0,64,0,64, + 0,64,0,64,0,64,0,64, + 0,64,0,64,0,64,0,64, + 0,64,0,64,0,64,0,64, + 0,64,0,64,0,64,0,64, + 0,64,0,64,0,64,0,64, + 0,64,0,64,0,64,0,64 +}; + +static short empty_block[] = { + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0 +}; + + +/*************************************************************************** +// Function: dispatchYContext +// Description: Allocate a DMA buffer write the Y MC Context info in it, +// and dispatch it to hardware. +***************************************************************************/ + +static __inline__ void dispatchYContext(i810XvMCSurface *privTarget, + i810XvMCSurface *privPast, + i810XvMCSurface *privFuture, + i810XvMCContext *pI810XvMC) { + uint *data; + drmBufPtr pDMA; + drm_i810_mc_t mc; + + pDMA = i810_get_free_buffer(pI810XvMC); + data = pDMA->address; + *data++ = CMD_FLUSH; + *data++ = BOOLEAN_ENA_2; + *data++ = CMD_FLUSH; + *data++ = DEST_BUFFER_INFO; + *data++ = privTarget->dbi1y; + *data++ = DEST_BUFFER_VAR; + *data++ = privTarget->dbv1; + /* Past Surface */ + *data++ = CMD_MAP_INFO; + *data++ = privPast->mi1y; + *data++ = privPast->mi2y; + *data++ = privPast->mi3y; + /* Future Surface */ + *data++ = CMD_MAP_INFO; + *data++ = privFuture->mi1y | 0x1<<28; + *data++ = privFuture->mi2y; + *data++ = privFuture->mi3y; + + mc.idx = pDMA->idx; + mc.used = (unsigned long)data - (unsigned long)pDMA->address; + mc.last_render = ++pI810XvMC->last_render; + privTarget->last_render = pI810XvMC->last_render; + I810_MC(pI810XvMC,mc); +} + +static __inline__ void renderError(void) { + printf("Invalid Macroblock Parameters found.\n"); + return; +} + +/*************************************************************************** +// Function: renderIntrainFrame +// Description: inline function that sets hardware parameters for an Intra +// encoded macroblock in a Frame picture. +***************************************************************************/ +static __inline__ void renderIntrainFrame(uint **datay,uint **datau, + uint **datav, + XvMCMacroBlock *mb, + short *block_ptr) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Y Blocks */ + *dy++ = GFXBLOCK + 68; + *dy++ = (1<<30) | (3<<28) | (0xf<<24); + *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<4); + *dy++ = (16<<16) | 16; + *dy++ = 0; + *dy++ = 0; + PACK_INTRA_DATA(dy,block_ptr,256); + dy += 64; + block_ptr += 256; + /* End Y Blocks */ + + /* U Block */ + *du++ = GFXBLOCK + 20; + *du++ = (2<<30) | (1<<28) | (1<<23); + *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3); + *du++ = (8<<16) | 8; + *du++ = 0; + *du++ = 0; + PACK_INTRA_DATA(du,block_ptr,64); + du += 16; + block_ptr += 64; + + /* V Block */ + *dv++ = GFXBLOCK + 20; + *dv++ = (3<<30) | (1<<28) | (1<<22); + *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3); + *dv++ = (8<<16) | 8; + *dv++ = 0; + *dv++ = 0; + PACK_INTRA_DATA(dv,block_ptr,64); + dv += 16; + block_ptr += 64; + + *datay = dy; + *datau = du; + *datav = dv; +} + +/*************************************************************************** +// Function: renderIntrainFrameDCT1 +// Description: inline function that sets hardware parameters for an Intra +// encoded macroblock in a Frame picture with DCT type 1. +***************************************************************************/ +static __inline__ void renderIntrainFrameDCT1(uint **datay,uint **datau, + uint **datav,XvMCMacroBlock *mb, + short *block_ptr,uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + + /* Y Blocks */ + *dy++ = GFXBLOCK + 36; + *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x2<<6); + *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3); + *dy++ = (8<<16) | 16; + *dy++ = 0; + *dy++ = 0; + PACK_INTRA_DATA(dy,block_ptr,128); + dy += 32; + block_ptr += 128; + + /* Second Y block */ + *dy++ = GFXBLOCK + 36; + *dy++ = (1<<30) | (2<<28) | (0x3<<26) | (0x3<<6); + *dy++ = ((uint)mb->x<<20) | ((uint)mb->y<<3); + *dy++ = (8<<16) | 16; + *dy++ = 0; + *dy++ = 0; + PACK_INTRA_DATA(dy,block_ptr,128); + dy += 32; + block_ptr += 128; + /* End Y Blocks */ + + + /* U Block */ + *du++ = GFXBLOCK + 20; + *du++ = (2<<30) | (1<<28) | (1<<23); + *du++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3); + *du++ = (8<<16) | 8; + *du++ = 0; + *du++ = 0; + PACK_INTRA_DATA(du,block_ptr,64); + du += 16; + block_ptr += 64; + + /* V Block */ + *dv++ = GFXBLOCK + 20; + *dv++ = (3<<30) | (1<<28) | (1<<22); + *dv++ = (((uint)mb->x)<<19) | (((uint)mb->y)<<3); + *dv++ = (8<<16) | 8; + *dv++ = 0; + *dv++ = 0; + PACK_INTRA_DATA(dv,block_ptr,64); + dv += 16; + block_ptr += 64; + + *datay = dy; + *datau = du; + *datav = dv; +} + + +/*************************************************************************** +// Function: renderIntrainField +// Description: inline function that sets hardware parameters for an Intra +// encoded macroblock in Field pictures. +***************************************************************************/ +static __inline__ void renderIntrainField(uint **datay,uint **datau, + uint **datav, + XvMCMacroBlock *mb,short *block_ptr, + uint ps) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); + uint dw1 = drps_table[~ps & 0x1]; + + /* Y Blocks */ + *dy++ = GFXBLOCK + 68; + *dy++ = (1<<30) | (3<<28) | (0xf<<24) | dw1; + *dy++ = xy; + *dy++ = (16<<16) | 16; + *dy++ = 0; + *dy++ = 0; + PACK_INTRA_DATA(dy,block_ptr,256); + dy += 64; + block_ptr += 256; + /* End Y Blocks */ + + xy >>= 1; + + /* U Block */ + *du++ = GFXBLOCK + 20; + *du++ = (2<<30) | (1<<28) | (1<<23) | dw1; + *du++ = xy; + *du++ = (8<<16) | 8; + *du++ = 0; + *du++ = 0; + PACK_INTRA_DATA(du,block_ptr,64); + du += 16; + block_ptr += 64; + + /* V Block */ + *dv++ = GFXBLOCK + 20; + *dv++ = (3<<30) | (1<<28) | (1<<22) | dw1; + *dv++ = xy; + *dv++ = (8<<16) | 8; + *dv++ = 0; + *dv++ = 0; + PACK_INTRA_DATA(dv,block_ptr,64); + dv += 16; + block_ptr += 64; + + *datay = dy; + *datau = du; + *datav = dv; +} + + +/*************************************************************************** +// Function: renderFieldinField +// Description: inline function that sets hardware parameters for a Field +// encoded macroblock in a Field Picture. +***************************************************************************/ +static __inline__ void renderFieldinField(uint **datay,uint **datau, + uint **datav, + XvMCMacroBlock *mb,short *block_ptr, + uint ps, uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Motion Vectors */ + short fmv[2]; + short bmv[2]; + /* gfxblock dword 1 */ + uint dw1; + + uint parity = ~ps & XVMC_TOP_FIELD; + + uint ysize = y_frame_bytes[mb->coded_block_pattern]; + uint usize = u_frame_bytes[mb->coded_block_pattern]; + uint vsize = v_frame_bytes[mb->coded_block_pattern]; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); + + /* i810 Specific flag used to identify the second field in a P frame */ + if(flags & 0x80000000) { + /* P Frame */ + if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) == + parity) { + /* Same parity, use reference field (map0) */ + dw1 = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) | + (((uint)mb->coded_block_pattern)<<22); + fmv[0] = mb->PMV[0][0][1]; + fmv[1] = mb->PMV[0][0][0]; + bmv[0] = 0; + bmv[1] = 0; + } + else { + /* + Opposite parity, set up as if it were backward + motion and use map1. + */ + dw1 = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) | + (((uint)mb->coded_block_pattern)<<22); + bmv[0] = mb->PMV[0][0][1]; + bmv[1] = mb->PMV[0][0][0]; + fmv[0] = 0; + fmv[1] = 0; + } + } + else { + dw1 = type_table[mb->macroblock_type & 0xf] | + drps_table[~ps & 0x1] | + mvfs_table[mb->motion_vertical_field_select & 3] | + (((uint)mb->coded_block_pattern)<<22); + + fmv[0] = mb->PMV[0][0][1]; + fmv[1] = mb->PMV[0][0][0]; + + bmv[0] = mb->PMV[0][1][1]; + bmv[1] = mb->PMV[0][1][0]; + } + + /* Y Block */ + *dy++ = GFXBLOCK + 4 + (ysize>>2); + *dy++ = (1<<30) | (3<<28) | dw1; + *dy++ = xy; + *dy++ = (16<<16) | 16; + *dy++ = *(uint *)fmv; + *dy++ = *(uint *)bmv; + PACK_CORR_DATA(dy,block_ptr,ysize); + block_ptr = (short *)((unsigned long)block_ptr + ysize); + /* End Y Blocks */ + + fmv[0] /= 2; + fmv[1] /= 2; + bmv[0] /= 2; + bmv[1] /= 2; + xy >>= 1; + + /* U Block */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1; + *du++ = xy; + *du++ = (8<<16) | 8; + *du++ = *(uint *)fmv; + *du++ = *(uint *)bmv; + PACK_CORR_DATA(du,block_ptr,usize); + block_ptr = (short *)((unsigned long)block_ptr + usize); + + /* V Block */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1; + *dv++ = xy; + *dv++ = (8<<16) | 8; + *dv++ = *(uint *)fmv; + *dv++ = *(uint *)bmv; + PACK_CORR_DATA(dv,block_ptr,vsize); + block_ptr = (short *)((unsigned long)block_ptr + vsize); + + *datay = dy; + *datau = du; + *datav = dv; +} + +/*************************************************************************** +// Function: render16x8inField +// Description: inline function that sets hardware parameters for a 16x8 +// encoded macroblock in a field picture. +***************************************************************************/ +static __inline__ void render16x8inField(uint **datay,uint **datau, + uint **datav, + XvMCMacroBlock *mb,short *block_ptr, + uint ps, uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Motion Vectors */ + short fmv[4]; + short bmv[4]; + /* gfxblock dword 1 */ + uint dw1[2]; + + uint y1size = y_first_field_bytes[mb->coded_block_pattern]; + uint y2size = y_second_field_bytes[mb->coded_block_pattern]; + uint usize = u_field_bytes[mb->coded_block_pattern]; + uint vsize = v_field_bytes[mb->coded_block_pattern]; + + uint parity = ~ps & XVMC_TOP_FIELD; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); + + /* i810 Specific flag used to identify the second field in a P frame */ + if(flags & 0x80000000) { + /* P Frame */ + if((mb->motion_vertical_field_select & XVMC_SELECT_FIRST_FORWARD) == + parity) { + /* Same parity, use reference field (map0) */ + dw1[0] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) | + (((uint)mb->coded_block_pattern)<<22); + + fmv[0] = mb->PMV[0][0][1]; + fmv[1] = mb->PMV[0][0][0]; + bmv[0] = 0; + bmv[1] = 0; + } + else { + /* + Opposite parity, set up as if it were backward + motion and use map1. + */ + dw1[0] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) | + (((uint)mb->coded_block_pattern)<<22); + + bmv[0] = mb->PMV[0][0][1]; + bmv[1] = mb->PMV[0][0][0]; + fmv[0] = 0; + fmv[1] = 0; + } + if((mb->motion_vertical_field_select & XVMC_SELECT_SECOND_FORWARD) == + (parity<<2)) { + /* Same parity, use reference field (map0) */ + dw1[1] = 1<<12 | ((0x2 + parity)<<6) | ((0x2 + parity)<<3) | + ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) | + (((uint)mb->coded_block_pattern<<24) & (0x3<<26))); + + fmv[2] = mb->PMV[1][0][1]; + fmv[3] = mb->PMV[1][0][0]; + bmv[2] = 0; + bmv[3] = 0; + } + else { + /* + Opposite parity, set up as if it were backward + motion and use map1. + */ + dw1[1] = 2<<12 | ((0x2 + parity)<<6) | (0x3 - parity) | + ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) | + (((uint)mb->coded_block_pattern<<24) & (0x3<<26))); + + bmv[2] = mb->PMV[1][0][1]; + bmv[3] = mb->PMV[1][0][0]; + fmv[2] = 0; + fmv[3] = 0; + } + } + else { + dw1[0] = type_table[mb->macroblock_type & 0xf] | + drps_table[~ps & 0x1] | + mvfs_table[mb->motion_vertical_field_select & 3] | + (((uint)mb->coded_block_pattern)<<22); + + dw1[1] = type_table[mb->macroblock_type & 0xf] | + drps_table[~ps & 0x1] | + mvfs_table[(mb->motion_vertical_field_select>>2) & 0x3] | + ((((uint)mb->coded_block_pattern<<22) & (0x3<<22)) | + (((uint)mb->coded_block_pattern<<24) & (0x3<<26))); + + fmv[0] = mb->PMV[0][0][1]; + fmv[1] = mb->PMV[0][0][0]; + fmv[2] = mb->PMV[1][0][1]; + fmv[3] = mb->PMV[1][0][0]; + + bmv[0] = mb->PMV[0][1][1]; + bmv[1] = mb->PMV[0][1][0]; + bmv[2] = mb->PMV[1][1][1]; + bmv[3] = mb->PMV[1][1][0]; + } + + /* First Y Block */ + *dy++ = GFXBLOCK + 4 + (y1size>>2); + *dy++ = (1<<30) | (2<<28) | dw1[0]; + *dy++ = xy; + *dy++ = (8<<16) | 16; + *dy++ = *(uint *)fmv; + *dy++ = *(uint *)bmv; + PACK_CORR_DATA(dy,block_ptr,y1size); + block_ptr = (short *)((unsigned long)block_ptr + y1size); + + /* Second Y Block */ + *dy++ = GFXBLOCK + 4 + (y2size>>2); + *dy++ = (1<<30) | (2<<28) | dw1[1]; + *dy++ = (xy + 8); + *dy++ = (8<<16) | 16; + *dy++ = *(uint *)&fmv[2]; + *dy++ = *(uint *)&bmv[2]; + PACK_CORR_DATA(dy,block_ptr,y2size); + block_ptr = (short *)((unsigned long)block_ptr + y2size); + /* End Y Blocks */ + + fmv[0] /= 2; + fmv[1] /= 2; + fmv[2] /= 2; + fmv[3] /= 2; + + bmv[0] /= 2; + bmv[1] /= 2; + bmv[2] /= 2; + bmv[3] /= 2; + + xy >>= 1; + + /* U Blocks */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[0]; + *du++ = xy; + *du++ = (4<<16) | 8; + *du++ = *(uint *)fmv; + *du++ = *(uint *)bmv; + PACK_CORR_DATA(du,block_ptr,usize); + block_ptr = (short *)((unsigned long)block_ptr + usize); + + /* Second U block */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[1]; + *du++ = (xy + 4); + *du++ = (4<<16) | 8; + *du++ = *(uint *)&fmv[2]; + *du++ = *(uint *)&bmv[2]; + PACK_CORR_DATA(du,block_ptr,usize); + block_ptr = (short *)((unsigned long)block_ptr + usize); + /* End U Blocks */ + + /* V Blocks */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[0]; + *dv++ = xy; + *dv++ = (4<<16) | 8; + *dv++ = *(uint *)fmv; + *dv++ = *(uint *)bmv; + PACK_CORR_DATA(dv,block_ptr,vsize); + block_ptr = (short *)((unsigned long)block_ptr + vsize); + + /* Second V Block */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[1]; + *dv++ = (xy + 4); + *dv++ = (4<<16) | 8; + *dv++ = *(uint *)&fmv[2]; + *dv++ = *(uint *)&bmv[2]; + PACK_CORR_DATA(dv,block_ptr,vsize); + block_ptr = (short *)((unsigned long)block_ptr + vsize); + /* End V Blocks */ + + *datay = dy; + *datau = du; + *datav = dv; +} + +/*************************************************************************** +// Function: renderDualPrimeinField +// Description: inline function that sets hardware parameters for a Dual +// prime encoded macroblock in a field picture. +***************************************************************************/ +static __inline__ void renderDualPrimeinField(uint **datay,uint **datau, + uint **datav,XvMCMacroBlock *mb, + short *block_ptr,uint ps, + uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Motion Vectors */ + short fmv[2]; + short bmv[2]; + /* gfxblock dword 1 */ + uint dw1; + + + uint ysize = y_frame_bytes[mb->coded_block_pattern]; + uint usize = u_frame_bytes[mb->coded_block_pattern]; + uint vsize = v_frame_bytes[mb->coded_block_pattern]; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); + + + if(ps & XVMC_TOP_FIELD) { + dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 2<<6 | 2<<3 | 3; + } + else { + dw1 = (mb->coded_block_pattern<<22) | 3<<12 | 3<<6 | 3<<3 | 2; + } + fmv[0] = mb->PMV[0][0][1]; + fmv[1] = mb->PMV[0][0][0]; + bmv[0] = mb->PMV[0][1][1]; + bmv[1] = mb->PMV[0][1][0]; + + /* Y Block */ + *dy++ = GFXBLOCK + 4 + (ysize>>2); + *dy++ = (1<<30) | (3<<28) | dw1; + *dy++ = xy; + *dy++ = (16<<16) | 16; + *dy++ = *(uint *)fmv; + *dy++ = *(uint *)bmv; + PACK_CORR_DATA(dy,block_ptr,ysize); + block_ptr = (short *)((unsigned long)block_ptr + ysize); + /* End Y Blocks */ + + fmv[0] /= 2; + fmv[1] /= 2; + bmv[0] /= 2; + bmv[1] /= 2; + xy >>= 1; + + /* U Block */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1; + *du++ = xy; + *du++ = (8<<16) | 8; + *du++ = *(uint *)fmv; + *du++ = *(uint *)bmv; + PACK_CORR_DATA(du,block_ptr,usize); + block_ptr = (short *)((unsigned long)block_ptr + usize); + + /* V Block */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1; + *dv++ = xy; + *dv++ = (8<<16) | 8; + *dv++ = *(uint *)fmv; + *dv++ = *(uint *)bmv; + PACK_CORR_DATA(dv,block_ptr,vsize); + block_ptr = (short *)((unsigned long)block_ptr + vsize); + + *datay = dy; + *datau = du; + *datav = dv; +} + +/*************************************************************************** +// Function: renderFieldinFrame +// Description: inline function that sets hardware parameters for a Field +// encoded macroblock in a frame picture. +***************************************************************************/ +typedef union { + short s[4]; + uint u[2]; +} su_t; + +static __inline__ void renderFieldinFrame(uint **datay,uint **datau, + uint **datav, + XvMCMacroBlock *mb,short *block_ptr, + uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Motion Vectors */ + su_t fmv; + su_t bmv; + /* gfxblock dword 1 */ + uint dw1[2]; + + uint y1size = y_first_field_bytes[mb->coded_block_pattern]; + uint y2size = y_second_field_bytes[mb->coded_block_pattern]; + uint usize = u_field_bytes[mb->coded_block_pattern]; + uint vsize = v_field_bytes[mb->coded_block_pattern]; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3); + + dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) | + mvfs_table[mb->motion_vertical_field_select & 3] | + (((uint)mb->coded_block_pattern)<<22); + + dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) | + mvfs_table[mb->motion_vertical_field_select>>2] | + (((mb->coded_block_pattern & 0x3) | + ((mb->coded_block_pattern & 0xc)<<2))<<22); + + fmv.s[0] = mb->PMV[0][0][1]/2; + fmv.s[1] = mb->PMV[0][0][0]; + fmv.s[2] = mb->PMV[1][0][1]/2; + fmv.s[3] = mb->PMV[1][0][0]; + + bmv.s[0] = mb->PMV[0][1][1]/2; + bmv.s[1] = mb->PMV[0][1][0]; + bmv.s[2] = mb->PMV[1][1][1]/2; + bmv.s[3] = mb->PMV[1][1][0]; + + /* First Y Block */ + *dy++ = GFXBLOCK + 4 + (y1size>>2); + *dy++ = (1<<30) | (2<<28) | dw1[0]; + *dy++ = xy; + *dy++ = (8<<16) | 16; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; + PACK_CORR_DATA(dy,block_ptr,y1size); + block_ptr = (short *)((unsigned long)block_ptr + y1size); + + /* Second Y Block */ + *dy++ = GFXBLOCK + 4 + (y2size>>2); + *dy++ = (1<<30) | (2<<28) | dw1[1]; + *dy++ = xy; + *dy++ = (8<<16) | 16; + *dy++ = fmv.u[1]; + *dy++ = bmv.u[1]; + PACK_CORR_DATA(dy,block_ptr,y2size); + block_ptr = (short *)((unsigned long)block_ptr + y2size); + /* End Y Blocks */ + + fmv.s[0] /= 2; + fmv.s[1] /= 2; + fmv.s[2] /= 2; + fmv.s[3] /= 2; + + bmv.s[0] /= 2; + bmv.s[1] /= 2; + bmv.s[2] /= 2; + bmv.s[3] /= 2; + + xy >>= 1; + + /* U Blocks */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[0]; + *du++ = xy; + *du++ = (4<<16) | 8; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; + if(usize) { + PACK_CORR_DATA_SHORT(du,block_ptr); + } + + /* Second U Block */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[1]; + *du++ = xy; + *du++ = (4<<16) | 8; + *du++ = fmv.u[1]; + *du++ = bmv.u[1]; + if(usize) { + block_ptr = (short *)((unsigned long)block_ptr + 16); + PACK_CORR_DATA_SHORT(du,block_ptr); + block_ptr = (short *)((unsigned long)block_ptr + 112); + } + /* End U Blocks */ + + /* V Blocks */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[0]; + *dv++ = xy; + *dv++ = (4<<16) | 8; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; + if(vsize) { + PACK_CORR_DATA_SHORT(dv,block_ptr); + } + + /* Second V Block */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[1]; + *dv++ = xy; + *dv++ = (4<<16) | 8; + *dv++ = fmv.u[1]; + *dv++ = bmv.u[1]; + if(vsize) { + block_ptr = (short *)((unsigned long)block_ptr + 16); + PACK_CORR_DATA_SHORT(dv,block_ptr); + block_ptr = (short *)((unsigned long)block_ptr + 112); + } + /* End V Blocks */ + + *datay = dy; + *datau = du; + *datav = dv; +} + +/*************************************************************************** +// Function: renderFieldinFrameDCT0 +// Description: inline function that sets hardware parameters for a Field +// encoded macroblock in a frame picture with DCT0. +***************************************************************************/ +static __inline__ void renderFieldinFrameDCT0(uint **datay,uint **datau, + uint **datav,XvMCMacroBlock *mb, + short *block_ptr,uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Motion Vectors */ + su_t fmv; + su_t bmv; + /* CBP */ + uint cbp = (uint)mb->coded_block_pattern; + /* gfxblock dword 1 */ + uint dw1[2]; + + short * top_left_b = NULL; + short * top_right_b = NULL; + short * bottom_left_b = NULL; + short * bottom_right_b = NULL; + + unsigned int ysize = y_dct0_field_bytes[cbp]; + unsigned int usize = u_field_bytes[cbp]; + unsigned int vsize = v_field_bytes[cbp]; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3); + + dw1[0] = type_table[mb->macroblock_type & 0xf] | (0x2<<6) | + mvfs_table[mb->motion_vertical_field_select & 3] | + ((cbp | ((cbp<<2) & 0x30))<<22); + + dw1[1] = type_table[mb->macroblock_type & 0xf] | (0x3<<6) | + mvfs_table[mb->motion_vertical_field_select>>2] | + ((cbp | ((cbp<<2) & 0x30))<<22); + + + fmv.s[0] = mb->PMV[0][0][1]/2; + fmv.s[1] = mb->PMV[0][0][0]; + fmv.s[2] = mb->PMV[1][0][1]/2; + fmv.s[3] = mb->PMV[1][0][0]; + + bmv.s[0] = mb->PMV[0][1][1]/2; + bmv.s[1] = mb->PMV[0][1][0]; + bmv.s[2] = mb->PMV[1][1][1]/2; + bmv.s[3] = mb->PMV[1][1][0]; + + /* + The i810 cannot use DCT0 directly with field motion, we have to + interlace the data for it. We use a zero block when the CBP has + one half of the to-be-interlaced data but not the other half. + */ + top_left_b = &empty_block[0]; + if(cbp & 0x20) { + top_left_b = block_ptr; + block_ptr += 64; + } + + top_right_b = &empty_block[0]; + if(cbp & 0x10) { + top_right_b = block_ptr; + block_ptr += 64; + } + + bottom_left_b = &empty_block[0]; + if(cbp & 0x8) { + bottom_left_b = block_ptr; + block_ptr += 64; + } + + bottom_right_b = &empty_block[0]; + if(cbp & 0x4) { + bottom_right_b = block_ptr; + block_ptr += 64; + } + + /* First Y Block */ + *dy++ = GFXBLOCK + 4 + (ysize>>2); + *dy++ = (1<<30) | (2<<28) | dw1[0]; + *dy++ = xy; + *dy++ = (8<<16) | 16; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; + if(dw1[0] & (1<<27)) { + PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); + } + if(dw1[0] & (1<<26)) { + PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b); + } + + /* Second Y Block */ + *dy++ = GFXBLOCK + 4 + (ysize>>2); + *dy++ = (1<<30) | (2<<28) | dw1[1]; + *dy++ = xy; + *dy++ = (8<<16) | 16; + *dy++ = fmv.u[1]; + *dy++ = bmv.u[1]; + if(dw1[1] & (1<<27)) { + top_left_b = (short *)((unsigned long)top_left_b + 16); + bottom_left_b = (short *)((unsigned long)bottom_left_b + 16); + PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); + } + if(dw1[1] & (1<<26)) { + top_right_b = (short *)((unsigned long)top_right_b + 16); + bottom_right_b = (short *)((unsigned long)bottom_right_b + 16); + PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b); + } + /* End Y Blocks */ + + fmv.s[0] /= 2; + fmv.s[1] /= 2; + fmv.s[2] /= 2; + fmv.s[3] /= 2; + + bmv.s[0] /= 2; + bmv.s[1] /= 2; + bmv.s[2] /= 2; + bmv.s[3] /= 2; + + xy >>= 1; + + /* U Blocks */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[0]; + *du++ = xy; + *du++ = (4<<16) | 8; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; + if(usize) { + PACK_CORR_DATA_SHORT(du,block_ptr); + } + + /* Second U Block */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[1]; + *du++ = xy; + *du++ = (4<<16) | 8; + *du++ = fmv.u[1]; + *du++ = bmv.u[1]; + if(usize) { + block_ptr = (short *)((unsigned long)block_ptr + 16); + PACK_CORR_DATA_SHORT(du,block_ptr); + block_ptr = (short *)((unsigned long)block_ptr + 112); + } + /* End U Blocks */ + + /* V Blocks */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[0]; + *dv++ = xy; + *dv++ = (4<<16) | 8; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; + if(vsize) { + PACK_CORR_DATA_SHORT(dv,block_ptr); + } + + /* Second V Block */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[1]; + *dv++ = xy; + *dv++ = (4<<16) | 8; + *dv++ = fmv.u[1]; + *dv++ = bmv.u[1]; + if(vsize) { + block_ptr = (short *)((unsigned long)block_ptr + 16); + PACK_CORR_DATA_SHORT(dv,block_ptr); + block_ptr = (short *)((unsigned long)block_ptr + 112); + } + /* End V Blocks */ + + *datay = dy; + *datau = du; + *datav = dv; +} + +/*************************************************************************** +// Function: renderFrameinFrame +// Description: inline function that sets hardware parameters for a Frame +// encoded macroblock in a frame picture. +***************************************************************************/ +static __inline__ void renderFrameinFrame(uint **datay,uint **datau, + uint **datav, + XvMCMacroBlock *mb,short *block_ptr, + uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Motion Vectors */ + su_t fmv; + su_t bmv; + /* gfxblock dword 1 */ + uint dw1; + + unsigned int ysize = y_frame_bytes[mb->coded_block_pattern]; + unsigned int usize = u_frame_bytes[mb->coded_block_pattern]; + unsigned int vsize = v_frame_bytes[mb->coded_block_pattern]; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); + + dw1 = type_table[mb->macroblock_type & 0xf] | + (((uint)mb->coded_block_pattern)<<22); + + + fmv.s[0] = mb->PMV[0][0][1]; + fmv.s[1] = mb->PMV[0][0][0]; + + bmv.s[0] = mb->PMV[0][1][1]; + bmv.s[1] = mb->PMV[0][1][0]; + + /* Y Block */ + *dy++ = GFXBLOCK + 4 + (ysize>>2); + *dy++ = (1<<30) | (3<<28) | dw1; + *dy++ = xy; + *dy++ = (16<<16) | 16; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; + PACK_CORR_DATA(dy,block_ptr,ysize); + block_ptr = (short *)((unsigned long)block_ptr + ysize); + /* End Y Blocks */ + + fmv.s[0] /= 2; + fmv.s[1] /= 2; + + bmv.s[0] /= 2; + bmv.s[1] /= 2; + + xy >>= 1; + + /* U Block */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1; + *du++ = xy; + *du++ = (8<<16) | 8; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; + PACK_CORR_DATA(du,block_ptr,usize); + block_ptr = (short *)((unsigned long)block_ptr + usize); + /* End U Block */ + + /* V Block */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1; + *dv++ = xy; + *dv++ = (8<<16) | 8; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; + PACK_CORR_DATA(dv,block_ptr,vsize); + block_ptr = (short *)((unsigned long)block_ptr + vsize); + /* End V Block */ + + *datay = dy; + *datau = du; + *datav = dv; +} + +/*************************************************************************** +// Function: renderFrameinFrameDCT1 +// Description: inline function that sets hardware parameters for a Frame +// encoded macroblock in a frame picture with DCT type 1. +***************************************************************************/ +static __inline__ void renderFrameinFrameDCT1(uint **datay,uint **datau, + uint **datav,XvMCMacroBlock *mb, + short *block_ptr,uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Motion Vectors */ + su_t fmv; + su_t bmv; + + short * top_left_b = NULL; + short * top_right_b = NULL; + short * bottom_left_b = NULL; + short * bottom_right_b = NULL; + + uint temp_bp = 0; + + uint ysize = y_dct1_frame_bytes[mb->coded_block_pattern]; + uint usize = u_frame_bytes[mb->coded_block_pattern]; + uint vsize = v_frame_bytes[mb->coded_block_pattern]; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<4); + + uint dw1 = type_table[mb->macroblock_type & 0xf] | + (((uint)mb->coded_block_pattern)<<22); + + fmv.s[0] = mb->PMV[0][0][1]; + fmv.s[1] = mb->PMV[0][0][0]; + + bmv.s[0] = mb->PMV[0][1][1]; + bmv.s[1] = mb->PMV[0][1][0]; + + /* + It is easiest to find out what blocks are in need of reading first + rather than as we go. + */ + top_left_b = &empty_block[0]; + if(dw1 & (1<<27)) { + temp_bp |= (1<<25); + top_left_b = block_ptr; + block_ptr += 64; + } + + top_right_b = &empty_block[0]; + if(dw1 & (1<<26)) { + temp_bp |= (1<<24); + top_right_b = block_ptr; + block_ptr += 64; + } + + bottom_left_b = &empty_block[0]; + if(dw1 & (1<<25)) { + temp_bp |= (1<<27); + bottom_left_b = block_ptr; + block_ptr += 64; + } + + bottom_right_b = &empty_block[0]; + if(dw1 & (1<<24)) { + temp_bp |= (1<<26); + bottom_right_b = block_ptr; + block_ptr += 64; + } + dw1 |= temp_bp; + + /* Y Block */ + *dy++ = GFXBLOCK + 4 + (ysize>>2); + *dy++ = (1<<30) | (3<<28) | dw1; + *dy++ = xy; + *dy++ = (16<<16) | 16; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; + if(dw1 & (1<<27)) { + PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b); + top_left_b = (short *)((unsigned long)top_left_b + 64); + bottom_left_b = (short *)((unsigned long)bottom_left_b + 64); + } + if(dw1 & (1<<26)) { + PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b); + top_right_b = (short *)((unsigned long)top_right_b + 64); + bottom_right_b = (short *)((unsigned long)bottom_right_b + 64); + } + if(dw1 & (1<<27)) { + PACK_CORR_DATA_1to0(dy,top_left_b,bottom_left_b); + } + if(dw1 & (1<<26)) { + PACK_CORR_DATA_1to0(dy,top_right_b,bottom_right_b); + } + /* End Y Block */ + + fmv.s[0] /= 2; + fmv.s[1] /= 2; + + bmv.s[0] /= 2; + bmv.s[1] /= 2; + + xy >>= 1; + + /* U Block */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1; + *du++ = xy; + *du++ = (8<<16) | 8; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; + PACK_CORR_DATA(du,block_ptr,usize); + block_ptr = (short *)((unsigned long)block_ptr + usize); + + /* V Block */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1; + *dv++ = xy; + *dv++ = (8<<16) | 8; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; + PACK_CORR_DATA(dv,block_ptr,vsize); + block_ptr = (short *)((unsigned long)block_ptr + vsize); + + *datay = dy; + *datau = du; + *datav = dv; +} + +/*************************************************************************** +// Function: renderDualPrimeinFrame +// Description: inline function that sets hardware parameters for a Dual +// Prime encoded macroblock in a frame picture with dct 1. +***************************************************************************/ +static __inline__ void renderDualPrimeinFrame(uint **datay,uint **datau, + uint **datav,XvMCMacroBlock *mb, + short *block_ptr,uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Motion Vectors */ + su_t fmv; + su_t bmv; + /* gfxblock dword 1 */ + uint dw1[2]; + + uint y1size = y_first_field_bytes[mb->coded_block_pattern]; + uint y2size = y_second_field_bytes[mb->coded_block_pattern]; + uint usize = u_field_bytes[mb->coded_block_pattern]; + uint vsize = v_field_bytes[mb->coded_block_pattern]; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3); + + /* + Past Surface (map 0) is used for same parity prediction, + Future surface (map 1) is used for opposite. + */ + dw1[0] = (((uint)mb->coded_block_pattern)<<22) | + 3<<12 | 2<<6 | 2<<3 | 3; + dw1[1] = (((mb->coded_block_pattern & 0x3) | + ((mb->coded_block_pattern & 0xc)<<2))<<22) | + 3<<12 | 3<<6 | 3<<3 | 2; + + fmv.s[0] = mb->PMV[0][0][1]; + fmv.s[1] = mb->PMV[0][0][0]; + bmv.s[0] = mb->PMV[1][0][1]; + bmv.s[1] = mb->PMV[1][0][0]; + + fmv.s[2] = mb->PMV[0][0][1]; + fmv.s[3] = mb->PMV[0][0][0]; + bmv.s[2] = mb->PMV[1][1][1]; + bmv.s[3] = mb->PMV[1][1][0]; + + /* First Y Block */ + *dy++ = GFXBLOCK + 4 + (y1size>>2); + *dy++ = (1<<30) | (2<<28) | dw1[0]; + *dy++ = xy; + *dy++ = (8<<16) | 16; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0];; + PACK_CORR_DATA(dy,block_ptr,y1size); + block_ptr = (short *)((unsigned long)block_ptr + y1size); + + /* Second Y Block */ + *dy++ = GFXBLOCK + 4 + (y2size>>2); + *dy++ = (1<<30) | (2<<28) | dw1[1]; + *dy++ = xy; + *dy++ = (8<<16) | 16; + *dy++ = fmv.u[1]; + *dy++ = bmv.u[1]; + PACK_CORR_DATA(dy,block_ptr,y2size); + block_ptr = (short *)((unsigned long)block_ptr + y2size); + + fmv.s[0] /= 2; + fmv.s[1] /= 2; + bmv.s[0] /= 2; + bmv.s[1] /= 2; + + fmv.s[2] /= 2; + fmv.s[3] /= 2; + bmv.s[2] /= 2; + bmv.s[3] /= 2; + + xy >>= 1; + + /* U Blocks */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[0]; + *du++ = xy; + *du++ = (4<<16) | 8; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; + if(dw1[0] & (1<<23)) { + PACK_CORR_DATA_SHORT(du,block_ptr); + } + + /* Second U Block */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[1]; + *du++ = xy; + *du++ = (4<<16) | 8; + *du++ = fmv.u[1]; + *du++ = bmv.u[1]; + if(dw1[1] & (1<<23)) { + block_ptr = (short *)((unsigned long)block_ptr + 16); + PACK_CORR_DATA_SHORT(du,block_ptr); + block_ptr = (short *)((unsigned long)block_ptr + 112); + } + /* End U Blocks */ + + /* V Blocks */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[0]; + *dv++ = xy; + *dv++ = (4<<16) | 8; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; + if(dw1[0] & (1<<22)) { + PACK_CORR_DATA_SHORT(dv,block_ptr); + } + + /* Second V Block */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[1]; + *dv++ = xy; + *dv++ = (4<<16) | 8; + *dv++ = fmv.u[1]; + *dv++ = bmv.u[1]; + if(dw1[1] & (1<<22)) { + block_ptr = (short *)((unsigned long)block_ptr + 16); + PACK_CORR_DATA_SHORT(dv,block_ptr); + block_ptr = (short *)((unsigned long)block_ptr + 112); + } + /* End V Blocks */ + + *datay = dy; + *datau = du; + *datav = dv; +} + +/*************************************************************************** +// Function: renderDualPrimeinFrameDCT0 +// Description: inline function that sets hardware parameters for a Dual +// Prime encoded macroblock in a frame picture with dct 0. +***************************************************************************/ +static __inline__ void renderDualPrimeinFrameDCT0(uint **datay,uint **datau, + uint **datav, + XvMCMacroBlock *mb, + short *block_ptr, + uint flags) { + + register uint *dy = *datay; + register uint *du = *datau; + register uint *dv = *datav; + + /* Motion Vectors */ + su_t fmv; + su_t bmv; + /* gfxblock dword 1 */ + uint dw1[2]; + + short * top_left_b = NULL; + short * top_right_b = NULL; + short * bottom_left_b = NULL; + short * bottom_right_b = NULL; + + uint cbp = (uint)mb->coded_block_pattern; + + uint ysize = y_dct0_field_bytes[cbp]; + uint usize = u_field_bytes[cbp]; + uint vsize = v_field_bytes[cbp]; + + uint xy = ((uint)mb->x<<20) | ((uint)mb->y<<3); + + /* + Past Surface (map 0) is used for same parity prediction, + Future surface (map 1) is used for opposite. + */ + dw1[0] = ((cbp | ((cbp<<2) & 0x30))<<22) | + 3<<12 | 2<<6 | 2<<3 | 3; + dw1[1] = ((cbp | ((cbp<<2) & 0x30))<<22) | + 3<<12 | 3<<6 | 3<<3 | 2; + + fmv.s[0] = mb->PMV[0][0][1]; + fmv.s[1] = mb->PMV[0][0][0]; + bmv.s[0] = mb->PMV[1][0][1]; + bmv.s[1] = mb->PMV[1][0][0]; + + fmv.s[2] = mb->PMV[0][0][1]; + fmv.s[3] = mb->PMV[0][0][0]; + bmv.s[2] = mb->PMV[1][1][1]; + bmv.s[3] = mb->PMV[1][1][0]; + + /* + The i810 cannot use DCT0 directly with field motion, we have to + interlace the data for it. We use a zero block when the CBP has + one half of the to-be-interlaced data but not the other half. + */ + top_left_b = &empty_block[0]; + if(cbp & 0x20) { + top_left_b = block_ptr; + block_ptr += 64; + } + + top_right_b = &empty_block[0]; + if(cbp & 0x10) { + top_right_b = block_ptr; + block_ptr += 64; + } + + bottom_left_b = &empty_block[0]; + if(cbp & 0x8) { + bottom_left_b = block_ptr; + block_ptr += 64; + } + + bottom_right_b = &empty_block[0]; + if(cbp & 0x4) { + bottom_right_b = block_ptr; + block_ptr += 64; + } + + /* First Y Block */ + *dy++ = GFXBLOCK + 4 + (ysize>>2); + *dy++ = (1<<30) | (2<<28) | dw1[0]; + *dy++ = xy; + *dy++ = (8<<16) | 16; + *dy++ = fmv.u[0]; + *dy++ = bmv.u[0]; + if(cbp & 0x20) { + PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); + } + if(cbp & 0x10) { + PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b); + } + + /* Second Y Block */ + *dy++ = GFXBLOCK + 4 + (ysize>>2); + *dy++ = (1<<30) | (2<<28) | dw1[1]; + *dy++ = xy; + *dy++ = (8<<16) | 16; + *dy++ = fmv.u[1]; + *dy++ = bmv.u[1]; + if(cbp & 0x20) { + top_left_b = (short *)((unsigned long)top_left_b + 16); + bottom_left_b = (short *)((unsigned long)bottom_left_b + 16); + PACK_CORR_DATA_0to1(dy,top_left_b,bottom_left_b); + } + if(cbp & 0x10) { + top_right_b = (short *)((unsigned long)top_right_b + 16); + bottom_right_b = (short *)((unsigned long)bottom_right_b + 16); + PACK_CORR_DATA_0to1(dy,top_right_b,bottom_right_b); + } + /* End Y Blocks */ + + + fmv.s[0] /= 2; + fmv.s[1] /= 2; + bmv.s[0] /= 2; + bmv.s[1] /= 2; + + fmv.s[2] /= 2; + fmv.s[3] /= 2; + bmv.s[2] /= 2; + bmv.s[3] /= 2; + + xy >>= 1; + + /* U Blocks */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[0]; + *du++ = xy; + *du++ = (4<<16) | 8; + *du++ = fmv.u[0]; + *du++ = bmv.u[0]; + if(cbp & (1<<23)) { + PACK_CORR_DATA_SHORT(du,block_ptr); + } + + /* Second U Block */ + *du++ = GFXBLOCK + 4 + (usize>>2); + *du++ = (2<<30) | (1<<28) | dw1[1]; + *du++ = xy; + *du++ = (4<<16) | 8; + *du++ = fmv.u[1]; + *du++ = bmv.u[1]; + if(cbp & (1<<23)) { + block_ptr = (short *)((unsigned long)block_ptr + 16); + PACK_CORR_DATA_SHORT(du,block_ptr); + block_ptr = (short *)((unsigned long)block_ptr + 112); + } + /* End U Blocks */ + + /* V Blocks */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[0]; + *dv++ = xy; + *dv++ = (4<<16) | 8; + *dv++ = fmv.u[0]; + *dv++ = bmv.u[0]; + if(cbp & (1<<22)) { + PACK_CORR_DATA_SHORT(dv,block_ptr); + } + + /* Second V Block */ + *dv++ = GFXBLOCK + 4 + (vsize>>2); + *dv++ = (3<<30) | (1<<28) | dw1[1]; + *dv++ = xy; + *dv++ = (4<<16) | 8; + *dv++ = fmv.u[1]; + *dv++ = bmv.u[1]; + if(cbp & (1<<22)) { + block_ptr = (short *)((unsigned long)block_ptr + 16); + PACK_CORR_DATA_SHORT(dv,block_ptr); + block_ptr = (short *)((unsigned long)block_ptr + 112); + } + /* End V Blocks */ + + *datay = dy; + *datau = du; + *datav = dv; +} + + +/*************************************************************************** +// Function: XvMCRenderSurface +// Description: This function does the actual HWMC. Given a list of +// macroblock structures it dispatched the hardware commands to execute +// them. DMA buffer containing Y data are dispatched as they fill up +// U and V DMA buffers are queued until all Y's are done. This minimizes +// the context flipping and flushing required when switching between Y +// U and V surfaces. +***************************************************************************/ +#define UV_QUEUE 14 +_X_EXPORT Status XvMCRenderSurface(Display *display, XvMCContext *context, + unsigned int picture_structure, + XvMCSurface *target_surface, + XvMCSurface *past_surface, + XvMCSurface *future_surface, + unsigned int flags, + unsigned int num_macroblocks, + unsigned int first_macroblock, + XvMCMacroBlockArray *macroblock_array, + XvMCBlockArray *blocks) { + /* Dma Data Structures */ + drmBufPtr pDMAy = NULL,pDMAu[UV_QUEUE],pDMAv[UV_QUEUE]; + int u_index = 0,v_index = 0; + int dirty_context = 1; + + /* Block Pointer */ + short *block_ptr; + /* Current Macroblock Pointer */ + XvMCMacroBlock *mb; + + drm_i810_mc_t mc; + int i,j; + i810XvMCSurface *privTarget; + i810XvMCSurface *privFuture = NULL; + i810XvMCSurface *privPast = NULL; + i810XvMCContext *pI810XvMC; + + /* DMA Pointers set to NULL */ + uint *datay = NULL; + uint *datau = NULL; + uint *datav = NULL; + + + /* Check Parameters for validity */ + if((target_surface == NULL) || (context == NULL) || (display == NULL)) { + printf("Error, Invalid Target,Context, or DIsplay!\n"); + return BadValue; + } + + if(num_macroblocks == 0) {return Success;} + if((macroblock_array == NULL) || (blocks == NULL)) {return BadValue;} + if(context->privData == NULL) {return BadValue;} + pI810XvMC = (i810XvMCContext *)context->privData; + + + if(target_surface->privData == NULL) { + printf("Error, Invalid Target Surface!\n"); + return BadValue; + } + privTarget = (i810XvMCSurface *)target_surface->privData; + + if(macroblock_array->num_blocks < (num_macroblocks + first_macroblock)) { + printf("Error, Too many macroblocks requested for MB array size.\n"); + return BadValue; + } + + /* Test For YV12 Surface */ + if(context->surface_type_id != FOURCC_YV12) { + printf("Error, HWMC only possible on YV12 Surfaces\n"); + return BadValue; + } + + /* P Frame Test */ + if(past_surface == NULL) { + /* Just to avoid some ifs later. */ + privPast = privTarget; + } + else { + if(past_surface->privData == NULL) { + printf("Error, Invalid Past Surface!\n"); + return BadValue; + } + privPast = (i810XvMCSurface *)past_surface->privData; + } + + + /* B Frame Test */ + if(future_surface == NULL) { + privFuture = privTarget; + if(pI810XvMC->dual_prime) { + privFuture = privPast; + /* I810 Specific flag for marking when dual prime is in use. */ + flags |= 0x40000000; + } + + /* + References are different for the Second Field Picture. The + i810 needs to know if it is the second field picture in a + P picture. We use a Private flag to mark this. + */ + if(flags & XVMC_SECOND_FIELD) { + /* I810 Specific flag for marking second fields. */ + flags |= 0x80000000; + } + } + else { + if((future_surface->privData == NULL) || (past_surface == NULL)) { + printf("Error, Invalid Future Surface or No Past Surface!\n"); + return BadValue; + } + privFuture = (i810XvMCSurface *)future_surface->privData; + + /* + Undo Second Field flag since the second field in B frames is just like + the first. + */ + flags &= ~0x80000000; + } + + /* Lock For DMA */ + I810_LOCK(pI810XvMC,0); + + for(i=first_macroblock; i<(num_macroblocks + first_macroblock); i++) { + /* Set up values needed for each macroblock */ + mb = ¯oblock_array->macro_blocks[i]; + block_ptr = &(blocks->blocks[mb->index<<6]); + + /* Lockup can happen if the coordinates are too far out of range */ + if(mb->x > target_surface->width>>4) { + mb->x = 0; + } + if(mb->y > target_surface->height>>4) { + mb->y = 0; + } + + /* If buffers are almost full dispatch them */ + if(datay) { + pDMAy->used = (unsigned long)datay - (unsigned long)pDMAy->address; + if(pDMAy->used > 3520) { + if(dirty_context) { + dispatchYContext(privTarget,privPast,privFuture,pI810XvMC); + } + dirty_context = 0; + mc.idx = pDMAy->idx; + mc.used = pDMAy->used; + datay = NULL; + mc.last_render = ++pI810XvMC->last_render; + privTarget->last_render = pI810XvMC->last_render; + I810_MC(pI810XvMC,mc); + } /* datay near full */ + } /* if(datay) */ + if(datau) { + pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address; + if(pDMAu[u_index]->used > 3904) { + u_index++; + datau = NULL; + if(u_index == UV_QUEUE) { + for(j=0; j<UV_QUEUE; j++) { + mc.idx = pDMAu[j]->idx; + mc.used = pDMAu[j]->used; + mc.last_render = ++pI810XvMC->last_render; + privTarget->last_render = pI810XvMC->last_render; + I810_MC(pI810XvMC,mc); + } + u_index = 0; + dirty_context = 1; + } /* if(u_index == UV_QUEUE) */ + } /* datau near full */ + } /* if(datau) */ + if(datav) { + pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address; + if(pDMAv[v_index]->used > 3904) { + v_index++; + datav = NULL; + if(v_index == UV_QUEUE) { + for(j=0; j<UV_QUEUE; j++) { + mc.idx = pDMAv[j]->idx; + mc.used = pDMAv[j]->used; + mc.last_render = ++pI810XvMC->last_render; + privTarget->last_render = pI810XvMC->last_render; + I810_MC(pI810XvMC,mc); + } + v_index = 0; + dirty_context = 1; + } /* if(v_index == UV_QUEUE) */ + } /* datav near full */ + } /* if(datav) */ + + /* Allocate buffers if this is the first loop,or if we just dispatched */ + if(datay == NULL) { + pDMAy = i810_get_free_buffer(pI810XvMC); + datay = pDMAy->address; + }/* if(datay == NULL) */ + if(datau == NULL) { + pDMAu[u_index] = i810_get_free_buffer(pI810XvMC); + datau = pDMAu[u_index]->address; + if(u_index == 0) { + *datau++ = CMD_FLUSH; + *datau++ = BOOLEAN_ENA_2; + *datau++ = CMD_FLUSH; + *datau++ = DEST_BUFFER_INFO; + *datau++ = privTarget->dbi1u; + *datau++ = DEST_BUFFER_VAR; + *datau++ = privTarget->dbv1; + /* Past Surface */ + *datau++ = CMD_MAP_INFO; + *datau++ = privPast->mi1u; + *datau++ = privPast->mi2u; + *datau++ = privPast->mi3u; + /* Future Surface */ + *datau++ = CMD_MAP_INFO; + *datau++ = privFuture->mi1u | 0x1<<28; + *datau++ = privFuture->mi2u; + *datau++ = privFuture->mi3u; + } + } /* if(datau == NULL) */ + if(datav == NULL) { + pDMAv[v_index] = i810_get_free_buffer(pI810XvMC); + datav = pDMAv[v_index]->address; + if(v_index == 0) { + *datav++ = CMD_FLUSH; + *datav++ = BOOLEAN_ENA_2; + *datav++ = CMD_FLUSH; + *datav++ = DEST_BUFFER_INFO; + *datav++ = privTarget->dbi1v; + *datav++ = DEST_BUFFER_VAR; + *datav++ = privTarget->dbv1; + /* Past Surface */ + *datav++ = CMD_MAP_INFO; + *datav++ = privPast->mi1v; + *datav++ = privPast->mi2v; + *datav++ = privPast->mi3v; + /* Future Surface */ + *datav++ = CMD_MAP_INFO; + *datav++ = privFuture->mi1v | 0x1<<28; + *datav++ = privFuture->mi2v; + *datav++ = privFuture->mi3v; + } + }/* if(datav == NULL) */ + + /* Catch no pattern case */ + if(!(mb->macroblock_type & 0x8)) { + mb->coded_block_pattern = 0; + } + + + if(mb->motion_type == XVMC_PREDICTION_DUAL_PRIME) { + /* + By default the maps will not be set up for dual + prime. We have to change them. + */ + if(!pI810XvMC->dual_prime) { + pI810XvMC->dual_prime = 1; + privFuture = privPast; + /* Y */ + *datay++ = CMD_MAP_INFO; + *datay++ = privFuture->mi1y | 0x1<<28; + *datay++ = privFuture->mi2y; + *datay++ = privFuture->mi3y; + /* U */ + *datau++ = CMD_MAP_INFO; + *datau++ = privFuture->mi1u | 0x1<<28; + *datau++ = privFuture->mi2u; + *datau++ = privFuture->mi3u; + /* V */ + *datav++ = CMD_MAP_INFO; + *datav++ = privFuture->mi1v | 0x1<<28; + *datav++ = privFuture->mi2v; + *datav++ = privFuture->mi3v; + } + } + if((pI810XvMC->dual_prime) && + (mb->motion_type != XVMC_PREDICTION_DUAL_PRIME)) { + pI810XvMC->dual_prime = 0; + privFuture = privTarget; + /* Y */ + *datay++ = CMD_MAP_INFO; + *datay++ = privFuture->mi1y | 0x1<<28; + *datay++ = privFuture->mi2y; + *datay++ = privFuture->mi3y; + /* U */ + *datau++ = CMD_MAP_INFO; + *datau++ = privFuture->mi1u | 0x1<<28; + *datau++ = privFuture->mi2u; + *datau++ = privFuture->mi3u; + /* V */ + *datav++ = CMD_MAP_INFO; + *datav++ = privFuture->mi1v | 0x1<<28; + *datav++ = privFuture->mi2v; + *datav++ = privFuture->mi3v; + } + + + /* Frame Picture */ + if((picture_structure & XVMC_FRAME_PICTURE) == XVMC_FRAME_PICTURE) { + /* Intra Blocks */ + if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) { + if(mb->dct_type) { + renderIntrainFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags); + continue; + } + renderIntrainFrame(&datay,&datau,&datav,mb,block_ptr); + continue; + } + switch((mb->motion_type & 0x3) | (mb->dct_type<<2)) { + case 0x2: /* Frame DCT0 */ + renderFrameinFrame(&datay,&datau,&datav,mb,block_ptr,flags); + continue; + case 0x5: /* Field DCT1 */ + renderFieldinFrame(&datay,&datau,&datav,mb,block_ptr,flags); + continue; + case 0x6: /* Frame DCT1 */ + renderFrameinFrameDCT1(&datay,&datau,&datav,mb,block_ptr,flags); + continue; + case 0x1: /* Field DCT0 */ + renderFieldinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags); + continue; + case 0x3: /* Dual Prime DCT0 */ + renderDualPrimeinFrame(&datay,&datau,&datav,mb,block_ptr,flags); + continue; + case 0x7: /* Dual Prime DCT1 */ + renderDualPrimeinFrameDCT0(&datay,&datau,&datav,mb,block_ptr,flags); + continue; + default: /* No Motion Type */ + renderError(); + continue; + } /* Switch */ + } /* Frame Picture */ + + /* Field Pictures */ + if(mb->macroblock_type & XVMC_MB_TYPE_INTRA) { + renderIntrainField(&datay,&datau,&datav,mb,block_ptr,picture_structure); + continue; + } + switch(mb->motion_type & 0x3) { + case 0x1: /* Field Motion */ + renderFieldinField(&datay,&datau,&datav,mb,block_ptr,picture_structure, + flags); + continue; + case 0x2: /* 16x8 Motion */ + render16x8inField(&datay,&datau,&datav,mb,block_ptr,picture_structure, + flags); + continue; + case 0x3: /* Dual Prime */ + renderDualPrimeinField(&datay,&datau,&datav,mb,block_ptr, + picture_structure,flags); + continue; + default: /* No Motion Type */ + renderError(); + continue; + } + continue; + + } /* for each Macroblock */ + + /* Dispatch remaining DMA buffers */ + if(dirty_context) { + dispatchYContext(privTarget,privPast,privFuture,pI810XvMC); + } + mc.idx = pDMAy->idx; + mc.used = (unsigned long)datay - (unsigned long)pDMAy->address; + mc.last_render = ++pI810XvMC->last_render; + privTarget->last_render = pI810XvMC->last_render; + I810_MC(pI810XvMC,mc); + + pDMAu[u_index]->used = (unsigned long)datau - (unsigned long)pDMAu[u_index]->address; + for(j=0; j<=u_index; j++) { + mc.idx = pDMAu[j]->idx; + mc.used = pDMAu[j]->used; + mc.last_render = ++pI810XvMC->last_render; + privTarget->last_render = pI810XvMC->last_render; + I810_MC(pI810XvMC,mc); + } + pDMAv[v_index]->used = (unsigned long)datav - (unsigned long)pDMAv[v_index]->address; + for(j=0; j<=v_index; j++) { + mc.idx = pDMAv[j]->idx; + mc.used = pDMAv[j]->used; + mc.last_render = ++pI810XvMC->last_render; + privTarget->last_render = pI810XvMC->last_render; + I810_MC(pI810XvMC,mc); + } + + I810_UNLOCK(pI810XvMC); + + return Success; +} + +/*************************************************************************** +// Function: XvMCPutSurface +// Description: +// Arguments: +// display: Connection to X server +// surface: Surface to be displayed +// draw: X Drawable on which to display the surface +// srcx: X coordinate of the top left corner of the region to be +// displayed within the surface. +// srcy: Y coordinate of the top left corner of the region to be +// displayed within the surface. +// srcw: Width of the region to be displayed. +// srch: Height of the region to be displayed. +// destx: X cordinate of the top left corner of the destination region +// in the drawable coordinates. +// desty: Y cordinate of the top left corner of the destination region +// in the drawable coordinates. +// destw: Width of the destination region. +// desth: Height of the destination region. +// flags: One or more of the following. +// XVMC_TOP_FIELD - Display only the Top field of the surface. +// XVMC_BOTTOM_FIELD - Display only the Bottom Field of the surface. +// XVMC_FRAME_PICTURE - Display both fields or frame. +// +// Info: Portions of this function derived from i810_video.c (XFree86) +// +// This function is organized so that we wait as long as possible before +// touching the overlay registers. Since we don't know that the last +// flip has happened yet we want to give the overlay as long as +// possible to catch up before we have to check on its progress. This +// makes it unlikely that we have to wait on the last flip. +***************************************************************************/ +_X_EXPORT Status XvMCPutSurface(Display *display,XvMCSurface *surface, + Drawable draw, short srcx, short srcy, + unsigned short srcw, unsigned short srch, + short destx, short desty, + unsigned short destw, unsigned short desth, + int flags) { + i810XvMCContext *pI810XvMC; + i810XvMCSurface *pI810Surface; + i810OverlayRecPtr pORegs; + unsigned int ysrc_offset,uvsrc_offset; + Box extents; + uint window_width,window_height; + unsigned int xscaleInt = 0,xscaleFract = 0,yscaleInt = 0,yscaleFract = 0; + unsigned int xscaleFractUV = 0,xscaleIntUV = 0,yscaleFractUV = 0; + unsigned int yscaleIntUV = 0,yPitch = 0,uvPitch = 0; + unsigned int ovcmd = 0; + uint d; + double xscale,yscale; + int diff; + int clipped_srcx, clipped_srcy, clipped_destx, clipped_desty; + int clipped_srcw, clipped_srch, clipped_destw, clipped_desth; + uint x1,y1,root_width,root_height; + int x2 = 0, y2 = 0,unused; + uint nChilds; + int stat; + Window win,root,parent,*pChilds; + + + if((display == NULL) || (surface == NULL)) { + return BadValue; + } + + if(surface->privData == NULL) { + return (error_base + XvMCBadSurface); + } + pI810Surface = (i810XvMCSurface *)surface->privData; + pI810XvMC = (i810XvMCContext *)pI810Surface->privContext; + pORegs = (i810OverlayRecPtr)pI810XvMC->oregs; + + + switch(surface->surface_type_id) { + case FOURCC_YV12: + case FOURCC_I420: + yPitch = (srcw + 7) & ~7; + uvPitch = ((srcw>>1) + 7) & ~7; + if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) { + srch = srch>>1; + } + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + /* FIXME: Non Planar not fully implemented. */ + return BadValue; + yPitch = ((srcw + 7) & ~7) << 1; + break; + }/* switch(surface->surface_type_id) */ + + /* + FIXME: This should be using the DRI's clip rect but that isn't + all hooked up yet. This has some latency but we get by. + */ + win = draw; + XQueryTree(display,win,&root,&parent,&pChilds,&nChilds); + if(nChilds) XFree(pChilds); + XGetGeometry(display,win, &root, &x2, &y2, &window_width, + &window_height, &d, &d); + x1 = x2; + y1 = y2; + win = parent; + do { + XQueryTree(display,win,&root,&parent,&pChilds,&nChilds); + if(nChilds) XFree(pChilds); + XGetGeometry(display,win, &root, &x2, &y2, &d, &d, &d, &d); + x1 += x2; + y1 += y2; + win = parent; + }while(win != root); + XGetGeometry(display,root, &root, &unused, &unused, + &root_width, &root_height, &d, &d); + + /* Left edge of Video window clipped to screen */ + extents.x1 = 0; + if(x1 > extents.x1) { + extents.x1 = x1; + } + /* Right edge of Video window clipped to screen */ + extents.x2 = root_width; + if(extents.x2 > (x1 + window_width)) { + extents.x2 = x1 + window_width; + } + /* Top edge of Video window clipped to screen */ + extents.y1 = 0; + if(y1 > extents.y1) { + extents.y1 = y1; + } + /* Bottom edge of Video window clipped to screen */ + extents.y2 = root_height; + if(extents.y2 > (y1 + window_height)) { + extents.y2 = y1 + window_height; + } + + /* + Clipping is more difficult than is seems. We need to keep the + scaling factors even if the destination window needs to be clipped. + We clip the destination window first then apply a scaled version + to the source window. + */ + + /* Put destination coords in screen coords */ + destx += x1; + desty += y1; + + /* Scale factors requested */ + xscale = (double)srcw / (double)destw; + yscale = (double)srch / (double)desth; + + /* + If destination window needs to be clipped we actually adjust both + the src and dest window so as to keep the scaling that was requested + */ + clipped_srcx = srcx; + clipped_srcy = srcy; + clipped_destx = destx; + clipped_desty = desty; + clipped_srcw = srcw; + clipped_srch = srch; + clipped_destw = destw; + clipped_desth = desth; + + /* Clip to the source surface boundaries */ + if(clipped_srcx < 0) { + clipped_destx += (0 - clipped_srcx) / xscale; + clipped_srcw -= clipped_srcx; + clipped_destw -= clipped_srcx / xscale; + clipped_srcx = 0; + } + if((clipped_srcw + clipped_srcx) > surface->width) { + clipped_srcw = surface->width - clipped_srcx; + clipped_destw -= (clipped_srcw - srcw) / xscale; + } + if(clipped_srcy < 0) { + clipped_desty += (0 - clipped_srcy) / yscale; + clipped_srch -= clipped_srcy; + clipped_desth -= clipped_srcy / yscale; + clipped_srcy = 0; + } + if((clipped_srch + clipped_srcy) > surface->height) { + clipped_srch = surface->height - clipped_srcy; + clipped_desth -= (clipped_srch - srch) / yscale; + } + + /* Clip to the extents */ + if(clipped_destx < extents.x1) { + diff = extents.x1 - clipped_destx; + clipped_srcx += diff * xscale; + clipped_srcw -= diff * xscale; + clipped_destw -= diff; + clipped_destx = extents.x1; + } + + diff = (clipped_destx + clipped_destw) - extents.x2; + if(diff > 0) { + clipped_destw -= diff; + clipped_srcw -= diff * xscale; + } + + if(clipped_desty < extents.y1) { + diff = extents.y1 - clipped_desty; + clipped_srcy += diff * yscale; + clipped_srch -= diff * yscale; + clipped_desth -= diff; + clipped_desty = 0; + } + + diff = (clipped_desty + clipped_desth) - extents.y2; + if(diff > 0) { + clipped_desth -= diff; + clipped_srch -= diff * yscale; + } + + /* If the whole window is clipped turn off the overlay */ + if((clipped_destx + clipped_destw < extents.x1) || + (clipped_desty + clipped_desth < extents.y1) || + (clipped_destx > extents.x2) || + (clipped_desty > extents.y2)) { + return XvMCHideSurface(display, surface); + } + + /* + Adjust the source offset width and height according to the clipped + destination window. + */ + ysrc_offset = ((clipped_srcx + 1) & ~1) + + ((clipped_srcy + 1) & ~1) * (1<<pI810Surface->pitch); + uvsrc_offset = (clipped_srcx>>1) + + (clipped_srcy>>1) * (1<<(pI810Surface->pitch - 1)); + + /* + Initially, YCbCr and Overlay Enable and + vertical chrominance up interpolation and horozontal chrominance + up interpolation + */ + ovcmd = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | + Y_ADJUST | OVERLAY_ENABLE; + + if ((clipped_destw != clipped_srcw) || + (clipped_desth != clipped_srch)) { + xscaleInt = (clipped_srcw / clipped_destw) & 0x3; + xscaleFract = (clipped_srcw << 12) / clipped_destw; + yscaleInt = (clipped_srch / clipped_desth) & 0x3; + yscaleFract = (clipped_srch << 12) / clipped_desth; + + if (clipped_destw > clipped_srcw) { + /* horizontal up-scaling */ + ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER; + ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER; + ovcmd |= (HC_UP_INTERPOLATION | HL_UP_INTERPOLATION); + } + + if (clipped_desth > clipped_srch) { + /* vertical up-scaling */ + ovcmd &= ~VERTICAL_CHROMINANCE_FILTER; + ovcmd &= ~VERTICAL_LUMINANCE_FILTER; + ovcmd |= (VC_UP_INTERPOLATION | VL_UP_INTERPOLATION); + } + + if (clipped_destw < clipped_srcw) { + /* horizontal down-scaling */ + ovcmd &= ~HORIZONTAL_CHROMINANCE_FILTER; + ovcmd &= ~HORIZONTAL_LUMINANCE_FILTER; + ovcmd |= (HC_DOWN_INTERPOLATION | HL_DOWN_INTERPOLATION); + } + + if (clipped_desth < clipped_srch) { + /* vertical down-scaling */ + ovcmd &= ~VERTICAL_CHROMINANCE_FILTER; + ovcmd &= ~VERTICAL_LUMINANCE_FILTER; + ovcmd |= (VC_DOWN_INTERPOLATION | VL_DOWN_INTERPOLATION); + } + + /* now calculate the UV scaling factor */ + if (xscaleFract) { + xscaleFractUV = xscaleFract >> MINUV_SCALE; + ovcmd &= ~HC_DOWN_INTERPOLATION; + ovcmd |= HC_UP_INTERPOLATION; + } + + if (xscaleInt) { + xscaleIntUV = xscaleInt >> MINUV_SCALE; + if (xscaleIntUV) { + ovcmd &= ~HC_UP_INTERPOLATION; + } + } + + if (yscaleFract) { + yscaleFractUV = yscaleFract >> MINUV_SCALE; + ovcmd &= ~VC_DOWN_INTERPOLATION; + ovcmd |= VC_UP_INTERPOLATION; + } + + if (yscaleInt) { + yscaleIntUV = yscaleInt >> MINUV_SCALE; + if (yscaleIntUV) { + ovcmd &= ~VC_UP_INTERPOLATION; + ovcmd |= VC_DOWN_INTERPOLATION; + } + } + + }/* if((destw != srcw) || (desth != srch)) */ + + /* Lock the DRM */ + I810_LOCK(pI810XvMC,0); + + /* Block until rendering on this surface is finished */ + stat = XVMC_RENDERING; + while(stat & XVMC_RENDERING) { + XvMCGetSurfaceStatus(display,surface,&stat); + } + /* Block until the last flip is finished */ + if(pI810XvMC->last_flip) { + BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current); + } + + pI810XvMC->current = !pI810XvMC->current; + pORegs->OV0CMD = ovcmd; + + if ((clipped_destw != clipped_srcw) || + (clipped_desth != clipped_srch)) { + pORegs->YRGBSCALE = (xscaleInt << 15) | + ((xscaleFract & 0xFFF) << 3) | (yscaleInt) | + ((yscaleFract & 0xFFF) << 20); + + pORegs->UVSCALE = yscaleIntUV | ((xscaleFractUV & 0xFFF) << 3) | + ((yscaleFractUV & 0xFFF) << 20); + } + else { + /* Normal 1:1 scaling */ + pORegs->YRGBSCALE = 0x80004000; + pORegs->UVSCALE = 0x80004000; + } + + pORegs->SHEIGHT = clipped_srch | (clipped_srch << 15); + pORegs->DWINPOS = (clipped_desty << 16) | clipped_destx; + pORegs->DWINSZ = ((clipped_desth<< 16) | (clipped_destw)); + + /* Attributes */ + pORegs->OV0CLRC0 = ((pI810XvMC->contrast & 0x1ff)<<8) | + (pI810XvMC->brightness & 0xff); + pORegs->OV0CLRC1 = (pI810XvMC->saturation & 0x3ff); + + /* Destination Colorkey Setup */ + pI810XvMC->oregs->DCLRKV = RGB16ToColorKey(pI810XvMC->colorkey); + + /* buffer locations, add the offset from the clipping */ + if(pI810XvMC->current) { + pORegs->OBUF_1Y = (unsigned long)pI810Surface->offset + + (unsigned long)pI810Surface->offsets[0] + ysrc_offset; + pORegs->OBUF_1V = (unsigned long)pI810Surface->offset + + (unsigned long)pI810Surface->offsets[2] + uvsrc_offset; + pORegs->OBUF_1U = (unsigned long)pI810Surface->offset + + (unsigned long)pI810Surface->offsets[1] + uvsrc_offset; + } + else { + pORegs->OBUF_0Y = (unsigned long)pI810Surface->offset + + (unsigned long)pI810Surface->offsets[0] + ysrc_offset; + pORegs->OBUF_0V = (unsigned long)pI810Surface->offset + + (unsigned long)pI810Surface->offsets[2] + uvsrc_offset; + pORegs->OBUF_0U = (unsigned long)pI810Surface->offset + + (unsigned long)pI810Surface->offsets[1] + uvsrc_offset; + } + + switch(surface->surface_type_id) { + case FOURCC_YV12: + case FOURCC_I420: + pORegs->SWID = (uvPitch << 16) | yPitch; + pORegs->SWIDQW = (uvPitch << 13) | (yPitch >> 3); + pORegs->OV0STRIDE = (1<<pI810Surface->pitch) | + ((1<<pI810Surface->pitch) << 15); + pORegs->OV0CMD &= ~SOURCE_FORMAT; + pORegs->OV0CMD |= YUV_420; + if((flags & XVMC_FRAME_PICTURE) != XVMC_FRAME_PICTURE) { + /* Top Field Only */ + if(flags & XVMC_TOP_FIELD) { + if(pI810XvMC->current == 1) { + pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD | + BUFFER1_FIELD0); + } + else { + pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD | + BUFFER0_FIELD0); + } + pORegs->YRGB_VPH = 1<<15 | 1<<31; + pORegs->UV_VPH = 3<<14 | 3<<30; + pORegs->INIT_PH = 0x06 | 0x18; + } + /* Bottom Field Only */ + else { + if(pI810XvMC->current == 1) { + pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD | + BUFFER1_FIELD1); + } + else { + pORegs->OV0CMD |= (VERTICAL_PHASE_BOTH | FLIP_TYPE_FIELD | + BUFFER0_FIELD1); + } + pORegs->YRGB_VPH = 0; + pORegs->UV_VPH = 7<<29 | 7<<13; + pORegs->INIT_PH = 0x06; + } + } + /* Frame Picture */ + else { + if(pI810XvMC->current == 1) { + pORegs->OV0CMD |= BUFFER1_FIELD0; + } + else { + pORegs->OV0CMD |= BUFFER0_FIELD0; + } + pORegs->YRGB_VPH = 0; + pORegs->UV_VPH = 0; + pORegs->INIT_PH = 0; + } + break; + case FOURCC_UYVY: + case FOURCC_YUY2: + default: + pORegs->SWID = srcw; + pORegs->SWIDQW = srcw >> 3; + pORegs->OV0STRIDE = pI810Surface->pitch; + pORegs->OV0CMD &= ~SOURCE_FORMAT; + pORegs->OV0CMD |= YUV_422; + pORegs->OV0CMD &= ~OV_BYTE_ORDER; + if (surface->surface_type_id == FOURCC_UYVY) { + pORegs->OV0CMD |= Y_SWAP; + } + + pORegs->OV0CMD &= ~BUFFER_AND_FIELD; + if(pI810XvMC->current == 1) { + pORegs->OV0CMD |= BUFFER1_FIELD0; + } + else { + pORegs->OV0CMD |= BUFFER0_FIELD0; + } + + break; + } /* switch(surface->surface_type_id) */ + + + + OVERLAY_FLIP(pI810XvMC); + + /* + The Overlay only flips when it knows you changed + something. So the first time change stuff while it + is watching to be sure. + */ + if(!pI810XvMC->last_flip) { + pORegs->OV0CMD &= ~0x4; + if(pI810XvMC->current == 1) { + pORegs->OV0CMD |= BUFFER1_FIELD0; + } + else { + pORegs->OV0CMD |= BUFFER0_FIELD0; + } + } + pI810Surface->last_flip = ++pI810XvMC->last_flip; + I810_UNLOCK(pI810XvMC); + + return Success; +} + +/*************************************************************************** +// Function: XvMCSyncSurface +// Arguments: +// display - Connection to the X server +// surface - The surface to synchronize +// Info: +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCSyncSurface(Display *display,XvMCSurface *surface) { + Status ret; + int stat=0; + /* + FIXME: Perhaps a timer here to prevent lockup? + FIXME: Perhaps a usleep to not be busy waiting? + */ + do { + ret = XvMCGetSurfaceStatus(display,surface,&stat); + }while(!ret && (stat & XVMC_RENDERING)); + return ret; +} + +/*************************************************************************** +// Function: XvMCFlushSurface +// Description: +// This function commits pending rendering requests to ensure that they +// wll be completed in a finite amount of time. +// Arguments: +// display - Connection to X server +// surface - Surface to flush +// Info: +// This command is a noop for i810 becuase we always dispatch buffers in +// render. There is little gain to be had with 4k buffers. +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCFlushSurface(Display * display, XvMCSurface *surface) { + return Success; +} + +/*************************************************************************** +// Function: XvMCGetSurfaceStatus +// Description: +// Arguments: +// display: connection to X server +// surface: The surface to query +// stat: One of the Following +// XVMC_RENDERING - The last XvMCRenderSurface command has not +// completed. +// XVMC_DISPLAYING - The surface is currently being displayed or a +// display is pending. +***************************************************************************/ +_X_EXPORT Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, + int *stat) { + i810XvMCSurface *privSurface; + i810XvMCContext *pI810XvMC; + int temp; + + if((display == NULL) || (surface == NULL) || (stat == NULL)) { + return BadValue; + } + if(surface->privData == NULL) { + return BadValue; + } + *stat = 0; + privSurface = surface->privData; + + pI810XvMC = privSurface->privContext; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadSurface); + } + + I810_LOCK(pI810XvMC,0); + if(privSurface->last_flip) { + /* This can not happen */ + if(pI810XvMC->last_flip < privSurface->last_flip) { + printf("Error: Context last flip is less than surface last flip.\n"); + return BadValue; + } + /* + If the context has 2 or more flips after this surface it + cannot be displaying. Don't bother to check. + */ + if(!(pI810XvMC->last_flip > (privSurface->last_flip + 1))) { + /* + If this surface was the last flipped it is either displaying + or about to be so don't bother checking. + */ + if(pI810XvMC->last_flip == privSurface->last_flip) { + *stat |= XVMC_DISPLAYING; + } + else { + /* + In this case there has been one more flip since our surface's + but we need to check if it is finished or not. + */ + temp = GET_FSTATUS(pI810XvMC); + if(((temp & (1<<20))>>20) != pI810XvMC->current) { + *stat |= XVMC_DISPLAYING; + } + } + } + } + + if(privSurface->last_render && + (privSurface->last_render > GET_RSTATUS(pI810XvMC))) { + *stat |= XVMC_RENDERING; + } + I810_UNLOCK(pI810XvMC); + + return Success; +} + +/*************************************************************************** +// +// Surface manipulation functions +// +***************************************************************************/ + +/*************************************************************************** +// Function: XvMCHideSurface +// Description: Stops the display of a surface. +// Arguments: +// display - Connection to the X server. +// surface - surface to be hidden. +// +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCHideSurface(Display *display, XvMCSurface *surface) { + i810XvMCSurface *pI810Surface; + i810XvMCContext *pI810XvMC; + int ss, xx; + + /* Did we get a good display and surface passed into us? */ + if(display == NULL) { + return BadValue; + } + + if(surface == NULL) { + return (error_base + XvMCBadSurface); + } + + XvMCSyncSurface(display, surface); + + /* Get surface private data pointer */ + if(surface->privData == NULL) { + return (error_base + XvMCBadSurface); + } + pI810Surface = (i810XvMCSurface *)surface->privData; + + /* + Get the status of the surface, if it is not currently displayed + we don't need to worry about it. + */ + if((xx = XvMCGetSurfaceStatus(display, surface, &ss)) != Success) { + return xx; + } + if(! (ss & XVMC_DISPLAYING)) { + return Success; + } + + /* Get the associated context pointer */ + pI810XvMC = (i810XvMCContext *)pI810Surface->privContext; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadSurface); + } + + if(pI810XvMC->last_flip) { + I810_LOCK(pI810XvMC,DRM_LOCK_QUIESCENT); + + /* Make sure last flip is done */ + BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current); + + /* Set the registers to turn the overlay off */ + pI810XvMC->oregs->OV0CMD = VC_UP_INTERPOLATION | HC_UP_INTERPOLATION | + Y_ADJUST; + pI810XvMC->current = !pI810XvMC->current; + if(pI810XvMC->current == 1) { + pI810XvMC->oregs->OV0CMD |= BUFFER1_FIELD0; + } + else { + pI810XvMC->oregs->OV0CMD |= BUFFER0_FIELD0; + } + OVERLAY_FLIP(pI810XvMC); + /* + Increment the context flip but not the surface. This way no + surface has the last flip #. + */ + pI810XvMC->last_flip++; + + + /* Now wait until the hardware reads the registers and makes the change. */ + BLOCK_OVERLAY(pI810XvMC,pI810XvMC->current) + + I810_UNLOCK(pI810XvMC); + } + + return Success; +} + + + + +/*************************************************************************** +// +// Functions that deal with subpictures +// +***************************************************************************/ + + + +/*************************************************************************** +// Function: XvMCCreateSubpicture +// Description: This creates a subpicture by filling out the XvMCSubpicture +// structure passed to it and returning Success. +// Arguments: +// display - Connection to the X server. +// context - The context to create the subpicture for. +// subpicture - Pre-allocated XvMCSubpicture structure to be filled in. +// width - of subpicture +// height - of subpicture +// xvimage_id - The id describing the XvImage format. +// +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCCreateSubpicture(Display *display, XvMCContext *context, + XvMCSubpicture *subpicture, + unsigned short width, unsigned short height, + int xvimage_id) { + i810XvMCContext *pI810XvMC; + i810XvMCSubpicture *pI810Subpicture; + int priv_count; + uint *priv_data; + Status ret; + + if((subpicture == NULL) || (context == NULL) || (display == NULL)){ + return BadValue; + } + + pI810XvMC = (i810XvMCContext *)context->privData; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadContext); + } + + + subpicture->context_id = context->context_id; + subpicture->xvimage_id = xvimage_id; + + /* These need to be checked to make sure they are not too big! */ + subpicture->width = width; + subpicture->height = height; + + subpicture->privData = + (i810XvMCSubpicture *)malloc(sizeof(i810XvMCSubpicture)); + + if(!subpicture->privData) { + return BadAlloc; + } + pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData; + + + if((ret = _xvmc_create_subpicture(display, context, subpicture, + &priv_count, &priv_data))) { + printf("Unable to create XvMCSubpicture.\n"); + return ret; + } + + if(priv_count != 1) { + printf("_xvmc_create_subpicture() returned incorrect data size.\n"); + printf("Expected 1 got %d\n",priv_count); + free(priv_data); + return BadAlloc; + } + /* Data == Client Address, offset == Physical address offset */ + pI810Subpicture->data = pI810XvMC->surfaces.address; + pI810Subpicture->offset = pI810XvMC->surfaces.offset; + + /* Initialize private values */ + pI810Subpicture->privContext = pI810XvMC; + + pI810Subpicture->last_render = 0; + pI810Subpicture->last_flip = 0; + + /* Based on the xvimage_id we will need to set the other values */ + subpicture->num_palette_entries = 16; + subpicture->entry_bytes = 3; + strcpy(subpicture->component_order,"YUV"); + + /* + i810's MC Engine needs surfaces of 2^x (x= 9,10,11,12) pitch + and the Tiler need 512k aligned surfaces, basically we are + stuck with fixed memory with pitch 1024. + */ + pI810Subpicture->pitch = 10; + + /* + offsets[0] == offset into the map described by either + address (Client memeory address) or offset (physical offset from fb base) + */ + pI810Subpicture->offsets[0] = priv_data[0]; + if(((unsigned long)pI810Subpicture->data + pI810Subpicture->offsets[0]) & 4095) { + printf("XvMCCreateSubpicture: Subpicture offset 0 is not 4096 aligned\n"); + } + + /* Free data returned from xvmc_create_surface */ + free(priv_data); + + /* Clear the surface to 0 */ + memset((void *)((unsigned long)pI810Subpicture->data + (unsigned long)pI810Subpicture->offsets[0]), + 0, ((1<<pI810Subpicture->pitch) * subpicture->height)); + + switch(subpicture->xvimage_id) { + case FOURCC_IA44: + case FOURCC_AI44: + /* Destination buffer info command */ + pI810Subpicture->dbi1 = ((((unsigned int)pI810Subpicture->offset + + pI810Subpicture->offsets[0]) & ~0xfc000fff) | + (pI810Subpicture->pitch - 9)); + + /* Destination buffer variables command */ + pI810Subpicture->dbv1 = (0x8<<20) | (0x8<<16); + + /* Map info command */ + pI810Subpicture->mi1 = (0x0<<24) | (3<<21) | (1<<9) | + (pI810Subpicture->pitch - 3); + + pI810Subpicture->mi2 = (((unsigned int)subpicture->height - 1)<<16) | + ((unsigned int)subpicture->width - 1); + + pI810Subpicture->mi3 = ((unsigned int)pI810Subpicture->offset + + pI810Subpicture->offsets[0]) & ~0xfc00000f; + break; + default: + free(subpicture->privData); + return BadMatch; + } + + pI810XvMC->ref++; + return Success; +} + + + +/*************************************************************************** +// Function: XvMCClearSubpicture +// Description: Clear the area of the given subpicture to "color". +// structure passed to it and returning Success. +// Arguments: +// display - Connection to the X server. +// subpicture - Subpicture to clear. +// x, y, width, height - rectangle in the subpicture to clear. +// color - The data to file the rectangle with. +// +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCClearSubpicture(Display *display, XvMCSubpicture *subpicture, + short x, short y, + unsigned short width, unsigned short height, + unsigned int color) { + + i810XvMCContext *pI810XvMC; + i810XvMCSubpicture *pI810Subpicture; + int i; + + if((subpicture == NULL) || (display == NULL)){ + return BadValue; + } + + if(!subpicture->privData) { + return (error_base + XvMCBadSubpicture); + } + pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData; + + pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadSubpicture); + } + + if((x < 0) || (x + width > subpicture->width)) { + return BadValue; + } + + if((y < 0) || (y + height > subpicture->height)) { + return BadValue; + } + + for(i=y; i<y + height; i++) { + memset((void *)((unsigned long)pI810Subpicture->data + + (unsigned long)pI810Subpicture->offsets[0] + x + + (1<<pI810Subpicture->pitch) * i),(char)color,width); + } + + return Success; +} + +/*************************************************************************** +// Function: XvMCCompositeSubpicture +// Description: Composite the XvImae on the subpicture. This composit uses +// non-premultiplied alpha. Destination alpha is utilized +// except for with indexed subpictures. Indexed subpictures +// use a simple "replace". +// Arguments: +// display - Connection to the X server. +// subpicture - Subpicture to clear. +// image - the XvImage to be used as the source of the composite. +// srcx, srcy, width, height - The rectangle from the image to be used. +// dstx, dsty - location in the subpicture to composite the source. +// +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCCompositeSubpicture(Display *display, XvMCSubpicture *subpicture, + XvImage *image, + short srcx, short srcy, + unsigned short width, unsigned short height, + short dstx, short dsty) { + + i810XvMCContext *pI810XvMC; + i810XvMCSubpicture *pI810Subpicture; + int i; + + if((subpicture == NULL) || (display == NULL)){ + return BadValue; + } + + if(!subpicture->privData) { + return (error_base + XvMCBadSubpicture); + } + pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData; + + pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadSubpicture); + } + + if((srcx < 0) || (srcx + width > image->width)) { + return BadValue; + } + + if((dstx < 0) || (dstx + width > subpicture->width)) { + return BadValue; + } + + if((srcy < 0) || (srcy + height > image->height)) { + return BadValue; + } + + if((dsty < 0) || (dsty + height > subpicture->height)) { + return BadValue; + } + + for(i=0; i<height; i++) { + memcpy((void *)((unsigned long)pI810Subpicture->data + + (unsigned long)pI810Subpicture->offsets[0] + dstx + + (1<<pI810Subpicture->pitch) * (i + dsty)), + (void *)((unsigned long)image->data + + (unsigned long)image->offsets[0] + srcx + + image->pitches[0] * (i + srcy)) + ,width); + } + + return Success; + +} + + +/*************************************************************************** +// Function: XvMCDestroySubpicture +// Description: Destroys the specified subpicture. +// Arguments: +// display - Connection to the X server. +// subpicture - Subpicture to be destroyed. +// +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture) { + + i810XvMCSubpicture *pI810Subpicture; + i810XvMCContext *pI810XvMC; + + if((display == NULL) || (subpicture == NULL)) { + return BadValue; + } + if(!subpicture->privData) { + return (error_base + XvMCBadSubpicture); + } + pI810Subpicture = (i810XvMCSubpicture *)subpicture->privData; + + pI810XvMC = (i810XvMCContext *)pI810Subpicture->privContext; + if(!pI810XvMC) { + return (error_base + XvMCBadSubpicture); + } + + + if(pI810Subpicture->last_render) { + XvMCSyncSubpicture(display,subpicture); + } + + _xvmc_destroy_subpicture(display,subpicture); + + i810_free_privContext(pI810XvMC); + + free(pI810Subpicture); + subpicture->privData = NULL; + return Success; +} + + +/*************************************************************************** +// Function: XvMCSetSubpicturePalette +// Description: Set the subpictures palette +// Arguments: +// display - Connection to the X server. +// subpicture - Subpiture to set palette for. +// palette - A pointer to an array holding the palette data. The array +// is num_palette_entries * entry_bytes in size. +// Returns: Status +***************************************************************************/ + +_X_EXPORT Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture, + unsigned char *palette) { + i810XvMCSubpicture *privSubpicture; + int i,j; + + if((display == NULL) || (subpicture == NULL)) { + return BadValue; + } + if(subpicture->privData == NULL) { + return (error_base + XvMCBadSubpicture); + } + privSubpicture = (i810XvMCSubpicture *)subpicture->privData; + + j=0; + for(i=0; i<16; i++) { + privSubpicture->palette[0][i] = palette[j++]; + privSubpicture->palette[1][i] = palette[j++]; + privSubpicture->palette[2][i] = palette[j++]; + } + return Success; +} + +/*************************************************************************** +// Function: XvMCBlendSubpicture +// Description: +// The behavior of this function is different depending on whether +// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo. +// i810 only support frontend behavior. +// +// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior): +// +// XvMCBlendSubpicture is a no-op in this case. +// +// Arguments: +// display - Connection to the X server. +// subpicture - The subpicture to be blended into the video. +// target_surface - The surface to be displayed with the blended subpic. +// source_surface - Source surface prior to blending. +// subx, suby, subw, subh - The rectangle from the subpicture to use. +// surfx, surfy, surfw, surfh - The rectangle in the surface to blend +// blend the subpicture rectangle into. Scaling can ocure if +// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set. +// +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCBlendSubpicture(Display *display, XvMCSurface *target_surface, + XvMCSubpicture *subpicture, + short subx, short suby, + unsigned short subw, unsigned short subh, + short surfx, short surfy, + unsigned short surfw, unsigned short surfh) { + + return BadMatch; +} + + + +/*************************************************************************** +// Function: XvMCBlendSubpicture2 +// Description: +// The behavior of this function is different depending on whether +// or not the XVMC_BACKEND_SUBPICTURE flag is set in the XvMCSurfaceInfo. +// i810 only supports frontend blending. +// +// XVMC_BACKEND_SUBPICTURE not set ("frontend" behavior): +// +// XvMCBlendSubpicture2 blends the source_surface and subpicture and +// puts it in the target_surface. This does not effect the status of +// the source surface but will cause the target_surface to query +// XVMC_RENDERING until the blend is completed. +// +// Arguments: +// display - Connection to the X server. +// subpicture - The subpicture to be blended into the video. +// target_surface - The surface to be displayed with the blended subpic. +// source_surface - Source surface prior to blending. +// subx, suby, subw, subh - The rectangle from the subpicture to use. +// surfx, surfy, surfw, surfh - The rectangle in the surface to blend +// blend the subpicture rectangle into. Scaling can ocure if +// XVMC_SUBPICTURE_INDEPENDENT_SCALING is set. +// +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCBlendSubpicture2(Display *display, + XvMCSurface *source_surface, + XvMCSurface *target_surface, + XvMCSubpicture *subpicture, + short subx, short suby, + unsigned short subw, unsigned short subh, + short surfx, short surfy, + unsigned short surfw, unsigned short surfh) { + drmBufPtr pDMA; + unsigned int *data; + i810XvMCContext *pI810XvMC; + i810XvMCSubpicture *privSubpicture; + i810XvMCSurface *privTarget; + i810XvMCSurface *privSource; + drm_i810_mc_t mc; + int i,j; + + if(display == NULL) { + return BadValue; + } + + if(subpicture == NULL) { + return (error_base + XvMCBadSubpicture); + } + + if((target_surface == NULL) || (source_surface == NULL)) { + return (error_base + XvMCBadSurface); + } + + if((subpicture->xvimage_id != FOURCC_AI44) && + (subpicture->xvimage_id != FOURCC_IA44)) { + return (error_base + XvMCBadSubpicture); + } + + if(!subpicture->privData) { + return (error_base + XvMCBadSubpicture); + } + privSubpicture = (i810XvMCSubpicture *)subpicture->privData; + + pI810XvMC = (i810XvMCContext *)privSubpicture->privContext; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadSubpicture); + } + + if(!target_surface->privData) { + return (error_base + XvMCBadSurface); + } + privTarget = (i810XvMCSurface *)target_surface->privData; + + if(!source_surface->privData) { + return (error_base + XvMCBadSurface); + } + privSource = (i810XvMCSurface *)source_surface->privData; + + + /* Check that size isn't bigger than subpicture */ + if((subx + subw) > subpicture->width) { + return BadValue; + } + if((suby + subh) > subpicture->height) { + return BadValue; + } + /* Check that dest isn't bigger than surface */ + if((surfx + surfw) > target_surface->width) { + return BadValue; + } + if((surfy + surfh) > target_surface->height) { + return BadValue; + } + /* Make sure surfaces match */ + if(target_surface->width != source_surface->width) { + return BadValue; + } + if(target_surface->height != source_surface->height) { + return BadValue; + } + + /* Lock For DMA */ + I810_LOCK(pI810XvMC,0); + + /* Allocate DMA buffer */ + pDMA = i810_get_free_buffer(pI810XvMC); + data = pDMA->address; + + /* Copy Y data first */ + /* SOURCE_COPY_BLT */ + *data++ = (2<<29) | (0x43<<22) | 0x4; + *data++ = (0xcc<<16) | (1<<26) | (1<<privTarget->pitch); + *data++ = (target_surface->height<<16) | target_surface->width; + *data++ = privTarget->offset + privTarget->offsets[0]; + *data++ = (1<<privSource->pitch); + *data++ = privSource->offset + privSource->offsets[0]; + + /* Select Context 1 for loading */ + *data++ = CMD_FLUSH; + *data++ = (5<<23) | (1<<17) | (1<<8); + *data++ = CMD_FLUSH; + + /* Load Palette */ + *data++ = MAP_PALETTE_LOAD; + /* 16 levels of alpha for each Y */ + switch(subpicture->xvimage_id) { + case FOURCC_IA44: + for(i=0; i<16; i++) { + for(j=0; j<16; j++) { + *data++ = (j<<12) | (j<<8) | privSubpicture->palette[0][i]; + } + } + break; + case FOURCC_AI44: + for(i=0; i<16; i++) { + for(j=0; j<16; j++) { + *data++ = (i<<12) | (i<<8) | privSubpicture->palette[0][j]; + } + } + break; + } + /* TARGET */ + /* *data++ = CMD_FLUSH; */ + /* *data++ = BOOLEAN_ENA_2; */ + *data++ = CMD_FLUSH; + *data++ = DEST_BUFFER_INFO; + *data++ = privTarget->dbi1y; + *data++ = DEST_BUFFER_VAR; + *data++ = privTarget->dbv1; + + /* ALPHA */ + *data++ = CMD_MAP_INFO; + *data++ = privSubpicture->mi1; + *data++ = privSubpicture->mi2; + *data++ = privSubpicture->mi3; + + *data++ = VERTEX_FORMAT | (1<<8) | (3<<1); + *data++ = BOOLEAN_ENA_1; + *data++ = SRC_DEST_BLEND_MONO | (0x940); + /* Map Filter */ + *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (0x224); + + /* Use context 1 */ + *data++ = CMD_FLUSH; + *data++ = (5<<23) | (1<<16) | 1; + *data++ = CMD_FLUSH; + + /* Drawing Rect Info */ + *data++ = DRAWING_RECT_INFO; + *data++ = 0x0; + *data++ = 0x0; + *data++ = 0x0; + *data++ = 0x0; + *data++ = 0x0; + + /* GFXPRIMITIVE RECTANGLE */ + *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11; + /* Bottom Right Vertex */ + *(float *)data++ = (float) (surfx + surfw); + *(float *)data++ = (float) (surfy + surfh); + *(float *)data++ = (float) (subx + subw); + *(float *)data++ = (float) (suby + subh); + /* Bottom Left Vertex */ + *(float *)data++ = (float) surfx; + *(float *)data++ = (float) (surfy + surfh); + *(float *)data++ = (float) subx; + *(float *)data++ = (float) (suby + subh); + /* Top Left Vertex */ + *(float *)data++ = (float) surfx; + *(float *)data++ = (float) surfy; + *(float *)data++ = (float) subx; + *(float *)data++ = (float) suby; + + /* Load and Use Context 0 */ + *data++ = CMD_FLUSH; + *data++ = (5<<23) | (1<<17) | (1<<16); + *data++ = CMD_FLUSH; + + /* U data */ + /* SOURCE_COPY_BLT */ + *data++ = (2<<29) | (0x43<<22) | 0x4; + *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1)); + *data++ = (target_surface->height<<15) | (target_surface->width>>1); + *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[1]; + *data++ = (1<<(privSource->pitch - 1)); + *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[1]; + + /* Context 1 select */ + *data++ = CMD_FLUSH; + *data++ = (5<<23) | (1<<17) | (1<<8); + *data++ = CMD_FLUSH; + /* ALPHA PALETTE */ + *data++ = MAP_PALETTE_LOAD; + /* 16 levels of alpha for each Y */ + switch(subpicture->xvimage_id) { + case FOURCC_IA44: + for(i=0; i<16; i++) { + for(j=0; j<16; j++) { + *data++ = (j<<12) | (j<<8) | privSubpicture->palette[2][i]; + } + } + break; + case FOURCC_AI44: + for(i=0; i<16; i++) { + for(j=0; j<16; j++) { + *data++ = (i<<12) | (i<<8) | privSubpicture->palette[2][j]; + } + } + break; + } + /* TARGET */ + *data++ = CMD_FLUSH; + *data++ = BOOLEAN_ENA_2; + *data++ = CMD_FLUSH; + *data++ = DEST_BUFFER_INFO; + *data++ = privTarget->dbi1u; + *data++ = DEST_BUFFER_VAR; + *data++ = privTarget->dbv1; + + /* ALPHA */ + *data++ = CMD_MAP_INFO; + *data++ = privSubpicture->mi1; + *data++ = privSubpicture->mi2; + *data++ = privSubpicture->mi3; + + *data++ = VERTEX_FORMAT | (1<<8) | (3<<1); + *data++ = BOOLEAN_ENA_1; + *data++ = SRC_DEST_BLEND_MONO | (0x940); + /* Map Filter */ + *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224); + + /* Use context 1 */ + *data++ = CMD_FLUSH; + *data++ = (5<<23) | (1<<16) | 1; + *data++ = CMD_FLUSH; + + /* Drawing Rect Info */ + *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3; + *data++ = 0; + *data++ = 0; + *data++ = 0; + *data++ = 0; + *data++ = 0; + + /* Rectangle */ + *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11; + /* Bottom Right */ + *(float *)data++ = (float) ((surfx + surfw)>>1); + *(float *)data++ = (float) ((surfy + surfh)>>1); + *(float *)data++ = (float) subx + subw; + *(float *)data++ = (float) suby + subh; + /* Bottom Left */ + *(float *)data++ = (float) (surfx>>1); + *(float *)data++ = (float) ((surfy + surfh)>>1); + *(float *)data++ = (float) subx; + *(float *)data++ = (float) suby + subh; + /* Top Left */ + *(float *)data++ = (float) (surfx>>1); + *(float *)data++ = (float) (surfy>>1); + *(float *)data++ = (float) subx; + *(float *)data++ = (float) suby; + + /* Load and Use Context 0 */ + *data++ = CMD_FLUSH; + *data++ = (5<<23) | (1<<17) | (1<<16); + *data++ = CMD_FLUSH; + + /* V data */ + /* SOURCE_COPY_BLT */ + *data++ = (2<<29) | (0x43<<22) | 0x4; + *data++ = (0xcc<<16) | (1<<26) | (1<<(privTarget->pitch - 1)); + *data++ = (target_surface->height<<15) | (target_surface->width>>1); + *data++ = (unsigned long)privTarget->offset + (unsigned long)privTarget->offsets[2]; + *data++ = (1<<(privSource->pitch - 1)); + *data++ = (unsigned long)privSource->offset + (unsigned long)privSource->offsets[2]; + + /* Context 1 select */ + *data++ = CMD_FLUSH; + *data++ = (5<<23) | (1<<17) | (1<<8); + *data++ = CMD_FLUSH; + + /* ALPHA PALETTE */ + *data++ = MAP_PALETTE_LOAD; + /* 16 levels of alpha for each Y */ + switch(subpicture->xvimage_id) { + case FOURCC_IA44: + for(i=0; i<16; i++) { + for(j=0; j<16; j++) { + *data++ = (j<<12) | (j<<8) | privSubpicture->palette[1][i]; + } + } + break; + case FOURCC_AI44: + for(i=0; i<16; i++) { + for(j=0; j<16; j++) { + *data++ = (i<<12) | (i<<8) | privSubpicture->palette[1][j]; + } + } + break; + } + /* TARGET */ + *data++ = CMD_FLUSH; + *data++ = BOOLEAN_ENA_2; + *data++ = CMD_FLUSH; + *data++ = DEST_BUFFER_INFO; + *data++ = privTarget->dbi1v; + *data++ = DEST_BUFFER_VAR; + *data++ = privTarget->dbv1; + + /* ALPHA */ + *data++ = CMD_MAP_INFO; + *data++ = privSubpicture->mi1; + *data++ = privSubpicture->mi2; + *data++ = privSubpicture->mi3; + + *data++ = VERTEX_FORMAT | (1<<8) | (3<<1); + *data++ = BOOLEAN_ENA_1; + *data++ = SRC_DEST_BLEND_MONO | (0x940); + /* Map Filter */ + *data++ = (3<<29) | (0x1c<<24) | (2<<19) | (1<<16) | (0x224); + + /* Use context 1 */ + *data++ = CMD_FLUSH; + *data++ = (5<<23) | (1<<16) | 1; + *data++ = CMD_FLUSH; + + /* Drawing Rect Info */ + *data++ = (3<<29) | (0x1d<<24) | (0x80<<16) | 3; + *data++ = 0; + *data++ = 0; + *data++ = 0; + *data++ = 0; + *data++ = 0; + + /* Rectangle */ + *data++ = (3<<29) | (0x1f<<24) | (0x7<<18) | 11; + /* Bottom Right */ + *(float *)data++ = (float) ((surfx + surfw)>>1); + *(float *)data++ = (float) ((surfy + surfh)>>1); + *(float *)data++ = (float) subx + subw; + *(float *)data++ = (float) suby + subh; + /* Bottom Left */ + *(float *)data++ = (float) (surfx>>1); + *(float *)data++ = (float) ((surfy + surfh)>>1); + *(float *)data++ = (float) subx; + *(float *)data++ = (float) suby + subh; + /* Top Left */ + *(float *)data++ = (float) (surfx>>1); + *(float *)data++ = (float) (surfy>>1); + *(float *)data++ = (float) subx; + *(float *)data++ = (float) suby; + + /* Load and Use Context 0 */ + *data++ = CMD_FLUSH; + *data++ = (5<<23) | (1<<17) | (1<<16); + *data++ = CMD_FLUSH; + + + /* Dispatch */ + pDMA->used = (unsigned long)data - (unsigned long)pDMA->address; + mc.idx = pDMA->idx; + mc.used = pDMA->used; + mc.last_render = ++pI810XvMC->last_render; + privTarget->last_render = pI810XvMC->last_render; + I810_MC(pI810XvMC,mc); + + I810_UNLOCK(pI810XvMC); + return Success; +} + + + +/*************************************************************************** +// Function: XvMCSyncSubpicture +// Description: This function blocks until all composite/clear requests on +// the subpicture have been complete. +// Arguments: +// display - Connection to the X server. +// subpicture - The subpicture to synchronize +// +// Returns: Status +***************************************************************************/ +_X_EXPORT Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture) { + Status ret; + int stat=0; + do { + ret = XvMCGetSubpictureStatus(display,subpicture,&stat); + }while(!ret && (stat & XVMC_RENDERING)); + return ret; +} + + + +/*************************************************************************** +// Function: XvMCFlushSubpicture +// Description: This function commits pending composite/clear requests to +// ensure that they will be completed in a finite amount of +// time. +// Arguments: +// display - Connection to the X server. +// subpicture - The subpicture whos compsiting should be flushed +// +// Returns: Status +// NOTES: i810 always dispatches commands so flush is a no-op +***************************************************************************/ +_X_EXPORT Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture) { + if(display == NULL) { + return BadValue; + } + if(subpicture == NULL) { + return (error_base + XvMCBadSubpicture); + } + + return Success; +} + + + +/*************************************************************************** +// Function: XvMCGetSubpictureStatus +// Description: This function gets the current status of a subpicture +// +// Arguments: +// display - Connection to the X server. +// subpicture - The subpicture whos status is being queried +// stat - The status of the subpicture. It can be any of the following +// OR'd together: +// XVMC_RENDERING - Last composite or clear request not completed +// XVMC_DISPLAYING - Suppicture currently being displayed. +// +// Returns: Status +// Notes: i810 always blends into a third surface so the subpicture is +// never actually displaying, only a copy of it is displaying. We only +// have to worry about the rendering case. +***************************************************************************/ +_X_EXPORT Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture, + int *stat) { + + i810XvMCSubpicture *privSubpicture; + i810XvMCContext *pI810XvMC; + + if((display == NULL) || (stat == NULL)) { + return BadValue; + } + if((subpicture == NULL) || (subpicture->privData == NULL)) { + return (error_base + XvMCBadSubpicture); + } + *stat = 0; + privSubpicture = (i810XvMCSubpicture *)subpicture->privData; + + pI810XvMC = (i810XvMCContext *)privSubpicture->privContext; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadSubpicture); + } + + I810_LOCK(pI810XvMC,0); + + if(privSubpicture->last_render && + (privSubpicture->last_render > GET_RSTATUS(pI810XvMC))) { + *stat |= XVMC_RENDERING; + } + I810_UNLOCK(pI810XvMC); + + return Success; +} + +#define NUM_XVMC_ATTRIBUTES 4 +static XvAttribute I810_XVMC_ATTRIBUTES[] = { + {XvGettable | XvSettable, 0, 0xffffff, "XV_COLORKEY"}, + {XvGettable | XvSettable, -127, +127, "XV_BRIGHTNESS"}, + {XvGettable | XvSettable, 0, 0x1ff, "XV_CONTRAST"}, + {XvGettable | XvSettable, 0, 0x3ff, "XV_SATURATION"} +}; + + +/*************************************************************************** +// Function: XvMCQueryAttributes +// Description: An array of XvAttributes of size "number" is returned by +// this function. If there are no attributes, NULL is returned and number +// is set to 0. The array may be freed with xfree(). +// +// Arguments: +// display - Connection to the X server. +// context - The context whos attributes we are querying. +// number - The number of returned atoms. +// +// Returns: +// An array of XvAttributes. +// Notes: +// For i810 we support these Attributes: +// XV_COLORKEY: The colorkey value, initialized from the Xv value at +// context creation time. +// XV_BRIGHTNESS +// XV_CONTRAST +// XV_SATURATION +***************************************************************************/ +_X_EXPORT XvAttribute *XvMCQueryAttributes(Display *display, XvMCContext *context, + int *number) { + i810XvMCContext *pI810XvMC; + XvAttribute *attributes; + + if(number == NULL) { + return NULL; + } + if(display == NULL) { + *number = 0; + return NULL; + } + if(context == NULL) { + *number = 0; + return NULL; + } + pI810XvMC = context->privData; + if(pI810XvMC == NULL) { + *number = 0; + return NULL; + } + + attributes = (XvAttribute *)malloc(NUM_XVMC_ATTRIBUTES * + sizeof(XvAttribute)); + if(attributes == NULL) { + *number = 0; + return NULL; + } + + memcpy(attributes,I810_XVMC_ATTRIBUTES,(NUM_XVMC_ATTRIBUTES * + sizeof(XvAttribute))); + + *number = NUM_XVMC_ATTRIBUTES; + return attributes; +} + +/*************************************************************************** +// Function: XvMCSetAttribute +// Description: This function sets a context-specific attribute. +// +// Arguments: +// display - Connection to the X server. +// context - The context whos attributes we are querying. +// attribute - The X atom of the attribute to be changed. +// value - The new value for the attribute. +// +// Returns: +// Status +// Notes: +// For i810 we support these Attributes: +// XV_COLORKEY: The colorkey value, initialized from the Xv value at +// context creation time. +// XV_BRIGHTNESS +// XV_CONTRAST +// XV_SATURATION +***************************************************************************/ +_X_EXPORT Status XvMCSetAttribute(Display *display, XvMCContext *context, + Atom attribute, int value) { + i810XvMCContext *pI810XvMC; + + if(display == NULL) { + return BadValue; + } + if(context == NULL) { + return (error_base + XvMCBadContext); + } + pI810XvMC = context->privData; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadContext); + } + + if(attribute == pI810XvMC->xv_colorkey) { + if((value < I810_XVMC_ATTRIBUTES[0].min_value) || + (value > I810_XVMC_ATTRIBUTES[0].max_value)) { + return BadValue; + } + pI810XvMC->colorkey = value; + return Success; + } + if(attribute == pI810XvMC->xv_brightness) { + if((value < I810_XVMC_ATTRIBUTES[1].min_value) || + (value > I810_XVMC_ATTRIBUTES[1].max_value)) { + return BadValue; + } + pI810XvMC->brightness = value; + return Success; + } + if(attribute == pI810XvMC->xv_saturation) { + if((value < I810_XVMC_ATTRIBUTES[2].min_value) || + (value > I810_XVMC_ATTRIBUTES[2].max_value)) { + return BadValue; + } + pI810XvMC->saturation = value; + return Success; + } + if(attribute == pI810XvMC->xv_contrast) { + if((value < I810_XVMC_ATTRIBUTES[3].min_value) || + (value > I810_XVMC_ATTRIBUTES[3].max_value)) { + return BadValue; + } + pI810XvMC->contrast = value; + return Success; + } + return BadValue; +} + +/*************************************************************************** +// Function: XvMCGetAttribute +// Description: This function queries a context-specific attribute and +// returns the value. +// +// Arguments: +// display - Connection to the X server. +// context - The context whos attributes we are querying. +// attribute - The X atom of the attribute to be queried +// value - The returned attribute value +// +// Returns: +// Status +// Notes: +// For i810 we support these Attributes: +// XV_COLORKEY: The colorkey value, initialized from the Xv value at +// context creation time. +// XV_BRIGHTNESS +// XV_CONTRAST +// XV_SATURATION +***************************************************************************/ +_X_EXPORT Status XvMCGetAttribute(Display *display, XvMCContext *context, + Atom attribute, int *value) { + i810XvMCContext *pI810XvMC; + + if(display == NULL) { + return BadValue; + } + if(context == NULL) { + return (error_base + XvMCBadContext); + } + pI810XvMC = context->privData; + if(pI810XvMC == NULL) { + return (error_base + XvMCBadContext); + } + if(value == NULL) { + return BadValue; + } + + if(attribute == pI810XvMC->xv_colorkey) { + *value = pI810XvMC->colorkey; + return Success; + } + if(attribute == pI810XvMC->xv_brightness) { + *value = pI810XvMC->brightness; + return Success; + } + if(attribute == pI810XvMC->xv_saturation) { + *value = pI810XvMC->saturation; + return Success; + } + if(attribute == pI810XvMC->xv_contrast) { + *value = pI810XvMC->contrast; + return Success; + } + return BadValue; +} + + + + diff --git a/src/legacy/i810/xvmc/I810XvMC.h b/src/legacy/i810/xvmc/I810XvMC.h new file mode 100644 index 00000000..9e311473 --- /dev/null +++ b/src/legacy/i810/xvmc/I810XvMC.h @@ -0,0 +1,366 @@ +/*************************************************************************** + +Copyright 2001 Intel Corporation. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +/*************************************************************************** + * libI810XvMC.h: MC Driver i810 includes + * + * Authors: + * Matt Sottek <matthew.j.sottek@intel.com> + * + * + ***************************************************************************/ + + +#ifndef I810XVMC_H +#define I810XVMC_H + +/* #define XVMC_DEBUG(x) do {x; }while(0); */ +#define XVMC_DEBUG(x) + +#include <stdint.h> +#include "xf86drm.h" +#include "../i810_common.h" +#include <X11/Xlibint.h> + + +/*************************************************************************** +// i810OverlayRec: Structure that is used to reference the overlay +// register memory. A i810OverlayRecPtr is set to the address of the +// allocated overlay registers. +***************************************************************************/ +typedef struct _i810OverlayRec { + unsigned int OBUF_0Y; + unsigned int OBUF_1Y; + unsigned int OBUF_0U; + unsigned int OBUF_0V; + unsigned int OBUF_1U; + unsigned int OBUF_1V; + unsigned int OV0STRIDE; + unsigned int YRGB_VPH; + unsigned int UV_VPH; + unsigned int HORZ_PH; + unsigned int INIT_PH; + unsigned int DWINPOS; + unsigned int DWINSZ; + unsigned int SWID; + unsigned int SWIDQW; + unsigned int SHEIGHT; + unsigned int YRGBSCALE; + unsigned int UVSCALE; + unsigned int OV0CLRC0; + unsigned int OV0CLRC1; + unsigned int DCLRKV; + unsigned int DCLRKM; + unsigned int SCLRKVH; + unsigned int SCLRKVL; + unsigned int SCLRKM; + unsigned int OV0CONF; + unsigned int OV0CMD; +} i810OverlayRec, *i810OverlayRecPtr; + + +/*************************************************************************** +// i810XvMCDrmMap: Holds the data about the DRM maps +***************************************************************************/ +typedef struct _i810XvMCDrmMap { + drm_handle_t offset; + drmAddress address; + unsigned int size; +} i810XvMCDrmMap, *i810XvMCDrmMapPtr; + +/*************************************************************************** +// i810XvMCContext: Private Context data referenced via the privData +// pointer in the XvMCContext structure. +***************************************************************************/ +typedef struct _i810XvMCContext { + int fd; /* File descriptor for /dev/dri */ + i810XvMCDrmMap overlay; + i810XvMCDrmMap surfaces; + drmBufMapPtr dmabufs; /* Data structure to hold available dma buffers */ + drm_context_t drmcontext; + unsigned int last_render; + unsigned int last_flip; + unsigned short ref; + unsigned short current; + int lock; /* Lightweight lock to avoid locking twice */ + char busIdString[10]; /* PCI:0:1:0 or PCI:0:2:0 */ + i810OverlayRecPtr oregs; + unsigned int dual_prime; /* Flag to identify when dual prime is in use. */ + unsigned int fb_base; + Atom xv_colorkey; + Atom xv_brightness; + Atom xv_contrast; + Atom xv_saturation; + int brightness; + int saturation; + int contrast; + int colorkey; +} i810XvMCContext; + +/*************************************************************************** +// i810XvMCSurface: Private data structure for each XvMCSurface. This +// structure is referenced by the privData pointer in the XvMCSurface +// structure. +***************************************************************************/ +typedef struct _i810XvMCSurface { + unsigned int pitch; + unsigned int dbi1y; /* Destination buffer info command word 1 for Y */ + unsigned int dbi1u; /* Destination buffer info command word 1 for U */ + unsigned int dbi1v; /* Destination buffer info command word 1 for V */ + unsigned int dbv1; /* Destination buffer variables command word 1 */ + unsigned int mi1y; /* Map Info command word 1 (Minus bit 28) for Y */ + unsigned int mi1u; /* Map Info command word 1 (Minus bit 28) for U */ + unsigned int mi1v; /* Map Info command word 1 (Minus bit 28) for V */ + unsigned int mi2y; /* Map info command word 2 for y */ + unsigned int mi2u; /* Map info command word 2 for y */ + unsigned int mi2v; /* Map info command word 2 for y */ + unsigned int mi3y; /* Map info command word 3 */ + unsigned int mi3u; /* Map info command word 3 */ + unsigned int mi3v; /* Map info command word 3 */ + unsigned int last_render; + unsigned int last_flip; + unsigned int second_field; /* Flags a surface that is only half done */ + drmAddress data; + drm_handle_t offset; + unsigned int offsets[3]; + i810XvMCContext *privContext; +} i810XvMCSurface; + +/*************************************************************************** +// i810XvMCSubpicture: Private data structure for each XvMCSubpicture. This +// structure is referenced by the privData pointer in the XvMCSubpicture +// structure. +***************************************************************************/ +typedef struct _i810XvMCSubpicture { + unsigned int pitch; + unsigned int dbi1; /* Destination buffer info command word 1 */ + unsigned int dbv1; /* Destination buffer variables command word */ + unsigned int mi1; /* Map Info command word 1 (Minus bit 28) */ + unsigned int mi2; /* Map info command word 2 */ + unsigned int mi3; /* Map info command word 3 */ + unsigned int last_render; + unsigned int last_flip; + drmAddress data; + drm_handle_t offset; + unsigned int offsets[1]; + unsigned char palette[3][16]; + i810XvMCContext *privContext; +} i810XvMCSubpicture; + +typedef struct _Box { + int x1,y1,x2,y2; +} Box, *BoxPtr; + +/*************************************************************************** +// drm_i810_overlay_t: Structure returned by overlay info ioctl. +// NOTE: If you change this structure you will have to change the equiv. +// structure in the kernel. +***************************************************************************/ +typedef struct _drm_i810_overlay_t { + unsigned int offset; + unsigned int physical; +} drm_i810_overlay_t; + +/*************************************************************************** +// drm_i810_dma_t: Structure used by dma allocation ioctl. +// NOTE: If you change this structure you will have to change the equiv. +// structure in the kernel. +***************************************************************************/ +typedef struct _drm_i810_dma { + void *virtual; + int request_idx; + int request_size; + int granted; +} drm_i810_dma_t; + +/*************************************************************************** +// drm_i810_mc_t: Structure used by mc dispatch ioctl. +// NOTE: If you change this structure you will have to change the equiv. +// structure in the kernel. +***************************************************************************/ +typedef struct _drm_i810_mc { + int idx; /* buffer index */ + int used; /* nr bytes in use */ + int num_blocks; /* number of GFXBlocks */ + int *length; /* List of lengths for GFXBlocks */ + unsigned int last_render; /* Last render request */ +} drm_i810_mc_t; + +/* Subpicture fourcc */ +#define FOURCC_IA44 0x34344149 + +/* Static Parameters */ +#define I810_XVMC_MAXWIDTH 720 +#define I810_XVMC_MAXHEIGHT 576 +#define I810_DEFAULT16_COLORKEY 31 +#define I810_DMA_BUF_NR 256 + +/* COMMANDS */ +#define CMD_FLUSH ((4<<23) | 0x1) +#define BOOLEAN_ENA_1 ((3<<29) | (3<<24) | (3<<2)) +#define BOOLEAN_ENA_2 ((3<<29) | (4<<24) | (3<<16) | (1<<3) | (1<<2)) +#define DEST_BUFFER_INFO (0x15<<23) +#define DEST_BUFFER_VAR ((0x3<<29) | (0x1d<<24) | (0x85<<16)) +#define DRAWING_RECT_INFO ((3<<29) | (0x1d<<24) | (0x80<<16) | 3) +#define GFXBLOCK ((0x3<<29) | (0x1e<<24)) +#define CMD_MAP_INFO ((0x3<<29) | (0x1d<<24) | 0x2) +#define MAP_PALETTE_LOAD ((3<<29) | (0x1d<<24) | (0x82<<16) | 0xff) +#define VERTEX_FORMAT ((3<<29) | (0x5<<24)) +#define SRC_DEST_BLEND_MONO ((3<<29) | (8<<24)) + +/* Bit Patterns */ + +/* + * OV0CMD - Overlay Command Register + */ +#define VERTICAL_CHROMINANCE_FILTER 0x70000000 +#define VC_SCALING_OFF 0x00000000 +#define VC_LINE_REPLICATION 0x10000000 +#define VC_UP_INTERPOLATION 0x20000000 +#define VC_PIXEL_DROPPING 0x50000000 +#define VC_DOWN_INTERPOLATION 0x60000000 +#define VERTICAL_LUMINANCE_FILTER 0x0E000000 +#define VL_SCALING_OFF 0x00000000 +#define VL_LINE_REPLICATION 0x02000000 +#define VL_UP_INTERPOLATION 0x04000000 +#define VL_PIXEL_DROPPING 0x0A000000 +#define VL_DOWN_INTERPOLATION 0x0C000000 +#define HORIZONTAL_CHROMINANCE_FILTER 0x01C00000 +#define HC_SCALING_OFF 0x00000000 +#define HC_LINE_REPLICATION 0x00400000 +#define HC_UP_INTERPOLATION 0x00800000 +#define HC_PIXEL_DROPPING 0x01400000 +#define HC_DOWN_INTERPOLATION 0x01800000 +#define HORIZONTAL_LUMINANCE_FILTER 0x00380000 +#define HL_SCALING_OFF 0x00000000 +#define HL_LINE_REPLICATION 0x00080000 +#define HL_UP_INTERPOLATION 0x00100000 +#define HL_PIXEL_DROPPING 0x00280000 +#define HL_DOWN_INTERPOLATION 0x00300000 + +#define Y_ADJUST 0x00010000 +#define OV_BYTE_ORDER 0x0000C000 +#define UV_SWAP 0x00004000 +#define Y_SWAP 0x00008000 +#define Y_AND_UV_SWAP 0x0000C000 +#define SOURCE_FORMAT 0x00003C00 +#define RGB_555 0x00000800 +#define RGB_565 0x00000C00 +#define YUV_422 0x00002000 +#define YUV_411 0x00002400 +#define YUV_420 0x00003000 +#define YUV_410 0x00003800 +#define VERTICAL_PHASE_BOTH 0x00000020 +#define FLIP_TYPE_FIELD 0x00000020 +#define FLIP_TYPE_FRAME 0x00000000 +#define BUFFER_AND_FIELD 0x00000006 +#define BUFFER0_FIELD0 0x00000000 +#define BUFFER0_FIELD1 0x00000002 +#define BUFFER1_FIELD0 0x00000004 +#define BUFFER1_FIELD1 0x00000006 +#define OVERLAY_ENABLE 0x00000001 + +/* + * DOV0STA - Display/Overlay 0 Status Register + */ +#define DOV0STA 0x30008 +#define OV0ADD 0x30000 +#define MINUV_SCALE 0x1 + +#define RGB16ToColorKey(c) \ + (((c & 0xF800) << 8) | ((c & 0x07E0) << 5) | ((c & 0x001F) << 3)) + +/* Locking Macros lightweight lock used to prevent relocking */ +#define I810_LOCK(c,f) \ + if(!c->lock) { \ + drmGetLock(c->fd, c->drmcontext, f); \ + } \ + c->lock++; + +#define I810_UNLOCK(c) \ + c->lock--; \ + if(!c->lock) { \ + drmUnlock(c->fd, c->drmcontext); \ + } + +/* + Block until the passed in value (n) is the active + buffer on the overlay. +*/ +#define BLOCK_OVERLAY(c,n) \ + do { \ + int temp,i=0; \ + while(i < 100000) { \ + temp = GET_FSTATUS(c); \ + if(((temp & (1<<20))>>20) == n) { \ + break; \ + } \ + usleep(10); \ + } \ + if(i == 100000) { \ + printf("Overlay Lockup.\n"); \ + return BadAlloc; \ + } \ + }while(0); + +#define OVERLAY_INFO(c,i) drmCommandRead(c->fd, DRM_I810_OV0INFO, &i, sizeof(i)) +#define OVERLAY_FLIP(c) drmCommandNone(c->fd, DRM_I810_OV0FLIP) +#define GET_FSTATUS(c) drmCommandNone(c->fd, DRM_I810_FSTATUS) +#define I810_MC(c,mc) drmCommandWrite(c->fd, DRM_I810_MC, &mc, sizeof(mc)) +#define GET_RSTATUS(c) drmCommandNone(c->fd, DRM_I810_RSTATUS) +#define GET_BUFFER(c,dma) drmCommandWriteRead(c->fd, DRM_I810_GETBUF, &dma, sizeof(drmI810DMA)) +#define FLUSH(c) drmCommandNone(c->fd, DRM_I810_FLUSH) + +/* + Definitions for temporary wire protocol hooks to be replaced + when a HW independent libXvMC is created. +*/ +extern Status _xvmc_create_context(Display *dpy, XvMCContext *context, + int *priv_count, uint **priv_data); + +extern Status _xvmc_destroy_context(Display *dpy, XvMCContext *context); + +extern Status _xvmc_create_surface(Display *dpy, XvMCContext *context, + XvMCSurface *surface, int *priv_count, + uint **priv_data); + +extern Status _xvmc_destroy_surface(Display *dpy, XvMCSurface *surface); + +extern Status _xvmc_create_subpicture(Display *dpy, XvMCContext *context, + XvMCSubpicture *subpicture, + int *priv_count, uint **priv_data); + +extern Status _xvmc_destroy_subpicture(Display *dpy, + XvMCSubpicture *subpicture); + +/* + Prototypes +*/ +drmBufPtr i810_get_free_buffer(i810XvMCContext *pI810XvMC); +void i810_free_privContext(i810XvMCContext *pI810XvMC); +void dp(unsigned int *address, unsigned int i); + +#endif diff --git a/src/legacy/i810/xvmc/Makefile.am b/src/legacy/i810/xvmc/Makefile.am new file mode 100644 index 00000000..69add1e4 --- /dev/null +++ b/src/legacy/i810/xvmc/Makefile.am @@ -0,0 +1,11 @@ +if XVMC +lib_LTLIBRARIES=libI810XvMC.la +endif + +libI810XvMC_la_SOURCES = I810XvMC.c \ + I810XvMC.h + +libI810XvMC_la_CFLAGS = @CWARNFLAGS@ @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \ + -DTRUE=1 -DFALSE=0 +libI810XvMC_la_LDFLAGS = -version-number 1:0:0 +libI810XvMC_la_LIBADD = @DRI_LIBS@ @DRM_LIBS@ @XVMCLIB_LIBS@ |