Kernel - Slight reworks to timer code
[tpg/acess2.git] / Modules / Display / PL110 / main.c
index 4f6ab77..c3b6e52 100644 (file)
@@ -19,6 +19,7 @@
 #include <drv_pci.h>\r
 #include <api_drv_video.h>\r
 #include <lib/keyvalue.h>\r
+#include <options.h>   // ARM Arch\r
 \r
 #define ABS(a) ((a)>0?(a):-(a))\r
 \r
@@ -43,9 +44,11 @@ struct sPL110
        Uint32  LCDLPCurr;\r
 };\r
 \r
-// === CONSTANTS ===\r
+#ifndef PL110_BASE\r
 #define PL110_BASE     0x10020000      // Integrator\r
+#endif\r
 \r
+// === CONSTANTS ===\r
 const struct {\r
        short W, H;\r
 }      caPL110_Modes[] = {\r
@@ -62,28 +65,31 @@ void        PL110_Uninstall();
 // Internal\r
 // Filesystem\r
 Uint64 PL110_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
-Uint64 PL110_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+Uint64 PL110_Write(tVFS_Node *node, Uint64 off, Uint64 len, const void *buffer);\r
  int   PL110_IOCtl(tVFS_Node *node, int id, void *data);\r
 // -- Internals\r
  int   PL110_int_SetResolution(int W, int H);\r
 \r
 // === GLOBALS ===\r
 MODULE_DEFINE(0, VERSION, PL110, PL110_Install, NULL, NULL);\r
-tDevFS_Driver  gPL110_DriverStruct = {\r
-       NULL, "PL110",\r
-       {\r
+tVFS_NodeType  gPL110_DevNodeType = {\r
        .Read = PL110_Read,\r
        .Write = PL110_Write,\r
        .IOCtl = PL110_IOCtl\r
-       }\r
+       };\r
+tDevFS_Driver  gPL110_DriverStruct = {\r
+       NULL, "PL110",\r
+       {.Type = &gPL110_DevNodeType}\r
 };\r
 // -- Options\r
 tPAddr gPL110_PhysBase = PL110_BASE;\r
+ int   gbPL110_IsVersatile = 1;\r
 // -- KeyVal parse rules\r
 const tKeyVal_ParseRules       gPL110_KeyValueParser = {\r
        NULL,\r
        {\r
                {"Base", "P", &gPL110_PhysBase},\r
+               {"IsVersatile", "i", &gbPL110_IsVersatile},\r
                {NULL, NULL, NULL}\r
        }\r
 };\r
@@ -98,6 +104,7 @@ tPAddr       gPL110_FramebufferPhys;
 void   *gpPL110_Framebuffer;\r
 // -- Misc\r
 tDrvUtil_Video_BufInfo gPL110_DrvUtil_BufInfo;\r
+tVideo_IOCtl_Pos       gPL110_CursorPos;\r
 \r
 // === CODE ===\r
 /**\r
@@ -133,7 +140,7 @@ Uint64 PL110_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)
 /**\r
  * \brief Write to the framebuffer\r
  */\r
-Uint64 PL110_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+Uint64 PL110_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, const void *Buffer)\r
 {\r
        gPL110_DrvUtil_BufInfo.BufferFormat = giPL110_BufferMode;\r
        return DrvUtil_Video_WriteLFB(&gPL110_DrvUtil_BufInfo, Offset, Length, Buffer);\r
@@ -154,8 +161,11 @@ int PL110_IOCtl(tVFS_Node *Node, int ID, void *Data)
        BASE_IOCTLS(DRV_TYPE_VIDEO, "PL110", VERSION, csaPL110_IOCtls);\r
 \r
        case VIDEO_IOCTL_SETBUFFORMAT:\r
+               DrvUtil_Video_RemoveCursor( &gPL110_DrvUtil_BufInfo );\r
                ret = giPL110_BufferMode;\r
                if(Data)        giPL110_BufferMode = *(int*)Data;\r
+               if(gPL110_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
+                       DrvUtil_Video_SetCursor( &gPL110_DrvUtil_BufInfo, &gDrvUtil_TextModeCursor );\r
                break;\r
        \r
        case VIDEO_IOCTL_GETSETMODE:\r
@@ -242,7 +252,26 @@ int PL110_IOCtl(tVFS_Node *Node, int ID, void *Data)
                break;\r
                }\r
        \r
-       case VIDEO_IOCTL_SETCURSOR:     break;\r
+       case VIDEO_IOCTL_SETCURSOR:\r
+               if( !Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Pos)) )\r
+                       LEAVE_RET('i', -1);\r
+\r
+               DrvUtil_Video_RemoveCursor( &gPL110_DrvUtil_BufInfo );\r
+               \r
+               gPL110_CursorPos = *(tVideo_IOCtl_Pos*)Data;\r
+               if(gPL110_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
+                       DrvUtil_Video_DrawCursor(\r
+                               &gPL110_DrvUtil_BufInfo,\r
+                               gPL110_CursorPos.x*giVT_CharWidth,\r
+                               gPL110_CursorPos.y*giVT_CharHeight\r
+                               );\r
+               else\r
+                       DrvUtil_Video_DrawCursor(\r
+                               &gPL110_DrvUtil_BufInfo,\r
+                               gPL110_CursorPos.x,\r
+                               gPL110_CursorPos.y\r
+                               );\r
+               break;\r
        \r
        default:\r
                LEAVE('i', -2);\r
@@ -258,10 +287,18 @@ int PL110_IOCtl(tVFS_Node *Node, int ID, void *Data)
 //\r
 \r
 /**\r
+ * \brief Set the LCD controller resolution\r
+ * \param W    Width (aligned to 16 pixels, cipped to 1024)\r
+ * \param H    Height (clipped to 768)\r
+ * \return Boolean failure\r
  */\r
 int PL110_int_SetResolution(int W, int H)\r
 {\r
-       W = (W + 15)/16;\r
+       W = (W + 15) & ~0xF;\r
+       if(W <= 0 || H <= 0) {\r
+               Log_Warning("PL110", "Attempted to set invalid resolution (%ix%i)", W, H);\r
+               return 1;\r
+       }\r
        if(W > 1024)    W = 1024;\r
        if(H > 768)     H = 768;\r
 \r
@@ -279,8 +316,20 @@ int PL110_int_SetResolution(int W, int H)
        gpPL110_IOMem->LCDUPBase = gPL110_FramebufferPhys;\r
        gpPL110_IOMem->LCDLPBase = 0;\r
 \r
-       gpPL110_IOMem->LCDIMSC = 0;\r
-       gpPL110_IOMem->LCDControl = (1 << 11)|(1 << 5)|(5<<1)|1;\r
+       // Power on, BGR mode, ???, ???, enabled\r
+       Uint32  controlWord = (1 << 11)|(1 << 8)|(1 << 5)|(5 << 1)|1;\r
+       // According to qemu, the Versatile version has these two the wrong\r
+       // way around\r
+       if( gbPL110_IsVersatile )\r
+       {\r
+               gpPL110_IOMem->LCDIMSC = controlWord;   // Actually LCDControl\r
+               gpPL110_IOMem->LCDControl = 0;  // Actually LCDIMSC\r
+       }\r
+       else\r
+       {\r
+               gpPL110_IOMem->LCDIMSC = 0;\r
+               gpPL110_IOMem->LCDControl = controlWord;\r
+       }\r
 \r
        giPL110_Width = W;\r
        giPL110_Height = H;\r

UCC git Repository :: git.ucc.asn.au