1 /**********************************************************************
2 *
3 * Copyright (C) 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 ******************************************************************************/
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 #include <plat/sgx_omaplfb.h>
36 #include "img_defs.h"
37 #include "servicesext.h"
38 #include "kerneldisplay.h"
39 #include "omaplfb.h"
41 /*
42 * Just use CONFIG_DSSCOMP to distinguish code which previously had
43 * additional mixes of CONFIG_TI_TILER and CONFIG_ION_OMAP. DSSCOMP makes
44 * it a given that ION and the TILER will be used.
45 * For kernel 3.4 we use CONFIG_DRM_OMAP_DMM_TILER instead of CONFIG_TI_TILER
46 */
47 #if defined(CONFIG_DSSCOMP)
48 #if !defined(CONFIG_ION_OMAP)
49 #error Expected CONFIG_ION_OMAP to be defined
50 #endif
51 #if defined(CONFIG_DRM_OMAP_DMM_TILER)
52 #include <../drivers/staging/omapdrm/omap_dmm_tiler.h>
53 #include <../drivers/video/omap2/dsscomp/tiler-utils.h>
54 #elif defined(CONFIG_TI_TILER)
55 #include <mach/tiler.h>
56 #else
57 #error Expected CONFIG_DRM_OMAP_DMM_TILER or CONFIG_TI_TILER to be defined
58 #endif
60 #ifndef DSS_MAX_NUMBER_YUV_PLANES
61 #define DSS_MAX_NUMBER_YUV_PLANES 2
62 #endif
64 #include <linux/ion.h>
65 #include <linux/omap_ion.h>
66 #include <video/dsscomp.h>
67 #include <plat/dsscomp.h>
68 #include <video/omap_hwc.h>
70 extern struct ion_device *omap_ion_device;
71 struct ion_client *gpsIONClient;
73 #endif
75 #define OMAPLFB_COMMAND_COUNT 1
77 #define OMAPLFB_VSYNC_SETTLE_COUNT 5
79 #define OMAPLFB_MAX_NUM_DEVICES FB_MAX
80 #if (OMAPLFB_MAX_NUM_DEVICES > FB_MAX)
81 #error "OMAPLFB_MAX_NUM_DEVICES must not be greater than FB_MAX"
82 #endif
84 static OMAPLFB_DEVINFO *gapsDevInfo[OMAPLFB_MAX_NUM_DEVICES];
86 static PFN_DC_GET_PVRJTABLE gpfnGetPVRJTable = NULL;
88 static IMG_BOOL gbBvInterfacePresent;
89 static IMG_BOOL gbBvReady = IMG_FALSE;
90 static IMG_BOOL bBltReady = IMG_FALSE;
92 static inline unsigned long RoundUpToMultiple(unsigned long x, unsigned long y)
93 {
94 unsigned long div = x / y;
95 unsigned long rem = x % y;
97 return (div + ((rem == 0) ? 0 : 1)) * y;
98 }
100 static unsigned long GCD(unsigned long x, unsigned long y)
101 {
102 while (y != 0)
103 {
104 unsigned long r = x % y;
105 x = y;
106 y = r;
107 }
109 return x;
110 }
112 static unsigned long LCM(unsigned long x, unsigned long y)
113 {
114 unsigned long gcd = GCD(x, y);
116 return (gcd == 0) ? 0 : ((x / gcd) * y);
117 }
119 unsigned OMAPLFBMaxFBDevIDPlusOne(void)
120 {
121 return OMAPLFB_MAX_NUM_DEVICES;
122 }
124 OMAPLFB_DEVINFO *OMAPLFBGetDevInfoPtr(unsigned uiFBDevID)
125 {
126 WARN_ON(uiFBDevID >= OMAPLFBMaxFBDevIDPlusOne());
128 if (uiFBDevID >= OMAPLFB_MAX_NUM_DEVICES)
129 {
130 return NULL;
131 }
133 return gapsDevInfo[uiFBDevID];
134 }
136 static inline void OMAPLFBSetDevInfoPtr(unsigned uiFBDevID, OMAPLFB_DEVINFO *psDevInfo)
137 {
138 WARN_ON(uiFBDevID >= OMAPLFB_MAX_NUM_DEVICES);
140 if (uiFBDevID < OMAPLFB_MAX_NUM_DEVICES)
141 {
142 gapsDevInfo[uiFBDevID] = psDevInfo;
143 }
144 }
146 static inline OMAPLFB_BOOL SwapChainHasChanged(OMAPLFB_DEVINFO *psDevInfo, OMAPLFB_SWAPCHAIN *psSwapChain)
147 {
148 return (psDevInfo->psSwapChain != psSwapChain) ||
149 (psDevInfo->uiSwapChainID != psSwapChain->uiSwapChainID);
150 }
152 static inline OMAPLFB_BOOL DontWaitForVSync(OMAPLFB_DEVINFO *psDevInfo)
153 {
154 OMAPLFB_BOOL bDontWait;
156 bDontWait = OMAPLFBAtomicBoolRead(&psDevInfo->sBlanked) ||
157 OMAPLFBAtomicBoolRead(&psDevInfo->sFlushCommands);
159 #if defined(CONFIG_HAS_EARLYSUSPEND)
160 bDontWait = bDontWait || OMAPLFBAtomicBoolRead(&psDevInfo->sEarlySuspendFlag);
161 #endif
162 #if defined(SUPPORT_DRI_DRM)
163 bDontWait = bDontWait || OMAPLFBAtomicBoolRead(&psDevInfo->sLeaveVT);
164 #endif
165 return bDontWait;
166 }
168 static IMG_VOID SetDCState(IMG_HANDLE hDevice, IMG_UINT32 ui32State)
169 {
170 OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)hDevice;
172 switch (ui32State)
173 {
174 case DC_STATE_FLUSH_COMMANDS:
175 OMAPLFBAtomicBoolSet(&psDevInfo->sFlushCommands, OMAPLFB_TRUE);
176 break;
177 case DC_STATE_FORCE_SWAP_TO_SYSTEM:
178 OMAPLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
179 break;
180 case DC_STATE_NO_FLUSH_COMMANDS:
181 OMAPLFBAtomicBoolSet(&psDevInfo->sFlushCommands, OMAPLFB_FALSE);
182 break;
183 default:
184 break;
185 }
186 }
188 static PVRSRV_ERROR OpenDCDevice(IMG_UINT32 uiPVRDevID,
189 IMG_HANDLE *phDevice,
190 PVRSRV_SYNC_DATA* psSystemBufferSyncData)
191 {
192 OMAPLFB_DEVINFO *psDevInfo;
193 OMAPLFB_ERROR eError;
194 unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
195 unsigned i;
197 for (i = 0; i < uiMaxFBDevIDPlusOne; i++)
198 {
199 psDevInfo = OMAPLFBGetDevInfoPtr(i);
200 if (psDevInfo != NULL && psDevInfo->uiPVRDevID == uiPVRDevID)
201 {
202 break;
203 }
204 }
205 if (i == uiMaxFBDevIDPlusOne)
206 {
207 DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
208 ": %s: PVR Device %u not found\n", __FUNCTION__, uiPVRDevID));
209 return PVRSRV_ERROR_INVALID_DEVICE;
210 }
213 psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
215 eError = OMAPLFBUnblankDisplay(psDevInfo);
216 if (eError != OMAPLFB_OK)
217 {
218 DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
219 ": %s: Device %u: OMAPLFBUnblankDisplay failed (%d)\n", __FUNCTION__, psDevInfo->uiFBDevID, eError));
220 return PVRSRV_ERROR_UNBLANK_DISPLAY_FAILED;
221 }
224 *phDevice = (IMG_HANDLE)psDevInfo;
226 return PVRSRV_OK;
227 }
229 static PVRSRV_ERROR CloseDCDevice(IMG_HANDLE hDevice)
230 {
231 #if defined(SUPPORT_DRI_DRM)
232 OMAPLFB_DEVINFO *psDevInfo = (OMAPLFB_DEVINFO *)hDevice;
234 OMAPLFBAtomicBoolSet(&psDevInfo->sLeaveVT, OMAPLFB_FALSE);
235 (void) OMAPLFBUnblankDisplay(psDevInfo);
236 #else
237 UNREFERENCED_PARAMETER(hDevice);
238 #endif
239 return PVRSRV_OK;
240 }
242 static PVRSRV_ERROR EnumDCFormats(IMG_HANDLE hDevice,
243 IMG_UINT32 *pui32NumFormats,
244 DISPLAY_FORMAT *psFormat)
245 {
246 OMAPLFB_DEVINFO *psDevInfo;
248 if(!hDevice || !pui32NumFormats)
249 {
250 return PVRSRV_ERROR_INVALID_PARAMS;
251 }
253 psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
255 *pui32NumFormats = 1;
257 if(psFormat)
258 {
259 psFormat[0] = psDevInfo->sDisplayFormat;
260 }
262 return PVRSRV_OK;
263 }
265 static PVRSRV_ERROR EnumDCDims(IMG_HANDLE hDevice,
266 DISPLAY_FORMAT *psFormat,
267 IMG_UINT32 *pui32NumDims,
268 DISPLAY_DIMS *psDim)
269 {
270 OMAPLFB_DEVINFO *psDevInfo;
272 if(!hDevice || !psFormat || !pui32NumDims)
273 {
274 return PVRSRV_ERROR_INVALID_PARAMS;
275 }
277 psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
279 *pui32NumDims = 1;
282 if(psDim)
283 {
284 psDim[0] = psDevInfo->sDisplayDim;
285 }
287 return PVRSRV_OK;
288 }
291 static PVRSRV_ERROR GetDCSystemBuffer(IMG_HANDLE hDevice, IMG_HANDLE *phBuffer)
292 {
293 OMAPLFB_DEVINFO *psDevInfo;
295 if(!hDevice || !phBuffer)
296 {
297 return PVRSRV_ERROR_INVALID_PARAMS;
298 }
300 psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
302 *phBuffer = (IMG_HANDLE)&psDevInfo->sSystemBuffer;
304 return PVRSRV_OK;
305 }
308 static PVRSRV_ERROR GetDCInfo(IMG_HANDLE hDevice, DISPLAY_INFO *psDCInfo)
309 {
310 OMAPLFB_DEVINFO *psDevInfo;
312 if(!hDevice || !psDCInfo)
313 {
314 return PVRSRV_ERROR_INVALID_PARAMS;
315 }
317 psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
319 *psDCInfo = psDevInfo->sDisplayInfo;
321 return PVRSRV_OK;
322 }
324 static PVRSRV_ERROR GetDCBufferAddr(IMG_HANDLE hDevice,
325 IMG_HANDLE hBuffer,
326 IMG_SYS_PHYADDR **ppsSysAddr,
327 IMG_UINT32 *pui32ByteSize,
328 IMG_VOID **ppvCpuVAddr,
329 IMG_HANDLE *phOSMapInfo,
330 IMG_BOOL *pbIsContiguous,
331 IMG_UINT32 *pui32TilingStride)
332 {
333 OMAPLFB_DEVINFO *psDevInfo;
334 OMAPLFB_BUFFER *psSystemBuffer;
336 UNREFERENCED_PARAMETER(pui32TilingStride);
338 if(!hDevice)
339 {
340 return PVRSRV_ERROR_INVALID_PARAMS;
341 }
343 if(!hBuffer)
344 {
345 return PVRSRV_ERROR_INVALID_PARAMS;
346 }
348 if (!ppsSysAddr)
349 {
350 return PVRSRV_ERROR_INVALID_PARAMS;
351 }
353 if (!pui32ByteSize)
354 {
355 return PVRSRV_ERROR_INVALID_PARAMS;
356 }
358 psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
360 psSystemBuffer = (OMAPLFB_BUFFER *)hBuffer;
362 *ppsSysAddr = &psSystemBuffer->sSysAddr;
364 *pui32ByteSize = (IMG_UINT32)psDevInfo->sFBInfo.ulBufferSize;
366 if (ppvCpuVAddr)
367 {
368 *ppvCpuVAddr = psDevInfo->sFBInfo.bIs2D ? NULL : psSystemBuffer->sCPUVAddr;
369 }
371 if (phOSMapInfo)
372 {
373 *phOSMapInfo = (IMG_HANDLE)0;
374 }
376 if (pbIsContiguous)
377 {
378 *pbIsContiguous = !psDevInfo->sFBInfo.bIs2D;
379 }
381 #if defined(CONFIG_DSSCOMP)
382 if (psDevInfo->sFBInfo.bIs2D) {
383 int i = (psSystemBuffer->sSysAddr.uiAddr - psDevInfo->sFBInfo.psPageList->uiAddr) >> PAGE_SHIFT;
384 *ppsSysAddr = psDevInfo->sFBInfo.psPageList + psDevInfo->sFBInfo.ulHeight * i;
385 }
386 #endif
388 return PVRSRV_OK;
389 }
391 static PVRSRV_ERROR CreateDCSwapChain(IMG_HANDLE hDevice,
392 IMG_UINT32 ui32Flags,
393 DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
394 DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
395 IMG_UINT32 ui32BufferCount,
396 PVRSRV_SYNC_DATA **ppsSyncData,
397 IMG_UINT32 ui32OEMFlags,
398 IMG_HANDLE *phSwapChain,
399 IMG_UINT32 *pui32SwapChainID)
400 {
401 OMAPLFB_DEVINFO *psDevInfo;
402 OMAPLFB_SWAPCHAIN *psSwapChain;
403 OMAPLFB_BUFFER *psBuffer;
404 IMG_UINT32 i;
405 PVRSRV_ERROR eError;
407 UNREFERENCED_PARAMETER(ui32OEMFlags);
410 if(!hDevice
411 || !psDstSurfAttrib
412 || !psSrcSurfAttrib
413 || !ppsSyncData
414 || !phSwapChain)
415 {
416 return PVRSRV_ERROR_INVALID_PARAMS;
417 }
419 psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
422 if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
423 {
424 return PVRSRV_ERROR_NOT_SUPPORTED;
425 }
427 OMAPLFBCreateSwapChainLock(psDevInfo);
430 if(psDevInfo->psSwapChain != NULL)
431 {
432 eError = PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
433 goto ExitUnLock;
434 }
437 if(ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
438 {
439 eError = PVRSRV_ERROR_TOOMANYBUFFERS;
440 goto ExitUnLock;
441 }
443 if ((psDevInfo->sFBInfo.ulRoundedBufferSize * (unsigned long)ui32BufferCount) > psDevInfo->sFBInfo.ulFBSize)
444 {
445 eError = PVRSRV_ERROR_TOOMANYBUFFERS;
446 goto ExitUnLock;
447 }
449 if(psDstSurfAttrib->pixelformat != psDevInfo->sDisplayFormat.pixelformat
450 || psDstSurfAttrib->sDims.ui32ByteStride != psDevInfo->sDisplayDim.ui32ByteStride
451 || psDstSurfAttrib->sDims.ui32Width != psDevInfo->sDisplayDim.ui32Width
452 || psDstSurfAttrib->sDims.ui32Height != psDevInfo->sDisplayDim.ui32Height)
453 {
455 eError = PVRSRV_ERROR_INVALID_PARAMS;
456 goto ExitUnLock;
457 }
459 if(psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat
460 || psDstSurfAttrib->sDims.ui32ByteStride != psSrcSurfAttrib->sDims.ui32ByteStride
461 || psDstSurfAttrib->sDims.ui32Width != psSrcSurfAttrib->sDims.ui32Width
462 || psDstSurfAttrib->sDims.ui32Height != psSrcSurfAttrib->sDims.ui32Height)
463 {
465 eError = PVRSRV_ERROR_INVALID_PARAMS;
466 goto ExitUnLock;
467 }
469 UNREFERENCED_PARAMETER(ui32Flags);
471 #if defined(PVR_OMAPFB3_UPDATE_MODE)
472 if (!OMAPLFBSetUpdateMode(psDevInfo, PVR_OMAPFB3_UPDATE_MODE))
473 {
474 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't set frame buffer update mode %d\n", __FUNCTION__, psDevInfo->uiFBDevID, PVR_OMAPFB3_UPDATE_MODE);
475 }
476 #endif
478 psSwapChain = (OMAPLFB_SWAPCHAIN*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_SWAPCHAIN));
479 if(!psSwapChain)
480 {
481 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
482 goto ExitUnLock;
483 }
485 psBuffer = (OMAPLFB_BUFFER*)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_BUFFER) * ui32BufferCount);
486 if(!psBuffer)
487 {
488 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
489 goto ErrorFreeSwapChain;
490 }
492 psSwapChain->ulBufferCount = (unsigned long)ui32BufferCount;
493 psSwapChain->psBuffer = psBuffer;
494 psSwapChain->bNotVSynced = OMAPLFB_TRUE;
495 psSwapChain->uiFBDevID = psDevInfo->uiFBDevID;
498 for(i=0; i<ui32BufferCount-1; i++)
499 {
500 psBuffer[i].psNext = &psBuffer[i+1];
501 }
503 psBuffer[i].psNext = &psBuffer[0];
505 for(i=0; i<ui32BufferCount; i++)
506 {
507 IMG_UINT32 ui32SwapBuffer = i;
508 IMG_UINT32 ui32BufferOffset = ui32SwapBuffer * (IMG_UINT32)psDevInfo->sFBInfo.ulRoundedBufferSize;
509 if (psDevInfo->sFBInfo.bIs2D)
510 {
511 ui32BufferOffset = 0;
512 }
514 psBuffer[i].psSyncData = ppsSyncData[i];
515 psBuffer[i].sSysAddr.uiAddr = psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
516 psBuffer[i].sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset;
517 psBuffer[i].ulYOffset = ui32BufferOffset / psDevInfo->sFBInfo.ulByteStride;
518 if (psDevInfo->sFBInfo.bIs2D)
519 {
520 psBuffer[i].sSysAddr.uiAddr += ui32SwapBuffer *
521 ALIGN((IMG_UINT32)psDevInfo->sFBInfo.ulWidth * psDevInfo->sFBInfo.uiBytesPerPixel, PAGE_SIZE);
522 }
523 psBuffer[i].psDevInfo = psDevInfo;
524 OMAPLFBInitBufferForSwap(&psBuffer[i]);
525 psBuffer[i].bvmap_handle = NULL;
526 }
529 if (OMAPLFBCreateSwapQueue(psSwapChain) != OMAPLFB_OK)
530 {
531 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Failed to create workqueue\n", __FUNCTION__, psDevInfo->uiFBDevID);
532 eError = PVRSRV_ERROR_UNABLE_TO_INSTALL_ISR;
533 goto ErrorFreeBuffers;
534 }
536 if (OMAPLFBEnableLFBEventNotification(psDevInfo)!= OMAPLFB_OK)
537 {
538 eError = PVRSRV_ERROR_UNABLE_TO_ENABLE_EVENT;
539 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't enable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID);
540 goto ErrorDestroySwapQueue;
541 }
543 psDevInfo->uiSwapChainID++;
544 if (psDevInfo->uiSwapChainID == 0)
545 {
546 psDevInfo->uiSwapChainID++;
547 }
549 psSwapChain->uiSwapChainID = psDevInfo->uiSwapChainID;
551 psDevInfo->psSwapChain = psSwapChain;
553 *pui32SwapChainID = psDevInfo->uiSwapChainID;
555 *phSwapChain = (IMG_HANDLE)psSwapChain;
557 eError = PVRSRV_OK;
558 goto ExitUnLock;
560 ErrorDestroySwapQueue:
561 OMAPLFBDestroySwapQueue(psSwapChain);
562 ErrorFreeBuffers:
563 OMAPLFBFreeKernelMem(psBuffer);
564 ErrorFreeSwapChain:
565 OMAPLFBFreeKernelMem(psSwapChain);
566 ExitUnLock:
567 OMAPLFBCreateSwapChainUnLock(psDevInfo);
568 return eError;
569 }
571 static PVRSRV_ERROR DestroyDCSwapChain(IMG_HANDLE hDevice,
572 IMG_HANDLE hSwapChain)
573 {
574 OMAPLFB_DEVINFO *psDevInfo;
575 OMAPLFB_SWAPCHAIN *psSwapChain;
576 OMAPLFB_ERROR eError;
578 if(!hDevice || !hSwapChain)
579 {
580 return PVRSRV_ERROR_INVALID_PARAMS;
581 }
583 psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
584 psSwapChain = (OMAPLFB_SWAPCHAIN*)hSwapChain;
586 OMAPLFBCreateSwapChainLock(psDevInfo);
588 if (SwapChainHasChanged(psDevInfo, psSwapChain))
589 {
590 printk(KERN_WARNING DRIVER_PREFIX
591 ": %s: Device %u: Swap chain mismatch\n", __FUNCTION__, psDevInfo->uiFBDevID);
593 eError = PVRSRV_ERROR_INVALID_PARAMS;
594 goto ExitUnLock;
595 }
598 OMAPLFBDestroySwapQueue(psSwapChain);
600 eError = OMAPLFBDisableLFBEventNotification(psDevInfo);
601 if (eError != OMAPLFB_OK)
602 {
603 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Couldn't disable framebuffer event notification\n", __FUNCTION__, psDevInfo->uiFBDevID);
604 }
606 OMAPLFBDeInitBltFBs(psDevInfo);
607 gbBvReady = IMG_FALSE;
608 bBltReady = IMG_FALSE;
610 OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
611 OMAPLFBFreeKernelMem(psSwapChain);
613 psDevInfo->psSwapChain = NULL;
615 OMAPLFBFlip(psDevInfo, &psDevInfo->sSystemBuffer);
616 (void) OMAPLFBCheckModeAndSync(psDevInfo);
618 eError = PVRSRV_OK;
620 ExitUnLock:
621 OMAPLFBCreateSwapChainUnLock(psDevInfo);
623 return eError;
624 }
626 static PVRSRV_ERROR SetDCDstRect(IMG_HANDLE hDevice,
627 IMG_HANDLE hSwapChain,
628 IMG_RECT *psRect)
629 {
630 UNREFERENCED_PARAMETER(hDevice);
631 UNREFERENCED_PARAMETER(hSwapChain);
632 UNREFERENCED_PARAMETER(psRect);
636 return PVRSRV_ERROR_NOT_SUPPORTED;
637 }
639 static PVRSRV_ERROR SetDCSrcRect(IMG_HANDLE hDevice,
640 IMG_HANDLE hSwapChain,
641 IMG_RECT *psRect)
642 {
643 UNREFERENCED_PARAMETER(hDevice);
644 UNREFERENCED_PARAMETER(hSwapChain);
645 UNREFERENCED_PARAMETER(psRect);
649 return PVRSRV_ERROR_NOT_SUPPORTED;
650 }
652 static PVRSRV_ERROR SetDCDstColourKey(IMG_HANDLE hDevice,
653 IMG_HANDLE hSwapChain,
654 IMG_UINT32 ui32CKColour)
655 {
656 UNREFERENCED_PARAMETER(hDevice);
657 UNREFERENCED_PARAMETER(hSwapChain);
658 UNREFERENCED_PARAMETER(ui32CKColour);
662 return PVRSRV_ERROR_NOT_SUPPORTED;
663 }
665 static PVRSRV_ERROR SetDCSrcColourKey(IMG_HANDLE hDevice,
666 IMG_HANDLE hSwapChain,
667 IMG_UINT32 ui32CKColour)
668 {
669 UNREFERENCED_PARAMETER(hDevice);
670 UNREFERENCED_PARAMETER(hSwapChain);
671 UNREFERENCED_PARAMETER(ui32CKColour);
675 return PVRSRV_ERROR_NOT_SUPPORTED;
676 }
678 static PVRSRV_ERROR GetDCBuffers(IMG_HANDLE hDevice,
679 IMG_HANDLE hSwapChain,
680 IMG_UINT32 *pui32BufferCount,
681 IMG_HANDLE *phBuffer)
682 {
683 OMAPLFB_DEVINFO *psDevInfo;
684 OMAPLFB_SWAPCHAIN *psSwapChain;
685 PVRSRV_ERROR eError;
686 unsigned i;
689 if(!hDevice
690 || !hSwapChain
691 || !pui32BufferCount
692 || !phBuffer)
693 {
694 return PVRSRV_ERROR_INVALID_PARAMS;
695 }
697 psDevInfo = (OMAPLFB_DEVINFO*)hDevice;
698 psSwapChain = (OMAPLFB_SWAPCHAIN*)hSwapChain;
700 OMAPLFBCreateSwapChainLock(psDevInfo);
702 if (SwapChainHasChanged(psDevInfo, psSwapChain))
703 {
704 printk(KERN_WARNING DRIVER_PREFIX
705 ": %s: Device %u: Swap chain mismatch\n", __FUNCTION__, psDevInfo->uiFBDevID);
707 eError = PVRSRV_ERROR_INVALID_PARAMS;
708 goto Exit;
709 }
712 *pui32BufferCount = (IMG_UINT32)psSwapChain->ulBufferCount;
715 for(i=0; i<psSwapChain->ulBufferCount; i++)
716 {
717 phBuffer[i] = (IMG_HANDLE)&psSwapChain->psBuffer[i];
718 }
720 eError = PVRSRV_OK;
722 Exit:
723 OMAPLFBCreateSwapChainUnLock(psDevInfo);
725 return eError;
726 }
728 static PVRSRV_ERROR SwapToDCBuffer(IMG_HANDLE hDevice,
729 IMG_HANDLE hBuffer,
730 IMG_UINT32 ui32SwapInterval,
731 IMG_HANDLE hPrivateTag,
732 IMG_UINT32 ui32ClipRectCount,
733 IMG_RECT *psClipRect)
734 {
735 UNREFERENCED_PARAMETER(hDevice);
736 UNREFERENCED_PARAMETER(hBuffer);
737 UNREFERENCED_PARAMETER(ui32SwapInterval);
738 UNREFERENCED_PARAMETER(hPrivateTag);
739 UNREFERENCED_PARAMETER(ui32ClipRectCount);
740 UNREFERENCED_PARAMETER(psClipRect);
744 return PVRSRV_OK;
745 }
747 #if !defined(CONFIG_GCBV)
748 IMG_BOOL OMAPLFBInitBlt(void)
749 {
750 return IMG_FALSE;
751 }
753 OMAPLFB_ERROR OMAPLFBInitBltFBs(OMAPLFB_DEVINFO *psDevInfo)
754 {
755 return OMAPLFB_ERROR_INIT_FAILURE;
756 }
758 void OMAPLFBDeInitBltFBs(OMAPLFB_DEVINFO *psDevInfo)
759 {
760 }
762 void OMAPLFBGetBltFBsBvHndl(OMAPLFB_FBINFO *psPVRFBInfo, IMG_UINTPTR_T *ppPhysAddr)
763 {
764 *ppPhysAddr = 0;
765 }
767 void OMAPLFBDoBlits(OMAPLFB_DEVINFO *psDevInfo, PDC_MEM_INFO *ppsMemInfos, struct omap_hwc_blit_data *blit_data, IMG_UINT32 ui32NumMemInfos)
768 {
769 }
770 #endif /* CONFIG_GCBV */
771 static OMAPLFB_BOOL WaitForVSyncSettle(OMAPLFB_DEVINFO *psDevInfo)
772 {
773 unsigned i;
774 for(i = 0; i < OMAPLFB_VSYNC_SETTLE_COUNT; i++)
775 {
776 if (DontWaitForVSync(psDevInfo) || !OMAPLFBWaitForVSync(psDevInfo))
777 {
778 return OMAPLFB_FALSE;
779 }
780 }
782 return OMAPLFB_TRUE;
783 }
785 void OMAPLFBSwapHandler(OMAPLFB_BUFFER *psBuffer)
786 {
787 OMAPLFB_DEVINFO *psDevInfo = psBuffer->psDevInfo;
788 OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
789 OMAPLFB_BOOL bPreviouslyNotVSynced;
791 #if defined(SUPPORT_DRI_DRM)
792 if (!OMAPLFBAtomicBoolRead(&psDevInfo->sLeaveVT))
793 #endif
794 {
795 OMAPLFBFlip(psDevInfo, psBuffer);
796 }
798 bPreviouslyNotVSynced = psSwapChain->bNotVSynced;
799 psSwapChain->bNotVSynced = OMAPLFB_TRUE;
802 if (!DontWaitForVSync(psDevInfo))
803 {
804 OMAPLFB_UPDATE_MODE eMode = OMAPLFBGetUpdateMode(psDevInfo);
805 int iBlankEvents = OMAPLFBAtomicIntRead(&psDevInfo->sBlankEvents);
807 switch(eMode)
808 {
809 case OMAPLFB_UPDATE_MODE_AUTO:
810 psSwapChain->bNotVSynced = OMAPLFB_FALSE;
812 if (bPreviouslyNotVSynced || psSwapChain->iBlankEvents != iBlankEvents)
813 {
814 psSwapChain->iBlankEvents = iBlankEvents;
815 psSwapChain->bNotVSynced = !WaitForVSyncSettle(psDevInfo);
816 } else if (psBuffer->ulSwapInterval != 0)
817 {
818 psSwapChain->bNotVSynced = !OMAPLFBWaitForVSync(psDevInfo);
819 }
820 break;
821 #if defined(PVR_OMAPFB3_MANUAL_UPDATE_SYNC_IN_SWAP)
822 case OMAPLFB_UPDATE_MODE_MANUAL:
823 if (psBuffer->ulSwapInterval != 0)
824 {
825 (void) OMAPLFBManualSync(psDevInfo);
826 }
827 break;
828 #endif
829 default:
830 break;
831 }
832 }
834 psDevInfo->sPVRJTable.pfnPVRSRVCmdComplete((IMG_HANDLE)psBuffer->hCmdComplete, IMG_TRUE);
835 }
837 #if defined(CONFIG_DSSCOMP)
840 static void dsscomp_proxy_cmdcomplete(void * cookie, int i)
841 {
842 gapsDevInfo[0]->sPVRJTable.pfnPVRSRVCmdComplete(cookie, i);
843 }
844 #endif
846 static IMG_BOOL ProcessFlipV1(IMG_HANDLE hCmdCookie,
847 OMAPLFB_DEVINFO *psDevInfo,
848 OMAPLFB_SWAPCHAIN *psSwapChain,
849 OMAPLFB_BUFFER *psBuffer,
850 unsigned long ulSwapInterval)
851 {
852 OMAPLFBCreateSwapChainLock(psDevInfo);
854 if (SwapChainHasChanged(psDevInfo, psSwapChain))
855 {
856 DEBUG_PRINTK((KERN_WARNING DRIVER_PREFIX
857 ": %s: Device %u (PVR Device ID %u): The swap chain has been destroyed\n",
858 __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
859 }
860 else
861 {
862 psBuffer->hCmdComplete = (OMAPLFB_HANDLE)hCmdCookie;
863 psBuffer->ulSwapInterval = ulSwapInterval;
864 #if defined(CONFIG_DSSCOMP)
865 if (is_tiler_addr(psBuffer->sSysAddr.uiAddr)) {
866 IMG_UINT32 w = psBuffer->psDevInfo->sDisplayDim.ui32Width;
867 IMG_UINT32 h = psBuffer->psDevInfo->sDisplayDim.ui32Height;
868 struct dsscomp_setup_dispc_data comp = {
869 .num_mgrs = 1,
870 .mgrs[0].alpha_blending = 1,
871 .num_ovls = 1,
872 .ovls[0].cfg = {
873 .width = w,
874 .win.w = w,
875 .crop.w = w,
876 .height = h,
877 .win.h = h,
878 .crop.h = h,
879 .stride = psBuffer->psDevInfo->sDisplayDim.ui32ByteStride,
880 .color_mode = OMAP_DSS_COLOR_ARGB32,
881 .enabled = 1,
882 .global_alpha = 255,
883 },
884 .mode = DSSCOMP_SETUP_DISPLAY,
885 };
886 struct tiler_pa_info *pas[1] = { NULL };
887 comp.ovls[0].ba = (u32) psBuffer->sSysAddr.uiAddr;
888 dsscomp_gralloc_queue(&comp, pas, true,
889 dsscomp_proxy_cmdcomplete,
890 (void *) psBuffer->hCmdComplete);
891 } else
892 #endif
893 {
894 OMAPLFBQueueBufferForSwap(psSwapChain, psBuffer);
895 }
896 }
898 OMAPLFBCreateSwapChainUnLock(psDevInfo);
900 return IMG_TRUE;
901 }
903 #if defined(CONFIG_DSSCOMP) && (defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER))
904 int meminfo_idx_valid(unsigned int meminfo_ix, int num_meminfos)
905 {
906 if (meminfo_ix < 0 || meminfo_ix >= num_meminfos) {
907 WARN(1, "%s: Invalid meminfo index %d, max %d\n",
908 __func__, meminfo_ix, num_meminfos);
909 return 0;
910 }
911 return 1;
912 }
914 static IMG_BOOL ProcessFlipV2(IMG_HANDLE hCmdCookie,
915 OMAPLFB_DEVINFO *psDevInfo,
916 PDC_MEM_INFO *ppsMemInfos,
917 IMG_UINT32 ui32NumMemInfos,
918 struct omap_hwc_data *psHwcData,
919 IMG_UINT32 uiHwcDataSz)
920 {
921 struct tiler_pa_info *apsTilerPAs[5];
922 IMG_UINT32 i, k;
923 struct {
924 IMG_UINTPTR_T uiAddr;
925 IMG_UINTPTR_T uiUVAddr;
926 struct tiler_pa_info *psTilerInfo;
927 } asMemInfo[5];
929 /* Framebuffer info just used to get FB geometry, the address to
930 * use for blitting (dst buffer) is the first meminfo
931 */
932 int rgz_items;
933 int calcsz;
934 struct dsscomp_setup_dispc_data *psDssData = &(psHwcData->dsscomp_data);
935 int iMemIdx = 0;
936 int iUseBltFB;
937 #ifdef CONFIG_DRM_OMAP_DMM_TILER
938 enum tiler_fmt fmt;
939 #endif
941 if (uiHwcDataSz <= offsetof(struct omap_hwc_data, blit_data))
942 rgz_items = 0;
943 else
944 rgz_items = psHwcData->blit_data.rgz_items;
947 psDssData = &(psHwcData->dsscomp_data);
948 calcsz = sizeof(*psHwcData) +
949 (sizeof(struct rgz_blt_entry) * rgz_items);
950 iUseBltFB = psHwcData->blit_data.rgz_flags & HWC_BLT_FLAG_USE_FB;
952 if (!iUseBltFB && rgz_items > 0) {
953 WARN(1, "Trying to blit without a pipe configured for the blit FB");
954 return IMG_FALSE;
955 }
957 if (rgz_items > 0 && !gbBvInterfacePresent)
958 {
959 /* We cannot blit if BV GC2D is not present!, likely a bug */
960 WARN(1, "Trying to blit when BV GC2D is not present");
961 rgz_items = 0; /* Prevent blits */
962 }
964 if (iUseBltFB && !bBltReady)
965 {
966 /* Defer allocation and mapping of blit buffers */
967 if (OMAPLFBInitBltFBs(psDevInfo) != OMAPLFB_OK)
968 {
969 WARN(1, "Could not initialize blit FBs");
970 return IMG_FALSE;
971 }
973 bBltReady = IMG_TRUE;
974 }
976 memset(asMemInfo, 0, sizeof(asMemInfo));
978 /* Check the size of private data along with the blit operations */
979 if (uiHwcDataSz != calcsz)
980 {
981 WARN(1, "invalid size of private data (%d vs %d)",
982 uiHwcDataSz, calcsz);
983 }
985 if (ui32NumMemInfos == 0)
986 {
987 WARN(1, "must have at least one layer");
988 return IMG_FALSE;
989 }
991 if (iUseBltFB)
992 {
993 iMemIdx++;
994 /* Increment the Blt framebuffer and get new address */
995 OMAPLFBGetBltFBsBvHndl(&psDevInfo->sFBInfo, &asMemInfo[0].uiAddr);
996 }
998 for (i = 0, k = iMemIdx; i < ui32NumMemInfos && k < ARRAY_SIZE(apsTilerPAs) &&
999 k < psDssData->num_ovls; i++, k++) {
1001 struct tiler_pa_info *psTilerInfo;
1002 IMG_CPU_VIRTADDR virtAddr;
1003 IMG_CPU_PHYADDR aPhyAddr[DSS_MAX_NUMBER_YUV_PLANES];
1004 IMG_UINT32 ui32NumPages;
1005 IMG_SIZE_T uByteSize;
1006 IMG_UINT32 ui32NumAddrOffsets = DSS_MAX_NUMBER_YUV_PLANES;
1007 int j;
1009 memset(aPhyAddr, 0x00, sizeof(aPhyAddr));
1011 uByteSize = psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuMultiPlanePAddr(
1012 ppsMemInfos[i], IMG_NULL /* We want the beginning of the buffers */,
1013 aPhyAddr, &ui32NumAddrOffsets);
1015 if(uByteSize < 0)
1016 continue;
1018 ui32NumPages = (uByteSize + PAGE_SIZE - 1) >> PAGE_SHIFT;
1020 /* TILER buffers do not need meminfos */
1021 if(is_tiler_addr((u32)aPhyAddr[0].uiAddr))
1022 {
1023 asMemInfo[k].uiAddr = aPhyAddr[0].uiAddr;
1024 #ifdef CONFIG_DRM_OMAP_DMM_TILER
1025 if (tiler_get_fmt((u32)aPhyAddr[0].uiAddr, &fmt) && fmt == TILFMT_8BIT)
1026 #else /* CONFIG_TI_TILER must be defined if CONFIG_DRM_OMAP_DMM_TILER is not */
1027 if (tiler_fmt((u32)aPhyAddr[0].uiAddr) == TILFMT_8BIT)
1028 #endif
1029 {
1030 if(ui32NumAddrOffsets > 1)
1031 asMemInfo[k].uiUVAddr = aPhyAddr[1].uiAddr;
1032 }
1033 continue;
1034 }
1036 if (aPhyAddr[0].uiAddr >= psDevInfo->psLINFBInfo->fix.smem_start &&
1037 aPhyAddr[0].uiAddr < (psDevInfo->psLINFBInfo->fix.smem_start + psDevInfo->psLINFBInfo->fix.smem_len))
1038 {
1039 asMemInfo[k].uiAddr = aPhyAddr[0].uiAddr;
1040 continue;
1041 }
1042 /* normal gralloc layer */
1043 psTilerInfo = kzalloc(sizeof(*psTilerInfo), GFP_KERNEL);
1044 if(!psTilerInfo)
1045 {
1046 continue;
1047 }
1049 psTilerInfo->mem = kzalloc(sizeof(*psTilerInfo->mem) * ui32NumPages, GFP_KERNEL);
1050 if(!psTilerInfo->mem)
1051 {
1052 kfree(psTilerInfo);
1053 continue;
1054 }
1056 psTilerInfo->num_pg = ui32NumPages;
1057 psTilerInfo->memtype = TILER_MEM_USING;
1058 for(j = 0; j < ui32NumPages; j++)
1059 {
1060 IMG_CPU_PHYADDR pagePhyAddr;
1061 psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuPAddr(ppsMemInfos[i], j << PAGE_SHIFT, &pagePhyAddr);
1062 psTilerInfo->mem[j] = (u32)pagePhyAddr.uiAddr;
1063 }
1065 /* need base address for in-page offset */
1066 psDevInfo->sPVRJTable.pfnPVRSRVDCMemInfoGetCpuVAddr(ppsMemInfos[i], &virtAddr);
1067 asMemInfo[k].uiAddr = (IMG_UINTPTR_T) virtAddr;
1068 asMemInfo[k].psTilerInfo = psTilerInfo;
1069 }
1071 for(i = 0; i < psDssData->num_ovls; i++)
1072 {
1073 unsigned int ix;
1074 apsTilerPAs[i] = NULL;
1076 /* only supporting Post2, cloned and fbmem layers */
1077 if (psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_LAYER_IX &&
1078 psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_OVL_IX &&
1079 psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_FB &&
1080 psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_ION)
1081 psDssData->ovls[i].cfg.enabled = false;
1083 if (psDssData->ovls[i].addressing != OMAP_DSS_BUFADDR_LAYER_IX)
1084 continue;
1086 /* Post2 layers */
1087 ix = psDssData->ovls[i].ba;
1088 if (ix >= k)
1089 {
1090 WARN(1, "Invalid Post2 layer (%u)", ix);
1091 psDssData->ovls[i].cfg.enabled = false;
1092 continue;
1093 }
1095 psDssData->ovls[i].addressing = OMAP_DSS_BUFADDR_DIRECT;
1096 psDssData->ovls[i].ba = (u32) asMemInfo[ix].uiAddr;
1097 psDssData->ovls[i].uv = (u32) asMemInfo[ix].uiUVAddr;
1098 apsTilerPAs[i] = asMemInfo[ix].psTilerInfo;
1099 }
1101 if (rgz_items > 0)
1102 {
1103 OMAPLFBDoBlits(psDevInfo, ppsMemInfos, &psHwcData->blit_data, ui32NumMemInfos);
1104 }
1106 if (psDssData->num_ovls == 0)
1107 dsscomp_proxy_cmdcomplete((void *)hCmdCookie, IMG_TRUE);
1108 else
1109 dsscomp_gralloc_queue(psDssData, apsTilerPAs, false,
1110 dsscomp_proxy_cmdcomplete,
1111 (void *)hCmdCookie);
1113 for(i = 0; i < ARRAY_SIZE(asMemInfo); i++)
1114 {
1115 tiler_pa_free(asMemInfo[i].psTilerInfo);
1116 }
1118 return IMG_TRUE;
1119 }
1121 #endif
1123 static IMG_BOOL ProcessFlip(IMG_HANDLE hCmdCookie,
1124 IMG_UINT32 ui32DataSize,
1125 IMG_VOID *pvData)
1126 {
1127 DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
1128 OMAPLFB_DEVINFO *psDevInfo;
1130 if(!hCmdCookie || !pvData)
1131 {
1132 return IMG_FALSE;
1133 }
1135 psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)pvData;
1137 if (psFlipCmd == IMG_NULL)
1138 {
1139 return IMG_FALSE;
1140 }
1142 psDevInfo = (OMAPLFB_DEVINFO*)psFlipCmd->hExtDevice;
1144 if(psFlipCmd->hExtBuffer)
1145 {
1146 return ProcessFlipV1(hCmdCookie,
1147 psDevInfo,
1148 psFlipCmd->hExtSwapChain,
1149 psFlipCmd->hExtBuffer,
1150 psFlipCmd->ui32SwapInterval);
1151 }
1152 else
1153 {
1154 #if defined(CONFIG_DSSCOMP) && (defined(CONFIG_TI_TILER) || defined(CONFIG_DRM_OMAP_DMM_TILER))
1155 DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd2;
1156 psFlipCmd2 = (DISPLAYCLASS_FLIP_COMMAND2 *)pvData;
1157 return ProcessFlipV2(hCmdCookie,
1158 psDevInfo,
1159 psFlipCmd2->ppsMemInfos,
1160 psFlipCmd2->ui32NumMemInfos,
1161 psFlipCmd2->pvPrivData,
1162 psFlipCmd2->ui32PrivDataLength);
1163 #else
1164 BUG();
1165 #endif
1166 }
1167 }
1169 #if defined(CONFIG_DSSCOMP)
1171 static OMAPLFB_ERROR OMAPLFBInitIonOmap(OMAPLFB_DEVINFO *psDevInfo,
1172 struct fb_info *psLINFBInfo,
1173 OMAPLFB_FBINFO *psPVRFBInfo)
1174 {
1175 int n;
1176 int iMaxSwapChainBuffs;
1177 int res;
1178 int i, x, y, w;
1179 ion_phys_addr_t phys;
1180 size_t size;
1181 struct tiler_view_t view;
1183 struct omap_ion_tiler_alloc_data sAllocData = {
1184 .w = ALIGN(psLINFBInfo->var.xres, PAGE_SIZE / (psLINFBInfo->var.bits_per_pixel / 8)),
1185 .h = psLINFBInfo->var.yres,
1186 .fmt = psLINFBInfo->var.bits_per_pixel == 16 ? TILER_PIXEL_FMT_16BIT : TILER_PIXEL_FMT_32BIT,
1187 .flags = 0,
1188 .token = 0,
1189 .out_align = PAGE_SIZE
1190 };
1191 unsigned uiFBDevID = psDevInfo->uiFBDevID;
1192 struct sgx_omaplfb_config *psFBPlatConfig = GetFBPlatConfig(uiFBDevID);
1194 #if defined(CONFIG_ION_OMAP)
1195 gpsIONClient = ion_client_create(omap_ion_device,
1196 1 << ION_HEAP_TYPE_CARVEOUT |
1197 1 << OMAP_ION_HEAP_TYPE_TILER |
1198 1 << ION_HEAP_TYPE_SYSTEM,
1199 "omaplfb");
1200 if (IS_ERR_OR_NULL(gpsIONClient))
1201 {
1202 printk(KERN_ERR DRIVER_PREFIX
1203 " %s: Could not create ion client\n", __FUNCTION__);
1204 return OMAPLFB_ERROR_INIT_FAILURE;
1205 }
1206 #endif /* defined(CONFIG_ION_OMAP) */
1208 if (!psFBPlatConfig->swap_chain_length)
1209 {
1210 /* Set a default swap chain length if it's not present in the platform data */
1211 iMaxSwapChainBuffs = 2;
1212 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Swap chain length missing in "
1213 "platform data, defaulting to %d\n", __FUNCTION__, psDevInfo->uiFBDevID,
1214 iMaxSwapChainBuffs);
1215 }
1216 else
1217 {
1218 iMaxSwapChainBuffs = psFBPlatConfig->swap_chain_length;
1219 }
1221 if (psFBPlatConfig->tiler2d_buffers < iMaxSwapChainBuffs)
1222 {
1223 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Trying to use %d tiler "
1224 "buffers which is less than the swap chain length of %d, maximum "
1225 "swap chain length will be set to %d\n", __FUNCTION__, psDevInfo->uiFBDevID,
1226 psFBPlatConfig->tiler2d_buffers, iMaxSwapChainBuffs, psFBPlatConfig->tiler2d_buffers);
1227 iMaxSwapChainBuffs = psFBPlatConfig->tiler2d_buffers;
1228 }
1230 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = iMaxSwapChainBuffs;
1231 n = psFBPlatConfig->tiler2d_buffers;
1233 printk(KERN_DEBUG DRIVER_PREFIX
1234 ": %s: Device %u: Requesting %d TILER 2D framebuffers\n", __FUNCTION__, uiFBDevID, n);
1235 sAllocData.w *= n;
1237 psPVRFBInfo->uiBytesPerPixel = psLINFBInfo->var.bits_per_pixel >> 3;
1238 psPVRFBInfo->bIs2D = OMAPLFB_TRUE;
1239 res = omap_ion_nonsecure_tiler_alloc(gpsIONClient, &sAllocData);
1240 if (res < 0)
1241 {
1242 printk(KERN_ERR DRIVER_PREFIX
1243 " %s: Device %u: Could not allocate 2D framebuffer(%d)\n", __FUNCTION__, uiFBDevID, res);
1244 return OMAPLFB_ERROR_INIT_FAILURE;
1245 }
1247 ion_phys(gpsIONClient, sAllocData.handle, &phys, &size);
1248 psPVRFBInfo->sSysAddr.uiAddr = phys;
1249 psPVRFBInfo->sCPUVAddr = 0;
1251 psPVRFBInfo->ulWidth = psLINFBInfo->var.xres;
1252 psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
1253 psPVRFBInfo->ulByteStride = PAGE_ALIGN(psPVRFBInfo->ulWidth * psPVRFBInfo->uiBytesPerPixel);
1254 psPVRFBInfo->ulBufferSize = psPVRFBInfo->ulHeight * psPVRFBInfo->ulByteStride;
1255 psPVRFBInfo->ulRoundedBufferSize = psPVRFBInfo->ulBufferSize;
1256 w = psPVRFBInfo->ulByteStride >> PAGE_SHIFT;
1258 /* this is an "effective" FB size to get correct number of buffers */
1259 psPVRFBInfo->ulFBSize = sAllocData.h * n * psPVRFBInfo->ulByteStride;
1260 psPVRFBInfo->psPageList = kzalloc(w * n * psPVRFBInfo->ulHeight * sizeof(*psPVRFBInfo->psPageList), GFP_KERNEL);
1261 if (!psPVRFBInfo->psPageList)
1262 {
1263 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Could not allocate page list\n", __FUNCTION__, psDevInfo->uiFBDevID);
1264 ion_free(gpsIONClient, sAllocData.handle);
1265 return OMAPLFB_ERROR_INIT_FAILURE;
1266 }
1267 psPVRFBInfo->psIONHandle = sAllocData.handle;
1269 tilview_create(&view, phys, psDevInfo->sFBInfo.ulWidth, psDevInfo->sFBInfo.ulHeight);
1270 for(i=0; i<n; i++)
1271 {
1272 for(y=0; y<psDevInfo->sFBInfo.ulHeight; y++)
1273 {
1274 for(x=0; x<w; x++)
1275 {
1276 psPVRFBInfo->psPageList[i * psDevInfo->sFBInfo.ulHeight * w + y * w + x].uiAddr =
1277 phys + view.v_inc * y + ((x + i * w) << PAGE_SHIFT);
1278 }
1279 }
1280 }
1281 return OMAPLFB_OK;
1282 }
1283 #endif
1285 static OMAPLFB_ERROR OMAPLFBInitFBVRAM(OMAPLFB_DEVINFO *psDevInfo,
1286 struct fb_info *psLINFBInfo,
1287 OMAPLFB_FBINFO *psPVRFBInfo)
1288 {
1289 struct sgx_omaplfb_config *psFBPlatConfig = GetFBPlatConfig(psDevInfo->uiFBDevID);
1290 unsigned long FBSize = psLINFBInfo->fix.smem_len;
1291 unsigned long ulLCM;
1292 int iMaxSwapChainBuffs;
1293 IMG_UINT32 ui32FBAvailableBuffs;
1295 /* Check if there is VRAM reserved for this FB */
1296 if (FBSize == 0 || psLINFBInfo->fix.line_length == 0)
1297 {
1298 return OMAPLFB_ERROR_INVALID_DEVICE;
1299 }
1301 /* Fail to init this DC device if vram buffers are not set */
1302 if (!psFBPlatConfig->vram_buffers)
1303 {
1304 return OMAPLFB_ERROR_INVALID_PARAMS;
1305 }
1307 if (!psFBPlatConfig->swap_chain_length)
1308 {
1309 /* Set a default swap chain length if it's not present in the platform data */
1310 iMaxSwapChainBuffs = 2;
1311 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Swap chain length missing in "
1312 "platform data, defaulting to %d\n", __FUNCTION__, psDevInfo->uiFBDevID,
1313 iMaxSwapChainBuffs);
1314 }
1315 else
1316 {
1317 iMaxSwapChainBuffs = psFBPlatConfig->swap_chain_length;
1318 }
1320 if (psFBPlatConfig->vram_buffers < iMaxSwapChainBuffs)
1321 {
1322 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Trying to use %d vram "
1323 "buffers which is less than the swap chain length of %d, maximum "
1324 "swap chain length will be set to %d\n", __FUNCTION__, psDevInfo->uiFBDevID,
1325 psFBPlatConfig->vram_buffers, iMaxSwapChainBuffs, psFBPlatConfig->vram_buffers);
1326 iMaxSwapChainBuffs = psFBPlatConfig->vram_buffers;
1327 }
1329 ulLCM = LCM(psLINFBInfo->fix.line_length, OMAPLFB_PAGE_SIZE);
1330 psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
1331 psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
1332 psPVRFBInfo->ulWidth = psLINFBInfo->var.xres;
1333 psPVRFBInfo->ulHeight = psLINFBInfo->var.yres;
1334 psPVRFBInfo->ulByteStride = psLINFBInfo->fix.line_length;
1335 psPVRFBInfo->ulFBSize = FBSize;
1336 psPVRFBInfo->bIs2D = OMAPLFB_FALSE;
1337 psPVRFBInfo->psPageList = IMG_NULL;
1338 psPVRFBInfo->ulBufferSize = psPVRFBInfo->ulHeight * psPVRFBInfo->ulByteStride;
1339 psPVRFBInfo->ulRoundedBufferSize = RoundUpToMultiple(psPVRFBInfo->ulBufferSize, ulLCM);
1340 ui32FBAvailableBuffs = (IMG_UINT32)(psDevInfo->sFBInfo.ulFBSize / psDevInfo->sFBInfo.ulRoundedBufferSize);
1342 if (!ui32FBAvailableBuffs)
1343 {
1344 printk(KERN_ERR DRIVER_PREFIX " %s: Device %u: Not enough vram to init swap "
1345 "chain buffers\n", __FUNCTION__, psDevInfo->uiFBDevID);
1346 return OMAPLFB_ERROR_INIT_FAILURE;
1347 }
1348 else if (ui32FBAvailableBuffs < psFBPlatConfig->vram_buffers)
1349 {
1350 printk(KERN_WARNING DRIVER_PREFIX ": %s: Device %u: Not enough vram to hold "
1351 "%d buffers (available %d), swap chain length will be set to %d\n",
1352 __FUNCTION__, psDevInfo->uiFBDevID, iMaxSwapChainBuffs, ui32FBAvailableBuffs,
1353 ui32FBAvailableBuffs);
1354 iMaxSwapChainBuffs = ui32FBAvailableBuffs;
1355 }
1356 else
1357 {
1358 iMaxSwapChainBuffs = psFBPlatConfig->vram_buffers;
1359 }
1361 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = iMaxSwapChainBuffs;
1363 printk(KERN_DEBUG DRIVER_PREFIX ": %s: Device %u: Using %d VRAM framebuffers\n", __FUNCTION__,
1364 psDevInfo->uiFBDevID, iMaxSwapChainBuffs);
1366 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1367 ": Device %u: Framebuffer virtual width: %u\n",
1368 psDevInfo->uiFBDevID, psLINFBInfo->var.xres_virtual));
1369 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1370 ": Device %u: Framebuffer virtual height: %u\n",
1371 psDevInfo->uiFBDevID, psLINFBInfo->var.yres_virtual));
1372 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1373 ": Device %u: LCM of stride and page size: %lu\n",
1374 psDevInfo->uiFBDevID, ulLCM));
1376 return OMAPLFB_OK;
1377 }
1379 static OMAPLFB_ERROR OMAPLFBInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
1380 {
1381 struct fb_info *psLINFBInfo;
1382 struct module *psLINFBOwner;
1383 OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
1384 OMAPLFB_ERROR eError = OMAPLFB_ERROR_GENERIC;
1385 unsigned uiFBDevID = psDevInfo->uiFBDevID;
1386 struct sgx_omaplfb_config *psFBPlatConfig;
1388 OMAPLFB_CONSOLE_LOCK();
1390 psLINFBInfo = registered_fb[uiFBDevID];
1391 if (psLINFBInfo == NULL)
1392 {
1393 eError = OMAPLFB_ERROR_INVALID_DEVICE;
1394 goto ErrorRelSem;
1395 }
1397 psLINFBOwner = psLINFBInfo->fbops->owner;
1398 if (!try_module_get(psLINFBOwner))
1399 {
1400 printk(KERN_INFO DRIVER_PREFIX
1401 ": %s: Device %u: Couldn't get framebuffer module\n", __FUNCTION__, uiFBDevID);
1403 goto ErrorRelSem;
1404 }
1406 if (psLINFBInfo->fbops->fb_open != NULL)
1407 {
1408 int res;
1410 res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
1411 if (res != 0)
1412 {
1413 printk(KERN_INFO DRIVER_PREFIX
1414 " %s: Device %u: Couldn't open framebuffer(%d)\n", __FUNCTION__, uiFBDevID, res);
1416 goto ErrorModPut;
1417 }
1418 }
1420 psDevInfo->psLINFBInfo = psLINFBInfo;
1422 /*
1423 * Abort registering this DC device if no platform data found. This
1424 * shouldn't happen since the FB index must be valid at this point.
1425 */
1426 psFBPlatConfig = GetFBPlatConfig(uiFBDevID);
1427 if (!psFBPlatConfig)
1428 {
1429 eError = OMAPLFB_ERROR_INVALID_PARAMS;
1430 goto ErrorModPut;
1431 }
1433 #if defined(CONFIG_DSSCOMP)
1434 if (psFBPlatConfig->tiler2d_buffers)
1435 {
1436 /* Use ION to create the flip chain buffers with TILER */
1437 eError = OMAPLFBInitIonOmap(psDevInfo, psLINFBInfo, psPVRFBInfo);
1438 if (eError != OMAPLFB_OK)
1439 {
1440 goto ErrorModPut;
1441 }
1442 }
1443 else
1444 #endif
1445 {
1446 /* Fall back to allocate flip chain buffers with VRAM */
1447 eError = OMAPLFBInitFBVRAM(psDevInfo, psLINFBInfo, psPVRFBInfo);
1448 if (eError != OMAPLFB_OK)
1449 {
1450 goto ErrorModPut;
1451 }
1452 }
1454 OMAPLFBPrintInfo(psDevInfo);
1455 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1456 ": Device %u: Framebuffer physical address: %p\n",
1457 psDevInfo->uiFBDevID, (void *)psPVRFBInfo->sSysAddr.uiAddr));
1458 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1459 ": Device %u: Framebuffer virtual address: %p\n",
1460 psDevInfo->uiFBDevID, (void *)psPVRFBInfo->sCPUVAddr));
1461 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1462 ": Device %u: Framebuffer size: %lu\n",
1463 psDevInfo->uiFBDevID, psPVRFBInfo->ulFBSize));
1464 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1465 ": Device %u: Framebuffer width: %lu\n",
1466 psDevInfo->uiFBDevID, psPVRFBInfo->ulWidth));
1467 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1468 ": Device %u: Framebuffer height: %lu\n",
1469 psDevInfo->uiFBDevID, psPVRFBInfo->ulHeight));
1470 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1471 ": Device %u: Framebuffer stride: %lu\n",
1472 psDevInfo->uiFBDevID, psPVRFBInfo->ulByteStride));
1474 if(psLINFBInfo->var.bits_per_pixel == 16)
1475 {
1476 if((psLINFBInfo->var.red.length == 5) &&
1477 (psLINFBInfo->var.green.length == 6) &&
1478 (psLINFBInfo->var.blue.length == 5) &&
1479 (psLINFBInfo->var.red.offset == 11) &&
1480 (psLINFBInfo->var.green.offset == 5) &&
1481 (psLINFBInfo->var.blue.offset == 0) &&
1482 (psLINFBInfo->var.red.msb_right == 0))
1483 {
1484 psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
1485 }
1486 else
1487 {
1488 printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown FB format\n", __FUNCTION__, uiFBDevID);
1489 }
1490 }
1491 else if(psLINFBInfo->var.bits_per_pixel == 32)
1492 {
1493 if((psLINFBInfo->var.red.length == 8) &&
1494 (psLINFBInfo->var.green.length == 8) &&
1495 (psLINFBInfo->var.blue.length == 8) &&
1496 (psLINFBInfo->var.red.offset == 16) &&
1497 (psLINFBInfo->var.green.offset == 8) &&
1498 (psLINFBInfo->var.blue.offset == 0) &&
1499 (psLINFBInfo->var.red.msb_right == 0))
1500 {
1501 psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_ARGB8888;
1502 }
1503 else
1504 {
1505 printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown FB format\n", __FUNCTION__, uiFBDevID);
1506 }
1507 }
1508 else
1509 {
1510 printk(KERN_INFO DRIVER_PREFIX ": %s: Device %u: Unknown FB format\n", __FUNCTION__, uiFBDevID);
1511 }
1513 psDevInfo->sFBInfo.ulPhysicalWidthmm =
1514 ((int)psLINFBInfo->var.width > 0) ? psLINFBInfo->var.width : 90;
1516 psDevInfo->sFBInfo.ulPhysicalHeightmm =
1517 ((int)psLINFBInfo->var.height > 0) ? psLINFBInfo->var.height : 54;
1520 psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
1521 psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
1523 eError = OMAPLFB_OK;
1524 goto ErrorRelSem;
1526 ErrorModPut:
1527 module_put(psLINFBOwner);
1528 ErrorRelSem:
1529 OMAPLFB_CONSOLE_UNLOCK();
1531 return eError;
1532 }
1534 static void OMAPLFBDeInitFBDev(OMAPLFB_DEVINFO *psDevInfo)
1535 {
1536 struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
1537 OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
1538 struct module *psLINFBOwner;
1540 OMAPLFB_CONSOLE_LOCK();
1542 psLINFBOwner = psLINFBInfo->fbops->owner;
1544 #if defined(CONFIG_DSSCOMP)
1545 kfree(psPVRFBInfo->psPageList);
1546 if (psPVRFBInfo->psIONHandle)
1547 {
1548 ion_free(gpsIONClient, psPVRFBInfo->psIONHandle);
1549 }
1550 if (psPVRFBInfo->psBltFBsIonHndl)
1551 {
1552 ion_free(gpsIONClient, psPVRFBInfo->psBltFBsIonHndl);
1553 }
1554 if (psPVRFBInfo->psBltFBsBvHndl)
1555 {
1556 int i;
1557 for (i = 0; i < psPVRFBInfo->psBltFBsNo; i++)
1558 {
1559 if (psPVRFBInfo->psBltFBsBvHndl[i])
1560 {
1561 kfree(psPVRFBInfo->psBltFBsBvHndl[i]);
1562 }
1563 }
1564 kfree(psPVRFBInfo->psBltFBsBvHndl);
1565 kfree(psPVRFBInfo->psBltFBsBvPhys);
1566 }
1567 #endif
1568 if (psLINFBInfo->fbops->fb_release != NULL)
1569 {
1570 (void) psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
1571 }
1573 module_put(psLINFBOwner);
1575 OMAPLFB_CONSOLE_UNLOCK();
1576 }
1578 static OMAPLFB_DEVINFO *OMAPLFBInitDev(unsigned uiFBDevID)
1579 {
1580 PFN_CMD_PROC pfnCmdProcList[OMAPLFB_COMMAND_COUNT];
1581 IMG_UINT32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
1582 OMAPLFB_DEVINFO *psDevInfo = NULL;
1585 psDevInfo = (OMAPLFB_DEVINFO *)OMAPLFBAllocKernelMem(sizeof(OMAPLFB_DEVINFO));
1587 if(psDevInfo == NULL)
1588 {
1589 printk(KERN_ERR DRIVER_PREFIX
1590 ": %s: Device %u: Couldn't allocate device information structure\n", __FUNCTION__, uiFBDevID);
1592 goto ErrorExit;
1593 }
1596 memset(psDevInfo, 0, sizeof(OMAPLFB_DEVINFO));
1598 psDevInfo->uiFBDevID = uiFBDevID;
1601 if(!(*gpfnGetPVRJTable)(&psDevInfo->sPVRJTable))
1602 {
1603 goto ErrorFreeDevInfo;
1604 }
1607 if(OMAPLFBInitFBDev(psDevInfo) != OMAPLFB_OK)
1608 {
1610 goto ErrorFreeDevInfo;
1611 }
1613 if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers != 0)
1614 {
1615 psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1;
1616 psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 1;
1617 }
1619 psDevInfo->sDisplayInfo.ui32PhysicalWidthmm = psDevInfo->sFBInfo.ulPhysicalWidthmm;
1620 psDevInfo->sDisplayInfo.ui32PhysicalHeightmm = psDevInfo->sFBInfo.ulPhysicalHeightmm;
1622 strncpy(psDevInfo->sDisplayInfo.szDisplayName, DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
1624 psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat;
1625 psDevInfo->sDisplayDim.ui32Width = (IMG_UINT32)psDevInfo->sFBInfo.ulWidth;
1626 psDevInfo->sDisplayDim.ui32Height = (IMG_UINT32)psDevInfo->sFBInfo.ulHeight;
1627 psDevInfo->sDisplayDim.ui32ByteStride = (IMG_UINT32)psDevInfo->sFBInfo.ulByteStride;
1629 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1630 ": Device %u: Maximum number of swap chain buffers: %u\n",
1631 psDevInfo->uiFBDevID, psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
1634 psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
1635 psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
1636 psDevInfo->sSystemBuffer.psDevInfo = psDevInfo;
1638 OMAPLFBInitBufferForSwap(&psDevInfo->sSystemBuffer);
1642 psDevInfo->sDCJTable.ui32TableSize = sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE);
1643 psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
1644 psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
1645 psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
1646 psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
1647 psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
1648 psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
1649 psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
1650 psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
1651 psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
1652 psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
1653 psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
1654 psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
1655 psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
1656 psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
1657 psDevInfo->sDCJTable.pfnSwapToDCBuffer = SwapToDCBuffer;
1658 psDevInfo->sDCJTable.pfnSetDCState = SetDCState;
1661 if(psDevInfo->sPVRJTable.pfnPVRSRVRegisterDCDevice(
1662 &psDevInfo->sDCJTable,
1663 &psDevInfo->uiPVRDevID) != PVRSRV_OK)
1664 {
1665 printk(KERN_ERR DRIVER_PREFIX
1666 ": %s: Device %u: PVR Services device registration failed\n", __FUNCTION__, uiFBDevID);
1668 goto ErrorDeInitFBDev;
1669 }
1670 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
1671 ": Device %u: PVR Device ID: %u\n",
1672 psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID));
1675 pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
1678 aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
1679 if (gbBvInterfacePresent)
1680 {
1681 aui32SyncCountList[DC_FLIP_COMMAND][1] = 32;
1682 }
1683 else
1684 {
1685 aui32SyncCountList[DC_FLIP_COMMAND][1] = 10;
1686 }
1692 if (psDevInfo->sPVRJTable.pfnPVRSRVRegisterCmdProcList(psDevInfo->uiPVRDevID,
1693 &pfnCmdProcList[0],
1694 aui32SyncCountList,
1695 OMAPLFB_COMMAND_COUNT) != PVRSRV_OK)
1696 {
1697 printk(KERN_ERR DRIVER_PREFIX
1698 ": %s: Device %u: Couldn't register command processing functions with PVR Services\n", __FUNCTION__, uiFBDevID);
1699 goto ErrorUnregisterDevice;
1700 }
1702 OMAPLFBCreateSwapChainLockInit(psDevInfo);
1704 OMAPLFBAtomicBoolInit(&psDevInfo->sBlanked, OMAPLFB_FALSE);
1705 OMAPLFBAtomicIntInit(&psDevInfo->sBlankEvents, 0);
1706 OMAPLFBAtomicBoolInit(&psDevInfo->sFlushCommands, OMAPLFB_FALSE);
1707 #if defined(CONFIG_HAS_EARLYSUSPEND)
1708 OMAPLFBAtomicBoolInit(&psDevInfo->sEarlySuspendFlag, OMAPLFB_FALSE);
1709 #endif
1710 #if defined(SUPPORT_DRI_DRM)
1711 OMAPLFBAtomicBoolInit(&psDevInfo->sLeaveVT, OMAPLFB_FALSE);
1712 #endif
1713 return psDevInfo;
1715 ErrorUnregisterDevice:
1716 (void)psDevInfo->sPVRJTable.pfnPVRSRVRemoveDCDevice(psDevInfo->uiPVRDevID);
1717 ErrorDeInitFBDev:
1718 OMAPLFBDeInitFBDev(psDevInfo);
1719 ErrorFreeDevInfo:
1720 OMAPLFBFreeKernelMem(psDevInfo);
1721 ErrorExit:
1722 return NULL;
1723 }
1725 #if defined(CONFIG_OMAPLFB)
1726 int OMAPLFBRegisterPVRDriver(PFN_DC_GET_PVRJTABLE pfnFuncTable)
1727 {
1728 gpfnGetPVRJTable = pfnFuncTable;
1730 if(OMAPLFBInit() != OMAPLFB_OK)
1731 {
1732 printk(KERN_ERR DRIVER_PREFIX
1733 " %s: Could not create ion client\n", __FUNCTION__);
1734 return -1;
1735 }
1736 return 0;
1737 }
1738 EXPORT_SYMBOL(OMAPLFBRegisterPVRDriver);
1739 #endif
1741 OMAPLFB_ERROR OMAPLFBInit(void)
1742 {
1743 unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
1744 unsigned i;
1745 unsigned uiDevicesFound = 0;
1747 #if !defined(CONFIG_OMAPLFB)
1748 if(OMAPLFBGetLibFuncAddr ("PVRGetDisplayClassJTable", &gpfnGetPVRJTable) != OMAPLFB_OK)
1749 {
1750 return OMAPLFB_ERROR_INIT_FAILURE;
1751 }
1752 #endif
1754 gbBvInterfacePresent = OMAPLFBInitBlt();
1756 if (!gbBvInterfacePresent)
1757 {
1758 printk(KERN_INFO DRIVER_PREFIX "%s: Blitsville gc2d "
1759 "not present, blits disabled\n", __func__);
1760 }
1761 for(i = uiMaxFBDevIDPlusOne; i-- != 0;)
1762 {
1763 OMAPLFB_DEVINFO *psDevInfo = OMAPLFBInitDev(i);
1765 if (psDevInfo != NULL)
1766 {
1768 OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, psDevInfo);
1769 uiDevicesFound++;
1770 }
1771 }
1773 return (uiDevicesFound != 0) ? OMAPLFB_OK : OMAPLFB_ERROR_INIT_FAILURE;
1774 }
1776 static OMAPLFB_BOOL OMAPLFBDeInitDev(OMAPLFB_DEVINFO *psDevInfo)
1777 {
1778 PVRSRV_DC_DISP2SRV_KMJTABLE *psPVRJTable = &psDevInfo->sPVRJTable;
1780 OMAPLFBCreateSwapChainLockDeInit(psDevInfo);
1782 OMAPLFBAtomicBoolDeInit(&psDevInfo->sBlanked);
1783 OMAPLFBAtomicIntDeInit(&psDevInfo->sBlankEvents);
1784 OMAPLFBAtomicBoolDeInit(&psDevInfo->sFlushCommands);
1785 #if defined(CONFIG_HAS_EARLYSUSPEND)
1786 OMAPLFBAtomicBoolDeInit(&psDevInfo->sEarlySuspendFlag);
1787 #endif
1788 #if defined(SUPPORT_DRI_DRM)
1789 OMAPLFBAtomicBoolDeInit(&psDevInfo->sLeaveVT);
1790 #endif
1791 psPVRJTable = &psDevInfo->sPVRJTable;
1793 if (psPVRJTable->pfnPVRSRVRemoveCmdProcList (psDevInfo->uiPVRDevID, OMAPLFB_COMMAND_COUNT) != PVRSRV_OK)
1794 {
1795 printk(KERN_ERR DRIVER_PREFIX
1796 ": %s: Device %u: PVR Device %u: Couldn't unregister command processing functions\n", __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID);
1797 return OMAPLFB_FALSE;
1798 }
1801 if (psPVRJTable->pfnPVRSRVRemoveDCDevice(psDevInfo->uiPVRDevID) != PVRSRV_OK)
1802 {
1803 printk(KERN_ERR DRIVER_PREFIX
1804 ": %s: Device %u: PVR Device %u: Couldn't remove device from PVR Services\n", __FUNCTION__, psDevInfo->uiFBDevID, psDevInfo->uiPVRDevID);
1805 return OMAPLFB_FALSE;
1806 }
1808 OMAPLFBDeInitFBDev(psDevInfo);
1810 OMAPLFBSetDevInfoPtr(psDevInfo->uiFBDevID, NULL);
1813 OMAPLFBFreeKernelMem(psDevInfo);
1815 return OMAPLFB_TRUE;
1816 }
1818 OMAPLFB_ERROR OMAPLFBDeInit(void)
1819 {
1820 unsigned uiMaxFBDevIDPlusOne = OMAPLFBMaxFBDevIDPlusOne();
1821 unsigned i;
1822 OMAPLFB_BOOL bError = OMAPLFB_FALSE;
1824 for(i = 0; i < uiMaxFBDevIDPlusOne; i++)
1825 {
1826 OMAPLFB_DEVINFO *psDevInfo = OMAPLFBGetDevInfoPtr(i);
1828 if (psDevInfo != NULL)
1829 {
1830 bError |= !OMAPLFBDeInitDev(psDevInfo);
1831 }
1832 }
1834 return (bError) ? OMAPLFB_ERROR_INIT_FAILURE : OMAPLFB_OK;
1835 }