1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
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.
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.
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.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
27 #include <linux/version.h>
28 #include <linux/kernel.h>
29 #include <linux/console.h>
31 #include <linux/module.h>
32 #include <linux/string.h>
33 #include <linux/notifier.h>
35 #include <asm/div64.h>
36 #include <video/sgx-util.h>
39 #include "servicesext.h"
40 #include "kerneldisplay.h"
43 static void *gpvAnchor;
47 #define OMAPLFB_COMMAND_COUNT 1
49 static IMG_BOOL (*pfnGetPVRJTable)(struct PVRSRV_DC_DISP2SRV_KMJTABLE *);
51 static struct OMAPLFB_DEVINFO *GetAnchorPtr(void)
53 return (struct OMAPLFB_DEVINFO *)gpvAnchor;
56 static void SetAnchorPtr(struct OMAPLFB_DEVINFO *psDevInfo)
58 gpvAnchor = (void *) psDevInfo;
61 static int FrameBufferEvents(struct notifier_block *psNotif,
62 unsigned long event, void *data)
64 struct OMAPLFB_DEVINFO *psDevInfo;
65 struct OMAPLFB_SWAPCHAIN *psSwapChain;
66 struct fb_event *psFBEvent = (struct fb_event *)data;
68 if (event != FB_EVENT_BLANK)
71 psDevInfo = GetAnchorPtr();
72 psSwapChain = psDevInfo->psSwapChain;
73 psSwapChain->bBlanked = (*(int *)psFBEvent->data != 0);
78 static enum PVRSRV_ERROR EnableLFBEventNotification(struct OMAPLFB_DEVINFO
82 struct OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
84 memset(&psDevInfo->sLINNotifBlock, 0,
85 sizeof(psDevInfo->sLINNotifBlock));
87 psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;
89 psSwapChain->bBlanked = IMG_FALSE;
91 res = fb_register_client(&psDevInfo->sLINNotifBlock);
93 printk(KERN_WARNING DRIVER_PREFIX
94 ": fb_register_client failed (%d)", res);
96 return PVRSRV_ERROR_GENERIC;
102 static enum PVRSRV_ERROR DisableLFBEventNotification(struct OMAPLFB_DEVINFO
107 res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
109 printk(KERN_WARNING DRIVER_PREFIX
110 ": fb_unregister_client failed (%d)", res);
111 return PVRSRV_ERROR_GENERIC;
117 static enum PVRSRV_ERROR OpenDCDevice(u32 ui32DeviceID, void **phDevice,
118 struct PVRSRV_SYNC_DATA *psSystemBufferSyncData)
120 struct OMAPLFB_DEVINFO *psDevInfo;
122 PVR_UNREFERENCED_PARAMETER(ui32DeviceID);
124 psDevInfo = GetAnchorPtr();
126 psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
128 *phDevice = (void *) psDevInfo;
133 static enum PVRSRV_ERROR CloseDCDevice(void *hDevice)
135 PVR_UNREFERENCED_PARAMETER(hDevice);
140 static enum PVRSRV_ERROR EnumDCFormats(void *hDevice, u32 *pui32NumFormats,
141 struct DISPLAY_FORMAT *psFormat)
143 struct OMAPLFB_DEVINFO *psDevInfo;
145 if (!hDevice || !pui32NumFormats)
146 return PVRSRV_ERROR_INVALID_PARAMS;
148 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
150 *pui32NumFormats = 1;
153 psFormat[0] = psDevInfo->sDisplayFormat;
158 static enum PVRSRV_ERROR EnumDCDims(void *hDevice,
159 struct DISPLAY_FORMAT *psFormat,
160 u32 *pui32NumDims, struct DISPLAY_DIMS *psDim)
162 struct OMAPLFB_DEVINFO *psDevInfo;
164 if (!hDevice || !psFormat || !pui32NumDims)
165 return PVRSRV_ERROR_INVALID_PARAMS;
167 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
172 psDim[0] = psDevInfo->sDisplayDim;
177 static enum PVRSRV_ERROR GetDCSystemBuffer(void *hDevice, void **phBuffer)
179 struct OMAPLFB_DEVINFO *psDevInfo;
181 if (!hDevice || !phBuffer)
182 return PVRSRV_ERROR_INVALID_PARAMS;
184 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
186 *phBuffer = (void *) &psDevInfo->sSystemBuffer;
191 static enum PVRSRV_ERROR GetDCInfo(void *hDevice, struct DISPLAY_INFO *psDCInfo)
193 struct OMAPLFB_DEVINFO *psDevInfo;
195 if (!hDevice || !psDCInfo)
196 return PVRSRV_ERROR_INVALID_PARAMS;
198 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
200 *psDCInfo = psDevInfo->sDisplayInfo;
205 static enum PVRSRV_ERROR GetDCBufferAddr(void *hDevice, void *hBuffer,
206 struct IMG_SYS_PHYADDR **ppsSysAddr,
208 void __iomem **ppvCpuVAddr,
210 IMG_BOOL *pbIsContiguous)
212 struct OMAPLFB_DEVINFO *psDevInfo;
213 struct OMAPLFB_BUFFER *psSystemBuffer;
216 return PVRSRV_ERROR_INVALID_PARAMS;
217 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
220 return PVRSRV_ERROR_INVALID_PARAMS;
221 psSystemBuffer = (struct OMAPLFB_BUFFER *)hBuffer;
224 return PVRSRV_ERROR_INVALID_PARAMS;
226 *ppsSysAddr = &psSystemBuffer->sSysAddr;
229 return PVRSRV_ERROR_INVALID_PARAMS;
231 *pui32ByteSize = psDevInfo->sFBInfo.ui32BufferSize;
234 *ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
237 *phOSMapInfo = (void *) 0;
240 *pbIsContiguous = IMG_TRUE;
245 static enum PVRSRV_ERROR CreateDCSwapChain(void *hDevice, u32 ui32Flags,
246 struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
247 struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
249 struct PVRSRV_SYNC_DATA **ppsSyncData,
250 u32 ui32OEMFlags, void **phSwapChain,
251 u32 *pui32SwapChainID)
253 struct OMAPLFB_DEVINFO *psDevInfo;
254 struct OMAPLFB_SWAPCHAIN *psSwapChain;
255 struct OMAPLFB_BUFFER *psBuffer;
257 enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
259 PVR_UNREFERENCED_PARAMETER(ui32OEMFlags);
260 PVR_UNREFERENCED_PARAMETER(pui32SwapChainID);
262 if (!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib ||
263 !ppsSyncData || !phSwapChain)
264 return PVRSRV_ERROR_INVALID_PARAMS;
266 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
268 if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
269 return PVRSRV_ERROR_NOT_SUPPORTED;
271 if (psDevInfo->psSwapChain != NULL)
272 return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
274 if (ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
275 return PVRSRV_ERROR_TOOMANYBUFFERS;
277 if ((psDevInfo->sFBInfo.ui32RoundedBufferSize * ui32BufferCount) >
278 psDevInfo->sFBInfo.ui32FBSize)
279 return PVRSRV_ERROR_TOOMANYBUFFERS;
281 if (psDstSurfAttrib->pixelformat !=
282 psDevInfo->sDisplayFormat.pixelformat ||
283 psDstSurfAttrib->sDims.ui32ByteStride !=
284 psDevInfo->sDisplayDim.ui32ByteStride ||
285 psDstSurfAttrib->sDims.ui32Width !=
286 psDevInfo->sDisplayDim.ui32Width ||
287 psDstSurfAttrib->sDims.ui32Height !=
288 psDevInfo->sDisplayDim.ui32Height)
289 return PVRSRV_ERROR_INVALID_PARAMS;
291 if (psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat ||
292 psDstSurfAttrib->sDims.ui32ByteStride !=
293 psSrcSurfAttrib->sDims.ui32ByteStride ||
294 psDstSurfAttrib->sDims.ui32Width !=
295 psSrcSurfAttrib->sDims.ui32Width ||
296 psDstSurfAttrib->sDims.ui32Height !=
297 psSrcSurfAttrib->sDims.ui32Height)
298 return PVRSRV_ERROR_INVALID_PARAMS;
300 PVR_UNREFERENCED_PARAMETER(ui32Flags);
302 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)
303 OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_SWAPCHAIN));
305 return PVRSRV_ERROR_OUT_OF_MEMORY;
307 psBuffer = (struct OMAPLFB_BUFFER *)
308 OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_BUFFER) *
311 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
312 goto ErrorFreeSwapChain;
315 psSwapChain->ui32BufferCount = ui32BufferCount;
316 psSwapChain->psBuffer = psBuffer;
317 psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
319 for (i = 0; i < ui32BufferCount - 1; i++)
320 psBuffer[i].psNext = &psBuffer[i + 1];
322 psBuffer[i].psNext = &psBuffer[0];
324 for (i = 0; i < ui32BufferCount; i++) {
325 u32 ui32BufferOffset = i *
326 psDevInfo->sFBInfo.ui32RoundedBufferSize;
328 psBuffer[i].psSyncData = ppsSyncData[i];
330 psBuffer[i].sSysAddr.uiAddr =
331 psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
332 psBuffer[i].sCPUVAddr =
333 psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset;
336 psDevInfo->psSwapChain = psSwapChain;
338 eError = EnableLFBEventNotification(psDevInfo);
339 if (eError != PVRSRV_OK) {
341 ": Couldn't enable framebuffer event notification\n");
342 goto ErrorFreeBuffer;
345 *phSwapChain = (void *) psSwapChain;
350 OMAPLFBFreeKernelMem(psBuffer);
352 OMAPLFBFreeKernelMem(psSwapChain);
357 static enum PVRSRV_ERROR DestroyDCSwapChain(void *hDevice, void *hSwapChain)
359 struct OMAPLFB_DEVINFO *psDevInfo;
360 struct OMAPLFB_SWAPCHAIN *psSwapChain;
361 enum PVRSRV_ERROR eError;
363 if (!hDevice || !hSwapChain)
364 return PVRSRV_ERROR_INVALID_PARAMS;
366 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
367 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)hSwapChain;
368 if (psSwapChain != psDevInfo->psSwapChain)
369 return PVRSRV_ERROR_INVALID_PARAMS;
371 eError = DisableLFBEventNotification(psDevInfo);
372 if (eError != PVRSRV_OK)
373 printk(KERN_WARNING DRIVER_PREFIX
374 ": Couldn't disable framebuffer event notification\n");
376 psDevInfo->psSwapChain = NULL;
378 OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
379 OMAPLFBFreeKernelMem(psSwapChain);
384 static enum PVRSRV_ERROR SetDCDstRect(void *hDevice,
385 void *hSwapChain, struct IMG_RECT *psRect)
387 PVR_UNREFERENCED_PARAMETER(hDevice);
388 PVR_UNREFERENCED_PARAMETER(hSwapChain);
389 PVR_UNREFERENCED_PARAMETER(psRect);
391 return PVRSRV_ERROR_NOT_SUPPORTED;
394 static enum PVRSRV_ERROR SetDCSrcRect(void *hDevice,
395 void *hSwapChain, struct IMG_RECT *psRect)
397 PVR_UNREFERENCED_PARAMETER(hDevice);
398 PVR_UNREFERENCED_PARAMETER(hSwapChain);
399 PVR_UNREFERENCED_PARAMETER(psRect);
401 return PVRSRV_ERROR_NOT_SUPPORTED;
404 static enum PVRSRV_ERROR SetDCDstColourKey(void *hDevice, void *hSwapChain,
407 PVR_UNREFERENCED_PARAMETER(hDevice);
408 PVR_UNREFERENCED_PARAMETER(hSwapChain);
409 PVR_UNREFERENCED_PARAMETER(ui32CKColour);
411 return PVRSRV_ERROR_NOT_SUPPORTED;
414 static enum PVRSRV_ERROR SetDCSrcColourKey(void *hDevice, void *hSwapChain,
417 PVR_UNREFERENCED_PARAMETER(hDevice);
418 PVR_UNREFERENCED_PARAMETER(hSwapChain);
419 PVR_UNREFERENCED_PARAMETER(ui32CKColour);
421 return PVRSRV_ERROR_NOT_SUPPORTED;
424 static enum PVRSRV_ERROR GetDCBuffers(void *hDevice, void *hSwapChain,
425 u32 *pui32BufferCount, void **phBuffer)
427 struct OMAPLFB_DEVINFO *psDevInfo;
428 struct OMAPLFB_SWAPCHAIN *psSwapChain;
431 if (!hDevice || !hSwapChain || !pui32BufferCount || !phBuffer)
432 return PVRSRV_ERROR_INVALID_PARAMS;
434 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
435 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)hSwapChain;
436 if (psSwapChain != psDevInfo->psSwapChain)
437 return PVRSRV_ERROR_INVALID_PARAMS;
439 *pui32BufferCount = psSwapChain->ui32BufferCount;
441 for (i = 0; i < psSwapChain->ui32BufferCount; i++)
442 phBuffer[i] = (void *) &psSwapChain->psBuffer[i];
447 static IMG_BOOL ProcessFlip(void *hCmdCookie, u32 ui32DataSize, void *pvData)
449 struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
450 struct OMAPLFB_DEVINFO *psDevInfo;
451 struct OMAPLFB_BUFFER *psBuffer;
452 struct OMAPLFB_SWAPCHAIN *psSwapChain;
454 if (!hCmdCookie || !pvData)
457 psFlipCmd = (struct DISPLAYCLASS_FLIP_COMMAND *)pvData;
459 if (psFlipCmd == NULL
460 || sizeof(struct DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
463 psDevInfo = (struct OMAPLFB_DEVINFO *)psFlipCmd->hExtDevice;
465 psBuffer = (struct OMAPLFB_BUFFER *)psFlipCmd->hExtBuffer;
466 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)psFlipCmd->hExtSwapChain;
468 psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie, IMG_TRUE);
473 static void CalcSwapChainSize(struct OMAPLFB_DEVINFO *psDevInfo)
475 if (psDevInfo->sFBInfo.ui32RoundedBufferSize)
476 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers =
477 psDevInfo->sFBInfo.ui32FBSize /
478 psDevInfo->sFBInfo.ui32RoundedBufferSize;
480 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 0;
482 if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers == 0) {
483 psDevInfo->sDisplayInfo.ui32MaxSwapChains = 0;
484 psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 0;
486 psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1;
487 psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 3;
490 psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0;
492 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
493 ": Maximum number of swap chain buffers: %u\n",
494 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
497 static void SetDevinfo(struct OMAPLFB_DEVINFO *psDevInfo)
499 struct OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
500 struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
501 unsigned long FBSize;
503 FBSize = (psLINFBInfo->screen_size) != 0 ?
504 psLINFBInfo->screen_size : psLINFBInfo->fix.smem_len;
505 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
506 ": Framebuffer physical address: 0x%lx\n",
507 psLINFBInfo->fix.smem_start));
508 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
509 ": Framebuffer virtual address: 0x%lx\n",
510 (unsigned long)psLINFBInfo->screen_base));
511 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
512 ": Framebuffer size: %lu\n", FBSize));
513 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
514 ": Framebuffer virtual width: %u\n",
515 psLINFBInfo->var.xres_virtual));
516 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
517 ": Framebuffer virtual height: %u\n",
518 psLINFBInfo->var.yres_virtual));
519 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
520 ": Framebuffer width: %u\n", psLINFBInfo->var.xres));
521 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
522 ": Framebuffer height: %u\n", psLINFBInfo->var.yres));
523 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
524 ": Framebuffer stride: %u\n",
525 psLINFBInfo->fix.line_length));
527 psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
528 psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
530 psPVRFBInfo->ui32Width = psLINFBInfo->var.xres_virtual;
531 psPVRFBInfo->ui32ByteStride = psLINFBInfo->fix.line_length;
532 psPVRFBInfo->ui32FBSize = FBSize;
534 /* Try double buffering */
535 psPVRFBInfo->ui32Height = psLINFBInfo->var.yres_virtual >> 1;
536 psPVRFBInfo->ui32BufferSize = psPVRFBInfo->ui32ByteStride *
537 psPVRFBInfo->ui32Height;
538 psPVRFBInfo->ui32RoundedBufferSize =
539 sgx_buffer_align(psPVRFBInfo->ui32ByteStride,
540 psPVRFBInfo->ui32BufferSize);
542 /* If the buffers aren't aligned assume single buffering */
543 if (psPVRFBInfo->ui32BufferSize != psPVRFBInfo->ui32RoundedBufferSize) {
544 psPVRFBInfo->ui32Height = psLINFBInfo->var.yres_virtual;
545 psPVRFBInfo->ui32BufferSize = psPVRFBInfo->ui32ByteStride *
546 psPVRFBInfo->ui32Height;
547 psPVRFBInfo->ui32RoundedBufferSize =
548 sgx_buffer_align(psPVRFBInfo->ui32ByteStride,
549 psPVRFBInfo->ui32BufferSize);
552 CalcSwapChainSize(psDevInfo);
554 if (psLINFBInfo->var.bits_per_pixel == 16) {
555 if ((psLINFBInfo->var.red.length == 5) &&
556 (psLINFBInfo->var.green.length == 6) &&
557 (psLINFBInfo->var.blue.length == 5) &&
558 (psLINFBInfo->var.red.offset == 11) &&
559 (psLINFBInfo->var.green.offset == 5) &&
560 (psLINFBInfo->var.blue.offset == 0) &&
561 (psLINFBInfo->var.red.msb_right == 0))
562 psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
564 printk("Unknown FB format\n");
565 } else if (psLINFBInfo->var.bits_per_pixel == 32) {
566 if ((psLINFBInfo->var.transp.length == 8) &&
567 (psLINFBInfo->var.red.length == 8) &&
568 (psLINFBInfo->var.green.length == 8) &&
569 (psLINFBInfo->var.blue.length == 8) &&
570 (psLINFBInfo->var.transp.offset == 24) &&
571 (psLINFBInfo->var.red.offset == 16) &&
572 (psLINFBInfo->var.green.offset == 8) &&
573 (psLINFBInfo->var.blue.offset == 0) &&
574 (psLINFBInfo->var.red.msb_right == 0))
575 psPVRFBInfo->ePixelFormat =
576 PVRSRV_PIXEL_FORMAT_ARGB8888;
577 else if ((psLINFBInfo->var.transp.length == 0) &&
578 (psLINFBInfo->var.red.length == 8) &&
579 (psLINFBInfo->var.green.length == 8) &&
580 (psLINFBInfo->var.blue.length == 8) &&
581 (psLINFBInfo->var.transp.offset == 0) &&
582 (psLINFBInfo->var.red.offset == 16) &&
583 (psLINFBInfo->var.green.offset == 8) &&
584 (psLINFBInfo->var.blue.offset == 0) &&
585 (psLINFBInfo->var.red.msb_right == 0))
586 psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB888;
588 printk(KERN_ERR "Unknown FB format\n");
590 printk(KERN_ERR "Unknown FB format\n");
593 psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat;
594 psDevInfo->sDisplayDim.ui32Width = psDevInfo->sFBInfo.ui32Width;
595 psDevInfo->sDisplayDim.ui32Height = psDevInfo->sFBInfo.ui32Height;
596 psDevInfo->sDisplayDim.ui32ByteStride =
597 psDevInfo->sFBInfo.ui32ByteStride;
598 psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
599 psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
600 psDevInfo->sSystemBuffer.ui32BufferSize =
601 psDevInfo->sFBInfo.ui32RoundedBufferSize;
604 static struct FB_EVENTS {
605 struct notifier_block notif;
606 struct OMAPLFB_DEVINFO *psDevInfo;
609 static int FBEvents(struct notifier_block *psNotif,
610 unsigned long event, void *data)
612 if (event == FB_EVENT_MODE_CHANGE) {
613 struct FB_EVENTS *psEvents =
614 container_of(psNotif, struct FB_EVENTS, notif);
615 SetDevinfo(psEvents->psDevInfo);
620 static enum PVRSRV_ERROR InitDev(struct OMAPLFB_DEVINFO *psDevInfo)
622 struct fb_info *psLINFBInfo;
623 struct module *psLINFBOwner;
624 struct OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
625 enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
627 acquire_console_sem();
629 if (fb_idx < 0 || fb_idx >= num_registered_fb) {
630 eError = PVRSRV_ERROR_INVALID_DEVICE;
634 psLINFBInfo = registered_fb[fb_idx];
636 psLINFBOwner = psLINFBInfo->fbops->owner;
637 if (!try_module_get(psLINFBOwner)) {
638 printk(KERN_INFO DRIVER_PREFIX
639 ": Couldn't get framebuffer module\n");
644 if (psLINFBInfo->fbops->fb_open != NULL) {
647 res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
649 printk(KERN_INFO DRIVER_PREFIX
650 ": Couldn't open framebuffer: %d\n", res);
656 psDevInfo->psLINFBInfo = psLINFBInfo;
658 SetDevinfo(psDevInfo);
660 gFBEventsData.notif.notifier_call = FBEvents;
661 gFBEventsData.psDevInfo = psDevInfo;
662 fb_register_client(&gFBEventsData.notif);
664 psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
665 psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
671 module_put(psLINFBOwner);
673 release_console_sem();
677 static void DeInitDev(struct OMAPLFB_DEVINFO *psDevInfo)
679 struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
680 struct module *psLINFBOwner;
682 acquire_console_sem();
684 fb_unregister_client(&gFBEventsData.notif);
686 psLINFBOwner = psLINFBInfo->fbops->owner;
688 if (psLINFBInfo->fbops->fb_release != NULL)
689 (void)psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
691 module_put(psLINFBOwner);
693 release_console_sem();
696 enum PVRSRV_ERROR OMAPLFBInit(void)
698 struct OMAPLFB_DEVINFO *psDevInfo;
700 psDevInfo = GetAnchorPtr();
702 if (psDevInfo == NULL) {
703 IMG_BOOL (*pfnCmdProcList[OMAPLFB_COMMAND_COUNT])
704 (void *, u32, void *);
705 u32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
707 psDevInfo = (struct OMAPLFB_DEVINFO *)
708 OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_DEVINFO));
711 return PVRSRV_ERROR_OUT_OF_MEMORY;
713 memset(psDevInfo, 0, sizeof(struct OMAPLFB_DEVINFO));
715 SetAnchorPtr((void *) psDevInfo);
717 psDevInfo->ui32RefCount = 0;
719 if (InitDev(psDevInfo) != PVRSRV_OK)
720 return PVRSRV_ERROR_INIT_FAILURE;
722 if (OMAPLFBGetLibFuncAddr("PVRGetDisplayClassJTable",
723 &pfnGetPVRJTable) != PVRSRV_OK)
724 return PVRSRV_ERROR_INIT_FAILURE;
726 if (!(*pfnGetPVRJTable) (&psDevInfo->sPVRJTable))
727 return PVRSRV_ERROR_INIT_FAILURE;
729 psDevInfo->psSwapChain = NULL;
731 CalcSwapChainSize(psDevInfo);
733 strncpy(psDevInfo->sDisplayInfo.szDisplayName,
734 DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
736 psDevInfo->sDCJTable.ui32TableSize =
737 sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE);
738 psDevInfo->sDCJTable.owner = THIS_MODULE;
739 psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
740 psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
741 psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
742 psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
743 psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
744 psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
745 psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
746 psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
747 psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
748 psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
749 psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
750 psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
751 psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
752 psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
753 psDevInfo->sDCJTable.pfnSetDCState = NULL;
755 if (psDevInfo->sPVRJTable.
756 pfnPVRSRVRegisterDCDevice(&psDevInfo->sDCJTable,
757 &psDevInfo->ui32DeviceID) !=
759 return PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
761 pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
763 aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
764 aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
766 if (psDevInfo->sPVRJTable.
767 pfnPVRSRVRegisterCmdProcList(psDevInfo->ui32DeviceID,
770 OMAPLFB_COMMAND_COUNT) !=
772 printk(KERN_WARNING DRIVER_PREFIX
773 ": Can't register callback\n");
774 return PVRSRV_ERROR_CANT_REGISTER_CALLBACK;
779 psDevInfo->ui32RefCount++;
785 enum PVRSRV_ERROR OMAPLFBDeinit(void)
787 struct OMAPLFB_DEVINFO *psDevInfo, *psDevFirst;
789 psDevFirst = GetAnchorPtr();
790 psDevInfo = psDevFirst;
792 if (psDevInfo == NULL)
793 return PVRSRV_ERROR_GENERIC;
795 psDevInfo->ui32RefCount--;
797 if (psDevInfo->ui32RefCount == 0) {
798 struct PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable =
799 &psDevInfo->sPVRJTable;
800 if (psDevInfo->sPVRJTable.
801 pfnPVRSRVRemoveCmdProcList(psDevInfo->ui32DeviceID,
802 OMAPLFB_COMMAND_COUNT) !=
804 return PVRSRV_ERROR_GENERIC;
807 pfnPVRSRVRemoveDCDevice(psDevInfo->ui32DeviceID) !=
809 return PVRSRV_ERROR_GENERIC;
811 DeInitDev(psDevInfo);
813 OMAPLFBFreeKernelMem(psDevInfo);