disable fb blank handling
[sgx.git] / services4 / 3rdparty / dc_omap3_linux / omaplfb_displayclass.c
1 /**********************************************************************
2  *
3  * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
4  * 
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  * 
9  * This program is distributed in the hope it will be useful but, except 
10  * as otherwise stated in writing, without any warranty; without even the 
11  * implied warranty of merchantability or fitness for a particular purpose. 
12  * See the GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License along with
15  * this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17  * 
18  * The full GNU General Public License is included in this distribution in
19  * the file called "COPYING".
20  *
21  * Contact Information:
22  * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23  * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK 
24  *
25  ******************************************************************************/
26
27 #include <linux/version.h>
28 #include <linux/kernel.h>
29 #include <linux/console.h>
30 #include <linux/fb.h>
31 #include <linux/module.h>
32 #include <linux/string.h>
33 #include <linux/notifier.h>
34
35 #include "img_defs.h"
36 #include "servicesext.h"
37 #include "kerneldisplay.h"
38 #include "omaplfb.h"
39
40 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
41 #define acquire_console_sem console_lock
42 #define release_console_sem console_unlock
43 #endif
44
45 static void *gpvAnchor;
46
47 static int fb_idx = 0;
48
49 #define OMAPLFB_COMMAND_COUNT           1
50
51 static PFN_DC_GET_PVRJTABLE pfnGetPVRJTable = 0;
52 static void OMAPLFBVSyncIHandler(struct work_struct*);
53
54 #define OMAPLFB_PAGE_SIZE 4096
55
56 /* Greatest common divisor */
57 static unsigned long gcd(unsigned long a, unsigned long b)
58 {
59         unsigned long r;
60
61         if (a < b) {
62                 r = a;
63                 a = b;
64                 b = r;
65         }
66
67         while ((r = a % b) != 0) {
68                 a = b;
69                 b = r;
70         }
71
72         return b;
73 }
74
75 /*
76  * Workout the smallest size that is aligned to both 4K (for the SGX)
77  * and line length (for the fbdev driver).
78  */
79 static unsigned int sgx_buffer_align(unsigned stride, unsigned size)
80 {
81         unsigned lcm;
82
83         if (!stride || !size)
84                 return 0;
85
86         lcm = stride * OMAPLFB_PAGE_SIZE / gcd(stride,
87                                                OMAPLFB_PAGE_SIZE);
88
89         return roundup(size, lcm);
90 }
91
92 OMAPLFB_DEVINFO * GetAnchorPtr(void)
93 {
94         return (OMAPLFB_DEVINFO *)gpvAnchor;
95 }
96
97 static void SetAnchorPtr(OMAPLFB_DEVINFO *psDevInfo)
98 {
99         gpvAnchor = (void*)psDevInfo;
100 }
101
102         
103 static void FlushInternalVSyncQueue(OMAPLFB_SWAPCHAIN *psSwapChain)
104 {
105         OMAPLFB_VSYNC_FLIP_ITEM *psFlipItem;
106         unsigned long            ulMaxIndex;
107         unsigned long            i;
108
109         
110         psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
111         ulMaxIndex = psSwapChain->ulBufferCount - 1;
112
113         for(i = 0; i < psSwapChain->ulBufferCount; i++)
114         {
115                 if (psFlipItem->bValid == OMAP_FALSE)
116                 {
117                         continue;
118                 }
119
120                 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": FlushInternalVSyncQueue: Flushing swap buffer (index %lu)\n", psSwapChain->ulRemoveIndex));
121
122                 if(psFlipItem->bFlipped == OMAP_FALSE)
123                 {
124                         
125                         OMAPLFBFlip(psSwapChain, (unsigned long)psFlipItem->sSysAddr);
126                 }
127                 
128                 if(psFlipItem->bCmdCompleted == OMAP_FALSE)
129                 {
130                         DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX ": FlushInternalVSyncQueue: Calling command complete for swap buffer (index %lu)\n", psSwapChain->ulRemoveIndex));
131
132                         psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete((IMG_HANDLE)psFlipItem->hCmdComplete, IMG_TRUE);
133                 }
134
135                 
136                 psSwapChain->ulRemoveIndex++;
137                 
138                 if(psSwapChain->ulRemoveIndex > ulMaxIndex)
139                 {
140                         psSwapChain->ulRemoveIndex = 0;
141                 }
142
143                 
144                 psFlipItem->bFlipped = OMAP_FALSE;
145                 psFlipItem->bCmdCompleted = OMAP_FALSE;
146                 psFlipItem->bValid = OMAP_FALSE;
147                 
148                 
149                 psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
150         }
151
152         psSwapChain->ulInsertIndex = 0;
153         psSwapChain->ulRemoveIndex = 0;
154 }
155
156 static void SetFlushStateInternalNoLock(OMAPLFB_DEVINFO* psDevInfo,
157                                         OMAP_BOOL bFlushState)
158 {
159         OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
160
161         if (psSwapChain == NULL)
162         {
163                 return;
164         }
165
166         if (bFlushState)
167         {
168                 if (psSwapChain->ulSetFlushStateRefCount == 0)
169                 {
170                         psSwapChain->bFlushCommands = OMAP_TRUE;
171                         FlushInternalVSyncQueue(psSwapChain);
172                 }
173                 psSwapChain->ulSetFlushStateRefCount++;
174         }
175         else
176         {
177                 if (psSwapChain->ulSetFlushStateRefCount != 0)
178                 {
179                         psSwapChain->ulSetFlushStateRefCount--;
180                         if (psSwapChain->ulSetFlushStateRefCount == 0)
181                         {
182                                 psSwapChain->bFlushCommands = OMAP_FALSE;
183                         }
184                 }
185         }
186 }
187
188 static IMG_VOID SetFlushStateInternal(OMAPLFB_DEVINFO* psDevInfo,
189                                       OMAP_BOOL bFlushState)
190 {
191         mutex_lock(&psDevInfo->sSwapChainLockMutex);
192         
193         SetFlushStateInternalNoLock(psDevInfo, bFlushState);
194
195         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
196 }
197
198 static void SetFlushStateExternal(OMAPLFB_DEVINFO* psDevInfo,
199                                   OMAP_BOOL bFlushState)
200 {
201         mutex_lock(&psDevInfo->sSwapChainLockMutex);
202
203         
204         if (psDevInfo->bFlushCommands != bFlushState)
205         {
206                 psDevInfo->bFlushCommands = bFlushState;
207                 SetFlushStateInternalNoLock(psDevInfo, bFlushState);
208         }
209
210         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
211 }
212
213 static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
214 {
215         OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)hDevice;
216
217         switch (ui32State)
218         {
219                 case DC_STATE_FLUSH_COMMANDS:
220                         SetFlushStateExternal(psDevInfo, OMAP_TRUE);
221                         break;
222                 case DC_STATE_NO_FLUSH_COMMANDS:
223                         SetFlushStateExternal(psDevInfo, OMAP_FALSE);
224                         break;
225                 default:
226                         break;
227         }
228
229         return;
230 }
231
232 static int FrameBufferEvents(struct notifier_block *psNotif,
233                              unsigned long event, void *data)
234 {
235         OMAPLFB_DEVINFO *psDevInfo;
236         OMAPLFB_SWAPCHAIN *psSwapChain;
237         struct fb_event *psFBEvent = (struct fb_event *)data;
238         OMAP_BOOL bBlanked;
239
240         
241         if (event != FB_EVENT_BLANK)
242         {
243                 return 0;
244         }
245
246         psDevInfo = GetAnchorPtr();
247         psSwapChain = psDevInfo->psSwapChain;
248
249         bBlanked = (*(IMG_INT *)psFBEvent->data != 0) ? OMAP_TRUE: OMAP_FALSE;
250
251         if (bBlanked != psSwapChain->bBlanked)
252         {
253                 psSwapChain->bBlanked = bBlanked;
254
255                 if (bBlanked)
256                 {
257                         
258                         SetFlushStateInternal(psDevInfo, OMAP_TRUE);
259                 }
260                 else
261                 {
262                         
263                         SetFlushStateInternal(psDevInfo, OMAP_FALSE);
264                 }
265         }
266
267         return 0;
268 }
269
270
271 static OMAP_ERROR UnblankDisplay(OMAPLFB_DEVINFO *psDevInfo)
272 {
273         int res;
274
275         acquire_console_sem();
276         res = fb_blank(psDevInfo->psLINFBInfo, 0);
277         release_console_sem();
278         if (res != 0 && res != -EINVAL)
279         {
280                 printk(KERN_WARNING DRIVER_PREFIX
281                         ": fb_blank failed (%d)", res);
282                 return (OMAP_ERROR_GENERIC);
283         }
284
285         return (OMAP_OK);
286 }
287
288 #if defined (CONFIG_OMAP2_DSS)
289 #include <linux/omapfb.h>
290 #include <linux/workqueue.h>
291 struct wq_flip {
292         struct fb_var_screeninfo var;
293             struct fb_info *psLINFBInfo; 
294         struct work_struct work;
295 };
296 struct wq_flip wq_flipdss2;
297
298 static void dss2_pan_display (struct work_struct *work)
299 {
300     struct wq_flip *ptrwq_flip =
301             container_of(work, struct wq_flip, work);
302     if (ptrwq_flip->psLINFBInfo->fbops->fb_pan_display != NULL) {
303         ptrwq_flip->psLINFBInfo->fbops->fb_pan_display (&ptrwq_flip->var, ptrwq_flip->psLINFBInfo);
304
305     }
306
307 }
308
309 /*
310          Flip implementation for DSS2 using fb_pan_display
311 */
312 IMG_VOID OMAPLFBFlipDSS2(OMAPLFB_SWAPCHAIN *psSwapChain,
313                                                   IMG_UINT32 aPhyAddr, int now)
314 {
315         OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr ();
316         struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
317         memcpy ( &wq_flipdss2.var, &psLINFBInfo->var, sizeof(struct fb_var_screeninfo)); 
318     wq_flipdss2.var.yoffset = (aPhyAddr-psLINFBInfo->fix.smem_start)/psLINFBInfo->fix.line_length;
319         wq_flipdss2.psLINFBInfo = psLINFBInfo;
320         if (now)
321                 dss2_pan_display(&wq_flipdss2.work);
322         else
323                 schedule_work (&wq_flipdss2.work);
324 }
325 #endif
326
327 void OMAPLFBFlip(OMAPLFB_SWAPCHAIN *psSwapChain, unsigned long aPhyAddr)
328 {
329         OMAPLFBFlipDSS2 (psSwapChain, aPhyAddr, 0);
330 }
331
332 void OMAPLFBWaitForVSync(void)
333 {
334 #if 0
335         if (lcd_mgr && lcd_mgr->device) 
336                 lcd_mgr->device->wait_vsync(lcd_mgr->device);
337 #endif
338 }
339
340 static OMAP_ERROR EnableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
341 {
342         OMAP_ERROR         eError;
343 #if 0
344         int                res;
345         OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
346
347         
348         memset(&psDevInfo->sLINNotifBlock, 0, sizeof(psDevInfo->sLINNotifBlock));
349
350         psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;
351
352         psSwapChain->bBlanked = OMAP_FALSE;
353
354         res = fb_register_client(&psDevInfo->sLINNotifBlock);
355         if (res != 0)
356         {
357                 printk(KERN_WARNING DRIVER_PREFIX
358                         ": fb_register_client failed (%d)", res);
359
360                 return (OMAP_ERROR_GENERIC);
361         }
362 #endif
363         eError = UnblankDisplay(psDevInfo);
364         if (eError != OMAP_OK)
365         {
366                 DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
367                         ": UnblankDisplay failed (%d)", eError));
368                 return eError;
369         }
370
371         return (OMAP_OK);
372 }
373
374 static OMAP_ERROR DisableLFBEventNotification(OMAPLFB_DEVINFO *psDevInfo)
375 {
376 #if 0
377         int res;
378
379         
380         res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
381         if (res != 0)
382         {
383                 printk(KERN_WARNING DRIVER_PREFIX
384                         ": fb_unregister_client failed (%d)", res);
385                 return (OMAP_ERROR_GENERIC);
386         }
387 #endif
388         return (OMAP_OK);
389 }
390
391 static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 ui32DeviceID,
392                                  IMG_HANDLE *phDevice,
393                                  PVRSRV_SYNC_DATA* psSystemBufferSyncData)
394 {
395         OMAPLFB_DEVINFO *psDevInfo;
396         OMAP_ERROR eError;
397
398         UNREFERENCED_PARAMETER(ui32DeviceID);
399
400         psDevInfo = GetAnchorPtr();
401
402         
403         psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
404         
405         eError = UnblankDisplay(psDevInfo);
406         if (eError != OMAP_OK)
407         {
408                 DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
409                         ": UnblankDisplay failed (%d)", eError));
410                 return (PVRSRV_ERROR_GENERIC);
411         }
412
413         
414         *phDevice = (IMG_HANDLE)psDevInfo;
415         
416         return (PVRSRV_OK);
417 }
418
419 static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
420 {
421         UNREFERENCED_PARAMETER(hDevice);
422
423         return (PVRSRV_OK);
424 }
425
426 static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
427                                   IMG_UINT32 *pui32NumFormats,
428                                   DISPLAY_FORMAT *psFormat)
429 {
430         OMAPLFB_DEVINFO *psDevInfo;
431         
432         if(!hDevice || !pui32NumFormats)
433         {
434                 return (PVRSRV_ERROR_INVALID_PARAMS);
435         }
436
437         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
438         
439         *pui32NumFormats = 1;
440         
441         if(psFormat)
442         {
443                 psFormat[0] = psDevInfo->sDisplayFormat;
444         }
445
446         return (PVRSRV_OK);
447 }
448
449 static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice, 
450                                DISPLAY_FORMAT *psFormat,
451                                IMG_UINT32 *pui32NumDims,
452                                DISPLAY_DIMS *psDim)
453 {
454         OMAPLFB_DEVINFO *psDevInfo;
455
456         if(!hDevice || !psFormat || !pui32NumDims)
457         {
458                 return (PVRSRV_ERROR_INVALID_PARAMS);
459         }
460
461         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
462
463         *pui32NumDims = 1;
464
465         
466         if(psDim)
467         {
468                 psDim[0] = psDevInfo->sDisplayDim;
469         }
470         
471         return (PVRSRV_OK);
472 }
473
474
475 static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE *phBuffer)
476 {
477         OMAPLFB_DEVINFO *psDevInfo;
478         
479         if(!hDevice || !phBuffer)
480         {
481                 return (PVRSRV_ERROR_INVALID_PARAMS);
482         }
483
484         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
485
486         *phBuffer = (IMG_HANDLE)&psDevInfo->sSystemBuffer;
487
488         return (PVRSRV_OK);
489 }
490
491
492 static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
493 {
494         OMAPLFB_DEVINFO *psDevInfo;
495         
496         if(!hDevice || !psDCInfo)
497         {
498                 return (PVRSRV_ERROR_INVALID_PARAMS);
499         }
500
501         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
502
503         *psDCInfo = psDevInfo->sDisplayInfo;
504
505         return (PVRSRV_OK);
506 }
507
508 static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE        hDevice,
509                                     IMG_HANDLE        hBuffer, 
510                                     IMG_SYS_PHYADDR   **ppsSysAddr,
511                                     IMG_UINT32        *pui32ByteSize,
512                                     IMG_VOID          **ppvCpuVAddr,
513                                     IMG_HANDLE        *phOSMapInfo,
514                                     IMG_BOOL          *pbIsContiguous)
515 {
516         OMAPLFB_DEVINFO *psDevInfo;
517         OMAPLFB_BUFFER *psSystemBuffer;
518
519         if(!hDevice)
520         {
521                 return (PVRSRV_ERROR_INVALID_PARAMS);
522         }
523         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
524         
525         if(!hBuffer)
526         {
527                 return (PVRSRV_ERROR_INVALID_PARAMS);
528         }
529         psSystemBuffer = (OMAPLFB_BUFFER *)hBuffer;
530
531         if (!ppsSysAddr)
532         {
533                 return (PVRSRV_ERROR_INVALID_PARAMS);
534         }
535
536         *ppsSysAddr = &psSystemBuffer->sSysAddr;
537
538         if (!pui32ByteSize)
539         {
540                 return (PVRSRV_ERROR_INVALID_PARAMS);
541         }
542
543         *pui32ByteSize = (IMG_UINT32)psDevInfo->sFBInfo.ulBufferSize;
544
545         if (ppvCpuVAddr)
546         {
547                 *ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
548         }
549
550         if (phOSMapInfo)
551         {
552                 *phOSMapInfo = (IMG_HANDLE)0;
553         }
554
555         if (pbIsContiguous)
556         {
557                 *pbIsContiguous = IMG_TRUE;
558         }
559
560         return (PVRSRV_OK);
561 }
562
563 static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
564                                       IMG_UINT32 ui32Flags,
565                                       DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
566                                       DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
567                                       IMG_UINT32 ui32BufferCount,
568                                       PVRSRV_SYNC_DATA **ppsSyncData,
569                                       IMG_UINT32 ui32OEMFlags,
570                                       IMG_HANDLE *phSwapChain,
571                                       IMG_UINT32 *pui32SwapChainID)
572 {
573         OMAPLFB_DEVINFO *psDevInfo;
574         OMAPLFB_SWAPCHAIN *psSwapChain;
575         OMAPLFB_BUFFER *psBuffer;
576         OMAPLFB_VSYNC_FLIP_ITEM *psVSyncFlips;
577         IMG_UINT32 i;
578         PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
579         IMG_UINT32 ui32BuffersToSkip;
580         UNREFERENCED_PARAMETER(ui32OEMFlags);
581         UNREFERENCED_PARAMETER(pui32SwapChainID);
582         
583         
584         if(!hDevice
585         || !psDstSurfAttrib
586         || !psSrcSurfAttrib
587         || !ppsSyncData
588         || !phSwapChain)
589         {
590                 return (PVRSRV_ERROR_INVALID_PARAMS);
591         }
592
593         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
594         
595         
596         if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
597         {
598                 return (PVRSRV_ERROR_NOT_SUPPORTED);
599         }
600
601         
602         if(psDevInfo->psSwapChain != NULL)
603         {
604                 return (PVRSRV_ERROR_FLIP_CHAIN_EXISTS);
605         }
606         
607         
608         if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
609         {
610                 return (PVRSRV_ERROR_TOOMANYBUFFERS);
611         }
612         
613         if ((psDevInfo->sFBInfo.ulRoundedBufferSize * (unsigned long)ui32BufferCount) > psDevInfo->sFBInfo.ulFBSize)
614         {
615                 return (PVRSRV_ERROR_TOOMANYBUFFERS);
616         }
617
618         
619         ui32BuffersToSkip = psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers - ui32BufferCount;
620
621         
622         if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat
623         || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride
624         || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width
625         || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height)
626         {
627                 
628                 return (PVRSRV_ERROR_INVALID_PARAMS);
629         }               
630
631         if(psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat
632         || psDstSurfAttrib->sDims.ui32ByteStride != psSrcSurfAttrib->sDims.ui32ByteStride
633         || psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width
634         || psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height)
635         {
636                 
637                 return (PVRSRV_ERROR_INVALID_PARAMS);
638         }               
639
640         
641         UNREFERENCED_PARAMETER(ui32Flags);
642         
643         
644         psSwapChain = (OMAPLFB_SWAPCHAIN*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_SWAPCHAIN));
645         if(!psSwapChain)
646         {
647                 return (PVRSRV_ERROR_OUT_OF_MEMORY);
648         }
649
650         psBuffer = (OMAPLFB_BUFFER*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_BUFFER) * ui32BufferCount);
651         if(!psBuffer)
652         {
653                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
654                 goto ErrorFreeSwapChain;
655         }
656
657         psVSyncFlips = (OMAPLFB_VSYNC_FLIP_ITEM *)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_VSYNC_FLIP_ITEM) * ui32BufferCount);
658         if (!psVSyncFlips)
659         {
660                 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
661                 goto ErrorFreeBuffers;
662         }
663
664         psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount;
665         psSwapChain->psBuffer = psBuffer;
666         psSwapChain->psVSyncFlips = psVSyncFlips;
667         psSwapChain->ulInsertIndex = 0;
668         psSwapChain->ulRemoveIndex = 0;
669         psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
670         psSwapChain->pvDevInfo = (void*)psDevInfo;
671
672         /* Init the workqueue and its own work */
673         INIT_WORK(&psDevInfo->vsync_work, OMAPLFBVSyncIHandler);
674         psDevInfo->vsync_isr_wq = create_workqueue("pvr_vsync_wq");
675         
676         for(i=0; i<ui32BufferCount-1; i++)
677         {
678                 psBuffer[i].psNext = &psBuffer[i+1];
679         }
680         
681         psBuffer[i].psNext = &psBuffer[0];
682
683         
684         for(i=0; i<ui32BufferCount; i++)
685         {
686                 IMG_UINT32 ui32SwapBuffer = i + ui32BuffersToSkip;
687                 IMG_UINT32 ui32BufferOffset = ui32SwapBuffer * (IMG_UINT32)psDevInfo->sFBInfo.ulRoundedBufferSize;
688
689                 psBuffer[i].psSyncData = ppsSyncData[i];
690
691                 psBuffer[i].sSysAddr.uiAddr = psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
692                 psBuffer[i].sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset;
693         }
694         
695         for(i=0; i<ui32BufferCount; i++)
696         {
697                 psVSyncFlips[i].bValid = OMAP_FALSE;
698                 psVSyncFlips[i].bFlipped = OMAP_FALSE;
699                 psVSyncFlips[i].bCmdCompleted = OMAP_FALSE;
700         }
701         
702         mutex_lock(&psDevInfo->sSwapChainLockMutex);
703
704         psDevInfo->psSwapChain = psSwapChain;
705         
706         psSwapChain->bFlushCommands = psDevInfo->bFlushCommands;
707
708         if (psSwapChain->bFlushCommands)
709         {
710                 psSwapChain->ulSetFlushStateRefCount = 1;
711         }
712         else
713         {
714                 psSwapChain->ulSetFlushStateRefCount = 0;
715         }
716                 
717         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
718
719         if (EnableLFBEventNotification(psDevInfo)!= OMAP_OK)
720         {
721                 printk(KERN_WARNING DRIVER_PREFIX ": Couldn't enable framebuffer event notification\n");
722                 goto ErrorDisableDisplayRegisters;
723         }
724
725         /* this is often 2 but could be 3, why oh why? */
726         printk(KERN_INFO "CreateDCSwapChain ui32BufferCount: %u\n", (u32)ui32BufferCount);
727         
728         *phSwapChain = (IMG_HANDLE)psSwapChain;
729
730         return (PVRSRV_OK);
731
732 ErrorDisableDisplayRegisters:
733         OMAPLFBFreeKernelMem(psVSyncFlips);
734 ErrorFreeBuffers:
735         OMAPLFBFreeKernelMem(psBuffer);
736 ErrorFreeSwapChain:
737         OMAPLFBFreeKernelMem(psSwapChain);
738
739         return eError;
740 }
741
742 static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
743         IMG_HANDLE hSwapChain)
744 {
745         OMAPLFB_DEVINFO *psDevInfo;
746         OMAPLFB_SWAPCHAIN *psSwapChain;
747         OMAP_ERROR eError;
748
749         
750         if(!hDevice || !hSwapChain)
751         {
752                 return (PVRSRV_ERROR_INVALID_PARAMS);
753         }
754         
755         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
756         psSwapChain = (OMAPLFB_SWAPCHAIN*)hSwapChain;
757         if (psSwapChain != psDevInfo->psSwapChain)
758         {
759                 return (PVRSRV_ERROR_INVALID_PARAMS);
760         }
761
762         eError = DisableLFBEventNotification(psDevInfo);
763         if (eError != OMAP_OK)
764         {
765                 printk(KERN_WARNING DRIVER_PREFIX ": Couldn't disable framebuffer event notification\n");
766         }
767
768         mutex_lock(&psDevInfo->sSwapChainLockMutex);    
769         
770         FlushInternalVSyncQueue(psSwapChain);
771         
772         OMAPLFBFlip(psSwapChain, (unsigned long)psDevInfo->sFBInfo.sSysAddr.uiAddr);
773         
774         psDevInfo->psSwapChain = NULL;
775  
776         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
777
778         /* Destroy the workqueue */
779         flush_workqueue(psDevInfo->vsync_isr_wq);
780         destroy_workqueue(psDevInfo->vsync_isr_wq);
781         
782         OMAPLFBFreeKernelMem(psSwapChain->psVSyncFlips);
783         OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
784         OMAPLFBFreeKernelMem(psSwapChain);
785
786         return (PVRSRV_OK);
787 }
788
789 static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
790         IMG_HANDLE hSwapChain,
791         IMG_RECT *psRect)
792 {
793         UNREFERENCED_PARAMETER(hDevice);
794         UNREFERENCED_PARAMETER(hSwapChain);
795         UNREFERENCED_PARAMETER(psRect);
796
797         
798         
799         return (PVRSRV_ERROR_NOT_SUPPORTED);
800 }
801
802 static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
803                                  IMG_HANDLE hSwapChain,
804                                  IMG_RECT *psRect)
805 {
806         UNREFERENCED_PARAMETER(hDevice);
807         UNREFERENCED_PARAMETER(hSwapChain);
808         UNREFERENCED_PARAMETER(psRect);
809
810         
811
812         return (PVRSRV_ERROR_NOT_SUPPORTED);
813 }
814
815 static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
816                                       IMG_HANDLE hSwapChain,
817                                       IMG_UINT32 ui32CKColour)
818 {
819         UNREFERENCED_PARAMETER(hDevice);
820         UNREFERENCED_PARAMETER(hSwapChain);
821         UNREFERENCED_PARAMETER(ui32CKColour);
822
823         
824
825         return (PVRSRV_ERROR_NOT_SUPPORTED);
826 }
827
828 static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
829                                       IMG_HANDLE hSwapChain,
830                                       IMG_UINT32 ui32CKColour)
831 {
832         UNREFERENCED_PARAMETER(hDevice);
833         UNREFERENCED_PARAMETER(hSwapChain);
834         UNREFERENCED_PARAMETER(ui32CKColour);
835
836         
837
838         return (PVRSRV_ERROR_NOT_SUPPORTED);
839 }
840
841 static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
842                                  IMG_HANDLE hSwapChain,
843                                  IMG_UINT32 *pui32BufferCount,
844                                  IMG_HANDLE *phBuffer)
845 {
846         OMAPLFB_DEVINFO   *psDevInfo;
847         OMAPLFB_SWAPCHAIN *psSwapChain;
848         unsigned long      i;
849         
850         
851         if(!hDevice 
852         || !hSwapChain
853         || !pui32BufferCount
854         || !phBuffer)
855         {
856                 return (PVRSRV_ERROR_INVALID_PARAMS);
857         }
858         
859         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
860         psSwapChain = (OMAPLFB_SWAPCHAIN*)hSwapChain;
861         if (psSwapChain != psDevInfo->psSwapChain)
862         {
863                 return (PVRSRV_ERROR_INVALID_PARAMS);
864         }
865         
866         
867         *pui32BufferCount = (IMG_UINT32)psSwapChain->ulBufferCount;
868         
869         
870         for(i=0; i<psSwapChain->ulBufferCount; i++)
871         {
872                 phBuffer[i] = (IMG_HANDLE)&psSwapChain->psBuffer[i];
873         }
874         
875         return (PVRSRV_OK);
876 }
877
878 static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE hDevice,
879                                    IMG_HANDLE hBuffer,
880                                    IMG_UINT32 ui32SwapInterval,
881                                    IMG_HANDLE hPrivateTag,
882                                    IMG_UINT32 ui32ClipRectCount,
883                                    IMG_RECT *psClipRect)
884 {
885         OMAPLFB_DEVINFO *psDevInfo;
886
887         UNREFERENCED_PARAMETER(ui32SwapInterval);
888         UNREFERENCED_PARAMETER(hPrivateTag);
889         UNREFERENCED_PARAMETER(psClipRect);
890         
891         if(!hDevice 
892         || !hBuffer
893         || (ui32ClipRectCount != 0))
894         {
895                 return (PVRSRV_ERROR_INVALID_PARAMS);
896         }
897
898         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
899
900         
901         return (PVRSRV_OK);
902 }
903
904 static PVRSRV_ERROR SwapToDCSystem(IMG_HANDLE hDevice,
905                                    IMG_HANDLE hSwapChain)
906 {
907         OMAPLFB_DEVINFO   *psDevInfo;
908         OMAPLFB_SWAPCHAIN *psSwapChain;
909
910         if(!hDevice || !hSwapChain)
911         {
912                 return (PVRSRV_ERROR_INVALID_PARAMS);
913         }
914
915         psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
916         psSwapChain = (OMAPLFB_SWAPCHAIN*)hSwapChain;
917         if (psSwapChain != psDevInfo->psSwapChain)
918         {
919                 return (PVRSRV_ERROR_INVALID_PARAMS);
920         }
921         
922         mutex_lock(&psDevInfo->sSwapChainLockMutex);
923         
924         FlushInternalVSyncQueue(psSwapChain);
925         
926         OMAPLFBFlip(psSwapChain, (unsigned long)psDevInfo->sFBInfo.sSysAddr.uiAddr);
927
928         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
929
930         return (PVRSRV_OK);
931 }
932
933 static void OMAPLFBVSyncIHandler(struct work_struct *work)
934 {
935         OMAPLFB_DEVINFO *psDevInfo = container_of(work, OMAPLFB_DEVINFO, vsync_work);
936         OMAPLFB_VSYNC_FLIP_ITEM *psFlipItem;
937         OMAPLFB_SWAPCHAIN *psSwapChain;
938         unsigned long ulMaxIndex;
939
940         mutex_lock(&psDevInfo->sSwapChainLockMutex);
941
942         psSwapChain = psDevInfo->psSwapChain;
943         if (!psSwapChain || psSwapChain->bFlushCommands)
944                 goto ExitUnlock;
945
946         psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
947         ulMaxIndex = psSwapChain->ulBufferCount - 1;
948         
949         /* VSync with the display here */
950         OMAPLFBWaitForVSync();
951
952         while(psFlipItem->bValid)
953         {       
954                 
955                 if(psFlipItem->bFlipped)
956                 {
957                         
958                         if(!psFlipItem->bCmdCompleted)
959                         {
960                                 
961                                 psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete((IMG_HANDLE)psFlipItem->hCmdComplete, IMG_TRUE);
962
963                                 
964                                 psFlipItem->bCmdCompleted = OMAP_TRUE;
965                         }
966
967                         
968                         psFlipItem->ulSwapInterval--;
969
970                         
971                         if(psFlipItem->ulSwapInterval == 0)
972                         {       
973                                 
974                                 psSwapChain->ulRemoveIndex++;
975                                 
976                                 if(psSwapChain->ulRemoveIndex > ulMaxIndex)
977                                 {
978                                         psSwapChain->ulRemoveIndex = 0;
979                                 }
980                                 
981                                 
982                                 psFlipItem->bCmdCompleted = OMAP_FALSE;
983                                 psFlipItem->bFlipped = OMAP_FALSE;
984         
985                                 
986                                 psFlipItem->bValid = OMAP_FALSE;
987                         }
988                         else
989                         {
990                                 queue_work(psDevInfo->vsync_isr_wq, &psDevInfo->vsync_work);
991                                 goto ExitUnlock;        
992                         }
993                 }
994                 else
995                 {
996                         
997                         OMAPLFBFlip(psSwapChain, (unsigned long)psFlipItem->sSysAddr);
998                                                 
999                         psFlipItem->bFlipped = OMAP_TRUE;
1000
1001                         /* 
1002                          * If the flip has been presented here then we need in the next
1003                          * VSYNC execute the command complete, schedule another work
1004                          */
1005                         queue_work(psDevInfo->vsync_isr_wq, &psDevInfo->vsync_work);
1006
1007                         goto ExitUnlock;        
1008                 }
1009                 
1010                 
1011                 psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulRemoveIndex];
1012         }
1013
1014 ExitUnlock:
1015         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
1016
1017 }
1018
1019 static IMG_BOOL ProcessFlip(IMG_HANDLE  hCmdCookie,
1020                             IMG_UINT32  ui32DataSize,
1021                             IMG_VOID   *pvData)
1022 {
1023         DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
1024         OMAPLFB_DEVINFO *psDevInfo;
1025         OMAPLFB_BUFFER *psBuffer;
1026         OMAPLFB_SWAPCHAIN *psSwapChain;
1027 #if defined(SYS_USING_INTERRUPTS)
1028         OMAPLFB_VSYNC_FLIP_ITEM* psFlipItem;
1029 #endif
1030         
1031         if(!hCmdCookie || !pvData)
1032         {
1033                 return IMG_FALSE;
1034         }
1035
1036         
1037         psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;
1038
1039         if (psFlipCmd == IMG_NULL || sizeof(DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
1040         {
1041                 return IMG_FALSE;
1042         }
1043
1044         
1045         psDevInfo = (OMAPLFB_DEVINFO*)psFlipCmd->hExtDevice;
1046         
1047         psBuffer = (OMAPLFB_BUFFER*)psFlipCmd->hExtBuffer;
1048         psSwapChain = (OMAPLFB_SWAPCHAIN*) psFlipCmd->hExtSwapChain;
1049
1050         mutex_lock(&psDevInfo->sSwapChainLockMutex);
1051         
1052         if (psDevInfo->bDeviceSuspended)
1053         {
1054                 psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie, IMG_TRUE);
1055                 goto ExitTrueUnlock;
1056         }
1057
1058 #if defined(SYS_USING_INTERRUPTS)
1059         
1060 //      if(psFlipCmd->ui32SwapInterval == 0 || psSwapChain->bFlushCommands == OMAP_TRUE)
1061         {
1062 #endif
1063                 
1064                 OMAPLFBFlipDSS2(psSwapChain, psBuffer->sSysAddr.uiAddr, 1);
1065
1066                 if (psSwapChain->ulBufferCount == 2)
1067                         psDevInfo->psLINFBInfo->fbops->fb_ioctl(
1068                                 psDevInfo->psLINFBInfo, OMAPFB_WAITFORGO, 0);
1069
1070                 psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie, IMG_TRUE);
1071
1072 #if defined(SYS_USING_INTERRUPTS)
1073                 goto ExitTrueUnlock;
1074         }
1075
1076         psFlipItem = &psSwapChain->psVSyncFlips[psSwapChain->ulInsertIndex];
1077
1078         
1079         if(psFlipItem->bValid == OMAP_FALSE)
1080         {
1081                 unsigned long ulMaxIndex = psSwapChain->ulBufferCount - 1;
1082                 
1083                 if(psSwapChain->ulInsertIndex == psSwapChain->ulRemoveIndex)
1084                 {
1085                         /* If both indexes are equal the queue is empty, present immediatly */
1086                         OMAPLFBFlip(psSwapChain, (unsigned long)psBuffer->sSysAddr.uiAddr);
1087
1088                         psFlipItem->bFlipped = OMAP_TRUE;
1089                 }
1090                 else
1091                 {
1092                         psFlipItem->bFlipped = OMAP_FALSE;
1093                 }
1094
1095                 /* The buffer is queued here, must be consumed by the VSYNC workqueue */
1096                 psFlipItem->hCmdComplete = (OMAP_HANDLE)hCmdCookie;
1097                 psFlipItem->ulSwapInterval = (unsigned long)psFlipCmd->ui32SwapInterval;
1098                 psFlipItem->sSysAddr = &psBuffer->sSysAddr;
1099                 psFlipItem->bValid = OMAP_TRUE;
1100
1101                 psSwapChain->ulInsertIndex++;
1102                 if(psSwapChain->ulInsertIndex > ulMaxIndex)
1103                 {
1104                         psSwapChain->ulInsertIndex = 0;
1105                 }
1106
1107                 /* Give work to the workqueue to sync with the display */                               
1108                 queue_work(psDevInfo->vsync_isr_wq, &psDevInfo->vsync_work);
1109
1110                 goto ExitTrueUnlock;
1111         }
1112         
1113         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
1114
1115         return IMG_FALSE;
1116 #endif
1117
1118 ExitTrueUnlock:
1119         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
1120         return IMG_TRUE;
1121 }
1122
1123
1124 static OMAP_ERROR InitDev(OMAPLFB_DEVINFO *psDevInfo)
1125 {
1126         struct fb_info *psLINFBInfo;
1127         struct module *psLINFBOwner;
1128         OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
1129         OMAP_ERROR eError = OMAP_ERROR_GENERIC;
1130         unsigned long FBSize;
1131
1132         acquire_console_sem();
1133
1134         if (fb_idx < 0 || fb_idx >= num_registered_fb)
1135         {
1136                 eError = OMAP_ERROR_INVALID_DEVICE;
1137                 goto errRelSem;
1138         }
1139
1140         psLINFBInfo = registered_fb[fb_idx];
1141
1142         psLINFBOwner = psLINFBInfo->fbops->owner;
1143         if (!try_module_get(psLINFBOwner))
1144         {
1145                 printk(KERN_INFO DRIVER_PREFIX
1146                         ": Couldn't get framebuffer module\n");
1147
1148                 goto errRelSem;
1149         }
1150
1151         if (psLINFBInfo->fbops->fb_open != NULL)
1152         {
1153                 int res;
1154
1155                 res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
1156                 if (res != 0)
1157                 {
1158                         printk(KERN_INFO DRIVER_PREFIX
1159                                 ": Couldn't open framebuffer: %d\n", res);
1160
1161                         goto errModPut;
1162                 }
1163         }
1164
1165         psDevInfo->psLINFBInfo = psLINFBInfo;
1166
1167         FBSize = (psLINFBInfo->screen_size) != 0 ?
1168                                         psLINFBInfo->screen_size :
1169                                         psLINFBInfo->fix.smem_len;
1170         DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1171                         ": Framebuffer physical address: 0x%lx\n",
1172                         psLINFBInfo->fix.smem_start));
1173         DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1174                         ": Framebuffer virtual address: 0x%lx\n",
1175                         (unsigned long)psLINFBInfo->screen_base));
1176         DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1177                         ": Framebuffer size: %lu\n",
1178                         FBSize));
1179         DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1180                         ": Framebuffer virtual width: %u\n",
1181                         psLINFBInfo->var.xres_virtual));
1182         DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1183                         ": Framebuffer virtual height: %u\n",
1184                         psLINFBInfo->var.yres_virtual));
1185         DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1186                         ": Framebuffer width: %u\n",
1187                         psLINFBInfo->var.xres));
1188         DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1189                         ": Framebuffer height: %u\n",
1190                         psLINFBInfo->var.yres));
1191         DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1192                         ": Framebuffer stride: %u\n",
1193                         psLINFBInfo->fix.line_length));
1194
1195         
1196         psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
1197         psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
1198
1199         psPVRFBInfo->ulWidth = psLINFBInfo->var.xres;
1200         psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
1201         psPVRFBInfo->ulByteStride =  psLINFBInfo->fix.line_length;
1202         psPVRFBInfo->ulFBSize = FBSize;
1203         psPVRFBInfo->ulBufferSize = psPVRFBInfo->ulHeight * psPVRFBInfo->ulByteStride;
1204
1205         psPVRFBInfo->ulRoundedBufferSize =
1206                 sgx_buffer_align(psPVRFBInfo->ulByteStride,
1207                                  psPVRFBInfo->ulBufferSize);
1208
1209         if(psLINFBInfo->var.bits_per_pixel == 16)
1210         {
1211                 if((psLINFBInfo->var.red.length == 5) &&
1212                         (psLINFBInfo->var.green.length == 6) && 
1213                         (psLINFBInfo->var.blue.length == 5) && 
1214                         (psLINFBInfo->var.red.offset == 11) &&
1215                         (psLINFBInfo->var.green.offset == 5) && 
1216                         (psLINFBInfo->var.blue.offset == 0) && 
1217                         (psLINFBInfo->var.red.msb_right == 0))
1218                 {
1219                         psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
1220                 }
1221                 else
1222                 {
1223                         printk("Unknown FB format\n");
1224                 }
1225         }
1226         else if(psLINFBInfo->var.bits_per_pixel == 32)
1227         {
1228                 if((psLINFBInfo->var.red.length == 8) &&
1229                         (psLINFBInfo->var.green.length == 8) && 
1230                         (psLINFBInfo->var.blue.length == 8) && 
1231                         (psLINFBInfo->var.red.offset == 16) &&
1232                         (psLINFBInfo->var.green.offset == 8) && 
1233                         (psLINFBInfo->var.blue.offset == 0) && 
1234                         (psLINFBInfo->var.red.msb_right == 0))
1235                 {
1236                         psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_ARGB8888;
1237                 }
1238                 else
1239                 {
1240                         printk("Unknown FB format\n");
1241                 }
1242         }       
1243         else
1244         {
1245                 printk("Unknown FB format\n");
1246         }
1247
1248         
1249         psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
1250         psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
1251
1252 #ifdef CONFIG_OMAP2_DSS
1253         INIT_WORK (&wq_flipdss2.work, dss2_pan_display);
1254 #endif
1255
1256         eError = OMAP_OK;
1257         goto errRelSem;
1258
1259 errModPut:
1260         module_put(psLINFBOwner);
1261 errRelSem:
1262         release_console_sem();
1263         return eError;
1264 }
1265
1266 static void DeInitDev(OMAPLFB_DEVINFO *psDevInfo)
1267 {
1268         struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
1269         struct module *psLINFBOwner;
1270
1271         acquire_console_sem();
1272
1273         psLINFBOwner = psLINFBInfo->fbops->owner;
1274
1275         if (psLINFBInfo->fbops->fb_release != NULL) 
1276         {
1277                 (void) psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
1278         }
1279
1280         module_put(psLINFBOwner);
1281
1282         release_console_sem();
1283 }
1284
1285 OMAP_ERROR OMAPLFBInit(void)
1286 {
1287         OMAPLFB_DEVINFO         *psDevInfo;
1288
1289         psDevInfo = GetAnchorPtr();
1290         
1291         if (psDevInfo == NULL)
1292         {
1293                 PFN_CMD_PROC                    pfnCmdProcList[OMAPLFB_COMMAND_COUNT];
1294                 IMG_UINT32                              aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
1295                 
1296                 psDevInfo = (OMAPLFB_DEVINFO *)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_DEVINFO));
1297
1298                 if(!psDevInfo)
1299                 {
1300                         return (OMAP_ERROR_OUT_OF_MEMORY);
1301                 }
1302
1303                 
1304                 memset(psDevInfo, 0, sizeof(OMAPLFB_DEVINFO));
1305
1306                 
1307                 SetAnchorPtr((void*)psDevInfo);
1308
1309                 
1310                 psDevInfo->ulRefCount = 0;
1311
1312                 
1313                 if(InitDev(psDevInfo) != OMAP_OK)
1314                 {
1315                         return (OMAP_ERROR_INIT_FAILURE);
1316                 }
1317
1318                 if(OMAPLFBGetLibFuncAddr ("PVRGetDisplayClassJTable", &pfnGetPVRJTable) != OMAP_OK)
1319                 {
1320                         return (OMAP_ERROR_INIT_FAILURE);
1321                 }
1322
1323                 
1324                 if(!(*pfnGetPVRJTable)(&psDevInfo->sPVRJTable))
1325                 {
1326                         return (OMAP_ERROR_INIT_FAILURE);
1327                 }
1328
1329                 mutex_init(&psDevInfo->sSwapChainLockMutex);
1330
1331                 psDevInfo->psSwapChain = 0;
1332                 psDevInfo->bFlushCommands = OMAP_FALSE;
1333                 psDevInfo->bDeviceSuspended = OMAP_FALSE;
1334
1335                 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = (IMG_UINT32)(psDevInfo->sFBInfo.ulFBSize / psDevInfo->sFBInfo.ulRoundedBufferSize);
1336 #if !defined (SUPPORT_TI_DSS_FW)
1337                 /*  Limiting the ui32MaxSwapChainBuffers to 3 */
1338                 if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers > 3)
1339                         psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 3;
1340 #endif
1341                 if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers == 0)
1342                 {
1343                         psDevInfo->sDisplayInfo.ui32MaxSwapChains = 0;
1344                         psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 0;
1345                 }
1346                 else
1347                 {
1348                         psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1;
1349                         psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 3;
1350                 }
1351                 psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0;
1352
1353                 strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
1354         
1355                 psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat;
1356                 psDevInfo->sDisplayDim.ui32Width      = (IMG_UINT32)psDevInfo->sFBInfo.ulWidth;
1357                 psDevInfo->sDisplayDim.ui32Height     = (IMG_UINT32)psDevInfo->sFBInfo.ulHeight;
1358                 psDevInfo->sDisplayDim.ui32ByteStride = (IMG_UINT32)psDevInfo->sFBInfo.ulByteStride;
1359
1360                 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1361                         ": Maximum number of swap chain buffers: %lu\n",
1362                         psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
1363
1364                 
1365                 psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
1366                 psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
1367                 psDevInfo->sSystemBuffer.ulBufferSize = psDevInfo->sFBInfo.ulRoundedBufferSize;
1368
1369                 
1370
1371                 psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
1372                 psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
1373                 psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
1374                 psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
1375                 psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
1376                 psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
1377                 psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
1378                 psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
1379                 psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
1380                 psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
1381                 psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
1382                 psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
1383                 psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
1384                 psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
1385                 psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
1386                 psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
1387                 psDevInfo->sDCJTable.pfnSwapToDCSystem = SwapToDCSystem;
1388                 psDevInfo->sDCJTable.pfnSetDCState = SetDCState;
1389
1390                 
1391                 if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice (
1392                         &psDevInfo->sDCJTable,
1393                         &psDevInfo->ulDeviceID ) != PVRSRV_OK)
1394                 {
1395                         return (OMAP_ERROR_DEVICE_REGISTER_FAILED);
1396                 }
1397
1398                 pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
1399
1400                 
1401                 aui32SyncCountList[DC_FLIP_COMMAND][0] = 0; 
1402                 aui32SyncCountList[DC_FLIP_COMMAND][1] = 2; 
1403
1404                 
1405
1406
1407
1408                 if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList (psDevInfo->ulDeviceID,
1409                                                                                                                                 &pfnCmdProcList[0],
1410                                                                                                                                 aui32SyncCountList,
1411                                                                                                                                 OMAPLFB_COMMAND_COUNT) != PVRSRV_OK)
1412                 {
1413                         printk(KERN_WARNING DRIVER_PREFIX ": Can't register callback\n");
1414                         return (OMAP_ERROR_CANT_REGISTER_CALLBACK);
1415                 }
1416
1417         }
1418
1419         
1420         psDevInfo->ulRefCount++;
1421
1422         
1423         return (OMAP_OK);
1424         
1425         }
1426
1427 OMAP_ERROR OMAPLFBDeinit(void)
1428 {
1429         OMAPLFB_DEVINFO *psDevInfo, *psDevFirst;
1430
1431         psDevFirst = GetAnchorPtr();
1432         psDevInfo = psDevFirst;
1433
1434         
1435         if (psDevInfo == NULL)
1436         {
1437                 return (OMAP_ERROR_GENERIC);
1438         }
1439
1440         
1441         psDevInfo->ulRefCount--;
1442
1443         if (psDevInfo->ulRefCount == 0)
1444         {
1445                 
1446                 PVRSRV_DC_DISP2SRV_KMJTABLE     *psJTable = &psDevInfo->sPVRJTable;
1447
1448                 if (psDevInfo->sPVRJTable.pfnPVRSRVRemoveCmdProcList (psDevInfo->ulDeviceID, OMAPLFB_COMMAND_COUNT) != PVRSRV_OK)
1449                 {
1450                         return (OMAP_ERROR_GENERIC);
1451                 }
1452
1453                 
1454                 if (psJTable->pfnPVRSRVRemoveDCDevice(psDevInfo->ulDeviceID) != PVRSRV_OK)
1455                 {
1456                         return (OMAP_ERROR_GENERIC);
1457                 }
1458
1459                 DeInitDev(psDevInfo);
1460
1461                 
1462                 OMAPLFBFreeKernelMem(psDevInfo);
1463         }
1464         
1465         
1466         SetAnchorPtr(NULL);
1467
1468         
1469         return (OMAP_OK);
1470 }
1471
1472
1473 #if defined(LDM_PLATFORM)
1474 void OMAPLFBDriverSuspend(void)
1475 {
1476         OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr();
1477
1478         mutex_lock(&psDevInfo->sSwapChainLockMutex);
1479
1480         if (psDevInfo->bDeviceSuspended)
1481         {
1482                 goto ExitUnlock;
1483         }
1484         psDevInfo->bDeviceSuspended = OMAP_TRUE;
1485
1486         
1487         SetFlushStateInternalNoLock(psDevInfo, OMAP_TRUE);
1488
1489         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
1490         
1491         return;
1492
1493 ExitUnlock:
1494         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
1495 }
1496
1497 void OMAPLFBDriverResume(void)
1498 {
1499         OMAPLFB_DEVINFO *psDevInfo = GetAnchorPtr();
1500
1501         if (psDevInfo->bDeviceSuspended == OMAP_FALSE)
1502         {
1503                 return;
1504         }
1505
1506         mutex_lock(&psDevInfo->sSwapChainLockMutex);
1507         
1508         SetFlushStateInternalNoLock(psDevInfo, OMAP_FALSE);
1509
1510         psDevInfo->bDeviceSuspended = OMAP_FALSE;
1511
1512         mutex_unlock(&psDevInfo->sSwapChainLockMutex);
1513 }
1514 #endif
1515