diff options
author | Alan Hourihane <alanh@fairlite.demon.co.uk> | 2005-01-06 14:43:14 +0000 |
---|---|---|
committer | Alan Hourihane <alanh@fairlite.demon.co.uk> | 2005-01-06 14:43:14 +0000 |
commit | 076c5116ae5eda1822da70184cbcc8942b470541 (patch) | |
tree | ee07fbc884b3374284d12a7dbf7c3b30a7cb0413 /src | |
parent | edb9b6fde0948bb1121a8456500ef9f55f734376 (diff) |
Add:
- Intel i915GM support to 2D DDX and 3D Mesa drivers.
- PanelID identification
- DRI suspend/resume support
- Detection of monitor changes on VT switches
- Support custom video modes if available in the Video BIOS
- 3D enhancements:
* GL_ARB_texture_cube_map
* GL_EXT_blend_equation_separate
* GL_ATI_blend_equation_separate
* GL_ARB_point_parameters
* GL_NV_blend_square
* GL_EXT_cull_vertex
* GL_ARB_depth_texture
* GL_SGIX_depth_texture
* GL_ARB_shadow
* GL_EXT_shadow_funcs
* GL_3DFX_texture_compression_FXT1
By Tungsten Graphics, Keith Whitwell & Alan Hourihane.
Diffstat (limited to 'src')
-rw-r--r-- | src/common.h | 8 | ||||
-rw-r--r-- | src/i810_driver.c | 4 | ||||
-rw-r--r-- | src/i830.h | 6 | ||||
-rw-r--r-- | src/i830_common.h | 3 | ||||
-rw-r--r-- | src/i830_cursor.c | 2 | ||||
-rw-r--r-- | src/i830_dri.c | 58 | ||||
-rw-r--r-- | src/i830_driver.c | 525 | ||||
-rw-r--r-- | src/i830_memory.c | 8 | ||||
-rw-r--r-- | src/i830_modes.c | 712 | ||||
-rw-r--r-- | src/i830_video.c | 80 |
10 files changed, 1317 insertions, 89 deletions
diff --git a/src/common.h b/src/common.h index 961da215..62854455 100644 --- a/src/common.h +++ b/src/common.h @@ -305,6 +305,11 @@ extern int I810_DEBUG; #define PCI_CHIP_I915_G_BRIDGE 0x2580 #endif +#ifndef PCI_CHIP_I915_GM +#define PCI_CHIP_I915_GM 0x2592 +#define PCI_CHIP_I915_GM_BRIDGE 0x2590 +#endif + #define IS_I810(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I810 || \ pI810->PciInfo->chipType == PCI_CHIP_I810_DC100 || \ pI810->PciInfo->chipType == PCI_CHIP_I810_E) @@ -314,8 +319,9 @@ extern int I810_DEBUG; #define IS_I85X(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I855_GM) #define IS_I865G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I865_G) #define IS_I915G(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_G) +#define IS_I915GM(pI810) (pI810->PciInfo->chipType == PCI_CHIP_I915_GM) -#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810)) +#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810)) #define GTT_PAGE_SIZE KB(4) #define ROUND_TO(x, y) (((x) + (y) - 1) / (y) * (y)) diff --git a/src/i810_driver.c b/src/i810_driver.c index b4732951..f60f7609 100644 --- a/src/i810_driver.c +++ b/src/i810_driver.c @@ -129,6 +129,7 @@ static SymTabRec I810Chipsets[] = { {PCI_CHIP_I855_GM, "852GM/855GM"}, {PCI_CHIP_I865_G, "865G"}, {PCI_CHIP_I915_G, "915G"}, + {PCI_CHIP_I915_GM, "915GM"}, {-1, NULL} }; @@ -144,6 +145,7 @@ static PciChipsets I810PciChipsets[] = { {PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA}, {PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA}, {PCI_CHIP_I915_G, PCI_CHIP_I915_G, RES_SHARED_VGA}, + {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED } }; @@ -560,6 +562,7 @@ I810Probe(DriverPtr drv, int flags) case PCI_CHIP_I830_M: case PCI_CHIP_I855_GM: case PCI_CHIP_I915_G: + case PCI_CHIP_I915_GM: xf86SetEntitySharable(usedChips[i]); /* Allocate an entity private if necessary */ @@ -1805,7 +1808,6 @@ I810ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) { vgaHWPtr hwp; I810Ptr pI810; - vgaRegPtr pVga; hwp = VGAHWPTR(pScrn); pI810 = I810PTR(pScrn); @@ -390,6 +390,7 @@ extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags); extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn); extern Bool I830DRIScreenInit(ScreenPtr pScreen); extern Bool I830DRIDoMappings(ScreenPtr pScreen); +extern Bool I830DRIResume(ScreenPtr pScreen); extern void I830DRICloseScreen(ScreenPtr pScreen); extern Bool I830DRIFinishScreenInit(ScreenPtr pScreen); #endif @@ -423,6 +424,11 @@ extern void I830ReadAllRegisters(I830Ptr pI830, I830RegPtr i830Reg); extern void I830ChangeFrontbuffer(ScrnInfoPtr pScrn,int buffer); +extern DisplayModePtr i830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, + VbeInfoBlock *vbe, int modeTypes); +extern void i830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe); +extern void i830PrintModes(ScrnInfoPtr pScrn); + /* * 12288 is set as the maximum, chosen because it is enough for * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare. diff --git a/src/i830_common.h b/src/i830_common.h index c5167c11..a0a00ff4 100644 --- a/src/i830_common.h +++ b/src/i830_common.h @@ -55,7 +55,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. typedef struct { enum { I830_INIT_DMA = 0x01, - I830_CLEANUP_DMA = 0x02 + I830_CLEANUP_DMA = 0x02, + I830_RESUME_DMA = 0x03 } func; unsigned int mmio_offset; int sarea_priv_offset; diff --git a/src/i830_cursor.c b/src/i830_cursor.c index c5fe2b88..367aaf45 100644 --- a/src/i830_cursor.c +++ b/src/i830_cursor.c @@ -304,7 +304,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y) } /* have to upload the base for the new position */ - if (IS_I915G(pI830)) { + if (IS_I915G(pI830) || IS_I915GM(pI830)) { if (pI830->CursorIsARGB) OUTREG(CURSOR_A_BASE, pI830->CursorMemARGB->Physical); else diff --git a/src/i830_dri.c b/src/i830_dri.c index 25ce9a97..034b0960 100644 --- a/src/i830_dri.c +++ b/src/i830_dri.c @@ -163,6 +163,24 @@ I830InitDma(ScrnInfoPtr pScrn) } static Bool +I830ResumeDma(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + drmI830Init info; + + memset(&info, 0, sizeof(drmI830Init)); + info.func = I830_RESUME_DMA; + + if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT, + &info, sizeof(drmI830Init))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "I830 Dma Resume Failed\n"); + return FALSE; + } + + return TRUE; +} + +static Bool I830SetParam(ScrnInfoPtr pScrn, int param, int value) { I830Ptr pI830 = I830PTR(pScrn); @@ -510,7 +528,7 @@ I830DRIScreenInit(ScreenPtr pScreen) return FALSE; } - /* Check the i830 DRM versioning */ + /* Check the i915 DRM versioning */ { drmVersionPtr version; @@ -568,6 +586,9 @@ I830DRIScreenInit(ScreenPtr pScreen) drmFreeVersion(version); return FALSE; } + if (version->version_minor < 2) + xf86DrvMsg(pScreen->myNum, X_WARNING, + "Resume functionality not available with DRM < 1.2\n"); pI830->drmMinor = version->version_minor; drmFreeVersion(version); } @@ -742,6 +763,41 @@ I830DRIDoMappings(ScreenPtr pScreen) return TRUE; } +Bool +I830DRIResume(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + I830DRIPtr pI830DRI = (I830DRIPtr) pI830->pDRIInfo->devPrivate; + + DPRINTF(PFX, "I830DRIResume\n"); + + I830ResumeDma(pScrn); + + { + pI830DRI->irq = drmGetInterruptFromBusID(pI830->drmSubFD, + ((pciConfigPtr) pI830-> + PciInfo->thisCard)->busnum, + ((pciConfigPtr) pI830-> + PciInfo->thisCard)->devnum, + ((pciConfigPtr) pI830-> + PciInfo->thisCard)->funcnum); + + if (drmCtlInstHandler(pI830->drmSubFD, pI830DRI->irq)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failure adding irq handler\n"); + pI830DRI->irq = 0; + return FALSE; + } + else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "[drm] dma control initialized, using IRQ %d\n", + pI830DRI->irq); + } + + return FALSE; +} + void I830DRICloseScreen(ScreenPtr pScreen) { diff --git a/src/i830_driver.c b/src/i830_driver.c index 7ed65147..a8b27dff 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -185,6 +185,7 @@ static SymTabRec I830BIOSChipsets[] = { {PCI_CHIP_I855_GM, "852GM/855GM"}, {PCI_CHIP_I865_G, "865G"}, {PCI_CHIP_I915_G, "915G"}, + {PCI_CHIP_I915_GM, "915GM"}, {-1, NULL} }; @@ -194,6 +195,7 @@ static PciChipsets I830BIOSPciChipsets[] = { {PCI_CHIP_I855_GM, PCI_CHIP_I855_GM, RES_SHARED_VGA}, {PCI_CHIP_I865_G, PCI_CHIP_I865_G, RES_SHARED_VGA}, {PCI_CHIP_I915_G, PCI_CHIP_I915_G, RES_SHARED_VGA}, + {PCI_CHIP_I915_GM, PCI_CHIP_I915_GM, RES_SHARED_VGA}, {-1, -1, RES_UNDEFINED} }; @@ -429,6 +431,114 @@ GetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh, int *availRefresh) } #endif +struct panelid { + short hsize; + short vsize; + short fptype; + char redbpp; + char greenbpp; + char bluebpp; + char reservedbpp; + int rsvdoffscrnmemsize; + int rsvdoffscrnmemptr; + char reserved[14]; +}; + +static void +I830InterpretPanelID(int scrnIndex, unsigned char *tmp) +{ + ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; + struct panelid *block = (struct panelid *)tmp; + +#define PANEL_DEFAULT_HZ 60 + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "PanelID returned panel resolution : %dx%d\n", + block->hsize, block->vsize); + + /* If we get bogus values from this, don't accept it */ + if (block->hsize == 0 || block->vsize == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Bad Panel resolution - ignoring panelID\n"); + + return; + } + + /* If we have monitor timings then don't overwrite them */ + if (pScrn->monitor->nHsync > 0 && + pScrn->monitor->nVrefresh > 0) + return; + + /* With panels, we're always assuming a refresh of 60Hz */ + + pScrn->monitor->nHsync = 1; + pScrn->monitor->nVrefresh = 1; + + /* Give a little tolerance for the selected panel */ + pScrn->monitor->hsync[0].lo = (float)((PANEL_DEFAULT_HZ/1.05)*block->vsize)/1000; + pScrn->monitor->hsync[0].hi = (float)((PANEL_DEFAULT_HZ/0.95)*block->vsize)/1000; + pScrn->monitor->vrefresh[0].lo = (float)PANEL_DEFAULT_HZ; + pScrn->monitor->vrefresh[0].hi = (float)PANEL_DEFAULT_HZ; +} + +/* This should probably go into the VBE layer */ +static unsigned char * +vbeReadPanelID(vbeInfoPtr pVbe) +{ + int RealOff = pVbe->real_mode_base; + pointer page = pVbe->memory; + unsigned char *tmp = NULL; + int screen = pVbe->pInt10->scrnIndex; + + pVbe->pInt10->ax = 0x4F11; + pVbe->pInt10->bx = 0x01; + pVbe->pInt10->cx = 0; + pVbe->pInt10->dx = 0; + pVbe->pInt10->es = SEG_ADDR(RealOff); + pVbe->pInt10->di = SEG_OFF(RealOff); + pVbe->pInt10->num = 0x10; + + xf86ExecX86int10(pVbe->pInt10); + + if ((pVbe->pInt10->ax & 0xff) != 0x4f) { + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID invalid\n"); + goto error; + } + switch (pVbe->pInt10->ax & 0xff00) { + case 0x0: + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read successfully\n"); + tmp = (unsigned char *)xnfalloc(32); + memcpy(tmp,page,32); + break; + case 0x100: + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID read failed\n"); + break; + default: + xf86DrvMsgVerb(screen,X_INFO,3,"VESA VBE PanelID unknown failure %i\n", + pVbe->pInt10->ax & 0xff00); + break; + } + + error: + return tmp; +} + +static void +vbeDoPanelID(vbeInfoPtr pVbe) +{ + unsigned char *PanelID_data; + + if (!pVbe) return; + + PanelID_data = vbeReadPanelID(pVbe); + + if (!PanelID_data) + return; + + I830InterpretPanelID(pVbe->pInt10->scrnIndex, PanelID_data); +} + + static int SetRefreshRate(ScrnInfoPtr pScrn, int mode, int refresh) { @@ -650,12 +760,33 @@ SetDisplayDevices(ScrnInfoPtr pScrn, int devices) temp = INREG(SWF0); OUTREG(SWF0, (temp & ~(0xffff)) | (devices & 0xffff)); - if (GetDisplayDevices(pScrn) != devices) + /* Now try to program the registers directly if the BIOS failed. + * This currently only turns on the CRT, but should be made to handle + * SDVO, TV, LFP etc. etc. + */ + temp = INREG(ADPA); + temp &= ~0xc0000c00; + /* Turn on ADPA */ + if (devices & PIPE_CRT) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "BIOS call failed, turning ADPA on directly. Pipe A.\n"); + temp |= 0x80000000; + } + if ((devices >> 8) & PIPE_CRT) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "BIOS call failed, turning ADPA on directly. Pipe B.\n"); + temp |= 0xC0000000; + } + OUTREG(ADPA, temp); + + if (GetDisplayDevices(pScrn) != devices) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "SetDisplayDevices failed with devices 0x%x instead of 0x%x\n", GetDisplayDevices(pScrn), devices); + return FALSE; + } - return FALSE; + return TRUE; } static Bool @@ -915,9 +1046,10 @@ I830DetectDisplayDevice(ScrnInfoPtr pScrn) /* Check for active devices connected to each display pipe. */ for (n = 0; n < pI830->availablePipes; n++) { pipe = ((pI830->operatingDevices >> PIPE_SHIFT(n)) & PIPE_ACTIVE_MASK); - if (pipe) { + if (pipe) pI830->pipeEnabled[n] = TRUE; - } + else + pI830->pipeEnabled[n] = FALSE; } GetPipeSizes(pScrn); @@ -941,7 +1073,7 @@ I830DetectMemory(ScrnInfoPtr pScrn) * The GTT varying according the the FbMapSize and the popup is 4KB */ range = (pI830->FbMapSize / (1024*1024)) + 4; - if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830)) { + if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830) || IS_I915GM(pI830)) { switch (gmch_ctrl & I830_GMCH_GMS_MASK) { case I855_GMCH_GMS_STOLEN_1M: memsize = MB(1) - KB(range); @@ -959,11 +1091,11 @@ I830DetectMemory(ScrnInfoPtr pScrn) memsize = MB(32) - KB(range); break; case I915G_GMCH_GMS_STOLEN_48M: - if (IS_I915G(pI830)) + if (IS_I915G(pI830) || IS_I915GM(pI830)) memsize = MB(48) - KB(range); break; case I915G_GMCH_GMS_STOLEN_64M: - if (IS_I915G(pI830)) + if (IS_I915G(pI830) || IS_I915GM(pI830)) memsize = MB(64) - KB(range); break; } @@ -1170,12 +1302,12 @@ SaveBIOSMemSize(ScrnInfoPtr pScrn) * Original implementation by Christian Zietz in a stand-alone tool. */ static CARD32 -TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit) +TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize) { #define SIZE 0x10000 #define _855_IDOFFSET (-23) #define _845_IDOFFSET (-19) - + const char *MAGICstring = "Total time for VGA POST:"; const int len = strlen(MAGICstring); I830Ptr pI830 = I830PTR(pScrn); @@ -1185,13 +1317,11 @@ TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit) CARD32 oldpermission; CARD32 ret = 0; int i,j = 0; - int reg = (IS_845G(pI830) || IS_I865G(pI830)) ? _845_DRAM_RW_CONTROL - : _855_DRAM_RW_CONTROL; - PCITAG tag =pciTag(0,0,0); - - if(!pI830->PciInfo - || !(IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830))) + int reg = (IS_845G(pI830) || IS_I865G(pI830)) ? _845_DRAM_RW_CONTROL : _855_DRAM_RW_CONTROL; + + if(!pI830->PciInfo + || !(IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830))) return 0; if (!pI830->pVbe) @@ -1201,7 +1331,8 @@ TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit) pI830->pVbe->pInt10->BIOSseg << 4); if (!pI830->BIOSMemSizeLoc) { - if (!preinit) + + if (!pI830->preinit) return 0; /* Search for MAGIC string */ @@ -1217,32 +1348,30 @@ TweakMemorySize(ScrnInfoPtr pScrn, CARD32 newsize, Bool preinit) if (j < len) return 0; pI830->BIOSMemSizeLoc = (i - j + 1 + (IS_845G(pI830) - ? _845_IDOFFSET : _855_IDOFFSET)); + ? _845_IDOFFSET : _855_IDOFFSET)); } - + position = biosAddr + pI830->BIOSMemSizeLoc; oldsize = *(CARD32 *)position; - ret = oldsize - 0x21000; - + /* verify that register really contains current size */ - if (preinit && ((ret >> 16) != pI830->vbeInfo->TotalMemory)) + if (pI830->preinit && ((ret >> 16) != pI830->vbeInfo->TotalMemory)) return 0; oldpermission = pciReadLong(tag, reg); pciWriteLong(tag, reg, DRAM_WRITE | (oldpermission & 0xffff)); - - *(CARD32 *)position = newsize + 0x21000; - if (preinit) { + *(CARD32 *)position = newsize + 0x21000; + if (pI830->preinit) { /* reinitialize VBE for new size */ VBEFreeVBEInfo(pI830->vbeInfo); vbeFree(pI830->pVbe); pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); pI830->vbeInfo = VBEGetVBEInfo(pI830->pVbe); - + /* verify that change was successful */ - if (pI830->vbeInfo->TotalMemory != (newsize >> 16)){ + if (pI830->vbeInfo->TotalMemory != (newsize >> 16)) { ret = 0; *(CARD32 *)position = oldsize; } else { @@ -1266,7 +1395,7 @@ RestoreBIOSMemSize(ScrnInfoPtr pScrn) DPRINTF(PFX, "RestoreBIOSMemSize\n"); - if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize,FALSE)) + if (TweakMemorySize(pScrn, pI830->saveBIOSMemSize)) return; if (!pI830->overrideBIOSMemSize) @@ -1507,6 +1636,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) I830EntPtr pI830Ent = NULL; int mem, memsize; int flags24; + int defmon = 0; int i, n; char *s; pointer pDDCModule, pVBEModule; @@ -1659,6 +1789,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) case PCI_CHIP_I915_G: chipname = "915G"; break; + case PCI_CHIP_I915_GM: + chipname = "915GM"; + break; default: chipname = "unknown chipset"; break; @@ -1696,7 +1829,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->LinearAddr = pI830->pEnt->device->MemBase; from = X_CONFIG; } else { - if (IS_I915G(pI830)) { + if (IS_I915G(pI830) || IS_I915GM(pI830)) { pI830->LinearAddr = pI830->PciInfo->memBase[2] & 0xF0000000; from = X_PROBED; } else if (pI830->PciInfo->memBase[1] != 0) { @@ -1718,7 +1851,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->MMIOAddr = pI830->pEnt->device->IOBase; from = X_CONFIG; } else { - if (IS_I915G(pI830)) { + if (IS_I915G(pI830) || IS_I915GM(pI830)) { pI830->MMIOAddr = pI830->PciInfo->memBase[0] & 0xFFF80000; from = X_PROBED; } else if (pI830->PciInfo->memBase[1]) { @@ -1763,7 +1896,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->FbMapSize = 0x4000000; /* 64MB - has this been tested ?? */ } } else { - if (IS_I915G(pI830)) { + if (IS_I915G(pI830) || IS_I915GM(pI830)) { if (pI830->PciInfo->memBase[2] & 0x08000000) pI830->FbMapSize = 0x8000000; /* 128MB aperture */ else @@ -2122,13 +2255,14 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BIOS now sees %ld kB VideoRAM\n", pI830->BIOSMemorySize / 1024); - } else if ((pI830->saveBIOSMemSize - = TweakMemorySize(pScrn, pI830->newBIOSMemSize,TRUE)) != 0) - pI830->overrideBIOSMemSize = TRUE; + } else + if ((pI830->saveBIOSMemSize = + TweakMemorySize(pScrn, pI830->newBIOSMemSize)) != 0) + pI830->overrideBIOSMemSize = TRUE; else { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS view of memory size can't be changed " - "(this is not an error).\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "BIOS view of memory size can't be changed " + "(this is not an error).\n"); } } } @@ -2372,7 +2506,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) pI830->CursorNeedsPhysical = FALSE; /* Force ring buffer to be in low memory for the 845G and later. */ - if (IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830)) + if (IS_845G(pI830) || IS_I85X(pI830) || IS_I865G(pI830) || IS_I915G(pI830) || IS_I915GM(pI830)) pI830->NeedRingBufferLow = TRUE; /* @@ -2412,12 +2546,22 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) "Maximum frambuffer space: %d kByte\n", pScrn->videoRam); SetPipeAccess(pScrn); + if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) { PreInitCleanup(pScrn); return FALSE; } - if ((pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule)) != NULL) { + /* Check we are on pipe B and have an LFP connected, before trying to + * read PanelID information. */ + if ((pI830->pipe == 1) && (pI830->operatingDevices & (PIPE_LFP << 8))) { + vbeDoPanelID(pI830->pVbe); + } + + /* If we managed to get PanelID, then try EDID too, and if we get that + * it'll override the PanelID information above */ + if (!pI830->vesa->monitor && + (pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule)) != NULL) { xf86PrintEDID(pI830->vesa->monitor); } if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) @@ -2484,7 +2628,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) } } - if (pI830->useExtendedRefresh) { + if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Will use BIOS call 0x5f05 to set refresh rates for CRTs.\n"); } @@ -2500,12 +2644,37 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Maximum space available for video modes: %d kByte\n", memsize); + /* By now, we should have had some monitor settings, but if not, we + * need to setup some defaults. These are used in common/xf86Modes.c + * so we'll use them here for GetModePool, and that's all. + * We unset them after the call, so we can report 'defaults' as being + * used through the common layer. + */ +#define DEFAULT_HSYNC_LO 28 +#define DEFAULT_HSYNC_HI 33 +#define DEFAULT_VREFRESH_LO 43 +#define DEFAULT_VREFRESH_HI 72 + + if (pScrn->monitor->nHsync == 0) { + pScrn->monitor->hsync[0].lo = DEFAULT_HSYNC_LO; + pScrn->monitor->hsync[0].hi = DEFAULT_HSYNC_HI; + pScrn->monitor->nHsync = 1; + defmon |= 1; + } + + if (pScrn->monitor->nVrefresh == 0) { + pScrn->monitor->vrefresh[0].lo = DEFAULT_VREFRESH_LO; + pScrn->monitor->vrefresh[0].hi = DEFAULT_VREFRESH_HI; + pScrn->monitor->nVrefresh = 1; + defmon |= 2; + } + /* * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS * functions. For that reason it's important to set only - * V_MODETYPE_VGA in the flags for VBEGetModePool(). + * V_MODETYPE_VGA in the flags. */ - pScrn->modePool = VBEGetModePool(pScrn, pI830->pVbe, pI830->vbeInfo, + pScrn->modePool = i830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo, V_MODETYPE_VGA); if (!pScrn->modePool) { @@ -2515,6 +2684,21 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) return FALSE; } + /* This may look a little weird, but to notify that we're using the + * default hsync/vrefresh we need to unset what we just set ..... + */ + if (defmon & 1) { + pScrn->monitor->hsync[0].lo = 0; + pScrn->monitor->hsync[0].hi = 0; + pScrn->monitor->nHsync = 0; + } + + if (defmon & 2) { + pScrn->monitor->vrefresh[0].lo = 0; + pScrn->monitor->vrefresh[0].hi = 0; + pScrn->monitor->nVrefresh = 0; + } + SetPipeAccess(pScrn); VBESetModeNames(pScrn->modePool); @@ -2670,7 +2854,7 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) #endif SetPipeAccess(pScrn); - VBEPrintModes(pScrn); + i830PrintModes(pScrn); if (!pI830->vesa->useDefaultRefresh) { /* @@ -2681,11 +2865,13 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags) * if there are no non-CRT devices attached. */ SetPipeAccess(pScrn); - VBESetModeParameters(pScrn, pI830->pVbe); + i830SetModeParameters(pScrn, pI830->pVbe); } /* PreInit shouldn't leave any state changes, so restore this. */ + pI830->preinit = FALSE; /* temporarily do this */ RestoreBIOSMemSize(pScrn); + pI830->preinit = TRUE; /* now put it back */ /* Don't need MMIO access anymore. */ if (pI830->swfSaved) { @@ -3153,10 +3339,10 @@ I830VESASetVBEMode(ScrnInfoPtr pScrn, int mode, VbeCRTCInfoBlock * block) VbeCRTCInfoBlock newblock; int Mon; - if (!pI830->pipe) - Mon = pI830->MonType2; - else + if (pI830->pipe == 0) Mon = pI830->MonType1; + else + Mon = pI830->MonType2; SetBIOSPipe(pScrn, !pI830->pipe); @@ -3306,10 +3492,10 @@ I830VESASetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode) */ if (pI830->Clone) { int Mon; - if (!pI830->pipe) - Mon = pI830->MonType2; - else + if (pI830->pipe == 0) Mon = pI830->MonType1; + else + Mon = pI830->MonType2; SetBIOSPipe(pScrn, !pI830->pipe); if (pI830->CloneRefresh && (Mon == PIPE_CRT)) { if (pI830->useExtendedRefresh && !pI830->vesa->useDefaultRefresh && @@ -3938,7 +4124,7 @@ I830BIOSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) * first, then re-initialise the VBE information. */ pI830->pVbe = VBEInit(NULL, pI830->pEnt->index); - if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE)) + if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize)) SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); if (!pI830->pVbe) return FALSE; @@ -4346,6 +4532,8 @@ I830BIOSLeaveVT(int scrnIndex, int flags) DPRINTF(PFX, "calling dri lock\n"); DRILock(screenInfo.screens[scrnIndex], 0); pI830->LockHeld = 1; + + drmCtlUninstHandler(pI830->drmSubFD); } #endif @@ -4361,6 +4549,7 @@ I830BIOSLeaveVT(int scrnIndex, int flags) I830UnbindGARTMemory(pScrn); if (pI830->AccelInfoRec) pI830->AccelInfoRec->NeedToSync = FALSE; + if (IsPrimary(pScrn)) { if (!SetDisplayDevices(pScrn, pI830->savedDevices)) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, @@ -4373,6 +4562,201 @@ I830BIOSLeaveVT(int scrnIndex, int flags) } } +static Bool +I830DetectMonitorChange(ScrnInfoPtr pScrn) +{ + I830Ptr pI830 = I830PTR(pScrn); + pointer pDDCModule; + DisplayModePtr p, pMon; + xf86MonPtr DDC; + struct detailed_monitor_section* detMon; + int i, memsize; + struct monitor_ranges *mon_range = NULL; + int displayWidth = pScrn->displayWidth; + int curHDisplay = pScrn->currentMode->HDisplay; + int curVDisplay = pScrn->currentMode->VDisplay; + + DPRINTF(PFX, "Detect Monitor Change\n"); + + SetPipeAccess(pScrn); + + /* Re-read EDID */ + if ((pDDCModule = xf86LoadSubModule(pScrn, "ddc")) == NULL) + return FALSE; + if (pI830->vesa->monitor) + xfree(pI830->vesa->monitor); + if ((pI830->vesa->monitor = vbeDoEDID(pI830->pVbe, pDDCModule)) != NULL) + xf86PrintEDID(pI830->vesa->monitor); + xf86UnloadSubModule(pDDCModule); + if ((pScrn->monitor->DDC = pI830->vesa->monitor) != NULL) + xf86SetDDCproperties(pScrn, pI830->vesa->monitor); + else + /* No DDC, so get out of here, and continue to use the current settings */ + return FALSE; + + DDC = (xf86MonPtr)(pScrn->monitor->DDC); + + /* Now change the hsync/vrefresh values of the current monitor to + * match those of DDC */ + for (i = 0; i < 4; i++) { + detMon = &DDC->det_mon[i]; + if(detMon->type == DS_RANGES) + mon_range = &detMon->section.ranges; + } + + if (!mon_range || mon_range->min_h == 0 || mon_range->max_h == 0 || + mon_range->min_v == 0 || mon_range->max_v == 0) + return FALSE; /* bad ddc */ + + if (mon_range) { +#define DDC_SYNC_TOLERANCE SYNC_TOLERANCE + if (pScrn->monitor->nHsync > 0) { + for (i = 0; i < pScrn->monitor->nHsync; i++) { + if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_h > + pScrn->monitor->hsync[i].lo || + (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_h < + pScrn->monitor->hsync[i].hi) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "config file hsync range %g-%gkHz not within DDC " + "hsync range %d-%dkHz\n", + pScrn->monitor->hsync[i].lo, pScrn->monitor->hsync[i].hi, + mon_range->min_h, mon_range->max_h); + } + pScrn->monitor->hsync[i].lo = mon_range->min_h; + pScrn->monitor->hsync[i].hi = mon_range->max_h; + } + } + + if (pScrn->monitor->nVrefresh > 0) { + for (i=0; i<pScrn->monitor->nVrefresh; i++) { + if ((1.0 - DDC_SYNC_TOLERANCE) * mon_range->min_v > + pScrn->monitor->vrefresh[i].lo || + (1.0 + DDC_SYNC_TOLERANCE) * mon_range->max_v < + pScrn->monitor->vrefresh[i].hi) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "config file vrefresh range %g-%gHz not within DDC " + "vrefresh range %d-%dHz\n", + pScrn->monitor->vrefresh[i].lo, pScrn->monitor->vrefresh[i].hi, + mon_range->min_v, mon_range->max_v); + } + pScrn->monitor->vrefresh[i].lo = mon_range->min_v; + pScrn->monitor->vrefresh[i].hi = mon_range->max_v; + } + } + } /* if (mon_range) */ + + /* Revalidate the modes */ + + /* + * Note: VBE modes (> 0x7f) won't work with Intel's extended BIOS + * functions. For that reason it's important to set only + * V_MODETYPE_VGA in the flags. + */ + pScrn->modePool = i830GetModePool(pScrn, pI830->pVbe, pI830->vbeInfo, + V_MODETYPE_VGA); + + if (!pScrn->modePool) { + /* This is bad, which would cause the Xserver to exit, maybe + * we should default to a 640x480 @ 60Hz mode here ??? */ + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No Video BIOS modes for chosen depth.\n"); + return FALSE; + } + + SetPipeAccess(pScrn); + VBESetModeNames(pScrn->modePool); + + if (pScrn->videoRam > (pI830->vbeInfo->TotalMemory * 64)) + memsize = pI830->vbeInfo->TotalMemory * 64; + else + memsize = pScrn->videoRam; + + VBEValidateModes(pScrn, pScrn->monitor->Modes, pScrn->display->modes, NULL, + NULL, 0, MAX_DISPLAY_PITCH, 1, + 0, MAX_DISPLAY_HEIGHT, + pScrn->display->virtualX, + pScrn->display->virtualY, + memsize, LOOKUP_BEST_REFRESH); + + p = pScrn->modes; + if (p == NULL) + return FALSE; + do { + int Clock = 100000000; /* incredible value */ + + for (pMon = pScrn->monitor->Modes; pMon != NULL; pMon = pMon->next) { + if ((pMon->HDisplay != p->HDisplay) || + (pMon->VDisplay != p->VDisplay) || + (pMon->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2))) + continue; + + /* Find lowest supported Clock for this resolution */ + if (Clock > pMon->Clock) + Clock = pMon->Clock; + } + + if (mon_range->max_clock < 2550 && + Clock / 1000.0 > mon_range->max_clock) { +#if 0 + ErrorF("(%s,%s) mode clock %gMHz exceeds DDC maximum %dMHz\n", + p->name, pScrn->monitor->id, + Clock/1000.0, mon_range->max_clock); +#endif + p->status = MODE_BAD; + } + p = p->next; + } while (p != NULL && p != pScrn->modes); + + pScrn->displayWidth = displayWidth; /* restore old displayWidth */ + + xf86PruneDriverModes(pScrn); + i830PrintModes(pScrn); + + /* Now check if the previously used mode is o.k. for the current monitor. + * This allows VT switching to continue happily when not disconnecting + * and reconnecting monitors */ + + pScrn->currentMode = pScrn->modes; + p = pScrn->modes; + if (p == NULL) + return FALSE; + do { + if ((p->HDisplay == curHDisplay) && + (p->VDisplay == curVDisplay) && + (!(p->Flags & (V_INTERLACE | V_DBLSCAN | V_CLKDIV2)))) { + pScrn->currentMode = p; /* previous mode is o.k. */ + } + p = p->next; + } while (p != NULL && p != pScrn->modes); + + /* Now readjust for panning if necessary */ + { + pScrn->frameX0 = (pScrn->frameX0 + pScrn->frameX1 + 1 - pScrn->currentMode->HDisplay) / 2; + + if (pScrn->frameX0 < 0) + pScrn->frameX0 = 0; + + pScrn->frameX1 = pScrn->frameX0 + pScrn->currentMode->HDisplay - 1; + if (pScrn->frameX1 >= pScrn->virtualX) { + pScrn->frameX0 = pScrn->virtualX - pScrn->currentMode->HDisplay; + pScrn->frameX1 = pScrn->virtualX - 1; + } + + pScrn->frameY0 = (pScrn->frameY0 + pScrn->frameY1 + 1 - pScrn->currentMode->VDisplay) / 2; + + if (pScrn->frameY0 < 0) + pScrn->frameY0 = 0; + + pScrn->frameY1 = pScrn->frameY0 + pScrn->currentMode->VDisplay - 1; + if (pScrn->frameY1 >= pScrn->virtualY) { + pScrn->frameY0 = pScrn->virtualY - pScrn->currentMode->VDisplay; + pScrn->frameY1 = pScrn->virtualY - 1; + } + } + + return TRUE; +} + /* * This gets called when gaining control of the VT, and from ScreenInit(). */ @@ -4385,10 +4769,36 @@ I830BIOSEnterVT(int scrnIndex, int flags) DPRINTF(PFX, "Enter VT\n"); if (IsPrimary(pScrn)) { + /* + * This is needed for restoring from ACPI modes (especially S3) + * so that we warmboot the Video BIOS. Some platforms have problems, + * warm booting when we don't need to, so check that we can call + * the Video BIOS with our display devices, and only when that fails, + * we'll warm boot it. + */ if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + xf86Int10InfoPtr pInt = xf86InitInt10(pI830->pEnt->index); + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "SetDisplayDevices failed, re-trying.\n"); + + /* Now perform our warm boot */ + if (pInt) { + pInt->num = 0xe6; + xf86ExecX86int10 (pInt); + xf86FreeInt10 (pInt); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Re-POSTing via int10.\n"); + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Re-POSTing via int10 failed, trying to continue.\n"); + } + + /* Finally, re-setup the display devices */ + if (!SetDisplayDevices(pScrn, pI830->operatingDevices)) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Failed to switch to configured display devices\n"); - return FALSE; + return FALSE; + } } } @@ -4400,7 +4810,7 @@ I830BIOSEnterVT(int scrnIndex, int flags) return FALSE; CheckInheritedState(pScrn); - if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize,FALSE)) + if (!TweakMemorySize(pScrn, pI830->newBIOSMemSize)) SetBIOSMemSize(pScrn, pI830->newBIOSMemSize); /* @@ -4420,8 +4830,13 @@ I830BIOSEnterVT(int scrnIndex, int flags) pScrn->virtualY * pScrn->displayWidth * pI830->cpp); #endif + /* Detect monitor change and switch to suitable mode */ + if (!pI830->starting) + I830DetectMonitorChange(pScrn); + if (!I830VESASetMode(pScrn, pScrn->currentMode)) return FALSE; + #ifdef I830_XV I830VideoSwitchModeAfter(pScrn, pScrn->currentMode); #endif @@ -4438,6 +4853,10 @@ I830BIOSEnterVT(int scrnIndex, int flags) #ifdef XF86DRI if (pI830->directRenderingEnabled) { if (!pI830->starting) { + /* gdg DRM driver 1.2 supports resume */ + if (pI830->drmMinor >= 2) + I830DRIResume(screenInfo.screens[scrnIndex]); + I830EmitInvarientState(pScrn); I830RefreshRing(pScrn); I830Sync(pScrn); diff --git a/src/i830_memory.c b/src/i830_memory.c index aad103a8..15de1806 100644 --- a/src/i830_memory.c +++ b/src/i830_memory.c @@ -1236,7 +1236,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, i830Reg->Fence[nr] = 0; - if (IS_I915G(pI830)) + if (IS_I915G(pI830) || IS_I915GM(pI830)) fence_mask = ~I915G_FENCE_START_MASK; else fence_mask = ~I830_FENCE_START_MASK; @@ -1244,7 +1244,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, if (start & fence_mask) { xf86DrvMsg(X_WARNING, pScrn->scrnIndex, "SetFence: %d: start (0x%08x) is not %s aligned\n", - nr, start, (IS_I915G(pI830)) ? "1MB" : "512k"); + nr, start, (IS_I915G(pI830) || IS_I915GM(pI830)) ? "1MB" : "512k"); return; } @@ -1264,7 +1264,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, val = (start | FENCE_X_MAJOR | FENCE_VALID); - if (IS_I915G(pI830)) { + if (IS_I915G(pI830) || IS_I915GM(pI830)) { switch (size) { case MB(1): val |= I915G_FENCE_SIZE_1M; @@ -1325,7 +1325,7 @@ SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch, } } - if (IS_I915G(pI830)) + if (IS_I915G(pI830) || IS_I915GM(pI830)) fence_pitch = pitch / 512; else fence_pitch = pitch / 128; diff --git a/src/i830_modes.c b/src/i830_modes.c new file mode 100644 index 00000000..853683df --- /dev/null +++ b/src/i830_modes.c @@ -0,0 +1,712 @@ +#define DEBUG_VERB 2 +/* + * Copyright © 2002 David Dawes + * + * 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 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 + * THE AUTHOR(S) 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. + * + * Except as contained in this notice, the name of the author(s) shall + * not be used in advertising or otherwise to promote the sale, use or other + * dealings in this Software without prior written authorization from + * the author(s). + * + * Authors: David Dawes <dawes@xfree86.org> + * + * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/vbe/vbeModes.c,v 1.6 2002/11/02 01:38:25 dawes Exp $ + */ +/* + * Modified by Alan Hourihane <alanh@tungstengraphics.com> + * to support extended BIOS modes for the Intel chipsets + */ + +#include "xf86.h" +#include "xf86_ansic.h" +#include "vbe.h" +#include "vbeModes.h" +#include "i830.h" + +#include <math.h> + +#define rint(x) floor(x) + +#define MARGIN_PERCENT 1.8 /* % of active vertical image */ +#define CELL_GRAN 8.0 /* assumed character cell granularity */ +#define MIN_PORCH 1 /* minimum front porch */ +#define V_SYNC_RQD 3 /* width of vsync in lines */ +#define H_SYNC_PERCENT 8.0 /* width of hsync as % of total line */ +#define MIN_VSYNC_PLUS_BP 550.0 /* min time of vsync + back porch (microsec) */ +#define M 600.0 /* blanking formula gradient */ +#define C 40.0 /* blanking formula offset */ +#define K 128.0 /* blanking formula scaling factor */ +#define J 20.0 /* blanking formula scaling factor */ + +/* C' and M' are part of the Blanking Duty Cycle computation */ + +#define C_PRIME (((C - J) * K/256.0) + J) +#define M_PRIME (K/256.0 * M) + +static DisplayModePtr +i830GetGTF (int h_pixels, int v_lines, float freq, + int interlaced, int margins) +{ + float h_pixels_rnd; + float v_lines_rnd; + float v_field_rate_rqd; + float top_margin; + float bottom_margin; + float interlace; + float h_period_est; + float vsync_plus_bp; + float v_back_porch; + float total_v_lines; + float v_field_rate_est; + float h_period; + float v_field_rate; + float v_frame_rate; + float left_margin; + float right_margin; + float total_active_pixels; + float ideal_duty_cycle; + float h_blank; + float total_pixels; + float pixel_freq; + float h_freq; + + float h_sync; + float h_front_porch; + float v_odd_front_porch_lines; + DisplayModePtr m; + + m = xnfcalloc(sizeof(DisplayModeRec), 1); + + + /* 1. In order to give correct results, the number of horizontal + * pixels requested is first processed to ensure that it is divisible + * by the character size, by rounding it to the nearest character + * cell boundary: + * + * [H PIXELS RND] = ((ROUND([H PIXELS]/[CELL GRAN RND],0))*[CELLGRAN RND]) + */ + + h_pixels_rnd = rint((float) h_pixels / CELL_GRAN) * CELL_GRAN; + + + /* 2. If interlace is requested, the number of vertical lines assumed + * by the calculation must be halved, as the computation calculates + * the number of vertical lines per field. In either case, the + * number of lines is rounded to the nearest integer. + * + * [V LINES RND] = IF([INT RQD?]="y", ROUND([V LINES]/2,0), + * ROUND([V LINES],0)) + */ + + v_lines_rnd = interlaced ? + rint((float) v_lines) / 2.0 : + rint((float) v_lines); + + /* 3. Find the frame rate required: + * + * [V FIELD RATE RQD] = IF([INT RQD?]="y", [I/P FREQ RQD]*2, + * [I/P FREQ RQD]) + */ + + v_field_rate_rqd = interlaced ? (freq * 2.0) : (freq); + + /* 4. Find number of lines in Top margin: + * + * [TOP MARGIN (LINES)] = IF([MARGINS RQD?]="Y", + * ROUND(([MARGIN%]/100*[V LINES RND]),0), + * 0) + */ + + top_margin = margins ? rint(MARGIN_PERCENT / 100.0 * v_lines_rnd) : (0.0); + + /* 5. Find number of lines in Bottom margin: + * + * [BOT MARGIN (LINES)] = IF([MARGINS RQD?]="Y", + * ROUND(([MARGIN%]/100*[V LINES RND]),0), + * 0) + */ + + bottom_margin = margins ? rint(MARGIN_PERCENT/100.0 * v_lines_rnd) : (0.0); + + /* 6. If interlace is required, then set variable [INTERLACE]=0.5: + * + * [INTERLACE]=(IF([INT RQD?]="y",0.5,0)) + */ + + interlace = interlaced ? 0.5 : 0.0; + + /* 7. Estimate the Horizontal period + * + * [H PERIOD EST] = ((1/[V FIELD RATE RQD]) - [MIN VSYNC+BP]/1000000) / + * ([V LINES RND] + (2*[TOP MARGIN (LINES)]) + + * [MIN PORCH RND]+[INTERLACE]) * 1000000 + */ + + h_period_est = (((1.0/v_field_rate_rqd) - (MIN_VSYNC_PLUS_BP/1000000.0)) + / (v_lines_rnd + (2*top_margin) + MIN_PORCH + interlace) + * 1000000.0); + + /* 8. Find the number of lines in V sync + back porch: + * + * [V SYNC+BP] = ROUND(([MIN VSYNC+BP]/[H PERIOD EST]),0) + */ + + vsync_plus_bp = rint(MIN_VSYNC_PLUS_BP/h_period_est); + + /* 9. Find the number of lines in V back porch alone: + * + * [V BACK PORCH] = [V SYNC+BP] - [V SYNC RND] + * + * XXX is "[V SYNC RND]" a typo? should be [V SYNC RQD]? + */ + + v_back_porch = vsync_plus_bp - V_SYNC_RQD; + + /* 10. Find the total number of lines in Vertical field period: + * + * [TOTAL V LINES] = [V LINES RND] + [TOP MARGIN (LINES)] + + * [BOT MARGIN (LINES)] + [V SYNC+BP] + [INTERLACE] + + * [MIN PORCH RND] + */ + + total_v_lines = v_lines_rnd + top_margin + bottom_margin + vsync_plus_bp + + interlace + MIN_PORCH; + + /* 11. Estimate the Vertical field frequency: + * + * [V FIELD RATE EST] = 1 / [H PERIOD EST] / [TOTAL V LINES] * 1000000 + */ + + v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0; + + /* 12. Find the actual horizontal period: + * + * [H PERIOD] = [H PERIOD EST] / ([V FIELD RATE RQD] / [V FIELD RATE EST]) + */ + + h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est); + + /* 13. Find the actual Vertical field frequency: + * + * [V FIELD RATE] = 1 / [H PERIOD] / [TOTAL V LINES] * 1000000 + */ + + v_field_rate = 1.0 / h_period / total_v_lines * 1000000.0; + + /* 14. Find the Vertical frame frequency: + * + * [V FRAME RATE] = (IF([INT RQD?]="y", [V FIELD RATE]/2, [V FIELD RATE])) + */ + + v_frame_rate = interlaced ? v_field_rate / 2.0 : v_field_rate; + + /* 15. Find number of pixels in left margin: + * + * [LEFT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", + * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / + * [CELL GRAN RND]),0)) * [CELL GRAN RND], + * 0)) + */ + + left_margin = margins ? + rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : + 0.0; + + /* 16. Find number of pixels in right margin: + * + * [RIGHT MARGIN (PIXELS)] = (IF( [MARGINS RQD?]="Y", + * (ROUND( ([H PIXELS RND] * [MARGIN%] / 100 / + * [CELL GRAN RND]),0)) * [CELL GRAN RND], + * 0)) + */ + + right_margin = margins ? + rint(h_pixels_rnd * MARGIN_PERCENT / 100.0 / CELL_GRAN) * CELL_GRAN : + 0.0; + + /* 17. Find total number of active pixels in image and left and right + * margins: + * + * [TOTAL ACTIVE PIXELS] = [H PIXELS RND] + [LEFT MARGIN (PIXELS)] + + * [RIGHT MARGIN (PIXELS)] + */ + + total_active_pixels = h_pixels_rnd + left_margin + right_margin; + + /* 18. Find the ideal blanking duty cycle from the blanking duty cycle + * equation: + * + * [IDEAL DUTY CYCLE] = [C'] - ([M']*[H PERIOD]/1000) + */ + + ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0); + + /* 19. Find the number of pixels in the blanking time to the nearest + * double character cell: + * + * [H BLANK (PIXELS)] = (ROUND(([TOTAL ACTIVE PIXELS] * + * [IDEAL DUTY CYCLE] / + * (100-[IDEAL DUTY CYCLE]) / + * (2*[CELL GRAN RND])), 0)) + * * (2*[CELL GRAN RND]) + */ + + h_blank = rint(total_active_pixels * + ideal_duty_cycle / + (100.0 - ideal_duty_cycle) / + (2.0 * CELL_GRAN)) * (2.0 * CELL_GRAN); + + /* 20. Find total number of pixels: + * + * [TOTAL PIXELS] = [TOTAL ACTIVE PIXELS] + [H BLANK (PIXELS)] + */ + + total_pixels = total_active_pixels + h_blank; + + /* 21. Find pixel clock frequency: + * + * [PIXEL FREQ] = [TOTAL PIXELS] / [H PERIOD] + */ + + pixel_freq = total_pixels / h_period; + + /* 22. Find horizontal frequency: + * + * [H FREQ] = 1000 / [H PERIOD] + */ + + h_freq = 1000.0 / h_period; + + + /* Stage 1 computations are now complete; I should really pass + the results to another function and do the Stage 2 + computations, but I only need a few more values so I'll just + append the computations here for now */ + + + + /* 17. Find the number of pixels in the horizontal sync period: + * + * [H SYNC (PIXELS)] =(ROUND(([H SYNC%] / 100 * [TOTAL PIXELS] / + * [CELL GRAN RND]),0))*[CELL GRAN RND] + */ + + h_sync = rint(H_SYNC_PERCENT/100.0 * total_pixels / CELL_GRAN) * CELL_GRAN; + + /* 18. Find the number of pixels in the horizontal front porch period: + * + * [H FRONT PORCH (PIXELS)] = ([H BLANK (PIXELS)]/2)-[H SYNC (PIXELS)] + */ + + h_front_porch = (h_blank / 2.0) - h_sync; + + /* 36. Find the number of lines in the odd front porch period: + * + * [V ODD FRONT PORCH(LINES)]=([MIN PORCH RND]+[INTERLACE]) + */ + + v_odd_front_porch_lines = MIN_PORCH + interlace; + + /* finally, pack the results in the DisplayMode struct */ + + m->HDisplay = (int) (h_pixels_rnd); + m->HSyncStart = (int) (h_pixels_rnd + h_front_porch); + m->HSyncEnd = (int) (h_pixels_rnd + h_front_porch + h_sync); + m->HTotal = (int) (total_pixels); + + m->VDisplay = (int) (v_lines_rnd); + m->VSyncStart = (int) (v_lines_rnd + v_odd_front_porch_lines); + m->VSyncEnd = (int) (int) (v_lines_rnd + v_odd_front_porch_lines + V_SYNC_RQD); + m->VTotal = (int) (total_v_lines); + + m->Clock = (int)(pixel_freq * 1000); + m->SynthClock = m->Clock; + m->HSync = h_freq; + m->VRefresh = freq; + + return (m); +} + +static DisplayModePtr +CheckMode(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, int id, + int flags) +{ + CARD16 major, minor; + VbeModeInfoBlock *mode; + DisplayModePtr pMode = NULL; + VbeModeInfoData *data; + Bool modeOK = FALSE; + ModeStatus status = MODE_OK; + + major = (unsigned)(vbe->VESAVersion >> 8); + minor = vbe->VESAVersion & 0xff; + + if ((mode = VBEGetModeInfo(pVbe, id)) == NULL) + return NULL; + + /* Does the mode match the depth/bpp? */ + /* Some BIOS's set BitsPerPixel to 15 instead of 16 for 15/16 */ + if (VBE_MODE_USABLE(mode, flags) && + ((pScrn->bitsPerPixel == 1 && !VBE_MODE_COLOR(mode)) || + (mode->BitsPerPixel > 8 && + (mode->RedMaskSize + mode->GreenMaskSize + + mode->BlueMaskSize) == pScrn->depth && + mode->BitsPerPixel == pScrn->bitsPerPixel) || + (mode->BitsPerPixel == 15 && pScrn->depth == 15) || + (mode->BitsPerPixel <= 8 && + mode->BitsPerPixel == pScrn->bitsPerPixel))) { + modeOK = TRUE; + xf86ErrorFVerb(DEBUG_VERB, "*"); + } + + /* + * Check if there's a valid monitor mode that this one can be matched + * up with. The actual matching is done later. + */ + if (modeOK) { + float vrefresh = 0.0f; + int i; + + for (i=0;i<pScrn->monitor->nVrefresh;i++) { + + for (vrefresh = pScrn->monitor->vrefresh[i].hi; + vrefresh >= pScrn->monitor->vrefresh[i].lo; vrefresh -= 1.0f) { + + if (vrefresh != (float)0.0f) { + pMode = i830GetGTF(mode->XResolution, mode->YResolution, + vrefresh, 0, 0); + + pMode->type = M_T_BUILTIN; + + status = xf86CheckModeForMonitor(pMode, pScrn->monitor); + if (status == MODE_OK) + modeOK = TRUE; + else + modeOK = FALSE; + pMode->status = status; + } else { + modeOK = FALSE; + } + if (modeOK) break; + } + if (modeOK) break; + } + } + + xf86ErrorFVerb(DEBUG_VERB, + "Mode: %x (%dx%d)\n", id, mode->XResolution, mode->YResolution); + xf86ErrorFVerb(DEBUG_VERB, + " ModeAttributes: 0x%x\n", mode->ModeAttributes); + xf86ErrorFVerb(DEBUG_VERB, + " WinAAttributes: 0x%x\n", mode->WinAAttributes); + xf86ErrorFVerb(DEBUG_VERB, + " WinBAttributes: 0x%x\n", mode->WinBAttributes); + xf86ErrorFVerb(DEBUG_VERB, + " WinGranularity: %d\n", mode->WinGranularity); + xf86ErrorFVerb(DEBUG_VERB, + " WinSize: %d\n", mode->WinSize); + xf86ErrorFVerb(DEBUG_VERB, + " WinASegment: 0x%x\n", mode->WinASegment); + xf86ErrorFVerb(DEBUG_VERB, + " WinBSegment: 0x%x\n", mode->WinBSegment); + xf86ErrorFVerb(DEBUG_VERB, + " WinFuncPtr: 0x%x\n", mode->WinFuncPtr); + xf86ErrorFVerb(DEBUG_VERB, + " BytesPerScanline: %d\n", mode->BytesPerScanline); + xf86ErrorFVerb(DEBUG_VERB, + " XResolution: %d\n", mode->XResolution); + xf86ErrorFVerb(DEBUG_VERB, + " YResolution: %d\n", mode->YResolution); + xf86ErrorFVerb(DEBUG_VERB, + " XCharSize: %d\n", mode->XCharSize); + xf86ErrorFVerb(DEBUG_VERB, + " YCharSize: %d\n", mode->YCharSize); + xf86ErrorFVerb(DEBUG_VERB, + " NumberOfPlanes: %d\n", mode->NumberOfPlanes); + xf86ErrorFVerb(DEBUG_VERB, + " BitsPerPixel: %d\n", mode->BitsPerPixel); + xf86ErrorFVerb(DEBUG_VERB, + " NumberOfBanks: %d\n", mode->NumberOfBanks); + xf86ErrorFVerb(DEBUG_VERB, + " MemoryModel: %d\n", mode->MemoryModel); + xf86ErrorFVerb(DEBUG_VERB, + " BankSize: %d\n", mode->BankSize); + xf86ErrorFVerb(DEBUG_VERB, + " NumberOfImages: %d\n", mode->NumberOfImages); + xf86ErrorFVerb(DEBUG_VERB, + " RedMaskSize: %d\n", mode->RedMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " RedFieldPosition: %d\n", mode->RedFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " GreenMaskSize: %d\n", mode->GreenMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " GreenFieldPosition: %d\n", mode->GreenFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " BlueMaskSize: %d\n", mode->BlueMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " BlueFieldPosition: %d\n", mode->BlueFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " RsvdMaskSize: %d\n", mode->RsvdMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " RsvdFieldPosition: %d\n", mode->RsvdFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " DirectColorModeInfo: %d\n", mode->DirectColorModeInfo); + if (major >= 2) { + xf86ErrorFVerb(DEBUG_VERB, + " PhysBasePtr: 0x%x\n", mode->PhysBasePtr); + if (major >= 3) { + xf86ErrorFVerb(DEBUG_VERB, + " LinBytesPerScanLine: %d\n", mode->LinBytesPerScanLine); + xf86ErrorFVerb(DEBUG_VERB, + " BnkNumberOfImagePages: %d\n", mode->BnkNumberOfImagePages); + xf86ErrorFVerb(DEBUG_VERB, + " LinNumberOfImagePages: %d\n", mode->LinNumberOfImagePages); + xf86ErrorFVerb(DEBUG_VERB, + " LinRedMaskSize: %d\n", mode->LinRedMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " LinRedFieldPosition: %d\n", mode->LinRedFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " LinGreenMaskSize: %d\n", mode->LinGreenMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " LinGreenFieldPosition: %d\n", mode->LinGreenFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " LinBlueMaskSize: %d\n", mode->LinBlueMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " LinBlueFieldPosition: %d\n", mode->LinBlueFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " LinRsvdMaskSize: %d\n", mode->LinRsvdMaskSize); + xf86ErrorFVerb(DEBUG_VERB, + " LinRsvdFieldPosition: %d\n", mode->LinRsvdFieldPosition); + xf86ErrorFVerb(DEBUG_VERB, + " MaxPixelClock: %d\n", mode->MaxPixelClock); + } + } + + if (!modeOK) { + VBEFreeModeInfo(mode); + if (pMode) + xfree(pMode); + return NULL; + } + + pMode->status = MODE_OK; + pMode->type = M_T_BUILTIN; + + /* for adjust frame */ + pMode->HDisplay = mode->XResolution; + pMode->VDisplay = mode->YResolution; + + data = xnfcalloc(sizeof(VbeModeInfoData), 1); + data->mode = id; + data->data = mode; + pMode->PrivSize = sizeof(VbeModeInfoData); + pMode->Private = (INT32*)data; + pMode->next = NULL; + return pMode; +} + +/* + * Check the available BIOS modes, and extract those that match the + * requirements into the modePool. Note: modePool is a NULL-terminated + * list. + */ + +DisplayModePtr +i830GetModePool(ScrnInfoPtr pScrn, vbeInfoPtr pVbe, VbeInfoBlock *vbe, + int modeTypes) +{ + DisplayModePtr pMode, p = NULL, modePool = NULL; + int i = 0; + + if (modeTypes & V_MODETYPE_VBE) { + while (vbe->VideoModePtr[i] != 0xffff) { + int id = vbe->VideoModePtr[i++]; + + if ((pMode = CheckMode(pScrn, pVbe, vbe, id, modeTypes)) != NULL) { + ModeStatus status = MODE_OK; + + /* Check the mode against a specified virtual size (if any) */ + if (pScrn->display->virtualX > 0 && + pMode->HDisplay > pScrn->display->virtualX) { + status = MODE_VIRTUAL_X; + } + if (pScrn->display->virtualY > 0 && + pMode->VDisplay > pScrn->display->virtualY) { + status = MODE_VIRTUAL_Y; + } + if (status != MODE_OK) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%dx%d\" (%s)\n", + pMode->HDisplay, pMode->VDisplay, + xf86ModeStatusToString(status)); + } else { + if (p == NULL) { + modePool = pMode; + } else { + p->next = pMode; + } + pMode->prev = NULL; + p = pMode; + } + } + } + } + if (modeTypes & V_MODETYPE_VGA) { + for (i = 0; i < 0x7F; i++) { + if ((pMode = CheckMode(pScrn, pVbe, vbe, i, modeTypes)) != NULL) { + ModeStatus status = MODE_OK; + + /* Check the mode against a specified virtual size (if any) */ + if (pScrn->display->virtualX > 0 && + pMode->HDisplay > pScrn->display->virtualX) { + status = MODE_VIRTUAL_X; + } + if (pScrn->display->virtualY > 0 && + pMode->VDisplay > pScrn->display->virtualY) { + status = MODE_VIRTUAL_Y; + } + if (status != MODE_OK) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Not using mode \"%dx%d\" (%s)\n", + pMode->HDisplay, pMode->VDisplay, + xf86ModeStatusToString(status)); + } else { + if (p == NULL) { + modePool = pMode; + } else { + p->next = pMode; + } + pMode->prev = NULL; + p = pMode; + } + } + } + } + return modePool; +} + +/* + * Go through the monitor modes and selecting the best set of + * parameters for each BIOS mode. Note: This is only supported in + * VBE version 3.0 or later. + */ +void +i830SetModeParameters(ScrnInfoPtr pScrn, vbeInfoPtr pVbe) +{ + DisplayModePtr pMode; + VbeModeInfoData *data; + + pMode = pScrn->modes; + do { + int clock; + + data = (VbeModeInfoData*)pMode->Private; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Attempting to use %dHz refresh for mode \"%s\" (%x)\n", + (int)pMode->VRefresh, pMode->name, data->mode); + data->block = xcalloc(sizeof(VbeCRTCInfoBlock), 1); + data->block->HorizontalTotal = pMode->HTotal; + data->block->HorizontalSyncStart = pMode->HSyncStart; + data->block->HorizontalSyncEnd = pMode->HSyncEnd; + data->block->VerticalTotal = pMode->VTotal; + data->block->VerticalSyncStart = pMode->VSyncStart; + data->block->VerticalSyncEnd = pMode->VSyncEnd; + data->block->Flags = ((pMode->Flags & V_NHSYNC) ? CRTC_NHSYNC : 0) | + ((pMode->Flags & V_NVSYNC) ? CRTC_NVSYNC : 0); + data->block->PixelClock = pMode->Clock * 1000; + /* XXX May not have this. */ + clock = VBEGetPixelClock(pVbe, data->mode, data->block->PixelClock); +#ifdef DEBUG + ErrorF("Setting clock %.2fMHz, closest is %.2fMHz\n", + (double)data->block->PixelClock / 1000000.0, + (double)clock / 1000000.0); +#endif + if (clock) + data->block->PixelClock = clock; + data->mode |= (1 << 11); + data->block->RefreshRate = ((double)(data->block->PixelClock) / + (double)(pMode->HTotal * pMode->VTotal)) * 100; + + pMode = pMode->next; + } while (pMode != pScrn->modes); +} + +void +i830PrintModes(ScrnInfoPtr scrp) +{ + DisplayModePtr p; + float hsync, refresh = 0; + char *desc, *desc2, *prefix, *uprefix; + + if (scrp == NULL) + return; + + xf86DrvMsg(scrp->scrnIndex, scrp->virtualFrom, "Virtual size is %dx%d " + "(pitch %d)\n", scrp->virtualX, scrp->virtualY, + scrp->displayWidth); + + p = scrp->modes; + if (p == NULL) + return; + + do { + desc = desc2 = ""; + if (p->HSync > 0.0) + hsync = p->HSync; + else if (p->HTotal > 0) + hsync = (float)p->Clock / (float)p->HTotal; + else + hsync = 0.0; + if (p->VTotal > 0) + refresh = hsync * 1000.0 / p->VTotal; + if (p->Flags & V_INTERLACE) { + refresh *= 2.0; + desc = " (I)"; + } + if (p->Flags & V_DBLSCAN) { + refresh /= 2.0; + desc = " (D)"; + } + if (p->VScan > 1) { + refresh /= p->VScan; + desc2 = " (VScan)"; + } + if (p->VRefresh > 0.0) + refresh = p->VRefresh; + if (p->type & M_T_BUILTIN) + prefix = "Built-in mode"; + else if (p->type & M_T_DEFAULT) + prefix = "Default mode"; + else + prefix = "Mode"; + if (p->type & M_T_USERDEF) + uprefix = "*"; + else + uprefix = " "; + if (p->name) + xf86DrvMsg(scrp->scrnIndex, X_CONFIG, + "%s%s \"%s\"\n", uprefix, prefix, p->name); + else + xf86DrvMsg(scrp->scrnIndex, X_PROBED, + "%s%s %dx%d (unnamed)\n", + uprefix, prefix, p->HDisplay, p->VDisplay); + p = p->next; + } while (p != NULL && p != scrp->modes); +} diff --git a/src/i830_video.c b/src/i830_video.c index 8cf7f451..6eb34da9 100644 --- a/src/i830_video.c +++ b/src/i830_video.c @@ -110,7 +110,7 @@ static void I830BlockHandler(int, pointer, pointer, pointer); #define MAKE_ATOM(a) MakeAtom(a, sizeof(a) - 1, TRUE) -static Atom xvBrightness, xvContrast, xvColorKey; +static Atom xvBrightness, xvContrast, xvColorKey, xvPipe; static Atom xvGamma0, xvGamma1, xvGamma2, xvGamma3, xvGamma4, xvGamma5; #define IMAGE_MAX_WIDTH 1440 @@ -251,7 +251,7 @@ static XF86VideoFormatRec Formats[NUM_FORMATS] = { {15, TrueColor}, {16, TrueColor}, {24, TrueColor} }; -#define NUM_ATTRIBUTES 9 +#define NUM_ATTRIBUTES 10 static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { {XvSettable | XvGettable, 0, (1 << 24) - 1, "XV_COLORKEY"}, @@ -262,7 +262,8 @@ static XF86AttributeRec Attributes[NUM_ATTRIBUTES] = { {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA2"}, {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA3"}, {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA4"}, - {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"} + {XvSettable | XvGettable, 0, 0xffffff, "XV_GAMMA5"}, + {XvSettable | XvGettable, 0, 1, "XV_PIPE"} }; #define NUM_IMAGES 4 @@ -342,6 +343,7 @@ typedef struct { int brightness; int contrast; + int pipe; RegionRec clip; CARD32 colorKey; @@ -503,7 +505,7 @@ I830ResetVideo(ScrnInfoPtr pScrn) * Select which pipe the overlay is enabled on. */ overlay->OCONFIG &= ~OVERLAY_PIPE_MASK; - if (pI830->pipe == 0) + if (pPriv->pipe == 0) overlay->OCONFIG |= OVERLAY_PIPE_A; else overlay->OCONFIG |= OVERLAY_PIPE_B; @@ -589,7 +591,7 @@ I830SetupImageVideo(ScreenPtr pScreen) adapt->type = XvWindowMask | XvInputMask | XvImageMask; adapt->flags = VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT; - adapt->name = "Intel(R) 830M/845G/852GM/855GM/865G/915G Video Overlay"; + adapt->name = "Intel(R) Video Overlay"; adapt->nEncodings = 1; adapt->pEncodings = DummyEncoding; adapt->nFormats = NUM_FORMATS; @@ -602,10 +604,12 @@ I830SetupImageVideo(ScreenPtr pScreen) adapt->pPortPrivates[0].ptr = (pointer) (pPriv); adapt->pAttributes = Attributes; adapt->nImages = NUM_IMAGES; - if (IS_I915G(pI830)) + if (IS_I915G(pI830) || IS_I915GM(pI830)) adapt->nAttributes = 9; /* has gamma */ else adapt->nAttributes = 3; + if (pI830->Clone) + adapt->nAttributes += 1; adapt->pImages = Images; adapt->PutVideo = NULL; adapt->PutStill = NULL; @@ -622,6 +626,7 @@ I830SetupImageVideo(ScreenPtr pScreen) pPriv->videoStatus = 0; pPriv->brightness = 0; pPriv->contrast = 64; + pPriv->pipe = pI830->pipe; /* default to current pipe */ pPriv->linear = NULL; pPriv->currentBuf = 0; pPriv->gamma5 = 0xc0c0c0; @@ -655,7 +660,12 @@ I830SetupImageVideo(ScreenPtr pScreen) xvBrightness = MAKE_ATOM("XV_BRIGHTNESS"); xvContrast = MAKE_ATOM("XV_CONTRAST"); xvColorKey = MAKE_ATOM("XV_COLORKEY"); - if (IS_I915G(pI830)) { + + /* Allow the pipe to be switched from pipe A to B when in clone mode */ + if (pI830->Clone) + xvPipe = MAKE_ATOM("XV_PIPE"); + + if (IS_I915G(pI830) || IS_I915GM(pI830)) { xvGamma0 = MAKE_ATOM("XV_GAMMA0"); xvGamma1 = MAKE_ATOM("XV_GAMMA1"); xvGamma2 = MAKE_ATOM("XV_GAMMA2"); @@ -759,7 +769,21 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, overlay->OCLRC0 = (pPriv->contrast << 18) | (pPriv->brightness & 0xff); if (pPriv->overlayOK) OVERLAY_UPDATE; - } else if (attribute == xvGamma0 && (IS_I915G(pI830))) { + } else if (pI830->Clone && attribute == xvPipe) { + if ((value < 0) || (value > 1)) + return BadValue; + pPriv->pipe = value; + /* + * Select which pipe the overlay is enabled on. + */ + overlay->OCONFIG &= ~OVERLAY_PIPE_MASK; + if (pPriv->pipe == 0) + overlay->OCONFIG |= OVERLAY_PIPE_A; + else + overlay->OCONFIG |= OVERLAY_PIPE_B; + if (pPriv->overlayOK) + OVERLAY_UPDATE; + } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830))) { /* Avoid video anomalies, so set gamma registers when overlay is off */ /* We also clamp the values if they are outside the ranges */ if (!*pI830->overlayOn) { @@ -768,35 +792,35 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, pPriv->gamma1 = pPriv->gamma0 + 0x7d; } else return BadRequest; - } else if (attribute == xvGamma1 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830))) { if (!*pI830->overlayOn) { pPriv->gamma1 = value; if (pPriv->gamma1 - pPriv->gamma0 > 0x7d) pPriv->gamma0 = pPriv->gamma1 - 0x7d; } else return BadRequest; - } else if (attribute == xvGamma2 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830))) { if (!*pI830->overlayOn) { pPriv->gamma2 = value; if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) pPriv->gamma3 = pPriv->gamma2 + 0x7d; } else return BadRequest; - } else if (attribute == xvGamma3 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830))) { if (!*pI830->overlayOn) { pPriv->gamma3 = value; if (pPriv->gamma3 - pPriv->gamma2 > 0x7d) pPriv->gamma2 = pPriv->gamma3 - 0x7d; } else return BadRequest; - } else if (attribute == xvGamma4 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830))) { if (!*pI830->overlayOn) { pPriv->gamma4 = value; if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) pPriv->gamma5 = pPriv->gamma4 + 0x7d; } else return BadRequest; - } else if (attribute == xvGamma5 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830))) { if (!*pI830->overlayOn) { pPriv->gamma5 = value; if (pPriv->gamma5 - pPriv->gamma4 > 0x7d) @@ -828,7 +852,7 @@ I830SetPortAttribute(ScrnInfoPtr pScrn, attribute == xvGamma2 || attribute == xvGamma3 || attribute == xvGamma4 || - attribute == xvGamma5) && (IS_I915G(pI830))) { + attribute == xvGamma5) && (IS_I915G(pI830) || IS_I915GM(pI830))) { I830UpdateGamma(pScrn); } @@ -846,17 +870,19 @@ I830GetPortAttribute(ScrnInfoPtr pScrn, *value = pPriv->brightness; } else if (attribute == xvContrast) { *value = pPriv->contrast; - } else if (attribute == xvGamma0 && (IS_I915G(pI830))) { + } else if (pI830->Clone && attribute == xvPipe) { + *value = pPriv->pipe; + } else if (attribute == xvGamma0 && (IS_I915G(pI830) || IS_I915GM(pI830))) { *value = pPriv->gamma0; - } else if (attribute == xvGamma1 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma1 && (IS_I915G(pI830) || IS_I915GM(pI830))) { *value = pPriv->gamma1; - } else if (attribute == xvGamma2 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma2 && (IS_I915G(pI830) || IS_I915GM(pI830))) { *value = pPriv->gamma2; - } else if (attribute == xvGamma3 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma3 && (IS_I915G(pI830) || IS_I915GM(pI830))) { *value = pPriv->gamma3; - } else if (attribute == xvGamma4 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma4 && (IS_I915G(pI830) || IS_I915GM(pI830))) { *value = pPriv->gamma4; - } else if (attribute == xvGamma5 && (IS_I915G(pI830))) { + } else if (attribute == xvGamma5 && (IS_I915G(pI830) || IS_I915GM(pI830))) { *value = pPriv->gamma5; } else if (attribute == xvColorKey) { *value = pPriv->colorKey; @@ -1448,7 +1474,7 @@ I830PutImage(ScrnInfoPtr pScrn, if (pI830->entityPrivate) { if (pI830->entityPrivate->XvInUse != -1 && - pI830->entityPrivate->XvInUse != pI830->pipe) { + pI830->entityPrivate->XvInUse != pPriv->pipe) { #ifdef PANORAMIX if (!noPanoramiXExtension) { return Success; /* faked for trying to share it */ @@ -1459,7 +1485,7 @@ I830PutImage(ScrnInfoPtr pScrn, } } - pI830->entityPrivate->XvInUse = pI830->pipe; + pI830->entityPrivate->XvInUse = pPriv->pipe; } /* Clip */ @@ -1836,7 +1862,7 @@ I830DisplaySurface(XF86SurfacePtr surface, if (pI830->entityPrivate) { if (pI830->entityPrivate->XvInUse != -1 && - pI830->entityPrivate->XvInUse != pI830->pipe) { + pI830->entityPrivate->XvInUse != pI830Priv->pipe) { #ifdef PANORAMIX if (!noPanoramiXExtension) { return Success; /* faked for trying to share it */ @@ -1847,7 +1873,7 @@ I830DisplaySurface(XF86SurfacePtr surface, } } - pI830->entityPrivate->XvInUse = pI830->pipe; + pI830->entityPrivate->XvInUse = pI830Priv->pipe; } x1 = src_x; @@ -1978,7 +2004,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) if (!pPriv) return; - if (pI830->pipe == 0) { + if (pPriv->pipe == 0) { if (INREG(PIPEACONF) & PIPEACONF_DOUBLE_WIDE) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling XVideo output because Pipe A is in double-wide mode.\n"); @@ -1990,7 +2016,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) } } - if (pI830->pipe == 1) { + if (pPriv->pipe == 1) { if (INREG(PIPEBCONF) & PIPEBCONF_DOUBLE_WIDE) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Disabling XVideo output because Pipe B is in double-wide mode.\n"); @@ -2003,7 +2029,7 @@ I830VideoSwitchModeAfter(ScrnInfoPtr pScrn, DisplayModePtr mode) } /* Check we are on pipe B and have an LFP connected */ - if ((pI830->pipe == 1) && (pI830->operatingDevices & (PIPE_LFP << 8))) { + if ((pPriv->pipe == 1) && (pI830->operatingDevices & (PIPE_LFP << 8))) { size = INREG(PIPEBSRC); hsize = (size >> 16) & 0x7FF; vsize = size & 0x7FF; |