Sorting source tree a bit
[tpg/acess2.git] / KernelLand / Modules / Display / Tegra2Vid / main.c
diff --git a/KernelLand/Modules/Display/Tegra2Vid/main.c b/KernelLand/Modules/Display/Tegra2Vid/main.c
new file mode 100644 (file)
index 0000000..d9405be
--- /dev/null
@@ -0,0 +1,326 @@
+/**\r
+ * main.c\r
+ * - Driver core\r
+ */\r
+#define DEBUG  0\r
+#define VERSION        ((0<<8)|10)\r
+#include <acess.h>\r
+#include <errno.h>\r
+#include <modules.h>\r
+#include <vfs.h>\r
+#include <fs_devfs.h>\r
+#include <drv_pci.h>\r
+#include <api_drv_video.h>\r
+#include <lib/keyvalue.h>\r
+#include <options.h>   // ARM Arch\r
+#include "tegra2.h"\r
+\r
+#define ABS(a) ((a)>0?(a):-(a))\r
+\r
+// === PROTOTYPES ===\r
+// Driver\r
+ int   Tegra2Vid_Install(char **Arguments);\r
+void   Tegra2Vid_Uninstall();\r
+// Internal\r
+// Filesystem\r
+Uint64 Tegra2Vid_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+Uint64 Tegra2Vid_Write(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
+ int   Tegra2Vid_IOCtl(tVFS_Node *node, int id, void *data);\r
+// -- Internals\r
+ int   Tegra2Vid_int_SetMode(int Mode);\r
+\r
+// === GLOBALS ===\r
+MODULE_DEFINE(0, VERSION, Tegra2Vid, Tegra2Vid_Install, NULL, NULL);\r
+tDevFS_Driver  gTegra2Vid_DriverStruct = {\r
+       NULL, "Tegra2Vid",\r
+       {\r
+       .Read = Tegra2Vid_Read,\r
+       .Write = Tegra2Vid_Write,\r
+       .IOCtl = Tegra2Vid_IOCtl\r
+       }\r
+};\r
+// -- Options\r
+tPAddr gTegra2Vid_PhysBase = TEGRA2VID_BASE;\r
+ int   gbTegra2Vid_IsVersatile = 1;\r
+// -- KeyVal parse rules\r
+const tKeyVal_ParseRules       gTegra2Vid_KeyValueParser = {\r
+       NULL,\r
+       {\r
+               {"Base", "P", &gTegra2Vid_PhysBase},\r
+               {NULL, NULL, NULL}\r
+       }\r
+};\r
+// -- Driver state\r
+ int   giTegra2Vid_CurrentMode = 0;\r
+ int   giTegra2Vid_BufferMode;\r
+size_t giTegra2Vid_FramebufferSize;\r
+Uint32 *gpTegra2Vid_IOMem;\r
+tPAddr gTegra2Vid_FramebufferPhys;\r
+void   *gpTegra2Vid_Framebuffer;\r
+// -- Misc\r
+tDrvUtil_Video_BufInfo gTegra2Vid_DrvUtil_BufInfo;\r
+tVideo_IOCtl_Pos       gTegra2Vid_CursorPos;\r
+\r
+// === CODE ===\r
+/**\r
+ */\r
+int Tegra2Vid_Install(char **Arguments)\r
+{\r
+//     KeyVal_Parse(&gTegra2Vid_KeyValueParser, Arguments);\r
+\r
+       gpTegra2Vid_IOMem = (void*)MM_MapHWPages(gTegra2Vid_PhysBase, 256/4);\r
+       {\r
+               Log_Debug("Tegra2Vid", "Display CMD Registers");\r
+               for( int i = 0x000; i <= 0x01A; i ++ )\r
+                       Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
+               for( int i = 0x028; i <= 0x043; i ++ )\r
+                       Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
+               Log_Debug("Tegra2Vid", "Display COM Registers");\r
+               for( int i = 0x300; i <= 0x329; i ++ )\r
+                       Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
+               Log_Debug("Tegra2Vid", "Display DISP Registers");\r
+               for( int i = 0x400; i <= 0x446; i ++ )\r
+                       Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
+               for( int i = 0x480; i <= 0x484; i ++ )\r
+                       Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
+               for( int i = 0x4C0; i <= 0x4C1; i ++ )\r
+                       Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
+\r
+               Log_Debug("Tegra2Vid", "WINC_A Registers");\r
+               for( int i = 0x700; i <= 0x714; i ++ )\r
+                       Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
+               Log_Debug("Tegra2Vid", "WINBUF_A");\r
+               for( int i = 0x800; i <= 0x80A; i ++ )\r
+                       Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
+       }\r
+//     return 1;\r
+       \r
+       giTegra2Vid_FramebufferSize =\r
+               (gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]&0xFFFF)\r
+               *(gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]>>16)*4;\r
+\r
+       Log_Debug("Tegra2Vid", "giTegra2Vid_FramebufferSize = 0x%x", giTegra2Vid_FramebufferSize);\r
+       gpTegra2Vid_Framebuffer = MM_MapHWPages(\r
+               gpTegra2Vid_IOMem[DC_WINBUF_A_START_ADDR_0],\r
+               (giTegra2Vid_FramebufferSize+PAGE_SIZE-1)/PAGE_SIZE\r
+               );\r
+       memset(gpTegra2Vid_Framebuffer, 0x1F, 0x1000);\r
+\r
+\r
+//     Tegra2Vid_int_SetMode(4);\r
+\r
+       DevFS_AddDevice( &gTegra2Vid_DriverStruct );\r
+\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \brief Clean up resources for driver unloading\r
+ */\r
+void Tegra2Vid_Uninstall()\r
+{\r
+}\r
+\r
+/**\r
+ * \brief Read from the framebuffer\r
+ */\r
+Uint64 Tegra2Vid_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
+{\r
+       return 0;\r
+}\r
+\r
+/**\r
+ * \brief Write to the framebuffer\r
+ */\r
+Uint64 Tegra2Vid_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
+{\r
+       gTegra2Vid_DrvUtil_BufInfo.BufferFormat = giTegra2Vid_BufferMode;\r
+       return DrvUtil_Video_WriteLFB(&gTegra2Vid_DrvUtil_BufInfo, Offset, Length, Buffer);\r
+}\r
+\r
+const char *csaTegra2Vid_IOCtls[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL};\r
+\r
+/**\r
+ * \brief Handle messages to the device\r
+ */\r
+int Tegra2Vid_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
+{\r
+        int    ret = -2;\r
+       ENTER("pNode iID pData", Node, ID, Data);\r
+       \r
+       switch(ID)\r
+       {\r
+       BASE_IOCTLS(DRV_TYPE_VIDEO, "PL110", VERSION, csaTegra2Vid_IOCtls);\r
+\r
+       case VIDEO_IOCTL_SETBUFFORMAT:\r
+               DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );\r
+               ret = giTegra2Vid_BufferMode;\r
+               if(Data)        giTegra2Vid_BufferMode = *(int*)Data;\r
+               if(gTegra2Vid_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
+                       DrvUtil_Video_SetCursor( &gTegra2Vid_DrvUtil_BufInfo, &gDrvUtil_TextModeCursor );\r
+               break;\r
+       \r
+       case VIDEO_IOCTL_GETSETMODE:\r
+               if(Data)\r
+               {\r
+                        int    newMode;\r
+                       \r
+                       if( !CheckMem(Data, sizeof(int)) )\r
+                               LEAVE_RET('i', -1);\r
+                       \r
+                       newMode = *(int*)Data;\r
+                       \r
+                       if(newMode < 0 || newMode >= ciTegra2Vid_ModeCount)\r
+                               LEAVE_RET('i', -1);\r
+\r
+                       if(newMode != giTegra2Vid_CurrentMode)\r
+                       {\r
+                               giTegra2Vid_CurrentMode = newMode;\r
+                               Tegra2Vid_int_SetMode( newMode );\r
+                       }\r
+               }\r
+               ret = giTegra2Vid_CurrentMode;\r
+               break;\r
+       \r
+       case VIDEO_IOCTL_FINDMODE:\r
+               {\r
+               tVideo_IOCtl_Mode *mode = Data;\r
+                int    closest, closestArea, reqArea = 0;\r
+               if(!Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)))\r
+                       LEAVE_RET('i', -1);\r
+               if( mode->bpp != 32 )\r
+                       LEAVE_RET('i', 0);\r
+               if( mode->flags != 0 )\r
+                       LEAVE_RET('i', 0);\r
+\r
+               ret = 0;\r
+\r
+               for( int i = 0; i < ciTegra2Vid_ModeCount; i ++ )\r
+               {\r
+                        int    area;\r
+                       if(mode->width == caTegra2Vid_Modes[i].W && mode->height == caTegra2Vid_Modes[i].H) {\r
+                               mode->id = i;\r
+                               ret = 1;\r
+                               break;\r
+                       }\r
+                       \r
+                       area = caTegra2Vid_Modes[i].W * caTegra2Vid_Modes[i].H;\r
+                       if(!reqArea) {\r
+                               reqArea = mode->width * mode->height;\r
+                               closest = i;\r
+                               closestArea = area;\r
+                       }\r
+                       else if( ABS(area - reqArea) < ABS(closestArea - reqArea) ) {\r
+                               closest = i;\r
+                               closestArea = area;\r
+                       }\r
+               }\r
+               \r
+               if( ret == 0 )\r
+               {\r
+                       mode->id = closest;\r
+                       ret = 1;\r
+               }\r
+               mode->width = caTegra2Vid_Modes[mode->id].W;\r
+               mode->height = caTegra2Vid_Modes[mode->id].H;\r
+               break;\r
+               }\r
+       \r
+       case VIDEO_IOCTL_MODEINFO:\r
+               {\r
+               tVideo_IOCtl_Mode *mode = Data;\r
+               if(!Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)))\r
+                       LEAVE_RET('i', -1);\r
+               if(mode->id < 0 || mode->id >= ciTegra2Vid_ModeCount)\r
+                       LEAVE_RET('i', 0);\r
+               \r
+\r
+               mode->bpp = 32;\r
+               mode->flags = 0;\r
+               mode->width = caTegra2Vid_Modes[mode->id].W;\r
+               mode->height = caTegra2Vid_Modes[mode->id].H;\r
+\r
+               ret = 1;\r
+               break;\r
+               }\r
+       \r
+       case VIDEO_IOCTL_SETCURSOR:\r
+               if( !Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Pos)) )\r
+                       LEAVE_RET('i', -1);\r
+\r
+               DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );\r
+               \r
+               gTegra2Vid_CursorPos = *(tVideo_IOCtl_Pos*)Data;\r
+               if(gTegra2Vid_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
+                       DrvUtil_Video_DrawCursor(\r
+                               &gTegra2Vid_DrvUtil_BufInfo,\r
+                               gTegra2Vid_CursorPos.x*giVT_CharWidth,\r
+                               gTegra2Vid_CursorPos.y*giVT_CharHeight\r
+                               );\r
+               else\r
+                       DrvUtil_Video_DrawCursor(\r
+                               &gTegra2Vid_DrvUtil_BufInfo,\r
+                               gTegra2Vid_CursorPos.x,\r
+                               gTegra2Vid_CursorPos.y\r
+                               );\r
+               break;\r
+       \r
+       default:\r
+               LEAVE('i', -2);\r
+               return -2;\r
+       }\r
+       \r
+       LEAVE('i', ret);\r
+       return ret;\r
+}\r
+\r
+//\r
+//\r
+//\r
+\r
+int Tegra2Vid_int_SetMode(int Mode)\r
+{\r
+       const struct sTegra2_Disp_Mode  *mode = &caTegra2Vid_Modes[Mode];\r
+        int    w = mode->W, h = mode->H;       // Horizontal/Vertical Active\r
+       *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_FRONT_PORCH_0) = (mode->VFP << 16) | mode->HFP; \r
+       *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_SYNC_WIDTH_0)  = (mode->HS << 16)  | mode->HS;\r
+       *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_BACK_PORCH_0)  = (mode->VBP << 16) | mode->HBP;\r
+       *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_DISP_ACTIVE_0) = (mode->H << 16)   | mode->W;\r
+\r
+       *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_POSITION_0) = 0;\r
+       *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_SIZE_0) = (mode->H << 16) | mode->W;\r
+       *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_DISP_COLOR_CONTROL_0) = 0x8;     // BASE888\r
+       *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_COLOR_DEPTH_0) = 12;    // Could be 13 (BGR/RGB)\r
+       *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_PRESCALED_SIZE_0) = (mode->H << 16) | mode->W;\r
+\r
+       Log_Debug("Tegra2Vid", "Mode %i (%ix%i) selected", Mode, w, h);\r
+\r
+       if( !gpTegra2Vid_Framebuffer || w*h*4 != giTegra2Vid_FramebufferSize )\r
+       {\r
+               if( gpTegra2Vid_Framebuffer )\r
+               {\r
+                       // TODO: Free framebuffer for reallocation\r
+               }\r
+\r
+               giTegra2Vid_FramebufferSize = w*h*4;            \r
+\r
+               gpTegra2Vid_Framebuffer = (void*)MM_AllocDMA(\r
+                       (giTegra2Vid_FramebufferSize + PAGE_SIZE-1) / PAGE_SIZE,\r
+                       32,\r
+                       &gTegra2Vid_FramebufferPhys\r
+                       );\r
+               // TODO: Catch allocation failures\r
+               Log_Debug("Tegra2Vid", "0x%x byte framebuffer at %p (%P phys)",\r
+                               giTegra2Vid_FramebufferSize,\r
+                               gpTegra2Vid_Framebuffer,\r
+                               gTegra2Vid_FramebufferPhys\r
+                               );\r
+               \r
+               // Tell hardware\r
+               *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_START_ADDR_0) = gTegra2Vid_FramebufferPhys;\r
+               *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_V_OFFSET_0) = 0;        // Y offset\r
+               *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_H_OFFSET_0) = 0;        // X offset\r
+       }\r
+\r
+       return 0;\r
+}\r

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