This is the first patch in a series to make the Siliconmotion driver work with the TQM5200 Board.
If no PCI device is found the driver tries to MMIO to the relevant location for a SM501 on PowerPC Localbus. If it finds the right device ID after MMIO-mapping it assumes the chip is there. If not it exits with an error message. On my TQM5200, gcc reverses the bit-fields (which are heavily used). Therefore, the bit-accesses to the registers are all wrong. I have not found a way to reverse the bit-fields back to the right order. As an example, I have converted the bit-field access to the STATUS register to bit-masking. But all other bit-fields still have to be converted that way, too. Anyway, with this patch, the driver should work as normal with the PCI devices. I cannot check this, could somebody please confirm? Regards, Marc
>From 6a228cee7940034c05decdecf7762bab3a986d35 Mon Sep 17 00:00:00 2001 From: Marc Scherer <[email protected]> Date: Tue, 14 Sep 2010 12:49:08 +0200 Subject: [PATCH video-siliconmotion] Added detection of SM501 on PPC LocalBus. Bit-fields are reversed on big-endian PPC :( Therefore, changed STATUS bit-field operations to bit-masks. TODO: change all remaining bit fields to bit-masks. Signed-off-by: Marc Scherer <[email protected]> --- src/regsmi.h | 13 ++---- src/smi.h | 7 +++ src/smi_501.c | 10 ++-- src/smi_501.h | 26 +++--------- src/smi_driver.c | 114 +++++++++++++++++++++++++++++++++++++++++++++++------- 5 files changed, 122 insertions(+), 48 deletions(-) diff --git a/src/regsmi.h b/src/regsmi.h index 5dd0320..6481850 100644 --- a/src/regsmi.h +++ b/src/regsmi.h @@ -217,7 +217,7 @@ VGAOUT8(SMIPtr pSmi, int port, CARD8 data) \ mem_barrier(); \ if (IS_MSOC(pSmi)) { \ - MSOCCmdStatusRec status; \ + int32_t status; \ \ /* bit 0: 2d engine idle if *not set* * bit 1: 2d fifo empty if *set* @@ -226,14 +226,9 @@ VGAOUT8(SMIPtr pSmi, int port, CARD8 data) * bit 19: command fifo empty if *set* * bit 20: 2d memory fifo empty idle if *set* */ \ - for (status.value = READ_SCR(pSmi, CMD_STATUS); \ - loop && (status.f.engine || \ - !status.f.cmdfifo || \ - status.f.setup || \ - status.f.csc || \ - !status.f.cmdhif || \ - !status.f.memfifo); \ - status.value = READ_SCR(pSmi, CMD_STATUS), loop--) \ + for (status = READ_SCR(pSmi, CMD_STATUS); \ + loop && (status & STATUS_IDLE_MASK) != STATUS_IDLE_VALUE; \ + status = READ_SCR(pSmi, CMD_STATUS), loop--) \ ; \ } \ else { \ diff --git a/src/smi.h b/src/smi.h index 0f72db9..ba03033 100644 --- a/src/smi.h +++ b/src/smi.h @@ -278,6 +278,13 @@ typedef struct #define SMIPTR(p) ((SMIPtr)((p)->driverPrivate)) /******************************************************************************/ +/* G L O B A L S */ +/******************************************************************************/ + +/* for PowerPC LocalBus */ +extern Bool ppcLocalBus; + +/******************************************************************************/ /* M A C R O S */ /******************************************************************************/ diff --git a/src/smi_501.c b/src/smi_501.c index a605e0d..33618d3 100644 --- a/src/smi_501.c +++ b/src/smi_501.c @@ -610,7 +610,7 @@ SMI501_PrintRegs(ScrnInfoPtr pScrn) void SMI501_WaitVSync(SMIPtr pSmi, int vsync_count) { - MSOCCmdStatusRec status; + int32_t status; int32_t timeout; while (vsync_count-- > 0) { @@ -618,18 +618,18 @@ SMI501_WaitVSync(SMIPtr pSmi, int vsync_count) timeout = 0; do { /* bit 11: vsync active *if set* */ - status.value = READ_SCR(pSmi, CMD_STATUS); + status = READ_SCR(pSmi, CMD_STATUS); if (++timeout == 10000) break; - } while (status.f.pvsync); + } while (status & STATUS_PVSYNC_MASK); /* Wait for start of vsync */ timeout = 0; do { - status.value = READ_SCR(pSmi, CMD_STATUS); + status = READ_SCR(pSmi, CMD_STATUS); if (++timeout == 10000) break; - } while (!status.f.pvsync); + } while (!(status & STATUS_PVSYNC_MASK)); } } diff --git a/src/smi_501.h b/src/smi_501.h index 10bcf6c..4995493 100644 --- a/src/smi_501.h +++ b/src/smi_501.h @@ -40,6 +40,9 @@ authorization from the XFree86 Project and Silicon Motion. #define bits(lo, hi) hi + 1 - lo +#define SMI501_ENDIAN_CTL 0x5C +#define SMI501_BIG_ENDIAN 0xFFFFFFFF +#define SMI501_LITTLE_ENDIAN 0x0 #define DRAM_CTL 0x000010 @@ -78,6 +81,9 @@ typedef union _MSOCCmdAddrRec { #define CMD_RETADDR 0x000020 #define CMD_STATUS 0x000024 +#define STATUS_IDLE_MASK 0x1C0007 +#define STATUS_IDLE_VALUE 0x180002 +#define STATUS_PVSYNC_MASK 0x000800 /* COMMAND LIST STATUS * Read/Write MMIO_base + 0x000024 * Power-on Default 0b0000.0000.000X.XXXX.XXXX.X000.0000.0XXX @@ -124,26 +130,6 @@ typedef union _MSOCCmdAddrRec { * 1: Empty. * 21:31 Reserved */ -typedef union _MSOCCmdStatusRec { - struct { - int32_t engine : bits( 0, 0); - int32_t cmdfifo : bits( 1, 1); - int32_t setup : bits( 2, 2); - int32_t u0 : bits( 3, 10); - int32_t pvsync : bits(11, 11); - int32_t cvsync : bits(12, 12); - int32_t player : bits(13, 13); - int32_t vlayer : bits(14, 14); - int32_t vfield : bits(15, 15); - int32_t clayer : bits(16, 16); - int32_t dma : bits(17, 17); - int32_t csc : bits(18, 18); - int32_t cmdhif : bits(19, 19); - int32_t memfifo : bits(20, 20); - int32_t u1 : bits(21, 31); - } f; - int32_t value; -} MSOCCmdStatusRec, *MSOCCmdStatusPtr; /* contents of either power0_clock or power1_clock */ #define CURRENT_CLOCK 0x00003c diff --git a/src/smi_driver.c b/src/smi_driver.c index 391efbc..c0d4ded 100644 --- a/src/smi_driver.c +++ b/src/smi_driver.c @@ -106,6 +106,10 @@ int smi_indent = 1; /* for dualhead */ int gSMIEntityIndex = -1; +/* for PowerPC LocalBus */ +/* tested only on TQM5200 Board with SM501 and MPC5200B */ +Bool ppcLocalBus = FALSE; + /* * This contains the functions needed by the server after loading the * driver module. It must be supplied, and gets added the driver list by @@ -319,6 +323,7 @@ SMI_Probe(DriverPtr drv, int flags) int numDevSections; int numUsed; Bool foundScreen = FALSE; + Bool pciError = FALSE; ENTER(); @@ -330,21 +335,46 @@ SMI_Probe(DriverPtr drv, int flags) #ifndef XSERVER_LIBPCIACCESS if (xf86GetPciVideoInfo() == NULL) - LEAVE(FALSE); + pciError = TRUE; #endif numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID, SMIChipsets, SMIPciChipsets, devSections, numDevSections, drv, &usedChips); - /* Free it since we don't need that list after this */ - xfree(devSections); if (numUsed <= 0) - LEAVE(FALSE); + pciError = TRUE; if (flags & PROBE_DETECT) foundScreen = TRUE; - else { + else if (pciError) { /* ClaimNoSlot if there is no PCI device */ + int entity; + ScrnInfoPtr pScrn; + + xf86DrvMsg(0, X_WARNING, SILICONMOTION_NAME ": no PCI device found, try LocalBus\n"); + numUsed = numDevSections; + for (i = 0; i < numUsed; i++) { + entity = xf86ClaimNoSlot(drv, 0, devSections[i], TRUE); + if((pScrn = xf86AllocateScreen(drv, 0))) + xf86AddEntityToScreen(pScrn, entity); + + pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION; + pScrn->driverName = SILICONMOTION_DRIVER_NAME; + pScrn->name = SILICONMOTION_NAME; + pScrn->Probe = SMI_Probe; + pScrn->PreInit = SMI_PreInit; + pScrn->ScreenInit = SMI_ScreenInit; + pScrn->SwitchMode = SMI_SwitchMode; + pScrn->AdjustFrame = SMI_AdjustFrame; + pScrn->EnterVT = SMI_EnterVT; + pScrn->LeaveVT = SMI_LeaveVT; + pScrn->FreeScreen = SMI_FreeScreen; + + foundScreen = TRUE; + ppcLocalBus = TRUE; + } + } + else { /* do PCI setup */ ScrnInfoPtr pScrn; EntityInfoPtr pEnt; @@ -371,6 +401,8 @@ SMI_Probe(DriverPtr drv, int flags) } } } + + xfree(devSections); xfree(usedChips); LEAVE(foundScreen); @@ -400,9 +432,13 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags) /* Find the PCI slot for this screen */ pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + if(ppcLocalBus) { + pSmi->PciInfo = NULL; + pSmi->Chipset = PCI_CHIP_SMI501; + } else { pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index); pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo); - + } if (IS_MSOC(pSmi)) { pSmi->Save = SMI501_Save; pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1); @@ -420,13 +456,14 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags) LEAVE(TRUE); } + if(!ppcLocalBus) { if (pEnt->location.type != BUS_PCI) { xfree(pEnt); SMI_FreeRec(pScrn); LEAVE(FALSE); } pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index); - + } /* Set pScrn->monitor */ pScrn->monitor = pScrn->confScreen->monitor; @@ -651,6 +688,9 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags) } else { from = X_PROBED; + if(ppcLocalBus) + pSmi->Chipset = SMI_MSOC; + else pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo); pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset); } @@ -660,6 +700,8 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n", pSmi->ChipRev); } + else if(ppcLocalBus) + pSmi->ChipRev = 0xA0; else pSmi->ChipRev = PCI_DEV_REVISION(pSmi->PciInfo); xfree(pEnt); @@ -683,6 +725,9 @@ SMI_PreInit(ScrnInfoPtr pScrn, int flags) xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset); #ifndef XSERVER_LIBPCIACCESS + if(ppcLocalBus) + pSmi->PciTag = NULL; + else pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device, pSmi->PciInfo->func); #endif @@ -1219,6 +1264,12 @@ SMI_MapMmio(ScrnInfoPtr pScrn) SMI_EnableMmio(pScrn); + if(ppcLocalBus) { + memBase = 0xE3E00000; /* fixed MMIO-Base on TQM5200 */ + pSmi->MapSize = 0x200000; /* in Bytes */ + pSmi->MapBase = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_MMIO, memBase, pSmi->MapSize); + } + else { switch (pSmi->Chipset) { case SMI_COUGAR3DR: memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM); @@ -1263,6 +1314,7 @@ SMI_MapMmio(ScrnInfoPtr pScrn) return (FALSE); } #endif + } if (pSmi->MapBase == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map " @@ -1306,13 +1358,13 @@ SMI_MapMmio(ScrnInfoPtr pScrn) pSmi->DataPortSize = 0x100000; break; case SMI_MSOC: - pSmi->DPRBase = pSmi->MapBase + 0x100000; - pSmi->VPRBase = pSmi->MapBase + 0x000000; - pSmi->CPRBase = pSmi->MapBase + 0x090000; - pSmi->DCRBase = pSmi->MapBase + 0x080000; - pSmi->SCRBase = pSmi->MapBase + 0x000000; + pSmi->DPRBase = pSmi->MapBase + 0x100000; /* 2D drawing engine */ + pSmi->VPRBase = pSmi->MapBase + 0x000000; /* ??? */ + pSmi->CPRBase = pSmi->MapBase + 0x090000; /* ZV port */ + pSmi->DCRBase = pSmi->MapBase + 0x080000; /* Display controller */ + pSmi->SCRBase = pSmi->MapBase + 0x000000; /* System config */ pSmi->IOBase = 0; - pSmi->DataPortBase = pSmi->MapBase + 0x110000; + pSmi->DataPortBase = pSmi->MapBase + 0x110000; /* 2D drawing engine data port */ pSmi->DataPortSize = 0x10000; break; default: @@ -1337,6 +1389,22 @@ SMI_MapMmio(ScrnInfoPtr pScrn) "DataPort=%p - %p\n", pSmi->DataPortBase, pSmi->DataPortBase + pSmi->DataPortSize - 1); + if(ppcLocalBus) { +#if __BYTE_ORDER == __BIG_ENDIAN + WRITE_SCR(pSmi, SMI501_ENDIAN_CTL, SMI501_BIG_ENDIAN); +#else + WRITE_SCR(pSmi, SMI501_ENDIAN_CTL, SMI501_LITTLE_ENDIAN); +#endif + /* TODO: make this test more general */ + if(READ_SCR(pSmi, DEVICE_ID) != 0x050100A0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No SM501 found on PPC LocalBus\n"); + return (FALSE); + } + else + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV, + "Found Device_ID = %08X\n", READ_SCR(pSmi, DEVICE_ID)); + } + return (TRUE); } @@ -1456,6 +1524,9 @@ SMI_MapMem(ScrnInfoPtr pScrn) if (pSmi->MapBase == NULL && SMI_MapMmio(pScrn) == FALSE) LEAVE(FALSE); + if(ppcLocalBus) + pScrn->memPhysBase = 0xE0000000; /* fixed FB-Base on TQM5200 */ + else pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM); if (pSmi->Chipset == SMI_LYNX3DM) @@ -1463,6 +1534,9 @@ SMI_MapMem(ScrnInfoPtr pScrn) else pSmi->fbMapOffset = 0x0; + if(ppcLocalBus) + pSmi->FBBase = xf86MapVidMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, pScrn->memPhysBase, pSmi->videoRAMBytes); + else { #ifndef XSERVER_LIBPCIACCESS pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER, @@ -1484,6 +1558,7 @@ SMI_MapMem(ScrnInfoPtr pScrn) LEAVE(FALSE); } #endif + } if (pSmi->FBBase == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, @@ -1585,6 +1660,17 @@ SMI_UnmapMem(ScrnInfoPtr pScrn) SMI_DisableMmio(pScrn); + if(ppcLocalBus) { + if (pSmi->MapBase) { + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase, pSmi->MapSize); + pSmi->MapBase = NULL; + } + if (pSmi->FBBase) { + xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->FBBase, pSmi->videoRAMBytes); + pSmi->FBBase = NULL; + } + } + else { if (pSmi->MapBase) { #ifndef XSERVER_LIBPCIACCESS xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase, @@ -1606,7 +1692,7 @@ SMI_UnmapMem(ScrnInfoPtr pScrn) #endif pSmi->FBBase = NULL; } - + } LEAVE(); } -- 1.7.0.4
_______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
