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

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