Modules/Tegra2Vid - Fiddling!
[tpg/acess2.git] / KernelLand / Modules / Display / Tegra2Vid / main.c
1 /**\r
2  * main.c\r
3  * - Driver core\r
4  */\r
5 #define DEBUG   0\r
6 #define VERSION ((0<<8)|10)\r
7 #include <acess.h>\r
8 #include <errno.h>\r
9 #include <modules.h>\r
10 #include <vfs.h>\r
11 #include <fs_devfs.h>\r
12 #include <drv_pci.h>\r
13 #include <api_drv_video.h>\r
14 #include <lib/keyvalue.h>\r
15 #include <options.h>    // ARM Arch\r
16 #include "tegra2.h"\r
17 \r
18 #define ABS(a)  ((a)>0?(a):-(a))\r
19 \r
20 // === PROTOTYPES ===\r
21 // Driver\r
22  int    Tegra2Vid_Install(char **Arguments);\r
23 void    Tegra2Vid_Uninstall();\r
24 // Internal\r
25 // Filesystem\r
26 size_t  Tegra2Vid_Read(tVFS_Node *node, off_t off, size_t len, void *buffer);\r
27 size_t  Tegra2Vid_Write(tVFS_Node *node, off_t off, size_t len, const void *buffer);\r
28  int    Tegra2Vid_IOCtl(tVFS_Node *node, int id, void *data);\r
29 // -- Internals\r
30  int    Tegra2Vid_int_SetMode(int Mode);\r
31 \r
32 // === GLOBALS ===\r
33 MODULE_DEFINE(0, VERSION, Tegra2Vid, Tegra2Vid_Install, NULL, NULL);\r
34 tVFS_NodeType   gTegra2Vid_NodeType = {\r
35         .Read = Tegra2Vid_Read,\r
36         .Write = Tegra2Vid_Write,\r
37         .IOCtl = Tegra2Vid_IOCtl\r
38         };\r
39 tDevFS_Driver   gTegra2Vid_DriverStruct = {\r
40         NULL, "Tegra2Vid",\r
41         {.Type = &gTegra2Vid_NodeType}\r
42 };\r
43 // -- Options\r
44 tPAddr  gTegra2Vid_PhysBase = TEGRA2VID_BASE;\r
45  int    gbTegra2Vid_IsVersatile = 1;\r
46 // -- KeyVal parse rules\r
47 const tKeyVal_ParseRules        gTegra2Vid_KeyValueParser = {\r
48         NULL,\r
49         {\r
50                 {"Base", "P", &gTegra2Vid_PhysBase},\r
51                 {NULL, NULL, NULL}\r
52         }\r
53 };\r
54 // -- Driver state\r
55  int    giTegra2Vid_CurrentMode = 0;\r
56  int    giTegra2Vid_BufferMode;\r
57 size_t  giTegra2Vid_FramebufferSize;\r
58 Uint32  *gpTegra2Vid_IOMem;\r
59 tPAddr  gTegra2Vid_FramebufferPhys;\r
60 void    *gpTegra2Vid_Framebuffer;\r
61 // -- Misc\r
62 tDrvUtil_Video_BufInfo  gTegra2Vid_DrvUtil_BufInfo;\r
63 tVideo_IOCtl_Pos        gTegra2Vid_CursorPos;\r
64 \r
65 // === CODE ===\r
66 /**\r
67  */\r
68 int Tegra2Vid_Install(char **Arguments)\r
69 {\r
70         return MODULE_ERR_NOTNEEDED;\r
71 //      KeyVal_Parse(&gTegra2Vid_KeyValueParser, Arguments);\r
72 \r
73         gpTegra2Vid_IOMem = (void*)MM_MapHWPages(gTegra2Vid_PhysBase, 256/4);\r
74         {\r
75                 Log_Debug("Tegra2Vid", "Display CMD Registers");\r
76                 for( int i = 0x000; i <= 0x01A; i ++ )\r
77                         Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
78                 for( int i = 0x028; i <= 0x043; i ++ )\r
79                         Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
80                 Log_Debug("Tegra2Vid", "Display COM Registers");\r
81                 for( int i = 0x300; i <= 0x329; i ++ )\r
82                         Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
83                 Log_Debug("Tegra2Vid", "Display DISP Registers");\r
84                 for( int i = 0x400; i <= 0x446; i ++ )\r
85                         Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
86                 for( int i = 0x480; i <= 0x484; i ++ )\r
87                         Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
88                 for( int i = 0x4C0; i <= 0x4C1; i ++ )\r
89                         Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
90 \r
91                 Log_Debug("Tegra2Vid", "WINC_A Registers");\r
92                 for( int i = 0x700; i <= 0x714; i ++ )\r
93                         Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
94                 Log_Debug("Tegra2Vid", "WINBUF_A");\r
95                 for( int i = 0x800; i <= 0x80A; i ++ )\r
96                         Log_Debug("Tegra2Vid", "[0x%03x] = 0x%08x", i, gpTegra2Vid_IOMem[i]);\r
97         }\r
98 //      return 1;\r
99 \r
100         // HACK!!!\r
101 #if 0\r
102         {\r
103                 int     w = 1680, h = 1050;\r
104                 gpTegra2Vid_IOMem[DC_DISP_DISP_ACTIVE_0] = (h << 16) | w;\r
105                 gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0] = (h << 16) | w;\r
106                 gpTegra2Vid_IOMem[DC_WIN_A_PRESCALED_SIZE_0] = (h << 16) | w;\r
107         }\r
108 #endif\r
109 \r
110         giTegra2Vid_FramebufferSize =\r
111                 (gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]&0xFFFF)\r
112                 *(gpTegra2Vid_IOMem[DC_WIN_A_SIZE_0]>>16)*4;\r
113 \r
114         Log_Debug("Tegra2Vid", "giTegra2Vid_FramebufferSize = 0x%x", giTegra2Vid_FramebufferSize);\r
115         gpTegra2Vid_Framebuffer = (void*)MM_MapHWPages(\r
116                 gpTegra2Vid_IOMem[DC_WINBUF_A_START_ADDR_0],\r
117                 (giTegra2Vid_FramebufferSize+PAGE_SIZE-1)/PAGE_SIZE\r
118                 );\r
119         memset(gpTegra2Vid_Framebuffer, 0xFF, 0x1000);\r
120 \r
121 //      gpTegra2Vid_IOMem[DC_WIN_A_WIN_OPTIONS_0] &= ~0x40;\r
122 //      gpTegra2Vid_IOMem[DC_WIN_A_COLOR_DEPTH_0] = 12; // Could be 13 (BGR/RGB)\r
123         gTegra2Vid_DrvUtil_BufInfo.Width = 1024;\r
124         gTegra2Vid_DrvUtil_BufInfo.Height = 768;\r
125         gTegra2Vid_DrvUtil_BufInfo.Pitch = 1024*4;\r
126         gTegra2Vid_DrvUtil_BufInfo.Depth = 32;\r
127         gTegra2Vid_DrvUtil_BufInfo.Framebuffer = gpTegra2Vid_Framebuffer;\r
128 \r
129 \r
130 //      Tegra2Vid_int_SetMode(4);\r
131 \r
132         DevFS_AddDevice( &gTegra2Vid_DriverStruct );\r
133 \r
134         return 0;\r
135 }\r
136 \r
137 /**\r
138  * \brief Clean up resources for driver unloading\r
139  */\r
140 void Tegra2Vid_Uninstall()\r
141 {\r
142 }\r
143 \r
144 /**\r
145  * \brief Read from the framebuffer\r
146  */\r
147 size_t Tegra2Vid_Read(tVFS_Node *node, off_t off, size_t len, void *buffer)\r
148 {\r
149         return 0;\r
150 }\r
151 \r
152 /**\r
153  * \brief Write to the framebuffer\r
154  */\r
155 size_t Tegra2Vid_Write(tVFS_Node *Node, off_t Offset, size_t Length, const void *Buffer)\r
156 {\r
157         gTegra2Vid_DrvUtil_BufInfo.BufferFormat = giTegra2Vid_BufferMode;\r
158         return DrvUtil_Video_WriteLFB(&gTegra2Vid_DrvUtil_BufInfo, Offset, Length, Buffer);\r
159 }\r
160 \r
161 const char *csaTegra2Vid_IOCtls[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL};\r
162 \r
163 /**\r
164  * \brief Handle messages to the device\r
165  */\r
166 int Tegra2Vid_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
167 {\r
168          int    ret = -2;\r
169         ENTER("pNode iID pData", Node, ID, Data);\r
170         \r
171         switch(ID)\r
172         {\r
173         BASE_IOCTLS(DRV_TYPE_VIDEO, "PL110", VERSION, csaTegra2Vid_IOCtls);\r
174 \r
175         case VIDEO_IOCTL_SETBUFFORMAT:\r
176                 DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );\r
177                 ret = giTegra2Vid_BufferMode;\r
178                 if(Data)        giTegra2Vid_BufferMode = *(int*)Data;\r
179                 if(gTegra2Vid_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
180                         DrvUtil_Video_SetCursor( &gTegra2Vid_DrvUtil_BufInfo, &gDrvUtil_TextModeCursor );\r
181                 break;\r
182         \r
183         case VIDEO_IOCTL_GETSETMODE:\r
184                 if(Data)\r
185                 {\r
186                          int    newMode;\r
187                         \r
188                         if( !CheckMem(Data, sizeof(int)) )\r
189                                 LEAVE_RET('i', -1);\r
190                         \r
191                         newMode = *(int*)Data;\r
192                         \r
193                         if(newMode < 0 || newMode >= ciTegra2Vid_ModeCount)\r
194                                 LEAVE_RET('i', -1);\r
195 \r
196                         if(newMode != giTegra2Vid_CurrentMode)\r
197                         {\r
198                                 giTegra2Vid_CurrentMode = newMode;\r
199                                 Tegra2Vid_int_SetMode( newMode );\r
200                         }\r
201                 }\r
202                 ret = giTegra2Vid_CurrentMode;\r
203                 break;\r
204         \r
205         case VIDEO_IOCTL_FINDMODE:\r
206                 {\r
207                 tVideo_IOCtl_Mode *mode = Data;\r
208                  int    closest=0, closestArea, reqArea = 0;\r
209                 if(!Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)))\r
210                         LEAVE_RET('i', -1);\r
211                 if( mode->bpp != 32 )\r
212                         LEAVE_RET('i', 0);\r
213                 if( mode->flags != 0 )\r
214                         LEAVE_RET('i', 0);\r
215 \r
216                 ret = 0;\r
217 \r
218                 for( int i = 0; i < ciTegra2Vid_ModeCount; i ++ )\r
219                 {\r
220                          int    area;\r
221                         if(mode->width == caTegra2Vid_Modes[i].W && mode->height == caTegra2Vid_Modes[i].H) {\r
222                                 mode->id = i;\r
223                                 ret = 1;\r
224                                 break;\r
225                         }\r
226                         \r
227                         area = caTegra2Vid_Modes[i].W * caTegra2Vid_Modes[i].H;\r
228                         if(!reqArea) {\r
229                                 reqArea = mode->width * mode->height;\r
230                                 closest = i;\r
231                                 closestArea = area;\r
232                         }\r
233                         else if( ABS(area - reqArea) < ABS(closestArea - reqArea) ) {\r
234                                 closest = i;\r
235                                 closestArea = area;\r
236                         }\r
237                 }\r
238                 \r
239                 if( ret == 0 )\r
240                 {\r
241                         mode->id = closest;\r
242                         ret = 1;\r
243                 }\r
244                 mode->width = caTegra2Vid_Modes[mode->id].W;\r
245                 mode->height = caTegra2Vid_Modes[mode->id].H;\r
246                 break;\r
247                 }\r
248         \r
249         case VIDEO_IOCTL_MODEINFO:\r
250                 {\r
251                 tVideo_IOCtl_Mode *mode = Data;\r
252                 if(!Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)))\r
253                         LEAVE_RET('i', -1);\r
254                 if(mode->id < 0 || mode->id >= ciTegra2Vid_ModeCount)\r
255                         LEAVE_RET('i', 0);\r
256                 \r
257 \r
258                 mode->bpp = 32;\r
259                 mode->flags = 0;\r
260                 mode->width = caTegra2Vid_Modes[mode->id].W;\r
261                 mode->height = caTegra2Vid_Modes[mode->id].H;\r
262 \r
263                 ret = 1;\r
264                 break;\r
265                 }\r
266         \r
267         case VIDEO_IOCTL_SETCURSOR:\r
268                 if( !Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Pos)) )\r
269                         LEAVE_RET('i', -1);\r
270 \r
271                 DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );\r
272                 \r
273                 gTegra2Vid_CursorPos = *(tVideo_IOCtl_Pos*)Data;\r
274                 if(gTegra2Vid_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
275                         DrvUtil_Video_DrawCursor(\r
276                                 &gTegra2Vid_DrvUtil_BufInfo,\r
277                                 gTegra2Vid_CursorPos.x*giVT_CharWidth,\r
278                                 gTegra2Vid_CursorPos.y*giVT_CharHeight\r
279                                 );\r
280                 else\r
281                         DrvUtil_Video_DrawCursor(\r
282                                 &gTegra2Vid_DrvUtil_BufInfo,\r
283                                 gTegra2Vid_CursorPos.x,\r
284                                 gTegra2Vid_CursorPos.y\r
285                                 );\r
286                 break;\r
287         \r
288         default:\r
289                 LEAVE('i', -2);\r
290                 return -2;\r
291         }\r
292         \r
293         LEAVE('i', ret);\r
294         return ret;\r
295 }\r
296 \r
297 //\r
298 //\r
299 //\r
300 \r
301 int Tegra2Vid_int_SetMode(int Mode)\r
302 {\r
303         const struct sTegra2_Disp_Mode  *mode = &caTegra2Vid_Modes[Mode];\r
304          int    w = mode->W, h = mode->H;       // Horizontal/Vertical Active\r
305         *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_FRONT_PORCH_0) = (mode->VFP << 16) | mode->HFP; \r
306         *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_SYNC_WIDTH_0)  = (mode->HS << 16)  | mode->HS;\r
307         *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_BACK_PORCH_0)  = (mode->VBP << 16) | mode->HBP;\r
308         *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_DISP_ACTIVE_0) = (mode->H << 16)   | mode->W;\r
309 \r
310         *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_POSITION_0) = 0;\r
311         *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_SIZE_0) = (h << 16) | w;\r
312         *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_DISP_COLOR_CONTROL_0) = 0x8;     // BASE888\r
313         *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_COLOR_DEPTH_0) = 12;    // Could be 13 (BGR/RGB)\r
314         *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_PRESCALED_SIZE_0) = (h << 16) | w;\r
315 \r
316         Log_Debug("Tegra2Vid", "Mode %i (%ix%i) selected", Mode, w, h);\r
317 \r
318         if( !gpTegra2Vid_Framebuffer || w*h*4 != giTegra2Vid_FramebufferSize )\r
319         {\r
320                 if( gpTegra2Vid_Framebuffer )\r
321                 {\r
322                         // TODO: Free framebuffer for reallocation\r
323                 }\r
324 \r
325                 giTegra2Vid_FramebufferSize = w*h*4;            \r
326 \r
327                 gpTegra2Vid_Framebuffer = (void*)MM_AllocDMA(\r
328                         (giTegra2Vid_FramebufferSize + PAGE_SIZE-1) / PAGE_SIZE,\r
329                         32,\r
330                         &gTegra2Vid_FramebufferPhys\r
331                         );\r
332                 // TODO: Catch allocation failures\r
333                 Log_Debug("Tegra2Vid", "0x%x byte framebuffer at %p (%P phys)",\r
334                                 giTegra2Vid_FramebufferSize,\r
335                                 gpTegra2Vid_Framebuffer,\r
336                                 gTegra2Vid_FramebufferPhys\r
337                                 );\r
338                 \r
339                 // Tell hardware\r
340                 *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_START_ADDR_0) = gTegra2Vid_FramebufferPhys;\r
341                 *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_V_OFFSET_0) = 0;        // Y offset\r
342                 *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_H_OFFSET_0) = 0;        // X offset\r
343         }\r
344 \r
345         return 0;\r
346 }\r

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