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>
38 #include "servicesext.h"
39 #include "kerneldisplay.h"
42 static void *gpvAnchor;
46 #define OMAPLFB_COMMAND_COUNT 1
48 static IMG_BOOL (*pfnGetPVRJTable)(struct PVRSRV_DC_DISP2SRV_KMJTABLE *);
50 #define OMAPLFB_PAGE_SIZE 4096
52 /* Greatest common divisor */
53 static unsigned long gcd(unsigned long a, unsigned long b)
63 while ((r = a % b) != 0) {
72 * Workout the smallest size that is aligned to both 4K (for the SGX)
73 * and line length (for the fbdev driver).
75 static unsigned int sgx_buffer_align(unsigned stride, unsigned size)
82 lcm = stride * OMAPLFB_PAGE_SIZE / gcd(stride,
85 return roundup(size, lcm);
88 static struct OMAPLFB_DEVINFO *GetAnchorPtr(void)
90 return (struct OMAPLFB_DEVINFO *)gpvAnchor;
93 static void SetAnchorPtr(struct OMAPLFB_DEVINFO *psDevInfo)
95 gpvAnchor = (void *) psDevInfo;
98 static int FrameBufferEvents(struct notifier_block *psNotif,
99 unsigned long event, void *data)
101 struct OMAPLFB_DEVINFO *psDevInfo;
102 struct OMAPLFB_SWAPCHAIN *psSwapChain;
103 struct fb_event *psFBEvent = (struct fb_event *)data;
105 if (event != FB_EVENT_BLANK)
108 psDevInfo = GetAnchorPtr();
109 psSwapChain = psDevInfo->psSwapChain;
110 psSwapChain->bBlanked = (*(int *)psFBEvent->data != 0);
115 static enum PVRSRV_ERROR EnableLFBEventNotification(struct OMAPLFB_DEVINFO
119 struct OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
121 memset(&psDevInfo->sLINNotifBlock, 0,
122 sizeof(psDevInfo->sLINNotifBlock));
124 psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;
126 psSwapChain->bBlanked = IMG_FALSE;
128 res = fb_register_client(&psDevInfo->sLINNotifBlock);
130 printk(KERN_WARNING DRIVER_PREFIX
131 ": fb_register_client failed (%d)", res);
133 return PVRSRV_ERROR_GENERIC;
139 static enum PVRSRV_ERROR DisableLFBEventNotification(struct OMAPLFB_DEVINFO
144 res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
146 printk(KERN_WARNING DRIVER_PREFIX
147 ": fb_unregister_client failed (%d)", res);
148 return PVRSRV_ERROR_GENERIC;
154 static enum PVRSRV_ERROR OpenDCDevice(u32 ui32DeviceID, void **phDevice,
155 struct PVRSRV_SYNC_DATA *psSystemBufferSyncData)
157 struct OMAPLFB_DEVINFO *psDevInfo;
159 PVR_UNREFERENCED_PARAMETER(ui32DeviceID);
161 psDevInfo = GetAnchorPtr();
163 psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
165 *phDevice = (void *) psDevInfo;
170 static enum PVRSRV_ERROR CloseDCDevice(void *hDevice)
172 PVR_UNREFERENCED_PARAMETER(hDevice);
177 static enum PVRSRV_ERROR EnumDCFormats(void *hDevice, u32 *pui32NumFormats,
178 struct DISPLAY_FORMAT *psFormat)
180 struct OMAPLFB_DEVINFO *psDevInfo;
182 if (!hDevice || !pui32NumFormats)
183 return PVRSRV_ERROR_INVALID_PARAMS;
185 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
187 *pui32NumFormats = 1;
190 psFormat[0] = psDevInfo->sDisplayFormat;
195 static enum PVRSRV_ERROR EnumDCDims(void *hDevice,
196 struct DISPLAY_FORMAT *psFormat,
197 u32 *pui32NumDims, struct DISPLAY_DIMS *psDim)
199 struct OMAPLFB_DEVINFO *psDevInfo;
201 if (!hDevice || !psFormat || !pui32NumDims)
202 return PVRSRV_ERROR_INVALID_PARAMS;
204 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
209 psDim[0] = psDevInfo->sDisplayDim;
214 static enum PVRSRV_ERROR GetDCSystemBuffer(void *hDevice, void **phBuffer)
216 struct OMAPLFB_DEVINFO *psDevInfo;
218 if (!hDevice || !phBuffer)
219 return PVRSRV_ERROR_INVALID_PARAMS;
221 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
223 *phBuffer = (void *) &psDevInfo->sSystemBuffer;
228 static enum PVRSRV_ERROR GetDCInfo(void *hDevice, struct DISPLAY_INFO *psDCInfo)
230 struct OMAPLFB_DEVINFO *psDevInfo;
232 if (!hDevice || !psDCInfo)
233 return PVRSRV_ERROR_INVALID_PARAMS;
235 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
237 *psDCInfo = psDevInfo->sDisplayInfo;
242 static enum PVRSRV_ERROR GetDCBufferAddr(void *hDevice, void *hBuffer,
243 struct IMG_SYS_PHYADDR **ppsSysAddr,
245 void __iomem **ppvCpuVAddr,
247 IMG_BOOL *pbIsContiguous)
249 struct OMAPLFB_DEVINFO *psDevInfo;
250 struct OMAPLFB_BUFFER *psSystemBuffer;
253 return PVRSRV_ERROR_INVALID_PARAMS;
254 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
257 return PVRSRV_ERROR_INVALID_PARAMS;
258 psSystemBuffer = (struct OMAPLFB_BUFFER *)hBuffer;
261 return PVRSRV_ERROR_INVALID_PARAMS;
263 *ppsSysAddr = &psSystemBuffer->sSysAddr;
266 return PVRSRV_ERROR_INVALID_PARAMS;
268 *pui32ByteSize = psDevInfo->sFBInfo.ui32BufferSize;
271 *ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
274 *phOSMapInfo = (void *) 0;
277 *pbIsContiguous = IMG_TRUE;
282 static enum PVRSRV_ERROR CreateDCSwapChain(void *hDevice, u32 ui32Flags,
283 struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
284 struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
286 struct PVRSRV_SYNC_DATA **ppsSyncData,
287 u32 ui32OEMFlags, void **phSwapChain,
288 u32 *pui32SwapChainID)
290 struct OMAPLFB_DEVINFO *psDevInfo;
291 struct OMAPLFB_SWAPCHAIN *psSwapChain;
292 struct OMAPLFB_BUFFER *psBuffer;
294 enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
296 PVR_UNREFERENCED_PARAMETER(ui32OEMFlags);
297 PVR_UNREFERENCED_PARAMETER(pui32SwapChainID);
299 if (!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib ||
300 !ppsSyncData || !phSwapChain)
301 return PVRSRV_ERROR_INVALID_PARAMS;
303 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
305 if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
306 return PVRSRV_ERROR_NOT_SUPPORTED;
308 if (psDevInfo->psSwapChain != NULL)
309 return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
311 if (ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
312 return PVRSRV_ERROR_TOOMANYBUFFERS;
314 if ((psDevInfo->sFBInfo.ui32RoundedBufferSize * ui32BufferCount) >
315 psDevInfo->sFBInfo.ui32FBSize)
316 return PVRSRV_ERROR_TOOMANYBUFFERS;
318 if (psDstSurfAttrib->pixelformat !=
319 psDevInfo->sDisplayFormat.pixelformat ||
320 psDstSurfAttrib->sDims.ui32ByteStride !=
321 psDevInfo->sDisplayDim.ui32ByteStride ||
322 psDstSurfAttrib->sDims.ui32Width !=
323 psDevInfo->sDisplayDim.ui32Width ||
324 psDstSurfAttrib->sDims.ui32Height !=
325 psDevInfo->sDisplayDim.ui32Height)
326 return PVRSRV_ERROR_INVALID_PARAMS;
328 if (psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat ||
329 psDstSurfAttrib->sDims.ui32ByteStride !=
330 psSrcSurfAttrib->sDims.ui32ByteStride ||
331 psDstSurfAttrib->sDims.ui32Width !=
332 psSrcSurfAttrib->sDims.ui32Width ||
333 psDstSurfAttrib->sDims.ui32Height !=
334 psSrcSurfAttrib->sDims.ui32Height)
335 return PVRSRV_ERROR_INVALID_PARAMS;
337 PVR_UNREFERENCED_PARAMETER(ui32Flags);
339 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)
340 OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_SWAPCHAIN));
342 return PVRSRV_ERROR_OUT_OF_MEMORY;
344 psBuffer = (struct OMAPLFB_BUFFER *)
345 OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_BUFFER) *
348 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
349 goto ErrorFreeSwapChain;
352 psSwapChain->ui32BufferCount = ui32BufferCount;
353 psSwapChain->psBuffer = psBuffer;
354 psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
356 for (i = 0; i < ui32BufferCount - 1; i++)
357 psBuffer[i].psNext = &psBuffer[i + 1];
359 psBuffer[i].psNext = &psBuffer[0];
361 for (i = 0; i < ui32BufferCount; i++) {
362 u32 ui32BufferOffset = i *
363 psDevInfo->sFBInfo.ui32RoundedBufferSize;
365 psBuffer[i].psSyncData = ppsSyncData[i];
367 psBuffer[i].sSysAddr.uiAddr =
368 psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
369 psBuffer[i].sCPUVAddr =
370 psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset;
373 psDevInfo->psSwapChain = psSwapChain;
375 eError = EnableLFBEventNotification(psDevInfo);
376 if (eError != PVRSRV_OK) {
378 ": Couldn't enable framebuffer event notification\n");
379 goto ErrorFreeBuffer;
382 *phSwapChain = (void *) psSwapChain;
387 OMAPLFBFreeKernelMem(psBuffer);
389 OMAPLFBFreeKernelMem(psSwapChain);
394 static enum PVRSRV_ERROR DestroyDCSwapChain(void *hDevice, void *hSwapChain)
396 struct OMAPLFB_DEVINFO *psDevInfo;
397 struct OMAPLFB_SWAPCHAIN *psSwapChain;
398 enum PVRSRV_ERROR eError;
400 if (!hDevice || !hSwapChain)
401 return PVRSRV_ERROR_INVALID_PARAMS;
403 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
404 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)hSwapChain;
405 if (psSwapChain != psDevInfo->psSwapChain)
406 return PVRSRV_ERROR_INVALID_PARAMS;
408 eError = DisableLFBEventNotification(psDevInfo);
409 if (eError != PVRSRV_OK)
410 printk(KERN_WARNING DRIVER_PREFIX
411 ": Couldn't disable framebuffer event notification\n");
413 psDevInfo->psSwapChain = NULL;
415 OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
416 OMAPLFBFreeKernelMem(psSwapChain);
421 static enum PVRSRV_ERROR SetDCDstRect(void *hDevice,
422 void *hSwapChain, struct IMG_RECT *psRect)
424 PVR_UNREFERENCED_PARAMETER(hDevice);
425 PVR_UNREFERENCED_PARAMETER(hSwapChain);
426 PVR_UNREFERENCED_PARAMETER(psRect);
428 return PVRSRV_ERROR_NOT_SUPPORTED;
431 static enum PVRSRV_ERROR SetDCSrcRect(void *hDevice,
432 void *hSwapChain, struct IMG_RECT *psRect)
434 PVR_UNREFERENCED_PARAMETER(hDevice);
435 PVR_UNREFERENCED_PARAMETER(hSwapChain);
436 PVR_UNREFERENCED_PARAMETER(psRect);
438 return PVRSRV_ERROR_NOT_SUPPORTED;
441 static enum PVRSRV_ERROR SetDCDstColourKey(void *hDevice, void *hSwapChain,
444 PVR_UNREFERENCED_PARAMETER(hDevice);
445 PVR_UNREFERENCED_PARAMETER(hSwapChain);
446 PVR_UNREFERENCED_PARAMETER(ui32CKColour);
448 return PVRSRV_ERROR_NOT_SUPPORTED;
451 static enum PVRSRV_ERROR SetDCSrcColourKey(void *hDevice, void *hSwapChain,
454 PVR_UNREFERENCED_PARAMETER(hDevice);
455 PVR_UNREFERENCED_PARAMETER(hSwapChain);
456 PVR_UNREFERENCED_PARAMETER(ui32CKColour);
458 return PVRSRV_ERROR_NOT_SUPPORTED;
461 static enum PVRSRV_ERROR GetDCBuffers(void *hDevice, void *hSwapChain,
462 u32 *pui32BufferCount, void **phBuffer)
464 struct OMAPLFB_DEVINFO *psDevInfo;
465 struct OMAPLFB_SWAPCHAIN *psSwapChain;
468 if (!hDevice || !hSwapChain || !pui32BufferCount || !phBuffer)
469 return PVRSRV_ERROR_INVALID_PARAMS;
471 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
472 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)hSwapChain;
473 if (psSwapChain != psDevInfo->psSwapChain)
474 return PVRSRV_ERROR_INVALID_PARAMS;
476 *pui32BufferCount = psSwapChain->ui32BufferCount;
478 for (i = 0; i < psSwapChain->ui32BufferCount; i++)
479 phBuffer[i] = (void *) &psSwapChain->psBuffer[i];
484 static IMG_BOOL ProcessFlip(void *hCmdCookie, u32 ui32DataSize, void *pvData)
486 struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
487 struct OMAPLFB_DEVINFO *psDevInfo;
488 struct OMAPLFB_BUFFER *psBuffer;
489 struct OMAPLFB_SWAPCHAIN *psSwapChain;
491 if (!hCmdCookie || !pvData)
494 psFlipCmd = (struct DISPLAYCLASS_FLIP_COMMAND *)pvData;
496 if (psFlipCmd == NULL
497 || sizeof(struct DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
500 psDevInfo = (struct OMAPLFB_DEVINFO *)psFlipCmd->hExtDevice;
502 psBuffer = (struct OMAPLFB_BUFFER *)psFlipCmd->hExtBuffer;
503 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)psFlipCmd->hExtSwapChain;
505 psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie, IMG_TRUE);
510 static void CalcSwapChainSize(struct OMAPLFB_DEVINFO *psDevInfo)
512 if (psDevInfo->sFBInfo.ui32RoundedBufferSize)
513 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers =
514 psDevInfo->sFBInfo.ui32FBSize /
515 psDevInfo->sFBInfo.ui32RoundedBufferSize;
517 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 0;
519 if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers == 0) {
520 psDevInfo->sDisplayInfo.ui32MaxSwapChains = 0;
521 psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 0;
523 psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1;
524 psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 3;
527 psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0;
529 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
530 ": Maximum number of swap chain buffers: %u\n",
531 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
534 static void SetDevinfo(struct OMAPLFB_DEVINFO *psDevInfo)
536 struct OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
537 struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
538 unsigned long FBSize;
540 FBSize = (psLINFBInfo->screen_size) != 0 ?
541 psLINFBInfo->screen_size : psLINFBInfo->fix.smem_len;
542 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
543 ": Framebuffer physical address: 0x%lx\n",
544 psLINFBInfo->fix.smem_start));
545 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
546 ": Framebuffer virtual address: 0x%lx\n",
547 (unsigned long)psLINFBInfo->screen_base));
548 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
549 ": Framebuffer size: %lu\n", FBSize));
550 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
551 ": Framebuffer virtual width: %u\n",
552 psLINFBInfo->var.xres_virtual));
553 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
554 ": Framebuffer virtual height: %u\n",
555 psLINFBInfo->var.yres_virtual));
556 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
557 ": Framebuffer width: %u\n", psLINFBInfo->var.xres));
558 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
559 ": Framebuffer height: %u\n", psLINFBInfo->var.yres));
560 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
561 ": Framebuffer stride: %u\n",
562 psLINFBInfo->fix.line_length));
564 psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
565 psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
567 psPVRFBInfo->ui32Width = psLINFBInfo->var.xres_virtual;
568 psPVRFBInfo->ui32ByteStride = psLINFBInfo->fix.line_length;
569 psPVRFBInfo->ui32FBSize = FBSize;
571 /* Try double buffering */
572 psPVRFBInfo->ui32Height = psLINFBInfo->var.yres_virtual >> 1;
573 psPVRFBInfo->ui32BufferSize = psPVRFBInfo->ui32ByteStride *
574 psPVRFBInfo->ui32Height;
575 psPVRFBInfo->ui32RoundedBufferSize =
576 sgx_buffer_align(psPVRFBInfo->ui32ByteStride,
577 psPVRFBInfo->ui32BufferSize);
579 /* If the buffers aren't aligned assume single buffering */
580 if (psPVRFBInfo->ui32BufferSize != psPVRFBInfo->ui32RoundedBufferSize) {
581 psPVRFBInfo->ui32Height = psLINFBInfo->var.yres_virtual;
582 psPVRFBInfo->ui32BufferSize = psPVRFBInfo->ui32ByteStride *
583 psPVRFBInfo->ui32Height;
584 psPVRFBInfo->ui32RoundedBufferSize =
585 sgx_buffer_align(psPVRFBInfo->ui32ByteStride,
586 psPVRFBInfo->ui32BufferSize);
589 CalcSwapChainSize(psDevInfo);
591 if (psLINFBInfo->var.bits_per_pixel == 16) {
592 if ((psLINFBInfo->var.red.length == 5) &&
593 (psLINFBInfo->var.green.length == 6) &&
594 (psLINFBInfo->var.blue.length == 5) &&
595 (psLINFBInfo->var.red.offset == 11) &&
596 (psLINFBInfo->var.green.offset == 5) &&
597 (psLINFBInfo->var.blue.offset == 0) &&
598 (psLINFBInfo->var.red.msb_right == 0))
599 psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
601 printk("Unknown FB format\n");
602 } else if (psLINFBInfo->var.bits_per_pixel == 32) {
603 if ((psLINFBInfo->var.transp.length == 8) &&
604 (psLINFBInfo->var.red.length == 8) &&
605 (psLINFBInfo->var.green.length == 8) &&
606 (psLINFBInfo->var.blue.length == 8) &&
607 (psLINFBInfo->var.transp.offset == 24) &&
608 (psLINFBInfo->var.red.offset == 16) &&
609 (psLINFBInfo->var.green.offset == 8) &&
610 (psLINFBInfo->var.blue.offset == 0) &&
611 (psLINFBInfo->var.red.msb_right == 0))
612 psPVRFBInfo->ePixelFormat =
613 PVRSRV_PIXEL_FORMAT_ARGB8888;
614 else if ((psLINFBInfo->var.transp.length == 0) &&
615 (psLINFBInfo->var.red.length == 8) &&
616 (psLINFBInfo->var.green.length == 8) &&
617 (psLINFBInfo->var.blue.length == 8) &&
618 (psLINFBInfo->var.transp.offset == 0) &&
619 (psLINFBInfo->var.red.offset == 16) &&
620 (psLINFBInfo->var.green.offset == 8) &&
621 (psLINFBInfo->var.blue.offset == 0) &&
622 (psLINFBInfo->var.red.msb_right == 0))
623 psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB888;
625 printk(KERN_ERR "Unknown FB format\n");
627 printk(KERN_ERR "Unknown FB format\n");
630 psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat;
631 psDevInfo->sDisplayDim.ui32Width = psDevInfo->sFBInfo.ui32Width;
632 psDevInfo->sDisplayDim.ui32Height = psDevInfo->sFBInfo.ui32Height;
633 psDevInfo->sDisplayDim.ui32ByteStride =
634 psDevInfo->sFBInfo.ui32ByteStride;
635 psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
636 psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
637 psDevInfo->sSystemBuffer.ui32BufferSize =
638 psDevInfo->sFBInfo.ui32RoundedBufferSize;
641 static struct FB_EVENTS {
642 struct notifier_block notif;
643 struct OMAPLFB_DEVINFO *psDevInfo;
646 static int FBEvents(struct notifier_block *psNotif,
647 unsigned long event, void *data)
649 if (event == FB_EVENT_MODE_CHANGE) {
650 struct FB_EVENTS *psEvents =
651 container_of(psNotif, struct FB_EVENTS, notif);
652 SetDevinfo(psEvents->psDevInfo);
657 static enum PVRSRV_ERROR InitDev(struct OMAPLFB_DEVINFO *psDevInfo)
659 struct fb_info *psLINFBInfo;
660 struct module *psLINFBOwner;
661 struct OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
662 enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
664 acquire_console_sem();
666 if (fb_idx < 0 || fb_idx >= num_registered_fb) {
667 eError = PVRSRV_ERROR_INVALID_DEVICE;
671 psLINFBInfo = registered_fb[fb_idx];
673 psLINFBOwner = psLINFBInfo->fbops->owner;
674 if (!try_module_get(psLINFBOwner)) {
675 printk(KERN_INFO DRIVER_PREFIX
676 ": Couldn't get framebuffer module\n");
681 if (psLINFBInfo->fbops->fb_open != NULL) {
684 res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
686 printk(KERN_INFO DRIVER_PREFIX
687 ": Couldn't open framebuffer: %d\n", res);
693 psDevInfo->psLINFBInfo = psLINFBInfo;
695 SetDevinfo(psDevInfo);
697 gFBEventsData.notif.notifier_call = FBEvents;
698 gFBEventsData.psDevInfo = psDevInfo;
699 fb_register_client(&gFBEventsData.notif);
701 psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
702 psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
708 module_put(psLINFBOwner);
710 release_console_sem();
714 static void DeInitDev(struct OMAPLFB_DEVINFO *psDevInfo)
716 struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
717 struct module *psLINFBOwner;
719 acquire_console_sem();
721 fb_unregister_client(&gFBEventsData.notif);
723 psLINFBOwner = psLINFBInfo->fbops->owner;
725 if (psLINFBInfo->fbops->fb_release != NULL)
726 (void)psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
728 module_put(psLINFBOwner);
730 release_console_sem();
733 enum PVRSRV_ERROR OMAPLFBInit(void)
735 struct OMAPLFB_DEVINFO *psDevInfo;
737 psDevInfo = GetAnchorPtr();
739 if (psDevInfo == NULL) {
740 IMG_BOOL (*pfnCmdProcList[OMAPLFB_COMMAND_COUNT])
741 (void *, u32, void *);
742 u32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
744 psDevInfo = (struct OMAPLFB_DEVINFO *)
745 OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_DEVINFO));
748 return PVRSRV_ERROR_OUT_OF_MEMORY;
750 memset(psDevInfo, 0, sizeof(struct OMAPLFB_DEVINFO));
752 SetAnchorPtr((void *) psDevInfo);
754 psDevInfo->ui32RefCount = 0;
756 if (InitDev(psDevInfo) != PVRSRV_OK)
757 return PVRSRV_ERROR_INIT_FAILURE;
759 if (OMAPLFBGetLibFuncAddr("PVRGetDisplayClassJTable",
760 &pfnGetPVRJTable) != PVRSRV_OK)
761 return PVRSRV_ERROR_INIT_FAILURE;
763 if (!(*pfnGetPVRJTable) (&psDevInfo->sPVRJTable))
764 return PVRSRV_ERROR_INIT_FAILURE;
766 psDevInfo->psSwapChain = NULL;
768 CalcSwapChainSize(psDevInfo);
770 strncpy(psDevInfo->sDisplayInfo.szDisplayName,
771 DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
773 psDevInfo->sDCJTable.ui32TableSize =
774 sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE);
775 psDevInfo->sDCJTable.owner = THIS_MODULE;
776 psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
777 psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
778 psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
779 psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
780 psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
781 psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
782 psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
783 psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
784 psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
785 psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
786 psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
787 psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
788 psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
789 psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
790 psDevInfo->sDCJTable.pfnSetDCState = NULL;
792 if (psDevInfo->sPVRJTable.
793 pfnPVRSRVRegisterDCDevice(&psDevInfo->sDCJTable,
794 &psDevInfo->ui32DeviceID) !=
796 return PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
798 pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
800 aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
801 aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
803 if (psDevInfo->sPVRJTable.
804 pfnPVRSRVRegisterCmdProcList(psDevInfo->ui32DeviceID,
807 OMAPLFB_COMMAND_COUNT) !=
809 printk(KERN_WARNING DRIVER_PREFIX
810 ": Can't register callback\n");
811 return PVRSRV_ERROR_CANT_REGISTER_CALLBACK;
816 psDevInfo->ui32RefCount++;
822 enum PVRSRV_ERROR OMAPLFBDeinit(void)
824 struct OMAPLFB_DEVINFO *psDevInfo, *psDevFirst;
826 psDevFirst = GetAnchorPtr();
827 psDevInfo = psDevFirst;
829 if (psDevInfo == NULL)
830 return PVRSRV_ERROR_GENERIC;
832 psDevInfo->ui32RefCount--;
834 if (psDevInfo->ui32RefCount == 0) {
835 struct PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable =
836 &psDevInfo->sPVRJTable;
837 if (psDevInfo->sPVRJTable.
838 pfnPVRSRVRemoveCmdProcList(psDevInfo->ui32DeviceID,
839 OMAPLFB_COMMAND_COUNT) !=
841 return PVRSRV_ERROR_GENERIC;
844 pfnPVRSRVRemoveDCDevice(psDevInfo->ui32DeviceID) !=
846 return PVRSRV_ERROR_GENERIC;
848 DeInitDev(psDevInfo);
850 OMAPLFBFreeKernelMem(psDevInfo);