X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Modules%2FDisplay%2FPL110%2Fmain.c;h=285cec4dda6208389fa2986202b44ec94c271fcd;hb=f42e912b8bc615c2009b795ce12d4c54cef4ee8b;hp=f1604c617a9f56bf0e7c33452513a83a7a3353ce;hpb=721e4b481a301692d40f231aa18dd247b6675a92;p=tpg%2Facess2.git diff --git a/Modules/Display/PL110/main.c b/Modules/Display/PL110/main.c index f1604c61..285cec4d 100644 --- a/Modules/Display/PL110/main.c +++ b/Modules/Display/PL110/main.c @@ -44,7 +44,8 @@ struct sPL110 }; // === CONSTANTS === -#define PL110_BASE 0x10020000 +#define PL110_BASE 0x10020000 // Integrator + const struct { short W, H; } caPL110_Modes[] = { @@ -78,11 +79,13 @@ tDevFS_Driver gPL110_DriverStruct = { }; // -- Options tPAddr gPL110_PhysBase = PL110_BASE; + int gbPL110_IsVersatile = 1; // -- KeyVal parse rules const tKeyVal_ParseRules gPL110_KeyValueParser = { NULL, { {"Base", "P", &gPL110_PhysBase}, + {"IsVersatile", "i", &gbPL110_IsVersatile}, {NULL, NULL, NULL} } }; @@ -97,6 +100,7 @@ tPAddr gPL110_FramebufferPhys; void *gpPL110_Framebuffer; // -- Misc tDrvUtil_Video_BufInfo gPL110_DrvUtil_BufInfo; +tVideo_IOCtl_Pos gPL110_CursorPos; // === CODE === /** @@ -134,7 +138,8 @@ Uint64 PL110_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer) */ Uint64 PL110_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) { - return DrvUtil_Video_WriteLFB(giPL110_BufferMode, &gPL110_DrvUtil_BufInfo, Offset, Length, Buffer); + gPL110_DrvUtil_BufInfo.BufferFormat = giPL110_BufferMode; + return DrvUtil_Video_WriteLFB(&gPL110_DrvUtil_BufInfo, Offset, Length, Buffer); } const char *csaPL110_IOCtls[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL}; @@ -152,8 +157,11 @@ int PL110_IOCtl(tVFS_Node *Node, int ID, void *Data) BASE_IOCTLS(DRV_TYPE_VIDEO, "PL110", VERSION, csaPL110_IOCtls); case VIDEO_IOCTL_SETBUFFORMAT: + DrvUtil_Video_RemoveCursor( &gPL110_DrvUtil_BufInfo ); ret = giPL110_BufferMode; if(Data) giPL110_BufferMode = *(int*)Data; + if(gPL110_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT) + DrvUtil_Video_SetCursor( &gPL110_DrvUtil_BufInfo, &gDrvUtil_TextModeCursor ); break; case VIDEO_IOCTL_GETSETMODE: @@ -240,7 +248,26 @@ int PL110_IOCtl(tVFS_Node *Node, int ID, void *Data) break; } - case VIDEO_IOCTL_SETCURSOR: break; + case VIDEO_IOCTL_SETCURSOR: + if( !Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Pos)) ) + LEAVE_RET('i', -1); + + DrvUtil_Video_RemoveCursor( &gPL110_DrvUtil_BufInfo ); + + gPL110_CursorPos = *(tVideo_IOCtl_Pos*)Data; + if(gPL110_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT) + DrvUtil_Video_DrawCursor( + &gPL110_DrvUtil_BufInfo, + gPL110_CursorPos.x*giVT_CharWidth, + gPL110_CursorPos.y*giVT_CharHeight + ); + else + DrvUtil_Video_DrawCursor( + &gPL110_DrvUtil_BufInfo, + gPL110_CursorPos.x, + gPL110_CursorPos.y + ); + break; default: LEAVE('i', -2); @@ -256,10 +283,18 @@ int PL110_IOCtl(tVFS_Node *Node, int ID, void *Data) // /** + * \brief Set the LCD controller resolution + * \param W Width (aligned to 16 pixels, cipped to 1024) + * \param H Height (clipped to 768) + * \return Boolean failure */ int PL110_int_SetResolution(int W, int H) { - W = (W + 15)/16; + W = (W + 15) & ~0xF; + if(W <= 0 || H <= 0) { + Log_Warning("PL110", "Attempted to set invalid resolution (%ix%i)", W, H); + return 1; + } if(W > 1024) W = 1024; if(H > 768) H = 768; @@ -277,8 +312,20 @@ int PL110_int_SetResolution(int W, int H) gpPL110_IOMem->LCDUPBase = gPL110_FramebufferPhys; gpPL110_IOMem->LCDLPBase = 0; - gpPL110_IOMem->LCDIMSC = 0; - gpPL110_IOMem->LCDControl = (1 << 11)|(1 << 5)|(5<<1)|1; + // Power on, BGR mode, ???, ???, enabled + Uint32 controlWord = (1 << 11)|(1 << 8)|(1 << 5)|(5 << 1)|1; + // According to qemu, the Versatile version has these two the wrong + // way around + if( gbPL110_IsVersatile ) + { + gpPL110_IOMem->LCDIMSC = controlWord; // Actually LCDControl + gpPL110_IOMem->LCDControl = 0; // Actually LCDIMSC + } + else + { + gpPL110_IOMem->LCDIMSC = 0; + gpPL110_IOMem->LCDControl = controlWord; + } giPL110_Width = W; giPL110_Height = H;