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