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 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)
43 #define acquire_console_sem console_lock
44 #define release_console_sem console_unlock
47 static void *gpvAnchor;
51 #define OMAPLFB_COMMAND_COUNT 1
53 static IMG_BOOL (*pfnGetPVRJTable)(struct PVRSRV_DC_DISP2SRV_KMJTABLE *);
55 #define OMAPLFB_PAGE_SIZE 4096
57 /* Greatest common divisor */
58 static unsigned long gcd(unsigned long a, unsigned long b)
68 while ((r = a % b) != 0) {
77 * Workout the smallest size that is aligned to both 4K (for the SGX)
78 * and line length (for the fbdev driver).
80 static unsigned int sgx_buffer_align(unsigned stride, unsigned size)
87 lcm = stride * OMAPLFB_PAGE_SIZE / gcd(stride,
90 return roundup(size, lcm);
93 static struct OMAPLFB_DEVINFO *GetAnchorPtr(void)
95 return (struct OMAPLFB_DEVINFO *)gpvAnchor;
98 static void SetAnchorPtr(struct OMAPLFB_DEVINFO *psDevInfo)
100 gpvAnchor = (void *) psDevInfo;
103 static int FrameBufferEvents(struct notifier_block *psNotif,
104 unsigned long event, void *data)
106 struct OMAPLFB_DEVINFO *psDevInfo;
107 struct OMAPLFB_SWAPCHAIN *psSwapChain;
108 struct fb_event *psFBEvent = (struct fb_event *)data;
110 if (event != FB_EVENT_BLANK)
113 psDevInfo = GetAnchorPtr();
114 psSwapChain = psDevInfo->psSwapChain;
115 psSwapChain->bBlanked = (*(int *)psFBEvent->data != 0);
120 static enum PVRSRV_ERROR EnableLFBEventNotification(struct OMAPLFB_DEVINFO
124 struct OMAPLFB_SWAPCHAIN *psSwapChain = psDevInfo->psSwapChain;
126 memset(&psDevInfo->sLINNotifBlock, 0,
127 sizeof(psDevInfo->sLINNotifBlock));
129 psDevInfo->sLINNotifBlock.notifier_call = FrameBufferEvents;
131 psSwapChain->bBlanked = IMG_FALSE;
133 res = fb_register_client(&psDevInfo->sLINNotifBlock);
135 printk(KERN_WARNING DRIVER_PREFIX
136 ": fb_register_client failed (%d)", res);
138 return PVRSRV_ERROR_GENERIC;
144 static enum PVRSRV_ERROR DisableLFBEventNotification(struct OMAPLFB_DEVINFO
149 res = fb_unregister_client(&psDevInfo->sLINNotifBlock);
151 printk(KERN_WARNING DRIVER_PREFIX
152 ": fb_unregister_client failed (%d)", res);
153 return PVRSRV_ERROR_GENERIC;
159 static enum PVRSRV_ERROR OpenDCDevice(u32 ui32DeviceID, void **phDevice,
160 struct PVRSRV_SYNC_DATA *psSystemBufferSyncData)
162 struct OMAPLFB_DEVINFO *psDevInfo;
164 PVR_UNREFERENCED_PARAMETER(ui32DeviceID);
166 psDevInfo = GetAnchorPtr();
168 psDevInfo->sSystemBuffer.psSyncData = psSystemBufferSyncData;
170 *phDevice = (void *) psDevInfo;
175 static enum PVRSRV_ERROR CloseDCDevice(void *hDevice)
177 PVR_UNREFERENCED_PARAMETER(hDevice);
182 static enum PVRSRV_ERROR EnumDCFormats(void *hDevice, u32 *pui32NumFormats,
183 struct DISPLAY_FORMAT *psFormat)
185 struct OMAPLFB_DEVINFO *psDevInfo;
187 if (!hDevice || !pui32NumFormats)
188 return PVRSRV_ERROR_INVALID_PARAMS;
190 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
192 *pui32NumFormats = 1;
195 psFormat[0] = psDevInfo->sDisplayFormat;
200 static enum PVRSRV_ERROR EnumDCDims(void *hDevice,
201 struct DISPLAY_FORMAT *psFormat,
202 u32 *pui32NumDims, struct DISPLAY_DIMS *psDim)
204 struct OMAPLFB_DEVINFO *psDevInfo;
206 if (!hDevice || !psFormat || !pui32NumDims)
207 return PVRSRV_ERROR_INVALID_PARAMS;
209 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
214 psDim[0] = psDevInfo->sDisplayDim;
219 static enum PVRSRV_ERROR GetDCSystemBuffer(void *hDevice, void **phBuffer)
221 struct OMAPLFB_DEVINFO *psDevInfo;
223 if (!hDevice || !phBuffer)
224 return PVRSRV_ERROR_INVALID_PARAMS;
226 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
228 *phBuffer = (void *) &psDevInfo->sSystemBuffer;
233 static enum PVRSRV_ERROR GetDCInfo(void *hDevice, struct DISPLAY_INFO *psDCInfo)
235 struct OMAPLFB_DEVINFO *psDevInfo;
237 if (!hDevice || !psDCInfo)
238 return PVRSRV_ERROR_INVALID_PARAMS;
240 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
242 *psDCInfo = psDevInfo->sDisplayInfo;
247 static enum PVRSRV_ERROR GetDCBufferAddr(void *hDevice, void *hBuffer,
248 struct IMG_SYS_PHYADDR **ppsSysAddr,
250 void __iomem **ppvCpuVAddr,
252 IMG_BOOL *pbIsContiguous)
254 struct OMAPLFB_DEVINFO *psDevInfo;
255 struct OMAPLFB_BUFFER *psSystemBuffer;
258 return PVRSRV_ERROR_INVALID_PARAMS;
259 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
262 return PVRSRV_ERROR_INVALID_PARAMS;
263 psSystemBuffer = (struct OMAPLFB_BUFFER *)hBuffer;
266 return PVRSRV_ERROR_INVALID_PARAMS;
268 *ppsSysAddr = &psSystemBuffer->sSysAddr;
271 return PVRSRV_ERROR_INVALID_PARAMS;
273 *pui32ByteSize = psDevInfo->sFBInfo.ui32BufferSize;
276 *ppvCpuVAddr = psSystemBuffer->sCPUVAddr;
279 *phOSMapInfo = (void *) 0;
282 *pbIsContiguous = IMG_TRUE;
287 static enum PVRSRV_ERROR CreateDCSwapChain(void *hDevice, u32 ui32Flags,
288 struct DISPLAY_SURF_ATTRIBUTES *psDstSurfAttrib,
289 struct DISPLAY_SURF_ATTRIBUTES *psSrcSurfAttrib,
291 struct PVRSRV_SYNC_DATA **ppsSyncData,
292 u32 ui32OEMFlags, void **phSwapChain,
293 u32 *pui32SwapChainID)
295 struct OMAPLFB_DEVINFO *psDevInfo;
296 struct OMAPLFB_SWAPCHAIN *psSwapChain;
297 struct OMAPLFB_BUFFER *psBuffer;
299 enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
301 PVR_UNREFERENCED_PARAMETER(ui32OEMFlags);
302 PVR_UNREFERENCED_PARAMETER(pui32SwapChainID);
304 if (!hDevice || !psDstSurfAttrib || !psSrcSurfAttrib ||
305 !ppsSyncData || !phSwapChain)
306 return PVRSRV_ERROR_INVALID_PARAMS;
308 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
310 if (psDevInfo->sDisplayInfo.ui32MaxSwapChains == 0)
311 return PVRSRV_ERROR_NOT_SUPPORTED;
313 if (psDevInfo->psSwapChain != NULL)
314 return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
316 if (ui32BufferCount > psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers)
317 return PVRSRV_ERROR_TOOMANYBUFFERS;
319 if ((psDevInfo->sFBInfo.ui32RoundedBufferSize * ui32BufferCount) >
320 psDevInfo->sFBInfo.ui32FBSize)
321 return PVRSRV_ERROR_TOOMANYBUFFERS;
323 if (psDstSurfAttrib->pixelformat !=
324 psDevInfo->sDisplayFormat.pixelformat ||
325 psDstSurfAttrib->sDims.ui32ByteStride !=
326 psDevInfo->sDisplayDim.ui32ByteStride ||
327 psDstSurfAttrib->sDims.ui32Width !=
328 psDevInfo->sDisplayDim.ui32Width ||
329 psDstSurfAttrib->sDims.ui32Height !=
330 psDevInfo->sDisplayDim.ui32Height)
331 return PVRSRV_ERROR_INVALID_PARAMS;
333 if (psDstSurfAttrib->pixelformat != psSrcSurfAttrib->pixelformat ||
334 psDstSurfAttrib->sDims.ui32ByteStride !=
335 psSrcSurfAttrib->sDims.ui32ByteStride ||
336 psDstSurfAttrib->sDims.ui32Width !=
337 psSrcSurfAttrib->sDims.ui32Width ||
338 psDstSurfAttrib->sDims.ui32Height !=
339 psSrcSurfAttrib->sDims.ui32Height)
340 return PVRSRV_ERROR_INVALID_PARAMS;
342 PVR_UNREFERENCED_PARAMETER(ui32Flags);
344 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)
345 OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_SWAPCHAIN));
347 return PVRSRV_ERROR_OUT_OF_MEMORY;
349 psBuffer = (struct OMAPLFB_BUFFER *)
350 OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_BUFFER) *
353 eError = PVRSRV_ERROR_OUT_OF_MEMORY;
354 goto ErrorFreeSwapChain;
357 psSwapChain->ui32BufferCount = ui32BufferCount;
358 psSwapChain->psBuffer = psBuffer;
359 psSwapChain->psPVRJTable = &psDevInfo->sPVRJTable;
361 for (i = 0; i < ui32BufferCount - 1; i++)
362 psBuffer[i].psNext = &psBuffer[i + 1];
364 psBuffer[i].psNext = &psBuffer[0];
366 for (i = 0; i < ui32BufferCount; i++) {
367 u32 ui32BufferOffset = i *
368 psDevInfo->sFBInfo.ui32RoundedBufferSize;
370 psBuffer[i].psSyncData = ppsSyncData[i];
372 psBuffer[i].sSysAddr.uiAddr =
373 psDevInfo->sFBInfo.sSysAddr.uiAddr + ui32BufferOffset;
374 psBuffer[i].sCPUVAddr =
375 psDevInfo->sFBInfo.sCPUVAddr + ui32BufferOffset;
378 psDevInfo->psSwapChain = psSwapChain;
380 eError = EnableLFBEventNotification(psDevInfo);
381 if (eError != PVRSRV_OK) {
383 ": Couldn't enable framebuffer event notification\n");
384 goto ErrorFreeBuffer;
387 *phSwapChain = (void *) psSwapChain;
392 OMAPLFBFreeKernelMem(psBuffer);
394 OMAPLFBFreeKernelMem(psSwapChain);
399 static enum PVRSRV_ERROR DestroyDCSwapChain(void *hDevice, void *hSwapChain)
401 struct OMAPLFB_DEVINFO *psDevInfo;
402 struct OMAPLFB_SWAPCHAIN *psSwapChain;
403 enum PVRSRV_ERROR eError;
405 if (!hDevice || !hSwapChain)
406 return PVRSRV_ERROR_INVALID_PARAMS;
408 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
409 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)hSwapChain;
410 if (psSwapChain != psDevInfo->psSwapChain)
411 return PVRSRV_ERROR_INVALID_PARAMS;
413 eError = DisableLFBEventNotification(psDevInfo);
414 if (eError != PVRSRV_OK)
415 printk(KERN_WARNING DRIVER_PREFIX
416 ": Couldn't disable framebuffer event notification\n");
418 psDevInfo->psSwapChain = NULL;
420 OMAPLFBFreeKernelMem(psSwapChain->psBuffer);
421 OMAPLFBFreeKernelMem(psSwapChain);
426 static enum PVRSRV_ERROR SetDCDstRect(void *hDevice,
427 void *hSwapChain, struct IMG_RECT *psRect)
429 PVR_UNREFERENCED_PARAMETER(hDevice);
430 PVR_UNREFERENCED_PARAMETER(hSwapChain);
431 PVR_UNREFERENCED_PARAMETER(psRect);
433 return PVRSRV_ERROR_NOT_SUPPORTED;
436 static enum PVRSRV_ERROR SetDCSrcRect(void *hDevice,
437 void *hSwapChain, struct IMG_RECT *psRect)
439 PVR_UNREFERENCED_PARAMETER(hDevice);
440 PVR_UNREFERENCED_PARAMETER(hSwapChain);
441 PVR_UNREFERENCED_PARAMETER(psRect);
443 return PVRSRV_ERROR_NOT_SUPPORTED;
446 static enum PVRSRV_ERROR SetDCDstColourKey(void *hDevice, void *hSwapChain,
449 PVR_UNREFERENCED_PARAMETER(hDevice);
450 PVR_UNREFERENCED_PARAMETER(hSwapChain);
451 PVR_UNREFERENCED_PARAMETER(ui32CKColour);
453 return PVRSRV_ERROR_NOT_SUPPORTED;
456 static enum PVRSRV_ERROR SetDCSrcColourKey(void *hDevice, void *hSwapChain,
459 PVR_UNREFERENCED_PARAMETER(hDevice);
460 PVR_UNREFERENCED_PARAMETER(hSwapChain);
461 PVR_UNREFERENCED_PARAMETER(ui32CKColour);
463 return PVRSRV_ERROR_NOT_SUPPORTED;
466 static enum PVRSRV_ERROR GetDCBuffers(void *hDevice, void *hSwapChain,
467 u32 *pui32BufferCount, void **phBuffer)
469 struct OMAPLFB_DEVINFO *psDevInfo;
470 struct OMAPLFB_SWAPCHAIN *psSwapChain;
473 if (!hDevice || !hSwapChain || !pui32BufferCount || !phBuffer)
474 return PVRSRV_ERROR_INVALID_PARAMS;
476 psDevInfo = (struct OMAPLFB_DEVINFO *)hDevice;
477 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)hSwapChain;
478 if (psSwapChain != psDevInfo->psSwapChain)
479 return PVRSRV_ERROR_INVALID_PARAMS;
481 *pui32BufferCount = psSwapChain->ui32BufferCount;
483 for (i = 0; i < psSwapChain->ui32BufferCount; i++)
484 phBuffer[i] = (void *) &psSwapChain->psBuffer[i];
489 static IMG_BOOL ProcessFlip(void *hCmdCookie, u32 ui32DataSize, void *pvData)
491 struct DISPLAYCLASS_FLIP_COMMAND *psFlipCmd;
492 struct OMAPLFB_DEVINFO *psDevInfo;
493 struct OMAPLFB_BUFFER *psBuffer;
494 struct OMAPLFB_SWAPCHAIN *psSwapChain;
496 if (!hCmdCookie || !pvData)
499 psFlipCmd = (struct DISPLAYCLASS_FLIP_COMMAND *)pvData;
501 if (psFlipCmd == NULL
502 || sizeof(struct DISPLAYCLASS_FLIP_COMMAND) != ui32DataSize)
505 psDevInfo = (struct OMAPLFB_DEVINFO *)psFlipCmd->hExtDevice;
507 psBuffer = (struct OMAPLFB_BUFFER *)psFlipCmd->hExtBuffer;
508 psSwapChain = (struct OMAPLFB_SWAPCHAIN *)psFlipCmd->hExtSwapChain;
510 psSwapChain->psPVRJTable->pfnPVRSRVCmdComplete(hCmdCookie, IMG_TRUE);
515 static void CalcSwapChainSize(struct OMAPLFB_DEVINFO *psDevInfo)
517 if (psDevInfo->sFBInfo.ui32RoundedBufferSize)
518 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers =
519 psDevInfo->sFBInfo.ui32FBSize /
520 psDevInfo->sFBInfo.ui32RoundedBufferSize;
522 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers = 0;
524 if (psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers == 0) {
525 psDevInfo->sDisplayInfo.ui32MaxSwapChains = 0;
526 psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 0;
528 psDevInfo->sDisplayInfo.ui32MaxSwapChains = 1;
529 psDevInfo->sDisplayInfo.ui32MaxSwapInterval = 3;
532 psDevInfo->sDisplayInfo.ui32MinSwapInterval = 0;
534 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
535 ": Maximum number of swap chain buffers: %u\n",
536 psDevInfo->sDisplayInfo.ui32MaxSwapChainBuffers));
539 static void SetDevinfo(struct OMAPLFB_DEVINFO *psDevInfo)
541 struct OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
542 struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
543 unsigned long FBSize;
545 FBSize = (psLINFBInfo->screen_size) != 0 ?
546 psLINFBInfo->screen_size : psLINFBInfo->fix.smem_len;
547 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
548 ": Framebuffer physical address: 0x%lx\n",
549 psLINFBInfo->fix.smem_start));
550 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
551 ": Framebuffer virtual address: 0x%lx\n",
552 (unsigned long)psLINFBInfo->screen_base));
553 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
554 ": Framebuffer size: %lu\n", FBSize));
555 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
556 ": Framebuffer virtual width: %u\n",
557 psLINFBInfo->var.xres_virtual));
558 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
559 ": Framebuffer virtual height: %u\n",
560 psLINFBInfo->var.yres_virtual));
561 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
562 ": Framebuffer width: %u\n", psLINFBInfo->var.xres));
563 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
564 ": Framebuffer height: %u\n", psLINFBInfo->var.yres));
565 DEBUG_PRINTK((KERN_INFO DRIVER_PREFIX
566 ": Framebuffer stride: %u\n",
567 psLINFBInfo->fix.line_length));
569 psPVRFBInfo->sSysAddr.uiAddr = psLINFBInfo->fix.smem_start;
570 psPVRFBInfo->sCPUVAddr = psLINFBInfo->screen_base;
572 psPVRFBInfo->ui32Width = psLINFBInfo->var.xres_virtual;
573 psPVRFBInfo->ui32ByteStride = psLINFBInfo->fix.line_length;
574 psPVRFBInfo->ui32FBSize = FBSize;
576 /* Try double buffering */
577 psPVRFBInfo->ui32Height = psLINFBInfo->var.yres_virtual >> 1;
578 psPVRFBInfo->ui32BufferSize = psPVRFBInfo->ui32ByteStride *
579 psPVRFBInfo->ui32Height;
580 psPVRFBInfo->ui32RoundedBufferSize =
581 sgx_buffer_align(psPVRFBInfo->ui32ByteStride,
582 psPVRFBInfo->ui32BufferSize);
584 /* If the buffers aren't aligned assume single buffering */
585 if (psPVRFBInfo->ui32BufferSize != psPVRFBInfo->ui32RoundedBufferSize) {
586 psPVRFBInfo->ui32Height = psLINFBInfo->var.yres_virtual;
587 psPVRFBInfo->ui32BufferSize = psPVRFBInfo->ui32ByteStride *
588 psPVRFBInfo->ui32Height;
589 psPVRFBInfo->ui32RoundedBufferSize =
590 sgx_buffer_align(psPVRFBInfo->ui32ByteStride,
591 psPVRFBInfo->ui32BufferSize);
594 CalcSwapChainSize(psDevInfo);
596 if (psLINFBInfo->var.bits_per_pixel == 16) {
597 if ((psLINFBInfo->var.red.length == 5) &&
598 (psLINFBInfo->var.green.length == 6) &&
599 (psLINFBInfo->var.blue.length == 5) &&
600 (psLINFBInfo->var.red.offset == 11) &&
601 (psLINFBInfo->var.green.offset == 5) &&
602 (psLINFBInfo->var.blue.offset == 0) &&
603 (psLINFBInfo->var.red.msb_right == 0))
604 psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB565;
606 printk("Unknown FB format\n");
607 } else if (psLINFBInfo->var.bits_per_pixel == 32) {
608 if ((psLINFBInfo->var.transp.length == 8) &&
609 (psLINFBInfo->var.red.length == 8) &&
610 (psLINFBInfo->var.green.length == 8) &&
611 (psLINFBInfo->var.blue.length == 8) &&
612 (psLINFBInfo->var.transp.offset == 24) &&
613 (psLINFBInfo->var.red.offset == 16) &&
614 (psLINFBInfo->var.green.offset == 8) &&
615 (psLINFBInfo->var.blue.offset == 0) &&
616 (psLINFBInfo->var.red.msb_right == 0))
617 psPVRFBInfo->ePixelFormat =
618 PVRSRV_PIXEL_FORMAT_ARGB8888;
619 else if ((psLINFBInfo->var.transp.length == 0) &&
620 (psLINFBInfo->var.red.length == 8) &&
621 (psLINFBInfo->var.green.length == 8) &&
622 (psLINFBInfo->var.blue.length == 8) &&
623 (psLINFBInfo->var.transp.offset == 0) &&
624 (psLINFBInfo->var.red.offset == 16) &&
625 (psLINFBInfo->var.green.offset == 8) &&
626 (psLINFBInfo->var.blue.offset == 0) &&
627 (psLINFBInfo->var.red.msb_right == 0))
628 psPVRFBInfo->ePixelFormat = PVRSRV_PIXEL_FORMAT_RGB888;
630 printk(KERN_ERR "Unknown FB format\n");
632 printk(KERN_ERR "Unknown FB format\n");
635 psDevInfo->sDisplayFormat.pixelformat = psDevInfo->sFBInfo.ePixelFormat;
636 psDevInfo->sDisplayDim.ui32Width = psDevInfo->sFBInfo.ui32Width;
637 psDevInfo->sDisplayDim.ui32Height = psDevInfo->sFBInfo.ui32Height;
638 psDevInfo->sDisplayDim.ui32ByteStride =
639 psDevInfo->sFBInfo.ui32ByteStride;
640 psDevInfo->sSystemBuffer.sSysAddr = psDevInfo->sFBInfo.sSysAddr;
641 psDevInfo->sSystemBuffer.sCPUVAddr = psDevInfo->sFBInfo.sCPUVAddr;
642 psDevInfo->sSystemBuffer.ui32BufferSize =
643 psDevInfo->sFBInfo.ui32RoundedBufferSize;
646 static struct FB_EVENTS {
647 struct notifier_block notif;
648 struct OMAPLFB_DEVINFO *psDevInfo;
651 static int FBEvents(struct notifier_block *psNotif,
652 unsigned long event, void *data)
654 if (event == FB_EVENT_MODE_CHANGE) {
655 struct FB_EVENTS *psEvents =
656 container_of(psNotif, struct FB_EVENTS, notif);
657 SetDevinfo(psEvents->psDevInfo);
662 static enum PVRSRV_ERROR InitDev(struct OMAPLFB_DEVINFO *psDevInfo)
664 struct fb_info *psLINFBInfo;
665 struct module *psLINFBOwner;
666 struct OMAPLFB_FBINFO *psPVRFBInfo = &psDevInfo->sFBInfo;
667 enum PVRSRV_ERROR eError = PVRSRV_ERROR_GENERIC;
669 acquire_console_sem();
671 if (fb_idx < 0 || fb_idx >= num_registered_fb) {
672 eError = PVRSRV_ERROR_INVALID_DEVICE;
676 psLINFBInfo = registered_fb[fb_idx];
678 psLINFBOwner = psLINFBInfo->fbops->owner;
679 if (!try_module_get(psLINFBOwner)) {
680 printk(KERN_INFO DRIVER_PREFIX
681 ": Couldn't get framebuffer module\n");
686 if (psLINFBInfo->fbops->fb_open != NULL) {
689 res = psLINFBInfo->fbops->fb_open(psLINFBInfo, 0);
691 printk(KERN_INFO DRIVER_PREFIX
692 ": Couldn't open framebuffer: %d\n", res);
698 psDevInfo->psLINFBInfo = psLINFBInfo;
700 SetDevinfo(psDevInfo);
702 gFBEventsData.notif.notifier_call = FBEvents;
703 gFBEventsData.psDevInfo = psDevInfo;
704 fb_register_client(&gFBEventsData.notif);
706 psDevInfo->sFBInfo.sSysAddr.uiAddr = psPVRFBInfo->sSysAddr.uiAddr;
707 psDevInfo->sFBInfo.sCPUVAddr = psPVRFBInfo->sCPUVAddr;
713 module_put(psLINFBOwner);
715 release_console_sem();
719 static void DeInitDev(struct OMAPLFB_DEVINFO *psDevInfo)
721 struct fb_info *psLINFBInfo = psDevInfo->psLINFBInfo;
722 struct module *psLINFBOwner;
724 acquire_console_sem();
726 fb_unregister_client(&gFBEventsData.notif);
728 psLINFBOwner = psLINFBInfo->fbops->owner;
730 if (psLINFBInfo->fbops->fb_release != NULL)
731 (void)psLINFBInfo->fbops->fb_release(psLINFBInfo, 0);
733 module_put(psLINFBOwner);
735 release_console_sem();
738 enum PVRSRV_ERROR OMAPLFBInit(void)
740 struct OMAPLFB_DEVINFO *psDevInfo;
742 psDevInfo = GetAnchorPtr();
744 if (psDevInfo == NULL) {
745 IMG_BOOL (*pfnCmdProcList[OMAPLFB_COMMAND_COUNT])
746 (void *, u32, void *);
747 u32 aui32SyncCountList[OMAPLFB_COMMAND_COUNT][2];
749 psDevInfo = (struct OMAPLFB_DEVINFO *)
750 OMAPLFBAllocKernelMem(sizeof(struct OMAPLFB_DEVINFO));
753 return PVRSRV_ERROR_OUT_OF_MEMORY;
755 memset(psDevInfo, 0, sizeof(struct OMAPLFB_DEVINFO));
757 SetAnchorPtr((void *) psDevInfo);
759 psDevInfo->ui32RefCount = 0;
761 if (InitDev(psDevInfo) != PVRSRV_OK)
762 return PVRSRV_ERROR_INIT_FAILURE;
764 if (OMAPLFBGetLibFuncAddr("PVRGetDisplayClassJTable",
765 &pfnGetPVRJTable) != PVRSRV_OK)
766 return PVRSRV_ERROR_INIT_FAILURE;
768 if (!(*pfnGetPVRJTable) (&psDevInfo->sPVRJTable))
769 return PVRSRV_ERROR_INIT_FAILURE;
771 psDevInfo->psSwapChain = NULL;
773 CalcSwapChainSize(psDevInfo);
775 strncpy(psDevInfo->sDisplayInfo.szDisplayName,
776 DISPLAY_DEVICE_NAME, MAX_DISPLAY_NAME_SIZE);
778 psDevInfo->sDCJTable.ui32TableSize =
779 sizeof(struct PVRSRV_DC_SRV2DISP_KMJTABLE);
780 psDevInfo->sDCJTable.owner = THIS_MODULE;
781 psDevInfo->sDCJTable.pfnOpenDCDevice = OpenDCDevice;
782 psDevInfo->sDCJTable.pfnCloseDCDevice = CloseDCDevice;
783 psDevInfo->sDCJTable.pfnEnumDCFormats = EnumDCFormats;
784 psDevInfo->sDCJTable.pfnEnumDCDims = EnumDCDims;
785 psDevInfo->sDCJTable.pfnGetDCSystemBuffer = GetDCSystemBuffer;
786 psDevInfo->sDCJTable.pfnGetDCInfo = GetDCInfo;
787 psDevInfo->sDCJTable.pfnGetBufferAddr = GetDCBufferAddr;
788 psDevInfo->sDCJTable.pfnCreateDCSwapChain = CreateDCSwapChain;
789 psDevInfo->sDCJTable.pfnDestroyDCSwapChain = DestroyDCSwapChain;
790 psDevInfo->sDCJTable.pfnSetDCDstRect = SetDCDstRect;
791 psDevInfo->sDCJTable.pfnSetDCSrcRect = SetDCSrcRect;
792 psDevInfo->sDCJTable.pfnSetDCDstColourKey = SetDCDstColourKey;
793 psDevInfo->sDCJTable.pfnSetDCSrcColourKey = SetDCSrcColourKey;
794 psDevInfo->sDCJTable.pfnGetDCBuffers = GetDCBuffers;
795 psDevInfo->sDCJTable.pfnSetDCState = NULL;
797 if (psDevInfo->sPVRJTable.
798 pfnPVRSRVRegisterDCDevice(&psDevInfo->sDCJTable,
799 &psDevInfo->ui32DeviceID) !=
801 return PVRSRV_ERROR_DEVICE_REGISTER_FAILED;
803 pfnCmdProcList[DC_FLIP_COMMAND] = ProcessFlip;
805 aui32SyncCountList[DC_FLIP_COMMAND][0] = 0;
806 aui32SyncCountList[DC_FLIP_COMMAND][1] = 2;
808 if (psDevInfo->sPVRJTable.
809 pfnPVRSRVRegisterCmdProcList(psDevInfo->ui32DeviceID,
812 OMAPLFB_COMMAND_COUNT) !=
814 printk(KERN_WARNING DRIVER_PREFIX
815 ": Can't register callback\n");
816 return PVRSRV_ERROR_CANT_REGISTER_CALLBACK;
821 psDevInfo->ui32RefCount++;
827 enum PVRSRV_ERROR OMAPLFBDeinit(void)
829 struct OMAPLFB_DEVINFO *psDevInfo, *psDevFirst;
831 psDevFirst = GetAnchorPtr();
832 psDevInfo = psDevFirst;
834 if (psDevInfo == NULL)
835 return PVRSRV_ERROR_GENERIC;
837 psDevInfo->ui32RefCount--;
839 if (psDevInfo->ui32RefCount == 0) {
840 struct PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable =
841 &psDevInfo->sPVRJTable;
842 if (psDevInfo->sPVRJTable.
843 pfnPVRSRVRemoveCmdProcList(psDevInfo->ui32DeviceID,
844 OMAPLFB_COMMAND_COUNT) !=
846 return PVRSRV_ERROR_GENERIC;
849 pfnPVRSRVRemoveDCDevice(psDevInfo->ui32DeviceID) !=
851 return PVRSRV_ERROR_GENERIC;
853 DeInitDev(psDevInfo);
855 OMAPLFBFreeKernelMem(psDevInfo);