#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
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_SetResolution(int W, int H);\r
+ int Tegra2Vid_int_SetMode(int Mode);\r
\r
// === GLOBALS ===\r
-MODULE_DEFINE(0, VERSION, PL110, Tegra2Vid_Install, NULL, NULL);\r
+MODULE_DEFINE(0, VERSION, Video_Tegra2, Tegra2Vid_Install, NULL, NULL);\r
tDevFS_Driver gTegra2Vid_DriverStruct = {\r
NULL, "PL110",\r
{\r
}\r
};\r
// -- Options\r
-tPAddr gTegra2Vid_PhysBase = Tegra2Vid_BASE;\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
- {"IsVersatile", "i", &gbTegra2Vid_IsVersatile},\r
{NULL, NULL, NULL}\r
}\r
};\r
// -- Driver state\r
int giTegra2Vid_CurrentMode = 0;\r
int giTegra2Vid_BufferMode;\r
- int giTegra2Vid_Width = 640;\r
- int giTegra2Vid_Height = 480;\r
size_t giTegra2Vid_FramebufferSize;\r
Uint8 *gpTegra2Vid_IOMem;\r
tPAddr gTegra2Vid_FramebufferPhys;\r
{\r
// KeyVal_Parse(&gTegra2Vid_KeyValueParser, Arguments);\r
\r
- gpTegra2Vid_IOMem = (void*)MM_MapHWPages(gTegra2Vid_PhysBase, 1);\r
+ gpTegra2Vid_IOMem = (void*)MM_MapHWPages(gTegra2Vid_PhysBase, 256/4);\r
\r
- Tegra2Vid_int_SetResolution(caTegra2Vid_Modes[0].W, caTegra2Vid_Modes[0].H);\r
+ Tegra2Vid_int_SetMode(4);\r
\r
DevFS_AddDevice( &gTegra2Vid_DriverStruct );\r
\r
if(newMode != giTegra2Vid_CurrentMode)\r
{\r
giTegra2Vid_CurrentMode = newMode;\r
- Tegra2Vid_int_SetResolution( caTegra2Vid_Modes[newMode].W, caTegra2Vid_Modes[newMode].H );\r
+ Tegra2Vid_int_SetMode( newMode );\r
}\r
}\r
ret = giTegra2Vid_CurrentMode;\r
//\r
//\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 Tegra2Vid_int_SetResolution(int W, int H)\r
+int Tegra2Vid_int_SetMode(int Mode)\r
{\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 = 1920;\r
- if(H > 768) H = 1080;\r
-\r
- gpTegra2Vid_IOMem->DCWinAPos = 0;\r
- gpTegra2Vid_IOMem->DCWinASize = (H << 16) | W;\r
-\r
- if( gpTegra2Vid_Framebuffer ) {\r
- MM_UnmapHWPages((tVAddr)gpTegra2Vid_Framebuffer, (giTegra2Vid_FramebufferSize+0xFFF)>>12);\r
- }\r
- giTegra2Vid_FramebufferSize = W*H*4;\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
- gpTegra2Vid_Framebuffer = (void*)MM_AllocDMA( (giTegra2Vid_FramebufferSize+0xFFF)>>12, 32, &gTegra2Vid_FramebufferPhys );\r
- gpTegra2Vid_IOMem->LCDUPBase = gTegra2Vid_FramebufferPhys;\r
- gpTegra2Vid_IOMem->LCDLPBase = 0;\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
+ *(Uint8*)(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
- // 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( gbTegra2Vid_IsVersatile )\r
- {\r
- gpTegra2Vid_IOMem->LCDIMSC = controlWord; // Actually LCDControl\r
- gpTegra2Vid_IOMem->LCDControl = 0; // Actually LCDIMSC\r
- }\r
- else\r
+ if( !gpTegra2Vid_Framebuffer || w*h*4 != giTegra2Vid_FramebufferSize )\r
{\r
- gpTegra2Vid_IOMem->LCDIMSC = 0;\r
- gpTegra2Vid_IOMem->LCDControl = controlWord;\r
- }\r
-\r
- giTegra2Vid_Width = W;\r
- giTegra2Vid_Height = H;\r
+ if( gpTegra2Vid_Framebuffer )\r
+ {\r
+ // TODO: Free framebuffer for reallocation\r
+ }\r
\r
- // Update the DrvUtil buffer info\r
- gTegra2Vid_DrvUtil_BufInfo.Framebuffer = gpTegra2Vid_Framebuffer;\r
- gTegra2Vid_DrvUtil_BufInfo.Pitch = W * 4;\r
- gTegra2Vid_DrvUtil_BufInfo.Width = W;\r
- gTegra2Vid_DrvUtil_BufInfo.Height = H;\r
- gTegra2Vid_DrvUtil_BufInfo.Depth = 32;\r
- \r
- return 0;\r
-}\r
+ giTegra2Vid_FramebufferSize = w*h*4; \r
\r
-int Tegra2_int_SetMode(int Mode)\r
-{\r
- *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_FRONT_PORTCH_0) = (gaTegra2Modes[Mode].VFP << 16) | gaTegra2Modes[Mode].HFP; \r
- *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_SYNC_WIDTH_0) = (gaTegra2Modes[Mode].HS << 16) | gaTegra2Modes[Mode].HS;\r
- *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_BACK_PORTCH_0) = (gaTegra2Modes[Mode].VBP << 16) | gaTegra2Modes[Mode].HBP;\r
- *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_DISP_ACTIVE_0) = (gaTegra2Modes[Mode].VA << 16) | gaTegra2Modes[Mode].HA;\r
-\r
- *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_POSITION_0) = 0;\r
- *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_SIZE_0) = (gaTegra2Modes[Mode].VA << 16) | gaTegra2Modes[Mode].HA;\r
- *(Uint8*)(gpTegra2Vid_IOMem + DC_WIN_A_COLOR_DEPTH_0) = 12; // Could be 13 (BGR/RGB)\r
- *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_PRESCALED_SIZE_0) = (gaTegra2Modes[Mode].VA << 16) | gaTegra2Modes[Mode].HA;\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
+ \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