Modules/Tegra2Vid - Got it compiling
[tpg/acess2.git] / Modules / Display / Tegra2 / 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 Uint64  Tegra2Vid_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer);\r
27 Uint64  Tegra2Vid_Write(tVFS_Node *node, Uint64 off, Uint64 len, 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, Video_Tegra2, Tegra2Vid_Install, NULL, NULL);\r
34 tDevFS_Driver   gTegra2Vid_DriverStruct = {\r
35         NULL, "PL110",\r
36         {\r
37         .Read = Tegra2Vid_Read,\r
38         .Write = Tegra2Vid_Write,\r
39         .IOCtl = Tegra2Vid_IOCtl\r
40         }\r
41 };\r
42 // -- Options\r
43 tPAddr  gTegra2Vid_PhysBase = TEGRA2VID_BASE;\r
44  int    gbTegra2Vid_IsVersatile = 1;\r
45 // -- KeyVal parse rules\r
46 const tKeyVal_ParseRules        gTegra2Vid_KeyValueParser = {\r
47         NULL,\r
48         {\r
49                 {"Base", "P", &gTegra2Vid_PhysBase},\r
50                 {"IsVersatile", "i", &gbTegra2Vid_IsVersatile},\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  int    giTegra2Vid_Width = 640;\r
58  int    giTegra2Vid_Height = 480;\r
59 size_t  giTegra2Vid_FramebufferSize;\r
60 Uint8   *gpTegra2Vid_IOMem;\r
61 tPAddr  gTegra2Vid_FramebufferPhys;\r
62 void    *gpTegra2Vid_Framebuffer;\r
63 // -- Misc\r
64 tDrvUtil_Video_BufInfo  gTegra2Vid_DrvUtil_BufInfo;\r
65 tVideo_IOCtl_Pos        gTegra2Vid_CursorPos;\r
66 \r
67 // === CODE ===\r
68 /**\r
69  */\r
70 int Tegra2Vid_Install(char **Arguments)\r
71 {\r
72 //      KeyVal_Parse(&gTegra2Vid_KeyValueParser, Arguments);\r
73         \r
74         gpTegra2Vid_IOMem = (void*)MM_MapHWPages(gTegra2Vid_PhysBase, 1);\r
75 \r
76         Tegra2Vid_int_SetMode(4);\r
77 \r
78         DevFS_AddDevice( &gTegra2Vid_DriverStruct );\r
79 \r
80         return 0;\r
81 }\r
82 \r
83 /**\r
84  * \brief Clean up resources for driver unloading\r
85  */\r
86 void Tegra2Vid_Uninstall()\r
87 {\r
88 }\r
89 \r
90 /**\r
91  * \brief Read from the framebuffer\r
92  */\r
93 Uint64 Tegra2Vid_Read(tVFS_Node *node, Uint64 off, Uint64 len, void *buffer)\r
94 {\r
95         return 0;\r
96 }\r
97 \r
98 /**\r
99  * \brief Write to the framebuffer\r
100  */\r
101 Uint64 Tegra2Vid_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer)\r
102 {\r
103         gTegra2Vid_DrvUtil_BufInfo.BufferFormat = giTegra2Vid_BufferMode;\r
104         return DrvUtil_Video_WriteLFB(&gTegra2Vid_DrvUtil_BufInfo, Offset, Length, Buffer);\r
105 }\r
106 \r
107 const char *csaTegra2Vid_IOCtls[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL};\r
108 \r
109 /**\r
110  * \brief Handle messages to the device\r
111  */\r
112 int Tegra2Vid_IOCtl(tVFS_Node *Node, int ID, void *Data)\r
113 {\r
114          int    ret = -2;\r
115         ENTER("pNode iID pData", Node, ID, Data);\r
116         \r
117         switch(ID)\r
118         {\r
119         BASE_IOCTLS(DRV_TYPE_VIDEO, "PL110", VERSION, csaTegra2Vid_IOCtls);\r
120 \r
121         case VIDEO_IOCTL_SETBUFFORMAT:\r
122                 DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );\r
123                 ret = giTegra2Vid_BufferMode;\r
124                 if(Data)        giTegra2Vid_BufferMode = *(int*)Data;\r
125                 if(gTegra2Vid_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
126                         DrvUtil_Video_SetCursor( &gTegra2Vid_DrvUtil_BufInfo, &gDrvUtil_TextModeCursor );\r
127                 break;\r
128         \r
129         case VIDEO_IOCTL_GETSETMODE:\r
130                 if(Data)\r
131                 {\r
132                          int    newMode;\r
133                         \r
134                         if( !CheckMem(Data, sizeof(int)) )\r
135                                 LEAVE_RET('i', -1);\r
136                         \r
137                         newMode = *(int*)Data;\r
138                         \r
139                         if(newMode < 0 || newMode >= ciTegra2Vid_ModeCount)\r
140                                 LEAVE_RET('i', -1);\r
141 \r
142                         if(newMode != giTegra2Vid_CurrentMode)\r
143                         {\r
144                                 giTegra2Vid_CurrentMode = newMode;\r
145                                 Tegra2Vid_int_SetMode( newMode );\r
146                         }\r
147                 }\r
148                 ret = giTegra2Vid_CurrentMode;\r
149                 break;\r
150         \r
151         case VIDEO_IOCTL_FINDMODE:\r
152                 {\r
153                 tVideo_IOCtl_Mode *mode = Data;\r
154                  int    closest, closestArea, reqArea = 0;\r
155                 if(!Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)))\r
156                         LEAVE_RET('i', -1);\r
157                 if( mode->bpp != 32 )\r
158                         LEAVE_RET('i', 0);\r
159                 if( mode->flags != 0 )\r
160                         LEAVE_RET('i', 0);\r
161 \r
162                 ret = 0;\r
163 \r
164                 for( int i = 0; i < ciTegra2Vid_ModeCount; i ++ )\r
165                 {\r
166                          int    area;\r
167                         if(mode->width == caTegra2Vid_Modes[i].W && mode->height == caTegra2Vid_Modes[i].H) {\r
168                                 mode->id = i;\r
169                                 ret = 1;\r
170                                 break;\r
171                         }\r
172                         \r
173                         area = caTegra2Vid_Modes[i].W * caTegra2Vid_Modes[i].H;\r
174                         if(!reqArea) {\r
175                                 reqArea = mode->width * mode->height;\r
176                                 closest = i;\r
177                                 closestArea = area;\r
178                         }\r
179                         else if( ABS(area - reqArea) < ABS(closestArea - reqArea) ) {\r
180                                 closest = i;\r
181                                 closestArea = area;\r
182                         }\r
183                 }\r
184                 \r
185                 if( ret == 0 )\r
186                 {\r
187                         mode->id = closest;\r
188                         ret = 1;\r
189                 }\r
190                 mode->width = caTegra2Vid_Modes[mode->id].W;\r
191                 mode->height = caTegra2Vid_Modes[mode->id].H;\r
192                 break;\r
193                 }\r
194         \r
195         case VIDEO_IOCTL_MODEINFO:\r
196                 {\r
197                 tVideo_IOCtl_Mode *mode = Data;\r
198                 if(!Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Mode)))\r
199                         LEAVE_RET('i', -1);\r
200                 if(mode->id < 0 || mode->id >= ciTegra2Vid_ModeCount)\r
201                         LEAVE_RET('i', 0);\r
202                 \r
203 \r
204                 mode->bpp = 32;\r
205                 mode->flags = 0;\r
206                 mode->width = caTegra2Vid_Modes[mode->id].W;\r
207                 mode->height = caTegra2Vid_Modes[mode->id].H;\r
208 \r
209                 ret = 1;\r
210                 break;\r
211                 }\r
212         \r
213         case VIDEO_IOCTL_SETCURSOR:\r
214                 if( !Data || !CheckMem(Data, sizeof(tVideo_IOCtl_Pos)) )\r
215                         LEAVE_RET('i', -1);\r
216 \r
217                 DrvUtil_Video_RemoveCursor( &gTegra2Vid_DrvUtil_BufInfo );\r
218                 \r
219                 gTegra2Vid_CursorPos = *(tVideo_IOCtl_Pos*)Data;\r
220                 if(gTegra2Vid_DrvUtil_BufInfo.BufferFormat == VIDEO_BUFFMT_TEXT)\r
221                         DrvUtil_Video_DrawCursor(\r
222                                 &gTegra2Vid_DrvUtil_BufInfo,\r
223                                 gTegra2Vid_CursorPos.x*giVT_CharWidth,\r
224                                 gTegra2Vid_CursorPos.y*giVT_CharHeight\r
225                                 );\r
226                 else\r
227                         DrvUtil_Video_DrawCursor(\r
228                                 &gTegra2Vid_DrvUtil_BufInfo,\r
229                                 gTegra2Vid_CursorPos.x,\r
230                                 gTegra2Vid_CursorPos.y\r
231                                 );\r
232                 break;\r
233         \r
234         default:\r
235                 LEAVE('i', -2);\r
236                 return -2;\r
237         }\r
238         \r
239         LEAVE('i', ret);\r
240         return ret;\r
241 }\r
242 \r
243 //\r
244 //\r
245 //\r
246 \r
247 int Tegra2Vid_int_SetMode(int Mode)\r
248 {\r
249         const struct sTegra2_Disp_Mode  *mode = &caTegra2Vid_Modes[Mode];\r
250          int    w = mode->W, h = mode->H;       // Horizontal/Vertical Active\r
251         *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_FRONT_PORCH_0) = (mode->VFP << 16) | mode->HFP; \r
252         *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_SYNC_WIDTH_0)  = (mode->HS << 16)  | mode->HS;\r
253         *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_BACK_PORCH_0)  = (mode->VBP << 16) | mode->HBP;\r
254         *(Uint32*)(gpTegra2Vid_IOMem + DC_DISP_DISP_ACTIVE_0) = (mode->H << 16)   | mode->W;\r
255 \r
256         *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_POSITION_0) = 0;\r
257         *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_SIZE_0) = (mode->H << 16) | mode->W;\r
258         *(Uint8*)(gpTegra2Vid_IOMem + DC_WIN_A_COLOR_DEPTH_0) = 12;     // Could be 13 (BGR/RGB)\r
259         *(Uint32*)(gpTegra2Vid_IOMem + DC_WIN_A_PRESCALED_SIZE_0) = (mode->H << 16) | mode->W;\r
260 \r
261         if( !gpTegra2Vid_Framebuffer || w*h*4 != giTegra2Vid_FramebufferSize )\r
262         {\r
263                 if( gpTegra2Vid_Framebuffer )\r
264                 {\r
265                         // TODO: Free framebuffer for reallocation\r
266                 }\r
267 \r
268                 giTegra2Vid_FramebufferSize = w*h*4;            \r
269 \r
270                 gpTegra2Vid_Framebuffer = (void*)MM_AllocDMA(\r
271                         (giTegra2Vid_FramebufferSize + PAGE_SIZE-1) / PAGE_SIZE,\r
272                         32,\r
273                         &gTegra2Vid_FramebufferPhys\r
274                         );\r
275                 // TODO: Catch allocation failures\r
276                 \r
277                 // Tell hardware\r
278                 *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_START_ADDR_0) = gTegra2Vid_FramebufferPhys;\r
279                 *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_V_OFFSET_0) = 0;        // Y offset\r
280                 *(Uint32*)(gpTegra2Vid_IOMem + DC_WINBUF_A_ADDR_H_OFFSET_0) = 0;        // X offset\r
281         }\r
282 \r
283         return 0;\r
284 }\r

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